linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 0/5] MIPS: Octeon: Use Device Tree.
@ 2012-03-01  0:56 David Daney
  2012-03-01  0:56 ` [PATCH v6 1/5] MIPS: Octeon: Add device tree source files David Daney
                   ` (4 more replies)
  0 siblings, 5 replies; 20+ messages in thread
From: David Daney @ 2012-03-01  0:56 UTC (permalink / raw)
  To: linux-mips, ralf, devicetree-discuss, Grant Likely, Rob Herring
  Cc: linux-kernel, David Daney

From: David Daney <david.daney@cavium.com>

This code has now had extensive testing, it is running on more
than 10 different boards and SOC combinations.

The patches in this set are all in the arch/mips tree and should
probably be merged by Ralf.

They do depend on this libfdt patch:

http://marc.info/?l=linux-kernel&m=133054335203615

New in v6:

o Device Tree bindings updated based on feedback and more actual use.

o Use of irq_domain support added to recent kernels.

New in v5:

o New irq triggering mode constants.

o Boot protocol to pass flattened device tree from bootloader.  This
  protocol may change based on attempts to arrive at a common protocol
  for all MIPS boards.

New in v4:

o Cleanup and error checking suggested by Sergei Shtylyov.

o Use device tree passed by bootloader if present.

New in v3:

o More updates to device tree bindings, and perhaps more importantly
  descriptions/definitions of the bindings

o Cleanup and style improvements as suggested by Grant Likley.

o Omitted all the driver changes, as they are unchanged from the last
  set, and at this stage the patches are just an RFC.

New in v2:

o Changed many device tree bindings.  They should be closer to the
  standard naming scheme now.

o Editing of the template device tree is done in the flattened form
  using libfdt.

o Standard platform driver functions used in preference to the
  of_platform variety.

v1:

Background: The Octeon family of SOCs has a variety of on-chip
controllers for Ethernet, MDIO, I2C, and several other I/O devices.
These chips are used on boards with a great variety of different
configurations.  To date, the configuration and bus topology
information has been hard coded in the drivers and support code.

To facilitate supporting new chips and boards, we are using the Device
Tree to encode the configuration information.  The migration from the
legacy approach to the device tree is as follows:

o A device tree template is statically linked into the kernel image.
  Based on SOC type and board type, legacy configuration probing code
  is used to prune and patch the device tree template.

o New SOCs and boards will directly use a device tree passed by the
  bootloader.


David Daney (5):
  MIPS: Octeon: Add device tree source files.
  MIPS: Don't define early_init_devtree() and device_tree_init() in
    prom.c for CPU_CAVIUM_OCTEON
  MIPS: Octeon: Add irq handlers for GPIO interrupts.
  MIPS: Octeon: Setup irq_domains for interrupts.
  MIPS: Octeon: Initialize and fixup device tree.

 .../bindings/ata/cavium-compact-flash.txt          |   30 +
 .../bindings/gpio/cavium-octeon-gpio.txt           |   48 ++
 .../devicetree/bindings/i2c/cavium-i2c.txt         |   34 ++
 .../devicetree/bindings/mips/cavium/bootbus.txt    |  126 ++++
 .../devicetree/bindings/mips/cavium/ciu.txt        |   26 +
 .../devicetree/bindings/mips/cavium/ciu2.txt       |   27 +
 .../devicetree/bindings/mips/cavium/dma-engine.txt |   21 +
 .../devicetree/bindings/mips/cavium/uctl.txt       |   47 ++
 .../devicetree/bindings/net/cavium-mdio.txt        |   27 +
 .../devicetree/bindings/net/cavium-mix.txt         |   40 ++
 .../devicetree/bindings/net/cavium-pip.txt         |   98 +++
 .../devicetree/bindings/serial/cavium-uart.txt     |   19 +
 arch/mips/Kconfig                                  |    3 +
 arch/mips/cavium-octeon/.gitignore                 |    2 +
 arch/mips/cavium-octeon/Makefile                   |   16 +
 arch/mips/cavium-octeon/octeon-irq.c               |  395 +++++++++++--
 arch/mips/cavium-octeon/octeon-platform.c          |  523 ++++++++++++++++-
 arch/mips/cavium-octeon/octeon_3xxx.dts            |  571 ++++++++++++++++++
 arch/mips/cavium-octeon/octeon_68xx.dts            |  625 ++++++++++++++++++++
 arch/mips/cavium-octeon/setup.c                    |   45 ++
 arch/mips/kernel/prom.c                            |    2 +
 21 files changed, 2661 insertions(+), 64 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/ata/cavium-compact-flash.txt
 create mode 100644 Documentation/devicetree/bindings/gpio/cavium-octeon-gpio.txt
 create mode 100644 Documentation/devicetree/bindings/i2c/cavium-i2c.txt
 create mode 100644 Documentation/devicetree/bindings/mips/cavium/bootbus.txt
 create mode 100644 Documentation/devicetree/bindings/mips/cavium/ciu.txt
 create mode 100644 Documentation/devicetree/bindings/mips/cavium/ciu2.txt
 create mode 100644 Documentation/devicetree/bindings/mips/cavium/dma-engine.txt
 create mode 100644 Documentation/devicetree/bindings/mips/cavium/uctl.txt
 create mode 100644 Documentation/devicetree/bindings/net/cavium-mdio.txt
 create mode 100644 Documentation/devicetree/bindings/net/cavium-mix.txt
 create mode 100644 Documentation/devicetree/bindings/net/cavium-pip.txt
 create mode 100644 Documentation/devicetree/bindings/serial/cavium-uart.txt
 create mode 100644 arch/mips/cavium-octeon/.gitignore
 create mode 100644 arch/mips/cavium-octeon/octeon_3xxx.dts
 create mode 100644 arch/mips/cavium-octeon/octeon_68xx.dts

-- 
1.7.2.3


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v6 1/5] MIPS: Octeon: Add device tree source files.
  2012-03-01  0:56 [PATCH v6 0/5] MIPS: Octeon: Use Device Tree David Daney
@ 2012-03-01  0:56 ` David Daney
  2012-03-01  0:56 ` [PATCH v6 2/5] MIPS: Don't define early_init_devtree() and device_tree_init() in prom.c for CPU_CAVIUM_OCTEON David Daney
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 20+ messages in thread
From: David Daney @ 2012-03-01  0:56 UTC (permalink / raw)
  To: linux-mips, ralf, devicetree-discuss, Grant Likely, Rob Herring
  Cc: linux-kernel, David Daney

From: David Daney <david.daney@cavium.com>

The two device tree files octeon_3xxx.dts and octeon_68xx.dts are
trimmed by code in a subsequent patch to reflect the hardware actually
present on the board.  To this end several properties that are not
part of the declared bindings are added to aid in trimming off
unwanted nodes.  Since the device tree and the code that trims it are
bound into the kernel binary, these 'marker' properties never escape
into the wild, and are purely an implementation detail of the kernel
early boot process.  This is done for backwards compatibility with
existing boards (identified by a board type enumeration value by their
bootloaders).  New boards will always pass a device tree from the
bootloader, the built-in trees are ignored in this case.

Signed-off-by: David Daney <david.daney@cavium.com>
---
 .../bindings/ata/cavium-compact-flash.txt          |   30 +
 .../bindings/gpio/cavium-octeon-gpio.txt           |   48 ++
 .../devicetree/bindings/i2c/cavium-i2c.txt         |   34 ++
 .../devicetree/bindings/mips/cavium/bootbus.txt    |  126 ++++
 .../devicetree/bindings/mips/cavium/ciu.txt        |   26 +
 .../devicetree/bindings/mips/cavium/ciu2.txt       |   27 +
 .../devicetree/bindings/mips/cavium/dma-engine.txt |   21 +
 .../devicetree/bindings/mips/cavium/uctl.txt       |   47 ++
 .../devicetree/bindings/net/cavium-mdio.txt        |   27 +
 .../devicetree/bindings/net/cavium-mix.txt         |   40 ++
 .../devicetree/bindings/net/cavium-pip.txt         |   98 +++
 .../devicetree/bindings/serial/cavium-uart.txt     |   19 +
 arch/mips/cavium-octeon/.gitignore                 |    2 +
 arch/mips/cavium-octeon/Makefile                   |   13 +
 arch/mips/cavium-octeon/octeon_3xxx.dts            |  571 ++++++++++++++++++
 arch/mips/cavium-octeon/octeon_68xx.dts            |  625 ++++++++++++++++++++
 16 files changed, 1754 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/ata/cavium-compact-flash.txt
 create mode 100644 Documentation/devicetree/bindings/gpio/cavium-octeon-gpio.txt
 create mode 100644 Documentation/devicetree/bindings/i2c/cavium-i2c.txt
 create mode 100644 Documentation/devicetree/bindings/mips/cavium/bootbus.txt
 create mode 100644 Documentation/devicetree/bindings/mips/cavium/ciu.txt
 create mode 100644 Documentation/devicetree/bindings/mips/cavium/ciu2.txt
 create mode 100644 Documentation/devicetree/bindings/mips/cavium/dma-engine.txt
 create mode 100644 Documentation/devicetree/bindings/mips/cavium/uctl.txt
 create mode 100644 Documentation/devicetree/bindings/net/cavium-mdio.txt
 create mode 100644 Documentation/devicetree/bindings/net/cavium-mix.txt
 create mode 100644 Documentation/devicetree/bindings/net/cavium-pip.txt
 create mode 100644 Documentation/devicetree/bindings/serial/cavium-uart.txt
 create mode 100644 arch/mips/cavium-octeon/.gitignore
 create mode 100644 arch/mips/cavium-octeon/octeon_3xxx.dts
 create mode 100644 arch/mips/cavium-octeon/octeon_68xx.dts

