--- /dev/null
+From 6c52eba54044791592aefd139bdc2a7b6127e981 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Wed, 17 Apr 2013 16:51:34 -0300
+Subject: [PATCH 001/203] ARM: mvebu: Add support for USB storage class in
+ mvebu_defconfig
+
+Some boards can have built-in USB storage class controllers so
+it's better to have this option included by default.
+
+Currently this option is needed to support built-in USB MMC controller
+found in Globalscale Mirabox board.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/configs/mvebu_defconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/configs/mvebu_defconfig
++++ b/arch/arm/configs/mvebu_defconfig
+@@ -60,6 +60,7 @@ CONFIG_USB_SUPPORT=y
+ CONFIG_USB=y
+ CONFIG_USB_EHCI_HCD=y
+ CONFIG_USB_EHCI_ROOT_HUB_TT=y
++CONFIG_USB_STORAGE=y
+ CONFIG_MMC=y
+ CONFIG_MMC_MVSDIO=y
+ CONFIG_NEW_LEDS=y
--- /dev/null
+From cf6eb4599d60cb9fa81465aa018c71d11e19ea6a Mon Sep 17 00:00:00 2001
+From: Simon Baatz <gmbnomis@gmail.com>
+Date: Mon, 13 May 2013 23:18:58 +0200
+Subject: [PATCH 002/203] ARM: mvebu: Use standard MMC binding for all users of
+ mvsdio
+
+In order to prepare the switch to the standard MMC device tree parser
+for mvsdio, adapt all current uses of mvsdio in the dts files to the
+standard format.
+
+Signed-off-by: Simon Baatz <gmbnomis@gmail.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-370-db.dts | 1 +
+ arch/arm/boot/dts/armada-370-mirabox.dts | 1 +
+ arch/arm/boot/dts/armada-370-rd.dts | 1 +
+ arch/arm/boot/dts/armada-370-xp.dtsi | 4 ++++
+ arch/arm/boot/dts/armada-xp-db.dts | 1 +
+ arch/arm/boot/dts/kirkwood-dreamplug.dts | 1 +
+ arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts | 2 ++
+ arch/arm/boot/dts/kirkwood-mplcec4.dts | 2 +-
+ arch/arm/boot/dts/kirkwood-topkick.dts | 1 +
+ arch/arm/boot/dts/kirkwood.dtsi | 4 ++++
+ 10 files changed, 17 insertions(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/armada-370-db.dts
++++ b/arch/arm/boot/dts/armada-370-db.dts
+@@ -74,6 +74,7 @@
+ */
+ status = "disabled";
+ /* No CD or WP GPIOs */
++ broken-cd;
+ };
+
+ usb@50000 {
+--- a/arch/arm/boot/dts/armada-370-mirabox.dts
++++ b/arch/arm/boot/dts/armada-370-mirabox.dts
+@@ -99,6 +99,7 @@
+ * No CD or WP GPIOs: SDIO interface used for
+ * Wifi/Bluetooth chip
+ */
++ broken-cd;
+ };
+
+ usb@50000 {
+--- a/arch/arm/boot/dts/armada-370-rd.dts
++++ b/arch/arm/boot/dts/armada-370-rd.dts
+@@ -64,6 +64,7 @@
+ pinctrl-names = "default";
+ status = "okay";
+ /* No CD or WP GPIOs */
++ broken-cd;
+ };
+
+ usb@50000 {
+--- a/arch/arm/boot/dts/armada-370-xp.dtsi
++++ b/arch/arm/boot/dts/armada-370-xp.dtsi
+@@ -143,6 +143,10 @@
+ reg = <0xd4000 0x200>;
+ interrupts = <54>;
+ clocks = <&gateclk 17>;
++ bus-width = <4>;
++ cap-sdio-irq;
++ cap-sd-highspeed;
++ cap-mmc-highspeed;
+ status = "disabled";
+ };
+
+--- a/arch/arm/boot/dts/armada-xp-db.dts
++++ b/arch/arm/boot/dts/armada-xp-db.dts
+@@ -97,6 +97,7 @@
+ pinctrl-names = "default";
+ status = "okay";
+ /* No CD or WP GPIOs */
++ broken-cd;
+ };
+
+ usb@50000 {
+--- a/arch/arm/boot/dts/kirkwood-dreamplug.dts
++++ b/arch/arm/boot/dts/kirkwood-dreamplug.dts
+@@ -79,6 +79,7 @@
+ pinctrl-names = "default";
+ status = "okay";
+ /* No CD or WP GPIOs */
++ broken-cd;
+ };
+ };
+
+--- a/arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts
++++ b/arch/arm/boot/dts/kirkwood-guruplug-server-plus.dts
+@@ -72,6 +72,8 @@
+
+ mvsdio@90000 {
+ status = "okay";
++ /* No CD or WP GPIOs */
++ broken-cd;
+ };
+ };
+
+--- a/arch/arm/boot/dts/kirkwood-mplcec4.dts
++++ b/arch/arm/boot/dts/kirkwood-mplcec4.dts
+@@ -136,7 +136,7 @@
+ pinctrl-0 = <&pmx_sdio &pmx_sdio_cd>;
+ pinctrl-names = "default";
+ status = "okay";
+- cd-gpios = <&gpio1 15 0>;
++ cd-gpios = <&gpio1 15 1>;
+ /* No WP GPIO */
+ };
+ };
+--- a/arch/arm/boot/dts/kirkwood-topkick.dts
++++ b/arch/arm/boot/dts/kirkwood-topkick.dts
+@@ -154,6 +154,7 @@
+ pinctrl-names = "default";
+ status = "okay";
+ /* No CD or WP GPIOs */
++ broken-cd;
+ };
+ };
+
+--- a/arch/arm/boot/dts/kirkwood.dtsi
++++ b/arch/arm/boot/dts/kirkwood.dtsi
+@@ -200,6 +200,10 @@
+ reg = <0x90000 0x200>;
+ interrupts = <28>;
+ clocks = <&gate_clk 4>;
++ bus-width = <4>;
++ cap-sdio-irq;
++ cap-sd-highspeed;
++ cap-mmc-highspeed;
+ status = "disabled";
+ };
+ };
--- /dev/null
+From 74cd8c09ae416261d7595021fc8062836dc750a2 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Fri, 17 May 2013 08:09:58 -0300
+Subject: [PATCH 003/203] ARM: mvebu: Add support for NOR flash device on
+ Armada XP-DB board
+
+The Armada XP Development Board (DB-78460-BP) has a NOR flash device
+connected to the Device Bus. This commit adds the device tree node
+to support this device.
+
+This SoC supports a flexible and dynamic decoding window allocation
+scheme; but since this feature is still not implemented we need
+to specify the window base address in the device tree node itself.
+
+This base address has been selected in a completely arbitrary fashion.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-xp-db.dts | 32 ++++++++++++++++++++++++++++++++
+ 1 file changed, 32 insertions(+)
+
+--- a/arch/arm/boot/dts/armada-xp-db.dts
++++ b/arch/arm/boot/dts/armada-xp-db.dts
+@@ -30,6 +30,9 @@
+ };
+
+ soc {
++ ranges = <0 0 0xd0000000 0x100000 /* Internal registers 1MiB */
++ 0xf0000000 0 0xf0000000 0x1000000>; /* Device Bus, NOR 16MiB */
++
+ internal-regs {
+ serial@12000 {
+ clock-frequency = <250000000>;
+@@ -156,6 +159,35 @@
+ status = "okay";
+ };
+ };
++
++ devbus-bootcs@10400 {
++ status = "okay";
++ ranges = <0 0xf0000000 0x1000000>;
++
++ /* Device Bus parameters are required */
++
++ /* Read parameters */
++ devbus,bus-width = <8>;
++ devbus,turn-off-ps = <60000>;
++ devbus,badr-skew-ps = <0>;
++ devbus,acc-first-ps = <124000>;
++ devbus,acc-next-ps = <248000>;
++ devbus,rd-setup-ps = <0>;
++ devbus,rd-hold-ps = <0>;
++
++ /* Write parameters */
++ devbus,sync-enable = <0>;
++ devbus,wr-high-ps = <60000>;
++ devbus,wr-low-ps = <60000>;
++ devbus,ale-wr-ps = <60000>;
++
++ /* NOR 16 MiB */
++ nor@0 {
++ compatible = "cfi-flash";
++ reg = <0 0x1000000>;
++ bank-width = <2>;
++ };
++ };
+ };
+ };
+ };
--- /dev/null
+From 7d375772a601bdf227902454705e402fc65b8bdf Mon Sep 17 00:00:00 2001
+From: Andrew Murray <Andrew.Murray@arm.com>
+Date: Tue, 7 May 2013 16:31:12 +0100
+Subject: [PATCH 004/203] of/pci: Provide support for parsing PCI DT ranges
+ property
+
+This patch factors out common implementation patterns to reduce overall kernel
+code and provide a means for host bridge drivers to directly obtain struct
+resources from the DT's ranges property without relying on architecture specific
+DT handling. This will make it easier to write archiecture independent host bridge
+drivers and mitigate against further duplication of DT parsing code.
+
+This patch can be used in the following way:
+
+ struct of_pci_range_parser parser;
+ struct of_pci_range range;
+
+ if (of_pci_range_parser_init(&parser, np))
+ ; //no ranges property
+
+ for_each_of_pci_range(&parser, &range) {
+
+ /*
+ directly access properties of the address range, e.g.:
+ range.pci_space, range.pci_addr, range.cpu_addr,
+ range.size, range.flags
+
+ alternatively obtain a struct resource, e.g.:
+ struct resource res;
+ of_pci_range_to_resource(&range, np, &res);
+ */
+ }
+
+Additionally the implementation takes care of adjacent ranges and merges them
+into a single range (as was the case with powerpc and microblaze).
+
+Signed-off-by: Andrew Murray <Andrew.Murray@arm.com>
+Signed-off-by: Liviu Dudau <Liviu.Dudau@arm.com>
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Reviewed-by: Rob Herring <rob.herring@calxeda.com>
+Tested-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Tested-by: Linus Walleij <linus.walleij@linaro.org>
+Tested-by: Jingoo Han <jg1.han@samsung.com>
+Acked-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ drivers/of/address.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/of_address.h | 48 +++++++++++++++++++++++++++++++++
+ 2 files changed, 115 insertions(+)
+
+--- a/drivers/of/address.c
++++ b/drivers/of/address.c
+@@ -223,6 +223,73 @@ int of_pci_address_to_resource(struct de
+ return __of_address_to_resource(dev, addrp, size, flags, NULL, r);
+ }
+ EXPORT_SYMBOL_GPL(of_pci_address_to_resource);
++
++int of_pci_range_parser_init(struct of_pci_range_parser *parser,
++ struct device_node *node)
++{
++ const int na = 3, ns = 2;
++ int rlen;
++
++ parser->node = node;
++ parser->pna = of_n_addr_cells(node);
++ parser->np = parser->pna + na + ns;
++
++ parser->range = of_get_property(node, "ranges", &rlen);
++ if (parser->range == NULL)
++ return -ENOENT;
++
++ parser->end = parser->range + rlen / sizeof(__be32);
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(of_pci_range_parser_init);
++
++struct of_pci_range *of_pci_range_parser_one(struct of_pci_range_parser *parser,
++ struct of_pci_range *range)
++{
++ const int na = 3, ns = 2;
++
++ if (!range)
++ return NULL;
++
++ if (!parser->range || parser->range + parser->np > parser->end)
++ return NULL;
++
++ range->pci_space = parser->range[0];
++ range->flags = of_bus_pci_get_flags(parser->range);
++ range->pci_addr = of_read_number(parser->range + 1, ns);
++ range->cpu_addr = of_translate_address(parser->node,
++ parser->range + na);
++ range->size = of_read_number(parser->range + parser->pna + na, ns);
++
++ parser->range += parser->np;
++
++ /* Now consume following elements while they are contiguous */
++ while (parser->range + parser->np <= parser->end) {
++ u32 flags, pci_space;
++ u64 pci_addr, cpu_addr, size;
++
++ pci_space = be32_to_cpup(parser->range);
++ flags = of_bus_pci_get_flags(parser->range);
++ pci_addr = of_read_number(parser->range + 1, ns);
++ cpu_addr = of_translate_address(parser->node,
++ parser->range + na);
++ size = of_read_number(parser->range + parser->pna + na, ns);
++
++ if (flags != range->flags)
++ break;
++ if (pci_addr != range->pci_addr + range->size ||
++ cpu_addr != range->cpu_addr + range->size)
++ break;
++
++ range->size += size;
++ parser->range += parser->np;
++ }
++
++ return range;
++}
++EXPORT_SYMBOL_GPL(of_pci_range_parser_one);
++
+ #endif /* CONFIG_PCI */
+
+ /*
+--- a/include/linux/of_address.h
++++ b/include/linux/of_address.h
+@@ -4,6 +4,36 @@
+ #include <linux/errno.h>
+ #include <linux/of.h>
+
++struct of_pci_range_parser {
++ struct device_node *node;
++ const __be32 *range;
++ const __be32 *end;
++ int np;
++ int pna;
++};
++
++struct of_pci_range {
++ u32 pci_space;
++ u64 pci_addr;
++ u64 cpu_addr;
++ u64 size;
++ u32 flags;
++};
++
++#define for_each_of_pci_range(parser, range) \
++ for (; of_pci_range_parser_one(parser, range);)
++
++static inline void of_pci_range_to_resource(struct of_pci_range *range,
++ struct device_node *np,
++ struct resource *res)
++{
++ res->flags = range->flags;
++ res->start = range->cpu_addr;
++ res->end = range->cpu_addr + range->size - 1;
++ res->parent = res->child = res->sibling = NULL;
++ res->name = np->full_name;
++}
++
+ #ifdef CONFIG_OF_ADDRESS
+ extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
+ extern bool of_can_translate_address(struct device_node *dev);
+@@ -27,6 +57,11 @@ static inline unsigned long pci_address_
+ #define pci_address_to_pio pci_address_to_pio
+ #endif
+
++extern int of_pci_range_parser_init(struct of_pci_range_parser *parser,
++ struct device_node *node);
++extern struct of_pci_range *of_pci_range_parser_one(
++ struct of_pci_range_parser *parser,
++ struct of_pci_range *range);
+ #else /* CONFIG_OF_ADDRESS */
+ #ifndef of_address_to_resource
+ static inline int of_address_to_resource(struct device_node *dev, int index,
+@@ -53,6 +88,19 @@ static inline const __be32 *of_get_addre
+ {
+ return NULL;
+ }
++
++static inline int of_pci_range_parser_init(struct of_pci_range_parser *parser,
++ struct device_node *node)
++{
++ return -1;
++}
++
++static inline struct of_pci_range *of_pci_range_parser_one(
++ struct of_pci_range_parser *parser,
++ struct of_pci_range *range)
++{
++ return NULL;
++}
+ #endif /* CONFIG_OF_ADDRESS */
+
+
--- /dev/null
+From 3f368ae1994efc17b59ffd34307c76b1f642527e Mon Sep 17 00:00:00 2001
+From: Thierry Reding <thierry.reding@avionic-design.de>
+Date: Mon, 11 Feb 2013 09:22:20 +0100
+Subject: [PATCH 006/203] of/pci: Add of_pci_parse_bus_range() function
+
+This function can be used to parse a bus-range property as specified by
+device nodes representing PCI bridges.
+
+Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
+---
+ drivers/of/of_pci.c | 25 +++++++++++++++++++++++++
+ include/linux/of_pci.h | 1 +
+ 2 files changed, 26 insertions(+)
+
+--- a/drivers/of/of_pci.c
++++ b/drivers/of/of_pci.c
+@@ -64,3 +64,28 @@ int of_pci_get_devfn(struct device_node
+ return (be32_to_cpup(reg) >> 8) & 0xff;
+ }
+ EXPORT_SYMBOL_GPL(of_pci_get_devfn);
++
++/**
++ * of_pci_parse_bus_range() - parse the bus-range property of a PCI device
++ * @node: device node
++ * @res: address to a struct resource to return the bus-range
++ *
++ * Returns 0 on success or a negative error-code on failure.
++ */
++int of_pci_parse_bus_range(struct device_node *node, struct resource *res)
++{
++ const __be32 *values;
++ int len;
++
++ values = of_get_property(node, "bus-range", &len);
++ if (!values || len < sizeof(*values) * 2)
++ return -EINVAL;
++
++ res->name = node->name;
++ res->start = be32_to_cpup(values++);
++ res->end = be32_to_cpup(values);
++ res->flags = IORESOURCE_BUS;
++
++ return 0;
++}
++EXPORT_SYMBOL_GPL(of_pci_parse_bus_range);
+--- a/include/linux/of_pci.h
++++ b/include/linux/of_pci.h
+@@ -11,5 +11,6 @@ struct device_node;
+ struct device_node *of_pci_find_child_device(struct device_node *parent,
+ unsigned int devfn);
+ int of_pci_get_devfn(struct device_node *np);
++int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
+
+ #endif
--- /dev/null
+From f12aa05cbfb88e5541814ffa7be7e195471568bd Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Fri, 7 Dec 2012 20:35:20 +0100
+Subject: [PATCH 007/203] clk: mvebu: create parent-child relation for PCIe
+ clocks on Armada 370
+
+The Armada 370 has two gatable clocks for each PCIe interface, and we
+want both of them to be enabled. We therefore make one of the two
+clocks a child of the other, as we did for the sataX and sataXlnk
+clocks on Armada XP.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Cc: Mike Turquette <mturquette@linaro.org>
+---
+ drivers/clk/mvebu/clk-gating-ctrl.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/clk/mvebu/clk-gating-ctrl.c
++++ b/drivers/clk/mvebu/clk-gating-ctrl.c
+@@ -119,8 +119,8 @@ static const struct mvebu_soc_descr __in
+ { "pex1_en", NULL, 2 },
+ { "ge1", NULL, 3 },
+ { "ge0", NULL, 4 },
+- { "pex0", NULL, 5 },
+- { "pex1", NULL, 9 },
++ { "pex0", "pex0_en", 5 },
++ { "pex1", "pex1_en", 9 },
+ { "sata0", NULL, 15 },
+ { "sdio", NULL, 17 },
+ { "tdm", NULL, 25 },
--- /dev/null
+From 5006da299ae65cadf92932f2f7b062b5a8c65798 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Fri, 18 Jan 2013 16:42:01 +0100
+Subject: [PATCH 008/203] clk: mvebu: add more PCIe clocks for Armada XP
+
+The current revision of the datasheet only mentions the gatable clocks
+for the PCIe 0.0, 0.1, 0.2 and 0.3 interfaces, and forgot to mention
+the ones for the PCIe 1.0, 1.1, 1.2, 1.3, 2.0 and 3.0
+interfaces. After confirmation with Marvell engineers, this patch adds
+the missing gatable clocks for those PCIe interfaces.
+
+It also changes the name of the previously existing PCIe gatable
+clocks, in order to match the naming using the datasheets.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Cc: Mike Turquette <mturquette@linaro.org>
+---
+ drivers/clk/mvebu/clk-gating-ctrl.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+--- a/drivers/clk/mvebu/clk-gating-ctrl.c
++++ b/drivers/clk/mvebu/clk-gating-ctrl.c
+@@ -137,10 +137,14 @@ static const struct mvebu_soc_descr __in
+ { "ge2", NULL, 2 },
+ { "ge1", NULL, 3 },
+ { "ge0", NULL, 4 },
+- { "pex0", NULL, 5 },
+- { "pex1", NULL, 6 },
+- { "pex2", NULL, 7 },
+- { "pex3", NULL, 8 },
++ { "pex00", NULL, 5 },
++ { "pex01", NULL, 6 },
++ { "pex02", NULL, 7 },
++ { "pex03", NULL, 8 },
++ { "pex10", NULL, 9 },
++ { "pex11", NULL, 10 },
++ { "pex12", NULL, 11 },
++ { "pex13", NULL, 12 },
+ { "bp", NULL, 13 },
+ { "sata0lnk", NULL, 14 },
+ { "sata0", "sata0lnk", 15 },
+@@ -152,6 +156,8 @@ static const struct mvebu_soc_descr __in
+ { "xor0", NULL, 22 },
+ { "crypto", NULL, 23 },
+ { "tdm", NULL, 25 },
++ { "pex20", NULL, 26 },
++ { "pex30", NULL, 27 },
+ { "xor1", NULL, 28 },
+ { "sata1lnk", NULL, 29 },
+ { "sata1", "sata1lnk", 30 },
--- /dev/null
+From cf7b5cb15e46b5357c60188b75b213a7f0b5fd32 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Fri, 18 Jan 2013 17:42:58 +0100
+Subject: [PATCH 009/203] pci: PCIe driver for Marvell Armada 370/XP systems
+
+This driver implements the support for the PCIe interfaces on the
+Marvell Armada 370/XP ARM SoCs. In the future, it might be extended to
+cover earlier families of Marvell SoCs, such as Dove, Orion and
+Kirkwood.
+
+The driver implements the hw_pci operations needed by the core ARM PCI
+code to setup PCI devices and get their corresponding IRQs, and the
+pci_ops operations that are used by the PCI core to read/write the
+configuration space of PCI devices.
+
+Since the PCIe interfaces of Marvell SoCs are completely separate and
+not linked together in a bus, this driver sets up an emulated PCI host
+bridge, with one PCI-to-PCI bridge as child for each hardware PCIe
+interface.
+
+In addition, this driver enumerates the different PCIe slots, and for
+those having a device plugged in, it sets up the necessary address
+decoding windows, using the mvebu-mbus driver.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+---
+ .../devicetree/bindings/pci/mvebu-pci.txt | 220 ++++++
+ drivers/pci/Kconfig | 2 +
+ drivers/pci/Makefile | 3 +
+ drivers/pci/host/Kconfig | 8 +
+ drivers/pci/host/Makefile | 1 +
+ drivers/pci/host/pci-mvebu.c | 880 +++++++++++++++++++++
+ 6 files changed, 1114 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/pci/mvebu-pci.txt
+ create mode 100644 drivers/pci/host/Kconfig
+ create mode 100644 drivers/pci/host/Makefile
+ create mode 100644 drivers/pci/host/pci-mvebu.c
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/pci/mvebu-pci.txt
+@@ -0,0 +1,220 @@
++* Marvell EBU PCIe interfaces
++
++Mandatory properties:
++- compatible: one of the following values:
++ marvell,armada-370-pcie
++ marvell,armada-xp-pcie
++- #address-cells, set to <3>
++- #size-cells, set to <2>
++- #interrupt-cells, set to <1>
++- bus-range: PCI bus numbers covered
++- device_type, set to "pci"
++- ranges: ranges for the PCI memory and I/O regions, as well as the
++ MMIO registers to control the PCIe interfaces.
++
++In addition, the Device Tree node must have sub-nodes describing each
++PCIe interface, having the following mandatory properties:
++- reg: used only for interrupt mapping, so only the first four bytes
++ are used to refer to the correct bus number and device number.
++- assigned-addresses: reference to the MMIO registers used to control
++ this PCIe interface.
++- clocks: the clock associated to this PCIe interface
++- marvell,pcie-port: the physical PCIe port number
++- status: either "disabled" or "okay"
++- device_type, set to "pci"
++- #address-cells, set to <3>
++- #size-cells, set to <2>
++- #interrupt-cells, set to <1>
++- ranges, empty property.
++- interrupt-map-mask and interrupt-map, standard PCI properties to
++ define the mapping of the PCIe interface to interrupt numbers.
++
++and the following optional properties:
++- marvell,pcie-lane: the physical PCIe lane number, for ports having
++ multiple lanes. If this property is not found, we assume that the
++ value is 0.
++
++Example:
++
++pcie-controller {
++ compatible = "marvell,armada-xp-pcie";
++ status = "disabled";
++ device_type = "pci";
++
++ #address-cells = <3>;
++ #size-cells = <2>;
++
++ bus-range = <0x00 0xff>;
++
++ ranges = <0x82000000 0 0xd0040000 0xd0040000 0 0x00002000 /* Port 0.0 registers */
++ 0x82000000 0 0xd0042000 0xd0042000 0 0x00002000 /* Port 2.0 registers */
++ 0x82000000 0 0xd0044000 0xd0044000 0 0x00002000 /* Port 0.1 registers */
++ 0x82000000 0 0xd0048000 0xd0048000 0 0x00002000 /* Port 0.2 registers */
++ 0x82000000 0 0xd004c000 0xd004c000 0 0x00002000 /* Port 0.3 registers */
++ 0x82000000 0 0xd0080000 0xd0080000 0 0x00002000 /* Port 1.0 registers */
++ 0x82000000 0 0xd0082000 0xd0082000 0 0x00002000 /* Port 3.0 registers */
++ 0x82000000 0 0xd0084000 0xd0084000 0 0x00002000 /* Port 1.1 registers */
++ 0x82000000 0 0xd0088000 0xd0088000 0 0x00002000 /* Port 1.2 registers */
++ 0x82000000 0 0xd008c000 0xd008c000 0 0x00002000 /* Port 1.3 registers */
++ 0x82000000 0 0xe0000000 0xe0000000 0 0x08000000 /* non-prefetchable memory */
++ 0x81000000 0 0 0xe8000000 0 0x00100000>; /* downstream I/O */
++
++ pcie@1,0 {
++ device_type = "pci";
++ assigned-addresses = <0x82000800 0 0xd0040000 0 0x2000>;
++ reg = <0x0800 0 0 0 0>;
++ #address-cells = <3>;
++ #size-cells = <2>;
++ #interrupt-cells = <1>;
++ ranges;
++ interrupt-map-mask = <0 0 0 0>;
++ interrupt-map = <0 0 0 0 &mpic 58>;
++ marvell,pcie-port = <0>;
++ marvell,pcie-lane = <0>;
++ clocks = <&gateclk 5>;
++ status = "disabled";
++ };
++
++ pcie@2,0 {
++ device_type = "pci";
++ assigned-addresses = <0x82001000 0 0xd0044000 0 0x2000>;
++ reg = <0x1000 0 0 0 0>;
++ #address-cells = <3>;
++ #size-cells = <2>;
++ #interrupt-cells = <1>;
++ ranges;
++ interrupt-map-mask = <0 0 0 0>;
++ interrupt-map = <0 0 0 0 &mpic 59>;
++ marvell,pcie-port = <0>;
++ marvell,pcie-lane = <1>;
++ clocks = <&gateclk 6>;
++ status = "disabled";
++ };
++
++ pcie@3,0 {
++ device_type = "pci";
++ assigned-addresses = <0x82001800 0 0xd0048000 0 0x2000>;
++ reg = <0x1800 0 0 0 0>;
++ #address-cells = <3>;
++ #size-cells = <2>;
++ #interrupt-cells = <1>;
++ ranges;
++ interrupt-map-mask = <0 0 0 0>;
++ interrupt-map = <0 0 0 0 &mpic 60>;
++ marvell,pcie-port = <0>;
++ marvell,pcie-lane = <2>;
++ clocks = <&gateclk 7>;
++ status = "disabled";
++ };
++
++ pcie@4,0 {
++ device_type = "pci";
++ assigned-addresses = <0x82002000 0 0xd004c000 0 0x2000>;
++ reg = <0x2000 0 0 0 0>;
++ #address-cells = <3>;
++ #size-cells = <2>;
++ #interrupt-cells = <1>;
++ ranges;
++ interrupt-map-mask = <0 0 0 0>;
++ interrupt-map = <0 0 0 0 &mpic 61>;
++ marvell,pcie-port = <0>;
++ marvell,pcie-lane = <3>;
++ clocks = <&gateclk 8>;
++ status = "disabled";
++ };
++
++ pcie@5,0 {
++ device_type = "pci";
++ assigned-addresses = <0x82002800 0 0xd0080000 0 0x2000>;
++ reg = <0x2800 0 0 0 0>;
++ #address-cells = <3>;
++ #size-cells = <2>;
++ #interrupt-cells = <1>;
++ ranges;
++ interrupt-map-mask = <0 0 0 0>;
++ interrupt-map = <0 0 0 0 &mpic 62>;
++ marvell,pcie-port = <1>;
++ marvell,pcie-lane = <0>;
++ clocks = <&gateclk 9>;
++ status = "disabled";
++ };
++
++ pcie@6,0 {
++ device_type = "pci";
++ assigned-addresses = <0x82003000 0 0xd0084000 0 0x2000>;
++ reg = <0x3000 0 0 0 0>;
++ #address-cells = <3>;
++ #size-cells = <2>;
++ #interrupt-cells = <1>;
++ ranges;
++ interrupt-map-mask = <0 0 0 0>;
++ interrupt-map = <0 0 0 0 &mpic 63>;
++ marvell,pcie-port = <1>;
++ marvell,pcie-lane = <1>;
++ clocks = <&gateclk 10>;
++ status = "disabled";
++ };
++
++ pcie@7,0 {
++ device_type = "pci";
++ assigned-addresses = <0x82003800 0 0xd0088000 0 0x2000>;
++ reg = <0x3800 0 0 0 0>;
++ #address-cells = <3>;
++ #size-cells = <2>;
++ #interrupt-cells = <1>;
++ ranges;
++ interrupt-map-mask = <0 0 0 0>;
++ interrupt-map = <0 0 0 0 &mpic 64>;
++ marvell,pcie-port = <1>;
++ marvell,pcie-lane = <2>;
++ clocks = <&gateclk 11>;
++ status = "disabled";
++ };
++
++ pcie@8,0 {
++ device_type = "pci";
++ assigned-addresses = <0x82004000 0 0xd008c000 0 0x2000>;
++ reg = <0x4000 0 0 0 0>;
++ #address-cells = <3>;
++ #size-cells = <2>;
++ #interrupt-cells = <1>;
++ ranges;
++ interrupt-map-mask = <0 0 0 0>;
++ interrupt-map = <0 0 0 0 &mpic 65>;
++ marvell,pcie-port = <1>;
++ marvell,pcie-lane = <3>;
++ clocks = <&gateclk 12>;
++ status = "disabled";
++ };
++ pcie@9,0 {
++ device_type = "pci";
++ assigned-addresses = <0x82004800 0 0xd0042000 0 0x2000>;
++ reg = <0x4800 0 0 0 0>;
++ #address-cells = <3>;
++ #size-cells = <2>;
++ #interrupt-cells = <1>;
++ ranges;
++ interrupt-map-mask = <0 0 0 0>;
++ interrupt-map = <0 0 0 0 &mpic 99>;
++ marvell,pcie-port = <2>;
++ marvell,pcie-lane = <0>;
++ clocks = <&gateclk 26>;
++ status = "disabled";
++ };
++
++ pcie@10,0 {
++ device_type = "pci";
++ assigned-addresses = <0x82005000 0 0xd0082000 0 0x2000>;
++ reg = <0x5000 0 0 0 0>;
++ #address-cells = <3>;
++ #size-cells = <2>;
++ #interrupt-cells = <1>;
++ ranges;
++ interrupt-map-mask = <0 0 0 0>;
++ interrupt-map = <0 0 0 0 &mpic 103>;
++ marvell,pcie-port = <3>;
++ marvell,pcie-lane = <0>;
++ clocks = <&gateclk 27>;
++ status = "disabled";
++ };
++};
+--- a/drivers/pci/Kconfig
++++ b/drivers/pci/Kconfig
+@@ -125,3 +125,5 @@ config PCI_IOAPIC
+ config PCI_LABEL
+ def_bool y if (DMI || ACPI)
+ select NLS
++
++source "drivers/pci/host/Kconfig"
+--- a/drivers/pci/Makefile
++++ b/drivers/pci/Makefile
+@@ -67,3 +67,6 @@ obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen
+ obj-$(CONFIG_OF) += of.o
+
+ ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
++
++# PCI host controller drivers
++obj-y += host/
+--- /dev/null
++++ b/drivers/pci/host/Kconfig
+@@ -0,0 +1,8 @@
++menu "PCI host controller drivers"
++ depends on PCI
++
++config PCI_MVEBU
++ bool "Marvell EBU PCIe controller"
++ depends on ARCH_MVEBU
++
++endmenu
+--- /dev/null
++++ b/drivers/pci/host/Makefile
+@@ -0,0 +1 @@
++obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
+--- /dev/null
++++ b/drivers/pci/host/pci-mvebu.c
+@@ -0,0 +1,880 @@
++/*
++ * PCIe driver for Marvell Armada 370 and Armada XP SoCs
++ *
++ * 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/kernel.h>
++#include <linux/pci.h>
++#include <linux/clk.h>
++#include <linux/module.h>
++#include <linux/mbus.h>
++#include <linux/slab.h>
++#include <linux/platform_device.h>
++#include <linux/of_address.h>
++#include <linux/of_pci.h>
++#include <linux/of_irq.h>
++#include <linux/of_platform.h>
++
++/*
++ * PCIe unit register offsets.
++ */
++#define PCIE_DEV_ID_OFF 0x0000
++#define PCIE_CMD_OFF 0x0004
++#define PCIE_DEV_REV_OFF 0x0008
++#define PCIE_BAR_LO_OFF(n) (0x0010 + ((n) << 3))
++#define PCIE_BAR_HI_OFF(n) (0x0014 + ((n) << 3))
++#define PCIE_HEADER_LOG_4_OFF 0x0128
++#define PCIE_BAR_CTRL_OFF(n) (0x1804 + (((n) - 1) * 4))
++#define PCIE_WIN04_CTRL_OFF(n) (0x1820 + ((n) << 4))
++#define PCIE_WIN04_BASE_OFF(n) (0x1824 + ((n) << 4))
++#define PCIE_WIN04_REMAP_OFF(n) (0x182c + ((n) << 4))
++#define PCIE_WIN5_CTRL_OFF 0x1880
++#define PCIE_WIN5_BASE_OFF 0x1884
++#define PCIE_WIN5_REMAP_OFF 0x188c
++#define PCIE_CONF_ADDR_OFF 0x18f8
++#define PCIE_CONF_ADDR_EN 0x80000000
++#define PCIE_CONF_REG(r) ((((r) & 0xf00) << 16) | ((r) & 0xfc))
++#define PCIE_CONF_BUS(b) (((b) & 0xff) << 16)
++#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 11)
++#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 8)
++#define PCIE_CONF_ADDR(bus, devfn, where) \
++ (PCIE_CONF_BUS(bus) | PCIE_CONF_DEV(PCI_SLOT(devfn)) | \
++ PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where) | \
++ PCIE_CONF_ADDR_EN)
++#define PCIE_CONF_DATA_OFF 0x18fc
++#define PCIE_MASK_OFF 0x1910
++#define PCIE_MASK_ENABLE_INTS 0x0f000000
++#define PCIE_CTRL_OFF 0x1a00
++#define PCIE_CTRL_X1_MODE 0x0001
++#define PCIE_STAT_OFF 0x1a04
++#define PCIE_STAT_BUS 0xff00
++#define PCIE_STAT_LINK_DOWN BIT(0)
++#define PCIE_DEBUG_CTRL 0x1a60
++#define PCIE_DEBUG_SOFT_RESET BIT(20)
++
++/*
++ * This product ID is registered by Marvell, and used when the Marvell
++ * SoC is not the root complex, but an endpoint on the PCIe bus. It is
++ * therefore safe to re-use this PCI ID for our emulated PCI-to-PCI
++ * bridge.
++ */
++#define MARVELL_EMULATED_PCI_PCI_BRIDGE_ID 0x7846
++
++/* PCI configuration space of a PCI-to-PCI bridge */
++struct mvebu_sw_pci_bridge {
++ u16 vendor;
++ u16 device;
++ u16 command;
++ u16 status;
++ u16 class;
++ u8 interface;
++ u8 revision;
++ u8 bist;
++ u8 header_type;
++ u8 latency_timer;
++ u8 cache_line_size;
++ u32 bar[2];
++ u8 primary_bus;
++ u8 secondary_bus;
++ u8 subordinate_bus;
++ u8 secondary_latency_timer;
++ u8 iobase;
++ u8 iolimit;
++ u16 secondary_status;
++ u16 membase;
++ u16 memlimit;
++ u16 prefmembase;
++ u16 prefmemlimit;
++ u32 prefbaseupper;
++ u32 preflimitupper;
++ u16 iobaseupper;
++ u16 iolimitupper;
++ u8 cappointer;
++ u8 reserved1;
++ u16 reserved2;
++ u32 romaddr;
++ u8 intline;
++ u8 intpin;
++ u16 bridgectrl;
++};
++
++struct mvebu_pcie_port;
++
++/* Structure representing all PCIe interfaces */
++struct mvebu_pcie {
++ struct platform_device *pdev;
++ struct mvebu_pcie_port *ports;
++ struct resource io;
++ struct resource realio;
++ struct resource mem;
++ struct resource busn;
++ int nports;
++};
++
++/* Structure representing one PCIe interface */
++struct mvebu_pcie_port {
++ char *name;
++ void __iomem *base;
++ spinlock_t conf_lock;
++ int haslink;
++ u32 port;
++ u32 lane;
++ int devfn;
++ struct clk *clk;
++ struct mvebu_sw_pci_bridge bridge;
++ struct device_node *dn;
++ struct mvebu_pcie *pcie;
++ phys_addr_t memwin_base;
++ size_t memwin_size;
++ phys_addr_t iowin_base;
++ size_t iowin_size;
++};
++
++static bool mvebu_pcie_link_up(struct mvebu_pcie_port *port)
++{
++ return !(readl(port->base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
++}
++
++static void mvebu_pcie_set_local_bus_nr(struct mvebu_pcie_port *port, int nr)
++{
++ u32 stat;
++
++ stat = readl(port->base + PCIE_STAT_OFF);
++ stat &= ~PCIE_STAT_BUS;
++ stat |= nr << 8;
++ writel(stat, port->base + PCIE_STAT_OFF);
++}
++
++/*
++ * Setup PCIE BARs and Address Decode Wins:
++ * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
++ * WIN[0-3] -> DRAM bank[0-3]
++ */
++static void __init mvebu_pcie_setup_wins(struct mvebu_pcie_port *port)
++{
++ const struct mbus_dram_target_info *dram;
++ u32 size;
++ int i;
++
++ dram = mv_mbus_dram_info();
++
++ /* First, disable and clear BARs and windows. */
++ for (i = 1; i < 3; i++) {
++ writel(0, port->base + PCIE_BAR_CTRL_OFF(i));
++ writel(0, port->base + PCIE_BAR_LO_OFF(i));
++ writel(0, port->base + PCIE_BAR_HI_OFF(i));
++ }
++
++ for (i = 0; i < 5; i++) {
++ writel(0, port->base + PCIE_WIN04_CTRL_OFF(i));
++ writel(0, port->base + PCIE_WIN04_BASE_OFF(i));
++ writel(0, port->base + PCIE_WIN04_REMAP_OFF(i));
++ }
++
++ writel(0, port->base + PCIE_WIN5_CTRL_OFF);
++ writel(0, port->base + PCIE_WIN5_BASE_OFF);
++ writel(0, port->base + PCIE_WIN5_REMAP_OFF);
++
++ /* Setup windows for DDR banks. Count total DDR size on the fly. */
++ size = 0;
++ for (i = 0; i < dram->num_cs; i++) {
++ const struct mbus_dram_window *cs = dram->cs + i;
++
++ writel(cs->base & 0xffff0000,
++ port->base + PCIE_WIN04_BASE_OFF(i));
++ writel(0, port->base + PCIE_WIN04_REMAP_OFF(i));
++ writel(((cs->size - 1) & 0xffff0000) |
++ (cs->mbus_attr << 8) |
++ (dram->mbus_dram_target_id << 4) | 1,
++ port->base + PCIE_WIN04_CTRL_OFF(i));
++
++ size += cs->size;
++ }
++
++ /* Round up 'size' to the nearest power of two. */
++ if ((size & (size - 1)) != 0)
++ size = 1 << fls(size);
++
++ /* Setup BAR[1] to all DRAM banks. */
++ writel(dram->cs[0].base, port->base + PCIE_BAR_LO_OFF(1));
++ writel(0, port->base + PCIE_BAR_HI_OFF(1));
++ writel(((size - 1) & 0xffff0000) | 1,
++ port->base + PCIE_BAR_CTRL_OFF(1));
++}
++
++static void __init mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
++{
++ u16 cmd;
++ u32 mask;
++
++ /* Point PCIe unit MBUS decode windows to DRAM space. */
++ mvebu_pcie_setup_wins(port);
++
++ /* Master + slave enable. */
++ cmd = readw(port->base + PCIE_CMD_OFF);
++ cmd |= PCI_COMMAND_IO;
++ cmd |= PCI_COMMAND_MEMORY;
++ cmd |= PCI_COMMAND_MASTER;
++ writew(cmd, port->base + PCIE_CMD_OFF);
++
++ /* Enable interrupt lines A-D. */
++ mask = readl(port->base + PCIE_MASK_OFF);
++ mask |= PCIE_MASK_ENABLE_INTS;
++ writel(mask, port->base + PCIE_MASK_OFF);
++}
++
++static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
++ struct pci_bus *bus,
++ u32 devfn, int where, int size, u32 *val)
++{
++ writel(PCIE_CONF_ADDR(bus->number, devfn, where),
++ port->base + PCIE_CONF_ADDR_OFF);
++
++ *val = readl(port->base + PCIE_CONF_DATA_OFF);
++
++ if (size == 1)
++ *val = (*val >> (8 * (where & 3))) & 0xff;
++ else if (size == 2)
++ *val = (*val >> (8 * (where & 3))) & 0xffff;
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
++ struct pci_bus *bus,
++ u32 devfn, int where, int size, u32 val)
++{
++ int ret = PCIBIOS_SUCCESSFUL;
++
++ writel(PCIE_CONF_ADDR(bus->number, devfn, where),
++ port->base + PCIE_CONF_ADDR_OFF);
++
++ if (size == 4)
++ writel(val, port->base + PCIE_CONF_DATA_OFF);
++ else if (size == 2)
++ writew(val, port->base + PCIE_CONF_DATA_OFF + (where & 3));
++ else if (size == 1)
++ writeb(val, port->base + PCIE_CONF_DATA_OFF + (where & 3));
++ else
++ ret = PCIBIOS_BAD_REGISTER_NUMBER;
++
++ return ret;
++}
++
++static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
++{
++ phys_addr_t iobase;
++
++ /* Are the new iobase/iolimit values invalid? */
++ if (port->bridge.iolimit < port->bridge.iobase ||
++ port->bridge.iolimitupper < port->bridge.iobaseupper) {
++
++ /* If a window was configured, remove it */
++ if (port->iowin_base) {
++ mvebu_mbus_del_window(port->iowin_base,
++ port->iowin_size);
++ port->iowin_base = 0;
++ port->iowin_size = 0;
++ }
++
++ return;
++ }
++
++ /*
++ * We read the PCI-to-PCI bridge emulated registers, and
++ * calculate the base address and size of the address decoding
++ * window to setup, according to the PCI-to-PCI bridge
++ * specifications. iobase is the bus address, port->iowin_base
++ * is the CPU address.
++ */
++ iobase = ((port->bridge.iobase & 0xF0) << 8) |
++ (port->bridge.iobaseupper << 16);
++ port->iowin_base = port->pcie->io.start + iobase;
++ port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) |
++ (port->bridge.iolimitupper << 16)) -
++ iobase);
++
++ mvebu_mbus_add_window_remap_flags(port->name, port->iowin_base,
++ port->iowin_size,
++ iobase,
++ MVEBU_MBUS_PCI_IO);
++
++ pci_ioremap_io(iobase, port->iowin_base);
++}
++
++static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
++{
++ /* Are the new membase/memlimit values invalid? */
++ if (port->bridge.memlimit < port->bridge.membase) {
++
++ /* If a window was configured, remove it */
++ if (port->memwin_base) {
++ mvebu_mbus_del_window(port->memwin_base,
++ port->memwin_size);
++ port->memwin_base = 0;
++ port->memwin_size = 0;
++ }
++
++ return;
++ }
++
++ /*
++ * We read the PCI-to-PCI bridge emulated registers, and
++ * calculate the base address and size of the address decoding
++ * window to setup, according to the PCI-to-PCI bridge
++ * specifications.
++ */
++ port->memwin_base = ((port->bridge.membase & 0xFFF0) << 16);
++ port->memwin_size =
++ (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) -
++ port->memwin_base;
++
++ mvebu_mbus_add_window_remap_flags(port->name, port->memwin_base,
++ port->memwin_size,
++ MVEBU_MBUS_NO_REMAP,
++ MVEBU_MBUS_PCI_MEM);
++}
++
++/*
++ * Initialize the configuration space of the PCI-to-PCI bridge
++ * associated with the given PCIe interface.
++ */
++static void mvebu_sw_pci_bridge_init(struct mvebu_pcie_port *port)
++{
++ struct mvebu_sw_pci_bridge *bridge = &port->bridge;
++
++ memset(bridge, 0, sizeof(struct mvebu_sw_pci_bridge));
++
++ bridge->status = PCI_STATUS_CAP_LIST;
++ bridge->class = PCI_CLASS_BRIDGE_PCI;
++ bridge->vendor = PCI_VENDOR_ID_MARVELL;
++ bridge->device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID;
++ bridge->header_type = PCI_HEADER_TYPE_BRIDGE;
++ bridge->cache_line_size = 0x10;
++
++ /* We support 32 bits I/O addressing */
++ bridge->iobase = PCI_IO_RANGE_TYPE_32;
++ bridge->iolimit = PCI_IO_RANGE_TYPE_32;
++}
++
++/*
++ * Read the configuration space of the PCI-to-PCI bridge associated to
++ * the given PCIe interface.
++ */
++static int mvebu_sw_pci_bridge_read(struct mvebu_pcie_port *port,
++ unsigned int where, int size, u32 *value)
++{
++ struct mvebu_sw_pci_bridge *bridge = &port->bridge;
++
++ switch (where & ~3) {
++ case PCI_VENDOR_ID:
++ *value = bridge->device << 16 | bridge->vendor;
++ break;
++
++ case PCI_COMMAND:
++ *value = bridge->status << 16 | bridge->command;
++ break;
++
++ case PCI_CLASS_REVISION:
++ *value = bridge->class << 16 | bridge->interface << 8 |
++ bridge->revision;
++ break;
++
++ case PCI_CACHE_LINE_SIZE:
++ *value = bridge->bist << 24 | bridge->header_type << 16 |
++ bridge->latency_timer << 8 | bridge->cache_line_size;
++ break;
++
++ case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1:
++ *value = bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4];
++ break;
++
++ case PCI_PRIMARY_BUS:
++ *value = (bridge->secondary_latency_timer << 24 |
++ bridge->subordinate_bus << 16 |
++ bridge->secondary_bus << 8 |
++ bridge->primary_bus);
++ break;
++
++ case PCI_IO_BASE:
++ *value = (bridge->secondary_status << 16 |
++ bridge->iolimit << 8 |
++ bridge->iobase);
++ break;
++
++ case PCI_MEMORY_BASE:
++ *value = (bridge->memlimit << 16 | bridge->membase);
++ break;
++
++ case PCI_PREF_MEMORY_BASE:
++ *value = (bridge->prefmemlimit << 16 | bridge->prefmembase);
++ break;
++
++ case PCI_PREF_BASE_UPPER32:
++ *value = bridge->prefbaseupper;
++ break;
++
++ case PCI_PREF_LIMIT_UPPER32:
++ *value = bridge->preflimitupper;
++ break;
++
++ case PCI_IO_BASE_UPPER16:
++ *value = (bridge->iolimitupper << 16 | bridge->iobaseupper);
++ break;
++
++ case PCI_ROM_ADDRESS1:
++ *value = 0;
++ break;
++
++ default:
++ *value = 0xffffffff;
++ return PCIBIOS_BAD_REGISTER_NUMBER;
++ }
++
++ if (size == 2)
++ *value = (*value >> (8 * (where & 3))) & 0xffff;
++ else if (size == 1)
++ *value = (*value >> (8 * (where & 3))) & 0xff;
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++/* Write to the PCI-to-PCI bridge configuration space */
++static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
++ unsigned int where, int size, u32 value)
++{
++ struct mvebu_sw_pci_bridge *bridge = &port->bridge;
++ u32 mask, reg;
++ int err;
++
++ if (size == 4)
++ mask = 0x0;
++ else if (size == 2)
++ mask = ~(0xffff << ((where & 3) * 8));
++ else if (size == 1)
++ mask = ~(0xff << ((where & 3) * 8));
++ else
++ return PCIBIOS_BAD_REGISTER_NUMBER;
++
++ err = mvebu_sw_pci_bridge_read(port, where & ~3, 4, ®);
++ if (err)
++ return err;
++
++ value = (reg & mask) | value << ((where & 3) * 8);
++
++ switch (where & ~3) {
++ case PCI_COMMAND:
++ bridge->command = value & 0xffff;
++ bridge->status = value >> 16;
++ break;
++
++ case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1:
++ bridge->bar[((where & ~3) - PCI_BASE_ADDRESS_0) / 4] = value;
++ break;
++
++ case PCI_IO_BASE:
++ /*
++ * We also keep bit 1 set, it is a read-only bit that
++ * indicates we support 32 bits addressing for the
++ * I/O
++ */
++ bridge->iobase = (value & 0xff) | PCI_IO_RANGE_TYPE_32;
++ bridge->iolimit = ((value >> 8) & 0xff) | PCI_IO_RANGE_TYPE_32;
++ bridge->secondary_status = value >> 16;
++ mvebu_pcie_handle_iobase_change(port);
++ break;
++
++ case PCI_MEMORY_BASE:
++ bridge->membase = value & 0xffff;
++ bridge->memlimit = value >> 16;
++ mvebu_pcie_handle_membase_change(port);
++ break;
++
++ case PCI_PREF_MEMORY_BASE:
++ bridge->prefmembase = value & 0xffff;
++ bridge->prefmemlimit = value >> 16;
++ break;
++
++ case PCI_PREF_BASE_UPPER32:
++ bridge->prefbaseupper = value;
++ break;
++
++ case PCI_PREF_LIMIT_UPPER32:
++ bridge->preflimitupper = value;
++ break;
++
++ case PCI_IO_BASE_UPPER16:
++ bridge->iobaseupper = value & 0xffff;
++ bridge->iolimitupper = value >> 16;
++ mvebu_pcie_handle_iobase_change(port);
++ break;
++
++ case PCI_PRIMARY_BUS:
++ bridge->primary_bus = value & 0xff;
++ bridge->secondary_bus = (value >> 8) & 0xff;
++ bridge->subordinate_bus = (value >> 16) & 0xff;
++ bridge->secondary_latency_timer = (value >> 24) & 0xff;
++ mvebu_pcie_set_local_bus_nr(port, bridge->secondary_bus);
++ break;
++
++ default:
++ break;
++ }
++
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static inline struct mvebu_pcie *sys_to_pcie(struct pci_sys_data *sys)
++{
++ return sys->private_data;
++}
++
++static struct mvebu_pcie_port *
++mvebu_pcie_find_port(struct mvebu_pcie *pcie, struct pci_bus *bus,
++ int devfn)
++{
++ int i;
++
++ for (i = 0; i < pcie->nports; i++) {
++ struct mvebu_pcie_port *port = &pcie->ports[i];
++ if (bus->number == 0 && port->devfn == devfn)
++ return port;
++ if (bus->number != 0 &&
++ port->bridge.secondary_bus == bus->number)
++ return port;
++ }
++
++ return NULL;
++}
++
++/* PCI configuration space write function */
++static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
++ int where, int size, u32 val)
++{
++ struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
++ struct mvebu_pcie_port *port;
++ unsigned long flags;
++ int ret;
++
++ port = mvebu_pcie_find_port(pcie, bus, devfn);
++ if (!port)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ /* Access the emulated PCI-to-PCI bridge */
++ if (bus->number == 0)
++ return mvebu_sw_pci_bridge_write(port, where, size, val);
++
++ if (!port->haslink || PCI_SLOT(devfn) != 0)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ /* Access the real PCIe interface */
++ spin_lock_irqsave(&port->conf_lock, flags);
++ ret = mvebu_pcie_hw_wr_conf(port, bus,
++ PCI_DEVFN(1, PCI_FUNC(devfn)),
++ where, size, val);
++ spin_unlock_irqrestore(&port->conf_lock, flags);
++
++ return ret;
++}
++
++/* PCI configuration space read function */
++static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
++ int size, u32 *val)
++{
++ struct mvebu_pcie *pcie = sys_to_pcie(bus->sysdata);
++ struct mvebu_pcie_port *port;
++ unsigned long flags;
++ int ret;
++
++ port = mvebu_pcie_find_port(pcie, bus, devfn);
++ if (!port) {
++ *val = 0xffffffff;
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ /* Access the emulated PCI-to-PCI bridge */
++ if (bus->number == 0)
++ return mvebu_sw_pci_bridge_read(port, where, size, val);
++
++ if (!port->haslink || PCI_SLOT(devfn) != 0) {
++ *val = 0xffffffff;
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ /* Access the real PCIe interface */
++ spin_lock_irqsave(&port->conf_lock, flags);
++ ret = mvebu_pcie_hw_rd_conf(port, bus,
++ PCI_DEVFN(1, PCI_FUNC(devfn)),
++ where, size, val);
++ spin_unlock_irqrestore(&port->conf_lock, flags);
++
++ return ret;
++}
++
++static struct pci_ops mvebu_pcie_ops = {
++ .read = mvebu_pcie_rd_conf,
++ .write = mvebu_pcie_wr_conf,
++};
++
++static int __init mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
++{
++ struct mvebu_pcie *pcie = sys_to_pcie(sys);
++ int i;
++
++ pci_add_resource_offset(&sys->resources, &pcie->realio, sys->io_offset);
++ pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
++ pci_add_resource(&sys->resources, &pcie->busn);
++
++ for (i = 0; i < pcie->nports; i++) {
++ struct mvebu_pcie_port *port = &pcie->ports[i];
++ mvebu_pcie_setup_hw(port);
++ }
++
++ return 1;
++}
++
++static int __init mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++ struct of_irq oirq;
++ int ret;
++
++ ret = of_irq_map_pci(dev, &oirq);
++ if (ret)
++ return ret;
++
++ return irq_create_of_mapping(oirq.controller, oirq.specifier,
++ oirq.size);
++}
++
++static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
++{
++ struct mvebu_pcie *pcie = sys_to_pcie(sys);
++ struct pci_bus *bus;
++
++ bus = pci_create_root_bus(&pcie->pdev->dev, sys->busnr,
++ &mvebu_pcie_ops, sys, &sys->resources);
++ if (!bus)
++ return NULL;
++
++ pci_scan_child_bus(bus);
++
++ return bus;
++}
++
++resource_size_t mvebu_pcie_align_resource(struct pci_dev *dev,
++ const struct resource *res,
++ resource_size_t start,
++ resource_size_t size,
++ resource_size_t align)
++{
++ if (dev->bus->number != 0)
++ return start;
++
++ /*
++ * On the PCI-to-PCI bridge side, the I/O windows must have at
++ * least a 64 KB size and be aligned on their size, and the
++ * memory windows must have at least a 1 MB size and be
++ * aligned on their size
++ */
++ if (res->flags & IORESOURCE_IO)
++ return round_up(start, max((resource_size_t)SZ_64K, size));
++ else if (res->flags & IORESOURCE_MEM)
++ return round_up(start, max((resource_size_t)SZ_1M, size));
++ else
++ return start;
++}
++
++static void __init mvebu_pcie_enable(struct mvebu_pcie *pcie)
++{
++ struct hw_pci hw;
++
++ memset(&hw, 0, sizeof(hw));
++
++ hw.nr_controllers = 1;
++ hw.private_data = (void **)&pcie;
++ hw.setup = mvebu_pcie_setup;
++ hw.scan = mvebu_pcie_scan_bus;
++ hw.map_irq = mvebu_pcie_map_irq;
++ hw.ops = &mvebu_pcie_ops;
++ hw.align_resource = mvebu_pcie_align_resource;
++
++ pci_common_init(&hw);
++}
++
++/*
++ * Looks up the list of register addresses encoded into the reg =
++ * <...> property for one that matches the given port/lane. Once
++ * found, maps it.
++ */
++static void __iomem * __init
++mvebu_pcie_map_registers(struct platform_device *pdev,
++ struct device_node *np,
++ struct mvebu_pcie_port *port)
++{
++ struct resource regs;
++ int ret = 0;
++
++ ret = of_address_to_resource(np, 0, ®s);
++ if (ret)
++ return NULL;
++
++ return devm_request_and_ioremap(&pdev->dev, ®s);
++}
++
++static int __init mvebu_pcie_probe(struct platform_device *pdev)
++{
++ struct mvebu_pcie *pcie;
++ struct device_node *np = pdev->dev.of_node;
++ struct of_pci_range range;
++ struct of_pci_range_parser parser;
++ struct device_node *child;
++ int i, ret;
++
++ pcie = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pcie),
++ GFP_KERNEL);
++ if (!pcie)
++ return -ENOMEM;
++
++ pcie->pdev = pdev;
++
++ if (of_pci_range_parser_init(&parser, np))
++ return -EINVAL;
++
++ /* Get the I/O and memory ranges from DT */
++ for_each_of_pci_range(&parser, &range) {
++ unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
++ if (restype == IORESOURCE_IO) {
++ of_pci_range_to_resource(&range, np, &pcie->io);
++ of_pci_range_to_resource(&range, np, &pcie->realio);
++ pcie->io.name = "I/O";
++ pcie->realio.start = max_t(resource_size_t,
++ PCIBIOS_MIN_IO,
++ range.pci_addr);
++ pcie->realio.end = min_t(resource_size_t,
++ IO_SPACE_LIMIT,
++ range.pci_addr + range.size);
++ }
++ if (restype == IORESOURCE_MEM) {
++ of_pci_range_to_resource(&range, np, &pcie->mem);
++ pcie->mem.name = "MEM";
++ }
++ }
++
++ /* Get the bus range */
++ ret = of_pci_parse_bus_range(np, &pcie->busn);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to parse bus-range property: %d\n",
++ ret);
++ return ret;
++ }
++
++ for_each_child_of_node(pdev->dev.of_node, child) {
++ if (!of_device_is_available(child))
++ continue;
++ pcie->nports++;
++ }
++
++ pcie->ports = devm_kzalloc(&pdev->dev, pcie->nports *
++ sizeof(struct mvebu_pcie_port),
++ GFP_KERNEL);
++ if (!pcie->ports)
++ return -ENOMEM;
++
++ i = 0;
++ for_each_child_of_node(pdev->dev.of_node, child) {
++ struct mvebu_pcie_port *port = &pcie->ports[i];
++
++ if (!of_device_is_available(child))
++ continue;
++
++ port->pcie = pcie;
++
++ if (of_property_read_u32(child, "marvell,pcie-port",
++ &port->port)) {
++ dev_warn(&pdev->dev,
++ "ignoring PCIe DT node, missing pcie-port property\n");
++ continue;
++ }
++
++ if (of_property_read_u32(child, "marvell,pcie-lane",
++ &port->lane))
++ port->lane = 0;
++
++ port->name = kasprintf(GFP_KERNEL, "pcie%d.%d",
++ port->port, port->lane);
++
++ port->devfn = of_pci_get_devfn(child);
++ if (port->devfn < 0)
++ continue;
++
++ port->base = mvebu_pcie_map_registers(pdev, child, port);
++ if (!port->base) {
++ dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",
++ port->port, port->lane);
++ continue;
++ }
++
++ if (mvebu_pcie_link_up(port)) {
++ port->haslink = 1;
++ dev_info(&pdev->dev, "PCIe%d.%d: link up\n",
++ port->port, port->lane);
++ } else {
++ port->haslink = 0;
++ dev_info(&pdev->dev, "PCIe%d.%d: link down\n",
++ port->port, port->lane);
++ }
++
++ port->clk = of_clk_get_by_name(child, NULL);
++ if (!port->clk) {
++ dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
++ port->port, port->lane);
++ iounmap(port->base);
++ port->haslink = 0;
++ continue;
++ }
++
++ port->dn = child;
++
++ clk_prepare_enable(port->clk);
++ spin_lock_init(&port->conf_lock);
++
++ mvebu_sw_pci_bridge_init(port);
++
++ i++;
++ }
++
++ mvebu_pcie_enable(pcie);
++
++ return 0;
++}
++
++static const struct of_device_id mvebu_pcie_of_match_table[] = {
++ { .compatible = "marvell,armada-xp-pcie", },
++ { .compatible = "marvell,armada-370-pcie", },
++ {},
++};
++MODULE_DEVICE_TABLE(of, mvebu_pcie_of_match_table);
++
++static struct platform_driver mvebu_pcie_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = "mvebu-pcie",
++ .of_match_table =
++ of_match_ptr(mvebu_pcie_of_match_table),
++ },
++};
++
++static int __init mvebu_pcie_init(void)
++{
++ return platform_driver_probe(&mvebu_pcie_driver,
++ mvebu_pcie_probe);
++}
++
++subsys_initcall(mvebu_pcie_init);
++
++MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
++MODULE_DESCRIPTION("Marvell EBU PCIe driver");
++MODULE_LICENSE("GPLv2");
--- /dev/null
+From 430d545623552ddc6b68785032cc9129d0a00b43 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Fri, 7 Dec 2012 20:56:52 +0100
+Subject: [PATCH 010/203] arm: mvebu: PCIe support is now available on mvebu
+
+Now that the PCIe driver for mvebu has been integrated and all its
+relevant dependencies, we can mark the ARCH_MVEBU platform has
+MIGHT_HAVE_PCI, which allows to select the PCI bus support if needed.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/mach-mvebu/Kconfig | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm/mach-mvebu/Kconfig
++++ b/arch/arm/mach-mvebu/Kconfig
+@@ -16,6 +16,8 @@ config ARCH_MVEBU
+ select MVEBU_MBUS
+ select ZONE_DMA if ARM_LPAE
+ select ARCH_REQUIRE_GPIOLIB
++ select MIGHT_HAVE_PCI
++ select PCI_QUIRKS if PCI
+
+ if ARCH_MVEBU
+
--- /dev/null
+From c3da1bb20af37c09a07756d54420470788f131c7 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Fri, 7 Dec 2012 22:49:57 +0100
+Subject: [PATCH 011/203] arm: mvebu: update defconfig with PCI and USB support
+
+Now that we have the necessary drivers and Device Tree informations to
+support PCIe on Armada 370 and Armada XP, enable the CONFIG_PCI
+option.
+
+Also, since the Armada 370 Mirabox has a built-in USB XHCI controller
+connected on the PCIe bus, enable the corresponding options as well.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/configs/mvebu_defconfig | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/arch/arm/configs/mvebu_defconfig
++++ b/arch/arm/configs/mvebu_defconfig
+@@ -13,6 +13,8 @@ CONFIG_MACH_ARMADA_370=y
+ CONFIG_MACH_ARMADA_XP=y
+ # CONFIG_CACHE_L2X0 is not set
+ # CONFIG_SWP_EMULATE is not set
++CONFIG_PCI=y
++CONFIG_PCI_MVEBU=y
+ CONFIG_SMP=y
+ CONFIG_AEABI=y
+ CONFIG_HIGHMEM=y
+@@ -61,6 +63,7 @@ CONFIG_USB=y
+ CONFIG_USB_EHCI_HCD=y
+ CONFIG_USB_EHCI_ROOT_HUB_TT=y
+ CONFIG_USB_STORAGE=y
++CONFIG_USB_XHCI_HCD=y
+ CONFIG_MMC=y
+ CONFIG_MMC_MVSDIO=y
+ CONFIG_NEW_LEDS=y
--- /dev/null
+From f865fd0e1c10bb044d56037eaa6ac4a4a122c62a Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Tue, 21 May 2013 12:33:28 +0200
+Subject: [PATCH 012/203] arm: mvebu: mark functions of armada-370-xp.c as
+ static
+
+All the functions in armada-370-xp.c are called from the
+DT_MACHINE_START function pointers, so there is no need for them to be
+visible outside of this file, and we therefore mark them as static.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/mach-mvebu/armada-370-xp.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/mach-mvebu/armada-370-xp.c
++++ b/arch/arm/mach-mvebu/armada-370-xp.c
+@@ -38,18 +38,18 @@ static struct map_desc armada_370_xp_io_
+ },
+ };
+
+-void __init armada_370_xp_map_io(void)
++static void __init armada_370_xp_map_io(void)
+ {
+ iotable_init(armada_370_xp_io_desc, ARRAY_SIZE(armada_370_xp_io_desc));
+ }
+
+-void __init armada_370_xp_timer_and_clk_init(void)
++static void __init armada_370_xp_timer_and_clk_init(void)
+ {
+ mvebu_clocks_init();
+ armada_370_xp_timer_init();
+ }
+
+-void __init armada_370_xp_init_early(void)
++static void __init armada_370_xp_init_early(void)
+ {
+ char *mbus_soc_name;
+
--- /dev/null
+From 8b417cc752ac4158dcfcf02beafce80b90fd827d Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 23 Apr 2013 16:21:26 -0300
+Subject: [PATCH 013/203] drivers: memory: Introduce Marvell EBU Device Bus
+ driver
+
+Marvell EBU SoCs such as Armada 370/XP, Orion5x (88f5xxx) and
+Discovery (mv78xx0) supports a Device Bus controller to access several
+kinds of memories and I/O devices (NOR, NAND, SRAM, FPGA).
+
+This commit adds a driver to handle this controller. So far only
+Armada 370, Armada XP and Discovery SoCs are supported.
+
+The driver must be registered through a device tree node;
+as explained in the binding document.
+
+For each child node in the device tree, this driver will:
+ * set timing parameters
+ * register a child device
+ * setup an address decoding window, using the mbus driver
+
+Keep in mind the address decoding window setup is only a temporary hack.
+This code will be removed from this devbus driver as soon as a proper device
+tree binding for the mbus driver is added.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Jason Cooper <jason@lakedaemon.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ .../bindings/memory-controllers/mvebu-devbus.txt | 156 ++++++++++
+ drivers/memory/Kconfig | 10 +
+ drivers/memory/Makefile | 1 +
+ drivers/memory/mvebu-devbus.c | 340 +++++++++++++++++++++
+ 4 files changed, 507 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/memory-controllers/mvebu-devbus.txt
+ create mode 100644 drivers/memory/mvebu-devbus.c
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/memory-controllers/mvebu-devbus.txt
+@@ -0,0 +1,156 @@
++Device tree bindings for MVEBU Device Bus controllers
++
++The Device Bus controller available in some Marvell's SoC allows to control
++different types of standard memory and I/O devices such as NOR, NAND, and FPGA.
++The actual devices are instantiated from the child nodes of a Device Bus node.
++
++Required properties:
++
++ - compatible: Currently only Armada 370/XP SoC are supported,
++ with this compatible string:
++
++ marvell,mvebu-devbus
++
++ - reg: A resource specifier for the register space.
++ This is the base address of a chip select within
++ the controller's register space.
++ (see the example below)
++
++ - #address-cells: Must be set to 1
++ - #size-cells: Must be set to 1
++ - ranges: Must be set up to reflect the memory layout with four
++ integer values for each chip-select line in use:
++ 0 <physical address of mapping> <size>
++
++Mandatory timing properties for child nodes:
++
++Read parameters:
++
++ - devbus,turn-off-ps: Defines the time during which the controller does not
++ drive the AD bus after the completion of a device read.
++ This prevents contentions on the Device Bus after a read
++ cycle from a slow device.
++
++ - devbus,bus-width: Defines the bus width (e.g. <16>)
++
++ - devbus,badr-skew-ps: Defines the time delay from from A[2:0] toggle,
++ to read data sample. This parameter is useful for
++ synchronous pipelined devices, where the address
++ precedes the read data by one or two cycles.
++
++ - devbus,acc-first-ps: Defines the time delay from the negation of
++ ALE[0] to the cycle that the first read data is sampled
++ by the controller.
++
++ - devbus,acc-next-ps: Defines the time delay between the cycle that
++ samples data N and the cycle that samples data N+1
++ (in burst accesses).
++
++ - devbus,rd-setup-ps: Defines the time delay between DEV_CSn assertion to
++ DEV_OEn assertion. If set to 0 (default),
++ DEV_OEn and DEV_CSn are asserted at the same cycle.
++ This parameter has no affect on <acc-first-ps> parameter
++ (no affect on first data sample). Set <rd-setup-ps>
++ to a value smaller than <acc-first-ps>.
++
++ - devbus,rd-hold-ps: Defines the time between the last data sample to the
++ de-assertion of DEV_CSn. If set to 0 (default),
++ DEV_OEn and DEV_CSn are de-asserted at the same cycle
++ (the cycle of the last data sample).
++ This parameter has no affect on DEV_OEn de-assertion.
++ DEV_OEn is always de-asserted the next cycle after
++ last data sampled. Also this parameter has no
++ affect on <turn-off-ps> parameter.
++ Set <rd-hold-ps> to a value smaller than <turn-off-ps>.
++
++Write parameters:
++
++ - devbus,ale-wr-ps: Defines the time delay from the ALE[0] negation cycle
++ to the DEV_WEn assertion.
++
++ - devbus,wr-low-ps: Defines the time during which DEV_WEn is active.
++ A[2:0] and Data are kept valid as long as DEV_WEn
++ is active. This parameter defines the setup time of
++ address and data to DEV_WEn rise.
++
++ - devbus,wr-high-ps: Defines the time during which DEV_WEn is kept
++ inactive (high) between data beats of a burst write.
++ DEV_A[2:0] and Data are kept valid (do not toggle) for
++ <wr-high-ps> - <tick> ps.
++ This parameter defines the hold time of address and
++ data after DEV_WEn rise.
++
++ - devbus,sync-enable: Synchronous device enable.
++ 1: True
++ 0: False
++
++An example for an Armada XP GP board, with a 16 MiB NOR device as child
++is showed below. Note that the Device Bus driver is in charge of allocating
++the mbus address decoding window for each of its child devices.
++The window is created using the chip select specified in the child
++device node together with the base address and size specified in the ranges
++property. For instance, in the example below the allocated decoding window
++will start at base address 0xf0000000, with a size 0x1000000 (16 MiB)
++for chip select 0 (a.k.a DEV_BOOTCS).
++
++This address window handling is done in this mvebu-devbus only as a temporary
++solution. It will be removed when the support for mbus device tree binding is
++added.
++
++The reg property implicitly specifies the chip select as this:
++
++ 0x10400: DEV_BOOTCS
++ 0x10408: DEV_CS0
++ 0x10410: DEV_CS1
++ 0x10418: DEV_CS2
++ 0x10420: DEV_CS3
++
++Example:
++
++ devbus-bootcs@d0010400 {
++ status = "okay";
++ ranges = <0 0xf0000000 0x1000000>; /* @addr 0xf0000000, size 0x1000000 */
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ /* Device Bus parameters are required */
++
++ /* Read parameters */
++ devbus,bus-width = <8>;
++ devbus,turn-off-ps = <60000>;
++ devbus,badr-skew-ps = <0>;
++ devbus,acc-first-ps = <124000>;
++ devbus,acc-next-ps = <248000>;
++ devbus,rd-setup-ps = <0>;
++ devbus,rd-hold-ps = <0>;
++
++ /* Write parameters */
++ devbus,sync-enable = <0>;
++ devbus,wr-high-ps = <60000>;
++ devbus,wr-low-ps = <60000>;
++ devbus,ale-wr-ps = <60000>;
++
++ flash@0 {
++ compatible = "cfi-flash";
++
++ /* 16 MiB */
++ reg = <0 0x1000000>;
++ bank-width = <2>;
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ /*
++ * We split the 16 MiB in two partitions,
++ * just as an example.
++ */
++ partition@0 {
++ label = "First";
++ reg = <0 0x800000>;
++ };
++
++ partition@800000 {
++ label = "Second";
++ reg = <0x800000 0x800000>;
++ };
++ };
++ };
+--- a/drivers/memory/Kconfig
++++ b/drivers/memory/Kconfig
+@@ -20,6 +20,16 @@ config TI_EMIF
+ parameters and other settings during frequency, voltage and
+ temperature changes
+
++config MVEBU_DEVBUS
++ bool "Marvell EBU Device Bus Controller"
++ default y
++ depends on PLAT_ORION && OF
++ help
++ This driver is for the Device Bus controller available in some
++ Marvell EBU SoCs such as Discovery (mv78xx0), Orion (88f5xxx) and
++ Armada 370 and Armada XP. This controller allows to handle flash
++ devices such as NOR, NAND, SRAM, and FPGA.
++
+ config TEGRA20_MC
+ bool "Tegra20 Memory Controller(MC) driver"
+ default y
+--- a/drivers/memory/Makefile
++++ b/drivers/memory/Makefile
+@@ -6,5 +6,6 @@ ifeq ($(CONFIG_DDR),y)
+ obj-$(CONFIG_OF) += of_memory.o
+ endif
+ obj-$(CONFIG_TI_EMIF) += emif.o
++obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o
+ obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
+ obj-$(CONFIG_TEGRA30_MC) += tegra30-mc.o
+--- /dev/null
++++ b/drivers/memory/mvebu-devbus.c
+@@ -0,0 +1,340 @@
++/*
++ * Marvell EBU SoC Device Bus Controller
++ * (memory controller for NOR/NAND/SRAM/FPGA devices)
++ *
++ * Copyright (C) 2013 Marvell
++ *
++ * This program is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation version 2 of the License.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/mbus.h>
++#include <linux/of_platform.h>
++#include <linux/of_address.h>
++#include <linux/platform_device.h>
++
++/* Register definitions */
++#define DEV_WIDTH_BIT 30
++#define BADR_SKEW_BIT 28
++#define RD_HOLD_BIT 23
++#define ACC_NEXT_BIT 17
++#define RD_SETUP_BIT 12
++#define ACC_FIRST_BIT 6
++
++#define SYNC_ENABLE_BIT 24
++#define WR_HIGH_BIT 16
++#define WR_LOW_BIT 8
++
++#define READ_PARAM_OFFSET 0x0
++#define WRITE_PARAM_OFFSET 0x4
++
++static const char * const devbus_wins[] = {
++ "devbus-boot",
++ "devbus-cs0",
++ "devbus-cs1",
++ "devbus-cs2",
++ "devbus-cs3",
++};
++
++struct devbus_read_params {
++ u32 bus_width;
++ u32 badr_skew;
++ u32 turn_off;
++ u32 acc_first;
++ u32 acc_next;
++ u32 rd_setup;
++ u32 rd_hold;
++};
++
++struct devbus_write_params {
++ u32 sync_enable;
++ u32 wr_high;
++ u32 wr_low;
++ u32 ale_wr;
++};
++
++struct devbus {
++ struct device *dev;
++ void __iomem *base;
++ unsigned long tick_ps;
++};
++
++static int get_timing_param_ps(struct devbus *devbus,
++ struct device_node *node,
++ const char *name,
++ u32 *ticks)
++{
++ u32 time_ps;
++ int err;
++
++ err = of_property_read_u32(node, name, &time_ps);
++ if (err < 0) {
++ dev_err(devbus->dev, "%s has no '%s' property\n",
++ name, node->full_name);
++ return err;
++ }
++
++ *ticks = (time_ps + devbus->tick_ps - 1) / devbus->tick_ps;
++
++ dev_dbg(devbus->dev, "%s: %u ps -> 0x%x\n",
++ name, time_ps, *ticks);
++ return 0;
++}
++
++static int devbus_set_timing_params(struct devbus *devbus,
++ struct device_node *node)
++{
++ struct devbus_read_params r;
++ struct devbus_write_params w;
++ u32 value;
++ int err;
++
++ dev_dbg(devbus->dev, "Setting timing parameter, tick is %lu ps\n",
++ devbus->tick_ps);
++
++ /* Get read timings */
++ err = of_property_read_u32(node, "devbus,bus-width", &r.bus_width);
++ if (err < 0) {
++ dev_err(devbus->dev,
++ "%s has no 'devbus,bus-width' property\n",
++ node->full_name);
++ return err;
++ }
++ /* Convert bit width to byte width */
++ r.bus_width /= 8;
++
++ err = get_timing_param_ps(devbus, node, "devbus,badr-skew-ps",
++ &r.badr_skew);
++ if (err < 0)
++ return err;
++
++ err = get_timing_param_ps(devbus, node, "devbus,turn-off-ps",
++ &r.turn_off);
++ if (err < 0)
++ return err;
++
++ err = get_timing_param_ps(devbus, node, "devbus,acc-first-ps",
++ &r.acc_first);
++ if (err < 0)
++ return err;
++
++ err = get_timing_param_ps(devbus, node, "devbus,acc-next-ps",
++ &r.acc_next);
++ if (err < 0)
++ return err;
++
++ err = get_timing_param_ps(devbus, node, "devbus,rd-setup-ps",
++ &r.rd_setup);
++ if (err < 0)
++ return err;
++
++ err = get_timing_param_ps(devbus, node, "devbus,rd-hold-ps",
++ &r.rd_hold);
++ if (err < 0)
++ return err;
++
++ /* Get write timings */
++ err = of_property_read_u32(node, "devbus,sync-enable",
++ &w.sync_enable);
++ if (err < 0) {
++ dev_err(devbus->dev,
++ "%s has no 'devbus,sync-enable' property\n",
++ node->full_name);
++ return err;
++ }
++
++ err = get_timing_param_ps(devbus, node, "devbus,ale-wr-ps",
++ &w.ale_wr);
++ if (err < 0)
++ return err;
++
++ err = get_timing_param_ps(devbus, node, "devbus,wr-low-ps",
++ &w.wr_low);
++ if (err < 0)
++ return err;
++
++ err = get_timing_param_ps(devbus, node, "devbus,wr-high-ps",
++ &w.wr_high);
++ if (err < 0)
++ return err;
++
++ /* Set read timings */
++ value = r.bus_width << DEV_WIDTH_BIT |
++ r.badr_skew << BADR_SKEW_BIT |
++ r.rd_hold << RD_HOLD_BIT |
++ r.acc_next << ACC_NEXT_BIT |
++ r.rd_setup << RD_SETUP_BIT |
++ r.acc_first << ACC_FIRST_BIT |
++ r.turn_off;
++
++ dev_dbg(devbus->dev, "read parameters register 0x%p = 0x%x\n",
++ devbus->base + READ_PARAM_OFFSET,
++ value);
++
++ writel(value, devbus->base + READ_PARAM_OFFSET);
++
++ /* Set write timings */
++ value = w.sync_enable << SYNC_ENABLE_BIT |
++ w.wr_low << WR_LOW_BIT |
++ w.wr_high << WR_HIGH_BIT |
++ w.ale_wr;
++
++ dev_dbg(devbus->dev, "write parameters register: 0x%p = 0x%x\n",
++ devbus->base + WRITE_PARAM_OFFSET,
++ value);
++
++ writel(value, devbus->base + WRITE_PARAM_OFFSET);
++
++ return 0;
++}
++
++static int mvebu_devbus_probe(struct platform_device *pdev)
++{
++ struct device *dev = &pdev->dev;
++ struct device_node *node = pdev->dev.of_node;
++ struct device_node *parent;
++ struct devbus *devbus;
++ struct resource *res;
++ struct clk *clk;
++ unsigned long rate;
++ const __be32 *ranges;
++ int err, cs;
++ int addr_cells, p_addr_cells, size_cells;
++ int ranges_len, tuple_len;
++ u32 base, size;
++
++ devbus = devm_kzalloc(&pdev->dev, sizeof(struct devbus), GFP_KERNEL);
++ if (!devbus)
++ return -ENOMEM;
++
++ devbus->dev = dev;
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ devbus->base = devm_ioremap_resource(&pdev->dev, res);
++ if (IS_ERR(devbus->base))
++ return PTR_ERR(devbus->base);
++
++ clk = devm_clk_get(&pdev->dev, NULL);
++ if (IS_ERR(clk))
++ return PTR_ERR(clk);
++ clk_prepare_enable(clk);
++
++ /*
++ * Obtain clock period in picoseconds,
++ * we need this in order to convert timing
++ * parameters from cycles to picoseconds.
++ */
++ rate = clk_get_rate(clk) / 1000;
++ devbus->tick_ps = 1000000000 / rate;
++
++ /* Read the device tree node and set the new timing parameters */
++ err = devbus_set_timing_params(devbus, node);
++ if (err < 0)
++ return err;
++
++ /*
++ * Allocate an address window for this device.
++ * If the device probing fails, then we won't be able to
++ * remove the allocated address decoding window.
++ *
++ * FIXME: This is only a temporary hack! We need to do this here
++ * because we still don't have device tree bindings for mbus.
++ * Once that support is added, we will declare these address windows
++ * statically in the device tree, and remove the window configuration
++ * from here.
++ */
++
++ /*
++ * Get the CS to choose the window string.
++ * This is a bit hacky, but it will be removed once the
++ * address windows are declared in the device tree.
++ */
++ cs = (((unsigned long)devbus->base) % 0x400) / 8;
++
++ /*
++ * Parse 'ranges' property to obtain a (base,size) window tuple.
++ * This will be removed once the address windows
++ * are declared in the device tree.
++ */
++ parent = of_get_parent(node);
++ if (!parent)
++ return -EINVAL;
++
++ p_addr_cells = of_n_addr_cells(parent);
++ of_node_put(parent);
++
++ addr_cells = of_n_addr_cells(node);
++ size_cells = of_n_size_cells(node);
++ tuple_len = (p_addr_cells + addr_cells + size_cells) * sizeof(__be32);
++
++ ranges = of_get_property(node, "ranges", &ranges_len);
++ if (ranges == NULL || ranges_len != tuple_len)
++ return -EINVAL;
++
++ base = of_translate_address(node, ranges + addr_cells);
++ if (base == OF_BAD_ADDR)
++ return -EINVAL;
++ size = of_read_number(ranges + addr_cells + p_addr_cells, size_cells);
++
++ /*
++ * Create an mbus address windows.
++ * FIXME: Remove this, together with the above code, once the
++ * address windows are declared in the device tree.
++ */
++ err = mvebu_mbus_add_window(devbus_wins[cs], base, size);
++ if (err < 0)
++ return err;
++
++ /*
++ * We need to create a child device explicitly from here to
++ * guarantee that the child will be probed after the timing
++ * parameters for the bus are written.
++ */
++ err = of_platform_populate(node, NULL, NULL, dev);
++ if (err < 0) {
++ mvebu_mbus_del_window(base, size);
++ return err;
++ }
++
++ return 0;
++}
++
++static const struct of_device_id mvebu_devbus_of_match[] = {
++ { .compatible = "marvell,mvebu-devbus" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, mvebu_devbus_of_match);
++
++static struct platform_driver mvebu_devbus_driver = {
++ .probe = mvebu_devbus_probe,
++ .driver = {
++ .name = "mvebu-devbus",
++ .owner = THIS_MODULE,
++ .of_match_table = mvebu_devbus_of_match,
++ },
++};
++
++static int __init mvebu_devbus_init(void)
++{
++ return platform_driver_register(&mvebu_devbus_driver);
++}
++module_init(mvebu_devbus_init);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Ezequiel Garcia <ezequiel.garcia@free-electrons.com>");
++MODULE_DESCRIPTION("Marvell EBU SoC Device Bus controller");
--- /dev/null
+From 348fc73a301b88ec3f2da8c1f02858c75e79455e Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Tue, 21 May 2013 19:53:09 +0200
+Subject: [PATCH 014/203] arm: mvebu: enable two USB interfaces on the Armada
+ XP GP board
+
+The Armada XP GP board has two USB slots: one on the front side and
+one on the back side. This commit enables the two USB host controllers
+that correspond to those wo USB slots.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-xp-gp.dts | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/arch/arm/boot/dts/armada-xp-gp.dts
++++ b/arch/arm/boot/dts/armada-xp-gp.dts
+@@ -105,6 +105,16 @@
+ phy-mode = "rgmii-id";
+ };
+
++ /* Front-side USB slot */
++ usb@50000 {
++ status = "okay";
++ };
++
++ /* Back-side USB slot */
++ usb@51000 {
++ status = "okay";
++ };
++
+ spi0: spi@10600 {
+ status = "okay";
+
--- /dev/null
+From 34361044442206dd7d10ff3309f8e0713e0fd856 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Thu, 23 May 2013 16:32:51 +0200
+Subject: [PATCH 015/203] pci: mvebu: no longer fake the slot location of
+ downstream devices
+
+By default, the Marvell hardware, for each PCIe interface, exhibits
+the following devices:
+
+ * On slot 0, a "Marvell Memory controller", identical on all PCIe
+ interfaces, and which isn't useful when the Marvell SoC is the PCIe
+ root complex (i.e, the normal case when we run Linux on the Marvell
+ SoC).
+
+ * On slot 1, the real PCIe card connected into the PCIe slot of the
+ board.
+
+So, what the Marvell PCIe driver was doing in its PCI-to-PCI bridge
+emulation is that when the Linux PCI core was trying to access the
+device in slot 0, we were in fact forwarding the configuration
+transaction to the device in slot 1. For all other slots, we were
+telling the Linux PCI core that there was no device connected.
+
+However, new versions of bootloaders from Marvell change the default
+PCIe configuration, and make the real device appear in slot 0, and the
+"Marvell Memory controller" in slot 1.
+
+Therefore, this commit modifies the Marvell PCIe driver to adjust the
+PCIe hardware configuration to make sure that this behavior (real
+device in slot 0, "Marvell Memory controller" in slot 1) is the one
+we'll see regardless of what the bootloader has done. It allows to
+remove the little hack that was forwarding configuration transactions
+on slot 0 to slot 1, which is nice.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ drivers/pci/host/pci-mvebu.c | 19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+--- a/drivers/pci/host/pci-mvebu.c
++++ b/drivers/pci/host/pci-mvebu.c
+@@ -51,6 +51,7 @@
+ #define PCIE_CTRL_X1_MODE 0x0001
+ #define PCIE_STAT_OFF 0x1a04
+ #define PCIE_STAT_BUS 0xff00
++#define PCIE_STAT_DEV 0x1f0000
+ #define PCIE_STAT_LINK_DOWN BIT(0)
+ #define PCIE_DEBUG_CTRL 0x1a60
+ #define PCIE_DEBUG_SOFT_RESET BIT(20)
+@@ -148,6 +149,16 @@ static void mvebu_pcie_set_local_bus_nr(
+ writel(stat, port->base + PCIE_STAT_OFF);
+ }
+
++static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie_port *port, int nr)
++{
++ u32 stat;
++
++ stat = readl(port->base + PCIE_STAT_OFF);
++ stat &= ~PCIE_STAT_DEV;
++ stat |= nr << 16;
++ writel(stat, port->base + PCIE_STAT_OFF);
++}
++
+ /*
+ * Setup PCIE BARs and Address Decode Wins:
+ * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
+@@ -572,8 +583,7 @@ static int mvebu_pcie_wr_conf(struct pci
+
+ /* Access the real PCIe interface */
+ spin_lock_irqsave(&port->conf_lock, flags);
+- ret = mvebu_pcie_hw_wr_conf(port, bus,
+- PCI_DEVFN(1, PCI_FUNC(devfn)),
++ ret = mvebu_pcie_hw_wr_conf(port, bus, devfn,
+ where, size, val);
+ spin_unlock_irqrestore(&port->conf_lock, flags);
+
+@@ -606,8 +616,7 @@ static int mvebu_pcie_rd_conf(struct pci
+
+ /* Access the real PCIe interface */
+ spin_lock_irqsave(&port->conf_lock, flags);
+- ret = mvebu_pcie_hw_rd_conf(port, bus,
+- PCI_DEVFN(1, PCI_FUNC(devfn)),
++ ret = mvebu_pcie_hw_rd_conf(port, bus, devfn,
+ where, size, val);
+ spin_unlock_irqrestore(&port->conf_lock, flags);
+
+@@ -817,6 +826,8 @@ static int __init mvebu_pcie_probe(struc
+ continue;
+ }
+
++ mvebu_pcie_set_local_dev_nr(port, 1);
++
+ if (mvebu_pcie_link_up(port)) {
+ port->haslink = 1;
+ dev_info(&pdev->dev, "PCIe%d.%d: link up\n",
--- /dev/null
+From 10f725e3a9e73aab2e5601206c88cf9cbc599243 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Thu, 23 May 2013 16:32:52 +0200
+Subject: [PATCH 016/203] pci: mvebu: allow the enumeration of devices beyond
+ physical bridges
+
+Until now, the Marvell PCIe driver was only allowing the enumeration
+of the devices in the secondary bus of the emulated PCI-to-PCI
+bridge. This works fine when a PCIe device is directly connected into
+a PCIe slot of the Marvell board.
+
+However, when the device connected in the PCIe slot is a physical PCIe
+bridge, beyond which a real PCIe device is connected, it no longer
+worked, as the driver was preventing the Linux PCI core from seeing
+such devices.
+
+This commit fixes that by ensuring that configuration transactions on
+subordinate busses are properly forwarded on the right PCIe interface.
+
+Thanks to this patch, a PCIe card beyond a PCIe bridge, itself beyond
+the emulated PCI-to-PCI bridge is properly detected, with the
+following layout:
+
+-[0000:00]-+-01.0-[01]----00.0
+ +-09.0-[02-07]----00.0-[03-07]--+-01.0-[04]--
+ | +-05.0-[05]--
+ | +-07.0-[06]--
+ | \-09.0-[07]----00.0
+ \-0a.0-[08]----00.0
+
+Where the PCIe interface that sits beyond the emulated PCI-to-PCI
+bridge at 09.0 allows to access the secondary bus 02, on which there
+is a PCIe bridge that allows to access the 3 to 7 busses, that are
+subordinates to this bridge. And on one of this bus (bus 7), there is
+one real PCIe device connected.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ drivers/pci/host/pci-mvebu.c | 31 ++++++++++++++++++++++++++++---
+ 1 file changed, 28 insertions(+), 3 deletions(-)
+
+--- a/drivers/pci/host/pci-mvebu.c
++++ b/drivers/pci/host/pci-mvebu.c
+@@ -554,7 +554,8 @@ mvebu_pcie_find_port(struct mvebu_pcie *
+ if (bus->number == 0 && port->devfn == devfn)
+ return port;
+ if (bus->number != 0 &&
+- port->bridge.secondary_bus == bus->number)
++ bus->number >= port->bridge.secondary_bus &&
++ bus->number <= port->bridge.subordinate_bus)
+ return port;
+ }
+
+@@ -578,7 +579,18 @@ static int mvebu_pcie_wr_conf(struct pci
+ if (bus->number == 0)
+ return mvebu_sw_pci_bridge_write(port, where, size, val);
+
+- if (!port->haslink || PCI_SLOT(devfn) != 0)
++ if (!port->haslink)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ /*
++ * On the secondary bus, we don't want to expose any other
++ * device than the device physically connected in the PCIe
++ * slot, visible in slot 0. In slot 1, there's a special
++ * Marvell device that only makes sense when the Armada is
++ * used as a PCIe endpoint.
++ */
++ if (bus->number == port->bridge.secondary_bus &&
++ PCI_SLOT(devfn) != 0)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ /* Access the real PCIe interface */
+@@ -609,7 +621,20 @@ static int mvebu_pcie_rd_conf(struct pci
+ if (bus->number == 0)
+ return mvebu_sw_pci_bridge_read(port, where, size, val);
+
+- if (!port->haslink || PCI_SLOT(devfn) != 0) {
++ if (!port->haslink) {
++ *val = 0xffffffff;
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ /*
++ * On the secondary bus, we don't want to expose any other
++ * device than the device physically connected in the PCIe
++ * slot, visible in slot 0. In slot 1, there's a special
++ * Marvell device that only makes sense when the Armada is
++ * used as a PCIe endpoint.
++ */
++ if (bus->number == port->bridge.secondary_bus &&
++ PCI_SLOT(devfn) != 0) {
+ *val = 0xffffffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
--- /dev/null
+From 33e771556f5e1a59c7dbcd953ce858dd3e50ed66 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Thu, 23 May 2013 16:32:53 +0200
+Subject: [PATCH 017/203] pci: mvebu: fix the emulation of the status register
+
+The status register of the PCI configuration space of PCI-to-PCI
+bridges contain some read-only bits, and so write-1-to-clear bits. So,
+the Linux PCI core sometimes writes 0xffff to this status register,
+and in the current PCI-to-PCI bridge emulation code of the Marvell
+driver, we do take all those 1s being written. Even the read-only bits
+are being overwritten.
+
+For now, all the read-only bits should be emulated to have the zero
+value.
+
+The other bits, that are write-1-to-clear bits are used to report
+various kind of errors, and are never set by the emulated bridge, so
+there is no need to support this write-1-to-clear bits mechanism.
+
+As a conclusion, the easiest solution is to simply emulate this status
+register by returning zero when read, and ignore the writes to it.
+
+This has two visible effects:
+
+ * The devsel is no longer 'unknown' in, i.e
+
+ Flags: bus master, 66MHz, user-definable features, ?? devsel, latency 0
+
+ becomes:
+
+ Flags: bus master, 66MHz, user-definable features, fast devsel, latency 0
+
+ in lspci -v.
+
+ This was caused by a value of 11b being read for devsel, which is
+ an invalid value. This 11b value being read was due to a previous
+ write of 0xffff into the status register.
+
+ * The capability list is no longer broken, because we indicate to the
+ Linux PCI core that we don't have a Capabilities Pointer in the PCI
+ configuration space of this bridge. The following message is
+ therefore no longer visible in lspci -v:
+
+ Capabilities: [fc] <chain broken>
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ drivers/pci/host/pci-mvebu.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+--- a/drivers/pci/host/pci-mvebu.c
++++ b/drivers/pci/host/pci-mvebu.c
+@@ -69,7 +69,6 @@ struct mvebu_sw_pci_bridge {
+ u16 vendor;
+ u16 device;
+ u16 command;
+- u16 status;
+ u16 class;
+ u8 interface;
+ u8 revision;
+@@ -359,7 +358,6 @@ static void mvebu_sw_pci_bridge_init(str
+
+ memset(bridge, 0, sizeof(struct mvebu_sw_pci_bridge));
+
+- bridge->status = PCI_STATUS_CAP_LIST;
+ bridge->class = PCI_CLASS_BRIDGE_PCI;
+ bridge->vendor = PCI_VENDOR_ID_MARVELL;
+ bridge->device = MARVELL_EMULATED_PCI_PCI_BRIDGE_ID;
+@@ -386,7 +384,7 @@ static int mvebu_sw_pci_bridge_read(stru
+ break;
+
+ case PCI_COMMAND:
+- *value = bridge->status << 16 | bridge->command;
++ *value = bridge->command;
+ break;
+
+ case PCI_CLASS_REVISION:
+@@ -479,7 +477,6 @@ static int mvebu_sw_pci_bridge_write(str
+ switch (where & ~3) {
+ case PCI_COMMAND:
+ bridge->command = value & 0xffff;
+- bridge->status = value >> 16;
+ break;
+
+ case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_1:
--- /dev/null
+From fc7dfe5cd096f5b5343f01f679a96ebc23e9da67 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Tue, 21 May 2013 12:33:26 +0200
+Subject: [PATCH 018/203] arm: mvebu: fix length of SATA registers area in
+ .dtsi
+
+The length of the registers area for the Marvell 370/XP SATA
+controller was incorrect in the .dtsi: 0x2400 while it should have
+been 0x5000. Until now, this problem wasn't noticed because there was
+a large static mapping for all I/Os set up by ->map_io(). But since
+we're going to get rid of this static mapping, we need to ensure that
+the register areas are properly sized.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-370-xp.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/armada-370-xp.dtsi
++++ b/arch/arm/boot/dts/armada-370-xp.dtsi
+@@ -80,7 +80,7 @@
+
+ sata@a0000 {
+ compatible = "marvell,orion-sata";
+- reg = <0xa0000 0x2400>;
++ reg = <0xa0000 0x5000>;
+ interrupts = <55>;
+ clocks = <&gateclk 15>, <&gateclk 30>;
+ clock-names = "0", "1";
--- /dev/null
+From d887da014c3fabf5fa4da47b143edc069e72fd62 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Tue, 21 May 2013 12:33:27 +0200
+Subject: [PATCH 019/203] arm: mvebu: fix length of Ethernet registers area in
+ .dtsi
+
+The length of the registers area for the Marvell 370/XP Ethernet
+controller was incorrect in the .dtsi: 0x2400 while it should have
+been 0x4000. Until now, this problem wasn't noticed because there was
+a large static mapping for all I/Os set up by ->map_io(). But since
+we're going to get rid of this static mapping, we need to ensure that
+the register areas are properly sized.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-370-xp.dtsi | 4 ++--
+ arch/arm/boot/dts/armada-xp-mv78460.dtsi | 2 +-
+ arch/arm/boot/dts/armada-xp.dtsi | 2 +-
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/arch/arm/boot/dts/armada-370-xp.dtsi
++++ b/arch/arm/boot/dts/armada-370-xp.dtsi
+@@ -96,7 +96,7 @@
+
+ ethernet@70000 {
+ compatible = "marvell,armada-370-neta";
+- reg = <0x70000 0x2500>;
++ reg = <0x70000 0x4000>;
+ interrupts = <8>;
+ clocks = <&gateclk 4>;
+ status = "disabled";
+@@ -104,7 +104,7 @@
+
+ ethernet@74000 {
+ compatible = "marvell,armada-370-neta";
+- reg = <0x74000 0x2500>;
++ reg = <0x74000 0x4000>;
+ interrupts = <10>;
+ clocks = <&gateclk 3>;
+ status = "disabled";
+--- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi
++++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
+@@ -107,7 +107,7 @@
+
+ ethernet@34000 {
+ compatible = "marvell,armada-370-neta";
+- reg = <0x34000 0x2500>;
++ reg = <0x34000 0x4000>;
+ interrupts = <14>;
+ clocks = <&gateclk 1>;
+ status = "disabled";
+--- a/arch/arm/boot/dts/armada-xp.dtsi
++++ b/arch/arm/boot/dts/armada-xp.dtsi
+@@ -88,7 +88,7 @@
+
+ ethernet@30000 {
+ compatible = "marvell,armada-370-neta";
+- reg = <0x30000 0x2500>;
++ reg = <0x30000 0x4000>;
+ interrupts = <12>;
+ clocks = <&gateclk 2>;
+ status = "disabled";
--- /dev/null
+From 25d3318a445c4f4360f86bf6d1d1a320d9646bb5 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Tue, 4 Jun 2013 04:52:23 +0000
+Subject: [PATCH 020/203] net: mvneta: read MAC address from hardware when
+ available
+
+This patch improves the logic used by the mvneta driver to find a MAC
+address for a particular interface. Until now, it was only looking at
+the Device Tree, and if no address was found, was falling back to
+generating a random MAC address.
+
+This patch adds the intermediate solution of reading the MAC address
+from the hardware registers, in case it has been set by the
+bootloader. So the order is now:
+
+ 1) MAC address from the Device Tree
+ 2) MAC address from the hardware registers
+ 3) Random MAC address
+
+This requires moving the MAC address initialization a little bit later
+in the ->probe() code, because it now requires the hardware registers
+to be remapped.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Cc: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Cc: Joe Perches <joe@perches.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/marvell/mvneta.c | 44 ++++++++++++++++++++++++++++-------
+ 1 file changed, 35 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/ethernet/marvell/mvneta.c
++++ b/drivers/net/ethernet/marvell/mvneta.c
+@@ -2260,6 +2260,21 @@ static int mvneta_change_mtu(struct net_
+ return 0;
+ }
+
++/* Get mac address */
++static void mvneta_get_mac_addr(struct mvneta_port *pp, unsigned char *addr)
++{
++ u32 mac_addr_l, mac_addr_h;
++
++ mac_addr_l = mvreg_read(pp, MVNETA_MAC_ADDR_LOW);
++ mac_addr_h = mvreg_read(pp, MVNETA_MAC_ADDR_HIGH);
++ addr[0] = (mac_addr_h >> 24) & 0xFF;
++ addr[1] = (mac_addr_h >> 16) & 0xFF;
++ addr[2] = (mac_addr_h >> 8) & 0xFF;
++ addr[3] = mac_addr_h & 0xFF;
++ addr[4] = (mac_addr_l >> 8) & 0xFF;
++ addr[5] = mac_addr_l & 0xFF;
++}
++
+ /* Handle setting mac address */
+ static int mvneta_set_mac_addr(struct net_device *dev, void *addr)
+ {
+@@ -2678,7 +2693,9 @@ static int mvneta_probe(struct platform_
+ u32 phy_addr;
+ struct mvneta_port *pp;
+ struct net_device *dev;
+- const char *mac_addr;
++ const char *dt_mac_addr;
++ char hw_mac_addr[ETH_ALEN];
++ const char *mac_from;
+ int phy_mode;
+ int err;
+
+@@ -2714,13 +2731,6 @@ static int mvneta_probe(struct platform_
+ goto err_free_irq;
+ }
+
+- mac_addr = of_get_mac_address(dn);
+-
+- if (!mac_addr || !is_valid_ether_addr(mac_addr))
+- eth_hw_addr_random(dev);
+- else
+- memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
+-
+ dev->tx_queue_len = MVNETA_MAX_TXD;
+ dev->watchdog_timeo = 5 * HZ;
+ dev->netdev_ops = &mvneta_netdev_ops;
+@@ -2751,6 +2761,21 @@ static int mvneta_probe(struct platform_
+
+ clk_prepare_enable(pp->clk);
+
++ dt_mac_addr = of_get_mac_address(dn);
++ if (dt_mac_addr && is_valid_ether_addr(dt_mac_addr)) {
++ mac_from = "device tree";
++ memcpy(dev->dev_addr, dt_mac_addr, ETH_ALEN);
++ } else {
++ mvneta_get_mac_addr(pp, hw_mac_addr);
++ if (is_valid_ether_addr(hw_mac_addr)) {
++ mac_from = "hardware";
++ memcpy(dev->dev_addr, hw_mac_addr, ETH_ALEN);
++ } else {
++ mac_from = "random";
++ eth_hw_addr_random(dev);
++ }
++ }
++
+ pp->tx_done_timer.data = (unsigned long)dev;
+
+ pp->tx_ring_size = MVNETA_MAX_TXD;
+@@ -2783,7 +2808,8 @@ static int mvneta_probe(struct platform_
+ goto err_deinit;
+ }
+
+- netdev_info(dev, "mac: %pM\n", dev->dev_addr);
++ netdev_info(dev, "Using %s mac address %pM\n", mac_from,
++ dev->dev_addr);
+
+ platform_set_drvdata(pdev, pp->dev);
+
--- /dev/null
+From 67373874e07eb8c54ab27f8fe9998690e50b1e91 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Thu, 6 Jun 2013 11:21:23 +0200
+Subject: [PATCH 021/203] arm: mvebu: armada-xp-db: ensure PCIe range is
+ specified
+
+The ranges DT entry needed by the PCIe controller is defined at the
+SoC .dtsi level. However, some boards have a NOR flash, and to support
+it, they need to override the SoC-level ranges property to add an
+additional range. Since PCIe and NOR support came separately, some
+boards were not properly changed to include the PCIe range in their
+ranges property at the .dts level.
+
+This commit fixes those platforms.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-xp-db.dts | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/arm/boot/dts/armada-xp-db.dts
++++ b/arch/arm/boot/dts/armada-xp-db.dts
+@@ -31,6 +31,7 @@
+
+ soc {
+ ranges = <0 0 0xd0000000 0x100000 /* Internal registers 1MiB */
++ 0xe0000000 0 0xe0000000 0x8100000 /* PCIe */
+ 0xf0000000 0 0xf0000000 0x1000000>; /* Device Bus, NOR 16MiB */
+
+ internal-regs {
--- /dev/null
+From 35e8d985e056f583290406258e3f17789bd05bce Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Fri, 7 Jun 2013 13:47:38 -0300
+Subject: [PATCH 022/203] bus: mvebu-mbus: Use pr_fmt
+
+In order to clean message printing, we replace pr_info with pr_fmt.
+This is purely cosmetic change, with the sole purpose of making
+the code a bit more readable.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Acked-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ drivers/bus/mvebu-mbus.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/bus/mvebu-mbus.c
++++ b/drivers/bus/mvebu-mbus.c
+@@ -49,6 +49,8 @@
+ * configuration (file 'devices').
+ */
+
++#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
++
+ #include <linux/kernel.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+@@ -762,7 +764,7 @@ int mvebu_mbus_add_window_remap_flags(co
+ break;
+
+ if (!s->soc->map[i].name) {
+- pr_err("mvebu-mbus: unknown device '%s'\n", devname);
++ pr_err("unknown device '%s'\n", devname);
+ return -ENODEV;
+ }
+
+@@ -775,7 +777,7 @@ int mvebu_mbus_add_window_remap_flags(co
+ attr |= 0x28;
+
+ if (!mvebu_mbus_window_conflicts(s, base, size, target, attr)) {
+- pr_err("mvebu-mbus: cannot add window '%s', conflicts with another window\n",
++ pr_err("cannot add window '%s', conflicts with another window\n",
+ devname);
+ return -EINVAL;
+ }
+@@ -842,7 +844,7 @@ int __init mvebu_mbus_init(const char *s
+ break;
+
+ if (!of_id->compatible) {
+- pr_err("mvebu-mbus: could not find a matching SoC family\n");
++ pr_err("could not find a matching SoC family\n");
+ return -ENODEV;
+ }
+
--- /dev/null
+From df8ceea297967c3452a514bbde715acebf3bda29 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Fri, 7 Jun 2013 13:47:49 -0300
+Subject: [PATCH 023/203] ARM: mvebu: Remove device tree unused properties on
+ A370
+
+These properties are not needed so it's safe to remove them.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Acked-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-370.dtsi | 4 ----
+ 1 file changed, 4 deletions(-)
+
+--- a/arch/arm/boot/dts/armada-370.dtsi
++++ b/arch/arm/boot/dts/armada-370.dtsi
+@@ -180,10 +180,6 @@
+
+ bus-range = <0x00 0xff>;
+
+- reg = <0x40000 0x2000>, <0x80000 0x2000>;
+-
+- reg-names = "pcie0.0", "pcie1.0";
+-
+ ranges = <0x82000000 0 0x40000 0x40000 0 0x00002000 /* Port 0.0 registers */
+ 0x82000000 0 0x80000 0x80000 0 0x00002000 /* Port 1.0 registers */
+ 0x82000000 0 0xe0000000 0xe0000000 0 0x08000000 /* non-prefetchable memory */
--- /dev/null
+From 9398729313b826469fede3acda5fedd1eb21cb3e Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Wed, 5 Jun 2013 09:04:54 +0200
+Subject: [PATCH 024/203] arm: mvebu: remove dependency of SMP init on static
+ I/O mapping
+
+The ->smp_init_cpus() function is called very early during boot, at a
+point where dynamic I/O mappings are not yet possible. However, in the
+Armada 370/XP implementation of this function, we have to get the
+number of CPUs. We used to do that by accessing a hardware register,
+which requires relying on a static I/O mapping set up by
+->map_io(). Not only this requires hardcoding a virtual address, but
+it also prevents us from removing the static I/O mapping.
+
+So this commit changes the way used to get the number of CPUs: we now
+use the Device Tree, which is a representation of the hardware, and
+provides us the number of available CPUs. This is also more accurate,
+because it potentially allows to boot the Linux kernel on only a
+number of CPUs given by the Device Tree, instead of unconditionally on
+all CPUs.
+
+As a consequence, the coherency_get_cpu_count() function becomes no
+longer used, so we remove it.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/mach-mvebu/coherency.c | 12 ------------
+ arch/arm/mach-mvebu/coherency.h | 4 ----
+ arch/arm/mach-mvebu/common.h | 2 ++
+ arch/arm/mach-mvebu/platsmp.c | 10 +++++++++-
+ 4 files changed, 11 insertions(+), 17 deletions(-)
+
+--- a/arch/arm/mach-mvebu/coherency.c
++++ b/arch/arm/mach-mvebu/coherency.c
+@@ -47,18 +47,6 @@ static struct of_device_id of_coherency_
+ { /* end of list */ },
+ };
+
+-#ifdef CONFIG_SMP
+-int coherency_get_cpu_count(void)
+-{
+- int reg, cnt;
+-
+- reg = readl(coherency_base + COHERENCY_FABRIC_CFG_OFFSET);
+- cnt = (reg & 0xF) + 1;
+-
+- return cnt;
+-}
+-#endif
+-
+ /* Function defined in coherency_ll.S */
+ int ll_set_cpu_coherent(void __iomem *base_addr, unsigned int hw_cpu_id);
+
+--- a/arch/arm/mach-mvebu/coherency.h
++++ b/arch/arm/mach-mvebu/coherency.h
+@@ -14,10 +14,6 @@
+ #ifndef __MACH_370_XP_COHERENCY_H
+ #define __MACH_370_XP_COHERENCY_H
+
+-#ifdef CONFIG_SMP
+-int coherency_get_cpu_count(void);
+-#endif
+-
+ int set_cpu_coherent(int cpu_id, int smp_group_id);
+ int coherency_init(void);
+
+--- a/arch/arm/mach-mvebu/common.h
++++ b/arch/arm/mach-mvebu/common.h
+@@ -15,6 +15,8 @@
+ #ifndef __ARCH_MVEBU_COMMON_H
+ #define __ARCH_MVEBU_COMMON_H
+
++#define ARMADA_XP_MAX_CPUS 4
++
+ void mvebu_restart(char mode, const char *cmd);
+
+ void armada_370_xp_init_irq(void);
+--- a/arch/arm/mach-mvebu/platsmp.c
++++ b/arch/arm/mach-mvebu/platsmp.c
+@@ -88,8 +88,16 @@ static int __cpuinit armada_xp_boot_seco
+
+ static void __init armada_xp_smp_init_cpus(void)
+ {
++ struct device_node *np;
+ unsigned int i, ncores;
+- ncores = coherency_get_cpu_count();
++
++ np = of_find_node_by_name(NULL, "cpus");
++ if (!np)
++ panic("No 'cpus' node found\n");
++
++ ncores = of_get_child_count(np);
++ if (ncores == 0 || ncores > ARMADA_XP_MAX_CPUS)
++ panic("Invalid number of CPUs in DT\n");
+
+ /* Limit possible CPUs to defconfig */
+ if (ncores > nr_cpu_ids) {
--- /dev/null
+From a4dd628f515f361cecfae08e568891442042e4e2 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Wed, 5 Jun 2013 09:04:55 +0200
+Subject: [PATCH 025/203] arm: mvebu: avoid hardcoded virtual address in
+ coherency code
+
+Now that the coherency_get_cpu_count() function no longer requires a
+very early mapping of the coherency unit registers, we can avoid the
+hardcoded virtual address in coherency.c. However, the coherency
+features are still used quite early, so we need to do the of_iomap()
+early enough, at the ->init_timer() level, so we have the call of
+coherency_init() at this point.
+
+Unfortunately, at ->init_timer() time, it is not possible to register
+a bus notifier, so we add a separate coherency_late_init() function
+that gets called as as postcore_initcall(), when bus notifiers are
+available.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/mach-mvebu/armada-370-xp.c | 2 +-
+ arch/arm/mach-mvebu/coherency.c | 20 ++++++++++----------
+ 2 files changed, 11 insertions(+), 11 deletions(-)
+
+--- a/arch/arm/mach-mvebu/armada-370-xp.c
++++ b/arch/arm/mach-mvebu/armada-370-xp.c
+@@ -47,6 +47,7 @@ static void __init armada_370_xp_timer_a
+ {
+ mvebu_clocks_init();
+ armada_370_xp_timer_init();
++ coherency_init();
+ }
+
+ static void __init armada_370_xp_init_early(void)
+@@ -76,7 +77,6 @@ static void __init armada_370_xp_init_ea
+ static void __init armada_370_xp_dt_init(void)
+ {
+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+- coherency_init();
+ }
+
+ static const char * const armada_370_xp_dt_compat[] = {
+--- a/arch/arm/mach-mvebu/coherency.c
++++ b/arch/arm/mach-mvebu/coherency.c
+@@ -27,14 +27,7 @@
+ #include <asm/smp_plat.h>
+ #include "armada-370-xp.h"
+
+-/*
+- * Some functions in this file are called very early during SMP
+- * initialization. At that time the device tree framework is not yet
+- * ready, and it is not possible to get the register address to
+- * ioremap it. That's why the pointer below is given with an initial
+- * value matching its virtual mapping
+- */
+-static void __iomem *coherency_base = ARMADA_370_XP_REGS_VIRT_BASE + 0x20200;
++static void __iomem *coherency_base;
+ static void __iomem *coherency_cpu_base;
+
+ /* Coherency fabric registers */
+@@ -135,9 +128,16 @@ int __init coherency_init(void)
+ coherency_base = of_iomap(np, 0);
+ coherency_cpu_base = of_iomap(np, 1);
+ set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
+- bus_register_notifier(&platform_bus_type,
+- &mvebu_hwcc_platform_nb);
+ }
+
+ return 0;
+ }
++
++static int __init coherency_late_init(void)
++{
++ bus_register_notifier(&platform_bus_type,
++ &mvebu_hwcc_platform_nb);
++ return 0;
++}
++
++postcore_initcall(coherency_late_init);
--- /dev/null
+From c7c7e6309ae12f2cb0d9053875876b57bb7587e4 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Wed, 5 Jun 2013 09:04:56 +0200
+Subject: [PATCH 026/203] arm: mvebu: move cache and mvebu-mbus initialization
+ later
+
+Current, the L2 cache and the mvebu-mbus drivers are initialized at
+->init_early() time. However, at ->init_early() time, ioremap() only
+works if a static I/O mapping has already been put in place. If it's
+not the case, it tries to do a memory allocation with kmalloc() which
+is not possible so early at this stage of the initialization.
+
+Since we want to get rid of the static I/O mapping, we cannot
+initialize the L2 cache driver and the mvebu-mbus driver so early. So,
+we move their initialization to the ->init_time() level, which is
+slightly later (so ioremap() works properly), but sufficiently early
+to be before the call of the ->smp_prepare_cpus() hook, which creates
+an address decoding window for the BootROM, which requires the
+mvebu-mbus driver to be properly initialized.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/mach-mvebu/armada-370-xp.c | 8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+--- a/arch/arm/mach-mvebu/armada-370-xp.c
++++ b/arch/arm/mach-mvebu/armada-370-xp.c
+@@ -45,14 +45,11 @@ static void __init armada_370_xp_map_io(
+
+ static void __init armada_370_xp_timer_and_clk_init(void)
+ {
++ char *mbus_soc_name;
++
+ mvebu_clocks_init();
+ armada_370_xp_timer_init();
+ coherency_init();
+-}
+-
+-static void __init armada_370_xp_init_early(void)
+-{
+- char *mbus_soc_name;
+
+ /*
+ * This initialization will be replaced by a DT-based
+@@ -88,7 +85,6 @@ DT_MACHINE_START(ARMADA_XP_DT, "Marvell
+ .smp = smp_ops(armada_xp_smp_ops),
+ .init_machine = armada_370_xp_dt_init,
+ .map_io = armada_370_xp_map_io,
+- .init_early = armada_370_xp_init_early,
+ .init_irq = irqchip_init,
+ .init_time = armada_370_xp_timer_and_clk_init,
+ .restart = mvebu_restart,
--- /dev/null
+From fe4fce3c521f5d9f3a64c4d06a73a5e6b7324116 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Wed, 5 Jun 2013 09:04:57 +0200
+Subject: [PATCH 027/203] arm: mvebu: remove hardcoded static I/O mapping
+
+Now that we have removed the need of the static I/O mapping for early
+initialization reasons, and fixed the registers area length that were
+broken, we can get rid of the static I/O mapping. Only the earlyprintk
+mapping needs to be set up, using the debug_ll_io_init() helper
+function.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/mach-mvebu/armada-370-xp.c | 11 +----------
+ arch/arm/mach-mvebu/armada-370-xp.h | 2 --
+ 2 files changed, 1 insertion(+), 12 deletions(-)
+
+--- a/arch/arm/mach-mvebu/armada-370-xp.c
++++ b/arch/arm/mach-mvebu/armada-370-xp.c
+@@ -29,18 +29,9 @@
+ #include "common.h"
+ #include "coherency.h"
+
+-static struct map_desc armada_370_xp_io_desc[] __initdata = {
+- {
+- .virtual = (unsigned long) ARMADA_370_XP_REGS_VIRT_BASE,
+- .pfn = __phys_to_pfn(ARMADA_370_XP_REGS_PHYS_BASE),
+- .length = ARMADA_370_XP_REGS_SIZE,
+- .type = MT_DEVICE,
+- },
+-};
+-
+ static void __init armada_370_xp_map_io(void)
+ {
+- iotable_init(armada_370_xp_io_desc, ARRAY_SIZE(armada_370_xp_io_desc));
++ debug_ll_io_init();
+ }
+
+ static void __init armada_370_xp_timer_and_clk_init(void)
+--- a/arch/arm/mach-mvebu/armada-370-xp.h
++++ b/arch/arm/mach-mvebu/armada-370-xp.h
+@@ -16,8 +16,6 @@
+ #define __MACH_ARMADA_370_XP_H
+
+ #define ARMADA_370_XP_REGS_PHYS_BASE 0xd0000000
+-#define ARMADA_370_XP_REGS_VIRT_BASE IOMEM(0xfec00000)
+-#define ARMADA_370_XP_REGS_SIZE SZ_1M
+
+ /* These defines can go away once mvebu-mbus has a DT binding */
+ #define ARMADA_370_XP_MBUS_WINS_BASE (ARMADA_370_XP_REGS_PHYS_BASE + 0x20000)
--- /dev/null
+From 88260610ea7a2c5a164721af28f59856880221b4 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Thu, 6 Jun 2013 12:24:28 +0200
+Subject: [PATCH 028/203] arm: mvebu: don't hardcode a physical address in
+ headsmp.S
+
+Now that the coherency_init() function is called a bit earlier, we can
+actually read the physical address of the coherency unit registers
+from the Device Tree, and communicate that to the headsmp.S code,
+which avoids hardcoding a physical address.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Will Deacon <will.deacon@arm.com>
+Acked-by: Nicolas Pitre <nico@linaro.org>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/mach-mvebu/coherency.c | 12 ++++++++++++
+ arch/arm/mach-mvebu/headsmp.S | 16 ++++++++--------
+ 2 files changed, 20 insertions(+), 8 deletions(-)
+
+--- a/arch/arm/mach-mvebu/coherency.c
++++ b/arch/arm/mach-mvebu/coherency.c
+@@ -25,8 +25,10 @@
+ #include <linux/dma-mapping.h>
+ #include <linux/platform_device.h>
+ #include <asm/smp_plat.h>
++#include <asm/cacheflush.h>
+ #include "armada-370-xp.h"
+
++unsigned long __cpuinitdata coherency_phys_base;
+ static void __iomem *coherency_base;
+ static void __iomem *coherency_cpu_base;
+
+@@ -124,7 +126,17 @@ int __init coherency_init(void)
+
+ np = of_find_matching_node(NULL, of_coherency_table);
+ if (np) {
++ struct resource res;
+ pr_info("Initializing Coherency fabric\n");
++ of_address_to_resource(np, 0, &res);
++ coherency_phys_base = res.start;
++ /*
++ * Ensure secondary CPUs will see the updated value,
++ * which they read before they join the coherency
++ * fabric, and therefore before they are coherent with
++ * the boot CPU cache.
++ */
++ sync_cache_w(&coherency_phys_base);
+ coherency_base = of_iomap(np, 0);
+ coherency_cpu_base = of_iomap(np, 1);
+ set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
+--- a/arch/arm/mach-mvebu/headsmp.S
++++ b/arch/arm/mach-mvebu/headsmp.S
+@@ -21,12 +21,6 @@
+ #include <linux/linkage.h>
+ #include <linux/init.h>
+
+-/*
+- * At this stage the secondary CPUs don't have acces yet to the MMU, so
+- * we have to provide physical addresses
+- */
+-#define ARMADA_XP_CFB_BASE 0xD0020200
+-
+ __CPUINIT
+
+ /*
+@@ -35,15 +29,21 @@
+ * startup
+ */
+ ENTRY(armada_xp_secondary_startup)
++ /* Get coherency fabric base physical address */
++ adr r0, 1f
++ ldr r1, [r0]
++ ldr r0, [r0, r1]
+
+ /* Read CPU id */
+ mrc p15, 0, r1, c0, c0, 5
+ and r1, r1, #0xF
+
+ /* Add CPU to coherency fabric */
+- ldr r0, =ARMADA_XP_CFB_BASE
+-
+ bl ll_set_cpu_coherent
+ b secondary_startup
+
+ ENDPROC(armada_xp_secondary_startup)
++
++ .align 2
++1:
++ .long coherency_phys_base - .
--- /dev/null
+From 070469397154c87b14fab48d2fc231ba83007c1b Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Wed, 5 Jun 2013 09:04:59 +0200
+Subject: [PATCH 029/203] arm: mvebu: don't hardcode the physical address for
+ mvebu-mbus
+
+Since the mvebu-mbus driver doesn't yet have a DT binding (and this DT
+binding may not necessarily be ready for 3.11), the physical address
+of the mvebu-mbus registers are currently hardcoded. This doesn't play
+well with the fact that the internal registers base address may be
+different depending on the bootloader.
+
+In order to have only one central place for the physical address of
+the internal registers, we now use of_translate_address() to translate
+the mvebu-mbus register offsets into the real physical address, by
+using DT-based address translation. This will go away once the
+mvebu-mbus driver gains a proper DT binding.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/mach-mvebu/armada-370-xp.c | 38 ++++++++++++++++++++++++++-----------
+ arch/arm/mach-mvebu/armada-370-xp.h | 8 --------
+ 2 files changed, 27 insertions(+), 19 deletions(-)
+
+--- a/arch/arm/mach-mvebu/armada-370-xp.c
++++ b/arch/arm/mach-mvebu/armada-370-xp.c
+@@ -14,6 +14,7 @@
+
+ #include <linux/kernel.h>
+ #include <linux/init.h>
++#include <linux/of_address.h>
+ #include <linux/of_platform.h>
+ #include <linux/io.h>
+ #include <linux/time-armada-370-xp.h>
+@@ -34,29 +35,44 @@ static void __init armada_370_xp_map_io(
+ debug_ll_io_init();
+ }
+
+-static void __init armada_370_xp_timer_and_clk_init(void)
++/*
++ * This initialization will be replaced by a DT-based
++ * initialization once the mvebu-mbus driver gains DT support.
++ */
++
++#define ARMADA_370_XP_MBUS_WINS_OFFS 0x20000
++#define ARMADA_370_XP_MBUS_WINS_SIZE 0x100
++#define ARMADA_370_XP_SDRAM_WINS_OFFS 0x20180
++#define ARMADA_370_XP_SDRAM_WINS_SIZE 0x20
++
++static void __init armada_370_xp_mbus_init(void)
+ {
+ char *mbus_soc_name;
++ struct device_node *dn;
++ const __be32 mbus_wins_offs = cpu_to_be32(ARMADA_370_XP_MBUS_WINS_OFFS);
++ const __be32 sdram_wins_offs = cpu_to_be32(ARMADA_370_XP_SDRAM_WINS_OFFS);
+
+- mvebu_clocks_init();
+- armada_370_xp_timer_init();
+- coherency_init();
+-
+- /*
+- * This initialization will be replaced by a DT-based
+- * initialization once the mvebu-mbus driver gains DT support.
+- */
+ if (of_machine_is_compatible("marvell,armada370"))
+ mbus_soc_name = "marvell,armada370-mbus";
+ else
+ mbus_soc_name = "marvell,armadaxp-mbus";
+
++ dn = of_find_node_by_name(NULL, "internal-regs");
++ BUG_ON(!dn);
++
+ mvebu_mbus_init(mbus_soc_name,
+- ARMADA_370_XP_MBUS_WINS_BASE,
++ of_translate_address(dn, &mbus_wins_offs),
+ ARMADA_370_XP_MBUS_WINS_SIZE,
+- ARMADA_370_XP_SDRAM_WINS_BASE,
++ of_translate_address(dn, &sdram_wins_offs),
+ ARMADA_370_XP_SDRAM_WINS_SIZE);
++}
+
++static void __init armada_370_xp_timer_and_clk_init(void)
++{
++ mvebu_clocks_init();
++ armada_370_xp_timer_init();
++ coherency_init();
++ armada_370_xp_mbus_init();
+ #ifdef CONFIG_CACHE_L2X0
+ l2x0_of_init(0, ~0UL);
+ #endif
+--- a/arch/arm/mach-mvebu/armada-370-xp.h
++++ b/arch/arm/mach-mvebu/armada-370-xp.h
+@@ -15,14 +15,6 @@
+ #ifndef __MACH_ARMADA_370_XP_H
+ #define __MACH_ARMADA_370_XP_H
+
+-#define ARMADA_370_XP_REGS_PHYS_BASE 0xd0000000
+-
+-/* These defines can go away once mvebu-mbus has a DT binding */
+-#define ARMADA_370_XP_MBUS_WINS_BASE (ARMADA_370_XP_REGS_PHYS_BASE + 0x20000)
+-#define ARMADA_370_XP_MBUS_WINS_SIZE 0x100
+-#define ARMADA_370_XP_SDRAM_WINS_BASE (ARMADA_370_XP_REGS_PHYS_BASE + 0x20180)
+-#define ARMADA_370_XP_SDRAM_WINS_SIZE 0x20
+-
+ #ifdef CONFIG_SMP
+ #include <linux/cpumask.h>
+
--- /dev/null
+From 70c30ca997919a4b8c9051a3903f30c79c735f12 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Wed, 5 Jun 2013 09:05:00 +0200
+Subject: [PATCH 030/203] arm: mvebu: add another earlyprintk Kconfig option
+
+In order to support both old and new bootloaders, we add a new Kconfig
+option for the earlyprintk UART selection. The existing option allows
+to work with old bootloaders (that keep the internal registers mapped
+at 0xd0000000), while the newly introduced option allows to work with
+new bootloaders (that remap the internal registers at 0xf1000000).
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/Kconfig.debug | 30 ++++++++++++++++++++++++++++--
+ arch/arm/include/debug/mvebu.S | 5 +++++
+ 2 files changed, 33 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/Kconfig.debug
++++ b/arch/arm/Kconfig.debug
+@@ -303,12 +303,37 @@ choice
+ their output to the serial port on MSM 8960 devices.
+
+ config DEBUG_MVEBU_UART
+- bool "Kernel low-level debugging messages via MVEBU UART"
++ bool "Kernel low-level debugging messages via MVEBU UART (old bootloaders)"
+ depends on ARCH_MVEBU
+ help
+ Say Y here if you want kernel low-level debugging support
+ on MVEBU based platforms.
+
++ This option should be used with the old bootloaders
++ that left the internal registers mapped at
++ 0xd0000000. As of today, this is the case on
++ platforms such as the Globalscale Mirabox or the
++ Plathome OpenBlocks AX3, when using the original
++ bootloader.
++
++ If the wrong DEBUG_MVEBU_UART* option is selected,
++ when u-boot hands over to the kernel, the system
++ silently crashes, with no serial output at all.
++
++ config DEBUG_MVEBU_UART_ALTERNATE
++ bool "Kernel low-level debugging messages via MVEBU UART (new bootloaders)"
++ depends on ARCH_MVEBU
++ help
++ Say Y here if you want kernel low-level debugging support
++ on MVEBU based platforms.
++
++ This option should be used with the new bootloaders
++ that remap the internal registers at 0xf1000000.
++
++ If the wrong DEBUG_MVEBU_UART* option is selected,
++ when u-boot hands over to the kernel, the system
++ silently crashes, with no serial output at all.
++
+ config DEBUG_NOMADIK_UART
+ bool "Kernel low-level debugging messages via NOMADIK UART"
+ depends on ARCH_NOMADIK
+@@ -632,7 +657,8 @@ config DEBUG_LL_INCLUDE
+ DEBUG_IMX51_UART || \
+ DEBUG_IMX53_UART ||\
+ DEBUG_IMX6Q_UART
+- default "debug/mvebu.S" if DEBUG_MVEBU_UART
++ default "debug/mvebu.S" if DEBUG_MVEBU_UART || \
++ DEBUG_MVEBU_UART_ALTERNATE
+ default "debug/mxs.S" if DEBUG_IMX23_UART || DEBUG_IMX28_UART
+ default "debug/nomadik.S" if DEBUG_NOMADIK_UART
+ default "debug/omap2plus.S" if DEBUG_OMAP2PLUS_UART
+--- a/arch/arm/include/debug/mvebu.S
++++ b/arch/arm/include/debug/mvebu.S
+@@ -11,7 +11,12 @@
+ * published by the Free Software Foundation.
+ */
+
++#ifdef CONFIG_DEBUG_MVEBU_UART_ALTERNATE
++#define ARMADA_370_XP_REGS_PHYS_BASE 0xf1000000
++#else
+ #define ARMADA_370_XP_REGS_PHYS_BASE 0xd0000000
++#endif
++
+ #define ARMADA_370_XP_REGS_VIRT_BASE 0xfec00000
+
+ .macro addruart, rp, rv, tmp
--- /dev/null
+From 7a3b99b8d16f2eb9ae5ac4ddf5e201eacdfacbf4 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Wed, 5 Jun 2013 09:05:01 +0200
+Subject: [PATCH 031/203] arm: mvebu: disable DEBUG_LL/EARLY_PRINTK in
+ defconfig
+
+Now that we have two different addresses for the UART, depending on
+which bootloader is used, it is no longer desirable to enable
+earlyprintk by default in the defconfig. Users who need earlyprintk
+support will have to enable it explicitly, and select the right UART
+configuration depending on their platform.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Acked-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/configs/mvebu_defconfig | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/arch/arm/configs/mvebu_defconfig
++++ b/arch/arm/configs/mvebu_defconfig
+@@ -100,5 +100,3 @@ CONFIG_TIMER_STATS=y
+ # CONFIG_DEBUG_BUGVERBOSE is not set
+ CONFIG_DEBUG_INFO=y
+ CONFIG_DEBUG_USER=y
+-CONFIG_DEBUG_LL=y
+-CONFIG_EARLY_PRINTK=y
--- /dev/null
+From e552d168344e941a1781682207269dbfd27850b1 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Tue, 18 Jun 2013 15:37:41 +0200
+Subject: [PATCH 032/203] arm: mvebu: enable mini-PCIe connectors on Armada 370
+ RD
+
+The Armada 370 RD board has two internal mini-PCIe connectors. This
+commit adds the necessary Device Tree informations to enable the usage
+of those mini-PCIe connectors.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Cc: Florian Fainelli <florian@openwrt.org>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-370-rd.dts | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/arch/arm/boot/dts/armada-370-rd.dts
++++ b/arch/arm/boot/dts/armada-370-rd.dts
+@@ -85,6 +85,22 @@
+ gpios = <&gpio0 6 1>;
+ };
+ };
++
++ pcie-controller {
++ status = "okay";
++
++ /* Internal mini-PCIe connector */
++ pcie@1,0 {
++ /* Port 0, Lane 0 */
++ status = "okay";
++ };
++
++ /* Internal mini-PCIe connector */
++ pcie@2,0 {
++ /* Port 1, Lane 0 */
++ status = "okay";
++ };
++ };
+ };
+ };
+ };
--- /dev/null
+From 3891658a01af7e875d4c176ebb5d713d74a6e998 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Thu, 20 Jun 2013 09:45:26 +0200
+Subject: [PATCH 033/203] arm: mvebu: fix coherency_late_init() for
+ multiplatform
+
+As noticed by Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>, commit
+865e0527d2d7 ('arm: mvebu: avoid hardcoded virtual address in
+coherency code') added a postcore_initcall() to register the bus
+notifier that the mvebu code needs to apply correct DMA operations on
+its platform devices breaks the multiplatform boot on other platforms,
+because the bus notifier registration is unconditional.
+
+This commit fixes that by registering the bus notifier only if we have
+the mvebu coherency unit described in the Device Tree. The conditional
+used is exactly the same in which the bus_register_notifier() call was
+originally enclosed before 865e0527d2d7 ('arm: mvebu: avoid hardcoded
+virtual address in coherency code').
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Reported-by: Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
+Acked-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/mach-mvebu/coherency.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/mach-mvebu/coherency.c
++++ b/arch/arm/mach-mvebu/coherency.c
+@@ -147,8 +147,9 @@ int __init coherency_init(void)
+
+ static int __init coherency_late_init(void)
+ {
+- bus_register_notifier(&platform_bus_type,
+- &mvebu_hwcc_platform_nb);
++ if (of_find_matching_node(NULL, of_coherency_table))
++ bus_register_notifier(&platform_bus_type,
++ &mvebu_hwcc_platform_nb);
+ return 0;
+ }
+
--- /dev/null
+From 4f6da1286d2602e00c049c29eb9e816587c752a5 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Sat, 22 Jun 2013 13:52:27 -0300
+Subject: [PATCH 034/203] ARM: mvebu: fix length of ethernet registers in
+ mv78260 dtsi
+
+The length of the registers area for the Marvell 370/XP Ethernet controller
+was incorrect in the .dtsi: 0x2500, while it should have been 0x4000.
+This problem wasn't noticed because there used to be a static mapping for
+all the MMIO register region set up by ->map_io().
+
+The register length was fixed in all the other device tree files,
+except from the armada-xp-mv78260.dtsi, in the following commit:
+
+ commit cf8088c5cac6ce20d914b9131533844b9291a054
+ Author: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ Date: Tue May 21 12:33:27 2013 +0200
+
+ arm: mvebu: fix length of Ethernet registers area in .dtsi
+
+This commit fixes a kernel panic in mvneta_probe(), when the kernel
+tries to access the unmapped registers:
+
+[ 163.639092] mvneta d0070000.ethernet eth0: mac: 6e:3c:4f:87:17:2e
+[ 163.646962] mvneta d0074000.ethernet eth1: mac: 6a:04:4e:6f:f5:ef
+[ 163.654853] mvneta d0030000.ethernet eth2: mac: 2a:99:19:19:fc:4c
+[ 163.661258] Unable to handle kernel paging request at virtual address f011bcf0
+[ 163.668523] pgd = c0004000
+[ 163.671237] [f011bcf0] *pgd=2f006811, *pte=00000000, *ppte=00000000
+[ 163.677565] Internal error: Oops: 807 [#1] SMP ARM
+[ 163.682370] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 3.10.0-rc6-01850-gba0682e #11
+[ 163.690046] task: ef04c000 ti: ef03e000 task.ti: ef03e000
+[ 163.695467] PC is at mvneta_probe+0x34c/0xabc
+[...]
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Acked-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-xp-mv78260.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
++++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+@@ -92,7 +92,7 @@
+
+ ethernet@34000 {
+ compatible = "marvell,armada-370-neta";
+- reg = <0x34000 0x2500>;
++ reg = <0x34000 0x4000>;
+ interrupts = <14>;
+ clocks = <&gateclk 1>;
+ status = "disabled";
--- /dev/null
+From 76de914223ec09274a7857e0d8cd7b739205dc3c Mon Sep 17 00:00:00 2001
+From: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Date: Fri, 21 Jun 2013 15:32:06 +0200
+Subject: [PATCH 035/203] i2c: mv64xxx: Set bus frequency to 100kHz if
+ clock-frequency is not provided
+
+This commit adds checking whether clock-frequency property acquisition
+has succeeded. If not, the frequency is set to 100kHz by default.
+
+The Device Tree binding documentation is updated accordingly.
+
+Based on the intials patches from Zbigniew Bodek
+
+Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Signed-off-by: Zbigniew Bodek <zbb@semihalf.com>
+Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
+---
+ Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt | 6 +++++-
+ drivers/i2c/busses/i2c-mv64xxx.c | 6 +++++-
+ 2 files changed, 10 insertions(+), 2 deletions(-)
+
+--- a/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
++++ b/Documentation/devicetree/bindings/i2c/i2c-mv64xxx.txt
+@@ -6,7 +6,11 @@ Required properties :
+ - reg : Offset and length of the register set for the device
+ - compatible : Should be "marvell,mv64xxx-i2c"
+ - interrupts : The interrupt number
+- - clock-frequency : Desired I2C bus clock frequency in Hz.
++
++Optional properties :
++
++ - clock-frequency : Desired I2C bus clock frequency in Hz. If not set the
++default frequency is 100kHz
+
+ Examples:
+
+--- a/drivers/i2c/busses/i2c-mv64xxx.c
++++ b/drivers/i2c/busses/i2c-mv64xxx.c
+@@ -580,7 +580,11 @@ mv64xxx_of_config(struct mv64xxx_i2c_dat
+ goto out;
+ }
+ tclk = clk_get_rate(drv_data->clk);
+- of_property_read_u32(np, "clock-frequency", &bus_freq);
++
++ rc = of_property_read_u32(np, "clock-frequency", &bus_freq);
++ if (rc)
++ bus_freq = 100000; /* 100kHz by default */
++
+ if (!mv64xxx_find_baud_factors(bus_freq, tclk,
+ &drv_data->freq_n, &drv_data->freq_m)) {
+ rc = -EINVAL;
--- /dev/null
+From 71a32c9519ba223d1dafcbe58d1699710720c5a8 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Thu, 1 Aug 2013 15:44:19 +0200
+Subject: [PATCH 036/203] PCI: mvebu: Disable prefetchable memory support in
+ PCI-to-PCI bridge
+
+The Marvell PCIe driver uses an emulated PCI-to-PCI bridge to be able
+to dynamically set up MBus address decoding windows for PCI I/O and
+memory regions depending on the PCI devices enumerated by Linux.
+
+However, this emulated PCI-to-PCI bridge logic makes the Linux PCI
+core believe that prefetchable memory regions are supported (because
+the registers are read/write), while in fact no adress decoding window
+is ever created for such regions. Since the Marvell MBus address
+decoding windows do not distinguish memory regions and prefetchable
+memory regions, this patch takes a simple approach: change the
+PCI-to-PCI bridge emulation to let the Linux PCI core know that we
+don't support prefetchable memory regions.
+
+To achieve this, we simply make the prefetchable memory base a
+read-only register that always returns 0. Reading/writing all the
+other prefetchable memory related registers has no effect.
+
+This problem was originally reported by Finn Hoffmann
+<finn@uni-bremen.de>, who couldn't get a RTL8111/8168B PCI NIC working
+on the NSA310 Kirkwood platform after updating to 3.11-rc. The problem
+was that the PCI-to-PCI bridge emulation was making the Linux PCI core
+believe that we support prefetchable memory, so the Linux PCI core was
+only filling the prefetchable memory base and limit registers, which
+does not lead to a MBus window being created. The below patch has been
+confirmed by Finn Hoffmann to fix his problem on Kirkwood, and has
+otherwise been successfully tested on the Armada XP GP platform with a
+e1000e PCIe NIC and a Marvell SATA PCIe card.
+
+Reported-by: Finn Hoffmann <finn@uni-bremen.de>
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+---
+ drivers/pci/host/pci-mvebu.c | 27 +--------------------------
+ 1 file changed, 1 insertion(+), 26 deletions(-)
+
+--- a/drivers/pci/host/pci-mvebu.c
++++ b/drivers/pci/host/pci-mvebu.c
+@@ -86,10 +86,6 @@ struct mvebu_sw_pci_bridge {
+ u16 secondary_status;
+ u16 membase;
+ u16 memlimit;
+- u16 prefmembase;
+- u16 prefmemlimit;
+- u32 prefbaseupper;
+- u32 preflimitupper;
+ u16 iobaseupper;
+ u16 iolimitupper;
+ u8 cappointer;
+@@ -419,15 +415,7 @@ static int mvebu_sw_pci_bridge_read(stru
+ break;
+
+ case PCI_PREF_MEMORY_BASE:
+- *value = (bridge->prefmemlimit << 16 | bridge->prefmembase);
+- break;
+-
+- case PCI_PREF_BASE_UPPER32:
+- *value = bridge->prefbaseupper;
+- break;
+-
+- case PCI_PREF_LIMIT_UPPER32:
+- *value = bridge->preflimitupper;
++ *value = 0;
+ break;
+
+ case PCI_IO_BASE_UPPER16:
+@@ -501,19 +489,6 @@ static int mvebu_sw_pci_bridge_write(str
+ mvebu_pcie_handle_membase_change(port);
+ break;
+
+- case PCI_PREF_MEMORY_BASE:
+- bridge->prefmembase = value & 0xffff;
+- bridge->prefmemlimit = value >> 16;
+- break;
+-
+- case PCI_PREF_BASE_UPPER32:
+- bridge->prefbaseupper = value;
+- break;
+-
+- case PCI_PREF_LIMIT_UPPER32:
+- bridge->preflimitupper = value;
+- break;
+-
+ case PCI_IO_BASE_UPPER16:
+ bridge->iobaseupper = value & 0xffff;
+ bridge->iolimitupper = value >> 16;
--- /dev/null
+From 9760aafa716292050a96d71a4bd7bd4e66053975 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 21 May 2013 10:24:48 -0300
+Subject: [PATCH 037/203] memory: mvebu-devbus: Remove address decoding window
+ workaround
+
+Now that mbus device tree binding has been introduced, remove the address
+decoding window management from this driver.
+A suitable 'ranges' entry should be added to the devbus-compatible node in
+the device tree, as described by the mbus binding documentation.
+
+Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+---
+ drivers/memory/mvebu-devbus.c | 64 ++-----------------------------------------
+ 1 file changed, 2 insertions(+), 62 deletions(-)
+
+--- a/drivers/memory/mvebu-devbus.c
++++ b/drivers/memory/mvebu-devbus.c
+@@ -208,16 +208,11 @@ static int mvebu_devbus_probe(struct pla
+ {
+ struct device *dev = &pdev->dev;
+ struct device_node *node = pdev->dev.of_node;
+- struct device_node *parent;
+ struct devbus *devbus;
+ struct resource *res;
+ struct clk *clk;
+ unsigned long rate;
+- const __be32 *ranges;
+- int err, cs;
+- int addr_cells, p_addr_cells, size_cells;
+- int ranges_len, tuple_len;
+- u32 base, size;
++ int err;
+
+ devbus = devm_kzalloc(&pdev->dev, sizeof(struct devbus), GFP_KERNEL);
+ if (!devbus)
+@@ -248,68 +243,13 @@ static int mvebu_devbus_probe(struct pla
+ return err;
+
+ /*
+- * Allocate an address window for this device.
+- * If the device probing fails, then we won't be able to
+- * remove the allocated address decoding window.
+- *
+- * FIXME: This is only a temporary hack! We need to do this here
+- * because we still don't have device tree bindings for mbus.
+- * Once that support is added, we will declare these address windows
+- * statically in the device tree, and remove the window configuration
+- * from here.
+- */
+-
+- /*
+- * Get the CS to choose the window string.
+- * This is a bit hacky, but it will be removed once the
+- * address windows are declared in the device tree.
+- */
+- cs = (((unsigned long)devbus->base) % 0x400) / 8;
+-
+- /*
+- * Parse 'ranges' property to obtain a (base,size) window tuple.
+- * This will be removed once the address windows
+- * are declared in the device tree.
+- */
+- parent = of_get_parent(node);
+- if (!parent)
+- return -EINVAL;
+-
+- p_addr_cells = of_n_addr_cells(parent);
+- of_node_put(parent);
+-
+- addr_cells = of_n_addr_cells(node);
+- size_cells = of_n_size_cells(node);
+- tuple_len = (p_addr_cells + addr_cells + size_cells) * sizeof(__be32);
+-
+- ranges = of_get_property(node, "ranges", &ranges_len);
+- if (ranges == NULL || ranges_len != tuple_len)
+- return -EINVAL;
+-
+- base = of_translate_address(node, ranges + addr_cells);
+- if (base == OF_BAD_ADDR)
+- return -EINVAL;
+- size = of_read_number(ranges + addr_cells + p_addr_cells, size_cells);
+-
+- /*
+- * Create an mbus address windows.
+- * FIXME: Remove this, together with the above code, once the
+- * address windows are declared in the device tree.
+- */
+- err = mvebu_mbus_add_window(devbus_wins[cs], base, size);
+- if (err < 0)
+- return err;
+-
+- /*
+ * We need to create a child device explicitly from here to
+ * guarantee that the child will be probed after the timing
+ * parameters for the bus are written.
+ */
+ err = of_platform_populate(node, NULL, NULL, dev);
+- if (err < 0) {
+- mvebu_mbus_del_window(base, size);
++ if (err < 0)
+ return err;
+- }
+
+ return 0;
+ }
--- /dev/null
+From 93b6bd1bf81cffd3e5739478c4434bf25458ec7d Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Fri, 5 Jul 2013 14:54:16 +0200
+Subject: [PATCH 038/203] bus: mvebu-mbus: Add new API for window creation
+
+We add an API to create MBus address decoding windows from the target
+ID and attribute. This function will be used later and deprecate the
+current name based scheme.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Tested-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+---
+ drivers/bus/mvebu-mbus.c | 33 +++++++++++++++++++++++++--------
+ include/linux/mbus.h | 6 ++++++
+ 2 files changed, 31 insertions(+), 8 deletions(-)
+
+--- a/drivers/bus/mvebu-mbus.c
++++ b/drivers/bus/mvebu-mbus.c
+@@ -748,6 +748,22 @@ static const struct of_device_id of_mveb
+ /*
+ * Public API of the driver
+ */
++int mvebu_mbus_add_window_remap_by_id(unsigned int target,
++ unsigned int attribute,
++ phys_addr_t base, size_t size,
++ phys_addr_t remap)
++{
++ struct mvebu_mbus_state *s = &mbus_state;
++
++ if (!mvebu_mbus_window_conflicts(s, base, size, target, attribute)) {
++ pr_err("cannot add window '%x:%x', conflicts with another window\n",
++ target, attribute);
++ return -EINVAL;
++ }
++
++ return mvebu_mbus_alloc_window(s, base, size, remap, target, attribute);
++}
++
+ int mvebu_mbus_add_window_remap_flags(const char *devname, phys_addr_t base,
+ size_t size, phys_addr_t remap,
+ unsigned int flags)
+@@ -776,14 +792,8 @@ int mvebu_mbus_add_window_remap_flags(co
+ else if (flags == MVEBU_MBUS_PCI_WA)
+ attr |= 0x28;
+
+- if (!mvebu_mbus_window_conflicts(s, base, size, target, attr)) {
+- pr_err("cannot add window '%s', conflicts with another window\n",
+- devname);
+- return -EINVAL;
+- }
+-
+- return mvebu_mbus_alloc_window(s, base, size, remap, target, attr);
+-
++ return mvebu_mbus_add_window_remap_by_id(target, attr, base,
++ size, remap);
+ }
+
+ int mvebu_mbus_add_window(const char *devname, phys_addr_t base, size_t size)
+@@ -792,6 +802,13 @@ int mvebu_mbus_add_window(const char *de
+ MVEBU_MBUS_NO_REMAP, 0);
+ }
+
++int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute,
++ phys_addr_t base, size_t size)
++{
++ return mvebu_mbus_add_window_remap_by_id(target, attribute, base,
++ size, MVEBU_MBUS_NO_REMAP);
++}
++
+ int mvebu_mbus_del_window(phys_addr_t base, size_t size)
+ {
+ int win;
+--- a/include/linux/mbus.h
++++ b/include/linux/mbus.h
+@@ -62,8 +62,14 @@ static inline const struct mbus_dram_tar
+ int mvebu_mbus_add_window_remap_flags(const char *devname, phys_addr_t base,
+ size_t size, phys_addr_t remap,
+ unsigned int flags);
++int mvebu_mbus_add_window_remap_by_id(unsigned int target,
++ unsigned int attribute,
++ phys_addr_t base, size_t size,
++ phys_addr_t remap);
+ int mvebu_mbus_add_window(const char *devname, phys_addr_t base,
+ size_t size);
++int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute,
++ phys_addr_t base, size_t size);
+ int mvebu_mbus_del_window(phys_addr_t base, size_t size);
+ int mvebu_mbus_init(const char *soc, phys_addr_t mbus_phys_base,
+ size_t mbus_size, phys_addr_t sdram_phys_base,
--- /dev/null
+From 5be79ea0d2bcec8c7360cfe3e7a491e5f176fa84 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 21 May 2013 10:44:54 -0300
+Subject: [PATCH 043/203] bus: mvebu-mbus: Factor out initialization details
+
+We introduce a common initialization function mvebu_mbus_common_init()
+that will be used by both legacy and device-tree initialization code.
+This patch is an intermediate step, which will allow to introduce the
+DT binding for this driver in a less intrusive way.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+---
+ drivers/bus/mvebu-mbus.c | 47 ++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 30 insertions(+), 17 deletions(-)
+
+--- a/drivers/bus/mvebu-mbus.c
++++ b/drivers/bus/mvebu-mbus.c
+@@ -847,26 +847,14 @@ static __init int mvebu_mbus_debugfs_ini
+ }
+ fs_initcall(mvebu_mbus_debugfs_init);
+
+-int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base,
+- size_t mbuswins_size,
+- phys_addr_t sdramwins_phys_base,
+- size_t sdramwins_size)
++static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus,
++ phys_addr_t mbuswins_phys_base,
++ size_t mbuswins_size,
++ phys_addr_t sdramwins_phys_base,
++ size_t sdramwins_size)
+ {
+- struct mvebu_mbus_state *mbus = &mbus_state;
+- const struct of_device_id *of_id;
+ int win;
+
+- for (of_id = of_mvebu_mbus_ids; of_id->compatible; of_id++)
+- if (!strcmp(of_id->compatible, soc))
+- break;
+-
+- if (!of_id->compatible) {
+- pr_err("could not find a matching SoC family\n");
+- return -ENODEV;
+- }
+-
+- mbus->soc = of_id->data;
+-
+ mbus->mbuswins_base = ioremap(mbuswins_phys_base, mbuswins_size);
+ if (!mbus->mbuswins_base)
+ return -ENOMEM;
+@@ -887,3 +875,28 @@ int __init mvebu_mbus_init(const char *s
+
+ return 0;
+ }
++
++int __init mvebu_mbus_init(const char *soc, phys_addr_t mbuswins_phys_base,
++ size_t mbuswins_size,
++ phys_addr_t sdramwins_phys_base,
++ size_t sdramwins_size)
++{
++ const struct of_device_id *of_id;
++
++ for (of_id = of_mvebu_mbus_ids; of_id->compatible; of_id++)
++ if (!strcmp(of_id->compatible, soc))
++ break;
++
++ if (!of_id->compatible) {
++ pr_err("could not find a matching SoC family\n");
++ return -ENODEV;
++ }
++
++ mbus_state.soc = of_id->data;
++
++ return mvebu_mbus_common_init(&mbus_state,
++ mbuswins_phys_base,
++ mbuswins_size,
++ sdramwins_phys_base,
++ sdramwins_size);
++}
--- /dev/null
+From e4123095febc94c547c0459db752e7879db79d76 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 21 May 2013 10:48:54 -0300
+Subject: [PATCH 044/203] bus: mvebu-mbus: Introduce device tree binding
+
+This patch adds the most fundamental device-tree initialization.
+We only introduce what's required to be able to probe the mvebu-mbus
+driver from the DT. Follow-up patches will extend the device tree binding,
+allowing to describe static address decoding windows.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+---
+ drivers/bus/mvebu-mbus.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/mbus.h | 1 +
+ 2 files changed, 50 insertions(+)
+
+--- a/drivers/bus/mvebu-mbus.c
++++ b/drivers/bus/mvebu-mbus.c
+@@ -900,3 +900,52 @@ int __init mvebu_mbus_init(const char *s
+ sdramwins_phys_base,
+ sdramwins_size);
+ }
++
++#ifdef CONFIG_OF
++int __init mvebu_mbus_dt_init(void)
++{
++ struct resource mbuswins_res, sdramwins_res;
++ struct device_node *np, *controller;
++ const struct of_device_id *of_id;
++ const __be32 *prop;
++ int ret;
++
++ np = of_find_matching_node(NULL, of_mvebu_mbus_ids);
++ if (!np) {
++ pr_err("could not find a matching SoC family\n");
++ return -ENODEV;
++ }
++
++ of_id = of_match_node(of_mvebu_mbus_ids, np);
++ mbus_state.soc = of_id->data;
++
++ prop = of_get_property(np, "controller", NULL);
++ if (!prop) {
++ pr_err("required 'controller' property missing\n");
++ return -EINVAL;
++ }
++
++ controller = of_find_node_by_phandle(be32_to_cpup(prop));
++ if (!controller) {
++ pr_err("could not find an 'mbus-controller' node\n");
++ return -ENODEV;
++ }
++
++ if (of_address_to_resource(controller, 0, &mbuswins_res)) {
++ pr_err("cannot get MBUS register address\n");
++ return -EINVAL;
++ }
++
++ if (of_address_to_resource(controller, 1, &sdramwins_res)) {
++ pr_err("cannot get SDRAM register address\n");
++ return -EINVAL;
++ }
++
++ ret = mvebu_mbus_common_init(&mbus_state,
++ mbuswins_res.start,
++ resource_size(&mbuswins_res),
++ sdramwins_res.start,
++ resource_size(&sdramwins_res));
++ return ret;
++}
++#endif
+--- a/include/linux/mbus.h
++++ b/include/linux/mbus.h
+@@ -74,5 +74,6 @@ int mvebu_mbus_del_window(phys_addr_t ba
+ int mvebu_mbus_init(const char *soc, phys_addr_t mbus_phys_base,
+ size_t mbus_size, phys_addr_t sdram_phys_base,
+ size_t sdram_size);
++int mvebu_mbus_dt_init(void);
+
+ #endif /* __LINUX_MBUS_H */
--- /dev/null
+From ece28a7e105cedb5a9ebd2553aa41d965fb83b64 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 28 May 2013 07:58:31 -0300
+Subject: [PATCH 045/203] bus: mvebu-mbus: Add static window allocation to the
+ DT binding
+
+This patch adds static window allocation to the device tree binding.
+Each first-child of the mbus-compatible node, with a suitable 'ranges'
+property, declaring an address translation, will trigger an address
+decoding window allocation.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+---
+ drivers/bus/mvebu-mbus.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 126 insertions(+), 1 deletion(-)
+
+--- a/drivers/bus/mvebu-mbus.c
++++ b/drivers/bus/mvebu-mbus.c
+@@ -902,6 +902,127 @@ int __init mvebu_mbus_init(const char *s
+ }
+
+ #ifdef CONFIG_OF
++/*
++ * The window IDs in the ranges DT property have the following format:
++ * - bits 28 to 31: MBus custom field
++ * - bits 24 to 27: window target ID
++ * - bits 16 to 23: window attribute ID
++ * - bits 0 to 15: unused
++ */
++#define CUSTOM(id) (((id) & 0xF0000000) >> 24)
++#define TARGET(id) (((id) & 0x0F000000) >> 24)
++#define ATTR(id) (((id) & 0x00FF0000) >> 16)
++
++static int __init mbus_dt_setup_win(struct mvebu_mbus_state *mbus,
++ u32 base, u32 size,
++ u8 target, u8 attr)
++{
++ const struct mvebu_mbus_mapping *map = mbus->soc->map;
++ const char *name;
++ int i;
++
++ /* Search for a suitable window in the existing mappings */
++ for (i = 0; map[i].name; i++)
++ if (map[i].target == target &&
++ map[i].attr == (attr & map[i].attrmask))
++ break;
++
++ name = map[i].name;
++ if (!name) {
++ pr_err("window 0x%x:0x%x is unknown, skipping\n",
++ target, attr);
++ return -EINVAL;
++ }
++
++ if (!mvebu_mbus_window_conflicts(mbus, base, size, target, attr)) {
++ pr_err("cannot add window '%s', conflicts with another window\n",
++ name);
++ return -EBUSY;
++ }
++
++ if (mvebu_mbus_alloc_window(mbus, base, size, MVEBU_MBUS_NO_REMAP,
++ target, attr)) {
++ pr_err("cannot add window '%s', too many windows\n",
++ name);
++ return -ENOMEM;
++ }
++ return 0;
++}
++
++static int __init
++mbus_parse_ranges(struct device_node *node,
++ int *addr_cells, int *c_addr_cells, int *c_size_cells,
++ int *cell_count, const __be32 **ranges_start,
++ const __be32 **ranges_end)
++{
++ const __be32 *prop;
++ int ranges_len, tuple_len;
++
++ /* Allow a node with no 'ranges' property */
++ *ranges_start = of_get_property(node, "ranges", &ranges_len);
++ if (*ranges_start == NULL) {
++ *addr_cells = *c_addr_cells = *c_size_cells = *cell_count = 0;
++ *ranges_start = *ranges_end = NULL;
++ return 0;
++ }
++ *ranges_end = *ranges_start + ranges_len / sizeof(__be32);
++
++ *addr_cells = of_n_addr_cells(node);
++
++ prop = of_get_property(node, "#address-cells", NULL);
++ *c_addr_cells = be32_to_cpup(prop);
++
++ prop = of_get_property(node, "#size-cells", NULL);
++ *c_size_cells = be32_to_cpup(prop);
++
++ *cell_count = *addr_cells + *c_addr_cells + *c_size_cells;
++ tuple_len = (*cell_count) * sizeof(__be32);
++
++ if (ranges_len % tuple_len) {
++ pr_warn("malformed ranges entry '%s'\n", node->name);
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int __init mbus_dt_setup(struct mvebu_mbus_state *mbus,
++ struct device_node *np)
++{
++ int addr_cells, c_addr_cells, c_size_cells;
++ int i, ret, cell_count;
++ const __be32 *r, *ranges_start, *ranges_end;
++
++ ret = mbus_parse_ranges(np, &addr_cells, &c_addr_cells,
++ &c_size_cells, &cell_count,
++ &ranges_start, &ranges_end);
++ if (ret < 0)
++ return ret;
++
++ for (i = 0, r = ranges_start; r < ranges_end; r += cell_count, i++) {
++ u32 windowid, base, size;
++ u8 target, attr;
++
++ /*
++ * An entry with a non-zero custom field do not
++ * correspond to a static window, so skip it.
++ */
++ windowid = of_read_number(r, 1);
++ if (CUSTOM(windowid))
++ continue;
++
++ target = TARGET(windowid);
++ attr = ATTR(windowid);
++
++ base = of_read_number(r + c_addr_cells, addr_cells);
++ size = of_read_number(r + c_addr_cells + addr_cells,
++ c_size_cells);
++ ret = mbus_dt_setup_win(mbus, base, size, target, attr);
++ if (ret < 0)
++ return ret;
++ }
++ return 0;
++}
++
+ int __init mvebu_mbus_dt_init(void)
+ {
+ struct resource mbuswins_res, sdramwins_res;
+@@ -946,6 +1067,10 @@ int __init mvebu_mbus_dt_init(void)
+ resource_size(&mbuswins_res),
+ sdramwins_res.start,
+ resource_size(&sdramwins_res));
+- return ret;
++ if (ret)
++ return ret;
++
++ /* Setup statically declared windows in the DT */
++ return mbus_dt_setup(&mbus_state, np);
+ }
+ #endif
--- /dev/null
+From c9646c891dbd07061a9ff5e061f9f9e54c571349 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 9 Jul 2013 10:41:53 -0300
+Subject: [PATCH 046/203] bus: mvebu-mbus: Add new API for the PCIe memory and
+ IO aperture
+
+We add two optional properties to the MBus DT binding, to encode
+the PCIe memory and IO aperture. This allows such information to
+be retrieved by -for instance- the pci driver to allocate the
+MBus decoding windows.
+
+Correspondingly, and in order to retrieve this information,
+we add two new APIs.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+---
+ drivers/bus/mvebu-mbus.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++
+ include/linux/mbus.h | 4 ++++
+ 2 files changed, 53 insertions(+)
+
+--- a/drivers/bus/mvebu-mbus.c
++++ b/drivers/bus/mvebu-mbus.c
+@@ -142,6 +142,8 @@ struct mvebu_mbus_state {
+ struct dentry *debugfs_root;
+ struct dentry *debugfs_sdram;
+ struct dentry *debugfs_devs;
++ struct resource pcie_mem_aperture;
++ struct resource pcie_io_aperture;
+ const struct mvebu_mbus_soc_data *soc;
+ int hw_io_coherency;
+ };
+@@ -821,6 +823,20 @@ int mvebu_mbus_del_window(phys_addr_t ba
+ return 0;
+ }
+
++void mvebu_mbus_get_pcie_mem_aperture(struct resource *res)
++{
++ if (!res)
++ return;
++ *res = mbus_state.pcie_mem_aperture;
++}
++
++void mvebu_mbus_get_pcie_io_aperture(struct resource *res)
++{
++ if (!res)
++ return;
++ *res = mbus_state.pcie_io_aperture;
++}
++
+ static __init int mvebu_mbus_debugfs_init(void)
+ {
+ struct mvebu_mbus_state *s = &mbus_state;
+@@ -1023,6 +1039,35 @@ static int __init mbus_dt_setup(struct m
+ return 0;
+ }
+
++static void __init mvebu_mbus_get_pcie_resources(struct device_node *np,
++ struct resource *mem,
++ struct resource *io)
++{
++ u32 reg[2];
++ int ret;
++
++ /*
++ * These are optional, so we clear them and they'll
++ * be zero if they are missing from the DT.
++ */
++ memset(mem, 0, sizeof(struct resource));
++ memset(io, 0, sizeof(struct resource));
++
++ ret = of_property_read_u32_array(np, "pcie-mem-aperture", reg, ARRAY_SIZE(reg));
++ if (!ret) {
++ mem->start = reg[0];
++ mem->end = mem->start + reg[1];
++ mem->flags = IORESOURCE_MEM;
++ }
++
++ ret = of_property_read_u32_array(np, "pcie-io-aperture", reg, ARRAY_SIZE(reg));
++ if (!ret) {
++ io->start = reg[0];
++ io->end = io->start + reg[1];
++ io->flags = IORESOURCE_IO;
++ }
++}
++
+ int __init mvebu_mbus_dt_init(void)
+ {
+ struct resource mbuswins_res, sdramwins_res;
+@@ -1062,6 +1107,10 @@ int __init mvebu_mbus_dt_init(void)
+ return -EINVAL;
+ }
+
++ /* Get optional pcie-{mem,io}-aperture properties */
++ mvebu_mbus_get_pcie_resources(np, &mbus_state.pcie_mem_aperture,
++ &mbus_state.pcie_io_aperture);
++
+ ret = mvebu_mbus_common_init(&mbus_state,
+ mbuswins_res.start,
+ resource_size(&mbuswins_res),
+--- a/include/linux/mbus.h
++++ b/include/linux/mbus.h
+@@ -11,6 +11,8 @@
+ #ifndef __LINUX_MBUS_H
+ #define __LINUX_MBUS_H
+
++struct resource;
++
+ struct mbus_dram_target_info
+ {
+ /*
+@@ -59,6 +61,8 @@ static inline const struct mbus_dram_tar
+ }
+ #endif
+
++void mvebu_mbus_get_pcie_mem_aperture(struct resource *res);
++void mvebu_mbus_get_pcie_io_aperture(struct resource *res);
+ int mvebu_mbus_add_window_remap_flags(const char *devname, phys_addr_t base,
+ size_t size, phys_addr_t remap,
+ unsigned int flags);
--- /dev/null
+From 90b1f963b07d05e8243e5053a910e8a47222f7a1 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Fri, 5 Jul 2013 14:54:17 +0200
+Subject: [PATCH 047/203] PCI: mvebu: Adapt to the new device tree layout
+
+The new device tree layout encodes the window's target ID and attribute
+in the PCIe controller node's ranges property. This allows to parse
+such entries to obtain such information and use the recently introduced
+MBus API to create the windows, instead of using the current name based
+scheme.
+
+Acked-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Tested-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+---
+ drivers/pci/host/pci-mvebu.c | 113 ++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 84 insertions(+), 29 deletions(-)
+
+--- a/drivers/pci/host/pci-mvebu.c
++++ b/drivers/pci/host/pci-mvebu.c
+@@ -119,6 +119,10 @@ struct mvebu_pcie_port {
+ u32 port;
+ u32 lane;
+ int devfn;
++ unsigned int mem_target;
++ unsigned int mem_attr;
++ unsigned int io_target;
++ unsigned int io_attr;
+ struct clk *clk;
+ struct mvebu_sw_pci_bridge bridge;
+ struct device_node *dn;
+@@ -303,10 +307,9 @@ static void mvebu_pcie_handle_iobase_cha
+ (port->bridge.iolimitupper << 16)) -
+ iobase);
+
+- mvebu_mbus_add_window_remap_flags(port->name, port->iowin_base,
+- port->iowin_size,
+- iobase,
+- MVEBU_MBUS_PCI_IO);
++ mvebu_mbus_add_window_remap_by_id(port->io_target, port->io_attr,
++ port->iowin_base, port->iowin_size,
++ iobase);
+
+ pci_ioremap_io(iobase, port->iowin_base);
+ }
+@@ -338,10 +341,8 @@ static void mvebu_pcie_handle_membase_ch
+ (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) -
+ port->memwin_base;
+
+- mvebu_mbus_add_window_remap_flags(port->name, port->memwin_base,
+- port->memwin_size,
+- MVEBU_MBUS_NO_REMAP,
+- MVEBU_MBUS_PCI_MEM);
++ mvebu_mbus_add_window_by_id(port->mem_target, port->mem_attr,
++ port->memwin_base, port->memwin_size);
+ }
+
+ /*
+@@ -730,12 +731,54 @@ mvebu_pcie_map_registers(struct platform
+ return devm_request_and_ioremap(&pdev->dev, ®s);
+ }
+
++#define DT_FLAGS_TO_TYPE(flags) (((flags) >> 24) & 0x03)
++#define DT_TYPE_IO 0x1
++#define DT_TYPE_MEM32 0x2
++#define DT_CPUADDR_TO_TARGET(cpuaddr) (((cpuaddr) >> 56) & 0xFF)
++#define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF)
++
++static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
++ unsigned long type, int *tgt, int *attr)
++{
++ const int na = 3, ns = 2;
++ const __be32 *range;
++ int rlen, nranges, rangesz, pna, i;
++
++ range = of_get_property(np, "ranges", &rlen);
++ if (!range)
++ return -EINVAL;
++
++ pna = of_n_addr_cells(np);
++ rangesz = pna + na + ns;
++ nranges = rlen / sizeof(__be32) / rangesz;
++
++ for (i = 0; i < nranges; i++) {
++ u32 flags = of_read_number(range, 1);
++ u32 slot = of_read_number(range, 2);
++ u64 cpuaddr = of_read_number(range + na, pna);
++ unsigned long rtype;
++
++ if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_IO)
++ rtype = IORESOURCE_IO;
++ else if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_MEM32)
++ rtype = IORESOURCE_MEM;
++
++ if (slot == PCI_SLOT(devfn) && type == rtype) {
++ *tgt = DT_CPUADDR_TO_TARGET(cpuaddr);
++ *attr = DT_CPUADDR_TO_ATTR(cpuaddr);
++ return 0;
++ }
++
++ range += rangesz;
++ }
++
++ return -ENOENT;
++}
++
+ static int __init mvebu_pcie_probe(struct platform_device *pdev)
+ {
+ struct mvebu_pcie *pcie;
+ struct device_node *np = pdev->dev.of_node;
+- struct of_pci_range range;
+- struct of_pci_range_parser parser;
+ struct device_node *child;
+ int i, ret;
+
+@@ -746,29 +789,25 @@ static int __init mvebu_pcie_probe(struc
+
+ pcie->pdev = pdev;
+
+- if (of_pci_range_parser_init(&parser, np))
++ /* Get the PCIe memory and I/O aperture */
++ mvebu_mbus_get_pcie_mem_aperture(&pcie->mem);
++ if (resource_size(&pcie->mem) == 0) {
++ dev_err(&pdev->dev, "invalid memory aperture size\n");
+ return -EINVAL;
++ }
+
+- /* Get the I/O and memory ranges from DT */
+- for_each_of_pci_range(&parser, &range) {
+- unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
+- if (restype == IORESOURCE_IO) {
+- of_pci_range_to_resource(&range, np, &pcie->io);
+- of_pci_range_to_resource(&range, np, &pcie->realio);
+- pcie->io.name = "I/O";
+- pcie->realio.start = max_t(resource_size_t,
+- PCIBIOS_MIN_IO,
+- range.pci_addr);
+- pcie->realio.end = min_t(resource_size_t,
+- IO_SPACE_LIMIT,
+- range.pci_addr + range.size);
+- }
+- if (restype == IORESOURCE_MEM) {
+- of_pci_range_to_resource(&range, np, &pcie->mem);
+- pcie->mem.name = "MEM";
+- }
++ mvebu_mbus_get_pcie_io_aperture(&pcie->io);
++ if (resource_size(&pcie->io) == 0) {
++ dev_err(&pdev->dev, "invalid I/O aperture size\n");
++ return -EINVAL;
+ }
+
++ pcie->realio.flags = pcie->io.flags;
++ pcie->realio.start = PCIBIOS_MIN_IO;
++ pcie->realio.end = min_t(resource_size_t,
++ IO_SPACE_LIMIT,
++ resource_size(&pcie->io));
++
+ /* Get the bus range */
+ ret = of_pci_parse_bus_range(np, &pcie->busn);
+ if (ret) {
+@@ -816,6 +855,22 @@ static int __init mvebu_pcie_probe(struc
+ if (port->devfn < 0)
+ continue;
+
++ ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_MEM,
++ &port->mem_target, &port->mem_attr);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for mem window\n",
++ port->port, port->lane);
++ continue;
++ }
++
++ ret = mvebu_get_tgt_attr(np, port->devfn, IORESOURCE_IO,
++ &port->io_target, &port->io_attr);
++ if (ret < 0) {
++ dev_err(&pdev->dev, "PCIe%d.%d: cannot get tgt/attr for io window\n",
++ port->port, port->lane);
++ continue;
++ }
++
+ port->base = mvebu_pcie_map_registers(pdev, child, port);
+ if (!port->base) {
+ dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",
--- /dev/null
+From 3dc077a80c71050e198e7884707ece042443fe3c Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 23 Jul 2013 07:36:00 -0300
+Subject: [PATCH 048/203] PCI: mvebu: Check valid base address before port
+ setup
+
+This driver does not fail to probe when it cannot obtain
+a port base address. Therefore, add a check for NULL base address
+before setting up the port, which prevents a kernel panic in such
+cases.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+---
+ drivers/pci/host/pci-mvebu.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/pci/host/pci-mvebu.c
++++ b/drivers/pci/host/pci-mvebu.c
+@@ -637,6 +637,8 @@ static int __init mvebu_pcie_setup(int n
+
+ for (i = 0; i < pcie->nports; i++) {
+ struct mvebu_pcie_port *port = &pcie->ports[i];
++ if (!port->base)
++ continue;
+ mvebu_pcie_setup_hw(port);
+ }
+
--- /dev/null
+From 1e94a8740cb1f9c328a3ae8ec4727d90bfb2d7f7 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Fri, 5 Jul 2013 14:54:23 +0200
+Subject: [PATCH 049/203] bus: mvebu-mbus: Remove the no longer used name-based
+ API
+
+Now that every user of the deprecated name-based API has been
+converted to using the ID-based API, let's remove the former one.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Tested-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+---
+ drivers/bus/mvebu-mbus.c | 38 --------------------------------------
+ include/linux/mbus.h | 5 -----
+ 2 files changed, 43 deletions(-)
+
+--- a/drivers/bus/mvebu-mbus.c
++++ b/drivers/bus/mvebu-mbus.c
+@@ -766,44 +766,6 @@ int mvebu_mbus_add_window_remap_by_id(un
+ return mvebu_mbus_alloc_window(s, base, size, remap, target, attribute);
+ }
+
+-int mvebu_mbus_add_window_remap_flags(const char *devname, phys_addr_t base,
+- size_t size, phys_addr_t remap,
+- unsigned int flags)
+-{
+- struct mvebu_mbus_state *s = &mbus_state;
+- u8 target, attr;
+- int i;
+-
+- if (!s->soc->map)
+- return -ENODEV;
+-
+- for (i = 0; s->soc->map[i].name; i++)
+- if (!strcmp(s->soc->map[i].name, devname))
+- break;
+-
+- if (!s->soc->map[i].name) {
+- pr_err("unknown device '%s'\n", devname);
+- return -ENODEV;
+- }
+-
+- target = s->soc->map[i].target;
+- attr = s->soc->map[i].attr;
+-
+- if (flags == MVEBU_MBUS_PCI_MEM)
+- attr |= 0x8;
+- else if (flags == MVEBU_MBUS_PCI_WA)
+- attr |= 0x28;
+-
+- return mvebu_mbus_add_window_remap_by_id(target, attr, base,
+- size, remap);
+-}
+-
+-int mvebu_mbus_add_window(const char *devname, phys_addr_t base, size_t size)
+-{
+- return mvebu_mbus_add_window_remap_flags(devname, base, size,
+- MVEBU_MBUS_NO_REMAP, 0);
+-}
+-
+ int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute,
+ phys_addr_t base, size_t size)
+ {
+--- a/include/linux/mbus.h
++++ b/include/linux/mbus.h
+@@ -63,15 +63,10 @@ static inline const struct mbus_dram_tar
+
+ void mvebu_mbus_get_pcie_mem_aperture(struct resource *res);
+ void mvebu_mbus_get_pcie_io_aperture(struct resource *res);
+-int mvebu_mbus_add_window_remap_flags(const char *devname, phys_addr_t base,
+- size_t size, phys_addr_t remap,
+- unsigned int flags);
+ int mvebu_mbus_add_window_remap_by_id(unsigned int target,
+ unsigned int attribute,
+ phys_addr_t base, size_t size,
+ phys_addr_t remap);
+-int mvebu_mbus_add_window(const char *devname, phys_addr_t base,
+- size_t size);
+ int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute,
+ phys_addr_t base, size_t size);
+ int mvebu_mbus_del_window(phys_addr_t base, size_t size);
--- /dev/null
+From 08c3b38a75ca47b74c81d14e1715ab9dc7b0e5cb Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Fri, 5 Jul 2013 14:54:24 +0200
+Subject: [PATCH 050/203] bus: mvebu-mbus: Remove name -> target, attribute
+ mapping tables
+
+This tables were used together with the name-based MBus window
+creation API. Since that's has been removed, we can also remove
+the tables.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Tested-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+---
+ drivers/bus/mvebu-mbus.c | 150 +++--------------------------------------------
+ 1 file changed, 7 insertions(+), 143 deletions(-)
+
+--- a/drivers/bus/mvebu-mbus.c
++++ b/drivers/bus/mvebu-mbus.c
+@@ -97,33 +97,6 @@
+
+ #define DOVE_DDR_BASE_CS_OFF(n) ((n) << 4)
+
+-struct mvebu_mbus_mapping {
+- const char *name;
+- u8 target;
+- u8 attr;
+- u8 attrmask;
+-};
+-
+-/*
+- * Masks used for the 'attrmask' field of mvebu_mbus_mapping. They
+- * allow to get the real attribute value, discarding the special bits
+- * used to select a PCI MEM region or a PCI WA region. This allows the
+- * debugfs code to reverse-match the name of a device from its
+- * target/attr values.
+- *
+- * For all devices except PCI, all bits of 'attr' must be
+- * considered. For most SoCs, only bit 3 should be ignored (it allows
+- * to select between PCI MEM and PCI I/O). On Orion5x however, there
+- * is the special bit 5 to select a PCI WA region.
+- */
+-#define MAPDEF_NOMASK 0xff
+-#define MAPDEF_PCIMASK 0xf7
+-#define MAPDEF_ORIONPCIMASK 0xd7
+-
+-/* Macro used to define one mvebu_mbus_mapping entry */
+-#define MAPDEF(__n, __t, __a, __m) \
+- { .name = __n, .target = __t, .attr = __a, .attrmask = __m }
+-
+ struct mvebu_mbus_state;
+
+ struct mvebu_mbus_soc_data {
+@@ -133,7 +106,6 @@ struct mvebu_mbus_soc_data {
+ void (*setup_cpu_target)(struct mvebu_mbus_state *s);
+ int (*show_cpu_target)(struct mvebu_mbus_state *s,
+ struct seq_file *seq, void *v);
+- const struct mvebu_mbus_mapping *map;
+ };
+
+ struct mvebu_mbus_state {
+@@ -430,8 +402,7 @@ static int mvebu_devs_debug_show(struct
+ u64 wbase, wremap;
+ u32 wsize;
+ u8 wtarget, wattr;
+- int enabled, i;
+- const char *name;
++ int enabled;
+
+ mvebu_mbus_read_window(mbus, win,
+ &enabled, &wbase, &wsize,
+@@ -442,18 +413,9 @@ static int mvebu_devs_debug_show(struct
+ continue;
+ }
+
+-
+- for (i = 0; mbus->soc->map[i].name; i++)
+- if (mbus->soc->map[i].target == wtarget &&
+- mbus->soc->map[i].attr ==
+- (wattr & mbus->soc->map[i].attrmask))
+- break;
+-
+- name = mbus->soc->map[i].name ?: "unknown";
+-
+- seq_printf(seq, "[%02d] %016llx - %016llx : %s",
++ seq_printf(seq, "[%02d] %016llx - %016llx : %04x:%04x",
+ win, (unsigned long long)wbase,
+- (unsigned long long)(wbase + wsize), name);
++ (unsigned long long)(wbase + wsize), wtarget, wattr);
+
+ if (win < mbus->soc->num_remappable_wins) {
+ seq_printf(seq, " (remap %016llx)\n",
+@@ -578,45 +540,12 @@ mvebu_mbus_dove_setup_cpu_target(struct
+ mvebu_mbus_dram_info.num_cs = cs;
+ }
+
+-static const struct mvebu_mbus_mapping armada_370_map[] = {
+- MAPDEF("bootrom", 1, 0xe0, MAPDEF_NOMASK),
+- MAPDEF("devbus-boot", 1, 0x2f, MAPDEF_NOMASK),
+- MAPDEF("devbus-cs0", 1, 0x3e, MAPDEF_NOMASK),
+- MAPDEF("devbus-cs1", 1, 0x3d, MAPDEF_NOMASK),
+- MAPDEF("devbus-cs2", 1, 0x3b, MAPDEF_NOMASK),
+- MAPDEF("devbus-cs3", 1, 0x37, MAPDEF_NOMASK),
+- MAPDEF("pcie0.0", 4, 0xe0, MAPDEF_PCIMASK),
+- MAPDEF("pcie1.0", 8, 0xe0, MAPDEF_PCIMASK),
+- {},
+-};
+-
+ static const struct mvebu_mbus_soc_data armada_370_mbus_data = {
+ .num_wins = 20,
+ .num_remappable_wins = 8,
+ .win_cfg_offset = armada_370_xp_mbus_win_offset,
+ .setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
+ .show_cpu_target = mvebu_sdram_debug_show_orion,
+- .map = armada_370_map,
+-};
+-
+-static const struct mvebu_mbus_mapping armada_xp_map[] = {
+- MAPDEF("bootrom", 1, 0x1d, MAPDEF_NOMASK),
+- MAPDEF("devbus-boot", 1, 0x2f, MAPDEF_NOMASK),
+- MAPDEF("devbus-cs0", 1, 0x3e, MAPDEF_NOMASK),
+- MAPDEF("devbus-cs1", 1, 0x3d, MAPDEF_NOMASK),
+- MAPDEF("devbus-cs2", 1, 0x3b, MAPDEF_NOMASK),
+- MAPDEF("devbus-cs3", 1, 0x37, MAPDEF_NOMASK),
+- MAPDEF("pcie0.0", 4, 0xe0, MAPDEF_PCIMASK),
+- MAPDEF("pcie0.1", 4, 0xd0, MAPDEF_PCIMASK),
+- MAPDEF("pcie0.2", 4, 0xb0, MAPDEF_PCIMASK),
+- MAPDEF("pcie0.3", 4, 0x70, MAPDEF_PCIMASK),
+- MAPDEF("pcie1.0", 8, 0xe0, MAPDEF_PCIMASK),
+- MAPDEF("pcie1.1", 8, 0xd0, MAPDEF_PCIMASK),
+- MAPDEF("pcie1.2", 8, 0xb0, MAPDEF_PCIMASK),
+- MAPDEF("pcie1.3", 8, 0x70, MAPDEF_PCIMASK),
+- MAPDEF("pcie2.0", 4, 0xf0, MAPDEF_PCIMASK),
+- MAPDEF("pcie3.0", 8, 0xf0, MAPDEF_PCIMASK),
+- {},
+ };
+
+ static const struct mvebu_mbus_soc_data armada_xp_mbus_data = {
+@@ -625,15 +554,6 @@ static const struct mvebu_mbus_soc_data
+ .win_cfg_offset = armada_370_xp_mbus_win_offset,
+ .setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
+ .show_cpu_target = mvebu_sdram_debug_show_orion,
+- .map = armada_xp_map,
+-};
+-
+-static const struct mvebu_mbus_mapping kirkwood_map[] = {
+- MAPDEF("pcie0.0", 4, 0xe0, MAPDEF_PCIMASK),
+- MAPDEF("pcie1.0", 4, 0xd0, MAPDEF_PCIMASK),
+- MAPDEF("sram", 3, 0x01, MAPDEF_NOMASK),
+- MAPDEF("nand", 1, 0x2f, MAPDEF_NOMASK),
+- {},
+ };
+
+ static const struct mvebu_mbus_soc_data kirkwood_mbus_data = {
+@@ -642,16 +562,6 @@ static const struct mvebu_mbus_soc_data
+ .win_cfg_offset = orion_mbus_win_offset,
+ .setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
+ .show_cpu_target = mvebu_sdram_debug_show_orion,
+- .map = kirkwood_map,
+-};
+-
+-static const struct mvebu_mbus_mapping dove_map[] = {
+- MAPDEF("pcie0.0", 0x4, 0xe0, MAPDEF_PCIMASK),
+- MAPDEF("pcie1.0", 0x8, 0xe0, MAPDEF_PCIMASK),
+- MAPDEF("cesa", 0x3, 0x01, MAPDEF_NOMASK),
+- MAPDEF("bootrom", 0x1, 0xfd, MAPDEF_NOMASK),
+- MAPDEF("scratchpad", 0xd, 0x0, MAPDEF_NOMASK),
+- {},
+ };
+
+ static const struct mvebu_mbus_soc_data dove_mbus_data = {
+@@ -660,18 +570,6 @@ static const struct mvebu_mbus_soc_data
+ .win_cfg_offset = orion_mbus_win_offset,
+ .setup_cpu_target = mvebu_mbus_dove_setup_cpu_target,
+ .show_cpu_target = mvebu_sdram_debug_show_dove,
+- .map = dove_map,
+-};
+-
+-static const struct mvebu_mbus_mapping orion5x_map[] = {
+- MAPDEF("pcie0.0", 4, 0x51, MAPDEF_ORIONPCIMASK),
+- MAPDEF("pci0.0", 3, 0x51, MAPDEF_ORIONPCIMASK),
+- MAPDEF("devbus-boot", 1, 0x0f, MAPDEF_NOMASK),
+- MAPDEF("devbus-cs0", 1, 0x1e, MAPDEF_NOMASK),
+- MAPDEF("devbus-cs1", 1, 0x1d, MAPDEF_NOMASK),
+- MAPDEF("devbus-cs2", 1, 0x1b, MAPDEF_NOMASK),
+- MAPDEF("sram", 0, 0x00, MAPDEF_NOMASK),
+- {},
+ };
+
+ /*
+@@ -684,7 +582,6 @@ static const struct mvebu_mbus_soc_data
+ .win_cfg_offset = orion_mbus_win_offset,
+ .setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
+ .show_cpu_target = mvebu_sdram_debug_show_orion,
+- .map = orion5x_map,
+ };
+
+ static const struct mvebu_mbus_soc_data orion5x_2win_mbus_data = {
+@@ -693,21 +590,6 @@ static const struct mvebu_mbus_soc_data
+ .win_cfg_offset = orion_mbus_win_offset,
+ .setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
+ .show_cpu_target = mvebu_sdram_debug_show_orion,
+- .map = orion5x_map,
+-};
+-
+-static const struct mvebu_mbus_mapping mv78xx0_map[] = {
+- MAPDEF("pcie0.0", 4, 0xe0, MAPDEF_PCIMASK),
+- MAPDEF("pcie0.1", 4, 0xd0, MAPDEF_PCIMASK),
+- MAPDEF("pcie0.2", 4, 0xb0, MAPDEF_PCIMASK),
+- MAPDEF("pcie0.3", 4, 0x70, MAPDEF_PCIMASK),
+- MAPDEF("pcie1.0", 8, 0xe0, MAPDEF_PCIMASK),
+- MAPDEF("pcie1.1", 8, 0xd0, MAPDEF_PCIMASK),
+- MAPDEF("pcie1.2", 8, 0xb0, MAPDEF_PCIMASK),
+- MAPDEF("pcie1.3", 8, 0x70, MAPDEF_PCIMASK),
+- MAPDEF("pcie2.0", 4, 0xf0, MAPDEF_PCIMASK),
+- MAPDEF("pcie3.0", 8, 0xf0, MAPDEF_PCIMASK),
+- {},
+ };
+
+ static const struct mvebu_mbus_soc_data mv78xx0_mbus_data = {
+@@ -716,7 +598,6 @@ static const struct mvebu_mbus_soc_data
+ .win_cfg_offset = mv78xx0_mbus_win_offset,
+ .setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
+ .show_cpu_target = mvebu_sdram_debug_show_orion,
+- .map = mv78xx0_map,
+ };
+
+ /*
+@@ -895,33 +776,16 @@ static int __init mbus_dt_setup_win(stru
+ u32 base, u32 size,
+ u8 target, u8 attr)
+ {
+- const struct mvebu_mbus_mapping *map = mbus->soc->map;
+- const char *name;
+- int i;
+-
+- /* Search for a suitable window in the existing mappings */
+- for (i = 0; map[i].name; i++)
+- if (map[i].target == target &&
+- map[i].attr == (attr & map[i].attrmask))
+- break;
+-
+- name = map[i].name;
+- if (!name) {
+- pr_err("window 0x%x:0x%x is unknown, skipping\n",
+- target, attr);
+- return -EINVAL;
+- }
+-
+ if (!mvebu_mbus_window_conflicts(mbus, base, size, target, attr)) {
+- pr_err("cannot add window '%s', conflicts with another window\n",
+- name);
++ pr_err("cannot add window '%04x:%04x', conflicts with another window\n",
++ target, attr);
+ return -EBUSY;
+ }
+
+ if (mvebu_mbus_alloc_window(mbus, base, size, MVEBU_MBUS_NO_REMAP,
+ target, attr)) {
+- pr_err("cannot add window '%s', too many windows\n",
+- name);
++ pr_err("cannot add window '%04x:%04x', too many windows\n",
++ target, attr);
+ return -ENOMEM;
+ }
+ return 0;
--- /dev/null
+From 8f14bc2a883316dfd95383900c61d7d9183e8eaf Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Fri, 5 Jul 2013 14:54:25 +0200
+Subject: [PATCH 051/203] bus: mvebu-mbus: Update main description
+
+After replacing the MBus name-based by the new ID-based API
+let's fix the general description of the driver at the beginning
+of the file.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Tested-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+---
+ drivers/bus/mvebu-mbus.c | 10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+--- a/drivers/bus/mvebu-mbus.c
++++ b/drivers/bus/mvebu-mbus.c
+@@ -35,13 +35,9 @@
+ *
+ * - Provides an API for platform code or device drivers to
+ * dynamically add or remove address decoding windows for the CPU ->
+- * device accesses. This API is mvebu_mbus_add_window(),
+- * mvebu_mbus_add_window_remap_flags() and
+- * mvebu_mbus_del_window(). Since the (target, attribute) values
+- * differ from one SoC family to another, the API uses a 'const char
+- * *' string to identify devices, and this driver is responsible for
+- * knowing the mapping between the name of a device and its
+- * corresponding (target, attribute) in the current SoC family.
++ * device accesses. This API is mvebu_mbus_add_window_by_id(),
++ * mvebu_mbus_add_window_remap_by_id() and
++ * mvebu_mbus_del_window().
+ *
+ * - Provides a debugfs interface in /sys/kernel/debug/mvebu-mbus/ to
+ * see the list of CPU -> SDRAM windows and their configuration
--- /dev/null
+From 2c8f0b1810ff9cd45ed2055441b4c43afcfb7d2a Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Fri, 5 Jul 2013 14:54:26 +0200
+Subject: [PATCH 052/203] bus: mvebu-mbus: Factorize Armada 370/XP data
+ structures
+
+These structures were only different in the mapping tables.
+Now that those tables have been removed, it doesn't make any sense
+to keep different structures.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Tested-by: Andrew Lunn <andrew@lunn.ch>
+Tested-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+---
+ drivers/bus/mvebu-mbus.c | 14 +++-----------
+ 1 file changed, 3 insertions(+), 11 deletions(-)
+
+--- a/drivers/bus/mvebu-mbus.c
++++ b/drivers/bus/mvebu-mbus.c
+@@ -536,15 +536,7 @@ mvebu_mbus_dove_setup_cpu_target(struct
+ mvebu_mbus_dram_info.num_cs = cs;
+ }
+
+-static const struct mvebu_mbus_soc_data armada_370_mbus_data = {
+- .num_wins = 20,
+- .num_remappable_wins = 8,
+- .win_cfg_offset = armada_370_xp_mbus_win_offset,
+- .setup_cpu_target = mvebu_mbus_default_setup_cpu_target,
+- .show_cpu_target = mvebu_sdram_debug_show_orion,
+-};
+-
+-static const struct mvebu_mbus_soc_data armada_xp_mbus_data = {
++static const struct mvebu_mbus_soc_data armada_370_xp_mbus_data = {
+ .num_wins = 20,
+ .num_remappable_wins = 8,
+ .win_cfg_offset = armada_370_xp_mbus_win_offset,
+@@ -604,9 +596,9 @@ static const struct mvebu_mbus_soc_data
+ */
+ static const struct of_device_id of_mvebu_mbus_ids[] = {
+ { .compatible = "marvell,armada370-mbus",
+- .data = &armada_370_mbus_data, },
++ .data = &armada_370_xp_mbus_data, },
+ { .compatible = "marvell,armadaxp-mbus",
+- .data = &armada_xp_mbus_data, },
++ .data = &armada_370_xp_mbus_data, },
+ { .compatible = "marvell,kirkwood-mbus",
+ .data = &kirkwood_mbus_data, },
+ { .compatible = "marvell,dove-mbus",