[U-Boot] [PATCH 0/6] at91: at91sam9g15 improvements

This series add some missing things for an at91sam9g15 board, which gets not mainlined, but there are common fixes, which are posted with this patchserie.
2 important things: - enable icache for AT91 based boards speeds up them a lot, for example reading 8MiB from an SPI NOR flash into RAM takes with icache off ~15 seconds with icache enabled only ~5 seconds.
gurnard board defines a board specific enable_caches() function which enables dcache .. with acomment that this breaks Ethernet MAC ... I removed this board specific function, and dcache enable functions should be added in arch/arm/mach-at91/arm926ejs/cache.c
- SPL clock fix, posted as RFC, as it may breaks other boards. If so, we may make clock settings in SPL board configurable through a weak function?
buildman finds no new errors/warnings with the patches from this patchseries applied.
Heiko Schocher (6): arm: at91: mpddrc: add missing MPDDRC_MD defines ARM: at91: clock: correct PRES offset for at91sam9x5 arm, at91: add icache support arm, at91: add some missing fields in PIO struct at91: add function to set IO drive [RFC] at91: SPL clock fix for AT91SAM9G15 based boards.
arch/arm/mach-at91/arm926ejs/Makefile | 1 + arch/arm/mach-at91/arm926ejs/cache.c | 29 ++++++++++++++++++++++++++ arch/arm/mach-at91/arm926ejs/clock.c | 6 ++++++ arch/arm/mach-at91/include/mach/at91_pio.h | 11 +++++++++- arch/arm/mach-at91/include/mach/atmel_mpddrc.h | 3 +++ arch/arm/mach-at91/include/mach/gpio.h | 2 ++ arch/arm/mach-at91/spl_at91.c | 13 +++++++++--- board/bluewater/gurnard/gurnard.c | 6 ------ drivers/gpio/at91_gpio.c | 29 ++++++++++++++++++++++++++ 9 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 arch/arm/mach-at91/arm926ejs/cache.c

