zephyr
zephyr copied to clipboard
[Driver] [GPIO] pca_series gpio expander driver
Scope
I was trying to write a new driver for PCAL6524, a i2c gpio expander. Going thourgh existing drivers, there are numbers of driver for different PCA(L) series devices. They share similiar register layout and control logic. So I intends to unify these drivers for PCA(L)xxxx series i2c gpio expanders.
If this driver gets merged, it should retire pca95xx
, pca953x
and pcal64xxa
drivers.
Method
By referencing exsisting gpio_pca95xx
and pcal64xxa
driver, I have drafted these code to show my intended implementation. As shown in code, different capablilties can be defined:
- basic functions this applies to all compatiable devices.
- "latch" and drive strength this is what "L" in PCALxxxx means. allows to "latch" input until read and configure drive strength to one of 4 levels.
- pull up/down pull enable and pull select
- interrupt mask able to mask interrupt on certain pins. most PCAL devices has this, as well as PCA957x.
- interrupt edge / clear seen on PCAL6524.
- output config seen on PCAL6524. note that although many devices is able to configure push-pull or open-drain on a per-port basis, PCAL6524 suports configure on a per-pin basis.
We can describe a compatible device using a set of feature flags and ngpios
property. Based on that, it's possible to create separate register maps and api maps to drive different devices.
Question
-
Is it necessary to maintain cache for all config registers? In the original code, lots of registers are "cached" to speed-up the "read-modify-write" process. In my view, I/O expanders are not meant to be frequenty reconfigured. We also do not have tools like regmap in linux to automate the caching. Maintaining cache for devices with different port size can be complicated in coding. My intention is to only cache output values. update: The final implementation use Kconfig to control caching. I've tested the
GPIO_PCA_SERIES_CACHE_ALL=n
option on pcal6524 onmimx93_evk_a55
board. TheGPIO_PCA_SERIES_CACHE_ALL=y
option remains to be fully tested. -
Is there way to avoid creating multiple dt-bindings? I tried to avoid creating a lot of dt-bindings by put a "part_no" property under a single
nxp,pca_series.yaml
dt-binding.
Any suggestions are welcomed.
Thanks