diff --git a/Documentation/devicetree/bindings/ata/cavium-compact-flash.txt b/Documentation/devicetree/bindings/ata/cavium-compact-flash.txt
new file mode 100644
index 0000000..93986a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/cavium-compact-flash.txt
@@ -0,0 +1,30 @@
+* Compact Flash
+
+The Cavium Compact Flash device is connected to the Octeon Boot Bus,
+and is thus a child of the Boot Bus device.  It can read and write
+industry standard compact flash devices.
+
+Properties:
+- compatible: "cavium,ebt3000-compact-flash";
+
+  Compatibility with many Cavium evaluation boards.
+
+- reg: The base address of the the CF chip select banks.  Depending on
+  the device configuration, there may be one or two banks.
+
+- cavium,bus-width: The width of the connection to the CF devices.  Valid
+  values are 8 and 16.
+
+- cavium,true-ide: Optional, if present the CF connection is in True IDE mode.
+
+- cavium,dma-engine-handle: Optional, a phandle for the DMA Engine connected
+  to this device.
+
+Example:
+	compact-flash@5,0 {
+		compatible = "cavium,ebt3000-compact-flash";
+		reg = <5 0 0x10000>, <6 0 0x10000>;
+		cavium,bus-width = <16>;
+		cavium,true-ide;
+		cavium,dma-engine-handle = <&dma0>;
+	};
diff --git a/Documentation/devicetree/bindings/gpio/cavium-octeon-gpio.txt b/Documentation/devicetree/bindings/gpio/cavium-octeon-gpio.txt
new file mode 100644
index 0000000..21b989a
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/cavium-octeon-gpio.txt
@@ -0,0 +1,48 @@
+* General Purpose Input Output (GPIO) bus.
+
+Properties:
+- compatible: "cavium,octeon-3860-gpio"
+
+  Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
+
+- reg: The base address of the GPIO unit's register bank.
+
+- gpio-controller: This is a GPIO controller.
+
+- #gpio-cells: Must be <2>.  The first cell is the GPIO pin.
+
+- interrupt-controller: The GPIO controller is also an interrupt
+  controller, any of its pins may be configured as an interrupt
+  source.
+
+- #interrupt-cells: Must be <2>.  The first cell is the GPIO pin
+   connected to the interrupt source.  The second cell is the interrupt
+   triggering protocol and may have one of four values:
+   1 - edge triggered on the rising edge.
+   2 - edge triggered on the falling edge
+   4 - level triggered active high.
+   8 - level triggered active low.
+
+- interrupts: Interrupt routing for pin 0.  The remaining pins are
+  also routed, but in a manner that can be derived from the pin0
+  routing, so they are not specified.
+
+Example:
+
+	gpio-controller@1070000000800 {
+		#gpio-cells = <2>;
+		compatible = "cavium,octeon-3860-gpio";
+		reg = <0x10700 0x00000800 0x0 0x100>;
+		gpio-controller;
+		/* Interrupts are specified by two parts:
+		 * 1) GPIO pin number (0..15)
+		 * 2) Triggering (1 - edge rising
+		 *		  2 - edge falling
+		 *		  4 - level active high
+		 *		  8 - level active low)
+		 */
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		/* The GPIO pin connect to 16 consecutive CUI bits */
+		interrupts = <0 16>;
+	};
diff --git a/Documentation/devicetree/bindings/i2c/cavium-i2c.txt b/Documentation/devicetree/bindings/i2c/cavium-i2c.txt
new file mode 100644
index 0000000..dced82e
--- /dev/null
+++ b/Documentation/devicetree/bindings/i2c/cavium-i2c.txt
@@ -0,0 +1,34 @@
+* Two Wire Serial Interface (TWSI) / I2C
+
+- compatible: "cavium,octeon-3860-twsi"
+
+  Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
+
+- reg: The base address of the TWSI/I2C bus controller register bank.
+
+- #address-cells: Must be <1>.
+
+- #size-cells: Must be <0>.  I2C addresses have no size component.
+
+- interrupts: A single interrupt specifier.
+
+- clock-frequency: The I2C bus clock rate in Hz.
+
+Example:
+	twsi0: i2c@1180000001000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "cavium,octeon-3860-twsi";
+		reg = <0x11800 0x00001000 0x0 0x200>;
+		interrupts = <0 45>;
+		clock-frequency = <100000>;
+
+		rtc@68 {
+			compatible = "dallas,ds1337";
+			reg = <0x68>;
+		};
+		tmp@4c {
+			compatible = "ti,tmp421";
+			reg = <0x4c>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/mips/cavium/bootbus.txt b/Documentation/devicetree/bindings/mips/cavium/bootbus.txt
new file mode 100644
index 0000000..6581478
--- /dev/null
+++ b/Documentation/devicetree/bindings/mips/cavium/bootbus.txt
@@ -0,0 +1,126 @@
+* Boot Bus
+
+The Octeon Boot Bus is a configurable parallel bus with 8 chip
+selects.  Each chip select is independently configurable.
+
+Properties:
+- compatible: "cavium,octeon-3860-bootbus"
+
+  Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
+
+- reg: The base address of the Boot Bus' register bank.
+
+- #address-cells: Must be <2>.  The first cell is the chip select
+   within the bootbus.  The second cell is the offset from the chip select.
+
+- #size-cells: Must be <1>.
+
+- ranges: There must be one one triplet of (child-bus-address,
+  parent-bus-address, length) for each active chip select.  If the
+  length element for any triplet is zero, the chip select is disabled,
+  making it inactive.
+
+The configuration parameters for each chip select are stored in child
+nodes.
+
+Configuration Properties:
+- compatible:  "cavium,octeon-3860-bootbus-config"
+
+- cavium,cs-index: A single cell indicating the chip select that
+  corresponds to this configuration.
+
+- cavium,t-adr: A cell specifying the ADR timing (in nS).
+
+- cavium,t-ce: A cell specifying the CE timing (in nS).
+
+- cavium,t-oe: A cell specifying the OE timing (in nS).
+
+- cavium,t-we: A cell specifying the WE timing (in nS).
+
+- cavium,t-rd-hld: A cell specifying the RD_HLD timing (in nS).
+
+- cavium,t-wr-hld: A cell specifying the WR_HLD timing (in nS).
+
+- cavium,t-pause: A cell specifying the PAUSE timing (in nS).
+
+- cavium,t-wait: A cell specifying the WAIT timing (in nS).
+
+- cavium,t-page: A cell specifying the PAGE timing (in nS).
+
+- cavium,t-rd-dly: A cell specifying the RD_DLY timing (in nS).
+
+- cavium,pages: A cell specifying the PAGES parameter (0 = 8 bytes, 1
+  = 2 bytes, 2 = 4 bytes, 3 = 8 bytes).
+
+- cavium,wait-mode: Optional.  If present, wait mode (WAITM) is selected.
+
+- cavium,page-mode: Optional.  If present, page mode (PAGEM) is selected.
+
+- cavium,bus-width: A cell specifying the WIDTH parameter (in bits) of
+  the bus for this chip select.
+
+- cavium,ale-mode: Optional.  If present, ALE mode is selected.
+
+- cavium,sam-mode: Optional.  If present, SAM mode is selected.
+
+- cavium,or-mode: Optional.  If present, OR mode is selected.
+
+Example:
+	bootbus: bootbus@1180000000000 {
+		compatible = "cavium,octeon-3860-bootbus";
+		reg = <0x11800 0x00000000 0x0 0x200>;
+		/* The chip select number and offset */
+		#address-cells = <2>;
+		/* The size of the chip select region */
+		#size-cells = <1>;
+		ranges = <0 0  0x0 0x1f400000  0xc00000>,
+			 <1 0  0x10000 0x30000000  0>,
+			 <2 0  0x10000 0x40000000  0>,
+			 <3 0  0x10000 0x50000000  0>,
+			 <4 0  0x0 0x1d020000  0x10000>,
+			 <5 0  0x0 0x1d040000  0x10000>,
+			 <6 0  0x0 0x1d050000  0x10000>,
+			 <7 0  0x10000 0x90000000  0>;
+
+			cavium,cs-config@0 {
+			compatible = "cavium,octeon-3860-bootbus-config";
+			cavium,cs-index = <0>;
+			cavium,t-adr  = <20>;
+			cavium,t-ce   = <60>;
+			cavium,t-oe   = <60>;
+			cavium,t-we   = <45>;
+			cavium,t-rd-hld = <35>;
+			cavium,t-wr-hld = <45>;
+			cavium,t-pause  = <0>;
+			cavium,t-wait   = <0>;
+			cavium,t-page   = <35>;
+			cavium,t-rd-dly = <0>;
+
+			cavium,pages     = <0>;
+			cavium,bus-width = <8>;
+		};
+		.
+		.
+		.
+		cavium,cs-config@6 {
+			compatible = "cavium,octeon-3860-bootbus-config";
+			cavium,cs-index = <6>;
+			cavium,t-adr  = <5>;
+			cavium,t-ce   = <300>;
+			cavium,t-oe   = <270>;
+			cavium,t-we   = <150>;
+			cavium,t-rd-hld = <100>;
+			cavium,t-wr-hld = <70>;
+			cavium,t-pause  = <0>;
+			cavium,t-wait   = <0>;
+			cavium,t-page   = <320>;
+			cavium,t-rd-dly = <0>;
+
+			cavium,pages     = <0>;
+			cavium,wait-mode;
+			cavium,bus-width = <16>;
+		};
+		.
+		.
+		.
+	};
diff --git a/Documentation/devicetree/bindings/mips/cavium/ciu.txt b/Documentation/devicetree/bindings/mips/cavium/ciu.txt
new file mode 100644
index 0000000..2c2d074
--- /dev/null
+++ b/Documentation/devicetree/bindings/mips/cavium/ciu.txt
@@ -0,0 +1,26 @@
+* Central Interrupt Unit
+
+Properties:
+- compatible: "cavium,octeon-3860-ciu"
+
+  Compatibility with all cn3XXX, cn5XXX and cn63XX SOCs.
+
+- interrupt-controller:  This is an interrupt controller.
+
+- reg: The base address of the CIU's register bank.
+
+- #interrupt-cells: Must be <2>.  The first cell is the bank within
+   the CIU and may have a value of 0 or 1.  The second cell is the bit
+   within the bank and may have a value between 0 and 63.
+
+Example:
+	interrupt-controller@1070000000000 {
+		compatible = "cavium,octeon-3860-ciu";
+		interrupt-controller;
+		/* Interrupts are specified by two parts:
+		 * 1) Controller register (0 or 1)
+		 * 2) Bit within the register (0..63)
+		 */
+		#interrupt-cells = <2>;
+		reg = <0x10700 0x00000000 0x0 0x7000>;
+	};
diff --git a/Documentation/devicetree/bindings/mips/cavium/ciu2.txt b/Documentation/devicetree/bindings/mips/cavium/ciu2.txt
new file mode 100644
index 0000000..0ec7ba8
--- /dev/null
+++ b/Documentation/devicetree/bindings/mips/cavium/ciu2.txt
@@ -0,0 +1,27 @@
+* Central Interrupt Unit
+
+Properties:
+- compatible: "cavium,octeon-6880-ciu2"
+
+  Compatibility with 68XX SOCs.
+
+- interrupt-controller:  This is an interrupt controller.
+
+- reg: The base address of the CIU's register bank.
+
+- #interrupt-cells: Must be <2>.  The first cell is the bank within
+  the CIU and may have a value between 0 and 63.  The second cell is
+  the bit within the bank and may also have a value between 0 and 63.
+
+Example:
+	interrupt-controller@1070100000000 {
+		compatible = "cavium,octeon-6880-ciu2";
+		interrupt-controller;
+		/* Interrupts are specified by two parts:
+		 * 1) Controller register (0..63)
+		 * 2) Bit within the register (0..63)
+		 */
+		#address-cells = <0>;
+		#interrupt-cells = <2>;
+		reg = <0x10701 0x00000000 0x0 0x4000000>;
+	};
diff --git a/Documentation/devicetree/bindings/mips/cavium/dma-engine.txt b/Documentation/devicetree/bindings/mips/cavium/dma-engine.txt
new file mode 100644
index 0000000..cb4291e
--- /dev/null
+++ b/Documentation/devicetree/bindings/mips/cavium/dma-engine.txt
@@ -0,0 +1,21 @@
+* DMA Engine.
+
+The Octeon DMA Engine transfers between the Boot Bus and main memory.
+The DMA Engine will be refered to by phandle by any device that is
+connected to it.
+
+Properties:
+- compatible: "cavium,octeon-5750-bootbus-dma"
+
+  Compatibility with all cn52XX, cn56XX and cn6XXX SOCs.
+
+- reg: The base address of the DMA Engine's register bank.
+
+- interrupts: A single interrupt specifier.
+
+Example:
+	dma0: dma-engine@1180000000100 {
+		compatible = "cavium,octeon-5750-bootbus-dma";
+		reg = <0x11800 0x00000100 0x0 0x8>;
+		interrupts = <0 63>;
+	};
diff --git a/Documentation/devicetree/bindings/mips/cavium/uctl.txt b/Documentation/devicetree/bindings/mips/cavium/uctl.txt
new file mode 100644
index 0000000..5dabe02
--- /dev/null
+++ b/Documentation/devicetree/bindings/mips/cavium/uctl.txt
@@ -0,0 +1,47 @@
+* UCTL USB controller glue
+
+Properties:
+- compatible: "cavium,octeon-6335-uctl"
+
+  Compatibility with all cn6XXX SOCs.
+
+- reg: The base address of the UCTL register bank.
+
+- #address-cells: Must be <2>.
+
+- #size-cells: Must be <2>.
+
+- ranges: Empty to signify direct mapping of the children.
+
+- refclk-frequency: A single cell containing the reference clock
+  frequency in Hz.
+
+- refclk-type: A string describing the reference clock connection
+  either "crystal" or "external".
+
+Example:
+	uctl@118006f000000 {
+		compatible = "cavium,octeon-6335-uctl";
+		reg = <0x11800 0x6f000000 0x0 0x100>;
+		ranges; /* Direct mapping */
+		#address-cells = <2>;
+		#size-cells = <2>;
+		/* 12MHz, 24MHz and 48MHz allowed */
+		refclk-frequency = <24000000>;
+		/* Either "crystal" or "external" */
+		refclk-type = "crystal";
+
+		ehci@16f0000000000 {
+			compatible = "cavium,octeon-6335-ehci","usb-ehci";
+			reg = <0x16f00 0x00000000 0x0 0x100>;
+			interrupts = <0 56>;
+			big-endian-regs;
+		};
+		ohci@16f0000000400 {
+			compatible = "cavium,octeon-6335-ohci","usb-ohci";
+			reg = <0x16f00 0x00000400 0x0 0x100>;
+			interrupts = <0 56>;
+			big-endian-regs;
+		};
+	};
+
diff --git a/Documentation/devicetree/bindings/net/cavium-mdio.txt b/Documentation/devicetree/bindings/net/cavium-mdio.txt
new file mode 100644
index 0000000..04cb749
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/cavium-mdio.txt
@@ -0,0 +1,27 @@
+* System Management Interface (SMI) / MDIO
+
+Properties:
+- compatible: "cavium,octeon-3860-mdio"
+
+  Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
+
+- reg: The base address of the MDIO bus controller register bank.
+
+- #address-cells: Must be <1>.
+
+- #size-cells: Must be <0>.  MDIO addresses have no size component.
+
+Typically an MDIO bus might have several children.
+
+Example:
+	mdio@1180000001800 {
+		compatible = "cavium,octeon-3860-mdio";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x11800 0x00001800 0x0 0x40>;
+
+		ethernet-phy@0 {
+			...
+			reg = <0>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/net/cavium-mix.txt b/Documentation/devicetree/bindings/net/cavium-mix.txt
new file mode 100644
index 0000000..e4f9d3c
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/cavium-mix.txt
@@ -0,0 +1,40 @@
+* MIX Ethernet controller.
+
+Properties:
+- compatible: "cavium,octeon-5750-mix"
+
+  Compatibility with all cn5XXX and cn6XXX SOCs populated with MIX
+  devices.
+
+- reg: The base addresses of four separate register banks.  The first
+  bank contains the MIX registers.  The second bank the corresponding
+  AGL registers.  The third bank are the AGL registers shared by all
+  MIX devices present.  The fourth bank is the AGL_PRT_CTL shared by
+  all MIX devices present.
+
+- cell-index: A single cell specifying which portion of the shared
+  register banks corresponds to this MIX device.
+
+- interrupts: Two interrupt specifiers.  The first is the MIX
+  interrupt routing and the second the routing for the AGL interrupts.
+
+- mac-address: Optional, the MAC address to assign to the device.
+
+- local-mac-address: Optional, the MAC address to assign to the device
+  if mac-address is not specified.
+
+- phy-handle: Optional, a phandle for the PHY device connected to this device.
+
+Example:
+	ethernet@1070000100800 {
+		compatible = "cavium,octeon-5750-mix";
+		reg = <0x10700 0x00100800 0x0 0x100>, /* MIX */
+		      <0x11800 0xE0000800 0x0 0x300>, /* AGL */
+		      <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED  */
+		      <0x11800 0xE0002008 0x0 0x8>;   /* AGL_PRT_CTL */
+		cell-index = <1>;
+		interrupts = <1 18>, < 1 46>;
+		local-mac-address = [ 00 0f b7 10 63 54 ];
+		phy-handle = <&phy1>;
+	};
+
diff --git a/Documentation/devicetree/bindings/net/cavium-pip.txt b/Documentation/devicetree/bindings/net/cavium-pip.txt
new file mode 100644
index 0000000..d4c53ba
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/cavium-pip.txt
@@ -0,0 +1,98 @@
+* PIP Ethernet nexus.
+
+The PIP Ethernet nexus can control several data packet input/output
+devices.  The devices have a two level grouping scheme.  There may be
+several interfaces, and each interface may have several ports.  These
+ports might be an individual Ethernet PHY.
+
+
+Properties for the PIP nexus:
+- compatible: "cavium,octeon-3860-pip"
+
+  Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
+
+- reg: The base address of the PIP's register bank.
+
+- #address-cells: Must be <1>.
+
+- #size-cells: Must be <0>.
+
+Properties for PIP interfaces which is a child the PIP nexus:
+- compatible: "cavium,octeon-3860-pip-interface"
+
+  Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
+
+- reg: The interface number.
+
+- #address-cells: Must be <1>.
+
+- #size-cells: Must be <0>.
+
+Properties for PIP port which is a child the PIP interface:
+- compatible: "cavium,octeon-3860-pip-port"
+
+  Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
+
+- reg: The port number within the interface group.
+
+- mac-address: Optional, the MAC address to assign to the device.
+
+- local-mac-address: Optional, the MAC address to assign to the device
+  if mac-address is not specified.
+
+- phy-handle: Optional, a phandle for the PHY device connected to this device.
+
+Example:
+
+	pip@11800a0000000 {
+		compatible = "cavium,octeon-3860-pip";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x11800 0xa0000000 0x0 0x2000>;
+
+		interface@0 {
+			compatible = "cavium,octeon-3860-pip-interface";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>; /* interface */
+
+			ethernet@0 {
+				compatible = "cavium,octeon-3860-pip-port";
+				reg = <0x0>; /* Port */
+				local-mac-address = [ 00 0f b7 10 63 60 ];
+				phy-handle = <&phy2>;
+			};
+			ethernet@1 {
+				compatible = "cavium,octeon-3860-pip-port";
+				reg = <0x1>; /* Port */
+				local-mac-address = [ 00 0f b7 10 63 61 ];
+				phy-handle = <&phy3>;
+			};
+			ethernet@2 {
+				compatible = "cavium,octeon-3860-pip-port";
+				reg = <0x2>; /* Port */
+				local-mac-address = [ 00 0f b7 10 63 62 ];
+				phy-handle = <&phy4>;
+			};
+			ethernet@3 {
+				compatible = "cavium,octeon-3860-pip-port";
+				reg = <0x3>; /* Port */
+				local-mac-address = [ 00 0f b7 10 63 63 ];
+				phy-handle = <&phy5>;
+			};
+		};
+
+		interface@1 {
+			compatible = "cavium,octeon-3860-pip-interface";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <1>; /* interface */
+
+			ethernet@0 {
+				compatible = "cavium,octeon-3860-pip-port";
+				reg = <0x0>; /* Port */
+				local-mac-address = [ 00 0f b7 10 63 64 ];
+				phy-handle = <&phy6>;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/serial/cavium-uart.txt b/Documentation/devicetree/bindings/serial/cavium-uart.txt
new file mode 100644
index 0000000..87a6c37
--- /dev/null
+++ b/Documentation/devicetree/bindings/serial/cavium-uart.txt
@@ -0,0 +1,19 @@
+* Universal Asynchronous Receiver/Transmitter (UART)
+
+- compatible: "cavium,octeon-3860-uart"
+
+  Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
+
+- reg: The base address of the UART register bank.
+
+- interrupts: A single interrupt specifier.
+
+- current-speed: Optional, the current bit rate in bits per second.
+
+Example:
+	uart1: serial@1180000000c00 {
+		compatible = "cavium,octeon-3860-uart","ns16550";
+		reg = <0x11800 0x00000c00 0x0 0x400>;
+		current-speed = <115200>;
+		interrupts = <0 35>;
+	};
diff --git a/arch/mips/cavium-octeon/.gitignore b/arch/mips/cavium-octeon/.gitignore
new file mode 100644
index 0000000..39c9686
--- /dev/null
+++ b/arch/mips/cavium-octeon/.gitignore
@@ -0,0 +1,2 @@
+*.dtb.S
+*.dtb
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
index 19eb043..1e37522 100644
--- a/arch/mips/cavium-octeon/Makefile
+++ b/arch/mips/cavium-octeon/Makefile
@@ -15,3 +15,16 @@ obj-y += octeon-memcpy.o
 obj-y += executive/
 
 obj-$(CONFIG_SMP)                     += smp.o
+
+DTS_FILES = octeon_3xxx.dts octeon_68xx.dts
+DTB_FILES = $(patsubst %.dts, %.dtb, $(DTS_FILES))
+
+obj-y += $(patsubst %.dts, %.dtb.o, $(DTS_FILES))
+
+$(obj)/%.dtb: $(src)/%.dts FORCE
+	$(call if_changed_dep,dtc)
+
+# Let's keep the .dtb files around in case we want to look at them.
+.SECONDARY:  $(addprefix $(obj)/, $(DTB_FILES))
+
+clean-files += $(DTB_FILES) $(patsubst %.dtb, %.dtb.S, $(DTB_FILES))
diff --git a/arch/mips/cavium-octeon/octeon_3xxx.dts b/arch/mips/cavium-octeon/octeon_3xxx.dts
new file mode 100644
index 0000000..e0fb0e3
--- /dev/null
+++ b/arch/mips/cavium-octeon/octeon_3xxx.dts
@@ -0,0 +1,571 @@
+/dts-v1/;
+/*
+ * OCTEON 3XXX, 5XXX, 63XX device tree skeleton.
+ *
+ * This device tree is pruned and patched by early boot code before
+ * use.  Because of this, it contains a super-set of the available
+ * devices and properties.
+ */
+/ {
+	compatible = "cavium,octeon-3860";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&ciu>;
+
+	soc@0 {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges; /* Direct mapping */
+
+		ciu: interrupt-controller@1070000000000 {
+			compatible = "cavium,octeon-3860-ciu";
+			interrupt-controller;
+			/* Interrupts are specified by two parts:
+			 * 1) Controller register (0 or 1)
+			 * 2) Bit within the register (0..63)
+			 */
+			#interrupt-cells = <2>;
+			reg = <0x10700 0x00000000 0x0 0x7000>;
+		};
+
+		gpio: gpio-controller@1070000000800 {
+			#gpio-cells = <2>;
+			compatible = "cavium,octeon-3860-gpio";
+			reg = <0x10700 0x00000800 0x0 0x100>;
+			gpio-controller;
+			/* Interrupts are specified by two parts:
+			 * 1) GPIO pin number (0..15)
+			 * 2) Triggering (1 - edge rising
+			 *		  2 - edge falling
+			 *		  4 - level active high
+			 *		  8 - level active low)
+			 */
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			/* The GPIO pin connect to 16 consecutive CUI bits */
+			interrupts = <0 16>; /* <0 17> <0 18> <0 19>
+				     <0 20> <0 21> <0 22> <0 23>
+				     <0 24> <0 25> <0 26> <0 27>
+				     <0 28> <0 29> <0 30> <0 31>; */
+		};
+
+		smi0: mdio@1180000001800 {
+			compatible = "cavium,octeon-3860-mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x11800 0x00001800 0x0 0x40>;
+
+			phy0: ethernet-phy@0 {
+				compatible = "marvell,88e1118";
+				marvell,reg-init =
+					/* Fix rx and tx clock transition timing */
+					<2 0x15 0xffcf 0>, /* Reg 2,21 Clear bits 4, 5 */
+					/* Adjust LED drive. */
+					<3 0x11 0 0x442a>, /* Reg 3,17 <- 0442a */
+					/* irq, blink-activity, blink-link */
+					<3 0x10 0 0x0242>; /* Reg 3,16 <- 0x0242 */
+				reg = <0>;
+			};
+
+			phy1: ethernet-phy@1 {
+				compatible = "marvell,88e1118";
+				marvell,reg-init =
+					/* Fix rx and tx clock transition timing */
+					<2 0x15 0xffcf 0>, /* Reg 2,21 Clear bits 4, 5 */
+					/* Adjust LED drive. */
+					<3 0x11 0 0x442a>, /* Reg 3,17 <- 0442a */
+					/* irq, blink-activity, blink-link */
+					<3 0x10 0 0x0242>; /* Reg 3,16 <- 0x0242 */
+				reg = <1>;
+			};
+
+			phy2: ethernet-phy@2 {
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy3: ethernet-phy@3 {
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy4: ethernet-phy@4 {
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy5: ethernet-phy@5 {
+				reg = <5>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+
+			phy6: ethernet-phy@6 {
+				reg = <6>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy7: ethernet-phy@7 {
+				reg = <7>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy8: ethernet-phy@8 {
+				reg = <8>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy9: ethernet-phy@9 {
+				reg = <9>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+		};
+
+		smi1: mdio@1180000001900 {
+			compatible = "cavium,octeon-3860-mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x11800 0x00001900 0x0 0x40>;
+
+			phy100: ethernet-phy@1 {
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy101: ethernet-phy@2 {
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy102: ethernet-phy@3 {
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+			phy103: ethernet-phy@4 {
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+				interrupt-parent = <&gpio>;
+				interrupts = <12 8>; /* Pin 12, active low */
+			};
+		};
+
+		mix0: ethernet@1070000100000 {
+			compatible = "cavium,octeon-5750-mix";
+			reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */
+			      <0x11800 0xE0000000 0x0 0x300>, /* AGL */
+			      <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED  */
+			      <0x11800 0xE0002000 0x0 0x8>;   /* AGL_PRT_CTL */
+			cell-index = <0>;
+			interrupts = <0 62>, <1 46>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			phy-handle = <&phy0>;
+		};
+
+		mix1: ethernet@1070000100800 {
+			compatible = "cavium,octeon-5750-mix";
+			reg = <0x10700 0x00100800 0x0 0x100>, /* MIX */
+			      <0x11800 0xE0000800 0x0 0x300>, /* AGL */
+			      <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED  */
+			      <0x11800 0xE0002008 0x0 0x8>;   /* AGL_PRT_CTL */
+			cell-index = <1>;
+			interrupts = <1 18>, < 1 46>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			phy-handle = <&phy1>;
+		};
+
+		pip: pip@11800a0000000 {
+			compatible = "cavium,octeon-3860-pip";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x11800 0xa0000000 0x0 0x2000>;
+
+			interface@0 {
+				compatible = "cavium,octeon-3860-pip-interface";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0>; /* interface */
+
+				ethernet@0 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x0>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy2>;
+					cavium,alt-phy-handle = <&phy100>;
+				};
+				ethernet@1 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x1>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy3>;
+					cavium,alt-phy-handle = <&phy101>;
+				};
+				ethernet@2 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x2>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy4>;
+					cavium,alt-phy-handle = <&phy102>;
+				};
+				ethernet@3 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x3>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy5>;
+					cavium,alt-phy-handle = <&phy103>;
+				};
+				ethernet@4 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x4>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+				ethernet@5 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x5>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+				ethernet@6 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x6>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+				ethernet@7 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x7>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+				ethernet@8 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x8>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+				ethernet@9 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x9>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+				ethernet@a {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0xa>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+				ethernet@b {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0xb>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+				ethernet@c {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0xc>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+				ethernet@d {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0xd>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+				ethernet@e {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0xe>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+				ethernet@f {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0xf>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+			};
+
+			interface@1 {
+				compatible = "cavium,octeon-3860-pip-interface";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <1>; /* interface */
+
+				ethernet@0 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x0>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy6>;
+				};
+				ethernet@1 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x1>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy7>;
+				};
+				ethernet@2 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x2>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy8>;
+				};
+				ethernet@3 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x3>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy9>;
+				};
+			};
+		};
+
+		twsi0: i2c@1180000001000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "cavium,octeon-3860-twsi";
+			reg = <0x11800 0x00001000 0x0 0x200>;
+			interrupts = <0 45>;
+			clock-frequency = <100000>;
+
+			rtc@68 {
+				compatible = "dallas,ds1337";
+				reg = <0x68>;
+			};
+			tmp@4c {
+				compatible = "ti,tmp421";
+				reg = <0x4c>;
+			};
+		};
+
+		twsi1: i2c@1180000001200 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "cavium,octeon-3860-twsi";
+			reg = <0x11800 0x00001200 0x0 0x200>;
+			interrupts = <0 59>;
+			clock-frequency = <100000>;
+		};
+
+		uart0: serial@1180000000800 {
+			compatible = "cavium,octeon-3860-uart","ns16550";
+			reg = <0x11800 0x00000800 0x0 0x400>;
+			clock-frequency = <0>;
+			current-speed = <115200>;
+			reg-shift = <3>;
+			interrupts = <0 34>;
+		};
+
+		uart1: serial@1180000000c00 {
+			compatible = "cavium,octeon-3860-uart","ns16550";
+			reg = <0x11800 0x00000c00 0x0 0x400>;
+			clock-frequency = <0>;
+			current-speed = <115200>;
+			reg-shift = <3>;
+			interrupts = <0 35>;
+		};
+
+		uart2: serial@1180000000400 {
+			compatible = "cavium,octeon-3860-uart","ns16550";
+			reg = <0x11800 0x00000400 0x0 0x400>;
+			clock-frequency = <0>;
+			current-speed = <115200>;
+			reg-shift = <3>;
+			interrupts = <1 16>;
+		};
+
+		bootbus: bootbus@1180000000000 {
+			compatible = "cavium,octeon-3860-bootbus";
+			reg = <0x11800 0x00000000 0x0 0x200>;
+			/* The chip select number and offset */
+			#address-cells = <2>;
+			/* The size of the chip select region */
+			#size-cells = <1>;
+			ranges = <0 0  0x0 0x1f400000  0xc00000>,
+				 <1 0  0x10000 0x30000000  0>,
+				 <2 0  0x10000 0x40000000  0>,
+				 <3 0  0x10000 0x50000000  0>,
+				 <4 0  0x0 0x1d020000  0x10000>,
+				 <5 0  0x0 0x1d040000  0x10000>,
+				 <6 0  0x0 0x1d050000  0x10000>,
+				 <7 0  0x10000 0x90000000  0>;
+
+			cavium,cs-config@0 {
+				compatible = "cavium,octeon-3860-bootbus-config";
+				cavium,cs-index = <0>;
+				cavium,t-adr  = <20>;
+				cavium,t-ce   = <60>;
+				cavium,t-oe   = <60>;
+				cavium,t-we   = <45>;
+				cavium,t-rd-hld = <35>;
+				cavium,t-wr-hld = <45>;
+				cavium,t-pause  = <0>;
+				cavium,t-wait   = <0>;
+				cavium,t-page   = <35>;
+				cavium,t-rd-dly = <0>;
+
+				cavium,pages     = <0>;
+				cavium,bus-width = <8>;
+			};
+			cavium,cs-config@4 {
+				compatible = "cavium,octeon-3860-bootbus-config";
+				cavium,cs-index = <4>;
+				cavium,t-adr  = <320>;
+				cavium,t-ce   = <320>;
+				cavium,t-oe   = <320>;
+				cavium,t-we   = <320>;
+				cavium,t-rd-hld = <320>;
+				cavium,t-wr-hld = <320>;
+				cavium,t-pause  = <320>;
+				cavium,t-wait   = <320>;
+				cavium,t-page   = <320>;
+				cavium,t-rd-dly = <0>;
+
+				cavium,pages     = <0>;
+				cavium,bus-width = <8>;
+			};
+			cavium,cs-config@5 {
+				compatible = "cavium,octeon-3860-bootbus-config";
+				cavium,cs-index = <5>;
+				cavium,t-adr  = <5>;
+				cavium,t-ce   = <300>;
+				cavium,t-oe   = <125>;
+				cavium,t-we   = <150>;
+				cavium,t-rd-hld = <100>;
+				cavium,t-wr-hld = <30>;
+				cavium,t-pause  = <0>;
+				cavium,t-wait   = <30>;
+				cavium,t-page   = <320>;
+				cavium,t-rd-dly = <0>;
+
+				cavium,pages     = <0>;
+				cavium,bus-width = <16>;
+			};
+			cavium,cs-config@6 {
+				compatible = "cavium,octeon-3860-bootbus-config";
+				cavium,cs-index = <6>;
+				cavium,t-adr  = <5>;
+				cavium,t-ce   = <300>;
+				cavium,t-oe   = <270>;
+				cavium,t-we   = <150>;
+				cavium,t-rd-hld = <100>;
+				cavium,t-wr-hld = <70>;
+				cavium,t-pause  = <0>;
+				cavium,t-wait   = <0>;
+				cavium,t-page   = <320>;
+				cavium,t-rd-dly = <0>;
+
+				cavium,pages     = <0>;
+				cavium,wait-mode;
+				cavium,bus-width = <16>;
+			};
+
+			flash0: nor@0,0 {
+				compatible = "cfi-flash";
+				reg = <0 0 0x800000>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+			};
+
+			led0: led-display@4,0 {
+				compatible = "avago,hdsp-253x";
+				reg = <4 0x20 0x20>, <4 0 0x20>;
+			};
+
+			cf0: compact-flash@5,0 {
+				compatible = "cavium,ebt3000-compact-flash";
+				reg = <5 0 0x10000>, <6 0 0x10000>;
+				cavium,bus-width = <16>;
+				cavium,true-ide;
+				cavium,dma-engine-handle = <&dma0>;
+			};
+		};
+
+		dma0: dma-engine@1180000000100 {
+			compatible = "cavium,octeon-5750-bootbus-dma";
+			reg = <0x11800 0x00000100 0x0 0x8>;
+			interrupts = <0 63>;
+		};
+		dma1: dma-engine@1180000000108 {
+			compatible = "cavium,octeon-5750-bootbus-dma";
+			reg = <0x11800 0x00000108 0x0 0x8>;
+			interrupts = <0 63>;
+		};
+
+		uctl: uctl@118006f000000 {
+			compatible = "cavium,octeon-6335-uctl";
+			reg = <0x11800 0x6f000000 0x0 0x100>;
+			ranges; /* Direct mapping */
+			#address-cells = <2>;
+			#size-cells = <2>;
+			/* 12MHz, 24MHz and 48MHz allowed */
+			refclk-frequency = <12000000>;
+			/* Either "crystal" or "external" */
+			refclk-type = "crystal";
+
+			ehci@16f0000000000 {
+				compatible = "cavium,octeon-6335-ehci","usb-ehci";
+				reg = <0x16f00 0x00000000 0x0 0x100>;
+				interrupts = <0 56>;
+				big-endian-regs;
+			};
+			ohci@16f0000000400 {
+				compatible = "cavium,octeon-6335-ohci","usb-ohci";
+				reg = <0x16f00 0x00000400 0x0 0x100>;
+				interrupts = <0 56>;
+				big-endian-regs;
+			};
+		};
+	};
+
+	aliases {
+		mix0 = &mix0;
+		mix1 = &mix1;
+		pip = &pip;
+		smi0 = &smi0;
+		smi1 = &smi1;
+		twsi0 = &twsi0;
+		twsi1 = &twsi1;
+		uart0 = &uart0;
+		uart1 = &uart1;
+		uart2 = &uart2;
+		flash0 = &flash0;
+		cf0 = &cf0;
+		uctl = &uctl;
+		led0 = &led0;
+	};
+ };
diff --git a/arch/mips/cavium-octeon/octeon_68xx.dts b/arch/mips/cavium-octeon/octeon_68xx.dts
new file mode 100644
index 0000000..bde6b23
--- /dev/null
+++ b/arch/mips/cavium-octeon/octeon_68xx.dts
@@ -0,0 +1,625 @@
+/dts-v1/;
+/*
+ * OCTEON 68XX device tree skeleton.
+ *
+ * This device tree is pruned and patched by early boot code before
+ * use.  Because of this, it contains a super-set of the available
+ * devices and properties.
+ */
+/ {
+	compatible = "cavium,octeon-6880";
+	#address-cells = <2>;
+	#size-cells = <2>;
+	interrupt-parent = <&ciu2>;
+
+	soc@0 {
+		compatible = "simple-bus";
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges; /* Direct mapping */
+
+		ciu2: interrupt-controller@1070100000000 {
+			compatible = "cavium,octeon-6880-ciu2";
+			interrupt-controller;
+			/* Interrupts are specified by two parts:
+			 * 1) Controller register (0 or 7)
+			 * 2) Bit within the register (0..63)
+			 */
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0x10701 0x00000000 0x0 0x4000000>;
+		};
+
+		gpio: gpio-controller@1070000000800 {
+			#gpio-cells = <2>;
+			compatible = "cavium,octeon-3860-gpio";
+			reg = <0x10700 0x00000800 0x0 0x100>;
+			gpio-controller;
+			/* Interrupts are specified by two parts:
+			 * 1) GPIO pin number (0..15)
+			 * 2) Triggering (1 - edge rising
+			 *		  2 - edge falling
+			 *		  4 - level active high
+			 *		  8 - level active low)
+			 */
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			/* The GPIO pins connect to 16 consecutive CUI bits */
+			interrupts = <7 0>; /* <7 1> <7 2> <7 3>
+				     <7 4> <7 5> <7 6> <7 7>
+				     <7 8> <7 9> <7 10> <7 11>
+				     <7 12> <7 13> <7 14> <7 15>; */
+		};
+
+		smi0: mdio@1180000003800 {
+			compatible = "cavium,octeon-3860-mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x11800 0x00003800 0x0 0x40>;
+
+			phy0: ethernet-phy@6 {
+				compatible = "marvell,88e1118";
+				marvell,reg-init =
+					/* Fix rx and tx clock transition timing */
+					<2 0x15 0xffcf 0>, /* Reg 2,21 Clear bits 4, 5 */
+					/* Adjust LED drive. */
+					<3 0x11 0 0x442a>, /* Reg 3,17 <- 0442a */
+					/* irq, blink-activity, blink-link */
+					<3 0x10 0 0x0242>; /* Reg 3,16 <- 0x0242 */
+				reg = <6>;
+			};
+
+			phy1: ethernet-phy@1 {
+				cavium,qlm-trim = "4,sgmii";
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy2: ethernet-phy@2 {
+				cavium,qlm-trim = "4,sgmii";
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy3: ethernet-phy@3 {
+				cavium,qlm-trim = "4,sgmii";
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy4: ethernet-phy@4 {
+				cavium,qlm-trim = "4,sgmii";
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+		};
+
+		smi1: mdio@1180000003880 {
+			compatible = "cavium,octeon-3860-mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x11800 0x00003880 0x0 0x40>;
+
+			phy41: ethernet-phy@1 {
+				cavium,qlm-trim = "0,sgmii";
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy42: ethernet-phy@2 {
+				cavium,qlm-trim = "0,sgmii";
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy43: ethernet-phy@3 {
+				cavium,qlm-trim = "0,sgmii";
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy44: ethernet-phy@4 {
+				cavium,qlm-trim = "0,sgmii";
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+		};
+
+		smi2: mdio@1180000003900 {
+			compatible = "cavium,octeon-3860-mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x11800 0x00003900 0x0 0x40>;
+
+			phy21: ethernet-phy@1 {
+				cavium,qlm-trim = "2,sgmii";
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy22: ethernet-phy@2 {
+				cavium,qlm-trim = "2,sgmii";
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy23: ethernet-phy@3 {
+				cavium,qlm-trim = "2,sgmii";
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy24: ethernet-phy@4 {
+				cavium,qlm-trim = "2,sgmii";
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+		};
+
+		smi3: mdio@1180000003980 {
+			compatible = "cavium,octeon-3860-mdio";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x11800 0x00003980 0x0 0x40>;
+
+			phy11: ethernet-phy@1 {
+				cavium,qlm-trim = "3,sgmii";
+				reg = <1>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy12: ethernet-phy@2 {
+				cavium,qlm-trim = "3,sgmii";
+				reg = <2>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy13: ethernet-phy@3 {
+				cavium,qlm-trim = "3,sgmii";
+				reg = <3>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+			phy14: ethernet-phy@4 {
+				cavium,qlm-trim = "3,sgmii";
+				reg = <4>;
+				compatible = "marvell,88e1149r";
+				marvell,reg-init = <3 0x10 0 0x5777>,
+					<3 0x11 0 0x00aa>,
+					<3 0x12 0 0x4105>,
+					<3 0x13 0 0x0a60>;
+			};
+		};
+
+		mix0: ethernet@1070000100000 {
+			compatible = "cavium,octeon-5750-mix";
+			reg = <0x10700 0x00100000 0x0 0x100>, /* MIX */
+			      <0x11800 0xE0000000 0x0 0x300>, /* AGL */
+			      <0x11800 0xE0000400 0x0 0x400>, /* AGL_SHARED  */
+			      <0x11800 0xE0002000 0x0 0x8>;   /* AGL_PRT_CTL */
+			cell-index = <0>;
+			interrupts = <6 40>, <6 32>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			phy-handle = <&phy0>;
+		};
+
+		pip: pip@11800a0000000 {
+			compatible = "cavium,octeon-3860-pip";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x11800 0xa0000000 0x0 0x2000>;
+
+			interface@4 {
+				compatible = "cavium,octeon-3860-pip-interface";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x4>; /* interface */
+
+				ethernet@0 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x0>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy1>;
+				};
+				ethernet@1 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x1>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy2>;
+				};
+				ethernet@2 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x2>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy3>;
+				};
+				ethernet@3 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x3>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy4>;
+				};
+			};
+
+			interface@3 {
+				compatible = "cavium,octeon-3860-pip-interface";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x3>; /* interface */
+
+				ethernet@0 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x0>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy11>;
+				};
+				ethernet@1 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x1>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy12>;
+				};
+				ethernet@2 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x2>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy13>;
+				};
+				ethernet@3 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x3>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy14>;
+				};
+			};
+
+			interface@2 {
+				compatible = "cavium,octeon-3860-pip-interface";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x2>; /* interface */
+
+				ethernet@0 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x0>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy21>;
+				};
+				ethernet@1 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x1>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy22>;
+				};
+				ethernet@2 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x2>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy23>;
+				};
+				ethernet@3 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x3>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy24>;
+				};
+			};
+
+			interface@1 {
+				compatible = "cavium,octeon-3860-pip-interface";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x1>; /* interface */
+
+				ethernet@0 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x0>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+				};
+			};
+
+			interface@0 {
+				compatible = "cavium,octeon-3860-pip-interface";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				reg = <0x0>; /* interface */
+
+				ethernet@0 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x0>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy41>;
+				};
+				ethernet@1 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x1>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy42>;
+				};
+				ethernet@2 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x2>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy43>;
+				};
+				ethernet@3 {
+					compatible = "cavium,octeon-3860-pip-port";
+					reg = <0x3>; /* Port */
+					local-mac-address = [ 00 00 00 00 00 00 ];
+					phy-handle = <&phy44>;
+				};
+			};
+		};
+
+		twsi0: i2c@1180000001000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "cavium,octeon-3860-twsi";
+			reg = <0x11800 0x00001000 0x0 0x200>;
+			interrupts = <3 32>;
+			clock-frequency = <100000>;
+
+			rtc@68 {
+				compatible = "dallas,ds1337";
+				reg = <0x68>;
+			};
+			tmp@4c {
+				compatible = "ti,tmp421";
+				reg = <0x4c>;
+			};
+		};
+
+		twsi1: i2c@1180000001200 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "cavium,octeon-3860-twsi";
+			reg = <0x11800 0x00001200 0x0 0x200>;
+			interrupts = <3 33>;
+			clock-frequency = <100000>;
+		};
+
+		uart0: serial@1180000000800 {
+			compatible = "cavium,octeon-3860-uart","ns16550";
+			reg = <0x11800 0x00000800 0x0 0x400>;
+			clock-frequency = <0>;
+			current-speed = <115200>;
+			reg-shift = <3>;
+			interrupts = <3 36>;
+		};
+
+		uart1: serial@1180000000c00 {
+			compatible = "cavium,octeon-3860-uart","ns16550";
+			reg = <0x11800 0x00000c00 0x0 0x400>;
+			clock-frequency = <0>;
+			current-speed = <115200>;
+			reg-shift = <3>;
+			interrupts = <3 37>;
+		};
+
+		bootbus: bootbus@1180000000000 {
+			compatible = "cavium,octeon-3860-bootbus";
+			reg = <0x11800 0x00000000 0x0 0x200>;
+			/* The chip select number and offset */
+			#address-cells = <2>;
+			/* The size of the chip select region */
+			#size-cells = <1>;
+			ranges = <0 0  0       0x1f400000  0xc00000>,
+				 <1 0  0x10000 0x30000000  0>,
+				 <2 0  0x10000 0x40000000  0>,
+				 <3 0  0x10000 0x50000000  0>,
+				 <4 0  0       0x1d020000  0x10000>,
+				 <5 0  0       0x1d040000  0x10000>,
+				 <6 0  0       0x1d050000  0x10000>,
+				 <7 0  0x10000 0x90000000  0>;
+
+			cavium,cs-config@0 {
+				compatible = "cavium,octeon-3860-bootbus-config";
+				cavium,cs-index = <0>;
+				cavium,t-adr  = <10>;
+				cavium,t-ce   = <50>;
+				cavium,t-oe   = <50>;
+				cavium,t-we   = <35>;
+				cavium,t-rd-hld = <25>;
+				cavium,t-wr-hld = <35>;
+				cavium,t-pause  = <0>;
+				cavium,t-wait   = <300>;
+				cavium,t-page   = <25>;
+				cavium,t-rd-dly = <0>;
+
+				cavium,pages     = <0>;
+				cavium,bus-width = <8>;
+			};
+			cavium,cs-config@4 {
+				compatible = "cavium,octeon-3860-bootbus-config";
+				cavium,cs-index = <4>;
+				cavium,t-adr  = <320>;
+				cavium,t-ce   = <320>;
+				cavium,t-oe   = <320>;
+				cavium,t-we   = <320>;
+				cavium,t-rd-hld = <320>;
+				cavium,t-wr-hld = <320>;
+				cavium,t-pause  = <320>;
+				cavium,t-wait   = <320>;
+				cavium,t-page   = <320>;
+				cavium,t-rd-dly = <0>;
+
+				cavium,pages     = <0>;
+				cavium,bus-width = <8>;
+			};
+			cavium,cs-config@5 {
+				compatible = "cavium,octeon-3860-bootbus-config";
+				cavium,cs-index = <5>;
+				cavium,t-adr  = <0>;
+				cavium,t-ce   = <300>;
+				cavium,t-oe   = <125>;
+				cavium,t-we   = <150>;
+				cavium,t-rd-hld = <100>;
+				cavium,t-wr-hld = <300>;
+				cavium,t-pause  = <0>;
+				cavium,t-wait   = <300>;
+				cavium,t-page   = <310>;
+				cavium,t-rd-dly = <0>;
+
+				cavium,pages     = <0>;
+				cavium,bus-width = <16>;
+			};
+			cavium,cs-config@6 {
+				compatible = "cavium,octeon-3860-bootbus-config";
+				cavium,cs-index = <6>;
+				cavium,t-adr  = <0>;
+				cavium,t-ce   = <30>;
+				cavium,t-oe   = <125>;
+				cavium,t-we   = <150>;
+				cavium,t-rd-hld = <100>;
+				cavium,t-wr-hld = <30>;
+				cavium,t-pause  = <0>;
+				cavium,t-wait   = <30>;
+				cavium,t-page   = <310>;
+				cavium,t-rd-dly = <0>;
+
+				cavium,pages     = <0>;
+				cavium,wait-mode;
+				cavium,bus-width = <16>;
+			};
+
+			flash0: nor@0,0 {
+				compatible = "cfi-flash";
+				reg = <0 0 0x800000>;
+				#address-cells = <1>;
+				#size-cells = <1>;
+
+				partition@0 {
+					label = "bootloader";
+					reg = <0 0x200000>;
+					read-only;
+				};
+				partition@200000 {
+					label = "kernel";
+					reg = <0x200000 0x200000>;
+				};
+				partition@400000 {
+					label = "cramfs";
+					reg = <0x400000 0x3fe000>;
+				};
+				partition@7fe000 {
+					label = "environment";
+					reg = <0x7fe000 0x2000>;
+					read-only;
+				};
+			};
+
+			led0: led-display@4,0 {
+				compatible = "avago,hdsp-253x";
+				reg = <4 0x20 0x20>, <4 0 0x20>;
+			};
+
+			compact-flash@5,0 {
+				compatible = "cavium,ebt3000-compact-flash";
+				reg = <5 0 0x10000>, <6 0 0x10000>;
+				cavium,bus-width = <16>;
+				cavium,true-ide;
+				cavium,dma-engine-handle = <&dma0>;
+			};
+		};
+
+		dma0: dma-engine@1180000000100 {
+			compatible = "cavium,octeon-5750-bootbus-dma";
+			reg = <0x11800 0x00000100 0x0 0x8>;
+			interrupts = <0 63>;
+		};
+		dma1: dma-engine@1180000000108 {
+			compatible = "cavium,octeon-5750-bootbus-dma";
+			reg = <0x11800 0x00000108 0x0 0x8>;
+			interrupts = <0 63>;
+		};
+
+		uctl: uctl@118006f000000 {
+			compatible = "cavium,octeon-6335-uctl";
+			reg = <0x11800 0x6f000000 0x0 0x100>;
+			ranges; /* Direct mapping */
+			#address-cells = <2>;
+			#size-cells = <2>;
+			/* 12MHz, 24MHz and 48MHz allowed */
+			refclk-frequency = <12000000>;
+			/* Either "crystal" or "external" */
+			refclk-type = "crystal";
+
+			ehci@16f0000000000 {
+				compatible = "cavium,octeon-6335-ehci","usb-ehci";
+				reg = <0x16f00 0x00000000 0x0 0x100>;
+				interrupts = <3 44>;
+				big-endian-regs;
+			};
+			ohci@16f0000000400 {
+				compatible = "cavium,octeon-6335-ohci","usb-ohci";
+				reg = <0x16f00 0x00000400 0x0 0x100>;
+				interrupts = <3 44>;
+				big-endian-regs;
+			};
+		};
+	};
+
+	aliases {
+		mix0 = &mix0;
+		pip = &pip;
+		smi0 = &smi0;
+		smi1 = &smi1;
+		smi2 = &smi2;
+		smi3 = &smi3;
+		twsi0 = &twsi0;
+		twsi1 = &twsi1;
+		uart0 = &uart0;
+		uart1 = &uart1;
+		uctl = &uctl;
+		led0 = &led0;
+		flash0 = &flash0;
+	};
+ };
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v6 2/5] MIPS: Don't define early_init_devtree() and device_tree_init() in prom.c for CPU_CAVIUM_OCTEON
  2012-03-01  0:56 [PATCH v6 0/5] MIPS: Octeon: Use Device Tree David Daney
  2012-03-01  0:56 ` [PATCH v6 1/5] MIPS: Octeon: Add device tree source files David Daney
@ 2012-03-01  0:56 ` David Daney
  2012-03-01  0:57 ` [PATCH v6 3/5] MIPS: Octeon: Add irq handlers for GPIO interrupts David Daney
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 20+ messages in thread
From: David Daney @ 2012-03-01  0:56 UTC (permalink / raw)
  To: linux-mips, ralf, devicetree-discuss, Grant Likely, Rob Herring
  Cc: linux-kernel, David Daney

From: David Daney <david.daney@cavium.com>

This code is not common enough to be in a shared file, so OCTEON defines
it's own versions.

When the last of this target specific code is moved out, we can remove
all of this.

Signed-off-by: David Daney <david.daney@cavium.com>
---
 arch/mips/kernel/prom.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
index 558b539..4aaa5c0 100644
--- a/arch/mips/kernel/prom.c
+++ b/arch/mips/kernel/prom.c
@@ -60,6 +60,7 @@ void __init early_init_dt_setup_initrd_arch(unsigned long start,
 }
 #endif
 
+#ifndef CONFIG_CPU_CAVIUM_OCTEON
 void __init early_init_devtree(void *params)
 {
 	/* Setup flat device-tree pointer */
@@ -95,3 +96,4 @@ void __init device_tree_init(void)
 	/* free the space reserved for the dt blob */
 	free_mem_mach(base, size);
 }
+#endif /* !CONFIG_CPU_CAVIUM_OCTEON */
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v6 3/5] MIPS: Octeon: Add irq handlers for GPIO interrupts.
  2012-03-01  0:56 [PATCH v6 0/5] MIPS: Octeon: Use Device Tree David Daney
  2012-03-01  0:56 ` [PATCH v6 1/5] MIPS: Octeon: Add device tree source files David Daney
  2012-03-01  0:56 ` [PATCH v6 2/5] MIPS: Don't define early_init_devtree() and device_tree_init() in prom.c for CPU_CAVIUM_OCTEON David Daney
@ 2012-03-01  0:57 ` David Daney
  2012-03-01  0:57 ` [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts David Daney
  2012-03-01  0:57 ` [PATCH v6 5/5] MIPS: Octeon: Initialize and fixup device tree David Daney
  4 siblings, 0 replies; 20+ messages in thread
From: David Daney @ 2012-03-01  0:57 UTC (permalink / raw)
  To: linux-mips, ralf, devicetree-discuss, Grant Likely, Rob Herring
  Cc: linux-kernel, David Daney

From: David Daney <david.daney@cavium.com>

This is needed for follow-on on patches for Octeon to use the Device
Tree to configure GPIO interrupts.

Signed-off-by: David Daney <david.daney@cavium.com>
---
 arch/mips/cavium-octeon/octeon-irq.c |   96 +++++++++++++++++++++++++++++++++-
 1 files changed, 95 insertions(+), 1 deletions(-)

diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index ffd4ae6..bdcedd3 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -505,6 +505,72 @@ static void octeon_irq_ciu_enable_all_v2(struct irq_data *data)
 	}
 }
 
+static void octeon_irq_gpio_setup(struct irq_data *data)
+{
+	union cvmx_gpio_bit_cfgx cfg;
+	int bit = data->irq - OCTEON_IRQ_GPIO0;
+	u32 t = irqd_get_trigger_type(data);
+
+	cfg.u64 = 0;
+	cfg.s.int_en = 1;
+	cfg.s.int_type = (t & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) != 0;
+	cfg.s.rx_xor = (t & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) != 0;
+
+	/* 1 uS glitch filter*/
+	cfg.s.fil_cnt = 7;
+	cfg.s.fil_sel = 3;
+
+	cvmx_write_csr(CVMX_GPIO_BIT_CFGX(bit), cfg.u64);
+}
+
+static void octeon_irq_ciu_enable_gpio_v2(struct irq_data *data)
+{
+	octeon_irq_gpio_setup(data);
+	octeon_irq_ciu_enable_v2(data);
+}
+
+static void octeon_irq_ciu_enable_gpio(struct irq_data *data)
+{
+	octeon_irq_gpio_setup(data);
+	octeon_irq_ciu_enable(data);
+}
+
+static int octeon_irq_ciu_gpio_set_type(struct irq_data *data, unsigned int t)
+{
+	u32 current_type = irqd_get_trigger_type(data);
+
+	/* If the type has been set, don't change it */
+	if (current_type && current_type != t)
+		return -EINVAL;
+
+	irqd_set_trigger_type(data, t);
+	return IRQ_SET_MASK_OK;
+}
+
+static void octeon_irq_ciu_disable_gpio_v2(struct irq_data *data)
+{
+	int bit = data->irq - OCTEON_IRQ_GPIO0;
+	cvmx_write_csr(CVMX_GPIO_BIT_CFGX(bit), 0);
+
+	octeon_irq_ciu_disable_all_v2(data);
+}
+
+static void octeon_irq_ciu_disable_gpio(struct irq_data *data)
+{
+	int bit = data->irq - OCTEON_IRQ_GPIO0;
+	cvmx_write_csr(CVMX_GPIO_BIT_CFGX(bit), 0);
+
+	octeon_irq_ciu_disable_all(data);
+}
+
+static void octeon_irq_ciu_gpio_ack(struct irq_data *data)
+{
+	int bit = data->irq - OCTEON_IRQ_GPIO0;
+	u64 mask = 1ull << bit;
+
+	cvmx_write_csr(CVMX_GPIO_INT_CLR, mask);
+}
+
 #ifdef CONFIG_SMP
 
 static void octeon_irq_cpu_offline_ciu(struct irq_data *data)
@@ -717,6 +783,31 @@ static struct irq_chip octeon_irq_chip_ciu_mbox = {
 	.flags = IRQCHIP_ONOFFLINE_ENABLED,
 };
 
+static struct irq_chip octeon_irq_chip_ciu_gpio_v2 = {
+	.name = "CIU-GPIO",
+	.irq_enable = octeon_irq_ciu_enable_gpio_v2,
+	.irq_disable = octeon_irq_ciu_disable_gpio_v2,
+	.irq_ack = octeon_irq_ciu_gpio_ack,
+	.irq_mask = octeon_irq_ciu_disable_local_v2,
+	.irq_unmask = octeon_irq_ciu_enable_v2,
+	.irq_set_type = octeon_irq_ciu_gpio_set_type,
+#ifdef CONFIG_SMP
+	.irq_set_affinity = octeon_irq_ciu_set_affinity_v2,
+#endif
+};
+
+static struct irq_chip octeon_irq_chip_ciu_gpio = {
+	.name = "CIU-GPIO",
+	.irq_enable = octeon_irq_ciu_enable_gpio,
+	.irq_disable = octeon_irq_ciu_disable_gpio,
+	.irq_mask = octeon_irq_dummy_mask,
+	.irq_ack = octeon_irq_ciu_gpio_ack,
+	.irq_set_type = octeon_irq_ciu_gpio_set_type,
+#ifdef CONFIG_SMP
+	.irq_set_affinity = octeon_irq_ciu_set_affinity,
+#endif
+};
+
 /*
  * Watchdog interrupts are special.  They are associated with a single
  * core, so we hardwire the affinity to that core.
@@ -890,6 +981,7 @@ static void __init octeon_irq_init_ciu(void)
 	struct irq_chip *chip_edge;
 	struct irq_chip *chip_mbox;
 	struct irq_chip *chip_wd;
+	struct irq_chip *chip_gpio;
 
 	octeon_irq_init_ciu_percpu();
 	octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu;
@@ -904,6 +996,7 @@ static void __init octeon_irq_init_ciu(void)
 		chip_edge = &octeon_irq_chip_ciu_edge_v2;
 		chip_mbox = &octeon_irq_chip_ciu_mbox_v2;
 		chip_wd = &octeon_irq_chip_ciu_wd_v2;
+		chip_gpio = &octeon_irq_chip_ciu_gpio_v2;
 	} else {
 		octeon_irq_ip2 = octeon_irq_ip2_v1;
 		octeon_irq_ip3 = octeon_irq_ip3_v1;
@@ -911,6 +1004,7 @@ static void __init octeon_irq_init_ciu(void)
 		chip_edge = &octeon_irq_chip_ciu_edge;
 		chip_mbox = &octeon_irq_chip_ciu_mbox;
 		chip_wd = &octeon_irq_chip_ciu_wd;
+		chip_gpio = &octeon_irq_chip_ciu_gpio;
 	}
 	octeon_irq_ip4 = octeon_irq_ip4_mask;
 
@@ -921,7 +1015,7 @@ static void __init octeon_irq_init_ciu(void)
 	for (i = 0; i < 16; i++)
 		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq);
 	for (i = 0; i < 16; i++)
-		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16, chip, handle_level_irq);
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16, chip_gpio, handle_level_irq);
 
 	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
 	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-01  0:56 [PATCH v6 0/5] MIPS: Octeon: Use Device Tree David Daney
                   ` (2 preceding siblings ...)
  2012-03-01  0:57 ` [PATCH v6 3/5] MIPS: Octeon: Add irq handlers for GPIO interrupts David Daney
@ 2012-03-01  0:57 ` David Daney
  2012-03-02 14:22   ` Rob Herring
  2012-03-02 19:02   ` Grant Likely
  2012-03-01  0:57 ` [PATCH v6 5/5] MIPS: Octeon: Initialize and fixup device tree David Daney
  4 siblings, 2 replies; 20+ messages in thread
From: David Daney @ 2012-03-01  0:57 UTC (permalink / raw)
  To: linux-mips, ralf, devicetree-discuss, Grant Likely, Rob Herring
  Cc: linux-kernel, David Daney

From: David Daney <david.daney@cavium.com>

Select IRQ_DOMAIN so the core irq_domain code and supply
irq_create_of_mapping().

Signed-off-by: David Daney <david.daney@cavium.com>
---
 arch/mips/Kconfig                    |    1 +
 arch/mips/cavium-octeon/octeon-irq.c |  301 +++++++++++++++++++++++++++-------
 2 files changed, 239 insertions(+), 63 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index ce30e2f..01344ae 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1432,6 +1432,7 @@ config CPU_CAVIUM_OCTEON
 	select WEAK_ORDERING
 	select CPU_SUPPORTS_HIGHMEM
 	select CPU_SUPPORTS_HUGEPAGES
+	select IRQ_DOMAIN
 	help
 	  The Cavium Octeon processor is a highly integrated chip containing
 	  many ethernet hardware widgets for networking tasks. The processor
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index bdcedd3..e9f2f6c 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -3,14 +3,16 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004-2008, 2009, 2010, 2011 Cavium Networks
+ * Copyright (C) 2004-2008, 2009, 2010, 2011, 2012 Cavium Networks
  */
 
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
 #include <linux/bitops.h>
 #include <linux/percpu.h>
 #include <linux/irq.h>
 #include <linux/smp.h>
+#include <linux/of.h>
 
 #include <asm/octeon/octeon.h>
 
@@ -42,20 +44,27 @@ struct octeon_core_chip_data {
 
 static struct octeon_core_chip_data octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES];
 
-static void __init octeon_irq_set_ciu_mapping(int irq, int line, int bit,
+static void __init octeon_irq_set_ciu_mapping(unsigned int irq,
+					      unsigned int line,
+					      unsigned int bit,
+					      struct irq_domain *domain,
 					      struct irq_chip *chip,
 					      irq_flow_handler_t handler)
 {
+	struct irq_data *irqd;
 	union octeon_ciu_chip_data cd;
 
 	irq_set_chip_and_handler(irq, chip, handler);
-
 	cd.l = 0;
 	cd.s.line = line;
 	cd.s.bit = bit;
 
 	irq_set_chip_data(irq, cd.p);
 	octeon_irq_ciu_to_irq[line][bit] = irq;
+
+	irqd = irq_get_irq_data(irq);
+	irqd->hwirq = line << 6 | bit;
+	irqd->domain = domain;
 }
 
 static int octeon_coreid_for_cpu(int cpu)
@@ -855,6 +864,107 @@ static struct irq_chip octeon_irq_chip_ciu_wd = {
 	.irq_mask = octeon_irq_dummy_mask,
 };
 
+static int octeon_irq_gpio_xlat(struct irq_domain *d,
+				struct device_node *node,
+				const u32 *intspec,
+				unsigned int intsize,
+				unsigned long *out_hwirq,
+				unsigned int *out_type)
+{
+	unsigned int irq;
+	unsigned int type;
+	unsigned int ciu = 0, bit = 0;
+	unsigned int pin;
+	unsigned int trigger;
+	bool set_edge_handler = false;
+
+	if (d->of_node != node)
+		return -EINVAL;
+
+	if (intsize < 2)
+		return -EINVAL;
+
+	pin = intspec[0];
+	if (pin >= 16)
+		return -EINVAL;
+
+	trigger = intspec[1];
+
+	switch (trigger) {
+	case 1:
+		type = IRQ_TYPE_EDGE_RISING;
+		set_edge_handler = true;
+		break;
+	case 2:
+		type = IRQ_TYPE_EDGE_FALLING;
+		set_edge_handler = true;
+		break;
+	case 4:
+		type = IRQ_TYPE_LEVEL_HIGH;
+		break;
+	case 8:
+		type = IRQ_TYPE_LEVEL_LOW;
+		break;
+	default:
+		pr_err("Error: (%s) Invalid irq trigger specification: %x\n",
+		       node->name,
+		       trigger);
+		type = IRQ_TYPE_LEVEL_LOW;
+		break;
+	}
+	*out_type = type;
+	*out_hwirq = ((unsigned long)d->host_data) + pin;
+
+	ciu = *out_hwirq >> 6;
+	bit = *out_hwirq & 0x3f;
+
+	irq = octeon_irq_ciu_to_irq[ciu][bit];
+
+	if (set_edge_handler)
+		__irq_set_handler(irq, handle_edge_irq, 0, NULL);
+
+	return 0;
+}
+
+static int octeon_irq_ciu_xlat(struct irq_domain *d,
+			       struct device_node *node,
+			       const u32 *intspec,
+			       unsigned int intsize,
+			       unsigned long *out_hwirq,
+			       unsigned int *out_type)
+{
+	unsigned int ciu, bit;
+
+	ciu = intspec[0];
+	bit = intspec[1];
+
+	if (ciu > 1 || bit > 63)
+		return -EINVAL;
+
+	if (octeon_irq_ciu_to_irq[ciu][bit] == 0)
+		return -EINVAL;
+
+	*out_hwirq = (ciu << 6) | bit;
+	*out_type = 0;
+
+	return 0;
+}
+static int octeon_irq_dummy_map(struct irq_domain *d,
+				unsigned int virq, irq_hw_number_t hw)
+{
+	return 0;
+}
+
+static struct irq_domain_ops octeon_irq_domain_ciu_ops = {
+	.map = octeon_irq_dummy_map,
+	.xlate = octeon_irq_ciu_xlat,
+};
+
+static struct irq_domain_ops octeon_irq_domain_gpio_ops = {
+	.map = octeon_irq_dummy_map,
+	.xlate = octeon_irq_gpio_xlat,
+};
+
 static void octeon_irq_ip2_v1(void)
 {
 	const unsigned long core_id = cvmx_get_core_num();
@@ -982,6 +1092,10 @@ static void __init octeon_irq_init_ciu(void)
 	struct irq_chip *chip_mbox;
 	struct irq_chip *chip_wd;
 	struct irq_chip *chip_gpio;
+	struct device_node *gpio_node;
+	struct device_node *ciu_node;
+	struct irq_domain *gpio_domain;
+	struct irq_domain *ciu_domain;
 
 	octeon_irq_init_ciu_percpu();
 	octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu;
@@ -1011,83 +1125,144 @@ static void __init octeon_irq_init_ciu(void)
 	/* Mips internal */
 	octeon_irq_init_core();
 
+	gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio");
+	ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-ciu");
+	/* gpio domain host_data is the base hwirq number. */
+	gpio_domain = irq_domain_add_linear(gpio_node, 16, &octeon_irq_domain_gpio_ops, (void *)16);
+	ciu_domain = irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL);
+
 	/* CIU_0 */
 	for (i = 0; i < 16; i++)
-		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq);
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0,
+					   ciu_domain, chip, handle_level_irq);
+
 	for (i = 0; i < 16; i++)
-		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16, chip_gpio, handle_level_irq);
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16,
+					   gpio_domain, chip_gpio, handle_level_irq);
 
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32,
+				   ciu_domain, chip_mbox, handle_percpu_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33,
+				   ciu_domain, chip_mbox, handle_percpu_irq);
 
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART0, 0, 34, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART1, 0, 35, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART0, 0, 34,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART1, 0, 35,
+				   ciu_domain, chip, handle_level_irq);
 
 	for (i = 0; i < 4; i++)
-		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq);
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36,
+					   ciu_domain, chip, handle_level_irq);
 	for (i = 0; i < 4; i++)
