summaryrefslogtreecommitdiff
path: root/driver/tcpm
diff options
context:
space:
mode:
authorTing Shen <phoenixshen@google.com>2021-07-20 17:18:25 +0800
committerCommit Bot <commit-bot@chromium.org>2021-08-13 10:20:33 +0000
commitf00ea7bb8f9d7f835981d969294fef0f5015c3f7 (patch)
treebddf8ff550f9a968ff3d8c3a638ebcb28f319de0 /driver/tcpm
parentff052aedbd21a41b52921c8c33b22eef03c03352 (diff)
downloadchrome-ec-f00ea7bb8f9d7f835981d969294fef0f5015c3f7.tar.gz
rt1718s: implement adc read
Cherry uses the VBUS1 adc channel in RT1718S to check the VBUS voltage on port 1. Thus add this function for Cherry. BUG=b:196001868 TEST=1) manually check the readings of ADC_VBUS1 2) Combined with board/ side changes, `ectool usbpdpower` shows correct value BRANCH=main Signed-off-by: Ting Shen <phoenixshen@google.com> Change-Id: I243f28b2bd4e8541257afcacb50a024a72e301fd Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3040801 Reviewed-by: Sue Chen <sue.chen@quanta.corp-partner.google.com> Reviewed-by: Eric Yilun Lin <yllin@google.com> Tested-by: Sue Chen <sue.chen@quanta.corp-partner.google.com> Tested-by: Ting Shen <phoenixshen@chromium.org> Commit-Queue: Ting Shen <phoenixshen@chromium.org>
Diffstat (limited to 'driver/tcpm')
-rw-r--r--driver/tcpm/rt1718s.c100
-rw-r--r--driver/tcpm/rt1718s.h25
2 files changed, 119 insertions, 6 deletions
diff --git a/driver/tcpm/rt1718s.c b/driver/tcpm/rt1718s.c
index 631d98a522..96a08785c2 100644
--- a/driver/tcpm/rt1718s.c
+++ b/driver/tcpm/rt1718s.c
@@ -25,26 +25,42 @@
#define RT1718S_SW_RESET_DELAY_MS 2
/* i2c_write function which won't wake TCPC from low power mode. */
-int rt1718s_write8(int port, int reg, int val)
+static int rt1718s_write(int port, int reg, int val, int len)
{
if (reg > 0xFF) {
return i2c_write_offset16(
tcpc_config[port].i2c_info.port,
tcpc_config[port].i2c_info.addr_flags,
- reg, val, 1);
+ reg, val, len);
+ } else if (len == 1) {
+ return tcpc_write(port, reg, val);
+ } else {
+ return tcpc_write16(port, reg, val);
}
- return tcpc_write(port, reg, val);
}
-int rt1718s_read8(int port, int reg, int *val)
+static int rt1718s_read(int port, int reg, int *val, int len)
{
if (reg > 0xFF) {
return i2c_read_offset16(
tcpc_config[port].i2c_info.port,
tcpc_config[port].i2c_info.addr_flags,
- reg, val, 1);
+ reg, val, len);
+ } else if (len == 1) {
+ return tcpc_read(port, reg, val);
+ } else {
+ return tcpc_read16(port, reg, val);
}
- return tcpc_read(port, reg, val);
+}
+
+int rt1718s_write8(int port, int reg, int val)
+{
+ return rt1718s_write(port, reg, val, 1);
+}
+
+int rt1718s_read8(int port, int reg, int *val)
+{
+ return rt1718s_read(port, reg, val, 1);
}
int rt1718s_update_bits8(int port, int reg, int mask, int val)
@@ -61,6 +77,17 @@ int rt1718s_update_bits8(int port, int reg, int mask, int val)
return rt1718s_write8(port, reg, reg_val);
}
+int rt1718s_write16(int port, int reg, int val)
+{
+ return rt1718s_write(port, reg, val, 2);
+}
+
+int rt1718s_read16(int port, int reg, int *val)
+{
+ return rt1718s_read(port, reg, val, 2);
+}
+
+
static int rt1718s_sw_reset(int port)
{
int rv;
@@ -385,6 +412,67 @@ static int rt1718s_enter_low_power_mode(int port)
}
#endif
+int rt1718s_get_adc(int port, enum rt1718s_adc_channel channel, int *adc_val)
+{
+ static struct mutex adc_lock;
+ int rv;
+ const int max_wait_times = 30;
+
+ if (in_interrupt_context()) {
+ CPRINTS("Err: use ADC in IRQ");
+ return EC_ERROR_INVAL;
+ }
+
+ mutex_lock(&adc_lock);
+
+ /* Start ADC conversation */
+ rv = rt1718s_write16(port, RT1718S_ADC_CTRL_01, BIT(channel));
+ if (rv)
+ goto out;
+
+ /*
+ * The expected conversion time is 85.3us * number of enabled channels.
+ * Polling for 3ms should be long enough.
+ */
+ for (int i = 0; i < max_wait_times; i++) {
+ int adc_done;
+
+ usleep(100);
+ rv = rt1718s_read8(port, RT1718S_RT_INT6, &adc_done);
+ if (rv)
+ goto out;
+ if (adc_done & RT1718S_RT_INT6_INT_ADC_DONE)
+ break;
+ if (i == max_wait_times - 1) {
+ CPRINTS("conversion fail channel=%d", channel);
+ rv = EC_ERROR_TIMEOUT;
+ goto out;
+ }
+ }
+
+ /* Read ADC data */
+ rv = rt1718s_read16(port, RT1718S_ADC_CHX_VOL_L(channel), adc_val);
+ if (rv)
+ goto out;
+
+ /*
+ * The resolution of VBUS1 ADC is 12.5mV,
+ * other channels are 4mV.
+ */
+ if (channel == RT1718S_ADC_VBUS1)
+ *adc_val = *adc_val * 125 / 10;
+ else
+ *adc_val *= 4;
+
+out:
+ /* Cleanup: disable adc and clear interrupt. Error ignored. */
+ rt1718s_write16(port, RT1718S_ADC_CTRL_01, 0);
+ rt1718s_write8(port, RT1718S_RT_INT6, RT1718S_RT_INT6_INT_ADC_DONE);
+
+ mutex_unlock(&adc_lock);
+ return rv;
+}
+
/* RT1718S is a TCPCI compatible port controller */
const struct tcpm_drv rt1718s_tcpm_drv = {
.init = &rt1718s_init,
diff --git a/driver/tcpm/rt1718s.h b/driver/tcpm/rt1718s.h
index fd1547cf25..9aed749440 100644
--- a/driver/tcpm/rt1718s.h
+++ b/driver/tcpm/rt1718s.h
@@ -59,6 +59,7 @@
#define RT1718S_RT_INT6_INT_BC12_SNK_DONE BIT(7)
#define RT1718S_RT_INT6_INT_HVDCP_CHK_DONE BIT(6)
#define RT1718S_RT_INT6_INT_BC12_TA_CHG BIT(5)
+#define RT1718S_RT_INT6_INT_ADC_DONE BIT(0)
#define RT1718S_RT_ST6 0xA4
#define RT1718S_RT_ST6_BC12_SNK_DONE BIT(7)
@@ -156,12 +157,36 @@
#define RT1718S_RT2_BC12_SRC_FUNC_SRC_MODE_SEL_BC12_DCP 0x20
#define RT1718S_RT2_BC12_SRC_FUNC_WAIT_VBUS_ON BIT(0)
+#define RT1718S_ADC_CTRL_01 0xF2A0
+#define RT1718S_ADC_CTRL_02 0xF2A1
+#define RT1718S_ADC_CHX_VOL_L(ch) (0xF2A6 + (ch) * 2)
+#define RT1718S_ADC_CHX_VOL_H(ch) (0xF2A7 + (ch) * 2)
+
extern const struct tcpm_drv rt1718s_tcpm_drv;
extern const struct bc12_drv rt1718s_bc12_drv;
int rt1718s_write8(int port, int reg, int val);
int rt1718s_read8(int port, int reg, int *val);
int rt1718s_update_bits8(int port, int reg, int mask, int val);
+int rt1718s_write16(int port, int reg, int val);
+int rt1718s_read16(int port, int reg, int *val);
__override_proto int board_rt1718s_init(int port);
+enum rt1718s_adc_channel {
+ RT1718S_ADC_VBUS1 = 0,
+ RT1718S_ADC_VBUS2,
+ RT1718S_ADC_VDC,
+ RT1718S_ADC_VBUS_CURRENT,
+ RT1718S_ADC_CC1,
+ RT1718S_ADC_CC2,
+ RT1718S_ADC_SBU1,
+ RT1718S_ADC_SBU2,
+ RT1718S_ADC_DP,
+ RT1718S_ADC_DM,
+ RT1718S_ADC_CH10,
+ RT1718S_ADC_CH11,
+};
+
+int rt1718s_get_adc(int port, enum rt1718s_adc_channel channel, int *adc_val);
+
#endif /* __CROS_EC_USB_PD_TCPM_MT6370_H */