diff options
Diffstat (limited to 'board/moonbuggy/pse.c')
-rw-r--r-- | board/moonbuggy/pse.c | 266 |
1 files changed, 0 insertions, 266 deletions
diff --git a/board/moonbuggy/pse.c b/board/moonbuggy/pse.c deleted file mode 100644 index 1c1b6bb41b..0000000000 --- a/board/moonbuggy/pse.c +++ /dev/null @@ -1,266 +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. - */ - -/* - * The LTC4291 is a power over ethernet (PoE) power sourcing equipment (PSE) - * controller. - */ - -#include "common.h" -#include "console.h" -#include "ec_commands.h" -#include "hooks.h" -#include "host_command.h" -#include "i2c.h" -#include "string.h" -#include "timer.h" -#include "util.h" - -#define LTC4291_I2C_ADDR 0x2C - -#define LTC4291_REG_SUPEVN_COR 0x0B -#define LTC4291_REG_STATPWR 0x10 -#define LTC4291_REG_STATPIN 0x11 -#define LTC4291_REG_OPMD 0x12 -#define LTC4291_REG_DISENA 0x13 -#define LTC4291_REG_DETENA 0x14 -#define LTC4291_REG_DETPB 0x18 -#define LTC4291_REG_PWRPB 0x19 -#define LTC4291_REG_RSTPB 0x1A -#define LTC4291_REG_ID 0x1B -#define LTC4291_REG_DEVID 0x43 -#define LTC4291_REG_HPMD1 0x46 -#define LTC4291_REG_HPMD2 0x4B -#define LTC4291_REG_HPMD3 0x50 -#define LTC4291_REG_HPMD4 0x55 -#define LTC4291_REG_LPWRPB 0x6E - -#define LTC4291_FLD_STATPIN_AUTO BIT(0) -#define LTC4291_FLD_RSTPB_RSTALL BIT(4) - -#define LTC4291_STATPWR_ON_PORT(port) (0x01 << (port)) -#define LTC4291_DETENA_EN_PORT(port) (0x11 << (port)) -#define LTC4291_DETPB_EN_PORT(port) (0x11 << (port)) -#define LTC4291_PWRPB_OFF_PORT(port) (0x10 << (port)) - -#define LTC4291_OPMD_AUTO 0xFF -#define LTC4291_DISENA_ALL 0x0F -#define LTC4291_DETENA_ALL 0xFF -#define LTC4291_ID 0x64 -#define LTC4291_DEVID 0x38 -#define LTC4291_HPMD_MIN 0x00 -#define LTC4291_HPMD_MAX 0xA8 - -#define LTC4291_PORT_MAX 4 - -#define LTC4291_RESET_DELAY_US (20 * MSEC) - -#define I2C_PSE_READ(reg, data) \ - i2c_read8(I2C_PORT_PSE, LTC4291_I2C_ADDR, LTC4291_REG_##reg, (data)) - -#define I2C_PSE_WRITE(reg, data) \ - i2c_write8(I2C_PORT_PSE, LTC4291_I2C_ADDR, LTC4291_REG_##reg, (data)) - -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) - -static int pse_write_hpmd(int port, int val) -{ - switch (port) { - case 0: - return I2C_PSE_WRITE(HPMD1, val); - case 1: - return I2C_PSE_WRITE(HPMD2, val); - case 2: - return I2C_PSE_WRITE(HPMD3, val); - case 3: - return I2C_PSE_WRITE(HPMD4, val); - default: - return EC_ERROR_INVAL; - } -} - -/* - * Port 1: 100W - * Port 2-4: 15W - */ -static int pse_port_hpmd[4] = { - LTC4291_HPMD_MAX, - LTC4291_HPMD_MIN, - LTC4291_HPMD_MIN, - LTC4291_HPMD_MIN, -}; - -static int pse_port_enable(int port) -{ - /* Enable detection and classification */ - return I2C_PSE_WRITE(DETPB, LTC4291_DETPB_EN_PORT(port)); -} - -static int pse_port_disable(int port) -{ - /* Request power off (this also disables detection/classification) */ - return I2C_PSE_WRITE(PWRPB, LTC4291_PWRPB_OFF_PORT(port)); -} - -static int pse_init_worker(void) -{ - timestamp_t deadline; - int err, id, devid, statpin, port; - - /* Ignore errors -- may already be resetting */ - I2C_PSE_WRITE(RSTPB, LTC4291_FLD_RSTPB_RSTALL); - - deadline.val = get_time().val + LTC4291_RESET_DELAY_US; - while ((err = I2C_PSE_READ(ID, &id)) != 0) { - if (timestamp_expired(deadline, NULL)) - return err; - } - - err = I2C_PSE_READ(DEVID, &devid); - if (err != 0) - return err; - - if (id != LTC4291_ID || devid != LTC4291_DEVID) - return EC_ERROR_INVAL; - - err = I2C_PSE_READ(STATPIN, &statpin); - if (err != 0) - return err; - - /* - * We don't want to supply power until we've had a chance to set the - * limits. - */ - if (statpin & LTC4291_FLD_STATPIN_AUTO) - CPRINTS("WARN: PSE reset in AUTO mode"); - - err = I2C_PSE_WRITE(OPMD, LTC4291_OPMD_AUTO); - if (err != 0) - return err; - - /* Set maximum power each port is allowed to allocate. */ - for (port = 0; port < LTC4291_PORT_MAX; port++) { - err = pse_write_hpmd(port, pse_port_hpmd[port]); - if (err != 0) - return err; - } - - err = I2C_PSE_WRITE(DISENA, LTC4291_DISENA_ALL); - if (err != 0) - return err; - - err = I2C_PSE_WRITE(DETENA, LTC4291_DETENA_ALL); - if (err != 0) - return err; - - return 0; -} - -static void pse_init(void) -{ - int err; - - err = pse_init_worker(); - if (err != 0) - CPRINTS("PSE init failed: %d", err); - else - CPRINTS("PSE init done"); -} -DECLARE_HOOK(HOOK_CHIPSET_RESUME, pse_init, HOOK_PRIO_DEFAULT); - -/* Also reset the PSE on a reboot to toggle the power. */ -DECLARE_HOOK(HOOK_CHIPSET_RESET, pse_init, HOOK_PRIO_DEFAULT); - -static int command_pse(int argc, char **argv) -{ - int port; - - /* - * TODO(b/156399232): endeavour: PSE controller reset by PLTRST - * - * Initialization does not reliably work after reset because the device - * is held in reset by the AP. Running this command after boot finishes - * always succeeds. Remove once the reset signal changes. - */ - if (!strncmp(argv[1], "init", 4)) - return pse_init_worker(); - - if (argc != 3) - return EC_ERROR_PARAM_COUNT; - - port = atoi(argv[1]); - if (port < 0 || port >= LTC4291_PORT_MAX) - return EC_ERROR_PARAM1; - - if (!strncmp(argv[2], "off", 3)) - return pse_port_disable(port); - else if (!strncmp(argv[2], "on", 2)) - return pse_port_enable(port); - else if (!strncmp(argv[2], "min", 3)) - return pse_write_hpmd(port, LTC4291_HPMD_MIN); - else if (!strncmp(argv[2], "max", 3)) - return pse_write_hpmd(port, LTC4291_HPMD_MAX); - else - return EC_ERROR_PARAM2; -} -DECLARE_CONSOLE_COMMAND(pse, command_pse, - "<port# 0-3> <off | on | min | max>", - "Set PSE port power"); - -static int ec_command_pse_status(int port, uint8_t *status) -{ - int detena, statpwr; - int err; - - err = I2C_PSE_READ(DETENA, &detena); - if (err != 0) - return err; - - err = I2C_PSE_READ(STATPWR, &statpwr); - if (err != 0) - return err; - - if ((detena & LTC4291_DETENA_EN_PORT(port)) == 0) - *status = EC_PSE_STATUS_DISABLED; - else if ((statpwr & LTC4291_STATPWR_ON_PORT(port)) == 0) - *status = EC_PSE_STATUS_ENABLED; - else - *status = EC_PSE_STATUS_POWERED; - - return 0; -} - -static enum ec_status ec_command_pse(struct host_cmd_handler_args *args) -{ - const struct ec_params_pse *p = args->params; - int err = 0; - - if (p->port >= LTC4291_PORT_MAX) - return EC_RES_INVALID_PARAM; - - switch (p->cmd) { - case EC_PSE_STATUS: { - struct ec_response_pse_status *r = args->response; - - args->response_size = sizeof(*r); - err = ec_command_pse_status(p->port, &r->status); - break; - } - case EC_PSE_ENABLE: - err = pse_port_enable(p->port); - break; - case EC_PSE_DISABLE: - err = pse_port_disable(p->port); - break; - default: - return EC_RES_INVALID_PARAM; - } - - if (err) - return EC_RES_ERROR; - - return EC_RES_SUCCESS; -} -DECLARE_HOST_COMMAND(EC_CMD_PSE, ec_command_pse, EC_VER_MASK(0)); |