diff -Nur linux-2.6.15.4-orig/arch/arm/Kconfig linux-2.6.15.4/arch/arm/Kconfig --- linux-2.6.15.4-orig/arch/arm/Kconfig 2006-02-10 08:22:48.000000000 +0100 +++ linux-2.6.15.4/arch/arm/Kconfig 2006-08-09 14:22:58.000000000 +0200 @@ -215,6 +215,21 @@ help This enables support for systems based on the Agilent AAEC-2000 +config MACH_AT91SAM9261EK + bool "Atmel AT91SAM9261-EK board" + help + Say Y here if you intend to run this kernel on AT91SAM9261-EK. + +config MACH_AT91SAM9260EK + bool "Atmel AT91SAM9260-EK board" + help + Say Y here if you intend to run this kernel on AT91SAM9260-EK. + +config MACH_NADIA2VB + bool "Atmel NADIA2-VB board" + help + Say Y here if you intend to run this kernel on NADIA2-VB. + endchoice source "arch/arm/mach-clps711x/Kconfig" @@ -728,6 +743,10 @@ source "drivers/char/Kconfig" +if MACH_AT91SAM9261EK || MACH_AT91SAM9260EK || MACH_NADIA2VB +source "drivers/spi/Kconfig" +endif + source "drivers/i2c/Kconfig" source "drivers/hwmon/Kconfig" diff -Nur linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/board-ek.c linux-2.6.15.4/arch/arm/mach-at91sam9260/board-ek.c --- linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/board-ek.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.15.4/arch/arm/mach-at91sam9260/board-ek.c 2006-08-09 10:53:02.000000000 +0200 @@ -0,0 +1,89 @@ +/* + * linux/arch/arm/mach-at91sam9260/board-ek.c + * + * Copyright (C) 2005 SAN People + * + * Epson S1D framebuffer glue code is: + * Copyright (C) 2005 Thibaut VARENE + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + + +extern void __init at91sam9260_init_irq(unsigned int priority[NR_IRQS]); +extern void __init at91_gpio_irq_setup(unsigned banks); + +static void __init ek_init_irq(void) +{ + /* Initialize AIC controller */ + at91sam9260_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(AT91_NR_PIO); +} + +extern void __init at91sam9260_map_io(void); + +static void __init ek_map_io(void) +{ + at91sam9260_map_io(); + + /* Initialize clocks: 18.432 MHz crystal */ + //at91_clock_init(AT91C_MASTER_CLOCK); + +} + +#if 0 +static struct at91_udc_data __initdata ek_udc_data = { + .vbus_pin = AT91_PIN_PB29, + .pullup_pin = AT91_PIN_PB30, +}; + +static void __init ek_board_init(void) +{ + /* USB Device */ + at91_add_device_udc(&ek_udc_data); +} +#endif + +MACHINE_START(AT91SAM9260EK, "ATMEL AT91SAM9260") + .phys_ram = AT91_SDRAM_BASE, + .phys_io = AT91C_BASE_AIC, + .io_pg_offst = ((AT91C_VA_BASE_SYS) >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .map_io = ek_map_io, + .init_irq = ek_init_irq, + .timer = &at91sam9260_timer, +MACHINE_END diff -Nur linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/core.c linux-2.6.15.4/arch/arm/mach-at91sam9260/core.c --- linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/core.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.15.4/arch/arm/mach-at91sam9260/core.c 2006-08-09 10:53:03.000000000 +0200 @@ -0,0 +1,62 @@ +/* + * linux/arch/arm/mach-at91sam9261/core.c + * + * Copyright (C) 2005 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 +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +extern void __init at91sam9260_init_irq(void); + + +/* + * System peripheral registers mapped at virtual address. + */ + +static struct map_desc at91sam9260_io_desc[] __initdata = { + { + .virtual = AT91C_VA_BASE_SYS, + .pfn = __phys_to_pfn(AT91C_BASE_AIC), + .length = SZ_4K, + .type = MT_DEVICE + }, + { + .virtual = AT91C_VA_BASE_EBI, + .pfn = __phys_to_pfn(AT91C_BASE_EBI), + .length = SZ_4K, + .type = MT_DEVICE + }, + { + .virtual = AT91C_VA_BASE_UDP, + .pfn = __phys_to_pfn(AT91_BASE_UDP), + .length = SZ_16K, + .type = MT_DEVICE + } +}; + + +void __init at91sam9260_map_io(void) +{ + iotable_init(at91sam9260_io_desc, ARRAY_SIZE(at91sam9260_io_desc)); +} + diff -Nur linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/devices.c linux-2.6.15.4/arch/arm/mach-at91sam9260/devices.c --- linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/devices.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.15.4/arch/arm/mach-at91sam9260/devices.c 2006-08-09 10:53:06.000000000 +0200 @@ -0,0 +1,234 @@ +/* + * linux/arch/arm/mach-at91sam9261/devices.c + * + * Copyright (C) 2005 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#define SZ_512 0x00000200 +#define SZ_256 0x00000100 +#define SZ_16 0x00000010 + +/* A generic dma mask must be set inorder for DMA relying devices to work */ +static u64 global_dmamask = 0xffffffffUL; + +static struct __initdata at91_pioline dbgu_data[] = { + {"DRXD", PIOB, 14, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"DTXD", PIOB, 15, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {0, 0, 0, 0, 0, 0}, +}; + +static struct resource dbgu_resources[] = { + { + .start = AT91C_BASE_DBGU, + .end = AT91C_BASE_DBGU + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91C_ID_SYS, + .end = AT91C_ID_SYS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device dbgu_device = { + .name = "usart", + .id = 0, + .num_resources = ARRAY_SIZE(dbgu_resources), + .dev = { + .platform_data = &dbgu_data, + }, + .resource = dbgu_resources, +}; + +static struct at91_pioline macb_pio[] = { + {"ERXDV", PIOA, 17, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"ETXCK", PIOA, 19, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"ECRS" , PIOA, 28, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, + {"ETX0" , PIOA, 12, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"ETX1" , PIOA, 13, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"ERX0", PIOA, 14, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"ERX1", PIOA, 15, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"ERXER", PIOA, 18, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"ETXER", PIOA, 22, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, + {"ETXEN", PIOA, 16, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"EMDC", PIOA, 20, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"EMDIO", PIOA, 21, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + +// {"E_F100", PIOE, 31, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"MDINTR", PIOC, 12, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {NULL, 0, 0, 0, 0, 0}, +}; + + +static struct __initdata at91_eth_pdata macb_data = { + .phy_id = 0, + .pio_data = macb_pio, +}; + + +static struct resource usb_ohci_resource[] = { + /* order *IS* significant */ + { + .start = AT91C_BASE_UHP, + .end = AT91C_BASE_UHP + SZ_1M - 1, + .flags = IORESOURCE_MEM, + }, { + .start = AT91C_ID_UHP, + .end = AT91C_ID_UHP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usb_ohci_device = { + .name = "usb-ohci", + .id = 0, + .dev = { + .dma_mask = &global_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = usb_ohci_resource, + .num_resources = ARRAY_SIZE(usb_ohci_resource), +}; + +static struct resource macb_resource[] = { + /* order *IS* significant */ + { + .start = AT91C_BASE_EMAC, + .end = AT91C_BASE_EMAC + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = AT91C_ID_EMAC, + .end = AT91C_ID_EMAC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device macb_device = { + .name = "macb", + .id = 0, + .dev = { + .dma_mask = &global_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &macb_data, + }, + .resource = macb_resource, + .num_resources = ARRAY_SIZE(macb_resource), +}; + + +static struct __initdata at91_pioline spi0_data[] = { + {"MISO0", PIOA, 0, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"MOSI0", PIOA, 1, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"SPCK0", PIOA, 2, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {0, 0, 0, 0, 0, 0}, +}; + +static struct resource spi0_resources[] = { + { + .start = AT91C_BASE_SPI0, + .end = AT91C_BASE_SPI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91C_ID_SPI0, + .end = AT91C_ID_SPI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device spi0_device = { + .name = "spi", + .id = 0, + .num_resources = ARRAY_SIZE(spi0_resources), + .dev = { + .platform_data = &spi0_data, + }, + .resource = spi0_resources, +}; + +static struct __initdata at91_pioline spi1_data[] = { + {"MISO1", PIOB, 0, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"MOSI1", PIOB, 1, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"SPCK1", PIOB, 2, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {0, 0, 0, 0, 0, 0}, +}; + +static struct resource spi1_resources[] = { + { + .start = AT91C_BASE_SPI1, + .end = AT91C_BASE_SPI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91C_ID_SPI1, + .end = AT91C_ID_SPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device spi1_device = { + .name = "spi", + .id = 1, + .num_resources = ARRAY_SIZE(spi1_resources), + .dev = { + .platform_data = &spi1_data, + }, + .resource = spi1_resources, +}; + +static struct platform_device *at91sam9260_devices[] __initdata = { + &dbgu_device, + &macb_device, + &usb_ohci_device, + &spi0_device, + &spi1_device, +/* + &usart0_device, + &usart1_device, + &usart2_device, + &usb_ohci_device, +*/ +}; + +static int __init at91sam9260_device_init(void) +{ +// at91_add_device_udc(); + return platform_add_devices(at91sam9260_devices, ARRAY_SIZE(at91sam9260_devices)); +} + +arch_initcall(at91sam9260_device_init); + +const struct platform_device *platform_get_device(const char *name, int id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(at91sam9260_devices); i++) { + if ((at91sam9260_devices[i]->id == id) && + (strcmp(at91sam9260_devices[i]->name, name) == 0)) + return at91sam9260_devices[i]; + } + return NULL; +} diff -Nur linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/gpio.c linux-2.6.15.4/arch/arm/mach-at91sam9260/gpio.c --- linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/gpio.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.15.4/arch/arm/mach-at91sam9260/gpio.c 2006-08-09 17:55:29.000000000 +0200 @@ -0,0 +1,328 @@ + + +/* + * linux/arch/arm/mach-at91sam9261/gpio.c + * + * Copyright (C) 2005 M. Amine SAYA, 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 as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#define AT91_PIOA 0x400 +#define AT91_PIOB 0x600 +#define AT91_PIOC 0x800 + +static const u32 pio_controller_offset[4] = { + AT91_PIOA, + AT91_PIOB, + AT91_PIOC, +}; + + +/*--------------------------------------------------------------------------*/ + +/* Not all hardware capabilities are exposed through these calls; they + * only encapsulate the most common features and modes. (So if you + * want to change signals in groups, do it directly.) + * + * Bootloaders will usually handle some of the pin multiplexing setup. + * The intent is certainly that by the time Linux is fully booted, all + * pins should have been fully initialized. These setup calls should + * only be used by board setup routines, or possibly in driver probe(). + * + * For bootloaders doing all that setup, these calls could be inlined + * as NOPs so Linux won't duplicate any setup code + */ + + +/* + * mux the pin to the corresponding internal peripheral role. + */ + + +void at91_gpio_periph_enable (unsigned int pio_va_base, + unsigned char pin, + unsigned char peripheral, + unsigned char use_pullup, + unsigned char use_filter) +{ + unsigned int mask = pin_to_mask(pin); + + writel(mask, (pio_va_base + PIO_IDR)); + + if(use_pullup) + writel(mask, (pio_va_base + PIO_PPUER)); + else + writel(mask, (pio_va_base + PIO_PPUDR)); + + switch (peripheral) + { + case 1: + writel(mask, (pio_va_base + PIO_BSR)); + break; + case 0: + default: + writel(mask, (pio_va_base + PIO_ASR)); + break; + } + + /* The Peripheral controls the pin (pio disabled) */ + writel(mask, (pio_va_base + PIO_PDR)); +} + + +EXPORT_SYMBOL(at91_gpio_periph_enable); + +void at91_gpio_configure (unsigned int pio_va_base, + unsigned char pin, + unsigned char in_out, + unsigned char use_pullup, + unsigned char use_filter) +{ + unsigned int mask = pin_to_mask(pin); + + /* The PIO controls the pin (periph disabled) */ + writel(mask, (pio_va_base + PIO_PER)); + + if(in_out) { /* the pin is an input */ + writel(mask, (pio_va_base + PIO_ODR)); + } + else { /* the pin is an output */ + writel(mask, (pio_va_base + PIO_OER)); + } + + if(use_pullup) + writel(mask, (pio_va_base + PIO_PPUER)); + else + writel(mask, (pio_va_base + PIO_PPUDR)); +} + + +EXPORT_SYMBOL(at91_gpio_configure); + +void at91_gpio_set_level (unsigned int pio_va_base, unsigned int pin, unsigned int level) +{ + unsigned int mask = pin_to_mask(pin); + + // This is just a sanity action to force a pin + // to output before driving it. + writel(mask, pio_va_base + PIO_PER); + writel(mask, pio_va_base + PIO_OER); + + if (level) + writel(mask, pio_va_base + PIO_SODR); + else // pin should be cleared + writel(mask, pio_va_base + PIO_CODR); + +} + + +EXPORT_SYMBOL(at91_gpio_set_level); + +unsigned int at91_gpio_get_level (unsigned int pio_va_base, unsigned int pin) +{ + unsigned int mask = pin_to_mask(pin); + + + // This is just a sanity action to force a pin + // to input before reading it. + writel(mask, pio_va_base + PIO_PER); + writel(mask, pio_va_base + PIO_ODR); + + return (readl(pio_va_base + PIO_PDSR) & mask); +} + + +EXPORT_SYMBOL(at91_gpio_get_level); + + +int at91_device_pio_setup (struct at91_pioline *pPin) { + + if(!pPin) { + printk(KERN_ERR "Define the PIO muxing of this device first !!\n"); + return -ENODEV; + } + + /* Sets all the pio muxing of the corresponding device as defined in its platform_data struct */ + while (pPin->pin_name) + { + if ((pPin->pio_ctrl_id != AT91C_ID_PIOA) && + (pPin->pio_ctrl_id != AT91C_ID_PIOB) && + (pPin->pio_ctrl_id != AT91C_ID_PIOC)) { + printk(KERN_ERR "Bad PIO controler ID %u, correct values are {%u, %u ,%u}\n", + pPin->pio_ctrl_id, AT91C_ID_PIOA, AT91C_ID_PIOB, AT91C_ID_PIOC); + return -ENODEV; + } + if (pPin->type == TYPE_PERIPH) // PIN is in PERIPH mode + at91_gpio_periph_enable(pPin->pio_ctrl_va_base, pPin->pin_num, pPin->direction, pPin->use_pullup, pPin->use_filter); + else // PIN is in PIO mode + at91_gpio_configure(pPin->pio_ctrl_va_base, pPin->pin_num, pPin->direction, pPin->use_pullup, pPin->use_filter); + pPin++; + } + + return 0; +} + +EXPORT_SYMBOL(at91_device_pio_setup); + +static inline void __iomem *pin_to_controller(unsigned pin) +{ + void __iomem *sys_base = (void __iomem *) AT91C_VA_BASE_SYS; + + pin -= PIN_BASE; + pin /= 32; + return sys_base + pio_controller_offset[pin]; + + return NULL; +} + +static inline unsigned pin_to_mask_o(unsigned pin) +{ + pin -= PIN_BASE; + return 1 << (pin % 32); +} + +/* + * read the pin's value (works even if it's not muxed as a gpio). + */ +int at91_get_gpio_value(unsigned pin) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask_o(pin); + u32 pdsr; + + if (!pio) + return -EINVAL; + pdsr = __raw_readl(pio + PIO_PDSR); + return (pdsr & mask) != 0; +} +EXPORT_SYMBOL(at91_get_gpio_value); + +/*--------------------------------------------------------------------------*/ + + +/* Several AIC controller irqs are dispatched through this GPIO handler. + * To use any AT91_PIN_* as an externally triggered IRQ, first call + * at91_set_gpio_input() then maybe enable its glitch filter. + * Then just request_irq() with the pin ID; it works like any ARM IRQ + * handler, though it always triggers on rising and falling edges. + * + * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after + * configuring them with at91_set_a_periph() or at91_set_b_periph(). + * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering. + */ + +static void gpio_irq_mask(unsigned pin) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask_o(pin); + + if (pio) + __raw_writel(mask, pio + PIO_IDR); +} + +static void gpio_irq_unmask(unsigned pin) +{ + void __iomem *pio = pin_to_controller(pin); + unsigned mask = pin_to_mask_o(pin); + + printk("gpio_irq_unmask %d %x\n", (int) pin, (int) pio); + if (pio) + __raw_writel(mask, pio + PIO_IER); +} + +static int gpio_irq_type(unsigned pin, unsigned type) +{ + return (type == IRQT_BOTHEDGE) ? 0 : -EINVAL; +} + +static struct irqchip gpio_irqchip = { + .mask = gpio_irq_mask, + .unmask = gpio_irq_unmask, + .set_type = gpio_irq_type, +}; + +static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs *regs) +{ + unsigned pin; + struct irqdesc *gpio; + void __iomem *pio; + u32 isr; + + pio = (void __force __iomem *) desc->chipdata; + + /* temporarily mask (level sensitive) parent IRQ */ + desc->chip->ack(irq); + for (;;) { + isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR); + if (!isr) + break; + + pin = (unsigned) desc->data; + gpio = &irq_desc[pin]; + + while (isr) { + if (isr & 1) + gpio->handle(pin, gpio, regs); + pin++; + gpio++; + isr >>= 1; + } + } + desc->chip->unmask(irq); + /* now it may re-trigger */ +} + +/* call this from board-specific init_irq */ +void __init at91_gpio_irq_setup(unsigned banks) +{ + unsigned pioc, pin, id; + + if (banks > 4) + banks = 4; + for (pioc = 0, pin = PIN_BASE, id = AT91_ID_PIOA; + pioc < banks; + pioc++, id++) { + void __iomem *controller; + unsigned i; + + controller = (void __iomem *) AT91C_VA_BASE_SYS + pio_controller_offset[pioc]; + __raw_writel(~0, controller + PIO_IDR); + + set_irq_data(id, (void *) pin); + set_irq_chipdata(id, (void __force *) controller); + + for (i = 0; i < 32; i++, pin++) { + set_irq_chip(pin, &gpio_irqchip); + set_irq_handler(pin, do_simple_IRQ); + set_irq_flags(pin, IRQF_VALID); + } + + set_irq_chained_handler(id, gpio_irq_handler); + printk("set_irq_chained_handler %d\n", id); + + /* enable the PIO peripheral clock */ + at91_enable_periph_clock(id); + //at91_sys_write(AT91_PMC_PCER, 1 << id); + } + pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, banks); +} + diff -Nur linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/gpio_tgt.c linux-2.6.15.4/arch/arm/mach-at91sam9260/gpio_tgt.c --- linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/gpio_tgt.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.15.4/arch/arm/mach-at91sam9260/gpio_tgt.c 2006-08-09 10:53:17.000000000 +0200 @@ -0,0 +1,365 @@ +/* + * linux/arch/arm/mach-at91sam9260/gpio.c + * + * Copyright (C) 2005 HP Labs + * + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + + +static inline unsigned pin_to_controller(unsigned pin) +{ + return (pin - PIN_BASE) / 32; +} + +static inline unsigned pin_to_mask(unsigned pin) +{ + return 1 << ((pin - PIN_BASE) % 32); +} + + +/*--------------------------------------------------------------------------*/ + +/* Not all hardware capabilities are exposed through these calls; they + * only encapsulate the most common features and modes. (So if you + * want to change signals in groups, do it directly.) + * + * Bootloaders will usually handle some of the pin multiplexing setup. + * The intent is certainly that by the time Linux is fully booted, all + * pins should have been fully initialized. These setup calls should + * only be used by board setup routines, or possibly in driver probe(). + * + * For bootloaders doing all that setup, these calls could be inlined + * as NOPs so Linux won't duplicate any setup code + */ + + +/* + * mux the pin to the "A" internal peripheral role. + */ +int __init_or_module at91_set_A_periph(unsigned pin, int use_pullup) +{ + unsigned pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (pio >= AT91_NR_PIO) + return -EINVAL; + + at91_sys_write(PIO_IDR(pio), mask); + at91_sys_write(use_pullup ? PIO_PPUER(pio) : PIO_PPUDR(pio), mask); + at91_sys_write(PIO_ASR(pio), mask); + at91_sys_write(PIO_PDR(pio), mask); + return 0; +} +EXPORT_SYMBOL(at91_set_A_periph); + + +/* + * mux the pin to the "B" internal peripheral role. + */ +int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup) +{ + unsigned pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (pio >= AT91_NR_PIO) + return -EINVAL; + + at91_sys_write(PIO_IDR(pio), mask); + at91_sys_write((use_pullup ? PIO_PPUER(pio) : PIO_PPUDR(pio)), mask); + at91_sys_write(PIO_BSR(pio), mask); + at91_sys_write(PIO_PDR(pio), mask); + return 0; +} +EXPORT_SYMBOL(at91_set_B_periph); + + +/* + * mux the pin to the gpio controller (instead of "A" or "B" peripheral), and + * configure it for an input. + */ +int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup) +{ + unsigned pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (pio >= AT91_NR_PIO) + return -EINVAL; + + at91_sys_write(PIO_IDR(pio), mask); + at91_sys_write((use_pullup ? PIO_PPUER(pio) : PIO_PPUDR(pio)), mask); + at91_sys_write(PIO_ODR(pio), mask); + at91_sys_write(PIO_PER(pio), mask); + return 0; +} +EXPORT_SYMBOL(at91_set_gpio_input); + + +/* + * mux the pin to the gpio controller (instead of "A" or "B" peripheral), + * and configure it for an output. + */ +int __init_or_module at91_set_gpio_output(unsigned pin, int value) +{ + unsigned pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (pio >= AT91_NR_PIO) + return -EINVAL; + + at91_sys_write(PIO_IDR(pio), mask); + at91_sys_write(PIO_PPUDR(pio), mask); + at91_sys_write((value ? PIO_SODR(pio) : PIO_CODR(pio)), mask); + at91_sys_write(PIO_OER(pio), mask); + at91_sys_write(PIO_PER(pio), mask); + return 0; +} +EXPORT_SYMBOL(at91_set_gpio_output); + + +/* + * enable/disable the glitch filter; mostly used with IRQ handling. + */ +int __init_or_module at91_set_deglitch(unsigned pin, int is_on) +{ + unsigned pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (pio >= AT91_NR_PIO) + return -EINVAL; + at91_sys_write((is_on ? PIO_IFER(pio) : PIO_IFDR(pio)), mask); + return 0; +} +EXPORT_SYMBOL(at91_set_deglitch); + +/* + * enable/disable the multi-driver; This is only valid for output and + * allows the output pin to run as an open collector output. + */ +int __init_or_module at91_set_multi_drive(unsigned pin, int is_on) +{ + unsigned pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (pio >= AT91_NR_PIO) + return -EINVAL; + + at91_sys_write((is_on ? PIO_MDER(pio) : PIO_MDDR(pio)), mask); + return 0; +} +EXPORT_SYMBOL(at91_set_multi_drive); + +/*--------------------------------------------------------------------------*/ + + +/* + * assuming the pin is muxed as a gpio output, set its value. + */ +int at91_set_gpio_value(unsigned pin, int value) +{ + unsigned pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (pio >= AT91_NR_PIO) + return -EINVAL; + at91_sys_write((value ? PIO_SODR(pio) : PIO_CODR(pio)), mask); + return 0; +} +EXPORT_SYMBOL(at91_set_gpio_value); + + +/* + * read the pin's value (works even if it's not muxed as a gpio). + */ +int at91_get_gpio_value(unsigned pin) +{ + unsigned pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + u32 pdsr; + + if (pio >= AT91_NR_PIO) + return -EINVAL; + pdsr = at91_sys_read(PIO_PDSR(pio)); + return (pdsr & mask) != 0; +} +EXPORT_SYMBOL(at91_get_gpio_value); + +/* + * Configure PIO in periph mode according to the platform informations + */ +#ifdef 0 +int at91_device_pio_setup (struct at91_pioline *pio_desc) +{ + unsigned pio, pin = 0; + + if(!pio_desc) { + printk(KERN_ERR "Define the PIO muxing of this device first !!\n"); + return 0; + } + + /* Sets all the pio muxing of the corresponding device as defined in its platform_data struct */ + while (pio_desc->pin_name) { + pio = pin_to_controller( pio_desc->pin_num); + if (pio >= AT91_NR_PIO) + printk(KERN_ERR "Bad pin number %u for pio %s in platform description\n", + pio_desc->pin_num, pio_desc->pin_name); + else if (pio_desc->type == ATM_PIO_PERIPH_A) + at91_set_A_periph(pio_desc->pin_num, + (pio_desc->attribute & ATM_PIO_PULLUP) ? 1 : 0); + else if (pio_desc->type == ATM_PIO_PERIPH_B) + at91_set_B_periph(pio_desc->pin_num, + (pio_desc->attribute & ATM_PIO_PULLUP) ? 1 : 0); + else if (pio_desc->type == ATM_PIO_INPUT) { + at91_set_deglitch(pio_desc->pin_num, + (pio_desc->attribute & ATM_PIO_DEGLITCH)? 1 : 0); + at91_set_gpio_input(pio_desc->pin_num, + (pio_desc->attribute & ATM_PIO_PULLUP) ? 1 : 0); + } + else if(pio_desc->type == ATM_PIO_OUTPUT) { + at91_set_multi_drive(pio_desc->pin_num, (pio_desc->attribute & ATM_PIO_OPENDRAIN) ? 1 : 0); + at91_set_gpio_output(pio_desc->pin_num, pio_desc->dft_value); + } + else + printk(KERN_ERR "Bad pin type %u for pio %s in platform description\n", + pio_desc->pin_num, pio_desc->pin_name); + ++pin; + ++pio_desc; + } + return pin; +} + +EXPORT_SYMBOL(at91_device_pio_setup); +#endif + +/*--------------------------------------------------------------------------*/ + + +/* Several AIC controller irqs are dispatched through this GPIO handler. + * To use any AT91_PIN_* as an externally triggered IRQ, first call + * at91_set_gpio_input() then maybe enable its glitch filter. + * Then just request_irq() with the pin ID; it works like any ARM IRQ + * handler, though it always triggers on rising and falling edges. + * + * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after + * configuring them with at91_set_a_periph() or at91_set_b_periph(). + * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering. + */ + +static void gpio_irq_mask(unsigned pin) +{ + unsigned pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (pio < AT91_NR_PIO) + at91_sys_write(PIO_IDR(pio), mask); +} + +static void gpio_irq_unmask(unsigned pin) +{ + unsigned pio = pin_to_controller(pin); + unsigned mask = pin_to_mask(pin); + + if (pio < AT91_NR_PIO) + at91_sys_write(PIO_IER(pio), mask); +} + +static int gpio_irq_type(unsigned pin, unsigned type) +{ + return (type == IRQT_BOTHEDGE) ? 0 : -EINVAL; +} + +static struct irqchip gpio_irqchip = { + .mask = gpio_irq_mask, + .unmask = gpio_irq_unmask, + .set_type = gpio_irq_type, +}; + +static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs *regs) +{ + unsigned pin; + struct irqdesc *gpio; + unsigned pio; + u32 isr; + + pio = (unsigned __force) desc->chipdata; + + /* temporarily mask (level sensitive) parent IRQ */ + desc->chip->ack(irq); + for (;;) { + isr = at91_sys_read(PIO_ISR(pio)) & at91_sys_read(PIO_IMR(pio)); + if (!isr) + break; + + pin = (unsigned) desc->data; + gpio = &irq_desc[pin]; + + while (isr) { + if (isr & 1) { + if (unlikely(gpio->disable_depth)) { + /* + * The core ARM interrupt handler lazily disables IRQs so + * another IRQ must be generated before it actually gets + * here to be disabled on the GPIO controller. + */ + gpio_irq_mask(pin); + } + else { + gpio->handle(pin, gpio, regs); + } + } + pin++; + gpio++; + isr >>= 1; + } + } + desc->chip->unmask(irq); + /* now it may re-trigger */ +} + +/* call this from board-specific init_irq */ +void __init at91_gpio_irq_setup(unsigned banks) +{ + unsigned pioc, pin, id; + + if (banks > AT91_NR_PIO) + banks = AT91_NR_PIO; + for (pioc = 0, pin = PIN_BASE, id = AT91_ID_PIOA; + pioc < banks; + pioc++, id++) { + unsigned pio = pin_to_controller(pin); + unsigned i; + + at91_sys_write(PIO_IDR(pio), ~0); + + set_irq_data(id, (void *) pin); + set_irq_chipdata(id, (void __force *) pioc); + + for (i = 0; i < 32; i++, pin++) { + set_irq_chip(pin, &gpio_irqchip); + set_irq_handler(pin, do_simple_IRQ); + set_irq_flags(pin, IRQF_VALID); + } + + set_irq_chained_handler(id, gpio_irq_handler); + + /* enable the PIO peripheral clock */ + at91_sys_write(PMC_PCER, 1 << id); + } + pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, banks); +} diff -Nur linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/irq.c linux-2.6.15.4/arch/arm/mach-at91sam9260/irq.c --- linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/irq.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.15.4/arch/arm/mach-at91sam9260/irq.c 2006-08-09 10:53:08.000000000 +0200 @@ -0,0 +1,123 @@ +/* + * linux/arch/arm/mach-at91sam9260/irq.c + * + * Copyright (C) 2005 M. Amine SAYA, 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define readreg_aic(offset) readl(AT91C_VA_BASE_AIC + offset) +#define writereg_aic(value, offset) writel(value, (AT91C_VA_BASE_AIC + offset)) + +/* Interrupt configuration */ +static volatile unsigned int at91sam9260_irq_smr[] __initdata = { + (AT91_SMR_FIQ), /*0 FIQ */ + (AT91_SMR_SYS), /*1 System Peripherals */ + (AT91_SMR_PIOA), /*2 PIO A */ + (AT91_SMR_PIOB), /*3 PIO B */ + (AT91_SMR_PIOC), /*4 PIO C */ + 0, /*5 */ + (AT91_SMR_US0), /*6 USART 0 */ + (AT91_SMR_US1), /*7 USART 1 */ + (AT91_SMR_US2), /*8 USART 2 */ + (AT91_SMR_MCI), /*9 Multimedia Card */ + (AT91_SMR_UDP), /*10 USB Device */ + (AT91_SMR_TWI), /*11 Two-wire interface */ + (AT91_SMR_SPI0), /*12 SPI 0 */ + (AT91_SMR_SPI1), /*13 SPI 1 */ + (AT91_SMR_SSC0), /*14 Sync Serial 0 */ + 0, /*15 */ + 0, /*16 */ + (AT91_SMR_TC0), /*17 TC 0 */ + (AT91_SMR_TC1), /*18 TC 1 */ + (AT91_SMR_TC2), /*19 TC 2 */ + (AT91_SMR_UHP), /*20 USB Host */ + (AT91_SMR_EMAC), /*21 EMAC */ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + (AT91_SMR_IRQ0), /* IRQ 0 */ + (AT91_SMR_IRQ1), /* IRQ 1 */ + (AT91_SMR_IRQ2), /* IRQ 2 */ +}; + +static void at91sam9260_mask_irq(unsigned int irq) +{ + /* Disable interrupt on AIC */ + writereg_aic(1 << irq, AIC_IDCR); +} + +static void at91sam9260_unmask_irq(unsigned int irq) +{ + /* Enable interrupt on AIC */ + writereg_aic(1 << irq, AIC_IECR); +} + +static struct irqchip at91sam9260_irq_chip = { + .ack = at91sam9260_mask_irq, + .mask = at91sam9260_mask_irq, + .unmask = at91sam9260_unmask_irq, +}; + +void at91sam9260_clear_irq(unsigned int irq) +{ + /* Clear an interrupt on AIC */ + writereg_aic(1 << irq, AIC_ICCR); +} + +void __init at91sam9260_init_irq(void) +{ + int i; + + /* + * The IVR is used by macro get_irqnr_and_base to read and verify. + * The irq number is NR_IRQS when a spurious interrupt has occured. + */ + for (i = 0; i < NR_AIC_IRQS; i++) { + /* Put irq number in Source Vector Register: */ + writereg_aic(i, (AIC_SVR + (i<<2))); + /* Store the Source Mode Register as defined in table above */ + writereg_aic(at91sam9260_irq_smr[i], (AIC_SMR + (i<<2))); + set_irq_chip(i, &at91sam9260_irq_chip); + set_irq_handler(i, do_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 */ + if (i < 8) + writereg_aic(readreg_aic(AIC_EOICR), AIC_EOICR); + } + + /* + * Spurious Interrupt ID in Spurious Vector Register is NR_IRQS + * When there is no current interrupt, the IRQ Vector Register reads the value stored in AIC_SPU + */ + writereg_aic(NR_AIC_IRQS, AIC_SPU); + + /* No debugging in AIC: Debug (Protect) Control Register */ + writereg_aic(0, AIC_DCR); + + /* Disable and clear all interrupts initially */ + writereg_aic(0xFFFFFFFF, AIC_IDCR); + writereg_aic(0xFFFFFFFF, AIC_ICCR); +} + diff -Nur linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/Makefile linux-2.6.15.4/arch/arm/mach-at91sam9260/Makefile --- linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/Makefile 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.15.4/arch/arm/mach-at91sam9260/Makefile 2006-08-09 10:53:09.000000000 +0200 @@ -0,0 +1,9 @@ +# +# Makefile for the linux kernel. +# + +# Common support +obj-y := board-ek.o core.o irq.o time.o gpio.o devices.o pmc.o +obj-m := +obj-n := +obj- := diff -Nur linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/Makefile.boot linux-2.6.15.4/arch/arm/mach-at91sam9260/Makefile.boot --- linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/Makefile.boot 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.15.4/arch/arm/mach-at91sam9260/Makefile.boot 2006-08-09 10:53:10.000000000 +0200 @@ -0,0 +1,11 @@ +# Note: the following conditions must always be true: +# ZRELADDR == virt_to_phys(TEXTADDR) +# PARAMS_PHYS must be within 4MB of ZRELADDR +# INITRD_PHYS must be in RAM + +zreladdr-y := 0x20008000 +params_phys-y := 0x20000100 +initrd_phys-y := 0x20410000 + +#params_phys-y := 0x00000100 +#initrd_phys-y := 0x00800000 diff -Nur linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/pmc.c linux-2.6.15.4/arch/arm/mach-at91sam9260/pmc.c --- linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/pmc.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.15.4/arch/arm/mach-at91sam9260/pmc.c 2006-08-09 17:49:52.000000000 +0200 @@ -0,0 +1,54 @@ +/* + * linux/arch/arm/mach-at91sam9261/pmc.c + * + * Copyright (C) 2005 M. Amine SAYA, 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#define readreg_pmc(offset) readl(AT91C_VA_BASE_PMC + offset) +#define writereg_pmc(value, offset) writel(value, (AT91C_VA_BASE_PMC + offset)) + + +void at91_disable_periph_clock(unsigned int irq) +{ + /* Disable the corresponding peripheral clock */ + writereg_pmc(1 << irq, PMC_PCDR); +} +EXPORT_SYMBOL(at91_disable_periph_clock); + +void at91_enable_periph_clock(unsigned int irq) +{ + /* Enable the corresponding peripheral clock */ + writereg_pmc(1 << irq, PMC_PCER); +} +EXPORT_SYMBOL(at91_enable_periph_clock); + +void at91_disable_system_clock(unsigned int mask) +{ + /* Disable the corresponding system clock */ + writereg_pmc(mask, PMC_SCDR); +} +EXPORT_SYMBOL(at91_disable_system_clock); + +void at91_enable_system_clock(unsigned int mask) +{ + /* Enable the corresponding system clock */ + writereg_pmc(mask, PMC_SCER); +} +EXPORT_SYMBOL(at91_enable_system_clock); + diff -Nur linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/time.c linux-2.6.15.4/arch/arm/mach-at91sam9260/time.c --- linux-2.6.15.4-orig/arch/arm/mach-at91sam9260/time.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.15.4/arch/arm/mach-at91sam9260/time.c 2006-08-09 10:53:12.000000000 +0200 @@ -0,0 +1,105 @@ +/* + * linux/arch/arm/mach-at91sam9260/time.c + * + * Copyright (C) 2005 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define readreg_pitc(offset) readl(AT91C_VA_BASE_PITC + offset) +#define writereg_pitc(value, offset) writel(value, (AT91C_VA_BASE_PITC + offset)) + +#define READ_PIT_CPIV(x) ((x) & AT91C_PITC_CPIV) +#define READ_PIT_PICNT(x) (((x) & AT91C_PITC_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 at91sam9260_gettimeoffset(void) +{ + unsigned long nb_us = ((READ_PIT_CPIV(readreg_pitc(PITC_PIIR)) * 1000000) / CLOCK_TICK_RATE) + ((READ_PIT_PICNT(readreg_pitc(PITC_PIIR)) * 1000000)/HZ); + return (nb_us); +} + +/* + * IRQ handler for the timer. + */ +static irqreturn_t at91sam9260_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + volatile unsigned int nb_ticks; + + if (readreg_pitc(PITC_PISR) & AT91C_PITC_PITS) { /* This is a shared interrupt */ + write_seqlock(&xtime_lock); + + /* Get number to ticks performed before interrupt and clear PIT interrupt */ + nb_ticks = READ_PIT_PICNT(readreg_pitc(PITC_PIVR)); + + do { + timer_tick(regs); + nb_ticks--; + } while(nb_ticks); + + write_sequnlock(&xtime_lock); + + return IRQ_HANDLED; + } else { + return IRQ_NONE; /* not handled */ + }; +} + +static struct irqaction at91sam9260_timer_irq = { + .name = "AT91SAM9260 Timer", + .flags = SA_SHIRQ | SA_INTERRUPT | SA_TIMER, + .handler= at91sam9260_timer_interrupt +}; + +/* + * Set up timer interrupt. + */ +void __init at91sam9260_timer_init(void) +{ + /* Enable timer */ + writereg_pitc(AT91C_PITC_PITEN, PITC_PIMR); + + /* Clear any pending interrupts */ + readreg_pitc(PITC_PIVR); + + /* Set Period Interval timer and enable its interrupt */ + writereg_pitc((readreg_pitc(PITC_PIMR) | ((LATCH & AT91C_PITC_CPIV) | AT91C_PITC_PITIEN)), PITC_PIMR); + + /* Make IRQs happen for the system timer. */ + setup_irq(AT91C_ID_SYS, &at91sam9260_timer_irq); + + /* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */ + tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE; + + return; +} + +struct sys_timer at91sam9260_timer = { + .init = at91sam9260_timer_init, + .offset = at91sam9260_gettimeoffset, +}; + diff -Nur linux-2.6.15.4-orig/arch/arm/mach-at91sam9261/board-ek.c linux-2.6.15.4/arch/arm/mach-at91sam9261/board-ek.c --- linux-2.6.15.4-orig/arch/arm/mach-at91sam9261/board-ek.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.15.4/arch/arm/mach-at91sam9261/board-ek.c 2006-08-09 10:44:57.000000000 +0200 @@ -0,0 +1,89 @@ +/* + * linux/arch/arm/mach-at91sam9261/board-ek.c + * + * Copyright (C) 2005 SAN People + * + * Epson S1D framebuffer glue code is: + * Copyright (C) 2005 Thibaut VARENE + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + + +extern void __init at91sam9261_init_irq(unsigned int priority[NR_IRQS]); +extern void __init at91_gpio_irq_setup(unsigned banks); + +static void __init ek_init_irq(void) +{ + /* Initialize AIC controller */ + at91sam9261_init_irq(NULL); + + /* Set up the GPIO interrupts */ + at91_gpio_irq_setup(AT91_NR_PIO); +} + +extern void __init at91sam9261_map_io(void); + +static void __init ek_map_io(void) +{ + at91sam9261_map_io(); + + /* Initialize clocks: 18.432 MHz crystal */ + //at91_clock_init(AT91C_MASTER_CLOCK); + +} + +#if 0 +static struct at91_udc_data __initdata ek_udc_data = { + .vbus_pin = AT91_PIN_PB29, + .pullup_pin = AT91_PIN_PB30, +}; + +static void __init ek_board_init(void) +{ + /* USB Device */ + at91_add_device_udc(&ek_udc_data); +} +#endif + +MACHINE_START(AT91SAM9261EK, "ATMEL AT91SAM9261") + .phys_ram = AT91_SDRAM_BASE, + .phys_io = AT91C_BASE_AIC, + .io_pg_offst = ((AT91C_VA_BASE_SYS) >> 18) & 0xfffc, + .boot_params = AT91_SDRAM_BASE + 0x100, + .map_io = ek_map_io, + .init_irq = ek_init_irq, + .timer = &at91sam9261_timer, +MACHINE_END diff -Nur linux-2.6.15.4-orig/arch/arm/mach-at91sam9261/core.c linux-2.6.15.4/arch/arm/mach-at91sam9261/core.c --- linux-2.6.15.4-orig/arch/arm/mach-at91sam9261/core.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.15.4/arch/arm/mach-at91sam9261/core.c 2006-08-09 10:44:57.000000000 +0200 @@ -0,0 +1,74 @@ +/* + * linux/arch/arm/mach-at91sam9261/core.c + * + * Copyright (C) 2005 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 +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +extern void __init at91sam9261_init_irq(void); + + +/* + * System peripheral registers mapped at virtual address. + */ + +static struct map_desc at91sam9261_io_desc[] __initdata = { + { + .virtual = AT91C_VA_BASE_SYS, + .pfn = __phys_to_pfn(AT91C_BASE_AIC), + .length = SZ_4K, + .type = MT_DEVICE + }, + { + .virtual = AT91C_VA_BASE_EBI, + .pfn = __phys_to_pfn(AT91C_BASE_EBI), + .length = SZ_4K, + .type = MT_DEVICE + }, + { + .virtual = AT91C_VA_BASE_UDP, + .pfn = __phys_to_pfn(AT91_BASE_UDP), + .length = SZ_16K, + .type = MT_DEVICE + } +}; + + +void __init at91sam9261_map_io(void) +{ + iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc)); +} + +/* +MACHINE_START(AT91SAM9261EK, "ATMEL AT91SAM9261") + .phys_ram = AT91_SDRAM_BASE, + .phys_io = AT91C_BASE_AIC, + .io_pg_offst = ((AT91C_VA_BASE_SYS) >> 18) & 0xfffc, + .boot_params = 0x00000000, + .map_io = at91sam9261_map_io, + .init_irq = at91sam9261_init_irq, + .timer = &at91sam9261_timer, +// .init_machine = at91sam9261_init_machine, +MACHINE_END +*/ diff -Nur linux-2.6.15.4-orig/arch/arm/mach-at91sam9261/devices.c linux-2.6.15.4/arch/arm/mach-at91sam9261/devices.c --- linux-2.6.15.4-orig/arch/arm/mach-at91sam9261/devices.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.6.15.4/arch/arm/mach-at91sam9261/devices.c 2006-08-09 10:44:57.000000000 +0200 @@ -0,0 +1,516 @@ +/* + * linux/arch/arm/mach-at91sam9261/devices.c + * + * Copyright (C) 2005 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define SZ_512 0x00000200 +#define SZ_256 0x00000100 +#define SZ_16 0x00000010 + +/* A generic dma mask must be set inorder for DMA relying devices to work */ +static u64 global_dmamask = 0xffffffffUL; + +static struct __initdata at91_pioline dbgu_data[] = { + {"DRXD", PIOA, 9, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"DTXD", PIOA, 10, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {0, 0, 0, 0, 0, 0}, +}; + +static struct resource dbgu_resources[] = { + { + .start = AT91C_BASE_DBGU, + .end = AT91C_BASE_DBGU + SZ_512 - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91C_ID_SYS, + .end = AT91C_ID_SYS, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device dbgu_device = { + .name = "usart", + .id = 0, + .num_resources = ARRAY_SIZE(dbgu_resources), + .dev = { + .platform_data = &dbgu_data, + }, + .resource = dbgu_resources, +}; + +static struct __initdata at91_pioline usart0_data[] = { + {"TXD0", PIOC, 8, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"RXD0", PIOC, 9, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"SCK0", PIOC, 10, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, + {"CTS0", PIOC, 11, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"RTS0", PIOA, 23, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {0, 0, 0, 0, 0, 0}, +}; + +static struct resource usart0_resources[] = { + { + .start = AT91C_BASE_US0, + .end = AT91C_BASE_US0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91C_ID_US0, + .end = AT91C_ID_US0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usart0_device = { + .name = "usart", + .id = 1, + .num_resources = ARRAY_SIZE(usart0_resources), + .dev = { + .platform_data = &usart0_data, + }, + .resource = usart0_resources, +}; + +static struct __initdata at91_pioline usart1_data[] = { + {"TXD1", PIOC, 12, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"RXD1", PIOC, 13, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, +#ifndef CONFIG_TFT_AT91 + {"SCK1", PIOA, 11, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, + {"RTS1", PIOA, 12, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, + {"CTS1", PIOA, 13, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, +#endif + {0, 0, 0, 0, 0, 0}, +}; + +static struct resource usart1_resources[] = { + { + .start = AT91C_BASE_US1, + .end = AT91C_BASE_US1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91C_ID_US1, + .end = AT91C_ID_US1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usart1_device = { + .name = "usart", + .id = 2, + .num_resources = ARRAY_SIZE(usart1_resources), + .dev = { + .platform_data = &usart1_data, + }, + .resource = usart1_resources, +}; + +static struct __initdata at91_pioline usart2_data[] = { + {"TXD2", PIOC, 14, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"RXD2", PIOC, 15, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"SCK2", PIOA, 14, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, + {"RTS2", PIOA, 15, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, + {"CTS2", PIOA, 16, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, + {0, 0, 0, 0, 0, 0}, +}; + +static struct resource usart2_resources[] = { + { + .start = AT91C_BASE_US2, + .end = AT91C_BASE_US2 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91C_ID_US2, + .end = AT91C_ID_US2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usart2_device = { + .name = "usart", + .id = 3, + .num_resources = ARRAY_SIZE(usart2_resources), + .dev = { + .platform_data = &usart2_data, + }, + .resource = usart2_resources, +}; + +static struct __initdata at91_pioline spi0_data[] = { + {"MISO0", PIOA, 0, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"MOSI0", PIOA, 1, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"SPCK0", PIOA, 2, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {0, 0, 0, 0, 0, 0}, +}; + +static struct resource spi0_resources[] = { + { + .start = AT91C_BASE_SPI0, + .end = AT91C_BASE_SPI0 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91C_ID_SPI0, + .end = AT91C_ID_SPI0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device spi0_device = { + .name = "spi", + .id = 0, + .num_resources = ARRAY_SIZE(spi0_resources), + .dev = { + .platform_data = &spi0_data, + }, + .resource = spi0_resources, +}; + +static struct __initdata at91_pioline spi1_data[] = { + {"MISO1", PIOB, 30, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"MOSI1", PIOB, 31, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"SPCK1", PIOB, 29, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {0, 0, 0, 0, 0, 0}, +}; + +static struct resource spi1_resources[] = { + { + .start = AT91C_BASE_SPI1, + .end = AT91C_BASE_SPI1 + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91C_ID_SPI1, + .end = AT91C_ID_SPI1, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device spi1_device = { + .name = "spi", + .id = 1, + .num_resources = ARRAY_SIZE(spi1_resources), + .dev = { + .platform_data = &spi1_data, + }, + .resource = spi1_resources, +}; + +static struct __initdata at91_pioline lcdc_data[] = { + {"LCDHSYNC", PIOB, 1, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDDOTCK", PIOB, 2, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDDEN" , PIOB, 3, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDCC" , PIOB, 4, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD2" , PIOB, 7, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD3" , PIOB, 8, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD4" , PIOB, 9, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD5" , PIOB, 10, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD6" , PIOB, 11, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD7" , PIOB, 12, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD10" , PIOB, 15, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD11" , PIOB, 16, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD12" , PIOB, 17, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD13" , PIOB, 18, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD14" , PIOB, 19, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD15" , PIOB, 20, TYPE_PERIPH, PERIPH_A, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD18" , PIOB, 23, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD19" , PIOB, 24, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD20" , PIOB, 25, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD21" , PIOB, 26, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD22" , PIOB, 27, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, + {"LCDD23" , PIOB, 28, TYPE_PERIPH, PERIPH_B, NO_PULL_UP, NO_GLITCH_FLT}, + {"POWCTRL" , PIOA, 12, TYPE_PIO , OUTPUT_MODE, NO_PULL_UP, NO_GLITCH_FLT}, + {0, 0, 0, 0, 0, 0}, +}; + +static struct resource lcdc_resources[] = { + { + .start = AT91C_BASE_LCDC, + .end = AT91C_BASE_LCDC + SZ_4K - 1, + .flags = IORESOURCE_MEM, + }, + { + .start = AT91C_ID_LCDC, + .end = AT91C_ID_LCDC, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device lcdc_device = { + .name = "sidsa-lcdc", + .id = 0, + .num_resources = ARRAY_SIZE(lcdc_resources), + .resource = lcdc_resources, + .dev = { + .dma_mask = &global_dmamask, + .coherent_dma_mask = 0xffffffff, + .platform_data = &lcdc_data, + }, +}; + +/* External Touch screen controller. */ +static struct __initdata at91_pioline tsc_data[] = { + {"BUSY", PIOA, 11, TYPE_PIO, INPUT_MODE, NO_PULL_UP, NO_GLITCH_FLT}, + {"NPENIRQ", PIOC, 2, TYPE_PIO, INPUT_MODE, PULLED_UP, NO_GLITCH_FLT}, + {0, 0, 0, 0, 0, 0}, +}; +/* It only has an irq line.*/ +static struct resource tsc_resources[] = { + { + .start = AT91C_ID_IRQ0, + .end = AT91C_ID_IRQ0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device tsc_device = { + .name = "ts", + .id = 0, + .num_resources = ARRAY_SIZE(tsc_resources), + .dev = { + .platform_data = &tsc_data, + }, + .resource = tsc_resources, +}; + + +static struct resource usb_ohci_resource[] = { + /* order *IS* significant */ + { + .start = AT91C_BASE_UHP, + .end = AT91C_BASE_UHP + SZ_1M - 1, + .flags = IORESOURCE_MEM, + }, { + .start = AT91C_ID_UHP, + .end = AT91C_ID_UHP, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device usb_ohci_device = { + .name = "usb-ohci", + .id = 0, + .dev = { + .dma_mask = &global_dmamask, + .coherent_dma_mask = 0xffffffff, + }, + .resource = usb_ohci_resource, + .num_resources = ARRAY_SIZE(usb_ohci_resource), +}; + + +#ifdef CONFIG_USB_GADGET_AT91 + + +static struct at91_udc_data __initdata ek_udc_data = { + .vbus_pin = AT91_PIN_PB29, + .pullup_pin = AT91_PIN_PB30, +}; + +static struct resource at91_udc_resources[] = { + { + .start = AT91_BASE_UDP, + .end = AT91_BASE_UDP + SZ_16K - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device at91sam9261_udc_device = { + .name = "at91_udc", + .id = -1, + .dev = { + .platform_data = &ek_udc_data, + }, + .resource = at91_udc_resources, + .num_resources = ARRAY_SIZE(at91_udc_resources), +}; + +void __init at91_add_device_udc(void) +{ + struct at91_udc_data *data = at91sam9261_udc_device.dev.platform_data; + + if (data->vbus_pin) { + at91_gpio_configure(AT91C_VA_BASE_PIOB, 29, 1, 0, 0); + } + if (data->pullup_pin) { + at91_gpio_configure(AT91C_VA_BASE_PIOB, 30, 0, 0, 0); + } + at91_enable_periph_clock(AT91C_ID_PIOB); + + platform_device_register(&at91sam9261_udc_device); +} + +#else +void __init at91_add_device_udc(void) {} +#endif + +#ifdef CONFIG_DM9000 +#include + +#define AT91C_EBI_CS2 ((char *) 0x30000000) // EBI Chip Select 2 base address +/* -------------------------------------------------------------------- + * DM9000 ethernet device + * -------------------------------------------------------------------- */ +static struct resource dm9000_resource[] = { + [0] = { + .start = AT91C_EBI_CS2, + .end = AT91C_EBI_CS2 + 3, + .flags = IORESOURCE_MEM + }, + [1] = { + .start = AT91C_EBI_CS2 + 0x44, + .end = AT91C_EBI_CS2 + 0xFF, + .flags = IORESOURCE_MEM + }, + [2] = { + .start = AT91_PIN_PC11, + .end = AT91_PIN_PC11, + .flags = IORESOURCE_IRQ + } + +}; + + +/* for the moment we limit ourselves to 16bit IO until some + * better IO routines can be written and tested +*/ + +/* for the moment we limit ourselves to 16bit IO until some + * better IO routines can be written and tested +*/ + +struct dm9000_plat_data dm9000_platdata = { + .flags = DM9000_PLATF_16BITONLY, +}; + +static struct platform_device dm9000_device = { + .name = "dm9000", + .id = 0, + .num_resources = ARRAY_SIZE(dm9000_resource), + .resource = dm9000_resource, + .dev = { + .platform_data = &dm9000_platdata, + } +}; +// SMC Chip Select 2 Timmings for DM9000 (davicom). +// These timmings were calculated for MASTER_CLOCK = 100000000 +// according to DM9000 timmings. Refer to SMC user interface +// in AT91SAM9261 datasheet to learn how to regenerate these +// values in case MASTER_CLOCK changes. + +#define AT91C_DM9000_NWE_SETUP (2 << 0) +#define AT91C_DM9000_NCS_WR_SETUP (0 << 8) +#define AT91C_DM9000_NRD_SETUP (2 << 16) +#define AT91C_DM9000_NCS_RD_SETUP (0 << 24) + +#define AT91C_DM9000_NWE_PULSE (4 << 0) +#define AT91C_DM9000_NCS_WR_PULSE (8 << 8) +#define AT91C_DM9000_NRD_PULSE (4 << 16) +#define AT91C_DM9000_NCS_RD_PULSE (8 << 24) + +#define AT91C_DM9000_NWE_CYCLE (16 << 0) +#define AT91C_DM9000_NRD_CYCLE (16 << 16) + +#define AT91C_DM9000_TDF (1 << 16) +static void __init at91_add_device_dm9000() +{ + printk("at91_add_device_dm9000 SMC & PIO initialisation %08x\n", AT91C_VA_BASE_EBI + SYS_SMC); + + //Configure SMC CS2 for DM9000 + writel( (AT91C_DM9000_NWE_SETUP | AT91C_DM9000_NCS_WR_SETUP | + AT91C_DM9000_NRD_SETUP | AT91C_DM9000_NCS_RD_SETUP), AT91C_VA_BASE_EBI + SMC_SETUP2); + + writel( (AT91C_DM9000_NWE_PULSE | AT91C_DM9000_NCS_WR_PULSE | AT91C_DM9000_NRD_PULSE | AT91C_DM9000_NCS_RD_PULSE), AT91C_VA_BASE_EBI + SMC_PULSE2); + + writel( (AT91C_DM9000_NWE_CYCLE | AT91C_DM9000_NRD_CYCLE), AT91C_VA_BASE_EBI + SMC_CYCLE2); + +//#ifdef DM9000_PLATF_16BITONLY + writel( (SMC_READMODE | SMC_WRITEMODE | SMC_NWAITM_NWAIT_DISABLE | + SMC_BAT_BYTE_WRITE | SMC_DBW_WIDTH_SIXTEEN_BITS | AT91C_DM9000_TDF), AT91C_VA_BASE_EBI + SMC_CTRL2); + printk("AT91_SMC->SMC_SETUP2 = %08x\n", readl(AT91C_VA_BASE_EBI + SMC_SETUP2)); + printk("AT91_SMC->SMC_PULSE2 = %08x\n", readl(AT91C_VA_BASE_EBI + SMC_PULSE2)); + printk("AT91_SMC->SMC_CYCLE2 = %08x\n", readl(AT91C_VA_BASE_EBI + SMC_CYCLE2)); +//#else + // AT91_SMC->SMC_CTRL2 = (AT91C_SMC_READMODE | AT91C_SMC_WRITEMODE | AT91C_SMC_NWAITM_NWAIT_ENABLE_READY | +// AT91C_SMC_DBW_WIDTH_EIGTH_BITS | AT91C_DM9000_TDF); +//#endif + + //Configure NWAIT signal + //AT91F_PIO_CfgPeriph(AT91C_BASE_PIOC,AT91C_PC2_NWAIT,0); + + //Configure Reset signal in output + at91_gpio_configure(AT91C_VA_BASE_PIOC, 10, 0, 0, 0); + //at91_set_gpio_output(AT91_PIN_PC10, 0); + + //Configure Interrupt pin in input, no pull-up + at91_gpio_configure(AT91C_VA_BASE_PIOC, 11, 1, 0, 0); + //at91_set_gpio_input(AT91_PIN_PC11, 0); + + // Enable clock for SMC and PIOC + at91_enable_periph_clock(AT91C_ID_PIOC); + + platform_device_register(&dm9000_device); +} +#else +static void __init at91_add_device_dm9000() {} +#endif /* CONFIG_DM9000 */ +