示例#1
0
static ssize_t fsl_otp_store(struct kobject *kobj, struct kobj_attribute *attr,
			     const char *buf, size_t count)
{
	unsigned int index = attr - otp_kattr;
	u32 value;
	int ret;

	sscanf(buf, "0x%x", &value);

	ret = clk_prepare_enable(otp_clk);
	if (ret)
		return 0;

	mutex_lock(&otp_mutex);

	set_otp_timing();
	ret = otp_wait_busy(0);
	if (ret)
		goto out;

	otp_write_bits(index, value, 0x3e77);

	/* Reload all the shadow registers */
	__raw_writel(BM_OCOTP_CTRL_RELOAD_SHADOWS,
		     otp_base + HW_OCOTP_CTRL_SET);
	udelay(1);
	otp_wait_busy(BM_OCOTP_CTRL_RELOAD_SHADOWS);

out:
	mutex_unlock(&otp_mutex);
	clk_disable_unprepare(otp_clk);
	return ret ? 0 : count;
}
示例#2
0
static ssize_t fsl_otp_show(struct kobject *kobj, struct kobj_attribute *attr,
			    char *buf)
{
	unsigned int index = attr - otp_kattr;
	u32 value = 0;
	int ret;

	ret = clk_prepare_enable(otp_clk);
	if (ret)
		return 0;

	mutex_lock(&otp_mutex);

	set_otp_timing();
	ret = otp_wait_busy(0);
	if (ret)
		goto out;

	value = __raw_readl(otp_base + HW_OCOTP_CUST_N(index));

out:
	mutex_unlock(&otp_mutex);
	clk_disable_unprepare(otp_clk);
	return ret ? 0 : sprintf(buf, "0x%x\n", value);
}
示例#3
0
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);
}
示例#4
0
static int otp_write_bits(int addr, u32 data, u32 magic)
{
	u32 c; /* for control register */

	/* init the control register */
	c = __raw_readl(otp_base + HW_OCOTP_CTRL);
	c &= ~BM_OCOTP_CTRL_ADDR;
	c |= BF(addr, OCOTP_CTRL_ADDR);
	c |= BF(magic, OCOTP_CTRL_WR_UNLOCK);
	__raw_writel(c, otp_base + HW_OCOTP_CTRL);

	/* init the data register */
	__raw_writel(data, otp_base + HW_OCOTP_DATA);
	otp_wait_busy(0);

	mdelay(2); /* Write Postamble */

	return 0;
}
示例#5
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;
}
示例#6
0
int fsl_otp_readl(unsigned long offset, u32 *value)
{
	int ret = 0;

	ret = clk_prepare_enable(otp_clk);
	if (ret)
		return ret;

	mutex_lock(&otp_mutex);

	set_otp_timing();
	ret = otp_wait_busy(0);
	if (ret)
		goto out;

        *value = __raw_readl(otp_base + offset);

out:
	mutex_unlock(&otp_mutex);
	clk_disable_unprepare(otp_clk);
        return ret;
}
示例#7
0
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;
}
示例#8
0
static int otp_blow_prep(void)
{
	return  (!set_otp_timing()) ? otp_wait_busy(0) : -1;
}