Skip to content

Commit 90c65cf

Browse files
barnas-michalcarlescufi
authored andcommitted
usbc: add support for vbus measurement using TCPCI compliant device
Add support for VBUS measuring part of the TCPCI compliant device. This device should be used as a child-node for the more specific TCPC driver and referenced by the vbus property in the usb-c connector node. Signed-off-by: Michał Barnaś <[email protected]>
1 parent 198e040 commit 90c65cf

File tree

5 files changed

+133
-0
lines changed

5 files changed

+133
-0
lines changed

drivers/usb_c/vbus/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ zephyr_library()
44

55
zephyr_library_sources_ifdef(CONFIG_USBC_VBUS_ADC usbc_vbus_adc.c)
66
zephyr_library_sources_ifdef(CONFIG_USBC_VBUS_NUMAKER usbc_vbus_numaker.c)
7+
zephyr_library_sources_ifdef(CONFIG_USBC_VBUS_TCPCI usbc_vbus_tcpci.c)

drivers/usb_c/vbus/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ config USBC_VBUS_INIT_PRIORITY
1818

1919
source "drivers/usb_c/vbus/Kconfig.usbc_vbus_adc"
2020
source "drivers/usb_c/vbus/Kconfig.numaker"
21+
source "drivers/usb_c/vbus/Kconfig.usbc_vbus_tcpci"
2122

2223
endif # USBC_VBUS_DRIVER
2324

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# USB-C TCPCI VBUS device configuration options
2+
3+
# Copyright 2024 Google LLC
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
config USBC_VBUS_TCPCI
7+
bool "USB-C VBUS TCPCI"
8+
select USBC_TCPC_TCPCI
9+
default y
10+
depends on DT_HAS_ZEPHYR_USB_C_VBUS_TCPCI_ENABLED
11+
help
12+
Measure VBUS using the TCPC chip compliant to TCPCI

drivers/usb_c/vbus/usbc_vbus_tcpci.c

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#define DT_DRV_COMPAT zephyr_usb_c_vbus_tcpci
7+
8+
#include <zephyr/logging/log.h>
9+
LOG_MODULE_REGISTER(usbc_vbus_tcpci, CONFIG_USBC_LOG_LEVEL);
10+
11+
#include <zephyr/device.h>
12+
#include <zephyr/kernel.h>
13+
#include <zephyr/drivers/i2c.h>
14+
#include <zephyr/drivers/usb_c/tcpci_priv.h>
15+
#include <zephyr/drivers/usb_c/usbc_vbus.h>
16+
#include <zephyr/drivers/usb_c/usbc_pd.h>
17+
#include <zephyr/usb_c/tcpci.h>
18+
19+
/** Configuration structure for device instances */
20+
struct vbus_tcpci_cfg {
21+
/** I2C bus and address used for communication, set from parent node of device. */
22+
const struct i2c_dt_spec i2c;
23+
};
24+
25+
static int tcpci_measure(const struct device *dev, int *vbus_meas)
26+
{
27+
const struct vbus_tcpci_cfg *cfg = dev->config;
28+
uint16_t measure;
29+
int ret;
30+
31+
__ASSERT(vbus_meas != NULL, "TCPCI VBUS meas must not be NULL");
32+
33+
ret = tcpci_read_reg16(&cfg->i2c, TCPC_REG_VBUS_VOLTAGE, &measure);
34+
if (ret != 0) {
35+
return ret;
36+
}
37+
38+
*vbus_meas = TCPC_REG_VBUS_VOLTAGE_VBUS(measure);
39+
40+
return 0;
41+
}
42+
43+
static bool tcpci_check_level(const struct device *dev, enum tc_vbus_level level)
44+
{
45+
int measure;
46+
int ret;
47+
48+
ret = tcpci_measure(dev, &measure);
49+
if (ret != 0) {
50+
return false;
51+
}
52+
53+
switch (level) {
54+
case TC_VBUS_SAFE0V:
55+
return (measure < PD_V_SAFE_0V_MAX_MV);
56+
case TC_VBUS_PRESENT:
57+
return (measure >= PD_V_SAFE_5V_MIN_MV);
58+
case TC_VBUS_REMOVED:
59+
return (measure < TC_V_SINK_DISCONNECT_MAX_MV);
60+
}
61+
62+
return false;
63+
}
64+
65+
static int tcpci_discharge(const struct device *dev, bool enable)
66+
{
67+
const struct vbus_tcpci_cfg *cfg = dev->config;
68+
69+
return tcpci_update_reg8(&cfg->i2c, TCPC_REG_POWER_CTRL,
70+
TCPC_REG_POWER_CTRL_FORCE_DISCHARGE,
71+
(enable) ? TCPC_REG_POWER_CTRL_FORCE_DISCHARGE : 0);
72+
}
73+
74+
static int tcpci_enable(const struct device *dev, bool enable)
75+
{
76+
const struct vbus_tcpci_cfg *cfg = dev->config;
77+
78+
return tcpci_update_reg8(&cfg->i2c, TCPC_REG_POWER_CTRL,
79+
TCPC_REG_POWER_CTRL_VBUS_VOL_MONITOR_DIS,
80+
(enable) ? 0 : TCPC_REG_POWER_CTRL_VBUS_VOL_MONITOR_DIS);
81+
}
82+
83+
static const struct usbc_vbus_driver_api vbus_tcpci_api = {.measure = tcpci_measure,
84+
.check_level = tcpci_check_level,
85+
.discharge = tcpci_discharge,
86+
.enable = tcpci_enable};
87+
88+
static int tcpci_init(const struct device *dev)
89+
{
90+
return 0;
91+
}
92+
93+
BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) > 0,
94+
"No compatible USB-C VBUS Measurement instance found");
95+
96+
#define VBUS_TCPCI_INIT_CFG(node) \
97+
{ \
98+
.i2c = {I2C_DT_SPEC_GET_ON_I2C(DT_PARENT(node))}, \
99+
}
100+
101+
#define DRIVER_INIT(inst) \
102+
static const struct vbus_tcpci_cfg drv_config_##inst = \
103+
VBUS_TCPCI_INIT_CFG(DT_DRV_INST(inst)); \
104+
DEVICE_DT_INST_DEFINE(inst, &tcpci_init, NULL, NULL, &drv_config_##inst, POST_KERNEL, \
105+
CONFIG_USBC_VBUS_INIT_PRIORITY, &vbus_tcpci_api);
106+
107+
DT_INST_FOREACH_STATUS_OKAY(DRIVER_INIT)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copyright 2024 Google LLC
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: |
5+
This device is used to measure VBUS on a Type-C Port and to
6+
discharge VBUS when needed.
7+
It should be used as a child node for a specific TCPCI compliant device. The I2C address is
8+
taken from the parent of this node.
9+
10+
compatible: "zephyr,usb-c-vbus-tcpci"
11+
12+
include: [base.yaml]

0 commit comments

Comments
 (0)