mvebu: backport mainline patches from kernel 3.13
authorLuka Perkov <luka@openwrt.org>
Tue, 11 Feb 2014 02:07:44 +0000 (02:07 +0000)
committerLuka Perkov <luka@openwrt.org>
Tue, 11 Feb 2014 02:07:44 +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.12, and Linux v3.13.
This work mainly covers:

* Finishes work for sharing the pxa nand driver(drivers/mtd/nand/pxa3xx_nand.c)
  between the PXA family, and the Armada family.
* timer initialization update, and access function for the Armada family.
* Generic IRQ handling backporting.
* Some bug fixes.

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

76 files changed:
target/linux/mvebu/patches-3.10/0128-mtd-nand-pxa3xx_nand-Remove-redundant-of_match_ptr.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0129-mtd-nand-pxa3xx-Move-DMA-I-O-enabling.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0130-mtd-nand-pxa3xx-Allocate-data-buffer-on-detected-fla.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0131-mtd-nand-remove-deprecated-IRQF_DISABLED.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0132-mtd-nand-pxa3xx-Add-documentation-about-the-controll.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0133-mtd-nand-pxa3xx-Prevent-sub-page-writes.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0134-mtd-nand-pxa3xx-read_page-returns-max_bitflips.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0135-mtd-nand-pxa3xx-Early-variant-detection.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0136-mtd-nand-pxa3xx-Use-chip-cmdfunc-instead-of-the-inte.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0137-mtd-nand-pxa3xx-Split-FIFO-size-from-to-be-read-FIFO.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0138-mtd-nand-pxa3xx-Replace-host-page_size-by-mtd-writes.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0139-mtd-nand-pxa3xx-Add-a-nice-comment-to-pxa3xx_set_dat.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0140-mtd-nand-pxa3xx-Use-a-completion-to-signal-device-re.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0141-mtd-nand-pxa3xx-Use-waitfunc-to-wait-for-the-device-.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0142-mtd-nand-pxa3xx-Add-bad-block-handling.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0143-mtd-nand-pxa3xx-Add-driver-specific-ECC-BCH-support.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0144-mtd-nand-pxa3xx-Clear-cmd-buffer-3-NDCB3-on-command-.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0145-mtd-nand-pxa3xx-Add-helper-function-to-set-page-addr.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0146-mtd-nand-pxa3xx-Remove-READ0-switch-case-falltrough.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0147-mtd-nand-pxa3xx-Split-prepare_command_pool-in-two-st.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0148-mtd-nand-pxa3xx-Move-the-data-buffer-clean-to-prepar.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0149-mtd-nand-pxa3xx-Fix-SEQIN-column-address-set.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0150-mtd-nand-pxa3xx-Add-a-read-write-buffers-markers.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0151-mtd-nand-pxa3xx-Introduce-multiple-page-I-O-support.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0152-mtd-nand-pxa3xx-Add-multiple-chunk-write-support.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0153-mtd-nand-pxa3xx-Add-ECC-BCH-correctable-errors-detec.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0154-mtd-nand-pxa3xx-make-ECC-configuration-checks-more-e.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0155-mtd-nand-pxa3xx-Use-info-use_dma-to-release-DMA-reso.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0156-mtd-nand-pxa3xx-Use-extended-cmdfunc-only-if-needed.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0157-mtd-nand-pxa3xx-Consolidate-ECC-initialization.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0158-mtd-nand-Allow-to-build-pxa3xx_nand-on-Orion-platfor.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0159-mtd-nand-pxa3xx-Make-config-menu-show-supported-plat.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0160-ARM-mvebu-config-Add-NAND-support.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0161-net-mvneta-Fix-incorrect-DMA-unmapping-size.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0162-mtd-nand-pxa3xx-Clear-need_wait-flag-when-starting-a.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0163-ARM-mvebu-move-ARMADA_XP_MAX_CPUS-to-armada-370-xp.h.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0164-ARM-mvebu-fix-register-length-for-Armada-XP-PMSU.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0165-ARM-mvebu-make-armada_370_xp_pmsu_init-static.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0166-clocksource-armada-370-xp-Use-BIT.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0167-clocksource-armada-370-xp-Simplify-TIMER_CTRL-regist.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0168-clocksource-armada-370-xp-Introduce-new-compatibles.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0169-clocksource-armada-370-xp-Replace-WARN_ON-with-BUG_O.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0170-clocksource-armada-370-xp-Get-reference-fixed-clock-.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0171-clocksource-armada-370-xp-Register-sched_clock-after.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0172-ARM-mvebu-Fix-the-Armada-370-XP-timer-compatible-str.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0173-ARM-mvebu-Add-the-reference-25-MHz-fixed-clock-to-Ar.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0174-ARM-mvebu-Add-clock-properties-to-Armada-XP-timer-no.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0175-ARM-mvebu-Relocate-PCIe-node-in-Armada-370-RD-board.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0176-of-irq-create-interrupts-extended-property.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0177-of-irq-Avoid-calling-list_first_entry-for-empty-list.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0178-of-clean-up-ifdefs-in-of_irq.h.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0179-of-irq-init-struct-resource-to-0-in-of_irq_to_resour.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0180-irq-of-Fix-comment-typo-for-irq_of_parse_and_map.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0181-of-Fix-dereferencing-node-name-in-debug-output-to-be.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0182-of-irq-Pass-trigger-type-in-IRQ-resource-flags.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0183-of-irq-Rename-of_irq_map_-functions-to-of_irq_parse_.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0184-of-irq-Replace-of_irq-with-of_phandle_args.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0185-of-irq-simplify-args-to-irq_create_of_mapping.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0186-of-irq-Refactor-interrupt-map-parsing.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0187-of-Add-helper-for-printing-an-of_phandle_args-struct.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0188-of-irq-Rework-of_irq_count.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0189-of-irq-create-interrupts-extended-property.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0190-of-irq-Fix-bug-in-interrupt-parsing-refactor.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0191-of-irq-Fix-potential-buffer-overflow.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0192-of-irq-Fix-interrupt-map-entry-matching.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0193-clocksource-armada-370-xp-Fix-device-tree-binding.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0194-clocksource-armada-370-xp-Add-detailed-clock-require.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0195-usb-Add-Device-Tree-support-to-XHCI-Platform-driver.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0196-ata-sata_mv-setting-PHY-speed-according-to-SControl-.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0197-xhci-fix-dma-mask-setup-in-xhci.c.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0198-of-Add-testcases-for-interrupt-parsing.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0199-PCI-mvebu-Convert-to-use-devm_ioremap_resource.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0200-PCI-mvebu-move-clock-enable-before-register-access.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0201-PCI-mvebu-increment-nports-only-for-registered-ports.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0202-ARM-mvebu-second-PCIe-unit-of-Armada-XP-mv78230-is-o.patch [new file with mode: 0644]
target/linux/mvebu/patches-3.10/0203-ARM-mvebu-fix-second-and-third-PCIe-unit-of-Armada-X.patch [new file with mode: 0644]

