diff mbox

[v0,06/10] arm: orion5x: Add DT-based support for Netgear WNR854T

Message ID 1468679348-10522-7-git-send-email-jm@lentin.co.uk (mailing list archive)
State New, archived
Headers show

Commit Message

Jamie Lentin July 16, 2016, 2:29 p.m. UTC
This is a router based on the mv88f5181 chipset.

http://www.netgear.com/support/product/WNR854T.aspx
http://wiki.openwrt.org/toh/netgear/wnr854t

Signed-off-by: Jamie Lentin <jm@lentin.co.uk>
---
 .../bindings/arm/marvell/marvell,orion5x.txt       |   1 +
 arch/arm/boot/dts/Makefile                         |   1 +
 arch/arm/boot/dts/orion5x-netgear-wnr854t.dts      | 200 +++++++++++++++++++++
 arch/arm/mach-orion5x/Kconfig                      |   6 +
 arch/arm/mach-orion5x/Makefile                     |   1 +
 arch/arm/mach-orion5x/board-wnr854t.c              |  78 ++++++++
 6 files changed, 287 insertions(+)
 create mode 100644 arch/arm/boot/dts/orion5x-netgear-wnr854t.dts
 create mode 100644 arch/arm/mach-orion5x/board-wnr854t.c

Comments

Andrew Lunn July 16, 2016, 4:34 p.m. UTC | #1
> +	chosen {
> +		bootargs = "console=ttyS0,115200n8 earlyprintk";
> +		linux,stdout-path = &uart0;
> +	};

You can put the board rate etc in the stdout-patch. Something like:

                stdout-path = "serial0:115200n8";

