From 210b94e864de9d50ed08603a1ff0834603f309e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 31 Jan 2008 14:20:21 +0100 Subject: ns9xxx: move registration of serial8250 to a dedicated file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now the needed structs are allocated dynamically from __init code reducing memory usage if the kernel runs on a board different from a9m9750dev. Signed-off-by: Uwe Kleine-König --- arch/arm/mach-ns9xxx/Kconfig | 4 ++ arch/arm/mach-ns9xxx/Makefile | 3 ++ arch/arm/mach-ns9xxx/board-a9m9750dev.c | 58 --------------------------- arch/arm/mach-ns9xxx/plat-serial8250.c | 69 +++++++++++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 58 deletions(-) create mode 100644 arch/arm/mach-ns9xxx/plat-serial8250.c (limited to 'arch/arm/mach-ns9xxx') diff --git a/arch/arm/mach-ns9xxx/Kconfig b/arch/arm/mach-ns9xxx/Kconfig index 8584ed10799..83c0efa7399 100644 --- a/arch/arm/mach-ns9xxx/Kconfig +++ b/arch/arm/mach-ns9xxx/Kconfig @@ -2,6 +2,9 @@ if ARCH_NS9XXX menu "NS9xxx Implementations" +config NS9XXX_HAVE_SERIAL8250 + bool + config MACH_CC9P9360DEV bool "ConnectCore 9P 9360 on an A9M9750 Devboard" select PROCESSOR_NS9360 @@ -23,6 +26,7 @@ config PROCESSOR_NS9360 config BOARD_A9M9750DEV bool + select NS9XXX_HAVE_SERIAL8250 config BOARD_JSCC9P9360 bool diff --git a/arch/arm/mach-ns9xxx/Makefile b/arch/arm/mach-ns9xxx/Makefile index 6fb82b855a5..ca2c68dede1 100644 --- a/arch/arm/mach-ns9xxx/Makefile +++ b/arch/arm/mach-ns9xxx/Makefile @@ -5,3 +5,6 @@ obj-$(CONFIG_MACH_CC9P9360JS) += mach-cc9p9360js.o obj-$(CONFIG_BOARD_A9M9750DEV) += board-a9m9750dev.o obj-$(CONFIG_BOARD_JSCC9P9360) += board-jscc9p9360.o + +# platform devices +obj-$(CONFIG_NS9XXX_HAVE_SERIAL8250) += plat-serial8250.o diff --git a/arch/arm/mach-ns9xxx/board-a9m9750dev.c b/arch/arm/mach-ns9xxx/board-a9m9750dev.c index 0f65177f9e5..14a06da25ac 100644 --- a/arch/arm/mach-ns9xxx/board-a9m9750dev.c +++ b/arch/arm/mach-ns9xxx/board-a9m9750dev.c @@ -8,8 +8,6 @@ * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. */ -#include -#include #include #include @@ -126,59 +124,6 @@ void __init board_a9m9750dev_init_irq(void) a9m9750dev_fpga_demux_handler); } -static struct plat_serial8250_port board_a9m9750dev_serial8250_port[] = { - { - .iobase = FPGA_UARTA_BASE, - .membase = (unsigned char*)FPGA_UARTA_BASE, - .mapbase = FPGA_UARTA_BASE, - .irq = IRQ_FPGA_UARTA, - .iotype = UPIO_MEM, - .uartclk = 18432000, - .regshift = 0, - .flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ, - }, { - .iobase = FPGA_UARTB_BASE, - .membase = (unsigned char*)FPGA_UARTB_BASE, - .mapbase = FPGA_UARTB_BASE, - .irq = IRQ_FPGA_UARTB, - .iotype = UPIO_MEM, - .uartclk = 18432000, - .regshift = 0, - .flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ, - }, { - .iobase = FPGA_UARTC_BASE, - .membase = (unsigned char*)FPGA_UARTC_BASE, - .mapbase = FPGA_UARTC_BASE, - .irq = IRQ_FPGA_UARTC, - .iotype = UPIO_MEM, - .uartclk = 18432000, - .regshift = 0, - .flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ, - }, { - .iobase = FPGA_UARTD_BASE, - .membase = (unsigned char*)FPGA_UARTD_BASE, - .mapbase = FPGA_UARTD_BASE, - .irq = IRQ_FPGA_UARTD, - .iotype = UPIO_MEM, - .uartclk = 18432000, - .regshift = 0, - .flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ, - }, { - /* end marker */ - }, -}; - -static struct platform_device board_a9m9750dev_serial_device = { - .name = "serial8250", - .dev = { - .platform_data = board_a9m9750dev_serial8250_port, - }, -}; - -static struct platform_device *board_a9m9750dev_devices[] __initdata = { - &board_a9m9750dev_serial_device, -}; - void __init board_a9m9750dev_init_machine(void) { u32 reg; @@ -210,7 +155,4 @@ void __init board_a9m9750dev_init_machine(void) __raw_writel(0x2, MEM_SMOED(0)); __raw_writel(0x6, MEM_SMRD(0)); __raw_writel(0x6, MEM_SMWD(0)); - - platform_add_devices(board_a9m9750dev_devices, - ARRAY_SIZE(board_a9m9750dev_devices)); } diff --git a/arch/arm/mach-ns9xxx/plat-serial8250.c b/arch/arm/mach-ns9xxx/plat-serial8250.c new file mode 100644 index 00000000000..5aa5d9baf8c --- /dev/null +++ b/arch/arm/mach-ns9xxx/plat-serial8250.c @@ -0,0 +1,69 @@ +/* + * arch/arm/mach-ns9xxx/plat-serial8250.c + * + * Copyright (C) 2008 by Digi International Inc. + * All rights reserved. + * + * 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 + +#define DRIVER_NAME "serial8250" + +static int __init ns9xxx_plat_serial8250_init(void) +{ + struct plat_serial8250_port *pdata; + struct platform_device *pdev; + int ret = -ENOMEM; + int i; + + if (!board_is_a9m9750dev()) + return -ENODEV; + + pdev = platform_device_alloc(DRIVER_NAME, 0); + if (!pdev) + goto err; + + pdata = kzalloc(5 * sizeof(*pdata), GFP_KERNEL); + if (!pdata) + goto err; + + pdev->dev.platform_data = pdata; + + pdata[0].iobase = FPGA_UARTA_BASE; + pdata[1].iobase = FPGA_UARTB_BASE; + pdata[2].iobase = FPGA_UARTC_BASE; + pdata[3].iobase = FPGA_UARTD_BASE; + + for (i = 0; i < 4; ++i) { + pdata[i].membase = (void __iomem *)pdata[i].iobase; + pdata[i].mapbase = pdata[i].iobase; + pdata[i].iotype = UPIO_MEM; + pdata[i].uartclk = 18432000; + pdata[i].flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; + } + + pdata[0].irq = IRQ_FPGA_UARTA; + pdata[1].irq = IRQ_FPGA_UARTB; + pdata[2].irq = IRQ_FPGA_UARTC; + pdata[3].irq = IRQ_FPGA_UARTD; + + ret = platform_device_add(pdev); + if (ret) { +err: + platform_device_put(pdev); + + printk(KERN_WARNING "Could not add %s (errno=%d)\n", + DRIVER_NAME, ret); + } + + return 0; +} + +arch_initcall(ns9xxx_plat_serial8250_init); -- cgit v1.2.3 From c1a9e91e426a78728c0e815b0355a7c0374d1088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 5 Feb 2008 16:08:50 +0100 Subject: ns9xxx: use default text offset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König --- arch/arm/mach-ns9xxx/Makefile.boot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mach-ns9xxx') diff --git a/arch/arm/mach-ns9xxx/Makefile.boot b/arch/arm/mach-ns9xxx/Makefile.boot index 75ed64e90fa..54654919229 100644 --- a/arch/arm/mach-ns9xxx/Makefile.boot +++ b/arch/arm/mach-ns9xxx/Makefile.boot @@ -1,2 +1,2 @@ -zreladdr-y := 0x108000 +zreladdr-y := 0x8000 params_phys-y := 0x100 -- cgit v1.2.3 From 13f429bd1b48ab67037a746ed274d7f58bb325d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 16 Oct 2007 15:32:59 +0200 Subject: ns9xxx: introduce a config variable for the cc9p9360 module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moreover now it's the module that selects the processor, and not the machine anymore. Signed-off-by: Uwe Kleine-König --- arch/arm/mach-ns9xxx/Kconfig | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'arch/arm/mach-ns9xxx') diff --git a/arch/arm/mach-ns9xxx/Kconfig b/arch/arm/mach-ns9xxx/Kconfig index 83c0efa7399..dd0cd5ac4b8 100644 --- a/arch/arm/mach-ns9xxx/Kconfig +++ b/arch/arm/mach-ns9xxx/Kconfig @@ -5,9 +5,23 @@ menu "NS9xxx Implementations" config NS9XXX_HAVE_SERIAL8250 bool +config PROCESSOR_NS9360 + bool + +config MODULE_CC9P9360 + bool + select PROCESSOR_NS9360 + +config BOARD_A9M9750DEV + select NS9XXX_HAVE_SERIAL8250 + bool + +config BOARD_JSCC9P9360 + bool + config MACH_CC9P9360DEV bool "ConnectCore 9P 9360 on an A9M9750 Devboard" - select PROCESSOR_NS9360 + select MODULE_CC9P9360 select BOARD_A9M9750DEV help Say Y here if you are using the Digi ConnectCore 9P 9360 @@ -15,22 +29,12 @@ config MACH_CC9P9360DEV config MACH_CC9P9360JS bool "ConnectCore 9P 9360 on a JSCC9P9360 Devboard" - select PROCESSOR_NS9360 + select MODULE_CC9P9360 select BOARD_JSCC9P9360 help Say Y here if you are using the Digi ConnectCore 9P 9360 on an JSCC9P9360 Development Board. -config PROCESSOR_NS9360 - bool - -config BOARD_A9M9750DEV - bool - select NS9XXX_HAVE_SERIAL8250 - -config BOARD_JSCC9P9360 - bool - endmenu endif -- cgit v1.2.3 From 724ce5ee15ff4c4f3035110b683b990a3b33c832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 15 Feb 2008 08:41:06 +0100 Subject: ns9xxx: prepare for adding support for Digi ns921x processors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The hardware team changed some things that were taken as being common to all ns9xxx processors up to now. This patch addresses: - irqs: s/IRQ_/IRQ_NS9360_/ - system module registers: some registers are still general, their definition lives now in include/asm-arm/arch-ns9xxx/regs-sys-common.h. The ns9360 specific ones are in .../regs-sys-ns9360.h As a result ns9360_systemclock cannot be static inline any more as its definition needs regs-sys-ns9360.h. This becomes a real problem when adding support for ns9215 as this will need regs-sys-ns9215.h and including both files will not work. For the same reason ns9360_reset() is now non-inline and gpio functions live in their own file. - register mapping: s/ns9xxx_map_io/ns9360_map_io/ - timer registers: move time.c to time-ns9360.c; s/ns9xxx_timer/ns9360_timer/ Signed-off-by: Uwe Kleine-König --- arch/arm/mach-ns9xxx/Makefile | 4 +- arch/arm/mach-ns9xxx/board-a9m9750dev.c | 11 +- arch/arm/mach-ns9xxx/generic.c | 27 +---- arch/arm/mach-ns9xxx/generic.h | 5 +- arch/arm/mach-ns9xxx/gpio-ns9360.c | 118 ++++++++++++++++++++ arch/arm/mach-ns9xxx/gpio-ns9360.h | 13 +++ arch/arm/mach-ns9xxx/gpio.c | 141 +++++++++--------------- arch/arm/mach-ns9xxx/irq.c | 4 +- arch/arm/mach-ns9xxx/mach-cc9p9360dev.c | 8 +- arch/arm/mach-ns9xxx/mach-cc9p9360js.c | 8 +- arch/arm/mach-ns9xxx/processor-ns9360.c | 54 ++++++++++ arch/arm/mach-ns9xxx/time-ns9360.c | 185 ++++++++++++++++++++++++++++++++ arch/arm/mach-ns9xxx/time.c | 184 ------------------------------- 13 files changed, 441 insertions(+), 321 deletions(-) create mode 100644 arch/arm/mach-ns9xxx/gpio-ns9360.c create mode 100644 arch/arm/mach-ns9xxx/gpio-ns9360.h create mode 100644 arch/arm/mach-ns9xxx/processor-ns9360.c create mode 100644 arch/arm/mach-ns9xxx/time-ns9360.c delete mode 100644 arch/arm/mach-ns9xxx/time.c (limited to 'arch/arm/mach-ns9xxx') diff --git a/arch/arm/mach-ns9xxx/Makefile b/arch/arm/mach-ns9xxx/Makefile index ca2c68dede1..67a9e30c878 100644 --- a/arch/arm/mach-ns9xxx/Makefile +++ b/arch/arm/mach-ns9xxx/Makefile @@ -1,8 +1,10 @@ -obj-y := irq.o time.o generic.o gpio.o +obj-y := irq.o generic.o gpio.o obj-$(CONFIG_MACH_CC9P9360DEV) += mach-cc9p9360dev.o obj-$(CONFIG_MACH_CC9P9360JS) += mach-cc9p9360js.o +obj-$(CONFIG_PROCESSOR_NS9360) += gpio-ns9360.o processor-ns9360.o time-ns9360.o + obj-$(CONFIG_BOARD_A9M9750DEV) += board-a9m9750dev.o obj-$(CONFIG_BOARD_JSCC9P9360) += board-jscc9p9360.o diff --git a/arch/arm/mach-ns9xxx/board-a9m9750dev.c b/arch/arm/mach-ns9xxx/board-a9m9750dev.c index 14a06da25ac..a494b71c019 100644 --- a/arch/arm/mach-ns9xxx/board-a9m9750dev.c +++ b/arch/arm/mach-ns9xxx/board-a9m9750dev.c @@ -14,7 +14,8 @@ #include #include -#include +#include +#include #include #include #include @@ -103,9 +104,9 @@ void __init board_a9m9750dev_init_irq(void) int i; if (gpio_request(11, "board a9m9750dev extirq2") == 0) - ns9xxx_gpio_configure(11, 0, 1); + ns9360_gpio_configure(11, 0, 1); else - printk(KERN_ERR "%s: cannot get gpio 11 for IRQ_EXT2\n", + printk(KERN_ERR "%s: cannot get gpio 11 for IRQ_NS9XXX_EXT2\n", __func__); for (i = FPGA_IRQ(0); i <= FPGA_IRQ(7); ++i) { @@ -114,13 +115,13 @@ void __init board_a9m9750dev_init_irq(void) set_irq_flags(i, IRQF_VALID); } - /* IRQ_EXT2: level sensitive + active low */ + /* IRQ_NS9XXX_EXT2: level sensitive + active low */ eic = __raw_readl(SYS_EIC(2)); REGSET(eic, SYS_EIC, PLTY, AL); REGSET(eic, SYS_EIC, LVEDG, LEVEL); __raw_writel(eic, SYS_EIC(2)); - set_irq_chained_handler(IRQ_EXT2, + set_irq_chained_handler(IRQ_NS9XXX_EXT2, a9m9750dev_fpga_demux_handler); } diff --git a/arch/arm/mach-ns9xxx/generic.c b/arch/arm/mach-ns9xxx/generic.c index d742c921e34..1e0f467879c 100644 --- a/arch/arm/mach-ns9xxx/generic.c +++ b/arch/arm/mach-ns9xxx/generic.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-ns9xxx/generic.c * - * Copyright (C) 2006 by Digi International Inc. + * Copyright (C) 2006,2007 by Digi International Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify it @@ -11,34 +11,9 @@ #include #include #include -#include -#include -#include -#include -#include -#include #include "generic.h" -static struct map_desc standard_io_desc[] __initdata = { - { /* BBus */ - .virtual = io_p2v(0x90000000), - .pfn = __phys_to_pfn(0x90000000), - .length = 0x00700000, - .type = MT_DEVICE, - }, { /* AHB */ - .virtual = io_p2v(0xa0100000), - .pfn = __phys_to_pfn(0xa0100000), - .length = 0x00900000, - .type = MT_DEVICE, - }, -}; - -void __init ns9xxx_map_io(void) -{ - iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc)); -} - void __init ns9xxx_init_machine(void) { } diff --git a/arch/arm/mach-ns9xxx/generic.h b/arch/arm/mach-ns9xxx/generic.h index 687e291773f..82493191aad 100644 --- a/arch/arm/mach-ns9xxx/generic.h +++ b/arch/arm/mach-ns9xxx/generic.h @@ -1,7 +1,7 @@ /* * arch/arm/mach-ns9xxx/generic.h * - * Copyright (C) 2006 by Digi International Inc. + * Copyright (C) 2006,2007 by Digi International Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify it @@ -13,7 +13,4 @@ #include void __init ns9xxx_init_irq(void); -void __init ns9xxx_map_io(void); void __init ns9xxx_init_machine(void); - -extern struct sys_timer ns9xxx_timer; diff --git a/arch/arm/mach-ns9xxx/gpio-ns9360.c b/arch/arm/mach-ns9xxx/gpio-ns9360.c new file mode 100644 index 00000000000..cabfb879dda --- /dev/null +++ b/arch/arm/mach-ns9xxx/gpio-ns9360.c @@ -0,0 +1,118 @@ +/* + * arch/arm/mach-ns9xxx/gpio-ns9360.c + * + * Copyright (C) 2006,2007 by Digi International Inc. + * All rights reserved. + * + * 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 "gpio-ns9360.h" + +static inline int ns9360_valid_gpio(unsigned gpio) +{ + return gpio <= 72; +} + +static inline void __iomem *ns9360_gpio_get_gconfaddr(unsigned gpio) +{ + if (gpio < 56) + return BBU_GCONFb1(gpio / 8); + else + /* + * this could be optimised away on + * ns9750 only builds, but it isn't ... + */ + return BBU_GCONFb2((gpio - 56) / 8); +} + +static inline void __iomem *ns9360_gpio_get_gctrladdr(unsigned gpio) +{ + if (gpio < 32) + return BBU_GCTRL1; + else if (gpio < 64) + return BBU_GCTRL2; + else + /* this could be optimised away on ns9750 only builds */ + return BBU_GCTRL3; +} + +static inline void __iomem *ns9360_gpio_get_gstataddr(unsigned gpio) +{ + if (gpio < 32) + return BBU_GSTAT1; + else if (gpio < 64) + return BBU_GSTAT2; + else + /* this could be optimised away on ns9750 only builds */ + return BBU_GSTAT3; +} + +/* + * each gpio can serve for 4 different purposes [0..3]. These are called + * "functions" and passed in the parameter func. Functions 0-2 are always some + * special things, function 3 is GPIO. If func == 3 dir specifies input or + * output, and with inv you can enable an inverter (independent of func). + */ +int __ns9360_gpio_configure(unsigned gpio, int dir, int inv, int func) +{ + void __iomem *conf = ns9360_gpio_get_gconfaddr(gpio); + u32 confval; + + confval = __raw_readl(conf); + REGSETIM_IDX(confval, BBU_GCONFx, DIR, gpio & 7, dir); + REGSETIM_IDX(confval, BBU_GCONFx, INV, gpio & 7, inv); + REGSETIM_IDX(confval, BBU_GCONFx, FUNC, gpio & 7, func); + __raw_writel(confval, conf); + + return 0; +} + +int ns9360_gpio_configure(unsigned gpio, int inv, int func) +{ + if (likely(ns9360_valid_gpio(gpio))) { + if (func == 3) { + printk(KERN_WARNING "use gpio_direction_input " + "or gpio_direction_output\n"); + return -EINVAL; + } else + return __ns9360_gpio_configure(gpio, 0, inv, func); + } else + return -EINVAL; +} +EXPORT_SYMBOL(ns9360_gpio_configure); + +int ns9360_gpio_get_value(unsigned gpio) +{ + void __iomem *stat = ns9360_gpio_get_gstataddr(gpio); + int ret; + + ret = 1 & (__raw_readl(stat) >> (gpio & 31)); + + return ret; +} + +void ns9360_gpio_set_value(unsigned gpio, int value) +{ + void __iomem *ctrl = ns9360_gpio_get_gctrladdr(gpio); + u32 ctrlval; + + ctrlval = __raw_readl(ctrl); + + if (value) + ctrlval |= 1 << (gpio & 31); + else + ctrlval &= ~(1 << (gpio & 31)); + + __raw_writel(ctrlval, ctrl); +} diff --git a/arch/arm/mach-ns9xxx/gpio-ns9360.h b/arch/arm/mach-ns9xxx/gpio-ns9360.h new file mode 100644 index 00000000000..131cd1715ca --- /dev/null +++ b/arch/arm/mach-ns9xxx/gpio-ns9360.h @@ -0,0 +1,13 @@ +/* + * arch/arm/mach-ns9xxx/gpio-ns9360.h + * + * Copyright (C) 2006,2007 by Digi International Inc. + * All rights reserved. + * + * 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. + */ +int __ns9360_gpio_configure(unsigned gpio, int dir, int inv, int func); +int ns9360_gpio_get_value(unsigned gpio); +void ns9360_gpio_set_value(unsigned gpio, int value); diff --git a/arch/arm/mach-ns9xxx/gpio.c b/arch/arm/mach-ns9xxx/gpio.c index 5286e9fc1d3..b3c963b0c8f 100644 --- a/arch/arm/mach-ns9xxx/gpio.c +++ b/arch/arm/mach-ns9xxx/gpio.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-ns9xxx/gpio.c * - * Copyright (C) 2006 by Digi International Inc. + * Copyright (C) 2006,2007 by Digi International Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify it @@ -15,12 +15,13 @@ #include #include -#include -#include +#include #include #include #include +#include "gpio-ns9360.h" + #if defined(CONFIG_PROCESSOR_NS9360) #define GPIO_MAX 72 #elif defined(CONFIG_PROCESSOR_NS9750) @@ -45,41 +46,10 @@ static inline int ns9xxx_valid_gpio(unsigned gpio) return gpio <= 49; else #endif + { BUG(); -} - -static inline void __iomem *ns9xxx_gpio_get_gconfaddr(unsigned gpio) -{ - if (gpio < 56) - return BBU_GCONFb1(gpio / 8); - else - /* - * this could be optimised away on - * ns9750 only builds, but it isn't ... - */ - return BBU_GCONFb2((gpio - 56) / 8); -} - -static inline void __iomem *ns9xxx_gpio_get_gctrladdr(unsigned gpio) -{ - if (gpio < 32) - return BBU_GCTRL1; - else if (gpio < 64) - return BBU_GCTRL2; - else - /* this could be optimised away on ns9750 only builds */ - return BBU_GCTRL3; -} - -static inline void __iomem *ns9xxx_gpio_get_gstataddr(unsigned gpio) -{ - if (gpio < 32) - return BBU_GSTAT1; - else if (gpio < 64) - return BBU_GSTAT2; - else - /* this could be optimised away on ns9750 only builds */ - return BBU_GSTAT3; + return 0; + } } int gpio_request(unsigned gpio, const char *label) @@ -98,49 +68,24 @@ void gpio_free(unsigned gpio) } EXPORT_SYMBOL(gpio_free); -/* - * each gpio can serve for 4 different purposes [0..3]. These are called - * "functions" and passed in the parameter func. Functions 0-2 are always some - * special things, function 3 is GPIO. If func == 3 dir specifies input or - * output, and with inv you can enable an inverter (independent of func). - */ -static int __ns9xxx_gpio_configure(unsigned gpio, int dir, int inv, int func) +int gpio_direction_input(unsigned gpio) { - void __iomem *conf = ns9xxx_gpio_get_gconfaddr(gpio); - u32 confval; - unsigned long flags; - - spin_lock_irqsave(&gpio_lock, flags); - - confval = __raw_readl(conf); - REGSETIM_IDX(confval, BBU_GCONFx, DIR, gpio & 7, dir); - REGSETIM_IDX(confval, BBU_GCONFx, INV, gpio & 7, inv); - REGSETIM_IDX(confval, BBU_GCONFx, FUNC, gpio & 7, func); - __raw_writel(confval, conf); + if (likely(ns9xxx_valid_gpio(gpio))) { + int ret = -EINVAL; + unsigned long flags; - spin_unlock_irqrestore(&gpio_lock, flags); + spin_lock_irqsave(&gpio_lock, flags); +#if defined(CONFIG_PROCESSOR_NS9360) + if (processor_is_ns9360()) + ret = __ns9360_gpio_configure(gpio, 0, 0, 3); + else +#endif + BUG(); - return 0; -} + spin_unlock_irqrestore(&gpio_lock, flags); -int ns9xxx_gpio_configure(unsigned gpio, int inv, int func) -{ - if (likely(ns9xxx_valid_gpio(gpio))) { - if (func == 3) { - printk(KERN_WARNING "use gpio_direction_input " - "or gpio_direction_output\n"); - return -EINVAL; - } else - return __ns9xxx_gpio_configure(gpio, 0, inv, func); - } else - return -EINVAL; -} -EXPORT_SYMBOL(ns9xxx_gpio_configure); + return ret; -int gpio_direction_input(unsigned gpio) -{ - if (likely(ns9xxx_valid_gpio(gpio))) { - return __ns9xxx_gpio_configure(gpio, 0, 0, 3); } else return -EINVAL; } @@ -149,9 +94,22 @@ EXPORT_SYMBOL(gpio_direction_input); int gpio_direction_output(unsigned gpio, int value) { if (likely(ns9xxx_valid_gpio(gpio))) { + int ret = -EINVAL; + unsigned long flags; + gpio_set_value(gpio, value); - return __ns9xxx_gpio_configure(gpio, 1, 0, 3); + spin_lock_irqsave(&gpio_lock, flags); +#if defined(CONFIG_PROCESSOR_NS9360) + if (processor_is_ns9360()) + ret = __ns9360_gpio_configure(gpio, 1, 0, 3); + else +#endif + BUG(); + + spin_unlock_irqrestore(&gpio_lock, flags); + + return ret; } else return -EINVAL; } @@ -159,31 +117,28 @@ EXPORT_SYMBOL(gpio_direction_output); int gpio_get_value(unsigned gpio) { - void __iomem *stat = ns9xxx_gpio_get_gstataddr(gpio); - int ret; - - ret = 1 & (__raw_readl(stat) >> (gpio & 31)); - - return ret; +#if defined(CONFIG_PROCESSOR_NS9360) + if (processor_is_ns9360()) + return ns9360_gpio_get_value(gpio); + else +#endif + { + BUG(); + return -EINVAL; + } } EXPORT_SYMBOL(gpio_get_value); void gpio_set_value(unsigned gpio, int value) { - void __iomem *ctrl = ns9xxx_gpio_get_gctrladdr(gpio); - u32 ctrlval; unsigned long flags; - spin_lock_irqsave(&gpio_lock, flags); - - ctrlval = __raw_readl(ctrl); - - if (value) - ctrlval |= 1 << (gpio & 31); +#if defined(CONFIG_PROCESSOR_NS9360) + if (processor_is_ns9360()) + ns9360_gpio_set_value(gpio, value); else - ctrlval &= ~(1 << (gpio & 31)); - - __raw_writel(ctrlval, ctrl); +#endif + BUG(); spin_unlock_irqrestore(&gpio_lock, flags); } diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c index 00001b874e9..d4a583cc44c 100644 --- a/arch/arm/mach-ns9xxx/irq.c +++ b/arch/arm/mach-ns9xxx/irq.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include @@ -67,7 +67,7 @@ void __init ns9xxx_init_irq(void) for (i = 0; i < 32; ++i) __raw_writel(i, SYS_IVA(i)); - for (i = IRQ_WATCHDOG; i <= IRQ_EXT3; ++i) { + for (i = 0; i <= 31; ++i) { set_irq_chip(i, &ns9xxx_chip); set_irq_handler(i, handle_level_irq); set_irq_flags(i, IRQF_VALID); diff --git a/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c b/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c index 760c9d0db7c..9623fff6b3b 100644 --- a/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c +++ b/arch/arm/mach-ns9xxx/mach-cc9p9360dev.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-ns9xxx/mach-cc9p9360dev.c * - * Copyright (C) 2006 by Digi International Inc. + * Copyright (C) 2006,2007 by Digi International Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify it @@ -11,12 +11,14 @@ #include #include +#include + #include "board-a9m9750dev.h" #include "generic.h" static void __init mach_cc9p9360dev_map_io(void) { - ns9xxx_map_io(); + ns9360_map_io(); board_a9m9750dev_map_io(); } @@ -36,6 +38,6 @@ MACHINE_START(CC9P9360DEV, "Digi ConnectCore 9P 9360 on an A9M9750 Devboard") .map_io = mach_cc9p9360dev_map_io, .init_irq = mach_cc9p9360dev_init_irq, .init_machine = mach_cc9p9360dev_init_machine, - .timer = &ns9xxx_timer, + .timer = &ns9360_timer, .boot_params = 0x100, MACHINE_END diff --git a/arch/arm/mach-ns9xxx/mach-cc9p9360js.c b/arch/arm/mach-ns9xxx/mach-cc9p9360js.c index 85c8b41105c..fcc815bdd29 100644 --- a/arch/arm/mach-ns9xxx/mach-cc9p9360js.c +++ b/arch/arm/mach-ns9xxx/mach-cc9p9360js.c @@ -1,7 +1,7 @@ /* * arch/arm/mach-ns9xxx/mach-cc9p9360js.c * - * Copyright (C) 2006 by Digi International Inc. + * Copyright (C) 2006,2007 by Digi International Inc. * All rights reserved. * * This program is free software; you can redistribute it and/or modify it @@ -11,6 +11,8 @@ #include #include +#include + #include "board-jscc9p9360.h" #include "generic.h" @@ -21,9 +23,9 @@ static void __init mach_cc9p9360js_init_machine(void) } MACHINE_START(CC9P9360JS, "Digi ConnectCore 9P 9360 on an JSCC9P9360 Devboard") - .map_io = ns9xxx_map_io, + .map_io = ns9360_map_io, .init_irq = ns9xxx_init_irq, .init_machine = mach_cc9p9360js_init_machine, - .timer = &ns9xxx_timer, + .timer = &ns9360_timer, .boot_params = 0x100, MACHINE_END diff --git a/arch/arm/mach-ns9xxx/processor-ns9360.c b/arch/arm/mach-ns9xxx/processor-ns9360.c new file mode 100644 index 00000000000..2bee0b7fccb --- /dev/null +++ b/arch/arm/mach-ns9xxx/processor-ns9360.c @@ -0,0 +1,54 @@ +/* + * arch/arm/mach-ns9xxx/processor-ns9360.c + * + * Copyright (C) 2007 by Digi International Inc. + * All rights reserved. + * + * 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 + +void ns9360_reset(char mode) +{ + u32 reg; + + reg = __raw_readl(SYS_PLL) >> 16; + REGSET(reg, SYS_PLL, SWC, YES); + __raw_writel(reg, SYS_PLL); +} + +#define CRYSTAL 29491200 /* Hz */ +unsigned long ns9360_systemclock(void) +{ + u32 pll = __raw_readl(SYS_PLL); + return CRYSTAL * (REGGETIM(pll, SYS_PLL, ND) + 1) + >> REGGETIM(pll, SYS_PLL, FS); +} + +static struct map_desc ns9360_io_desc[] __initdata = { + { /* BBus */ + .virtual = io_p2v(0x90000000), + .pfn = __phys_to_pfn(0x90000000), + .length = 0x00700000, + .type = MT_DEVICE, + }, { /* AHB */ + .virtual = io_p2v(0xa0100000), + .pfn = __phys_to_pfn(0xa0100000), + .length = 0x00900000, + .type = MT_DEVICE, + }, +}; + +void __init ns9360_map_io(void) +{ + iotable_init(ns9360_io_desc, ARRAY_SIZE(ns9360_io_desc)); +} diff --git a/arch/arm/mach-ns9xxx/time-ns9360.c b/arch/arm/mach-ns9xxx/time-ns9360.c new file mode 100644 index 00000000000..4d573c9793e --- /dev/null +++ b/arch/arm/mach-ns9xxx/time-ns9360.c @@ -0,0 +1,185 @@ +/* + * arch/arm/mach-ns9xxx/time-ns9360.c + * + * Copyright (C) 2006,2007 by Digi International Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "generic.h" + +#define TIMER_CLOCKSOURCE 0 +#define TIMER_CLOCKEVENT 1 +static u32 latch; + +static cycle_t ns9360_clocksource_read(void) +{ + return __raw_readl(SYS_TR(TIMER_CLOCKSOURCE)); +} + +static struct clocksource ns9360_clocksource = { + .name = "ns9360-timer" __stringify(TIMER_CLOCKSOURCE), + .rating = 300, + .read = ns9360_clocksource_read, + .mask = CLOCKSOURCE_MASK(32), + .shift = 20, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void ns9360_clockevent_setmode(enum clock_event_mode mode, + struct clock_event_device *clk) +{ + u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT)); + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + __raw_writel(latch, SYS_TRC(TIMER_CLOCKEVENT)); + REGSET(tc, SYS_TCx, REN, EN); + REGSET(tc, SYS_TCx, INTS, EN); + REGSET(tc, SYS_TCx, TEN, EN); + break; + + case CLOCK_EVT_MODE_ONESHOT: + REGSET(tc, SYS_TCx, REN, DIS); + REGSET(tc, SYS_TCx, INTS, EN); + + /* fall through */ + + case CLOCK_EVT_MODE_UNUSED: + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_RESUME: + default: + REGSET(tc, SYS_TCx, TEN, DIS); + break; + } + + __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT)); +} + +static int ns9360_clockevent_setnextevent(unsigned long evt, + struct clock_event_device *clk) +{ + u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT)); + + if (REGGET(tc, SYS_TCx, TEN)) { + REGSET(tc, SYS_TCx, TEN, DIS); + __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT)); + } + + REGSET(tc, SYS_TCx, TEN, EN); + + __raw_writel(evt, SYS_TRC(TIMER_CLOCKEVENT)); + + __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT)); + + return 0; +} + +static struct clock_event_device ns9360_clockevent_device = { + .name = "ns9360-timer" __stringify(TIMER_CLOCKEVENT), + .shift = 20, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_mode = ns9360_clockevent_setmode, + .set_next_event = ns9360_clockevent_setnextevent, +}; + +static irqreturn_t ns9360_clockevent_handler(int irq, void *dev_id) +{ + int timerno = irq - IRQ_NS9360_TIMER0; + u32 tc; + + struct clock_event_device *evt = &ns9360_clockevent_device; + + /* clear irq */ + tc = __raw_readl(SYS_TC(timerno)); + if (REGGET(tc, SYS_TCx, REN) == SYS_TCx_REN_DIS) { + REGSET(tc, SYS_TCx, TEN, DIS); + __raw_writel(tc, SYS_TC(timerno)); + } + REGSET(tc, SYS_TCx, INTC, SET); + __raw_writel(tc, SYS_TC(timerno)); + REGSET(tc, SYS_TCx, INTC, UNSET); + __raw_writel(tc, SYS_TC(timerno)); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct irqaction ns9360_clockevent_action = { + .name = "ns9360-timer" __stringify(TIMER_CLOCKEVENT), + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, + .handler = ns9360_clockevent_handler, +}; + +static void __init ns9360_timer_init(void) +{ + int tc; + + tc = __raw_readl(SYS_TC(TIMER_CLOCKSOURCE)); + if (REGGET(tc, SYS_TCx, TEN)) { + REGSET(tc, SYS_TCx, TEN, DIS); + __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE)); + } + + __raw_writel(0, SYS_TRC(TIMER_CLOCKSOURCE)); + + REGSET(tc, SYS_TCx, TEN, EN); + REGSET(tc, SYS_TCx, TDBG, STOP); + REGSET(tc, SYS_TCx, TLCS, CPU); + REGSET(tc, SYS_TCx, TM, IEE); + REGSET(tc, SYS_TCx, INTS, DIS); + REGSET(tc, SYS_TCx, UDS, UP); + REGSET(tc, SYS_TCx, TSZ, 32); + REGSET(tc, SYS_TCx, REN, EN); + + __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE)); + + ns9360_clocksource.mult = clocksource_hz2mult(ns9360_cpuclock(), + ns9360_clocksource.shift); + + clocksource_register(&ns9360_clocksource); + + latch = SH_DIV(ns9360_cpuclock(), HZ, 0); + + tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT)); + REGSET(tc, SYS_TCx, TEN, DIS); + REGSET(tc, SYS_TCx, TDBG, STOP); + REGSET(tc, SYS_TCx, TLCS, CPU); + REGSET(tc, SYS_TCx, TM, IEE); + REGSET(tc, SYS_TCx, INTS, DIS); + REGSET(tc, SYS_TCx, UDS, DOWN); + REGSET(tc, SYS_TCx, TSZ, 32); + REGSET(tc, SYS_TCx, REN, EN); + __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT)); + + ns9360_clockevent_device.mult = div_sc(ns9360_cpuclock(), + NSEC_PER_SEC, ns9360_clockevent_device.shift); + ns9360_clockevent_device.max_delta_ns = + clockevent_delta2ns(-1, &ns9360_clockevent_device); + ns9360_clockevent_device.min_delta_ns = + clockevent_delta2ns(1, &ns9360_clockevent_device); + + ns9360_clockevent_device.cpumask = cpumask_of_cpu(0); + clockevents_register_device(&ns9360_clockevent_device); + + setup_irq(IRQ_NS9360_TIMER0 + TIMER_CLOCKEVENT, + &ns9360_clockevent_action); +} + +struct sys_timer ns9360_timer = { + .init = ns9360_timer_init, +}; diff --git a/arch/arm/mach-ns9xxx/time.c b/arch/arm/mach-ns9xxx/time.c deleted file mode 100644 index c3dd1f4acb9..00000000000 --- a/arch/arm/mach-ns9xxx/time.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * arch/arm/mach-ns9xxx/time.c - * - * Copyright (C) 2006 by Digi International Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "generic.h" - -#define TIMER_CLOCKSOURCE 0 -#define TIMER_CLOCKEVENT 1 -static u32 latch; - -static cycle_t ns9xxx_clocksource_read(void) -{ - return __raw_readl(SYS_TR(TIMER_CLOCKSOURCE)); -} - -static struct clocksource ns9xxx_clocksource = { - .name = "ns9xxx-timer" __stringify(TIMER_CLOCKSOURCE), - .rating = 300, - .read = ns9xxx_clocksource_read, - .mask = CLOCKSOURCE_MASK(32), - .shift = 20, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static void ns9xxx_clockevent_setmode(enum clock_event_mode mode, - struct clock_event_device *clk) -{ - u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT)); - - switch(mode) { - case CLOCK_EVT_MODE_PERIODIC: - __raw_writel(latch, SYS_TRC(TIMER_CLOCKEVENT)); - REGSET(tc, SYS_TCx, REN, EN); - REGSET(tc, SYS_TCx, INTS, EN); - REGSET(tc, SYS_TCx, TEN, EN); - break; - - case CLOCK_EVT_MODE_ONESHOT: - REGSET(tc, SYS_TCx, REN, DIS); - REGSET(tc, SYS_TCx, INTS, EN); - - /* fall through */ - - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_RESUME: - default: - REGSET(tc, SYS_TCx, TEN, DIS); - break; - } - - __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT)); -} - -static int ns9xxx_clockevent_setnextevent(unsigned long evt, - struct clock_event_device *clk) -{ - u32 tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT)); - - if (REGGET(tc, SYS_TCx, TEN)) { - REGSET(tc, SYS_TCx, TEN, DIS); - __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT)); - } - - REGSET(tc, SYS_TCx, TEN, EN); - - __raw_writel(evt, SYS_TRC(TIMER_CLOCKEVENT)); - - __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT)); - - return 0; -} - -static struct clock_event_device ns9xxx_clockevent_device = { - .name = "ns9xxx-timer" __stringify(TIMER_CLOCKEVENT), - .shift = 20, - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .set_mode = ns9xxx_clockevent_setmode, - .set_next_event = ns9xxx_clockevent_setnextevent, -}; - -static irqreturn_t ns9xxx_clockevent_handler(int irq, void *dev_id) -{ - int timerno = irq - IRQ_TIMER0; - u32 tc; - - struct clock_event_device *evt = &ns9xxx_clockevent_device; - - /* clear irq */ - tc = __raw_readl(SYS_TC(timerno)); - if (REGGET(tc, SYS_TCx, REN) == SYS_TCx_REN_DIS) { - REGSET(tc, SYS_TCx, TEN, DIS); - __raw_writel(tc, SYS_TC(timerno)); - } - REGSET(tc, SYS_TCx, INTC, SET); - __raw_writel(tc, SYS_TC(timerno)); - REGSET(tc, SYS_TCx, INTC, UNSET); - __raw_writel(tc, SYS_TC(timerno)); - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct irqaction ns9xxx_clockevent_action = { - .name = "ns9xxx-timer" __stringify(TIMER_CLOCKEVENT), - .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, - .handler = ns9xxx_clockevent_handler, -}; - -static void __init ns9xxx_timer_init(void) -{ - int tc; - - tc = __raw_readl(SYS_TC(TIMER_CLOCKSOURCE)); - if (REGGET(tc, SYS_TCx, TEN)) { - REGSET(tc, SYS_TCx, TEN, DIS); - __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE)); - } - - __raw_writel(0, SYS_TRC(TIMER_CLOCKSOURCE)); - - REGSET(tc, SYS_TCx, TEN, EN); - REGSET(tc, SYS_TCx, TDBG, STOP); - REGSET(tc, SYS_TCx, TLCS, CPU); - REGSET(tc, SYS_TCx, TM, IEE); - REGSET(tc, SYS_TCx, INTS, DIS); - REGSET(tc, SYS_TCx, UDS, UP); - REGSET(tc, SYS_TCx, TSZ, 32); - REGSET(tc, SYS_TCx, REN, EN); - - __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE)); - - ns9xxx_clocksource.mult = clocksource_hz2mult(ns9xxx_cpuclock(), - ns9xxx_clocksource.shift); - - clocksource_register(&ns9xxx_clocksource); - - latch = SH_DIV(ns9xxx_cpuclock(), HZ, 0); - - tc = __raw_readl(SYS_TC(TIMER_CLOCKEVENT)); - REGSET(tc, SYS_TCx, TEN, DIS); - REGSET(tc, SYS_TCx, TDBG, STOP); - REGSET(tc, SYS_TCx, TLCS, CPU); - REGSET(tc, SYS_TCx, TM, IEE); - REGSET(tc, SYS_TCx, INTS, DIS); - REGSET(tc, SYS_TCx, UDS, DOWN); - REGSET(tc, SYS_TCx, TSZ, 32); - REGSET(tc, SYS_TCx, REN, EN); - __raw_writel(tc, SYS_TC(TIMER_CLOCKEVENT)); - - ns9xxx_clockevent_device.mult = div_sc(ns9xxx_cpuclock(), - NSEC_PER_SEC, ns9xxx_clockevent_device.shift); - ns9xxx_clockevent_device.max_delta_ns = - clockevent_delta2ns(-1, &ns9xxx_clockevent_device); - ns9xxx_clockevent_device.min_delta_ns = - clockevent_delta2ns(1, &ns9xxx_clockevent_device); - - ns9xxx_clockevent_device.cpumask = cpumask_of_cpu(0); - clockevents_register_device(&ns9xxx_clockevent_device); - - setup_irq(IRQ_TIMER0 + TIMER_CLOCKEVENT, &ns9xxx_clockevent_action); -} - -struct sys_timer ns9xxx_timer = { - .init = ns9xxx_timer_init, -}; -- cgit v1.2.3 From 5e69b945f20aec17bf057acbb61b6682461e7149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 29 Feb 2008 13:27:53 +0100 Subject: ns9xxx: make use of the chip's irq priorisation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The irq controller automatically masks the current and all lower prioritised tasks until the current irq is acked. Signed-off-by: Uwe Kleine-König --- arch/arm/mach-ns9xxx/irq.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'arch/arm/mach-ns9xxx') diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c index d4a583cc44c..7ddc8fde774 100644 --- a/arch/arm/mach-ns9xxx/irq.c +++ b/arch/arm/mach-ns9xxx/irq.c @@ -9,6 +9,7 @@ * the Free Software Foundation. */ #include +#include #include #include #include @@ -52,6 +53,43 @@ static struct irq_chip ns9xxx_chip = { .unmask = ns9xxx_unmask_irq, }; +#if 0 +#define handle_irq handle_level_irq +#else +void handle_prio_irq(unsigned int irq, struct irq_desc *desc) +{ + unsigned int cpu = smp_processor_id(); + struct irqaction *action; + irqreturn_t action_ret; + + spin_lock(&desc->lock); + + if (unlikely(desc->status & IRQ_INPROGRESS)) + goto out_unlock; + + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); + kstat_cpu(cpu).irqs[irq]++; + + action = desc->action; + if (unlikely(!action || (desc->status & IRQ_DISABLED))) + goto out_unlock; + + desc->status |= IRQ_INPROGRESS; + spin_unlock(&desc->lock); + + action_ret = handle_IRQ_event(irq, action); + + spin_lock(&desc->lock); + desc->status &= ~IRQ_INPROGRESS; + if (!(desc->status & IRQ_DISABLED) && desc->chip->ack) + desc->chip->ack(irq); + +out_unlock: + spin_unlock(&desc->lock); +} +#define handle_irq handle_prio_irq +#endif + void __init ns9xxx_init_irq(void) { int i; @@ -69,7 +107,7 @@ void __init ns9xxx_init_irq(void) for (i = 0; i <= 31; ++i) { set_irq_chip(i, &ns9xxx_chip); - set_irq_handler(i, handle_level_irq); + set_irq_handler(i, handle_irq); set_irq_flags(i, IRQF_VALID); } } -- cgit v1.2.3 From ed6f5987235c628e1041311d7c1efdf659e2dad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 11 Dec 2007 16:52:50 +0100 Subject: ns9xxx: add support for irq priorisation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit prio2irq(0) is the highest prioritized interrupt. For now there is no binary change intended. If you intend to change the priorisation, you have to assert: ∀ x ∈ {0, 1, ⋯ 31}: (irq2prio ∘ prio2irq)(x) = x Signed-off-by: Uwe Kleine-König --- arch/arm/mach-ns9xxx/irq.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'arch/arm/mach-ns9xxx') diff --git a/arch/arm/mach-ns9xxx/irq.c b/arch/arm/mach-ns9xxx/irq.c index 7ddc8fde774..36e5835e609 100644 --- a/arch/arm/mach-ns9xxx/irq.c +++ b/arch/arm/mach-ns9xxx/irq.c @@ -19,12 +19,17 @@ #include "generic.h" +/* simple interrupt prio table: prio(x) < prio(y) <=> x < y */ +#define irq2prio(i) (i) +#define prio2irq(p) (p) + static void ns9xxx_mask_irq(unsigned int irq) { /* XXX: better use cpp symbols */ - u32 ic = __raw_readl(SYS_IC(irq / 4)); - ic &= ~(1 << (7 + 8 * (3 - (irq & 3)))); - __raw_writel(ic, SYS_IC(irq / 4)); + int prio = irq2prio(irq); + u32 ic = __raw_readl(SYS_IC(prio / 4)); + ic &= ~(1 << (7 + 8 * (3 - (prio & 3)))); + __raw_writel(ic, SYS_IC(prio / 4)); } static void ns9xxx_ack_irq(unsigned int irq) @@ -41,9 +46,10 @@ static void ns9xxx_maskack_irq(unsigned int irq) static void ns9xxx_unmask_irq(unsigned int irq) { /* XXX: better use cpp symbols */ - u32 ic = __raw_readl(SYS_IC(irq / 4)); - ic |= 1 << (7 + 8 * (3 - (irq & 3))); - __raw_writel(ic, SYS_IC(irq / 4)); + int prio = irq2prio(irq); + u32 ic = __raw_readl(SYS_IC(prio / 4)); + ic |= 1 << (7 + 8 * (3 - (prio & 3))); + __raw_writel(ic, SYS_IC(prio / 4)); } static struct irq_chip ns9xxx_chip = { @@ -96,14 +102,14 @@ void __init ns9xxx_init_irq(void) /* disable all IRQs */ for (i = 0; i < 8; ++i) - __raw_writel((4 * i) << 24 | (4 * i + 1) << 16 | - (4 * i + 2) << 8 | (4 * i + 3), SYS_IC(i)); + __raw_writel(prio2irq(4 * i) << 24 | + prio2irq(4 * i + 1) << 16 | + prio2irq(4 * i + 2) << 8 | + prio2irq(4 * i + 3), + SYS_IC(i)); - /* simple interrupt prio table: - * prio(x) < prio(y) <=> x < y - */ for (i = 0; i < 32; ++i) - __raw_writel(i, SYS_IVA(i)); + __raw_writel(prio2irq(i), SYS_IVA(i)); for (i = 0; i <= 31; ++i) { set_irq_chip(i, &ns9xxx_chip); -- cgit v1.2.3 From 04c366f06341259c88886a0d359e3597ba4c23f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Wed, 6 Feb 2008 15:22:56 +0100 Subject: ns9xxx: add clock api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Uwe Kleine-König --- arch/arm/mach-ns9xxx/Makefile | 2 +- arch/arm/mach-ns9xxx/clock.c | 215 ++++++++++++++++++++++++++++++++++++++++++ arch/arm/mach-ns9xxx/clock.h | 35 +++++++ 3 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-ns9xxx/clock.c create mode 100644 arch/arm/mach-ns9xxx/clock.h (limited to 'arch/arm/mach-ns9xxx') diff --git a/arch/arm/mach-ns9xxx/Makefile b/arch/arm/mach-ns9xxx/Makefile index 67a9e30c878..41efaf9ad50 100644 --- a/arch/arm/mach-ns9xxx/Makefile +++ b/arch/arm/mach-ns9xxx/Makefile @@ -1,4 +1,4 @@ -obj-y := irq.o generic.o gpio.o +obj-y := clock.o generic.o gpio.o irq.o obj-$(CONFIG_MACH_CC9P9360DEV) += mach-cc9p9360dev.o obj-$(CONFIG_MACH_CC9P9360JS) += mach-cc9p9360js.o diff --git a/arch/arm/mach-ns9xxx/clock.c b/arch/arm/mach-ns9xxx/clock.c new file mode 100644 index 00000000000..f8639161068 --- /dev/null +++ b/arch/arm/mach-ns9xxx/clock.c @@ -0,0 +1,215 @@ +/* + * arch/arm/mach-ns9xxx/clock.c + * + * Copyright (C) 2007 by Digi International Inc. + * All rights reserved. + * + * 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 "clock.h" + +static LIST_HEAD(clocks); +static DEFINE_SPINLOCK(clk_lock); + +struct clk *clk_get(struct device *dev, const char *id) +{ + struct clk *p, *ret = NULL, *retgen = NULL; + unsigned long flags; + int idno; + + if (dev == NULL || dev->bus != &platform_bus_type) + idno = -1; + else + idno = to_platform_device(dev)->id; + + spin_lock_irqsave(&clk_lock, flags); + list_for_each_entry(p, &clocks, node) { + if (strcmp(id, p->name) == 0) { + if (p->id == idno) { + if (!try_module_get(p->owner)) + continue; + ret = p; + break; + } else if (p->id == -1) + /* remember match with id == -1 in case there is + * no clock for idno */ + retgen = p; + } + } + + if (!ret && retgen && try_module_get(retgen->owner)) + ret = retgen; + + if (ret) + ++ret->refcount; + + spin_unlock_irqrestore(&clk_lock, flags); + + return ret ? ret : ERR_PTR(-ENOENT); +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ + module_put(clk->owner); + --clk->refcount; +} +EXPORT_SYMBOL(clk_put); + +static int clk_enable_unlocked(struct clk *clk) +{ + int ret = 0; + if (clk->parent) { + ret = clk_enable_unlocked(clk->parent); + if (ret) + return ret; + } + + if (clk->usage++ == 0 && clk->endisable) + ret = clk->endisable(clk, 1); + + return ret; +} + +int clk_enable(struct clk *clk) +{ + int ret; + unsigned long flags; + + spin_lock_irqsave(&clk_lock, flags); + + ret = clk_enable_unlocked(clk); + + spin_unlock_irqrestore(&clk_lock, flags); + + return ret; +} +EXPORT_SYMBOL(clk_enable); + +static void clk_disable_unlocked(struct clk *clk) +{ + if (--clk->usage == 0 && clk->endisable) + clk->endisable(clk, 0); + + if (clk->parent) + clk_disable_unlocked(clk->parent); +} + +void clk_disable(struct clk *clk) +{ + unsigned long flags; + + spin_lock_irqsave(&clk_lock, flags); + + clk_disable_unlocked(clk); + + spin_unlock_irqrestore(&clk_lock, flags); +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + if (clk->get_rate) + return clk->get_rate(clk); + + if (clk->rate) + return clk->rate; + + if (clk->parent) + return clk_get_rate(clk->parent); + + return 0; +} +EXPORT_SYMBOL(clk_get_rate); + +int clk_register(struct clk *clk) +{ + unsigned long flags; + + spin_lock_irqsave(&clk_lock, flags); + + list_add(&clk->node, &clocks); + + if (clk->parent) + ++clk->parent->refcount; + + spin_unlock_irqrestore(&clk_lock, flags); + + return 0; +} + +int clk_unregister(struct clk *clk) +{ + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&clk_lock, flags); + + if (clk->usage || clk->refcount) + ret = -EBUSY; + else + list_del(&clk->node); + + if (clk->parent) + --clk->parent->refcount; + + spin_unlock_irqrestore(&clk_lock, flags); + + return ret; +} + +#if defined CONFIG_DEBUG_FS + +#include +#include + +static int clk_debugfs_show(struct seq_file *s, void *null) +{ + unsigned long flags; + struct clk *p; + + spin_lock_irqsave(&clk_lock, flags); + + list_for_each_entry(p, &clocks, node) + seq_printf(s, "%s.%d: usage=%lu refcount=%lu rate=%lu\n", + p->name, p->id, p->usage, p->refcount, + p->usage ? clk_get_rate(p) : 0); + + spin_unlock_irqrestore(&clk_lock, flags); + + return 0; +} + +static int clk_debugfs_open(struct inode *inode, struct file *file) +{ + return single_open(file, clk_debugfs_show, NULL); +} + +static struct file_operations clk_debugfs_operations = { + .open = clk_debugfs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init clk_debugfs_init(void) +{ + struct dentry *dentry; + + dentry = debugfs_create_file("clk", S_IFREG | S_IRUGO, NULL, NULL, + &clk_debugfs_operations); + return IS_ERR(dentry) ? PTR_ERR(dentry) : 0; +} +subsys_initcall(clk_debugfs_init); + +#endif /* if defined CONFIG_DEBUG_FS */ diff --git a/arch/arm/mach-ns9xxx/clock.h b/arch/arm/mach-ns9xxx/clock.h new file mode 100644 index 00000000000..b86c30dd79e --- /dev/null +++ b/arch/arm/mach-ns9xxx/clock.h @@ -0,0 +1,35 @@ +/* + * arch/arm/mach-ns9xxx/clock.h + * + * Copyright (C) 2007 by Digi International Inc. + * All rights reserved. + * + * 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 __NS9XXX_CLOCK_H +#define __NS9XXX_CLOCK_H + +#include + +struct clk { + struct module *owner; + const char *name; + int id; + + struct clk *parent; + + unsigned long rate; + int (*endisable)(struct clk *, int enable); + unsigned long (*get_rate)(struct clk *); + + struct list_head node; + unsigned long refcount; + unsigned long usage; +}; + +int clk_register(struct clk *clk); +int clk_unregister(struct clk *clk); + +#endif /* ifndef __NS9XXX_CLOCK_H */ -- cgit v1.2.3