summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
Diffstat (limited to 'board')
-rw-r--r--board/samus_pd/board.c116
-rw-r--r--board/samus_pd/board.h26
-rw-r--r--board/samus_pd/gpio.inc8
-rw-r--r--board/samus_pd/usb_pd_config.h10
-rw-r--r--board/samus_pd/usb_pd_policy.c14
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;