aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/versatile/clk-icst.c60
-rw-r--r--drivers/clk/versatile/clk-icst.h14
-rw-r--r--drivers/clk/versatile/clk-integrator.c45
-rw-r--r--drivers/clk/versatile/clk-realview.c57
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 */
30struct clk_icst { 32struct 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 */
46static 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 */
64static 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
40static unsigned long icst_recalc_rate(struct clk_hw *hw, 81static 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
79struct clk * __init icst_clk_register(struct device *dev, 120struct 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 */
3struct clk_icst_desc { 10struct 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
9struct clk *icst_clk_register(struct device *dev, 16struct 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 */
32static 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 */
48static 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
62static const struct icst_params cp_auxvco_params = { 26static 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
74static const struct clk_icst_desc __initdata cp_icst_desc = { 38static 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
24static void __iomem *sys_lock;
25static void __iomem *sys_vcoreg;
26
27/**
28 * realview_oscvco_get() - get ICST OSC settings for the RealView
29 */
30static 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
42static 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
56static const struct icst_params realview_oscvco_params = { 24static 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
68static const struct clk_icst_desc __initdata realview_icst_desc = { 36static 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
42static 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}