add missing MPDDRC_MD defines
Signed-off-by: Heiko Schocher hs@denx.de ---
arch/arm/mach-at91/include/mach/atmel_mpddrc.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/arm/mach-at91/include/mach/atmel_mpddrc.h b/arch/arm/mach-at91/include/mach/atmel_mpddrc.h index d37d908..f6bcecd 100644 --- a/arch/arm/mach-at91/include/mach/atmel_mpddrc.h +++ b/arch/arm/mach-at91/include/mach/atmel_mpddrc.h @@ -147,6 +147,9 @@ int ddr3_init(const unsigned int base, #define ATMEL_MPDDRC_TPR2_TFAW_MASK 0xf
/* Bit field in Memory Device Register */ +#define ATMEL_MPDDRC_MD_SDR_SDRAM 0x0 +#define ATMEL_MPDDRC_MD_LP_SDR_SDRAM 0x1 +#define ATMEL_MPDDRC_MD_DDR_SDRAM 0x2 #define ATMEL_MPDDRC_MD_LPDDR_SDRAM 0x3 #define ATMEL_MPDDRC_MD_DDR3_SDRAM 0x4 #define ATMEL_MPDDRC_MD_LPDDR3_SDRAM 0x5

-----Original Message----- From: U-Boot [mailto:u-boot-bounces@lists.denx.de] On Behalf Of Heiko Schocher Sent: 2016年8月17日 15:13 To: U-Boot Mailing List u-boot@lists.denx.de Cc: Bo Shen voice.shen@atmel.com Subject: [U-Boot] [PATCH 1/6] arm: at91: mpddrc: add missing MPDDRC_MD defines
add missing MPDDRC_MD defines
Signed-off-by: Heiko Schocher hs@denx.de
Acked-by: Wenyou Yang wenyou.yang@atmel.com
arch/arm/mach-at91/include/mach/atmel_mpddrc.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/arm/mach-at91/include/mach/atmel_mpddrc.h b/arch/arm/mach- at91/include/mach/atmel_mpddrc.h index d37d908..f6bcecd 100644 --- a/arch/arm/mach-at91/include/mach/atmel_mpddrc.h +++ b/arch/arm/mach-at91/include/mach/atmel_mpddrc.h @@ -147,6 +147,9 @@ int ddr3_init(const unsigned int base, #define ATMEL_MPDDRC_TPR2_TFAW_MASK 0xf
/* Bit field in Memory Device Register */ +#define ATMEL_MPDDRC_MD_SDR_SDRAM 0x0 +#define ATMEL_MPDDRC_MD_LP_SDR_SDRAM 0x1 +#define ATMEL_MPDDRC_MD_DDR_SDRAM 0x2 #define ATMEL_MPDDRC_MD_LPDDR_SDRAM 0x3 #define ATMEL_MPDDRC_MD_DDR3_SDRAM 0x4
#define ATMEL_MPDDRC_MD_LPDDR3_SDRAM 0x5
2.5.5
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

On 17.08.16 09:13, Heiko Schocher wrote:
add missing MPDDRC_MD defines
Signed-off-by: Heiko Schocher hs@denx.de
Reviewed-by: Andreas Bießmann andreas@biessmann.org
arch/arm/mach-at91/include/mach/atmel_mpddrc.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/arch/arm/mach-at91/include/mach/atmel_mpddrc.h b/arch/arm/mach-at91/include/mach/atmel_mpddrc.h index d37d908..f6bcecd 100644 --- a/arch/arm/mach-at91/include/mach/atmel_mpddrc.h +++ b/arch/arm/mach-at91/include/mach/atmel_mpddrc.h @@ -147,6 +147,9 @@ int ddr3_init(const unsigned int base, #define ATMEL_MPDDRC_TPR2_TFAW_MASK 0xf
/* Bit field in Memory Device Register */ +#define ATMEL_MPDDRC_MD_SDR_SDRAM 0x0 +#define ATMEL_MPDDRC_MD_LP_SDR_SDRAM 0x1 +#define ATMEL_MPDDRC_MD_DDR_SDRAM 0x2 #define ATMEL_MPDDRC_MD_LPDDR_SDRAM 0x3 #define ATMEL_MPDDRC_MD_DDR3_SDRAM 0x4 #define ATMEL_MPDDRC_MD_LPDDR3_SDRAM 0x5

Dear Heiko Schocher,
Heiko Schocher hs@denx.de writes:
add missing MPDDRC_MD defines
Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Wenyou Yang wenyou.yang@atmel.com Reviewed-by: Andreas Bießmann andreas@biessmann.org
arch/arm/mach-at91/include/mach/atmel_mpddrc.h | 3 +++ 1 file changed, 3 insertions(+)
applied to u-boot-atmel/master, thanks!
Best regards, Andreas Bießmann

on at91sam9x5 PRES offset is 4 in the PMC master clock register.
Signed-off-by: Heiko Schocher hs@denx.de ---
arch/arm/mach-at91/arm926ejs/clock.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/arch/arm/mach-at91/arm926ejs/clock.c b/arch/arm/mach-at91/arm926ejs/clock.c index c8d24ae..e3181fa 100644 --- a/arch/arm/mach-at91/arm926ejs/clock.c +++ b/arch/arm/mach-at91/arm926ejs/clock.c @@ -162,7 +162,13 @@ int at91_clock_init(unsigned long main_clock) gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK); freq = gd->arch.mck_rate_hz;
+#if defined(CONFIG_AT91SAM9X5) + /* different in prescale on at91sam9x5 */ + freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 4)); +#else freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */ +#endif + #if defined(CONFIG_AT91SAM9G20) /* mdiv ; (x >> 7) = ((x >> 8) * 2) */ gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ?

-----Original Message----- From: U-Boot [mailto:u-boot-bounces@lists.denx.de] On Behalf Of Heiko Schocher Sent: 2016年8月17日 15:13 To: U-Boot Mailing List u-boot@lists.denx.de Cc: Bo Shen voice.shen@atmel.com Subject: [U-Boot] [PATCH 2/6] ARM: at91: clock: correct PRES offset for at91sam9x5
on at91sam9x5 PRES offset is 4 in the PMC master clock register.
Signed-off-by: Heiko Schocher hs@denx.de
Acked-by: Wenyou Yang wenyou.yang@atmel.com
arch/arm/mach-at91/arm926ejs/clock.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/arch/arm/mach-at91/arm926ejs/clock.c b/arch/arm/mach- at91/arm926ejs/clock.c index c8d24ae..e3181fa 100644 --- a/arch/arm/mach-at91/arm926ejs/clock.c +++ b/arch/arm/mach-at91/arm926ejs/clock.c @@ -162,7 +162,13 @@ int at91_clock_init(unsigned long main_clock) gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK); freq = gd->arch.mck_rate_hz;
+#if defined(CONFIG_AT91SAM9X5)
- /* different in prescale on at91sam9x5 */
- freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 4)); #else freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /*
prescale */ +#endif
#if defined(CONFIG_AT91SAM9G20) /* mdiv ; (x >> 7) = ((x >> 8) * 2) */ gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ? -- 2.5.5
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

On 17.08.16 09:13, Heiko Schocher wrote:
on at91sam9x5 PRES offset is 4 in the PMC master clock register.
Signed-off-by: Heiko Schocher hs@denx.de
arch/arm/mach-at91/arm926ejs/clock.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/arch/arm/mach-at91/arm926ejs/clock.c b/arch/arm/mach-at91/arm926ejs/clock.c index c8d24ae..e3181fa 100644 --- a/arch/arm/mach-at91/arm926ejs/clock.c +++ b/arch/arm/mach-at91/arm926ejs/clock.c @@ -162,7 +162,13 @@ int at91_clock_init(unsigned long main_clock) gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK); freq = gd->arch.mck_rate_hz;
+#if defined(CONFIG_AT91SAM9X5)
- /* different in prescale on at91sam9x5 */
- freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 4));
This one is really ugly ... I can live with the ifdef here but have you realized the 0x7 for PRES?
Andreas
+#else freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */ +#endif
#if defined(CONFIG_AT91SAM9G20) /* mdiv ; (x >> 7) = ((x >> 8) * 2) */ gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ?