diff --git a/target/linux/mvebu/patches-3.10/0128-mtd-nand-pxa3xx_nand-Remove-redundant-of_match_ptr.patch b/target/linux/mvebu/patches-3.10/0128-mtd-nand-pxa3xx_nand-Remove-redundant-of_match_ptr.patch
new file mode 100644 (file)
index 0000000..a0c4e69
--- /dev/null
@@ -0,0 +1,25 @@
+From 38a6d3f3330da6586695746a0a85a96143171211 Mon Sep 17 00:00:00 2001
+From: Sachin Kamat <sachin.kamat@linaro.org>
+Date: Mon, 30 Sep 2013 15:10:24 +0530
+Subject: [PATCH 128/203] mtd: nand: pxa3xx_nand: Remove redundant of_match_ptr
+
+The data structure of_match_ptr() protects is always compiled in.
+Hence of_match_ptr() is not needed.
+
+Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -1412,7 +1412,7 @@ static int pxa3xx_nand_resume(struct pla
+ static struct platform_driver pxa3xx_nand_driver = {
+       .driver = {
+               .name   = "pxa3xx-nand",
+-              .of_match_table = of_match_ptr(pxa3xx_nand_dt_ids),
++              .of_match_table = pxa3xx_nand_dt_ids,
+       },
+       .probe          = pxa3xx_nand_probe,
+       .remove         = pxa3xx_nand_remove,
diff --git a/target/linux/mvebu/patches-3.10/0129-mtd-nand-pxa3xx-Move-DMA-I-O-enabling.patch b/target/linux/mvebu/patches-3.10/0129-mtd-nand-pxa3xx-Move-DMA-I-O-enabling.patch
new file mode 100644 (file)
index 0000000..0c95a61
--- /dev/null
@@ -0,0 +1,40 @@
+From 18166290599760e8ff1b6c0389834beafd09a517 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Fri, 4 Oct 2013 15:30:37 -0300
+Subject: [PATCH 129/203] mtd: nand: pxa3xx: Move DMA I/O enabling
+
+Instead of setting info->dma each time a command is prepared,
+we can move it after the DMA buffers are allocated.
+
+This is more clear and it's the proper place to enable this, given
+DMA cannot be turned on and off during runtime.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -540,7 +540,6 @@ static int prepare_command_pool(struct p
+       info->oob_size          = 0;
+       info->use_ecc           = 0;
+       info->use_spare         = 1;
+-      info->use_dma           = (use_dma) ? 1 : 0;
+       info->is_ready          = 0;
+       info->retcode           = ERR_NONE;
+       if (info->cs != 0)
+@@ -950,6 +949,11 @@ static int pxa3xx_nand_init_buff(struct
+               return info->data_dma_ch;
+       }
++      /*
++       * Now that DMA buffers are allocated we turn on
++       * DMA proper for I/O operations.
++       */
++      info->use_dma = 1;
+       return 0;
+ }
diff --git a/target/linux/mvebu/patches-3.10/0130-mtd-nand-pxa3xx-Allocate-data-buffer-on-detected-fla.patch b/target/linux/mvebu/patches-3.10/0130-mtd-nand-pxa3xx-Allocate-data-buffer-on-detected-fla.patch
new file mode 100644 (file)
index 0000000..09f022b
--- /dev/null
@@ -0,0 +1,143 @@
+From 71d6267980d7590e38059a784785ca158e361f87 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Fri, 4 Oct 2013 15:30:38 -0300
+Subject: [PATCH 130/203] mtd: nand: pxa3xx: Allocate data buffer on detected
+ flash size
+
+This commit replaces the currently hardcoded buffer size, by a
+dynamic detection scheme. First a small 256 bytes buffer is allocated
+so the device can be detected (using READID and friends commands).
+
+After detection, this buffer is released and a new buffer is allocated
+to acommodate the page size plus out-of-band size.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 45 ++++++++++++++++++++++++++++--------------
+ 1 file changed, 30 insertions(+), 15 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -39,6 +39,13 @@
+ #define NAND_STOP_DELAY               (2 * HZ/50)
+ #define PAGE_CHUNK_SIZE               (2048)
++/*
++ * Define a buffer size for the initial command that detects the flash device:
++ * STATUS, READID and PARAM. The largest of these is the PARAM command,
++ * needing 256 bytes.
++ */
++#define INIT_BUFFER_SIZE      256
++
+ /* registers and bit definitions */
+ #define NDCR          (0x00) /* Control register */
+ #define NDTR0CS0      (0x04) /* Timing Parameter 0 for CS0 */
+@@ -164,6 +171,7 @@ struct pxa3xx_nand_info {
+       unsigned int            buf_start;
+       unsigned int            buf_count;
++      unsigned int            buf_size;
+       /* DMA information */
+       int                     drcmr_dat;
+@@ -911,26 +919,20 @@ static int pxa3xx_nand_detect_config(str
+       return 0;
+ }
+-/* the maximum possible buffer size for large page with OOB data
+- * is: 2048 + 64 = 2112 bytes, allocate a page here for both the
+- * data buffer and the DMA descriptor
+- */
+-#define MAX_BUFF_SIZE PAGE_SIZE
+-
+ #ifdef ARCH_HAS_DMA
+ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
+ {
+       struct platform_device *pdev = info->pdev;
+-      int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc);
++      int data_desc_offset = info->buf_size - sizeof(struct pxa_dma_desc);
+       if (use_dma == 0) {
+-              info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
++              info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
+               if (info->data_buff == NULL)
+                       return -ENOMEM;
+               return 0;
+       }
+-      info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
++      info->data_buff = dma_alloc_coherent(&pdev->dev, info->buf_size,
+                               &info->data_buff_phys, GFP_KERNEL);
+       if (info->data_buff == NULL) {
+               dev_err(&pdev->dev, "failed to allocate dma buffer\n");
+@@ -944,7 +946,7 @@ static int pxa3xx_nand_init_buff(struct
+                               pxa3xx_nand_data_dma_irq, info);
+       if (info->data_dma_ch < 0) {
+               dev_err(&pdev->dev, "failed to request data dma\n");
+-              dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
++              dma_free_coherent(&pdev->dev, info->buf_size,
+                               info->data_buff, info->data_buff_phys);
+               return info->data_dma_ch;
+       }
+@@ -962,7 +964,7 @@ static void pxa3xx_nand_free_buff(struct
+       struct platform_device *pdev = info->pdev;
+       if (use_dma) {
+               pxa_free_dma(info->data_dma_ch);
+-              dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE,
++              dma_free_coherent(&pdev->dev, info->buf_size,
+                                 info->data_buff, info->data_buff_phys);
+       } else {
+               kfree(info->data_buff);
+@@ -971,7 +973,7 @@ static void pxa3xx_nand_free_buff(struct
+ #else
+ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
+ {
+-      info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
++      info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
+       if (info->data_buff == NULL)
+               return -ENOMEM;
+       return 0;
+@@ -1085,7 +1087,16 @@ KEEP_CONFIG:
+       else
+               host->col_addr_cycles = 1;
++      /* release the initial buffer */
++      kfree(info->data_buff);
++
++      /* allocate the real data + oob buffer */
++      info->buf_size = mtd->writesize + mtd->oobsize;
++      ret = pxa3xx_nand_init_buff(info);
++      if (ret)
++              return ret;
+       info->oob_buff = info->data_buff + mtd->writesize;
++
+       if ((mtd->size >> chip->page_shift) > 65536)
+               host->row_addr_cycles = 3;
+       else
+@@ -1191,9 +1202,13 @@ static int alloc_nand_resource(struct pl
+       }
+       info->mmio_phys = r->start;
+-      ret = pxa3xx_nand_init_buff(info);
+-      if (ret)
++      /* Allocate a buffer to allow flash detection */
++      info->buf_size = INIT_BUFFER_SIZE;
++      info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
++      if (info->data_buff == NULL) {
++              ret = -ENOMEM;
+               goto fail_disable_clk;
++      }
+       /* initialize all interrupts to be disabled */
+       disable_int(info, NDSR_MASK);
+@@ -1211,7 +1226,7 @@ static int alloc_nand_resource(struct pl
+ fail_free_buf:
+       free_irq(irq, info);
+-      pxa3xx_nand_free_buff(info);
++      kfree(info->data_buff);
+ fail_disable_clk:
+       clk_disable_unprepare(info->clk);
+       return ret;
diff --git a/target/linux/mvebu/patches-3.10/0131-mtd-nand-remove-deprecated-IRQF_DISABLED.patch b/target/linux/mvebu/patches-3.10/0131-mtd-nand-remove-deprecated-IRQF_DISABLED.patch
new file mode 100644 (file)
index 0000000..6cecbf2
--- /dev/null
@@ -0,0 +1,27 @@
+From e3779fc4a84e1c51c061e3e13b1abf1c9a56a2cd Mon Sep 17 00:00:00 2001
+From: Michael Opdenacker <michael.opdenacker@free-electrons.com>
+Date: Sun, 13 Oct 2013 08:21:32 +0200
+Subject: [PATCH 131/203] mtd: nand: remove deprecated IRQF_DISABLED
+
+This patch proposes to remove the use of the IRQF_DISABLED flag
+
+It's a NOOP since 2.6.35 and it will be removed one day.
+
+Signed-off-by: Michael Opdenacker <michael.opdenacker@free-electrons.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -1213,8 +1213,7 @@ static int alloc_nand_resource(struct pl
+       /* initialize all interrupts to be disabled */
+       disable_int(info, NDSR_MASK);
+-      ret = request_irq(irq, pxa3xx_nand_irq, IRQF_DISABLED,
+-                        pdev->name, info);
++      ret = request_irq(irq, pxa3xx_nand_irq, 0, pdev->name, info);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to request IRQ\n");
+               goto fail_free_buf;
diff --git a/target/linux/mvebu/patches-3.10/0132-mtd-nand-pxa3xx-Add-documentation-about-the-controll.patch b/target/linux/mvebu/patches-3.10/0132-mtd-nand-pxa3xx-Add-documentation-about-the-controll.patch
new file mode 100644 (file)
index 0000000..561c7d7
--- /dev/null
@@ -0,0 +1,28 @@
+From 54c1163b143e4ed911b8dddc0829c87f93b3debd Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 7 Nov 2013 12:17:10 -0300
+Subject: [PATCH 132/203] mtd: nand: pxa3xx: Add documentation about the
+ controller
+
+Given there's no public specification to this date, and in order
+to capture some important details and singularities about the
+controller let's document them once and for good.
+
+Cc: linux-doc@vger.kernel.org
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -7,6 +7,8 @@
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
++ *
++ * See Documentation/mtd/nand/pxa3xx-nand.txt for more details.
+  */
+ #include <linux/kernel.h>
diff --git a/target/linux/mvebu/patches-3.10/0133-mtd-nand-pxa3xx-Prevent-sub-page-writes.patch b/target/linux/mvebu/patches-3.10/0133-mtd-nand-pxa3xx-Prevent-sub-page-writes.patch
new file mode 100644 (file)
index 0000000..1af6da2
--- /dev/null
@@ -0,0 +1,25 @@
+From ec1977c2873dc7f0e6cec3edb8c30d92882f65d1 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 7 Nov 2013 12:17:12 -0300
+Subject: [PATCH 133/203] mtd: nand: pxa3xx: Prevent sub-page writes
+
+The current driver doesn't support sub-page writing, so report
+that to the NAND core.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -1145,6 +1145,7 @@ static int alloc_nand_resource(struct pl
+               chip->read_byte         = pxa3xx_nand_read_byte;
+               chip->read_buf          = pxa3xx_nand_read_buf;
+               chip->write_buf         = pxa3xx_nand_write_buf;
++              chip->options           |= NAND_NO_SUBPAGE_WRITE;
+       }
+       spin_lock_init(&chip->controller->lock);
diff --git a/target/linux/mvebu/patches-3.10/0134-mtd-nand-pxa3xx-read_page-returns-max_bitflips.patch b/target/linux/mvebu/patches-3.10/0134-mtd-nand-pxa3xx-read_page-returns-max_bitflips.patch
new file mode 100644 (file)
index 0000000..afb8172
--- /dev/null
@@ -0,0 +1,42 @@
+From 97598678602aaea473303523ce37a45d258206ca Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 7 Nov 2013 12:17:13 -0300
+Subject: [PATCH 134/203] mtd: nand: pxa3xx: read_page() returns max_bitflips
+
+As per the ecc.read_page() prototype, we must return the maximum number
+of bitflips that were corrected on any one region covering an ecc step.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -751,6 +751,7 @@ static int pxa3xx_nand_read_page_hwecc(s
+ {
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
++      int max_bitflips = 0;
+       chip->read_buf(mtd, buf, mtd->writesize);
+       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+@@ -758,6 +759,7 @@ static int pxa3xx_nand_read_page_hwecc(s
+       if (info->retcode == ERR_SBERR) {
+               switch (info->use_ecc) {
+               case 1:
++                      max_bitflips = 1;
+                       mtd->ecc_stats.corrected++;
+                       break;
+               case 0:
+@@ -776,7 +778,7 @@ static int pxa3xx_nand_read_page_hwecc(s
+                       mtd->ecc_stats.failed++;
+       }
+-      return 0;
++      return max_bitflips;
+ }
+ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
diff --git a/target/linux/mvebu/patches-3.10/0135-mtd-nand-pxa3xx-Early-variant-detection.patch b/target/linux/mvebu/patches-3.10/0135-mtd-nand-pxa3xx-Early-variant-detection.patch
new file mode 100644 (file)
index 0000000..328a2ab
--- /dev/null
@@ -0,0 +1,97 @@
+From dc333ddda677d416a6726509e144c6dfb93e7e89 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 7 Nov 2013 12:17:14 -0300
+Subject: [PATCH 135/203] mtd: nand: pxa3xx: Early variant detection
+
+In order to customize early settings depending on the detected SoC variant,
+move the detection to be before the nand_chip struct filling.
+
+In a follow-up patch, this change is needed to detect the variant *before*
+the call to alloc_nand_resource(), which allows to set a different cmdfunc()
+for each variant.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 48 +++++++++++++++++++++---------------------
+ 1 file changed, 24 insertions(+), 24 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -258,6 +258,29 @@ static struct pxa3xx_nand_flash builtin_
+ /* convert nano-seconds to nand flash controller clock cycles */
+ #define ns2cycle(ns, clk)     (int)((ns) * (clk / 1000000) / 1000)
++static struct of_device_id pxa3xx_nand_dt_ids[] = {
++      {
++              .compatible = "marvell,pxa3xx-nand",
++              .data       = (void *)PXA3XX_NAND_VARIANT_PXA,
++      },
++      {
++              .compatible = "marvell,armada370-nand",
++              .data       = (void *)PXA3XX_NAND_VARIANT_ARMADA370,
++      },
++      {}
++};
++MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
++
++static enum pxa3xx_nand_variant
++pxa3xx_nand_get_variant(struct platform_device *pdev)
++{
++      const struct of_device_id *of_id =
++                      of_match_device(pxa3xx_nand_dt_ids, &pdev->dev);
++      if (!of_id)
++              return PXA3XX_NAND_VARIANT_PXA;
++      return (enum pxa3xx_nand_variant)of_id->data;
++}
++
+ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
+                                  const struct pxa3xx_nand_timing *t)
+ {
+@@ -1125,6 +1148,7 @@ static int alloc_nand_resource(struct pl
+               return -ENOMEM;
+       info->pdev = pdev;
++      info->variant = pxa3xx_nand_get_variant(pdev);
+       for (cs = 0; cs < pdata->num_cs; cs++) {
+               mtd = (struct mtd_info *)((unsigned int)&info[1] +
+                     (sizeof(*mtd) + sizeof(*host)) * cs);
+@@ -1259,29 +1283,6 @@ static int pxa3xx_nand_remove(struct pla
+       return 0;
+ }
+-static struct of_device_id pxa3xx_nand_dt_ids[] = {
+-      {
+-              .compatible = "marvell,pxa3xx-nand",
+-              .data       = (void *)PXA3XX_NAND_VARIANT_PXA,
+-      },
+-      {
+-              .compatible = "marvell,armada370-nand",
+-              .data       = (void *)PXA3XX_NAND_VARIANT_ARMADA370,
+-      },
+-      {}
+-};
+-MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids);
+-
+-static enum pxa3xx_nand_variant
+-pxa3xx_nand_get_variant(struct platform_device *pdev)
+-{
+-      const struct of_device_id *of_id =
+-                      of_match_device(pxa3xx_nand_dt_ids, &pdev->dev);
+-      if (!of_id)
+-              return PXA3XX_NAND_VARIANT_PXA;
+-      return (enum pxa3xx_nand_variant)of_id->data;
+-}
+-
+ static int pxa3xx_nand_probe_dt(struct platform_device *pdev)
+ {
+       struct pxa3xx_nand_platform_data *pdata;
+@@ -1338,7 +1339,6 @@ static int pxa3xx_nand_probe(struct plat
+       }
+       info = platform_get_drvdata(pdev);
+-      info->variant = pxa3xx_nand_get_variant(pdev);
+       probe_success = 0;
+       for (cs = 0; cs < pdata->num_cs; cs++) {
+               struct mtd_info *mtd = info->host[cs]->mtd;
diff --git a/target/linux/mvebu/patches-3.10/0136-mtd-nand-pxa3xx-Use-chip-cmdfunc-instead-of-the-inte.patch b/target/linux/mvebu/patches-3.10/0136-mtd-nand-pxa3xx-Use-chip-cmdfunc-instead-of-the-inte.patch
new file mode 100644 (file)
index 0000000..de79b8d
--- /dev/null
@@ -0,0 +1,41 @@
+From 67ab922e1e292494732a10f367d3de47338639ac Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 7 Nov 2013 12:17:15 -0300
+Subject: [PATCH 136/203] mtd: nand: pxa3xx: Use chip->cmdfunc instead of the
+ internal
+
+Whenever possible, it's always better to use the generic chip->cmdfunc
+instead of the internal pxa3xx_nand_cmdfunc().
+In this particular case, this will allow to have multiple cmdfunc()
+implementations for different SoC variants.
+
+Reviewed-by: Huang Shijie <shijie8@gmail.com>
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -1015,14 +1015,18 @@ static void pxa3xx_nand_free_buff(struct
+ static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
+ {
+       struct mtd_info *mtd;
++      struct nand_chip *chip;
+       int ret;
++
+       mtd = info->host[info->cs]->mtd;
++      chip = mtd->priv;
++
+       /* use the common timing to make a try */
+       ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+       if (ret)
+               return ret;
+-      pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
++      chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+       if (info->is_ready)
+               return 0;
diff --git a/target/linux/mvebu/patches-3.10/0137-mtd-nand-pxa3xx-Split-FIFO-size-from-to-be-read-FIFO.patch b/target/linux/mvebu/patches-3.10/0137-mtd-nand-pxa3xx-Split-FIFO-size-from-to-be-read-FIFO.patch
new file mode 100644 (file)
index 0000000..e00921d
--- /dev/null
@@ -0,0 +1,74 @@
+From 496f307424d3958ef43ad06ae6a0be98ede2a92c Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 7 Nov 2013 12:17:16 -0300
+Subject: [PATCH 137/203] mtd: nand: pxa3xx: Split FIFO size from to-be-read
+ FIFO count
+
+Introduce a fifo_size field to represent the size of the controller's
+FIFO buffer, and use it to distinguish that size from the amount
+of data bytes to be read from the FIFO.
+
+This is important to support devices with pages larger than the
+controller's internal FIFO, that need to read the pages in FIFO-sized
+chunks.
+
+In particular, the current code is at least confusing, for it mixes
+all the different sizes involved: FIFO size, page size and data size.
+
+This commit starts the cleaning by removing the info->page_size field
+that is not currently used. The host->page_size field should also
+be removed and use always mtd->writesize instead. Follow up commits
+will clean this up.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -201,8 +201,8 @@ struct pxa3xx_nand_info {
+       int                     use_spare;      /* use spare ? */
+       int                     is_ready;
+-      unsigned int            page_size;      /* page size of attached chip */
+-      unsigned int            data_size;      /* data size in FIFO */
++      unsigned int            fifo_size;      /* max. data size in the FIFO */
++      unsigned int            data_size;      /* data to be read from FIFO */
+       unsigned int            oob_size;
+       int                     retcode;
+@@ -307,16 +307,15 @@ static void pxa3xx_nand_set_timing(struc
+ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
+ {
+-      struct pxa3xx_nand_host *host = info->host[info->cs];
+       int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
+-      info->data_size = host->page_size;
++      info->data_size = info->fifo_size;
+       if (!oob_enable) {
+               info->oob_size = 0;
+               return;
+       }
+-      switch (host->page_size) {
++      switch (info->fifo_size) {
+       case 2048:
+               info->oob_size = (info->use_ecc) ? 40 : 64;
+               break;
+@@ -933,9 +932,12 @@ static int pxa3xx_nand_detect_config(str
+       uint32_t ndcr = nand_readl(info, NDCR);
+       if (ndcr & NDCR_PAGE_SZ) {
++              /* Controller's FIFO size */
++              info->fifo_size = 2048;
+               host->page_size = 2048;
+               host->read_id_bytes = 4;
+       } else {
++              info->fifo_size = 512;
+               host->page_size = 512;
+               host->read_id_bytes = 2;
+       }
diff --git a/target/linux/mvebu/patches-3.10/0138-mtd-nand-pxa3xx-Replace-host-page_size-by-mtd-writes.patch b/target/linux/mvebu/patches-3.10/0138-mtd-nand-pxa3xx-Replace-host-page_size-by-mtd-writes.patch
new file mode 100644 (file)
index 0000000..259f6a0
--- /dev/null
@@ -0,0 +1,72 @@
+From ad40a597cbfeb2374c799ba6dad3a69f131511c8 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 7 Nov 2013 12:17:17 -0300
+Subject: [PATCH 138/203] mtd: nand: pxa3xx: Replace host->page_size by
+ mtd->writesize
+
+There's no need to privately store the device page size as it's
+available in mtd structure field mtd->writesize.
+Also, this removes the hardcoded page size value, leaving the
+auto-detected value only.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 10 +++-------
+ 1 file changed, 3 insertions(+), 7 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -151,7 +151,6 @@ struct pxa3xx_nand_host {
+       void                    *info_data;
+       /* page size of attached chip */
+-      unsigned int            page_size;
+       int                     use_ecc;
+       int                     cs;
+@@ -614,12 +613,12 @@ static int prepare_command_pool(struct p
+                       info->buf_start += mtd->writesize;
+               /* Second command setting for large pages */
+-              if (host->page_size >= PAGE_CHUNK_SIZE)
++              if (mtd->writesize >= PAGE_CHUNK_SIZE)
+                       info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8);
+       case NAND_CMD_SEQIN:
+               /* small page addr setting */
+-              if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) {
++              if (unlikely(mtd->writesize < PAGE_CHUNK_SIZE)) {
+                       info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+                                       | (column & 0xFF);
+@@ -895,7 +894,6 @@ static int pxa3xx_nand_config_flash(stru
+       }
+       /* calculate flash information */
+-      host->page_size = f->page_size;
+       host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
+       /* calculate addressing information */
+@@ -934,11 +932,9 @@ static int pxa3xx_nand_detect_config(str
+       if (ndcr & NDCR_PAGE_SZ) {
+               /* Controller's FIFO size */
+               info->fifo_size = 2048;
+-              host->page_size = 2048;
+               host->read_id_bytes = 4;
+       } else {
+               info->fifo_size = 512;
+-              host->page_size = 512;
+               host->read_id_bytes = 2;
+       }
+@@ -1106,7 +1102,7 @@ static int pxa3xx_nand_scan(struct mtd_i
+       def = pxa3xx_flash_ids;
+ KEEP_CONFIG:
+       chip->ecc.mode = NAND_ECC_HW;
+-      chip->ecc.size = host->page_size;
++      chip->ecc.size = info->fifo_size;
+       chip->ecc.strength = 1;
+       if (info->reg_ndcr & NDCR_DWIDTH_M)
diff --git a/target/linux/mvebu/patches-3.10/0139-mtd-nand-pxa3xx-Add-a-nice-comment-to-pxa3xx_set_dat.patch b/target/linux/mvebu/patches-3.10/0139-mtd-nand-pxa3xx-Add-a-nice-comment-to-pxa3xx_set_dat.patch
new file mode 100644 (file)
index 0000000..aeecae6
--- /dev/null
@@ -0,0 +1,30 @@
+From 8bce53e42f78e009fbfbd4a98ea98f66e6cd5b4c Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 7 Nov 2013 12:17:18 -0300
+Subject: [PATCH 139/203] mtd: nand: pxa3xx: Add a nice comment to
+ pxa3xx_set_datasize()
+
+Add a comment clarifying the use of pxa3xx_set_datasize() which is only
+applicable on data read/write commands (i.e. commands with a data cycle,
+such as READID, READ0, STATUS, etc.)
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -304,6 +304,11 @@ static void pxa3xx_nand_set_timing(struc
+       nand_writel(info, NDTR1CS0, ndtr1);
+ }
++/*
++ * Set the data and OOB size, depending on the selected
++ * spare and ECC configuration.
++ * Only applicable to READ0, READOOB and PAGEPROG commands.
++ */
+ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
+ {
+       int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
diff --git a/target/linux/mvebu/patches-3.10/0140-mtd-nand-pxa3xx-Use-a-completion-to-signal-device-re.patch b/target/linux/mvebu/patches-3.10/0140-mtd-nand-pxa3xx-Use-a-completion-to-signal-device-re.patch
new file mode 100644 (file)
index 0000000..7f5108f
--- /dev/null
@@ -0,0 +1,138 @@
+From b5289e9cb18e6c254e13826e6bcfbfe95b819d77 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:26 -0300
+Subject: [PATCH 140/203] mtd: nand: pxa3xx: Use a completion to signal device
+ ready
+
+The expected behavior of the waitfunc() NAND chip call is to wait
+for the device to be READY (this is a standard chip line).
+However, the current implementation does almost nothing, which opens
+the possibility of issuing a command to a non-ready device.
+
+Fix this by adding a new completion to wait for the ready event to arrive.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 38 ++++++++++++++++++++++++--------------
+ 1 file changed, 24 insertions(+), 14 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -37,6 +37,7 @@
+ #include <linux/platform_data/mtd-nand-pxa3xx.h>
++#define NAND_DEV_READY_TIMEOUT  50
+ #define       CHIP_DELAY_TIMEOUT      (2 * HZ/10)
+ #define NAND_STOP_DELAY               (2 * HZ/50)
+ #define PAGE_CHUNK_SIZE               (2048)
+@@ -168,7 +169,7 @@ struct pxa3xx_nand_info {
+       struct clk              *clk;
+       void __iomem            *mmio_base;
+       unsigned long           mmio_phys;
+-      struct completion       cmd_complete;
++      struct completion       cmd_complete, dev_ready;
+       unsigned int            buf_start;
+       unsigned int            buf_count;
+@@ -198,7 +199,7 @@ struct pxa3xx_nand_info {
+       int                     use_ecc;        /* use HW ECC ? */
+       int                     use_dma;        /* use DMA ? */
+       int                     use_spare;      /* use spare ? */
+-      int                     is_ready;
++      int                     need_wait;
+       unsigned int            fifo_size;      /* max. data size in the FIFO */
+       unsigned int            data_size;      /* data to be read from FIFO */
+@@ -480,7 +481,7 @@ static void start_data_dma(struct pxa3xx
+ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
+ {
+       struct pxa3xx_nand_info *info = devid;
+-      unsigned int status, is_completed = 0;
++      unsigned int status, is_completed = 0, is_ready = 0;
+       unsigned int ready, cmd_done;
+       if (info->cs == 0) {
+@@ -516,8 +517,8 @@ static irqreturn_t pxa3xx_nand_irq(int i
+               is_completed = 1;
+       }
+       if (status & ready) {
+-              info->is_ready = 1;
+               info->state = STATE_READY;
++              is_ready = 1;
+       }
+       if (status & NDSR_WRCMDREQ) {
+@@ -546,6 +547,8 @@ static irqreturn_t pxa3xx_nand_irq(int i
+       nand_writel(info, NDSR, status);
+       if (is_completed)
+               complete(&info->cmd_complete);
++      if (is_ready)
++              complete(&info->dev_ready);
+ NORMAL_IRQ_EXIT:
+       return IRQ_HANDLED;
+ }
+@@ -576,7 +579,6 @@ static int prepare_command_pool(struct p
+       info->oob_size          = 0;
+       info->use_ecc           = 0;
+       info->use_spare         = 1;
+-      info->is_ready          = 0;
+       info->retcode           = ERR_NONE;
+       if (info->cs != 0)
+               info->ndcb0 = NDCB0_CSEL;
+@@ -749,6 +751,8 @@ static void pxa3xx_nand_cmdfunc(struct m
+       exec_cmd = prepare_command_pool(info, command, column, page_addr);
+       if (exec_cmd) {
+               init_completion(&info->cmd_complete);
++              init_completion(&info->dev_ready);
++              info->need_wait = 1;
+               pxa3xx_nand_start(info);
+               ret = wait_for_completion_timeout(&info->cmd_complete,
+@@ -863,21 +867,27 @@ static int pxa3xx_nand_waitfunc(struct m
+ {
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
++      int ret;
++
++      if (info->need_wait) {
++              ret = wait_for_completion_timeout(&info->dev_ready,
++                              CHIP_DELAY_TIMEOUT);
++              info->need_wait = 0;
++              if (!ret) {
++                      dev_err(&info->pdev->dev, "Ready time out!!!\n");
++                      return NAND_STATUS_FAIL;
++              }
++      }
+       /* pxa3xx_nand_send_command has waited for command complete */
+       if (this->state == FL_WRITING || this->state == FL_ERASING) {
+               if (info->retcode == ERR_NONE)
+                       return 0;
+-              else {
+-                      /*
+-                       * any error make it return 0x01 which will tell
+-                       * the caller the erase and write fail
+-                       */
+-                      return 0x01;
+-              }
++              else
++                      return NAND_STATUS_FAIL;
+       }
+-      return 0;
++      return NAND_STATUS_READY;
+ }
+ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
+@@ -1030,7 +1040,7 @@ static int pxa3xx_nand_sensing(struct px
+               return ret;
+       chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+-      if (info->is_ready)
++      if (!info->need_wait)
+               return 0;
+       return -ENODEV;
diff --git a/target/linux/mvebu/patches-3.10/0141-mtd-nand-pxa3xx-Use-waitfunc-to-wait-for-the-device-.patch b/target/linux/mvebu/patches-3.10/0141-mtd-nand-pxa3xx-Use-waitfunc-to-wait-for-the-device-.patch
new file mode 100644 (file)
index 0000000..13fdffe
--- /dev/null
@@ -0,0 +1,34 @@
+From 2a1254f505ca4d376eae81768e4d5d890b578d13 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:27 -0300
+Subject: [PATCH 141/203] mtd: nand: pxa3xx: Use waitfunc() to wait for the
+ device to be ready
+
+In pxa3xx_nand_sensing() instead of simply using info->is_ready
+after issuing a command, the correct way of checking is to wait
+for the device to be ready through the chip's waitfunc().
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -1040,10 +1040,11 @@ static int pxa3xx_nand_sensing(struct px
+               return ret;
+       chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+-      if (!info->need_wait)
+-              return 0;
++      ret = chip->waitfunc(mtd, chip);
++      if (ret & NAND_STATUS_FAIL)
++              return -ENODEV;
+-      return -ENODEV;
++      return 0;
+ }
+ static int pxa3xx_nand_scan(struct mtd_info *mtd)
diff --git a/target/linux/mvebu/patches-3.10/0142-mtd-nand-pxa3xx-Add-bad-block-handling.patch b/target/linux/mvebu/patches-3.10/0142-mtd-nand-pxa3xx-Add-bad-block-handling.patch
new file mode 100644 (file)
index 0000000..0d04bf4
--- /dev/null
@@ -0,0 +1,108 @@
+From bd428b9b18c2dffb8c9d737e99adfd145822e502 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:28 -0300
+Subject: [PATCH 142/203] mtd: nand: pxa3xx: Add bad block handling
+
+Add support for flash-based bad block table using Marvell's
+custom in-flash bad block table layout. The support is enabled
+a 'flash_bbt' platform data or device tree parameter.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ .../devicetree/bindings/mtd/pxa3xx-nand.txt        |  2 ++
+ drivers/mtd/nand/pxa3xx_nand.c                     | 37 ++++++++++++++++++++++
+ include/linux/platform_data/mtd-nand-pxa3xx.h      |  3 ++
+ 3 files changed, 42 insertions(+)
+
+--- a/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
++++ b/Documentation/devicetree/bindings/mtd/pxa3xx-nand.txt
+@@ -13,6 +13,8 @@ Optional properties:
+  - marvell,nand-keep-config:  Set to keep the NAND controller config as set
+                               by the bootloader
+  - num-cs:                    Number of chipselect lines to usw
++ - nand-on-flash-bbt:                 boolean to enable on flash bbt option if
++                              not present false
+ Example:
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -26,6 +26,7 @@
+ #include <linux/slab.h>
+ #include <linux/of.h>
+ #include <linux/of_device.h>
++#include <linux/of_mtd.h>
+ #if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)
+ #define ARCH_HAS_DMA
+@@ -241,6 +242,29 @@ static struct pxa3xx_nand_flash builtin_
+ { "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
+ };
++static u8 bbt_pattern[] = {'M', 'V', 'B', 'b', 't', '0' };
++static u8 bbt_mirror_pattern[] = {'1', 't', 'b', 'B', 'V', 'M' };
++
++static struct nand_bbt_descr bbt_main_descr = {
++      .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
++              | NAND_BBT_2BIT | NAND_BBT_VERSION,
++      .offs = 8,
++      .len = 6,
++      .veroffs = 14,
++      .maxblocks = 8,         /* Last 8 blocks in each chip */
++      .pattern = bbt_pattern
++};
++
++static struct nand_bbt_descr bbt_mirror_descr = {
++      .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE
++              | NAND_BBT_2BIT | NAND_BBT_VERSION,
++      .offs = 8,
++      .len = 6,
++      .veroffs = 14,
++      .maxblocks = 8,         /* Last 8 blocks in each chip */
++      .pattern = bbt_mirror_pattern
++};
++
+ /* Define a default flash type setting serve as flash detecting only */
+ #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
+@@ -1126,6 +1150,18 @@ KEEP_CONFIG:
+       if (nand_scan_ident(mtd, 1, def))
+               return -ENODEV;
++
++      if (pdata->flash_bbt) {
++              /*
++               * We'll use a bad block table stored in-flash and don't
++               * allow writing the bad block marker to the flash.
++               */
++              chip->bbt_options |= NAND_BBT_USE_FLASH |
++                                   NAND_BBT_NO_OOB_BBM;
++              chip->bbt_td = &bbt_main_descr;
++              chip->bbt_md = &bbt_mirror_descr;
++      }
++
+       /* calculate addressing information */
+       if (mtd->writesize >= 2048)
+               host->col_addr_cycles = 2;
+@@ -1320,6 +1356,7 @@ static int pxa3xx_nand_probe_dt(struct p
+       if (of_get_property(np, "marvell,nand-keep-config", NULL))
+               pdata->keep_config = 1;
+       of_property_read_u32(np, "num-cs", &pdata->num_cs);
++      pdata->flash_bbt = of_get_nand_on_flash_bbt(np);
+       pdev->dev.platform_data = pdata;
+--- a/include/linux/platform_data/mtd-nand-pxa3xx.h
++++ b/include/linux/platform_data/mtd-nand-pxa3xx.h
+@@ -55,6 +55,9 @@ struct pxa3xx_nand_platform_data {
+       /* indicate how many chip selects will be used */
+       int     num_cs;
++      /* use an flash-based bad block table */
++      bool    flash_bbt;
++
+       const struct mtd_partition              *parts[NUM_CHIP_SELECT];
+       unsigned int                            nr_parts[NUM_CHIP_SELECT];
diff --git a/target/linux/mvebu/patches-3.10/0143-mtd-nand-pxa3xx-Add-driver-specific-ECC-BCH-support.patch b/target/linux/mvebu/patches-3.10/0143-mtd-nand-pxa3xx-Add-driver-specific-ECC-BCH-support.patch
new file mode 100644 (file)
index 0000000..c310eff
--- /dev/null
@@ -0,0 +1,172 @@
+From 3677d22ed7e3a631f35e2addc4e2181f6215e4b0 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:29 -0300
+Subject: [PATCH 143/203] mtd: nand: pxa3xx: Add driver-specific ECC BCH
+ support
+
+This commit adds the BCH ECC support available in NFCv2 controller.
+Depending on the detected required strength the respective ECC layout
+is selected.
+
+This commit adds an empty ECC layout, since support to access large
+pages is first required. Once that support is added, a proper ECC
+layout will be added as well.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 86 +++++++++++++++++++++++++++++++++---------
+ 1 file changed, 69 insertions(+), 17 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -58,6 +58,7 @@
+ #define NDPCR         (0x18) /* Page Count Register */
+ #define NDBDR0                (0x1C) /* Bad Block Register 0 */
+ #define NDBDR1                (0x20) /* Bad Block Register 1 */
++#define NDECCCTRL     (0x28) /* ECC control */
+ #define NDDB          (0x40) /* Data Buffer */
+ #define NDCB0         (0x48) /* Command Buffer0 */
+ #define NDCB1         (0x4C) /* Command Buffer1 */
+@@ -198,6 +199,7 @@ struct pxa3xx_nand_info {
+       int                     cs;
+       int                     use_ecc;        /* use HW ECC ? */
++      int                     ecc_bch;        /* using BCH ECC? */
+       int                     use_dma;        /* use DMA ? */
+       int                     use_spare;      /* use spare ? */
+       int                     need_wait;
+@@ -205,6 +207,8 @@ struct pxa3xx_nand_info {
+       unsigned int            fifo_size;      /* max. data size in the FIFO */
+       unsigned int            data_size;      /* data to be read from FIFO */
+       unsigned int            oob_size;
++      unsigned int            spare_size;
++      unsigned int            ecc_size;
+       int                     retcode;
+       /* cached register value */
+@@ -339,19 +343,12 @@ static void pxa3xx_set_datasize(struct p
+       int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
+       info->data_size = info->fifo_size;
+-      if (!oob_enable) {
+-              info->oob_size = 0;
++      if (!oob_enable)
+               return;
+-      }
+-      switch (info->fifo_size) {
+-      case 2048:
+-              info->oob_size = (info->use_ecc) ? 40 : 64;
+-              break;
+-      case 512:
+-              info->oob_size = (info->use_ecc) ? 8 : 16;
+-              break;
+-      }
++      info->oob_size = info->spare_size;
++      if (!info->use_ecc)
++              info->oob_size += info->ecc_size;
+ }
+ /**
+@@ -366,10 +363,15 @@ static void pxa3xx_nand_start(struct pxa
+       ndcr = info->reg_ndcr;
+-      if (info->use_ecc)
++      if (info->use_ecc) {
+               ndcr |= NDCR_ECC_EN;
+-      else
++              if (info->ecc_bch)
++                      nand_writel(info, NDECCCTRL, 0x1);
++      } else {
+               ndcr &= ~NDCR_ECC_EN;
++              if (info->ecc_bch)
++                      nand_writel(info, NDECCCTRL, 0x0);
++      }
+       if (info->use_dma)
+               ndcr |= NDCR_DMA_EN;
+@@ -1071,6 +1073,41 @@ static int pxa3xx_nand_sensing(struct px
+       return 0;
+ }
++static int pxa_ecc_init(struct pxa3xx_nand_info *info,
++                      struct nand_ecc_ctrl *ecc,
++                      int strength, int page_size)
++{
++      /*
++       * We don't use strength here as the PXA variant
++       * is used with non-ONFI compliant devices.
++       */
++      if (page_size == 2048) {
++              info->spare_size = 40;
++              info->ecc_size = 24;
++              ecc->mode = NAND_ECC_HW;
++              ecc->size = 512;
++              ecc->strength = 1;
++              return 1;
++
++      } else if (page_size == 512) {
++              info->spare_size = 8;
++              info->ecc_size = 8;
++              ecc->mode = NAND_ECC_HW;
++              ecc->size = 512;
++              ecc->strength = 1;
++              return 1;
++      }
++      return 0;
++}
++
++static int armada370_ecc_init(struct pxa3xx_nand_info *info,
++                            struct nand_ecc_ctrl *ecc,
++                            int strength, int page_size)
++{
++      /* Unimplemented yet */
++      return 0;
++}
++
+ static int pxa3xx_nand_scan(struct mtd_info *mtd)
+ {
+       struct pxa3xx_nand_host *host = mtd->priv;
+@@ -1141,13 +1178,13 @@ static int pxa3xx_nand_scan(struct mtd_i
+       pxa3xx_flash_ids[1].name = NULL;
+       def = pxa3xx_flash_ids;
+ KEEP_CONFIG:
+-      chip->ecc.mode = NAND_ECC_HW;
+-      chip->ecc.size = info->fifo_size;
+-      chip->ecc.strength = 1;
+-
+       if (info->reg_ndcr & NDCR_DWIDTH_M)
+               chip->options |= NAND_BUSWIDTH_16;
++      /* Device detection must be done with ECC disabled */
++      if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
++              nand_writel(info, NDECCCTRL, 0x0);
++
+       if (nand_scan_ident(mtd, 1, def))
+               return -ENODEV;
+@@ -1162,6 +1199,21 @@ KEEP_CONFIG:
+               chip->bbt_md = &bbt_mirror_descr;
+       }
++      if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
++              ret = armada370_ecc_init(info, &chip->ecc,
++                                 chip->ecc_strength_ds,
++                                 mtd->writesize);
++      else
++              ret = pxa_ecc_init(info, &chip->ecc,
++                                 chip->ecc_strength_ds,
++                                 mtd->writesize);
++      if (!ret) {
++              dev_err(&info->pdev->dev,
++                      "ECC strength %d at page size %d is not supported\n",
++                      chip->ecc_strength_ds, mtd->writesize);
++              return -ENODEV;
++      }
++
+       /* calculate addressing information */
+       if (mtd->writesize >= 2048)
+               host->col_addr_cycles = 2;
diff --git a/target/linux/mvebu/patches-3.10/0144-mtd-nand-pxa3xx-Clear-cmd-buffer-3-NDCB3-on-command-.patch b/target/linux/mvebu/patches-3.10/0144-mtd-nand-pxa3xx-Clear-cmd-buffer-3-NDCB3-on-command-.patch
new file mode 100644 (file)
index 0000000..567cc8e
--- /dev/null
@@ -0,0 +1,34 @@
+From cb574fecefd9552e5c6c5105adab7b37b0feb712 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:30 -0300
+Subject: [PATCH 144/203] mtd: nand: pxa3xx: Clear cmd buffer #3 (NDCB3) on
+ command start
+
+Command buffer #3 is not properly cleared and it keeps the last
+set value. Fix this by clearing when a command is setup.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -606,6 +606,7 @@ static int prepare_command_pool(struct p
+       info->use_ecc           = 0;
+       info->use_spare         = 1;
+       info->retcode           = ERR_NONE;
++      info->ndcb3             = 0;
+       if (info->cs != 0)
+               info->ndcb0 = NDCB0_CSEL;
+       else
+@@ -627,7 +628,6 @@ static int prepare_command_pool(struct p
+       default:
+               info->ndcb1 = 0;
+               info->ndcb2 = 0;
+-              info->ndcb3 = 0;
+               break;
+       }
diff --git a/target/linux/mvebu/patches-3.10/0145-mtd-nand-pxa3xx-Add-helper-function-to-set-page-addr.patch b/target/linux/mvebu/patches-3.10/0145-mtd-nand-pxa3xx-Add-helper-function-to-set-page-addr.patch
new file mode 100644 (file)
index 0000000..a0a909e
--- /dev/null
@@ -0,0 +1,70 @@
+From 09a84f8e89c3715160423701b0606ef99e2a05bf Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:31 -0300
+Subject: [PATCH 145/203] mtd: nand: pxa3xx: Add helper function to set page
+ address
+
+Let's simplify the code by first introducing a helper function
+to set the page address, as done by the READ0, READOOB and SEQIN
+commands.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 36 +++++++++++++++++++++---------------
+ 1 file changed, 21 insertions(+), 15 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -587,6 +587,26 @@ static inline int is_buf_blank(uint8_t *
+       return 1;
+ }
++static void set_command_address(struct pxa3xx_nand_info *info,
++              unsigned int page_size, uint16_t column, int page_addr)
++{
++      /* small page addr setting */
++      if (page_size < PAGE_CHUNK_SIZE) {
++              info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
++                              | (column & 0xFF);
++
++              info->ndcb2 = 0;
++      } else {
++              info->ndcb1 = ((page_addr & 0xFFFF) << 16)
++                              | (column & 0xFFFF);
++
++              if (page_addr & 0xFF0000)
++                      info->ndcb2 = (page_addr & 0xFF0000) >> 16;
++              else
++                      info->ndcb2 = 0;
++      }
++}
++
+ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
+               uint16_t column, int page_addr)
+ {
+@@ -650,22 +670,8 @@ static int prepare_command_pool(struct p
+                       info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8);
+       case NAND_CMD_SEQIN:
+-              /* small page addr setting */
+-              if (unlikely(mtd->writesize < PAGE_CHUNK_SIZE)) {
+-                      info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+-                                      | (column & 0xFF);
+-
+-                      info->ndcb2 = 0;
+-              } else {
+-                      info->ndcb1 = ((page_addr & 0xFFFF) << 16)
+-                                      | (column & 0xFFFF);
+-
+-                      if (page_addr & 0xFF0000)
+-                              info->ndcb2 = (page_addr & 0xFF0000) >> 16;
+-                      else
+-                              info->ndcb2 = 0;
+-              }
++              set_command_address(info, mtd->writesize, column, page_addr);
+               info->buf_count = mtd->writesize + mtd->oobsize;
+               memset(info->data_buff, 0xFF, info->buf_count);
diff --git a/target/linux/mvebu/patches-3.10/0146-mtd-nand-pxa3xx-Remove-READ0-switch-case-falltrough.patch b/target/linux/mvebu/patches-3.10/0146-mtd-nand-pxa3xx-Remove-READ0-switch-case-falltrough.patch
new file mode 100644 (file)
index 0000000..0631b92
--- /dev/null
@@ -0,0 +1,32 @@
+From 11532c10a29e4faef29b5f3b354391d1e2f90213 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:32 -0300
+Subject: [PATCH 146/203] mtd: nand: pxa3xx: Remove READ0 switch/case
+ falltrough
+
+READ0 and READOOB command preparation has a falltrough to SEQIN
+case, where the command address is specified.
+This is certainly confusing and makes the code less readable with
+no added value. Let's remove it.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -669,6 +669,11 @@ static int prepare_command_pool(struct p
+               if (mtd->writesize >= PAGE_CHUNK_SIZE)
+                       info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8);
++              set_command_address(info, mtd->writesize, column, page_addr);
++              info->buf_count = mtd->writesize + mtd->oobsize;
++              memset(info->data_buff, 0xFF, info->buf_count);
++              break;
++
+       case NAND_CMD_SEQIN:
+               set_command_address(info, mtd->writesize, column, page_addr);
diff --git a/target/linux/mvebu/patches-3.10/0147-mtd-nand-pxa3xx-Split-prepare_command_pool-in-two-st.patch b/target/linux/mvebu/patches-3.10/0147-mtd-nand-pxa3xx-Split-prepare_command_pool-in-two-st.patch
new file mode 100644 (file)
index 0000000..aa25c07
--- /dev/null
@@ -0,0 +1,101 @@
+From 78c8c8dc7e27c4502504cb4daa07bc9762f54de9 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:33 -0300
+Subject: [PATCH 147/203] mtd: nand: pxa3xx: Split prepare_command_pool() in
+ two stages
+
+This commit splits the prepare_command_pool() function into two
+stages: prepare_start_command() / prepare_set_command().
+
+This is a preparation patch without any functionality changes,
+and is meant to allow support for multiple page reading/writing
+operations.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 44 ++++++++++++++++++++++++------------------
+ 1 file changed, 25 insertions(+), 19 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -607,18 +607,8 @@ static void set_command_address(struct p
+       }
+ }
+-static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
+-              uint16_t column, int page_addr)
++static void prepare_start_command(struct pxa3xx_nand_info *info, int command)
+ {
+-      int addr_cycle, exec_cmd;
+-      struct pxa3xx_nand_host *host;
+-      struct mtd_info *mtd;
+-
+-      host = info->host[info->cs];
+-      mtd = host->mtd;
+-      addr_cycle = 0;
+-      exec_cmd = 1;
+-
+       /* reset data and oob column point to handle data */
+       info->buf_start         = 0;
+       info->buf_count         = 0;
+@@ -627,10 +617,6 @@ static int prepare_command_pool(struct p
+       info->use_spare         = 1;
+       info->retcode           = ERR_NONE;
+       info->ndcb3             = 0;
+-      if (info->cs != 0)
+-              info->ndcb0 = NDCB0_CSEL;
+-      else
+-              info->ndcb0 = 0;
+       switch (command) {
+       case NAND_CMD_READ0:
+@@ -642,14 +628,32 @@ static int prepare_command_pool(struct p
+       case NAND_CMD_PARAM:
+               info->use_spare = 0;
+               break;
+-      case NAND_CMD_SEQIN:
+-              exec_cmd = 0;
+-              break;
+       default:
+               info->ndcb1 = 0;
+               info->ndcb2 = 0;
+               break;
+       }
++}
++
++static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
++              uint16_t column, int page_addr)
++{
++      int addr_cycle, exec_cmd;
++      struct pxa3xx_nand_host *host;
++      struct mtd_info *mtd;
++
++      host = info->host[info->cs];
++      mtd = host->mtd;
++      addr_cycle = 0;
++      exec_cmd = 1;
++
++      if (info->cs != 0)
++              info->ndcb0 = NDCB0_CSEL;
++      else
++              info->ndcb0 = 0;
++
++      if (command == NAND_CMD_SEQIN)
++              exec_cmd = 0;
+       addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles
+                                   + host->col_addr_cycles);
+@@ -784,8 +788,10 @@ static void pxa3xx_nand_cmdfunc(struct m
+               nand_writel(info, NDTR1CS0, info->ndtr1cs0);
+       }
++      prepare_start_command(info, command);
++
+       info->state = STATE_PREPARED;
+-      exec_cmd = prepare_command_pool(info, command, column, page_addr);
++      exec_cmd = prepare_set_command(info, command, column, page_addr);
+       if (exec_cmd) {
+               init_completion(&info->cmd_complete);
+               init_completion(&info->dev_ready);
diff --git a/target/linux/mvebu/patches-3.10/0148-mtd-nand-pxa3xx-Move-the-data-buffer-clean-to-prepar.patch b/target/linux/mvebu/patches-3.10/0148-mtd-nand-pxa3xx-Move-the-data-buffer-clean-to-prepar.patch
new file mode 100644 (file)
index 0000000..3d74844
--- /dev/null
@@ -0,0 +1,69 @@
+From 1c0aed9b4cfb7bb891aab07a429436d017ac4d7c Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:34 -0300
+Subject: [PATCH 148/203] mtd: nand: pxa3xx: Move the data buffer clean to
+ prepare_start_command()
+
+To allow future support of multiple page reading/writing, move the data
+buffer clean out of prepare_set_command().
+
+This is done to prevent the data buffer from being cleaned on every command
+preparation, when a multiple command sequence is implemented to read/write
+pages larger than the FIFO size (2 KiB).
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 21 ++++++++++++++++-----
+ 1 file changed, 16 insertions(+), 5 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -609,6 +609,9 @@ static void set_command_address(struct p
+ static void prepare_start_command(struct pxa3xx_nand_info *info, int command)
+ {
++      struct pxa3xx_nand_host *host = info->host[info->cs];
++      struct mtd_info *mtd = host->mtd;
++
+       /* reset data and oob column point to handle data */
+       info->buf_start         = 0;
+       info->buf_count         = 0;
+@@ -633,6 +636,19 @@ static void prepare_start_command(struct
+               info->ndcb2 = 0;
+               break;
+       }
++
++      /*
++       * If we are about to issue a read command, or about to set
++       * the write address, then clean the data buffer.
++       */
++      if (command == NAND_CMD_READ0 ||
++          command == NAND_CMD_READOOB ||
++          command == NAND_CMD_SEQIN) {
++
++              info->buf_count = mtd->writesize + mtd->oobsize;
++              memset(info->data_buff, 0xFF, info->buf_count);
++      }
++
+ }
+ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
+@@ -674,16 +690,11 @@ static int prepare_set_command(struct px
+                       info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8);
+               set_command_address(info, mtd->writesize, column, page_addr);
+-              info->buf_count = mtd->writesize + mtd->oobsize;
+-              memset(info->data_buff, 0xFF, info->buf_count);
+               break;
+       case NAND_CMD_SEQIN:
+               set_command_address(info, mtd->writesize, column, page_addr);
+-              info->buf_count = mtd->writesize + mtd->oobsize;
+-              memset(info->data_buff, 0xFF, info->buf_count);
+-
+               break;
+       case NAND_CMD_PAGEPROG:
diff --git a/target/linux/mvebu/patches-3.10/0149-mtd-nand-pxa3xx-Fix-SEQIN-column-address-set.patch b/target/linux/mvebu/patches-3.10/0149-mtd-nand-pxa3xx-Fix-SEQIN-column-address-set.patch
new file mode 100644 (file)
index 0000000..cb59ccb
--- /dev/null
@@ -0,0 +1,32 @@
+From d5c9b013c71a570737353270f94b9a52639fcea1 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:35 -0300
+Subject: [PATCH 149/203] mtd: nand: pxa3xx: Fix SEQIN column address set
+
+This commit adds support page programming with a non-zero "column"
+address setting. This is important to support OOB writing, through
+command sequences such as:
+
+  cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, ofs);
+  write_buf(mtd, oob_buf, 6);
+  cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -694,7 +694,8 @@ static int prepare_set_command(struct px
+       case NAND_CMD_SEQIN:
+-              set_command_address(info, mtd->writesize, column, page_addr);
++              info->buf_start = column;
++              set_command_address(info, mtd->writesize, 0, page_addr);
+               break;
+       case NAND_CMD_PAGEPROG:
diff --git a/target/linux/mvebu/patches-3.10/0150-mtd-nand-pxa3xx-Add-a-read-write-buffers-markers.patch b/target/linux/mvebu/patches-3.10/0150-mtd-nand-pxa3xx-Add-a-read-write-buffers-markers.patch
new file mode 100644 (file)
index 0000000..1251f60
--- /dev/null
@@ -0,0 +1,111 @@
+From 6e3022aeb5d221af838ad43a2163374aecacf929 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:36 -0300
+Subject: [PATCH 150/203] mtd: nand: pxa3xx: Add a read/write buffers markers
+
+In preparation to support multiple (aka chunked, aka splitted)
+page I/O, this commit adds 'data_buff_pos' and 'oob_buff_pos' fields
+to keep track of where the next read (or write) should be done.
+
+This will allow multiple calls to handle_data_pio() to continue
+the read (or write) operation.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 40 +++++++++++++++++++++++++++++-----------
+ 1 file changed, 29 insertions(+), 11 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -176,6 +176,8 @@ struct pxa3xx_nand_info {
+       unsigned int            buf_start;
+       unsigned int            buf_count;
+       unsigned int            buf_size;
++      unsigned int            data_buff_pos;
++      unsigned int            oob_buff_pos;
+       /* DMA information */
+       int                     drcmr_dat;
+@@ -338,11 +340,12 @@ static void pxa3xx_nand_set_timing(struc
+  * spare and ECC configuration.
+  * Only applicable to READ0, READOOB and PAGEPROG commands.
+  */
+-static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
++static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info,
++                              struct mtd_info *mtd)
+ {
+       int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
+-      info->data_size = info->fifo_size;
++      info->data_size = mtd->writesize;
+       if (!oob_enable)
+               return;
+@@ -430,26 +433,39 @@ static void disable_int(struct pxa3xx_na
+ static void handle_data_pio(struct pxa3xx_nand_info *info)
+ {
++      unsigned int do_bytes = min(info->data_size, info->fifo_size);
++
+       switch (info->state) {
+       case STATE_PIO_WRITING:
+-              __raw_writesl(info->mmio_base + NDDB, info->data_buff,
+-                              DIV_ROUND_UP(info->data_size, 4));
++              __raw_writesl(info->mmio_base + NDDB,
++                            info->data_buff + info->data_buff_pos,
++                            DIV_ROUND_UP(do_bytes, 4));
++
+               if (info->oob_size > 0)
+-                      __raw_writesl(info->mmio_base + NDDB, info->oob_buff,
+-                                      DIV_ROUND_UP(info->oob_size, 4));
++                      __raw_writesl(info->mmio_base + NDDB,
++                                    info->oob_buff + info->oob_buff_pos,
++                                    DIV_ROUND_UP(info->oob_size, 4));
+               break;
+       case STATE_PIO_READING:
+-              __raw_readsl(info->mmio_base + NDDB, info->data_buff,
+-                              DIV_ROUND_UP(info->data_size, 4));
++              __raw_readsl(info->mmio_base + NDDB,
++                           info->data_buff + info->data_buff_pos,
++                           DIV_ROUND_UP(do_bytes, 4));
++
+               if (info->oob_size > 0)
+-                      __raw_readsl(info->mmio_base + NDDB, info->oob_buff,
+-                                      DIV_ROUND_UP(info->oob_size, 4));
++                      __raw_readsl(info->mmio_base + NDDB,
++                                   info->oob_buff + info->oob_buff_pos,
++                                   DIV_ROUND_UP(info->oob_size, 4));
+               break;
+       default:
+               dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
+                               info->state);
+               BUG();
+       }
++
++      /* Update buffer pointers for multi-page read/write */
++      info->data_buff_pos += do_bytes;
++      info->oob_buff_pos += info->oob_size;
++      info->data_size -= do_bytes;
+ }
+ #ifdef ARCH_HAS_DMA
+@@ -616,6 +632,8 @@ static void prepare_start_command(struct
+       info->buf_start         = 0;
+       info->buf_count         = 0;
+       info->oob_size          = 0;
++      info->data_buff_pos     = 0;
++      info->oob_buff_pos      = 0;
+       info->use_ecc           = 0;
+       info->use_spare         = 1;
+       info->retcode           = ERR_NONE;
+@@ -626,7 +644,7 @@ static void prepare_start_command(struct
+       case NAND_CMD_PAGEPROG:
+               info->use_ecc = 1;
+       case NAND_CMD_READOOB:
+-              pxa3xx_set_datasize(info);
++              pxa3xx_set_datasize(info, mtd);
+               break;
+       case NAND_CMD_PARAM:
+               info->use_spare = 0;
diff --git a/target/linux/mvebu/patches-3.10/0151-mtd-nand-pxa3xx-Introduce-multiple-page-I-O-support.patch b/target/linux/mvebu/patches-3.10/0151-mtd-nand-pxa3xx-Introduce-multiple-page-I-O-support.patch
new file mode 100644 (file)
index 0000000..f8e3c87
--- /dev/null
@@ -0,0 +1,325 @@
+From cfd1799f9ec5c9820f371e1fcf2f3c458bd24ebb Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:37 -0300
+Subject: [PATCH 151/203] mtd: nand: pxa3xx: Introduce multiple page I/O
+ support
+
+As preparation work to fully support large pages, this commit adds
+the initial infrastructure to support splitted (aka chunked) I/O
+operation. This commit adds support for read, and follow-up patches
+will add write support.
+
+When a read (aka READ0) command is issued, the driver loops issuing
+the same command until all the requested data is transfered, changing
+the 'extended' command field as needed.
+
+For instance, if the driver is required to read a 4 KiB page, using a
+chunk size of 2 KiB, the transaction is splitted in:
+1. Monolithic read, first 2 KiB page chunk is read
+2. Last naked read, second and last 2KiB page chunk is read
+
+If ECC is enabled it is calculated on each chunk transfered and added
+at a controller-fixed location after the data chunk that must be
+spare area.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 182 ++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 172 insertions(+), 10 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -103,6 +103,8 @@
+ #define NDCB0_ST_ROW_EN         (0x1 << 26)
+ #define NDCB0_AUTO_RS         (0x1 << 25)
+ #define NDCB0_CSEL            (0x1 << 24)
++#define NDCB0_EXT_CMD_TYPE_MASK       (0x7 << 29)
++#define NDCB0_EXT_CMD_TYPE(x) (((x) << 29) & NDCB0_EXT_CMD_TYPE_MASK)
+ #define NDCB0_CMD_TYPE_MASK   (0x7 << 21)
+ #define NDCB0_CMD_TYPE(x)     (((x) << 21) & NDCB0_CMD_TYPE_MASK)
+ #define NDCB0_NC              (0x1 << 20)
+@@ -113,6 +115,14 @@
+ #define NDCB0_CMD1_MASK               (0xff)
+ #define NDCB0_ADDR_CYC_SHIFT  (16)
++#define EXT_CMD_TYPE_DISPATCH 6 /* Command dispatch */
++#define EXT_CMD_TYPE_NAKED_RW 5 /* Naked read or Naked write */
++#define EXT_CMD_TYPE_READ     4 /* Read */
++#define EXT_CMD_TYPE_DISP_WR  4 /* Command dispatch with write */
++#define EXT_CMD_TYPE_FINAL    3 /* Final command */
++#define EXT_CMD_TYPE_LAST_RW  1 /* Last naked read/write */
++#define EXT_CMD_TYPE_MONO     0 /* Monolithic read/write */
++
+ /* macros for registers read/write */
+ #define nand_writel(info, off, val)   \
+       __raw_writel((val), (info)->mmio_base + (off))
+@@ -206,8 +216,8 @@ struct pxa3xx_nand_info {
+       int                     use_spare;      /* use spare ? */
+       int                     need_wait;
+-      unsigned int            fifo_size;      /* max. data size in the FIFO */
+       unsigned int            data_size;      /* data to be read from FIFO */
++      unsigned int            chunk_size;     /* split commands chunk size */
+       unsigned int            oob_size;
+       unsigned int            spare_size;
+       unsigned int            ecc_size;
+@@ -271,6 +281,31 @@ static struct nand_bbt_descr bbt_mirror_
+       .pattern = bbt_mirror_pattern
+ };
++static struct nand_ecclayout ecc_layout_4KB_bch4bit = {
++      .eccbytes = 64,
++      .eccpos = {
++              32,  33,  34,  35,  36,  37,  38,  39,
++              40,  41,  42,  43,  44,  45,  46,  47,
++              48,  49,  50,  51,  52,  53,  54,  55,
++              56,  57,  58,  59,  60,  61,  62,  63,
++              96,  97,  98,  99,  100, 101, 102, 103,
++              104, 105, 106, 107, 108, 109, 110, 111,
++              112, 113, 114, 115, 116, 117, 118, 119,
++              120, 121, 122, 123, 124, 125, 126, 127},
++      /* Bootrom looks in bytes 0 & 5 for bad blocks */
++      .oobfree = { {6, 26}, { 64, 32} }
++};
++
++static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
++      .eccbytes = 128,
++      .eccpos = {
++              32,  33,  34,  35,  36,  37,  38,  39,
++              40,  41,  42,  43,  44,  45,  46,  47,
++              48,  49,  50,  51,  52,  53,  54,  55,
++              56,  57,  58,  59,  60,  61,  62,  63},
++      .oobfree = { }
++};
++
+ /* Define a default flash type setting serve as flash detecting only */
+ #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
+@@ -433,7 +468,7 @@ static void disable_int(struct pxa3xx_na
+ static void handle_data_pio(struct pxa3xx_nand_info *info)
+ {
+-      unsigned int do_bytes = min(info->data_size, info->fifo_size);
++      unsigned int do_bytes = min(info->data_size, info->chunk_size);
+       switch (info->state) {
+       case STATE_PIO_WRITING:
+@@ -670,7 +705,7 @@ static void prepare_start_command(struct
+ }
+ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
+-              uint16_t column, int page_addr)
++              int ext_cmd_type, uint16_t column, int page_addr)
+ {
+       int addr_cycle, exec_cmd;
+       struct pxa3xx_nand_host *host;
+@@ -703,9 +738,20 @@ static int prepare_set_command(struct px
+               if (command == NAND_CMD_READOOB)
+                       info->buf_start += mtd->writesize;
+-              /* Second command setting for large pages */
+-              if (mtd->writesize >= PAGE_CHUNK_SIZE)
++              /*
++               * Multiple page read needs an 'extended command type' field,
++               * which is either naked-read or last-read according to the
++               * state.
++               */
++              if (mtd->writesize == PAGE_CHUNK_SIZE) {
+                       info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8);
++              } else if (mtd->writesize > PAGE_CHUNK_SIZE) {
++                      info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8)
++                                      | NDCB0_LEN_OVRD
++                                      | NDCB0_EXT_CMD_TYPE(ext_cmd_type);
++                      info->ndcb3 = info->chunk_size +
++                                    info->oob_size;
++              }
+               set_command_address(info, mtd->writesize, column, page_addr);
+               break;
+@@ -821,7 +867,8 @@ static void pxa3xx_nand_cmdfunc(struct m
+       prepare_start_command(info, command);
+       info->state = STATE_PREPARED;
+-      exec_cmd = prepare_set_command(info, command, column, page_addr);
++      exec_cmd = prepare_set_command(info, command, 0, column, page_addr);
++
+       if (exec_cmd) {
+               init_completion(&info->cmd_complete);
+               init_completion(&info->dev_ready);
+@@ -839,6 +886,93 @@ static void pxa3xx_nand_cmdfunc(struct m
+       info->state = STATE_IDLE;
+ }
++static void armada370_nand_cmdfunc(struct mtd_info *mtd,
++                                 const unsigned command,
++                                 int column, int page_addr)
++{
++      struct pxa3xx_nand_host *host = mtd->priv;
++      struct pxa3xx_nand_info *info = host->info_data;
++      int ret, exec_cmd, ext_cmd_type;
++
++      /*
++       * if this is a x16 device then convert the input
++       * "byte" address into a "word" address appropriate
++       * for indexing a word-oriented device
++       */
++      if (info->reg_ndcr & NDCR_DWIDTH_M)
++              column /= 2;
++
++      /*
++       * There may be different NAND chip hooked to
++       * different chip select, so check whether
++       * chip select has been changed, if yes, reset the timing
++       */
++      if (info->cs != host->cs) {
++              info->cs = host->cs;
++              nand_writel(info, NDTR0CS0, info->ndtr0cs0);
++              nand_writel(info, NDTR1CS0, info->ndtr1cs0);
++      }
++
++      /* Select the extended command for the first command */
++      switch (command) {
++      case NAND_CMD_READ0:
++      case NAND_CMD_READOOB:
++              ext_cmd_type = EXT_CMD_TYPE_MONO;
++              break;
++      default:
++              ext_cmd_type = 0;
++      }
++
++      prepare_start_command(info, command);
++
++      /*
++       * Prepare the "is ready" completion before starting a command
++       * transaction sequence. If the command is not executed the
++       * completion will be completed, see below.
++       *
++       * We can do that inside the loop because the command variable
++       * is invariant and thus so is the exec_cmd.
++       */
++      info->need_wait = 1;
++      init_completion(&info->dev_ready);
++      do {
++              info->state = STATE_PREPARED;
++              exec_cmd = prepare_set_command(info, command, ext_cmd_type,
++                                             column, page_addr);
++              if (!exec_cmd) {
++                      info->need_wait = 0;
++                      complete(&info->dev_ready);
++                      break;
++              }
++
++              init_completion(&info->cmd_complete);
++              pxa3xx_nand_start(info);
++
++              ret = wait_for_completion_timeout(&info->cmd_complete,
++                              CHIP_DELAY_TIMEOUT);
++              if (!ret) {
++                      dev_err(&info->pdev->dev, "Wait time out!!!\n");
++                      /* Stop State Machine for next command cycle */
++                      pxa3xx_nand_stop(info);
++                      break;
++              }
++
++              /* Check if the sequence is complete */
++              if (info->data_size == 0)
++                      break;
++
++              if (command == NAND_CMD_READ0 || command == NAND_CMD_READOOB) {
++                      /* Last read: issue a 'last naked read' */
++                      if (info->data_size == info->chunk_size)
++                              ext_cmd_type = EXT_CMD_TYPE_LAST_RW;
++                      else
++                              ext_cmd_type = EXT_CMD_TYPE_NAKED_RW;
++              }
++      } while (1);
++
++      info->state = STATE_IDLE;
++}
++
+ static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
+               struct nand_chip *chip, const uint8_t *buf, int oob_required)
+ {
+@@ -1019,13 +1153,14 @@ static int pxa3xx_nand_detect_config(str
+       if (ndcr & NDCR_PAGE_SZ) {
+               /* Controller's FIFO size */
+-              info->fifo_size = 2048;
++              info->chunk_size = 2048;
+               host->read_id_bytes = 4;
+       } else {
+-              info->fifo_size = 512;
++              info->chunk_size = 512;
+               host->read_id_bytes = 2;
+       }
++      /* Set an initial chunk size */
+       info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
+       info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
+       info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
+@@ -1129,6 +1264,7 @@ static int pxa_ecc_init(struct pxa3xx_na
+        * is used with non-ONFI compliant devices.
+        */
+       if (page_size == 2048) {
++              info->chunk_size = 2048;
+               info->spare_size = 40;
+               info->ecc_size = 24;
+               ecc->mode = NAND_ECC_HW;
+@@ -1137,6 +1273,7 @@ static int pxa_ecc_init(struct pxa3xx_na
+               return 1;
+       } else if (page_size == 512) {
++              info->chunk_size = 512;
+               info->spare_size = 8;
+               info->ecc_size = 8;
+               ecc->mode = NAND_ECC_HW;
+@@ -1151,7 +1288,28 @@ static int armada370_ecc_init(struct pxa
+                             struct nand_ecc_ctrl *ecc,
+                             int strength, int page_size)
+ {
+-      /* Unimplemented yet */
++      if (strength == 4 && page_size == 4096) {
++              info->ecc_bch = 1;
++              info->chunk_size = 2048;
++              info->spare_size = 32;
++              info->ecc_size = 32;
++              ecc->mode = NAND_ECC_HW;
++              ecc->size = info->chunk_size;
++              ecc->layout = &ecc_layout_4KB_bch4bit;
++              ecc->strength = 16;
++              return 1;
++
++      } else if (strength == 8 && page_size == 4096) {
++              info->ecc_bch = 1;
++              info->chunk_size = 1024;
++              info->spare_size = 0;
++              info->ecc_size = 32;
++              ecc->mode = NAND_ECC_HW;
++              ecc->size = info->chunk_size;
++              ecc->layout = &ecc_layout_4KB_bch8bit;
++              ecc->strength = 16;
++              return 1;
++      }
+       return 0;
+ }
+@@ -1319,12 +1477,16 @@ static int alloc_nand_resource(struct pl
+               chip->controller        = &info->controller;
+               chip->waitfunc          = pxa3xx_nand_waitfunc;
+               chip->select_chip       = pxa3xx_nand_select_chip;
+-              chip->cmdfunc           = pxa3xx_nand_cmdfunc;
+               chip->read_word         = pxa3xx_nand_read_word;
+               chip->read_byte         = pxa3xx_nand_read_byte;
+               chip->read_buf          = pxa3xx_nand_read_buf;
+               chip->write_buf         = pxa3xx_nand_write_buf;
+               chip->options           |= NAND_NO_SUBPAGE_WRITE;
++
++              if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
++                      chip->cmdfunc = armada370_nand_cmdfunc;
++              else
++                      chip->cmdfunc = pxa3xx_nand_cmdfunc;
+       }
+       spin_lock_init(&chip->controller->lock);
diff --git a/target/linux/mvebu/patches-3.10/0152-mtd-nand-pxa3xx-Add-multiple-chunk-write-support.patch b/target/linux/mvebu/patches-3.10/0152-mtd-nand-pxa3xx-Add-multiple-chunk-write-support.patch
new file mode 100644 (file)
index 0000000..058dc0b
--- /dev/null
@@ -0,0 +1,146 @@
+From db95c66cebb6297595a5a32b369d1033b08775ce Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:38 -0300
+Subject: [PATCH 152/203] mtd: nand: pxa3xx: Add multiple chunk write support
+
+This commit adds write support for large pages (4 KiB, 8 KiB).
+Such support is implemented by issuing a multiple command sequence,
+transfering a set of 2 KiB chunks per transaction.
+
+The splitted command sequence requires to send the SEQIN command
+independently of the PAGEPROG command and therefore it's set as
+an execution command.
+
+Since PAGEPROG enables ECC, each 2 KiB chunk of data is written
+together with ECC code at a controller-fixed location within
+the flash page.
+
+Currently, only devices with a 4 KiB page size has been tested.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 81 +++++++++++++++++++++++++++++++++++++-----
+ 1 file changed, 73 insertions(+), 8 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -760,6 +760,20 @@ static int prepare_set_command(struct px
+               info->buf_start = column;
+               set_command_address(info, mtd->writesize, 0, page_addr);
++
++              /*
++               * Multiple page programming needs to execute the initial
++               * SEQIN command that sets the page address.
++               */
++              if (mtd->writesize > PAGE_CHUNK_SIZE) {
++                      info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
++                              | NDCB0_EXT_CMD_TYPE(ext_cmd_type)
++                              | addr_cycle
++                              | command;
++                      /* No data transfer in this case */
++                      info->data_size = 0;
++                      exec_cmd = 1;
++              }
+               break;
+       case NAND_CMD_PAGEPROG:
+@@ -769,13 +783,40 @@ static int prepare_set_command(struct px
+                       break;
+               }
+-              info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+-                              | NDCB0_AUTO_RS
+-                              | NDCB0_ST_ROW_EN
+-                              | NDCB0_DBC
+-                              | (NAND_CMD_PAGEPROG << 8)
+-                              | NAND_CMD_SEQIN
+-                              | addr_cycle;
++              /* Second command setting for large pages */
++              if (mtd->writesize > PAGE_CHUNK_SIZE) {
++                      /*
++                       * Multiple page write uses the 'extended command'
++                       * field. This can be used to issue a command dispatch
++                       * or a naked-write depending on the current stage.
++                       */
++                      info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
++                                      | NDCB0_LEN_OVRD
++                                      | NDCB0_EXT_CMD_TYPE(ext_cmd_type);
++                      info->ndcb3 = info->chunk_size +
++                                    info->oob_size;
++
++                      /*
++                       * This is the command dispatch that completes a chunked
++                       * page program operation.
++                       */
++                      if (info->data_size == 0) {
++                              info->ndcb0 = NDCB0_CMD_TYPE(0x1)
++                                      | NDCB0_EXT_CMD_TYPE(ext_cmd_type)
++                                      | command;
++                              info->ndcb1 = 0;
++                              info->ndcb2 = 0;
++                              info->ndcb3 = 0;
++                      }
++              } else {
++                      info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
++                                      | NDCB0_AUTO_RS
++                                      | NDCB0_ST_ROW_EN
++                                      | NDCB0_DBC
++                                      | (NAND_CMD_PAGEPROG << 8)
++                                      | NAND_CMD_SEQIN
++                                      | addr_cycle;
++              }
+               break;
+       case NAND_CMD_PARAM:
+@@ -919,8 +960,15 @@ static void armada370_nand_cmdfunc(struc
+       case NAND_CMD_READOOB:
+               ext_cmd_type = EXT_CMD_TYPE_MONO;
+               break;
++      case NAND_CMD_SEQIN:
++              ext_cmd_type = EXT_CMD_TYPE_DISPATCH;
++              break;
++      case NAND_CMD_PAGEPROG:
++              ext_cmd_type = EXT_CMD_TYPE_NAKED_RW;
++              break;
+       default:
+               ext_cmd_type = 0;
++              break;
+       }
+       prepare_start_command(info, command);
+@@ -958,7 +1006,16 @@ static void armada370_nand_cmdfunc(struc
+               }
+               /* Check if the sequence is complete */
+-              if (info->data_size == 0)
++              if (info->data_size == 0 && command != NAND_CMD_PAGEPROG)
++                      break;
++
++              /*
++               * After a splitted program command sequence has issued
++               * the command dispatch, the command sequence is complete.
++               */
++              if (info->data_size == 0 &&
++                  command == NAND_CMD_PAGEPROG &&
++                  ext_cmd_type == EXT_CMD_TYPE_DISPATCH)
+                       break;
+               if (command == NAND_CMD_READ0 || command == NAND_CMD_READOOB) {
+@@ -967,6 +1024,14 @@ static void armada370_nand_cmdfunc(struc
+                               ext_cmd_type = EXT_CMD_TYPE_LAST_RW;
+                       else
+                               ext_cmd_type = EXT_CMD_TYPE_NAKED_RW;
++
++              /*
++               * If a splitted program command has no more data to transfer,
++               * the command dispatch must be issued to complete.
++               */
++              } else if (command == NAND_CMD_PAGEPROG &&
++                         info->data_size == 0) {
++                              ext_cmd_type = EXT_CMD_TYPE_DISPATCH;
+               }
+       } while (1);
diff --git a/target/linux/mvebu/patches-3.10/0153-mtd-nand-pxa3xx-Add-ECC-BCH-correctable-errors-detec.patch b/target/linux/mvebu/patches-3.10/0153-mtd-nand-pxa3xx-Add-ECC-BCH-correctable-errors-detec.patch
new file mode 100644 (file)
index 0000000..fa68e5b
--- /dev/null
@@ -0,0 +1,144 @@
+From 26d82e0081aa6f0c7db5e4bb5b154b7c528cb8d6 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 14 Nov 2013 18:25:39 -0300
+Subject: [PATCH 153/203] mtd: nand: pxa3xx: Add ECC BCH correctable errors
+ detection
+
+This commit extends the ECC correctable error detection to include
+ECC BCH errors. The number of BCH correctable errors can be any up to 16,
+and the actual value is exposed in the NDSR register.
+
+Therefore, we change some symbol names to refer to correctable or
+uncorrectable (instead of single-bit or double-bit as it was in the
+Hamming case) and while at it, cleanup the detection code slightly.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 57 ++++++++++++++++++++++++++----------------
+ 1 file changed, 35 insertions(+), 22 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -85,6 +85,9 @@
+ #define NDCR_INT_MASK           (0xFFF)
+ #define NDSR_MASK             (0xfff)
++#define NDSR_ERR_CNT_OFF      (16)
++#define NDSR_ERR_CNT_MASK       (0x1f)
++#define NDSR_ERR_CNT(sr)      ((sr >> NDSR_ERR_CNT_OFF) & NDSR_ERR_CNT_MASK)
+ #define NDSR_RDY                (0x1 << 12)
+ #define NDSR_FLASH_RDY          (0x1 << 11)
+ #define NDSR_CS0_PAGED                (0x1 << 10)
+@@ -93,8 +96,8 @@
+ #define NDSR_CS1_CMDD         (0x1 << 7)
+ #define NDSR_CS0_BBD          (0x1 << 6)
+ #define NDSR_CS1_BBD          (0x1 << 5)
+-#define NDSR_DBERR            (0x1 << 4)
+-#define NDSR_SBERR            (0x1 << 3)
++#define NDSR_UNCORERR         (0x1 << 4)
++#define NDSR_CORERR           (0x1 << 3)
+ #define NDSR_WRDREQ           (0x1 << 2)
+ #define NDSR_RDDREQ           (0x1 << 1)
+ #define NDSR_WRCMDREQ         (0x1)
+@@ -135,9 +138,9 @@ enum {
+       ERR_NONE        = 0,
+       ERR_DMABUSERR   = -1,
+       ERR_SENDCMD     = -2,
+-      ERR_DBERR       = -3,
++      ERR_UNCORERR    = -3,
+       ERR_BBERR       = -4,
+-      ERR_SBERR       = -5,
++      ERR_CORERR      = -5,
+ };
+ enum {
+@@ -221,6 +224,8 @@ struct pxa3xx_nand_info {
+       unsigned int            oob_size;
+       unsigned int            spare_size;
+       unsigned int            ecc_size;
++      unsigned int            ecc_err_cnt;
++      unsigned int            max_bitflips;
+       int                     retcode;
+       /* cached register value */
+@@ -571,10 +576,25 @@ static irqreturn_t pxa3xx_nand_irq(int i
+       status = nand_readl(info, NDSR);
+-      if (status & NDSR_DBERR)
+-              info->retcode = ERR_DBERR;
+-      if (status & NDSR_SBERR)
+-              info->retcode = ERR_SBERR;
++      if (status & NDSR_UNCORERR)
++              info->retcode = ERR_UNCORERR;
++      if (status & NDSR_CORERR) {
++              info->retcode = ERR_CORERR;
++              if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 &&
++                  info->ecc_bch)
++                      info->ecc_err_cnt = NDSR_ERR_CNT(status);
++              else
++                      info->ecc_err_cnt = 1;
++
++              /*
++               * Each chunk composing a page is corrected independently,
++               * and we need to store maximum number of corrected bitflips
++               * to return it to the MTD layer in ecc.read_page().
++               */
++              info->max_bitflips = max_t(unsigned int,
++                                         info->max_bitflips,
++                                         info->ecc_err_cnt);
++      }
+       if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {
+               /* whether use dma to transfer data */
+               if (info->use_dma) {
+@@ -672,6 +692,7 @@ static void prepare_start_command(struct
+       info->use_ecc           = 0;
+       info->use_spare         = 1;
+       info->retcode           = ERR_NONE;
++      info->ecc_err_cnt       = 0;
+       info->ndcb3             = 0;
+       switch (command) {
+@@ -1053,26 +1074,18 @@ static int pxa3xx_nand_read_page_hwecc(s
+ {
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
+-      int max_bitflips = 0;
+       chip->read_buf(mtd, buf, mtd->writesize);
+       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+-      if (info->retcode == ERR_SBERR) {
+-              switch (info->use_ecc) {
+-              case 1:
+-                      max_bitflips = 1;
+-                      mtd->ecc_stats.corrected++;
+-                      break;
+-              case 0:
+-              default:
+-                      break;
+-              }
+-      } else if (info->retcode == ERR_DBERR) {
++      if (info->retcode == ERR_CORERR && info->use_ecc) {
++              mtd->ecc_stats.corrected += info->ecc_err_cnt;
++
++      } else if (info->retcode == ERR_UNCORERR) {
+               /*
+                * for blank page (all 0xff), HW will calculate its ECC as
+                * 0, which is different from the ECC information within
+-               * OOB, ignore such double bit errors
++               * OOB, ignore such uncorrectable errors
+                */
+               if (is_buf_blank(buf, mtd->writesize))
+                       info->retcode = ERR_NONE;
+@@ -1080,7 +1093,7 @@ static int pxa3xx_nand_read_page_hwecc(s
+                       mtd->ecc_stats.failed++;
+       }
+-      return max_bitflips;
++      return info->max_bitflips;
+ }
+ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
diff --git a/target/linux/mvebu/patches-3.10/0154-mtd-nand-pxa3xx-make-ECC-configuration-checks-more-e.patch b/target/linux/mvebu/patches-3.10/0154-mtd-nand-pxa3xx-make-ECC-configuration-checks-more-e.patch
new file mode 100644 (file)
index 0000000..8d9d21a
--- /dev/null
@@ -0,0 +1,67 @@
+From c312e183e96bed3b727888673d4b6b54b8e6283e Mon Sep 17 00:00:00 2001
+From: Brian Norris <computersforpeace@gmail.com>
+Date: Thu, 14 Nov 2013 14:41:32 -0800
+Subject: [PATCH 154/203] mtd: nand: pxa3xx: make ECC configuration checks more
+ explicit
+
+The Armada BCH configuration in this driver uses one of the two
+following ECC schemes:
+
+ 16-bit correction per 2048 bytes
+ 16-bit correction per 1024 bytes
+
+These are sufficient for mapping to the 4-bit per 512-bytes and 8-bit
+per 512-bytes (respectively) minimum correctability requirements of many
+common NAND.
+
+The current code only checks for the required strength (4-bit or 8-bit)
+without checking the ECC step size that is associated with that strength
+(and simply assumes it is 512). While that is often a safe assumption to
+make, let's make it explicit, since we have that information.
+
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+Acked-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -1364,9 +1364,13 @@ static int pxa_ecc_init(struct pxa3xx_na
+ static int armada370_ecc_init(struct pxa3xx_nand_info *info,
+                             struct nand_ecc_ctrl *ecc,
+-                            int strength, int page_size)
++                            int strength, int ecc_stepsize, int page_size)
+ {
+-      if (strength == 4 && page_size == 4096) {
++      /*
++       * Required ECC: 4-bit correction per 512 bytes
++       * Select: 16-bit correction per 2048 bytes
++       */
++      if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) {
+               info->ecc_bch = 1;
+               info->chunk_size = 2048;
+               info->spare_size = 32;
+@@ -1377,7 +1381,11 @@ static int armada370_ecc_init(struct pxa
+               ecc->strength = 16;
+               return 1;
+-      } else if (strength == 8 && page_size == 4096) {
++      /*
++       * Required ECC: 8-bit correction per 512 bytes
++       * Select: 16-bit correction per 1024 bytes
++       */
++      } else if (strength == 8 && ecc_stepsize == 512 && page_size == 4096) {
+               info->ecc_bch = 1;
+               info->chunk_size = 1024;
+               info->spare_size = 0;
+@@ -1485,6 +1493,7 @@ KEEP_CONFIG:
+       if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+               ret = armada370_ecc_init(info, &chip->ecc,
+                                  chip->ecc_strength_ds,
++                                 chip->ecc_step_ds,
+                                  mtd->writesize);
+       else
+               ret = pxa_ecc_init(info, &chip->ecc,
diff --git a/target/linux/mvebu/patches-3.10/0155-mtd-nand-pxa3xx-Use-info-use_dma-to-release-DMA-reso.patch b/target/linux/mvebu/patches-3.10/0155-mtd-nand-pxa3xx-Use-info-use_dma-to-release-DMA-reso.patch
new file mode 100644 (file)
index 0000000..d86cc9b
--- /dev/null
@@ -0,0 +1,29 @@
+From 4c6bade4cf80d77decc5ea89fbaadff8b008f5e9 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Mon, 25 Nov 2013 12:35:28 -0300
+Subject: [PATCH 155/203] mtd: nand: pxa3xx: Use info->use_dma to release DMA
+ resources
+
+After the driver allocates all DMA resources, it sets "info->use_dma".
+Therefore, we need to check that variable to decide which resources
+needs to be freed, instead of the global use_dma variable.
+
+Without this change, when the device probe fails, the driver will try
+to release unallocated DMA resources, with nasty results.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -1288,7 +1288,7 @@ static int pxa3xx_nand_init_buff(struct
+ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
+ {
+       struct platform_device *pdev = info->pdev;
+-      if (use_dma) {
++      if (info->use_dma) {
+               pxa_free_dma(info->data_dma_ch);
+               dma_free_coherent(&pdev->dev, info->buf_size,
+                                 info->data_buff, info->data_buff_phys);
diff --git a/target/linux/mvebu/patches-3.10/0156-mtd-nand-pxa3xx-Use-extended-cmdfunc-only-if-needed.patch b/target/linux/mvebu/patches-3.10/0156-mtd-nand-pxa3xx-Use-extended-cmdfunc-only-if-needed.patch
new file mode 100644 (file)
index 0000000..7b14da8
--- /dev/null
@@ -0,0 +1,89 @@
+From a701d8e1c4c1e31a208dae616ed9067ba4e90191 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Mon, 25 Nov 2013 11:02:51 -0300
+Subject: [PATCH 156/203] mtd: nand: pxa3xx: Use extended cmdfunc() only if
+ needed
+
+Currently, we have two different cmdfunc's implementations:
+one for PXA3xx SoC variant and one for Armada 370/XP SoC variant.
+
+The former is the legacy one, typically constrained to devices
+with page sizes smaller or equal to the controller's FIFO buffer.
+On the other side, the latter _only_ supports the so-called extended
+command semantics, which allow to handle devices with larger
+page sizes (4 KiB, 8 KiB, ...).
+
+This means we currently don't support devices with smaller pages on the
+A370/XP SoC. Fix it by first renaming the cmdfuncs variants, and then
+make the choice based on device page size (and SoC variant), rather than
+SoC variant alone.
+
+While at it, add a check for page size, to make sure we don't allow larger
+pages sizes on the PXA3xx variant.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 31 +++++++++++++++++++++----------
+ 1 file changed, 21 insertions(+), 10 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -900,8 +900,8 @@ static int prepare_set_command(struct px
+       return exec_cmd;
+ }
+-static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
+-                              int column, int page_addr)
++static void nand_cmdfunc(struct mtd_info *mtd, unsigned command,
++                       int column, int page_addr)
+ {
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
+@@ -948,9 +948,9 @@ static void pxa3xx_nand_cmdfunc(struct m
+       info->state = STATE_IDLE;
+ }
+-static void armada370_nand_cmdfunc(struct mtd_info *mtd,
+-                                 const unsigned command,
+-                                 int column, int page_addr)
++static void nand_cmdfunc_extended(struct mtd_info *mtd,
++                                const unsigned command,
++                                int column, int page_addr)
+ {
+       struct pxa3xx_nand_host *host = mtd->priv;
+       struct pxa3xx_nand_info *info = host->info_data;
+@@ -1490,6 +1490,21 @@ KEEP_CONFIG:
+               chip->bbt_md = &bbt_mirror_descr;
+       }
++      /*
++       * If the page size is bigger than the FIFO size, let's check
++       * we are given the right variant and then switch to the extended
++       * (aka splitted) command handling,
++       */
++      if (mtd->writesize > PAGE_CHUNK_SIZE) {
++              if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) {
++                      chip->cmdfunc = nand_cmdfunc_extended;
++              } else {
++                      dev_err(&info->pdev->dev,
++                              "unsupported page size on this variant\n");
++                      return -ENODEV;
++              }
++      }
++
+       if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+               ret = armada370_ecc_init(info, &chip->ecc,
+                                  chip->ecc_strength_ds,
+@@ -1569,11 +1584,7 @@ static int alloc_nand_resource(struct pl
+               chip->read_buf          = pxa3xx_nand_read_buf;
+               chip->write_buf         = pxa3xx_nand_write_buf;
+               chip->options           |= NAND_NO_SUBPAGE_WRITE;
+-
+-              if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+-                      chip->cmdfunc = armada370_nand_cmdfunc;
+-              else
+-                      chip->cmdfunc = pxa3xx_nand_cmdfunc;
++              chip->cmdfunc           = nand_cmdfunc;
+       }
+       spin_lock_init(&chip->controller->lock);
diff --git a/target/linux/mvebu/patches-3.10/0157-mtd-nand-pxa3xx-Consolidate-ECC-initialization.patch b/target/linux/mvebu/patches-3.10/0157-mtd-nand-pxa3xx-Consolidate-ECC-initialization.patch
new file mode 100644 (file)
index 0000000..28ec7d8
--- /dev/null
@@ -0,0 +1,100 @@
+From 70c36de37f357f38b5a56292534133d75e7d8870 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Mon, 25 Nov 2013 12:36:18 -0300
+Subject: [PATCH 157/203] mtd: nand: pxa3xx: Consolidate ECC initialization
+
+In order to avoid code duplication, let's consolidate the ECC setting
+for all SoC variants. Such decision is based on page size and ECC
+strength requirements.
+
+Also, provide a default value for the case where such ECC information
+is not provided (non-ONFI devices).
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 40 ++++++++++++++++------------------------
+ 1 file changed, 16 insertions(+), 24 deletions(-)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -1335,13 +1335,9 @@ static int pxa3xx_nand_sensing(struct px
+ static int pxa_ecc_init(struct pxa3xx_nand_info *info,
+                       struct nand_ecc_ctrl *ecc,
+-                      int strength, int page_size)
++                      int strength, int ecc_stepsize, int page_size)
+ {
+-      /*
+-       * We don't use strength here as the PXA variant
+-       * is used with non-ONFI compliant devices.
+-       */
+-      if (page_size == 2048) {
++      if (strength == 1 && ecc_stepsize == 512 && page_size == 2048) {
+               info->chunk_size = 2048;
+               info->spare_size = 40;
+               info->ecc_size = 24;
+@@ -1350,7 +1346,7 @@ static int pxa_ecc_init(struct pxa3xx_na
+               ecc->strength = 1;
+               return 1;
+-      } else if (page_size == 512) {
++      } else if (strength == 1 && ecc_stepsize == 512 && page_size == 512) {
+               info->chunk_size = 512;
+               info->spare_size = 8;
+               info->ecc_size = 8;
+@@ -1358,19 +1354,12 @@ static int pxa_ecc_init(struct pxa3xx_na
+               ecc->size = 512;
+               ecc->strength = 1;
+               return 1;
+-      }
+-      return 0;
+-}
+-static int armada370_ecc_init(struct pxa3xx_nand_info *info,
+-                            struct nand_ecc_ctrl *ecc,
+-                            int strength, int ecc_stepsize, int page_size)
+-{
+       /*
+        * Required ECC: 4-bit correction per 512 bytes
+        * Select: 16-bit correction per 2048 bytes
+        */
+-      if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) {
++      } else if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) {
+               info->ecc_bch = 1;
+               info->chunk_size = 2048;
+               info->spare_size = 32;
+@@ -1411,6 +1400,7 @@ static int pxa3xx_nand_scan(struct mtd_i
+       uint32_t id = -1;
+       uint64_t chipsize;
+       int i, ret, num;
++      uint16_t ecc_strength, ecc_step;
+       if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
+               goto KEEP_CONFIG;
+@@ -1505,15 +1495,17 @@ KEEP_CONFIG:
+               }
+       }
+-      if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
+-              ret = armada370_ecc_init(info, &chip->ecc,
+-                                 chip->ecc_strength_ds,
+-                                 chip->ecc_step_ds,
+-                                 mtd->writesize);
+-      else
+-              ret = pxa_ecc_init(info, &chip->ecc,
+-                                 chip->ecc_strength_ds,
+-                                 mtd->writesize);
++      ecc_strength = chip->ecc_strength_ds;
++      ecc_step = chip->ecc_step_ds;
++
++      /* Set default ECC strength requirements on non-ONFI devices */
++      if (ecc_strength < 1 && ecc_step < 1) {
++              ecc_strength = 1;
++              ecc_step = 512;
++      }
++
++      ret = pxa_ecc_init(info, &chip->ecc, ecc_strength,
++                         ecc_step, mtd->writesize);
+       if (!ret) {
+               dev_err(&info->pdev->dev,
+                       "ECC strength %d at page size %d is not supported\n",
diff --git a/target/linux/mvebu/patches-3.10/0158-mtd-nand-Allow-to-build-pxa3xx_nand-on-Orion-platfor.patch b/target/linux/mvebu/patches-3.10/0158-mtd-nand-Allow-to-build-pxa3xx_nand-on-Orion-platfor.patch
new file mode 100644 (file)
index 0000000..6ac5a67
--- /dev/null
@@ -0,0 +1,29 @@
+From 933f5de151614aee0f7b1f664f86b04f3773a075 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Mon, 12 Aug 2013 14:14:59 -0300
+Subject: [PATCH 158/203] mtd: nand: Allow to build pxa3xx_nand on Orion
+ platforms
+
+The Armada 370 and Armada XP SoC families, selected by PLAT_ORION,
+have a Nand Flash Controller (NFC) IP very similar to the one present
+in PXA platforms. Therefore, we want to build this driver on PLAT_ORION.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Tested-by: Daniel Mack <zonque@gmail.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+---
+ drivers/mtd/nand/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/mtd/nand/Kconfig
++++ b/drivers/mtd/nand/Kconfig
+@@ -354,7 +354,7 @@ config MTD_NAND_ATMEL
+ config MTD_NAND_PXA3xx
+       tristate "Support for NAND flash devices on PXA3xx"
+-      depends on PXA3xx || ARCH_MMP
++      depends on PXA3xx || ARCH_MMP || PLAT_ORION
+       help
+         This enables the driver for the NAND flash device found on
+         PXA3xx processors
diff --git a/target/linux/mvebu/patches-3.10/0159-mtd-nand-pxa3xx-Make-config-menu-show-supported-plat.patch b/target/linux/mvebu/patches-3.10/0159-mtd-nand-pxa3xx-Make-config-menu-show-supported-plat.patch
new file mode 100644 (file)
index 0000000..001a9ee
--- /dev/null
@@ -0,0 +1,31 @@
+From b1abf1e5c6a7531a1a93a0ab6c75607dcb0e9947 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 7 Nov 2013 12:17:11 -0300
+Subject: [PATCH 159/203] mtd: nand: pxa3xx: Make config menu show supported
+ platforms
+
+Since we have now support for the NFCv2 controller found on
+Armada 370/XP platforms.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Brian Norris <computersforpeace@gmail.com>
+---
+ drivers/mtd/nand/Kconfig | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/mtd/nand/Kconfig
++++ b/drivers/mtd/nand/Kconfig
+@@ -353,11 +353,11 @@ config MTD_NAND_ATMEL
+         on Atmel AT91 and AVR32 processors.
+ config MTD_NAND_PXA3xx
+-      tristate "Support for NAND flash devices on PXA3xx"
++      tristate "NAND support on PXA3xx and Armada 370/XP"
+       depends on PXA3xx || ARCH_MMP || PLAT_ORION
+       help
+         This enables the driver for the NAND flash device found on
+-        PXA3xx processors
++        PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
+ config MTD_NAND_SLC_LPC32XX
+       tristate "NXP LPC32xx SLC Controller"
diff --git a/target/linux/mvebu/patches-3.10/0160-ARM-mvebu-config-Add-NAND-support.patch b/target/linux/mvebu/patches-3.10/0160-ARM-mvebu-config-Add-NAND-support.patch
new file mode 100644 (file)
index 0000000..4edcaf2
--- /dev/null
@@ -0,0 +1,24 @@
+From a18945a7fd26b83c765b60bcffe306421f7efe80 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Mon, 2 Dec 2013 18:44:40 -0300
+Subject: [PATCH 160/203] ARM: mvebu: config: Add NAND support
+
+Enable the pxa3xx-nand driver, which now supports the NAND controller
+in Armada 370/XP SoC.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ arch/arm/configs/mvebu_defconfig | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm/configs/mvebu_defconfig
++++ b/arch/arm/configs/mvebu_defconfig
+@@ -53,6 +53,8 @@ CONFIG_MTD_CFI_INTELEXT=y
+ CONFIG_MTD_CFI_AMDSTD=y
+ CONFIG_MTD_CFI_STAA=y
+ CONFIG_MTD_PHYSMAP_OF=y
++CONFIG_MTD_NAND=y
++CONFIG_MTD_NAND_PXA3xx=y
+ CONFIG_SERIAL_8250_DW=y
+ CONFIG_GPIOLIB=y
+ CONFIG_GPIO_SYSFS=y
diff --git a/target/linux/mvebu/patches-3.10/0161-net-mvneta-Fix-incorrect-DMA-unmapping-size.patch b/target/linux/mvebu/patches-3.10/0161-net-mvneta-Fix-incorrect-DMA-unmapping-size.patch
new file mode 100644 (file)
index 0000000..f5d600f
--- /dev/null
@@ -0,0 +1,69 @@
+From f834da3962eaee5d72f152e9a066c06ec0d9c2c4 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 5 Dec 2013 13:35:37 -0300
+Subject: [PATCH 161/203] net: mvneta: Fix incorrect DMA unmapping size
+
+The current code unmaps the DMA mapping created for rx skb_buff's by
+using the data_size as the the mapping size. This is wrong since the
+correct size to specify should match the size used to create the mapping.
+
+This commit removes the following DMA_API_DEBUG warning:
+
+------------[ cut here ]------------
+WARNING: at lib/dma-debug.c:887 check_unmap+0x3a8/0x860()
+mvneta d0070000.ethernet: DMA-API: device driver frees DMA memory with different size [device address=0x000000002eb80000] [map size=1600 bytes] [unmap size=66 bytes]
+CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.10.21-01444-ga88ae13-dirty #92
+[<c0013600>] (unwind_backtrace+0x0/0xf8) from [<c0010fb8>] (show_stack+0x10/0x14)
+[<c0010fb8>] (show_stack+0x10/0x14) from [<c001afa0>] (warn_slowpath_common+0x48/0x68)
+[<c001afa0>] (warn_slowpath_common+0x48/0x68) from [<c001b01c>] (warn_slowpath_fmt+0x30/0x40)
+[<c001b01c>] (warn_slowpath_fmt+0x30/0x40) from [<c018d0fc>] (check_unmap+0x3a8/0x860)
+[<c018d0fc>] (check_unmap+0x3a8/0x860) from [<c018d734>] (debug_dma_unmap_page+0x64/0x70)
+[<c018d734>] (debug_dma_unmap_page+0x64/0x70) from [<c0233f78>] (mvneta_rx+0xec/0x468)
+[<c0233f78>] (mvneta_rx+0xec/0x468) from [<c023436c>] (mvneta_poll+0x78/0x16c)
+[<c023436c>] (mvneta_poll+0x78/0x16c) from [<c02db468>] (net_rx_action+0x94/0x160)
+[<c02db468>] (net_rx_action+0x94/0x160) from [<c0021e68>] (__do_softirq+0xe8/0x1d0)
+[<c0021e68>] (__do_softirq+0xe8/0x1d0) from [<c0021ff8>] (do_softirq+0x4c/0x58)
+[<c0021ff8>] (do_softirq+0x4c/0x58) from [<c0022228>] (irq_exit+0x58/0x90)
+[<c0022228>] (irq_exit+0x58/0x90) from [<c000e7c8>] (handle_IRQ+0x3c/0x94)
+[<c000e7c8>] (handle_IRQ+0x3c/0x94) from [<c0008548>] (armada_370_xp_handle_irq+0x4c/0xb4)
+[<c0008548>] (armada_370_xp_handle_irq+0x4c/0xb4) from [<c000dc20>] (__irq_svc+0x40/0x50)
+Exception stack(0xc04f1f70 to 0xc04f1fb8)
+1f60:                                     c1fe46f8 00000000 00001d92 00001d92
+1f80: c04f0000 c04f0000 c04f84a4 c03e081c c05220e7 00000001 c05220e7 c04f0000
+1fa0: 00000000 c04f1fb8 c000eaf8 c004c048 60000113 ffffffff
+[<c000dc20>] (__irq_svc+0x40/0x50) from [<c004c048>] (cpu_startup_entry+0x54/0x128)
+[<c004c048>] (cpu_startup_entry+0x54/0x128) from [<c04c1a14>] (start_kernel+0x29c/0x2f0)
+[<c04c1a14>] (start_kernel+0x29c/0x2f0) from [<00008074>] (0x8074)
+---[ end trace d4955f6acd178110 ]---
+Mapped at:
+ [<c018d600>] debug_dma_map_page+0x4c/0x11c
+ [<c0235d6c>] mvneta_setup_rxqs+0x398/0x598
+ [<c0236084>] mvneta_open+0x40/0x17c
+ [<c02dbbd4>] __dev_open+0x9c/0x100
+ [<c02dbe58>] __dev_change_flags+0x7c/0x134
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ drivers/net/ethernet/marvell/mvneta.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/marvell/mvneta.c
++++ b/drivers/net/ethernet/marvell/mvneta.c
+@@ -1341,7 +1341,7 @@ static void mvneta_rxq_drop_pkts(struct
+               dev_kfree_skb_any(skb);
+               dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
+-                               rx_desc->data_size, DMA_FROM_DEVICE);
++                               MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
+       }
+       if (rx_done)
+@@ -1387,7 +1387,7 @@ static int mvneta_rx(struct mvneta_port
+               }
+               dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
+-                               rx_desc->data_size, DMA_FROM_DEVICE);
++                               MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
+               rx_bytes = rx_desc->data_size -
+                       (ETH_FCS_LEN + MVNETA_MH_SIZE);
diff --git a/target/linux/mvebu/patches-3.10/0162-mtd-nand-pxa3xx-Clear-need_wait-flag-when-starting-a.patch b/target/linux/mvebu/patches-3.10/0162-mtd-nand-pxa3xx-Clear-need_wait-flag-when-starting-a.patch
new file mode 100644 (file)
index 0000000..5665ca1
--- /dev/null
@@ -0,0 +1,50 @@
+From 7efaa8677ffd07d54d0122b5e92f29b74a36ad39 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 19 Dec 2013 06:08:03 -0300
+Subject: [PATCH 162/203] mtd: nand: pxa3xx: Clear need_wait flag when starting
+ a command
+
+Currently the driver assumes all commands will eventually trigger a RnB
+transition, and thus a "device is ready" IRQ.
+
+This assumption means that on every issued command, the dev_ready completion
+handler is init'ed and the need_wait flag is set.
+
+However this is incorrect: some commands (such as NAND_CMD_STATUS) don't
+make the device 'busy' and thus a RnB transition never occurs.
+Given, the NAND core never calls waitfunc() after such commands, this
+is not a problem.
+
+Therefore, it's possible to only clear the need_wait flag on every command
+that is started.
+
+This fixes a current bug that can be reproduced on PXA boards by writing
+blank (all 0xff'ed) to a page:
+
+  1. The kernel issues NAND_CMD_STATUS and sets need_wait=1. The flag
+     won't be cleared for this command since no RnB transition is
+     involved.
+
+  2. NAND_CMD_PAGEPROG is issued but since the data is blank, the driver
+     decides not to execute the command (and no IRQ activity is
+     involved).
+
+  3. The NAND core calls waitfunc() and waits for the dev_ready
+     completion, which will never end since the device _is_ already ready.
+
+Tested-by: Arnaud Ebalard <arno@natisbad.org>
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ drivers/mtd/nand/pxa3xx_nand.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/mtd/nand/pxa3xx_nand.c
++++ b/drivers/mtd/nand/pxa3xx_nand.c
+@@ -694,6 +694,7 @@ static void prepare_start_command(struct
+       info->retcode           = ERR_NONE;
+       info->ecc_err_cnt       = 0;
+       info->ndcb3             = 0;
++      info->need_wait         = 0;
+       switch (command) {
+       case NAND_CMD_READ0:
diff --git a/target/linux/mvebu/patches-3.10/0163-ARM-mvebu-move-ARMADA_XP_MAX_CPUS-to-armada-370-xp.h.patch b/target/linux/mvebu/patches-3.10/0163-ARM-mvebu-move-ARMADA_XP_MAX_CPUS-to-armada-370-xp.h.patch
new file mode 100644 (file)
index 0000000..5f46bc1
--- /dev/null
@@ -0,0 +1,39 @@
+From b340059540cbc90412f3e7159dc57a178e0effd6 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Wed, 4 Dec 2013 14:28:59 +0100
+Subject: [PATCH 163/203] ARM: mvebu: move ARMADA_XP_MAX_CPUS to
+ armada-370-xp.h
+
+The ARMADA_XP_MAX_CPUS definition was in common.h, which as its name
+says, is common to all mvebu SoCs. It is more logical to have this XP
+specific definition in the already existing armada-370-xp.h header
+file.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/mach-mvebu/armada-370-xp.h | 2 ++
+ arch/arm/mach-mvebu/common.h        | 2 --
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm/mach-mvebu/armada-370-xp.h
++++ b/arch/arm/mach-mvebu/armada-370-xp.h
+@@ -18,6 +18,8 @@
+ #ifdef CONFIG_SMP
+ #include <linux/cpumask.h>
++#define ARMADA_XP_MAX_CPUS 4
++
+ void armada_mpic_send_doorbell(const struct cpumask *mask, unsigned int irq);
+ void armada_xp_mpic_smp_cpu_init(void);
+ #endif
+--- a/arch/arm/mach-mvebu/common.h
++++ b/arch/arm/mach-mvebu/common.h
+@@ -15,8 +15,6 @@
+ #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);
diff --git a/target/linux/mvebu/patches-3.10/0164-ARM-mvebu-fix-register-length-for-Armada-XP-PMSU.patch b/target/linux/mvebu/patches-3.10/0164-ARM-mvebu-fix-register-length-for-Armada-XP-PMSU.patch
new file mode 100644 (file)
index 0000000..7b58f61
--- /dev/null
@@ -0,0 +1,34 @@
+From 10208caf7f0ebfb3d6b546aa2ae66e42462551e0 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Wed, 4 Dec 2013 14:37:52 +0100
+Subject: [PATCH 164/203] ARM: mvebu: fix register length for Armada XP PMSU
+
+The per-CPU PMSU registers documented in the datasheet start at
+0x22100 and the last register for CPU3 is at 0x22428. However, the DT
+informations use <0x22100 0x430>, which makes the region end at
+0x22530 and not 0x22430.
+
+Moreover, looking at the datasheet, we can see that the registers for
+CPU0 start at 0x22100, for CPU1 at 0x22200, for CPU2 at 0x22300 and
+for CPU3 at 0x22400. It seems clear that 0x100 bytes of registers have
+been used per CPU.
+
+Therefore, this commit reduces the length of the PMSU per-CPU register
+area from the incorrect 0x430 bytes to a more logical 0x400 bytes.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/boot/dts/armada-xp.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm/boot/dts/armada-xp.dtsi
++++ b/arch/arm/boot/dts/armada-xp.dtsi
+@@ -48,7 +48,7 @@
+                       armada-370-xp-pmsu@22000 {
+                               compatible = "marvell,armada-370-xp-pmsu";
+-                              reg = <0x22100 0x430>, <0x20800 0x20>;
++                              reg = <0x22100 0x400>, <0x20800 0x20>;
+                       };
+                       serial@12200 {
diff --git a/target/linux/mvebu/patches-3.10/0165-ARM-mvebu-make-armada_370_xp_pmsu_init-static.patch b/target/linux/mvebu/patches-3.10/0165-ARM-mvebu-make-armada_370_xp_pmsu_init-static.patch
new file mode 100644 (file)
index 0000000..72465a1
--- /dev/null
@@ -0,0 +1,36 @@
+From 167c442fb9adf4c2e02663a0291c6cfae31bad72 Mon Sep 17 00:00:00 2001
+From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Date: Thu, 5 Dec 2013 10:02:25 +0100
+Subject: [PATCH 165/203] ARM: mvebu: make armada_370_xp_pmsu_init() static
+
+The armada_370_xp_pmsu_init() function is called as an
+early_initcall(). Therefore, there is no need to export this function,
+and we can make it static.
+
+Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+---
+ arch/arm/mach-mvebu/common.h | 1 -
+ arch/arm/mach-mvebu/pmsu.c   | 2 +-
+ 2 files changed, 1 insertion(+), 2 deletions(-)
+
+--- a/arch/arm/mach-mvebu/common.h
++++ b/arch/arm/mach-mvebu/common.h
+@@ -22,7 +22,6 @@ void armada_370_xp_handle_irq(struct pt_
+ void armada_xp_cpu_die(unsigned int cpu);
+ int armada_370_xp_coherency_init(void);
+-int armada_370_xp_pmsu_init(void);
+ void armada_xp_secondary_startup(void);
+ extern struct smp_operations armada_xp_smp_ops;
+ #endif
+--- a/arch/arm/mach-mvebu/pmsu.c
++++ b/arch/arm/mach-mvebu/pmsu.c
+@@ -58,7 +58,7 @@ int armada_xp_boot_cpu(unsigned int cpu_
+ }
+ #endif
+-int __init armada_370_xp_pmsu_init(void)
++static int __init armada_370_xp_pmsu_init(void)
+ {
+       struct device_node *np;
diff --git a/target/linux/mvebu/patches-3.10/0166-clocksource-armada-370-xp-Use-BIT.patch b/target/linux/mvebu/patches-3.10/0166-clocksource-armada-370-xp-Use-BIT.patch
new file mode 100644 (file)
index 0000000..8f07046
--- /dev/null
@@ -0,0 +1,37 @@
+From ea331be867c791bca8200e6d707499845d8dfa87 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 13 Aug 2013 11:43:10 -0300
+Subject: [PATCH 166/203] clocksource: armada-370-xp: Use BIT()
+
+This is a purely cosmetic commit: we replace hardcoded values that
+representing bits by BIT(), which is slightly more readable.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+---
+ drivers/clocksource/time-armada-370-xp.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/clocksource/time-armada-370-xp.c
++++ b/drivers/clocksource/time-armada-370-xp.c
+@@ -35,13 +35,13 @@
+  * Timer block registers.
+  */
+ #define TIMER_CTRL_OFF                0x0000
+-#define  TIMER0_EN             0x0001
+-#define  TIMER0_RELOAD_EN      0x0002
+-#define  TIMER0_25MHZ            0x0800
++#define  TIMER0_EN             BIT(0)
++#define  TIMER0_RELOAD_EN      BIT(1)
++#define  TIMER0_25MHZ            BIT(11)
+ #define  TIMER0_DIV(div)         ((div) << 19)
+-#define  TIMER1_EN             0x0004
+-#define  TIMER1_RELOAD_EN      0x0008
+-#define  TIMER1_25MHZ            0x1000
++#define  TIMER1_EN             BIT(2)
++#define  TIMER1_RELOAD_EN      BIT(3)
++#define  TIMER1_25MHZ            BIT(12)
+ #define  TIMER1_DIV(div)         ((div) << 22)
+ #define TIMER_EVENTS_STATUS   0x0004
+ #define  TIMER0_CLR_MASK         (~0x1)
diff --git a/target/linux/mvebu/patches-3.10/0167-clocksource-armada-370-xp-Simplify-TIMER_CTRL-regist.patch b/target/linux/mvebu/patches-3.10/0167-clocksource-armada-370-xp-Simplify-TIMER_CTRL-regist.patch
new file mode 100644 (file)
index 0000000..109d52d
--- /dev/null
@@ -0,0 +1,174 @@
+From 7a5e03909417ccecc85819837d10cbb6ffe1d759 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 13 Aug 2013 11:43:11 -0300
+Subject: [PATCH 167/203] clocksource: armada-370-xp: Simplify TIMER_CTRL
+ register access
+
+This commit creates two functions to access the TIMER_CTRL register:
+one for global one for the per-cpu. This makes the code much more
+readable. In addition, since the TIMER_CTRL register is also used for
+watchdog, this is preparation work for future thread-safe improvements.
+
+Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+---
+ drivers/clocksource/time-armada-370-xp.c | 69 ++++++++++++++------------------
+ 1 file changed, 30 insertions(+), 39 deletions(-)
+
+--- a/drivers/clocksource/time-armada-370-xp.c
++++ b/drivers/clocksource/time-armada-370-xp.c
+@@ -71,6 +71,18 @@ static u32 ticks_per_jiffy;
+ static struct clock_event_device __percpu **percpu_armada_370_xp_evt;
++static void timer_ctrl_clrset(u32 clr, u32 set)
++{
++      writel((readl(timer_base + TIMER_CTRL_OFF) & ~clr) | set,
++              timer_base + TIMER_CTRL_OFF);
++}
++
++static void local_timer_ctrl_clrset(u32 clr, u32 set)
++{
++      writel((readl(local_base + TIMER_CTRL_OFF) & ~clr) | set,
++              local_base + TIMER_CTRL_OFF);
++}
++
+ static u32 notrace armada_370_xp_read_sched_clock(void)
+ {
+       return ~readl(timer_base + TIMER0_VAL_OFF);
+@@ -83,7 +95,6 @@ static int
+ armada_370_xp_clkevt_next_event(unsigned long delta,
+                               struct clock_event_device *dev)
+ {
+-      u32 u;
+       /*
+        * Clear clockevent timer interrupt.
+        */
+@@ -97,11 +108,8 @@ armada_370_xp_clkevt_next_event(unsigned
+       /*
+        * Enable the timer.
+        */
+-      u = readl(local_base + TIMER_CTRL_OFF);
+-      u = ((u & ~TIMER0_RELOAD_EN) | TIMER0_EN |
+-           TIMER0_DIV(TIMER_DIVIDER_SHIFT));
+-      writel(u, local_base + TIMER_CTRL_OFF);
+-
++      local_timer_ctrl_clrset(TIMER0_RELOAD_EN,
++                              TIMER0_EN | TIMER0_DIV(TIMER_DIVIDER_SHIFT));
+       return 0;
+ }
+@@ -109,8 +117,6 @@ static void
+ armada_370_xp_clkevt_mode(enum clock_event_mode mode,
+                         struct clock_event_device *dev)
+ {
+-      u32 u;
+-
+       if (mode == CLOCK_EVT_MODE_PERIODIC) {
+               /*
+@@ -122,18 +128,14 @@ armada_370_xp_clkevt_mode(enum clock_eve
+               /*
+                * Enable timer.
+                */
+-
+-              u = readl(local_base + TIMER_CTRL_OFF);
+-
+-              writel((u | TIMER0_EN | TIMER0_RELOAD_EN |
+-                      TIMER0_DIV(TIMER_DIVIDER_SHIFT)),
+-                      local_base + TIMER_CTRL_OFF);
++              local_timer_ctrl_clrset(0, TIMER0_RELOAD_EN |
++                                         TIMER0_EN |
++                                         TIMER0_DIV(TIMER_DIVIDER_SHIFT));
+       } else {
+               /*
+                * Disable timer.
+                */
+-              u = readl(local_base + TIMER_CTRL_OFF);
+-              writel(u & ~TIMER0_EN, local_base + TIMER_CTRL_OFF);
++              local_timer_ctrl_clrset(TIMER0_EN, 0);
+               /*
+                * ACK pending timer interrupt.
+@@ -169,18 +171,18 @@ static irqreturn_t armada_370_xp_timer_i
+  */
+ static int __cpuinit armada_370_xp_timer_setup(struct clock_event_device *evt)
+ {
+-      u32 u;
++      u32 clr = 0, set = 0;
+       int cpu = smp_processor_id();
+       /* Use existing clock_event for cpu 0 */
+       if (!smp_processor_id())
+               return 0;
+-      u = readl(local_base + TIMER_CTRL_OFF);
+       if (timer25Mhz)
+-              writel(u | TIMER0_25MHZ, local_base + TIMER_CTRL_OFF);
++              set = TIMER0_25MHZ;
+       else
+-              writel(u & ~TIMER0_25MHZ, local_base + TIMER_CTRL_OFF);
++              clr = TIMER0_25MHZ;
++      local_timer_ctrl_clrset(clr, set);
+       evt->name               = armada_370_xp_clkevt.name;
+       evt->irq                = armada_370_xp_clkevt.irq;
+@@ -212,7 +214,7 @@ static struct local_timer_ops armada_370
+ static void __init armada_370_xp_timer_init(struct device_node *np)
+ {
+-      u32 u;
++      u32 clr = 0, set = 0;
+       int res;
+       timer_base = of_iomap(np, 0);
+@@ -221,29 +223,20 @@ static void __init armada_370_xp_timer_i
+       if (of_find_property(np, "marvell,timer-25Mhz", NULL)) {
+               /* The fixed 25MHz timer is available so let's use it */
+-              u = readl(local_base + TIMER_CTRL_OFF);
+-              writel(u | TIMER0_25MHZ,
+-                     local_base + TIMER_CTRL_OFF);
+-              u = readl(timer_base + TIMER_CTRL_OFF);
+-              writel(u | TIMER0_25MHZ,
+-                     timer_base + TIMER_CTRL_OFF);
++              set = TIMER0_25MHZ;
+               timer_clk = 25000000;
+       } else {
+               unsigned long rate = 0;
+               struct clk *clk = of_clk_get(np, 0);
+               WARN_ON(IS_ERR(clk));
+               rate =  clk_get_rate(clk);
+-              u = readl(local_base + TIMER_CTRL_OFF);
+-              writel(u & ~(TIMER0_25MHZ),
+-                     local_base + TIMER_CTRL_OFF);
+-
+-              u = readl(timer_base + TIMER_CTRL_OFF);
+-              writel(u & ~(TIMER0_25MHZ),
+-                     timer_base + TIMER_CTRL_OFF);
+-
+               timer_clk = rate / TIMER_DIVIDER;
++
++              clr = TIMER0_25MHZ;
+               timer25Mhz = false;
+       }
++      timer_ctrl_clrset(clr, set);
++      local_timer_ctrl_clrset(clr, set);
+       /*
+        * We use timer 0 as clocksource, and private(local) timer 0
+@@ -265,10 +258,8 @@ static void __init armada_370_xp_timer_i
+       writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
+       writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
+-      u = readl(timer_base + TIMER_CTRL_OFF);
+-
+-      writel((u | TIMER0_EN | TIMER0_RELOAD_EN |
+-              TIMER0_DIV(TIMER_DIVIDER_SHIFT)), timer_base + TIMER_CTRL_OFF);
++      timer_ctrl_clrset(0, TIMER0_EN | TIMER0_RELOAD_EN |
++                           TIMER0_DIV(TIMER_DIVIDER_SHIFT));
+       clocksource_mmio_init(timer_base + TIMER0_VAL_OFF,
+                             "armada_370_xp_clocksource",
diff --git a/target/linux/mvebu/patches-3.10/0168-clocksource-armada-370-xp-Introduce-new-compatibles.patch b/target/linux/mvebu/patches-3.10/0168-clocksource-armada-370-xp-Introduce-new-compatibles.patch
new file mode 100644 (file)
index 0000000..f028dfa
--- /dev/null
@@ -0,0 +1,101 @@
+From 9cb47bf175645d15f97e6d964dd4a4f089275ef5 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 13 Aug 2013 11:43:13 -0300
+Subject: [PATCH 168/203] clocksource: armada-370-xp: Introduce new compatibles
+
+The Armada XP SoC clocksource driver cannot work without the 25 MHz
+fixed timer. Therefore it's appropriate to introduce a new compatible
+string and use it to set the 25 MHz fixed timer.
+
+The 'marvell,timer-25MHz' property will be marked as deprecated.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+---
+ drivers/clocksource/time-armada-370-xp.c | 54 +++++++++++++++++++++++---------
+ 1 file changed, 39 insertions(+), 15 deletions(-)
+
+--- a/drivers/clocksource/time-armada-370-xp.c
++++ b/drivers/clocksource/time-armada-370-xp.c
+@@ -13,6 +13,19 @@
+  *
+  * Timer 0 is used as free-running clocksource, while timer 1 is
+  * used as clock_event_device.
++ *
++ * ---
++ * Clocksource driver for Armada 370 and Armada XP SoC.
++ * This driver implements one compatible string for each SoC, given
++ * each has its own characteristics:
++ *
++ *   * Armada 370 has no 25 MHz fixed timer.
++ *
++ *   * Armada XP cannot work properly without such 25 MHz fixed timer as
++ *     doing otherwise leads to using a clocksource whose frequency varies
++ *     when doing cpufreq frequency changes.
++ *
++ * See Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt
+  */
+ #include <linux/init.h>
+@@ -212,7 +225,7 @@ static struct local_timer_ops armada_370
+       .stop   =  armada_370_xp_timer_stop,
+ };
+-static void __init armada_370_xp_timer_init(struct device_node *np)
++static void __init armada_370_xp_timer_common_init(struct device_node *np)
+ {
+       u32 clr = 0, set = 0;
+       int res;
+@@ -221,20 +234,10 @@ static void __init armada_370_xp_timer_i
+       WARN_ON(!timer_base);
+       local_base = of_iomap(np, 1);
+-      if (of_find_property(np, "marvell,timer-25Mhz", NULL)) {
+-              /* The fixed 25MHz timer is available so let's use it */
++      if (timer25Mhz)
+               set = TIMER0_25MHZ;
+-              timer_clk = 25000000;
+-      } else {
+-              unsigned long rate = 0;
+-              struct clk *clk = of_clk_get(np, 0);
+-              WARN_ON(IS_ERR(clk));
+-              rate =  clk_get_rate(clk);
+-              timer_clk = rate / TIMER_DIVIDER;
+-
++      else
+               clr = TIMER0_25MHZ;
+-              timer25Mhz = false;
+-      }
+       timer_ctrl_clrset(clr, set);
+       local_timer_ctrl_clrset(clr, set);
+@@ -288,5 +291,26 @@ static void __init armada_370_xp_timer_i
+ #endif
+       }
+ }
+-CLOCKSOURCE_OF_DECLARE(armada_370_xp, "marvell,armada-370-xp-timer",
+-                     armada_370_xp_timer_init);
++
++static void __init armada_xp_timer_init(struct device_node *np)
++{
++      /* The fixed 25MHz timer is required, timer25Mhz is true by default */
++      timer_clk = 25000000;
++
++      armada_370_xp_timer_common_init(np);
++}
++CLOCKSOURCE_OF_DECLARE(armada_xp, "marvell,armada-xp-timer",
++                     armada_xp_timer_init);
++
++static void __init armada_370_timer_init(struct device_node *np)
++{
++      struct clk *clk = of_clk_get(np, 0);
++
++      WARN_ON(IS_ERR(clk));
++      timer_clk = clk_get_rate(clk) / TIMER_DIVIDER;
++      timer25Mhz = false;
++
++      armada_370_xp_timer_common_init(np);
++}
++CLOCKSOURCE_OF_DECLARE(armada_370, "marvell,armada-370-timer",
++                     armada_370_timer_init);
diff --git a/target/linux/mvebu/patches-3.10/0169-clocksource-armada-370-xp-Replace-WARN_ON-with-BUG_O.patch b/target/linux/mvebu/patches-3.10/0169-clocksource-armada-370-xp-Replace-WARN_ON-with-BUG_O.patch
new file mode 100644 (file)
index 0000000..e170760
--- /dev/null
@@ -0,0 +1,29 @@
+From bcaac3d9265d751f7d20df6ed0ac24241308dff7 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 20 Aug 2013 12:45:52 -0300
+Subject: [PATCH 169/203] clocksource: armada-370-xp: Replace WARN_ON with
+ BUG_ON
+
+If the clock fails to be obtained and the timer fails to be properly
+registered, the kernel will freeze real soon. Instead, let's BUG()
+where the actual problem is located.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Acked-by: Jason Cooper <jason@lakedaemon.net>
+Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+---
+ drivers/clocksource/time-armada-370-xp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/clocksource/time-armada-370-xp.c
++++ b/drivers/clocksource/time-armada-370-xp.c
+@@ -306,7 +306,7 @@ static void __init armada_370_timer_init
+ {
+       struct clk *clk = of_clk_get(np, 0);
+-      WARN_ON(IS_ERR(clk));
++      BUG_ON(IS_ERR(clk));
+       timer_clk = clk_get_rate(clk) / TIMER_DIVIDER;
+       timer25Mhz = false;
diff --git a/target/linux/mvebu/patches-3.10/0170-clocksource-armada-370-xp-Get-reference-fixed-clock-.patch b/target/linux/mvebu/patches-3.10/0170-clocksource-armada-370-xp-Get-reference-fixed-clock-.patch
new file mode 100644 (file)
index 0000000..e87f7fc
--- /dev/null
@@ -0,0 +1,36 @@
+From 7d7214129f7bde5bb55c0691968407b48f08efb5 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 20 Aug 2013 12:45:53 -0300
+Subject: [PATCH 170/203] clocksource: armada-370-xp: Get reference fixed-clock
+ by name
+
+The Armada XP timer has two mandatory clock inputs: nbclk and refclk,
+as specified by the device-tree binding.
+
+This commit fixes the clock selection. Instead of hard-coding the clock
+rate for the 25 MHz reference fixed-clock, obtain the clock by its name.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Acked-by: Jason Cooper <jason@lakedaemon.net>
+Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+---
+ drivers/clocksource/time-armada-370-xp.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/clocksource/time-armada-370-xp.c
++++ b/drivers/clocksource/time-armada-370-xp.c
+@@ -294,8 +294,11 @@ static void __init armada_370_xp_timer_c
+ static void __init armada_xp_timer_init(struct device_node *np)
+ {
+-      /* The fixed 25MHz timer is required, timer25Mhz is true by default */
+-      timer_clk = 25000000;
++      struct clk *clk = of_clk_get_by_name(np, "fixed");
++
++      /* The 25Mhz fixed clock is mandatory, and must always be available */
++      BUG_ON(IS_ERR(clk));
++      timer_clk = clk_get_rate(clk);
+       armada_370_xp_timer_common_init(np);
+ }
diff --git a/target/linux/mvebu/patches-3.10/0171-clocksource-armada-370-xp-Register-sched_clock-after.patch b/target/linux/mvebu/patches-3.10/0171-clocksource-armada-370-xp-Register-sched_clock-after.patch
new file mode 100644 (file)
index 0000000..c5b4dce
--- /dev/null
@@ -0,0 +1,65 @@
+From 3d7976bb4a0f34203456cc0e9054b4a6401c9fdb Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 26 Nov 2013 18:20:14 -0300
+Subject: [PATCH 171/203] clocksource: armada-370-xp: Register sched_clock
+ after the counter reset
+
+This commit registers the sched_clock _after_ the counter reset
+(instead of before). This removes the timestamp 'jump' in kernel
+log messages.
+
+Before this change:
+
+[    0.000000] sched_clock: 32 bits at 25MHz, resolution 40ns, wraps every 171798691800ns
+[    0.000000] Initializing Coherency fabric
+[    0.000000] Aurora cache controller enabled
+[    0.000000] l2x0: 16 ways, CACHE_ID 0x00000100, AUX_CTRL 0x1a696b12, Cache size: 1024 kB
+[  163.507447] Calibrating delay loop... 1325.05 BogoMIPS (lpj=662528)
+[  163.521419] pid_max: default: 32768 minimum: 301
+[  163.526185] Mount-cache hash table entries: 512
+[  163.531095] CPU: Testing write buffer coherency: ok
+
+After this change:
+
+[    0.000000] sched_clock: 32 bits at 25MHz, resolution 40ns, wraps every 171798691800ns
+[    0.000000] Initializing Coherency fabric
+[    0.000000] Aurora cache controller enabled
+[    0.000000] l2x0: 16 ways, CACHE_ID 0x00000100, AUX_CTRL 0x1a696b12, Cache size: 1024 kB
+[    0.016849] Calibrating delay loop... 1325.05 BogoMIPS (lpj=662528)
+[    0.030820] pid_max: default: 32768 minimum: 301
+[    0.035588] Mount-cache hash table entries: 512
+[    0.040500] CPU: Testing write buffer coherency: ok
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Acked-by: Jason Cooper <jason@lakedaemon.net>
+---
+ drivers/clocksource/time-armada-370-xp.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/clocksource/time-armada-370-xp.c
++++ b/drivers/clocksource/time-armada-370-xp.c
+@@ -250,11 +250,6 @@ static void __init armada_370_xp_timer_c
+       ticks_per_jiffy = (timer_clk + HZ / 2) / HZ;
+       /*
+-       * Set scale and timer for sched_clock.
+-       */
+-      setup_sched_clock(armada_370_xp_read_sched_clock, 32, timer_clk);
+-
+-      /*
+        * Setup free-running clocksource timer (interrupts
+        * disabled).
+        */
+@@ -264,6 +259,11 @@ static void __init armada_370_xp_timer_c
+       timer_ctrl_clrset(0, TIMER0_EN | TIMER0_RELOAD_EN |
+                            TIMER0_DIV(TIMER_DIVIDER_SHIFT));
++      /*
++       * Set scale and timer for sched_clock.
++       */
++      setup_sched_clock(armada_370_xp_read_sched_clock, 32, timer_clk);
++
+       clocksource_mmio_init(timer_base + TIMER0_VAL_OFF,
+                             "armada_370_xp_clocksource",
+                             timer_clk, 300, 32, clocksource_mmio_readl_down);
diff --git a/target/linux/mvebu/patches-3.10/0172-ARM-mvebu-Fix-the-Armada-370-XP-timer-compatible-str.patch b/target/linux/mvebu/patches-3.10/0172-ARM-mvebu-Fix-the-Armada-370-XP-timer-compatible-str.patch
new file mode 100644 (file)
index 0000000..de409aa
--- /dev/null
@@ -0,0 +1,62 @@
+From e33103d8d4cfc513467eb30bc4faee5c91c8e6c2 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 13 Aug 2013 11:43:15 -0300
+Subject: [PATCH 172/203] ARM: mvebu: Fix the Armada 370/XP timer compatible
+ strings
+
+The "marvell,armada-370-xp-timer" compatible string, together with
+the "marvell,timer-25Mhz" property are deprecated and should be
+removed from current DT.
+
+Instead, the timer DT nodes are now required to have an appropriate
+compatible string, which should be either "marvell,armada-370-timer"
+or "marvell,armada-xp-timer", depending on SoC.
+
+The clock property is now required only for Armada 370 so move it accordingly.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-370-xp.dtsi | 2 --
+ arch/arm/boot/dts/armada-370.dtsi    | 5 +++++
+ arch/arm/boot/dts/armada-xp.dtsi     | 2 +-
+ 3 files changed, 6 insertions(+), 3 deletions(-)
+
+--- a/arch/arm/boot/dts/armada-370-xp.dtsi
++++ b/arch/arm/boot/dts/armada-370-xp.dtsi
+@@ -143,10 +143,8 @@
+                       };
+                       timer@20300 {
+-                              compatible = "marvell,armada-370-xp-timer";
+                               reg = <0x20300 0x30>, <0x21040 0x30>;
+                               interrupts = <37>, <38>, <39>, <40>, <5>, <6>;
+-                              clocks = <&coreclk 2>;
+                       };
+                       sata@a0000 {
+--- a/arch/arm/boot/dts/armada-370.dtsi
++++ b/arch/arm/boot/dts/armada-370.dtsi
+@@ -163,6 +163,11 @@
+                               interrupts = <91>;
+                       };
++                      timer@20300 {
++                              compatible = "marvell,armada-370-timer";
++                              clocks = <&coreclk 2>;
++                      };
++
+                       coreclk: mvebu-sar@18230 {
+                               compatible = "marvell,armada-370-core-clock";
+                               reg = <0x18230 0x08>;
+--- a/arch/arm/boot/dts/armada-xp.dtsi
++++ b/arch/arm/boot/dts/armada-xp.dtsi
+@@ -69,7 +69,7 @@
+                       };
+                       timer@20300 {
+-                              marvell,timer-25Mhz;
++                              compatible = "marvell,armada-xp-timer";
+                       };
+                       coreclk: mvebu-sar@18230 {
diff --git a/target/linux/mvebu/patches-3.10/0173-ARM-mvebu-Add-the-reference-25-MHz-fixed-clock-to-Ar.patch b/target/linux/mvebu/patches-3.10/0173-ARM-mvebu-Add-the-reference-25-MHz-fixed-clock-to-Ar.patch
new file mode 100644 (file)
index 0000000..4f7dd76
--- /dev/null
@@ -0,0 +1,34 @@
+From e4011be91332bacc5cf166e1ce92c3678fc7c646 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 20 Aug 2013 12:45:50 -0300
+Subject: [PATCH 173/203] ARM: mvebu: Add the reference 25 MHz fixed-clock to
+ Armada XP
+
+The Armada XP SoC has a reference 25 MHz fixed-clock that is used in
+some controllers such as the timer and the watchdog. This commit adds
+a DT representation of this clock through a fixed-clock compatible node.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Reviewed-by: Mike Turquette <mturquette@linaro.org>
+Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-xp.dtsi | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/arch/arm/boot/dts/armada-xp.dtsi
++++ b/arch/arm/boot/dts/armada-xp.dtsi
+@@ -169,4 +169,13 @@
+                       };
+               };
+       };
++
++      clocks {
++              /* 25 MHz reference crystal */
++              refclk: oscillator {
++                      compatible = "fixed-clock";
++                      #clock-cells = <0>;
++                      clock-frequency = <25000000>;
++              };
++      };
+ };
diff --git a/target/linux/mvebu/patches-3.10/0174-ARM-mvebu-Add-clock-properties-to-Armada-XP-timer-no.patch b/target/linux/mvebu/patches-3.10/0174-ARM-mvebu-Add-clock-properties-to-Armada-XP-timer-no.patch
new file mode 100644 (file)
index 0000000..51796bf
--- /dev/null
@@ -0,0 +1,30 @@
+From 200b303fc6c2709340996b02ae0c9a7130de7ec3 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 20 Aug 2013 12:45:51 -0300
+Subject: [PATCH 174/203] ARM: mvebu: Add clock properties to Armada XP timer
+ node
+
+With the addition of the Armada XP reference clock, we can now model
+accurately the available clock inputs for the timer: namely, nbclk
+and refclk. For each of this clock inputs we assign a name, for the
+driver to select as appropriate.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Reviewed-by: Mike Turquette <mturquette@linaro.org>
+Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-xp.dtsi | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arm/boot/dts/armada-xp.dtsi
++++ b/arch/arm/boot/dts/armada-xp.dtsi
+@@ -70,6 +70,8 @@
+                       timer@20300 {
+                               compatible = "marvell,armada-xp-timer";
++                              clocks = <&coreclk 2>, <&refclk>;
++                              clock-names = "nbclk", "fixed";
+                       };
+                       coreclk: mvebu-sar@18230 {
diff --git a/target/linux/mvebu/patches-3.10/0175-ARM-mvebu-Relocate-PCIe-node-in-Armada-370-RD-board.patch b/target/linux/mvebu/patches-3.10/0175-ARM-mvebu-Relocate-PCIe-node-in-Armada-370-RD-board.patch
new file mode 100644 (file)
index 0000000..3b37ab9
--- /dev/null
@@ -0,0 +1,62 @@
+From 079d1ecae4bd4166a0f89bcb8e0c96bec1b39622 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Thu, 8 Aug 2013 18:03:09 -0300
+Subject: [PATCH 175/203] ARM: mvebu: Relocate PCIe node in Armada 370 RD board
+
+The pcie-controller node needs to be relocated according the MBus
+DT binding, since it's now a child of the mbus-compatible node.
+
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-370-rd.dts | 32 ++++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+--- a/arch/arm/boot/dts/armada-370-rd.dts
++++ b/arch/arm/boot/dts/armada-370-rd.dts
+@@ -31,6 +31,22 @@
+               ranges = <MBUS_ID(0xf0, 0x01) 0 0xd0000000 0x100000
+                         MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000>;
++              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";
++                      };
++              };
++
+               internal-regs {
+                       serial@12000 {
+                               clock-frequency = <200000000>;
+@@ -88,22 +104,6 @@
+                                       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/0176-of-irq-create-interrupts-extended-property.patch b/target/linux/mvebu/patches-3.10/0176-of-irq-create-interrupts-extended-property.patch
new file mode 100644 (file)
index 0000000..a31d2d0
--- /dev/null
@@ -0,0 +1,104 @@
+From 6dc29d94d92ccc558b946bd57cd8d7cb19d8def1 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@linaro.org>
+Date: Thu, 19 Dec 2013 09:30:47 -0300
+Subject: [PATCH 176/203] of/irq: create interrupts-extended property
+
+The standard interrupts property in device tree can only handle
+interrupts coming from a single interrupt parent. If a device is wired
+to multiple interrupt controllers, then it needs to be attached to a
+node with an interrupt-map property to demux the interrupt specifiers
+which is confusing. It would be a lot easier if there was a form of the
+interrupts property that allows for a separate interrupt phandle for
+each interrupt specifier.
+
+This patch does exactly that by creating a new interrupts-extended
+property which reuses the phandle+arguments pattern used by GPIOs and
+other core bindings.
+
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+Acked-by: Tony Lindgren <tony@atomide.com>
+Acked-by: Kumar Gala <galak@codeaurora.org>
+[grant.likely: removed versatile platform hunks into separate patch]
+Cc: Rob Herring <rob.herring@calxeda.com>
+
+Conflicts:
+       arch/arm/boot/dts/testcases/tests-interrupts.dtsi
+       drivers/of/selftest.c
+---
+ .../bindings/interrupt-controller/interrupts.txt   | 29 +++++++++++++++++-----
+ drivers/of/irq.c                                   | 16 ++++++++----
+ 2 files changed, 34 insertions(+), 11 deletions(-)
+
+--- a/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
++++ b/Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
+@@ -4,16 +4,33 @@ Specifying interrupt information for dev
+ 1) Interrupt client nodes
+ -------------------------
+-Nodes that describe devices which generate interrupts must contain an
+-"interrupts" property. This property must contain a list of interrupt
+-specifiers, one per output interrupt. The format of the interrupt specifier is
+-determined by the interrupt controller to which the interrupts are routed; see
+-section 2 below for details.
++Nodes that describe devices which generate interrupts must contain an either an
++"interrupts" property or an "interrupts-extended" property. These properties
++contain a list of interrupt specifiers, one per output interrupt. The format of
++the interrupt specifier is determined by the interrupt controller to which the
++interrupts are routed; see section 2 below for details.
++
++  Example:
++      interrupt-parent = <&intc1>;
++      interrupts = <5 0>, <6 0>;
+ The "interrupt-parent" property is used to specify the controller to which
+ interrupts are routed and contains a single phandle referring to the interrupt
+ controller node. This property is inherited, so it may be specified in an
+-interrupt client node or in any of its parent nodes.
++interrupt client node or in any of its parent nodes. Interrupts listed in the
++"interrupts" property are always in reference to the node's interrupt parent.
++
++The "interrupts-extended" property is a special form for use when a node needs
++to reference multiple interrupt parents. Each entry in this property contains
++both the parent phandle and the interrupt specifier. "interrupts-extended"
++should only be used when a device has multiple interrupt parents.
++
++  Example:
++      interrupts-extended = <&intc1 5 1>, <&intc2 1 0>;
++
++A device node may contain either "interrupts" or "interrupts-extended", but not
++both. If both properties are present, then the operating system should log an
++error and use only the data in "interrupts".
+ 2) Interrupt controller nodes
+ -----------------------------
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -293,17 +293,23 @@ int of_irq_map_one(struct device_node *d
+       if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
+               return of_irq_map_oldworld(device, index, out_irq);
++      /* Get the reg property (if any) */
++      addr = of_get_property(device, "reg", NULL);
++
+       /* Get the interrupts property */
+       intspec = of_get_property(device, "interrupts", &intlen);
+-      if (intspec == NULL)
+-              return -EINVAL;
++      if (intspec == NULL) {
++              /* Try the new-style interrupts-extended */
++              res = of_parse_phandle_with_args(device, "interrupts-extended",
++                                              "#interrupt-cells", index, out_irq);
++              if (res)
++                      return -EINVAL;
++              return of_irq_parse_raw(addr, out_irq);
++      }
+       intlen /= sizeof(*intspec);
+       pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
+-      /* Get the reg property (if any) */
+-      addr = of_get_property(device, "reg", NULL);
+-
+       /* Look for the interrupt parent. */
+       p = of_irq_find_parent(device);
+       if (p == NULL)
diff --git a/target/linux/mvebu/patches-3.10/0177-of-irq-Avoid-calling-list_first_entry-for-empty-list.patch b/target/linux/mvebu/patches-3.10/0177-of-irq-Avoid-calling-list_first_entry-for-empty-list.patch
new file mode 100644 (file)
index 0000000..14b3d13
--- /dev/null
@@ -0,0 +1,30 @@
+From f159ea8ab3bce09a098d0d56c9e8909f385b87aa Mon Sep 17 00:00:00 2001
+From: Axel Lin <axel.lin@ingics.com>
+Date: Thu, 19 Dec 2013 09:30:48 -0300
+Subject: [PATCH 177/203] of/irq: Avoid calling list_first_entry() for empty
+ list
+
+list_first_entry() expects the list is not empty, we need to check if list is
+empty before calling list_first_entry(). Thus use list_first_entry_or_null()
+instead of list_first_entry().
+
+Signed-off-by: Axel Lin <axel.lin@ingics.com>
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+---
+ drivers/of/irq.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -488,8 +488,9 @@ void __init of_irq_init(const struct of_
+               }
+               /* Get the next pending parent that might have children */
+-              desc = list_first_entry(&intc_parent_list, typeof(*desc), list);
+-              if (list_empty(&intc_parent_list) || !desc) {
++              desc = list_first_entry_or_null(&intc_parent_list,
++                                              typeof(*desc), list);
++              if (!desc) {
+                       pr_err("of_irq_init: children remain, but no parents\n");
+                       break;
+               }
diff --git a/target/linux/mvebu/patches-3.10/0178-of-clean-up-ifdefs-in-of_irq.h.patch b/target/linux/mvebu/patches-3.10/0178-of-clean-up-ifdefs-in-of_irq.h.patch
new file mode 100644 (file)
index 0000000..57ea574
--- /dev/null
@@ -0,0 +1,68 @@
+From 704f3796c741df558d624078c5094439c0b65d09 Mon Sep 17 00:00:00 2001
+From: Rob Herring <rob.herring@calxeda.com>
+Date: Thu, 19 Dec 2013 09:30:49 -0300
+Subject: [PATCH 178/203] of: clean-up ifdefs in of_irq.h
+
+Much of of_irq.h is needlessly ifdef'ed. Clean this up and minimize the
+amount ifdef'ed code. This fixes some  build warnings when CONFIG_OF
+is not enabled (seen on i386 and x86_64):
+
+include/linux/of_irq.h:82:7: warning: 'struct device_node' declared inside parameter list [enabled by default]
+include/linux/of_irq.h:82:7: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default]
+include/linux/of_irq.h:87:47: warning: 'struct device_node' declared inside parameter list [enabled by default]
+
+Compile tested on i386, sparc and arm.
+
+Reported-by: Randy Dunlap <rdunlap@infradead.org>
+Cc: Grant Likely <grant.likely@linaro.org>
+Signed-off-by: Rob Herring <rob.herring@calxeda.com>
+---
+ include/linux/of_irq.h | 20 ++++++++------------
+ 1 file changed, 8 insertions(+), 12 deletions(-)
+
+--- a/include/linux/of_irq.h
++++ b/include/linux/of_irq.h
+@@ -1,8 +1,6 @@
+ #ifndef __OF_IRQ_H
+ #define __OF_IRQ_H
+-#if defined(CONFIG_OF)
+-struct of_irq;
+ #include <linux/types.h>
+ #include <linux/errno.h>
+ #include <linux/irq.h>
+@@ -10,14 +8,6 @@ struct of_irq;
+ #include <linux/ioport.h>
+ #include <linux/of.h>
+-/*
+- * irq_of_parse_and_map() is used by all OF enabled platforms; but SPARC
+- * implements it differently.  However, the prototype is the same for all,
+- * so declare it here regardless of the CONFIG_OF_IRQ setting.
+- */
+-extern unsigned int irq_of_parse_and_map(struct device_node *node, int index);
+-
+-#if defined(CONFIG_OF_IRQ)
+ /**
+  * of_irq - container for device_node/irq_specifier pair for an irq controller
+  * @controller: pointer to interrupt controller device tree node
+@@ -71,11 +61,17 @@ extern int of_irq_to_resource(struct dev
+ extern int of_irq_count(struct device_node *dev);
+ extern int of_irq_to_resource_table(struct device_node *dev,
+               struct resource *res, int nr_irqs);
+-extern struct device_node *of_irq_find_parent(struct device_node *child);
+ extern void of_irq_init(const struct of_device_id *matches);
+-#endif /* CONFIG_OF_IRQ */
++#if defined(CONFIG_OF)
++/*
++ * irq_of_parse_and_map() is used by all OF enabled platforms; but SPARC
++ * implements it differently.  However, the prototype is the same for all,
++ * so declare it here regardless of the CONFIG_OF_IRQ setting.
++ */
++extern unsigned int irq_of_parse_and_map(struct device_node *node, int index);
++extern struct device_node *of_irq_find_parent(struct device_node *child);
+ #else /* !CONFIG_OF */
+ static inline unsigned int irq_of_parse_and_map(struct device_node *dev,
diff --git a/target/linux/mvebu/patches-3.10/0179-of-irq-init-struct-resource-to-0-in-of_irq_to_resour.patch b/target/linux/mvebu/patches-3.10/0179-of-irq-init-struct-resource-to-0-in-of_irq_to_resour.patch
new file mode 100644 (file)
index 0000000..1e14dbf
--- /dev/null
@@ -0,0 +1,27 @@
+From 15a2884ede54118137708ccc72f246fe986f8a57 Mon Sep 17 00:00:00 2001
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Date: Thu, 19 Dec 2013 09:30:50 -0300
+Subject: [PATCH 179/203] of/irq: init struct resource to 0 in
+ of_irq_to_resource()
+
+It almost does not matter because most users use only the ->start member
+of the struct. However if this struct is passed to a platform device
+which is then added via platform_device_add() then the ->parent member is
+also used.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+---
+ drivers/of/irq.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -351,6 +351,7 @@ int of_irq_to_resource(struct device_nod
+       if (r && irq) {
+               const char *name = NULL;
++              memset(r, 0, sizeof(*r));
+               /*
+                * Get optional "interrupts-names" property to add a name
+                * to the resource.
diff --git a/target/linux/mvebu/patches-3.10/0180-irq-of-Fix-comment-typo-for-irq_of_parse_and_map.patch b/target/linux/mvebu/patches-3.10/0180-irq-of-Fix-comment-typo-for-irq_of_parse_and_map.patch
new file mode 100644 (file)
index 0000000..b66a59f
--- /dev/null
@@ -0,0 +1,24 @@
+From 3d73f7a8db8a7506630174d0e8609138d97c8326 Mon Sep 17 00:00:00 2001
+From: Yijing Wang <wangyijing@huawei.com>
+Date: Thu, 19 Dec 2013 09:30:51 -0300
+Subject: [PATCH 180/203] irq/of: Fix comment typo for irq_of_parse_and_map
+
+Fix trivial comment typo for irq_of_parse_and_map().
+
+Signed-off-by: Yijing Wang <wangyijing@huawei.com>
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+---
+ drivers/of/irq.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -28,7 +28,7 @@
+ /**
+  * irq_of_parse_and_map - Parse and map an interrupt into linux virq space
+- * @device: Device node of the device whose interrupt is to be mapped
++ * @dev: Device node of the device whose interrupt is to be mapped
+  * @index: Index of the interrupt to map
+  *
+  * This function is a wrapper that chains of_irq_map_one() and
diff --git a/target/linux/mvebu/patches-3.10/0181-of-Fix-dereferencing-node-name-in-debug-output-to-be.patch b/target/linux/mvebu/patches-3.10/0181-of-Fix-dereferencing-node-name-in-debug-output-to-be.patch
new file mode 100644 (file)
index 0000000..ce62d53
--- /dev/null
@@ -0,0 +1,82 @@
+From 02abb20a226a5a1e5c6dfaaf765dd71a90200cf9 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@linaro.org>
+Date: Thu, 19 Dec 2013 09:30:52 -0300
+Subject: [PATCH 181/203] of: Fix dereferencing node name in debug output to be
+ safe
+
+Several locations in the of_address and of_irq code dereference the
+full_name parameter from a device_node pointer without checking if the
+pointer is valid.  This patch switches to use of_node_full_name() which
+always checks the pointer.
+
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+---
+ drivers/of/address.c | 6 +++---
+ drivers/of/irq.c     | 8 ++++----
+ 2 files changed, 7 insertions(+), 7 deletions(-)
+
+--- a/drivers/of/address.c
++++ b/drivers/of/address.c
+@@ -481,7 +481,7 @@ static u64 __of_translate_address(struct
+       int na, ns, pna, pns;
+       u64 result = OF_BAD_ADDR;
+-      pr_debug("OF: ** translation for device %s **\n", dev->full_name);
++      pr_debug("OF: ** translation for device %s **\n", of_node_full_name(dev));
+       /* Increase refcount at current level */
+       of_node_get(dev);
+@@ -496,13 +496,13 @@ static u64 __of_translate_address(struct
+       bus->count_cells(dev, &na, &ns);
+       if (!OF_CHECK_COUNTS(na, ns)) {
+               printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
+-                     dev->full_name);
++                     of_node_full_name(dev));
+               goto bail;
+       }
+       memcpy(addr, in_addr, na * 4);
+       pr_debug("OF: bus is %s (na=%d, ns=%d) on %s\n",
+-          bus->name, na, ns, parent->full_name);
++          bus->name, na, ns, of_node_full_name(parent));
+       of_dump_addr("OF: translating address:", addr, na);
+       /* Translate */
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -102,7 +102,7 @@ int of_irq_map_raw(struct device_node *p
+       int imaplen, match, i;
+       pr_debug("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
+-               parent->full_name, be32_to_cpup(intspec),
++               of_node_full_name(parent), be32_to_cpup(intspec),
+                be32_to_cpup(intspec + 1), ointsize);
+       ipar = of_node_get(parent);
+@@ -126,7 +126,7 @@ int of_irq_map_raw(struct device_node *p
+               goto fail;
+       }
+-      pr_debug("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize);
++      pr_debug("of_irq_map_raw: ipar=%s, size=%d\n", of_node_full_name(ipar), intsize);
+       if (ointsize != intsize)
+               return -EINVAL;
+@@ -287,7 +287,7 @@ int of_irq_map_one(struct device_node *d
+       u32 intsize, intlen;
+       int res = -EINVAL;
+-      pr_debug("of_irq_map_one: dev=%s, index=%d\n", device->full_name, index);
++      pr_debug("of_irq_map_one: dev=%s, index=%d\n", of_node_full_name(device), index);
+       /* OldWorld mac stuff is "special", handle out of line */
+       if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
+@@ -361,7 +361,7 @@ int of_irq_to_resource(struct device_nod
+               r->start = r->end = irq;
+               r->flags = IORESOURCE_IRQ;
+-              r->name = name ? name : dev->full_name;
++              r->name = name ? name : of_node_full_name(dev);
+       }
+       return irq;
diff --git a/target/linux/mvebu/patches-3.10/0182-of-irq-Pass-trigger-type-in-IRQ-resource-flags.patch b/target/linux/mvebu/patches-3.10/0182-of-irq-Pass-trigger-type-in-IRQ-resource-flags.patch
new file mode 100644 (file)
index 0000000..5363b2e
--- /dev/null
@@ -0,0 +1,34 @@
+From 4bd60065fb935a5d390c9a442be3a18d2ea18eee Mon Sep 17 00:00:00 2001
+From: Tomasz Figa <tomasz.figa@gmail.com>
+Date: Thu, 19 Dec 2013 09:30:53 -0300
+Subject: [PATCH 182/203] of/irq: Pass trigger type in IRQ resource flags
+
+Some drivers might rely on availability of trigger flags in IRQ
+resource, for example to configure the hardware for particular interrupt
+type. However current code creating IRQ resources from data in device
+tree does not configure trigger flags in resulting resources.
+
+This patch tries to solve the problem, based on the fact that
+irq_of_parse_and_map() configures the trigger based on DT interrupt
+specifier and IRQD_TRIGGER_* flags are consistent with IORESOURCE_IRQ_*,
+and we can get correct trigger flags by calling irqd_get_trigger_type()
+after mapping the interrupt.
+
+Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com>
+[grant.likely: Merged the two assignments to r->flags]
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+---
+ drivers/of/irq.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -360,7 +360,7 @@ int of_irq_to_resource(struct device_nod
+                                             &name);
+               r->start = r->end = irq;
+-              r->flags = IORESOURCE_IRQ;
++              r->flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(irq));
+               r->name = name ? name : of_node_full_name(dev);
+       }
diff --git a/target/linux/mvebu/patches-3.10/0183-of-irq-Rename-of_irq_map_-functions-to-of_irq_parse_.patch b/target/linux/mvebu/patches-3.10/0183-of-irq-Rename-of_irq_map_-functions-to-of_irq_parse_.patch
new file mode 100644 (file)
index 0000000..5007d91
--- /dev/null
@@ -0,0 +1,682 @@
+From fd33285b3dab183df0cea06de9f618886dc0f1c0 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@linaro.org>
+Date: Thu, 19 Dec 2013 09:30:54 -0300
+Subject: [PATCH 183/203] of/irq: Rename of_irq_map_* functions to
+ of_irq_parse_*
+
+The OF irq handling code has been overloading the term 'map' to refer to
+both parsing the data in the device tree and mapping it to the internal
+linux irq system. This is probably because the device tree does have the
+concept of an 'interrupt-map' function for translating interrupt
+references from one node to another, but 'map' is still confusing when
+the primary purpose of some of the functions are to parse the DT data.
+
+This patch renames all the of_irq_map_* functions to of_irq_parse_*
+which makes it clear that there is a difference between the parsing
+phase and the mapping phase. Kernel code can make use of just the
+parsing or just the mapping support as needed by the subsystem.
+
+The patch was generated mechanically with a handful of sed commands.
+
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+Acked-by: Michal Simek <monstr@monstr.eu>
+Acked-by: Tony Lindgren <tony@atomide.com>
+Cc: Ralf Baechle <ralf@linux-mips.org>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+
+Conflicts:
+       arch/arm/mach-integrator/pci_v3.c
+       arch/mips/pci/pci-rt3883.c
+---
+ arch/arm/mach-integrator/pci_v3.c              | 279 +++++++++++++++++++++++++
+ arch/microblaze/pci/pci-common.c               |   2 +-
+ arch/mips/pci/fixup-lantiq.c                   |   2 +-
+ arch/powerpc/kernel/pci-common.c               |   2 +-
+ arch/powerpc/platforms/cell/celleb_scc_pciex.c |   2 +-
+ arch/powerpc/platforms/cell/celleb_scc_sio.c   |   2 +-
+ arch/powerpc/platforms/cell/spider-pic.c       |   2 +-
+ arch/powerpc/platforms/cell/spu_manage.c       |   2 +-
+ arch/powerpc/platforms/fsl_uli1575.c           |   2 +-
+ arch/powerpc/platforms/powermac/pic.c          |   2 +-
+ arch/powerpc/platforms/pseries/event_sources.c |   2 +-
+ arch/powerpc/sysdev/mpic_msi.c                 |   2 +-
+ arch/x86/kernel/devicetree.c                   |   2 +-
+ drivers/of/address.c                           |   4 +-
+ drivers/of/irq.c                               |  28 +--
+ drivers/of/of_pci_irq.c                        |  10 +-
+ drivers/pci/host/pci-mvebu.c                   |   2 +-
+ include/linux/of_irq.h                         |   8 +-
+ include/linux/of_pci.h                         |   2 +-
+ 19 files changed, 318 insertions(+), 39 deletions(-)
+
+--- a/arch/arm/mach-integrator/pci_v3.c
++++ b/arch/arm/mach-integrator/pci_v3.c
+@@ -610,3 +610,282 @@ void __init pci_v3_postinit(void)
+       register_isa_ports(PHYS_PCI_MEM_BASE, PHYS_PCI_IO_BASE, 0);
+ }
++
++/*
++ * A small note about bridges and interrupts.  The DECchip 21050 (and
++ * later) adheres to the PCI-PCI bridge specification.  This says that
++ * the interrupts on the other side of a bridge are swizzled in the
++ * following manner:
++ *
++ * Dev    Interrupt   Interrupt
++ *        Pin on      Pin on
++ *        Device      Connector
++ *
++ *   4    A           A
++ *        B           B
++ *        C           C
++ *        D           D
++ *
++ *   5    A           B
++ *        B           C
++ *        C           D
++ *        D           A
++ *
++ *   6    A           C
++ *        B           D
++ *        C           A
++ *        D           B
++ *
++ *   7    A           D
++ *        B           A
++ *        C           B
++ *        D           C
++ *
++ * Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
++ * Thus, each swizzle is ((pin-1) + (device#-4)) % 4
++ */
++
++/*
++ * This routine handles multiple bridges.
++ */
++static u8 __init pci_v3_swizzle(struct pci_dev *dev, u8 *pinp)
++{
++      if (*pinp == 0)
++              *pinp = 1;
++
++      return pci_common_swizzle(dev, pinp);
++}
++
++static int irq_tab[4] __initdata = {
++      IRQ_AP_PCIINT0, IRQ_AP_PCIINT1, IRQ_AP_PCIINT2, IRQ_AP_PCIINT3
++};
++
++/*
++ * map the specified device/slot/pin to an IRQ.  This works out such
++ * that slot 9 pin 1 is INT0, pin 2 is INT1, and slot 10 pin 1 is INT1.
++ */
++static int __init pci_v3_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++      int intnr = ((slot - 9) + (pin - 1)) & 3;
++
++      return irq_tab[intnr];
++}
++
++static struct hw_pci pci_v3 __initdata = {
++      .swizzle                = pci_v3_swizzle,
++      .setup                  = pci_v3_setup,
++      .nr_controllers         = 1,
++      .ops                    = &pci_v3_ops,
++      .preinit                = pci_v3_preinit,
++      .postinit               = pci_v3_postinit,
++};
++
++#ifdef CONFIG_OF
++
++static int __init pci_v3_map_irq_dt(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++      struct of_irq oirq;
++      int ret;
++
++      ret = of_irq_parse_pci(dev, &oirq);
++      if (ret) {
++              dev_err(&dev->dev, "of_irq_parse_pci() %d\n", ret);
++              /* Proper return code 0 == NO_IRQ */
++              return 0;
++      }
++
++      return irq_create_of_mapping(oirq.controller, oirq.specifier,
++                                   oirq.size);
++}
++
++static int __init pci_v3_dtprobe(struct platform_device *pdev,
++                              struct device_node *np)
++{
++      struct of_pci_range_parser parser;
++      struct of_pci_range range;
++      struct resource *res;
++      int irq, ret;
++
++      if (of_pci_range_parser_init(&parser, np))
++              return -EINVAL;
++
++      /* Get base for bridge registers */
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (!res) {
++              dev_err(&pdev->dev, "unable to obtain PCIv3 base\n");
++              return -ENODEV;
++      }
++      pci_v3_base = devm_ioremap(&pdev->dev, res->start,
++                                 resource_size(res));
++      if (!pci_v3_base) {
++              dev_err(&pdev->dev, "unable to remap PCIv3 base\n");
++              return -ENODEV;
++      }
++
++      /* Get and request error IRQ resource */
++      irq = platform_get_irq(pdev, 0);
++      if (irq <= 0) {
++              dev_err(&pdev->dev, "unable to obtain PCIv3 error IRQ\n");
++              return -ENODEV;
++      }
++      ret = devm_request_irq(&pdev->dev, irq, v3_irq, 0,
++                      "PCIv3 error", NULL);
++      if (ret < 0) {
++              dev_err(&pdev->dev, "unable to request PCIv3 error IRQ %d (%d)\n", irq, ret);
++              return ret;
++      }
++
++      for_each_of_pci_range(&parser, &range) {
++              if (!range.flags) {
++                      of_pci_range_to_resource(&range, np, &conf_mem);
++                      conf_mem.name = "PCIv3 config";
++              }
++              if (range.flags & IORESOURCE_IO) {
++                      of_pci_range_to_resource(&range, np, &io_mem);
++                      io_mem.name = "PCIv3 I/O";
++              }
++              if ((range.flags & IORESOURCE_MEM) &&
++                      !(range.flags & IORESOURCE_PREFETCH)) {
++                      non_mem_pci = range.pci_addr;
++                      non_mem_pci_sz = range.size;
++                      of_pci_range_to_resource(&range, np, &non_mem);
++                      non_mem.name = "PCIv3 non-prefetched mem";
++              }
++              if ((range.flags & IORESOURCE_MEM) &&
++                      (range.flags & IORESOURCE_PREFETCH)) {
++                      pre_mem_pci = range.pci_addr;
++                      pre_mem_pci_sz = range.size;
++                      of_pci_range_to_resource(&range, np, &pre_mem);
++                      pre_mem.name = "PCIv3 prefetched mem";
++              }
++      }
++
++      if (!conf_mem.start || !io_mem.start ||
++          !non_mem.start || !pre_mem.start) {
++              dev_err(&pdev->dev, "missing ranges in device node\n");
++              return -EINVAL;
++      }
++
++      pci_v3.map_irq = pci_v3_map_irq_dt;
++      pci_common_init_dev(&pdev->dev, &pci_v3);
++
++      return 0;
++}
++
++#else
++
++static inline int pci_v3_dtprobe(struct platform_device *pdev,
++                                struct device_node *np)
++{
++      return -EINVAL;
++}
++
++#endif
++
++static int __init pci_v3_probe(struct platform_device *pdev)
++{
++      struct device_node *np = pdev->dev.of_node;
++      int ret;
++
++      /* Remap the Integrator system controller */
++      ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100);
++      if (!ap_syscon_base) {
++              dev_err(&pdev->dev, "unable to remap the AP syscon for PCIv3\n");
++              return -ENODEV;
++      }
++
++      /* Device tree probe path */
++      if (np)
++              return pci_v3_dtprobe(pdev, np);
++
++      pci_v3_base = devm_ioremap(&pdev->dev, PHYS_PCI_V3_BASE, SZ_64K);
++      if (!pci_v3_base) {
++              dev_err(&pdev->dev, "unable to remap PCIv3 base\n");
++              return -ENODEV;
++      }
++
++      ret = devm_request_irq(&pdev->dev, IRQ_AP_V3INT, v3_irq, 0, "V3", NULL);
++      if (ret) {
++              dev_err(&pdev->dev, "unable to grab PCI error interrupt: %d\n",
++                      ret);
++              return -ENODEV;
++      }
++
++      conf_mem.name = "PCIv3 config";
++      conf_mem.start = PHYS_PCI_CONFIG_BASE;
++      conf_mem.end = PHYS_PCI_CONFIG_BASE + SZ_16M - 1;
++      conf_mem.flags = IORESOURCE_MEM;
++
++      io_mem.name = "PCIv3 I/O";
++      io_mem.start = PHYS_PCI_IO_BASE;
++      io_mem.end = PHYS_PCI_IO_BASE + SZ_16M - 1;
++      io_mem.flags = IORESOURCE_MEM;
++
++      non_mem_pci = 0x00000000;
++      non_mem_pci_sz = SZ_256M;
++      non_mem.name = "PCIv3 non-prefetched mem";
++      non_mem.start = PHYS_PCI_MEM_BASE;
++      non_mem.end = PHYS_PCI_MEM_BASE + SZ_256M - 1;
++      non_mem.flags = IORESOURCE_MEM;
++
++      pre_mem_pci = 0x10000000;
++      pre_mem_pci_sz = SZ_256M;
++      pre_mem.name = "PCIv3 prefetched mem";
++      pre_mem.start = PHYS_PCI_PRE_BASE + SZ_256M;
++      pre_mem.end = PHYS_PCI_PRE_BASE + SZ_256M - 1;
++      pre_mem.flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
++
++      pci_v3.map_irq = pci_v3_map_irq;
++
++      pci_common_init_dev(&pdev->dev, &pci_v3);
++
++      return 0;
++}
++
++static const struct of_device_id pci_ids[] = {
++      { .compatible = "v3,v360epc-pci", },
++      {},
++};
++
++static struct platform_driver pci_v3_driver = {
++      .driver = {
++              .name = "pci-v3",
++              .of_match_table = pci_ids,
++      },
++};
++
++static int __init pci_v3_init(void)
++{
++      return platform_driver_probe(&pci_v3_driver, pci_v3_probe);
++}
++
++subsys_initcall(pci_v3_init);
++
++/*
++ * Static mappings for the PCIv3 bridge
++ *
++ * e8000000   40000000        PCI memory              PHYS_PCI_MEM_BASE       (max 512M)
++ * ec000000   61000000        PCI config space        PHYS_PCI_CONFIG_BASE    (max 16M)
++ * fee00000   60000000        PCI IO                  PHYS_PCI_IO_BASE        (max 16M)
++ */
++static struct map_desc pci_v3_io_desc[] __initdata __maybe_unused = {
++      {
++              .virtual        = (unsigned long)PCI_MEMORY_VADDR,
++              .pfn            = __phys_to_pfn(PHYS_PCI_MEM_BASE),
++              .length         = SZ_16M,
++              .type           = MT_DEVICE
++      }, {
++              .virtual        = (unsigned long)PCI_CONFIG_VADDR,
++              .pfn            = __phys_to_pfn(PHYS_PCI_CONFIG_BASE),
++              .length         = SZ_16M,
++              .type           = MT_DEVICE
++      }
++};
++
++int __init pci_v3_early_init(void)
++{
++      iotable_init(pci_v3_io_desc, ARRAY_SIZE(pci_v3_io_desc));
++      vga_base = (unsigned long)PCI_MEMORY_VADDR;
++      pci_map_io_early(__phys_to_pfn(PHYS_PCI_IO_BASE));
++      return 0;
++}
+--- a/arch/microblaze/pci/pci-common.c
++++ b/arch/microblaze/pci/pci-common.c
+@@ -217,7 +217,7 @@ int pci_read_irq_line(struct pci_dev *pc
+       memset(&oirq, 0xff, sizeof(oirq));
+ #endif
+       /* Try to get a mapping from the device-tree */
+-      if (of_irq_map_pci(pci_dev, &oirq)) {
++      if (of_irq_parse_pci(pci_dev, &oirq)) {
+               u8 line, pin;
+               /* If that fails, lets fallback to what is in the config
+--- a/arch/mips/pci/fixup-lantiq.c
++++ b/arch/mips/pci/fixup-lantiq.c
+@@ -28,7 +28,7 @@ int __init pcibios_map_irq(const struct
+       struct of_irq dev_irq;
+       int irq;
+-      if (of_irq_map_pci(dev, &dev_irq)) {
++      if (of_irq_parse_pci(dev, &dev_irq)) {
+               dev_err(&dev->dev, "trying to map irq for unknown slot:%d pin:%d\n",
+                       slot, pin);
+               return 0;
+--- a/arch/powerpc/kernel/pci-common.c
++++ b/arch/powerpc/kernel/pci-common.c
+@@ -237,7 +237,7 @@ static int pci_read_irq_line(struct pci_
+       memset(&oirq, 0xff, sizeof(oirq));
+ #endif
+       /* Try to get a mapping from the device-tree */
+-      if (of_irq_map_pci(pci_dev, &oirq)) {
++      if (of_irq_parse_pci(pci_dev, &oirq)) {
+               u8 line, pin;
+               /* If that fails, lets fallback to what is in the config
+--- a/arch/powerpc/platforms/cell/celleb_scc_pciex.c
++++ b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
+@@ -507,7 +507,7 @@ static __init int celleb_setup_pciex(str
+       phb->ops = &scc_pciex_pci_ops;
+       /* internal interrupt handler */
+-      if (of_irq_map_one(node, 1, &oirq)) {
++      if (of_irq_parse_one(node, 1, &oirq)) {
+               pr_err("PCIEXC:Failed to map irq\n");
+               goto error;
+       }
+--- a/arch/powerpc/platforms/cell/celleb_scc_sio.c
++++ b/arch/powerpc/platforms/cell/celleb_scc_sio.c
+@@ -53,7 +53,7 @@ static int __init txx9_serial_init(void)
+                       if (!(txx9_serial_bitmap & (1<<i)))
+                               continue;
+-                      if (of_irq_map_one(node, i, &irq))
++                      if (of_irq_parse_one(node, i, &irq))
+                               continue;
+                       if (of_address_to_resource(node,
+                               txx9_scc_tab[i].index, &res))
+--- a/arch/powerpc/platforms/cell/spider-pic.c
++++ b/arch/powerpc/platforms/cell/spider-pic.c
+@@ -236,7 +236,7 @@ static unsigned int __init spider_find_c
+        * tree in case the device-tree is ever fixed
+        */
+       struct of_irq oirq;
+-      if (of_irq_map_one(pic->host->of_node, 0, &oirq) == 0) {
++      if (of_irq_parse_one(pic->host->of_node, 0, &oirq) == 0) {
+               virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+                                            oirq.size);
+               return virq;
+--- a/arch/powerpc/platforms/cell/spu_manage.c
++++ b/arch/powerpc/platforms/cell/spu_manage.c
+@@ -182,7 +182,7 @@ static int __init spu_map_interrupts(str
+       int i;
+       for (i=0; i < 3; i++) {
+-              ret = of_irq_map_one(np, i, &oirq);
++              ret = of_irq_parse_one(np, i, &oirq);
+               if (ret) {
+                       pr_debug("spu_new: failed to get irq %d\n", i);
+                       goto err;
+--- a/arch/powerpc/platforms/fsl_uli1575.c
++++ b/arch/powerpc/platforms/fsl_uli1575.c
+@@ -333,7 +333,7 @@ static void hpcd_final_uli5288(struct pc
+       laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8);
+       laddr[1] = laddr[2] = 0;
+-      of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq);
++      of_irq_parse_raw(hosenode, &pin, 1, laddr, &oirq);
+       virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+                                    oirq.size);
+       dev->irq = virq;
+--- a/arch/powerpc/platforms/powermac/pic.c
++++ b/arch/powerpc/platforms/powermac/pic.c
+@@ -393,7 +393,7 @@ static void __init pmac_pic_probe_oldsty
+ #endif
+ }
+-int of_irq_map_oldworld(struct device_node *device, int index,
++int of_irq_parse_oldworld(struct device_node *device, int index,
+                       struct of_irq *out_irq)
+ {
+       const u32 *ints = NULL;
+--- a/arch/powerpc/platforms/pseries/event_sources.c
++++ b/arch/powerpc/platforms/pseries/event_sources.c
+@@ -55,7 +55,7 @@ void request_event_sources_irqs(struct d
+       /* Else use normal interrupt tree parsing */
+       else {
+               /* First try to do a proper OF tree parsing */
+-              for (index = 0; of_irq_map_one(np, index, &oirq) == 0;
++              for (index = 0; of_irq_parse_one(np, index, &oirq) == 0;
+                    index++) {
+                       if (count > 15)
+                               break;
+--- a/arch/powerpc/sysdev/mpic_msi.c
++++ b/arch/powerpc/sysdev/mpic_msi.c
+@@ -63,7 +63,7 @@ static int mpic_msi_reserve_u3_hwirqs(st
+               pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);
+               index = 0;
+-              while (of_irq_map_one(np, index++, &oirq) == 0) {
++              while (of_irq_parse_one(np, index++, &oirq) == 0) {
+                       ops->xlate(mpic->irqhost, NULL, oirq.specifier,
+                                               oirq.size, &hwirq, &flags);
+                       msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq);
+--- a/arch/x86/kernel/devicetree.c
++++ b/arch/x86/kernel/devicetree.c
+@@ -117,7 +117,7 @@ static int x86_of_pci_irq_enable(struct
+       if (!pin)
+               return 0;
+-      ret = of_irq_map_pci(dev, &oirq);
++      ret = of_irq_parse_pci(dev, &oirq);
+       if (ret)
+               return ret;
+--- a/drivers/of/address.c
++++ b/drivers/of/address.c
+@@ -524,12 +524,12 @@ static u64 __of_translate_address(struct
+               pbus->count_cells(dev, &pna, &pns);
+               if (!OF_CHECK_COUNTS(pna, pns)) {
+                       printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
+-                             dev->full_name);
++                             of_node_full_name(dev));
+                       break;
+               }
+               pr_debug("OF: parent bus is %s (na=%d, ns=%d) on %s\n",
+-                  pbus->name, pna, pns, parent->full_name);
++                  pbus->name, pna, pns, of_node_full_name(parent));
+               /* Apply bus translation */
+               if (of_translate_one(dev, bus, pbus, addr, na, ns, pna, rprop))
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -31,14 +31,14 @@
+  * @dev: Device node of the device whose interrupt is to be mapped
+  * @index: Index of the interrupt to map
+  *
+- * This function is a wrapper that chains of_irq_map_one() and
++ * This function is a wrapper that chains of_irq_parse_one() and
+  * irq_create_of_mapping() to make things easier to callers
+  */
+ unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
+ {
+       struct of_irq oirq;
+-      if (of_irq_map_one(dev, index, &oirq))
++      if (of_irq_parse_one(dev, index, &oirq))
+               return 0;
+       return irq_create_of_mapping(oirq.controller, oirq.specifier,
+@@ -79,7 +79,7 @@ struct device_node *of_irq_find_parent(s
+ }
+ /**
+- * of_irq_map_raw - Low level interrupt tree parsing
++ * of_irq_parse_raw - Low level interrupt tree parsing
+  * @parent:   the device interrupt parent
+  * @intspec:  interrupt specifier ("interrupts" property of the device)
+  * @ointsize:   size of the passed in interrupt specifier
+@@ -93,7 +93,7 @@ struct device_node *of_irq_find_parent(s
+  * properties, for example when resolving PCI interrupts when no device
+  * node exist for the parent.
+  */
+-int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
++int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec,
+                  u32 ointsize, const __be32 *addr, struct of_irq *out_irq)
+ {
+       struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
+@@ -101,7 +101,7 @@ int of_irq_map_raw(struct device_node *p
+       u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
+       int imaplen, match, i;
+-      pr_debug("of_irq_map_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
++      pr_debug("of_irq_parse_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
+                of_node_full_name(parent), be32_to_cpup(intspec),
+                be32_to_cpup(intspec + 1), ointsize);
+@@ -126,7 +126,7 @@ int of_irq_map_raw(struct device_node *p
+               goto fail;
+       }
+-      pr_debug("of_irq_map_raw: ipar=%s, size=%d\n", of_node_full_name(ipar), intsize);
++      pr_debug("of_irq_parse_raw: ipar=%s, size=%d\n", of_node_full_name(ipar), intsize);
+       if (ointsize != intsize)
+               return -EINVAL;
+@@ -269,29 +269,29 @@ int of_irq_map_raw(struct device_node *p
+       return -EINVAL;
+ }
+-EXPORT_SYMBOL_GPL(of_irq_map_raw);
++EXPORT_SYMBOL_GPL(of_irq_parse_raw);
+ /**
+- * of_irq_map_one - Resolve an interrupt for a device
++ * of_irq_parse_one - Resolve an interrupt for a device
+  * @device: the device whose interrupt is to be resolved
+  * @index: index of the interrupt to resolve
+  * @out_irq: structure of_irq filled by this function
+  *
+  * This function resolves an interrupt, walking the tree, for a given
+- * device-tree node. It's the high level pendant to of_irq_map_raw().
++ * device-tree node. It's the high level pendant to of_irq_parse_raw().
+  */
+-int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq)
++int of_irq_parse_one(struct device_node *device, int index, struct of_irq *out_irq)
+ {
+       struct device_node *p;
+       const __be32 *intspec, *tmp, *addr;
+       u32 intsize, intlen;
+       int res = -EINVAL;
+-      pr_debug("of_irq_map_one: dev=%s, index=%d\n", of_node_full_name(device), index);
++      pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index);
+       /* OldWorld mac stuff is "special", handle out of line */
+       if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
+-              return of_irq_map_oldworld(device, index, out_irq);
++              return of_irq_parse_oldworld(device, index, out_irq);
+       /* Get the reg property (if any) */
+       addr = of_get_property(device, "reg", NULL);
+@@ -328,13 +328,13 @@ int of_irq_map_one(struct device_node *d
+               goto out;
+       /* Get new specifier and map it */
+-      res = of_irq_map_raw(p, intspec + index * intsize, intsize,
++      res = of_irq_parse_raw(p, intspec + index * intsize, intsize,
+                            addr, out_irq);
+  out:
+       of_node_put(p);
+       return res;
+ }
+-EXPORT_SYMBOL_GPL(of_irq_map_one);
++EXPORT_SYMBOL_GPL(of_irq_parse_one);
+ /**
+  * of_irq_to_resource - Decode a node's IRQ and return it as a resource
+--- a/drivers/of/of_pci_irq.c
++++ b/drivers/of/of_pci_irq.c
+@@ -5,7 +5,7 @@
+ #include <asm/prom.h>
+ /**
+- * of_irq_map_pci - Resolve the interrupt for a PCI device
++ * of_irq_parse_pci - Resolve the interrupt for a PCI device
+  * @pdev:       the device whose interrupt is to be resolved
+  * @out_irq:    structure of_irq filled by this function
+  *
+@@ -15,7 +15,7 @@
+  * PCI tree until an device-node is found, at which point it will finish
+  * resolving using the OF tree walking.
+  */
+-int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq)
++int of_irq_parse_pci(const struct pci_dev *pdev, struct of_irq *out_irq)
+ {
+       struct device_node *dn, *ppnode;
+       struct pci_dev *ppdev;
+@@ -30,7 +30,7 @@ int of_irq_map_pci(const struct pci_dev
+        */
+       dn = pci_device_to_OF_node(pdev);
+       if (dn) {
+-              rc = of_irq_map_one(dn, 0, out_irq);
++              rc = of_irq_parse_one(dn, 0, out_irq);
+               if (!rc)
+                       return rc;
+       }
+@@ -88,6 +88,6 @@ int of_irq_map_pci(const struct pci_dev
+       lspec_be = cpu_to_be32(lspec);
+       laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
+       laddr[1]  = laddr[2] = cpu_to_be32(0);
+-      return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
++      return of_irq_parse_raw(ppnode, &lspec_be, 1, laddr, out_irq);
+ }
+-EXPORT_SYMBOL_GPL(of_irq_map_pci);
++EXPORT_SYMBOL_GPL(of_irq_parse_pci);
+--- a/drivers/pci/host/pci-mvebu.c
++++ b/drivers/pci/host/pci-mvebu.c
+@@ -652,7 +652,7 @@ static int __init mvebu_pcie_map_irq(con
+       struct of_irq oirq;
+       int ret;
+-      ret = of_irq_map_pci(dev, &oirq);
++      ret = of_irq_parse_pci(dev, &oirq);
+       if (ret)
+               return ret;
+--- a/include/linux/of_irq.h
++++ b/include/linux/of_irq.h
+@@ -35,12 +35,12 @@ typedef int (*of_irq_init_cb_t)(struct d
+ #if defined(CONFIG_PPC32) && defined(CONFIG_PPC_PMAC)
+ extern unsigned int of_irq_workarounds;
+ extern struct device_node *of_irq_dflt_pic;
+-extern int of_irq_map_oldworld(struct device_node *device, int index,
++extern int of_irq_parse_oldworld(struct device_node *device, int index,
+                              struct of_irq *out_irq);
+ #else /* CONFIG_PPC32 && CONFIG_PPC_PMAC */
+ #define of_irq_workarounds (0)
+ #define of_irq_dflt_pic (NULL)
+-static inline int of_irq_map_oldworld(struct device_node *device, int index,
++static inline int of_irq_parse_oldworld(struct device_node *device, int index,
+                                     struct of_irq *out_irq)
+ {
+       return -EINVAL;
+@@ -48,10 +48,10 @@ static inline int of_irq_map_oldworld(st
+ #endif /* CONFIG_PPC32 && CONFIG_PPC_PMAC */
+-extern int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
++extern int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec,
+                         u32 ointsize, const __be32 *addr,
+                         struct of_irq *out_irq);
+-extern int of_irq_map_one(struct device_node *device, int index,
++extern int of_irq_parse_one(struct device_node *device, int index,
+                         struct of_irq *out_irq);
+ extern unsigned int irq_create_of_mapping(struct device_node *controller,
+                                         const u32 *intspec,
+--- a/include/linux/of_pci.h
++++ b/include/linux/of_pci.h
+@@ -6,7 +6,7 @@
+ struct pci_dev;
+ struct of_irq;
+-int of_irq_map_pci(const struct pci_dev *pdev, struct of_irq *out_irq);
++int of_irq_parse_pci(const struct pci_dev *pdev, struct of_irq *out_irq);
+ struct device_node;
+ struct device_node *of_pci_find_child_device(struct device_node *parent,
diff --git a/target/linux/mvebu/patches-3.10/0184-of-irq-Replace-of_irq-with-of_phandle_args.patch b/target/linux/mvebu/patches-3.10/0184-of-irq-Replace-of_irq-with-of_phandle_args.patch
new file mode 100644 (file)
index 0000000..f22da5f
--- /dev/null
@@ -0,0 +1,486 @@
+From 1baf727ee1d863a0eacd249cff6afc99022593c2 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@linaro.org>
+Date: Thu, 19 Dec 2013 09:30:55 -0300
+Subject: [PATCH 184/203] of/irq: Replace of_irq with of_phandle_args
+
+struct of_irq and struct of_phandle_args are exactly the same structure.
+This patch makes the kernel use of_phandle_args everywhere. This in
+itself isn't a big deal, but it makes some follow-on patches simpler.
+
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+Acked-by: Michal Simek <monstr@monstr.eu>
+Acked-by: Tony Lindgren <tony@atomide.com>
+Cc: Russell King <linux@arm.linux.org.uk>
+Cc: Ralf Baechle <ralf@linux-mips.org>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+
+Conflicts:
+       arch/mips/pci/pci-rt3883.c
+---
+ arch/arm/mach-integrator/pci_v3.c              |  5 ++---
+ arch/microblaze/pci/pci-common.c               |  9 ++++-----
+ arch/mips/pci/fixup-lantiq.c                   |  5 ++---
+ arch/powerpc/kernel/pci-common.c               |  9 ++++-----
+ arch/powerpc/platforms/cell/celleb_scc_pciex.c |  5 ++---
+ arch/powerpc/platforms/cell/celleb_scc_sio.c   |  5 ++---
+ arch/powerpc/platforms/cell/spider-pic.c       |  6 +++---
+ arch/powerpc/platforms/cell/spu_manage.c       | 12 ++++++------
+ arch/powerpc/platforms/fsl_uli1575.c           |  8 +++-----
+ arch/powerpc/platforms/powermac/pic.c          |  8 ++++----
+ arch/powerpc/platforms/pseries/event_sources.c |  7 +++----
+ arch/powerpc/sysdev/mpic_msi.c                 |  6 +++---
+ arch/x86/kernel/devicetree.c                   |  5 ++---
+ drivers/of/irq.c                               | 15 +++++++--------
+ drivers/of/of_pci_irq.c                        |  2 +-
+ drivers/pci/host/pci-mvebu.c                   |  5 ++---
+ include/linux/of_irq.h                         | 24 ++++--------------------
+ include/linux/of_pci.h                         |  4 ++--
+ 18 files changed, 56 insertions(+), 84 deletions(-)
+
+--- a/arch/arm/mach-integrator/pci_v3.c
++++ b/arch/arm/mach-integrator/pci_v3.c
+@@ -684,7 +684,7 @@ static struct hw_pci pci_v3 __initdata =
+ static int __init pci_v3_map_irq_dt(const struct pci_dev *dev, u8 slot, u8 pin)
+ {
+-      struct of_irq oirq;
++      struct of_phandle_args oirq;
+       int ret;
+       ret = of_irq_parse_pci(dev, &oirq);
+@@ -694,8 +694,7 @@ static int __init pci_v3_map_irq_dt(cons
+               return 0;
+       }
+-      return irq_create_of_mapping(oirq.controller, oirq.specifier,
+-                                   oirq.size);
++      return irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
+ }
+ static int __init pci_v3_dtprobe(struct platform_device *pdev,
+--- a/arch/microblaze/pci/pci-common.c
++++ b/arch/microblaze/pci/pci-common.c
+@@ -199,7 +199,7 @@ void pcibios_set_master(struct pci_dev *
+  */
+ int pci_read_irq_line(struct pci_dev *pci_dev)
+ {
+-      struct of_irq oirq;
++      struct of_phandle_args oirq;
+       unsigned int virq;
+       /* The current device-tree that iSeries generates from the HV
+@@ -243,11 +243,10 @@ int pci_read_irq_line(struct pci_dev *pc
+                       irq_set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+       } else {
+               pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
+-                       oirq.size, oirq.specifier[0], oirq.specifier[1],
+-                       of_node_full_name(oirq.controller));
++                       oirq.args_count, oirq.args[0], oirq.args[1],
++                       of_node_full_name(oirq.np));
+-              virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+-                                           oirq.size);
++              virq = irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
+       }
+       if (!virq) {
+               pr_debug(" Failed to map !\n");
+--- a/arch/mips/pci/fixup-lantiq.c
++++ b/arch/mips/pci/fixup-lantiq.c
+@@ -25,7 +25,7 @@ int pcibios_plat_dev_init(struct pci_dev
+ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+ {
+-      struct of_irq dev_irq;
++      struct of_phandle_args dev_irq;
+       int irq;
+       if (of_irq_parse_pci(dev, &dev_irq)) {
+@@ -33,8 +33,7 @@ int __init pcibios_map_irq(const struct
+                       slot, pin);
+               return 0;
+       }
+-      irq = irq_create_of_mapping(dev_irq.controller, dev_irq.specifier,
+-                                      dev_irq.size);
++      irq = irq_create_of_mapping(dev_irq.np, dev_irq.args, dev_irq.args_count);
+       dev_info(&dev->dev, "SLOT:%d PIN:%d IRQ:%d\n", slot, pin, irq);
+       return irq;
+ }
+--- a/arch/powerpc/kernel/pci-common.c
++++ b/arch/powerpc/kernel/pci-common.c
+@@ -228,7 +228,7 @@ int pcibios_add_platform_entries(struct
+  */
+ static int pci_read_irq_line(struct pci_dev *pci_dev)
+ {
+-      struct of_irq oirq;
++      struct of_phandle_args oirq;
+       unsigned int virq;
+       pr_debug("PCI: Try to map irq for %s...\n", pci_name(pci_dev));
+@@ -263,11 +263,10 @@ static int pci_read_irq_line(struct pci_
+                       irq_set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+       } else {
+               pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
+-                       oirq.size, oirq.specifier[0], oirq.specifier[1],
+-                       of_node_full_name(oirq.controller));
++                       oirq.args_count, oirq.args[0], oirq.args[1],
++                       of_node_full_name(oirq.np));
+-              virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+-                                           oirq.size);
++              virq = irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
+       }
+       if(virq == NO_IRQ) {
+               pr_debug(" Failed to map !\n");
+--- a/arch/powerpc/platforms/cell/celleb_scc_pciex.c
++++ b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
+@@ -486,7 +486,7 @@ static __init int celleb_setup_pciex(str
+                                    struct pci_controller *phb)
+ {
+       struct resource r;
+-      struct of_irq oirq;
++      struct of_phandle_args oirq;
+       int virq;
+       /* SMMIO registers; used inside this file */
+@@ -511,8 +511,7 @@ static __init int celleb_setup_pciex(str
+               pr_err("PCIEXC:Failed to map irq\n");
+               goto error;
+       }
+-      virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+-                                   oirq.size);
++      virq = irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
+       if (request_irq(virq, pciex_handle_internal_irq,
+                       0, "pciex", (void *)phb)) {
+               pr_err("PCIEXC:Failed to request irq\n");
+--- a/arch/powerpc/platforms/cell/celleb_scc_sio.c
++++ b/arch/powerpc/platforms/cell/celleb_scc_sio.c
+@@ -45,7 +45,7 @@ static int __init txx9_serial_init(void)
+       struct device_node *node;
+       int i;
+       struct uart_port req;
+-      struct of_irq irq;
++      struct of_phandle_args irq;
+       struct resource res;
+       for_each_compatible_node(node, "serial", "toshiba,sio-scc") {
+@@ -66,8 +66,7 @@ static int __init txx9_serial_init(void)
+ #ifdef CONFIG_SERIAL_TXX9_CONSOLE
+                       req.membase = ioremap(req.mapbase, 0x24);
+ #endif
+-                      req.irq = irq_create_of_mapping(irq.controller,
+-                              irq.specifier, irq.size);
++                      req.irq = irq_create_of_mapping(irq.np, irq.args, irq.args_count);
+                       req.flags |= UPF_IOREMAP | UPF_BUGGY_UART
+                               /*HAVE_CTS_LINE*/;
+                       req.uartclk = 83300000;
+--- a/arch/powerpc/platforms/cell/spider-pic.c
++++ b/arch/powerpc/platforms/cell/spider-pic.c
+@@ -235,10 +235,10 @@ static unsigned int __init spider_find_c
+       /* First, we check whether we have a real "interrupts" in the device
+        * tree in case the device-tree is ever fixed
+        */
+-      struct of_irq oirq;
++      struct of_phandle_args oirq;
+       if (of_irq_parse_one(pic->host->of_node, 0, &oirq) == 0) {
+-              virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+-                                           oirq.size);
++              virq = irq_create_of_mapping(oirq.np, oirq.args,
++                                           oirq.args_count);
+               return virq;
+       }
+--- a/arch/powerpc/platforms/cell/spu_manage.c
++++ b/arch/powerpc/platforms/cell/spu_manage.c
+@@ -177,7 +177,7 @@ out:
+ static int __init spu_map_interrupts(struct spu *spu, struct device_node *np)
+ {
+-      struct of_irq oirq;
++      struct of_phandle_args oirq;
+       int ret;
+       int i;
+@@ -188,10 +188,10 @@ static int __init spu_map_interrupts(str
+                       goto err;
+               }
+               ret = -EINVAL;
+-              pr_debug("  irq %d no 0x%x on %s\n", i, oirq.specifier[0],
+-                       oirq.controller->full_name);
+-              spu->irqs[i] = irq_create_of_mapping(oirq.controller,
+-                                      oirq.specifier, oirq.size);
++              pr_debug("  irq %d no 0x%x on %s\n", i, oirq.args[0],
++                       oirq.np->full_name);
++              spu->irqs[i] = irq_create_of_mapping(oirq.np,
++                                      oirq.args, oirq.args_count);
+               if (spu->irqs[i] == NO_IRQ) {
+                       pr_debug("spu_new: failed to map it !\n");
+                       goto err;
+@@ -200,7 +200,7 @@ static int __init spu_map_interrupts(str
+       return 0;
+ err:
+-      pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier,
++      pr_debug("failed to map irq %x for spu %s\n", *oirq.args,
+               spu->name);
+       for (; i >= 0; i--) {
+               if (spu->irqs[i] != NO_IRQ)
+--- a/arch/powerpc/platforms/fsl_uli1575.c
++++ b/arch/powerpc/platforms/fsl_uli1575.c
+@@ -321,8 +321,8 @@ static void hpcd_final_uli5288(struct pc
+ {
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+       struct device_node *hosenode = hose ? hose->dn : NULL;
+-      struct of_irq oirq;
+-      int virq, pin = 2;
++      struct of_phandle_args oirq;
++      int pin = 2;
+       u32 laddr[3];
+       if (!machine_is(mpc86xx_hpcd))
+@@ -334,9 +334,7 @@ static void hpcd_final_uli5288(struct pc
+       laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8);
+       laddr[1] = laddr[2] = 0;
+       of_irq_parse_raw(hosenode, &pin, 1, laddr, &oirq);
+-      virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+-                                   oirq.size);
+-      dev->irq = virq;
++      dev->irq = irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
+ }
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, hpcd_quirk_uli1575);
+--- a/arch/powerpc/platforms/powermac/pic.c
++++ b/arch/powerpc/platforms/powermac/pic.c
+@@ -394,7 +394,7 @@ static void __init pmac_pic_probe_oldsty
+ }
+ int of_irq_parse_oldworld(struct device_node *device, int index,
+-                      struct of_irq *out_irq)
++                      struct of_phandle_args *out_irq)
+ {
+       const u32 *ints = NULL;
+       int intlen;
+@@ -422,9 +422,9 @@ int of_irq_parse_oldworld(struct device_
+       if (index >= intlen)
+               return -EINVAL;
+-      out_irq->controller = NULL;
+-      out_irq->specifier[0] = ints[index];
+-      out_irq->size = 1;
++      out_irq->np = NULL;
++      out_irq->args[0] = ints[index];
++      out_irq->args_count = 1;
+       return 0;
+ }
+--- a/arch/powerpc/platforms/pseries/event_sources.c
++++ b/arch/powerpc/platforms/pseries/event_sources.c
+@@ -25,7 +25,7 @@ void request_event_sources_irqs(struct d
+                               const char *name)
+ {
+       int i, index, count = 0;
+-      struct of_irq oirq;
++      struct of_phandle_args oirq;
+       const u32 *opicprop;
+       unsigned int opicplen;
+       unsigned int virqs[16];
+@@ -59,9 +59,8 @@ void request_event_sources_irqs(struct d
+                    index++) {
+                       if (count > 15)
+                               break;
+-                      virqs[count] = irq_create_of_mapping(oirq.controller,
+-                                                          oirq.specifier,
+-                                                          oirq.size);
++                      virqs[count] = irq_create_of_mapping(oirq.np, oirq.args,
++                                                          oirq.args_count);
+                       if (virqs[count] == NO_IRQ) {
+                               pr_err("event-sources: Unable to allocate "
+                                      "interrupt number for %s\n",
+--- a/arch/powerpc/sysdev/mpic_msi.c
++++ b/arch/powerpc/sysdev/mpic_msi.c
+@@ -35,7 +35,7 @@ static int mpic_msi_reserve_u3_hwirqs(st
+       const struct irq_domain_ops *ops = mpic->irqhost->ops;
+       struct device_node *np;
+       int flags, index, i;
+-      struct of_irq oirq;
++      struct of_phandle_args oirq;
+       pr_debug("mpic: found U3, guessing msi allocator setup\n");
+@@ -64,8 +64,8 @@ static int mpic_msi_reserve_u3_hwirqs(st
+               index = 0;
+               while (of_irq_parse_one(np, index++, &oirq) == 0) {
+-                      ops->xlate(mpic->irqhost, NULL, oirq.specifier,
+-                                              oirq.size, &hwirq, &flags);
++                      ops->xlate(mpic->irqhost, NULL, oirq.args,
++                                              oirq.args_count, &hwirq, &flags);
+                       msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq);
+               }
+       }
+--- a/arch/x86/kernel/devicetree.c
++++ b/arch/x86/kernel/devicetree.c
+@@ -106,7 +106,7 @@ struct device_node *pcibios_get_phb_of_n
+ static int x86_of_pci_irq_enable(struct pci_dev *dev)
+ {
+-      struct of_irq oirq;
++      struct of_phandle_args oirq;
+       u32 virq;
+       int ret;
+       u8 pin;
+@@ -121,8 +121,7 @@ static int x86_of_pci_irq_enable(struct
+       if (ret)
+               return ret;
+-      virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+-                      oirq.size);
++      virq = irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
+       if (virq == 0)
+               return -EINVAL;
+       dev->irq = virq;
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -36,13 +36,12 @@
+  */
+ unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
+ {
+-      struct of_irq oirq;
++      struct of_phandle_args oirq;
+       if (of_irq_parse_one(dev, index, &oirq))
+               return 0;
+-      return irq_create_of_mapping(oirq.controller, oirq.specifier,
+-                                   oirq.size);
++      return irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
+ }
+ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
+@@ -94,7 +93,7 @@ struct device_node *of_irq_find_parent(s
+  * node exist for the parent.
+  */
+ int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec,
+-                 u32 ointsize, const __be32 *addr, struct of_irq *out_irq)
++                 u32 ointsize, const __be32 *addr, struct of_phandle_args *out_irq)
+ {
+       struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
+       const __be32 *tmp, *imap, *imask;
+@@ -156,10 +155,10 @@ int of_irq_parse_raw(struct device_node
+                               NULL) {
+                       pr_debug(" -> got it !\n");
+                       for (i = 0; i < intsize; i++)
+-                              out_irq->specifier[i] =
++                              out_irq->args[i] =
+                                               of_read_number(intspec +i, 1);
+-                      out_irq->size = intsize;
+-                      out_irq->controller = ipar;
++                      out_irq->args_count = intsize;
++                      out_irq->np = ipar;
+                       of_node_put(old);
+                       return 0;
+               }
+@@ -280,7 +279,7 @@ EXPORT_SYMBOL_GPL(of_irq_parse_raw);
+  * This function resolves an interrupt, walking the tree, for a given
+  * device-tree node. It's the high level pendant to of_irq_parse_raw().
+  */
+-int of_irq_parse_one(struct device_node *device, int index, struct of_irq *out_irq)
++int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq)
+ {
+       struct device_node *p;
+       const __be32 *intspec, *tmp, *addr;
+--- a/drivers/of/of_pci_irq.c
++++ b/drivers/of/of_pci_irq.c
+@@ -15,7 +15,7 @@
+  * PCI tree until an device-node is found, at which point it will finish
+  * resolving using the OF tree walking.
+  */
+-int of_irq_parse_pci(const struct pci_dev *pdev, struct of_irq *out_irq)
++int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
+ {
+       struct device_node *dn, *ppnode;
+       struct pci_dev *ppdev;
+--- a/drivers/pci/host/pci-mvebu.c
++++ b/drivers/pci/host/pci-mvebu.c
+@@ -649,15 +649,14 @@ static int __init mvebu_pcie_setup(int n
+ static int __init mvebu_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+ {
+-      struct of_irq oirq;
++      struct of_phandle_args oirq;
+       int ret;
+       ret = of_irq_parse_pci(dev, &oirq);
+       if (ret)
+               return ret;
+-      return irq_create_of_mapping(oirq.controller, oirq.specifier,
+-                                   oirq.size);
++      return irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
+ }
+ static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
+--- a/include/linux/of_irq.h
++++ b/include/linux/of_irq.h
+@@ -8,22 +8,6 @@
+ #include <linux/ioport.h>
+ #include <linux/of.h>
+-/**
+- * of_irq - container for device_node/irq_specifier pair for an irq controller
+- * @controller: pointer to interrupt controller device tree node
+- * @size: size of interrupt specifier
+- * @specifier: array of cells @size long specifing the specific interrupt
+- *
+- * This structure is returned when an interrupt is mapped. The controller
+- * field needs to be put() after use
+- */
+-#define OF_MAX_IRQ_SPEC               4 /* We handle specifiers of at most 4 cells */
+-struct of_irq {
+-      struct device_node *controller; /* Interrupt controller node */
+-      u32 size; /* Specifier size */
+-      u32 specifier[OF_MAX_IRQ_SPEC]; /* Specifier copy */
+-};
+-
+ typedef int (*of_irq_init_cb_t)(struct device_node *, struct device_node *);
+ /*
+@@ -36,12 +20,12 @@ typedef int (*of_irq_init_cb_t)(struct d
+ extern unsigned int of_irq_workarounds;
+ extern struct device_node *of_irq_dflt_pic;
+ extern int of_irq_parse_oldworld(struct device_node *device, int index,
+-                             struct of_irq *out_irq);
++                             struct of_phandle_args *out_irq);
+ #else /* CONFIG_PPC32 && CONFIG_PPC_PMAC */
+ #define of_irq_workarounds (0)
+ #define of_irq_dflt_pic (NULL)
+ static inline int of_irq_parse_oldworld(struct device_node *device, int index,
+-                                    struct of_irq *out_irq)
++                                    struct of_phandle_args *out_irq)
+ {
+       return -EINVAL;
+ }
+@@ -50,9 +34,9 @@ static inline int of_irq_parse_oldworld(
+ extern int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec,
+                         u32 ointsize, const __be32 *addr,
+-                        struct of_irq *out_irq);
++                        struct of_phandle_args *out_irq);
+ extern int of_irq_parse_one(struct device_node *device, int index,
+-                        struct of_irq *out_irq);
++                        struct of_phandle_args *out_irq);
+ extern unsigned int irq_create_of_mapping(struct device_node *controller,
+                                         const u32 *intspec,
+                                         unsigned int intsize);
+--- a/include/linux/of_pci.h
++++ b/include/linux/of_pci.h
+@@ -5,8 +5,8 @@
+ #include <linux/msi.h>
+ struct pci_dev;
+-struct of_irq;
+-int of_irq_parse_pci(const struct pci_dev *pdev, struct of_irq *out_irq);
++struct of_phandle_args;
++int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq);
+ struct device_node;
+ struct device_node *of_pci_find_child_device(struct device_node *parent,
diff --git a/target/linux/mvebu/patches-3.10/0185-of-irq-simplify-args-to-irq_create_of_mapping.patch b/target/linux/mvebu/patches-3.10/0185-of-irq-simplify-args-to-irq_create_of_mapping.patch
new file mode 100644 (file)
index 0000000..2de7e7b
--- /dev/null
@@ -0,0 +1,245 @@
+From 5e69ff59f7e51ddfde0b31587beb9e40ea1c85bc Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@linaro.org>
+Date: Thu, 19 Dec 2013 09:30:56 -0300
+Subject: [PATCH 185/203] of/irq: simplify args to irq_create_of_mapping
+
+All the callers of irq_create_of_mapping() pass the contents of a struct
+of_phandle_args structure to the function. Since all the callers already
+have an of_phandle_args pointer, why not pass it directly to
+irq_create_of_mapping()?
+
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+Acked-by: Michal Simek <monstr@monstr.eu>
+Acked-by: Tony Lindgren <tony@atomide.com>
+Cc: Thomas Gleixner <tglx@linutronix.de>
+Cc: Russell King <linux@arm.linux.org.uk>
+Cc: Ralf Baechle <ralf@linux-mips.org>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+
+Conflicts:
+       arch/mips/pci/pci-rt3883.c
+       kernel/irq/irqdomain.c
+---
+ arch/arm/mach-integrator/pci_v3.c              |  2 +-
+ arch/microblaze/pci/pci-common.c               |  2 +-
+ arch/mips/pci/fixup-lantiq.c                   |  2 +-
+ arch/powerpc/kernel/pci-common.c               |  2 +-
+ arch/powerpc/platforms/cell/celleb_scc_pciex.c |  2 +-
+ arch/powerpc/platforms/cell/celleb_scc_sio.c   |  2 +-
+ arch/powerpc/platforms/cell/spider-pic.c       |  7 ++-----
+ arch/powerpc/platforms/cell/spu_manage.c       |  3 +--
+ arch/powerpc/platforms/fsl_uli1575.c           |  2 +-
+ arch/powerpc/platforms/pseries/event_sources.c |  3 +--
+ arch/x86/kernel/devicetree.c                   |  2 +-
+ drivers/of/irq.c                               |  2 +-
+ drivers/pci/host/pci-mvebu.c                   |  2 +-
+ include/linux/of_irq.h                         |  4 +---
+ kernel/irq/irqdomain.c                         | 15 +++++++--------
+ 15 files changed, 22 insertions(+), 30 deletions(-)
+
+--- a/arch/arm/mach-integrator/pci_v3.c
++++ b/arch/arm/mach-integrator/pci_v3.c
+@@ -694,7 +694,7 @@ static int __init pci_v3_map_irq_dt(cons
+               return 0;
+       }
+-      return irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
++      return irq_create_of_mapping(&oirq);
+ }
+ static int __init pci_v3_dtprobe(struct platform_device *pdev,
+--- a/arch/microblaze/pci/pci-common.c
++++ b/arch/microblaze/pci/pci-common.c
+@@ -246,7 +246,7 @@ int pci_read_irq_line(struct pci_dev *pc
+                        oirq.args_count, oirq.args[0], oirq.args[1],
+                        of_node_full_name(oirq.np));
+-              virq = irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
++              virq = irq_create_of_mapping(&oirq);
+       }
+       if (!virq) {
+               pr_debug(" Failed to map !\n");
+--- a/arch/mips/pci/fixup-lantiq.c
++++ b/arch/mips/pci/fixup-lantiq.c
+@@ -33,7 +33,7 @@ int __init pcibios_map_irq(const struct
+                       slot, pin);
+               return 0;
+       }
+-      irq = irq_create_of_mapping(dev_irq.np, dev_irq.args, dev_irq.args_count);
++      irq = irq_create_of_mapping(&dev_irq);
+       dev_info(&dev->dev, "SLOT:%d PIN:%d IRQ:%d\n", slot, pin, irq);
+       return irq;
+ }
+--- a/arch/powerpc/kernel/pci-common.c
++++ b/arch/powerpc/kernel/pci-common.c
+@@ -266,7 +266,7 @@ static int pci_read_irq_line(struct pci_
+                        oirq.args_count, oirq.args[0], oirq.args[1],
+                        of_node_full_name(oirq.np));
+-              virq = irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
++              virq = irq_create_of_mapping(&oirq);
+       }
+       if(virq == NO_IRQ) {
+               pr_debug(" Failed to map !\n");
+--- a/arch/powerpc/platforms/cell/celleb_scc_pciex.c
++++ b/arch/powerpc/platforms/cell/celleb_scc_pciex.c
+@@ -511,7 +511,7 @@ static __init int celleb_setup_pciex(str
+               pr_err("PCIEXC:Failed to map irq\n");
+               goto error;
+       }
+-      virq = irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
++      virq = irq_create_of_mapping(&oirq);
+       if (request_irq(virq, pciex_handle_internal_irq,
+                       0, "pciex", (void *)phb)) {
+               pr_err("PCIEXC:Failed to request irq\n");
+--- a/arch/powerpc/platforms/cell/celleb_scc_sio.c
++++ b/arch/powerpc/platforms/cell/celleb_scc_sio.c
+@@ -66,7 +66,7 @@ static int __init txx9_serial_init(void)
+ #ifdef CONFIG_SERIAL_TXX9_CONSOLE
+                       req.membase = ioremap(req.mapbase, 0x24);
+ #endif
+-                      req.irq = irq_create_of_mapping(irq.np, irq.args, irq.args_count);
++                      req.irq = irq_create_of_mapping(&irq);
+                       req.flags |= UPF_IOREMAP | UPF_BUGGY_UART
+                               /*HAVE_CTS_LINE*/;
+                       req.uartclk = 83300000;
+--- a/arch/powerpc/platforms/cell/spider-pic.c
++++ b/arch/powerpc/platforms/cell/spider-pic.c
+@@ -236,11 +236,8 @@ static unsigned int __init spider_find_c
+        * tree in case the device-tree is ever fixed
+        */
+       struct of_phandle_args oirq;
+-      if (of_irq_parse_one(pic->host->of_node, 0, &oirq) == 0) {
+-              virq = irq_create_of_mapping(oirq.np, oirq.args,
+-                                           oirq.args_count);
+-              return virq;
+-      }
++      if (of_irq_parse_one(pic->host->of_node, 0, &oirq) == 0)
++              return irq_create_of_mapping(&oirq);
+       /* Now do the horrible hacks */
+       tmp = of_get_property(pic->host->of_node, "#interrupt-cells", NULL);
+--- a/arch/powerpc/platforms/cell/spu_manage.c
++++ b/arch/powerpc/platforms/cell/spu_manage.c
+@@ -190,8 +190,7 @@ static int __init spu_map_interrupts(str
+               ret = -EINVAL;
+               pr_debug("  irq %d no 0x%x on %s\n", i, oirq.args[0],
+                        oirq.np->full_name);
+-              spu->irqs[i] = irq_create_of_mapping(oirq.np,
+-                                      oirq.args, oirq.args_count);
++              spu->irqs[i] = irq_create_of_mapping(&oirq);
+               if (spu->irqs[i] == NO_IRQ) {
+                       pr_debug("spu_new: failed to map it !\n");
+                       goto err;
+--- a/arch/powerpc/platforms/fsl_uli1575.c
++++ b/arch/powerpc/platforms/fsl_uli1575.c
+@@ -334,7 +334,7 @@ static void hpcd_final_uli5288(struct pc
+       laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8);
+       laddr[1] = laddr[2] = 0;
+       of_irq_parse_raw(hosenode, &pin, 1, laddr, &oirq);
+-      dev->irq = irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
++      dev->irq = irq_create_of_mapping(&oirq);
+ }
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, hpcd_quirk_uli1575);
+--- a/arch/powerpc/platforms/pseries/event_sources.c
++++ b/arch/powerpc/platforms/pseries/event_sources.c
+@@ -59,8 +59,7 @@ void request_event_sources_irqs(struct d
+                    index++) {
+                       if (count > 15)
+                               break;
+-                      virqs[count] = irq_create_of_mapping(oirq.np, oirq.args,
+-                                                          oirq.args_count);
++                      virqs[count] = irq_create_of_mapping(&oirq);
+                       if (virqs[count] == NO_IRQ) {
+                               pr_err("event-sources: Unable to allocate "
+                                      "interrupt number for %s\n",
+--- a/arch/x86/kernel/devicetree.c
++++ b/arch/x86/kernel/devicetree.c
+@@ -121,7 +121,7 @@ static int x86_of_pci_irq_enable(struct
+       if (ret)
+               return ret;
+-      virq = irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
++      virq = irq_create_of_mapping(&oirq);
+       if (virq == 0)
+               return -EINVAL;
+       dev->irq = virq;
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -41,7 +41,7 @@ unsigned int irq_of_parse_and_map(struct
+       if (of_irq_parse_one(dev, index, &oirq))
+               return 0;
+-      return irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
++      return irq_create_of_mapping(&oirq);
+ }
+ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
+--- a/drivers/pci/host/pci-mvebu.c
++++ b/drivers/pci/host/pci-mvebu.c
+@@ -656,7 +656,7 @@ static int __init mvebu_pcie_map_irq(con
+       if (ret)
+               return ret;
+-      return irq_create_of_mapping(oirq.np, oirq.args, oirq.args_count);
++      return irq_create_of_mapping(&oirq);
+ }
+ static struct pci_bus *mvebu_pcie_scan_bus(int nr, struct pci_sys_data *sys)
+--- a/include/linux/of_irq.h
++++ b/include/linux/of_irq.h
+@@ -37,9 +37,7 @@ extern int of_irq_parse_raw(struct devic
+                         struct of_phandle_args *out_irq);
+ extern int of_irq_parse_one(struct device_node *device, int index,
+                         struct of_phandle_args *out_irq);
+-extern unsigned int irq_create_of_mapping(struct device_node *controller,
+-                                        const u32 *intspec,
+-                                        unsigned int intsize);
++extern unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data);
+ extern int of_irq_to_resource(struct device_node *dev, int index,
+                             struct resource *r);
+ extern int of_irq_count(struct device_node *dev);
+--- a/kernel/irq/irqdomain.c
++++ b/kernel/irq/irqdomain.c
+@@ -655,15 +655,14 @@ int irq_create_strict_mappings(struct ir
+ }
+ EXPORT_SYMBOL_GPL(irq_create_strict_mappings);
+-unsigned int irq_create_of_mapping(struct device_node *controller,
+-                                 const u32 *intspec, unsigned int intsize)
++unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
+ {
+       struct irq_domain *domain;
+       irq_hw_number_t hwirq;
+       unsigned int type = IRQ_TYPE_NONE;
+       unsigned int virq;
+-      domain = controller ? irq_find_host(controller) : irq_default_domain;
++      domain = irq_data->np ? irq_find_host(irq_data->np) : irq_default_domain;
+       if (!domain) {
+ #ifdef CONFIG_MIPS
+               /*
+@@ -677,17 +676,17 @@ unsigned int irq_create_of_mapping(struc
+               if (intsize > 0)
+                       return intspec[0];
+ #endif
+-              pr_warning("no irq domain found for %s !\n",
+-                         of_node_full_name(controller));
++              pr_warn("no irq domain found for %s !\n",
++                      of_node_full_name(irq_data->np));
+               return 0;
+       }
+       /* If domain has no translation, then we assume interrupt line */
+       if (domain->ops->xlate == NULL)
+-              hwirq = intspec[0];
++              hwirq = irq_data->args[0];
+       else {
+-              if (domain->ops->xlate(domain, controller, intspec, intsize,
+-                                   &hwirq, &type))
++              if (domain->ops->xlate(domain, irq_data->np, irq_data->args,
++                                      irq_data->args_count, &hwirq, &type))
+                       return 0;
+       }
diff --git a/target/linux/mvebu/patches-3.10/0186-of-irq-Refactor-interrupt-map-parsing.patch b/target/linux/mvebu/patches-3.10/0186-of-irq-Refactor-interrupt-map-parsing.patch
new file mode 100644 (file)
index 0000000..7f17bb7
--- /dev/null
@@ -0,0 +1,287 @@
+From 44ad702902e9e274f57edce8944e46540b978f9a Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@linaro.org>
+Date: Thu, 19 Dec 2013 09:30:57 -0300
+Subject: [PATCH 186/203] of/irq: Refactor interrupt-map parsing
+
+All the users of of_irq_parse_raw pass in a raw interrupt specifier from
+the device tree and expect it to be returned (possibly modified) in an
+of_phandle_args structure. However, the primary function of
+of_irq_parse_raw() is to check for translations due to the presence of
+one or more interrupt-map properties. The actual placing of the data
+into an of_phandle_args structure is trivial. If it is refactored to
+accept an of_phandle_args structure directly, then it becomes possible
+to consume of_phandle_args from other sources. This is important for an
+upcoming patch that allows a device to be connected to more than one
+interrupt parent. It also simplifies the code a bit.
+
+The biggest complication with this patch is that the old version works
+on the interrupt specifiers in __be32 form, but the of_phandle_args
+structure is intended to carry it in the cpu-native version. A bit of
+churn was required to make this work. In the end it results in tighter
+code, so the churn is worth it.
+
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+Acked-by: Tony Lindgren <tony@atomide.com>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+---
+ arch/powerpc/platforms/fsl_uli1575.c |   6 +-
+ drivers/of/irq.c                     | 108 ++++++++++++++++++-----------------
+ drivers/of/of_pci_irq.c              |   7 ++-
+ include/linux/of_irq.h               |   5 +-
+ 4 files changed, 67 insertions(+), 59 deletions(-)
+
+--- a/arch/powerpc/platforms/fsl_uli1575.c
++++ b/arch/powerpc/platforms/fsl_uli1575.c
+@@ -322,7 +322,6 @@ static void hpcd_final_uli5288(struct pc
+       struct pci_controller *hose = pci_bus_to_host(dev->bus);
+       struct device_node *hosenode = hose ? hose->dn : NULL;
+       struct of_phandle_args oirq;
+-      int pin = 2;
+       u32 laddr[3];
+       if (!machine_is(mpc86xx_hpcd))
+@@ -331,9 +330,12 @@ static void hpcd_final_uli5288(struct pc
+       if (!hosenode)
+               return;
++      oirq.np = hosenode;
++      oirq.args[0] = 2;
++      oirq.args_count = 1;
+       laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8);
+       laddr[1] = laddr[2] = 0;
+-      of_irq_parse_raw(hosenode, &pin, 1, laddr, &oirq);
++      of_irq_parse_raw(laddr, &oirq);
+       dev->irq = irq_create_of_mapping(&oirq);
+ }
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -80,31 +80,32 @@ struct device_node *of_irq_find_parent(s
+ /**
+  * of_irq_parse_raw - Low level interrupt tree parsing
+  * @parent:   the device interrupt parent
+- * @intspec:  interrupt specifier ("interrupts" property of the device)
+- * @ointsize:   size of the passed in interrupt specifier
+- * @addr:     address specifier (start of "reg" property of the device)
+- * @out_irq:  structure of_irq filled by this function
++ * @addr:     address specifier (start of "reg" property of the device) in be32 format
++ * @out_irq:  structure of_irq updated by this function
+  *
+  * Returns 0 on success and a negative number on error
+  *
+  * This function is a low-level interrupt tree walking function. It
+  * can be used to do a partial walk with synthetized reg and interrupts
+  * properties, for example when resolving PCI interrupts when no device
+- * node exist for the parent.
++ * node exist for the parent. It takes an interrupt specifier structure as
++ * input, walks the tree looking for any interrupt-map properties, translates
++ * the specifier for each map, and then returns the translated map.
+  */
+-int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec,
+-                 u32 ointsize, const __be32 *addr, struct of_phandle_args *out_irq)
++int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
+ {
+       struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
+-      const __be32 *tmp, *imap, *imask;
++      __be32 initial_match_array[8];
++      const __be32 *match_array = initial_match_array;
++      const __be32 *tmp, *imap, *imask, dummy_imask[] = { ~0, ~0, ~0, ~0, ~0 };
+       u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
+       int imaplen, match, i;
+       pr_debug("of_irq_parse_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
+-               of_node_full_name(parent), be32_to_cpup(intspec),
+-               be32_to_cpup(intspec + 1), ointsize);
++               of_node_full_name(out_irq->np), out_irq->args[0], out_irq->args[1],
++               out_irq->args_count);
+-      ipar = of_node_get(parent);
++      ipar = of_node_get(out_irq->np);
+       /* First get the #interrupt-cells property of the current cursor
+        * that tells us how to interpret the passed-in intspec. If there
+@@ -127,7 +128,7 @@ int of_irq_parse_raw(struct device_node
+       pr_debug("of_irq_parse_raw: ipar=%s, size=%d\n", of_node_full_name(ipar), intsize);
+-      if (ointsize != intsize)
++      if (out_irq->args_count != intsize)
+               return -EINVAL;
+       /* Look for this #address-cells. We have to implement the old linux
+@@ -146,6 +147,21 @@ int of_irq_parse_raw(struct device_node
+       pr_debug(" -> addrsize=%d\n", addrsize);
++      /* If we were passed no "reg" property and we attempt to parse
++       * an interrupt-map, then #address-cells must be 0.
++       * Fail if it's not.
++       */
++      if (addr == NULL && addrsize != 0) {
++              pr_debug(" -> no reg passed in when needed !\n");
++              return -EINVAL;
++      }
++
++      /* Precalculate the match array - this simplifies match loop */
++      for (i = 0; i < addrsize; i++)
++              initial_match_array[i] = addr[i];
++      for (i = 0; i < intsize; i++)
++              initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]);
++
+       /* Now start the actual "proper" walk of the interrupt tree */
+       while (ipar != NULL) {
+               /* Now check if cursor is an interrupt-controller and if it is
+@@ -154,11 +170,6 @@ int of_irq_parse_raw(struct device_node
+               if (of_get_property(ipar, "interrupt-controller", NULL) !=
+                               NULL) {
+                       pr_debug(" -> got it !\n");
+-                      for (i = 0; i < intsize; i++)
+-                              out_irq->args[i] =
+-                                              of_read_number(intspec +i, 1);
+-                      out_irq->args_count = intsize;
+-                      out_irq->np = ipar;
+                       of_node_put(old);
+                       return 0;
+               }
+@@ -175,34 +186,16 @@ int of_irq_parse_raw(struct device_node
+               /* Look for a mask */
+               imask = of_get_property(ipar, "interrupt-map-mask", NULL);
+-
+-              /* If we were passed no "reg" property and we attempt to parse
+-               * an interrupt-map, then #address-cells must be 0.
+-               * Fail if it's not.
+-               */
+-              if (addr == NULL && addrsize != 0) {
+-                      pr_debug(" -> no reg passed in when needed !\n");
+-                      goto fail;
+-              }
++              if (!imask)
++                      imask = dummy_imask;
+               /* Parse interrupt-map */
+               match = 0;
+               while (imaplen > (addrsize + intsize + 1) && !match) {
+                       /* Compare specifiers */
+                       match = 1;
+-                      for (i = 0; i < addrsize && match; ++i) {
+-                              __be32 mask = imask ? imask[i]
+-                                                  : cpu_to_be32(0xffffffffu);
+-                              match = ((addr[i] ^ imap[i]) & mask) == 0;
+-                      }
+-                      for (; i < (addrsize + intsize) && match; ++i) {
+-                              __be32 mask = imask ? imask[i]
+-                                                  : cpu_to_be32(0xffffffffu);
+-                              match =
+-                                 ((intspec[i-addrsize] ^ imap[i]) & mask) == 0;
+-                      }
+-                      imap += addrsize + intsize;
+-                      imaplen -= addrsize + intsize;
++                      for (i = 0; i < (addrsize + intsize); i++, imaplen--)
++                              match = !((match_array[i] ^ *imap++) & imask[i]);
+                       pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen);
+@@ -247,12 +240,18 @@ int of_irq_parse_raw(struct device_node
+               if (!match)
+                       goto fail;
+-              of_node_put(old);
+-              old = of_node_get(newpar);
++              /*
++               * Successfully parsed an interrrupt-map translation; copy new
++               * interrupt specifier into the out_irq structure
++               */
++              of_node_put(out_irq->np);
++              out_irq->np = of_node_get(newpar);
++
++              match_array = imap - newaddrsize - newintsize;
++              for (i = 0; i < newintsize; i++)
++                      out_irq->args[i] = be32_to_cpup(imap - newintsize + i);
++              out_irq->args_count = intsize = newintsize;
+               addrsize = newaddrsize;
+-              intsize = newintsize;
+-              intspec = imap - intsize;
+-              addr = intspec - addrsize;
+       skiplevel:
+               /* Iterate again with new parent */
+@@ -263,7 +262,7 @@ int of_irq_parse_raw(struct device_node
+       }
+  fail:
+       of_node_put(ipar);
+-      of_node_put(old);
++      of_node_put(out_irq->np);
+       of_node_put(newpar);
+       return -EINVAL;
+@@ -276,15 +275,16 @@ EXPORT_SYMBOL_GPL(of_irq_parse_raw);
+  * @index: index of the interrupt to resolve
+  * @out_irq: structure of_irq filled by this function
+  *
+- * This function resolves an interrupt, walking the tree, for a given
+- * device-tree node. It's the high level pendant to of_irq_parse_raw().
++ * This function resolves an interrupt for a node by walking the interrupt tree,
++ * finding which interrupt controller node it is attached to, and returning the
++ * interrupt specifier that can be used to retrieve a Linux IRQ number.
+  */
+ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq)
+ {
+       struct device_node *p;
+       const __be32 *intspec, *tmp, *addr;
+       u32 intsize, intlen;
+-      int res = -EINVAL;
++      int i, res = -EINVAL;
+       pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index);
+@@ -326,9 +326,15 @@ int of_irq_parse_one(struct device_node
+       if ((index + 1) * intsize > intlen)
+               goto out;
+-      /* Get new specifier and map it */
+-      res = of_irq_parse_raw(p, intspec + index * intsize, intsize,
+-                           addr, out_irq);
++      /* Copy intspec into irq structure */
++      intspec += index * intsize;
++      out_irq->np = p;
++      out_irq->args_count = intsize;
++      for (i = 0; i < intsize; i++)
++              out_irq->args[i] = be32_to_cpup(intspec++);
++
++      /* Check if there are any interrupt-map translations to process */
++      res = of_irq_parse_raw(addr, out_irq);
+  out:
+       of_node_put(p);
+       return res;
+--- a/drivers/of/of_pci_irq.c
++++ b/drivers/of/of_pci_irq.c
+@@ -85,9 +85,12 @@ int of_irq_parse_pci(const struct pci_de
+               pdev = ppdev;
+       }
++      out_irq->np = ppnode;
++      out_irq->args_count = 1;
++      out_irq->args[0] = lspec;
+       lspec_be = cpu_to_be32(lspec);
+       laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
+-      laddr[1]  = laddr[2] = cpu_to_be32(0);
+-      return of_irq_parse_raw(ppnode, &lspec_be, 1, laddr, out_irq);
++      laddr[1] = laddr[2] = cpu_to_be32(0);
++      return of_irq_parse_raw(laddr, out_irq);
+ }
+ EXPORT_SYMBOL_GPL(of_irq_parse_pci);
+--- a/include/linux/of_irq.h
++++ b/include/linux/of_irq.h
+@@ -31,10 +31,7 @@ static inline int of_irq_parse_oldworld(
+ }
+ #endif /* CONFIG_PPC32 && CONFIG_PPC_PMAC */
+-
+-extern int of_irq_parse_raw(struct device_node *parent, const __be32 *intspec,
+-                        u32 ointsize, const __be32 *addr,
+-                        struct of_phandle_args *out_irq);
++extern int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq);
+ extern int of_irq_parse_one(struct device_node *device, int index,
+                         struct of_phandle_args *out_irq);
+ extern unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data);
diff --git a/target/linux/mvebu/patches-3.10/0187-of-Add-helper-for-printing-an-of_phandle_args-struct.patch b/target/linux/mvebu/patches-3.10/0187-of-Add-helper-for-printing-an-of_phandle_args-struct.patch
new file mode 100644 (file)
index 0000000..064e9a2
--- /dev/null
@@ -0,0 +1,62 @@
+From 061855025b6842debdf6ea2e8bfd86f50700e263 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@linaro.org>
+Date: Thu, 19 Dec 2013 09:30:58 -0300
+Subject: [PATCH 187/203] of: Add helper for printing an of_phandle_args
+ structure
+
+It is sometimes useful for debug to get the contents of an
+of_phandle_args structure out into the kernel log.
+
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+
+Conflicts:
+       drivers/of/base.c
+---
+ drivers/of/base.c  | 9 +++++++++
+ drivers/of/irq.c   | 6 +++---
+ include/linux/of.h | 1 +
+ 3 files changed, 13 insertions(+), 3 deletions(-)
+
+--- a/drivers/of/base.c
++++ b/drivers/of/base.c
+@@ -1136,6 +1136,15 @@ EXPORT_SYMBOL(of_parse_phandle);
+  * To get a device_node of the `node2' node you may call this:
+  * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
+  */
++void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
++{
++      int i;
++      printk("%s %s", msg, of_node_full_name(args->np));
++      for (i = 0; i < args->args_count; i++)
++              printk(i ? ",%08x" : ":%08x", args->args[i]);
++      printk("\n");
++}
++
+ static int __of_parse_phandle_with_args(const struct device_node *np,
+                                       const char *list_name,
+                                       const char *cells_name, int index,
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -101,9 +101,9 @@ int of_irq_parse_raw(const __be32 *addr,
+       u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
+       int imaplen, match, i;
+-      pr_debug("of_irq_parse_raw: par=%s,intspec=[0x%08x 0x%08x...],ointsize=%d\n",
+-               of_node_full_name(out_irq->np), out_irq->args[0], out_irq->args[1],
+-               out_irq->args_count);
++#ifdef DEBUG
++      of_print_phandle_args("of_irq_parse_raw: ", out_irq);
++#endif
+       ipar = of_node_get(out_irq->np);
+--- a/include/linux/of.h
++++ b/include/linux/of.h
+@@ -274,6 +274,7 @@ extern int of_n_size_cells(struct device
+ extern const struct of_device_id *of_match_node(
+       const struct of_device_id *matches, const struct device_node *node);
+ extern int of_modalias_node(struct device_node *node, char *modalias, int len);
++extern void of_print_phandle_args(const char *msg, const struct of_phandle_args *args);
+ extern struct device_node *of_parse_phandle(const struct device_node *np,
+                                           const char *phandle_name,
+                                           int index);
diff --git a/target/linux/mvebu/patches-3.10/0188-of-irq-Rework-of_irq_count.patch b/target/linux/mvebu/patches-3.10/0188-of-irq-Rework-of_irq_count.patch
new file mode 100644 (file)
index 0000000..39fc794
--- /dev/null
@@ -0,0 +1,36 @@
+From 3665853921092bb68aa0929efb3a94ecdfc96782 Mon Sep 17 00:00:00 2001
+From: Thierry Reding <thierry.reding@gmail.com>
+Date: Thu, 19 Dec 2013 09:30:59 -0300
+Subject: [PATCH 188/203] of/irq: Rework of_irq_count()
+
+The of_irq_to_resource() helper that is used to implement of_irq_count()
+tries to resolve interrupts and in fact creates a mapping for resolved
+interrupts. That's pretty heavy lifting for something that claims to
+just return the number of interrupts requested by a given device node.
+
+Instead, use the more lightweight of_irq_map_one(), which, despite the
+name, doesn't create an actual mapping. Perhaps a better name would be
+of_irq_translate_one().
+
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Acked-by: Rob Herring <rob.herring@calxeda.com>
+[grant.likely: fixup s/of_irq_map_one/of_irq_parse_one/]
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+---
+ drivers/of/irq.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -379,9 +379,10 @@ EXPORT_SYMBOL_GPL(of_irq_to_resource);
+  */
+ int of_irq_count(struct device_node *dev)
+ {
++      struct of_phandle_args irq;
+       int nr = 0;
+-      while (of_irq_to_resource(dev, nr, NULL))
++      while (of_irq_parse_one(dev, nr, &irq) == 0)
+               nr++;
+       return nr;
diff --git a/target/linux/mvebu/patches-3.10/0189-of-irq-create-interrupts-extended-property.patch b/target/linux/mvebu/patches-3.10/0189-of-irq-create-interrupts-extended-property.patch
new file mode 100644 (file)
index 0000000..7e2e2ba
--- /dev/null
@@ -0,0 +1,192 @@
+From efd4032754a57bc258eafe30fde684ec47dc36e1 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@linaro.org>
+Date: Thu, 19 Dec 2013 09:31:00 -0300
+Subject: [PATCH 189/203] of/irq: create interrupts-extended property
+
+The standard interrupts property in device tree can only handle
+interrupts coming from a single interrupt parent. If a device is wired
+to multiple interrupt controllers, then it needs to be attached to a
+node with an interrupt-map property to demux the interrupt specifiers
+which is confusing. It would be a lot easier if there was a form of the
+interrupts property that allows for a separate interrupt phandle for
+each interrupt specifier.
+
+This patch does exactly that by creating a new interrupts-extended
+property which reuses the phandle+arguments pattern used by GPIOs and
+other core bindings.
+
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+Acked-by: Tony Lindgren <tony@atomide.com>
+Acked-by: Kumar Gala <galak@codeaurora.org>
+[grant.likely: removed versatile platform hunks into separate patch]
+Cc: Rob Herring <rob.herring@calxeda.com>
+
+Conflicts:
+       arch/arm/boot/dts/testcases/tests-interrupts.dtsi
+       drivers/of/selftest.c
+---
+ drivers/of/selftest.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 145 insertions(+), 1 deletion(-)
+
+--- a/drivers/of/selftest.c
++++ b/drivers/of/selftest.c
+@@ -154,6 +154,147 @@ static void __init of_selftest_property_
+       selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc);
+ }
++static void __init of_selftest_parse_interrupts(void)
++{
++      struct device_node *np;
++      struct of_phandle_args args;
++      int i, rc;
++
++      np = of_find_node_by_path("/testcase-data/interrupts/interrupts0");
++      if (!np) {
++              pr_err("missing testcase data\n");
++              return;
++      }
++
++      for (i = 0; i < 4; i++) {
++              bool passed = true;
++              args.args_count = 0;
++              rc = of_irq_parse_one(np, i, &args);
++
++              passed &= !rc;
++              passed &= (args.args_count == 1);
++              passed &= (args.args[0] == (i + 1));
++
++              selftest(passed, "index %i - data error on node %s rc=%i\n",
++                       i, args.np->full_name, rc);
++      }
++      of_node_put(np);
++
++      np = of_find_node_by_path("/testcase-data/interrupts/interrupts1");
++      if (!np) {
++              pr_err("missing testcase data\n");
++              return;
++      }
++
++      for (i = 0; i < 4; i++) {
++              bool passed = true;
++              args.args_count = 0;
++              rc = of_irq_parse_one(np, i, &args);
++
++              /* Test the values from tests-phandle.dtsi */
++              switch (i) {
++              case 0:
++                      passed &= !rc;
++                      passed &= (args.args_count == 1);
++                      passed &= (args.args[0] == 9);
++                      break;
++              case 1:
++                      passed &= !rc;
++                      passed &= (args.args_count == 3);
++                      passed &= (args.args[0] == 10);
++                      passed &= (args.args[1] == 11);
++                      passed &= (args.args[2] == 12);
++                      break;
++              case 2:
++                      passed &= !rc;
++                      passed &= (args.args_count == 2);
++                      passed &= (args.args[0] == 13);
++                      passed &= (args.args[1] == 14);
++                      break;
++              case 3:
++                      passed &= !rc;
++                      passed &= (args.args_count == 2);
++                      passed &= (args.args[0] == 15);
++                      passed &= (args.args[1] == 16);
++                      break;
++              default:
++                      passed = false;
++              }
++              selftest(passed, "index %i - data error on node %s rc=%i\n",
++                       i, args.np->full_name, rc);
++      }
++      of_node_put(np);
++}
++
++static void __init of_selftest_parse_interrupts_extended(void)
++{
++      struct device_node *np;
++      struct of_phandle_args args;
++      int i, rc;
++
++      np = of_find_node_by_path("/testcase-data/interrupts/interrupts-extended0");
++      if (!np) {
++              pr_err("missing testcase data\n");
++              return;
++      }
++
++      for (i = 0; i < 7; i++) {
++              bool passed = true;
++              rc = of_irq_parse_one(np, i, &args);
++
++              /* Test the values from tests-phandle.dtsi */
++              switch (i) {
++              case 0:
++                      passed &= !rc;
++                      passed &= (args.args_count == 1);
++                      passed &= (args.args[0] == 1);
++                      break;
++              case 1:
++                      passed &= !rc;
++                      passed &= (args.args_count == 3);
++                      passed &= (args.args[0] == 2);
++                      passed &= (args.args[1] == 3);
++                      passed &= (args.args[2] == 4);
++                      break;
++              case 2:
++                      passed &= !rc;
++                      passed &= (args.args_count == 2);
++                      passed &= (args.args[0] == 5);
++                      passed &= (args.args[1] == 6);
++                      break;
++              case 3:
++                      passed &= !rc;
++                      passed &= (args.args_count == 1);
++                      passed &= (args.args[0] == 9);
++                      break;
++              case 4:
++                      passed &= !rc;
++                      passed &= (args.args_count == 3);
++                      passed &= (args.args[0] == 10);
++                      passed &= (args.args[1] == 11);
++                      passed &= (args.args[2] == 12);
++                      break;
++              case 5:
++                      passed &= !rc;
++                      passed &= (args.args_count == 2);
++                      passed &= (args.args[0] == 13);
++                      passed &= (args.args[1] == 14);
++                      break;
++              case 6:
++                      passed &= !rc;
++                      passed &= (args.args_count == 1);
++                      passed &= (args.args[0] == 15);
++                      break;
++              default:
++                      passed = false;
++              }
++
++              selftest(passed, "index %i - data error on node %s rc=%i\n",
++                       i, args.np->full_name, rc);
++      }
++      of_node_put(np);
++}
++
+ static int __init of_selftest(void)
+ {
+       struct device_node *np;
+@@ -168,7 +309,10 @@ static int __init of_selftest(void)
+       pr_info("start of selftest - you will see error messages\n");
+       of_selftest_parse_phandle_with_args();
+       of_selftest_property_match_string();
+-      pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL");
++      of_selftest_parse_interrupts();
++      of_selftest_parse_interrupts_extended();
++      pr_info("end of selftest - %i passed, %i failed\n",
++              selftest_results.passed, selftest_results.failed);
+       return 0;
+ }
+ late_initcall(of_selftest);
diff --git a/target/linux/mvebu/patches-3.10/0190-of-irq-Fix-bug-in-interrupt-parsing-refactor.patch b/target/linux/mvebu/patches-3.10/0190-of-irq-Fix-bug-in-interrupt-parsing-refactor.patch
new file mode 100644 (file)
index 0000000..5e1e605
--- /dev/null
@@ -0,0 +1,60 @@
+From 1c67d6e7cc30a856e79664e0be3a1f705bad56e4 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@linaro.org>
+Date: Thu, 19 Dec 2013 09:31:01 -0300
+Subject: [PATCH 190/203] of/irq: Fix bug in interrupt parsing refactor.
+
+Commit 2361613206e6, "of/irq: Refactor interrupt-map parsing" introduced
+a bug. The irq parsing will fail for some nodes that don't have a reg
+property. It is fixed by deferring the check for reg until it is
+actually needed. Also adjust the testcase data to catch the bug.
+
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+Tested-by: Stephen Warren <swarren@nvidia.com>
+Tested-by: Ming Lei <tom.leiming@gmail.com>
+Tested-by: Stephen Warren <swarren@nvidia.com>
+Cc: Rob Herring <rob.herring@calxeda.com>
+
+Conflicts:
+       arch/arm/boot/dts/testcases/tests-interrupts.dtsi
+---
+ drivers/of/irq.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -147,18 +147,9 @@ int of_irq_parse_raw(const __be32 *addr,
+       pr_debug(" -> addrsize=%d\n", addrsize);
+-      /* If we were passed no "reg" property and we attempt to parse
+-       * an interrupt-map, then #address-cells must be 0.
+-       * Fail if it's not.
+-       */
+-      if (addr == NULL && addrsize != 0) {
+-              pr_debug(" -> no reg passed in when needed !\n");
+-              return -EINVAL;
+-      }
+-
+       /* Precalculate the match array - this simplifies match loop */
+       for (i = 0; i < addrsize; i++)
+-              initial_match_array[i] = addr[i];
++              initial_match_array[i] = addr ? addr[i] : 0;
+       for (i = 0; i < intsize; i++)
+               initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]);
+@@ -174,6 +165,15 @@ int of_irq_parse_raw(const __be32 *addr,
+                       return 0;
+               }
++              /*
++               * interrupt-map parsing does not work without a reg
++               * property when #address-cells != 0
++               */
++              if (addrsize && !addr) {
++                      pr_debug(" -> no reg passed in when needed !\n");
++                      goto fail;
++              }
++
+               /* Now look for an interrupt-map */
+               imap = of_get_property(ipar, "interrupt-map", &imaplen);
+               /* No interrupt map, check for an interrupt parent */
diff --git a/target/linux/mvebu/patches-3.10/0191-of-irq-Fix-potential-buffer-overflow.patch b/target/linux/mvebu/patches-3.10/0191-of-irq-Fix-potential-buffer-overflow.patch
new file mode 100644 (file)
index 0000000..9c7908d
--- /dev/null
@@ -0,0 +1,52 @@
+From 5a1bd82f089e19ba049a871a0d5538ed9eb5e5cd Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@linaro.org>
+Date: Thu, 19 Dec 2013 09:31:02 -0300
+Subject: [PATCH 191/203] of/irq: Fix potential buffer overflow
+
+Commit 2361613206e6, "of/irq: Refactor interrupt-map parsing" introduced
+a potential buffer overflow bug because it doesn't do sufficient range
+checking on the input data. This patch adds the appropriate checking and
+buffer size adjustments. If the bounds are out of range then warn
+loudly. MAX_PHANDLE_ARGS should be sufficient. If it is not then the
+value can be increased.
+
+Signed-off-by: Grant Likely <grant.likely@linaro.org>
+Cc: Rob Herring <rob.herring@calxeda.com>
+---
+ drivers/of/irq.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -95,9 +95,9 @@ struct device_node *of_irq_find_parent(s
+ int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
+ {
+       struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
+-      __be32 initial_match_array[8];
++      __be32 initial_match_array[MAX_PHANDLE_ARGS];
+       const __be32 *match_array = initial_match_array;
+-      const __be32 *tmp, *imap, *imask, dummy_imask[] = { ~0, ~0, ~0, ~0, ~0 };
++      const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 };
+       u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
+       int imaplen, match, i;
+@@ -147,6 +147,10 @@ int of_irq_parse_raw(const __be32 *addr,
+       pr_debug(" -> addrsize=%d\n", addrsize);
++      /* Range check so that the temporary buffer doesn't overflow */
++      if (WARN_ON(addrsize + intsize > MAX_PHANDLE_ARGS))
++              goto fail;
++
+       /* Precalculate the match array - this simplifies match loop */
+       for (i = 0; i < addrsize; i++)
+               initial_match_array[i] = addr ? addr[i] : 0;
+@@ -229,6 +233,8 @@ int of_irq_parse_raw(const __be32 *addr,
+                           newintsize, newaddrsize);
+                       /* Check for malformed properties */
++                      if (WARN_ON(newaddrsize + newintsize > MAX_PHANDLE_ARGS))
++                              goto fail;
+                       if (imaplen < (newaddrsize + newintsize))
+                               goto fail;
diff --git a/target/linux/mvebu/patches-3.10/0192-of-irq-Fix-interrupt-map-entry-matching.patch b/target/linux/mvebu/patches-3.10/0192-of-irq-Fix-interrupt-map-entry-matching.patch
new file mode 100644 (file)
index 0000000..3de0b14
--- /dev/null
@@ -0,0 +1,26 @@
+From 8413f9010508998c62969827850a7434a1d5716c Mon Sep 17 00:00:00 2001
+From: Tomasz Figa <t.figa@samsung.com>
+Date: Thu, 19 Dec 2013 09:31:03 -0300
+Subject: [PATCH 192/203] of: irq: Fix interrupt-map entry matching
+
+This patch fixes interrupt-map entry matching code to properly match all
+specifier cells with interrupt map entries.
+
+Signed-off-by: Tomasz Figa <t.figa@samsung.com>
+Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
+Signed-off-by: Rob Herring <rob.herring@calxeda.com>
+---
+ drivers/of/irq.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/of/irq.c
++++ b/drivers/of/irq.c
+@@ -199,7 +199,7 @@ int of_irq_parse_raw(const __be32 *addr,
+                       /* Compare specifiers */
+                       match = 1;
+                       for (i = 0; i < (addrsize + intsize); i++, imaplen--)
+-                              match = !((match_array[i] ^ *imap++) & imask[i]);
++                              match &= !((match_array[i] ^ *imap++) & imask[i]);
+                       pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen);
diff --git a/target/linux/mvebu/patches-3.10/0193-clocksource-armada-370-xp-Fix-device-tree-binding.patch b/target/linux/mvebu/patches-3.10/0193-clocksource-armada-370-xp-Fix-device-tree-binding.patch
new file mode 100644 (file)
index 0000000..4ee7f3f
--- /dev/null
@@ -0,0 +1,70 @@
+From ba47ab198541f6ed822b3c9691b392d83edba8b4 Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 13 Aug 2013 11:43:14 -0300
+Subject: [PATCH 193/203] clocksource: armada-370-xp: Fix device-tree binding
+
+This commit fixes the DT binding for the Armada 370/XP SoC timer.
+The previous "marvell,armada-370-xp-timer" compatible is removed and
+two new compatible strings are introduced: "marvell,armada-xp-timer"
+and "marvell,armada-370-timer".
+
+The rationale behind this change is that the Armada 370 SoC and the
+Armada XP SoC timers are not really compatible:
+
+  * Armada 370 has no 25 MHz fixed timer.
+
+  * Armada XP cannot work properly without such 25 MHz fixed timer
+    as doing otherwise leads to using a clocksource whose frequency
+    varies when doing cpufreq frequency changes.
+
+This commit also removes the "marvell,timer-25Mhz" property, given
+it's now meaningless.
+
+Cc: devicetree@vger.kernel.org
+Acked-by: Jason Cooper <jason@lakedaemon.net>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+---
+ .../bindings/timer/marvell,armada-370-xp-timer.txt | 27 ++++++++++++++++++----
+ 1 file changed, 22 insertions(+), 5 deletions(-)
+
+--- a/Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt
++++ b/Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt
+@@ -2,14 +2,31 @@ Marvell Armada 370 and Armada XP Timers
+ ---------------------------------------
+ Required properties:
+-- compatible: Should be "marvell,armada-370-xp-timer"
++- compatible: Should be either "marvell,armada-370-timer" or
++  "marvell,armada-xp-timer" as appropriate.
+ - interrupts: Should contain the list of Global Timer interrupts and
+   then local timer interrupts
+ - reg: Should contain location and length for timers register. First
+   pair for the Global Timer registers, second pair for the
+   local/private timers.
+-- clocks: clock driving the timer hardware
++- clocks: clock driving the timer hardware, only required for
++  "marvell,armada-370-timer";
+-Optional properties:
+-- marvell,timer-25Mhz: Tells whether the Global timer supports the 25
+-  Mhz fixed mode (available on Armada XP and not on Armada 370)
++Examples:
++
++- Armada 370:
++
++      timer {
++              compatible = "marvell,armada-370-timer";
++              reg = <0x20300 0x30>, <0x21040 0x30>;
++              interrupts = <37>, <38>, <39>, <40>, <5>, <6>;
++              clocks = <&coreclk 2>;
++      };
++
++- Armada XP:
++
++      timer {
++              compatible = "marvell,armada-xp-timer";
++              reg = <0x20300 0x30>, <0x21040 0x30>;
++              interrupts = <37>, <38>, <39>, <40>, <5>, <6>;
++      };
diff --git a/target/linux/mvebu/patches-3.10/0194-clocksource-armada-370-xp-Add-detailed-clock-require.patch b/target/linux/mvebu/patches-3.10/0194-clocksource-armada-370-xp-Add-detailed-clock-require.patch
new file mode 100644 (file)
index 0000000..333f7b6
--- /dev/null
@@ -0,0 +1,47 @@
+From d569707433b26bb70f6b595a480bcfb3043a614c Mon Sep 17 00:00:00 2001
+From: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Date: Tue, 20 Aug 2013 12:45:54 -0300
+Subject: [PATCH 194/203] clocksource: armada-370-xp: Add detailed clock
+ requirements in devicetree binding
+
+Specifies the required clock inputs for each supported compatible.
+Armada 370 requires a single clock phandle, and Armada XP requires
+two clock phandles with clock-names "nbclk" and "fixed".
+
+Cc: devicetree@vger.kernel.org
+Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
+Acked-by: Jason Cooper <jason@lakedaemon.net>
+Acked-by: Stephen Warren <swarren@nvidia.com>
+Acked-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
+---
+ .../bindings/timer/marvell,armada-370-xp-timer.txt          | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+--- a/Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt
++++ b/Documentation/devicetree/bindings/timer/marvell,armada-370-xp-timer.txt
+@@ -9,8 +9,15 @@ Required properties:
+ - reg: Should contain location and length for timers register. First
+   pair for the Global Timer registers, second pair for the
+   local/private timers.
+-- clocks: clock driving the timer hardware, only required for
+-  "marvell,armada-370-timer";
++
++Clocks required for compatible = "marvell,armada-370-timer":
++- clocks : Must contain a single entry describing the clock input
++
++Clocks required for compatible = "marvell,armada-xp-timer":
++- clocks : Must contain an entry for each entry in clock-names.
++- clock-names : Must include the following entries:
++  "nbclk" (L2/coherency fabric clock),
++  "fixed" (Reference 25 MHz fixed-clock).
+ Examples:
+@@ -29,4 +36,6 @@ Examples:
+               compatible = "marvell,armada-xp-timer";
+               reg = <0x20300 0x30>, <0x21040 0x30>;
+               interrupts = <37>, <38>, <39>, <40>, <5>, <6>;
++              clocks = <&coreclk 2>, <&refclk>;
++              clock-names = "nbclk", "fixed";
+       };
diff --git a/target/linux/mvebu/patches-3.10/0195-usb-Add-Device-Tree-support-to-XHCI-Platform-driver.patch b/target/linux/mvebu/patches-3.10/0195-usb-Add-Device-Tree-support-to-XHCI-Platform-driver.patch
new file mode 100644 (file)
index 0000000..091c3a1
--- /dev/null
@@ -0,0 +1,68 @@
+From 956b857c1fc80164859adbe1147704b1f352e153 Mon Sep 17 00:00:00 2001
+From: Al Cooper <alcooperx@gmail.com>
+Date: Fri, 6 Dec 2013 00:18:25 +0100
+Subject: [PATCH 195/203] usb: Add Device Tree support to XHCI Platform driver
+
+Add Device Tree match table to xhci-plat.c. Add DT bindings document.
+
+Signed-off-by: Al Cooper <alcooperx@gmail.com>
+Cc: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+Cc: Felipe Balbi <balbi@ti.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+Conflicts:
+       drivers/usb/host/xhci-plat.c
+---
+ Documentation/devicetree/bindings/usb/usb-xhci.txt | 14 ++++++++++++++
+ drivers/usb/host/xhci-plat.c                       | 10 ++++++++++
+ 2 files changed, 24 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/usb/usb-xhci.txt
+
+--- /dev/null
++++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt
+@@ -0,0 +1,14 @@
++USB xHCI controllers
++
++Required properties:
++  - compatible: should be "xhci-platform".
++  - reg: should contain address and length of the standard XHCI
++    register set for the device.
++  - interrupts: one XHCI interrupt should be described here.
++
++Example:
++      usb@f0931000 {
++              compatible = "xhci-platform";
++              reg = <0xf0931000 0x8c8>;
++              interrupts = <0x0 0x4e 0x0>;
++      };
+--- a/drivers/usb/host/xhci-plat.c
++++ b/drivers/usb/host/xhci-plat.c
+@@ -14,6 +14,7 @@
+ #include <linux/platform_device.h>
+ #include <linux/module.h>
+ #include <linux/slab.h>
++#include <linux/of.h>
+ #include "xhci.h"
+@@ -186,11 +187,20 @@ static int xhci_plat_remove(struct platf
+       return 0;
+ }
++#ifdef CONFIG_OF
++static const struct of_device_id usb_xhci_of_match[] = {
++      { .compatible = "xhci-platform" },
++      { },
++};
++MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
++#endif
++
+ static struct platform_driver usb_xhci_driver = {
+       .probe  = xhci_plat_probe,
+       .remove = xhci_plat_remove,
+       .driver = {
+               .name = "xhci-hcd",
++              .of_match_table = of_match_ptr(usb_xhci_of_match),
+       },
+ };
+ MODULE_ALIAS("platform:xhci-hcd");
diff --git a/target/linux/mvebu/patches-3.10/0196-ata-sata_mv-setting-PHY-speed-according-to-SControl-.patch b/target/linux/mvebu/patches-3.10/0196-ata-sata_mv-setting-PHY-speed-according-to-SControl-.patch
new file mode 100644 (file)
index 0000000..8a3162c
--- /dev/null
@@ -0,0 +1,58 @@
+From d587c866f34aa8e59ddc3628969113e725e36eab Mon Sep 17 00:00:00 2001
+From: Lior Amsalem <alior@marvell.com>
+Date: Mon, 23 Dec 2013 13:07:35 +0100
+Subject: [PATCH 196/203] ata: sata_mv: setting PHY speed according to SControl
+ speed
+
+This patch fixes a SATA hotplug issue on the Armada 370 and Armada XP
+SoCs. Without it, if a disk is unplugged from a SATA port, then further
+hotplug notification are now longer received on this port.
+
+This should be applied to every -stable kernel supporting Armada SoCs.
+
+Signed-off-by: Lior Amsalem <alior@marvell.com>
+Signed-off-by: Nadav Haklai <nadavh@marvell.com>
+Signed-off-by: Simon Guinot <simon.guinot@sequanux.org>
+Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Cc: Jason Cooper <jason@lakedaemon.net>
+Cc: Andrew Lunn <andrew@lunn.ch>
+Cc: Gregory Clement <gregory.clement@free-electrons.com>
+Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+Cc: stable@vger.kernel.org
+---
+ drivers/ata/sata_mv.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/ata/sata_mv.c
++++ b/drivers/ata/sata_mv.c
+@@ -304,6 +304,7 @@ enum {
+       MV5_LTMODE              = 0x30,
+       MV5_PHY_CTL             = 0x0C,
+       SATA_IFCFG              = 0x050,
++      LP_PHY_CTL              = 0x058,
+       MV_M2_PREAMP_MASK       = 0x7e0,
+@@ -1353,6 +1354,7 @@ static int mv_scr_write(struct ata_link
+       if (ofs != 0xffffffffU) {
+               void __iomem *addr = mv_ap_base(link->ap) + ofs;
++              void __iomem *lp_phy_addr = mv_ap_base(link->ap) + LP_PHY_CTL;
+               if (sc_reg_in == SCR_CONTROL) {
+                       /*
+                        * Workaround for 88SX60x1 FEr SATA#26:
+@@ -1369,6 +1371,14 @@ static int mv_scr_write(struct ata_link
+                        */
+                       if ((val & 0xf) == 1 || (readl(addr) & 0xf) == 1)
+                               val |= 0xf000;
++
++                      /*
++                       * Setting PHY speed according to SControl speed
++                       */
++                      if ((val & 0xf0) == 0x10)
++                              writelfl(0x7, lp_phy_addr);
++                      else
++                              writelfl(0x227, lp_phy_addr);
+               }
+               writelfl(val, addr);
+               return 0;
diff --git a/target/linux/mvebu/patches-3.10/0197-xhci-fix-dma-mask-setup-in-xhci.c.patch b/target/linux/mvebu/patches-3.10/0197-xhci-fix-dma-mask-setup-in-xhci.c.patch
new file mode 100644 (file)
index 0000000..84fcbaf
--- /dev/null
@@ -0,0 +1,124 @@
+From 5cb802766e9cdc9a56e8ce8e4686692ebbcfb5cc Mon Sep 17 00:00:00 2001
+From: Xenia Ragiadakou <burzalodowa@gmail.com>
+Date: Mon, 23 Dec 2013 16:59:02 +0100
+Subject: [PATCH 197/203] xhci: fix dma mask setup in xhci.c
+
+The function dma_set_mask() tests internally whether the dma_mask pointer
+for the device is initialized and fails if the dma_mask pointer is NULL.
+On pci platforms, the device dma_mask pointer is initialized, when pci
+devices are enumerated, to point to the pci_dev->dma_mask which is 0xffffffff.
+However, for non-pci platforms, the dma_mask pointer may not be initialized
+and in that case dma_set_mask() will fail.
+
+This patch initializes the dma_mask and the coherent_dma_mask to 32bits
+in xhci_plat_probe(), before the call to usb_create_hcd() that sets the
+"uses_dma" flag for the usb bus and the call to usb_add_hcd() that creates
+coherent dma pools for the usb hcd.
+
+Moreover, a call to dma_set_mask() does not set the device coherent_dma_mask.
+Since the xhci-hcd driver calls dma_alloc_coherent() and dma_pool_alloc()
+to allocate consistent DMA memory blocks, the coherent DMA address mask
+has to be set explicitly.
+
+This patch sets the coherent_dma_mask to 64bits in xhci_gen_setup() when
+the xHC is capable for 64-bit DMA addressing.
+
+If dma_set_mask() succeeds, for a given bitmask, it is guaranteed that
+the given bitmask is also supported for consistent DMA mappings.
+
+Other changes introduced in this patch are:
+
+- The return value of dma_set_mask() is checked to ensure that the required
+  dma bitmask conforms with the host system's addressing capabilities.
+
+- The dma_mask setup code for the non-primary hcd was removed since both
+  primary and non-primary hcd refer to the same generic device whose
+  dma_mask and coherent_dma_mask are already set during the setup of
+  the primary hcd.
+
+- The code for reading the HCCPARAMS register to find out the addressing
+  capabilities of xHC was removed since its value is already cached in
+  xhci->hccparams.
+
+- hcd->self.controller was replaced with the dev variable since it is
+  already available.
+
+Signed-off-by: Xenia Ragiadakou <burzalodowa@gmail.com>
+Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
+
+Conflicts:
+       drivers/usb/host/xhci-plat.c
+---
+ drivers/usb/host/xhci-plat.c | 10 ++++++++++
+ drivers/usb/host/xhci.c      | 19 +++++--------------
+ 2 files changed, 15 insertions(+), 14 deletions(-)
+
+--- a/drivers/usb/host/xhci-plat.c
++++ b/drivers/usb/host/xhci-plat.c
+@@ -15,6 +15,7 @@
+ #include <linux/module.h>
+ #include <linux/slab.h>
+ #include <linux/of.h>
++#include <linux/dma-mapping.h>
+ #include "xhci.h"
+@@ -105,6 +106,15 @@ static int xhci_plat_probe(struct platfo
+       if (!res)
+               return -ENODEV;
++      /* Initialize dma_mask and coherent_dma_mask to 32-bits */
++      ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
++      if (ret)
++              return ret;
++      if (!pdev->dev.dma_mask)
++              pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
++      else
++              dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
++
+       hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
+       if (!hcd)
+               return -ENOMEM;
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -4654,7 +4654,6 @@ int xhci_gen_setup(struct usb_hcd *hcd,
+       struct xhci_hcd         *xhci;
+       struct device           *dev = hcd->self.controller;
+       int                     retval;
+-      u32                     temp;
+       /* Accept arbitrarily long scatter-gather lists */
+       hcd->self.sg_tablesize = ~0;
+@@ -4682,14 +4681,6 @@ int xhci_gen_setup(struct usb_hcd *hcd,
+               /* xHCI private pointer was set in xhci_pci_probe for the second
+                * registered roothub.
+                */
+-              xhci = hcd_to_xhci(hcd);
+-              temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
+-              if (HCC_64BIT_ADDR(temp)) {
+-                      xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
+-                      dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64));
+-              } else {
+-                      dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32));
+-              }
+               return 0;
+       }
+@@ -4728,12 +4719,12 @@ int xhci_gen_setup(struct usb_hcd *hcd,
+               goto error;
+       xhci_dbg(xhci, "Reset complete\n");
+-      temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
+-      if (HCC_64BIT_ADDR(temp)) {
++      /* Set dma_mask and coherent_dma_mask to 64-bits,
++       * if xHC supports 64-bit addressing */
++      if (HCC_64BIT_ADDR(xhci->hcc_params) &&
++                      !dma_set_mask(dev, DMA_BIT_MASK(64))) {
+               xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
+-              dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64));
+-      } else {
+-              dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32));
++              dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
+       }
+       xhci_dbg(xhci, "Calling HCD init\n");
diff --git a/target/linux/mvebu/patches-3.10/0198-of-Add-testcases-for-interrupt-parsing.patch b/target/linux/mvebu/patches-3.10/0198-of-Add-testcases-for-interrupt-parsing.patch
new file mode 100644 (file)
index 0000000..cbb9252
--- /dev/null
@@ -0,0 +1,104 @@
+From 39623dc5cb8814223e9580e22e78dfab10d91783 Mon Sep 17 00:00:00 2001
+From: Grant Likely <grant.likely@linaro.org>
+Date: Tue, 24 Dec 2013 11:36:02 +0100
+Subject: [PATCH 198/203] of: Add testcases for interrupt parsing
+
+This patch extends the DT selftest code with some test cases for the
+interrupt parsing functions.
+
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ arch/arm/boot/dts/testcases/tests-interrupts.dtsi | 41 +++++++++++++++++++++++
+ arch/arm/boot/dts/testcases/tests.dtsi            |  1 +
+ drivers/of/selftest.c                             | 15 ++++++---
+ 3 files changed, 52 insertions(+), 5 deletions(-)
+ create mode 100644 arch/arm/boot/dts/testcases/tests-interrupts.dtsi
+
+--- /dev/null
++++ b/arch/arm/boot/dts/testcases/tests-interrupts.dtsi
+@@ -0,0 +1,41 @@
++
++/ {
++      testcase-data {
++              interrupts {
++                      #address-cells = <0>;
++                      test_intc0: intc0 {
++                              interrupt-controller;
++                              #interrupt-cells = <1>;
++                      };
++
++                      test_intc1: intc1 {
++                              interrupt-controller;
++                              #interrupt-cells = <3>;
++                      };
++
++                      test_intc2: intc2 {
++                              interrupt-controller;
++                              #interrupt-cells = <2>;
++                      };
++
++                      test_intmap0: intmap0 {
++                              #interrupt-cells = <1>;
++                              #address-cells = <0>;
++                              interrupt-map = <1 &test_intc0 9>,
++                                              <2 &test_intc1 10 11 12>,
++                                              <3 &test_intc2 13 14>,
++                                              <4 &test_intc2 15 16>;
++                      };
++
++                      interrupts0 {
++                              interrupt-parent = <&test_intc0>;
++                              interrupts = <1>, <2>, <3>, <4>;
++                      };
++
++                      interrupts1 {
++                              interrupt-parent = <&test_intmap0>;
++                              interrupts = <1>, <2>, <3>, <4>;
++                      };
++              };
++      };
++};
+--- a/arch/arm/boot/dts/testcases/tests.dtsi
++++ b/arch/arm/boot/dts/testcases/tests.dtsi
+@@ -1 +1,2 @@
+ /include/ "tests-phandle.dtsi"
++/include/ "tests-interrupts.dtsi"
+--- a/drivers/of/selftest.c
++++ b/drivers/of/selftest.c
+@@ -9,18 +9,24 @@
+ #include <linux/errno.h>
+ #include <linux/module.h>
+ #include <linux/of.h>
++#include <linux/of_irq.h>
+ #include <linux/list.h>
+ #include <linux/mutex.h>
+ #include <linux/slab.h>
+ #include <linux/device.h>
+-static bool selftest_passed = true;
++static struct selftest_results {
++      int passed;
++      int failed;
++} selftest_results;
++
+ #define selftest(result, fmt, ...) { \
+       if (!(result)) { \
+-              pr_err("FAIL %s:%i " fmt, __FILE__, __LINE__, ##__VA_ARGS__); \
+-              selftest_passed = false; \
++              selftest_results.failed++; \
++              pr_err("FAIL %s():%i " fmt, __func__, __LINE__, ##__VA_ARGS__); \
+       } else { \
+-              pr_info("pass %s:%i\n", __FILE__, __LINE__); \
++              selftest_results.passed++; \
++              pr_debug("pass %s():%i\n", __func__, __LINE__); \
+       } \
+ }
+@@ -131,7 +137,6 @@ static void __init of_selftest_property_
+       struct device_node *np;
+       int rc;
+-      pr_info("start\n");
+       np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
+       if (!np) {
+               pr_err("No testcase data in device tree\n");
diff --git a/target/linux/mvebu/patches-3.10/0199-PCI-mvebu-Convert-to-use-devm_ioremap_resource.patch b/target/linux/mvebu/patches-3.10/0199-PCI-mvebu-Convert-to-use-devm_ioremap_resource.patch
new file mode 100644 (file)
index 0000000..7f1bdb2
--- /dev/null
@@ -0,0 +1,44 @@
+From 508e3a33ebe14ae4444a45b3f65dff5d5e6a4c73 Mon Sep 17 00:00:00 2001
+From: Tushar Behera <tushar.behera@linaro.org>
+Date: Mon, 17 Jun 2013 14:46:13 +0530
+Subject: [PATCH 199/203] PCI: mvebu: Convert to use devm_ioremap_resource
+
+Commit 75096579c3ac ("lib: devres: Introduce devm_ioremap_resource()")
+introduced devm_ioremap_resource() and deprecated the use of
+devm_request_and_ioremap().
+
+While at it, modify mvebu_pcie_map_registers() to propagate error code.
+
+Signed-off-by: Tushar Behera <tushar.behera@linaro.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
+---
+ drivers/pci/host/pci-mvebu.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/pci/host/pci-mvebu.c
++++ b/drivers/pci/host/pci-mvebu.c
+@@ -736,9 +736,9 @@ mvebu_pcie_map_registers(struct platform
+       ret = of_address_to_resource(np, 0, &regs);
+       if (ret)
+-              return NULL;
++              return ERR_PTR(ret);
+-      return devm_request_and_ioremap(&pdev->dev, &regs);
++      return devm_ioremap_resource(&pdev->dev, &regs);
+ }
+ static void __init mvebu_pcie_msi_enable(struct mvebu_pcie *pcie)
+@@ -897,9 +897,10 @@ static int __init mvebu_pcie_probe(struc
+               }
+               port->base = mvebu_pcie_map_registers(pdev, child, port);
+-              if (!port->base) {
++              if (IS_ERR(port->base)) {
+                       dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",
+                               port->port, port->lane);
++                      port->base = NULL;
+                       continue;
+               }
diff --git a/target/linux/mvebu/patches-3.10/0200-PCI-mvebu-move-clock-enable-before-register-access.patch b/target/linux/mvebu/patches-3.10/0200-PCI-mvebu-move-clock-enable-before-register-access.patch
new file mode 100644 (file)
index 0000000..33fba3d
--- /dev/null
@@ -0,0 +1,65 @@
+From c524c5790d413b37702013e7e83a845fd3f007ac Mon Sep 17 00:00:00 2001
+From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+Date: Tue, 13 Aug 2013 14:25:20 +0200
+Subject: [PATCH 200/203] PCI: mvebu: move clock enable before register access
+
+The clock passed to PCI controller found on MVEBU SoCs may come from a
+clock gate. This requires the clock to be enabled before any registers
+are accessed. Therefore, move the clock enable before register iomap to
+ensure it is enabled.
+
+Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ drivers/pci/host/pci-mvebu.c | 25 ++++++++++++-------------
+ 1 file changed, 12 insertions(+), 13 deletions(-)
+
+--- a/drivers/pci/host/pci-mvebu.c
++++ b/drivers/pci/host/pci-mvebu.c
+@@ -896,11 +896,23 @@ static int __init mvebu_pcie_probe(struc
+                       continue;
+               }
++              port->clk = of_clk_get_by_name(child, NULL);
++              if (IS_ERR(port->clk)) {
++                      dev_err(&pdev->dev, "PCIe%d.%d: cannot get clock\n",
++                             port->port, port->lane);
++                      continue;
++              }
++
++              ret = clk_prepare_enable(port->clk);
++              if (ret)
++                      continue;
++
+               port->base = mvebu_pcie_map_registers(pdev, child, port);
+               if (IS_ERR(port->base)) {
+                       dev_err(&pdev->dev, "PCIe%d.%d: cannot map registers\n",
+                               port->port, port->lane);
+                       port->base = NULL;
++                      clk_disable_unprepare(port->clk);
+                       continue;
+               }
+@@ -916,22 +928,9 @@ static int __init mvebu_pcie_probe(struc
+                                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++;
+       }
diff --git a/target/linux/mvebu/patches-3.10/0201-PCI-mvebu-increment-nports-only-for-registered-ports.patch b/target/linux/mvebu/patches-3.10/0201-PCI-mvebu-increment-nports-only-for-registered-ports.patch
new file mode 100644 (file)
index 0000000..810fbe1
--- /dev/null
@@ -0,0 +1,47 @@
+From e619fe9eb65d8064739f16eca2015145ac920f13 Mon Sep 17 00:00:00 2001
+From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+Date: Tue, 13 Aug 2013 14:25:21 +0200
+Subject: [PATCH 201/203] PCI: mvebu: increment nports only for registered
+ ports
+
+The number of ports is probed by counting the number of available child nodes.
+Later on, the registration of a port can fail and cause a mismatch between
+the ->nports counter and registered ports. This patch modifies the counting
+strategy, to make ->nports represent the number of registered ports instead
+of the number of available childs.
+
+Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ drivers/pci/host/pci-mvebu.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+--- a/drivers/pci/host/pci-mvebu.c
++++ b/drivers/pci/host/pci-mvebu.c
+@@ -841,13 +841,14 @@ static int __init mvebu_pcie_probe(struc
+               return ret;
+       }
++      i = 0;
+       for_each_child_of_node(pdev->dev.of_node, child) {
+               if (!of_device_is_available(child))
+                       continue;
+-              pcie->nports++;
++              i++;
+       }
+-      pcie->ports = devm_kzalloc(&pdev->dev, pcie->nports *
++      pcie->ports = devm_kzalloc(&pdev->dev, i *
+                                  sizeof(struct mvebu_pcie_port),
+                                  GFP_KERNEL);
+       if (!pcie->ports)
+@@ -934,8 +935,8 @@ static int __init mvebu_pcie_probe(struc
+               i++;
+       }
++      pcie->nports = i;
+       mvebu_pcie_msi_enable(pcie);
+-
+       mvebu_pcie_enable(pcie);
+       return 0;
diff --git a/target/linux/mvebu/patches-3.10/0202-ARM-mvebu-second-PCIe-unit-of-Armada-XP-mv78230-is-o.patch b/target/linux/mvebu/patches-3.10/0202-ARM-mvebu-second-PCIe-unit-of-Armada-XP-mv78230-is-o.patch
new file mode 100644 (file)
index 0000000..af2a59a
--- /dev/null
@@ -0,0 +1,85 @@
+From b2ea44bd7bca49fe5696857327a1d1514edd1196 Mon Sep 17 00:00:00 2001
+From: Arnaud Ebalard <arno@natisbad.org>
+Date: Tue, 5 Nov 2013 21:45:48 +0100
+Subject: [PATCH 202/203] ARM: mvebu: second PCIe unit of Armada XP mv78230 is
+ only x1 capable
+
+Various Marvell datasheets advertise second PCIe unit of mv78230
+flavour of Armada XP as x4/quad x1 capable. This second unit is in
+fact only x1 capable. This patch fixes current mv78230 .dtsi to
+reflect that, i.e. makes 1.0 the second interface (instead of 2.0
+at the moment). This was successfully tested on a mv78230-based
+ReadyNAS 2120 platform with a x1 device (FL1009 XHCI controller)
+connected to this second interface.
+
+Signed-off-by: Arnaud Ebalard <arno@natisbad.org>
+Acked-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Cc: <stable@vger.kernel.org> # v3.10.x
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-xp-mv78230.dtsi | 24 ++++++++++++------------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi
++++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+@@ -47,7 +47,7 @@
+               /*
+                * MV78230 has 2 PCIe units Gen2.0: One unit can be
+                * configured as x4 or quad x1 lanes. One unit is
+-               * x4/x1.
++               * x1 only.
+                */
+               pcie-controller {
+                       compatible = "marvell,armada-xp-pcie";
+@@ -62,10 +62,10 @@
+                       ranges =
+                              <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000   /* Port 0.0 registers */
+-                              0x82000000 0 0x42000 MBUS_ID(0xf0, 0x01) 0x42000 0 0x00002000   /* Port 2.0 registers */
+                               0x82000000 0 0x44000 MBUS_ID(0xf0, 0x01) 0x44000 0 0x00002000   /* Port 0.1 registers */
+                               0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000   /* Port 0.2 registers */
+                               0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000   /* Port 0.3 registers */
++                              0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000   /* Port 1.0 registers */
+                               0x82000000 0x1 0       MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
+                               0x81000000 0x1 0       MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */
+                               0x82000000 0x2 0       MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
+@@ -74,8 +74,8 @@
+                               0x81000000 0x3 0       MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO  */
+                               0x82000000 0x4 0       MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
+                               0x81000000 0x4 0       MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO  */
+-                              0x82000000 0x9 0       MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
+-                              0x81000000 0x9 0       MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO  */>;
++                              0x82000000 0x5 0       MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
++                              0x81000000 0x5 0       MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */>;
+                       pcie@1,0 {
+                               device_type = "pci";
+@@ -145,20 +145,20 @@
+                               status = "disabled";
+                       };
+-                      pcie@9,0 {
++                      pcie@5,0 {
+                               device_type = "pci";
+-                              assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
+-                              reg = <0x4800 0 0 0 0>;
++                              assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
++                              reg = <0x2800 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+-                              ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
+-                                        0x81000000 0 0 0x81000000 0x9 0 1 0>;
++                              ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
++                                        0x81000000 0 0 0x81000000 0x5 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &mpic 99>;
+-                              marvell,pcie-port = <2>;
++                              interrupt-map = <0 0 0 0 &mpic 62>;
++                              marvell,pcie-port = <1>;
+                               marvell,pcie-lane = <0>;
+-                              clocks = <&gateclk 26>;
++                              clocks = <&gateclk 9>;
+                               status = "disabled";
+                       };
+               };
diff --git a/target/linux/mvebu/patches-3.10/0203-ARM-mvebu-fix-second-and-third-PCIe-unit-of-Armada-X.patch b/target/linux/mvebu/patches-3.10/0203-ARM-mvebu-fix-second-and-third-PCIe-unit-of-Armada-X.patch
new file mode 100644 (file)
index 0000000..70953bf
--- /dev/null
@@ -0,0 +1,180 @@
+From 9c2caf4d2d60780182d7754896c41496192b99c2 Mon Sep 17 00:00:00 2001
+From: Arnaud Ebalard <arno@natisbad.org>
+Date: Tue, 5 Nov 2013 21:46:02 +0100
+Subject: [PATCH 203/203] ARM: mvebu: fix second and third PCIe unit of Armada
+ XP mv78260
+
+mv78260 flavour of Marvell Armada XP SoC has 3 PCIe units. The
+two first units are both x4 and quad x1 capable. The third unit
+is only x4 capable. This patch fixes mv78260 .dtsi to reflect
+those capabilities.
+
+Signed-off-by: Arnaud Ebalard <arno@natisbad.org>
+Acked-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+Cc: <stable@vger.kernel.org> # v3.10.x
+Signed-off-by: Jason Cooper <jason@lakedaemon.net>
+---
+ arch/arm/boot/dts/armada-xp-mv78260.dtsi | 109 ++++++++++++++++++++++++-------
+ 1 file changed, 85 insertions(+), 24 deletions(-)
+
+--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
++++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+@@ -48,7 +48,7 @@
+               /*
+                * MV78260 has 3 PCIe units Gen2.0: Two units can be
+                * configured as x4 or quad x1 lanes. One unit is
+-               * x4/x1.
++               * x4 only.
+                */
+               pcie-controller {
+                       compatible = "marvell,armada-xp-pcie";
+@@ -68,7 +68,9 @@
+                               0x82000000 0 0x48000 MBUS_ID(0xf0, 0x01) 0x48000 0 0x00002000   /* Port 0.2 registers */
+                               0x82000000 0 0x4c000 MBUS_ID(0xf0, 0x01) 0x4c000 0 0x00002000   /* Port 0.3 registers */
+                               0x82000000 0 0x80000 MBUS_ID(0xf0, 0x01) 0x80000 0 0x00002000   /* Port 1.0 registers */
+-                              0x82000000 0 0x82000 MBUS_ID(0xf0, 0x01) 0x82000 0 0x00002000   /* Port 3.0 registers */
++                              0x82000000 0 0x84000 MBUS_ID(0xf0, 0x01) 0x84000 0 0x00002000   /* Port 1.1 registers */
++                              0x82000000 0 0x88000 MBUS_ID(0xf0, 0x01) 0x88000 0 0x00002000   /* Port 1.2 registers */
++                              0x82000000 0 0x8c000 MBUS_ID(0xf0, 0x01) 0x8c000 0 0x00002000   /* Port 1.3 registers */
+                               0x82000000 0x1 0     MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
+                               0x81000000 0x1 0     MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */
+                               0x82000000 0x2 0     MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */
+@@ -77,10 +79,18 @@
+                               0x81000000 0x3 0     MBUS_ID(0x04, 0xb0) 0 1 0 /* Port 0.2 IO  */
+                               0x82000000 0x4 0     MBUS_ID(0x04, 0x78) 0 1 0 /* Port 0.3 MEM */
+                               0x81000000 0x4 0     MBUS_ID(0x04, 0x70) 0 1 0 /* Port 0.3 IO  */
+-                              0x82000000 0x9 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
+-                              0x81000000 0x9 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */
+-                              0x82000000 0xa 0     MBUS_ID(0x08, 0xf8) 0 1 0 /* Port 3.0 MEM */
+-                              0x81000000 0xa 0     MBUS_ID(0x08, 0xf0) 0 1 0 /* Port 3.0 IO  */>;
++
++                              0x82000000 0x5 0     MBUS_ID(0x08, 0xe8) 0 1 0 /* Port 1.0 MEM */
++                              0x81000000 0x5 0     MBUS_ID(0x08, 0xe0) 0 1 0 /* Port 1.0 IO  */
++                              0x82000000 0x6 0     MBUS_ID(0x08, 0xd8) 0 1 0 /* Port 1.1 MEM */
++                              0x81000000 0x6 0     MBUS_ID(0x08, 0xd0) 0 1 0 /* Port 1.1 IO  */
++                              0x82000000 0x7 0     MBUS_ID(0x08, 0xb8) 0 1 0 /* Port 1.2 MEM */
++                              0x81000000 0x7 0     MBUS_ID(0x08, 0xb0) 0 1 0 /* Port 1.2 IO  */
++                              0x82000000 0x8 0     MBUS_ID(0x08, 0x78) 0 1 0 /* Port 1.3 MEM */
++                              0x81000000 0x8 0     MBUS_ID(0x08, 0x70) 0 1 0 /* Port 1.3 IO  */
++
++                              0x82000000 0x9 0     MBUS_ID(0x04, 0xf8) 0 1 0 /* Port 2.0 MEM */
++                              0x81000000 0x9 0     MBUS_ID(0x04, 0xf0) 0 1 0 /* Port 2.0 IO  */>;
+                       pcie@1,0 {
+                               device_type = "pci";
+@@ -106,8 +116,8 @@
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+-                                ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
+-                                          0x81000000 0 0 0x81000000 0x2 0 1 0>;
++                              ranges = <0x82000000 0 0 0x82000000 0x2 0 1 0
++                                        0x81000000 0 0 0x81000000 0x2 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+                               interrupt-map = <0 0 0 0 &mpic 59>;
+                               marvell,pcie-port = <0>;
+@@ -150,37 +160,88 @@
+                               status = "disabled";
+                       };
+-                      pcie@9,0 {
++                      pcie@5,0 {
+                               device_type = "pci";
+-                              assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
+-                              reg = <0x4800 0 0 0 0>;
++                              assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
++                              reg = <0x2800 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+-                              ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
+-                                        0x81000000 0 0 0x81000000 0x9 0 1 0>;
++                              ranges = <0x82000000 0 0 0x82000000 0x5 0 1 0
++                                        0x81000000 0 0 0x81000000 0x5 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &mpic 99>;
+-                              marvell,pcie-port = <2>;
++                              interrupt-map = <0 0 0 0 &mpic 62>;
++                              marvell,pcie-port = <1>;
+                               marvell,pcie-lane = <0>;
+-                              clocks = <&gateclk 26>;
++                              clocks = <&gateclk 9>;
+                               status = "disabled";
+                       };
+-                      pcie@10,0 {
++                      pcie@6,0 {
+                               device_type = "pci";
+-                              assigned-addresses = <0x82000800 0 0x82000 0 0x2000>;
+-                              reg = <0x5000 0 0 0 0>;
++                              assigned-addresses = <0x82000800 0 0x84000 0 0x2000>;
++                              reg = <0x3000 0 0 0 0>;
+                               #address-cells = <3>;
+                               #size-cells = <2>;
+                               #interrupt-cells = <1>;
+-                              ranges = <0x82000000 0 0 0x82000000 0xa 0 1 0
+-                                        0x81000000 0 0 0x81000000 0xa 0 1 0>;
++                              ranges = <0x82000000 0 0 0x82000000 0x6 0 1 0
++                                        0x81000000 0 0 0x81000000 0x6 0 1 0>;
+                               interrupt-map-mask = <0 0 0 0>;
+-                              interrupt-map = <0 0 0 0 &mpic 103>;
+-                              marvell,pcie-port = <3>;
++                              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 = <0x82000800 0 0x88000 0 0x2000>;
++                              reg = <0x3800 0 0 0 0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              #interrupt-cells = <1>;
++                              ranges = <0x82000000 0 0 0x82000000 0x7 0 1 0
++                                        0x81000000 0 0 0x81000000 0x7 0 1 0>;
++                              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 = <0x82000800 0 0x8c000 0 0x2000>;
++                              reg = <0x4000 0 0 0 0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              #interrupt-cells = <1>;
++                              ranges = <0x82000000 0 0 0x82000000 0x8 0 1 0
++                                        0x81000000 0 0 0x81000000 0x8 0 1 0>;
++                              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 = <0x82000800 0 0x42000 0 0x2000>;
++                              reg = <0x4800 0 0 0 0>;
++                              #address-cells = <3>;
++                              #size-cells = <2>;
++                              #interrupt-cells = <1>;
++                              ranges = <0x82000000 0 0 0x82000000 0x9 0 1 0
++                                        0x81000000 0 0 0x81000000 0x9 0 1 0>;
++                              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 27>;
++                              clocks = <&gateclk 26>;
+                               status = "disabled";
+                       };
+               };