-		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq);
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40,
+					   ciu_domain, chip, handle_level_irq);
 
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI, 0, 45, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TRACE0, 0, 47, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI, 0, 45,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TRACE0, 0, 47,
+				   ciu_domain, chip, handle_level_irq);
 
 	for (i = 0; i < 2; i++)
-		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GMX_DRP0, 0, i + 48, chip_edge, handle_edge_irq);
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GMX_DRP0, 0, i + 48,
+					   ciu_domain, chip_edge, handle_edge_irq);
 
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD_DRP, 0, 50, chip_edge, handle_edge_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY_ZERO, 0, 51, chip_edge, handle_edge_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD_DRP, 0, 50,
+				   ciu_domain, chip_edge, handle_edge_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY_ZERO, 0, 51,
+				   ciu_domain, chip_edge, handle_edge_irq);
 
 	for (i = 0; i < 4; i++)
-		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip_edge, handle_edge_irq);
-
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PCM, 0, 57, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MPI, 0, 58, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI2, 0, 59, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_POWIQ, 0, 60, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPDPPTHR, 0, 61, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII0, 0, 62, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq);
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52,
+					   ciu_domain, chip_edge, handle_edge_irq);
+
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PCM, 0, 57,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MPI, 0, 58,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI2, 0, 59,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_POWIQ, 0, 60,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPDPPTHR, 0, 61,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII0, 0, 62,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63,
+				   ciu_domain, chip, handle_level_irq);
 
 	/* CIU_1 */
 	for (i = 0; i < 16; i++)
