>> Can you add printks in dw_readl/dw_writel and maybe a few extra printks >> in their callers to see what accesses are being made, and share the >> resulting trace? Here is a follow up with the key difference between the working and non-working traces. Works (with the __i2c_dw_enable_and_wait() in i2c_dw_xfer_init() : ... [ 0.222195] i2c-designware-pci 0000:00:18.3: i2c_dw_disable_int: dw_writel(0x30, 0x00000000) [ 0.222198] i2c-designware-pci 0000:00:18.3: __i2c_dw_enable: dw_writel(0x6c, 0x00000001) [ 0.222201] i2c-designware-pci 0000:00:18.3: __i2c_dw_enable_and_wait: dw_readl(0x9c) => 0x00000000 [ 0.222465] i2c-designware-pci 0000:00:18.3: __i2c_dw_enable: dw_writel(0x6c, 0x00000001) [ 0.222469] i2c-designware-pci 0000:00:18.3: __i2c_dw_enable_and_wait: dw_readl(0x9c) => 0x00000001 [ 0.222472] i2c-designware-pci 0000:00:18.3: i2c_dw_xfer_init: dw_readl(0x40) => 0x00000001 [ 0.222475] i2c-designware-pci 0000:00:18.3: i2c_dw_xfer_init: dw_writel(0x30, 0x00000254) ... The first write(0x6c,1)/read(0x9c) sequence returns 0 (not enabled). It works after a retry. Non-functional trace fragment from the previous email: ... [ 0.229248] i2c-designware-pci 0000:00:18.3: i2c_dw_disable_int: dw_writel(0x30, 0x00000000) [ 0.229251] i2c-designware-pci 0000:00:18.3: __i2c_dw_enable: dw_writel(0x6c, 0x00000001) [ 0.229254] i2c-designware-pci 0000:00:18.3: i2c_dw_xfer_init: dw_readl(0x40) => 0x00000000 [ 0.229257] i2c-designware-pci 0000:00:18.3: i2c_dw_xfer_init: dw_writel(0x30, 0x00000254) ...