From d0179efc5dcc1a158ea6a6a5f12365f880a3eada Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Mon, 20 Oct 2008 01:51:03 +0200 Subject: [PATCH] --- yaml --- r: 123933 b: refs/heads/master c: 9569dae75f6f6987e79fa26cf6da3fc24006c996 h: refs/heads/master i: 123931: 5100c7bcc2f110c0de6119c144fb9758843662f2 v: v3 --- [refs] | 2 +- trunk/arch/arm/Kconfig | 3 +- trunk/arch/arm/configs/netx_defconfig | 6 +- trunk/arch/arm/configs/picotux200_defconfig | 6 +- trunk/arch/arm/kernel/ftrace.c | 2 +- trunk/arch/arm/mach-at91/at91rm9200_time.c | 9 - .../arm/mach-netx/include/mach/netx-regs.h | 22 -- trunk/arch/arm/mach-netx/time.c | 98 +------ trunk/arch/arm/mach-netx/xc.c | 6 +- trunk/arch/arm/mach-orion5x/Makefile | 2 +- trunk/arch/arm/mach-orion5x/common.h | 7 - trunk/arch/arm/mach-orion5x/gpio.c | 231 ----------------- .../arch/arm/mach-orion5x/include/mach/gpio.h | 26 +- .../arch/arm/mach-orion5x/include/mach/irqs.h | 4 +- .../arm/mach-orion5x/include/mach/orion5x.h | 6 - trunk/arch/arm/mach-orion5x/irq.c | 24 +- trunk/arch/arm/mach-orion5x/mpp.c | 6 +- trunk/arch/arm/plat-orion/Makefile | 2 + trunk/arch/arm/plat-orion/gpio.c | 239 ++++++++++++++++++ trunk/arch/arm/plat-orion/include/plat/gpio.h | 32 +++ 20 files changed, 334 insertions(+), 399 deletions(-) delete mode 100644 trunk/arch/arm/mach-orion5x/gpio.c create mode 100644 trunk/arch/arm/plat-orion/gpio.c create mode 100644 trunk/arch/arm/plat-orion/include/plat/gpio.h diff --git a/[refs] b/[refs] index bdccf6815072..b7cd3cfb0348 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 828aac2ee239dca9c1856c4856a57912e6a487c4 +refs/heads/master: 9569dae75f6f6987e79fa26cf6da3fc24006c996 diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index 4f870207f496..f1a3b10cfa9e 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -156,6 +156,7 @@ config ARCH_MTD_XIP bool config GENERIC_HARDIRQS_NO__DO_IRQ + bool def_bool y if OPROFILE @@ -287,8 +288,6 @@ config ARCH_NETX bool "Hilscher NetX based" select CPU_ARM926T select ARM_VIC - select GENERIC_CLOCKEVENTS - select GENERIC_TIME help This enables support for systems based on the Hilscher NetX Soc diff --git a/trunk/arch/arm/configs/netx_defconfig b/trunk/arch/arm/configs/netx_defconfig index 61d0fc5b2417..0884f2370c3a 100644 --- a/trunk/arch/arm/configs/netx_defconfig +++ b/trunk/arch/arm/configs/netx_defconfig @@ -728,9 +728,9 @@ CONFIG_RTC_CLASS=m # # RTC interfaces # -CONFIG_RTC_INTF_SYSFS=y -CONFIG_RTC_INTF_PROC=y -CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m # # RTC drivers diff --git a/trunk/arch/arm/configs/picotux200_defconfig b/trunk/arch/arm/configs/picotux200_defconfig index 59e4463c2da2..14826f0dabde 100644 --- a/trunk/arch/arm/configs/picotux200_defconfig +++ b/trunk/arch/arm/configs/picotux200_defconfig @@ -1069,9 +1069,9 @@ CONFIG_RTC_CLASS=m # # RTC interfaces # -CONFIG_RTC_INTF_SYSFS=y -CONFIG_RTC_INTF_PROC=y -CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_SYSFS=m +CONFIG_RTC_INTF_PROC=m +CONFIG_RTC_INTF_DEV=m # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # diff --git a/trunk/arch/arm/kernel/ftrace.c b/trunk/arch/arm/kernel/ftrace.c index c63842766229..6c90479e8974 100644 --- a/trunk/arch/arm/kernel/ftrace.c +++ b/trunk/arch/arm/kernel/ftrace.c @@ -95,7 +95,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func) return ret; } -/* run from ftrace_init with irqs disabled */ +/* run from kstop_machine */ int __init ftrace_dyn_arch_init(void *data) { ftrace_mcount_set(data); diff --git a/trunk/arch/arm/mach-at91/at91rm9200_time.c b/trunk/arch/arm/mach-at91/at91rm9200_time.c index d140eae53ded..a72e798a2a40 100644 --- a/trunk/arch/arm/mach-at91/at91rm9200_time.c +++ b/trunk/arch/arm/mach-at91/at91rm9200_time.c @@ -141,15 +141,6 @@ clkevt32k_next_event(unsigned long delta, struct clock_event_device *dev) /* Use "raw" primitives so we behave correctly on RT kernels. */ raw_local_irq_save(flags); - /* - * According to Thomas Gleixner irqs are already disabled here. Simply - * removing raw_local_irq_save above (and the matching - * raw_local_irq_restore) was not accepted. See - * http://thread.gmane.org/gmane.linux.ports.arm.kernel/41174 - * So for now (2008-11-20) just warn once if irqs were not disabled ... - */ - WARN_ON_ONCE(!raw_irqs_disabled_flags(flags)); - /* The alarm IRQ uses absolute time (now+delta), not the relative * time (delta) in our calling convention. Like all clockevents * using such "match" hardware, we have a race to defend against. diff --git a/trunk/arch/arm/mach-netx/include/mach/netx-regs.h b/trunk/arch/arm/mach-netx/include/mach/netx-regs.h index 08c60ff227be..5104a00d40f4 100644 --- a/trunk/arch/arm/mach-netx/include/mach/netx-regs.h +++ b/trunk/arch/arm/mach-netx/include/mach/netx-regs.h @@ -328,28 +328,6 @@ #define NETX_PFIFO_FILL_LEVEL(pfifo) NETX_PFIFO_REG(0x180 + ((pfifo)<<2)) #define NETX_PFIFO_XPEC_ISR(xpec) NETX_PFIFO_REG(0x400 + ((xpec) << 2)) - -/******************************* - * Memory Controller * - *******************************/ - -/* Registers */ -#define NETX_MEMCR_REG(ofs) __io(NETX_VA_MEMCR + (ofs)) -#define NETX_MEMCR_SRAM_CTRL(cs) NETX_MEMCR_REG(0x0 + 4 * (cs)) /* SRAM for CS 0..2 */ -#define NETX_MEMCR_SDRAM_CFG_CTRL NETX_MEMCR_REG(0x40) -#define NETX_MEMCR_SDRAM_TIMING_CTRL NETX_MEMCR_REG(0x44) -#define NETX_MEMCR_SDRAM_MODE NETX_MEMCR_REG(0x48) -#define NETX_MEMCR_SDRAM_EXT_MODE NETX_MEMCR_REG(0x4c) -#define NETX_MEMCR_PRIO_TIMESLOT_CTRL NETX_MEMCR_REG(0x80) -#define NETX_MEMCR_PRIO_ACCESS_CTRL NETX_MEMCR_REG(0x84) - -/* Bits */ -#define NETX_MEMCR_SRAM_CTRL_WIDTHEXTMEM(x) (((x) & 0x3) << 24) -#define NETX_MEMCR_SRAM_CTRL_WSPOSTPAUSEEXTMEM(x) (((x) & 0x3) << 16) -#define NETX_MEMCR_SRAM_CTRL_WSPREPASEEXTMEM(x) (((x) & 0x3) << 8) -#define NETX_MEMCR_SRAM_CTRL_WSEXTMEM(x) (((x) & 0x1f) << 0) - - /******************************* * Dual Port Memory * *******************************/ diff --git a/trunk/arch/arm/mach-netx/time.c b/trunk/arch/arm/mach-netx/time.c index d51d627ce7cf..7c540c1f01fa 100644 --- a/trunk/arch/arm/mach-netx/time.c +++ b/trunk/arch/arm/mach-netx/time.c @@ -21,100 +21,43 @@ #include #include #include -#include #include #include #include #include -#define TIMER_CLOCKEVENT 0 -#define TIMER_CLOCKSOURCE 1 - -static void netx_set_mode(enum clock_event_mode mode, - struct clock_event_device *clk) -{ - u32 tmode; - - /* disable timer */ - writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT)); - - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - writel(LATCH, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT)); - tmode = NETX_GPIO_COUNTER_CTRL_RST_EN | - NETX_GPIO_COUNTER_CTRL_IRQ_EN | - NETX_GPIO_COUNTER_CTRL_RUN; - break; - - case CLOCK_EVT_MODE_ONESHOT: - writel(0, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKEVENT)); - tmode = NETX_GPIO_COUNTER_CTRL_IRQ_EN | - NETX_GPIO_COUNTER_CTRL_RUN; - break; - - default: - WARN(1, "%s: unhandled mode %d\n", __func__, mode); - /* fall through */ - - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_RESUME: - tmode = 0; - break; - } - - writel(tmode, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKEVENT)); -} - -static int netx_set_next_event(unsigned long evt, - struct clock_event_device *clk) -{ - writel(0 - evt, NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKEVENT)); - return 0; -} - -static struct clock_event_device netx_clockevent = { - .name = "netx-timer" __stringify(TIMER_CLOCKEVENT), - .shift = 32, - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_next_event = netx_set_next_event, - .set_mode = netx_set_mode, -}; - /* * IRQ handler for the timer */ static irqreturn_t netx_timer_interrupt(int irq, void *dev_id) { - struct clock_event_device *evt = &netx_clockevent; + timer_tick(); /* acknowledge interrupt */ writel(COUNTER_BIT(0), NETX_GPIO_IRQ); - evt->event_handler(evt); - return IRQ_HANDLED; } static struct irqaction netx_timer_irq = { - .name = "NetX Timer Tick", - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = netx_timer_interrupt, + .name = "NetX Timer Tick", + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = netx_timer_interrupt, }; cycle_t netx_get_cycles(void) { - return readl(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE)); + return readl(NETX_GPIO_COUNTER_CURRENT(1)); } static struct clocksource clocksource_netx = { - .name = "netx_timer", + .name = "netx_timer", .rating = 200, .read = netx_get_cycles, .mask = CLOCKSOURCE_MASK(32), - .shift = 20, + .shift = 20, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; @@ -134,37 +77,24 @@ static void __init netx_timer_init(void) /* acknowledge interrupt */ writel(COUNTER_BIT(0), NETX_GPIO_IRQ); - /* Enable the interrupt in the specific timer - * register and start timer - */ + /* Enable the interrupt in the specific timer register and start timer */ writel(COUNTER_BIT(0), NETX_GPIO_IRQ_ENABLE); writel(NETX_GPIO_COUNTER_CTRL_IRQ_EN | NETX_GPIO_COUNTER_CTRL_RUN, - NETX_GPIO_COUNTER_CTRL(0)); + NETX_GPIO_COUNTER_CTRL(0)); setup_irq(NETX_IRQ_TIMER0, &netx_timer_irq); /* Setup timer one for clocksource */ - writel(0, NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE)); - writel(0, NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE)); - writel(0xffffffff, NETX_GPIO_COUNTER_MAX(TIMER_CLOCKSOURCE)); + writel(0, NETX_GPIO_COUNTER_CTRL(1)); + writel(0, NETX_GPIO_COUNTER_CURRENT(1)); + writel(0xFFFFFFFF, NETX_GPIO_COUNTER_MAX(1)); - writel(NETX_GPIO_COUNTER_CTRL_RUN, - NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE)); + writel(NETX_GPIO_COUNTER_CTRL_RUN, + NETX_GPIO_COUNTER_CTRL(1)); clocksource_netx.mult = clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_netx.shift); clocksource_register(&clocksource_netx); - - netx_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, - netx_clockevent.shift); - netx_clockevent.max_delta_ns = - clockevent_delta2ns(0xfffffffe, &netx_clockevent); - /* with max_delta_ns >= delta2ns(0x800) the system currently runs fine. - * Adding some safety ... */ - netx_clockevent.min_delta_ns = - clockevent_delta2ns(0xa00, &netx_clockevent); - netx_clockevent.cpumask = cpumask_of_cpu(0); - clockevents_register_device(&netx_clockevent); } struct sys_timer netx_timer = { diff --git a/trunk/arch/arm/mach-netx/xc.c b/trunk/arch/arm/mach-netx/xc.c index 8fc6205dc3a5..32eabf5dfa4f 100644 --- a/trunk/arch/arm/mach-netx/xc.c +++ b/trunk/arch/arm/mach-netx/xc.c @@ -92,10 +92,10 @@ static int xc_check_ptr(struct xc *x, unsigned long adr, unsigned int size) return -1; } -static int xc_patch(struct xc *x, const void *patch, int count) +static int xc_patch(struct xc *x, void *patch, int count) { unsigned int val, adr; - const unsigned int *data = patch; + unsigned int *data = patch; int i; for (i = 0; i < count; i++) { @@ -117,7 +117,7 @@ int xc_request_firmware(struct xc *x) struct fw_header *head; unsigned int size; int i; - const void *src; + void *src; unsigned long dst; sprintf(name, "xc%d.bin", x->no); diff --git a/trunk/arch/arm/mach-orion5x/Makefile b/trunk/arch/arm/mach-orion5x/Makefile index 3d4a1bc12355..edc38e2c856f 100644 --- a/trunk/arch/arm/mach-orion5x/Makefile +++ b/trunk/arch/arm/mach-orion5x/Makefile @@ -1,4 +1,4 @@ -obj-y += common.o addr-map.o pci.o gpio.o irq.o mpp.o +obj-y += common.o addr-map.o pci.o irq.o mpp.o obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o diff --git a/trunk/arch/arm/mach-orion5x/common.h b/trunk/arch/arm/mach-orion5x/common.h index a000c7c6ee96..798b9a5e3da9 100644 --- a/trunk/arch/arm/mach-orion5x/common.h +++ b/trunk/arch/arm/mach-orion5x/common.h @@ -51,13 +51,6 @@ int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys); struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys); int orion5x_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin); -/* - * Valid GPIO pins according to MPP setup, used by machine-setup. - * (/mach-orion/gpio.c). - */ -void orion5x_gpio_set_valid(unsigned pin, int valid); -void gpio_display(void); /* debug */ - struct machine_desc; struct meminfo; struct tag; diff --git a/trunk/arch/arm/mach-orion5x/gpio.c b/trunk/arch/arm/mach-orion5x/gpio.c deleted file mode 100644 index f99d08811e5a..000000000000 --- a/trunk/arch/arm/mach-orion5x/gpio.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * arch/arm/mach-orion5x/gpio.c - * - * GPIO functions for Marvell Orion System On Chip - * - * Maintainer: Tzachi Perelstein - * - * 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 -#include -#include -#include -#include -#include "common.h" - -static DEFINE_SPINLOCK(gpio_lock); -static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)]; -static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */ - -void __init orion5x_gpio_set_valid(unsigned pin, int valid) -{ - if (valid) - __set_bit(pin, gpio_valid); - else - __clear_bit(pin, gpio_valid); -} - -/* - * GENERIC_GPIO primitives - */ -int gpio_direction_input(unsigned pin) -{ - unsigned long flags; - - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { - pr_debug("%s: invalid GPIO %d\n", __func__, pin); - return -EINVAL; - } - - spin_lock_irqsave(&gpio_lock, flags); - - /* - * Some callers might have not used the gpio_request(), - * so flag this pin as requested now. - */ - if (!gpio_label[pin]) - gpio_label[pin] = "?"; - - orion5x_setbits(GPIO_IO_CONF, 1 << pin); - - spin_unlock_irqrestore(&gpio_lock, flags); - return 0; -} -EXPORT_SYMBOL(gpio_direction_input); - -int gpio_direction_output(unsigned pin, int value) -{ - unsigned long flags; - int mask; - - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { - pr_debug("%s: invalid GPIO %d\n", __func__, pin); - return -EINVAL; - } - - spin_lock_irqsave(&gpio_lock, flags); - - /* - * Some callers might have not used the gpio_request(), - * so flag this pin as requested now. - */ - if (!gpio_label[pin]) - gpio_label[pin] = "?"; - - mask = 1 << pin; - orion5x_clrbits(GPIO_BLINK_EN, mask); - if (value) - orion5x_setbits(GPIO_OUT, mask); - else - orion5x_clrbits(GPIO_OUT, mask); - orion5x_clrbits(GPIO_IO_CONF, mask); - - spin_unlock_irqrestore(&gpio_lock, flags); - return 0; -} -EXPORT_SYMBOL(gpio_direction_output); - -int gpio_get_value(unsigned pin) -{ - int val, mask = 1 << pin; - - if (readl(GPIO_IO_CONF) & mask) - val = readl(GPIO_DATA_IN) ^ readl(GPIO_IN_POL); - else - val = readl(GPIO_OUT); - - return val & mask; -} -EXPORT_SYMBOL(gpio_get_value); - -void gpio_set_value(unsigned pin, int value) -{ - unsigned long flags; - int mask = 1 << pin; - - spin_lock_irqsave(&gpio_lock, flags); - - orion5x_clrbits(GPIO_BLINK_EN, mask); - if (value) - orion5x_setbits(GPIO_OUT, mask); - else - orion5x_clrbits(GPIO_OUT, mask); - - spin_unlock_irqrestore(&gpio_lock, flags); -} -EXPORT_SYMBOL(gpio_set_value); - -void orion5x_gpio_set_blink(unsigned pin, int blink) -{ - unsigned long flags; - int mask = 1 << pin; - - spin_lock_irqsave(&gpio_lock, flags); - - orion5x_clrbits(GPIO_OUT, mask); - if (blink) - orion5x_setbits(GPIO_BLINK_EN, mask); - else - orion5x_clrbits(GPIO_BLINK_EN, mask); - - spin_unlock_irqrestore(&gpio_lock, flags); -} -EXPORT_SYMBOL(orion5x_gpio_set_blink); - -int gpio_request(unsigned pin, const char *label) -{ - int ret = 0; - unsigned long flags; - - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { - pr_debug("%s: invalid GPIO %d\n", __func__, pin); - return -EINVAL; - } - - spin_lock_irqsave(&gpio_lock, flags); - - if (gpio_label[pin]) { - pr_debug("%s: GPIO %d already used as %s\n", - __func__, pin, gpio_label[pin]); - ret = -EBUSY; - } else - gpio_label[pin] = label ? label : "?"; - - spin_unlock_irqrestore(&gpio_lock, flags); - return ret; -} -EXPORT_SYMBOL(gpio_request); - -void gpio_free(unsigned pin) -{ - might_sleep(); - - if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { - pr_debug("%s: invalid GPIO %d\n", __func__, pin); - return; - } - - if (!gpio_label[pin]) - pr_warning("%s: GPIO %d already freed\n", __func__, pin); - else - gpio_label[pin] = NULL; -} -EXPORT_SYMBOL(gpio_free); - -/* Debug helper */ -void gpio_display(void) -{ - int i; - - for (i = 0; i < GPIO_MAX; i++) { - printk(KERN_DEBUG "Pin-%d: ", i); - - if (!test_bit(i, gpio_valid)) { - printk("non-GPIO\n"); - } else if (!gpio_label[i]) { - printk("GPIO, free\n"); - } else { - printk("GPIO, used by %s, ", gpio_label[i]); - if (readl(GPIO_IO_CONF) & (1 << i)) { - printk("input, active %s, level %s, edge %s\n", - ((readl(GPIO_IN_POL) >> i) & 1) ? "low" : "high", - ((readl(GPIO_LEVEL_MASK) >> i) & 1) ? "enabled" : "masked", - ((readl(GPIO_EDGE_MASK) >> i) & 1) ? "enabled" : "masked"); - } else { - printk("output, val=%d\n", (readl(GPIO_OUT) >> i) & 1); - } - } - } - - printk(KERN_DEBUG "MPP_0_7_CTRL (0x%08x) = 0x%08x\n", - MPP_0_7_CTRL, readl(MPP_0_7_CTRL)); - printk(KERN_DEBUG "MPP_8_15_CTRL (0x%08x) = 0x%08x\n", - MPP_8_15_CTRL, readl(MPP_8_15_CTRL)); - printk(KERN_DEBUG "MPP_16_19_CTRL (0x%08x) = 0x%08x\n", - MPP_16_19_CTRL, readl(MPP_16_19_CTRL)); - printk(KERN_DEBUG "MPP_DEV_CTRL (0x%08x) = 0x%08x\n", - MPP_DEV_CTRL, readl(MPP_DEV_CTRL)); - printk(KERN_DEBUG "GPIO_OUT (0x%08x) = 0x%08x\n", - GPIO_OUT, readl(GPIO_OUT)); - printk(KERN_DEBUG "GPIO_IO_CONF (0x%08x) = 0x%08x\n", - GPIO_IO_CONF, readl(GPIO_IO_CONF)); - printk(KERN_DEBUG "GPIO_BLINK_EN (0x%08x) = 0x%08x\n", - GPIO_BLINK_EN, readl(GPIO_BLINK_EN)); - printk(KERN_DEBUG "GPIO_IN_POL (0x%08x) = 0x%08x\n", - GPIO_IN_POL, readl(GPIO_IN_POL)); - printk(KERN_DEBUG "GPIO_DATA_IN (0x%08x) = 0x%08x\n", - GPIO_DATA_IN, readl(GPIO_DATA_IN)); - printk(KERN_DEBUG "GPIO_LEVEL_MASK (0x%08x) = 0x%08x\n", - GPIO_LEVEL_MASK, readl(GPIO_LEVEL_MASK)); - printk(KERN_DEBUG "GPIO_EDGE_CAUSE (0x%08x) = 0x%08x\n", - GPIO_EDGE_CAUSE, readl(GPIO_EDGE_CAUSE)); - printk(KERN_DEBUG "GPIO_EDGE_MASK (0x%08x) = 0x%08x\n", - GPIO_EDGE_MASK, readl(GPIO_EDGE_MASK)); -} diff --git a/trunk/arch/arm/mach-orion5x/include/mach/gpio.h b/trunk/arch/arm/mach-orion5x/include/mach/gpio.h index 65dc136a86f7..a1a387b189a0 100644 --- a/trunk/arch/arm/mach-orion5x/include/mach/gpio.h +++ b/trunk/arch/arm/mach-orion5x/include/mach/gpio.h @@ -2,18 +2,23 @@ * arch/arm/mach-orion5x/include/mach/gpio.h * * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any + * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. */ -extern int gpio_request(unsigned pin, const char *label); -extern void gpio_free(unsigned pin); -extern int gpio_direction_input(unsigned pin); -extern int gpio_direction_output(unsigned pin, int value); -extern int gpio_get_value(unsigned pin); -extern void gpio_set_value(unsigned pin, int value); -extern void orion5x_gpio_set_blink(unsigned pin, int blink); -extern void gpio_display(void); /* debug */ +#ifndef __ASM_ARCH_GPIO_H +#define __ASM_ARCH_GPIO_H + +#include +#include +#include /* cansleep wrappers */ + +#define GPIO_MAX 32 +#define GPIO_OUT(pin) ORION5X_DEV_BUS_REG(0x100) +#define GPIO_IO_CONF(pin) ORION5X_DEV_BUS_REG(0x104) +#define GPIO_BLINK_EN(pin) ORION5X_DEV_BUS_REG(0x108) +#define GPIO_IN_POL(pin) ORION5X_DEV_BUS_REG(0x10c) +#define GPIO_DATA_IN(pin) ORION5X_DEV_BUS_REG(0x110) static inline int gpio_to_irq(int pin) { @@ -25,4 +30,5 @@ static inline int irq_to_gpio(int irq) return irq - IRQ_ORION5X_GPIO_START; } -#include /* cansleep wrappers */ + +#endif diff --git a/trunk/arch/arm/mach-orion5x/include/mach/irqs.h b/trunk/arch/arm/mach-orion5x/include/mach/irqs.h index d5b0fbf6b965..a6fa9d8f12d8 100644 --- a/trunk/arch/arm/mach-orion5x/include/mach/irqs.h +++ b/trunk/arch/arm/mach-orion5x/include/mach/irqs.h @@ -13,8 +13,6 @@ #ifndef __ASM_ARCH_IRQS_H #define __ASM_ARCH_IRQS_H -#include "orion5x.h" /* need GPIO_MAX */ - /* * Orion Main Interrupt Controller */ @@ -54,7 +52,7 @@ * Orion General Purpose Pins */ #define IRQ_ORION5X_GPIO_START 32 -#define NR_GPIO_IRQS GPIO_MAX +#define NR_GPIO_IRQS 32 #define NR_IRQS (IRQ_ORION5X_GPIO_START + NR_GPIO_IRQS) diff --git a/trunk/arch/arm/mach-orion5x/include/mach/orion5x.h b/trunk/arch/arm/mach-orion5x/include/mach/orion5x.h index 9f5ce1ce5840..a8915081773b 100644 --- a/trunk/arch/arm/mach-orion5x/include/mach/orion5x.h +++ b/trunk/arch/arm/mach-orion5x/include/mach/orion5x.h @@ -134,11 +134,6 @@ #define MPP_16_19_CTRL ORION5X_DEV_BUS_REG(0x050) #define MPP_DEV_CTRL ORION5X_DEV_BUS_REG(0x008) #define MPP_RESET_SAMPLE ORION5X_DEV_BUS_REG(0x010) -#define GPIO_OUT ORION5X_DEV_BUS_REG(0x100) -#define GPIO_IO_CONF ORION5X_DEV_BUS_REG(0x104) -#define GPIO_BLINK_EN ORION5X_DEV_BUS_REG(0x108) -#define GPIO_IN_POL ORION5X_DEV_BUS_REG(0x10c) -#define GPIO_DATA_IN ORION5X_DEV_BUS_REG(0x110) #define GPIO_EDGE_CAUSE ORION5X_DEV_BUS_REG(0x114) #define GPIO_EDGE_MASK ORION5X_DEV_BUS_REG(0x118) #define GPIO_LEVEL_MASK ORION5X_DEV_BUS_REG(0x11c) @@ -149,7 +144,6 @@ #define DEV_BUS_CTRL ORION5X_DEV_BUS_REG(0x4c0) #define DEV_BUS_INT_CAUSE ORION5X_DEV_BUS_REG(0x4d0) #define DEV_BUS_INT_MASK ORION5X_DEV_BUS_REG(0x4d4) -#define GPIO_MAX 32 /*************************************************************************** * Orion CPU Bridge Registers diff --git a/trunk/arch/arm/mach-orion5x/irq.c b/trunk/arch/arm/mach-orion5x/irq.c index 632a36f5cf14..6b2f1353797e 100644 --- a/trunk/arch/arm/mach-orion5x/irq.c +++ b/trunk/arch/arm/mach-orion5x/irq.c @@ -22,7 +22,7 @@ /***************************************************************************** * Orion GPIO IRQ * - * GPIO_IN_POL register controlls whether GPIO_DATA_IN will hold the same + * GPIO_IN_POL register controls whether GPIO_DATA_IN will hold the same * value of the line or the opposite value. * * Level IRQ handlers: DATA_IN is used directly as cause register. @@ -82,7 +82,7 @@ static int orion5x_gpio_set_irq_type(u32 irq, u32 type) int pin = irq_to_gpio(irq); struct irq_desc *desc; - if ((readl(GPIO_IO_CONF) & (1 << pin)) == 0) { + if ((readl(GPIO_IO_CONF(pin)) & (1 << pin)) == 0) { printk(KERN_ERR "orion5x_gpio_set_irq_type failed " "(irq %d, pin %d).\n", irq, pin); return -EINVAL; @@ -94,22 +94,22 @@ static int orion5x_gpio_set_irq_type(u32 irq, u32 type) case IRQ_TYPE_LEVEL_HIGH: desc->handle_irq = handle_level_irq; desc->status |= IRQ_LEVEL; - orion5x_clrbits(GPIO_IN_POL, (1 << pin)); + orion5x_clrbits(GPIO_IN_POL(pin), (1 << pin)); break; case IRQ_TYPE_LEVEL_LOW: desc->handle_irq = handle_level_irq; desc->status |= IRQ_LEVEL; - orion5x_setbits(GPIO_IN_POL, (1 << pin)); + orion5x_setbits(GPIO_IN_POL(pin), (1 << pin)); break; case IRQ_TYPE_EDGE_RISING: desc->handle_irq = handle_edge_irq; desc->status &= ~IRQ_LEVEL; - orion5x_clrbits(GPIO_IN_POL, (1 << pin)); + orion5x_clrbits(GPIO_IN_POL(pin), (1 << pin)); break; case IRQ_TYPE_EDGE_FALLING: desc->handle_irq = handle_edge_irq; desc->status &= ~IRQ_LEVEL; - orion5x_setbits(GPIO_IN_POL, (1 << pin)); + orion5x_setbits(GPIO_IN_POL(pin), (1 << pin)); break; case IRQ_TYPE_EDGE_BOTH: desc->handle_irq = handle_edge_irq; @@ -117,11 +117,11 @@ static int orion5x_gpio_set_irq_type(u32 irq, u32 type) /* * set initial polarity based on current input level */ - if ((readl(GPIO_IN_POL) ^ readl(GPIO_DATA_IN)) + if ((readl(GPIO_IN_POL(pin)) ^ readl(GPIO_DATA_IN(pin))) & (1 << pin)) - orion5x_setbits(GPIO_IN_POL, (1 << pin)); /* falling */ + orion5x_setbits(GPIO_IN_POL(pin), (1 << pin)); /* falling */ else - orion5x_clrbits(GPIO_IN_POL, (1 << pin)); /* rising */ + orion5x_clrbits(GPIO_IN_POL(pin), (1 << pin)); /* rising */ break; default: @@ -149,7 +149,7 @@ static void orion5x_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) BUG_ON(irq < IRQ_ORION5X_GPIO_0_7 || irq > IRQ_ORION5X_GPIO_24_31); offs = (irq - IRQ_ORION5X_GPIO_0_7) * 8; - cause = (readl(GPIO_DATA_IN) & readl(GPIO_LEVEL_MASK)) | + cause = (readl(GPIO_DATA_IN(offs)) & readl(GPIO_LEVEL_MASK)) | (readl(GPIO_EDGE_CAUSE) & readl(GPIO_EDGE_MASK)); for (pin = offs; pin < offs + 8; pin++) { @@ -158,9 +158,9 @@ static void orion5x_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) desc = irq_desc + irq; if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { /* Swap polarity (race with GPIO line) */ - u32 polarity = readl(GPIO_IN_POL); + u32 polarity = readl(GPIO_IN_POL(pin)); polarity ^= 1 << pin; - writel(polarity, GPIO_IN_POL); + writel(polarity, GPIO_IN_POL(pin)); } generic_handle_irq(irq); } diff --git a/trunk/arch/arm/mach-orion5x/mpp.c b/trunk/arch/arm/mach-orion5x/mpp.c index 640ea2a3fc6c..e23a3f91d6c6 100644 --- a/trunk/arch/arm/mach-orion5x/mpp.c +++ b/trunk/arch/arm/mach-orion5x/mpp.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "common.h" #include "mpp.h" @@ -152,7 +153,10 @@ void __init orion5x_mpp_conf(struct orion5x_mpp_mode *mode) *reg &= ~(0xf << shift); *reg |= (num_type & 0xf) << shift; - orion5x_gpio_set_valid(mode->mpp, !!(mode->type == MPP_GPIO)); + if (mode->type == MPP_UNUSED && (mode->mpp < 16 || is_5182())) + orion_gpio_set_unused(mode->mpp); + + orion_gpio_set_valid(mode->mpp, !!(mode->type == MPP_GPIO)); mode++; } diff --git a/trunk/arch/arm/plat-orion/Makefile b/trunk/arch/arm/plat-orion/Makefile index 198f3dde2be3..56021a72e10c 100644 --- a/trunk/arch/arm/plat-orion/Makefile +++ b/trunk/arch/arm/plat-orion/Makefile @@ -6,3 +6,5 @@ obj-y := irq.o pcie.o time.o obj-m := obj-n := obj- := + +obj-$(CONFIG_GENERIC_GPIO) += gpio.o diff --git a/trunk/arch/arm/plat-orion/gpio.c b/trunk/arch/arm/plat-orion/gpio.c new file mode 100644 index 000000000000..d86fc085e489 --- /dev/null +++ b/trunk/arch/arm/plat-orion/gpio.c @@ -0,0 +1,239 @@ +/* + * arch/arm/plat-orion/gpio.c + * + * Marvell Orion SoC GPIO handling. + * + * 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 +#include +#include +#include + +static DEFINE_SPINLOCK(gpio_lock); +static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */ +static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)]; + +static inline void __set_direction(unsigned pin, int input) +{ + u32 u; + + u = readl(GPIO_IO_CONF(pin)); + if (input) + u |= 1 << (pin & 31); + else + u &= ~(1 << (pin & 31)); + writel(u, GPIO_IO_CONF(pin)); +} + +static void __set_level(unsigned pin, int high) +{ + u32 u; + + u = readl(GPIO_OUT(pin)); + if (high) + u |= 1 << (pin & 31); + else + u &= ~(1 << (pin & 31)); + writel(u, GPIO_OUT(pin)); +} + + +/* + * GENERIC_GPIO primitives. + */ +int gpio_direction_input(unsigned pin) +{ + unsigned long flags; + + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __func__, pin); + return -EINVAL; + } + + spin_lock_irqsave(&gpio_lock, flags); + + /* + * Some callers might not have used gpio_request(), + * so flag this pin as requested now. + */ + if (gpio_label[pin] == NULL) + gpio_label[pin] = "?"; + + /* + * Configure GPIO direction. + */ + __set_direction(pin, 1); + + spin_unlock_irqrestore(&gpio_lock, flags); + + return 0; +} +EXPORT_SYMBOL(gpio_direction_input); + +int gpio_direction_output(unsigned pin, int value) +{ + unsigned long flags; + u32 u; + + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __func__, pin); + return -EINVAL; + } + + spin_lock_irqsave(&gpio_lock, flags); + + /* + * Some callers might not have used gpio_request(), + * so flag this pin as requested now. + */ + if (gpio_label[pin] == NULL) + gpio_label[pin] = "?"; + + /* + * Disable blinking. + */ + u = readl(GPIO_BLINK_EN(pin)); + u &= ~(1 << (pin & 31)); + writel(u, GPIO_BLINK_EN(pin)); + + /* + * Configure GPIO output value. + */ + __set_level(pin, value); + + /* + * Configure GPIO direction. + */ + __set_direction(pin, 0); + + spin_unlock_irqrestore(&gpio_lock, flags); + + return 0; +} +EXPORT_SYMBOL(gpio_direction_output); + +int gpio_get_value(unsigned pin) +{ + int val; + + if (readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31))) + val = readl(GPIO_DATA_IN(pin)) ^ readl(GPIO_IN_POL(pin)); + else + val = readl(GPIO_OUT(pin)); + + return (val >> (pin & 31)) & 1; +} +EXPORT_SYMBOL(gpio_get_value); + +void gpio_set_value(unsigned pin, int value) +{ + unsigned long flags; + u32 u; + + spin_lock_irqsave(&gpio_lock, flags); + + /* + * Disable blinking. + */ + u = readl(GPIO_BLINK_EN(pin)); + u &= ~(1 << (pin & 31)); + writel(u, GPIO_BLINK_EN(pin)); + + /* + * Configure GPIO output value. + */ + __set_level(pin, value); + + spin_unlock_irqrestore(&gpio_lock, flags); +} +EXPORT_SYMBOL(gpio_set_value); + +int gpio_request(unsigned pin, const char *label) +{ + unsigned long flags; + int ret; + + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __func__, pin); + return -EINVAL; + } + + spin_lock_irqsave(&gpio_lock, flags); + if (gpio_label[pin] == NULL) { + gpio_label[pin] = label ? label : "?"; + ret = 0; + } else { + pr_debug("%s: GPIO %d already used as %s\n", + __func__, pin, gpio_label[pin]); + ret = -EBUSY; + } + spin_unlock_irqrestore(&gpio_lock, flags); + + return ret; +} +EXPORT_SYMBOL(gpio_request); + +void gpio_free(unsigned pin) +{ + if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) { + pr_debug("%s: invalid GPIO %d\n", __func__, pin); + return; + } + + if (gpio_label[pin] == NULL) + pr_warning("%s: GPIO %d already freed\n", __func__, pin); + else + gpio_label[pin] = NULL; +} +EXPORT_SYMBOL(gpio_free); + + +/* + * Orion-specific GPIO API extensions. + */ +void __init orion_gpio_set_unused(unsigned pin) +{ + /* + * Configure as output, drive low. + */ + __set_level(pin, 0); + __set_direction(pin, 0); +} + +void __init orion_gpio_set_valid(unsigned pin, int valid) +{ + if (valid) + __set_bit(pin, gpio_valid); + else + __clear_bit(pin, gpio_valid); +} + +void orion_gpio_set_blink(unsigned pin, int blink) +{ + unsigned long flags; + u32 u; + + spin_lock_irqsave(&gpio_lock, flags); + + /* + * Set output value to zero. + */ + __set_level(pin, 0); + + u = readl(GPIO_BLINK_EN(pin)); + if (blink) + u |= 1 << (pin & 31); + else + u &= ~(1 << (pin & 31)); + writel(u, GPIO_BLINK_EN(pin)); + + spin_unlock_irqrestore(&gpio_lock, flags); +} +EXPORT_SYMBOL(orion_gpio_set_blink); diff --git a/trunk/arch/arm/plat-orion/include/plat/gpio.h b/trunk/arch/arm/plat-orion/include/plat/gpio.h new file mode 100644 index 000000000000..956658df269f --- /dev/null +++ b/trunk/arch/arm/plat-orion/include/plat/gpio.h @@ -0,0 +1,32 @@ +/* + * arch/arm/plat-orion/include/plat/gpio.h + * + * Marvell Orion SoC GPIO handling. + * + * 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 __PLAT_GPIO_H +#define __PLAT_GPIO_H + +/* + * GENERIC_GPIO primitives. + */ +int gpio_request(unsigned pin, const char *label); +void gpio_free(unsigned pin); +int gpio_direction_input(unsigned pin); +int gpio_direction_output(unsigned pin, int value); +int gpio_get_value(unsigned pin); +void gpio_set_value(unsigned pin, int value); + +/* + * Orion-specific GPIO API extensions. + */ +void orion_gpio_set_unused(unsigned pin); +void orion_gpio_set_valid(unsigned pin, int valid); +void orion_gpio_set_blink(unsigned pin, int blink); + + +#endif