aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/versatile/clk-impd1.c86
1 files 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 @@
1/* 1/*
2 * Clock driver for the ARM Integrator/IM-PD1 board 2 * Clock driver for the ARM Integrator/IM-PD1 board
3 * Copyright (C) 2012 Linus Walleij 3 * Copyright (C) 2012-2013 Linus Walleij
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as 6 * it under the terms of the GNU General Public License version 2 as
@@ -18,20 +18,28 @@
18#include "clk-icst.h" 18#include "clk-icst.h"
19 19
20struct impd1_clk { 20struct impd1_clk {
21 struct clk *vcoclk; 21 char *vco1name;
22 struct clk *vco1clk;
23 char *vco2name;
24 struct clk *vco2clk;
25 struct clk *mmciclk;
26 char *uartname;
22 struct clk *uartclk; 27 struct clk *uartclk;
23 struct clk_lookup *clks[3]; 28 char *spiname;
29 struct clk *spiclk;
30 char *scname;
31 struct clk *scclk;
32 struct clk_lookup *clks[6];
24}; 33};
25 34
35/* One entry for each connected IM-PD1 LM */
26static struct impd1_clk impd1_clks[4]; 36static struct impd1_clk impd1_clks[4];
27 37
28/* 38/*
29 * There are two VCO's on the IM-PD1 but only one is used by the 39 * There are two VCO's on the IM-PD1
30 * kernel, that is why we are only implementing the control of
31 * IMPD1_OSC1 here.
32 */ 40 */
33 41
34static const struct icst_params impd1_vco_params = { 42static const struct icst_params impd1_vco1_params = {
35 .ref = 24000000, /* 24 MHz */ 43 .ref = 24000000, /* 24 MHz */
36 .vco_max = ICST525_VCO_MAX_3V, 44 .vco_max = ICST525_VCO_MAX_3V,
37 .vco_min = ICST525_VCO_MIN, 45 .vco_min = ICST525_VCO_MIN,
@@ -44,11 +52,29 @@ static const struct icst_params impd1_vco_params = {
44}; 52};
45 53
46static const struct clk_icst_desc impd1_icst1_desc = { 54static const struct clk_icst_desc impd1_icst1_desc = {
47 .params = &impd1_vco_params, 55 .params = &impd1_vco1_params,
48 .vco_offset = IMPD1_OSC1, 56 .vco_offset = IMPD1_OSC1,
49 .lock_offset = IMPD1_LOCK, 57 .lock_offset = IMPD1_LOCK,
50}; 58};
51 59
60static const struct icst_params impd1_vco2_params = {
61 .ref = 24000000, /* 24 MHz */
62 .vco_max = ICST525_VCO_MAX_3V,
63 .vco_min = ICST525_VCO_MIN,
64 .vd_min = 12,
65 .vd_max = 519,
66 .rd_min = 3,
67 .rd_max = 120,
68 .s2div = icst525_s2div,
69 .idx2s = icst525_idx2s,
70};
71
72static const struct clk_icst_desc impd1_icst2_desc = {
73 .params = &impd1_vco2_params,
74 .vco_offset = IMPD1_OSC2,
75 .lock_offset = IMPD1_LOCK,
76};
77
52/** 78/**
53 * integrator_impd1_clk_init() - set up the integrator clock tree 79 * integrator_impd1_clk_init() - set up the integrator clock tree
54 * @base: base address of the logic module (LM) 80 * @base: base address of the logic module (LM)
@@ -66,16 +92,39 @@ void integrator_impd1_clk_init(void __iomem *base, unsigned int id)
66 } 92 }
67 imc = &impd1_clks[id]; 93 imc = &impd1_clks[id];
68 94
69 clk = icst_clk_register(NULL, &impd1_icst1_desc, "icst1", base); 95 imc->vco1name = kasprintf(GFP_KERNEL, "lm%x-vco1", id);
96 clk = icst_clk_register(NULL, &impd1_icst1_desc, imc->vco1name, base);
70 imc->vco1clk = clk; 97 imc->vco1clk = clk;
71 imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id); 98 imc->clks[0] = clkdev_alloc(clk, NULL, "lm%x:01000", id);
72 99
73 /* UART reference clock */ 100 /* VCO2 is also called "CLK2" */
74 clk = clk_register_fixed_rate(NULL, "uartclk", NULL, CLK_IS_ROOT, 101 imc->vco2name = kasprintf(GFP_KERNEL, "lm%x-vco2", id);
75 14745600); 102 clk = icst_clk_register(NULL, &impd1_icst2_desc, imc->vco2name, base);
103 imc->vco2clk = clk;
104
105 /* MMCI uses CLK2 right off */
106 imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:00700", id);
107
108 /* UART reference clock divides CLK2 by a fixed factor 4 */
109 imc->uartname = kasprintf(GFP_KERNEL, "lm%x-uartclk", id);
110 clk = clk_register_fixed_factor(NULL, imc->uartname, imc->vco2name,
111 CLK_IGNORE_UNUSED, 1, 4);
76 imc->uartclk = clk; 112 imc->uartclk = clk;
77 imc->clks[1] = clkdev_alloc(clk, NULL, "lm%x:00100", id); 113 imc->clks[2] = clkdev_alloc(clk, NULL, "lm%x:00100", id);
78 imc->clks[2] = clkdev_alloc(clk, NULL, "lm%x:00200", id); 114 imc->clks[3] = clkdev_alloc(clk, NULL, "lm%x:00200", id);
115
116 /* SPI PL022 clock divides CLK2 by a fixed factor 64 */
117 imc->spiname = kasprintf(GFP_KERNEL, "lm%x-spiclk", id);
118 clk = clk_register_fixed_factor(NULL, imc->spiname, imc->vco2name,
119 CLK_IGNORE_UNUSED, 1, 64);
120 imc->clks[4] = clkdev_alloc(clk, NULL, "lm%x:00300", id);
121
122 /* Smart Card clock divides CLK2 by a fixed factor 4 */
123 imc->scname = kasprintf(GFP_KERNEL, "lm%x-scclk", id);
124 clk = clk_register_fixed_factor(NULL, imc->scname, imc->vco2name,
125 CLK_IGNORE_UNUSED, 1, 4);
126 imc->scclk = clk;
127 imc->clks[5] = clkdev_alloc(clk, NULL, "lm%x:00600", id);
79 128
80 for (i = 0; i < ARRAY_SIZE(imc->clks); i++) 129 for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
81 clkdev_add(imc->clks[i]); 130 clkdev_add(imc->clks[i]);
@@ -92,6 +141,13 @@ void integrator_impd1_clk_exit(unsigned int id)
92 141
93 for (i = 0; i < ARRAY_SIZE(imc->clks); i++) 142 for (i = 0; i < ARRAY_SIZE(imc->clks); i++)
94 clkdev_drop(imc->clks[i]); 143 clkdev_drop(imc->clks[i]);
144 clk_unregister(imc->spiclk);
95 clk_unregister(imc->uartclk); 145 clk_unregister(imc->uartclk);
96 clk_unregister(imc->vcoclk); 146 clk_unregister(imc->vco2clk);
147 clk_unregister(imc->vco1clk);
148 kfree(imc->scname);
149 kfree(imc->spiname);
150 kfree(imc->uartname);
151 kfree(imc->vco2name);
152 kfree(imc->vco1name);
97} 153}