> +	gpio-leds {
> +		compatible = "gpio-leds";
> +		pinctrl-0 = <&pmx_power_led &pmx_power_led_blink &pmx_wan_led>;
> +		pinctrl-names = "default";
> +
> +		led@0 {
> +			label = "power:green";

Documentation/leds/leds-class.txt says:

LED Device Naming
=================

Is currently of the form:

"devicename:colour:function"

> +	dsa@0 {
> +		compatible = "marvell,dsa";
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		dsa,ethernet = <&ethport>;
> +		dsa,mii-bus = <&mdio>;
> +
> +		switch@0 {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +			reg = <0 0>;	/* MDIO address 0, switch 0 in tree */
> +
> +			port@0 {
> +				reg = <0>;
> +				label = "lan3";
> +			};
> +
> +			port@1 {
> +				reg = <1>;
> +				label = "lan4";
> +			};
> +
> +			port@2 {
> +				reg = <2>;
> +				label = "wan";
> +			};
> +
> +			port@3 {
> +				reg = <3>;
> +				label = "cpu";
> +			};
> +
> +			port@5 {
> +				reg = <5>;
> +				label = "lan1";
> +			};
> +
> +			port@7 {
> +				reg = <7>;
> +				label = "lan2";
> +			};
> +		};
> +	};
> +};

This all looks sensible, if a bit mixed up. Lets discuss the switch
issue in a different thread.

> +&devbus_bootcs {
> +	status = "okay";
> +
> +	devbus,keep-config;
> +
> +	flash@0 {
> +		compatible = "cfi-flash";
> +		reg = <0 0x800000>;
> +		bank-width = <1>;
> +		#address-cells = <1>;
> +		#size-cells = <1>;

Documentation/devicetree/bindings/mtd/partition.txt says the
partitions should be placed under a partitions node. There are some
conditions when that does not work. So please try it, and if it does
not, ignore my comment...

> +
> +		partition@0 {
> +			label = "kernel";
> +			reg = <0x0 0x100000>;
> +		};
> +
> +		partition@100000 {
> +			label = "rootfs";
> +			reg = <0x100000 0x660000>;
> +		};
> +
> +		partition@760000 {
> +			label = "uboot_env";
> +			reg = <0x760000 0x20000>;
> +		};
> +
> +		partition@780000 {
> +			label = "uboot";
> +			reg = <0x780000 0x80000>;
> +			read-only;
> +		};
> +	};
> +};

> +&pinctrl {
> +	pinctrl-0 = <&pmx_pci_gpios &pmx_ge>;
> +	pinctrl-names = "default";
> +
> +	pmx_power_led: pmx-power-led {
> +		marvell,pins = "mpp0";
> +		marvell,function = "gpio";
> +	};
> +
> +	pmx_reset_switch: pmx-reset-switch {
> +		marvell,pins = "mpp1";
> +		marvell,function = "gpio";
> +	};

Ah, this is missing from your DSA node. You can then add:

reset-gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;

inside the switch@0 node.

> +	pmx_ge: pmx-ge {
> +		marvell,pins = "mpp9", "mpp12",	"mpp13", "mpp14", "mpp15",
> +				"mpp16", "mpp17", "mpp18", "mpp19";
> +		marvell,function = "ge";
> +	};
> +};

This can go into the .dtsi file your previous patch added. 

> +
> +&uart0 {
> +	/* Pin 1: Tx, Pin 7: Rx, Pin 8: Gnd */
> +	status = "okay";

Nice to see the comment.

     Andrew
Andrew Lunn July 16, 2016, 4:39 p.m. UTC | #2
> +	pmx_reset_switch: pmx-reset-switch {
> +		marvell,pins = "mpp1";
> +		marvell,function = "gpio";
> +	};

Ah! I think i interpreted that wrong. This does not reset the Ethernet
switch. It is actually a switch on the front to reset the whole box?

How about calling it button, not switch?

    Andrew
Arnd Bergmann July 16, 2016, 7:10 p.m. UTC | #3
On Saturday, July 16, 2016 3:29:04 PM CEST Jamie Lentin wrote:
> +
> +#define WNR854T_PCI_SLOT0_OFFS	7
> +#define WNR854T_PCI_SLOT0_IRQ_PIN	4
> +
> +static void __init wnr854t_pci_preinit(void)
> +{
> +	int pin;
> +
> +	/*
> +	 * Configure PCI GPIO IRQ pins
> +	 */
> +	pin = WNR854T_PCI_SLOT0_IRQ_PIN;
> +	if (gpio_request(pin, "PCI Int") == 0) {
> +		if (gpio_direction_input(pin) == 0) {
> +			irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
> +		} else {
> +			pr_err("wnr854t_pci_preinit failed to set_irq_type pin %d\n",
> +				pin);
> +			gpio_free(pin);
> +		}
> +	} else {
> +		pr_err("wnr854t_pci_preinit failed to request gpio %d\n", pin);
> +	}
> +}
> +
> +static int __init wnr854t_pci_map_irq(const struct pci_dev *dev, u8 slot,
> +	u8 pin)
> +{
> +	int irq;
> +
> +	/*
> +	 * Check for devices with hard-wired IRQs.
> +	 */
> +	irq = orion5x_pci_map_irq(dev, slot, pin);
> +	if (irq != -1)
> +		return irq;
> +
> +	/*
> +	 * PCI IRQs are connected via GPIOs
> +	 */
> +	switch (slot - WNR854T_PCI_SLOT0_OFFS) {
> +	case 0:
> +		return gpio_to_irq(WNR854T_PCI_SLOT0_IRQ_PIN);
> +	default:
> +		return -1;
> +	}
> +}

The other patches all appear good to me, but I find this one suspicious.

Why are you not using the device tree for probing PCI? Is there anything
missing in drivers/pci/host/pci-mvebu.c, or do you just need help
describing it in DT?

	Arnd
Jamie Lentin July 17, 2016, 9:39 a.m. UTC | #4
On Sat, 16 Jul 2016, Arnd Bergmann wrote:

> On Saturday, July 16, 2016 3:29:04 PM CEST Jamie Lentin wrote:
>> +
>> +#define WNR854T_PCI_SLOT0_OFFS	7
>> +#define WNR854T_PCI_SLOT0_IRQ_PIN	4
>> +
>> +static void __init wnr854t_pci_preinit(void)
>> +{
>> +	int pin;
>> +
>> +	/*
>> +	 * Configure PCI GPIO IRQ pins
>> +	 */
>> +	pin = WNR854T_PCI_SLOT0_IRQ_PIN;
>> +	if (gpio_request(pin, "PCI Int") == 0) {
>> +		if (gpio_direction_input(pin) == 0) {
>> +			irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
>> +		} else {
>> +			pr_err("wnr854t_pci_preinit failed to set_irq_type pin %d\n",
>> +				pin);
>> +			gpio_free(pin);
>> +		}
>> +	} else {
>> +		pr_err("wnr854t_pci_preinit failed to request gpio %d\n", pin);
>> +	}
>> +}
>> +
>> +static int __init wnr854t_pci_map_irq(const struct pci_dev *dev, u8 slot,
>> +	u8 pin)
>> +{
>> +	int irq;
>> +
>> +	/*
>> +	 * Check for devices with hard-wired IRQs.
>> +	 */
>> +	irq = orion5x_pci_map_irq(dev, slot, pin);
>> +	if (irq != -1)
>> +		return irq;
>> +
>> +	/*
>> +	 * PCI IRQs are connected via GPIOs
>> +	 */
>> +	switch (slot - WNR854T_PCI_SLOT0_OFFS) {
>> +	case 0:
>> +		return gpio_to_irq(WNR854T_PCI_SLOT0_IRQ_PIN);
>> +	default:
>> +		return -1;
>> +	}
>> +}
>
> The other patches all appear good to me, but I find this one suspicious.
>
> Why are you not using the device tree for probing PCI? Is there anything
> missing in drivers/pci/host/pci-mvebu.c, or do you just need help
> describing it in DT?

Unlike the other SoC's supported by pci-mvebu.c, orion5x has one PCI port 
as well as a PCIe port. Given no other orion5x boards seem to use 
pci-mvebu, I'm assuming there's work to be done before the PCI port can be 
used via. pci-mvebu.c

This is something I can look into if there aren't patches out there, but 
wanted to get the rest into a reasonable state first.

>
> 	Arnd
>
Arnd Bergmann July 17, 2016, 8:41 p.m. UTC | #5
On Sunday, July 17, 2016 10:39:01 AM CEST Jamie Lentin wrote:
> On Sat, 16 Jul 2016, Arnd Bergmann wrote:

> > The other patches all appear good to me, but I find this one suspicious.
> >
> > Why are you not using the device tree for probing PCI? Is there anything
> > missing in drivers/pci/host/pci-mvebu.c, or do you just need help
> > describing it in DT?
> 
> Unlike the other SoC's supported by pci-mvebu.c, orion5x has one PCI port 
> as well as a PCIe port. Given no other orion5x boards seem to use 
> pci-mvebu, I'm assuming there's work to be done before the PCI port can be 
> used via. pci-mvebu.c
> 
> This is something I can look into if there aren't patches out there, but 
> wanted to get the rest into a reasonable state first.

Ok, I see your point. However, we also don't have any other Orion5x machines
using DT that rely on old probe method, and I this is something that
is particularly hard to retrofit later.

I would assume that the PCIe port should work out of the box with the driver
we have, but the PCI controller does not, and it will require some work.
Looking at https://wiki.openwrt.org/toh/netgear/wnr854t, I assume that
you want only PCI but not PCIe, correct?

The good news is that we can completely separate the two, we just have two
different PCI domains if both are enabled, so we just need to add a new
driver for the PCI port to drivers/pci/host. The pci_ops can be copied
from the existing driver, although a couple of minor cleanups would be
possible. The special handling of bus numbers and the rc_pci_fixup()
can probably just go away, and the latter part is particularly
important, because building a kernel with the fixup included might
break any system with a Marvell host bridge.

We also don't seem to need any MBUS window setup for the I/O and
memory spaces, which greatly simplifies the driver compared to the
pci-mvebu one, it would be a fairly straightforward implementation
based on pci-host-generic.c (which unfortunately just got way
more complicated and might need to go on a diet).

	Arnd
Rob Herring (Arm) July 17, 2016, 8:51 p.m. UTC | #6
On Sat, Jul 16, 2016 at 03:29:04PM +0100, Jamie Lentin wrote:
> This is a router based on the mv88f5181 chipset.
> 
> http://www.netgear.com/support/product/WNR854T.aspx
> http://wiki.openwrt.org/toh/netgear/wnr854t
> 
> Signed-off-by: Jamie Lentin <jm@lentin.co.uk>
> ---
>  .../bindings/arm/marvell/marvell,orion5x.txt       |   1 +
>  arch/arm/boot/dts/Makefile                         |   1 +
>  arch/arm/boot/dts/orion5x-netgear-wnr854t.dts      | 200 +++++++++++++++++++++
>  arch/arm/mach-orion5x/Kconfig                      |   6 +
>  arch/arm/mach-orion5x/Makefile                     |   1 +
>  arch/arm/mach-orion5x/board-wnr854t.c              |  78 ++++++++
>  6 files changed, 287 insertions(+)
>  create mode 100644 arch/arm/boot/dts/orion5x-netgear-wnr854t.dts
>  create mode 100644 arch/arm/mach-orion5x/board-wnr854t.c
> 
> diff --git a/Documentation/devicetree/bindings/arm/marvell/marvell,orion5x.txt b/Documentation/devicetree/bindings/arm/marvell/marvell,orion5x.txt
> index ff3c120..748a8f2 100644
> --- a/Documentation/devicetree/bindings/arm/marvell/marvell,orion5x.txt
> +++ b/Documentation/devicetree/bindings/arm/marvell/marvell,orion5x.txt
> @@ -22,3 +22,4 @@ board. Currently known boards are:
>  "lacie,d2-network"
>  "marvell,rd-88f5182-nas"
>  "maxtor,shared-storage-2"
> +"netgear,wnr854t"
> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
> index 95c1923..63b9202 100644
> --- a/arch/arm/boot/dts/Makefile
> +++ b/arch/arm/boot/dts/Makefile
> @@ -535,6 +535,7 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
>  	orion5x-linkstation-lswtgl.dtb \
>  	orion5x-lswsgl.dtb \
>  	orion5x-maxtor-shared-storage-2.dtb \
> +	orion5x-netgear-wnr854t.dtb \
>  	orion5x-rd88f5182-nas.dtb
>  dtb-$(CONFIG_ARCH_PRIMA2) += \
>  	prima2-evb.dtb
> diff --git a/arch/arm/boot/dts/orion5x-netgear-wnr854t.dts b/arch/arm/boot/dts/orion5x-netgear-wnr854t.dts
> new file mode 100644
> index 0000000..a8e89d8
> --- /dev/null
> +++ b/arch/arm/boot/dts/orion5x-netgear-wnr854t.dts
> @@ -0,0 +1,200 @@
> +/*
> + * Copyright (C) 2014 Jamie Lentin <jm@lentin.co.uk>

It's 2016 now.

> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +/dts-v1/;
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/input/input.h>
> +#include "orion5x-mv88f5181.dtsi"
> +
> +/ {
> +	model = "Netgear WNR854-t";
> +	compatible = "netgear,wnr854t", "marvell,orion5x-88f5181",
> +			"marvell,orion5x";
> +
> +	memory {
> +		reg = <0x00000000 0x2000000>; /* 32 MB */
> +	};
> +
> +	chosen {
> +		bootargs = "console=ttyS0,115200n8 earlyprintk";
> +		linux,stdout-path = &uart0;

As kind of mentioned, drop the linux prefix here.

> +	};
> +
> +	soc {
> +		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>,
> +			<MBUS_ID(0x09, 0x00) 0 0xf2200000 0x800>,
> +			<MBUS_ID(0x01, 0x0f) 0 0xf4000000 0x800000>;
> +	};
> +
> +	gpio-keys {
> +		compatible = "gpio-keys";
> +		pinctrl-0 = <&pmx_reset_switch>;
> +		pinctrl-names = "default";
> +
> +		reset {
> +			label = "Reset Button";
> +			linux,code = <KEY_RESTART>;
> +			gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
> +		};
> +	};
> +
> +	gpio-leds {
> +		compatible = "gpio-leds";
> +		pinctrl-0 = <&pmx_power_led &pmx_power_led_blink &pmx_wan_led>;
> +		pinctrl-names = "default";
> +
> +		led@0 {
> +			label = "power:green";
> +			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
> +		};
> +
> +		led@1 {
> +			label = "power:blink";
> +			gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
> +		};
> +
> +		led@2 {
> +			label = "wan:green";
> +			gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
> +		};
> +	};
> +
> +	dsa@0 {
> +		compatible = "marvell,dsa";
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +
> +		dsa,ethernet = <&ethport>;
> +		dsa,mii-bus = <&mdio>;
> +
> +		switch@0 {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +			reg = <0 0>;	/* MDIO address 0, switch 0 in tree */
> +
> +			port@0 {
> +				reg = <0>;
> +				label = "lan3";
> +			};
> +
> +			port@1 {
> +				reg = <1>;
> +				label = "lan4";
> +			};
> +
> +			port@2 {
> +				reg = <2>;
> +				label = "wan";
> +			};
> +
> +			port@3 {
> +				reg = <3>;
> +				label = "cpu";
> +			};
> +
> +			port@5 {
> +				reg = <5>;
> +				label = "lan1";
> +			};
> +
> +			port@7 {
> +				reg = <7>;
> +				label = "lan2";
> +			};
> +		};
> +	};
> +};
> +
> +&devbus_bootcs {
> +	status = "okay";
> +
> +	devbus,keep-config;
> +
> +	flash@0 {
> +		compatible = "cfi-flash";
> +		reg = <0 0x800000>;
> +		bank-width = <1>;
> +		#address-cells = <1>;
> +		#size-cells = <1>;
> +
> +		partition@0 {

The new recommended style adds a level here with a partitions node and 
the type of partitioning.

> +			label = "kernel";
> +			reg = <0x0 0x100000>;
> +		};
> +
> +		partition@100000 {
> +			label = "rootfs";
> +			reg = <0x100000 0x660000>;
> +		};
> +
> +		partition@760000 {
> +			label = "uboot_env";
> +			reg = <0x760000 0x20000>;
> +		};
> +
> +		partition@780000 {
> +			label = "uboot";
> +			reg = <0x780000 0x80000>;
> +			read-only;
> +		};
> +	};
> +};
> +
> +&mdio {
> +	status = "okay";
> +};
> +
> +&eth {
> +	status = "okay";
> +	ethernet-port@0 {
> +		speed = <1000>;
> +		duplex = <1>;
> +	};
> +};
> +
> +&pinctrl {
> +	pinctrl-0 = <&pmx_pci_gpios &pmx_ge>;
> +	pinctrl-names = "default";
> +
> +	pmx_power_led: pmx-power-led {
> +		marvell,pins = "mpp0";
> +		marvell,function = "gpio";
> +	};
> +
> +	pmx_reset_switch: pmx-reset-switch {
> +		marvell,pins = "mpp1";
> +		marvell,function = "gpio";
> +	};
> +
> +	pmx_power_led_blink: pmx-power-led-blink {
> +		marvell,pins = "mpp2";
> +		marvell,function = "gpio";
> +	};
> +
> +	pmx_wan_led: pmx-wan-led {
> +		marvell,pins = "mpp3";
> +		marvell,function = "gpio";
> +	};
> +
> +	pmx_pci_gpios: pmx-pci-gpios {
> +		marvell,pins = "mpp4";
> +		marvell,function = "gpio";
> +	};
> +
> +	pmx_ge: pmx-ge {
> +		marvell,pins = "mpp9", "mpp12",	"mpp13", "mpp14", "mpp15",
> +				"mpp16", "mpp17", "mpp18", "mpp19";
> +		marvell,function = "ge";
> +	};
> +};
> +
> +&uart0 {
> +	/* Pin 1: Tx, Pin 7: Rx, Pin 8: Gnd */
> +	status = "okay";
> +};
> diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
> index a2af158..1fdb95d 100644
> --- a/arch/arm/mach-orion5x/Kconfig
> +++ b/arch/arm/mach-orion5x/Kconfig
> @@ -151,6 +151,12 @@ config MACH_MSS2_DT
>  	  Say 'Y' here if you want your kernel to support the
>  	  Maxtor Shared Storage II platform.
>  
> +config MACH_WNR854T_DT

