summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2014-03-27 21:31:59 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-04-12 01:45:51 +0000
commita1e8b316db8b72e0f23c1475a8d4ae715a4ca38d (patch)
tree9e589422b58c77a395551ca9de6757d3336c8066
parent6c6276fd455dced1d4fecb3f2f050b81765c6bf7 (diff)
downloadchrome-ec-a1e8b316db8b72e0f23c1475a8d4ae715a4ca38d.tar.gz
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 <vpalatin@chromium.org> BRANCH=none BUG=none TEST=none Change-Id: Ic2d3616c9fd2bf3ebeccba74a5519697e7c3e899 Reviewed-on: https://chromium-review.googlesource.com/194220 Tested-by: Vincent Palatin <vpalatin@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Commit-Queue: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/zinger/board.c197
-rw-r--r--board/zinger/board.h25
-rw-r--r--board/zinger/build.mk2
-rw-r--r--board/zinger/hardware.c180
-rw-r--r--board/zinger/runtime.c96
-rw-r--r--board/zinger/usb_pd_config.h79
-rw-r--r--board/zinger/usb_pd_policy.c108
-rwxr-xr-xutil/flash_ec2
8 files changed, 502 insertions, 187 deletions
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" ;;