[U-Boot] [PATCH 0/6] Add ARMv7M STM32F1 and STM3210E-EVAL board support

This series adds support for the STM32F1 SoC family and the STM3210E-EVAL board on top of the STM32F4 SoC family support [1].
Since this board has no DRAM the first patch fixes the build when CONFIG_NR_DRAM_BANKS is not set. A patch is also required to force the processor to stay in Thumb mode when 'go'ing to an application.
As the STM32F1 differs greatly from STM32F4 in flash and clock layout, there's a separate subdirectory for the STM32F1 family. The gpio and serial drivers are shared as these peripherals are mostly similar with only the pinmux bits being significantly different in the gpio driver.
The STM3210E-EVAL board is supported with 1MiB Flash and 96KiB of SRAM on the STM32F103ZGT6, USART1 for console, and four user LEDs.
[1] http://lists.denx.de/pipermail/u-boot/2015-March/206640.html
Matt Porter (6): image: fix build when CONFIG_NR_DRAM_BANKS is disabled on ARM common/cmd_boot: keep ARM v7M in thumb mode during do_go_exec() ARMv7M: add STM32F1 support gpio: stm32: add stm32f1 support serial: stm32: add stm32f1 support board: add stm3210e-eval board support
arch/arm/Kconfig | 5 + arch/arm/cpu/armv7m/Makefile | 1 + arch/arm/cpu/armv7m/stm32f1/Makefile | 13 ++ arch/arm/cpu/armv7m/stm32f1/clock.c | 195 ++++++++++++++++++++++++++++++ arch/arm/cpu/armv7m/stm32f1/flash.c | 179 +++++++++++++++++++++++++++ arch/arm/cpu/armv7m/stm32f1/soc.c | 35 ++++++ arch/arm/cpu/armv7m/stm32f1/timer.c | 120 ++++++++++++++++++ arch/arm/include/asm/arch-stm32f1/gpio.h | 117 ++++++++++++++++++ arch/arm/include/asm/arch-stm32f1/stm32.h | 115 ++++++++++++++++++ board/st/stm3210e-eval/Kconfig | 19 +++ board/st/stm3210e-eval/MAINTAINERS | 5 + board/st/stm3210e-eval/Makefile | 13 ++ board/st/stm3210e-eval/stm3210e-eval.c | 85 +++++++++++++ common/cmd_boot.c | 4 + common/image.c | 2 +- configs/stm3210e-eval_defconfig | 3 + drivers/gpio/stm32_gpio.c | 103 +++++++++++++++- drivers/serial/serial_stm32.c | 7 ++ include/configs/stm3210e-eval.h | 117 ++++++++++++++++++ include/flash.h | 1 + 20 files changed, 1137 insertions(+), 2 deletions(-) create mode 100644 arch/arm/cpu/armv7m/stm32f1/Makefile create mode 100644 arch/arm/cpu/armv7m/stm32f1/clock.c create mode 100644 arch/arm/cpu/armv7m/stm32f1/flash.c create mode 100644 arch/arm/cpu/armv7m/stm32f1/soc.c create mode 100644 arch/arm/cpu/armv7m/stm32f1/timer.c create mode 100644 arch/arm/include/asm/arch-stm32f1/gpio.h create mode 100644 arch/arm/include/asm/arch-stm32f1/stm32.h create mode 100644 board/st/stm3210e-eval/Kconfig create mode 100644 board/st/stm3210e-eval/MAINTAINERS create mode 100644 board/st/stm3210e-eval/Makefile create mode 100644 board/st/stm3210e-eval/stm3210e-eval.c create mode 100644 configs/stm3210e-eval_defconfig create mode 100644 include/configs/stm3210e-eval.h

common/image.c currently implicitly depends on CONFIG_NR_DRAM_BANKS when CONFIG_ARM is enabled. Make this requirement explicit.
Signed-off-by: Matt Porter mporter@konsulko.com --- common/image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/image.c b/common/image.c index 162b682..73c24f5 100644 --- a/common/image.c +++ b/common/image.c @@ -461,7 +461,7 @@ phys_size_t getenv_bootm_size(void) tmp = 0;
-#if defined(CONFIG_ARM) +#if defined(CONFIG_ARM) && defined(CONFIG_NR_DRAM_BANKS) return gd->bd->bi_dram[0].size - tmp; #else return gd->bd->bi_memsize - tmp;

Hello Matt,
On Tue, 14 Apr 2015 14:07:17 -0400, Matt Porter mporter@konsulko.com wrote:
common/image.c currently implicitly depends on CONFIG_NR_DRAM_BANKS when CONFIG_ARM is enabled. Make this requirement explicit.
Signed-off-by: Matt Porter mporter@konsulko.com
common/image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/image.c b/common/image.c index 162b682..73c24f5 100644 --- a/common/image.c +++ b/common/image.c @@ -461,7 +461,7 @@ phys_size_t getenv_bootm_size(void) tmp = 0;
-#if defined(CONFIG_ARM) +#if defined(CONFIG_ARM) && defined(CONFIG_NR_DRAM_BANKS) return gd->bd->bi_dram[0].size - tmp; #else return gd->bd->bi_memsize - tmp; -- 2.1.0
I am not entirely fond of a symbol's existence conditioning some code which does not actually use the symbol. I do understand the dependency here -- that bi_dram[0] is meaningful only if CONFIG_NR_DRAM_BANKS is 1 or more -- but then, why does this code not depend on the value of the symbol? Makes me think the patch is not complete and the code should be fixed to depend on the value of CONFIG_NR_DRAM_BANKS.
Amicalement,

On Thu, Apr 16, 2015 at 03:52:16PM +0200, Albert ARIBAUD wrote:
Hello Matt,
On Tue, 14 Apr 2015 14:07:17 -0400, Matt Porter mporter@konsulko.com wrote:
common/image.c currently implicitly depends on CONFIG_NR_DRAM_BANKS when CONFIG_ARM is enabled. Make this requirement explicit.
Signed-off-by: Matt Porter mporter@konsulko.com
common/image.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/common/image.c b/common/image.c index 162b682..73c24f5 100644 --- a/common/image.c +++ b/common/image.c @@ -461,7 +461,7 @@ phys_size_t getenv_bootm_size(void) tmp = 0;
-#if defined(CONFIG_ARM) +#if defined(CONFIG_ARM) && defined(CONFIG_NR_DRAM_BANKS) return gd->bd->bi_dram[0].size - tmp; #else return gd->bd->bi_memsize - tmp;
I am not entirely fond of a symbol's existence conditioning some code which does not actually use the symbol. I do understand the dependency here -- that bi_dram[0] is meaningful only if CONFIG_NR_DRAM_BANKS is 1 or more -- but then, why does this code not depend on the value of the symbol? Makes me think the patch is not complete and the code should be fixed to depend on the value of CONFIG_NR_DRAM_BANKS.
The problem is that CONFIG_NR_DRAM_BANKS means both "I have DRAM" and "I have X number of DRAM banks". In turn include/asm-generic/u-boot.h will only say we have gd->bd->bi_dram if CONFIG_NR_DRAM_BANKS is set so we can only reference that field when it's also set. Otherwise we get a compile error about no such member.
There's a further argument (as I read and re-read getenv_bootm_size()) that getenv_bootm_clsize() should be cleaned-up / re-worked as it defaults to too large of a value (which is why stuff gets relocated "high" and then Linux doesn't see it and then people do initrd_high=0xffffffff and fdt_high=0xffffffff) but that's unrelated to this patch I think.

