summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Huang <david.huang@quanta.corp-partner.google.com>2023-03-17 09:19:45 +0800
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-03-20 04:12:43 +0000
commit441ba1e1d063ff0bf8befd7055adf77a1e05794c (patch)
tree9b54bbb2e9f6c3f9ef381fa862f3ccb325d80752
parentef44ebdc0a74ddca5b8cf9722f0afe0cf858b70e (diff)
downloadchrome-ec-441ba1e1d063ff0bf8befd7055adf77a1e05794c.tar.gz
common: Move pse driver into driver place
Since there are more projects using this driver. Move it into driver place. BUG=b:273191751 BRANCH=None TEST=make buildall -j Change-Id: I50e2cb480a551ce19722edc2b6f70824f4b9147e Signed-off-by: David Huang <david.huang@quanta.corp-partner.google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4335461 Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
-rw-r--r--driver/build.mk3
-rw-r--r--driver/pse_ltc4291.c209
-rw-r--r--include/config.h3
-rw-r--r--include/driver/pse_ltc4291.h60
-rw-r--r--zephyr/CMakeLists.txt2
-rw-r--r--zephyr/Kconfig7
-rw-r--r--zephyr/shim/include/config_chip.h5
7 files changed, 289 insertions, 0 deletions
diff --git a/driver/build.mk b/driver/build.mk
index 23e6dcd149..3d3871e7ec 100644
--- a/driver/build.mk
+++ b/driver/build.mk
@@ -124,6 +124,9 @@ driver-$(CONFIG_GPU_NVIDIA)+=nvidia_gpu.o
# Voltage regulators
driver-$(CONFIG_REGULATOR_IR357X)+=regulator_ir357x.o
+# Power Sourcing Equipment
+driver-$(CONFIG_PSE_LTC4291)+=pse_ltc4291.o
+
# Temperature sensors
driver-$(CONFIG_TEMP_SENSOR_ADT7481)+=temp_sensor/adt7481.o
driver-$(CONFIG_TEMP_SENSOR_BD99992GW)+=temp_sensor/bd99992gw.o
diff --git a/driver/pse_ltc4291.c b/driver/pse_ltc4291.c
new file mode 100644
index 0000000000..80255eb501
--- /dev/null
+++ b/driver/pse_ltc4291.c
@@ -0,0 +1,209 @@
+/* Copyright 2023 The ChromiumOS Authors
+ * 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 "pse_ltc4291.h"
+#include "string.h"
+#include "timer.h"
+#include "util.h"
+
+#define CPRINTS(format, args...) cprints(CC_SYSTEM, "PSE: " 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;
+ }
+}
+
+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)) != EC_SUCCESS) {
+ if (timestamp_expired(deadline, NULL))
+ return EC_ERROR_TIMEOUT;
+ msleep(1);
+ }
+
+ err = I2C_PSE_READ(DEVID, &devid);
+ if (err != EC_SUCCESS)
+ return err;
+
+ if (id != LTC4291_ID || devid != LTC4291_DEVID)
+ return EC_ERROR_INVAL;
+
+ err = I2C_PSE_READ(STATPIN, &statpin);
+ if (err != EC_SUCCESS)
+ 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 != EC_SUCCESS)
+ 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 != EC_SUCCESS)
+ return err;
+ }
+
+ err = I2C_PSE_WRITE(DISENA, LTC4291_DISENA_ALL);
+ if (err != EC_SUCCESS)
+ return err;
+
+ err = I2C_PSE_WRITE(DETENA, LTC4291_DETENA_ALL);
+ if (err != EC_SUCCESS)
+ return err;
+
+ return EC_SUCCESS;
+}
+
+static void pse_init(void)
+{
+ int err;
+
+ err = pse_init_worker();
+ if (err != EC_SUCCESS)
+ 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, const char **argv)
+{
+ int port;
+
+ /*
+ * 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 != EC_SUCCESS)
+ return err;
+
+ err = I2C_PSE_READ(STATPWR, &statpwr);
+ if (err != EC_SUCCESS)
+ 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 EC_SUCCESS;
+}
+
+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));
diff --git a/include/config.h b/include/config.h
index af7ef8d94d..59900a7fcb 100644
--- a/include/config.h
+++ b/include/config.h
@@ -3748,6 +3748,9 @@
/* Support PS/2 interface */
#undef CONFIG_PS2
+/* Support Power Sourcing Equipment */
+#undef CONFIG_PSE_LTC4291
+
/*
* Define this option to enable programmable voltage detector which will
* trigger an interrupt when the voltage drops below a threshold specified
diff --git a/include/driver/pse_ltc4291.h b/include/driver/pse_ltc4291.h
new file mode 100644
index 0000000000..4db9ac4998
--- /dev/null
+++ b/include/driver/pse_ltc4291.h
@@ -0,0 +1,60 @@
+/* Copyright 2023 The ChromiumOS Authors
+ * 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 "i2c.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))
+
+extern const int pse_port_hpmd[LTC4291_PORT_MAX];
diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt
index 33dabdeba5..a9a8e6c4f0 100644
--- a/zephyr/CMakeLists.txt
+++ b/zephyr/CMakeLists.txt
@@ -376,6 +376,8 @@ if (CONFIG_PLATFORM_EC_HIBERNATE AND CONFIG_AP_PWRSEQ)
endif ()
zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_PANIC
"${PLATFORM_EC}/common/panic_output.c")
+zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_PSE_LTC4291
+ "${PLATFORM_EC}/driver/pse_ltc4291.c")
zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_SHA256_SW
"${PLATFORM_EC}/common/sha256.c")
zephyr_library_sources_ifdef(CONFIG_SOC_IT8XXX2_SHA256_HW_ACCELERATE
diff --git a/zephyr/Kconfig b/zephyr/Kconfig
index f8ae3553ab..5a4850da25 100644
--- a/zephyr/Kconfig
+++ b/zephyr/Kconfig
@@ -562,6 +562,13 @@ config PLATFORM_EC_BUTTON_DEBOUNCE
help
Configure the button debounce time in us per project requirement.
+config PLATFORM_EC_PSE_LTC4291
+ bool "power sourcing equipment (PSE) support"
+ help
+ Enable the power sourcing equipment (PSE) driver support for
+ Analog Device power over ethernet (PoE) power sourcing equipment (PSE)
+ controller.
+
config PLATFORM_EC_PWM_HC
bool
help
diff --git a/zephyr/shim/include/config_chip.h b/zephyr/shim/include/config_chip.h
index e073f13396..d8ef2b04f2 100644
--- a/zephyr/shim/include/config_chip.h
+++ b/zephyr/shim/include/config_chip.h
@@ -835,6 +835,11 @@ extern char mock_jump_data[CONFIG_PLATFORM_EC_PRESERVED_END_OF_RAM_SIZE];
#define CONFIG_BUTTON_TRIGGERED_RECOVERY
#endif
+#undef CONFIG_PSE_LTC4291
+#ifdef PLATFORM_EC_PSE_LTC4291
+#define CONFIG_PSE_LTC4291
+#endif
+
#undef CONFIG_PWM_KBLIGHT
#undef CONFIG_KEYBOARD_BACKLIGHT
#ifdef CONFIG_PLATFORM_EC_PWM_KBLIGHT