-		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
-
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART2, 1, 16, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII1, 1, 18, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_NAND, 1, 19, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MIO, 1, 20, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IOB, 1, 21, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_FPA, 1, 22, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_POW, 1, 23, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_L2C, 1, 24, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD, 1, 25, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PIP, 1, 26, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PKO, 1, 27, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_ZIP, 1, 28, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TIM, 1, 29, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RAD, 1, 30, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY, 1, 31, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFA, 1, 32, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USBCTL, 1, 33, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SLI, 1, 34, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DPI, 1, 35, chip, handle_level_irq);
-
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGX0, 1, 36, chip, handle_level_irq);
-
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGL, 1, 46, chip, handle_level_irq);
-
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PTP, 1, 47, chip_edge, handle_edge_irq);
-
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56, chip, handle_level_irq);
-	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63, chip, handle_level_irq);
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0,
+					   ciu_domain, chip_wd, handle_level_irq);
+
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART2, 1, 16,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII1, 1, 18,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_NAND, 1, 19,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MIO, 1, 20,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IOB, 1, 21,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_FPA, 1, 22,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_POW, 1, 23,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_L2C, 1, 24,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD, 1, 25,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PIP, 1, 26,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PKO, 1, 27,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_ZIP, 1, 28,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TIM, 1, 29,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RAD, 1, 30,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY, 1, 31,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFA, 1, 32,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USBCTL, 1, 33,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SLI, 1, 34,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DPI, 1, 35,
+				   ciu_domain, chip, handle_level_irq);
+
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGX0, 1, 36,
+				   ciu_domain, chip, handle_level_irq);
+
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGL, 1, 46,
+				   ciu_domain, chip, handle_level_irq);
+
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PTP, 1, 47,
+				   ciu_domain, chip_edge, handle_edge_irq);
+
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56,
+				   ciu_domain, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63,
+				   ciu_domain, chip, handle_level_irq);
 
 	/* Enable the CIU lines */
 	set_c0_status(STATUSF_IP3 | STATUSF_IP2);
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH v6 5/5] MIPS: Octeon: Initialize and fixup device tree.
  2012-03-01  0:56 [PATCH v6 0/5] MIPS: Octeon: Use Device Tree David Daney
                   ` (3 preceding siblings ...)
  2012-03-01  0:57 ` [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts David Daney
@ 2012-03-01  0:57 ` David Daney
  4 siblings, 0 replies; 20+ messages in thread
From: David Daney @ 2012-03-01  0:57 UTC (permalink / raw)
  To: linux-mips, ralf, devicetree-discuss, Grant Likely, Rob Herring
  Cc: linux-kernel, David Daney

From: David Daney <david.daney@cavium.com>

Signed-off-by: David Daney <david.daney@cavium.com>
---
 arch/mips/Kconfig                         |    2 +
 arch/mips/cavium-octeon/Makefile          |    3 +
 arch/mips/cavium-octeon/octeon-platform.c |  523 ++++++++++++++++++++++++++++-
 arch/mips/cavium-octeon/setup.c           |   45 +++
 4 files changed, 572 insertions(+), 1 deletions(-)

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 01344ae..f694bdd 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1433,6 +1433,8 @@ config CPU_CAVIUM_OCTEON
 	select CPU_SUPPORTS_HIGHMEM
 	select CPU_SUPPORTS_HUGEPAGES
 	select IRQ_DOMAIN
+	select USE_OF
+	select LIBFDT
 	help
 	  The Cavium Octeon processor is a highly integrated chip containing
 	  many ethernet hardware widgets for networking tasks. The processor
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
index 1e37522..bc96e29 100644
--- a/arch/mips/cavium-octeon/Makefile
+++ b/arch/mips/cavium-octeon/Makefile
@@ -9,6 +9,9 @@
 # Copyright (C) 2005-2009 Cavium Networks
 #
 
+CFLAGS_octeon-platform.o = -I$(src)/../../../scripts/dtc/libfdt
+CFLAGS_setup.o = -I$(src)/../../../scripts/dtc/libfdt
+
 obj-y := cpu.o setup.o serial.o octeon-platform.o octeon-irq.o csrc-octeon.o
 obj-y += dma-octeon.o flash_setup.o
 obj-y += octeon-memcpy.o
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index cd61d72..2754bc2 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004-2010 Cavium Networks
+ * Copyright (C) 2004-2011 Cavium Networks
  * Copyright (C) 2008 Wind River Systems
  */
 
@@ -13,10 +13,16 @@
 #include <linux/usb.h>
 #include <linux/dma-mapping.h>
 #include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_fdt.h>
+#include <linux/libfdt.h>
 
 #include <asm/octeon/octeon.h>
 #include <asm/octeon/cvmx-rnm-defs.h>
+#include <asm/octeon/cvmx-helper.h>
+#include <asm/octeon/cvmx-helper-board.h>
 
 static struct octeon_cf_data octeon_cf_data;
 
@@ -440,6 +446,521 @@ device_initcall(octeon_ohci_device_init);
 
 #endif /* CONFIG_USB */
 
+static struct of_device_id __initdata octeon_ids[] = {
+	{ .compatible = "simple-bus", },
+	{ .compatible = "cavium,octeon-6335-uctl", },
+	{ .compatible = "cavium,octeon-3860-bootbus", },
+	{ .compatible = "cavium,mdio-mux", },
+	{ .compatible = "gpio-leds", },
+	{},
+};
+
+static bool __init octeon_has_88e1145(void)
+{
+	return !OCTEON_IS_MODEL(OCTEON_CN52XX) &&
+	       !OCTEON_IS_MODEL(OCTEON_CN6XXX) &&
+	       !OCTEON_IS_MODEL(OCTEON_CN56XX);
+}
+
+static void __init octeon_fdt_set_phy(int eth, int phy_addr)
+{
+	const __be32 *phy_handle;
+	const __be32 *alt_phy_handle;
+	const __be32 *reg;
+	u32 phandle;
+	int phy;
+	int alt_phy;
+	const char *p;
+	int current_len;
+	char new_name[20];
+
+	phy_handle = fdt_getprop(initial_boot_params, eth, "phy-handle", NULL);
+	if (!phy_handle)
+		return;
+
+	phandle = be32_to_cpup(phy_handle);
+	phy = fdt_node_offset_by_phandle(initial_boot_params, phandle);
+
+	alt_phy_handle = fdt_getprop(initial_boot_params, eth, "cavium,alt-phy-handle", NULL);
+	if (alt_phy_handle) {
+		u32 alt_phandle = be32_to_cpup(alt_phy_handle);
+		alt_phy = fdt_node_offset_by_phandle(initial_boot_params, alt_phandle);
+	} else {
+		alt_phy = -1;
+	}
+
+	if (phy_addr < 0 || phy < 0) {
+		/* Delete the PHY things */
+		fdt_nop_property(initial_boot_params, eth, "phy-handle");
+		/* This one may fail */
+		fdt_nop_property(initial_boot_params, eth, "cavium,alt-phy-handle");
+		if (phy >= 0)
+			fdt_nop_node(initial_boot_params, phy);
+		if (alt_phy >= 0)
+			fdt_nop_node(initial_boot_params, alt_phy);
+		return;
+	}
+
+	if (phy_addr >= 256 && alt_phy > 0) {
+		const struct fdt_property *phy_prop;
+		struct fdt_property *alt_prop;
+		u32 phy_handle_name;
+
+		/* Use the alt phy node instead.*/
+		phy_prop = fdt_get_property(initial_boot_params, eth, "phy-handle", NULL);
+		phy_handle_name = phy_prop->nameoff;
+		fdt_nop_node(initial_boot_params, phy);
+		fdt_nop_property(initial_boot_params, eth, "phy-handle");
+		alt_prop = fdt_get_property_w(initial_boot_params, eth, "cavium,alt-phy-handle", NULL);
+		alt_prop->nameoff = phy_handle_name;
+		phy = alt_phy;
+	}
+
+	phy_addr &= 0xff;
+
+	if (octeon_has_88e1145()) {
+		fdt_nop_property(initial_boot_params, phy, "marvell,reg-init");
+		memset(new_name, 0, sizeof(new_name));
+		strcpy(new_name, "marvell,88e1145");
+		p = fdt_getprop(initial_boot_params, phy, "compatible",
+				&current_len);
+		if (p && current_len >= strlen(new_name))
+			fdt_setprop_inplace(initial_boot_params, phy,
+					"compatible", new_name, current_len);
+	}
+
+	reg = fdt_getprop(initial_boot_params, phy, "reg", NULL);
+	if (phy_addr == be32_to_cpup(reg))
+		return;
+
+	fdt_setprop_inplace_cell(initial_boot_params, phy, "reg", phy_addr);
+
+	snprintf(new_name, sizeof(new_name), "ethernet-phy@%x", phy_addr);
+
+	p = fdt_get_name(initial_boot_params, phy, &current_len);
+	if (p && current_len == strlen(new_name))
+		fdt_set_name(initial_boot_params, phy, new_name);
+	else
+		pr_err("Error: could not rename ethernet phy: <%s>", p);
+}
+
+static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac)
+{
+	u8 new_mac[6];
+	u64 mac = *pmac;
+	int r;
+
+	new_mac[0] = (mac >> 40) & 0xff;
+	new_mac[1] = (mac >> 32) & 0xff;
+	new_mac[2] = (mac >> 24) & 0xff;
+	new_mac[3] = (mac >> 16) & 0xff;
+	new_mac[4] = (mac >> 8) & 0xff;
+	new_mac[5] = mac & 0xff;
+
+	r = fdt_setprop_inplace(initial_boot_params, n, "local-mac-address",
+				new_mac, sizeof(new_mac));
+
+	if (r) {
+		pr_err("Setting \"local-mac-address\" failed %d", r);
+		return;
+	}
+	*pmac = mac + 1;
+}
+
+static void __init octeon_fdt_rm_ethernet(int node)
+{
+	const __be32 *phy_handle;
+
+	phy_handle = fdt_getprop(initial_boot_params, node, "phy-handle", NULL);
+	if (phy_handle) {
+		u32 ph = be32_to_cpup(phy_handle);
+		int p = fdt_node_offset_by_phandle(initial_boot_params, ph);
+		if (p >= 0)
+			fdt_nop_node(initial_boot_params, p);
+	}
+	fdt_nop_node(initial_boot_params, node);
+}
+
+static void __init octeon_fdt_pip_port(int iface, int i, int p, int max, u64 *pmac)
+{
+	char name_buffer[20];
+	int eth;
+	int phy_addr;
+	int ipd_port;
+
+	snprintf(name_buffer, sizeof(name_buffer), "ethernet@%x", p);
+	eth = fdt_subnode_offset(initial_boot_params, iface, name_buffer);
+	if (eth < 0)
+		return;
+	if (p > max) {
+		pr_debug("Deleting port %x:%x\n", i, p);
+		octeon_fdt_rm_ethernet(eth);
+		return;
+	}
+	if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+		ipd_port = (0x100 * i) + (0x10 * p) + 0x800;
+	else
+		ipd_port = 16 * i + p;
+
+	phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
+	octeon_fdt_set_phy(eth, phy_addr);
+	octeon_fdt_set_mac_addr(eth, pmac);
+}
+
+static void __init octeon_fdt_pip_iface(int pip, int idx, u64 *pmac)
+{
+	char name_buffer[20];
+	int iface;
+	int p;
+	int count;
+
+	count = cvmx_helper_interface_enumerate(idx);
+
+	snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx);
+	iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer);
+	if (iface < 0)
+		return;
+
+	for (p = 0; p < 16; p++)
+		octeon_fdt_pip_port(iface, idx, p, count - 1, pmac);
+}
+
+int __init octeon_prune_device_tree(void)
+{
+	int i, max_port, uart_mask;
+	const char *pip_path;
+	const char *alias_prop;
+	char name_buffer[20];
+	int aliases;
+	u64 mac_addr_base;
+
+	if (fdt_check_header(initial_boot_params))
+		panic("Corrupt Device Tree.");
+
+	aliases = fdt_path_offset(initial_boot_params, "/aliases");
+	if (aliases < 0) {
+		pr_err("Error: No /aliases node in device tree.");
+		return -EINVAL;
+	}
+
+
+	mac_addr_base =
+		((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 |
+		((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 |
+		((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 |
+		((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 |
+		((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 |
+		(octeon_bootinfo->mac_addr_base[5] & 0xffull);
+
+	if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
+		max_port = 2;
+	else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN68XX))
+		max_port = 1;
+	else
+		max_port = 0;
+
+	if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E)
+		max_port = 0;
+
+	for (i = 0; i < 2; i++) {
+		int mgmt;
+		snprintf(name_buffer, sizeof(name_buffer),
+			 "mix%d", i);
+		alias_prop = fdt_getprop(initial_boot_params, aliases,
+					name_buffer, NULL);
+		if (alias_prop) {
+			mgmt = fdt_path_offset(initial_boot_params, alias_prop);
+			if (mgmt < 0)
+				continue;
+			if (i >= max_port) {
+				pr_debug("Deleting mix%d\n", i);
+				octeon_fdt_rm_ethernet(mgmt);
+				fdt_nop_property(initial_boot_params, aliases,
+						 name_buffer);
+			} else {
+				int phy_addr = cvmx_helper_board_get_mii_address(CVMX_HELPER_BOARD_MGMT_IPD_PORT + i);
+				octeon_fdt_set_phy(mgmt, phy_addr);
+				octeon_fdt_set_mac_addr(mgmt, &mac_addr_base);
+			}
+		}
+	}
+
+	pip_path = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
+	if (pip_path) {
+		int pip = fdt_path_offset(initial_boot_params, pip_path);
+		if (pip  >= 0)
+			for (i = 0; i <= 4; i++)
+				octeon_fdt_pip_iface(pip, i, &mac_addr_base);
+	}
+
+	/* I2C */
+	if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
+	    OCTEON_IS_MODEL(OCTEON_CN63XX) ||
+	    OCTEON_IS_MODEL(OCTEON_CN68XX) ||
+	    OCTEON_IS_MODEL(OCTEON_CN56XX))
+		max_port = 2;
+	else
+		max_port = 1;
+
+	for (i = 0; i < 2; i++) {
+		int i2c;
+		snprintf(name_buffer, sizeof(name_buffer),
+			 "twsi%d", i);
+		alias_prop = fdt_getprop(initial_boot_params, aliases,
+					name_buffer, NULL);
+
+		if (alias_prop) {
+			i2c = fdt_path_offset(initial_boot_params, alias_prop);
+			if (i2c < 0)
+				continue;
+			if (i >= max_port) {
+				pr_debug("Deleting twsi%d\n", i);
+				fdt_nop_node(initial_boot_params, i2c);
+				fdt_nop_property(initial_boot_params, aliases,
+						 name_buffer);
+			}
+		}
+	}
+
+	/* SMI/MDIO */
+	if (OCTEON_IS_MODEL(OCTEON_CN68XX))
+		max_port = 4;
+	else if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
+		 OCTEON_IS_MODEL(OCTEON_CN63XX) ||
+		 OCTEON_IS_MODEL(OCTEON_CN56XX))
+		max_port = 2;
+	else
+		max_port = 1;
+
+	for (i = 0; i < 2; i++) {
+		int i2c;
+		snprintf(name_buffer, sizeof(name_buffer),
+			 "smi%d", i);
+		alias_prop = fdt_getprop(initial_boot_params, aliases,
+					name_buffer, NULL);
+
+		if (alias_prop) {
+			i2c = fdt_path_offset(initial_boot_params, alias_prop);
+			if (i2c < 0)
+				continue;
+			if (i >= max_port) {
+				pr_debug("Deleting smi%d\n", i);
+				fdt_nop_node(initial_boot_params, i2c);
+				fdt_nop_property(initial_boot_params, aliases,
+						 name_buffer);
+			}
+		}
+	}
+
+	/* Serial */
+	uart_mask = 3;
+
+	/* Right now CN52XX is the only chip with a third uart */
+	if (OCTEON_IS_MODEL(OCTEON_CN52XX))
+		uart_mask |= 4; /* uart2 */
+
+	for (i = 0; i < 3; i++) {
+		int uart;
+		snprintf(name_buffer, sizeof(name_buffer),
+			 "uart%d", i);
+		alias_prop = fdt_getprop(initial_boot_params, aliases,
+					name_buffer, NULL);
+
+		if (alias_prop) {
+			uart = fdt_path_offset(initial_boot_params, alias_prop);
+			if (uart_mask & (1 << i))
+				continue;
+			pr_debug("Deleting uart%d\n", i);
+			fdt_nop_node(initial_boot_params, uart);
+			fdt_nop_property(initial_boot_params, aliases,
+					 name_buffer);
+		}
+	}
+
+	/* Compact Flash */
+	alias_prop = fdt_getprop(initial_boot_params, aliases,
+				 "cf0", NULL);
+	if (alias_prop) {
+		union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
+		unsigned long base_ptr, region_base, region_size;
+		unsigned long region1_base = 0;
+		unsigned long region1_size = 0;
+		int cs, bootbus;
+		bool is_16bit = false;
+		bool is_true_ide = false;
+		__be32 new_reg[6];
+		__be32 *ranges;
+		int len;
+
+		int cf = fdt_path_offset(initial_boot_params, alias_prop);
+		base_ptr = 0;
+		if (octeon_bootinfo->major_version == 1
+			&& octeon_bootinfo->minor_version >= 1) {
+			if (octeon_bootinfo->compact_flash_common_base_addr)
+				base_ptr = octeon_bootinfo->compact_flash_common_base_addr;
+		} else {
+			base_ptr = 0x1d000800;
+		}
+
+		if (!base_ptr)
+			goto no_cf;
+
+		/* Find CS0 region. */
+		for (cs = 0; cs < 8; cs++) {
+			mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
+			region_base = mio_boot_reg_cfg.s.base << 16;
+			region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
+			if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
+				&& base_ptr < region_base + region_size) {
+				is_16bit = mio_boot_reg_cfg.s.width;
+				break;
+			}
+		}
+		if (cs >= 7) {
+			/* cs and cs + 1 are CS0 and CS1, both must be less than 8. */
+			goto no_cf;
+		}
+
+		if (!(base_ptr & 0xfffful)) {
+			/*
+			 * Boot loader signals availability of DMA (true_ide
+			 * mode) by setting low order bits of base_ptr to
+			 * zero.
+			 */
+
+			/* Asume that CS1 immediately follows. */
+			mio_boot_reg_cfg.u64 =
+				cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs + 1));
+			region1_base = mio_boot_reg_cfg.s.base << 16;
+			region1_size = (mio_boot_reg_cfg.s.size + 1) << 16;
+			if (!mio_boot_reg_cfg.s.en)
+				goto no_cf;
+			is_true_ide = true;
+
+		} else {
+			fdt_nop_property(initial_boot_params, cf, "cavium,true-ide");
+			fdt_nop_property(initial_boot_params, cf, "cavium,dma-engine-handle");
+			if (!is_16bit) {
+				__be32 width = cpu_to_be32(8);
+				fdt_setprop_inplace(initial_boot_params, cf,
+						"cavium,bus-width", &width, sizeof(width));
+			}
+		}
+		new_reg[0] = cpu_to_be32(cs);
+		new_reg[1] = cpu_to_be32(0);
+		new_reg[2] = cpu_to_be32(0x10000);
+		new_reg[3] = cpu_to_be32(cs + 1);
+		new_reg[4] = cpu_to_be32(0);
+		new_reg[5] = cpu_to_be32(0x10000);
+		fdt_setprop_inplace(initial_boot_params, cf,
+				    "reg",  new_reg, sizeof(new_reg));
+
+		bootbus = fdt_parent_offset(initial_boot_params, cf);
+		if (bootbus < 0)
+			goto no_cf;
+		ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len);
+		if (!ranges || len < (5 * 8 * sizeof(__be32)))
+			goto no_cf;
+
+		ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32);
+		ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff);
+		ranges[(cs * 5) + 4] = cpu_to_be32(region_size);
+		if (is_true_ide) {
+			cs++;
+			ranges[(cs * 5) + 2] = cpu_to_be32(region1_base >> 32);
+			ranges[(cs * 5) + 3] = cpu_to_be32(region1_base & 0xffffffff);
+			ranges[(cs * 5) + 4] = cpu_to_be32(region1_size);
+		}
+		goto end_cf;
+no_cf:
+		fdt_nop_node(initial_boot_params, cf);
+
+end_cf:
+		;
+	}
+
+	/* 8 char LED */
+	alias_prop = fdt_getprop(initial_boot_params, aliases,
+				 "led0", NULL);
+	if (alias_prop) {
+		union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
+		unsigned long base_ptr, region_base, region_size;
+		int cs, bootbus;
+		__be32 new_reg[6];
+		__be32 *ranges;
+		int len;
+		int led = fdt_path_offset(initial_boot_params, alias_prop);
+
+		base_ptr = octeon_bootinfo->led_display_base_addr;
+		if (base_ptr == 0)
+			goto no_led;
+		/* Find CS0 region. */
+		for (cs = 0; cs < 8; cs++) {
+			mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
+			region_base = mio_boot_reg_cfg.s.base << 16;
+			region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
+			if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
+				&& base_ptr < region_base + region_size)
+				break;
+		}
+
+		if (cs > 7)
+			goto no_led;
+
+		new_reg[0] = cpu_to_be32(cs);
+		new_reg[1] = cpu_to_be32(0x20);
+		new_reg[2] = cpu_to_be32(0x20);
+		new_reg[3] = cpu_to_be32(cs);
+		new_reg[4] = cpu_to_be32(0);
+		new_reg[5] = cpu_to_be32(0x20);
+		fdt_setprop_inplace(initial_boot_params, led,
+				    "reg",  new_reg, sizeof(new_reg));
+
+		bootbus = fdt_parent_offset(initial_boot_params, led);
+		if (bootbus < 0)
+			goto no_led;
+		ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len);
+		if (!ranges || len < (5 * 8 * sizeof(__be32)))
+			goto no_led;
+
+		ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32);
+		ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff);
+		ranges[(cs * 5) + 4] = cpu_to_be32(region_size);
+		goto end_led;
+
+no_led:
+		fdt_nop_node(initial_boot_params, led);
+end_led:
+		;
+	}
+
+	/* OHCI/UHCI USB */
+	alias_prop = fdt_getprop(initial_boot_params, aliases,
+				 "uctl", NULL);
+	if (alias_prop) {
+		int uctl = fdt_path_offset(initial_boot_params, alias_prop);
+
+		if (uctl >= 0 && (!OCTEON_IS_MODEL(OCTEON_CN6XXX) ||
+				  octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC2E)) {
+			pr_debug("Deleting uctl\n");
+			fdt_nop_node(initial_boot_params, uctl);
+			fdt_nop_property(initial_boot_params, aliases, "uctl");
+		} else if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E ||
+			   octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC4E) {
+			/* Missing "refclk-type" defaults to crystal. */
+			fdt_nop_property(initial_boot_params, uctl, "refclk-type");
+		}
+	}
+
+	return 0;
+}
+
+static int __init octeon_publish_devices(void)
+{
+	return of_platform_bus_probe(NULL, octeon_ids, NULL);
+}
+device_initcall(octeon_publish_devices);
+
 MODULE_AUTHOR("David Daney <ddaney@caviumnetworks.com>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Platform driver for Octeon SOC");
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index 260b273..03e8be0 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -20,6 +20,8 @@
 #include <linux/platform_device.h>
 #include <linux/serial_core.h>
 #include <linux/serial_8250.h>
+#include <linux/of_fdt.h>
+#include <linux/libfdt.h>
 
 #include <asm/processor.h>
 #include <asm/reboot.h>
@@ -775,3 +777,46 @@ void prom_free_prom_memory(void)
 	}
 #endif
 }
+
+int octeon_prune_device_tree(void);
+
+extern const char __dtb_octeon_3xxx_begin;
+extern const char __dtb_octeon_3xxx_end;
+extern const char __dtb_octeon_68xx_begin;
+extern const char __dtb_octeon_68xx_end;
+void __init device_tree_init(void)
+{
+	int dt_size;
+	struct boot_param_header *fdt;
+	bool do_prune;
+
+	if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) {
+		fdt = phys_to_virt(octeon_bootinfo->fdt_addr);
+		if (fdt_check_header(fdt))
+			panic("Corrupt Device Tree passed to kernel.");
+		dt_size = be32_to_cpu(fdt->totalsize);
+		do_prune = false;
+	} else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
+		fdt = (struct boot_param_header *)&__dtb_octeon_68xx_begin;
+		dt_size = &__dtb_octeon_68xx_end - &__dtb_octeon_68xx_begin;
+		do_prune = true;
+	} else {
+		fdt = (struct boot_param_header *)&__dtb_octeon_3xxx_begin;
+		dt_size = &__dtb_octeon_3xxx_end - &__dtb_octeon_3xxx_begin;
+		do_prune = true;
+	}
+
+	/* Copy the default tree from init memory. */
+	initial_boot_params = early_init_dt_alloc_memory_arch(dt_size, 8);
+	if (initial_boot_params == NULL)
+		panic("Could not allocate initial_boot_params\n");
+	memcpy(initial_boot_params, fdt, dt_size);
+
+	if (do_prune) {
+		octeon_prune_device_tree();
+		pr_info("Using internal Device Tree.\n");
+	} else {
+		pr_info("Using passed Device Tree.\n");
+	}
+	unflatten_device_tree();
+}
-- 
1.7.2.3


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-01  0:57 ` [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts David Daney
@ 2012-03-02 14:22   ` Rob Herring
  2012-03-02 18:03     ` David Daney
  2012-03-02 19:02   ` Grant Likely
  1 sibling, 1 reply; 20+ messages in thread
From: Rob Herring @ 2012-03-02 14:22 UTC (permalink / raw)
  To: David Daney
  Cc: linux-mips, ralf, devicetree-discuss, Grant Likely, Rob Herring,
	linux-kernel, David Daney

David,

On 02/29/2012 06:57 PM, David Daney wrote:
> From: David Daney <david.daney@cavium.com>
> 
> Select IRQ_DOMAIN so the core irq_domain code and supply
> irq_create_of_mapping().
> 
> Signed-off-by: David Daney <david.daney@cavium.com>
> ---
>  arch/mips/Kconfig                    |    1 +
>  arch/mips/cavium-octeon/octeon-irq.c |  301 +++++++++++++++++++++++++++-------
>  2 files changed, 239 insertions(+), 63 deletions(-)
> 
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index ce30e2f..01344ae 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -1432,6 +1432,7 @@ config CPU_CAVIUM_OCTEON
>  	select WEAK_ORDERING
>  	select CPU_SUPPORTS_HIGHMEM
>  	select CPU_SUPPORTS_HUGEPAGES
> +	select IRQ_DOMAIN

IIRC, Grant has a patch cued up that enables IRQ_DOMAIN for all of MIPS.

>  	help
>  	  The Cavium Octeon processor is a highly integrated chip containing
>  	  many ethernet hardware widgets for networking tasks. The processor
> diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
> index bdcedd3..e9f2f6c 100644
> --- a/arch/mips/cavium-octeon/octeon-irq.c
> +++ b/arch/mips/cavium-octeon/octeon-irq.c
> @@ -3,14 +3,16 @@
>   * License.  See the file "COPYING" in the main directory of this archive
>   * for more details.
>   *
> - * Copyright (C) 2004-2008, 2009, 2010, 2011 Cavium Networks
> + * Copyright (C) 2004-2008, 2009, 2010, 2011, 2012 Cavium Networks
>   */.
>  
>  #include <linux/interrupt.h>
> +#include <linux/irqdomain.h>
>  #include <linux/bitops.h>
>  #include <linux/percpu.h>
>  #include <linux/irq.h>
>  #include <linux/smp.h>
> +#include <linux/of.h>
>  
>  #include <asm/octeon/octeon.h>
>  
> @@ -42,20 +44,27 @@ struct octeon_core_chip_data {
>  
>  static struct octeon_core_chip_data octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES];
>  
> -static void __init octeon_irq_set_ciu_mapping(int irq, int line, int bit,
> +static void __init octeon_irq_set_ciu_mapping(unsigned int irq,
> +					      unsigned int line,
> +					      unsigned int bit,
> +					      struct irq_domain *domain,
>  					      struct irq_chip *chip,
>  					      irq_flow_handler_t handler)
>  {
> +	struct irq_data *irqd;
>  	union octeon_ciu_chip_data cd;
>  
>  	irq_set_chip_and_handler(irq, chip, handler);
> -
>  	cd.l = 0;
>  	cd.s.line = line;
>  	cd.s.bit = bit;
>  
>  	irq_set_chip_data(irq, cd.p);
>  	octeon_irq_ciu_to_irq[line][bit] = irq;
> +
> +	irqd = irq_get_irq_data(irq);
> +	irqd->hwirq = line << 6 | bit;
> +	irqd->domain = domain;

I think the domain code will set these.

>  }
>  
>  static int octeon_coreid_for_cpu(int cpu)
> @@ -855,6 +864,107 @@ static struct irq_chip octeon_irq_chip_ciu_wd = {
>  	.irq_mask = octeon_irq_dummy_mask,
>  };
>  
> +static int octeon_irq_gpio_xlat(struct irq_domain *d,
> +				struct device_node *node,
> +				const u32 *intspec,
> +				unsigned int intsize,
> +				unsigned long *out_hwirq,
> +				unsigned int *out_type)
> +{
> +	unsigned int irq;
> +	unsigned int type;
> +	unsigned int ciu = 0, bit = 0;
> +	unsigned int pin;
> +	unsigned int trigger;
> +	bool set_edge_handler = false;
> +
> +	if (d->of_node != node)
> +		return -EINVAL;
> +
> +	if (intsize < 2)
> +		return -EINVAL;
> +
> +	pin = intspec[0];
> +	if (pin >= 16)
> +		return -EINVAL;
> +
> +	trigger = intspec[1];
> +
> +	switch (trigger) {
> +	case 1:
> +		type = IRQ_TYPE_EDGE_RISING;
> +		set_edge_handler = true;
> +		break;
> +	case 2:
> +		type = IRQ_TYPE_EDGE_FALLING;
> +		set_edge_handler = true;
> +		break;
> +	case 4:
> +		type = IRQ_TYPE_LEVEL_HIGH;
> +		break;
> +	case 8:
> +		type = IRQ_TYPE_LEVEL_LOW;
> +		break;
> +	default:
> +		pr_err("Error: (%s) Invalid irq trigger specification: %x\n",
> +		       node->name,
> +		       trigger);
> +		type = IRQ_TYPE_LEVEL_LOW;
> +		break;
> +	}
> +	*out_type = type;
> +	*out_hwirq = ((unsigned long)d->host_data) + pin;
> +
> +	ciu = *out_hwirq >> 6;
> +	bit = *out_hwirq & 0x3f;
> +
> +	irq = octeon_irq_ciu_to_irq[ciu][bit];
> +
> +	if (set_edge_handler)
> +		__irq_set_handler(irq, handle_edge_irq, 0, NULL);
> +
> +	return 0;
> +}
> +
> +static int octeon_irq_ciu_xlat(struct irq_domain *d,
> +			       struct device_node *node,
> +			       const u32 *intspec,
> +			       unsigned int intsize,
> +			       unsigned long *out_hwirq,
> +			       unsigned int *out_type)
> +{
> +	unsigned int ciu, bit;
> +
> +	ciu = intspec[0];
> +	bit = intspec[1];
> +
> +	if (ciu > 1 || bit > 63)
> +		return -EINVAL;
> +
> +	if (octeon_irq_ciu_to_irq[ciu][bit] == 0)
> +		return -EINVAL;
> +
> +	*out_hwirq = (ciu << 6) | bit;
> +	*out_type = 0;
> +
> +	return 0;
> +}
> +static int octeon_irq_dummy_map(struct irq_domain *d,
> +				unsigned int virq, irq_hw_number_t hw)
> +{
> +	return 0;
> +}
> +
> +static struct irq_domain_ops octeon_irq_domain_ciu_ops = {
> +	.map = octeon_irq_dummy_map,
> +	.xlate = octeon_irq_ciu_xlat,
> +};
> +
> +static struct irq_domain_ops octeon_irq_domain_gpio_ops = {
> +	.map = octeon_irq_dummy_map,
> +	.xlate = octeon_irq_gpio_xlat,
> +};
> +
>  static void octeon_irq_ip2_v1(void)
>  {
>  	const unsigned long core_id = cvmx_get_core_num();
> @@ -982,6 +1092,10 @@ static void __init octeon_irq_init_ciu(void)
>  	struct irq_chip *chip_mbox;
>  	struct irq_chip *chip_wd;
>  	struct irq_chip *chip_gpio;
> +	struct device_node *gpio_node;
> +	struct device_node *ciu_node;
> +	struct irq_domain *gpio_domain;
> +	struct irq_domain *ciu_domain;
>  
>  	octeon_irq_init_ciu_percpu();
>  	octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu;
> @@ -1011,83 +1125,144 @@ static void __init octeon_irq_init_ciu(void)
>  	/* Mips internal */
>  	octeon_irq_init_core();
>  
> +	gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio");
> +	ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-ciu");
> +	/* gpio domain host_data is the base hwirq number. */
> +	gpio_domain = irq_domain_add_linear(gpio_node, 16, &octeon_irq_domain_gpio_ops, (void *)16);

It would be better to define a struct here rather than casting a data
value to a ptr.

> +	ciu_domain = irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL);
> +
>  	/* CIU_0 */
>  	for (i = 0; i < 16; i++)
> -		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq);
> +		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0,
> +					   ciu_domain, chip, handle_level_irq);
> +
>  	for (i = 0; i < 16; i++)
> -		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16, chip_gpio, handle_level_irq);
> +		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16,
> +					   gpio_domain, chip_gpio, handle_level_irq);
>  
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32,
> +				   ciu_domain, chip_mbox, handle_percpu_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33,
> +				   ciu_domain, chip_mbox, handle_percpu_irq);
>  
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART0, 0, 34, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART1, 0, 35, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART0, 0, 34,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART1, 0, 35,
> +				   ciu_domain, chip, handle_level_irq);
>  
>  	for (i = 0; i < 4; i++)
> -		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq);
> +		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36,
> +					   ciu_domain, chip, handle_level_irq);
>  	for (i = 0; i < 4; i++)
> -		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq);
> +		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40,
> +					   ciu_domain, chip, handle_level_irq);
>  
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI, 0, 45, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TRACE0, 0, 47, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI, 0, 45,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TRACE0, 0, 47,
> +				   ciu_domain, chip, handle_level_irq);
>  
>  	for (i = 0; i < 2; i++)
> -		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GMX_DRP0, 0, i + 48, chip_edge, handle_edge_irq);
> +		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GMX_DRP0, 0, i + 48,
> +					   ciu_domain, chip_edge, handle_edge_irq);
>  
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD_DRP, 0, 50, chip_edge, handle_edge_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY_ZERO, 0, 51, chip_edge, handle_edge_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD_DRP, 0, 50,
> +				   ciu_domain, chip_edge, handle_edge_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY_ZERO, 0, 51,
> +				   ciu_domain, chip_edge, handle_edge_irq);
>  
>  	for (i = 0; i < 4; i++)
> -		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip_edge, handle_edge_irq);
> -
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PCM, 0, 57, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MPI, 0, 58, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI2, 0, 59, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_POWIQ, 0, 60, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPDPPTHR, 0, 61, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII0, 0, 62, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq);
> +		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52,
> +					   ciu_domain, chip_edge, handle_edge_irq);
> +
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PCM, 0, 57,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MPI, 0, 58,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI2, 0, 59,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_POWIQ, 0, 60,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPDPPTHR, 0, 61,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII0, 0, 62,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63,
> +				   ciu_domain, chip, handle_level_irq);
>  
>  	/* CIU_1 */
>  	for (i = 0; i < 16; i++)
> -		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
> -
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART2, 1, 16, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII1, 1, 18, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_NAND, 1, 19, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MIO, 1, 20, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IOB, 1, 21, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_FPA, 1, 22, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_POW, 1, 23, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_L2C, 1, 24, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD, 1, 25, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PIP, 1, 26, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PKO, 1, 27, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_ZIP, 1, 28, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TIM, 1, 29, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RAD, 1, 30, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY, 1, 31, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFA, 1, 32, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USBCTL, 1, 33, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SLI, 1, 34, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DPI, 1, 35, chip, handle_level_irq);
> -
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGX0, 1, 36, chip, handle_level_irq);
> -
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGL, 1, 46, chip, handle_level_irq);
> -
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PTP, 1, 47, chip_edge, handle_edge_irq);
> -
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63, chip, handle_level_irq);
> +		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0,
> +					   ciu_domain, chip_wd, handle_level_irq);
> +
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART2, 1, 16,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII1, 1, 18,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_NAND, 1, 19,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MIO, 1, 20,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IOB, 1, 21,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_FPA, 1, 22,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_POW, 1, 23,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_L2C, 1, 24,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD, 1, 25,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PIP, 1, 26,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PKO, 1, 27,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_ZIP, 1, 28,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TIM, 1, 29,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RAD, 1, 30,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY, 1, 31,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFA, 1, 32,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USBCTL, 1, 33,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SLI, 1, 34,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DPI, 1, 35,
> +				   ciu_domain, chip, handle_level_irq);
> +
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGX0, 1, 36,
> +				   ciu_domain, chip, handle_level_irq);
> +
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGL, 1, 46,
> +				   ciu_domain, chip, handle_level_irq);
> +
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PTP, 1, 47,
> +				   ciu_domain, chip_edge, handle_edge_irq);
> +
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63,
> +				   ciu_domain, chip, handle_level_irq);
>  

Can all these calls be moved into the .map function somehow?

edge vs. level should be driven by dts.

Rob

>  	/* Enable the CIU lines */
>  	set_c0_status(STATUSF_IP3 | STATUSF_IP2);


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-02 14:22   ` Rob Herring
@ 2012-03-02 18:03     ` David Daney
  2012-03-02 19:07       ` Grant Likely
  2012-03-03 19:38       ` Rob Herring
  0 siblings, 2 replies; 20+ messages in thread
From: David Daney @ 2012-03-02 18:03 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Daney, linux-mips, ralf, devicetree-discuss, Grant Likely,
	Rob Herring, linux-kernel

On 03/02/2012 06:22 AM, Rob Herring wrote:
[...]
>> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
>> index ce30e2f..01344ae 100644
>> --- a/arch/mips/Kconfig
>> +++ b/arch/mips/Kconfig
>> @@ -1432,6 +1432,7 @@ config CPU_CAVIUM_OCTEON
>>   	select WEAK_ORDERING
>>   	select CPU_SUPPORTS_HIGHMEM
>>   	select CPU_SUPPORTS_HUGEPAGES
>> +	select IRQ_DOMAIN
>
> IIRC, Grant has a patch cued up that enables IRQ_DOMAIN for all of MIPS.
>

Indeed, I now see it in linux-next.  I will remove this one.

>>   	help
>>   	  The Cavium Octeon processor is a highly integrated chip containing
>>   	  many ethernet hardware widgets for networking tasks. The processor
>> diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
>> index bdcedd3..e9f2f6c 100644
>> --- a/arch/mips/cavium-octeon/octeon-irq.c
>> +++ b/arch/mips/cavium-octeon/octeon-irq.c
[...]
>> +static void __init octeon_irq_set_ciu_mapping(unsigned int irq,
>> +					      unsigned int line,
>> +					      unsigned int bit,
>> +					      struct irq_domain *domain,
>>   					      struct irq_chip *chip,
>>   					      irq_flow_handler_t handler)
>>   {
>> +	struct irq_data *irqd;
>>   	union octeon_ciu_chip_data cd;
>>
>>   	irq_set_chip_and_handler(irq, chip, handler);
>> -
>>   	cd.l = 0;
>>   	cd.s.line = line;
>>   	cd.s.bit = bit;
>>
>>   	irq_set_chip_data(irq, cd.p);
>>   	octeon_irq_ciu_to_irq[line][bit] = irq;
>> +
>> +	irqd = irq_get_irq_data(irq);
>> +	irqd->hwirq = line<<  6 | bit;
>> +	irqd->domain = domain;
>
> I think the domain code will set these.

It is my understanding that the domain code only does this for:

o irq_domain_add_legacy()

o irq_create_direct_mapping()

o irq_create_mapping()

We use none of those.  So I do it here.

If there is a better way, I am open to suggestions.

[...]
>> @@ -982,6 +1092,10 @@ static void __init octeon_irq_init_ciu(void)
>>   	struct irq_chip *chip_mbox;
>>   	struct irq_chip *chip_wd;
>>   	struct irq_chip *chip_gpio;
>> +	struct device_node *gpio_node;
>> +	struct device_node *ciu_node;
>> +	struct irq_domain *gpio_domain;
>> +	struct irq_domain *ciu_domain;
>>
>>   	octeon_irq_init_ciu_percpu();
>>   	octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu;
>> @@ -1011,83 +1125,144 @@ static void __init octeon_irq_init_ciu(void)
>>   	/* Mips internal */
>>   	octeon_irq_init_core();
>>
>> +	gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio");
>> +	ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-ciu");
>> +	/* gpio domain host_data is the base hwirq number. */
>> +	gpio_domain = irq_domain_add_linear(gpio_node, 16,&octeon_irq_domain_gpio_ops, (void *)16);
>
> It would be better to define a struct here rather than casting a data
> value to a ptr.

You mean allocate storage for the data somewhere and then pass a pointer 
to it?

If so, I could, but it would just be adding code and data size just to 
satisfy some coding style thing...

Or do you want a union of the pointer and my int?  That would use the 
same amount of storage, but add more source code to gain what?

[...]
>> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48,
>> +				   ciu_domain, chip, handle_level_irq);
>> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49,
>> +				   ciu_domain, chip, handle_level_irq);
>> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50,
>> +				   ciu_domain, chip, handle_level_irq);
>> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51,
>> +				   ciu_domain, chip, handle_level_irq);
>> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52,
>> +				   ciu_domain, chip, handle_level_irq);
>> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56,
>> +				   ciu_domain, chip, handle_level_irq);
>> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63,
>> +				   ciu_domain, chip, handle_level_irq);
>>
>
> Can all these calls be moved into the .map function somehow?
>

No, the non-OF code using the OCTEON_IRQ_* symbols doesn't use 
irq_domain, so the .map function would never be used.


> edge vs. level should be driven by dts.
>

We may have to disagree on this point.  Because:

1) edge vs. level can be accurately probed, as we do here.

2) The dts doesnt contain the information.


David Daney

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-01  0:57 ` [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts David Daney
  2012-03-02 14:22   ` Rob Herring
@ 2012-03-02 19:02   ` Grant Likely
  1 sibling, 0 replies; 20+ messages in thread
From: Grant Likely @ 2012-03-02 19:02 UTC (permalink / raw)
  To: David Daney, linux-mips, ralf, devicetree-discuss, Rob Herring
  Cc: linux-kernel, David Daney

On Wed, 29 Feb 2012 16:57:01 -0800, David Daney <ddaney.cavm@gmail.com> wrote:
> From: David Daney <david.daney@cavium.com>
> 
> Select IRQ_DOMAIN so the core irq_domain code and supply
> irq_create_of_mapping().
> 
> Signed-off-by: David Daney <david.daney@cavium.com>
> ---
>  arch/mips/Kconfig                    |    1 +
>  arch/mips/cavium-octeon/octeon-irq.c |  301 +++++++++++++++++++++++++++-------
>  2 files changed, 239 insertions(+), 63 deletions(-)
> 
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index ce30e2f..01344ae 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -1432,6 +1432,7 @@ config CPU_CAVIUM_OCTEON
>  	select WEAK_ORDERING
>  	select CPU_SUPPORTS_HIGHMEM
>  	select CPU_SUPPORTS_HUGEPAGES
> +	select IRQ_DOMAIN
>  	help
>  	  The Cavium Octeon processor is a highly integrated chip containing
>  	  many ethernet hardware widgets for networking tasks. The processor
> diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
> index bdcedd3..e9f2f6c 100644
> --- a/arch/mips/cavium-octeon/octeon-irq.c
> +++ b/arch/mips/cavium-octeon/octeon-irq.c
> @@ -3,14 +3,16 @@
>   * License.  See the file "COPYING" in the main directory of this archive
>   * for more details.
>   *
> - * Copyright (C) 2004-2008, 2009, 2010, 2011 Cavium Networks
> + * Copyright (C) 2004-2008, 2009, 2010, 2011, 2012 Cavium Networks
>   */
>  
>  #include <linux/interrupt.h>
> +#include <linux/irqdomain.h>
>  #include <linux/bitops.h>
>  #include <linux/percpu.h>
>  #include <linux/irq.h>
>  #include <linux/smp.h>
> +#include <linux/of.h>
>  
>  #include <asm/octeon/octeon.h>
>  
> @@ -42,20 +44,27 @@ struct octeon_core_chip_data {
>  
>  static struct octeon_core_chip_data octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES];
>  
> -static void __init octeon_irq_set_ciu_mapping(int irq, int line, int bit,
> +static void __init octeon_irq_set_ciu_mapping(unsigned int irq,
> +					      unsigned int line,
> +					      unsigned int bit,
> +					      struct irq_domain *domain,
>  					      struct irq_chip *chip,
>  					      irq_flow_handler_t handler)
>  {
> +	struct irq_data *irqd;
>  	union octeon_ciu_chip_data cd;
>  
>  	irq_set_chip_and_handler(irq, chip, handler);
> -
>  	cd.l = 0;
>  	cd.s.line = line;
>  	cd.s.bit = bit;
>  
>  	irq_set_chip_data(irq, cd.p);
>  	octeon_irq_ciu_to_irq[line][bit] = irq;
> +
> +	irqd = irq_get_irq_data(irq);
> +	irqd->hwirq = line << 6 | bit;

irqdomain sets up hwirq for you.  Don't set it manually because it will
mess up irqdomain mappings.

> +	irqd->domain = domain;

Ditto here; irqdomain manages the domain pointer internally.

>  }
>  
>  static int octeon_coreid_for_cpu(int cpu)
> @@ -855,6 +864,107 @@ static struct irq_chip octeon_irq_chip_ciu_wd = {
>  	.irq_mask = octeon_irq_dummy_mask,
>  };
>  
> +static int octeon_irq_gpio_xlat(struct irq_domain *d,
> +				struct device_node *node,
> +				const u32 *intspec,
> +				unsigned int intsize,
> +				unsigned long *out_hwirq,
> +				unsigned int *out_type)
> +{
> +	unsigned int irq;
> +	unsigned int type;
> +	unsigned int ciu = 0, bit = 0;
> +	unsigned int pin;
> +	unsigned int trigger;
> +	bool set_edge_handler = false;
> +
> +	if (d->of_node != node)
> +		return -EINVAL;
> +
> +	if (intsize < 2)
> +		return -EINVAL;
> +
> +	pin = intspec[0];
> +	if (pin >= 16)
> +		return -EINVAL;
> +
> +	trigger = intspec[1];
> +
> +	switch (trigger) {
> +	case 1:
> +		type = IRQ_TYPE_EDGE_RISING;
> +		set_edge_handler = true;
> +		break;
> +	case 2:
> +		type = IRQ_TYPE_EDGE_FALLING;
> +		set_edge_handler = true;
> +		break;
> +	case 4:
> +		type = IRQ_TYPE_LEVEL_HIGH;
> +		break;
> +	case 8:
> +		type = IRQ_TYPE_LEVEL_LOW;
> +		break;
> +	default:
> +		pr_err("Error: (%s) Invalid irq trigger specification: %x\n",
> +		       node->name,
> +		       trigger);
> +		type = IRQ_TYPE_LEVEL_LOW;
> +		break;
> +	}
> +	*out_type = type;
> +	*out_hwirq = ((unsigned long)d->host_data) + pin;
> +
> +	ciu = *out_hwirq >> 6;
> +	bit = *out_hwirq & 0x3f;
> +
> +	irq = octeon_irq_ciu_to_irq[ciu][bit];

Again; this is overstepping onto irqdomain responsibility.  Don't set
up the irq in the xlate routine; only parse the date and if you need to
store extra data like 'set_edge_handler' (using the hwirq number as the
key).  The irq setup must be done in the .map callback which will be
passed the actual irq number to be used.

> +
> +	if (set_edge_handler)
> +		__irq_set_handler(irq, handle_edge_irq, 0, NULL);
> +
> +	return 0;
> +}
> +
> +static int octeon_irq_ciu_xlat(struct irq_domain *d,
> +			       struct device_node *node,
> +			       const u32 *intspec,
> +			       unsigned int intsize,
> +			       unsigned long *out_hwirq,
> +			       unsigned int *out_type)
> +{
> +	unsigned int ciu, bit;
> +
> +	ciu = intspec[0];
> +	bit = intspec[1];
> +
> +	if (ciu > 1 || bit > 63)
> +		return -EINVAL;
> +
> +	if (octeon_irq_ciu_to_irq[ciu][bit] == 0)
> +		return -EINVAL;
> +
> +	*out_hwirq = (ciu << 6) | bit;
> +	*out_type = 0;
> +
> +	return 0;
> +}
> +static int octeon_irq_dummy_map(struct irq_domain *d,
> +				unsigned int virq, irq_hw_number_t hw)
> +{
> +	return 0;
> +}
> +
> +static struct irq_domain_ops octeon_irq_domain_ciu_ops = {
> +	.map = octeon_irq_dummy_map,
> +	.xlate = octeon_irq_ciu_xlat,
> +};
> +
> +static struct irq_domain_ops octeon_irq_domain_gpio_ops = {
> +	.map = octeon_irq_dummy_map,
> +	.xlate = octeon_irq_gpio_xlat,
> +};
> +
>  static void octeon_irq_ip2_v1(void)
>  {
>  	const unsigned long core_id = cvmx_get_core_num();
> @@ -982,6 +1092,10 @@ static void __init octeon_irq_init_ciu(void)
>  	struct irq_chip *chip_mbox;
>  	struct irq_chip *chip_wd;
>  	struct irq_chip *chip_gpio;
> +	struct device_node *gpio_node;
> +	struct device_node *ciu_node;
> +	struct irq_domain *gpio_domain;
> +	struct irq_domain *ciu_domain;
>  
>  	octeon_irq_init_ciu_percpu();
>  	octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu;
> @@ -1011,83 +1125,144 @@ static void __init octeon_irq_init_ciu(void)
>  	/* Mips internal */
>  	octeon_irq_init_core();
>  
> +	gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio");
> +	ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-ciu");
> +	/* gpio domain host_data is the base hwirq number. */
> +	gpio_domain = irq_domain_add_linear(gpio_node, 16, &octeon_irq_domain_gpio_ops, (void *)16);
> +	ciu_domain = irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL);
> +
>  	/* CIU_0 */
>  	for (i = 0; i < 16; i++)
> -		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq);
> +		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0,
> +					   ciu_domain, chip, handle_level_irq);
> +
>  	for (i = 0; i < 16; i++)
> -		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16, chip_gpio, handle_level_irq);
> +		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16,
> +					   gpio_domain, chip_gpio, handle_level_irq);
>  
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32,
> +				   ciu_domain, chip_mbox, handle_percpu_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33,
> +				   ciu_domain, chip_mbox, handle_percpu_irq);
>  
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART0, 0, 34, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART1, 0, 35, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART0, 0, 34,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART1, 0, 35,
> +				   ciu_domain, chip, handle_level_irq);
>  
>  	for (i = 0; i < 4; i++)
> -		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq);
> +		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36,
> +					   ciu_domain, chip, handle_level_irq);
>  	for (i = 0; i < 4; i++)
> -		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq);
> +		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40,
> +					   ciu_domain, chip, handle_level_irq);
>  
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI, 0, 45, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TRACE0, 0, 47, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI, 0, 45,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TRACE0, 0, 47,
> +				   ciu_domain, chip, handle_level_irq);
>  
>  	for (i = 0; i < 2; i++)
> -		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GMX_DRP0, 0, i + 48, chip_edge, handle_edge_irq);
> +		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GMX_DRP0, 0, i + 48,
> +					   ciu_domain, chip_edge, handle_edge_irq);
>  
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD_DRP, 0, 50, chip_edge, handle_edge_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY_ZERO, 0, 51, chip_edge, handle_edge_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD_DRP, 0, 50,
> +				   ciu_domain, chip_edge, handle_edge_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY_ZERO, 0, 51,
> +				   ciu_domain, chip_edge, handle_edge_irq);
>  
>  	for (i = 0; i < 4; i++)
> -		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip_edge, handle_edge_irq);
> -
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PCM, 0, 57, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MPI, 0, 58, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI2, 0, 59, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_POWIQ, 0, 60, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPDPPTHR, 0, 61, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII0, 0, 62, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq);
> +		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52,
> +					   ciu_domain, chip_edge, handle_edge_irq);
> +
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PCM, 0, 57,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MPI, 0, 58,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI2, 0, 59,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_POWIQ, 0, 60,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPDPPTHR, 0, 61,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII0, 0, 62,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63,
> +				   ciu_domain, chip, handle_level_irq);
>  
>  	/* CIU_1 */
>  	for (i = 0; i < 16; i++)
> -		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
> -
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART2, 1, 16, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII1, 1, 18, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_NAND, 1, 19, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MIO, 1, 20, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IOB, 1, 21, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_FPA, 1, 22, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_POW, 1, 23, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_L2C, 1, 24, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD, 1, 25, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PIP, 1, 26, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PKO, 1, 27, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_ZIP, 1, 28, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TIM, 1, 29, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RAD, 1, 30, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY, 1, 31, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFA, 1, 32, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USBCTL, 1, 33, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SLI, 1, 34, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DPI, 1, 35, chip, handle_level_irq);
> -
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGX0, 1, 36, chip, handle_level_irq);
> -
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGL, 1, 46, chip, handle_level_irq);
> -
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PTP, 1, 47, chip_edge, handle_edge_irq);
> -
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56, chip, handle_level_irq);
> -	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63, chip, handle_level_irq);
> +		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0,
> +					   ciu_domain, chip_wd, handle_level_irq);
> +
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART2, 1, 16,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII1, 1, 18,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_NAND, 1, 19,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MIO, 1, 20,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IOB, 1, 21,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_FPA, 1, 22,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_POW, 1, 23,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_L2C, 1, 24,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD, 1, 25,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PIP, 1, 26,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PKO, 1, 27,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_ZIP, 1, 28,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TIM, 1, 29,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RAD, 1, 30,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY, 1, 31,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFA, 1, 32,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USBCTL, 1, 33,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SLI, 1, 34,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DPI, 1, 35,
> +				   ciu_domain, chip, handle_level_irq);
> +
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGX0, 1, 36,
> +				   ciu_domain, chip, handle_level_irq);
> +
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGL, 1, 46,
> +				   ciu_domain, chip, handle_level_irq);
> +
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PTP, 1, 47,
> +				   ciu_domain, chip_edge, handle_edge_irq);
> +
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56,
> +				   ciu_domain, chip, handle_level_irq);
> +	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63,
> +				   ciu_domain, chip, handle_level_irq);
>  
>  	/* Enable the CIU lines */
>  	set_c0_status(STATUSF_IP3 | STATUSF_IP2);
> -- 
> 1.7.2.3
> 

