diff options
Diffstat (limited to 'board/samus_pd/board.c')
-rw-r--r-- | board/samus_pd/board.c | 116 |
1 files changed, 114 insertions, 2 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); +} |