On Wed, Aug 17, 2016 at 09:13:24AM +0200, Heiko Schocher wrote:
on at91sam9x5 PRES offset is 4 in the PMC master clock register.
Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Wenyou Yang wenyou.yang@atmel.com
Acked-by: Andreas Bießmann andreas@biessmann.org
arch/arm/mach-at91/arm926ejs/clock.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/arch/arm/mach-at91/arm926ejs/clock.c b/arch/arm/mach-at91/arm926ejs/clock.c index c8d24ae..e3181fa 100644 --- a/arch/arm/mach-at91/arm926ejs/clock.c +++ b/arch/arm/mach-at91/arm926ejs/clock.c @@ -162,7 +162,13 @@ int at91_clock_init(unsigned long main_clock) gd->arch.mck_rate_hz = at91_css_to_rate(mckr & AT91_PMC_MCKR_CSS_MASK); freq = gd->arch.mck_rate_hz;
+#if defined(CONFIG_AT91SAM9X5)
- /* different in prescale on at91sam9x5 */
- freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 4));
+#else freq /= (1 << ((mckr & AT91_PMC_MCKR_PRES_MASK) >> 2)); /* prescale */ +#endif
#if defined(CONFIG_AT91SAM9G20) /* mdiv ; (x >> 7) = ((x >> 8) * 2) */ gd->arch.mck_rate_hz = (mckr & AT91_PMC_MCKR_MDIV_MASK) ?

Dear Heiko Schocher,
Heiko Schocher hs@denx.de writes:
on at91sam9x5 PRES offset is 4 in the PMC master clock register.
Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Wenyou Yang wenyou.yang@atmel.com Acked-by: Andreas Bießmann andreas@biessmann.org
arch/arm/mach-at91/arm926ejs/clock.c | 6 ++++++ 1 file changed, 6 insertions(+)
applied to u-boot-atmel/master, thanks!
Best regards, Andreas Bießmann

add at least icache support for at91 based boards. This speeds up NOR flash access on an at91sam9g15 based board from 15.2 seconds reading 8 MiB from a SPI NOR flash to 5.7 seconds.
Signed-off-by: Heiko Schocher hs@denx.de
--- removed the dcache enable in the gurnard board. Comment says that enabling dcache breaks Ethernet MAC ... why is it then enabled?
@Simon: If you need dache enabled for the gurnard board, arch/arm/mach-at91/arm926ejs/cache.c is the correct place for doing this, I think. Please add there the common functions needed for dcache support on at91 plattforms and undef in the gurnard board configuration CONFIG_SYS_DCACHE_OFF.
arch/arm/mach-at91/arm926ejs/Makefile | 1 + arch/arm/mach-at91/arm926ejs/cache.c | 29 +++++++++++++++++++++++++++++ board/bluewater/gurnard/gurnard.c | 6 ------ 3 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 arch/arm/mach-at91/arm926ejs/cache.c
diff --git a/arch/arm/mach-at91/arm926ejs/Makefile b/arch/arm/mach-at91/arm926ejs/Makefile index ddc323f..d36e15a 100644 --- a/arch/arm/mach-at91/arm926ejs/Makefile +++ b/arch/arm/mach-at91/arm926ejs/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_AT91SAM9N12) += at91sam9n12_devices.o obj-$(CONFIG_AT91SAM9X5) += at91sam9x5_devices.o obj-$(CONFIG_AT91_EFLASH) += eflash.o obj-$(CONFIG_AT91_LED) += led.o +obj-y += cache.o obj-y += clock.o obj-y += cpu.o obj-y += reset.o diff --git a/arch/arm/mach-at91/arm926ejs/cache.c b/arch/arm/mach-at91/arm926ejs/cache.c new file mode 100644 index 0000000..8813706 --- /dev/null +++ b/arch/arm/mach-at91/arm926ejs/cache.c @@ -0,0 +1,29 @@ +/* + * (C) Copyright 2016 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include <linux/types.h> +#include <common.h> + +void enable_caches(void) +{ +#ifndef CONFIG_SYS_ICACHE_OFF + icache_enable(); +#endif +} + +#ifndef CONFIG_SYS_ICACHE_OFF +/* Invalidate entire I-cache and branch predictor array */ +void invalidate_icache_all(void) +{ + unsigned long i = 0; + + asm ("mcr p15, 0, %0, c7, c5, 0" : : "r" (i)); +} +#else +void invalidate_icache_all(void) +{ +} +#endif diff --git a/board/bluewater/gurnard/gurnard.c b/board/bluewater/gurnard/gurnard.c index 2a36d29..08b1401 100644 --- a/board/bluewater/gurnard/gurnard.c +++ b/board/bluewater/gurnard/gurnard.c @@ -414,12 +414,6 @@ void reset_phy(void) { }
-/* This breaks the Ethernet MAC at present */ -void enable_caches(void) -{ - dcache_enable(); -} - /* SPI chip select control - only used for FPGA programming */ #ifdef CONFIG_ATMEL_SPI