There should only be at most 1 kconfig entry for all orion5x DT based 
platforms.

> +	bool "Netgear WNR854T (Flattened Device Tree)"
> +	help
> +	  Say 'Y' here if you want your kernel to support the
> +	  Netgear WNR854T platform.
> +
>  config MACH_WNR854T
>  	bool "Netgear WNR854T"
>  	help
Thomas Petazzoni July 18, 2016, 9:44 a.m. UTC | #7
Hello,

On Sun, 17 Jul 2016 22:41:35 +0200, Arnd Bergmann wrote:

> I would assume that the PCIe port should work out of the box with the driver

Unfortunately, no. The PCIe on Orion5x requires a workaround for
reading/writing the PCI configuration space. Instead of doing MMIO
accesses to PCIE_CONF_ADDR_OFF / PCIE_CONF_DATA_OFF, you must map a
MBus window, which provides a memory-mapped view of the PCI
configuration space.

Definitely not impossible to implement, but the driver doesn't work
as-is.

> We also don't seem to need any MBUS window setup for the I/O and
> memory spaces, which greatly simplifies the driver compared to the
> pci-mvebu one, it would be a fairly straightforward implementation
> based on pci-host-generic.c (which unfortunately just got way
> more complicated and might need to go on a diet).

MBus windows are needed. See:

        mvebu_mbus_add_window_remap_by_id(ORION_MBUS_PCI_IO_TARGET,
                                          ORION_MBUS_PCI_IO_ATTR,
                                          ORION5X_PCI_IO_PHYS_BASE,
                                          ORION5X_PCI_IO_SIZE,
                                          ORION5X_PCI_IO_BUS_BASE);
        mvebu_mbus_add_window_by_id(ORION_MBUS_PCI_MEM_TARGET,
                                    ORION_MBUS_PCI_MEM_ATTR,
                                    ORION5X_PCI_MEM_PHYS_BASE,
                                    ORION5X_PCI_MEM_SIZE);

