diff options
Diffstat (limited to 'board/zinger/hardware.c')
-rw-r--r-- | board/zinger/hardware.c | 480 |
1 files changed, 0 insertions, 480 deletions
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); -} |