On 17 August 2016 at 01:13, Heiko Schocher hs@denx.de wrote:
add at least icache support for at91 based boards. This speeds up NOR flash access on an at91sam9g15 based board from 15.2 seconds reading 8 MiB from a SPI NOR flash to 5.7 seconds.
Signed-off-by: Heiko Schocher hs@denx.de
removed the dcache enable in the gurnard board. Comment says that enabling dcache breaks Ethernet MAC ... why is it then enabled?
@Simon: If you need dache enabled for the gurnard board, arch/arm/mach-at91/arm926ejs/cache.c is the correct place for doing this, I think. Please add there the common functions needed for dcache support on at91 plattforms and undef in the gurnard board configuration CONFIG_SYS_DCACHE_OFF.
arch/arm/mach-at91/arm926ejs/Makefile | 1 + arch/arm/mach-at91/arm926ejs/cache.c | 29 +++++++++++++++++++++++++++++ board/bluewater/gurnard/gurnard.c | 6 ------ 3 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 arch/arm/mach-at91/arm926ejs/cache.c
Reviewed-by: Simon Glass sjg@chromium.org

On 17.08.16 09:13, Heiko Schocher wrote:
add at least icache support for at91 based boards. This speeds up NOR flash access on an at91sam9g15 based board from 15.2 seconds reading 8 MiB from a SPI NOR flash to 5.7 seconds.
Signed-off-by: Heiko Schocher hs@denx.de
Reviewed-by: Andreas Bießmann andreas@biessmann.org

Dear Heiko Schocher,
Heiko Schocher hs@denx.de writes:
add at least icache support for at91 based boards. This speeds up NOR flash access on an at91sam9g15 based board from 15.2 seconds reading 8 MiB from a SPI NOR flash to 5.7 seconds.
Signed-off-by: Heiko Schocher hs@denx.de Reviewed-by: Simon Glass sjg@chromium.org Reviewed-by: Andreas Bießmann andreas@biessmann.org
removed the dcache enable in the gurnard board. Comment says that enabling dcache breaks Ethernet MAC ... why is it then enabled?
@Simon: If you need dache enabled for the gurnard board, arch/arm/mach-at91/arm926ejs/cache.c is the correct place for doing this, I think. Please add there the common functions needed for dcache support on at91 plattforms and undef in the gurnard board configuration CONFIG_SYS_DCACHE_OFF.
arch/arm/mach-at91/arm926ejs/Makefile | 1 + arch/arm/mach-at91/arm926ejs/cache.c | 29 +++++++++++++++++++++++++++++ board/bluewater/gurnard/gurnard.c | 6 ------ 3 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 arch/arm/mach-at91/arm926ejs/cache.c
applied to u-boot-atmel/master, thanks!
Best regards, Andreas Bießmann

