From patchwork Thu Jul 7 16:02:24 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Toshifumi NISHINAGA X-Patchwork-Id: 646334 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 3rm5TC1MQ7z9sCj for ; Fri, 8 Jul 2016 17:19:11 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=crL2QDt8; dkim-atps=neutral Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 0942C4BA81; Fri, 8 Jul 2016 09:19:02 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id w9sGsvZjIXTb; Fri, 8 Jul 2016 09:19:01 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 4A3F74BA16; Fri, 8 Jul 2016 09:18:53 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id D92A74B7FB for ; Thu, 7 Jul 2016 18:02:57 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id IMTXteNIFp2N for ; Thu, 7 Jul 2016 18:02:57 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-pa0-f65.google.com (mail-pa0-f65.google.com [209.85.220.65]) by theia.denx.de (Postfix) with ESMTPS id 3FFD14A01C for ; Thu, 7 Jul 2016 18:02:53 +0200 (CEST) Received: by mail-pa0-f65.google.com with SMTP id ts6so2139893pac.0 for ; Thu, 07 Jul 2016 09:02:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=pgk52v9PvDJR5Rgdk91bs3Gv8aplhkJw3dkGdX/OHw4=; b=crL2QDt8NXbmTB1LjgrZFPEhZ/gVmGA1ACXY4uADYYTXXklhzrRHYUfYx4aKOwzigO /ygMb93AqbvZp4N9wvaTv6Tah6EXuXT45G6/1TigPDO8MhVzoQ+3umrbSCf54g+RHfVs FbYU+N1cc7LqqBLOwu/RdLY7Y4nGqvE6rdu5YGsgufvETsu/aB0FBe56Mvk4VwmF+a9z JrC/LHYpOIkPfNKFoOrSYmDVVc9ZJOURiJyFb2N/jcWuDxknEerdPrEc3QZM3koSo26V llVfuFXPlMdPVNZa8gG14glqqsPUyy0I1H/6AfKR1qumwlIelsDb1NJ3fgl6DaGJRr6Z gw1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=pgk52v9PvDJR5Rgdk91bs3Gv8aplhkJw3dkGdX/OHw4=; b=TIDUAMhH8Jz8EWbS1S/55TzmdT3s6wTVpy4bIbsDsKerxJtRiMl/QQDcYOIlpA85po MwNCriMq0D88ZrhQZRtlsZuMBHjTZo3qg9HOIk7Ir5bm3AS2lbhZahKPzAcTTciDQnAl C5rfFfkKSB+IPrvBicLTQsLsEx03owiV1G2vOzQQXcYAxadoRf/KNc6xgO7FgiiADN79 DAcO9GK6RGa4G+jBZNDGpa8IW8WGYK2787/H5rKc2Er98tkrEjMoZgxGCEl8JMH31qDH VCoNWBi/jeBGUl/gbSMU135gfMGafstorMOEhrMBDs0OUmA7OciiSzDQ7XCcKPCq6ceZ hbEg== X-Gm-Message-State: ALyK8tJp2L8ZlGlxxNsBy+ZNFmsRetb1Th2VaR2PoKgvWVzR6ly6GEA+rWlcM/piNjJ0ng== X-Received: by 10.66.189.104 with SMTP id gh8mr1496728pac.125.1467907371389; Thu, 07 Jul 2016 09:02:51 -0700 (PDT) Received: from localhost.localdomain ([133.28.97.122]) by smtp.gmail.com with ESMTPSA id tt1sm1277029pac.35.2016.07.07.09.02.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 07 Jul 2016 09:02:50 -0700 (PDT) From: tnishinaga.dev@gmail.com To: u-boot@lists.denx.de Date: Fri, 8 Jul 2016 01:02:24 +0900 Message-Id: <20160707160226.4145-2-tnishinaga.dev@gmail.com> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20160707160226.4145-1-tnishinaga.dev@gmail.com> References: <20160707160226.4145-1-tnishinaga.dev@gmail.com> X-Mailman-Approved-At: Fri, 08 Jul 2016 09:18:44 +0200 Cc: Toshifumi NISHINAGA , gregkh@linuxfoundation.org Subject: [U-Boot] [PATCH 1/3] stm32: clk: Add 200MHz clock configuration for stm32f746 discovery board X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Toshifumi NISHINAGA This patch adds 200MHz clock configuration for stm32f746 discovery board. This patch is based on STM32F4 and emcraft's[1]. [1]: https://github.com/EmcraftSystems/u-boot Signed-off-by: Toshifumi NISHINAGA --- arch/arm/include/asm/arch-stm32f7/stm32.h | 46 ++++++ arch/arm/mach-stm32/stm32f7/Makefile | 2 +- arch/arm/mach-stm32/stm32f7/clock.c | 228 ++++++++++++++++++++++++++++++ arch/arm/mach-stm32/stm32f7/soc.c | 27 ++++ drivers/serial/serial_stm32x7.c | 16 ++- include/configs/stm32f746-disco.h | 3 +- 6 files changed, 319 insertions(+), 3 deletions(-) create mode 100644 arch/arm/mach-stm32/stm32f7/soc.c diff --git a/arch/arm/include/asm/arch-stm32f7/stm32.h b/arch/arm/include/asm/arch-stm32f7/stm32.h index 68bdab0..de55ae5 100644 --- a/arch/arm/include/asm/arch-stm32f7/stm32.h +++ b/arch/arm/include/asm/arch-stm32f7/stm32.h @@ -64,6 +64,52 @@ enum clock { }; #define STM32_BUS_MASK 0xFFFF0000 +struct stm32_rcc_regs { + u32 cr; /* RCC clock control */ + u32 pllcfgr; /* RCC PLL configuration */ + u32 cfgr; /* RCC clock configuration */ + u32 cir; /* RCC clock interrupt */ + u32 ahb1rstr; /* RCC AHB1 peripheral reset */ + u32 ahb2rstr; /* RCC AHB2 peripheral reset */ + u32 ahb3rstr; /* RCC AHB3 peripheral reset */ + u32 rsv0; + u32 apb1rstr; /* RCC APB1 peripheral reset */ + u32 apb2rstr; /* RCC APB2 peripheral reset */ + u32 rsv1[2]; + u32 ahb1enr; /* RCC AHB1 peripheral clock enable */ + u32 ahb2enr; /* RCC AHB2 peripheral clock enable */ + u32 ahb3enr; /* RCC AHB3 peripheral clock enable */ + u32 rsv2; + u32 apb1enr; /* RCC APB1 peripheral clock enable */ + u32 apb2enr; /* RCC APB2 peripheral clock enable */ + u32 rsv3[2]; + u32 ahb1lpenr; /* RCC AHB1 periph clk enable in low pwr mode */ + u32 ahb2lpenr; /* RCC AHB2 periph clk enable in low pwr mode */ + u32 ahb3lpenr; /* RCC AHB3 periph clk enable in low pwr mode */ + u32 rsv4; + u32 apb1lpenr; /* RCC APB1 periph clk enable in low pwr mode */ + u32 apb2lpenr; /* RCC APB2 periph clk enable in low pwr mode */ + u32 rsv5[2]; + u32 bdcr; /* RCC Backup domain control */ + u32 csr; /* RCC clock control & status */ + u32 rsv6[2]; + u32 sscgr; /* RCC spread spectrum clock generation */ + u32 plli2scfgr; /* RCC PLLI2S configuration */ + u32 pllsaicfgr; + u32 dckcfgr; +}; +#define STM32_RCC ((struct stm32_rcc_regs *)RCC_BASE) + +struct stm32_pwr_regs { + u32 cr1; /* power control register 1 */ + u32 csr1; /* power control/status register 2 */ + u32 cr2; /* power control register 2 */ + u32 csr2; /* power control/status register 2 */ +}; +#define STM32_PWR ((struct stm32_pwr_regs *)PWR_BASE) + int configure_clocks(void); +unsigned long clock_get(enum clock clck); +void stm32_flash_latency_cfg(int latency); #endif /* _ASM_ARCH_HARDWARE_H */ diff --git a/arch/arm/mach-stm32/stm32f7/Makefile b/arch/arm/mach-stm32/stm32f7/Makefile index 40f1ad3..643d4d9 100644 --- a/arch/arm/mach-stm32/stm32f7/Makefile +++ b/arch/arm/mach-stm32/stm32f7/Makefile @@ -5,4 +5,4 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-y += timer.o clock.o +obj-y += timer.o clock.o soc.o diff --git a/arch/arm/mach-stm32/stm32f7/clock.c b/arch/arm/mach-stm32/stm32f7/clock.c index 17a715b..78d22d4 100644 --- a/arch/arm/mach-stm32/stm32f7/clock.c +++ b/arch/arm/mach-stm32/stm32f7/clock.c @@ -11,6 +11,234 @@ #include #include +#define RCC_CR_HSION (1 << 0) +#define RCC_CR_HSEON (1 << 16) +#define RCC_CR_HSERDY (1 << 17) +#define RCC_CR_HSEBYP (1 << 18) +#define RCC_CR_CSSON (1 << 19) +#define RCC_CR_PLLON (1 << 24) +#define RCC_CR_PLLRDY (1 << 25) + +#define RCC_PLLCFGR_PLLM_MASK 0x3F +#define RCC_PLLCFGR_PLLN_MASK 0x7FC0 +#define RCC_PLLCFGR_PLLP_MASK 0x30000 +#define RCC_PLLCFGR_PLLQ_MASK 0xF000000 +#define RCC_PLLCFGR_PLLSRC (1 << 22) +#define RCC_PLLCFGR_PLLM_SHIFT 0 +#define RCC_PLLCFGR_PLLN_SHIFT 6 +#define RCC_PLLCFGR_PLLP_SHIFT 16 +#define RCC_PLLCFGR_PLLQ_SHIFT 24 + +#define RCC_CFGR_AHB_PSC_MASK 0xF0 +#define RCC_CFGR_APB1_PSC_MASK 0x1C00 +#define RCC_CFGR_APB2_PSC_MASK 0xE000 +#define RCC_CFGR_SW0 (1 << 0) +#define RCC_CFGR_SW1 (1 << 1) +#define RCC_CFGR_SW_MASK 0x3 +#define RCC_CFGR_SW_HSI 0 +#define RCC_CFGR_SW_HSE RCC_CFGR_SW0 +#define RCC_CFGR_SW_PLL RCC_CFGR_SW1 +#define RCC_CFGR_SWS0 (1 << 2) +#define RCC_CFGR_SWS1 (1 << 3) +#define RCC_CFGR_SWS_MASK 0xC +#define RCC_CFGR_SWS_HSI 0 +#define RCC_CFGR_SWS_HSE RCC_CFGR_SWS0 +#define RCC_CFGR_SWS_PLL RCC_CFGR_SWS1 +#define RCC_CFGR_HPRE_SHIFT 4 +#define RCC_CFGR_PPRE1_SHIFT 10 +#define RCC_CFGR_PPRE2_SHIFT 13 + +#define RCC_APB1ENR_PWREN (1 << 28) + +/* + * RCC USART specific definitions + */ +#define RCC_ENR_USART1EN (1 << 4) +#define RCC_ENR_USART2EN (1 << 17) +#define RCC_ENR_USART3EN (1 << 18) +#define RCC_ENR_USART6EN (1 << 5) + +/* + * Offsets of some PWR registers + */ +#define PWR_CR1_ODEN (1 << 16) +#define PWR_CR1_ODSWEN (1 << 17) +#define PWR_CSR1_ODRDY (1 << 16) +#define PWR_CSR1_ODSWRDY (1 << 17) + + +/* + * RCC GPIO specific definitions + */ +#define RCC_ENR_GPIO_A_EN (1 << 0) +#define RCC_ENR_GPIO_B_EN (1 << 1) +#define RCC_ENR_GPIO_C_EN (1 << 2) +#define RCC_ENR_GPIO_D_EN (1 << 3) +#define RCC_ENR_GPIO_E_EN (1 << 4) +#define RCC_ENR_GPIO_F_EN (1 << 5) +#define RCC_ENR_GPIO_G_EN (1 << 6) +#define RCC_ENR_GPIO_H_EN (1 << 7) +#define RCC_ENR_GPIO_I_EN (1 << 8) +#define RCC_ENR_GPIO_J_EN (1 << 9) +#define RCC_ENR_GPIO_K_EN (1 << 10) + +struct pll_psc { + u8 pll_m; + u16 pll_n; + u8 pll_p; + u8 pll_q; + u8 ahb_psc; + u8 apb1_psc; + u8 apb2_psc; +}; + +#define AHB_PSC_1 0 +#define AHB_PSC_2 0x8 +#define AHB_PSC_4 0x9 +#define AHB_PSC_8 0xA +#define AHB_PSC_16 0xB +#define AHB_PSC_64 0xC +#define AHB_PSC_128 0xD +#define AHB_PSC_256 0xE +#define AHB_PSC_512 0xF + +#define APB_PSC_1 0 +#define APB_PSC_2 0x4 +#define APB_PSC_4 0x5 +#define APB_PSC_8 0x6 +#define APB_PSC_16 0x7 + +#if !defined(CONFIG_STM32_HSE_HZ) +#error "CONFIG_STM32_HSE_HZ not defined!" +#else +#if (CONFIG_STM32_HSE_HZ == 25000000) +#if (CONFIG_SYS_CLK_FREQ == 200000000) +/* 200 MHz */ +struct pll_psc sys_pll_psc = { + .pll_m = 25, + .pll_n = 400, + .pll_p = 2, + .pll_q = 8, + .ahb_psc = AHB_PSC_1, + .apb1_psc = APB_PSC_4, + .apb2_psc = APB_PSC_2 +}; +#endif +#else +#error "No PLL/Prescaler configuration for given CONFIG_STM32_HSE_HZ exists" +#endif +#endif + +int configure_clocks(void) +{ + /* Reset RCC configuration */ + setbits_le32(&STM32_RCC->cr, RCC_CR_HSION); + writel(0, &STM32_RCC->cfgr); /* Reset CFGR */ + clrbits_le32(&STM32_RCC->cr, (RCC_CR_HSEON | RCC_CR_CSSON + | RCC_CR_PLLON)); + writel(0x24003010, &STM32_RCC->pllcfgr); /* Reset value from RM */ + clrbits_le32(&STM32_RCC->cr, RCC_CR_HSEBYP); + writel(0, &STM32_RCC->cir); /* Disable all interrupts */ + + /* Configure for HSE+PLL operation */ + setbits_le32(&STM32_RCC->cr, RCC_CR_HSEON); + while (!(readl(&STM32_RCC->cr) & RCC_CR_HSERDY)) + ; + + setbits_le32(&STM32_RCC->cfgr, (( + sys_pll_psc.ahb_psc << RCC_CFGR_HPRE_SHIFT) + | (sys_pll_psc.apb1_psc << RCC_CFGR_PPRE1_SHIFT) + | (sys_pll_psc.apb2_psc << RCC_CFGR_PPRE2_SHIFT))); + + /* Configure the main PLL */ + uint32_t pllcfgr = 0; + pllcfgr = RCC_PLLCFGR_PLLSRC; /* pll source HSE */ + pllcfgr |= sys_pll_psc.pll_m << RCC_PLLCFGR_PLLM_SHIFT; + pllcfgr |= sys_pll_psc.pll_n << RCC_PLLCFGR_PLLN_SHIFT; + pllcfgr |= ((sys_pll_psc.pll_p >> 1) - 1) << RCC_PLLCFGR_PLLP_SHIFT; + pllcfgr |= sys_pll_psc.pll_q << RCC_PLLCFGR_PLLQ_SHIFT; + writel(pllcfgr, &STM32_RCC->pllcfgr); + + /* Enable the main PLL */ + setbits_le32(&STM32_RCC->cr, RCC_CR_PLLON); + while (!(readl(&STM32_RCC->cr) & RCC_CR_PLLRDY)) + ; + + /* Enable high performance mode, System frequency up to 200 MHz */ + setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_PWREN); + setbits_le32(&STM32_PWR->cr1, PWR_CR1_ODEN); + /* Infinite wait! */ + while (!(readl(&STM32_PWR->csr1) & PWR_CSR1_ODRDY)) + ; + /* Enable the Over-drive switch */ + setbits_le32(&STM32_PWR->cr1, PWR_CR1_ODSWEN); + /* Infinite wait! */ + while (!(readl(&STM32_PWR->csr1) & PWR_CSR1_ODSWRDY)) + ; + + stm32_flash_latency_cfg(5); + clrbits_le32(&STM32_RCC->cfgr, (RCC_CFGR_SW0 | RCC_CFGR_SW1)); + setbits_le32(&STM32_RCC->cfgr, RCC_CFGR_SW_PLL); + + while ((readl(&STM32_RCC->cfgr) & RCC_CFGR_SWS_MASK) != + RCC_CFGR_SWS_PLL) + ; + + return 0; +} + +unsigned long clock_get(enum clock clck) +{ + u32 sysclk = 0; + u32 shift = 0; + /* Prescaler table lookups for clock computation */ + u8 ahb_psc_table[16] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9 + }; + u8 apb_psc_table[8] = { + 0, 0, 0, 0, 1, 2, 3, 4 + }; + + if ((readl(&STM32_RCC->cfgr) & RCC_CFGR_SWS_MASK) == + RCC_CFGR_SWS_PLL) { + u16 pllm, plln, pllp; + pllm = (readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLM_MASK); + plln = ((readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLN_MASK) + >> RCC_PLLCFGR_PLLN_SHIFT); + pllp = ((((readl(&STM32_RCC->pllcfgr) & RCC_PLLCFGR_PLLP_MASK) + >> RCC_PLLCFGR_PLLP_SHIFT) + 1) << 1); + sysclk = ((CONFIG_STM32_HSE_HZ / pllm) * plln) / pllp; + } + + switch (clck) { + case CLOCK_CORE: + return sysclk; + break; + case CLOCK_AHB: + shift = ahb_psc_table[( + (readl(&STM32_RCC->cfgr) & RCC_CFGR_AHB_PSC_MASK) + >> RCC_CFGR_HPRE_SHIFT)]; + return sysclk >>= shift; + break; + case CLOCK_APB1: + shift = apb_psc_table[( + (readl(&STM32_RCC->cfgr) & RCC_CFGR_APB1_PSC_MASK) + >> RCC_CFGR_PPRE1_SHIFT)]; + return sysclk >>= shift; + break; + case CLOCK_APB2: + shift = apb_psc_table[( + (readl(&STM32_RCC->cfgr) & RCC_CFGR_APB2_PSC_MASK) + >> RCC_CFGR_PPRE2_SHIFT)]; + return sysclk >>= shift; + break; + default: + return 0; + break; + } +} + + void clock_setup(int peripheral) { switch (peripheral) { diff --git a/arch/arm/mach-stm32/stm32f7/soc.c b/arch/arm/mach-stm32/stm32f7/soc.c new file mode 100644 index 0000000..6a1e019 --- /dev/null +++ b/arch/arm/mach-stm32/stm32f7/soc.c @@ -0,0 +1,27 @@ +/* + * (C) Copyright 2015 + * Kamil Lulko, + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +u32 get_cpu_rev(void) +{ + return 0; +} + +int arch_cpu_init(void) +{ + configure_clocks(); + + return 0; +} + +void s_init(void) +{ +} diff --git a/drivers/serial/serial_stm32x7.c b/drivers/serial/serial_stm32x7.c index cfbfab7..592c0bd 100644 --- a/drivers/serial/serial_stm32x7.c +++ b/drivers/serial/serial_stm32x7.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "serial_stm32x7.h" @@ -18,7 +19,20 @@ static int stm32_serial_setbrg(struct udevice *dev, int baudrate) { struct stm32x7_serial_platdata *plat = dev->platdata; struct stm32_usart *const usart = plat->base; - writel(plat->clock/baudrate, &usart->brr); + u32 clock, int_div, frac_div, tmp; + + if (((u32)usart & STM32_BUS_MASK) == APB1_PERIPH_BASE) + clock = clock_get(CLOCK_APB1); + else if (((u32)usart & STM32_BUS_MASK) == APB2_PERIPH_BASE) + clock = clock_get(CLOCK_APB2); + else + return -EINVAL; + + int_div = (25 * clock) / (4 * baudrate); + tmp = ((int_div / 100) << USART_BRR_M_SHIFT) & USART_BRR_M_MASK; + frac_div = int_div - (100 * (tmp >> USART_BRR_M_SHIFT)); + tmp |= (((frac_div * 16) + 50) / 100) & USART_BRR_F_MASK; + writel(tmp, &usart->brr); return 0; } diff --git a/include/configs/stm32f746-disco.h b/include/configs/stm32f746-disco.h index e544a21..e1140a8 100644 --- a/include/configs/stm32f746-disco.h +++ b/include/configs/stm32f746-disco.h @@ -42,7 +42,8 @@ #define CONFIG_STM32_FLASH #define CONFIG_STM32X7_SERIAL -#define CONFIG_SYS_CLK_FREQ 16*1000*1000 /* 180 MHz */ +#define CONFIG_STM32_HSE_HZ 25000000 +#define CONFIG_SYS_CLK_FREQ 200000000 /* 200 MHz */ #define CONFIG_SYS_HZ_CLOCK 1000000 /* Timer is clocked at 1MHz */ #define CONFIG_CMDLINE_TAG