mvebu: backport mainline patches from kernel 3.11
authorLuka Perkov <luka@openwrt.org>
Tue, 11 Feb 2014 02:07:38 +0000 (02:07 +0000)
committerLuka Perkov <luka@openwrt.org>
Tue, 11 Feb 2014 02:07:38 +0000 (02:07 +0000)
This is a backport of the patches accepted to the Linux mainline related to
mvebu SoC (Armada XP and Armada 370) between Linux v3.10, and Linux v3.11.
This work mainly covers:

* Enabling USB storage, and PCI to mvebu_defconfig.
* Add support for NOR flash.
* Some PCI device tree related updates, and bus parsing.
* Adding Armada XP & 370 PCI driver, and update some clock gating
  specifics.
* Introduce Marvell EBU Device Bus driver.
* Enaling USB in the armada*.dts.
* Enabling, and updating the mvebu-mbus.
* Some SATA and Ethernet related fixes.

Signed-off-by: Seif Mazareeb <seif.mazareeb@gmail.com>
CC: Luka Perkov <luka@openwrt.org>
SVN-Revision: 39564

47 files changed:
target/linux/mvebu/patches-3.10/0001-ARM-mvebu-Add-support-for-USB-storage-class-in-mvebu.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0002-ARM-mvebu-Use-standard-MMC-binding-for-all-users-of-.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0003-ARM-mvebu-Add-support-for-NOR-flash-device-on-Armada.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0004-of-pci-Provide-support-for-parsing-PCI-DT-ranges-pro.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0006-of-pci-Add-of_pci_parse_bus_range-function.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0007-clk-mvebu-create-parent-child-relation-for-PCIe-cloc.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0008-clk-mvebu-add-more-PCIe-clocks-for-Armada-XP.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0009-pci-PCIe-driver-for-Marvell-Armada-370-XP-systems.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0010-arm-mvebu-PCIe-support-is-now-available-on-mvebu.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0011-arm-mvebu-update-defconfig-with-PCI-and-USB-support.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0012-arm-mvebu-mark-functions-of-armada-370-xp.c-as-stati.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0013-drivers-memory-Introduce-Marvell-EBU-Device-Bus-driv.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0014-arm-mvebu-enable-two-USB-interfaces-on-the-Armada-XP.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0015-pci-mvebu-no-longer-fake-the-slot-location-of-downst.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0016-pci-mvebu-allow-the-enumeration-of-devices-beyond-ph.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0017-pci-mvebu-fix-the-emulation-of-the-status-register.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0018-arm-mvebu-fix-length-of-SATA-registers-area-in-.dtsi.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0019-arm-mvebu-fix-length-of-Ethernet-registers-area-in-..patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0020-net-mvneta-read-MAC-address-from-hardware-when-avail.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0021-arm-mvebu-armada-xp-db-ensure-PCIe-range-is-specifie.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0022-bus-mvebu-mbus-Use-pr_fmt.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0023-ARM-mvebu-Remove-device-tree-unused-properties-on-A3.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0024-arm-mvebu-remove-dependency-of-SMP-init-on-static-I-.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0025-arm-mvebu-avoid-hardcoded-virtual-address-in-coheren.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0026-arm-mvebu-move-cache-and-mvebu-mbus-initialization-l.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0027-arm-mvebu-remove-hardcoded-static-I-O-mapping.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0028-arm-mvebu-don-t-hardcode-a-physical-address-in-heads.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0029-arm-mvebu-don-t-hardcode-the-physical-address-for-mv.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0030-arm-mvebu-add-another-earlyprintk-Kconfig-option.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0031-arm-mvebu-disable-DEBUG_LL-EARLY_PRINTK-in-defconfig.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0032-arm-mvebu-enable-mini-PCIe-connectors-on-Armada-370-.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0033-arm-mvebu-fix-coherency_late_init-for-multiplatform.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0034-ARM-mvebu-fix-length-of-ethernet-registers-in-mv7826.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0035-i2c-mv64xxx-Set-bus-frequency-to-100kHz-if-clock-fre.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0036-PCI-mvebu-Disable-prefetchable-memory-support-in-PCI.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0037-memory-mvebu-devbus-Remove-address-decoding-window-w.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0038-bus-mvebu-mbus-Add-new-API-for-window-creation.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0043-bus-mvebu-mbus-Factor-out-initialization-details.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0044-bus-mvebu-mbus-Introduce-device-tree-binding.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0045-bus-mvebu-mbus-Add-static-window-allocation-to-the-D.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0046-bus-mvebu-mbus-Add-new-API-for-the-PCIe-memory-and-I.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0047-PCI-mvebu-Adapt-to-the-new-device-tree-layout.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0048-PCI-mvebu-Check-valid-base-address-before-port-setup.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0049-bus-mvebu-mbus-Remove-the-no-longer-used-name-based-.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0050-bus-mvebu-mbus-Remove-name-target-attribute-mapping-.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0051-bus-mvebu-mbus-Update-main-description.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0052-bus-mvebu-mbus-Factorize-Armada-370-XP-data-structur.patch [new file with mode: 0644]

