diff options
Diffstat (limited to 'driver/ioexpander/tca64xxa.c')
-rw-r--r-- | driver/ioexpander/tca64xxa.c | 226 |
1 files changed, 0 insertions, 226 deletions
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 -}; |