add missing
u32 io_delay; /* 0x110 I/O delay register */ u32 io_driver1; /* 0x114 I/O driver register 1 */ u32 io_driver2; /* 0x118 I/O driver register 2 */
fields in struct at91_port.
Signed-off-by: Heiko Schocher hs@denx.de ---
arch/arm/mach-at91/include/mach/at91_pio.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach-at91/include/mach/at91_pio.h index 3012278..8e054e1 100644 --- a/arch/arm/mach-at91/include/mach/at91_pio.h +++ b/arch/arm/mach-at91/include/mach/at91_pio.h @@ -103,7 +103,11 @@ typedef struct at91_port { u32 wpsr; /* 0xE8 Write Protect Status Register */ u32 reserved11[5]; /* */ u32 schmitt; /* 0x100 Schmitt Trigger Register */ - u32 reserved12[63]; + u32 reserved12[3]; + u32 io_delay; /* 0x110 I/O delay register */ + u32 io_driver1; /* 0x114 I/O driver register 1 */ + u32 io_driver2; /* 0x118 I/O driver register 2 */ + u32 reserved13[57]; #else u32 reserved6[85]; #endif

-----Original Message----- From: U-Boot [mailto:u-boot-bounces@lists.denx.de] On Behalf Of Heiko Schocher Sent: 2016年8月17日 15:13 To: U-Boot Mailing List u-boot@lists.denx.de Cc: Bo Shen voice.shen@atmel.com Subject: [U-Boot] [PATCH 4/6] arm, at91: add some missing fields in PIO struct
add missing
u32 io_delay; /* 0x110 I/O delay register */ u32 io_driver1; /* 0x114 I/O driver register 1 */ u32 io_driver2; /* 0x118 I/O driver register 2 */
fields in struct at91_port.
Signed-off-by: Heiko Schocher hs@denx.de
Acked-by: Wenyou Yang wenyou.yang@atmel.com
arch/arm/mach-at91/include/mach/at91_pio.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach- at91/include/mach/at91_pio.h index 3012278..8e054e1 100644 --- a/arch/arm/mach-at91/include/mach/at91_pio.h +++ b/arch/arm/mach-at91/include/mach/at91_pio.h @@ -103,7 +103,11 @@ typedef struct at91_port { u32 wpsr; /* 0xE8 Write Protect Status Register */ u32 reserved11[5]; /* */ u32 schmitt; /* 0x100 Schmitt Trigger Register */
- u32 reserved12[63];
- u32 reserved12[3];
- u32 io_delay; /* 0x110 I/O delay register */
- u32 io_driver1; /* 0x114 I/O driver register 1 */
- u32 io_driver2; /* 0x118 I/O driver register 2 */
- u32 reserved13[57];
#else u32 reserved6[85];
#endif
2.5.5
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

On 17.08.16 09:13, Heiko Schocher wrote:
add missing
u32 io_delay; /* 0x110 I/O delay register */ u32 io_driver1; /* 0x114 I/O driver register 1 */ u32 io_driver2; /* 0x118 I/O driver register 2 */
This is also a mess ... it is true for sam9x5, but sama5d4 has 0x110 reserved, 0x114 reserved and 0x118 I/O driver register 1, same for sama5d3 and persumably others ...
Why is is needed here? Couldn't we switch to device tree on the long run?
Andreas
fields in struct at91_port.
Signed-off-by: Heiko Schocher hs@denx.de
arch/arm/mach-at91/include/mach/at91_pio.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach-at91/include/mach/at91_pio.h index 3012278..8e054e1 100644 --- a/arch/arm/mach-at91/include/mach/at91_pio.h +++ b/arch/arm/mach-at91/include/mach/at91_pio.h @@ -103,7 +103,11 @@ typedef struct at91_port { u32 wpsr; /* 0xE8 Write Protect Status Register */ u32 reserved11[5]; /* */ u32 schmitt; /* 0x100 Schmitt Trigger Register */
- u32 reserved12[63];
- u32 reserved12[3];
- u32 io_delay; /* 0x110 I/O delay register */
- u32 io_driver1; /* 0x114 I/O driver register 1 */
- u32 io_driver2; /* 0x118 I/O driver register 2 */
- u32 reserved13[57];
#else u32 reserved6[85]; #endif

add new function to set I/O drive.
Signed-off-by: Heiko Schocher hs@denx.de ---
arch/arm/mach-at91/include/mach/at91_pio.h | 5 +++++ arch/arm/mach-at91/include/mach/gpio.h | 2 ++ drivers/gpio/at91_gpio.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+)
diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach-at91/include/mach/at91_pio.h index 8e054e1..535208a 100644 --- a/arch/arm/mach-at91/include/mach/at91_pio.h +++ b/arch/arm/mach-at91/include/mach/at91_pio.h @@ -134,6 +134,7 @@ int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div); int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on); int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin); #endif +int at91_set_pio_io_drive(unsigned port, unsigned pin, int value); int at91_set_pio_input(unsigned port, unsigned pin, int use_pullup); int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on); int at91_set_pio_output(unsigned port, unsigned pin, int value); @@ -151,4 +152,8 @@ int at91_get_pio_value(unsigned port, unsigned pin); #define AT91_PIO_PORTD 0x3 #define AT91_PIO_PORTE 0x4
+/* allowed I/O driver values */ +#define AT91_PIO_HI_DRIVE 0 +#define AT91_PIO_MEDIUM_DRIVE 1 +#define AT91_PIO_LOW_DRIVE 2 #endif diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h index 6d2a7b7..2b89309 100644 --- a/arch/arm/mach-at91/include/mach/gpio.h +++ b/arch/arm/mach-at91/include/mach/gpio.h @@ -227,6 +227,8 @@ static inline unsigned pin_to_mask(unsigned pin) at91_set_pio_value((x - PIN_BASE) / 32,(x % 32), y) #define at91_get_gpio_value(x) \ at91_get_pio_value((x - PIN_BASE) / 32,(x % 32)) +#define at91_set_gpio_io_drive(x, v) \ + at91_set_pio_io_drive((x - PIN_BASE) / 32,(x % 32), v) #else #define at91_set_gpio_value(x, y) at91_set_pio_value(x, y) #define at91_get_gpio_value(x) at91_get_pio_value(x) diff --git a/drivers/gpio/at91_gpio.c b/drivers/gpio/at91_gpio.c index 8e52e3d..1f624f8 100644 --- a/drivers/gpio/at91_gpio.c +++ b/drivers/gpio/at91_gpio.c @@ -358,6 +358,35 @@ int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on) return 0; }
+#if defined(CPU_HAS_PIO3) +/* + * set I/O driver value + */ +int at91_set_pio_io_drive(unsigned port, unsigned pin, int value) +{ + struct at91_port *at91_port = at91_pio_get_port(port); + u32 *reg; + u32 mask; + + if (pin > 15) { + reg = &at91_port->io_driver2; + pin -= 16; + } else { + reg = &at91_port->io_driver1; + } + + mask = 0x3 << (pin * 2); + clrsetbits_le32(reg, mask, value << (pin * 2)); + return 0; +} +#else +int at91_set_pio_io_drive(unsigned port, unsigned pin, int value) +{ + return -ENOENT; +} +#endif + + static void at91_set_port_value(struct at91_port *at91_port, int offset, int value) {

