summaryrefslogtreecommitdiff
path: root/driver/gl3590.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/gl3590.c')
-rw-r--r--driver/gl3590.c346
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,
- &reg, 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 */