On ARM v7M, the processor will return to ARM mode when executing a blx instruction with bit 0 of the address == 0. Always set it to 1 to stay in thumb mode.
Signed-off-by: Matt Porter mporter@konsulko.com --- common/cmd_boot.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/common/cmd_boot.c b/common/cmd_boot.c index 8f2e070..20ce652 100644 --- a/common/cmd_boot.c +++ b/common/cmd_boot.c @@ -38,6 +38,10 @@ static int do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * pass address parameter as argv[0] (aka command name), * and all remaining args */ +#ifdef CONFIG_CPU_V7M + /* For ARM V7M, set bit zero to stay in Thumb mode */ + addr++; +#endif rc = do_go_exec ((void *)addr, argc - 1, argv + 1); if (rc != 0) rcode = 1;

2015-04-14 20:07 GMT+02:00 Matt Porter mporter@konsulko.com:
On ARM v7M, the processor will return to ARM mode when executing a blx instruction with bit 0 of the address == 0. Always set it to 1 to stay in thumb mode.
Signed-off-by: Matt Porter mporter@konsulko.com
common/cmd_boot.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/common/cmd_boot.c b/common/cmd_boot.c index 8f2e070..20ce652 100644 --- a/common/cmd_boot.c +++ b/common/cmd_boot.c @@ -38,6 +38,10 @@ static int do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * pass address parameter as argv[0] (aka command name), * and all remaining args */ +#ifdef CONFIG_CPU_V7M
/* For ARM V7M, set bit zero to stay in Thumb mode */
addr++;
+#endif rc = do_go_exec ((void *)addr, argc - 1, argv + 1); if (rc != 0) rcode = 1;
-- 2.1.0
I think addr |= 1 would be better - there is always a possibility that kernel image has the zero bit already set (this is the case in my own Buildroot build setup I am using for STM32F4 builds). Anyways - keeping this bit set should be the responsibility of kernel image build process so such machine specific quirk can be kept out of the common code.
/Kamil

On Wed, Apr 15, 2015 at 12:33:43PM +0200, Kamil Lulko wrote:
2015-04-14 20:07 GMT+02:00 Matt Porter mporter@konsulko.com:
On ARM v7M, the processor will return to ARM mode when executing a blx instruction with bit 0 of the address == 0. Always set it to 1 to stay in thumb mode.
Signed-off-by: Matt Porter mporter@konsulko.com
common/cmd_boot.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/common/cmd_boot.c b/common/cmd_boot.c index 8f2e070..20ce652 100644 --- a/common/cmd_boot.c +++ b/common/cmd_boot.c @@ -38,6 +38,10 @@ static int do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * pass address parameter as argv[0] (aka command name), * and all remaining args */ +#ifdef CONFIG_CPU_V7M
/* For ARM V7M, set bit zero to stay in Thumb mode */
addr++;
+#endif rc = do_go_exec ((void *)addr, argc - 1, argv + 1); if (rc != 0) rcode = 1;
I think addr |= 1 would be better - there is always a possibility that kernel image has the zero bit already set (this is the case in my own Buildroot build setup I am using for STM32F4 builds). Anyways - keeping this bit set should be the responsibility of kernel image build process so such machine specific quirk can be kept out of the common code.
I'd agree about |='ing in 1. But it's not a machine quirk, it's a requirement of the Cortex-M family that you not exit Thumb-mode (since it's Thumb-only) and given how we end up trying to jump to the address (here or in 'go' which Matt didn't post the patch for, but same logic) we can / will have problems if we don't do this. You can work around it for images we throw a header into but 'go' is where this gets really annoying.

On Wed, Apr 15, 2015 at 08:34:30AM -0400, Tom Rini wrote:
On Wed, Apr 15, 2015 at 12:33:43PM +0200, Kamil Lulko wrote:
2015-04-14 20:07 GMT+02:00 Matt Porter mporter@konsulko.com:
On ARM v7M, the processor will return to ARM mode when executing a blx instruction with bit 0 of the address == 0. Always set it to 1 to stay in thumb mode.
Signed-off-by: Matt Porter mporter@konsulko.com
common/cmd_boot.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/common/cmd_boot.c b/common/cmd_boot.c index 8f2e070..20ce652 100644 --- a/common/cmd_boot.c +++ b/common/cmd_boot.c @@ -38,6 +38,10 @@ static int do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * pass address parameter as argv[0] (aka command name), * and all remaining args */ +#ifdef CONFIG_CPU_V7M
/* For ARM V7M, set bit zero to stay in Thumb mode */
addr++;
+#endif rc = do_go_exec ((void *)addr, argc - 1, argv + 1); if (rc != 0) rcode = 1;
I think addr |= 1 would be better - there is always a possibility that kernel image has the zero bit already set (this is the case in my own Buildroot build setup I am using for STM32F4 builds). Anyways - keeping this bit set should be the responsibility of kernel image build process so such machine specific quirk can be kept out of the common code.
I'd agree about |='ing in 1. But it's not a machine quirk, it's a requirement of the Cortex-M family that you not exit Thumb-mode (since it's Thumb-only) and given how we end up trying to jump to the address (here or in 'go' which Matt didn't post the patch for, but same logic) we can / will have problems if we don't do this. You can work around it for images we throw a header into but 'go' is where this gets really annoying.
"|1" is indeed much better, I will update it for that implementation. Just to be clear, this patch *is* for the go command which is what I use to load my RTOS. Kamil's comment implies the bootm path which I don't touch at all since I don't even support it in this config (we're running full U-Boot from SRAM and the CMD_BOOTM support is quite large and not necessary for my application).
I understand the concern about cluttering up common code with this. An alternative is to force this knowledge on the user such that they need to "go 080203a9" to run a Thumb-2 application located at 0x080203a8. It's ugly, but could be documented. I'd rather see an address fixup function or similar approach if we want to avoid cluttering the common path with ifdefry.
-Matt

Hello Matt,
On Tue, 14 Apr 2015 14:07:18 -0400, Matt Porter mporter@konsulko.com wrote:
On ARM v7M, the processor will return to ARM mode when executing a blx instruction with bit 0 of the address == 0. Always set it to 1 to stay in thumb mode.
This should be done for all targets which build with Thumb instruction set, not only ARMv7M, should it not?
Signed-off-by: Matt Porter mporter@konsulko.com
common/cmd_boot.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/common/cmd_boot.c b/common/cmd_boot.c index 8f2e070..20ce652 100644 --- a/common/cmd_boot.c +++ b/common/cmd_boot.c @@ -38,6 +38,10 @@ static int do_go(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) * pass address parameter as argv[0] (aka command name), * and all remaining args */ +#ifdef CONFIG_CPU_V7M
- /* For ARM V7M, set bit zero to stay in Thumb mode */
- addr++;
+#endif rc = do_go_exec ((void *)addr, argc - 1, argv + 1); if (rc != 0) rcode = 1;
-- 2.1.0
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Amicalement,

On Thu, Apr 16, 2015 at 03:53:56PM +0200, Albert ARIBAUD wrote:
Hello Matt,
On Tue, 14 Apr 2015 14:07:18 -0400, Matt Porter mporter@konsulko.com wrote:
On ARM v7M, the processor will return to ARM mode when executing a blx instruction with bit 0 of the address == 0. Always set it to 1 to stay in thumb mode.
This should be done for all targets which build with Thumb instruction set, not only ARMv7M, should it not?
No, because it's not a problem on CPUs where we can do Thumb or non-Thumb instructions, only on CPUs where we can _only_ do Thumb instructions (or the special subset of "other" instructions the core allows). On ARM v7M trying to do the blx in ARM mode isn't allowed and causes an abort (or some other exception, I forget which) to happen upon execution.

