This patch allows for a more flexible ioremap() interception based on iotable contents.
SoCs that need ioremap() to fill up davinci_soc_info may directly call davinci_io_init() and use ioremap() as needed. Such SoCs must not fill io_desc and io_desc_num entries in struct davinci_soc_info. Signed-off-by: Cyril Chemparathy <[email protected]> Tested-by: Sandeep Paulraj <[email protected]> --- v4: removed __davinci_ioremap() and related infrastructure v4: split davinci_io_init() out of davinci_common_init() arch/arm/mach-davinci/common.c | 13 +------- arch/arm/mach-davinci/da830.c | 2 + arch/arm/mach-davinci/da850.c | 2 + arch/arm/mach-davinci/include/mach/io.h | 5 +++ arch/arm/mach-davinci/io.c | 49 +++++++++++++++++++++++++++--- 5 files changed, 55 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-davinci/common.c b/arch/arm/mach-davinci/common.c index 94f27cb..aac43b1 100644 --- a/arch/arm/mach-davinci/common.c +++ b/arch/arm/mach-davinci/common.c @@ -65,17 +65,8 @@ void __init davinci_common_init(struct davinci_soc_info *soc_info) memcpy(&davinci_soc_info, soc_info, sizeof(struct davinci_soc_info)); - if (davinci_soc_info.io_desc && (davinci_soc_info.io_desc_num > 0)) - iotable_init(davinci_soc_info.io_desc, - davinci_soc_info.io_desc_num); - - /* - * Normally devicemaps_init() would flush caches and tlb after - * mdesc->map_io(), but we must also do it here because of the CPU - * revision check below. - */ - local_flush_tlb_all(); - flush_cache_all(); + davinci_io_init(davinci_soc_info.io_desc, + davinci_soc_info.io_desc_num); /* * We want to check CPU revision early for cpu_is_xxxx() macros. diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c index 68e5233..4bcdc6f 100644 --- a/arch/arm/mach-davinci/da830.c +++ b/arch/arm/mach-davinci/da830.c @@ -1210,6 +1210,8 @@ static struct davinci_soc_info davinci_soc_info_da830 = { void __init da830_init(void) { + davinci_io_init(da830_io_desc, ARRAY_SIZE(da830_io_desc)); + da8xx_syscfg0_base = 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 8aefcff..c2c2d58 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c @@ -1099,6 +1099,8 @@ void __init da850_init(void) { unsigned int v; + davinci_io_init(da850_io_desc, ARRAY_SIZE(da850_io_desc)); + da8xx_syscfg0_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K); if (WARN(!da8xx_syscfg0_base, "Unable to map syscfg0 module")) return; diff --git a/arch/arm/mach-davinci/include/mach/io.h b/arch/arm/mach-davinci/include/mach/io.h index 62b0a90..3f456b7 100644 --- a/arch/arm/mach-davinci/include/mach/io.h +++ b/arch/arm/mach-davinci/include/mach/io.h @@ -25,8 +25,13 @@ #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 phys, size_t size, unsigned int type); void davinci_iounmap(volatile void __iomem *addr); + +void davinci_io_init(struct map_desc *desc, unsigned long desc_num); + #endif #endif /* __ASM_ARCH_IO_H */ diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c index a1c0b6b..81862ec 100644 --- a/arch/arm/mach-davinci/io.c +++ b/arch/arm/mach-davinci/io.c @@ -12,19 +12,31 @@ #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> + +static struct map_desc *davinci_io_desc; +static unsigned long davinci_io_desc_num; /* * 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); + struct map_desc *desc = davinci_io_desc; + int i; + + for (i = 0; i < davinci_io_desc_num; i++, desc++) { + unsigned long iophys = __pfn_to_phys(desc->pfn); + unsigned long iosize = desc->length; + + if (p >= iophys && (p + size) <= (iophys + iosize)) + return __io(desc->virtual + p - iophys); + } - return __arm_ioremap_caller(p, size, type, __builtin_return_address(0)); + return __arm_ioremap_caller(p, size, type, + __builtin_return_address(0)); } EXPORT_SYMBOL(davinci_ioremap); @@ -36,3 +48,30 @@ void davinci_iounmap(volatile void __iomem *addr) __iounmap(addr); } EXPORT_SYMBOL(davinci_iounmap); + +void __init davinci_io_init(struct map_desc *desc, unsigned long desc_num) +{ + if (!desc || !desc_num) + return; + + /* silently refuse to init twice ...*/ + if (davinci_io_desc) { + /* ... unless things change */ + BUG_ON(davinci_io_desc != desc || + davinci_io_desc_num != desc_num); + return; + } + + davinci_io_desc = desc; + davinci_io_desc_num = desc_num; + + iotable_init(desc, desc_num); + + /* + * Normally devicemaps_init() would flush caches and tlb after + * mdesc->map_io(), but we must also do it here because of the CPU + * revision check below. + */ + local_flush_tlb_all(); + flush_cache_all(); +} -- 1.6.3.3 _______________________________________________ Davinci-linux-open-source mailing list [email protected] http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source
