Linux kernel hangs on i.MX6UL after early read of OTP registers

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Linux kernel hangs on i.MX6UL after early read of OTP registers

1,143 Views
HectorPalacios
Senior Contributor I

Hello,

I need to read the values of some OTP registers early during kernel initialization.

I'm reading them at the end of the probe() function of the fsl_opt.c driver.

static int fsl_otp_probe(struct platform_device *pdev)
{
     u32 reg;
     ...

     mutex_init(&otp_mutex);

     fsl_otp_read(0x22, &reg);
     printk("MAC0: 0x%08x\n", reg);
     return 0;
}

When I do this, the system hangs.

I tracked it down to the point where the OTP clock is disabled in the fsl_otp_read() function:

out:
     mutex_unlock(&otp_mutex);
       clk_disable_unprepare(otp_clk);

       return ret;
}

If I comment the clk_disable_unprepare(), the kernel goes on normally.

The function is basically writing a b00 to CCM_CCGR2[CG6], thus disabling the OTP clock.

If I don't do the early access, everything works fine, and even the sysfs access to OTP registers works without problems.

A similar code on the i.MX6 works ok, but not on the i.MX6UL.

I don't understand why disabling the OTP clock causes the kernel to hang.

I'm using kernel version: 4.1.15

+CC FabioEstevam


Regards,

--

Héctor Palacios

Labels (2)
Tags (2)
0 Kudos
2 Replies

670 Views
weidong_sun
NXP TechSupport
NXP TechSupport

Hello Hector,

(1) Corresponding register

CCM_CCGR2 is the register of CCM module, not OTP,  So check if you wrote error address, please!

CCM's base address is 20C_4000h

OTP's base 21B_C000h

So the address you will operate is 20C_4000h + 70h offset = 20C_4070h

(2) About code of "out"

When read or write failed, code of out will run, so it means erros occured when writing, so otp clock is disabled. that is to say, otp clock can't be disabled when system is running.

(3) device type in fsl_otp.c

I didn't find fsl_otp_read() function in otp driver, it should be added by yourself, the driver supports i.mx6 series processor, so you should pay attention to varible "devtype".

Hope above messages are helpful for you!

Best Regards,

Weidong

0 Kudos

670 Views
HectorPalacios
Senior Contributor I

Hello Weidong,

(1) CCM register

What my message said is that the function clk_disable_unprepare(otp_clk)is disabling the OTP clock. This is the function that is causing the hang, if it runs after having read an OTP register.

(2) 'out: code'

The code reaches the 'out' label not only on error, but also on normal successful flow, as you can see in fsl_otp_show()

linux-2.6-imx.git - Freescale i.MX Linux Tree 

(3) fsl_otp_read()

True, I created the function. Sorry about that. But the function is basically doing the same than fsl_otp_show(): read an OTP word. Here the code:

static u32 fsl_otp_read(int index, u32 *value)
{
     int ret;

     if (!fsl_otp)
          return -ENODEV;

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

     mutex_lock(&otp_mutex);

     fsl_otp->set_otp_timing();
     ret = otp_wait_busy(0);
     if (ret){
          *value = 0;
          goto out;
     }

     *value = __raw_readl(otp_base + HW_OCOTP_CUST_N(index));
out:
     mutex_unlock(&otp_mutex);
      clk_disable_unprepare(otp_clk);
     return ret;
}


static ssize_t fsl_otp_show(struct kobject *kobj, struct kobj_attribute *attr,
                   char *buf)
{
     unsigned int index = attr - otp_kattr;
     unsigned int phy_index;
     u32 value = 0;
     int ret;

     phy_index = fsl_otp_word_physical(fsl_otp, index);
     ret = fsl_otp_read(phy_index,&value);
     return ret ? 0 : sprintf(buf, "0x%x\n", value);
}

If I call fsl_otp_read() function at the end of the probe(), the kernel hangs when the OTP clock is disabled.

0 Kudos