-- 
email sent from notmuch.vim plugin

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-02 18:03     ` David Daney
@ 2012-03-02 19:07       ` Grant Likely
  2012-03-02 19:29         ` David Daney
  2012-03-03 19:38       ` Rob Herring
  1 sibling, 1 reply; 20+ messages in thread
From: Grant Likely @ 2012-03-02 19:07 UTC (permalink / raw)
  To: David Daney, Rob Herring
  Cc: David Daney, linux-mips, ralf, devicetree-discuss, Rob Herring,
	linux-kernel

On Fri, 02 Mar 2012 10:03:58 -0800, David Daney <david.daney@cavium.com> wrote:
> On 03/02/2012 06:22 AM, Rob Herring wrote:
> [...]
> >> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> >> index ce30e2f..01344ae 100644
> >> --- a/arch/mips/Kconfig
> >> +++ b/arch/mips/Kconfig
> >> @@ -1432,6 +1432,7 @@ config CPU_CAVIUM_OCTEON
> >>   	select WEAK_ORDERING
> >>   	select CPU_SUPPORTS_HIGHMEM
> >>   	select CPU_SUPPORTS_HUGEPAGES
> >> +	select IRQ_DOMAIN
> >
> > IIRC, Grant has a patch cued up that enables IRQ_DOMAIN for all of MIPS.
> >
> 
> Indeed, I now see it in linux-next.  I will remove this one.
> 
> >>   	help
> >>   	  The Cavium Octeon processor is a highly integrated chip containing
> >>   	  many ethernet hardware widgets for networking tasks. The processor
> >> diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
> >> index bdcedd3..e9f2f6c 100644
> >> --- a/arch/mips/cavium-octeon/octeon-irq.c
> >> +++ b/arch/mips/cavium-octeon/octeon-irq.c
> [...]
> >> +static void __init octeon_irq_set_ciu_mapping(unsigned int irq,
> >> +					      unsigned int line,
> >> +					      unsigned int bit,
> >> +					      struct irq_domain *domain,
> >>   					      struct irq_chip *chip,
> >>   					      irq_flow_handler_t handler)
> >>   {
> >> +	struct irq_data *irqd;
> >>   	union octeon_ciu_chip_data cd;
> >>
> >>   	irq_set_chip_and_handler(irq, chip, handler);
> >> -
> >>   	cd.l = 0;
> >>   	cd.s.line = line;
> >>   	cd.s.bit = bit;
> >>
> >>   	irq_set_chip_data(irq, cd.p);
> >>   	octeon_irq_ciu_to_irq[line][bit] = irq;
> >> +
> >> +	irqd = irq_get_irq_data(irq);
> >> +	irqd->hwirq = line<<  6 | bit;
> >> +	irqd->domain = domain;
> >
> > I think the domain code will set these.
> 
> It is my understanding that the domain code only does this for:
> 
> o irq_domain_add_legacy()
> 
> o irq_create_direct_mapping()
> 
> o irq_create_mapping()
> 
> We use none of those.  So I do it here.
> 
> If there is a better way, I am open to suggestions.

irq_create_mapping is called by irq_create_of_mapping() which is
in turn called by irq_of_parse_and-map().  irq_domain always
manages the hwirq and domain values.  Driver code cannot manipulate
them manually.

g.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-02 19:07       ` Grant Likely
@ 2012-03-02 19:29         ` David Daney
  2012-03-03 19:35           ` Rob Herring
  0 siblings, 1 reply; 20+ messages in thread
From: David Daney @ 2012-03-02 19:29 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rob Herring, David Daney, linux-mips, ralf, devicetree-discuss,
	Rob Herring, linux-kernel

On 03/02/2012 11:07 AM, Grant Likely wrote:
> On Fri, 02 Mar 2012 10:03:58 -0800, David Daney<david.daney@cavium.com>  wrote:
>> On 03/02/2012 06:22 AM, Rob Herring wrote:
>> [...]
>>>> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
>>>> index ce30e2f..01344ae 100644
>>>> --- a/arch/mips/Kconfig
>>>> +++ b/arch/mips/Kconfig
>>>> @@ -1432,6 +1432,7 @@ config CPU_CAVIUM_OCTEON
>>>>    	select WEAK_ORDERING
>>>>    	select CPU_SUPPORTS_HIGHMEM
>>>>    	select CPU_SUPPORTS_HUGEPAGES
>>>> +	select IRQ_DOMAIN
>>>
>>> IIRC, Grant has a patch cued up that enables IRQ_DOMAIN for all of MIPS.
>>>
>>
>> Indeed, I now see it in linux-next.  I will remove this one.
>>
>>>>    	help
>>>>    	  The Cavium Octeon processor is a highly integrated chip containing
>>>>    	  many ethernet hardware widgets for networking tasks. The processor
>>>> diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
>>>> index bdcedd3..e9f2f6c 100644
>>>> --- a/arch/mips/cavium-octeon/octeon-irq.c
>>>> +++ b/arch/mips/cavium-octeon/octeon-irq.c
>> [...]
>>>> +static void __init octeon_irq_set_ciu_mapping(unsigned int irq,
>>>> +					      unsigned int line,
>>>> +					      unsigned int bit,
>>>> +					      struct irq_domain *domain,
>>>>    					      struct irq_chip *chip,
>>>>    					      irq_flow_handler_t handler)
>>>>    {
>>>> +	struct irq_data *irqd;
>>>>    	union octeon_ciu_chip_data cd;
>>>>
>>>>    	irq_set_chip_and_handler(irq, chip, handler);
>>>> -
>>>>    	cd.l = 0;
>>>>    	cd.s.line = line;
>>>>    	cd.s.bit = bit;
>>>>
>>>>    	irq_set_chip_data(irq, cd.p);
>>>>    	octeon_irq_ciu_to_irq[line][bit] = irq;
>>>> +
>>>> +	irqd = irq_get_irq_data(irq);
>>>> +	irqd->hwirq = line<<   6 | bit;
>>>> +	irqd->domain = domain;
>>>
>>> I think the domain code will set these.
>>
>> It is my understanding that the domain code only does this for:
>>
>> o irq_domain_add_legacy()
>>
>> o irq_create_direct_mapping()
>>
>> o irq_create_mapping()
>>
>> We use none of those.  So I do it here.
>>
>> If there is a better way, I am open to suggestions.
>
> irq_create_mapping is called by irq_create_of_mapping() which is
> in turn called by irq_of_parse_and-map().  irq_domain always
> manages the hwirq and domain values.  Driver code cannot manipulate
> them manually.
>

I really must be missing something.

Given:

1) I must have a mapping between hwirq and irq that I control so that 
non-OF code using the OCTEON_IRQ_* constants continues to work.

2) irq_create_mapping() will allocate a random irq value if none is 
already assigned to the hwirq.

Therefore: To avoid having random irq values assigned, I must manually 
assign them.

David Daney

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-02 19:29         ` David Daney
@ 2012-03-03 19:35           ` Rob Herring
  2012-03-04  5:09             ` David Daney
  0 siblings, 1 reply; 20+ messages in thread
From: Rob Herring @ 2012-03-03 19:35 UTC (permalink / raw)
  To: David Daney
  Cc: Grant Likely, David Daney, linux-mips, ralf, devicetree-discuss,
	Rob Herring, linux-kernel

On 03/02/2012 01:29 PM, David Daney wrote:
> On 03/02/2012 11:07 AM, Grant Likely wrote:
>> On Fri, 02 Mar 2012 10:03:58 -0800, David
>> Daney<david.daney@cavium.com>  wrote:
>>> On 03/02/2012 06:22 AM, Rob Herring wrote:
>>> [...]
>>>>> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
>>>>> index ce30e2f..01344ae 100644
>>>>> --- a/arch/mips/Kconfig
>>>>> +++ b/arch/mips/Kconfig
>>>>> @@ -1432,6 +1432,7 @@ config CPU_CAVIUM_OCTEON
>>>>>        select WEAK_ORDERING
>>>>>        select CPU_SUPPORTS_HIGHMEM
>>>>>        select CPU_SUPPORTS_HUGEPAGES
>>>>> +    select IRQ_DOMAIN
>>>>
>>>> IIRC, Grant has a patch cued up that enables IRQ_DOMAIN for all of
>>>> MIPS.
>>>>
>>>
>>> Indeed, I now see it in linux-next.  I will remove this one.
>>>
>>>>>        help
>>>>>          The Cavium Octeon processor is a highly integrated chip
>>>>> containing
>>>>>          many ethernet hardware widgets for networking tasks. The
>>>>> processor
>>>>> diff --git a/arch/mips/cavium-octeon/octeon-irq.c
>>>>> b/arch/mips/cavium-octeon/octeon-irq.c
>>>>> index bdcedd3..e9f2f6c 100644
>>>>> --- a/arch/mips/cavium-octeon/octeon-irq.c
>>>>> +++ b/arch/mips/cavium-octeon/octeon-irq.c
>>> [...]
>>>>> +static void __init octeon_irq_set_ciu_mapping(unsigned int irq,
>>>>> +                          unsigned int line,
>>>>> +                          unsigned int bit,
>>>>> +                          struct irq_domain *domain,
>>>>>                              struct irq_chip *chip,
>>>>>                              irq_flow_handler_t handler)
>>>>>    {
>>>>> +    struct irq_data *irqd;
>>>>>        union octeon_ciu_chip_data cd;
>>>>>
>>>>>        irq_set_chip_and_handler(irq, chip, handler);
>>>>> -
>>>>>        cd.l = 0;
>>>>>        cd.s.line = line;
>>>>>        cd.s.bit = bit;
>>>>>
>>>>>        irq_set_chip_data(irq, cd.p);
>>>>>        octeon_irq_ciu_to_irq[line][bit] = irq;
>>>>> +
>>>>> +    irqd = irq_get_irq_data(irq);
>>>>> +    irqd->hwirq = line<<   6 | bit;
>>>>> +    irqd->domain = domain;
>>>>
>>>> I think the domain code will set these.
>>>
>>> It is my understanding that the domain code only does this for:
>>>
>>> o irq_domain_add_legacy()
>>>
>>> o irq_create_direct_mapping()
>>>
>>> o irq_create_mapping()
>>>
>>> We use none of those.  So I do it here.
>>>
>>> If there is a better way, I am open to suggestions.
>>
>> irq_create_mapping is called by irq_create_of_mapping() which is
>> in turn called by irq_of_parse_and-map().  irq_domain always
>> manages the hwirq and domain values.  Driver code cannot manipulate
>> them manually.
>>
> 
> I really must be missing something.
> 
> Given:
> 
> 1) I must have a mapping between hwirq and irq that I control so that
> non-OF code using the OCTEON_IRQ_* constants continues to work.

Those defines are what you need to work to get rid of.

> 2) irq_create_mapping() will allocate a random irq value if none is
> already assigned to the hwirq.
> 
> Therefore: To avoid having random irq values assigned, I must manually
> assign them.
> 

