diff options
Diffstat (limited to 'arch/mips/rb532')
| -rw-r--r-- | arch/mips/rb532/Makefile | 2 | ||||
| -rw-r--r-- | arch/mips/rb532/Platform | 7 | ||||
| -rw-r--r-- | arch/mips/rb532/devices.c | 111 | ||||
| -rw-r--r-- | arch/mips/rb532/gpio.c | 99 | ||||
| -rw-r--r-- | arch/mips/rb532/irq.c | 60 | ||||
| -rw-r--r-- | arch/mips/rb532/prom.c | 7 | ||||
| -rw-r--r-- | arch/mips/rb532/serial.c | 3 | ||||
| -rw-r--r-- | arch/mips/rb532/setup.c | 1 |
8 files changed, 142 insertions, 148 deletions
diff --git a/arch/mips/rb532/Makefile b/arch/mips/rb532/Makefile index 8f0b6b6a162..efdecdb6e3e 100644 --- a/arch/mips/rb532/Makefile +++ b/arch/mips/rb532/Makefile @@ -3,5 +3,3 @@ # obj-y += irq.o time.o setup.o serial.o prom.o gpio.o devices.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/rb532/Platform b/arch/mips/rb532/Platform new file mode 100644 index 00000000000..aeec45a7cbb --- /dev/null +++ b/arch/mips/rb532/Platform @@ -0,0 +1,7 @@ +# +# Routerboard 532 +# +platform-$(CONFIG_MIKROTIK_RB532) += rb532/ +cflags-$(CONFIG_MIKROTIK_RB532) += \ + -I$(srctree)/arch/mips/include/asm/mach-rc32434 +load-$(CONFIG_MIKROTIK_RB532) += 0xffffffff80101000 diff --git a/arch/mips/rb532/devices.c b/arch/mips/rb532/devices.c index c1c29181bd4..3af00b2a26e 100644 --- a/arch/mips/rb532/devices.c +++ b/arch/mips/rb532/devices.c @@ -15,6 +15,7 @@ * GNU General Public License for more details. */ #include <linux/kernel.h> +#include <linux/export.h> #include <linux/init.h> #include <linux/ctype.h> #include <linux/string.h> @@ -24,6 +25,7 @@ #include <linux/mtd/partitions.h> #include <linux/gpio_keys.h> #include <linux/input.h> +#include <linux/serial_8250.h> #include <asm/bootinfo.h> @@ -39,6 +41,29 @@ #define ETH0_RX_DMA_ADDR (DMA0_BASE_ADDR + 0 * DMA_CHAN_OFFSET) #define ETH0_TX_DMA_ADDR (DMA0_BASE_ADDR + 1 * DMA_CHAN_OFFSET) +extern unsigned int idt_cpu_freq; + +static struct mpmc_device dev3; + +void set_latch_u5(unsigned char or_mask, unsigned char nand_mask) +{ + unsigned long flags; + + spin_lock_irqsave(&dev3.lock, flags); + + dev3.state = (dev3.state | or_mask) & ~nand_mask; + writeb(dev3.state, dev3.base); + + spin_unlock_irqrestore(&dev3.lock, flags); +} +EXPORT_SYMBOL(set_latch_u5); + +unsigned char get_latch_u5(void) +{ + return dev3.state; +} +EXPORT_SYMBOL(get_latch_u5); + static struct resource korina_dev0_res[] = { { .name = "korina_regs", @@ -86,7 +111,6 @@ static struct korina_device korina_dev0_data = { static struct platform_device korina_dev0 = { .id = -1, .name = "korina", - .dev.platform_data = &korina_dev0_data, .resource = korina_dev0_res, .num_resources = ARRAY_SIZE(korina_dev0_res), }; @@ -176,26 +200,9 @@ static struct platform_device rb532_led = { .id = -1, }; -static struct gpio_keys_button rb532_gpio_btn[] = { - { - .gpio = 1, - .code = BTN_0, - .desc = "S1", - .active_low = 1, - } -}; - -static struct gpio_keys_platform_data rb532_gpio_btn_data = { - .buttons = rb532_gpio_btn, - .nbuttons = ARRAY_SIZE(rb532_gpio_btn), -}; - static struct platform_device rb532_button = { - .name = "gpio-keys", + .name = "rb532-button", .id = -1, - .dev = { - .platform_data = &rb532_gpio_btn_data, - } }; static struct resource rb532_wdt_res[] = { @@ -208,51 +215,65 @@ static struct resource rb532_wdt_res[] = { }; static struct platform_device rb532_wdt = { - .name = "rc32434_wdt", - .id = -1, - .resource = rb532_wdt_res, + .name = "rc32434_wdt", + .id = -1, + .resource = rb532_wdt_res, .num_resources = ARRAY_SIZE(rb532_wdt_res), }; +static struct plat_serial8250_port rb532_uart_res[] = { + { + .membase = (char *)KSEG1ADDR(REGBASE + UART0BASE), + .irq = UART0_IRQ, + .regshift = 2, + .iotype = UPIO_MEM, + .flags = UPF_BOOT_AUTOCONF, + }, + { + .flags = 0, + } +}; + +static struct platform_device rb532_uart = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev.platform_data = &rb532_uart_res, +}; + static struct platform_device *rb532_devs[] = { &korina_dev0, &nand_slot0, &cf_slot0, &rb532_led, &rb532_button, + &rb532_uart, &rb532_wdt }; static void __init parse_mac_addr(char *macstr) { - int i, j; - unsigned char result, value; + int i, h, l; for (i = 0; i < 6; i++) { - result = 0; - if (i != 5 && *(macstr + 2) != ':') return; - for (j = 0; j < 2; j++) { - if (isxdigit(*macstr) - && (value = - isdigit(*macstr) ? *macstr - - '0' : toupper(*macstr) - 'A' + 10) < 16) { - result = result * 16 + value; - macstr++; - } else - return; - } + h = hex_to_bin(*macstr++); + if (h == -1) + return; + + l = hex_to_bin(*macstr++); + if (l == -1) + return; macstr++; - korina_dev0_data.mac[i] = result; + korina_dev0_data.mac[i] = (h << 4) + l; } } /* NAND definitions */ -#define NAND_CHIP_DELAY 25 +#define NAND_CHIP_DELAY 25 static void __init rb532_nand_setup(void) { @@ -272,7 +293,6 @@ static void __init rb532_nand_setup(void) rb532_nand_data.chip.nr_partitions = ARRAY_SIZE(rb532_partition_info); rb532_nand_data.chip.partitions = rb532_partition_info; rb532_nand_data.chip.chip_delay = NAND_CHIP_DELAY; - rb532_nand_data.chip.options = NAND_NO_AUTOINCR; } @@ -291,9 +311,22 @@ static int __init plat_setup_devices(void) nand_slot0_res[0].start = readl(IDT434_REG_BASE + DEV2BASE); nand_slot0_res[0].end = nand_slot0_res[0].start + 0x1000; + /* Read and map device controller 3 */ + dev3.base = ioremap_nocache(readl(IDT434_REG_BASE + DEV3BASE), 1); + + if (!dev3.base) { + printk(KERN_ERR "rb532: cannot remap device controller 3\n"); + return -ENXIO; + } + /* Initialise the NAND device */ rb532_nand_setup(); + /* set the uart clock to the current cpu frequency */ + rb532_uart_res[0].uartclk = idt_cpu_freq; + + dev_set_drvdata(&korina_dev0.dev, &korina_dev0_data); + return platform_add_devices(rb532_devs, ARRAY_SIZE(rb532_devs)); } diff --git a/arch/mips/rb532/gpio.c b/arch/mips/rb532/gpio.c index 0e84c8ab6a3..a18007613c3 100644 --- a/arch/mips/rb532/gpio.c +++ b/arch/mips/rb532/gpio.c @@ -29,6 +29,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/types.h> +#include <linux/export.h> #include <linux/spinlock.h> #include <linux/platform_device.h> #include <linux/gpio.h> @@ -41,72 +42,15 @@ struct rb532_gpio_chip { void __iomem *regbase; }; -struct mpmc_device dev3; - static struct resource rb532_gpio_reg0_res[] = { { - .name = "gpio_reg0", - .start = REGBASE + GPIOBASE, - .end = REGBASE + GPIOBASE + sizeof(struct rb532_gpio_reg) - 1, - .flags = IORESOURCE_MEM, - } -}; - -static struct resource rb532_dev3_ctl_res[] = { - { - .name = "dev3_ctl", - .start = REGBASE + DEV3BASE, - .end = REGBASE + DEV3BASE + sizeof(struct dev_reg) - 1, + .name = "gpio_reg0", + .start = REGBASE + GPIOBASE, + .end = REGBASE + GPIOBASE + sizeof(struct rb532_gpio_reg) - 1, .flags = IORESOURCE_MEM, } }; -void set_434_reg(unsigned reg_offs, unsigned bit, unsigned len, unsigned val) -{ - unsigned long flags; - unsigned data; - unsigned i = 0; - - spin_lock_irqsave(&dev3.lock, flags); - - data = readl(IDT434_REG_BASE + reg_offs); - for (i = 0; i != len; ++i) { - if (val & (1 << i)) - data |= (1 << (i + bit)); - else - data &= ~(1 << (i + bit)); - } - writel(data, (IDT434_REG_BASE + reg_offs)); - - spin_unlock_irqrestore(&dev3.lock, flags); -} -EXPORT_SYMBOL(set_434_reg); - -unsigned get_434_reg(unsigned reg_offs) -{ - return readl(IDT434_REG_BASE + reg_offs); -} -EXPORT_SYMBOL(get_434_reg); - -void set_latch_u5(unsigned char or_mask, unsigned char nand_mask) -{ - unsigned long flags; - - spin_lock_irqsave(&dev3.lock, flags); - - dev3.state = (dev3.state | or_mask) & ~nand_mask; - writel(dev3.state, &dev3.base); - - spin_unlock_irqrestore(&dev3.lock, flags); -} -EXPORT_SYMBOL(set_latch_u5); - -unsigned char get_latch_u5(void) -{ - return dev3.state; -} -EXPORT_SYMBOL(get_latch_u5); - /* rb532_set_bit - sanely set a bit * * bitval: new value for the bit @@ -119,13 +63,11 @@ static inline void rb532_set_bit(unsigned bitval, unsigned long flags; u32 val; - bitval = !!bitval; /* map parameter to {0,1} */ - local_irq_save(flags); val = readl(ioaddr); - val &= ~( ~bitval << offset ); /* unset bit if bitval == 0 */ - val |= ( bitval << offset ); /* set bit if bitval == 1 */ + val &= ~(!bitval << offset); /* unset bit if bitval == 0 */ + val |= (!!bitval << offset); /* set bit if bitval == 1 */ writel(val, ioaddr); local_irq_restore(flags); @@ -171,8 +113,8 @@ static int rb532_gpio_direction_input(struct gpio_chip *chip, unsigned offset) gpch = container_of(chip, struct rb532_gpio_chip, chip); - if (rb532_get_bit(offset, gpch->regbase + GPIOFUNC)) - return 1; /* alternate function, GPIOCFG is ignored */ + /* disable alternate function in case it's set */ + rb532_set_bit(0, offset, gpch->regbase + GPIOFUNC); rb532_set_bit(0, offset, gpch->regbase + GPIOCFG); return 0; @@ -188,8 +130,8 @@ static int rb532_gpio_direction_output(struct gpio_chip *chip, gpch = container_of(chip, struct rb532_gpio_chip, chip); - if (rb532_get_bit(offset, gpch->regbase + GPIOFUNC)) - return 1; /* alternate function, GPIOCFG is ignored */ + /* disable alternate function in case it's set */ + rb532_set_bit(0, offset, gpch->regbase + GPIOFUNC); /* set the initial output value */ rb532_set_bit(value, offset, gpch->regbase + GPIOD); @@ -233,17 +175,18 @@ EXPORT_SYMBOL(rb532_gpio_set_istat); /* * Configure GPIO alternate function */ -static void rb532_gpio_set_func(int bit, unsigned gpio) +void rb532_gpio_set_func(unsigned gpio) { - rb532_set_bit(bit, gpio, rb532_gpio_chip->regbase + GPIOFUNC); + rb532_set_bit(1, gpio, rb532_gpio_chip->regbase + GPIOFUNC); } +EXPORT_SYMBOL(rb532_gpio_set_func); int __init rb532_gpio_init(void) { struct resource *r; r = rb532_gpio_reg0_res; - rb532_gpio_chip->regbase = ioremap_nocache(r->start, r->end - r->start); + rb532_gpio_chip->regbase = ioremap_nocache(r->start, resource_size(r)); if (!rb532_gpio_chip->regbase) { printk(KERN_ERR "rb532: cannot remap GPIO register 0\n"); @@ -253,20 +196,6 @@ int __init rb532_gpio_init(void) /* Register our GPIO chip */ gpiochip_add(&rb532_gpio_chip->chip); - r = rb532_dev3_ctl_res; - dev3.base = ioremap_nocache(r->start, r->end - r->start); - - if (!dev3.base) { - printk(KERN_ERR "rb532: cannot remap device controller 3\n"); - return -ENXIO; - } - - /* configure CF_GPIO_NUM as CFRDY IRQ source */ - rb532_gpio_set_func(0, CF_GPIO_NUM); - rb532_gpio_direction_input(&rb532_gpio_chip->chip, CF_GPIO_NUM); - rb532_gpio_set_ilevel(1, CF_GPIO_NUM); - rb532_gpio_set_istat(0, CF_GPIO_NUM); - return 0; } arch_initcall(rb532_gpio_init); diff --git a/arch/mips/rb532/irq.c b/arch/mips/rb532/irq.c index 549b46d2fce..3a431e802bb 100644 --- a/arch/mips/rb532/irq.c +++ b/arch/mips/rb532/irq.c @@ -21,7 +21,7 @@ * * Copyright 2002 MontaVista Software Inc. * Author: MontaVista Software, Inc. - * stevel@mvista.com or source@mvista.com + * stevel@mvista.com or source@mvista.com */ #include <linux/bitops.h> @@ -36,23 +36,22 @@ #include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/timex.h> -#include <linux/slab.h> #include <linux/random.h> #include <linux/delay.h> #include <asm/bootinfo.h> #include <asm/time.h> #include <asm/mipsregs.h> -#include <asm/system.h> #include <asm/mach-rc32434/irq.h> +#include <asm/mach-rc32434/gpio.h> struct intr_group { u32 mask; /* mask of valid bits in pending/mask registers */ volatile u32 *base_addr; }; -#define RC32434_NR_IRQS (GROUP4_IRQ_BASE + 32) +#define RC32434_NR_IRQS (GROUP4_IRQ_BASE + 32) #if (NR_IRQS < RC32434_NR_IRQS) #error Too little irqs defined. Did you override <asm/irq.h> ? @@ -111,10 +110,10 @@ static inline void ack_local_irq(unsigned int ip) clear_c0_cause(ipnum); } -static void rb532_enable_irq(unsigned int irq_nr) +static void rb532_enable_irq(struct irq_data *d) { + unsigned int group, intr_bit, irq_nr = d->irq; int ip = irq_nr - GROUP0_IRQ_BASE; - unsigned int group, intr_bit; volatile unsigned int *addr; if (ip < 0) @@ -132,10 +131,10 @@ static void rb532_enable_irq(unsigned int irq_nr) } } -static void rb532_disable_irq(unsigned int irq_nr) +static void rb532_disable_irq(struct irq_data *d) { + unsigned int group, intr_bit, mask, irq_nr = d->irq; int ip = irq_nr - GROUP0_IRQ_BASE; - unsigned int group, intr_bit, mask; volatile unsigned int *addr; if (ip < 0) { @@ -150,6 +149,10 @@ static void rb532_disable_irq(unsigned int irq_nr) mask |= intr_bit; WRITE_MASK(addr, mask); + /* There is a maximum of 14 GPIO interrupts */ + if (group == GPIO_MAPPED_IRQ_GROUP && irq_nr <= (GROUP4_IRQ_BASE + 13)) + rb532_gpio_set_istat(0, irq_nr - GPIO_MAPPED_IRQ_BASE); + /* * if there are no more interrupts enabled in this * group, disable corresponding IP @@ -159,18 +162,41 @@ static void rb532_disable_irq(unsigned int irq_nr) } } -static void rb532_mask_and_ack_irq(unsigned int irq_nr) +static void rb532_mask_and_ack_irq(struct irq_data *d) +{ + rb532_disable_irq(d); + ack_local_irq(group_to_ip(irq_to_group(d->irq))); +} + +static int rb532_set_type(struct irq_data *d, unsigned type) { - rb532_disable_irq(irq_nr); - ack_local_irq(group_to_ip(irq_to_group(irq_nr))); + int gpio = d->irq - GPIO_MAPPED_IRQ_BASE; + int group = irq_to_group(d->irq); + + if (group != GPIO_MAPPED_IRQ_GROUP || d->irq > (GROUP4_IRQ_BASE + 13)) + return (type == IRQ_TYPE_LEVEL_HIGH) ? 0 : -EINVAL; + + switch (type) { + case IRQ_TYPE_LEVEL_HIGH: + rb532_gpio_set_ilevel(1, gpio); + break; + case IRQ_TYPE_LEVEL_LOW: + rb532_gpio_set_ilevel(0, gpio); + break; + default: + return -EINVAL; + } + + return 0; } static struct irq_chip rc32434_irq_type = { .name = "RB532", - .ack = rb532_disable_irq, - .mask = rb532_disable_irq, - .mask_ack = rb532_mask_and_ack_irq, - .unmask = rb532_enable_irq, + .irq_ack = rb532_disable_irq, + .irq_mask = rb532_disable_irq, + .irq_mask_ack = rb532_mask_and_ack_irq, + .irq_unmask = rb532_enable_irq, + .irq_set_type = rb532_set_type, }; void __init arch_init_irq(void) @@ -180,8 +206,8 @@ void __init arch_init_irq(void) pr_info("Initializing IRQ's: %d out of %d\n", RC32434_NR_IRQS, NR_IRQS); for (i = 0; i < RC32434_NR_IRQS; i++) - set_irq_chip_and_handler(i, &rc32434_irq_type, - handle_level_irq); + irq_set_chip_and_handler(i, &rc32434_irq_type, + handle_level_irq); } /* Main Interrupt dispatcher */ diff --git a/arch/mips/rb532/prom.c b/arch/mips/rb532/prom.c index 46ca24dbcc2..a757ded437c 100644 --- a/arch/mips/rb532/prom.c +++ b/arch/mips/rb532/prom.c @@ -69,15 +69,14 @@ static inline unsigned long tag2ul(char *arg, const char *tag) void __init prom_setup_cmdline(void) { - char cmd_line[CL_SIZE]; + static char cmd_line[COMMAND_LINE_SIZE] __initdata; char *cp, *board; int prom_argc; - char **prom_argv, **prom_envp; + char **prom_argv; int i; prom_argc = fw_arg0; prom_argv = (char **) fw_arg1; - prom_envp = (char **) fw_arg2; cp = cmd_line; /* Note: it is common that parameters start @@ -115,7 +114,7 @@ void __init prom_setup_cmdline(void) strcpy(cp, arcs_cmdline); cp += strlen(arcs_cmdline); } - cmd_line[CL_SIZE-1] = '\0'; + cmd_line[COMMAND_LINE_SIZE - 1] = '\0'; strcpy(arcs_cmdline, cmd_line); } diff --git a/arch/mips/rb532/serial.c b/arch/mips/rb532/serial.c index 3e0d7ec3a57..70482540b3d 100644 --- a/arch/mips/rb532/serial.c +++ b/arch/mips/rb532/serial.c @@ -29,6 +29,7 @@ #include <linux/tty.h> #include <linux/serial_core.h> #include <linux/serial_8250.h> +#include <linux/irq.h> #include <asm/serial.h> #include <asm/mach-rc32434/rb.h> @@ -36,7 +37,7 @@ extern unsigned int idt_cpu_freq; static struct uart_port rb532_uart = { - .type = PORT_16550A, + .flags = UPF_BOOT_AUTOCONF, .line = 0, .irq = UART0_IRQ, .iotype = UPIO_MEM, diff --git a/arch/mips/rb532/setup.c b/arch/mips/rb532/setup.c index 50f530f5b60..d0c64e71d53 100644 --- a/arch/mips/rb532/setup.c +++ b/arch/mips/rb532/setup.c @@ -3,6 +3,7 @@ */ #include <linux/init.h> +#include <linux/export.h> #include <asm/bootinfo.h> #include <asm/reboot.h> |
