From ffa73e1b91c33b4f69fdf5d8f8653c03d2426aaf Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Mon, 22 Jun 2020 10:42:05 +0200 Subject: ARM: at91: add at91sam9/sama5 reset reason detection The reset controller status register contains information about the last reset's cause. Tell barebox about it. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/at91sam9_rst.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/at91sam9_rst.c b/arch/arm/mach-at91/at91sam9_rst.c index 8f03576e69..a61a26936f 100644 --- a/arch/arm/mach-at91/at91sam9_rst.c +++ b/arch/arm/mach-at91/at91sam9_rst.c @@ -7,14 +7,42 @@ #include #include #include +#include #include #include +#include struct at91sam9x_rst { struct restart_handler restart; void __iomem *base; }; +static int reasons[] = { + RESET_POR, /* GENERAL Both VDDCORE and VDDBU rising */ + RESET_WKE, /* WAKEUP VDDCORE rising */ + RESET_WDG, /* WATCHDOG Watchdog fault occurred */ + RESET_RST, /* SOFTWARE Reset required by the software */ + RESET_EXT, /* USER NRST pin detected low */ +}; + +static void at91sam9x_set_reset_reason(struct device_d *dev, + void __iomem *base) +{ + enum reset_src_type type = RESET_UKWN; + u32 sr, rsttyp; + + sr = readl(base + AT91_RSTC_SR); + rsttyp = FIELD_GET(AT91_RSTC_RSTTYP, sr); + + if (rsttyp < ARRAY_SIZE(reasons)) + type = reasons[rsttyp]; + + dev_info(dev, "reset reason %s (RSTC_SR: 0x%05x)\n", + reset_source_to_string(type), sr); + + reset_source_set(type); +} + static void __noreturn at91sam9x_restart_soc(struct restart_handler *rst) { struct at91sam9x_rst *priv = container_of(rst, struct at91sam9x_rst, restart); @@ -52,6 +80,8 @@ static int at91sam9x_rst_probe(struct device_d *dev) clk_enable(clk); + at91sam9x_set_reset_reason(dev, priv->base); + priv->restart.name = "at91sam9x-rst"; priv->restart.restart = at91sam9x_restart_soc; -- cgit v1.2.3 From 238cf3326ac1ec009173c85fa664889d5cb57bdb Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Mon, 22 Jun 2020 11:53:52 +0200 Subject: ARM: at91: choose proper parent for both MCI clocks When booting from SDMMC0, Use of SDMMC1 fails with: ERROR: clk: couldn't set sdmmc1_gclk clk rate to 480000000 (-22), current rate: 32768 This is because the first stage bootloader only reparents the boot SDMMC instance and barebox does no automatic reparenting for the other one. Force both clocks to have a suitable parent. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/dts/sama5d2.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/dts/sama5d2.dtsi b/arch/arm/dts/sama5d2.dtsi index 51e964fc0f..fadcc83815 100644 --- a/arch/arm/dts/sama5d2.dtsi +++ b/arch/arm/dts/sama5d2.dtsi @@ -6,3 +6,11 @@ mmc1 = &sdmmc1; }; }; + +&sdmmc0 { + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; +}; + +&sdmmc1 { + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; +}; -- cgit v1.2.3 From 5ecc4063f5f435b24987239a9211fe676fdcaa15 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:10:55 +0200 Subject: ARM: at91: remove include from assembly code They are unused and force all headers included by it to have __ASSEMBLY__ guards for non-preprocessor code. Avoid this. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/at91sam9_reset.S | 1 - arch/arm/mach-at91/at91sam9g45_reset.S | 1 - 2 files changed, 2 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/at91sam9_reset.S b/arch/arm/mach-at91/at91sam9_reset.S index 65e22f4fe7..ba3f768331 100644 --- a/arch/arm/mach-at91/at91sam9_reset.S +++ b/arch/arm/mach-at91/at91sam9_reset.S @@ -14,7 +14,6 @@ */ #include -#include #include #include diff --git a/arch/arm/mach-at91/at91sam9g45_reset.S b/arch/arm/mach-at91/at91sam9g45_reset.S index 6a58de618c..98db15c0b0 100644 --- a/arch/arm/mach-at91/at91sam9g45_reset.S +++ b/arch/arm/mach-at91/at91sam9g45_reset.S @@ -11,7 +11,6 @@ */ #include -#include #include #include -- cgit v1.2.3 From 66cfbb08d8197b7686ed911c2762a610aaa099a3 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:10:56 +0200 Subject: ARM: at91: sama5d2: cast peripheral base addresses to __iomem pointers The peripheral addresses should be always cast with IOMEM() anyway, so do this directly in the header to make user code less verbose. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/boards/sama5d27-giantboard/lowlevel.c | 6 +- arch/arm/boards/sama5d27-som1/lowlevel.c | 14 +- arch/arm/mach-at91/include/mach/sama5d2.h | 169 +++++++++++++------------ 3 files changed, 96 insertions(+), 93 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/boards/sama5d27-giantboard/lowlevel.c b/arch/arm/boards/sama5d27-giantboard/lowlevel.c index 0236c424c1..50bc2613c6 100644 --- a/arch/arm/boards/sama5d27-giantboard/lowlevel.c +++ b/arch/arm/boards/sama5d27-giantboard/lowlevel.c @@ -20,7 +20,7 @@ static inline void sama5d2_pmc_enable_periph_clock(int clk) { - at91_pmc_sam9x5_enable_periph_clock(IOMEM(SAMA5D2_BASE_PMC), clk); + at91_pmc_sam9x5_enable_periph_clock(SAMA5D2_BASE_PMC, clk); } static void dbgu_init(void) @@ -29,12 +29,12 @@ static void dbgu_init(void) sama5d2_pmc_enable_periph_clock(SAMA5D2_ID_PIOD); - at91_mux_pio4_set_A_periph(IOMEM(SAMA5D2_BASE_PIOD), + at91_mux_pio4_set_A_periph(SAMA5D2_BASE_PIOD, pin_to_mask(AT91_PIN_PD3)); /* DBGU TXD */ sama5d2_pmc_enable_periph_clock(SAMA5D2_ID_UART1); - at91_dbgu_setup_ll(IOMEM(SAMA5D2_BASE_UART1), mck, 115200); + at91_dbgu_setup_ll(SAMA5D2_BASE_UART1, mck, 115200); putc_ll('>'); } diff --git a/arch/arm/boards/sama5d27-som1/lowlevel.c b/arch/arm/boards/sama5d27-som1/lowlevel.c index 62d35be912..569960be44 100644 --- a/arch/arm/boards/sama5d27-som1/lowlevel.c +++ b/arch/arm/boards/sama5d27-som1/lowlevel.c @@ -24,13 +24,13 @@ static inline void sama5d2_pmc_enable_periph_clock(int clk) { - at91_pmc_sam9x5_enable_periph_clock(IOMEM(SAMA5D2_BASE_PMC), clk); + at91_pmc_sam9x5_enable_periph_clock(SAMA5D2_BASE_PMC, clk); } static void ek_turn_led(unsigned color) { struct { - unsigned long pio; + void __iomem *pio; unsigned bit; unsigned color; } *led, leds[] = { @@ -41,9 +41,9 @@ static void ek_turn_led(unsigned color) }; for (led = leds; led->pio; led++) { - at91_mux_gpio4_enable(IOMEM(led->pio), BIT(led->bit)); - at91_mux_gpio4_input(IOMEM(led->pio), BIT(led->bit), false); - at91_mux_gpio4_set(IOMEM(led->pio), BIT(led->bit), led->color); + at91_mux_gpio4_enable(led->pio, BIT(led->bit)); + at91_mux_gpio4_input(led->pio, BIT(led->bit), false); + at91_mux_gpio4_set(led->pio, BIT(led->bit), led->color); } } @@ -53,12 +53,12 @@ static void ek_dbgu_init(void) sama5d2_pmc_enable_periph_clock(SAMA5D2_ID_PIOD); - at91_mux_pio4_set_A_periph(IOMEM(SAMA5D2_BASE_PIOD), + at91_mux_pio4_set_A_periph(SAMA5D2_BASE_PIOD, pin_to_mask(AT91_PIN_PD3)); /* DBGU TXD */ sama5d2_pmc_enable_periph_clock(SAMA5D2_ID_UART1); - at91_dbgu_setup_ll(IOMEM(SAMA5D2_BASE_UART1), mck, 115200); + at91_dbgu_setup_ll(SAMA5D2_BASE_UART1, mck, 115200); putc_ll('>'); } diff --git a/arch/arm/mach-at91/include/mach/sama5d2.h b/arch/arm/mach-at91/include/mach/sama5d2.h index 3dad7d9c9c..ada9c59e03 100644 --- a/arch/arm/mach-at91/include/mach/sama5d2.h +++ b/arch/arm/mach-at91/include/mach/sama5d2.h @@ -14,6 +14,9 @@ #ifndef SAMA5D2_H #define SAMA5D2_H +#include +#include + /* * Peripheral identifiers/interrupts. (Table 18-9) */ @@ -101,100 +104,100 @@ * User Peripheral physical base addresses. */ -#define SAMA5D2_BASE_LCDC 0xf0000000 -#define SAMA5D2_BASE_XDMAC1 0xf0004000 -#define SAMA5D2_BASE_HXISI 0xf0008000 -#define SAMA5D2_BASE_MPDDRC 0xf000c000 -#define SAMA5D2_BASE_XDMAC0 0xf0010000 -#define SAMA5D2_BASE_PMC 0xf0014000 -#define SAMA5D2_BASE_MATRIX64 0xf0018000 /* MATRIX0 */ -#define SAMA5D2_BASE_AESB 0xf001c000 -#define SAMA5D2_BASE_QSPI0 0xf0020000 -#define SAMA5D2_BASE_QSPI1 0xf0024000 -#define SAMA5D2_BASE_SHA 0xf0028000 -#define SAMA5D2_BASE_AES 0xf002c000 +#define SAMA5D2_BASE_LCDC IOMEM(0xf0000000) +#define SAMA5D2_BASE_XDMAC1 IOMEM(0xf0004000) +#define SAMA5D2_BASE_HXISI IOMEM(0xf0008000) +#define SAMA5D2_BASE_MPDDRC IOMEM(0xf000c000) +#define SAMA5D2_BASE_XDMAC0 IOMEM(0xf0010000) +#define SAMA5D2_BASE_PMC IOMEM(0xf0014000) +#define SAMA5D2_BASE_MATRIX64 IOMEM(0xf0018000) /* MATRIX0 */ +#define SAMA5D2_BASE_AESB IOMEM(0xf001c000) +#define SAMA5D2_BASE_QSPI0 IOMEM(0xf0020000) +#define SAMA5D2_BASE_QSPI1 IOMEM(0xf0024000) +#define SAMA5D2_BASE_SHA IOMEM(0xf0028000) +#define SAMA5D2_BASE_AES IOMEM(0xf002c000) -#define SAMA5D2_BASE_SPI0 0xf8000000 -#define SAMA5D2_BASE_SSC0 0xf8004000 -#define SAMA5D2_BASE_GMAC 0xf8008000 -#define SAMA5D2_BASE_TC0 0xf800c000 -#define SAMA5D2_BASE_TC1 0xf8010000 -#define SAMA5D2_BASE_HSMC 0xf8014000 -#define SAMA5D2_BASE_PDMIC 0xf8018000 -#define SAMA5D2_BASE_UART0 0xf801c000 -#define SAMA5D2_BASE_UART1 0xf8020000 -#define SAMA5D2_BASE_UART2 0xf8024000 -#define SAMA5D2_BASE_TWI0 0xf8028000 -#define SAMA5D2_BASE_PWMC 0xf802c000 -#define SAMA5D2_BASE_SFR 0xf8030000 -#define SAMA5D2_BASE_FLEXCOM0 0xf8034000 -#define SAMA5D2_BASE_FLEXCOM1 0xf8038000 -#define SAMA5D2_BASE_SAIC 0xf803c000 -#define SAMA5D2_BASE_ICM 0xf8040000 -#define SAMA5D2_BASE_SECURAM 0xf8044000 -#define SAMA5D2_BASE_SYSC 0xf8048000 -#define SAMA5D2_BASE_ACC 0xf804a000 -#define SAMA5D2_BASE_SFC 0xf804c000 -#define SAMA5D2_BASE_I2SC0 0xf8050000 -#define SAMA5D2_BASE_CAN0 0xf8054000 +#define SAMA5D2_BASE_SPI0 IOMEM(0xf8000000) +#define SAMA5D2_BASE_SSC0 IOMEM(0xf8004000) +#define SAMA5D2_BASE_GMAC IOMEM(0xf8008000) +#define SAMA5D2_BASE_TC0 IOMEM(0xf800c000) +#define SAMA5D2_BASE_TC1 IOMEM(0xf8010000) +#define SAMA5D2_BASE_HSMC IOMEM(0xf8014000) +#define SAMA5D2_BASE_PDMIC IOMEM(0xf8018000) +#define SAMA5D2_BASE_UART0 IOMEM(0xf801c000) +#define SAMA5D2_BASE_UART1 IOMEM(0xf8020000) +#define SAMA5D2_BASE_UART2 IOMEM(0xf8024000) +#define SAMA5D2_BASE_TWI0 IOMEM(0xf8028000) +#define SAMA5D2_BASE_PWMC IOMEM(0xf802c000) +#define SAMA5D2_BASE_SFR IOMEM(0xf8030000) +#define SAMA5D2_BASE_FLEXCOM0 IOMEM(0xf8034000) +#define SAMA5D2_BASE_FLEXCOM1 IOMEM(0xf8038000) +#define SAMA5D2_BASE_SAIC IOMEM(0xf803c000) +#define SAMA5D2_BASE_ICM IOMEM(0xf8040000) +#define SAMA5D2_BASE_SECURAM IOMEM(0xf8044000) +#define SAMA5D2_BASE_SYSC IOMEM(0xf8048000) +#define SAMA5D2_BASE_ACC IOMEM(0xf804a000) +#define SAMA5D2_BASE_SFC IOMEM(0xf804c000) +#define SAMA5D2_BASE_I2SC0 IOMEM(0xf8050000) +#define SAMA5D2_BASE_CAN0 IOMEM(0xf8054000) -#define SAMA5D2_BASE_SPI1 0xfc000000 -#define SAMA5D2_BASE_SSC1 0xfc004000 -#define SAMA5D2_BASE_UART3 0xfc008000 -#define SAMA5D2_BASE_UART4 0xfc00c000 -#define SAMA5D2_BASE_FLEXCOM2 0xfc010000 -#define SAMA5D2_BASE_FLEXCOM3 0xfc014000 -#define SAMA5D2_BASE_FLEXCOM4 0xfc018000 -#define SAMA5D2_BASE_TRNG 0xfc01c000 -#define SAMA5D2_BASE_AIC 0xfc020000 -#define SAMA5D2_BASE_TWI1 0xfc028000 -#define SAMA5D2_BASE_UDPHS 0xfc02c000 -#define SAMA5D2_BASE_ADC 0xfc030000 +#define SAMA5D2_BASE_SPI1 IOMEM(0xfc000000) +#define SAMA5D2_BASE_SSC1 IOMEM(0xfc004000) +#define SAMA5D2_BASE_UART3 IOMEM(0xfc008000) +#define SAMA5D2_BASE_UART4 IOMEM(0xfc00c000) +#define SAMA5D2_BASE_FLEXCOM2 IOMEM(0xfc010000) +#define SAMA5D2_BASE_FLEXCOM3 IOMEM(0xfc014000) +#define SAMA5D2_BASE_FLEXCOM4 IOMEM(0xfc018000) +#define SAMA5D2_BASE_TRNG IOMEM(0xfc01c000) +#define SAMA5D2_BASE_AIC IOMEM(0xfc020000) +#define SAMA5D2_BASE_TWI1 IOMEM(0xfc028000) +#define SAMA5D2_BASE_UDPHS IOMEM(0xfc02c000) +#define SAMA5D2_BASE_ADC IOMEM(0xfc030000) -#define SAMA5D2_BASE_PIOA 0xfc038000 -#define SAMA5D2_BASE_MATRIX32 0xfc03c000 /* MATRIX1 */ -#define SAMA5D2_BASE_SECUMOD 0xfc040000 -#define SAMA5D2_BASE_TDES 0xfc044000 -#define SAMA5D2_BASE_CLASSD 0xfc048000 -#define SAMA5D2_BASE_I2SC1 0xfc04c000 -#define SAMA5D2_BASE_CAN1 0xfc050000 -#define SAMA5D2_BASE_SFRBU 0xfc05c000 -#define SAMA5D2_BASE_CHIPID 0xfc069000 +#define SAMA5D2_BASE_PIOA IOMEM(0xfc038000) +#define SAMA5D2_BASE_MATRIX32 IOMEM(0xfc03c000) /* MATRIX1 */ +#define SAMA5D2_BASE_SECUMOD IOMEM(0xfc040000) +#define SAMA5D2_BASE_TDES IOMEM(0xfc044000) +#define SAMA5D2_BASE_CLASSD IOMEM(0xfc048000) +#define SAMA5D2_BASE_I2SC1 IOMEM(0xfc04c000) +#define SAMA5D2_BASE_CAN1 IOMEM(0xfc050000) +#define SAMA5D2_BASE_SFRBU IOMEM(0xfc05c000) +#define SAMA5D2_BASE_CHIPID IOMEM(0xfc069000) /* * Address Memory Space */ -#define SAMA5D2_BASE_INTERNAL_MEM 0x00000000 -#define SAMA5D2_BASE_CS0 0x10000000 -#define SAMA5D2_BASE_DDRCS 0x20000000 -#define SAMA5D2_BASE_DDRCS_AES 0x40000000 -#define SAMA5D2_BASE_CS1 0x60000000 -#define SAMA5D2_BASE_CS2 0x70000000 -#define SAMA5D2_BASE_CS3 0x80000000 -#define SAMA5D2_BASE_QSPI0_AES_MEM 0x90000000 -#define SAMA5D2_BASE_QSPI1_AES_MEM 0x98000000 -#define SAMA5D2_BASE_SDHC0 0xa0000000 -#define SAMA5D2_BASE_SDHC1 0xb0000000 -#define SAMA5D2_BASE_NFC_CMD_REG 0xc0000000 -#define SAMA5D2_BASE_QSPI0_MEM 0xd0000000 -#define SAMA5D2_BASE_QSPI1_MEM 0xd8000000 -#define SAMA5D2_BASE_PERIPH 0xf0000000 +#define SAMA5D2_BASE_INTERNAL_MEM IOMEM(0x00000000) +#define SAMA5D2_BASE_CS0 IOMEM(0x10000000) +#define SAMA5D2_BASE_DDRCS IOMEM(0x20000000) +#define SAMA5D2_BASE_DDRCS_AES IOMEM(0x40000000) +#define SAMA5D2_BASE_CS1 IOMEM(0x60000000) +#define SAMA5D2_BASE_CS2 IOMEM(0x70000000) +#define SAMA5D2_BASE_CS3 IOMEM(0x80000000) +#define SAMA5D2_BASE_QSPI0_AES_MEM IOMEM(0x90000000) +#define SAMA5D2_BASE_QSPI1_AES_MEM IOMEM(0x98000000) +#define SAMA5D2_BASE_SDHC0 IOMEM(0xa0000000) +#define SAMA5D2_BASE_SDHC1 IOMEM(0xb0000000) +#define SAMA5D2_BASE_NFC_CMD_REG IOMEM(0xc0000000) +#define SAMA5D2_BASE_QSPI0_MEM IOMEM(0xd0000000) +#define SAMA5D2_BASE_QSPI1_MEM IOMEM(0xd8000000) +#define SAMA5D2_BASE_PERIPH IOMEM(0xf0000000) /* * Internal Memories */ -#define SAMA5D2_BASE_ROM 0x00000000 /* ROM */ -#define SAMA5D2_BASE_ECC_ROM 0x00060000 /* ECC ROM */ -#define SAMA5D2_BASE_NFC_SRAM 0x00100000 /* NFC SRAM */ -#define SAMA5D2_BASE_SRAM0 0x00200000 /* SRAM0 */ -#define SAMA5D2_BASE_SRAM1 0x00220000 /* SRAM1 */ -#define SAMA5D2_BASE_UDPHS_SRAM 0x00300000 /* UDPHS RAM */ -#define SAMA5D2_BASE_UHP_OHCI 0x00400000 /* UHP OHCI */ -#define SAMA5D2_BASE_UHP_EHCI 0x00500000 /* UHP EHCI */ -#define SAMA5D2_BASE_AXI_MATRIX 0x00600000 /* AXI Maxtrix */ -#define SAMA5D2_BASE_DAP 0x00700000 /* DAP */ -#define SAMA5D2_BASE_PTC 0x00800000 /* PTC */ -#define SAMA5D2_BASE_L2CC 0x00A00000 /* L2CC */ +#define SAMA5D2_BASE_ROM IOMEM(0x00000000) /* ROM */ +#define SAMA5D2_BASE_ECC_ROM IOMEM(0x00060000) /* ECC ROM */ +#define SAMA5D2_BASE_NFC_SRAM 0x00100000 /* NFC SRAM */ +#define SAMA5D2_BASE_SRAM0 0x00200000 /* SRAM0 */ +#define SAMA5D2_BASE_SRAM1 0x00220000 /* SRAM1 */ +#define SAMA5D2_BASE_UDPHS_SRAM 0x00300000 /* UDPHS RAM */ +#define SAMA5D2_BASE_UHP_OHCI IOMEM(0x00400000) /* UHP OHCI */ +#define SAMA5D2_BASE_UHP_EHCI IOMEM(0x00500000) /* UHP EHCI */ +#define SAMA5D2_BASE_AXI_MATRIX IOMEM(0x00600000) /* AXI Maxtrix */ +#define SAMA5D2_BASE_DAP IOMEM(0x00700000) /* DAP */ +#define SAMA5D2_BASE_PTC IOMEM(0x00800000) /* PTC */ +#define SAMA5D2_BASE_L2CC IOMEM(0x00A00000) /* L2CC */ /* * Other misc defines -- cgit v1.2.3 From e026b2ca2f7484dbca18780ceb9e284d21e6b6b2 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:10:57 +0200 Subject: ARM: at91: import at91bootstrap's at91_ddrsdrc.h Instead of adding missing definitions to the existing at91sam9_ddrsdr.h and adapting the incoming DDRAM initialization code from at91bootstrap, just replace the lightly used existing header with: https://github.com/linux4sam/at91bootstrap/blob/v3.8.12/include/arch/at91_ddrsdrc.h For easier comprehension, the replacement is done in three steps: Here the header is imported. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/include/mach/at91_ddrsdrc.h | 295 +++++++++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 arch/arm/mach-at91/include/mach/at91_ddrsdrc.h (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/include/mach/at91_ddrsdrc.h b/arch/arm/mach-at91/include/mach/at91_ddrsdrc.h new file mode 100644 index 0000000000..17e64fcb9a --- /dev/null +++ b/arch/arm/mach-at91/include/mach/at91_ddrsdrc.h @@ -0,0 +1,295 @@ +/* SPDX-License-Identifier: BSD-1-Clause */ +/* + * Copyright (c) 2006, Atmel Corporation + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + */ +#ifndef __AT91_DDRSDRC_H__ +#define __AT91_DDRSDRC_H__ + +/**** Register offset in AT91S_HDDRSDRC2 structure ***/ +#define AT91_HDDRSDRC2_MR 0x00 /* Mode Register */ +#define AT91_HDDRSDRC2_RTR 0x04 /* Refresh Timer Register */ +#define AT91_HDDRSDRC2_CR 0x08 /* Configuration Register */ +#define AT91_HDDRSDRC2_T0PR 0x0C /* Timing Parameter 0 Register */ +#define AT91_HDDRSDRC2_T1PR 0x10 /* Timing Parameter 1 Register */ +#define AT91_HDDRSDRC2_T2PR 0x14 /* Timing Parameter 2 Register */ +#define AT91_HDDRSDRC2_T3PR 0x18 /* Timing Parameter 3 Register */ +#define AT91_HDDRSDRC2_LPR 0x1C /* Low-power Register */ +#define AT91_HDDRSDRC2_MDR 0x20 /* Memory Device Register */ +#define AT91_HDDRSDRC2_DLL 0x24 /* DLL Information Register */ +#define AT91_HDDRSDRC2_HS 0x2C /* High Speed Register */ + +/* below items defined for sama5d3x */ +#define AT91_MPDDRC_LPDDR2_HS 0x24 /* MPDDRC LPDDR2 High Speed Register */ +#define AT91_MPDDRC_LPDDR2_LPR 0x28 /* MPDDRC LPDDR2 Low-power Register */ +#define AT91_MPDDRC_LPDDR2_CAL_MR4 0x2C /* MPDDRC LPDDR2 Calibration and MR4 Register */ +#define AT91_MPDDRC_LPDDR2_TIM_CAL 0x30 /* MPDDRC LPDDR2 Timing Calibration Register */ +#define AT91_MPDDRC_IO_CALIBR 0x34 /* MPDDRC IO Calibration */ +#define AT91_MPDDRC_OCMS 0x38 /* MPDDRC OCMS Register */ +#define AT91_MPDDRC_OCMS_KEY1 0x3C /* MPDDRC OCMS KEY1 Register */ +#define AT91_MPDDRC_OCMS_KEY2 0x40 /* MPDDRC OCMS KEY2 Register */ +/* 0x54 ~ 0x70 Reserved */ +#define AT91_MPDDRC_DLL_MOR 0x74 /* MPDDRC DLL Master Offset Register */ +#define AT91_MPDDRC_DLL_SOR 0x78 /* MPDDRC DLL Slave Offset Register */ +#define AT91_MPDDRC_DLL_MSR 0x7C /* MPDDRC DLL Master Status Register */ +#define AT91_MPDDRC_DLL_S0SR 0x80 /* MPDDRC DLL Slave 0 Status Register */ +#define AT91_MPDDRC_DLL_S1SR 0x84 /* MPDDRC DLL Slave 1 Status Register */ + +#define AT91_MPDDRC_RD_DATA_PATH 0x5C /* MPDDRC Read Data Path */ + +/* 0x94 ~ 0xE0 Reserved */ +#define AT91_HDDRSDRC2_WPCR 0xE4 /* Write Protect Mode Register */ +#define AT91_HDDRSDRC2_WPSR 0xE8 /* Write Protect Status Register */ + +/* -------- HDDRSDRC2_MR : (HDDRSDRC2 Offset: 0x0) Mode Register --------*/ +#define AT91_DDRC2_MODE (0x7UL << 0) +#define AT91_DDRC2_MODE_NORMAL_CMD (0x0UL) +#define AT91_DDRC2_MODE_NOP_CMD (0x1UL) +#define AT91_DDRC2_MODE_PRCGALL_CMD (0x2UL) +#define AT91_DDRC2_MODE_LMR_CMD (0x3UL) +#define AT91_DDRC2_MODE_RFSH_CMD (0x4UL) +#define AT91_DDRC2_MODE_EXT_LMR_CMD (0x5UL) +#define AT91_DDRC2_MODE_DEEP_CMD (0x6UL) +#define AT91_DDRC2_MODE_LPDDR2_CMD (0x7UL) +#define AT91_DDRC2_MRS(value) (value << 8) + +/* -------- HDDRSDRC2_RTR : (HDDRSDRC2 Offset: 0x4) Refresh Timer Register -------- */ +#define AT91_DDRC2_COUNT (0xFFFUL << 0) +#define AT91_DDRC2_ADJ_REF (0x1UL << 16) +#define AT91_DDRC2_DISABLE_ADJ_REF (0x0UL << 16) +#define AT91_DDRC2_ENABLE_ADJ_REF (0x1UL << 16) + +/* -------- HDDRSDRC2_CR : (HDDRSDRC2 Offset: 0x8) Configuration Register --------*/ +#define AT91_DDRC2_NC (0x3UL << 0) +#define AT91_DDRC2_NC_DDR9_SDR8 (0x0UL) +#define AT91_DDRC2_NC_DDR10_SDR9 (0x1UL) +#define AT91_DDRC2_NC_DDR11_SDR10 (0x2UL) +#define AT91_DDRC2_NC_DDR12_SDR11 (0x3UL) +#define AT91_DDRC2_NR (0x3UL << 2) +#define AT91_DDRC2_NR_11 (0x0UL << 2) +#define AT91_DDRC2_NR_12 (0x1UL << 2) +#define AT91_DDRC2_NR_13 (0x2UL << 2) +#define AT91_DDRC2_NR_14 (0x3UL << 2) +#define AT91_DDRC2_CAS (0x7UL << 4) +#define AT91_DDRC2_CAS_2 (0x2UL << 4) +#define AT91_DDRC2_CAS_3 (0x3UL << 4) +#define AT91_DDRC2_CAS_4 (0x4UL << 4) +#define AT91_DDRC2_CAS_5 (0x5UL << 4) +#define AT91_DDRC2_CAS_6 (0x6UL << 4) +#define AT91_DDRC2_RESET_DLL (0x1UL << 7) +#define AT91_DDRC2_DISABLE_RESET_DLL (0x0UL << 7) +#define AT91_DDRC2_ENABLE_RESET_DLL (0x1UL << 7) +#define AT91_DDRC2_DIC_DS (0x1UL << 8) +#define AT91_DDRC2_NORMAL_STRENGTH_RZQ6 (0x0UL << 8) +#define AT91_DDRC2_WEAK_STRENGTH_RZQ7 (0x1UL << 8) +#define AT91_DDRC2_DLL (0x1UL << 9) +#define AT91_DDRC2_ENABLE_DLL (0x0UL << 9) +#define AT91_DDRC2_DISABLE_DLL (0x1UL << 9) +#define AT91_DDRC2_ZQ (0x03 << 10) +#define AT91_DDRC2_ZQ_INIT (0x0 << 10) +#define AT91_DDRC2_ZQ_LONG (0x1 << 10) +#define AT91_DDRC2_ZQ_SHORT (0x2 << 10) +#define AT91_DDRC2_ZQ_RESET (0x3 << 10) +#define AT91_DDRC2_OCD (0x7UL << 12) +#define AT91_DDRC2_OCD_EXIT (0x0UL << 12) +#define AT91_DDRC2_OCD_DEFAULT (0x7UL << 12) +#define AT91_DDRC2_EBISHARE (0x1UL << 16) +#define AT91_DDRC2_DQMS (0x1UL << 16) +#define AT91_DDRC2_DQMS_NOT_SHARED (0x0UL << 16) +#define AT91_DDRC2_DQMS_SHARED (0x1UL << 16) +#define AT91_DDRC2_ENRDM (0x1UL << 17) +#define AT91_DDRC2_ENRDM_DISABLE (0x0UL << 17) +#define AT91_DDRC2_ENRDM_ENABLE (0x1UL << 17) +#define AT91_DDRC2_ACTBST (0x1UL << 18) +#define AT91_DDRC2_NB_BANKS (0x1UL << 20) +#define AT91_DDRC2_NB_BANKS_4 (0x0UL << 20) +#define AT91_DDRC2_NB_BANKS_8 (0x1UL << 20) +#define AT91_DDRC2_NDQS (0x1UL << 21) /* Not DQS(sama5d3x only) */ +#define AT91_DDRC2_NDQS_ENABLED (0x0UL << 21) +#define AT91_DDRC2_NDQS_DISABLED (0x1UL << 21) +#define AT91_DDRC2_DECOD (0x1UL << 22) +#define AT91_DDRC2_DECOD_SEQUENTIAL (0x0UL << 22) +#define AT91_DDRC2_DECOD_INTERLEAVED (0x1UL << 22) +#define AT91_DDRC2_UNAL (0x1UL << 23) /* Support Unaligned Access(sama5d3x only) */ +#define AT91_DDRC2_UNAL_UNSUPPORTED (0x0UL << 23) +#define AT91_DDRC2_UNAL_SUPPORTED (0x1UL << 23) + +/* -------- HDDRSDRC2_T0PR : (HDDRSDRC2 Offset: 0xc) Timing0 Register --------*/ +#define AT91_DDRC2_TRAS (0xFUL << 0) +#define AT91_DDRC2_TRAS_(x) (x & 0x0f) +#define AT91_DDRC2_TRCD (0xFUL << 4) +#define AT91_DDRC2_TRCD_(x) ((x & 0x0f) << 4) +#define AT91_DDRC2_TWR (0xFUL << 8) +#define AT91_DDRC2_TWR_(x) ((x & 0x0f) << 8) +#define AT91_DDRC2_TRC (0xFUL << 12) +#define AT91_DDRC2_TRC_(x) ((x & 0x0f) << 12) +#define AT91_DDRC2_TRP (0xFUL << 16) +#define AT91_DDRC2_TRP_(x) ((x & 0x0f) << 16) +#define AT91_DDRC2_TRRD (0xFUL << 20) +#define AT91_DDRC2_TRRD_(x) ((x & 0x0f) << 20) +#define AT91_DDRC2_TWTR (0xFUL << 24) +#define AT91_DDRC2_TWTR_(x) ((x & 0x0f) << 24) +#define AT91_DDRC2_TMRD (0xFUL << 28) +#define AT91_DDRC2_TMRD_(x) ((x & 0x0f) << 28) + +/* -------- HDDRSDRC2_T1PR : (HDDRSDRC2 Offset: 0x10) Timing1 Register -------- */ +#define AT91_DDRC2_TRFC (0x7FUL << 0) +#define AT91_DDRC2_TRFC_(x) (x & 0x7f) +#define AT91_DDRC2_TXSNR (0xFFUL << 8) +#define AT91_DDRC2_TXSNR_(x) ((x & 0xff) << 8) +#define AT91_DDRC2_TXSRD (0xFFUL << 16) +#define AT91_DDRC2_TXSRD_(x) ((x & 0xff) << 16) +#define AT91_DDRC2_TXP (0xFUL << 24) +#define AT91_DDRC2_TXP_(x) ((x & 0x0f) << 24) + +/* -------- HDDRSDRC2_T2PR : (HDDRSDRC2 Offset: 0x14) Timing2 Register --------*/ +#define AT91_DDRC2_TXARD (0xFUL << 0) +#define AT91_DDRC2_TXARD_(x) (x & 0x0f) +#define AT91_DDRC2_TXARDS (0xFUL << 4) +#define AT91_DDRC2_TXARDS_(x) ((x & 0x0f) << 4) +#define AT91_DDRC2_TRPA (0xFUL << 8) +#define AT91_DDRC2_TRPA_(x) ((x & 0x0f) << 8) +#define AT91_DDRC2_TRT (0xFUL << 12) +#define AT91_DDRC2_TRTP_(x) ((x & 0x0f) << 12) +#define AT91_DDRC2_TFA (0xFUL << 16) +#define AT91_DDRC2_TFAW_(x) ((x & 0x0f) << 16) + +/* -------- HDDRSDRC2_LPR : (HDDRSDRC2 Offset: 0x1c) --------*/ +#define AT91_DDRC2_LPCB (0x3UL << 0) +#define AT91_DDRC2_LPCB_DISABLED (0x0UL) +#define AT91_DDRC2_LPCB_SELFREFRESH (0x1UL) +#define AT91_DDRC2_LPCB_POWERDOWN (0x2UL) +#define AT91_DDRC2_LPCB_DEEP_PWD (0x3UL) +#define AT91_DDRC2_CLK_FR (0x1UL << 2) +#define AT91_DDRC2_PASR (0x7UL << 4) +#define AT91_DDRC2_PASR_(x) ((x & 0x7) << 4) +#define AT91_DDRC2_DS (0x7UL << 8) +#define AT91_DDRC2_DS_(x) ((x & 0x7) << 8) +#define AT91_DDRC2_TIMEOUT (0x3UL << 12) +#define AT91_DDRC2_TIMEOUT_0 (0x0UL << 12) +#define AT91_DDRC2_TIMEOUT_64 (0x1UL << 12) +#define AT91_DDRC2_TIMEOUT_128 (0x2UL << 12) +#define AT91_DDRC2_TIMEOUT_Reserved (0x3UL << 12) +#define AT91_DDRC2_ADPE (0x1UL << 16) +#define AT91_DDRC2_ADPE_FAST (0x0UL << 16) +#define AT91_DDRC2_ADPE_SLOW (0x1UL << 16) +#define AT91_DDRC2_UPD_MR (0x3UL << 20) +#define AT91_DDRC2_UPD_MR_NO_UPDATE (0x0UL << 20) +#define AT91_DDRC2_UPD_MR_SHARED_BUS (0x1UL << 20) +#define AT91_DDRC2_UPD_MR_NO_SHARED_BUS (0x2UL << 20) +#define AT91_DDRC2_SELF_DONE (0x1UL << 25) + +/* -------- HDDRSDRC2_MDR : (HDDRSDRC2 Offset: 0x20) Memory Device Register -------- */ +#define AT91_DDRC2_MD (0x7UL << 0) +#define AT91_DDRC2_MD_SDR_SDRAM (0x0UL) +#define AT91_DDRC2_MD_LP_SDR_SDRAM (0x1UL) +#define AT91_DDRC2_MD_DDR_SDRAM (0x2UL) +#define AT91_DDRC2_MD_LP_DDR_SDRAM (0x3UL) +#define AT91_DDRC2_MD_DDR3_SDRAM (0x4UL) +#define AT91_DDRC2_MD_LPDDR3_SDRAM (0x5UL) +#define AT91_DDRC2_MD_DDR2_SDRAM (0x6UL) +#define AT91_DDRC2_MD_LPDDR2_SDRAM (0x7UL) +#define AT91_DDRC2_DBW (0x1UL << 4) +#define AT91_DDRC2_DBW_32_BITS (0x0UL << 4) +#define AT91_DDRC2_DBW_16_BITS (0x1UL << 4) + +/* -------- HDDRSDRC2_DLL : (HDDRSDRC2 Offset: 0x24) DLL Information Register --------*/ +#define AT91_DDRC2_MDINC (0x1UL << 0) +#define AT91_DDRC2_MDDEC (0x1UL << 1) +#define AT91_DDRC2_MDOVF (0x1UL << 2) +#define AT91_DDRC2_MDVAL (0xFFUL << 8) + +/* ------- MPDDRC_LPDDR2_LPR (offset: 0x28) */ +#define AT91_LPDDRC2_BK_MASK_PASR(value) (value << 0) +#define AT91_LPDDRC2_SEG_MASK(value) (value << 8) +#define AT91_LPDDRC2_DS(value) (value << 24) + +/* -------- HDDRSDRC2_HS : (HDDRSDRC2 Offset: 0x2c) High Speed Register --------*/ +#define AT91_DDRC2_NO_ANT (0x1UL << 2) + +/* -------- MPDDRC_LPDDR2_CAL_MR4: (MPDDRC Offset: 0x2c) Calibration and MR4 Register --------*/ +#define AT91_DDRC2_COUNT_CAL_MASK (0xFFFFUL) +#define AT91_DDRC2_COUNT_CAL(value) (((value) & AT91_DDRC2_COUNT_CAL_MASK) << 0) +#define AT91_DDRC2_MR4R(value) (((value) & 0xFFFFUL) << 16) + +/* -------- MPDDRC_LPDDR2_TIM_CAL : (MPDDRC Offset: 0x30) */ +#define AT91_DDRC2_ZQCS(value) (value << 0) + +/* -------- MPDDRC_IO_CALIBR : (MPDDRC Offset: 0x34) IO Calibration --------*/ +#define AT91_MPDDRC_RDIV (0x7UL << 0) +#define AT91_MPDDRC_RDIV_LPDDR2_RZQ_34 (0x1UL << 0) +#define AT91_MPDDRC_RDIV_LPDDR2_RZQ_48 (0x3UL << 0) +#define AT91_MPDDRC_RDIV_LPDDR2_RZQ_60 (0x4UL << 0) +#define AT91_MPDDRC_RDIV_LPDDR2_RZQ_120 (0x7UL << 0) + +#define AT91_MPDDRC_RDIV_DDR2_RZQ_33_3 (0x2UL << 0) +#define AT91_MPDDRC_RDIV_DDR2_RZQ_50 (0x4UL << 0) +#define AT91_MPDDRC_RDIV_DDR2_RZQ_66_7 (0x6UL << 0) +#define AT91_MPDDRC_RDIV_DDR2_RZQ_100 (0x7UL << 0) + +#define AT91_MPDDRC_RDIV_LPDDR3_RZQ_38 (0x02UL << 0) +#define AT91_MPDDRC_RDIV_LPDDR3_RZQ_46 (0x03UL << 0) +#define AT91_MPDDRC_RDIV_LPDDR3_RZQ_57 (0x04UL << 0) +#define AT91_MPDDRC_RDIV_LPDDR3_RZQ_77 (0x06UL << 0) +#define AT91_MPDDRC_RDIV_LPDDR3_RZQ_115 (0x07UL << 0) + +#define AT91_MPDDRC_ENABLE_CALIB (0x01 << 4) +#define AT91_MPDDRC_DISABLE_CALIB (0x00 << 4) +#define AT91_MPDDRC_EN_CALIB (0x01 << 4) + +#define AT91_MPDDRC_TZQIO (0x7FUL << 8) +#define AT91_MPDDRC_TZQIO_(x) ((x) << 8) +#define AT91_MPDDRC_TZQIO_0 (0x0UL << 8) +#define AT91_MPDDRC_TZQIO_1 (0x1UL << 8) +#define AT91_MPDDRC_TZQIO_3 (0x3UL << 8) +#define AT91_MPDDRC_TZQIO_4 (0x4UL << 8) +#define AT91_MPDDRC_TZQIO_5 (0x5UL << 8) +#define AT91_MPDDRC_TZQIO_31 (0x1FUL << 8) + +#define AT91_MPDDRC_CALCODEP (0xFUL << 16) +#define AT91_MPDDRC_CALCODEP_(x) ((x) << 16) + +#define AT91_MPDDRC_CALCODEN (0xFUL << 20) +#define AT91_MPDDRC_CALCODEN_(x) ((x) << 20) + +/* ---- MPDDRC_RD_DATA_PATH : (MPDDRC Offset: 0x5c) MPDDRC Read Data Path */ +#define AT91_MPDDRC_SHIFT_SAMPLING (0x03 << 0) +#define AT91_MPDDRC_RD_DATA_PATH_NO_SHIFT (0x00 << 0) +#define AT91_MPDDRC_RD_DATA_PATH_ONE_CYCLES (0x01 << 0) +#define AT91_MPDDRC_RD_DATA_PATH_TWO_CYCLES (0x02 << 0) +#define AT91_MPDDRC_RD_DATA_PATH_THREE_CYCLES (0x03 << 0) + +/* -------- MPDDRC_DLL_MOR : (MPDDRC Offset: 0x74) DLL Master Offset Register --------*/ +#define AT91_MPDDRC_MOFF(value) (value << 0) +#define AT91_MPDDRC_MOFF_1 (0x1UL << 0) +#define AT91_MPDDRC_MOFF_7 (0x7UL << 0) +#define AT91_MPDDRC_CLK90OFF(value) (value << 8) +#define AT91_MPDDRC_CLK90OFF_1 (0x1UL << 8) +#define AT91_MPDDRC_CLK90OFF_31 (0x1FUL << 8) +#define AT91_MPDDRC_SELOFF (0x1UL << 16) +#define AT91_MPDDRC_SELOFF_DISABLED (0x0UL << 16) +#define AT91_MPDDRC_SELOFF_ENABLED (0x1UL << 16) +#define AT91_MPDDRC_KEY (0xC5UL << 24) + +/* -------- MPDDRC_DLL_SOR : (MPDDRC Offset: 0x78) DLL Slave Offset Register --------*/ +#define AT91_MPDDRC_S0OFF_1 (0x1UL << 0) +#define AT91_MPDDRC_S1OFF_1 (0x1UL << 8) +#define AT91_MPDDRC_S2OFF_1 (0x1UL << 16) +#define AT91_MPDDRC_S3OFF_1 (0x1UL << 24) + +#define AT91_MPDDRC_S0OFF(value) (value << 0) +#define AT91_MPDDRC_S1OFF(value) (value << 8) +#define AT91_MPDDRC_S2OFF(value) (value << 16) +#define AT91_MPDDRC_S3OFF(value) (value << 24) + +/* -------- HDDRSDRC2_WPCR : (HDDRSDRC2 Offset: 0xe4) Write Protect Control Register --------*/ +#define AT91_DDRC2_WPEN (0x1UL << 0) +#define AT91_DDRC2_WPKEY (0xFFFFFFUL << 8) + +/* -------- HDDRSDRC2_WPSR : (HDDRSDRC2 Offset: 0xe8) Write Protect Status Register --------*/ +#define AT91_DDRC2_WPVS (0x1UL << 0) +#define AT91_DDRC2_WPSRC (0xFFFFUL << 8) + +#endif /* #ifndef __AT91_DDRSDRC_H__ */ -- cgit v1.2.3 From 51f99624a2fe1e5def7aa10d8f8a873488fbcecf Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:10:58 +0200 Subject: ARM: at91: migrate at91sam9_ddrsdr.h to use at91bootstrap's at91_ddrsdrc.h Instead of adding missing definitions to the existing at91sam9_ddrsdr.h and adapting the incoming DDRAM initialization code from at91bootstrap, just replace the lightly used existing header with: https://github.com/linux4sam/at91bootstrap/blob/v3.8.12/include/arch/at91_ddrsdrc.h For easier comprehension, the replacement is done in three steps: Here the existing at91sam9_ddrsdr.h has its now duplicate (in function, not name) macros removed and existing users are migrated to use the new header. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/at91sam9g45_reset.S | 6 +- arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h | 138 ++-------------------- 2 files changed, 12 insertions(+), 132 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/at91sam9g45_reset.S b/arch/arm/mach-at91/at91sam9g45_reset.S index 98db15c0b0..c3115fd9ca 100644 --- a/arch/arm/mach-at91/at91sam9g45_reset.S +++ b/arch/arm/mach-at91/at91sam9g45_reset.S @@ -19,13 +19,13 @@ .globl at91sam9g45_reset at91sam9g45_reset: mov r2, #1 - mov r3, #AT91_DDRSDRC_LPCB_POWER_DOWN + mov r3, #AT91_DDRC2_LPCB_POWERDOWN ldr r4, =AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST .balign 32 @ align to cache line - str r2, [r0, #AT91_DDRSDRC_RTR] @ disable DDR0 access - str r3, [r0, #AT91_DDRSDRC_LPR] @ power down DDR0 + str r2, [r0, #AT91_HDDRSDRC2_RTR] @ disable DDR0 access + str r3, [r0, #AT91_HDDRSDRC2_LPR] @ power down DDR0 str r4, [r1] @ reset processor b . diff --git a/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h b/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h index 496cf70701..0341951ff3 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h +++ b/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h @@ -12,130 +12,10 @@ #ifndef AT91SAM9_DDRSDR_H #define AT91SAM9_DDRSDR_H -#define AT91_DDRSDRC_MR 0x00 /* Mode Register */ -#define AT91_DDRSDRC_MODE (0x7 << 0) /* Command Mode */ -#define AT91_DDRSDRC_MODE_NORMAL 0 -#define AT91_DDRSDRC_MODE_NOP 1 -#define AT91_DDRSDRC_MODE_PRECHARGE 2 -#define AT91_DDRSDRC_MODE_LMR 3 -#define AT91_DDRSDRC_MODE_REFRESH 4 -#define AT91_DDRSDRC_MODE_EXT_LMR 5 -#define AT91_DDRSDRC_MODE_DEEP 6 - -#define AT91_DDRSDRC_RTR 0x04 /* Refresh Timer Register */ -#define AT91_DDRSDRC_COUNT (0xfff << 0) /* Refresh Timer Counter */ - -#define AT91_DDRSDRC_CR 0x08 /* Configuration Register */ -#define AT91_DDRSDRC_NC (3 << 0) /* Number of Column Bits */ -#define AT91_DDRSDRC_NC_SDR8 (0 << 0) -#define AT91_DDRSDRC_NC_SDR9 (1 << 0) -#define AT91_DDRSDRC_NC_SDR10 (2 << 0) -#define AT91_DDRSDRC_NC_SDR11 (3 << 0) -#define AT91_DDRSDRC_NC_DDR9 (0 << 0) -#define AT91_DDRSDRC_NC_DDR10 (1 << 0) -#define AT91_DDRSDRC_NC_DDR11 (2 << 0) -#define AT91_DDRSDRC_NC_DDR12 (3 << 0) -#define AT91_DDRSDRC_NR (3 << 2) /* Number of Row Bits */ -#define AT91_DDRSDRC_NR_11 (0 << 2) -#define AT91_DDRSDRC_NR_12 (1 << 2) -#define AT91_DDRSDRC_NR_13 (2 << 2) -#define AT91_DDRSDRC_NR_14 (3 << 2) -#define AT91_DDRSDRC_CAS (7 << 4) /* CAS Latency */ -#define AT91_DDRSDRC_CAS_2 (2 << 4) -#define AT91_DDRSDRC_CAS_3 (3 << 4) -#define AT91_DDRSDRC_CAS_25 (6 << 4) -#define AT91_DDRSDRC_RST_DLL (1 << 7) /* Reset DLL */ -#define AT91_DDRSDRC_DICDS (1 << 8) /* Output impedance control */ -#define AT91_DDRSDRC_DIS_DLL (1 << 9) /* Disable DLL [SAM9 Only] */ -#define AT91_DDRSDRC_OCD (1 << 12) /* Off-Chip Driver [SAM9 Only] */ -#define AT91_DDRSDRC_DQMS (1 << 16) /* Mask Data is Shared [SAM9 Only] */ -#define AT91_DDRSDRC_ACTBST (1 << 18) /* Active Bank X to Burst Stop Read Access Bank Y [SAM9 Only] */ -#define AT91_DDRSDRC_NB (1 << 20) /* Number of -Banks [not SAM9G45] */ -#define AT91_SDRAMC_NB_4 (0 << 20) -#define AT91_SDRAMC_NB_8 (1 << 20) - -#define AT91_DDRSDRC_T0PR 0x0C /* Timing 0 Register */ -#define AT91_DDRSDRC_TRAS (0xf << 0) /* Active to Precharge delay */ -#define AT91_DDRSDRC_TRCD (0xf << 4) /* Row to Column delay */ -#define AT91_DDRSDRC_TWR (0xf << 8) /* Write recovery delay */ -#define AT91_DDRSDRC_TRC (0xf << 12) /* Row cycle delay */ -#define AT91_DDRSDRC_TRP (0xf << 16) /* Row precharge delay */ -#define AT91_DDRSDRC_TRRD (0xf << 20) /* Active BankA to BankB */ -#define AT91_DDRSDRC_TWTR (0x7 << 24) /* Internal Write to Read delay */ -#define AT91CAP9_DDRSDRC_TWTR (1 << 24) /* Internal Write to Read delay */ -#define AT91_DDRSDRC_RED_WRRD (0x1 << 27) /* Reduce Write to Read Delay [SAM9 Only] */ -#define AT91_DDRSDRC_TMRD (0xf << 28) /* Load mode to active/refresh delay */ - -#define AT91_DDRSDRC_T1PR 0x10 /* Timing 1 Register */ -#define AT91_DDRSDRC_TRFC (0x1f << 0) /* Row Cycle Delay */ -#define AT91_DDRSDRC_TXSNR (0xff << 8) /* Exit self-refresh to non-read */ -#define AT91_DDRSDRC_TXSRD (0xff << 16) /* Exit self-refresh to read */ -#define AT91_DDRSDRC_TXP (0xf << 24) /* Exit power-down delay */ - -#define AT91_DDRSDRC_T2PR 0x14 /* Timing 2 Register [SAM9 Only] */ -#define AT91_DDRSDRC_TXARD (0xf << 0) /* Exit active power down delay to read command in mode "Fast Exit" */ -#define AT91_DDRSDRC_TXARDS (0xf << 4) /* Exit active power down delay to read command in mode "Slow Exit" */ -#define AT91_DDRSDRC_TRPA (0xf << 8) /* Row Precharge All delay */ -#define AT91_DDRSDRC_TRTP (0x7 << 12) /* Read to Precharge delay */ - -#define AT91_DDRSDRC_LPR 0x1C /* Low Power Register */ -#define AT91CAP9_DDRSDRC_LPR 0x18 /* Low Power Register */ -#define AT91_DDRSDRC_LPCB (3 << 0) /* Low-power Configurations */ -#define AT91_DDRSDRC_LPCB_DISABLE 0 -#define AT91_DDRSDRC_LPCB_SELF_REFRESH 1 -#define AT91_DDRSDRC_LPCB_POWER_DOWN 2 -#define AT91_DDRSDRC_LPCB_DEEP_POWER_DOWN 3 -#define AT91_DDRSDRC_CLKFR (1 << 2) /* Clock Frozen */ -#define AT91_DDRSDRC_PASR (7 << 4) /* Partial Array Self Refresh */ -#define AT91_DDRSDRC_TCSR (3 << 8) /* Temperature Compensated Self Refresh */ -#define AT91_DDRSDRC_DS (3 << 10) /* Drive Strength */ -#define AT91_DDRSDRC_TIMEOUT (3 << 12) /* Time to define when Low Power Mode is enabled */ -#define AT91_DDRSDRC_TIMEOUT_0_CLK_CYCLES (0 << 12) -#define AT91_DDRSDRC_TIMEOUT_64_CLK_CYCLES (1 << 12) -#define AT91_DDRSDRC_TIMEOUT_128_CLK_CYCLES (2 << 12) -#define AT91_DDRSDRC_APDE (1 << 16) /* Active power down exit time */ -#define AT91_DDRSDRC_UPD_MR (3 << 20) /* Update load mode register and extended mode register */ - -#define AT91_DDRSDRC_MDR 0x20 /* Memory Device Register */ -#define AT91CAP9_DDRSDRC_MDR 0x1C /* Memory Device Register */ -#define AT91_DDRSDRC_MD (3 << 0) /* Memory Device Type */ -#define AT91_DDRSDRC_MD_SDR 0 -#define AT91_DDRSDRC_MD_LOW_POWER_SDR 1 -#define AT91CAP9_DDRSDRC_MD_DDR 2 -#define AT91_DDRSDRC_MD_LOW_POWER_DDR 3 -#define AT91_DDRSDRC_MD_DDR2 6 /* [SAM9 Only] */ -#define AT91_DDRSDRC_DBW (1 << 4) /* Data Bus Width */ -#define AT91_DDRSDRC_DBW_32BITS (0 << 4) -#define AT91_DDRSDRC_DBW_16BITS (1 << 4) - -#define AT91_DDRSDRC_DLL 0x24 /* DLL Information Register */ -#define AT91CAP9_DDRSDRC_DLL 0x20 /* DLL Information Register */ -#define AT91_DDRSDRC_MDINC (1 << 0) /* Master Delay increment */ -#define AT91_DDRSDRC_MDDEC (1 << 1) /* Master Delay decrement */ -#define AT91_DDRSDRC_MDOVF (1 << 2) /* Master Delay Overflow */ -#define AT91CAP9_DDRSDRC_SDCOVF (1 << 3) /* Slave Delay Correction Overflow */ -#define AT91CAP9_DDRSDRC_SDCUDF (1 << 4) /* Slave Delay Correction Underflow */ -#define AT91CAP9_DDRSDRC_SDERF (1 << 5) /* Slave Delay Correction error */ -#define AT91_DDRSDRC_MDVAL (0xff << 8) /* Master Delay value */ -#define AT91CAP9_DDRSDRC_SDVAL (0xff << 16) /* Slave Delay value */ -#define AT91CAP9_DDRSDRC_SDCVAL (0xff << 24) /* Slave Delay Correction value */ - -#define AT91_DDRSDRC_HS 0x2C /* High Speed Register [SAM9 Only] */ -#define AT91_DDRSDRC_DIS_ATCP_RD (1 << 2) /* Anticip read access is disabled */ - -#define AT91_DDRSDRC_DELAY(n) (0x30 + (0x4 * (n))) /* Delay I/O Register n */ - -#define AT91_DDRSDRC_WPMR 0xE4 /* Write Protect Mode Register [SAM9 Only] */ -#define AT91_DDRSDRC_WP (1 << 0) /* Write protect enable */ -#define AT91_DDRSDRC_WPKEY (0xffffff << 8) /* Write protect key */ -#define AT91_DDRSDRC_KEY (0x444452 << 8) /* Write protect key = "DDR" */ - -#define AT91_DDRSDRC_WPSR 0xE8 /* Write Protect Status Register [SAM9 Only] */ -#define AT91_DDRSDRC_WPVS (1 << 0) /* Write protect violation status */ -#define AT91_DDRSDRC_WPVSRC (0xffff << 8) /* Write protect violation source */ +#include #ifndef __ASSEMBLY__ +#include #include #include @@ -146,11 +26,11 @@ static inline u32 at91_get_ddram_size(void __iomem *base, bool is_nb) u32 size; bool is_sdram; - cr = readl(base + AT91_DDRSDRC_CR); - mdr = readl(base + AT91_DDRSDRC_MDR); + cr = readl(base + AT91_HDDRSDRC2_CR); + mdr = readl(base + AT91_HDDRSDRC2_MDR); /* will always be false for sama5d2, sama5d3 or sama5d4 */ - is_sdram = (mdr & AT91_DDRSDRC_MD) <= AT91_DDRSDRC_MD_LOW_POWER_SDR; + is_sdram = (mdr & AT91_DDRC2_MD) <= AT91_DDRC2_MD_LP_SDR_SDRAM; /* Formula: * size = bank << (col + row + 1); @@ -159,19 +39,19 @@ static inline u32 at91_get_ddram_size(void __iomem *base, bool is_nb) */ size = 1; /* COL */ - size += (cr & AT91_DDRSDRC_NC) + 8; + size += (cr & AT91_DDRC2_NC) + 8; if (!is_sdram) size ++; /* ROW */ - size += ((cr & AT91_DDRSDRC_NR) >> 2) + 11; + size += ((cr & AT91_DDRC2_NR) >> 2) + 11; /* BANK */ if (is_nb) - size = ((cr & AT91_DDRSDRC_NB) ? 8 : 4) << size; + size = ((cr & AT91_DDRC2_NB_BANKS) ? 8 : 4) << size; else size = 4 << size; /* bandwidth */ - if (!(mdr & AT91_DDRSDRC_DBW)) + if (!(mdr & AT91_DDRC2_DBW)) size <<= 1; return size; -- cgit v1.2.3 From a84a4e0384983119be00d2b205b51091299ef1d7 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:10:59 +0200 Subject: ARM: at91: replace at91sam9_ddrsdr.h with at91bootstrap's at91_ddrsdrc.h Instead of adding missing definitions to the existing at91sam9_ddrsdr.h and adapting the incoming DDRAM initialization code from at91bootstrap, just replace the lightly used existing header with: https://github.com/linux4sam/at91bootstrap/blob/v3.8.12/include/arch/at91_ddrsdrc.h For easier comprehension, the replacement is done in three steps: This last step copies the memory size querying functions from at91sam9_ddrsdr.h to at91_ddrsdrc.h, then deletes it and fixes all references. Reviewed-by: Sam Ravnborg Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/boards/at91sam9m10g45ek/lowlevel.c | 2 +- arch/arm/boards/at91sam9m10ihd/lowlevel.c | 2 +- arch/arm/boards/at91sam9n12ek/lowlevel.c | 2 +- arch/arm/boards/at91sam9x5ek/lowlevel.c | 3 +- arch/arm/boards/pm9g45/lowlevel.c | 3 +- arch/arm/boards/sama5d3_xplained/lowlevel.c | 2 +- arch/arm/boards/sama5d3xek/lowlevel.c | 2 +- arch/arm/boards/sama5d4_xplained/lowlevel.c | 2 +- arch/arm/boards/sama5d4ek/lowlevel.c | 2 +- arch/arm/mach-at91/at91sam9g45_devices.c | 2 +- arch/arm/mach-at91/at91sam9g45_reset.S | 2 +- arch/arm/mach-at91/at91sam9n12_devices.c | 2 +- arch/arm/mach-at91/at91sam9x5_devices.c | 2 +- arch/arm/mach-at91/include/mach/at91_ddrsdrc.h | 78 +++++++++++++++++++ arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h | 94 ----------------------- arch/arm/mach-at91/sama5d3_devices.c | 2 +- arch/arm/mach-at91/sama5d4_devices.c | 2 +- 17 files changed, 94 insertions(+), 110 deletions(-) delete mode 100644 arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h (limited to 'arch/arm') diff --git a/arch/arm/boards/at91sam9m10g45ek/lowlevel.c b/arch/arm/boards/at91sam9m10g45ek/lowlevel.c index 0f3a035d1d..755e7ec029 100644 --- a/arch/arm/boards/at91sam9m10g45ek/lowlevel.c +++ b/arch/arm/boards/at91sam9m10g45ek/lowlevel.c @@ -11,7 +11,7 @@ #include #include -#include +#include void __naked __bare_init barebox_arm_reset_vector(uint32_t r0, uint32_t r1, uint32_t r2) { diff --git a/arch/arm/boards/at91sam9m10ihd/lowlevel.c b/arch/arm/boards/at91sam9m10ihd/lowlevel.c index e07ff892cd..817c7548c9 100644 --- a/arch/arm/boards/at91sam9m10ihd/lowlevel.c +++ b/arch/arm/boards/at91sam9m10ihd/lowlevel.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include diff --git a/arch/arm/boards/at91sam9n12ek/lowlevel.c b/arch/arm/boards/at91sam9n12ek/lowlevel.c index 5bc18f8fca..4353555d0d 100644 --- a/arch/arm/boards/at91sam9n12ek/lowlevel.c +++ b/arch/arm/boards/at91sam9n12ek/lowlevel.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include void __naked __bare_init barebox_arm_reset_vector(uint32_t r0, uint32_t r1, uint32_t r2) diff --git a/arch/arm/boards/at91sam9x5ek/lowlevel.c b/arch/arm/boards/at91sam9x5ek/lowlevel.c index c1433c8f7e..ebd417b19c 100644 --- a/arch/arm/boards/at91sam9x5ek/lowlevel.c +++ b/arch/arm/boards/at91sam9x5ek/lowlevel.c @@ -1,7 +1,6 @@ #include #include -#include -#include +#include #include #include #include diff --git a/arch/arm/boards/pm9g45/lowlevel.c b/arch/arm/boards/pm9g45/lowlevel.c index fc0bfe405b..5f66b28254 100644 --- a/arch/arm/boards/pm9g45/lowlevel.c +++ b/arch/arm/boards/pm9g45/lowlevel.c @@ -10,7 +10,8 @@ #include #include -#include +#include + #include void __naked __bare_init barebox_arm_reset_vector(uint32_t r0, uint32_t r1, uint32_t r2) diff --git a/arch/arm/boards/sama5d3_xplained/lowlevel.c b/arch/arm/boards/sama5d3_xplained/lowlevel.c index 8653c48c69..28c07d5053 100644 --- a/arch/arm/boards/sama5d3_xplained/lowlevel.c +++ b/arch/arm/boards/sama5d3_xplained/lowlevel.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include void __naked __bare_init barebox_arm_reset_vector(uint32_t r0, uint32_t r1, uint32_t r2) diff --git a/arch/arm/boards/sama5d3xek/lowlevel.c b/arch/arm/boards/sama5d3xek/lowlevel.c index 8653c48c69..28c07d5053 100644 --- a/arch/arm/boards/sama5d3xek/lowlevel.c +++ b/arch/arm/boards/sama5d3xek/lowlevel.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include void __naked __bare_init barebox_arm_reset_vector(uint32_t r0, uint32_t r1, uint32_t r2) diff --git a/arch/arm/boards/sama5d4_xplained/lowlevel.c b/arch/arm/boards/sama5d4_xplained/lowlevel.c index 9a6a767e5f..3c58a08f3b 100644 --- a/arch/arm/boards/sama5d4_xplained/lowlevel.c +++ b/arch/arm/boards/sama5d4_xplained/lowlevel.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include void __naked __bare_init barebox_arm_reset_vector(uint32_t r0, uint32_t r1, uint32_t r2) diff --git a/arch/arm/boards/sama5d4ek/lowlevel.c b/arch/arm/boards/sama5d4ek/lowlevel.c index 9a6a767e5f..3c58a08f3b 100644 --- a/arch/arm/boards/sama5d4ek/lowlevel.c +++ b/arch/arm/boards/sama5d4ek/lowlevel.c @@ -10,7 +10,7 @@ #include #include -#include +#include #include void __naked __bare_init barebox_arm_reset_vector(uint32_t r0, uint32_t r1, uint32_t r2) diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 43d8d5fbd6..389d88c17d 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/mach-at91/at91sam9g45_reset.S b/arch/arm/mach-at91/at91sam9g45_reset.S index c3115fd9ca..67517bf591 100644 --- a/arch/arm/mach-at91/at91sam9g45_reset.S +++ b/arch/arm/mach-at91/at91sam9g45_reset.S @@ -11,7 +11,7 @@ */ #include -#include +#include #include .arm diff --git a/arch/arm/mach-at91/at91sam9n12_devices.c b/arch/arm/mach-at91/at91sam9n12_devices.c index 43cbb79af4..91b3e9b2fb 100644 --- a/arch/arm/mach-at91/at91sam9n12_devices.c +++ b/arch/arm/mach-at91/at91sam9n12_devices.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/mach-at91/at91sam9x5_devices.c b/arch/arm/mach-at91/at91sam9x5_devices.c index ab506a1f42..022e4fb59a 100644 --- a/arch/arm/mach-at91/at91sam9x5_devices.c +++ b/arch/arm/mach-at91/at91sam9x5_devices.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/mach-at91/include/mach/at91_ddrsdrc.h b/arch/arm/mach-at91/include/mach/at91_ddrsdrc.h index 17e64fcb9a..7d70fe4cb4 100644 --- a/arch/arm/mach-at91/include/mach/at91_ddrsdrc.h +++ b/arch/arm/mach-at91/include/mach/at91_ddrsdrc.h @@ -292,4 +292,82 @@ #define AT91_DDRC2_WPVS (0x1UL << 0) #define AT91_DDRC2_WPSRC (0xFFFFUL << 8) +#ifndef __ASSEMBLY__ +#include +#include +#include + +static inline u32 at91_get_ddram_size(void __iomem *base, bool is_nb) +{ + u32 cr; + u32 mdr; + u32 size; + bool is_sdram; + + cr = readl(base + AT91_HDDRSDRC2_CR); + mdr = readl(base + AT91_HDDRSDRC2_MDR); + + /* will always be false for sama5d2, sama5d3 or sama5d4 */ + is_sdram = (mdr & AT91_DDRC2_MD) <= AT91_DDRC2_MD_LP_SDR_SDRAM; + + /* Formula: + * size = bank << (col + row + 1); + * if (bandwidth == 32 bits) + * size <<= 1; + */ + size = 1; + /* COL */ + size += (cr & AT91_DDRC2_NC) + 8; + if (!is_sdram) + size ++; + /* ROW */ + size += ((cr & AT91_DDRC2_NR) >> 2) + 11; + /* BANK */ + if (is_nb) + size = ((cr & AT91_DDRC2_NB_BANKS) ? 8 : 4) << size; + else + size = 4 << size; + + /* bandwidth */ + if (!(mdr & AT91_DDRC2_DBW)) + size <<= 1; + + return size; +} + +static inline u32 at91sam9g45_get_ddram_size(int bank) +{ + switch (bank) { + case 0: + return at91_get_ddram_size(IOMEM(AT91SAM9G45_BASE_DDRSDRC0), false); + case 1: + return at91_get_ddram_size(IOMEM(AT91SAM9G45_BASE_DDRSDRC1), false); + default: + return 0; + } +} + +static inline u32 at91sam9x5_get_ddram_size(void) +{ + return at91_get_ddram_size(IOMEM(AT91SAM9X5_BASE_DDRSDRC0), true); +} + +static inline u32 at91sam9n12_get_ddram_size(void) +{ + return at91_get_ddram_size(IOMEM(AT91SAM9N12_BASE_DDRSDRC0), true); +} + +static inline u32 at91sama5d3_get_ddram_size(void) +{ + return at91_get_ddram_size(IOMEM(SAMA5D3_BASE_MPDDRC), true); +} + +static inline u32 at91sama5d4_get_ddram_size(void) +{ + return at91_get_ddram_size(IOMEM(SAMA5D4_BASE_MPDDRC), true); +} + + +#endif /* __ASSEMBLY__ */ + #endif /* #ifndef __AT91_DDRSDRC_H__ */ diff --git a/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h b/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h deleted file mode 100644 index 0341951ff3..0000000000 --- a/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Header file for the Atmel DDR/SDR SDRAM Controller - * - * Copyright (C) 2010 Atmel Corporation - * Nicolas Ferre - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - */ -#ifndef AT91SAM9_DDRSDR_H -#define AT91SAM9_DDRSDR_H - -#include - -#ifndef __ASSEMBLY__ -#include -#include -#include - -static inline u32 at91_get_ddram_size(void __iomem *base, bool is_nb) -{ - u32 cr; - u32 mdr; - u32 size; - bool is_sdram; - - cr = readl(base + AT91_HDDRSDRC2_CR); - mdr = readl(base + AT91_HDDRSDRC2_MDR); - - /* will always be false for sama5d2, sama5d3 or sama5d4 */ - is_sdram = (mdr & AT91_DDRC2_MD) <= AT91_DDRC2_MD_LP_SDR_SDRAM; - - /* Formula: - * size = bank << (col + row + 1); - * if (bandwidth == 32 bits) - * size <<= 1; - */ - size = 1; - /* COL */ - size += (cr & AT91_DDRC2_NC) + 8; - if (!is_sdram) - size ++; - /* ROW */ - size += ((cr & AT91_DDRC2_NR) >> 2) + 11; - /* BANK */ - if (is_nb) - size = ((cr & AT91_DDRC2_NB_BANKS) ? 8 : 4) << size; - else - size = 4 << size; - - /* bandwidth */ - if (!(mdr & AT91_DDRC2_DBW)) - size <<= 1; - - return size; -} - -static inline u32 at91sam9g45_get_ddram_size(int bank) -{ - switch (bank) { - case 0: - return at91_get_ddram_size(IOMEM(AT91SAM9G45_BASE_DDRSDRC0), false); - case 1: - return at91_get_ddram_size(IOMEM(AT91SAM9G45_BASE_DDRSDRC1), false); - default: - return 0; - } -} - -static inline u32 at91sam9x5_get_ddram_size(void) -{ - return at91_get_ddram_size(IOMEM(AT91SAM9X5_BASE_DDRSDRC0), true); -} - -static inline u32 at91sam9n12_get_ddram_size(void) -{ - return at91_get_ddram_size(IOMEM(AT91SAM9N12_BASE_DDRSDRC0), true); -} - -static inline u32 at91sama5d3_get_ddram_size(void) -{ - return at91_get_ddram_size(IOMEM(SAMA5D3_BASE_MPDDRC), true); -} - -static inline u32 at91sama5d4_get_ddram_size(void) -{ - return at91_get_ddram_size(IOMEM(SAMA5D4_BASE_MPDDRC), true); -} - -#endif - -#endif diff --git a/arch/arm/mach-at91/sama5d3_devices.c b/arch/arm/mach-at91/sama5d3_devices.c index bf4a03d404..e29ed2ba97 100644 --- a/arch/arm/mach-at91/sama5d3_devices.c +++ b/arch/arm/mach-at91/sama5d3_devices.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/arch/arm/mach-at91/sama5d4_devices.c b/arch/arm/mach-at91/sama5d4_devices.c index 5a1109dc0e..7be9e260d4 100644 --- a/arch/arm/mach-at91/sama5d4_devices.c +++ b/arch/arm/mach-at91/sama5d4_devices.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.3 From ef76748baaca509deee7638949b8f8c60966fce6 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:00 +0200 Subject: ARM: at91: import early_udelay from at91bootstrap For use by the incoming at91bootstrap DDRAMC initialization code, this commit provides an early_udelay function usable in PBL imported from https://github.com/linux4sam/at91bootstrap/blob/v3.8.12/driver/at91_pit.c Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/Makefile | 1 + arch/arm/mach-at91/early_udelay.c | 56 ++++++++++++++++++++++++++ arch/arm/mach-at91/include/mach/at91_pmc_ll.h | 13 +++++- arch/arm/mach-at91/include/mach/early_udelay.h | 14 +++++++ 4 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-at91/early_udelay.c create mode 100644 arch/arm/mach-at91/include/mach/early_udelay.h (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 89aff54b8a..863b62eddc 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -1,5 +1,6 @@ obj-y += setup.o lwl-y += at91_pmc_ll.o +lwl-$(CONFIG_CLOCKSOURCE_ATMEL_PIT) += early_udelay.o ifeq ($(CONFIG_COMMON_CLK_OF_PROVIDER),) obj-y += clock.o diff --git a/arch/arm/mach-at91/early_udelay.c b/arch/arm/mach-at91/early_udelay.c new file mode 100644 index 0000000000..632e797beb --- /dev/null +++ b/arch/arm/mach-at91/early_udelay.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BSD-1-Clause +/* + * Copyright (c) 2012, Atmel Corporation + */ + +#include +#include +#include +#include +#include + +static unsigned int master_clock; +static void __iomem *pmc, *pit; +static bool has_h32mxdiv; + +/* Because the below statement is used in the function: + * ((MASTER_CLOCK >> 10) * usec) is used, + * to our 32-bit system. the argu "usec" maximum value is: + * supposed "MASTER_CLOCK" is 132M. + * 132000000 / 1024 = 128906 + * (0xffffffff) / 128906 = 33318. + * So the maximum delay time is 33318 us. + */ +/* requires PIT to be initialized, but not the clocksource framework */ +void early_udelay(unsigned int usec) +{ + unsigned int delay; + unsigned int current; + unsigned int base = readl(pit + AT91_PIT_PIIR); + + if (has_h32mxdiv) + master_clock /= 2; + + delay = ((master_clock >> 10) * usec) >> 14; + + do { + current = readl(pit + AT91_PIT_PIIR); + current -= base; + } while (current < delay); +} + +void early_udelay_init(void __iomem *pmc_base, + void __iomem *pit_base, + unsigned int clock, + unsigned int master_clock_rate, + unsigned int flags) +{ + master_clock = master_clock_rate; + pmc = pmc_base; + pit = pit_base; + has_h32mxdiv = at91_pmc_check_mck_h32mxdiv(pmc, flags); + + writel(AT91_PIT_PIV | AT91_PIT_PITEN, pit + AT91_PIT_MR); + + at91_pmc_enable_periph_clock(pmc_base, clock); +} diff --git a/arch/arm/mach-at91/include/mach/at91_pmc_ll.h b/arch/arm/mach-at91/include/mach/at91_pmc_ll.h index eda40e8e12..e3d3e3ad59 100644 --- a/arch/arm/mach-at91/include/mach/at91_pmc_ll.h +++ b/arch/arm/mach-at91/include/mach/at91_pmc_ll.h @@ -13,6 +13,7 @@ #define AT91_PMC_LL_FLAG_SAM9X5_PMC (1 << 0) #define AT91_PMC_LL_FLAG_MEASURE_XTAL (1 << 1) #define AT91_PMC_LL_FLAG_DISABLE_RC (1 << 2) +#define AT91_PMC_LL_FLAG_H32MXDIV (1 << 3) #define AT91_PMC_LL_AT91RM9200 (0) #define AT91_PMC_LL_AT91SAM9260 (0) @@ -27,7 +28,8 @@ AT91_PMC_LL_FLAG_MEASURE_XTAL) #define AT91_PMC_LL_SAMA5D3 (AT91_PMC_LL_FLAG_SAM9X5_PMC | \ AT91_PMC_LL_FLAG_DISABLE_RC) -#define AT91_PMC_LL_SAMA5D4 (AT91_PMC_LL_FLAG_SAM9X5_PMC) +#define AT91_PMC_LL_SAMA5D4 (AT91_PMC_LL_FLAG_SAM9X5_PMC | \ + AT91_PMC_LL_FLAG_H32MXDIV) void at91_pmc_init(void __iomem *pmc_base, unsigned int flags); void at91_pmc_cfg_mck(void __iomem *pmc_base, u32 pmc_mckr, unsigned int flags); @@ -75,4 +77,13 @@ static inline int at91_pmc_sam9x5_enable_periph_clock(void __iomem *pmc_base, return 0; } +static inline bool at91_pmc_check_mck_h32mxdiv(void __iomem *pmc_base, + unsigned flags) +{ + if (flags & AT91_PMC_LL_FLAG_H32MXDIV) + return readl(pmc_base + AT91_PMC_MCKR) & AT91_PMC_H32MXDIV; + + return false; +} + #endif diff --git a/arch/arm/mach-at91/include/mach/early_udelay.h b/arch/arm/mach-at91/include/mach/early_udelay.h new file mode 100644 index 0000000000..1c1b0123fe --- /dev/null +++ b/arch/arm/mach-at91/include/mach/early_udelay.h @@ -0,0 +1,14 @@ +#ifndef __EARLY_UDELAY_H__ +#define __EARLY_UDELAY_H__ + +#include + +/* requires PIT to be initialized, but not the clocksource framework */ +void early_udelay(unsigned int usec); +void early_udelay_init(void __iomem *pmc_base, + void __iomem *pit_base, + unsigned int clock, + unsigned int master_clock_rate, + unsigned int flags); + +#endif -- cgit v1.2.3 From 823d4400f244296c73a77cd9b83e9de96b6af9c2 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:01 +0200 Subject: ARM: at91: import low level DDRAMC initialization code from at91bootstrap This commit imports DDRAMC initialization routines for use in PBL from https://github.com/linux4sam/at91bootstrap/blob/v3.8.12/driver/ddramc.c Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/Makefile | 2 +- arch/arm/mach-at91/ddramc_ll.c | 507 +++++++++++++++++++++++++++++++ arch/arm/mach-at91/include/mach/ddramc.h | 36 +++ 3 files changed, 544 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-at91/ddramc_ll.c create mode 100644 arch/arm/mach-at91/include/mach/ddramc.h (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 863b62eddc..a7e9ce5938 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -1,5 +1,5 @@ obj-y += setup.o -lwl-y += at91_pmc_ll.o +lwl-y += at91_pmc_ll.o ddramc_ll.o lwl-$(CONFIG_CLOCKSOURCE_ATMEL_PIT) += early_udelay.o ifeq ($(CONFIG_COMMON_CLK_OF_PROVIDER),) diff --git a/arch/arm/mach-at91/ddramc_ll.c b/arch/arm/mach-at91/ddramc_ll.c new file mode 100644 index 0000000000..4768fdcd62 --- /dev/null +++ b/arch/arm/mach-at91/ddramc_ll.c @@ -0,0 +1,507 @@ +// SPDX-License-Identifier: BSD-1-Clause +/* + * Copyright (c) 2007, Stelian Pop + * Copyright (c) 2007 Lead Tech Design + */ + +#include +#include +#include +#include +#include + +void at91_ddram_initialize(void __iomem *base_address, + void __iomem *ram_address, + struct at91_ddramc_register *ddramc_config) +{ + unsigned long ba_offset; + unsigned long cr = 0; + + /* compute BA[] offset according to CR configuration */ + ba_offset = (ddramc_config->cr & AT91_DDRC2_NC) + 9; + if ((ddramc_config->cr & AT91_DDRC2_DECOD) == AT91_DDRC2_DECOD_SEQUENTIAL) + ba_offset += ((ddramc_config->cr & AT91_DDRC2_NR) >> 2) + 11; + + ba_offset += (ddramc_config->mdr & AT91_DDRC2_DBW) ? 1 : 2; + + /* + * Step 1: Program the memory device type into the Memory Device Register + */ + writel(ddramc_config->mdr, base_address + AT91_HDDRSDRC2_MDR); + + /* + * Step 2: Program the feature of DDR2-SDRAM device into + * the Timing Register, and into the Configuration Register + */ + writel(ddramc_config->cr, base_address + AT91_HDDRSDRC2_CR); + + writel(ddramc_config->t0pr, base_address + AT91_HDDRSDRC2_T0PR); + writel(ddramc_config->t1pr, base_address + AT91_HDDRSDRC2_T1PR); + writel(ddramc_config->t2pr, base_address + AT91_HDDRSDRC2_T2PR); + + /* + * Step 3: An NOP command is issued to the DDR2-SDRAM + */ + writel(AT91_DDRC2_MODE_NOP_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address); + /* Now, clocks which drive the DDR2-SDRAM device are enabled */ + + /* A minimum pause wait 200 us is provided to precede any signal toggle. + (6 core cycles per iteration, core is at 396MHz: min 13340 loops) */ + early_udelay(200); + + /* + * Step 4: An NOP command is issued to the DDR2-SDRAM + */ + writel(AT91_DDRC2_MODE_NOP_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address); + /* Now, CKE is driven high */ + /* wait 400 ns min */ + early_udelay(1); + + /* + * Step 5: An all banks precharge command is issued to the DDR2-SDRAM. + */ + writel(AT91_DDRC2_MODE_PRCGALL_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address); + + /* wait 2 cycles min (of tCK) = 15 ns min */ + early_udelay(1); + + /* + * Step 6: An Extended Mode Register set(EMRS2) cycle is issued to chose between commercial or high + * temperature operations. + * Perform a write access to DDR2-SDRAM to acknowledge this command. + * The write address must be chosen so that BA[1] is set to 1 and BA[0] is set to 0. + */ + writel(AT91_DDRC2_MODE_EXT_LMR_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address + (0x2 << ba_offset)); + + /* wait 2 cycles min (of tCK) = 15 ns min */ + early_udelay(1); + + /* + * Step 7: An Extended Mode Register set(EMRS3) cycle is issued + * to set the Extended Mode Register to "0". + * Perform a write access to DDR2-SDRAM to acknowledge this command. + * The write address must be chosen so that BA[1] is set to 1 and BA[0] is set to 1. + */ + writel(AT91_DDRC2_MODE_EXT_LMR_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address + (0x3 << ba_offset)); + + /* wait 2 cycles min (of tCK) = 15 ns min */ + early_udelay(1); + + /* + * Step 8: An Extened Mode Register set(EMRS1) cycle is issued to enable DLL, + * and to program D.I.C(Output Driver Impedance Control) + * Perform a write access to DDR2-SDRAM to acknowledge this command. + * The write address must be chosen so that BA[1] is set to 0 and BA[0] is set to 1. + */ + writel(AT91_DDRC2_MODE_EXT_LMR_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address + (0x1 << ba_offset)); + + /* An additional 200 cycles of clock are required for locking DLL */ + early_udelay(1); + + /* + * Step 9: Program DLL field into the Configuration Register to high(Enable DLL reset) + */ + cr = readl(base_address + AT91_HDDRSDRC2_CR); + writel(cr | AT91_DDRC2_ENABLE_RESET_DLL, base_address + AT91_HDDRSDRC2_CR); + + /* + * Step 10: A Mode Register set(MRS) cycle is issied to reset DLL. + * Perform a write access to DDR2-SDRAM to acknowledge this command. + * The write address must be chosen so that BA[1:0] bits are set to 0. + */ + writel(AT91_DDRC2_MODE_LMR_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address + (0x0 << ba_offset)); + + /* wait 2 cycles min (of tCK) = 15 ns min */ + early_udelay(1); + + /* + * Step 11: An all banks precharge command is issued to the DDR2-SDRAM. + */ + writel(AT91_DDRC2_MODE_PRCGALL_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address); + + /* wait 400 ns min (not needed on certain DDR2 devices) */ + early_udelay(1); + + /* + * Step 12: Two auto-refresh (CBR) cycles are provided. + * Program the auto refresh command (CBR) into the Mode Register. + */ + writel(AT91_DDRC2_MODE_RFSH_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address); + + /* wait TRFC cycles min (135 ns min) extended to 400 ns */ + early_udelay(1); + + /* Set 2nd CBR */ + writel(AT91_DDRC2_MODE_RFSH_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address); + + /* wait TRFC cycles min (135 ns min) extended to 400 ns */ + early_udelay(1); + + /* + * Step 13: Program DLL field into the Configuration Register to low(Disable DLL reset). + */ + cr = readl(base_address + AT91_HDDRSDRC2_CR); + writel(cr & ~AT91_DDRC2_ENABLE_RESET_DLL, base_address + AT91_HDDRSDRC2_CR); + + /* + * Step 14: A Mode Register set (MRS) cycle is issued to program + * the parameters of the DDR2-SDRAM devices, in particular CAS latency, + * burst length and to disable DDL reset. + * Perform a write access to DDR2-SDRAM to acknowledge this command. + * The write address must be chosen so that BA[1:0] bits are set to 0. + */ + writel(AT91_DDRC2_MODE_LMR_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address + (0x0 << ba_offset)); + + /* wait 2 cycles min (of tCK) = 15 ns min */ + early_udelay(1); + + /* + * Step 15: Program OCD field into the Configuration Register + * to high (OCD calibration default). + */ + cr = readl(base_address + AT91_HDDRSDRC2_CR); + writel(cr | AT91_DDRC2_OCD_DEFAULT, base_address + AT91_HDDRSDRC2_CR); + + /* wait 2 cycles min (of tCK) = 15 ns min */ + early_udelay(1); + + /* + * Step 16: An Extended Mode Register set (EMRS1) cycle is issued to OCD default value. + * Perform a write access to DDR2-SDRAM to acknowledge this command. + * The write address must be chosen so that BA[1] is set to 0 and BA[0] is set to 1. + */ + writel(AT91_DDRC2_MODE_EXT_LMR_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address + (0x1 << ba_offset)); + + /* wait 2 cycles min (of tCK) = 15 ns min */ + early_udelay(1); + + /* + * Step 17: Program OCD field into the Configuration Register + * to low (OCD calibration mode exit). + */ + cr = readl(base_address + AT91_HDDRSDRC2_CR); + writel(cr & ~AT91_DDRC2_OCD_DEFAULT, base_address + AT91_HDDRSDRC2_CR); + + /* wait 2 cycles min (of tCK) = 15 ns min */ + early_udelay(1); + + /* + * Step 18: An Extended Mode Register set (EMRS1) cycle is issued to enable OCD exit. + * Perform a write access to DDR2-SDRAM to acknowledge this command. + * The write address must be chosen so that BA[1] is set to 0 and BA[0] is set to 1. + */ + writel(AT91_DDRC2_MODE_EXT_LMR_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address + (0x1 << ba_offset)); + + /* wait 2 cycles min (of tCK) = 15 ns min */ + early_udelay(1); + + /* + * Step 19: A Nornal mode command is provided. + */ + writel(AT91_DDRC2_MODE_NORMAL_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address); + + /* + * Step 20: Perform a write access to any DDR2-SDRAM address + */ + writel(0, ram_address); + + /* + * Step 21: Write the refresh rate into the count field in the Refresh Timer register. + */ + writel(ddramc_config->rtr, base_address + AT91_HDDRSDRC2_RTR); + + /* + * Now we are ready to work on the DDRSDR + * wait for end of calibration + */ + early_udelay(10); +} + +/* This initialization sequence is sama5d3 and sama5d4 LP-DDR2 specific */ + +void at91_lpddr2_sdram_initialize(void __iomem *base_address, + void __iomem *ram_address, + struct at91_ddramc_register *ddramc_config) +{ + unsigned long reg; + + writel(ddramc_config->lpddr2_lpr, base_address + AT91_MPDDRC_LPDDR2_LPR); + + writel(ddramc_config->tim_calr, base_address + AT91_MPDDRC_LPDDR2_TIM_CAL); + + /* + * Step 1: Program the memory device type. + */ + writel(ddramc_config->mdr, base_address + AT91_HDDRSDRC2_MDR); + + /* + * Step 2: Program the feature of the low-power DDR2-SDRAM device. + */ + writel(ddramc_config->cr, base_address + AT91_HDDRSDRC2_CR); + + writel(ddramc_config->t0pr, base_address + AT91_HDDRSDRC2_T0PR); + writel(ddramc_config->t1pr, base_address + AT91_HDDRSDRC2_T1PR); + writel(ddramc_config->t2pr, base_address + AT91_HDDRSDRC2_T2PR); + + /* + * Step 3: A NOP command is issued to the low-power DDR2-SDRAM. + */ + writel(AT91_DDRC2_MODE_NOP_CMD, base_address + AT91_HDDRSDRC2_MR); + + /* + * Step 3bis: Add memory barrier then Perform a write access to + * any low-power DDR2-SDRAM address to acknowledge the command. + */ + dmb(); + writel(0, ram_address); + + /* + * Step 4: A pause of at least 100 ns must be observed before + * a single toggle. + */ + early_udelay(1); + + /* + * Step 5: A NOP command is issued to the low-power DDR2-SDRAM. + */ + writel(AT91_DDRC2_MODE_NOP_CMD, base_address + AT91_HDDRSDRC2_MR); + dmb(); + writel(0, ram_address); + + /* + * Step 6: A pause of at least 200 us must be observed before a Reset + * Command. + */ + early_udelay(200); + + /* + * Step 7: A Reset command is issued to the low-power DDR2-SDRAM. + */ + writel(AT91_DDRC2_MRS(63) | AT91_DDRC2_MODE_LPDDR2_CMD, + base_address + AT91_HDDRSDRC2_MR); + dmb(); + writel(0, ram_address); + + /* + * Step 8: A pause of at least tINIT5 must be observed before issuing + * any commands. + */ + early_udelay(1); + + /* + * Step 9: A Calibration command is issued to the low-power DDR2-SDRAM. + */ + reg = readl(base_address + AT91_HDDRSDRC2_CR); + reg &= ~AT91_DDRC2_ZQ; + reg |= AT91_DDRC2_ZQ_RESET; + writel(reg, base_address + AT91_HDDRSDRC2_CR); + + writel(AT91_DDRC2_MRS(10) | AT91_DDRC2_MODE_LPDDR2_CMD, + base_address + AT91_HDDRSDRC2_MR); + dmb(); + writel(0, ram_address); + + /* + * Step 9bis: The ZQ Calibration command is now issued. + * Program the type of calibration in the MPDDRC_CR: set the + * ZQ field to the SHORT value. + */ + reg = readl(base_address + AT91_HDDRSDRC2_CR); + reg &= ~AT91_DDRC2_ZQ; + reg |= AT91_DDRC2_ZQ_SHORT; + writel(reg, base_address + AT91_HDDRSDRC2_CR); + + /* + * Step 10: A Mode Register Write command with 1 to the MRS field + * is issued to the low-power DDR2-SDRAM. + */ + writel(AT91_DDRC2_MRS(1) | AT91_DDRC2_MODE_LPDDR2_CMD, + base_address + AT91_HDDRSDRC2_MR); + dmb(); + writel(0, ram_address); + + /* + * Step 11: A Mode Register Write command with 2 to the MRS field + * is issued to the low-power DDR2-SDRAM. + */ + writel(AT91_DDRC2_MRS(2) | AT91_DDRC2_MODE_LPDDR2_CMD, + base_address + AT91_HDDRSDRC2_MR); + dmb(); + writel(0, ram_address); + + /* + * Step 12: A Mode Register Write command with 3 to the MRS field + * is issued to the low-power DDR2-SDRAM. + */ + writel(AT91_DDRC2_MRS(3) | AT91_DDRC2_MODE_LPDDR2_CMD, + base_address + AT91_HDDRSDRC2_MR); + dmb(); + writel(0, ram_address); + + /* + * Step 13: A Mode Register Write command with 16 to the MRS field + * is issued to the low-power DDR2-SDRAM. + */ + writel(AT91_DDRC2_MRS(16) | AT91_DDRC2_MODE_LPDDR2_CMD, + base_address + AT91_HDDRSDRC2_MR); + dmb(); + writel(0, ram_address); + + /* + * Step 14: A Normal Mode command is provided. + */ + writel(AT91_DDRC2_MODE_NORMAL_CMD, base_address + AT91_HDDRSDRC2_MR); + dmb(); + writel(0, ram_address); + + /* + * Step 15: close the input buffers: error in documentation: no need. + */ + + /* + * Step 16: Write the refresh rate into the COUNT field in the MPDDRC + * Refresh Timer Register. + */ + writel(ddramc_config->rtr, base_address + AT91_HDDRSDRC2_RTR); + + /* + * Now configure the CAL MR4 register. + */ + writel(ddramc_config->cal_mr4r, base_address + AT91_MPDDRC_LPDDR2_CAL_MR4); +} + +void at91_lpddr1_sdram_initialize(void __iomem *base_address, + void __iomem *ram_address, + struct at91_ddramc_register *ddramc_config) +{ + unsigned long ba_offset; + + /* Compute BA[] offset according to CR configuration */ + ba_offset = (ddramc_config->cr & AT91_DDRC2_NC) + 8; + if (!(ddramc_config->cr & AT91_DDRC2_DECOD_INTERLEAVED)) + ba_offset += ((ddramc_config->cr & AT91_DDRC2_NR) >> 2) + 11; + + ba_offset += (ddramc_config->mdr & AT91_DDRC2_DBW) ? 1 : 2; + + /* + * Step 1: Program the memory device type in the MPDDRC Memory Device Register + */ + writel(ddramc_config->mdr, base_address + AT91_HDDRSDRC2_MDR); + + /* + * Step 2: Program the features of the low-power DDR1-SDRAM device + * in the MPDDRC Configuration Register and in the MPDDRC Timing + * Parameter 0 Register/MPDDRC Timing Parameter 1 Register. + */ + writel(ddramc_config->cr, base_address + AT91_HDDRSDRC2_CR); + + writel(ddramc_config->t0pr, base_address + AT91_HDDRSDRC2_T0PR); + writel(ddramc_config->t1pr, base_address + AT91_HDDRSDRC2_T1PR); + writel(ddramc_config->t2pr, base_address + AT91_HDDRSDRC2_T2PR); + + /* + * Step 3: Program Temperature Compensated Self-refresh (TCR), + * Partial Array Self-refresh (PASR) and Drive Strength (DS) parameters + * in the MPDDRC Low-power Register. + */ + writel(ddramc_config->lpr, base_address + AT91_HDDRSDRC2_LPR); + + /* + * Step 4: A NOP command is issued to the low-power DDR1-SDRAM. + * Program the NOP command in the MPDDRC Mode Register (MPDDRC_MR). + * The clocks which drive the low-power DDR1-SDRAM device + * are now enabled. + */ + writel(AT91_DDRC2_MODE_NOP_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address); + + /* + * Step 5: A pause of at least 200 us must be observed before + * a signal toggle. + */ + early_udelay(200); + + /* + * Step 6: A NOP command is issued to the low-power DDR1-SDRAM. + * Program the NOP command in the MPDDRC_MR. calibration request is + * now made to the I/O pad. + */ + writel(AT91_DDRC2_MODE_NOP_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address); + + /* + * Step 7: An All Banks Precharge command is issued + * to the low-power DDR1-SDRAM. + * Program All Banks Precharge command in the MPDDRC_MR. + */ + writel(AT91_DDRC2_MODE_PRCGALL_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address); + + /* + * Step 8: Two auto-refresh (CBR) cycles are provided. + * Program the Auto Refresh command (CBR) in the MPDDRC_MR. + * The application must write a four to the MODE field + * in the MPDDRC_MR. Perform a write access to any low-power + * DDR1-SDRAM location twice to acknowledge these commands. + */ + writel(AT91_DDRC2_MODE_RFSH_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address); + + writel(AT91_DDRC2_MODE_RFSH_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address); + + /* + * Step 9: An Extended Mode Register Set (EMRS) cycle is issued to + * program the low-power DDR1-SDRAM parameters (TCSR, PASR, DS). + * The application must write a five to the MODE field in the MPDDRC_MR + * and perform a write access to the SDRAM to acknowledge this command. + * The write address must be chosen so that signal BA[1] is set to 1 + * and BA[0] is set to 0. + */ + writel(AT91_DDRC2_MODE_EXT_LMR_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address + (0x2 << ba_offset)); + + /* + * Step 10: A Mode Register Set (MRS) cycle is issued to program + * parameters of the low-power DDR1-SDRAM devices, in particular + * CAS latency. + * The application must write a three to the MODE field in the MPDDRC_MR + * and perform a write access to the SDRAM to acknowledge this command. + * The write address must be chosen so that signals BA[1:0] are set to 0. + */ + writel(AT91_DDRC2_MODE_LMR_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address + (0x0 << ba_offset)); + + /* + * Step 11: The application must enter Normal mode, write a zero + * to the MODE field in the MPDDRC_MR and perform a write access + * at any location in the SDRAM to acknowledge this command. + */ + writel(AT91_DDRC2_MODE_NORMAL_CMD, base_address + AT91_HDDRSDRC2_MR); + writel(0, ram_address); + + /* + * Step 12: Perform a write access to any low-power DDR1-SDRAM address. + */ + writel(0, ram_address); + + /* + * Step 14: Write the refresh rate into the COUNT field in the MPDDRC + * Refresh Timer Register (MPDDRC_RTR): + */ + writel(ddramc_config->rtr, base_address + AT91_HDDRSDRC2_RTR); +} diff --git a/arch/arm/mach-at91/include/mach/ddramc.h b/arch/arm/mach-at91/include/mach/ddramc.h new file mode 100644 index 0000000000..0b33afc213 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/ddramc.h @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: BSD-1-Clause +/* + * Copyright (c) 2006, Atmel Corporation + */ +#ifndef __DDRAMC_H__ +#define __DDRAMC_H__ + +/* Note: reserved bits must always be zeroed */ +struct at91_ddramc_register { + unsigned long mdr; + unsigned long cr; + unsigned long rtr; + unsigned long t0pr; + unsigned long t1pr; + unsigned long t2pr; + unsigned long lpr; + unsigned long lpddr2_lpr; + unsigned long tim_calr; + unsigned long cal_mr4r; +}; + +void at91_ddram_initialize(void __iomem *base_address, + void __iomem *ram_address, + struct at91_ddramc_register *ddramc_config); + +void at91_lpddr2_sdram_initialize(void __iomem *base_address, + void __iomem *ram_address, + struct at91_ddramc_register *ddramc_config); + + +void at91_lpddr1_sdram_initialize(void __iomem *base_address, + void __iomem *ram_address, + struct at91_ddramc_register *ddramc_config); + + +#endif /* #ifndef __DDRAMC_H__ */ -- cgit v1.2.3 From 0dbd1a8bd5399ee81a657e69da04b64d9d6756ef Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:02 +0200 Subject: ARM: at91: watchdog: implement at91_wdt_disable Board code might want to disable the watchdog in PBL and enable it later prior to boot. Provide a helper to do so. Reviewed-by: Sam Ravnborg Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/include/mach/at91_wdt.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/include/mach/at91_wdt.h b/arch/arm/mach-at91/include/mach/at91_wdt.h index 36d37b9d2d..d295d35d1b 100644 --- a/arch/arm/mach-at91/include/mach/at91_wdt.h +++ b/arch/arm/mach-at91/include/mach/at91_wdt.h @@ -35,4 +35,20 @@ #define AT91_WDT_WDUNF (1 << 0) /* Watchdog Underflow */ #define AT91_WDT_WDERR (1 << 1) /* Watchdog Error */ +#ifndef __ASSEMBLY__ +// SPDX-License-Identifier: BSD-1-Clause +/* + * Copyright (c) 2006, Atmel Corporation + */ + +#include + +static inline void at91_wdt_disable(void __iomem *wdt_base) +{ + u32 reg = readl(wdt_base + AT91_WDT_MR); + reg |= AT91_WDT_WDDIS; + writel(reg, wdt_base + AT91_WDT_MR); +} + +#endif /* __ASSEMBLY__ */ #endif -- cgit v1.2.3 From 652fa3610aef231789c139ae6c3e49b244f873fa Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:04 +0200 Subject: ARM: at91: implement sama5d2 lowlevel init Port over the low level initialization for sama5d2 SoCs from at91bootstrap. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/boards/sama5d27-giantboard/lowlevel.c | 9 +-- arch/arm/boards/sama5d27-som1/lowlevel.c | 9 +-- arch/arm/mach-at91/Makefile | 1 + arch/arm/mach-at91/include/mach/at91_pmc.h | 22 +++++++ arch/arm/mach-at91/include/mach/sama5d2_ll.h | 27 +++++++++ arch/arm/mach-at91/sama5d2_ll.c | 80 ++++++++++++++++++++++++++ 6 files changed, 132 insertions(+), 16 deletions(-) create mode 100644 arch/arm/mach-at91/include/mach/sama5d2_ll.h create mode 100644 arch/arm/mach-at91/sama5d2_ll.c (limited to 'arch/arm') diff --git a/arch/arm/boards/sama5d27-giantboard/lowlevel.c b/arch/arm/boards/sama5d27-giantboard/lowlevel.c index 50bc2613c6..e08217105b 100644 --- a/arch/arm/boards/sama5d27-giantboard/lowlevel.c +++ b/arch/arm/boards/sama5d27-giantboard/lowlevel.c @@ -8,9 +8,7 @@ #include #include -#include - -#include +#include #include #include #include @@ -18,11 +16,6 @@ /* PCK = 492MHz, MCK = 164MHz */ #define MASTER_CLOCK 164000000 -static inline void sama5d2_pmc_enable_periph_clock(int clk) -{ - at91_pmc_sam9x5_enable_periph_clock(SAMA5D2_BASE_PMC, clk); -} - static void dbgu_init(void) { unsigned mck = MASTER_CLOCK / 2; diff --git a/arch/arm/boards/sama5d27-som1/lowlevel.c b/arch/arm/boards/sama5d27-som1/lowlevel.c index 569960be44..2b39e5abc3 100644 --- a/arch/arm/boards/sama5d27-som1/lowlevel.c +++ b/arch/arm/boards/sama5d27-som1/lowlevel.c @@ -8,9 +8,7 @@ #include #include -#include - -#include +#include #include #include #include @@ -22,11 +20,6 @@ /* PCK = 492MHz, MCK = 164MHz */ #define MASTER_CLOCK 164000000 -static inline void sama5d2_pmc_enable_periph_clock(int clk) -{ - at91_pmc_sam9x5_enable_periph_clock(SAMA5D2_BASE_PMC, clk); -} - static void ek_turn_led(unsigned color) { struct { diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index a7e9ce5938..ea39d7d8c2 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -25,6 +25,7 @@ ifeq ($(CONFIG_OFDEVICE),) obj-$(CONFIG_SOC_AT91SAM9263) += at91sam9263.o at91sam9263_devices.o obj-$(CONFIG_SOC_SAMA5D3) += sama5d3.o sama5d3_devices.o endif +lwl-$(CONFIG_SOC_SAMA5D2) += sama5d2_ll.o obj-$(CONFIG_SOC_AT91SAM9G20) += at91sam9260.o at91sam9260_devices.o obj-$(CONFIG_SOC_AT91SAM9G45) += at91sam9g45.o at91sam9g45_devices.o obj-$(CONFIG_SOC_AT91SAM9X5) += at91sam9x5.o at91sam9x5_devices.o diff --git a/arch/arm/mach-at91/include/mach/at91_pmc.h b/arch/arm/mach-at91/include/mach/at91_pmc.h index 4d60becefb..66b4e49286 100644 --- a/arch/arm/mach-at91/include/mach/at91_pmc.h +++ b/arch/arm/mach-at91/include/mach/at91_pmc.h @@ -42,6 +42,7 @@ #define AT91_CKGR_UCKR 0x1C /* UTMI Clock Register [some SAM9] */ #define AT91_PMC_UPLLEN (1 << 16) /* UTMI PLL Enable */ #define AT91_PMC_UPLLCOUNT (0xf << 20) /* UTMI PLL Start-up Time */ +#define AT91_PMC_UPLLCOUNT_DEFAULT (0x1UL << 20) #define AT91_PMC_BIASEN (1 << 24) /* UTMI BIAS Enable */ #define AT91_PMC_BIASCOUNT (0xf << 28) /* UTMI BIAS Start-up Time */ @@ -66,9 +67,17 @@ #define AT91_CKGR_PLLAR 0x28 /* PLL A Register */ #define AT91_CKGR_PLLBR 0x2c /* PLL B Register */ #define AT91_PMC_DIV (0xff << 0) /* Divider */ +#define AT91_PMC_DIV_BYPASS (1 << 0) /* Divider bypass */ #define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */ #define AT91_PMC_OUT (3 << 14) /* PLL Clock Frequency Range */ +#define AT91_PMC_OUT_0 (0 << 14) +#define AT91_PMC_OUT_1 (1 << 14) +#define AT91_PMC_OUT_2 (2 << 14) +#define AT91_PMC_OUT_3 (3 << 14) #define AT91_PMC_MUL (0x7ff << 16) /* PLL Multiplier */ +#define AT91_PMC_MUL_(n) (((n) << 16) & AT91_PMC_MUL) +#define AT91_PMC3_MUL (0x7f << 18) /* PLL Multiplier [SAMA5 only]*/ +#define AT91_PMC3_MUL_(n) (((n) << 18) & AT91_PMC3_MUL) #define AT91_PMC_USBDIV (3 << 28) /* USB Divisor (PLLB only) */ #define AT91_PMC_USBDIV_1 (0 << 28) #define AT91_PMC_USBDIV_2 (1 << 28) @@ -153,6 +162,7 @@ #define AT91_PMC_MOSCSELS (1 << 16) /* Main Oscillator Selection [some SAM9] */ #define AT91_PMC_MOSCRCS (1 << 17) /* Main On-Chip RC [some SAM9] */ #define AT91_PMC_CFDEV (1 << 18) /* Clock Failure Detector Event [some SAM9] */ +#define AT91_PMC_GCKRDY (1 << 24) #define AT91_PMC_IMR 0x6c /* Interrupt Mask Register */ #define AT91_PMC_PLLICPR 0x80 /* PLL Charge Pump Current Register */ #define AT91_PMC_ICPPLLA (0xf << 0) @@ -179,6 +189,13 @@ #define AT91_PMC_PCR 0x10c /* Peripheral Control Register [some SAM9] */ #define AT91_PMC_PCR_PID (0x3f << 0) /* Peripheral ID */ +#define AT91_PMC_GCKCSS (0x7 << 8) +#define AT91_PMC_GCKCSS_SLOW_CLK (0x0 << 8) +#define AT91_PMC_GCKCSS_MAIN_CLK (0x1 << 8) +#define AT91_PMC_GCKCSS_PLLA_CLK (0x2 << 8) +#define AT91_PMC_GCKCSS_UPLL_CLK (0x3 << 8) +#define AT91_PMC_GCKCSS_MCK_CLK (0x4 << 8) +#define AT91_PMC_GCKCSS_AUDIO_CLK (0x5 << 8) #define AT91_PMC_PCR_CMD (0x1 << 12) /* Command */ #define AT91_PMC_PCR_DIV_MASK (0x3 << 16) #define AT91_PMC_PCR_DIV(n) ((n) << 16) /* Divisor value */ @@ -186,7 +203,12 @@ #define AT91_PMC_PCR_DIV2 0x1 /* Peripheral clock is MCK/2 */ #define AT91_PMC_PCR_DIV4 0x2 /* Peripheral clock is MCK/4 */ #define AT91_PMC_PCR_DIV8 0x3 /* Peripheral clock is MCK/8 */ +#define AT91_PMC_GCKDIV (0xff << 20) +#define AT91_PMC_GCKDIV_MSK 0xff +#define AT91_PMC_GCKDIV_OFFSET 20 +#define AT91_PMC_GCKDIV_(x) (((x) & AT91_PMC_GCKDIV_MSK) << AT91_PMC_GCKDIV_OFFSET) #define AT91_PMC_PCR_EN (0x1 << 28) /* Enable */ +#define AT91_PMC_GCK_EN (0x1 << 29) #define AT91_PMC_PCER1 0x100 /* Peripheral Clock Enable Register 1 */ #define AT91_PMC_PCDR1 0x104 /* Peripheral Clock Disable Register 1 */ diff --git a/arch/arm/mach-at91/include/mach/sama5d2_ll.h b/arch/arm/mach-at91/include/mach/sama5d2_ll.h new file mode 100644 index 0000000000..7c38a84f53 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/sama5d2_ll.h @@ -0,0 +1,27 @@ +#ifndef __MACH_SAMA5D2_LL__ +#define __MACH_SAMA5D2_LL__ + +#include +#include +#include +#include + +#include + +static inline void sama5d2_pmc_enable_periph_clock(int clk) +{ + at91_pmc_sam9x5_enable_periph_clock(SAMA5D2_BASE_PMC, clk); +} + +void sama5d2_lowlevel_init(void); + +/* requires relocation */ +static inline void sama5d2_udelay_init(unsigned int msc) +{ + early_udelay_init(SAMA5D2_BASE_PMC, SAMA5D2_BASE_PITC, + SAMA5D2_ID_PIT, msc, AT91_PMC_LL_SAMA5D2); +} + +void sama5d2_ddr2_init(struct at91_ddramc_register *ddramc_reg_config); + +#endif diff --git a/arch/arm/mach-at91/sama5d2_ll.c b/arch/arm/mach-at91/sama5d2_ll.c new file mode 100644 index 0000000000..a038bf4b86 --- /dev/null +++ b/arch/arm/mach-at91/sama5d2_ll.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: BSD-1-Clause +/* + * Copyright (c) 2017, Microchip Corporation + * + * Microchip's name may not be used to endorse or promote products derived + * from this software without specific prior written permission. + */ + +#include +#include +#include +#include +#include +#include + +#define sama5d2_pmc_write(off, val) writel(val, SAMA5D2_BASE_PMC + off) +#define sama5d2_pmc_read(off) readl(SAMA5D2_BASE_PMC + off) + +void sama5d2_ddr2_init(struct at91_ddramc_register *ddramc_reg_config) +{ + unsigned int reg; + + /* enable ddr2 clock */ + sama5d2_pmc_enable_periph_clock(SAMA5D2_ID_MPDDRC); + sama5d2_pmc_write(AT91_PMC_SCER, AT91CAP9_PMC_DDR); + + reg = AT91_MPDDRC_RD_DATA_PATH_ONE_CYCLES; + writel(reg, SAMA5D2_BASE_MPDDRC + AT91_MPDDRC_RD_DATA_PATH); + + reg = readl(SAMA5D2_BASE_MPDDRC + AT91_MPDDRC_IO_CALIBR); + reg &= ~AT91_MPDDRC_RDIV; + reg &= ~AT91_MPDDRC_TZQIO; + reg |= AT91_MPDDRC_RDIV_DDR2_RZQ_50; + reg |= AT91_MPDDRC_TZQIO_(101); + writel(reg, SAMA5D2_BASE_MPDDRC + AT91_MPDDRC_IO_CALIBR); + + /* DDRAM2 Controller initialize */ + at91_ddram_initialize(SAMA5D2_BASE_MPDDRC, IOMEM(SAMA5_DDRCS), + ddramc_reg_config); +} + +static void sama5d2_pmc_init(void) +{ + at91_pmc_init(SAMA5D2_BASE_PMC, AT91_PMC_LL_SAMA5D2); + + /* Configure PLLA = MOSC * (PLL_MULA + 1) / PLL_DIVA */ + sama5d2_pmc_write(AT91_CKGR_PLLAR, AT91_PMC_PLLA_WR_ERRATA); + sama5d2_pmc_write(AT91_CKGR_PLLAR, AT91_PMC_PLLA_WR_ERRATA + | AT91_PMC3_MUL_(40) | AT91_PMC_OUT_0 + | AT91_PMC_PLLCOUNT + | AT91_PMC_DIV_BYPASS); + + while (!(sama5d2_pmc_read(AT91_PMC_SR) & AT91_PMC_LOCKA)) + ; + + /* Initialize PLLA charge pump */ + /* No need: we keep what is set in ROM code */ + //sama5d2_pmc_write(AT91_PMC_PLLICPR, AT91_PMC_IPLLA_3); + + /* Switch PCK/MCK on PLLA output */ + at91_pmc_cfg_mck(SAMA5D2_BASE_PMC, + AT91_PMC_H32MXDIV + | AT91_PMC_PLLADIV2_ON + | AT91SAM9_PMC_MDIV_3 + | AT91_PMC_CSS_PLLA, + AT91_PMC_LL_SAMA5D2); +} + +static void sama5d2_rstc_init(void) +{ + writel(AT91_RSTC_KEY | AT91_RSTC_URSTEN, + SAMA5D2_BASE_RSTC + AT91_RSTC_MR); +} + +void sama5d2_lowlevel_init(void) +{ + arm_cpu_lowlevel_init(); + sama5d2_pmc_init(); + sama5d2_rstc_init(); +} -- cgit v1.2.3 From 6199e561e17f52233d852c6037865693e9dd82cc Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:05 +0200 Subject: ARM: at91: sama5d2: add sama5d2 matrix configuration Different peripherals, including the SDRAM, are unusable without prior matrix configuration. Port over the necessary at91bootstrap parts for sama5d2 use. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/Makefile | 2 +- arch/arm/mach-at91/include/mach/matrix.h | 21 +++++ arch/arm/mach-at91/include/mach/tz_matrix.h | 95 +++++++++++++++++++ arch/arm/mach-at91/matrix.c | 45 +++++++++ arch/arm/mach-at91/sama5d2_ll.c | 140 ++++++++++++++++++++++++++++ 5 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-at91/include/mach/matrix.h create mode 100644 arch/arm/mach-at91/include/mach/tz_matrix.h create mode 100644 arch/arm/mach-at91/matrix.c (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index ea39d7d8c2..6aaef7c531 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -1,5 +1,5 @@ obj-y += setup.o -lwl-y += at91_pmc_ll.o ddramc_ll.o +lwl-y += at91_pmc_ll.o ddramc_ll.o matrix.o lwl-$(CONFIG_CLOCKSOURCE_ATMEL_PIT) += early_udelay.o ifeq ($(CONFIG_COMMON_CLK_OF_PROVIDER),) diff --git a/arch/arm/mach-at91/include/mach/matrix.h b/arch/arm/mach-at91/include/mach/matrix.h new file mode 100644 index 0000000000..5dbfcfe414 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/matrix.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-1-Clause */ +/* + * Copyright (c) 2013, Atmel Corporation + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + */ +#ifndef __MATRIX_H__ +#define __MATRIX_H__ + +#include + +void at91_matrix_write_protect_enable(void __iomem *matrix_base); +void at91_matrix_write_protect_disable(void __iomem *matrix_base); +void at91_matrix_configure_slave_security(void __iomem *matrix_base, + unsigned int slave, + unsigned int srtop_setting, + unsigned int srsplit_setting, + unsigned int ssr_setting); + +#endif /* #ifndef __MATRIX_H__ */ diff --git a/arch/arm/mach-at91/include/mach/tz_matrix.h b/arch/arm/mach-at91/include/mach/tz_matrix.h new file mode 100644 index 0000000000..85589bfa65 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/tz_matrix.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: BSD-1-Clause */ +/* + * Copyright (c) 2013, Atmel Corporation + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + */ +#ifndef __TZ_MATRIX_H__ +#define __TZ_MATRIX_H__ + +#define MATRIX_MCFG(n) (0x0000 + (n) * 4)/* Master Configuration Register */ +#define MATRIX_SCFG(n) (0x0040 + (n) * 4)/* Slave Configuration Register */ +#define MATRIX_PRAS(n) (0x0080 + (n) * 8)/* Priority Register A for Slave */ +#define MATRIX_PRBS(n) (0x0084 + (n) * 8)/* Priority Register B for Slave */ + +#define MATRIX_MRCR 0x0100 /* Master Remap Control Register */ +#define MATRIX_MEIER 0x0150 /* Master Error Interrupt Enable Register */ +#define MATRIX_MEIDR 0x0154 /* Master Error Interrupt Disable Register */ +#define MATRIX_MEIMR 0x0158 /* Master Error Interrupt Mask Register */ +#define MATRIX_MESR 0x015c /* Master Error Statue Register */ + +/* Master n Error Address Register */ +#define MATRIX_MEAR(n) (0x0160 + (n) * 4) + +#define MATRIX_WPMR 0x01E4 /* Write Protect Mode Register */ +#define MATRIX_WPSR 0x01E8 /* Write Protect Status Register */ + +/* Security Slave n Register */ +#define MATRIX_SSR(n) (0x0200 + (n) * 4) +/* Security Area Split Slave n Register */ +#define MATRIX_SASSR(n) (0x0240 + (n) * 4) +/* Security Region Top Slave n Register */ +#define MATRIX_SRTSR(n) (0x0280 + (n) * 4) + +/* Security Peripheral Select n Register */ +#define MATRIX_SPSELR(n) (0x02c0 + (n) * 4) + +/**************************************************************************/ +/* Write Protect Mode Register (MATRIX_WPMR) */ +#define MATRIX_WPMR_WPEN (1 << 0) /* Write Protect Enable */ +#define MATRIX_WPMR_WPEN_DISABLE (0 << 0) +#define MATRIX_WPMR_WPEN_ENABLE (1 << 0) +#define MATRIX_WPMR_WPKEY (PASSWD << 8) /* Write Protect KEY */ +#define MATRIX_WPMR_WPKEY_PASSWD (0x4D4154 << 8) + +/* Security Slave Registers (MATRIX_SSRx) */ +#define MATRIX_LANSECH(n, bit) ((bit) << n) +#define MATRIX_LANSECH_S(n) (0x00 << n) +#define MATRIX_LANSECH_NS(n) (0x01 << n) +#define MATRIX_RDNSECH(n, bit) ((bit) << (n + 8)) +#define MATRIX_RDNSECH_S(n) (0x00 << (n + 8)) +#define MATRIX_RDNSECH_NS(n) (0x01 << (n + 8)) +#define MATRIX_WRNSECH(n, bit) ((bit) << (n + 16)) +#define MATRIX_WRNSECH_S(n) (0x00 << (n + 16)) +#define MATRIX_WRNSECH_NS(n) (0x01 << (n + 16)) + +/* Security Areas Split Slave Registers (MATRIX_SASSRx) */ +#define MATRIX_SASPLIT(n, value) ((value) << (4 * n)) +#define MATRIX_SASPLIT_VALUE_4K 0x00 +#define MATRIX_SASPLIT_VALUE_8K 0x01 +#define MATRIX_SASPLIT_VALUE_16K 0x02 +#define MATRIX_SASPLIT_VALUE_32K 0x03 +#define MATRIX_SASPLIT_VALUE_64K 0x04 +#define MATRIX_SASPLIT_VALUE_128K 0x05 +#define MATRIX_SASPLIT_VALUE_256K 0x06 +#define MATRIX_SASPLIT_VALUE_512K 0x07 +#define MATRIX_SASPLIT_VALUE_1M 0x08 +#define MATRIX_SASPLIT_VALUE_2M 0x09 +#define MATRIX_SASPLIT_VALUE_4M 0x0a +#define MATRIX_SASPLIT_VALUE_8M 0x0b +#define MATRIX_SASPLIT_VALUE_16M 0x0c +#define MATRIX_SASPLIT_VALUE_32M 0x0d +#define MATRIX_SASPLIT_VALUE_64M 0x0e +#define MATRIX_SASPLIT_VALUE_128M 0x0f + +/* Security Region Top Slave Registers (MATRIX_SRTSRx) */ +#define MATRIX_SRTOP(n, value) ((value) << (4 * n)) +#define MATRIX_SRTOP_VALUE_4K 0x00 +#define MATRIX_SRTOP_VALUE_8K 0x01 +#define MATRIX_SRTOP_VALUE_16K 0x02 +#define MATRIX_SRTOP_VALUE_32K 0x03 +#define MATRIX_SRTOP_VALUE_64K 0x04 +#define MATRIX_SRTOP_VALUE_128K 0x05 +#define MATRIX_SRTOP_VALUE_256K 0x06 +#define MATRIX_SRTOP_VALUE_512K 0x07 +#define MATRIX_SRTOP_VALUE_1M 0x08 +#define MATRIX_SRTOP_VALUE_2M 0x09 +#define MATRIX_SRTOP_VALUE_4M 0x0a +#define MATRIX_SRTOP_VALUE_8M 0x0b +#define MATRIX_SRTOP_VALUE_16M 0x0c +#define MATRIX_SRTOP_VALUE_32M 0x0d +#define MATRIX_SRTOP_VALUE_64M 0x0e +#define MATRIX_SRTOP_VALUE_128M 0x0f + +#endif /* #ifndef __TZ_MATRIX_H__ */ diff --git a/arch/arm/mach-at91/matrix.c b/arch/arm/mach-at91/matrix.c new file mode 100644 index 0000000000..b2e7345ec1 --- /dev/null +++ b/arch/arm/mach-at91/matrix.c @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: BSD-1-Clause */ +/* + * Copyright (c) 2013, Atmel Corporation + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + */ + +#include +#include +#include + +static inline void matrix_write(void __iomem *base, + unsigned int offset, + const unsigned int value) +{ + writel(value, base + offset); +} + +static inline unsigned int matrix_read(void __iomem *base, unsigned int offset) +{ + return readl(base + offset); +} + +void at91_matrix_write_protect_enable(void __iomem *matrix_base) +{ + matrix_write(matrix_base, MATRIX_WPMR, + MATRIX_WPMR_WPKEY_PASSWD | MATRIX_WPMR_WPEN_ENABLE); +} + +void at91_matrix_write_protect_disable(void __iomem *matrix_base) +{ + matrix_write(matrix_base, MATRIX_WPMR, MATRIX_WPMR_WPKEY_PASSWD); +} + +void at91_matrix_configure_slave_security(void __iomem *matrix_base, + unsigned int slave, + unsigned int srtop_setting, + unsigned int srsplit_setting, + unsigned int ssr_setting) +{ + matrix_write(matrix_base, MATRIX_SSR(slave), ssr_setting); + matrix_write(matrix_base, MATRIX_SRTSR(slave), srtop_setting); + matrix_write(matrix_base, MATRIX_SASSR(slave), srsplit_setting); +} diff --git a/arch/arm/mach-at91/sama5d2_ll.c b/arch/arm/mach-at91/sama5d2_ll.c index a038bf4b86..c3b5061777 100644 --- a/arch/arm/mach-at91/sama5d2_ll.c +++ b/arch/arm/mach-at91/sama5d2_ll.c @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include @@ -66,6 +68,143 @@ static void sama5d2_pmc_init(void) AT91_PMC_LL_SAMA5D2); } +static void matrix_configure_slave(void) +{ + u32 ddr_port; + u32 ssr_setting, sasplit_setting, srtop_setting; + + /* + * Matrix 0 (H64MX) + */ + + /* + * 0: Bridge from H64MX to AXIMX + * (Internal ROM, Crypto Library, PKCC RAM): Always Secured + */ + + /* 1: H64MX Peripheral Bridge */ + + /* 2 ~ 9 DDR2 Port0 ~ 7: Non-Secure */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128M); + sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_128M); + ssr_setting = MATRIX_LANSECH_NS(0) | + MATRIX_RDNSECH_NS(0) | + MATRIX_WRNSECH_NS(0); + for (ddr_port = 0; ddr_port < 8; ddr_port++) { + at91_matrix_configure_slave_security(SAMA5D2_BASE_MATRIX64, + SAMA5D2_H64MX_SLAVE_DDR2_PORT_0 + ddr_port, + srtop_setting, + sasplit_setting, + ssr_setting); + } + + /* + * 10: Internal SRAM 128K + * TOP0 is set to 128K + * SPLIT0 is set to 64K + * LANSECH0 is set to 0, the low area of region 0 is the Securable one + * RDNSECH0 is set to 0, region 0 Securable area is secured for reads. + * WRNSECH0 is set to 0, region 0 Securable area is secured for writes + */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128K); + sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_64K); + ssr_setting = MATRIX_LANSECH_S(0) | + MATRIX_RDNSECH_S(0) | + MATRIX_WRNSECH_S(0); + at91_matrix_configure_slave_security(SAMA5D2_BASE_MATRIX64, + SAMA5D2_H64MX_SLAVE_INTERNAL_SRAM, + srtop_setting, + sasplit_setting, + ssr_setting); + + /* 11: Internal SRAM 128K (Cache L2) */ + /* 12: QSPI0 */ + /* 13: QSPI1 */ + /* 14: AESB */ + + /* + * Matrix 1 (H32MX) + */ + + /* 0: Bridge from H32MX to H64MX: Not Secured */ + + /* 1: H32MX Peripheral Bridge 0: Not Secured */ + + /* 2: H32MX Peripheral Bridge 1: Not Secured */ + + /* + * 3: External Bus Interface + * EBI CS0 Memory(256M) ----> Slave Region 0, 1 + * EBI CS1 Memory(256M) ----> Slave Region 2, 3 + * EBI CS2 Memory(256M) ----> Slave Region 4, 5 + * EBI CS3 Memory(128M) ----> Slave Region 6 + * NFC Command Registers(128M) -->Slave Region 7 + * + * NANDFlash(EBI CS3) --> Slave Region 6: Non-Secure + */ + srtop_setting = MATRIX_SRTOP(6, MATRIX_SRTOP_VALUE_128M) | + MATRIX_SRTOP(7, MATRIX_SRTOP_VALUE_128M); + sasplit_setting = MATRIX_SASPLIT(6, MATRIX_SASPLIT_VALUE_128M) | + MATRIX_SASPLIT(7, MATRIX_SASPLIT_VALUE_128M); + ssr_setting = MATRIX_LANSECH_NS(6) | + MATRIX_RDNSECH_NS(6) | + MATRIX_WRNSECH_NS(6) | + MATRIX_LANSECH_NS(7) | + MATRIX_RDNSECH_NS(7) | + MATRIX_WRNSECH_NS(7); + at91_matrix_configure_slave_security(SAMA5D2_BASE_MATRIX32, + SAMA5D2_H32MX_EXTERNAL_EBI, + srtop_setting, + sasplit_setting, + ssr_setting); + + /* 4: NFC SRAM (4K): Non-Secure */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_8K); + sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_8K); + ssr_setting = MATRIX_LANSECH_NS(0) | + MATRIX_RDNSECH_NS(0) | + MATRIX_WRNSECH_NS(0); + at91_matrix_configure_slave_security(SAMA5D2_BASE_MATRIX32, + SAMA5D2_H32MX_NFC_SRAM, + srtop_setting, + sasplit_setting, + ssr_setting); + + /* 5: + * USB Device High Speed Dual Port RAM (DPR): 1M + * USB Host OHCI registers: 1M + * USB Host EHCI registers: 1M + */ + srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_1M) | + MATRIX_SRTOP(1, MATRIX_SRTOP_VALUE_1M) | + MATRIX_SRTOP(2, MATRIX_SRTOP_VALUE_1M); + sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_1M) | + MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_1M) | + MATRIX_SASPLIT(2, MATRIX_SASPLIT_VALUE_1M); + ssr_setting = MATRIX_LANSECH_NS(0) | + MATRIX_LANSECH_NS(1) | + MATRIX_LANSECH_NS(2) | + MATRIX_RDNSECH_NS(0) | + MATRIX_RDNSECH_NS(1) | + MATRIX_RDNSECH_NS(2) | + MATRIX_WRNSECH_NS(0) | + MATRIX_WRNSECH_NS(1) | + MATRIX_WRNSECH_NS(2); + at91_matrix_configure_slave_security(SAMA5D2_BASE_MATRIX32, + SAMA5D2_H32MX_USB, + srtop_setting, + sasplit_setting, + ssr_setting); +} + +static void sama5d2_matrix_init(void) +{ + at91_matrix_write_protect_disable(SAMA5D2_BASE_MATRIX64); + at91_matrix_write_protect_disable(SAMA5D2_BASE_MATRIX32); + + matrix_configure_slave(); +} + static void sama5d2_rstc_init(void) { writel(AT91_RSTC_KEY | AT91_RSTC_URSTEN, @@ -76,5 +215,6 @@ void sama5d2_lowlevel_init(void) { arm_cpu_lowlevel_init(); sama5d2_pmc_init(); + sama5d2_matrix_init(); sama5d2_rstc_init(); } -- cgit v1.2.3 From c0edbe48a4e00194cf4490b7c673e6f4a91d251f Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:06 +0200 Subject: ARM: at91: add sama5d2 cache init The L2 cache controller needs some initialization before use. Same goes for the CAN SRAM, do so after the MMU setup. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/Makefile | 1 + arch/arm/mach-at91/sama5d2.c | 52 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 arch/arm/mach-at91/sama5d2.c (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 6aaef7c531..7c8399ee76 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_SOC_AT91SAM9263) += at91sam9263.o at91sam9263_devices.o obj-$(CONFIG_SOC_SAMA5D3) += sama5d3.o sama5d3_devices.o endif lwl-$(CONFIG_SOC_SAMA5D2) += sama5d2_ll.o +obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o obj-$(CONFIG_SOC_AT91SAM9G20) += at91sam9260.o at91sam9260_devices.o obj-$(CONFIG_SOC_AT91SAM9G45) += at91sam9g45.o at91sam9g45_devices.o obj-$(CONFIG_SOC_AT91SAM9X5) += at91sam9x5.o at91sam9x5_devices.o diff --git a/arch/arm/mach-at91/sama5d2.c b/arch/arm/mach-at91/sama5d2.c new file mode 100644 index 0000000000..2f74b0b38d --- /dev/null +++ b/arch/arm/mach-at91/sama5d2.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include +#include + +#define SFR_CAN 0x48 +#define SFR_L2CC_HRAMC 0x58 + +static void sama5d2_can_ram_init(void) +{ + writel(0x00210021, SAMA5D2_BASE_SFR + SFR_CAN); +} + +static void sama5d2_l2x0_init(void) +{ + void __iomem *l2x0_base = SAMA5D2_BASE_L2CC; + u32 cfg; + + writel(0x1, SAMA5D2_BASE_SFR + SFR_L2CC_HRAMC); + + /* Prefetch Control */ + cfg = readl(l2x0_base + L2X0_PREFETCH_CTRL); + /* prefetch offset: TODO find proper values */ + cfg |= 0x1; + cfg |= L2X0_INCR_DOUBLE_LINEFILL_EN | L2X0_PREFETCH_DROP_EN + | L2X0_DOUBLE_LINEFILL_EN; + cfg |= L2X0_DATA_PREFETCH_EN | L2X0_INSTRUCTION_PREFETCH_EN; + writel(cfg, l2x0_base + L2X0_PREFETCH_CTRL); + + /* Power Control */ + cfg = readl(l2x0_base + L2X0_POWER_CTRL); + cfg |= L2X0_STNDBY_MODE_EN | L2X0_DYNAMIC_CLK_GATING_EN; + writel(cfg, l2x0_base + L2X0_POWER_CTRL); + + l2x0_init(l2x0_base, 0x0, ~0UL); +} + +static int sama5d2_init(void) +{ + if (!of_machine_is_compatible("atmel,sama5d2")) + return 0; + + sama5d2_can_ram_init(); + sama5d2_l2x0_init(); + + return 0; +} +postmmu_initcall(sama5d2_init); -- cgit v1.2.3 From 53d48be1757d379bcdeb94a63deeeea8e9965353 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:07 +0200 Subject: ARM: at91: add necessary Advanced Interrupt Controller configuration Without reconfiguration of the AIC redirection, the OS interrupt handling will misbehave later on. Add it to the SoC init. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/Makefile | 2 +- arch/arm/mach-at91/aic.c | 28 ++++++++++++++++++++++++++++ arch/arm/mach-at91/include/mach/aic.h | 9 +++++++++ arch/arm/mach-at91/sama5d2.c | 2 ++ 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-at91/aic.c create mode 100644 arch/arm/mach-at91/include/mach/aic.h (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 7c8399ee76..254bbeef27 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -1,4 +1,4 @@ -obj-y += setup.o +obj-y += setup.o aic.o lwl-y += at91_pmc_ll.o ddramc_ll.o matrix.o lwl-$(CONFIG_CLOCKSOURCE_ATMEL_PIT) += early_udelay.o diff --git a/arch/arm/mach-at91/aic.c b/arch/arm/mach-at91/aic.c new file mode 100644 index 0000000000..b40f1d214b --- /dev/null +++ b/arch/arm/mach-at91/aic.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: BSD-1-Clause +/* + * Copyright (c) 2015, Atmel Corporation + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + */ + +#include +#include + +#define SFR_AICREDIR 0x54 +#define SFR_SN1 0x50 /* Serial Number 1 Register */ + +void at91_aic_redir(void __iomem *sfr, u32 key) +{ + u32 key32; + + if (readl(sfr + SFR_AICREDIR) & 0x01) + return; + + key32 = readl(sfr + SFR_SN1) ^ key; + writel(key32 | 0x01, sfr + SFR_AICREDIR); + /* bits[31:1] = key */ + /* bit[0] = 1 => all interrupts redirected to AIC */ + /* bit[0] = 0 => secure interrupts directed to SAIC, + others to AIC (default) */ +} diff --git a/arch/arm/mach-at91/include/mach/aic.h b/arch/arm/mach-at91/include/mach/aic.h new file mode 100644 index 0000000000..c1f026b60c --- /dev/null +++ b/arch/arm/mach-at91/include/mach/aic.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: BSD-1-Clause */ +#ifndef __AT91_AIC_H_ +#define __AT91_AIC_H_ + +#include + +void at91_aic_redir(void __iomem *sfr, u32 key); + +#endif diff --git a/arch/arm/mach-at91/sama5d2.c b/arch/arm/mach-at91/sama5d2.c index 2f74b0b38d..c498b09645 100644 --- a/arch/arm/mach-at91/sama5d2.c +++ b/arch/arm/mach-at91/sama5d2.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,7 @@ static int sama5d2_init(void) if (!of_machine_is_compatible("atmel,sama5d2")) return 0; + at91_aic_redir(SAMA5D2_BASE_SFR, SAMA5D2_AICREDIR_KEY); sama5d2_can_ram_init(); sama5d2_l2x0_init(); -- cgit v1.2.3 From 666643cb2459390dfd0ed8f9fe5565d10b32806f Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:08 +0200 Subject: ARM: at91: extend low level PMC driver for generic clk support The SAMA5D2 and SAM9X60 both feature generic clocks, which we already support in barebox proper, but not in PBL. Add PBL support for setting the parent and enabling them, so we may use it to enable the SDMMC peripherals in first stage. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/at91_pmc_ll.c | 169 ++++++++++++++++++++++++-- arch/arm/mach-at91/include/mach/at91_pmc_ll.h | 21 +++- arch/arm/mach-at91/include/mach/sama5d2_ll.h | 15 ++- 3 files changed, 187 insertions(+), 18 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/at91_pmc_ll.c b/arch/arm/mach-at91/at91_pmc_ll.c index 4d39f57909..9205322db9 100644 --- a/arch/arm/mach-at91/at91_pmc_ll.c +++ b/arch/arm/mach-at91/at91_pmc_ll.c @@ -1,17 +1,51 @@ // SPDX-License-Identifier: BSD-1-Clause /* * Copyright (c) 2006, Atmel Corporation + * Copyright (C) 2019 Microchip Technology Inc. and its subsidiaries * - * Atmel's name may not be used to endorse or promote products + * Atmel/Microchip's name may not be used to endorse or promote products * derived from this software without specific prior written permission. */ +#define pr_fmt(fmt) "at91pmc: " fmt + #include +#include +#include #include +#include + +#define SFR_UTMICKTRIM 0x30 /* UTMI Clock Trimming Register */ +#define AT91_UTMICKTRIM_FREQ 0x03 + +#define PMC_GCSR0 0xC0 /* PMCv2 Generic Clock Status Register 0 */ +#define PMC_GCSR1 0xC4 /* PMCv2 Generic Clock Status Register 1 */ #define at91_pmc_write(off, val) writel(val, pmc_base + off) #define at91_pmc_read(off) readl(pmc_base + off) +#define MHZ (1000 * 1000UL) + +static unsigned long at91_pmc_get_main_xtal(void __iomem *pmc_base) +{ + u32 tmp; + + /* Enable a measurement of the Main Crystal Oscillator */ + tmp = at91_pmc_read(AT91_CKGR_MCFR); + tmp |= AT91_PMC_CCSS_XTAL_OSC; + tmp |= AT91_PMC_RCMEAS; + at91_pmc_write(AT91_CKGR_MCFR, tmp); + + do { + tmp = at91_pmc_read(AT91_CKGR_MCFR); + } while (!(tmp & AT91_PMC_MAINRDY)); + + /* read once more like the datasheet says */ + tmp = at91_pmc_read(AT91_CKGR_MCFR) & AT91_PMC_MAINF; + + return tmp * (AT91_SLOW_CLOCK / 16); +} + void at91_pmc_init(void __iomem *pmc_base, unsigned int flags) { u32 tmp; @@ -46,16 +80,8 @@ void at91_pmc_init(void __iomem *pmc_base, unsigned int flags) while (!(at91_pmc_read(AT91_PMC_SR) & AT91_PMC_MOSCS)) ; - if (flags & AT91_PMC_LL_FLAG_MEASURE_XTAL) { - /* Enable a measurement of the Main Crystal Oscillator */ - tmp = at91_pmc_read(AT91_CKGR_MCFR); - tmp |= AT91_PMC_CCSS_XTAL_OSC; - tmp |= AT91_PMC_RCMEAS; - at91_pmc_write(AT91_CKGR_MCFR, tmp); - - while (!(at91_pmc_read(AT91_CKGR_MCFR) & AT91_PMC_MAINRDY)) - ; - } + if (flags & AT91_PMC_LL_FLAG_MEASURE_XTAL) + (void)at91_pmc_get_main_xtal(pmc_base); /* Switch from internal 12MHz RC to the Main Crystal Oscillator */ tmp = at91_pmc_read(AT91_CKGR_MOR); @@ -184,3 +210,124 @@ void at91_pmc_cfg_mck(void __iomem *pmc_base, u32 pmc_mckr, unsigned int flags) while (!(at91_pmc_read(AT91_PMC_SR) & AT91_PMC_MCKRDY)) ; } + +static void pmc_configure_utmi_ref_clk(void __iomem *pmc_base, + void __iomem *sfr_base, + unsigned long main_xtal) +{ + unsigned int utmi_ref_clk_freq = 0, tmp; + + /* + * If mainck rate is different from 12 MHz, we have to configure + * the FREQ field of the SFR_UTMICKTRIM register to generate properly + * the utmi clock. + */ + if (main_xtal < (16 + 4) * MHZ) + utmi_ref_clk_freq++; + if (main_xtal < (24 + 10) * MHZ) + utmi_ref_clk_freq++; + if (main_xtal < (48 + 10) * MHZ) + utmi_ref_clk_freq++; + + /* + * Not supported on SAMA5D2 but it's not an issue since MAINCK + * maximum value is 24 MHz. + */ + tmp = readl(sfr_base + SFR_UTMICKTRIM); + tmp &= ~AT91_UTMICKTRIM_FREQ; + tmp |= utmi_ref_clk_freq; + writel(tmp, sfr_base + SFR_UTMICKTRIM); +} + +static void pmc_uckr_clk(void __iomem *pmc_base, + void __iomem *sfr_base, + unsigned long main_xtal) +{ + unsigned int uckr = at91_pmc_read(AT91_CKGR_UCKR); + unsigned int sr; + + if (main_xtal) { + pmc_configure_utmi_ref_clk(pmc_base, sfr_base, + main_xtal); + uckr |= (AT91_PMC_UPLLCOUNT_DEFAULT | + AT91_PMC_UPLLEN | AT91_PMC_BIASEN); + sr = AT91_PMC_LOCKU; + } else { + uckr &= ~(AT91_PMC_UPLLEN | AT91_PMC_BIASEN); + sr = 0; + } + + at91_pmc_write(AT91_CKGR_UCKR, uckr); + + do { + early_udelay(1); + } while ((at91_pmc_read(AT91_PMC_SR) & AT91_PMC_LOCKU) != sr); +} + +static inline unsigned gck_status(unsigned periph_id, + unsigned flags) +{ + if (flags & AT91_PMC_LL_FLAG_GCSR) + return periph_id < 32 ? PMC_GCSR0 : PMC_GCSR1; + + return AT91_PMC_SR; +} + +static inline unsigned gck_ready(unsigned status, + unsigned periph_id, + unsigned flags) +{ + unsigned mask; + + if (flags & AT91_PMC_LL_FLAG_GCSR) + mask = 1 << (periph_id & 0x1f); + else + mask = AT91_PMC_GCKRDY; + + return status & mask; +} + +int at91_pmc_enable_generic_clock(void __iomem *pmc_base, + void __iomem *sfr_base, + unsigned int periph_id, + unsigned int clk_source, unsigned int div, + unsigned int flags) +{ + unsigned long main_xtal; + unsigned int regval, status; + unsigned int timeout = 1000; + + if (periph_id > 0x7f) + return -EINVAL; + + if (div > 0xff) + return -EINVAL; + + main_xtal = at91_pmc_get_main_xtal(pmc_base); + + if ((flags & AT91_PMC_LL_FLAG_PMC_UTMI) && + !(at91_pmc_read(AT91_PMC_SR) & AT91_PMC_LOCKU)) + pmc_uckr_clk(pmc_base, sfr_base, main_xtal); + + at91_pmc_write(AT91_PMC_PCR, periph_id); + regval = at91_pmc_read(AT91_PMC_PCR); + regval &= ~AT91_PMC_GCKCSS; + regval &= ~AT91_PMC_GCKDIV; + + regval |= clk_source; + regval |= AT91_PMC_PCR_CMD | AT91_PMC_GCKDIV_(div) | AT91_PMC_GCK_EN; + + at91_pmc_write(AT91_PMC_PCR, regval); + + for (timeout = 1000; timeout; timeout--) { + early_udelay(1); + + status = at91_pmc_read(gck_status(periph_id, flags)); + if (gck_ready(status, periph_id, flags)) + return 0; + } + + pr_warn("Timeout waiting for GCK ready!\n"); + + return 0; +} diff --git a/arch/arm/mach-at91/include/mach/at91_pmc_ll.h b/arch/arm/mach-at91/include/mach/at91_pmc_ll.h index e3d3e3ad59..6ec3ae0852 100644 --- a/arch/arm/mach-at91/include/mach/at91_pmc_ll.h +++ b/arch/arm/mach-at91/include/mach/at91_pmc_ll.h @@ -14,27 +14,38 @@ #define AT91_PMC_LL_FLAG_MEASURE_XTAL (1 << 1) #define AT91_PMC_LL_FLAG_DISABLE_RC (1 << 2) #define AT91_PMC_LL_FLAG_H32MXDIV (1 << 3) +#define AT91_PMC_LL_FLAG_PMC_UTMI (1 << 4) +#define AT91_PMC_LL_FLAG_GCSR (1 << 5) #define AT91_PMC_LL_AT91RM9200 (0) #define AT91_PMC_LL_AT91SAM9260 (0) #define AT91_PMC_LL_AT91SAM9261 (0) #define AT91_PMC_LL_AT91SAM9263 (0) -#define AT91_PMC_LL_AT91SAM9G45 (0) +#define AT91_PMC_LL_AT91SAM9G45 (AT91_PMC_LL_FLAG_PMC_UTMI) #define AT91_PMC_LL_AT91SAM9X5 (AT91_PMC_LL_FLAG_SAM9X5_PMC | \ - AT91_PMC_LL_FLAG_DISABLE_RC) + AT91_PMC_LL_FLAG_DISABLE_RC | \ + AT91_PMC_LL_FLAG_PMC_UTMI) #define AT91_PMC_LL_AT91SAM9N12 (AT91_PMC_LL_FLAG_SAM9X5_PMC | \ AT91_PMC_LL_FLAG_DISABLE_RC) #define AT91_PMC_LL_SAMA5D2 (AT91_PMC_LL_FLAG_SAM9X5_PMC | \ - AT91_PMC_LL_FLAG_MEASURE_XTAL) + AT91_PMC_LL_FLAG_MEASURE_XTAL | \ + AT91_PMC_LL_FLAG_PMC_UTMI) #define AT91_PMC_LL_SAMA5D3 (AT91_PMC_LL_FLAG_SAM9X5_PMC | \ - AT91_PMC_LL_FLAG_DISABLE_RC) + AT91_PMC_LL_FLAG_DISABLE_RC | \ + AT91_PMC_LL_FLAG_PMC_UTMI) #define AT91_PMC_LL_SAMA5D4 (AT91_PMC_LL_FLAG_SAM9X5_PMC | \ - AT91_PMC_LL_FLAG_H32MXDIV) + AT91_PMC_LL_FLAG_H32MXDIV | \ + AT91_PMC_LL_FLAG_PMC_UTMI) void at91_pmc_init(void __iomem *pmc_base, unsigned int flags); void at91_pmc_cfg_mck(void __iomem *pmc_base, u32 pmc_mckr, unsigned int flags); void at91_pmc_cfg_plla(void __iomem *pmc_base, u32 pmc_pllar, unsigned int flags); +int at91_pmc_enable_generic_clock(void __iomem *pmc_base, void __iomem *sfr_base, + unsigned int periph_id, + unsigned int clk_source, unsigned int div, + unsigned int flags); + static inline void at91_pmc_init_pll(void __iomem *pmc_base, u32 pmc_pllicpr) { writel(pmc_pllicpr, pmc_base + AT91_PMC_PLLICPR); diff --git a/arch/arm/mach-at91/include/mach/sama5d2_ll.h b/arch/arm/mach-at91/include/mach/sama5d2_ll.h index 7c38a84f53..e6fa391425 100644 --- a/arch/arm/mach-at91/include/mach/sama5d2_ll.h +++ b/arch/arm/mach-at91/include/mach/sama5d2_ll.h @@ -8,13 +8,13 @@ #include +void sama5d2_lowlevel_init(void); + static inline void sama5d2_pmc_enable_periph_clock(int clk) { at91_pmc_sam9x5_enable_periph_clock(SAMA5D2_BASE_PMC, clk); } -void sama5d2_lowlevel_init(void); - /* requires relocation */ static inline void sama5d2_udelay_init(unsigned int msc) { @@ -22,6 +22,17 @@ static inline void sama5d2_udelay_init(unsigned int msc) SAMA5D2_ID_PIT, msc, AT91_PMC_LL_SAMA5D2); } + void sama5d2_ddr2_init(struct at91_ddramc_register *ddramc_reg_config); +static inline int sama5d2_pmc_enable_generic_clock(unsigned int periph_id, + unsigned int clk_source, + unsigned int div) +{ + return at91_pmc_enable_generic_clock(SAMA5D2_BASE_PMC, + SAMA5D2_BASE_SFR, + periph_id, clk_source, div, + AT91_PMC_LL_SAMA5D2); +} + #endif -- cgit v1.2.3 From f322224716c394c9825a553b16b25db243e8d868 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:12 +0200 Subject: ARM: at91: add code for sama5 boot source detection SAMA5 BootROM passes information about the boot source in the r4 register. Add functions to parse these. To make use of this, entry point must back up the r4 register, because otherwise it's clobbered by local variable use. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/include/mach/sama5_bootsource.h | 46 ++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 arch/arm/mach-at91/include/mach/sama5_bootsource.h (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/include/mach/sama5_bootsource.h b/arch/arm/mach-at91/include/mach/sama5_bootsource.h new file mode 100644 index 0000000000..29354dcaf3 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/sama5_bootsource.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef AT91_SAMA5_BOOTSOURCE_H_ +#define AT91_SAMA5_BOOTSOURCE_H_ + +#include +#include +#include +#include +#include + +/* Boot modes stored by BootROM in r4 */ +#define SAMA5_BOOTSOURCE_SPI 0 +#define SAMA5_BOOTSOURCE_MCI 1 +#define SAMA5_BOOTSOURCE_SMC 2 +#define SAMA5_BOOTSOURCE_TWI 3 +#define SAMA5_BOOTSOURCE_QSPI 4 +#define SAMA5_BOOTSOURCE_SAM_BA 7 + +#define SAMA5_BOOTSOURCE GENMASK(3, 0) +#define SAMA5_BOOTSOURCE_INSTANCE GENMASK(7, 4) + +static inline int sama5_bootsource(u32 reg) +{ + u32 dev = FIELD_GET(SAMA5_BOOTSOURCE, reg); + + switch(dev) { + case SAMA5_BOOTSOURCE_MCI: + return BOOTSOURCE_MMC; + case SAMA5_BOOTSOURCE_SPI: + return BOOTSOURCE_SPI_NOR; + case SAMA5_BOOTSOURCE_QSPI: + return BOOTSOURCE_SPI; + case SAMA5_BOOTSOURCE_SMC: + return BOOTSOURCE_NAND; + case SAMA5_BOOTSOURCE_SAM_BA: + return BOOTSOURCE_SERIAL; + } + return BOOTSOURCE_UNKNOWN; +} + +static inline int sama5_bootsource_instance(u32 reg) +{ + return FIELD_GET(SAMA5_BOOTSOURCE_INSTANCE, reg); +} + +#endif -- cgit v1.2.3 From 87603c7b93af5dba6968e0e50709f1cbd8f42b53 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:13 +0200 Subject: ARM: at91: add helpers for chain-loading barebox from SD-card With PBL FAT support implemented, provide an sama5d2_sdhci_start_image helper that can be called from the PBL to chainload a barebox.bin file from the first FAT partition. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/Kconfig | 5 ++ arch/arm/mach-at91/Makefile | 1 + arch/arm/mach-at91/include/mach/xload.h | 12 +++++ arch/arm/mach-at91/xload-mmc.c | 90 +++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 arch/arm/mach-at91/include/mach/xload.h create mode 100644 arch/arm/mach-at91/xload-mmc.c (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 54fa9b8aa2..25ef854bf0 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -40,6 +40,11 @@ config HAVE_AT91_I2S_MUX_CLK config HAVE_AT91_SAM9X60_PLL bool +config AT91_MCI_PBL + bool + depends on MCI_ATMEL_SDHCI_PBL + default y + # Select if board uses the common at91sam926x_board_init config AT91SAM926X_BOARD_INIT bool diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 254bbeef27..31a91b967e 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_AT91_BOOTSTRAP) += bootstrap.o obj-y += at91sam9_reset.o obj-y += at91sam9g45_reset.o +pbl-$(CONFIG_AT91_MCI_PBL) += xload-mmc.o obj-$(CONFIG_AT91SAM9_SMC) += sam9_smc.o obj-$(CONFIG_HAVE_AT91SAM9_RST) += at91sam9_rst.o diff --git a/arch/arm/mach-at91/include/mach/xload.h b/arch/arm/mach-at91/include/mach/xload.h new file mode 100644 index 0000000000..f110236b0b --- /dev/null +++ b/arch/arm/mach-at91/include/mach/xload.h @@ -0,0 +1,12 @@ +#ifndef __MACH_XLOAD_H +#define __MACH_XLOAD_H + +#include +#include + +void __noreturn sama5d2_sdhci_start_image(u32 r4); + +int at91_sdhci_bio_init(struct pbl_bio *bio, void __iomem *base); + +#endif /* __MACH_XLOAD_H */ + diff --git a/arch/arm/mach-at91/xload-mmc.c b/arch/arm/mach-at91/xload-mmc.c new file mode 100644 index 0000000000..42341fa54b --- /dev/null +++ b/arch/arm/mach-at91/xload-mmc.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void __naked __noreturn xload_bb(void __noreturn (*bb)(void), u32 r4) +{ + asm volatile("mov r4, %0" : : "r"(r4) : ); + asm volatile("bx %0" : : "r"(bb) : ); +} + +static void at91_fat_start_image(struct pbl_bio *bio, + void *buf, unsigned int len, + u32 r4) +{ + void __noreturn (*bb)(void); + int ret; + + ret = pbl_fat_load(bio, "barebox.bin", buf, len); + if (ret < 0) { + pr_err("pbl_fat_load: error %d\n", ret); + return; + } + + bb = buf; + + sync_caches_for_execution(); + + xload_bb(bb, r4); +} + +static const struct sdhci_instance { + void __iomem *base; + unsigned id; + u8 periph; + s8 pins[15]; +} sdhci_instances[] = { + [0] = { + .base = SAMA5D2_BASE_SDHC0, .id = SAMA5D2_ID_SDMMC0, .periph = AT91_MUX_PERIPH_A, + .pins = { 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 13, 10, 11, 12, -1 } + }, + [1] = { + .base = SAMA5D2_BASE_SDHC1, .id = SAMA5D2_ID_SDMMC1, .periph = AT91_MUX_PERIPH_E, + .pins = { 18, 19, 20, 21, 22, 28, 30, -1 } + }, +}; + +/** + * sama5d2_sdhci_start_image - Load and start an image from FAT-formatted SDHCI + * @r4: value of r4 passed by BootROM + */ +void __noreturn sama5d2_sdhci_start_image(u32 r4) +{ + void *buf = (void *)SAMA5_DDRCS; + const struct sdhci_instance *instance; + struct pbl_bio bio; + const s8 *pin; + int ret; + + ret = sama5_bootsource_instance(r4); + if (ret > 1) + panic("Couldn't determine boot MCI instance\n"); + + instance = &sdhci_instances[ret]; + + sama5d2_pmc_enable_periph_clock(SAMA5D2_ID_PIOA); + for (pin = instance->pins; *pin >= 0; pin++) { + at91_mux_pio4_set_periph(SAMA5D2_BASE_PIOA, + BIT(*pin), instance->periph); + } + + sama5d2_pmc_enable_periph_clock(instance->id); + sama5d2_pmc_enable_generic_clock(instance->id, AT91_PMC_GCKCSS_UPLL_CLK, 1); + + ret = at91_sdhci_bio_init(&bio, instance->base); + if (ret) + goto out_panic; + + /* TODO: eMMC boot partition handling: they are not FAT-formatted */ + + at91_fat_start_image(&bio, buf, SZ_16M, r4); + +out_panic: + panic("FAT chainloading failed\n"); +} -- cgit v1.2.3 From eb54e4fc5acde09095b1092ca8740be18d48fe24 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:14 +0200 Subject: ARM: at91: sama5d2: reuse stack set-up by first stage Stack is always set up to end of SRAM before PBL, either by ROM code or by first stage bootloader, be it at91bootstrap or barebox in a later commit, so no need to change the stack pointer again. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/boards/sama5d27-giantboard/lowlevel.c | 13 +++---------- arch/arm/boards/sama5d27-som1/lowlevel.c | 13 +++---------- 2 files changed, 6 insertions(+), 20 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/boards/sama5d27-giantboard/lowlevel.c b/arch/arm/boards/sama5d27-giantboard/lowlevel.c index e08217105b..4419e946f1 100644 --- a/arch/arm/boards/sama5d27-giantboard/lowlevel.c +++ b/arch/arm/boards/sama5d27-giantboard/lowlevel.c @@ -34,10 +34,12 @@ static void dbgu_init(void) extern char __dtb_z_at91_sama5d27_giantboard_start[]; -static noinline void giantboard_entry(void) +ENTRY_FUNCTION(start_sama5d27_giantboard, r0, r1, r2) { void *fdt; + arm_cpu_lowlevel_init(); + if (IS_ENABLED(CONFIG_DEBUG_LL)) dbgu_init(); @@ -45,12 +47,3 @@ static noinline void giantboard_entry(void) barebox_arm_entry(SAMA5_DDRCS, SZ_128M, fdt); } - -ENTRY_FUNCTION(start_sama5d27_giantboard, r0, r1, r2) -{ - arm_cpu_lowlevel_init(); - - arm_setup_stack(SAMA5D2_SRAM_BASE + SAMA5D2_SRAM_SIZE); - - giantboard_entry(); -} diff --git a/arch/arm/boards/sama5d27-som1/lowlevel.c b/arch/arm/boards/sama5d27-som1/lowlevel.c index 2b39e5abc3..b7780ec8ae 100644 --- a/arch/arm/boards/sama5d27-som1/lowlevel.c +++ b/arch/arm/boards/sama5d27-som1/lowlevel.c @@ -58,10 +58,12 @@ static void ek_dbgu_init(void) extern char __dtb_z_at91_sama5d27_som1_ek_start[]; -static noinline void som1_entry(void) +ENTRY_FUNCTION(start_sama5d27_som1_ek, r0, r1, r2) { void *fdt; + arm_cpu_lowlevel_init(); + if (IS_ENABLED(CONFIG_DEBUG_LL)) ek_dbgu_init(); @@ -70,12 +72,3 @@ static noinline void som1_entry(void) ek_turn_led(RGB_LED_GREEN); barebox_arm_entry(SAMA5_DDRCS, SZ_128M, fdt); } - -ENTRY_FUNCTION(start_sama5d27_som1_ek, r0, r1, r2) -{ - arm_cpu_lowlevel_init(); - - arm_setup_stack(SAMA5D2_SRAM_BASE + SAMA5D2_SRAM_SIZE); - - som1_entry(); -} -- cgit v1.2.3 From 1ecfb8ec3eb58ba04cea2cbb56604c16676afd1a Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:15 +0200 Subject: ARM: at91: debug_ll: remove duplicated IS_ENABLED(CONFIG_DEBUG_LL) condition There are three users of at91_dbgu_setup_ll and all already call this function only when IS_ENABLED(CONFIG_DEBUG_LL). Remove the duplicated condition from the function itself. This allows us to use the function for pbl_set_console use later on, even with DEBUG_LL disabled. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/mach-at91/include/mach/at91_dbgu.h | 34 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/mach-at91/include/mach/at91_dbgu.h b/arch/arm/mach-at91/include/mach/at91_dbgu.h index 0ba9cdae10..29aaa2dfe1 100644 --- a/arch/arm/mach-at91/include/mach/at91_dbgu.h +++ b/arch/arm/mach-at91/include/mach/at91_dbgu.h @@ -94,30 +94,28 @@ static inline void at91_dbgu_setup_ll(void __iomem *dbgu_base, unsigned mck, unsigned baudrate) { - if (IS_ENABLED(CONFIG_DEBUG_LL)) { - u32 brgr = mck / (baudrate * 16); + u32 brgr = mck / (baudrate * 16); - if ((mck / (baudrate * 16)) % 10 >= 5) - brgr++; + if ((mck / (baudrate * 16)) % 10 >= 5) + brgr++; - writel(~0, dbgu_base + AT91_DBGU_IDR); + writel(~0, dbgu_base + AT91_DBGU_IDR); - writel(AT91_DBGU_RSTRX - | AT91_DBGU_RSTTX - | AT91_DBGU_RXDIS - | AT91_DBGU_TXDIS, - dbgu_base + AT91_DBGU_CR); + writel(AT91_DBGU_RSTRX + | AT91_DBGU_RSTTX + | AT91_DBGU_RXDIS + | AT91_DBGU_TXDIS, + dbgu_base + AT91_DBGU_CR); - writel(brgr, dbgu_base + AT91_DBGU_BRGR); + writel(brgr, dbgu_base + AT91_DBGU_BRGR); - writel(AT91_DBGU_PAR_NONE - | AT91_DBGU_CHMODE_NORMAL - | AT91_DBGU_CHRL_8BIT - | AT91_DBGU_NBSTOP_1BIT, - dbgu_base + AT91_DBGU_MR); + writel(AT91_DBGU_PAR_NONE + | AT91_DBGU_CHMODE_NORMAL + | AT91_DBGU_CHRL_8BIT + | AT91_DBGU_NBSTOP_1BIT, + dbgu_base + AT91_DBGU_MR); - writel(AT91_DBGU_RXEN | AT91_DBGU_TXEN, dbgu_base + AT91_DBGU_CR); - } + writel(AT91_DBGU_RXEN | AT91_DBGU_TXEN, dbgu_base + AT91_DBGU_CR); } #endif -- cgit v1.2.3 From 01474752795536d9dad1a7631f0f54c6c0191892 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:16 +0200 Subject: ARM: at91: sama5d2: reduce UART setup boilerplate with new helpers The sama5d2 can be fused for one of 9 preset UART iosets. This is then used by the BootROM for printing the `RomBOOT' header and for the XMODEM protocol implemented by the SAM-BA monitor. Add two new sama5d2 specific helpers: - sama5d2_dbgu_setup_ll for setting up the port with only pinmux and master clock as arguments - sama5d2_resetup_uart_console for resetup of the uart console with same pinmux used by the ROM code The default value, when unfused, is UART_1_IOSET_1 (RX@PD2, TX@PD3), which are the same ones used on the two sama5d2 board supported so far. With this change, the DEBUG_LL baudrate is also no longer fixed at 115200, but instead comes from the CONFIG_BAUDRATE symbol. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/boards/sama5d27-giantboard/lowlevel.c | 11 +-- arch/arm/boards/sama5d27-som1/lowlevel.c | 11 +-- arch/arm/mach-at91/include/mach/debug_ll.h | 17 ++++- arch/arm/mach-at91/include/mach/sama5d2.h | 56 ++++++++++++++ arch/arm/mach-at91/include/mach/sama5d2_ll.h | 101 +++++++++++++++++++++++++ 5 files changed, 172 insertions(+), 24 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/boards/sama5d27-giantboard/lowlevel.c b/arch/arm/boards/sama5d27-giantboard/lowlevel.c index 4419e946f1..a30441d7cc 100644 --- a/arch/arm/boards/sama5d27-giantboard/lowlevel.c +++ b/arch/arm/boards/sama5d27-giantboard/lowlevel.c @@ -18,16 +18,7 @@ static void dbgu_init(void) { - unsigned mck = MASTER_CLOCK / 2; - - sama5d2_pmc_enable_periph_clock(SAMA5D2_ID_PIOD); - - at91_mux_pio4_set_A_periph(SAMA5D2_BASE_PIOD, - pin_to_mask(AT91_PIN_PD3)); /* DBGU TXD */ - - sama5d2_pmc_enable_periph_clock(SAMA5D2_ID_UART1); - - at91_dbgu_setup_ll(SAMA5D2_BASE_UART1, mck, 115200); + sama5d2_resetup_uart_console(MASTER_CLOCK); putc_ll('>'); } diff --git a/arch/arm/boards/sama5d27-som1/lowlevel.c b/arch/arm/boards/sama5d27-som1/lowlevel.c index b7780ec8ae..2e408ce832 100644 --- a/arch/arm/boards/sama5d27-som1/lowlevel.c +++ b/arch/arm/boards/sama5d27-som1/lowlevel.c @@ -42,16 +42,7 @@ static void ek_turn_led(unsigned color) static void ek_dbgu_init(void) { - unsigned mck = MASTER_CLOCK / 2; - - sama5d2_pmc_enable_periph_clock(SAMA5D2_ID_PIOD); - - at91_mux_pio4_set_A_periph(SAMA5D2_BASE_PIOD, - pin_to_mask(AT91_PIN_PD3)); /* DBGU TXD */ - - sama5d2_pmc_enable_periph_clock(SAMA5D2_ID_UART1); - - at91_dbgu_setup_ll(SAMA5D2_BASE_UART1, mck, 115200); + sama5d2_resetup_uart_console(MASTER_CLOCK); putc_ll('>'); } diff --git a/arch/arm/mach-at91/include/mach/debug_ll.h b/arch/arm/mach-at91/include/mach/debug_ll.h index b713930424..b3cbdbc26f 100644 --- a/arch/arm/mach-at91/include/mach/debug_ll.h +++ b/arch/arm/mach-at91/include/mach/debug_ll.h @@ -9,6 +9,9 @@ #define __MACH_DEBUG_LL_H__ #include +#include +#include +#include #define ATMEL_US_CSR 0x0014 #define ATMEL_US_THR 0x001c @@ -22,13 +25,19 @@ * * This does not append a newline */ -static inline void PUTC_LL(char c) +static inline void at91_dbgu_putc(void __iomem *base, int c) { - while (!(readl(CONFIG_DEBUG_AT91_UART_BASE + ATMEL_US_CSR) & ATMEL_US_TXRDY)) + while (!(readl(base + ATMEL_US_CSR) & ATMEL_US_TXRDY)) barrier(); - writel(c, CONFIG_DEBUG_AT91_UART_BASE + ATMEL_US_THR); + writel(c, base + ATMEL_US_THR); - while (!(readl(CONFIG_DEBUG_AT91_UART_BASE + ATMEL_US_CSR) & ATMEL_US_TXEMPTY)) + while (!(readl(base + ATMEL_US_CSR) & ATMEL_US_TXEMPTY)) barrier(); } + +static inline void PUTC_LL(char c) +{ + at91_dbgu_putc(IOMEM(CONFIG_DEBUG_AT91_UART_BASE), c); +} + #endif diff --git a/arch/arm/mach-at91/include/mach/sama5d2.h b/arch/arm/mach-at91/include/mach/sama5d2.h index ada9c59e03..90b566ffc4 100644 --- a/arch/arm/mach-at91/include/mach/sama5d2.h +++ b/arch/arm/mach-at91/include/mach/sama5d2.h @@ -16,6 +16,8 @@ #include #include +#include +#include /* * Peripheral identifiers/interrupts. (Table 18-9) @@ -261,4 +263,58 @@ #define SAMA5D2_SRAM_BASE SAMA5D2_BASE_SRAM0 #define SAMA5D2_SRAM_SIZE (128 * SZ_1K) +static inline void __iomem *sama5d2_pio_map_bank(int bank, unsigned *id) +{ + switch(bank + 'A') { + case 'A': + *id = SAMA5D2_ID_PIOA; + return SAMA5D2_BASE_PIOA; + case 'B': + *id = SAMA5D2_ID_PIOB; + return SAMA5D2_BASE_PIOB; + case 'C': + *id = SAMA5D2_ID_PIOC; + return SAMA5D2_BASE_PIOC; + case 'D': + *id = SAMA5D2_ID_PIOD; + return SAMA5D2_BASE_PIOD; + } + + return NULL; +} + +#define SAMA5D2_BUREG_INDEX GENMASK(1, 0) +#define SAMA5D2_BUREG_VALID BIT(2) + +#define SAMA5D2_SFC_DR(x) (SAMA5D2_BASE_SFC + 0x20 + 4 * (x)) + +#define SAMA5D2_BOOTCFG_QSPI_0 GENMASK(1, 0) +#define SAMA5D2_BOOTCFG_QSPI_1 GENMASK(3, 2) +#define SAMA5D2_BOOTCFG_SPI_0 GENMASK(5, 4) +#define SAMA5D2_BOOTCFG_SPI_1 GENMASK(7, 6) +#define SAMA5D2_BOOTCFG_NFC GENMASK(9, 8) +#define SAMA5D2_BOOTCFG_SDMMC_0 BIT(10) +#define SAMA5D2_BOOTCFG_SDMMC_1 BIT(11) +#define SAMA5D2_BOOTCFG_UART GENMASK(15, 12) +#define SAMA5D2_BOOTCFG_JTAG GENMASK(17, 16) +#define SAMA5D2_BOOTCFG_EXT_MEM_BOOT_EN BIT(18) +#define SAMA5D2_BOOTCFG_QSPI_XIP BIT(21) +#define SAMA5D2_DISABLE_BSC_CR BIT(22) +#define SAMA5D2_DISABLE_MONITOR BIT(24) +#define SAMA5D2_SECURE_MODE BIT(29) + +static inline u32 sama5d2_bootcfg(void) +{ + u32 __iomem *bureg = SAMA5D2_BASE_SECURAM + 0x1400; + u32 bsc_cr = readl(SAMA5D2_BASE_SYSC + 0x54); + u32 __iomem *bootcfg; + + if (bsc_cr & SAMA5D2_BUREG_VALID) + bootcfg = &bureg[FIELD_GET(SAMA5D2_BUREG_INDEX, bsc_cr)]; + else + bootcfg = SAMA5D2_SFC_DR(512 / 32); + + return readl(bootcfg); +} + #endif diff --git a/arch/arm/mach-at91/include/mach/sama5d2_ll.h b/arch/arm/mach-at91/include/mach/sama5d2_ll.h index e6fa391425..96f3bc5452 100644 --- a/arch/arm/mach-at91/include/mach/sama5d2_ll.h +++ b/arch/arm/mach-at91/include/mach/sama5d2_ll.h @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include @@ -35,4 +37,103 @@ static inline int sama5d2_pmc_enable_generic_clock(unsigned int periph_id, AT91_PMC_LL_SAMA5D2); } +static inline int sama5d2_dbgu_setup_ll(unsigned dbgu_id, + unsigned pin, unsigned periph, + unsigned mck) +{ + unsigned mask, bank, pio_id; + void __iomem *dbgu_base, *pio_base; + + mask = pin_to_mask(pin); + bank = pin_to_bank(pin); + + switch (dbgu_id) { + case SAMA5D2_ID_UART0: + dbgu_base = SAMA5D2_BASE_UART0; + break; + case SAMA5D2_ID_UART1: + dbgu_base = SAMA5D2_BASE_UART1; + break; + case SAMA5D2_ID_UART2: + dbgu_base = SAMA5D2_BASE_UART2; + break; + case SAMA5D2_ID_UART3: + dbgu_base = SAMA5D2_BASE_UART3; + break; + case SAMA5D2_ID_UART4: + dbgu_base = SAMA5D2_BASE_UART4; + break; + default: + return -EINVAL; + } + + pio_base = sama5d2_pio_map_bank(bank, &pio_id); + if (!pio_base) + return -EINVAL; + + sama5d2_pmc_enable_periph_clock(pio_id); + + at91_mux_pio4_set_periph(pio_base, mask, periph); + + sama5d2_pmc_enable_periph_clock(dbgu_id); + + at91_dbgu_setup_ll(dbgu_base, mck / 2, CONFIG_BAUDRATE); + + return 0; +} + +struct sama5d2_uart_pinmux { + void __iomem *base; + u8 id, dtxd, periph; +}; + +#define SAMA5D2_UART(idx, pio, periph) (struct sama5d2_uart_pinmux) { \ + SAMA5D2_BASE_UART##idx, SAMA5D2_ID_UART##idx, \ + AT91_PIN_##pio, AT91_MUX_PERIPH_##periph } + +static inline void __iomem *sama5d2_resetup_uart_console(unsigned mck) +{ + struct sama5d2_uart_pinmux pinmux; + + /* Table 48-2 I/O Lines and 16.4.4 Boot Configuration Word */ + + switch (FIELD_GET(SAMA5D2_BOOTCFG_UART, sama5d2_bootcfg())) { + case 0: /* UART_1_IOSET_1 */ + pinmux = SAMA5D2_UART(1, PD3, A); + break; + case 1: /* UART_0_IOSET_1 */ + pinmux = SAMA5D2_UART(0, PB27, C); + break; + case 2: /* UART_1_IOSET_2 */ + pinmux = SAMA5D2_UART(1, PC8, E); + break; + case 3: /* UART_2_IOSET_1 */ + pinmux = SAMA5D2_UART(2, PD5, B); + break; + case 4: /* UART_2_IOSET_2 */ + pinmux = SAMA5D2_UART(2, PD24, A); + break; + case 5: /* UART_2_IOSET_3 */ + pinmux = SAMA5D2_UART(2, PD20, C); + break; + case 6: /* UART_3_IOSET_1 */ + pinmux = SAMA5D2_UART(3, PC13, D); + break; + case 7: /* UART_3_IOSET_2 */ + pinmux = SAMA5D2_UART(3, PD0, C); + break; + case 8: /* UART_3_IOSET_3 */ + pinmux = SAMA5D2_UART(3, PB12, C); + break; + case 9: /* UART_4_IOSET_1 */ + pinmux = SAMA5D2_UART(4, PB4, A); + break; + default: + return NULL; + } + + sama5d2_dbgu_setup_ll(pinmux.id, pinmux.dtxd, pinmux.periph, mck); + return pinmux.base; +} + #endif -- cgit v1.2.3 From 3c7606dde3793b7f13c82924caa85ad24423f91f Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:17 +0200 Subject: ARM: at91: sama5d27-som1: add additional first stage entry point The BootROM constrains us to a 64K big first stage bootloader. Add a PBL entry point for a xload barebox that sets up the minimum necessary to load a FAT32 barebox.bin from the SD-Card. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/boards/sama5d27-som1/lowlevel.c | 30 +++++++++++------ arch/arm/mach-at91/Kconfig | 1 + arch/arm/mach-at91/include/mach/barebox-arm.h | 21 ++++++++++++ .../mach-at91/include/mach/sama5d2-sip-ddramc.h | 39 ++++++++++++++++++++++ images/Makefile.at91 | 5 +++ 5 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 arch/arm/mach-at91/include/mach/barebox-arm.h create mode 100644 arch/arm/mach-at91/include/mach/sama5d2-sip-ddramc.h (limited to 'arch/arm') diff --git a/arch/arm/boards/sama5d27-som1/lowlevel.c b/arch/arm/boards/sama5d27-som1/lowlevel.c index 2e408ce832..012f21614c 100644 --- a/arch/arm/boards/sama5d27-som1/lowlevel.c +++ b/arch/arm/boards/sama5d27-som1/lowlevel.c @@ -5,13 +5,12 @@ #include #include - -#include -#include +#include #include #include +#include #include -#include +#include #define RGB_LED_GREEN (1 << 0) #define RGB_LED_RED (1 << 1) @@ -40,23 +39,32 @@ static void ek_turn_led(unsigned color) } } -static void ek_dbgu_init(void) +SAMA5_ENTRY_FUNCTION(start_sama5d27_som1_ek_xload_mmc, r4) { - sama5d2_resetup_uart_console(MASTER_CLOCK); + void __iomem *dbgu_base; + sama5d2_lowlevel_init(); + dbgu_base = sama5d2_resetup_uart_console(MASTER_CLOCK); putc_ll('>'); + + relocate_to_current_adr(); + setup_c(); + + pbl_set_putc(at91_dbgu_putc, dbgu_base); + + ek_turn_led(RGB_LED_RED | RGB_LED_GREEN); /* Yellow */ + sama5d2_udelay_init(MASTER_CLOCK); + sama5d2_d1g_ddrconf(); + sama5d2_sdhci_start_image(r4); } extern char __dtb_z_at91_sama5d27_som1_ek_start[]; -ENTRY_FUNCTION(start_sama5d27_som1_ek, r0, r1, r2) +SAMA5_ENTRY_FUNCTION(start_sama5d27_som1_ek, r4) { void *fdt; - arm_cpu_lowlevel_init(); - - if (IS_ENABLED(CONFIG_DEBUG_LL)) - ek_dbgu_init(); + putc_ll('>'); fdt = __dtb_z_at91_sama5d27_som1_ek_start + get_runtime_offset(); diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 25ef854bf0..f388d00b8f 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -603,6 +603,7 @@ config MACH_SAMA5D27_SOM1 bool "Microchip SAMA5D27 SoM-1 Evaluation Kit" select SOC_SAMA5D2 select OFDEVICE + select MCI_ATMEL_SDHCI_PBL select COMMON_CLK_OF_PROVIDER help Select this if you are using Microchip's sama5d27 SoM evaluation kit diff --git a/arch/arm/mach-at91/include/mach/barebox-arm.h b/arch/arm/mach-at91/include/mach/barebox-arm.h new file mode 100644 index 0000000000..4a65c6f8fa --- /dev/null +++ b/arch/arm/mach-at91/include/mach/barebox-arm.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef AT91_BAREBOX_ARM_H_ +#define AT91_BAREBOX_ARM_H_ + +#include + +#define SAMA5_ENTRY_FUNCTION(name, r4) \ + void name (u32 r0, u32 r1, u32 r2, u32 r3); \ + \ + static void __##name(u32); \ + \ + void NAKED __section(.text_head_entry_##name) name \ + (u32 r0, u32 r1, u32 r2, u32 r3) \ + { \ + register u32 r4 asm("r4"); \ + __barebox_arm_head(); \ + __##name(r4); \ + } \ + static void NAKED noinline __##name \ + (u32 r4) +#endif diff --git a/arch/arm/mach-at91/include/mach/sama5d2-sip-ddramc.h b/arch/arm/mach-at91/include/mach/sama5d2-sip-ddramc.h new file mode 100644 index 0000000000..35c92c43fc --- /dev/null +++ b/arch/arm/mach-at91/include/mach/sama5d2-sip-ddramc.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: BSD-1-Clause + * + * Copyright (C) 2014, Atmel Corporation + * + * SAMA5D27 System-in-Package DDRAMC configuration + */ + +#include +#include +#include + +static inline void sama5d2_d1g_ddrconf(void) /* DDR2 1Gbit SDRAM */ +{ + struct at91_ddramc_register conf = { + .mdr = AT91_DDRC2_DBW_16_BITS | AT91_DDRC2_MD_DDR2_SDRAM, + + .cr = AT91_DDRC2_NC_DDR10_SDR9 | AT91_DDRC2_NR_13 | + AT91_DDRC2_CAS_3 | AT91_DDRC2_DISABLE_RESET_DLL | + AT91_DDRC2_WEAK_STRENGTH_RZQ7 | AT91_DDRC2_ENABLE_DLL | + AT91_DDRC2_NB_BANKS_8 | AT91_DDRC2_NDQS_ENABLED | + AT91_DDRC2_DECOD_INTERLEAVED | AT91_DDRC2_UNAL_SUPPORTED, + + .rtr = 0x511, + + .t0pr = AT91_DDRC2_TRAS_(7) | AT91_DDRC2_TRCD_(3) | + AT91_DDRC2_TWR_(3) | AT91_DDRC2_TRC_(9) | + AT91_DDRC2_TRP_(3) | AT91_DDRC2_TRRD_(2) | + AT91_DDRC2_TWTR_(2) | AT91_DDRC2_TMRD_(2), + + .t1pr = AT91_DDRC2_TRFC_(22) | AT91_DDRC2_TXSNR_(23) | + AT91_DDRC2_TXSRD_(200) | AT91_DDRC2_TXP_(2), + + .t2pr = AT91_DDRC2_TXARD_(2) | AT91_DDRC2_TXARDS_(8) | + AT91_DDRC2_TRPA_(4) | AT91_DDRC2_TRTP_(2) | + AT91_DDRC2_TFAW_(8), + }; + + sama5d2_ddr2_init(&conf); +} diff --git a/images/Makefile.at91 b/images/Makefile.at91 index 448d71fb98..bc63357c5d 100644 --- a/images/Makefile.at91 +++ b/images/Makefile.at91 @@ -18,6 +18,11 @@ pblb-$(CONFIG_MACH_SAMA5D27_SOM1) += start_sama5d27_som1_ek FILE_barebox-sama5d27-som1-ek.img = start_sama5d27_som1_ek.pblb image-$(CONFIG_MACH_SAMA5D27_SOM1) += barebox-sama5d27-som1-ek.img +pblb-$(CONFIG_MACH_SAMA5D27_SOM1) += start_sama5d27_som1_ek_xload_mmc +MAX_PBL_IMAGE_SIZE_start_sama5d27_som1_ek_xload_mmc = 0xffff +FILE_barebox-sama5d27-som1-ek-xload-mmc.img = start_sama5d27_som1_ek_xload_mmc.pblb +image-$(CONFIG_MACH_SAMA5D27_SOM1) += barebox-sama5d27-som1-ek-xload-mmc.img + pblb-$(CONFIG_MACH_SAMA5D27_GIANTBOARD) += start_sama5d27_giantboard FILE_barebox-groboards-sama5d27-giantboard.img = start_sama5d27_giantboard.pblb image-$(CONFIG_MACH_SAMA5D27_GIANTBOARD) += barebox-groboards-sama5d27-giantboard.img -- cgit v1.2.3 From 7208a44d8bc6058a120d49b7061e2b9f9c0502c8 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:18 +0200 Subject: ARM: at91: sama5d2: read back memory size from DDRAM controller We hard code memory size at three places: - In the configuration we use to initialize the DDRAM controller - In the minimal available size passed from PBL to barebox proper - In the device tree memory node override Remove the two latter ones and replace them with code that reads the size back from controller. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/boards/sama5d27-giantboard/lowlevel.c | 2 +- arch/arm/boards/sama5d27-som1/lowlevel.c | 2 +- arch/arm/dts/at91-sama5d27_giantboard.dts | 4 -- arch/arm/dts/at91-sama5d27_som1_ek.dts | 4 -- arch/arm/dts/sama5d2.dtsi | 2 + arch/arm/mach-at91/Kconfig | 4 ++ arch/arm/mach-at91/Makefile | 1 + arch/arm/mach-at91/ddramc.c | 57 ++++++++++++++++++++++++++ arch/arm/mach-at91/include/mach/ddramc.h | 2 + 9 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 arch/arm/mach-at91/ddramc.c (limited to 'arch/arm') diff --git a/arch/arm/boards/sama5d27-giantboard/lowlevel.c b/arch/arm/boards/sama5d27-giantboard/lowlevel.c index a30441d7cc..0bb3a7289c 100644 --- a/arch/arm/boards/sama5d27-giantboard/lowlevel.c +++ b/arch/arm/boards/sama5d27-giantboard/lowlevel.c @@ -36,5 +36,5 @@ ENTRY_FUNCTION(start_sama5d27_giantboard, r0, r1, r2) fdt = __dtb_z_at91_sama5d27_giantboard_start + get_runtime_offset(); - barebox_arm_entry(SAMA5_DDRCS, SZ_128M, fdt); + sama5d2_barebox_entry(fdt); } diff --git a/arch/arm/boards/sama5d27-som1/lowlevel.c b/arch/arm/boards/sama5d27-som1/lowlevel.c index 012f21614c..792e065076 100644 --- a/arch/arm/boards/sama5d27-som1/lowlevel.c +++ b/arch/arm/boards/sama5d27-som1/lowlevel.c @@ -69,5 +69,5 @@ SAMA5_ENTRY_FUNCTION(start_sama5d27_som1_ek, r4) fdt = __dtb_z_at91_sama5d27_som1_ek_start + get_runtime_offset(); ek_turn_led(RGB_LED_GREEN); - barebox_arm_entry(SAMA5_DDRCS, SZ_128M, fdt); + sama5d2_barebox_entry(fdt); } diff --git a/arch/arm/dts/at91-sama5d27_giantboard.dts b/arch/arm/dts/at91-sama5d27_giantboard.dts index 7e48fa18ae..6ba094c3da 100644 --- a/arch/arm/dts/at91-sama5d27_giantboard.dts +++ b/arch/arm/dts/at91-sama5d27_giantboard.dts @@ -38,10 +38,6 @@ linux,default-trigger = "mmc0"; }; }; - - memory { - reg = <0x20000000 0x8000000>; - }; }; &slow_xtal { diff --git a/arch/arm/dts/at91-sama5d27_som1_ek.dts b/arch/arm/dts/at91-sama5d27_som1_ek.dts index cd038dc7c1..b9042d1131 100644 --- a/arch/arm/dts/at91-sama5d27_som1_ek.dts +++ b/arch/arm/dts/at91-sama5d27_som1_ek.dts @@ -13,10 +13,6 @@ device-path = &barebox_env; }; }; - - memory { - reg = <0x20000000 0x8000000>; - }; }; &qspi1 { diff --git a/arch/arm/dts/sama5d2.dtsi b/arch/arm/dts/sama5d2.dtsi index fadcc83815..c9af5f2f7a 100644 --- a/arch/arm/dts/sama5d2.dtsi +++ b/arch/arm/dts/sama5d2.dtsi @@ -7,6 +7,8 @@ }; }; +/delete-node/ &{/memory}; + &sdmmc0 { assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; }; diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index f388d00b8f..8584dcd979 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -40,6 +40,9 @@ config HAVE_AT91_I2S_MUX_CLK config HAVE_AT91_SAM9X60_PLL bool +config HAVE_AT91_DDRAMC + bool + config AT91_MCI_PBL bool depends on MCI_ATMEL_SDHCI_PBL @@ -87,6 +90,7 @@ config SOC_SAMA5D2 select PINCTRL_AT91PIO4 select HAS_MACB select HAVE_MACH_ARM_HEAD + select HAVE_AT91_DDRAMC config SOC_SAMA5D3 bool diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 31a91b967e..3b9f60a95a 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_AT91_BOOTSTRAP) += bootstrap.o obj-y += at91sam9_reset.o obj-y += at91sam9g45_reset.o +obj-pbl-$(CONFIG_HAVE_AT91_DDRAMC) += ddramc.o pbl-$(CONFIG_AT91_MCI_PBL) += xload-mmc.o obj-$(CONFIG_AT91SAM9_SMC) += sam9_smc.o diff --git a/arch/arm/mach-at91/ddramc.c b/arch/arm/mach-at91/ddramc.c new file mode 100644 index 0000000000..6dac794689 --- /dev/null +++ b/arch/arm/mach-at91/ddramc.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Ahmad Fatoum + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned sama5_ramsize(void __iomem *base) +{ + return at91_get_ddram_size(base, true); +} + +void __noreturn sama5d2_barebox_entry(void *boarddata) +{ + barebox_arm_entry(SAMA5_DDRCS, sama5_ramsize(SAMA5D2_BASE_MPDDRC), + boarddata); +} + +static int sama5_ddr_probe(struct device_d *dev) +{ + struct resource *iores; + void __iomem *base; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + base = IOMEM(iores->start); + + arm_add_mem_device("ram0", SAMA5_DDRCS, sama5_ramsize(base)); + + return 0; +} + +static struct of_device_id sama5_ddr_dt_ids[] = { + { .compatible = "atmel,sama5d3-ddramc" }, + { /* sentinel */ } +}; + +static struct driver_d sama5_ddr_driver = { + .name = "sama5-ddramc", + .probe = sama5_ddr_probe, + .of_compatible = sama5_ddr_dt_ids, +}; + +static int sama5_ddr_init(void) +{ + return platform_driver_register(&sama5_ddr_driver); +} +mem_initcall(sama5_ddr_init); diff --git a/arch/arm/mach-at91/include/mach/ddramc.h b/arch/arm/mach-at91/include/mach/ddramc.h index 0b33afc213..cd85bb6eab 100644 --- a/arch/arm/mach-at91/include/mach/ddramc.h +++ b/arch/arm/mach-at91/include/mach/ddramc.h @@ -32,5 +32,7 @@ void at91_lpddr1_sdram_initialize(void __iomem *base_address, void __iomem *ram_address, struct at91_ddramc_register *ddramc_config); +void __noreturn sama5d2_barebox_entry(void *boarddata); + #endif /* #ifndef __DDRAMC_H__ */ -- cgit v1.2.3 From 5991cb8eeb8a4eea2587be3b1d1b45d845bd3c68 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:19 +0200 Subject: ARM: at91: sama5d2: populate $bootsource and $bootsource_instance The BootROM passes us information about the boot medium in r4 and we already use that in first stage and pass it along to second stage PBL already. To make use of it, we need to pass it to barebox proper, do this by writing it in the last 4 bytes of the SRAM. As second stage always run in DRAM, this is safe to do. We could also write to SRAM directly from first stage, but at91bootstrap passes info in r4 as well for the sama5d3 boards, so we do it likewise to maintain compatibility. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/boards/sama5d27-giantboard/lowlevel.c | 6 +++--- arch/arm/boards/sama5d27-som1/lowlevel.c | 2 +- arch/arm/mach-at91/ddramc.c | 4 +++- arch/arm/mach-at91/include/mach/ddramc.h | 3 +-- arch/arm/mach-at91/include/mach/sama5_bootsource.h | 3 +++ arch/arm/mach-at91/sama5d2.c | 17 +++++++++++++++++ 6 files changed, 28 insertions(+), 7 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/boards/sama5d27-giantboard/lowlevel.c b/arch/arm/boards/sama5d27-giantboard/lowlevel.c index 0bb3a7289c..3dada9baf2 100644 --- a/arch/arm/boards/sama5d27-giantboard/lowlevel.c +++ b/arch/arm/boards/sama5d27-giantboard/lowlevel.c @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include #include @@ -25,7 +25,7 @@ static void dbgu_init(void) extern char __dtb_z_at91_sama5d27_giantboard_start[]; -ENTRY_FUNCTION(start_sama5d27_giantboard, r0, r1, r2) +SAMA5_ENTRY_FUNCTION(start_sama5d27_giantboard, r4) { void *fdt; @@ -36,5 +36,5 @@ ENTRY_FUNCTION(start_sama5d27_giantboard, r0, r1, r2) fdt = __dtb_z_at91_sama5d27_giantboard_start + get_runtime_offset(); - sama5d2_barebox_entry(fdt); + sama5d2_barebox_entry(r4, fdt); } diff --git a/arch/arm/boards/sama5d27-som1/lowlevel.c b/arch/arm/boards/sama5d27-som1/lowlevel.c index 792e065076..b093711918 100644 --- a/arch/arm/boards/sama5d27-som1/lowlevel.c +++ b/arch/arm/boards/sama5d27-som1/lowlevel.c @@ -69,5 +69,5 @@ SAMA5_ENTRY_FUNCTION(start_sama5d27_som1_ek, r4) fdt = __dtb_z_at91_sama5d27_som1_ek_start + get_runtime_offset(); ek_turn_led(RGB_LED_GREEN); - sama5d2_barebox_entry(fdt); + sama5d2_barebox_entry(r4, fdt); } diff --git a/arch/arm/mach-at91/ddramc.c b/arch/arm/mach-at91/ddramc.c index 6dac794689..a241ea9f0a 100644 --- a/arch/arm/mach-at91/ddramc.c +++ b/arch/arm/mach-at91/ddramc.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -18,8 +19,9 @@ static unsigned sama5_ramsize(void __iomem *base) return at91_get_ddram_size(base, true); } -void __noreturn sama5d2_barebox_entry(void *boarddata) +void __noreturn sama5d2_barebox_entry(unsigned int r4, void *boarddata) { + __sama5d2_stashed_bootrom_r4 = r4; barebox_arm_entry(SAMA5_DDRCS, sama5_ramsize(SAMA5D2_BASE_MPDDRC), boarddata); } diff --git a/arch/arm/mach-at91/include/mach/ddramc.h b/arch/arm/mach-at91/include/mach/ddramc.h index cd85bb6eab..b929bf5f58 100644 --- a/arch/arm/mach-at91/include/mach/ddramc.h +++ b/arch/arm/mach-at91/include/mach/ddramc.h @@ -32,7 +32,6 @@ void at91_lpddr1_sdram_initialize(void __iomem *base_address, void __iomem *ram_address, struct at91_ddramc_register *ddramc_config); -void __noreturn sama5d2_barebox_entry(void *boarddata); - +void __noreturn sama5d2_barebox_entry(unsigned int r4, void *boarddata); #endif /* #ifndef __DDRAMC_H__ */ diff --git a/arch/arm/mach-at91/include/mach/sama5_bootsource.h b/arch/arm/mach-at91/include/mach/sama5_bootsource.h index 29354dcaf3..0f90afe902 100644 --- a/arch/arm/mach-at91/include/mach/sama5_bootsource.h +++ b/arch/arm/mach-at91/include/mach/sama5_bootsource.h @@ -43,4 +43,7 @@ static inline int sama5_bootsource_instance(u32 reg) return FIELD_GET(SAMA5_BOOTSOURCE_INSTANCE, reg); } +#define __sama5d2_stashed_bootrom_r4 \ + (*(volatile u32 *)(SAMA5D2_SRAM_BASE + SAMA5D2_SRAM_SIZE - 0x4)) + #endif diff --git a/arch/arm/mach-at91/sama5d2.c b/arch/arm/mach-at91/sama5d2.c index c498b09645..2ce6d7f36f 100644 --- a/arch/arm/mach-at91/sama5d2.c +++ b/arch/arm/mach-at91/sama5d2.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #define SFR_CAN 0x48 @@ -52,3 +53,19 @@ static int sama5d2_init(void) return 0; } postmmu_initcall(sama5d2_init); + +static int sama5d2_bootsource_init(void) +{ + u32 r4; + + if (!of_machine_is_compatible("atmel,sama5d2")) + return 0; + + r4 = __sama5d2_stashed_bootrom_r4; + + bootsource_set(sama5_bootsource(r4)); + bootsource_set_instance(sama5_bootsource_instance(r4)); + + return 0; +} +postcore_initcall(sama5d2_bootsource_init); -- cgit v1.2.3 From 9ac9186550fce7fe13ddb389ddf2e81c47859662 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:20 +0200 Subject: ARM: at91: sama5d27-som1-ek: add barebox_update and multi environment support We now have second stage support for running from sdmmc0 and sdmmc1. Add a barebox environment and update handler for the two SD cards. As fall back, we use the environment in the QSPI flash as before as this is soldered to the SoM and is always available. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/boards/sama5d27-som1/Makefile | 1 + arch/arm/boards/sama5d27-som1/board.c | 35 ++++++++++++++++++++++++++++++++++ arch/arm/dts/at91-sama5d27_som1_ek.dts | 17 ++++++++++++++++- arch/arm/mach-at91/Kconfig | 1 + 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 arch/arm/boards/sama5d27-som1/board.c (limited to 'arch/arm') diff --git a/arch/arm/boards/sama5d27-som1/Makefile b/arch/arm/boards/sama5d27-som1/Makefile index b08c4a93ca..092c31d6b2 100644 --- a/arch/arm/boards/sama5d27-som1/Makefile +++ b/arch/arm/boards/sama5d27-som1/Makefile @@ -1 +1,2 @@ lwl-y += lowlevel.o +obj-y += board.o diff --git a/arch/arm/boards/sama5d27-som1/board.c b/arch/arm/boards/sama5d27-som1/board.c new file mode 100644 index 0000000000..00c0e92a5d --- /dev/null +++ b/arch/arm/boards/sama5d27-som1/board.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include +#include +#include +#include +#include + +static int ek_device_init(void) +{ + int flags_sd = 0, flags_usd = 0; + if (!of_machine_is_compatible("atmel,sama5d27-som1-ek")) + return 0; + + if (bootsource_get() == BOOTSOURCE_MMC) { + if (bootsource_get_instance() == 0) { + flags_sd = BBU_HANDLER_FLAG_DEFAULT; + of_device_enable_path("/chosen/environment-sd"); + } else { + flags_usd = BBU_HANDLER_FLAG_DEFAULT; + of_device_enable_path("/chosen/environment-microsd"); + } + } else { + of_device_enable_path("/chosen/environment-qspi"); + } + + bbu_register_std_file_update("SD", flags_sd, "/mnt/mmc0.0/barebox.bin", + filetype_arm_barebox); + bbu_register_std_file_update("microSD", flags_usd, "/mnt/mmc1.0/barebox.bin", + filetype_arm_barebox); + return 0; +} +device_initcall(ek_device_init); diff --git a/arch/arm/dts/at91-sama5d27_som1_ek.dts b/arch/arm/dts/at91-sama5d27_som1_ek.dts index b9042d1131..befee89ad7 100644 --- a/arch/arm/dts/at91-sama5d27_som1_ek.dts +++ b/arch/arm/dts/at91-sama5d27_som1_ek.dts @@ -8,9 +8,24 @@ / { chosen { - environment { + environment-qspi { compatible = "barebox,environment"; device-path = &barebox_env; + status = "disabled"; + }; + + environment-sd { + compatible = "barebox,environment"; + device-path = &sdmmc0; + file-path = "barebox.env"; + status = "disabled"; + }; + + environment-microsd { + compatible = "barebox,environment"; + device-path = &sdmmc1; + file-path = "barebox.env"; + status = "disabled"; }; }; }; diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 8584dcd979..52eefc7361 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -609,6 +609,7 @@ config MACH_SAMA5D27_SOM1 select OFDEVICE select MCI_ATMEL_SDHCI_PBL select COMMON_CLK_OF_PROVIDER + select FS_FAT_WRITE if MCI_ATMEL_SDHCI && FS_FAT && ENV_HANDLING help Select this if you are using Microchip's sama5d27 SoM evaluation kit -- cgit v1.2.3 From b12324293fbec7e07a5d03588ad412c7476668a1 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:21 +0200 Subject: ARM: at91: sama5d27-giantboard: add additional first stage entry point The BootROM constrains us to a 64K big first stage bootloader. Add a PBL entry point for a xload barebox that sets up the minimum necessary to load a FAT32 barebox.bin from the SD-Card. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/boards/sama5d27-giantboard/lowlevel.c | 26 +++++++++++++++++--------- images/Makefile.at91 | 5 +++++ 2 files changed, 22 insertions(+), 9 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/boards/sama5d27-giantboard/lowlevel.c b/arch/arm/boards/sama5d27-giantboard/lowlevel.c index 3dada9baf2..ee8297fa45 100644 --- a/arch/arm/boards/sama5d27-giantboard/lowlevel.c +++ b/arch/arm/boards/sama5d27-giantboard/lowlevel.c @@ -5,22 +5,33 @@ #include #include - -#include #include #include +#include +#include #include #include -#include /* PCK = 492MHz, MCK = 164MHz */ #define MASTER_CLOCK 164000000 -static void dbgu_init(void) +SAMA5_ENTRY_FUNCTION(start_sama5d27_giantboard_xload_mmc, r4) { - sama5d2_resetup_uart_console(MASTER_CLOCK); + void __iomem *dbgu_base; + + sama5d2_lowlevel_init(); + dbgu_base = sama5d2_resetup_uart_console(MASTER_CLOCK); putc_ll('>'); + + relocate_to_current_adr(); + setup_c(); + + pbl_set_putc(at91_dbgu_putc, dbgu_base); + + sama5d2_udelay_init(MASTER_CLOCK); + sama5d2_d1g_ddrconf(); + sama5d2_sdhci_start_image(r4); } extern char __dtb_z_at91_sama5d27_giantboard_start[]; @@ -29,10 +40,7 @@ SAMA5_ENTRY_FUNCTION(start_sama5d27_giantboard, r4) { void *fdt; - arm_cpu_lowlevel_init(); - - if (IS_ENABLED(CONFIG_DEBUG_LL)) - dbgu_init(); + putc_ll('>'); fdt = __dtb_z_at91_sama5d27_giantboard_start + get_runtime_offset(); diff --git a/images/Makefile.at91 b/images/Makefile.at91 index bc63357c5d..00fa4cab27 100644 --- a/images/Makefile.at91 +++ b/images/Makefile.at91 @@ -26,3 +26,8 @@ image-$(CONFIG_MACH_SAMA5D27_SOM1) += barebox-sama5d27-som1-ek-xload-mmc.img pblb-$(CONFIG_MACH_SAMA5D27_GIANTBOARD) += start_sama5d27_giantboard FILE_barebox-groboards-sama5d27-giantboard.img = start_sama5d27_giantboard.pblb image-$(CONFIG_MACH_SAMA5D27_GIANTBOARD) += barebox-groboards-sama5d27-giantboard.img + +pblb-$(CONFIG_MACH_SAMA5D27_GIANTBOARD) += start_sama5d27_giantboard_xload_mmc +FILE_barebox-groboards-sama5d27-giantboard-xload-mmc.img = start_sama5d27_giantboard_xload_mmc.pblb +MAX_PBL_IMAGE_SIZE_start_sama5d27_giantboard_xload_mmc = 0xffff +image-$(CONFIG_MACH_SAMA5D27_GIANTBOARD) += barebox-groboards-sama5d27-giantboard-xload-mmc.img -- cgit v1.2.3 From a668f9d1a8b60356ab08268644ade84e39ff4d46 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Wed, 1 Jul 2020 11:11:22 +0200 Subject: ARM: at91: sama5d27-giantboard: add default environment/bbu The board only has SD-Card as storage. Add a barebox update handler to flash barebox to it, as well as an nv.boot.default=mmc1 to boot from it. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/boards/sama5d27-giantboard/Makefile | 2 ++ arch/arm/boards/sama5d27-giantboard/board.c | 17 +++++++++++++++++ .../defaultenv-giantboard/nv/boot.default | 1 + arch/arm/dts/at91-sama5d27_giantboard.dts | 6 ++++++ 4 files changed, 26 insertions(+) create mode 100644 arch/arm/boards/sama5d27-giantboard/board.c create mode 100644 arch/arm/boards/sama5d27-giantboard/defaultenv-giantboard/nv/boot.default (limited to 'arch/arm') diff --git a/arch/arm/boards/sama5d27-giantboard/Makefile b/arch/arm/boards/sama5d27-giantboard/Makefile index b08c4a93ca..f5869c4839 100644 --- a/arch/arm/boards/sama5d27-giantboard/Makefile +++ b/arch/arm/boards/sama5d27-giantboard/Makefile @@ -1 +1,3 @@ lwl-y += lowlevel.o +obj-y += board.o +bbenv-y += defaultenv-giantboard diff --git a/arch/arm/boards/sama5d27-giantboard/board.c b/arch/arm/boards/sama5d27-giantboard/board.c new file mode 100644 index 0000000000..1d4453ede3 --- /dev/null +++ b/arch/arm/boards/sama5d27-giantboard/board.c @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include +#include + +static int giantboard_device_init(void) +{ + bbu_register_std_file_update("microSD", BBU_HANDLER_FLAG_DEFAULT, + "/mnt/mmc1.0/barebox.bin", + filetype_arm_barebox); + + defaultenv_append_directory(defaultenv_giantboard); + + return 0; +} +device_initcall(giantboard_device_init); diff --git a/arch/arm/boards/sama5d27-giantboard/defaultenv-giantboard/nv/boot.default b/arch/arm/boards/sama5d27-giantboard/defaultenv-giantboard/nv/boot.default new file mode 100644 index 0000000000..646f435652 --- /dev/null +++ b/arch/arm/boards/sama5d27-giantboard/defaultenv-giantboard/nv/boot.default @@ -0,0 +1 @@ +mmc1 diff --git a/arch/arm/dts/at91-sama5d27_giantboard.dts b/arch/arm/dts/at91-sama5d27_giantboard.dts index 6ba094c3da..2ba3ff2171 100644 --- a/arch/arm/dts/at91-sama5d27_giantboard.dts +++ b/arch/arm/dts/at91-sama5d27_giantboard.dts @@ -25,6 +25,12 @@ chosen { stdout-path = &uart1; + + environment { + compatible = "barebox,environment"; + device-path = &sdmmc1; + file-path = "barebox.env"; + }; }; leds { -- cgit v1.2.3 From 424b33c88b90fe656dbe2c3a9c954ea6d4f7479b Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Sat, 11 Jul 2020 11:02:02 +0200 Subject: ARM: at91: dts: sama5d27-som1: adapt to upstream partition layout Linux v5.8-rc1 adds partitions to the flash@0 node, which now overlap with the partitions we define and resulting in errors: ERROR: m25p0.barebox: New partition m25p0.barebox conflicts with m25p0.at91bootstrap ERROR: m25p0.barebox-environment: New partition m25p0.barebox-environment conflicts with m25p0.bootloader We don't want to reuse those partitions as their name may and probably will change (they have leading zeroes in the unit address). We could use the &{/path/to/partition} syntax, but that might be broken soon as well, as the nodes aren't inside a partitions node with a "fixed-partitions" compatible. The busses also don't align with the yaml schema and might be renamed. Nuke the full flash@0 node and supply ours and avoid these problems. The offsets of the partitions have been adjusted to coincide with the upstream offsets for second stage bootloader and environment. Signed-off-by: Ahmad Fatoum Signed-off-by: Sascha Hauer --- arch/arm/dts/at91-sama5d27_som1_ek.dts | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'arch/arm') diff --git a/arch/arm/dts/at91-sama5d27_som1_ek.dts b/arch/arm/dts/at91-sama5d27_som1_ek.dts index befee89ad7..97a326dd2b 100644 --- a/arch/arm/dts/at91-sama5d27_som1_ek.dts +++ b/arch/arm/dts/at91-sama5d27_som1_ek.dts @@ -31,18 +31,28 @@ }; &qspi1 { + /delete-node/ flash@0; + flash@0 { - #address-cells = <1>; - #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <80000000>; + m25p,fast-read; - partition@0 { - label = "barebox"; - reg = <0x0 0x80000>; - }; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + barebox@40000 { + label = "barebox"; + reg = <0x40000 0xc0000>; + }; - barebox_env: partition@80000 { - label = "barebox-environment"; - reg = <0x80000 0x80000>; + barebox_env: barebox-env@100000 { + label = "barebox-environment"; + reg = <0x100000 0x40000>; + }; }; }; }; -- cgit v1.2.3