1
0
Fork 0

imx: ocotp: mxc add i.MX7D support

* Ocotp of i.MX7D has different operation rule.
  This patch is to add support for i.MX7D ocotp.

Signed-off-by: Adrian Alonso <aalonso@freescale.com>
Signed-off-by: Peng Fan <Peng.Fan@freescale.com>
Signed-off-by: Ye.Li <B37916@freescale.com>
utp
Adrian Alonso 2015-08-11 11:19:52 -05:00 committed by Stefano Babic
parent 26dd346464
commit 42c91c10c5
1 changed files with 72 additions and 0 deletions

View File

@ -25,8 +25,21 @@
#define BM_CTRL_ERROR 0x00000200
#define BM_CTRL_BUSY 0x00000100
#define BO_CTRL_ADDR 0
#ifdef CONFIG_MX7
#define BM_CTRL_ADDR 0x0000000f
#define BM_CTRL_RELOAD 0x00000400
#else
#define BM_CTRL_ADDR 0x0000007f
#endif
#ifdef CONFIG_MX7
#define BO_TIMING_FSOURCE 12
#define BM_TIMING_FSOURCE 0x0007f000
#define BV_TIMING_FSOURCE_NS 1001
#define BO_TIMING_PROG 0
#define BM_TIMING_PROG 0x00000fff
#define BV_TIMING_PROG_US 10
#else
#define BO_TIMING_STROBE_READ 16
#define BM_TIMING_STROBE_READ 0x003f0000
#define BV_TIMING_STROBE_READ_NS 37
@ -36,6 +49,7 @@
#define BO_TIMING_STROBE_PROG 0
#define BM_TIMING_STROBE_PROG 0x00000fff
#define BV_TIMING_STROBE_PROG_US 10
#endif
#define BM_READ_CTRL_READ_FUSE 0x00000001
@ -109,6 +123,25 @@ int fuse_read(u32 bank, u32 word, u32 *val)
return finish_access(regs, __func__);
}
#ifdef CONFIG_MX7
static void set_timing(struct ocotp_regs *regs)
{
u32 ipg_clk;
u32 fsource, prog;
u32 timing;
ipg_clk = mxc_get_clock(MXC_IPG_CLK);
fsource = DIV_ROUND_UP((ipg_clk / 1000) * BV_TIMING_FSOURCE_NS,
+ 1000000) + 1;
prog = DIV_ROUND_CLOSEST(ipg_clk * BV_TIMING_PROG_US, 1000000) + 1;
timing = BF(fsource, TIMING_FSOURCE) | BF(prog, TIMING_PROG);
clrsetbits_le32(&regs->timing, BM_TIMING_FSOURCE | BM_TIMING_PROG,
timing);
}
#else
static void set_timing(struct ocotp_regs *regs)
{
u32 ipg_clk;
@ -130,12 +163,17 @@ static void set_timing(struct ocotp_regs *regs)
clrsetbits_le32(&regs->timing, BM_TIMING_STROBE_READ | BM_TIMING_RELAX |
BM_TIMING_STROBE_PROG, timing);
}
#endif
static void setup_direct_access(struct ocotp_regs *regs, u32 bank, u32 word,
int write)
{
u32 wr_unlock = write ? BV_CTRL_WR_UNLOCK_KEY : 0;
#ifdef CONFIG_MX7
u32 addr = bank;
#else
u32 addr = bank << 3 | word;
#endif
set_timing(regs);
clrsetbits_le32(&regs->ctrl, BM_CTRL_WR_UNLOCK | BM_CTRL_ADDR,
@ -155,7 +193,11 @@ int fuse_sense(u32 bank, u32 word, u32 *val)
setup_direct_access(regs, bank, word, false);
writel(BM_READ_CTRL_READ_FUSE, &regs->read_ctrl);
wait_busy(regs, 1);
#ifdef CONFIG_MX7
*val = readl((&regs->read_fuse_data0) + (word << 2));
#else
*val = readl(&regs->read_fuse_data);
#endif
return finish_access(regs, __func__);
}
@ -176,8 +218,38 @@ int fuse_prog(u32 bank, u32 word, u32 val)
return ret;
setup_direct_access(regs, bank, word, true);
#ifdef CONFIG_MX7
switch (word) {
case 0:
writel(0, &regs->data1);
writel(0, &regs->data2);
writel(0, &regs->data3);
writel(val, &regs->data0);
break;
case 1:
writel(val, &regs->data1);
writel(0, &regs->data2);
writel(0, &regs->data3);
writel(0, &regs->data0);
break;
case 2:
writel(0, &regs->data1);
writel(val, &regs->data2);
writel(0, &regs->data3);
writel(0, &regs->data0);
break;
case 3:
writel(0, &regs->data1);
writel(0, &regs->data2);
writel(val, &regs->data3);
writel(0, &regs->data0);
break;
}
wait_busy(regs, BV_TIMING_PROG_US);
#else
writel(val, &regs->data);
wait_busy(regs, BV_TIMING_STROBE_PROG_US);
#endif
udelay(WRITE_POSTAMBLE_US);
return finish_access(regs, __func__);