This patch allows for a more flexible ioremap() interception.  The mechanism
works by translating physical addresses based on soc-specific iotable
contents (davinci_soc_info.io_desc), once davinci_soc_info is populated by
davinci_common_init().

Signed-off-by: Cyril Chemparathy <cy...@ti.com>
Tested-by: Sandeep Paulraj <s-paul...@ti.com>
---
 arch/arm/mach-davinci/da830.c           |    7 +++++-
 arch/arm/mach-davinci/da850.c           |    9 ++++++-
 arch/arm/mach-davinci/include/mach/io.h |    4 +++
 arch/arm/mach-davinci/io.c              |   33 +++++++++++++++++++++++++++---
 4 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c
index 122e61a..168f277 100644
--- a/arch/arm/mach-davinci/da830.c
+++ b/arch/arm/mach-davinci/da830.c
@@ -1206,9 +1206,14 @@ static struct davinci_soc_info davinci_soc_info_da830 = {
        .emac_pdata             = &da8xx_emac_pdata,
 };
 
+#define da830_early_ioremap(p, s)                              \
+       __davinci_ioremap(p, s,                                 \
+                       davinci_soc_info_da830.io_desc,         \
+                       davinci_soc_info_da830.io_desc_num)
+
 void __init da830_init(void)
 {
-       da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K);
+       da8xx_syscfg0_base = da830_early_ioremap(DA8XX_SYSCFG0_BASE, SZ_4K);
        if (WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module"))
                return;
 
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index d0fd756..27eb32e 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -1093,15 +1093,20 @@ static struct davinci_soc_info davinci_soc_info_da850 = 
{
        .sram_len               = SZ_8K,
 };
 
+#define da850_early_ioremap(p, s)                              \
+       __davinci_ioremap(p, s,                                 \
+                       davinci_soc_info_da850.io_desc,         \
+                       davinci_soc_info_da850.io_desc_num)
+
 void __init da850_init(void)
 {
        unsigned int v;
 
-       da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K);
+       da8xx_syscfg0_base = da850_early_ioremap(DA8XX_SYSCFG0_BASE, SZ_4K);
        if (WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module"))
                return;
 
-       da8xx_syscfg1_base = ioremap(DA8XX_SYSCFG1_BASE, SZ_4K);
+       da8xx_syscfg1_base = da850_early_ioremap(DA8XX_SYSCFG1_BASE, SZ_4K);
        if (WARN(!da8xx_syscfg1_base, "Unable to map syscfg1 module"))
                return;
 
diff --git a/arch/arm/mach-davinci/include/mach/io.h 
b/arch/arm/mach-davinci/include/mach/io.h
index 62b0a90..4aa301c 100644
--- a/arch/arm/mach-davinci/include/mach/io.h
+++ b/arch/arm/mach-davinci/include/mach/io.h
@@ -25,6 +25,10 @@
 #define __arch_ioremap(p, s, t)        davinci_ioremap(p, s, t)
 #define __arch_iounmap(v)      davinci_iounmap(v)
 
+struct map_desc;
+
+void __iomem *__davinci_ioremap(unsigned long p, size_t size,
+               struct map_desc *io_desc, int io_desc_num);
 void __iomem *davinci_ioremap(unsigned long phys, size_t size,
                              unsigned int type);
 void davinci_iounmap(volatile void __iomem *addr);
diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c
index a1c0b6b..3a62f14 100644
--- a/arch/arm/mach-davinci/io.c
+++ b/arch/arm/mach-davinci/io.c
@@ -12,17 +12,42 @@
 #include <linux/io.h>
 
 #include <asm/tlb.h>
+#include <asm/mach/map.h>
 
-#define BETWEEN(p, st, sz)     ((p) >= (st) && (p) < ((st) + (sz)))
-#define XLATE(p, pst, vst)     ((void __iomem *)((p) - (pst) + (vst)))
+#include <mach/common.h>
+
+/*
+ * Remap io addresses based on a soc-specific io-descriptor table. This is
+ * useful in early arch init code before davinci_common_init().  After
+ * davinci_common_init(), regular ioremap() calls should be used.
+ */
+void __iomem *__davinci_ioremap(unsigned long p, size_t size,
+               struct map_desc *io_desc, int io_desc_num)
+{
+       int i;
+
+       for (i = 0; i < io_desc_num; i++, io_desc++) {
+               unsigned long iophys = __pfn_to_phys(io_desc->pfn);
+               unsigned long iosize = io_desc->length;
+
+               if (p >= iophys && (p + size) <= (iophys + iosize))
+                       return __io(io_desc->virtual + p - iophys);
+       }
+
+       return NULL;
+}
 
 /*
  * Intercept ioremap() requests for addresses in our fixed mapping regions.
  */
 void __iomem *davinci_ioremap(unsigned long p, size_t size, unsigned int type)
 {
-       if (BETWEEN(p, IO_PHYS, IO_SIZE))
-               return XLATE(p, IO_PHYS, IO_VIRT);
+       void __iomem *ret;
+
+       ret = __davinci_ioremap(p, size, davinci_soc_info.io_desc,
+                       davinci_soc_info.io_desc_num);
+       if (ret)
+               return ret;
 
        return __arm_ioremap_caller(p, size, type, __builtin_return_address(0));
 }
-- 
1.6.3.3

_______________________________________________
Davinci-linux-open-source mailing list
Davinci-linux-open-source@linux.davincidsp.com
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to