diff options
Diffstat (limited to 'arch')
41 files changed, 632 insertions, 1992 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 61d949e9233f..29bb2aca02d4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -429,12 +429,15 @@ config ARCH_IXP4XX depends on MMU select ARCH_HAS_DMA_SET_COHERENT_MASK select ARCH_SUPPORTS_BIG_ENDIAN - select CLKSRC_MMIO select CPU_XSCALE select DMABOUNCE if PCI select GENERIC_CLOCKEVENTS + select GENERIC_IRQ_MULTI_HANDLER + select GPIO_IXP4XX select GPIOLIB select HAVE_PCI + select IXP4XX_IRQ + select IXP4XX_TIMER select NEED_MACH_IO_H select USB_EHCI_BIG_ENDIAN_DESC select USB_EHCI_BIG_ENDIAN_MMIO diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index f4f5aeaf3298..7af4e3289a89 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -229,6 +229,9 @@ dtb-$(CONFIG_ARCH_HIX5HD2) += \ dtb-$(CONFIG_ARCH_INTEGRATOR) += \ integratorap.dtb \ integratorcp.dtb +dtb-$(CONFIG_ARCH_IXP4XX) += \ + intel-ixp42x-linksys-nslu2.dtb \ + intel-ixp43x-gateworks-gw2358.dtb dtb-$(CONFIG_ARCH_KEYSTONE) += \ keystone-k2hk-evm.dtb \ keystone-k2l-evm.dtb \ diff --git a/arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts b/arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts new file mode 100644 index 000000000000..8fcd95805ff4 --- /dev/null +++ b/arch/arm/boot/dts/intel-ixp42x-linksys-nslu2.dts @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: ISC +/* + * Device Tree file for Linksys NSLU2 + */ + +/dts-v1/; + +#include "intel-ixp42x.dtsi" +#include <dt-bindings/input/input.h> + +/ { + model = "Linksys NSLU2 (Network Storage Link for USB 2.0 Disk Drives)"; + compatible = "linksys,nslu2", "intel,ixp42x"; + #address-cells = <1>; + #size-cells = <1>; + + memory@0 { + /* 32 MB SDRAM */ + device_type = "memory"; + reg = <0x00000000 0x2000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200n8 root=/dev/mtdblock2 rw rootfstype=squashfs,jffs2 rootwait"; + stdout-path = "uart0:115200n8"; + }; + + aliases { + serial0 = &uart0; + }; + + leds { + compatible = "gpio-leds"; + led-status { + label = "nslu2:red:status"; + gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; + default-state = "on"; + linux,default-trigger = "heartbeat"; + }; + led-ready { + label = "nslu2:green:ready"; + gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>; + default-state = "on"; + }; + led-disk-1 { + label = "nslu2:green:disk-1"; + gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + led-disk-2 { + label = "nslu2:green:disk-2"; + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + default-state = "off"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + button-power { + wakeup-source; + linux,code = <KEY_POWER>; + label = "power"; + gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>; + }; + button-reset { + wakeup-source; + linux,code = <KEY_ESC>; + label = "reset"; + gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + }; + }; + + i2c { + compatible = "i2c-gpio"; + sda-gpios = <&gpio0 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio0 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + #address-cells = <1>; + #size-cells = <0>; + + rtc@6f { + compatible = "xicor,x1205"; + reg = <0x6f>; + }; + }; + + gpio-poweroff { + compatible = "gpio-poweroff"; + gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + timeout-ms = <5000>; + }; + + /* The first 16MB region on the expansion bus */ + flash@50000000 { + compatible = "intel,ixp4xx-flash", "cfi-flash"; + bank-width = <2>; + /* + * 8 MB of Flash in 0x20000 byte blocks + * mapped in at 0x50000000 + */ + reg = <0x50000000 0x800000>; + + partitions { + compatible = "redboot-fis"; + /* Eraseblock at 0x7e0000 */ + fis-index-block = <0x3f>; + }; + }; +}; diff --git a/arch/arm/boot/dts/intel-ixp42x.dtsi b/arch/arm/boot/dts/intel-ixp42x.dtsi new file mode 100644 index 000000000000..a9622ca850cc --- /dev/null +++ b/arch/arm/boot/dts/intel-ixp42x.dtsi @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: ISC +/* + * Device Tree file for Intel XScale Network Processors + * in the IXP 42x series. This series has 32 interrupts. + */ +#include "intel-ixp4xx.dtsi" + +/ { + soc { + interrupt-controller@c8003000 { + compatible = "intel,ixp42x-interrupt"; + }; + + /* + * This is the USB Device Mode (UDC) controller, which is used + * to present the IXP4xx as a device on a USB bus. + */ + usb@c800b000 { + compatible = "intel,ixp4xx-udc"; + reg = <0xc800b000 0x1000>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358.dts b/arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358.dts new file mode 100644 index 000000000000..ba1163a1e1e7 --- /dev/null +++ b/arch/arm/boot/dts/intel-ixp43x-gateworks-gw2358.dts @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: ISC +/* + * Device Tree file for Gateworks IXP43x-based Cambria GW2358 + */ + +/dts-v1/; + +#include "intel-ixp43x.dtsi" + +/ { + model = "Gateworks Cambria GW2358"; + compatible = "gateworks,gw2358", "intel,ixp43x"; + #address-cells = <1>; + #size-cells = <1>; + + memory@0 { + /* 128 MB SDRAM */ + device_type = "memory"; + reg = <0x00000000 0x8000000>; + }; + + chosen { + bootargs = "console=ttyS0,115200n8 root=/dev/mtdblock2 rw rootfstype=squashfs,jffs2 rootwait"; + stdout-path = "uart0:115200n8"; + }; + + aliases { + serial0 = &uart0; + }; + + leds { + compatible = "gpio-leds"; + led-user { + label = "gw2358:green:LED"; + gpios = <&pld1 0 GPIO_ACTIVE_LOW>; + default-state = "on"; + linux,default-trigger = "heartbeat"; + }; + }; + + + i2c { + compatible = "i2c-gpio"; + sda-gpios = <&gpio0 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + scl-gpios = <&gpio0 6 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>; + #address-cells = <1>; + #size-cells = <0>; + + hwmon@28 { + compatible = "adi,ad7418"; + reg = <0x28>; + }; + rtc: ds1672@68 { + compatible = "dallas,ds1672"; + reg = <0x68>; + }; + eeprom@51 { + compatible = "atmel,24c08"; + reg = <0x51>; + pagesize = <16>; + size = <1024>; + read-only; + }; + pld0: pld@56 { + compatible = "gateworks,pld-gpio"; + reg = <0x56>; + gpio-controller; + #gpio-cells = <2>; + }; + /* This PLD just handles the LED and user button */ + pld1: pld@57 { + compatible = "gateworks,pld-gpio"; + reg = <0x57>; + gpio-controller; + #gpio-cells = <2>; + }; + }; + + flash@50000000 { + compatible = "intel,ixp4xx-flash", "cfi-flash"; + bank-width = <2>; + /* + * 32 MB of Flash in 0x20000 byte blocks + * mapped in at 0x50000000 + */ + reg = <0x50000000 0x2000000>; + + partitions { + compatible = "redboot-fis"; + /* Eraseblock at 0x1fe0000 */ + fis-index-block = <0xff>; + }; + }; +}; diff --git a/arch/arm/boot/dts/intel-ixp43x.dtsi b/arch/arm/boot/dts/intel-ixp43x.dtsi new file mode 100644 index 000000000000..494fb2ff57a0 --- /dev/null +++ b/arch/arm/boot/dts/intel-ixp43x.dtsi @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: ISC +/* + * Device Tree file for Intel XScale Network Processors + * in the IXP 43x series. This series has 64 interrupts and adds a few more + * peripherals over the 42x series. + */ +#include "intel-ixp4xx.dtsi" + +/ { + soc { + interrupt-controller@c8003000 { + compatible = "intel,ixp43x-interrupt"; + }; + }; +}; diff --git a/arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi b/arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi new file mode 100644 index 000000000000..f8cd506659dc --- /dev/null +++ b/arch/arm/boot/dts/intel-ixp45x-ixp46x.dtsi @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: ISC +/* + * Device Tree file for Intel XScale Network Processors + * in the IXP45x and IXP46x series. This series has 64 interrupts and adds a + * few more peripherals over the 42x and 43x series so this extends the + * basic IXP4xx DTSI. + */ +#include "intel-ixp4xx.dtsi" + +/ { + soc { + interrupt-controller@c8003000 { + compatible = "intel,ixp43x-interrupt"; + }; + + /* + * This is the USB Device Mode (UDC) controller, which is used + * to present the IXP4xx as a device on a USB bus. + */ + usb@c800b000 { + compatible = "intel,ixp4xx-udc"; + reg = <0xc800b000 0x1000>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + i2c@c8011000 { + compatible = "intel,ixp4xx-i2c"; + reg = <0xc8011000 0x18>; + interrupts = <33 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm/boot/dts/intel-ixp4xx.dtsi b/arch/arm/boot/dts/intel-ixp4xx.dtsi new file mode 100644 index 000000000000..d4a09584f417 --- /dev/null +++ b/arch/arm/boot/dts/intel-ixp4xx.dtsi @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: ISC +/* + * Device Tree file for Intel XScale Network Processors + * in the IXP 4xx series. + */ +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/gpio/gpio.h> + +/ { + soc { + #address-cells = <1>; + #size-cells = <1>; + ranges; + compatible = "simple-bus"; + interrupt-parent = <&intcon>; + + qmgr: queue-manager@60000000 { + compatible = "intel,ixp4xx-ahb-queue-manager"; + reg = <0x60000000 0x4000>; + interrupts = <3 IRQ_TYPE_LEVEL_HIGH>, <4 IRQ_TYPE_LEVEL_HIGH>; + }; + + uart0: serial@c8000000 { + compatible = "intel,xscale-uart"; + reg = <0xc8000000 0x1000>; + /* + * The reg-offset and reg-shift is a side effect + * of running the platform in big endian mode. + */ + reg-offset = <3>; + reg-shift = <2>; + interrupts = <15 IRQ_TYPE_LEVEL_HIGH>; + clock-frequency = <14745600>; + no-loopback-test; + }; + + gpio0: gpio@c8004000 { + compatible = "intel,ixp4xx-gpio"; + reg = <0xc8004000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + intcon: interrupt-controller@c8003000 { + /* + * Note: no compatible string. The subvariant of the + * chip needs to define what version it is. The + * location of the interrupt controller is fixed in + * memory across all variants. + */ + reg = <0xc8003000 0x100>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + timer@c8005000 { + compatible = "intel,ixp4xx-timer"; + reg = <0xc8005000 0x100>; + interrupts = <5 IRQ_TYPE_LEVEL_HIGH>; + }; + + npe@c8006000 { + compatible = "intel,ixp4xx-network-processing-engine"; + reg = <0xc8006000 0x1000>, <0xc8007000 0x1000>, <0xc8008000 0x1000>; + }; + }; +}; diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig index fea008123eb1..83afb80d38a8 100644 --- a/arch/arm/mach-ixp4xx/Kconfig +++ b/arch/arm/mach-ixp4xx/Kconfig @@ -4,6 +4,20 @@ menu "Intel IXP4xx Implementation Options" comment "IXP4xx Platforms" +config MACH_IXP4XX_OF + bool + prompt "Devce Tree IXP4xx boards" + default y + select ARM_APPENDED_DTB # Old Redboot bootloaders deployed + select I2C + select I2C_IOP3XX + select PCI + select SERIAL_OF_PLATFORM + select TIMER_OF + select USE_OF + help + Say 'Y' here to support Device Tree-based IXP4xx platforms. + config MACH_NSLU2 bool prompt "Linksys NSLU2" @@ -222,19 +236,6 @@ config IXP4XX_INDIRECT_PCI need to use the indirect method instead. If you don't know what you need, leave this option unselected. -config IXP4XX_QMGR - tristate "IXP4xx Queue Manager support" - help - This driver supports IXP4xx built-in hardware queue manager - and is automatically selected by Ethernet and HSS drivers. - -config IXP4XX_NPE - tristate "IXP4xx Network Processor Engine support" - select FW_LOADER - help - This driver supports IXP4xx built-in network coprocessors - and is automatically selected by Ethernet and HSS drivers. - endmenu endif diff --git a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile index f09994500a34..1fa4e6605782 100644 --- a/arch/arm/mach-ixp4xx/Makefile +++ b/arch/arm/mach-ixp4xx/Makefile @@ -6,6 +6,9 @@ obj-pci-y := obj-pci-n := +# Device tree platform +obj-pci-$(CONFIG_MACH_IXP4XX_OF) += ixp4xx-of.o + obj-pci-$(CONFIG_ARCH_IXDP4XX) += ixdp425-pci.o obj-pci-$(CONFIG_MACH_AVILA) += avila-pci.o obj-pci-$(CONFIG_MACH_IXDPG425) += ixdpg425-pci.o @@ -40,5 +43,3 @@ obj-$(CONFIG_MACH_GORAMO_MLR) += goramo_mlr.o obj-$(CONFIG_MACH_ARCOM_VULCAN) += vulcan-setup.o obj-$(CONFIG_PCI) += $(obj-pci-$(CONFIG_PCI)) common-pci.o -obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx_qmgr.o -obj-$(CONFIG_IXP4XX_NPE) += ixp4xx_npe.o diff --git a/arch/arm/mach-ixp4xx/avila-pci.c b/arch/arm/mach-ixp4xx/avila-pci.c index 548c7d43ade6..9c834f0f4231 100644 --- a/arch/arm/mach-ixp4xx/avila-pci.c +++ b/arch/arm/mach-ixp4xx/avila-pci.c @@ -27,6 +27,8 @@ #include <mach/hardware.h> #include <asm/mach-types.h> +#include "irqs.h" + #define AVILA_MAX_DEV 4 #define LOFT_MAX_DEV 6 #define IRQ_LINES 4 diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c index 44cbbce6bda6..1981b33109cb 100644 --- a/arch/arm/mach-ixp4xx/avila-setup.c +++ b/arch/arm/mach-ixp4xx/avila-setup.c @@ -28,6 +28,8 @@ #include <asm/mach/arch.h> #include <asm/mach/flash.h> +#include "irqs.h" + #define AVILA_SDA_PIN 7 #define AVILA_SCL_PIN 6 diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 846e033c56fa..cc5f15679d29 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -22,41 +22,30 @@ #include <linux/serial_core.h> #include <linux/interrupt.h> #include <linux/bitops.h> -#include <linux/time.h> -#include <linux/clocksource.h> -#include <linux/clockchips.h> #include <linux/io.h> #include <linux/export.h> -#include <linux/gpio/driver.h> #include <linux/cpu.h> #include <linux/pci.h> #include <linux/sched_clock.h> +#include <linux/bitops.h> +#include <linux/irqchip/irq-ixp4xx.h> +#include <linux/platform_data/timer-ixp4xx.h> #include <mach/udc.h> #include <mach/hardware.h> #include <mach/io.h> #include <linux/uaccess.h> #include <asm/pgtable.h> #include <asm/page.h> +#include <asm/exception.h> #include <asm/irq.h> #include <asm/system_misc.h> #include <asm/mach/map.h> #include <asm/mach/irq.h> #include <asm/mach/time.h> -#define IXP4XX_TIMER_FREQ 66666000 - -/* - * The timer register doesn't allow to specify the two least significant bits of - * the timeout value and assumes them being zero. So make sure IXP4XX_LATCH is - * the best value with the two least significant bits unset. - */ -#define IXP4XX_LATCH DIV_ROUND_CLOSEST(IXP4XX_TIMER_FREQ, \ - (IXP4XX_OST_RELOAD_MASK + 1) * HZ) * \ - (IXP4XX_OST_RELOAD_MASK + 1) +#include "irqs.h" -static void __init ixp4xx_clocksource_init(void); -static void __init ixp4xx_clockevent_init(void); -static struct clock_event_device clockevent_ixp4xx; +#define IXP4XX_TIMER_FREQ 66666000 /************************************************************************* * IXP4xx chipset I/O mapping @@ -77,11 +66,6 @@ static struct map_desc ixp4xx_io_desc[] __initdata = { .pfn = __phys_to_pfn(IXP4XX_PCI_CFG_BASE_PHYS), .length = IXP4XX_PCI_CFG_REGION_SIZE, .type = MT_DEVICE - }, { /* Queue Manager */ - .virtual = (unsigned long)IXP4XX_QMGR_BASE_VIRT, - .pfn = __phys_to_pfn(IXP4XX_QMGR_BASE_PHYS), - .length = IXP4XX_QMGR_REGION_SIZE, - .type = MT_DEVICE }, }; @@ -90,258 +74,23 @@ void __init ixp4xx_map_io(void) iotable_init(ixp4xx_io_desc, ARRAY_SIZE(ixp4xx_io_desc)); } -/* - * GPIO-functions - */ -/* - * The following converted to the real HW bits the gpio_line_config - */ -/* GPIO pin types */ -#define IXP4XX_GPIO_OUT 0x1 -#define IXP4XX_GPIO_IN 0x2 - -/* GPIO signal types */ -#define IXP4XX_GPIO_LOW 0 -#define IXP4XX_GPIO_HIGH 1 - -/* GPIO Clocks */ -#define IXP4XX_GPIO_CLK_0 14 -#define IXP4XX_GPIO_CLK_1 15 - -static void gpio_line_config(u8 line, u32 direction) -{ - if (direction == IXP4XX_GPIO_IN) - *IXP4XX_GPIO_GPOER |= (1 << line); - else - *IXP4XX_GPIO_GPOER &= ~(1 << line); -} - -static void gpio_line_get(u8 line, int *value) -{ - *value = (*IXP4XX_GPIO_GPINR >> line) & 0x1; -} - -static void gpio_line_set(u8 line, int value) -{ - if (value == IXP4XX_GPIO_HIGH) - *IXP4XX_GPIO_GPOUTR |= (1 << line); - else if (value == IXP4XX_GPIO_LOW) - *IXP4XX_GPIO_GPOUTR &= ~(1 << line); -} - -/************************************************************************* - * IXP4xx chipset IRQ handling - * - * TODO: GPIO IRQs should be marked invalid until the user of the IRQ - * (be it PCI or something else) configures that GPIO line - * as an IRQ. - **************************************************************************/ -enum ixp4xx_irq_type { - IXP4XX_IRQ_LEVEL, IXP4XX_IRQ_EDGE -}; - -/* Each bit represents an IRQ: 1: edge-triggered, 0: level triggered */ -static unsigned long long ixp4xx_irq_edge = 0; - -/* - * IRQ -> GPIO mapping table - */ -static signed char irq2gpio[32] = { - -1, -1, -1, -1, -1, -1, 0, 1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 2, 3, 4, 5, 6, - 7, 8, 9, 10, 11, 12, -1, -1, -}; - -static int ixp4xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) -{ - int irq; - - for (irq = 0; irq < 32; irq++) { - if (irq2gpio[irq] == gpio) - return irq; - } - return -EINVAL; -} - -static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type) -{ - int line = irq2gpio[d->irq]; - u32 int_style; - enum ixp4xx_irq_type irq_type; - volatile u32 *int_reg; - - /* - * Only for GPIO IRQs - */ - if (line < 0) - return -EINVAL; - - switch (type){ - case IRQ_TYPE_EDGE_BOTH: - int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL; - irq_type = IXP4XX_IRQ_EDGE; - break; - case IRQ_TYPE_EDGE_RISING: - int_style = IXP4XX_GPIO_STYLE_RISING_EDGE; - irq_type = IXP4XX_IRQ_EDGE; - break; - case IRQ_TYPE_EDGE_FALLING: - int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE; - irq_type = IXP4XX_IRQ_EDGE; - break; - case IRQ_TYPE_LEVEL_HIGH: - int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH; - irq_type = IXP4XX_IRQ_LEVEL; - break; - case IRQ_TYPE_LEVEL_LOW: - int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW; - irq_type = IXP4XX_IRQ_LEVEL; - break; - default: - return -EINVAL; - } - - if (irq_type == IXP4XX_IRQ_EDGE) - ixp4xx_irq_edge |= (1 << d->irq); - else - ixp4xx_irq_edge &= ~(1 << d->irq); - - if (line >= 8) { /* pins 8-15 */ - line -= 8; - int_reg = IXP4XX_GPIO_GPIT2R; - } else { /* pins 0-7 */ - int_reg = IXP4XX_GPIO_GPIT1R; - } - - /* Clear the style for the appropriate pin */ - *int_reg &= ~(IXP4XX_GPIO_STYLE_CLEAR << - (line * IXP4XX_GPIO_STYLE_SIZE)); - - *IXP4XX_GPIO_GPISR = (1 << line); - - /* Set the new style */ - *int_reg |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE)); - - /* Configure the line as an input */ - gpio_line_config(irq2gpio[d->irq], IXP4XX_GPIO_IN); - - return 0; -} - -static void ixp4xx_irq_mask(struct irq_data *d) -{ - if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->irq >= 32) - *IXP4XX_ICMR2 &= ~(1 << (d->irq - 32)); - else - *IXP4XX_ICMR &= ~(1 << d->irq); -} - -static void ixp4xx_irq_ack(struct irq_data *d) -{ - int line = (d->irq < 32) ? irq2gpio[d->irq] : -1; - - if (line >= 0) - *IXP4XX_GPIO_GPISR = (1 << line); -} - -/* - * Level triggered interrupts on GPIO lines can only be cleared when the - * interrupt condition disappears. - */ -static void ixp4xx_irq_unmask(struct irq_data *d) -{ - if (!(ixp4xx_irq_edge & (1 << d->irq))) - ixp4xx_irq_ack(d); - - if ((cpu_is_ixp46x() || cpu_is_ixp43x()) && d->irq >= 32) - *IXP4XX_ICMR2 |= (1 << (d->irq - 32)); - else - *IXP4XX_ICMR |= (1 << d->irq); -} - -static struct irq_chip ixp4xx_irq_chip = { - .name = "IXP4xx", - .irq_ack = ixp4xx_irq_ack, - .irq_mask = ixp4xx_irq_mask, - .irq_unmask = ixp4xx_irq_unmask, - .irq_set_type = ixp4xx_set_irq_type, -}; - void __init ixp4xx_init_irq(void) { - int i = 0; - /* * ixp4xx does not implement the XScale PWRMODE register * so it must not call cpu_do_idle(). */ cpu_idle_poll_ctrl(true); - /* Route all sources to IRQ instead of FIQ */ - *IXP4XX_ICLR = 0x0; - - /* Disable all interrupt */ - *IXP4XX_ICMR = 0x0; - - if (cpu_is_ixp46x() || cpu_is_ixp43x()) { - /* Route upper 32 sources to IRQ instead of FIQ */ - *IXP4XX_ICLR2 = 0x00; - - /* Disable upper 32 interrupts */ - *IXP4XX_ICMR2 = 0x00; - } - - /* Default to all level triggered */ - for(i = 0; i < NR_IRQS; i++) { - irq_set_chip_and_handler(i, &ixp4xx_irq_chip, - handle_level_irq); - irq_clear_status_flags(i, IRQ_NOREQUEST); - } + ixp4xx_irq_init(IXP4XX_INTC_BASE_PHYS, + (cpu_is_ixp46x() || cpu_is_ixp43x())); } - -/************************************************************************* - * IXP4xx timer tick - * We use OS timer1 on the CPU for the timer tick and the timestamp - * counter as a source of real clock ticks to account for missed jiffies. - *************************************************************************/ - -static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - - /* Clear Pending Interrupt by writing '1' to it */ - *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - -static struct irqaction ixp4xx_timer_irq = { - .name = "timer1", - .flags = IRQF_TIMER | IRQF_IRQPOLL, - .handler = ixp4xx_timer_interrupt, - .dev_id = &clockevent_ixp4xx, -}; - void __init ixp4xx_timer_init(void) { - /* Reset/disable counter */ - *IXP4XX_OSRT1 = 0; - - /* Clear Pending Interrupt by writing '1' to it */ - *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; - - /* Reset time-stamp counter */ - *IXP4XX_OSTS = 0; - - /* Connect the interrupt handler and enable the interrupt */ - setup_irq(IRQ_IXP4XX_TIMER1, &ixp4xx_timer_irq); - - ixp4xx_clocksource_init(); - ixp4xx_clockevent_init(); + return ixp4xx_timer_setup(IXP4XX_TIMER_BASE_PHYS, + IRQ_IXP4XX_TIMER1, + IXP4XX_TIMER_FREQ); } static struct pxa2xx_udc_mach_info ixp4xx_udc_info; @@ -364,6 +113,24 @@ static struct resource ixp4xx_udc_resources[] = { }, }; +static struct resource ixp4xx_gpio_resource[] = { + { + .start = IXP4XX_GPIO_BASE_PHYS, + .end = IXP4XX_GPIO_BASE_PHYS + 0xfff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device ixp4xx_gpio_device = { + .name = "ixp4xx-gpio", + .id = -1, + .dev = { + .coherent_dma_mask = DMA_BIT_MASK(32), + }, + .resource = ixp4xx_gpio_resource, + .num_resources = ARRAY_SIZE(ixp4xx_gpio_resource), +}; + /* * USB device controller. The IXP4xx uses the same controller as PXA25X, * so we just use the same device. @@ -378,7 +145,61 @@ static struct platform_device ixp4xx_udc_device = { }, }; +static struct resource ixp4xx_npe_resources[] = { + { + .start = IXP4XX_NPEA_BASE_PHYS, + .end = IXP4XX_NPEA_BASE_PHYS + 0xfff, + .flags = IORESOURCE_MEM, + }, + { + .start = IXP4XX_NPEB_BASE_PHYS, + .end = IXP4XX_NPEB_BASE_PHYS + 0xfff, + .flags = IORESOURCE_MEM, + }, + { + .start = IXP4XX_NPEC_BASE_PHYS, + .end = IXP4XX_NPEC_BASE_PHYS + 0xfff, + .flags = IORESOURCE_MEM, + }, + +}; + +static struct platform_device ixp4xx_npe_device = { + .name = "ixp4xx-npe", + .id = -1, + .num_resources = ARRAY_SIZE(ixp4xx_npe_resources), + .resource = ixp4xx_npe_resources, +}; + +static struct resource ixp4xx_qmgr_resources[] = { + { + .start = IXP4XX_QMGR_BASE_PHYS, + .end = IXP4XX_QMGR_BASE_PHYS + 0x3fff, + .flags = IORESOURCE_MEM, + }, + { + .start = IRQ_IXP4XX_QM1, + .end = IRQ_IXP4XX_QM1, + .flags = IORESOURCE_IRQ, + }, + { + .start = IRQ_IXP4XX_QM2, + .end = IRQ_IXP4XX_QM2, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device ixp4xx_qmgr_device = { + .name = "ixp4xx-qmgr", + .id = -1, + .num_resources = ARRAY_SIZE(ixp4xx_qmgr_resources), + .resource = ixp4xx_qmgr_resources, +}; + static struct platform_device *ixp4xx_devices[] __initdata = { + &ixp4xx_npe_device, + &ixp4xx_qmgr_device, + &ixp4xx_gpio_device, &ixp4xx_udc_device, }; @@ -413,56 +234,12 @@ static struct platform_device *ixp46x_devices[] __initdata = { unsigned long ixp4xx_exp_bus_size; EXPORT_SYMBOL(ixp4xx_exp_bus_size); -static int ixp4xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) -{ - gpio_line_config(gpio, IXP4XX_GPIO_IN); - - return 0; -} - -static int ixp4xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, - int level) -{ - gpio_line_set(gpio, level); - gpio_line_config(gpio, IXP4XX_GPIO_OUT); - - return 0; -} - -static int ixp4xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio) -{ - int value; - - gpio_line_get(gpio, &value); - - return value; -} - -static void ixp4xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, - int value) -{ - gpio_line_set(gpio, value); -} - -static struct gpio_chip ixp4xx_gpio_chip = { - .label = "IXP4XX_GPIO_CHIP", - .direction_input = ixp4xx_gpio_direction_input, - .direction_output = ixp4xx_gpio_direction_output, - .get = ixp4xx_gpio_get_value, - .set = ixp4xx_gpio_set_value, - .to_irq = ixp4xx_gpio_to_irq, - .base = 0, - .ngpio = 16, -}; - void __init ixp4xx_sys_init(void) { ixp4xx_exp_bus_size = SZ_16M; platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices)); - gpiochip_add_data(&ixp4xx_gpio_chip, NULL); - if (cpu_is_ixp46x()) { int region; @@ -481,103 +258,8 @@ void __init ixp4xx_sys_init(void) ixp4xx_exp_bus_size >> 20); } -/* - * sched_clock() - */ -static u64 notrace ixp4xx_read_sched_clock(void) -{ - return *IXP4XX_OSTS; -} - -/* - * clocksource - */ - -static u64 ixp4xx_clocksource_read(struct clocksource *c) -{ - return *IXP4XX_OSTS; -} - unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ; EXPORT_SYMBOL(ixp4xx_timer_freq); -static void __init ixp4xx_clocksource_init(void) -{ - sched_clock_register(ixp4xx_read_sched_clock, 32, ixp4xx_timer_freq); - - clocksource_mmio_init(NULL, "OSTS", ixp4xx_timer_freq, 200, 32, - ixp4xx_clocksource_read); -} - -/* - * clockevents - */ -static int ixp4xx_set_next_event(unsigned long evt, - struct clock_event_device *unused) -{ - unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK; - - *IXP4XX_OSRT1 = (evt & ~IXP4XX_OST_RELOAD_MASK) | opts; - - return 0; -} - -static int ixp4xx_shutdown(struct clock_event_device *evt) -{ - unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK; - unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK; - - opts &= ~IXP4XX_OST_ENABLE; - *IXP4XX_OSRT1 = osrt | opts; - return 0; -} - -static int ixp4xx_set_oneshot(struct clock_event_device *evt) -{ - unsigned long opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT; - unsigned long osrt = 0; - - /* period set by 'set next_event' */ - *IXP4XX_OSRT1 = osrt | opts; - return 0; -} - -static int ixp4xx_set_periodic(struct clock_event_device *evt) -{ - unsigned long opts = IXP4XX_OST_ENABLE; - unsigned long osrt = IXP4XX_LATCH & ~IXP4XX_OST_RELOAD_MASK; - - *IXP4XX_OSRT1 = osrt | opts; - return 0; -} - -static int ixp4xx_resume(struct clock_event_device *evt) -{ - unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK; - unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK; - - opts |= IXP4XX_OST_ENABLE; - *IXP4XX_OSRT1 = osrt | opts; - return 0; -} - -static struct clock_event_device clockevent_ixp4xx = { - .name = "ixp4xx timer1", - .features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_FEAT_ONESHOT, - .rating = 200, - .set_state_shutdown = ixp4xx_shutdown, - .set_state_periodic = ixp4xx_set_periodic, - .set_state_oneshot = ixp4xx_set_oneshot, - .tick_resume = ixp4xx_resume, - .set_next_event = ixp4xx_set_next_event, -}; - -static void __init ixp4xx_clockevent_init(void) -{ - clockevent_ixp4xx.cpumask = cpumask_of(0); - clockevents_config_and_register(&clockevent_ixp4xx, IXP4XX_TIMER_FREQ, - 0xf, 0xfffffffe); -} void ixp4xx_restart(enum reboot_mode mode, const char *cmd) { diff --git a/arch/arm/mach-ixp4xx/coyote-pci.c b/arch/arm/mach-ixp4xx/coyote-pci.c index 5d14ce2aee6d..a16c35d2bb96 100644 --- a/arch/arm/mach-ixp4xx/coyote-pci.c +++ b/arch/arm/mach-ixp4xx/coyote-pci.c @@ -23,6 +23,8 @@ #include <asm/irq.h> #include <asm/mach/pci.h> +#include "irqs.h" + #define SLOT0_DEVID 14 #define SLOT1_DEVID 15 diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c index 7e40fe70933b..7ca43ca2816d 100644 --- a/arch/arm/mach-ixp4xx/coyote-setup.c +++ b/arch/arm/mach-ixp4xx/coyote-setup.c @@ -25,6 +25,8 @@ #include <asm/mach/arch.h> #include <asm/mach/flash.h> +#include "irqs.h" + #define COYOTE_IDE_BASE_PHYS IXP4XX_EXP_BUS_BASE(3) #define COYOTE_IDE_BASE_VIRT 0xFFFE1000 #define COYOTE_IDE_REGION_SIZE 0x1000 diff --git a/arch/arm/mach-ixp4xx/dsmg600-pci.c b/arch/arm/mach-ixp4xx/dsmg600-pci.c index 8dca76937723..6899023bd1b7 100644 --- a/arch/arm/mach-ixp4xx/dsmg600-pci.c +++ b/arch/arm/mach-ixp4xx/dsmg600-pci.c @@ -22,6 +22,8 @@ #include <asm/mach/pci.h> #include <asm/mach-types.h> +#include "irqs.h" + #define MAX_DEV 4 #define IRQ_LINES 3 diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c index 397190f3a8da..4d4c62fced71 100644 --- a/arch/arm/mach-ixp4xx/dsmg600-setup.c +++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c @@ -35,6 +35,8 @@ #include <asm/mach/flash.h> #include <asm/mach/time.h> +#include "irqs.h" + #define DSMG600_SDA_PIN 5 #define DSMG600_SCL_PIN 4 @@ -268,9 +270,6 @@ static void __init dsmg600_init(void) { ixp4xx_sys_init(); - /* Make sure that GPIO14 and GPIO15 are not used as clocks */ - *IXP4XX_GPIO_GPCLKR = 0; - dsmg600_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); dsmg600_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; diff --git a/arch/arm/mach-ixp4xx/fsg-pci.c b/arch/arm/mach-ixp4xx/fsg-pci.c index fd4a8625b4ae..6c08bb9d9807 100644 --- a/arch/arm/mach-ixp4xx/fsg-pci.c +++ b/arch/arm/mach-ixp4xx/fsg-pci.c @@ -22,6 +22,8 @@ #include <asm/mach/pci.h> #include <asm/mach-types.h> +#include "irqs.h" + #define MAX_DEV 3 #define IRQ_LINES 3 diff --git a/arch/arm/mach-ixp4xx/fsg-setup.c b/arch/arm/mach-ixp4xx/fsg-setup.c index f0a152e365b1..648932d8d7a8 100644 --- a/arch/arm/mach-ixp4xx/fsg-setup.c +++ b/arch/arm/mach-ixp4xx/fsg-setup.c @@ -29,6 +29,8 @@ #include <asm/mach/arch.h> #include <asm/mach/flash.h> +#include "irqs.h" + #define FSG_SDA_PIN 12 #define FSG_SCL_PIN 13 diff --git a/arch/arm/mach-ixp4xx/gateway7001-pci.c b/arch/arm/mach-ixp4xx/gateway7001-pci.c index d9d6cc089707..903c75330b76 100644 --- a/arch/arm/mach-ixp4xx/gateway7001-pci.c +++ b/arch/arm/mach-ixp4xx/gateway7001-pci.c @@ -27,6 +27,8 @@ #include <asm/mach/pci.h> +#include "irqs.h" + void __init gateway7001_pci_preinit(void) { irq_set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW); diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c index 1be6faf6da9a..678e7dfff0e5 100644 --- a/arch/arm/mach-ixp4xx/gateway7001-setup.c +++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c @@ -28,6 +28,8 @@ #include <asm/mach/arch.h> #include <asm/mach/flash.h> +#include "irqs.h" + static struct flash_platform_data gateway7001_flash_data = { .map_name = "cfi_probe", .width = 2, diff --git a/arch/arm/mach-ixp4xx/gtwx5715-pci.c b/arch/arm/mach-ixp4xx/gtwx5715-pci.c index 551d114c9e14..1223d160448f 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-pci.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-pci.c @@ -30,6 +30,8 @@ #include <mach/hardware.h> #include <asm/mach/pci.h> +#include "irqs.h" + #define SLOT0_DEVID 0 #define SLOT1_DEVID 1 #define INTA 10 /* slot 1 has INTA and INTB crossed */ diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c index 16a12994fb53..5dbdde8e2338 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c @@ -36,6 +36,8 @@ #include <asm/mach/arch.h> #include <asm/mach/flash.h> +#include "irqs.h" + /* GPIO 5,6,7 and 12 are hard wired to the Kendin KS8995M Switch and operate as an SPI type interface. The details of the interface are available on Kendin/Micrel's web site. */ diff --git a/arch/arm/mach-ixp4xx/include/mach/entry-macro.S b/arch/arm/mach-ixp4xx/include/mach/entry-macro.S deleted file mode 100644 index 79adf83e2c3d..000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/entry-macro.S +++ /dev/null @@ -1,41 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/include/mach/entry-macro.S - * - * Low-level IRQ helper macros for IXP4xx-based platforms - * - * 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 <mach/hardware.h> - - .macro get_irqnr_preamble, base, tmp - .endm - - .macro get_irqnr_and_base, irqnr, irqstat, base, tmp - ldr \irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP_OFFSET) - ldr \irqstat, [\irqstat] @ get interrupts - cmp \irqstat, #0 - beq 1001f @ upper IRQ? - clz \irqnr, \irqstat - mov \base, #31 - sub \irqnr, \base, \irqnr - b 1002f @ lower IRQ being - @ handled - -1001: - /* - * IXP465/IXP435 has an upper IRQ status register - */ -#if defined(CONFIG_CPU_IXP46X) || defined(CONFIG_CPU_IXP43X) - ldr \irqstat, =(IXP4XX_INTC_BASE_VIRT+IXP4XX_ICIP2_OFFSET) - ldr \irqstat, [\irqstat] @ get upper interrupts - mov \irqnr, #63 - clz \irqstat, \irqstat - cmp \irqstat, #32 - subne \irqnr, \irqnr, \irqstat -#endif -1002: - .endm - - diff --git a/arch/arm/mach-ixp4xx/include/mach/irqs.h b/arch/arm/mach-ixp4xx/include/mach/irqs.h deleted file mode 100644 index 7e6d4cce7c27..000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/irqs.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * arch/arm/mach-ixp4xx/include/mach/irqs.h - * - * IRQ definitions for IXP4XX based systems - * - * Copyright (C) 2002 Intel Corporation. - * Copyright (C) 2003 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 version 2 as - * published by the Free Software Foundation. - * - */ - -#ifndef _ARCH_IXP4XX_IRQS_H_ -#define _ARCH_IXP4XX_IRQS_H_ - -#define IRQ_IXP4XX_NPEA 0 -#define IRQ_IXP4XX_NPEB 1 -#define IRQ_IXP4XX_NPEC 2 -#define IRQ_IXP4XX_QM1 3 -#define IRQ_IXP4XX_QM2 4 -#define IRQ_IXP4XX_TIMER1 5 -#define IRQ_IXP4XX_GPIO0 6 -#define IRQ_IXP4XX_GPIO1 7 -#define IRQ_IXP4XX_PCI_INT 8 -#define IRQ_IXP4XX_PCI_DMA1 9 -#define IRQ_IXP4XX_PCI_DMA2 10 -#define IRQ_IXP4XX_TIMER2 11 -#define IRQ_IXP4XX_USB 12 -#define IRQ_IXP4XX_UART2 13 -#define IRQ_IXP4XX_TIMESTAMP 14 -#define IRQ_IXP4XX_UART1 15 -#define IRQ_IXP4XX_WDOG 16 -#define IRQ_IXP4XX_AHB_PMU 17 -#define IRQ_IXP4XX_XSCALE_PMU 18 -#define IRQ_IXP4XX_GPIO2 19 -#define IRQ_IXP4XX_GPIO3 20 -#define IRQ_IXP4XX_GPIO4 21 -#define IRQ_IXP4XX_GPIO5 22 -#define IRQ_IXP4XX_GPIO6 23 -#define IRQ_IXP4XX_GPIO7 24 -#define IRQ_IXP4XX_GPIO8 25 -#define IRQ_IXP4XX_GPIO9 26 -#define IRQ_IXP4XX_GPIO10 27 -#define IRQ_IXP4XX_GPIO11 28 -#define IRQ_IXP4XX_GPIO12 29 -#define IRQ_IXP4XX_SW_INT1 30 -#define IRQ_IXP4XX_SW_INT2 31 -#define IRQ_IXP4XX_USB_HOST 32 -#define IRQ_IXP4XX_I2C 33 -#define IRQ_IXP4XX_SSP 34 -#define IRQ_IXP4XX_TSYNC 35 -#define IRQ_IXP4XX_EAU_DONE 36 -#define IRQ_IXP4XX_SHA_DONE 37 -#define IRQ_IXP4XX_SWCP_PE 58 -#define IRQ_IXP4XX_QM_PE 60 -#define IRQ_IXP4XX_MCU_ECC 61 -#define IRQ_IXP4XX_EXP_PE 62 - -#define _IXP4XX_GPIO_IRQ(n) (IRQ_IXP4XX_GPIO ## n) -#define IXP4XX_GPIO_IRQ(n) _IXP4XX_GPIO_IRQ(n) - -/* - * Only first 32 sources are valid if running on IXP42x systems - */ -#if defined(CONFIG_CPU_IXP46X) || defined(CONFIG_CPU_IXP43X) -#define NR_IRQS 64 -#else -#define NR_IRQS 32 -#endif - -#define XSCALE_PMU_IRQ (IRQ_IXP4XX_XSCALE_PMU) - -#endif diff --git a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h index b7ddd27419c2..588b76651085 100644 --- a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h +++ b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h @@ -43,8 +43,6 @@ * Queue Manager */ #define IXP4XX_QMGR_BASE_PHYS 0x60000000 -#define IXP4XX_QMGR_BASE_VIRT IOMEM(0xFEF15000) -#define IXP4XX_QMGR_REGION_SIZE 0x00004000 /* * Peripheral space, including debug UART. Must be section-aligned so that @@ -132,9 +130,6 @@ #define IXP4XX_INTC_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x3000) #define IXP4XX_GPIO_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x4000) #define IXP4XX_TIMER_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x5000) -#define IXP4XX_NPEA_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x6000) -#define IXP4XX_NPEB_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x7000) -#define IXP4XX_NPEC_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x8000) #define IXP4XX_EthB_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x9000) #define IXP4XX_EthC_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0xA000) #define IXP4XX_USB_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0xB000) @@ -148,95 +143,6 @@ #define IXP4XX_SSP_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x12000) /* - * Constants to make it easy to access Interrupt Controller registers - */ -#define IXP4XX_ICPR_OFFSET 0x00 /* Interrupt Status */ -#define IXP4XX_ICMR_OFFSET 0x04 /* Interrupt Enable */ -#define IXP4XX_ICLR_OFFSET 0x08 /* Interrupt IRQ/FIQ Select */ -#define IXP4XX_ICIP_OFFSET 0x0C /* IRQ Status */ -#define IXP4XX_ICFP_OFFSET 0x10 /* FIQ Status */ -#define IXP4XX_ICHR_OFFSET 0x14 /* Interrupt Priority */ -#define IXP4XX_ICIH_OFFSET 0x18 /* IRQ Highest Pri Int */ -#define IXP4XX_ICFH_OFFSET 0x1C /* FIQ Highest Pri Int */ - -/* - * IXP465-only - */ -#define IXP4XX_ICPR2_OFFSET 0x20 /* Interrupt Status 2 */ -#define IXP4XX_ICMR2_OFFSET 0x24 /* Interrupt Enable 2 */ -#define IXP4XX_ICLR2_OFFSET 0x28 /* Interrupt IRQ/FIQ Select 2 */ -#define IXP4XX_ICIP2_OFFSET 0x2C /* IRQ Status */ -#define IXP4XX_ICFP2_OFFSET 0x30 /* FIQ Status */ -#define IXP4XX_ICEEN_OFFSET 0x34 /* Error High Pri Enable */ - - -/* - * Interrupt Controller Register Definitions. - */ - -#define IXP4XX_INTC_REG(x) ((volatile u32 *)(IXP4XX_INTC_BASE_VIRT+(x))) - -#define IXP4XX_ICPR IXP4XX_INTC_REG(IXP4XX_ICPR_OFFSET) -#define IXP4XX_ICMR IXP4XX_INTC_REG(IXP4XX_ICMR_OFFSET) -#define IXP4XX_ICLR IXP4XX_INTC_REG(IXP4XX_ICLR_OFFSET) -#define IXP4XX_ICIP IXP4XX_INTC_REG(IXP4XX_ICIP_OFFSET) -#define IXP4XX_ICFP IXP4XX_INTC_REG(IXP4XX_ICFP_OFFSET) -#define IXP4XX_ICHR IXP4XX_INTC_REG(IXP4XX_ICHR_OFFSET) -#define IXP4XX_ICIH IXP4XX_INTC_REG(IXP4XX_ICIH_OFFSET) -#define IXP4XX_ICFH IXP4XX_INTC_REG(IXP4XX_ICFH_OFFSET) -#define IXP4XX_ICPR2 IXP4XX_INTC_REG(IXP4XX_ICPR2_OFFSET) -#define IXP4XX_ICMR2 IXP4XX_INTC_REG(IXP4XX_ICMR2_OFFSET) -#define IXP4XX_ICLR2 IXP4XX_INTC_REG(IXP4XX_ICLR2_OFFSET) -#define IXP4XX_ICIP2 IXP4XX_INTC_REG(IXP4XX_ICIP2_OFFSET) -#define IXP4XX_ICFP2 IXP4XX_INTC_REG(IXP4XX_ICFP2_OFFSET) -#define IXP4XX_ICEEN IXP4XX_INTC_REG(IXP4XX_ICEEN_OFFSET) - -/* - * Constants to make it easy to access GPIO registers - */ -#define IXP4XX_GPIO_GPOUTR_OFFSET 0x00 -#define IXP4XX_GPIO_GPOER_OFFSET 0x04 -#define IXP4XX_GPIO_GPINR_OFFSET 0x08 -#define IXP4XX_GPIO_GPISR_OFFSET 0x0C -#define IXP4XX_GPIO_GPIT1R_OFFSET 0x10 -#define IXP4XX_GPIO_GPIT2R_OFFSET 0x14 -#define IXP4XX_GPIO_GPCLKR_OFFSET 0x18 -#define IXP4XX_GPIO_GPDBSELR_OFFSET 0x1C - -/* - * GPIO Register Definitions. - * [Only perform 32bit reads/writes] - */ -#define IXP4XX_GPIO_REG(x) ((volatile u32 *)(IXP4XX_GPIO_BASE_VIRT+(x))) - -#define IXP4XX_GPIO_GPOUTR IXP4XX_GPIO_REG(IXP4XX_GPIO_GPOUTR_OFFSET) -#define IXP4XX_GPIO_GPOER IXP4XX_GPIO_REG(IXP4XX_GPIO_GPOER_OFFSET) -#define IXP4XX_GPIO_GPINR IXP4XX_GPIO_REG(IXP4XX_GPIO_GPINR_OFFSET) -#define IXP4XX_GPIO_GPISR IXP4XX_GPIO_REG(IXP4XX_GPIO_GPISR_OFFSET) -#define IXP4XX_GPIO_GPIT1R IXP4XX_GPIO_REG(IXP4XX_GPIO_GPIT1R_OFFSET) -#define IXP4XX_GPIO_GPIT2R IXP4XX_GPIO_REG(IXP4XX_GPIO_GPIT2R_OFFSET) -#define IXP4XX_GPIO_GPCLKR IXP4XX_GPIO_REG(IXP4XX_GPIO_GPCLKR_OFFSET) -#define IXP4XX_GPIO_GPDBSELR IXP4XX_GPIO_REG(IXP4XX_GPIO_GPDBSELR_OFFSET) - -/* - * GPIO register bit definitions - */ - -/* Interrupt styles - */ -#define IXP4XX_GPIO_STYLE_ACTIVE_HIGH 0x0 -#define IXP4XX_GPIO_STYLE_ACTIVE_LOW 0x1 -#define IXP4XX_GPIO_STYLE_RISING_EDGE 0x2 -#define IXP4XX_GPIO_STYLE_FALLING_EDGE 0x3 -#define IXP4XX_GPIO_STYLE_TRANSITIONAL 0x4 - -/* - * Mask used to clear interrupt styles - */ -#define IXP4XX_GPIO_STYLE_CLEAR 0x7 -#define IXP4XX_GPIO_STYLE_SIZE 3 - -/* * Constants to make it easy to access Timer Control/Status registers */ #define IXP4XX_OSTS_OFFSET 0x00 /* Continious TimeStamp */ diff --git a/arch/arm/mach-ixp4xx/include/mach/npe.h b/arch/arm/mach-ixp4xx/include/mach/npe.h deleted file mode 100644 index 3a980845e557..000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/npe.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __IXP4XX_NPE_H -#define __IXP4XX_NPE_H - -#include <linux/kernel.h> - -extern const char *npe_names[]; - -struct npe_regs { - u32 exec_addr, exec_data, exec_status_cmd, exec_count; - u32 action_points[4]; - u32 watchpoint_fifo, watch_count; - u32 profile_count; - u32 messaging_status, messaging_control; - u32 mailbox_status, /*messaging_*/ in_out_fifo; -}; - -struct npe { - struct resource *mem_res; - struct npe_regs __iomem *regs; - u32 regs_phys; - int id; - int valid; -}; - - -static inline const char *npe_name(struct npe *npe) -{ - return npe_names[npe->id]; -} - -int npe_running(struct npe *npe); -int npe_send_message(struct npe *npe, const void *msg, const char *what); -int npe_recv_message(struct npe *npe, void *msg, const char *what); -int npe_send_recv_message(struct npe *npe, void *msg, const char *what); -int npe_load_firmware(struct npe *npe, const char *name, struct device *dev); -struct npe *npe_request(unsigned id); -void npe_release(struct npe *npe); - -#endif /* __IXP4XX_NPE_H */ diff --git a/arch/arm/mach-ixp4xx/include/mach/qmgr.h b/arch/arm/mach-ixp4xx/include/mach/qmgr.h deleted file mode 100644 index 4de8da536dbb..000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/qmgr.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - */ - -#ifndef IXP4XX_QMGR_H -#define IXP4XX_QMGR_H - -#include <linux/io.h> -#include <linux/kernel.h> - -#define DEBUG_QMGR 0 - -#define HALF_QUEUES 32 -#define QUEUES 64 -#define MAX_QUEUE_LENGTH 4 /* in dwords */ - -#define QUEUE_STAT1_EMPTY 1 /* queue status bits */ -#define QUEUE_STAT1_NEARLY_EMPTY 2 -#define QUEUE_STAT1_NEARLY_FULL 4 -#define QUEUE_STAT1_FULL 8 -#define QUEUE_STAT2_UNDERFLOW 1 -#define QUEUE_STAT2_OVERFLOW 2 - -#define QUEUE_WATERMARK_0_ENTRIES 0 -#define QUEUE_WATERMARK_1_ENTRY 1 -#define QUEUE_WATERMARK_2_ENTRIES 2 -#define QUEUE_WATERMARK_4_ENTRIES 3 -#define QUEUE_WATERMARK_8_ENTRIES 4 -#define QUEUE_WATERMARK_16_ENTRIES 5 -#define QUEUE_WATERMARK_32_ENTRIES 6 -#define QUEUE_WATERMARK_64_ENTRIES 7 - -/* queue interrupt request conditions */ -#define QUEUE_IRQ_SRC_EMPTY 0 -#define QUEUE_IRQ_SRC_NEARLY_EMPTY 1 -#define QUEUE_IRQ_SRC_NEARLY_FULL 2 -#define QUEUE_IRQ_SRC_FULL 3 -#define QUEUE_IRQ_SRC_NOT_EMPTY 4 -#define QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY 5 -#define QUEUE_IRQ_SRC_NOT_NEARLY_FULL 6 -#define QUEUE_IRQ_SRC_NOT_FULL 7 - -struct qmgr_regs { - u32 acc[QUEUES][MAX_QUEUE_LENGTH]; /* 0x000 - 0x3FF */ - u32 stat1[4]; /* 0x400 - 0x40F */ - u32 stat2[2]; /* 0x410 - 0x417 */ - u32 statne_h; /* 0x418 - queue nearly empty */ - u32 statf_h; /* 0x41C - queue full */ - u32 irqsrc[4]; /* 0x420 - 0x42F IRC source */ - u32 irqen[2]; /* 0x430 - 0x437 IRQ enabled */ - u32 irqstat[2]; /* 0x438 - 0x43F - IRQ access only */ - u32 reserved[1776]; - u32 sram[2048]; /* 0x2000 - 0x3FFF - config and buffer */ -}; - -void qmgr_set_irq(unsigned int queue, int src, - void (*handler)(void *pdev), void *pdev); -void qmgr_enable_irq(unsigned int queue); -void qmgr_disable_irq(unsigned int queue); - -/* request_ and release_queue() must be called from non-IRQ context */ - -#if DEBUG_QMGR -extern char qmgr_queue_descs[QUEUES][32]; - -int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, - unsigned int nearly_empty_watermark, - unsigned int nearly_full_watermark, - const char *desc_format, const char* name); -#else -int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, - unsigned int nearly_empty_watermark, - unsigned int nearly_full_watermark); -#define qmgr_request_queue(queue, len, nearly_empty_watermark, \ - nearly_full_watermark, desc_format, name) \ - __qmgr_request_queue(queue, len, nearly_empty_watermark, \ - nearly_full_watermark) -#endif - -void qmgr_release_queue(unsigned int queue); - - -static inline void qmgr_put_entry(unsigned int queue, u32 val) -{ - struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; -#if DEBUG_QMGR - BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */ - - printk(KERN_DEBUG "Queue %s(%i) put %X\n", - qmgr_queue_descs[queue], queue, val); -#endif - __raw_writel(val, &qmgr_regs->acc[queue][0]); -} - -static inline u32 qmgr_get_entry(unsigned int queue) -{ - u32 val; - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - val = __raw_readl(&qmgr_regs->acc[queue][0]); -#if DEBUG_QMGR - BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */ - - printk(KERN_DEBUG "Queue %s(%i) get %X\n", - qmgr_queue_descs[queue], queue, val); -#endif - return val; -} - -static inline int __qmgr_get_stat1(unsigned int queue) -{ - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - return (__raw_readl(&qmgr_regs->stat1[queue >> 3]) - >> ((queue & 7) << 2)) & 0xF; -} - -static inline int __qmgr_get_stat2(unsigned int queue) -{ - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - BUG_ON(queue >= HALF_QUEUES); - return (__raw_readl(&qmgr_regs->stat2[queue >> 4]) - >> ((queue & 0xF) << 1)) & 0x3; -} - -/** - * qmgr_stat_empty() - checks if a hardware queue is empty - * @queue: queue number - * - * Returns non-zero value if the queue is empty. - */ -static inline int qmgr_stat_empty(unsigned int queue) -{ - BUG_ON(queue >= HALF_QUEUES); - return __qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY; -} - -/** - * qmgr_stat_below_low_watermark() - checks if a queue is below low watermark - * @queue: queue number - * - * Returns non-zero value if the queue is below low watermark. - */ -static inline int qmgr_stat_below_low_watermark(unsigned int queue) -{ - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - if (queue >= HALF_QUEUES) - return (__raw_readl(&qmgr_regs->statne_h) >> - (queue - HALF_QUEUES)) & 0x01; - return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY; -} - -/** - * qmgr_stat_above_high_watermark() - checks if a queue is above high watermark - * @queue: queue number - * - * Returns non-zero value if the queue is above high watermark - */ -static inline int qmgr_stat_above_high_watermark(unsigned int queue) -{ - BUG_ON(queue >= HALF_QUEUES); - return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL; -} - -/** - * qmgr_stat_full() - checks if a hardware queue is full - * @queue: queue number - * - * Returns non-zero value if the queue is full. - */ -static inline int qmgr_stat_full(unsigned int queue) -{ - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - if (queue >= HALF_QUEUES) - return (__raw_readl(&qmgr_regs->statf_h) >> - (queue - HALF_QUEUES)) & 0x01; - return __qmgr_get_stat1(queue) & QUEUE_STAT1_FULL; -} - -/** - * qmgr_stat_underflow() - checks if a hardware queue experienced underflow - * @queue: queue number - * - * Returns non-zero value if the queue experienced underflow. - */ -static inline int qmgr_stat_underflow(unsigned int queue) -{ - return __qmgr_get_stat2(queue) & QUEUE_STAT2_UNDERFLOW; -} - -/** - * qmgr_stat_overflow() - checks if a hardware queue experienced overflow - * @queue: queue number - * - * Returns non-zero value if the queue experienced overflow. - */ -static inline int qmgr_stat_overflow(unsigned int queue) -{ - return __qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW; -} - -#endif diff --git a/arch/arm/mach-ixp4xx/irqs.h b/arch/arm/mach-ixp4xx/irqs.h new file mode 100644 index 000000000000..6b7f220cf9e0 --- /dev/null +++ b/arch/arm/mach-ixp4xx/irqs.h @@ -0,0 +1,68 @@ +/* + * arch/arm/mach-ixp4xx/include/mach/irqs.h + * + * IRQ definitions for IXP4XX based systems + * + * Copyright (C) 2002 Intel Corporation. + * Copyright (C) 2003 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 version 2 as + * published by the Free Software Foundation. + * + */ + +#ifndef _ARCH_IXP4XX_IRQS_H_ +#define _ARCH_IXP4XX_IRQS_H_ + +#define IRQ_IXP4XX_BASE 16 + +#define IRQ_IXP4XX_NPEA (IRQ_IXP4XX_BASE + 0) +#define IRQ_IXP4XX_NPEB (IRQ_IXP4XX_BASE + 1) +#define IRQ_IXP4XX_NPEC (IRQ_IXP4XX_BASE + 2) +#define IRQ_IXP4XX_QM1 (IRQ_IXP4XX_BASE + 3) +#define IRQ_IXP4XX_QM2 (IRQ_IXP4XX_BASE + 4) +#define IRQ_IXP4XX_TIMER1 (IRQ_IXP4XX_BASE + 5) +#define IRQ_IXP4XX_GPIO0 (IRQ_IXP4XX_BASE + 6) +#define IRQ_IXP4XX_GPIO1 (IRQ_IXP4XX_BASE + 7) +#define IRQ_IXP4XX_PCI_INT (IRQ_IXP4XX_BASE + 8) +#define IRQ_IXP4XX_PCI_DMA1 (IRQ_IXP4XX_BASE + 9) +#define IRQ_IXP4XX_PCI_DMA2 (IRQ_IXP4XX_BASE + 10) +#define IRQ_IXP4XX_TIMER2 (IRQ_IXP4XX_BASE + 11) +#define IRQ_IXP4XX_USB (IRQ_IXP4XX_BASE + 12) +#define IRQ_IXP4XX_UART2 (IRQ_IXP4XX_BASE + 13) +#define IRQ_IXP4XX_TIMESTAMP (IRQ_IXP4XX_BASE + 14) +#define IRQ_IXP4XX_UART1 (IRQ_IXP4XX_BASE + 15) +#define IRQ_IXP4XX_WDOG (IRQ_IXP4XX_BASE + 16) +#define IRQ_IXP4XX_AHB_PMU (IRQ_IXP4XX_BASE + 17) +#define IRQ_IXP4XX_XSCALE_PMU (IRQ_IXP4XX_BASE + 18) +#define IRQ_IXP4XX_GPIO2 (IRQ_IXP4XX_BASE + 19) +#define IRQ_IXP4XX_GPIO3 (IRQ_IXP4XX_BASE + 20) +#define IRQ_IXP4XX_GPIO4 (IRQ_IXP4XX_BASE + 21) +#define IRQ_IXP4XX_GPIO5 (IRQ_IXP4XX_BASE + 22) +#define IRQ_IXP4XX_GPIO6 (IRQ_IXP4XX_BASE + 23) +#define IRQ_IXP4XX_GPIO7 (IRQ_IXP4XX_BASE + 24) +#define IRQ_IXP4XX_GPIO8 (IRQ_IXP4XX_BASE + 25) +#define IRQ_IXP4XX_GPIO9 (IRQ_IXP4XX_BASE + 26) +#define IRQ_IXP4XX_GPIO10 (IRQ_IXP4XX_BASE + 27) +#define IRQ_IXP4XX_GPIO11 (IRQ_IXP4XX_BASE + 28) +#define IRQ_IXP4XX_GPIO12 (IRQ_IXP4XX_BASE + 29) +#define IRQ_IXP4XX_SW_INT1 (IRQ_IXP4XX_BASE + 30) +#define IRQ_IXP4XX_SW_INT2 (IRQ_IXP4XX_BASE + 31) +#define IRQ_IXP4XX_USB_HOST (IRQ_IXP4XX_BASE + 32) +#define IRQ_IXP4XX_I2C (IRQ_IXP4XX_BASE + 33) +#define IRQ_IXP4XX_SSP (IRQ_IXP4XX_BASE + 34) +#define IRQ_IXP4XX_TSYNC (IRQ_IXP4XX_BASE + 35) +#define IRQ_IXP4XX_EAU_DONE (IRQ_IXP4XX_BASE + 36) +#define IRQ_IXP4XX_SHA_DONE (IRQ_IXP4XX_BASE + 37) +#define IRQ_IXP4XX_SWCP_PE (IRQ_IXP4XX_BASE + 58) +#define IRQ_IXP4XX_QM_PE (IRQ_IXP4XX_BASE + 60) +#define IRQ_IXP4XX_MCU_ECC (IRQ_IXP4XX_BASE + 61) +#define IRQ_IXP4XX_EXP_PE (IRQ_IXP4XX_BASE + 62) + +#define _IXP4XX_GPIO_IRQ(n) (IRQ_IXP4XX_GPIO ## n) +#define IXP4XX_GPIO_IRQ(n) _IXP4XX_GPIO_IRQ(n) + +#define XSCALE_PMU_IRQ (IRQ_IXP4XX_XSCALE_PMU) + +#endif diff --git a/arch/arm/mach-ixp4xx/ixdp425-pci.c b/arch/arm/mach-ixp4xx/ixdp425-pci.c index 318424dd3c50..c1340465b2ea 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-pci.c +++ b/arch/arm/mach-ixp4xx/ixdp425-pci.c @@ -24,6 +24,8 @@ #include <mach/hardware.h> #include <asm/mach-types.h> +#include "irqs.h" + #define MAX_DEV 4 #define IRQ_LINES 4 diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index 57d7df79d838..6f0f7ed18ea8 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c @@ -32,6 +32,8 @@ #include <asm/mach/arch.h> #include <asm/mach/flash.h> +#include "irqs.h" + #define IXDP425_SDA_PIN 7 #define IXDP425_SCL_PIN 6 diff --git a/arch/arm/mach-ixp4xx/ixdpg425-pci.c b/arch/arm/mach-ixp4xx/ixdpg425-pci.c index 1f8717ba13dc..ac0e9bc6eb4d 100644 --- a/arch/arm/mach-ixp4xx/ixdpg425-pci.c +++ b/arch/arm/mach-ixp4xx/ixdpg425-pci.c @@ -23,6 +23,8 @@ #include <asm/mach/pci.h> +#include "irqs.h" + void __init ixdpg425_pci_preinit(void) { irq_set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW); diff --git a/arch/arm/mach-ixp4xx/ixp4xx-of.c b/arch/arm/mach-ixp4xx/ixp4xx-of.c new file mode 100644 index 000000000000..7449b8319c8a --- /dev/null +++ b/arch/arm/mach-ixp4xx/ixp4xx-of.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * IXP4xx Device Tree boot support + */ +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/io.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> + +#include <mach/hardware.h> +#include <mach/ixp4xx-regs.h> + +static struct map_desc ixp4xx_of_io_desc[] __initdata = { + /* + * This is needed for runtime system configuration checks, + * such as reading if hardware so-and-so is present. This + * could eventually be converted into a syscon once all boards + * are converted to device tree. + */ + { + .virtual = IXP4XX_EXP_CFG_BASE_VIRT, + .pfn = __phys_to_pfn(IXP4XX_EXP_CFG_BASE_PHYS), + .length = SZ_4K, + .type = MT_DEVICE, + }, +#ifdef CONFIG_DEBUG_UART_8250 + /* This is needed for LL-debug/earlyprintk/debug-macro.S */ + { + .virtual = CONFIG_DEBUG_UART_VIRT, + .pfn = __phys_to_pfn(CONFIG_DEBUG_UART_PHYS), + .length = SZ_4K, + .type = MT_DEVICE, + }, +#endif +}; + +static void __init ixp4xx_of_map_io(void) +{ + iotable_init(ixp4xx_of_io_desc, ARRAY_SIZE(ixp4xx_of_io_desc)); +} + +/* + * We handle 4 differen SoC families. These compatible strings are enough + * to provide the core so that different boards can add their more detailed + * specifics. + */ +static const char *ixp4xx_of_board_compat[] = { + "intel,ixp42x", + "intel,ixp43x", + "intel,ixp45x", + "intel,ixp46x", + NULL, +}; + +DT_MACHINE_START(IXP4XX_DT, "IXP4xx (Device Tree)") + .map_io = ixp4xx_of_map_io, + .dt_compat = ixp4xx_of_board_compat, +MACHINE_END diff --git a/arch/arm/mach-ixp4xx/ixp4xx_npe.c b/arch/arm/mach-ixp4xx/ixp4xx_npe.c deleted file mode 100644 index d4eb09a62863..000000000000 --- a/arch/arm/mach-ixp4xx/ixp4xx_npe.c +++ /dev/null @@ -1,742 +0,0 @@ -/* - * Intel IXP4xx Network Processor Engine driver for Linux - * - * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - * - * The code is based on publicly available information: - * - Intel IXP4xx Developer's Manual and other e-papers - * - Intel IXP400 Access Library Software (BSD license) - * - previous works by Christian Hohnstaedt <chohnstaedt@innominate.com> - * Thanks, Christian. - */ - -#include <linux/delay.h> -#include <linux/dma-mapping.h> -#include <linux/firmware.h> -#include <linux/io.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <mach/npe.h> - -#define DEBUG_MSG 0 -#define DEBUG_FW 0 - -#define NPE_COUNT 3 -#define MAX_RETRIES 1000 /* microseconds */ -#define NPE_42X_DATA_SIZE 0x800 /* in dwords */ -#define NPE_46X_DATA_SIZE 0x1000 -#define NPE_A_42X_INSTR_SIZE 0x1000 -#define NPE_B_AND_C_42X_INSTR_SIZE 0x800 -#define NPE_46X_INSTR_SIZE 0x1000 -#define REGS_SIZE 0x1000 - -#define NPE_PHYS_REG 32 - -#define FW_MAGIC 0xFEEDF00D -#define FW_BLOCK_TYPE_INSTR 0x0 -#define FW_BLOCK_TYPE_DATA 0x1 -#define FW_BLOCK_TYPE_EOF 0xF - -/* NPE exec status (read) and command (write) */ -#define CMD_NPE_STEP 0x01 -#define CMD_NPE_START 0x02 -#define CMD_NPE_STOP 0x03 -#define CMD_NPE_CLR_PIPE 0x04 -#define CMD_CLR_PROFILE_CNT 0x0C -#define CMD_RD_INS_MEM 0x10 /* instruction memory */ -#define CMD_WR_INS_MEM 0x11 -#define CMD_RD_DATA_MEM 0x12 /* data memory */ -#define CMD_WR_DATA_MEM 0x13 -#define CMD_RD_ECS_REG 0x14 /* exec access register */ -#define CMD_WR_ECS_REG 0x15 - -#define STAT_RUN 0x80000000 -#define STAT_STOP 0x40000000 -#define STAT_CLEAR 0x20000000 -#define STAT_ECS_K 0x00800000 /* pipeline clean */ - -#define NPE_STEVT 0x1B -#define NPE_STARTPC 0x1C -#define NPE_REGMAP 0x1E -#define NPE_CINDEX 0x1F - -#define INSTR_WR_REG_SHORT 0x0000C000 -#define INSTR_WR_REG_BYTE 0x00004000 -#define INSTR_RD_FIFO 0x0F888220 -#define INSTR_RESET_MBOX 0x0FAC8210 - -#define ECS_BG_CTXT_REG_0 0x00 /* Background Executing Context */ -#define ECS_BG_CTXT_REG_1 0x01 /* Stack level */ -#define ECS_BG_CTXT_REG_2 0x02 -#define ECS_PRI_1_CTXT_REG_0 0x04 /* Priority 1 Executing Context */ -#define ECS_PRI_1_CTXT_REG_1 0x05 /* Stack level */ -#define ECS_PRI_1_CTXT_REG_2 0x06 -#define ECS_PRI_2_CTXT_REG_0 0x08 /* Priority 2 Executing Context */ -#define ECS_PRI_2_CTXT_REG_1 0x09 /* Stack level */ -#define ECS_PRI_2_CTXT_REG_2 0x0A -#define ECS_DBG_CTXT_REG_0 0x0C /* Debug Executing Context */ -#define ECS_DBG_CTXT_REG_1 0x0D /* Stack level */ -#define ECS_DBG_CTXT_REG_2 0x0E -#define ECS_INSTRUCT_REG 0x11 /* NPE Instruction Register */ - -#define ECS_REG_0_ACTIVE 0x80000000 /* all levels */ -#define ECS_REG_0_NEXTPC_MASK 0x1FFF0000 /* BG/PRI1/PRI2 levels */ -#define ECS_REG_0_LDUR_BITS 8 -#define ECS_REG_0_LDUR_MASK 0x00000700 /* all levels */ -#define ECS_REG_1_CCTXT_BITS 16 -#define ECS_REG_1_CCTXT_MASK 0x000F0000 /* all levels */ -#define ECS_REG_1_SELCTXT_BITS 0 -#define ECS_REG_1_SELCTXT_MASK 0x0000000F /* all levels */ -#define ECS_DBG_REG_2_IF 0x00100000 /* debug level */ -#define ECS_DBG_REG_2_IE 0x00080000 /* debug level */ - -/* NPE watchpoint_fifo register bit */ -#define WFIFO_VALID 0x80000000 - -/* NPE messaging_status register bit definitions */ -#define MSGSTAT_OFNE 0x00010000 /* OutFifoNotEmpty */ -#define MSGSTAT_IFNF 0x00020000 /* InFifoNotFull */ -#define MSGSTAT_OFNF 0x00040000 /* OutFifoNotFull */ -#define MSGSTAT_IFNE 0x00080000 /* InFifoNotEmpty */ -#define MSGSTAT_MBINT 0x00100000 /* Mailbox interrupt */ -#define MSGSTAT_IFINT 0x00200000 /* InFifo interrupt */ -#define MSGSTAT_OFINT 0x00400000 /* OutFifo interrupt */ -#define MSGSTAT_WFINT 0x00800000 /* WatchFifo interrupt */ - -/* NPE messaging_control register bit definitions */ -#define MSGCTL_OUT_FIFO 0x00010000 /* enable output FIFO */ -#define MSGCTL_IN_FIFO 0x00020000 /* enable input FIFO */ -#define MSGCTL_OUT_FIFO_WRITE 0x01000000 /* enable FIFO + WRITE */ -#define MSGCTL_IN_FIFO_WRITE 0x02000000 - -/* NPE mailbox_status value for reset */ -#define RESET_MBOX_STAT 0x0000F0F0 - -#define NPE_A_FIRMWARE "NPE-A" -#define NPE_B_FIRMWARE "NPE-B" -#define NPE_C_FIRMWARE "NPE-C" - -const char *npe_names[] = { NPE_A_FIRMWARE, NPE_B_FIRMWARE, NPE_C_FIRMWARE }; - -#define print_npe(pri, npe, fmt, ...) \ - printk(pri "%s: " fmt, npe_name(npe), ## __VA_ARGS__) - -#if DEBUG_MSG -#define debug_msg(npe, fmt, ...) \ - print_npe(KERN_DEBUG, npe, fmt, ## __VA_ARGS__) -#else -#define debug_msg(npe, fmt, ...) -#endif - -static struct { - u32 reg, val; -} ecs_reset[] = { - { ECS_BG_CTXT_REG_0, 0xA0000000 }, - { ECS_BG_CTXT_REG_1, 0x01000000 }, - { ECS_BG_CTXT_REG_2, 0x00008000 }, - { ECS_PRI_1_CTXT_REG_0, 0x20000080 }, - { ECS_PRI_1_CTXT_REG_1, 0x01000000 }, - { ECS_PRI_1_CTXT_REG_2, 0x00008000 }, - { ECS_PRI_2_CTXT_REG_0, 0x20000080 }, - { ECS_PRI_2_CTXT_REG_1, 0x01000000 }, - { ECS_PRI_2_CTXT_REG_2, 0x00008000 }, - { ECS_DBG_CTXT_REG_0, 0x20000000 }, - { ECS_DBG_CTXT_REG_1, 0x00000000 }, - { ECS_DBG_CTXT_REG_2, 0x001E0000 }, - { ECS_INSTRUCT_REG, 0x1003C00F }, -}; - -static struct npe npe_tab[NPE_COUNT] = { - { - .id = 0, - .regs = (struct npe_regs __iomem *)IXP4XX_NPEA_BASE_VIRT, - .regs_phys = IXP4XX_NPEA_BASE_PHYS, - }, { - .id = 1, - .regs = (struct npe_regs __iomem *)IXP4XX_NPEB_BASE_VIRT, - .regs_phys = IXP4XX_NPEB_BASE_PHYS, - }, { - .id = 2, - .regs = (struct npe_regs __iomem *)IXP4XX_NPEC_BASE_VIRT, - .regs_phys = IXP4XX_NPEC_BASE_PHYS, - } -}; - -int npe_running(struct npe *npe) -{ - return (__raw_readl(&npe->regs->exec_status_cmd) & STAT_RUN) != 0; -} - -static void npe_cmd_write(struct npe *npe, u32 addr, int cmd, u32 data) -{ - __raw_writel(data, &npe->regs->exec_data); - __raw_writel(addr, &npe->regs->exec_addr); - __raw_writel(cmd, &npe->regs->exec_status_cmd); -} - -static u32 npe_cmd_read(struct npe *npe, u32 addr, int cmd) -{ - __raw_writel(addr, &npe->regs->exec_addr); - __raw_writel(cmd, &npe->regs->exec_status_cmd); - /* Iintroduce extra read cycles after issuing read command to NPE - so that we read the register after the NPE has updated it. - This is to overcome race condition between XScale and NPE */ - __raw_readl(&npe->regs->exec_data); - __raw_readl(&npe->regs->exec_data); - return __raw_readl(&npe->regs->exec_data); -} - -static void npe_clear_active(struct npe *npe, u32 reg) -{ - u32 val = npe_cmd_read(npe, reg, CMD_RD_ECS_REG); - npe_cmd_write(npe, reg, CMD_WR_ECS_REG, val & ~ECS_REG_0_ACTIVE); -} - -static void npe_start(struct npe *npe) -{ - /* ensure only Background Context Stack Level is active */ - npe_clear_active(npe, ECS_PRI_1_CTXT_REG_0); - npe_clear_active(npe, ECS_PRI_2_CTXT_REG_0); - npe_clear_active(npe, ECS_DBG_CTXT_REG_0); - - __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd); - __raw_writel(CMD_NPE_START, &npe->regs->exec_status_cmd); -} - -static void npe_stop(struct npe *npe) -{ - __raw_writel(CMD_NPE_STOP, &npe->regs->exec_status_cmd); - __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd); /*FIXME?*/ -} - -static int __must_check npe_debug_instr(struct npe *npe, u32 instr, u32 ctx, - u32 ldur) -{ - u32 wc; - int i; - - /* set the Active bit, and the LDUR, in the debug level */ - npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG, - ECS_REG_0_ACTIVE | (ldur << ECS_REG_0_LDUR_BITS)); - - /* set CCTXT at ECS DEBUG L3 to specify in which context to execute - the instruction, and set SELCTXT at ECS DEBUG Level to specify - which context store to access. - Debug ECS Level Reg 1 has form 0x000n000n, where n = context number - */ - npe_cmd_write(npe, ECS_DBG_CTXT_REG_1, CMD_WR_ECS_REG, - (ctx << ECS_REG_1_CCTXT_BITS) | - (ctx << ECS_REG_1_SELCTXT_BITS)); - - /* clear the pipeline */ - __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd); - - /* load NPE instruction into the instruction register */ - npe_cmd_write(npe, ECS_INSTRUCT_REG, CMD_WR_ECS_REG, instr); - - /* we need this value later to wait for completion of NPE execution - step */ - wc = __raw_readl(&npe->regs->watch_count); - - /* issue a Step One command via the Execution Control register */ - __raw_writel(CMD_NPE_STEP, &npe->regs->exec_status_cmd); - - /* Watch Count register increments when NPE completes an instruction */ - for (i = 0; i < MAX_RETRIES; i++) { - if (wc != __raw_readl(&npe->regs->watch_count)) - return 0; - udelay(1); - } - - print_npe(KERN_ERR, npe, "reset: npe_debug_instr(): timeout\n"); - return -ETIMEDOUT; -} - -static int __must_check npe_logical_reg_write8(struct npe *npe, u32 addr, - u8 val, u32 ctx) -{ - /* here we build the NPE assembler instruction: mov8 d0, #0 */ - u32 instr = INSTR_WR_REG_BYTE | /* OpCode */ - addr << 9 | /* base Operand */ - (val & 0x1F) << 4 | /* lower 5 bits to immediate data */ - (val & ~0x1F) << (18 - 5);/* higher 3 bits to CoProc instr. */ - return npe_debug_instr(npe, instr, ctx, 1); /* execute it */ -} - -static int __must_check npe_logical_reg_write16(struct npe *npe, u32 addr, - u16 val, u32 ctx) -{ - /* here we build the NPE assembler instruction: mov16 d0, #0 */ - u32 instr = INSTR_WR_REG_SHORT | /* OpCode */ - addr << 9 | /* base Operand */ - (val & 0x1F) << 4 | /* lower 5 bits to immediate data */ - (val & ~0x1F) << (18 - 5);/* higher 11 bits to CoProc instr. */ - return npe_debug_instr(npe, instr, ctx, 1); /* execute it */ -} - -static int __must_check npe_logical_reg_write32(struct npe *npe, u32 addr, - u32 val, u32 ctx) -{ - /* write in 16 bit steps first the high and then the low value */ - if (npe_logical_reg_write16(npe, addr, val >> 16, ctx)) - return -ETIMEDOUT; - return npe_logical_reg_write16(npe, addr + 2, val & 0xFFFF, ctx); -} - -static int npe_reset(struct npe *npe) -{ - u32 val, ctl, exec_count, ctx_reg2; - int i; - - ctl = (__raw_readl(&npe->regs->messaging_control) | 0x3F000000) & - 0x3F3FFFFF; - - /* disable parity interrupt */ - __raw_writel(ctl & 0x3F00FFFF, &npe->regs->messaging_control); - - /* pre exec - debug instruction */ - /* turn off the halt bit by clearing Execution Count register. */ - exec_count = __raw_readl(&npe->regs->exec_count); - __raw_writel(0, &npe->regs->exec_count); - /* ensure that IF and IE are on (temporarily), so that we don't end up - stepping forever */ - ctx_reg2 = npe_cmd_read(npe, ECS_DBG_CTXT_REG_2, CMD_RD_ECS_REG); - npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2 | - ECS_DBG_REG_2_IF | ECS_DBG_REG_2_IE); - - /* clear the FIFOs */ - while (__raw_readl(&npe->regs->watchpoint_fifo) & WFIFO_VALID) - ; - while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE) - /* read from the outFIFO until empty */ - print_npe(KERN_DEBUG, npe, "npe_reset: read FIFO = 0x%X\n", - __raw_readl(&npe->regs->in_out_fifo)); - - while (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE) - /* step execution of the NPE intruction to read inFIFO using - the Debug Executing Context stack */ - if (npe_debug_instr(npe, INSTR_RD_FIFO, 0, 0)) - return -ETIMEDOUT; - - /* reset the mailbox reg from the XScale side */ - __raw_writel(RESET_MBOX_STAT, &npe->regs->mailbox_status); - /* from NPE side */ - if (npe_debug_instr(npe, INSTR_RESET_MBOX, 0, 0)) - return -ETIMEDOUT; - - /* Reset the physical registers in the NPE register file */ - for (val = 0; val < NPE_PHYS_REG; val++) { - if (npe_logical_reg_write16(npe, NPE_REGMAP, val >> 1, 0)) - return -ETIMEDOUT; - /* address is either 0 or 4 */ - if (npe_logical_reg_write32(npe, (val & 1) * 4, 0, 0)) - return -ETIMEDOUT; - } - - /* Reset the context store = each context's Context Store registers */ - - /* Context 0 has no STARTPC. Instead, this value is used to set NextPC - for Background ECS, to set where NPE starts executing code */ - val = npe_cmd_read(npe, ECS_BG_CTXT_REG_0, CMD_RD_ECS_REG); - val &= ~ECS_REG_0_NEXTPC_MASK; - val |= (0 /* NextPC */ << 16) & ECS_REG_0_NEXTPC_MASK; - npe_cmd_write(npe, ECS_BG_CTXT_REG_0, CMD_WR_ECS_REG, val); - - for (i = 0; i < 16; i++) { - if (i) { /* Context 0 has no STEVT nor STARTPC */ - /* STEVT = off, 0x80 */ - if (npe_logical_reg_write8(npe, NPE_STEVT, 0x80, i)) - return -ETIMEDOUT; - if (npe_logical_reg_write16(npe, NPE_STARTPC, 0, i)) - return -ETIMEDOUT; - } - /* REGMAP = d0->p0, d8->p2, d16->p4 */ - if (npe_logical_reg_write16(npe, NPE_REGMAP, 0x820, i)) - return -ETIMEDOUT; - if (npe_logical_reg_write8(npe, NPE_CINDEX, 0, i)) - return -ETIMEDOUT; - } - - /* post exec */ - /* clear active bit in debug level */ - npe_cmd_write(npe, ECS_DBG_CTXT_REG_0, CMD_WR_ECS_REG, 0); - /* clear the pipeline */ - __raw_writel(CMD_NPE_CLR_PIPE, &npe->regs->exec_status_cmd); - /* restore previous values */ - __raw_writel(exec_count, &npe->regs->exec_count); - npe_cmd_write(npe, ECS_DBG_CTXT_REG_2, CMD_WR_ECS_REG, ctx_reg2); - - /* write reset values to Execution Context Stack registers */ - for (val = 0; val < ARRAY_SIZE(ecs_reset); val++) - npe_cmd_write(npe, ecs_reset[val].reg, CMD_WR_ECS_REG, - ecs_reset[val].val); - - /* clear the profile counter */ - __raw_writel(CMD_CLR_PROFILE_CNT, &npe->regs->exec_status_cmd); - - __raw_writel(0, &npe->regs->exec_count); - __raw_writel(0, &npe->regs->action_points[0]); - __raw_writel(0, &npe->regs->action_points[1]); - __raw_writel(0, &npe->regs->action_points[2]); - __raw_writel(0, &npe->regs->action_points[3]); - __raw_writel(0, &npe->regs->watch_count); - - val = ixp4xx_read_feature_bits(); - /* reset the NPE */ - ixp4xx_write_feature_bits(val & - ~(IXP4XX_FEATURE_RESET_NPEA << npe->id)); - /* deassert reset */ - ixp4xx_write_feature_bits(val | - (IXP4XX_FEATURE_RESET_NPEA << npe->id)); - for (i = 0; i < MAX_RETRIES; i++) { - if (ixp4xx_read_feature_bits() & - (IXP4XX_FEATURE_RESET_NPEA << npe->id)) - break; /* NPE is back alive */ - udelay(1); - } - if (i == MAX_RETRIES) - return -ETIMEDOUT; - - npe_stop(npe); - - /* restore NPE configuration bus Control Register - parity settings */ - __raw_writel(ctl, &npe->regs->messaging_control); - return 0; -} - - -int npe_send_message(struct npe *npe, const void *msg, const char *what) -{ - const u32 *send = msg; - int cycles = 0; - - debug_msg(npe, "Trying to send message %s [%08X:%08X]\n", - what, send[0], send[1]); - - if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE) { - debug_msg(npe, "NPE input FIFO not empty\n"); - return -EIO; - } - - __raw_writel(send[0], &npe->regs->in_out_fifo); - - if (!(__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNF)) { - debug_msg(npe, "NPE input FIFO full\n"); - return -EIO; - } - - __raw_writel(send[1], &npe->regs->in_out_fifo); - - while ((cycles < MAX_RETRIES) && - (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_IFNE)) { - udelay(1); - cycles++; - } - - if (cycles == MAX_RETRIES) { - debug_msg(npe, "Timeout sending message\n"); - return -ETIMEDOUT; - } - -#if DEBUG_MSG > 1 - debug_msg(npe, "Sending a message took %i cycles\n", cycles); -#endif - return 0; -} - -int npe_recv_message(struct npe *npe, void *msg, const char *what) -{ - u32 *recv = msg; - int cycles = 0, cnt = 0; - - debug_msg(npe, "Trying to receive message %s\n", what); - - while (cycles < MAX_RETRIES) { - if (__raw_readl(&npe->regs->messaging_status) & MSGSTAT_OFNE) { - recv[cnt++] = __raw_readl(&npe->regs->in_out_fifo); - if (cnt == 2) - break; - } else { - udelay(1); - cycles++; - } - } - - switch(cnt) { - case 1: - debug_msg(npe, "Received [%08X]\n", recv[0]); - break; - case 2: - debug_msg(npe, "Received [%08X:%08X]\n", recv[0], recv[1]); - break; - } - - if (cycles == MAX_RETRIES) { - debug_msg(npe, "Timeout waiting for message\n"); - return -ETIMEDOUT; - } - -#if DEBUG_MSG > 1 - debug_msg(npe, "Receiving a message took %i cycles\n", cycles); -#endif - return 0; -} - -int npe_send_recv_message(struct npe *npe, void *msg, const char *what) -{ - int result; - u32 *send = msg, recv[2]; - - if ((result = npe_send_message(npe, msg, what)) != 0) - return result; - if ((result = npe_recv_message(npe, recv, what)) != 0) - return result; - - if ((recv[0] != send[0]) || (recv[1] != send[1])) { - debug_msg(npe, "Message %s: unexpected message received\n", - what); - return -EIO; - } - return 0; -} - - -int npe_load_firmware(struct npe *npe, const char *name, struct device *dev) -{ - const struct firmware *fw_entry; - - struct dl_block { - u32 type; - u32 offset; - } *blk; - - struct dl_image { - u32 magic; - u32 id; - u32 size; - union { - u32 data[0]; - struct dl_block blocks[0]; - }; - } *image; - - struct dl_codeblock { - u32 npe_addr; - u32 size; - u32 data[0]; - } *cb; - - int i, j, err, data_size, instr_size, blocks, table_end; - u32 cmd; - - if ((err = request_firmware(&fw_entry, name, dev)) != 0) - return err; - - err = -EINVAL; - if (fw_entry->size < sizeof(struct dl_image)) { - print_npe(KERN_ERR, npe, "incomplete firmware file\n"); - goto err; - } - image = (struct dl_image*)fw_entry->data; - -#if DEBUG_FW - print_npe(KERN_DEBUG, npe, "firmware: %08X %08X %08X (0x%X bytes)\n", - image->magic, image->id, image->size, image->size * 4); -#endif - - if (image->magic == swab32(FW_MAGIC)) { /* swapped file */ - image->id = swab32(image->id); - image->size = swab32(image->size); - } else if (image->magic != FW_MAGIC) { - print_npe(KERN_ERR, npe, "bad firmware file magic: 0x%X\n", - image->magic); - goto err; - } - if ((image->size * 4 + sizeof(struct dl_image)) != fw_entry->size) { - print_npe(KERN_ERR, npe, - "inconsistent size of firmware file\n"); - goto err; - } - if (((image->id >> 24) & 0xF /* NPE ID */) != npe->id) { - print_npe(KERN_ERR, npe, "firmware file NPE ID mismatch\n"); - goto err; - } - if (image->magic == swab32(FW_MAGIC)) - for (i = 0; i < image->size; i++) - image->data[i] = swab32(image->data[i]); - - if (cpu_is_ixp42x() && ((image->id >> 28) & 0xF /* device ID */)) { - print_npe(KERN_INFO, npe, "IXP43x/IXP46x firmware ignored on " - "IXP42x\n"); - goto err; - } - - if (npe_running(npe)) { - print_npe(KERN_INFO, npe, "unable to load firmware, NPE is " - "already running\n"); - err = -EBUSY; - goto err; - } -#if 0 - npe_stop(npe); - npe_reset(npe); -#endif - - print_npe(KERN_INFO, npe, "firmware functionality 0x%X, " - "revision 0x%X:%X\n", (image->id >> 16) & 0xFF, - (image->id >> 8) & 0xFF, image->id & 0xFF); - - if (cpu_is_ixp42x()) { - if (!npe->id) - instr_size = NPE_A_42X_INSTR_SIZE; - else - instr_size = NPE_B_AND_C_42X_INSTR_SIZE; - data_size = NPE_42X_DATA_SIZE; - } else { - instr_size = NPE_46X_INSTR_SIZE; - data_size = NPE_46X_DATA_SIZE; - } - - for (blocks = 0; blocks * sizeof(struct dl_block) / 4 < image->size; - blocks++) - if (image->blocks[blocks].type == FW_BLOCK_TYPE_EOF) - break; - if (blocks * sizeof(struct dl_block) / 4 >= image->size) { - print_npe(KERN_INFO, npe, "firmware EOF block marker not " - "found\n"); - goto err; - } - -#if DEBUG_FW - print_npe(KERN_DEBUG, npe, "%i firmware blocks found\n", blocks); -#endif - - table_end = blocks * sizeof(struct dl_block) / 4 + 1 /* EOF marker */; - for (i = 0, blk = image->blocks; i < blocks; i++, blk++) { - if (blk->offset > image->size - sizeof(struct dl_codeblock) / 4 - || blk->offset < table_end) { - print_npe(KERN_INFO, npe, "invalid offset 0x%X of " - "firmware block #%i\n", blk->offset, i); - goto err; - } - - cb = (struct dl_codeblock*)&image->data[blk->offset]; - if (blk->type == FW_BLOCK_TYPE_INSTR) { - if (cb->npe_addr + cb->size > instr_size) - goto too_big; - cmd = CMD_WR_INS_MEM; - } else if (blk->type == FW_BLOCK_TYPE_DATA) { - if (cb->npe_addr + cb->size > data_size) - goto too_big; - cmd = CMD_WR_DATA_MEM; - } else { - print_npe(KERN_INFO, npe, "invalid firmware block #%i " - "type 0x%X\n", i, blk->type); - goto err; - } - if (blk->offset + sizeof(*cb) / 4 + cb->size > image->size) { - print_npe(KERN_INFO, npe, "firmware block #%i doesn't " - "fit in firmware image: type %c, start 0x%X," - " length 0x%X\n", i, - blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D', - cb->npe_addr, cb->size); - goto err; - } - - for (j = 0; j < cb->size; j++) - npe_cmd_write(npe, cb->npe_addr + j, cmd, cb->data[j]); - } - - npe_start(npe); - if (!npe_running(npe)) - print_npe(KERN_ERR, npe, "unable to start\n"); - release_firmware(fw_entry); - return 0; - -too_big: - print_npe(KERN_INFO, npe, "firmware block #%i doesn't fit in NPE " - "memory: type %c, start 0x%X, length 0x%X\n", i, - blk->type == FW_BLOCK_TYPE_INSTR ? 'I' : 'D', - cb->npe_addr, cb->size); -err: - release_firmware(fw_entry); - return err; -} - - -struct npe *npe_request(unsigned id) -{ - if (id < NPE_COUNT) - if (npe_tab[id].valid) - if (try_module_get(THIS_MODULE)) - return &npe_tab[id]; - return NULL; -} - -void npe_release(struct npe *npe) -{ - module_put(THIS_MODULE); -} - - -static int __init npe_init_module(void) -{ - - int i, found = 0; - - for (i = 0; i < NPE_COUNT; i++) { - struct npe *npe = &npe_tab[i]; - if (!(ixp4xx_read_feature_bits() & - (IXP4XX_FEATURE_RESET_NPEA << i))) - continue; /* NPE already disabled or not present */ - if (!(npe->mem_res = request_mem_region(npe->regs_phys, - REGS_SIZE, - npe_name(npe)))) { - print_npe(KERN_ERR, npe, - "failed to request memory region\n"); - continue; - } - - if (npe_reset(npe)) - continue; - npe->valid = 1; - found++; - } - - if (!found) - return -ENODEV; - return 0; -} - -static void __exit npe_cleanup_module(void) -{ - int i; - - for (i = 0; i < NPE_COUNT; i++) - if (npe_tab[i].mem_res) { - npe_reset(&npe_tab[i]); - release_resource(npe_tab[i].mem_res); - } -} - -module_init(npe_init_module); -module_exit(npe_cleanup_module); - -MODULE_AUTHOR("Krzysztof Halasa"); -MODULE_LICENSE("GPL v2"); -MODULE_FIRMWARE(NPE_A_FIRMWARE); -MODULE_FIRMWARE(NPE_B_FIRMWARE); -MODULE_FIRMWARE(NPE_C_FIRMWARE); - -EXPORT_SYMBOL(npe_names); -EXPORT_SYMBOL(npe_running); -EXPORT_SYMBOL(npe_request); -EXPORT_SYMBOL(npe_release); -EXPORT_SYMBOL(npe_load_firmware); -EXPORT_SYMBOL(npe_send_message); -EXPORT_SYMBOL(npe_recv_message); -EXPORT_SYMBOL(npe_send_recv_message); diff --git a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c b/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c deleted file mode 100644 index 9d1b6b7c394c..000000000000 --- a/arch/arm/mach-ixp4xx/ixp4xx_qmgr.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Intel IXP4xx Queue Manager driver for Linux - * - * Copyright (C) 2007 Krzysztof Halasa <khc@pm.waw.pl> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - */ - -#include <linux/ioport.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <mach/qmgr.h> - -static struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; -static struct resource *mem_res; -static spinlock_t qmgr_lock; -static u32 used_sram_bitmap[4]; /* 128 16-dword pages */ -static void (*irq_handlers[QUEUES])(void *pdev); -static void *irq_pdevs[QUEUES]; - -#if DEBUG_QMGR -char qmgr_queue_descs[QUEUES][32]; -#endif - -void qmgr_set_irq(unsigned int queue, int src, - void (*handler)(void *pdev), void *pdev) -{ - unsigned long flags; - - spin_lock_irqsave(&qmgr_lock, flags); - if (queue < HALF_QUEUES) { - u32 __iomem *reg; - int bit; - BUG_ON(src > QUEUE_IRQ_SRC_NOT_FULL); - reg = &qmgr_regs->irqsrc[queue >> 3]; /* 8 queues per u32 */ - bit = (queue % 8) * 4; /* 3 bits + 1 reserved bit per queue */ - __raw_writel((__raw_readl(reg) & ~(7 << bit)) | (src << bit), - reg); - } else - /* IRQ source for queues 32-63 is fixed */ - BUG_ON(src != QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY); - - irq_handlers[queue] = handler; - irq_pdevs[queue] = pdev; - spin_unlock_irqrestore(&qmgr_lock, flags); -} - - -static irqreturn_t qmgr_irq1_a0(int irq, void *pdev) -{ - int i, ret = 0; - u32 en_bitmap, src, stat; - - /* ACK - it may clear any bits so don't rely on it */ - __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[0]); - - en_bitmap = qmgr_regs->irqen[0]; - while (en_bitmap) { - i = __fls(en_bitmap); /* number of the last "low" queue */ - en_bitmap &= ~BIT(i); - src = qmgr_regs->irqsrc[i >> 3]; - stat = qmgr_regs->stat1[i >> 3]; - if (src & 4) /* the IRQ condition is inverted */ - stat = ~stat; - if (stat & BIT(src & 3)) { - irq_handlers[i](irq_pdevs[i]); - ret = IRQ_HANDLED; - } - } - return ret; -} - - -static irqreturn_t qmgr_irq2_a0(int irq, void *pdev) -{ - int i, ret = 0; - u32 req_bitmap; - - /* ACK - it may clear any bits so don't rely on it */ - __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[1]); - - req_bitmap = qmgr_regs->irqen[1] & qmgr_regs->statne_h; - while (req_bitmap) { - i = __fls(req_bitmap); /* number of the last "high" queue */ - req_bitmap &= ~BIT(i); - irq_handlers[HALF_QUEUES + i](irq_pdevs[HALF_QUEUES + i]); - ret = IRQ_HANDLED; - } - return ret; -} - - -static irqreturn_t qmgr_irq(int irq, void *pdev) -{ - int i, half = (irq == IRQ_IXP4XX_QM1 ? 0 : 1); - u32 req_bitmap = __raw_readl(&qmgr_regs->irqstat[half]); - - if (!req_bitmap) - return 0; - __raw_writel(req_bitmap, &qmgr_regs->irqstat[half]); /* ACK */ - - while (req_bitmap) { - i = __fls(req_bitmap); /* number of the last queue */ - req_bitmap &= ~BIT(i); - i += half * HALF_QUEUES; - irq_handlers[i](irq_pdevs[i]); - } - return IRQ_HANDLED; -} - - -void qmgr_enable_irq(unsigned int queue) -{ - unsigned long flags; - int half = queue / 32; - u32 mask = 1 << (queue & (HALF_QUEUES - 1)); - - spin_lock_irqsave(&qmgr_lock, flags); - __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) | mask, - &qmgr_regs->irqen[half]); - spin_unlock_irqrestore(&qmgr_lock, flags); -} - -void qmgr_disable_irq(unsigned int queue) -{ - unsigned long flags; - int half = queue / 32; - u32 mask = 1 << (queue & (HALF_QUEUES - 1)); - - spin_lock_irqsave(&qmgr_lock, flags); - __raw_writel(__raw_readl(&qmgr_regs->irqen[half]) & ~mask, - &qmgr_regs->irqen[half]); - __raw_writel(mask, &qmgr_regs->irqstat[half]); /* clear */ - spin_unlock_irqrestore(&qmgr_lock, flags); -} - -static inline void shift_mask(u32 *mask) -{ - mask[3] = mask[3] << 1 | mask[2] >> 31; - mask[2] = mask[2] << 1 | mask[1] >> 31; - mask[1] = mask[1] << 1 | mask[0] >> 31; - mask[0] <<= 1; -} - -#if DEBUG_QMGR -int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, - unsigned int nearly_empty_watermark, - unsigned int nearly_full_watermark, - const char *desc_format, const char* name) -#else -int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, - unsigned int nearly_empty_watermark, - unsigned int nearly_full_watermark) -#endif -{ - u32 cfg, addr = 0, mask[4]; /* in 16-dwords */ - int err; - - BUG_ON(queue >= QUEUES); - - if ((nearly_empty_watermark | nearly_full_watermark) & ~7) - return -EINVAL; - - switch (len) { - case 16: - cfg = 0 << 24; - mask[0] = 0x1; - break; - case 32: - cfg = 1 << 24; - mask[0] = 0x3; - break; - case 64: - cfg = 2 << 24; - mask[0] = 0xF; - break; - case 128: - cfg = 3 << 24; - mask[0] = 0xFF; - break; - default: - return -EINVAL; - } - - cfg |= nearly_empty_watermark << 26; - cfg |= nearly_full_watermark << 29; - len /= 16; /* in 16-dwords: 1, 2, 4 or 8 */ - mask[1] = mask[2] = mask[3] = 0; - - if (!try_module_get(THIS_MODULE)) - return -ENODEV; - - spin_lock_irq(&qmgr_lock); - if (__raw_readl(&qmgr_regs->sram[queue])) { - err = -EBUSY; - goto err; - } - - while (1) { - if (!(used_sram_bitmap[0] & mask[0]) && - !(used_sram_bitmap[1] & mask[1]) && - !(used_sram_bitmap[2] & mask[2]) && - !(used_sram_bitmap[3] & mask[3])) - break; /* found free space */ - - addr++; - shift_mask(mask); - if (addr + len > ARRAY_SIZE(qmgr_regs->sram)) { - printk(KERN_ERR "qmgr: no free SRAM space for" - " queue %i\n", queue); - err = -ENOMEM; - goto err; - } - } - - used_sram_bitmap[0] |= mask[0]; - used_sram_bitmap[1] |= mask[1]; - used_sram_bitmap[2] |= mask[2]; - used_sram_bitmap[3] |= mask[3]; - __raw_writel(cfg | (addr << 14), &qmgr_regs->sram[queue]); -#if DEBUG_QMGR - snprintf(qmgr_queue_descs[queue], sizeof(qmgr_queue_descs[0]), - desc_format, name); - printk(KERN_DEBUG "qmgr: requested queue %s(%i) addr = 0x%02X\n", - qmgr_queue_descs[queue], queue, addr); -#endif - spin_unlock_irq(&qmgr_lock); - return 0; - -err: - spin_unlock_irq(&qmgr_lock); - module_put(THIS_MODULE); - return err; -} - -void qmgr_release_queue(unsigned int queue) -{ - u32 cfg, addr, mask[4]; - - BUG_ON(queue >= QUEUES); /* not in valid range */ - - spin_lock_irq(&qmgr_lock); - cfg = __raw_readl(&qmgr_regs->sram[queue]); - addr = (cfg >> 14) & 0xFF; - - BUG_ON(!addr); /* not requested */ - - switch ((cfg >> 24) & 3) { - case 0: mask[0] = 0x1; break; - case 1: mask[0] = 0x3; break; - case 2: mask[0] = 0xF; break; - case 3: mask[0] = 0xFF; break; - } - - mask[1] = mask[2] = mask[3] = 0; - - while (addr--) - shift_mask(mask); - -#if DEBUG_QMGR - printk(KERN_DEBUG "qmgr: releasing queue %s(%i)\n", - qmgr_queue_descs[queue], queue); - qmgr_queue_descs[queue][0] = '\x0'; -#endif - - while ((addr = qmgr_get_entry(queue))) - printk(KERN_ERR "qmgr: released queue %i not empty: 0x%08X\n", - queue, addr); - - __raw_writel(0, &qmgr_regs->sram[queue]); - - used_sram_bitmap[0] &= ~mask[0]; - used_sram_bitmap[1] &= ~mask[1]; - used_sram_bitmap[2] &= ~mask[2]; - used_sram_bitmap[3] &= ~mask[3]; - irq_handlers[queue] = NULL; /* catch IRQ bugs */ - spin_unlock_irq(&qmgr_lock); - - module_put(THIS_MODULE); -} - -static int qmgr_init(void) -{ - int i, err; - irq_handler_t handler1, handler2; - - mem_res = request_mem_region(IXP4XX_QMGR_BASE_PHYS, - IXP4XX_QMGR_REGION_SIZE, - "IXP4xx Queue Manager"); - if (mem_res == NULL) - return -EBUSY; - - /* reset qmgr registers */ - for (i = 0; i < 4; i++) { - __raw_writel(0x33333333, &qmgr_regs->stat1[i]); - __raw_writel(0, &qmgr_regs->irqsrc[i]); - } - for (i = 0; i < 2; i++) { - __raw_writel(0, &qmgr_regs->stat2[i]); - __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[i]); /* clear */ - __raw_writel(0, &qmgr_regs->irqen[i]); - } - - __raw_writel(0xFFFFFFFF, &qmgr_regs->statne_h); - __raw_writel(0, &qmgr_regs->statf_h); - - for (i = 0; i < QUEUES; i++) - __raw_writel(0, &qmgr_regs->sram[i]); - - if (cpu_is_ixp42x_rev_a0()) { - handler1 = qmgr_irq1_a0; - handler2 = qmgr_irq2_a0; - } else - handler1 = handler2 = qmgr_irq; - - err = request_irq(IRQ_IXP4XX_QM1, handler1, 0, "IXP4xx Queue Manager", - NULL); - if (err) { - printk(KERN_ERR "qmgr: failed to request IRQ%i (%i)\n", - IRQ_IXP4XX_QM1, err); - goto error_irq; - } - - err = request_irq(IRQ_IXP4XX_QM2, handler2, 0, "IXP4xx Queue Manager", - NULL); - if (err) { - printk(KERN_ERR "qmgr: failed to request IRQ%i (%i)\n", - IRQ_IXP4XX_QM2, err); - goto error_irq2; - } - - used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */ - spin_lock_init(&qmgr_lock); - - printk(KERN_INFO "IXP4xx Queue Manager initialized.\n"); - return 0; - -error_irq2: - free_irq(IRQ_IXP4XX_QM1, NULL); -error_irq: - release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE); - return err; -} - -static void qmgr_remove(void) -{ - free_irq(IRQ_IXP4XX_QM1, NULL); - free_irq(IRQ_IXP4XX_QM2, NULL); - synchronize_irq(IRQ_IXP4XX_QM1); - synchronize_irq(IRQ_IXP4XX_QM2); - release_mem_region(IXP4XX_QMGR_BASE_PHYS, IXP4XX_QMGR_REGION_SIZE); -} - -module_init(qmgr_init); -module_exit(qmgr_remove); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Krzysztof Halasa"); - -EXPORT_SYMBOL(qmgr_set_irq); -EXPORT_SYMBOL(qmgr_enable_irq); -EXPORT_SYMBOL(qmgr_disable_irq); -#if DEBUG_QMGR -EXPORT_SYMBOL(qmgr_queue_descs); -EXPORT_SYMBOL(qmgr_request_queue); -#else -EXPORT_SYMBOL(__qmgr_request_queue); -#endif -EXPORT_SYMBOL(qmgr_release_queue); diff --git a/arch/arm/mach-ixp4xx/nas100d-pci.c b/arch/arm/mach-ixp4xx/nas100d-pci.c index 8f0eba0a6800..925ef805f966 100644 --- a/arch/arm/mach-ixp4xx/nas100d-pci.c +++ b/arch/arm/mach-ixp4xx/nas100d-pci.c @@ -21,6 +21,8 @@ #include <asm/mach/pci.h> #include <asm/mach-types.h> +#include "irqs.h" + #define MAX_DEV 3 #define IRQ_LINES 3 diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c index 4138d6aa4c52..c142cfa8c5d6 100644 --- a/arch/arm/mach-ixp4xx/nas100d-setup.c +++ b/arch/arm/mach-ixp4xx/nas100d-setup.c @@ -34,6 +34,8 @@ #include <asm/mach/arch.h> #include <asm/mach/flash.h> +#include "irqs.h" + #define NAS100D_SDA_PIN 5 #define NAS100D_SCL_PIN 6 @@ -279,9 +281,6 @@ static void __init nas100d_init(void) ixp4xx_sys_init(); - /* gpio 14 and 15 are _not_ clocks */ - *IXP4XX_GPIO_GPCLKR = 0; - nas100d_flash_resource.start = IXP4XX_EXP_BUS_BASE(0); nas100d_flash_resource.end = IXP4XX_EXP_BUS_BASE(0) + ixp4xx_exp_bus_size - 1; diff --git a/arch/arm/mach-ixp4xx/nslu2-pci.c b/arch/arm/mach-ixp4xx/nslu2-pci.c index 032defe111aa..d69ee4066d20 100644 --- a/arch/arm/mach-ixp4xx/nslu2-pci.c +++ b/arch/arm/mach-ixp4xx/nslu2-pci.c @@ -21,6 +21,8 @@ #include <asm/mach/pci.h> #include <asm/mach-types.h> +#include "irqs.h" + #define MAX_DEV 3 #define IRQ_LINES 3 diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c index 341b263482ef..ee1877fcfafe 100644 --- a/arch/arm/mach-ixp4xx/nslu2-setup.c +++ b/arch/arm/mach-ixp4xx/nslu2-setup.c @@ -32,6 +32,8 @@ #include <asm/mach/flash.h> #include <asm/mach/time.h> +#include "irqs.h" + #define NSLU2_SDA_PIN 7 #define NSLU2_SCL_PIN 6 @@ -125,10 +127,18 @@ static struct platform_device nslu2_i2c_gpio = { }, }; +static struct resource nslu2_beeper_resources[] = { + { + .start = IRQ_IXP4XX_TIMER2, + .flags = IORESOURCE_IRQ, + }, +}; + static struct platform_device nslu2_beeper = { .name = "ixp4xx-beeper", .id = NSLU2_GPIO_BUZZ, - .num_resources = 0, + .resource = nslu2_beeper_resources, + .num_resources = ARRAY_SIZE(nslu2_beeper_resources), }; static struct resource nslu2_uart_resources[] = { diff --git a/arch/arm/mach-ixp4xx/wg302v2-pci.c b/arch/arm/mach-ixp4xx/wg302v2-pci.c index c92e5b82af36..cf83f7e24179 100644 --- a/arch/arm/mach-ixp4xx/wg302v2-pci.c +++ b/arch/arm/mach-ixp4xx/wg302v2-pci.c @@ -27,6 +27,8 @@ #include <asm/mach/pci.h> +#include "irqs.h" + void __init wg302v2_pci_preinit(void) { irq_set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW); diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c index 90b3c604e8b6..8711e299229b 100644 --- a/arch/arm/mach-ixp4xx/wg302v2-setup.c +++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c @@ -29,6 +29,8 @@ #include <asm/mach/arch.h> #include <asm/mach/flash.h> +#include "irqs.h" + static struct flash_platform_data wg302v2_flash_data = { .map_name = "cfi_probe", .width = 2, |