diff options
Diffstat (limited to 'board/zinger')
-rw-r--r-- | board/zinger/board.c | 106 | ||||
-rw-r--r-- | board/zinger/board.h | 131 | ||||
-rw-r--r-- | board/zinger/build.mk | 13 | ||||
-rw-r--r-- | board/zinger/dev_key.pem | 27 | ||||
-rw-r--r-- | board/zinger/ec.irqlist | 14 | ||||
-rw-r--r-- | board/zinger/ec.tasklist | 9 | ||||
-rw-r--r-- | board/zinger/hardware.c | 480 | ||||
-rw-r--r-- | board/zinger/runtime.c | 293 | ||||
-rw-r--r-- | board/zinger/usb_pd_config.h | 109 | ||||
-rw-r--r-- | board/zinger/usb_pd_policy.c | 565 | ||||
-rw-r--r-- | board/zinger/vif_override.xml | 3 |
11 files changed, 0 insertions, 1750 deletions
diff --git a/board/zinger/board.c b/board/zinger/board.c deleted file mode 100644 index b3784fde33..0000000000 --- a/board/zinger/board.c +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright 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 charger configuration */ - -#include "common.h" -#include "cros_version.h" -#include "debug_printf.h" -#include "ec_commands.h" -#include "registers.h" -#include "rsa.h" -#include "rwsig.h" -#include "sha256.h" -#include "system.h" -#include "task.h" -#include "usb_pd.h" -#include "util.h" - -/* Large 768-Byte buffer for RSA computation : could be re-use afterwards... */ -static uint32_t rsa_workbuf[3 * RSANUMWORDS]; - -extern void pd_rx_handler(void); - -/* RW firmware reset vector */ -static uint32_t * const rw_rst = - (uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE+CONFIG_RW_MEM_OFF+4); - -/* External interrupt EXTINT7 for external comparator on PA7 */ -void pd_rx_interrupt(void) -{ - /* trigger reception handling */ - pd_rx_handler(); -} -DECLARE_IRQ(STM32_IRQ_EXTI4_15, pd_rx_interrupt, 1); - -static void jump_to_rw(void) -{ - void (*jump_rw_rst)(void) = (void *)*rw_rst; - - debug_printf("Jump to RW\n"); - /* Disable interrupts */ - asm volatile("cpsid i"); - /* Call RW firmware reset vector */ - jump_rw_rst(); -} - -int is_ro_mode(void) -{ - return (uint32_t)&jump_to_rw < (uint32_t)rw_rst; -} - -static int check_rw_valid(void *rw_hash) -{ - int good; - - /* Check if we have a RW firmware flashed */ - if (*rw_rst == 0xffffffff) - return 0; - - good = rsa_verify((const struct rsa_public_key *)CONFIG_RO_PUBKEY_ADDR, - (const uint8_t *)CONFIG_RW_SIG_ADDR, - rw_hash, rsa_workbuf); - if (!good) { - debug_printf("RSA FAILED\n"); - pd_log_event(PD_EVENT_ACC_RW_FAIL, 0, 0, NULL); - return 0; - } - - return 1; -} - -extern void pd_task(void *u); - -int main(void) -{ - void *rw_hash; - - hardware_init(); - debug_printf("%s started\n", - is_ro_mode() ? "RO" : "RW"); - - /* the RO partition protection is not enabled : do it */ - if (!flash_physical_is_permanently_protected()) - flash_physical_permanent_protect(); - - /* - * calculate the hash of the RW partition - * - * Also pre-cache it so we can answer Discover Identity VDM - * fast enough (in less than 30ms). - */ - rw_hash = flash_hash_rw(); - - /* Verify RW firmware and use it if valid */ - if (is_ro_mode() && check_rw_valid(rw_hash)) - jump_to_rw(); - - /* background loop for PD events */ - pd_task(NULL); - - debug_printf("EXIT!\n"); - /* we should never reach that point */ - system_reset(0); - return 0; -} diff --git a/board/zinger/board.h b/board/zinger/board.h deleted file mode 100644 index 82fb29f29e..0000000000 --- a/board/zinger/board.h +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright 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 charger configuration. This config is used for multiple boards - * including zinger and minimuffin. - */ - -#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) */ -#define CONFIG_UART_CONSOLE 1 - -#ifdef BOARD_ZINGER -#define CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR USB_PD_HW_DEV_ID_ZINGER -#define CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR 1 -#elif defined(BOARD_MINIMUFFIN) -#define CONFIG_USB_PD_HW_DEV_ID_BOARD_MAJOR USB_PD_HW_DEV_ID_MINIMUFFIN -#define CONFIG_USB_PD_HW_DEV_ID_BOARD_MINOR 0 -#else -#error "Board does not have a USB-PD HW Device ID" -#endif - -/* Optional features */ -#undef CONFIG_COMMON_GPIO -#undef CONFIG_COMMON_PANIC_OUTPUT -#undef CONFIG_COMMON_RUNTIME -#undef CONFIG_COMMON_TIMER -#define CONFIG_LOW_POWER_IDLE -#undef CONFIG_CONSOLE_CMDHELP -#undef CONFIG_DEBUG_ASSERT -#undef CONFIG_DEBUG_EXCEPTIONS -#undef CONFIG_DEBUG_STACK_OVERFLOW -#undef CONFIG_FLASH_CROS -#undef CONFIG_FLASH_PHYSICAL -#undef CONFIG_FMAP -/* Not using pstate but keep some space for the public key */ -#undef CONFIG_FW_PSTATE_SIZE -#define CONFIG_FW_PSTATE_SIZE 544 -#define CONFIG_HIBERNATE -#define CONFIG_HIBERNATE_WAKEUP_PINS STM32_PWR_CSR_EWUP1 -#define CONFIG_HW_CRC -#undef CONFIG_LID_SWITCH -#define CONFIG_LTO -#define CONFIG_RSA -#define CONFIG_RWSIG_TYPE_USBPD1 -#define CONFIG_SHA256 -#undef CONFIG_TASK_PROFILING -#define CONFIG_USB_POWER_DELIVERY -#define CONFIG_USB_PD_TCPMV1 -#define CONFIG_USB_PD_ALT_MODE -#define CONFIG_USB_PD_CUSTOM_PDO -#undef CONFIG_USB_PD_DUAL_ROLE -#undef CONFIG_USB_PD_INTERNAL_COMP -#define CONFIG_USB_PD_LOGGING -#undef CONFIG_EVENT_LOG_SIZE -#define CONFIG_EVENT_LOG_SIZE 256 -#define CONFIG_USB_PD_LOW_POWER_IDLE_WHEN_CONNECTED -#define CONFIG_USB_PD_PORT_MAX_COUNT 1 -#define CONFIG_USB_PD_TCPC -#define CONFIG_USB_PD_TCPM_STUB -#undef CONFIG_USB_PD_RX_COMP_IRQ -#define CONFIG_USB_PD_SIMPLE_DFP -#define CONFIG_USB_PD_VBUS_DETECT_GPIO -#define CONFIG_USBC_BACKWARDS_COMPATIBLE_DFP -#undef CONFIG_WATCHDOG_HELP -#undef CONFIG_WATCHDOG_PERIOD_MS -#define CONFIG_WATCHDOG_PERIOD_MS 2300 - -/* debug printf flash footprinf is about 1400 bytes */ -#define CONFIG_DEBUG_PRINTF -#define UARTN CONFIG_UART_CONSOLE -#define UARTN_BASE STM32_USART_BASE(CONFIG_UART_CONSOLE) - -/* USB configuration */ -#if defined(BOARD_ZINGER) -#define CONFIG_USB_PID 0x5012 -#define CONFIG_USB_BCD_DEV 0x0001 /* v 0.01 */ -#elif defined(BOARD_MINIMUFFIN) -#define CONFIG_USB_PID 0x5013 -#define CONFIG_USB_BCD_DEV 0x0001 /* v 0.01 */ -#endif - -#ifndef __ASSEMBLER__ - -#include "common.h" - -/* No GPIO abstraction layer */ - -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 - -/* 3.0A Rp */ -#define PD_SRC_VNC (PD_SRC_3_0_VNC_MV * 4096 / 3300/* 12-bit ADC, 3.3V range */) - -/* delay necessary for the voltage transition on the power supply */ -#define PD_POWER_SUPPLY_TURN_ON_DELAY 50000 /* us */ -#define PD_POWER_SUPPLY_TURN_OFF_DELAY 50000 /* us */ - -/* Initialize all useful registers */ -void hardware_init(void); - -/* last interrupt event */ -extern volatile uint32_t last_event; - -/* RW section flashing */ -int flash_erase_rw(void); -int flash_write_rw(int offset, int size, const char *data); -void flash_physical_permanent_protect(void); -int flash_physical_is_permanently_protected(void); -uint8_t *flash_hash_rw(void); -int is_ro_mode(void); - -void __enter_hibernate(uint32_t seconds, uint32_t microseconds); - -#endif /* !__ASSEMBLER__ */ - -#endif /* __CROS_EC_BOARD_H */ diff --git a/board/zinger/build.mk b/board/zinger/build.mk deleted file mode 100644 index 566cf34ce0..0000000000 --- a/board/zinger/build.mk +++ /dev/null @@ -1,13 +0,0 @@ -# -*- makefile -*- -# Copyright 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. -# -# Board specific files build - -# the IC is STmicro STM32F031F6 -CHIP:=stm32 -CHIP_FAMILY:=stm32f0 -CHIP_VARIANT:=stm32f03x - -board-y=board.o hardware.o runtime.o usb_pd_policy.o diff --git a/board/zinger/dev_key.pem b/board/zinger/dev_key.pem deleted file mode 100644 index 6912b1f44e..0000000000 --- a/board/zinger/dev_key.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpgIBAAKCAQEAvI3KBubudlZyX1oBNzWhQ+bNemHNVC5bO7TjJMTYTIJeKTaW -IyHCFLF9ztpe8tT9Y+ga4VO9PEktP1WJpdU0ecG6VwK3951/cElosfnIPmIY7dVp -PQtGtGS/Zih1nTMRV5hqtGa9SRg0i2kdph+quFXGQoMriTl0StmvNVtD51nRPGwc -ZsG9+P0yfnyo7l3qXtKu5gBx/jDne2kl5/isPHkKfl9le+aNQaNjWeJyB4XDqHXM -AjuW1G7FxoKlU4b363gQbE84Q80X1Qd9iAoRj/HLmDrx9h6FDFs+HbKDfCYtg2fK -upEHr1bFUCxjc6AWuFglSq0yn5kyp1Bh5CD3PQIDAQABAoIBAQCNO2NlEhrx9sSK -mX8pnHkjxECK97D16hcaPN6azvr5K/ldw25n+ERIfb4vb7AJEfKOn+9qce/ftSw4 -MVj+Jxm8TZjGzdmAlq87KzFJhkAwQghMNTszpzuZqZEX8xxN2E+YHilm4UHM+114 -Qw8bPMMCefUcIuY8ThXGbxFm1Oqi4YHHfqE6waRc0XXnLZOYr7NDCmhgyUG1dpAH -kW0EYuJ1UNGaKE4LsWKvi0SYBQ48Mqh1XPkyiL/5I2whewsU2K4KEjynZp0+ULUG -Dxfv3uCywsSsLuNR+EV5tTUp4eY1BLKULJQTMH3hyV1Xf1qEt2YN/3ZHsv7MPQzS -sPIdN+LhAoGBAN6wbcxPnfkJROOVRUzE05IEEBalVULLo1cA1ss/7RjIeUvdRCAa -12OxF4LSNzrSxcPCLsDnYq+j4HoS6KZ31c1TbaKcaUOPfRohrtGBZMxPgDTZgEBa -JlsVtD2vzYvfUIpVQFz6Tnix3F29Gq5RaZdW5/qwOYyx0wtUrPf+pwZ5AoGBANjC -MjgoGtcubR6chDhZcFU4vopdL7IEhMOZ1qxLFTQnINGXXDJpgVvdJRKdDV29DjNZ -zF9wgmoiVm+uM/344bquUV7KHl5bEsZ+4KH6EA4y3IKVgxaxU7dpF6Q6L+rAuYp/ -j0N9XoVnS3aq30HkTkt+jQe0Hl6eEDOJqHEjolXlAoGBAJbMqs3cbIGkQT5May1d -bFhI4Aw10dL1y5qzOsFQfOJ3f4xcPjHve0RLPDye1j/DU6EI8lg3WKDQPMbt3xY7 -uFDe2jNv7+iMVo9Hl/bPxM6GV69ySmNJqQetXu0XC/5YL1Y9/OP5rQIWj7/6uwKo -pvSRKW6dv5sDIINfx/H4RGshAoGBAMIs7Tn7S1gaoev7QEMOdCAT7jUbF3/8pkZn -SLUdqcgHiVHYquIKO7TknbJX+MJReygrOHcC3gFf81imkLLiQqyuPfyRSbUzFtW0 -kVzpG3rsuzdL4pvwjNNQFLqs2YIN1eipLtjBtWwCRcrvdYKcmDrvCj2tcEtIg7D3 -j2qTBni1AoGBAI58xPHxB0cNclhWiFHPNgk98GkwADWxfeTZduoyfpraSrpbseu8 -Cfgq1p5E2nM9jWx4jdKA/fxdD40bneupPi5w5SE2gmwtmQFR3TehI8gxNbEL2Gq6 -6ZkgxnGNxFaE6saHVDHKU8Q2bgzCI8JlOOtSjzKvbr+hsQMYHcEJxom6 ------END RSA PRIVATE KEY----- diff --git a/board/zinger/ec.irqlist b/board/zinger/ec.irqlist deleted file mode 100644 index 690fa950fc..0000000000 --- a/board/zinger/ec.irqlist +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright 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. - */ - -/** - * List of enabled IRQ. To enable an IRQ, use ENABLE_IRQ(irq_num). Any - * IRQ that is not listed here is disabled. - */ - -ENABLE_IRQ(STM32_IRQ_EXTI4_15) -ENABLE_IRQ(STM32_IRQ_ADC_COMP) -ENABLE_IRQ(STM32_IRQ_TIM2) -ENABLE_IRQ(STM32_IRQ_RTC_WAKEUP) diff --git a/board/zinger/ec.tasklist b/board/zinger/ec.tasklist deleted file mode 100644 index 091eb90a22..0000000000 --- a/board/zinger/ec.tasklist +++ /dev/null @@ -1,9 +0,0 @@ -/* Copyright 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. - */ - -/** - * See CONFIG_TASK_LIST in config.h for details. - */ -#define CONFIG_TASK_LIST diff --git a/board/zinger/hardware.c b/board/zinger/hardware.c deleted file mode 100644 index c19e6f0f6b..0000000000 --- a/board/zinger/hardware.c +++ /dev/null @@ -1,480 +0,0 @@ -/* Copyright 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 "common.h" -#include "cpu.h" -#include "registers.h" -#include "task.h" -#include "timer.h" -#include "util.h" -#include "watchdog.h" - -static void system_init(void) -{ - /* Enable access to RCC CSR register and RTC backup registers */ - STM32_PWR_CR |= BIT(8); - - /* switch on LSI */ - STM32_RCC_CSR |= BIT(0); - /* Wait for LSI to be ready */ - while (!(STM32_RCC_CSR & BIT(1))) - ; - /* re-configure RTC if needed */ - if ((STM32_RCC_BDCR & 0x00018300) != 0x00008200) { - /* the RTC settings are bad, we need to reset it */ - STM32_RCC_BDCR |= 0x00010000; - /* Enable RTC and use LSI as clock source */ - STM32_RCC_BDCR = (STM32_RCC_BDCR & ~0x00018300) | 0x00008200; - } -} - -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 - 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 - */ - - /* - * Clear power control/status register to disable wakeup - * pin A0, so that we can change it to an output. - */ - STM32_PWR_CSR = 0; - STM32_PWR_CR |= 0xc; - - 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(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 */ - STM32_GPIO_ODR(GPIO_F) = 0; - STM32_GPIO_MODER(GPIO_F) = OUT(0) | OUT(1); - STM32_GPIO_OTYPER(GPIO_F) = 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) -{ - /* Only do the calibration if the ADC is off */ - if (!(STM32_ADC_CR & 1)) { - /* ADC calibration */ - STM32_ADC_CR = STM32_ADC_CR_ADCAL; /* set ADCAL = 1, ADC off */ - /* wait for the end of calibration */ - while (STM32_ADC_CR & STM32_ADC_CR_ADCAL) - ; - } - /* Single conversion, right aligned, 12-bit */ - STM32_ADC_CFGR1 = BIT(12); /* BIT(15) => AUTOOFF */; - /* clock is ADCCLK (ADEN must be off when writing this reg) */ - STM32_ADC_CFGR2 = 0; - /* Sampling time : 71.5 ADC clock cycles, about 5us */ - STM32_ADC_SMPR = 6; - - /* - * ADC enable (note: takes 4 ADC clocks between end of calibration - * and setting ADEN). - */ - STM32_ADC_CR = STM32_ADC_CR_ADEN; - while (!(STM32_ADC_ISR & STM32_ADC_ISR_ADRDY)) - STM32_ADC_CR = STM32_ADC_CR_ADEN; - /* Disable interrupts */ - STM32_ADC_IER = 0; - /* Analog watchdog IRQ */ - task_enable_irq(STM32_IRQ_ADC_COMP); -} - -static void uart_init(void) -{ - /* set baudrate */ - STM32_USART_BRR(UARTN_BASE) = - DIV_ROUND_NEAREST(CPU_CLOCK, CONFIG_UART_BAUD_RATE); - /* UART enabled, 8 Data bits, oversampling x16, no parity */ - STM32_USART_CR1(UARTN_BASE) = - STM32_USART_CR1_UE | STM32_USART_CR1_TE | STM32_USART_CR1_RE; - /* 1 stop bit, no fancy stuff */ - STM32_USART_CR2(UARTN_BASE) = 0x0000; - /* DMA disabled, special modes disabled, error interrupt disabled */ - STM32_USART_CR3(UARTN_BASE) = 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_TIM_PSC(2) = CPU_CLOCK / 1000000 - 1; - STM32_TIM_EGR(2) = 0x0001; /* Reload the pre-scaler */ - STM32_TIM_CR1(2) = 1; - STM32_TIM32_CNT(2) = 0x00000000; - STM32_TIM_SR(2) = 0; /* Clear pending interrupts */ - STM32_TIM_DIER(2) = 1; /* Overflow interrupt */ - 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"); -} - -extern void runtime_init(void); -void hardware_init(void) -{ - uint32_t raw_cause = STM32_RCC_CSR; - uint32_t pwr_status = STM32_PWR_CSR; - - power_init(); - - /* Clear the hardware reset cause by setting the RMVF bit */ - STM32_RCC_CSR |= BIT(24); - /* Clear SBF in PWR_CSR */ - STM32_PWR_CR |= BIT(3); - - /* - * WORKAROUND: as we cannot de-activate the watchdog during - * long hibernation, we are woken-up once by the watchdog and - * go back to hibernate if we detect that condition, without - * watchdog initialized this time. - * The RTC deadline (if any) is already set. - */ - if ((pwr_status & 0x2) && (raw_cause & 0x60000000)) - __enter_hibernate(0, 0); - - system_init(); - runtime_init(); /* sets clock */ - pins_init(); - uart_init(); - timers_init(); - watchdog_init(); - adc_init(); - irq_init(); -} - -static int watchdog_ain_id, watchdog_ain_high, watchdog_ain_low; - -static int adc_enable_last_watchdog(void) -{ - return adc_enable_watchdog(watchdog_ain_id, watchdog_ain_high, - watchdog_ain_low); -} - -static inline int adc_watchdog_enabled(void) -{ - return STM32_ADC_CFGR1 & BIT(23); -} - -int adc_read_channel(enum adc_channel ch) -{ - int value; - int watchdog_enabled = adc_watchdog_enabled(); - - if (watchdog_enabled) - adc_disable_watchdog(); - - /* Select channel to convert */ - STM32_ADC_CHSELR = 1 << ch; - /* Clear flags */ - STM32_ADC_ISR = 0x8e; - /* Start conversion */ - STM32_ADC_CR |= BIT(2); /* ADSTART */ - /* Wait for end of conversion */ - while (!(STM32_ADC_ISR & BIT(2))) - ; - /* read converted value */ - value = STM32_ADC_DR; - - if (watchdog_enabled) - adc_enable_last_watchdog(); - - return value; -} - -int adc_enable_watchdog(int ch, int high, int low) -{ - /* store last watchdog setup */ - watchdog_ain_id = ch; - watchdog_ain_high = high; - watchdog_ain_low = low; - - /* Set thresholds */ - STM32_ADC_TR = ((high & 0xfff) << 16) | (low & 0xfff); - /* Select channel to convert */ - STM32_ADC_CHSELR = 1 << ch; - /* Clear flags */ - STM32_ADC_ISR = 0x8e; - /* Set Watchdog enable bit on a single channel / continuous mode */ - STM32_ADC_CFGR1 = (ch << 26) | BIT(23) | BIT(22) - | BIT(13) | BIT(12); - /* Enable watchdog interrupt */ - STM32_ADC_IER = BIT(7); - /* Start continuous conversion */ - STM32_ADC_CR |= BIT(2); /* ADSTART */ - - return EC_SUCCESS; -} - -int adc_disable_watchdog(void) -{ - /* Stop on-going conversion */ - STM32_ADC_CR |= BIT(4); /* ADSTP */ - /* Wait for conversion to stop */ - while (STM32_ADC_CR & BIT(4)) - ; - /* CONT=0 -> continuous mode off / Clear Watchdog enable */ - STM32_ADC_CFGR1 = BIT(12); - /* Disable interrupt */ - STM32_ADC_IER = 0; - /* Clear flags */ - STM32_ADC_ISR = 0x8e; - - return EC_SUCCESS; -} - -/* ---- flash handling ---- */ - -/* - * Approximate number of CPU cycles per iteration of the loop when polling - * the flash status - */ -#define CYCLE_PER_FLASH_LOOP 10 - -/* Flash page programming timeout. This is 2x the datasheet max. */ -#define FLASH_TIMEOUT_US 16000 -#define FLASH_TIMEOUT_LOOP \ - (FLASH_TIMEOUT_US * (CPU_CLOCK / SECOND) / CYCLE_PER_FLASH_LOOP) - -/* Flash unlocking keys */ -#define KEY1 0x45670123 -#define KEY2 0xCDEF89AB - -/* Lock bits for FLASH_CR register */ -#define PG BIT(0) -#define PER BIT(1) -#define OPTPG BIT(4) -#define OPTER BIT(5) -#define STRT BIT(6) -#define CR_LOCK BIT(7) -#define OPTWRE BIT(9) - -int crec_flash_physical_write(int offset, int size, const char *data) -{ - uint16_t *address = (uint16_t *)(CONFIG_PROGRAM_MEMORY_BASE + offset); - int res = EC_SUCCESS; - int i; - - if ((uint32_t)address > - CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_SIZE_BYTES) - return EC_ERROR_INVAL; - - /* unlock CR if needed */ - if (STM32_FLASH_CR & CR_LOCK) { - STM32_FLASH_KEYR = KEY1; - STM32_FLASH_KEYR = KEY2; - } - - /* Clear previous error status */ - STM32_FLASH_SR = 0x34; - /* set the ProGram bit */ - STM32_FLASH_CR |= PG; - - for (; size > 0; size -= sizeof(uint16_t)) { - /* wait to be ready */ - for (i = 0; (STM32_FLASH_SR & 1) && (i < FLASH_TIMEOUT_LOOP); - i++) - ; - /* write the half word */ - *address++ = data[0] + (data[1] << 8); - data += 2; - /* Wait for writes to complete */ - for (i = 0; (STM32_FLASH_SR & 1) && (i < FLASH_TIMEOUT_LOOP); - i++) - ; - if (i == FLASH_TIMEOUT_LOOP) { - res = EC_ERROR_TIMEOUT; - goto exit_wr; - } - /* Check for error conditions - erase failed, voltage error, - * protection error */ - if (STM32_FLASH_SR & 0x14) { - res = EC_ERROR_UNKNOWN; - goto exit_wr; - } - } - -exit_wr: - STM32_FLASH_CR &= ~PG; - STM32_FLASH_CR = CR_LOCK; - - return res; -} - -int crec_flash_physical_erase(int offset, int size) -{ - int res = EC_SUCCESS; - - /* unlock CR if needed */ - if (STM32_FLASH_CR & CR_LOCK) { - STM32_FLASH_KEYR = KEY1; - STM32_FLASH_KEYR = KEY2; - } - - /* Clear previous error status */ - STM32_FLASH_SR = 0x34; - /* set PER bit */ - STM32_FLASH_CR |= PER; - - for (; size > 0; size -= CONFIG_FLASH_ERASE_SIZE, - offset += CONFIG_FLASH_ERASE_SIZE) { - int i; - /* select page to erase */ - STM32_FLASH_AR = CONFIG_PROGRAM_MEMORY_BASE + offset; - /* set STRT bit : start erase */ - STM32_FLASH_CR |= STRT; - - - /* Wait for erase to complete */ - for (i = 0; (STM32_FLASH_SR & 1) && (i < FLASH_TIMEOUT_LOOP); - i++) - ; - if (i == FLASH_TIMEOUT_LOOP) { - res = EC_ERROR_TIMEOUT; - goto exit_er; - } - - /* - * Check for error conditions - erase failed, voltage error, - * protection error - */ - if (STM32_FLASH_SR & 0x14) { - res = EC_ERROR_UNKNOWN; - goto exit_er; - } - } - -exit_er: - STM32_FLASH_CR &= ~PER; - STM32_FLASH_CR = CR_LOCK; - - return res; -} - -static void unlock_erase_optb(void) -{ - int i; - - /* Clear previous error status */ - STM32_FLASH_SR = 0x34; - - /* wait to be ready */ - for (i = 0; (STM32_FLASH_SR & 1) && (i < FLASH_TIMEOUT_LOOP); i++) - ; - - /* Unlock the option bytes access */ - if (STM32_FLASH_CR & CR_LOCK) { - STM32_FLASH_KEYR = KEY1; - STM32_FLASH_KEYR = KEY2; - } - if (!(STM32_FLASH_CR & OPTWRE)) { - STM32_FLASH_OPTKEYR = KEY1; - STM32_FLASH_OPTKEYR = KEY2; - } - /* Must be set in 2 separate lines. */ - STM32_FLASH_CR |= OPTER; - STM32_FLASH_CR |= STRT; - - /* wait to be ready */ - for (i = 0; (STM32_FLASH_SR & 1) && (i < FLASH_TIMEOUT_LOOP); i++) - ; - /* reset erasing bits */ - STM32_FLASH_CR = OPTWRE; -} - - -static void write_optb(int byte, uint8_t value) -{ - volatile int16_t *hword = (uint16_t *)(STM32_OPTB_BASE + byte); - int i; - - /* Clear previous error status */ - STM32_FLASH_SR = 0x34; - - /* set OPTPG bit */ - STM32_FLASH_CR |= OPTPG; - - *hword = ((~value) << STM32_OPTB_COMPL_SHIFT) | value; - - /* reset OPTPG bit */ - STM32_FLASH_CR = OPTWRE; - - /* wait to be ready */ - for (i = 0; (STM32_FLASH_SR & 1) && (i < FLASH_TIMEOUT_LOOP); i++) - ; -} - -void flash_physical_permanent_protect(void) -{ - unlock_erase_optb(); - /* protect the 16KB RO partition against write/erase in WRP0 */ - write_optb(8, 0xF0); - /* Set RDP to level 1 to prevent disabling the protection */ - write_optb(0, 0x11); - /* Reset by using OBL_LAUNCH to take changes into account */ - asm volatile("cpsid i"); - STM32_FLASH_CR |= FLASH_CR_OBL_LAUNCH; - /* Spin and wait for reboot; should never return */ - while (1) - ; -} - -int flash_physical_is_permanently_protected(void) -{ - /* if RDP is still at level 0, the flash protection is not in place */ - return (STM32_FLASH_OBR & STM32_FLASH_OBR_RDP_MASK) && - /* the low 16KB (RO partition) are write-protected */ - !(STM32_FLASH_WRPR & 0xF); -} diff --git a/board/zinger/runtime.c b/board/zinger/runtime.c deleted file mode 100644 index 5d17bfda04..0000000000 --- a/board/zinger/runtime.c +++ /dev/null @@ -1,293 +0,0 @@ -/* Copyright 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 "chip/stm32/clock-f.h" -#include "clock.h" -#include "common.h" -#include "cpu.h" -#include "debug_printf.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -volatile uint32_t last_event; -uint32_t sleep_mask; - -/* High word of the 64-bit timestamp counter */ -static volatile uint32_t clksrc_high; - -timestamp_t get_time(void) -{ - timestamp_t t; - - t.le.lo = STM32_TIM32_CNT(2); - t.le.hi = clksrc_high; - return t; -} - -void force_time(timestamp_t ts) -{ - STM32_TIM32_CNT(2) = ts.le.lo; -} - -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; -} - -void interrupt_disable(void) -{ - asm("cpsid i"); -} - -void interrupt_enable(void) -{ - asm("cpsie i"); -} - -uint32_t task_set_event(task_id_t tskid, uint32_t event) -{ - last_event = event; - - return 0; -} - -void tim2_interrupt(void) -{ - uint32_t stat = STM32_TIM_SR(2); - - if (stat & 2) { /* Event match */ - /* disable match interrupt but keep update interrupt */ - STM32_TIM_DIER(2) = 1; - last_event = TASK_EVENT_TIMER; - } - if (stat & 1) /* Counter overflow */ - clksrc_high++; - - STM32_TIM_SR(2) = ~stat & 3; /* clear interrupt flags */ - task_clear_pending_irq(STM32_IRQ_TIM2); -} -DECLARE_IRQ(STM32_IRQ_TIM2, tim2_interrupt, 1); - -static void zinger_config_hispeed_clock(void) -{ - /* Ensure that HSI8 is ON */ - if (!(STM32_RCC_CR & BIT(1))) { - /* Enable HSI */ - STM32_RCC_CR |= BIT(0); - /* Wait for HSI to be ready */ - while (!(STM32_RCC_CR & BIT(1))) - ; - } - /* PLLSRC = HSI, PLLMUL = x12 (x HSI/2) = 48Mhz */ - STM32_RCC_CFGR = 0x00288000; - /* Enable PLL */ - STM32_RCC_CR |= BIT(24); - /* Wait for PLL to be ready */ - while (!(STM32_RCC_CR & BIT(25))) - ; - - /* switch SYSCLK to PLL */ - STM32_RCC_CFGR = 0x00288002; - /* wait until the PLL is the clock source */ - while ((STM32_RCC_CFGR & 0xc) != 0x8) - ; -} - -void runtime_init(void) -{ - /* - * put 1 Wait-State for flash access to ensure proper reads at 48Mhz - * and enable prefetch buffer. - */ - STM32_FLASH_ACR = STM32_FLASH_ACR_LATENCY | STM32_FLASH_ACR_PRFTEN; - - config_hispeed_clock(); - - rtc_init(); -} - -/* - * minimum delay to enter stop mode - * STOP_MODE_LATENCY: max time to wake up from STOP mode with regulator in low - * power mode is 5 us + PLL locking time is 200us. - * SET_RTC_MATCH_DELAY: max time to set RTC match alarm. if we set the alarm - * in the past, it will never wake up and cause a watchdog. - */ -#define STOP_MODE_LATENCY 300 /* us */ -#define SET_RTC_MATCH_DELAY 200 /* us */ -#define MAX_LATENCY (STOP_MODE_LATENCY + SET_RTC_MATCH_DELAY) - -uint32_t task_wait_event(int timeout_us) -{ - uint32_t evt; - timestamp_t t0, t1; - struct rtc_time_reg rtc0, rtc1; - - t1.val = get_time().val + timeout_us; - - asm volatile("cpsid i"); - /* the event already happened */ - if (last_event || !timeout_us) { - evt = last_event; - last_event = 0; - - asm volatile("cpsie i ; isb"); - return evt; - } - - /* loop until an event is triggered */ - while (1) { - /* set timeout on timer */ - if (timeout_us < 0) { - asm volatile ("wfi"); - } else if (timeout_us <= MAX_LATENCY || - t1.le.lo - timeout_us > t1.le.lo + MAX_LATENCY || - !DEEP_SLEEP_ALLOWED) { - STM32_TIM32_CCR1(2) = STM32_TIM32_CNT(2) + timeout_us; - STM32_TIM_DIER(2) = 3; /* match interrupt and UIE */ - - asm volatile("wfi"); - - STM32_TIM_DIER(2) = 1; /* disable match, keep UIE */ - } else { - t0 = get_time(); - - /* set deep sleep bit */ - CPU_SCB_SYSCTRL |= 0x4; - - set_rtc_alarm(0, timeout_us - STOP_MODE_LATENCY, - &rtc0, 0); - - asm volatile("wfi"); - - CPU_SCB_SYSCTRL &= ~0x4; - - zinger_config_hispeed_clock(); - - /* fast forward timer according to RTC counter */ - reset_rtc_alarm(&rtc1); - t0.val += get_rtc_diff(&rtc0, &rtc1); - force_time(t0); - } - - asm volatile("cpsie i ; isb"); - /* note: interrupt that woke us up will run here */ - asm volatile("cpsid i"); - - t0 = get_time(); - /* check for timeout if timeout was set */ - if (timeout_us >= 0 && t0.val >= t1.val) - last_event = TASK_EVENT_TIMER; - /* break from loop when event has triggered */ - if (last_event) - break; - /* recalculate timeout if timeout was set */ - if (timeout_us >= 0) - timeout_us = t1.val - t0.val; - } - - evt = last_event; - last_event = 0; - asm volatile("cpsie i ; isb"); - return evt; -} - -uint32_t task_wait_event_mask(uint32_t event_mask, int timeout_us) -{ - uint32_t evt = 0; - - /* Add the timer event to the mask so we can indicate a timeout */ - event_mask |= TASK_EVENT_TIMER; - - /* Wait until an event matching event_mask */ - do { - evt |= task_wait_event(timeout_us); - } while (!(evt & event_mask)); - - /* Restore any pending events not in the event_mask */ - if (evt & ~event_mask) - task_set_event(0, evt & ~event_mask); - - return evt & event_mask; -} - -noreturn -void __keep cpu_reset(void) -{ - /* Disable interrupts */ - asm volatile("cpsid i"); - /* reboot the CPU */ - CPU_NVIC_APINT = 0x05fa0004; - /* Spin and wait for reboot; should never return */ - while (1) - ; -} - -void system_reset(int flags) -{ - cpu_reset(); -} -/** - * Default exception handler, which reports a panic. - * - * Declare this as a naked call so we can extract the real LR and SP. - */ -void exception_panic(void) __attribute__((naked)); -void exception_panic(void) -{ -#ifdef CONFIG_DEBUG_PRINTF - asm volatile( - "mov r0, %0\n" - /* TODO: Should this be SP_process instead of SP_main? */ - "mov r3, sp\n" - "ldr r1, [r3, #6*4]\n" /* retrieve exception PC */ - "ldr r2, [r3, #5*4]\n" /* retrieve exception LR */ - "bl debug_printf\n" - : : "r"("PANIC PC=%08x LR=%08x\n\n")); -#endif - cpu_reset(); -} - -void panic_reboot(void) -{ /* for div / 0 */ - debug_printf("DIV0 PANIC\n\n"); - cpu_reset(); -} - -enum ec_image system_get_image_copy(void) -{ - if (is_ro_mode()) - return EC_IMAGE_RO; - else - return EC_IMAGE_RW; -} - -/* --- 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 deleted file mode 100644 index d0797b3d80..0000000000 --- a/board/zinger/usb_pd_config.h +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright 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 __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 14 -#define TIM_CLOCK_PD_RX_C0 3 - -#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 1 - -/* 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 is using SPI1 on PA4-6 */ -#define SPI_REGS(p) STM32_SPI1_REGS - -static inline void spi_enable_clock(int port) -{ - /* Already done in hardware_init() */ -} - -#define DMAC_SPI_TX(p) STM32_DMAC_CH3 - -/* RX is on TIM3 CH1 connected to TIM3 CH2 pin (PA7, not internal COMP) */ -#define TIM_TX_CCR_IDX(p) TIM_TX_CCR_C0 -#define TIM_RX_CCR_IDX(p) TIM_RX_CCR_C0 -/* connect TIM3 CH1 to TIM3_CH2 input */ -#define TIM_CCR_CS 2 -#define EXTI_COMP_MASK(p) BIT(7) -#define IRQ_COMP STM32_IRQ_EXTI4_15 -/* the RX is inverted, triggers on rising edge */ -#define EXTI_XTSR STM32_EXTI_RTSR - -#define DMAC_TIM_RX(p) STM32_DMAC_CH4 - -/* the pins used for communication need to be hi-speed */ -static inline void pd_set_pins_speed(int port) -{ - /* Already done in hardware_init() */ -} - -/* Reset SPI peripheral used for TX */ -static inline void pd_tx_spi_reset(int port) -{ - /* Reset SPI1 */ - STM32_RCC_APB2RSTR |= BIT(12); - STM32_RCC_APB2RSTR &= ~BIT(12); -} - -/* Drive the CC line from the TX block */ -static inline void pd_tx_enable(int port, int polarity) -{ - /* Drive SPI MISO on PA6 by putting it in AF mode */ - STM32_GPIO_MODER(GPIO_A) |= 0x2 << (2*6); - /* Drive TX GND on PA4 */ - STM32_GPIO_BSRR(GPIO_A) = 1 << (4 + 16 /* Reset */); -} - -/* Put the TX driver in Hi-Z state */ -static inline void pd_tx_disable(int port, int polarity) -{ - /* Put TX GND (PA4) in Hi-Z state */ - STM32_GPIO_BSRR(GPIO_A) = BIT(4) /* Set */; - /* Put SPI MISO (PA6) in Hi-Z by putting it in input mode */ - STM32_GPIO_MODER(GPIO_A) &= ~(0x3 << (2*6)); -} - -/* we know the plug polarity, do the right configuration */ -static inline void pd_select_polarity(int port, int polarity) -{ - /* captive cable : no polarity */ -} - -/* Initialize pins used for TX and put them in Hi-Z */ -static inline void pd_tx_init(void) -{ - /* Already done in hardware_init() */ -} - -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 high */ - return (cc == 0) ? adc_read_channel(ADC_CH_CC1_PD) : 4096; -} - -#endif /* __CROS_EC_USB_PD_CONFIG_H */ diff --git a/board/zinger/usb_pd_policy.c b/board/zinger/usb_pd_policy.c deleted file mode 100644 index f47789e063..0000000000 --- a/board/zinger/usb_pd_policy.c +++ /dev/null @@ -1,565 +0,0 @@ -/* Copyright 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 "adc.h" -#include "common.h" -#include "console.h" -#include "debug_printf.h" -#include "ec_commands.h" -#include "hooks.h" -#include "registers.h" -#include "system.h" -#include "task.h" -#include "timer.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 (enable OR'ing FETs) = 1 */ - STM32_GPIO_BSRR(GPIO_F) = GPIO_SET(0); -} - -static inline void output_disable(void) -{ - /* GPF0 (disable OR'ing FETs) = 0 */ - STM32_GPIO_BSRR(GPIO_F) = GPIO_RESET(0); -} - -static inline int output_is_enabled(void) -{ - /* GPF0 = enable output FET */ - return STM32_GPIO_ODR(GPIO_F) & 1; -} - -/* ----- fault conditions ----- */ - -enum faults { - FAULT_OK = 0, - FAULT_OCP, /* Over-Current Protection */ - FAULT_FAST_OCP, /* Over-Current Protection for interrupt context */ - FAULT_OVP, /* Under or Over-Voltage Protection */ - FAULT_DISCHARGE, /* Discharge was ineffective */ -}; - -/* current fault condition */ -static enum faults fault; -/* expiration date of the last fault condition */ -static timestamp_t fault_deadline; - -/* ADC in 12-bit mode */ -#define ADC_SCALE BIT(12) -/* ADC power supply : VDDA = 3.3V */ -#define VDDA_MV 3300 -/* Current sense resistor : 5 milliOhm */ -#define R_SENSE 5 -/* VBUS voltage is measured through 10k / 100k voltage divider = /11 */ -#define VOLT_DIV ((10+100)/10) -/* The current sensing op-amp has a x100 gain */ -#define CURR_GAIN 100 -/* convert VBUS voltage in raw ADC value */ -#define VBUS_MV(mv) ((mv)*ADC_SCALE/VOLT_DIV/VDDA_MV) -/* convert VBUS current in raw ADC value */ -#define VBUS_MA(ma) ((ma)*ADC_SCALE*R_SENSE/1000*CURR_GAIN/VDDA_MV) -/* convert raw ADC value to mA */ -#define ADC_TO_CURR_MA(vbus) ((vbus)*1000/(ADC_SCALE*R_SENSE)*VDDA_MV/CURR_GAIN) -/* convert raw ADC value to mV */ -#define ADC_TO_VOLT_MV(vbus) ((vbus)*VOLT_DIV*VDDA_MV/ADC_SCALE) - -/* Max current */ -#if defined(BOARD_ZINGER) -#define RATED_CURRENT 3000 -#elif defined(BOARD_MINIMUFFIN) -#define RATED_CURRENT 2250 -#endif - -/* Max current : 20% over rated current */ -#define MAX_CURRENT VBUS_MA(RATED_CURRENT * 6/5) -/* Fast short circuit protection : 50% over rated current */ -#define MAX_CURRENT_FAST VBUS_MA(RATED_CURRENT * 3/2) -/* reset over-current after 1 second */ -#define OCP_TIMEOUT SECOND - -/* Threshold below which we stop fast OCP to save power */ -#define SINK_IDLE_CURRENT VBUS_MA(500 /* mA */) - -/* Under-voltage limit is 0.8x Vnom */ -#define UVP_MV(mv) VBUS_MV((mv) * 8 / 10) -/* Over-voltage limit is 1.2x Vnom */ -#define OVP_MV(mv) VBUS_MV((mv) * 12 / 10) -/* Over-voltage recovery threshold is 1.1x Vnom */ -#define OVP_REC_MV(mv) VBUS_MV((mv) * 11 / 10) - -/* Maximum discharging delay */ -#define DISCHARGE_TIMEOUT (275*MSEC) -/* Voltage overshoot below the OVP threshold for discharging to avoid OVP */ -#define DISCHARGE_OVERSHOOT_MV VBUS_MV(200) - -/* Time to wait after last RX edge interrupt before allowing deep sleep */ -#define PD_RX_SLEEP_TIMEOUT (100*MSEC) - -/* ----- output voltage discharging ----- */ - -/* expiration date of the discharge */ -static timestamp_t discharge_deadline; - -static inline void discharge_enable(void) -{ - STM32_GPIO_BSRR(GPIO_F) = GPIO_SET(1); -} - -static inline void discharge_disable(void) -{ - STM32_GPIO_BSRR(GPIO_F) = GPIO_RESET(1); - adc_disable_watchdog(); -} - -static inline int discharge_is_enabled(void) -{ - /* GPF1 = enable discharge FET */ - return STM32_GPIO_ODR(GPIO_F) & 2; -} - -static void discharge_voltage(int target_volt) -{ - discharge_enable(); - discharge_deadline.val = get_time().val + DISCHARGE_TIMEOUT; - /* Monitor VBUS voltage */ - target_volt -= DISCHARGE_OVERSHOOT_MV; - disable_sleep(SLEEP_MASK_USB_PWR); - adc_enable_watchdog(ADC_CH_V_SENSE, 0xFFF, target_volt); -} - -/* ----------------------- USB Power delivery policy ---------------------- */ - -#define PDO_FIXED_FLAGS (PDO_FIXED_UNCONSTRAINED | PDO_FIXED_DATA_SWAP) - -/* Voltage indexes for the PDOs */ -enum volt_idx { - PDO_IDX_5V = 0, - PDO_IDX_12V = 1, - PDO_IDX_20V = 2, - - PDO_IDX_COUNT -}; - -/* Power Delivery Objects */ -const uint32_t pd_src_pdo[] = { - [PDO_IDX_5V] = PDO_FIXED(5000, RATED_CURRENT, PDO_FIXED_FLAGS), - [PDO_IDX_12V] = PDO_FIXED(12000, RATED_CURRENT, PDO_FIXED_FLAGS), - [PDO_IDX_20V] = PDO_FIXED(20000, RATED_CURRENT, PDO_FIXED_FLAGS), -}; -const int pd_src_pdo_cnt = ARRAY_SIZE(pd_src_pdo); -BUILD_ASSERT(ARRAY_SIZE(pd_src_pdo) == PDO_IDX_COUNT); - -/* PDO voltages (should match the table above) */ -static const struct { - enum volt select; /* GPIO configuration to select the voltage */ - int uvp; /* under-voltage limit in mV */ - int ovp; /* over-voltage limit in mV */ - int ovp_rec;/* over-voltage recovery threshold in mV */ -} voltages[ARRAY_SIZE(pd_src_pdo)] = { - [PDO_IDX_5V] = {VO_5V, UVP_MV(5000), OVP_MV(5000), - OVP_REC_MV(5000)}, - [PDO_IDX_12V] = {VO_12V, UVP_MV(12000), OVP_MV(12000), - OVP_REC_MV(12000)}, - [PDO_IDX_20V] = {VO_20V, UVP_MV(20000), OVP_MV(20000), - OVP_REC_MV(20000)}, -}; - -/* current and previous selected PDO entry */ -static int volt_idx; -static int last_volt_idx; -/* target voltage at the end of discharge */ -static int discharge_volt_idx; - -/* output current measurement */ -int vbus_amp; - -__override int pd_board_check_request(uint32_t rdo, int pdo_cnt) -{ - /* fault condition or output disabled: reject transitions */ - if (fault != FAULT_OK || !output_is_enabled()) - return EC_ERROR_INVAL; - - return EC_SUCCESS; -} - -void pd_transition_voltage(int idx) -{ - last_volt_idx = volt_idx; - volt_idx = idx - 1; - if (volt_idx < last_volt_idx) { /* down voltage transition */ - /* Stop OCP monitoring */ - adc_disable_watchdog(); - - discharge_volt_idx = volt_idx; - /* from 20V : do an intermediate step at 12V */ - if (volt_idx == PDO_IDX_5V && last_volt_idx == PDO_IDX_20V) - volt_idx = PDO_IDX_12V; - discharge_voltage(voltages[volt_idx].ovp); - } else if (volt_idx > last_volt_idx) { /* up voltage transition */ - if (discharge_is_enabled()) { - /* Make sure discharging is disabled */ - discharge_disable(); - /* Enable over-current monitoring */ - adc_enable_watchdog(ADC_CH_A_SENSE, - MAX_CURRENT_FAST, 0); - } - } - set_output_voltage(voltages[volt_idx].select); -} - -int pd_set_power_supply_ready(int port) -{ - /* fault condition not cleared : do not turn on power */ - if ((fault != FAULT_OK) || discharge_is_enabled()) - return EC_ERROR_INVAL; - - output_enable(); - /* Over-current monitoring */ - adc_enable_watchdog(ADC_CH_A_SENSE, MAX_CURRENT_FAST, 0); - - return EC_SUCCESS; /* we are ready */ -} - -void pd_power_supply_reset(int port) -{ - int need_discharge = (volt_idx > 0) || discharge_is_enabled(); - - output_disable(); - last_volt_idx = volt_idx; - /* from 20V : do an intermediate step at 12V */ - volt_idx = volt_idx == PDO_IDX_20V ? PDO_IDX_12V : PDO_IDX_5V; - set_output_voltage(voltages[volt_idx].select); - /* TODO transition delay */ - - /* Stop OCP monitoring to save power */ - adc_disable_watchdog(); - - /* discharge voltage to 5V ? */ - if (need_discharge) { - /* final target : 5V */ - discharge_volt_idx = PDO_IDX_5V; - discharge_voltage(voltages[volt_idx].ovp); - } -} - -int pd_check_data_swap(int port, - enum pd_data_role data_role) -{ - /* Allow data swap if we are a DFP, otherwise don't allow */ - return (data_role == PD_ROLE_DFP) ? 1 : 0; -} - -void pd_execute_data_swap(int port, - enum pd_data_role data_role) -{ - /* Do nothing */ -} - -void pd_check_pr_role(int port, - enum pd_power_role pr_role, - int flags) -{ -} - -void pd_check_dr_role(int port, - enum pd_data_role dr_role, - int flags) -{ - /* If DFP, try to switch to UFP */ - if ((flags & PD_FLAGS_PARTNER_DR_DATA) && dr_role == PD_ROLE_DFP) - pd_request_data_swap(port); -} - -int pd_board_checks(void) -{ -#ifdef CONFIG_HIBERNATE - static timestamp_t hib_to; - static int hib_to_ready; -#endif - int vbus_volt; - int ovp_idx; - - /* Reload the watchdog */ - STM32_IWDG_KR = STM32_IWDG_KR_RELOAD; - -#ifdef CONFIG_HIBERNATE - /* If output is disabled for long enough, then hibernate */ - if (!pd_is_connected(0) && hib_to_ready) { - if (get_time().val >= hib_to.val) { - debug_printf("hib\n"); - __enter_hibernate(0, 0); - } - } else { - hib_to.val = get_time().val + 60*SECOND; - hib_to_ready = 1; - } -#endif - - /* if it's been a while since last RX edge, then allow deep sleep */ - if (get_time_since_last_edge(0) > PD_RX_SLEEP_TIMEOUT) - enable_sleep(SLEEP_MASK_USB_PD); - - vbus_volt = adc_read_channel(ADC_CH_V_SENSE); - vbus_amp = adc_read_channel(ADC_CH_A_SENSE); - - if (fault == FAULT_FAST_OCP) { - debug_printf("Fast OCP\n"); - pd_log_event(PD_EVENT_PS_FAULT, 0, PS_FAULT_FAST_OCP, NULL); - fault = FAULT_OCP; - /* reset over-current after 1 second */ - fault_deadline.val = get_time().val + OCP_TIMEOUT; - return EC_ERROR_INVAL; - } - - if (vbus_amp > MAX_CURRENT) { - /* 3 more samples to check whether this is just a transient */ - int count; - for (count = 0; count < 3; count++) - if (adc_read_channel(ADC_CH_A_SENSE) < MAX_CURRENT) - break; - /* trigger the slow OCP iff all 4 samples are above the max */ - if (count == 3) { - debug_printf("OCP %d mA\n", - vbus_amp * VDDA_MV / CURR_GAIN * 1000 - / R_SENSE / ADC_SCALE); - pd_log_event(PD_EVENT_PS_FAULT, 0, PS_FAULT_OCP, NULL); - fault = FAULT_OCP; - /* reset over-current after 1 second */ - fault_deadline.val = get_time().val + OCP_TIMEOUT; - return EC_ERROR_INVAL; - } - } - /* - * Optimize power consumption when the sink is idle : - * Enable STOP mode while we are connected, - * this kills fast OCP as the actual ADC conversion for the analog - * watchdog will happen on the next wake-up (x0 ms latency). - */ - if (vbus_amp < SINK_IDLE_CURRENT && !discharge_is_enabled()) - /* override the PD state machine sleep mask */ - enable_sleep(SLEEP_MASK_USB_PWR); - else if (vbus_amp > SINK_IDLE_CURRENT) - disable_sleep(SLEEP_MASK_USB_PWR); - - /* - * Set the voltage index to use for checking OVP. During a down step - * transition, use the previous voltage index to check for OVP. - */ - ovp_idx = discharge_is_enabled() ? last_volt_idx : volt_idx; - - if ((output_is_enabled() && (vbus_volt > voltages[ovp_idx].ovp)) || - (fault && (vbus_volt > voltages[ovp_idx].ovp_rec))) { - if (!fault) { - debug_printf("OVP %d mV\n", - ADC_TO_VOLT_MV(vbus_volt)); - pd_log_event(PD_EVENT_PS_FAULT, 0, PS_FAULT_OVP, NULL); - } - fault = FAULT_OVP; - /* no timeout */ - fault_deadline.val = get_time().val; - return EC_ERROR_INVAL; - } - - /* the discharge did not work properly */ - if (discharge_is_enabled() && - (get_time().val > discharge_deadline.val)) { - /* ensure we always finish a 2-step discharge */ - volt_idx = discharge_volt_idx; - set_output_voltage(voltages[volt_idx].select); - /* stop it */ - discharge_disable(); - /* enable over-current monitoring */ - adc_enable_watchdog(ADC_CH_A_SENSE, MAX_CURRENT_FAST, 0); - debug_printf("Disch FAIL %d mV\n", - ADC_TO_VOLT_MV(vbus_volt)); - pd_log_event(PD_EVENT_PS_FAULT, 0, PS_FAULT_DISCH, NULL); - fault = FAULT_DISCHARGE; - /* reset it after 1 second */ - fault_deadline.val = get_time().val + OCP_TIMEOUT; - return EC_ERROR_INVAL; - } - - /* everything is good *and* the error condition has expired */ - if ((fault != FAULT_OK) && (get_time().val > fault_deadline.val)) { - fault = FAULT_OK; - debug_printf("Reset fault\n"); - /* - * Reset the PD state and communication on both side, - * so we can now re-negociate a voltage. - */ - return EC_ERROR_INVAL; - } - - return EC_SUCCESS; - -} - -void pd_adc_interrupt(void) -{ - /* Clear flags */ - STM32_ADC_ISR = 0x8e; - - if (discharge_is_enabled()) { - if (discharge_volt_idx != volt_idx) { - /* first step of the discharge completed: now 12V->5V */ - volt_idx = PDO_IDX_5V; - set_output_voltage(VO_5V); - discharge_voltage(voltages[PDO_IDX_5V].ovp); - } else { /* discharge complete */ - discharge_disable(); - /* enable over-current monitoring */ - adc_enable_watchdog(ADC_CH_A_SENSE, - MAX_CURRENT_FAST, 0); - } - } else {/* Over-current detection */ - /* cut the power output */ - pd_power_supply_reset(0); - /* record a special fault */ - fault = FAULT_FAST_OCP; - /* pd_board_checks() will record the timeout later */ - } - - /* clear ADC irq so we don't get a second interrupt */ - task_clear_pending_irq(STM32_IRQ_ADC_COMP); -} -DECLARE_IRQ(STM32_IRQ_ADC_COMP, pd_adc_interrupt, 1); - -/* ----------------- Vendor Defined Messages ------------------ */ -const uint32_t vdo_idh = VDO_IDH(0, /* data caps as USB host */ - 0, /* data caps as USB device */ - IDH_PTYPE_UNDEF, /* Undefined */ - 1, /* supports alt modes */ - USB_VID_GOOGLE); - -const uint32_t vdo_product = VDO_PRODUCT(CONFIG_USB_PID, CONFIG_USB_BCD_DEV); - -/* When set true, we are in GFU mode */ -static int gfu_mode; - -static int svdm_response_identity(int port, uint32_t *payload) -{ - payload[VDO_I(IDH)] = vdo_idh; - payload[VDO_I(CSTAT)] = VDO_CSTAT(0); - payload[VDO_I(PRODUCT)] = vdo_product; - return VDO_I(PRODUCT) + 1; -} - -static int svdm_response_svids(int port, uint32_t *payload) -{ - payload[1] = VDO_SVID(USB_VID_GOOGLE, 0); - return 2; -} - -/* Will only ever be a single mode for this device */ -#define MODE_CNT 1 -#define OPOS 1 - -const uint32_t vdo_dp_mode[MODE_CNT] = { - VDO_MODE_GOOGLE(MODE_GOOGLE_FU) -}; - -static int svdm_response_modes(int port, uint32_t *payload) -{ - if (PD_VDO_VID(payload[0]) != USB_VID_GOOGLE) - return 0; /* nak */ - - memcpy(payload + 1, vdo_dp_mode, sizeof(vdo_dp_mode)); - return MODE_CNT + 1; -} - -static int svdm_enter_mode(int port, uint32_t *payload) -{ - /* SID & mode request is valid */ - if ((PD_VDO_VID(payload[0]) != USB_VID_GOOGLE) || - (PD_VDO_OPOS(payload[0]) != OPOS)) - return 0; /* will generate NAK */ - - gfu_mode = 1; - debug_printf("GFU\n"); - return 1; -} - -static int svdm_exit_mode(int port, uint32_t *payload) -{ - gfu_mode = 0; - return 1; /* Must return ACK */ -} - -static struct amode_fx dp_fx = { - .status = NULL, - .config = NULL, -}; - -const struct svdm_response svdm_rsp = { - .identity = &svdm_response_identity, - .svids = &svdm_response_svids, - .modes = &svdm_response_modes, - .enter_mode = &svdm_enter_mode, - .amode = &dp_fx, - .exit_mode = &svdm_exit_mode, -}; - -__override int pd_custom_vdm(int port, int cnt, uint32_t *payload, - uint32_t **rpayload) -{ - int cmd = PD_VDO_CMD(payload[0]); - int rsize; - - if (PD_VDO_VID(payload[0]) != USB_VID_GOOGLE || !gfu_mode) - return 0; - - debug_printf("%pT] VDM/%d [%d] %08x\n", - PRINTF_TIMESTAMP_NOW, cnt, cmd, payload[0]); - *rpayload = payload; - - rsize = pd_custom_flash_vdm(port, cnt, payload); - if (!rsize) { - switch (cmd) { - case VDO_CMD_PING_ENABLE: - pd_ping_enable(0, payload[1]); - rsize = 1; - break; - case VDO_CMD_CURRENT: - /* return last measured current */ - payload[1] = ADC_TO_CURR_MA(vbus_amp); - rsize = 2; - break; - case VDO_CMD_GET_LOG: - rsize = pd_vdm_get_log_entry(payload); - break; - default: - /* Unknown : do not answer */ - return 0; - } - } - - /* respond (positively) to the request */ - payload[0] |= VDO_SRC_RESPONDER; - - return rsize; -} diff --git a/board/zinger/vif_override.xml b/board/zinger/vif_override.xml deleted file mode 100644 index 32736caf64..0000000000 --- a/board/zinger/vif_override.xml +++ /dev/null @@ -1,3 +0,0 @@ -<!-- Add VIF field overrides here. See genvif.c and the Vendor Info File - Definition from the USB-IF. ---> |