diff options
author | Alec Berg <alecaberg@chromium.org> | 2015-07-01 14:16:24 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2015-07-06 18:38:33 +0000 |
commit | 319682834457599b1e3da9037e153d201978bda4 (patch) | |
tree | 51a849ef53120e174e2c5e9e119ca979a3c38464 /board/lucid | |
parent | 662ed790927f3fd3a837a20a0638283a6beb2a7e (diff) | |
download | chrome-ec-319682834457599b1e3da9037e153d201978bda4.tar.gz |
lucid: add support for lucid battery pack board
Add support for lucid battery pack board.
BUG=chrome-os-partner:42111
BRANCH=none
TEST=make -j buildall
Change-Id: I145a1a362503bcd35ee92e6c013af4facd95f443
Signed-off-by: Alec Berg <alecaberg@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/283170
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
Diffstat (limited to 'board/lucid')
l--------- | board/lucid/Makefile | 1 | ||||
-rw-r--r-- | board/lucid/battery.c | 54 | ||||
-rw-r--r-- | board/lucid/board.c | 178 | ||||
-rw-r--r-- | board/lucid/board.h | 111 | ||||
-rw-r--r-- | board/lucid/build.mk | 15 | ||||
-rw-r--r-- | board/lucid/ec.tasklist | 24 | ||||
-rw-r--r-- | board/lucid/gpio.inc | 47 | ||||
-rw-r--r-- | board/lucid/usb_pd_config.h | 162 | ||||
-rw-r--r-- | board/lucid/usb_pd_policy.c | 212 |
9 files changed, 804 insertions, 0 deletions
diff --git a/board/lucid/Makefile b/board/lucid/Makefile new file mode 120000 index 0000000000..94aaae2c4d --- /dev/null +++ b/board/lucid/Makefile @@ -0,0 +1 @@ +../../Makefile
\ No newline at end of file diff --git a/board/lucid/battery.c b/board/lucid/battery.c new file mode 100644 index 0000000000..7d1cc7fadd --- /dev/null +++ b/board/lucid/battery.c @@ -0,0 +1,54 @@ +/* Copyright 2015 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. + * + * Battery pack vendor provided charging profile + */ + +#include "battery.h" +#include "battery_smart.h" +#include "i2c.h" +#include "util.h" + +/* Shutdown mode parameter to write to manufacturer access register */ +#define PARAM_CUT_OFF_LOW 0x10 +#define PARAM_CUT_OFF_HIGH 0x00 + +/* Battery info for BQ40Z55 */ +static const struct battery_info info = { + .voltage_max = 4350, /* mV */ + .voltage_normal = 3800, + .voltage_min = 3000, + .precharge_current = 256, /* mA */ + .start_charging_min_c = 0, + .start_charging_max_c = 55, + .charging_min_c = 0, + .charging_max_c = 60, + .discharging_min_c = -20, + .discharging_max_c = 60, +}; + +const struct battery_info *battery_get_info(void) +{ + return &info; +} + +int board_cut_off_battery(void) +{ + int rv; + uint8_t buf[3]; + + /* Ship mode command must be sent twice to take effect */ + buf[0] = SB_MANUFACTURER_ACCESS & 0xff; + buf[1] = PARAM_CUT_OFF_LOW; + buf[2] = PARAM_CUT_OFF_HIGH; + + i2c_lock(I2C_PORT_BATTERY, 1); + rv = i2c_xfer(I2C_PORT_BATTERY, BATTERY_ADDR, buf, 3, NULL, 0, + I2C_XFER_SINGLE); + rv |= i2c_xfer(I2C_PORT_BATTERY, BATTERY_ADDR, buf, 3, NULL, 0, + I2C_XFER_SINGLE); + i2c_lock(I2C_PORT_BATTERY, 0); + + return rv; +} diff --git a/board/lucid/board.c b/board/lucid/board.c new file mode 100644 index 0000000000..7379dfcc25 --- /dev/null +++ b/board/lucid/board.c @@ -0,0 +1,178 @@ +/* Copyright 2015 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. + */ +/* lucid board configuration */ + +#include "adc.h" +#include "adc_chip.h" +#include "charge_manager.h" +#include "charge_state.h" +#include "common.h" +#include "console.h" +#include "extpower.h" +#include "gpio.h" +#include "hooks.h" +#include "i2c.h" +#include "registers.h" +#include "task.h" +#include "util.h" + +#define CPRINTS(format, args...) cprints(CC_USBCHARGE, format, ## args) + +/* Default input current limit when VBUS is present */ +#define DEFAULT_CURR_LIMIT 500 /* mA */ + +void board_config_pre_init(void) +{ + /* enable SYSCFG clock */ + STM32_RCC_APB2ENR |= 1 << 0; + /* + * the DMA mapping is : + * Chan 2 : TIM1_CH1 (C0 RX) + * Chan 3 : SPI1_TX (C0 TX) + * Chan 4 : USART1_TX + * Chan 5 : USART1_RX + */ + + /* + * Remap USART1 RX/TX DMA to match uart driver. + */ + STM32_SYSCFG_CFGR1 |= (1 << 9) | (1 << 10); +} + +static void update_vbus_supplier(int vbus_level) +{ + struct charge_port_info charge; + + charge.voltage = USB_BC12_CHARGE_VOLTAGE; + charge.current = vbus_level ? DEFAULT_CURR_LIMIT : 0; + charge_manager_update_charge(CHARGE_SUPPLIER_VBUS, 0, &charge); +} + +void vbus_evt(enum gpio_signal signal) +{ + /* + * We are using AC_PRESENT signal to detect VBUS presence since + * lucid only has one port and charging is always enabled. + */ + + update_vbus_supplier(gpio_get_level(signal)); + + if (task_start_called()) + task_wake(TASK_ID_PD); + + /* trigger AC present interrupt */ + extpower_interrupt(signal); +} + +#include "gpio_list.h" + +/* ADC channels */ +const struct adc_t adc_channels[] = { + /* USB PD CC lines sensing. Converted to mV (3300mV/4096). */ + [ADC_C0_CC1_PD] = {"C0_CC1_PD", 3300, 4096, 0, STM32_AIN(1)}, + [ADC_C0_CC2_PD] = {"C0_CC2_PD", 3300, 4096, 0, STM32_AIN(3)}, + + /* Vbus sensing. Converted to mV, full ADC is equivalent to 30.25V. */ + [ADC_VBUS] = {"VBUS", 30250, 4096, 0, STM32_AIN(7)}, +}; +BUILD_ASSERT(ARRAY_SIZE(adc_channels) == ADC_CH_COUNT); + +/* I2C ports */ +const struct i2c_port_t i2c_ports[] = { + {"master", I2C_PORT_MASTER, 100, + GPIO_MASTER_I2C_SCL, GPIO_MASTER_I2C_SDA}, + {"slave", I2C_PORT_SLAVE, 100, + GPIO_SLAVE_I2C_SCL, GPIO_SLAVE_I2C_SDA}, +}; +const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports); + +/* Initialize board. */ +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_BC12_CHARGE_VOLTAGE; + 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); + } + + /* Initialize VBUS supplier based on whether or not VBUS is present */ + update_vbus_supplier(gpio_get_level(GPIO_AC_PRESENT)); +} +DECLARE_HOOK(HOOK_INIT, board_init, HOOK_PRIO_DEFAULT); + +int board_set_active_charge_port(int charge_port) +{ + /* Only one port and it's always enabled */ + return EC_SUCCESS; +} + +void board_set_charge_limit(int charge_ma) +{ + int rv; + + charge_ma = MAX(charge_ma, CONFIG_CHARGER_INPUT_CURRENT); + rv = charge_set_input_current_limit(charge_ma); + if (rv < 0) + CPRINTS("Failed to set input current limit for PD"); +} + +/* Charge manager callback function, called on delayed override timeout */ +void board_charge_manager_override_timeout(void) +{ +} +DECLARE_DEFERRED(board_charge_manager_override_timeout); + +/** + * Custom physical check of battery presence. + */ +enum battery_present battery_is_present(void) +{ + return gpio_get_level(GPIO_BAT_PRESENT) ? BP_YES : BP_NO; +} + +static int discharging_on_ac; + +/** + * Discharge battery when on AC power for factory test. + */ +int board_discharge_on_ac(int enable) +{ + int rv = charger_discharge_on_ac(enable); + + if (rv == EC_SUCCESS) + discharging_on_ac = enable; + + return rv; +} + +/** + * Check if we are discharging while connected to AC + */ +int board_is_discharging_on_ac(void) +{ + return discharging_on_ac; +} diff --git a/board/lucid/board.h b/board/lucid/board.h new file mode 100644 index 0000000000..4237d17e71 --- /dev/null +++ b/board/lucid/board.h @@ -0,0 +1,111 @@ +/* Copyright 2015 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. + */ + +/* lucid board configuration */ + +#ifndef __CROS_EC_BOARD_H +#define __CROS_EC_BOARD_H + +/* 48 MHz SYSCLK clock frequency */ +#define CPU_CLOCK 48000000 + +/* the UART console is on USART1 (PA9/PA10) */ +#undef CONFIG_UART_CONSOLE +#define CONFIG_UART_CONSOLE 1 + +/* Optional features */ +#define CONFIG_ADC +#define CONFIG_BATTERY_PRESENT_CUSTOM +#define CONFIG_BATTERY_SMART +#define CONFIG_BOARD_PRE_INIT +#define CONFIG_CHARGE_MANAGER +#define CONFIG_CHARGER +#define CONFIG_CHARGER_V2 +#define CONFIG_CHARGER_DISCHARGE_ON_AC +#define CONFIG_CHARGER_BQ24773 +#define CONFIG_CHARGER_ILIM_PIN_DISABLED +#define CONFIG_CHARGER_INPUT_CURRENT 500 +#define CONFIG_CHARGER_SENSE_RESISTOR 10 +#define CONFIG_CHARGER_SENSE_RESISTOR_AC 10 +#undef CONFIG_CMD_IDLE_STATS +#undef CONFIG_CMD_SHMEM +#undef CONFIG_CMD_TIMERINFO +#undef CONFIG_DEBUG_ASSERT +#define CONFIG_EXTPOWER_GPIO +#define CONFIG_FORCE_CONSOLE_RESUME +#define CONFIG_HIBERNATE_WAKEUP_PINS (STM32_PWR_CSR_EWUP2) +#define CONFIG_HW_CRC +#define CONFIG_I2C +#undef CONFIG_LID_SWITCH +#define CONFIG_LOW_POWER_IDLE +#define CONFIG_STM_HWTIMER32 +#undef CONFIG_TASK_PROFILING +#define CONFIG_USB_POWER_DELIVERY +#define CONFIG_USB_PD_ALT_MODE +#define CONFIG_USB_PD_ALT_MODE_DFP +#define CONFIG_USB_PD_DUAL_ROLE +#define CONFIG_USB_PD_INTERNAL_COMP +#define CONFIG_USB_PD_PORT_COUNT 1 +#define CONFIG_USB_PD_TCPC +#define CONFIG_USB_PD_TCPM_STUB +#undef CONFIG_WATCHDOG_HELP + +/* Use PSTATE embedded in the RO image, not in its own erase block */ +#undef CONFIG_FLASH_PSTATE_BANK +#undef CONFIG_FW_PSTATE_SIZE +#define CONFIG_FW_PSTATE_SIZE 0 + +/* I2C ports configuration */ +#define I2C_PORT_MASTER 1 +#define I2C_PORT_SLAVE 0 +#define I2C_PORT_EC I2C_PORT_SLAVE +#define I2C_PORT_CHARGER I2C_PORT_MASTER +#define I2C_PORT_BATTERY I2C_PORT_MASTER + +/* slave address for host commands */ +#define CONFIG_HOSTCMD_I2C_SLAVE_ADDR 0x3c + +/* Allow dangerous commands */ +#define CONFIG_SYSTEM_UNLOCKED + +/* No Write-protect GPIO, force the write-protection */ +#define CONFIG_WP_ALWAYS + +#ifndef __ASSEMBLER__ + +/* Timer selection */ +#define TIM_CLOCK32 2 +#define TIM_ADC 3 + +#include "gpio_signal.h" + +/* ADC signal */ +enum adc_channel { + ADC_C0_CC1_PD = 0, + ADC_C0_CC2_PD, + ADC_VBUS, + /* Number of ADC channels */ + ADC_CH_COUNT +}; + +/* Discharge battery when on AC power for factory test. */ +int board_discharge_on_ac(int enable); +int board_is_discharging_on_ac(void); + +#define PD_DEFAULT_STATE PD_STATE_SNK_DISCONNECTED + +/* 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 */ + +/* Define typical operating power and max power */ +#define PD_OPERATING_POWER_MW 10000 +#define PD_MAX_POWER_MW 60000 +#define PD_MAX_CURRENT_MA 3000 +#define PD_MAX_VOLTAGE_MV 20000 + +#endif /* !__ASSEMBLER__ */ + +#endif /* __CROS_EC_BOARD_H */ diff --git a/board/lucid/build.mk b/board/lucid/build.mk new file mode 100644 index 0000000000..634d0b8c34 --- /dev/null +++ b/board/lucid/build.mk @@ -0,0 +1,15 @@ +# -*- makefile -*- +# Copyright 2015 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. +# +# Board specific files build + +# the IC is STmicro STM32F072CBU7 +CHIP:=stm32 +CHIP_FAMILY:=stm32f0 +CHIP_VARIANT:=stm32f07x + +board-y=board.o +board-$(CONFIG_BATTERY_SMART)+=battery.o +board-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_policy.o diff --git a/board/lucid/ec.tasklist b/board/lucid/ec.tasklist new file mode 100644 index 0000000000..1537f55eec --- /dev/null +++ b/board/lucid/ec.tasklist @@ -0,0 +1,24 @@ +/* Copyright 2015 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. + */ + +/** + * List of enabled tasks in the priority order + * + * The first one has the lowest priority. + * + * For each task, use the macro TASK_ALWAYS(n, r, d, s) for base tasks and + * TASK_NOTEST(n, r, d, s) for tasks that can be excluded in test binaries, + * where : + * 'n' in the name of the task + * 'r' in the main routine of the task + * 'd' in an opaque parameter passed to the routine at startup + * 's' is the stack size in bytes; must be a multiple of 8 + */ +#define CONFIG_TASK_LIST \ + TASK_ALWAYS(HOOKS, hook_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(CHARGER, charger_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_NOTEST(HOSTCMD, host_command_task, NULL, TASK_STACK_SIZE) \ + TASK_ALWAYS(CONSOLE, console_task, NULL, LARGER_TASK_STACK_SIZE) \ + TASK_ALWAYS(PD, pd_task, NULL, LARGER_TASK_STACK_SIZE) diff --git a/board/lucid/gpio.inc b/board/lucid/gpio.inc new file mode 100644 index 0000000000..aa6f010d02 --- /dev/null +++ b/board/lucid/gpio.inc @@ -0,0 +1,47 @@ +/* -*- mode:c -*- + * + * Copyright 2015 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. + */ + +/* Interrupts */ +GPIO_INT(AC_PRESENT, PIN(C, 13), GPIO_INT_BOTH, vbus_evt) /* AC power present */ + +/* PD RX/TX */ +GPIO(USB_C0_CC1_PD, PIN(A, 1), GPIO_ANALOG) +GPIO(USB_C0_CC2_PD, PIN(A, 3), GPIO_ANALOG) +GPIO(USB_C0_CC1_TX_DATA, PIN(B, 4), GPIO_INPUT) +GPIO(USB_C0_CC2_TX_DATA, PIN(A, 6), GPIO_INPUT) + +#if 0 +/* Alternate functions */ +GPIO(USB_C0_TX_CLKOUT, PIN(B, 15), GPIO_OUT_LOW) +GPIO(USB_C0_TX_CLKIN, PIN(B, 3), GPIO_OUT_LOW) +#endif + +/* Other inputs */ +GPIO(PPVAR_VBUS_SENSE, PIN(A, 7), GPIO_ANALOG) +GPIO(BAT_PRESENT, PIN(A, 14), GPIO_INPUT) +GPIO(USB_C0_N, PIN(A, 11), GPIO_INPUT) +GPIO(USB_C0_P, PIN(A, 12), GPIO_INPUT) + +/* Other outputs */ +GPIO(AP_INT_L, PIN(A, 13), GPIO_ODR_HIGH) +GPIO(USB_C_CC_EN, PIN(A, 15), GPIO_OUT_HIGH) + +UNIMPLEMENTED(ENTERING_RW) + +/* + * I2C pins should be configured as inputs until I2C module is + * initialized. This will avoid driving the lines unintentionally. + */ +GPIO(SLAVE_I2C_SCL, PIN(B, 6), GPIO_INPUT) +GPIO(SLAVE_I2C_SDA, PIN(B, 7), GPIO_INPUT) +GPIO(MASTER_I2C_SCL, PIN(B, 10), GPIO_INPUT) +GPIO(MASTER_I2C_SDA, PIN(B, 11), GPIO_INPUT) + +ALTERNATE(PIN_MASK(B, 0x0008), 0, MODULE_USB_PD, 0) /* SPI1: SCK(PB3) */ +ALTERNATE(PIN_MASK(B, 0x8000), 1, MODULE_USB_PD, 0) /* TIM15_CH2: PB15) */ +ALTERNATE(PIN_MASK(A, 0x0600), 1, MODULE_UART, 0) /* USART1: PA9/PA10 */ +ALTERNATE(PIN_MASK(B, 0x0cc0), 1, MODULE_I2C, 0) /* I2C SLAVE:PB6/7 MASTER:PB10/11 */ diff --git a/board/lucid/usb_pd_config.h b/board/lucid/usb_pd_config.h new file mode 100644 index 0000000000..50c42489af --- /dev/null +++ b/board/lucid/usb_pd_config.h @@ -0,0 +1,162 @@ +/* Copyright 2015 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. + */ + +#include "adc.h" +#include "gpio.h" +#include "registers.h" + +/* USB Power delivery board configuration */ + +#ifndef __CROS_EC_USB_PD_CONFIG_H +#define __CROS_EC_USB_PD_CONFIG_H + +/* Timer selection for baseband PD communication */ +#define TIM_CLOCK_PD_TX_C0 15 +#define TIM_CLOCK_PD_RX_C0 1 + +#define TIM_CLOCK_PD_TX(p) TIM_CLOCK_PD_TX_C0 +#define TIM_CLOCK_PD_RX(p) TIM_CLOCK_PD_RX_C0 + +/* Timer channel */ +#define TIM_RX_CCR_C0 1 +#define TIM_TX_CCR_C0 2 + +/* RX timer capture/compare register */ +#define TIM_CCR_C0 (&STM32_TIM_CCRx(TIM_CLOCK_PD_RX_C0, TIM_RX_CCR_C0)) +#define TIM_RX_CCR_REG(p) TIM_CCR_C0 + +/* TX and RX timer register */ +#define TIM_REG_TX_C0 (STM32_TIM_BASE(TIM_CLOCK_PD_TX_C0)) +#define TIM_REG_RX_C0 (STM32_TIM_BASE(TIM_CLOCK_PD_RX_C0)) +#define TIM_REG_TX(p) TIM_REG_TX_C0 +#define TIM_REG_RX(p) TIM_REG_RX_C0 + +/* use the hardware accelerator for CRC */ +#define CONFIG_HW_CRC + +/* TX uses SPI1 on PB3-4 */ +#define SPI_REGS(p) STM32_SPI1_REGS +static inline void spi_enable_clock(int port) +{ + STM32_RCC_APB2ENR |= STM32_RCC_PB2_SPI1; +} + +/* DMA for transmit uses DMA_CH3 */ +#define DMAC_SPI_TX(p) STM32_DMAC_CH3 + +/* RX uses COMP1 and COMP2 on TIM1 CH1 */ +#define CMP1OUTSEL STM32_COMP_CMP1OUTSEL_TIM1_IC1 +#define CMP2OUTSEL STM32_COMP_CMP2OUTSEL_TIM1_IC1 + +#define TIM_TX_CCR_IDX(p) TIM_TX_CCR_C0 +#define TIM_RX_CCR_IDX(p) TIM_RX_CCR_C0 +#define TIM_CCR_CS 1 +#define EXTI_COMP_MASK(p) ((1 << 21) | (1 << 22)) +#define IRQ_COMP STM32_IRQ_COMP +/* triggers packet detection on comparator falling edge */ +#define EXTI_XTSR STM32_EXTI_FTSR + +/* DMA for receive uses DMA_CH2 */ +#define DMAC_TIM_RX(p) STM32_DMAC_CH2 + +/* the pins used for communication need to be hi-speed */ +static inline void pd_set_pins_speed(int port) +{ + /* 40 MHz pin speed on SPI PB3/4/15 */ + STM32_GPIO_OSPEEDR(GPIO_B) |= 0xC00003C0; + /* 40 MHz pin speed on SPI PA6 */ + STM32_GPIO_OSPEEDR(GPIO_A) |= 0x00003000; +} + +/* Reset SPI peripheral used for TX */ +static inline void pd_tx_spi_reset(int port) +{ + /* Reset SPI1 */ + STM32_RCC_APB2RSTR |= (1 << 12); + STM32_RCC_APB2RSTR &= ~(1 << 12); +} + +/* Drive the CC line from the TX block */ +static inline void pd_tx_enable(int port, int polarity) +{ + /* put SPI function on TX pin */ + if (polarity) { + /* USB_C0_CC2_TX_DATA: PA6 is SPI1 MISO */ + gpio_set_alternate_function(GPIO_A, 0x0040, 0); + /* MCU ADC PA3 pin output low */ + STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) + & ~(3 << (2*3))) /* PA3 disable ADC */ + | (1 << (2*3)); /* Set as GPO */ + gpio_set_level(GPIO_USB_C0_CC2_PD, 0); + } else { + /* USB_C0_CC1_TX_DATA: PB4 is SPI1 MISO */ + gpio_set_alternate_function(GPIO_B, 0x0010, 0); + /* MCU ADC PA1 pin output low */ + STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) + & ~(3 << (2*1))) /* PA1 disable ADC */ + | (1 << (2*1)); /* Set as GPO */ + gpio_set_level(GPIO_USB_C0_CC1_PD, 0); + } + +} + +/* Put the TX driver in Hi-Z state */ +static inline void pd_tx_disable(int port, int polarity) +{ + if (polarity) { + /* Set TX_DATA to Hi-Z, PA6 is SPI1 MISO */ + STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) + & ~(3 << (2*6))); + /* set ADC PA3 pin to ADC function (Hi-Z) */ + STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) + | (3 << (2*3))); /* PA3 as ADC */ + } else { + /* Set TX_DATA to Hi-Z, PB4 is SPI1 MISO */ + STM32_GPIO_MODER(GPIO_B) = (STM32_GPIO_MODER(GPIO_B) + & ~(3 << (2*4))); + /* set ADC PA1 pin to ADC function (Hi-Z) */ + STM32_GPIO_MODER(GPIO_A) = (STM32_GPIO_MODER(GPIO_A) + | (3 << (2*1))); /* PA1 as ADC */ + } +} + +/* we know the plug polarity, do the right configuration */ +static inline void pd_select_polarity(int port, int polarity) +{ + /* + * use the right comparator : CC1 -> PA1 (COMP1 INP) + * CC2 -> PA3 (COMP2 INP) + * use VrefInt / 2 as INM (about 600mV) + */ + STM32_COMP_CSR = (STM32_COMP_CSR + & ~(STM32_COMP_CMP1INSEL_MASK | STM32_COMP_CMP2INSEL_MASK + | STM32_COMP_CMP1EN | STM32_COMP_CMP2EN)) + | STM32_COMP_CMP1INSEL_VREF12 | STM32_COMP_CMP2INSEL_VREF12 + | (polarity ? STM32_COMP_CMP2EN : STM32_COMP_CMP1EN); +} + +/* Initialize pins used for TX and put them in Hi-Z */ +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) +{ + /* We're always a pull-down, nothing to do here */ +} + +static inline void pd_config_init(int port, uint8_t power_role) +{ + /* Initialize TX pins and put them in Hi-Z */ + pd_tx_init(); +} + +static inline int pd_adc_read(int port, int cc) +{ + return adc_read_channel(cc ? ADC_C0_CC2_PD : ADC_C0_CC1_PD); +} + +#endif /* __CROS_EC_USB_PD_CONFIG_H */ diff --git a/board/lucid/usb_pd_policy.c b/board/lucid/usb_pd_policy.c new file mode 100644 index 0000000000..380e45454d --- /dev/null +++ b/board/lucid/usb_pd_policy.c @@ -0,0 +1,212 @@ +/* Copyright 2015 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. + */ + +#include "charge_manager.h" +#include "common.h" +#include "console.h" +#include "gpio.h" +#include "hooks.h" +#include "registers.h" +#include "system.h" +#include "task.h" +#include "timer.h" +#include "util.h" +#include "usb_pd.h" + +#define CPRINTF(format, args...) cprintf(CC_USBPD, format, ## args) +#define CPRINTS(format, args...) cprints(CC_USBPD, format, ## args) + +#define PDO_FIXED_FLAGS PDO_FIXED_DATA_SWAP + +/* Source PDOs */ +const uint32_t pd_src_pdo[] = {}; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); + +const uint32_t pd_snk_pdo[] = { + PDO_FIXED(5000, 500, PDO_FIXED_FLAGS), + PDO_BATT(4750, 21000, 15000), + PDO_VAR(4750, 21000, 3000), +}; +const int pd_snk_pdo_cnt = ARRAY_SIZE(pd_snk_pdo); + +int pd_is_valid_input_voltage(int mv) +{ + /* Any voltage less than the max is allowed */ + return 1; +} + +int pd_check_requested_voltage(uint32_t rdo) +{ + return EC_SUCCESS; +} + +void pd_transition_voltage(int idx) +{ + /* No operation: sink only */ +} + +int pd_set_power_supply_ready(int port) +{ + return EC_SUCCESS; +} + +void pd_power_supply_reset(int port) +{ +} + +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(CHARGE_SUPPLIER_PD, port, &charge); +} + +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(CHARGE_SUPPLIER_TYPEC, port, &charge); +} + +int pd_snk_is_vbus_provided(int port) +{ + return gpio_get_level(GPIO_AC_PRESENT); +} + +int pd_board_checks(void) +{ + return EC_SUCCESS; +} + +int pd_check_power_swap(int port) +{ + /* Always refuse power swap */ + return 0; +} + +int pd_check_data_swap(int port, int data_role) +{ + /* Allow data swap if we are a UFP, otherwise don't allow */ + return (data_role == PD_ROLE_UFP) ? 1 : 0; +} + +void pd_execute_data_swap(int port, int data_role) +{ + /* Do nothing */ +} + +void pd_check_pr_role(int port, int pr_role, int flags) +{ +} + +void pd_check_dr_role(int port, int dr_role, int flags) +{ + /* If UFP, try to switch to DFP */ + if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_UFP) + pd_request_data_swap(port); +} +/* ----------------- Vendor Defined Messages ------------------ */ +const struct svdm_response svdm_rsp = { + .identity = NULL, + .svids = NULL, + .modes = NULL, +}; + +int pd_custom_vdm(int port, int cnt, uint32_t *payload, + uint32_t **rpayload) +{ + int cmd = PD_VDO_CMD(payload[0]); + uint16_t dev_id = 0; + int is_rw; + + /* make sure we have some payload */ + if (cnt == 0) + return 0; + + switch (cmd) { + case VDO_CMD_VERSION: + /* guarantee last byte of payload is null character */ + *(payload + cnt - 1) = 0; + CPRINTF("version: %s\n", (char *)(payload+1)); + break; + case VDO_CMD_READ_INFO: + case VDO_CMD_SEND_INFO: + /* copy hash */ + if (cnt == 7) { + dev_id = VDO_INFO_HW_DEV_ID(payload[6]); + is_rw = VDO_INFO_IS_RW(payload[6]); + pd_dev_store_rw_hash(port, + dev_id, + payload + 1, + is_rw ? + SYSTEM_IMAGE_RW : + SYSTEM_IMAGE_RO); + + CPRINTF("DevId:%d.%d SW:%d RW:%d\n", + HW_DEV_ID_MAJ(dev_id), + HW_DEV_ID_MIN(dev_id), + VDO_INFO_SW_DBG_VER(payload[6]), + is_rw); + } else if (cnt == 6) { + /* really old devices don't have last byte */ + pd_dev_store_rw_hash(port, dev_id, payload + 1, + SYSTEM_IMAGE_UNKNOWN); + } + break; + case VDO_CMD_CURRENT: + CPRINTF("Current: %dmA\n", payload[1]); + break; + case VDO_CMD_GET_LOG: + break; + } + + return 0; +} + +static int svdm_enter_gfu_mode(int port, uint32_t mode_caps) +{ + /* Always enter GFU mode */ + return 0; +} + +static void svdm_exit_gfu_mode(int port) +{ +} + +static int svdm_gfu_status(int port, uint32_t *payload) +{ + /* + * This is called after enter mode is successful, send unstructured + * VDM to read info. + */ + pd_send_vdm(port, USB_VID_GOOGLE, VDO_CMD_READ_INFO, NULL, 0); + return 0; +} + +static int svdm_gfu_config(int port, uint32_t *payload) +{ + return 0; +} + +static int svdm_gfu_attention(int port, uint32_t *payload) +{ + return 0; +} + +const struct svdm_amode_fx supported_modes[] = { + { + .svid = USB_VID_GOOGLE, + .enter = &svdm_enter_gfu_mode, + .status = &svdm_gfu_status, + .config = &svdm_gfu_config, + .attention = &svdm_gfu_attention, + .exit = &svdm_exit_gfu_mode, + } +}; +const int supported_modes_cnt = ARRAY_SIZE(supported_modes); |