summaryrefslogtreecommitdiff
path: root/driver/ioexpander
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2021-11-04 12:11:58 -0600
committerCommit Bot <commit-bot@chromium.org>2021-11-05 04:22:34 +0000
commit252457d4b21f46889eebad61d4c0a65331919cec (patch)
tree01856c4d31d710b20e85a74c8d7b5836e35c3b98 /driver/ioexpander
parent08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff)
downloadchrome-ec-252457d4b21f46889eebad61d4c0a65331919cec.tar.gz
In the interest of making long-term branch maintenance incur as little technical debt on us as possible, we should not maintain any files on the branch we are not actually using. This has the added effect of making it extremely clear when merging CLs from the main branch when changes have the possibility to affect us. The follow-on CL adds a convenience script to actually pull updates from the main branch and generate a CL for the update. BUG=b:204206272 BRANCH=ish TEST=make BOARD=arcada_ish && make BOARD=drallion_ish Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Tom Hughes <tomhughes@chromium.org>
Diffstat (limited to 'driver/ioexpander')
-rw-r--r--driver/ioexpander/ccgxxf.c145
-rw-r--r--driver/ioexpander/ioexpander_nct38xx.c470
-rw-r--r--driver/ioexpander/it8300.h106
-rw-r--r--driver/ioexpander/it8801.c683
-rw-r--r--driver/ioexpander/it8801.h126
-rw-r--r--driver/ioexpander/pca9534.c52
-rw-r--r--driver/ioexpander/pca9534.h59
-rw-r--r--driver/ioexpander/pca9555.h45
-rw-r--r--driver/ioexpander/pca9675.c127
-rw-r--r--driver/ioexpander/pca9675.h39
-rw-r--r--driver/ioexpander/pcal6408.c354
-rw-r--r--driver/ioexpander/pcal6408.h42
-rw-r--r--driver/ioexpander/tca64xxa.c226
-rw-r--r--driver/ioexpander/tca64xxa.h25
14 files changed, 0 insertions, 2499 deletions
diff --git a/driver/ioexpander/ccgxxf.c b/driver/ioexpander/ccgxxf.c
deleted file mode 100644
index ac079d7b2f..0000000000
--- a/driver/ioexpander/ccgxxf.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/* 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 "console.h"
-#include "i2c.h"
-#include "ioexpander.h"
-
-/* Add after all include files */
-#include "ccgxxf.h"
-
-#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args)
-
-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
- * - 1.8V level GPIOs are supported per port and outputs can only be
- * open-drain pins
- */
-static int ccgxxf_set_flags_by_mask(int ioex, int port, int mask, int flags)
-{
- uint16_t pin_mode;
- int rv;
-
- /* Push-pull output can't be configured for 1.8V level */
- if ((flags & GPIO_OUTPUT) && (flags & GPIO_SEL_1P8V) &&
- !(flags & GPIO_OPEN_DRAIN)) {
- CPRINTS("Invalid flags: ioex=%d, port=%d, mask=%d, flags=0x%x",
- ioex, port, mask, flags);
-
- return EC_ERROR_INVAL;
- }
-
- 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);
-
- /* Note: once set the 1.8V level affect whole GPIO port */
- if (flags & GPIO_SEL_1P8V)
- pin_mode |= CCGXXF_GPIO_1P8V_SEL;
-
- /*
- * 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/ioexpander/ioexpander_nct38xx.c b/driver/ioexpander/ioexpander_nct38xx.c
deleted file mode 100644
index 8c87a33d24..0000000000
--- a/driver/ioexpander/ioexpander_nct38xx.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-/* GPIO expander for Nuvoton NCT38XX. */
-
-#include "console.h"
-#include "gpio.h"
-#include "i2c.h"
-#include "ioexpander.h"
-#include "nct38xx.h"
-#include "tcpm/tcpci.h"
-
-#define CPRINTF(format, args...) cprintf(CC_GPIO, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args)
-
-/*
- * Store the GPIO_ALERT_MASK_0/1 and chip ID registers locally. In this way,
- * we don't have to read it via I2C transaction everytime.
- */
-struct nct38xx_chip_data {
- uint8_t int_mask[2];
- int chip_id;
-};
-
-static struct nct38xx_chip_data chip_data[CONFIG_IO_EXPANDER_PORT_COUNT] = {
- [0 ... (CONFIG_IO_EXPANDER_PORT_COUNT - 1)] = { {0, 0}, -1 }
-};
-
-static int nct38xx_ioex_check_is_valid(int ioex, int port, int mask)
-{
- if (chip_data[ioex].chip_id == NCT38XX_VARIANT_3808) {
- if (port == 1) {
- CPRINTF("Port 1 is not support in NCT3808\n");
- return EC_ERROR_INVAL;
- }
- if (mask & ~NCT38XXX_3808_VALID_GPIO_MASK) {
-
- CPRINTF("GPIO%02d is not support in NCT3808\n",
- __fls(mask));
- return EC_ERROR_INVAL;
- }
- }
-
- return EC_SUCCESS;
-}
-
-static int nct38xx_ioex_init(int ioex)
-{
- int rv, val;
- struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
-
- /*
- * Check the NCT38xx part number in the register DEVICE_ID[4:2]:
- * 000: NCT3807
- * 010: NCT3808
- */
- rv = i2c_read8(ioex_p->i2c_host_port, ioex_p->i2c_addr_flags,
- TCPC_REG_BCD_DEV, &val);
-
- if (rv != EC_SUCCESS) {
- CPRINTF("Failed to read NCT38XX DEV ID for IOexpander %d\n",
- ioex);
- return rv;
- }
-
- chip_data[ioex].chip_id = ((uint8_t)val & NCT38XX_VARIANT_MASK) >> 2;
-
- /*
- * NCT38XX uses the Vendor Define bit in the ALERT event to indicate
- * that an IOEX IO's interrupt is triggered.
- * Normally, The ALERT MASK for Vendor Define event should be set by
- * the NCT38XX TCPCI driver's init function.
- * However, it should be also set here if we want to test the interrupt
- * function of IOEX when the NCT38XX TCPCI driver is not included.
- */
- if (!IS_ENABLED(CONFIG_USB_PD_TCPM_NCT38XX)) {
- rv = i2c_write16(ioex_p->i2c_host_port,
- ioex_p->i2c_addr_flags, TCPC_REG_ALERT_MASK,
- TCPC_REG_ALERT_VENDOR_DEF);
- if (rv != EC_SUCCESS)
- return rv;
- }
- return EC_SUCCESS;
-}
-
-static int nct38xx_ioex_get_level(int ioex, int port, int mask, int *val)
-{
- int rv, reg;
-
- rv = nct38xx_ioex_check_is_valid(ioex, port, mask);
- if (rv != EC_SUCCESS)
- return rv;
-
- reg = NCT38XX_REG_GPIO_DATA_IN(port);
- rv = i2c_read8(ioex_config[ioex].i2c_host_port,
- ioex_config[ioex].i2c_addr_flags, reg, val);
- if (rv != EC_SUCCESS)
- return rv;
-
- *val = !!(*val & mask);
-
- return EC_SUCCESS;
-}
-
-static int nct38xx_ioex_set_level(int ioex, int port, int mask, int value)
-{
- int rv, reg, val;
-
- rv = nct38xx_ioex_check_is_valid(ioex, port, mask);
- if (rv != EC_SUCCESS)
- return rv;
-
- reg = NCT38XX_REG_GPIO_DATA_OUT(port);
-
- rv = i2c_read8(ioex_config[ioex].i2c_host_port,
- ioex_config[ioex].i2c_addr_flags, reg, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (value)
- val |= mask;
- else
- val &= ~mask;
-
- return i2c_write8(ioex_config[ioex].i2c_host_port,
- ioex_config[ioex].i2c_addr_flags, reg, val);
-}
-
-static int nct38xx_ioex_get_flags(int ioex, int port, int mask, int *flags)
-{
- int rv, reg, val, i2c_port, i2c_addr;
- struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
-
- i2c_port = ioex_p->i2c_host_port;
- i2c_addr = ioex_p->i2c_addr_flags;
-
- rv = nct38xx_ioex_check_is_valid(ioex, port, mask);
- if (rv != EC_SUCCESS)
- return rv;
-
- reg = NCT38XX_REG_GPIO_DIR(port);
- rv = i2c_read8(i2c_port, i2c_addr, reg, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (val & mask)
- *flags |= GPIO_OUTPUT;
- else
- *flags |= GPIO_INPUT;
-
- reg = NCT38XX_REG_GPIO_DATA_IN(port);
- rv = i2c_read8(i2c_port, i2c_addr, reg, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (val & mask)
- *flags |= GPIO_HIGH;
- else
- *flags |= GPIO_LOW;
-
- reg = NCT38XX_REG_GPIO_OD_SEL(port);
- rv = i2c_read8(i2c_port, i2c_addr, reg, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (val & mask)
- *flags |= GPIO_OPEN_DRAIN;
-
- return EC_SUCCESS;
-}
-
-static int nct38xx_ioex_sel_int_type(int i2c_port, int i2c_addr, int port,
- int mask, int flags)
-{
- int rv;
- int reg_rising, reg_falling;
- int rising, falling;
-
- reg_rising = NCT38XX_REG_GPIO_ALERT_RISE(port);
- rv = i2c_read8(i2c_port, i2c_addr, reg_rising, &rising);
- if (rv != EC_SUCCESS)
- return rv;
-
- reg_falling = NCT38XX_REG_GPIO_ALERT_FALL(port);
- rv = i2c_read8(i2c_port, i2c_addr, reg_falling, &falling);
- if (rv != EC_SUCCESS)
- return rv;
-
- /* Handle interrupt for level trigger */
- if ((flags & GPIO_INT_F_HIGH) || (flags & GPIO_INT_F_LOW)) {
- int reg_level, level;
-
- reg_level = NCT38XX_REG_GPIO_ALERT_LEVEL(port);
- rv = i2c_read8(i2c_port, i2c_addr, reg_level, &level);
- if (rv != EC_SUCCESS)
- return rv;
- /*
- * For "level" triggered interrupt, the related bit in
- * ALERT_RISE and ALERT_FALL registers must be 0
- */
- rising &= ~mask;
- falling &= ~mask;
- if (flags & GPIO_INT_F_HIGH)
- level |= mask;
- else
- level &= ~mask;
-
- rv = i2c_write8(i2c_port, i2c_addr, reg_rising, rising);
- if (rv != EC_SUCCESS)
- return rv;
- rv = i2c_write8(i2c_port, i2c_addr, reg_falling, falling);
- if (rv != EC_SUCCESS)
- return rv;
- rv = i2c_write8(i2c_port, i2c_addr, reg_level, level);
- if (rv != EC_SUCCESS)
- return rv;
- } else if ((flags & GPIO_INT_F_RISING) ||
- (flags & GPIO_INT_F_FALLING)) {
- if (flags & GPIO_INT_F_RISING)
- rising |= mask;
- else
- rising &= ~mask;
- if (flags & GPIO_INT_F_FALLING)
- falling |= mask;
- else
- falling &= ~mask;
- rv = i2c_write8(i2c_port, i2c_addr, reg_rising, rising);
- if (rv != EC_SUCCESS)
- return rv;
- rv = i2c_write8(i2c_port, i2c_addr, reg_falling, falling);
- if (rv != EC_SUCCESS)
- return rv;
- }
- return EC_SUCCESS;
-}
-
-static int nct38xx_ioex_set_flags_by_mask(int ioex, int port, int mask,
- int flags)
-{
- int rv, reg, val, i2c_port, i2c_addr;
- struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
-
- i2c_port = ioex_p->i2c_host_port;
- i2c_addr = ioex_p->i2c_addr_flags;
-
- rv = nct38xx_ioex_check_is_valid(ioex, port, mask);
- if (rv != EC_SUCCESS)
- return rv;
-
- /*
- * GPIO port 0 muxs with alternative function. Disable the alternative
- * function before setting flags.
- */
- if (port == 0) {
- /* GPIO03 in NCT3807 is not muxed with other function. */
- if (!(chip_data[ioex].chip_id ==
- NCT38XX_VARIANT_3807 && mask & 0x08)) {
- reg = NCT38XX_REG_MUX_CONTROL;
- rv = i2c_read8(i2c_port, i2c_addr, reg, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- val = (val | mask);
- rv = i2c_write8(i2c_port, i2c_addr, reg, val);
- if (rv != EC_SUCCESS)
- return rv;
- }
- }
-
- val = flags & ~NCT38XX_SUPPORT_GPIO_FLAGS;
- if (val) {
- CPRINTF("Flag 0x%08x is not supported\n", val);
- return EC_ERROR_INVAL;
- }
-
- /* Select open drain 0:push-pull 1:open-drain */
- reg = NCT38XX_REG_GPIO_OD_SEL(port);
- rv = i2c_read8(i2c_port, i2c_addr, reg, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (flags & GPIO_OPEN_DRAIN)
- val |= mask;
- else
- val &= ~mask;
- rv = i2c_write8(i2c_port, i2c_addr, reg, val);
- if (rv != EC_SUCCESS)
- return rv;
-
- nct38xx_ioex_sel_int_type(i2c_port, i2c_addr, port, mask, flags);
-
- /* Configure the output level */
- reg = NCT38XX_REG_GPIO_DATA_OUT(port);
- rv = i2c_read8(i2c_port, i2c_addr, reg, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (flags & GPIO_HIGH)
- val |= mask;
- else if (flags & GPIO_LOW)
- val &= ~mask;
- rv = i2c_write8(i2c_port, i2c_addr, reg, val);
- if (rv != EC_SUCCESS)
- return rv;
-
- reg = NCT38XX_REG_GPIO_DIR(port);
- rv = i2c_read8(i2c_port, i2c_addr, reg, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (flags & GPIO_OUTPUT)
- val |= mask;
- else
- val &= ~mask;
-
- return i2c_write8(i2c_port, i2c_addr, reg, val);
-}
-
-/*
- * The following functions are used for IO's interrupt support.
- *
- * please note that if the system needs to use an IO on NCT38XX to support
- * the interrupt, the following two consideration should be taken into account.
- * 1. Interrupt latency:
- * Because it requires to access the registers of NCT38XX via I2C
- * transaction to know the interrupt event, there is some added latency
- * for the interrupt handling. If the interrupt requires short latency,
- * we do not recommend to connect such a signal to the NCT38XX.
- *
- * 2. Shared ALERT pin:
- * Because the ALERT pin is shared also with the TCPC ALERT, we do not
- * recommend to connect any signal that may generate a high rate of
- * interrupts so it will not interfere with the normal work of the
- * TCPC.
- */
-static int nct38xx_ioex_enable_interrupt(int ioex, int port, int mask,
- int enable)
-{
- int rv, reg, val;
- struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
-
- rv = nct38xx_ioex_check_is_valid(ioex, port, mask);
- if (rv != EC_SUCCESS)
- return rv;
-
- /* Clear the pending bit */
- reg = NCT38XX_REG_GPIO_ALERT_STAT(port);
- rv = i2c_read8(ioex_p->i2c_host_port, ioex_p->i2c_addr_flags,
- reg, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- val |= mask;
- rv = i2c_write8(ioex_p->i2c_host_port, ioex_p->i2c_addr_flags,
- reg, val);
- if (rv != EC_SUCCESS)
- return rv;
-
- reg = NCT38XX_REG_GPIO_ALERT_MASK(port);
- if (enable) {
- /* Enable the alert mask */
- chip_data[ioex].int_mask[port] |= mask;
- val = chip_data[ioex].int_mask[port];
- } else {
- /* Disable the alert mask */
- chip_data[ioex].int_mask[port] &= ~mask;
- val = chip_data[ioex].int_mask[port];
- }
-
- return i2c_write8(ioex_p->i2c_host_port, ioex_p->i2c_addr_flags,
- reg, val);
-}
-
-int nct38xx_ioex_event_handler(int ioex)
-{
- int reg, int_status, int_mask;
- int i, j, total_port;
- const struct ioex_info *g;
- struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
- int rv = 0;
-
- int_mask = chip_data[ioex].int_mask[0] | (
- chip_data[ioex].int_mask[1] << 8);
- reg = NCT38XX_REG_GPIO_ALERT_STAT(0);
- /*
- * Read ALERT_STAT_0 and ALERT_STAT_1 register in a single I2C
- * transaction to increase efficiency
- */
- rv = i2c_read16(ioex_p->i2c_host_port, ioex_p->i2c_addr_flags,
- reg, &int_status);
- if (rv != EC_SUCCESS)
- return rv;
-
- int_status = int_status & int_mask;
- /*
- * Clear the changed status bits in ALERT_STAT_0 and ALERT_STAT_1
- * register in a single I2C transaction to increase efficiency
- */
- rv = i2c_write16(ioex_p->i2c_host_port, ioex_p->i2c_addr_flags,
- reg, int_status);
- if (rv != EC_SUCCESS)
- return rv;
-
- /* For NCT3808, only check one port */
- total_port = (chip_data[ioex].chip_id == NCT38XX_VARIANT_3808) ?
- NCT38XX_NCT3808_MAX_IO_PORT :
- NCT38XX_NCT3807_MAX_IO_PORT;
- for (i = 0; i < total_port; i++) {
- uint8_t pending;
-
- pending = int_status >> (i * 8);
-
- if (!pending)
- continue;
-
- for (j = 0, g = ioex_list; j < ioex_ih_count; j++, g++) {
-
- if (ioex == g->ioex && i == g->port &&
- (pending & g->mask)) {
- ioex_irq_handlers[j](j + IOEX_SIGNAL_START);
- pending &= ~g->mask;
- if (!pending)
- break;
- }
-
- }
- }
-
- return EC_SUCCESS;
-}
-
-/*
- * Normally, the ALERT MASK for Vendor Define event should be checked by
- * the NCT38XX TCPCI driver's tcpc_alert function.
- * However, it should be checked here if we want to test the interrupt
- * function of IOEX when the NCT38XX TCPCI driver is not included.
- */
-void nct38xx_ioex_handle_alert(int ioex)
-{
- int rv, status;
- struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
-
- rv = i2c_read16(ioex_p->i2c_host_port, ioex_p->i2c_addr_flags,
- TCPC_REG_ALERT, &status);
- if (rv != EC_SUCCESS)
- CPRINTF("fail to read ALERT register\n");
-
- if (status & TCPC_REG_ALERT_VENDOR_DEF) {
- rv = i2c_write16(ioex_p->i2c_host_port,
- ioex_p->i2c_addr_flags, TCPC_REG_ALERT,
- TCPC_REG_ALERT_VENDOR_DEF);
- if (rv != EC_SUCCESS) {
- CPRINTF("Fail to clear Vendor Define mask\n");
- return;
- }
- nct38xx_ioex_event_handler(ioex);
- }
-}
-
-const struct ioexpander_drv nct38xx_ioexpander_drv = {
- .init = &nct38xx_ioex_init,
- .get_level = &nct38xx_ioex_get_level,
- .set_level = &nct38xx_ioex_set_level,
- .get_flags_by_mask = &nct38xx_ioex_get_flags,
- .set_flags_by_mask = &nct38xx_ioex_set_flags_by_mask,
- .enable_interrupt = &nct38xx_ioex_enable_interrupt,
-};
diff --git a/driver/ioexpander/it8300.h b/driver/ioexpander/it8300.h
deleted file mode 100644
index 2b47e7f3e1..0000000000
--- a/driver/ioexpander/it8300.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* Copyright 2018 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.
- *
- * ITE IT8300 I/O Port expander driver header
- */
-
-#ifndef __CROS_EC_IOEXPANDER_IT8300_H
-#define __CROS_EC_IOEXPANDER_IT8300_H
-
-#include "i2c.h"
-
-/* Gather Interrupt Status Register */
-#define IT8300_GISR 0x0
-
-/* Interrupt Status Registers */
-#define IT8300_ISR_A 0x6
-#define IT8300_ISR_B 0x7
-#define IT8300_ISR_C 0x28
-#define IT8300_ISR_D 0x2E
-#define IT8300_ISR_E 0x2F
-
-/* Port Data Register Groups */
-#define IT8300_PDGR_A 0x1
-#define IT8300_PDGR_B 0x2
-#define IT8300_PDGR_C 0x3
-#define IT8300_PDGR_D 0x4
-#define IT8300_PDGR_E 0x5
-
-/* GPIO Port Control n Registers */
-#define IT8300_GPCR_A0 0x10
-#define IT8300_GPCR_A1 0x11
-#define IT8300_GPCR_A2 0x12
-#define IT8300_GPCR_A3 0x13
-#define IT8300_GPCR_A4 0x14
-#define IT8300_GPCR_A5 0x15
-#define IT8300_GPCR_A6 0x16
-#define IT8300_GPCR_A7 0x17
-
-#define IT8300_GPCR_B0 0x18
-#define IT8300_GPCR_B1 0x19
-#define IT8300_GPCR_B2 0x1A
-#define IT8300_GPCR_B3 0x1B
-#define IT8300_GPCR_B4 0x1C
-#define IT8300_GPCR_B5 0x1D
-#define IT8300_GPCR_B6 0x1E
-
-#define IT8300_GPCR_C0 0x20
-#define IT8300_GPCR_C1 0x21
-#define IT8300_GPCR_C2 0x22
-#define IT8300_GPCR_C3 0x23
-#define IT8300_GPCR_C4 0x24
-#define IT8300_GPCR_C5 0x25
-#define IT8300_GPCR_C6 0x26
-
-#define IT8300_GPCR_D0 0x08
-#define IT8300_GPCR_D1 0x09
-#define IT8300_GPCR_D2 0x0A
-#define IT8300_GPCR_D3 0x0B
-#define IT8300_GPCR_D4 0x0C
-#define IT8300_GPCR_D5 0x0D
-
-#define IT8300_GPCR_E0 0x32
-
-#define IT8300_GPCR_E2 0x34
-#define IT8300_GPCR_E3 0x35
-#define IT8300_GPCR_E4 0x36
-#define IT8300_GPCR_E5 0x37
-#define IT8300_GPCR_E6 0x38
-
-#define IT8300_GPCR_GPI_MODE BIT(7)
-#define IT8300_GPCR_GP0_MODE BIT(6)
-#define IT8300_GPCR_PULL_UP_EN BIT(2)
-#define IT8300_GPCR_PULL_DN_EN BIT(1)
-
-/* EXGPIO Clear Alert */
-#define IT8300_ECA 0x30
-
-/* EXGPIO Alert Enable */
-#define IT8300_EAE 0x31
-
-/* Port Data Mirror Registers */
-#define IT8300_PDMRA_A 0x29
-#define IT8300_PDMRA_B 0x2A
-#define IT8300_PDMRA_C 0x2B
-#define IT8300_PDMRA_D 0x2C
-#define IT8300_PDMRA_E 0x2D
-
-/* Output Open-Drain Enable Registers */
-#define IT8300_OODER_A 0x39
-#define IT8300_OODER_B 0x3A
-#define IT8300_OODER_C 0x3B
-#define IT8300_OODER_D 0x3C
-#define IT8300_OODER_E 0x3D
-
-/* IT83200 Port GPIOs */
-#define IT8300_GPX_0 BIT(0)
-#define IT8300_GPX_1 BIT(1)
-#define IT8300_GPX_2 BIT(2)
-#define IT8300_GPX_3 BIT(3)
-#define IT8300_GPX_4 BIT(4)
-#define IT8300_GPX_5 BIT(5)
-#define IT8300_GPX_6 BIT(6)
-#define IT8300_GPX_7 BIT(7)
-
-#endif /* __CROS_EC_IOEXPANDER_IT8300_H */
diff --git a/driver/ioexpander/it8801.c b/driver/ioexpander/it8801.c
deleted file mode 100644
index 96070074fb..0000000000
--- a/driver/ioexpander/it8801.c
+++ /dev/null
@@ -1,683 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#include "common.h"
-#include "console.h"
-#include "gpio.h"
-#include "hooks.h"
-#include "i2c.h"
-#include "ioexpander.h"
-#include "it8801.h"
-#include "keyboard_raw.h"
-#include "keyboard_scan.h"
-#include "registers.h"
-#include "task.h"
-#include "util.h"
-#include "keyboard_backlight.h"
-
-#define CPRINTS(format, args...) cprints(CC_KEYSCAN, format, ## args)
-
-static int it8801_ioex_set_level(int ioex, int port, int mask, int value);
-static void it8801_ioex_event_handler(void);
-DECLARE_DEFERRED(it8801_ioex_event_handler);
-
-static int it8801_read(int reg, int *data)
-{
- return i2c_read8(IT8801_KEYBOARD_PWM_I2C_PORT,
- IT8801_KEYBOARD_PWM_I2C_ADDR_FLAGS, reg, data);
-}
-
-__maybe_unused static int it8801_write(int reg, int data)
-{
- return i2c_write8(IT8801_KEYBOARD_PWM_I2C_PORT,
- IT8801_KEYBOARD_PWM_I2C_ADDR_FLAGS, reg, data);
-}
-
-struct it8801_vendor_id_t {
- uint8_t chip_id;
- uint8_t reg;
-};
-
-static const struct it8801_vendor_id_t it8801_vendor_id_verify[] = {
- { 0x12, IT8801_REG_HBVIDR},
- { 0x83, IT8801_REG_LBVIDR},
-};
-
-static int it8801_check_vendor_id(void)
-{
- int i, ret, val;
-
- /* Verify vendor ID registers(16-bits). */
- for (i = 0; i < ARRAY_SIZE(it8801_vendor_id_verify); i++) {
- ret = it8801_read(it8801_vendor_id_verify[i].reg, &val);
-
- if (ret != EC_SUCCESS)
- return ret;
-
- if (val != it8801_vendor_id_verify[i].chip_id)
- return EC_ERROR_UNKNOWN;
- }
-
- return EC_SUCCESS;
-}
-
-/*
- * Keyboard and GPIO interrupts are muxed inside the IT8801 chip.
- * Interrupt enable register controls the individual pins from
- * triggering this global interrupt hence it is okay that this
- * pin is enabled all the time.
- */
-static void it8801_muxed_kbd_gpio_intr_enable(void)
-{
- static bool intr_enabled;
-
- /*
- * Allow enabling this pin either by Keyboard enable code or
- * IOEX init code whichever gets called first.
- */
- if (!intr_enabled) {
- gpio_clear_pending_interrupt(GPIO_IT8801_SMB_INT);
- gpio_enable_interrupt(GPIO_IT8801_SMB_INT);
- intr_enabled = true;
- }
-}
-
-#ifdef CONFIG_KEYBOARD_NOT_RAW
-void keyboard_raw_init(void)
-{
- int ret;
-
- /* Verify Vendor ID registers. */
- ret = it8801_check_vendor_id();
- if (ret) {
- CPRINTS("Failed to read IT8801 vendor id %x", ret);
- return;
- }
-
- /* KSO alternate function switching(KSO[21:20, 18]). */
- it8801_write(IT8801_REG_GPIO01_KSO18, IT8801_REG_MASK_GPIOAFS_FUNC2);
- it8801_write(IT8801_REG_GPIO22_KSO21, IT8801_REG_MASK_GPIOAFS_FUNC2);
- it8801_write(IT8801_REG_GPIO23_KSO20, IT8801_REG_MASK_GPIOAFS_FUNC2);
-
- /* Start with KEYBOARD_COLUMN_ALL, KSO[22:11, 6:0] output low. */
- it8801_write(IT8801_REG_KSOMCR, IT8801_REG_MASK_AKSOSC);
-
- if (IS_ENABLED(CONFIG_KEYBOARD_COL2_INVERTED)) {
- /*
- * Since most of the KSO pins can't drive up, we'll must use
- * a pin capable of being a GPIO instead and use the GPIO
- * feature to do the required inverted push pull.
- */
- it8801_write(IT8801_REG_GPIO23_KSO20, IT8801_REG_MASK_GPIODIR);
-
- /* Start with KEYBOARD_COLUMN_ALL, output high(so selected). */
- it8801_ioex_set_level(0, 2, IT8801_REG_GPIO23SOV, 1);
- }
-
- /* Keyboard scan in interrupt enable register */
- it8801_write(IT8801_REG_KSIIER, 0xff);
- /* Gather KSI interrupt enable */
- it8801_write(IT8801_REG_GIECR, IT8801_REG_MASK_GKSIIE);
- /* Alert response enable */
- it8801_write(IT8801_REG_SMBCR, IT8801_REG_MASK_ARE);
-
- keyboard_raw_enable_interrupt(0);
-}
-
-void keyboard_raw_task_start(void)
-{
- keyboard_raw_enable_interrupt(1);
-}
-
-__overridable const uint8_t it8801_kso_mapping[] = {
- 0, 1, 20, 3, 4, 5, 6, 17, 18, 16, 15, 11, 12,
-#ifdef CONFIG_KEYBOARD_KEYPAD
- 13, 14
-#endif
-};
-BUILD_ASSERT(ARRAY_SIZE(it8801_kso_mapping) == KEYBOARD_COLS_MAX);
-
-test_mockable void keyboard_raw_drive_column(int col)
-{
- int kso_val;
-
- /* Tri-state all outputs */
- if (col == KEYBOARD_COLUMN_NONE) {
- /* KSO[22:11, 6:0] output high */
- kso_val = IT8801_REG_MASK_KSOSDIC | IT8801_REG_MASK_AKSOSC;
-
- if (IS_ENABLED(CONFIG_KEYBOARD_COL2_INVERTED)) {
- /* Output low(so not selected). */
- it8801_ioex_set_level(0, 2, IT8801_REG_GPIO23SOV, 0);
- }
- }
- /* Assert all outputs */
- else if (col == KEYBOARD_COLUMN_ALL) {
- /* KSO[22:11, 6:0] output low */
- kso_val = IT8801_REG_MASK_AKSOSC;
-
- if (IS_ENABLED(CONFIG_KEYBOARD_COL2_INVERTED)) {
- /* Output high(so selected). */
- it8801_ioex_set_level(0, 2, IT8801_REG_GPIO23SOV, 1);
- }
- } else {
- /* To check if column is valid or not. */
- if (col >= KEYBOARD_COLS_MAX)
- return;
- /*
- * Selected KSO[20, 18:11, 6:3, 1:0] output low,
- * all others KSO output high.
- */
- kso_val = it8801_kso_mapping[col];
-
- if (IS_ENABLED(CONFIG_KEYBOARD_COL2_INVERTED)) {
- /* GPIO23 is inverted. */
- if (col == IT8801_REG_MASK_SELKSO2) {
- /* Output high(so selected). */
- it8801_ioex_set_level(0, 2,
- IT8801_REG_GPIO23SOV, 1);
- } else {
- /* Output low(so not selected). */
- it8801_ioex_set_level(0, 2,
- IT8801_REG_GPIO23SOV, 0);
- }
- }
- }
-
- it8801_write(IT8801_REG_KSOMCR, kso_val);
-}
-
-test_mockable int keyboard_raw_read_rows(void)
-{
- int data = 0;
- int ksieer = 0;
-
- it8801_read(IT8801_REG_KSIDR, &data);
-
- /* This register needs to write clear after reading data */
- it8801_read(IT8801_REG_KSIEER, &ksieer);
- it8801_write(IT8801_REG_KSIEER, ksieer);
-
- /* Bits are active-low, so invert returned levels */
- return (~data) & 0xff;
-}
-
-void keyboard_raw_enable_interrupt(int enable)
-{
- if (enable) {
- /* Clear pending iterrupts */
- it8801_write(IT8801_REG_KSIEER, 0xff);
-
- /* Enable muxed Keyboard & GPIO interrupt */
- it8801_muxed_kbd_gpio_intr_enable();
- }
-
- it8801_write(IT8801_REG_KSIIER, enable ? 0xff : 0x00);
-}
-#endif /* CONFIG_KEYBOARD_NOT_RAW */
-
-void io_expander_it8801_interrupt(enum gpio_signal signal)
-{
- hook_call_deferred(&it8801_ioex_event_handler_data, 0);
-}
-
-static int it8801_ioex_read(int ioex, int reg, int *data)
-{
- struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
-
- return i2c_read8(ioex_p->i2c_host_port, ioex_p->i2c_addr_flags,
- reg, data);
-}
-
-static int it8801_ioex_write(int ioex, int reg, int data)
-{
- struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
-
- return i2c_write8(ioex_p->i2c_host_port, ioex_p->i2c_addr_flags,
- reg, data);
-}
-
-static int it8801_ioex_update(int ioex, int reg, int data,
- enum mask_update_action action)
-{
- struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
-
- return i2c_update8(ioex_p->i2c_host_port, ioex_p->i2c_addr_flags,
- reg, data, action);
-}
-
-static const int it8801_valid_gpio_group[] = {
- IT8801_VALID_GPIO_G0_MASK,
- IT8801_VALID_GPIO_G1_MASK,
- IT8801_VALID_GPIO_G2_MASK,
-};
-
-/* Mutexes */
-static struct mutex ioex_mutex;
-
-static uint8_t it8801_gpio_sov[ARRAY_SIZE(it8801_valid_gpio_group)];
-
-/*
- * Initialize the general purpose I/O port(GPIO)
- */
-static int it8801_ioex_init(int ioex)
-{
- int ret, port, val = 0;
-
- /* Verify Vendor ID registers. */
- ret = it8801_check_vendor_id();
- if (ret) {
- CPRINTS("Failed to read IT8801 vendor id %x", ret);
- return ret;
- }
-
- /*
- * We will read the value of SOVR and write it to the
- * cache(it8801_gpio_sov[port]) to avoid causing cache
- * to reset when EC is reset.
- */
- for (port = 0; port < ARRAY_SIZE(it8801_valid_gpio_group); port++) {
- it8801_ioex_read(ioex, IT8801_REG_GPIO_SOVR(port), &val);
- it8801_gpio_sov[port] = val;
- }
-
- /* Enable muxed Keyboard & GPIO interrupt */
- it8801_muxed_kbd_gpio_intr_enable();
-
- return EC_SUCCESS;
-}
-
-static int ioex_check_is_not_valid(int port, int mask)
-{
- if (port >= ARRAY_SIZE(it8801_valid_gpio_group)) {
- CPRINTS("Port%d is not support in IT8801", port);
- return EC_ERROR_INVAL;
- }
-
- if (mask & ~it8801_valid_gpio_group[port]) {
- CPRINTS("GPIO%d-%d is not support in IT8801", port,
- __fls(mask & ~it8801_valid_gpio_group[port]));
- return EC_ERROR_INVAL;
- }
-
- return EC_SUCCESS;
-}
-
-static int it8801_ioex_get_level(int ioex, int port, int mask, int *val)
-{
- int rv;
-
- if (ioex_check_is_not_valid(port, mask))
- return EC_ERROR_INVAL;
-
- rv = it8801_ioex_read(ioex, IT8801_REG_GPIO_IPSR(port), val);
-
- *val = !!(*val & mask);
-
- return rv;
-}
-
-static int it8801_ioex_set_level(int ioex, int port, int mask, int value)
-{
- int rv = EC_SUCCESS;
-
- if (ioex_check_is_not_valid(port, mask))
- return EC_ERROR_INVAL;
-
- mutex_lock(&ioex_mutex);
- /*
- * The bit of output value in SOV is different than
- * the one we were about to set it to.
- */
- if (!!(it8801_gpio_sov[port] & mask) ^ value) {
- if (value)
- it8801_gpio_sov[port] |= mask;
- else
- it8801_gpio_sov[port] &= ~mask;
-
- rv = it8801_ioex_write(ioex, IT8801_REG_GPIO_SOVR(port),
- it8801_gpio_sov[port]);
- }
- mutex_unlock(&ioex_mutex);
-
- return rv;
-}
-
-static int it8801_ioex_get_flags_by_mask(int ioex, int port,
- int mask, int *flags)
-{
- int rv, val;
-
- if (ioex_check_is_not_valid(port, mask))
- return EC_ERROR_INVAL;
-
- rv = it8801_ioex_read(ioex, IT8801_REG_GPIO_CR(port, mask), &val);
- if (rv)
- return rv;
-
- *flags = 0;
-
- /* Get GPIO direction */
- *flags |= (val & IT8801_GPIODIR) ? GPIO_OUTPUT : GPIO_INPUT;
-
- /* Get GPIO type, 0:push-pull 1:open-drain */
- if (val & IT8801_GPIOIOT)
- *flags |= GPIO_OPEN_DRAIN;
-
- rv = it8801_ioex_read(ioex, IT8801_REG_GPIO_IPSR(port), &val);
- if (rv)
- return rv;
-
- /* Get GPIO output level */
- *flags |= (val & mask) ? GPIO_HIGH : GPIO_LOW;
-
- return EC_SUCCESS;
-}
-
-static int it8801_ioex_set_flags_by_mask(int ioex, int port,
- int mask, int flags)
-{
- int rv, val;
-
- if (ioex_check_is_not_valid(port, mask))
- return EC_ERROR_INVAL;
-
- if (flags & ~IT8801_SUPPORT_GPIO_FLAGS) {
- CPRINTS("Flag 0x%08x is not supported at port %d, mask %d",
- flags, port, mask);
- return EC_ERROR_INVAL;
- }
-
- /* GPIO alternate function switching(GPIO[00, 12:15, 20:23]). */
- rv = it8801_ioex_write(ioex, IT8801_REG_GPIO_CR(port, mask),
- IT8801_REG_MASK_GPIOAFS_FUNC1);
- if (rv)
- return rv;
-
- mutex_lock(&ioex_mutex);
- rv = it8801_ioex_read(ioex, IT8801_REG_GPIO_CR(port, mask), &val);
- if (rv)
- goto unlock_mutex;
-
- /* Select open drain 0:push-pull 1:open-drain */
- if (flags & GPIO_OPEN_DRAIN)
- val |= IT8801_GPIOIOT;
- else
- val &= ~IT8801_GPIOIOT;
-
- /* Select GPIO direction */
- if (flags & GPIO_OUTPUT) {
- /* Configure the output level */
- if (flags & GPIO_HIGH)
- it8801_gpio_sov[port] |= mask;
- else
- it8801_gpio_sov[port] &= ~mask;
-
- rv = it8801_ioex_write(ioex, IT8801_REG_GPIO_SOVR(port),
- it8801_gpio_sov[port]);
- if (rv)
- goto unlock_mutex;
-
- val |= IT8801_GPIODIR;
- } else {
- val &= ~IT8801_GPIODIR;
- }
-
- /* Set Interrupt Type */
- if (flags & GPIO_INT_RISING)
- val |= IT8801_GPIOIOT_INT_RISING;
- if (flags & GPIO_INT_FALLING)
- val |= IT8801_GPIOIOT_INT_FALLING;
-
- rv = it8801_ioex_write(ioex, IT8801_REG_GPIO_CR(port, mask), val);
-
-unlock_mutex:
- mutex_unlock(&ioex_mutex);
-
- return rv;
-}
-
-/* Enable the individual GPIO interrupt pins based on the board requirement. */
-static int it8801_ioex_enable_interrupt(int ioex, int port, int mask,
- int enable)
-{
- int rv;
-
- if (ioex_check_is_not_valid(port, mask))
- return EC_ERROR_INVAL;
-
- /* Clear pending interrupt */
- rv = it8801_ioex_update(ioex, IT8801_REG_GPIO_ISR(port),
- mask, MASK_SET);
- if (rv)
- return rv;
-
- return it8801_ioex_update(ioex, IT8801_REG_GPIO_IER(port),
- mask, enable ? MASK_SET : MASK_CLR);
-}
-
-static void it8801_ioex_irq(int ioex, int port)
-{
- int rv, data, i;
- const struct ioex_info *g;
-
- rv = it8801_ioex_read(ioex, IT8801_REG_GPIO_ISR(port), &data);
- if (rv || !data)
- return;
-
- /* Trigger the intended interrupt from the IOEX IRQ pins */
- for (i = 0, g = ioex_list; i < ioex_ih_count; i++, g++) {
- if (ioex == g->ioex && port == g->port && data & g->mask) {
- ioex_irq_handlers[i](i + IOEX_SIGNAL_START);
- data &= ~g->mask;
-
- /* Clear pending interrupt */
- it8801_ioex_update(ioex, IT8801_REG_GPIO_ISR(port),
- g->mask, MASK_SET);
-
- if (!data)
- break;
- }
- }
-}
-
-static void it8801_ioex_event_handler(void)
-{
- int data, i;
-
- /* Gather KSI interrupt status register */
- if (it8801_read(IT8801_REG_GISR, &data))
- return;
-
- /* Wake the keyboard scan task if KSI interrupts are triggered */
- if (IS_ENABLED(CONFIG_KEYBOARD_NOT_RAW) &&
- data & IT8801_REG_MASK_GISR_GKSIIS)
- task_wake(TASK_ID_KEYSCAN);
-
- /*
- * Trigger the GPIO callback functions if the GPIO interrupts are
- * triggered.
- */
- if (data & (IT8801_REG_MASK_GISR_GGPIOGXIS)) {
- for (i = 0; i < CONFIG_IO_EXPANDER_PORT_COUNT; i++) {
- if (ioex_config[i].drv == &it8801_ioexpander_drv) {
- /* Interrupt from GPIO port 0 is triggered */
- if (data & IT8801_REG_MASK_GISR_GGPIOG0IS)
- it8801_ioex_irq(i, 0);
- /* Interrupt from GPIO port 1 is triggered */
- if (data & IT8801_REG_MASK_GISR_GGPIOG1IS)
- it8801_ioex_irq(i, 1);
- /* Interrupt from GPIO port 2 is triggered */
- if (data & IT8801_REG_MASK_GISR_GGPIOG2IS)
- it8801_ioex_irq(i, 2);
- }
- }
- }
-}
-
-const struct ioexpander_drv it8801_ioexpander_drv = {
- .init = &it8801_ioex_init,
- .get_level = &it8801_ioex_get_level,
- .set_level = &it8801_ioex_set_level,
- .get_flags_by_mask = &it8801_ioex_get_flags_by_mask,
- .set_flags_by_mask = &it8801_ioex_set_flags_by_mask,
- .enable_interrupt = &it8801_ioex_enable_interrupt,
-};
-
-static void dump_register(int reg)
-{
- int rv;
- int data;
-
- ccprintf("[%Xh] = ", reg);
-
- rv = it8801_read(reg, &data);
-
- if (!rv)
- ccprintf("0x%02x\n", data);
- else
- ccprintf("ERR (%d)\n", rv);
-}
-
-static int it8801_dump(int argc, char **argv)
-{
- dump_register(IT8801_REG_KSIIER);
- dump_register(IT8801_REG_KSIEER);
- dump_register(IT8801_REG_KSIDR);
- dump_register(IT8801_REG_KSOMCR);
-
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(it8801_dump, it8801_dump, "NULL",
- "Dumps IT8801 registers");
-
-#ifdef CONFIG_IO_EXPANDER_IT8801_PWM
-
-struct it8801_pwm_gpio_map {
- int port;
- int mask;
- int pushpull_en;
-};
-
-const static struct it8801_pwm_gpio_map it8801_pwm_gpio_map[] = {
- [1] = {.port = 1, .mask = BIT(2), .pushpull_en = BIT(0)},
- [2] = {.port = 1, .mask = BIT(3), .pushpull_en = BIT(1)},
- [3] = {.port = 1, .mask = BIT(4), .pushpull_en = BIT(2)},
- [4] = {.port = 1, .mask = BIT(5), .pushpull_en = BIT(3)},
- [7] = {.port = 2, .mask = BIT(0), .pushpull_en = BIT(4)},
- [8] = {.port = 2, .mask = BIT(3), .pushpull_en = BIT(5)},
- [9] = {.port = 2, .mask = BIT(2), .pushpull_en = BIT(6)},
-};
-
-void it8801_pwm_enable(enum pwm_channel ch, int enabled)
-{
- int port, mask, val, index;
-
- index = it8801_pwm_channels[ch].index;
- if (index < 0 || index >= ARRAY_SIZE(it8801_pwm_gpio_map))
- return;
- port = it8801_pwm_gpio_map[index].port;
- mask = it8801_pwm_gpio_map[index].mask;
- if (port == 0 && mask == 0)
- return;
-
- /*
- * PWM1~4,7: alt func 1
- * PWM8,9: alt func 2
- */
- if (it8801_pwm_channels[ch].index <= 7)
- it8801_write(IT8801_REG_GPIO_CR(port, mask),
- 0x1 << IT8801_GPIOAFS_SHIFT);
- else
- it8801_write(IT8801_REG_GPIO_CR(port, mask),
- 0x2 << IT8801_GPIOAFS_SHIFT);
-
- it8801_read(IT8801_REG_PWMMCR(it8801_pwm_channels[ch].index), &val);
- val &= (~IT8801_PWMMCR_MCR_MASK);
- if (enabled)
- val |= IT8801_PWMMCR_MCR_BLINKING;
- it8801_write(IT8801_REG_PWMMCR(it8801_pwm_channels[ch].index), val);
-
- /*
- * 1: enable push pull function
- */
- it8801_read(IT8801_REG_PWMODDSR, &val);
- val &= ~it8801_pwm_gpio_map[index].pushpull_en;
- if (enabled)
- val |= it8801_pwm_gpio_map[index].pushpull_en;
- it8801_write(IT8801_REG_PWMODDSR, val);
-
-}
-
-int it8801_pwm_get_enabled(enum pwm_channel ch)
-{
- int val;
-
- if (it8801_read(IT8801_REG_PWMMCR(it8801_pwm_channels[ch].index), &val))
- return 0;
- return (val & IT8801_PWMMCR_MCR_MASK) == IT8801_PWMMCR_MCR_BLINKING;
-}
-
-void it8801_pwm_set_raw_duty(enum pwm_channel ch, uint16_t duty)
-{
- duty = MIN(duty, 255);
- duty = MAX(duty, 0);
- it8801_write(IT8801_REG_PWMDCR(it8801_pwm_channels[ch].index), duty);
-}
-
-uint16_t it8801_pwm_get_raw_duty(enum pwm_channel ch)
-{
- int val;
-
- if (it8801_read(IT8801_REG_PWMDCR(it8801_pwm_channels[ch].index), &val))
- return 0;
- return val;
-}
-
-void it8801_pwm_set_duty(enum pwm_channel ch, int percent)
-{
- return it8801_pwm_set_raw_duty(ch, percent * 255 / 100);
-}
-
-int it8801_pwm_get_duty(enum pwm_channel ch)
-{
- return it8801_pwm_get_raw_duty(ch) * 100 / 255;
-}
-
-#ifdef CONFIG_KEYBOARD_BACKLIGHT
-const enum pwm_channel it8801_kblight_pwm_ch = IT8801_PWM_CH_KBLIGHT;
-
-static int it8801_kblight_enable(int enable)
-{
- it8801_pwm_enable(it8801_kblight_pwm_ch, enable);
- return EC_SUCCESS;
-}
-
-static int it8801_kblight_set_brightness(int percent)
-{
- it8801_pwm_set_duty(it8801_kblight_pwm_ch, percent);
- return EC_SUCCESS;
-}
-
-static int it8801_kblight_get_brightness(void)
-{
- return it8801_pwm_get_duty(it8801_kblight_pwm_ch);
-}
-
-static int it8801_kblight_init(void)
-{
- it8801_pwm_set_duty(it8801_kblight_pwm_ch, 0);
- it8801_pwm_enable(it8801_kblight_pwm_ch, 1);
- return EC_SUCCESS;
-}
-
-const struct kblight_drv kblight_it8801 = {
- .init = it8801_kblight_init,
- .set = it8801_kblight_set_brightness,
- .get = it8801_kblight_get_brightness,
- .enable = it8801_kblight_enable,
-};
-#endif
-#endif /* CONFIG_IO_EXPANDER_IT8801_PWM */
diff --git a/driver/ioexpander/it8801.h b/driver/ioexpander/it8801.h
deleted file mode 100644
index 05a17acf78..0000000000
--- a/driver/ioexpander/it8801.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/* Copyright 2019 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.
- *
- * IT8801 is an I/O expander with the keyboard matrix controller.
- *
- */
-
-#ifndef __CROS_EC_IO_EXPANDER_IT8801_H
-#define __CROS_EC_IO_EXPANDER_IT8801_H
-
-/* I2C address flags (7-bit without R/W) */
-#define IT8801_I2C_ADDR1 0x38
-#define IT8801_I2C_ADDR2 0x39
-
-/* Keyboard Matrix Scan control (KBS) */
-#define IT8801_REG_KSOMCR 0x40
-#define IT8801_REG_MASK_KSOSDIC BIT(7)
-#define IT8801_REG_MASK_KSE BIT(6)
-#define IT8801_REG_MASK_AKSOSC BIT(5)
-#define IT8801_REG_KSIDR 0x41
-#define IT8801_REG_KSIEER 0x42
-#define IT8801_REG_KSIIER 0x43
-#define IT8801_REG_SMBCR 0xfa
-#define IT8801_REG_MASK_ARE BIT(4)
-#define IT8801_REG_GIECR 0xfb
-#define IT8801_REG_MASK_GKSIIE BIT(3)
-#define IT8801_REG_GPIO10 0x12
-#define IT8801_REG_GPIO00_KSO19 0x0a
-#define IT8801_REG_GPIO01_KSO18 0x0b
-#define IT8801_REG_GPIO22_KSO21 0x1c
-#define IT8801_REG_GPIO23_KSO20 0x1d
-#define IT8801_REG_MASK_GPIOAFS_PULLUP BIT(7)
-#define IT8801_REG_MASK_GPIOAFS_FUNC2 BIT(6)
-#define IT8801_REG_MASK_GPIODIR BIT(5)
-#define IT8801_REG_MASK_GPIOPUE BIT(0)
-#define IT8801_REG_GPIO23SOV BIT(3)
-#define IT8801_REG_MASK_SELKSO2 0x02
-#define IT8801_REG_GISR 0xF9
-#define IT8801_REG_MASK_GISR_GKSIIS BIT(6)
-#define IT8801_REG_MASK_GISR_GGPIOG2IS BIT(2)
-#define IT8801_REG_MASK_GISR_GGPIOG1IS BIT(1)
-#define IT8801_REG_MASK_GISR_GGPIOG0IS BIT(0)
-#define IT8801_REG_MASK_GISR_GGPIOGXIS (IT8801_REG_MASK_GISR_GGPIOG2IS | \
- IT8801_REG_MASK_GISR_GGPIOG1IS | IT8801_REG_MASK_GISR_GGPIOG0IS)
-#define IT8801_REG_LBVIDR 0xFE
-#define IT8801_REG_HBVIDR 0xFF
-#define IT8801_KSO_COUNT 18
-
-/* General Purpose I/O Port (GPIO) */
-#define IT8801_SUPPORT_GPIO_FLAGS (GPIO_OPEN_DRAIN | GPIO_INPUT | \
- GPIO_OUTPUT | GPIO_LOW | GPIO_HIGH | GPIO_INT_ANY)
-
-#define IT8801_REG_MASK_GPIOAFS_FUNC1 (0x00 << 7)
-
-/* IT8801 only supports GPIO 0/1/2 */
-#define IT8801_VALID_GPIO_G0_MASK 0xD9
-#define IT8801_VALID_GPIO_G1_MASK 0x3F
-#define IT8801_VALID_GPIO_G2_MASK 0x0F
-
-extern __override_proto const uint8_t it8801_kso_mapping[];
-extern const struct ioexpander_drv it8801_ioexpander_drv;
-
-/* GPIO Register map */
-/* Input pin status register */
-#define IT8801_REG_GPIO_IPSR(port) (0x00 + (port))
-/* Set output value register */
-#define IT8801_REG_GPIO_SOVR(port) (0x05 + (port))
-/* Control register */
-#define IT8801_REG_GPIO_CR(port, mask) \
- (0x0A + (port) * 8 + GPIO_MASK_TO_NUM(mask))
-/* Interrupt status register */
-#define IT8801_REG_GPIO_ISR(port) (0x32 + (port))
-/* Interrupt enable register */
-#define IT8801_REG_GPIO_IER(port) (0x37 + (port))
-
-/* Control register values */
-#define IT8801_GPIOAFS_SHIFT 6 /* bit 6~7 */
-
-#define IT8801_GPIODIR BIT(5) /* direction, output=1 */
-/* input pin */
-#define IT8801_GPIOIOT_INT_RISING BIT(3)
-#define IT8801_GPIOIOT_INT_FALLING BIT(4)
-
-#define IT8801_GPIODIR BIT(5)
-#define IT8801_GPIOIOT BIT(4)
-#define IT8801_GPIOPOL BIT(2) /* polarity */
-#define IT8801_GPIOPDE BIT(1) /* pull-down enable */
-#define IT8801_GPIOPUE BIT(0) /* pull-up enable */
-
-/* ISR for IT8801's SMB_INT# */
-void io_expander_it8801_interrupt(enum gpio_signal signal);
-
-#ifdef CONFIG_IO_EXPANDER_IT8801_PWM
-
-/* Mapping PWM_CH_LED_* to it8801 channel */
-struct it8801_pwm_t {
- int index;
-};
-
-extern const struct it8801_pwm_t it8801_pwm_channels[];
-extern const struct kblight_drv kblight_it8801;
-
-/* standard pwm interface as defined in pwm.h */
-void it8801_pwm_enable(enum pwm_channel ch, int enabled);
-int it8801_pwm_get_enabled(enum pwm_channel ch);
-void it8801_pwm_set_raw_duty(enum pwm_channel ch, uint16_t duty);
-uint16_t it8801_pwm_get_raw_duty(enum pwm_channel ch);
-void it8801_pwm_set_duty(enum pwm_channel ch, int percent);
-int it8801_pwm_get_duty(enum pwm_channel ch);
-
-#define IT8801_REG_PWMODDSR 0x5F
-#define IT8801_REG_PWMMCR(n) (0x60 + ((n) - 1) * 8)
-#define IT8801_REG_PWMDCR(n) (0x64 + ((n) - 1) * 8)
-#define IT8801_REG_PWMPRSL(n) (0x66 + ((n) - 1) * 8)
-#define IT8801_REG_PWMPRSM(n) (0x67 + ((n) - 1) * 8)
-
-#define IT8801_PWMMCR_MCR_MASK 0x3
-#define IT8801_PWMMCR_MCR_OFF 0
-#define IT8801_PWMMCR_MCR_BLINKING 1
-#define IT8801_PWMMCR_MCR_BREATHING 2
-#define IT8801_PWMMCR_MCR_ON 3
-
-#endif /* CONFIG_IO_EXPANDER_IT8801_PWM */
-
-#endif /* __CROS_EC_KBEXPANDER_IT8801_H */
diff --git a/driver/ioexpander/pca9534.c b/driver/ioexpander/pca9534.c
deleted file mode 100644
index d56eb864cb..0000000000
--- a/driver/ioexpander/pca9534.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/* Copyright 2014 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.
- *
- * NXP PCA9534 I/O expander
- */
-
-#include "i2c.h"
-#include "pca9534.h"
-
-static int pca9534_pin_read(const int port, const uint16_t addr_flags,
- int reg, int pin, int *val)
-{
- int ret;
- ret = i2c_read8(port, addr_flags, reg, val);
- *val = (*val & BIT(pin)) ? 1 : 0;
- return ret;
-}
-
-static int pca9534_pin_write(const int port, const uint16_t addr_flags,
- int reg, int pin, int val)
-{
- int ret, v;
- ret = i2c_read8(port, addr_flags, reg, &v);
- if (ret != EC_SUCCESS)
- return ret;
- v &= ~BIT(pin);
- if (val)
- v |= 1 << pin;
- return i2c_write8(port, addr_flags, reg, v);
-}
-
-int pca9534_get_level(const int port, const uint16_t addr_flags,
- int pin, int *level)
-{
- return pca9534_pin_read(port, addr_flags,
- PCA9534_REG_INPUT, pin, level);
-}
-
-int pca9534_set_level(const int port, const uint16_t addr_flags,
- int pin, int level)
-{
- return pca9534_pin_write(port, addr_flags,
- PCA9534_REG_OUTPUT, pin, level);
-}
-
-int pca9534_config_pin(const int port, const uint16_t addr_flags,
- int pin, int is_input)
-{
- return pca9534_pin_write(port, addr_flags,
- PCA9534_REG_CONFIG, pin, is_input);
-}
diff --git a/driver/ioexpander/pca9534.h b/driver/ioexpander/pca9534.h
deleted file mode 100644
index 0fec577576..0000000000
--- a/driver/ioexpander/pca9534.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Copyright 2014 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.
- *
- * NXP PCA9534 I/O expander
- */
-
-#ifndef __CROS_EC_IOEXPANDER_PCA9534_H
-#define __CROS_EC_IOEXPANDER_PCA9534_H
-
-#define PCA9534_REG_INPUT 0x0
-#define PCA9534_REG_OUTPUT 0x1
-#define PCA9534_REG_CONFIG 0x3
-
-#define PCA9534_OUTPUT 0
-#define PCA9534_INPUT 1
-
-/*
- * Get input level. Note that this reflects the actual level on the
- * pin, even if the pin is configured as output.
- *
- * @param port The I2C port of PCA9534.
- * @param addr The address of PCA9534.
- * @param pin The index of the pin to read.
- * @param level The pointer to where the read level is stored.
- *
- * @return EC_SUCCESS, or EC_ERROR_* on error.
- */
-int pca9534_get_level(const int port, const uint16_t addr_flags,
- int pin, int *level);
-
-/*
- * Set output level. This function has no effect if the pin is
- * configured as input.
- *
- * @param port The I2C port of PCA9534.
- * @param addr The address of PCA9534.
- * @param pin The index of the pin to set.
- * @param level The level to set.
- *
- * @return EC_SUCCESS, or EC_ERROR_* on error.
- */
-int pca9534_set_level(const int port, const uint16_t addr_flags,
- int pin, int level);
-
-/*
- * Config a pin as input or output.
- *
- * @param port The I2C port of PCA9534.
- * @param addr The address of PCA9534.
- * @param pin The index of the pin to set.
- * @param is_input PCA9534_INPUT or PCA9534_OUTPUT.
- *
- * @return EC_SUCCESS, or EC_ERROR_* on error.
- */
-int pca9534_config_pin(const int port, const uint16_t addr_flags,
- int pin, int is_input);
-
-#endif /* __CROS_EC_IOEXPANDER_PCA9534_H */
diff --git a/driver/ioexpander/pca9555.h b/driver/ioexpander/pca9555.h
deleted file mode 100644
index 273f898821..0000000000
--- a/driver/ioexpander/pca9555.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Copyright 2017 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.
- *
- * NXP PCA9555 I/O Port expander driver header
- */
-
-#ifndef __CROS_EC_IOEXPANDER_PCA9555_H
-#define __CROS_EC_IOEXPANDER_PCA9555_H
-
-#include "i2c.h"
-
-#define PCA9555_CMD_INPUT_PORT_0 0
-#define PCA9555_CMD_INPUT_PORT_1 1
-#define PCA9555_CMD_OUTPUT_PORT_0 2
-#define PCA9555_CMD_OUTPUT_PORT_1 3
-#define PCA9555_CMD_POLARITY_INVERSION_PORT_0 4
-#define PCA9555_CMD_POLARITY_INVERSION_PORT_1 5
-#define PCA9555_CMD_CONFIGURATION_PORT_0 6
-#define PCA9555_CMD_CONFIGURATION_PORT_1 7
-
-#define PCA9555_IO_0 BIT(0)
-#define PCA9555_IO_1 BIT(1)
-#define PCA9555_IO_2 BIT(2)
-#define PCA9555_IO_3 BIT(3)
-#define PCA9555_IO_4 BIT(4)
-#define PCA9555_IO_5 BIT(5)
-#define PCA9555_IO_6 BIT(6)
-#define PCA9555_IO_7 BIT(7)
-
-static inline int pca9555_read(const int port,
- const uint16_t i2c_addr_flags,
- int reg, int *data_ptr)
-{
- return i2c_read8(port, i2c_addr_flags, reg, data_ptr);
-}
-
-static inline int pca9555_write(const int port,
- const uint16_t i2c_addr_flags,
- int reg, int data)
-{
- return i2c_write8(port, i2c_addr_flags, reg, data);
-}
-
-#endif /* __CROS_EC_IOEXPANDER_PCA9555_H */
diff --git a/driver/ioexpander/pca9675.c b/driver/ioexpander/pca9675.c
deleted file mode 100644
index 3fe3bfa0c4..0000000000
--- a/driver/ioexpander/pca9675.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/* Copyright 2020 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.
- *
- * NXP PCA9675PW I/O Port expander driver source
- */
-
-#include "i2c.h"
-#include "ioexpander.h"
-#include "pca9675.h"
-
-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_read16(int ioex, uint16_t *data)
-{
- return i2c_xfer(ioex_config[ioex].i2c_host_port,
- ioex_config[ioex].i2c_addr_flags,
- NULL, 0, (uint8_t *)data, 2);
-}
-
-static int pca9675_write16(int ioex, uint16_t data)
-{
- /*
- * PCA9675 is Quasi-bidirectional I/O architecture hence
- * append the direction (1 = input, 0 = output) to prevent
- * overwriting I/O pins inadvertently.
- */
- data |= pca9675_iox[ioex].io_direction;
-
- return i2c_xfer(ioex_config[ioex].i2c_host_port,
- ioex_config[ioex].i2c_addr_flags,
- (uint8_t *)&data, 2, NULL, 0);
-}
-
-static int pca9675_reset(int ioex)
-{
- uint8_t reset = PCA9675_RESET_SEQ_DATA;
-
- return i2c_xfer(ioex_config[ioex].i2c_host_port,
- 0, &reset, 1, NULL, 0);
-}
-
-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 & mask) {
- rv = pca9675_read16(ioex, &data_read);
- if (!rv)
- *val = !!(data_read & mask);
- } else {
- *val = !!(pca9675_iox[ioex].cache_out_pins & mask);
- }
-
- return rv;
-}
-
-static int pca9675_set_level(int ioex, int port, int mask, int val)
-{
- /* Update the output pins */
- 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);
-}
-
-static int pca9675_set_flags_by_mask(int ioex, int port, int mask, int flags)
-{
- int rv = EC_SUCCESS;
-
- /* Initialize the I/O directions */
- if (flags & GPIO_INPUT) {
- pca9675_iox[ioex].io_direction |= mask;
- } else {
- pca9675_iox[ioex].io_direction &= ~mask;
-
- /* Initialize the pin */
- rv = pca9675_set_level(ioex, port, mask, flags & GPIO_HIGH);
- }
-
- return rv;
-}
-
-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)
-{
- pca9675_iox[ioex].io_direction = PCA9675_DEFAULT_IO_DIRECTION;
- pca9675_iox[ioex].cache_out_pins = 0;
-
- /* Set pca9675 to Power-on reset */
- 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
deleted file mode 100644
index 59f36918a4..0000000000
--- a/driver/ioexpander/pca9675.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright 2020 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.
- *
- * NXP PCA9675PW I/O Port expander driver header
- */
-
-#ifndef __CROS_EC_IOEXPANDER_PCA9675_H
-#define __CROS_EC_IOEXPANDER_PCA9675_H
-
-/* 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,
-};
-
-/* 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
-
-extern const struct ioexpander_drv pca9675_ioexpander_drv;
-
-#endif /* __CROS_EC_IOEXPANDER_PCA9675_H */
diff --git a/driver/ioexpander/pcal6408.c b/driver/ioexpander/pcal6408.c
deleted file mode 100644
index 287e0506d0..0000000000
--- a/driver/ioexpander/pcal6408.c
+++ /dev/null
@@ -1,354 +0,0 @@
-/* Copyright 2020 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.
- *
- * NXP PCA(L)6408 I/O expander
- */
-#include "common.h"
-#include "console.h"
-#include "math_util.h"
-#include "gpio.h"
-#include "i2c.h"
-#include "ioexpander.h"
-#include "pcal6408.h"
-
-#define CPRINTF(format, args...) cprintf(CC_GPIO, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args)
-
-/*
- * Store interrupt mask registers locally. In this way,
- * we don't have to read it via i2c transaction every time.
- * Default value of interrupt mask register is 0xff.
- */
-uint8_t pcal6408_int_mask[] = {
- [0 ... (CONFIG_IO_EXPANDER_PORT_COUNT - 1)] = 0xff };
-
-
-static int pcal6408_read(int ioex, int reg, int *data)
-{
- int rv;
- struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
-
- rv = i2c_read8(ioex_p->i2c_host_port, ioex_p->i2c_addr_flags,
- reg, data);
-
- return rv;
-}
-
-static int pcal6408_write(int ioex, int reg, int data)
-{
- int rv;
- struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
-
- rv = i2c_write8(ioex_p->i2c_host_port, ioex_p->i2c_addr_flags,
- reg, data);
-
- return rv;
-}
-
-static int pcal6408_ioex_check_is_valid(int port, int mask)
-{
- if (port != 0)
- return EC_ERROR_INVAL;
-
- if (mask & ~PCAL6408_VALID_GPIO_MASK) {
- CPRINTF("GPIO%02d is not support in PCAL6408\n",
- __fls(mask));
- return EC_ERROR_INVAL;
- }
-
- return EC_SUCCESS;
-}
-
-static int pcal6408_ioex_init(int ioex)
-{
- /* It seems that we have nothing to do here.
- * This chip has not a chip id to be identified.
- */
- return EC_SUCCESS;
-}
-
-static int pcal6408_ioex_get_level(int ioex, int port, int mask, int *val)
-{
- int rv;
-
- rv = pcal6408_ioex_check_is_valid(port, mask);
- if (rv != EC_SUCCESS)
- return rv;
-
- rv = pcal6408_read(ioex, PCAL6408_REG_INPUT, val);
- if (rv != EC_SUCCESS)
- return rv;
-
- *val = !!(*val & mask);
-
- return EC_SUCCESS;
-}
-
-static int pcal6408_ioex_set_level(int ioex, int port, int mask, int value)
-{
- int rv, val;
-
- rv = pcal6408_ioex_check_is_valid(port, mask);
- if (rv != EC_SUCCESS)
- return rv;
-
- rv = pcal6408_read(ioex, PCAL6408_REG_OUTPUT, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (value)
- val |= mask;
- else
- val &= ~mask;
-
- return pcal6408_write(ioex, PCAL6408_REG_OUTPUT, val);
-}
-
-static int pcal6408_ioex_get_flags_by_mask(int ioex, int port, int mask,
- int *flags)
-{
- int rv, val;
-
- rv = pcal6408_ioex_check_is_valid(port, mask);
- if (rv != EC_SUCCESS)
- return rv;
-
- *flags = GPIO_FLAG_NONE;
-
- rv = pcal6408_read(ioex, PCAL6408_REG_CONFIG, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (val & mask)
- *flags |= GPIO_INPUT;
- else
- *flags |= GPIO_OUTPUT;
-
- rv = pcal6408_read(ioex, PCAL6408_REG_INPUT, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (val & mask)
- *flags |= GPIO_HIGH;
- else
- *flags |= GPIO_LOW;
-
- rv = pcal6408_read(ioex, PCAL6408_REG_OUT_CONFIG, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (val & PCAL6408_OUT_CONFIG_OPEN_DRAIN)
- *flags |= GPIO_OPEN_DRAIN;
-
- rv = pcal6408_read(ioex, PCAL6408_REG_PULL_ENABLE, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (val & mask) {
- rv = pcal6408_read(ioex, PCAL6408_REG_PULL_UP_DOWN, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (val & mask)
- *flags |= GPIO_PULL_UP;
- else
- *flags |= GPIO_PULL_DOWN;
- }
-
- rv = pcal6408_read(ioex, PCAL6408_REG_INT_MASK, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if ((!!(val & mask) == 0) && ((*flags) & GPIO_INPUT))
- *flags |= GPIO_INT_BOTH;
-
- return rv;
-}
-
-static int pcal6408_ioex_set_flags_by_mask(int ioex, int port, int mask,
- int flags)
-{
- int rv, val;
-
- rv = pcal6408_ioex_check_is_valid(port, mask);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (((flags & GPIO_INT_BOTH) == GPIO_INT_RISING) ||
- ((flags & GPIO_INT_BOTH) == GPIO_INT_FALLING)) {
- CPRINTF("PCAL6408 only support GPIO_INT_BOTH.\n");
- return EC_ERROR_INVAL;
- }
-
-
- if ((flags & (GPIO_INT_F_RISING | GPIO_INT_F_FALLING)) &&
- !(flags & GPIO_INPUT)) {
- CPRINTF("Interrupt pin must be GPIO_INPUT.\n");
- return EC_ERROR_INVAL;
- }
-
- /* All output gpios share GPIO_OPEN_DRAIN, should be consistent */
- if (flags & GPIO_OPEN_DRAIN)
- val = PCAL6408_OUT_CONFIG_OPEN_DRAIN;
- else
- val = 0;
-
- rv = pcal6408_write(ioex, PCAL6408_REG_OUT_CONFIG, val);
- if (rv != EC_SUCCESS)
- return rv;
-
- rv = pcal6408_read(ioex, PCAL6408_REG_CONFIG, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (flags & GPIO_INPUT)
- val |= mask;
- if (flags & GPIO_OUTPUT)
- val &= ~mask;
-
- rv = pcal6408_write(ioex, PCAL6408_REG_CONFIG, val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (flags & GPIO_OUTPUT) {
- rv = pcal6408_read(ioex, PCAL6408_REG_OUTPUT, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (flags & GPIO_HIGH)
- val |= mask;
- else if (flags & GPIO_LOW)
- val &= ~mask;
-
- rv = pcal6408_write(ioex, PCAL6408_REG_OUTPUT, val);
- if (rv != EC_SUCCESS)
- return rv;
- }
-
- if (!(flags & (GPIO_PULL_UP | GPIO_PULL_DOWN))) {
- rv = pcal6408_read(ioex, PCAL6408_REG_PULL_ENABLE, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- val &= ~mask;
-
- rv = pcal6408_write(ioex, PCAL6408_REG_PULL_ENABLE, val);
- if (rv != EC_SUCCESS)
- return rv;
- } else {
- rv = pcal6408_read(ioex, PCAL6408_REG_PULL_ENABLE, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- val |= mask;
-
- rv = pcal6408_write(ioex, PCAL6408_REG_PULL_ENABLE, val);
- if (rv != EC_SUCCESS)
- return rv;
-
- rv = pcal6408_read(ioex, PCAL6408_REG_PULL_UP_DOWN, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (flags & GPIO_PULL_UP)
- val |= mask;
- else if (flags & GPIO_PULL_DOWN)
- val &= ~mask;
-
- rv = pcal6408_write(ioex, PCAL6408_REG_PULL_UP_DOWN, val);
- if (rv != EC_SUCCESS)
- return rv;
- }
-
- return rv;
-}
-
-static int pcal6408_ioex_enable_interrupt(int ioex, int port, int mask,
- int enable)
-{
- int rv, val;
-
- rv = pcal6408_ioex_check_is_valid(port, mask);
- if (rv != EC_SUCCESS)
- return rv;
-
- /* Interrupt should be latched */
- rv = pcal6408_read(ioex, PCAL6408_REG_INPUT_LATCH, &val);
- if (rv != EC_SUCCESS)
- return rv;
-
- if (enable)
- val |= mask;
- else
- val &= ~mask;
-
- rv = pcal6408_write(ioex, PCAL6408_REG_INPUT_LATCH, val);
- if (rv != EC_SUCCESS)
- return rv;
-
- /*
- * Enable or disable interrupt.
- * In PCAL6408_REG_INT_MASK, 0 = enable interrupt,
- * 1 = disable interrupt.
- */
- if (enable)
- pcal6408_int_mask[ioex] &= ~mask;
- else
- pcal6408_int_mask[ioex] |= mask;
-
- rv = pcal6408_write(ioex, PCAL6408_REG_INT_MASK,
- pcal6408_int_mask[ioex]);
-
- return rv;
-}
-
-int pcal6408_ioex_event_handler(int ioex)
-{
- int int_status, int_mask;
- struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
- int i, rv = 0;
- const struct ioex_info *g;
-
- int_mask = pcal6408_int_mask[ioex];
-
- /*
- * Read input port register will clear the interrupt,
- * read status register will not.
- */
- rv = i2c_read8(ioex_p->i2c_host_port, ioex_p->i2c_addr_flags,
- PCAL6408_REG_INT_STATUS, &int_status);
- if (rv != EC_SUCCESS)
- return rv;
-
- /*
- * In pcal6408_int_mask[x], 0 = enable interrupt,
- * 1 = disable interrupt.
- */
- int_status = int_status & ~int_mask;
-
- if (!int_status)
- return EC_SUCCESS;
-
- for (i = 0, g = ioex_list; i < ioex_ih_count; i++, g++) {
-
- if (ioex == g->ioex && 0 == g->port &&
- (int_status & g->mask)) {
- ioex_irq_handlers[i](i + IOEX_SIGNAL_START);
- int_status &= ~g->mask;
- if (!int_status)
- break;
- }
- }
-
- return EC_SUCCESS;
-}
-
-const struct ioexpander_drv pcal6408_ioexpander_drv = {
- .init = &pcal6408_ioex_init,
- .get_level = &pcal6408_ioex_get_level,
- .set_level = &pcal6408_ioex_set_level,
- .get_flags_by_mask = &pcal6408_ioex_get_flags_by_mask,
- .set_flags_by_mask = &pcal6408_ioex_set_flags_by_mask,
- .enable_interrupt = &pcal6408_ioex_enable_interrupt,
-};
diff --git a/driver/ioexpander/pcal6408.h b/driver/ioexpander/pcal6408.h
deleted file mode 100644
index fc9969aab1..0000000000
--- a/driver/ioexpander/pcal6408.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Copyright 2020 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.
- *
- * NXP PCA(L)6408 I/O expander
- */
-
-#ifndef __CROS_EC_IOEXPANDER_PCAL6408_H
-#define __CROS_EC_IOEXPANDER_PCAL6408_H
-
-#define PCAL6408_I2C_ADDR0 0x20
-#define PCAL6408_I2C_ADDR1 0x21
-
-#define PCAL6408_REG_INPUT 0x00
-#define PCAL6408_REG_OUTPUT 0x01
-#define PCAL6408_REG_POLARITY_INVERSION 0x02
-#define PCAL6408_REG_CONFIG 0x03
-#define PCAL6408_REG_OUT_STRENGTH0 0x40
-#define PCAL6408_REG_OUT_STRENGTH1 0x41
-#define PCAL6408_REG_INPUT_LATCH 0x42
-#define PCAL6408_REG_PULL_ENABLE 0x43
-#define PCAL6408_REG_PULL_UP_DOWN 0x44
-#define PCAL6408_REG_INT_MASK 0x45
-#define PCAL6408_REG_INT_STATUS 0x46
-#define PCAL6408_REG_OUT_CONFIG 0x4f
-
-#define PCAL6408_VALID_GPIO_MASK 0xff
-
-#define PCAL6408_OUTPUT 0
-#define PCAL6408_INPUT 1
-
-#define PCAL6408_OUT_CONFIG_OPEN_DRAIN 0x01
-
-/*
- * Check which IO's interrupt event is triggered. If any, call its
- * registered interrupt handler.
- */
-int pcal6408_ioex_event_handler(int ioex);
-
-extern const struct ioexpander_drv pcal6408_ioexpander_drv;
-
-#endif /* __CROS_EC_IOEXPANDER_PCAL6408_H */
diff --git a/driver/ioexpander/tca64xxa.c b/driver/ioexpander/tca64xxa.c
deleted file mode 100644
index 9a70ceec11..0000000000
--- a/driver/ioexpander/tca64xxa.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/* 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.
- */
-
-#include "common.h"
-#include "i2c.h"
-#include "ioexpander.h"
-#include "system.h"
-#include "tca64xxa.h"
-
-/*
- * This chip series contain registers in the same order.
- * Difference between models is only amount of registers and
- * value of which you must multiply to access specific register.
- * For 16 bit series, registers are 2 byte away, so to access TCA64XXA_REG_CONF
- * you must multiply it by 2. For 24 bit, they are away by 4 bytes so you
- * must multiply them by 4. Flags value contains information which version
- * of chip is used.
- */
-#define TCA64XXA_PORT_ID(port, reg, flags) \
- ((((flags) & TCA64XXA_FLAG_VER_MASK) \
- >> TCA64XXA_FLAG_VER_OFFSET) * (reg) + (port))
-
-static int tca64xxa_write_byte(int ioex, int port, int reg, uint8_t val)
-{
- const struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
- const int reg_addr = TCA64XXA_PORT_ID(port, reg, ioex_p->flags);
-
- return i2c_write8(ioex_p->i2c_host_port,
- ioex_p->i2c_addr_flags,
- reg_addr,
- val);
-}
-
-static int tca64xxa_read_byte(int ioex, int port, int reg, int *val)
-{
- const struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
- const int reg_addr = TCA64XXA_PORT_ID(port, reg, ioex_p->flags);
-
- return i2c_read8(ioex_p->i2c_host_port,
- ioex_p->i2c_addr_flags,
- reg_addr,
- val);
-}
-
-/* Restore default values in registers */
-static int tca64xxa_reset(int ioex, int portsCount)
-{
- int port;
- int ret;
-
- /*
- * On servo_v4p1, reset pin is pulled up and it results in values
- * not being restored to default ones after software reboot.
- * This loop sets default values (from specification) to all registers.
- */
- for (port = 0; port < portsCount; port++) {
- ret = tca64xxa_write_byte(ioex,
- port,
- TCA64XXA_REG_OUTPUT,
- TCA64XXA_DEFAULT_OUTPUT);
- if (ret)
- return ret;
-
- ret = tca64xxa_write_byte(ioex,
- port,
- TCA64XXA_REG_POLARITY_INV,
- TCA64XXA_DEFAULT_POLARITY_INV);
- if (ret)
- return ret;
-
- ret = tca64xxa_write_byte(ioex,
- port,
- TCA64XXA_REG_CONF,
- TCA64XXA_DEFAULT_CONF);
- if (ret)
- return ret;
- }
-
- return EC_SUCCESS;
-}
-
-/* Initialize IO expander chip/driver */
-static int tca64xxa_init(int ioex)
-{
- const struct ioexpander_config_t *ioex_p = &ioex_config[ioex];
- int portsCount;
-
- if (ioex_p->flags & TCA64XXA_FLAG_VER_TCA6416A)
- portsCount = 2;
- else if (ioex_p->flags & TCA64XXA_FLAG_VER_TCA6424A)
- portsCount = 3;
- else
- return EC_ERROR_UNIMPLEMENTED;
-
- if (!system_jumped_late())
- return tca64xxa_reset(ioex, portsCount);
-
- return EC_SUCCESS;
-}
-
-/* Get the current level of the IOEX pin */
-static int tca64xxa_get_level(int ioex, int port, int mask, int *val)
-{
- int buf;
- int ret;
-
- ret = tca64xxa_read_byte(ioex, port, TCA64XXA_REG_INPUT, &buf);
- *val = !!(buf & mask);
-
- return ret;
-}
-
-/* Set the level of the IOEX pin */
-static int tca64xxa_set_level(int ioex, int port, int mask, int val)
-{
- int ret;
- int v;
-
- ret = tca64xxa_read_byte(ioex, port, TCA64XXA_REG_OUTPUT, &v);
- if (ret)
- return ret;
-
- if (val)
- v |= mask;
- else
- v &= ~mask;
-
- return tca64xxa_write_byte(ioex, port, TCA64XXA_REG_OUTPUT, v);
-}
-
-/* Get flags for the IOEX pin */
-static int tca64xxa_get_flags_by_mask(int ioex, int port, int mask, int *flags)
-{
- int ret;
- int v;
-
- ret = tca64xxa_read_byte(ioex, port, TCA64XXA_REG_CONF, &v);
- if (ret)
- return ret;
-
- *flags = 0;
- if (v & mask) {
- *flags |= GPIO_INPUT;
- } else {
- *flags |= GPIO_OUTPUT;
-
- ret = tca64xxa_read_byte(ioex, port, TCA64XXA_REG_OUTPUT, &v);
- if(ret)
- return ret;
-
- if (v & mask)
- *flags |= GPIO_HIGH;
- else
- *flags |= GPIO_LOW;
- }
-
- return EC_SUCCESS;
-}
-
-/* Set flags for the IOEX pin */
-static int tca64xxa_set_flags_by_mask(int ioex, int port, int mask, int flags)
-{
- int ret;
- int v;
-
- /* Output value */
- if (flags & GPIO_OUTPUT) {
- ret = tca64xxa_read_byte(ioex, port, TCA64XXA_REG_OUTPUT, &v);
- if (ret)
- return ret;
-
- if (flags & GPIO_LOW)
- v &= ~mask;
- else if (flags & GPIO_HIGH)
- v |= mask;
- else
- return EC_ERROR_INVAL;
-
- ret = tca64xxa_write_byte(ioex, port, TCA64XXA_REG_OUTPUT, v);
- if (ret)
- return ret;
- }
-
- /* Configuration */
- ret = tca64xxa_read_byte(ioex, port, TCA64XXA_REG_CONF, &v);
- if(ret)
- return ret;
-
- if (flags & GPIO_INPUT)
- v |= mask;
- else if (flags & GPIO_OUTPUT)
- v &= ~mask;
- else
- return EC_ERROR_INVAL;
-
- ret = tca64xxa_write_byte(ioex, port, TCA64XXA_REG_CONF, v);
- if (ret)
- return ret;
-
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_IO_EXPANDER_SUPPORT_GET_PORT
-
-/* Read levels for whole IO expander port */
-static int tca64xxa_get_port(int ioex, int port, int *val)
-{
- return tca64xxa_read_byte(ioex, port, TCA64XXA_REG_INPUT, val);
-}
-
-#endif
-
-/* Driver structure */
-const struct ioexpander_drv tca64xxa_ioexpander_drv = {
- .init = tca64xxa_init,
- .get_level = tca64xxa_get_level,
- .set_level = tca64xxa_set_level,
- .get_flags_by_mask = tca64xxa_get_flags_by_mask,
- .set_flags_by_mask = tca64xxa_set_flags_by_mask,
- .enable_interrupt = NULL,
-#ifdef CONFIG_IO_EXPANDER_SUPPORT_GET_PORT
- .get_port = tca64xxa_get_port,
-#endif
-};
diff --git a/driver/ioexpander/tca64xxa.h b/driver/ioexpander/tca64xxa.h
deleted file mode 100644
index 8c3448f804..0000000000
--- a/driver/ioexpander/tca64xxa.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* 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.
- */
-
-#ifndef __CROS_EC_DRIVER_IOEXPANDER_TCA64XXA_H_
-#define __CROS_EC_DRIVER_IOEXPANDER_TCA64XXA_H_
-
-#define TCA64XXA_FLAG_VER_TCA6416A 2
-#define TCA64XXA_FLAG_VER_TCA6424A 4
-#define TCA64XXA_FLAG_VER_MASK GENMASK(2, 1)
-#define TCA64XXA_FLAG_VER_OFFSET 0
-
-#define TCA64XXA_REG_INPUT 0
-#define TCA64XXA_REG_OUTPUT 1
-#define TCA64XXA_REG_POLARITY_INV 2
-#define TCA64XXA_REG_CONF 3
-
-#define TCA64XXA_DEFAULT_OUTPUT 0xFF
-#define TCA64XXA_DEFAULT_POLARITY_INV 0x00
-#define TCA64XXA_DEFAULT_CONF 0xFF
-
-extern const struct ioexpander_drv tca64xxa_ioexpander_drv;
-
-#endif /* __CROS_EC_DRIVER_IOEXPANDER_TCA64XXA_H_ */