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> 1633b1d3f4SDaniel Gorsulowski #include <asm/arch/at91sam9_smc.h> 1733b1d3f4SDaniel Gorsulowski #include <asm/arch/at91_common.h> 1833b1d3f4SDaniel Gorsulowski #include <asm/arch/at91_pmc.h> 1933b1d3f4SDaniel Gorsulowski #include <asm/arch/at91_rstc.h> 20d4562e09SDaniel Gorsulowski #include <asm/arch/at91_matrix.h> 21d4562e09SDaniel Gorsulowski #include <asm/arch/at91_pio.h> 2233b1d3f4SDaniel Gorsulowski #include <asm/arch/clk.h> 2333b1d3f4SDaniel Gorsulowski #include <netdev.h> 2433b1d3f4SDaniel Gorsulowski 2533b1d3f4SDaniel Gorsulowski DECLARE_GLOBAL_DATA_PTR; 2633b1d3f4SDaniel Gorsulowski 2733b1d3f4SDaniel Gorsulowski /* 2833b1d3f4SDaniel Gorsulowski * Miscelaneous platform dependent initialisations 2933b1d3f4SDaniel Gorsulowski */ 3033b1d3f4SDaniel Gorsulowski 3183bf0057SDaniel Gorsulowski #ifdef CONFIG_REVISION_TAG 3233b1d3f4SDaniel Gorsulowski static int hw_rev = -1; /* hardware revision */ 3333b1d3f4SDaniel Gorsulowski 3433b1d3f4SDaniel Gorsulowski int get_hw_rev(void) 3533b1d3f4SDaniel Gorsulowski { 3633b1d3f4SDaniel Gorsulowski if (hw_rev >= 0) 3733b1d3f4SDaniel Gorsulowski return hw_rev; 3833b1d3f4SDaniel Gorsulowski 39d4562e09SDaniel Gorsulowski hw_rev = at91_get_pio_value(AT91_PIO_PORTB, 19); 40d4562e09SDaniel Gorsulowski hw_rev |= at91_get_pio_value(AT91_PIO_PORTB, 20) << 1; 41d4562e09SDaniel Gorsulowski hw_rev |= at91_get_pio_value(AT91_PIO_PORTB, 21) << 2; 42d4562e09SDaniel Gorsulowski hw_rev |= at91_get_pio_value(AT91_PIO_PORTB, 22) << 3; 4333b1d3f4SDaniel Gorsulowski 4433b1d3f4SDaniel Gorsulowski if (hw_rev == 15) 4533b1d3f4SDaniel Gorsulowski hw_rev = 0; 4633b1d3f4SDaniel Gorsulowski 4733b1d3f4SDaniel Gorsulowski return hw_rev; 4833b1d3f4SDaniel Gorsulowski } 4983bf0057SDaniel Gorsulowski #endif /* CONFIG_REVISION_TAG */ 5033b1d3f4SDaniel Gorsulowski 5133b1d3f4SDaniel Gorsulowski #ifdef CONFIG_CMD_NAND 5233b1d3f4SDaniel Gorsulowski static void meesc_nand_hw_init(void) 5333b1d3f4SDaniel Gorsulowski { 5433b1d3f4SDaniel Gorsulowski unsigned long csa; 550cb77bfaSMatthias Fuchs at91_smc_t *smc = (at91_smc_t *) ATMEL_BASE_SMC0; 560cb77bfaSMatthias Fuchs at91_matrix_t *matrix = (at91_matrix_t *) ATMEL_BASE_MATRIX; 5733b1d3f4SDaniel Gorsulowski 5833b1d3f4SDaniel Gorsulowski /* Enable CS3 */ 59d4562e09SDaniel Gorsulowski csa = readl(&matrix->csa[0]) | AT91_MATRIX_CSA_EBI_CS3A; 60d4562e09SDaniel Gorsulowski writel(csa, &matrix->csa[0]); 6133b1d3f4SDaniel Gorsulowski 6233b1d3f4SDaniel Gorsulowski /* Configure SMC CS3 for NAND/SmartMedia */ 63dd80264dSDaniel Gorsulowski writel(AT91_SMC_SETUP_NWE(1) | AT91_SMC_SETUP_NCS_WR(1) | 64dd80264dSDaniel Gorsulowski AT91_SMC_SETUP_NRD(2) | AT91_SMC_SETUP_NCS_RD(2), 65d4562e09SDaniel Gorsulowski &smc->cs[3].setup); 66d4562e09SDaniel Gorsulowski 67d4562e09SDaniel Gorsulowski writel(AT91_SMC_PULSE_NWE(3) | AT91_SMC_PULSE_NCS_WR(3) | 68d4562e09SDaniel Gorsulowski AT91_SMC_PULSE_NRD(3) | AT91_SMC_PULSE_NCS_RD(3), 69d4562e09SDaniel Gorsulowski &smc->cs[3].pulse); 70d4562e09SDaniel Gorsulowski 71dd80264dSDaniel Gorsulowski writel(AT91_SMC_CYCLE_NWE(6) | AT91_SMC_CYCLE_NRD(6), 72d4562e09SDaniel Gorsulowski &smc->cs[3].cycle); 73d4562e09SDaniel Gorsulowski writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE | 74d4562e09SDaniel Gorsulowski AT91_SMC_MODE_EXNW_DISABLE | 75d4562e09SDaniel Gorsulowski AT91_SMC_MODE_DBW_8 | 76dd80264dSDaniel Gorsulowski AT91_SMC_MODE_TDF_CYCLE(12), 77d4562e09SDaniel Gorsulowski &smc->cs[3].mode); 7833b1d3f4SDaniel Gorsulowski 7933b1d3f4SDaniel Gorsulowski /* Configure RDY/BSY */ 80ac45bb16SAndreas Bießmann gpio_direction_input(CONFIG_SYS_NAND_READY_PIN); 8133b1d3f4SDaniel Gorsulowski 8233b1d3f4SDaniel Gorsulowski /* Enable NandFlash */ 83ac45bb16SAndreas Bießmann gpio_direction_output(CONFIG_SYS_NAND_ENABLE_PIN, 1); 8433b1d3f4SDaniel Gorsulowski } 8533b1d3f4SDaniel Gorsulowski #endif /* CONFIG_CMD_NAND */ 8633b1d3f4SDaniel Gorsulowski 8733b1d3f4SDaniel Gorsulowski #ifdef CONFIG_MACB 8833b1d3f4SDaniel Gorsulowski static void meesc_macb_hw_init(void) 8933b1d3f4SDaniel Gorsulowski { 90*70341e2eSWenyou Yang at91_periph_clk_enable(ATMEL_ID_EMAC); 91*70341e2eSWenyou Yang 9233b1d3f4SDaniel Gorsulowski at91_macb_hw_init(); 9333b1d3f4SDaniel Gorsulowski } 9433b1d3f4SDaniel Gorsulowski #endif 9533b1d3f4SDaniel Gorsulowski 9633b1d3f4SDaniel Gorsulowski /* 9733b1d3f4SDaniel Gorsulowski * Static memory controller initialization to enable Beckhoff ET1100 EtherCAT 9833b1d3f4SDaniel Gorsulowski * controller debugging 9933b1d3f4SDaniel Gorsulowski * The ET1100 is located at physical address 0x70000000 10033b1d3f4SDaniel Gorsulowski * Its process memory is located at physical address 0x70001000 10133b1d3f4SDaniel Gorsulowski */ 10233b1d3f4SDaniel Gorsulowski static void meesc_ethercat_hw_init(void) 10333b1d3f4SDaniel Gorsulowski { 1040cb77bfaSMatthias Fuchs at91_smc_t *smc1 = (at91_smc_t *) ATMEL_BASE_SMC1; 105d4562e09SDaniel Gorsulowski 10633b1d3f4SDaniel Gorsulowski /* Configure SMC EBI1_CS0 for EtherCAT */ 107d4562e09SDaniel Gorsulowski writel(AT91_SMC_SETUP_NWE(0) | AT91_SMC_SETUP_NCS_WR(0) | 108d4562e09SDaniel Gorsulowski AT91_SMC_SETUP_NRD(0) | AT91_SMC_SETUP_NCS_RD(0), 109d4562e09SDaniel Gorsulowski &smc1->cs[0].setup); 110d4562e09SDaniel Gorsulowski writel(AT91_SMC_PULSE_NWE(4) | AT91_SMC_PULSE_NCS_WR(9) | 111d4562e09SDaniel Gorsulowski AT91_SMC_PULSE_NRD(5) | AT91_SMC_PULSE_NCS_RD(9), 112d4562e09SDaniel Gorsulowski &smc1->cs[0].pulse); 113d4562e09SDaniel Gorsulowski writel(AT91_SMC_CYCLE_NWE(10) | AT91_SMC_CYCLE_NRD(6), 114d4562e09SDaniel Gorsulowski &smc1->cs[0].cycle); 115a380279bSDaniel Gorsulowski /* 116a380279bSDaniel Gorsulowski * Configure behavior at external wait signal, byte-select mode, 16 bit 117a380279bSDaniel Gorsulowski * data bus width, none data float wait states and TDF optimization 118a380279bSDaniel Gorsulowski */ 119d4562e09SDaniel Gorsulowski writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_EXNW_READY | 120d4562e09SDaniel Gorsulowski AT91_SMC_MODE_DBW_16 | AT91_SMC_MODE_TDF_CYCLE(0) | 121d4562e09SDaniel Gorsulowski AT91_SMC_MODE_TDF, &smc1->cs[0].mode); 12233b1d3f4SDaniel Gorsulowski 12333b1d3f4SDaniel Gorsulowski /* Configure RDY/BSY */ 124d4562e09SDaniel Gorsulowski at91_set_b_periph(AT91_PIO_PORTE, 20, 0); /* EBI1_NWAIT */ 12533b1d3f4SDaniel Gorsulowski } 12633b1d3f4SDaniel Gorsulowski 12733b1d3f4SDaniel Gorsulowski int dram_init(void) 12833b1d3f4SDaniel Gorsulowski { 12983bf0057SDaniel Gorsulowski /* dram_init must store complete ramsize in gd->ram_size */ 13083bf0057SDaniel Gorsulowski gd->ram_size = get_ram_size((void *)PHYS_SDRAM, 13183bf0057SDaniel Gorsulowski PHYS_SDRAM_SIZE); 13233b1d3f4SDaniel Gorsulowski return 0; 13333b1d3f4SDaniel Gorsulowski } 13433b1d3f4SDaniel Gorsulowski 13583bf0057SDaniel Gorsulowski void dram_init_banksize(void) 13683bf0057SDaniel Gorsulowski { 13783bf0057SDaniel Gorsulowski gd->bd->bi_dram[0].start = PHYS_SDRAM; 13883bf0057SDaniel Gorsulowski gd->bd->bi_dram[0].size = PHYS_SDRAM_SIZE; 13983bf0057SDaniel Gorsulowski } 14083bf0057SDaniel Gorsulowski 14133b1d3f4SDaniel Gorsulowski int board_eth_init(bd_t *bis) 14233b1d3f4SDaniel Gorsulowski { 14333b1d3f4SDaniel Gorsulowski int rc = 0; 14433b1d3f4SDaniel Gorsulowski #ifdef CONFIG_MACB 1450cb77bfaSMatthias Fuchs rc = macb_eth_initialize(0, (void *)ATMEL_BASE_EMAC, 0x00); 14633b1d3f4SDaniel Gorsulowski #endif 14733b1d3f4SDaniel Gorsulowski return rc; 14833b1d3f4SDaniel Gorsulowski } 14933b1d3f4SDaniel Gorsulowski 15083bf0057SDaniel Gorsulowski #ifdef CONFIG_DISPLAY_BOARDINFO 15133b1d3f4SDaniel Gorsulowski int checkboard(void) 15233b1d3f4SDaniel Gorsulowski { 15333b1d3f4SDaniel Gorsulowski char str[32]; 154a380279bSDaniel Gorsulowski u_char hw_type; /* hardware type */ 15533b1d3f4SDaniel Gorsulowski 156a380279bSDaniel Gorsulowski /* read the "Type" register of the ET1100 controller */ 157a380279bSDaniel Gorsulowski hw_type = readb(CONFIG_ET1100_BASE); 158a380279bSDaniel Gorsulowski 159a380279bSDaniel Gorsulowski switch (hw_type) { 160a380279bSDaniel Gorsulowski case 0x11: 161a380279bSDaniel Gorsulowski case 0x3F: 162a380279bSDaniel Gorsulowski /* ET1100 present, arch number of MEESC-Board */ 163a380279bSDaniel Gorsulowski gd->bd->bi_arch_number = MACH_TYPE_MEESC; 164a380279bSDaniel Gorsulowski puts("Board: CAN-EtherCAT Gateway"); 165a380279bSDaniel Gorsulowski break; 166a380279bSDaniel Gorsulowski case 0xFF: 167a380279bSDaniel Gorsulowski /* no ET1100 present, arch number of EtherCAN/2-Board */ 168a380279bSDaniel Gorsulowski gd->bd->bi_arch_number = MACH_TYPE_ETHERCAN2; 169a380279bSDaniel Gorsulowski puts("Board: EtherCAN/2 Gateway"); 170a380279bSDaniel Gorsulowski /* switch on LED1D */ 171d4562e09SDaniel Gorsulowski at91_set_pio_output(AT91_PIO_PORTB, 12, 1); 172a380279bSDaniel Gorsulowski break; 173a380279bSDaniel Gorsulowski default: 174a380279bSDaniel Gorsulowski /* assume, no ET1100 present, arch number of EtherCAN/2-Board */ 175a380279bSDaniel Gorsulowski gd->bd->bi_arch_number = MACH_TYPE_ETHERCAN2; 176a380279bSDaniel Gorsulowski printf("ERROR! Read invalid hw_type: %02X\n", hw_type); 177a380279bSDaniel Gorsulowski puts("Board: EtherCAN/2 Gateway"); 178a380279bSDaniel Gorsulowski break; 179a380279bSDaniel Gorsulowski } 180cdb74977SWolfgang Denk if (getenv_f("serial#", str, sizeof(str)) > 0) { 18133b1d3f4SDaniel Gorsulowski puts(", serial# "); 18233b1d3f4SDaniel Gorsulowski puts(str); 18333b1d3f4SDaniel Gorsulowski } 18483bf0057SDaniel Gorsulowski #ifdef CONFIG_REVISION_TAG 18533b1d3f4SDaniel Gorsulowski printf("\nHardware-revision: 1.%d\n", get_hw_rev()); 18683bf0057SDaniel Gorsulowski #endif 18733b1d3f4SDaniel Gorsulowski printf("Mach-type: %lu\n", gd->bd->bi_arch_number); 18833b1d3f4SDaniel Gorsulowski return 0; 18933b1d3f4SDaniel Gorsulowski } 19083bf0057SDaniel Gorsulowski #endif /* CONFIG_DISPLAY_BOARDINFO */ 19133b1d3f4SDaniel Gorsulowski 192a380279bSDaniel Gorsulowski #ifdef CONFIG_SERIAL_TAG 193a380279bSDaniel Gorsulowski void get_board_serial(struct tag_serialnr *serialnr) 194a380279bSDaniel Gorsulowski { 195a380279bSDaniel Gorsulowski char *str; 196a380279bSDaniel Gorsulowski 197a380279bSDaniel Gorsulowski char *serial = getenv("serial#"); 198a380279bSDaniel Gorsulowski if (serial) { 199a380279bSDaniel Gorsulowski str = strchr(serial, '_'); 200a380279bSDaniel Gorsulowski if (str && (strlen(str) >= 4)) { 201a380279bSDaniel Gorsulowski serialnr->high = (*(str + 1) << 8) | *(str + 2); 202a380279bSDaniel Gorsulowski serialnr->low = simple_strtoul(str + 3, NULL, 16); 203a380279bSDaniel Gorsulowski } 204a380279bSDaniel Gorsulowski } else { 205a380279bSDaniel Gorsulowski serialnr->high = 0; 206a380279bSDaniel Gorsulowski serialnr->low = 0; 207a380279bSDaniel Gorsulowski } 208a380279bSDaniel Gorsulowski } 209a380279bSDaniel Gorsulowski #endif 210a380279bSDaniel Gorsulowski 211a380279bSDaniel Gorsulowski #ifdef CONFIG_REVISION_TAG 212a380279bSDaniel Gorsulowski u32 get_board_rev(void) 213a380279bSDaniel Gorsulowski { 214a380279bSDaniel Gorsulowski return hw_rev | 0x100; 215a380279bSDaniel Gorsulowski } 216a380279bSDaniel Gorsulowski #endif 217a380279bSDaniel Gorsulowski 218a3f3897bSDaniel Gorsulowski #ifdef CONFIG_MISC_INIT_R 219a3f3897bSDaniel Gorsulowski int misc_init_r(void) 220a3f3897bSDaniel Gorsulowski { 221a3f3897bSDaniel Gorsulowski char *str; 222a3f3897bSDaniel Gorsulowski char buf[32]; 2230cb77bfaSMatthias Fuchs at91_pmc_t *pmc = (at91_pmc_t *) ATMEL_BASE_PMC; 224a3f3897bSDaniel Gorsulowski 225a3f3897bSDaniel Gorsulowski /* 226a3f3897bSDaniel Gorsulowski * Normally the processor clock has a divisor of 2. 227a3f3897bSDaniel Gorsulowski * In some cases this this needs to be set to 4. 228a3f3897bSDaniel Gorsulowski * Check the user has set environment mdiv to 4 to change the divisor. 229a3f3897bSDaniel Gorsulowski */ 230a3f3897bSDaniel Gorsulowski if ((str = getenv("mdiv")) && (strcmp(str, "4") == 0)) { 231d4562e09SDaniel Gorsulowski writel((readl(&pmc->mckr) & ~AT91_PMC_MDIV) | 232d4562e09SDaniel Gorsulowski AT91SAM9_PMC_MDIV_4, &pmc->mckr); 233d4562e09SDaniel Gorsulowski at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK); 234a3f3897bSDaniel Gorsulowski serial_setbrg(); 235a3f3897bSDaniel Gorsulowski /* Notify the user that the clock is not default */ 236a3f3897bSDaniel Gorsulowski printf("Setting master clock to %s MHz\n", 237a3f3897bSDaniel Gorsulowski strmhz(buf, get_mck_clk_rate())); 238a3f3897bSDaniel Gorsulowski } 239a3f3897bSDaniel Gorsulowski 240a3f3897bSDaniel Gorsulowski return 0; 241a3f3897bSDaniel Gorsulowski } 242a3f3897bSDaniel Gorsulowski #endif /* CONFIG_MISC_INIT_R */ 243a3f3897bSDaniel Gorsulowski 2440cb77bfaSMatthias Fuchs int board_early_init_f(void) 24533b1d3f4SDaniel Gorsulowski { 246*70341e2eSWenyou Yang at91_periph_clk_enable(ATMEL_ID_PIOA); 247*70341e2eSWenyou Yang at91_periph_clk_enable(ATMEL_ID_PIOB); 248*70341e2eSWenyou Yang at91_periph_clk_enable(ATMEL_ID_PIOCDE); 249*70341e2eSWenyou Yang at91_periph_clk_enable(ATMEL_ID_UHP); 25033b1d3f4SDaniel Gorsulowski 2510cb77bfaSMatthias Fuchs at91_seriald_hw_init(); 2520cb77bfaSMatthias Fuchs 2530cb77bfaSMatthias Fuchs return 0; 2540cb77bfaSMatthias Fuchs } 2550cb77bfaSMatthias Fuchs 2560cb77bfaSMatthias Fuchs int board_init(void) 2570cb77bfaSMatthias Fuchs { 258a380279bSDaniel Gorsulowski /* initialize ET1100 Controller */ 259a380279bSDaniel Gorsulowski meesc_ethercat_hw_init(); 26033b1d3f4SDaniel Gorsulowski 26133b1d3f4SDaniel Gorsulowski /* adress of boot parameters */ 2620cb77bfaSMatthias Fuchs gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; 26333b1d3f4SDaniel Gorsulowski 26433b1d3f4SDaniel Gorsulowski #ifdef CONFIG_CMD_NAND 26533b1d3f4SDaniel Gorsulowski meesc_nand_hw_init(); 26633b1d3f4SDaniel Gorsulowski #endif 26733b1d3f4SDaniel Gorsulowski #ifdef CONFIG_HAS_DATAFLASH 26833b1d3f4SDaniel Gorsulowski at91_spi0_hw_init(1 << 0); 26933b1d3f4SDaniel Gorsulowski #endif 27033b1d3f4SDaniel Gorsulowski #ifdef CONFIG_MACB 27133b1d3f4SDaniel Gorsulowski meesc_macb_hw_init(); 27233b1d3f4SDaniel Gorsulowski #endif 27333b1d3f4SDaniel Gorsulowski #ifdef CONFIG_AT91_CAN 27433b1d3f4SDaniel Gorsulowski at91_can_hw_init(); 27533b1d3f4SDaniel Gorsulowski #endif 27664037fb4SDaniel Gorsulowski #ifdef CONFIG_USB_OHCI_NEW 27764037fb4SDaniel Gorsulowski at91_uhp_hw_init(); 27864037fb4SDaniel Gorsulowski #endif 27933b1d3f4SDaniel Gorsulowski return 0; 28033b1d3f4SDaniel Gorsulowski } 281