From 20e00c13681b69ad7f858a5e28baeb0c6e61c9e6 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Wed, 17 Aug 2016 09:13:23 +0200 Subject: [PATCH 01/20] arm: at91: mpddrc: add missing MPDDRC_MD defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add missing MPDDRC_MD defines Signed-off-by: Heiko Schocher Acked-by: Wenyou Yang Reviewed-by: Andreas Bießmann --- 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 d37d9082cdb..f6bcecda383 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 From 806a5a3958e4af483e529cf0db75464055d6e13a Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Wed, 17 Aug 2016 09:13:24 +0200 Subject: [PATCH 02/20] ARM: at91: clock: correct PRES offset for at91sam9x5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit on at91sam9x5 PRES offset is 4 in the PMC master clock register. Signed-off-by: Heiko Schocher Acked-by: Wenyou Yang Acked-by: Andreas Bießmann --- 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 c8d24ae8265..e3181fab84f 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) ? From 6ed67659b93f9b3190558845c20faea1447ae4ce Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Wed, 17 Aug 2016 09:13:25 +0200 Subject: [PATCH 03/20] arm, at91: add icache support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Simon Glass Reviewed-by: Andreas Bießmann --- 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 ddc323f6415..d36e15a51cc 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 00000000000..8813706232e --- /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 +#include + +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 2a36d29788c..08b1401372c 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 From ae5070d627fa04f42fc8b29400e2d189eb8b6bd2 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Thu, 1 Sep 2016 09:49:14 -0400 Subject: [PATCH 04/20] AT91: Correct misspelling of "redundent" in partition names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Robert P. J. Day Reviewed-by: Andreas Bießmann --- include/configs/at91-sama5_common.h | 2 +- include/configs/at91sam9rlek.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/configs/at91-sama5_common.h b/include/configs/at91-sama5_common.h index b09ef33e574..13140bae1f8 100644 --- a/include/configs/at91-sama5_common.h +++ b/include/configs/at91-sama5_common.h @@ -74,7 +74,7 @@ #define CONFIG_BOOTARGS \ "console=ttyS0,115200 earlyprintk " \ "mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro," \ - "256K(env),256k(env_redundent),256k(spare)," \ + "256K(env),256k(env_redundant),256k(spare)," \ "512k(dtb),6M(kernel)ro,-(rootfs) " \ "rootfstype=ubifs ubi.mtd=7 root=ubi0:rootfs" diff --git a/include/configs/at91sam9rlek.h b/include/configs/at91sam9rlek.h index 5b3a3d1b481..23184ceba00 100644 --- a/include/configs/at91sam9rlek.h +++ b/include/configs/at91sam9rlek.h @@ -148,7 +148,7 @@ #define CONFIG_BOOTARGS \ "console=ttyS0,115200 earlyprintk " \ "mtdparts=atmel_nand:256k(bootstrap)ro,512k(uboot)ro," \ - "256K(env),256k(env_redundent),256k(spare)," \ + "256K(env),256k(env_redundant),256k(spare)," \ "512k(dtb),6M(kernel)ro,-(rootfs) " \ "rootfstype=ubifs ubi.mtd=7 root=ubi0:rootfs" From b892b054b12fc38e5077434c9c6146a7bd6f21a6 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Tue, 13 Sep 2016 10:25:55 +0800 Subject: [PATCH 05/20] clk: at91: Fix at91-pmc and at91-sckc's class ID The at91-pmc and at91-sckc aren't the clock providers, change their class ID from UCLASS_CLK to UCLASS_SIMPLE_BUS, they also don't need to bind the child nodes explicitly, the .post_bind callback of simple_bus uclass will do it for them. Signed-off-by: Wenyou Yang Acked-by: Stephen Warren Reviewed-by: Simon Glass --- drivers/clk/at91/pmc.c | 10 ++-------- drivers/clk/at91/sckc.c | 17 +++++------------ 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index a08d7e82eb3..76ff3871d0b 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -14,21 +14,15 @@ DECLARE_GLOBAL_DATA_PTR; -static int at91_pmc_bind(struct udevice *dev) -{ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - static const struct udevice_id at91_pmc_match[] = { { .compatible = "atmel,sama5d2-pmc" }, {} }; U_BOOT_DRIVER(at91_pmc) = { - .name = "at91-pmc-core", - .id = UCLASS_CLK, + .name = "at91-pmc", + .id = UCLASS_SIMPLE_BUS, .of_match = at91_pmc_match, - .bind = at91_pmc_bind, }; int at91_pmc_core_probe(struct udevice *dev) diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c index b207611de1c..6035e209599 100644 --- a/drivers/clk/at91/sckc.c +++ b/drivers/clk/at91/sckc.c @@ -6,25 +6,18 @@ */ #include -#include #include #include DECLARE_GLOBAL_DATA_PTR; -static int at91_sckc_clk_bind(struct udevice *dev) -{ - return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); -} - -static const struct udevice_id at91_sckc_clk_match[] = { +static const struct udevice_id at91_sckc_match[] = { { .compatible = "atmel,at91sam9x5-sckc" }, {} }; -U_BOOT_DRIVER(at91_sckc_clk) = { - .name = "at91_sckc_clk", - .id = UCLASS_CLK, - .of_match = at91_sckc_clk_match, - .bind = at91_sckc_clk_bind, +U_BOOT_DRIVER(at91_sckc) = { + .name = "at91-sckc", + .id = UCLASS_SIMPLE_BUS, + .of_match = at91_sckc_match, }; From 9e63c49a526856a1ce79c18d8e3b51f46f21f716 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Sun, 18 Sep 2016 15:37:47 +0800 Subject: [PATCH 06/20] ARM: at91/dt: sama5d2: Fix the warning from dtc Fix the warning from dtc like, ---8<---- Warning (unit_address_vs_reg): Node /ahb/apb/pmc@f0014000/periph64ck/sdmmc0_hclk has a reg or ranges property, but no unit name --->8---- Signed-off-by: Wenyou Yang Acked-by: Stephen Warren --- arch/arm/dts/sama5d2.dtsi | 140 +++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/arch/arm/dts/sama5d2.dtsi b/arch/arm/dts/sama5d2.dtsi index 19feb6609db..a881d9e05c0 100644 --- a/arch/arm/dts/sama5d2.dtsi +++ b/arch/arm/dts/sama5d2.dtsi @@ -79,7 +79,7 @@ #clock-cells = <0>; }; - plla: pllack { + plla: pllack@0 { compatible = "atmel,sama5d3-clk-pll"; #clock-cells = <0>; clocks = <&main>; @@ -146,17 +146,17 @@ interrupt-parent = <&pmc>; clocks = <&main>, <&plladiv>, <&utmi>, <&mck>; - prog0: prog0 { + prog0: prog@0 { #clock-cells = <0>; reg = <0>; }; - prog1: prog1 { + prog1: prog@1 { #clock-cells = <0>; reg = <1>; }; - prog2: prog2 { + prog2: prog@2 { #clock-cells = <0>; reg = <2>; }; @@ -167,49 +167,49 @@ #address-cells = <1>; #size-cells = <0>; - ddrck: ddrck { + ddrck: ddrck@2 { #clock-cells = <0>; reg = <2>; clocks = <&mck>; }; - lcdck: lcdck { + lcdck: lcdck@3 { #clock-cells = <0>; reg = <3>; clocks = <&mck>; }; - uhpck: uhpck { + uhpck: uhpck@6 { #clock-cells = <0>; reg = <6>; clocks = <&usb>; }; - udpck: udpck { + udpck: udpck@7 { #clock-cells = <0>; reg = <7>; clocks = <&usb>; }; - pck0: pck0 { + pck0: pck0@8 { #clock-cells = <0>; reg = <8>; clocks = <&prog0>; }; - pck1: pck1 { + pck1: pck1@9 { #clock-cells = <0>; reg = <9>; clocks = <&prog1>; }; - pck2: pck2 { + pck2: pck2@10 { #clock-cells = <0>; reg = <10>; clocks = <&prog2>; }; - iscck: iscck { + iscck: iscck@18 { #clock-cells = <0>; reg = <18>; clocks = <&mck>; @@ -222,203 +222,203 @@ #size-cells = <0>; clocks = <&h32ck>; - macb0_clk: macb0_clk { + macb0_clk: macb0_clk@5 { #clock-cells = <0>; reg = <5>; atmel,clk-output-range = <0 83000000>; }; - tdes_clk: tdes_clk { + tdes_clk: tdes_clk@11 { #clock-cells = <0>; reg = <11>; atmel,clk-output-range = <0 83000000>; }; - matrix1_clk: matrix1_clk { + matrix1_clk: matrix1_clk@14 { #clock-cells = <0>; reg = <14>; }; - hsmc_clk: hsmc_clk { + hsmc_clk: hsmc_clk@17 { #clock-cells = <0>; reg = <17>; }; - pioA_clk: pioA_clk { + pioA_clk: pioA_clk@18 { #clock-cells = <0>; reg = <18>; atmel,clk-output-range = <0 83000000>; }; - flx0_clk: flx0_clk { + flx0_clk: flx0_clk@19 { #clock-cells = <0>; reg = <19>; atmel,clk-output-range = <0 83000000>; }; - flx1_clk: flx1_clk { + flx1_clk: flx1_clk@20 { #clock-cells = <0>; reg = <20>; atmel,clk-output-range = <0 83000000>; }; - flx2_clk: flx2_clk { + flx2_clk: flx2_clk@21 { #clock-cells = <0>; reg = <21>; atmel,clk-output-range = <0 83000000>; }; - flx3_clk: flx3_clk { + flx3_clk: flx3_clk@22 { #clock-cells = <0>; reg = <22>; atmel,clk-output-range = <0 83000000>; }; - flx4_clk: flx4_clk { + flx4_clk: flx4_clk@23 { #clock-cells = <0>; reg = <23>; atmel,clk-output-range = <0 83000000>; }; - uart0_clk: uart0_clk { + uart0_clk: uart0_clk@24 { #clock-cells = <0>; reg = <24>; atmel,clk-output-range = <0 83000000>; }; - uart1_clk: uart1_clk { + uart1_clk: uart1_clk@25 { #clock-cells = <0>; reg = <25>; atmel,clk-output-range = <0 83000000>; }; - uart2_clk: uart2_clk { + uart2_clk: uart2_clk@26 { #clock-cells = <0>; reg = <26>; atmel,clk-output-range = <0 83000000>; }; - uart3_clk: uart3_clk { + uart3_clk: uart3_clk@27 { #clock-cells = <0>; reg = <27>; atmel,clk-output-range = <0 83000000>; }; - uart4_clk: uart4_clk { + uart4_clk: uart4_clk@28 { #clock-cells = <0>; reg = <28>; atmel,clk-output-range = <0 83000000>; }; - twi0_clk: twi0_clk { + twi0_clk: twi0_clk@29 { reg = <29>; #clock-cells = <0>; atmel,clk-output-range = <0 83000000>; }; - twi1_clk: twi1_clk { + twi1_clk: twi1_clk@30 { #clock-cells = <0>; reg = <30>; atmel,clk-output-range = <0 83000000>; }; - spi0_clk: spi0_clk { + spi0_clk: spi0_clk@33 { #clock-cells = <0>; reg = <33>; atmel,clk-output-range = <0 83000000>; }; - spi1_clk: spi1_clk { + spi1_clk: spi1_clk@34 { #clock-cells = <0>; reg = <34>; atmel,clk-output-range = <0 83000000>; }; - tcb0_clk: tcb0_clk { + tcb0_clk: tcb0_clk@35 { #clock-cells = <0>; reg = <35>; atmel,clk-output-range = <0 83000000>; }; - tcb1_clk: tcb1_clk { + tcb1_clk: tcb1_clk@36 { #clock-cells = <0>; reg = <36>; atmel,clk-output-range = <0 83000000>; }; - pwm_clk: pwm_clk { + pwm_clk: pwm_clk@38 { #clock-cells = <0>; reg = <38>; atmel,clk-output-range = <0 83000000>; }; - adc_clk: adc_clk { + adc_clk: adc_clk@40 { #clock-cells = <0>; reg = <40>; atmel,clk-output-range = <0 83000000>; }; - uhphs_clk: uhphs_clk { + uhphs_clk: uhphs_clk@41 { #clock-cells = <0>; reg = <41>; atmel,clk-output-range = <0 83000000>; }; - udphs_clk: udphs_clk { + udphs_clk: udphs_clk@42 { #clock-cells = <0>; reg = <42>; atmel,clk-output-range = <0 83000000>; }; - ssc0_clk: ssc0_clk { + ssc0_clk: ssc0_clk@43 { #clock-cells = <0>; reg = <43>; atmel,clk-output-range = <0 83000000>; }; - ssc1_clk: ssc1_clk { + ssc1_clk: ssc1_clk@44 { #clock-cells = <0>; reg = <44>; atmel,clk-output-range = <0 83000000>; }; - trng_clk: trng_clk { + trng_clk: trng_clk@47 { #clock-cells = <0>; reg = <47>; atmel,clk-output-range = <0 83000000>; }; - pdmic_clk: pdmic_clk { + pdmic_clk: pdmic_clk@48 { #clock-cells = <0>; reg = <48>; atmel,clk-output-range = <0 83000000>; }; - i2s0_clk: i2s0_clk { + i2s0_clk: i2s0_clk@54 { #clock-cells = <0>; reg = <54>; atmel,clk-output-range = <0 83000000>; }; - i2s1_clk: i2s1_clk { + i2s1_clk: i2s1_clk@55 { #clock-cells = <0>; reg = <55>; atmel,clk-output-range = <0 83000000>; }; - can0_clk: can0_clk { + can0_clk: can0_clk@56 { #clock-cells = <0>; reg = <56>; atmel,clk-output-range = <0 83000000>; }; - can1_clk: can1_clk { + can1_clk: can1_clk@57 { #clock-cells = <0>; reg = <57>; atmel,clk-output-range = <0 83000000>; }; - classd_clk: classd_clk { + classd_clk: classd_clk@59 { #clock-cells = <0>; reg = <59>; atmel,clk-output-range = <0 83000000>; @@ -431,67 +431,67 @@ #size-cells = <0>; clocks = <&mck>; - dma0_clk: dma0_clk { + dma0_clk: dma0_clk@6 { #clock-cells = <0>; reg = <6>; }; - dma1_clk: dma1_clk { + dma1_clk: dma1_clk@7 { #clock-cells = <0>; reg = <7>; }; - aes_clk: aes_clk { + aes_clk: aes_clk@9 { #clock-cells = <0>; reg = <9>; }; - aesb_clk: aesb_clk { + aesb_clk: aesb_clk@10 { #clock-cells = <0>; reg = <10>; }; - sha_clk: sha_clk { + sha_clk: sha_clk@12 { #clock-cells = <0>; reg = <12>; }; - mpddr_clk: mpddr_clk { + mpddr_clk: mpddr_clk@13 { #clock-cells = <0>; reg = <13>; }; - matrix0_clk: matrix0_clk { + matrix0_clk: matrix0_clk@15 { #clock-cells = <0>; reg = <15>; }; - sdmmc0_hclk: sdmmc0_hclk { + sdmmc0_hclk: sdmmc0_hclk@31 { #clock-cells = <0>; reg = <31>; }; - sdmmc1_hclk: sdmmc1_hclk { + sdmmc1_hclk: sdmmc1_hclk@32 { #clock-cells = <0>; reg = <32>; }; - lcdc_clk: lcdc_clk { + lcdc_clk: lcdc_clk@45 { #clock-cells = <0>; reg = <45>; }; - isc_clk: isc_clk { + isc_clk: isc_clk@46 { #clock-cells = <0>; reg = <46>; }; - qspi0_clk: qspi0_clk { + qspi0_clk: qspi0_clk@52 { #clock-cells = <0>; reg = <52>; }; - qspi1_clk: qspi1_clk { + qspi1_clk: qspi1_clk@53 { #clock-cells = <0>; reg = <53>; }; @@ -504,62 +504,62 @@ interrupt-parent = <&pmc>; clocks = <&main>, <&plla>, <&utmi>, <&mck>; - sdmmc0_gclk: sdmmc0_gclk { + sdmmc0_gclk: sdmmc0_gclk@31 { #clock-cells = <0>; reg = <31>; }; - sdmmc1_gclk: sdmmc1_gclk { + sdmmc1_gclk: sdmmc1_gclk@32 { #clock-cells = <0>; reg = <32>; }; - tcb0_gclk: tcb0_gclk { + tcb0_gclk: tcb0_gclk@35 { #clock-cells = <0>; reg = <35>; atmel,clk-output-range = <0 83000000>; }; - tcb1_gclk: tcb1_gclk { + tcb1_gclk: tcb1_gclk@36 { #clock-cells = <0>; reg = <36>; atmel,clk-output-range = <0 83000000>; }; - pwm_gclk: pwm_gclk { + pwm_gclk: pwm_gclk@38 { #clock-cells = <0>; reg = <38>; atmel,clk-output-range = <0 83000000>; }; - pdmic_gclk: pdmic_gclk { + pdmic_gclk: pdmic_gclk@48 { #clock-cells = <0>; reg = <48>; }; - i2s0_gclk: i2s0_gclk { + i2s0_gclk: i2s0_gclk@54 { #clock-cells = <0>; reg = <54>; }; - i2s1_gclk: i2s1_gclk { + i2s1_gclk: i2s1_gclk@55 { #clock-cells = <0>; reg = <55>; }; - can0_gclk: can0_gclk { + can0_gclk: can0_gclk@56 { #clock-cells = <0>; reg = <56>; atmel,clk-output-range = <0 80000000>; }; - can1_gclk: can1_gclk { + can1_gclk: can1_gclk@57 { #clock-cells = <0>; reg = <57>; atmel,clk-output-range = <0 80000000>; }; - classd_gclk: classd_gclk { + classd_gclk: classd_gclk@59 { #clock-cells = <0>; reg = <59>; atmel,clk-output-range = <0 100000000>; From 3f56b1321593c0081e77a3bc900177e6cf2f21d6 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Tue, 27 Sep 2016 11:00:28 +0800 Subject: [PATCH 07/20] clk: clk-uclass: Assign clk->dev before call .of_xlate In order to make clk->dev available in ops->of_xlate() to get the clock ID from the 'reg' property of the clock node, assign the clk->dev before calling ops->of_xlate(). Signed-off-by: Wenyou Yang Acked-by: Stephen Warren Acked-by: Simon Glass --- drivers/clk/clk-uclass.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index c42fff6ec29..153ceba702d 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -80,6 +80,9 @@ int clk_get_by_index(struct udevice *dev, int index, struct clk *clk) __func__, ret); return ret; } + + clk->dev = dev_clk; + ops = clk_dev_ops(dev_clk); if (ops->of_xlate) From 6cadaa046b196bebebd7acb13edd840bcfef98e2 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Tue, 27 Sep 2016 11:00:29 +0800 Subject: [PATCH 08/20] clk: at91: Improve the clock implementation For the peripheral clock, provide the clock ops for the clock provider, such as spi0_clk. The .of_xlate is to get the clk->id, the .enable is to enable the spi0 peripheral clock, the .get_rate is to get the clock frequency. The driver for periph32ck node is responsible for recursively binding its children as clk devices, not provide the clock ops. So do the generated clock and system clock. Signed-off-by: Wenyou Yang Acked-by: Stephen Warren --- drivers/clk/at91/Kconfig | 1 + drivers/clk/at91/clk-generated.c | 87 ++++++++++++++++++------------- drivers/clk/at91/clk-peripheral.c | 74 ++++++++++++++++++-------- drivers/clk/at91/clk-system.c | 57 +++++++++++--------- drivers/clk/at91/pmc.c | 62 +++++++++++++++++++--- drivers/clk/at91/pmc.h | 5 +- 6 files changed, 196 insertions(+), 90 deletions(-) diff --git a/drivers/clk/at91/Kconfig b/drivers/clk/at91/Kconfig index 10050d8a442..904ed48e51e 100644 --- a/drivers/clk/at91/Kconfig +++ b/drivers/clk/at91/Kconfig @@ -1,6 +1,7 @@ config CLK_AT91 bool "AT91 clock drivers" depends on CLK + select MISC help This option is used to enable the AT91 clock driver. The driver supports the AT91 clock generator, including diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c index f6164cc8ca1..d36f64ffdf8 100644 --- a/drivers/clk/at91/clk-generated.c +++ b/drivers/clk/at91/clk-generated.c @@ -17,15 +17,41 @@ DECLARE_GLOBAL_DATA_PTR; #define GENERATED_SOURCE_MAX 6 #define GENERATED_MAX_DIV 255 -struct generated_clk_priv { +/** + * generated_clk_bind() - for the generated clock driver + * Recursively bind its children as clk devices. + * + * @return: 0 on success, or negative error code on failure + */ +static int generated_clk_bind(struct udevice *dev) +{ + return at91_clk_sub_device_bind(dev, "generic-clk"); +} + +static const struct udevice_id generated_clk_match[] = { + { .compatible = "atmel,sama5d2-clk-generated" }, + {} +}; + +U_BOOT_DRIVER(generated_clk) = { + .name = "generated-clk", + .id = UCLASS_MISC, + .of_match = generated_clk_match, + .bind = generated_clk_bind, +}; + +/*-------------------------------------------------------------*/ + +struct generic_clk_priv { u32 num_parents; }; -static ulong generated_clk_get_rate(struct clk *clk) +static ulong generic_clk_get_rate(struct clk *clk) { struct pmc_platdata *plat = dev_get_platdata(clk->dev); struct at91_pmc *pmc = plat->reg_base; struct clk parent; + ulong clk_rate; u32 tmp, gckdiv; u8 parent_id; int ret; @@ -36,18 +62,22 @@ static ulong generated_clk_get_rate(struct clk *clk) AT91_PMC_PCR_GCKCSS_MASK; gckdiv = (tmp >> AT91_PMC_PCR_GCKDIV_OFFSET) & AT91_PMC_PCR_GCKDIV_MASK; - ret = clk_get_by_index(clk->dev, parent_id, &parent); + ret = clk_get_by_index(dev_get_parent(clk->dev), parent_id, &parent); if (ret) return 0; - return clk_get_rate(&parent) / (gckdiv + 1); + clk_rate = clk_get_rate(&parent) / (gckdiv + 1); + + clk_free(&parent); + + return clk_rate; } -static ulong generated_clk_set_rate(struct clk *clk, ulong rate) +static ulong generic_clk_set_rate(struct clk *clk, ulong rate) { struct pmc_platdata *plat = dev_get_platdata(clk->dev); struct at91_pmc *pmc = plat->reg_base; - struct generated_clk_priv *priv = dev_get_priv(clk->dev); + struct generic_clk_priv *priv = dev_get_priv(clk->dev); struct clk parent, best_parent; ulong tmp_rate, best_rate = rate, parent_rate; int tmp_diff, best_diff = -1; @@ -58,7 +88,7 @@ static ulong generated_clk_set_rate(struct clk *clk, ulong rate) int ret; for (i = 0; i < priv->num_parents; i++) { - ret = clk_get_by_index(clk->dev, i, &parent); + ret = clk_get_by_index(dev_get_parent(clk->dev), i, &parent); if (ret) return ret; @@ -111,18 +141,20 @@ static ulong generated_clk_set_rate(struct clk *clk, ulong rate) return 0; } -static struct clk_ops generated_clk_ops = { - .get_rate = generated_clk_get_rate, - .set_rate = generated_clk_set_rate, +static struct clk_ops generic_clk_ops = { + .of_xlate = at91_clk_of_xlate, + .get_rate = generic_clk_get_rate, + .set_rate = generic_clk_set_rate, }; -static int generated_clk_ofdata_to_platdata(struct udevice *dev) +static int generic_clk_ofdata_to_platdata(struct udevice *dev) { - struct generated_clk_priv *priv = dev_get_priv(dev); + struct generic_clk_priv *priv = dev_get_priv(dev); u32 cells[GENERATED_SOURCE_MAX]; u32 num_parents; - num_parents = fdtdec_get_int_array_count(gd->fdt_blob, dev->of_offset, + num_parents = fdtdec_get_int_array_count(gd->fdt_blob, + dev_get_parent(dev)->of_offset, "clocks", cells, GENERATED_SOURCE_MAX); @@ -134,29 +166,12 @@ static int generated_clk_ofdata_to_platdata(struct udevice *dev) return 0; } -static int generated_clk_bind(struct udevice *dev) -{ - return at91_pmc_clk_node_bind(dev); -} - -static int generated_clk_probe(struct udevice *dev) -{ - return at91_pmc_core_probe(dev); -} - -static const struct udevice_id generated_clk_match[] = { - { .compatible = "atmel,sama5d2-clk-generated" }, - {} -}; - -U_BOOT_DRIVER(generated_clk) = { - .name = "generated-clk", +U_BOOT_DRIVER(generic_clk) = { + .name = "generic-clk", .id = UCLASS_CLK, - .of_match = generated_clk_match, - .bind = generated_clk_bind, - .probe = generated_clk_probe, - .ofdata_to_platdata = generated_clk_ofdata_to_platdata, - .priv_auto_alloc_size = sizeof(struct generated_clk_priv), + .probe = at91_clk_probe, + .ofdata_to_platdata = generic_clk_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct generic_clk_priv), .platdata_auto_alloc_size = sizeof(struct pmc_platdata), - .ops = &generated_clk_ops, + .ops = &generic_clk_ops, }; diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c index 16688e90b41..e1ed447133e 100644 --- a/drivers/clk/at91/clk-peripheral.c +++ b/drivers/clk/at91/clk-peripheral.c @@ -16,7 +16,32 @@ #define PERIPHERAL_ID_MAX 31 #define PERIPHERAL_MASK(id) (1 << ((id) & PERIPHERAL_ID_MAX)) -static int sam9x5_periph_clk_enable(struct clk *clk) +/** + * sam9x5_periph_clk_bind() - for the periph clock driver + * Recursively bind its children as clk devices. + * + * @return: 0 on success, or negative error code on failure + */ +static int sam9x5_periph_clk_bind(struct udevice *dev) +{ + return at91_clk_sub_device_bind(dev, "periph-clk"); +} + +static const struct udevice_id sam9x5_periph_clk_match[] = { + { .compatible = "atmel,at91sam9x5-clk-peripheral" }, + {} +}; + +U_BOOT_DRIVER(sam9x5_periph_clk) = { + .name = "sam9x5-periph-clk", + .id = UCLASS_MISC, + .of_match = sam9x5_periph_clk_match, + .bind = sam9x5_periph_clk_bind, +}; + +/*---------------------------------------------------------*/ + +static int periph_clk_enable(struct clk *clk) { struct pmc_platdata *plat = dev_get_platdata(clk->dev); struct at91_pmc *pmc = plat->reg_base; @@ -30,31 +55,36 @@ static int sam9x5_periph_clk_enable(struct clk *clk) return 0; } -static struct clk_ops sam9x5_periph_clk_ops = { - .enable = sam9x5_periph_clk_enable, -}; - -static int sam9x5_periph_clk_bind(struct udevice *dev) +static ulong periph_get_rate(struct clk *clk) { - return at91_pmc_clk_node_bind(dev); + struct udevice *dev; + struct clk clk_dev; + ulong clk_rate; + int ret; + + dev = dev_get_parent(clk->dev); + + ret = clk_get_by_index(dev, 0, &clk_dev); + if (ret) + return ret; + + clk_rate = clk_get_rate(&clk_dev); + + clk_free(&clk_dev); + + return clk_rate; } -static int sam9x5_periph_clk_probe(struct udevice *dev) -{ - return at91_pmc_core_probe(dev); -} - -static const struct udevice_id sam9x5_periph_clk_match[] = { - { .compatible = "atmel,at91sam9x5-clk-peripheral" }, - {} +static struct clk_ops periph_clk_ops = { + .of_xlate = at91_clk_of_xlate, + .enable = periph_clk_enable, + .get_rate = periph_get_rate, }; -U_BOOT_DRIVER(sam9x5_periph_clk) = { - .name = "sam9x5-periph-clk", - .id = UCLASS_CLK, - .of_match = sam9x5_periph_clk_match, - .bind = sam9x5_periph_clk_bind, - .probe = sam9x5_periph_clk_probe, +U_BOOT_DRIVER(clk_periph) = { + .name = "periph-clk", + .id = UCLASS_CLK, .platdata_auto_alloc_size = sizeof(struct pmc_platdata), - .ops = &sam9x5_periph_clk_ops, + .probe = at91_clk_probe, + .ops = &periph_clk_ops, }; diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c index fa80bade7a9..5b59a0c8520 100644 --- a/drivers/clk/at91/clk-system.c +++ b/drivers/clk/at91/clk-system.c @@ -14,12 +14,37 @@ #define SYSTEM_MAX_ID 31 +/** + * at91_system_clk_bind() - for the system clock driver + * Recursively bind its children as clk devices. + * + * @return: 0 on success, or negative error code on failure + */ +static int at91_system_clk_bind(struct udevice *dev) +{ + return at91_clk_sub_device_bind(dev, "system-clk"); +} + +static const struct udevice_id at91_system_clk_match[] = { + { .compatible = "atmel,at91rm9200-clk-system" }, + {} +}; + +U_BOOT_DRIVER(at91_system_clk) = { + .name = "at91-system-clk", + .id = UCLASS_MISC, + .of_match = at91_system_clk_match, + .bind = at91_system_clk_bind, +}; + +/*----------------------------------------------------------*/ + static inline int is_pck(int id) { return (id >= 8) && (id <= 15); } -static int at91_system_clk_enable(struct clk *clk) +static int system_clk_enable(struct clk *clk) { struct pmc_platdata *plat = dev_get_platdata(clk->dev); struct at91_pmc *pmc = plat->reg_base; @@ -46,31 +71,15 @@ static int at91_system_clk_enable(struct clk *clk) return 0; } -static struct clk_ops at91_system_clk_ops = { - .enable = at91_system_clk_enable, +static struct clk_ops system_clk_ops = { + .of_xlate = at91_clk_of_xlate, + .enable = system_clk_enable, }; -static int at91_system_clk_bind(struct udevice *dev) -{ - return at91_pmc_clk_node_bind(dev); -} - -static int at91_system_clk_probe(struct udevice *dev) -{ - return at91_pmc_core_probe(dev); -} - -static const struct udevice_id at91_system_clk_match[] = { - { .compatible = "atmel,at91rm9200-clk-system" }, - {} -}; - -U_BOOT_DRIVER(at91_system_clk) = { - .name = "at91-system-clk", +U_BOOT_DRIVER(system_clk) = { + .name = "system-clk", .id = UCLASS_CLK, - .of_match = at91_system_clk_match, - .bind = at91_system_clk_bind, - .probe = at91_system_clk_probe, + .probe = at91_clk_probe, .platdata_auto_alloc_size = sizeof(struct pmc_platdata), - .ops = &at91_system_clk_ops, + .ops = &system_clk_ops, }; diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index 76ff3871d0b..76ba91af812 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -25,6 +25,8 @@ U_BOOT_DRIVER(at91_pmc) = { .of_match = at91_pmc_match, }; +/*---------------------------------------------------------*/ + int at91_pmc_core_probe(struct udevice *dev) { struct pmc_platdata *plat = dev_get_platdata(dev); @@ -36,21 +38,41 @@ int at91_pmc_core_probe(struct udevice *dev) return 0; } -int at91_pmc_clk_node_bind(struct udevice *dev) +/** + * at91_clk_sub_device_bind() - for the at91 clock driver + * Recursively bind its children as clk devices. + * + * @return: 0 on success, or negative error code on failure + */ +int at91_clk_sub_device_bind(struct udevice *dev, const char *drv_name) { const void *fdt = gd->fdt_blob; int offset = dev->of_offset; + bool pre_reloc_only = !(gd->flags & GD_FLG_RELOC); const char *name; int ret; for (offset = fdt_first_subnode(fdt, offset); offset > 0; offset = fdt_next_subnode(fdt, offset)) { + if (pre_reloc_only && + !fdt_getprop(fdt, offset, "u-boot,dm-pre-reloc", NULL)) + continue; + /* + * If this node has "compatible" property, this is not + * a clock sub-node, but a normal device. skip. + */ + fdt_get_property(fdt, offset, "compatible", &ret); + if (ret >= 0) + continue; + + if (ret != -FDT_ERR_NOTFOUND) + return ret; + name = fdt_get_name(fdt, offset, NULL); if (!name) return -EINVAL; - - ret = device_bind_driver_to_node(dev, "clk", name, + ret = device_bind_driver_to_node(dev, drv_name, name, offset, NULL); if (ret) return ret; @@ -59,7 +81,33 @@ int at91_pmc_clk_node_bind(struct udevice *dev) return 0; } -U_BOOT_DRIVER(clk_generic) = { - .id = UCLASS_CLK, - .name = "clk", -}; +int at91_clk_of_xlate(struct clk *clk, struct fdtdec_phandle_args *args) +{ + int periph; + + if (args->args_count) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + periph = fdtdec_get_uint(gd->fdt_blob, clk->dev->of_offset, "reg", -1); + if (periph < 0) + return -EINVAL; + + clk->id = periph; + + return 0; +} + +int at91_clk_probe(struct udevice *dev) +{ + struct udevice *dev_periph_container, *dev_pmc; + struct pmc_platdata *plat = dev_get_platdata(dev); + + dev_periph_container = dev_get_parent(dev); + dev_pmc = dev_get_parent(dev_periph_container); + + plat->reg_base = (struct at91_pmc *)dev_get_addr_ptr(dev_pmc); + + return 0; +} diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index 5444c84db66..f222fce11f4 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -13,6 +13,9 @@ struct pmc_platdata { }; int at91_pmc_core_probe(struct udevice *dev); -int at91_pmc_clk_node_bind(struct udevice *dev); +int at91_clk_sub_device_bind(struct udevice *dev, const char *drv_name); + +int at91_clk_of_xlate(struct clk *clk, struct fdtdec_phandle_args *args); +int at91_clk_probe(struct udevice *dev); #endif From d85d92ae7b25ea8d824494a7460f27b2c72cb5ca Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Tue, 27 Sep 2016 11:00:30 +0800 Subject: [PATCH 09/20] gpio: atmel_pio4: Remove unnecessary clock calling Due to the peripheral clock driver improvement, remove the unnecessary clock calling. Signed-off-by: Wenyou Yang Acked-by: Stephen Warren --- drivers/gpio/atmel_pio4.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/drivers/gpio/atmel_pio4.c b/drivers/gpio/atmel_pio4.c index 7adea885650..cb90b0241a2 100644 --- a/drivers/gpio/atmel_pio4.c +++ b/drivers/gpio/atmel_pio4.c @@ -284,27 +284,15 @@ static int atmel_pio4_probe(struct udevice *dev) struct atmel_pio4_platdata *plat = dev_get_platdata(dev); struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); struct atmel_pioctrl_data *pioctrl_data; - struct udevice *dev_clk; struct clk clk; fdt_addr_t addr_base; u32 nbanks; - int periph; int ret; ret = clk_get_by_index(dev, 0, &clk); if (ret) return ret; - periph = fdtdec_get_uint(gd->fdt_blob, clk.dev->of_offset, "reg", -1); - if (periph < 0) - return -EINVAL; - - dev_clk = dev_get_parent(clk.dev); - ret = clk_request(dev_clk, &clk); - if (ret) - return ret; - - clk.id = periph; ret = clk_enable(&clk); if (ret) return ret; From 2ccc07bbdcd85878aa02cf4afb8aa5ed7ef1b446 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Tue, 27 Sep 2016 11:00:31 +0800 Subject: [PATCH 10/20] i2c: at91_i2c: Remove unnecessary clock calling Due to the peripheral clock driver improvement, remove the unnecessary clock calling. Signed-off-by: Wenyou Yang Reviewed-by: Heiko Schocher --- drivers/i2c/at91_i2c.c | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/drivers/i2c/at91_i2c.c b/drivers/i2c/at91_i2c.c index d71f75c5faa..dcd3ce8627b 100644 --- a/drivers/i2c/at91_i2c.c +++ b/drivers/i2c/at91_i2c.c @@ -176,34 +176,18 @@ static void at91_calc_i2c_clock(struct udevice *dev, int i2c_clk) static int at91_i2c_enable_clk(struct udevice *dev) { struct at91_i2c_bus *bus = dev_get_priv(dev); - struct udevice *dev_clk; struct clk clk; ulong clk_rate; - int periph; int ret; ret = clk_get_by_index(dev, 0, &clk); if (ret) return -EINVAL; - periph = fdtdec_get_uint(gd->fdt_blob, clk.dev->of_offset, "reg", -1); - if (periph < 0) - return -EINVAL; - - dev_clk = dev_get_parent(clk.dev); - ret = clk_request(dev_clk, &clk); - if (ret) - return ret; - - clk.id = periph; ret = clk_enable(&clk); if (ret) return ret; - ret = clk_get_by_index(dev_clk, 0, &clk); - if (ret) - return ret; - clk_rate = clk_get_rate(&clk); if (!clk_rate) return -ENODEV; From 52f37333bc3277cf182e4afb9d59ef2c6f09816e Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Tue, 27 Sep 2016 11:00:32 +0800 Subject: [PATCH 11/20] i2c: at91_i2c: Change error return -ENODEV to -EINVAL Change the error return value -ENODEV from to -EINVAL for more reasonable. Signed-off-by: Wenyou Yang Reviewed-by: Heiko Schocher --- drivers/i2c/at91_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/at91_i2c.c b/drivers/i2c/at91_i2c.c index dcd3ce8627b..4bc54eea596 100644 --- a/drivers/i2c/at91_i2c.c +++ b/drivers/i2c/at91_i2c.c @@ -190,7 +190,7 @@ static int at91_i2c_enable_clk(struct udevice *dev) clk_rate = clk_get_rate(&clk); if (!clk_rate) - return -ENODEV; + return -EINVAL; bus->bus_clk_rate = clk_rate; From c6a0f7f1356dd68a269dcfa34aae8f75a01ef7fe Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Tue, 27 Sep 2016 11:00:33 +0800 Subject: [PATCH 12/20] usb: ehci-atmel: Remove unnecessary clock calling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to the peripheral clock driver improvement, remove the unnecessary clock calling. Signed-off-by: Wenyou Yang Reviewed-by: Andreas Bießmann --- drivers/usb/host/ehci-atmel.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 2b138c51535..a5c6d349747 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -56,9 +56,7 @@ struct ehci_atmel_priv { static int ehci_atmel_enable_clk(struct udevice *dev) { - struct udevice *dev_clk; struct clk clk; - int periph; int ret; ret = clk_get_by_index(dev, 0, &clk); @@ -73,19 +71,6 @@ static int ehci_atmel_enable_clk(struct udevice *dev) if (ret) return -EINVAL; - periph = fdtdec_get_uint(gd->fdt_blob, clk.dev->of_offset, "reg", -1); - if (periph < 0) - return -EINVAL; - - dev_clk = dev_get_parent(clk.dev); - if (!dev_clk) - return -ENODEV; - - ret = clk_request(dev_clk, &clk); - if (ret) - return ret; - - clk.id = periph; ret = clk_enable(&clk); if (ret) return ret; From 339cb0732ae98ae81b0460f4ed16bd6e3e044efc Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Tue, 27 Sep 2016 11:00:34 +0800 Subject: [PATCH 13/20] mmc: atmel_sdhci: Remove unnecessary clock calling Due to the peripheral and generated clock driver improvement, remove the unnecessary clock calling. Signed-off-by: Wenyou Yang Reviewed-by: Jaehoon Chung --- drivers/mmc/atmel_sdhci.c | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/drivers/mmc/atmel_sdhci.c b/drivers/mmc/atmel_sdhci.c index 20bba1a2797..6654b542788 100644 --- a/drivers/mmc/atmel_sdhci.c +++ b/drivers/mmc/atmel_sdhci.c @@ -50,29 +50,6 @@ struct atmel_sdhci_plat { struct mmc mmc; }; -static int atmel_sdhci_get_clk(struct udevice *dev, int index, struct clk *clk) -{ - struct udevice *dev_clk; - int periph, ret; - - ret = clk_get_by_index(dev, index, clk); - if (ret) - return ret; - - periph = fdtdec_get_uint(gd->fdt_blob, clk->dev->of_offset, "reg", -1); - if (periph < 0) - return -EINVAL; - - dev_clk = dev_get_parent(clk->dev); - ret = clk_request(dev_clk, clk); - if (ret) - return ret; - - clk->id = periph; - - return 0; -} - static int atmel_sdhci_probe(struct udevice *dev) { struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); @@ -85,7 +62,7 @@ static int atmel_sdhci_probe(struct udevice *dev) struct clk clk; int ret; - ret = atmel_sdhci_get_clk(dev, 0, &clk); + ret = clk_get_by_index(dev, 0, &clk); if (ret) return ret; @@ -106,7 +83,7 @@ static int atmel_sdhci_probe(struct udevice *dev) clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT; gck_rate = clk_base * 1000000 * (clk_mul + 1); - ret = atmel_sdhci_get_clk(dev, 1, &clk); + ret = clk_get_by_index(dev, 1, &clk); if (ret) return ret; From 6ec739aa525bb238acdd428042a11183ce4be3c4 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 17 Oct 2016 09:49:54 +0800 Subject: [PATCH 14/20] serial: Kconfig: Add ATMEL_USART option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add ATMEL_USART option to support to enable the Atmel usart driver from Kconfig. Signed-off-by: Wenyou Yang Reviewed-by: Andreas Bießmann --- drivers/serial/Kconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 541cf2e512f..9e489024461 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -296,6 +296,13 @@ config AR933X_UART tree binding to operate, please refer to the document at doc/device-tree-bindings/serial/qca,ar9330-uart.txt. +config ATMEL_USART + bool "Atmel USART support" + help + Select this to enable USART support for Atmel SoCs. It can be + configured in the device tree, and input clock frequency can + be got from the clk node. + config FSL_LPUART bool "Freescale LPUART support" help From 998cf3c2becb933a87d001c24193911e64dc8b6a Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 17 Oct 2016 09:49:55 +0800 Subject: [PATCH 15/20] serial: atmel_usart: Support enable an early debug UART MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support to enable an early debug UART for debugging. Signed-off-by: Wenyou Yang Reviewed-by: Simon Glass Reviewed-by: Andreas Bießmann --- drivers/serial/Kconfig | 7 +++++++ drivers/serial/atmel_usart.c | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 9e489024461..507a27da039 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -98,6 +98,13 @@ config DEBUG_UART_AR933X driver will be available until the real driver model serial is running. +config DEBUG_UART_ATMEL + bool "Atmel USART" + help + Select this to enable a debug UART using the atmel usart driver. You + will need to provide parameters to make this work. The driver will + be available until the real driver-model serial is running. + config DEBUG_UART_NS16550 bool "ns16550" help diff --git a/drivers/serial/atmel_usart.c b/drivers/serial/atmel_usart.c index e450135c757..7674f97e8dd 100644 --- a/drivers/serial/atmel_usart.c +++ b/drivers/serial/atmel_usart.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -226,3 +227,24 @@ U_BOOT_DRIVER(serial_atmel) = { .priv_auto_alloc_size = sizeof(struct atmel_serial_priv), }; #endif + +#ifdef CONFIG_DEBUG_UART_ATMEL +static inline void _debug_uart_init(void) +{ + atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_DEBUG_UART_BASE; + + atmel_serial_setbrg_internal(usart, 0, CONFIG_BAUDRATE); +} + +static inline void _debug_uart_putc(int ch) +{ + atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_DEBUG_UART_BASE; + + while (!(readl(&usart->csr) & USART3_BIT(TXRDY))) + ; + + writel(ch, &usart->thr); +} + +DEBUG_UART_FUNCS +#endif From 6f170c4d77381d18e5acee4ba92dfbd10107bc80 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 17 Oct 2016 09:55:23 +0800 Subject: [PATCH 16/20] board: sama5d2_xplained: Move config options to defconfigs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the config options from the include/configs/sama5d2_xplained.h to configs/sama5d2_xplained_*_defconfig. Signed-off-by: Wenyou Yang Reviewed-by: Andreas Bießmann --- .../atmel/sama5d2_xplained/sama5d2_xplained.c | 2 ++ configs/sama5d2_xplained_mmc_defconfig | 31 ++++++++++++++++++- configs/sama5d2_xplained_spiflash_defconfig | 31 ++++++++++++++++++- include/configs/sama5d2_xplained.h | 25 --------------- 4 files changed, 62 insertions(+), 27 deletions(-) diff --git a/board/atmel/sama5d2_xplained/sama5d2_xplained.c b/board/atmel/sama5d2_xplained/sama5d2_xplained.c index 93df7ba32a8..413a000d227 100644 --- a/board/atmel/sama5d2_xplained/sama5d2_xplained.c +++ b/board/atmel/sama5d2_xplained/sama5d2_xplained.c @@ -25,10 +25,12 @@ DECLARE_GLOBAL_DATA_PTR; +#ifndef CONFIG_DM_SPI int spi_cs_is_valid(unsigned int bus, unsigned int cs) { return bus == 0 && cs == 0; } +#endif void spi_cs_activate(struct spi_slave *slave) { diff --git a/configs/sama5d2_xplained_mmc_defconfig b/configs/sama5d2_xplained_mmc_defconfig index 23ab4d6d34d..08ecea64011 100644 --- a/configs/sama5d2_xplained_mmc_defconfig +++ b/configs/sama5d2_xplained_mmc_defconfig @@ -8,6 +8,9 @@ CONFIG_SPL_FAT_SUPPORT=y CONFIG_SPL_LIBDISK_SUPPORT=y CONFIG_SPL_MMC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_DM_GPIO=y +CONFIG_DM_SERIAL=y +CONFIG_DEFAULT_DEVICE_TREE="at91-sama5d2_xplained" CONFIG_FIT=y CONFIG_SYS_EXTRA_OPTIONS="SAMA5D2,SYS_USE_MMC" CONFIG_BOOTDELAY=3 @@ -21,14 +24,40 @@ CONFIG_CMD_BOOTZ=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_MMC=y CONFIG_CMD_SF=y +CONFIG_CMD_I2C=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_DHCP=y CONFIG_CMD_PING=y CONFIG_CMD_FAT=y +CONFIG_OF_CONTROL=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_DM=y +CONFIG_SPL_DM=y +CONFIG_BLK=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_CLK_AT91=y +CONFIG_AT91_UTMI=y +CONFIG_AT91_H32MX=y +CONFIG_AT91_GENERIC_CLK=y +CONFIG_ATMEL_PIO4=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_AT91=y +CONFIG_DM_MMC=y +CONFIG_DM_MMC_OPS=y +CONFIG_ATMEL_SDHCI=y +CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_ATMEL=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_AT91PIO4=y +CONFIG_ATMEL_USART=y +CONFIG_DM_SPI=y +CONFIG_ATMEL_SPI=y CONFIG_USB=y CONFIG_USB_STORAGE=y +CONFIG_DM_USB=y +CONFIG_USB_EHCI_HCD=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_ATMEL_USBA=y -CONFIG_OF_LIBFDT=y diff --git a/configs/sama5d2_xplained_spiflash_defconfig b/configs/sama5d2_xplained_spiflash_defconfig index f208dc2473f..b49d2adf676 100644 --- a/configs/sama5d2_xplained_spiflash_defconfig +++ b/configs/sama5d2_xplained_spiflash_defconfig @@ -7,6 +7,9 @@ CONFIG_SPL_LIBGENERIC_SUPPORT=y CONFIG_SPL_SERIAL_SUPPORT=y CONFIG_SPL_SPI_FLASH_SUPPORT=y CONFIG_SPL_SPI_SUPPORT=y +CONFIG_DM_GPIO=y +CONFIG_DM_SERIAL=y +CONFIG_DEFAULT_DEVICE_TREE="at91-sama5d2_xplained" CONFIG_FIT=y CONFIG_SYS_EXTRA_OPTIONS="SAMA5D2,SYS_USE_SERIALFLASH" CONFIG_BOOTDELAY=3 @@ -20,14 +23,40 @@ CONFIG_CMD_BOOTZ=y # CONFIG_CMD_FLASH is not set CONFIG_CMD_MMC=y CONFIG_CMD_SF=y +CONFIG_CMD_I2C=y CONFIG_CMD_USB=y # CONFIG_CMD_FPGA is not set CONFIG_CMD_DHCP=y CONFIG_CMD_PING=y CONFIG_CMD_FAT=y +CONFIG_OF_CONTROL=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_DM=y +CONFIG_SPL_DM=y +CONFIG_BLK=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_CLK_AT91=y +CONFIG_AT91_UTMI=y +CONFIG_AT91_H32MX=y +CONFIG_AT91_GENERIC_CLK=y +CONFIG_ATMEL_PIO4=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_AT91=y +CONFIG_DM_MMC=y +CONFIG_DM_MMC_OPS=y +CONFIG_ATMEL_SDHCI=y +CONFIG_DM_SPI_FLASH=y CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_ATMEL=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_AT91PIO4=y +CONFIG_ATMEL_USART=y +CONFIG_DM_SPI=y +CONFIG_ATMEL_SPI=y CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_EHCI_HCD=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_ATMEL_USBA=y -CONFIG_OF_LIBFDT=y diff --git a/include/configs/sama5d2_xplained.h b/include/configs/sama5d2_xplained.h index 30fb9a4dfb6..435956d75ad 100644 --- a/include/configs/sama5d2_xplained.h +++ b/include/configs/sama5d2_xplained.h @@ -15,11 +15,6 @@ #include "at91-sama5_common.h" -/* serial console */ -#define CONFIG_ATMEL_USART -#define CONFIG_USART_BASE ATMEL_BASE_UART1 -#define CONFIG_USART_ID ATMEL_ID_UART1 - /* SDRAM */ #define CONFIG_NR_DRAM_BANKS 1 #define CONFIG_SYS_SDRAM_BASE ATMEL_BASE_DDRCS @@ -34,14 +29,8 @@ #define CONFIG_SYS_LOAD_ADDR 0x22000000 /* load address */ -#undef CONFIG_AT91_GPIO -#define CONFIG_ATMEL_PIO4 - /* SerialFlash */ #ifdef CONFIG_CMD_SF -#define CONFIG_ATMEL_SPI -#define CONFIG_ATMEL_SPI0 -#define CONFIG_SPI_FLASH_ATMEL #define CONFIG_SF_DEFAULT_BUS 0 #define CONFIG_SF_DEFAULT_CS 0 #define CONFIG_SF_DEFAULT_SPEED 30000000 @@ -51,23 +40,9 @@ #undef CONFIG_CMD_NAND /* MMC */ - #ifdef CONFIG_CMD_MMC -#define CONFIG_MMC #define CONFIG_GENERIC_MMC #define CONFIG_SDHCI -#define CONFIG_ATMEL_SDHCI -#define CONFIG_ATMEL_SDHCI0 -#define CONFIG_ATMEL_SDHCI1 -#define CONFIG_SUPPORT_EMMC_BOOT -#endif - -/* USB */ - -#ifdef CONFIG_CMD_USB -#define CONFIG_USB_EHCI -#define CONFIG_USB_EHCI_ATMEL -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 3 #endif /* USB device */ From 7bfaa0ceb8d938df680223dde14ef2234ab69587 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 17 Oct 2016 09:55:24 +0800 Subject: [PATCH 17/20] board: sama5d2_xplained: Clean up code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the introduction of pinctrl and clk driver, and the dts file, remove unneeded the pin configurations and the clock enabling code. Signed-off-by: Wenyou Yang Reviewed-by: Simon Glass Reviewed-by: Andreas Bießmann --- .../atmel/sama5d2_xplained/sama5d2_xplained.c | 104 ------------------ 1 file changed, 104 deletions(-) diff --git a/board/atmel/sama5d2_xplained/sama5d2_xplained.c b/board/atmel/sama5d2_xplained/sama5d2_xplained.c index 413a000d227..7ccadf214a1 100644 --- a/board/atmel/sama5d2_xplained/sama5d2_xplained.c +++ b/board/atmel/sama5d2_xplained/sama5d2_xplained.c @@ -25,34 +25,6 @@ DECLARE_GLOBAL_DATA_PTR; -#ifndef CONFIG_DM_SPI -int spi_cs_is_valid(unsigned int bus, unsigned int cs) -{ - return bus == 0 && cs == 0; -} -#endif - -void spi_cs_activate(struct spi_slave *slave) -{ - atmel_pio4_set_pio_output(AT91_PIO_PORTA, 17, 0); -} - -void spi_cs_deactivate(struct spi_slave *slave) -{ - atmel_pio4_set_pio_output(AT91_PIO_PORTA, 17, 1); -} - -static void board_spi0_hw_init(void) -{ - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 14, 0); - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 15, 0); - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 16, 0); - - atmel_pio4_set_pio_output(AT91_PIO_PORTA, 17, 1); - - at91_periph_clk_enable(ATMEL_ID_SPI0); -} - static void board_usb_hw_init(void) { atmel_pio4_set_pio_output(AT91_PIO_PORTB, 10, 1); @@ -159,55 +131,6 @@ static void board_gmac_hw_init(void) at91_periph_clk_enable(ATMEL_ID_GMAC); } -static void board_sdhci0_hw_init(void) -{ - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 0, 0); /* SDMMC0_CK */ - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 1, 0); /* SDMMC0_CMD */ - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 2, 0); /* SDMMC0_DAT0 */ - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 3, 0); /* SDMMC0_DAT1 */ - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 4, 0); /* SDMMC0_DAT2 */ - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 5, 0); /* SDMMC0_DAT3 */ - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 6, 0); /* SDMMC0_DAT4 */ - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 7, 0); /* SDMMC0_DAT5 */ - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 8, 0); /* SDMMC0_DAT6 */ - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 9, 0); /* SDMMC0_DAT7 */ - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 10, 0); /* SDMMC0_RSTN */ - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 11, 0); /* SDMMC0_VDDSEL */ - atmel_pio4_set_a_periph(AT91_PIO_PORTA, 13, 0); /* SDMMC0_CD */ - - at91_periph_clk_enable(ATMEL_ID_SDMMC0); - at91_enable_periph_generated_clk(ATMEL_ID_SDMMC0, - GCK_CSS_UPLL_CLK, 1); -} - -static void board_sdhci1_hw_init(void) -{ - atmel_pio4_set_e_periph(AT91_PIO_PORTA, 18, 0); /* SDMMC1_DAT0 */ - atmel_pio4_set_e_periph(AT91_PIO_PORTA, 19, 0); /* SDMMC1_DAT1 */ - atmel_pio4_set_e_periph(AT91_PIO_PORTA, 20, 0); /* SDMMC1_DAT2 */ - atmel_pio4_set_e_periph(AT91_PIO_PORTA, 21, 0); /* SDMMC1_DAT3 */ - atmel_pio4_set_e_periph(AT91_PIO_PORTA, 22, 0); /* SDMMC1_CK */ - atmel_pio4_set_e_periph(AT91_PIO_PORTA, 27, 0); /* SDMMC1_RSTN */ - atmel_pio4_set_e_periph(AT91_PIO_PORTA, 28, 0); /* SDMMC1_CMD */ - atmel_pio4_set_e_periph(AT91_PIO_PORTA, 30, 0); /* SDMMC1_CD */ - - at91_periph_clk_enable(ATMEL_ID_SDMMC1); - at91_enable_periph_generated_clk(ATMEL_ID_SDMMC1, - GCK_CSS_UPLL_CLK, 1); -} - -int board_mmc_init(bd_t *bis) -{ -#ifdef CONFIG_ATMEL_SDHCI0 - atmel_sdhci_init((void *)ATMEL_BASE_SDMMC0, ATMEL_ID_SDMMC0); -#endif -#ifdef CONFIG_ATMEL_SDHCI1 - atmel_sdhci_init((void *)ATMEL_BASE_SDMMC1, ATMEL_ID_SDMMC1); -#endif - - return 0; -} - static void board_uart1_hw_init(void) { atmel_pio4_set_a_periph(AT91_PIO_PORTD, 2, 1); /* URXD1 */ @@ -218,11 +141,6 @@ static void board_uart1_hw_init(void) int board_early_init_f(void) { - at91_periph_clk_enable(ATMEL_ID_PIOA); - at91_periph_clk_enable(ATMEL_ID_PIOB); - at91_periph_clk_enable(ATMEL_ID_PIOC); - at91_periph_clk_enable(ATMEL_ID_PIOD); - board_uart1_hw_init(); return 0; @@ -233,17 +151,6 @@ int board_init(void) /* address of boot parameters */ gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; -#ifdef CONFIG_ATMEL_SPI - board_spi0_hw_init(); -#endif -#ifdef CONFIG_ATMEL_SDHCI -#ifdef CONFIG_ATMEL_SDHCI0 - board_sdhci0_hw_init(); -#endif -#ifdef CONFIG_ATMEL_SDHCI1 - board_sdhci1_hw_init(); -#endif -#endif #ifdef CONFIG_MACB board_gmac_hw_init(); #endif @@ -289,17 +196,6 @@ int board_eth_init(bd_t *bis) #ifdef CONFIG_SPL_BUILD void spl_board_init(void) { -#ifdef CONFIG_SYS_USE_SERIALFLASH - board_spi0_hw_init(); -#endif -#ifdef CONFIG_ATMEL_SDHCI -#ifdef CONFIG_ATMEL_SDHCI0 - board_sdhci0_hw_init(); -#endif -#ifdef CONFIG_ATMEL_SDHCI1 - board_sdhci1_hw_init(); -#endif -#endif } static void ddrc_conf(struct atmel_mpddrc_config *ddrc) From 0daa2e1870762ebf0a9ae97a6a923e938faddbc4 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 17 Oct 2016 09:55:25 +0800 Subject: [PATCH 18/20] board: sama5d2_xplained: Set 'ethaddr' got from AT24MAC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If 'ethaddr' is not set, we will get the ethernet address from AT24MAC, and set it to 'ethaddr' variable. Signed-off-by: Wenyou Yang Signed-off-by: Songjun Wu Reviewed-by: Andreas Bießmann --- .../atmel/sama5d2_xplained/sama5d2_xplained.c | 51 +++++++++++++++++++ include/configs/sama5d2_xplained.h | 6 +++ 2 files changed, 57 insertions(+) diff --git a/board/atmel/sama5d2_xplained/sama5d2_xplained.c b/board/atmel/sama5d2_xplained/sama5d2_xplained.c index 7ccadf214a1..cceccd2ac45 100644 --- a/board/atmel/sama5d2_xplained/sama5d2_xplained.c +++ b/board/atmel/sama5d2_xplained/sama5d2_xplained.c @@ -7,6 +7,8 @@ #include #include +#include +#include #include #include #include @@ -192,6 +194,55 @@ int board_eth_init(bd_t *bis) return rc; } +#ifdef CONFIG_CMD_I2C +static int set_ethaddr_from_eeprom(void) +{ + const int ETH_ADDR_LEN = 6; + unsigned char ethaddr[ETH_ADDR_LEN]; + const char *ETHADDR_NAME = "ethaddr"; + struct udevice *bus, *dev; + + if (getenv(ETHADDR_NAME)) + return 0; + + if (uclass_get_device_by_seq(UCLASS_I2C, 1, &bus)) { + printf("Cannot find I2C bus 1\n"); + return -1; + } + + if (dm_i2c_probe(bus, AT24MAC_ADDR, 0, &dev)) { + printf("Failed to probe I2C chip\n"); + return -1; + } + + if (dm_i2c_read(dev, AT24MAC_REG, ethaddr, ETH_ADDR_LEN)) { + printf("Failed to read ethernet address from EEPROM\n"); + return -1; + } + + if (!is_valid_ethaddr(ethaddr)) { + printf("The ethernet address read from EEPROM is not valid!\n"); + return -1; + } + + return eth_setenv_enetaddr(ETHADDR_NAME, ethaddr); +} +#else +static int set_ethaddr_from_eeprom(void) +{ + return 0; +} +#endif + +#ifdef CONFIG_MISC_INIT_R +int misc_init_r(void) +{ + set_ethaddr_from_eeprom(); + + return 0; +} +#endif + /* SPL */ #ifdef CONFIG_SPL_BUILD void spl_board_init(void) diff --git a/include/configs/sama5d2_xplained.h b/include/configs/sama5d2_xplained.h index 435956d75ad..7fb2bdcd4c2 100644 --- a/include/configs/sama5d2_xplained.h +++ b/include/configs/sama5d2_xplained.h @@ -15,6 +15,8 @@ #include "at91-sama5_common.h" +#define CONFIG_MISC_INIT_R + /* SDRAM */ #define CONFIG_NR_DRAM_BANKS 1 #define CONFIG_SYS_SDRAM_BASE ATMEL_BASE_DDRCS @@ -54,6 +56,10 @@ #define CONFIG_DOS_PARTITION #endif +/* I2C */ +#define AT24MAC_ADDR 0x5c +#define AT24MAC_REG 0x9a + /* Ethernet Hardware */ #define CONFIG_MACB #define CONFIG_RMII From 2992dd833d11cd988125b11ae72bc18e53b0b2ab Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Mon, 17 Oct 2016 09:55:26 +0800 Subject: [PATCH 19/20] board: sama5d2_xplained: Enable an early debug UART MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable an early debug UART to debug problems when an ICE or other debug mechanism is not available. Signed-off-by: Wenyou Yang Reviewed-by: Simon Glass Reviewed-by: Andreas Bießmann --- board/atmel/sama5d2_xplained/sama5d2_xplained.c | 16 +++++++++++++++- configs/sama5d2_xplained_mmc_defconfig | 6 ++++++ configs/sama5d2_xplained_spiflash_defconfig | 6 ++++++ include/configs/sama5d2_xplained.h | 2 ++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/board/atmel/sama5d2_xplained/sama5d2_xplained.c b/board/atmel/sama5d2_xplained/sama5d2_xplained.c index cceccd2ac45..c5337af4de6 100644 --- a/board/atmel/sama5d2_xplained/sama5d2_xplained.c +++ b/board/atmel/sama5d2_xplained/sama5d2_xplained.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -141,12 +142,25 @@ static void board_uart1_hw_init(void) at91_periph_clk_enable(ATMEL_ID_UART1); } -int board_early_init_f(void) +#ifdef CONFIG_DEBUG_UART_BOARD_INIT +void board_debug_uart_init(void) { board_uart1_hw_init(); +} +#endif + +#ifdef CONFIG_BOARD_EARLY_INIT_F +int board_early_init_f(void) +{ +#ifdef CONFIG_DEBUG_UART + debug_uart_init(); +#else + board_uart1_hw_init(); +#endif return 0; } +#endif int board_init(void) { diff --git a/configs/sama5d2_xplained_mmc_defconfig b/configs/sama5d2_xplained_mmc_defconfig index 08ecea64011..8a786f1a062 100644 --- a/configs/sama5d2_xplained_mmc_defconfig +++ b/configs/sama5d2_xplained_mmc_defconfig @@ -52,6 +52,12 @@ CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_ATMEL=y CONFIG_PINCTRL=y CONFIG_PINCTRL_AT91PIO4=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_ATMEL=y +CONFIG_DEBUG_UART_BASE=0xf8020000 +CONFIG_DEBUG_UART_CLOCK=0 +CONFIG_DEBUG_UART_BOARD_INIT=y +CONFIG_DEBUG_UART_ANNOUNCE=y CONFIG_ATMEL_USART=y CONFIG_DM_SPI=y CONFIG_ATMEL_SPI=y diff --git a/configs/sama5d2_xplained_spiflash_defconfig b/configs/sama5d2_xplained_spiflash_defconfig index b49d2adf676..51594e71f71 100644 --- a/configs/sama5d2_xplained_spiflash_defconfig +++ b/configs/sama5d2_xplained_spiflash_defconfig @@ -51,6 +51,12 @@ CONFIG_SPI_FLASH=y CONFIG_SPI_FLASH_ATMEL=y CONFIG_PINCTRL=y CONFIG_PINCTRL_AT91PIO4=y +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_ATMEL=y +CONFIG_DEBUG_UART_BASE=0xf8020000 +CONFIG_DEBUG_UART_CLOCK=0 +CONFIG_DEBUG_UART_BOARD_INIT=y +CONFIG_DEBUG_UART_ANNOUNCE=y CONFIG_ATMEL_USART=y CONFIG_DM_SPI=y CONFIG_ATMEL_SPI=y diff --git a/include/configs/sama5d2_xplained.h b/include/configs/sama5d2_xplained.h index 7fb2bdcd4c2..f6946453e5d 100644 --- a/include/configs/sama5d2_xplained.h +++ b/include/configs/sama5d2_xplained.h @@ -15,6 +15,8 @@ #include "at91-sama5_common.h" +#define CONFIG_BOARD_EARLY_INIT_F + #define CONFIG_MISC_INIT_R /* SDRAM */ From 0eafd4b77615efdd948e698d83be746dcf026a53 Mon Sep 17 00:00:00 2001 From: Wenyou Yang Date: Fri, 28 Oct 2016 14:17:49 +0800 Subject: [PATCH 20/20] dm: at91: Add driver model support for the spi driver Add driver model support while retaining the existing legacy code. This allows the driver to support boards that have converted to driver model as well as those that have not. Signed-off-by: Wenyou Yang Reviewed-by: Simon Glass Acked-by: Stephen Warren --- drivers/spi/Kconfig | 8 ++ drivers/spi/atmel_spi.c | 288 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 296 insertions(+) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 8724f87c498..0f51b3a21b8 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -32,6 +32,14 @@ config ATH79_SPI uses driver model and requires a device tree binding to operate. please refer to doc/device-tree-bindings/spi/spi-ath79.txt. +config ATMEL_SPI + bool "Atmel SPI driver" + depends on ARCH_AT91 + help + This enables driver for the Atmel SPI Controller, present on + many AT32 (AVR32) and AT91 (ARM) chips. This driver can be + used to access the SPI Flash, such as AT25DF321. + config CADENCE_QSPI bool "Cadence QSPI driver" help diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index ed6278b86fd..76491142318 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -4,16 +4,30 @@ * SPDX-License-Identifier: GPL-2.0+ */ #include +#include +#include +#include #include #include +#include #include #include #include +#ifdef CONFIG_DM_SPI +#include +#endif +#ifdef CONFIG_DM_GPIO +#include +#endif #include "atmel_spi.h" +DECLARE_GLOBAL_DATA_PTR; + +#ifndef CONFIG_DM_SPI + static int spi_has_wdrbt(struct atmel_spi_slave *slave) { unsigned int ver; @@ -209,3 +223,277 @@ out: return 0; } + +#else + +#define MAX_CS_COUNT 4 + +struct atmel_spi_platdata { + struct at91_spi *regs; +}; + +struct atmel_spi_priv { + unsigned int freq; /* Default frequency */ + unsigned int mode; + ulong bus_clk_rate; + struct gpio_desc cs_gpios[MAX_CS_COUNT]; +}; + +static int atmel_spi_claim_bus(struct udevice *dev) +{ + struct udevice *bus = dev_get_parent(dev); + struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); + struct atmel_spi_priv *priv = dev_get_priv(bus); + struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); + struct at91_spi *reg_base = bus_plat->regs; + u32 cs = slave_plat->cs; + u32 freq = priv->freq; + u32 scbr, csrx, mode; + + scbr = (priv->bus_clk_rate + freq - 1) / freq; + if (scbr > ATMEL_SPI_CSRx_SCBR_MAX) + return -EINVAL; + + if (scbr < 1) + scbr = 1; + + csrx = ATMEL_SPI_CSRx_SCBR(scbr); + csrx |= ATMEL_SPI_CSRx_BITS(ATMEL_SPI_BITS_8); + + if (!(priv->mode & SPI_CPHA)) + csrx |= ATMEL_SPI_CSRx_NCPHA; + if (priv->mode & SPI_CPOL) + csrx |= ATMEL_SPI_CSRx_CPOL; + + writel(csrx, ®_base->csr[cs]); + + mode = ATMEL_SPI_MR_MSTR | + ATMEL_SPI_MR_MODFDIS | + ATMEL_SPI_MR_WDRBT | + ATMEL_SPI_MR_PCS(~(1 << cs)); + + writel(mode, ®_base->mr); + + writel(ATMEL_SPI_CR_SPIEN, ®_base->cr); + + return 0; +} + +static int atmel_spi_release_bus(struct udevice *dev) +{ + struct udevice *bus = dev_get_parent(dev); + struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); + + writel(ATMEL_SPI_CR_SPIDIS, &bus_plat->regs->cr); + + return 0; +} + +static void atmel_spi_cs_activate(struct udevice *dev) +{ + struct udevice *bus = dev_get_parent(dev); + struct atmel_spi_priv *priv = dev_get_priv(bus); + struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); + u32 cs = slave_plat->cs; + + dm_gpio_set_value(&priv->cs_gpios[cs], 0); +} + +static void atmel_spi_cs_deactivate(struct udevice *dev) +{ + struct udevice *bus = dev_get_parent(dev); + struct atmel_spi_priv *priv = dev_get_priv(bus); + struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); + u32 cs = slave_plat->cs; + + dm_gpio_set_value(&priv->cs_gpios[cs], 1); +} + +static int atmel_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct udevice *bus = dev_get_parent(dev); + struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); + struct at91_spi *reg_base = bus_plat->regs; + + u32 len_tx, len_rx, len; + u32 status; + const u8 *txp = dout; + u8 *rxp = din; + u8 value; + + if (bitlen == 0) + goto out; + + /* + * The controller can do non-multiple-of-8 bit + * transfers, but this driver currently doesn't support it. + * + * It's also not clear how such transfers are supposed to be + * represented as a stream of bytes...this is a limitation of + * the current SPI interface. + */ + if (bitlen % 8) { + /* Errors always terminate an ongoing transfer */ + flags |= SPI_XFER_END; + goto out; + } + + len = bitlen / 8; + + /* + * The controller can do automatic CS control, but it is + * somewhat quirky, and it doesn't really buy us much anyway + * in the context of U-Boot. + */ + if (flags & SPI_XFER_BEGIN) { + atmel_spi_cs_activate(dev); + + /* + * sometimes the RDR is not empty when we get here, + * in theory that should not happen, but it DOES happen. + * Read it here to be on the safe side. + * That also clears the OVRES flag. Required if the + * following loop exits due to OVRES! + */ + readl(®_base->rdr); + } + + for (len_tx = 0, len_rx = 0; len_rx < len; ) { + status = readl(®_base->sr); + + if (status & ATMEL_SPI_SR_OVRES) + return -1; + + if ((len_tx < len) && (status & ATMEL_SPI_SR_TDRE)) { + if (txp) + value = *txp++; + else + value = 0; + writel(value, ®_base->tdr); + len_tx++; + } + + if (status & ATMEL_SPI_SR_RDRF) { + value = readl(®_base->rdr); + if (rxp) + *rxp++ = value; + len_rx++; + } + } + +out: + if (flags & SPI_XFER_END) { + /* + * Wait until the transfer is completely done before + * we deactivate CS. + */ + wait_for_bit(__func__, ®_base->sr, + ATMEL_SPI_SR_TXEMPTY, true, 1000, false); + + atmel_spi_cs_deactivate(dev); + } + + return 0; +} + +static int atmel_spi_set_speed(struct udevice *bus, uint speed) +{ + struct atmel_spi_priv *priv = dev_get_priv(bus); + + priv->freq = speed; + + return 0; +} + +static int atmel_spi_set_mode(struct udevice *bus, uint mode) +{ + struct atmel_spi_priv *priv = dev_get_priv(bus); + + priv->mode = mode; + + return 0; +} + +static const struct dm_spi_ops atmel_spi_ops = { + .claim_bus = atmel_spi_claim_bus, + .release_bus = atmel_spi_release_bus, + .xfer = atmel_spi_xfer, + .set_speed = atmel_spi_set_speed, + .set_mode = atmel_spi_set_mode, + /* + * cs_info is not needed, since we require all chip selects to be + * in the device tree explicitly + */ +}; + +static int atmel_spi_enable_clk(struct udevice *bus) +{ + struct atmel_spi_priv *priv = dev_get_priv(bus); + struct clk clk; + ulong clk_rate; + int ret; + + ret = clk_get_by_index(bus, 0, &clk); + if (ret) + return -EINVAL; + + ret = clk_enable(&clk); + if (ret) + return ret; + + clk_rate = clk_get_rate(&clk); + if (!clk_rate) + return -EINVAL; + + priv->bus_clk_rate = clk_rate; + + clk_free(&clk); + + return 0; +} + +static int atmel_spi_probe(struct udevice *bus) +{ + struct atmel_spi_platdata *bus_plat = dev_get_platdata(bus); + struct atmel_spi_priv *priv = dev_get_priv(bus); + int i, ret; + + ret = atmel_spi_enable_clk(bus); + if (ret) + return ret; + + bus_plat->regs = (struct at91_spi *)dev_get_addr(bus); + + ret = gpio_request_list_by_name(bus, "cs-gpios", priv->cs_gpios, + ARRAY_SIZE(priv->cs_gpios), 0); + if (ret < 0) { + error("Can't get %s gpios! Error: %d", bus->name, ret); + return ret; + } + + for(i = 0; i < ARRAY_SIZE(priv->cs_gpios); i++) { + dm_gpio_set_dir_flags(&priv->cs_gpios[i], + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + } + + writel(ATMEL_SPI_CR_SWRST, &bus_plat->regs->cr); + + return 0; +} + +static const struct udevice_id atmel_spi_ids[] = { + { .compatible = "atmel,at91rm9200-spi" }, + { } +}; + +U_BOOT_DRIVER(atmel_spi) = { + .name = "atmel_spi", + .id = UCLASS_SPI, + .of_match = atmel_spi_ids, + .ops = &atmel_spi_ops, + .platdata_auto_alloc_size = sizeof(struct atmel_spi_platdata), + .priv_auto_alloc_size = sizeof(struct atmel_spi_priv), + .probe = atmel_spi_probe, +}; +#endif