Add ARMv7M STM32F1 support including clocks, timer, gpio, and flash.
Signed-off-by: Matt Porter mporter@konsulko.com --- arch/arm/cpu/armv7m/Makefile | 1 + arch/arm/cpu/armv7m/stm32f1/Makefile | 13 ++ arch/arm/cpu/armv7m/stm32f1/clock.c | 195 ++++++++++++++++++++++++++++++ arch/arm/cpu/armv7m/stm32f1/flash.c | 179 +++++++++++++++++++++++++++ arch/arm/cpu/armv7m/stm32f1/soc.c | 35 ++++++ arch/arm/cpu/armv7m/stm32f1/timer.c | 120 ++++++++++++++++++ arch/arm/include/asm/arch-stm32f1/gpio.h | 117 ++++++++++++++++++ arch/arm/include/asm/arch-stm32f1/stm32.h | 115 ++++++++++++++++++ include/flash.h | 1 + 9 files changed, 776 insertions(+) create mode 100644 arch/arm/cpu/armv7m/stm32f1/Makefile create mode 100644 arch/arm/cpu/armv7m/stm32f1/clock.c create mode 100644 arch/arm/cpu/armv7m/stm32f1/flash.c create mode 100644 arch/arm/cpu/armv7m/stm32f1/soc.c create mode 100644 arch/arm/cpu/armv7m/stm32f1/timer.c create mode 100644 arch/arm/include/asm/arch-stm32f1/gpio.h create mode 100644 arch/arm/include/asm/arch-stm32f1/stm32.h
diff --git a/arch/arm/cpu/armv7m/Makefile b/arch/arm/cpu/armv7m/Makefile index b662e03..93a1956 100644 --- a/arch/arm/cpu/armv7m/Makefile +++ b/arch/arm/cpu/armv7m/Makefile @@ -8,4 +8,5 @@ extra-y := start.o obj-y += cpu.o
+obj-$(CONFIG_STM32F1) += stm32f1/ obj-$(CONFIG_STM32F4) += stm32f4/ diff --git a/arch/arm/cpu/armv7m/stm32f1/Makefile b/arch/arm/cpu/armv7m/stm32f1/Makefile new file mode 100644 index 0000000..7b43761 --- /dev/null +++ b/arch/arm/cpu/armv7m/stm32f1/Makefile @@ -0,0 +1,13 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2015 +# Kamil Lulko, rev13@wp.pl +# +# Copyright 2015 Konsulko Group, Matt Porter mporter@konsulko.com +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += soc.o clock.o timer.o flash.o diff --git a/arch/arm/cpu/armv7m/stm32f1/clock.c b/arch/arm/cpu/armv7m/stm32f1/clock.c new file mode 100644 index 0000000..b921eff --- /dev/null +++ b/arch/arm/cpu/armv7m/stm32f1/clock.c @@ -0,0 +1,195 @@ +/* + * (C) Copyright 2015 + * Kamil Lulko, rev13@wp.pl + * + * Copyright 2015 Konsulko Group, Matt Porter mporter@konsulko.com + * + * (C) Copyright 2014 + * STMicroelectronics + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/stm32.h> + +#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_CFGR_PLLMUL_MASK 0x3C0000 +#define RCC_CFGR_PLLMUL_SHIFT 18 +#define RCC_CFGR_PLLSRC_HSE (1 << 16) + +#define RCC_CFGR_AHB_PSC_MASK 0xF0 +#define RCC_CFGR_APB1_PSC_MASK 0x700 +#define RCC_CFGR_APB2_PSC_MASK 0x3800 +#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 8 +#define RCC_CFGR_PPRE2_SHIFT 11 + +#define RCC_APB1ENR_PWREN (1 << 28) + +#define PWR_CR_VOS0 (1 << 14) +#define PWR_CR_VOS1 (1 << 15) +#define PWR_CR_VOS_MASK 0xC000 +#define PWR_CR_VOS_SCALE_MODE_1 (PWR_CR_VOS0 | PWR_CR_VOS1) +#define PWR_CR_VOS_SCALE_MODE_2 (PWR_CR_VOS1) +#define PWR_CR_VOS_SCALE_MODE_3 (PWR_CR_VOS0) + +#define FLASH_ACR_WS(n) n +#define FLASH_ACR_PRFTEN (1 << 8) +#define FLASH_ACR_ICEN (1 << 9) +#define FLASH_ACR_DCEN (1 << 10) + +struct psc { + 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 == 8000000) +#define RCC_CFGR_PLLMUL_CFG 0x7 +struct psc psc_hse = { + .ahb_psc = AHB_PSC_1, + .apb1_psc = APB_PSC_2, + .apb2_psc = APB_PSC_1 +}; +#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)); + 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)) + ; + + /* Enable high performance mode, System frequency up to 168 MHz */ + setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_PWREN); + writel(PWR_CR_VOS_SCALE_MODE_1, &STM32_PWR->cr); + + setbits_le32(&STM32_RCC->cfgr, + RCC_CFGR_PLLMUL_CFG << RCC_CFGR_PLLMUL_SHIFT); + setbits_le32(&STM32_RCC->cfgr, RCC_CFGR_PLLSRC_HSE); + setbits_le32(&STM32_RCC->cfgr, (( + psc_hse.ahb_psc << RCC_CFGR_HPRE_SHIFT) + | (psc_hse.apb1_psc << RCC_CFGR_PPRE1_SHIFT) + | (psc_hse.apb2_psc << RCC_CFGR_PPRE2_SHIFT))); + + setbits_le32(&STM32_RCC->cr, RCC_CR_PLLON); + + while (!(readl(&STM32_RCC->cr) & RCC_CR_PLLRDY)) + ; + + /* 5 wait states, Prefetch enabled, D-Cache enabled, I-Cache enabled */ + writel(FLASH_ACR_WS(5) | FLASH_ACR_PRFTEN | FLASH_ACR_ICEN + | FLASH_ACR_DCEN, &STM32_FLASH->acr); + + 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; + /* PLL table lookups for clock computation */ + u8 pll_mul_table[16] = { + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16 + }; + /* 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 pll; + pll = ((readl(&STM32_RCC->cfgr) & RCC_CFGR_PLLMUL_MASK) + >> RCC_CFGR_PLLMUL_SHIFT); + sysclk = CONFIG_STM32_HSE_HZ * pll_mul_table[pll]; + } + + 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; + } +} diff --git a/arch/arm/cpu/armv7m/stm32f1/flash.c b/arch/arm/cpu/armv7m/stm32f1/flash.c new file mode 100644 index 0000000..b1ee1d9 --- /dev/null +++ b/arch/arm/cpu/armv7m/stm32f1/flash.c @@ -0,0 +1,179 @@ +/* + * (C) Copyright 2015 + * Kamil Lulko, rev13@wp.pl + * + * Copyright 2015 Konsulko Group, Matt Porter mporter@konsulko.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/stm32.h> + +#define STM32_FLASH_KEY1 0x45670123 +#define STM32_FLASH_KEY2 0xcdef89ab + +#define STM32_NUM_BANKS 2 +#define STM32_MAX_BANK 0x200 + +flash_info_t flash_info[STM32_NUM_BANKS]; +static struct stm32_flash_bank_regs *flash_bank[STM32_NUM_BANKS]; + +static void stm32f1_flash_lock(u8 bank, u8 lock) +{ + if (lock) { + setbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_LOCK); + } else { + writel(STM32_FLASH_KEY1, &flash_bank[bank]->keyr); + writel(STM32_FLASH_KEY2, &flash_bank[bank]->keyr); + } +} + +/* Only XL devices are supported (2 KiB sector size) */ +unsigned long flash_init(void) +{ + u8 i, banks; + u16 j, size; + + /* Set up accessors for XL devices with wonky register layout */ + flash_bank[0] = (struct stm32_flash_bank_regs *)&STM32_FLASH->keyr; + flash_bank[1] = (struct stm32_flash_bank_regs *)&STM32_FLASH->keyr2; + + /* + * Get total flash size (in KiB) and configure number of banks + * present and sector count per bank. + */ + size = readw(&STM32_DES->flash_size); + if (size <= STM32_MAX_BANK) { + banks = 1; + flash_info[0].sector_count = size >> 1; + } else if (size > STM32_MAX_BANK) { + banks = 2; + flash_info[0].sector_count = STM32_MAX_BANK >> 1; + flash_info[1].sector_count = (size - STM32_MAX_BANK) >> 1; + } + + /* Configure start/size for all sectors */ + for (i = 0; i < banks; i++) { + flash_info[i].flash_id = FLASH_STM32F1; + flash_info[i].start[0] = CONFIG_SYS_FLASH_BASE + (i << 19); + flash_info[i].size = 2048; + for (j = 1; (j < flash_info[i].sector_count); j++) { + flash_info[i].start[j] = flash_info[i].start[j - 1] + + 2048; + flash_info[i].size += 2048; + } + } + + return size << 10; +} + +void flash_print_info(flash_info_t *info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf("Missing or unknown FLASH type\n"); + return; + } else if (info->flash_id == FLASH_STM32F1) { + printf("STM32F1 Embedded Flash\n"); + } + + printf(" Size: %ld MB in %d Sectors\n", + info->size >> 10, info->sector_count); + + printf(" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; ++i) { + if ((i % 5) == 0) + printf("\n "); + printf(" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " "); + } + printf("\n"); + return; +} + +int flash_erase(flash_info_t *info, int first, int last) +{ + u8 bank = 0xff; + int i; + + for (i = 0; i < STM32_NUM_BANKS; i++) { + if (info == &flash_info[i]) { + bank = i; + break; + } + } + if (bank == 0xff) + return -1; + + stm32f1_flash_lock(bank, 0); + + for (i = first; i <= last; i++) { + while (readl(&flash_bank[bank]->sr) & STM32_FLASH_SR_BSY) + ; + + setbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_PER); + + writel(info->start[i], &flash_bank[bank]->ar); + + setbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_STRT); + + while (readl(&flash_bank[bank]->sr) & STM32_FLASH_SR_BSY) + ; + } + + clrbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_PER); + + stm32f1_flash_lock(bank, 1); + + return 0; +} + +int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong i; + u8 bank = 0xff; + + if (addr & 1) { + printf("Flash address must be half word aligned\n"); + return -1; + } + + if (cnt & 1) { + printf("Flash length must be half word aligned\n"); + return -1; + } + + for (i = 0; i < 2; i++) { + if (info == &flash_info[i]) { + bank = i; + break; + } + } + + if (bank == 0xff) + return -1; + + while (readl(&flash_bank[bank]->sr) & STM32_FLASH_SR_BSY) + ; + + stm32f1_flash_lock(bank, 0); + + setbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_PG); + + /* STM32F1 requires half word writes */ + for (i = 0; i < cnt >> 1; i++) { + *(u16 *)(addr + i * 2) = ((u16 *)src)[i]; + while (readl(&flash_bank[bank]->sr) & STM32_FLASH_SR_BSY) + ; + } + + clrbits_le32(&flash_bank[bank]->cr, STM32_FLASH_CR_PG); + + stm32f1_flash_lock(bank, 1); + + return 0; +} diff --git a/arch/arm/cpu/armv7m/stm32f1/soc.c b/arch/arm/cpu/armv7m/stm32f1/soc.c new file mode 100644 index 0000000..ecb1269 --- /dev/null +++ b/arch/arm/cpu/armv7m/stm32f1/soc.c @@ -0,0 +1,35 @@ +/* + * (C) Copyright 2015 + * Kamil Lulko, rev13@wp.pl + * + * Copyright 2015 Konsulko Group, Matt Porter mporter@konsulko.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/armv7m.h> +#include <asm/arch/stm32.h> + +u32 get_cpu_rev(void) +{ + return 0; +} + +int arch_cpu_init(void) +{ + configure_clocks(); + + /* + * Configure the memory protection unit (MPU) to allow full access to + * the whole 4GB address space. + */ + writel(0, &V7M_MPU->rnr); + writel(0, &V7M_MPU->rbar); + writel((V7M_MPU_RASR_AP_RW_RW | V7M_MPU_RASR_SIZE_4GB + | V7M_MPU_RASR_EN), &V7M_MPU->rasr); + writel(V7M_MPU_CTRL_ENABLE | V7M_MPU_CTRL_HFNMIENA, &V7M_MPU->ctrl); + + return 0; +} diff --git a/arch/arm/cpu/armv7m/stm32f1/timer.c b/arch/arm/cpu/armv7m/stm32f1/timer.c new file mode 100644 index 0000000..67bb87e --- /dev/null +++ b/arch/arm/cpu/armv7m/stm32f1/timer.c @@ -0,0 +1,120 @@ +/* + * (C) Copyright 2015 + * Kamil Lulko, rev13@wp.pl + * + * Copyright 2015 Konsulko Group, Matt Porter mporter@konsulko.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/armv7m.h> +#include <asm/arch/stm32.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define STM32_TIM2_BASE (STM32_APB1PERIPH_BASE + 0x0000) + +#define RCC_APB1ENR_TIM2EN (1 << 0) + +struct stm32_tim2_5 { + u32 cr1; + u32 cr2; + u32 smcr; + u32 dier; + u32 sr; + u32 egr; + u32 ccmr1; + u32 ccmr2; + u32 ccer; + u32 cnt; + u32 psc; + u32 arr; + u32 reserved1; + u32 ccr1; + u32 ccr2; + u32 ccr3; + u32 ccr4; + u32 reserved2; + u32 dcr; + u32 dmar; + u32 or; +}; + +#define TIM_CR1_CEN (1 << 0) + +#define TIM_EGR_UG (1 << 0) + +int timer_init(void) +{ + struct stm32_tim2_5 *tim = (struct stm32_tim2_5 *)STM32_TIM2_BASE; + + setbits_le32(&STM32_RCC->apb1enr, RCC_APB1ENR_TIM2EN); + + if (clock_get(CLOCK_AHB) == clock_get(CLOCK_APB1)) + writel((clock_get(CLOCK_APB1) / CONFIG_SYS_HZ_CLOCK) - 1, + &tim->psc); + else + writel(((clock_get(CLOCK_APB1) * 2) / CONFIG_SYS_HZ_CLOCK) - 1, + &tim->psc); + + writel(0xFFFFFFFF, &tim->arr); + writel(TIM_CR1_CEN, &tim->cr1); + setbits_le32(&tim->egr, TIM_EGR_UG); + + gd->arch.tbl = 0; + gd->arch.tbu = 0; + gd->arch.lastinc = 0; + + return 0; +} + +ulong get_timer(ulong base) +{ + return (get_ticks() / (CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ)) - base; +} + +unsigned long long get_ticks(void) +{ + struct stm32_tim2_5 *tim = (struct stm32_tim2_5 *)STM32_TIM2_BASE; + u32 now; + + now = readl(&tim->cnt); + + if (now >= gd->arch.lastinc) + gd->arch.tbl += (now - gd->arch.lastinc); + else + gd->arch.tbl += (0xFFFFFFFF - gd->arch.lastinc) + now; + + gd->arch.lastinc = now; + + return gd->arch.tbl; +} + +void reset_timer(void) +{ + struct stm32_tim2_5 *tim = (struct stm32_tim2_5 *)STM32_TIM2_BASE; + + gd->arch.lastinc = readl(&tim->cnt); + gd->arch.tbl = 0; +} + +/* delay x useconds */ +void __udelay(ulong usec) +{ + unsigned long long start; + + start = get_ticks(); /* get current timestamp */ + while ((get_ticks() - start) < usec) + ; /* loop till time has passed */ +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return CONFIG_SYS_HZ_CLOCK; +} diff --git a/arch/arm/include/asm/arch-stm32f1/gpio.h b/arch/arm/include/asm/arch-stm32f1/gpio.h new file mode 100644 index 0000000..bd5fbaf --- /dev/null +++ b/arch/arm/include/asm/arch-stm32f1/gpio.h @@ -0,0 +1,117 @@ +/* + * (C) Copyright 2011 + * Yuri Tikhonov, Emcraft Systems, yur@emcraft.com + * + * (C) Copyright 2015 + * Kamil Lulko, rev13@wp.pl + * + * Copyright 2015 Konsulko Group, Matt Porter mporter@konsulko.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _STM32_GPIO_H_ +#define _STM32_GPIO_H_ + +enum stm32_gpio_port { + STM32_GPIO_PORT_A = 0, + STM32_GPIO_PORT_B, + STM32_GPIO_PORT_C, + STM32_GPIO_PORT_D, + STM32_GPIO_PORT_E, + STM32_GPIO_PORT_F, + STM32_GPIO_PORT_G, +}; + +enum stm32_gpio_pin { + STM32_GPIO_PIN_0 = 0, + STM32_GPIO_PIN_1, + STM32_GPIO_PIN_2, + STM32_GPIO_PIN_3, + STM32_GPIO_PIN_4, + STM32_GPIO_PIN_5, + STM32_GPIO_PIN_6, + STM32_GPIO_PIN_7, + STM32_GPIO_PIN_8, + STM32_GPIO_PIN_9, + STM32_GPIO_PIN_10, + STM32_GPIO_PIN_11, + STM32_GPIO_PIN_12, + STM32_GPIO_PIN_13, + STM32_GPIO_PIN_14, + STM32_GPIO_PIN_15 +}; + +enum stm32_gpio_icnf { + STM32_GPIO_ICNF_AN = 0, + STM32_GPIO_ICNF_IN_FLT, + STM32_GPIO_ICNF_IN_PUD, + STM32_GPIO_ICNF_RSVD +}; + +enum stm32_gpio_ocnf { + STM32_GPIO_OCNF_GP_PP = 0, + STM32_GPIO_OCNF_GP_OD, + STM32_GPIO_OCNF_AF_PP, + STM32_GPIO_OCNF_AF_OD +}; + +enum stm32_gpio_pupd { + STM32_GPIO_PUPD_DOWN = 0, + STM32_GPIO_PUPD_UP, +}; + +enum stm32_gpio_mode { + STM32_GPIO_MODE_IN = 0, + STM32_GPIO_MODE_OUT_10M, + STM32_GPIO_MODE_OUT_2M, + STM32_GPIO_MODE_OUT_50M +}; + +enum stm32_gpio_af { + STM32_GPIO_AF0 = 0, + STM32_GPIO_AF1, + STM32_GPIO_AF2, + STM32_GPIO_AF3, + STM32_GPIO_AF4, + STM32_GPIO_AF5, + STM32_GPIO_AF6, + STM32_GPIO_AF7, + STM32_GPIO_AF8, + STM32_GPIO_AF9, + STM32_GPIO_AF10, + STM32_GPIO_AF11, + STM32_GPIO_AF12, + STM32_GPIO_AF13, + STM32_GPIO_AF14, + STM32_GPIO_AF15 +}; + +struct stm32_gpio_dsc { + enum stm32_gpio_port port; + enum stm32_gpio_pin pin; +}; + +struct stm32_gpio_ctl { + enum stm32_gpio_icnf icnf; + enum stm32_gpio_ocnf ocnf; + enum stm32_gpio_mode mode; + enum stm32_gpio_pupd pupd; + enum stm32_gpio_af af; +}; + +static inline unsigned stm32_gpio_to_port(unsigned gpio) +{ + return gpio / 16; +} + +static inline unsigned stm32_gpio_to_pin(unsigned gpio) +{ + return gpio % 16; +} + +int stm32_gpio_config(const struct stm32_gpio_dsc *gpio_dsc, + const struct stm32_gpio_ctl *gpio_ctl); +int stm32_gpout_set(const struct stm32_gpio_dsc *gpio_dsc, int state); + +#endif /* _STM32_GPIO_H_ */ diff --git a/arch/arm/include/asm/arch-stm32f1/stm32.h b/arch/arm/include/asm/arch-stm32f1/stm32.h new file mode 100644 index 0000000..5910d62 --- /dev/null +++ b/arch/arm/include/asm/arch-stm32f1/stm32.h @@ -0,0 +1,115 @@ +/* + * (C) Copyright 2011 + * Yuri Tikhonov, Emcraft Systems, yur@emcraft.com + * + * (C) Copyright 2015 + * Kamil Lulko, rev13@wp.pl + * + * Copyright 2015 Konsulko Group, Matt Porter mporter@konsulko.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _MACH_STM32_H_ +#define _MACH_STM32_H_ + +/* + * Peripheral memory map + */ +#define STM32_PERIPH_BASE 0x40000000 +#define STM32_APB1PERIPH_BASE (STM32_PERIPH_BASE + 0x00000000) +#define STM32_APB2PERIPH_BASE (STM32_PERIPH_BASE + 0x00010000) +#define STM32_AHB1PERIPH_BASE (STM32_PERIPH_BASE + 0x00018000) + +#define STM32_BUS_MASK 0xFFFF0000 + +/* + * Register maps + */ +struct stm32_des_regs { + u16 flash_size; + u16 pad1; + u32 pad2; + u32 uid0; + u32 uid1; + u32 uid2; +}; + +struct stm32_rcc_regs { + u32 cr; /* RCC clock control */ + u32 cfgr; /* RCC clock configuration */ + u32 cir; /* RCC clock interrupt */ + u32 apb2rstr; /* RCC APB2 peripheral reset */ + u32 apb1rstr; /* RCC APB1 peripheral reset */ + u32 ahbenr; /* RCC AHB peripheral clock enable */ + u32 apb2enr; /* RCC APB2 peripheral clock enable */ + u32 apb1enr; /* RCC APB1 peripheral clock enable */ + u32 bdcr; /* RCC Backup domain control */ + u32 csr; /* RCC clock control & status */ +}; + +struct stm32_pwr_regs { + u32 cr; + u32 csr; +}; + +struct stm32_flash_regs { + u32 acr; + u32 keyr; + u32 optkeyr; + u32 sr; + u32 cr; + u32 ar; + u32 rsvd1; /* Reserved */ + u32 obr; + u32 wrpr; + u32 rsvd2[8]; /* Reserved */ + u32 keyr2; + u32 rsvd3; + u32 sr2; + u32 cr2; + u32 ar2; +}; + +/* Per bank register set for XL devices */ +struct stm32_flash_bank_regs { + u32 keyr; + u32 rsvd; /* Reserved */ + u32 sr; + u32 cr; + u32 ar; +}; + +/* + * Registers access macros + */ +#define STM32_DES_BASE (0x1ffff7e0) +#define STM32_DES ((struct stm32_des_regs *)STM32_DES_BASE) + +#define STM32_RCC_BASE (STM32_AHB1PERIPH_BASE + 0x9000) +#define STM32_RCC ((struct stm32_rcc_regs *)STM32_RCC_BASE) + +#define STM32_PWR_BASE (STM32_APB1PERIPH_BASE + 0x7000) +#define STM32_PWR ((struct stm32_pwr_regs *)STM32_PWR_BASE) + +#define STM32_FLASH_BASE (STM32_AHB1PERIPH_BASE + 0xa000) +#define STM32_FLASH ((struct stm32_flash_regs *)STM32_FLASH_BASE) + +#define STM32_FLASH_SR_BSY (1 << 0) + +#define STM32_FLASH_CR_PG (1 << 0) +#define STM32_FLASH_CR_PER (1 << 1) +#define STM32_FLASH_CR_STRT (1 << 6) +#define STM32_FLASH_CR_LOCK (1 << 7) + +enum clock { + CLOCK_CORE, + CLOCK_AHB, + CLOCK_APB1, + CLOCK_APB2 +}; + +int configure_clocks(void); +unsigned long clock_get(enum clock clck); + +#endif /* _MACH_STM32_H_ */ diff --git a/include/flash.h b/include/flash.h index 48aa3a5..5754cf9 100644 --- a/include/flash.h +++ b/include/flash.h @@ -460,6 +460,7 @@ extern flash_info_t *flash_get_info(ulong base); #define FLASH_S29GL128N 0x00F1 /* Spansion S29GL128N */
#define FLASH_STM32F4 0x00F2 /* STM32F4 Embedded Flash */ +#define FLASH_STM32F1 0x00F3 /* STM32F1 Embedded Flash */
#define FLASH_UNKNOWN 0xFFFF /* unknown flash type */

