changed Makefile and profiles, added patches for kernel 2.6.24
[openwrt.git] / target / linux / s3c24xx / patches-2.6.24 / 1015-s3c2410-pwm.patch.patch
1 From e9db29d62cbcef7974099c3a4deac69ad2a72190 Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Fri, 4 Apr 2008 11:31:44 +0100
4 Subject: [PATCH] s3c2410-pwm.patch
5  This patch adds a PWM api abstraction for the S3C2410 SoC
6
7 Signed-off-by: Javi Roman <javiroman@kernel-labs.org>
8 Signed-off-by: Harald Welte <laforge@openmoko.org>
9 ---
10  arch/arm/mach-s3c2410/Kconfig      |    6 +
11  arch/arm/mach-s3c2410/Makefile     |    1 +
12  arch/arm/mach-s3c2410/pwm.c        |  214 ++++++++++++++++++++++++++++++++++++
13  include/asm-arm/arch-s3c2410/pwm.h |   40 +++++++
14  4 files changed, 261 insertions(+), 0 deletions(-)
15  create mode 100644 arch/arm/mach-s3c2410/pwm.c
16  create mode 100644 include/asm-arm/arch-s3c2410/pwm.h
17
18 diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
19 index ff339e1..e42195f 100644
20 --- a/arch/arm/mach-s3c2410/Kconfig
21 +++ b/arch/arm/mach-s3c2410/Kconfig
22 @@ -9,6 +9,7 @@ config CPU_S3C2410
23         depends on ARCH_S3C2410
24         select S3C2410_CLOCK
25         select S3C2410_GPIO
26 +       select S3C2410_PWM
27         select CPU_LLSERIAL_S3C2410
28         select S3C2410_PM if PM
29         help
30 @@ -37,6 +38,11 @@ config S3C2410_CLOCK
31         help
32           Clock code for the S3C2410, and similar processors
33  
34 +config S3C2410_PWM
35 +       bool
36 +       help
37 +         PWM timer code for the S3C2410, and similar processors
38 +
39  
40  menu "S3C2410 Machines"
41  
42 diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
43 index 8952a8d..bb577f4 100644
44 --- a/arch/arm/mach-s3c2410/Makefile
45 +++ b/arch/arm/mach-s3c2410/Makefile
46 @@ -16,6 +16,7 @@ obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o
47  obj-$(CONFIG_S3C2410_PM)       += pm.o sleep.o
48  obj-$(CONFIG_S3C2410_GPIO)     += gpio.o
49  obj-$(CONFIG_S3C2410_CLOCK)    += clock.o
50 +obj-$(CONFIG_S3C2410_PWM)      += pwm.o
51  
52  # Machine support
53  
54 diff --git a/arch/arm/mach-s3c2410/pwm.c b/arch/arm/mach-s3c2410/pwm.c
55 new file mode 100644
56 index 0000000..8a07359
57 --- /dev/null
58 +++ b/arch/arm/mach-s3c2410/pwm.c
59 @@ -0,0 +1,214 @@
60 +/*
61 + * arch/arm/mach-s3c2410/3c2410-pwm.c
62 + *
63 + * Copyright (c) by Javi Roman <javiroman@kernel-labs.org>
64 + *              for the OpenMoko Project.
65 + *
66 + *     S3C2410A SoC PWM support
67 + *
68 + * This program is free software; you can redistribute it and/or modify
69 + * it under the terms of the GNU General Public License as published by
70 + * the Free Software Foundation; either version 2 of the License, or
71 + * (at your option) any later version.
72 + *
73 + * You should have received a copy of the GNU General Public License
74 + * along with this program; if not, write to the Free Software
75 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
76 + *
77 + */
78 +
79 +#include <linux/kernel.h>
80 +#include <linux/init.h>
81 +#include <linux/clk.h>
82 +#include <asm/hardware.h>
83 +#include <asm/plat-s3c/regs-timer.h>
84 +#include <asm/arch/pwm.h>
85 +
86 +int s3c2410_pwm_disable(struct s3c2410_pwm *pwm)
87 +{
88 +       unsigned long tcon;
89 +
90 +       /* stop timer */
91 +       tcon = __raw_readl(S3C2410_TCON);
92 +       tcon &= 0xffffff00;
93 +       __raw_writel(tcon, S3C2410_TCON);
94 +
95 +       clk_disable(pwm->pclk);
96 +       clk_put(pwm->pclk);
97 +
98 +       return 0;
99 +}
100 +EXPORT_SYMBOL_GPL(s3c2410_pwm_disable);
101 +
102 +int s3c2410_pwm_init(struct s3c2410_pwm *pwm)
103 +{
104 +       pwm->pclk = clk_get(NULL, "timers");
105 +       if (IS_ERR(pwm->pclk))
106 +               return PTR_ERR(pwm->pclk);
107 +
108 +       clk_enable(pwm->pclk);
109 +       pwm->pclk_rate = clk_get_rate(pwm->pclk);
110 +       return 0;
111 +}
112 +EXPORT_SYMBOL_GPL(s3c2410_pwm_init);
113 +
114 +int s3c2410_pwm_enable(struct s3c2410_pwm *pwm)
115 +{
116 +       unsigned long tcfg0, tcfg1, tcnt, tcmp;
117 +
118 +       /* control registers bits */
119 +       tcfg1 = __raw_readl(S3C2410_TCFG1);
120 +       tcfg0 = __raw_readl(S3C2410_TCFG0);
121 +
122 +       /* divider & scaler slection */
123 +       switch (pwm->timerid) {
124 +       case PWM0:
125 +               tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
126 +               tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
127 +               break;
128 +       case PWM1:
129 +               tcfg1 &= ~S3C2410_TCFG1_MUX1_MASK;
130 +               tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
131 +               break;
132 +       case PWM2:
133 +               tcfg1 &= ~S3C2410_TCFG1_MUX2_MASK;
134 +               tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
135 +               break;
136 +       case PWM3:
137 +               tcfg1 &= ~S3C2410_TCFG1_MUX3_MASK;
138 +               tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
139 +               break;
140 +       case PWM4:
141 +               /* timer four is not capable of doing PWM */
142 +               break;
143 +       default:
144 +               clk_disable(pwm->pclk);
145 +               clk_put(pwm->pclk);
146 +               return -1;
147 +       }
148 +
149 +       /* divider & scaler values */
150 +       tcfg1 |= pwm->divider;
151 +       __raw_writel(tcfg1, S3C2410_TCFG1);
152 +
153 +       switch (pwm->timerid) {
154 +       case PWM0:
155 +       case PWM1:
156 +               tcfg0 |= pwm->prescaler;
157 +               __raw_writel(tcfg0, S3C2410_TCFG0);
158 +               break;
159 +       default:
160 +               if ((tcfg0 | pwm->prescaler) != tcfg0) {
161 +                       printk(KERN_WARNING "not changing prescaler of PWM %u,"
162 +                              " since it's shared with timer4 (clock tick)\n",
163 +                              pwm->timerid);
164 +               }
165 +               break;
166 +       }
167 +
168 +       /* timer count and compare buffer initial values */
169 +       tcnt = pwm->counter;
170 +       tcmp = pwm->comparer;
171 +
172 +       __raw_writel(tcnt, S3C2410_TCNTB(pwm->timerid));
173 +       __raw_writel(tcmp, S3C2410_TCMPB(pwm->timerid));
174 +
175 +       /* ensure timer is stopped */
176 +       s3c2410_pwm_stop(pwm);
177 +
178 +       return 0;
179 +}
180 +EXPORT_SYMBOL_GPL(s3c2410_pwm_enable);
181 +
182 +int s3c2410_pwm_start(struct s3c2410_pwm *pwm)
183 +{
184 +       unsigned long tcon;
185 +
186 +       tcon = __raw_readl(S3C2410_TCON);
187 +
188 +       switch (pwm->timerid) {
189 +       case PWM0:
190 +               tcon |= S3C2410_TCON_T0START;
191 +               tcon &= ~S3C2410_TCON_T0MANUALUPD;
192 +               break;
193 +       case PWM1:
194 +               tcon |= S3C2410_TCON_T1START;
195 +               tcon &= ~S3C2410_TCON_T1MANUALUPD;
196 +               break;
197 +       case PWM2:
198 +               tcon |= S3C2410_TCON_T2START;
199 +               tcon &= ~S3C2410_TCON_T2MANUALUPD;
200 +               break;
201 +       case PWM3:
202 +               tcon |= S3C2410_TCON_T3START;
203 +               tcon &= ~S3C2410_TCON_T3MANUALUPD;
204 +               break;
205 +       case PWM4:
206 +               /* timer four is not capable of doing PWM */
207 +       default:
208 +               return -ENODEV;
209 +       }
210 +
211 +       __raw_writel(tcon, S3C2410_TCON);
212 +
213 +       return 0;
214 +}
215 +EXPORT_SYMBOL_GPL(s3c2410_pwm_start);
216 +
217 +int s3c2410_pwm_stop(struct s3c2410_pwm *pwm)
218 +{
219 +       unsigned long tcon;
220 +
221 +       tcon = __raw_readl(S3C2410_TCON);
222 +
223 +       switch (pwm->timerid) {
224 +       case PWM0:
225 +               tcon &= ~0x00000000;
226 +               tcon |= S3C2410_TCON_T0RELOAD;
227 +               tcon |= S3C2410_TCON_T0MANUALUPD;
228 +               break;
229 +       case PWM1:
230 +               tcon &= ~0x00000080;
231 +               tcon |= S3C2410_TCON_T1RELOAD;
232 +               tcon |= S3C2410_TCON_T1MANUALUPD;
233 +               break;
234 +       case PWM2:
235 +               tcon &= ~0x00000800;
236 +               tcon |= S3C2410_TCON_T2RELOAD;
237 +               tcon |= S3C2410_TCON_T2MANUALUPD;
238 +               break;
239 +       case PWM3:
240 +               tcon &= ~0x00008000;
241 +               tcon |= S3C2410_TCON_T3RELOAD;
242 +               tcon |= S3C2410_TCON_T3MANUALUPD;
243 +               break;
244 +       case PWM4:
245 +               /* timer four is not capable of doing PWM */
246 +       default:
247 +               return -ENODEV;
248 +       }
249 +
250 +       __raw_writel(tcon, S3C2410_TCON);
251 +
252 +       return 0;
253 +}
254 +EXPORT_SYMBOL_GPL(s3c2410_pwm_stop);
255 +
256 +int s3c2410_pwm_duty_cycle(int reg_value, struct s3c2410_pwm *pwm)
257 +{
258 +       __raw_writel(reg_value, S3C2410_TCMPB(pwm->timerid));
259 +
260 +       return 0;
261 +}
262 +EXPORT_SYMBOL_GPL(s3c2410_pwm_duty_cycle);
263 +
264 +int s3c2410_pwm_dumpregs(void)
265 +{
266 +       printk(KERN_INFO "TCON: %08lx, TCFG0: %08lx, TCFG1: %08lx\n",
267 +                       (unsigned long) __raw_readl(S3C2410_TCON),
268 +                       (unsigned long) __raw_readl(S3C2410_TCFG0),
269 +                       (unsigned long) __raw_readl(S3C2410_TCFG1));
270 +
271 +       return 0;
272 +}
273 +EXPORT_SYMBOL_GPL(s3c2410_pwm_dumpregs);
274 diff --git a/include/asm-arm/arch-s3c2410/pwm.h b/include/asm-arm/arch-s3c2410/pwm.h
275 new file mode 100644
276 index 0000000..a797ec3
277 --- /dev/null
278 +++ b/include/asm-arm/arch-s3c2410/pwm.h
279 @@ -0,0 +1,40 @@
280 +#ifndef __S3C2410_PWM_H
281 +#define __S3C2410_PWM_H
282 +
283 +#include <linux/err.h>
284 +#include <linux/platform_device.h>
285 +#include <linux/clk.h>
286 +
287 +#include <asm-arm/io.h>
288 +#include <asm/arch/hardware.h>
289 +#include <asm/mach-types.h>
290 +#include <asm/plat-s3c/regs-timer.h>
291 +#include <asm/arch/gta01.h>
292 +
293 +enum pwm_timer {
294 +       PWM0,
295 +       PWM1,
296 +       PWM2,
297 +       PWM3,
298 +       PWM4
299 +};
300 +
301 +struct s3c2410_pwm {
302 +       enum pwm_timer timerid;
303 +       struct clk *pclk;
304 +       unsigned long pclk_rate;
305 +       unsigned long prescaler;
306 +       unsigned long divider;
307 +       unsigned long counter;
308 +       unsigned long comparer;
309 +};
310 +
311 +int s3c2410_pwm_init(struct s3c2410_pwm *s3c2410_pwm);
312 +int s3c2410_pwm_enable(struct s3c2410_pwm *s3c2410_pwm);
313 +int s3c2410_pwm_disable(struct s3c2410_pwm *s3c2410_pwm);
314 +int s3c2410_pwm_start(struct s3c2410_pwm *s3c2410_pwm);
315 +int s3c2410_pwm_stop(struct s3c2410_pwm *s3c2410_pwm);
316 +int s3c2410_pwm_duty_cycle(int reg_value, struct s3c2410_pwm *s3c2410_pwm);
317 +int s3c2410_pwm_dumpregs(void);
318 +
319 +#endif /* __S3C2410_PWM_H */
320 -- 
321 1.5.6.5
322