in orion5x_setup_wins().

Note that we already have some Orion5x converted to DT, and that use
PCI: board-rd88f5182.c is an example. So we could very well take Jamie
patches as-is, and move later to a DT-representation for PCI/PCIe.

Best regards,

Thomas
Arnd Bergmann July 18, 2016, 10:06 a.m. UTC | #8
On Monday, July 18, 2016 11:44:24 AM CEST Thomas Petazzoni wrote:
> 
> On Sun, 17 Jul 2016 22:41:35 +0200, Arnd Bergmann wrote:
> 
> > I would assume that the PCIe port should work out of the box with the driver
> 
> Unfortunately, no. The PCIe on Orion5x requires a workaround for
> reading/writing the PCI configuration space. Instead of doing MMIO
> accesses to PCIE_CONF_ADDR_OFF / PCIE_CONF_DATA_OFF, you must map a
> MBus window, which provides a memory-mapped view of the PCI
> configuration space.
> 
> Definitely not impossible to implement, but the driver doesn't work
> as-is.

Ok.

> > We also don't seem to need any MBUS window setup for the I/O and
> > memory spaces, which greatly simplifies the driver compared to the
> > pci-mvebu one, it would be a fairly straightforward implementation
> > based on pci-host-generic.c (which unfortunately just got way
> > more complicated and might need to go on a diet).
> 
> MBus windows are needed. See:
> 
>         mvebu_mbus_add_window_remap_by_id(ORION_MBUS_PCI_IO_TARGET,
>                                           ORION_MBUS_PCI_IO_ATTR,
>                                           ORION5X_PCI_IO_PHYS_BASE,
>                                           ORION5X_PCI_IO_SIZE,
>                                           ORION5X_PCI_IO_BUS_BASE);
>         mvebu_mbus_add_window_by_id(ORION_MBUS_PCI_MEM_TARGET,
>                                     ORION_MBUS_PCI_MEM_ATTR,
>                                     ORION5X_PCI_MEM_PHYS_BASE,
>                                     ORION5X_PCI_MEM_SIZE);
> 
> in orion5x_setup_wins().

Ok, I was just looking at the wrong file, as they are set up from
common.c, not pci.c.

> Note that we already have some Orion5x converted to DT, and that use
> PCI: board-rd88f5182.c is an example. So we could very well take Jamie
> patches as-is, and move later to a DT-representation for PCI/PCIe.

Ah, I thought all the DT users were moved to mach-mvebu. I agree
this new patch isn't introducing anything we don't already have then,
so we can just take it, but the conversion will not be nice when
we do that.

I was also hoping that we could get to the point where pci_common_init()
is only used for legacy machines without DT and without multiplatform,
it seems I missed a couple of users here.

	Arnd
Jamie Lentin July 19, 2016, 9:40 a.m. UTC | #9
On Mon, 18 Jul 2016, Arnd Bergmann wrote:

