From a1e8b316db8b72e0f23c1475a8d4ae715a4ca38d Mon Sep 17 00:00:00 2001 From: Vincent Palatin Date: Thu, 27 Mar 2014 21:31:59 -0700 Subject: Zinger board configuration Add the USB Power delivery PHY configuration, and all the pins and details to use the real Zinger board. Signed-off-by: Vincent Palatin BRANCH=none BUG=none TEST=none Change-Id: Ic2d3616c9fd2bf3ebeccba74a5519697e7c3e899 Reviewed-on: https://chromium-review.googlesource.com/194220 Tested-by: Vincent Palatin Reviewed-by: Randall Spangler Commit-Queue: Vincent Palatin --- board/zinger/board.c | 197 +++---------------------------------------- board/zinger/board.h | 25 ++++++ board/zinger/build.mk | 2 +- board/zinger/hardware.c | 180 +++++++++++++++++++++++++++++++++++++++ board/zinger/runtime.c | 96 +++++++++++++++++++++ board/zinger/usb_pd_config.h | 79 +++++++++++++++++ board/zinger/usb_pd_policy.c | 108 ++++++++++++++++++++++++ util/flash_ec | 2 +- 8 files changed, 502 insertions(+), 187 deletions(-) create mode 100644 board/zinger/hardware.c create mode 100644 board/zinger/runtime.c create mode 100644 board/zinger/usb_pd_config.h create mode 100644 board/zinger/usb_pd_policy.c diff --git a/board/zinger/board.c b/board/zinger/board.c index f48979dbd0..9a830e7e14 100644 --- a/board/zinger/board.c +++ b/board/zinger/board.c @@ -6,205 +6,32 @@ #include "common.h" #include "debug.h" +#include "irq_handler.h" #include "registers.h" -#include "timer.h" +#include "usb_pd.h" #include "util.h" -static void clock_init(void) -{ - /* put 1 Wait-State for flash access to ensure proper reads at 48Mhz */ - STM32_FLASH_ACR = 0x1001; /* 1 WS / Prefetch enabled */ - - /* Ensure that HSI8 is ON */ - if (!(STM32_RCC_CR & (1 << 1))) { - /* Enable HSI */ - STM32_RCC_CR |= 1 << 0; - /* Wait for HSI to be ready */ - while (!(STM32_RCC_CR & (1 << 1))) - ; - } - /* PLLSRC = HSI, PLLMUL = x12 (x HSI/2) = 48Mhz */ - STM32_RCC_CFGR = 0x00288000; - /* Enable PLL */ - STM32_RCC_CR |= 1 << 24; - /* Wait for PLL to be ready */ - while (!(STM32_RCC_CR & (1 << 25))) - ; - - /* switch SYSCLK to PLL */ - STM32_RCC_CFGR = 0x00288002; - /* wait until the PLL is the clock source */ - while ((STM32_RCC_CFGR & 0xc) != 0x8) - ; -} - -static void power_init(void) -{ - /* enable SYSCFG, COMP, ADC, SPI1, USART1, TIM17 */ - STM32_RCC_APB2ENR = 0x00045201; - /* enable TIM2, TIM14, PWR */ - STM32_RCC_APB1ENR = 0x10000101; - /* enable DMA, SRAM, CRC, GPA, GPB, GPC, GPF */ - STM32_RCC_AHBENR = 0x4e0045; - /* TODO: remove GPC on real board */ -} - -/* GPIO setting helpers */ -#define OUT(n) (1 << ((n) * 2)) -#define AF(n) (2 << ((n) * 2)) -#define ANALOG(n) (3 << ((n) * 2)) -#define HIGH(n) (1 << (n)) -#define ODR(n) (1 << (n)) -#define HISPEED(n) (3 << ((n) * 2)) -#define AFx(n, x) (x << (((n) % 8) * 4)) -/* GPIO level setting helpers through BSRR register */ -#define GPIO_SET(n) (1 << (n)) -#define GPIO_RESET(n) (1 << ((n) + 16)) - -static void pins_init(void) -{ - /* Pin usage: - * PA0 () : Wakeup on Vnc / Threshold - * PA1 (ANALOG - ADC_IN1) : CC sense - * PA2 (ANALOG - ADC_IN2) : Current sense - * PA3 (ANALOG - ADC_IN3) : Voltage sense - * PA4 (OUT - OD GPIO) : PD TX enable - * PA5 (AF0 - SPI1_SCK) : TX clock in - * PA6 (AF0 - SPI1_MISO) : PD TX - * PA7 (AF5 - TIM17_CH1) : PD RX - * PA9 (AF1 - UART1_TX) : [DEBUG] UART TX - * PA10 (AF1 - UART1_RX) : [DEBUG] UART RX - * PA13 (OUT - GPIO) : voltage select[0] - * PA14 (OUT - GPIO) : voltage select[1] - * PB1 (AF0 - TIM14_CH1) : TX clock out - * PF0 (OUT - GPIO) : LM5050 FET driver off - * PF1 (OUT - GPIO) : discharge FET - */ - STM32_GPIO_ODR(GPIO_A) = HIGH(4) | HIGH(6); - STM32_GPIO_AFRL(GPIO_A) = AFx(7, 5); - STM32_GPIO_AFRH(GPIO_A) = AFx(9, 1) | AFx(10, 1); - STM32_GPIO_OTYPER(GPIO_A) = ODR(4) | ODR(6); - STM32_GPIO_OSPEEDR(GPIO_A) = HISPEED(5) | HISPEED(6) | HISPEED(7); - STM32_GPIO_MODER(GPIO_A) = ANALOG(1) | ANALOG(2) | ANALOG(3) | OUT(4) - | AF(5) /*| AF(6)*/ | AF(7) | AF(9) | AF(10) - | OUT(13) | OUT(14); - /* set PF0 / PF1 as output, PF0 is open-drain, high by default */ - STM32_GPIO_ODR(GPIO_F) = HIGH(0); - STM32_GPIO_MODER(GPIO_F) = OUT(0) | OUT(1); - STM32_GPIO_OTYPER(GPIO_F) = ODR(1); - - /* Set PB1 as AF0 (TIM14_CH1) */ - STM32_GPIO_OSPEEDR(GPIO_B) = HISPEED(1); - STM32_GPIO_MODER(GPIO_B) = AF(1); - - /* --- dev board only --- */ - /* - * Blue LED : PC8 (OUT) - * Green LED : PC9 (OUT) - */ - STM32_GPIO_ODR(GPIO_C) = HIGH(9); - STM32_GPIO_MODER(GPIO_C) = OUT(8) | OUT(9); -} - - -static void uart_init(void) -{ - /* set baudrate */ - STM32_USART_BRR(UARTN) = - DIV_ROUND_NEAREST(CPU_CLOCK, CONFIG_UART_BAUD_RATE); - /* UART enabled, 8 Data bits, oversampling x16, no parity */ - STM32_USART_CR1(UARTN) = - STM32_USART_CR1_UE | STM32_USART_CR1_TE | STM32_USART_CR1_RE; - /* 1 stop bit, no fancy stuff */ - STM32_USART_CR2(UARTN) = 0x0000; - /* DMA disabled, special modes disabled, error interrupt disabled */ - STM32_USART_CR3(UARTN) = 0x0000; -} - -static void timers_init(void) -{ - /* TIM2 is a 32-bit free running counter with 1Mhz frequency */ - STM32_TIM_CR2(2) = 0x0000; - STM32_TIM32_ARR(2) = 0xFFFFFFFF; - STM32_TIM32_CNT(2) = 0; - STM32_TIM_PSC(2) = CPU_CLOCK / 1000000 - 1; - STM32_TIM_EGR(2) = 0x0001; /* Reload the pre-scaler */ - STM32_TIM_CR1(2) = 1; -} - -timestamp_t get_time(void) -{ - timestamp_t t; - - t.le.lo = STM32_TIM32_CNT(2); - t.le.hi = 0; - return t; -} - -void udelay(unsigned us) -{ - unsigned t0 = STM32_TIM32_CNT(2); - while ((STM32_TIM32_CNT(2) - t0) < us) - ; -} - -static void hardware_init(void) -{ - power_init(); - clock_init(); - pins_init(); - uart_init(); - timers_init(); -} - -/* ------------------------- Power supply control ------------------------ */ - -/* Output voltage selection */ -enum volt { - VO_5V = GPIO_RESET(13) | GPIO_RESET(14), - VO_12V = GPIO_SET(13) | GPIO_RESET(14), - VO_13V = GPIO_RESET(13) | GPIO_SET(14), - VO_20V = GPIO_SET(13) | GPIO_SET(14), -}; - -static inline void set_output_voltage(enum volt v) -{ - /* set voltage_select on PA13/PA14 */ - STM32_GPIO_BSRR(GPIO_A) = v; -} - -static inline void output_enable(void) -{ - /* GPF0 (FET driver shutdown) = 0 */ - STM32_GPIO_BSRR(GPIO_F) = GPIO_RESET(0); -} +extern void pd_rx_handler(void); -static inline void output_disable(void) +/* External interrupt EXTINT7 for external comparator on PA7 */ +void IRQ_HANDLER(STM32_IRQ_EXTI4_15)(void) { - /* GPF0 (FET driver shutdown) = 1 */ - STM32_GPIO_BSRR(GPIO_F) = GPIO_SET(0); + /* clear the interrupt */ + STM32_EXTI_PR = STM32_EXTI_PR; + /* trigger reception handling */ + pd_rx_handler(); } -/* default forced output voltage */ -#define VO_DEFAULT VO_12V +extern void pd_task(void); int main(void) { hardware_init(); debug_printf("Power supply started ...\n"); - set_output_voltage(VO_DEFAULT); - debug_printf("set output voltage : " STRINGIFY(VO_DEFAULT) "\n"); - output_enable(); + /* background loop for PD events */ + pd_task(); - while (1) { - /* magic LED blinker on the test board */ - STM32_GPIO_BSRR(GPIO_C) = GPIO_SET(8); - udelay(200000); - STM32_GPIO_BSRR(GPIO_C) = GPIO_RESET(8); - udelay(750000); - debug_printf("%T ALIVE\n"); - } while (1) ; } diff --git a/board/zinger/board.h b/board/zinger/board.h index fccdb2a01e..90b492871b 100644 --- a/board/zinger/board.h +++ b/board/zinger/board.h @@ -15,6 +15,10 @@ #define CONFIG_UART_CONSOLE 1 /* Optional features */ +#define CONFIG_USB_POWER_DELIVERY +#undef CONFIG_USB_PD_DUAL_ROLE +#undef CONFIG_USB_PD_INTERNAL_COMP +#define CONFIG_HW_CRC #undef CONFIG_WATCHDOG_HELP #undef CONFIG_LID_SWITCH #undef CONFIG_TASK_PROFILING @@ -29,15 +33,36 @@ #undef CONFIG_FLASH #undef CONFIG_FMAP +/* Stub value */ +#define TASK_ID_PD 0 + /* debug printf flash footprinf is about 1400 bytes */ #define CONFIG_DEBUG_PRINTF #define UARTN CONFIG_UART_CONSOLE #ifndef __ASSEMBLER__ +#include "common.h" + /* No GPIO abstraction layer */ enum gpio_signal; +enum adc_channel { + ADC_CH_CC1_PD = 1, + ADC_CH_A_SENSE = 2, + ADC_CH_V_SENSE = 3, + /* Number of ADC channels */ + ADC_CH_COUNT +}; +/* captive cable : no CC2 */ +#define ADC_CH_CC2_PD ADC_CH_CC1_PD + +/* Initialize all useful registers */ +void hardware_init(void); + +/* last interrupt event */ +extern volatile uint32_t last_event; + #endif /* !__ASSEMBLER__ */ #endif /* __BOARD_H */ diff --git a/board/zinger/build.mk b/board/zinger/build.mk index 9a1249744a..4e9e2f1f6d 100644 --- a/board/zinger/build.mk +++ b/board/zinger/build.mk @@ -10,5 +10,5 @@ CHIP:=stm32 CHIP_FAMILY:=stm32f0 CHIP_VARIANT:=stm32f03x -board-y=board.o +board-y=board.o hardware.o runtime.o usb_pd_policy.o board-$(CONFIG_DEBUG_PRINTF)+=debug.o diff --git a/board/zinger/hardware.c b/board/zinger/hardware.c new file mode 100644 index 0000000000..0a939a72eb --- /dev/null +++ b/board/zinger/hardware.c @@ -0,0 +1,180 @@ +/* Copyright (c) 2014 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. + */ +/* Hardware initialization and common functions */ + +#include "adc.h" +#include "adc_chip.h" +#include "common.h" +#include "cpu.h" +#include "registers.h" +#include "task.h" +#include "timer.h" +#include "util.h" + +static void clock_init(void) +{ + /* put 1 Wait-State for flash access to ensure proper reads at 48Mhz */ + STM32_FLASH_ACR = 0x1001; /* 1 WS / Prefetch enabled */ + + /* Ensure that HSI8 is ON */ + if (!(STM32_RCC_CR & (1 << 1))) { + /* Enable HSI */ + STM32_RCC_CR |= 1 << 0; + /* Wait for HSI to be ready */ + while (!(STM32_RCC_CR & (1 << 1))) + ; + } + /* PLLSRC = HSI, PLLMUL = x12 (x HSI/2) = 48Mhz */ + STM32_RCC_CFGR = 0x00288000; + /* Enable PLL */ + STM32_RCC_CR |= 1 << 24; + /* Wait for PLL to be ready */ + while (!(STM32_RCC_CR & (1 << 25))) + ; + + /* switch SYSCLK to PLL */ + STM32_RCC_CFGR = 0x00288002; + /* wait until the PLL is the clock source */ + while ((STM32_RCC_CFGR & 0xc) != 0x8) + ; +} + +static void power_init(void) +{ + /* enable SYSCFG, COMP, ADC, SPI1, USART1 */ + STM32_RCC_APB2ENR = 0x00005201; + /* enable TIM2, TIM3, TIM14, PWR */ + STM32_RCC_APB1ENR = 0x10000103; + /* enable DMA, SRAM, CRC, GPA, GPB, GPF */ + STM32_RCC_AHBENR = 0x460045; +} + +/* GPIO setting helpers */ +#define OUT(n) (1 << ((n) * 2)) +#define AF(n) (2 << ((n) * 2)) +#define ANALOG(n) (3 << ((n) * 2)) +#define HIGH(n) (1 << (n)) +#define ODR(n) (1 << (n)) +#define HISPEED(n) (3 << ((n) * 2)) +#define AFx(n, x) (x << (((n) % 8) * 4)) + +static void pins_init(void) +{ + /* Pin usage: + * PA0 (OUT - OD GPIO) : Wakeup on Vnc / Threshold + * PA1 (ANALOG - ADC_IN1) : CC sense + * PA2 (ANALOG - ADC_IN2) : Current sense + * PA3 (ANALOG - ADC_IN3) : Voltage sense + * PA4 (OUT - OD GPIO) : PD TX enable + * PA5 (AF0 - SPI1_SCK) : TX clock in + * PA6 (AF0 - SPI1_MISO) : PD TX + * PA7 (AF5 - TIM3_CH2) : PD RX + * PA9 (AF1 - UART1_TX) : [DEBUG] UART TX + * PA10 (AF1 - UART1_RX) : [DEBUG] UART RX + * PA13 (OUT - GPIO) : voltage select[0] + * PA14 (OUT - GPIO) : voltage select[1] + * PB1 (AF0 - TIM14_CH1) : TX clock out + * PF0 (OUT - GPIO) : LM5050 FET driver off + * PF1 (OUT - GPIO) : discharge FET + */ + STM32_GPIO_ODR(GPIO_A) = /* HIGH(0) | */ HIGH(4); + STM32_GPIO_AFRL(GPIO_A) = AFx(7, 1); + STM32_GPIO_AFRH(GPIO_A) = AFx(9, 1) | AFx(10, 1); + STM32_GPIO_OTYPER(GPIO_A) = ODR(0) | ODR(4); + STM32_GPIO_OSPEEDR(GPIO_A) = HISPEED(5) | HISPEED(6) | HISPEED(7); + STM32_GPIO_MODER(GPIO_A) = OUT(0) | ANALOG(1) | ANALOG(2) | ANALOG(3) + | OUT(4) | AF(5) /*| AF(6)*/ | AF(7) | AF(9) + | AF(10) | OUT(13) | OUT(14); + /* set PF0 / PF1 as output, PF0 is open-drain, high by default */ + STM32_GPIO_ODR(GPIO_F) = HIGH(0); + STM32_GPIO_MODER(GPIO_F) = OUT(0) | OUT(1); + STM32_GPIO_OTYPER(GPIO_F) = ODR(0); + + /* Set PB1 as AF0 (TIM14_CH1) */ + STM32_GPIO_OSPEEDR(GPIO_B) = HISPEED(1); + STM32_GPIO_MODER(GPIO_B) = AF(1); +} + +static void adc_init(void) +{ + /* ADC calibration (done with ADEN = 0) */ + STM32_ADC_CR = 1 << 31; /* set ADCAL = 1, ADC off */ + /* wait for the end of calibration */ + while (STM32_ADC_CR & (1 << 31)) + ; + /* ADC enabled */ + STM32_ADC_CR = 1 << 0; + /* Single conversion, right aligned, 12-bit */ + STM32_ADC_CFGR1 = 1 << 12; /* (1 << 15) => AUTOOFF */; + /* clock is ADCCLK */ + STM32_ADC_CFGR2 = 0; + /* Sampling time : 13.5 ADC clock cycles. */ + STM32_ADC_SMPR = 2; +} + +static void uart_init(void) +{ + /* set baudrate */ + STM32_USART_BRR(UARTN) = + DIV_ROUND_NEAREST(CPU_CLOCK, CONFIG_UART_BAUD_RATE); + /* UART enabled, 8 Data bits, oversampling x16, no parity */ + STM32_USART_CR1(UARTN) = + STM32_USART_CR1_UE | STM32_USART_CR1_TE | STM32_USART_CR1_RE; + /* 1 stop bit, no fancy stuff */ + STM32_USART_CR2(UARTN) = 0x0000; + /* DMA disabled, special modes disabled, error interrupt disabled */ + STM32_USART_CR3(UARTN) = 0x0000; +} + +static void timers_init(void) +{ + /* TIM2 is a 32-bit free running counter with 1Mhz frequency */ + STM32_TIM_CR2(2) = 0x0000; + STM32_TIM32_ARR(2) = 0xFFFFFFFF; + STM32_TIM32_CNT(2) = 0; + STM32_TIM_PSC(2) = CPU_CLOCK / 1000000 - 1; + STM32_TIM_EGR(2) = 0x0001; /* Reload the pre-scaler */ + STM32_TIM_CR1(2) = 1; + STM32_TIM_DIER(2) = 0; + task_enable_irq(STM32_IRQ_TIM2); +} + +static void irq_init(void) +{ + /* clear all pending interrupts */ + CPU_NVIC_UNPEND(0) = 0xffffffff; + /* enable global interrupts */ + asm("cpsie i"); +} + +void hardware_init(void) +{ + power_init(); + clock_init(); + pins_init(); + uart_init(); + timers_init(); + adc_init(); + irq_init(); +} + +int adc_read_channel(enum adc_channel ch) +{ + int value; + + /* Select channel to convert */ + STM32_ADC_CHSELR = 1 << ch; + /* Clear flags */ + STM32_ADC_ISR = 0xe; + /* Start conversion */ + STM32_ADC_CR |= 1 << 2; /* ADSTART */ + /* Wait for end of conversion */ + while (!(STM32_ADC_ISR & (1 << 2))) + ; + /* read converted value */ + value = STM32_ADC_DR; + + return value; +} diff --git a/board/zinger/runtime.c b/board/zinger/runtime.c new file mode 100644 index 0000000000..24558693db --- /dev/null +++ b/board/zinger/runtime.c @@ -0,0 +1,96 @@ +/* Copyright (c) 2014 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. + */ +/* tiny substitute of the runtime layer */ + +#include "common.h" +#include "cpu.h" +#include "debug.h" +#include "irq_handler.h" +#include "registers.h" +#include "timer.h" +#include "util.h" + +volatile uint32_t last_event; + +timestamp_t get_time(void) +{ + timestamp_t t; + + t.le.lo = STM32_TIM32_CNT(2); + t.le.hi = 0; + return t; +} + +void udelay(unsigned us) +{ + unsigned t0 = STM32_TIM32_CNT(2); + while ((STM32_TIM32_CNT(2) - t0) < us) + ; +} + +void task_enable_irq(int irq) +{ + CPU_NVIC_EN(0) = 1 << irq; +} + +void task_disable_irq(int irq) +{ + CPU_NVIC_DIS(0) = 1 << irq; +} + +void task_clear_pending_irq(int irq) +{ + CPU_NVIC_UNPEND(0) = 1 << irq; +} + +uint32_t task_set_event(task_id_t tskid, uint32_t event, int wait) +{ + last_event = event; + + return 0; +} + +void IRQ_HANDLER(STM32_IRQ_TIM2)(void) +{ + STM32_TIM_DIER(2) = 0; /* disable match interrupt */ + task_clear_pending_irq(STM32_IRQ_TIM2); + last_event = 1 << 29 /* task event wake */; +} + +uint32_t task_wait_event(int timeout_us) +{ + uint32_t evt; + + /* the event already happened */ + if (last_event || !timeout_us) { + evt = last_event; + last_event = 0; + + return evt; + } + + /* set timeout on timer */ + if (timeout_us > 0) { + STM32_TIM32_CCR1(2) = STM32_TIM32_CNT(2) + timeout_us; + STM32_TIM_SR(2) = 0; /* clear match flag */ + STM32_TIM_DIER(2) = 2; /* match interrupt */ + } + + /* sleep until next interrupt */ + asm volatile("wfi"); + + STM32_TIM_DIER(2) = 0; /* disable match interrupt */ + evt = last_event; + last_event = 0; + + return evt; +} + +/* --- stubs --- */ +void __hw_timer_enable_clock(int n, int enable) +{ /* Done in hardware init */ } + +void usleep(unsigned us) +{ /* Used only as a workaround */ } diff --git a/board/zinger/usb_pd_config.h b/board/zinger/usb_pd_config.h new file mode 100644 index 0000000000..0900f51a05 --- /dev/null +++ b/board/zinger/usb_pd_config.h @@ -0,0 +1,79 @@ +/* Copyright (c) 2014 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. + */ + +/* USB Power delivery board configuration */ + +#ifndef __USB_PD_CONFIG_H +#define __USB_PD_CONFIG_H + +/* Timer selection for baseband PD communication */ +#define TIM_CLOCK_PD_TX 14 +#define TIM_CLOCK_PD_RX 3 + +/* use the hardware accelerator for CRC */ +#define CONFIG_HW_CRC + +/* TX is using SPI1 on PA4-6 */ +#define SPI_REGS STM32_SPI1_REGS +#define DMAC_SPI_TX STM32_DMAC_CH3 + +static inline void spi_enable_clock(void) +{ + /* Already done in hardware_init() */ +} + +/* RX is on TIM3 CH1 connected to TIM3 CH2 pin (PA7, not internal COMP) */ +#define DMAC_TIM_RX STM32_DMAC_CH4 +#define TIM_CCR_IDX 1 +/* connect TIM3 CH1 to TIM3_CH2 input */ +#define TIM_CCR_CS 2 +#define EXTI_COMP 7 +#define IRQ_COMP STM32_IRQ_EXTI4_15 +/* the RX is inverted, triggers on rising edge */ +#define EXTI_XTSR STM32_EXTI_RTSR + +/* Clock divider for RX edges timings (2.4Mhz counter from 48Mhz clock) */ +#define RX_CLOCK_DIV (20 - 1) + +/* the pins used for communication need to be hi-speed */ +static inline void pd_set_pins_speed(void) +{ + /* Already done in hardware_init() */ +} + +/* Drive the CC line from the TX block */ +static inline void pd_tx_enable(void) +{ + /* Drive TX GND on PA4 */ + STM32_GPIO_BSRR(GPIO_A) = 1 << (4 + 16 /* Reset */); + /* Drive SPI MISO on PA6 by putting it in AF mode */ + STM32_GPIO_MODER(GPIO_A) |= 0x2 << (2*6); +} + +/* Put the TX driver in Hi-Z state */ +static inline void pd_tx_disable(void) +{ + /* Put TX GND (PA4) in Hi-Z state */ + STM32_GPIO_BSRR(GPIO_A) = 1 << 4 /* Set */; + /* Put SPI MISO (PA6) in Hi-Z by putting it in input mode */ + STM32_GPIO_MODER(GPIO_A) &= ~(0x3 << (2*6)); +} + +/* Initialize pins used for TX and put them in Hi-Z */ +static inline void pd_tx_init(void) +{ + /* Already done in hardware_init() */ +} + +/* 3.0A DFP : no-connect voltage is 2.45V */ +#define PD_SRC_VNC (2450 /*mV*/ * 4096 / 3300/* 12-bit ADC with 3.3V range */) + +/* we are a power supply, boot as a power source waiting for a sink */ +#define PD_DEFAULT_STATE PD_STATE_SRC_DISCONNECTED + +/* delay necessary for the voltage transition on the power supply */ +#define PD_POWER_SUPPLY_TRANSITION_DELAY 50000 /* us */ + +#endif /* __USB_PD_CONFIG_H */ diff --git a/board/zinger/usb_pd_policy.c b/board/zinger/usb_pd_policy.c new file mode 100644 index 0000000000..5f314185a3 --- /dev/null +++ b/board/zinger/usb_pd_policy.c @@ -0,0 +1,108 @@ +/* Copyright (c) 2014 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 "board.h" +#include "common.h" +#include "console.h" +#include "debug.h" +#include "hooks.h" +#include "registers.h" +#include "util.h" +#include "usb_pd.h" + +/* ------------------------- Power supply control ------------------------ */ + +/* GPIO level setting helpers through BSRR register */ +#define GPIO_SET(n) (1 << (n)) +#define GPIO_RESET(n) (1 << ((n) + 16)) + +/* Output voltage selection */ +enum volt { + VO_5V = GPIO_RESET(13) | GPIO_RESET(14), + VO_12V = GPIO_SET(13) | GPIO_RESET(14), + VO_13V = GPIO_RESET(13) | GPIO_SET(14), + VO_20V = GPIO_SET(13) | GPIO_SET(14), +}; + +static inline void set_output_voltage(enum volt v) +{ + /* set voltage_select on PA13/PA14 */ + STM32_GPIO_BSRR(GPIO_A) = v; +} + +static inline void output_enable(void) +{ + /* GPF0 (FET driver shutdown) = 0 */ + STM32_GPIO_BSRR(GPIO_F) = GPIO_RESET(0); +} + +static inline void output_disable(void) +{ + /* GPF0 (FET driver shutdown) = 1 */ + STM32_GPIO_BSRR(GPIO_F) = GPIO_SET(0); +} + +/* ----------------------- USB Power delivery policy ---------------------- */ + +/* Power Delivery Objects */ +const uint32_t pd_src_pdo[] = { + PDO_FIXED(5000, 500, PDO_FIXED_EXTERNAL), + PDO_FIXED(5000, 3000, 0), + PDO_FIXED(12000, 3000, 0), + PDO_FIXED(20000, 2000, 0), +}; +const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); + +/* PDO voltages (should match the table above) */ +static enum volt voltages[ARRAY_SIZE(pd_src_pdo)] = { + VO_5V, + VO_5V, + VO_12V, + VO_20V, +}; + +int pd_request_voltage(uint32_t rdo) +{ + int op_ma = rdo & 0x3FF; + int max_ma = (rdo >> 10) & 0x3FF; + int idx = rdo >> 28; + uint32_t pdo; + uint32_t pdo_ma; + + if (!idx || idx > pd_src_pdo_cnt) + return EC_ERROR_INVAL; /* Invalid index */ + + /* check current ... */ + pdo = pd_src_pdo[idx - 1]; + pdo_ma = (pdo & 0x3ff); + if (op_ma > pdo_ma) + return EC_ERROR_INVAL; /* too much op current */ + if (max_ma > pdo_ma) + return EC_ERROR_INVAL; /* too much max current */ + + debug_printf("Switch to %d V %d mA (for %d/%d mA)\n", + ((pdo >> 10) & 0x3ff) * 50, (pdo & 0x3ff) * 10, + ((rdo >> 10) & 0x3ff) * 10, (rdo & 0x3ff) * 10); + + output_disable(); + /* TODO discharge ? */ + set_output_voltage(voltages[idx-1]); + + return EC_SUCCESS; +} + +int pd_set_power_supply_ready(void) +{ + output_enable(); + return EC_SUCCESS; /* we are ready */ +} + +void pd_power_supply_reset(void) +{ + output_disable(); + /* TODO discharge ? */ + set_output_voltage(VO_5V); + /* TODO transition delay */ +} diff --git a/util/flash_ec b/util/flash_ec index 823198d96c..3bfee7c61d 100755 --- a/util/flash_ec +++ b/util/flash_ec @@ -240,7 +240,7 @@ save="$(servo_save)" case "${BOARD}" in big | blaze | discovery | nyan | pit | snow | spring ) flash_stm32 ;; - fruitpie ) flash_stm32 ;; + fruitpie | zinger) flash_stm32 ;; falco | peppy | rambi | samus | squawks ) flash_lm4 ;; link ) flash_link ;; *) die "board ${BOARD} not supported" ;; -- cgit v1.2.1