aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorBen Dooks <ben-linux@fluff.org>2008-11-21 05:36:04 -0500
committerBen Dooks <ben-linux@fluff.org>2008-12-15 16:46:24 -0500
commit82fd8e681d60a195ce6e9fc783d0ebe7a81b1ead (patch)
tree8163599c280ebacf42015f3b3bf0a159e330d180 /arch/arm
parentf2edc7565a14aa82231c847abf33d02314cac9f9 (diff)
[ARM] S3C: Add set_rate/round_rate methods for pwm-scaler clock
Add the set_rate and round_rate methods for the pwm-scaler clock for use with the time code. Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/plat-s3c/pwm-clock.c51
1 files changed, 47 insertions, 4 deletions
diff --git a/arch/arm/plat-s3c/pwm-clock.c b/arch/arm/plat-s3c/pwm-clock.c
index 3fad68a1e6bc..b0fcbc1fb64b 100644
--- a/arch/arm/plat-s3c/pwm-clock.c
+++ b/arch/arm/plat-s3c/pwm-clock.c
@@ -73,7 +73,7 @@
73 * tclk -------------------------/ 73 * tclk -------------------------/
74*/ 74*/
75 75
76static unsigned long clk_pwm_scaler_getrate(struct clk *clk) 76static unsigned long clk_pwm_scaler_get_rate(struct clk *clk)
77{ 77{
78 unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0); 78 unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0);
79 79
@@ -87,18 +87,61 @@ static unsigned long clk_pwm_scaler_getrate(struct clk *clk)
87 return clk_get_rate(clk->parent) / (tcfg0 + 1); 87 return clk_get_rate(clk->parent) / (tcfg0 + 1);
88} 88}
89 89
90/* TODO - add set rate calls. */ 90static unsigned long clk_pwm_scaler_round_rate(struct clk *clk,
91 unsigned long rate)
92{
93 unsigned long parent_rate = clk_get_rate(clk->parent);
94 unsigned long divisor = parent_rate / rate;
95
96 if (divisor > 256)
97 divisor = 256;
98 else if (divisor < 2)
99 divisor = 2;
100
101 return parent_rate / divisor;
102}
103
104static int clk_pwm_scaler_set_rate(struct clk *clk, unsigned long rate)
105{
106 unsigned long round = clk_pwm_scaler_round_rate(clk, rate);
107 unsigned long tcfg0;
108 unsigned long divisor;
109 unsigned long flags;
110
111 divisor = clk_get_rate(clk->parent) / round;
112 divisor--;
113
114 local_irq_save(flags);
115 tcfg0 = __raw_readl(S3C2410_TCFG0);
116
117 if (clk->id == 1) {
118 tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
119 tcfg0 |= divisor << S3C2410_TCFG_PRESCALER1_SHIFT;
120 } else {
121 tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
122 tcfg0 |= divisor;
123 }
124
125 __raw_writel(tcfg0, S3C2410_TCFG0);
126 local_irq_restore(flags);
127
128 return 0;
129}
91 130
92static struct clk clk_timer_scaler[] = { 131static struct clk clk_timer_scaler[] = {
93 [0] = { 132 [0] = {
94 .name = "pwm-scaler0", 133 .name = "pwm-scaler0",
95 .id = -1, 134 .id = -1,
96 .get_rate = clk_pwm_scaler_getrate, 135 .get_rate = clk_pwm_scaler_get_rate,
136 .set_rate = clk_pwm_scaler_set_rate,
137 .round_rate = clk_pwm_scaler_round_rate,
97 }, 138 },
98 [1] = { 139 [1] = {
99 .name = "pwm-scaler1", 140 .name = "pwm-scaler1",
100 .id = -1, 141 .id = -1,
101 .get_rate = clk_pwm_scaler_getrate, 142 .get_rate = clk_pwm_scaler_get_rate,
143 .set_rate = clk_pwm_scaler_set_rate,
144 .round_rate = clk_pwm_scaler_round_rate,
102 }, 145 },
103}; 146};
104 147