> On Monday, July 18, 2016 11:44:24 AM CEST Thomas Petazzoni wrote:
>>
>> On Sun, 17 Jul 2016 22:41:35 +0200, Arnd Bergmann wrote:
>>
>>> I would assume that the PCIe port should work out of the box with the driver
>>
>> Unfortunately, no. The PCIe on Orion5x requires a workaround for
>> reading/writing the PCI configuration space. Instead of doing MMIO
>> accesses to PCIE_CONF_ADDR_OFF / PCIE_CONF_DATA_OFF, you must map a
>> MBus window, which provides a memory-mapped view of the PCI
>> configuration space.
>>
>> Definitely not impossible to implement, but the driver doesn't work
>> as-is.
>
> Ok.

Unfortunately this isn't something I can test as the PCIe port on the SoC 
doesn't go anywhere in my case.

>>> We also don't seem to need any MBUS window setup for the I/O and
>>> memory spaces, which greatly simplifies the driver compared to the
>>> pci-mvebu one, it would be a fairly straightforward implementation
>>> based on pci-host-generic.c (which unfortunately just got way
>>> more complicated and might need to go on a diet).
>>
>> MBus windows are needed. See:
>>
>>         mvebu_mbus_add_window_remap_by_id(ORION_MBUS_PCI_IO_TARGET,
>>                                           ORION_MBUS_PCI_IO_ATTR,
>>                                           ORION5X_PCI_IO_PHYS_BASE,
>>                                           ORION5X_PCI_IO_SIZE,
>>                                           ORION5X_PCI_IO_BUS_BASE);
>>         mvebu_mbus_add_window_by_id(ORION_MBUS_PCI_MEM_TARGET,
>>                                     ORION_MBUS_PCI_MEM_ATTR,
>>                                     ORION5X_PCI_MEM_PHYS_BASE,
>>                                     ORION5X_PCI_MEM_SIZE);
>>
>> in orion5x_setup_wins().
>
> Ok, I was just looking at the wrong file, as they are set up from
> common.c, not pci.c.
>
>> Note that we already have some Orion5x converted to DT, and that use
>> PCI: board-rd88f5182.c is an example. So we could very well take Jamie
>> patches as-is, and move later to a DT-representation for PCI/PCIe.
>
> Ah, I thought all the DT users were moved to mach-mvebu. I agree
> this new patch isn't introducing anything we don't already have then,
> so we can just take it, but the conversion will not be nice when
> we do that.

Yes, board-wnr854t.c is a clone of the existing board-rd88f5182.c. 
Although I'd presume that it too would need late_initcall() or somesuch 
mechanism to probe PCI once the GPIO controller is available.

> I was also hoping that we could get to the point where pci_common_init()
> is only used for legacy machines without DT and without multiplatform,
> it seems I missed a couple of users here.
>
> 	Arnd
>
Jamie Lentin July 19, 2016, 9:46 a.m. UTC | #10
On Sun, 17 Jul 2016, Rob Herring wrote:

> On Sat, Jul 16, 2016 at 03:29:04PM +0100, Jamie Lentin wrote:
>> This is a router based on the mv88f5181 chipset.
>>
>> http://www.netgear.com/support/product/WNR854T.aspx
>> http://wiki.openwrt.org/toh/netgear/wnr854t
>>
>> Signed-off-by: Jamie Lentin <jm@lentin.co.uk>
>> ---
>>  .../bindings/arm/marvell/marvell,orion5x.txt       |   1 +
>>  arch/arm/boot/dts/Makefile                         |   1 +
>>  arch/arm/boot/dts/orion5x-netgear-wnr854t.dts      | 200 +++++++++++++++++++++
>>  arch/arm/mach-orion5x/Kconfig                      |   6 +
>>  arch/arm/mach-orion5x/Makefile                     |   1 +
>>  arch/arm/mach-orion5x/board-wnr854t.c              |  78 ++++++++
>>  6 files changed, 287 insertions(+)
>>  create mode 100644 arch/arm/boot/dts/orion5x-netgear-wnr854t.dts
>>  create mode 100644 arch/arm/mach-orion5x/board-wnr854t.c
>>
>> diff --git a/Documentation/devicetree/bindings/arm/marvell/marvell,orion5x.txt b/Documentation/devicetree/bindings/arm/marvell/marvell,orion5x.txt
>> index ff3c120..748a8f2 100644
>> --- a/Documentation/devicetree/bindings/arm/marvell/marvell,orion5x.txt
>> +++ b/Documentation/devicetree/bindings/arm/marvell/marvell,orion5x.txt
>> @@ -22,3 +22,4 @@ board. Currently known boards are:
>>  "lacie,d2-network"
>>  "marvell,rd-88f5182-nas"
>>  "maxtor,shared-storage-2"
>> +"netgear,wnr854t"
>> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
>> index 95c1923..63b9202 100644
>> --- a/arch/arm/boot/dts/Makefile
>> +++ b/arch/arm/boot/dts/Makefile
>> @@ -535,6 +535,7 @@ dtb-$(CONFIG_ARCH_ORION5X) += \
>>  	orion5x-linkstation-lswtgl.dtb \
>>  	orion5x-lswsgl.dtb \
>>  	orion5x-maxtor-shared-storage-2.dtb \
>> +	orion5x-netgear-wnr854t.dtb \
>>  	orion5x-rd88f5182-nas.dtb
>>  dtb-$(CONFIG_ARCH_PRIMA2) += \
>>  	prima2-evb.dtb
>> diff --git a/arch/arm/boot/dts/orion5x-netgear-wnr854t.dts b/arch/arm/boot/dts/orion5x-netgear-wnr854t.dts
>> new file mode 100644
>> index 0000000..a8e89d8
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/orion5x-netgear-wnr854t.dts
>> @@ -0,0 +1,200 @@
>> +/*
>> + * Copyright (C) 2014 Jamie Lentin <jm@lentin.co.uk>
>
> It's 2016 now.
>
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + */
>> +
>> +/dts-v1/;
>> +
>> +#include <dt-bindings/gpio/gpio.h>
>> +#include <dt-bindings/input/input.h>
>> +#include "orion5x-mv88f5181.dtsi"
>> +
>> +/ {
>> +	model = "Netgear WNR854-t";
>> +	compatible = "netgear,wnr854t", "marvell,orion5x-88f5181",
>> +			"marvell,orion5x";
>> +
>> +	memory {
>> +		reg = <0x00000000 0x2000000>; /* 32 MB */
>> +	};
>> +
>> +	chosen {
>> +		bootargs = "console=ttyS0,115200n8 earlyprintk";
>> +		linux,stdout-path = &uart0;
>
> As kind of mentioned, drop the linux prefix here.
>
>> +	};
>> +
>> +	soc {
>> +		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>,
>> +			<MBUS_ID(0x09, 0x00) 0 0xf2200000 0x800>,
>> +			<MBUS_ID(0x01, 0x0f) 0 0xf4000000 0x800000>;
>> +	};
>> +
>> +	gpio-keys {
>> +		compatible = "gpio-keys";
>> +		pinctrl-0 = <&pmx_reset_switch>;
>> +		pinctrl-names = "default";
>> +
>> +		reset {
>> +			label = "Reset Button";
>> +			linux,code = <KEY_RESTART>;
>> +			gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
>> +		};
>> +	};
>> +
>> +	gpio-leds {
>> +		compatible = "gpio-leds";
>> +		pinctrl-0 = <&pmx_power_led &pmx_power_led_blink &pmx_wan_led>;
>> +		pinctrl-names = "default";
>> +
>> +		led@0 {
>> +			label = "power:green";
>> +			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
>> +		};
>> +
>> +		led@1 {
>> +			label = "power:blink";
>> +			gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
>> +		};
>> +
>> +		led@2 {
>> +			label = "wan:green";
>> +			gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
>> +		};
>> +	};
>> +
>> +	dsa@0 {
>> +		compatible = "marvell,dsa";
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +
>> +		dsa,ethernet = <&ethport>;
>> +		dsa,mii-bus = <&mdio>;
>> +
>> +		switch@0 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +			reg = <0 0>;	/* MDIO address 0, switch 0 in tree */
>> +
>> +			port@0 {
>> +				reg = <0>;
>> +				label = "lan3";
>> +			};
>> +
>> +			port@1 {
>> +				reg = <1>;
>> +				label = "lan4";
>> +			};
>> +
>> +			port@2 {
>> +				reg = <2>;
>> +				label = "wan";
>> +			};
>> +
>> +			port@3 {
>> +				reg = <3>;
>> +				label = "cpu";
>> +			};
>> +
>> +			port@5 {
>> +				reg = <5>;
>> +				label = "lan1";
>> +			};
>> +
>> +			port@7 {
>> +				reg = <7>;
>> +				label = "lan2";
>> +			};
>> +		};
>> +	};
>> +};
>> +
>> +&devbus_bootcs {
>> +	status = "okay";
>> +
>> +	devbus,keep-config;
>> +
>> +	flash@0 {
>> +		compatible = "cfi-flash";
>> +		reg = <0 0x800000>;
>> +		bank-width = <1>;
>> +		#address-cells = <1>;
>> +		#size-cells = <1>;
>> +
>> +		partition@0 {
>
> The new recommended style adds a level here with a partitions node and
> the type of partitioning.
>
>> +			label = "kernel";
>> +			reg = <0x0 0x100000>;
>> +		};
>> +
>> +		partition@100000 {
>> +			label = "rootfs";
>> +			reg = <0x100000 0x660000>;
>> +		};
>> +
>> +		partition@760000 {
>> +			label = "uboot_env";
>> +			reg = <0x760000 0x20000>;
>> +		};
>> +
>> +		partition@780000 {
>> +			label = "uboot";
>> +			reg = <0x780000 0x80000>;
>> +			read-only;
>> +		};
>> +	};
>> +};
>> +
>> +&mdio {
>> +	status = "okay";
>> +};
>> +
>> +&eth {
>> +	status = "okay";
>> +	ethernet-port@0 {
>> +		speed = <1000>;
>> +		duplex = <1>;
>> +	};
>> +};
>> +
>> +&pinctrl {
>> +	pinctrl-0 = <&pmx_pci_gpios &pmx_ge>;
>> +	pinctrl-names = "default";
>> +
>> +	pmx_power_led: pmx-power-led {
>> +		marvell,pins = "mpp0";
>> +		marvell,function = "gpio";
>> +	};
>> +
>> +	pmx_reset_switch: pmx-reset-switch {
>> +		marvell,pins = "mpp1";
>> +		marvell,function = "gpio";
>> +	};
>> +
>> +	pmx_power_led_blink: pmx-power-led-blink {
>> +		marvell,pins = "mpp2";
>> +		marvell,function = "gpio";
>> +	};
>> +
>> +	pmx_wan_led: pmx-wan-led {
>> +		marvell,pins = "mpp3";
>> +		marvell,function = "gpio";
>> +	};
>> +
>> +	pmx_pci_gpios: pmx-pci-gpios {
>> +		marvell,pins = "mpp4";
>> +		marvell,function = "gpio";
>> +	};
>> +
>> +	pmx_ge: pmx-ge {
>> +		marvell,pins = "mpp9", "mpp12",	"mpp13", "mpp14", "mpp15",
>> +				"mpp16", "mpp17", "mpp18", "mpp19";
>> +		marvell,function = "ge";
>> +	};
>> +};
>> +
>> +&uart0 {
>> +	/* Pin 1: Tx, Pin 7: Rx, Pin 8: Gnd */
>> +	status = "okay";
>> +};
>> diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
>> index a2af158..1fdb95d 100644
>> --- a/arch/arm/mach-orion5x/Kconfig
>> +++ b/arch/arm/mach-orion5x/Kconfig
>> @@ -151,6 +151,12 @@ config MACH_MSS2_DT
>>  	  Say 'Y' here if you want your kernel to support the
>>  	  Maxtor Shared Storage II platform.
>>
>> +config MACH_WNR854T_DT
>
> There should only be at most 1 kconfig entry for all orion5x DT based
> platforms.

Even though it needs arch/arm/mach-orion5x/board-wnr854t.c to init the 
PCI? orion5x currently has other board _DT options, I presumed for this 
reason.

