Browse Source
Add driver for NXP nx20p3483 power path controller that can be used to control and protect sink and source path of USB-C connector. Signed-off-by: Michał Barnaś <mb@semihalf.com>pull/67772/head
7 changed files with 708 additions and 0 deletions
@ -0,0 +1,20 @@
@@ -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 |
@ -0,0 +1,457 @@
@@ -0,0 +1,457 @@
|
||||
/*
|
||||
* Copyright 2023 Google LLC |
||||
* SPDX-License-Identifier: Apache-2.0 |
||||
*/ |
||||
|
||||
#include <zephyr/device.h> |
||||
#include <zephyr/logging/log.h> |
||||
#include <zephyr/drivers/gpio.h> |
||||
#include <zephyr/drivers/i2c.h> |
||||
#include <zephyr/shell/shell.h> |
||||
#include <zephyr/drivers/usb_c/usbc_ppc.h> |
||||
|
||||
#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) |
@ -0,0 +1,127 @@
@@ -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<zephyr/dt-bindings/usb-c/nxp_nx20p3483.h> |
||||
|
||||
/** 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_ */ |
@ -0,0 +1,39 @@
@@ -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. |
@ -0,0 +1,62 @@
@@ -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_ */ |
Loading…
Reference in new issue