--- /dev/null
+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,
--- /dev/null
+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;
+ }
+
--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+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>
--- /dev/null
+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);
--- /dev/null
+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)
--- /dev/null
+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;
--- /dev/null
+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;
+
--- /dev/null
+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;
+ }
--- /dev/null
+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)
--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+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)
--- /dev/null
+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];
+
--- /dev/null
+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;
--- /dev/null
+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;
+ }
+
--- /dev/null
+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);
+
--- /dev/null
+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);
--- /dev/null
+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);
--- /dev/null
+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:
--- /dev/null
+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:
--- /dev/null
+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;
--- /dev/null
+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);
--- /dev/null
+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);
+
--- /dev/null
+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)
--- /dev/null
+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,
--- /dev/null
+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);
--- /dev/null
+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);
--- /dev/null
+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",
--- /dev/null
+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
--- /dev/null
+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"
--- /dev/null
+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
--- /dev/null
+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);
--- /dev/null
+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:
--- /dev/null
+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);
--- /dev/null
+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 {
--- /dev/null
+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;
+
--- /dev/null
+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)
--- /dev/null
+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",
--- /dev/null
+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);
--- /dev/null
+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;
+
--- /dev/null
+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);
+ }
--- /dev/null
+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);
--- /dev/null
+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 {
--- /dev/null
+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>;
++ };
++ };
+ };
--- /dev/null
+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 {
--- /dev/null
+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";
+- };
+- };
+ };
+ };
+ };
--- /dev/null
+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)
--- /dev/null
+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;
+ }
--- /dev/null
+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,
--- /dev/null
+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.
--- /dev/null
+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
--- /dev/null
+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;
--- /dev/null
+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);
+ }
+
--- /dev/null
+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,
--- /dev/null
+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,
--- /dev/null
+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;
+ }
+
--- /dev/null
+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);
--- /dev/null
+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);
--- /dev/null
+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;
--- /dev/null
+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);
--- /dev/null
+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 */
--- /dev/null
+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;
+
--- /dev/null
+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);
+
--- /dev/null
+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>;
++ };
--- /dev/null
+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";
+ };
--- /dev/null
+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");
--- /dev/null
+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;
--- /dev/null
+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");
--- /dev/null
+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");
--- /dev/null
+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, ®s);
+ if (ret)
+- return NULL;
++ return ERR_PTR(ret);
+
+- return devm_request_and_ioremap(&pdev->dev, ®s);
++ return devm_ioremap_resource(&pdev->dev, ®s);
+ }
+
+ 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;
+ }
+
--- /dev/null
+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++;
+ }
+
--- /dev/null
+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;
--- /dev/null
+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";
+ };
+ };
--- /dev/null
+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";
+ };
+ };