diff options
-rw-r--r-- | common/Makefile | 1 | ||||
-rw-r--r-- | common/cmd_imxotp.c | 156 | ||||
-rw-r--r-- | cpu/arm_cortexa8/mx6/generic.c | 24 | ||||
-rw-r--r-- | drivers/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/misc/imx_otp.c | 256 | ||||
-rw-r--r-- | include/asm-arm/arch-mx6/regs-ocotp.h | 367 | ||||
-rw-r--r-- | include/configs/mx6q_arm2.h | 11 | ||||
-rw-r--r-- | include/imx_otp.h | 30 |
8 files changed, 846 insertions, 0 deletions
diff --git a/common/Makefile b/common/Makefile index f4d2cbd..1f218e7 100644 --- a/common/Makefile +++ b/common/Makefile @@ -171,6 +171,7 @@ COBJS-$(CONFIG_MODEM_SUPPORT) += modem.o COBJS-$(CONFIG_UPDATE_TFTP) += update.o COBJS-$(CONFIG_USB_KEYBOARD) += usb_kbd.o COBJS-$(CONFIG_FASTBOOT) += cmd_fastboot.o +COBJS-$(CONFIG_CMD_IMXOTP) += cmd_imxotp.o COBJS := $(sort $(COBJS-y)) SRCS := $(AOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/common/cmd_imxotp.c b/common/cmd_imxotp.c new file mode 100644 index 0000000..b976aaa --- /dev/null +++ b/common/cmd_imxotp.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <common.h> +#include <command.h> +#include <imx_otp.h> + +/* + * meant to reject most of the zeros return by simple_strtoul call. + * + */ +int validate_zero_from_simple_strtoul(char *str) +{ + int i = 0; + + /* reject negatives */ + if (str[0] == '-') + return -1; + + /* reject no zero initialed */ + if (str[0] != '0') + return -1; + + /* accept zero */ + if (strlen(str) == 1) + return 0; + + /* only accept started with "0x" or "0X" or "00" */ + if (str[1] != 'x' && str[1] != 'X' && str[1] != '0') + return -1; + + /* reject "0x" or "0X" or "00" only */ + if (strlen(str) == 3) + return -1; + + /* only accept all zeros */ + for (i = 1; i < strlen(str) - 1; i++) { + if (str[1] != '0') + return -1; + } + return 0; +} + +int do_imxotp(cmd_tbl_t *cmd_tbl, int flag, int argc, char* argv[]) +{ + u32 addr, value_read, fused_value, value_to_fuse; + int force_to_fuse = 0; + + if (argc < 3) { +usage: + cmd_usage(cmd_tbl); + return 1; + } + + if (!strcmp(argv[1], "read")) { + switch (argc) { + case 3: + addr = simple_strtoul(argv[2], NULL, 16); + if ((addr == 0) && + validate_zero_from_simple_strtoul(argv[2])) + goto usage; + break; + default: + goto usage; + } + printf("Reading fuse at index: 0x%X\n", addr); + if (imx_otp_read_one_u32(addr, &value_read)) + return -1; + printf("Fuse at (index: 0x%X) value: 0x%X\n", addr, value_read); + } else if (!strcmp(argv[1], "blow")) { + if (argc < 4 || argc > 5) + goto usage; + + if (!strcmp(argv[2], "--force")) { + force_to_fuse = 1; + addr = simple_strtoul(argv[3], NULL, 16); + if ((addr == 0) + && validate_zero_from_simple_strtoul(argv[3])) + goto usage; + value_to_fuse = simple_strtoul(argv[4], NULL, 16); + if ((value_to_fuse == 0) + && validate_zero_from_simple_strtoul(argv[4])) + goto usage; + } else { + addr = simple_strtoul(argv[2], NULL, 16); + if ((addr == 0) + && validate_zero_from_simple_strtoul(argv[2])) + goto usage; + value_to_fuse = simple_strtoul(argv[3], NULL, 16); + if ((value_to_fuse == 0) + && validate_zero_from_simple_strtoul(argv[3])) + goto usage; + } + + /* show the current value of specified address (fuse index) */ + if (imx_otp_read_one_u32(addr, &value_read)) + return -1; + printf("Current fuse at (index: 0x%X) value: 0x%X\n", + addr, value_read); + + if ((value_to_fuse & value_read) == value_to_fuse) + printf("!! Fuse blow skipped:" + " the bits have been already set.\n"); + else if (force_to_fuse) { + printf("Blowing fuse at index: 0x%X, value: 0x%X\n", + addr, value_to_fuse); + if (imx_otp_blow_one_u32(addr, + value_to_fuse, &fused_value)) { + printf("ERROR: failed to blow fuse" + " at 0x%X with value of 0x%X\n", + addr, value_to_fuse); + } else { + printf("Operation %s fuse" + " at (index: 0x%X) value: 0x%X\n", + ((fused_value & value_to_fuse) == + value_to_fuse) ? "succeeded" + : "failed", + addr, fused_value); + } + } else { + printf("!! Fuse blow aborted." + " if you do want to blow it." + " Please use the command:\n" + "%s blow --force %X %X\n", + argv[0], addr, value_to_fuse); + } + } else + goto usage; + + return 0; +} + +U_BOOT_CMD(imxotp, 5, 0, do_imxotp, + "One-Time Programable sub-system", + "imxotp read <addr>\n" + " - read fuse at 'addr'\n" + "imxotp blow [--force] <addr> <value>\n" + " - blow fuse at 'addr' with hex value 'value'\n" +); diff --git a/cpu/arm_cortexa8/mx6/generic.c b/cpu/arm_cortexa8/mx6/generic.c index f959b95..11fac50 100644 --- a/cpu/arm_cortexa8/mx6/generic.c +++ b/cpu/arm_cortexa8/mx6/generic.c @@ -770,3 +770,27 @@ void ipu_clk_enable(void) void ipu_clk_disable(void) { } + +int otp_clk_enable(void) +{ + u32 reg = 0; + + reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR2); + if (!(reg & 0x3000)) + reg |= 0x3000; + writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR2); + return 0; +} + +int otp_clk_disable(void) +{ + u32 reg = 0; + + reg = readl(CCM_BASE_ADDR + CLKCTL_CCGR2); + if ((reg & 0x3000) == 0x3000) + reg &= ~(0x3000); + writel(reg, CCM_BASE_ADDR + CLKCTL_CCGR2); + return 0; +} + + diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 5bbafea..685ae8c 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -29,6 +29,7 @@ COBJS-$(CONFIG_ALI152X) += ali512x.o COBJS-$(CONFIG_DS4510) += ds4510.o COBJS-$(CONFIG_FSL_LAW) += fsl_law.o COBJS-$(CONFIG_IMX_IIM) += imx_iim.o +COBJS-$(CONFIG_IMX_OTP) += imx_otp.o COBJS-$(CONFIG_IMX_PWM) += imx_pwm.o COBJS-$(CONFIG_NS87308) += ns87308.o COBJS-$(CONFIG_STATUS_LED) += status_led.o diff --git a/drivers/misc/imx_otp.c b/drivers/misc/imx_otp.c new file mode 100644 index 0000000..917924d --- /dev/null +++ b/drivers/misc/imx_otp.c @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <asm/io.h> +#include <common.h> +#include <asm-arm/arch/regs-ocotp.h> +#include <imx_otp.h> + +#define HW_OCOTP_CUSTn(n) (0x00000400 + (n) * 0x10) +#define BF(value, field) (((value) << BP_##field) & BM_##field) +#define DEF_RELAX 20 + +#ifdef CONFIG_IMX_OTP_DEBUG +#define log(a, ...) printf("[%s,%3d]:"a"\n", __func__, __LINE__, ## __VA_ARGS__) +#else +#define log(a, ...) +#endif + +static int otp_wait_busy(u32 flags) +{ + int count; + u32 c; + + for (count = 10000; count >= 0; count--) { + c = readl(IMX_OTP_BASE + HW_OCOTP_CTRL); + if (!(c & (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR | flags))) + break; + } + + if (count < 0) { + printf("ERROR: otp_wait_busy timeout. 0x%X\n", c); + /* clear ERROR bit, busy bit will be cleared by controller */ + writel(BM_OCOTP_CTRL_ERROR, IMX_OTP_BASE + HW_OCOTP_CTRL_CLR); + return -1; + } + + log("wait busy successful."); + return 0; +} + +static int set_otp_timing(void) +{ + u32 clk_rate = 0; + u32 relax, strobe_read, strobe_prog; + u32 timing = 0; + + /* get clock */ + clk_rate = mxc_get_clock(MXC_IPG_CLK); + if (clk_rate == -1) { + printf("ERROR: mxc_get_clock failed\n"); + return -1; + } + + log("clk_rate: %d.", clk_rate); + + relax = clk_rate / (1000000000 / DEF_RELAX) - 1; + strobe_prog = clk_rate / (1000000000 / 10000) + 2 * (DEF_RELAX + 1) - 1; + strobe_read = clk_rate / (1000000000 / 40) + 2 * (DEF_RELAX + 1) - 1; + + timing = BF(relax, OCOTP_TIMING_RELAX); + timing |= BF(strobe_read, OCOTP_TIMING_STROBE_READ); + timing |= BF(strobe_prog, OCOTP_TIMING_STROBE_PROG); + log("timing: 0x%X", timing); + + writel(timing, IMX_OTP_BASE + HW_OCOTP_TIMING); + + return 0; +} + +static int otp_read_prep(void) +{ + return (!set_otp_timing()) ? otp_wait_busy(0) : -1; +} + +static int otp_read_post(void) +{ + return 0; +} + +static int otp_blow_prep(void) +{ + return (!set_otp_timing()) ? otp_wait_busy(0) : -1; +} + +static int otp_blow_post(void) +{ + printf("Reloading shadow registers...\n"); + /* reload all the shadow registers */ + writel(BM_OCOTP_CTRL_RELOAD_SHADOWS, + IMX_OTP_BASE + HW_OCOTP_CTRL_SET); + udelay(1); + + return otp_wait_busy(BM_OCOTP_CTRL_RELOAD_SHADOWS); +} + +static int fuse_read_addr(u32 addr, u32 *pdata) +{ + u32 ctrl_reg = 0; + +#ifdef CONFIG_IMX_OTP_READ_SHADOW_REG + *pdata = readl(IMX_OTP_BASE + HW_OCOTP_CUSTn(addr)); + printf("Shadow register data: 0x%X\n", *pdata); +#endif + + ctrl_reg = readl(IMX_OTP_BASE + HW_OCOTP_CTRL); + ctrl_reg &= ~BM_OCOTP_CTRL_ADDR; + ctrl_reg &= ~BM_OCOTP_CTRL_WR_UNLOCK; + ctrl_reg |= BF(addr, OCOTP_CTRL_ADDR); + writel(ctrl_reg, IMX_OTP_BASE + HW_OCOTP_CTRL); + + writel(BM_OCOTP_READ_CTRL_READ_FUSE, IMX_OTP_BASE + HW_OCOTP_READ_CTRL); + if (otp_wait_busy(0)) + return -1; + + *pdata = readl(IMX_OTP_BASE + HW_OCOTP_READ_FUSE_DATA); + *pdata = BF_OCOTP_READ_FUSE_DATA_DATA(*pdata); + return 0; +} + +static int fuse_blow_addr(u32 addr, u32 value) +{ + u32 ctrl_reg = 0; + + log("blowing..."); + + /* control register */ + ctrl_reg = readl(IMX_OTP_BASE + HW_OCOTP_CTRL); + ctrl_reg &= ~BM_OCOTP_CTRL_ADDR; + ctrl_reg |= BF(addr, OCOTP_CTRL_ADDR); + ctrl_reg |= BF(BV_OCOTP_CTRL_WR_UNLOCK__KEY, OCOTP_CTRL_WR_UNLOCK); + writel(ctrl_reg, IMX_OTP_BASE + HW_OCOTP_CTRL); + + writel(BF_OCOTP_DATA_DATA(value), IMX_OTP_BASE + HW_OCOTP_DATA); + if (otp_wait_busy(0)) + return -1; + + /* write postamble */ + udelay(2000); + return 0; +} + +/* + * read one u32 to indexed fuse + */ +int imx_otp_read_one_u32(u32 index, u32 *pdata) +{ + u32 ctrl_reg = 0; + int ret = 0; + + log("index: 0x%X", index); + if (index > IMX_OTP_ADDR_MAX) { + printf("ERROR: invalid address.\n"); + ret = -1; + goto exit_nop; + } + + if (otp_clk_enable()) { + ret = -1; + printf("ERROR: failed to initialize OTP\n"); + goto exit_nop; + } + + if (otp_read_prep()) { + ret = -1; + printf("ERROR: read preparation failed\n"); + goto exit_cleanup; + } + if (fuse_read_addr(index, pdata)) { + ret = -1; + printf("ERROR: read failed\n"); + goto exit_cleanup; + } + if (otp_read_post()) { + ret = -1; + printf("ERROR: read post operation failed\n"); + goto exit_cleanup; + } + + if (*pdata == IMX_OTP_DATA_ERROR_VAL) { + ctrl_reg = readl(IMX_OTP_BASE + HW_OCOTP_CTRL); + if (ctrl_reg & BM_OCOTP_CTRL_ERROR) { + printf("ERROR: read fuse failed\n"); + ret = -1; + goto exit_cleanup; + } + } + +exit_cleanup: + otp_clk_disable(); +exit_nop: + return ret; +} + +/* + * blow one u32 to indexed fuse + */ +int imx_otp_blow_one_u32(u32 index, u32 data, u32 *pfused_value) +{ + u32 ctrl_reg = 0; + int ret = 0; + + if (otp_clk_enable()) { + ret = -1; + goto exit_nop; + } + + if (otp_blow_prep()) { + ret = -1; + printf("ERROR: blow preparation failed\n"); + goto exit_cleanup; + } + if (fuse_blow_addr(index, data)) { + ret = -1; + printf("ERROR: blow fuse failed\n"); + goto exit_cleanup; + } + if (otp_blow_post()) { + ret = -1; + printf("ERROR: blow post operation failed\n"); + goto exit_cleanup; + } + + ctrl_reg = readl(IMX_OTP_BASE + HW_OCOTP_CTRL); + if (ctrl_reg & BM_OCOTP_CTRL_ERROR) { + ret = -1; + goto exit_cleanup; + } + + if (imx_otp_read_one_u32(index, pfused_value)) { + ret = -1; + goto exit_cleanup; + } + +exit_cleanup: + otp_clk_disable(); +exit_nop: + return ret; +} + diff --git a/include/asm-arm/arch-mx6/regs-ocotp.h b/include/asm-arm/arch-mx6/regs-ocotp.h new file mode 100644 index 0000000..d3c8de9 --- /dev/null +++ b/include/asm-arm/arch-mx6/regs-ocotp.h @@ -0,0 +1,367 @@ +/* + * Freescale OCOTP Register Definitions + * + * Copyright 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is created by xml file. Don't Edit it. + * + * Xml Revision: 1.12 + * Template revision: 1.3 + */ + +#ifndef __ARCH_ARM___OCOTP_H +#define __ARCH_ARM___OCOTP_H + + +#define HW_OCOTP_CTRL (0x00000000) +#define HW_OCOTP_CTRL_SET (0x00000004) +#define HW_OCOTP_CTRL_CLR (0x00000008) +#define HW_OCOTP_CTRL_TOG (0x0000000c) + +#define BP_OCOTP_CTRL_WR_UNLOCK 16 +#define BM_OCOTP_CTRL_WR_UNLOCK 0xFFFF0000 +#define BF_OCOTP_CTRL_WR_UNLOCK(v) \ + (((v) << 16) & BM_OCOTP_CTRL_WR_UNLOCK) +#define BV_OCOTP_CTRL_WR_UNLOCK__KEY 0x3E77 +#define BP_OCOTP_CTRL_RSVD1 13 +#define BM_OCOTP_CTRL_RSVD1 0x0000E000 +#define BF_OCOTP_CTRL_RSVD1(v) \ + (((v) << 13) & BM_OCOTP_CTRL_RSVD1) +#define BM_OCOTP_CTRL_CRC_FAIL 0x00001000 +#define BM_OCOTP_CTRL_CRC_TEST 0x00000800 +#define BM_OCOTP_CTRL_RELOAD_SHADOWS 0x00000400 +#define BM_OCOTP_CTRL_ERROR 0x00000200 +#define BM_OCOTP_CTRL_BUSY 0x00000100 +#define BM_OCOTP_CTRL_RSVD0 0x00000080 +#define BP_OCOTP_CTRL_ADDR 0 +#define BM_OCOTP_CTRL_ADDR 0x0000007F +#define BF_OCOTP_CTRL_ADDR(v) \ + (((v) << 0) & BM_OCOTP_CTRL_ADDR) + +#define HW_OCOTP_TIMING (0x00000010) + +#define BP_OCOTP_TIMING_RSRVD0 28 +#define BM_OCOTP_TIMING_RSRVD0 0xF0000000 +#define BF_OCOTP_TIMING_RSRVD0(v) \ + (((v) << 28) & BM_OCOTP_TIMING_RSRVD0) +#define BP_OCOTP_TIMING_WAIT 22 +#define BM_OCOTP_TIMING_WAIT 0x0FC00000 +#define BF_OCOTP_TIMING_WAIT(v) \ + (((v) << 22) & BM_OCOTP_TIMING_WAIT) +#define BP_OCOTP_TIMING_STROBE_READ 16 +#define BM_OCOTP_TIMING_STROBE_READ 0x003F0000 +#define BF_OCOTP_TIMING_STROBE_READ(v) \ + (((v) << 16) & BM_OCOTP_TIMING_STROBE_READ) +#define BP_OCOTP_TIMING_RELAX 12 +#define BM_OCOTP_TIMING_RELAX 0x0000F000 +#define BF_OCOTP_TIMING_RELAX(v) \ + (((v) << 12) & BM_OCOTP_TIMING_RELAX) +#define BP_OCOTP_TIMING_STROBE_PROG 0 +#define BM_OCOTP_TIMING_STROBE_PROG 0x00000FFF +#define BF_OCOTP_TIMING_STROBE_PROG(v) \ + (((v) << 0) & BM_OCOTP_TIMING_STROBE_PROG) + +#define HW_OCOTP_DATA (0x00000020) + +#define BP_OCOTP_DATA_DATA 0 +#define BM_OCOTP_DATA_DATA 0xFFFFFFFF +#define BF_OCOTP_DATA_DATA(v) (v) + +#define HW_OCOTP_READ_CTRL (0x00000030) + +#define BP_OCOTP_READ_CTRL_RSVD0 1 +#define BM_OCOTP_READ_CTRL_RSVD0 0xFFFFFFFE +#define BF_OCOTP_READ_CTRL_RSVD0(v) \ + (((v) << 1) & BM_OCOTP_READ_CTRL_RSVD0) +#define BM_OCOTP_READ_CTRL_READ_FUSE 0x00000001 + +#define HW_OCOTP_READ_FUSE_DATA (0x00000040) + +#define BP_OCOTP_READ_FUSE_DATA_DATA 0 +#define BM_OCOTP_READ_FUSE_DATA_DATA 0xFFFFFFFF +#define BF_OCOTP_READ_FUSE_DATA_DATA(v) (v) + +#define HW_OCOTP_SW_STICKY (0x00000050) + +#define BP_OCOTP_SW_STICKY_RSVD0 5 +#define BM_OCOTP_SW_STICKY_RSVD0 0xFFFFFFE0 +#define BF_OCOTP_SW_STICKY_RSVD0(v) \ + (((v) << 5) & BM_OCOTP_SW_STICKY_RSVD0) +#define BM_OCOTP_SW_STICKY_JTAG_BLOCK_RELEASE 0x00000010 +#define BM_OCOTP_SW_STICKY_BLOCK_ROM_PART 0x00000008 +#define BM_OCOTP_SW_STICKY_FIELD_RETURN_LOCK 0x00000004 +#define BM_OCOTP_SW_STICKY_SRK_REVOKE_LOCK 0x00000002 +#define BM_OCOTP_SW_STICKY_BLOCK_DTCP_KEY 0x00000001 + +#define HW_OCOTP_SCS (0x00000060) +#define HW_OCOTP_SCS_SET (0x00000064) +#define HW_OCOTP_SCS_CLR (0x00000068) +#define HW_OCOTP_SCS_TOG (0x0000006c) + +#define BM_OCOTP_SCS_LOCK 0x80000000 +#define BP_OCOTP_SCS_SPARE 1 +#define BM_OCOTP_SCS_SPARE 0x7FFFFFFE +#define BF_OCOTP_SCS_SPARE(v) \ + (((v) << 1) & BM_OCOTP_SCS_SPARE) +#define BM_OCOTP_SCS_HAB_JDE 0x00000001 + +#define HW_OCOTP_CRC_ADDR (0x00000070) + +#define BP_OCOTP_CRC_ADDR_RSVD0 19 +#define BM_OCOTP_CRC_ADDR_RSVD0 0xFFF80000 +#define BF_OCOTP_CRC_ADDR_RSVD0(v) \ + (((v) << 19) & BM_OCOTP_CRC_ADDR_RSVD0) +#define BP_OCOTP_CRC_ADDR_CRC_ADDR 16 +#define BM_OCOTP_CRC_ADDR_CRC_ADDR 0x00070000 +#define BF_OCOTP_CRC_ADDR_CRC_ADDR(v) \ + (((v) << 16) & BM_OCOTP_CRC_ADDR_CRC_ADDR) +#define BP_OCOTP_CRC_ADDR_DATA_END_ADDR 8 +#define BM_OCOTP_CRC_ADDR_DATA_END_ADDR 0x0000FF00 +#define BF_OCOTP_CRC_ADDR_DATA_END_ADDR(v) \ + (((v) << 8) & BM_OCOTP_CRC_ADDR_DATA_END_ADDR) +#define BP_OCOTP_CRC_ADDR_DATA_START_ADDR 0 +#define BM_OCOTP_CRC_ADDR_DATA_START_ADDR 0x000000FF +#define BF_OCOTP_CRC_ADDR_DATA_START_ADDR(v) \ + (((v) << 0) & BM_OCOTP_CRC_ADDR_DATA_START_ADDR) + +#define HW_OCOTP_CRC_VALUE (0x00000080) + +#define BP_OCOTP_CRC_VALUE_DATA 0 +#define BM_OCOTP_CRC_VALUE_DATA 0xFFFFFFFF +#define BF_OCOTP_CRC_VALUE_DATA(v) (v) + +#define HW_OCOTP_VERSION (0x00000090) + +#define BP_OCOTP_VERSION_MAJOR 24 +#define BM_OCOTP_VERSION_MAJOR 0xFF000000 +#define BF_OCOTP_VERSION_MAJOR(v) \ + (((v) << 24) & BM_OCOTP_VERSION_MAJOR) +#define BP_OCOTP_VERSION_MINOR 16 +#define BM_OCOTP_VERSION_MINOR 0x00FF0000 +#define BF_OCOTP_VERSION_MINOR(v) \ + (((v) << 16) & BM_OCOTP_VERSION_MINOR) +#define BP_OCOTP_VERSION_STEP 0 +#define BM_OCOTP_VERSION_STEP 0x0000FFFF +#define BF_OCOTP_VERSION_STEP(v) \ + (((v) << 0) & BM_OCOTP_VERSION_STEP) + +#define HW_OCOTP_LOCK (0x00000400) + +#define BP_OCOTP_LOCK_UNALLOCATED 30 +#define BM_OCOTP_LOCK_UNALLOCATED 0xC0000000 +#define BF_OCOTP_LOCK_UNALLOCATED(v) \ + (((v) << 30) & BM_OCOTP_LOCK_UNALLOCATED) +#define BP_OCOTP_LOCK_CRC_GP_HI_LOCK 28 +#define BM_OCOTP_LOCK_CRC_GP_HI_LOCK 0x30000000 +#define BF_OCOTP_LOCK_CRC_GP_HI_LOCK(v) \ + (((v) << 28) & BM_OCOTP_LOCK_CRC_GP_HI_LOCK) +#define BP_OCOTP_LOCK_CRC_GP_LO_LOCK 26 +#define BM_OCOTP_LOCK_CRC_GP_LO_LOCK 0x0C000000 +#define BF_OCOTP_LOCK_CRC_GP_LO_LOCK(v) \ + (((v) << 26) & BM_OCOTP_LOCK_CRC_GP_LO_LOCK) +#define BM_OCOTP_LOCK_PIN 0x02000000 +#define BM_OCOTP_LOCK_RSVD2 0x01000000 +#define BM_OCOTP_LOCK_DTCP_DEV_CERT 0x00800000 +#define BM_OCOTP_LOCK_MISC_CONF 0x00400000 +#define BM_OCOTP_LOCK_HDCP_KEYS 0x00200000 +#define BM_OCOTP_LOCK_HDCP_KSV 0x00100000 +#define BP_OCOTP_LOCK_ANALOG 18 +#define BM_OCOTP_LOCK_ANALOG 0x000C0000 +#define BF_OCOTP_LOCK_ANALOG(v) \ + (((v) << 18) & BM_OCOTP_LOCK_ANALOG) +#define BM_OCOTP_LOCK_OTPMK 0x00020000 +#define BM_OCOTP_LOCK_DTCP_KEY 0x00010000 +#define BM_OCOTP_LOCK_RSVD1 0x00008000 +#define BM_OCOTP_LOCK_SRK 0x00004000 +#define BP_OCOTP_LOCK_GP2 12 +#define BM_OCOTP_LOCK_GP2 0x00003000 +#define BF_OCOTP_LOCK_GP2(v) \ + (((v) << 12) & BM_OCOTP_LOCK_GP2) +#define BP_OCOTP_LOCK_GP1 10 +#define BM_OCOTP_LOCK_GP1 0x00000C00 +#define BF_OCOTP_LOCK_GP1(v) \ + (((v) << 10) & BM_OCOTP_LOCK_GP1) +#define BP_OCOTP_LOCK_MAC_ADDR 8 +#define BM_OCOTP_LOCK_MAC_ADDR 0x00000300 +#define BF_OCOTP_LOCK_MAC_ADDR(v) \ + (((v) << 8) & BM_OCOTP_LOCK_MAC_ADDR) +#define BM_OCOTP_LOCK_RSVD0 0x00000080 +#define BM_OCOTP_LOCK_SJC_RESP 0x00000040 +#define BP_OCOTP_LOCK_MEM_TRIM 4 +#define BM_OCOTP_LOCK_MEM_TRIM 0x00000030 +#define BF_OCOTP_LOCK_MEM_TRIM(v) \ + (((v) << 4) & BM_OCOTP_LOCK_MEM_TRIM) +#define BP_OCOTP_LOCK_BOOT_CFG 2 +#define BM_OCOTP_LOCK_BOOT_CFG 0x0000000C +#define BF_OCOTP_LOCK_BOOT_CFG(v) \ + (((v) << 2) & BM_OCOTP_LOCK_BOOT_CFG) +#define BP_OCOTP_LOCK_TESTER 0 +#define BM_OCOTP_LOCK_TESTER 0x00000003 +#define BF_OCOTP_LOCK_TESTER(v) \ + (((v) << 0) & BM_OCOTP_LOCK_TESTER) + +/* + * multi-register-define name HW_OCOTP_CFGn + * base 0x00000410 + * count 7 + * offset 0x10 + */ +#define HW_OCOTP_CFGn(n) (0x00000410 + (n) * 0x10) +#define BP_OCOTP_CFGn_BITS 0 +#define BM_OCOTP_CFGn_BITS 0xFFFFFFFF +#define BF_OCOTP_CFGn_BITS(v) (v) + +/* + * multi-register-define name HW_OCOTP_MEMn + * base 0x00000480 + * count 5 + * offset 0x10 + */ +#define HW_OCOTP_MEMn(n) (0x00000480 + (n) * 0x10) +#define BP_OCOTP_MEMn_BITS 0 +#define BM_OCOTP_MEMn_BITS 0xFFFFFFFF +#define BF_OCOTP_MEMn_BITS(v) (v) + +/* + * multi-register-define name HW_OCOTP_ANAn + * base 0x000004D0 + * count 3 + * offset 0x10 + */ +#define HW_OCOTP_ANAn(n) (0x000004d0 + (n) * 0x10) +#define BP_OCOTP_ANAn_BITS 0 +#define BM_OCOTP_ANAn_BITS 0xFFFFFFFF +#define BF_OCOTP_ANAn_BITS(v) (v) + +/* + * multi-register-define name HW_OCOTP_OTPMKn + * base 0x00000500 + * count 8 + * offset 0x10 + */ +#define HW_OCOTP_OTPMKn(n) (0x00000500 + (n) * 0x10) +#define BP_OCOTP_OTPMKn_BITS 0 +#define BM_OCOTP_OTPMKn_BITS 0xFFFFFFFF +#define BF_OCOTP_OTPMKn_BITS(v) (v) + +/* + * multi-register-define name HW_OCOTP_SRKn + * base 0x00000580 + * count 8 + * offset 0x10 + */ +#define HW_OCOTP_SRKn(n) (0x00000580 + (n) * 0x10) +#define BP_OCOTP_SRKn_BITS 0 +#define BM_OCOTP_SRKn_BITS 0xFFFFFFFF +#define BF_OCOTP_SRKn_BITS(v) (v) + +/* + * multi-register-define name HW_OCOTP_SJC_RESPn + * base 0x00000600 + * count 2 + * offset 0x10 + */ +#define HW_OCOTP_SJC_RESPn(n) (0x00000600 + (n) * 0x10) +#define BP_OCOTP_SJC_RESPn_BITS 0 +#define BM_OCOTP_SJC_RESPn_BITS 0xFFFFFFFF +#define BF_OCOTP_SJC_RESPn_BITS(v) (v) + +/* + * multi-register-define name HW_OCOTP_MACn + * base 0x00000620 + * count 2 + * offset 0x10 + */ +#define HW_OCOTP_MACn(n) (0x00000620 + (n) * 0x10) +#define BP_OCOTP_MACn_BITS 0 +#define BM_OCOTP_MACn_BITS 0xFFFFFFFF +#define BF_OCOTP_MACn_BITS(v) (v) + +/* + * multi-register-define name HW_OCOTP_HDCP_KSVn + * base 0x00000640 + * count 2 + * offset 0x10 + */ +#define HW_OCOTP_HDCP_KSVn(n) (0x00000640 + (n) * 0x10) +#define BP_OCOTP_HDCP_KSVn_BITS 0 +#define BM_OCOTP_HDCP_KSVn_BITS 0xFFFFFFFF +#define BF_OCOTP_HDCP_KSVn_BITS(v) (v) + +#define HW_OCOTP_GP1 (0x00000660) + +#define BP_OCOTP_GP1_BITS 0 +#define BM_OCOTP_GP1_BITS 0xFFFFFFFF +#define BF_OCOTP_GP1_BITS(v) (v) + +#define HW_OCOTP_GP2 (0x00000670) + +#define BP_OCOTP_GP2_BITS 0 +#define BM_OCOTP_GP2_BITS 0xFFFFFFFF +#define BF_OCOTP_GP2_BITS(v) (v) + +/* + * multi-register-define name HW_OCOTP_DTCP_KEYn + * base 0x00000680 + * count 5 + * offset 0x10 + */ +#define HW_OCOTP_DTCP_KEYn(n) (0x00000680 + (n) * 0x10) +#define BP_OCOTP_DTCP_KEYn_BITS 0 +#define BM_OCOTP_DTCP_KEYn_BITS 0xFFFFFFFF +#define BF_OCOTP_DTCP_KEYn_BITS(v) (v) + +#define HW_OCOTP_MISC_CONF (0x000006d0) + +#define BP_OCOTP_MISC_CONF_BITS 0 +#define BM_OCOTP_MISC_CONF_BITS 0xFFFFFFFF +#define BF_OCOTP_MISC_CONF_BITS(v) (v) + +#define HW_OCOTP_FIELD_RETURN (0x000006e0) + +#define BP_OCOTP_FIELD_RETURN_BITS 0 +#define BM_OCOTP_FIELD_RETURN_BITS 0xFFFFFFFF +#define BF_OCOTP_FIELD_RETURN_BITS(v) (v) + +#define HW_OCOTP_SRK_REVOKE (0x000006f0) + +#define BP_OCOTP_SRK_REVOKE_BITS 0 +#define BM_OCOTP_SRK_REVOKE_BITS 0xFFFFFFFF +#define BF_OCOTP_SRK_REVOKE_BITS(v) (v) + +/* + * multi-register-define name HW_OCOTP_HDCP_KEYn + * base 0x00000800 + * count 72 + * offset 0x10 + */ +#define HW_OCOTP_HDCP_KEYn(n) (0x00000800 + (n) * 0x10) +#define BP_OCOTP_HDCP_KEYn_BITS 0 +#define BM_OCOTP_HDCP_KEYn_BITS 0xFFFFFFFF +#define BF_OCOTP_HDCP_KEYn_BITS(v) (v) + +/* + * multi-register-define name HW_OCOTP_CRCn + * base 0x00000D00 + * count 8 + * offset 0x10 + */ +#define HW_OCOTP_CRCn(n) (0x00000d00 + (n) * 0x10) +#define BP_OCOTP_CRCn_BITS 0 +#define BM_OCOTP_CRCn_BITS 0xFFFFFFFF +#define BF_OCOTP_CRCn_BITS(v) (v) +#endif /* __ARCH_ARM___OCOTP_H */ diff --git a/include/configs/mx6q_arm2.h b/include/configs/mx6q_arm2.h index 165d13a..c9bff96 100644 --- a/include/configs/mx6q_arm2.h +++ b/include/configs/mx6q_arm2.h @@ -90,6 +90,7 @@ #define CONFIG_CMD_SPI #define CONFIG_CMD_I2C +#define CONFIG_CMD_IMXOTP /* Enable below configure when supporting nand */ #define CONFIG_CMD_SF @@ -169,6 +170,16 @@ #define CONFIG_NETMASK 255.255.255.0 /* + * OCOTP Configs + */ +#ifdef CONFIG_CMD_IMXOTP + #define CONFIG_IMX_OTP + #define IMX_OTP_BASE OCOTP_BASE_ADDR + #define IMX_OTP_ADDR_MAX 0x7F + #define IMX_OTP_DATA_ERROR_VAL 0xBADABADA +#endif + +/* * I2C Configs */ #ifdef CONFIG_CMD_I2C diff --git a/include/imx_otp.h b/include/imx_otp.h new file mode 100644 index 0000000..87650d8 --- /dev/null +++ b/include/imx_otp.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __IMX_OCOTP_H_ +#define __IMX_OCOTP_H_ 1 + +int imx_otp_read_one_u32(u32 addr, u32 *value); +int imx_otp_blow_one_u32(u32 addr, u32 value, u32 *pfused_value); + +int otp_clk_enable(void); +int otp_clk_disable(void); + +#endif + |