diff options
author | Vijay Hiremath <vijay.p.hiremath@intel.com> | 2021-04-26 17:42:39 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-05-05 19:18:09 +0000 |
commit | 45cdc0f7acd939efc686b4e600b32445f1e017f3 (patch) | |
tree | 2e2639586a313b38ad5e9d2a55604861a506bf00 | |
parent | e96d9283e51c1fc105e1cc2b7d6757105699baf3 (diff) | |
download | chrome-ec-45cdc0f7acd939efc686b4e600b32445f1e017f3.tar.gz |
I/O Expander: Add CCG6XX driver
Cypress CCGXXF PD has built-in I/O Expander, added driver to enable
GPIO functionality.
BUG=none
BRANCH=none
TEST=Tested on ADLRVP, ioexget & ioexset works as expected
Change-Id: I8503178703ad166ac77e96d1990133c88169d23a
Signed-off-by: Vijay Hiremath <vijay.p.hiremath@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2853143
Tested-by: Svyatoslav Paliy <svpaliy@gmail.com>
Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
-rw-r--r-- | driver/build.mk | 1 | ||||
-rw-r--r-- | driver/ioexpander/ccgxxf.c | 130 | ||||
-rw-r--r-- | driver/tcpm/ccgxxf.h | 44 | ||||
-rw-r--r-- | include/config.h | 3 | ||||
-rw-r--r-- | util/config_allowed.txt | 1 |
5 files changed, 179 insertions, 0 deletions
diff --git a/driver/build.mk b/driver/build.mk index a5434c7357..53f6c0cdb4 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -78,6 +78,7 @@ driver-$(CONFIG_CHARGER_SM5803)+=charger/sm5803.o include $(_driver_cur_dir)fingerprint/build.mk # I/O expander +driver-$(CONFIG_IO_EXPANDER_CCGXXF)+=ioexpander/ccgxxf.o driver-$(CONFIG_IO_EXPANDER_IT8801)+=ioexpander/it8801.o driver-$(CONFIG_IO_EXPANDER_NCT38XX)+=ioexpander/ioexpander_nct38xx.o driver-$(CONFIG_IO_EXPANDER_PCA9534)+=ioexpander/pca9534.o diff --git a/driver/ioexpander/ccgxxf.c b/driver/ioexpander/ccgxxf.c new file mode 100644 index 0000000000..afaa6820d5 --- /dev/null +++ b/driver/ioexpander/ccgxxf.c @@ -0,0 +1,130 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Cypress CCGXXF I/O Port expander (built inside PD chip) driver source + */ + +#include "i2c.h" +#include "ioexpander.h" + +/* Add after all include files */ +#include "ccgxxf.h" + +static inline int ccgxxf_read8(int ioex, int reg, int *data) +{ + return i2c_read8(ioex_config[ioex].i2c_host_port, + ioex_config[ioex].i2c_addr_flags, reg, data); +} + +static inline int ccgxxf_update8(int ioex, int reg, uint8_t mask, + enum mask_update_action action) +{ + return i2c_update8(ioex_config[ioex].i2c_host_port, + ioex_config[ioex].i2c_addr_flags, reg, mask, action); +} + +static inline int ccgxxf_write16(int ioex, uint16_t reg, uint16_t data) +{ + return i2c_write16(ioex_config[ioex].i2c_host_port, + ioex_config[ioex].i2c_addr_flags, reg, data); +} + +static int ccgxxf_get_level(int ioex, int port, int mask, int *val) +{ + int rv; + + rv = ccgxxf_read8(ioex, CCGXXF_REG_GPIO_STATUS(port), val); + if (!rv) + *val = !!(*val & mask); + + return rv; +} + +static int ccgxxf_set_level(int ioex, int port, int mask, int val) +{ + return ccgxxf_update8(ioex, CCGXXF_REG_GPIO_CONTROL(port), mask, val); +} + +/* + * Following type of pins are supported + * - Output pins are supported with open-drain & pull-up + * - Input pins are supported with pull-up & pull-down + * - Analog pins + * + * TODO: Add support for 1.8V level GPIOs, after implementing it in the + * CCGXXF firmware. + */ +static int ccgxxf_set_flags_by_mask(int ioex, int port, int mask, int flags) +{ + uint16_t pin_mode; + int rv; + + if (flags & GPIO_OUTPUT) { + if (flags & GPIO_OPEN_DRAIN) { + if (flags & GPIO_PULL_UP) + pin_mode = CCGXXF_GPIO_MODE_RES_UP; + else + pin_mode = CCGXXF_GPIO_MODE_OD_LOW; + } else { + pin_mode = CCGXXF_GPIO_MODE_STRONG; + } + } else if (flags & GPIO_INPUT) { + if (flags & GPIO_PULL_UP) { + pin_mode = CCGXXF_GPIO_MODE_RES_UP; + flags |= GPIO_HIGH; + } else if (flags & GPIO_PULL_DOWN) { + pin_mode = CCGXXF_GPIO_MODE_RES_DWN; + flags |= GPIO_LOW; + } else { + pin_mode = CCGXXF_GPIO_MODE_HIZ_DIGITAL; + } + } else if (flags & GPIO_ANALOG) { + pin_mode = CCGXXF_GPIO_MODE_HIZ_ANALOG; + } else { + return EC_ERROR_INVAL; + } + + pin_mode = port | (pin_mode << CCGXXF_GPIO_PIN_MODE_SHIFT) | + (mask << CCGXXF_GPIO_PIN_MASK_SHIFT); + + /* + * Before setting the GPIO mode, initilaize the pins to default value + * to avoid spike on pins. + */ + if (flags & (GPIO_HIGH | GPIO_LOW)) { + rv = ccgxxf_set_level(ioex, port, mask, + flags & GPIO_HIGH ? 1 : 0); + if (rv) + return rv; + } + + return ccgxxf_write16(ioex, CCGXXF_REG_GPIO_MODE, pin_mode); +} + +static int ccgxxf_get_flags_by_mask(int ioex, int port, int mask, int *flags) +{ + /* TODO: Add it after implementing in the CCGXXF firmware. */ + return EC_SUCCESS; +} + +static int ccgxxf_enable_interrupt(int ioex, int port, int mask, int enable) +{ + /* CCGXXF doesn't have interrupt capability on I/O expnader pins */ + return EC_ERROR_UNIMPLEMENTED; +} + +int ccgxxf_init(int ioex) +{ + /* TCPC init of CCGXXF should handle initialization */ + return EC_SUCCESS; +} + +const struct ioexpander_drv ccgxxf_ioexpander_drv = { + .init = &ccgxxf_init, + .get_level = &ccgxxf_get_level, + .set_level = &ccgxxf_set_level, + .get_flags_by_mask = &ccgxxf_get_flags_by_mask, + .set_flags_by_mask = &ccgxxf_set_flags_by_mask, + .enable_interrupt = &ccgxxf_enable_interrupt, +}; diff --git a/driver/tcpm/ccgxxf.h b/driver/tcpm/ccgxxf.h index 6efab51757..8868e9174c 100644 --- a/driver/tcpm/ccgxxf.h +++ b/driver/tcpm/ccgxxf.h @@ -14,4 +14,48 @@ #define CCGXXF_I2C_ADDR2_FLAGS 0x40 #define CCGXXF_I2C_ADDR3_FLAGS 0x42 +/* CCGXXF built in I/O expander definitions */ +#ifdef CONFIG_IO_EXPANDER_CCGXXF + +/* CCGXXF I/O ports that can be referenced in gpio.inc */ +enum ccgxxf_io_ports { + CCGXXF_PORT_0, + CCGXXF_PORT_1, + CCGXXF_PORT_2, + CCGXXF_PORT_3 +}; + +/* CCGXXF I/O pins that can be referenced in gpio.inc */ +enum ccgxxf_io_pins { + CCGXXF_IO_0, + CCGXXF_IO_1, + CCGXXF_IO_2, + CCGXXF_IO_3, + CCGXXF_IO_4, + CCGXXF_IO_5, + CCGXXF_IO_6, + CCGXXF_IO_7 +}; + +#define CCGXXF_REG_GPIO_CONTROL(port) ((port) + 0x80) +#define CCGXXF_REG_GPIO_STATUS(port) ((port) + 0x84) + +#define CCGXXF_REG_GPIO_MODE 0x88 +#define CCGXXF_GPIO_PIN_MASK_SHIFT 8 +#define CCGXXF_GPIO_PIN_MODE_SHIFT 2 +enum ccgxxf_gpio_mode { + CCGXXF_GPIO_MODE_HIZ_ANALOG, + CCGXXF_GPIO_MODE_HIZ_DIGITAL, + CCGXXF_GPIO_MODE_RES_UP, + CCGXXF_GPIO_MODE_RES_DWN, + CCGXXF_GPIO_MODE_OD_LOW, + CCGXXF_GPIO_MODE_OD_HIGH, + CCGXXF_GPIO_MODE_STRONG, + CCGXXF_GPIO_MODE_RES_UPDOWN +}; + +extern const struct ioexpander_drv ccgxxf_ioexpander_drv; + +#endif /* CONFIG_IO_EXPANDER_CCGXXF */ + #endif /* __CROS_EC_DRIVER_TCPM_CCGXXF_H */ diff --git a/include/config.h b/include/config.h index b6f48c741a..5c360f6a99 100644 --- a/include/config.h +++ b/include/config.h @@ -2570,6 +2570,9 @@ /******************************************************************************/ +/* Support CCGXXF I/O expander built inside PD chip */ +#undef CONFIG_IO_EXPANDER_CCGXXF + /* Support IT8801 I/O expander. */ #undef CONFIG_IO_EXPANDER_IT8801 diff --git a/util/config_allowed.txt b/util/config_allowed.txt index 060cb8f27f..58ef95aa5c 100644 --- a/util/config_allowed.txt +++ b/util/config_allowed.txt @@ -570,6 +570,7 @@ CONFIG_INTEL_RVP_MECC_VERSION_0_9 CONFIG_INTEL_RVP_MECC_VERSION_1_0 CONFIG_INTERNAL_STORAGE CONFIG_IO_EXPANDER +CONFIG_IO_EXPANDER_CCGXXF CONFIG_IO_EXPANDER_IT8801 CONFIG_IO_EXPANDER_IT8801_PWM CONFIG_IO_EXPANDER_NCT38XX |