>> +	bool "Netgear WNR854T (Flattened Device Tree)"
>> +	help
>> +	  Say 'Y' here if you want your kernel to support the
>> +	  Netgear WNR854T platform.
>> +
>>  config MACH_WNR854T
>>  	bool "Netgear WNR854T"
>>  	help
>
Arnd Bergmann July 19, 2016, 9:46 a.m. UTC | #11
On Tuesday, July 19, 2016 10:40:16 AM CEST Jamie Lentin wrote:
> On Mon, 18 Jul 2016, Arnd Bergmann wrote:
> 
> > On Monday, July 18, 2016 11:44:24 AM CEST Thomas Petazzoni wrote:
> >>
> >> On Sun, 17 Jul 2016 22:41:35 +0200, Arnd Bergmann wrote:
> >>
> >>> I would assume that the PCIe port should work out of the box with the driver
> >>
> >> Unfortunately, no. The PCIe on Orion5x requires a workaround for
> >> reading/writing the PCI configuration space. Instead of doing MMIO
> >> accesses to PCIE_CONF_ADDR_OFF / PCIE_CONF_DATA_OFF, you must map a
> >> MBus window, which provides a memory-mapped view of the PCI
> >> configuration space.
> >>
> >> Definitely not impossible to implement, but the driver doesn't work
> >> as-is.
> >
> > Ok.
> 
> Unfortunately this isn't something I can test as the PCIe port on the SoC 
> doesn't go anywhere in my case.

As I said, this wouldn't be a problem: we should consider the PCI and PCIe
ports on this chip as completely separate anyway, so we can work on
the drivers independently.

> >>> We also don't seem to need any MBUS window setup for the I/O and
> >>> memory spaces, which greatly simplifies the driver compared to the
> >>> pci-mvebu one, it would be a fairly straightforward implementation
> >>> based on pci-host-generic.c (which unfortunately just got way
> >>> more complicated and might need to go on a diet).
> >>
> >> MBus windows are needed. See:
> >>
> >>         mvebu_mbus_add_window_remap_by_id(ORION_MBUS_PCI_IO_TARGET,
> >>                                           ORION_MBUS_PCI_IO_ATTR,
> >>                                           ORION5X_PCI_IO_PHYS_BASE,
> >>                                           ORION5X_PCI_IO_SIZE,
> >>                                           ORION5X_PCI_IO_BUS_BASE);
> >>         mvebu_mbus_add_window_by_id(ORION_MBUS_PCI_MEM_TARGET,
> >>                                     ORION_MBUS_PCI_MEM_ATTR,
> >>                                     ORION5X_PCI_MEM_PHYS_BASE,
> >>                                     ORION5X_PCI_MEM_SIZE);
> >>
> >> in orion5x_setup_wins().
> >
> > Ok, I was just looking at the wrong file, as they are set up from
> > common.c, not pci.c.
> >
> >> Note that we already have some Orion5x converted to DT, and that use
> >> PCI: board-rd88f5182.c is an example. So we could very well take Jamie
> >> patches as-is, and move later to a DT-representation for PCI/PCIe.
> >
> > Ah, I thought all the DT users were moved to mach-mvebu. I agree
> > this new patch isn't introducing anything we don't already have then,
> > so we can just take it, but the conversion will not be nice when
> > we do that.
> 
> Yes, board-wnr854t.c is a clone of the existing board-rd88f5182.c. 
> Although I'd presume that it too would need late_initcall() or somesuch 
> mechanism to probe PCI once the GPIO controller is available.

Deferred probing should be fine once the driver is migrated from
pci_common_init() to registering the host bridge directly.

	Arnd
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/arm/marvell/marvell,orion5x.txt b/Documentation/devicetree/bindings/arm/marvell/marvell,orion5x.txt
index ff3c120..748a8f2 100644
--- a/Documentation/devicetree/bindings/arm/marvell/marvell,orion5x.txt
+++ b/Documentation/devicetree/bindings/arm/marvell/marvell,orion5x.txt
@@ -22,3 +22,4 @@  board. Currently known boards are:
 "lacie,d2-network"
 "marvell,rd-88f5182-nas"
 "maxtor,shared-storage-2"
+"netgear,wnr854t"
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 95c1923..63b9202 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -535,6 +535,7 @@  dtb-$(CONFIG_ARCH_ORION5X) += \
 	orion5x-linkstation-lswtgl.dtb \
 	orion5x-lswsgl.dtb \
 	orion5x-maxtor-shared-storage-2.dtb \
+	orion5x-netgear-wnr854t.dtb \
 	orion5x-rd88f5182-nas.dtb
 dtb-$(CONFIG_ARCH_PRIMA2) += \
 	prima2-evb.dtb