Add support for the STM32F1 family to the STM32 gpio driver.
Signed-off-by: Matt Porter mporter@konsulko.com --- drivers/gpio/stm32_gpio.c | 103 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-)
diff --git a/drivers/gpio/stm32_gpio.c b/drivers/gpio/stm32_gpio.c index d3497e9..9174414 100644 --- a/drivers/gpio/stm32_gpio.c +++ b/drivers/gpio/stm32_gpio.c @@ -5,6 +5,8 @@ * (C) Copyright 2015 * Kamil Lulko, rev13@wp.pl * + * Copyright 2015 Konsulko Group, Matt Porter mporter@konsulko.com + * * SPDX-License-Identifier: GPL-2.0+ */
@@ -16,6 +18,7 @@
DECLARE_GLOBAL_DATA_PTR;
+#ifdef STM32_F4 #define STM32_GPIOA_BASE (STM32_AHB1PERIPH_BASE + 0x0000) #define STM32_GPIOB_BASE (STM32_AHB1PERIPH_BASE + 0x0400) #define STM32_GPIOC_BASE (STM32_AHB1PERIPH_BASE + 0x0800) @@ -90,6 +93,90 @@ int stm32_gpio_config(const struct stm32_gpio_dsc *dsc, out: return rv; } +#else +#define STM32_GPIOA_BASE (STM32_APB2PERIPH_BASE + 0x0800) +#define STM32_GPIOB_BASE (STM32_APB2PERIPH_BASE + 0x0C00) +#define STM32_GPIOC_BASE (STM32_APB2PERIPH_BASE + 0x1000) +#define STM32_GPIOD_BASE (STM32_APB2PERIPH_BASE + 0x1400) +#define STM32_GPIOE_BASE (STM32_APB2PERIPH_BASE + 0x1800) +#define STM32_GPIOF_BASE (STM32_APB2PERIPH_BASE + 0x1C00) +#define STM32_GPIOG_BASE (STM32_APB2PERIPH_BASE + 0x2000) + +static const unsigned long io_base[] = { + STM32_GPIOA_BASE, STM32_GPIOB_BASE, STM32_GPIOC_BASE, + STM32_GPIOD_BASE, STM32_GPIOE_BASE, STM32_GPIOF_BASE, + STM32_GPIOG_BASE +}; + +#define STM32_GPIO_CR_MODE_MASK 0x3 +#define STM32_GPIO_CR_MODE_SHIFT(p) (p * 4) +#define STM32_GPIO_CR_CNF_MASK 0x3 +#define STM32_GPIO_CR_CNF_SHIFT(p) (p * 4 + 2) + +struct stm32_gpio_regs { + u32 crl; /* GPIO port configuration low */ + u32 crh; /* GPIO port configuration high */ + u32 idr; /* GPIO port input data */ + u32 odr; /* GPIO port output data */ + u32 bsrr; /* GPIO port bit set/reset */ + u32 brr; /* GPIO port bit reset */ + u32 lckr; /* GPIO port configuration lock */ +}; + +#define CHECK_DSC(x) (!x || x->port > 6 || x->pin > 15) +#define CHECK_CTL(x) (!x || x->mode > 3 || x->icnf > 3 || x->ocnf > 3 || \ + x->pupd > 1) + +int stm32_gpio_config(const struct stm32_gpio_dsc *dsc, + const struct stm32_gpio_ctl *ctl) +{ + struct stm32_gpio_regs *gpio_regs; + u32 *cr; + int p, crp; + int rv; + + if (CHECK_DSC(dsc)) { + rv = -EINVAL; + goto out; + } + if (CHECK_CTL(ctl)) { + rv = -EINVAL; + goto out; + } + + p = dsc->pin; + + gpio_regs = (struct stm32_gpio_regs *)io_base[dsc->port]; + + /* Enable clock for GPIO port */ + setbits_le32(&STM32_RCC->apb2enr, 0x04 << dsc->port); + + if (p < 8) { + cr = &gpio_regs->crl; + crp = p; + } else { + cr = &gpio_regs->crh; + crp = p - 8; + } + + clrbits_le32(cr, 0x3 << STM32_GPIO_CR_MODE_SHIFT(crp)); + setbits_le32(cr, ctl->mode << STM32_GPIO_CR_MODE_SHIFT(crp)); + + clrbits_le32(cr, 0x3 << STM32_GPIO_CR_CNF_SHIFT(crp)); + /* Inputs set the optional pull up / pull down */ + if (ctl->mode == STM32_GPIO_MODE_IN) { + setbits_le32(cr, ctl->icnf << STM32_GPIO_CR_CNF_SHIFT(crp)); + clrbits_le32(&gpio_regs->odr, 0x1 << p); + setbits_le32(&gpio_regs->odr, ctl->pupd << p); + } else { + setbits_le32(cr, ctl->ocnf << STM32_GPIO_CR_CNF_SHIFT(crp)); + } + + rv = 0; +out: + return rv; +} +#endif
int stm32_gpout_set(const struct stm32_gpio_dsc *dsc, int state) { @@ -148,10 +235,18 @@ int gpio_direction_input(unsigned gpio)
dsc.port = stm32_gpio_to_port(gpio); dsc.pin = stm32_gpio_to_pin(gpio); +#ifdef STM32_F4 ctl.af = STM32_GPIO_AF0; ctl.mode = STM32_GPIO_MODE_IN; + ctl.otype = STM32_GPIO_OTYPE_PP; ctl.pupd = STM32_GPIO_PUPD_NO; ctl.speed = STM32_GPIO_SPEED_50M; +#else + ctl.mode = STM32_GPIO_MODE_IN; + ctl.icnf = STM32_GPIO_ICNF_IN_FLT; + ctl.ocnf = STM32_GPIO_OCNF_GP_PP; /* ignored for input */ + ctl.pupd = STM32_GPIO_PUPD_UP; /* ignored for floating */ +#endif
return stm32_gpio_config(&dsc, &ctl); } @@ -164,11 +259,17 @@ int gpio_direction_output(unsigned gpio, int value)
dsc.port = stm32_gpio_to_port(gpio); dsc.pin = stm32_gpio_to_pin(gpio); +#ifdef STM32_F4 ctl.af = STM32_GPIO_AF0; ctl.mode = STM32_GPIO_MODE_OUT; - ctl.otype = STM32_GPIO_OTYPE_PP; ctl.pupd = STM32_GPIO_PUPD_NO; ctl.speed = STM32_GPIO_SPEED_50M; +#else + ctl.mode = STM32_GPIO_MODE_OUT_50M; + ctl.ocnf = STM32_GPIO_OCNF_GP_PP; + ctl.icnf = STM32_GPIO_ICNF_IN_FLT; /* ignored for output */ + ctl.pupd = STM32_GPIO_PUPD_UP; /* ignored for output */ +#endif
res = stm32_gpio_config(&dsc, &ctl); if (res < 0)

