mirror of
https://github.com/torvalds/linux.git
synced 2024-12-01 08:31:37 +00:00
Some Integrator patches that matured for v3.14:
- Use PATCH_PHYS_TO_VIRT and AUTO_ZRELADDR. - Support cascaded interrupts on the SIC. - Complete clock implementation for the IM-PD1. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJSxyvwAAoJEEEQszewGV1zObQQAI7bN0/vmtZkoBbIeoXTAolZ KTEqf+Gdtlny4AvW4PUeutDRr4zvFHKYo5uBbr9bQFl4S89ke29nLXhyrvJbAWJs tujyX0mWb38fosEGeVo3YGbDIw9+O3CMRM+zaHyt/yzcHANnPeecpt3dFNheaTKs W7Axw5YFszpfxs5xQYMrrudbXd6TbsZWSn1pJpNlPvoo8b0HV72ARZNDAM2NO2rY rOSUzl8MKb0tAW7Nj4D8vLqAtYkjA7lX6sdXQBbqpUyTINR5/35ifW/K74q1miMS 3T5ECbwrW9CHSW2jrTt28knafasAsJKCMdJ9SXu7uzOZogglTuBSw52MIhP2QvHS mxOXBHkCazCMum4WndLe1ygSigQZR2SAufmjzESsE82RBF2UmkgqR34aaxag9x/X avxUM/3Opgosa12AD8buSP5NfYqMjvqXzwdNs6YbC1UPqRYIgn9FcJ6cFzkVXoKi GWgz6Ko6MiR9HVDBqw8uHrIBKuaa3oZ5+jt0x54ZuI3tOxV1wUxR3AcgWQsF2tSN nPg8GTvZNiEfo6fWSIx7V2H/txFfAj1Z3JG6tFQTfLtE5G7MssxyNitoxZsIeWuB x1+tnsOQRpBlkUb92LS37ndLJoFfknbCgFUAIgMozntfCRQi/6REWAKGDo0fTOmG +uN+Q6JMFj62jZ6dgumd =cCZc -----END PGP SIGNATURE----- Merge tag 'integrator-for-v3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator into next/drivers From Linus Walleij: Some Integrator patches that matured for v3.14: - Use PATCH_PHYS_TO_VIRT and AUTO_ZRELADDR. - Support cascaded interrupts on the SIC. - Complete clock implementation for the IM-PD1. * tag 'integrator-for-v3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator: clk: versatile: fixup IM-PD1 clock implementation clk: versatile: pass a name to ICST clock provider ARM: integrator: pass parent IRQ to the SIC irqchip: versatile FPGA: support cascaded interrupts from DT ARM: integrator: Default enable ARM_PATCH_PHYS_VIRT, AUTO_ZRELADDR Signed-off-by: Olof Johansson <olof@lixom.net>
This commit is contained in:
commit
3d7e0207ce
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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>;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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, base);
|
||||
imc->vcoclk = clk;
|
||||
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);
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
||||
#include <asm/exception.h>
|
||||
#include <asm/mach/irq.h>
|
||||
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user