-----Original Message----- From: U-Boot [mailto:u-boot-bounces@lists.denx.de] On Behalf Of Heiko Schocher Sent: 2016年8月17日 15:13 To: U-Boot Mailing List u-boot@lists.denx.de Cc: Bo Shen voice.shen@atmel.com Subject: [U-Boot] [PATCH 5/6] at91: add function to set IO drive
add new function to set I/O drive.
Signed-off-by: Heiko Schocher hs@denx.de
Acked-by: Wenyou Yang wenyou.yang@atmel.com
arch/arm/mach-at91/include/mach/at91_pio.h | 5 +++++ arch/arm/mach-at91/include/mach/gpio.h | 2 ++ drivers/gpio/at91_gpio.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+)
diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach- at91/include/mach/at91_pio.h index 8e054e1..535208a 100644 --- a/arch/arm/mach-at91/include/mach/at91_pio.h +++ b/arch/arm/mach-at91/include/mach/at91_pio.h @@ -134,6 +134,7 @@ int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div); int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on); int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin); #endif +int at91_set_pio_io_drive(unsigned port, unsigned pin, int value); int at91_set_pio_input(unsigned port, unsigned pin, int use_pullup); int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on); int at91_set_pio_output(unsigned port, unsigned pin, int value); @@ -151,4 +152,8 @@ int at91_get_pio_value(unsigned port, unsigned pin); #define AT91_PIO_PORTD 0x3 #define AT91_PIO_PORTE 0x4
+/* allowed I/O driver values */ +#define AT91_PIO_HI_DRIVE 0 +#define AT91_PIO_MEDIUM_DRIVE 1 +#define AT91_PIO_LOW_DRIVE 2 #endif diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach- at91/include/mach/gpio.h index 6d2a7b7..2b89309 100644 --- a/arch/arm/mach-at91/include/mach/gpio.h +++ b/arch/arm/mach-at91/include/mach/gpio.h @@ -227,6 +227,8 @@ static inline unsigned pin_to_mask(unsigned pin) at91_set_pio_value((x - PIN_BASE) / 32,(x % 32), y) #define at91_get_gpio_value(x) \ at91_get_pio_value((x - PIN_BASE) / 32,(x % 32)) +#define at91_set_gpio_io_drive(x, v) \
- at91_set_pio_io_drive((x - PIN_BASE) / 32,(x % 32), v)
#else #define at91_set_gpio_value(x, y) at91_set_pio_value(x, y) #define at91_get_gpio_value(x) at91_get_pio_value(x) diff --git a/drivers/gpio/at91_gpio.c b/drivers/gpio/at91_gpio.c index 8e52e3d..1f624f8 100644 --- a/drivers/gpio/at91_gpio.c +++ b/drivers/gpio/at91_gpio.c @@ -358,6 +358,35 @@ int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on) return 0; }
+#if defined(CPU_HAS_PIO3) +/*
- set I/O driver value
- */
+int at91_set_pio_io_drive(unsigned port, unsigned pin, int value) {
- struct at91_port *at91_port = at91_pio_get_port(port);
- u32 *reg;
- u32 mask;
- if (pin > 15) {
reg = &at91_port->io_driver2;
pin -= 16;
- } else {
reg = &at91_port->io_driver1;
- }
- mask = 0x3 << (pin * 2);
- clrsetbits_le32(reg, mask, value << (pin * 2));
- return 0;
+} +#else +int at91_set_pio_io_drive(unsigned port, unsigned pin, int value) {
- return -ENOENT;
+} +#endif
static void at91_set_port_value(struct at91_port *at91_port, int offset, int value) { -- 2.5.5
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

On 17.08.16 09:13, Heiko Schocher wrote:
add new function to set I/O drive.
Signed-off-by: Heiko Schocher hs@denx.de
arch/arm/mach-at91/include/mach/at91_pio.h | 5 +++++ arch/arm/mach-at91/include/mach/gpio.h | 2 ++ drivers/gpio/at91_gpio.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+)
diff --git a/arch/arm/mach-at91/include/mach/at91_pio.h b/arch/arm/mach-at91/include/mach/at91_pio.h index 8e054e1..535208a 100644 --- a/arch/arm/mach-at91/include/mach/at91_pio.h +++ b/arch/arm/mach-at91/include/mach/at91_pio.h @@ -134,6 +134,7 @@ int at91_set_pio_debounce(unsigned port, unsigned pin, int is_on, int div); int at91_set_pio_pulldown(unsigned port, unsigned pin, int is_on); int at91_set_pio_disable_schmitt_trig(unsigned port, unsigned pin); #endif +int at91_set_pio_io_drive(unsigned port, unsigned pin, int value); int at91_set_pio_input(unsigned port, unsigned pin, int use_pullup); int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on); int at91_set_pio_output(unsigned port, unsigned pin, int value); @@ -151,4 +152,8 @@ int at91_get_pio_value(unsigned port, unsigned pin); #define AT91_PIO_PORTD 0x3 #define AT91_PIO_PORTE 0x4
+/* allowed I/O driver values */ +#define AT91_PIO_HI_DRIVE 0
sama5 has 0 + 1 low drive, 2 medium and 3 hi :(
+#define AT91_PIO_MEDIUM_DRIVE 1 +#define AT91_PIO_LOW_DRIVE 2 #endif diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h index 6d2a7b7..2b89309 100644 --- a/arch/arm/mach-at91/include/mach/gpio.h +++ b/arch/arm/mach-at91/include/mach/gpio.h @@ -227,6 +227,8 @@ static inline unsigned pin_to_mask(unsigned pin) at91_set_pio_value((x - PIN_BASE) / 32,(x % 32), y) #define at91_get_gpio_value(x) \ at91_get_pio_value((x - PIN_BASE) / 32,(x % 32)) +#define at91_set_gpio_io_drive(x, v) \
- at91_set_pio_io_drive((x - PIN_BASE) / 32,(x % 32), v)
#else #define at91_set_gpio_value(x, y) at91_set_pio_value(x, y) #define at91_get_gpio_value(x) at91_get_pio_value(x) diff --git a/drivers/gpio/at91_gpio.c b/drivers/gpio/at91_gpio.c index 8e52e3d..1f624f8 100644 --- a/drivers/gpio/at91_gpio.c +++ b/drivers/gpio/at91_gpio.c @@ -358,6 +358,35 @@ int at91_set_pio_multi_drive(unsigned port, unsigned pin, int is_on) return 0; }
+#if defined(CPU_HAS_PIO3) +/*
- set I/O driver value
- */
+int at91_set_pio_io_drive(unsigned port, unsigned pin, int value) +{
- struct at91_port *at91_port = at91_pio_get_port(port);
- u32 *reg;
- u32 mask;
- if (pin > 15) {
reg = &at91_port->io_driver2;
pin -= 16;
- } else {
reg = &at91_port->io_driver1;
- }
- mask = 0x3 << (pin * 2);
- clrsetbits_le32(reg, mask, value << (pin * 2));
- return 0;
+} +#else +int at91_set_pio_io_drive(unsigned port, unsigned pin, int value) +{
- return -ENOENT;
+} +#endif
static void at91_set_port_value(struct at91_port *at91_port, int offset, int value) {

on a at91sam9g15 basd board I need another MOR register init as common for at91 based boards. Changes:
- set AT91_PMC_MOR_KEY to 0x37, without this writting has no effect to tthis register. - AT91_PMC_MOR_OSCOUNT to 0 - set AT91_PMC_MOR_MOSCEN and AT91_PMC_MOR_MOSCSEL
Signed-off-by: Heiko Schocher hs@denx.de
--- I post this as a RFC patch, because this settings may break other boards ... so if this is not a valid common setting, I propose to make this setting board configurable through a weak function ...
arch/arm/mach-at91/spl_at91.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-at91/spl_at91.c b/arch/arm/mach-at91/spl_at91.c index cc3341a..4d8ed26 100644 --- a/arch/arm/mach-at91/spl_at91.c +++ b/arch/arm/mach-at91/spl_at91.c @@ -31,13 +31,20 @@ static void enable_ext_reset(void) void lowlevel_clock_init(void) { struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC; + u32 tmp;
if (!(readl(&pmc->sr) & AT91_PMC_MOSCS)) { - /* Enable Main Oscillator */ - writel(AT91_PMC_MOSCS | (0x40 << 8), &pmc->mor); + tmp = readl(&pmc->mor); + tmp &= ~AT91_PMC_MOR_OSCOUNT(0xff); + tmp &= ~AT91_PMC_MOR_KEY(0xff); + tmp |= AT91_PMC_MOR_MOSCEN; + tmp |= AT91_PMC_MOR_MOSCSEL; + tmp |= AT91_PMC_MOR_OSCOUNT(0); + tmp |= AT91_PMC_MOR_KEY(0x37); + writel(tmp, &pmc->mor);
/* Wait until Main Oscillator is stable */ - while (!(readl(&pmc->sr) & AT91_PMC_MOSCS)) + while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCS)) ; }

