diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/versatile/clk-icst.c | 60 | ||||
-rw-r--r-- | drivers/clk/versatile/clk-icst.h | 14 | ||||
-rw-r--r-- | drivers/clk/versatile/clk-integrator.c | 45 | ||||
-rw-r--r-- | drivers/clk/versatile/clk-realview.c | 57 |
4 files changed, 81 insertions, 95 deletions
diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index 23d2d7ea1beb..67ccf4aa7277 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c | |||
@@ -17,33 +17,74 @@ | |||
17 | #include <linux/clkdev.h> | 17 | #include <linux/clkdev.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/clk-provider.h> | 19 | #include <linux/clk-provider.h> |
20 | #include <linux/io.h> | ||
20 | 21 | ||
21 | #include "clk-icst.h" | 22 | #include "clk-icst.h" |
22 | 23 | ||
23 | /** | 24 | /** |
24 | * struct clk_icst - ICST VCO clock wrapper | 25 | * struct clk_icst - ICST VCO clock wrapper |
25 | * @hw: corresponding clock hardware entry | 26 | * @hw: corresponding clock hardware entry |
27 | * @vcoreg: VCO register address | ||
28 | * @lockreg: VCO lock register address | ||
26 | * @params: parameters for this ICST instance | 29 | * @params: parameters for this ICST instance |
27 | * @rate: current rate | 30 | * @rate: current rate |
28 | * @setvco: function to commit ICST settings to hardware | ||
29 | */ | 31 | */ |
30 | struct clk_icst { | 32 | struct clk_icst { |
31 | struct clk_hw hw; | 33 | struct clk_hw hw; |
34 | void __iomem *vcoreg; | ||
35 | void __iomem *lockreg; | ||
32 | const struct icst_params *params; | 36 | const struct icst_params *params; |
33 | unsigned long rate; | 37 | unsigned long rate; |
34 | struct icst_vco (*getvco)(void); | ||
35 | void (*setvco)(struct icst_vco); | ||
36 | }; | 38 | }; |
37 | 39 | ||
38 | #define to_icst(_hw) container_of(_hw, struct clk_icst, hw) | 40 | #define to_icst(_hw) container_of(_hw, struct clk_icst, hw) |
39 | 41 | ||
42 | /** | ||
43 | * vco_get() - get ICST VCO settings from a certain register | ||
44 | * @vcoreg: register containing the VCO settings | ||
45 | */ | ||
46 | static struct icst_vco vco_get(void __iomem *vcoreg) | ||
47 | { | ||
48 | u32 val; | ||
49 | struct icst_vco vco; | ||
50 | |||
51 | val = readl(vcoreg); | ||
52 | vco.v = val & 0x1ff; | ||
53 | vco.r = (val >> 9) & 0x7f; | ||
54 | vco.s = (val >> 16) & 03; | ||
55 | return vco; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * vco_set() - commit changes to an ICST VCO | ||
60 | * @locreg: register to poke to unlock the VCO for writing | ||
61 | * @vcoreg: register containing the VCO settings | ||
62 | * @vco: ICST VCO parameters to commit | ||
63 | */ | ||
64 | static void vco_set(void __iomem *lockreg, | ||
65 | void __iomem *vcoreg, | ||
66 | struct icst_vco vco) | ||
67 | { | ||
68 | u32 val; | ||
69 | |||
70 | val = readl(vcoreg) & ~0x7ffff; | ||
71 | val |= vco.v | (vco.r << 9) | (vco.s << 16); | ||
72 | |||
73 | /* This magic unlocks the VCO so it can be controlled */ | ||
74 | writel(0xa05f, lockreg); | ||
75 | writel(val, vcoreg); | ||
76 | /* This locks the VCO again */ | ||
77 | writel(0, lockreg); | ||
78 | } | ||
79 | |||
80 | |||
40 | static unsigned long icst_recalc_rate(struct clk_hw *hw, | 81 | static unsigned long icst_recalc_rate(struct clk_hw *hw, |
41 | unsigned long parent_rate) | 82 | unsigned long parent_rate) |
42 | { | 83 | { |
43 | struct clk_icst *icst = to_icst(hw); | 84 | struct clk_icst *icst = to_icst(hw); |
44 | struct icst_vco vco; | 85 | struct icst_vco vco; |
45 | 86 | ||
46 | vco = icst->getvco(); | 87 | vco = vco_get(icst->vcoreg); |
47 | icst->rate = icst_hz(icst->params, vco); | 88 | icst->rate = icst_hz(icst->params, vco); |
48 | return icst->rate; | 89 | return icst->rate; |
49 | } | 90 | } |
@@ -66,7 +107,7 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate, | |||
66 | 107 | ||
67 | vco = icst_hz_to_vco(icst->params, rate); | 108 | vco = icst_hz_to_vco(icst->params, rate); |
68 | icst->rate = icst_hz(icst->params, vco); | 109 | icst->rate = icst_hz(icst->params, vco); |
69 | icst->setvco(vco); | 110 | vco_set(icst->vcoreg, icst->lockreg, vco); |
70 | return 0; | 111 | return 0; |
71 | } | 112 | } |
72 | 113 | ||
@@ -76,8 +117,9 @@ static const struct clk_ops icst_ops = { | |||
76 | .set_rate = icst_set_rate, | 117 | .set_rate = icst_set_rate, |
77 | }; | 118 | }; |
78 | 119 | ||
79 | struct clk * __init icst_clk_register(struct device *dev, | 120 | struct clk *icst_clk_register(struct device *dev, |
80 | const struct clk_icst_desc *desc) | 121 | const struct clk_icst_desc *desc, |
122 | void __iomem *base) | ||
81 | { | 123 | { |
82 | struct clk *clk; | 124 | struct clk *clk; |
83 | struct clk_icst *icst; | 125 | struct clk_icst *icst; |
@@ -95,8 +137,8 @@ struct clk * __init icst_clk_register(struct device *dev, | |||
95 | init.num_parents = 0; | 137 | init.num_parents = 0; |
96 | icst->hw.init = &init; | 138 | icst->hw.init = &init; |
97 | icst->params = desc->params; | 139 | icst->params = desc->params; |
98 | icst->getvco = desc->getvco; | 140 | icst->vcoreg = base + desc->vco_offset; |
99 | icst->setvco = desc->setvco; | 141 | icst->lockreg = base + desc->lock_offset; |
100 | 142 | ||
101 | clk = clk_register(dev, &icst->hw); | 143 | clk = clk_register(dev, &icst->hw); |
102 | if (IS_ERR(clk)) | 144 | if (IS_ERR(clk)) |
diff --git a/drivers/clk/versatile/clk-icst.h b/drivers/clk/versatile/clk-icst.h index 71b4c56c1410..dad51b6ffd00 100644 --- a/drivers/clk/versatile/clk-icst.h +++ b/drivers/clk/versatile/clk-icst.h | |||
@@ -1,10 +1,18 @@ | |||
1 | #include <asm/hardware/icst.h> | 1 | #include <asm/hardware/icst.h> |
2 | 2 | ||
3 | /** | ||
4 | * struct clk_icst_desc - descriptor for the ICST VCO | ||
5 | * @params: ICST parameters | ||
6 | * @vco_offset: offset to the ICST VCO from the provided memory base | ||
7 | * @lock_offset: offset to the ICST VCO locking register from the provided | ||
8 | * memory base | ||
9 | */ | ||
3 | struct clk_icst_desc { | 10 | struct clk_icst_desc { |
4 | const struct icst_params *params; | 11 | const struct icst_params *params; |
5 | struct icst_vco (*getvco)(void); | 12 | u32 vco_offset; |
6 | void (*setvco)(struct icst_vco); | 13 | u32 lock_offset; |
7 | }; | 14 | }; |
8 | 15 | ||
9 | struct clk *icst_clk_register(struct device *dev, | 16 | struct clk *icst_clk_register(struct device *dev, |
10 | const struct clk_icst_desc *desc); | 17 | const struct clk_icst_desc *desc, |
18 | void __iomem *base); | ||
diff --git a/drivers/clk/versatile/clk-integrator.c b/drivers/clk/versatile/clk-integrator.c index 3c816ae17c16..08593b4ee2c9 100644 --- a/drivers/clk/versatile/clk-integrator.c +++ b/drivers/clk/versatile/clk-integrator.c | |||
@@ -10,7 +10,7 @@ | |||
10 | #include <linux/clk.h> | 10 | #include <linux/clk.h> |
11 | #include <linux/clkdev.h> | 11 | #include <linux/clkdev.h> |
12 | #include <linux/err.h> | 12 | #include <linux/err.h> |
13 | #include <linux/io.h> | 13 | #include <linux/platform_data/clk-integrator.h> |
14 | 14 | ||
15 | #include <mach/hardware.h> | 15 | #include <mach/hardware.h> |
16 | #include <mach/platform.h> | 16 | #include <mach/platform.h> |
@@ -22,42 +22,6 @@ | |||
22 | * Inspired by portions of: | 22 | * Inspired by portions of: |
23 | * plat-versatile/clock.c and plat-versatile/include/plat/clock.h | 23 | * plat-versatile/clock.c and plat-versatile/include/plat/clock.h |
24 | */ | 24 | */ |
25 | #define CM_LOCK (__io_address(INTEGRATOR_HDR_BASE)+INTEGRATOR_HDR_LOCK_OFFSET) | ||
26 | #define CM_AUXOSC (__io_address(INTEGRATOR_HDR_BASE)+0x1c) | ||
27 | |||
28 | /** | ||
29 | * cp_auxvco_get() - get ICST VCO settings for the Integrator/CP | ||
30 | * @vco: ICST VCO parameters to update with hardware status | ||
31 | */ | ||
32 | static struct icst_vco cp_auxvco_get(void) | ||
33 | { | ||
34 | u32 val; | ||
35 | struct icst_vco vco; | ||
36 | |||
37 | val = readl(CM_AUXOSC); | ||
38 | vco.v = val & 0x1ff; | ||
39 | vco.r = (val >> 9) & 0x7f; | ||
40 | vco.s = (val >> 16) & 03; | ||
41 | return vco; | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * cp_auxvco_set() - commit changes to Integrator/CP ICST VCO | ||
46 | * @vco: ICST VCO parameters to commit | ||
47 | */ | ||
48 | static void cp_auxvco_set(struct icst_vco vco) | ||
49 | { | ||
50 | u32 val; | ||
51 | |||
52 | val = readl(CM_AUXOSC) & ~0x7ffff; | ||
53 | val |= vco.v | (vco.r << 9) | (vco.s << 16); | ||
54 | |||
55 | /* This magic unlocks the CM VCO so it can be controlled */ | ||
56 | writel(0xa05f, CM_LOCK); | ||
57 | writel(val, CM_AUXOSC); | ||
58 | /* This locks the CM again */ | ||
59 | writel(0, CM_LOCK); | ||
60 | } | ||
61 | 25 | ||
62 | static const struct icst_params cp_auxvco_params = { | 26 | static const struct icst_params cp_auxvco_params = { |
63 | .ref = 24000000, | 27 | .ref = 24000000, |
@@ -73,8 +37,8 @@ static const struct icst_params cp_auxvco_params = { | |||
73 | 37 | ||
74 | static const struct clk_icst_desc __initdata cp_icst_desc = { | 38 | static const struct clk_icst_desc __initdata cp_icst_desc = { |
75 | .params = &cp_auxvco_params, | 39 | .params = &cp_auxvco_params, |
76 | .getvco = cp_auxvco_get, | 40 | .vco_offset = 0x1c, |
77 | .setvco = cp_auxvco_set, | 41 | .lock_offset = INTEGRATOR_HDR_LOCK_OFFSET, |
78 | }; | 42 | }; |
79 | 43 | ||
80 | /* | 44 | /* |
@@ -114,6 +78,7 @@ void __init integrator_clk_init(bool is_cp) | |||
114 | clk_register_clkdev(clk, NULL, "sp804"); | 78 | clk_register_clkdev(clk, NULL, "sp804"); |
115 | 79 | ||
116 | /* ICST VCO clock used on the Integrator/CP CLCD */ | 80 | /* ICST VCO clock used on the Integrator/CP CLCD */ |
117 | clk = icst_clk_register(NULL, &cp_icst_desc); | 81 | clk = icst_clk_register(NULL, &cp_icst_desc, |
82 | __io_address(INTEGRATOR_HDR_BASE)); | ||
118 | clk_register_clkdev(clk, NULL, "clcd"); | 83 | clk_register_clkdev(clk, NULL, "clcd"); |
119 | } | 84 | } |
diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c index fd2dbdbc269d..cda07e70a408 100644 --- a/drivers/clk/versatile/clk-realview.c +++ b/drivers/clk/versatile/clk-realview.c | |||
@@ -21,38 +21,6 @@ | |||
21 | * Implementation of the ARM RealView clock trees. | 21 | * Implementation of the ARM RealView clock trees. |
22 | */ | 22 | */ |
23 | 23 | ||
24 | static void __iomem *sys_lock; | ||
25 | static void __iomem *sys_vcoreg; | ||
26 | |||
27 | /** | ||
28 | * realview_oscvco_get() - get ICST OSC settings for the RealView | ||
29 | */ | ||
30 | static struct icst_vco realview_oscvco_get(void) | ||
31 | { | ||
32 | u32 val; | ||
33 | struct icst_vco vco; | ||
34 | |||
35 | val = readl(sys_vcoreg); | ||
36 | vco.v = val & 0x1ff; | ||
37 | vco.r = (val >> 9) & 0x7f; | ||
38 | vco.s = (val >> 16) & 03; | ||
39 | return vco; | ||
40 | } | ||
41 | |||
42 | static void realview_oscvco_set(struct icst_vco vco) | ||
43 | { | ||
44 | u32 val; | ||
45 | |||
46 | val = readl(sys_vcoreg) & ~0x7ffff; | ||
47 | val |= vco.v | (vco.r << 9) | (vco.s << 16); | ||
48 | |||
49 | /* This magic unlocks the CM VCO so it can be controlled */ | ||
50 | writel(0xa05f, sys_lock); | ||
51 | writel(val, sys_vcoreg); | ||
52 | /* This locks the CM again */ | ||
53 | writel(0, sys_lock); | ||
54 | } | ||
55 | |||
56 | static const struct icst_params realview_oscvco_params = { | 24 | static const struct icst_params realview_oscvco_params = { |
57 | .ref = 24000000, | 25 | .ref = 24000000, |
58 | .vco_max = ICST307_VCO_MAX, | 26 | .vco_max = ICST307_VCO_MAX, |
@@ -65,10 +33,16 @@ static const struct icst_params realview_oscvco_params = { | |||
65 | .idx2s = icst307_idx2s, | 33 | .idx2s = icst307_idx2s, |
66 | }; | 34 | }; |
67 | 35 | ||
68 | static const struct clk_icst_desc __initdata realview_icst_desc = { | 36 | static const struct clk_icst_desc __initdata realview_osc0_desc = { |
69 | .params = &realview_oscvco_params, | 37 | .params = &realview_oscvco_params, |
70 | .getvco = realview_oscvco_get, | 38 | .vco_offset = REALVIEW_SYS_OSC0_OFFSET, |
71 | .setvco = realview_oscvco_set, | 39 | .lock_offset = REALVIEW_SYS_LOCK_OFFSET, |
40 | }; | ||
41 | |||
42 | static const struct clk_icst_desc __initdata realview_osc4_desc = { | ||
43 | .params = &realview_oscvco_params, | ||
44 | .vco_offset = REALVIEW_SYS_OSC4_OFFSET, | ||
45 | .lock_offset = REALVIEW_SYS_LOCK_OFFSET, | ||
72 | }; | 46 | }; |
73 | 47 | ||
74 | /* | 48 | /* |
@@ -78,13 +52,6 @@ void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176) | |||
78 | { | 52 | { |
79 | struct clk *clk; | 53 | struct clk *clk; |
80 | 54 | ||
81 | sys_lock = sysbase + REALVIEW_SYS_LOCK_OFFSET; | ||
82 | if (is_pb1176) | ||
83 | sys_vcoreg = sysbase + REALVIEW_SYS_OSC0_OFFSET; | ||
84 | else | ||
85 | sys_vcoreg = sysbase + REALVIEW_SYS_OSC4_OFFSET; | ||
86 | |||
87 | |||
88 | /* APB clock dummy */ | 55 | /* APB clock dummy */ |
89 | clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0); | 56 | clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0); |
90 | clk_register_clkdev(clk, "apb_pclk", NULL); | 57 | clk_register_clkdev(clk, "apb_pclk", NULL); |
@@ -116,7 +83,11 @@ void __init realview_clk_init(void __iomem *sysbase, bool is_pb1176) | |||
116 | clk_register_clkdev(clk, NULL, "sp804"); | 83 | clk_register_clkdev(clk, NULL, "sp804"); |
117 | 84 | ||
118 | /* ICST VCO clock */ | 85 | /* ICST VCO clock */ |
119 | clk = icst_clk_register(NULL, &realview_icst_desc); | 86 | if (is_pb1176) |
87 | clk = icst_clk_register(NULL, &realview_osc0_desc, sysbase); | ||
88 | else | ||
89 | clk = icst_clk_register(NULL, &realview_osc4_desc, sysbase); | ||
90 | |||
120 | clk_register_clkdev(clk, NULL, "dev:clcd"); | 91 | clk_register_clkdev(clk, NULL, "dev:clcd"); |
121 | clk_register_clkdev(clk, NULL, "issp:clcd"); | 92 | clk_register_clkdev(clk, NULL, "issp:clcd"); |
122 | } | 93 | } |