diff options
-rw-r--r-- | arch/arm/plat-s3c/pwm-clock.c | 51 |
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 | ||
76 | static unsigned long clk_pwm_scaler_getrate(struct clk *clk) | 76 | static 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. */ | 90 | static 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 | |||
104 | static 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 | ||
92 | static struct clk clk_timer_scaler[] = { | 131 | static 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 | ||