Repurposing I2C Pins without Device PM

I'm working to write a Zephyr-compatible driver for the LP5814 on a board with a nRF5340. The LP5814 is an LED controller that receives commands over an I2C interface. There's a feature of the LP5814 that is proving to be difficult to implement because of how Zephyr controls access to the I2C bus.

The feature in question is the LP5814's low power mode. Entering it requires a simple I2C transaction, but leaving it involves a special sequence of edges on the SDA and SCL pins that belong to the I2C bus. See the timing diagram:

There's an alternate way to enter and exit low power mode, but it looks like it could be vulnerable to being activated with I2C traffic meant for other devices.

Multiple threads in my application access I2C devices. They go through the usual Zephyr-nrfx glue code, which involves a synchronization object so that only one thread can do a transaction at a time. Unfortunately, there isn't a way to acquire this lock without also enabling the I2C peripheral. It would be desired to acquire the lock while keeping the I2C peripheral disabled so that no other I2C-driven device driver could interrupt the wakeup procedure of the LP5814.

We're currently on Zephyr 3.4, so I looked ahead to newer releases to see if such functionality was added. I see that an "exclusive access" pair of functions was added in Zephyr's PR 86721, but it still uses the Device Power Manager get/put functions to drive pinctrl. If I'm not mistaken, I can't finesse pinctrl into respecting the GPIO configuration required for the LP5814 wakeup procedure.

github.com/.../86721

Currently, my work-around is to access the nrfx driver directly so I can shut off the I2C peripheral and reconfigure the pins to my desires, restoring the configurations and reactivating the I2C peripheral when finished. This workaround has to be wrapped in something like a scheduler disable, which feels awful.

I plan to make my application request all I2C operations through a new layer of firmware with a lock that doesn't interact with the Device Power Manager. In-between my main application logic and device drivers are HALs. I will make those HALs use the new layer so the lock is respected and so that I don't have to edit any of the drivers that comes with Zephyr or NCS. I'm worried that System Work Queue work from those drivers will not be able to respect the new design, though.

Is there something I seem to be missing? Is Zephyr/NCS just not really equipped to handle an I2C device that needs the SDA and SCL pins to be repurposed on occasion?

Related