diff options
Diffstat (limited to 'driver/gl3590.c')
-rw-r--r-- | driver/gl3590.c | 346 |
1 files changed, 0 insertions, 346 deletions
diff --git a/driver/gl3590.c b/driver/gl3590.c deleted file mode 100644 index cb8d914d8c..0000000000 --- a/driver/gl3590.c +++ /dev/null @@ -1,346 +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. - */ - -#include "console.h" -#include "hooks.h" -#include "i2c.h" -#include "system.h" -#include "util.h" -#include "pwr_defs.h" - -#include "gl3590.h" - -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args) - -/* GL3590 is unique in terms of i2c_read, since it doesn't support repeated - * start sequence. One need to issue two separate transactions - first is write - * with a register offset, then after a delay second transaction is actual read. - */ -int gl3590_read(int hub, uint8_t reg, uint8_t *data, int count) -{ - int rv; - struct uhub_i2c_iface_t *uhub_p = &uhub_config[hub]; - - i2c_lock(uhub_p->i2c_host_port, 1); - rv = i2c_xfer_unlocked(uhub_p->i2c_host_port, - uhub_p->i2c_addr, - ®, 1, - NULL, 0, - I2C_XFER_SINGLE); - i2c_lock(uhub_p->i2c_host_port, 0); - - if (rv) - return rv; - - /* GL3590 requires at least 1ms between consecutive i2c transactions */ - udelay(MSEC); - - i2c_lock(uhub_p->i2c_host_port, 1); - rv = i2c_xfer_unlocked(uhub_p->i2c_host_port, - uhub_p->i2c_addr, - NULL, 0, - data, count, - I2C_XFER_SINGLE); - i2c_lock(uhub_p->i2c_host_port, 0); - - /* - * GL3590 requires at least 1ms between consecutive i2c transactions. - * Make sure that we are safe across API calls. - */ - udelay(MSEC); - - return rv; -}; - -int gl3590_write(int hub, uint8_t reg, uint8_t *data, int count) -{ - int rv; - uint8_t buf[5]; - struct uhub_i2c_iface_t *uhub_p = &uhub_config[hub]; - - /* GL3590 registers accept 4 bytes at max */ - if (count > (sizeof(buf) - 1)) { - ccprintf("Too many bytes to write"); - return EC_ERROR_INVAL; - } - - buf[0] = reg; - memcpy(&buf[1], data, count); - - i2c_lock(uhub_p->i2c_host_port, 1); - rv = i2c_xfer_unlocked(uhub_p->i2c_host_port, - uhub_p->i2c_addr, - buf, count + 1, - NULL, 0, - I2C_XFER_SINGLE); - i2c_lock(uhub_p->i2c_host_port, 0); - - /* - * GL3590 requires at least 1ms between consecutive i2c transactions. - * Make sure that we are safe across API calls. - */ - udelay(MSEC); - - return rv; -} - -/* - * Basic initialization of GL3590 I2C interface. - * - * Please note, that I2C interface is online not earlier than ~50ms after - * RESETJ# is deasserted. Platform should check that PGREEN_A_SMD pin is - * asserted. This init function shouldn't be invoked until that time. - */ -void gl3590_init(int hub) -{ - uint8_t tmp; - struct uhub_i2c_iface_t *uhub_p = &uhub_config[hub]; - - if (uhub_p->initialized) - return; - - if (gl3590_read(hub, GL3590_HUB_MODE_REG, &tmp, 1)) { - CPRINTF("GL3590: Cannot read HUB_MODE register"); - return; - } - if ((tmp & GL3590_HUB_MODE_I2C_READY) == 0) - CPRINTF("GL3590 interface isn't ready, consider deferring " - "this init\n"); - - /* Deassert INTR# signal */ - tmp = GL3590_INT_CLEAR; - if (gl3590_write(hub, GL3590_INT_REG, &tmp, 1)) { - CPRINTF("GL3590: Cannot write to INT register"); - return; - }; - - uhub_p->initialized = 1; -} - -/* - * GL3590 chip may drive I2C_SDA and I2C_SCL lines for 200ms (max) after it is - * released from reset (through gpio de-assertion in main()). In order to avoid - * broken I2C transactions, we need to add an extra delay before any activity on - * the I2C bus in the system. - */ -static void gl3590_delay_on_init(void) -{ - CPRINTS("Applying 200ms delay for GL3590 to release I2C lines"); - udelay(200 * MSEC); -} -DECLARE_HOOK(HOOK_INIT, gl3590_delay_on_init, HOOK_PRIO_INIT_I2C - 1); - -void gl3590_irq_handler(int hub) -{ - uint8_t buf = 0; - uint8_t res_reg[2]; - struct uhub_i2c_iface_t *uhub_p = &uhub_config[hub]; - - if (!uhub_p->initialized) - return; - - /* Verify that irq is pending */ - if (gl3590_read(hub, GL3590_INT_REG, &buf, sizeof(buf))) { - ccprintf("Cannot read from the host hub i2c\n"); - goto exit; - } - - if ((buf & GL3590_INT_PENDING) == 0) { - ccprintf("Invalid hub event\n"); - goto exit; - } - - /* Get the hub event reason */ - if (gl3590_read(hub, GL3590_RESPONSE_REG, res_reg, sizeof(res_reg))) { - ccprintf("Cannot read from the host hub i2c\n"); - goto exit; - } - - if ((res_reg[0] & GL3590_RESPONSE_REG_SYNC_MASK) == 0) - ccprintf("Host hub response: "); - else - ccprintf("Host hub event! "); - - switch(res_reg[0]) { - case 0x0: - ccprintf("No response"); - break; - case 0x1: - ccprintf("Successful"); - break; - case 0x2: - ccprintf("Invalid command"); - break; - case 0x3: - ccprintf("Invalid arguments"); - break; - case 0x4: - ccprintf("Invalid port: %d", res_reg[1]); - break; - case 0x5: - ccprintf("Command not completed"); - break; - case 0x80: - ccprintf("Reset complete"); - break; - case 0x81: - ccprintf("Power operation mode change"); - break; - case 0x82: - ccprintf("Connect change"); - break; - case 0x83: - ccprintf("Error on the specific port"); - break; - case 0x84: - ccprintf("Hub state change"); - break; - case 0x85: - ccprintf("SetFeature PORT_POWER failure"); - break; - default: - ccprintf("Unknown value: 0x%0x", res_reg[0]); - } - ccprintf("\n"); - - if (res_reg[1]) - ccprintf("Affected port %d\n", res_reg[1]); - -exit: - /* Try to clear interrupt */ - buf = GL3590_INT_CLEAR; - gl3590_write(hub, GL3590_INT_REG, &buf, sizeof(buf)); -} - -enum ec_error_list gl3590_ufp_pwr(int hub, struct pwr_con_t *pwr) -{ - uint8_t hub_sts, hub_mode; - int rv = 0; - struct uhub_i2c_iface_t *uhub_p = &uhub_config[hub]; - - if (!uhub_p->initialized) - return EC_ERROR_HW_INTERNAL; - - if (gl3590_read(hub, GL3590_HUB_STS_REG, &hub_sts, sizeof(hub_sts))) { - CPRINTF("Error reading HUB_STS %d\n", rv); - return EC_ERROR_BUSY; - } - - pwr->volts = 5; - - switch ((hub_sts & GL3590_HUB_STS_HOST_PWR_MASK) >> - GL3590_HUB_STS_HOST_PWR_SHIFT) { - case GL3590_DEFAULT_HOST_PWR_SRC: - if (gl3590_read(hub, GL3590_HUB_MODE_REG, &hub_mode, - sizeof(hub_mode))) { - CPRINTF("Error reading HUB_MODE %d\n", rv); - return EC_ERROR_BUSY; - } - if (hub_mode & GL3590_HUB_MODE_USB3_EN) { - pwr->milli_amps = 900; - return EC_SUCCESS; - } else if (hub_mode & GL3590_HUB_MODE_USB2_EN) { - pwr->milli_amps = 500; - return EC_SUCCESS; - } else { - CPRINTF("GL3590: Neither USB3 nor USB2 hubs " - "configured\n"); - return EC_ERROR_HW_INTERNAL; - } - case GL3590_1_5_A_HOST_PWR_SRC: - pwr->milli_amps = 1500; - return EC_SUCCESS; - case GL3590_3_0_A_HOST_PWR_SRC: - pwr->milli_amps = 3000; - return EC_SUCCESS; - default: - CPRINTF("GL3590: Unkown host power source %d\n", hub_sts); - return EC_ERROR_UNKNOWN; - } -} - -#define GL3590_EN_PORT_MAX_RETRY_COUNT 10 - -int gl3590_enable_ports(int hub, uint8_t port_mask, bool enable) -{ - uint8_t buf[4] = {0}; - uint8_t en_mask = 0; - uint8_t tmp; - int rv, i; - struct uhub_i2c_iface_t *uhub_p = &uhub_config[hub]; - - if (!uhub_p->initialized) - return EC_ERROR_HW_INTERNAL; - - if (!enable) - en_mask = port_mask; - - buf[0] = en_mask; - buf[2] = port_mask; - - for (i = 1; i <= GL3590_EN_PORT_MAX_RETRY_COUNT; i++) { - rv = gl3590_write(hub, GL3590_PORT_DISABLED_REG, buf, - sizeof(buf)); - if (rv) - return rv; - - usleep(200 * MSEC); - - /* Verify whether port is enabled/disabled */ - rv = gl3590_read(hub, GL3590_PORT_EN_STS_REG, &tmp, 1); - if (rv) - return rv; - - if (enable && ((tmp & port_mask) == port_mask)) - break; - if (!enable && ((tmp & port_mask) == 0)) - break; - - if (i > GL3590_EN_PORT_MAX_RETRY_COUNT) { - CPRINTF("GL3590: Failed to %s port 0x%x\n", - enable ? "enable" : "disable", port_mask); - return EC_ERROR_HW_INTERNAL; - } - - CPRINTF("GL3590: Port %s retrying.. %d/%d\n" - "Port status is 0x%x\n", enable ? "enable" : "disable", - i, GL3590_EN_PORT_MAX_RETRY_COUNT, tmp); - } - - return EC_SUCCESS; -} - -#ifdef CONFIG_CMD_GL3590 -static int command_gl3590(int argc, char **argv) -{ - char *e; - int port; - - if (argc < 2) - return EC_ERROR_PARAM_COUNT; - - port = strtoi(argv[2], &e, 0); - if (*e) - return EC_ERROR_PARAM2; - - if (strcasecmp(argv[1], "enable") == 0) { - if (!gl3590_enable_ports(0, port, 1)) - return EC_SUCCESS; - else - return EC_ERROR_HW_INTERNAL; - } else if (strcasecmp(argv[1], "disable") == 0) { - if (!gl3590_enable_ports(0, port, 0)) - return EC_SUCCESS; - else - return EC_ERROR_HW_INTERNAL; - } - - return EC_ERROR_PARAM1; -} -DECLARE_CONSOLE_COMMAND(gl3590, command_gl3590, - "<enable | disable> <port_bitmask>", - "Manage GL3590 USB3.1 hub and its ports"); -#endif /* CONFIG_CMD_GL3590 */ |