133b1d3f4SDaniel Gorsulowski /* 233b1d3f4SDaniel Gorsulowski * (C) Copyright 2007-2008 3c9e798d3SStelian Pop * Stelian Pop <stelian@popies.net> 433b1d3f4SDaniel Gorsulowski * Lead Tech Design <www.leadtechdesign.com> 533b1d3f4SDaniel Gorsulowski * 683bf0057SDaniel Gorsulowski * (C) Copyright 2009-2015 733b1d3f4SDaniel Gorsulowski * Daniel Gorsulowski <daniel.gorsulowski@esd.eu> 833b1d3f4SDaniel Gorsulowski * esd electronic system design gmbh <www.esd.eu> 933b1d3f4SDaniel Gorsulowski * 101a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 1133b1d3f4SDaniel Gorsulowski */ 1233b1d3f4SDaniel Gorsulowski 1333b1d3f4SDaniel Gorsulowski #include <common.h> 140cb77bfaSMatthias Fuchs #include <asm/io.h> 15ac45bb16SAndreas Bießmann #include <asm/gpio.h> 16c62db35dSSimon Glass #include <asm/mach-types.h> 17*5d982856SSimon Glass #include <asm/setup.h> 1833b1d3f4SDaniel Gorsulowski #include <asm/arch/at91sam9_smc.h> 1933b1d3f4SDaniel Gorsulowski #include <asm/arch/at91_common.h> 2033b1d3f4SDaniel Gorsulowski #include <asm/arch/at91_pmc.h> 2133b1d3f4SDaniel Gorsulowski #include <asm/arch/at91_rstc.h> 22d4562e09SDaniel Gorsulowski #include <asm/arch/at91_matrix.h> 23d4562e09SDaniel Gorsulowski #include <asm/arch/at91_pio.h> 2433b1d3f4SDaniel Gorsulowski #include <asm/arch/clk.h> 2533b1d3f4SDaniel Gorsulowski #include <netdev.h> 2633b1d3f4SDaniel Gorsulowski 2733b1d3f4SDaniel Gorsulowski DECLARE_GLOBAL_DATA_PTR; 2833b1d3f4SDaniel Gorsulowski 2933b1d3f4SDaniel Gorsulowski /* 3033b1d3f4SDaniel Gorsulowski * Miscelaneous platform dependent initialisations 3133b1d3f4SDaniel Gorsulowski */ 3233b1d3f4SDaniel Gorsulowski 3383bf0057SDaniel Gorsulowski #ifdef CONFIG_REVISION_TAG 3433b1d3f4SDaniel Gorsulowski static int hw_rev = -1; /* hardware revision */ 3533b1d3f4SDaniel Gorsulowski 3633b1d3f4SDaniel Gorsulowski int get_hw_rev(void) 3733b1d3f4SDaniel Gorsulowski { 3833b1d3f4SDaniel Gorsulowski if (hw_rev >= 0) 3933b1d3f4SDaniel Gorsulowski return hw_rev; 4033b1d3f4SDaniel Gorsulowski 41d4562e09SDaniel Gorsulowski hw_rev = at91_get_pio_value(AT91_PIO_PORTB, 19); 42d4562e09SDaniel Gorsulowski hw_rev |= at91_get_pio_value(AT91_PIO_PORTB, 20) << 1; 43d4562e09SDaniel Gorsulowski hw_rev |= at91_get_pio_value(AT91_PIO_PORTB, 21) << 2; 44d4562e09SDaniel Gorsulowski hw_rev |= at91_get_pio_value(AT91_PIO_PORTB, 22) << 3; 4533b1d3f4SDaniel Gorsulowski 4633b1d3f4SDaniel Gorsulowski if (hw_rev == 15) 4733b1d3f4SDaniel Gorsulowski hw_rev = 0; 4833b1d3f4SDaniel Gorsulowski 4933b1d3f4SDaniel Gorsulowski return hw_rev; 5033b1d3f4SDaniel Gorsulowski } 5183bf0057SDaniel Gorsulowski #endif /* CONFIG_REVISION_TAG */ 5233b1d3f4SDaniel Gorsulowski 5333b1d3f4SDaniel Gorsulowski #ifdef CONFIG_CMD_NAND 5433b1d3f4SDaniel Gorsulowski static void meesc_nand_hw_init(void) 5533b1d3f4SDaniel Gorsulowski { 5633b1d3f4SDaniel Gorsulowski unsigned long csa; 570cb77bfaSMatthias Fuchs at91_smc_t *smc = (at91_smc_t *) ATMEL_BASE_SMC0; 580cb77bfaSMatthias Fuchs at91_matrix_t *matrix = (at91_matrix_t *) ATMEL_BASE_MATRIX; 5933b1d3f4SDaniel Gorsulowski 6033b1d3f4SDaniel Gorsulowski /* Enable CS3 */ 61d4562e09SDaniel Gorsulowski csa = readl(&matrix->csa[0]) | AT91_MATRIX_CSA_EBI_CS3A; 62d4562e09SDaniel Gorsulowski writel(csa, &matrix->csa[0]); 6333b1d3f4SDaniel Gorsulowski 6433b1d3f4SDaniel Gorsulowski /* Configure SMC CS3 for NAND/SmartMedia */ 65dd80264dSDaniel Gorsulowski writel(AT91_SMC_SETUP_NWE(1) | AT91_SMC_SETUP_NCS_WR(1) | 66dd80264dSDaniel Gorsulowski AT91_SMC_SETUP_NRD(2) | AT91_SMC_SETUP_NCS_RD(2), 67d4562e09SDaniel Gorsulowski &smc->cs[3].setup); 68d4562e09SDaniel Gorsulowski 69d4562e09SDaniel Gorsulowski writel(AT91_SMC_PULSE_NWE(3) | AT91_SMC_PULSE_NCS_WR(3) | 70d4562e09SDaniel Gorsulowski AT91_SMC_PULSE_NRD(3) | AT91_SMC_PULSE_NCS_RD(3), 71d4562e09SDaniel Gorsulowski &smc->cs[3].pulse); 72d4562e09SDaniel Gorsulowski 73dd80264dSDaniel Gorsulowski writel(AT91_SMC_CYCLE_NWE(6) | AT91_SMC_CYCLE_NRD(6), 74d4562e09SDaniel Gorsulowski &smc->cs[3].cycle); 75d4562e09SDaniel Gorsulowski writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE | 76d4562e09SDaniel Gorsulowski AT91_SMC_MODE_EXNW_DISABLE | 77d4562e09SDaniel Gorsulowski AT91_SMC_MODE_DBW_8 | 78dd80264dSDaniel Gorsulowski AT91_SMC_MODE_TDF_CYCLE(12), 79d4562e09SDaniel Gorsulowski &smc->cs[3].mode); 8033b1d3f4SDaniel Gorsulowski 8133b1d3f4SDaniel Gorsulowski /* Configure RDY/BSY */ 82ac45bb16SAndreas Bießmann gpio_direction_input(CONFIG_SYS_NAND_READY_PIN); 8333b1d3f4SDaniel Gorsulowski 8433b1d3f4SDaniel Gorsulowski /* Enable NandFlash */ 85ac45bb16SAndreas Bießmann gpio_direction_output(CONFIG_SYS_NAND_ENABLE_PIN, 1); 8633b1d3f4SDaniel Gorsulowski } 8733b1d3f4SDaniel Gorsulowski #endif /* CONFIG_CMD_NAND */ 8833b1d3f4SDaniel Gorsulowski 8933b1d3f4SDaniel Gorsulowski #ifdef CONFIG_MACB 9033b1d3f4SDaniel Gorsulowski static void meesc_macb_hw_init(void) 9133b1d3f4SDaniel Gorsulowski { 9270341e2eSWenyou Yang at91_periph_clk_enable(ATMEL_ID_EMAC); 9370341e2eSWenyou Yang 9433b1d3f4SDaniel Gorsulowski at91_macb_hw_init(); 9533b1d3f4SDaniel Gorsulowski } 9633b1d3f4SDaniel Gorsulowski #endif 9733b1d3f4SDaniel Gorsulowski 9833b1d3f4SDaniel Gorsulowski /* 9933b1d3f4SDaniel Gorsulowski * Static memory controller initialization to enable Beckhoff ET1100 EtherCAT 10033b1d3f4SDaniel Gorsulowski * controller debugging 10133b1d3f4SDaniel Gorsulowski * The ET1100 is located at physical address 0x70000000 10233b1d3f4SDaniel Gorsulowski * Its process memory is located at physical address 0x70001000 10333b1d3f4SDaniel Gorsulowski */ 10433b1d3f4SDaniel Gorsulowski static void meesc_ethercat_hw_init(void) 10533b1d3f4SDaniel Gorsulowski { 1060cb77bfaSMatthias Fuchs at91_smc_t *smc1 = (at91_smc_t *) ATMEL_BASE_SMC1; 107d4562e09SDaniel Gorsulowski 10833b1d3f4SDaniel Gorsulowski /* Configure SMC EBI1_CS0 for EtherCAT */ 109d4562e09SDaniel Gorsulowski writel(AT91_SMC_SETUP_NWE(0) | AT91_SMC_SETUP_NCS_WR(0) | 110d4562e09SDaniel Gorsulowski AT91_SMC_SETUP_NRD(0) | AT91_SMC_SETUP_NCS_RD(0), 111d4562e09SDaniel Gorsulowski &smc1->cs[0].setup); 112d4562e09SDaniel Gorsulowski writel(AT91_SMC_PULSE_NWE(4) | AT91_SMC_PULSE_NCS_WR(9) | 113d4562e09SDaniel Gorsulowski AT91_SMC_PULSE_NRD(5) | AT91_SMC_PULSE_NCS_RD(9), 114d4562e09SDaniel Gorsulowski &smc1->cs[0].pulse); 115d4562e09SDaniel Gorsulowski writel(AT91_SMC_CYCLE_NWE(10) | AT91_SMC_CYCLE_NRD(6), 116d4562e09SDaniel Gorsulowski &smc1->cs[0].cycle); 117a380279bSDaniel Gorsulowski /* 118a380279bSDaniel Gorsulowski * Configure behavior at external wait signal, byte-select mode, 16 bit 119a380279bSDaniel Gorsulowski * data bus width, none data float wait states and TDF optimization 120a380279bSDaniel Gorsulowski */ 121d4562e09SDaniel Gorsulowski writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_EXNW_READY | 122d4562e09SDaniel Gorsulowski AT91_SMC_MODE_DBW_16 | AT91_SMC_MODE_TDF_CYCLE(0) | 123d4562e09SDaniel Gorsulowski AT91_SMC_MODE_TDF, &smc1->cs[0].mode); 12433b1d3f4SDaniel Gorsulowski 12533b1d3f4SDaniel Gorsulowski /* Configure RDY/BSY */ 126d4562e09SDaniel Gorsulowski at91_set_b_periph(AT91_PIO_PORTE, 20, 0); /* EBI1_NWAIT */ 12733b1d3f4SDaniel Gorsulowski } 12833b1d3f4SDaniel Gorsulowski 12933b1d3f4SDaniel Gorsulowski int dram_init(void) 13033b1d3f4SDaniel Gorsulowski { 13183bf0057SDaniel Gorsulowski /* dram_init must store complete ramsize in gd->ram_size */ 13283bf0057SDaniel Gorsulowski gd->ram_size = get_ram_size((void *)PHYS_SDRAM, 13383bf0057SDaniel Gorsulowski PHYS_SDRAM_SIZE); 13433b1d3f4SDaniel Gorsulowski return 0; 13533b1d3f4SDaniel Gorsulowski } 13633b1d3f4SDaniel Gorsulowski 13776b00acaSSimon Glass int dram_init_banksize(void) 13883bf0057SDaniel Gorsulowski { 13983bf0057SDaniel Gorsulowski gd->bd->bi_dram[0].start = PHYS_SDRAM; 14083bf0057SDaniel Gorsulowski gd->bd->bi_dram[0].size = PHYS_SDRAM_SIZE; 14176b00acaSSimon Glass 14276b00acaSSimon Glass return 0; 14383bf0057SDaniel Gorsulowski } 14483bf0057SDaniel Gorsulowski 14533b1d3f4SDaniel Gorsulowski int board_eth_init(bd_t *bis) 14633b1d3f4SDaniel Gorsulowski { 14733b1d3f4SDaniel Gorsulowski int rc = 0; 14833b1d3f4SDaniel Gorsulowski #ifdef CONFIG_MACB 1490cb77bfaSMatthias Fuchs rc = macb_eth_initialize(0, (void *)ATMEL_BASE_EMAC, 0x00); 15033b1d3f4SDaniel Gorsulowski #endif 15133b1d3f4SDaniel Gorsulowski return rc; 15233b1d3f4SDaniel Gorsulowski } 15333b1d3f4SDaniel Gorsulowski 15483bf0057SDaniel Gorsulowski #ifdef CONFIG_DISPLAY_BOARDINFO 15533b1d3f4SDaniel Gorsulowski int checkboard(void) 15633b1d3f4SDaniel Gorsulowski { 15733b1d3f4SDaniel Gorsulowski char str[32]; 158a380279bSDaniel Gorsulowski u_char hw_type; /* hardware type */ 15933b1d3f4SDaniel Gorsulowski 160a380279bSDaniel Gorsulowski /* read the "Type" register of the ET1100 controller */ 161a380279bSDaniel Gorsulowski hw_type = readb(CONFIG_ET1100_BASE); 162a380279bSDaniel Gorsulowski 163a380279bSDaniel Gorsulowski switch (hw_type) { 164a380279bSDaniel Gorsulowski case 0x11: 165a380279bSDaniel Gorsulowski case 0x3F: 166a380279bSDaniel Gorsulowski /* ET1100 present, arch number of MEESC-Board */ 167a380279bSDaniel Gorsulowski gd->bd->bi_arch_number = MACH_TYPE_MEESC; 168a380279bSDaniel Gorsulowski puts("Board: CAN-EtherCAT Gateway"); 169a380279bSDaniel Gorsulowski break; 170a380279bSDaniel Gorsulowski case 0xFF: 171a380279bSDaniel Gorsulowski /* no ET1100 present, arch number of EtherCAN/2-Board */ 172a380279bSDaniel Gorsulowski gd->bd->bi_arch_number = MACH_TYPE_ETHERCAN2; 173a380279bSDaniel Gorsulowski puts("Board: EtherCAN/2 Gateway"); 174a380279bSDaniel Gorsulowski /* switch on LED1D */ 175d4562e09SDaniel Gorsulowski at91_set_pio_output(AT91_PIO_PORTB, 12, 1); 176a380279bSDaniel Gorsulowski break; 177a380279bSDaniel Gorsulowski default: 178a380279bSDaniel Gorsulowski /* assume, no ET1100 present, arch number of EtherCAN/2-Board */ 179a380279bSDaniel Gorsulowski gd->bd->bi_arch_number = MACH_TYPE_ETHERCAN2; 180a380279bSDaniel Gorsulowski printf("ERROR! Read invalid hw_type: %02X\n", hw_type); 181a380279bSDaniel Gorsulowski puts("Board: EtherCAN/2 Gateway"); 182a380279bSDaniel Gorsulowski break; 183a380279bSDaniel Gorsulowski } 184cdb74977SWolfgang Denk if (getenv_f("serial#", str, sizeof(str)) > 0) { 18533b1d3f4SDaniel Gorsulowski puts(", serial# "); 18633b1d3f4SDaniel Gorsulowski puts(str); 18733b1d3f4SDaniel Gorsulowski } 18883bf0057SDaniel Gorsulowski #ifdef CONFIG_REVISION_TAG 18933b1d3f4SDaniel Gorsulowski printf("\nHardware-revision: 1.%d\n", get_hw_rev()); 19083bf0057SDaniel Gorsulowski #endif 19133b1d3f4SDaniel Gorsulowski printf("Mach-type: %lu\n", gd->bd->bi_arch_number); 19233b1d3f4SDaniel Gorsulowski return 0; 19333b1d3f4SDaniel Gorsulowski } 19483bf0057SDaniel Gorsulowski #endif /* CONFIG_DISPLAY_BOARDINFO */ 19533b1d3f4SDaniel Gorsulowski 196a380279bSDaniel Gorsulowski #ifdef CONFIG_SERIAL_TAG 197a380279bSDaniel Gorsulowski void get_board_serial(struct tag_serialnr *serialnr) 198a380279bSDaniel Gorsulowski { 199a380279bSDaniel Gorsulowski char *str; 200a380279bSDaniel Gorsulowski 201a380279bSDaniel Gorsulowski char *serial = getenv("serial#"); 202a380279bSDaniel Gorsulowski if (serial) { 203a380279bSDaniel Gorsulowski str = strchr(serial, '_'); 204a380279bSDaniel Gorsulowski if (str && (strlen(str) >= 4)) { 205a380279bSDaniel Gorsulowski serialnr->high = (*(str + 1) << 8) | *(str + 2); 206a380279bSDaniel Gorsulowski serialnr->low = simple_strtoul(str + 3, NULL, 16); 207a380279bSDaniel Gorsulowski } 208a380279bSDaniel Gorsulowski } else { 209a380279bSDaniel Gorsulowski serialnr->high = 0; 210a380279bSDaniel Gorsulowski serialnr->low = 0; 211a380279bSDaniel Gorsulowski } 212a380279bSDaniel Gorsulowski } 213a380279bSDaniel Gorsulowski #endif 214a380279bSDaniel Gorsulowski 215a380279bSDaniel Gorsulowski #ifdef CONFIG_REVISION_TAG 216a380279bSDaniel Gorsulowski u32 get_board_rev(void) 217a380279bSDaniel Gorsulowski { 218a380279bSDaniel Gorsulowski return hw_rev | 0x100; 219a380279bSDaniel Gorsulowski } 220a380279bSDaniel Gorsulowski #endif 221a380279bSDaniel Gorsulowski 222a3f3897bSDaniel Gorsulowski #ifdef CONFIG_MISC_INIT_R 223a3f3897bSDaniel Gorsulowski int misc_init_r(void) 224a3f3897bSDaniel Gorsulowski { 225a3f3897bSDaniel Gorsulowski char *str; 226a3f3897bSDaniel Gorsulowski char buf[32]; 2270cb77bfaSMatthias Fuchs at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; 228a3f3897bSDaniel Gorsulowski 229a3f3897bSDaniel Gorsulowski /* 230a3f3897bSDaniel Gorsulowski * Normally the processor clock has a divisor of 2. 231a3f3897bSDaniel Gorsulowski * In some cases this this needs to be set to 4. 232a3f3897bSDaniel Gorsulowski * Check the user has set environment mdiv to 4 to change the divisor. 233a3f3897bSDaniel Gorsulowski */ 234a3f3897bSDaniel Gorsulowski if ((str = getenv("mdiv")) && (strcmp(str, "4") == 0)) { 235d4562e09SDaniel Gorsulowski writel((readl(&pmc->mckr) & ~AT91_PMC_MDIV) | 236d4562e09SDaniel Gorsulowski AT91SAM9_PMC_MDIV_4, &pmc->mckr); 237d4562e09SDaniel Gorsulowski at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK); 238a3f3897bSDaniel Gorsulowski serial_setbrg(); 239a3f3897bSDaniel Gorsulowski /* Notify the user that the clock is not default */ 240a3f3897bSDaniel Gorsulowski printf("Setting master clock to %s MHz\n", 241a3f3897bSDaniel Gorsulowski strmhz(buf, get_mck_clk_rate())); 242a3f3897bSDaniel Gorsulowski } 243a3f3897bSDaniel Gorsulowski 244a3f3897bSDaniel Gorsulowski return 0; 245a3f3897bSDaniel Gorsulowski } 246a3f3897bSDaniel Gorsulowski #endif /* CONFIG_MISC_INIT_R */ 247a3f3897bSDaniel Gorsulowski 2480cb77bfaSMatthias Fuchs int board_early_init_f(void) 24933b1d3f4SDaniel Gorsulowski { 25070341e2eSWenyou Yang at91_periph_clk_enable(ATMEL_ID_PIOA); 25170341e2eSWenyou Yang at91_periph_clk_enable(ATMEL_ID_PIOB); 25270341e2eSWenyou Yang at91_periph_clk_enable(ATMEL_ID_PIOCDE); 25370341e2eSWenyou Yang at91_periph_clk_enable(ATMEL_ID_UHP); 25433b1d3f4SDaniel Gorsulowski 2550cb77bfaSMatthias Fuchs at91_seriald_hw_init(); 2560cb77bfaSMatthias Fuchs 2570cb77bfaSMatthias Fuchs return 0; 2580cb77bfaSMatthias Fuchs } 2590cb77bfaSMatthias Fuchs 2600cb77bfaSMatthias Fuchs int board_init(void) 2610cb77bfaSMatthias Fuchs { 262a380279bSDaniel Gorsulowski /* initialize ET1100 Controller */ 263a380279bSDaniel Gorsulowski meesc_ethercat_hw_init(); 26433b1d3f4SDaniel Gorsulowski 26533b1d3f4SDaniel Gorsulowski /* adress of boot parameters */ 2660cb77bfaSMatthias Fuchs gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; 26733b1d3f4SDaniel Gorsulowski 26833b1d3f4SDaniel Gorsulowski #ifdef CONFIG_CMD_NAND 26933b1d3f4SDaniel Gorsulowski meesc_nand_hw_init(); 27033b1d3f4SDaniel Gorsulowski #endif 27133b1d3f4SDaniel Gorsulowski #ifdef CONFIG_HAS_DATAFLASH 27233b1d3f4SDaniel Gorsulowski at91_spi0_hw_init(1 << 0); 27333b1d3f4SDaniel Gorsulowski #endif 27433b1d3f4SDaniel Gorsulowski #ifdef CONFIG_MACB 27533b1d3f4SDaniel Gorsulowski meesc_macb_hw_init(); 27633b1d3f4SDaniel Gorsulowski #endif 27733b1d3f4SDaniel Gorsulowski #ifdef CONFIG_AT91_CAN 27833b1d3f4SDaniel Gorsulowski at91_can_hw_init(); 27933b1d3f4SDaniel Gorsulowski #endif 28064037fb4SDaniel Gorsulowski #ifdef CONFIG_USB_OHCI_NEW 28164037fb4SDaniel Gorsulowski at91_uhp_hw_init(); 28264037fb4SDaniel Gorsulowski #endif 28333b1d3f4SDaniel Gorsulowski return 0; 28433b1d3f4SDaniel Gorsulowski } 285