diff options
-rw-r--r-- | board/lucid/board.c | 76 | ||||
-rw-r--r-- | board/lucid/board.h | 1 | ||||
-rw-r--r-- | chip/stm32/build.mk | 1 | ||||
-rw-r--r-- | chip/stm32/charger_detect.c | 55 | ||||
-rw-r--r-- | chip/stm32/registers.h | 9 | ||||
-rw-r--r-- | include/charger_detect.h | 17 | ||||
-rw-r--r-- | include/config.h | 3 |
7 files changed, 138 insertions, 24 deletions
diff --git a/board/lucid/board.c b/board/lucid/board.c index d82467bd7e..a536153b42 100644 --- a/board/lucid/board.c +++ b/board/lucid/board.c @@ -8,6 +8,7 @@ #include "adc_chip.h" #include "charge_manager.h" #include "charge_state.h" +#include "charger_detect.h" #include "common.h" #include "console.h" #include "extpower.h" @@ -18,9 +19,11 @@ #include "registers.h" #include "task.h" #include "usb_charge.h" +#include "usb_pd.h" #include "util.h" #define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) +#define USB_CHG_DETECT_DELAY_US 5000 void board_config_pre_init(void) { @@ -40,6 +43,52 @@ void board_config_pre_init(void) STM32_SYSCFG_CFGR1 |= (1 << 9) | (1 << 10); } +static void reset_charge(int port) +{ + struct charge_port_info charge_none; + + charge_none.voltage = USB_CHARGER_VOLTAGE_MV; + charge_none.current = 0; + charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY, + port, + &charge_none); + charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP, + port, + &charge_none); + charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP, + port, + &charge_none); + charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP, + port, + &charge_none); + charge_manager_update_charge(CHARGE_SUPPLIER_OTHER, + port, + &charge_none); +} + +static void usb_charger_bc12_detect(void) +{ + int type; + struct charge_port_info charge; + + type = charger_detect_get_device_type(); + if (gpio_get_level(GPIO_AC_PRESENT) && type) { + charge.voltage = USB_CHARGER_VOLTAGE_MV; + if (type == CHARGE_SUPPLIER_BC12_CDP) + charge.current = 1500; + else + charge.current = 500; + + charge_manager_update_charge(type, 0, &charge); + } else + reset_charge(0); + + + /* notify host of power info change */ + pd_send_host_event(PD_EVENT_POWER_CHANGE); +} +DECLARE_DEFERRED(usb_charger_bc12_detect); + static void update_vbus_supplier(int vbus_level) { struct charge_port_info charge; @@ -56,6 +105,7 @@ void vbus_evt(enum gpio_signal signal) * lucid only has one port and charging is always enabled. */ + hook_call_deferred(usb_charger_bc12_detect, USB_CHG_DETECT_DELAY_US); update_vbus_supplier(gpio_get_level(signal)); task_wake(TASK_ID_PD_C0); @@ -95,32 +145,10 @@ const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); static void board_init(void) { int i; - struct charge_port_info charge_none; /* Initialize all BC1.2 charge suppliers to 0 */ - /* - * TODO: use built-in USB peripheral to detect BC1.2 suppliers an - * update charge manager. - */ - charge_none.voltage = USB_CHARGER_VOLTAGE_MV; - charge_none.current = 0; - for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) { - charge_manager_update_charge(CHARGE_SUPPLIER_PROPRIETARY, - i, - &charge_none); - charge_manager_update_charge(CHARGE_SUPPLIER_BC12_CDP, - i, - &charge_none); - charge_manager_update_charge(CHARGE_SUPPLIER_BC12_DCP, - i, - &charge_none); - charge_manager_update_charge(CHARGE_SUPPLIER_BC12_SDP, - i, - &charge_none); - charge_manager_update_charge(CHARGE_SUPPLIER_OTHER, - i, - &charge_none); - } + for (i = 0; i < CONFIG_USB_PD_PORT_COUNT; i++) + reset_charge(i); /* Enable charge status interrupt */ gpio_enable_interrupt(GPIO_CHARGE_STATUS); diff --git a/board/lucid/board.h b/board/lucid/board.h index f9fd68c5b1..2163d28517 100644 --- a/board/lucid/board.h +++ b/board/lucid/board.h @@ -50,6 +50,7 @@ #define CONFIG_LOW_POWER_IDLE #define CONFIG_LTO #define CONFIG_STM_HWTIMER32 +#define CONFIG_STM32_CHARGER_DETECT #undef CONFIG_TASK_PROFILING #define CONFIG_USB_POWER_DELIVERY #define CONFIG_USB_PD_ALT_MODE diff --git a/chip/stm32/build.mk b/chip/stm32/build.mk index 53b48b6ab5..6878c76065 100644 --- a/chip/stm32/build.mk +++ b/chip/stm32/build.mk @@ -50,6 +50,7 @@ chip-$(CHIP_FAMILY_STM32F0)+=flash-f.o chip-$(CHIP_FAMILY_STM32F3)+=flash-f.o endif chip-$(CONFIG_ADC)+=adc-$(CHIP_FAMILY).o +chip-$(CONFIG_STM32_CHARGER_DETECT)+=charger_detect.o chip-$(CONFIG_DEBUG_PRINTF)+=debug_printf.o chip-$(CONFIG_PWM)+=pwm.o chip-$(CONFIG_USB)+=usb.o usb-$(CHIP_FAMILY).o usb_endpoints.o diff --git a/chip/stm32/charger_detect.c b/chip/stm32/charger_detect.c new file mode 100644 index 0000000000..b32b9f3ac0 --- /dev/null +++ b/chip/stm32/charger_detect.c @@ -0,0 +1,55 @@ +/* Copyright 2016 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. + */ +/* Detect what adapter is connected */ + +#include "charge_manager.h" +#include "hooks.h" +#include "registers.h" +#include "timer.h" + +static void enable_usb(void) +{ + /* Enable USB device clock. */ + STM32_RCC_APB1ENR |= STM32_RCC_PB1_USB; +} +DECLARE_HOOK(HOOK_INIT, enable_usb, HOOK_PRIO_DEFAULT); + +static void disable_usb(void) +{ + /* Disable USB device clock. */ + STM32_RCC_APB1ENR &= ~STM32_RCC_PB1_USB; +} +DECLARE_HOOK(HOOK_SYSJUMP, disable_usb, HOOK_PRIO_DEFAULT); + +static uint16_t detect_type(uint16_t det_type) +{ + STM32_USB_BCDR &= 0; + usleep(1); + STM32_USB_BCDR |= (STM32_USB_BCDR_BCDEN | det_type); + usleep(1); + STM32_USB_BCDR &= ~(STM32_USB_BCDR_BCDEN | det_type); + return STM32_USB_BCDR; +} + + +int charger_detect_get_device_type(void) +{ + uint16_t pdet_result; + + if (!(detect_type(STM32_USB_BCDR_DCDEN) & STM32_USB_BCDR_DCDET)) + return CHARGE_SUPPLIER_PD; + + pdet_result = detect_type(STM32_USB_BCDR_PDEN); + /* TODO: add support for detecting proprietary chargers. */ + if (pdet_result & STM32_USB_BCDR_PDET) { + if (detect_type(STM32_USB_BCDR_SDEN) & STM32_USB_BCDR_SDET) + return CHARGE_SUPPLIER_BC12_DCP; + else + return CHARGE_SUPPLIER_BC12_CDP; + } else if (pdet_result & STM32_USB_BCDR_PS2DET) + return CHARGE_SUPPLIER_PROPRIETARY; + else + return CHARGE_SUPPLIER_BC12_SDP; +} diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h index 57fb2a9ec0..283fd44498 100644 --- a/chip/stm32/registers.h +++ b/chip/stm32/registers.h @@ -1327,6 +1327,15 @@ typedef volatile struct stm32_dma_regs stm32_dma_regs_t; #define STM32_USB_LPMCSR REG16(STM32_USB_FS_BASE + 0x54) #define STM32_USB_BCDR REG16(STM32_USB_FS_BASE + 0x58) +#define STM32_USB_BCDR_BCDEN (1 << 0) +#define STM32_USB_BCDR_DCDEN (1 << 1) +#define STM32_USB_BCDR_PDEN (1 << 2) +#define STM32_USB_BCDR_SDEN (1 << 3) +#define STM32_USB_BCDR_DCDET (1 << 4) +#define STM32_USB_BCDR_PDET (1 << 5) +#define STM32_USB_BCDR_SDET (1 << 6) +#define STM32_USB_BCDR_PS2DET (1 << 7) + #define EP_MASK 0x0F0F #define EP_TX_DTOG 0x0040 #define EP_TX_MASK 0x0030 diff --git a/include/charger_detect.h b/include/charger_detect.h new file mode 100644 index 0000000000..ae2001e418 --- /dev/null +++ b/include/charger_detect.h @@ -0,0 +1,17 @@ +/* Copyright 2016 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. + */ +/* Detect what adapter is connected */ + +#ifndef __CROS_CHARGER_DETECT_H +#define __CROS_CHARGER_DETECT_H + +/* + * Get attached device type. + * + * @return CHARGE_SUPPLIER_BC12_* or 0 if the device type was not detected + */ +int charger_detect_get_device_type(void); + +#endif /* __CROS_CHARGER_DETECT_H */ diff --git a/include/config.h b/include/config.h index a0a0d5c4cf..1845cd1ff5 100644 --- a/include/config.h +++ b/include/config.h @@ -1607,6 +1607,9 @@ /* Use 32-bit timer for clock source on stm32. */ #undef CONFIG_STM_HWTIMER32 +/* Compile charger detect for STM32 */ +#undef CONFIG_STM32_CHARGER_DETECT + /* Fake hibernate mode */ #undef CONFIG_STM32L_FAKE_HIBERNATE |