summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--driver/bc12/mt6360.c174
-rw-r--r--driver/bc12/mt6360.h40
-rw-r--r--driver/build.mk1
-rw-r--r--include/config.h4
4 files changed, 218 insertions, 1 deletions
diff --git a/driver/bc12/mt6360.c b/driver/bc12/mt6360.c
new file mode 100644
index 0000000000..4f0dbc4cf6
--- /dev/null
+++ b/driver/bc12/mt6360.c
@@ -0,0 +1,174 @@
+/* Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "charger.h"
+#include "charge_manager.h"
+#include "console.h"
+#include "driver/bc12/mt6360.h"
+#include "hooks.h"
+#include "i2c.h"
+#include "task.h"
+#include "timer.h"
+#include "usb_charge.h"
+#include "usb_pd.h"
+
+/* Console output macros */
+#define CPRINTF(format, args...) cprintf(CC_CHARGER, format, ## args)
+#define CPRINTS(format, args...) \
+ cprints(CC_USBCHARGE, "%s " format, "MT6360", ## args)
+
+static enum ec_error_list mt6360_read8(int reg, int *val)
+{
+ return i2c_read8(mt6360_config.i2c_port, mt6360_config.i2c_addr_flags,
+ reg, val);
+}
+
+static enum ec_error_list mt6360_write8(int reg, int val)
+{
+ return i2c_write8(mt6360_config.i2c_port, mt6360_config.i2c_addr_flags,
+ reg, val);
+}
+
+static int mt6360_update_bits(int reg, int mask, int val)
+{
+ int rv;
+ int reg_val;
+
+ rv = mt6360_read8(reg, &reg_val);
+ if (rv)
+ return rv;
+ reg_val &= ~mask;
+ reg_val |= (mask & val);
+ rv = mt6360_write8(reg, reg_val);
+ return rv;
+}
+
+static inline int mt6360_set_bit(int reg, int mask)
+{
+ return mt6360_update_bits(reg, mask, mask);
+}
+
+static inline int mt6360_clr_bit(int reg, int mask)
+{
+ return mt6360_update_bits(reg, mask, 0x00);
+}
+
+static int mt6360_get_bc12_device_type(void)
+{
+ int reg;
+
+ if (mt6360_read8(MT6360_REG_USB_STATUS_1, &reg))
+ return CHARGE_SUPPLIER_NONE;
+
+ switch (reg & MT6360_MASK_USB_STATUS) {
+ case MT6360_MASK_SDP:
+ CPRINTS("BC12 SDP");
+ return CHARGE_SUPPLIER_BC12_SDP;
+ case MT6360_MASK_CDP:
+ CPRINTS("BC12 CDP");
+ return CHARGE_SUPPLIER_BC12_CDP;
+ case MT6360_MASK_DCP:
+ CPRINTS("BC12 DCP");
+ return CHARGE_SUPPLIER_BC12_DCP;
+ default:
+ CPRINTS("BC12 NONE");
+ return CHARGE_SUPPLIER_NONE;
+ }
+}
+
+static int mt6360_get_bc12_ilim(int charge_supplier)
+{
+ switch (charge_supplier) {
+ case CHARGE_SUPPLIER_BC12_DCP:
+ case CHARGE_SUPPLIER_BC12_CDP:
+ return USB_CHARGER_MAX_CURR_MA;
+ case CHARGE_SUPPLIER_BC12_SDP:
+ default:
+ return USB_CHARGER_MIN_CURR_MA;
+ }
+}
+
+static int mt6360_enable_bc12_detection(int en)
+{
+ int rv;
+
+ if (en) {
+#ifdef CONFIG_MT6360_BC12_GPIO
+ gpio_set_level(GPIO_BC12_DET_EN, 1);
+#endif
+ return mt6360_set_bit(MT6360_REG_DEVICE_TYPE,
+ MT6360_MASK_USBCHGEN);
+ }
+
+ rv = mt6360_clr_bit(MT6360_REG_DEVICE_TYPE, MT6360_MASK_USBCHGEN);
+#ifdef CONFIG_MT6360_BC12_GPIO
+ gpio_set_level(GPIO_BC12_DET_EN, 0);
+#endif
+ return rv;
+}
+
+static void mt6360_update_charge_manager(int port)
+{
+ static int current_bc12_type = CHARGE_SUPPLIER_NONE;
+ int reg;
+ int new_bc12_type = CHARGE_SUPPLIER_NONE;
+
+ mt6360_read8(MT6360_REG_DPDMIRQ, &reg);
+
+ if (pd_snk_is_vbus_provided(port) && (reg & MT6360_MASK_DPDMIRQ_ATTACH))
+ new_bc12_type = mt6360_get_bc12_device_type();
+
+ if (new_bc12_type != current_bc12_type) {
+ charge_manager_update_charge(current_bc12_type, port, NULL);
+
+ if (new_bc12_type != CHARGE_SUPPLIER_NONE) {
+ struct charge_port_info chg = {
+ .current = mt6360_get_bc12_ilim(new_bc12_type),
+ .voltage = USB_CHARGER_VOLTAGE_MV,
+ };
+
+ charge_manager_update_charge(new_bc12_type, port, &chg);
+ }
+
+ current_bc12_type = new_bc12_type;
+ }
+
+ /* write clear */
+ mt6360_write8(MT6360_REG_DPDMIRQ, reg);
+}
+
+static void mt6360_usb_charger_task(const int port)
+{
+ mt6360_clr_bit(MT6360_REG_DPDM_MASK1,
+ MT6360_REG_DPDM_MASK1_CHGDET_DONEI_M);
+ mt6360_enable_bc12_detection(0);
+
+ while (1) {
+ uint32_t evt = task_wait_event(-1);
+
+ /* vbus change, start bc12 detection */
+ if (evt & USB_CHG_EVENT_VBUS)
+ mt6360_enable_bc12_detection(1);
+
+ /* detection done, update charge_manager and stop detection */
+ if (evt & USB_CHG_EVENT_BC12) {
+ mt6360_update_charge_manager(port);
+ mt6360_enable_bc12_detection(0);
+ }
+ }
+}
+
+const struct bc12_drv mt6360_drv = {
+ .usb_charger_task = mt6360_usb_charger_task,
+};
+
+#ifdef CONFIG_BC12_SINGLE_DRIVER
+/* provide a default bc12_ports[] for backward compatibility */
+struct bc12_config bc12_ports[CHARGE_PORT_COUNT] = {
+ [0 ... (CHARGE_PORT_COUNT - 1)] = {
+ .drv = &mt6360_drv,
+ },
+};
+#endif /* CONFIG_BC12_SINGLE_DRIVER */
diff --git a/driver/bc12/mt6360.h b/driver/bc12/mt6360.h
new file mode 100644
index 0000000000..1b01f490cb
--- /dev/null
+++ b/driver/bc12/mt6360.h
@@ -0,0 +1,40 @@
+/* Copyright 2020 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_MT6360_H
+
+#define MT6360_PMU_SLAVE_ADDR_FLAGS 0x34
+#define MT6360_PMIC_SLAVE_ADDR_FLAGS 0x1A
+#define MT6360_LDO_SLAVE_ADDR_FLAGS 0x64
+#define MT6360_PD_SLAVE_ADDR_FLAGS 0x4E
+
+#define MT6360_IRQ_MASK 0x0C
+
+#define MT6360_REG_DEVICE_TYPE 0x22
+#define MT6360_MASK_USBCHGEN BIT(7)
+
+#define MT6360_REG_USB_STATUS_1 0x27
+#define MT6360_MASK_USB_STATUS 0x70
+#define MT6360_MASK_SDP 0x20
+#define MT6360_MASK_DCP 0x40
+#define MT6360_MASK_CDP 0x50
+
+#define MT6360_REG_DPDMIRQ 0xD6
+#define MT6360_MASK_DPDMIRQ_ATTACH BIT(0)
+#define MT6360_MASK_DPDMIRQ_DETACH BIT(1)
+
+#define MT6360_REG_DPDM_MASK1 0xF6
+#define MT6360_REG_DPDM_MASK1_CHGDET_DONEI_M BIT(0)
+
+struct mt6360_config_t {
+ int i2c_port;
+ int i2c_addr_flags;
+};
+
+extern const struct mt6360_config_t mt6360_config;
+
+extern const struct bc12_drv mt6360_drv;
+
+#endif /* __CROS_EC_MT6360_H */
diff --git a/driver/build.mk b/driver/build.mk
index 9a7107b066..368f392ed5 100644
--- a/driver/build.mk
+++ b/driver/build.mk
@@ -28,6 +28,7 @@ driver-$(CONFIG_ACCEL_LIS2DS)+=accel_lis2ds.o stm_mems_common.o
# BC1.2 Charger Detection Devices
driver-$(CONFIG_BC12_DETECT_MAX14637)+=bc12/max14637.o
+driver-$(CONFIG_BC12_DETECT_MT6360)+=bc12/mt6360.o
driver-$(CONFIG_BC12_DETECT_PI3USB9201)+=bc12/pi3usb9201.o
driver-$(CONFIG_BC12_DETECT_PI3USB9281)+=bc12/pi3usb9281.o
diff --git a/include/config.h b/include/config.h
index 93f8a437c4..2d13bb550c 100644
--- a/include/config.h
+++ b/include/config.h
@@ -864,11 +864,12 @@
#undef CONFIG_CHARGER_MT6370_BACKLIGHT
/*
- * MT6370 BC1.2 USB-PHY control.
+ * MT6360/MT6370 BC1.2 USB-PHY control.
* If defined, USB-PHY connection is controlled by GPIO_BC12_DET_EN.
* Assert GPIO_BC12_DET_EN to detect BC1.2 device, and deassert
* GPIO_BC12_DET_EN to mux USB-PHY back.
*/
+#undef CONFIG_MT6360_BC12_GPIO
#undef CONFIG_CHARGER_MT6370_BC12_GPIO
/*
@@ -4187,6 +4188,7 @@
/* External BC1.2 charger detection devices. */
#undef CONFIG_BC12_DETECT_MAX14637
+#undef CONFIG_BC12_DETECT_MT6360
#undef CONFIG_BC12_DETECT_PI3USB9201
#undef CONFIG_BC12_DETECT_PI3USB9281
/* Number of Pericom PI3USB9281 chips present in system */