Commit 1895ef4e authored by Olof Johansson's avatar Olof Johansson

Merge tag 'ixp4xx-for-armsoc' of...

Merge tag 'ixp4xx-for-armsoc' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik into arm/soc

This modernizes the IXP4xx platform and adds initial Device Tree
Support. We migrate to MULTI_IRQ_HANDLER, bumps the IRQs to
offset 16, converts to SPARSE_IRQ, then we add proper subsystem
drivers in each subsystem for irqchip, GPIO and clocksource and
switch over to using these new drivers.

Next we modernize the NPE and QMGR drivers and push them down
into drivers/soc.

This has been tested on the IXP4xx NSLU2 and the Gateworks
GW2358-4.

* tag 'ixp4xx-for-armsoc' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-nomadik: (31 commits)
  ARM: dts: Add queue manager and NPE to the IXP4xx DTSI
  soc: ixp4xx: qmgr: Add DT probe code
  soc: ixp4xx: qmgr: Add DT bindings for IXP4xx qmgr
  soc: ixp4xx: npe: Add DT probe code
  soc: ixp4xx: Add DT bindings for IXP4xx NPE
  soc: ixp4xx: qmgr: Pass resources
  soc: ixp4xx: Remove unused functions
  soc: ixp4xx: Uninline several functions
  soc: ixp4xx: npe: Pass addresses as resources
  ARM: ixp4xx: Turn the QMGR into a platform device
  ARM: ixp4xx: Turn the NPE into a platform device
  ARM: ixp4xx: Move IXP4xx QMGR and NPE headers
  ARM: ixp4xx: Move NPE and QMGR to drivers/soc
  ARM: dts: Add some initial IXP4xx device trees
  ARM: ixp4xx: Add device tree boot support
  ARM: ixp4xx: Add DT bindings
  gpio: ixp4xx: Add OF probing support
  gpio: ixp4xx: Add DT bindings
  clocksource/drivers/ixp4xx: Add OF initialization support
  clocksource/drivers/ixp4xx: Add DT bindings
  ...
