This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/DRA71: Getting the following error when I2C1 and I2C2's peripheral registers are read "44000000.ocp:L3 Custom Error: MASTER MPU TARGET L4_PER1_P3 (Read): Data Access in User mode during Functional access"

Part Number: DRA71

Tool/software: Linux

Hi TI,

I am  trying to read On chip peripheral’s registers. In this case I2C.  Following is the output when i2cdetect tool is executed.

#i2cdetect -l
i2c-0   i2c             OMAP I2C adapter                        I2C adapter
i2c-1   i2c             OMAP I2C adapter                        I2C adapter
i2c-3   i2c             LVDS I2C adapter                        I2C adapter

I tried to read a register named “I2C_IRQSTATUS” of i2c-0(@0x48070028) and i2c-1(@0x48072028) using omapconf utility, we got the following error. The same error is observed when reading in an user space application through mmap() system call on /dev/mem.

# ./omapconf read 0x48072028

[ 4492.136407] ------------[ cut here ]------------

[ 4492.141059] WARNING: CPU: 0 PID: 397 at /mnt/yocto/yocto_repo/build/arago-tmp-external-linaro-toolchain/work-shared/delphi-jlr-isp-proto/kernel-source/drivers/bus/omap_l3_noc.c:147 l3_interrupt_handler+0x24c/0x350()

[ 4492.160259] 44000000.ocp:L3 Custom Error: MASTER MPU TARGET L4_PER1_P3 (Read): Data Access in User mode during Functional access

[ 4492.171867] Modules linked in: sch_fq_codel dspmem(O) cryptodev(O) cmemk(O) ti_fpd3_serdes ti_vip ti_csc ti_sc videobuf2_dma_contig videobuf2_memops ti_vpdma easylink_irq(O) ar0144at

[ 4492.188283] CPU: 0 PID: 397 Comm: omapconf Tainted: G        W  O    4.4.45-g89944627d5 #2

[ 4492.196578] Hardware name: Generic DRA72X (Flattened Device Tree)

[ 4492.202707] [<c0015c00>] (unwind_backtrace) from [<c0013830>] (show_stack+0x10/0x14)

[ 4492.210487] [<c0013830>] (show_stack) from [<c0032228>] (warn_slowpath_common+0x80/0xac)

[ 4492.218614] [<c0032228>] (warn_slowpath_common) from [<c0032284>] (warn_slowpath_fmt+0x30/0x40)

[ 4492.227350] [<c0032284>] (warn_slowpath_fmt) from [<c027c040>] (l3_interrupt_handler+0x24c/0x350)

[ 4492.236264] [<c027c040>] (l3_interrupt_handler) from [<c00667fc>] (handle_irq_event_percpu+0x9c/0x158)

[ 4492.245612] [<c00667fc>] (handle_irq_event_percpu) from [<c00668f0>] (handle_irq_event+0x38/0x5c)

[ 4492.254525] [<c00668f0>] (handle_irq_event) from [<c0069460>] (handle_fasteoi_irq+0xe0/0x1a8)

[ 4492.263089] [<c0069460>] (handle_fasteoi_irq) from [<c0065f54>] (generic_handle_irq+0x24/0x34)

[ 4492.271738] [<c0065f54>] (generic_handle_irq) from [<c00661b8>] (__handle_domain_irq+0x70/0xdc)

[ 4492.280474] [<c00661b8>] (__handle_domain_irq) from [<c00094fc>] (gic_handle_irq+0x38/0x64)

[ 4492.288859] [<c00094fc>] (gic_handle_irq) from [<c0014504>] (__irq_usr+0x44/0x60)

[ 4492.296369] Exception stack(0xdd899fb0 to 0xdd899ff8)

[ 4492.301438] 9fa0:                                     00000000 00000000 ffffffff 00000000

[ 4492.309648] 9fc0: 00000000 000d67c4 00000000 00000045 001b343c beebedc8 beebeed5 000d8547

[ 4492.317857] 9fe0: ffffffff beebead8 0001118d 00011190 20070030 ffffffff

[ 4492.324495] ---[ end trace 04c86c10cca3b266 ]---

[ 4492.329185] Unhandled fault: imprecise external abort (0x1406) at 0x00000000

[ 4492.336261] pgd = d9578000

[ 4492.338974] [00000000] *pgd=00000000

00000000

[ 4492.350463] systemd[1]: systemd-journald.service: Failed with result 'core-dump'.

[ 4492.358595] systemd[1]: systemd-journald.service: Service has no hold-off time, scheduling restart.

root@delphi-jlr-isp-proto:/usr/local/bin# [ 4492.368091] systemd[1]: Stopped Flush Journal to Persistent Storage.

[ 4492.378303] systemd[1]: Stopping Flush Journal to Persistent Storage...

[ 4492.385017] systemd[1]: Stopped Journal Service.

[ 4492.392152] systemd[1]: Starting Journal Service...