So you should be using legacy domain if you need to maintain fixed hwirq
to linux irq numbers. "linear" is a bit confusing as it doesn't mean
linear 1:1 irq number assignment, but linear search.

Ultimately, for DT boot you should use of_irq_init to scan the dts, and
then create a linear domain for each interrupt controller node. You may
need to decide on linear vs. legacy at runtime based on having a DT node
pointer or not.

Rob

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-02 18:03     ` David Daney
  2012-03-02 19:07       ` Grant Likely
@ 2012-03-03 19:38       ` Rob Herring
  2012-03-04  5:41         ` David Daney
  1 sibling, 1 reply; 20+ messages in thread
From: Rob Herring @ 2012-03-03 19:38 UTC (permalink / raw)
  To: David Daney
  Cc: David Daney, linux-mips, ralf, devicetree-discuss, Grant Likely,
	Rob Herring, linux-kernel

On 03/02/2012 12:03 PM, David Daney wrote:
> On 03/02/2012 06:22 AM, Rob Herring wrote:
> [...]
>>> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
>>> index ce30e2f..01344ae 100644
>>> --- a/arch/mips/Kconfig
>>> +++ b/arch/mips/Kconfig
>>> @@ -1432,6 +1432,7 @@ config CPU_CAVIUM_OCTEON
>>>       select WEAK_ORDERING
>>>       select CPU_SUPPORTS_HIGHMEM
>>>       select CPU_SUPPORTS_HUGEPAGES
>>> +    select IRQ_DOMAIN
>>
>> IIRC, Grant has a patch cued up that enables IRQ_DOMAIN for all of MIPS.
>>
> 
> Indeed, I now see it in linux-next.  I will remove this one.
> 
>>>       help
>>>         The Cavium Octeon processor is a highly integrated chip
>>> containing
>>>         many ethernet hardware widgets for networking tasks. The
>>> processor
>>> diff --git a/arch/mips/cavium-octeon/octeon-irq.c
>>> b/arch/mips/cavium-octeon/octeon-irq.c
>>> index bdcedd3..e9f2f6c 100644
>>> --- a/arch/mips/cavium-octeon/octeon-irq.c
>>> +++ b/arch/mips/cavium-octeon/octeon-irq.c
> [...]
>>> +static void __init octeon_irq_set_ciu_mapping(unsigned int irq,
>>> +                          unsigned int line,
>>> +                          unsigned int bit,
>>> +                          struct irq_domain *domain,
>>>                             struct irq_chip *chip,
>>>                             irq_flow_handler_t handler)
>>>   {
>>> +    struct irq_data *irqd;
>>>       union octeon_ciu_chip_data cd;
>>>
>>>       irq_set_chip_and_handler(irq, chip, handler);
>>> -
>>>       cd.l = 0;
>>>       cd.s.line = line;
>>>       cd.s.bit = bit;
>>>
>>>       irq_set_chip_data(irq, cd.p);
>>>       octeon_irq_ciu_to_irq[line][bit] = irq;
>>> +
>>> +    irqd = irq_get_irq_data(irq);
>>> +    irqd->hwirq = line<<  6 | bit;
>>> +    irqd->domain = domain;
>>
>> I think the domain code will set these.
> 
> It is my understanding that the domain code only does this for:
> 
> o irq_domain_add_legacy()
> 
> o irq_create_direct_mapping()
> 
> o irq_create_mapping()
> 
> We use none of those.  So I do it here.
> 
> If there is a better way, I am open to suggestions.

How do you convert local h/w irq controller numbers in the dts to linux
irq #'s?

> 
> [...]
>>> @@ -982,6 +1092,10 @@ static void __init octeon_irq_init_ciu(void)
>>>       struct irq_chip *chip_mbox;
>>>       struct irq_chip *chip_wd;
>>>       struct irq_chip *chip_gpio;
>>> +    struct device_node *gpio_node;
>>> +    struct device_node *ciu_node;
>>> +    struct irq_domain *gpio_domain;
>>> +    struct irq_domain *ciu_domain;
>>>
>>>       octeon_irq_init_ciu_percpu();
>>>       octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu;
>>> @@ -1011,83 +1125,144 @@ static void __init octeon_irq_init_ciu(void)
>>>       /* Mips internal */
>>>       octeon_irq_init_core();
>>>
>>> +    gpio_node = of_find_compatible_node(NULL, NULL,
>>> "cavium,octeon-3860-gpio");
>>> +    ciu_node = of_find_compatible_node(NULL, NULL,
>>> "cavium,octeon-3860-ciu");
>>> +    /* gpio domain host_data is the base hwirq number. */
>>> +    gpio_domain = irq_domain_add_linear(gpio_node,
>>> 16,&octeon_irq_domain_gpio_ops, (void *)16);
>>
>> It would be better to define a struct here rather than casting a data
>> value to a ptr.
> 
> You mean allocate storage for the data somewhere and then pass a pointer
> to it?
> 
> If so, I could, but it would just be adding code and data size just to
> satisfy some coding style thing...
> 
> Or do you want a union of the pointer and my int?  That would use the
> same amount of storage, but add more source code to gain what?

The former. It's better style, less error prone and easily expanded if
more data is needed in the future.

> 
> [...]
>>> +    octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48,
>>> +                   ciu_domain, chip, handle_level_irq);
>>> +    octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49,
>>> +                   ciu_domain, chip, handle_level_irq);
>>> +    octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50,
>>> +                   ciu_domain, chip, handle_level_irq);
>>> +    octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51,
>>> +                   ciu_domain, chip, handle_level_irq);
>>> +    octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52,
>>> +                   ciu_domain, chip, handle_level_irq);
>>> +    octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56,
>>> +                   ciu_domain, chip, handle_level_irq);
>>> +    octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63,
>>> +                   ciu_domain, chip, handle_level_irq);
>>>
>>
>> Can all these calls be moved into the .map function somehow?
>>
> 
> No, the non-OF code using the OCTEON_IRQ_* symbols doesn't use
> irq_domain, so the .map function would never be used.
> 

