diff options
Diffstat (limited to 'arch/arm/boards/skov-arm9cpu')
-rw-r--r-- | arch/arm/boards/skov-arm9cpu/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/boards/skov-arm9cpu/board.c | 68 | ||||
-rw-r--r-- | arch/arm/boards/skov-arm9cpu/lowlevel.c | 220 |
3 files changed, 156 insertions, 134 deletions
diff --git a/arch/arm/boards/skov-arm9cpu/Makefile b/arch/arm/boards/skov-arm9cpu/Makefile index 01c7a259e9..da63d2625f 100644 --- a/arch/arm/boards/skov-arm9cpu/Makefile +++ b/arch/arm/boards/skov-arm9cpu/Makefile @@ -1,2 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only + obj-y += board.o lwl-y += lowlevel.o diff --git a/arch/arm/boards/skov-arm9cpu/board.c b/arch/arm/boards/skov-arm9cpu/board.c index 8d5eadbb9a..20507922cb 100644 --- a/arch/arm/boards/skov-arm9cpu/board.c +++ b/arch/arm/boards/skov-arm9cpu/board.c @@ -7,32 +7,42 @@ #include <envfs.h> #include <init.h> #include <gpio.h> +#include <bootsource.h> #include <linux/sizes.h> -#include <mach/at91sam9263_matrix.h> -#include <mach/at91sam9_sdramc.h> -#include <mach/at91sam9_smc.h> -#include <mach/hardware.h> -#include <mach/iomux.h> +#include <mach/at91/at91sam9263_matrix.h> +#include <mach/at91/at91sam9_sdramc.h> +#include <mach/at91/at91sam9_smc.h> +#include <mach/at91/hardware.h> +#include <mach/at91/iomux.h> -static struct sam9_smc_config ek_nand_smc_config = { - .ncs_read_setup = 0, - .nrd_setup = 1, +static struct sam9_smc_config skov_nor_smc_config = { + /* Setup time is 2 cycles after the CS signal */ + .nwe_setup = 2, .ncs_write_setup = 0, - .nwe_setup = 1, + .nrd_setup = 2, + .ncs_read_setup = 0, - .ncs_read_pulse = 3, - .nrd_pulse = 3, - .ncs_write_pulse = 3, - .nwe_pulse = 3, + /* Set pulse long enough - pulse should be a bit shorter than the cycle */ + .nwe_pulse = 10, + .ncs_write_pulse = 12, + .nrd_pulse = 10, + .ncs_read_pulse = 12, - .read_cycle = 5, - .write_cycle = 5, + /* Set cycle long enougth at least 12 Cycles->120ns plus a little extra */ + .write_cycle = 0x13, + .read_cycle = 0x13, + /* Set mode: 16Bit bus width, enable read and write + * Note: pagemode + 32 byte pages do not work with the 29GL512P flash + */ .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | - AT91_SMC_EXNWMODE_DISABLE, - .tdf_cycles = 2, + AT91_SMC_EXNWMODE_DISABLE | + AT91_SMC_BAT_WRITE | + AT91_SMC_DBW_16 | + AT91_SMC_TDFMODE, + .tdf_cycles = 1, }; BAREBOX_MAGICVAR(board.mem, "The detected memory size in MiB"); @@ -45,26 +55,29 @@ static int mem; * But is required before we start the other drives. * Use device_initcall() to maintain this order. */ -static int skov_arm9_probe(struct device_d *dev) +static int skov_arm9_probe(struct device *dev) { - unsigned long csa; + barebox_set_hostname("skov-arm9cpu"); add_generic_device("at91sam9-smc", 0, NULL, AT91SAM9263_BASE_SMC0, 0x200, IORESOURCE_MEM, NULL); add_generic_device("at91sam9-smc", 1, NULL, AT91SAM9263_BASE_SMC1, 0x200, IORESOURCE_MEM, NULL); - csa = readl(AT91SAM9263_BASE_MATRIX + AT91SAM9263_MATRIX_EBI0CSA); - csa |= AT91SAM9263_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA; - writel(csa, AT91SAM9263_BASE_MATRIX + AT91SAM9263_MATRIX_EBI0CSA); - - /* configure chip-select 3 (NAND) */ - sam9_smc_configure(0, 3, &ek_nand_smc_config); + /* configure chip-select 0 (NOR) */ + sam9_smc_configure(0, 0, &skov_nor_smc_config); mem = at91_get_sdram_size(IOMEM(AT91SAM9263_BASE_SDRAMC0)); mem = mem / SZ_1M; globalvar_add_simple_int("board.mem", &mem, "%u"); + /* + * NOR first stage bootloader is at91bootstrap, so if we find traces + * of barebox in on-chip SRAM, it must mean we have booted from SD + */ + if (is_barebox_arm_head((void *)AT91SAM9263_SRAM0_BASE)) + bootsource_set_raw(BOOTSOURCE_MMC, BOOTSOURCE_INSTANCE_UNKNOWN); + return 0; } @@ -75,10 +88,11 @@ static __maybe_unused struct of_device_id skov_arm9_ids[] = { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, skov_arm9_ids); -static struct driver_d skov_arm9_driver = { +static struct driver skov_arm9_driver = { .name = "skov-arm9", .probe = skov_arm9_probe, .of_compatible = DRV_OF_COMPAT(skov_arm9_ids), }; -device_platform_driver(skov_arm9_driver); +coredevice_platform_driver(skov_arm9_driver); diff --git a/arch/arm/boards/skov-arm9cpu/lowlevel.c b/arch/arm/boards/skov-arm9cpu/lowlevel.c index d335953a73..baf0b7bfc9 100644 --- a/arch/arm/boards/skov-arm9cpu/lowlevel.c +++ b/arch/arm/boards/skov-arm9cpu/lowlevel.c @@ -1,127 +1,133 @@ // SPDX-License-Identifier: GPL-2.0 -// PDX-FileCopyrightText: 2018 Sam Ravnborg <sam@ravnborg.org> - -#include <linux/sizes.h> - -#include <asm/barebox-arm.h> - -#include <mach/at91sam926x_board_init.h> -#include <mach/at91sam9263_matrix.h> - -#define MASTER_PLL_MUL 171 -#define MASTER_PLL_DIV 14 +// SPDX-FileCopyrightText: 2022 Sam Ravnborg <sam@ravnborg.org> + +#include <mach/at91/at91sam926x_board_init.h> +#include <mach/at91/at91sam9263_matrix.h> +#include <mach/at91/sam92_ll.h> +#include <mach/at91/xload.h> +#include <mach/at91/barebox-arm.h> +#include <linux/build_bug.h> + +/* MCK = 20 MHz */ +#define MAIN_CLOCK 200000000 +#define MASTER_CLOCK (MAIN_CLOCK / 2) /* PMC_MCKR divides by 2 */ + +#define PLLA_SETTINGS (AT91_PMC_PLLA_WR_ERRATA | AT91_PMC_MUL_(49) | AT91_PMC_OUT_2 | \ + AT91_PMC_PLLCOUNT_(48) | AT91_PMC_DIV_(4)) +static_assert(PLLA_SETTINGS == 0x2031B004); + +#define PLLB_SETTINGS (AT91_PMC_USBDIV_2 | AT91_PMC_MUL_(5) | AT91_PMC_OUT_0 | \ + AT91_PMC_PLLCOUNT_(48) | AT91_PMC_DIV_BYPASS) +static_assert(PLLB_SETTINGS == 0x10053001); + +/* + * Check if target is 64 or 128 MB and adjust AT91_SDRAMC_CR + * accordingly. + * Size Start Size(hex) + * 64 MB => 0x20000000 0x4000000 + * 128 MB => 0x20000000 0x8000000 + * + * If 64 MiB RAM with NC_10 set, then we see holes in the memory, which + * is how we detect if memory is 64 or 128 MiB + */ +static int check_if_128mb(void) +{ + unsigned int *test_adr = (unsigned int *)AT91_CHIPSELECT_1; + unsigned int test_val = 0xdeadbee0; + unsigned int *p; + int i; + + /* Fill up memory with a known pattern */ + p = test_adr; + for (i = 0; i < 0xb00; i++) + *p++ = test_val + i; + + /* + * Check that we can read back the values just written + * If one or more fails, we have only 64 MB + */ + p = test_adr; + for (i = 0; i < 0xb00; i++) + if (*p++ != (test_val + i)) + return false; + + return true; +} -static void __bare_init skovarm9cpu_board_config(struct at91sam926x_board_cfg *cfg) +static void sam9263_sdramc_init(void) { - /* Disable Watchdog */ - cfg->wdt_mr = - AT91_WDT_WDIDLEHLT | AT91_WDT_WDDBGHLT | - AT91_WDT_WDV | - AT91_WDT_WDDIS | - AT91_WDT_WDD; - - /* define PDC[31:16] as DATA[31:16] */ - cfg->ebi_pio_pdr = 0xFFFF0000; - /* no pull-up for D[31:16] */ - cfg->ebi_pio_ppudr = 0xFFFF0000; - /* EBI0_CSA, CS1 SDRAM, CS3 NAND Flash, 3.3V memories */ - cfg->ebi_csa = - AT91SAM9263_MATRIX_EBI0_DBPUC | AT91SAM9263_MATRIX_EBI0_VDDIOMSEL_3_3V | - AT91SAM9263_MATRIX_EBI0_CS1A_SDRAMC; - - cfg->smc_cs = 0; - cfg->smc_mode = - AT91_SMC_READMODE | AT91_SMC_WRITEMODE | - AT91_SMC_DBW_16 | - AT91_SMC_TDFMODE | - AT91_SMC_TDF_(6); - cfg->smc_cycle = - AT91_SMC_NWECYCLE_(22) | AT91_SMC_NRDCYCLE_(22); - cfg->smc_pulse = - AT91_SMC_NWEPULSE_(11) | AT91_SMC_NCS_WRPULSE_(11) | - AT91_SMC_NRDPULSE_(11) | AT91_SMC_NCS_RDPULSE_(11); - cfg->smc_setup = - AT91_SMC_NWESETUP_(10) | AT91_SMC_NCS_WRSETUP_(10) | - AT91_SMC_NRDSETUP_(10) | AT91_SMC_NCS_RDSETUP_(10); - - cfg->pmc_mor = - AT91_PMC_MOSCEN | - (255 << 8); /* Main Oscillator Start-up Time */ - cfg->pmc_pllar = - AT91_PMC_PLLA_WR_ERRATA | /* Bit 29 must be 1 when prog */ - AT91_PMC_OUT | - AT91_PMC_PLLCOUNT | /* PLL Counter */ - (2 << 28) | /* PLL Clock Frequency Range */ - ((MASTER_PLL_MUL - 1) << 16) | (MASTER_PLL_DIV); - /* PCK/2 = MCK Master Clock from PLLA */ - cfg->pmc_mckr1 = - AT91_PMC_CSS_SLOW | - AT91_PMC_PRES_1 | - AT91SAM9_PMC_MDIV_2 | - AT91_PMC_PDIV_1; - /* PCK/2 = MCK Master Clock from PLLA */ - cfg->pmc_mckr2 = - AT91_PMC_CSS_PLLA | - AT91_PMC_PRES_1 | - AT91SAM9_PMC_MDIV_2 | - AT91_PMC_PDIV_1; - - /* SDRAM */ - /* SDRAMC_TR - Refresh Timer register */ - cfg->sdrc_tr1 = 0x13C; - /* SDRAMC_CR - Configuration register*/ - cfg->sdrc_cr = - AT91_SDRAMC_NC_10 | /* Assume 128MiB */ - AT91_SDRAMC_NR_13 | - AT91_SDRAMC_NB_4 | - AT91_SDRAMC_CAS_3 | - AT91_SDRAMC_DBW_32 | - (1 << 8) | /* Write Recovery Delay */ - (7 << 12) | /* Row Cycle Delay */ - (2 << 16) | /* Row Precharge Delay */ - (2 << 20) | /* Row to Column Delay */ - (5 << 24) | /* Active to Precharge Delay */ - (1 << 28); /* Exit Self Refresh to Active Delay */ - - /* Memory Device Register -> SDRAM */ - cfg->sdrc_mdr = AT91_SDRAMC_MD_SDRAM; - /* SDRAM_TR */ - cfg->sdrc_tr2 = 1200; - - /* user reset enable */ - cfg->rstc_rmr = - AT91_RSTC_KEY | - AT91_RSTC_PROCRST | - AT91_RSTC_RSTTYP_WAKEUP | - AT91_RSTC_RSTTYP_WATCHDOG; + void __iomem *piod = IOMEM(AT91SAM9263_BASE_PIOD); + static struct at91sam9_sdramc_config config = { + .sdramc = IOMEM(AT91SAM9263_BASE_SDRAMC0), + .mr = 0, + .tr = (MASTER_CLOCK * 7) / 1000000, // TODO 140 versus 0x13c (316)? + .cr = AT91_SDRAMC_NC_10 | AT91_SDRAMC_NR_13 | AT91_SDRAMC_CAS_2 + | AT91_SDRAMC_NB_4 | AT91_SDRAMC_DBW_32 + | AT91_SDRAMC_TWR_2 | AT91_SDRAMC_TRC_7 + | AT91_SDRAMC_TRP_2 | AT91_SDRAMC_TRCD_2 + | AT91_SDRAMC_TRAS_5 | AT91_SDRAMC_TXSR_8, + .lpr = 0, + .mdr = AT91_SDRAMC_MD_SDRAM, + }; + + /* Define PD[31:16] as DATA[31:16] */ + at91_mux_gpio_disable(piod, GENMASK(31, 16)); + /* No pull-up for D[31:16] */ + at91_mux_set_pullup(piod, GENMASK(31, 16), false); + /* PD16 to PD31 are pheripheral A */ + at91_mux_set_A_periph(piod, GENMASK(31, 16)); + + /* EBI0_CSA, CS1 SDRAM, 3.3V memories */ + setbits_le32(IOMEM(AT91SAM9263_BASE_MATRIX + AT91SAM9263_MATRIX_EBI0CSA), + AT91SAM9263_MATRIX_EBI0_VDDIOMSEL_3_3V | AT91SAM9263_MATRIX_EBI0_CS1A_SDRAMC); + + at91sam9_sdramc_initialize(&config, AT91SAM9263_BASE_EBI0_CS1); + + if (!check_if_128mb()) { + /* Change number of columns to 9 for 64MB ram. */ + /* Other parameters does not need to be changed due to chip size. */ + + pr_debug("64M variant detected\n"); + + /* Clear NC bits */ + config.cr &= ~AT91_SDRAMC_NC; + config.cr |= AT91_SDRAMC_NC_9; + at91sam9_sdramc_initialize(&config, AT91SAM9263_BASE_EBI0_CS1); + } } -static void __bare_init skov_arm9cpu_init(void *fdt) +static noinline void continue_skov_arm9cpu_xload_mmc(void) { - struct at91sam926x_board_cfg cfg; + sam9263_lowlevel_init(PLLA_SETTINGS, PLLB_SETTINGS); + sam92_dbgu_setup_ll(MASTER_CLOCK); - cfg.pio = IOMEM(AT91SAM9263_BASE_PIOD); - cfg.sdramc = IOMEM(AT91SAM9263_BASE_SDRAMC0); - cfg.ebi_pio_is_peripha = true; - cfg.matrix_csa = IOMEM(AT91SAM9263_BASE_MATRIX + AT91SAM9263_MATRIX_EBI0CSA); + sam92_udelay_init(MASTER_CLOCK); + sam9263_sdramc_init(); + sam9263_atmci_start_image(1, MASTER_CLOCK, 0); +} - skovarm9cpu_board_config(&cfg); - at91sam9263_board_init(&cfg); +SAM9_ENTRY_FUNCTION(start_skov_arm9cpu_xload_mmc) +{ + /* Configure system so we are less constrained */ + arm_cpu_lowlevel_init(); + relocate_to_current_adr(); + setup_c(); - barebox_arm_entry(AT91_CHIPSELECT_1, at91_get_sdram_size(cfg.sdramc), - fdt); + continue_skov_arm9cpu_xload_mmc(); } extern char __dtb_at91_skov_arm9cpu_start[]; -ENTRY_FUNCTION(start_skov_arm9cpu, r0, r1, r2) +AT91_ENTRY_FUNCTION(start_skov_arm9cpu, r0, r1, r2) { void *fdt; + /* + * We may be running after at91bootstrap, so redo the initialization to + * be sure, everything is as we expect it. + */ arm_cpu_lowlevel_init(); - arm_setup_stack(AT91SAM9263_SRAM0_BASE + AT91SAM9263_SRAM0_SIZE); fdt = __dtb_at91_skov_arm9cpu_start + get_runtime_offset(); - - skov_arm9cpu_init(fdt); + barebox_arm_entry(AT91_CHIPSELECT_1, at91sam9263_get_sdram_size(0), fdt); } |