From fe989145447341bff1ed68bd8aaee12ea860d461 Mon Sep 17 00:00:00 2001 From: panchaxari Date: Mon, 2 Dec 2013 16:58:51 +0530 Subject: [PATCH 1/5] ARM: integrator: Default enable ARM_PATCH_PHYS_VIRT, AUTO_ZRELADDR ARM_PATCH_PHYS_VIRT and AUTO_ZRELADDR has been enabled as default configs to integrator platform. Introduction of PHYS_VIRT config as default would enable phy-to-virt and virt-to-phy translation function at boot and module loading time and enforce dynamic reallocation of memory. AUTO_ZRELADDR config would enable calculation of kernel load address at run time. PHYS_VIRT config is mutually exclusive to XIP_KERNEL, XIP_KERNEL is used in systems with NOR flash devices, and ZRELADDR config is mutually exclusive to ZBOOT_ROM. Requesting maintainers of Integrator platform to evaluate the changes on the board and comment, as I dont have the board for testing and also requesting an ACK. Signed-off-by: panchaxari Cc: Linus Walleij Cc: Russell King Cc: Arnd Bergmann Cc: Michal Simek Cc: Olof Johansson Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Signed-off-by: Linus Walleij --- arch/arm/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c1f1a7eee953..b346fb11cc3e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -313,6 +313,8 @@ config ARCH_INTEGRATOR bool "ARM Ltd. Integrator family" select ARCH_HAS_CPUFREQ select ARM_AMBA + select ARM_PATCH_PHYS_VIRT + select AUTO_ZRELADDR select COMMON_CLK select COMMON_CLK_VERSATILE select GENERIC_CLOCKEVENTS From bdd272cbb97a66cf83061d22cfd19beb7267943a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 4 Oct 2013 15:15:35 +0200 Subject: [PATCH 2/5] irqchip: versatile FPGA: support cascaded interrupts from DT The Versatile FPGA interrupt controller supports cascading interrupts, i.e. that its output is connected to the input of another interrupt controller. This makes it possible to pass a parent interrupt from the device tree and print it in the boot log if applicable. Acked-by: Thomas Gleixner Signed-off-by: Linus Walleij --- .../bindings/arm/versatile-fpga-irq.txt | 5 +++++ drivers/irqchip/irq-versatile-fpga.c | 15 +++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/versatile-fpga-irq.txt b/Documentation/devicetree/bindings/arm/versatile-fpga-irq.txt index 9989eda755d9..c9cf605bb995 100644 --- a/Documentation/devicetree/bindings/arm/versatile-fpga-irq.txt +++ b/Documentation/devicetree/bindings/arm/versatile-fpga-irq.txt @@ -29,3 +29,8 @@ pic: pic@14000000 { clear-mask = <0xffffffff>; valid-mask = <0x003fffff>; }; + +Optional properties: +- interrupts: if the FPGA IRQ controller is cascaded, i.e. if its IRQ + output is simply connected to the input of another IRQ controller, + then the parent IRQ shall be specified in this property. diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c index 47a52ab580d8..3ae2bb8d9cf2 100644 --- a/drivers/irqchip/irq-versatile-fpga.c +++ b/drivers/irqchip/irq-versatile-fpga.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -167,8 +168,12 @@ void __init fpga_irq_init(void __iomem *base, const char *name, int irq_start, f->used_irqs++; } - pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs\n", + pr_info("FPGA IRQ chip %d \"%s\" @ %p, %u irqs", fpga_irq_id, name, base, f->used_irqs); + if (parent_irq != -1) + pr_cont(", parent IRQ: %d\n", parent_irq); + else + pr_cont("\n"); fpga_irq_id++; } @@ -180,6 +185,7 @@ int __init fpga_irq_of_init(struct device_node *node, void __iomem *base; u32 clear_mask; u32 valid_mask; + int parent_irq; if (WARN_ON(!node)) return -ENODEV; @@ -193,7 +199,12 @@ int __init fpga_irq_of_init(struct device_node *node, if (of_property_read_u32(node, "valid-mask", &valid_mask)) valid_mask = 0; - fpga_irq_init(base, node->name, 0, -1, valid_mask, node); + /* Some chips are cascaded from a parent IRQ */ + parent_irq = irq_of_parse_and_map(node, 0); + if (!parent_irq) + parent_irq = -1; + + fpga_irq_init(base, node->name, 0, parent_irq, valid_mask, node); writel(clear_mask, base + IRQ_ENABLE_CLEAR); writel(clear_mask, base + FIQ_ENABLE_CLEAR); From 8f6344faafb455e7481d87490d372c8337a0e32b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 4 Oct 2013 15:25:32 +0200 Subject: [PATCH 3/5] ARM: integrator: pass parent IRQ to the SIC The SIC is cascaded off the PIC, so specify this in the device tree. Signed-off-by: Linus Walleij --- arch/arm/boot/dts/integratorcp.dts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/boot/dts/integratorcp.dts b/arch/arm/boot/dts/integratorcp.dts index 7deb3a3182b4..a21c17de9a5e 100644 --- a/arch/arm/boot/dts/integratorcp.dts +++ b/arch/arm/boot/dts/integratorcp.dts @@ -47,8 +47,11 @@ valid-mask = <0x00000007>; }; + /* The SIC is cascaded off IRQ 26 on the PIC */ sic: sic@ca000000 { compatible = "arm,versatile-fpga-irq"; + interrupt-parent = <&pic>; + interrupts = <26>; #interrupt-cells = <1>; interrupt-controller; reg = <0xca000000 0x100>; From ae6e694ef566ed69a2537c80771a9031ec627494 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 22 Nov 2013 11:30:05 +0100 Subject: [PATCH 4/5] clk: versatile: pass a name to ICST clock provider When we have more than one of these clocks in a system (such as on the IM-PD1) we need a mechanism to pass a name for the clock. Refactor to add this as an argument. Acked-by: Mike Turquette Signed-off-by: Linus Walleij --- drivers/clk/versatile/clk-icst.c | 3 ++- drivers/clk/versatile/clk-icst.h | 1 + drivers/clk/versatile/clk-impd1.c | 4 ++-- drivers/clk/versatile/clk-integrator.c | 2 +- drivers/clk/versatile/clk-realview.c | 6 ++++-- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index f5e4c21b301f..8cbfcf88fae3 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -119,6 +119,7 @@ static const struct clk_ops icst_ops = { struct clk *icst_clk_register(struct device *dev, const struct clk_icst_desc *desc, + const char *name, void __iomem *base) { struct clk *clk; @@ -130,7 +131,7 @@ struct clk *icst_clk_register(struct device *dev, pr_err("could not allocate ICST clock!\n"); return ERR_PTR(-ENOMEM); } - init.name = "icst"; + init.name = name; init.ops = &icst_ops; init.flags = CLK_IS_ROOT; init.parent_names = NULL; diff --git a/drivers/clk/versatile/clk-icst.h b/drivers/clk/versatile/clk-icst.h index dad51b6ffd00..be99dd0da785 100644 --- a/drivers/clk/versatile/clk-icst.h +++ b/drivers/clk/versatile/clk-icst.h @@ -15,4 +15,5 @@ struct clk_icst_desc { struct clk *icst_clk_register(struct device *dev, const struct clk_icst_desc *desc, + const char *name, void __iomem *base); diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c index 369139af2a3b..b693a2bbf25a 100644 --- a/drivers/clk/versatile/clk-impd1.c +++ b/drivers/clk/versatile/clk-impd1.c @@ -66,8 +66,8 @@ void integrator_impd1_clk_init(void __iomem *base, unsigned int id) } imc = &impd1_clks[id]; - clk = icst_clk_register(NULL, &impd1_icst1_desc, base); - imc->vcoclk = clk; + clk = icst_clk_register(NULL, &impd1_icst1_desc, "icst1", base); + imc->vco1clk = clk; imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id); /* UART reference clock */ diff --git a/drivers/clk/versatile/clk-integrator.c b/drivers/clk/versatile/clk-integrator.c index 08593b4ee2c9..bda8967e09c2 100644 --- a/drivers/clk/versatile/clk-integrator.c +++ b/drivers/clk/versatile/clk-integrator.c @@ -78,7 +78,7 @@ void __init integrator_clk_init(bool is_cp) clk_register_clkdev(clk, NULL, "sp804"); /* ICST VCO clock used on the Integrator/CP CLCD */ - clk = icst_clk_register(NULL, &cp_icst_desc, + clk = icst_clk_register(NULL, &cp_icst_desc, "icst", __io_address(INTEGRATOR_HDR_BASE)); clk_register_clkdev(clk, NULL, "clcd"); } diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c index cda07e70a408..747e7b31117c 100644 --- a/drivers/clk/versatile/clk-realview.c +++ b/drivers/clk/versatile/clk-realview.c @@ -84,9 +84,11 @@ void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176) /* ICST VCO clock */ if (is_pb1176) - clk = icst_clk_register(NULL, &realview_osc0_desc, sysbase); + clk = icst_clk_register(NULL, &realview_osc0_desc, + "osc0", sysbase); else - clk = icst_clk_register(NULL, &realview_osc4_desc, sysbase); + clk = icst_clk_register(NULL, &realview_osc4_desc, + "osc4", sysbase); clk_register_clkdev(clk, NULL, "dev:clcd"); clk_register_clkdev(clk, NULL, "issp:clcd"); From 8e048b9997efbe75fe77b1f14d3af41700cc8724 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 22 Nov 2013 16:25:09 +0100 Subject: [PATCH 5/5] clk: versatile: fixup IM-PD1 clock implementation Register both VCO clocks, give per-logical module unique names to the clocks so we can have several IM-PD1's connected (in theory). Implement all the fixed-factor clocks as children of VCO2. Tested by using the UARTs and the PL181 MMC block on the IM-PD1, works flawlessly. Acked-by: Mike Turquette Signed-off-by: Linus Walleij --- drivers/clk/versatile/clk-impd1.c | 86 +++++++++++++++++++++++++------ 1 file changed, 71 insertions(+), 15 deletions(-) diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c index b693a2bbf25a..844f8d711a12 100644 --- a/drivers/clk/versatile/clk-impd1.c +++ b/drivers/clk/versatile/clk-impd1.c @@ -1,6 +1,6 @@ /* * Clock driver for the ARM Integrator/IM-PD1 board - * Copyright (C) 2012 Linus Walleij + * Copyright (C) 2012-2013 Linus Walleij * * 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 @@ -18,20 +18,28 @@ #include "clk-icst.h" struct impd1_clk { - struct clk *vcoclk; + char *vco1name; + struct clk *vco1clk; + char *vco2name; + struct clk *vco2clk; + struct clk *mmciclk; + char *uartname; struct clk *uartclk; - struct clk_lookup *clks[3]; + char *spiname; + struct clk *spiclk; + char *scname; + struct clk *scclk; + struct clk_lookup *clks[6]; }; +/* One entry for each connected IM-PD1 LM */ static struct impd1_clk impd1_clks[4]; /* - * There are two VCO's on the IM-PD1 but only one is used by the - * kernel, that is why we are only implementing the control of - * IMPD1_OSC1 here. + * There are two VCO's on the IM-PD1 */ -static const struct icst_params impd1_vco_params = { +static const struct icst_params impd1_vco1_params = { .ref = 24000000, /* 24 MHz */ .vco_max = ICST525_VCO_MAX_3V, .vco_min = ICST525_VCO_MIN, @@ -44,11 +52,29 @@ static const struct icst_params impd1_vco_params = { }; static const struct clk_icst_desc impd1_icst1_desc = { - .params = &impd1_vco_params, + .params = &impd1_vco1_params, .vco_offset = IMPD1_OSC1, .lock_offset = IMPD1_LOCK, }; +static const struct icst_params impd1_vco2_params = { + .ref = 24000000, /* 24 MHz */ + .vco_max = ICST525_VCO_MAX_3V, + .vco_min = ICST525_VCO_MIN, + .vd_min = 12, + .vd_max = 519, + .rd_min = 3, + .rd_max = 120, + .s2div = icst525_s2div, + .idx2s = icst525_idx2s, +}; + +static const struct clk_icst_desc impd1_icst2_desc = { + .params = &impd1_vco2_params, + .vco_offset = IMPD1_OSC2, + .lock_offset = IMPD1_LOCK, +}; + /** * integrator_impd1_clk_init() - set up the integrator clock tree * @base: base address of the logic module (LM) @@ -66,16 +92,39 @@ void integrator_impd1_clk_init(void __iomem *base, unsigned int id) } imc = &impd1_clks[id]; - clk = icst_clk_register(NULL, &impd1_icst1_desc, "icst1", base); + imc->vco1name = kasprintf(GFP_KERNEL, "lm%x-vco1", id); + clk = icst_clk_register(NULL, &impd1_icst1_desc, imc->vco1name, base); imc->vco1clk = clk; imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id); - /* UART reference clock */ - clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT, - 14745600); + /* VCO2 is also called "CLK2" */ + imc->vco2name = kasprintf(GFP_KERNEL, "lm%x-vco2", id); + clk = icst_clk_register(NULL, &impd1_icst2_desc, imc->vco2name, base); + imc->vco2clk = clk; + + /* MMCI uses CLK2 right off */ + imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:00700", id); + + /* UART reference clock divides CLK2 by a fixed factor 4 */ + imc->uartname = kasprintf(GFP_KERNEL, "lm%x-uartclk", id); + clk = clk_register_fixed_factor(NULL, imc->uartname, imc->vco2name, + CLK_IGNORE_UNUSED, 1, 4); imc->uartclk = clk; - imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:00100", id); - imc->clks[2] = clkdev_alloc(clk, NULL, "lm%x:00200", id); + imc->clks[2] = clkdev_alloc(clk, NULL, "lm%x:00100", id); + imc->clks[3] = clkdev_alloc(clk, NULL, "lm%x:00200", id); + + /* SPI PL022 clock divides CLK2 by a fixed factor 64 */ + imc->spiname = kasprintf(GFP_KERNEL, "lm%x-spiclk", id); + clk = clk_register_fixed_factor(NULL, imc->spiname, imc->vco2name, + CLK_IGNORE_UNUSED, 1, 64); + imc->clks[4] = clkdev_alloc(clk, NULL, "lm%x:00300", id); + + /* Smart Card clock divides CLK2 by a fixed factor 4 */ + imc->scname = kasprintf(GFP_KERNEL, "lm%x-scclk", id); + clk = clk_register_fixed_factor(NULL, imc->scname, imc->vco2name, + CLK_IGNORE_UNUSED, 1, 4); + imc->scclk = clk; + imc->clks[5] = clkdev_alloc(clk, NULL, "lm%x:00600", id); for (i = 0; i < ARRAY_SIZE(imc->clks); i++) clkdev_add(imc->clks[i]); @@ -92,6 +141,13 @@ void integrator_impd1_clk_exit(unsigned int id) for (i = 0; i < ARRAY_SIZE(imc->clks); i++) clkdev_drop(imc->clks[i]); + clk_unregister(imc->spiclk); clk_unregister(imc->uartclk); - clk_unregister(imc->vcoclk); + clk_unregister(imc->vco2clk); + clk_unregister(imc->vco1clk); + kfree(imc->scname); + kfree(imc->spiname); + kfree(imc->uartname); + kfree(imc->vco2name); + kfree(imc->vco1name); }