diff --git a/arch/arm/boot/dts/orion5x-netgear-wnr854t.dts b/arch/arm/boot/dts/orion5x-netgear-wnr854t.dts
new file mode 100644
index 0000000..a8e89d8
--- /dev/null
+++ b/arch/arm/boot/dts/orion5x-netgear-wnr854t.dts
@@ -0,0 +1,200 @@ 
+/*
+ * Copyright (C) 2014 Jamie Lentin <jm@lentin.co.uk>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "orion5x-mv88f5181.dtsi"
+
+/ {
+	model = "Netgear WNR854-t";
+	compatible = "netgear,wnr854t", "marvell,orion5x-88f5181",
+			"marvell,orion5x";
+
+	memory {
+		reg = <0x00000000 0x2000000>; /* 32 MB */
+	};
+
+	chosen {
+		bootargs = "console=ttyS0,115200n8 earlyprintk";
+		linux,stdout-path = &uart0;
+	};
+
+	soc {
+		ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000>,
+			<MBUS_ID(0x09, 0x00) 0 0xf2200000 0x800>,
+			<MBUS_ID(0x01, 0x0f) 0 0xf4000000 0x800000>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+		pinctrl-0 = <&pmx_reset_switch>;
+		pinctrl-names = "default";
+
+		reset {
+			label = "Reset Button";
+			linux,code = <KEY_RESTART>;
+			gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+		pinctrl-0 = <&pmx_power_led &pmx_power_led_blink &pmx_wan_led>;
+		pinctrl-names = "default";
+
+		led@0 {
+			label = "power:green";
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+
+		led@1 {
+			label = "power:blink";
+			gpios = <&gpio0 2 GPIO_ACTIVE_LOW>;
+		};
+
+		led@2 {
+			label = "wan:green";
+			gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	dsa@0 {
+		compatible = "marvell,dsa";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		dsa,ethernet = <&ethport>;
+		dsa,mii-bus = <&mdio>;
+
+		switch@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0 0>;	/* MDIO address 0, switch 0 in tree */
+
+			port@0 {
+				reg = <0>;
+				label = "lan3";
+			};
+
+			port@1 {
+				reg = <1>;
+				label = "lan4";
+			};
+
+			port@2 {
+				reg = <2>;
+				label = "wan";
+			};
+
+			port@3 {
+				reg = <3>;
+				label = "cpu";
+			};
+
+			port@5 {
+				reg = <5>;
+				label = "lan1";
+			};
+
+			port@7 {
+				reg = <7>;
+				label = "lan2";
+			};
+		};
+	};
+};
+
+&devbus_bootcs {
+	status = "okay";
+
+	devbus,keep-config;
+
+	flash@0 {
+		compatible = "cfi-flash";
+		reg = <0 0x800000>;
+		bank-width = <1>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		partition@0 {
+			label = "kernel";
+			reg = <0x0 0x100000>;
+		};
+
+		partition@100000 {
+			label = "rootfs";
+			reg = <0x100000 0x660000>;
+		};
+
+		partition@760000 {
+			label = "uboot_env";
+			reg = <0x760000 0x20000>;
+		};
+
+		partition@780000 {
+			label = "uboot";
+			reg = <0x780000 0x80000>;
+			read-only;
+		};
+	};
+};
+
+&mdio {
+	status = "okay";
+};
+
+&eth {
+	status = "okay";
+	ethernet-port@0 {
+		speed = <1000>;
+		duplex = <1>;
+	};
+};
+
+&pinctrl {
+	pinctrl-0 = <&pmx_pci_gpios &pmx_ge>;
+	pinctrl-names = "default";
+
+	pmx_power_led: pmx-power-led {
+		marvell,pins = "mpp0";
+		marvell,function = "gpio";
+	};
+
+	pmx_reset_switch: pmx-reset-switch {
+		marvell,pins = "mpp1";
+		marvell,function = "gpio";
+	};
+
+	pmx_power_led_blink: pmx-power-led-blink {
+		marvell,pins = "mpp2";
+		marvell,function = "gpio";
+	};
+
+	pmx_wan_led: pmx-wan-led {
+		marvell,pins = "mpp3";
+		marvell,function = "gpio";
+	};
+
+	pmx_pci_gpios: pmx-pci-gpios {
+		marvell,pins = "mpp4";
+		marvell,function = "gpio";
+	};
+
+	pmx_ge: pmx-ge {
+		marvell,pins = "mpp9", "mpp12",	"mpp13", "mpp14", "mpp15",
+				"mpp16", "mpp17", "mpp18", "mpp19";
+		marvell,function = "ge";
+	};
+};
+
+&uart0 {
+	/* Pin 1: Tx, Pin 7: Rx, Pin 8: Gnd */
+	status = "okay";
+};
diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
index a2af158..1fdb95d 100644
--- a/arch/arm/mach-orion5x/Kconfig
+++ b/arch/arm/mach-orion5x/Kconfig
@@ -151,6 +151,12 @@  config MACH_MSS2_DT
 	  Say 'Y' here if you want your kernel to support the
 	  Maxtor Shared Storage II platform.
 
+config MACH_WNR854T_DT
+	bool "Netgear WNR854T (Flattened Device Tree)"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  Netgear WNR854T platform.
+
 config MACH_WNR854T
 	bool "Netgear WNR854T"
 	help
diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile
index 4b2502b..9dff2d3 100644
--- a/arch/arm/mach-orion5x/Makefile
+++ b/arch/arm/mach-orion5x/Makefile
@@ -24,3 +24,4 @@  obj-$(CONFIG_ARCH_ORION5X_DT)		+= board-dt.o
 obj-$(CONFIG_MACH_D2NET_DT)	+= board-d2net.o
 obj-$(CONFIG_MACH_MSS2_DT)	+= board-mss2.o
 obj-$(CONFIG_MACH_RD88F5182_DT)	+= board-rd88f5182.o
+obj-$(CONFIG_MACH_WNR854T_DT)	+= board-wnr854t.o
diff --git a/arch/arm/mach-orion5x/board-wnr854t.c b/arch/arm/mach-orion5x/board-wnr854t.c
new file mode 100644
index 0000000..c506e33
--- /dev/null
+++ b/arch/arm/mach-orion5x/board-wnr854t.c
@@ -0,0 +1,78 @@ 
+/*
+ * Netgear WNR854T PCI setup
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/pci.h>
+#include <asm/mach/pci.h>
+#include "common.h"
+#include "orion5x.h"
+
+#define WNR854T_PCI_SLOT0_OFFS	7
+#define WNR854T_PCI_SLOT0_IRQ_PIN	4
+
+static void __init wnr854t_pci_preinit(void)
+{
+	int pin;
+
+	/*
+	 * Configure PCI GPIO IRQ pins
+	 */
+	pin = WNR854T_PCI_SLOT0_IRQ_PIN;
+	if (gpio_request(pin, "PCI Int") == 0) {
+		if (gpio_direction_input(pin) == 0) {
+			irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+		} else {
+			pr_err("wnr854t_pci_preinit failed to set_irq_type pin %d\n",
+				pin);
+			gpio_free(pin);
+		}
+	} else {
+		pr_err("wnr854t_pci_preinit failed to request gpio %d\n", pin);
+	}
+}
+
+static int __init wnr854t_pci_map_irq(const struct pci_dev *dev, u8 slot,
+	u8 pin)
+{
+	int irq;
+
+	/*
+	 * Check for devices with hard-wired IRQs.
+	 */
+	irq = orion5x_pci_map_irq(dev, slot, pin);
+	if (irq != -1)
+		return irq;
+
+	/*
+	 * PCI IRQs are connected via GPIOs
+	 */
+	switch (slot - WNR854T_PCI_SLOT0_OFFS) {
+	case 0:
+		return gpio_to_irq(WNR854T_PCI_SLOT0_IRQ_PIN);
+	default:
+		return -1;
+	}
+}
+
+static struct hw_pci wnr854t_pci __initdata = {
+	.nr_controllers	= 2,
+	.preinit	= wnr854t_pci_preinit,
+	.setup		= orion5x_pci_sys_setup,
+	.scan		= orion5x_pci_sys_scan_bus,
+	.map_irq	= wnr854t_pci_map_irq,
+};
+
+static int __init wnr854t_pci_init(void)
+{
+	if (of_machine_is_compatible("netgear,wnr854t"))
+		pci_common_init(&wnr854t_pci);
+
+	return 0;
+}
+/* NB: Use late_initcall so we can gpio_request() without being deferred */
+late_initcall(wnr854t_pci_init);