[ 4492.405515] systemd-journald[400]: File /run/log/journal/e5eeda1d12bb4071a39d7ed6e95f96dc/system.journal corrupted or uncleanly shut down, renaming and replacing.

[ 4492.428194] systemd[1]: Started Journal Service.

I followed one of the posts in the community and got a suggestion to read the PMIC registers of I2C peripheral to check if the peripheral is enabled or disabled. So I did that. I did a read on register CM_L4PER_I2C1_CLKCTRL@0x4A00 97A0 and CM_L4PER_I2C2_CLKCTRL@0x4A00 97A8, it returned 0x00030000, meaning its disabled.

I checked with our BSP engineer regarding this and got a confirmation that both I2C1 and I2C2 (In Linux I2C0 and I2C1) are enabled. To double check this we used i2cget tool to read a register of a PMIC chip connected on I2C0 bus.

# i2cget -f -y 0 0x60 0x1
0x22

So my question is Whether the I2C1 and I2C2 (In Linux I2C0 and I2C1) peripherals are enabled or not?

If the answer to the above question is disabled, then how are we able to read the registers of a PMIC chip connected to I2C1 (In Linux I2C0) bus?

Thanks,

Gowtham

  • Hi Gowtham,

    The i2c driver in Linux does power management. Which means it will put the module in low power mode when the i2c transactions are not happening.

    When you run the i2c commands, it is turned on and then after usage, put back to the sleep/low power mode.

    But the registers are accessible whenever required, You should see the i2c interrupts increasing in the /proc/interrupts file.

    Now, omapconf is bypassing the i2c driver and trying to read the registers directly, that's why the above mentioned errors.

    If you want it to disable the power management, you can do so by adding following properties in the i2c device tree nodes.

    ti,no-idle;

    ti,no-reset-on-init;

    You

    Regards,

    Nikhil D

  • Hi Nikil,

    Thank you for your suggestion. I checked with our BSP engineer and got a suggestion that its not a good idea to disable power optimization. I set the register 

    CM_L4PER_I2C2_CLKCTRL(@0x4A0097A8)=0x00000002 and I am able to access I2C2 registers using devmem2 tool. But we are looking at a clean solution and we don't want to enable the peripheral from the application side. But we just want to read the peripheral registers. Does the i2c driver provide any mechanism to read these registers? If so could you please give a simple example?

    Thanks a lot for your support!

    Thanks,

    Gowtham

  • Hi Gowtham,

    No driver is supposed to expose any register reads/writes to the user space. It provides you with i2c functionality that's good enough.
    Why would you need to read the interrupt status register from application.

    What are you trying to achieve?

    Avoid using omapconf or any register read/write in the production use case.
    Applications should only be using driver provided functionality.


    Regards,
    Nikhil D
  • Hi Nikhil,

    As part of our implementation, we need to read the on chip peripheral's registers periodically and compare with the value which is being set at start up and take certain actions if the value is modified.
    For this implementation, just to check if those registers are accessible, we used omapconf.

    Thanks,
    Gowtham
  • Hi Nikhil,
    What would be the safe method to implement the above mentioned requirement?

    Thanks,
    Gowtham
  • Hello,

    Ideally, you should not write any application which depends on certain REGISTER in the chip.
    It should wait on some event or some communication from kernel to notify or simple sysfs based polling.

    Only kernel drivers should be reading/writing the registers.
    Can you explain in detail why you need to read I2C IRQSTATUS register or any other register from the application?

    As I said before, you can turn off the power management for the i2c instance and the regs are always accessible.
    There is no way you can keep the registers accessible EVEN FROM KERNEL without telling the i2c driver that you need it.


    Regards,
    Nikhil D
  • Hi Nikhil,

    Thank you for the fast reply.

    We are using few peripherals in our project. I2C is one of them. Under any circumstances, if the registers of these peripherals are modified by any means, we should take corrective actions like resetting the board or rewriting the registers. For this, we should periodically read these registers and compare with the initially set value. I2C IRQSTATUS is one of the registers of the I2C peripheral which will be monitored.

    Thanks,
    Gowtham
  • Hi Gowtham,

    If you want to periodically read the registers, then it makes complete sense to disable the power management for desired I2C instance
    This is the first thing that I suggested. And now I would strongly recommend that as the only solution here.

    Nikhil D
  • Hi Nikhil,

    Is it safe to power on the peripheral externally (outside I2C driver), like in a custom Kernel Module before reading the register and turn it off after reading? Will it have any side effects? We will just read the registers and will modify them.

    Thanks,
    Gowtham

  • Gowtham,

    There are many problems with this.
    You have to ensure that kernel is not using the i2c before you turn off the clock.
    Its going to get complicated.

    You will not save much power by turning on/off the i2c controller and have to worry about weird corner cases.
    Specially when you say that you want to periodically check the regs
    Simply turn off the power management for i2c.



    Regards,
    Nikhil D
  • Hi Nikhil,

    Thank you for your recommendation.

    Regards,

    Gowtham