summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVijay Hiremath <vijay.p.hiremath@intel.com>2021-04-26 17:42:39 -0700
committerCommit Bot <commit-bot@chromium.org>2021-05-05 19:18:09 +0000
commit45cdc0f7acd939efc686b4e600b32445f1e017f3 (patch)
tree2e2639586a313b38ad5e9d2a55604861a506bf00
parente96d9283e51c1fc105e1cc2b7d6757105699baf3 (diff)
downloadchrome-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.mk1
-rw-r--r--driver/ioexpander/ccgxxf.c130
-rw-r--r--driver/tcpm/ccgxxf.h44
-rw-r--r--include/config.h3
-rw-r--r--util/config_allowed.txt1
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