.map is called for legacy domains during domain add.


> 
>> edge vs. level should be driven by dts.
>>
> 
> We may have to disagree on this point.  Because:
> 
> 1) edge vs. level can be accurately probed, as we do here.

Looks like you are just hard coding it here. Where do you read something
that tells you the interrupt is level or edge?

Rob

> 
> 2) The dts doesnt contain the information.
> 
> 
> David Daney


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-03 19:35           ` Rob Herring
@ 2012-03-04  5:09             ` David Daney
  2012-03-09  5:57               ` Grant Likely
  0 siblings, 1 reply; 20+ messages in thread
From: David Daney @ 2012-03-04  5:09 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Daney, Grant Likely, David Daney, linux-mips, ralf,
	devicetree-discuss, Rob Herring, linux-kernel

On 03/03/2012 11:35 AM, Rob Herring wrote:
> On 03/02/2012 01:29 PM, David Daney wrote:
>> On 03/02/2012 11:07 AM, Grant Likely wrote:
>>> +static void __init octeon_irq_set_ciu_mapping(unsigned int irq,
>>> +                          unsigned int line,
>>> +                          unsigned int bit,
>>> +                          struct irq_domain *domain,
>>>                               struct irq_chip *chip,
>>>                               irq_flow_handler_t handler)
>>>     {
>>> +    struct irq_data *irqd;
>>>         union octeon_ciu_chip_data cd;
>>>
>>>         irq_set_chip_and_handler(irq, chip, handler);
>>> -
>>>         cd.l = 0;
>>>         cd.s.line = line;
>>>         cd.s.bit = bit;
>>>
>>>         irq_set_chip_data(irq, cd.p);
>>>         octeon_irq_ciu_to_irq[line][bit] = irq;
>>> +
>>> +    irqd = irq_get_irq_data(irq);
>>> +    irqd->hwirq = line<<    6 | bit;
>>> +    irqd->domain = domain;
>>>>> I think the domain code will set these.
>>>> It is my understanding that the domain code only does this for:
>>>>
>>>> o irq_domain_add_legacy()
>>>>
>>>> o irq_create_direct_mapping()
>>>>
>>>> o irq_create_mapping()
>>>>
>>>> We use none of those.  So I do it here.
>>>>
>>>> If there is a better way, I am open to suggestions.
>>> irq_create_mapping is called by irq_create_of_mapping() which is
>>> in turn called by irq_of_parse_and-map().  irq_domain always
>>> manages the hwirq and domain values.  Driver code cannot manipulate
>>> them manually.
>>>
>> I really must be missing something.
>>
>> Given:
>>
>> 1) I must have a mapping between hwirq and irq that I control so that
>> non-OF code using the OCTEON_IRQ_* constants continues to work.
> Those defines are what you need to work to get rid of.

We are not starting from a blank slate here.  There is a lot of in-tree 
code using these symbols.  We cannot make them disappear with wishful 
thinking.

The first step is a switch to irq_domains using the existing mappings.

After we do that, I have patches to transition some drivers to use the 
OF mapping via irq_domains.  After those are merged, we can work toward 
getting rid of OCTEON_IRQ_*.  But I think it must be the last step in 
the process, not the first.
>
>> 2) irq_create_mapping() will allocate a random irq value if none is
>> already assigned to the hwirq.
>>
>> Therefore: To avoid having random irq values assigned, I must manually
>> assign them.
>>
> So you should be using legacy domain if you need to maintain fixed hwirq
> to linux irq numbers. "linear" is a bit confusing as it doesn't mean
> linear 1:1 irq number assignment, but linear search.

My reading of Grant's code in linux-next directly contradicts this 
statement.  There is no code in irqdomain.c, that I can see, that allows 
me to have an arbitrary mapping of irq <--> hwirq values.


>
> Ultimately, for DT boot you should use of_irq_init to scan the dts, and
> then create a linear domain for each interrupt controller node. You may
> need to decide on linear vs. legacy at runtime based on having a DT node
> pointer or not.

Perhaps, but we need to take the first step before gradually arriving at 
some Ultimate Solution.

We will also need to handle irq controllers with 2^20 sparsely populated 
hwirq values, so linear domains will probably be out of the question there.

David Daney

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-03 19:38       ` Rob Herring
@ 2012-03-04  5:41         ` David Daney
  0 siblings, 0 replies; 20+ messages in thread
From: David Daney @ 2012-03-04  5:41 UTC (permalink / raw)
  To: Rob Herring
  Cc: David Daney, David Daney, linux-mips, ralf, devicetree-discuss,
	Grant Likely, Rob Herring, linux-kernel

On 03/03/2012 11:38 AM, Rob Herring wrote:
> On 03/02/2012 12:03 PM, David Daney wrote:
>> +
>> +    irqd = irq_get_irq_data(irq);
>> +    irqd->hwirq = line<<   6 | bit;
>> +    irqd->domain = domain;
>>> I think the domain code will set these.
>> It is my understanding that the domain code only does this for:
>>
>> o irq_domain_add_legacy()
>>
>> o irq_create_direct_mapping()
>>
>> o irq_create_mapping()
>>
>> We use none of those.  So I do it here.
>>
>> If there is a better way, I am open to suggestions.
> How do you convert local h/w irq controller numbers in the dts to linux
> irq #'s?

With the calls to octeon_irq_set_ciu_mapping() ...

  [...]
>>>> +    octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48,
>>>> +                   ciu_domain, chip, handle_level_irq);
>>>> +    octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49,
>>>> +                   ciu_domain, chip, handle_level_irq);
>>>> +    octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50,
>>>> +                   ciu_domain, chip, handle_level_irq);
>>>> +    octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51,
>>>> +                   ciu_domain, chip, handle_level_irq);
>>>> +    octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52,
>>>> +                   ciu_domain, chip, handle_level_irq);
>>>> +    octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56,
>>>> +                   ciu_domain, chip, handle_level_irq);
>>>> +    octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63,
>>>> +                   ciu_domain, chip, handle_level_irq);
>>>>

>>>> [...]
>>> edge vs. level should be driven by dts.
>>>
>> We may have to disagree on this point.  Because:
>>
>> 1) edge vs. level can be accurately probed, as we do here.
> Looks like you are just hard coding it here. Where do you read something
> that tells you the interrupt is level or edge?

We probe for the type of interrupt controller by reading the SOC 
identifier number, although we can get the same information from the dts.

Once we know the type of interrupt controller, the level vs. edge is 
known a priori, and that knowlege is encoded in all these 
octeon_irq_set_ciu_mapping() calls.

And on top of this...

>> 2) The dts doesn't contain the information.
>>

So it is kind of a moot point.

It is not some sort of generic interrupt controller that can be 
configured in different ways, each line has certain properties endowed 
upon it by the chip designers, and once a line is assigned a particular 
configuration, it is never changed in future generations.

For external devices attached to the GPIO interrupt lines, things are 
different, we can only know the triggering via the dts, and lo and 
behold... it is there and we use it.


David Daney

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-04  5:09             ` David Daney
@ 2012-03-09  5:57               ` Grant Likely
  2012-03-09 18:45                 ` David Daney
  0 siblings, 1 reply; 20+ messages in thread
From: Grant Likely @ 2012-03-09  5:57 UTC (permalink / raw)
  To: David Daney, Rob Herring
  Cc: David Daney, David Daney, linux-mips, ralf, devicetree-discuss,
	Rob Herring, linux-kernel

On Sat, 03 Mar 2012 21:09:32 -0800, David Daney <david.s.daney@gmail.com> wrote:
> On 03/03/2012 11:35 AM, Rob Herring wrote:
> > On 03/02/2012 01:29 PM, David Daney wrote:
> >> On 03/02/2012 11:07 AM, Grant Likely wrote:
> >>> +static void __init octeon_irq_set_ciu_mapping(unsigned int irq,
> >>> +                          unsigned int line,
> >>> +                          unsigned int bit,
> >>> +                          struct irq_domain *domain,
> >>>                               struct irq_chip *chip,
> >>>                               irq_flow_handler_t handler)
> >>>     {
> >>> +    struct irq_data *irqd;
> >>>         union octeon_ciu_chip_data cd;
> >>>
> >>>         irq_set_chip_and_handler(irq, chip, handler);
> >>> -
> >>>         cd.l = 0;
> >>>         cd.s.line = line;
> >>>         cd.s.bit = bit;
> >>>
> >>>         irq_set_chip_data(irq, cd.p);
> >>>         octeon_irq_ciu_to_irq[line][bit] = irq;
> >>> +
> >>> +    irqd = irq_get_irq_data(irq);
> >>> +    irqd->hwirq = line<<    6 | bit;
> >>> +    irqd->domain = domain;
> >>>>> I think the domain code will set these.
> >>>> It is my understanding that the domain code only does this for:
> >>>>
> >>>> o irq_domain_add_legacy()
> >>>>
> >>>> o irq_create_direct_mapping()
> >>>>
> >>>> o irq_create_mapping()
> >>>>
> >>>> We use none of those.  So I do it here.
> >>>>
> >>>> If there is a better way, I am open to suggestions.
> >>> irq_create_mapping is called by irq_create_of_mapping() which is
> >>> in turn called by irq_of_parse_and-map().  irq_domain always
> >>> manages the hwirq and domain values.  Driver code cannot manipulate
> >>> them manually.
> >>>
> >> I really must be missing something.
> >>
> >> Given:
> >>
> >> 1) I must have a mapping between hwirq and irq that I control so that
> >> non-OF code using the OCTEON_IRQ_* constants continues to work.
> > Those defines are what you need to work to get rid of.
> 
> We are not starting from a blank slate here.  There is a lot of in-tree 
> code using these symbols.  We cannot make them disappear with wishful 
> thinking.
> 
> The first step is a switch to irq_domains using the existing mappings.
> 
> After we do that, I have patches to transition some drivers to use the 
> OF mapping via irq_domains.  After those are merged, we can work toward 
> getting rid of OCTEON_IRQ_*.  But I think it must be the last step in 
> the process, not the first.
> >
> >> 2) irq_create_mapping() will allocate a random irq value if none is
> >> already assigned to the hwirq.
> >>
> >> Therefore: To avoid having random irq values assigned, I must manually
> >> assign them.
> >>
> > So you should be using legacy domain if you need to maintain fixed hwirq
> > to linux irq numbers. "linear" is a bit confusing as it doesn't mean
> > linear 1:1 irq number assignment, but linear search.
> 
> My reading of Grant's code in linux-next directly contradicts this 
> statement.  There is no code in irqdomain.c, that I can see, that allows 
> me to have an arbitrary mapping of irq <--> hwirq values.

