diff options
Diffstat (limited to 'arch/arm/mach-ep93xx')
32 files changed, 2573 insertions, 0 deletions
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig new file mode 100644 index 0000000..5a1b8c0 --- /dev/null +++ b/arch/arm/mach-ep93xx/Kconfig @@ -0,0 +1,107 @@ +if ARCH_EP93XX + +menu "Cirrus EP93xx Implementation Options" + +config CRUNCH + bool "Support for MaverickCrunch" + help + Enable kernel support for MaverickCrunch. + +comment "EP93xx Platforms" + +config MACH_ADSSPHERE + bool "Support ADS Sphere" + help + Say 'Y' here if you want your kernel to support the ADS + Sphere board. + +config MACH_EDB9302 + bool "Support Cirrus Logic EDB9302" + help + Say 'Y' here if you want your kernel to support the Cirrus + Logic EDB9302 Evaluation Board. + +config MACH_EDB9302A + bool "Support Cirrus Logic EDB9302A" + help + Say 'Y' here if you want your kernel to support the Cirrus + Logic EDB9302A Evaluation Board. + +config MACH_EDB9307 + bool "Support Cirrus Logic EDB9307" + help + Say 'Y' here if you want your kernel to support the Cirrus + Logic EDB9307 Evaluation Board. + +config MACH_EDB9312 + bool "Support Cirrus Logic EDB9312" + help + Say 'Y' here if you want your kernel to support the Cirrus + Logic EDB9312 Evaluation Board. + +config MACH_EDB9315 + bool "Support Cirrus Logic EDB9315" + help + Say 'Y' here if you want your kernel to support the Cirrus + Logic EDB9315 Evaluation Board. + +config MACH_EDB9315A + bool "Support Cirrus Logic EDB9315A" + help + Say 'Y' here if you want your kernel to support the Cirrus + Logic EDB9315A Evaluation Board. + +config MACH_GESBC9312 + bool "Support Glomation GESBC-9312-sx" + help + Say 'Y' here if you want your kernel to support the Glomation + GESBC-9312-sx board. + +config MACH_MICRO9 + bool + default n + +config MACH_MICRO9H + bool "Support Contec Hypercontrol Micro9-H" + select MACH_MICRO9 + help + Say 'Y' here if you want your kernel to support the + Contec Hypercontrol Micro9-H board. + +config MACH_MICRO9M + bool "Support Contec Hypercontrol Micro9-M" + select MACH_MICRO9 + help + Say 'Y' here if you want your kernel to support the + Contec Hypercontrol Micro9-M board. + +config MACH_MICRO9L + bool "Support Contec Hypercontrol Micro9-L" + select MACH_MICRO9 + help + Say 'Y' here if you want your kernel to support the + Contec Hypercontrol Micro9-L board. + +config MACH_TS72XX + bool "Support Technologic Systems TS-72xx SBC" + help + Say 'Y' here if you want your kernel to support the + Technologic Systems TS-72xx board. + +choice + prompt "Select a UART for early kernel messages" + +config EP93XX_EARLY_UART1 + bool "UART1" + +config EP93XX_EARLY_UART2 + bool "UART2" + +config EP93XX_EARLY_UART3 + bool "UART3" + +endchoice + +endmenu + +endif diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile new file mode 100644 index 0000000..c1252ca --- /dev/null +++ b/arch/arm/mach-ep93xx/Makefile @@ -0,0 +1,18 @@ +# +# Makefile for the linux kernel. +# +obj-y := core.o clock.o gpio.o +obj-m := +obj-n := +obj- := + +obj-$(CONFIG_MACH_ADSSPHERE) += adssphere.o +obj-$(CONFIG_MACH_EDB9302) += edb9302.o +obj-$(CONFIG_MACH_EDB9302A) += edb9302a.o +obj-$(CONFIG_MACH_EDB9307) += edb9307.o +obj-$(CONFIG_MACH_EDB9312) += edb9312.o +obj-$(CONFIG_MACH_EDB9315) += edb9315.o +obj-$(CONFIG_MACH_EDB9315A) += edb9315a.o +obj-$(CONFIG_MACH_GESBC9312) += gesbc9312.o +obj-$(CONFIG_MACH_MICRO9) += micro9.o +obj-$(CONFIG_MACH_TS72XX) += ts72xx.o diff --git a/arch/arm/mach-ep93xx/Makefile.boot b/arch/arm/mach-ep93xx/Makefile.boot new file mode 100644 index 0000000..d5561ad --- /dev/null +++ b/arch/arm/mach-ep93xx/Makefile.boot @@ -0,0 +1,2 @@ + zreladdr-y := 0x00008000 +params_phys-y := 0x00000100 diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c new file mode 100644 index 0000000..561db73 --- /dev/null +++ b/arch/arm/mach-ep93xx/adssphere.c @@ -0,0 +1,67 @@ +/* + * arch/arm/mach-ep93xx/adssphere.c + * ADS Sphere support. + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data adssphere_flash_data = { + .width = 4, +}; + +static struct resource adssphere_flash_resource = { + .start = 0x60000000, + .end = 0x61ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device adssphere_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &adssphere_flash_data, + }, + .num_resources = 1, + .resource = &adssphere_flash_resource, +}; + +static struct ep93xx_eth_data adssphere_eth_data = { + .phy_id = 1, +}; + +static void __init adssphere_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&adssphere_flash); + + ep93xx_register_eth(&adssphere_eth_data, 1); +} + +MACHINE_START(ADSSPHERE, "ADS Sphere board") + /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = adssphere_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c new file mode 100644 index 0000000..8c9f249 --- /dev/null +++ b/arch/arm/mach-ep93xx/clock.c @@ -0,0 +1,170 @@ +/* + * arch/arm/mach-ep93xx/clock.c + * Clock control for Cirrus EP93xx chips. + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * 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/kernel.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/module.h> +#include <linux/string.h> +#include <linux/io.h> +#include <asm/div64.h> +#include <mach/hardware.h> + +struct clk { + char *name; + unsigned long rate; + int users; + u32 enable_reg; + u32 enable_mask; +}; + +static struct clk clk_uart = { + .name = "UARTCLK", + .rate = 14745600, +}; +static struct clk clk_pll1 = { + .name = "pll1", +}; +static struct clk clk_f = { + .name = "fclk", +}; +static struct clk clk_h = { + .name = "hclk", +}; +static struct clk clk_p = { + .name = "pclk", +}; +static struct clk clk_pll2 = { + .name = "pll2", +}; +static struct clk clk_usb_host = { + .name = "usb_host", + .enable_reg = EP93XX_SYSCON_CLOCK_CONTROL, + .enable_mask = EP93XX_SYSCON_CLOCK_USH_EN, +}; + + +static struct clk *clocks[] = { + &clk_uart, + &clk_pll1, + &clk_f, + &clk_h, + &clk_p, + &clk_pll2, + &clk_usb_host, +}; + +struct clk *clk_get(struct device *dev, const char *id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(clocks); i++) { + if (!strcmp(clocks[i]->name, id)) + return clocks[i]; + } + + return ERR_PTR(-ENOENT); +} +EXPORT_SYMBOL(clk_get); + +int clk_enable(struct clk *clk) +{ + if (!clk->users++ && clk->enable_reg) { + u32 value; + + value = __raw_readl(clk->enable_reg); + __raw_writel(value | clk->enable_mask, clk->enable_reg); + } + + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ + if (!--clk->users && clk->enable_reg) { + u32 value; + + value = __raw_readl(clk->enable_reg); + __raw_writel(value & ~clk->enable_mask, clk->enable_reg); + } +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put); + + + +static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 }; +static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 }; +static char pclk_divisors[] = { 1, 2, 4, 8 }; + +/* + * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS + */ +static unsigned long calc_pll_rate(u32 config_word) +{ + unsigned long long rate; + int i; + + rate = 14745600; + rate *= ((config_word >> 11) & 0x1f) + 1; /* X1FBD */ + rate *= ((config_word >> 5) & 0x3f) + 1; /* X2FBD */ + do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */ + for (i = 0; i < ((config_word >> 16) & 3); i++) /* PS */ + rate >>= 1; + + return (unsigned long)rate; +} + +static int __init ep93xx_clock_init(void) +{ + u32 value; + + value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1); + if (!(value & 0x00800000)) { /* PLL1 bypassed? */ + clk_pll1.rate = 14745600; + } else { + clk_pll1.rate = calc_pll_rate(value); + } + clk_f.rate = clk_pll1.rate / fclk_divisors[(value >> 25) & 0x7]; + clk_h.rate = clk_pll1.rate / hclk_divisors[(value >> 20) & 0x7]; + clk_p.rate = clk_h.rate / pclk_divisors[(value >> 18) & 0x3]; + + value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2); + if (!(value & 0x00080000)) { /* PLL2 bypassed? */ + clk_pll2.rate = 14745600; + } else if (value & 0x00040000) { /* PLL2 enabled? */ + clk_pll2.rate = calc_pll_rate(value); + } else { + clk_pll2.rate = 0; + } + clk_usb_host.rate = clk_pll2.rate / (((value >> 28) & 0xf) + 1); + + printk(KERN_INFO "ep93xx: PLL1 running at %ld MHz, PLL2 at %ld MHz\n", + clk_pll1.rate / 1000000, clk_pll2.rate / 1000000); + printk(KERN_INFO "ep93xx: FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n", + clk_f.rate / 1000000, clk_h.rate / 1000000, + clk_p.rate / 1000000); + + return 0; +} +arch_initcall(ep93xx_clock_init); diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c new file mode 100644 index 0000000..48345fb --- /dev/null +++ b/arch/arm/mach-ep93xx/core.c @@ -0,0 +1,522 @@ +/* + * arch/arm/mach-ep93xx/core.c + * Core routines for Cirrus EP93xx chips. + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org> + * + * Thanks go to Michael Burian and Ray Lehtiniemi for their key + * role in the ep93xx linux community. + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/serial.h> +#include <linux/tty.h> +#include <linux/bitops.h> +#include <linux/serial_8250.h> +#include <linux/serial_core.h> +#include <linux/device.h> +#include <linux/mm.h> +#include <linux/dma-mapping.h> +#include <linux/time.h> +#include <linux/timex.h> +#include <linux/delay.h> +#include <linux/termios.h> +#include <linux/amba/bus.h> +#include <linux/amba/serial.h> +#include <linux/io.h> + +#include <asm/types.h> +#include <asm/setup.h> +#include <asm/memory.h> +#include <mach/hardware.h> +#include <asm/irq.h> +#include <asm/system.h> +#include <asm/tlbflush.h> +#include <asm/pgtable.h> + +#include <asm/mach/map.h> +#include <asm/mach/time.h> +#include <asm/mach/irq.h> +#include <mach/gpio.h> + +#include <asm/hardware/vic.h> + + +/************************************************************************* + * Static I/O mappings that are needed for all EP93xx platforms + *************************************************************************/ +static struct map_desc ep93xx_io_desc[] __initdata = { + { + .virtual = EP93XX_AHB_VIRT_BASE, + .pfn = __phys_to_pfn(EP93XX_AHB_PHYS_BASE), + .length = EP93XX_AHB_SIZE, + .type = MT_DEVICE, + }, { + .virtual = EP93XX_APB_VIRT_BASE, + .pfn = __phys_to_pfn(EP93XX_APB_PHYS_BASE), + .length = EP93XX_APB_SIZE, + .type = MT_DEVICE, + }, +}; + +void __init ep93xx_map_io(void) +{ + iotable_init(ep93xx_io_desc, ARRAY_SIZE(ep93xx_io_desc)); +} + + +/************************************************************************* + * Timer handling for EP93xx + ************************************************************************* + * The ep93xx has four internal timers. Timers 1, 2 (both 16 bit) and + * 3 (32 bit) count down at 508 kHz, are self-reloading, and can generate + * an interrupt on underflow. Timer 4 (40 bit) counts down at 983.04 kHz, + * is free-running, and can't generate interrupts. + * + * The 508 kHz timers are ideal for use for the timer interrupt, as the + * most common values of HZ divide 508 kHz nicely. We pick one of the 16 + * bit timers (timer 1) since we don't need more than 16 bits of reload + * value as long as HZ >= 8. + * + * The higher clock rate of timer 4 makes it a better choice than the + * other timers for use in gettimeoffset(), while the fact that it can't + * generate interrupts means we don't have to worry about not being able + * to use this timer for something else. We also use timer 4 for keeping + * track of lost jiffies. + */ +static unsigned int last_jiffy_time; + +#define TIMER4_TICKS_PER_JIFFY ((CLOCK_TICK_RATE + (HZ/2)) / HZ) + +static int ep93xx_timer_interrupt(int irq, void *dev_id) +{ + __raw_writel(1, EP93XX_TIMER1_CLEAR); + while ((signed long) + (__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time) + >= TIMER4_TICKS_PER_JIFFY) { + last_jiffy_time += TIMER4_TICKS_PER_JIFFY; + timer_tick(); + } + + return IRQ_HANDLED; +} + +static struct irqaction ep93xx_timer_irq = { + .name = "ep93xx timer", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = ep93xx_timer_interrupt, +}; + +static void __init ep93xx_timer_init(void) +{ + /* Enable periodic HZ timer. */ + __raw_writel(0x48, EP93XX_TIMER1_CONTROL); + __raw_writel((508469 / HZ) - 1, EP93XX_TIMER1_LOAD); + __raw_writel(0xc8, EP93XX_TIMER1_CONTROL); + + /* Enable lost jiffy timer. */ + __raw_writel(0x100, EP93XX_TIMER4_VALUE_HIGH); + + setup_irq(IRQ_EP93XX_TIMER1, &ep93xx_timer_irq); +} + +static unsigned long ep93xx_gettimeoffset(void) +{ + int offset; + + offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time; + + /* Calculate (1000000 / 983040) * offset. */ + return offset + (53 * offset / 3072); +} + +struct sys_timer ep93xx_timer = { + .init = ep93xx_timer_init, + .offset = ep93xx_gettimeoffset, +}; + + +/************************************************************************* + * GPIO handling for EP93xx + *************************************************************************/ +static unsigned char gpio_int_unmasked[3]; +static unsigned char gpio_int_enabled[3]; +static unsigned char gpio_int_type1[3]; +static unsigned char gpio_int_type2[3]; + +/* Port ordering is: A B F */ +static const u8 int_type1_register_offset[3] = { 0x90, 0xac, 0x4c }; +static const u8 int_type2_register_offset[3] = { 0x94, 0xb0, 0x50 }; +static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 }; +static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x58 }; + +void ep93xx_gpio_update_int_params(unsigned port) +{ + BUG_ON(port > 2); + + __raw_writeb(0, EP93XX_GPIO_REG(int_en_register_offset[port])); + + __raw_writeb(gpio_int_type2[port], + EP93XX_GPIO_REG(int_type2_register_offset[port])); + + __raw_writeb(gpio_int_type1[port], + EP93XX_GPIO_REG(int_type1_register_offset[port])); + + __raw_writeb(gpio_int_unmasked[port] & gpio_int_enabled[port], + EP93XX_GPIO_REG(int_en_register_offset[port])); +} + +void ep93xx_gpio_int_mask(unsigned line) +{ + gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7)); +} + +/************************************************************************* + * EP93xx IRQ handling + *************************************************************************/ +static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + unsigned char status; + int i; + + status = __raw_readb(EP93XX_GPIO_A_INT_STATUS); + for (i = 0; i < 8; i++) { + if (status & (1 << i)) { + int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_A(0)) + i; + generic_handle_irq(gpio_irq); + } + } + + status = __raw_readb(EP93XX_GPIO_B_INT_STATUS); + for (i = 0; i < 8; i++) { + if (status & (1 << i)) { + int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i; + desc = irq_desc + gpio_irq; + generic_handle_irq(gpio_irq); + } + } +} + +static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + /* + * map discontiguous hw irq range to continous sw irq range: + * + * IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7}) + */ + int port_f_idx = ((irq + 1) & 7) ^ 4; /* {19..22,47..50} -> {0..7} */ + int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_F(0)) + port_f_idx; + + generic_handle_irq(gpio_irq); +} + +static void ep93xx_gpio_irq_ack(unsigned int irq) +{ + int line = irq_to_gpio(irq); + int port = line >> 3; + int port_mask = 1 << (line & 7); + + if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { + gpio_int_type2[port] ^= port_mask; /* switch edge direction */ + ep93xx_gpio_update_int_params(port); + } + + __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); +} + +static void ep93xx_gpio_irq_mask_ack(unsigned int irq) +{ + int line = irq_to_gpio(irq); + int port = line >> 3; + int port_mask = 1 << (line & 7); + + if ((irq_desc[irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) + gpio_int_type2[port] ^= port_mask; /* switch edge direction */ + + gpio_int_unmasked[port] &= ~port_mask; + ep93xx_gpio_update_int_params(port); + + __raw_writeb(port_mask, EP93XX_GPIO_REG(eoi_register_offset[port])); +} + +static void ep93xx_gpio_irq_mask(unsigned int irq) +{ + int line = irq_to_gpio(irq); + int port = line >> 3; + + gpio_int_unmasked[port] &= ~(1 << (line & 7)); + ep93xx_gpio_update_int_params(port); +} + +static void ep93xx_gpio_irq_unmask(unsigned int irq) +{ + int line = irq_to_gpio(irq); + int port = line >> 3; + + gpio_int_unmasked[port] |= 1 << (line & 7); + ep93xx_gpio_update_int_params(port); +} + + +/* + * gpio_int_type1 controls whether the interrupt is level (0) or + * edge (1) triggered, while gpio_int_type2 controls whether it + * triggers on low/falling (0) or high/rising (1). + */ +static int ep93xx_gpio_irq_type(unsigned int irq, unsigned int type) +{ + struct irq_desc *desc = irq_desc + irq; + const int gpio = irq_to_gpio(irq); + const int port = gpio >> 3; + const int port_mask = 1 << (gpio & 7); + + gpio_direction_input(gpio); + + switch (type) { + case IRQ_TYPE_EDGE_RISING: + gpio_int_type1[port] |= port_mask; + gpio_int_type2[port] |= port_mask; + desc->handle_irq = handle_edge_irq; + break; + case IRQ_TYPE_EDGE_FALLING: + gpio_int_type1[port] |= port_mask; + gpio_int_type2[port] &= ~port_mask; + desc->handle_irq = handle_edge_irq; + break; + case IRQ_TYPE_LEVEL_HIGH: + gpio_int_type1[port] &= ~port_mask; + gpio_int_type2[port] |= port_mask; + desc->handle_irq = handle_level_irq; + break; + case IRQ_TYPE_LEVEL_LOW: + gpio_int_type1[port] &= ~port_mask; + gpio_int_type2[port] &= ~port_mask; + desc->handle_irq = handle_level_irq; + break; + case IRQ_TYPE_EDGE_BOTH: + gpio_int_type1[port] |= port_mask; + /* set initial polarity based on current input level */ + if (gpio_get_value(gpio)) + gpio_int_type2[port] &= ~port_mask; /* falling */ + else + gpio_int_type2[port] |= port_mask; /* rising */ + desc->handle_irq = handle_edge_irq; + break; + default: + pr_err("ep93xx: failed to set irq type %d for gpio %d\n", + type, gpio); + return -EINVAL; + } + + gpio_int_enabled[port] |= port_mask; + + desc->status &= ~IRQ_TYPE_SENSE_MASK; + desc->status |= type & IRQ_TYPE_SENSE_MASK; + + ep93xx_gpio_update_int_params(port); + + return 0; +} + +static struct irq_chip ep93xx_gpio_irq_chip = { + .name = "GPIO", + .ack = ep93xx_gpio_irq_ack, + .mask_ack = ep93xx_gpio_irq_mask_ack, + .mask = ep93xx_gpio_irq_mask, + .unmask = ep93xx_gpio_irq_unmask, + .set_type = ep93xx_gpio_irq_type, +}; + + +void __init ep93xx_init_irq(void) +{ + int gpio_irq; + + vic_init((void *)EP93XX_VIC1_BASE, 0, EP93XX_VIC1_VALID_IRQ_MASK); + vic_init((void *)EP93XX_VIC2_BASE, 32, EP93XX_VIC2_VALID_IRQ_MASK); + + for (gpio_irq = gpio_to_irq(0); + gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) { + set_irq_chip(gpio_irq, &ep93xx_gpio_irq_chip); + set_irq_handler(gpio_irq, handle_level_irq); + set_irq_flags(gpio_irq, IRQF_VALID); + } + + set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler); + set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler); + set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler); + set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler); + set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler); + set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler); + set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler); + set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler); + set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler); +} + + +/************************************************************************* + * EP93xx peripheral handling + *************************************************************************/ +#define EP93XX_UART_MCR_OFFSET (0x0100) + +static void ep93xx_uart_set_mctrl(struct amba_device *dev, + void __iomem *base, unsigned int mctrl) +{ + unsigned int mcr; + + mcr = 0; + if (!(mctrl & TIOCM_RTS)) + mcr |= 2; + if (!(mctrl & TIOCM_DTR)) + mcr |= 1; + + __raw_writel(mcr, base + EP93XX_UART_MCR_OFFSET); +} + +static struct amba_pl010_data ep93xx_uart_data = { + .set_mctrl = ep93xx_uart_set_mctrl, +}; + +static struct amba_device uart1_device = { + .dev = { + .bus_id = "apb:uart1", + .platform_data = &ep93xx_uart_data, + }, + .res = { + .start = EP93XX_UART1_PHYS_BASE, + .end = EP93XX_UART1_PHYS_BASE + 0x0fff, + .flags = IORESOURCE_MEM, + }, + .irq = { IRQ_EP93XX_UART1, NO_IRQ }, + .periphid = 0x00041010, +}; + +static struct amba_device uart2_device = { + .dev = { + .bus_id = "apb:uart2", + .platform_data = &ep93xx_uart_data, + }, + .res = { + .start = EP93XX_UART2_PHYS_BASE, + .end = EP93XX_UART2_PHYS_BASE + 0x0fff, + .flags = IORESOURCE_MEM, + }, + .irq = { IRQ_EP93XX_UART2, NO_IRQ }, + .periphid = 0x00041010, +}; + +static struct amba_device uart3_device = { + .dev = { + .bus_id = "apb:uart3", + .platform_data = &ep93xx_uart_data, + }, + .res = { + .start = EP93XX_UART3_PHYS_BASE, + .end = EP93XX_UART3_PHYS_BASE + 0x0fff, + .flags = IORESOURCE_MEM, + }, + .irq = { IRQ_EP93XX_UART3, NO_IRQ }, + .periphid = 0x00041010, +}; + + +static struct platform_device ep93xx_rtc_device = { + .name = "ep93xx-rtc", + .id = -1, + .num_resources = 0, +}; + + +static struct resource ep93xx_ohci_resources[] = { + [0] = { + .start = EP93XX_USB_PHYS_BASE, + .end = EP93XX_USB_PHYS_BASE + 0x0fff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_EP93XX_USB, + .end = IRQ_EP93XX_USB, + .flags = IORESOURCE_IRQ, + }, +}; + + +static struct platform_device ep93xx_ohci_device = { + .name = "ep93xx-ohci", + .id = -1, + .dev = { + .dma_mask = &ep93xx_ohci_device.dev.coherent_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .num_resources = ARRAY_SIZE(ep93xx_ohci_resources), + .resource = ep93xx_ohci_resources, +}; + +static struct ep93xx_eth_data ep93xx_eth_data; + +static struct resource ep93xx_eth_resource[] = { + { + .start = EP93XX_ETHERNET_PHYS_BASE, + .end = EP93XX_ETHERNET_PHYS_BASE + 0xffff, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_EP93XX_ETHERNET, + .end = IRQ_EP93XX_ETHERNET, + .flags = IORESOURCE_IRQ, + } +}; + +static struct platform_device ep93xx_eth_device = { + .name = "ep93xx-eth", + .id = -1, + .dev = { + .platform_data = &ep93xx_eth_data, + }, + .num_resources = ARRAY_SIZE(ep93xx_eth_resource), + .resource = ep93xx_eth_resource, +}; + +void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr) +{ + if (copy_addr) { + memcpy(data->dev_addr, + (void *)(EP93XX_ETHERNET_BASE + 0x50), 6); + } + + ep93xx_eth_data = *data; + platform_device_register(&ep93xx_eth_device); +} + +extern void ep93xx_gpio_init(void); + +void __init ep93xx_init_devices(void) +{ + unsigned int v; + + /* + * Disallow access to MaverickCrunch initially. + */ + v = __raw_readl(EP93XX_SYSCON_DEVICE_CONFIG); + v &= ~EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE; + __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); + __raw_writel(v, EP93XX_SYSCON_DEVICE_CONFIG); + + ep93xx_gpio_init(); + + amba_device_register(&uart1_device, &iomem_resource); + amba_device_register(&uart2_device, &iomem_resource); + amba_device_register(&uart3_device, &iomem_resource); + + platform_device_register(&ep93xx_rtc_device); + platform_device_register(&ep93xx_ohci_device); +} diff --git a/arch/arm/mach-ep93xx/edb9302.c b/arch/arm/mach-ep93xx/edb9302.c new file mode 100644 index 0000000..e4add5b --- /dev/null +++ b/arch/arm/mach-ep93xx/edb9302.c @@ -0,0 +1,67 @@ +/* + * arch/arm/mach-ep93xx/edb9302.c + * Cirrus Logic EDB9302 support. + * + * Copyright (C) 2006 George Kashperko <george@chas.com.ua> + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data edb9302_flash_data = { + .width = 2, +}; + +static struct resource edb9302_flash_resource = { + .start = 0x60000000, + .end = 0x60ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device edb9302_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &edb9302_flash_data, + }, + .num_resources = 1, + .resource = &edb9302_flash_resource, +}; + +static struct ep93xx_eth_data edb9302_eth_data = { + .phy_id = 1, +}; + +static void __init edb9302_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&edb9302_flash); + + ep93xx_register_eth(&edb9302_eth_data, 1); +} + +MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board") + /* Maintainer: George Kashperko <george@chas.com.ua> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = edb9302_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ep93xx/edb9302a.c b/arch/arm/mach-ep93xx/edb9302a.c new file mode 100644 index 0000000..02c4405 --- /dev/null +++ b/arch/arm/mach-ep93xx/edb9302a.c @@ -0,0 +1,67 @@ +/* + * arch/arm/mach-ep93xx/edb9302a.c + * Cirrus Logic EDB9302A support. + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data edb9302a_flash_data = { + .width = 2, +}; + +static struct resource edb9302a_flash_resource = { + .start = 0x60000000, + .end = 0x60ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device edb9302a_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &edb9302a_flash_data, + }, + .num_resources = 1, + .resource = &edb9302a_flash_resource, +}; + +static struct ep93xx_eth_data edb9302a_eth_data = { + .phy_id = 1, +}; + +static void __init edb9302a_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&edb9302a_flash); + + ep93xx_register_eth(&edb9302a_eth_data, 1); +} + +MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board") + /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0xc0000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = edb9302a_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ep93xx/edb9307.c b/arch/arm/mach-ep93xx/edb9307.c new file mode 100644 index 0000000..040edbd --- /dev/null +++ b/arch/arm/mach-ep93xx/edb9307.c @@ -0,0 +1,67 @@ +/* + * arch/arm/mach-ep93xx/edb9307.c + * Cirrus Logic EDB9307 support. + * + * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org> + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data edb9307_flash_data = { + .width = 4, +}; + +static struct resource edb9307_flash_resource = { + .start = 0x60000000, + .end = 0x61ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device edb9307_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &edb9307_flash_data, + }, + .num_resources = 1, + .resource = &edb9307_flash_resource, +}; + +static struct ep93xx_eth_data edb9307_eth_data = { + .phy_id = 1, +}; + +static void __init edb9307_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&edb9307_flash); + + ep93xx_register_eth(&edb9307_eth_data, 1); +} + +MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board") + /* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = edb9307_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ep93xx/edb9312.c b/arch/arm/mach-ep93xx/edb9312.c new file mode 100644 index 0000000..6853e30 --- /dev/null +++ b/arch/arm/mach-ep93xx/edb9312.c @@ -0,0 +1,68 @@ +/* + * arch/arm/mach-ep93xx/edb9312.c + * Cirrus Logic EDB9312 support. + * + * Copyright (C) 2006 Infosys Technologies Limited + * Toufeeq Hussain <toufeeq_hussain@infosys.com> + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data edb9312_flash_data = { + .width = 4, +}; + +static struct resource edb9312_flash_resource = { + .start = 0x60000000, + .end = 0x61ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device edb9312_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &edb9312_flash_data, + }, + .num_resources = 1, + .resource = &edb9312_flash_resource, +}; + +static struct ep93xx_eth_data edb9312_eth_data = { + .phy_id = 1, +}; + +static void __init edb9312_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&edb9312_flash); + + ep93xx_register_eth(&edb9312_eth_data, 1); +} + +MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board") + /* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = edb9312_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ep93xx/edb9315.c b/arch/arm/mach-ep93xx/edb9315.c new file mode 100644 index 0000000..9469b35 --- /dev/null +++ b/arch/arm/mach-ep93xx/edb9315.c @@ -0,0 +1,67 @@ +/* + * arch/arm/mach-ep93xx/edb9315.c + * Cirrus Logic EDB9315 support. + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data edb9315_flash_data = { + .width = 4, +}; + +static struct resource edb9315_flash_resource = { + .start = 0x60000000, + .end = 0x61ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device edb9315_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &edb9315_flash_data, + }, + .num_resources = 1, + .resource = &edb9315_flash_resource, +}; + +static struct ep93xx_eth_data edb9315_eth_data = { + .phy_id = 1, +}; + +static void __init edb9315_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&edb9315_flash); + + ep93xx_register_eth(&edb9315_eth_data, 1); +} + +MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board") + /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = edb9315_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ep93xx/edb9315a.c b/arch/arm/mach-ep93xx/edb9315a.c new file mode 100644 index 0000000..584457c --- /dev/null +++ b/arch/arm/mach-ep93xx/edb9315a.c @@ -0,0 +1,67 @@ +/* + * arch/arm/mach-ep93xx/edb9315a.c + * Cirrus Logic EDB9315A support. + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data edb9315a_flash_data = { + .width = 2, +}; + +static struct resource edb9315a_flash_resource = { + .start = 0x60000000, + .end = 0x60ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device edb9315a_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &edb9315a_flash_data, + }, + .num_resources = 1, + .resource = &edb9315a_flash_resource, +}; + +static struct ep93xx_eth_data edb9315a_eth_data = { + .phy_id = 1, +}; + +static void __init edb9315a_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&edb9315a_flash); + + ep93xx_register_eth(&edb9315a_eth_data, 1); +} + +MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board") + /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0xc0000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = edb9315a_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c new file mode 100644 index 0000000..035b24e --- /dev/null +++ b/arch/arm/mach-ep93xx/gesbc9312.c @@ -0,0 +1,67 @@ +/* + * arch/arm/mach-ep93xx/gesbc9312.c + * Glomation GESBC-9312-sx support. + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +static struct physmap_flash_data gesbc9312_flash_data = { + .width = 4, +}; + +static struct resource gesbc9312_flash_resource = { + .start = 0x60000000, + .end = 0x607fffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device gesbc9312_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &gesbc9312_flash_data, + }, + .num_resources = 1, + .resource = &gesbc9312_flash_resource, +}; + +static struct ep93xx_eth_data gesbc9312_eth_data = { + .phy_id = 1, +}; + +static void __init gesbc9312_init_machine(void) +{ + ep93xx_init_devices(); + platform_device_register(&gesbc9312_flash); + + ep93xx_register_eth(&gesbc9312_eth_data, 0); +} + +MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx") + /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = gesbc9312_init_machine, +MACHINE_END diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c new file mode 100644 index 0000000..482cf3d --- /dev/null +++ b/arch/arm/mach-ep93xx/gpio.c @@ -0,0 +1,158 @@ +/* + * linux/arch/arm/mach-ep93xx/gpio.c + * + * Generic EP93xx GPIO handling + * + * Copyright (c) 2008 Ryan Mallon <ryan@bluewatersys.com> + * + * Based on code originally from: + * linux/arch/arm/mach-ep93xx/core.c + * + * 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/module.h> +#include <linux/seq_file.h> +#include <linux/io.h> + +#include <mach/ep93xx-regs.h> +#include <asm/gpio.h> + +struct ep93xx_gpio_chip { + struct gpio_chip chip; + + unsigned int data_reg; + unsigned int data_dir_reg; +}; + +#define to_ep93xx_gpio_chip(c) container_of(c, struct ep93xx_gpio_chip, chip) + +/* From core.c */ +extern void ep93xx_gpio_int_mask(unsigned line); +extern void ep93xx_gpio_update_int_params(unsigned port); + +static int ep93xx_gpio_direction_input(struct gpio_chip *chip, unsigned offset) +{ + struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); + unsigned long flags; + u8 v; + + local_irq_save(flags); + v = __raw_readb(ep93xx_chip->data_dir_reg); + v &= ~(1 << offset); + __raw_writeb(v, ep93xx_chip->data_dir_reg); + local_irq_restore(flags); + + return 0; +} + +static int ep93xx_gpio_direction_output(struct gpio_chip *chip, + unsigned offset, int val) +{ + struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); + unsigned long flags; + int line; + u8 v; + + local_irq_save(flags); + + /* Set the value */ + v = __raw_readb(ep93xx_chip->data_reg); + if (val) + v |= (1 << offset); + else + v &= ~(1 << offset); + __raw_writeb(v, ep93xx_chip->data_reg); + + /* Drive as an output */ + line = chip->base + offset; + if (line <= EP93XX_GPIO_LINE_MAX_IRQ) { + /* Ports A/B/F */ + ep93xx_gpio_int_mask(line); + ep93xx_gpio_update_int_params(line >> 3); + } + + v = __raw_readb(ep93xx_chip->data_dir_reg); + v |= (1 << offset); + __raw_writeb(v, ep93xx_chip->data_dir_reg); + + local_irq_restore(flags); + + return 0; +} + +static int ep93xx_gpio_get(struct gpio_chip *chip, unsigned offset) +{ + struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); + + return !!(__raw_readb(ep93xx_chip->data_reg) & (1 << offset)); +} + +static void ep93xx_gpio_set(struct gpio_chip *chip, unsigned offset, int val) +{ + struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); + unsigned long flags; + u8 v; + + local_irq_save(flags); + v = __raw_readb(ep93xx_chip->data_reg); + if (val) + v |= (1 << offset); + else + v &= ~(1 << offset); + __raw_writeb(v, ep93xx_chip->data_reg); + local_irq_restore(flags); +} + +static void ep93xx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) +{ + struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip); + u8 data_reg, data_dir_reg; + int i; + + data_reg = __raw_readb(ep93xx_chip->data_reg); + data_dir_reg = __raw_readb(ep93xx_chip->data_dir_reg); + + for (i = 0; i < chip->ngpio; i++) + seq_printf(s, "GPIO %s%d: %s %s\n", chip->label, i, + (data_reg & (1 << i)) ? "set" : "clear", + (data_dir_reg & (1 << i)) ? "out" : "in"); +} + +#define EP93XX_GPIO_BANK(name, dr, ddr, base_gpio) \ + { \ + .chip = { \ + .label = name, \ + .direction_input = ep93xx_gpio_direction_input, \ + .direction_output = ep93xx_gpio_direction_output, \ + .get = ep93xx_gpio_get, \ + .set = ep93xx_gpio_set, \ + .dbg_show = ep93xx_gpio_dbg_show, \ + .base = base_gpio, \ + .ngpio = 8, \ + }, \ + .data_reg = EP93XX_GPIO_REG(dr), \ + .data_dir_reg = EP93XX_GPIO_REG(ddr), \ + } + +static struct ep93xx_gpio_chip ep93xx_gpio_banks[] = { + EP93XX_GPIO_BANK("A", 0x00, 0x10, 0), + EP93XX_GPIO_BANK("B", 0x04, 0x14, 8), + EP93XX_GPIO_BANK("C", 0x08, 0x18, 40), + EP93XX_GPIO_BANK("D", 0x0c, 0x1c, 24), + EP93XX_GPIO_BANK("E", 0x20, 0x24, 32), + EP93XX_GPIO_BANK("F", 0x30, 0x34, 16), + EP93XX_GPIO_BANK("G", 0x38, 0x3c, 48), + EP93XX_GPIO_BANK("H", 0x40, 0x44, 56), +}; + +void __init ep93xx_gpio_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) + gpiochip_add(&ep93xx_gpio_banks[i].chip); +} diff --git a/arch/arm/mach-ep93xx/include/mach/debug-macro.S b/arch/arm/mach-ep93xx/include/mach/debug-macro.S new file mode 100644 index 0000000..802858b --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/debug-macro.S @@ -0,0 +1,22 @@ +/* + * arch/arm/mach-ep93xx/include/mach/debug-macro.S + * Debugging macro include header + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * 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 <mach/ep93xx-regs.h> + + .macro addruart,rx + mrc p15, 0, \rx, c1, c0 + tst \rx, #1 @ MMU enabled? + ldreq \rx, =EP93XX_APB_PHYS_BASE @ Physical base + ldrne \rx, =EP93XX_APB_VIRT_BASE @ virtual base + orr \rx, \rx, #0x000c0000 + .endm + +#include <asm/hardware/debug-pl01x.S> diff --git a/arch/arm/mach-ep93xx/include/mach/dma.h b/arch/arm/mach-ep93xx/include/mach/dma.h new file mode 100644 index 0000000..d0fa965 --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/dma.h @@ -0,0 +1,3 @@ +/* + * arch/arm/mach-ep93xx/include/mach/dma.h + */ diff --git a/arch/arm/mach-ep93xx/include/mach/entry-macro.S b/arch/arm/mach-ep93xx/include/mach/entry-macro.S new file mode 100644 index 0000000..96b85e2 --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/entry-macro.S @@ -0,0 +1,59 @@ +/* + * arch/arm/mach-ep93xx/include/mach/entry-macro.S + * IRQ demultiplexing for EP93xx + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * 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 <mach/ep93xx-regs.h> + + .macro disable_fiq + .endm + + .macro get_irqnr_preamble, base, tmp + .endm + + .macro arch_ret_to_user, tmp1, tmp2 + .endm + + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \base, =(EP93XX_AHB_VIRT_BASE) + orr \base, \base, #0x000b0000 + mov \irqnr, #0 + ldr \irqstat, [\base] @ lower 32 interrupts + cmp \irqstat, #0 + bne 1001f + + eor \base, \base, #0x00070000 + ldr \irqstat, [\base] @ upper 32 interrupts + cmp \irqstat, #0 + beq 1002f + mov \irqnr, #0x20 + +1001: + movs \tmp, \irqstat, lsl #16 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #16 + + movs \tmp, \irqstat, lsl #8 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #8 + + movs \tmp, \irqstat, lsl #4 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #4 + + movs \tmp, \irqstat, lsl #2 + movne \irqstat, \tmp + addeq \irqnr, \irqnr, #2 + + movs \tmp, \irqstat, lsl #1 + addeq \irqnr, \irqnr, #1 + orrs \base, \base, #1 + +1002: + .endm diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h new file mode 100644 index 0000000..22d6c9a --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h @@ -0,0 +1,167 @@ +/* + * arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h + */ + +#ifndef __ASM_ARCH_EP93XX_REGS_H +#define __ASM_ARCH_EP93XX_REGS_H + +/* + * EP93xx Physical Memory Map: + * + * The ASDO pin is sampled at system reset to select a synchronous or + * asynchronous boot configuration. When ASDO is "1" (i.e. pulled-up) + * the synchronous boot mode is selected. When ASDO is "0" (i.e + * pulled-down) the asynchronous boot mode is selected. + * + * In synchronous boot mode nSDCE3 is decoded starting at physical address + * 0x00000000 and nCS0 is decoded starting at 0xf0000000. For asynchronous + * boot mode they are swapped with nCS0 decoded at 0x00000000 ann nSDCE3 + * decoded at 0xf0000000. + * + * There is known errata for the EP93xx dealing with External Memory + * Configurations. Please refer to "AN273: EP93xx Silicon Rev E Design + * Guidelines" for more information. This document can be found at: + * + * http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf + */ + +#define EP93XX_CS0_PHYS_BASE_ASYNC 0x00000000 /* ASDO Pin = 0 */ +#define EP93XX_SDCE3_PHYS_BASE_SYNC 0x00000000 /* ASDO Pin = 1 */ +#define EP93XX_CS1_PHYS_BASE 0x10000000 +#define EP93XX_CS2_PHYS_BASE 0x20000000 +#define EP93XX_CS3_PHYS_BASE 0x30000000 +#define EP93XX_PCMCIA_PHYS_BASE 0x40000000 +#define EP93XX_CS6_PHYS_BASE 0x60000000 +#define EP93XX_CS7_PHYS_BASE 0x70000000 +#define EP93XX_SDCE0_PHYS_BASE 0xc0000000 +#define EP93XX_SDCE1_PHYS_BASE 0xd0000000 +#define EP93XX_SDCE2_PHYS_BASE 0xe0000000 +#define EP93XX_SDCE3_PHYS_BASE_ASYNC 0xf0000000 /* ASDO Pin = 0 */ +#define EP93XX_CS0_PHYS_BASE_SYNC 0xf0000000 /* ASDO Pin = 1 */ + +/* + * EP93xx linux memory map: + * + * virt phys size + * fe800000 5M per-platform mappings + * fed00000 80800000 2M APB + * fef00000 80000000 1M AHB + */ + +#define EP93XX_AHB_PHYS_BASE 0x80000000 +#define EP93XX_AHB_VIRT_BASE 0xfef00000 +#define EP93XX_AHB_SIZE 0x00100000 + +#define EP93XX_APB_PHYS_BASE 0x80800000 +#define EP93XX_APB_VIRT_BASE 0xfed00000 +#define EP93XX_APB_SIZE 0x00200000 + + +/* AHB peripherals */ +#define EP93XX_DMA_BASE (EP93XX_AHB_VIRT_BASE + 0x00000000) + +#define EP93XX_ETHERNET_BASE (EP93XX_AHB_VIRT_BASE + 0x00010000) +#define EP93XX_ETHERNET_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00010000) + +#define EP93XX_USB_BASE (EP93XX_AHB_VIRT_BASE + 0x00020000) +#define EP93XX_USB_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00020000) + +#define EP93XX_RASTER_BASE (EP93XX_AHB_VIRT_BASE + 0x00030000) + +#define EP93XX_GRAPHICS_ACCEL_BASE (EP93XX_AHB_VIRT_BASE + 0x00040000) + +#define EP93XX_SDRAM_CONTROLLER_BASE (EP93XX_AHB_VIRT_BASE + 0x00060000) + +#define EP93XX_PCMCIA_CONTROLLER_BASE (EP93XX_AHB_VIRT_BASE + 0x00080000) + +#define EP93XX_BOOT_ROM_BASE (EP93XX_AHB_VIRT_BASE + 0x00090000) + +#define EP93XX_IDE_BASE (EP93XX_AHB_VIRT_BASE + 0x000a0000) + +#define EP93XX_VIC1_BASE (EP93XX_AHB_VIRT_BASE + 0x000b0000) + +#define EP93XX_VIC2_BASE (EP93XX_AHB_VIRT_BASE + 0x000c0000) + + +/* APB peripherals */ +#define EP93XX_TIMER_BASE (EP93XX_APB_VIRT_BASE + 0x00010000) +#define EP93XX_TIMER_REG(x) (EP93XX_TIMER_BASE + (x)) +#define EP93XX_TIMER1_LOAD EP93XX_TIMER_REG(0x00) +#define EP93XX_TIMER1_VALUE EP93XX_TIMER_REG(0x04) +#define EP93XX_TIMER1_CONTROL EP93XX_TIMER_REG(0x08) +#define EP93XX_TIMER1_CLEAR EP93XX_TIMER_REG(0x0c) +#define EP93XX_TIMER2_LOAD EP93XX_TIMER_REG(0x20) +#define EP93XX_TIMER2_VALUE EP93XX_TIMER_REG(0x24) +#define EP93XX_TIMER2_CONTROL EP93XX_TIMER_REG(0x28) +#define EP93XX_TIMER2_CLEAR EP93XX_TIMER_REG(0x2c) +#define EP93XX_TIMER4_VALUE_LOW EP93XX_TIMER_REG(0x60) +#define EP93XX_TIMER4_VALUE_HIGH EP93XX_TIMER_REG(0x64) +#define EP93XX_TIMER3_LOAD EP93XX_TIMER_REG(0x80) +#define EP93XX_TIMER3_VALUE EP93XX_TIMER_REG(0x84) +#define EP93XX_TIMER3_CONTROL EP93XX_TIMER_REG(0x88) +#define EP93XX_TIMER3_CLEAR EP93XX_TIMER_REG(0x8c) + +#define EP93XX_I2S_BASE (EP93XX_APB_VIRT_BASE + 0x00020000) + +#define EP93XX_SECURITY_BASE (EP93XX_APB_VIRT_BASE + 0x00030000) + +#define EP93XX_GPIO_BASE (EP93XX_APB_VIRT_BASE + 0x00040000) +#define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) +#define EP93XX_GPIO_F_INT_TYPE1 EP93XX_GPIO_REG(0x4c) +#define EP93XX_GPIO_F_INT_TYPE2 EP93XX_GPIO_REG(0x50) +#define EP93XX_GPIO_F_INT_ACK EP93XX_GPIO_REG(0x54) +#define EP93XX_GPIO_F_INT_ENABLE EP93XX_GPIO_REG(0x58) +#define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c) +#define EP93XX_GPIO_A_INT_TYPE1 EP93XX_GPIO_REG(0x90) +#define EP93XX_GPIO_A_INT_TYPE2 EP93XX_GPIO_REG(0x94) +#define EP93XX_GPIO_A_INT_ACK EP93XX_GPIO_REG(0x98) +#define EP93XX_GPIO_A_INT_ENABLE EP93XX_GPIO_REG(0x9c) +#define EP93XX_GPIO_A_INT_STATUS EP93XX_GPIO_REG(0xa0) +#define EP93XX_GPIO_B_INT_TYPE1 EP93XX_GPIO_REG(0xac) +#define EP93XX_GPIO_B_INT_TYPE2 EP93XX_GPIO_REG(0xb0) +#define EP93XX_GPIO_B_INT_ACK EP93XX_GPIO_REG(0xb4) +#define EP93XX_GPIO_B_INT_ENABLE EP93XX_GPIO_REG(0xb8) +#define EP93XX_GPIO_B_INT_STATUS EP93XX_GPIO_REG(0xbc) + +#define EP93XX_AAC_BASE (EP93XX_APB_VIRT_BASE + 0x00080000) + +#define EP93XX_SPI_BASE (EP93XX_APB_VIRT_BASE + 0x000a0000) + +#define EP93XX_IRDA_BASE (EP93XX_APB_VIRT_BASE + 0x000b0000) + +#define EP93XX_UART1_BASE (EP93XX_APB_VIRT_BASE + 0x000c0000) +#define EP93XX_UART1_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x000c0000) + +#define EP93XX_UART2_BASE (EP93XX_APB_VIRT_BASE + 0x000d0000) +#define EP93XX_UART2_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x000d0000) + +#define EP93XX_UART3_BASE (EP93XX_APB_VIRT_BASE + 0x000e0000) +#define EP93XX_UART3_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x000e0000) + +#define EP93XX_KEY_MATRIX_BASE (EP93XX_APB_VIRT_BASE + 0x000f0000) + +#define EP93XX_ADC_BASE (EP93XX_APB_VIRT_BASE + 0x00100000) +#define EP93XX_TOUCHSCREEN_BASE (EP93XX_APB_VIRT_BASE + 0x00100000) + +#define EP93XX_PWM_BASE (EP93XX_APB_VIRT_BASE + 0x00110000) + +#define EP93XX_RTC_BASE (EP93XX_APB_VIRT_BASE + 0x00120000) + +#define EP93XX_SYSCON_BASE (EP93XX_APB_VIRT_BASE + 0x00130000) +#define EP93XX_SYSCON_REG(x) (EP93XX_SYSCON_BASE + (x)) +#define EP93XX_SYSCON_POWER_STATE EP93XX_SYSCON_REG(0x00) +#define EP93XX_SYSCON_CLOCK_CONTROL EP93XX_SYSCON_REG(0x04) +#define EP93XX_SYSCON_CLOCK_UARTBAUD 0x20000000 +#define EP93XX_SYSCON_CLOCK_USH_EN 0x10000000 +#define EP93XX_SYSCON_HALT EP93XX_SYSCON_REG(0x08) +#define EP93XX_SYSCON_STANDBY EP93XX_SYSCON_REG(0x0c) +#define EP93XX_SYSCON_CLOCK_SET1 EP93XX_SYSCON_REG(0x20) +#define EP93XX_SYSCON_CLOCK_SET2 EP93XX_SYSCON_REG(0x24) +#define EP93XX_SYSCON_DEVICE_CONFIG EP93XX_SYSCON_REG(0x80) +#define EP93XX_SYSCON_DEVICE_CONFIG_CRUNCH_ENABLE 0x00800000 +#define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0) + +#define EP93XX_WATCHDOG_BASE (EP93XX_APB_VIRT_BASE + 0x00140000) + + +#endif diff --git a/arch/arm/mach-ep93xx/include/mach/gesbc9312.h b/arch/arm/mach-ep93xx/include/mach/gesbc9312.h new file mode 100644 index 0000000..21fe2b9 --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/gesbc9312.h @@ -0,0 +1,3 @@ +/* + * arch/arm/mach-ep93xx/include/mach/gesbc9312.h + */ diff --git a/arch/arm/mach-ep93xx/include/mach/gpio.h b/arch/arm/mach-ep93xx/include/mach/gpio.h new file mode 100644 index 0000000..f702041 --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/gpio.h @@ -0,0 +1,128 @@ +/* + * arch/arm/mach-ep93xx/include/mach/gpio.h + */ + +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H + +/* GPIO port A. */ +#define EP93XX_GPIO_LINE_A(x) ((x) + 0) +#define EP93XX_GPIO_LINE_EGPIO0 EP93XX_GPIO_LINE_A(0) +#define EP93XX_GPIO_LINE_EGPIO1 EP93XX_GPIO_LINE_A(1) +#define EP93XX_GPIO_LINE_EGPIO2 EP93XX_GPIO_LINE_A(2) +#define EP93XX_GPIO_LINE_EGPIO3 EP93XX_GPIO_LINE_A(3) +#define EP93XX_GPIO_LINE_EGPIO4 EP93XX_GPIO_LINE_A(4) +#define EP93XX_GPIO_LINE_EGPIO5 EP93XX_GPIO_LINE_A(5) +#define EP93XX_GPIO_LINE_EGPIO6 EP93XX_GPIO_LINE_A(6) +#define EP93XX_GPIO_LINE_EGPIO7 EP93XX_GPIO_LINE_A(7) + +/* GPIO port B. */ +#define EP93XX_GPIO_LINE_B(x) ((x) + 8) +#define EP93XX_GPIO_LINE_EGPIO8 EP93XX_GPIO_LINE_B(0) +#define EP93XX_GPIO_LINE_EGPIO9 EP93XX_GPIO_LINE_B(1) +#define EP93XX_GPIO_LINE_EGPIO10 EP93XX_GPIO_LINE_B(2) +#define EP93XX_GPIO_LINE_EGPIO11 EP93XX_GPIO_LINE_B(3) +#define EP93XX_GPIO_LINE_EGPIO12 EP93XX_GPIO_LINE_B(4) +#define EP93XX_GPIO_LINE_EGPIO13 EP93XX_GPIO_LINE_B(5) +#define EP93XX_GPIO_LINE_EGPIO14 EP93XX_GPIO_LINE_B(6) +#define EP93XX_GPIO_LINE_EGPIO15 EP93XX_GPIO_LINE_B(7) + +/* GPIO port C. */ +#define EP93XX_GPIO_LINE_C(x) ((x) + 40) +#define EP93XX_GPIO_LINE_ROW0 EP93XX_GPIO_LINE_C(0) +#define EP93XX_GPIO_LINE_ROW1 EP93XX_GPIO_LINE_C(1) +#define EP93XX_GPIO_LINE_ROW2 EP93XX_GPIO_LINE_C(2) +#define EP93XX_GPIO_LINE_ROW3 EP93XX_GPIO_LINE_C(3) +#define EP93XX_GPIO_LINE_ROW4 EP93XX_GPIO_LINE_C(4) +#define EP93XX_GPIO_LINE_ROW5 EP93XX_GPIO_LINE_C(5) +#define EP93XX_GPIO_LINE_ROW6 EP93XX_GPIO_LINE_C(6) +#define EP93XX_GPIO_LINE_ROW7 EP93XX_GPIO_LINE_C(7) + +/* GPIO port D. */ +#define EP93XX_GPIO_LINE_D(x) ((x) + 24) +#define EP93XX_GPIO_LINE_COL0 EP93XX_GPIO_LINE_D(0) +#define EP93XX_GPIO_LINE_COL1 EP93XX_GPIO_LINE_D(1) +#define EP93XX_GPIO_LINE_COL2 EP93XX_GPIO_LINE_D(2) +#define EP93XX_GPIO_LINE_COL3 EP93XX_GPIO_LINE_D(3) +#define EP93XX_GPIO_LINE_COL4 EP93XX_GPIO_LINE_D(4) +#define EP93XX_GPIO_LINE_COL5 EP93XX_GPIO_LINE_D(5) +#define EP93XX_GPIO_LINE_COL6 EP93XX_GPIO_LINE_D(6) +#define EP93XX_GPIO_LINE_COL7 EP93XX_GPIO_LINE_D(7) + +/* GPIO port E. */ +#define EP93XX_GPIO_LINE_E(x) ((x) + 32) +#define EP93XX_GPIO_LINE_GRLED EP93XX_GPIO_LINE_E(0) +#define EP93XX_GPIO_LINE_RDLED EP93XX_GPIO_LINE_E(1) +#define EP93XX_GPIO_LINE_DIORn EP93XX_GPIO_LINE_E(2) +#define EP93XX_GPIO_LINE_IDECS1n EP93XX_GPIO_LINE_E(3) +#define EP93XX_GPIO_LINE_IDECS2n EP93XX_GPIO_LINE_E(4) +#define EP93XX_GPIO_LINE_IDEDA0 EP93XX_GPIO_LINE_E(5) +#define EP93XX_GPIO_LINE_IDEDA1 EP93XX_GPIO_LINE_E(6) +#define EP93XX_GPIO_LINE_IDEDA2 EP93XX_GPIO_LINE_E(7) + +/* GPIO port F. */ +#define EP93XX_GPIO_LINE_F(x) ((x) + 16) +#define EP93XX_GPIO_LINE_WP EP93XX_GPIO_LINE_F(0) +#define EP93XX_GPIO_LINE_MCCD1 EP93XX_GPIO_LINE_F(1) +#define EP93XX_GPIO_LINE_MCCD2 EP93XX_GPIO_LINE_F(2) +#define EP93XX_GPIO_LINE_MCBVD1 EP93XX_GPIO_LINE_F(3) +#define EP93XX_GPIO_LINE_MCBVD2 EP93XX_GPIO_LINE_F(4) +#define EP93XX_GPIO_LINE_VS1 EP93XX_GPIO_LINE_F(5) +#define EP93XX_GPIO_LINE_READY EP93XX_GPIO_LINE_F(6) +#define EP93XX_GPIO_LINE_VS2 EP93XX_GPIO_LINE_F(7) + +/* GPIO port G. */ +#define EP93XX_GPIO_LINE_G(x) ((x) + 48) +#define EP93XX_GPIO_LINE_EECLK EP93XX_GPIO_LINE_G(0) +#define EP93XX_GPIO_LINE_EEDAT EP93XX_GPIO_LINE_G(1) +#define EP93XX_GPIO_LINE_SLA0 EP93XX_GPIO_LINE_G(2) +#define EP93XX_GPIO_LINE_SLA1 EP93XX_GPIO_LINE_G(3) +#define EP93XX_GPIO_LINE_DD12 EP93XX_GPIO_LINE_G(4) +#define EP93XX_GPIO_LINE_DD13 EP93XX_GPIO_LINE_G(5) +#define EP93XX_GPIO_LINE_DD14 EP93XX_GPIO_LINE_G(6) +#define EP93XX_GPIO_LINE_DD15 EP93XX_GPIO_LINE_G(7) + +/* GPIO port H. */ +#define EP93XX_GPIO_LINE_H(x) ((x) + 56) +#define EP93XX_GPIO_LINE_DD0 EP93XX_GPIO_LINE_H(0) +#define EP93XX_GPIO_LINE_DD1 EP93XX_GPIO_LINE_H(1) +#define EP93XX_GPIO_LINE_DD2 EP93XX_GPIO_LINE_H(2) +#define EP93XX_GPIO_LINE_DD3 EP93XX_GPIO_LINE_H(3) +#define EP93XX_GPIO_LINE_DD4 EP93XX_GPIO_LINE_H(4) +#define EP93XX_GPIO_LINE_DD5 EP93XX_GPIO_LINE_H(5) +#define EP93XX_GPIO_LINE_DD6 EP93XX_GPIO_LINE_H(6) +#define EP93XX_GPIO_LINE_DD7 EP93XX_GPIO_LINE_H(7) + +/* maximum value for gpio line identifiers */ +#define EP93XX_GPIO_LINE_MAX EP93XX_GPIO_LINE_H(7) + +/* maximum value for irq capable line identifiers */ +#define EP93XX_GPIO_LINE_MAX_IRQ EP93XX_GPIO_LINE_F(7) + +/* new generic GPIO API - see Documentation/gpio.txt */ + +#include <asm-generic/gpio.h> + +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value +#define gpio_cansleep __gpio_cansleep + +/* + * Map GPIO A0..A7 (0..7) to irq 64..71, + * B0..B7 (7..15) to irq 72..79, and + * F0..F7 (16..24) to irq 80..87. + */ +static inline int gpio_to_irq(unsigned gpio) +{ + if (gpio <= EP93XX_GPIO_LINE_MAX_IRQ) + return 64 + gpio; + + return -EINVAL; +} + +static inline int irq_to_gpio(unsigned irq) +{ + return irq - gpio_to_irq(0); +} + +#endif diff --git a/arch/arm/mach-ep93xx/include/mach/hardware.h b/arch/arm/mach-ep93xx/include/mach/hardware.h new file mode 100644 index 0000000..529807d --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/hardware.h @@ -0,0 +1,16 @@ +/* + * arch/arm/mach-ep93xx/include/mach/hardware.h + */ +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +#include "ep93xx-regs.h" + +#define pcibios_assign_all_busses() 0 + +#include "platform.h" + +#include "gesbc9312.h" +#include "ts72xx.h" + +#endif diff --git a/arch/arm/mach-ep93xx/include/mach/io.h b/arch/arm/mach-ep93xx/include/mach/io.h new file mode 100644 index 0000000..1ab9a90 --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/io.h @@ -0,0 +1,8 @@ +/* + * arch/arm/mach-ep93xx/include/mach/io.h + */ + +#define IO_SPACE_LIMIT 0xffffffff + +#define __io(p) ((void __iomem *)(p)) +#define __mem_pci(p) (p) diff --git a/arch/arm/mach-ep93xx/include/mach/irqs.h b/arch/arm/mach-ep93xx/include/mach/irqs.h new file mode 100644 index 0000000..ff98390 --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/irqs.h @@ -0,0 +1,78 @@ +/* + * arch/arm/mach-ep93xx/include/mach/irqs.h + */ + +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H + +#define IRQ_EP93XX_COMMRX 2 +#define IRQ_EP93XX_COMMTX 3 +#define IRQ_EP93XX_TIMER1 4 +#define IRQ_EP93XX_TIMER2 5 +#define IRQ_EP93XX_AACINTR 6 +#define IRQ_EP93XX_DMAM2P0 7 +#define IRQ_EP93XX_DMAM2P1 8 +#define IRQ_EP93XX_DMAM2P2 9 +#define IRQ_EP93XX_DMAM2P3 10 +#define IRQ_EP93XX_DMAM2P4 11 +#define IRQ_EP93XX_DMAM2P5 12 +#define IRQ_EP93XX_DMAM2P6 13 +#define IRQ_EP93XX_DMAM2P7 14 +#define IRQ_EP93XX_DMAM2P8 15 +#define IRQ_EP93XX_DMAM2P9 16 +#define IRQ_EP93XX_DMAM2M0 17 +#define IRQ_EP93XX_DMAM2M1 18 +#define IRQ_EP93XX_GPIO0MUX 19 +#define IRQ_EP93XX_GPIO1MUX 20 +#define IRQ_EP93XX_GPIO2MUX 21 +#define IRQ_EP93XX_GPIO3MUX 22 +#define IRQ_EP93XX_UART1RX 23 +#define IRQ_EP93XX_UART1TX 24 +#define IRQ_EP93XX_UART2RX 25 +#define IRQ_EP93XX_UART2TX 26 +#define IRQ_EP93XX_UART3RX 27 +#define IRQ_EP93XX_UART3TX 28 +#define IRQ_EP93XX_KEY 29 +#define IRQ_EP93XX_TOUCH 30 +#define EP93XX_VIC1_VALID_IRQ_MASK 0x7ffffffc + +#define IRQ_EP93XX_EXT0 32 +#define IRQ_EP93XX_EXT1 33 +#define IRQ_EP93XX_EXT2 34 +#define IRQ_EP93XX_64HZ 35 +#define IRQ_EP93XX_WATCHDOG 36 +#define IRQ_EP93XX_RTC 37 +#define IRQ_EP93XX_IRDA 38 +#define IRQ_EP93XX_ETHERNET 39 +#define IRQ_EP93XX_EXT3 40 +#define IRQ_EP93XX_PROG 41 +#define IRQ_EP93XX_1HZ 42 +#define IRQ_EP93XX_VSYNC 43 +#define IRQ_EP93XX_VIDEO_FIFO 44 +#define IRQ_EP93XX_SSP1RX 45 +#define IRQ_EP93XX_SSP1TX 46 +#define IRQ_EP93XX_GPIO4MUX 47 +#define IRQ_EP93XX_GPIO5MUX 48 +#define IRQ_EP93XX_GPIO6MUX 49 +#define IRQ_EP93XX_GPIO7MUX 50 +#define IRQ_EP93XX_TIMER3 51 +#define IRQ_EP93XX_UART1 52 +#define IRQ_EP93XX_SSP 53 +#define IRQ_EP93XX_UART2 54 +#define IRQ_EP93XX_UART3 55 +#define IRQ_EP93XX_USB 56 +#define IRQ_EP93XX_ETHERNET_PME 57 +#define IRQ_EP93XX_DSP 58 +#define IRQ_EP93XX_GPIO_AB 59 +#define IRQ_EP93XX_SAI 60 +#define EP93XX_VIC2_VALID_IRQ_MASK 0x1fffffff + +#define NR_EP93XX_IRQS (64 + 24) + +#define EP93XX_BOARD_IRQ(x) (NR_EP93XX_IRQS + (x)) +#define EP93XX_BOARD_IRQS 32 + +#define NR_IRQS (NR_EP93XX_IRQS + EP93XX_BOARD_IRQS) + + +#endif diff --git a/arch/arm/mach-ep93xx/include/mach/memory.h b/arch/arm/mach-ep93xx/include/mach/memory.h new file mode 100644 index 0000000..f1b6335 --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/memory.h @@ -0,0 +1,14 @@ +/* + * arch/arm/mach-ep93xx/include/mach/memory.h + */ + +#ifndef __ASM_ARCH_MEMORY_H +#define __ASM_ARCH_MEMORY_H + +#define PHYS_OFFSET UL(0x00000000) + +#define __bus_to_virt(x) __phys_to_virt(x) +#define __virt_to_bus(x) __virt_to_phys(x) + + +#endif diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h new file mode 100644 index 0000000..db2489d --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -0,0 +1,20 @@ +/* + * arch/arm/mach-ep93xx/include/mach/platform.h + */ + +#ifndef __ASSEMBLY__ + +struct ep93xx_eth_data +{ + unsigned char dev_addr[6]; + unsigned char phy_id; +}; + +void ep93xx_map_io(void); +void ep93xx_init_irq(void); +void ep93xx_init_time(unsigned long); +void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr); +void ep93xx_init_devices(void); +extern struct sys_timer ep93xx_timer; + +#endif diff --git a/arch/arm/mach-ep93xx/include/mach/system.h b/arch/arm/mach-ep93xx/include/mach/system.h new file mode 100644 index 0000000..67789d0 --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/system.h @@ -0,0 +1,26 @@ +/* + * arch/arm/mach-ep93xx/include/mach/system.h + */ + +#include <mach/hardware.h> + +static inline void arch_idle(void) +{ + cpu_do_idle(); +} + +static inline void arch_reset(char mode) +{ + u32 devicecfg; + + local_irq_disable(); + + devicecfg = __raw_readl(EP93XX_SYSCON_DEVICE_CONFIG); + __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); + __raw_writel(devicecfg | 0x80000000, EP93XX_SYSCON_DEVICE_CONFIG); + __raw_writel(0xaa, EP93XX_SYSCON_SWLOCK); + __raw_writel(devicecfg & ~0x80000000, EP93XX_SYSCON_DEVICE_CONFIG); + + while (1) + ; +} diff --git a/arch/arm/mach-ep93xx/include/mach/timex.h b/arch/arm/mach-ep93xx/include/mach/timex.h new file mode 100644 index 0000000..6b3503b --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/timex.h @@ -0,0 +1,5 @@ +/* + * arch/arm/mach-ep93xx/include/mach/timex.h + */ + +#define CLOCK_TICK_RATE 983040 diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h new file mode 100644 index 0000000..34ddec0 --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h @@ -0,0 +1,101 @@ +/* + * arch/arm/mach-ep93xx/include/mach/ts72xx.h + */ + +/* + * TS72xx memory map: + * + * virt phys size + * febff000 22000000 4K model number register + * febfe000 22400000 4K options register + * febfd000 22800000 4K options register #2 + * febfc000 [67]0000000 4K NAND data register + * febfb000 [67]0400000 4K NAND control register + * febfa000 [67]0800000 4K NAND busy register + * febf9000 10800000 4K TS-5620 RTC index register + * febf8000 11700000 4K TS-5620 RTC data register + */ + +#define TS72XX_MODEL_PHYS_BASE 0x22000000 +#define TS72XX_MODEL_VIRT_BASE 0xfebff000 +#define TS72XX_MODEL_SIZE 0x00001000 + +#define TS72XX_MODEL_TS7200 0x00 +#define TS72XX_MODEL_TS7250 0x01 +#define TS72XX_MODEL_TS7260 0x02 + + +#define TS72XX_OPTIONS_PHYS_BASE 0x22400000 +#define TS72XX_OPTIONS_VIRT_BASE 0xfebfe000 +#define TS72XX_OPTIONS_SIZE 0x00001000 + +#define TS72XX_OPTIONS_COM2_RS485 0x02 +#define TS72XX_OPTIONS_MAX197 0x01 + + +#define TS72XX_OPTIONS2_PHYS_BASE 0x22800000 +#define TS72XX_OPTIONS2_VIRT_BASE 0xfebfd000 +#define TS72XX_OPTIONS2_SIZE 0x00001000 + +#define TS72XX_OPTIONS2_TS9420 0x04 +#define TS72XX_OPTIONS2_TS9420_BOOT 0x02 + + +#define TS72XX_NOR_PHYS_BASE 0x60000000 +#define TS72XX_NOR2_PHYS_BASE 0x62000000 + +#define TS72XX_NAND1_DATA_PHYS_BASE 0x60000000 +#define TS72XX_NAND2_DATA_PHYS_BASE 0x70000000 +#define TS72XX_NAND_DATA_VIRT_BASE 0xfebfc000 +#define TS72XX_NAND_DATA_SIZE 0x00001000 + +#define TS72XX_NAND1_CONTROL_PHYS_BASE 0x60400000 +#define TS72XX_NAND2_CONTROL_PHYS_BASE 0x70400000 +#define TS72XX_NAND_CONTROL_VIRT_BASE 0xfebfb000 +#define TS72XX_NAND_CONTROL_SIZE 0x00001000 + +#define TS72XX_NAND1_BUSY_PHYS_BASE 0x60800000 +#define TS72XX_NAND2_BUSY_PHYS_BASE 0x70800000 +#define TS72XX_NAND_BUSY_VIRT_BASE 0xfebfa000 +#define TS72XX_NAND_BUSY_SIZE 0x00001000 + + +#define TS72XX_RTC_INDEX_VIRT_BASE 0xfebf9000 +#define TS72XX_RTC_INDEX_PHYS_BASE 0x10800000 +#define TS72XX_RTC_INDEX_SIZE 0x00001000 + +#define TS72XX_RTC_DATA_VIRT_BASE 0xfebf8000 +#define TS72XX_RTC_DATA_PHYS_BASE 0x11700000 +#define TS72XX_RTC_DATA_SIZE 0x00001000 + + +#ifndef __ASSEMBLY__ +#include <linux/io.h> + +static inline int board_is_ts7200(void) +{ + return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7200; +} + +static inline int board_is_ts7250(void) +{ + return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7250; +} + +static inline int board_is_ts7260(void) +{ + return __raw_readb(TS72XX_MODEL_VIRT_BASE) == TS72XX_MODEL_TS7260; +} + +static inline int is_max197_installed(void) +{ + return !!(__raw_readb(TS72XX_OPTIONS_VIRT_BASE) & + TS72XX_OPTIONS_MAX197); +} + +static inline int is_ts9420_installed(void) +{ + return !!(__raw_readb(TS72XX_OPTIONS2_VIRT_BASE) & + TS72XX_OPTIONS2_TS9420); +} +#endif diff --git a/arch/arm/mach-ep93xx/include/mach/uncompress.h b/arch/arm/mach-ep93xx/include/mach/uncompress.h new file mode 100644 index 0000000..16026c2 --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/uncompress.h @@ -0,0 +1,94 @@ +/* + * arch/arm/mach-ep93xx/include/mach/uncompress.h + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * 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 <mach/ep93xx-regs.h> + +static unsigned char __raw_readb(unsigned int ptr) +{ + return *((volatile unsigned char *)ptr); +} + +static unsigned int __raw_readl(unsigned int ptr) +{ + return *((volatile unsigned int *)ptr); +} + +static void __raw_writeb(unsigned char value, unsigned int ptr) +{ + *((volatile unsigned char *)ptr) = value; +} + +static void __raw_writel(unsigned int value, unsigned int ptr) +{ + *((volatile unsigned int *)ptr) = value; +} + +#if defined(CONFIG_EP93XX_EARLY_UART1) +#define UART_BASE EP93XX_UART1_PHYS_BASE +#elif defined(CONFIG_EP93XX_EARLY_UART2) +#define UART_BASE EP93XX_UART2_PHYS_BASE +#elif defined(CONFIG_EP93XX_EARLY_UART3) +#define UART_BASE EP93XX_UART3_PHYS_BASE +#else +#define UART_BASE EP93XX_UART1_PHYS_BASE +#endif + +#define PHYS_UART_DATA (UART_BASE + 0x00) +#define PHYS_UART_FLAG (UART_BASE + 0x18) +#define UART_FLAG_TXFF 0x20 + +static inline void putc(int c) +{ + int i; + + for (i = 0; i < 1000; i++) { + /* Transmit fifo not full? */ + if (!(__raw_readb(PHYS_UART_FLAG) & UART_FLAG_TXFF)) + break; + } + + __raw_writeb(c, PHYS_UART_DATA); +} + +static inline void flush(void) +{ +} + + +/* + * Some bootloaders don't turn off DMA from the ethernet MAC before + * jumping to linux, which means that we might end up with bits of RX + * status and packet data scribbled over the uncompressed kernel image. + * Work around this by resetting the ethernet MAC before we uncompress. + */ +#define PHYS_ETH_SELF_CTL 0x80010020 +#define ETH_SELF_CTL_RESET 0x00000001 + +static void ethernet_reset(void) +{ + unsigned int v; + + /* Reset the ethernet MAC. */ + v = __raw_readl(PHYS_ETH_SELF_CTL); + __raw_writel(v | ETH_SELF_CTL_RESET, PHYS_ETH_SELF_CTL); + + /* Wait for reset to finish. */ + while (__raw_readl(PHYS_ETH_SELF_CTL) & ETH_SELF_CTL_RESET) + ; +} + + +static void arch_decomp_setup(void) +{ + ethernet_reset(); +} + +#define arch_decomp_wdog() diff --git a/arch/arm/mach-ep93xx/include/mach/vmalloc.h b/arch/arm/mach-ep93xx/include/mach/vmalloc.h new file mode 100644 index 0000000..aed21cd --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/vmalloc.h @@ -0,0 +1,5 @@ +/* + * arch/arm/mach-ep93xx/include/mach/vmalloc.h + */ + +#define VMALLOC_END 0xfe800000 diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c new file mode 100644 index 0000000..c219723 --- /dev/null +++ b/arch/arm/mach-ep93xx/micro9.c @@ -0,0 +1,127 @@ +/* + * linux/arch/arm/mach-ep93xx/micro9.c + * + * Copyright (C) 2006 Contec Steuerungstechnik & Automation GmbH + * Manfred Gruber <manfred.gruber@contec.at> + * + * 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/ioport.h> +#include <linux/kernel.h> +#include <linux/mm.h> +#include <linux/platform_device.h> +#include <linux/sched.h> +#include <linux/io.h> +#include <linux/mtd/physmap.h> + +#include <mach/hardware.h> + +#include <asm/mach/arch.h> +#include <asm/mach-types.h> + +static struct ep93xx_eth_data micro9_eth_data = { + .phy_id = 0x1f, +}; + +static void __init micro9_init(void) +{ + ep93xx_register_eth(µ9_eth_data, 1); +} + +/* + * Micro9-H + */ +#ifdef CONFIG_MACH_MICRO9H +static struct physmap_flash_data micro9h_flash_data = { + .width = 4, +}; + +static struct resource micro9h_flash_resource = { + .start = 0x10000000, + .end = 0x13ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device micro9h_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = µ9h_flash_data, + }, + .num_resources = 1, + .resource = µ9h_flash_resource, +}; + +static void __init micro9h_init(void) +{ + platform_device_register(µ9h_flash); +} + +static void __init micro9h_init_machine(void) +{ + ep93xx_init_devices(); + micro9_init(); + micro9h_init(); +} + +MACHINE_START(MICRO9, "Contec Hypercontrol Micro9-H") + /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = micro9h_init_machine, +MACHINE_END +#endif + +/* + * Micro9-M + */ +#ifdef CONFIG_MACH_MICRO9M +static void __init micro9m_init_machine(void) +{ + ep93xx_init_devices(); + micro9_init(); +} + +MACHINE_START(MICRO9M, "Contec Hypercontrol Micro9-M") + /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = micro9m_init_machine, +MACHINE_END +#endif + +/* + * Micro9-L + */ +#ifdef CONFIG_MACH_MICRO9L +static void __init micro9l_init_machine(void) +{ + ep93xx_init_devices(); + micro9_init(); +} + +MACHINE_START(MICRO9L, "Contec Hypercontrol Micro9-L") + /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = micro9l_init_machine, +MACHINE_END +#endif + diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c new file mode 100644 index 0000000..b4aa4c0 --- /dev/null +++ b/arch/arm/mach-ep93xx/ts72xx.c @@ -0,0 +1,183 @@ +/* + * arch/arm/mach-ep93xx/ts72xx.c + * Technologic Systems TS72xx SBC support. + * + * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org> + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/mtd/physmap.h> +#include <linux/platform_device.h> +#include <linux/m48t86.h> +#include <linux/io.h> +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +static struct map_desc ts72xx_io_desc[] __initdata = { + { + .virtual = TS72XX_MODEL_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_MODEL_PHYS_BASE), + .length = TS72XX_MODEL_SIZE, + .type = MT_DEVICE, + }, { + .virtual = TS72XX_OPTIONS_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_OPTIONS_PHYS_BASE), + .length = TS72XX_OPTIONS_SIZE, + .type = MT_DEVICE, + }, { + .virtual = TS72XX_OPTIONS2_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE), + .length = TS72XX_OPTIONS2_SIZE, + .type = MT_DEVICE, + }, { + .virtual = TS72XX_RTC_INDEX_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_RTC_INDEX_PHYS_BASE), + .length = TS72XX_RTC_INDEX_SIZE, + .type = MT_DEVICE, + }, { + .virtual = TS72XX_RTC_DATA_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE), + .length = TS72XX_RTC_DATA_SIZE, + .type = MT_DEVICE, + } +}; + +static struct map_desc ts72xx_nand_io_desc[] __initdata = { + { + .virtual = TS72XX_NAND_DATA_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_NAND1_DATA_PHYS_BASE), + .length = TS72XX_NAND_DATA_SIZE, + .type = MT_DEVICE, + }, { + .virtual = TS72XX_NAND_CONTROL_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_NAND1_CONTROL_PHYS_BASE), + .length = TS72XX_NAND_CONTROL_SIZE, + .type = MT_DEVICE, + }, { + .virtual = TS72XX_NAND_BUSY_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_NAND1_BUSY_PHYS_BASE), + .length = TS72XX_NAND_BUSY_SIZE, + .type = MT_DEVICE, + } +}; + +static struct map_desc ts72xx_alternate_nand_io_desc[] __initdata = { + { + .virtual = TS72XX_NAND_DATA_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_NAND2_DATA_PHYS_BASE), + .length = TS72XX_NAND_DATA_SIZE, + .type = MT_DEVICE, + }, { + .virtual = TS72XX_NAND_CONTROL_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_NAND2_CONTROL_PHYS_BASE), + .length = TS72XX_NAND_CONTROL_SIZE, + .type = MT_DEVICE, + }, { + .virtual = TS72XX_NAND_BUSY_VIRT_BASE, + .pfn = __phys_to_pfn(TS72XX_NAND2_BUSY_PHYS_BASE), + .length = TS72XX_NAND_BUSY_SIZE, + .type = MT_DEVICE, + } +}; + +static void __init ts72xx_map_io(void) +{ + ep93xx_map_io(); + iotable_init(ts72xx_io_desc, ARRAY_SIZE(ts72xx_io_desc)); + + /* + * The TS-7200 has NOR flash, the other models have NAND flash. + */ + if (!board_is_ts7200()) { + if (is_ts9420_installed()) { + iotable_init(ts72xx_alternate_nand_io_desc, + ARRAY_SIZE(ts72xx_alternate_nand_io_desc)); + } else { + iotable_init(ts72xx_nand_io_desc, + ARRAY_SIZE(ts72xx_nand_io_desc)); + } + } +} + +static struct physmap_flash_data ts72xx_flash_data = { + .width = 1, +}; + +static struct resource ts72xx_flash_resource = { + .start = TS72XX_NOR_PHYS_BASE, + .end = TS72XX_NOR_PHYS_BASE + 0x00ffffff, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device ts72xx_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &ts72xx_flash_data, + }, + .num_resources = 1, + .resource = &ts72xx_flash_resource, +}; + +static unsigned char ts72xx_rtc_readbyte(unsigned long addr) +{ + __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE); + return __raw_readb(TS72XX_RTC_DATA_VIRT_BASE); +} + +static void ts72xx_rtc_writebyte(unsigned char value, unsigned long addr) +{ + __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE); + __raw_writeb(value, TS72XX_RTC_DATA_VIRT_BASE); +} + +static struct m48t86_ops ts72xx_rtc_ops = { + .readbyte = ts72xx_rtc_readbyte, + .writebyte = ts72xx_rtc_writebyte, +}; + +static struct platform_device ts72xx_rtc_device = { + .name = "rtc-m48t86", + .id = -1, + .dev = { + .platform_data = &ts72xx_rtc_ops, + }, + .num_resources = 0, +}; + +static struct ep93xx_eth_data ts72xx_eth_data = { + .phy_id = 1, +}; + +static void __init ts72xx_init_machine(void) +{ + ep93xx_init_devices(); + if (board_is_ts7200()) + platform_device_register(&ts72xx_flash); + platform_device_register(&ts72xx_rtc_device); + + ep93xx_register_eth(&ts72xx_eth_data, 1); +} + +MACHINE_START(TS72XX, "Technologic Systems TS-72xx SBC") + /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = 0x00000100, + .map_io = ts72xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = ts72xx_init_machine, +MACHINE_END |