diff --git a/drivers/usb_c/ppc/CMakeLists.txt b/drivers/usb_c/ppc/CMakeLists.txt index cb3e4634496..dc3fc83988c 100644 --- a/drivers/usb_c/ppc/CMakeLists.txt +++ b/drivers/usb_c/ppc/CMakeLists.txt @@ -3,3 +3,4 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_USBC_PPC_SHELL shell.c) +zephyr_library_sources_ifdef(CONFIG_USBC_PPC_NX20P3483 nxp_nx20p3483.c) diff --git a/drivers/usb_c/ppc/Kconfig b/drivers/usb_c/ppc/Kconfig index da5364f5d45..c3fc93e1f4e 100644 --- a/drivers/usb_c/ppc/Kconfig +++ b/drivers/usb_c/ppc/Kconfig @@ -21,6 +21,8 @@ config USBC_PPC_SHELL help Add useful shell commands to manipulate and debug the PPCs +source "drivers/usb_c/ppc/Kconfig.nxp" + module = USBC_PPC module-str = usbc-ppc source "subsys/logging/Kconfig.template.log_config" diff --git a/drivers/usb_c/ppc/Kconfig.nxp b/drivers/usb_c/ppc/Kconfig.nxp new file mode 100644 index 00000000000..1d1de6a49e9 --- /dev/null +++ b/drivers/usb_c/ppc/Kconfig.nxp @@ -0,0 +1,20 @@ +# NXP NX20P3483 Configuration menu + +# Copyright 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +config USBC_PPC_NX20P3483 + bool "NXP NX20P3483 support" + default y + depends on DT_HAS_NXP_NX20P3483_ENABLED + help + Enable USB-C PPC support for NXP nx20p3483 chip + +if USBC_PPC_NX20P3483 + +config USBC_PPC_NX20P3483_DUMP_FULL_REG_NAMES + bool "Dump full register names" + help + Dump human-readable names instead of offsets of registers + +endif diff --git a/drivers/usb_c/ppc/nxp_nx20p3483.c b/drivers/usb_c/ppc/nxp_nx20p3483.c new file mode 100644 index 00000000000..8b6a2fe914d --- /dev/null +++ b/drivers/usb_c/ppc/nxp_nx20p3483.c @@ -0,0 +1,457 @@ +/* + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include "nxp_nx20p3483_priv.h" + +#define DT_DRV_COMPAT nxp_nx20p3483 +LOG_MODULE_REGISTER(nxp_nx20p3483, CONFIG_USBC_PPC_LOG_LEVEL); + +#ifdef CONFIG_USBC_PPC_NX20P3483_DUMP_FULL_REG_NAMES +static const char *const nx20p3483_reg_names[] = { + "Device ID ", "Device Status ", "Switch Control ", + "Switch Status ", "Interrupt 1 ", "Interrupt 2 ", + "Interrupt 1 Mask ", "Interrupt 2 Mask ", "OVLO Threshold ", + "HV SRC OCP Threshold", "5V SRC OCP Threshold", "Device Control ", +}; +#endif + +/* Driver structures */ + +struct nx20p3483_cfg { + /** Device address on I2C bus */ + const struct i2c_dt_spec bus; + /** GPIO used as interrupt request */ + const struct gpio_dt_spec irq_gpio; + + /** Overvoltage protection threshold for sink role */ + int snk_ovp_thresh; + /** Boolean value whether to use high-voltage source if true or 5V source if false */ + bool src_use_hv; + /** Overcurrent protection threshold for 5V source role */ + int src_5v_ocp_thresh; + /** Overcurrent protection threshold for HV source role */ + int src_hv_ocp_thresh; +}; + +struct nx20p3483_data { + /** Device structure to get from data structure */ + const struct device *dev; + /** Interrupt request callback object */ + struct gpio_callback irq_cb; + /** Workqueue object for handling interrupts */ + struct k_work irq_work; + + /** Callback used to notify about PPC events, like overcurrent or short */ + usbc_ppc_event_cb_t event_cb; + /** Data sent as parameter to the callback */ + void *event_cb_data; +}; + +/* Helper functions */ + +static int read_reg(const struct device *dev, uint8_t reg, uint8_t *value) +{ + const struct nx20p3483_cfg *cfg = dev->config; + int ret; + + ret = i2c_reg_read_byte(cfg->bus.bus, cfg->bus.addr, reg, value); + if (ret != 0) { + LOG_ERR("Error reading reg %02x: %d", reg, ret); + return ret; + } + + return 0; +} + +static int write_reg(const struct device *dev, uint8_t reg, uint8_t value) +{ + const struct nx20p3483_cfg *cfg = dev->config; + int ret; + + ret = i2c_reg_write_byte(cfg->bus.bus, cfg->bus.addr, reg, value); + if (ret != 0) { + LOG_ERR("Error writing reg %02x: %d", reg, ret); + return ret; + } + + return 0; +} + +static int nx20p3483_set_snk_ovp_limit(const struct device *dev, uint8_t u_thresh) +{ + int ret; + + if (u_thresh < NX20P3483_I_THRESHOLD_0_400 || u_thresh > NX20P3483_I_THRESHOLD_3_400) { + return -EINVAL; + } + + ret = write_reg(dev, NX20P3483_REG_OVLO_THRESHOLD, u_thresh); + if (ret != 0) { + LOG_ERR("Couldn't set SNK OVP: %d", ret); + return ret; + } + + LOG_DBG("Set SNK OVP: %d", u_thresh); + return 0; +} + +/* API functions */ + +int nx20p3483_is_dead_battery_mode(const struct device *dev) +{ + uint8_t sts_reg; + int ret; + + ret = read_reg(dev, NX20P3483_REG_DEVICE_STATUS, &sts_reg); + if (ret != 0) { + return ret; + } + + return ((sts_reg & NX20P3483_REG_DEVICE_STATUS_MODE_MASK) == NX20P3483_MODE_DEAD_BATTERY); +} + +int nx20p3483_exit_dead_battery_mode(const struct device *dev) +{ + uint8_t ctrl_reg; + int ret; + + ret = read_reg(dev, NX20P3483_REG_DEVICE_CTRL, &ctrl_reg); + if (ret != 0) { + return ret; + } + + ctrl_reg |= NX20P3483_REG_DEVICE_CTRL_DB_EXIT; + ret = write_reg(dev, NX20P3483_REG_DEVICE_CTRL, ctrl_reg); + if (ret != 0) { + return ret; + } + + return 0; +} + +static int nx20p3483_is_vbus_source(const struct device *dev) +{ + uint8_t sts_reg; + int ret; + + ret = read_reg(dev, NX20P3483_REG_SWITCH_STATUS, &sts_reg); + if (ret != 0) { + return ret; + } + + return !!(sts_reg & + (NX20P3483_REG_SWITCH_STATUS_5VSRC | NX20P3483_REG_SWITCH_STATUS_HVSRC)); +} + +static int nx20p3483_is_vbus_sink(const struct device *dev) +{ + uint8_t sts_reg; + int ret; + + ret = read_reg(dev, NX20P3483_REG_SWITCH_STATUS, &sts_reg); + if (ret != 0) { + return ret; + } + + return !!(sts_reg & NX20P3483_REG_SWITCH_STATUS_HVSNK); +} + +static int nx20p3483_set_vbus_sink(const struct device *dev, bool enable) +{ + const struct nx20p3483_cfg *cfg = dev->config; + + /* + * The nx20p3483 is enabled by external GPIO signal, however enabling it sets the + * overvoltage threshold to the highest possible value. Due to that, the threshold has + * to be set here again. Must be called after enabling the path by the external signal. + */ + return nx20p3483_set_snk_ovp_limit(dev, cfg->snk_ovp_thresh); +} + +static int nx20p3483_set_vbus_discharge(const struct device *dev, bool enable) +{ + uint8_t ctrl_reg; + int ret; + + ret = read_reg(dev, NX20P3483_REG_DEVICE_CTRL, &ctrl_reg); + if (ret != 0) { + return ret; + } + + if (enable) { + ctrl_reg |= NX20P3483_REG_DEVICE_CTRL_VBUSDIS_EN; + } else { + ctrl_reg &= ~NX20P3483_REG_DEVICE_CTRL_VBUSDIS_EN; + } + + ret = write_reg(dev, NX20P3483_REG_DEVICE_CTRL, ctrl_reg); + + return ret; +} + +static int nx20p3483_set_event_handler(const struct device *dev, usbc_ppc_event_cb_t handler, + void *handler_data) +{ + struct nx20p3483_data *data = dev->data; + + data->event_cb = handler; + data->event_cb_data = handler_data; + + return 0; +} + +static int nx20p3483_dump_regs(const struct device *dev) +{ + const struct nx20p3483_cfg *cfg = dev->config; + uint8_t val; + + LOG_INF("NX20P alert: %d", gpio_pin_get(cfg->irq_gpio.port, cfg->irq_gpio.pin)); + LOG_INF("PPC %s:%s registers:", cfg->bus.bus->name, dev->name); + for (int a = 0; a <= NX20P3483_REG_DEVICE_CTRL; a++) { + i2c_reg_read_byte(cfg->bus.bus, cfg->bus.addr, a, &val); + +#ifdef CONFIG_USBC_PPC_NX20P3483_DUMP_FULL_REG_NAMES + LOG_INF("- [%s] = 0x%02x", nx20p3483_reg_names[a], val); +#else + LOG_INF("- [%02x] = 0x%02x", a, val); +#endif + } + + return 0; +} + +static struct usbc_ppc_drv nx20p3483_driver_api = { + .is_dead_battery_mode = nx20p3483_is_dead_battery_mode, + .exit_dead_battery_mode = nx20p3483_exit_dead_battery_mode, + .is_vbus_source = nx20p3483_is_vbus_source, + .is_vbus_sink = nx20p3483_is_vbus_sink, + .set_snk_ctrl = nx20p3483_set_vbus_sink, + .set_vbus_discharge = nx20p3483_set_vbus_discharge, + .set_event_handler = nx20p3483_set_event_handler, + .dump_regs = nx20p3483_dump_regs, +}; + +static int nx20p3483_set_src_ovc_limit(const struct device *dev, uint8_t i_thresh_5v, + uint8_t i_thresh_hv) +{ + int ret; + + if (i_thresh_5v < NX20P3483_I_THRESHOLD_0_400 || + i_thresh_5v > NX20P3483_I_THRESHOLD_3_400) { + LOG_ERR("Invalid SRC 5V ovc threshold: %d", i_thresh_5v); + return -EINVAL; + } + + if (i_thresh_hv < NX20P3483_I_THRESHOLD_0_400 || + i_thresh_hv > NX20P3483_I_THRESHOLD_3_400) { + LOG_ERR("Invalid SRC HV ovc threshold: %d", i_thresh_hv); + return -EINVAL; + } + + ret = write_reg(dev, NX20P3483_REG_5V_SRC_OCP_THRESHOLD, i_thresh_5v); + if (ret != 0) { + return ret; + } + + ret = write_reg(dev, NX20P3483_REG_HV_SRC_OCP_THRESHOLD, i_thresh_hv); + if (ret != 0) { + return ret; + } + + LOG_DBG("Set SRC OVC 5V: %d, HV: %d", i_thresh_5v, i_thresh_hv); + return 0; +} + +static void nx20p3483_send_event(const struct device *dev, enum usbc_ppc_event ev) +{ + struct nx20p3483_data *data = dev->data; + + if (data->event_cb != NULL) { + data->event_cb(dev, data->event_cb_data, ev); + } +} + +static void nx20p3483_irq_handler(const struct device *port, struct gpio_callback *cb, + gpio_port_pins_t pins) +{ + struct nx20p3483_data *data = CONTAINER_OF(cb, struct nx20p3483_data, irq_cb); + + k_work_submit(&data->irq_work); +} + +static void nx20p3483_irq_worker(struct k_work *work) +{ + struct nx20p3483_data *data = CONTAINER_OF(work, struct nx20p3483_data, irq_work); + const struct device *dev = data->dev; + uint8_t irq1, irq2; + int ret; + + ret = read_reg(dev, NX20P3483_REG_INT1, &irq1); + if (ret != 0) { + LOG_ERR("Couldn't read irq1"); + return; + } + + ret = read_reg(dev, NX20P3483_REG_INT2, &irq2); + if (ret != 0) { + LOG_ERR("Couldn't read irq2"); + return; + } + + if (data->event_cb == NULL) { + LOG_DBG("No callback set: %02x %02x", irq1, irq1); + } + + /* Generic alerts */ + if (irq1 & NX20P3483_REG_INT1_DBEXIT_ERR) { + LOG_INF("PPC dead battery exit failed"); + nx20p3483_send_event(dev, USBC_PPC_EVENT_DEAD_BATTERY_ERROR); + } + + if (irq1 & NX20P3483_REG_INT1_OTP) { + LOG_INF("PPC over temperature"); + nx20p3483_send_event(dev, USBC_PPC_EVENT_OVER_TEMPERATURE); + } + + if (irq1 & NX20P3483_REG_INT2_EN_ERR) { + LOG_INF("PPC source and sink enabled"); + nx20p3483_send_event(dev, USBC_PPC_EVENT_BOTH_SNKSRC_ENABLED); + } + + /* Source */ + if (irq1 & NX20P3483_REG_INT1_OV_5VSRC || irq2 & NX20P3483_REG_INT2_OV_HVSRC) { + LOG_INF("PPC source overvoltage"); + nx20p3483_send_event(dev, USBC_PPC_EVENT_SRC_OVERVOLTAGE); + } + + if (irq1 & NX20P3483_REG_INT1_RCP_5VSRC || irq2 & NX20P3483_REG_INT2_RCP_HVSRC) { + LOG_INF("PPC source reverse current"); + nx20p3483_send_event(dev, USBC_PPC_EVENT_SRC_REVERSE_CURRENT); + } + + if (irq1 & NX20P3483_REG_INT1_OC_5VSRC || irq2 & NX20P3483_REG_INT2_OC_HVSRC) { + LOG_INF("PPC source overcurrent"); + nx20p3483_send_event(dev, USBC_PPC_EVENT_SRC_OVERCURRENT); + } + + if (irq1 & NX20P3483_REG_INT1_SC_5VSRC || irq2 & NX20P3483_REG_INT2_SC_HVSRC) { + LOG_INF("PPC source short"); + nx20p3483_send_event(dev, USBC_PPC_EVENT_SRC_SHORT); + } + + /* Sink */ + if (irq2 & NX20P3483_REG_INT2_RCP_HVSNK) { + LOG_INF("PPC sink reverse current"); + nx20p3483_send_event(dev, USBC_PPC_EVENT_SNK_REVERSE_CURRENT); + } + + if (irq2 & NX20P3483_REG_INT2_SC_HVSNK) { + LOG_INF("PPC sink short"); + nx20p3483_send_event(dev, USBC_PPC_EVENT_SNK_SHORT); + } + + if (irq2 & NX20P3483_REG_INT2_OV_HVSNK) { + LOG_INF("PPC sink overvoltage"); + nx20p3483_send_event(dev, USBC_PPC_EVENT_SNK_OVERVOLTAGE); + } +} + +static int nx20p3483_dev_init(const struct device *dev) +{ + const struct nx20p3483_cfg *cfg = dev->config; + struct nx20p3483_data *data = dev->data; + uint8_t reg; + int ret; + + LOG_INF("Initializing PPC"); + + /* Initialize irq */ + ret = gpio_pin_configure(cfg->irq_gpio.port, cfg->irq_gpio.pin, GPIO_INPUT | GPIO_PULL_UP); + if (ret != 0) { + return ret; + } + + ret = gpio_pin_interrupt_configure(cfg->irq_gpio.port, cfg->irq_gpio.pin, + GPIO_INT_EDGE_FALLING); + if (ret != 0) { + return ret; + } + + gpio_init_callback(&data->irq_cb, nx20p3483_irq_handler, BIT(cfg->irq_gpio.pin)); + ret = gpio_add_callback(cfg->irq_gpio.port, &data->irq_cb); + if (ret != 0) { + return ret; + } + + /* Initialize work_q */ + k_work_init(&data->irq_work, nx20p3483_irq_worker); + k_work_submit(&data->irq_work); + + /* If src_use_hv, select the HV src path but do not enable it yet */ + read_reg(dev, NX20P3483_REG_SWITCH_CTRL, ®); + if (cfg->src_use_hv) { + reg |= NX20P3483_REG_SWITCH_CTRL_SRC; + } else { + reg &= ~NX20P3483_REG_SWITCH_CTRL_SRC; + } + + write_reg(dev, NX20P3483_REG_SWITCH_CTRL, reg); + + /* Set limits */ + ret = nx20p3483_set_snk_ovp_limit(dev, cfg->snk_ovp_thresh); + if (ret != 0) { + return ret; + } + + ret = nx20p3483_set_src_ovc_limit(dev, cfg->src_5v_ocp_thresh, cfg->src_hv_ocp_thresh); + if (ret != 0) { + return ret; + } + + return 0; +} + +#define NX20P3483_DRIVER_CFG_INIT(node) \ + { \ + .bus = I2C_DT_SPEC_GET(node), .irq_gpio = GPIO_DT_SPEC_GET(node, irq_gpios), \ + .snk_ovp_thresh = DT_PROP(node, snk_ovp), .src_use_hv = DT_PROP(node, src_hv), \ + .src_5v_ocp_thresh = DT_PROP(node, src_5v_ocp), \ + .src_hv_ocp_thresh = DT_PROP(node, src_hv_ocp), \ + } + +#define NX20P3483_DRIVER_CFG_ASSERTS(node) \ + BUILD_ASSERT(DT_PROP(node, snk_ovp) >= NX20P3483_U_THRESHOLD_6_0 && \ + DT_PROP(node, snk_ovp) <= NX20P3483_U_THRESHOLD_23_0, \ + "Invalid overvoltage threshold"); \ + BUILD_ASSERT(DT_PROP(node, src_5v_ocp) >= NX20P3483_I_THRESHOLD_0_400 && \ + DT_PROP(node, src_5v_ocp) <= NX20P3483_I_THRESHOLD_3_400, \ + "Invalid overcurrent threshold"); \ + BUILD_ASSERT(DT_PROP(node, src_hv_ocp) >= NX20P3483_I_THRESHOLD_0_400 && \ + DT_PROP(node, src_hv_ocp) <= NX20P3483_I_THRESHOLD_3_400, \ + "Invalid overcurrent threshold"); + +#define NX20P3483_DRIVER_DATA_INIT(node) \ + { \ + .dev = DEVICE_DT_GET(node), \ + } + +#define NX20P3483_DRIVER_INIT(inst) \ + static struct nx20p3483_data drv_data_nx20p3483##inst = \ + NX20P3483_DRIVER_DATA_INIT(DT_DRV_INST(inst)); \ + NX20P3483_DRIVER_CFG_ASSERTS(DT_DRV_INST(inst)); \ + static struct nx20p3483_cfg drv_cfg_nx20p3483##inst = \ + NX20P3483_DRIVER_CFG_INIT(DT_DRV_INST(inst)); \ + DEVICE_DT_INST_DEFINE(inst, &nx20p3483_dev_init, NULL, &drv_data_nx20p3483##inst, \ + &drv_cfg_nx20p3483##inst, POST_KERNEL, \ + CONFIG_USBC_PPC_INIT_PRIORITY, &nx20p3483_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(NX20P3483_DRIVER_INIT) diff --git a/drivers/usb_c/ppc/nxp_nx20p3483_priv.h b/drivers/usb_c/ppc/nxp_nx20p3483_priv.h new file mode 100644 index 00000000000..b033be4a730 --- /dev/null +++ b/drivers/usb_c/ppc/nxp_nx20p3483_priv.h @@ -0,0 +1,127 @@ +/* + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief NX20P3483 PPC registers definitions + */ + +#ifndef ZEPHYR_DRIVERS_USBC_PPC_NXP_NX20P3483_PRIV_H_ +#define ZEPHYR_DRIVERS_USBC_PPC_NXP_NX20P3483_PRIV_H_ + +#include + +/** Register address - device id */ +#define NX20P3483_REG_DEVICE_ID 0x00 +/** Bit mask for vendor id */ +#define NX20P3483_REG_DEVICE_ID_VENDOR_MASK GENMASK(7, 3) +/** Bit mask for version id */ +#define NX20P3483_REG_DEVICE_ID_REVISION_MASK GENMASK(2, 0) + +/** Register address - device status */ +#define NX20P3483_REG_DEVICE_STATUS 0x01 +/** Bit mask for device mode */ +#define NX20P3483_REG_DEVICE_STATUS_MODE_MASK GENMASK(2, 0) + +/** Value for dead battery mode */ +#define NX20P3483_MODE_DEAD_BATTERY 0 +/** Value for high-voltage sink mode */ +#define NX20P3483_MODE_HV_SNK 1 +/** Value for 5V source mode */ +#define NX20P3483_MODE_5V_SRC 2 +/** Value for high-voltage source mode */ +#define NX20P3483_MODE_HV_SRC 3 +/** Value for standby mode */ +#define NX20P3483_MODE_STANDBY 4 + +/** Register address - switch control */ +#define NX20P3483_REG_SWITCH_CTRL 0x02 +/** Bit field for source path selection. If set, HV source path is selected, 5V otherwise. */ +#define NX20P3483_REG_SWITCH_CTRL_SRC BIT(7) + +/** Register address - switch status */ +#define NX20P3483_REG_SWITCH_STATUS 0x03 +/** Bit field for 5V source switch enabled */ +#define NX20P3483_REG_SWITCH_STATUS_5VSRC BIT(2) +/** Bit field for HV source switch enabled */ +#define NX20P3483_REG_SWITCH_STATUS_HVSRC BIT(1) +/** Bit field for HV sink switch enabled */ +#define NX20P3483_REG_SWITCH_STATUS_HVSNK BIT(0) + +/** Register address - interrupt1 */ +#define NX20P3483_REG_INT1 0x04 +/** Bit field for exit dead battery error */ +#define NX20P3483_REG_INT1_DBEXIT_ERR BIT(7) +/** Bit field for overvoltage fault triggered on 5V source path */ +#define NX20P3483_REG_INT1_OV_5VSRC BIT(4) +/** Bit field for reverse current fault triggered on 5V source path */ +#define NX20P3483_REG_INT1_RCP_5VSRC BIT(3) +/** Bit field for short circuit fault triggered on 5V source path */ +#define NX20P3483_REG_INT1_SC_5VSRC BIT(2) +/** Bit field for overcurrent fault triggered on 5V source path */ +#define NX20P3483_REG_INT1_OC_5VSRC BIT(1) +/** Bit field for over temperature protection fault triggered */ +#define NX20P3483_REG_INT1_OTP BIT(0) + +/** Register address - interrupt2*/ +#define NX20P3483_REG_INT2 0x05 +/** Bit field for sink and source routes enabled fault */ +#define NX20P3483_REG_INT2_EN_ERR BIT(7) +/** Bit field for reverse current fault triggered on HV sink path */ +#define NX20P3483_REG_INT2_RCP_HVSNK BIT(6) +/** Bit field for short circuit fault triggered on HV sink path */ +#define NX20P3483_REG_INT2_SC_HVSNK BIT(5) +/** Bit field for overvoltage fault triggered on HV sink path */ +#define NX20P3483_REG_INT2_OV_HVSNK BIT(4) +/** Bit field for reverse current fault triggered on HV source path */ +#define NX20P3483_REG_INT2_RCP_HVSRC BIT(3) +/** Bit field for short circuit fault triggered on HV source path */ +#define NX20P3483_REG_INT2_SC_HVSRC BIT(2) +/** Bit field for overcurrent fault triggered on HV source path */ +#define NX20P3483_REG_INT2_OC_HVSRC BIT(1) +/** Bit field for overvoltage fault triggered on HV source path */ +#define NX20P3483_REG_INT2_OV_HVSRC BIT(0) + +/** Register address - interrupt1 mask */ +#define NX20P3483_REG_INT1_MASK 0x06 + +/** Register address - interrupt2 mask*/ +#define NX20P3483_REG_INT2_MASK 0x07 + +/** Register address - OVLO threshold (overvoltage threshold) */ +#define NX20P3483_REG_OVLO_THRESHOLD 0x08 +/** + * Bit mask for overvoltage threshold value + * Values used in this register are defined as NX20P3483_U_THRESHOLD_* + */ +#define NX20P3483_REG_OVLO_THRESHOLD_MASK GENMASK(2, 0) + +/* Internal 5V VBUS Switch Current Limit Settings (min) */ +#define NX20P3483_ILIM_MASK 0xF + +/** + * Register address - HV source switch OCP threshold + * Values used in this register are defined as NX20P3483_I_THRESHOLD_* + */ +#define NX20P3483_REG_HV_SRC_OCP_THRESHOLD 0x09 + +/** + * Register address - 5V source switch OCP threshold + * Values used in this register are defined as NX20P3483_I_THRESHOLD_* + */ +#define NX20P3483_REG_5V_SRC_OCP_THRESHOLD 0x0A + +/** Register address - device control */ +#define NX20P3483_REG_DEVICE_CTRL 0x0B +/** Bit field for fast role swap capability activated */ +#define NX20P3483_REG_DEVICE_CTRL_FRS_AT BIT(3) +/** Bit field for exit dead battery mode */ +#define NX20P3483_REG_DEVICE_CTRL_DB_EXIT BIT(2) +/** Bit field for VBUS discharge circuit enabled */ +#define NX20P3483_REG_DEVICE_CTRL_VBUSDIS_EN BIT(1) +/** Bit field for LDO shutdown */ +#define NX20P3483_REG_DEVICE_CTRL_LDO_SD BIT(0) + +#endif /* ZEPHYR_DRIVERS_USBC_PPC_NXP_NX20P3483_PRIV_H_ */ diff --git a/dts/bindings/ppc/nxp,nx20p3483.yaml b/dts/bindings/ppc/nxp,nx20p3483.yaml new file mode 100644 index 00000000000..c705ac32c33 --- /dev/null +++ b/dts/bindings/ppc/nxp,nx20p3483.yaml @@ -0,0 +1,39 @@ +# Copyright 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +description: NXP NX20P3483 Power path controller chip + +compatible: "nxp,nx20p3483" + +include: [base.yaml, i2c-device.yaml] + +properties: + irq-gpios: + type: phandle-array + description: Interrupt pin + + snk-ovp: + type: int + default: 1 + description: + Sink high-voltage overvoltage protection threshold in millivolts. + This value must be set using one of the NX20P348X_U_THRESHOLD_* defines. + + src-hv: + type: boolean + description: + If set, source role will use high-voltage path instead of 5V. + + src-hv-ocp: + type: int + default: 6 + description: + Source high-voltage overcurrent protection threshold in milliamperes. + This value must be set using one of the NX20P348X_I_THRESHOLD_* defines. + + src-5v-ocp: + type: int + default: 6 + description: + Source 5V overcurrent protection threshold in milliamperes. + This value must be set using one of the NX20P348X_I_THRESHOLD_* defines. diff --git a/include/zephyr/dt-bindings/usb-c/nxp_nx20p3483.h b/include/zephyr/dt-bindings/usb-c/nxp_nx20p3483.h new file mode 100644 index 00000000000..e25db0a1431 --- /dev/null +++ b/include/zephyr/dt-bindings/usb-c/nxp_nx20p3483.h @@ -0,0 +1,62 @@ +/* + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Values used to define the sink overvoltage and source overcurrent protections thresholds. + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_USBC_NXP_NX20P3483_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_USBC_NXP_NX20P3483_H_ + +/** Voltage limit of 6.0V */ +#define NX20P3483_U_THRESHOLD_6_0 0 +/** Voltage limit of 6.8V */ +#define NX20P3483_U_THRESHOLD_6_8 1 /* <-- default */ +/** Voltage limit of 10.0V */ +#define NX20P3483_U_THRESHOLD_10_0 2 +/** Voltage limit of 11.5V */ +#define NX20P3483_U_THRESHOLD_11_5 3 +/** Voltage limit of 14.0V */ +#define NX20P3483_U_THRESHOLD_14_0 4 +/** Voltage limit of 17.0V */ +#define NX20P3483_U_THRESHOLD_17_0 5 +/** Voltage limit of 23.0V */ +#define NX20P3483_U_THRESHOLD_23_0 6 + +/** Current limit of 400mA */ +#define NX20P3483_I_THRESHOLD_0_400 0 +/** Current limit of 600mA */ +#define NX20P3483_I_THRESHOLD_0_600 1 +/** Current limit of 800mA */ +#define NX20P3483_I_THRESHOLD_0_800 2 +/** Current limit of 1000mA */ +#define NX20P3483_I_THRESHOLD_1_000 3 +/** Current limit of 1200mA */ +#define NX20P3483_I_THRESHOLD_1_200 4 +/** Current limit of 1400mA */ +#define NX20P3483_I_THRESHOLD_1_400 5 +/** Current limit of 1600mA */ +#define NX20P3483_I_THRESHOLD_1_600 6 /* <-- default */ +/** Current limit of 1800mA */ +#define NX20P3483_I_THRESHOLD_1_800 7 +/** Current limit of 2000mA */ +#define NX20P3483_I_THRESHOLD_2_000 8 +/** Current limit of 2200mA */ +#define NX20P3483_I_THRESHOLD_2_200 9 +/** Current limit of 2400mA */ +#define NX20P3483_I_THRESHOLD_2_400 10 +/** Current limit of 2600mA */ +#define NX20P3483_I_THRESHOLD_2_600 11 +/** Current limit of 2800mA */ +#define NX20P3483_I_THRESHOLD_2_800 12 +/** Current limit of 3000mA */ +#define NX20P3483_I_THRESHOLD_3_000 13 +/** Current limit of 3200mA */ +#define NX20P3483_I_THRESHOLD_3_200 14 +/** Current limit of 3400mA */ +#define NX20P3483_I_THRESHOLD_3_400 15 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_USBC_NXP_NX20P3483_H_ */