133b1d3f4SDaniel Gorsulowski /* 233b1d3f4SDaniel Gorsulowski * (C) Copyright 2007-2008 333b1d3f4SDaniel Gorsulowski * Stelian Pop <stelian.pop@leadtechdesign.com> 433b1d3f4SDaniel Gorsulowski * Lead Tech Design <www.leadtechdesign.com> 533b1d3f4SDaniel Gorsulowski * 6*d4562e09SDaniel Gorsulowski * (C) Copyright 2009-2010 733b1d3f4SDaniel Gorsulowski * Daniel Gorsulowski <daniel.gorsulowski@esd.eu> 833b1d3f4SDaniel Gorsulowski * esd electronic system design gmbh <www.esd.eu> 933b1d3f4SDaniel Gorsulowski * 1033b1d3f4SDaniel Gorsulowski * See file CREDITS for list of people who contributed to this 1133b1d3f4SDaniel Gorsulowski * project. 1233b1d3f4SDaniel Gorsulowski * 1333b1d3f4SDaniel Gorsulowski * This program is free software; you can redistribute it and/or 1433b1d3f4SDaniel Gorsulowski * modify it under the terms of the GNU General Public License as 1533b1d3f4SDaniel Gorsulowski * published by the Free Software Foundation; either version 2 of 1633b1d3f4SDaniel Gorsulowski * the License, or (at your option) any later version. 1733b1d3f4SDaniel Gorsulowski * 1833b1d3f4SDaniel Gorsulowski * This program is distributed in the hope that it will be useful, 1933b1d3f4SDaniel Gorsulowski * but WITHOUT ANY WARRANTY; without even the implied warranty of 2033b1d3f4SDaniel Gorsulowski * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2133b1d3f4SDaniel Gorsulowski * GNU General Public License for more details. 2233b1d3f4SDaniel Gorsulowski * 2333b1d3f4SDaniel Gorsulowski * You should have received a copy of the GNU General Public License 2433b1d3f4SDaniel Gorsulowski * along with this program; if not, write to the Free Software 2533b1d3f4SDaniel Gorsulowski * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 2633b1d3f4SDaniel Gorsulowski * MA 02111-1307 USA 2733b1d3f4SDaniel Gorsulowski */ 2833b1d3f4SDaniel Gorsulowski 2933b1d3f4SDaniel Gorsulowski #include <common.h> 3033b1d3f4SDaniel Gorsulowski #include <asm/arch/at91sam9263.h> 3133b1d3f4SDaniel Gorsulowski #include <asm/arch/at91sam9_smc.h> 3233b1d3f4SDaniel Gorsulowski #include <asm/arch/at91_common.h> 3333b1d3f4SDaniel Gorsulowski #include <asm/arch/at91_pmc.h> 3433b1d3f4SDaniel Gorsulowski #include <asm/arch/at91_rstc.h> 35*d4562e09SDaniel Gorsulowski #include <asm/arch/at91_matrix.h> 36*d4562e09SDaniel Gorsulowski #include <asm/arch/at91_pio.h> 3733b1d3f4SDaniel Gorsulowski #include <asm/arch/clk.h> 3833b1d3f4SDaniel Gorsulowski #include <asm/arch/hardware.h> 3933b1d3f4SDaniel Gorsulowski #include <asm/arch/io.h> 4033b1d3f4SDaniel Gorsulowski #include <netdev.h> 4133b1d3f4SDaniel Gorsulowski 4233b1d3f4SDaniel Gorsulowski DECLARE_GLOBAL_DATA_PTR; 4333b1d3f4SDaniel Gorsulowski 4433b1d3f4SDaniel Gorsulowski /* 4533b1d3f4SDaniel Gorsulowski * Miscelaneous platform dependent initialisations 4633b1d3f4SDaniel Gorsulowski */ 4733b1d3f4SDaniel Gorsulowski 4833b1d3f4SDaniel Gorsulowski static int hw_rev = -1; /* hardware revision */ 4933b1d3f4SDaniel Gorsulowski 5033b1d3f4SDaniel Gorsulowski int get_hw_rev(void) 5133b1d3f4SDaniel Gorsulowski { 5233b1d3f4SDaniel Gorsulowski if (hw_rev >= 0) 5333b1d3f4SDaniel Gorsulowski return hw_rev; 5433b1d3f4SDaniel Gorsulowski 55*d4562e09SDaniel Gorsulowski hw_rev = at91_get_pio_value(AT91_PIO_PORTB, 19); 56*d4562e09SDaniel Gorsulowski hw_rev |= at91_get_pio_value(AT91_PIO_PORTB, 20) << 1; 57*d4562e09SDaniel Gorsulowski hw_rev |= at91_get_pio_value(AT91_PIO_PORTB, 21) << 2; 58*d4562e09SDaniel Gorsulowski hw_rev |= at91_get_pio_value(AT91_PIO_PORTB, 22) << 3; 5933b1d3f4SDaniel Gorsulowski 6033b1d3f4SDaniel Gorsulowski if (hw_rev == 15) 6133b1d3f4SDaniel Gorsulowski hw_rev = 0; 6233b1d3f4SDaniel Gorsulowski 6333b1d3f4SDaniel Gorsulowski return hw_rev; 6433b1d3f4SDaniel Gorsulowski } 6533b1d3f4SDaniel Gorsulowski 6633b1d3f4SDaniel Gorsulowski #ifdef CONFIG_CMD_NAND 6733b1d3f4SDaniel Gorsulowski static void meesc_nand_hw_init(void) 6833b1d3f4SDaniel Gorsulowski { 6933b1d3f4SDaniel Gorsulowski unsigned long csa; 70*d4562e09SDaniel Gorsulowski at91_smc_t *smc = (at91_smc_t *) AT91_SMC0_BASE; 71*d4562e09SDaniel Gorsulowski at91_matrix_t *matrix = (at91_matrix_t *) AT91_MATRIX_BASE; 7233b1d3f4SDaniel Gorsulowski 7333b1d3f4SDaniel Gorsulowski /* Enable CS3 */ 74*d4562e09SDaniel Gorsulowski csa = readl(&matrix->csa[0]) | AT91_MATRIX_CSA_EBI_CS3A; 75*d4562e09SDaniel Gorsulowski writel(csa, &matrix->csa[0]); 7633b1d3f4SDaniel Gorsulowski 7733b1d3f4SDaniel Gorsulowski /* Configure SMC CS3 for NAND/SmartMedia */ 78*d4562e09SDaniel Gorsulowski writel(AT91_SMC_SETUP_NWE(1) | AT91_SMC_SETUP_NCS_WR(0) | 79*d4562e09SDaniel Gorsulowski AT91_SMC_SETUP_NRD(1) | AT91_SMC_SETUP_NCS_RD(0), 80*d4562e09SDaniel Gorsulowski &smc->cs[3].setup); 81*d4562e09SDaniel Gorsulowski 82*d4562e09SDaniel Gorsulowski writel(AT91_SMC_PULSE_NWE(3) | AT91_SMC_PULSE_NCS_WR(3) | 83*d4562e09SDaniel Gorsulowski AT91_SMC_PULSE_NRD(3) | AT91_SMC_PULSE_NCS_RD(3), 84*d4562e09SDaniel Gorsulowski &smc->cs[3].pulse); 85*d4562e09SDaniel Gorsulowski 86*d4562e09SDaniel Gorsulowski writel(AT91_SMC_CYCLE_NWE(5) | AT91_SMC_CYCLE_NRD(5), 87*d4562e09SDaniel Gorsulowski &smc->cs[3].cycle); 88*d4562e09SDaniel Gorsulowski writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_WM_NWE | 89*d4562e09SDaniel Gorsulowski AT91_SMC_MODE_EXNW_DISABLE | 90*d4562e09SDaniel Gorsulowski AT91_SMC_MODE_DBW_8 | 91*d4562e09SDaniel Gorsulowski AT91_SMC_MODE_TDF_CYCLE(2), 92*d4562e09SDaniel Gorsulowski &smc->cs[3].mode); 9333b1d3f4SDaniel Gorsulowski 9433b1d3f4SDaniel Gorsulowski /* Configure RDY/BSY */ 95*d4562e09SDaniel Gorsulowski at91_set_pio_input(CONFIG_SYS_NAND_READY_PIN, 1); 9633b1d3f4SDaniel Gorsulowski 9733b1d3f4SDaniel Gorsulowski /* Enable NandFlash */ 98*d4562e09SDaniel Gorsulowski at91_set_pio_output(CONFIG_SYS_NAND_ENABLE_PIN, 1); 9933b1d3f4SDaniel Gorsulowski } 10033b1d3f4SDaniel Gorsulowski #endif /* CONFIG_CMD_NAND */ 10133b1d3f4SDaniel Gorsulowski 10233b1d3f4SDaniel Gorsulowski #ifdef CONFIG_MACB 10333b1d3f4SDaniel Gorsulowski static void meesc_macb_hw_init(void) 10433b1d3f4SDaniel Gorsulowski { 105*d4562e09SDaniel Gorsulowski at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; 10633b1d3f4SDaniel Gorsulowski /* Enable clock */ 107*d4562e09SDaniel Gorsulowski writel(1 << AT91SAM9263_ID_EMAC, &pmc->pcer); 10833b1d3f4SDaniel Gorsulowski at91_macb_hw_init(); 10933b1d3f4SDaniel Gorsulowski } 11033b1d3f4SDaniel Gorsulowski #endif 11133b1d3f4SDaniel Gorsulowski 11233b1d3f4SDaniel Gorsulowski /* 11333b1d3f4SDaniel Gorsulowski * Static memory controller initialization to enable Beckhoff ET1100 EtherCAT 11433b1d3f4SDaniel Gorsulowski * controller debugging 11533b1d3f4SDaniel Gorsulowski * The ET1100 is located at physical address 0x70000000 11633b1d3f4SDaniel Gorsulowski * Its process memory is located at physical address 0x70001000 11733b1d3f4SDaniel Gorsulowski */ 11833b1d3f4SDaniel Gorsulowski static void meesc_ethercat_hw_init(void) 11933b1d3f4SDaniel Gorsulowski { 120*d4562e09SDaniel Gorsulowski at91_smc_t *smc1 = (at91_smc_t *) AT91_SMC1_BASE; 121*d4562e09SDaniel Gorsulowski 12233b1d3f4SDaniel Gorsulowski /* Configure SMC EBI1_CS0 for EtherCAT */ 123*d4562e09SDaniel Gorsulowski writel(AT91_SMC_SETUP_NWE(0) | AT91_SMC_SETUP_NCS_WR(0) | 124*d4562e09SDaniel Gorsulowski AT91_SMC_SETUP_NRD(0) | AT91_SMC_SETUP_NCS_RD(0), 125*d4562e09SDaniel Gorsulowski &smc1->cs[0].setup); 126*d4562e09SDaniel Gorsulowski writel(AT91_SMC_PULSE_NWE(4) | AT91_SMC_PULSE_NCS_WR(9) | 127*d4562e09SDaniel Gorsulowski AT91_SMC_PULSE_NRD(5) | AT91_SMC_PULSE_NCS_RD(9), 128*d4562e09SDaniel Gorsulowski &smc1->cs[0].pulse); 129*d4562e09SDaniel Gorsulowski writel(AT91_SMC_CYCLE_NWE(10) | AT91_SMC_CYCLE_NRD(6), 130*d4562e09SDaniel Gorsulowski &smc1->cs[0].cycle); 131a380279bSDaniel Gorsulowski /* 132a380279bSDaniel Gorsulowski * Configure behavior at external wait signal, byte-select mode, 16 bit 133a380279bSDaniel Gorsulowski * data bus width, none data float wait states and TDF optimization 134a380279bSDaniel Gorsulowski */ 135*d4562e09SDaniel Gorsulowski writel(AT91_SMC_MODE_RM_NRD | AT91_SMC_MODE_EXNW_READY | 136*d4562e09SDaniel Gorsulowski AT91_SMC_MODE_DBW_16 | AT91_SMC_MODE_TDF_CYCLE(0) | 137*d4562e09SDaniel Gorsulowski AT91_SMC_MODE_TDF, &smc1->cs[0].mode); 13833b1d3f4SDaniel Gorsulowski 13933b1d3f4SDaniel Gorsulowski /* Configure RDY/BSY */ 140*d4562e09SDaniel Gorsulowski at91_set_b_periph(AT91_PIO_PORTE, 20, 0); /* EBI1_NWAIT */ 14133b1d3f4SDaniel Gorsulowski } 14233b1d3f4SDaniel Gorsulowski 14333b1d3f4SDaniel Gorsulowski int dram_init(void) 14433b1d3f4SDaniel Gorsulowski { 14533b1d3f4SDaniel Gorsulowski gd->bd->bi_dram[0].start = PHYS_SDRAM; 14633b1d3f4SDaniel Gorsulowski gd->bd->bi_dram[0].size = get_ram_size((long *) PHYS_SDRAM, (1 << 27)); 14733b1d3f4SDaniel Gorsulowski return 0; 14833b1d3f4SDaniel Gorsulowski } 14933b1d3f4SDaniel Gorsulowski 15033b1d3f4SDaniel Gorsulowski int board_eth_init(bd_t *bis) 15133b1d3f4SDaniel Gorsulowski { 15233b1d3f4SDaniel Gorsulowski int rc = 0; 15333b1d3f4SDaniel Gorsulowski #ifdef CONFIG_MACB 154*d4562e09SDaniel Gorsulowski rc = macb_eth_initialize(0, (void *)AT91_EMAC_BASE, 0x00); 15533b1d3f4SDaniel Gorsulowski #endif 15633b1d3f4SDaniel Gorsulowski return rc; 15733b1d3f4SDaniel Gorsulowski } 15833b1d3f4SDaniel Gorsulowski 15933b1d3f4SDaniel Gorsulowski int checkboard(void) 16033b1d3f4SDaniel Gorsulowski { 16133b1d3f4SDaniel Gorsulowski char str[32]; 162a380279bSDaniel Gorsulowski u_char hw_type; /* hardware type */ 16333b1d3f4SDaniel Gorsulowski 164a380279bSDaniel Gorsulowski /* read the "Type" register of the ET1100 controller */ 165a380279bSDaniel Gorsulowski hw_type = readb(CONFIG_ET1100_BASE); 166a380279bSDaniel Gorsulowski 167a380279bSDaniel Gorsulowski switch (hw_type) { 168a380279bSDaniel Gorsulowski case 0x11: 169a380279bSDaniel Gorsulowski case 0x3F: 170a380279bSDaniel Gorsulowski /* ET1100 present, arch number of MEESC-Board */ 171a380279bSDaniel Gorsulowski gd->bd->bi_arch_number = MACH_TYPE_MEESC; 172a380279bSDaniel Gorsulowski puts("Board: CAN-EtherCAT Gateway"); 173a380279bSDaniel Gorsulowski break; 174a380279bSDaniel Gorsulowski case 0xFF: 175a380279bSDaniel Gorsulowski /* no ET1100 present, arch number of EtherCAN/2-Board */ 176a380279bSDaniel Gorsulowski gd->bd->bi_arch_number = MACH_TYPE_ETHERCAN2; 177a380279bSDaniel Gorsulowski puts("Board: EtherCAN/2 Gateway"); 178a380279bSDaniel Gorsulowski /* switch on LED1D */ 179*d4562e09SDaniel Gorsulowski at91_set_pio_output(AT91_PIO_PORTB, 12, 1); 180a380279bSDaniel Gorsulowski break; 181a380279bSDaniel Gorsulowski default: 182a380279bSDaniel Gorsulowski /* assume, no ET1100 present, arch number of EtherCAN/2-Board */ 183a380279bSDaniel Gorsulowski gd->bd->bi_arch_number = MACH_TYPE_ETHERCAN2; 184a380279bSDaniel Gorsulowski printf("ERROR! Read invalid hw_type: %02X\n", hw_type); 185a380279bSDaniel Gorsulowski puts("Board: EtherCAN/2 Gateway"); 186a380279bSDaniel Gorsulowski break; 187a380279bSDaniel Gorsulowski } 188cdb74977SWolfgang Denk if (getenv_f("serial#", str, sizeof(str)) > 0) { 18933b1d3f4SDaniel Gorsulowski puts(", serial# "); 19033b1d3f4SDaniel Gorsulowski puts(str); 19133b1d3f4SDaniel Gorsulowski } 19233b1d3f4SDaniel Gorsulowski printf("\nHardware-revision: 1.%d\n", get_hw_rev()); 19333b1d3f4SDaniel Gorsulowski printf("Mach-type: %lu\n", gd->bd->bi_arch_number); 19433b1d3f4SDaniel Gorsulowski return 0; 19533b1d3f4SDaniel Gorsulowski } 19633b1d3f4SDaniel Gorsulowski 197a380279bSDaniel Gorsulowski #ifdef CONFIG_SERIAL_TAG 198a380279bSDaniel Gorsulowski void get_board_serial(struct tag_serialnr *serialnr) 199a380279bSDaniel Gorsulowski { 200a380279bSDaniel Gorsulowski char *str; 201a380279bSDaniel Gorsulowski 202a380279bSDaniel Gorsulowski char *serial = getenv("serial#"); 203a380279bSDaniel Gorsulowski if (serial) { 204a380279bSDaniel Gorsulowski str = strchr(serial, '_'); 205a380279bSDaniel Gorsulowski if (str && (strlen(str) >= 4)) { 206a380279bSDaniel Gorsulowski serialnr->high = (*(str + 1) << 8) | *(str + 2); 207a380279bSDaniel Gorsulowski serialnr->low = simple_strtoul(str + 3, NULL, 16); 208a380279bSDaniel Gorsulowski } 209a380279bSDaniel Gorsulowski } else { 210a380279bSDaniel Gorsulowski serialnr->high = 0; 211a380279bSDaniel Gorsulowski serialnr->low = 0; 212a380279bSDaniel Gorsulowski } 213a380279bSDaniel Gorsulowski } 214a380279bSDaniel Gorsulowski #endif 215a380279bSDaniel Gorsulowski 216a380279bSDaniel Gorsulowski #ifdef CONFIG_REVISION_TAG 217a380279bSDaniel Gorsulowski u32 get_board_rev(void) 218a380279bSDaniel Gorsulowski { 219a380279bSDaniel Gorsulowski return hw_rev | 0x100; 220a380279bSDaniel Gorsulowski } 221a380279bSDaniel Gorsulowski #endif 222a380279bSDaniel Gorsulowski 223a3f3897bSDaniel Gorsulowski #ifdef CONFIG_MISC_INIT_R 224a3f3897bSDaniel Gorsulowski int misc_init_r(void) 225a3f3897bSDaniel Gorsulowski { 226a3f3897bSDaniel Gorsulowski char *str; 227a3f3897bSDaniel Gorsulowski char buf[32]; 228*d4562e09SDaniel Gorsulowski at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; 229a3f3897bSDaniel Gorsulowski 230a3f3897bSDaniel Gorsulowski /* 231a3f3897bSDaniel Gorsulowski * Normally the processor clock has a divisor of 2. 232a3f3897bSDaniel Gorsulowski * In some cases this this needs to be set to 4. 233a3f3897bSDaniel Gorsulowski * Check the user has set environment mdiv to 4 to change the divisor. 234a3f3897bSDaniel Gorsulowski */ 235a3f3897bSDaniel Gorsulowski if ((str = getenv("mdiv")) && (strcmp(str, "4") == 0)) { 236*d4562e09SDaniel Gorsulowski writel((readl(&pmc->mckr) & ~AT91_PMC_MDIV) | 237*d4562e09SDaniel Gorsulowski AT91SAM9_PMC_MDIV_4, &pmc->mckr); 238*d4562e09SDaniel Gorsulowski at91_clock_init(CONFIG_SYS_AT91_MAIN_CLOCK); 239a3f3897bSDaniel Gorsulowski serial_setbrg(); 240a3f3897bSDaniel Gorsulowski /* Notify the user that the clock is not default */ 241a3f3897bSDaniel Gorsulowski printf("Setting master clock to %s MHz\n", 242a3f3897bSDaniel Gorsulowski strmhz(buf, get_mck_clk_rate())); 243a3f3897bSDaniel Gorsulowski } 244a3f3897bSDaniel Gorsulowski 245a3f3897bSDaniel Gorsulowski return 0; 246a3f3897bSDaniel Gorsulowski } 247a3f3897bSDaniel Gorsulowski #endif /* CONFIG_MISC_INIT_R */ 248a3f3897bSDaniel Gorsulowski 24933b1d3f4SDaniel Gorsulowski int board_init(void) 25033b1d3f4SDaniel Gorsulowski { 251*d4562e09SDaniel Gorsulowski at91_pmc_t *pmc = (at91_pmc_t *) AT91_PMC_BASE; 252*d4562e09SDaniel Gorsulowski 25333b1d3f4SDaniel Gorsulowski /* Peripheral Clock Enable Register */ 254*d4562e09SDaniel Gorsulowski writel(1 << AT91SAM9263_ID_PIOA | 25533b1d3f4SDaniel Gorsulowski 1 << AT91SAM9263_ID_PIOB | 256*d4562e09SDaniel Gorsulowski 1 << AT91SAM9263_ID_PIOCDE, 257*d4562e09SDaniel Gorsulowski &pmc->pcer); 25833b1d3f4SDaniel Gorsulowski 259a380279bSDaniel Gorsulowski /* initialize ET1100 Controller */ 260a380279bSDaniel Gorsulowski meesc_ethercat_hw_init(); 26133b1d3f4SDaniel Gorsulowski 26233b1d3f4SDaniel Gorsulowski /* adress of boot parameters */ 26333b1d3f4SDaniel Gorsulowski gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; 26433b1d3f4SDaniel Gorsulowski 26533b1d3f4SDaniel Gorsulowski at91_serial_hw_init(); 26633b1d3f4SDaniel Gorsulowski #ifdef CONFIG_CMD_NAND 26733b1d3f4SDaniel Gorsulowski meesc_nand_hw_init(); 26833b1d3f4SDaniel Gorsulowski #endif 26933b1d3f4SDaniel Gorsulowski #ifdef CONFIG_HAS_DATAFLASH 27033b1d3f4SDaniel Gorsulowski at91_spi0_hw_init(1 << 0); 27133b1d3f4SDaniel Gorsulowski #endif 27233b1d3f4SDaniel Gorsulowski #ifdef CONFIG_MACB 27333b1d3f4SDaniel Gorsulowski meesc_macb_hw_init(); 27433b1d3f4SDaniel Gorsulowski #endif 27533b1d3f4SDaniel Gorsulowski #ifdef CONFIG_AT91_CAN 27633b1d3f4SDaniel Gorsulowski at91_can_hw_init(); 27733b1d3f4SDaniel Gorsulowski #endif 27833b1d3f4SDaniel Gorsulowski return 0; 27933b1d3f4SDaniel Gorsulowski } 280