diff options
Diffstat (limited to 'arch/arm/mach-at91rm9200')
24 files changed, 3094 insertions, 111 deletions
diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91rm9200/Kconfig index 2f85e8693b1b..9f11db8af233 100644 --- a/arch/arm/mach-at91rm9200/Kconfig +++ b/arch/arm/mach-at91rm9200/Kconfig @@ -2,7 +2,8 @@ if ARCH_AT91 menu "Atmel AT91 System-on-Chip" -comment "Atmel AT91 Processors" +choice + prompt "Atmel AT91 Processor" config ARCH_AT91RM9200 bool "AT91RM9200" @@ -13,6 +14,8 @@ config ARCH_AT91SAM9260 config ARCH_AT91SAM9261 bool "AT91SAM9261" +endchoice + # ---------------------------------------------------------- if ARCH_AT91RM9200 @@ -33,7 +36,6 @@ config ARCH_AT91RM9200DK Select this if you are using Atmel's AT91RM9200-DK Development board. (Discontinued) - config MACH_AT91RM9200EK bool "Atmel AT91RM9200-EK Evaluation Kit" depends on ARCH_AT91RM9200 @@ -90,6 +92,13 @@ if ARCH_AT91SAM9260 comment "AT91SAM9260 Board Type" +config MACH_AT91SAM9260EK + bool "Atmel AT91SAM9260-EK Evaluation Kit" + depends on ARCH_AT91SAM9260 + help + Select this if you are using Atmel's AT91SAM9260-EK Evaluation Kit. + <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3933> + endif # ---------------------------------------------------------- @@ -98,8 +107,31 @@ if ARCH_AT91SAM9261 comment "AT91SAM9261 Board Type" +config MACH_AT91SAM9261EK + bool "Atmel AT91SAM9261-EK Evaluation Kit" + depends on ARCH_AT91SAM9261 + help + Select this if you are using Atmel's AT91SAM9261-EK Evaluation Kit. + <http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3820> + endif +# ---------------------------------------------------------- + +comment "AT91 Board Options" + +config MTD_AT91_DATAFLASH_CARD + bool "Enable DataFlash Card support" + depends on (ARCH_AT91RM9200DK || MACH_AT91RM9200EK || MACH_AT91SAM9260EK || MACH_AT91SAM9261EK) + help + Enable support for the DataFlash card. + +config MTD_NAND_AT91_BUSWIDTH_16 + bool "Enable 16-bit data bus interface to NAND flash" + depends on (MACH_AT91SAM9261EK || MACH_AT91SAM9260EK) + help + On AT91SAM926x boards both types of NAND flash can be present + (8 and 16 bit data bus width). # ---------------------------------------------------------- diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile index c174805c24e5..cf777007847a 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91rm9200/Makefile @@ -2,7 +2,7 @@ # Makefile for the linux kernel. # -obj-y := clock.o irq.o gpio.o devices.o +obj-y := clock.o irq.o gpio.o obj-m := obj-n := obj- := @@ -10,11 +10,11 @@ obj- := obj-$(CONFIG_PM) += pm.o # CPU-specific support -obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o -obj-$(CONFIG_ARCH_AT91SAM9260) += -obj-$(CONFIG_ARCH_AT91SAM9261) += +obj-$(CONFIG_ARCH_AT91RM9200) += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o +obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o +obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o -# AT91RM9200 Board-specific support +# AT91RM9200 board-specific support obj-$(CONFIG_MACH_ONEARM) += board-1arm.o obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o @@ -26,8 +26,10 @@ obj-$(CONFIG_MACH_ATEB9200) += board-eb9200.o obj-$(CONFIG_MACH_KAFA) += board-kafa.o # AT91SAM9260 board-specific support +obj-$(CONFIG_MACH_AT91SAM9260EK) += board-sam9260ek.o # AT91SAM9261 board-specific support +obj-$(CONFIG_MACH_AT91SAM9261EK) += board-sam9261ek.o # LEDs support led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o diff --git a/arch/arm/mach-at91rm9200/at91rm9200.c b/arch/arm/mach-at91rm9200/at91rm9200.c index dcf6136fedf9..a92e9a495b07 100644 --- a/arch/arm/mach-at91rm9200/at91rm9200.c +++ b/arch/arm/mach-at91rm9200/at91rm9200.c @@ -14,8 +14,10 @@ #include <asm/mach/arch.h> #include <asm/mach/map.h> +#include <asm/arch/at91rm9200.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91_st.h> -#include <asm/hardware.h> #include "generic.h" #include "clock.h" @@ -26,32 +28,12 @@ static struct map_desc at91rm9200_io_desc[] __initdata = { .length = SZ_4K, .type = MT_DEVICE, }, { - .virtual = AT91_VA_BASE_SPI, - .pfn = __phys_to_pfn(AT91RM9200_BASE_SPI), - .length = SZ_16K, - .type = MT_DEVICE, - }, { .virtual = AT91_VA_BASE_EMAC, .pfn = __phys_to_pfn(AT91RM9200_BASE_EMAC), .length = SZ_16K, .type = MT_DEVICE, }, { - .virtual = AT91_VA_BASE_TWI, - .pfn = __phys_to_pfn(AT91RM9200_BASE_TWI), - .length = SZ_16K, - .type = MT_DEVICE, - }, { - .virtual = AT91_VA_BASE_MCI, - .pfn = __phys_to_pfn(AT91RM9200_BASE_MCI), - .length = SZ_16K, - .type = MT_DEVICE, - }, { - .virtual = AT91_VA_BASE_UDP, - .pfn = __phys_to_pfn(AT91RM9200_BASE_UDP), - .length = SZ_16K, - .type = MT_DEVICE, - }, { - .virtual = AT91_SRAM_VIRT_BASE, + .virtual = AT91_IO_VIRT_BASE - AT91RM9200_SRAM_SIZE, .pfn = __phys_to_pfn(AT91RM9200_SRAM_BASE), .length = AT91RM9200_SRAM_SIZE, .type = MT_DEVICE, @@ -222,6 +204,16 @@ static struct at91_gpio_bank at91rm9200_gpio[] = { } }; +static void at91rm9200_reset(void) +{ + /* + * Perform a hardware reset with the use of the Watchdog timer. + */ + at91_sys_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1); + at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); +} + + /* -------------------------------------------------------------------- * AT91RM9200 processor initialization * -------------------------------------------------------------------- */ @@ -230,6 +222,12 @@ void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks /* Map peripherals */ iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc)); + at91_arch_reset = at91rm9200_reset; + at91_extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1) + | (1 << AT91RM9200_ID_IRQ2) | (1 << AT91RM9200_ID_IRQ3) + | (1 << AT91RM9200_ID_IRQ4) | (1 << AT91RM9200_ID_IRQ5) + | (1 << AT91RM9200_ID_IRQ6); + /* Init clock subsystem */ at91_clock_init(main_clock); diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/at91rm9200_devices.c index 059824376629..4641b99db0ee 100644 --- a/arch/arm/mach-at91rm9200/devices.c +++ b/arch/arm/mach-at91rm9200/at91rm9200_devices.c @@ -1,5 +1,5 @@ /* - * arch/arm/mach-at91rm9200/devices.c + * arch/arm/mach-at91rm9200/at91rm9200_devices.c * * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> * Copyright (C) 2005 David Brownell @@ -15,9 +15,10 @@ #include <linux/platform_device.h> -#include <asm/hardware.h> #include <asm/arch/board.h> #include <asm/arch/gpio.h> +#include <asm/arch/at91rm9200.h> +#include <asm/arch/at91rm9200_mc.h> #include "generic.h" @@ -33,7 +34,7 @@ static u64 ohci_dmamask = 0xffffffffUL; static struct at91_usbh_data usbh_data; -static struct resource at91_usbh_resources[] = { +static struct resource usbh_resources[] = { [0] = { .start = AT91RM9200_UHP_BASE, .end = AT91RM9200_UHP_BASE + SZ_1M - 1, @@ -54,8 +55,8 @@ static struct platform_device at91rm9200_usbh_device = { .coherent_dma_mask = 0xffffffff, .platform_data = &usbh_data, }, - .resource = at91_usbh_resources, - .num_resources = ARRAY_SIZE(at91_usbh_resources), + .resource = usbh_resources, + .num_resources = ARRAY_SIZE(usbh_resources), }; void __init at91_add_device_usbh(struct at91_usbh_data *data) @@ -78,7 +79,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {} #ifdef CONFIG_USB_GADGET_AT91 static struct at91_udc_data udc_data; -static struct resource at91_udc_resources[] = { +static struct resource udc_resources[] = { [0] = { .start = AT91RM9200_BASE_UDP, .end = AT91RM9200_BASE_UDP + SZ_16K - 1, @@ -97,8 +98,8 @@ static struct platform_device at91rm9200_udc_device = { .dev = { .platform_data = &udc_data, }, - .resource = at91_udc_resources, - .num_resources = ARRAY_SIZE(at91_udc_resources), + .resource = udc_resources, + .num_resources = ARRAY_SIZE(udc_resources), }; void __init at91_add_device_udc(struct at91_udc_data *data) @@ -129,7 +130,7 @@ void __init at91_add_device_udc(struct at91_udc_data *data) {} static u64 eth_dmamask = 0xffffffffUL; static struct at91_eth_data eth_data; -static struct resource at91_eth_resources[] = { +static struct resource eth_resources[] = { [0] = { .start = AT91_VA_BASE_EMAC, .end = AT91_VA_BASE_EMAC + SZ_16K - 1, @@ -150,8 +151,8 @@ static struct platform_device at91rm9200_eth_device = { .coherent_dma_mask = 0xffffffff, .platform_data = ð_data, }, - .resource = at91_eth_resources, - .num_resources = ARRAY_SIZE(at91_eth_resources), + .resource = eth_resources, + .num_resources = ARRAY_SIZE(eth_resources), }; void __init at91_add_device_eth(struct at91_eth_data *data) @@ -202,11 +203,13 @@ void __init at91_add_device_eth(struct at91_eth_data *data) {} #if defined(CONFIG_AT91_CF) || defined(CONFIG_AT91_CF_MODULE) static struct at91_cf_data cf_data; -static struct resource at91_cf_resources[] = { +#define CF_BASE AT91_CHIPSELECT_4 + +static struct resource cf_resources[] = { [0] = { - .start = AT91_CF_BASE, + .start = CF_BASE, /* ties up CS4, CS5 and CS6 */ - .end = AT91_CF_BASE + (0x30000000 - 1), + .end = CF_BASE + (0x30000000 - 1), .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, }, }; @@ -217,15 +220,38 @@ static struct platform_device at91rm9200_cf_device = { .dev = { .platform_data = &cf_data, }, - .resource = at91_cf_resources, - .num_resources = ARRAY_SIZE(at91_cf_resources), + .resource = cf_resources, + .num_resources = ARRAY_SIZE(cf_resources), }; void __init at91_add_device_cf(struct at91_cf_data *data) { + unsigned int csa; + if (!data) return; + data->chipselect = 4; /* can only use EBI ChipSelect 4 */ + + /* CF takes over CS4, CS5, CS6 */ + csa = at91_sys_read(AT91_EBI_CSA); + at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH); + + /* + * Static memory controller timing adjustments. + * REVISIT: these timings are in terms of MCK cycles, so + * when MCK changes (cpufreq etc) so must these values... + */ + at91_sys_write(AT91_SMC_CSR(4), + AT91_SMC_ACSS_STD + | AT91_SMC_DBW_16 + | AT91_SMC_BAT + | AT91_SMC_WSEN + | AT91_SMC_NWS_(32) /* wait states */ + | AT91_SMC_RWSETUP_(6) /* setup time */ + | AT91_SMC_RWHOLD_(4) /* hold time */ + ); + /* input/irq */ if (data->irq_pin) { at91_set_gpio_input(data->irq_pin, 1); @@ -245,6 +271,9 @@ void __init at91_add_device_cf(struct at91_cf_data *data) at91_set_A_periph(AT91_PIN_PC11, 0); /* NCS5/CFCE1 */ at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */ + /* nWAIT is _not_ a default setting */ + at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */ + cf_data = *data; platform_device_register(&at91rm9200_cf_device); } @@ -257,11 +286,11 @@ void __init at91_add_device_cf(struct at91_cf_data *data) {} * MMC / SD * -------------------------------------------------------------------- */ -#if defined(CONFIG_MMC_AT91RM9200) || defined(CONFIG_MMC_AT91RM9200_MODULE) +#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) static u64 mmc_dmamask = 0xffffffffUL; static struct at91_mmc_data mmc_data; -static struct resource at91_mmc_resources[] = { +static struct resource mmc_resources[] = { [0] = { .start = AT91RM9200_BASE_MCI, .end = AT91RM9200_BASE_MCI + SZ_16K - 1, @@ -282,8 +311,8 @@ static struct platform_device at91rm9200_mmc_device = { .coherent_dma_mask = 0xffffffff, .platform_data = &mmc_data, }, - .resource = at91_mmc_resources, - .num_resources = ARRAY_SIZE(at91_mmc_resources), + .resource = mmc_resources, + .num_resources = ARRAY_SIZE(mmc_resources), }; void __init at91_add_device_mmc(struct at91_mmc_data *data) @@ -298,31 +327,33 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data) } if (data->wp_pin) at91_set_gpio_input(data->wp_pin, 1); + if (data->vcc_pin) + at91_set_gpio_output(data->vcc_pin, 0); /* CLK */ at91_set_A_periph(AT91_PIN_PA27, 0); - if (data->is_b) { + if (data->slot_b) { /* CMD */ - at91_set_B_periph(AT91_PIN_PA8, 0); + at91_set_B_periph(AT91_PIN_PA8, 1); /* DAT0, maybe DAT1..DAT3 */ - at91_set_B_periph(AT91_PIN_PA9, 0); + at91_set_B_periph(AT91_PIN_PA9, 1); if (data->wire4) { - at91_set_B_periph(AT91_PIN_PA10, 0); - at91_set_B_periph(AT91_PIN_PA11, 0); - at91_set_B_periph(AT91_PIN_PA12, 0); + at91_set_B_periph(AT91_PIN_PA10, 1); + at91_set_B_periph(AT91_PIN_PA11, 1); + at91_set_B_periph(AT91_PIN_PA12, 1); } } else { /* CMD */ - at91_set_A_periph(AT91_PIN_PA28, 0); + at91_set_A_periph(AT91_PIN_PA28, 1); /* DAT0, maybe DAT1..DAT3 */ - at91_set_A_periph(AT91_PIN_PA29, 0); + at91_set_A_periph(AT91_PIN_PA29, 1); if (data->wire4) { - at91_set_B_periph(AT91_PIN_PB3, 0); - at91_set_B_periph(AT91_PIN_PB4, 0); - at91_set_B_periph(AT91_PIN_PB5, 0); + at91_set_B_periph(AT91_PIN_PB3, 1); + at91_set_B_periph(AT91_PIN_PB4, 1); + at91_set_B_periph(AT91_PIN_PB5, 1); } } @@ -341,29 +372,45 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data) {} #if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) static struct at91_nand_data nand_data; -static struct resource at91_nand_resources[] = { +#define NAND_BASE AT91_CHIPSELECT_3 + +static struct resource nand_resources[] = { { - .start = AT91_SMARTMEDIA_BASE, - .end = AT91_SMARTMEDIA_BASE + SZ_8M - 1, + .start = NAND_BASE, + .end = NAND_BASE + SZ_8M - 1, .flags = IORESOURCE_MEM, } }; -static struct platform_device at91_nand_device = { +static struct platform_device at91rm9200_nand_device = { .name = "at91_nand", .id = -1, .dev = { .platform_data = &nand_data, }, - .resource = at91_nand_resources, - .num_resources = ARRAY_SIZE(at91_nand_resources), + .resource = nand_resources, + .num_resources = ARRAY_SIZE(nand_resources), }; void __init at91_add_device_nand(struct at91_nand_data *data) { + unsigned int csa; + if (!data) return; + /* enable the address range of CS3 */ + csa = at91_sys_read(AT91_EBI_CSA); + at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS3A_SMC_SMARTMEDIA); + + /* set the bus interface characteristics */ + at91_sys_write(AT91_SMC_CSR(3), AT91_SMC_ACSS_STD | AT91_SMC_DBW_8 | AT91_SMC_WSEN + | AT91_SMC_NWS_(5) + | AT91_SMC_TDF_(1) + | AT91_SMC_RWSETUP_(0) /* tDS Data Set up Time 30 - ns */ + | AT91_SMC_RWHOLD_(1) /* tDH Data Hold Time 20 - ns */ + ); + /* enable pin */ if (data->enable_pin) at91_set_gpio_output(data->enable_pin, 1); @@ -380,7 +427,7 @@ void __init at91_add_device_nand(struct at91_nand_data *data) at91_set_A_periph(AT91_PIN_PC3, 0); /* SMWE */ nand_data = *data; - platform_device_register(&at91_nand_device); + platform_device_register(&at91rm9200_nand_device); } #else void __init at91_add_device_nand(struct at91_nand_data *data) {} @@ -392,10 +439,25 @@ void __init at91_add_device_nand(struct at91_nand_data *data) {} * -------------------------------------------------------------------- */ #if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) + +static struct resource twi_resources[] = { + [0] = { + .start = AT91RM9200_BASE_TWI, + .end = AT91RM9200_BASE_TWI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_TWI, + .end = AT91RM9200_ID_TWI, + .flags = IORESOURCE_IRQ, + }, +}; + static struct platform_device at91rm9200_twi_device = { .name = "at91_i2c", .id = -1, - .num_resources = 0, + .resource = twi_resources, + .num_resources = ARRAY_SIZE(twi_resources), }; void __init at91_add_device_i2c(void) @@ -421,7 +483,7 @@ void __init at91_add_device_i2c(void) {} #if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE) static u64 spi_dmamask = 0xffffffffUL; -static struct resource at91_spi_resources[] = { +static struct resource spi_resources[] = { [0] = { .start = AT91RM9200_BASE_SPI, .end = AT91RM9200_BASE_SPI + SZ_16K - 1, @@ -438,14 +500,14 @@ static struct platform_device at91rm9200_spi_device = { .name = "at91_spi", .id = 0, .dev = { - .dma_mask = &spi_dmamask, - .coherent_dma_mask = 0xffffffff, + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, }, - .resource = at91_spi_resources, - .num_resources = ARRAY_SIZE(at91_spi_resources), + .resource = spi_resources, + .num_resources = ARRAY_SIZE(spi_resources), }; -static const unsigned at91_spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; +static const unsigned spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) { @@ -461,7 +523,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) if (devices[i].controller_data) cs_pin = (unsigned long) devices[i].controller_data; else - cs_pin = at91_spi_standard_cs[devices[i].chip_select]; + cs_pin = spi_standard_cs[devices[i].chip_select]; #ifdef CONFIG_SPI_AT91_MANUAL_CS at91_set_gpio_output(cs_pin, 1); @@ -474,7 +536,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) } spi_register_board_info(devices, nr_devices); - at91_clock_associate("spi0_clk", &at91rm9200_spi_device.dev, "spi"); + at91_clock_associate("spi_clk", &at91rm9200_spi_device.dev, "spi"); platform_device_register(&at91rm9200_spi_device); } #else @@ -486,7 +548,7 @@ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) * RTC * -------------------------------------------------------------------- */ -#if defined(CONFIG_RTC_DRV_AT91) || defined(CONFIG_RTC_DRV_AT91_MODULE) +#if defined(CONFIG_RTC_DRV_AT91RM9200) || defined(CONFIG_RTC_DRV_AT91RM9200_MODULE) static struct platform_device at91rm9200_rtc_device = { .name = "at91_rtc", .id = -1, @@ -506,7 +568,7 @@ static void __init at91_add_device_rtc(void) {} * Watchdog * -------------------------------------------------------------------- */ -#if defined(CONFIG_AT91_WATCHDOG) || defined(CONFIG_AT91_WATCHDOG_MODULE) +#if defined(CONFIG_AT91RM9200_WATCHDOG) || defined(CONFIG_AT91RM9200_WATCHDOG_MODULE) static struct platform_device at91rm9200_wdt_device = { .name = "at91_wdt", .id = -1, diff --git a/arch/arm/mach-at91rm9200/at91rm9200_time.c b/arch/arm/mach-at91rm9200/at91rm9200_time.c index 07c9cea8961d..b999e192a7e9 100644 --- a/arch/arm/mach-at91rm9200/at91rm9200_time.c +++ b/arch/arm/mach-at91rm9200/at91rm9200_time.c @@ -30,6 +30,8 @@ #include <asm/io.h> #include <asm/mach/time.h> +#include <asm/arch/at91_st.h> + static unsigned long last_crtr; /* @@ -99,6 +101,9 @@ void at91rm9200_timer_reset(void) /* Set Period Interval timer */ at91_sys_write(AT91_ST_PIMR, LATCH); + /* Clear any pending interrupts */ + (void) at91_sys_read(AT91_ST_SR); + /* Enable Period Interval Timer interrupt */ at91_sys_write(AT91_ST_IER, AT91_ST_PITS); } diff --git a/arch/arm/mach-at91rm9200/at91sam9260.c b/arch/arm/mach-at91rm9200/at91sam9260.c new file mode 100644 index 000000000000..203f073a53e6 --- /dev/null +++ b/arch/arm/mach-at91rm9200/at91sam9260.c @@ -0,0 +1,294 @@ +/* + * arch/arm/mach-at91rm9200/at91sam9260.c + * + * Copyright (C) 2006 SAN People + * + * 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. + * + */ + +#include <linux/module.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/arch/at91sam9260.h> +#include <asm/arch/at91_pmc.h> + +#include "generic.h" +#include "clock.h" + +static struct map_desc at91sam9260_io_desc[] __initdata = { + { + .virtual = AT91_VA_BASE_SYS, + .pfn = __phys_to_pfn(AT91_BASE_SYS), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE, + .pfn = __phys_to_pfn(AT91SAM9260_SRAM0_BASE), + .length = AT91SAM9260_SRAM0_SIZE, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT91SAM9260_SRAM0_SIZE - AT91SAM9260_SRAM1_SIZE, + .pfn = __phys_to_pfn(AT91SAM9260_SRAM1_BASE), + .length = AT91SAM9260_SRAM1_SIZE, + .type = MT_DEVICE, + }, +}; + +/* -------------------------------------------------------------------- + * Clocks + * -------------------------------------------------------------------- */ + +/* + * The peripheral clocks. + */ +static struct clk pioA_clk = { + .name = "pioA_clk", + .pmc_mask = 1 << AT91SAM9260_ID_PIOA, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioB_clk = { + .name = "pioB_clk", + .pmc_mask = 1 << AT91SAM9260_ID_PIOB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioC_clk = { + .name = "pioC_clk", + .pmc_mask = 1 << AT91SAM9260_ID_PIOC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk adc_clk = { + .name = "adc_clk", + .pmc_mask = 1 << AT91SAM9260_ID_ADC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart0_clk = { + .name = "usart0_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart1_clk = { + .name = "usart1_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart2_clk = { + .name = "usart2_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc_clk = { + .name = "mci_clk", + .pmc_mask = 1 << AT91SAM9260_ID_MCI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk udc_clk = { + .name = "udc_clk", + .pmc_mask = 1 << AT91SAM9260_ID_UDP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi_clk = { + .name = "twi_clk", + .pmc_mask = 1 << AT91SAM9260_ID_TWI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi0_clk = { + .name = "spi0_clk", + .pmc_mask = 1 << AT91SAM9260_ID_SPI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi1_clk = { + .name = "spi1_clk", + .pmc_mask = 1 << AT91SAM9260_ID_SPI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ohci_clk = { + .name = "ohci_clk", + .pmc_mask = 1 << AT91SAM9260_ID_UHP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ether_clk = { + .name = "ether_clk", + .pmc_mask = 1 << AT91SAM9260_ID_EMAC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk isi_clk = { + .name = "isi_clk", + .pmc_mask = 1 << AT91SAM9260_ID_ISI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart3_clk = { + .name = "usart3_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US3, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart4_clk = { + .name = "usart4_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US4, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart5_clk = { + .name = "usart5_clk", + .pmc_mask = 1 << AT91SAM9260_ID_US5, + .type = CLK_TYPE_PERIPHERAL, +}; + +static struct clk *periph_clocks[] __initdata = { + &pioA_clk, + &pioB_clk, + &pioC_clk, + &adc_clk, + &usart0_clk, + &usart1_clk, + &usart2_clk, + &mmc_clk, + &udc_clk, + &twi_clk, + &spi0_clk, + &spi1_clk, + // ssc + // tc0 .. tc2 + &ohci_clk, + ðer_clk, + &isi_clk, + &usart3_clk, + &usart4_clk, + &usart5_clk, + // tc3 .. tc5 + // irq0 .. irq2 +}; + +/* + * The two programmable clocks. + * You must configure pin multiplexing to bring these signals out. + */ +static struct clk pck0 = { + .name = "pck0", + .pmc_mask = AT91_PMC_PCK0, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 0, +}; +static struct clk pck1 = { + .name = "pck1", + .pmc_mask = AT91_PMC_PCK1, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 1, +}; + +static void __init at91sam9260_register_clocks(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) + clk_register(periph_clocks[i]); + + clk_register(&pck0); + clk_register(&pck1); +} + +/* -------------------------------------------------------------------- + * GPIO + * -------------------------------------------------------------------- */ + +static struct at91_gpio_bank at91sam9260_gpio[] = { + { + .id = AT91SAM9260_ID_PIOA, + .offset = AT91_PIOA, + .clock = &pioA_clk, + }, { + .id = AT91SAM9260_ID_PIOB, + .offset = AT91_PIOB, + .clock = &pioB_clk, + }, { + .id = AT91SAM9260_ID_PIOC, + .offset = AT91_PIOC, + .clock = &pioC_clk, + } +}; + +static void at91sam9260_reset(void) +{ +#warning "Implement CPU reset" +} + + +/* -------------------------------------------------------------------- + * AT91SAM9260 processor initialization + * -------------------------------------------------------------------- */ + +void __init at91sam9260_initialize(unsigned long main_clock) +{ + /* Map peripherals */ + iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc)); + + at91_arch_reset = at91sam9260_reset; + at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1) + | (1 << AT91SAM9260_ID_IRQ2); + + /* Init clock subsystem */ + at91_clock_init(main_clock); + + /* Register the processor-specific clocks */ + at91sam9260_register_clocks(); + + /* Register GPIO subsystem */ + at91_gpio_init(at91sam9260_gpio, 3); +} + +/* -------------------------------------------------------------------- + * Interrupt initialization + * -------------------------------------------------------------------- */ + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at91sam9260_default_irq_priority[NR_AIC_IRQS] __initdata = { + 7, /* Advanced Interrupt Controller */ + 7, /* System Peripherals */ + 0, /* Parallel IO Controller A */ + 0, /* Parallel IO Controller B */ + 0, /* Parallel IO Controller C */ + 0, /* Analog-to-Digital Converter */ + 6, /* USART 0 */ + 6, /* USART 1 */ + 6, /* USART 2 */ + 0, /* Multimedia Card Interface */ + 4, /* USB Device Port */ + 0, /* Two-Wire Interface */ + 6, /* Serial Peripheral Interface 0 */ + 6, /* Serial Peripheral Interface 1 */ + 5, /* Serial Synchronous Controller */ + 0, + 0, + 0, /* Timer Counter 0 */ + 0, /* Timer Counter 1 */ + 0, /* Timer Counter 2 */ + 3, /* USB Host port */ + 3, /* Ethernet */ + 0, /* Image Sensor Interface */ + 6, /* USART 3 */ + 6, /* USART 4 */ + 6, /* USART 5 */ + 0, /* Timer Counter 3 */ + 0, /* Timer Counter 4 */ + 0, /* Timer Counter 5 */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ +}; + +void __init at91sam9260_init_interrupts(unsigned int priority[NR_AIC_IRQS]) +{ + if (!priority) + priority = at91sam9260_default_irq_priority; + + /* Initialize the AIC interrupt controller */ + at91_aic_init(priority); + + /* Enable GPIO interrupts */ + at91_gpio_irq_setup(); +} diff --git a/arch/arm/mach-at91rm9200/at91sam9260_devices.c b/arch/arm/mach-at91rm9200/at91sam9260_devices.c new file mode 100644 index 000000000000..f42d3a40ec3c --- /dev/null +++ b/arch/arm/mach-at91rm9200/at91sam9260_devices.c @@ -0,0 +1,867 @@ +/* + * arch/arm/mach-at91rm9200/at91sam9260_devices.c + * + * Copyright (C) 2006 Atmel + * + * 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. + * + */ +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <linux/platform_device.h> + +#include <asm/arch/board.h> +#include <asm/arch/gpio.h> +#include <asm/arch/at91sam9260.h> +#include <asm/arch/at91sam926x_mc.h> +#include <asm/arch/at91sam9260_matrix.h> + +#include "generic.h" + +#define SZ_512 0x00000200 +#define SZ_256 0x00000100 +#define SZ_16 0x00000010 + +/* -------------------------------------------------------------------- + * USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static u64 ohci_dmamask = 0xffffffffUL; +static struct at91_usbh_data usbh_data; + +static struct resource usbh_resources[] = { + [0] = { + .start = AT91SAM9260_UHP_BASE, + .end = AT91SAM9260_UHP_BASE + SZ_1M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_UHP, + .end = AT91SAM9260_ID_UHP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91_usbh_device = { + .name = "at91_ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &usbh_data, + }, + .resource = usbh_resources, + .num_resources = ARRAY_SIZE(usbh_resources), +}; + +void __init at91_add_device_usbh(struct at91_usbh_data *data) +{ + if (!data) + return; + + usbh_data = *data; + platform_device_register(&at91_usbh_device); +} +#else +void __init at91_add_device_usbh(struct at91_usbh_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * USB Device (Gadget) + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_USB_GADGET_AT91 +static struct at91_udc_data udc_data; + +static struct resource udc_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_UDP, + .end = AT91SAM9260_BASE_UDP + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_UDP, + .end = AT91SAM9260_ID_UDP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91_udc_device = { + .name = "at91_udc", + .id = -1, + .dev = { + .platform_data = &udc_data, + }, + .resource = udc_resources, + .num_resources = ARRAY_SIZE(udc_resources), +}; + +void __init at91_add_device_udc(struct at91_udc_data *data) +{ + if (!data) + return; + + if (data->vbus_pin) { + at91_set_gpio_input(data->vbus_pin, 0); + at91_set_deglitch(data->vbus_pin, 1); + } + + /* Pullup pin is handled internally by USB device peripheral */ + + udc_data = *data; + platform_device_register(&at91_udc_device); +} +#else +void __init at91_add_device_udc(struct at91_udc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * Ethernet + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MACB) || defined(CONFIG_MACB_MODULE) +static u64 eth_dmamask = 0xffffffffUL; +static struct eth_platform_data eth_data; + +static struct resource eth_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_EMAC, + .end = AT91SAM9260_BASE_EMAC + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_EMAC, + .end = AT91SAM9260_ID_EMAC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_eth_device = { + .name = "macb", + .id = -1, + .dev = { + .dma_mask = ð_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = ð_data, + }, + .resource = eth_resources, + .num_resources = ARRAY_SIZE(eth_resources), +}; + +void __init at91_add_device_eth(struct eth_platform_data *data) +{ + if (!data) + return; + + if (data->phy_irq_pin) { + at91_set_gpio_input(data->phy_irq_pin, 0); + at91_set_deglitch(data->phy_irq_pin, 1); + } + + /* Pins used for MII and RMII */ + at91_set_A_periph(AT91_PIN_PA19, 0); /* ETXCK_EREFCK */ + at91_set_A_periph(AT91_PIN_PA17, 0); /* ERXDV */ + at91_set_A_periph(AT91_PIN_PA14, 0); /* ERX0 */ + at91_set_A_periph(AT91_PIN_PA15, 0); /* ERX1 */ + at91_set_A_periph(AT91_PIN_PA18, 0); /* ERXER */ + at91_set_A_periph(AT91_PIN_PA16, 0); /* ETXEN */ + at91_set_A_periph(AT91_PIN_PA12, 0); /* ETX0 */ + at91_set_A_periph(AT91_PIN_PA13, 0); /* ETX1 */ + at91_set_A_periph(AT91_PIN_PA21, 0); /* EMDIO */ + at91_set_A_periph(AT91_PIN_PA20, 0); /* EMDC */ + + if (!data->is_rmii) { + at91_set_B_periph(AT91_PIN_PA28, 0); /* ECRS */ + at91_set_B_periph(AT91_PIN_PA29, 0); /* ECOL */ + at91_set_B_periph(AT91_PIN_PA25, 0); /* ERX2 */ + at91_set_B_periph(AT91_PIN_PA26, 0); /* ERX3 */ + at91_set_B_periph(AT91_PIN_PA27, 0); /* ERXCK */ + at91_set_B_periph(AT91_PIN_PA23, 0); /* ETX2 */ + at91_set_B_periph(AT91_PIN_PA24, 0); /* ETX3 */ + at91_set_B_periph(AT91_PIN_PA22, 0); /* ETXER */ + } + + eth_data = *data; + platform_device_register(&at91sam9260_eth_device); +} +#else +void __init at91_add_device_eth(struct eth_platform_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * MMC / SD + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) +static u64 mmc_dmamask = 0xffffffffUL; +static struct at91_mmc_data mmc_data; + +static struct resource mmc_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_MCI, + .end = AT91SAM9260_BASE_MCI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_MCI, + .end = AT91SAM9260_ID_MCI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_mmc_device = { + .name = "at91_mci", + .id = -1, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &mmc_data, + }, + .resource = mmc_resources, + .num_resources = ARRAY_SIZE(mmc_resources), +}; + +void __init at91_add_device_mmc(struct at91_mmc_data *data) +{ + if (!data) + return; + + /* input/irq */ + if (data->det_pin) { + at91_set_gpio_input(data->det_pin, 1); + at91_set_deglitch(data->det_pin, 1); + } + if (data->wp_pin) + at91_set_gpio_input(data->wp_pin, 1); + if (data->vcc_pin) + at91_set_gpio_output(data->vcc_pin, 0); + + /* CLK */ + at91_set_A_periph(AT91_PIN_PA8, 0); + + if (data->slot_b) { + /* CMD */ + at91_set_B_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_B_periph(AT91_PIN_PA0, 1); + if (data->wire4) { + at91_set_B_periph(AT91_PIN_PA5, 1); + at91_set_B_periph(AT91_PIN_PA4, 1); + at91_set_B_periph(AT91_PIN_PA3, 1); + } + } else { + /* CMD */ + at91_set_A_periph(AT91_PIN_PA7, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA6, 1); + if (data->wire4) { + at91_set_A_periph(AT91_PIN_PA9, 1); + at91_set_A_periph(AT91_PIN_PA10, 1); + at91_set_A_periph(AT91_PIN_PA11, 1); + } + } + + mmc_data = *data; + platform_device_register(&at91sam9260_mmc_device); +} +#else +void __init at91_add_device_mmc(struct at91_mmc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * NAND / SmartMedia + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) +static struct at91_nand_data nand_data; + +#define NAND_BASE AT91_CHIPSELECT_3 + +static struct resource nand_resources[] = { + { + .start = NAND_BASE, + .end = NAND_BASE + SZ_8M - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91sam9260_nand_device = { + .name = "at91_nand", + .id = -1, + .dev = { + .platform_data = &nand_data, + }, + .resource = nand_resources, + .num_resources = ARRAY_SIZE(nand_resources), +}; + +void __init at91_add_device_nand(struct at91_nand_data *data) +{ + unsigned long csa, mode; + + if (!data) + return; + + csa = at91_sys_read(AT91_MATRIX_EBICSA); + at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC); + + /* set the bus interface characteristics */ + at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0) + | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0)); + + at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(2) | AT91_SMC_NCS_WRPULSE_(5) + | AT91_SMC_NRDPULSE_(2) | AT91_SMC_NCS_RDPULSE_(5)); + + at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7)); + + if (data->bus_width_16) + mode = AT91_SMC_DBW_16; + else + mode = AT91_SMC_DBW_8; + at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1)); + + /* enable pin */ + if (data->enable_pin) + at91_set_gpio_output(data->enable_pin, 1); + + /* ready/busy pin */ + if (data->rdy_pin) + at91_set_gpio_input(data->rdy_pin, 1); + + /* card detect pin */ + if (data->det_pin) + at91_set_gpio_input(data->det_pin, 1); + + nand_data = *data; + platform_device_register(&at91sam9260_nand_device); +} +#else +void __init at91_add_device_nand(struct at91_nand_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * TWI (i2c) + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) + +static struct resource twi_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_TWI, + .end = AT91SAM9260_BASE_TWI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_TWI, + .end = AT91SAM9260_ID_TWI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_twi_device = { + .name = "at91_i2c", + .id = -1, + .resource = twi_resources, + .num_resources = ARRAY_SIZE(twi_resources), +}; + +void __init at91_add_device_i2c(void) +{ + /* pins used for TWI interface */ + at91_set_A_periph(AT91_PIN_PA23, 0); /* TWD */ + at91_set_multi_drive(AT91_PIN_PA23, 1); + + at91_set_A_periph(AT91_PIN_PA24, 0); /* TWCK */ + at91_set_multi_drive(AT91_PIN_PA24, 1); + + platform_device_register(&at91sam9260_twi_device); +} +#else +void __init at91_add_device_i2c(void) {} +#endif + + +/* -------------------------------------------------------------------- + * SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) +static u64 spi_dmamask = 0xffffffffUL; + +static struct resource spi0_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_SPI0, + .end = AT91SAM9260_BASE_SPI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_SPI0, + .end = AT91SAM9260_ID_SPI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_spi0_device = { + .name = "atmel_spi", + .id = 0, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi0_resources, + .num_resources = ARRAY_SIZE(spi0_resources), +}; + +static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PC11, AT91_PIN_PC16, AT91_PIN_PC17 }; + +static struct resource spi1_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_SPI1, + .end = AT91SAM9260_BASE_SPI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_SPI1, + .end = AT91SAM9260_ID_SPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9260_spi1_device = { + .name = "atmel_spi", + .id = 1, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi1_resources, + .num_resources = ARRAY_SIZE(spi1_resources), +}; + +static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB3, AT91_PIN_PC5, AT91_PIN_PC4, AT91_PIN_PC3 }; + +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) +{ + int i; + unsigned long cs_pin; + short enable_spi0 = 0; + short enable_spi1 = 0; + + /* Choose SPI chip-selects */ + for (i = 0; i < nr_devices; i++) { + if (devices[i].controller_data) + cs_pin = (unsigned long) devices[i].controller_data; + else if (devices[i].bus_num == 0) + cs_pin = spi0_standard_cs[devices[i].chip_select]; + else + cs_pin = spi1_standard_cs[devices[i].chip_select]; + + if (devices[i].bus_num == 0) + enable_spi0 = 1; + else + enable_spi1 = 1; + + /* enable chip-select pin */ + at91_set_gpio_output(cs_pin, 1); + + /* pass chip-select pin to driver */ + devices[i].controller_data = (void *) cs_pin; + } + + spi_register_board_info(devices, nr_devices); + + /* Configure SPI bus(es) */ + if (enable_spi0) { + at91_set_A_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */ + at91_set_A_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */ + at91_set_A_periph(AT91_PIN_PA2, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi0_clk", &at91sam9260_spi0_device.dev, "spi_clk"); + platform_device_register(&at91sam9260_spi0_device); + } + if (enable_spi1) { + at91_set_A_periph(AT91_PIN_PB0, 0); /* SPI1_MISO */ + at91_set_A_periph(AT91_PIN_PB1, 0); /* SPI1_MOSI */ + at91_set_A_periph(AT91_PIN_PB2, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi1_clk", &at91sam9260_spi1_device.dev, "spi_clk"); + platform_device_register(&at91sam9260_spi1_device); + } +} +#else +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + * LEDs + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_LEDS) +u8 at91_leds_cpu; +u8 at91_leds_timer; + +void __init at91_init_leds(u8 cpu_led, u8 timer_led) +{ + at91_leds_cpu = cpu_led; + at91_leds_timer = timer_led; +} +#else +void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} +#endif + + +/* -------------------------------------------------------------------- + * UART + * -------------------------------------------------------------------- */ +#if defined(CONFIG_SERIAL_ATMEL) +static struct resource dbgu_resources[] = { + [0] = { + .start = AT91_VA_BASE_SYS + AT91_DBGU, + .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_SYS, + .end = AT91_ID_SYS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data dbgu_data = { + .use_dma_tx = 0, + .use_dma_rx = 0, /* DBGU not capable of receive DMA */ + .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), +}; + +static struct platform_device at91sam9260_dbgu_device = { + .name = "atmel_usart", + .id = 0, + .dev = { + .platform_data = &dbgu_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = dbgu_resources, + .num_resources = ARRAY_SIZE(dbgu_resources), +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB14, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PB15, 1); /* DTXD */ +} + +static struct resource uart0_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US0, + .end = AT91SAM9260_BASE_US0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US0, + .end = AT91SAM9260_ID_US0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart0_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart0_device = { + .name = "atmel_usart", + .id = 1, + .dev = { + .platform_data = &uart0_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart0_resources, + .num_resources = ARRAY_SIZE(uart0_resources), +}; + +static inline void configure_usart0_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB4, 1); /* TXD0 */ + at91_set_A_periph(AT91_PIN_PB5, 0); /* RXD0 */ + at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS0 */ + at91_set_A_periph(AT91_PIN_PB27, 0); /* CTS0 */ + at91_set_A_periph(AT91_PIN_PB24, 0); /* DTR0 */ + at91_set_A_periph(AT91_PIN_PB22, 0); /* DSR0 */ + at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD0 */ + at91_set_A_periph(AT91_PIN_PB25, 0); /* RI0 */ +} + +static struct resource uart1_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US1, + .end = AT91SAM9260_BASE_US1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US1, + .end = AT91SAM9260_ID_US1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart1_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart1_device = { + .name = "atmel_usart", + .id = 2, + .dev = { + .platform_data = &uart1_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart1_resources, + .num_resources = ARRAY_SIZE(uart1_resources), +}; + +static inline void configure_usart1_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB6, 1); /* TXD1 */ + at91_set_A_periph(AT91_PIN_PB7, 0); /* RXD1 */ + at91_set_A_periph(AT91_PIN_PB28, 0); /* RTS1 */ + at91_set_A_periph(AT91_PIN_PB29, 0); /* CTS1 */ +} + +static struct resource uart2_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US2, + .end = AT91SAM9260_BASE_US2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US2, + .end = AT91SAM9260_ID_US2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart2_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart2_device = { + .name = "atmel_usart", + .id = 3, + .dev = { + .platform_data = &uart2_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart2_resources, + .num_resources = ARRAY_SIZE(uart2_resources), +}; + +static inline void configure_usart2_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB8, 1); /* TXD2 */ + at91_set_A_periph(AT91_PIN_PB9, 0); /* RXD2 */ +} + +static struct resource uart3_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US3, + .end = AT91SAM9260_BASE_US3 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US3, + .end = AT91SAM9260_ID_US3, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart3_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart3_device = { + .name = "atmel_usart", + .id = 4, + .dev = { + .platform_data = &uart3_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart3_resources, + .num_resources = ARRAY_SIZE(uart3_resources), +}; + +static inline void configure_usart3_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB10, 1); /* TXD3 */ + at91_set_A_periph(AT91_PIN_PB11, 0); /* RXD3 */ +} + +static struct resource uart4_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US4, + .end = AT91SAM9260_BASE_US4 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US4, + .end = AT91SAM9260_ID_US4, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart4_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart4_device = { + .name = "atmel_usart", + .id = 5, + .dev = { + .platform_data = &uart4_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart4_resources, + .num_resources = ARRAY_SIZE(uart4_resources), +}; + +static inline void configure_usart4_pins(void) +{ + at91_set_B_periph(AT91_PIN_PA31, 1); /* TXD4 */ + at91_set_B_periph(AT91_PIN_PA30, 0); /* RXD4 */ +} + +static struct resource uart5_resources[] = { + [0] = { + .start = AT91SAM9260_BASE_US5, + .end = AT91SAM9260_BASE_US5 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9260_ID_US5, + .end = AT91SAM9260_ID_US5, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart5_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9260_uart5_device = { + .name = "atmel_usart", + .id = 6, + .dev = { + .platform_data = &uart5_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart5_resources, + .num_resources = ARRAY_SIZE(uart5_resources), +}; + +static inline void configure_usart5_pins(void) +{ + at91_set_A_periph(AT91_PIN_PB12, 1); /* TXD5 */ + at91_set_A_periph(AT91_PIN_PB13, 0); /* RXD5 */ +} + +struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ +struct platform_device *atmel_default_console_device; /* the serial console device */ + +void __init at91_init_serial(struct at91_uart_config *config) +{ + int i; + + /* Fill in list of supported UARTs */ + for (i = 0; i < config->nr_tty; i++) { + switch (config->tty_map[i]) { + case 0: + configure_usart0_pins(); + at91_uarts[i] = &at91sam9260_uart0_device; + at91_clock_associate("usart0_clk", &at91sam9260_uart0_device.dev, "usart"); + break; + case 1: + configure_usart1_pins(); + at91_uarts[i] = &at91sam9260_uart1_device; + at91_clock_associate("usart1_clk", &at91sam9260_uart1_device.dev, "usart"); + break; + case 2: + configure_usart2_pins(); + at91_uarts[i] = &at91sam9260_uart2_device; + at91_clock_associate("usart2_clk", &at91sam9260_uart2_device.dev, "usart"); + break; + case 3: + configure_usart3_pins(); + at91_uarts[i] = &at91sam9260_uart3_device; + at91_clock_associate("usart3_clk", &at91sam9260_uart3_device.dev, "usart"); + break; + case 4: + configure_usart4_pins(); + at91_uarts[i] = &at91sam9260_uart4_device; + at91_clock_associate("usart4_clk", &at91sam9260_uart4_device.dev, "usart"); + break; + case 5: + configure_usart5_pins(); + at91_uarts[i] = &at91sam9260_uart5_device; + at91_clock_associate("usart5_clk", &at91sam9260_uart5_device.dev, "usart"); + break; + case 6: + configure_dbgu_pins(); + at91_uarts[i] = &at91sam9260_dbgu_device; + at91_clock_associate("mck", &at91sam9260_dbgu_device.dev, "usart"); + break; + default: + continue; + } + at91_uarts[i]->id = i; /* update ID number to mapped ID */ + } + + /* Set serial console device */ + if (config->console_tty < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[config->console_tty]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + +void __init at91_add_device_serial(void) +{ + int i; + + for (i = 0; i < ATMEL_MAX_UART; i++) { + if (at91_uarts[i]) + platform_device_register(at91_uarts[i]); + } +} +#else +void __init at91_init_serial(struct at91_uart_config *config) {} +void __init at91_add_device_serial(void) {} +#endif + + +/* -------------------------------------------------------------------- */ +/* + * These devices are always present and don't need any board-specific + * setup. + */ +static int __init at91_add_standard_devices(void) +{ + return 0; +} + +arch_initcall(at91_add_standard_devices); diff --git a/arch/arm/mach-at91rm9200/at91sam9261.c b/arch/arm/mach-at91rm9200/at91sam9261.c new file mode 100644 index 000000000000..5a82f35da2e9 --- /dev/null +++ b/arch/arm/mach-at91rm9200/at91sam9261.c @@ -0,0 +1,289 @@ +/* + * arch/arm/mach-at91rm9200/at91sam9261.c + * + * Copyright (C) 2005 SAN People + * + * 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. + * + */ + +#include <linux/module.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/arch/at91sam9261.h> +#include <asm/arch/at91_pmc.h> + +#include "generic.h" +#include "clock.h" + +static struct map_desc at91sam9261_io_desc[] __initdata = { + { + .virtual = AT91_VA_BASE_SYS, + .pfn = __phys_to_pfn(AT91_BASE_SYS), + .length = SZ_16K, + .type = MT_DEVICE, + }, { + .virtual = AT91_IO_VIRT_BASE - AT91SAM9261_SRAM_SIZE, + .pfn = __phys_to_pfn(AT91SAM9261_SRAM_BASE), + .length = AT91SAM9261_SRAM_SIZE, + .type = MT_DEVICE, + }, +}; + +/* -------------------------------------------------------------------- + * Clocks + * -------------------------------------------------------------------- */ + +/* + * The peripheral clocks. + */ +static struct clk pioA_clk = { + .name = "pioA_clk", + .pmc_mask = 1 << AT91SAM9261_ID_PIOA, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioB_clk = { + .name = "pioB_clk", + .pmc_mask = 1 << AT91SAM9261_ID_PIOB, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk pioC_clk = { + .name = "pioC_clk", + .pmc_mask = 1 << AT91SAM9261_ID_PIOC, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart0_clk = { + .name = "usart0_clk", + .pmc_mask = 1 << AT91SAM9261_ID_US0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart1_clk = { + .name = "usart1_clk", + .pmc_mask = 1 << AT91SAM9261_ID_US1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk usart2_clk = { + .name = "usart2_clk", + .pmc_mask = 1 << AT91SAM9261_ID_US2, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk mmc_clk = { + .name = "mci_clk", + .pmc_mask = 1 << AT91SAM9261_ID_MCI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk udc_clk = { + .name = "udc_clk", + .pmc_mask = 1 << AT91SAM9261_ID_UDP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk twi_clk = { + .name = "twi_clk", + .pmc_mask = 1 << AT91SAM9261_ID_TWI, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi0_clk = { + .name = "spi0_clk", + .pmc_mask = 1 << AT91SAM9261_ID_SPI0, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk spi1_clk = { + .name = "spi1_clk", + .pmc_mask = 1 << AT91SAM9261_ID_SPI1, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk ohci_clk = { + .name = "ohci_clk", + .pmc_mask = 1 << AT91SAM9261_ID_UHP, + .type = CLK_TYPE_PERIPHERAL, +}; +static struct clk lcdc_clk = { + .name = "lcdc_clk", + .pmc_mask = 1 << AT91SAM9261_ID_LCDC, + .type = CLK_TYPE_PERIPHERAL, +}; + +static struct clk *periph_clocks[] __initdata = { + &pioA_clk, + &pioB_clk, + &pioC_clk, + &usart0_clk, + &usart1_clk, + &usart2_clk, + &mmc_clk, + &udc_clk, + &twi_clk, + &spi0_clk, + &spi1_clk, + // ssc 0 .. ssc2 + // tc0 .. tc2 + &ohci_clk, + &lcdc_clk, + // irq0 .. irq2 +}; + +/* + * The four programmable clocks. + * You must configure pin multiplexing to bring these signals out. + */ +static struct clk pck0 = { + .name = "pck0", + .pmc_mask = AT91_PMC_PCK0, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 0, +}; +static struct clk pck1 = { + .name = "pck1", + .pmc_mask = AT91_PMC_PCK1, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 1, +}; +static struct clk pck2 = { + .name = "pck2", + .pmc_mask = AT91_PMC_PCK2, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 2, +}; +static struct clk pck3 = { + .name = "pck3", + .pmc_mask = AT91_PMC_PCK3, + .type = CLK_TYPE_PROGRAMMABLE, + .id = 3, +}; + +/* HClocks */ +static struct clk hck0 = { + .name = "hck0", + .pmc_mask = AT91_PMC_HCK0, + .type = CLK_TYPE_SYSTEM, + .id = 0, +}; +static struct clk hck1 = { + .name = "hck1", + .pmc_mask = AT91_PMC_HCK1, + .type = CLK_TYPE_SYSTEM, + .id = 1, +}; + +static void __init at91sam9261_register_clocks(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(periph_clocks); i++) + clk_register(periph_clocks[i]); + + clk_register(&pck0); + clk_register(&pck1); + clk_register(&pck2); + clk_register(&pck3); + + clk_register(&hck0); + clk_register(&hck1); +} + +/* -------------------------------------------------------------------- + * GPIO + * -------------------------------------------------------------------- */ + +static struct at91_gpio_bank at91sam9261_gpio[] = { + { + .id = AT91SAM9261_ID_PIOA, + .offset = AT91_PIOA, + .clock = &pioA_clk, + }, { + .id = AT91SAM9261_ID_PIOB, + .offset = AT91_PIOB, + .clock = &pioB_clk, + }, { + .id = AT91SAM9261_ID_PIOC, + .offset = AT91_PIOC, + .clock = &pioC_clk, + } +}; + +static void at91sam9261_reset(void) +{ +#warning "Implement CPU reset" +} + + +/* -------------------------------------------------------------------- + * AT91SAM9261 processor initialization + * -------------------------------------------------------------------- */ + +void __init at91sam9261_initialize(unsigned long main_clock) +{ + /* Map peripherals */ + iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc)); + + at91_arch_reset = at91sam9261_reset; + at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1) + | (1 << AT91SAM9261_ID_IRQ2); + + /* Init clock subsystem */ + at91_clock_init(main_clock); + + /* Register the processor-specific clocks */ + at91sam9261_register_clocks(); + + /* Register GPIO subsystem */ + at91_gpio_init(at91sam9261_gpio, 3); +} + +/* -------------------------------------------------------------------- + * Interrupt initialization + * -------------------------------------------------------------------- */ + +/* + * The default interrupt priority levels (0 = lowest, 7 = highest). + */ +static unsigned int at91sam9261_default_irq_priority[NR_AIC_IRQS] __initdata = { + 7, /* Advanced Interrupt Controller */ + 7, /* System Peripherals */ + 0, /* Parallel IO Controller A */ + 0, /* Parallel IO Controller B */ + 0, /* Parallel IO Controller C */ + 0, + 6, /* USART 0 */ + 6, /* USART 1 */ + 6, /* USART 2 */ + 0, /* Multimedia Card Interface */ + 4, /* USB Device Port */ + 0, /* Two-Wire Interface */ + 6, /* Serial Peripheral Interface 0 */ + 6, /* Serial Peripheral Interface 1 */ + 5, /* Serial Synchronous Controller 0 */ + 5, /* Serial Synchronous Controller 1 */ + 5, /* Serial Synchronous Controller 2 */ + 0, /* Timer Counter 0 */ + 0, /* Timer Counter 1 */ + 0, /* Timer Counter 2 */ + 3, /* USB Host port */ + 3, /* LCD Controller */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ + 0, /* Advanced Interrupt Controller */ +}; + +void __init at91sam9261_init_interrupts(unsigned int priority[NR_AIC_IRQS]) +{ + if (!priority) + priority = at91sam9261_default_irq_priority; + + /* Initialize the AIC interrupt controller */ + at91_aic_init(priority); + + /* Enable GPIO interrupts */ + at91_gpio_irq_setup(); +} diff --git a/arch/arm/mach-at91rm9200/at91sam9261_devices.c b/arch/arm/mach-at91rm9200/at91sam9261_devices.c new file mode 100644 index 000000000000..ed1d79081b35 --- /dev/null +++ b/arch/arm/mach-at91rm9200/at91sam9261_devices.c @@ -0,0 +1,741 @@ +/* + * arch/arm/mach-at91rm9200/at91sam9261_devices.c + * + * Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org> + * Copyright (C) 2005 David Brownell + * + * 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. + * + */ +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <linux/platform_device.h> + +#include <asm/arch/board.h> +#include <asm/arch/gpio.h> +#include <asm/arch/at91sam9261.h> +#include <asm/arch/at91sam9261_matrix.h> +#include <asm/arch/at91sam926x_mc.h> + +#include "generic.h" + +#define SZ_512 0x00000200 +#define SZ_256 0x00000100 +#define SZ_16 0x00000010 + +/* -------------------------------------------------------------------- + * USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static u64 ohci_dmamask = 0xffffffffUL; +static struct at91_usbh_data usbh_data; + +static struct resource usbh_resources[] = { + [0] = { + .start = AT91SAM9261_UHP_BASE, + .end = AT91SAM9261_UHP_BASE + SZ_1M - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_UHP, + .end = AT91SAM9261_ID_UHP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_usbh_device = { + .name = "at91_ohci", + .id = -1, + .dev = { + .dma_mask = &ohci_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &usbh_data, + }, + .resource = usbh_resources, + .num_resources = ARRAY_SIZE(usbh_resources), +}; + +void __init at91_add_device_usbh(struct at91_usbh_data *data) +{ + if (!data) + return; + + usbh_data = *data; + platform_device_register(&at91sam9261_usbh_device); +} +#else +void __init at91_add_device_usbh(struct at91_usbh_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * USB Device (Gadget) + * -------------------------------------------------------------------- */ + +#ifdef CONFIG_USB_GADGET_AT91 +static struct at91_udc_data udc_data; + +static struct resource udc_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_UDP, + .end = AT91SAM9261_BASE_UDP + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_UDP, + .end = AT91SAM9261_ID_UDP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_udc_device = { + .name = "at91_udc", + .id = -1, + .dev = { + .platform_data = &udc_data, + }, + .resource = udc_resources, + .num_resources = ARRAY_SIZE(udc_resources), +}; + +void __init at91_add_device_udc(struct at91_udc_data *data) +{ + unsigned long x; + + if (!data) + return; + + if (data->vbus_pin) { + at91_set_gpio_input(data->vbus_pin, 0); + at91_set_deglitch(data->vbus_pin, 1); + } + + /* Pullup pin is handled internally */ + x = at91_sys_read(AT91_MATRIX_USBPUCR); + at91_sys_write(AT91_MATRIX_USBPUCR, x | AT91_MATRIX_USBPUCR_PUON); + + udc_data = *data; + platform_device_register(&at91sam9261_udc_device); +} +#else +void __init at91_add_device_udc(struct at91_udc_data *data) {} +#endif + +/* -------------------------------------------------------------------- + * MMC / SD + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MMC_AT91) || defined(CONFIG_MMC_AT91_MODULE) +static u64 mmc_dmamask = 0xffffffffUL; +static struct at91_mmc_data mmc_data; + +static struct resource mmc_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_MCI, + .end = AT91SAM9261_BASE_MCI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_MCI, + .end = AT91SAM9261_ID_MCI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_mmc_device = { + .name = "at91_mci", + .id = -1, + .dev = { + .dma_mask = &mmc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &mmc_data, + }, + .resource = mmc_resources, + .num_resources = ARRAY_SIZE(mmc_resources), +}; + +void __init at91_add_device_mmc(struct at91_mmc_data *data) +{ + if (!data) + return; + + /* input/irq */ + if (data->det_pin) { + at91_set_gpio_input(data->det_pin, 1); + at91_set_deglitch(data->det_pin, 1); + } + if (data->wp_pin) + at91_set_gpio_input(data->wp_pin, 1); + if (data->vcc_pin) + at91_set_gpio_output(data->vcc_pin, 0); + + /* CLK */ + at91_set_B_periph(AT91_PIN_PA2, 0); + + /* CMD */ + at91_set_B_periph(AT91_PIN_PA1, 1); + + /* DAT0, maybe DAT1..DAT3 */ + at91_set_B_periph(AT91_PIN_PA0, 1); + if (data->wire4) { + at91_set_B_periph(AT91_PIN_PA4, 1); + at91_set_B_periph(AT91_PIN_PA5, 1); + at91_set_B_periph(AT91_PIN_PA6, 1); + } + + mmc_data = *data; + platform_device_register(&at91sam9261_mmc_device); +} +#else +void __init at91_add_device_mmc(struct at91_mmc_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * NAND / SmartMedia + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_MTD_NAND_AT91) || defined(CONFIG_MTD_NAND_AT91_MODULE) +static struct at91_nand_data nand_data; + +#define NAND_BASE AT91_CHIPSELECT_3 + +static struct resource nand_resources[] = { + { + .start = NAND_BASE, + .end = NAND_BASE + SZ_256M - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91_nand_device = { + .name = "at91_nand", + .id = -1, + .dev = { + .platform_data = &nand_data, + }, + .resource = nand_resources, + .num_resources = ARRAY_SIZE(nand_resources), +}; + +void __init at91_add_device_nand(struct at91_nand_data *data) +{ + unsigned long csa, mode; + + if (!data) + return; + + csa = at91_sys_read(AT91_MATRIX_EBICSA); + at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_CS3A_SMC); + + /* set the bus interface characteristics */ + at91_sys_write(AT91_SMC_SETUP(3), AT91_SMC_NWESETUP_(0) | AT91_SMC_NCS_WRSETUP_(0) + | AT91_SMC_NRDSETUP_(0) | AT91_SMC_NCS_RDSETUP_(0)); + + at91_sys_write(AT91_SMC_PULSE(3), AT91_SMC_NWEPULSE_(2) | AT91_SMC_NCS_WRPULSE_(5) + | AT91_SMC_NRDPULSE_(2) | AT91_SMC_NCS_RDPULSE_(5)); + + at91_sys_write(AT91_SMC_CYCLE(3), AT91_SMC_NWECYCLE_(7) | AT91_SMC_NRDCYCLE_(7)); + + if (data->bus_width_16) + mode = AT91_SMC_DBW_16; + else + mode = AT91_SMC_DBW_8; + at91_sys_write(AT91_SMC_MODE(3), mode | AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_TDF_(1)); + + /* enable pin */ + if (data->enable_pin) + at91_set_gpio_output(data->enable_pin, 1); + + /* ready/busy pin */ + if (data->rdy_pin) + at91_set_gpio_input(data->rdy_pin, 1); + + /* card detect pin */ + if (data->det_pin) + at91_set_gpio_input(data->det_pin, 1); + + at91_set_A_periph(AT91_PIN_PC0, 0); /* NANDOE */ + at91_set_A_periph(AT91_PIN_PC1, 0); /* NANDWE */ + + nand_data = *data; + platform_device_register(&at91_nand_device); +} + +#else +void __init at91_add_device_nand(struct at91_nand_data *data) {} +#endif + + +/* -------------------------------------------------------------------- + * TWI (i2c) + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_I2C_AT91) || defined(CONFIG_I2C_AT91_MODULE) + +static struct resource twi_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_TWI, + .end = AT91SAM9261_BASE_TWI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_TWI, + .end = AT91SAM9261_ID_TWI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_twi_device = { + .name = "at91_i2c", + .id = -1, + .resource = twi_resources, + .num_resources = ARRAY_SIZE(twi_resources), +}; + +void __init at91_add_device_i2c(void) +{ + /* pins used for TWI interface */ + at91_set_A_periph(AT91_PIN_PA7, 0); /* TWD */ + at91_set_multi_drive(AT91_PIN_PA7, 1); + + at91_set_A_periph(AT91_PIN_PA8, 0); /* TWCK */ + at91_set_multi_drive(AT91_PIN_PA8, 1); + + platform_device_register(&at91sam9261_twi_device); +} +#else +void __init at91_add_device_i2c(void) {} +#endif + + +/* -------------------------------------------------------------------- + * SPI + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) +static u64 spi_dmamask = 0xffffffffUL; + +static struct resource spi0_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_SPI0, + .end = AT91SAM9261_BASE_SPI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_SPI0, + .end = AT91SAM9261_ID_SPI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_spi0_device = { + .name = "atmel_spi", + .id = 0, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi0_resources, + .num_resources = ARRAY_SIZE(spi0_resources), +}; + +static const unsigned spi0_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; + +static struct resource spi1_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_SPI1, + .end = AT91SAM9261_BASE_SPI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_SPI1, + .end = AT91SAM9261_ID_SPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91sam9261_spi1_device = { + .name = "atmel_spi", + .id = 1, + .dev = { + .dma_mask = &spi_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = spi1_resources, + .num_resources = ARRAY_SIZE(spi1_resources), +}; + +static const unsigned spi1_standard_cs[4] = { AT91_PIN_PB28, AT91_PIN_PA24, AT91_PIN_PA25, AT91_PIN_PA26 }; + +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) +{ + int i; + unsigned long cs_pin; + short enable_spi0 = 0; + short enable_spi1 = 0; + + /* Choose SPI chip-selects */ + for (i = 0; i < nr_devices; i++) { + if (devices[i].controller_data) + cs_pin = (unsigned long) devices[i].controller_data; + else if (devices[i].bus_num == 0) + cs_pin = spi0_standard_cs[devices[i].chip_select]; + else + cs_pin = spi1_standard_cs[devices[i].chip_select]; + + if (devices[i].bus_num == 0) + enable_spi0 = 1; + else + enable_spi1 = 1; + + /* enable chip-select pin */ + at91_set_gpio_output(cs_pin, 1); + + /* pass chip-select pin to driver */ + devices[i].controller_data = (void *) cs_pin; + } + + spi_register_board_info(devices, nr_devices); + + /* Configure SPI bus(es) */ + if (enable_spi0) { + at91_set_A_periph(AT91_PIN_PA0, 0); /* SPI0_MISO */ + at91_set_A_periph(AT91_PIN_PA1, 0); /* SPI0_MOSI */ + at91_set_A_periph(AT91_PIN_PA2, 0); /* SPI0_SPCK */ + + at91_clock_associate("spi0_clk", &at91sam9261_spi0_device.dev, "spi_clk"); + platform_device_register(&at91sam9261_spi0_device); + } + if (enable_spi1) { + at91_set_A_periph(AT91_PIN_PB30, 0); /* SPI1_MISO */ + at91_set_A_periph(AT91_PIN_PB31, 0); /* SPI1_MOSI */ + at91_set_A_periph(AT91_PIN_PB29, 0); /* SPI1_SPCK */ + + at91_clock_associate("spi1_clk", &at91sam9261_spi1_device.dev, "spi_clk"); + platform_device_register(&at91sam9261_spi1_device); + } +} +#else +void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} +#endif + + +/* -------------------------------------------------------------------- + * LCD Controller + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_FB_AT91) || defined(CONFIG_FB_AT91_MODULE) +static u64 lcdc_dmamask = 0xffffffffUL; +static struct at91fb_info lcdc_data; + +static struct resource lcdc_resources[] = { + [0] = { + .start = AT91SAM9261_LCDC_BASE, + .end = AT91SAM9261_LCDC_BASE + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_LCDC, + .end = AT91SAM9261_ID_LCDC, + .flags = IORESOURCE_IRQ, + }, +#if defined(CONFIG_FB_INTSRAM) + [2] = { + .start = AT91SAM9261_SRAM_BASE, + .end = AT91SAM9261_SRAM_BASE + AT91SAM9261_SRAM_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +#endif +}; + +static struct platform_device at91_lcdc_device = { + .name = "at91-fb", + .id = 0, + .dev = { + .dma_mask = &lcdc_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &lcdc_data, + }, + .resource = lcdc_resources, + .num_resources = ARRAY_SIZE(lcdc_resources), +}; + +void __init at91_add_device_lcdc(struct at91fb_info *data) +{ + if (!data) { + return; + } + + at91_set_A_periph(AT91_PIN_PB1, 0); /* LCDHSYNC */ + at91_set_A_periph(AT91_PIN_PB2, 0); /* LCDDOTCK */ + at91_set_A_periph(AT91_PIN_PB3, 0); /* LCDDEN */ + at91_set_A_periph(AT91_PIN_PB4, 0); /* LCDCC */ + at91_set_A_periph(AT91_PIN_PB7, 0); /* LCDD2 */ + at91_set_A_periph(AT91_PIN_PB8, 0); /* LCDD3 */ + at91_set_A_periph(AT91_PIN_PB9, 0); /* LCDD4 */ + at91_set_A_periph(AT91_PIN_PB10, 0); /* LCDD5 */ + at91_set_A_periph(AT91_PIN_PB11, 0); /* LCDD6 */ + at91_set_A_periph(AT91_PIN_PB12, 0); /* LCDD7 */ + at91_set_A_periph(AT91_PIN_PB15, 0); /* LCDD10 */ + at91_set_A_periph(AT91_PIN_PB16, 0); /* LCDD11 */ + at91_set_A_periph(AT91_PIN_PB17, 0); /* LCDD12 */ + at91_set_A_periph(AT91_PIN_PB18, 0); /* LCDD13 */ + at91_set_A_periph(AT91_PIN_PB19, 0); /* LCDD14 */ + at91_set_A_periph(AT91_PIN_PB20, 0); /* LCDD15 */ + at91_set_B_periph(AT91_PIN_PB23, 0); /* LCDD18 */ + at91_set_B_periph(AT91_PIN_PB24, 0); /* LCDD19 */ + at91_set_B_periph(AT91_PIN_PB25, 0); /* LCDD20 */ + at91_set_B_periph(AT91_PIN_PB26, 0); /* LCDD21 */ + at91_set_B_periph(AT91_PIN_PB27, 0); /* LCDD22 */ + at91_set_B_periph(AT91_PIN_PB28, 0); /* LCDD23 */ + + lcdc_data = *data; + platform_device_register(&at91_lcdc_device); +} +#else +void __init at91_add_device_lcdc(struct at91fb_info *data) {} +#endif + + +/* -------------------------------------------------------------------- + * LEDs + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_LEDS) +u8 at91_leds_cpu; +u8 at91_leds_timer; + +void __init at91_init_leds(u8 cpu_led, u8 timer_led) +{ + at91_leds_cpu = cpu_led; + at91_leds_timer = timer_led; +} +#else +void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} +#endif + + +/* -------------------------------------------------------------------- + * UART + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_SERIAL_ATMEL) +static struct resource dbgu_resources[] = { + [0] = { + .start = AT91_VA_BASE_SYS + AT91_DBGU, + .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_ID_SYS, + .end = AT91_ID_SYS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data dbgu_data = { + .use_dma_tx = 0, + .use_dma_rx = 0, /* DBGU not capable of receive DMA */ + .regs = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU), +}; + +static struct platform_device at91sam9261_dbgu_device = { + .name = "atmel_usart", + .id = 0, + .dev = { + .platform_data = &dbgu_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = dbgu_resources, + .num_resources = ARRAY_SIZE(dbgu_resources), +}; + +static inline void configure_dbgu_pins(void) +{ + at91_set_A_periph(AT91_PIN_PA9, 0); /* DRXD */ + at91_set_A_periph(AT91_PIN_PA10, 1); /* DTXD */ +} + +static struct resource uart0_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_US0, + .end = AT91SAM9261_BASE_US0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_US0, + .end = AT91SAM9261_ID_US0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart0_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9261_uart0_device = { + .name = "atmel_usart", + .id = 1, + .dev = { + .platform_data = &uart0_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart0_resources, + .num_resources = ARRAY_SIZE(uart0_resources), +}; + +static inline void configure_usart0_pins(void) +{ + at91_set_A_periph(AT91_PIN_PC8, 1); /* TXD0 */ + at91_set_A_periph(AT91_PIN_PC9, 0); /* RXD0 */ + at91_set_A_periph(AT91_PIN_PC10, 0); /* RTS0 */ + at91_set_A_periph(AT91_PIN_PC11, 0); /* CTS0 */ +} + +static struct resource uart1_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_US1, + .end = AT91SAM9261_BASE_US1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_US1, + .end = AT91SAM9261_ID_US1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart1_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9261_uart1_device = { + .name = "atmel_usart", + .id = 2, + .dev = { + .platform_data = &uart1_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart1_resources, + .num_resources = ARRAY_SIZE(uart1_resources), +}; + +static inline void configure_usart1_pins(void) +{ + at91_set_A_periph(AT91_PIN_PC12, 1); /* TXD1 */ + at91_set_A_periph(AT91_PIN_PC13, 0); /* RXD1 */ +} + +static struct resource uart2_resources[] = { + [0] = { + .start = AT91SAM9261_BASE_US2, + .end = AT91SAM9261_BASE_US2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91SAM9261_ID_US2, + .end = AT91SAM9261_ID_US2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct atmel_uart_data uart2_data = { + .use_dma_tx = 1, + .use_dma_rx = 1, +}; + +static struct platform_device at91sam9261_uart2_device = { + .name = "atmel_usart", + .id = 3, + .dev = { + .platform_data = &uart2_data, + .coherent_dma_mask = 0xffffffff, + }, + .resource = uart2_resources, + .num_resources = ARRAY_SIZE(uart2_resources), +}; + +static inline void configure_usart2_pins(void) +{ + at91_set_A_periph(AT91_PIN_PC15, 0); /* RXD2 */ + at91_set_A_periph(AT91_PIN_PC14, 1); /* TXD2 */ +} + +struct platform_device *at91_uarts[ATMEL_MAX_UART]; /* the UARTs to use */ +struct platform_device *atmel_default_console_device; /* the serial console device */ + +void __init at91_init_serial(struct at91_uart_config *config) +{ + int i; + + /* Fill in list of supported UARTs */ + for (i = 0; i < config->nr_tty; i++) { + switch (config->tty_map[i]) { + case 0: + configure_usart0_pins(); + at91_uarts[i] = &at91sam9261_uart0_device; + at91_clock_associate("usart0_clk", &at91sam9261_uart0_device.dev, "usart"); + break; + case 1: + configure_usart1_pins(); + at91_uarts[i] = &at91sam9261_uart1_device; + at91_clock_associate("usart1_clk", &at91sam9261_uart1_device.dev, "usart"); + break; + case 2: + configure_usart2_pins(); + at91_uarts[i] = &at91sam9261_uart2_device; + at91_clock_associate("usart2_clk", &at91sam9261_uart2_device.dev, "usart"); + break; + case 3: + configure_dbgu_pins(); + at91_uarts[i] = &at91sam9261_dbgu_device; + at91_clock_associate("mck", &at91sam9261_dbgu_device.dev, "usart"); + break; + default: + continue; + } + at91_uarts[i]->id = i; /* update ID number to mapped ID */ + } + + /* Set serial console device */ + if (config->console_tty < ATMEL_MAX_UART) + atmel_default_console_device = at91_uarts[config->console_tty]; + if (!atmel_default_console_device) + printk(KERN_INFO "AT91: No default serial console defined.\n"); +} + +void __init at91_add_device_serial(void) +{ + int i; + + for (i = 0; i < ATMEL_MAX_UART; i++) { + if (at91_uarts[i]) + platform_device_register(at91_uarts[i]); + } +} +#else +void __init at91_init_serial(struct at91_uart_config *config) {} +void __init at91_add_device_serial(void) {} +#endif + + +/* -------------------------------------------------------------------- */ + +/* + * These devices are always present and don't need any board-specific + * setup. + */ +static int __init at91_add_standard_devices(void) +{ + return 0; +} + +arch_initcall(at91_add_standard_devices); diff --git a/arch/arm/mach-at91rm9200/at91sam926x_time.c b/arch/arm/mach-at91rm9200/at91sam926x_time.c new file mode 100644 index 000000000000..99df5f6ee42e --- /dev/null +++ b/arch/arm/mach-at91rm9200/at91sam926x_time.c @@ -0,0 +1,114 @@ +/* + * linux/arch/arm/mach-at91rm9200/at91sam926x_time.c + * + * Copyright (C) 2005-2006 M. Amine SAYA, ATMEL Rousset, France + * Revision 2005 M. Nicolas Diremdjian, ATMEL Rousset, France + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/time.h> + +#include <asm/hardware.h> +#include <asm/io.h> +#include <asm/mach/time.h> + +#include <asm/arch/at91_pit.h> + + +#define PIT_CPIV(x) ((x) & AT91_PIT_CPIV) +#define PIT_PICNT(x) (((x) & AT91_PIT_PICNT) >> 20) + +/* + * Returns number of microseconds since last timer interrupt. Note that interrupts + * will have been disabled by do_gettimeofday() + * 'LATCH' is hwclock ticks (see CLOCK_TICK_RATE in timex.h) per jiffy. + * 'tick' is usecs per jiffy (linux/timex.h). + */ +static unsigned long at91sam926x_gettimeoffset(void) +{ + unsigned long elapsed; + unsigned long t = at91_sys_read(AT91_PIT_PIIR); + + elapsed = (PIT_PICNT(t) * LATCH) + PIT_CPIV(t); /* hardware clock cycles */ + + return (unsigned long)(elapsed * 1000000) / LATCH; +} + +/* + * IRQ handler for the timer. + */ +static irqreturn_t at91sam926x_timer_interrupt(int irq, void *dev_id) +{ + volatile long nr_ticks; + + if (at91_sys_read(AT91_PIT_SR) & AT91_PIT_PITS) { /* This is a shared interrupt */ + write_seqlock(&xtime_lock); + + /* Get number to ticks performed before interrupt and clear PIT interrupt */ + nr_ticks = PIT_PICNT(at91_sys_read(AT91_PIT_PIVR)); + do { + timer_tick(); + nr_ticks--; + } while (nr_ticks); + + write_sequnlock(&xtime_lock); + return IRQ_HANDLED; + } else + return IRQ_NONE; /* not handled */ +} + +static struct irqaction at91sam926x_timer_irq = { + .name = "at91_tick", + .flags = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER, + .handler = at91sam926x_timer_interrupt +}; + +void at91sam926x_timer_reset(void) +{ + /* Disable timer */ + at91_sys_write(AT91_PIT_MR, 0); + + /* Clear any pending interrupts */ + (void) at91_sys_read(AT91_PIT_PIVR); + + /* Set Period Interval timer and enable its interrupt */ + at91_sys_write(AT91_PIT_MR, (LATCH & AT91_PIT_PIV) | AT91_PIT_PITIEN | AT91_PIT_PITEN); +} + +/* + * Set up timer interrupt. + */ +void __init at91sam926x_timer_init(void) +{ + /* Initialize and enable the timer */ + at91sam926x_timer_reset(); + + /* Make IRQs happen for the system timer. */ + setup_irq(AT91_ID_SYS, &at91sam926x_timer_irq); +} + +#ifdef CONFIG_PM +static void at91sam926x_timer_suspend(void) +{ + /* Disable timer */ + at91_sys_write(AT91_PIT_MR, 0); +} +#else +#define at91sam926x_timer_suspend NULL +#endif + +struct sys_timer at91sam926x_timer = { + .init = at91sam926x_timer_init, + .offset = at91sam926x_gettimeoffset, + .suspend = at91sam926x_timer_suspend, + .resume = at91sam926x_timer_reset, +}; + diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91rm9200/board-carmeva.c index 98208740e7c5..654f0379550a 100644 --- a/arch/arm/mach-at91rm9200/board-carmeva.c +++ b/arch/arm/mach-at91rm9200/board-carmeva.c @@ -65,7 +65,6 @@ static void __init carmeva_init_irq(void) at91rm9200_init_interrupts(NULL); } - static struct at91_eth_data __initdata carmeva_eth_data = { .phy_irq_pin = AT91_PIN_PC4, .is_rmii = 1, @@ -89,8 +88,33 @@ static struct at91_udc_data __initdata carmeva_udc_data = { // }; static struct at91_mmc_data __initdata carmeva_mmc_data = { - .is_b = 0, + .slot_b = 0, .wire4 = 1, + .det_pin = AT91_PIN_PB10, + .wp_pin = AT91_PIN_PC14, +}; + +static struct spi_board_info carmeva_spi_devices[] = { + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 10 * 1000 * 1000, + }, + { /* User accessable spi - cs1 (250KHz) */ + .modalias = "spi-cs1", + .chip_select = 1, + .max_speed_hz = 250 * 1000, + }, + { /* User accessable spi - cs2 (1MHz) */ + .modalias = "spi-cs2", + .chip_select = 2, + .max_speed_hz = 1 * 1000 * 1000, + }, + { /* User accessable spi - cs3 (10MHz) */ + .modalias = "spi-cs3", + .chip_select = 3, + .max_speed_hz = 10 * 1000 * 1000, + }, }; static void __init carmeva_board_init(void) @@ -105,10 +129,10 @@ static void __init carmeva_board_init(void) at91_add_device_udc(&carmeva_udc_data); /* I2C */ at91_add_device_i2c(); + /* SPI */ + at91_add_device_spi(carmeva_spi_devices, ARRAY_SIZE(carmeva_spi_devices)); /* Compact Flash */ // at91_add_device_cf(&carmeva_cf_data); - /* SPI */ -// at91_add_device_spi(NULL, 0); /* MMC */ at91_add_device_mmc(&carmeva_mmc_data); } diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c index 8eeae491ce71..b8bb8052607a 100644 --- a/arch/arm/mach-at91rm9200/board-csb337.c +++ b/arch/arm/mach-at91rm9200/board-csb337.c @@ -99,7 +99,7 @@ static struct at91_cf_data __initdata csb337_cf_data = { static struct at91_mmc_data __initdata csb337_mmc_data = { .det_pin = AT91_PIN_PD5, - .is_b = 0, + .slot_b = 0, .wire4 = 1, .wp_pin = AT91_PIN_PD6, }; diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c index c699f3984d4b..7522bf91bce8 100644 --- a/arch/arm/mach-at91rm9200/board-dk.c +++ b/arch/arm/mach-at91rm9200/board-dk.c @@ -27,6 +27,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> +#include <linux/mtd/physmap.h> #include <asm/hardware.h> #include <asm/setup.h> @@ -39,6 +40,7 @@ #include <asm/arch/board.h> #include <asm/arch/gpio.h> +#include <asm/arch/at91rm9200_mc.h> #include "generic.h" @@ -93,7 +95,7 @@ static struct at91_cf_data __initdata dk_cf_data = { }; static struct at91_mmc_data __initdata dk_mmc_data = { - .is_b = 0, + .slot_b = 0, .wire4 = 1, }; @@ -145,6 +147,30 @@ static struct at91_nand_data __initdata dk_nand_data = { .partition_info = nand_partitions, }; +#define DK_FLASH_BASE AT91_CHIPSELECT_0 +#define DK_FLASH_SIZE 0x200000 + +static struct physmap_flash_data dk_flash_data = { + .width = 2, +}; + +static struct resource dk_flash_resource = { + .start = DK_FLASH_BASE, + .end = DK_FLASH_BASE + DK_FLASH_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device dk_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &dk_flash_data, + }, + .resource = &dk_flash_resource, + .num_resources = 1, +}; + + static void __init dk_board_init(void) { /* Serial */ @@ -172,6 +198,8 @@ static void __init dk_board_init(void) #endif /* NAND */ at91_add_device_nand(&dk_nand_data); + /* NOR Flash */ + platform_device_register(&dk_flash); /* VGA */ // dk_add_device_video(); } diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91rm9200/board-eb9200.c index 65e867ba2df3..80b72cf7264c 100644 --- a/arch/arm/mach-at91rm9200/board-eb9200.c +++ b/arch/arm/mach-at91rm9200/board-eb9200.c @@ -87,7 +87,7 @@ static struct at91_cf_data __initdata eb9200_cf_data = { }; static struct at91_mmc_data __initdata eb9200_mmc_data = { - .is_b = 0, + .slot_b = 0, .wire4 = 1, }; diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c index 830eb7932178..c4fdb415f20e 100644 --- a/arch/arm/mach-at91rm9200/board-ek.c +++ b/arch/arm/mach-at91rm9200/board-ek.c @@ -27,6 +27,7 @@ #include <linux/module.h> #include <linux/platform_device.h> #include <linux/spi/spi.h> +#include <linux/mtd/physmap.h> #include <asm/hardware.h> #include <asm/setup.h> @@ -39,6 +40,7 @@ #include <asm/arch/board.h> #include <asm/arch/gpio.h> +#include <asm/arch/at91rm9200_mc.h> #include "generic.h" @@ -87,7 +89,7 @@ static struct at91_udc_data __initdata ek_udc_data = { static struct at91_mmc_data __initdata ek_mmc_data = { .det_pin = AT91_PIN_PB27, - .is_b = 0, + .slot_b = 0, .wire4 = 1, .wp_pin = AT91_PIN_PA17, }; @@ -107,6 +109,30 @@ static struct spi_board_info ek_spi_devices[] = { #endif }; +#define EK_FLASH_BASE AT91_CHIPSELECT_0 +#define EK_FLASH_SIZE 0x200000 + +static struct physmap_flash_data ek_flash_data = { + .width = 2, +}; + +static struct resource ek_flash_resource = { + .start = EK_FLASH_BASE, + .end = EK_FLASH_BASE + EK_FLASH_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device ek_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &ek_flash_data, + }, + .resource = &ek_flash_resource, + .num_resources = 1, +}; + + static void __init ek_board_init(void) { /* Serial */ @@ -130,6 +156,8 @@ static void __init ek_board_init(void) at91_set_gpio_output(AT91_PIN_PB22, 1); /* this MMC card slot can optionally use SPI signaling (CS3). */ at91_add_device_mmc(&ek_mmc_data); #endif + /* NOR Flash */ + platform_device_register(&ek_flash); /* VGA */ // ek_add_device_video(); } diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91rm9200/board-kb9202.c index 35a954a44b1b..759d8191854f 100644 --- a/arch/arm/mach-at91rm9200/board-kb9202.c +++ b/arch/arm/mach-at91rm9200/board-kb9202.c @@ -84,7 +84,7 @@ static struct at91_udc_data __initdata kb9202_udc_data = { static struct at91_mmc_data __initdata kb9202_mmc_data = { .det_pin = AT91_PIN_PB2, - .is_b = 0, + .slot_b = 0, .wire4 = 1, }; diff --git a/arch/arm/mach-at91rm9200/board-sam9260ek.c b/arch/arm/mach-at91rm9200/board-sam9260ek.c new file mode 100644 index 000000000000..da5d58ac870b --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-sam9260ek.c @@ -0,0 +1,202 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-ek.c + * + * Copyright (C) 2005 SAN People + * Copyright (C) 2006 Atmel + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> + +#include <asm/hardware.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/irq.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <asm/arch/board.h> +#include <asm/arch/gpio.h> +#include <asm/arch/at91sam926x_mc.h> + +#include "generic.h" + + +/* + * Serial port configuration. + * 0 .. 5 = USART0 .. USART5 + * 6 = DBGU + */ +static struct at91_uart_config __initdata ek_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 3, + .tty_map = { 6, 0, 1, -1, -1, -1, -1 } /* ttyS0, ..., ttyS6 */ +}; + +static void __init ek_map_io(void) +{ + /* Initialize processor: 18.432 MHz crystal */ + at91sam9260_initialize(18432000); + + /* Setup the serial ports and console */ + at91_init_serial(&ek_uart_config); +} + +static void __init ek_init_irq(void) +{ + at91sam9260_init_interrupts(NULL); +} + + +/* + * USB Host port + */ +static struct at91_usbh_data __initdata ek_usbh_data = { + .ports = 2, +}; + +/* + * USB Device port + */ +static struct at91_udc_data __initdata ek_udc_data = { + .vbus_pin = AT91_PIN_PC5, + .pullup_pin = 0, /* pull-up driven by UDC */ +}; + + +/* + * SPI devices. + */ +static struct spi_board_info ek_spi_devices[] = { +#if !defined(CONFIG_MMC_AT91) + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 1, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD) + { /* DataFlash card */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +#endif +#endif +#if defined(CONFIG_SND_AT73C213) + { /* AT73C213 DAC */ + .modalias = "snd_at73c213", + .chip_select = 0, + .max_speed_hz = 10 * 1000 * 1000, + .bus_num = 1, + }, +#endif +}; + + +/* + * MACB Ethernet device + */ +static struct __initdata eth_platform_data ek_macb_data = { + .phy_irq_pin = AT91_PIN_PA7, + .is_rmii = 1, +}; + + +/* + * NAND flash + */ +static struct mtd_partition __initdata ek_nand_partition[] = { + { + .name = "Partition 1", + .offset = 0, + .size = 256 * 1024, + }, + { + .name = "Partition 2", + .offset = 256 * 1024, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct mtd_partition *nand_partitions(int size, int *num_partitions) +{ + *num_partitions = ARRAY_SIZE(ek_nand_partition); + return ek_nand_partition; +} + +static struct at91_nand_data __initdata ek_nand_data = { + .ale = 21, + .cle = 22, +// .det_pin = ... not connected + .rdy_pin = AT91_PIN_PC13, + .enable_pin = AT91_PIN_PC14, + .partition_info = nand_partitions, +#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16) + .bus_width_16 = 1, +#else + .bus_width_16 = 0, +#endif +}; + + +/* + * MCI (SD/MMC) + */ +static struct at91_mmc_data __initdata ek_mmc_data = { + .slot_b = 1, + .wire4 = 1, +// .det_pin = ... not connected +// .wp_pin = ... not connected +// .vcc_pin = ... not connected +}; + +static void __init ek_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* USB Host */ + at91_add_device_usbh(&ek_usbh_data); + /* USB Device */ + at91_add_device_udc(&ek_udc_data); + /* SPI */ + at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); + /* NAND */ + at91_add_device_nand(&ek_nand_data); + /* Ethernet */ + at91_add_device_eth(&ek_macb_data); + /* MMC */ + at91_add_device_mmc(&ek_mmc_data); +} + +MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK") + /* Maintainer: Atmel */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91sam926x_timer, + .map_io = ek_map_io, + .init_irq = ek_init_irq, + .init_machine = ek_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/board-sam9261ek.c b/arch/arm/mach-at91rm9200/board-sam9261ek.c new file mode 100644 index 000000000000..30b490d8886b --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-sam9261ek.c @@ -0,0 +1,259 @@ +/* + * linux/arch/arm/mach-at91rm9200/board-ek.c + * + * Copyright (C) 2005 SAN People + * Copyright (C) 2006 Atmel + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> +#include <linux/dm9000.h> + +#include <asm/hardware.h> +#include <asm/setup.h> +#include <asm/mach-types.h> +#include <asm/irq.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> + +#include <asm/arch/board.h> +#include <asm/arch/gpio.h> +#include <asm/arch/at91sam926x_mc.h> + +#include "generic.h" + + +/* + * Serial port configuration. + * 0 .. 2 = USART0 .. USART2 + * 3 = DBGU + */ +static struct at91_uart_config __initdata ek_uart_config = { + .console_tty = 0, /* ttyS0 */ + .nr_tty = 1, + .tty_map = { 3, -1, -1, -1 } /* ttyS0, ..., ttyS3 */ +}; + +static void __init ek_map_io(void) +{ + /* Initialize processor: 18.432 MHz crystal */ + at91sam9261_initialize(18432000); + + /* Setup the serial ports and console */ + at91_init_serial(&ek_uart_config); +} + +static void __init ek_init_irq(void) +{ + at91sam9261_init_interrupts(NULL); +} + + +/* + * DM9000 ethernet device + */ +#if defined(CONFIG_DM9000) +static struct resource at91sam9261_dm9000_resource[] = { + [0] = { + .start = AT91_CHIPSELECT_2, + .end = AT91_CHIPSELECT_2 + 3, + .flags = IORESOURCE_MEM + }, + [1] = { + .start = AT91_CHIPSELECT_2 + 0x44, + .end = AT91_CHIPSELECT_2 + 0xFF, + .flags = IORESOURCE_MEM + }, + [2] = { + .start = AT91_PIN_PC11, + .end = AT91_PIN_PC11, + .flags = IORESOURCE_IRQ + } +}; + +static struct dm9000_plat_data dm9000_platdata = { + .flags = DM9000_PLATF_16BITONLY, +}; + +static struct platform_device at91sam9261_dm9000_device = { + .name = "dm9000", + .id = 0, + .num_resources = ARRAY_SIZE(at91sam9261_dm9000_resource), + .resource = at91sam9261_dm9000_resource, + .dev = { + .platform_data = &dm9000_platdata, + } +}; + +static void __init ek_add_device_dm9000(void) +{ + /* + * Configure Chip-Select 2 on SMC for the DM9000. + * Note: These timings were calculated for MASTER_CLOCK = 100000000 + * according to the DM9000 timings. + */ + at91_sys_write(AT91_SMC_SETUP(2), AT91_SMC_NWESETUP_(2) | AT91_SMC_NCS_WRSETUP_(0) | AT91_SMC_NRDSETUP_(2) | AT91_SMC_NCS_RDSETUP_(0)); + at91_sys_write(AT91_SMC_PULSE(2), AT91_SMC_NWEPULSE_(4) | AT91_SMC_NCS_WRPULSE_(8) | AT91_SMC_NRDPULSE_(4) | AT91_SMC_NCS_RDPULSE_(8)); + at91_sys_write(AT91_SMC_CYCLE(2), AT91_SMC_NWECYCLE_(16) | AT91_SMC_NRDCYCLE_(16)); + at91_sys_write(AT91_SMC_MODE(2), AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_WRITE | AT91_SMC_DBW_16 | AT91_SMC_TDF_(1)); + + /* Configure Reset signal as output */ + at91_set_gpio_output(AT91_PIN_PC10, 0); + + /* Configure Interrupt pin as input, no pull-up */ + at91_set_gpio_input(AT91_PIN_PC11, 0); + + platform_device_register(&at91sam9261_dm9000_device); +} +#else +static void __init ek_add_device_dm9000(void) {} +#endif /* CONFIG_DM9000 */ + + +/* + * USB Host Port + */ +static struct at91_usbh_data __initdata ek_usbh_data = { + .ports = 2, +}; + + +/* + * USB Device Port + */ +static struct at91_udc_data __initdata ek_udc_data = { + .vbus_pin = AT91_PIN_PB29, + .pullup_pin = 0, /* pull-up driven by UDC */ +}; + + +/* + * MCI (SD/MMC) + */ +static struct at91_mmc_data __initdata ek_mmc_data = { + .wire4 = 1, +// .det_pin = ... not connected +// .wp_pin = ... not connected +// .vcc_pin = ... not connected +}; + + +/* + * NAND flash + */ +static struct mtd_partition __initdata ek_nand_partition[] = { + { + .name = "Partition 1", + .offset = 0, + .size = 256 * 1024, + }, + { + .name = "Partition 2", + .offset = 256 * 1024 , + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct mtd_partition *nand_partitions(int size, int *num_partitions) +{ + *num_partitions = ARRAY_SIZE(ek_nand_partition); + return ek_nand_partition; +} + +static struct at91_nand_data __initdata ek_nand_data = { + .ale = 22, + .cle = 21, +// .det_pin = ... not connected + .rdy_pin = AT91_PIN_PC15, + .enable_pin = AT91_PIN_PC14, + .partition_info = nand_partitions, +#if defined(CONFIG_MTD_NAND_AT91_BUSWIDTH_16) + .bus_width_16 = 1, +#else + .bus_width_16 = 0, +#endif +}; + +/* + * SPI devices + */ +static struct spi_board_info ek_spi_devices[] = { + { /* DataFlash chip */ + .modalias = "mtd_dataflash", + .chip_select = 0, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD) + { /* DataFlash card - jumper (J12) configurable to CS3 or CS0 */ + .modalias = "mtd_dataflash", + .chip_select = 3, + .max_speed_hz = 15 * 1000 * 1000, + .bus_num = 0, + }, +#elif defined(CONFIG_SND_AT73C213) + { /* AT73C213 DAC */ + .modalias = "snd_at73c213", + .chip_select = 3, + .max_speed_hz = 10 * 1000 * 1000, + .bus_num = 0, + }, +#endif +}; + + +static void __init ek_board_init(void) +{ + /* Serial */ + at91_add_device_serial(); + /* USB Host */ + at91_add_device_usbh(&ek_usbh_data); + /* USB Device */ + at91_add_device_udc(&ek_udc_data); + /* I2C */ + at91_add_device_i2c(); + /* NAND */ + at91_add_device_nand(&ek_nand_data); + /* DM9000 ethernet */ + ek_add_device_dm9000(); + + /* spi0 and mmc/sd share the same PIO pins */ +#if defined(CONFIG_SPI_ATMEL) || defined(CONFIG_SPI_ATMEL_MODULE) + /* SPI */ + at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); +#else + /* MMC */ + at91_add_device_mmc(&ek_mmc_data); +#endif +} + +MACHINE_START(AT91SAM9261EK, "Atmel AT91SAM9261-EK") + /* Maintainer: Atmel */ + .phys_io = AT91_BASE_SYS, + .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .timer = &at91sam926x_timer, + .map_io = ek_map_io, + .init_irq = ek_init_irq, + .init_machine = ek_board_init, +MACHINE_END diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c index a43b061a7c85..4dee21fefe5a 100644 --- a/arch/arm/mach-at91rm9200/clock.c +++ b/arch/arm/mach-at91rm9200/clock.c @@ -28,6 +28,8 @@ #include <asm/mach-types.h> #include <asm/hardware.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/cpu.h> #include "clock.h" @@ -41,6 +43,7 @@ #define clk_is_primary(x) ((x)->type & CLK_TYPE_PRIMARY) #define clk_is_programmable(x) ((x)->type & CLK_TYPE_PROGRAMMABLE) #define clk_is_peripheral(x) ((x)->type & CLK_TYPE_PERIPHERAL) +#define clk_is_sys(x) ((x)->type & CLK_TYPE_SYSTEM) static LIST_HEAD(clocks); @@ -114,13 +117,11 @@ static void pmc_sys_mode(struct clk *clk, int is_on) static struct clk udpck = { .name = "udpck", .parent = &pllb, - .pmc_mask = AT91_PMC_UDP, .mode = pmc_sys_mode, }; static struct clk uhpck = { .name = "uhpck", .parent = &pllb, - .pmc_mask = AT91_PMC_UHP, .mode = pmc_sys_mode, }; @@ -434,6 +435,12 @@ int __init clk_register(struct clk *clk) clk->mode = pmc_periph_mode; list_add_tail(&clk->node, &clocks); } + else if (clk_is_sys(clk)) { + clk->parent = &mck; + clk->mode = pmc_sys_mode; + + list_add_tail(&clk->node, &clocks); + } #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS else if (clk_is_programmable(clk)) { clk->mode = pmc_sys_mode; @@ -586,9 +593,21 @@ int __init at91_clock_init(unsigned long main_clock) */ at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M; pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init); - at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP); + if (cpu_is_at91rm9200()) { + uhpck.pmc_mask = AT91RM9200_PMC_UHP; + udpck.pmc_mask = AT91RM9200_PMC_UDP; + at91_sys_write(AT91_PMC_SCDR, AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP); + at91_sys_write(AT91_PMC_SCER, AT91RM9200_PMC_MCKUDP); + } else if (cpu_is_at91sam9260()) { + uhpck.pmc_mask = AT91SAM926x_PMC_UHP; + udpck.pmc_mask = AT91SAM926x_PMC_UDP; + at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP); + } else if (cpu_is_at91sam9261()) { + uhpck.pmc_mask = (AT91SAM926x_PMC_UHP | AT91_PMC_HCK0); + udpck.pmc_mask = AT91SAM926x_PMC_UDP; + at91_sys_write(AT91_PMC_SCDR, AT91SAM926x_PMC_UHP | AT91_PMC_HCK0 | AT91SAM926x_PMC_UDP); + } at91_sys_write(AT91_CKGR_PLLBR, 0); - at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP); udpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init); uhpck.rate_hz = at91_usb_rate(&pllb, pllb.rate_hz, at91_pllb_usb_init); diff --git a/arch/arm/mach-at91rm9200/clock.h b/arch/arm/mach-at91rm9200/clock.h index 0592e662ab37..b5c7a2eb2d1d 100644 --- a/arch/arm/mach-at91rm9200/clock.h +++ b/arch/arm/mach-at91rm9200/clock.h @@ -10,6 +10,7 @@ #define CLK_TYPE_PLL 0x2 #define CLK_TYPE_PROGRAMMABLE 0x4 #define CLK_TYPE_PERIPHERAL 0x8 +#define CLK_TYPE_SYSTEM 0x10 struct clk { diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91rm9200/generic.h index 694e411e285f..8c4d5a77d485 100644 --- a/arch/arm/mach-at91rm9200/generic.h +++ b/arch/arm/mach-at91rm9200/generic.h @@ -10,14 +10,19 @@ /* Processors */ extern void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks); +extern void __init at91sam9260_initialize(unsigned long main_clock); +extern void __init at91sam9261_initialize(unsigned long main_clock); /* Interrupts */ extern void __init at91rm9200_init_interrupts(unsigned int priority[]); +extern void __init at91sam9260_init_interrupts(unsigned int priority[]); +extern void __init at91sam9261_init_interrupts(unsigned int priority[]); extern void __init at91_aic_init(unsigned int priority[]); /* Timer */ struct sys_timer; extern struct sys_timer at91rm9200_timer; +extern struct sys_timer at91sam926x_timer; /* Clocks */ extern int __init at91_clock_init(unsigned long main_clock); @@ -39,3 +44,6 @@ struct at91_gpio_bank { }; extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks); extern void __init at91_gpio_irq_setup(void); + +extern void (*at91_arch_reset)(void); +extern int at91_extern_irq; diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c index 7467d644f0a3..3f188508c391 100644 --- a/arch/arm/mach-at91rm9200/gpio.c +++ b/arch/arm/mach-at91rm9200/gpio.c @@ -19,6 +19,8 @@ #include <asm/io.h> #include <asm/hardware.h> +#include <asm/arch/at91_pio.h> +#include <asm/arch/at91_pmc.h> #include <asm/arch/gpio.h> #include "generic.h" @@ -332,10 +334,10 @@ static struct irq_chip gpio_irqchip = { .set_wake = gpio_irq_set_wake, }; -static void gpio_irq_handler(unsigned irq, struct irqdesc *desc) +static void gpio_irq_handler(unsigned irq, struct irq_desc *desc) { unsigned pin; - struct irqdesc *gpio; + struct irq_desc *gpio; void __iomem *pio; u32 isr; @@ -396,7 +398,7 @@ void __init at91_gpio_irq_setup(void) __raw_writel(~0, controller + PIO_IDR); set_irq_data(id, (void *) pin); - set_irq_chipdata(id, controller); + set_irq_chip_data(id, controller); for (i = 0; i < 32; i++, pin++) { /* @@ -404,7 +406,7 @@ void __init at91_gpio_irq_setup(void) * shorter, and the AIC handles interupts sanely. */ set_irq_chip(pin, &gpio_irqchip); - set_irq_handler(pin, do_simple_IRQ); + set_irq_handler(pin, handle_simple_irq); set_irq_flags(pin, IRQF_VALID); } diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c index 3e488117ca91..2148daafd29c 100644 --- a/arch/arm/mach-at91rm9200/irq.c +++ b/arch/arm/mach-at91rm9200/irq.c @@ -47,6 +47,10 @@ static void at91_aic_unmask_irq(unsigned int irq) at91_sys_write(AT91_AIC_IECR, 1 << irq); } +unsigned int at91_extern_irq; + +#define is_extern_irq(irq) ((1 << (irq)) & at91_extern_irq) + static int at91_aic_set_type(unsigned irq, unsigned type) { unsigned int smr, srctype; @@ -59,14 +63,16 @@ static int at91_aic_set_type(unsigned irq, unsigned type) srctype = AT91_AIC_SRCTYPE_RISING; break; case IRQT_LOW: - if ((irq > AT91_ID_FIQ) && (irq < AT91RM9200_ID_IRQ0)) /* only supported on external interrupts */ + if ((irq == AT91_ID_FIQ) || is_extern_irq(irq)) /* only supported on external interrupts */ + srctype = AT91_AIC_SRCTYPE_LOW; + else return -EINVAL; - srctype = AT91_AIC_SRCTYPE_LOW; break; case IRQT_FALLING: - if ((irq > AT91_ID_FIQ) && (irq < AT91RM9200_ID_IRQ0)) /* only supported on external interrupts */ + if ((irq == AT91_ID_FIQ) || is_extern_irq(irq)) /* only supported on external interrupts */ + srctype = AT91_AIC_SRCTYPE_FALLING; + else return -EINVAL; - srctype = AT91_AIC_SRCTYPE_FALLING; break; default: return -EINVAL; @@ -139,7 +145,7 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS]) at91_sys_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]); set_irq_chip(i, &at91_aic_chip); - set_irq_handler(i, do_level_IRQ); + set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID | IRQF_PROBE); /* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */ diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91rm9200/pm.c index 32c95d8eaacf..67aa5572a3ea 100644 --- a/arch/arm/mach-at91rm9200/pm.c +++ b/arch/arm/mach-at91rm9200/pm.c @@ -26,7 +26,10 @@ #include <asm/mach/irq.h> #include <asm/mach-types.h> +#include <asm/arch/at91_pmc.h> +#include <asm/arch/at91rm9200_mc.h> #include <asm/arch/gpio.h> +#include <asm/arch/cpu.h> #include "generic.h" @@ -68,9 +71,15 @@ static int at91_pm_verify_clocks(void) scsr = at91_sys_read(AT91_PMC_SCSR); /* USB must not be using PLLB */ - if ((scsr & (AT91_PMC_UHP | AT91_PMC_UDP)) != 0) { - pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n"); - return 0; + if (cpu_is_at91rm9200()) { + if ((scsr & (AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP)) != 0) { + pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n"); + return 0; + } + } else if (cpu_is_at91sam9260()) { +#warning "Check SAM9260 USB clocks" + } else if (cpu_is_at91sam9261()) { +#warning "Check SAM9261 USB clocks" } #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS @@ -112,7 +121,6 @@ EXPORT_SYMBOL(at91_suspend_entering_slow_clock); static void (*slow_clock)(void); - static int at91_pm_enter(suspend_state_t state) { at91_gpio_suspend(); @@ -123,13 +131,7 @@ static int at91_pm_enter(suspend_state_t state) (at91_sys_read(AT91_PMC_PCSR) | (1 << AT91_ID_FIQ) | (1 << AT91_ID_SYS) - | (1 << AT91RM9200_ID_IRQ0) - | (1 << AT91RM9200_ID_IRQ1) - | (1 << AT91RM9200_ID_IRQ2) - | (1 << AT91RM9200_ID_IRQ3) - | (1 << AT91RM9200_ID_IRQ4) - | (1 << AT91RM9200_ID_IRQ5) - | (1 << AT91RM9200_ID_IRQ6)) + | (at91_extern_irq)) & at91_sys_read(AT91_AIC_IMR), state); |