There are 4 kinds of mappings available; legacy, linear, radix and nomap.

Ignore nomap and radix; you don't want them.

legacy maps a contiguous range of hwirq numbers to a contiguous range of
linux irq numbers.  To preserve the exising #define mappings but still add
DT support, this is the one that you want.  The downside is that it requires
all the irq_descs to be allocated ahead of time (which probably isn't a
problem for you).

The linear map has a linear reverse map lookup table that allows arbitrary
irq <--> hwirq mappings.  This mapping is preferred, but it doesn't work
if you need to preserve #defined irq mappings.

g.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-09  5:57               ` Grant Likely
@ 2012-03-09 18:45                 ` David Daney
  2012-03-09 21:07                   ` Rob Herring
  0 siblings, 1 reply; 20+ messages in thread
From: David Daney @ 2012-03-09 18:45 UTC (permalink / raw)
  To: Grant Likely
  Cc: David Daney, Rob Herring, David Daney, linux-mips, ralf,
	devicetree-discuss, Rob Herring, linux-kernel

On 03/08/2012 09:57 PM, Grant Likely wrote:
> On Sat, 03 Mar 2012 21:09:32 -0800, David Daney<david.s.daney@gmail.com>  wrote:
>> On 03/03/2012 11:35 AM, Rob Herring wrote:
>>> On 03/02/2012 01:29 PM, David Daney wrote:
>>>> On 03/02/2012 11:07 AM, Grant Likely wrote:
>>>>> +static void __init octeon_irq_set_ciu_mapping(unsigned int irq,
>>>>> +                          unsigned int line,
>>>>> +                          unsigned int bit,
>>>>> +                          struct irq_domain *domain,
>>>>>                                struct irq_chip *chip,
>>>>>                                irq_flow_handler_t handler)
>>>>>      {
>>>>> +    struct irq_data *irqd;
>>>>>          union octeon_ciu_chip_data cd;
>>>>>
>>>>>          irq_set_chip_and_handler(irq, chip, handler);
>>>>> -
>>>>>          cd.l = 0;
>>>>>          cd.s.line = line;
>>>>>          cd.s.bit = bit;
>>>>>
>>>>>          irq_set_chip_data(irq, cd.p);
>>>>>          octeon_irq_ciu_to_irq[line][bit] = irq;
>>>>> +
>>>>> +    irqd = irq_get_irq_data(irq);
>>>>> +    irqd->hwirq = line<<     6 | bit;
>>>>> +    irqd->domain = domain;
>>>>>>> I think the domain code will set these.
>>>>>> It is my understanding that the domain code only does this for:
>>>>>>
>>>>>> o irq_domain_add_legacy()
>>>>>>
>>>>>> o irq_create_direct_mapping()
>>>>>>
>>>>>> o irq_create_mapping()
>>>>>>
>>>>>> We use none of those.  So I do it here.
>>>>>>
>>>>>> If there is a better way, I am open to suggestions.
>>>>> irq_create_mapping is called by irq_create_of_mapping() which is
>>>>> in turn called by irq_of_parse_and-map().  irq_domain always
>>>>> manages the hwirq and domain values.  Driver code cannot manipulate
>>>>> them manually.
>>>>>
>>>> I really must be missing something.
>>>>
>>>> Given:
>>>>
>>>> 1) I must have a mapping between hwirq and irq that I control so that
>>>> non-OF code using the OCTEON_IRQ_* constants continues to work.
>>> Those defines are what you need to work to get rid of.
>>
>> We are not starting from a blank slate here.  There is a lot of in-tree
>> code using these symbols.  We cannot make them disappear with wishful
>> thinking.
>>
>> The first step is a switch to irq_domains using the existing mappings.
>>
>> After we do that, I have patches to transition some drivers to use the
>> OF mapping via irq_domains.  After those are merged, we can work toward
>> getting rid of OCTEON_IRQ_*.  But I think it must be the last step in
>> the process, not the first.
>>>
>>>> 2) irq_create_mapping() will allocate a random irq value if none is
>>>> already assigned to the hwirq.
>>>>
>>>> Therefore: To avoid having random irq values assigned, I must manually
>>>> assign them.
>>>>
>>> So you should be using legacy domain if you need to maintain fixed hwirq
>>> to linux irq numbers. "linear" is a bit confusing as it doesn't mean
>>> linear 1:1 irq number assignment, but linear search.
>>
>> My reading of Grant's code in linux-next directly contradicts this
>> statement.  There is no code in irqdomain.c, that I can see, that allows
>> me to have an arbitrary mapping of irq<-->  hwirq values.
>
> There are 4 kinds of mappings available; legacy, linear, radix and nomap.
>

Yes, I had discovered that.

> Ignore nomap and radix; you don't want them.
>
> legacy maps a contiguous range of hwirq numbers to a contiguous range of
> linux irq numbers.  To preserve the exising #define mappings but still add
> DT support, this is the one that you want.

This is precisely the point that you and Rob seem to have missed in the 
last three or four back-and-forths about this.

Probably I have not explained well enough why legacy will not work.

We have three different interrupt controllers (although only one is 
currently in-tree).  hwirq to irq mapping for them is more or less as 
follows:

irq                 hwirqCIU        hwirqCIU2      hwirqCIU3
----------------------------------------------------------------------
OCTEON_IRQ_USB0     56               81             934562
OCTEON_IRQ_TWSI     45              224             100543
OCTEON_IRQ_UART0    34              228               4572
.
.
.

Now what we notice here is that there is no possible 1:1 linearly 
increasing mapping possible for the irq and *all* three hwirq sets.  We 
want a single binary that contains support for all three interrupt 
controllers, so the OCTEON_IRQ_* values have to be the same for all 
three interrupt controllers.  Because of this, legacy mapping is 
*impossible*.

Since the possible ranges of the hwirq values is very large and quite 
sparse, probably the radix mapping will be required.

Also to support non-OF drivers and architecture specific code for the 
near future, I really think the existing IRQ values *must* be preserved.

Therefore, as I said above, we need a way for my SOC/board code to 
specify the mapping.

Perhaps we need to add an optional function to struct irq_domain_ops 
that would allow the default mapping to be overridden on a per 
irq_domain basis.

Otherwise, I think I will have to keep poking into the internal 
irq_domain data structures to get the mappings I want.

What do you think?

David Daney

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-09 18:45                 ` David Daney
@ 2012-03-09 21:07                   ` Rob Herring
  2012-03-10  0:08                     ` David Daney
  0 siblings, 1 reply; 20+ messages in thread
From: Rob Herring @ 2012-03-09 21:07 UTC (permalink / raw)
  To: David Daney
  Cc: Grant Likely, David Daney, linux-mips, ralf, devicetree-discuss,
	Rob Herring, linux-kernel

On 03/09/2012 12:45 PM, David Daney wrote:
> On 03/08/2012 09:57 PM, Grant Likely wrote:
>> On Sat, 03 Mar 2012 21:09:32 -0800, David
>> Daney<david.s.daney@gmail.com>  wrote:
>>> On 03/03/2012 11:35 AM, Rob Herring wrote:
>>>> On 03/02/2012 01:29 PM, David Daney wrote:
>>>>> On 03/02/2012 11:07 AM, Grant Likely wrote:
>>>>>> +static void __init octeon_irq_set_ciu_mapping(unsigned int irq,
>>>>>> +                          unsigned int line,
>>>>>> +                          unsigned int bit,
>>>>>> +                          struct irq_domain *domain,
>>>>>>                                struct irq_chip *chip,
>>>>>>                                irq_flow_handler_t handler)
>>>>>>      {
>>>>>> +    struct irq_data *irqd;
>>>>>>          union octeon_ciu_chip_data cd;
>>>>>>
>>>>>>          irq_set_chip_and_handler(irq, chip, handler);
>>>>>> -
>>>>>>          cd.l = 0;
>>>>>>          cd.s.line = line;
>>>>>>          cd.s.bit = bit;
>>>>>>
>>>>>>          irq_set_chip_data(irq, cd.p);
>>>>>>          octeon_irq_ciu_to_irq[line][bit] = irq;
>>>>>> +
>>>>>> +    irqd = irq_get_irq_data(irq);
>>>>>> +    irqd->hwirq = line<<     6 | bit;
>>>>>> +    irqd->domain = domain;
>>>>>>>> I think the domain code will set these.
>>>>>>> It is my understanding that the domain code only does this for:
>>>>>>>
>>>>>>> o irq_domain_add_legacy()
>>>>>>>
>>>>>>> o irq_create_direct_mapping()
>>>>>>>
>>>>>>> o irq_create_mapping()
>>>>>>>
>>>>>>> We use none of those.  So I do it here.
>>>>>>>
>>>>>>> If there is a better way, I am open to suggestions.
>>>>>> irq_create_mapping is called by irq_create_of_mapping() which is
>>>>>> in turn called by irq_of_parse_and-map().  irq_domain always
>>>>>> manages the hwirq and domain values.  Driver code cannot manipulate
>>>>>> them manually.
>>>>>>
>>>>> I really must be missing something.
>>>>>
>>>>> Given:
>>>>>
>>>>> 1) I must have a mapping between hwirq and irq that I control so that
>>>>> non-OF code using the OCTEON_IRQ_* constants continues to work.
>>>> Those defines are what you need to work to get rid of.
>>>
>>> We are not starting from a blank slate here.  There is a lot of in-tree
>>> code using these symbols.  We cannot make them disappear with wishful
>>> thinking.
>>>
>>> The first step is a switch to irq_domains using the existing mappings.
>>>
>>> After we do that, I have patches to transition some drivers to use the
>>> OF mapping via irq_domains.  After those are merged, we can work toward
>>> getting rid of OCTEON_IRQ_*.  But I think it must be the last step in
>>> the process, not the first.
>>>>
>>>>> 2) irq_create_mapping() will allocate a random irq value if none is
>>>>> already assigned to the hwirq.
>>>>>
>>>>> Therefore: To avoid having random irq values assigned, I must manually
>>>>> assign them.
>>>>>
>>>> So you should be using legacy domain if you need to maintain fixed
>>>> hwirq
>>>> to linux irq numbers. "linear" is a bit confusing as it doesn't mean
>>>> linear 1:1 irq number assignment, but linear search.
>>>
>>> My reading of Grant's code in linux-next directly contradicts this
>>> statement.  There is no code in irqdomain.c, that I can see, that allows
>>> me to have an arbitrary mapping of irq<-->  hwirq values.
>>
>> There are 4 kinds of mappings available; legacy, linear, radix and nomap.
>>
> 
> Yes, I had discovered that.
> 
>> Ignore nomap and radix; you don't want them.
>>
>> legacy maps a contiguous range of hwirq numbers to a contiguous range of
>> linux irq numbers.  To preserve the exising #define mappings but still
>> add
>> DT support, this is the one that you want.
> 
> This is precisely the point that you and Rob seem to have missed in the
> last three or four back-and-forths about this.
> 
> Probably I have not explained well enough why legacy will not work.
> 
> We have three different interrupt controllers (although only one is
> currently in-tree).  hwirq to irq mapping for them is more or less as
> follows:

I'll just repeat what others have said: if it's not upstream it doesn't
exist.

We have no knowledge about out of tree h/w to understand what you need

> irq                 hwirqCIU        hwirqCIU2      hwirqCIU3
> ----------------------------------------------------------------------
> OCTEON_IRQ_USB0     56               81             934562
> OCTEON_IRQ_TWSI     45              224             100543
> OCTEON_IRQ_UART0    34              228               4572
> .
> .
> .

How many actual hwirqs in each case and what is the range?

So for CIU3, it seems you would need to use a radix tree. CIU2 is
probably borderline depending on what is the max number. But because you
don't yet have code in tree for either yet, you can use a linear domain
for now. It shouldn't be hard to switch from linear to radix later.

> Now what we notice here is that there is no possible 1:1 linearly
> increasing mapping possible for the irq and *all* three hwirq sets.  We
> want a single binary that contains support for all three interrupt
> controllers, so the OCTEON_IRQ_* values have to be the same for all
> three interrupt controllers.  Because of this, legacy mapping is
> *impossible*.

OCTEON_IRQ_* values need to go. You may not have to do that now, but
certainly before doing support for CIU2 and CIU3 you do. Those platforms
should be DT only.

> 
> Since the possible ranges of the hwirq values is very large and quite
> sparse, probably the radix mapping will be required.
> 

Yes. You're not the only one with this issue.

> Also to support non-OF drivers and architecture specific code for the
> near future, I really think the existing IRQ values *must* be preserved.
> 

For a legacy boot yes. But when you boot with DT, you should not need
them. This is certainly possible as several ARM platforms do this. You
need to start with minimal set of drivers enabled for DT and add them
back in 1 by 1.

Rob

> Therefore, as I said above, we need a way for my SOC/board code to
> specify the mapping.
> 
> Perhaps we need to add an optional function to struct irq_domain_ops
> that would allow the default mapping to be overridden on a per
> irq_domain basis.
> 
> Otherwise, I think I will have to keep poking into the internal
> irq_domain data structures to get the mappings I want.
> 
> What do you think?
> 
> David Daney


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-09 21:07                   ` Rob Herring
@ 2012-03-10  0:08                     ` David Daney
  2012-03-10 16:20                       ` Rob Herring
  0 siblings, 1 reply; 20+ messages in thread
From: David Daney @ 2012-03-10  0:08 UTC (permalink / raw)
  To: Rob Herring
  Cc: Grant Likely, David Daney, linux-mips, ralf, devicetree-discuss,
	Rob Herring, linux-kernel

On 03/09/2012 01:07 PM, Rob Herring wrote:
> On 03/09/2012 12:45 PM, David Daney wrote:
[...]
>>
>> Probably I have not explained well enough why legacy will not work.
>>
>> We have three different interrupt controllers (although only one is
>> currently in-tree).  hwirq to irq mapping for them is more or less as
>> follows:
>
> I'll just repeat what others have said: if it's not upstream it doesn't
> exist.
>
> We have no knowledge about out of tree h/w to understand what you need
>
>> irq                 hwirqCIU        hwirqCIU2      hwirqCIU3
>> ----------------------------------------------------------------------
>> OCTEON_IRQ_USB0     56               81             934562
>> OCTEON_IRQ_TWSI     45              224             100543
>> OCTEON_IRQ_UART0    34              228               4572
>> .
>> .
>> .
>
> How many actual hwirqs in each case and what is the range?
>
> So for CIU3, it seems you would need to use a radix tree. CIU2 is
> probably borderline depending on what is the max number. But because you
> don't yet have code in tree for either yet, you can use a linear domain
> for now. It shouldn't be hard to switch from linear to radix later.
>
>> Now what we notice here is that there is no possible 1:1 linearly
>> increasing mapping possible for the irq and *all* three hwirq sets.  We
>> want a single binary that contains support for all three interrupt
>> controllers, so the OCTEON_IRQ_* values have to be the same for all
>> three interrupt controllers.  Because of this, legacy mapping is
>> *impossible*.
>
> OCTEON_IRQ_* values need to go. You may not have to do that now, but
> certainly before doing support for CIU2 and CIU3 you do. Those platforms
> should be DT only.
>
>>
>> Since the possible ranges of the hwirq values is very large and quite
>> sparse, probably the radix mapping will be required.
>>
>
> Yes. You're not the only one with this issue.
>
>> Also to support non-OF drivers and architecture specific code for the
>> near future, I really think the existing IRQ values *must* be preserved.
>>
>
> For a legacy boot yes. But when you boot with DT, you should not need
> them.

It is not a matter of how the system is booted, rather what all the 
drivers are expecting...

> This is certainly possible as several ARM platforms do this. You
> need to start with minimal set of drivers enabled for DT and add them
> back in 1 by 1.
>

What I don't understand about this is what happens during the transition?

What if a shared interrupt were referred from one non-OF driver by its 
symbolic OCTEON_IRQ_? value, and from a second driver by its hwirq value 
extracted from the DT?  In that case you would be referring to the same 
interrupt line by two different irq values, clearly that should be 
prevented.

At a minimum, the change made for each converted driver would have to 
include: removing the OCTEON_IRQ_? values,  Maintain a list of hwirqs 
that are outside of the domain and report this by the.map() function, 
and then update this list.

David Daney

> Rob
>
>> Therefore, as I said above, we need a way for my SOC/board code to
>> specify the mapping.
>>
>> Perhaps we need to add an optional function to struct irq_domain_ops
>> that would allow the default mapping to be overridden on a per
>> irq_domain basis.
>>
>> Otherwise, I think I will have to keep poking into the internal
>> irq_domain data structures to get the mappings I want.
>>
>> What do you think?
>>
>> David Daney
>
>


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts.
  2012-03-10  0:08                     ` David Daney
@ 2012-03-10 16:20                       ` Rob Herring
  0 siblings, 0 replies; 20+ messages in thread
From: Rob Herring @ 2012-03-10 16:20 UTC (permalink / raw)
  To: David Daney
  Cc: Grant Likely, David Daney, linux-mips, ralf, devicetree-discuss,
	Rob Herring, linux-kernel

On 03/09/2012 06:08 PM, David Daney wrote:
> On 03/09/2012 01:07 PM, Rob Herring wrote:
>> On 03/09/2012 12:45 PM, David Daney wrote:
> [...]
>>>
>>> Probably I have not explained well enough why legacy will not work.
>>>
>>> We have three different interrupt controllers (although only one is
>>> currently in-tree).  hwirq to irq mapping for them is more or less as
>>> follows:
>>
>> I'll just repeat what others have said: if it's not upstream it doesn't
>> exist.
>>
>> We have no knowledge about out of tree h/w to understand what you need
>>
>>> irq                 hwirqCIU        hwirqCIU2      hwirqCIU3
>>> ----------------------------------------------------------------------
>>> OCTEON_IRQ_USB0     56               81             934562
>>> OCTEON_IRQ_TWSI     45              224             100543
>>> OCTEON_IRQ_UART0    34              228               4572
>>> .
>>> .
>>> .
>>
>> How many actual hwirqs in each case and what is the range?
>>
>> So for CIU3, it seems you would need to use a radix tree. CIU2 is
>> probably borderline depending on what is the max number. But because you
>> don't yet have code in tree for either yet, you can use a linear domain
>> for now. It shouldn't be hard to switch from linear to radix later.
>>
>>> Now what we notice here is that there is no possible 1:1 linearly
>>> increasing mapping possible for the irq and *all* three hwirq sets.  We
>>> want a single binary that contains support for all three interrupt
>>> controllers, so the OCTEON_IRQ_* values have to be the same for all
>>> three interrupt controllers.  Because of this, legacy mapping is
>>> *impossible*.
>>
>> OCTEON_IRQ_* values need to go. You may not have to do that now, but
>> certainly before doing support for CIU2 and CIU3 you do. Those platforms
>> should be DT only.
>>
>>>
>>> Since the possible ranges of the hwirq values is very large and quite
>>> sparse, probably the radix mapping will be required.
>>>
>>
>> Yes. You're not the only one with this issue.
>>
>>> Also to support non-OF drivers and architecture specific code for the
>>> near future, I really think the existing IRQ values *must* be preserved.
>>>
>>
>> For a legacy boot yes. But when you boot with DT, you should not need
>> them.
> 
> It is not a matter of how the system is booted, rather what all the
> drivers are expecting...
> 
>> This is certainly possible as several ARM platforms do this. You
>> need to start with minimal set of drivers enabled for DT and add them
>> back in 1 by 1.
>>
> 
> What I don't understand about this is what happens during the transition?
> 
> What if a shared interrupt were referred from one non-OF driver by its
> symbolic OCTEON_IRQ_? value, and from a second driver by its hwirq value
> extracted from the DT?  In that case you would be referring to the same
> interrupt line by two different irq values, clearly that should be
> prevented.
> 
> At a minimum, the change made for each converted driver would have to
> include: removing the OCTEON_IRQ_? values,  Maintain a list of hwirqs
> that are outside of the domain and report this by the.map() function,
> and then update this list.

Drivers should only deal with Linux irq numbers and should only get them
as a resource passed into the driver probe. This is true with or without
DT. I only see 2 drivers directly using OCTEON_IRQ defines: ethernet and
watchdog. Fix them. The serial setup code needs to use resources as
well. The other place you will see irq defines is platform device
declarations (i2c is an example in your case). For DT boot, you would
not register the static devices and the devices should be created
dynamically.

Rob

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2012-03-10 16:20 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-01  0:56 [PATCH v6 0/5] MIPS: Octeon: Use Device Tree David Daney
2012-03-01  0:56 ` [PATCH v6 1/5] MIPS: Octeon: Add device tree source files David Daney
2012-03-01  0:56 ` [PATCH v6 2/5] MIPS: Don't define early_init_devtree() and device_tree_init() in prom.c for CPU_CAVIUM_OCTEON David Daney
2012-03-01  0:57 ` [PATCH v6 3/5] MIPS: Octeon: Add irq handlers for GPIO interrupts David Daney
2012-03-01  0:57 ` [PATCH v6 4/5] MIPS: Octeon: Setup irq_domains for interrupts David Daney
2012-03-02 14:22   ` Rob Herring
2012-03-02 18:03     ` David Daney
2012-03-02 19:07       ` Grant Likely
2012-03-02 19:29         ` David Daney
2012-03-03 19:35           ` Rob Herring
2012-03-04  5:09             ` David Daney
2012-03-09  5:57               ` Grant Likely
2012-03-09 18:45                 ` David Daney
2012-03-09 21:07                   ` Rob Herring
2012-03-10  0:08                     ` David Daney
2012-03-10 16:20                       ` Rob Herring
2012-03-03 19:38       ` Rob Herring
2012-03-04  5:41         ` David Daney
2012-03-02 19:02   ` Grant Likely
2012-03-01  0:57 ` [PATCH v6 5/5] MIPS: Octeon: Initialize and fixup device tree David Daney

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).