diff options
Diffstat (limited to 'board')
-rw-r--r-- | board/samus_pd/board.c | 116 | ||||
-rw-r--r-- | board/samus_pd/board.h | 26 | ||||
-rw-r--r-- | board/samus_pd/gpio.inc | 8 | ||||
-rw-r--r-- | board/samus_pd/usb_pd_config.h | 10 | ||||
-rw-r--r-- | board/samus_pd/usb_pd_policy.c | 14 |
5 files changed, 163 insertions, 11 deletions
diff --git a/board/samus_pd/board.c b/board/samus_pd/board.c index deca02675e..9c46b97952 100644 --- a/board/samus_pd/board.c +++ b/board/samus_pd/board.c @@ -7,26 +7,39 @@ #include "adc.h" #include "adc_chip.h" #include "battery.h" +#include "charge_manager.h" #include "common.h" #include "console.h" #include "gpio.h" #include "hooks.h" #include "i2c.h" +#include "pi3usb9281.h" #include "power.h" +#include "pwm.h" +#include "pwm_chip.h" #include "registers.h" #include "switch.h" #include "system.h" #include "task.h" +#include "usb.h" #include "usb_pd.h" #include "usb_pd_config.h" #include "util.h" +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) + /* Chipset power state */ static enum power_state ps; /* Battery state of charge */ int batt_soc; +/* PWM channels. Must be in the exact same order as in enum pwm_channel. */ +const struct pwm_t pwm_channels[] = { + {STM32_TIM(15), STM32_TIM_CH(2), 0, GPIO_ILIM_ADJ_PWM, GPIO_ALT_F1}, +}; +BUILD_ASSERT(ARRAY_SIZE(pwm_channels) == PWM_CH_COUNT); + void vbus0_evt(enum gpio_signal signal) { ccprintf("VBUS %d, %d!\n", signal, gpio_get_level(signal)); @@ -39,9 +52,54 @@ void vbus1_evt(enum gpio_signal signal) task_wake(TASK_ID_PD_C1); } -void bc12_evt(enum gpio_signal signal) +/* + * Update available charge. Called from deferred task, queued on Pericom + * interrupt. + */ +static void board_usb_charger_update(int port) +{ + int device_type, charger_status; + struct charge_port_info charge; + charge.voltage = USB_BC12_CHARGE_VOLTAGE; + + /* Read interrupt register to clear*/ + pi3usb9281_get_interrupts(port); + device_type = pi3usb9281_get_device_type(port); + charger_status = pi3usb9281_get_charger_status(port); + + /* Attachment: decode + update available charge */ + if (device_type || (charger_status & 0x1f)) + charge.current = pi3usb9281_get_ilim(device_type, + charger_status); + /* Detachment: update available charge to 0 */ + else + charge.current = 0; + + charge_manager_update(CHARGE_SUPPLIER_BC12, port, &charge); + +} + +/* Pericom USB deferred tasks -- called after USB device insert / removal */ +static void usb_port0_charger_update(void) +{ + board_usb_charger_update(0); +} +DECLARE_DEFERRED(usb_port0_charger_update); + +static void usb_port1_charger_update(void) +{ + board_usb_charger_update(1); +} +DECLARE_DEFERRED(usb_port1_charger_update); + +void usb0_evt(enum gpio_signal signal) { - ccprintf("PERICOM %d!\n", signal); + hook_call_deferred(usb_port0_charger_update, 0); +} + +void usb1_evt(enum gpio_signal signal) +{ + hook_call_deferred(usb_port1_charger_update, 0); } void pch_evt(enum gpio_signal signal) @@ -121,6 +179,14 @@ static void board_init(void) gpio_enable_interrupt(GPIO_USB_C0_VBUS_WAKE); gpio_enable_interrupt(GPIO_USB_C1_VBUS_WAKE); + /* Enable pericom BC1.2 interrupts. */ + gpio_enable_interrupt(GPIO_USB_C0_BC12_INT_L); + gpio_enable_interrupt(GPIO_USB_C1_BC12_INT_L); + pi3usb9281_set_interrupt_mask(0, 0xff); + pi3usb9281_set_interrupt_mask(1, 0xff); + pi3usb9281_enable_interrupts(0); + pi3usb9281_enable_interrupts(1); + /* Determine initial chipset state */ if (slp_s5 && slp_s3) { disable_sleep(SLEEP_MASK_AP_RUN); @@ -155,6 +221,18 @@ static void board_init(void) pd_enable = 1; } pd_comm_enable(pd_enable); + + /* Enable ILIM PWM: initial duty cycle 0% = 500mA limit. */ + pwm_enable(PWM_CH_ILIM, 1); + pwm_set_duty(PWM_CH_ILIM, 0); + + /* + * Initialize BC1.2 USB charging, so that charge manager will assign + * charge port based upon charger actually present. Charger detection + * can take up to 200ms after power-on, so delay the initialization. + */ + hook_call_deferred(usb_port0_charger_update, 200 * MSEC); + hook_call_deferred(usb_port1_charger_update, 200 * MSEC); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); @@ -305,3 +383,37 @@ enum battery_present battery_is_present(void) return BP_YES; return BP_NOT_SURE; } + +/** + * Set active charge port -- only one port can be active at a time. + * + * @param charge_port Charge port to enable. + */ +void board_set_active_charge_port(int charge_port) +{ + if (charge_port >= 0 && charge_port < PD_PORT_COUNT && + pd_get_role(charge_port) != PD_ROLE_SINK) { + CPRINTS("Port %d is not a sink, skipping enable", charge_port); + charge_port = CHARGE_PORT_NONE; + } + gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, !(charge_port == 0)); + gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, !(charge_port == 1)); + CPRINTS("Set active charge port %d", charge_port); +} + +/** + * Set the charge limit based upon desired maximum. + * + * @param charge_ma Desired charge limit (mA). + */ +void board_set_charge_limit(int charge_ma) +{ + int pwm_duty = MA_TO_PWM(charge_ma); + if (pwm_duty < 0) + pwm_duty = 0; + else if (pwm_duty > 100) + pwm_duty = 100; + + pwm_set_duty(PWM_CH_ILIM, pwm_duty); + CPRINTS("Set ilim duty %d", pwm_duty); +} diff --git a/board/samus_pd/board.h b/board/samus_pd/board.h index be1dad7f8d..8729cdc2a2 100644 --- a/board/samus_pd/board.h +++ b/board/samus_pd/board.h @@ -18,12 +18,14 @@ /* Optional features */ #define CONFIG_ADC #define CONFIG_BOARD_PRE_INIT +#define CONFIG_CHARGE_MANAGER #define CONFIG_FORCE_CONSOLE_RESUME #define CONFIG_HIBERNATE_WAKEUP_PINS (STM32_PWR_CSR_EWUP3|STM32_PWR_CSR_EWUP8) #define CONFIG_HW_CRC #define CONFIG_I2C #undef CONFIG_LID_SWITCH #define CONFIG_LOW_POWER_IDLE +#define CONFIG_PWM #define CONFIG_STM_HWTIMER32 #undef CONFIG_TASK_PROFILING #define CONFIG_USB_POWER_DELIVERY @@ -35,9 +37,11 @@ #define CONFIG_USB_PD_DUAL_ROLE #define CONFIG_USB_PD_FLASH_ERASE_CHECK #define CONFIG_USB_PD_INTERNAL_COMP +#define CONFIG_USB_SWITCH_PI3USB9281 +#undef CONFIG_USB_SWITCH_PI3USB9281_MUX_GPIO +#define CONFIG_USB_SWITCH_PI3USB9281_MUX_GPIO GPIO_USB_C_BC12_SEL #define CONFIG_USBC_SS_MUX #define CONFIG_USBC_VCONN -#define CONFIG_USB_SWITCH_TSU6721 #define CONFIG_VBOOT_HASH #undef CONFIG_WATCHDOG_HELP @@ -63,6 +67,7 @@ #define TIM_CLOCK32 2 #define TIM_ADC 3 +#include "charge_manager.h" #include "gpio_signal.h" /* ADC signal */ @@ -76,12 +81,31 @@ enum adc_channel { ADC_CH_COUNT }; +enum pwm_channel { + PWM_CH_ILIM = 0, + /* Number of PWM channels */ + PWM_CH_COUNT +}; + +/* Charge current limit min / max, based on PWM duty cycle */ +#define PWM_0_MA 500 +#define PWM_100_MA 4000 + +/* Map current in milli-amps to PWM duty cycle percentage */ +#define MA_TO_PWM(curr) (((curr) - PWM_0_MA) * 100 / (PWM_100_MA - PWM_0_MA)) + /* Called when we receive battery level info from the EC. */ void board_update_battery_soc(int soc); /* Get the last received battery level. */ int board_get_battery_soc(void); +/* Set the active charge port. */ +void board_set_active_charge_port(int charge_port); + +/* Set the charge current limit. */ +void board_set_charge_limit(int charge_ma); + #endif /* !__ASSEMBLER__ */ #endif /* __BOARD_H */ diff --git a/board/samus_pd/gpio.inc b/board/samus_pd/gpio.inc index 9d38f94e68..6345b7b365 100644 --- a/board/samus_pd/gpio.inc +++ b/board/samus_pd/gpio.inc @@ -8,8 +8,8 @@ /* Interrupts */ GPIO(USB_C0_VBUS_WAKE, E, 6, GPIO_INT_BOTH, vbus0_evt) GPIO(USB_C1_VBUS_WAKE, F, 2, GPIO_INT_BOTH, vbus1_evt) -GPIO(USB_C0_BC12_INT_L, B, 0, GPIO_INT_FALLING, bc12_evt) -GPIO(USB_C1_BC12_INT_L, C, 11, GPIO_INT_FALLING, bc12_evt) +GPIO(USB_C0_BC12_INT_L, B, 0, GPIO_INT_FALLING, usb0_evt) +GPIO(USB_C1_BC12_INT_L, C, 11, GPIO_INT_FALLING, usb1_evt) GPIO(PCH_SLP_S0_L, C, 14, GPIO_INT_BOTH, pch_evt) GPIO(PCH_SLP_S3_L, C, 15, GPIO_INT_BOTH, pch_evt) GPIO(PCH_SLP_S5_L, D, 7, GPIO_INT_BOTH, pch_evt) @@ -42,8 +42,8 @@ GPIO(USB_C0_TX_CLKIN, B, 13, GPIO_OUT_LOW, NULL) /* Power and muxes control */ GPIO(PPVAR_BOOSTIN_SENSE, C, 1, GPIO_ANALOG, NULL) GPIO(PP3300_USB_PD_EN, A, 8, GPIO_OUT_HIGH, NULL) -GPIO(USB_C0_CHARGE_EN_L, D, 12, GPIO_OUT_LOW, NULL) -GPIO(USB_C1_CHARGE_EN_L, D, 13, GPIO_OUT_LOW, NULL) +GPIO(USB_C0_CHARGE_EN_L, D, 12, GPIO_OUT_LOW, NULL) +GPIO(USB_C1_CHARGE_EN_L, D, 13, GPIO_OUT_LOW, NULL) GPIO(USB_C0_5V_EN, D, 14, GPIO_OUT_LOW, NULL) GPIO(USB_C1_5V_EN, D, 15, GPIO_OUT_LOW, NULL) GPIO(USB_C0_CC1_VCONN1_EN_L, D, 8, GPIO_OUT_HIGH, NULL) diff --git a/board/samus_pd/usb_pd_config.h b/board/samus_pd/usb_pd_config.h index 083606c413..62b699f3c0 100644 --- a/board/samus_pd/usb_pd_config.h +++ b/board/samus_pd/usb_pd_config.h @@ -3,6 +3,10 @@ * found in the LICENSE file. */ +#include "adc.h" +#include "chip/stm32/registers.h" +#include "gpio.h" + /* USB Power delivery board configuration */ #ifndef __USB_PD_CONFIG_H @@ -200,8 +204,7 @@ static inline void pd_set_host_mode(int port, int enable) /* Pull low for device mode. */ gpio_set_level(GPIO_USB_C0_CC1_ODL, 0); gpio_set_level(GPIO_USB_C0_CC2_ODL, 0); - /* Enable the charging path*/ - gpio_set_level(GPIO_USB_C0_CHARGE_EN_L, 0); + /* Let charge_manager decide to enable the port */ } } else { if (enable) { @@ -216,8 +219,7 @@ static inline void pd_set_host_mode(int port, int enable) /* Pull low for device mode. */ gpio_set_level(GPIO_USB_C1_CC1_ODL, 0); gpio_set_level(GPIO_USB_C1_CC2_ODL, 0); - /* Enable the charging path*/ - gpio_set_level(GPIO_USB_C1_CHARGE_EN_L, 0); + /* Let charge_manager decide to enable the port */ } } } diff --git a/board/samus_pd/usb_pd_policy.c b/board/samus_pd/usb_pd_policy.c index 680895ae72..378c04033c 100644 --- a/board/samus_pd/usb_pd_policy.c +++ b/board/samus_pd/usb_pd_policy.c @@ -146,10 +146,24 @@ static void pd_send_ec_int(void) void pd_set_input_current_limit(int port, uint32_t max_ma, uint32_t supply_voltage) { + struct charge_port_info charge; + charge.current = max_ma; + charge.voltage = supply_voltage; + charge_manager_update(CHARGE_SUPPLIER_PD, port, &charge); + pd_status.curr_lim_ma = max_ma; pd_send_ec_int(); } +void typec_set_input_current_limit(int port, uint32_t max_ma, + uint32_t supply_voltage) +{ + struct charge_port_info charge; + charge.current = max_ma; + charge.voltage = supply_voltage; + charge_manager_update(CHARGE_SUPPLIER_TYPEC, port, &charge); +} + int pd_board_checks(void) { return EC_SUCCESS; |