Hi Heiko,
-----Original Message----- From: U-Boot [mailto:u-boot-bounces@lists.denx.de] On Behalf Of Heiko Schocher Sent: 2016年8月17日 15:13 To: U-Boot Mailing List u-boot@lists.denx.de Cc: Bo Shen voice.shen@atmel.com Subject: [U-Boot] [PATCH 6/6] [RFC] at91: SPL clock fix for AT91SAM9G15 based boards.
on a at91sam9g15 basd board I need another MOR register init as common for at91 based boards. Changes: MM
- set AT91_PMC_MOR_KEY to 0x37, without this writting has no effect to tthis register.
- AT91_PMC_MOR_OSCOUNT to 0
- set AT91_PMC_MOR_MOSCEN and AT91_PMC_MOR_MOSCSEL
Signed-off-by: Heiko Schocher hs@denx.de
I post this as a RFC patch, because this settings may break other boards ... so if this is not a valid common setting, I propose to make this setting board configurable through a weak function ...
arch/arm/mach-at91/spl_at91.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-at91/spl_at91.c b/arch/arm/mach-at91/spl_at91.c index cc3341a..4d8ed26 100644 --- a/arch/arm/mach-at91/spl_at91.c +++ b/arch/arm/mach-at91/spl_at91.c @@ -31,13 +31,20 @@ static void enable_ext_reset(void) void lowlevel_clock_init(void) { struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
u32 tmp;
if (!(readl(&pmc->sr) & AT91_PMC_MOSCS)) {
/* Enable Main Oscillator */
writel(AT91_PMC_MOSCS | (0x40 << 8), &pmc->mor);
tmp = readl(&pmc->mor);
tmp &= ~AT91_PMC_MOR_OSCOUNT(0xff);
tmp &= ~AT91_PMC_MOR_KEY(0xff);
tmp |= AT91_PMC_MOR_MOSCEN;
tmp |= AT91_PMC_MOR_MOSCSEL;
tmp |= AT91_PMC_MOR_OSCOUNT(0);
tmp |= AT91_PMC_MOR_KEY(0x37);
writel(tmp, &pmc->mor);
I think, it needs two steps to configure the CKGR_MOR register. 1./ set AT91_PMC_MOR_MOSCEN, then wait to check the MOSCXTS bit of the PMC Status Register. 2./ set AT91_PMC_MOR_MOSCSEL, then wait for check the MOSCSLES bit of the PMC Status Register.
AT91_PMC_MOR_OSCOUNT should not be set 0.
/* Wait until Main Oscillator is stable */
while (!(readl(&pmc->sr) & AT91_PMC_MOSCS))
}while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCS)) ;
-- 2.5.5
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Best Regards, Wenyou Yang