Signed-off-by: default avatarOlof Johansson <olof@lixom.net>
parents 6a508f98 1fae0ad1
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/arm/intel-ixp4xx.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel IXP4xx Device Tree Bindings
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
properties:
compatible:
oneOf:
- items:
- enum:
- linksys,nslu2
- const: intel,ixp42x
- items:
- enum:
- gateworks,gw2358
- const: intel,ixp43x
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2019 Linaro Ltd.
%YAML 1.2
---
$id: "http://devicetree.org/schemas/firmware/intel-ixp4xx-network-processing-engine.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Intel IXP4xx Network Processing Engine
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
description: |
On the IXP4xx SoCs, the Network Processing Engine (NPE) is a small
processor that can load a firmware to perform offloading of networking
and crypto tasks. It also manages the MDIO bus to the ethernet PHYs
on the IXP4xx platform. All IXP4xx platforms have three NPEs at
consecutive memory locations. They are all included in the same
device node since they are not independent of each other.
properties:
compatible:
oneOf:
- items:
- const: intel,ixp4xx-network-processing-engine
reg:
minItems: 3
maxItems: 3
items:
- description: NPE0 register range
- description: NPE1 register range
- description: NPE2 register range
required:
- compatible
- reg
examples:
- |
npe@c8006000 {
compatible = "intel,ixp4xx-network-processing-engine";
reg = <0xc8006000 0x1000>, <0xc8007000 0x1000>, <0xc8008000 0x1000>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2018 Linaro Ltd.
%YAML 1.2
---
$id: "http://devicetree.org/schemas/interrupt/intel-ixp4xx-interrupt.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Intel IXP4xx XScale Networking Processors Interrupt Controller
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
description: |
This interrupt controller is found in the Intel IXP4xx processors.
Some processors have 32 interrupts, some have up to 64 interrupts.
The exact number of interrupts is determined from the compatible
string.
The distinct IXP4xx families with different interrupt controller
variations are IXP42x, IXP43x, IXP45x and IXP46x. Those four
families were the only ones to reach the developer and consumer
market.
properties:
compatible:
items:
- enum:
- intel,ixp42x-interrupt
- intel,ixp43x-interrupt
- intel,ixp45x-interrupt
- intel,ixp46x-interrupt
reg:
maxItems: 1
interrupt-controller: true
'#interrupt-cells':
const: 2
required:
- compatible
- reg
- interrupt-controller
- '#interrupt-cells'
examples:
- |
intcon: interrupt-controller@c8003000 {
compatible = "intel,ixp43x-interrupt";
reg = <0xc8003000 0x100>;
interrupt-controller;
#interrupt-cells = <2>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2019 Linaro Ltd.
%YAML 1.2
---
$id: "http://devicetree.org/schemas/misc/intel-ixp4xx-ahb-queue-manager.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Intel IXP4xx AHB Queue Manager
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
description: |
The IXP4xx AHB Queue Manager maintains queues as circular buffers in
an 8KB embedded SRAM along with hardware pointers. It is used by both
the XScale processor and the NPEs (Network Processing Units) in the
IXP4xx for accelerating queues, especially for networking. Clients pick
queues from the queue manager with foo-queue = <&qmgr N> where the
&qmgr is a phandle to the queue manager and N is the queue resource
number. The queue resources available and their specific purpose
on a certain IXP4xx system will vary.
properties:
compatible:
items:
- const: intel,ixp4xx-ahb-queue-manager
reg:
maxItems: 1
interrupts:
items:
- description: Interrupt for queues 0-31
- description: Interrupt for queues 32-63
required:
- compatible
- reg
- interrupts
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
qmgr: queue-manager@60000000 {
compatible = "intel,ixp4xx-ahb-queue-manager";
reg = <0x60000000 0x4000>;
interrupts = <3 IRQ_TYPE_LEVEL_HIGH>, <4 IRQ_TYPE_LEVEL_HIGH>;
};
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# Copyright 2018 Linaro Ltd.
%YAML 1.2
---
$id: "http://devicetree.org/schemas/timer/intel-ixp4xx-timer.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Intel IXP4xx XScale Networking Processors Timers
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
description: This timer is found in the Intel IXP4xx processors.
properties:
compatible:
items:
- const: intel,ixp4xx-timer
reg:
description: Should contain registers location and length
interrupts:
minItems: 1
maxItems: 2
items:
- description: Timer 1 interrupt
- description: Timer 2 interrupt
required:
- compatible
- reg
- interrupts
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
timer@c8005000 {
compatible = "intel,ixp4xx-timer";
reg = <0xc8005000 0x100>;
interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
};
......@@ -1685,11 +1685,21 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
ARM/INTEL IXP4XX ARM ARCHITECTURE
M: Linus Walleij <linusw@kernel.org>
M: Imre Kaloz <kaloz@openwrt.org>
M: Krzysztof Halasa <khalasa@piap.pl>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/arm/intel-ixp4xx.yaml
F: Documentation/devicetree/bindings/gpio/intel,ixp4xx-gpio.txt
F: Documentation/devicetree/bindings/interrupt-controller/intel,ixp4xx-interrupt.yaml
F: Documentation/devicetree/bindings/timer/intel,ixp4xx-timer.yaml
F: arch/arm/mach-ixp4xx/
F: drivers/clocksource/timer-ixp4xx.c
F: drivers/gpio/gpio-ixp4xx.c
F: drivers/irqchip/irq-ixp4xx.c
F: include/linux/irqchip/irq-ixp4xx.h
F: include/linux/platform_data/timer-ixp4xx.h
ARM/INTEL RESEARCH IMOTE/STARGATE 2 MACHINE SUPPORT
M: Jonathan Cameron <jic23@cam.ac.uk>
......@@ -7876,10 +7886,10 @@ F: Documentation/media/v4l-drivers/ipu3.rst
INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT
M: Krzysztof Halasa <khalasa@piap.pl>
S: Maintained
F: arch/arm/mach-ixp4xx/include/mach/qmgr.h
F: arch/arm/mach-ixp4xx/include/mach/npe.h
F: arch/arm/mach-ixp4xx/ixp4xx_qmgr.c
F: arch/arm/mach-ixp4xx/ixp4xx_npe.c
F: include/linux/soc/ixp4xx/qmgr.h
F: include/linux/soc/ixp4xx/npe.h
F: drivers/soc/ixp4xx/ixp4xx-qmgr.c
F: drivers/soc/ixp4xx/ixp4xx-npe.c
F: drivers/net/ethernet/xscale/ixp4xx_eth.c
F: drivers/net/wan/ixp4xx_hss.c
......
......@@ -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
......
......@@ -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 \
......
// 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>;
};
};
};
// 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";
};
};
};
// 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>;
};
};
};
// 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";
};
};
};
// 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";
};
};
};
// 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>;
};
};
};
......@@ -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
......@@ -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
......@@ -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
......
......@@ -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
......
This diff is collapsed.
......@@ -23,6 +23,8 @@
#include <asm/irq.h>
#include <asm/mach/pci.h>
#include "irqs.h"
#define SLOT0_DEVID 14
#define SLOT1_DEVID 15
......
......@@ -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
......
......@@ -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
......
......@@ -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;
......
......@@ -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
......
......@@ -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
......
......@@ -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);
......
......@@ -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,
......
......@@ -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 */
......
......@@ -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. */
......
/*
* 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
/*
* 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
......@@ -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)
......@@ -147,95 +142,6 @@
#define IXP4XX_I2C_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x11000)
#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
*/
......
/*
* 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
......@@ -24,6 +24,8 @@
#include <mach/hardware.h>
#include <asm/mach-types.h>
#include "irqs.h"
#define MAX_DEV 4
#define IRQ_LINES 4
......
......@@ -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
......
......@@ -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);
......
// 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
......@@ -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
......
......@@ -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;
......
......@@ -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
......
......@@ -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[] = {
......
......@@ -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);
......
......@@ -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,
......
......@@ -69,6 +69,13 @@ config FTTMR010_TIMER
Enables support for the Faraday Technology timer block
FTTMR010.
config IXP4XX_TIMER
bool "Intel XScale IXP4xx timer driver" if COMPILE_TEST
depends on HAS_IOMEM
select CLKSRC_MMIO
help
Enables support for the Intel XScale IXP4xx SoC timer.
config ROCKCHIP_TIMER
bool "Rockchip timer driver" if COMPILE_TEST
depends on ARM || ARM64
......
......@@ -20,6 +20,7 @@ obj-$(CONFIG_OMAP_DM_TIMER) += timer-ti-dm.o
obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o
obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o
obj-$(CONFIG_FTTMR010_TIMER) += timer-fttmr010.o
obj-$(CONFIG_IXP4XX_TIMER) += timer-ixp4xx.o
obj-$(CONFIG_ROCKCHIP_TIMER) += timer-rockchip.o
obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o
obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o
......
// SPDX-License-Identifier: GPL-2.0
/*
* IXP4 timer driver
* Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
*
* Based on arch/arm/mach-ixp4xx/common.c
* Copyright 2002 (C) Intel Corporation
* Copyright 2003-2004 (C) MontaVista, Software, Inc.
* Copyright (C) Deepak Saxena <dsaxena@plexity.net>
*/
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/clockchips.h>
#include <linux/clocksource.h>
#include <linux/sched_clock.h>
#include <linux/slab.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
/* Goes away with OF conversion */
#include <linux/platform_data/timer-ixp4xx.h>
/*
* Constants to make it easy to access Timer Control/Status registers
*/
#define IXP4XX_OSTS_OFFSET 0x00 /* Continuous Timestamp */
#define IXP4XX_OST1_OFFSET 0x04 /* Timer 1 Timestamp */
#define IXP4XX_OSRT1_OFFSET 0x08 /* Timer 1 Reload */
#define IXP4XX_OST2_OFFSET 0x0C /* Timer 2 Timestamp */
#define IXP4XX_OSRT2_OFFSET 0x10 /* Timer 2 Reload */
#define IXP4XX_OSWT_OFFSET 0x14 /* Watchdog Timer */
#define IXP4XX_OSWE_OFFSET 0x18 /* Watchdog Enable */
#define IXP4XX_OSWK_OFFSET 0x1C /* Watchdog Key */
#define IXP4XX_OSST_OFFSET 0x20 /* Timer Status */
/*
* Timer register values and bit definitions
*/
#define IXP4XX_OST_ENABLE 0x00000001
#define IXP4XX_OST_ONE_SHOT 0x00000002
/* Low order bits of reload value ignored */
#define IXP4XX_OST_RELOAD_MASK 0x00000003
#define IXP4XX_OST_DISABLED 0x00000000
#define IXP4XX_OSST_TIMER_1_PEND 0x00000001
#define IXP4XX_OSST_TIMER_2_PEND 0x00000002
#define IXP4XX_OSST_TIMER_TS_PEND 0x00000004
#define IXP4XX_OSST_TIMER_WDOG_PEND 0x00000008
#define IXP4XX_OSST_TIMER_WARM_RESET 0x00000010
#define IXP4XX_WDT_KEY 0x0000482E
#define IXP4XX_WDT_RESET_ENABLE 0x00000001
#define IXP4XX_WDT_IRQ_ENABLE 0x00000002
#define IXP4XX_WDT_COUNT_ENABLE 0x00000004
struct ixp4xx_timer {
void __iomem *base;
unsigned int tick_rate;
u32 latch;
struct clock_event_device clkevt;
#ifdef CONFIG_ARM
struct delay_timer delay_timer;
#endif
};
/*
* A local singleton used by sched_clock and delay timer reads, which are
* fast and stateless
*/
static struct ixp4xx_timer *local_ixp4xx_timer;
static inline struct ixp4xx_timer *
to_ixp4xx_timer(struct clock_event_device *evt)
{
return container_of(evt, struct ixp4xx_timer, clkevt);
}
static u64 notrace ixp4xx_read_sched_clock(void)
{
return __raw_readl(local_ixp4xx_timer->base + IXP4XX_OSTS_OFFSET);
}
static u64 ixp4xx_clocksource_read(struct clocksource *c)
{
return __raw_readl(local_ixp4xx_timer->base + IXP4XX_OSTS_OFFSET);
}
static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id)
{
struct ixp4xx_timer *tmr = dev_id;
struct clock_event_device *evt = &tmr->clkevt;
/* Clear Pending Interrupt */
__raw_writel(IXP4XX_OSST_TIMER_1_PEND,
tmr->base + IXP4XX_OSST_OFFSET);
evt->event_handler(evt);
return IRQ_HANDLED;
}
static int ixp4xx_set_next_event(unsigned long cycles,
struct clock_event_device *evt)
{
struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
u32 val;
val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET);
/* Keep enable/oneshot bits */
val &= IXP4XX_OST_RELOAD_MASK;
__raw_writel((cycles & ~IXP4XX_OST_RELOAD_MASK) | val,
tmr->base + IXP4XX_OSRT1_OFFSET);
return 0;
}
static int ixp4xx_shutdown(struct clock_event_device *evt)
{
struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
u32 val;
val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET);
val &= ~IXP4XX_OST_ENABLE;
__raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET);
return 0;
}
static int ixp4xx_set_oneshot(struct clock_event_device *evt)
{
struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
__raw_writel(IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT,
tmr->base + IXP4XX_OSRT1_OFFSET);
return 0;
}
static int ixp4xx_set_periodic(struct clock_event_device *evt)
{
struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
u32 val;
val = tmr->latch & ~IXP4XX_OST_RELOAD_MASK;
val |= IXP4XX_OST_ENABLE;
__raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET);
return 0;
}
static int ixp4xx_resume(struct clock_event_device *evt)
{
struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt);
u32 val;
val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET);
val |= IXP4XX_OST_ENABLE;
__raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET);
return 0;
}
/*
* 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 __init int ixp4xx_timer_register(void __iomem *base,
int timer_irq,
unsigned int timer_freq)
{
struct ixp4xx_timer *tmr;
int ret;
tmr = kzalloc(sizeof(*tmr), GFP_KERNEL);
if (!tmr)
return -ENOMEM;
tmr->base = base;
tmr->tick_rate = timer_freq;
/*
* 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 the latch is the best value with the two least
* significant bits unset.
*/
tmr->latch = DIV_ROUND_CLOSEST(timer_freq,
(IXP4XX_OST_RELOAD_MASK + 1) * HZ)
* (IXP4XX_OST_RELOAD_MASK + 1);
local_ixp4xx_timer = tmr;
/* Reset/disable counter */
__raw_writel(0, tmr->base + IXP4XX_OSRT1_OFFSET);
/* Clear any pending interrupt on timer 1 */
__raw_writel(IXP4XX_OSST_TIMER_1_PEND,
tmr->base + IXP4XX_OSST_OFFSET);
/* Reset time-stamp counter */
__raw_writel(0, tmr->base + IXP4XX_OSTS_OFFSET);
clocksource_mmio_init(NULL, "OSTS", timer_freq, 200, 32,
ixp4xx_clocksource_read);
tmr->clkevt.name = "ixp4xx timer1";
tmr->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
tmr->clkevt.rating = 200;
tmr->clkevt.set_state_shutdown = ixp4xx_shutdown;
tmr->clkevt.set_state_periodic = ixp4xx_set_periodic;
tmr->clkevt.set_state_oneshot = ixp4xx_set_oneshot;
tmr->clkevt.tick_resume = ixp4xx_resume;
tmr->clkevt.set_next_event = ixp4xx_set_next_event;
tmr->clkevt.cpumask = cpumask_of(0);
tmr->clkevt.irq = timer_irq;
ret = request_irq(timer_irq, ixp4xx_timer_interrupt,
IRQF_TIMER, "IXP4XX-TIMER1", tmr);
if (ret) {
pr_crit("no timer IRQ\n");
return -ENODEV;
}
clockevents_config_and_register(&tmr->clkevt, timer_freq,
0xf, 0xfffffffe);
#ifdef CONFIG_ARM
sched_clock_register(ixp4xx_read_sched_clock, 32, timer_freq);
#endif
return 0;
}
/**
* ixp4xx_timer_setup() - Timer setup function to be called from boardfiles
* @timerbase: physical base of timer block
* @timer_irq: Linux IRQ number for the timer
* @timer_freq: Fixed frequency of the timer
*/
void __init ixp4xx_timer_setup(resource_size_t timerbase,
int timer_irq,
unsigned int timer_freq)
{
void __iomem *base;
base = ioremap(timerbase, 0x100);
if (!base) {
pr_crit("IXP4xx: can't remap timer\n");
return;
}
ixp4xx_timer_register(base, timer_irq, timer_freq);
}
EXPORT_SYMBOL_GPL(ixp4xx_timer_setup);
#ifdef CONFIG_OF
static __init int ixp4xx_of_timer_init(struct device_node *np)
{
void __iomem *base;
int irq;
int ret;
base = of_iomap(np, 0);
if (!base) {
pr_crit("IXP4xx: can't remap timer\n");
return -ENODEV;
}
irq = irq_of_parse_and_map(np, 0);
if (irq <= 0) {
pr_err("Can't parse IRQ\n");
ret = -EINVAL;
goto out_unmap;
}
/* TODO: get some fixed clocks into the device tree */
ret = ixp4xx_timer_register(base, irq, 66666000);
if (ret)
goto out_unmap;
return 0;
out_unmap:
iounmap(base);
return ret;
}
TIMER_OF_DECLARE(ixp4xx, "intel,ixp4xx-timer", ixp4xx_of_timer_init);
#endif
......@@ -30,8 +30,8 @@
#include <crypto/authenc.h>
#include <crypto/scatterwalk.h>
#include <mach/npe.h>
#include <mach/qmgr.h>
#include <linux/soc/ixp4xx/npe.h>
#include <linux/soc/ixp4xx/qmgr.h>
#define MAX_KEYLEN 32
......
......@@ -287,6 +287,19 @@ config GPIO_IOP
If unsure, say N.
config GPIO_IXP4XX
bool "Intel IXP4xx GPIO"
depends on ARM # For <asm/mach-types.h>
depends on ARCH_IXP4XX
select GPIO_GENERIC
select IRQ_DOMAIN
select IRQ_DOMAIN_HIERARCHY
help
Say yes here to support the GPIO functionality of a number of Intel
IXP4xx series of chips.
If unsure, say N.
config GPIO_LOONGSON
bool "Loongson-2/3 GPIO support"
depends on CPU_LOONGSON2 || CPU_LOONGSON3
......
......@@ -61,6 +61,7 @@ obj-$(CONFIG_GPIO_HLWD) += gpio-hlwd.o
obj-$(CONFIG_HTC_EGPIO) += gpio-htc-egpio.o
obj-$(CONFIG_GPIO_ICH) += gpio-ich.o
obj-$(CONFIG_GPIO_IOP) += gpio-iop.o
obj-$(CONFIG_GPIO_IXP4XX) += gpio-ixp4xx.o
obj-$(CONFIG_GPIO_IT87) += gpio-it87.o
obj-$(CONFIG_GPIO_JANZ_TTL) += gpio-janz-ttl.o
obj-$(CONFIG_GPIO_KEMPLD) += gpio-kempld.o
......
This diff is collapsed.
......@@ -30,6 +30,8 @@ MODULE_ALIAS("platform:ixp4xx-beeper");
static DEFINE_SPINLOCK(beep_lock);
static int ixp4xx_timer2_irq;
static void ixp4xx_spkr_control(unsigned int pin, unsigned int count)
{
unsigned long flags;
......@@ -90,6 +92,7 @@ static irqreturn_t ixp4xx_spkr_interrupt(int irq, void *dev_id)
static int ixp4xx_spkr_probe(struct platform_device *dev)
{
struct input_dev *input_dev;
int irq;
int err;
input_dev = input_allocate_device();
......@@ -110,15 +113,22 @@ static int ixp4xx_spkr_probe(struct platform_device *dev)
input_dev->sndbit[0] = BIT_MASK(SND_BELL) | BIT_MASK(SND_TONE);
input_dev->event = ixp4xx_spkr_event;
irq = platform_get_irq(dev, 0);
if (irq < 0) {
err = irq;
goto err_free_device;
}
err = gpio_request(dev->id, "ixp4-beeper");
if (err)
goto err_free_device;
err = request_irq(IRQ_IXP4XX_TIMER2, &ixp4xx_spkr_interrupt,
err = request_irq(irq, &ixp4xx_spkr_interrupt,
IRQF_NO_SUSPEND, "ixp4xx-beeper",
(void *) dev->id);
if (err)
goto err_free_gpio;
ixp4xx_timer2_irq = irq;
err = input_register_device(input_dev);
if (err)
......@@ -129,7 +139,7 @@ static int ixp4xx_spkr_probe(struct platform_device *dev)
return 0;
err_free_irq:
free_irq(IRQ_IXP4XX_TIMER2, (void *)dev->id);
free_irq(irq, (void *)dev->id);
err_free_gpio:
gpio_free(dev->id);
err_free_device:
......@@ -146,10 +156,10 @@ static int ixp4xx_spkr_remove(struct platform_device *dev)
input_unregister_device(input_dev);
/* turn the speaker off */
disable_irq(IRQ_IXP4XX_TIMER2);
disable_irq(ixp4xx_timer2_irq);
ixp4xx_spkr_control(pin, 0);
free_irq(IRQ_IXP4XX_TIMER2, (void *)dev->id);
free_irq(ixp4xx_timer2_irq, (void *)dev->id);
gpio_free(dev->id);
return 0;
......@@ -161,7 +171,7 @@ static void ixp4xx_spkr_shutdown(struct platform_device *dev)
unsigned int pin = (unsigned int) input_get_drvdata(input_dev);
/* turn off the speaker */
disable_irq(IRQ_IXP4XX_TIMER2);
disable_irq(ixp4xx_timer2_irq);
ixp4xx_spkr_control(pin, 0);
}
......
......@@ -160,6 +160,12 @@ config IMGPDC_IRQ
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
config IXP4XX_IRQ
bool
select IRQ_DOMAIN
select GENERIC_IRQ_MULTI_HANDLER
select SPARSE_IRQ
config MADERA_IRQ
tristate
......
......@@ -43,6 +43,7 @@ obj-$(CONFIG_ATMEL_AIC5_IRQ) += irq-atmel-aic-common.o irq-atmel-aic5.o
obj-$(CONFIG_I8259) += irq-i8259.o
obj-$(CONFIG_IMGPDC_IRQ) += irq-imgpdc.o
obj-$(CONFIG_IRQ_MIPS_CPU) += irq-mips-cpu.o
obj-$(CONFIG_IXP4XX_IRQ) += irq-ixp4xx.o
obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o
obj-$(CONFIG_JCORE_AIC) += irq-jcore-aic.o
obj-$(CONFIG_RDA_INTC) += irq-rda-intc.o
......
This diff is collapsed.
......@@ -31,14 +31,15 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/net_tstamp.h>
#include <linux/of.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
#include <linux/ptp_classify.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <mach/ixp46x_ts.h>
#include <mach/npe.h>
#include <mach/qmgr.h>
#include <linux/soc/ixp4xx/npe.h>
#include <linux/soc/ixp4xx/qmgr.h>
#define DEBUG_DESC 0
#define DEBUG_RX 0
......@@ -1497,6 +1498,15 @@ static struct platform_driver ixp4xx_eth_driver = {
static int __init eth_init_module(void)
{
int err;
/*
* FIXME: we bail out on device tree boot but this really needs
* to be fixed in a nicer way: this registers the MDIO bus before
* even matching the driver infrastructure, we should only probe
* detected hardware.
*/
if (of_have_populated_dt())
return -ENODEV;
if ((err = ixp4xx_mdio_register()))
return err;
return platform_driver_register(&ixp4xx_eth_driver);
......
......@@ -22,8 +22,8 @@
#include <linux/platform_device.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <mach/npe.h>
#include <mach/qmgr.h>
#include <linux/soc/ixp4xx/npe.h>
#include <linux/soc/ixp4xx/qmgr.h>
#define DEBUG_DESC 0
#define DEBUG_RX 0
......
......@@ -6,6 +6,7 @@ source "drivers/soc/atmel/Kconfig"
source "drivers/soc/bcm/Kconfig"
source "drivers/soc/fsl/Kconfig"
source "drivers/soc/imx/Kconfig"
source "drivers/soc/ixp4xx/Kconfig"
source "drivers/soc/mediatek/Kconfig"
source "drivers/soc/qcom/Kconfig"
source "drivers/soc/renesas/Kconfig"
......
......@@ -11,6 +11,7 @@ obj-$(CONFIG_MACH_DOVE) += dove/
obj-y += fsl/
obj-$(CONFIG_ARCH_GEMINI) += gemini/
obj-$(CONFIG_ARCH_MXC) += imx/
obj-$(CONFIG_ARCH_IXP4XX) += ixp4xx/
obj-$(CONFIG_SOC_XWAY) += lantiq/
obj-y += mediatek/
obj-y += amlogic/
......
menu "IXP4xx SoC drivers"
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
obj-$(CONFIG_IXP4XX_QMGR) += ixp4xx-qmgr.o
obj-$(CONFIG_IXP4XX_NPE) += ixp4xx-npe.o
......@@ -20,7 +20,9 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <mach/npe.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/soc/ixp4xx/npe.h>
#define DEBUG_MSG 0
#define DEBUG_FW 0
......@@ -153,16 +155,10 @@ static struct {
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,
}
};
......@@ -682,28 +678,37 @@ void npe_release(struct npe *npe)
module_put(THIS_MODULE);
}
static int __init npe_init_module(void)
static int ixp4xx_npe_probe(struct platform_device *pdev)
{
int i, found = 0;
struct device *dev = &pdev->dev;
struct resource *res;
for (i = 0; i < NPE_COUNT; i++) {
struct npe *npe = &npe_tab[i];
res = platform_get_resource(pdev, IORESOURCE_MEM, i);
if (!res)
return -ENODEV;
if (!(ixp4xx_read_feature_bits() &
(IXP4XX_FEATURE_RESET_NPEA << i)))
(IXP4XX_FEATURE_RESET_NPEA << i))) {
dev_info(dev, "NPE%d at 0x%08x-0x%08x not available\n",
i, res->start, res->end);
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;
}
npe->regs = devm_ioremap_resource(dev, res);
if (!npe->regs)
return -ENOMEM;
if (npe_reset(npe))
if (npe_reset(npe)) {
dev_info(dev, "NPE%d at 0x%08x-0x%08x does not reset\n",
i, res->start, res->end);
continue;
}
npe->valid = 1;
dev_info(dev, "NPE%d at 0x%08x-0x%08x registered\n",
i, res->start, res->end);
found++;
}
......@@ -712,19 +717,34 @@ static int __init npe_init_module(void)
return 0;
}
static void __exit npe_cleanup_module(void)
static int ixp4xx_npe_remove(struct platform_device *pdev)
{
int i;
for (i = 0; i < NPE_COUNT; i++)
if (npe_tab[i].mem_res) {
if (npe_tab[i].regs) {
npe_reset(&npe_tab[i]);
release_resource(npe_tab[i].mem_res);
}
return 0;
}
module_init(npe_init_module);
module_exit(npe_cleanup_module);
static const struct of_device_id ixp4xx_npe_of_match[] = {
{
.compatible = "intel,ixp4xx-network-processing-engine",
},
{},
};
static struct platform_driver ixp4xx_npe_driver = {
.driver = {
.name = "ixp4xx-npe",
.of_match_table = of_match_ptr(ixp4xx_npe_of_match),
},
.probe = ixp4xx_npe_probe,
.remove = ixp4xx_npe_remove,
};
module_platform_driver(ixp4xx_npe_driver);
MODULE_AUTHOR("Krzysztof Halasa");
MODULE_LICENSE("GPL v2");
......
......@@ -12,10 +12,13 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <mach/qmgr.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/soc/ixp4xx/qmgr.h>
static struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT;
static struct resource *mem_res;
static struct qmgr_regs __iomem *qmgr_regs;
static int qmgr_irq_1;
static int qmgr_irq_2;
static spinlock_t qmgr_lock;
static u32 used_sram_bitmap[4]; /* 128 16-dword pages */
static void (*irq_handlers[QUEUES])(void *pdev);
......@@ -25,6 +28,94 @@ static void *irq_pdevs[QUEUES];
char qmgr_queue_descs[QUEUES][32];
#endif
void qmgr_put_entry(unsigned int queue, u32 val)
{
#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]);
}
u32 qmgr_get_entry(unsigned int queue)
{
u32 val;
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 int __qmgr_get_stat1(unsigned int queue)
{
return (__raw_readl(&qmgr_regs->stat1[queue >> 3])
>> ((queue & 7) << 2)) & 0xF;
}
static int __qmgr_get_stat2(unsigned int queue)
{
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.
*/
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.
*/
int qmgr_stat_below_low_watermark(unsigned int queue)
{
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_full() - checks if a hardware queue is full
* @queue: queue number
*
* Returns non-zero value if the queue is full.
*/
int qmgr_stat_full(unsigned int queue)
{
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_overflow() - checks if a hardware queue experienced overflow
* @queue: queue number
*
* Returns non-zero value if the queue experienced overflow.
*/
int qmgr_stat_overflow(unsigned int queue)
{
return __qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW;
}
void qmgr_set_irq(unsigned int queue, int src,
void (*handler)(void *pdev), void *pdev)
{
......@@ -95,7 +186,7 @@ static irqreturn_t qmgr_irq2_a0(int irq, void *pdev)
static irqreturn_t qmgr_irq(int irq, void *pdev)
{
int i, half = (irq == IRQ_IXP4XX_QM1 ? 0 : 1);
int i, half = (irq == qmgr_irq_1 ? 0 : 1);
u32 req_bitmap = __raw_readl(&qmgr_regs->irqstat[half]);
if (!req_bitmap)
......@@ -282,16 +373,29 @@ void qmgr_release_queue(unsigned int queue)
module_put(THIS_MODULE);
}
static int qmgr_init(void)
static int ixp4xx_qmgr_probe(struct platform_device *pdev)
{
int i, err;
irq_handler_t handler1, handler2;
struct device *dev = &pdev->dev;
struct resource *res;
int irq1, irq2;
mem_res = request_mem_region(IXP4XX_QMGR_BASE_PHYS,
IXP4XX_QMGR_REGION_SIZE,
"IXP4xx Queue Manager");
if (mem_res == NULL)
return -EBUSY;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
qmgr_regs = devm_ioremap_resource(dev, res);
if (!qmgr_regs)
return -ENOMEM;
irq1 = platform_get_irq(pdev, 0);
if (irq1 <= 0)
return irq1 ? irq1 : -EINVAL;
qmgr_irq_1 = irq1;
irq2 = platform_get_irq(pdev, 1);
if (irq2 <= 0)
return irq2 ? irq2 : -EINVAL;
qmgr_irq_2 = irq2;
/* reset qmgr registers */
for (i = 0; i < 4; i++) {
......@@ -316,50 +420,62 @@ static int qmgr_init(void)
} else
handler1 = handler2 = qmgr_irq;
err = request_irq(IRQ_IXP4XX_QM1, handler1, 0, "IXP4xx Queue Manager",
NULL);
err = devm_request_irq(dev, irq1, 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;
dev_err(dev, "failed to request IRQ%i (%i)\n",
irq1, err);
return err;
}
err = request_irq(IRQ_IXP4XX_QM2, handler2, 0, "IXP4xx Queue Manager",
NULL);
err = devm_request_irq(dev, irq2, 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;
dev_err(dev, "failed to request IRQ%i (%i)\n",
irq2, err);
return err;
}
used_sram_bitmap[0] = 0xF; /* 4 first pages reserved for config */
spin_lock_init(&qmgr_lock);
printk(KERN_INFO "IXP4xx Queue Manager initialized.\n");
dev_info(dev, "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)
static int ixp4xx_qmgr_remove(struct platform_device *pdev)
{
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);
synchronize_irq(qmgr_irq_1);
synchronize_irq(qmgr_irq_2);
return 0;
}
module_init(qmgr_init);
module_exit(qmgr_remove);
static const struct of_device_id ixp4xx_qmgr_of_match[] = {
{
.compatible = "intel,ixp4xx-ahb-queue-manager",
},
{},
};
static struct platform_driver ixp4xx_qmgr_driver = {
.driver = {
.name = "ixp4xx-qmgr",
.of_match_table = of_match_ptr(ixp4xx_qmgr_of_match),
},
.probe = ixp4xx_qmgr_probe,
.remove = ixp4xx_qmgr_remove,
};
module_platform_driver(ixp4xx_qmgr_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Krzysztof Halasa");
EXPORT_SYMBOL(qmgr_put_entry);
EXPORT_SYMBOL(qmgr_get_entry);
EXPORT_SYMBOL(qmgr_stat_empty);
EXPORT_SYMBOL(qmgr_stat_below_low_watermark);
EXPORT_SYMBOL(qmgr_stat_full);
EXPORT_SYMBOL(qmgr_stat_overflow);
EXPORT_SYMBOL(qmgr_set_irq);
EXPORT_SYMBOL(qmgr_enable_irq);
EXPORT_SYMBOL(qmgr_disable_irq);
......
......@@ -21,6 +21,7 @@
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/of.h>
#include <linux/watchdog.h>
#include <linux/init.h>
#include <linux/bitops.h>
......@@ -176,6 +177,14 @@ static int __init ixp4xx_wdt_init(void)
{
int ret;
/*
* FIXME: we bail out on device tree boot but this really needs
* to be fixed in a nicer way: this registers the MDIO bus before
* even matching the driver infrastructure, we should only probe
* detected hardware.
*/
if (of_have_populated_dt())
return -ENODEV;
if (!(read_cpuid_id() & 0xf) && !cpu_is_ixp46x()) {
pr_err("Rev. A0 IXP42x CPU detected - watchdog disabled\n");
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __IRQ_IXP4XX_H
#define __IRQ_IXP4XX_H
#include <linux/ioport.h>
struct irq_domain;
void ixp4xx_irq_init(resource_size_t irqbase,
bool is_356);
struct irq_domain *ixp4xx_get_irq_domain(void);
#endif /* __IRQ_IXP4XX_H */
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __TIMER_IXP4XX_H
#define __TIMER_IXP4XX_H
#include <linux/ioport.h>
void __init ixp4xx_timer_setup(resource_size_t timerbase,
int timer_irq,
unsigned int timer_freq);
#endif
......@@ -16,9 +16,7 @@ struct npe_regs {
};
struct npe {
struct resource *mem_res;
struct npe_regs __iomem *regs;
u32 regs_phys;
int id;
int valid;
};
......
......@@ -57,6 +57,13 @@ struct qmgr_regs {
u32 sram[2048]; /* 0x2000 - 0x3FFF - config and buffer */
};
void qmgr_put_entry(unsigned int queue, u32 val);
u32 qmgr_get_entry(unsigned int queue);
int qmgr_stat_empty(unsigned int queue);
int qmgr_stat_below_low_watermark(unsigned int queue);
int qmgr_stat_full(unsigned int queue);
int qmgr_stat_overflow(unsigned int queue);
void qmgr_release_queue(unsigned int queue);
void qmgr_set_irq(unsigned int queue, int src,
void (*handler)(void *pdev), void *pdev);
void qmgr_enable_irq(unsigned int queue);
......@@ -81,124 +88,4 @@ int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */,
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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment