From: Linus Torvalds Date: Thu, 5 Jun 2014 22:57:04 +0000 (-0700) Subject: Merge branch 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm into next X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=eb3d3ec567e8;p=deliverable%2Flinux.git Merge branch 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm into next Pull ARM updates from Russell King: - Major clean-up of the L2 cache support code. The existing mess was becoming rather unmaintainable through all the additions that others have done over time. This turns it into a much nicer structure, and implements a few performance improvements as well. - Clean up some of the CP15 control register tweaks for alignment support, moving some code and data into alignment.c - DMA properties for ARM, from Santosh and reviewed by DT people. This adds DT properties to specify bus translations we can't discover automatically, and to indicate whether devices are coherent. - Hibernation support for ARM - Make ftrace work with read-only text in modules - add suspend support for PJ4B CPUs - rework interrupt masking for undefined instruction handling, which allows us to enable interrupts earlier in the handling of these exceptions. - support for big endian page tables - fix stacktrace support to exclude stacktrace functions from the trace, and add save_stack_trace_regs() implementation so that kprobes can record stack traces. - Add support for the Cortex-A17 CPU. - Remove last vestiges of ARM710 support. - Removal of ARM "meminfo" structure, finally converting us solely to memblock to handle the early memory initialisation. * 'for-linus' of git://ftp.arm.linux.org.uk/~rmk/linux-arm: (142 commits) ARM: ensure C page table setup code follows assembly code (part II) ARM: ensure C page table setup code follows assembly code ARM: consolidate last remaining open-coded alignment trap enable ARM: remove global cr_no_alignment ARM: remove CPU_CP15 conditional from alignment.c ARM: remove unused adjust_cr() function ARM: move "noalign" command line option to alignment.c ARM: provide common method to clear bits in CPU control register ARM: 8025/1: Get rid of meminfo ARM: 8060/1: mm: allow sub-architectures to override PCI I/O memory type ARM: 8066/1: correction for ARM patch 8031/2 ARM: 8049/1: ftrace/add save_stack_trace_regs() implementation ARM: 8065/1: remove last use of CONFIG_CPU_ARM710 ARM: 8062/1: Modify ldrt fixup handler to re-execute the userspace instruction ARM: 8047/1: rwsem: use asm-generic rwsem implementation ARM: l2c: trial at enabling some Cortex-A9 optimisations ARM: l2c: add warnings for stuff modifying aux_ctrl register values ARM: l2c: print a warning with L2C-310 caches if the cache size is modified ARM: l2c: remove old .set_debug method ARM: l2c: kill L2X0_AUX_CTRL_MASK before anyone else makes use of this ... --- eb3d3ec567e868c8a3bfbfdfc9465ffd52983d11 diff --cc arch/arm/kernel/devtree.c index ea9ce92a4b52,679a83d470cc..e94a157ddff1 --- a/arch/arm/kernel/devtree.c +++ b/arch/arm/kernel/devtree.c @@@ -27,17 -27,41 +27,13 @@@ #include #include - void __init early_init_dt_add_memory_arch(u64 base, u64 size) -void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) --{ - arm_add_memory(base, size); - return memblock_virt_alloc(size, align); --} - -void __init arm_dt_memblock_reserve(void) -{ - u64 *reserve_map, base, size; - if (!initial_boot_params) - return; +#ifdef CONFIG_SMP +extern struct of_cpu_method __cpu_method_of_table[]; - /* Reserve the dtb region */ - memblock_reserve(virt_to_phys(initial_boot_params), - be32_to_cpu(initial_boot_params->totalsize)); +static const struct of_cpu_method __cpu_method_of_table_sentinel + __used __section(__cpu_method_of_table_end); - /* - * Process the reserve map. This will probably overlap the initrd - * and dtb locations which are already reserved, but overlaping - * doesn't hurt anything - */ - reserve_map = ((void*)initial_boot_params) + - be32_to_cpu(initial_boot_params->off_mem_rsvmap); - while (1) { - base = be64_to_cpup(reserve_map++); - size = be64_to_cpup(reserve_map++); - if (!size) - break; - memblock_reserve(base, size); - } -} - -#ifdef CONFIG_SMP -extern struct of_cpu_method __cpu_method_of_table_begin[]; -extern struct of_cpu_method __cpu_method_of_table_end[]; static int __init set_smp_ops_by_method(struct device_node *node) { diff --cc arch/arm/mach-exynos/exynos.c index a56ce45a3f90,a763c0862da9..90aab4d75d08 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@@ -246,25 -305,17 +243,6 @@@ void __init exynos_init_io(void exynos_map_io(); } - static int __init exynos4_l2x0_cache_init(void) - { - int ret; - - if (!soc_is_exynos4()) - return 0; - - ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK); - if (ret) - return ret; -struct bus_type exynos_subsys = { - .name = "exynos-core", - .dev_name = "exynos-core", -}; -- - if (IS_ENABLED(CONFIG_S5P_SLEEP)) { - l2x0_regs_phys = virt_to_phys(&l2x0_saved_regs); - clean_dcache_area(&l2x0_regs_phys, sizeof(unsigned long)); - } - return 0; -static int __init exynos_core_init(void) -{ - return subsys_system_register(&exynos_subsys, NULL); --} - early_initcall(exynos4_l2x0_cache_init); -core_initcall(exynos_core_init); -- static void __init exynos_dt_machine_init(void) { struct device_node *i2c_np; diff --cc arch/arm/mach-mvebu/board-v7.c index 01cfce6ac20b,48169caa56ea..594262b27f56 --- a/arch/arm/mach-mvebu/board-v7.c +++ b/arch/arm/mach-mvebu/board-v7.c @@@ -195,8 -121,9 +197,10 @@@ static const char * const armada_375_dt }; DT_MACHINE_START(ARMADA_375_DT, "Marvell Armada 375 (Device Tree)") + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, .init_time = mvebu_timer_and_clk_init, + .init_machine = mvebu_dt_init, .restart = mvebu_restart, .dt_compat = armada_375_dt_compat, MACHINE_END diff --cc arch/arm/mach-omap2/omap-mpuss-lowpower.c index eb76e47091ad,61cb77f8cf12..4001325f90fb --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@@ -187,19 -187,15 +187,15 @@@ static void l2x0_pwrst_prepare(unsigne * in every restore MPUSS OFF path. */ #ifdef CONFIG_CACHE_L2X0 - static void save_l2x0_context(void) + static void __init save_l2x0_context(void) { - u32 val; - void __iomem *l2x0_base = omap4_get_l2cache_base(); - if (l2x0_base) { - val = readl_relaxed(l2x0_base + L2X0_AUX_CTRL); - writel_relaxed(val, sar_base + L2X0_AUXCTRL_OFFSET); - val = readl_relaxed(l2x0_base + L2X0_PREFETCH_CTRL); - writel_relaxed(val, sar_base + L2X0_PREFETCH_CTRL_OFFSET); - } - __raw_writel(l2x0_saved_regs.aux_ctrl, ++ writel_relaxed(l2x0_saved_regs.aux_ctrl, + sar_base + L2X0_AUXCTRL_OFFSET); - __raw_writel(l2x0_saved_regs.prefetch_ctrl, ++ writel_relaxed(l2x0_saved_regs.prefetch_ctrl, + sar_base + L2X0_PREFETCH_CTRL_OFFSET); } #else - static void save_l2x0_context(void) + static void __init save_l2x0_context(void) {} #endif diff --cc arch/arm/mach-orion5x/common.h index 26d6f34b6027,ca3803017c59..cd0389c6e822 --- a/arch/arm/mach-orion5x/common.h +++ b/arch/arm/mach-orion5x/common.h @@@ -64,16 -64,16 +64,15 @@@ int orion5x_pci_sys_setup(int nr, struc struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys); int orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); - struct meminfo; -/* board init functions for boards not fully converted to fdt */ -#ifdef CONFIG_MACH_EDMINI_V2_DT -void edmini_v2_init(void); -#else -static inline void edmini_v2_init(void) {}; -#endif - struct tag; - extern void __init tag_fixup_mem32(struct tag *, char **, struct meminfo *); + extern void __init tag_fixup_mem32(struct tag *, char **); +#ifdef CONFIG_MACH_MSS2_DT +extern void mss2_init(void); +#else +static inline void mss2_init(void) {} +#endif + /***************************************************************************** * Helpers to access Orion registers ****************************************************************************/ diff --cc arch/arm/mach-rockchip/rockchip.c index 4499b0a31a27,138b9975313a..968cc348e624 --- a/arch/arm/mach-rockchip/rockchip.c +++ b/arch/arm/mach-rockchip/rockchip.c @@@ -39,6 -33,8 +33,7 @@@ static const char * const rockchip_boar }; DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)") - .init_machine = rockchip_dt_init, + .l2c_aux_val = 0, + .l2c_aux_mask = ~0, - .smp = smp_ops(rockchip_smp_ops), .dt_compat = rockchip_board_dt_compat, MACHINE_END diff --cc arch/arm/mach-vexpress/v2m.c index 38f4f6f37770,b2fea70d412d..6ff681a24ba7 --- a/arch/arm/mach-vexpress/v2m.c +++ b/arch/arm/mach-vexpress/v2m.c @@@ -370,10 -369,70 +370,9 @@@ MACHINE_START(VEXPRESS, "ARM-Versatile .init_machine = v2m_init, MACHINE_END -static struct map_desc v2m_rs1_io_desc __initdata = { - .virtual = V2M_PERIPH, - .pfn = __phys_to_pfn(0x1c000000), - .length = SZ_2M, - .type = MT_DEVICE, -}; - -static int __init v2m_dt_scan_memory_map(unsigned long node, const char *uname, - int depth, void *data) -{ - const char **map = data; - - if (strcmp(uname, "motherboard") != 0) - return 0; - - *map = of_get_flat_dt_prop(node, "arm,v2m-memory-map", NULL); - - return 1; -} - -void __init v2m_dt_map_io(void) -{ - const char *map = NULL; - - of_scan_flat_dt(v2m_dt_scan_memory_map, &map); - - if (map && strcmp(map, "rs1") == 0) - iotable_init(&v2m_rs1_io_desc, 1); - else - iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc)); - -#if defined(CONFIG_SMP) - vexpress_dt_smp_map_io(); -#endif -} - -void __init v2m_dt_init_early(void) -{ - u32 dt_hbi; - - vexpress_sysreg_of_early_init(); - - /* Confirm board type against DT property, if available */ - if (of_property_read_u32(of_allnodes, "arm,hbi", &dt_hbi) == 0) { - u32 hbi = vexpress_get_hbi(VEXPRESS_SITE_MASTER); - - if (WARN_ON(dt_hbi != hbi)) - pr_warning("vexpress: DT HBI (%x) is not matching " - "hardware (%x)!\n", dt_hbi, hbi); - } - - versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000); -} - -static const struct of_device_id v2m_dt_bus_match[] __initconst = { - { .compatible = "simple-bus", }, - { .compatible = "arm,amba-bus", }, - { .compatible = "arm,vexpress,config-bus", }, - {} -}; - static void __init v2m_dt_init(void) { - l2x0_of_init(0x00400000, 0xfe0fffff); - of_platform_populate(NULL, v2m_dt_bus_match, NULL, NULL); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); } static const char * const v2m_dt_match[] __initconst = { @@@ -383,7 -442,11 +382,9 @@@ DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express") .dt_compat = v2m_dt_match, + .l2c_aux_val = 0x00400000, + .l2c_aux_mask = 0xfe0fffff, - .smp = smp_ops(vexpress_smp_ops), + .smp = smp_ops(vexpress_smp_dt_ops), .smp_init = smp_init_ops(vexpress_smp_init_ops), - .map_io = v2m_dt_map_io, - .init_early = v2m_dt_init_early, .init_machine = v2m_dt_init, MACHINE_END diff --cc arch/arm/mach-zynq/common.c index edbd9d83f407,d1e992e6403e..31a6fa40ba37 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@@ -105,43 -66,8 +105,38 @@@ static int __init zynq_get_revision(voi static void __init zynq_init_machine(void) { struct platform_device_info devinfo = { .name = "cpufreq-cpu0", }; + struct soc_device_attribute *soc_dev_attr; + struct soc_device *soc_dev; + struct device *parent = NULL; + - /* - * 64KB way size, 8-way associativity, parity disabled - */ - l2x0_of_init(0x02060000, 0xF0F0FFFF); - + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) + goto out; + + system_rev = zynq_get_revision(); + + soc_dev_attr->family = kasprintf(GFP_KERNEL, "Xilinx Zynq"); + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "0x%x", system_rev); + soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "0x%x", + zynq_slcr_get_device_id()); + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + kfree(soc_dev_attr->family); + kfree(soc_dev_attr->revision); + kfree(soc_dev_attr->soc_id); + kfree(soc_dev_attr); + goto out; + } + + parent = soc_device_to_device(soc_dev); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); +out: + /* + * Finished with the static registrations now; fill in the missing + * devices + */ + of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); platform_device_register(&zynq_cpuidle_device); platform_device_register_full(&devinfo); diff --cc drivers/of/address.c index 95351b2a112c,d244b2859aac..5edfcb0da37d --- a/drivers/of/address.c +++ b/drivers/of/address.c @@@ -701,3 -721,113 +701,113 @@@ void __iomem *of_iomap(struct device_no return ioremap(res.start, resource_size(&res)); } EXPORT_SYMBOL(of_iomap); + + /** + * of_dma_get_range - Get DMA range info + * @np: device node to get DMA range info + * @dma_addr: pointer to store initial DMA address of DMA range + * @paddr: pointer to store initial CPU address of DMA range + * @size: pointer to store size of DMA range + * + * Look in bottom up direction for the first "dma-ranges" property + * and parse it. + * dma-ranges format: + * DMA addr (dma_addr) : naddr cells + * CPU addr (phys_addr_t) : pna cells + * size : nsize cells + * + * It returns -ENODEV if "dma-ranges" property was not found + * for this device in DT. + */ + int of_dma_get_range(struct device_node *np, u64 *dma_addr, u64 *paddr, u64 *size) + { + struct device_node *node = of_node_get(np); + const __be32 *ranges = NULL; + int len, naddr, nsize, pna; + int ret = 0; + u64 dmaaddr; + + if (!node) + return -EINVAL; + + while (1) { + naddr = of_n_addr_cells(node); + nsize = of_n_size_cells(node); + node = of_get_next_parent(node); + if (!node) + break; + + ranges = of_get_property(node, "dma-ranges", &len); + + /* Ignore empty ranges, they imply no translation required */ + if (ranges && len > 0) + break; + + /* + * At least empty ranges has to be defined for parent node if + * DMA is supported + */ + if (!ranges) + break; + } + + if (!ranges) { + pr_debug("%s: no dma-ranges found for node(%s)\n", + __func__, np->full_name); + ret = -ENODEV; + goto out; + } + + len /= sizeof(u32); + + pna = of_n_addr_cells(node); + + /* dma-ranges format: + * DMA addr : naddr cells + * CPU addr : pna cells + * size : nsize cells + */ + dmaaddr = of_read_number(ranges, naddr); + *paddr = of_translate_dma_address(np, ranges); + if (*paddr == OF_BAD_ADDR) { + pr_err("%s: translation of DMA address(%pad) to CPU address failed node(%s)\n", + __func__, dma_addr, np->full_name); + ret = -EINVAL; + goto out; + } + *dma_addr = dmaaddr; + + *size = of_read_number(ranges + naddr + pna, nsize); + + pr_debug("dma_addr(%llx) cpu_addr(%llx) size(%llx)\n", + *dma_addr, *paddr, *size); + + out: + of_node_put(node); + + return ret; + } + EXPORT_SYMBOL_GPL(of_dma_get_range); + + /** + * of_dma_is_coherent - Check if device is coherent + * @np: device node + * + * It returns true if "dma-coherent" property was found + * for this device in DT. + */ + bool of_dma_is_coherent(struct device_node *np) + { + struct device_node *node = of_node_get(np); + + while (node) { + if (of_property_read_bool(node, "dma-coherent")) { + of_node_put(node); + return true; + } + node = of_get_next_parent(node); + } + of_node_put(node); + return false; + } -EXPORT_SYMBOL_GPL(of_dma_is_coherent); ++EXPORT_SYMBOL_GPL(of_dma_is_coherent); diff --cc drivers/of/platform.c index 92c060e58b02,4e91583a3908..d90a02d89f51 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@@ -176,14 -269,9 +234,9 @@@ static struct platform_device *of_platf dev = of_device_alloc(np, bus_id, parent); if (!dev) - return NULL; + goto err_clear_flag; - #if defined(CONFIG_MICROBLAZE) - dev->archdata.dma_mask = 0xffffffffUL; - #endif - dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); - if (!dev->dev.dma_mask) - dev->dev.dma_mask = &dev->dev.coherent_dma_mask; + of_dma_configure(dev); dev->dev.bus = &platform_bus_type; dev->dev.platform_data = platform_data;