diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2020-07-27 21:58:14 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2020-07-27 21:58:14 +0200 |
commit | e41d307e072de3642c0ce293ef3786ff1340440b (patch) | |
tree | 8bdd95ae53fc5cd6db7dae46058f545131d992b4 /arch/arm | |
parent | 3322880d50b964c17021f9a6089d191b6cf1586b (diff) | |
parent | 424b33c88b90fe656dbe2c3a9c954ea6d4f7479b (diff) | |
download | barebox-e41d307e072de3642c0ce293ef3786ff1340440b.tar.gz barebox-e41d307e072de3642c0ce293ef3786ff1340440b.tar.xz |
Merge branch 'for-next/at91'
Diffstat (limited to 'arch/arm')
56 files changed, 2493 insertions, 446 deletions
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 <asm/barebox-arm.h> #include <mach/hardware.h> -#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_ddrsdrc.h> 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 <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> -#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_ddrsdrc.h> #include <mach/at91sam9g45.h> #include <mach/hardware.h> 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 <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> -#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_ddrsdrc.h> #include <mach/hardware.h> 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 <common.h> #include <linux/sizes.h> -#include <mach/at91sam9_ddrsdr.h> -#include <mach/hardware.h> +#include <mach/at91_ddrsdrc.h> #include <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> #include <io.h> 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 <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> -#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_ddrsdrc.h> + #include <mach/hardware.h> void __naked __bare_init barebox_arm_reset_vector(uint32_t r0, uint32_t r1, uint32_t r2) 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 <init.h> +#include <envfs.h> +#include <bbu.h> + +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/boards/sama5d27-giantboard/lowlevel.c b/arch/arm/boards/sama5d27-giantboard/lowlevel.c index 0236c424c1..ee8297fa45 100644 --- a/arch/arm/boards/sama5d27-giantboard/lowlevel.c +++ b/arch/arm/boards/sama5d27-giantboard/lowlevel.c @@ -5,59 +5,44 @@ #include <common.h> #include <init.h> - -#include <asm/barebox-arm-head.h> -#include <asm/barebox-arm.h> -#include <mach/at91_pmc_ll.h> - -#include <mach/hardware.h> +#include <mach/barebox-arm.h> +#include <mach/sama5d2_ll.h> +#include <mach/xload.h> +#include <mach/sama5d2-sip-ddramc.h> #include <mach/iomux.h> #include <debug_ll.h> -#include <mach/at91_dbgu.h> /* PCK = 492MHz, MCK = 164MHz */ #define MASTER_CLOCK 164000000 -static inline void sama5d2_pmc_enable_periph_clock(int clk) +SAMA5_ENTRY_FUNCTION(start_sama5d27_giantboard_xload_mmc, r4) { - at91_pmc_sam9x5_enable_periph_clock(IOMEM(SAMA5D2_BASE_PMC), clk); -} + void __iomem *dbgu_base; -static void dbgu_init(void) -{ - unsigned mck = MASTER_CLOCK / 2; + sama5d2_lowlevel_init(); - sama5d2_pmc_enable_periph_clock(SAMA5D2_ID_PIOD); - - at91_mux_pio4_set_A_periph(IOMEM(SAMA5D2_BASE_PIOD), - pin_to_mask(AT91_PIN_PD3)); /* DBGU TXD */ + dbgu_base = sama5d2_resetup_uart_console(MASTER_CLOCK); + putc_ll('>'); - sama5d2_pmc_enable_periph_clock(SAMA5D2_ID_UART1); + relocate_to_current_adr(); + setup_c(); - at91_dbgu_setup_ll(IOMEM(SAMA5D2_BASE_UART1), mck, 115200); + pbl_set_putc(at91_dbgu_putc, dbgu_base); - putc_ll('>'); + sama5d2_udelay_init(MASTER_CLOCK); + sama5d2_d1g_ddrconf(); + sama5d2_sdhci_start_image(r4); } extern char __dtb_z_at91_sama5d27_giantboard_start[]; -static noinline void giantboard_entry(void) +SAMA5_ENTRY_FUNCTION(start_sama5d27_giantboard, r4) { void *fdt; - if (IS_ENABLED(CONFIG_DEBUG_LL)) - dbgu_init(); + putc_ll('>'); fdt = __dtb_z_at91_sama5d27_giantboard_start + get_runtime_offset(); - 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(); + sama5d2_barebox_entry(r4, fdt); } 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 <common.h> +#include <linux/sizes.h> +#include <init.h> +#include <asm/memory.h> +#include <bbu.h> +#include <bootsource.h> +#include <of.h> + +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/boards/sama5d27-som1/lowlevel.c b/arch/arm/boards/sama5d27-som1/lowlevel.c index 62d35be912..b093711918 100644 --- a/arch/arm/boards/sama5d27-som1/lowlevel.c +++ b/arch/arm/boards/sama5d27-som1/lowlevel.c @@ -5,15 +5,12 @@ #include <common.h> #include <init.h> - -#include <asm/barebox-arm-head.h> -#include <asm/barebox-arm.h> -#include <mach/at91_pmc_ll.h> - -#include <mach/hardware.h> +#include <mach/barebox-arm.h> +#include <mach/sama5d2_ll.h> #include <mach/iomux.h> +#include <mach/xload.h> #include <debug_ll.h> -#include <mach/at91_dbgu.h> +#include <mach/sama5d2-sip-ddramc.h> #define RGB_LED_GREEN (1 << 0) #define RGB_LED_RED (1 << 1) @@ -22,15 +19,10 @@ /* PCK = 492MHz, MCK = 164MHz */ #define MASTER_CLOCK 164000000 -static inline void sama5d2_pmc_enable_periph_clock(int clk) -{ - at91_pmc_sam9x5_enable_periph_clock(IOMEM(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,48 +33,41 @@ 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); } } -static void ek_dbgu_init(void) +SAMA5_ENTRY_FUNCTION(start_sama5d27_som1_ek_xload_mmc, r4) { - unsigned mck = MASTER_CLOCK / 2; - - sama5d2_pmc_enable_periph_clock(SAMA5D2_ID_PIOD); + void __iomem *dbgu_base; + sama5d2_lowlevel_init(); - at91_mux_pio4_set_A_periph(IOMEM(SAMA5D2_BASE_PIOD), - pin_to_mask(AT91_PIN_PD3)); /* DBGU TXD */ + dbgu_base = sama5d2_resetup_uart_console(MASTER_CLOCK); + putc_ll('>'); - sama5d2_pmc_enable_periph_clock(SAMA5D2_ID_UART1); + relocate_to_current_adr(); + setup_c(); - at91_dbgu_setup_ll(IOMEM(SAMA5D2_BASE_UART1), mck, 115200); + pbl_set_putc(at91_dbgu_putc, dbgu_base); - putc_ll('>'); + 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[]; -static noinline void som1_entry(void) +SAMA5_ENTRY_FUNCTION(start_sama5d27_som1_ek, r4) { void *fdt; - if (IS_ENABLED(CONFIG_DEBUG_LL)) - ek_dbgu_init(); + putc_ll('>'); 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); -} - -ENTRY_FUNCTION(start_sama5d27_som1_ek, r0, r1, r2) -{ - arm_cpu_lowlevel_init(); - - arm_setup_stack(SAMA5D2_SRAM_BASE + SAMA5D2_SRAM_SIZE); - - som1_entry(); + sama5d2_barebox_entry(r4, fdt); } 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 <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> -#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_ddrsdrc.h> #include <mach/hardware.h> 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 <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> -#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_ddrsdrc.h> #include <mach/hardware.h> 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 <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> -#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_ddrsdrc.h> #include <mach/hardware.h> 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 <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> -#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_ddrsdrc.h> #include <mach/hardware.h> void __naked __bare_init barebox_arm_reset_vector(uint32_t r0, uint32_t r1, uint32_t r2) diff --git a/arch/arm/dts/at91-sama5d27_giantboard.dts b/arch/arm/dts/at91-sama5d27_giantboard.dts index 7e48fa18ae..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 { @@ -38,10 +44,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..97a326dd2b 100644 --- a/arch/arm/dts/at91-sama5d27_som1_ek.dts +++ b/arch/arm/dts/at91-sama5d27_som1_ek.dts @@ -8,30 +8,51 @@ / { chosen { - environment { + environment-qspi { compatible = "barebox,environment"; device-path = &barebox_env; + status = "disabled"; }; - }; - memory { - reg = <0x20000000 0x8000000>; + 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"; + }; }; }; &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>; + }; }; }; }; diff --git a/arch/arm/dts/sama5d2.dtsi b/arch/arm/dts/sama5d2.dtsi index 51e964fc0f..c9af5f2f7a 100644 --- a/arch/arm/dts/sama5d2.dtsi +++ b/arch/arm/dts/sama5d2.dtsi @@ -6,3 +6,13 @@ mmc1 = &sdmmc1; }; }; + +/delete-node/ &{/memory}; + +&sdmmc0 { + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; +}; + +&sdmmc1 { + assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_UTMI>; +}; diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 54fa9b8aa2..52eefc7361 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -40,6 +40,14 @@ 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 + default y + # Select if board uses the common at91sam926x_board_init config AT91SAM926X_BOARD_INIT bool @@ -82,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 @@ -598,7 +607,9 @@ 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 + 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 diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 89aff54b8a..3b9f60a95a 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 +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 ifeq ($(CONFIG_COMMON_CLK_OF_PROVIDER),) obj-y += clock.o @@ -11,6 +12,8 @@ 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 obj-$(CONFIG_HAVE_AT91SAM9_RST) += at91sam9_rst.o @@ -24,6 +27,8 @@ 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_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/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 <mach/aic.h> +#include <io.h> + +#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/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 <common.h> +#include <mach/hardware.h> +#include <mach/at91_pmc.h> #include <mach/at91_pmc_ll.h> +#include <mach/early_udelay.h> + +#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/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 <linux/linkage.h> -#include <mach/hardware.h> #include <mach/at91sam9_sdramc.h> #include <mach/at91_rstc.h> 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 <init.h> #include <io.h> #include <restart.h> +#include <linux/bitfield.h> #include <linux/clk.h> #include <mach/at91_rstc.h> +#include <reset_source.h> 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; 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 <mach/hardware.h> #include <mach/at91_pmc.h> #include <mach/at91sam9g45_matrix.h> -#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_ddrsdrc.h> #include <mach/at91_rtt.h> #include <mach/board.h> #include <mach/iomux.h> diff --git a/arch/arm/mach-at91/at91sam9g45_reset.S b/arch/arm/mach-at91/at91sam9g45_reset.S index 6a58de618c..67517bf591 100644 --- a/arch/arm/mach-at91/at91sam9g45_reset.S +++ b/arch/arm/mach-at91/at91sam9g45_reset.S @@ -11,8 +11,7 @@ */ #include <linux/linkage.h> -#include <mach/hardware.h> -#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_ddrsdrc.h> #include <mach/at91_rstc.h> .arm @@ -20,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/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 <mach/board.h> #include <mach/at91_pmc.h> #include <mach/at91sam9n12_matrix.h> -#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_ddrsdrc.h> #include <mach/iomux.h> #include <mach/cpu.h> #include <i2c/i2c-gpio.h> 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 <mach/board.h> #include <mach/at91_pmc.h> #include <mach/at91sam9x5_matrix.h> -#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_ddrsdrc.h> #include <mach/iomux.h> #include <mach/cpu.h> #include <i2c/i2c-gpio.h> diff --git a/arch/arm/mach-at91/ddramc.c b/arch/arm/mach-at91/ddramc.c new file mode 100644 index 0000000000..a241ea9f0a --- /dev/null +++ b/arch/arm/mach-at91/ddramc.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Ahmad Fatoum <a.fatoum@pengutronix.de> + */ + +#include <common.h> +#include <init.h> +#include <mach/ddramc.h> +#include <mach/hardware.h> +#include <asm/barebox-arm.h> +#include <mach/at91_ddrsdrc.h> +#include <mach/sama5_bootsource.h> +#include <asm/memory.h> +#include <pbl.h> +#include <io.h> + +static unsigned sama5_ramsize(void __iomem *base) +{ + return at91_get_ddram_size(base, true); +} + +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); +} + +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/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 <stelian.pop@leadtechdesign.com> + * Copyright (c) 2007 Lead Tech Design <www.leadtechdesign.com> + */ + +#include <linux/kconfig.h> +#include <asm/system.h> +#include <mach/at91_ddrsdrc.h> +#include <mach/ddramc.h> +#include <mach/early_udelay.h> + +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/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 <mach/hardware.h> +#include <asm/io.h> +#include <mach/at91_pmc_ll.h> +#include <mach/at91_pit.h> +#include <mach/early_udelay.h> + +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/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 <linux/compiler.h> + +void at91_aic_redir(void __iomem *sfr, u32 key); + +#endif 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 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..7d70fe4cb4 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/at91_ddrsdrc.h @@ -0,0 +1,373 @@ +/* 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) + +#ifndef __ASSEMBLY__ +#include <common.h> +#include <io.h> +#include <mach/hardware.h> + +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/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/at91_pmc_ll.h b/arch/arm/mach-at91/include/mach/at91_pmc_ll.h index eda40e8e12..6ec3ae0852 100644 --- a/arch/arm/mach-at91/include/mach/at91_pmc_ll.h +++ b/arch/arm/mach-at91/include/mach/at91_pmc_ll.h @@ -13,26 +13,39 @@ #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_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) -#define AT91_PMC_LL_SAMA5D4 (AT91_PMC_LL_FLAG_SAM9X5_PMC) + 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_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); @@ -75,4 +88,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/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 <asm-generic/io.h> + +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 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 496cf70701..0000000000 --- a/arch/arm/mach-at91/include/mach/at91sam9_ddrsdr.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Header file for the Atmel DDR/SDR SDRAM Controller - * - * Copyright (C) 2010 Atmel Corporation - * Nicolas Ferre <nicolas.ferre@atmel.com> - * - * 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 - -#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 */ - -#ifndef __ASSEMBLY__ -#include <io.h> -#include <mach/hardware.h> - -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_DDRSDRC_CR); - mdr = readl(base + AT91_DDRSDRC_MDR); - - /* will always be false for sama5d2, sama5d3 or sama5d4 */ - is_sdram = (mdr & AT91_DDRSDRC_MD) <= AT91_DDRSDRC_MD_LOW_POWER_SDR; - - /* Formula: - * size = bank << (col + row + 1); - * if (bandwidth == 32 bits) - * size <<= 1; - */ - size = 1; - /* COL */ - size += (cr & AT91_DDRSDRC_NC) + 8; - if (!is_sdram) - size ++; - /* ROW */ - size += ((cr & AT91_DDRSDRC_NR) >> 2) + 11; - /* BANK */ - if (is_nb) - size = ((cr & AT91_DDRSDRC_NB) ? 8 : 4) << size; - else - size = 4 << size; - - /* bandwidth */ - if (!(mdr & AT91_DDRSDRC_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/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 <asm/barebox-arm.h> + +#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/ddramc.h b/arch/arm/mach-at91/include/mach/ddramc.h new file mode 100644 index 0000000000..b929bf5f58 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/ddramc.h @@ -0,0 +1,37 @@ +// 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); + +void __noreturn sama5d2_barebox_entry(unsigned int r4, void *boarddata); + +#endif /* #ifndef __DDRAMC_H__ */ 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 <asm/io.h> +#include <mach/gpio.h> +#include <mach/hardware.h> +#include <mach/at91_dbgu.h> #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/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 <linux/compiler.h> + +/* 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 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 <linux/compiler.h> + +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/sama5_bootsource.h b/arch/arm/mach-at91/include/mach/sama5_bootsource.h new file mode 100644 index 0000000000..0f90afe902 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/sama5_bootsource.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef AT91_SAMA5_BOOTSOURCE_H_ +#define AT91_SAMA5_BOOTSOURCE_H_ + +#include <errno.h> +#include <bootsource.h> +#include <linux/bitops.h> +#include <linux/bitfield.h> +#include <mach/hardware.h> + +/* 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); +} + +#define __sama5d2_stashed_bootrom_r4 \ + (*(volatile u32 *)(SAMA5D2_SRAM_BASE + SAMA5D2_SRAM_SIZE - 0x4)) + +#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 <mach/at91_ddrsdrc.h> +#include <mach/ddramc.h> +#include <mach/sama5d2_ll.h> + +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/arch/arm/mach-at91/include/mach/sama5d2.h b/arch/arm/mach-at91/include/mach/sama5d2.h index 3dad7d9c9c..90b566ffc4 100644 --- a/arch/arm/mach-at91/include/mach/sama5d2.h +++ b/arch/arm/mach-at91/include/mach/sama5d2.h @@ -14,6 +14,11 @@ #ifndef SAMA5D2_H #define SAMA5D2_H +#include <asm/io.h> +#include <linux/sizes.h> +#include <linux/bitops.h> +#include <linux/bitfield.h> + /* * Peripheral identifiers/interrupts. (Table 18-9) */ @@ -101,100 +106,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 @@ -258,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 new file mode 100644 index 0000000000..96f3bc5452 --- /dev/null +++ b/arch/arm/mach-at91/include/mach/sama5d2_ll.h @@ -0,0 +1,139 @@ +#ifndef __MACH_SAMA5D2_LL__ +#define __MACH_SAMA5D2_LL__ + +#include <mach/sama5d2.h> +#include <mach/at91_pmc_ll.h> +#include <mach/iomux.h> +#include <mach/debug_ll.h> +#include <mach/early_udelay.h> +#include <mach/ddramc.h> + +#include <common.h> + +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); +} + +/* 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); + +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); +} + +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 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/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 <linux/compiler.h> +#include <pbl.h> + +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/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 <io.h> +#include <mach/tz_matrix.h> +#include <mach/matrix.h> + +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.c b/arch/arm/mach-at91/sama5d2.c new file mode 100644 index 0000000000..2ce6d7f36f --- /dev/null +++ b/arch/arm/mach-at91/sama5d2.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <common.h> +#include <of.h> +#include <init.h> +#include <mach/aic.h> +#include <mach/sama5d2.h> +#include <asm/cache-l2x0.h> +#include <mach/sama5_bootsource.h> +#include <asm/mmu.h> + +#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; + + at91_aic_redir(SAMA5D2_BASE_SFR, SAMA5D2_AICREDIR_KEY); + sama5d2_can_ram_init(); + sama5d2_l2x0_init(); + + 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); diff --git a/arch/arm/mach-at91/sama5d2_ll.c b/arch/arm/mach-at91/sama5d2_ll.c new file mode 100644 index 0000000000..c3b5061777 --- /dev/null +++ b/arch/arm/mach-at91/sama5d2_ll.c @@ -0,0 +1,220 @@ +// 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 <mach/sama5d2_ll.h> +#include <mach/at91_ddrsdrc.h> +#include <mach/ddramc.h> +#include <mach/early_udelay.h> +#include <mach/tz_matrix.h> +#include <mach/matrix.h> +#include <mach/at91_rstc.h> +#include <asm/barebox-arm.h> + +#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 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, + SAMA5D2_BASE_RSTC + AT91_RSTC_MR); +} + +void sama5d2_lowlevel_init(void) +{ + arm_cpu_lowlevel_init(); + sama5d2_pmc_init(); + sama5d2_matrix_init(); + sama5d2_rstc_init(); +} 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 <mach/board.h> #include <mach/at91_pmc.h> #include <mach/at91sam9x5_matrix.h> -#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_ddrsdrc.h> #include <mach/iomux.h> #include <mach/cpu.h> #include <i2c/i2c-gpio.h> 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 <mach/board.h> #include <mach/at91_pmc.h> #include <mach/at91sam9x5_matrix.h> -#include <mach/at91sam9_ddrsdr.h> +#include <mach/at91_ddrsdrc.h> #include <mach/iomux.h> #include <mach/cpu.h> #include <i2c/i2c-gpio.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 <common.h> +#include <mach/xload.h> +#include <mach/sama5_bootsource.h> +#include <mach/hardware.h> +#include <mach/sama5d2_ll.h> +#include <mach/gpio.h> +#include <linux/sizes.h> +#include <asm/cache.h> +#include <pbl.h> + +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"); +} |