From 3e062b07ada88edb9ffdd147e39c7df4b4418f64 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Tue, 5 Jun 2007 16:36:55 +0100 Subject: [PATCH 01/45] [ARM] 4430/1: davinci: clock control support Support clock control driver for TI DaVinci SoC Signed-off-by: Vladimir Barinov Signed-off-by: Kevin Hilman Signed-off-by: Russell King --- arch/arm/mach-davinci/Makefile | 2 +- arch/arm/mach-davinci/board-evm.c | 2 + arch/arm/mach-davinci/clock.c | 323 +++++++++++++++++++++++++++ arch/arm/mach-davinci/clock.h | 33 +++ arch/arm/mach-davinci/io.c | 6 + include/asm-arm/arch-davinci/clock.h | 22 ++ 6 files changed, 387 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-davinci/clock.c create mode 100644 arch/arm/mach-davinci/clock.h create mode 100644 include/asm-arm/arch-davinci/clock.h diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index a8f88cd29905..b86c7f046204 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -4,7 +4,7 @@ # # Common objects -obj-y := time.o irq.o serial.o io.o id.o psc.o +obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o # Board specific obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-evm.c index 633c12e43044..9e4024c4965f 100644 --- a/arch/arm/mach-davinci/board-evm.c +++ b/arch/arm/mach-davinci/board-evm.c @@ -32,6 +32,7 @@ void __init davinci_psc_init(void); void __init davinci_irq_init(void); void __init davinci_map_common_io(void); +void __init davinci_init_common_hw(void); /* NOR Flash base address set to CS0 by default */ #define NOR_FLASH_PHYS 0x02000000 @@ -116,6 +117,7 @@ static __init void davinci_evm_init(void) static __init void davinci_evm_irq_init(void) { + davinci_init_common_hw(); davinci_irq_init(); } diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c new file mode 100644 index 000000000000..139ceaa35e24 --- /dev/null +++ b/arch/arm/mach-davinci/clock.c @@ -0,0 +1,323 @@ +/* + * TI DaVinci clock config file + * + * Copyright (C) 2006 Texas Instruments. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "clock.h" + +/* PLL/Reset register offsets */ +#define PLLM 0x110 + +static LIST_HEAD(clocks); +static DEFINE_MUTEX(clocks_mutex); +static DEFINE_SPINLOCK(clockfw_lock); + +static unsigned int commonrate; +static unsigned int armrate; +static unsigned int fixedrate = 27000000; /* 27 MHZ */ + +extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable); + +/* + * Returns a clock. Note that we first try to use device id on the bus + * and clock name. If this fails, we try to use clock name only. + */ +struct clk *clk_get(struct device *dev, const char *id) +{ + struct clk *p, *clk = ERR_PTR(-ENOENT); + int idno; + + if (dev == NULL || dev->bus != &platform_bus_type) + idno = -1; + else + idno = to_platform_device(dev)->id; + + mutex_lock(&clocks_mutex); + + list_for_each_entry(p, &clocks, node) { + if (p->id == idno && + strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + clk = p; + goto found; + } + } + + list_for_each_entry(p, &clocks, node) { + if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { + clk = p; + break; + } + } + +found: + mutex_unlock(&clocks_mutex); + + return clk; +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ + if (clk && !IS_ERR(clk)) + module_put(clk->owner); +} +EXPORT_SYMBOL(clk_put); + +static int __clk_enable(struct clk *clk) +{ + if (clk->flags & ALWAYS_ENABLED) + return 0; + + davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1); + return 0; +} + +static void __clk_disable(struct clk *clk) +{ + if (clk->usecount) + return; + + davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0); +} + +int clk_enable(struct clk *clk) +{ + unsigned long flags; + int ret = 0; + + if (clk == NULL || IS_ERR(clk)) + return -EINVAL; + + if (clk->usecount++ == 0) { + spin_lock_irqsave(&clockfw_lock, flags); + ret = __clk_enable(clk); + spin_unlock_irqrestore(&clockfw_lock, flags); + } + + return ret; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + if (clk == NULL || IS_ERR(clk)) + return; + + if (clk->usecount > 0 && !(--clk->usecount)) { + spin_lock_irqsave(&clockfw_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clockfw_lock, flags); + } +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + if (clk == NULL || IS_ERR(clk)) + return -EINVAL; + + return *(clk->rate); +} +EXPORT_SYMBOL(clk_get_rate); + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (clk == NULL || IS_ERR(clk)) + return -EINVAL; + + return *(clk->rate); +} +EXPORT_SYMBOL(clk_round_rate); + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + if (clk == NULL || IS_ERR(clk)) + return -EINVAL; + + /* changing the clk rate is not supported */ + return -EINVAL; +} +EXPORT_SYMBOL(clk_set_rate); + +int clk_register(struct clk *clk) +{ + if (clk == NULL || IS_ERR(clk)) + return -EINVAL; + + mutex_lock(&clocks_mutex); + list_add(&clk->node, &clocks); + mutex_unlock(&clocks_mutex); + + return 0; +} +EXPORT_SYMBOL(clk_register); + +void clk_unregister(struct clk *clk) +{ + if (clk == NULL || IS_ERR(clk)) + return; + + mutex_lock(&clocks_mutex); + list_del(&clk->node); + mutex_unlock(&clocks_mutex); +} +EXPORT_SYMBOL(clk_unregister); + +static struct clk davinci_clks[] = { + { + .name = "ARMCLK", + .rate = &armrate, + .lpsc = -1, + .flags = ALWAYS_ENABLED, + }, + { + .name = "UART", + .rate = &fixedrate, + .lpsc = DAVINCI_LPSC_UART0, + }, + { + .name = "EMACCLK", + .rate = &commonrate, + .lpsc = DAVINCI_LPSC_EMAC_WRAPPER, + }, + { + .name = "I2CCLK", + .rate = &fixedrate, + .lpsc = DAVINCI_LPSC_I2C, + }, + { + .name = "IDECLK", + .rate = &commonrate, + .lpsc = DAVINCI_LPSC_ATA, + }, + { + .name = "McBSPCLK", + .rate = &commonrate, + .lpsc = DAVINCI_LPSC_McBSP, + }, + { + .name = "MMCSDCLK", + .rate = &commonrate, + .lpsc = DAVINCI_LPSC_MMC_SD, + }, + { + .name = "SPICLK", + .rate = &commonrate, + .lpsc = DAVINCI_LPSC_SPI, + }, + { + .name = "gpio", + .rate = &commonrate, + .lpsc = DAVINCI_LPSC_GPIO, + }, + { + .name = "AEMIFCLK", + .rate = &commonrate, + .lpsc = DAVINCI_LPSC_AEMIF, + .usecount = 1, + } +}; + +int __init davinci_clk_init(void) +{ + struct clk *clkp; + int count = 0; + u32 pll_mult; + + pll_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM); + commonrate = ((pll_mult + 1) * 27000000) / 6; + armrate = ((pll_mult + 1) * 27000000) / 2; + + for (clkp = davinci_clks; count < ARRAY_SIZE(davinci_clks); + count++, clkp++) { + clk_register(clkp); + + /* Turn on clocks that have been enabled in the + * table above */ + if (clkp->usecount) + clk_enable(clkp); + } + + return 0; +} + +#ifdef CONFIG_PROC_FS +#include +#include + +static void *davinci_ck_start(struct seq_file *m, loff_t *pos) +{ + return *pos < 1 ? (void *)1 : NULL; +} + +static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos) +{ + ++*pos; + return NULL; +} + +static void davinci_ck_stop(struct seq_file *m, void *v) +{ +} + +static int davinci_ck_show(struct seq_file *m, void *v) +{ + struct clk *cp; + + list_for_each_entry(cp, &clocks, node) + seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount); + + return 0; +} + +static struct seq_operations davinci_ck_op = { + .start = davinci_ck_start, + .next = davinci_ck_next, + .stop = davinci_ck_stop, + .show = davinci_ck_show +}; + +static int davinci_ck_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &davinci_ck_op); +} + +static struct file_operations proc_davinci_ck_operations = { + .open = davinci_ck_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static int __init davinci_ck_proc_init(void) +{ + struct proc_dir_entry *entry; + + entry = create_proc_entry("davinci_clocks", 0, NULL); + if (entry) + entry->proc_fops = &proc_davinci_ck_operations; + return 0; + +} +__initcall(davinci_ck_proc_init); +#endif /* CONFIG_DEBUG_PROC_FS */ diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h new file mode 100644 index 000000000000..ed47079a52e4 --- /dev/null +++ b/arch/arm/mach-davinci/clock.h @@ -0,0 +1,33 @@ +/* + * TI DaVinci clock definitions + * + * Copyright (C) 2006 Texas Instruments. + * + * 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. + */ + +#ifndef __ARCH_ARM_DAVINCI_CLOCK_H +#define __ARCH_ARM_DAVINCI_CLOCK_H + +struct clk { + struct list_head node; + struct module *owner; + const char *name; + unsigned int *rate; + int id; + __s8 usecount; + __u8 flags; + __u8 lpsc; +}; + +/* Clock flags */ +#define RATE_CKCTL 1 +#define RATE_FIXED 2 +#define RATE_PROPAGATES 4 +#define VIRTUAL_CLOCK 8 +#define ALWAYS_ENABLED 16 +#define ENABLE_REG_32BIT 32 + +#endif diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c index 87fae6fb6ecf..47787ff84a6a 100644 --- a/arch/arm/mach-davinci/io.c +++ b/arch/arm/mach-davinci/io.c @@ -17,6 +17,7 @@ #include #include +#include extern void davinci_check_revision(void); @@ -49,3 +50,8 @@ void __init davinci_map_common_io(void) */ davinci_check_revision(); } + +void __init davinci_init_common_hw(void) +{ + davinci_clk_init(); +} diff --git a/include/asm-arm/arch-davinci/clock.h b/include/asm-arm/arch-davinci/clock.h new file mode 100644 index 000000000000..cc168b7a14f2 --- /dev/null +++ b/include/asm-arm/arch-davinci/clock.h @@ -0,0 +1,22 @@ +/* + * include/asm-arm/arch-davinci/clock.h + * + * Clock control driver for DaVinci - header file + * + * Authors: Vladimir Barinov + * + * 2007 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef __ASM_ARCH_DAVINCI_CLOCK_H +#define __ASM_ARCH_DAVINCI_CLOCK_H + +struct clk; + +extern int clk_register(struct clk *clk); +extern void clk_unregister(struct clk *clk); +extern int davinci_clk_init(void); + +#endif From 3d9edf09d4525dad95f98b31f31aa86b8071fab9 Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Tue, 10 Jul 2007 13:03:43 +0100 Subject: [PATCH 02/45] [ARM] 4457/2: davinci: GPIO support Support GPIO driver for TI DaVinci SoC Signed-off-by: Vladimir Barinov Acked-by: David Brownell Acked-by: Kevin Hilman Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/mach-davinci/Makefile | 3 +- arch/arm/mach-davinci/gpio.c | 286 ++++++++++++++++++++++++ include/asm-arm/arch-davinci/gpio.h | 156 +++++++++++++ include/asm-arm/arch-davinci/hardware.h | 38 ++++ 5 files changed, 483 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-davinci/gpio.c create mode 100644 include/asm-arm/arch-davinci/gpio.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 50d9f3e4e0f1..d0aaecbcdf72 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -384,6 +384,7 @@ config ARCH_DAVINCI bool "TI DaVinci" select GENERIC_TIME select GENERIC_CLOCKEVENTS + select GENERIC_GPIO help Support for TI's DaVinci platform. diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index b86c7f046204..731c0a6d5176 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -4,7 +4,8 @@ # # Common objects -obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o +obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o \ + gpio.o # Board specific obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c new file mode 100644 index 000000000000..9c67886e7189 --- /dev/null +++ b/arch/arm/mach-davinci/gpio.c @@ -0,0 +1,286 @@ +/* + * TI DaVinci GPIO Support + * + * Copyright (c) 2006 David Brownell + * Copyright (c) 2007, MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +static DEFINE_SPINLOCK(gpio_lock); +static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO); + +int gpio_request(unsigned gpio, const char *tag) +{ + if (gpio >= DAVINCI_N_GPIO) + return -EINVAL; + + if (test_and_set_bit(gpio, gpio_in_use)) + return -EBUSY; + + return 0; +} +EXPORT_SYMBOL(gpio_request); + +void gpio_free(unsigned gpio) +{ + if (gpio >= DAVINCI_N_GPIO) + return; + + clear_bit(gpio, gpio_in_use); +} +EXPORT_SYMBOL(gpio_free); + +/* create a non-inlined version */ +static struct gpio_controller *__iomem gpio2controller(unsigned gpio) +{ + return __gpio_to_controller(gpio); +} + +/* + * Assuming the pin is muxed as a gpio output, set its output value. + */ +void __gpio_set(unsigned gpio, int value) +{ + struct gpio_controller *__iomem g = gpio2controller(gpio); + + __raw_writel(__gpio_mask(gpio), value ? &g->set_data : &g->clr_data); +} +EXPORT_SYMBOL(__gpio_set); + + +/* + * Read the pin's value (works even if it's set up as output); + * returns zero/nonzero. + * + * Note that changes are synched to the GPIO clock, so reading values back + * right after you've set them may give old values. + */ +int __gpio_get(unsigned gpio) +{ + struct gpio_controller *__iomem g = gpio2controller(gpio); + + return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data)); +} +EXPORT_SYMBOL(__gpio_get); + + +/*--------------------------------------------------------------------------*/ + +/* + * board setup code *MUST* set PINMUX0 and PINMUX1 as + * needed, and enable the GPIO clock. + */ + +int gpio_direction_input(unsigned gpio) +{ + struct gpio_controller *__iomem g = gpio2controller(gpio); + u32 temp; + u32 mask; + + if (!g) + return -EINVAL; + + spin_lock(&gpio_lock); + mask = __gpio_mask(gpio); + temp = __raw_readl(&g->dir); + temp |= mask; + __raw_writel(temp, &g->dir); + spin_unlock(&gpio_lock); + return 0; +} +EXPORT_SYMBOL(gpio_direction_input); + +int gpio_direction_output(unsigned gpio, int value) +{ + struct gpio_controller *__iomem g = gpio2controller(gpio); + u32 temp; + u32 mask; + + if (!g) + return -EINVAL; + + spin_lock(&gpio_lock); + mask = __gpio_mask(gpio); + temp = __raw_readl(&g->dir); + temp &= ~mask; + __raw_writel(mask, value ? &g->set_data : &g->clr_data); + __raw_writel(temp, &g->dir); + spin_unlock(&gpio_lock); + return 0; +} +EXPORT_SYMBOL(gpio_direction_output); + +/* + * We expect irqs will normally be set up as input pins, but they can also be + * used as output pins ... which is convenient for testing. + * + * NOTE: GPIO0..GPIO7 also have direct INTC hookups, which work in addition + * to their GPIOBNK0 irq (but with a bit less overhead). But we don't have + * a good way to hook those up ... + * + * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also + * serve as EDMA event triggers. + */ + +static void gpio_irq_disable(unsigned irq) +{ + struct gpio_controller *__iomem g = get_irq_chip_data(irq); + u32 mask = __gpio_mask(irq_to_gpio(irq)); + + __raw_writel(mask, &g->clr_falling); + __raw_writel(mask, &g->clr_rising); +} + +static void gpio_irq_enable(unsigned irq) +{ + struct gpio_controller *__iomem g = get_irq_chip_data(irq); + u32 mask = __gpio_mask(irq_to_gpio(irq)); + + if (irq_desc[irq].status & IRQ_TYPE_EDGE_FALLING) + __raw_writel(mask, &g->set_falling); + if (irq_desc[irq].status & IRQ_TYPE_EDGE_RISING) + __raw_writel(mask, &g->set_rising); +} + +static int gpio_irq_type(unsigned irq, unsigned trigger) +{ + struct gpio_controller *__iomem g = get_irq_chip_data(irq); + u32 mask = __gpio_mask(irq_to_gpio(irq)); + + if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) + return -EINVAL; + + irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK; + irq_desc[irq].status |= trigger; + + __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING) + ? &g->set_falling : &g->clr_falling); + __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING) + ? &g->set_rising : &g->clr_rising); + return 0; +} + +static struct irq_chip gpio_irqchip = { + .name = "GPIO", + .enable = gpio_irq_enable, + .disable = gpio_irq_disable, + .set_type = gpio_irq_type, +}; + +static void +gpio_irq_handler(unsigned irq, struct irq_desc *desc) +{ + struct gpio_controller *__iomem g = get_irq_chip_data(irq); + u32 mask = 0xffff; + + /* we only care about one bank */ + if (irq & 1) + mask <<= 16; + + /* temporarily mask (level sensitive) parent IRQ */ + desc->chip->ack(irq); + while (1) { + u32 status; + struct irq_desc *gpio; + int n; + int res; + + /* ack any irqs */ + status = __raw_readl(&g->intstat) & mask; + if (!status) + break; + __raw_writel(status, &g->intstat); + if (irq & 1) + status >>= 16; + + /* now demux them to the right lowlevel handler */ + n = (int)get_irq_data(irq); + gpio = &irq_desc[n]; + while (status) { + res = ffs(status); + n += res; + gpio += res; + desc_handle_irq(n - 1, gpio - 1); + status >>= res; + } + } + desc->chip->unmask(irq); + /* now it may re-trigger */ +} + +/* + * NOTE: for suspend/resume, probably best to make a sysdev (and class) + * with its suspend/resume calls hooking into the results of the set_wake() + * calls ... so if no gpios are wakeup events the clock can be disabled, + * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0 + * can be set appropriately for GPIOV33 pins. + */ + +static int __init davinci_gpio_irq_setup(void) +{ + unsigned gpio, irq, bank; + struct clk *clk; + + clk = clk_get(NULL, "gpio"); + if (IS_ERR(clk)) { + printk(KERN_ERR "Error %ld getting gpio clock?\n", + PTR_ERR(clk)); + return 0; + } + + clk_enable(clk); + + for (gpio = 0, irq = gpio_to_irq(0), bank = IRQ_GPIOBNK0; + gpio < DAVINCI_N_GPIO; bank++) { + struct gpio_controller *__iomem g = gpio2controller(gpio); + unsigned i; + + __raw_writel(~0, &g->clr_falling); + __raw_writel(~0, &g->clr_rising); + + /* set up all irqs in this bank */ + set_irq_chained_handler(bank, gpio_irq_handler); + set_irq_chip_data(bank, g); + set_irq_data(bank, (void *)irq); + + for (i = 0; i < 16 && gpio < DAVINCI_N_GPIO; + i++, irq++, gpio++) { + set_irq_chip(irq, &gpio_irqchip); + set_irq_chip_data(irq, g); + set_irq_handler(irq, handle_simple_irq); + set_irq_flags(irq, IRQF_VALID); + } + } + + /* BINTEN -- per-bank interrupt enable. genirq would also let these + * bits be set/cleared dynamically. + */ + __raw_writel(0x1f, (void *__iomem) + IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08)); + + printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0)); + + return 0; +} + +arch_initcall(davinci_gpio_irq_setup); diff --git a/include/asm-arm/arch-davinci/gpio.h b/include/asm-arm/arch-davinci/gpio.h new file mode 100644 index 000000000000..ea24a0e0bfd6 --- /dev/null +++ b/include/asm-arm/arch-davinci/gpio.h @@ -0,0 +1,156 @@ +/* + * TI DaVinci GPIO Support + * + * Copyright (c) 2006 David Brownell + * Copyright (c) 2007, MontaVista Software, Inc. + * + * 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. + */ + +#ifndef __DAVINCI_GPIO_H +#define __DAVINCI_GPIO_H + +/* + * basic gpio routines + * + * board-specific init should be done by arch/.../.../board-XXX.c (maybe + * initializing banks together) rather than boot loaders; kexec() won't + * go through boot loaders. + * + * the gpio clock will be turned on when gpios are used, and you may also + * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are + * used as gpios, not with other peripherals. + * + * GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation, and maybe + * for later updates, code should write GPIO(N) or: + * - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53) + * - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70) + * + * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc + * for now, that's != GPIO(N) + */ +#define GPIO(X) (X) /* 0 <= X <= 70 */ +#define GPIOV18(X) (X) /* 1.8V i/o; 0 <= X <= 53 */ +#define GPIOV33(X) ((X)+54) /* 3.3V i/o; 0 <= X <= 17 */ + +struct gpio_controller { + u32 dir; + u32 out_data; + u32 set_data; + u32 clr_data; + u32 in_data; + u32 set_rising; + u32 clr_rising; + u32 set_falling; + u32 clr_falling; + u32 intstat; +}; + +/* The __gpio_to_controller() and __gpio_mask() functions inline to constants + * with constant parameters; or in outlined code they execute at runtime. + * + * You'd access the controller directly when reading or writing more than + * one gpio value at a time, and to support wired logic where the value + * being driven by the cpu need not match the value read back. + * + * These are NOT part of the cross-platform GPIO interface + */ +static inline struct gpio_controller *__iomem +__gpio_to_controller(unsigned gpio) +{ + void *__iomem ptr; + + if (gpio < 32) + ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10); + else if (gpio < 64) + ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38); + else if (gpio < DAVINCI_N_GPIO) + ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60); + else + ptr = NULL; + return ptr; +} + +static inline u32 __gpio_mask(unsigned gpio) +{ + return 1 << (gpio % 32); +} + +/* The get/set/clear functions will inline when called with constant + * parameters, for low-overhead bitbanging. Illegal constant parameters + * cause link-time errors. + * + * Otherwise, calls with variable parameters use outlined functions. + */ +extern int __error_inval_gpio(void); + +extern void __gpio_set(unsigned gpio, int value); +extern int __gpio_get(unsigned gpio); + +static inline void gpio_set_value(unsigned gpio, int value) +{ + if (__builtin_constant_p(value)) { + struct gpio_controller *__iomem g; + u32 mask; + + if (gpio >= DAVINCI_N_GPIO) + __error_inval_gpio(); + + g = __gpio_to_controller(gpio); + mask = __gpio_mask(gpio); + if (value) + __raw_writel(mask, &g->set_data); + else + __raw_writel(mask, &g->clr_data); + return; + } + + __gpio_set(gpio, value); +} + +/* Returns zero or nonzero; works for gpios configured as inputs OR + * as outputs. + * + * NOTE: changes in reported values are synchronized to the GPIO clock. + * This is most easily seen after calling gpio_set_value() and then immediatly + * gpio_get_value(), where the gpio_get_value() would return the old value + * until the GPIO clock ticks and the new value gets latched. + */ + +static inline int gpio_get_value(unsigned gpio) +{ + struct gpio_controller *__iomem g; + + if (!__builtin_constant_p(gpio)) + return __gpio_get(gpio); + + if (gpio >= DAVINCI_N_GPIO) + return __error_inval_gpio(); + + g = __gpio_to_controller(gpio); + return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data)); +} + +/* powerup default direction is IN */ +extern int gpio_direction_input(unsigned gpio); +extern int gpio_direction_output(unsigned gpio, int value); + +#include /* cansleep wrappers */ + +extern int gpio_request(unsigned gpio, const char *tag); +extern void gpio_free(unsigned gpio); + +static inline int gpio_to_irq(unsigned gpio) +{ + return DAVINCI_N_AINTC_IRQ + gpio; +} + +static inline int irq_to_gpio(unsigned irq) +{ + return irq - DAVINCI_N_AINTC_IRQ; +} + +#endif /* __DAVINCI_GPIO_H */ diff --git a/include/asm-arm/arch-davinci/hardware.h b/include/asm-arm/arch-davinci/hardware.h index 60362d80229e..a2e8969afaca 100644 --- a/include/asm-arm/arch-davinci/hardware.h +++ b/include/asm-arm/arch-davinci/hardware.h @@ -11,4 +11,42 @@ #ifndef __ASM_ARCH_HARDWARE_H #define __ASM_ARCH_HARDWARE_H +/* + * Base register addresses + */ +#define DAVINCI_DMA_3PCC_BASE (0x01C00000) +#define DAVINCI_DMA_3PTC0_BASE (0x01C10000) +#define DAVINCI_DMA_3PTC1_BASE (0x01C10400) +#define DAVINCI_I2C_BASE (0x01C21000) +#define DAVINCI_PWM0_BASE (0x01C22000) +#define DAVINCI_PWM1_BASE (0x01C22400) +#define DAVINCI_PWM2_BASE (0x01C22800) +#define DAVINCI_SYSTEM_MODULE_BASE (0x01C40000) +#define DAVINCI_PLL_CNTRL0_BASE (0x01C40800) +#define DAVINCI_PLL_CNTRL1_BASE (0x01C40C00) +#define DAVINCI_PWR_SLEEP_CNTRL_BASE (0x01C41000) +#define DAVINCI_SYSTEM_DFT_BASE (0x01C42000) +#define DAVINCI_IEEE1394_BASE (0x01C60000) +#define DAVINCI_USB_OTG_BASE (0x01C64000) +#define DAVINCI_CFC_ATA_BASE (0x01C66000) +#define DAVINCI_SPI_BASE (0x01C66800) +#define DAVINCI_GPIO_BASE (0x01C67000) +#define DAVINCI_UHPI_BASE (0x01C67800) +#define DAVINCI_VPSS_REGS_BASE (0x01C70000) +#define DAVINCI_EMAC_CNTRL_REGS_BASE (0x01C80000) +#define DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE (0x01C81000) +#define DAVINCI_EMAC_WRAPPER_RAM_BASE (0x01C82000) +#define DAVINCI_MDIO_CNTRL_REGS_BASE (0x01C84000) +#define DAVINCI_IMCOP_BASE (0x01CC0000) +#define DAVINCI_ASYNC_EMIF_CNTRL_BASE (0x01E00000) +#define DAVINCI_VLYNQ_BASE (0x01E01000) +#define DAVINCI_MCBSP_BASE (0x01E02000) +#define DAVINCI_MMC_SD_BASE (0x01E10000) +#define DAVINCI_MS_BASE (0x01E20000) +#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE (0x02000000) +#define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE (0x04000000) +#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE (0x06000000) +#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE (0x08000000) +#define DAVINCI_VLYNQ_REMOTE_BASE (0x0C000000) + #endif /* __ASM_ARCH_HARDWARE_H */ From 83f53220f8313f097cdf181928be13bafbb697ea Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Tue, 10 Jul 2007 13:10:04 +0100 Subject: [PATCH 03/45] [ARM] 4432/5: davinci: pin mux support Support pin multiplexing configurations driver for TI DaVinci SoC Signed-off-by: Vladimir Barinov Acked-by: Kevin Hilman Signed-off-by: Russell King --- arch/arm/mach-davinci/Makefile | 2 +- arch/arm/mach-davinci/mux.c | 41 ++++++++++++++ arch/arm/mach-davinci/psc.c | 87 +++++++++++++++++++----------- include/asm-arm/arch-davinci/mux.h | 55 +++++++++++++++++++ 4 files changed, 154 insertions(+), 31 deletions(-) create mode 100644 arch/arm/mach-davinci/mux.c create mode 100644 include/asm-arm/arch-davinci/mux.h diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile index 731c0a6d5176..99ac2e55774d 100644 --- a/arch/arm/mach-davinci/Makefile +++ b/arch/arm/mach-davinci/Makefile @@ -5,7 +5,7 @@ # Common objects obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o \ - gpio.o + gpio.o mux.o # Board specific obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o diff --git a/arch/arm/mach-davinci/mux.c b/arch/arm/mach-davinci/mux.c new file mode 100644 index 000000000000..92d26bd305b7 --- /dev/null +++ b/arch/arm/mach-davinci/mux.c @@ -0,0 +1,41 @@ +/* + * DaVinci pin multiplexing configurations + * + * Author: Vladimir Barinov, MontaVista Software, Inc. + * + * 2007 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#include +#include + +#include + +#include + +/* System control register offsets */ +#define PINMUX0 0x00 +#define PINMUX1 0x04 + +static DEFINE_SPINLOCK(mux_lock); + +void davinci_mux_peripheral(unsigned int mux, unsigned int enable) +{ + u32 pinmux, muxreg = PINMUX0; + + if (mux >= DAVINCI_MUX_LEVEL2) { + muxreg = PINMUX1; + mux -= DAVINCI_MUX_LEVEL2; + } + + spin_lock(&mux_lock); + pinmux = davinci_readl(DAVINCI_SYSTEM_MODULE_BASE + muxreg); + if (enable) + pinmux |= (1 << mux); + else + pinmux &= ~(1 << mux); + davinci_writel(pinmux, DAVINCI_SYSTEM_MODULE_BASE + muxreg); + spin_unlock(&mux_lock); +} diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c index e1b0050283a6..1334416559ad 100644 --- a/arch/arm/mach-davinci/psc.c +++ b/arch/arm/mach-davinci/psc.c @@ -25,39 +25,40 @@ #include #include #include +#include -#define PTCMD __REG(0x01C41120) -#define PDSTAT __REG(0x01C41200) -#define PDCTL1 __REG(0x01C41304) -#define EPCPR __REG(0x01C41070) -#define PTSTAT __REG(0x01C41128) +/* PSC register offsets */ +#define EPCPR 0x070 +#define PTCMD 0x120 +#define PTSTAT 0x128 +#define PDSTAT 0x200 +#define PDCTL1 0x304 +#define MDSTAT 0x800 +#define MDCTL 0xA00 -#define MDSTAT IO_ADDRESS(0x01C41800) -#define MDCTL IO_ADDRESS(0x01C41A00) - -#define PINMUX0 __REG(0x01c40000) -#define PINMUX1 __REG(0x01c40004) -#define VDD3P3V_PWDN __REG(0x01C40048) +/* System control register offsets */ +#define VDD3P3V_PWDN 0x48 static void davinci_psc_mux(unsigned int id) { switch (id) { case DAVINCI_LPSC_ATA: - PINMUX0 |= (1 << 17) | (1 << 16); + davinci_mux_peripheral(DAVINCI_MUX_HDIREN, 1); + davinci_mux_peripheral(DAVINCI_MUX_ATAEN, 1); break; case DAVINCI_LPSC_MMC_SD: /* VDD power manupulations are done in U-Boot for CPMAC * so applies to MMC as well */ /*Set up the pull regiter for MMC */ - VDD3P3V_PWDN = 0x0; - PINMUX1 &= (~(1 << 9)); + davinci_writel(0, DAVINCI_SYSTEM_MODULE_BASE + VDD3P3V_PWDN); + davinci_mux_peripheral(DAVINCI_MUX_MSTK, 0); break; case DAVINCI_LPSC_I2C: - PINMUX1 |= (1 << 7); + davinci_mux_peripheral(DAVINCI_MUX_I2C, 1); break; case DAVINCI_LPSC_McBSP: - PINMUX1 |= (1 << 10); + davinci_mux_peripheral(DAVINCI_MUX_ASP, 1); break; default: break; @@ -67,33 +68,59 @@ static void davinci_psc_mux(unsigned int id) /* Enable or disable a PSC domain */ void davinci_psc_config(unsigned int domain, unsigned int id, char enable) { - volatile unsigned int *mdstat = (unsigned int *)((int)MDSTAT + 4 * id); - volatile unsigned int *mdctl = (unsigned int *)((int)MDCTL + 4 * id); + u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask; if (id < 0) return; + mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id); if (enable) - *mdctl |= 0x00000003; /* Enable Module */ + mdctl |= 0x00000003; /* Enable Module */ else - *mdctl &= 0xFFFFFFF2; /* Disable Module */ + mdctl &= 0xFFFFFFF2; /* Disable Module */ + davinci_writel(mdctl, DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id); - if ((PDSTAT & 0x00000001) == 0) { - PDCTL1 |= 0x1; - PTCMD = (1 << domain); - while ((((EPCPR >> domain) & 1) == 0)); + pdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDSTAT); + if ((pdstat & 0x00000001) == 0) { + pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); + pdctl1 |= 0x1; + davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); - PDCTL1 |= 0x100; - while (!(((PTSTAT >> domain) & 1) == 0)); + ptcmd = 1 << domain; + davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD); + + do { + epcpr = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + + EPCPR); + } while ((((epcpr >> domain) & 1) == 0)); + + pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); + pdctl1 |= 0x100; + davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1); + + do { + ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + + PTSTAT); + } while (!(((ptstat >> domain) & 1) == 0)); } else { - PTCMD = (1 << domain); - while (!(((PTSTAT >> domain) & 1) == 0)); + ptcmd = 1 << domain; + davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD); + + do { + ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + + PTSTAT); + } while (!(((ptstat >> domain) & 1) == 0)); } if (enable) - while (!((*mdstat & 0x0000001F) == 0x3)); + mdstat_mask = 0x3; else - while (!((*mdstat & 0x0000001F) == 0x2)); + mdstat_mask = 0x2; + + do { + mdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + + MDSTAT + 4 * id); + } while (!((mdstat & 0x0000001F) == mdstat_mask)); if (enable) davinci_psc_mux(id); diff --git a/include/asm-arm/arch-davinci/mux.h b/include/asm-arm/arch-davinci/mux.h new file mode 100644 index 000000000000..c24b6782804d --- /dev/null +++ b/include/asm-arm/arch-davinci/mux.h @@ -0,0 +1,55 @@ +/* + * DaVinci pin multiplexing defines + * + * Author: Vladimir Barinov, MontaVista Software, Inc. + * + * 2007 (c) MontaVista Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ +#ifndef __ASM_ARCH_MUX_H +#define __ASM_ARCH_MUX_H + +#define DAVINCI_MUX_AEAW0 0 +#define DAVINCI_MUX_AEAW1 1 +#define DAVINCI_MUX_AEAW2 2 +#define DAVINCI_MUX_AEAW3 3 +#define DAVINCI_MUX_AEAW4 4 +#define DAVINCI_MUX_AECS4 10 +#define DAVINCI_MUX_AECS5 11 +#define DAVINCI_MUX_VLYNQWD0 12 +#define DAVINCI_MUX_VLYNQWD1 13 +#define DAVINCI_MUX_VLSCREN 14 +#define DAVINCI_MUX_VLYNQEN 15 +#define DAVINCI_MUX_HDIREN 16 +#define DAVINCI_MUX_ATAEN 17 +#define DAVINCI_MUX_RGB666 22 +#define DAVINCI_MUX_RGB888 23 +#define DAVINCI_MUX_LOEEN 24 +#define DAVINCI_MUX_LFLDEN 25 +#define DAVINCI_MUX_CWEN 26 +#define DAVINCI_MUX_CFLDEN 27 +#define DAVINCI_MUX_HPIEN 29 +#define DAVINCI_MUX_1394EN 30 +#define DAVINCI_MUX_EMACEN 31 + +#define DAVINCI_MUX_LEVEL2 32 +#define DAVINCI_MUX_UART0 (DAVINCI_MUX_LEVEL2 + 0) +#define DAVINCI_MUX_UART1 (DAVINCI_MUX_LEVEL2 + 1) +#define DAVINCI_MUX_UART2 (DAVINCI_MUX_LEVEL2 + 2) +#define DAVINCI_MUX_U2FLO (DAVINCI_MUX_LEVEL2 + 3) +#define DAVINCI_MUX_PWM0 (DAVINCI_MUX_LEVEL2 + 4) +#define DAVINCI_MUX_PWM1 (DAVINCI_MUX_LEVEL2 + 5) +#define DAVINCI_MUX_PWM2 (DAVINCI_MUX_LEVEL2 + 6) +#define DAVINCI_MUX_I2C (DAVINCI_MUX_LEVEL2 + 7) +#define DAVINCI_MUX_SPI (DAVINCI_MUX_LEVEL2 + 8) +#define DAVINCI_MUX_MSTK (DAVINCI_MUX_LEVEL2 + 9) +#define DAVINCI_MUX_ASP (DAVINCI_MUX_LEVEL2 + 10) +#define DAVINCI_MUX_CLK0 (DAVINCI_MUX_LEVEL2 + 16) +#define DAVINCI_MUX_CLK1 (DAVINCI_MUX_LEVEL2 + 17) +#define DAVINCI_MUX_TIMIN (DAVINCI_MUX_LEVEL2 + 18) + +extern void davinci_mux_peripheral(unsigned int mux, unsigned int enable); + +#endif /* __ASM_ARCH_MUX_H */ From eac1d8dab03bde6d20679c961a6409c1b786c201 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 11 Jul 2007 10:14:53 +0100 Subject: [PATCH 04/45] [ARM] 4466/1: ANUBIS: Anubis AX88796 support This patch adds the resources necessary for the AX88796 driver to attach to the AX88796 network controller fitted on the Simtec Anubis board. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2440/mach-anubis.c | 35 +++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c index bff7ddd06a52..64456f9a0f6d 100644 --- a/arch/arm/mach-s3c2440/mach-anubis.c +++ b/arch/arm/mach-s3c2440/mach-anubis.c @@ -42,6 +42,8 @@ #include #include +#include + #include #include #include @@ -260,6 +262,38 @@ static struct platform_device anubis_device_ide1 = { .resource = anubis_ide1_resource, }; +/* Asix AX88796 10/100 ethernet controller */ + +static struct ax_plat_data anubis_asix_platdata = { + .flags = AXFLG_MAC_FROMDEV, + .wordlength = 2, + .dcr_val = 0x48, + .rcr_val = 0x40, +}; + +static struct resource anubis_asix_resource[] = { + [0] = { + .start = S3C2410_CS5, + .end = S3C2410_CS5 + (0x20 * 0x20) -1, + .flags = IORESOURCE_MEM + }, + [1] = { + .start = IRQ_ASIX, + .end = IRQ_ASIX, + .flags = IORESOURCE_IRQ + } +}; + +static struct platform_device anubis_device_asix = { + .name = "ax88796", + .id = 0, + .num_resources = ARRAY_SIZE(anubis_asix_resource), + .resource = anubis_asix_resource, + .dev = { + .platform_data = &anubis_asix_platdata, + } +}; + /* Standard Anubis devices */ static struct platform_device *anubis_devices[] __initdata = { @@ -271,6 +305,7 @@ static struct platform_device *anubis_devices[] __initdata = { &s3c_device_nand, &anubis_device_ide0, &anubis_device_ide1, + &anubis_device_asix, }; static struct clk *anubis_clocks[] = { From 8a9ccb7f182d15d6d6d0debb819790f25c87a30b Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 12 Jul 2007 10:47:35 +0100 Subject: [PATCH 05/45] [ARM] 4468/2: ANUBIS: Add SM501 device resources Add resources for the SM501 present on the Simtec Anubis board, including the framebuffer and the I2C for DDC. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2440/mach-anubis.c | 70 +++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c index 64456f9a0f6d..53675aa516f3 100644 --- a/arch/arm/mach-s3c2440/mach-anubis.c +++ b/arch/arm/mach-s3c2440/mach-anubis.c @@ -18,6 +18,9 @@ #include #include +#include +#include + #include #include #include @@ -294,6 +297,72 @@ static struct platform_device anubis_device_asix = { } }; +/* SM501 */ + +static struct resource anubis_sm501_resource[] = { + [0] = { + .start = S3C2410_CS2, + .end = S3C2410_CS2 + SZ_8M, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = S3C2410_CS2 + SZ_64M - SZ_2M, + .end = S3C2410_CS2 + SZ_64M - 1, + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = IRQ_EINT0, + .end = IRQ_EINT0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct sm501_initdata anubis_sm501_initdata = { + .gpio_high = { + .set = 0x3F000000, /* 24bit panel */ + .mask = 0x0, + }, + .misc_timing = { + .set = 0x010100, /* SDRAM timing */ + .mask = 0x1F1F00, + }, + .misc_control = { + .set = SM501_MISC_PNL_24BIT, + .mask = 0, + }, + + /* set the SDRAM and bus clocks */ + .mclk = 72 * MHZ, + .m1xclk = 144 * MHZ, +}; + +static struct sm501_platdata_gpio_i2c anubis_sm501_gpio_i2c[] = { + [0] = { + .pin_scl = 44, + .pin_sda = 45, + }, + [1] = { + .pin_scl = 40, + .pin_sda = 41, + }, +}; + +static struct sm501_platdata anubis_sm501_platdata = { + .init = &anubis_sm501_initdata, + .gpio_i2c = anubis_sm501_gpio_i2c, + .gpio_i2c_nr = ARRAY_SIZE(anubis_sm501_gpio_i2c), +}; + +static struct platform_device anubis_device_sm501 = { + .name = "sm501", + .id = 0, + .num_resources = ARRAY_SIZE(anubis_sm501_resource), + .resource = anubis_sm501_resource, + .dev = { + .platform_data = &anubis_sm501_platdata, + }, +}; + /* Standard Anubis devices */ static struct platform_device *anubis_devices[] __initdata = { @@ -306,6 +375,7 @@ static struct platform_device *anubis_devices[] __initdata = { &anubis_device_ide0, &anubis_device_ide1, &anubis_device_asix, + &anubis_device_sm501, }; static struct clk *anubis_clocks[] = { From ad3613f4798e229c8885b924c88e17ab85fef96a Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Wed, 11 Jul 2007 11:10:42 +0100 Subject: [PATCH 06/45] [ARM] 4469/1: ANUBIS: large page NAND support Add support for the partition layour used on the revision B modules which ship with large page NAND flash as default. The differnce between the old and new layouts is that the large page devices use 128KiB blocks, so the initial loader partition now ends at 128KiB boundary pushing the begining of partition 1 up. The rest of the partitions are in the same place as the small page NAND devices. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2440/mach-anubis.c | 36 +++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-s3c2440/mach-anubis.c b/arch/arm/mach-s3c2440/mach-anubis.c index 53675aa516f3..29c163d300d4 100644 --- a/arch/arm/mach-s3c2440/mach-anubis.c +++ b/arch/arm/mach-s3c2440/mach-anubis.c @@ -158,6 +158,29 @@ static struct mtd_partition anubis_default_nand_part[] = { } }; +static struct mtd_partition anubis_default_nand_part_large[] = { + [0] = { + .name = "Boot Agent", + .size = SZ_128K, + .offset = 0, + }, + [1] = { + .name = "/boot", + .size = SZ_4M - SZ_128K, + .offset = SZ_128K, + }, + [2] = { + .name = "user1", + .offset = SZ_4M, + .size = SZ_32M - SZ_4M, + }, + [3] = { + .name = "user2", + .offset = SZ_32M, + .size = MTDPART_SIZ_FULL, + } +}; + /* the Anubis has 3 selectable slots for nand-flash, the two * on-board chip areas, as well as the external slot. * @@ -409,8 +432,17 @@ static void __init anubis_map_io(void) s3c24xx_init_clocks(0); s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs)); - /* ensure that the GPIO is setup */ - s3c2410_gpio_setpin(S3C2410_GPA0, 1); + /* check for the newer revision boards with large page nand */ + + if ((__raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK) >= 4) { + printk(KERN_INFO "ANUBIS-B detected (revision %d)\n", + __raw_readb(ANUBIS_VA_IDREG) & ANUBIS_IDREG_REVMASK); + anubis_nand_sets[0].partitions = anubis_default_nand_part_large; + anubis_nand_sets[0].nr_partitions = ARRAY_SIZE(anubis_default_nand_part_large); + } else { + /* ensure that the GPIO is setup */ + s3c2410_gpio_setpin(S3C2410_GPA0, 1); + } } static void __init anubis_init(void) From 5ce4b1fe6c6a126f9274f19d8b2d2c8d29cd49b6 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 12 Jul 2007 10:44:53 +0100 Subject: [PATCH 07/45] [ARM] 4467/3: BAST: AX88796 device resources Add resources for the AX88796 on the Simtec BAST. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2410/mach-bast.c | 59 +++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index f01de807b72f..8b52ea95d4f6 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c @@ -20,6 +20,8 @@ #include #include +#include + #include #include #include @@ -409,6 +411,61 @@ static struct s3c2410_platform_i2c bast_i2c_info = { .max_freq = 130*1000, }; +/* Asix AX88796 10/100 ethernet controller */ + +static struct ax_plat_data bast_asix_platdata = { + .flags = AXFLG_MAC_FROMDEV, + .wordlength = 2, + .dcr_val = 0x48, + .rcr_val = 0x40, +}; + +static struct resource bast_asix_resource[] = { + [0] = { + .start = S3C2410_CS5 + BAST_PA_ASIXNET, + .end = S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20) - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20), + .end = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1f * 0x20), + .flags = IORESOURCE_MEM, + }, + [2] = { + .start = IRQ_ASIX, + .end = IRQ_ASIX, + .flags = IORESOURCE_IRQ + } +}; + +static struct platform_device bast_device_asix = { + .name = "ax88796", + .id = 0, + .num_resources = ARRAY_SIZE(bast_asix_resource), + .resource = bast_asix_resource, + .dev = { + .platform_data = &bast_asix_platdata + } +}; + +/* Asix AX88796 10/100 ethernet controller parallel port */ + +static struct resource bast_asixpp_resource[] = { + [0] = { + .start = S3C2410_CS5 + BAST_PA_ASIXNET + (0x18 * 0x20), + .end = S3C2410_CS5 + BAST_PA_ASIXNET + (0x1b * 0x20) - 1, + .flags = IORESOURCE_MEM, + } +}; + +static struct platform_device bast_device_axpp = { + .name = "ax88796-pp", + .id = 0, + .num_resources = ARRAY_SIZE(bast_asixpp_resource), + .resource = bast_asixpp_resource, +}; + +/* LCD/VGA controller */ static struct s3c2410fb_mach_info __initdata bast_lcd_info = { .width = 640, @@ -453,6 +510,8 @@ static struct platform_device *bast_devices[] __initdata = { &s3c_device_nand, &bast_device_nor, &bast_device_dm9k, + &bast_device_asix, + &bast_device_axpp, &bast_sio, }; From 3c3e69cd4c667e6ce7939d83b274d48c57779479 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 12 Jul 2007 10:57:37 +0100 Subject: [PATCH 08/45] [ARM] 4470/2: OSIRIS: large page NAND support Add support for the partition layout on the revision B modules which have large page NAND fitted. The new partition table accounts for the use of the 128KiB block parts, which means the second partition on the device is moved to the new boundary. Signed-off-by: Ben Dooks Signed-off-by: Russell King --- arch/arm/mach-s3c2440/mach-osiris.c | 38 ++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-s3c2440/mach-osiris.c b/arch/arm/mach-s3c2440/mach-osiris.c index 15811601f03d..89f4c9c5777b 100644 --- a/arch/arm/mach-s3c2440/mach-osiris.c +++ b/arch/arm/mach-s3c2440/mach-osiris.c @@ -166,6 +166,29 @@ static struct mtd_partition osiris_default_nand_part[] = { } }; +static struct mtd_partition osiris_default_nand_part_large[] = { + [0] = { + .name = "Boot Agent", + .size = SZ_128K, + .offset = 0, + }, + [1] = { + .name = "/boot", + .size = SZ_4M - SZ_128K, + .offset = SZ_128K, + }, + [2] = { + .name = "user1", + .offset = SZ_4M, + .size = SZ_32M - SZ_4M, + }, + [3] = { + .name = "user2", + .offset = SZ_32M, + .size = MTDPART_SIZ_FULL, + } +}; + /* the Osiris has 3 selectable slots for nand-flash, the two * on-board chip areas, as well as the external slot. * @@ -322,14 +345,23 @@ static void __init osiris_map_io(void) s3c24xx_init_clocks(0); s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs)); + /* check for the newer revision boards with large page nand */ + + if ((__raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK) >= 4) { + printk(KERN_INFO "OSIRIS-B detected (revision %d)\n", + __raw_readb(OSIRIS_VA_IDREG) & OSIRIS_ID_REVMASK); + osiris_nand_sets[0].partitions = osiris_default_nand_part_large; + osiris_nand_sets[0].nr_partitions = ARRAY_SIZE(osiris_default_nand_part_large); + } else { + /* write-protect line to the NAND */ + s3c2410_gpio_setpin(S3C2410_GPA0, 1); + } + /* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */ local_irq_save(flags); __raw_writel(__raw_readl(S3C2410_BWSCON) | S3C2410_BWSCON_ST1 | S3C2410_BWSCON_ST2 | S3C2410_BWSCON_ST3 | S3C2410_BWSCON_ST4 | S3C2410_BWSCON_ST5, S3C2410_BWSCON); local_irq_restore(flags); - - /* write-protect line to the NAND */ - s3c2410_gpio_setpin(S3C2410_GPA0, 1); } static void __init osiris_init(void) From b3e6a508ed920698d367e5993ed056d70364d91f Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Sat, 12 May 2007 14:31:17 +0100 Subject: [PATCH 09/45] [ARM] 4373/1: i.MX/MX1 GPIO support implementation Support for generic input output for MX1 family. The implementation prevents allocation of one pin by two users, but does not store pointer to the user description permanently, because this solution would have bigger memory overhead. The simple way to integrate code with per BSP pins setup and allocation is required else all GPIO registration checking is useless. The function imx_gpio_setup_multiple_pins() can be used for this purpose in future. Signed-off-by: Pavel Pisa Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/mach-imx/generic.c | 118 ++++++++++++++++++++++++++++ include/asm-arm/arch-imx/gpio.h | 102 ++++++++++++++++++++++++ include/asm-arm/arch-imx/imx-regs.h | 2 + 4 files changed, 223 insertions(+) create mode 100644 include/asm-arm/arch-imx/gpio.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 50d9f3e4e0f1..8b553954365f 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -241,6 +241,7 @@ config ARCH_H720X config ARCH_IMX bool "IMX" + select GENERIC_GPIO help Support for Motorola's i.MX family of processors (MX1, MXL). diff --git a/arch/arm/mach-imx/generic.c b/arch/arm/mach-imx/generic.c index 1c474cf709ca..a58b678006df 100644 --- a/arch/arm/mach-imx/generic.c +++ b/arch/arm/mach-imx/generic.c @@ -28,12 +28,16 @@ #include #include +#include #include #include #include #include #include +#include + +unsigned long imx_gpio_alloc_map[(GPIO_PORT_MAX + 1) * 32 / BITS_PER_LONG]; void imx_gpio_mode(int gpio_mode) { @@ -95,6 +99,120 @@ void imx_gpio_mode(int gpio_mode) EXPORT_SYMBOL(imx_gpio_mode); +int imx_gpio_request(unsigned gpio, const char *label) +{ + if(gpio >= (GPIO_PORT_MAX + 1) * 32) + printk(KERN_ERR "imx_gpio: Attempt to request nonexistent GPIO %d for \"%s\"\n", + gpio, label ? label : "?"); + return -EINVAL; + + if(test_and_set_bit(gpio, imx_gpio_alloc_map)) { + printk(KERN_ERR "imx_gpio: GPIO %d already used. Allocation for \"%s\" failed\n", + gpio, label ? label : "?"); + return -EBUSY; + } + + return 0; +} + +EXPORT_SYMBOL(imx_gpio_request); + +void imx_gpio_free(unsigned gpio) +{ + if(gpio >= (GPIO_PORT_MAX + 1) * 32) + return; + + clear_bit(gpio, imx_gpio_alloc_map); +} + +EXPORT_SYMBOL(imx_gpio_free); + +int imx_gpio_direction_input(unsigned gpio) +{ + imx_gpio_mode(gpio| GPIO_IN); + return 0; +} + +EXPORT_SYMBOL(imx_gpio_direction_input); + +int imx_gpio_direction_output(unsigned gpio, int value) +{ + imx_gpio_set_value(gpio, value); + imx_gpio_mode(gpio| GPIO_OUT); + return 0; +} + +EXPORT_SYMBOL(imx_gpio_direction_output); + +int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count, + int alloc_mode, const char *label) +{ + const int *p = pin_list; + int i; + unsigned gpio; + unsigned mode; + + for (i = 0; i < count; i++) { + gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK); + mode = *p & ~(GPIO_PIN_MASK | GPIO_PORT_MASK); + + if (gpio >= (GPIO_PORT_MAX + 1) * 32) + goto setup_error; + + if (alloc_mode & IMX_GPIO_ALLOC_MODE_RELEASE) + imx_gpio_free(gpio); + else if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_NO_ALLOC)) + if (imx_gpio_request(gpio, label)) + if (!(alloc_mode & IMX_GPIO_ALLOC_MODE_TRY_ALLOC)) + goto setup_error; + + if (!(alloc_mode & (IMX_GPIO_ALLOC_MODE_ALLOC_ONLY | + IMX_GPIO_ALLOC_MODE_RELEASE))) + imx_gpio_mode(gpio | mode); + + p++; + } + return 0; + +setup_error: + if(alloc_mode & (IMX_GPIO_ALLOC_MODE_NO_ALLOC | + IMX_GPIO_ALLOC_MODE_TRY_ALLOC)) + return -EINVAL; + + while (p != pin_list) { + p--; + gpio = *p & (GPIO_PIN_MASK | GPIO_PORT_MASK); + imx_gpio_free(gpio); + } + + return -EINVAL; +} + +EXPORT_SYMBOL(imx_gpio_setup_multiple_pins); + +void __imx_gpio_set_value(unsigned gpio, int value) +{ + imx_gpio_set_value_inline(gpio, value); +} + +EXPORT_SYMBOL(__imx_gpio_set_value); + +int imx_gpio_to_irq(unsigned gpio) +{ + return IRQ_GPIOA(0) + gpio; +} + +EXPORT_SYMBOL(imx_gpio_to_irq); + +int imx_irq_to_gpio(unsigned irq) +{ + if (irq < IRQ_GPIOA(0)) + return -EINVAL; + return irq - IRQ_GPIOA(0); +} + +EXPORT_SYMBOL(imx_irq_to_gpio); + /* * get the system pll clock in Hz * diff --git a/include/asm-arm/arch-imx/gpio.h b/include/asm-arm/arch-imx/gpio.h new file mode 100644 index 000000000000..486023263f32 --- /dev/null +++ b/include/asm-arm/arch-imx/gpio.h @@ -0,0 +1,102 @@ +#ifndef _IMX_GPIO_H + +#include + +#define IMX_GPIO_ALLOC_MODE_NORMAL 0 +#define IMX_GPIO_ALLOC_MODE_NO_ALLOC 1 +#define IMX_GPIO_ALLOC_MODE_TRY_ALLOC 2 +#define IMX_GPIO_ALLOC_MODE_ALLOC_ONLY 4 +#define IMX_GPIO_ALLOC_MODE_RELEASE 8 + +extern int imx_gpio_request(unsigned gpio, const char *label); + +extern void imx_gpio_free(unsigned gpio); + +extern int imx_gpio_setup_multiple_pins(const int *pin_list, unsigned count, + int alloc_mode, const char *label); + +extern int imx_gpio_direction_input(unsigned gpio); + +extern int imx_gpio_direction_output(unsigned gpio, int value); + +extern void __imx_gpio_set_value(unsigned gpio, int value); + +static inline int imx_gpio_get_value(unsigned gpio) +{ + return SSR(gpio >> GPIO_PORT_SHIFT) & (1 << (gpio & GPIO_PIN_MASK)); +} + +static inline void imx_gpio_set_value_inline(unsigned gpio, int value) +{ + unsigned long flags; + + raw_local_irq_save(flags); + if(value) + DR(gpio >> GPIO_PORT_SHIFT) |= (1 << (gpio & GPIO_PIN_MASK)); + else + DR(gpio >> GPIO_PORT_SHIFT) &= ~(1 << (gpio & GPIO_PIN_MASK)); + raw_local_irq_restore(flags); +} + +static inline void imx_gpio_set_value(unsigned gpio, int value) +{ + if(__builtin_constant_p(gpio)) + imx_gpio_set_value_inline(gpio, value); + else + __imx_gpio_set_value(gpio, value); +} + +extern int imx_gpio_to_irq(unsigned gpio); + +extern int imx_irq_to_gpio(unsigned irq); + +/*-------------------------------------------------------------------------*/ + +/* Wrappers for "new style" GPIO calls. These calls i.MX specific versions + * to allow future extension of GPIO logic. + */ + +static inline int gpio_request(unsigned gpio, const char *label) +{ + return imx_gpio_request(gpio, label); +} + +static inline void gpio_free(unsigned gpio) +{ + imx_gpio_free(gpio); +} + +static inline int gpio_direction_input(unsigned gpio) +{ + return imx_gpio_direction_input(gpio); +} + +static inline int gpio_direction_output(unsigned gpio, int value) +{ + return imx_gpio_direction_output(gpio, value); +} + +static inline int gpio_get_value(unsigned gpio) +{ + return imx_gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + imx_gpio_set_value(gpio, value); +} + +#include /* cansleep wrappers */ + +static inline int gpio_to_irq(unsigned gpio) +{ + return imx_gpio_to_irq(gpio); +} + +static inline int irq_to_gpio(unsigned irq) +{ + return imx_irq_to_gpio(irq); +} + + +#endif diff --git a/include/asm-arm/arch-imx/imx-regs.h b/include/asm-arm/arch-imx/imx-regs.h index 30de404c61f5..fb9de2733879 100644 --- a/include/asm-arm/arch-imx/imx-regs.h +++ b/include/asm-arm/arch-imx/imx-regs.h @@ -77,6 +77,8 @@ #define SWR(x) __REG2(IMX_GPIO_BASE + 0x3c, ((x) & 3) << 8) #define PUEN(x) __REG2(IMX_GPIO_BASE + 0x40, ((x) & 3) << 8) +#define GPIO_PORT_MAX 3 + #define GPIO_PIN_MASK 0x1f #define GPIO_PORT_MASK (0x3 << 5) From 89bba43514d06478eb27e3fa9099a8ae7dee5589 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Sun, 13 May 2007 17:37:33 +0100 Subject: [PATCH 10/45] [ARM] 4374/3: i.MX/MX1 clock event source Support clock event source based on i.MX general purpose timer in free running timer mode. Signed-off-by: Pavel Pisa Acked-by: Thomas Gleixner Acked-by: Sascha Hauer Signed-off-by: Russell King --- arch/arm/Kconfig | 2 + arch/arm/mach-imx/time.c | 121 ++++++++++++++++++++++++++++++++++----- 2 files changed, 109 insertions(+), 14 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 8b553954365f..9dc455ef9eb5 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -242,6 +242,8 @@ config ARCH_H720X config ARCH_IMX bool "IMX" select GENERIC_GPIO + select GENERIC_TIME + select GENERIC_CLOCKEVENTS help Support for Motorola's i.MX family of processors (MX1, MXL). diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c index 6960a9d04217..010f6fa984a6 100644 --- a/arch/arm/mach-imx/time.c +++ b/arch/arm/mach-imx/time.c @@ -3,6 +3,7 @@ * * Copyright (C) 2000-2001 Deep Blue Solutions * Copyright (C) 2002 Shane Nay (shane@minirl.com) + * Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com) * * 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 @@ -15,6 +16,7 @@ #include #include #include +#include #include #include @@ -25,7 +27,8 @@ /* Use timer 1 as system timer */ #define TIMER_BASE IMX_TIM1_BASE -static unsigned long evt_diff; +static struct clock_event_device clockevent_imx; +static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED; /* * IRQ handler for the timer @@ -33,25 +36,20 @@ static unsigned long evt_diff; static irqreturn_t imx_timer_interrupt(int irq, void *dev_id) { + struct clock_event_device *evt = &clockevent_imx; uint32_t tstat; + irqreturn_t ret = IRQ_NONE; /* clear the interrupt */ tstat = IMX_TSTAT(TIMER_BASE); IMX_TSTAT(TIMER_BASE) = 0; if (tstat & TSTAT_COMP) { - do { - - write_seqlock(&xtime_lock); - timer_tick(); - write_sequnlock(&xtime_lock); - IMX_TCMP(TIMER_BASE) += evt_diff; - - } while (unlikely((int32_t)(IMX_TCMP(TIMER_BASE) - - IMX_TCN(TIMER_BASE)) < 0)); + evt->event_handler(evt); + ret = IRQ_HANDLED; } - return IRQ_HANDLED; + return ret; } static struct irqaction imx_timer_irq = { @@ -70,10 +68,8 @@ static void __init imx_timer_hardware_init(void) */ IMX_TCTL(TIMER_BASE) = 0; IMX_TPRER(TIMER_BASE) = 0; - IMX_TCMP(TIMER_BASE) = LATCH - 1; - IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_IRQEN | TCTL_TEN; - evt_diff = LATCH; + IMX_TCTL(TIMER_BASE) = TCTL_FRR | TCTL_CLK_PCLK1 | TCTL_TEN; } cycle_t imx_get_cycles(void) @@ -99,11 +95,108 @@ static int __init imx_clocksource_init(void) return 0; } +static int imx_set_next_event(unsigned long evt, + struct clock_event_device *unused) +{ + unsigned long tcmp; + + tcmp = IMX_TCN(TIMER_BASE) + evt; + IMX_TCMP(TIMER_BASE) = tcmp; + + return (int32_t)(tcmp - IMX_TCN(TIMER_BASE)) < 0 ? -ETIME : 0; +} + +#ifdef DEBUG +static const char *clock_event_mode_label[]={ + [CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC", + [CLOCK_EVT_MODE_ONESHOT] = "CLOCK_EVT_MODE_ONESHOT", + [CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN", + [CLOCK_EVT_MODE_UNUSED] = "CLOCK_EVT_MODE_UNUSED" +}; +#endif /*DEBUG*/ + +static void imx_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) +{ + unsigned long flags; + + /* + * The timer interrupt generation is disabled at least + * for enough time to call imx_set_next_event() + */ + local_irq_save(flags); + /* Disable interrupt in GPT module */ + IMX_TCTL(TIMER_BASE) &= ~TCTL_IRQEN; + if (mode != clockevent_mode) { + /* Set event time into far-far future */ + IMX_TCMP(TIMER_BASE) = IMX_TCN(TIMER_BASE) - 3; + /* Clear pending interrupt */ + IMX_TSTAT(TIMER_BASE) &= ~TSTAT_COMP; + } + +#ifdef DEBUG + printk(KERN_INFO "imx_set_mode: changing mode from %s to %s\n", + clock_event_mode_label[clockevent_mode], clock_event_mode_label[mode]); +#endif /*DEBUG*/ + + /* Remember timer mode */ + clockevent_mode = mode; + local_irq_restore(flags); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + printk(KERN_ERR "imx_set_mode: Periodic mode is not supported for i.MX\n"); + break; + case CLOCK_EVT_MODE_ONESHOT: + /* + * Do not put overhead of interrupt enable/disable into + * imx_set_next_event(), the core has about 4 minutes + * to call imx_set_next_event() or shutdown clock after + * mode switching + */ + local_irq_save(flags); + IMX_TCTL(TIMER_BASE) |= TCTL_IRQEN; + local_irq_restore(flags); + break; + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + /* Left event sources disabled, no more interrupts appears */ + break; + } +} + +static struct clock_event_device clockevent_imx = { + .name = "imx_timer1", + .features = CLOCK_EVT_FEAT_ONESHOT, + .shift = 32, + .set_mode = imx_set_mode, + .set_next_event = imx_set_next_event, + .rating = 200, +}; + +static int __init imx_clockevent_init(void) +{ + clockevent_imx.mult = div_sc(imx_get_perclk1(), NSEC_PER_SEC, + clockevent_imx.shift); + clockevent_imx.max_delta_ns = + clockevent_delta2ns(0xfffffffe, &clockevent_imx); + clockevent_imx.min_delta_ns = + clockevent_delta2ns(0xf, &clockevent_imx); + + clockevent_imx.cpumask = cpumask_of_cpu(0); + + clockevents_register_device(&clockevent_imx); + + return 0; +} + + static void __init imx_timer_init(void) { imx_timer_hardware_init(); imx_clocksource_init(); + imx_clockevent_init(); + /* * Make irqs happen for the system timer */ From 51198ea9478b6e10759ab07cd0b9917663c8df7a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 6 Jun 2007 17:51:21 +0100 Subject: [PATCH 11/45] [ARM] 4429/2: iop13xx: expose the 'iop' attribute versions of the tpmi control registers The tpmi control registers can be accessed on the internal bus via an address with PCI attributes or IOP attributes (i.e. read-only, read-write... etc). The sas driver needs access to the iop-attribute registers for initialization. Changelog: * use ARRAY_SIZE for num_resources, Russell King Signed-off-by: Dan Williams Signed-off-by: Russell King --- arch/arm/mach-iop13xx/tpmi.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-iop13xx/tpmi.c b/arch/arm/mach-iop13xx/tpmi.c index d3dc278213da..2476347ea62f 100644 --- a/arch/arm/mach-iop13xx/tpmi.c +++ b/arch/arm/mach-iop13xx/tpmi.c @@ -29,13 +29,15 @@ #define IOP13XX_TPMI_MMR(dev) IOP13XX_REG_ADDR32_PHYS(0x48000 + (dev << 12)) #define IOP13XX_TPMI_MEM(dev) IOP13XX_REG_ADDR32_PHYS(0x60000 + (dev << 13)) #define IOP13XX_TPMI_CTRL(dev) IOP13XX_REG_ADDR32_PHYS(0x50000 + (dev << 10)) +#define IOP13XX_TPMI_IOP_CTRL(dev) (IOP13XX_TPMI_CTRL(dev) + 0x2000) #define IOP13XX_TPMI_MMR_SIZE (SZ_4K - 1) #define IOP13XX_TPMI_MEM_SIZE (255) #define IOP13XX_TPMI_MEM_CTRL (SZ_1K - 1) #define IOP13XX_TPMI_RESOURCE_MMR 0 #define IOP13XX_TPMI_RESOURCE_MEM 1 #define IOP13XX_TPMI_RESOURCE_CTRL 2 -#define IOP13XX_TPMI_RESOURCE_IRQ 3 +#define IOP13XX_TPMI_RESOURCE_IOP_CTRL 3 +#define IOP13XX_TPMI_RESOURCE_IRQ 4 static struct resource iop13xx_tpmi_0_resources[] = { [IOP13XX_TPMI_RESOURCE_MMR] = { @@ -53,6 +55,11 @@ static struct resource iop13xx_tpmi_0_resources[] = { .end = IOP13XX_TPMI_CTRL(0) + IOP13XX_TPMI_MEM_CTRL, .flags = IORESOURCE_MEM, }, + [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = { + .start = IOP13XX_TPMI_IOP_CTRL(0), + .end = IOP13XX_TPMI_IOP_CTRL(0) + IOP13XX_TPMI_MEM_CTRL, + .flags = IORESOURCE_MEM, + }, [IOP13XX_TPMI_RESOURCE_IRQ] = { .start = IRQ_IOP13XX_TPMI0_OUT, .end = IRQ_IOP13XX_TPMI0_OUT, @@ -76,6 +83,11 @@ static struct resource iop13xx_tpmi_1_resources[] = { .end = IOP13XX_TPMI_CTRL(1) + IOP13XX_TPMI_MEM_CTRL, .flags = IORESOURCE_MEM, }, + [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = { + .start = IOP13XX_TPMI_IOP_CTRL(1), + .end = IOP13XX_TPMI_IOP_CTRL(1) + IOP13XX_TPMI_MEM_CTRL, + .flags = IORESOURCE_MEM, + }, [IOP13XX_TPMI_RESOURCE_IRQ] = { .start = IRQ_IOP13XX_TPMI1_OUT, .end = IRQ_IOP13XX_TPMI1_OUT, @@ -99,6 +111,11 @@ static struct resource iop13xx_tpmi_2_resources[] = { .end = IOP13XX_TPMI_CTRL(2) + IOP13XX_TPMI_MEM_CTRL, .flags = IORESOURCE_MEM, }, + [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = { + .start = IOP13XX_TPMI_IOP_CTRL(2), + .end = IOP13XX_TPMI_IOP_CTRL(2) + IOP13XX_TPMI_MEM_CTRL, + .flags = IORESOURCE_MEM, + }, [IOP13XX_TPMI_RESOURCE_IRQ] = { .start = IRQ_IOP13XX_TPMI2_OUT, .end = IRQ_IOP13XX_TPMI2_OUT, @@ -122,6 +139,11 @@ static struct resource iop13xx_tpmi_3_resources[] = { .end = IOP13XX_TPMI_CTRL(3) + IOP13XX_TPMI_MEM_CTRL, .flags = IORESOURCE_MEM, }, + [IOP13XX_TPMI_RESOURCE_IOP_CTRL] = { + .start = IOP13XX_TPMI_IOP_CTRL(3), + .end = IOP13XX_TPMI_IOP_CTRL(3) + IOP13XX_TPMI_MEM_CTRL, + .flags = IORESOURCE_MEM, + }, [IOP13XX_TPMI_RESOURCE_IRQ] = { .start = IRQ_IOP13XX_TPMI3_OUT, .end = IRQ_IOP13XX_TPMI3_OUT, @@ -133,7 +155,7 @@ u64 iop13xx_tpmi_mask = DMA_64BIT_MASK; static struct platform_device iop13xx_tpmi_0_device = { .name = "iop-tpmi", .id = 0, - .num_resources = 4, + .num_resources = ARRAY_SIZE(iop13xx_tpmi_0_resources), .resource = iop13xx_tpmi_0_resources, .dev = { .dma_mask = &iop13xx_tpmi_mask, @@ -144,7 +166,7 @@ static struct platform_device iop13xx_tpmi_0_device = { static struct platform_device iop13xx_tpmi_1_device = { .name = "iop-tpmi", .id = 1, - .num_resources = 4, + .num_resources = ARRAY_SIZE(iop13xx_tpmi_1_resources), .resource = iop13xx_tpmi_1_resources, .dev = { .dma_mask = &iop13xx_tpmi_mask, @@ -155,7 +177,7 @@ static struct platform_device iop13xx_tpmi_1_device = { static struct platform_device iop13xx_tpmi_2_device = { .name = "iop-tpmi", .id = 2, - .num_resources = 4, + .num_resources = ARRAY_SIZE(iop13xx_tpmi_2_resources), .resource = iop13xx_tpmi_2_resources, .dev = { .dma_mask = &iop13xx_tpmi_mask, @@ -166,7 +188,7 @@ static struct platform_device iop13xx_tpmi_2_device = { static struct platform_device iop13xx_tpmi_3_device = { .name = "iop-tpmi", .id = 3, - .num_resources = 4, + .num_resources = ARRAY_SIZE(iop13xx_tpmi_3_resources), .resource = iop13xx_tpmi_3_resources, .dev = { .dma_mask = &iop13xx_tpmi_mask, From 4ad48b4bfa121a67ec04162d584afcfa75ed151a Mon Sep 17 00:00:00 2001 From: Vladimir Barinov Date: Wed, 16 May 2007 20:39:02 +0100 Subject: [PATCH 12/45] [ARM] 4385/2: ixdp425: NAND support IXDP425 NAND support (arch specific part). The generic platform driver that is used by ixdp425 platfrom is already in upstream kernel in 2.6.22-rc1. Signed-off-by: Vladimir Barinov Signed-off-by: Ruslan Sushko Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- arch/arm/mach-ixp4xx/ixdp425-setup.c | 96 +++++++++++++++++++++++++++ include/asm-arm/arch-ixp4xx/ixdp425.h | 4 ++ 2 files changed, 100 insertions(+) diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index ec4f07950ec6..d5008d8fc9a5 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -15,6 +15,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -24,6 +28,7 @@ #include #include #include +#include static struct flash_platform_data ixdp425_flash_data = { .map_name = "cfi_probe", @@ -44,6 +49,77 @@ static struct platform_device ixdp425_flash = { .resource = &ixdp425_flash_resource, }; +#if defined(CONFIG_MTD_NAND_PLATFORM) || \ + defined(CONFIG_MTD_NAND_PLATFORM_MODULE) + +#ifdef CONFIG_MTD_PARTITIONS +const char *part_probes[] = { "cmdlinepart", NULL }; + +static struct mtd_partition ixdp425_partitions[] = { + { + .name = "ixp400 NAND FS 0", + .offset = 0, + .size = SZ_8M + }, { + .name = "ixp400 NAND FS 1", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL + }, +}; +#endif + +static void +ixdp425_flash_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) +{ + struct nand_chip *this = mtd->priv; + int offset = (int)this->priv; + + if (ctrl & NAND_CTRL_CHANGE) { + if (ctrl & NAND_NCE) { + gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_LOW); + udelay(5); + } else + gpio_line_set(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_HIGH); + + offset = (ctrl & NAND_CLE) ? IXDP425_NAND_CMD_BYTE : 0; + offset |= (ctrl & NAND_ALE) ? IXDP425_NAND_ADDR_BYTE : 0; + this->priv = (void *)offset; + } + + if (cmd != NAND_CMD_NONE) + writeb(cmd, this->IO_ADDR_W + offset); +} + +static struct platform_nand_data ixdp425_flash_nand_data = { + .chip = { + .chip_delay = 30, + .options = NAND_NO_AUTOINCR, +#ifdef CONFIG_MTD_PARTITIONS + .part_probe_types = part_probes, + .partitions = ixdp425_partitions, + .nr_partitions = ARRAY_SIZE(ixdp425_partitions), +#endif + }, + .ctrl = { + .cmd_ctrl = ixdp425_flash_nand_cmd_ctrl + } +}; + +static struct resource ixdp425_flash_nand_resource = { + .flags = IORESOURCE_MEM, +}; + +static struct platform_device ixdp425_flash_nand = { + .name = "gen_nand", + .id = -1, + .dev = { + .platform_data = &ixdp425_flash_nand_data, + }, + .num_resources = 1, + .resource = &ixdp425_flash_nand_resource, +}; +#endif /* CONFIG_MTD_NAND_PLATFORM */ + static struct ixp4xx_i2c_pins ixdp425_i2c_gpio_pins = { .sda_pin = IXDP425_SDA_PIN, .scl_pin = IXDP425_SCL_PIN, @@ -104,6 +180,10 @@ static struct platform_device ixdp425_uart = { static struct platform_device *ixdp425_devices[] __initdata = { &ixdp425_i2c_controller, &ixdp425_flash, +#if defined(CONFIG_MTD_NAND_PLATFORM) || \ + defined(CONFIG_MTD_NAND_PLATFORM_MODULE) + &ixdp425_flash_nand, +#endif &ixdp425_uart }; @@ -115,6 +195,22 @@ static void __init ixdp425_init(void) ixdp425_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; +#if defined(CONFIG_MTD_NAND_PLATFORM) || \ + defined(CONFIG_MTD_NAND_PLATFORM_MODULE) + ixdp425_flash_nand_resource.start = IXP4XX_EXP_BUS_BASE(3), + ixdp425_flash_nand_resource.end = IXP4XX_EXP_BUS_BASE(3) + 0x10 - 1; + + gpio_line_config(IXDP425_NAND_NCE_PIN, IXP4XX_GPIO_OUT); + + /* Configure expansion bus for NAND Flash */ + *IXP4XX_EXP_CS3 = IXP4XX_EXP_BUS_CS_EN | + IXP4XX_EXP_BUS_STROBE_T(1) | /* extend by 1 clock */ + IXP4XX_EXP_BUS_CYCLES(0) | /* Intel cycles */ + IXP4XX_EXP_BUS_SIZE(0) | /* 512bytes addr space*/ + IXP4XX_EXP_BUS_WR_EN | + IXP4XX_EXP_BUS_BYTE_EN; /* 8 bit data bus */ +#endif + if (cpu_is_ixp43x()) { ixdp425_uart.num_resources = 1; ixdp425_uart_data[1].flags = 0; diff --git a/include/asm-arm/arch-ixp4xx/ixdp425.h b/include/asm-arm/arch-ixp4xx/ixdp425.h index 3d3820d7ba09..e0791af3bfea 100644 --- a/include/asm-arm/arch-ixp4xx/ixdp425.h +++ b/include/asm-arm/arch-ixp4xx/ixdp425.h @@ -32,4 +32,8 @@ #define IXDP425_PCI_INTC_PIN 9 #define IXDP425_PCI_INTD_PIN 8 +/* NAND Flash pins */ +#define IXDP425_NAND_NCE_PIN 12 +#define IXDP425_NAND_CMD_BYTE 0x01 +#define IXDP425_NAND_ADDR_BYTE 0x02 From 46918bd13b887e8f0ae2987e690bc2af9c6c08a4 Mon Sep 17 00:00:00 2001 From: Imre Kaloz Date: Sat, 2 Jun 2007 15:44:08 +0100 Subject: [PATCH 13/45] [ARM] 4425/2: Gateway 7001 series support This patch provides support for the Gateway 7001 AccessPoint series. Updated to stay below the 80 char limit in uncompress.h Signed-off-by: Imre Kaloz Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- arch/arm/mach-ixp4xx/Kconfig | 8 ++ arch/arm/mach-ixp4xx/Makefile | 2 + arch/arm/mach-ixp4xx/gateway7001-pci.c | 64 ++++++++++++++ arch/arm/mach-ixp4xx/gateway7001-setup.c | 108 +++++++++++++++++++++++ include/asm-arm/arch-ixp4xx/uncompress.h | 5 +- 5 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-ixp4xx/gateway7001-pci.c create mode 100644 arch/arm/mach-ixp4xx/gateway7001-setup.c diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig index 060909870b50..daaa190c1253 100644 --- a/arch/arm/mach-ixp4xx/Kconfig +++ b/arch/arm/mach-ixp4xx/Kconfig @@ -41,6 +41,14 @@ config ARCH_ADI_COYOTE Engineering Coyote Gateway Reference Platform. For more information on this platform, see . +config MACH_GATEWAY7001 + bool "Gateway 7001" + select PCI + help + Say 'Y' here if you want your kernel to support Gateway's + 7001 Access Point. For more information on this platform, + see http://openwrt.org + config ARCH_IXDP425 bool "IXDP425" help diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile index 3b87c47e06cf..b79ce249866a 100644 --- a/arch/arm/mach-ixp4xx/Makefile +++ b/arch/arm/mach-ixp4xx/Makefile @@ -13,6 +13,7 @@ obj-pci-$(CONFIG_MACH_GTWX5715) += gtwx5715-pci.o obj-pci-$(CONFIG_MACH_NSLU2) += nslu2-pci.o obj-pci-$(CONFIG_MACH_NAS100D) += nas100d-pci.o obj-pci-$(CONFIG_MACH_DSMG600) += dsmg600-pci.o +obj-pci-$(CONFIG_MACH_GATEWAY7001) += gateway7001-pci.o obj-y += common.o @@ -24,5 +25,6 @@ obj-$(CONFIG_MACH_GTWX5715) += gtwx5715-setup.o obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o nslu2-power.o obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o nas100d-power.o obj-$(CONFIG_MACH_DSMG600) += dsmg600-setup.o dsmg600-power.o +obj-$(CONFIG_MACH_GATEWAY7001) += gateway7001-setup.o obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o diff --git a/arch/arm/mach-ixp4xx/gateway7001-pci.c b/arch/arm/mach-ixp4xx/gateway7001-pci.c new file mode 100644 index 000000000000..4f2eeb050314 --- /dev/null +++ b/arch/arm/mach-ixp4xx/gateway7001-pci.c @@ -0,0 +1,64 @@ +/* + * arch/arch/mach-ixp4xx/gateway7001-pci.c + * + * PCI setup routines for Gateway 7001 + * + * Copyright (C) 2007 Imre Kaloz + * + * based on coyote-pci.c: + * Copyright (C) 2002 Jungo Software Technologies. + * Copyright (C) 2003 MontaVista Softwrae, Inc. + * + * Maintainer: Imre Kaloz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +void __init gateway7001_pci_preinit(void) +{ + set_irq_type(IRQ_IXP4XX_GPIO10, IRQT_LOW); + set_irq_type(IRQ_IXP4XX_GPIO11, IRQT_LOW); + + ixp4xx_pci_preinit(); +} + +static int __init gateway7001_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + if (slot == 1) + return IRQ_IXP4XX_GPIO11; + else if (slot == 2) + return IRQ_IXP4XX_GPIO10; + else return -1; +} + +struct hw_pci gateway7001_pci __initdata = { + .nr_controllers = 1, + .preinit = gateway7001_pci_preinit, + .swizzle = pci_std_swizzle, + .setup = ixp4xx_setup, + .scan = ixp4xx_scan_bus, + .map_irq = gateway7001_map_irq, +}; + +int __init gateway7001_pci_init(void) +{ + if (machine_is_gateway7001()) + pci_common_init(&gateway7001_pci); + return 0; +} + +subsys_initcall(gateway7001_pci_init); diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c new file mode 100644 index 000000000000..37876832e141 --- /dev/null +++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c @@ -0,0 +1,108 @@ +/* + * arch/arm/mach-ixp4xx/gateway7001-setup.c + * + * Board setup for the Gateway 7001 board + * + * Copyright (C) 2007 Imre Kaloz + * + * based on coyote-setup.c: + * Copyright (C) 2003-2005 MontaVista Software, Inc. + * + * Author: Imre Kaloz + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct flash_platform_data gateway7001_flash_data = { + .map_name = "cfi_probe", + .width = 2, +}; + +static struct resource gateway7001_flash_resource = { + .flags = IORESOURCE_MEM, +}; + +static struct platform_device gateway7001_flash = { + .name = "IXP4XX-Flash", + .id = 0, + .dev = { + .platform_data = &gateway7001_flash_data, + }, + .num_resources = 1, + .resource = &gateway7001_flash_resource, +}; + +static struct resource gateway7001_uart_resource = { + .start = IXP4XX_UART2_BASE_PHYS, + .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, + .flags = IORESOURCE_MEM, +}; + +static struct plat_serial8250_port gateway7001_uart_data[] = { + { + .mapbase = IXP4XX_UART2_BASE_PHYS, + .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, + .irq = IRQ_IXP4XX_UART2, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = IXP4XX_UART_XTAL, + }, + { }, +}; + +static struct platform_device gateway7001_uart = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = gateway7001_uart_data, + }, + .num_resources = 1, + .resource = &gateway7001_uart_resource, +}; + +static struct platform_device *gateway7001_devices[] __initdata = { + &gateway7001_flash, + &gateway7001_uart +}; + +static void __init gateway7001_init(void) +{ + ixp4xx_sys_init(); + + gateway7001_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); + gateway7001_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; + + *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; + *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; + + platform_add_devices(gateway7001_devices, ARRAY_SIZE(gateway7001_devices)); +} + +#ifdef CONFIG_MACH_GATEWAY7001 +MACHINE_START(GATEWAY7001, "Gateway 7001 AP") + /* Maintainer: Imre Kaloz */ + .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, + .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, + .map_io = ixp4xx_map_io, + .init_irq = ixp4xx_init_irq, + .timer = &ixp4xx_timer, + .boot_params = 0x0100, + .init_machine = gateway7001_init, +MACHINE_END +#endif diff --git a/include/asm-arm/arch-ixp4xx/uncompress.h b/include/asm-arm/arch-ixp4xx/uncompress.h index 09ae6c91be60..bf7a7882bf7c 100644 --- a/include/asm-arm/arch-ixp4xx/uncompress.h +++ b/include/asm-arm/arch-ixp4xx/uncompress.h @@ -38,9 +38,10 @@ static void flush(void) static __inline__ void __arch_decomp_setup(unsigned long arch_id) { /* - * Coyote and gtwx5715 only have UART2 connected + * Some boards are using UART2 as console */ - if (machine_is_adi_coyote() || machine_is_gtwx5715()) + if (machine_is_adi_coyote() || machine_is_gtwx5715() || + machine_is_gateway7001()) uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS; else uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS; From dcdeeb21c010e9b5cb2e91f865cd5bebb65bc31f Mon Sep 17 00:00:00 2001 From: Imre Kaloz Date: Sat, 2 Jun 2007 15:47:51 +0100 Subject: [PATCH 14/45] [ARM] 4426/2: Netgear WG302 v2 and WAG302 v2 support This patch provides support for the Netgear WG302 v2 and WAG302 v2 AccessPoint series. This patch relies on the patch "Gateway 7001 series support" minimally, as they only have UART2 connected. Updated to stay below the 80 char limit in uncompress.h Signed-off-by: Imre Kaloz Signed-off-by: Deepak Saxena Signed-off-by: Russell King --- arch/arm/mach-ixp4xx/Kconfig | 8 ++ arch/arm/mach-ixp4xx/Makefile | 2 + arch/arm/mach-ixp4xx/wg302v2-pci.c | 64 +++++++++++++ arch/arm/mach-ixp4xx/wg302v2-setup.c | 109 +++++++++++++++++++++++ include/asm-arm/arch-ixp4xx/uncompress.h | 2 +- 5 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-ixp4xx/wg302v2-pci.c create mode 100644 arch/arm/mach-ixp4xx/wg302v2-setup.c diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig index daaa190c1253..61b2dfcb89d6 100644 --- a/arch/arm/mach-ixp4xx/Kconfig +++ b/arch/arm/mach-ixp4xx/Kconfig @@ -49,6 +49,14 @@ config MACH_GATEWAY7001 7001 Access Point. For more information on this platform, see http://openwrt.org +config MACH_WG302V2 + bool "Netgear WG302 v2 / WAG302 v2" + select PCI + help + Say 'Y' here if you want your kernel to support Netgear's + WG302 v2 or WAG302 v2 Access Points. For more information + on this platform, see http://openwrt.org + config ARCH_IXDP425 bool "IXDP425" help diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile index b79ce249866a..77e00ade5585 100644 --- a/arch/arm/mach-ixp4xx/Makefile +++ b/arch/arm/mach-ixp4xx/Makefile @@ -14,6 +14,7 @@ obj-pci-$(CONFIG_MACH_NSLU2) += nslu2-pci.o obj-pci-$(CONFIG_MACH_NAS100D) += nas100d-pci.o obj-pci-$(CONFIG_MACH_DSMG600) += dsmg600-pci.o obj-pci-$(CONFIG_MACH_GATEWAY7001) += gateway7001-pci.o +obj-pci-$(CONFIG_MACH_WG302V2) += wg302v2-pci.o obj-y += common.o @@ -26,5 +27,6 @@ obj-$(CONFIG_MACH_NSLU2) += nslu2-setup.o nslu2-power.o obj-$(CONFIG_MACH_NAS100D) += nas100d-setup.o nas100d-power.o obj-$(CONFIG_MACH_DSMG600) += dsmg600-setup.o dsmg600-power.o obj-$(CONFIG_MACH_GATEWAY7001) += gateway7001-setup.o +obj-$(CONFIG_MACH_WG302V2) += wg302v2-setup.o obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o diff --git a/arch/arm/mach-ixp4xx/wg302v2-pci.c b/arch/arm/mach-ixp4xx/wg302v2-pci.c new file mode 100644 index 000000000000..7c0e3aa4ef5d --- /dev/null +++ b/arch/arm/mach-ixp4xx/wg302v2-pci.c @@ -0,0 +1,64 @@ +/* + * arch/arch/mach-ixp4xx/wg302v2-pci.c + * + * PCI setup routines for the Netgear WG302 v2 and WAG302 v2 + * + * Copyright (C) 2007 Imre Kaloz + * + * based on coyote-pci.c: + * Copyright (C) 2002 Jungo Software Technologies. + * Copyright (C) 2003 MontaVista Software, Inc. + * + * Maintainer: Imre Kaloz + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +void __init wg302v2_pci_preinit(void) +{ + set_irq_type(IRQ_IXP4XX_GPIO8, IRQT_LOW); + set_irq_type(IRQ_IXP4XX_GPIO9, IRQT_LOW); + + ixp4xx_pci_preinit(); +} + +static int __init wg302v2_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + if (slot == 1) + return IRQ_IXP4XX_GPIO8; + else if (slot == 2) + return IRQ_IXP4XX_GPIO9; + else return -1; +} + +struct hw_pci wg302v2_pci __initdata = { + .nr_controllers = 1, + .preinit = wg302v2_pci_preinit, + .swizzle = pci_std_swizzle, + .setup = ixp4xx_setup, + .scan = ixp4xx_scan_bus, + .map_irq = wg302v2_map_irq, +}; + +int __init wg302v2_pci_init(void) +{ + if (machine_is_wg302v2()) + pci_common_init(&wg302v2_pci); + return 0; +} + +subsys_initcall(wg302v2_pci_init); diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c new file mode 100644 index 000000000000..f7e09ad804e8 --- /dev/null +++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c @@ -0,0 +1,109 @@ +/* + * arch/arm/mach-ixp4xx/wg302-setup.c + * + * Board setup for the Netgear WG302 v2 and WAG302 v2 + * + * Copyright (C) 2007 Imre Kaloz + * + * based on coyote-setup.c: + * Copyright (C) 2003-2005 MontaVista Software, Inc. + * + * Author: Imre Kaloz + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct flash_platform_data wg302v2_flash_data = { + .map_name = "cfi_probe", + .width = 2, +}; + +static struct resource wg302v2_flash_resource = { + .flags = IORESOURCE_MEM, +}; + +static struct platform_device wg302v2_flash = { + .name = "IXP4XX-Flash", + .id = 0, + .dev = { + .platform_data = &wg302v2_flash_data, + }, + .num_resources = 1, + .resource = &wg302v2_flash_resource, +}; + +static struct resource wg302v2_uart_resource = { + .start = IXP4XX_UART2_BASE_PHYS, + .end = IXP4XX_UART2_BASE_PHYS + 0x0fff, + .flags = IORESOURCE_MEM, +}; + +static struct plat_serial8250_port wg302v2_uart_data[] = { + { + .mapbase = IXP4XX_UART2_BASE_PHYS, + .membase = (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET, + .irq = IRQ_IXP4XX_UART2, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST, + .iotype = UPIO_MEM, + .regshift = 2, + .uartclk = IXP4XX_UART_XTAL, + }, + { }, +}; + +static struct platform_device wg302v2_uart = { + .name = "serial8250", + .id = PLAT8250_DEV_PLATFORM, + .dev = { + .platform_data = wg302v2_uart_data, + }, + .num_resources = 1, + .resource = &wg302v2_uart_resource, +}; + +static struct platform_device *wg302v2_devices[] __initdata = { + &wg302v2_flash, + &wg302v2_uart, +}; + +static void __init wg302v2_init(void) +{ + ixp4xx_sys_init(); + + wg302v2_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); + wg302v2_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + SZ_32M - 1; + + *IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE; + *IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0; + + platform_add_devices(wg302v2_devices, ARRAY_SIZE(wg302v2_devices)); +} + +#ifdef CONFIG_MACH_WG302V2 +MACHINE_START(WG302V2, "Netgear WG302 v2 / WAG302 v2") + /* Maintainer: Imre Kaloz */ + .phys_io = IXP4XX_PERIPHERAL_BASE_PHYS, + .io_pg_offst = ((IXP4XX_PERIPHERAL_BASE_VIRT) >> 18) & 0xfffc, + .map_io = ixp4xx_map_io, + .init_irq = ixp4xx_init_irq, + .timer = &ixp4xx_timer, + .boot_params = 0x0100, + .init_machine = wg302v2_init, +MACHINE_END +#endif diff --git a/include/asm-arm/arch-ixp4xx/uncompress.h b/include/asm-arm/arch-ixp4xx/uncompress.h index bf7a7882bf7c..f7a35b78823f 100644 --- a/include/asm-arm/arch-ixp4xx/uncompress.h +++ b/include/asm-arm/arch-ixp4xx/uncompress.h @@ -41,7 +41,7 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id) * Some boards are using UART2 as console */ if (machine_is_adi_coyote() || machine_is_gtwx5715() || - machine_is_gateway7001()) + machine_is_gateway7001() || machine_is_wg302v2()) uart_base = (volatile u32*) IXP4XX_UART2_BASE_PHYS; else uart_base = (volatile u32*) IXP4XX_UART1_BASE_PHYS; From ddaca4a26efc0716708f027914bf5508e2d86cc7 Mon Sep 17 00:00:00 2001 From: Michael-Luke Jones Date: Thu, 31 May 2007 12:27:14 +0100 Subject: [PATCH 15/45] [ARM] 4408/2: Fixup support for gtwx5715 ixp4xx board This patch fixes up compiling of the gtwx5715 board setup code, which has apparently been broken since 2.6.18 and the generic IRQ changes. In addition it removes some unecessary extern declarations in the gtwx5715-pci.c file. Signed-off-by: Michael-Luke Jones Signed-off-by: Russell King --- arch/arm/mach-ixp4xx/gtwx5715-pci.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c index a66484b63d36..289d29392736 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-pci.c @@ -25,17 +25,14 @@ #include #include #include +#include + #include #include #include #include #include -extern void ixp4xx_pci_preinit(void); -extern int ixp4xx_setup(int nr, struct pci_sys_data *sys); -extern struct pci_bus *ixp4xx_scan_bus(int nr, struct pci_sys_data *sys); - - /* * The exact GPIO pins and IRQs are defined in arch-ixp4xx/gtwx5715.h * Slot 0 isn't actually populated with a card connector but From d85ed59524d936f4c2657ba39a483b4ab373a59e Mon Sep 17 00:00:00 2001 From: Michael-Luke Jones Date: Sat, 26 May 2007 21:58:07 +0100 Subject: [PATCH 16/45] [ARM] 4407/1: Remove in-kernel mach id setting for gtwx5715 ixp4xx board If MACH_GTWX5715 is set in Kconfig, this code sets the mach id automatically. Howeber, this means that any IXP4xx kernel which is setup to support the gtwx5715 board will not successfully boot on any other board. If the bootloader sets the wrong mach id, it should be set correctly by a kernel shim. Signed-off-by: Michael-Luke Jones Signed-off-by: Russell King --- arch/arm/boot/compressed/head-xscale.S | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/arm/boot/compressed/head-xscale.S b/arch/arm/boot/compressed/head-xscale.S index 73c5d9e0201c..236bbe578312 100644 --- a/arch/arm/boot/compressed/head-xscale.S +++ b/arch/arm/boot/compressed/head-xscale.S @@ -41,11 +41,6 @@ __XScale_start: mov r7, #MACH_TYPE_COTULLA_IDP #endif -#ifdef CONFIG_MACH_GTWX5715 - mov r7, #(MACH_TYPE_GTWX5715 & 0xff) - orr r7, r7, #(MACH_TYPE_GTWX5715 & 0xff00) -#endif - #ifdef CONFIG_ARCH_IXP2000 mov r1, #-1 mov r0, #0xd6000000 From eab03b3f6609518a80eae4d1f5d78ff8f44e116a Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 3 Jun 2007 18:50:49 +0100 Subject: [PATCH 17/45] [ARM] If linux/irq.h is included, asm/irq.h is not required Signed-off-by: Russell King --- arch/arm/mach-ixp4xx/gateway7001-pci.c | 1 - arch/arm/mach-ixp4xx/gtwx5715-pci.c | 1 - arch/arm/mach-ixp4xx/wg302v2-pci.c | 1 - 3 files changed, 3 deletions(-) diff --git a/arch/arm/mach-ixp4xx/gateway7001-pci.c b/arch/arm/mach-ixp4xx/gateway7001-pci.c index 4f2eeb050314..6abf568322d3 100644 --- a/arch/arm/mach-ixp4xx/gateway7001-pci.c +++ b/arch/arm/mach-ixp4xx/gateway7001-pci.c @@ -24,7 +24,6 @@ #include #include -#include #include diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c index 289d29392736..0d5a42455820 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-pci.c @@ -29,7 +29,6 @@ #include #include -#include #include #include diff --git a/arch/arm/mach-ixp4xx/wg302v2-pci.c b/arch/arm/mach-ixp4xx/wg302v2-pci.c index 7c0e3aa4ef5d..6588f2c758e2 100644 --- a/arch/arm/mach-ixp4xx/wg302v2-pci.c +++ b/arch/arm/mach-ixp4xx/wg302v2-pci.c @@ -24,7 +24,6 @@ #include #include -#include #include From 8a87a996eae3d25b0670a243f4829ea4aa9eb63d Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Mon, 14 May 2007 14:30:15 +0100 Subject: [PATCH 18/45] [ARM] 4377/1: KS8695: GPIO driver Driver to control the GPIO pins on the KS8695 processor. The driver natively supports the Generic GPIO interface. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/Kconfig | 1 + arch/arm/mach-ks8695/Makefile | 2 +- arch/arm/mach-ks8695/gpio.c | 218 +++++++++++++++++++++++++++++ include/asm-arm/arch-ks8695/gpio.h | 79 +++++++++++ 4 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-ks8695/gpio.c create mode 100644 include/asm-arm/arch-ks8695/gpio.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 50d9f3e4e0f1..68f2006fdfdd 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -308,6 +308,7 @@ config ARCH_L7200 config ARCH_KS8695 bool "Micrel/Kendin KS8695" + select GENERIC_GPIO help Support for Micrel/Kendin KS8695 "Centaur" (ARM922T) based System-on-Chip devices. diff --git a/arch/arm/mach-ks8695/Makefile b/arch/arm/mach-ks8695/Makefile index 56b7d337333a..2a07a281fa8a 100644 --- a/arch/arm/mach-ks8695/Makefile +++ b/arch/arm/mach-ks8695/Makefile @@ -3,7 +3,7 @@ # Makefile for KS8695 architecture support # -obj-y := cpu.o irq.o time.o devices.o +obj-y := cpu.o irq.o time.o gpio.o devices.o obj-m := obj-n := obj- := diff --git a/arch/arm/mach-ks8695/gpio.c b/arch/arm/mach-ks8695/gpio.c new file mode 100644 index 000000000000..b1aa3cb3d4a3 --- /dev/null +++ b/arch/arm/mach-ks8695/gpio.c @@ -0,0 +1,218 @@ +/* + * arch/arm/mach-ks8695/gpio.c + * + * Copyright (C) 2006 Andrew Victor + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +/* + * Configure a GPIO line for either GPIO function, or its internal + * function (Interrupt, Timer, etc). + */ +static void __init_or_module ks8695_gpio_mode(unsigned int pin, short gpio) +{ + unsigned int enable[] = { IOPC_IOEINT0EN, IOPC_IOEINT1EN, IOPC_IOEINT2EN, IOPC_IOEINT3EN, IOPC_IOTIM0EN, IOPC_IOTIM1EN }; + unsigned long x, flags; + + if (pin > KS8695_GPIO_5) /* only GPIO 0..5 have internal functions */ + return; + + local_irq_save(flags); + + x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); + if (gpio) /* GPIO: set bit to 0 */ + x &= ~enable[pin]; + else /* Internal function: set bit to 1 */ + x |= enable[pin]; + __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPC); + + local_irq_restore(flags); +} + + +static unsigned short gpio_irq[] = { KS8695_IRQ_EXTERN0, KS8695_IRQ_EXTERN1, KS8695_IRQ_EXTERN2, KS8695_IRQ_EXTERN3 }; + +/* + * Configure GPIO pin as external interrupt source. + */ +int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type) +{ + unsigned long x, flags; + + if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ + return -EINVAL; + + local_irq_save(flags); + + /* set pin as input */ + x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); + x &= ~IOPM_(pin); + __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); + + local_irq_restore(flags); + + /* Set IRQ triggering type */ + set_irq_type(gpio_irq[pin], type); + + /* enable interrupt mode */ + ks8695_gpio_mode(pin, 0); + + return 0; +} +EXPORT_SYMBOL(ks8695_gpio_interrupt); + + + +/* .... Generic GPIO interface .............................................. */ + +/* + * Configure the GPIO line as an input. + */ +int __init_or_module gpio_direction_input(unsigned int pin) +{ + unsigned long x, flags; + + if (pin > KS8695_GPIO_15) + return -EINVAL; + + /* set pin to GPIO mode */ + ks8695_gpio_mode(pin, 1); + + local_irq_save(flags); + + /* set pin as input */ + x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); + x &= ~IOPM_(pin); + __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); + + local_irq_restore(flags); + + return 0; +} +EXPORT_SYMBOL(gpio_direction_input); + + +/* + * Configure the GPIO line as an output, with default state. + */ +int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state) +{ + unsigned long x, flags; + + if (pin > KS8695_GPIO_15) + return -EINVAL; + + /* set pin to GPIO mode */ + ks8695_gpio_mode(pin, 1); + + local_irq_save(flags); + + /* set line state */ + x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); + if (state) + x |= (1 << pin); + else + x &= ~(1 << pin); + __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); + + /* set pin as output */ + x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPM); + x |= IOPM_(pin); + __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPM); + + local_irq_restore(flags); + + return 0; +} +EXPORT_SYMBOL(gpio_direction_output); + + +/* + * Set the state of an output GPIO line. + */ +void gpio_set_value(unsigned int pin, unsigned int state) +{ + unsigned long x, flags; + + if (pin > KS8695_GPIO_15) + return; + + local_irq_save(flags); + + /* set output line state */ + x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); + if (state) + x |= (1 << pin); + else + x &= ~(1 << pin); + __raw_writel(x, KS8695_GPIO_VA + KS8695_IOPD); + + local_irq_restore(flags); +} +EXPORT_SYMBOL(gpio_set_value); + + +/* + * Read the state of a GPIO line. + */ +int gpio_get_value(unsigned int pin) +{ + unsigned long x; + + if (pin > KS8695_GPIO_15) + return -EINVAL; + + x = __raw_readl(KS8695_GPIO_VA + KS8695_IOPD); + return (x & (1 << pin)) != 0; +} +EXPORT_SYMBOL(gpio_get_value); + + +/* + * Map GPIO line to IRQ number. + */ +int gpio_to_irq(unsigned int pin) +{ + if (pin > KS8695_GPIO_3) /* only GPIO 0..3 can generate IRQ */ + return -EINVAL; + + return gpio_irq[pin]; +} +EXPORT_SYMBOL(gpio_to_irq); + + +/* + * Map IRQ number to GPIO line. + */ +int irq_to_gpio(unsigned int irq) +{ + if ((irq < KS8695_IRQ_EXTERN0) || (irq > KS8695_IRQ_EXTERN3)) + return -EINVAL; + + return (irq - KS8695_IRQ_EXTERN0); +} +EXPORT_SYMBOL(irq_to_gpio); diff --git a/include/asm-arm/arch-ks8695/gpio.h b/include/asm-arm/arch-ks8695/gpio.h new file mode 100644 index 000000000000..65ceea28607b --- /dev/null +++ b/include/asm-arm/arch-ks8695/gpio.h @@ -0,0 +1,79 @@ +/* + * include/asm-arm/arch-ks8695/gpio.h + * + * Copyright (C) 2006 Andrew Victor + * + * 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. + */ + +#ifndef __ASM_ARCH_GPIO_H_ +#define __ASM_ARCH_GPIO_H_ + +#define KS8695_GPIO_0 0 +#define KS8695_GPIO_1 1 +#define KS8695_GPIO_2 2 +#define KS8695_GPIO_3 3 +#define KS8695_GPIO_4 4 +#define KS8695_GPIO_5 5 +#define KS8695_GPIO_6 6 +#define KS8695_GPIO_7 7 +#define KS8695_GPIO_8 8 +#define KS8695_GPIO_9 9 +#define KS8695_GPIO_10 10 +#define KS8695_GPIO_11 11 +#define KS8695_GPIO_12 12 +#define KS8695_GPIO_13 13 +#define KS8695_GPIO_14 14 +#define KS8695_GPIO_15 15 + + +/* + * Configure GPIO pin as external interrupt source. + */ +int __init_or_module ks8695_gpio_interrupt(unsigned int pin, unsigned int type); + +/* + * Configure the GPIO line as an input. + */ +int __init_or_module gpio_direction_input(unsigned int pin); + +/* + * Configure the GPIO line as an output, with default state. + */ +int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state); + +/* + * Set the state of an output GPIO line. + */ +void gpio_set_value(unsigned int pin, unsigned int state); + +/* + * Read the state of a GPIO line. + */ +int gpio_get_value(unsigned int pin); + +/* + * Map GPIO line to IRQ number. + */ +int gpio_to_irq(unsigned int pin); + +/* + * Map IRQ number to GPIO line. + */ +int irq_to_gpio(unsigned int irq); + + +#include + +static inline int gpio_request(unsigned int pin, const char *label) +{ + return 0; +} + +static inline void gpio_free(unsigned int pin) +{ +} + +#endif From 4486b86368d72bcac76439638b36667b1c6a1360 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 3 Jun 2007 18:54:42 +0100 Subject: [PATCH 19/45] [ARM] riscpc: fix decompressor font file handling font_acorn_8x8.o was being built in drivers/video/console/ twice during a build _in the same location_ - once for the kernel proper, and once for the decompressor. The result is when you came to run an install target, the kernel was always rebuilt due to this file apparantly having been built with different compiler arguments. Solve this by making a local copy at build time in the decompressor's directory. Signed-off-by: Russell King --- arch/arm/boot/compressed/.gitignore | 1 + arch/arm/boot/compressed/Makefile | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore index aefee20cbf98..b15f927a5926 100644 --- a/arch/arm/boot/compressed/.gitignore +++ b/arch/arm/boot/compressed/.gitignore @@ -1 +1,2 @@ piggy.gz +font.c diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index adddc7131685..a1f1691b67fe 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -6,15 +6,13 @@ HEAD = head.o OBJS = misc.o -FONTC = drivers/video/console/font_acorn_8x8.c - -FONT = $(addprefix ../../../../drivers/video/console/, font_acorn_8x8.o) +FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c # # Architecture dependencies # ifeq ($(CONFIG_ARCH_ACORN),y) -OBJS += ll_char_wr.o $(FONT) +OBJS += ll_char_wr.o font.o endif ifeq ($(CONFIG_ARCH_SHARK),y) @@ -73,7 +71,7 @@ endif SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ -targets := vmlinux vmlinux.lds piggy.gz piggy.o $(FONT) \ +targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \ head.o misc.o $(OBJS) EXTRA_CFLAGS := -fpic EXTRA_AFLAGS := @@ -105,7 +103,10 @@ $(obj)/piggy.gz: $(obj)/../Image FORCE $(obj)/piggy.o: $(obj)/piggy.gz FORCE -CFLAGS_font_acorn_8x8.o := -Dstatic= +CFLAGS_font.o := -Dstatic= + +$(obj)/font.c: $(FONTC) + $(call cmd,shipped) $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile .config @sed "$(SEDFLAGS)" < $< > $@ From 6d78b5f9c6cf59c98d3833e09d0ed6aebd6a33d3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 3 Jun 2007 19:26:04 +0100 Subject: [PATCH 20/45] [ARM] Fix bounding error in ioremap_pfn() If size=16M offset=2K then we should map two supersections rather than just one. Signed-off-by: Russell King --- arch/arm/mm/ioremap.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index f3ade18862aa..75952779ce19 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -280,7 +280,10 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, if (!type) return NULL; - size = PAGE_ALIGN(size); + /* + * Page align the mapping size, taking account of any offset. + */ + size = PAGE_ALIGN(offset + size); area = get_vm_area(size, VM_IOREMAP); if (!area) @@ -325,11 +328,6 @@ __arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype) if (!size || last_addr < phys_addr) return NULL; - /* - * Page align the mapping size - */ - size = PAGE_ALIGN(last_addr + 1) - phys_addr; - return __arm_ioremap_pfn(pfn, offset, size, mtype); } EXPORT_SYMBOL(__arm_ioremap); From 7d09e85448dfa78e3e58186c934449aaf6d49b50 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 1 Jun 2007 17:14:53 +0100 Subject: [PATCH 21/45] [ARM] 4393/2: ARMv7: Add uncompressing code for the new CPU Id format The current arch/arm/boot/compressed/head.S code only supports cores to ARMv6 with the old CPU Id format. This patch adds support for the new ARMv6 with the new CPU Id and ARMv7 cores that no longer have the ARMv4 cache operations. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/boot/compressed/head.S | 93 ++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 680ea6ed77b8..d7fb5ee1637e 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -436,6 +436,28 @@ __armv4_mmu_cache_on: mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs mov pc, r12 +__armv7_mmu_cache_on: + mov r12, lr + mrc p15, 0, r11, c0, c1, 4 @ read ID_MMFR0 + tst r11, #0xf @ VMSA + blne __setup_mmu + mov r0, #0 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer + tst r11, #0xf @ VMSA + mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs + mrc p15, 0, r0, c1, c0, 0 @ read control reg + orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement + orr r0, r0, #0x003c @ write buffer + orrne r0, r0, #1 @ MMU enabled + movne r1, #-1 + mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer + mcrne p15, 0, r1, c3, c0, 0 @ load domain access control + mcr p15, 0, r0, c1, c0, 0 @ load control register + mrc p15, 0, r0, c1, c0, 0 @ and read it back + mov r0, #0 + mcr p15, 0, r0, c7, c5, 4 @ ISB + mov pc, r12 + __arm6_mmu_cache_on: mov r12, lr bl __setup_mmu @@ -622,11 +644,17 @@ proc_types: b __armv4_mmu_cache_flush .word 0x0007b000 @ ARMv6 - .word 0x0007f000 + .word 0x000ff000 b __armv4_mmu_cache_on b __armv4_mmu_cache_off b __armv6_mmu_cache_flush + .word 0x000f0000 @ new CPU Id + .word 0x000f0000 + b __armv7_mmu_cache_on + b __armv7_mmu_cache_off + b __armv7_mmu_cache_flush + .word 0 @ unrecognised type .word 0 mov pc, lr @@ -674,6 +702,16 @@ __armv4_mmu_cache_off: mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4 mov pc, lr +__armv7_mmu_cache_off: + mrc p15, 0, r0, c1, c0 + bic r0, r0, #0x000d + mcr p15, 0, r0, c1, c0 @ turn MMU and cache off + mov r12, lr + bl __armv7_mmu_cache_flush + mov r0, #0 + mcr p15, 0, r0, c8, c7, 0 @ invalidate whole TLB + mov pc, r12 + __arm6_mmu_cache_off: mov r0, #0x00000030 @ ARM6 control reg. b __armv3_mmu_cache_off @@ -730,6 +768,59 @@ __armv6_mmu_cache_flush: mcr p15, 0, r1, c7, c10, 4 @ drain WB mov pc, lr +__armv7_mmu_cache_flush: + mrc p15, 0, r10, c0, c1, 5 @ read ID_MMFR1 + tst r10, #0xf << 16 @ hierarchical cache (ARMv7) + beq hierarchical + mov r10, #0 + mcr p15, 0, r10, c7, c14, 0 @ clean+invalidate D + b iflush +hierarchical: + stmfd sp!, {r0-r5, r7, r9-r11} + mrc p15, 1, r0, c0, c0, 1 @ read clidr + ands r3, r0, #0x7000000 @ extract loc from clidr + mov r3, r3, lsr #23 @ left align loc bit field + beq finished @ if loc is 0, then no need to clean + mov r10, #0 @ start clean at cache level 0 +loop1: + add r2, r10, r10, lsr #1 @ work out 3x current cache level + mov r1, r0, lsr r2 @ extract cache type bits from clidr + and r1, r1, #7 @ mask of the bits for current cache only + cmp r1, #2 @ see what cache we have at this level + blt skip @ skip if no cache, or just i-cache + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + mcr p15, 0, r10, c7, c5, 4 @ isb to sych the new cssr&csidr + mrc p15, 1, r1, c0, c0, 0 @ read the new csidr + and r2, r1, #7 @ extract the length of the cache lines + add r2, r2, #4 @ add 4 (line length offset) + ldr r4, =0x3ff + ands r4, r4, r1, lsr #3 @ find maximum number on the way size + .word 0xe16f5f14 @ clz r5, r4 - find bit position of way size increment + ldr r7, =0x7fff + ands r7, r7, r1, lsr #13 @ extract max number of the index size +loop2: + mov r9, r4 @ create working copy of max way size +loop3: + orr r11, r10, r9, lsl r5 @ factor way and cache number into r11 + orr r11, r11, r7, lsl r2 @ factor index number into r11 + mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way + subs r9, r9, #1 @ decrement the way + bge loop3 + subs r7, r7, #1 @ decrement the index + bge loop2 +skip: + add r10, r10, #2 @ increment cache number + cmp r3, r10 + bgt loop1 +finished: + mov r10, #0 @ swith back to cache level 0 + mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr + ldmfd sp!, {r0-r5, r7, r9-r11} +iflush: + mcr p15, 0, r10, c7, c5, 0 @ invalidate I+BTB + mcr p15, 0, r10, c7, c10, 4 @ drain WB + mov pc, lr + __armv4_mmu_cache_flush: mov r2, #64*1024 @ default: 32K dcache size (*2) mov r11, #32 @ default: 32 byte line size From 9d20fdd58e74d4d26dc5216efaaa0f800c23dd3a Mon Sep 17 00:00:00 2001 From: Bill Gatliff Date: Thu, 31 May 2007 22:02:22 +0100 Subject: [PATCH 22/45] [ARM] 4423/1: add ATAGS support Examines the ATAGS pointer (r2) at boot, and interprets a nonzero value as a reference to an ATAGS structure. A suitable ATAGS structure replaces the kernel's command line. Signed-off-by: Bill Gatliff Signed-off-by: Russell King --- arch/arm/kernel/head-common.S | 40 ++++++++++++++++++++++++++++++++--- arch/arm/kernel/head.S | 7 +++++- arch/arm/kernel/setup.c | 6 +++++- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S index a52da0ddb43d..024a9cf469b4 100644 --- a/arch/arm/kernel/head-common.S +++ b/arch/arm/kernel/head-common.S @@ -20,7 +20,8 @@ __switch_data: .long _end @ r7 .long processor_id @ r4 .long __machine_arch_type @ r5 - .long cr_alignment @ r6 + .long __atags_pointer @ r6 + .long cr_alignment @ r7 .long init_thread_union + THREAD_START_SP @ sp /* @@ -29,6 +30,7 @@ __switch_data: * * r0 = cp#15 control register * r1 = machine ID + * r2 = atags pointer * r9 = processor ID */ .type __mmap_switched, %function @@ -47,11 +49,12 @@ __mmap_switched: strcc fp, [r6],#4 bcc 1b - ldmia r3, {r4, r5, r6, sp} + ldmia r3, {r4, r5, r6, r7, sp} str r9, [r4] @ Save processor ID str r1, [r5] @ Save machine type + str r2, [r6] @ Save atags pointer bic r4, r0, #CR_A @ Clear 'A' bit - stmia r6, {r0, r4} @ Save control register values + stmia r7, {r0, r4} @ Save control register values b start_kernel /* @@ -215,3 +218,34 @@ ENTRY(lookup_machine_type) bl __lookup_machine_type mov r0, r5 ldmfd sp!, {r4 - r6, pc} + +/* Determine validity of the r2 atags pointer. The heuristic requires + * that the pointer be aligned, in the first 16k of physical RAM and + * that the ATAG_CORE marker is first and present. Future revisions + * of this function may be more lenient with the physical address and + * may also be able to move the ATAGS block if necessary. + * + * r8 = machinfo + * + * Returns: + * r2 either valid atags pointer, or zero + * r5, r6 corrupted + */ + + .type __vet_atags, %function +__vet_atags: + tst r2, #0x3 @ aligned? + bne 1f + + ldr r5, [r2, #0] @ is first tag ATAG_CORE? + subs r5, r5, #ATAG_CORE_SIZE + bne 1f + ldr r5, [r2, #4] + ldr r6, =ATAG_CORE + cmp r5, r6 + bne 1f + + mov pc, lr @ atag pointer is ok + +1: mov r2, #0 + mov pc, lr diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 41f98b4ba2ee..7898cbc9861a 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -29,6 +29,10 @@ #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) #define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) +#define ATAG_CORE 0x54410001 +#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2) + + /* * swapper_pg_dir is the virtual address of the initial page table. * We place the page tables 16K below KERNEL_RAM_VADDR. Therefore, we must @@ -61,7 +65,7 @@ * * This is normally called from the decompressor code. The requirements * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0, - * r1 = machine nr. + * r1 = machine nr, r2 = atags pointer. * * This code is mostly position independent, so if you link the kernel at * 0xc0008000, you call this at __pa(0xc0008000). @@ -85,6 +89,7 @@ ENTRY(stext) bl __lookup_machine_type @ r5=machinfo movs r8, r5 @ invalid machine (r5=0)? beq __error_a @ yes, error 'a' + bl __vet_atags bl __create_page_tables /* diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 650eac1bc0a6..5be2e987b843 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -63,6 +63,8 @@ unsigned int processor_id; unsigned int __machine_arch_type; EXPORT_SYMBOL(__machine_arch_type); +unsigned int __atags_pointer __initdata; + unsigned int system_rev; EXPORT_SYMBOL(system_rev); @@ -780,7 +782,9 @@ void __init setup_arch(char **cmdline_p) if (mdesc->soft_reboot) reboot_setup("s"); - if (mdesc->boot_params) + if (__atags_pointer) + tags = phys_to_virt(__atags_pointer); + else if (mdesc->boot_params) tags = phys_to_virt(mdesc->boot_params); /* From 909d6c6c80311f800aee338e5fa528818b115951 Mon Sep 17 00:00:00 2001 From: "George G. Davis" Date: Tue, 26 Jun 2007 01:38:27 +0100 Subject: [PATCH 23/45] [ARM] 4453/1: Fully Decode ARM instruction set state in show_regs() tombstone The ARM show_regs() tombstone only partially decodes which ARM ISA was executing at the time a fault occurred displaying either "(T)" for the Thumb case or nothing at all for other cases. This patch therefore explicitly identifies which state the processor is in at the time of a fault: ARM, Thumb, Jazelle or JazelleEE. Signed-off-by: George G. Davis Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/kernel/process.c | 8 ++++++-- include/asm-arm/ptrace.h | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 842361777d4e..93b7f8e22dcc 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -44,6 +44,10 @@ static const char *processor_modes[] = { "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" }; +static const char *isa_modes[] = { + "ARM" , "Thumb" , "Jazelle", "ThumbEE" +}; + extern void setup_mm_for_reboot(char mode); static volatile int hlt_counter; @@ -230,11 +234,11 @@ void __show_regs(struct pt_regs *regs) buf[3] = flags & PSR_V_BIT ? 'V' : 'v'; buf[4] = '\0'; - printk("Flags: %s IRQs o%s FIQs o%s Mode %s%s Segment %s\n", + printk("Flags: %s IRQs o%s FIQs o%s Mode %s ISA %s Segment %s\n", buf, interrupts_enabled(regs) ? "n" : "ff", fast_interrupts_enabled(regs) ? "n" : "ff", processor_modes[processor_mode(regs)], - thumb_mode(regs) ? " (T)" : "", + isa_modes[isa_mode(regs)], get_fs() == get_ds() ? "kernel" : "user"); #ifdef CONFIG_CPU_CP15 { diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h index ee3d93c281d8..ff038b65f370 100644 --- a/include/asm-arm/ptrace.h +++ b/include/asm-arm/ptrace.h @@ -103,6 +103,10 @@ struct pt_regs { #define thumb_mode(regs) (0) #endif +#define isa_mode(regs) \ + ((((regs)->ARM_cpsr & PSR_J_BIT) >> 23) | \ + (((regs)->ARM_cpsr & PSR_T_BIT) >> 5)) + #define processor_mode(regs) \ ((regs)->ARM_cpsr & MODE_MASK) From f62c3f2c35874713ebbb6b6a4b9d9c6caaed4f14 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 15 May 2007 11:03:24 +0100 Subject: [PATCH 24/45] [ARM] pxa: remove useless pxa_pm_finish() function pxa_pm_finish() does nothing but return zero. The core code does nothing with this return value, and will not try to call the finish method in the pm_ops structure if it is NULL. Therefore, we can remove this useless function. Signed-off-by: Russell King --- arch/arm/common/sharpsl_pm.c | 1 - arch/arm/mach-pxa/pm.c | 11 ----------- include/asm-arm/arch-pxa/pm.h | 1 - 3 files changed, 13 deletions(-) diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c index 3bf3a927ae22..62cb50816cc6 100644 --- a/arch/arm/common/sharpsl_pm.c +++ b/arch/arm/common/sharpsl_pm.c @@ -768,7 +768,6 @@ static void sharpsl_apm_get_power_status(struct apm_power_info *info) static struct pm_ops sharpsl_pm_ops = { .prepare = pxa_pm_prepare, .enter = corgi_pxa_pm_enter, - .finish = pxa_pm_finish, .valid = pm_valid_only_mem, }; diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index 6bf15ae73848..6d86203aef7b 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -213,20 +213,9 @@ int pxa_pm_prepare(suspend_state_t state) EXPORT_SYMBOL_GPL(pxa_pm_prepare); -/* - * Called after devices are re-setup, but before processes are thawed. - */ -int pxa_pm_finish(suspend_state_t state) -{ - return 0; -} - -EXPORT_SYMBOL_GPL(pxa_pm_finish); - static struct pm_ops pxa_pm_ops = { .prepare = pxa_pm_prepare, .enter = pxa_pm_enter, - .finish = pxa_pm_finish, .valid = pm_valid_only_mem, }; diff --git a/include/asm-arm/arch-pxa/pm.h b/include/asm-arm/arch-pxa/pm.h index 7a8a1cdf430d..52243a62c4e7 100644 --- a/include/asm-arm/arch-pxa/pm.h +++ b/include/asm-arm/arch-pxa/pm.h @@ -9,4 +9,3 @@ extern int pxa_pm_prepare(suspend_state_t state); extern int pxa_pm_enter(suspend_state_t state); -extern int pxa_pm_finish(suspend_state_t state); From f4b6a0a401f2cec5e6199e805ed42f30d8c04e94 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 15 May 2007 16:49:02 +0100 Subject: [PATCH 25/45] [ARM] pxa: use mutexes instead of semaphores Signed-off-by: Russell King --- arch/arm/mach-pxa/clock.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c index 8f7c90a0593b..34a31caa6f9d 100644 --- a/arch/arm/mach-pxa/clock.c +++ b/arch/arm/mach-pxa/clock.c @@ -12,7 +12,6 @@ #include #include -#include struct clk { struct list_head node; @@ -25,21 +24,21 @@ struct clk { }; static LIST_HEAD(clocks); -static DECLARE_MUTEX(clocks_sem); +static DEFINE_MUTEX(clocks_mutex); static DEFINE_SPINLOCK(clocks_lock); struct clk *clk_get(struct device *dev, const char *id) { struct clk *p, *clk = ERR_PTR(-ENOENT); - down(&clocks_sem); + mutex_lock(&clocks_mutex); list_for_each_entry(p, &clocks, node) { if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) { clk = p; break; } } - up(&clocks_sem); + mutex_unlock(&clocks_mutex); return clk; } @@ -101,18 +100,18 @@ static struct clk clk_gpio27 = { int clk_register(struct clk *clk) { - down(&clocks_sem); + mutex_lock(&clocks_mutex); list_add(&clk->node, &clocks); - up(&clocks_sem); + mutex_unlock(&clocks_mutex); return 0; } EXPORT_SYMBOL(clk_register); void clk_unregister(struct clk *clk) { - down(&clocks_sem); + mutex_lock(&clocks_mutex); list_del(&clk->node); - up(&clocks_sem); + mutex_unlock(&clocks_mutex); } EXPORT_SYMBOL(clk_unregister); From 7a2b94bc39915041304578188441f0f21aa5532a Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 16 May 2007 15:44:37 +0100 Subject: [PATCH 26/45] [ARM] pxa: remove MMC register defines from pxa-regs.h pxamci.h redefines the MMC registers differently so they can be used with ioremap. Remove the incompatible definitions from pxa-regs.h. Signed-off-by: Russell King --- drivers/mmc/host/pxamci.h | 22 ---------------------- include/asm-arm/arch-pxa/pxa-regs.h | 22 +--------------------- 2 files changed, 1 insertion(+), 43 deletions(-) diff --git a/drivers/mmc/host/pxamci.h b/drivers/mmc/host/pxamci.h index 1b163220df2b..df17c281278a 100644 --- a/drivers/mmc/host/pxamci.h +++ b/drivers/mmc/host/pxamci.h @@ -1,25 +1,3 @@ -#undef MMC_STRPCL -#undef MMC_STAT -#undef MMC_CLKRT -#undef MMC_SPI -#undef MMC_CMDAT -#undef MMC_RESTO -#undef MMC_RDTO -#undef MMC_BLKLEN -#undef MMC_NOB -#undef MMC_PRTBUF -#undef MMC_I_MASK -#undef END_CMD_RES -#undef PRG_DONE -#undef DATA_TRAN_DONE -#undef MMC_I_REG -#undef MMC_CMD -#undef MMC_ARGH -#undef MMC_ARGL -#undef MMC_RES -#undef MMC_RXFIFO -#undef MMC_TXFIFO - #define MMC_STRPCL 0x0000 #define STOP_CLOCK (1 << 0) #define START_CLOCK (2 << 0) diff --git a/include/asm-arm/arch-pxa/pxa-regs.h b/include/asm-arm/arch-pxa/pxa-regs.h index dbcc9298b0c8..e68b593d69da 100644 --- a/include/asm-arm/arch-pxa/pxa-regs.h +++ b/include/asm-arm/arch-pxa/pxa-regs.h @@ -1765,29 +1765,9 @@ #define SSACD_P(x) (*(((x) == 1) ? &SSACD_P1 : ((x) == 2) ? &SSACD_P2 : ((x) == 3) ? &SSACD_P3 : NULL)) /* - * MultiMediaCard (MMC) controller + * MultiMediaCard (MMC) controller - see drivers/mmc/host/pxamci.h */ -#define MMC_STRPCL __REG(0x41100000) /* Control to start and stop MMC clock */ -#define MMC_STAT __REG(0x41100004) /* MMC Status Register (read only) */ -#define MMC_CLKRT __REG(0x41100008) /* MMC clock rate */ -#define MMC_SPI __REG(0x4110000c) /* SPI mode control bits */ -#define MMC_CMDAT __REG(0x41100010) /* Command/response/data sequence control */ -#define MMC_RESTO __REG(0x41100014) /* Expected response time out */ -#define MMC_RDTO __REG(0x41100018) /* Expected data read time out */ -#define MMC_BLKLEN __REG(0x4110001c) /* Block length of data transaction */ -#define MMC_NOB __REG(0x41100020) /* Number of blocks, for block mode */ -#define MMC_PRTBUF __REG(0x41100024) /* Partial MMC_TXFIFO FIFO written */ -#define MMC_I_MASK __REG(0x41100028) /* Interrupt Mask */ -#define MMC_I_REG __REG(0x4110002c) /* Interrupt Register (read only) */ -#define MMC_CMD __REG(0x41100030) /* Index of current command */ -#define MMC_ARGH __REG(0x41100034) /* MSW part of the current command argument */ -#define MMC_ARGL __REG(0x41100038) /* LSW part of the current command argument */ -#define MMC_RES __REG(0x4110003c) /* Response FIFO (read only) */ -#define MMC_RXFIFO __REG(0x41100040) /* Receive FIFO (read only) */ -#define MMC_TXFIFO __REG(0x41100044) /* Transmit FIFO (write only) */ - - /* * Core Clock */ From b23170c01f6e4ea043df7cd9486c2488e01f3d60 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 15 May 2007 10:26:49 +0100 Subject: [PATCH 27/45] [ARM] pxa: introduce cpu_is_pxaXXX macros Signed-off-by: Russell King --- arch/arm/mach-pxa/generic.c | 6 ++--- include/asm-arm/arch-pxa/hardware.h | 36 +++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 64b08b744f9f..147b7c40d9f9 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -448,16 +448,14 @@ static struct platform_device *devices[] __initdata = { static int __init pxa_init(void) { - int cpuid, ret; + int ret; ret = platform_add_devices(devices, ARRAY_SIZE(devices)); if (ret) return ret; /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */ - cpuid = read_cpuid(CPUID_ID); - if (((cpuid >> 4) & 0xfff) == 0x2d0 || - ((cpuid >> 4) & 0xfff) == 0x290) + if (cpu_is_pxa25x()) ret = platform_device_register(&hwuart_device); return ret; diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h index e2bdc2fbede1..386121746417 100644 --- a/include/asm-arm/arch-pxa/hardware.h +++ b/include/asm-arm/arch-pxa/hardware.h @@ -62,6 +62,42 @@ #ifndef __ASSEMBLY__ +#define __cpu_is_pxa21x(id) \ + ({ \ + unsigned int _id = (id) >> 4 & 0xf3f; \ + _id == 0x212; \ + }) + +#define __cpu_is_pxa25x(id) \ + ({ \ + unsigned int _id = (id) >> 4 & 0xfff; \ + _id == 0x2d0 || _id == 0x290; \ + }) + +#define __cpu_is_pxa27x(id) \ + ({ \ + unsigned int _id = (id) >> 4 & 0xfff; \ + _id == 0x411; \ + }) + +#define cpu_is_pxa21x() \ + ({ \ + unsigned int id = read_cpuid(CPUID_ID); \ + __cpu_is_pxa21x(id); \ + }) + +#define cpu_is_pxa25x() \ + ({ \ + unsigned int id = read_cpuid(CPUID_ID); \ + __cpu_is_pxa25x(id); \ + }) + +#define cpu_is_pxa27x() \ + ({ \ + unsigned int id = read_cpuid(CPUID_ID); \ + __cpu_is_pxa27x(id); \ + }) + /* * Handy routine to set GPIO alternate functions */ From e176bb05fec4c00450302a75e81f8da3dc9e309e Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 15 May 2007 11:16:10 +0100 Subject: [PATCH 28/45] [ARM] pxa: move pm_ops structure into CPU specific files Move the pm_ops structure into the PXA25x and PXA27x support files. Remove the old pxa_pm_prepare() function, and rename the both pxa_cpu_pm_prepare() functions as pxa_pm_prepare(). We'll fix that later. Signed-off-by: Russell King --- arch/arm/mach-pxa/pm.c | 26 -------------------------- arch/arm/mach-pxa/pxa25x.c | 20 +++++++++++++++++++- arch/arm/mach-pxa/pxa27x.c | 17 +++++++++++++++-- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index 6d86203aef7b..d439ffa1b071 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -200,29 +200,3 @@ unsigned long sleep_phys_sp(void *sp) { return virt_to_phys(sp); } - -/* - * Called after processes are frozen, but before we shut down devices. - */ -int pxa_pm_prepare(suspend_state_t state) -{ - extern int pxa_cpu_pm_prepare(suspend_state_t state); - - return pxa_cpu_pm_prepare(state); -} - -EXPORT_SYMBOL_GPL(pxa_pm_prepare); - -static struct pm_ops pxa_pm_ops = { - .prepare = pxa_pm_prepare, - .enter = pxa_pm_enter, - .valid = pm_valid_only_mem, -}; - -static int __init pxa_pm_init(void) -{ - pm_set_ops(&pxa_pm_ops); - return 0; -} - -device_initcall(pxa_pm_init); diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index c1f21739bf71..8560439ba0b9 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -23,6 +23,7 @@ #include #include +#include #include "generic.h" @@ -105,7 +106,7 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz); #ifdef CONFIG_PM -int pxa_cpu_pm_prepare(suspend_state_t state) +int pxa_pm_prepare(suspend_state_t state) { switch (state) { case PM_SUSPEND_MEM: @@ -133,4 +134,21 @@ void pxa_cpu_pm_enter(suspend_state_t state) } } +static struct pm_ops pxa25x_pm_ops = { + .prepare = pxa_pm_prepare, + .enter = pxa_pm_enter, + .valid = pm_valid_only_mem, +}; #endif + +static int __init pxa25x_init(void) +{ + if (cpu_is_pxa21x() || cpu_is_pxa25x()) { +#ifdef CONFIG_PM + pm_set_ops(&pxa25x_pm_ops); +#endif + } + return 0; +} + +subsys_initcall(pxa25x_init); diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 1939acc3f9f7..be6ca7d3afa2 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "generic.h" @@ -122,7 +123,7 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz); #ifdef CONFIG_PM -int pxa_cpu_pm_prepare(suspend_state_t state) +int pxa_pm_prepare(suspend_state_t state) { switch (state) { case PM_SUSPEND_MEM: @@ -162,6 +163,11 @@ void pxa_cpu_pm_enter(suspend_state_t state) } } +static struct pm_ops pxa27x_pm_ops = { + .prepare = pxa_pm_prepare, + .enter = pxa_pm_enter, + .valid = pm_valid_only_mem, +}; #endif /* @@ -205,7 +211,14 @@ static struct platform_device *devices[] __initdata = { static int __init pxa27x_init(void) { - return platform_add_devices(devices, ARRAY_SIZE(devices)); + int ret = 0; + if (cpu_is_pxa27x()) { +#ifdef CONFIG_PM + pm_set_ops(&pxa27x_pm_ops); +#endif + ret = platform_add_devices(devices, ARRAY_SIZE(devices)); + } + return ret; } subsys_initcall(pxa27x_init); From 88dfe98c688e1700a4a9f73f8b7d570f4f52170d Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 15 May 2007 11:22:48 +0100 Subject: [PATCH 29/45] [ARM] pxa: Fix PXA27x suspend type validation, remove pxa_pm_prepare() pxa_pm_prepare() tried to validate the suspend method type. As noted in previous commits: eb9289eb20df6b54214c45ac7c6bf5179a149026 9c372d06ce9ddf65e1393f9ea22a6d6bd5f96b42 e8c9c502690efd24b7055bf608e7a3c34216848b the checking of the suspend type in the 'prepare' method is the wrong place to do this; use the 'valid' method instead. This means that pxa_pm_prepare() can be entirely removed. Signed-off-by: Russell King --- arch/arm/common/sharpsl_pm.c | 1 - arch/arm/mach-pxa/pxa25x.c | 13 ------------- arch/arm/mach-pxa/pxa27x.c | 19 ++++++------------- 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/arch/arm/common/sharpsl_pm.c b/arch/arm/common/sharpsl_pm.c index 62cb50816cc6..111a7fa5debe 100644 --- a/arch/arm/common/sharpsl_pm.c +++ b/arch/arm/common/sharpsl_pm.c @@ -766,7 +766,6 @@ static void sharpsl_apm_get_power_status(struct apm_power_info *info) } static struct pm_ops sharpsl_pm_ops = { - .prepare = pxa_pm_prepare, .enter = corgi_pxa_pm_enter, .valid = pm_valid_only_mem, }; diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 8560439ba0b9..fe29c6e03a4f 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -106,18 +106,6 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz); #ifdef CONFIG_PM -int pxa_pm_prepare(suspend_state_t state) -{ - switch (state) { - case PM_SUSPEND_MEM: - break; - default: - return -EINVAL; - } - - return 0; -} - void pxa_cpu_pm_enter(suspend_state_t state) { extern void pxa_cpu_suspend(unsigned int); @@ -135,7 +123,6 @@ void pxa_cpu_pm_enter(suspend_state_t state) } static struct pm_ops pxa25x_pm_ops = { - .prepare = pxa_pm_prepare, .enter = pxa_pm_enter, .valid = pm_valid_only_mem, }; diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index be6ca7d3afa2..ac40fa5f7709 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -123,17 +123,6 @@ EXPORT_SYMBOL(get_lcdclk_frequency_10khz); #ifdef CONFIG_PM -int pxa_pm_prepare(suspend_state_t state) -{ - switch (state) { - case PM_SUSPEND_MEM: - case PM_SUSPEND_STANDBY: - return 0; - default: - return -EINVAL; - } -} - void pxa_cpu_pm_enter(suspend_state_t state) { extern void pxa_cpu_standby(void); @@ -163,10 +152,14 @@ void pxa_cpu_pm_enter(suspend_state_t state) } } +static int pxa27x_pm_valid(suspend_state_t state) +{ + return state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY; +} + static struct pm_ops pxa27x_pm_ops = { - .prepare = pxa_pm_prepare, .enter = pxa_pm_enter, - .valid = pm_valid_only_mem, + .valid = pxa27x_pm_valid, }; #endif From 486c955118dbbb0f13dc4d40cc5dac2b23f82676 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 6 Jun 2007 06:22:20 +0100 Subject: [PATCH 30/45] [ARM] 4434/1: PXA: remove PXA_IRQ_SKIP 1. PXA_IRQ_SKIP is defined to be 7 on PXA25x so that the first IRQ starts from zero. This makes IRQ numbering inconsistent between PXA25x and PXA27x. Remove this macro so that the same IRQ_XXXXX definition has the same value on both PXA25x and PXA27x. 2. make IRQ_SSP3..IRQ_PWRI2C valid only if PXA27x is defined, this avoids unintentional use of these macros on PXA25x Signed-off-by: eric miao Signed-off-by: Russell King --- arch/arm/mach-pxa/irq.c | 10 +++++----- include/asm-arm/arch-pxa/entry-macro.S | 2 +- include/asm-arm/arch-pxa/irqs.h | 11 ++++------- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 4619d5fe606c..45ce711f0472 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -30,12 +30,12 @@ static void pxa_mask_low_irq(unsigned int irq) { - ICMR &= ~(1 << (irq + PXA_IRQ_SKIP)); + ICMR &= ~(1 << irq); } static void pxa_unmask_low_irq(unsigned int irq) { - ICMR |= (1 << (irq + PXA_IRQ_SKIP)); + ICMR |= (1 << irq); } static int pxa_set_wake(unsigned int irq, unsigned int on) @@ -75,12 +75,12 @@ static struct irq_chip pxa_internal_chip_low = { static void pxa_mask_high_irq(unsigned int irq) { - ICMR2 &= ~(1 << (irq - 32 + PXA_IRQ_SKIP)); + ICMR2 &= ~(1 << (irq - 32)); } static void pxa_unmask_high_irq(unsigned int irq) { - ICMR2 |= (1 << (irq - 32 + PXA_IRQ_SKIP)); + ICMR2 |= (1 << (irq - 32)); } static struct irq_chip pxa_internal_chip_high = { @@ -351,7 +351,7 @@ void __init pxa_init_irq(void) /* GPIO 0 and 1 must have their mask bit always set */ GPIO_IRQ_mask[0] = 3; - for (irq = PXA_IRQ(PXA_IRQ_SKIP); irq <= PXA_IRQ(31); irq++) { + for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) { set_irq_chip(irq, &pxa_internal_chip_low); set_irq_handler(irq, handle_level_irq); set_irq_flags(irq, IRQF_VALID); diff --git a/include/asm-arm/arch-pxa/entry-macro.S b/include/asm-arm/arch-pxa/entry-macro.S index 1d5fbb9b379a..b7bf0dd4fa44 100644 --- a/include/asm-arm/arch-pxa/entry-macro.S +++ b/include/asm-arm/arch-pxa/entry-macro.S @@ -34,6 +34,6 @@ rsb \irqstat, \irqnr, #0 and \irqstat, \irqstat, \irqnr clz \irqnr, \irqstat - rsb \irqnr, \irqnr, #(31 - PXA_IRQ_SKIP) + rsb \irqnr, \irqnr, #31 1001: .endm diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h index 67ed43674c63..dc4e7548b7d5 100644 --- a/include/asm-arm/arch-pxa/irqs.h +++ b/include/asm-arm/arch-pxa/irqs.h @@ -11,14 +11,9 @@ */ +#define PXA_IRQ(x) (x) + #ifdef CONFIG_PXA27x -#define PXA_IRQ_SKIP 0 -#else -#define PXA_IRQ_SKIP 7 -#endif - -#define PXA_IRQ(x) ((x) - PXA_IRQ_SKIP) - #define IRQ_SSP3 PXA_IRQ(0) /* SSP3 service request */ #define IRQ_MSL PXA_IRQ(1) /* MSL Interface interrupt */ #define IRQ_USBH2 PXA_IRQ(2) /* USB Host interrupt 1 (OHCI) */ @@ -26,6 +21,8 @@ #define IRQ_KEYPAD PXA_IRQ(4) /* Key pad controller */ #define IRQ_MEMSTK PXA_IRQ(5) /* Memory Stick interrupt */ #define IRQ_PWRI2C PXA_IRQ(6) /* Power I2C interrupt */ +#endif + #define IRQ_HWUART PXA_IRQ(7) /* HWUART Transmit/Receive/Error (PXA26x) */ #define IRQ_OST_4_11 PXA_IRQ(7) /* OS timer 4-11 matches (PXA27x) */ #define IRQ_GPIO0 PXA_IRQ(8) /* GPIO0 Edge Detect */ From c08b7b3ef6bf489ddabadc03e050f3db2ea44b5d Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 6 Jun 2007 06:32:38 +0100 Subject: [PATCH 31/45] [ARM] 4435/1: PXA: remove PXA_INTERNAL_IRQS 1. define PXA_GPIO_IRQ_BASE to be right after the internal IRQs, and define PXA_GPIO_IRQ_NUM to be 128 for all PXA2xx variants 2. make the code specific to the high IRQ numbers (32..64) to be PXA27x specific 3. add a function pxa_init_irq_high() to initialize the internal high IRQ chip, the invoke of this function could be moved to PXA27x specific initialization code Signed-off-by: eric miao Signed-off-by: Russell King --- arch/arm/mach-pxa/irq.c | 26 ++++++++++++++++---------- include/asm-arm/arch-pxa/irqs.h | 15 ++++++--------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 45ce711f0472..844d3de3ef44 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -67,7 +67,7 @@ static struct irq_chip pxa_internal_chip_low = { .set_wake = pxa_set_wake, }; -#if PXA_INTERNAL_IRQS > 32 +#ifdef CONFIG_PXA27x /* * This is for the second set of internal IRQs as found on the PXA27x. @@ -90,6 +90,19 @@ static struct irq_chip pxa_internal_chip_high = { .unmask = pxa_unmask_high_irq, }; +void __init pxa_init_irq_high(void) +{ + int irq; + + ICMR2 = 0; + ICLR2 = 0; + + for (irq = PXA_IRQ(32); irq < PXA_IRQ(64); irq++) { + set_irq_chip(irq, &pxa_internal_chip_high); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } +} #endif /* Note that if an input/irq line ever gets changed to an output during @@ -314,7 +327,6 @@ static struct irq_chip pxa_muxed_gpio_chip = { .set_wake = pxa_set_gpio_wake, }; - void __init pxa_init_irq(void) { int irq; @@ -338,8 +350,6 @@ void __init pxa_init_irq(void) #ifdef CONFIG_PXA27x /* And similarly for the extra regs on the PXA27x */ - ICMR2 = 0; - ICLR2 = 0; GFER3 = 0; GRER3 = 0; GEDR3 = GEDR3; @@ -357,12 +367,8 @@ void __init pxa_init_irq(void) set_irq_flags(irq, IRQF_VALID); } -#if PXA_INTERNAL_IRQS > 32 - for (irq = PXA_IRQ(32); irq < PXA_IRQ(PXA_INTERNAL_IRQS); irq++) { - set_irq_chip(irq, &pxa_internal_chip_high); - set_irq_handler(irq, handle_level_irq); - set_irq_flags(irq, IRQF_VALID); - } +#ifdef CONFIG_PXA27x + pxa_init_irq_high(); #endif for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { diff --git a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h index dc4e7548b7d5..a07fe0f928cd 100644 --- a/include/asm-arm/arch-pxa/irqs.h +++ b/include/asm-arm/arch-pxa/irqs.h @@ -55,18 +55,15 @@ #ifdef CONFIG_PXA27x #define IRQ_TPM PXA_IRQ(32) /* TPM interrupt */ #define IRQ_CAMERA PXA_IRQ(33) /* Camera Interface */ - -#define PXA_INTERNAL_IRQS 34 -#else -#define PXA_INTERNAL_IRQS 32 #endif -#define GPIO_2_x_TO_IRQ(x) \ - PXA_IRQ((x) - 2 + PXA_INTERNAL_IRQS) +#define PXA_GPIO_IRQ_BASE (64) +#define PXA_GPIO_IRQ_NUM (128) + +#define GPIO_2_x_TO_IRQ(x) (PXA_GPIO_IRQ_BASE + (x)) #define IRQ_GPIO(x) (((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_x_TO_IRQ(x)) -#define IRQ_TO_GPIO_2_x(i) \ - ((i) - IRQ_GPIO(2) + 2) +#define IRQ_TO_GPIO_2_x(i) ((i) - PXA_GPIO_IRQ_BASE) #define IRQ_TO_GPIO(i) (((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i)) #if defined(CONFIG_PXA25x) @@ -81,7 +78,7 @@ * these. If you need more, increase IRQ_BOARD_END, but keep it * within sensible limits. */ -#define IRQ_BOARD_START (IRQ_GPIO(PXA_LAST_GPIO) + 1) +#define IRQ_BOARD_START (PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM) #define IRQ_BOARD_END (IRQ_BOARD_START + 16) #define IRQ_SA1111_START (IRQ_BOARD_END) From 53665a50fdac6fe11e0dde4e2b95700ed5184dc4 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 6 Jun 2007 06:36:04 +0100 Subject: [PATCH 32/45] [ARM] 4436/1: PXA: move low IRQ initialization code to pxa_init_irq_low() 1. move low IRQ initialization code to pxa_init_irq_low() Signed-off-by: eric miao Signed-off-by: Russell King --- arch/arm/mach-pxa/irq.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 844d3de3ef44..42b2da2f213e 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -67,6 +67,26 @@ static struct irq_chip pxa_internal_chip_low = { .set_wake = pxa_set_wake, }; +void __init pxa_init_irq_low(void) +{ + int irq; + + /* disable all IRQs */ + ICMR = 0; + + /* all IRQs are IRQ, not FIQ */ + ICLR = 0; + + /* only unmasked interrupts kick us out of idle */ + ICCR = 1; + + for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) { + set_irq_chip(irq, &pxa_internal_chip_low); + set_irq_handler(irq, handle_level_irq); + set_irq_flags(irq, IRQF_VALID); + } +} + #ifdef CONFIG_PXA27x /* @@ -331,12 +351,6 @@ void __init pxa_init_irq(void) { int irq; - /* disable all IRQs */ - ICMR = 0; - - /* all IRQs are IRQ, not FIQ */ - ICLR = 0; - /* clear all GPIO edge detects */ GFER0 = 0; GFER1 = 0; @@ -355,18 +369,10 @@ void __init pxa_init_irq(void) GEDR3 = GEDR3; #endif - /* only unmasked interrupts kick us out of idle */ - ICCR = 1; - /* GPIO 0 and 1 must have their mask bit always set */ GPIO_IRQ_mask[0] = 3; - for (irq = PXA_IRQ(0); irq <= PXA_IRQ(31); irq++) { - set_irq_chip(irq, &pxa_internal_chip_low); - set_irq_handler(irq, handle_level_irq); - set_irq_flags(irq, IRQF_VALID); - } - + pxa_init_irq_low(); #ifdef CONFIG_PXA27x pxa_init_irq_high(); #endif From 348f2e3b2956e30f07d2507d7234c3f12a8a612d Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 6 Jun 2007 06:37:15 +0100 Subject: [PATCH 33/45] [ARM] 4437/1: PXA: move the GPIO IRQ initialization code to pxa_init_irq_gpio() move the GPIO IRQ initialization code to pxa_init_irq_gpio() Signed-off-by: eric miao Signed-off-by: Russell King --- arch/arm/mach-pxa/irq.c | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 42b2da2f213e..256f8d2b3d9b 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -347,43 +347,27 @@ static struct irq_chip pxa_muxed_gpio_chip = { .set_wake = pxa_set_gpio_wake, }; -void __init pxa_init_irq(void) +void __init pxa_init_irq_gpio(int gpio_nr) { - int irq; + int irq, i; /* clear all GPIO edge detects */ - GFER0 = 0; - GFER1 = 0; - GFER2 = 0; - GRER0 = 0; - GRER1 = 0; - GRER2 = 0; - GEDR0 = GEDR0; - GEDR1 = GEDR1; - GEDR2 = GEDR2; - -#ifdef CONFIG_PXA27x - /* And similarly for the extra regs on the PXA27x */ - GFER3 = 0; - GRER3 = 0; - GEDR3 = GEDR3; -#endif + for (i = 0; i < gpio_nr; i += 32) { + GFER(i) = 0; + GRER(i) = 0; + GEDR(i) = GEDR(i); + } /* GPIO 0 and 1 must have their mask bit always set */ GPIO_IRQ_mask[0] = 3; - pxa_init_irq_low(); -#ifdef CONFIG_PXA27x - pxa_init_irq_high(); -#endif - for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) { set_irq_chip(irq, &pxa_low_gpio_chip); set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); } - for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(PXA_LAST_GPIO); irq++) { + for (irq = IRQ_GPIO(2); irq <= IRQ_GPIO(gpio_nr); irq++) { set_irq_chip(irq, &pxa_muxed_gpio_chip); set_irq_handler(irq, handle_edge_irq); set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); @@ -393,3 +377,12 @@ void __init pxa_init_irq(void) set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low); set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler); } + +void __init pxa_init_irq(void) +{ + pxa_init_irq_low(); +#ifdef CONFIG_PXA27x + pxa_init_irq_high(); +#endif + pxa_init_irq_gpio(PXA_LAST_GPIO + 1); +} From 4a3dcd35c82a2a25b2832502290e1a3f1571e9ef Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 6 Jun 2007 06:45:18 +0100 Subject: [PATCH 34/45] [ARM] 4438/1: PXA: remove #ifdef .. #endif from pxa_gpio_demux_handler() 1. use GPIO_IRQ_mask[] to select those bits of interest, actually only those "unmasked" GPIO IRQs with their corresponding bits in GPIO_IRQ_mask[] set to "1" should be checked 2. remove #ifdef PXA_LAST_GPIO > 96 .. #endif, GPIO_IRQ_mask[] is used to mask out the irrelevant bits, so that even though the GEDR3 on PXA25x is reserved, it will be masked, and the following code will never run. Another point is that GPIO85- GPIO95 bits within GEDR2 will also be masked out on PXA25x Signed-off-by: eric miao Signed-off-by: Russell King --- arch/arm/mach-pxa/irq.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 256f8d2b3d9b..09d2fe19c85f 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -250,7 +250,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) do { loop = 0; - mask = GEDR0 & ~3; + mask = GEDR0 & GPIO_IRQ_mask[0] & ~3; if (mask) { GEDR0 = mask; irq = IRQ_GPIO(2); @@ -266,7 +266,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) loop = 1; } - mask = GEDR1; + mask = GEDR1 & GPIO_IRQ_mask[1]; if (mask) { GEDR1 = mask; irq = IRQ_GPIO(32); @@ -281,7 +281,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) loop = 1; } - mask = GEDR2; + mask = GEDR2 & GPIO_IRQ_mask[2]; if (mask) { GEDR2 = mask; irq = IRQ_GPIO(64); @@ -296,8 +296,7 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) loop = 1; } -#if PXA_LAST_GPIO >= 96 - mask = GEDR3; + mask = GEDR3 & GPIO_IRQ_mask[3]; if (mask) { GEDR3 = mask; irq = IRQ_GPIO(96); @@ -311,7 +310,6 @@ static void pxa_gpio_demux_handler(unsigned int irq, struct irq_desc *desc) } while (mask); loop = 1; } -#endif } while (loop); } From 8118d124949ed8ff1a450e0c0d13cfab8c2ff7aa Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 6 Jun 2007 06:49:59 +0100 Subject: [PATCH 35/45] [ARM] 4440/1: PXA: enable the checking of ICIP2 for IRQs ICIP2 is not examined during IRQ entrance, this patch add the checking if the processor is PXA27x or later, with CoreG bits in CPUID (Core Generation) > 1 Signed-off-by: eric miao Signed-off-by: Russell King --- include/asm-arm/arch-pxa/entry-macro.S | 28 +++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/include/asm-arm/arch-pxa/entry-macro.S b/include/asm-arm/arch-pxa/entry-macro.S index b7bf0dd4fa44..b7e730851461 100644 --- a/include/asm-arm/arch-pxa/entry-macro.S +++ b/include/asm-arm/arch-pxa/entry-macro.S @@ -20,15 +20,33 @@ .endm .macro get_irqnr_and_base, irqnr, irqstat, base, tmp -#ifdef CONFIG_PXA27x - mrc p6, 0, \irqstat, c0, c0, 0 @ ICIP - mrc p6, 0, \irqnr, c1, c0, 0 @ ICMR -#else + mrc p15, 0, \tmp, c0, c0, 0 @ CPUID + mov \tmp, \tmp, lsr #13 + and \tmp, \tmp, #0x7 @ Core G + cmp \tmp, #1 + bhi 1004f + mov \base, #io_p2v(0x40000000) @ IIR Ctl = 0x40d00000 add \base, \base, #0x00d00000 ldr \irqstat, [\base, #0] @ ICIP ldr \irqnr, [\base, #4] @ ICMR -#endif + b 1002f + +1004: + mrc p6, 0, \irqstat, c6, c0, 0 @ ICIP2 + mrc p6, 0, \irqnr, c7, c0, 0 @ ICMR2 + ands \irqstat, \irqstat, \irqnr + beq 1003f + rsb \irqstat, \irqnr, #0 + and \irqstat, \irqstat, \irqnr + clz \irqnr, \irqstat + rsb \irqnr, \irqnr, #31 + add \irqnr, \irqnr, #32 + b 1001f +1003: + mrc p6, 0, \irqstat, c0, c0, 0 @ ICIP + mrc p6, 0, \irqnr, c1, c0, 0 @ ICMR +1002: ands \irqnr, \irqstat, \irqnr beq 1001f rsb \irqstat, \irqnr, #0 From cd49104d99b56383a3b1fdce2f31018197093c31 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 22 Jun 2007 04:14:09 +0100 Subject: [PATCH 36/45] [ARM] 4450/1: pxa: add pxa25x_init_irq() and pxa27x_init_irq() /* should be ok this time, I aligned this patch to your arm:pxa2.mbox */ 1. move pxa25x specific IRQ initialization code to pxa25x_init_irq() and pxa27x code to pxa27x_init_irq(), remove pxa_init_irq() 2. replace all pxa_init_irq() with their PXA25x or PXA27x specific functions Signed-off-by: eric miao Signed-off-by: Russell King --- arch/arm/mach-pxa/corgi.c | 6 +++--- arch/arm/mach-pxa/generic.h | 6 +++++- arch/arm/mach-pxa/idp.c | 2 +- arch/arm/mach-pxa/irq.c | 9 --------- arch/arm/mach-pxa/lpd270.c | 2 +- arch/arm/mach-pxa/lubbock.c | 2 +- arch/arm/mach-pxa/mainstone.c | 2 +- arch/arm/mach-pxa/poodle.c | 2 +- arch/arm/mach-pxa/pxa25x.c | 7 +++++++ arch/arm/mach-pxa/pxa27x.c | 8 ++++++++ arch/arm/mach-pxa/spitz.c | 6 +++--- arch/arm/mach-pxa/tosa.c | 2 +- arch/arm/mach-pxa/trizeps4.c | 2 +- 13 files changed, 33 insertions(+), 23 deletions(-) diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index a1a900d16665..a12eb18391b1 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -368,7 +368,7 @@ MACHINE_START(CORGI, "SHARP Corgi") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, .map_io = pxa_map_io, - .init_irq = pxa_init_irq, + .init_irq = pxa25x_init_irq, .init_machine = corgi_init, .timer = &pxa_timer, MACHINE_END @@ -380,7 +380,7 @@ MACHINE_START(SHEPHERD, "SHARP Shepherd") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, .map_io = pxa_map_io, - .init_irq = pxa_init_irq, + .init_irq = pxa25x_init_irq, .init_machine = corgi_init, .timer = &pxa_timer, MACHINE_END @@ -392,7 +392,7 @@ MACHINE_START(HUSKY, "SHARP Husky") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_corgi, .map_io = pxa_map_io, - .init_irq = pxa_init_irq, + .init_irq = pxa25x_init_irq, .init_machine = corgi_init, .timer = &pxa_timer, MACHINE_END diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index e54a8dd63c17..91ab2ad8b34b 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -12,8 +12,12 @@ struct sys_timer; extern struct sys_timer pxa_timer; +extern void __init pxa_init_irq_low(void); +extern void __init pxa_init_irq_high(void); +extern void __init pxa_init_irq_gpio(int gpio_nr); +extern void __init pxa25x_init_irq(void); +extern void __init pxa27x_init_irq(void); extern void __init pxa_map_io(void); -extern void __init pxa_init_irq(void); extern unsigned int get_clk_frequency_khz(int info); diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c index 64df44043a65..ffa73fae3d8d 100644 --- a/arch/arm/mach-pxa/idp.c +++ b/arch/arm/mach-pxa/idp.c @@ -152,7 +152,7 @@ static void __init idp_init(void) static void __init idp_init_irq(void) { - pxa_init_irq(); + pxa25x_init_irq(); set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE); } diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 09d2fe19c85f..4b867b0789d5 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -375,12 +375,3 @@ void __init pxa_init_irq_gpio(int gpio_nr) set_irq_chip(IRQ_GPIO_2_x, &pxa_internal_chip_low); set_irq_chained_handler(IRQ_GPIO_2_x, pxa_gpio_demux_handler); } - -void __init pxa_init_irq(void) -{ - pxa_init_irq_low(); -#ifdef CONFIG_PXA27x - pxa_init_irq_high(); -#endif - pxa_init_irq_gpio(PXA_LAST_GPIO + 1); -} diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c index e3097664ffe1..7949f60d7d7f 100644 --- a/arch/arm/mach-pxa/lpd270.c +++ b/arch/arm/mach-pxa/lpd270.c @@ -97,7 +97,7 @@ static void __init lpd270_init_irq(void) { int irq; - pxa_init_irq(); + pxa27x_init_irq(); __raw_writew(0, LPD270_INT_MASK); __raw_writew(0, LPD270_INT_STATUS); diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 6377b2e29ff0..45a3c7e635b5 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -103,7 +103,7 @@ static void __init lubbock_init_irq(void) { int irq; - pxa_init_irq(); + pxa25x_init_irq(); /* setup extra lubbock irqs */ for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) { diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index ed99a81b98f3..086b4e2f5bef 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -89,7 +89,7 @@ static void __init mainstone_init_irq(void) { int irq; - pxa_init_irq(); + pxa27x_init_irq(); /* setup extra Mainstone irqs */ for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) { diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 34fb80b37023..53eaccfd6da7 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -412,7 +412,7 @@ MACHINE_START(POODLE, "SHARP Poodle") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_poodle, .map_io = pxa_map_io, - .init_irq = pxa_init_irq, + .init_irq = pxa25x_init_irq, .timer = &pxa_timer, .init_machine = poodle_init, MACHINE_END diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index fe29c6e03a4f..a8796aea8353 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -128,6 +129,12 @@ static struct pm_ops pxa25x_pm_ops = { }; #endif +void __init pxa25x_init_irq(void) +{ + pxa_init_irq_low(); + pxa_init_irq_gpio(85); +} + static int __init pxa25x_init(void) { if (cpu_is_pxa21x() || cpu_is_pxa25x()) { diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index ac40fa5f7709..1407985c8ab0 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -202,6 +203,13 @@ static struct platform_device *devices[] __initdata = { &ohci_device, }; +void __init pxa27x_init_irq(void) +{ + pxa_init_irq_low(); + pxa_init_irq_high(); + pxa_init_irq_gpio(128); +} + static int __init pxa27x_init(void) { int ret = 0; diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 3cbac63bed3c..838b73d159e3 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -560,7 +560,7 @@ MACHINE_START(SPITZ, "SHARP Spitz") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_spitz, .map_io = pxa_map_io, - .init_irq = pxa_init_irq, + .init_irq = pxa27x_init_irq, .init_machine = spitz_init, .timer = &pxa_timer, MACHINE_END @@ -572,7 +572,7 @@ MACHINE_START(BORZOI, "SHARP Borzoi") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_spitz, .map_io = pxa_map_io, - .init_irq = pxa_init_irq, + .init_irq = pxa27x_init_irq, .init_machine = spitz_init, .timer = &pxa_timer, MACHINE_END @@ -584,7 +584,7 @@ MACHINE_START(AKITA, "SHARP Akita") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_spitz, .map_io = pxa_map_io, - .init_irq = pxa_init_irq, + .init_irq = pxa27x_init_irq, .init_machine = akita_init, .timer = &pxa_timer, MACHINE_END diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 72738771fb57..017253466005 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -332,7 +332,7 @@ MACHINE_START(TOSA, "SHARP Tosa") .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, .fixup = fixup_tosa, .map_io = pxa_map_io, - .init_irq = pxa_init_irq, + .init_irq = pxa25x_init_irq, .init_machine = tosa_init, .timer = &pxa_timer, MACHINE_END diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c index 28c79bd0a3a0..47a1f7ee2bbb 100644 --- a/arch/arm/mach-pxa/trizeps4.c +++ b/arch/arm/mach-pxa/trizeps4.c @@ -503,7 +503,7 @@ MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module") .boot_params = TRIZEPS4_SDRAM_BASE + 0x100, .init_machine = trizeps4_init, .map_io = trizeps4_map_io, - .init_irq = pxa_init_irq, + .init_irq = pxa27x_init_irq, .timer = &pxa_timer, MACHINE_END From f53f066c25036210036730d64c876ea586114425 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Fri, 22 Jun 2007 05:40:17 +0100 Subject: [PATCH 37/45] [ARM] 4451/1: pxa: make dma.c generic and remove cpu specific dma code Since the number of dma channels varies between pxa25x and pxa27x, it introduces some specific code in dma.c. This patch moves the specific code to pxa25x.c and pxa27x.c and makes dma.c more generic. 1. add pxa_init_dma() for dma initialization, the number of channels are passed in by the argument 2. add a "prio" field to the "struct pxa_dma_channel" for the channel priority, and is initialized in pxa_init_dma() 3. use a general priority comparison with the channels "prio" field so to remove the processor specific pxa_for_each_dma_prio macro, this is not lightning fast as the original one, but it is acceptable as it happens when requesting dma, which is usually not so performance critical Signed-off-by: eric miao Acked-by: Nicolas Pitre Signed-off-by: Russell King --- arch/arm/mach-pxa/dma.c | 44 ++++++++++++++++++++++++---------- arch/arm/mach-pxa/pxa25x.c | 5 ++++ arch/arm/mach-pxa/pxa27x.c | 3 +++ include/asm-arm/arch-pxa/dma.h | 22 ++--------------- 4 files changed, 41 insertions(+), 33 deletions(-) diff --git a/arch/arm/mach-pxa/dma.c b/arch/arm/mach-pxa/dma.c index 4440babe7b97..93c4f31f127f 100644 --- a/arch/arm/mach-pxa/dma.c +++ b/arch/arm/mach-pxa/dma.c @@ -25,12 +25,15 @@ #include -static struct dma_channel { +struct dma_channel { char *name; + pxa_dma_prio prio; void (*irq_handler)(int, void *); void *data; -} dma_channels[PXA_DMA_CHANNELS]; +}; +static struct dma_channel *dma_channels; +static int num_dma_channels; int pxa_request_dma (char *name, pxa_dma_prio prio, void (*irq_handler)(int, void *), @@ -47,8 +50,9 @@ int pxa_request_dma (char *name, pxa_dma_prio prio, do { /* try grabbing a DMA channel with the requested priority */ - pxa_for_each_dma_prio (i, prio) { - if (!dma_channels[i].name) { + for (i = 0; i < num_dma_channels; i++) { + if ((dma_channels[i].prio == prio) && + !dma_channels[i].name) { found = 1; break; } @@ -91,7 +95,7 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id) { int i, dint = DINT; - for (i = 0; i < PXA_DMA_CHANNELS; i++) { + for (i = 0; i < num_dma_channels; i++) { if (dint & (1 << i)) { struct dma_channel *channel = &dma_channels[i]; if (channel->name && channel->irq_handler) { @@ -109,18 +113,32 @@ static irqreturn_t dma_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } -static int __init pxa_dma_init (void) +int __init pxa_init_dma(int num_ch) { - int ret; + int i, ret; - ret = request_irq (IRQ_DMA, dma_irq_handler, 0, "DMA", NULL); - if (ret) + dma_channels = kzalloc(sizeof(struct dma_channel) * num_ch, GFP_KERNEL); + if (dma_channels == NULL) + return -ENOMEM; + + ret = request_irq(IRQ_DMA, dma_irq_handler, IRQF_DISABLED, "DMA", NULL); + if (ret) { printk (KERN_CRIT "Wow! Can't register IRQ for DMA\n"); - return ret; -} + kfree(dma_channels); + return ret; + } -arch_initcall(pxa_dma_init); + /* dma channel priorities on pxa2xx processors: + * ch 0 - 3, 16 - 19 <--> (0) DMA_PRIO_HIGH + * ch 4 - 7, 20 - 23 <--> (1) DMA_PRIO_MEDIUM + * ch 8 - 15, 24 - 31 <--> (2) DMA_PRIO_LOW + */ + for (i = 0; i < num_ch; i++) + dma_channels[i].prio = min((i & 0xf) >> 2, DMA_PRIO_LOW); + + num_dma_channels = num_ch; + return 0; +} EXPORT_SYMBOL(pxa_request_dma); EXPORT_SYMBOL(pxa_free_dma); - diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index a8796aea8353..13437582342d 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "generic.h" @@ -137,7 +138,11 @@ void __init pxa25x_init_irq(void) static int __init pxa25x_init(void) { + int ret = 0; + if (cpu_is_pxa21x() || cpu_is_pxa25x()) { + if ((ret = pxa_init_dma(16))) + return ret; #ifdef CONFIG_PM pm_set_ops(&pxa25x_pm_ops); #endif diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 1407985c8ab0..5b819e2c5563 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "generic.h" @@ -214,6 +215,8 @@ static int __init pxa27x_init(void) { int ret = 0; if (cpu_is_pxa27x()) { + if ((ret = pxa_init_dma(32))) + return ret; #ifdef CONFIG_PM pm_set_ops(&pxa27x_pm_ops); #endif diff --git a/include/asm-arm/arch-pxa/dma.h b/include/asm-arm/arch-pxa/dma.h index bed042d71d68..3280ee2ddfa5 100644 --- a/include/asm-arm/arch-pxa/dma.h +++ b/include/asm-arm/arch-pxa/dma.h @@ -30,30 +30,12 @@ typedef enum { DMA_PRIO_LOW = 2 } pxa_dma_prio; -#if defined(CONFIG_PXA27x) - -#define PXA_DMA_CHANNELS 32 - -#define pxa_for_each_dma_prio(ch, prio) \ -for ( \ - ch = prio * 4; \ - ch != (4 << prio) + 16; \ - ch = (ch + 1 == (4 << prio)) ? (prio * 4 + 16) : (ch + 1) \ -) - -#elif defined(CONFIG_PXA25x) - -#define PXA_DMA_CHANNELS 16 - -#define pxa_for_each_dma_prio(ch, prio) \ - for (ch = prio * 4; ch != (4 << prio); ch++) - -#endif - /* * DMA registration */ +int __init pxa_init_dma(int num_ch); + int pxa_request_dma (char *name, pxa_dma_prio prio, void (*irq_handler)(int, void *), From 2aca0a865722fce435034cee5a33e1726fe10a9f Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 27 Jun 2007 09:56:05 +0100 Subject: [PATCH 38/45] [ARM] pxa: stop doing our own rtc management over suspend Remove the RTC management over a suspend/resume cycle. Firstly, we may not be using the internal RTC for time keeping; some platforms have an external RTC for this inspite of the PXA having an internal RTC. Secondly, the RTC library code handles updating system time on resume. Signed-off-by: Russell King --- arch/arm/mach-pxa/pm.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index d439ffa1b071..e66dbc26add1 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -77,7 +77,6 @@ int pxa_pm_enter(suspend_state_t state) { unsigned long sleep_save[SLEEP_SAVE_SIZE]; unsigned long checksum = 0; - struct timespec delta, rtc; int i; extern void pxa_cpu_pm_enter(suspend_state_t state); @@ -87,11 +86,6 @@ int pxa_pm_enter(suspend_state_t state) iwmmxt_task_disable(NULL); #endif - /* preserve current time */ - rtc.tv_sec = RCNR; - rtc.tv_nsec = 0; - save_time_delta(&delta, &rtc); - SAVE(GPLR0); SAVE(GPLR1); SAVE(GPLR2); SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2); SAVE(GRER0); SAVE(GRER1); SAVE(GRER2); @@ -183,10 +177,6 @@ int pxa_pm_enter(suspend_state_t state) RESTORE(PSTR); - /* restore current time */ - rtc.tv_sec = RCNR; - restore_time_delta(&delta, &rtc); - #ifdef DEBUG printk(KERN_DEBUG "*** made it back from resume\n"); #endif From 4adb70fc1b9b545ce6221f0cc35a8fa0eab13461 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 27 Jun 2007 09:57:32 +0100 Subject: [PATCH 39/45] [ARM] pxa: remove boot time RTC initialisation The RTC library code contains everything necessary to set the system time from the RTC; for similar reasons as the previous commit, it's far better to let the RTC library code sort this out rather than implement something which might not be appropriate for everyone. Signed-off-by: Russell King --- arch/arm/mach-pxa/time.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c index 5248abe334d2..6f91fd2d061a 100644 --- a/arch/arm/mach-pxa/time.c +++ b/arch/arm/mach-pxa/time.c @@ -30,11 +30,6 @@ #include -static inline unsigned long pxa_get_rtc_time(void) -{ - return RCNR; -} - static int pxa_set_rtc(void) { unsigned long current_time = xtime.tv_sec; @@ -122,10 +117,6 @@ static void __init pxa_timer_init(void) set_rtc = pxa_set_rtc; - tv.tv_nsec = 0; - tv.tv_sec = pxa_get_rtc_time(); - do_settimeofday(&tv); - OIER = 0; /* disable any timer interrupts */ OSSR = 0xf; /* clear status on all timers */ setup_irq(IRQ_OST0, &pxa_timer_irq); From 34f3231f435dfb8e6c83271c63461fdd2901dc97 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 15 May 2007 10:39:49 +0100 Subject: [PATCH 40/45] [ARM] pxa: move device registration into CPU-specific file This allows individual CPU support to determine which platform devices should be registered. Also fix a copy-n-paste bug in the I2C power platform device entry. Signed-off-by: Russell King --- arch/arm/mach-pxa/generic.c | 90 ++++++++----------------------------- arch/arm/mach-pxa/generic.h | 11 +++++ arch/arm/mach-pxa/pxa25x.c | 22 ++++++++- arch/arm/mach-pxa/pxa27x.c | 36 +++++++++++++-- 4 files changed, 83 insertions(+), 76 deletions(-) diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index 147b7c40d9f9..a496e498ef57 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -242,7 +242,7 @@ static struct resource pxamci_resources[] = { static u64 pxamci_dmamask = 0xffffffffUL; -static struct platform_device pxamci_device = { +struct platform_device pxamci_device = { .name = "pxa2xx-mci", .id = -1, .dev = { @@ -281,7 +281,7 @@ static struct resource pxa2xx_udc_resources[] = { static u64 udc_dma_mask = ~(u32)0; -static struct platform_device udc_device = { +struct platform_device pxaudc_device = { .name = "pxa2xx-udc", .id = -1, .resource = pxa2xx_udc_resources, @@ -307,7 +307,7 @@ static struct resource pxafb_resources[] = { static u64 fb_dma_mask = ~(u64)0; -static struct platform_device pxafb_device = { +struct platform_device pxafb_device = { .name = "pxa2xx-fb", .id = -1, .dev = { @@ -328,24 +328,24 @@ void __init set_pxa_fb_parent(struct device *parent_dev) pxafb_device.dev.parent = parent_dev; } -static struct platform_device ffuart_device = { +struct platform_device ffuart_device = { .name = "pxa2xx-uart", .id = 0, }; -static struct platform_device btuart_device = { +struct platform_device btuart_device = { .name = "pxa2xx-uart", .id = 1, }; -static struct platform_device stuart_device = { +struct platform_device stuart_device = { .name = "pxa2xx-uart", .id = 2, }; -static struct platform_device hwuart_device = { +struct platform_device hwuart_device = { .name = "pxa2xx-uart", .id = 3, }; -static struct resource i2c_resources[] = { +static struct resource pxai2c_resources[] = { { .start = 0x40301680, .end = 0x403016a3, @@ -357,40 +357,19 @@ static struct resource i2c_resources[] = { }, }; -static struct platform_device i2c_device = { +struct platform_device pxai2c_device = { .name = "pxa2xx-i2c", .id = 0, - .resource = i2c_resources, - .num_resources = ARRAY_SIZE(i2c_resources), + .resource = pxai2c_resources, + .num_resources = ARRAY_SIZE(pxai2c_resources), }; -#ifdef CONFIG_PXA27x -static struct resource i2c_power_resources[] = { - { - .start = 0x40f00180, - .end = 0x40f001a3, - .flags = IORESOURCE_MEM, - }, { - .start = IRQ_PWRI2C, - .end = IRQ_PWRI2C, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device i2c_power_device = { - .name = "pxa2xx-i2c", - .id = 1, - .resource = i2c_power_resources, - .num_resources = ARRAY_SIZE(i2c_resources), -}; -#endif - void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info) { - i2c_device.dev.platform_data = info; + pxai2c_device.dev.platform_data = info; } -static struct resource i2s_resources[] = { +static struct resource pxai2s_resources[] = { { .start = 0x40400000, .end = 0x40400083, @@ -402,16 +381,16 @@ static struct resource i2s_resources[] = { }, }; -static struct platform_device i2s_device = { +struct platform_device pxai2s_device = { .name = "pxa2xx-i2s", .id = -1, - .resource = i2s_resources, - .num_resources = ARRAY_SIZE(i2s_resources), + .resource = pxai2s_resources, + .num_resources = ARRAY_SIZE(pxai2s_resources), }; static u64 pxaficp_dmamask = ~(u32)0; -static struct platform_device pxaficp_device = { +struct platform_device pxaficp_device = { .name = "pxa2xx-ir", .id = -1, .dev = { @@ -425,40 +404,7 @@ void __init pxa_set_ficp_info(struct pxaficp_platform_data *info) pxaficp_device.dev.platform_data = info; } -static struct platform_device pxartc_device = { +struct platform_device pxartc_device = { .name = "sa1100-rtc", .id = -1, }; - -static struct platform_device *devices[] __initdata = { - &pxamci_device, - &udc_device, - &pxafb_device, - &ffuart_device, - &btuart_device, - &stuart_device, - &pxaficp_device, - &i2c_device, -#ifdef CONFIG_PXA27x - &i2c_power_device, -#endif - &i2s_device, - &pxartc_device, -}; - -static int __init pxa_init(void) -{ - int ret; - - ret = platform_add_devices(devices, ARRAY_SIZE(devices)); - if (ret) - return ret; - - /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */ - if (cpu_is_pxa25x()) - ret = platform_device_register(&hwuart_device); - - return ret; -} - -subsys_initcall(pxa_init); diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index 91ab2ad8b34b..b9b96ec4b9bc 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -26,3 +26,14 @@ extern unsigned int get_clk_frequency_khz(int info); mi->bank[__nr].size = (__size), \ mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27) +extern struct platform_device pxamci_device; +extern struct platform_device pxaudc_device; +extern struct platform_device pxafb_device; +extern struct platform_device ffuart_device; +extern struct platform_device btuart_device; +extern struct platform_device stuart_device; +extern struct platform_device hwuart_device; +extern struct platform_device pxai2c_device; +extern struct platform_device pxai2s_device; +extern struct platform_device pxaficp_device; +extern struct platform_device pxartc_device; diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 13437582342d..72b949bdf658 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -136,6 +137,19 @@ void __init pxa25x_init_irq(void) pxa_init_irq_gpio(85); } +static struct platform_device *pxa25x_devices[] __initdata = { + &pxamci_device, + &pxaudc_device, + &pxafb_device, + &ffuart_device, + &btuart_device, + &stuart_device, + &pxai2c_device, + &pxai2s_device, + &pxaficp_device, + &pxartc_device, +}; + static int __init pxa25x_init(void) { int ret = 0; @@ -146,8 +160,14 @@ static int __init pxa25x_init(void) #ifdef CONFIG_PM pm_set_ops(&pxa25x_pm_ops); #endif + ret = platform_add_devices(pxa25x_devices, + ARRAY_SIZE(pxa25x_devices)); } - return 0; + /* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */ + if (cpu_is_pxa25x()) + ret = platform_device_register(&hwuart_device); + + return ret; } subsys_initcall(pxa25x_init); diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 5b819e2c5563..27fd2fa56eaf 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -184,7 +184,7 @@ static struct resource pxa27x_ohci_resources[] = { }, }; -static struct platform_device ohci_device = { +static struct platform_device pxaohci_device = { .name = "pxa27x-ohci", .id = -1, .dev = { @@ -197,11 +197,41 @@ static struct platform_device ohci_device = { void __init pxa_set_ohci_info(struct pxaohci_platform_data *info) { - ohci_device.dev.platform_data = info; + pxaohci_device.dev.platform_data = info; } +static struct resource i2c_power_resources[] = { + { + .start = 0x40f00180, + .end = 0x40f001a3, + .flags = IORESOURCE_MEM, + }, { + .start = IRQ_PWRI2C, + .end = IRQ_PWRI2C, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device pxai2c_power_device = { + .name = "pxa2xx-i2c", + .id = 1, + .resource = i2c_power_resources, + .num_resources = ARRAY_SIZE(i2c_power_resources), +}; + static struct platform_device *devices[] __initdata = { - &ohci_device, + &pxamci_device, + &pxaudc_device, + &pxafb_device, + &ffuart_device, + &btuart_device, + &stuart_device, + &pxai2c_device, + &pxai2c_power_device, + &pxai2s_device, + &pxaficp_device, + &pxartc_device, + &pxaohci_device, }; void __init pxa27x_init_irq(void) From 46c41e62a1feb4ab2e941f33f06bbf8feab2d2cf Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 15 May 2007 15:39:36 +0100 Subject: [PATCH 41/45] [ARM] pxa: move platform devices to separate header file Signed-off-by: Russell King --- arch/arm/mach-pxa/corgi.c | 1 + arch/arm/mach-pxa/devices.h | 11 +++++++++++ arch/arm/mach-pxa/generic.c | 1 + arch/arm/mach-pxa/generic.h | 11 ----------- arch/arm/mach-pxa/idp.c | 1 + arch/arm/mach-pxa/lpd270.c | 1 + arch/arm/mach-pxa/lubbock.c | 1 + arch/arm/mach-pxa/mainstone.c | 1 + arch/arm/mach-pxa/poodle.c | 1 + arch/arm/mach-pxa/pxa25x.c | 1 + arch/arm/mach-pxa/pxa27x.c | 1 + arch/arm/mach-pxa/spitz.c | 1 + arch/arm/mach-pxa/tosa.c | 2 +- arch/arm/mach-pxa/trizeps4.c | 1 + 14 files changed, 23 insertions(+), 12 deletions(-) create mode 100644 arch/arm/mach-pxa/devices.h diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index a12eb18391b1..aab27297b3c6 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -44,6 +44,7 @@ #include #include "generic.h" +#include "devices.h" #include "sharpsl.h" diff --git a/arch/arm/mach-pxa/devices.h b/arch/arm/mach-pxa/devices.h new file mode 100644 index 000000000000..9a6faff8e5a7 --- /dev/null +++ b/arch/arm/mach-pxa/devices.h @@ -0,0 +1,11 @@ +extern struct platform_device pxamci_device; +extern struct platform_device pxaudc_device; +extern struct platform_device pxafb_device; +extern struct platform_device ffuart_device; +extern struct platform_device btuart_device; +extern struct platform_device stuart_device; +extern struct platform_device hwuart_device; +extern struct platform_device pxai2c_device; +extern struct platform_device pxai2s_device; +extern struct platform_device pxaficp_device; +extern struct platform_device pxartc_device; diff --git a/arch/arm/mach-pxa/generic.c b/arch/arm/mach-pxa/generic.c index a496e498ef57..296539b6359c 100644 --- a/arch/arm/mach-pxa/generic.c +++ b/arch/arm/mach-pxa/generic.c @@ -43,6 +43,7 @@ #include #include +#include "devices.h" #include "generic.h" /* diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h index b9b96ec4b9bc..91ab2ad8b34b 100644 --- a/arch/arm/mach-pxa/generic.h +++ b/arch/arm/mach-pxa/generic.h @@ -26,14 +26,3 @@ extern unsigned int get_clk_frequency_khz(int info); mi->bank[__nr].size = (__size), \ mi->bank[__nr].node = (((unsigned)(__start) - PHYS_OFFSET) >> 27) -extern struct platform_device pxamci_device; -extern struct platform_device pxaudc_device; -extern struct platform_device pxafb_device; -extern struct platform_device ffuart_device; -extern struct platform_device btuart_device; -extern struct platform_device stuart_device; -extern struct platform_device hwuart_device; -extern struct platform_device pxai2c_device; -extern struct platform_device pxai2s_device; -extern struct platform_device pxaficp_device; -extern struct platform_device pxartc_device; diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c index ffa73fae3d8d..465108da2851 100644 --- a/arch/arm/mach-pxa/idp.c +++ b/arch/arm/mach-pxa/idp.c @@ -38,6 +38,7 @@ #include #include "generic.h" +#include "devices.h" /* TODO: * - add pxa2xx_audio_ops_t device structure diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c index 7949f60d7d7f..26116440a7c9 100644 --- a/arch/arm/mach-pxa/lpd270.c +++ b/arch/arm/mach-pxa/lpd270.c @@ -46,6 +46,7 @@ #include #include "generic.h" +#include "devices.h" static unsigned int lpd270_irq_enabled; diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c index 45a3c7e635b5..e70048fd00a5 100644 --- a/arch/arm/mach-pxa/lubbock.c +++ b/arch/arm/mach-pxa/lubbock.c @@ -48,6 +48,7 @@ #include #include "generic.h" +#include "devices.h" #define LUB_MISC_WR __LUB_REG(LUBBOCK_FPGA_PHYS + 0x080) diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index 086b4e2f5bef..b02c79c7e6a3 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -46,6 +46,7 @@ #include #include "generic.h" +#include "devices.h" static unsigned long mainstone_irq_enabled; diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 53eaccfd6da7..655668d4d0e9 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -45,6 +45,7 @@ #include #include "generic.h" +#include "devices.h" #include "sharpsl.h" static struct resource poodle_scoop_resources[] = { diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c index 72b949bdf658..f36ca448338e 100644 --- a/arch/arm/mach-pxa/pxa25x.c +++ b/arch/arm/mach-pxa/pxa25x.c @@ -29,6 +29,7 @@ #include #include "generic.h" +#include "devices.h" /* * Various clock factors driven by the CCCR register. diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 27fd2fa56eaf..aa5bb02c897b 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -26,6 +26,7 @@ #include #include "generic.h" +#include "devices.h" /* Crystal clock: 13MHz */ #define BASE_CLK 13000000 diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 838b73d159e3..bae47e145de8 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -48,6 +48,7 @@ #include #include "generic.h" +#include "devices.h" #include "sharpsl.h" /* diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 017253466005..240fd042083d 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -42,7 +42,7 @@ #include #include "generic.h" - +#include "devices.h" /* * SCOOP Device diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c index 47a1f7ee2bbb..e4ba43bdf85d 100644 --- a/arch/arm/mach-pxa/trizeps4.c +++ b/arch/arm/mach-pxa/trizeps4.c @@ -49,6 +49,7 @@ #include #include "generic.h" +#include "devices.h" /******************************************************************************************** * ONBOARD FLASH From f884b1cf578e079f01682514ae1ae64c74586602 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Thu, 12 Jul 2007 16:10:22 +0100 Subject: [PATCH 42/45] [ARM] 4473/2: Take the HWCAP definitions out of the elf.h file The patch moves the HWCAP definitions and the extern elf_hwcap declaration to the hwcap.h header file. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- include/asm-arm/Kbuild | 2 ++ include/asm-arm/elf.h | 23 +---------------------- include/asm-arm/hwcap.h | 28 ++++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 22 deletions(-) create mode 100644 include/asm-arm/hwcap.h diff --git a/include/asm-arm/Kbuild b/include/asm-arm/Kbuild index c68e1680da01..73237bd130a2 100644 --- a/include/asm-arm/Kbuild +++ b/include/asm-arm/Kbuild @@ -1 +1,3 @@ include include/asm-generic/Kbuild.asm + +unifdef-y += hwcap.h diff --git a/include/asm-arm/elf.h b/include/asm-arm/elf.h index 3679a8a8922e..d7a777f05088 100644 --- a/include/asm-arm/elf.h +++ b/include/asm-arm/elf.h @@ -7,6 +7,7 @@ */ #include #include +#include typedef unsigned long elf_greg_t; typedef unsigned long elf_freg_t[3]; @@ -39,30 +40,8 @@ typedef struct user_fp elf_fpregset_t; #endif #define ELF_ARCH EM_ARM -/* - * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP - */ -#define HWCAP_SWP 1 -#define HWCAP_HALF 2 -#define HWCAP_THUMB 4 -#define HWCAP_26BIT 8 /* Play it safe */ -#define HWCAP_FAST_MULT 16 -#define HWCAP_FPA 32 -#define HWCAP_VFP 64 -#define HWCAP_EDSP 128 -#define HWCAP_JAVA 256 -#define HWCAP_IWMMXT 512 -#define HWCAP_CRUNCH 1024 - #ifdef __KERNEL__ #ifndef __ASSEMBLY__ -/* - * This yields a mask that user programs can use to figure out what - * instruction set this cpu supports. - */ -#define ELF_HWCAP (elf_hwcap) -extern unsigned int elf_hwcap; - /* * This yields a string that ld.so will use to load implementation * specific libraries for optimization. This is more specific in diff --git a/include/asm-arm/hwcap.h b/include/asm-arm/hwcap.h new file mode 100644 index 000000000000..01a1391d3014 --- /dev/null +++ b/include/asm-arm/hwcap.h @@ -0,0 +1,28 @@ +#ifndef __ASMARM_HWCAP_H +#define __ASMARM_HWCAP_H + +/* + * HWCAP flags - for elf_hwcap (in kernel) and AT_HWCAP + */ +#define HWCAP_SWP 1 +#define HWCAP_HALF 2 +#define HWCAP_THUMB 4 +#define HWCAP_26BIT 8 /* Play it safe */ +#define HWCAP_FAST_MULT 16 +#define HWCAP_FPA 32 +#define HWCAP_VFP 64 +#define HWCAP_EDSP 128 +#define HWCAP_JAVA 256 +#define HWCAP_IWMMXT 512 +#define HWCAP_CRUNCH 1024 + +#if defined(__KERNEL__) && !defined(__ASSEMBLY__) +/* + * This yields a mask that user programs can use to figure out what + * instruction set this cpu supports. + */ +#define ELF_HWCAP (elf_hwcap) +extern unsigned int elf_hwcap; +#endif + +#endif From d1cbbd6b413510c6512f4f80ffd48db1a8dd554a Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Wed, 11 Jul 2007 11:29:39 +0100 Subject: [PATCH 43/45] [ARM] 4474/1: Do not check the PSR_F_BIT in valid_user_regs When running Linux in non-secure mode (on ARM1176 for example), depending on the CP15 secure configuration register, the CPSR.F bit (6) might only be modified from the secure mode. However, the valid_user_regs() function checks for this bit being cleared. With commit a6c61e9d, a SIGSEGV is forced in handle_signal() if the user registers are not considered valid. The patch also ensures that the CPSR.A bit is cleared and the USR mode is set if the CPU does not support the 26bit user mode. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- include/asm-arm/ptrace.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/include/asm-arm/ptrace.h b/include/asm-arm/ptrace.h index ff038b65f370..7aaa206cb54e 100644 --- a/include/asm-arm/ptrace.h +++ b/include/asm-arm/ptrace.h @@ -10,6 +10,8 @@ #ifndef __ASM_ARM_PTRACE_H #define __ASM_ARM_PTRACE_H +#include + #define PTRACE_GETREGS 12 #define PTRACE_SETREGS 13 #define PTRACE_GETFPREGS 14 @@ -45,6 +47,7 @@ #define PSR_T_BIT 0x00000020 #define PSR_F_BIT 0x00000040 #define PSR_I_BIT 0x00000080 +#define PSR_A_BIT 0x00000100 #define PSR_J_BIT 0x01000000 #define PSR_Q_BIT 0x08000000 #define PSR_V_BIT 0x10000000 @@ -121,14 +124,17 @@ struct pt_regs { */ static inline int valid_user_regs(struct pt_regs *regs) { - if (user_mode(regs) && - (regs->ARM_cpsr & (PSR_F_BIT|PSR_I_BIT)) == 0) + if (user_mode(regs) && (regs->ARM_cpsr & PSR_I_BIT) == 0) { + regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT); return 1; + } /* * Force CPSR to something logical... */ - regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | PSR_T_BIT | MODE32_BIT; + regs->ARM_cpsr &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | PSR_T_BIT | MODE32_BIT; + if (!(elf_hwcap & HWCAP_26BIT)) + regs->ARM_cpsr |= USR_MODE; return 0; } From f3ebbc20ab835ff98cf920f85de989064e352ee5 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 12 Jul 2007 21:29:06 +0100 Subject: [PATCH 44/45] [ARM] sa1100: stop doing our own rtc management over suspend Remove the RTC management over a suspend/resume cycle. As per the corresponding PXA patch, the RTC library code handles updating system time on resume. Signed-off-by: Russell King --- arch/arm/mach-sa1100/pm.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/arch/arm/mach-sa1100/pm.c b/arch/arm/mach-sa1100/pm.c index d674cf343156..01a37d3c0727 100644 --- a/arch/arm/mach-sa1100/pm.c +++ b/arch/arm/mach-sa1100/pm.c @@ -57,12 +57,7 @@ enum { SLEEP_SAVE_SP = 0, static int sa11x0_pm_enter(suspend_state_t state) { unsigned long gpio, sleep_save[SLEEP_SAVE_SIZE]; - struct timespec delta, rtc; - /* preserve current time */ - rtc.tv_sec = RCNR; - rtc.tv_nsec = 0; - save_time_delta(&delta, &rtc); gpio = GPLR; /* save vital registers */ @@ -119,10 +114,6 @@ static int sa11x0_pm_enter(suspend_state_t state) */ PSSR = PSSR_PH; - /* restore current time */ - rtc.tv_sec = RCNR; - restore_time_delta(&delta, &rtc); - return 0; } From fcae8e098877b798c365fd9d807f86d5e2a2b324 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 12 Jul 2007 21:29:45 +0100 Subject: [PATCH 45/45] [ARM] sa1100: remove boot time RTC initialisation The RTC library code contains everything necessary to set the system time from the RTC; for similar reasons as the previous commit, it's far better to let the RTC library code sort this out rather than implement something which might not be appropriate for everyone. Signed-off-by: Russell King --- arch/arm/mach-sa1100/time.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c index 29cb0c1604ab..fdf7b016e7ad 100644 --- a/arch/arm/mach-sa1100/time.c +++ b/arch/arm/mach-sa1100/time.c @@ -21,25 +21,6 @@ #define RTC_DEF_DIVIDER (32768 - 1) #define RTC_DEF_TRIM 0 -static unsigned long __init sa1100_get_rtc_time(void) -{ - /* - * According to the manual we should be able to let RTTR be zero - * and then a default divisor for a 32.768KHz clock is used. - * Apparently this doesn't work, at least for my SA1110 rev 5. - * If the clock divider is uninitialized then reset it to the - * default value to get the 1Hz clock. - */ - if (RTTR == 0) { - RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16); - printk(KERN_WARNING "Warning: uninitialized Real Time Clock\n"); - /* The current RTC value probably doesn't make sense either */ - RCNR = 0; - return 0; - } - return RCNR; -} - static int sa1100_set_rtc(void) { unsigned long current_time = xtime.tv_sec; @@ -117,15 +98,10 @@ static struct irqaction sa1100_timer_irq = { static void __init sa1100_timer_init(void) { - struct timespec tv; unsigned long flags; set_rtc = sa1100_set_rtc; - tv.tv_nsec = 0; - tv.tv_sec = sa1100_get_rtc_time(); - do_settimeofday(&tv); - OIER = 0; /* disable any timer interrupts */ OSSR = 0xf; /* clear status on all timers */ setup_irq(IRQ_OST0, &sa1100_timer_irq);