summaryrefslogtreecommitdiff
path: root/drivers/clk/versatile
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-08 22:31:16 +0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-08 22:31:16 +0400
commit3f17ea6dea8ba5668873afa54628a91aaa3fb1c0 (patch)
treeafbeb2accd4c2199ddd705ae943995b143a0af02 /drivers/clk/versatile
parent1860e379875dfe7271c649058aeddffe5afd9d0d (diff)
parent1a5700bc2d10cd379a795fd2bb377a190af5acd4 (diff)
downloadlinux-3f17ea6dea8ba5668873afa54628a91aaa3fb1c0.tar.xz
Merge branch 'next' (accumulated 3.16 merge window patches) into master
Now that 3.15 is released, this merges the 'next' branch into 'master', bringing us to the normal situation where my 'master' branch is the merge window. * accumulated work in next: (6809 commits) ufs: sb mutex merge + mutex_destroy powerpc: update comments for generic idle conversion cris: update comments for generic idle conversion idle: remove cpu_idle() forward declarations nbd: zero from and len fields in NBD_CMD_DISCONNECT. mm: convert some level-less printks to pr_* MAINTAINERS: adi-buildroot-devel is moderated MAINTAINERS: add linux-api for review of API/ABI changes mm/kmemleak-test.c: use pr_fmt for logging fs/dlm/debug_fs.c: replace seq_printf by seq_puts fs/dlm/lockspace.c: convert simple_str to kstr fs/dlm/config.c: convert simple_str to kstr mm: mark remap_file_pages() syscall as deprecated mm: memcontrol: remove unnecessary memcg argument from soft limit functions mm: memcontrol: clean up memcg zoneinfo lookup mm/memblock.c: call kmemleak directly from memblock_(alloc|free) mm/mempool.c: update the kmemleak stack trace for mempool allocations lib/radix-tree.c: update the kmemleak stack trace for radix tree allocations mm: introduce kmemleak_update_trace() mm/kmemleak.c: use %u to print ->checksum ...
Diffstat (limited to 'drivers/clk/versatile')
-rw-r--r--drivers/clk/versatile/Kconfig26
-rw-r--r--drivers/clk/versatile/Makefile5
-rw-r--r--drivers/clk/versatile/clk-icst.c2
-rw-r--r--drivers/clk/versatile/clk-impd1.c38
-rw-r--r--drivers/clk/versatile/clk-vexpress-osc.c96
5 files changed, 104 insertions, 63 deletions
diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig
new file mode 100644
index 000000000000..1530c9352a76
--- /dev/null
+++ b/drivers/clk/versatile/Kconfig
@@ -0,0 +1,26 @@
+config COMMON_CLK_VERSATILE
+ bool "Clock driver for ARM Reference designs"
+ depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64
+ ---help---
+ Supports clocking on ARM Reference designs:
+ - Integrator/AP and Integrator/CP
+ - RealView PB1176, EB, PB11MP and PBX
+ - Versatile Express
+
+config CLK_SP810
+ bool "Clock driver for ARM SP810 System Controller"
+ depends on COMMON_CLK_VERSATILE
+ default y if ARCH_VEXPRESS
+ ---help---
+ Supports clock muxing (REFCLK/TIMCLK to TIMERCLKEN0-3) capabilities
+ of the ARM SP810 System Controller cell.
+
+config CLK_VEXPRESS_OSC
+ bool "Clock driver for Versatile Express OSC clock generators"
+ depends on COMMON_CLK_VERSATILE
+ depends on VEXPRESS_CONFIG
+ default y if ARCH_VEXPRESS
+ ---help---
+ Simple regmap-based driver driving clock generators on Versatile
+ Express platforms hidden behind its configuration infrastructure,
+ commonly known as OSCs.
diff --git a/drivers/clk/versatile/Makefile b/drivers/clk/versatile/Makefile
index c16ca787170a..fd449f9b006d 100644
--- a/drivers/clk/versatile/Makefile
+++ b/drivers/clk/versatile/Makefile
@@ -3,5 +3,6 @@ obj-$(CONFIG_ICST) += clk-icst.o
obj-$(CONFIG_ARCH_INTEGRATOR) += clk-integrator.o
obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o
obj-$(CONFIG_ARCH_REALVIEW) += clk-realview.o
-obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o clk-sp810.o
-obj-$(CONFIG_VEXPRESS_CONFIG) += clk-vexpress-osc.o
+obj-$(CONFIG_ARCH_VEXPRESS) += clk-vexpress.o
+obj-$(CONFIG_CLK_SP810) += clk-sp810.o
+obj-$(CONFIG_CLK_VEXPRESS_OSC) += clk-vexpress-osc.o
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c
index a820b0cfcf57..bc96f103bd7c 100644
--- a/drivers/clk/versatile/clk-icst.c
+++ b/drivers/clk/versatile/clk-icst.c
@@ -140,6 +140,7 @@ struct clk *icst_clk_register(struct device *dev,
pclone = kmemdup(desc->params, sizeof(*pclone), GFP_KERNEL);
if (!pclone) {
+ kfree(icst);
pr_err("could not clone ICST params\n");
return ERR_PTR(-ENOMEM);
}
@@ -160,3 +161,4 @@ struct clk *icst_clk_register(struct device *dev,
return clk;
}
+EXPORT_SYMBOL_GPL(icst_clk_register);
diff --git a/drivers/clk/versatile/clk-impd1.c b/drivers/clk/versatile/clk-impd1.c
index 31b44f025f9e..1cc1330dc570 100644
--- a/drivers/clk/versatile/clk-impd1.c
+++ b/drivers/clk/versatile/clk-impd1.c
@@ -20,6 +20,8 @@
#define IMPD1_LOCK 0x08
struct impd1_clk {
+ char *pclkname;
+ struct clk *pclk;
char *vco1name;
struct clk *vco1clk;
char *vco2name;
@@ -31,7 +33,7 @@ struct impd1_clk {
struct clk *spiclk;
char *scname;
struct clk *scclk;
- struct clk_lookup *clks[6];
+ struct clk_lookup *clks[15];
};
/* One entry for each connected IM-PD1 LM */
@@ -86,6 +88,7 @@ void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
{
struct impd1_clk *imc;
struct clk *clk;
+ struct clk *pclk;
int i;
if (id > 3) {
@@ -94,11 +97,18 @@ void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
}
imc = &impd1_clks[id];
+ /* Register the fixed rate PCLK */
+ imc->pclkname = kasprintf(GFP_KERNEL, "lm%x-pclk", id);
+ pclk = clk_register_fixed_rate(NULL, imc->pclkname, NULL,
+ CLK_IS_ROOT, 0);
+ imc->pclk = pclk;
+
imc->vco1name = kasprintf(GFP_KERNEL, "lm%x-vco1", id);
clk = icst_clk_register(NULL, &impd1_icst1_desc, imc->vco1name, NULL,
base);
imc->vco1clk = clk;
- imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id);
+ imc->clks[0] = clkdev_alloc(pclk, "apb_pclk", "lm%x:01000", id);
+ imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:01000", id);
/* VCO2 is also called "CLK2" */
imc->vco2name = kasprintf(GFP_KERNEL, "lm%x-vco2", id);
@@ -107,32 +117,43 @@ void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
imc->vco2clk = clk;
/* MMCI uses CLK2 right off */
- imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:00700", id);
+ imc->clks[2] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00700", id);
+ imc->clks[3] = 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[2] = clkdev_alloc(clk, NULL, "lm%x:00100", id);
- imc->clks[3] = clkdev_alloc(clk, NULL, "lm%x:00200", id);
+ imc->clks[4] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00100", id);
+ imc->clks[5] = clkdev_alloc(clk, NULL, "lm%x:00100", id);
+ imc->clks[6] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00200", id);
+ imc->clks[7] = 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);
+ imc->clks[8] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00300", id);
+ imc->clks[9] = clkdev_alloc(clk, NULL, "lm%x:00300", id);
+
+ /* The GPIO blocks and AACI have only PCLK */
+ imc->clks[10] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00400", id);
+ imc->clks[11] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00500", id);
+ imc->clks[12] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00800", 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);
+ imc->clks[13] = clkdev_alloc(pclk, "apb_pclk", "lm%x:00600", id);
+ imc->clks[14] = clkdev_alloc(clk, NULL, "lm%x:00600", id);
for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
clkdev_add(imc->clks[i]);
}
+EXPORT_SYMBOL_GPL(integrator_impd1_clk_init);
void integrator_impd1_clk_exit(unsigned int id)
{
@@ -149,9 +170,12 @@ void integrator_impd1_clk_exit(unsigned int id)
clk_unregister(imc->uartclk);
clk_unregister(imc->vco2clk);
clk_unregister(imc->vco1clk);
+ clk_unregister(imc->pclk);
kfree(imc->scname);
kfree(imc->spiname);
kfree(imc->uartname);
kfree(imc->vco2name);
kfree(imc->vco1name);
+ kfree(imc->pclkname);
}
+EXPORT_SYMBOL_GPL(integrator_impd1_clk_exit);
diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c
index 422391242b39..529a59c0fbfa 100644
--- a/drivers/clk/versatile/clk-vexpress-osc.c
+++ b/drivers/clk/versatile/clk-vexpress-osc.c
@@ -11,8 +11,6 @@
* Copyright (C) 2012 ARM Limited
*/
-#define pr_fmt(fmt) "vexpress-osc: " fmt
-
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
@@ -22,7 +20,7 @@
#include <linux/vexpress.h>
struct vexpress_osc {
- struct vexpress_config_func *func;
+ struct regmap *reg;
struct clk_hw hw;
unsigned long rate_min;
unsigned long rate_max;
@@ -36,7 +34,7 @@ static unsigned long vexpress_osc_recalc_rate(struct clk_hw *hw,
struct vexpress_osc *osc = to_vexpress_osc(hw);
u32 rate;
- vexpress_config_read(osc->func, 0, &rate);
+ regmap_read(osc->reg, 0, &rate);
return rate;
}
@@ -60,7 +58,7 @@ static int vexpress_osc_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct vexpress_osc *osc = to_vexpress_osc(hw);
- return vexpress_config_write(osc->func, 0, rate);
+ return regmap_write(osc->reg, 0, rate);
}
static struct clk_ops vexpress_osc_ops = {
@@ -70,58 +68,31 @@ static struct clk_ops vexpress_osc_ops = {
};
-struct clk * __init vexpress_osc_setup(struct device *dev)
-{
- struct clk_init_data init;
- struct vexpress_osc *osc = kzalloc(sizeof(*osc), GFP_KERNEL);
-
- if (!osc)
- return NULL;
-
- osc->func = vexpress_config_func_get_by_dev(dev);
- if (!osc->func) {
- kfree(osc);
- return NULL;
- }
-
- init.name = dev_name(dev);
- init.ops = &vexpress_osc_ops;
- init.flags = CLK_IS_ROOT;
- init.num_parents = 0;
- osc->hw.init = &init;
-
- return clk_register(NULL, &osc->hw);
-}
-
-void __init vexpress_osc_of_setup(struct device_node *node)
+static int vexpress_osc_probe(struct platform_device *pdev)
{
+ struct clk_lookup *cl = pdev->dev.platform_data; /* Non-DT lookup */
struct clk_init_data init;
struct vexpress_osc *osc;
struct clk *clk;
u32 range[2];
- vexpress_sysreg_of_early_init();
-
- osc = kzalloc(sizeof(*osc), GFP_KERNEL);
+ osc = devm_kzalloc(&pdev->dev, sizeof(*osc), GFP_KERNEL);
if (!osc)
- return;
+ return -ENOMEM;
- osc->func = vexpress_config_func_get_by_node(node);
- if (!osc->func) {
- pr_err("Failed to obtain config func for node '%s'!\n",
- node->full_name);
- goto error;
- }
+ osc->reg = devm_regmap_init_vexpress_config(&pdev->dev);
+ if (IS_ERR(osc->reg))
+ return PTR_ERR(osc->reg);
- if (of_property_read_u32_array(node, "freq-range", range,
+ if (of_property_read_u32_array(pdev->dev.of_node, "freq-range", range,
ARRAY_SIZE(range)) == 0) {
osc->rate_min = range[0];
osc->rate_max = range[1];
}
- of_property_read_string(node, "clock-output-names", &init.name);
- if (!init.name)
- init.name = node->full_name;
+ if (of_property_read_string(pdev->dev.of_node, "clock-output-names",
+ &init.name) != 0)
+ init.name = dev_name(&pdev->dev);
init.ops = &vexpress_osc_ops;
init.flags = CLK_IS_ROOT;
@@ -130,20 +101,37 @@ void __init vexpress_osc_of_setup(struct device_node *node)
osc->hw.init = &init;
clk = clk_register(NULL, &osc->hw);
- if (IS_ERR(clk)) {
- pr_err("Failed to register clock '%s'!\n", init.name);
- goto error;
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, clk);
+
+ /* Only happens for non-DT cases */
+ if (cl) {
+ cl->clk = clk;
+ clkdev_add(cl);
}
- of_clk_add_provider(node, of_clk_src_simple_get, clk);
+ dev_dbg(&pdev->dev, "Registered clock '%s'\n", init.name);
+
+ return 0;
+}
- pr_debug("Registered clock '%s'\n", init.name);
+static struct of_device_id vexpress_osc_of_match[] = {
+ { .compatible = "arm,vexpress-osc", },
+ {}
+};
- return;
+static struct platform_driver vexpress_osc_driver = {
+ .driver = {
+ .name = "vexpress-osc",
+ .of_match_table = vexpress_osc_of_match,
+ },
+ .probe = vexpress_osc_probe,
+};
-error:
- if (osc->func)
- vexpress_config_func_put(osc->func);
- kfree(osc);
+static int __init vexpress_osc_init(void)
+{
+ return platform_driver_register(&vexpress_osc_driver);
}
-CLK_OF_DECLARE(vexpress_soc, "arm,vexpress-osc", vexpress_osc_of_setup);
+core_initcall(vexpress_osc_init);