2828#include <zephyr/logging/log.h>
2929LOG_MODULE_REGISTER (gpio_pca95xx );
3030
31+ #if CONFIG_LITTLE_ENDIAN
32+ #define LOW_BYTE_LE16_IDX 0
33+ #define HIGH_BYTE_LE16_IDX 1
34+ #else
35+ #define LOW_BYTE_LE16_IDX 1
36+ #define HIGH_BYTE_LE16_IDX 0
37+ #endif
38+
3139/* Register definitions */
3240#define REG_INPUT_PORT0 0x00
3341#define REG_INPUT_PORT1 0x01
@@ -36,7 +44,7 @@ LOG_MODULE_REGISTER(gpio_pca95xx);
3644#define REG_POL_INV_PORT0 0x04
3745#define REG_POL_INV_PORT1 0x05
3846#define REG_CONF_PORT0 0x06
39- #define REG_CONG_PORT1 0x07
47+ #define REG_CONF_PORT1 0x07
4048#define REG_OUT_DRV_STRENGTH_PORT0_L 0x40
4149#define REG_OUT_DRV_STRENGTH_PORT0_H 0x41
4250#define REG_OUT_DRV_STRENGTH_PORT1_L 0x42
@@ -108,6 +116,37 @@ struct gpio_pca95xx_drv_data {
108116#endif
109117};
110118
119+ static int read_port_reg (const struct device * dev , uint8_t reg , uint8_t pin ,
120+ uint16_t * cache , uint16_t * buf )
121+ {
122+ const struct gpio_pca95xx_config * const config = dev -> config ;
123+ uint8_t b_buf ;
124+ int ret ;
125+
126+ if (pin >= 8 )
127+ reg ++ ;
128+
129+ ret = i2c_reg_read_byte_dt (& config -> bus , reg , & b_buf );
130+ if (ret != 0 ) {
131+ LOG_ERR ("PCA95XX[0x%X]: error reading register 0x%X (%d)" ,
132+ config -> bus .addr , reg , ret );
133+ return ret ;
134+ }
135+
136+ if (pin < 8 ) {
137+ ((uint8_t * )cache )[LOW_BYTE_LE16_IDX ] = b_buf ;
138+ } else {
139+ ((uint8_t * )cache )[HIGH_BYTE_LE16_IDX ] = b_buf ;
140+ }
141+
142+ * buf = * cache ;
143+
144+ LOG_DBG ("PCA95XX[0x%X]: Read: REG[0x%X] = 0x%X" ,
145+ config -> bus .addr , reg , b_buf );
146+
147+ return 0 ;
148+ }
149+
111150/**
112151 * @brief Read both port 0 and port 1 registers of certain register function.
113152 *
@@ -145,6 +184,36 @@ static int read_port_regs(const struct device *dev, uint8_t reg,
145184 return 0 ;
146185}
147186
187+
188+ static int write_port_reg (const struct device * dev , uint8_t reg , uint8_t pin ,
189+ uint16_t * cache , uint16_t value )
190+ {
191+ const struct gpio_pca95xx_config * const config = dev -> config ;
192+ uint8_t buf [2 ];
193+ int ret ;
194+
195+ if (pin < 8 ) {
196+ buf [1 ] = value ;
197+ } else {
198+ buf [1 ] = value >> 8 ;
199+ reg ++ ;
200+ }
201+ buf [0 ] = reg ;
202+
203+ LOG_DBG ("PCA95XX[0x%X]: Write: REG[0x%X] = 0x%X" , config -> bus .addr ,
204+ reg , buf [1 ]);
205+
206+ ret = i2c_write_dt (& config -> bus , buf , sizeof (buf ));
207+ if (ret == 0 ) {
208+ * cache = value ;
209+ } else {
210+ LOG_ERR ("PCA95XX[0x%X]: error writing to register 0x%X "
211+ "(%d)" , config -> bus .addr , reg , ret );
212+ }
213+
214+ return ret ;
215+ }
216+
148217/**
149218 * @brief Write both port 0 and port 1 registers of certain register function.
150219 *
@@ -182,6 +251,16 @@ static int write_port_regs(const struct device *dev, uint8_t reg,
182251 return ret ;
183252}
184253
254+ static inline int update_input_reg (const struct device * dev , uint8_t pin ,
255+ uint16_t * buf )
256+ {
257+ struct gpio_pca95xx_drv_data * const drv_data =
258+ (struct gpio_pca95xx_drv_data * const )dev -> data ;
259+
260+ return read_port_reg (dev , REG_INPUT_PORT0 , pin ,
261+ & drv_data -> reg_cache .input , buf );
262+ }
263+
185264static inline int update_input_regs (const struct device * dev , uint16_t * buf )
186265{
187266 struct gpio_pca95xx_drv_data * const drv_data =
@@ -191,6 +270,16 @@ static inline int update_input_regs(const struct device *dev, uint16_t *buf)
191270 & drv_data -> reg_cache .input , buf );
192271}
193272
273+ static inline int update_output_reg (const struct device * dev , uint8_t pin ,
274+ uint16_t value )
275+ {
276+ struct gpio_pca95xx_drv_data * const drv_data =
277+ (struct gpio_pca95xx_drv_data * const )dev -> data ;
278+
279+ return write_port_reg (dev , REG_OUTPUT_PORT0 , pin ,
280+ & drv_data -> reg_cache .output , value );
281+ }
282+
194283static inline int update_output_regs (const struct device * dev , uint16_t value )
195284{
196285 struct gpio_pca95xx_drv_data * const drv_data =
@@ -200,43 +289,45 @@ static inline int update_output_regs(const struct device *dev, uint16_t value)
200289 & drv_data -> reg_cache .output , value );
201290}
202291
203- static inline int update_direction_regs (const struct device * dev ,
292+ static inline int update_direction_reg (const struct device * dev , uint8_t pin ,
204293 uint16_t value )
205294{
206295 struct gpio_pca95xx_drv_data * const drv_data =
207296 (struct gpio_pca95xx_drv_data * const )dev -> data ;
208297
209- return write_port_regs (dev , REG_CONF_PORT0 ,
210- & drv_data -> reg_cache .dir , value );
298+ return write_port_reg (dev , REG_CONF_PORT0 , pin ,
299+ & drv_data -> reg_cache .dir , value );
211300}
212301
213- static inline int update_pul_sel_regs (const struct device * dev ,
214- uint16_t value )
302+ static inline int update_pul_sel_reg (const struct device * dev , uint8_t pin ,
303+ uint16_t value )
215304{
216305 struct gpio_pca95xx_drv_data * const drv_data =
217306 (struct gpio_pca95xx_drv_data * const )dev -> data ;
218307
219- return write_port_regs (dev , REG_PUD_SEL_PORT0 ,
220- & drv_data -> reg_cache .pud_sel , value );
308+ return write_port_reg (dev , REG_PUD_SEL_PORT0 , pin ,
309+ & drv_data -> reg_cache .pud_sel , value );
221310}
222311
223- static inline int update_pul_en_regs (const struct device * dev , uint16_t value )
312+ static inline int update_pul_en_reg (const struct device * dev , uint8_t pin ,
313+ uint8_t value )
224314{
225315 struct gpio_pca95xx_drv_data * const drv_data =
226316 (struct gpio_pca95xx_drv_data * const )dev -> data ;
227317
228- return write_port_regs (dev , REG_PUD_EN_PORT0 ,
229- & drv_data -> reg_cache .pud_en , value );
318+ return write_port_reg (dev , REG_PUD_EN_PORT0 , pin ,
319+ & drv_data -> reg_cache .pud_en , value );
230320}
231321
232322#ifdef CONFIG_GPIO_PCA95XX_INTERRUPT
233- static inline int update_int_mask_regs (const struct device * dev , uint16_t value )
323+ static inline int update_int_mask_reg (const struct device * dev , uint8_t pin ,
324+ uint16_t value )
234325{
235326 struct gpio_pca95xx_drv_data * const drv_data =
236327 (struct gpio_pca95xx_drv_data * const )dev -> data ;
237328
238- return write_port_regs (dev , REG_INT_MASK_PORT0 ,
239- & drv_data -> reg_cache .int_mask , value );
329+ return write_port_reg (dev , REG_INT_MASK_PORT0 , pin ,
330+ & drv_data -> reg_cache .int_mask , value );
240331}
241332#endif /* CONFIG_GPIO_PCA95XX_INTERRUPT */
242333
@@ -264,7 +355,7 @@ static int setup_pin_dir(const struct device *dev, uint32_t pin, int flags)
264355 } else if ((flags & GPIO_OUTPUT_INIT_LOW ) != 0U ) {
265356 reg_out &= ~BIT (pin );
266357 }
267- ret = update_output_regs (dev , reg_out );
358+ ret = update_output_reg (dev , pin , reg_out );
268359 if (ret != 0 ) {
269360 return ret ;
270361 }
@@ -273,7 +364,7 @@ static int setup_pin_dir(const struct device *dev, uint32_t pin, int flags)
273364 reg_dir |= BIT (pin );
274365 }
275366
276- ret = update_direction_regs (dev , reg_dir );
367+ ret = update_direction_reg (dev , pin , reg_dir );
277368
278369 return ret ;
279370}
@@ -319,7 +410,7 @@ static int setup_pin_pullupdown(const struct device *dev, uint32_t pin,
319410 /* pull down == 0, pull up == 1 */
320411 WRITE_BIT (reg_pud , pin , (flags & GPIO_PULL_UP ) != 0U );
321412
322- ret = update_pul_sel_regs (dev , reg_pud );
413+ ret = update_pul_sel_reg (dev , pin , reg_pud );
323414 if (ret ) {
324415 return ret ;
325416 }
@@ -331,7 +422,7 @@ static int setup_pin_pullupdown(const struct device *dev, uint32_t pin,
331422 WRITE_BIT (reg_pud , pin ,
332423 (flags & (GPIO_PULL_UP | GPIO_PULL_DOWN )) != 0U );
333424
334- ret = update_pul_en_regs (dev , reg_pud );
425+ ret = update_pul_en_reg (dev , pin , reg_pud );
335426
336427 return ret ;
337428}
@@ -394,8 +485,7 @@ static int gpio_pca95xx_config(const struct device *dev,
394485 return ret ;
395486}
396487
397- static int gpio_pca95xx_port_get_raw (const struct device * dev ,
398- uint32_t * value )
488+ static int gpio_pca95xx_port_get_raw (const struct device * dev , uint32_t * value )
399489{
400490 struct gpio_pca95xx_drv_data * const drv_data =
401491 (struct gpio_pca95xx_drv_data * const )dev -> data ;
@@ -587,7 +677,7 @@ static int gpio_pca95xx_pin_interrupt_configure(const struct device *dev,
587677 reg_out = drv_data -> reg_cache .int_mask ;
588678 WRITE_BIT (reg_out , pin , (mode == GPIO_INT_MODE_DISABLED ));
589679
590- ret = update_int_mask_regs (dev , reg_out );
680+ ret = update_int_mask_reg (dev , pin , reg_out );
591681 if (ret != 0 ) {
592682 LOG_ERR ("PCA95XX[0x%X]: failed to update int mask (%d)" ,
593683 config -> bus .addr , ret );
0 commit comments