summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorVijay Hiremath <vijay.p.hiremath@intel.com>2021-04-21 15:45:01 -0700
committerCommit Bot <commit-bot@chromium.org>2021-04-23 05:42:36 +0000
commita4e38fe2152b56a178a77c4ff8b89ba5f85e027b (patch)
tree3e21a939309b351f8afe329d3c437e8c7c0de74f /driver
parent8d411971acc3a9ebf35918a40e6814a430121b8b (diff)
downloadchrome-ec-a4e38fe2152b56a178a77c4ff8b89ba5f85e027b.tar.gz
pca9675: Add code to fit standard I/O expander functionality
Added code so that PCA9675 I/O expander driver fits standard I/O expander functionality. BUG=b:169814014 BRANCH=none TEST=Manually tested on ADLRVP, ioexget & ioexset works Cq-Depend: chromium:2845014 Change-Id: I07957a3f1de9b70fc396d767e8cc3ac8884b9c2e Signed-off-by: Vijay Hiremath <vijay.p.hiremath@intel.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2829985 Reviewed-by: caveh jalali <caveh@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r--driver/ioexpander/pca9675.c93
-rw-r--r--driver/ioexpander/pca9675.h90
2 files changed, 88 insertions, 95 deletions
diff --git a/driver/ioexpander/pca9675.c b/driver/ioexpander/pca9675.c
index df1217bba0..7b08a64175 100644
--- a/driver/ioexpander/pca9675.c
+++ b/driver/ioexpander/pca9675.c
@@ -5,20 +5,26 @@
* NXP PCA9675PW I/O Port expander driver source
*/
-/* TODO (b/169814014): Implement code to fit "struct ioexpander_drv" */
-
+#include "i2c.h"
+#include "ioexpander.h"
#include "pca9675.h"
-static uint16_t cache_out_pins[CONFIG_IO_EXPANDER_PORT_COUNT];
+struct pca9675_ioexpander {
+ /* I/O port direction (1 = input, 0 = output) */
+ uint16_t io_direction;
+ uint16_t cache_out_pins;
+};
+
+static struct pca9675_ioexpander pca9675_iox[CONFIG_IO_EXPANDER_PORT_COUNT];
-static int pca9675_read(int ioex, uint16_t *data)
+static int pca9675_read16(int ioex, uint16_t *data)
{
- return i2c_xfer(pca9675_iox[ioex].i2c_host_port,
- pca9675_iox[ioex].i2c_addr_flags,
+ return i2c_xfer(ioex_config[ioex].i2c_host_port,
+ ioex_config[ioex].i2c_addr_flags,
NULL, 0, (uint8_t *)data, 2);
}
-static int pca9675_write(int ioex, uint16_t data)
+static int pca9675_write16(int ioex, uint16_t data)
{
/*
* PCA9675 is Quasi-bidirectional I/O architecture hence
@@ -27,8 +33,8 @@ static int pca9675_write(int ioex, uint16_t data)
*/
data |= pca9675_iox[ioex].io_direction;
- return i2c_xfer(pca9675_iox[ioex].i2c_host_port,
- pca9675_iox[ioex].i2c_addr_flags,
+ return i2c_xfer(ioex_config[ioex].i2c_host_port,
+ ioex_config[ioex].i2c_addr_flags,
(uint8_t *)&data, 2, NULL, 0);
}
@@ -36,45 +42,80 @@ static int pca9675_reset(int ioex)
{
uint8_t reset = PCA9675_RESET_SEQ_DATA;
- return i2c_xfer(pca9675_iox[ioex].i2c_host_port,
+ return i2c_xfer(ioex_config[ioex].i2c_host_port,
0, &reset, 1, NULL, 0);
}
-int pca9675_get_pin(int ioex, uint16_t pin, bool *level)
+static int pca9675_set_flags_by_mask(int ioex, int port, int mask, int flags)
+{
+ /* Initialize the I/O directions */
+ if (flags & GPIO_INPUT)
+ pca9675_iox[ioex].io_direction |= mask;
+ else
+ pca9675_iox[ioex].io_direction &= ~mask;
+
+ return EC_SUCCESS;
+}
+
+static int pca9675_get_flags_by_mask(int ioex, int port, int mask, int *flags)
+{
+ *flags = mask & pca9675_iox[ioex].io_direction ?
+ GPIO_INPUT : GPIO_OUTPUT;
+
+ return EC_SUCCESS;
+}
+
+static int pca9675_get_level(int ioex, int port, int mask, int *val)
{
int rv = EC_SUCCESS;
uint16_t data_read;
/* Read from IO-expander only if the pin is input */
- if (pca9675_iox[ioex].io_direction & pin) {
- rv = pca9675_read(ioex, &data_read);
+ if (pca9675_iox[ioex].io_direction & mask) {
+ rv = pca9675_read16(ioex, &data_read);
if (!rv)
- *level = !!(data_read & pin);
+ *val = !!(data_read & mask);
} else {
- *level = !!(cache_out_pins[ioex] & pin);
+ *val = !!(pca9675_iox[ioex].cache_out_pins & mask);
}
return rv;
}
-int pca9675_update_pins(int ioex, uint16_t setpins, uint16_t clearpins)
+static int pca9675_set_level(int ioex, int port, int mask, int val)
{
/* Update the output pins */
- cache_out_pins[ioex] |= setpins;
- cache_out_pins[ioex] &= ~clearpins;
+ if (val)
+ pca9675_iox[ioex].cache_out_pins |= mask;
+ else
+ pca9675_iox[ioex].cache_out_pins &= ~mask;
+
+ return pca9675_write16(ioex, pca9675_iox[ioex].cache_out_pins);
+}
- return pca9675_write(ioex, cache_out_pins[ioex]);
+static int pca9675_enable_interrupt(int ioex, int port, int mask, int enable)
+{
+ /*
+ * Nothing to do as an interrupt is generated by any rising or
+ * falling edge of the port inputs.
+ */
+ return EC_SUCCESS;
}
int pca9675_init(int ioex)
{
- int rv;
+ pca9675_iox[ioex].io_direction = PCA9675_DEFAULT_IO_DIRECTION;
+ pca9675_iox[ioex].cache_out_pins = 0;
/* Set pca9675 to Power-on reset */
- rv = pca9675_reset(ioex);
- if (rv)
- return rv;
-
- /* Initialize the I/O direction */
- return pca9675_write(ioex, 0);
+ return pca9675_reset(ioex);
}
+
+const struct ioexpander_drv pca9675_ioexpander_drv = {
+ .init = &pca9675_init,
+ .get_level = &pca9675_get_level,
+ .set_level = &pca9675_set_level,
+ .get_flags_by_mask = &pca9675_get_flags_by_mask,
+ .set_flags_by_mask = &pca9675_set_flags_by_mask,
+ .enable_interrupt = &pca9675_enable_interrupt,
+};
diff --git a/driver/ioexpander/pca9675.h b/driver/ioexpander/pca9675.h
index e01278f7d6..59f36918a4 100644
--- a/driver/ioexpander/pca9675.h
+++ b/driver/ioexpander/pca9675.h
@@ -8,80 +8,32 @@
#ifndef __CROS_EC_IOEXPANDER_PCA9675_H
#define __CROS_EC_IOEXPANDER_PCA9675_H
-#include <stdbool.h>
-
-#include "hooks.h"
-#include "i2c.h"
-
-#define PCA9675_IO_P00 BIT(0)
-#define PCA9675_IO_P01 BIT(1)
-#define PCA9675_IO_P02 BIT(2)
-#define PCA9675_IO_P03 BIT(3)
-#define PCA9675_IO_P04 BIT(4)
-#define PCA9675_IO_P05 BIT(5)
-#define PCA9675_IO_P06 BIT(6)
-#define PCA9675_IO_P07 BIT(7)
-
-#define PCA9675_IO_P10 BIT(8)
-#define PCA9675_IO_P11 BIT(9)
-#define PCA9675_IO_P12 BIT(10)
-#define PCA9675_IO_P13 BIT(11)
-#define PCA9675_IO_P14 BIT(12)
-#define PCA9675_IO_P15 BIT(13)
-#define PCA9675_IO_P16 BIT(14)
-#define PCA9675_IO_P17 BIT(15)
+/* PCA9675 IO pins that can be referenced in gpio.inc */
+enum pca9675_io_pins {
+ PCA9675_IO_P00,
+ PCA9675_IO_P01,
+ PCA9675_IO_P02,
+ PCA9675_IO_P03,
+ PCA9675_IO_P04,
+ PCA9675_IO_P05,
+ PCA9675_IO_P06,
+ PCA9675_IO_P07,
+ PCA9675_IO_P10,
+ PCA9675_IO_P11,
+ PCA9675_IO_P12,
+ PCA9675_IO_P13,
+ PCA9675_IO_P14,
+ PCA9675_IO_P15,
+ PCA9675_IO_P16,
+ PCA9675_IO_P17,
+};
-/* Sent 06 to address 00 to reset the PCA9675 to back to power up state */
+/* Write 06 to address 00 to reset the PCA9675 to back to power up state */
#define PCA9675_RESET_SEQ_DATA 0x06
/* Default I/O directons of PCA9675 is input */
#define PCA9675_DEFAULT_IO_DIRECTION 0xffff
-#define HOOK_PRIO_INIT_PCA9675 (HOOK_PRIO_INIT_I2C + 1)
-
-/* PCA9675 IOexpander structure */
-struct pca9675_ioexpander {
- /* Physical I2C port connects to the IO expander chip. */
- const int i2c_host_port;
- /* I2C slave address */
- const uint16_t i2c_addr_flags;
- /* I/O port direction (1 = input, 0 = output) */
- const uint16_t io_direction;
-};
-
-extern const struct pca9675_ioexpander pca9675_iox[];
-
-/*
- * Get input level. Note that this reflects the actual level on the
- * pin, even if the pin is configured as output.
- *
- * @param ioex I/O expander port number
- * @param pin Pin number
- * @param level Pointer to get pin level
- *
- * @return EC_SUCCESS, or EC_ERROR_* on error.
- */
-int pca9675_get_pin(int ioex, uint16_t pin, bool *level);
-
-/*
- * Update pin levels. This function has no effect if the pin is
- * configured as input.
- *
- * @param ioex I/O expander port number
- * @param setpins Pins to be set
- * @param clearpins Pins to be cleared
- *
- * @return EC_SUCCESS, or EC_ERROR_* on error.
- */
-int pca9675_update_pins(int ioex, uint16_t setpins, uint16_t clearpins);
-
-/*
- * Initialize the PCA9675 to power up state
- *
- * @param ioex I/O expander port number
- *
- * @return EC_SUCCESS, or EC_ERROR_* on error.
- */
-int pca9675_init(int ioex);
+extern const struct ioexpander_drv pca9675_ioexpander_drv;
#endif /* __CROS_EC_IOEXPANDER_PCA9675_H */