Add support for the STM32F1 famly to the STM32 serial driver.
Signed-off-by: Matt Porter mporter@konsulko.com --- drivers/serial/serial_stm32.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/serial/serial_stm32.c b/drivers/serial/serial_stm32.c index 3c80096..a0397e1 100644 --- a/drivers/serial/serial_stm32.c +++ b/drivers/serial/serial_stm32.c @@ -2,6 +2,8 @@ * (C) Copyright 2015 * Kamil Lulko, rev13@wp.pl * + * Copyright 2015 Konsulko Group, Matt Porter mporter@konsulko.com + * * SPDX-License-Identifier: GPL-2.0+ */
@@ -10,8 +12,13 @@ #include <serial.h> #include <asm/arch/stm32.h>
+#ifdef CONFIG_STM32F4 #define STM32_USART1_BASE (STM32_APB2PERIPH_BASE + 0x1000) #define RCC_APB2ENR_USART1EN (1 << 4) +#else +#define STM32_USART1_BASE (STM32_APB2PERIPH_BASE + 0x3800) +#define RCC_APB2ENR_USART1EN (1 << 14) +#endif
#define USART_BASE STM32_USART1_BASE #define RCC_USART_ENABLE RCC_APB2ENR_USART1EN

Add support for the STM32F1-based stm3210e-eval boards from ST. UART, Flash, GPIO, and LEDs are supported.
Signed-off-by: Matt Porter mporter@konsulko.com --- arch/arm/Kconfig | 5 ++ board/st/stm3210e-eval/Kconfig | 19 ++++++ board/st/stm3210e-eval/MAINTAINERS | 5 ++ board/st/stm3210e-eval/Makefile | 13 ++++ board/st/stm3210e-eval/stm3210e-eval.c | 85 ++++++++++++++++++++++++ configs/stm3210e-eval_defconfig | 3 + include/configs/stm3210e-eval.h | 117 +++++++++++++++++++++++++++++++++ 7 files changed, 247 insertions(+) create mode 100644 board/st/stm3210e-eval/Kconfig create mode 100644 board/st/stm3210e-eval/MAINTAINERS create mode 100644 board/st/stm3210e-eval/Makefile create mode 100644 board/st/stm3210e-eval/stm3210e-eval.c create mode 100644 configs/stm3210e-eval_defconfig create mode 100644 include/configs/stm3210e-eval.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4eb047c..bcf4e46 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -731,6 +731,10 @@ config ARCH_UNIPHIER select SPL select OF_CONTROL
+config TARGET_STM3210E_EVAL + bool "Support STM3210E-EVAL board" + select CPU_V7M + config TARGET_STM32F429_DISCOVERY bool "Support STM32F429 Discovery" select CPU_V7M @@ -872,6 +876,7 @@ source "board/spear/spear600/Kconfig" source "board/spear/x600/Kconfig" source "board/st-ericsson/snowball/Kconfig" source "board/st-ericsson/u8500/Kconfig" +source "board/st/stm3210e-eval/Kconfig" source "board/st/stm32f429-discovery/Kconfig" source "board/st/stv0991/Kconfig" source "board/sunxi/Kconfig" diff --git a/board/st/stm3210e-eval/Kconfig b/board/st/stm3210e-eval/Kconfig new file mode 100644 index 0000000..49bc770 --- /dev/null +++ b/board/st/stm3210e-eval/Kconfig @@ -0,0 +1,19 @@ +if TARGET_STM3210E_EVAL + +config SYS_BOARD + string + default "stm3210e-eval" + +config SYS_VENDOR + string + default "st" + +config SYS_SOC + string + default "stm32f1" + +config SYS_CONFIG_NAME + string + default "stm3210e-eval" + +endif diff --git a/board/st/stm3210e-eval/MAINTAINERS b/board/st/stm3210e-eval/MAINTAINERS new file mode 100644 index 0000000..0f9f31b --- /dev/null +++ b/board/st/stm3210e-eval/MAINTAINERS @@ -0,0 +1,5 @@ +M: Matt Porter mporter@konsulko.com +S: Maintained +F: board/st/stm3210e-eval/ +F: include/configs/stm3210e-eval.h +F: configs/stm3210e-eval_defconfig diff --git a/board/st/stm3210e-eval/Makefile b/board/st/stm3210e-eval/Makefile new file mode 100644 index 0000000..b018e08 --- /dev/null +++ b/board/st/stm3210e-eval/Makefile @@ -0,0 +1,13 @@ +# +# (C) Copyright 2000-2004 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2015 +# Kamil Lulko, rev13@wp.pl +# +# Copyright 2015 Konsulko Group, Matt Porter mporter@konsulko.com +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y := stm3210e-eval.o diff --git a/board/st/stm3210e-eval/stm3210e-eval.c b/board/st/stm3210e-eval/stm3210e-eval.c new file mode 100644 index 0000000..a801983 --- /dev/null +++ b/board/st/stm3210e-eval/stm3210e-eval.c @@ -0,0 +1,85 @@ +/* + * (C) Copyright 2011, 2012, 2013 + * Yuri Tikhonov, Emcraft Systems, yur@emcraft.com + * Alexander Potashev, Emcraft Systems, aspotashev@emcraft.com + * Vladimir Khusainov, Emcraft Systems, vlad@emcraft.com + * Pavel Boldin, Emcraft Systems, paboldin@emcraft.com + * + * (C) Copyright 2015 + * Kamil Lulko, rev13@wp.pl + * + * Copyright 2015 Konsulko Group, Matt Porter mporter@konsulko.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/armv7m.h> +#include <asm/arch/stm32.h> +#include <asm/arch/gpio.h> + +DECLARE_GLOBAL_DATA_PTR; + +const struct stm32_gpio_ctl gpio_ctl_usart[] = { + /* TX */ + { + .mode = STM32_GPIO_MODE_OUT_50M, + .ocnf = STM32_GPIO_OCNF_AF_PP, + }, + /* RX */ + { + .mode = STM32_GPIO_MODE_IN, + .icnf = STM32_GPIO_ICNF_IN_FLT, + } +}; + +static const struct stm32_gpio_dsc usart1_gpio[] = { + {STM32_GPIO_PORT_A, STM32_GPIO_PIN_9}, /* TX */ + {STM32_GPIO_PORT_A, STM32_GPIO_PIN_10}, /* RX */ +}; + +int uart2_setup_gpio(void) +{ + int i; + int rv = 0; + + for (i = 0; i < ARRAY_SIZE(usart1_gpio); i++) { + rv = stm32_gpio_config(&usart1_gpio[i], &gpio_ctl_usart[i]); + if (rv) + goto out; + } + +out: + return rv; +} + +int dram_init(void) +{ + gd->ram_size = CONFIG_SYS_RAM_SIZE; + + return 0; +} + +u32 get_board_rev(void) +{ + return 0; +} + +int board_early_init_f(void) +{ + int res; + + res = uart2_setup_gpio(); + if (res) + return res; + + return 0; +} + +int board_init(void) +{ + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; + + return 0; +} diff --git a/configs/stm3210e-eval_defconfig b/configs/stm3210e-eval_defconfig new file mode 100644 index 0000000..ac3cad3 --- /dev/null +++ b/configs/stm3210e-eval_defconfig @@ -0,0 +1,3 @@ +CONFIG_ARM=y +CONFIG_TARGET_STM3210E_EVAL=y +CONFIG_CMD_BOOTM=n diff --git a/include/configs/stm3210e-eval.h b/include/configs/stm3210e-eval.h new file mode 100644 index 0000000..295c472 --- /dev/null +++ b/include/configs/stm3210e-eval.h @@ -0,0 +1,117 @@ +/* + * (C) Copyright 2015 + * Kamil Lulko, rev13@wp.pl + * + * Copyright 2015 Konsulko Group, Matt Porter mporter@konsulko.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define CONFIG_STM32F1 +#define CONFIG_STM3210E_EVAL +#define CONFIG_SYS_GENERIC_BOARD + +#define CONFIG_BOARD_EARLY_INIT_F + +#define CONFIG_SYS_MAX_FLASH_BANKS 2 +#define CONFIG_SYS_MAX_FLASH_SECT 256 +#define CONFIG_SYS_FLASH_BASE 0x08000000 + +#define CONFIG_SYS_INIT_SP_ADDR 0x20010000 +#define CONFIG_SYS_TEXT_BASE 0x08000000 + +#define CONFIG_SYS_ICACHE_OFF +#define CONFIG_SYS_DCACHE_OFF + +#define CONFIG_SYS_RAM_SIZE 0x00018000 +#define CONFIG_SYS_SDRAM_BASE 0x20000000 +#define CONFIG_SYS_LOAD_ADDR 0x20000000 +#define CONFIG_LOADADDR 0x20000000 + +#define CONFIG_ENV_IS_IN_FLASH +#define CONFIG_ENV_OFFSET (64 << 10) +#define CONFIG_ENV_SECT_SIZE (2 << 10) +#define CONFIG_ENV_SIZE (2 << 10) +#define CONFIG_ENV_MAX_ENTRIES 32 + +#define CONFIG_GPIO_LED +#define CONFIG_STATUS_LED +#define CONFIG_BOARD_SPECIFIC_LED +#define STATUS_LED_BOOT 0 +#define STATUS_LED_BIT 86 /* LD1 - Green */ +#define STATUS_LED_STATE STATUS_LED_OFF +#define STATUS_LED_PERIOD (CONFIG_SYS_HZ / 10) +#define STATUS_LED_BIT1 87 /* LD2 - Orange */ +#define STATUS_LED_STATE1 STATUS_LED_OFF +#define STATUS_LED_PERIOD1 (CONFIG_SYS_HZ / 10) +#define STATUS_LED_BIT2 88 /* LD3 - Red */ +#define STATUS_LED_STATE2 STATUS_LED_OFF +#define STATUS_LED_PERIOD2 (CONFIG_SYS_HZ / 10) +#define STATUS_LED_BIT3 89 /* LD4 - Blue */ +#define STATUS_LED_STATE3 STATUS_LED_OFF +#define STATUS_LED_PERIOD3 (CONFIG_SYS_HZ / 10) + +#define CONFIG_STM32_GPIO +#define CONFIG_STM32_SERIAL +#define CONFIG_STM32_USART1 + +#define CONFIG_STM32_HSE_HZ 8000000 + +#define CONFIG_SYS_HZ_CLOCK 1000000 /* Timer is clocked at 1MHz */ + +#define CONFIG_SYS_CBSIZE 256 +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE \ + + sizeof(CONFIG_SYS_PROMPT) + 16) + +#define CONFIG_SYS_MAXARGS 16 + +#define CONFIG_SYS_MALLOC_LEN (2048) + +#define CONFIG_STACKSIZE (2048) + +#define CONFIG_BAUDRATE 115200 + +#define CONFIG_SYS_BARGSIZE 64 + +#define CONFIG_BOOTDELAY 3 +#define CONFIG_AUTOBOOT + +/* + * Command line configuration. + */ +#define CONFIG_SYS_LONGHELP +#undef CONFIG_CMD_BDI /* bdinfo */ +#undef CONFIG_CMD_BOOTD /* bootd */ +#define CONFIG_CMD_ECHO /* echo arguments */ +#define CONFIG_CMD_LOADB /* loadb */ +#define CONFIG_CMD_MEMORY /* md mm nm mw cp cmp crc base loop */ +#undef CONFIG_CMD_MISC /* Misc functions like sleep etc*/ +#undef CONFIG_CMD_RUN /* run command in env variable */ +#define CONFIG_CMD_SAVEENV /* saveenv */ +#define CONFIG_CRC32 + +#undef CONFIG_SYS_HUSH_PARSER +#define CONFIG_SYS_PROMPT "STM3210E-EVAL> " +#undef CONFIG_AUTO_COMPLETE +#undef CONFIG_CMDLINE_EDITING + +#define CONFIG_CMD_FLASH +#undef CONFIG_CMD_MISC +#undef CONFIG_CMD_TIMER +#define CONFIG_CMD_LED + +#undef CONFIG_BOOTM_LINUX +#undef CONFIG_BOOTM_NETBSD +#undef CONFIG_BOOTM_PLAN9 +#undef CONFIG_BOOTM_RTEMS +#undef CONFIG_BOOTM_VXWORKS + +#undef CONFIG_GZIP +#undef CONFIG_ZLIB +#undef CONFIG_PARTITIONS + + +#endif /* __CONFIG_H */
participants (4)
-
Albert ARIBAUD
-
Kamil Lulko
-
Matt Porter
-
Tom Rini