diff --git a/target/linux/mvebu/patches-3.10/0001-ARM-mvebu-Add-support-for-USB-storage-class-in-mvebu.patch b/target/linux/mvebu/patches-3.10/0001-ARM-mvebu-Add-support-for-USB-storage-class-in-mvebu.patch
new file mode 100644 (file)
index 0000000..7ffc403
--- /dev/null
@@ -0,0 +1,28 @@
+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
diff --git a/target/linux/mvebu/patches-3.10/0002-ARM-mvebu-Use-standard-MMC-binding-for-all-users-of-.patch b/target/linux/mvebu/patches-3.10/0002-ARM-mvebu-Use-standard-MMC-binding-for-all-users-of-.patch
new file mode 100644 (file)
index 0000000..536009c
--- /dev/null
@@ -0,0 +1,133 @@
+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";
+               };
+       };
diff --git a/target/linux/mvebu/patches-3.10/0003-ARM-mvebu-Add-support-for-NOR-flash-device-on-Armada.patch b/target/linux/mvebu/patches-3.10/0003-ARM-mvebu-Add-support-for-NOR-flash-device-on-Armada.patch
new file mode 100644 (file)
index 0000000..22f8ad0
--- /dev/null
@@ -0,0 +1,71 @@
+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>;
++                              };
++                      };
+               };
+       };
+ };
diff --git a/target/linux/mvebu/patches-3.10/0004-of-pci-Provide-support-for-parsing-PCI-DT-ranges-pro.patch b/target/linux/mvebu/patches-3.10/0004-of-pci-Provide-support-for-parsing-PCI-DT-ranges-pro.patch
new file mode 100644 (file)
index 0000000..6c82070
--- /dev/null
@@ -0,0 +1,196 @@
+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 */
diff --git a/target/linux/mvebu/patches-3.10/0006-of-pci-Add-of_pci_parse_bus_range-function.patch b/target/linux/mvebu/patches-3.10/0006-of-pci-Add-of_pci_parse_bus_range-function.patch
new file mode 100644 (file)
index 0000000..ae07e83
--- /dev/null
@@ -0,0 +1,54 @@
+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
diff --git a/target/linux/mvebu/patches-3.10/0007-clk-mvebu-create-parent-child-relation-for-PCIe-cloc.patch b/target/linux/mvebu/patches-3.10/0007-clk-mvebu-create-parent-child-relation-for-PCIe-cloc.patch
new file mode 100644 (file)
index 0000000..c556c27
--- /dev/null
@@ -0,0 +1,30 @@
+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 },
diff --git a/target/linux/mvebu/patches-3.10/0008-clk-mvebu-add-more-PCIe-clocks-for-Armada-XP.patch b/target/linux/mvebu/patches-3.10/0008-clk-mvebu-add-more-PCIe-clocks-for-Armada-XP.patch
new file mode 100644 (file)
index 0000000..871aa3d
--- /dev/null
@@ -0,0 +1,50 @@
+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 },
diff --git a/target/linux/mvebu/patches-3.10/0009-pci-PCIe-driver-for-Marvell-Armada-370-XP-systems.patch b/target/linux/mvebu/patches-3.10/0009-pci-PCIe-driver-for-Marvell-Armada-370-XP-systems.patch
new file mode 100644 (file)
index 0000000..13ddae8
--- /dev/null
@@ -0,0 +1,1177 @@
+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, &reg);
++      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, &regs);
++      if (ret)
++              return NULL;
++
++      return devm_request_and_ioremap(&pdev->dev, &regs);
++}
++
++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");
diff --git a/target/linux/mvebu/patches-3.10/0010-arm-mvebu-PCIe-support-is-now-available-on-mvebu.patch b/target/linux/mvebu/patches-3.10/0010-arm-mvebu-PCIe-support-is-now-available-on-mvebu.patch
new file mode 100644 (file)
index 0000000..2e90b7d
--- /dev/null
@@ -0,0 +1,25 @@
+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
diff --git a/target/linux/mvebu/patches-3.10/0011-arm-mvebu-update-defconfig-with-PCI-and-USB-support.patch b/target/linux/mvebu/patches-3.10/0011-arm-mvebu-update-defconfig-with-PCI-and-USB-support.patch
new file mode 100644 (file)
index 0000000..3aeeb47
--- /dev/null
@@ -0,0 +1,36 @@
+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
diff --git a/target/linux/mvebu/patches-3.10/0012-arm-mvebu-mark-functions-of-armada-370-xp.c-as-stati.patch b/target/linux/mvebu/patches-3.10/0012-arm-mvebu-mark-functions-of-armada-370-xp.c-as-stati.patch
new file mode 100644 (file)
index 0000000..bbb5ceb
--- /dev/null
@@ -0,0 +1,40 @@
+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;
diff --git a/target/linux/mvebu/patches-3.10/0013-drivers-memory-Introduce-Marvell-EBU-Device-Bus-driv.patch b/target/linux/mvebu/patches-3.10/0013-drivers-memory-Introduce-Marvell-EBU-Device-Bus-driv.patch
new file mode 100644 (file)
index 0000000..5f00e9f
--- /dev/null
@@ -0,0 +1,568 @@
+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");
diff --git a/target/linux/mvebu/patches-3.10/0014-arm-mvebu-enable-two-USB-interfaces-on-the-Armada-XP.patch b/target/linux/mvebu/patches-3.10/0014-arm-mvebu-enable-two-USB-interfaces-on-the-Armada-XP.patch
new file mode 100644 (file)
index 0000000..120e14d
--- /dev/null
@@ -0,0 +1,35 @@
+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";
diff --git a/target/linux/mvebu/patches-3.10/0015-pci-mvebu-no-longer-fake-the-slot-location-of-downst.patch b/target/linux/mvebu/patches-3.10/0015-pci-mvebu-no-longer-fake-the-slot-location-of-downst.patch
new file mode 100644 (file)
index 0000000..c3dd1f1
--- /dev/null
@@ -0,0 +1,97 @@
+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",
diff --git a/target/linux/mvebu/patches-3.10/0016-pci-mvebu-allow-the-enumeration-of-devices-beyond-ph.patch b/target/linux/mvebu/patches-3.10/0016-pci-mvebu-allow-the-enumeration-of-devices-beyond-ph.patch
new file mode 100644 (file)
index 0000000..bda383a
--- /dev/null
@@ -0,0 +1,97 @@
+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;
+       }
diff --git a/target/linux/mvebu/patches-3.10/0017-pci-mvebu-fix-the-emulation-of-the-status-register.patch b/target/linux/mvebu/patches-3.10/0017-pci-mvebu-fix-the-emulation-of-the-status-register.patch
new file mode 100644 (file)
index 0000000..9da0c58
--- /dev/null
@@ -0,0 +1,87 @@
+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:
diff --git a/target/linux/mvebu/patches-3.10/0018-arm-mvebu-fix-length-of-SATA-registers-area-in-.dtsi.patch b/target/linux/mvebu/patches-3.10/0018-arm-mvebu-fix-length-of-SATA-registers-area-in-.dtsi.patch
new file mode 100644 (file)
index 0000000..5a78cc5
--- /dev/null
@@ -0,0 +1,30 @@
+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";
diff --git a/target/linux/mvebu/patches-3.10/0019-arm-mvebu-fix-length-of-Ethernet-registers-area-in-..patch b/target/linux/mvebu/patches-3.10/0019-arm-mvebu-fix-length-of-Ethernet-registers-area-in-..patch
new file mode 100644 (file)
index 0000000..193d87c
--- /dev/null
@@ -0,0 +1,63 @@
+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";
diff --git a/target/linux/mvebu/patches-3.10/0020-net-mvneta-read-MAC-address-from-hardware-when-avail.patch b/target/linux/mvebu/patches-3.10/0020-net-mvneta-read-MAC-address-from-hardware-when-avail.patch
new file mode 100644 (file)
index 0000000..9866f0c
--- /dev/null
@@ -0,0 +1,112 @@
+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);
diff --git a/target/linux/mvebu/patches-3.10/0021-arm-mvebu-armada-xp-db-ensure-PCIe-range-is-specifie.patch b/target/linux/mvebu/patches-3.10/0021-arm-mvebu-armada-xp-db-ensure-PCIe-range-is-specifie.patch
new file mode 100644 (file)
index 0000000..a57b6c8
--- /dev/null
@@ -0,0 +1,31 @@
+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 {
diff --git a/target/linux/mvebu/patches-3.10/0022-bus-mvebu-mbus-Use-pr_fmt.patch b/target/linux/mvebu/patches-3.10/0022-bus-mvebu-mbus-Use-pr_fmt.patch
new file mode 100644 (file)
index 0000000..ab2e7b4
--- /dev/null
@@ -0,0 +1,54 @@
+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;
+       }
diff --git a/target/linux/mvebu/patches-3.10/0023-ARM-mvebu-Remove-device-tree-unused-properties-on-A3.patch b/target/linux/mvebu/patches-3.10/0023-ARM-mvebu-Remove-device-tree-unused-properties-on-A3.patch
new file mode 100644 (file)
index 0000000..39270c7
--- /dev/null
@@ -0,0 +1,28 @@
+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 */
diff --git a/target/linux/mvebu/patches-3.10/0024-arm-mvebu-remove-dependency-of-SMP-init-on-static-I-.patch b/target/linux/mvebu/patches-3.10/0024-arm-mvebu-remove-dependency-of-SMP-init-on-static-I-.patch
new file mode 100644 (file)
index 0000000..38c908f
--- /dev/null
@@ -0,0 +1,99 @@
+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) {
diff --git a/target/linux/mvebu/patches-3.10/0025-arm-mvebu-avoid-hardcoded-virtual-address-in-coheren.patch b/target/linux/mvebu/patches-3.10/0025-arm-mvebu-avoid-hardcoded-virtual-address-in-coheren.patch
new file mode 100644 (file)
index 0000000..b6c3722
--- /dev/null
@@ -0,0 +1,81 @@
+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);
diff --git a/target/linux/mvebu/patches-3.10/0026-arm-mvebu-move-cache-and-mvebu-mbus-initialization-l.patch b/target/linux/mvebu/patches-3.10/0026-arm-mvebu-move-cache-and-mvebu-mbus-initialization-l.patch
new file mode 100644 (file)
index 0000000..de2ed73
--- /dev/null
@@ -0,0 +1,54 @@
+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,
diff --git a/target/linux/mvebu/patches-3.10/0027-arm-mvebu-remove-hardcoded-static-I-O-mapping.patch b/target/linux/mvebu/patches-3.10/0027-arm-mvebu-remove-hardcoded-static-I-O-mapping.patch
new file mode 100644 (file)
index 0000000..7890592
--- /dev/null
@@ -0,0 +1,52 @@
+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)
diff --git a/target/linux/mvebu/patches-3.10/0028-arm-mvebu-don-t-hardcode-a-physical-address-in-heads.patch b/target/linux/mvebu/patches-3.10/0028-arm-mvebu-don-t-hardcode-a-physical-address-in-heads.patch
new file mode 100644 (file)
index 0000000..af98e9d
--- /dev/null
@@ -0,0 +1,91 @@
+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 - .
diff --git a/target/linux/mvebu/patches-3.10/0029-arm-mvebu-don-t-hardcode-the-physical-address-for-mv.patch b/target/linux/mvebu/patches-3.10/0029-arm-mvebu-don-t-hardcode-the-physical-address-for-mv.patch
new file mode 100644 (file)
index 0000000..62c6bcb
--- /dev/null
@@ -0,0 +1,109 @@
+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>
diff --git a/target/linux/mvebu/patches-3.10/0030-arm-mvebu-add-another-earlyprintk-Kconfig-option.patch b/target/linux/mvebu/patches-3.10/0030-arm-mvebu-add-another-earlyprintk-Kconfig-option.patch
new file mode 100644 (file)
index 0000000..7faeb98
--- /dev/null
@@ -0,0 +1,85 @@
+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
diff --git a/target/linux/mvebu/patches-3.10/0031-arm-mvebu-disable-DEBUG_LL-EARLY_PRINTK-in-defconfig.patch b/target/linux/mvebu/patches-3.10/0031-arm-mvebu-disable-DEBUG_LL-EARLY_PRINTK-in-defconfig.patch
new file mode 100644 (file)
index 0000000..e1e2e62
--- /dev/null
@@ -0,0 +1,27 @@
+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
diff --git a/target/linux/mvebu/patches-3.10/0032-arm-mvebu-enable-mini-PCIe-connectors-on-Armada-370-.patch b/target/linux/mvebu/patches-3.10/0032-arm-mvebu-enable-mini-PCIe-connectors-on-Armada-370-.patch
new file mode 100644 (file)
index 0000000..81ab352
--- /dev/null
@@ -0,0 +1,42 @@
+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";
++                              };
++                      };
+               };
+       };
+  };
diff --git a/target/linux/mvebu/patches-3.10/0033-arm-mvebu-fix-coherency_late_init-for-multiplatform.patch b/target/linux/mvebu/patches-3.10/0033-arm-mvebu-fix-coherency_late_init-for-multiplatform.patch
new file mode 100644 (file)
index 0000000..21fad3e
--- /dev/null
@@ -0,0 +1,41 @@
+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;
+ }
diff --git a/target/linux/mvebu/patches-3.10/0034-ARM-mvebu-fix-length-of-ethernet-registers-in-mv7826.patch b/target/linux/mvebu/patches-3.10/0034-ARM-mvebu-fix-length-of-ethernet-registers-in-mv7826.patch
new file mode 100644 (file)
index 0000000..6ee5835
--- /dev/null
@@ -0,0 +1,53 @@
+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";
diff --git a/target/linux/mvebu/patches-3.10/0035-i2c-mv64xxx-Set-bus-frequency-to-100kHz-if-clock-fre.patch b/target/linux/mvebu/patches-3.10/0035-i2c-mv64xxx-Set-bus-frequency-to-100kHz-if-clock-fre.patch
new file mode 100644 (file)
index 0000000..4de7da9
--- /dev/null
@@ -0,0 +1,51 @@
+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;
diff --git a/target/linux/mvebu/patches-3.10/0036-PCI-mvebu-Disable-prefetchable-memory-support-in-PCI.patch b/target/linux/mvebu/patches-3.10/0036-PCI-mvebu-Disable-prefetchable-memory-support-in-PCI.patch
new file mode 100644 (file)
index 0000000..afb104a
--- /dev/null
@@ -0,0 +1,91 @@
+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;
diff --git a/target/linux/mvebu/patches-3.10/0037-memory-mvebu-devbus-Remove-address-decoding-window-w.patch b/target/linux/mvebu/patches-3.10/0037-memory-mvebu-devbus-Remove-address-decoding-window-w.patch
new file mode 100644 (file)
index 0000000..1983016
--- /dev/null
@@ -0,0 +1,109 @@
+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;
+ }
diff --git a/target/linux/mvebu/patches-3.10/0038-bus-mvebu-mbus-Add-new-API-for-window-creation.patch b/target/linux/mvebu/patches-3.10/0038-bus-mvebu-mbus-Add-new-API-for-window-creation.patch
new file mode 100644 (file)
index 0000000..4ebb3f3
--- /dev/null
@@ -0,0 +1,90 @@
+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,
diff --git a/target/linux/mvebu/patches-3.10/0043-bus-mvebu-mbus-Factor-out-initialization-details.patch b/target/linux/mvebu/patches-3.10/0043-bus-mvebu-mbus-Factor-out-initialization-details.patch
new file mode 100644 (file)
index 0000000..e6a9032
--- /dev/null
@@ -0,0 +1,81 @@
+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);
++}
diff --git a/target/linux/mvebu/patches-3.10/0044-bus-mvebu-mbus-Introduce-device-tree-binding.patch b/target/linux/mvebu/patches-3.10/0044-bus-mvebu-mbus-Introduce-device-tree-binding.patch
new file mode 100644 (file)
index 0000000..ef2d1b4
--- /dev/null
@@ -0,0 +1,83 @@
+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 */
diff --git a/target/linux/mvebu/patches-3.10/0045-bus-mvebu-mbus-Add-static-window-allocation-to-the-D.patch b/target/linux/mvebu/patches-3.10/0045-bus-mvebu-mbus-Add-static-window-allocation-to-the-D.patch
new file mode 100644 (file)
index 0000000..d9e783a
--- /dev/null
@@ -0,0 +1,160 @@
+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
diff --git a/target/linux/mvebu/patches-3.10/0046-bus-mvebu-mbus-Add-new-API-for-the-PCIe-memory-and-I.patch b/target/linux/mvebu/patches-3.10/0046-bus-mvebu-mbus-Add-new-API-for-the-PCIe-memory-and-I.patch
new file mode 100644 (file)
index 0000000..973ffde
--- /dev/null
@@ -0,0 +1,121 @@
+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);
diff --git a/target/linux/mvebu/patches-3.10/0047-PCI-mvebu-Adapt-to-the-new-device-tree-layout.patch b/target/linux/mvebu/patches-3.10/0047-PCI-mvebu-Adapt-to-the-new-device-tree-layout.patch
new file mode 100644 (file)
index 0000000..08de63d
--- /dev/null
@@ -0,0 +1,184 @@
+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, &regs);
+ }
++#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",
diff --git a/target/linux/mvebu/patches-3.10/0048-PCI-mvebu-Check-valid-base-address-before-port-setup.patch b/target/linux/mvebu/patches-3.10/0048-PCI-mvebu-Check-valid-base-address-before-port-setup.patch
new file mode 100644 (file)
index 0000000..c9022bb
--- /dev/null
@@ -0,0 +1,29 @@
+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);
+       }
diff --git a/target/linux/mvebu/patches-3.10/0049-bus-mvebu-mbus-Remove-the-no-longer-used-name-based-.patch b/target/linux/mvebu/patches-3.10/0049-bus-mvebu-mbus-Remove-the-no-longer-used-name-based-.patch
new file mode 100644 (file)
index 0000000..ac97c11
--- /dev/null
@@ -0,0 +1,82 @@
+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);
diff --git a/target/linux/mvebu/patches-3.10/0050-bus-mvebu-mbus-Remove-name-target-attribute-mapping-.patch b/target/linux/mvebu/patches-3.10/0050-bus-mvebu-mbus-Remove-name-target-attribute-mapping-.patch
new file mode 100644 (file)
index 0000000..0b62633
--- /dev/null
@@ -0,0 +1,266 @@
+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;
diff --git a/target/linux/mvebu/patches-3.10/0051-bus-mvebu-mbus-Update-main-description.patch b/target/linux/mvebu/patches-3.10/0051-bus-mvebu-mbus-Update-main-description.patch
new file mode 100644 (file)
index 0000000..8e10d90
--- /dev/null
@@ -0,0 +1,35 @@
+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
diff --git a/target/linux/mvebu/patches-3.10/0052-bus-mvebu-mbus-Factorize-Armada-370-XP-data-structur.patch b/target/linux/mvebu/patches-3.10/0052-bus-mvebu-mbus-Factorize-Armada-370-XP-data-structur.patch
new file mode 100644 (file)
index 0000000..382aa43
--- /dev/null
@@ -0,0 +1,48 @@
+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",