diff options
-rw-r--r-- | board/coffeecake/board.c | 60 | ||||
-rw-r--r-- | board/coffeecake/board.h | 33 | ||||
-rw-r--r-- | board/coffeecake/ec.tasklist | 1 | ||||
-rw-r--r-- | board/coffeecake/gpio.inc | 31 | ||||
-rw-r--r-- | board/coffeecake/usb_pd_config.h | 39 | ||||
-rw-r--r-- | board/coffeecake/usb_pd_policy.c | 56 |
6 files changed, 182 insertions, 38 deletions
diff --git a/board/coffeecake/board.c b/board/coffeecake/board.c index 27a5070651..bc44f07a00 100644 --- a/board/coffeecake/board.c +++ b/board/coffeecake/board.c @@ -6,11 +6,14 @@ #include "adc.h" #include "adc_chip.h" +#include "charger/sy21612.h" +#include "clock.h" #include "common.h" #include "ec_commands.h" #include "ec_version.h" #include "gpio.h" #include "hooks.h" +#include "i2c.h" #include "mcdp28x0.h" #include "registers.h" #include "task.h" @@ -26,6 +29,12 @@ static volatile int hpd_prev_level; void hpd_event(enum gpio_signal signal); #include "gpio_list.h" +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + {"charger", I2C_PORT_SY21612, 400, GPIO_I2C0_SCL, GPIO_I2C0_SDA}, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + /** * Hotplug detect deferred task * @@ -93,11 +102,39 @@ void hpd_event(enum gpio_signal signal) hpd_prev_level = level; } +/* USB C VBUS output selection */ +void board_set_usb_output_voltage(int mv) +{ + const int ra = 40200; + const int rb = 10000; + const int rc = 6650; + int dac_mv; + uint32_t dac_val; + + /* vbat = 1.0 * ra/rb + 1.0 - (vdac - 1.0) * ra/rc */ + dac_mv = 1000 + (1000 * rc / rb) + ((1000 - mv) * rc / ra); + if (dac_mv < 0) + dac_mv = 0; + + /* Set voltage Vout=Vdac with Vref = 3.3v */ + /* TODO: use Vdda instead */ + dac_val = dac_mv * 4096 / 3300; + STM32_DAC_DHR12RD = dac_val | (dac_val << 16); +} + /* Initialize board. */ void board_config_pre_init(void) { - /* enable SYSCFG clock */ + /* Enable SYSCFG clock */ STM32_RCC_APB2ENR |= 1 << 0; + /* Enable DAC interface clock. */ + STM32_RCC_APB1ENR |= (1 << 29); + /* Delay 1 APB clock cycle after the clock is enabled */ + clock_wait_bus_cycles(BUS_APB, 1); + /* Start DAC channel 1 & 2 */ + STM32_DAC_CR = STM32_DAC_CR_EN1 | STM32_DAC_CR_EN2; + /* Set 5Vsafe Vdac */ + board_set_usb_output_voltage(5000); /* Remap USART DMA to match the USART driver */ STM32_SYSCFG_CFGR1 |= (1 << 9) | (1 << 10);/* Remap USART1 RX/TX DMA */ } @@ -144,7 +181,6 @@ static void factory_validation_deferred(void) /* test mcdp via serial to validate function */ if (!mcdp_get_info(&info) && (MCDP_FAMILY(info.family) == 0x0010) && (MCDP_CHIPID(info.chipid) == 0x2850)) { - gpio_set_level(GPIO_MCDP_READY, 1); pd_log_event(PD_EVENT_VIDEO_CODEC, PD_LOG_PORT_SIZE(0, sizeof(info)), 0, &info); @@ -154,6 +190,18 @@ static void factory_validation_deferred(void) } DECLARE_DEFERRED(factory_validation_deferred); +static void board_post_init(void) +{ + sy21612_enable_regulator(1); + /* + * AC powered - DRP SOURCE + * DUT powered - DRP SINK + */ + pd_set_dual_role(gpio_get_level(GPIO_AC_PRESENT_L) ? + PD_DRP_FORCE_SINK : PD_DRP_FORCE_SOURCE); +} +DECLARE_DEFERRED(board_post_init); + /* Initialize board. */ static void board_init(void) { @@ -166,9 +214,10 @@ static void board_init(void) hpd_prev_ts = now.val; gpio_enable_interrupt(GPIO_DP_HPD); - gpio_set_level(GPIO_STM_READY, 1); /* factory test only */ /* Delay needed to allow HDMI MCU to boot. */ hook_call_deferred(&factory_validation_deferred_data, 200*MSEC); + /* Initialize buck-boost converter */ + hook_call_deferred(&board_post_init_data, 0); } DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); @@ -176,7 +225,10 @@ DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); /* ADC channels */ const struct adc_t adc_channels[] = { /* USB PD CC lines sensing. Converted to mV (3300mV/4096). */ - [ADC_CH_CC1_PD] = {"USB_C_CC1_PD", 3300, 4096, 0, STM32_AIN(1)}, + [ADC_CH_CC1_PD] = {"USB_C_CC1_PD", 3300, 4096, 0, STM32_AIN(1)}, + [ADC_VBUS_MON] = {"VBUS_MON", 13200, 4096, 0, STM32_AIN(2)}, + [ADC_DAC_REF_TP28] = {"DAC_REF_TP28", 3300, 4096, 0, STM32_AIN(4)}, + [ADC_DAC_VOLT] = {"DAC_VOLT", 3300, 4096, 0, STM32_AIN(5)}, }; BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); diff --git a/board/coffeecake/board.h b/board/coffeecake/board.h index f7bc554a21..0653253b51 100644 --- a/board/coffeecake/board.h +++ b/board/coffeecake/board.h @@ -18,8 +18,13 @@ #define CONFIG_STM_HWTIMER32 #define CONFIG_ADC #define CONFIG_BOARD_PRE_INIT +#define CONFIG_CMD_CHARGER +#define CONFIG_CMD_GPIO_EXTENDED #define CONFIG_CMD_SPI_FLASH +#define CONFIG_CHARGER_SY21612 #define CONFIG_HW_CRC +#define CONFIG_I2C +#define CONFIG_I2C_MASTER #define CONFIG_RSA #define CONFIG_RWSIG #define CONFIG_RWSIG_TYPE_USBPD1 @@ -75,6 +80,9 @@ /* ADC signal */ enum adc_channel { ADC_CH_CC1_PD = 0, + ADC_VBUS_MON, + ADC_DAC_REF_TP28, + ADC_DAC_VOLT, /* Number of ADC channels */ ADC_CH_COUNT }; @@ -90,15 +98,25 @@ enum usb_strings { USB_STR_COUNT }; -/* we are never a source : don't care about power supply */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 0 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 0 /* us */ +/* 3.0A Rp */ +#define PD_SRC_VNC PD_SRC_3_0_VNC_MV +#define PD_SRC_RD_THRESHOLD PD_SRC_3_0_RD_THRESH_MV + +/* delay necessary for the voltage transition on the power supply */ +/* TODO (code.google.com/p/chrome-os-partner/issues/detail?id=37078) + * Need to measure these and adjust for honeybuns. + */ +#define PD_POWER_SUPPLY_TURN_ON_DELAY 50000 /* us */ +#define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */ /* Define typical operating power and max power */ #define PD_OPERATING_POWER_MW 1000 -#define PD_MAX_POWER_MW 1500 -#define PD_MAX_CURRENT_MA 300 -#define PD_MAX_VOLTAGE_MV 5000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 15000 + +/* Board interfaces */ +void board_set_usb_output_voltage(int mv); #endif /* !__ASSEMBLER__ */ @@ -112,4 +130,7 @@ enum usb_strings { #define USB_EP_CONTROL 0 #define USB_EP_COUNT 1 +/* I2C ports */ +#define I2C_PORT_SY21612 0 + #endif /* __CROS_EC_BOARD_H */ diff --git a/board/coffeecake/ec.tasklist b/board/coffeecake/ec.tasklist index 5254b70e2b..63a775523d 100644 --- a/board/coffeecake/ec.tasklist +++ b/board/coffeecake/ec.tasklist @@ -18,5 +18,6 @@ */ #define CONFIG_TASK_LIST \ TASK_ALWAYS(HOOKS, hook_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(SY21612, sy21612_task, NULL, SMALLER_TASK_STACK_SIZE) \ TASK_ALWAYS(CONSOLE, console_task, NULL, TASK_STACK_SIZE) \ TASK_ALWAYS(PD_C0, pd_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/coffeecake/gpio.inc b/board/coffeecake/gpio.inc index cfb689d825..bc0fea43e2 100644 --- a/board/coffeecake/gpio.inc +++ b/board/coffeecake/gpio.inc @@ -9,29 +9,44 @@ * Note: Those with interrupt handlers must be declared first. */ GPIO_INT(DP_HPD, PIN(A, 0), GPIO_INT_BOTH, hpd_event) +GPIO_INT(CHARGER_INT, PIN(C, 13), GPIO_INT_FALLING, sy21612_int) GPIO(USB_C_CC1_PD, PIN(A, 1), GPIO_ANALOG) -GPIO(STM_READY, PIN(A, 2), GPIO_OUT_LOW) /* factory test only */ +GPIO(VBUS_DIV4_MON, PIN(A, 2), GPIO_ANALOG) GPIO(MCDP_RESET_L, PIN(A, 3), GPIO_OUT_HIGH) -GPIO(PD_DAC_REF, PIN(A, 4), GPIO_ANALOG) +GPIO(PD_DAC_REF_TP28, PIN(A, 4), GPIO_ANALOG) +GPIO(DAC_VBUS_VOLT, PIN(A, 5), GPIO_ANALOG) +GPIO(LED_GREEN, PIN(A, 6), GPIO_OUT_LOW) +GPIO(LED_BLUE, PIN(A, 7), GPIO_OUT_LOW) -GPIO(MCDP_READY, PIN(A, 7), GPIO_OUT_LOW) /* factory test only */ GPIO(PD_SBU_ENABLE, PIN(A, 8), GPIO_OUT_LOW) GPIO(USB_DM, PIN(A, 11), GPIO_ANALOG) GPIO(USB_DP, PIN(A, 12), GPIO_ANALOG) -GPIO(PD_CC1_TX_EN, PIN(A, 15), GPIO_OUT_LOW) +GPIO(PD_DISCHARGE, PIN(A, 13), GPIO_OUT_LOW) +GPIO(PD_CC1_ODL, PIN(A, 15), GPIO_ODR_LOW) -GPIO(MCDP_GPIO1, PIN(B, 0), GPIO_INPUT) -GPIO(MCDP_CONFIG1, PIN(B, 1), GPIO_INPUT) +GPIO(EN_PP3300, PIN(B, 0), GPIO_OUT_HIGH) +GPIO(MCU_PB1, PIN(B, 1), GPIO_OUT_LOW) GPIO(PD_MCDP_SPI_WP_L, PIN(B, 2), GPIO_OUT_LOW) -GPIO(PD_CC1_TX_DATA, PIN(B, 4), GPIO_OUT_LOW) +GPIO(PD_CC1_TX_DATA, PIN(B, 4), GPIO_INPUT) +GPIO(PD_CC1_HOST_HIGH, PIN(B, 5), GPIO_INPUT) +GPIO(I2C0_SCL, PIN(B, 6), GPIO_INPUT) +GPIO(I2C0_SDA, PIN(B, 7), GPIO_INPUT) +GPIO(LED_ORANGE, PIN(B, 9), GPIO_OUT_LOW) GPIO(PD_MCDP_SPI_CS_L, PIN(B, 12), GPIO_INPUT) +GPIO(USB_C_VBUS_DET_L, PIN(C, 14), GPIO_INPUT) +GPIO(AC_PRESENT_L, PIN(C, 15), GPIO_INPUT) + +GPIO(EN_PP5000, PIN(F, 0), GPIO_OUT_HIGH) +GPIO(EN_USB_PD, PIN(F, 1), GPIO_OUT_HIGH) + /* Unimplemented signals which we need to emulate for now */ UNIMPLEMENTED(ENTERING_RW) UNIMPLEMENTED(WP_L) ALTERNATE(PIN_MASK(B, 0x0008), 0, MODULE_USB_PD, 0) /* SPI1: SCK(PB3) */ -ALTERNATE(PIN_MASK(B, 0x0200), 2, MODULE_USB_PD, 0) /* TIM17_CH1: PB9 */ +ALTERNATE(PIN_MASK(B, 0x0100), 2, MODULE_USB_PD, 0) /* TIM16_CH1: PB9 */ ALTERNATE(PIN_MASK(A, 0x0600), 1, MODULE_UART, GPIO_PULL_UP) /* USART1: PA9/PA10 */ ALTERNATE(PIN_MASK(B, 0x0C00), 4, MODULE_UART, GPIO_PULL_UP) /* USART3: PB10/PB11 */ +ALTERNATE(PIN_MASK(B, 0x00C0), 1, MODULE_I2C, 0) /* I2C MASTER:PB6/7 */ diff --git a/board/coffeecake/usb_pd_config.h b/board/coffeecake/usb_pd_config.h index 181ccd20c2..2282ea4e4b 100644 --- a/board/coffeecake/usb_pd_config.h +++ b/board/coffeecake/usb_pd_config.h @@ -9,7 +9,7 @@ #define __CROS_EC_USB_PD_CONFIG_H /* Timer selection for baseband PD communication */ -#define TIM_CLOCK_PD_TX_C0 17 +#define TIM_CLOCK_PD_TX_C0 16 #define TIM_CLOCK_PD_RX_C0 1 #define TIM_CLOCK_PD_TX(p) TIM_CLOCK_PD_TX_C0 @@ -80,19 +80,18 @@ static inline void pd_tx_enable(int port, int polarity) { /* PB4 is SPI1_MISO */ gpio_set_alternate_function(GPIO_B, 0x0010, 0); - - gpio_set_level(GPIO_PD_CC1_TX_EN, 1); + /* USB_C_CC1_PD: PA1 output low */ + gpio_set_flags(GPIO_USB_C_CC1_PD, GPIO_OUTPUT); + gpio_set_level(GPIO_USB_C_CC1_PD, 0); } /* Put the TX driver in Hi-Z state */ static inline void pd_tx_disable(int port, int polarity) { - /* output low on SPI TX (PB4) to disable the FET */ - STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) - & ~(3 << (2*4))) - | (1 << (2*4)); + /* SPI TX (PB4) Hi-Z */ + gpio_set_flags(GPIO_PD_CC1_TX_DATA, GPIO_INPUT); /* put the low level reference in Hi-Z */ - gpio_set_level(GPIO_PD_CC1_TX_EN, 0); + gpio_set_flags(GPIO_USB_C_CC1_PD, GPIO_ANALOG); } static inline void pd_select_polarity(int port, int polarity) @@ -111,7 +110,17 @@ static inline void pd_tx_init(void) gpio_config_module(MODULE_USB_PD, 1); } -static inline void pd_set_host_mode(int port, int enable) {} +static inline void pd_set_host_mode(int port, int enable) +{ + if (enable) { + gpio_set_level(GPIO_PD_CC1_ODL, 1); + gpio_set_flags(GPIO_PD_CC1_HOST_HIGH, GPIO_OUTPUT); + gpio_set_level(GPIO_PD_CC1_HOST_HIGH, 1); + } else { + gpio_set_flags(GPIO_PD_CC1_HOST_HIGH, GPIO_INPUT); + gpio_set_level(GPIO_PD_CC1_ODL, 0); + } +} static inline void pd_config_init(int port, uint8_t power_role) { @@ -121,8 +130,16 @@ static inline void pd_config_init(int port, uint8_t power_role) static inline int pd_adc_read(int port, int cc) { - /* only one CC line, assume other one is always low */ - return (cc == 0) ? adc_read_channel(ADC_CH_CC1_PD) : 0; + if (cc == 0) + return adc_read_channel(ADC_CH_CC1_PD); + /* + * Check HOST_HIGH Rp setting. + * Return 3300mV on host mode. + */ + if ((STM32_GPIO_MODER(GPIO_B) & (3 << (2*5))) == (1 << (2*5))) + return 3300; + else + return 0; } #endif /* __CROS_EC_USB_PD_CONFIG_H */ diff --git a/board/coffeecake/usb_pd_policy.c b/board/coffeecake/usb_pd_policy.c index 2b9e9d60d3..e6150dea63 100644 --- a/board/coffeecake/usb_pd_policy.c +++ b/board/coffeecake/usb_pd_policy.c @@ -5,6 +5,7 @@ #include "adc.h" #include "board.h" +#include "charger/sy21612.h" #include "common.h" #include "console.h" #include "ec_commands.h" @@ -22,15 +23,28 @@ #define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) #define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) -#define PDO_FIXED_FLAGS PDO_FIXED_COMM_CAP +#define PDO_FIXED_FLAGS (PDO_FIXED_DUAL_ROLE | PDO_FIXED_DATA_SWAP |\ + PDO_FIXED_COMM_CAP) -/* Source PDOs */ -const uint32_t pd_src_pdo[] = {}; + +/* Voltage indexes for the PDOs */ +enum volt_idx { + PDO_IDX_5V = 0, + PDO_IDX_9V = 1, + /* TODO: add PPS support */ + PDO_IDX_COUNT +}; + +/* PDOs */ +const uint32_t pd_src_pdo[] = { + [PDO_IDX_5V] = PDO_FIXED(5000, 3000, PDO_FIXED_FLAGS), + [PDO_IDX_9V] = PDO_FIXED(9000, 3000, PDO_FIXED_FLAGS), +}; const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); +BUILD_ASSERT(ARRAY_SIZE(pd_src_pdo) == PDO_IDX_COUNT); -/* Fake PDOs : we just want our pre-defined voltages */ const uint32_t pd_snk_pdo[] = { - PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), + PDO_FIXED(5000, 1500, PDO_FIXED_FLAGS), }; const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); @@ -52,16 +66,35 @@ int pd_is_valid_input_voltage(int mv) void pd_transition_voltage(int idx) { - /* No operation: sink only */ + /* TODO: discharge, PPS */ + switch (idx - 1) { + case PDO_IDX_9V: + board_set_usb_output_voltage(9000); + break; + case PDO_IDX_5V: + default: + board_set_usb_output_voltage(5000); + break; + } } int pd_set_power_supply_ready(int port) { + sy21612_set_sink_mode(1); + sy21612_set_vbus_volt(SY21612_VBUS_9V); + sy21612_set_adc_mode(1); + sy21612_enable_adc(1); + sy21612_set_vbus_discharge(1); return EC_SUCCESS; } void pd_power_supply_reset(int port) { + sy21612_set_sink_mode(0); + sy21612_set_vbus_volt(SY21612_VBUS_9V); + sy21612_set_adc_mode(1); + sy21612_enable_adc(1); + sy21612_set_vbus_discharge(1); } int pd_snk_is_vbus_provided(int port) @@ -82,21 +115,26 @@ int pd_check_power_swap(int port) int pd_check_data_swap(int port, int data_role) { - /* Always refuse data swap */ - return 0; + /* We can swap to UFP */ + return data_role == PD_ROLE_DFP; } void pd_execute_data_swap(int port, int data_role) { - /* Do nothing */ + /* TODO: turn on pp5000, pp3300 */ } void pd_check_pr_role(int port, int pr_role, int flags) { + if (pr_role == PD_ROLE_UFP && !gpio_get_level(GPIO_AC_PRESENT_L)) + pd_request_power_swap(port); + } void pd_check_dr_role(int port, int dr_role, int flags) { + if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_DFP) + pd_request_data_swap(port); } /* ----------------- Vendor Defined Messages ------------------ */ const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ |