/* This file is part of MutekH. MutekH is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; version 2.1 of the License. MutekH is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . Copyright Julien Peeters (c) 2016 */ #include #include #include #include #include #include #include #include #include #include #include /* CPU */ DEV_DECLARE_STATIC(cpu_dev, "cpu", DEVICE_FLAG_CPU, arm32m_drv, DEV_STATIC_RES_ID(0, 0), DEV_STATIC_RES_FREQ(72000000, 1) ); /* GPIO A..E. */ DEV_DECLARE_STATIC(gpio_dev, "gpio", 0, stm32_gpio_drv, DEV_STATIC_RES_DEV_ICU("/cpu"), DEV_STATIC_RES_IRQ(0, STM32_IRQ_EXTI0, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), DEV_STATIC_RES_IRQ(1, STM32_IRQ_EXTI1, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), DEV_STATIC_RES_IRQ(2, STM32_IRQ_EXTI2, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), DEV_STATIC_RES_IRQ(3, STM32_IRQ_EXTI3, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), DEV_STATIC_RES_IRQ(4, STM32_IRQ_EXTI4, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), DEV_STATIC_RES_IRQ(5, STM32_IRQ_EXTI9_5, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), DEV_STATIC_RES_IRQ(6, STM32_IRQ_EXTI15_10, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1) ); /* UART 4 */ DEV_DECLARE_STATIC(uart2_dev, "uart4", 0, stm32_usart_drv, DEV_STATIC_RES_MEM(STM32_UART4_ADDR, STM32_UART4_ADDR + STM32_UART4_SIZE), DEV_STATIC_RES_FREQ(72000000, 1), DEV_STATIC_RES_DEV_ICU("/cpu"), DEV_STATIC_RES_IRQ(0, STM32_IRQ_UART4, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), DEV_STATIC_RES_DEV_PARAM("iomux", "/gpio"), DEV_STATIC_RES_IOMUX("tx", 0, STM32_PC10, 0, 0), DEV_STATIC_RES_IOMUX("rx", 0, STM32_PC11, 0, 0), DEV_STATIC_RES_UART(19200, 8, DEV_UART_PARITY_NONE, 1, 0, 0) ); /* Timer 4 */ DEV_DECLARE_STATIC(timer4_dev, "timer4", 0, stm32_timer_drv, DEV_STATIC_RES_MEM(STM32_TIM4_ADDR, STM32_TIM4_ADDR + STM32_TIM4_SIZE), DEV_STATIC_RES_FREQ(72000000, 1), DEV_STATIC_RES_DEV_ICU("/cpu"), DEV_STATIC_RES_IRQ(0, STM32_IRQ_TIM4, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), ); #if defined(CONFIG_DRIVER_NET_DWC10100) /* UART 4 */ DEV_DECLARE_STATIC(dwc10100_dev, "eth0", 0, dwc10100_drv, DEV_STATIC_RES_MEM(STM32_ETHERNET_MAC_ADDR, STM32_ETHERNET_MAC_ADDR + STM32_ETHERNET_MAC_SIZE), DEV_STATIC_RES_MEM(STM32_ETHERNET_MMC_ADDR, STM32_ETHERNET_MMC_ADDR + STM32_ETHERNET_MMC_SIZE), DEV_STATIC_RES_MEM(STM32_ETHERNET_DMA_ADDR, STM32_ETHERNET_DMA_ADDR + STM32_ETHERNET_DMA_SIZE), DEV_STATIC_RES_FREQ(72000000, 1), DEV_STATIC_RES_DEV_PARAM("gpio", "/gpio"), DEV_STATIC_RES_DEV_IOMUX("/gpio"), DEV_STATIC_RES_IOMUX("mdc", 0, STM32_PC1, 0, 0), DEV_STATIC_RES_IOMUX("mdio", 0, STM32_PA2, 0, 0), DEV_STATIC_RES_GPIO("resetn", STM32_PC7, 1), DEV_STATIC_RES_DEV_ICU("/cpu"), DEV_STATIC_RES_IRQ(0, STM32_IRQ_ETH, DEV_IRQ_SENSE_HIGH_LEVEL, 0, 0x1), ); #endif #include #include #include #include #define __IO volatile struct stm32f1xx_flash_dev_s { __IO uint32_t FLASH_ACR; __IO uint32_t FLASH_KEYR; __IO uint32_t FLASH_OPTKEYR; __IO uint32_t FLASH_SR; __IO uint32_t FLASH_CR; __IO uint32_t FLASH_AR; __IO uint32_t __reserved0; __IO uint32_t FLASH_OBR; __IO uint32_t FLASH_WRPR; } __attribute__ ((packed)); #define STM32_FLASH_LAT_WS(n) ((n) & 0x7) void stm32_clock_init(void) { uintptr_t a; uint32_t x; __IO struct stm32f1xx_flash_dev_s *flash_dev = (struct stm32f1xx_flash_dev_s *) 0x40022000; /* Disable interrupts. */ cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_CIR_ADDR, 0); /* PLL OFF, PLLI2S OFF, HSE ON, HSI OFF. */ cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_CR_ADDR, endian_le32(STM32_RCC_CR_HSEON)); /* Wait for hse to stabilize. */ do { x = endian_le32(cpu_mem_read_32(STM32_RCC_ADDR + STM32_RCC_CR_ADDR)); } while (!(x & STM32_RCC_CR_HSERDY)); /* Set PLL2 @ 40MHz and PLL3 @ 50MHz */ x = 0; STM32_RCC_CFGR2_PREDIV2_SET(x, 0x4 /* / 5 */); STM32_RCC_CFGR2_PLL2MUL_SET(x, 0x6 /* x 8 */); STM32_RCC_CFGR2_PLL3MUL_SET(x, 0x8 /* x 10 */); cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_CFGR2_ADDR, endian_le32(x)); /* Enable PLL2 @ 40MHz */ a = STM32_RCC_ADDR + STM32_RCC_CR_ADDR; x = endian_le32(cpu_mem_read_32(a)); STM32_RCC_CR_PLL2ON_SET(x, 1); cpu_mem_write_32(a, endian_le32(x)); /* Wait for PLL2 to lock */ do { x = endian_le32(cpu_mem_read_32(a)); } while (!(x & STM32_RCC_CR_PLL2RDY)); /* Enable PLL3 @ 50MHz */ STM32_RCC_CR_PLL3ON_SET(x, 1); cpu_mem_write_32(a, endian_le32(x)); /* Wait for PLL2 to lock */ do { x = endian_le32(cpu_mem_read_32(a)); } while (!(x & STM32_RCC_CR_PLL3RDY)); /* Set PLL @ 72MHz as sink of PLL2 */ x = endian_le32(cpu_mem_read_32(STM32_RCC_ADDR + STM32_RCC_CFGR2_ADDR)); STM32_RCC_CFGR2_PREDIV1SRC_SET(x, 0x1 /* PLL2 */); STM32_RCC_CFGR2_PREDIV1_SET(x, 0x4 /* / 5 */); cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_CFGR2_ADDR, endian_le32(x)); x = endian_le32(cpu_mem_read_32(STM32_RCC_ADDR + STM32_RCC_CFGR_ADDR)); STM32_RCC_CFGR_PLLSRC_SET(x, 0x1 /* PREDIV1 */); STM32_RCC_CFGR_PLLMUL_SET(x, 0x7 /* x 9 */); cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_CFGR_ADDR, endian_le32(x)); /* Enable PLL */ a = STM32_RCC_ADDR + STM32_RCC_CR_ADDR; x = endian_le32(cpu_mem_read_32(a)); STM32_RCC_CR_PLLON_SET(x, 1); cpu_mem_write_32(a, endian_le32(x)); /* Wait for PLL to lock */ do { x = endian_le32(cpu_mem_read_32(a)); } while (!(x & STM32_RCC_CR_PLLRDY)); /* set wait cycles for the flash. */ flash_dev->FLASH_ACR = STM32_FLASH_LAT_WS(2); /* Configure prescalers. */ a = STM32_RCC_ADDR + STM32_RCC_CFGR_ADDR; x = endian_le32(cpu_mem_read_32(a)); STM32_RCC_CFGR_HPRE_SET(x, 0x0 /* / 1 */); /* 72MHZ */ STM32_RCC_CFGR_PPRE1_SET(x, 0x1 /* / 2 */); /* 36MHZ */ STM32_RCC_CFGR_PPRE2_SET(x, 0x0 /* / 1 */); /* 72MHz */ /* Use PLL-based clock path for the system clock. */ STM32_RCC_CFGR_SW_SET(x, 0x2 /* PLL */); /* Set MCO clock source */ STM32_RCC_CFGR_MCO_SET(x, 0x6 /* HSE */); cpu_mem_write_32(a, endian_le32(x)); /* Wait for system clock to be sourced by the PLL. */ do { x = endian_le32(cpu_mem_read_32(a)); } while (!(x & STM32_RCC_CFGR_SWS_PLL)); /* Enable all clock gates. */ cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_AHBENR_ADDR, -1); cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_APB1ENR_ADDR, -1); cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_APB2ENR_ADDR, -1); cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_AHBRSTR_ADDR, -1); cpu_mem_write_32(STM32_RCC_ADDR + STM32_RCC_AHBRSTR_ADDR, 0); }