diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2012-03-15 05:04:36 -0400 |
---|---|---|
committer | Thierry Reding <thierry.reding@avionic-design.de> | 2012-07-02 15:39:02 -0400 |
commit | 215c29d3d0e925189ade522d1ea6052a320d7692 (patch) | |
tree | 8540120b08bc764be976d9503acd93ebdd9d8fdb | |
parent | 29693248edf10830db2ef82b36806e378ff75c67 (diff) |
ARM Samsung: Move s3c pwm driver to pwm framework
Move the driver to drivers/pwm/ and convert it to use the framework.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Cc: Ben Dooks <ben-linux@fluff.org>
Cc: Kukjin Kim <kgene.kim@samsung.com>
[eric@eukrea.com: fix pwmchip_add return code test]
Signed-off-by: Eric BĂ©nard <eric@eukrea.com>
Signed-off-by: Thierry Reding <thierry.reding@avionic-design.de>
-rw-r--r-- | arch/arm/plat-samsung/Makefile | 4 | ||||
-rw-r--r-- | drivers/pwm/Kconfig | 9 | ||||
-rw-r--r-- | drivers/pwm/Makefile | 1 | ||||
-rw-r--r-- | drivers/pwm/pwm-samsung.c (renamed from arch/arm/plat-samsung/pwm.c) | 230 |
4 files changed, 98 insertions, 146 deletions
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile index 860b2db4db15..96854721319c 100644 --- a/arch/arm/plat-samsung/Makefile +++ b/arch/arm/plat-samsung/Makefile | |||
@@ -63,7 +63,3 @@ obj-$(CONFIG_S5P_SLEEP) += s5p-sleep.o | |||
63 | # PD support | 63 | # PD support |
64 | 64 | ||
65 | obj-$(CONFIG_SAMSUNG_PD) += pd.o | 65 | obj-$(CONFIG_SAMSUNG_PD) += pd.o |
66 | |||
67 | # PWM support | ||
68 | |||
69 | obj-$(CONFIG_HAVE_PWM) += pwm.o | ||
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index a9a971581108..0d9aa92636c3 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig | |||
@@ -36,6 +36,15 @@ config PWM_PXA | |||
36 | To compile this driver as a module, choose M here: the module | 36 | To compile this driver as a module, choose M here: the module |
37 | will be called pwm-pxa. | 37 | will be called pwm-pxa. |
38 | 38 | ||
39 | config PWM_SAMSUNG | ||
40 | tristate "Samsung pwm support" | ||
41 | depends on PLAT_SAMSUNG | ||
42 | help | ||
43 | Generic PWM framework driver for Samsung. | ||
44 | |||
45 | To compile this driver as a module, choose M here: the module | ||
46 | will be called pwm-samsung. | ||
47 | |||
39 | config PWM_TEGRA | 48 | config PWM_TEGRA |
40 | tristate "NVIDIA Tegra PWM support" | 49 | tristate "NVIDIA Tegra PWM support" |
41 | depends on ARCH_TEGRA | 50 | depends on ARCH_TEGRA |
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 3dd1b8357a0c..a1d87b173312 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile | |||
@@ -2,4 +2,5 @@ obj-$(CONFIG_PWM) += core.o | |||
2 | obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o | 2 | obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o |
3 | obj-$(CONFIG_PWM_IMX) += pwm-imx.o | 3 | obj-$(CONFIG_PWM_IMX) += pwm-imx.o |
4 | obj-$(CONFIG_PWM_PXA) += pwm-pxa.o | 4 | obj-$(CONFIG_PWM_PXA) += pwm-pxa.o |
5 | obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o | ||
5 | obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o | 6 | obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o |
diff --git a/arch/arm/plat-samsung/pwm.c b/drivers/pwm/pwm-samsung.c index c559d8438c70..c40c37e968e6 100644 --- a/arch/arm/plat-samsung/pwm.c +++ b/drivers/pwm/pwm-samsung.c | |||
@@ -24,8 +24,7 @@ | |||
24 | 24 | ||
25 | #include <plat/regs-timer.h> | 25 | #include <plat/regs-timer.h> |
26 | 26 | ||
27 | struct pwm_device { | 27 | struct s3c_chip { |
28 | struct list_head list; | ||
29 | struct platform_device *pdev; | 28 | struct platform_device *pdev; |
30 | 29 | ||
31 | struct clk *clk_div; | 30 | struct clk *clk_div; |
@@ -36,117 +35,65 @@ struct pwm_device { | |||
36 | unsigned int duty_ns; | 35 | unsigned int duty_ns; |
37 | 36 | ||
38 | unsigned char tcon_base; | 37 | unsigned char tcon_base; |
39 | unsigned char running; | ||
40 | unsigned char use_count; | ||
41 | unsigned char pwm_id; | 38 | unsigned char pwm_id; |
39 | struct pwm_chip chip; | ||
42 | }; | 40 | }; |
43 | 41 | ||
42 | #define to_s3c_chip(chip) container_of(chip, struct s3c_chip, chip) | ||
43 | |||
44 | #define pwm_dbg(_pwm, msg...) dev_dbg(&(_pwm)->pdev->dev, msg) | 44 | #define pwm_dbg(_pwm, msg...) dev_dbg(&(_pwm)->pdev->dev, msg) |
45 | 45 | ||
46 | static struct clk *clk_scaler[2]; | 46 | static struct clk *clk_scaler[2]; |
47 | 47 | ||
48 | static inline int pwm_is_tdiv(struct pwm_device *pwm) | 48 | static inline int pwm_is_tdiv(struct s3c_chip *chip) |
49 | { | ||
50 | return clk_get_parent(pwm->clk) == pwm->clk_div; | ||
51 | } | ||
52 | |||
53 | static DEFINE_MUTEX(pwm_lock); | ||
54 | static LIST_HEAD(pwm_list); | ||
55 | |||
56 | struct pwm_device *pwm_request(int pwm_id, const char *label) | ||
57 | { | ||
58 | struct pwm_device *pwm; | ||
59 | int found = 0; | ||
60 | |||
61 | mutex_lock(&pwm_lock); | ||
62 | |||
63 | list_for_each_entry(pwm, &pwm_list, list) { | ||
64 | if (pwm->pwm_id == pwm_id) { | ||
65 | found = 1; | ||
66 | break; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | if (found) { | ||
71 | if (pwm->use_count == 0) { | ||
72 | pwm->use_count = 1; | ||
73 | pwm->label = label; | ||
74 | } else | ||
75 | pwm = ERR_PTR(-EBUSY); | ||
76 | } else | ||
77 | pwm = ERR_PTR(-ENOENT); | ||
78 | |||
79 | mutex_unlock(&pwm_lock); | ||
80 | return pwm; | ||
81 | } | ||
82 | |||
83 | EXPORT_SYMBOL(pwm_request); | ||
84 | |||
85 | |||
86 | void pwm_free(struct pwm_device *pwm) | ||
87 | { | 49 | { |
88 | mutex_lock(&pwm_lock); | 50 | return clk_get_parent(chip->clk) == chip->clk_div; |
89 | |||
90 | if (pwm->use_count) { | ||
91 | pwm->use_count--; | ||
92 | pwm->label = NULL; | ||
93 | } else | ||
94 | printk(KERN_ERR "PWM%d device already freed\n", pwm->pwm_id); | ||
95 | |||
96 | mutex_unlock(&pwm_lock); | ||
97 | } | 51 | } |
98 | 52 | ||
99 | EXPORT_SYMBOL(pwm_free); | ||
100 | |||
101 | #define pwm_tcon_start(pwm) (1 << (pwm->tcon_base + 0)) | 53 | #define pwm_tcon_start(pwm) (1 << (pwm->tcon_base + 0)) |
102 | #define pwm_tcon_invert(pwm) (1 << (pwm->tcon_base + 2)) | 54 | #define pwm_tcon_invert(pwm) (1 << (pwm->tcon_base + 2)) |
103 | #define pwm_tcon_autoreload(pwm) (1 << (pwm->tcon_base + 3)) | 55 | #define pwm_tcon_autoreload(pwm) (1 << (pwm->tcon_base + 3)) |
104 | #define pwm_tcon_manulupdate(pwm) (1 << (pwm->tcon_base + 1)) | 56 | #define pwm_tcon_manulupdate(pwm) (1 << (pwm->tcon_base + 1)) |
105 | 57 | ||
106 | int pwm_enable(struct pwm_device *pwm) | 58 | static int s3c_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) |
107 | { | 59 | { |
60 | struct s3c_chip *s3c = to_s3c_chip(chip); | ||
108 | unsigned long flags; | 61 | unsigned long flags; |
109 | unsigned long tcon; | 62 | unsigned long tcon; |
110 | 63 | ||
111 | local_irq_save(flags); | 64 | local_irq_save(flags); |
112 | 65 | ||
113 | tcon = __raw_readl(S3C2410_TCON); | 66 | tcon = __raw_readl(S3C2410_TCON); |
114 | tcon |= pwm_tcon_start(pwm); | 67 | tcon |= pwm_tcon_start(s3c); |
115 | __raw_writel(tcon, S3C2410_TCON); | 68 | __raw_writel(tcon, S3C2410_TCON); |
116 | 69 | ||
117 | local_irq_restore(flags); | 70 | local_irq_restore(flags); |
118 | 71 | ||
119 | pwm->running = 1; | ||
120 | return 0; | 72 | return 0; |
121 | } | 73 | } |
122 | 74 | ||
123 | EXPORT_SYMBOL(pwm_enable); | 75 | static void s3c_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) |
124 | |||
125 | void pwm_disable(struct pwm_device *pwm) | ||
126 | { | 76 | { |
77 | struct s3c_chip *s3c = to_s3c_chip(chip); | ||
127 | unsigned long flags; | 78 | unsigned long flags; |
128 | unsigned long tcon; | 79 | unsigned long tcon; |
129 | 80 | ||
130 | local_irq_save(flags); | 81 | local_irq_save(flags); |
131 | 82 | ||
132 | tcon = __raw_readl(S3C2410_TCON); | 83 | tcon = __raw_readl(S3C2410_TCON); |
133 | tcon &= ~pwm_tcon_start(pwm); | 84 | tcon &= ~pwm_tcon_start(s3c); |
134 | __raw_writel(tcon, S3C2410_TCON); | 85 | __raw_writel(tcon, S3C2410_TCON); |
135 | 86 | ||
136 | local_irq_restore(flags); | 87 | local_irq_restore(flags); |
137 | |||
138 | pwm->running = 0; | ||
139 | } | 88 | } |
140 | 89 | ||
141 | EXPORT_SYMBOL(pwm_disable); | 90 | static unsigned long pwm_calc_tin(struct s3c_chip *s3c, unsigned long freq) |
142 | |||
143 | static unsigned long pwm_calc_tin(struct pwm_device *pwm, unsigned long freq) | ||
144 | { | 91 | { |
145 | unsigned long tin_parent_rate; | 92 | unsigned long tin_parent_rate; |
146 | unsigned int div; | 93 | unsigned int div; |
147 | 94 | ||
148 | tin_parent_rate = clk_get_rate(clk_get_parent(pwm->clk_div)); | 95 | tin_parent_rate = clk_get_rate(clk_get_parent(s3c->clk_div)); |
149 | pwm_dbg(pwm, "tin parent at %lu\n", tin_parent_rate); | 96 | pwm_dbg(s3c, "tin parent at %lu\n", tin_parent_rate); |
150 | 97 | ||
151 | for (div = 2; div <= 16; div *= 2) { | 98 | for (div = 2; div <= 16; div *= 2) { |
152 | if ((tin_parent_rate / (div << 16)) < freq) | 99 | if ((tin_parent_rate / (div << 16)) < freq) |
@@ -158,8 +105,10 @@ static unsigned long pwm_calc_tin(struct pwm_device *pwm, unsigned long freq) | |||
158 | 105 | ||
159 | #define NS_IN_HZ (1000000000UL) | 106 | #define NS_IN_HZ (1000000000UL) |
160 | 107 | ||
161 | int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) | 108 | static int s3c_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, |
109 | int duty_ns, int period_ns) | ||
162 | { | 110 | { |
111 | struct s3c_chip *s3c = to_s3c_chip(chip); | ||
163 | unsigned long tin_rate; | 112 | unsigned long tin_rate; |
164 | unsigned long tin_ns; | 113 | unsigned long tin_ns; |
165 | unsigned long period; | 114 | unsigned long period; |
@@ -178,38 +127,38 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) | |||
178 | if (duty_ns > period_ns) | 127 | if (duty_ns > period_ns) |
179 | return -EINVAL; | 128 | return -EINVAL; |
180 | 129 | ||
181 | if (period_ns == pwm->period_ns && | 130 | if (period_ns == s3c->period_ns && |
182 | duty_ns == pwm->duty_ns) | 131 | duty_ns == s3c->duty_ns) |
183 | return 0; | 132 | return 0; |
184 | 133 | ||
185 | /* The TCMP and TCNT can be read without a lock, they're not | 134 | /* The TCMP and TCNT can be read without a lock, they're not |
186 | * shared between the timers. */ | 135 | * shared between the timers. */ |
187 | 136 | ||
188 | tcmp = __raw_readl(S3C2410_TCMPB(pwm->pwm_id)); | 137 | tcmp = __raw_readl(S3C2410_TCMPB(s3c->pwm_id)); |
189 | tcnt = __raw_readl(S3C2410_TCNTB(pwm->pwm_id)); | 138 | tcnt = __raw_readl(S3C2410_TCNTB(s3c->pwm_id)); |
190 | 139 | ||
191 | period = NS_IN_HZ / period_ns; | 140 | period = NS_IN_HZ / period_ns; |
192 | 141 | ||
193 | pwm_dbg(pwm, "duty_ns=%d, period_ns=%d (%lu)\n", | 142 | pwm_dbg(s3c, "duty_ns=%d, period_ns=%d (%lu)\n", |
194 | duty_ns, period_ns, period); | 143 | duty_ns, period_ns, period); |
195 | 144 | ||
196 | /* Check to see if we are changing the clock rate of the PWM */ | 145 | /* Check to see if we are changing the clock rate of the PWM */ |
197 | 146 | ||
198 | if (pwm->period_ns != period_ns) { | 147 | if (s3c->period_ns != period_ns) { |
199 | if (pwm_is_tdiv(pwm)) { | 148 | if (pwm_is_tdiv(s3c)) { |
200 | tin_rate = pwm_calc_tin(pwm, period); | 149 | tin_rate = pwm_calc_tin(s3c, period); |
201 | clk_set_rate(pwm->clk_div, tin_rate); | 150 | clk_set_rate(s3c->clk_div, tin_rate); |
202 | } else | 151 | } else |
203 | tin_rate = clk_get_rate(pwm->clk); | 152 | tin_rate = clk_get_rate(s3c->clk); |
204 | 153 | ||
205 | pwm->period_ns = period_ns; | 154 | s3c->period_ns = period_ns; |
206 | 155 | ||
207 | pwm_dbg(pwm, "tin_rate=%lu\n", tin_rate); | 156 | pwm_dbg(s3c, "tin_rate=%lu\n", tin_rate); |
208 | 157 | ||
209 | tin_ns = NS_IN_HZ / tin_rate; | 158 | tin_ns = NS_IN_HZ / tin_rate; |
210 | tcnt = period_ns / tin_ns; | 159 | tcnt = period_ns / tin_ns; |
211 | } else | 160 | } else |
212 | tin_ns = NS_IN_HZ / clk_get_rate(pwm->clk); | 161 | tin_ns = NS_IN_HZ / clk_get_rate(s3c->clk); |
213 | 162 | ||
214 | /* Note, counters count down */ | 163 | /* Note, counters count down */ |
215 | 164 | ||
@@ -220,7 +169,7 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) | |||
220 | if (tcmp == tcnt) | 169 | if (tcmp == tcnt) |
221 | tcmp--; | 170 | tcmp--; |
222 | 171 | ||
223 | pwm_dbg(pwm, "tin_ns=%lu, tcmp=%ld/%lu\n", tin_ns, tcmp, tcnt); | 172 | pwm_dbg(s3c, "tin_ns=%lu, tcmp=%ld/%lu\n", tin_ns, tcmp, tcnt); |
224 | 173 | ||
225 | if (tcmp < 0) | 174 | if (tcmp < 0) |
226 | tcmp = 0; | 175 | tcmp = 0; |
@@ -229,15 +178,15 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) | |||
229 | 178 | ||
230 | local_irq_save(flags); | 179 | local_irq_save(flags); |
231 | 180 | ||
232 | __raw_writel(tcmp, S3C2410_TCMPB(pwm->pwm_id)); | 181 | __raw_writel(tcmp, S3C2410_TCMPB(s3c->pwm_id)); |
233 | __raw_writel(tcnt, S3C2410_TCNTB(pwm->pwm_id)); | 182 | __raw_writel(tcnt, S3C2410_TCNTB(s3c->pwm_id)); |
234 | 183 | ||
235 | tcon = __raw_readl(S3C2410_TCON); | 184 | tcon = __raw_readl(S3C2410_TCON); |
236 | tcon |= pwm_tcon_manulupdate(pwm); | 185 | tcon |= pwm_tcon_manulupdate(s3c); |
237 | tcon |= pwm_tcon_autoreload(pwm); | 186 | tcon |= pwm_tcon_autoreload(s3c); |
238 | __raw_writel(tcon, S3C2410_TCON); | 187 | __raw_writel(tcon, S3C2410_TCON); |
239 | 188 | ||
240 | tcon &= ~pwm_tcon_manulupdate(pwm); | 189 | tcon &= ~pwm_tcon_manulupdate(s3c); |
241 | __raw_writel(tcon, S3C2410_TCON); | 190 | __raw_writel(tcon, S3C2410_TCON); |
242 | 191 | ||
243 | local_irq_restore(flags); | 192 | local_irq_restore(flags); |
@@ -245,24 +194,17 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) | |||
245 | return 0; | 194 | return 0; |
246 | } | 195 | } |
247 | 196 | ||
248 | EXPORT_SYMBOL(pwm_config); | 197 | static struct pwm_ops s3c_pwm_ops = { |
249 | 198 | .enable = s3c_pwm_enable, | |
250 | static int pwm_register(struct pwm_device *pwm) | 199 | .disable = s3c_pwm_disable, |
251 | { | 200 | .config = s3c_pwm_config, |
252 | pwm->duty_ns = -1; | 201 | .owner = THIS_MODULE, |
253 | pwm->period_ns = -1; | 202 | }; |
254 | |||
255 | mutex_lock(&pwm_lock); | ||
256 | list_add_tail(&pwm->list, &pwm_list); | ||
257 | mutex_unlock(&pwm_lock); | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | 203 | ||
262 | static int s3c_pwm_probe(struct platform_device *pdev) | 204 | static int s3c_pwm_probe(struct platform_device *pdev) |
263 | { | 205 | { |
264 | struct device *dev = &pdev->dev; | 206 | struct device *dev = &pdev->dev; |
265 | struct pwm_device *pwm; | 207 | struct s3c_chip *s3c; |
266 | unsigned long flags; | 208 | unsigned long flags; |
267 | unsigned long tcon; | 209 | unsigned long tcon; |
268 | unsigned int id = pdev->id; | 210 | unsigned int id = pdev->id; |
@@ -273,83 +215,87 @@ static int s3c_pwm_probe(struct platform_device *pdev) | |||
273 | return -ENXIO; | 215 | return -ENXIO; |
274 | } | 216 | } |
275 | 217 | ||
276 | pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); | 218 | s3c = kzalloc(sizeof(*s3c), GFP_KERNEL); |
277 | if (pwm == NULL) { | 219 | if (s3c == NULL) { |
278 | dev_err(dev, "failed to allocate pwm_device\n"); | 220 | dev_err(dev, "failed to allocate pwm_device\n"); |
279 | return -ENOMEM; | 221 | return -ENOMEM; |
280 | } | 222 | } |
281 | 223 | ||
282 | pwm->pdev = pdev; | ||
283 | pwm->pwm_id = id; | ||
284 | |||
285 | /* calculate base of control bits in TCON */ | 224 | /* calculate base of control bits in TCON */ |
286 | pwm->tcon_base = id == 0 ? 0 : (id * 4) + 4; | 225 | s3c->tcon_base = id == 0 ? 0 : (id * 4) + 4; |
226 | s3c->chip.ops = &s3c_pwm_ops; | ||
227 | s3c->chip.base = -1; | ||
228 | s3c->chip.npwm = 1; | ||
287 | 229 | ||
288 | pwm->clk = clk_get(dev, "pwm-tin"); | 230 | s3c->clk = clk_get(dev, "pwm-tin"); |
289 | if (IS_ERR(pwm->clk)) { | 231 | if (IS_ERR(s3c->clk)) { |
290 | dev_err(dev, "failed to get pwm tin clk\n"); | 232 | dev_err(dev, "failed to get pwm tin clk\n"); |
291 | ret = PTR_ERR(pwm->clk); | 233 | ret = PTR_ERR(s3c->clk); |
292 | goto err_alloc; | 234 | goto err_alloc; |
293 | } | 235 | } |
294 | 236 | ||
295 | pwm->clk_div = clk_get(dev, "pwm-tdiv"); | 237 | s3c->clk_div = clk_get(dev, "pwm-tdiv"); |
296 | if (IS_ERR(pwm->clk_div)) { | 238 | if (IS_ERR(s3c->clk_div)) { |
297 | dev_err(dev, "failed to get pwm tdiv clk\n"); | 239 | dev_err(dev, "failed to get pwm tdiv clk\n"); |
298 | ret = PTR_ERR(pwm->clk_div); | 240 | ret = PTR_ERR(s3c->clk_div); |
299 | goto err_clk_tin; | 241 | goto err_clk_tin; |
300 | } | 242 | } |
301 | 243 | ||
302 | clk_enable(pwm->clk); | 244 | clk_enable(s3c->clk); |
303 | clk_enable(pwm->clk_div); | 245 | clk_enable(s3c->clk_div); |
304 | 246 | ||
305 | local_irq_save(flags); | 247 | local_irq_save(flags); |
306 | 248 | ||
307 | tcon = __raw_readl(S3C2410_TCON); | 249 | tcon = __raw_readl(S3C2410_TCON); |
308 | tcon |= pwm_tcon_invert(pwm); | 250 | tcon |= pwm_tcon_invert(s3c); |
309 | __raw_writel(tcon, S3C2410_TCON); | 251 | __raw_writel(tcon, S3C2410_TCON); |
310 | 252 | ||
311 | local_irq_restore(flags); | 253 | local_irq_restore(flags); |
312 | 254 | ||
313 | 255 | ret = pwmchip_add(&s3c->chip); | |
314 | ret = pwm_register(pwm); | 256 | if (ret < 0) { |
315 | if (ret) { | ||
316 | dev_err(dev, "failed to register pwm\n"); | 257 | dev_err(dev, "failed to register pwm\n"); |
317 | goto err_clk_tdiv; | 258 | goto err_clk_tdiv; |
318 | } | 259 | } |
319 | 260 | ||
320 | pwm_dbg(pwm, "config bits %02x\n", | 261 | pwm_dbg(s3c, "config bits %02x\n", |
321 | (__raw_readl(S3C2410_TCON) >> pwm->tcon_base) & 0x0f); | 262 | (__raw_readl(S3C2410_TCON) >> s3c->tcon_base) & 0x0f); |
322 | 263 | ||
323 | dev_info(dev, "tin at %lu, tdiv at %lu, tin=%sclk, base %d\n", | 264 | dev_info(dev, "tin at %lu, tdiv at %lu, tin=%sclk, base %d\n", |
324 | clk_get_rate(pwm->clk), | 265 | clk_get_rate(s3c->clk), |
325 | clk_get_rate(pwm->clk_div), | 266 | clk_get_rate(s3c->clk_div), |
326 | pwm_is_tdiv(pwm) ? "div" : "ext", pwm->tcon_base); | 267 | pwm_is_tdiv(s3c) ? "div" : "ext", s3c->tcon_base); |
327 | 268 | ||
328 | platform_set_drvdata(pdev, pwm); | 269 | platform_set_drvdata(pdev, s3c); |
329 | return 0; | 270 | return 0; |
330 | 271 | ||
331 | err_clk_tdiv: | 272 | err_clk_tdiv: |
332 | clk_disable(pwm->clk_div); | 273 | clk_disable(s3c->clk_div); |
333 | clk_disable(pwm->clk); | 274 | clk_disable(s3c->clk); |
334 | clk_put(pwm->clk_div); | 275 | clk_put(s3c->clk_div); |
335 | 276 | ||
336 | err_clk_tin: | 277 | err_clk_tin: |
337 | clk_put(pwm->clk); | 278 | clk_put(s3c->clk); |
338 | 279 | ||
339 | err_alloc: | 280 | err_alloc: |
340 | kfree(pwm); | 281 | kfree(s3c); |
341 | return ret; | 282 | return ret; |
342 | } | 283 | } |
343 | 284 | ||
344 | static int __devexit s3c_pwm_remove(struct platform_device *pdev) | 285 | static int __devexit s3c_pwm_remove(struct platform_device *pdev) |
345 | { | 286 | { |
346 | struct pwm_device *pwm = platform_get_drvdata(pdev); | 287 | struct s3c_chip *s3c = platform_get_drvdata(pdev); |
288 | int err; | ||
289 | |||
290 | err = pwmchip_remove(&s3c->chip); | ||
291 | if (err < 0) | ||
292 | return err; | ||
347 | 293 | ||
348 | clk_disable(pwm->clk_div); | 294 | clk_disable(s3c->clk_div); |
349 | clk_disable(pwm->clk); | 295 | clk_disable(s3c->clk); |
350 | clk_put(pwm->clk_div); | 296 | clk_put(s3c->clk_div); |
351 | clk_put(pwm->clk); | 297 | clk_put(s3c->clk); |
352 | kfree(pwm); | 298 | kfree(s3c); |
353 | 299 | ||
354 | return 0; | 300 | return 0; |
355 | } | 301 | } |
@@ -357,26 +303,26 @@ static int __devexit s3c_pwm_remove(struct platform_device *pdev) | |||
357 | #ifdef CONFIG_PM | 303 | #ifdef CONFIG_PM |
358 | static int s3c_pwm_suspend(struct platform_device *pdev, pm_message_t state) | 304 | static int s3c_pwm_suspend(struct platform_device *pdev, pm_message_t state) |
359 | { | 305 | { |
360 | struct pwm_device *pwm = platform_get_drvdata(pdev); | 306 | struct s3c_chip *s3c = platform_get_drvdata(pdev); |
361 | 307 | ||
362 | /* No one preserve these values during suspend so reset them | 308 | /* No one preserve these values during suspend so reset them |
363 | * Otherwise driver leaves PWM unconfigured if same values | 309 | * Otherwise driver leaves PWM unconfigured if same values |
364 | * passed to pwm_config | 310 | * passed to pwm_config |
365 | */ | 311 | */ |
366 | pwm->period_ns = 0; | 312 | s3c->period_ns = 0; |
367 | pwm->duty_ns = 0; | 313 | s3c->duty_ns = 0; |
368 | 314 | ||
369 | return 0; | 315 | return 0; |
370 | } | 316 | } |
371 | 317 | ||
372 | static int s3c_pwm_resume(struct platform_device *pdev) | 318 | static int s3c_pwm_resume(struct platform_device *pdev) |
373 | { | 319 | { |
374 | struct pwm_device *pwm = platform_get_drvdata(pdev); | 320 | struct s3c_chip *s3c = platform_get_drvdata(pdev); |
375 | unsigned long tcon; | 321 | unsigned long tcon; |
376 | 322 | ||
377 | /* Restore invertion */ | 323 | /* Restore invertion */ |
378 | tcon = __raw_readl(S3C2410_TCON); | 324 | tcon = __raw_readl(S3C2410_TCON); |
379 | tcon |= pwm_tcon_invert(pwm); | 325 | tcon |= pwm_tcon_invert(s3c); |
380 | __raw_writel(tcon, S3C2410_TCON); | 326 | __raw_writel(tcon, S3C2410_TCON); |
381 | 327 | ||
382 | return 0; | 328 | return 0; |