Hi Heiko,
On 17.08.16 09:13, Heiko Schocher wrote:
on a at91sam9g15 basd board I need another MOR register init as common for at91 based boards. Changes:
- set AT91_PMC_MOR_KEY to 0x37, without this writting has no effect to tthis register.
- AT91_PMC_MOR_OSCOUNT to 0
- set AT91_PMC_MOR_MOSCEN and AT91_PMC_MOR_MOSCSEL
Signed-off-by: Heiko Schocher hs@denx.de
I post this as a RFC patch, because this settings may break other boards ... so if this is not a valid common setting, I propose to make this setting board configurable through a weak function ...
arch/arm/mach-at91/spl_at91.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-at91/spl_at91.c b/arch/arm/mach-at91/spl_at91.c index cc3341a..4d8ed26 100644 --- a/arch/arm/mach-at91/spl_at91.c +++ b/arch/arm/mach-at91/spl_at91.c @@ -31,13 +31,20 @@ static void enable_ext_reset(void) void lowlevel_clock_init(void) { struct at91_pmc *pmc = (struct at91_pmc *)ATMEL_BASE_PMC;
u32 tmp;
if (!(readl(&pmc->sr) & AT91_PMC_MOSCS)) {
/* Enable Main Oscillator */
writel(AT91_PMC_MOSCS | (0x40 << 8), &pmc->mor);
tmp = readl(&pmc->mor);
tmp &= ~AT91_PMC_MOR_OSCOUNT(0xff);
tmp &= ~AT91_PMC_MOR_KEY(0xff);
tmp |= AT91_PMC_MOR_MOSCEN;
tmp |= AT91_PMC_MOR_MOSCSEL;
tmp |= AT91_PMC_MOR_OSCOUNT(0);
this is weird configuration to me. Why do you set the counter to 0? Is the Oscillator really immediately stable? Or is it an external Oscillator which should be bypassed?
Nevertheless, you should do a two step procedure here according to PMC Programming Sequence. First switching the Oscillator on and second activate the master clock from it. Each of the steps may poll the status register for appropriate flags (or use interrupts).
Any chance to merge this lowlevel clock init with spl_atmel? At least this part for enabling main oscillator.
Andreas
tmp |= AT91_PMC_MOR_KEY(0x37);
writel(tmp, &pmc->mor);
/* Wait until Main Oscillator is stable */
while (!(readl(&pmc->sr) & AT91_PMC_MOSCS))
}while (!(readl(&pmc->sr) & AT91_PMC_IXR_MOSCS)) ;

Hello Andreas,
Am 17.08.2016 um 09:13 schrieb Heiko Schocher:
This series add some missing things for an at91sam9g15 board, which gets not mainlined, but there are common fixes, which are posted with this patchserie.
2 important things:
enable icache for AT91 based boards speeds up them a lot, for example reading 8MiB from an SPI NOR flash into RAM takes with icache off ~15 seconds with icache enabled only ~5 seconds.
gurnard board defines a board specific enable_caches() function which enables dcache .. with acomment that this breaks Ethernet MAC ... I removed this board specific function, and dcache enable functions should be added in arch/arm/mach-at91/arm926ejs/cache.c
SPL clock fix, posted as RFC, as it may breaks other boards. If so, we may make clock settings in SPL board configurable through a weak function?
buildman finds no new errors/warnings with the patches from this patchseries applied.
Heiko Schocher (6): arm: at91: mpddrc: add missing MPDDRC_MD defines ARM: at91: clock: correct PRES offset for at91sam9x5 arm, at91: add icache support arm, at91: add some missing fields in PIO struct at91: add function to set IO drive [RFC] at91: SPL clock fix for AT91SAM9G15 based boards.
arch/arm/mach-at91/arm926ejs/Makefile | 1 + arch/arm/mach-at91/arm926ejs/cache.c | 29 ++++++++++++++++++++++++++ arch/arm/mach-at91/arm926ejs/clock.c | 6 ++++++ arch/arm/mach-at91/include/mach/at91_pio.h | 11 +++++++++- arch/arm/mach-at91/include/mach/atmel_mpddrc.h | 3 +++ arch/arm/mach-at91/include/mach/gpio.h | 2 ++ arch/arm/mach-at91/spl_at91.c | 13 +++++++++--- board/bluewater/gurnard/gurnard.c | 6 ------ drivers/gpio/at91_gpio.c | 29 ++++++++++++++++++++++++++ 9 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 arch/arm/mach-at91/arm926ejs/cache.c
This patchset is now pending for more than 1 month ... are there any issues, or do you plan to apply it?
Thanks!
bye, Heiko
participants (4)
-
Andreas Bießmann
-
Heiko Schocher
-
Simon Glass
-
Wenyou.Yang@microchip.com