PWM: ecap: Clean the access method for PWMSS config space.
[sitara-epos/sitara-epos-kernel.git] / drivers / pwm / ecap.c
1 /*
2  * eCAP driver for PWM output generation
3  *
4  * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation version 2.
9  *
10  * This program is distributed .as is. WITHOUT ANY WARRANTY of any
11  * kind, whether express or implied; without even the implied warranty
12  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15 #include <linux/module.h>
16 #include <linux/kernel.h>
17 #include <linux/platform_device.h>
18 #include <linux/err.h>
19 #include <linux/clk.h>
20 #include <linux/io.h>
21 #include <linux/pwm/pwm.h>
22 #include <linux/slab.h>
24 #include <plat/clock.h>
25 #include <plat/config_pwm.h>
27 #define TIMER_CTR_REG                   0x0
28 #define CAPTURE_2_REG                   0x0c
29 #define CAPTURE_3_REG                   0x10
30 #define CAPTURE_4_REG                   0x14
31 #define CAPTURE_CTRL2_REG               0x2A
33 #define ECTRL2_SYNCOSEL_MASK            (0x03 << 6)
35 #define ECTRL2_MDSL_ECAP                BIT(9)
36 #define ECTRL2_CTRSTP_FREERUN           BIT(4)
37 #define ECTRL2_PLSL_LOW                 BIT(10)
38 #define ECTRL2_SYNC_EN                  BIT(5)
40 struct ecap_pwm {
41         struct pwm_device pwm;
42         struct pwm_device_ops ops;
43         spinlock_t      lock;
44         struct clk      *clk;
45         void __iomem    *mmio_base;
46         u8 version;
47         void __iomem *config_mem_base;
48 };
50 static inline struct ecap_pwm *to_ecap_pwm(const struct pwm_device *p)
51 {
52         return pwm_get_drvdata(p);
53 }
55 static int ecap_pwm_stop(struct pwm_device *p)
56 {
57         unsigned long flags, v;
58         struct ecap_pwm *ep = to_ecap_pwm(p);
60         /* Trying to stop a non-running PWM, not allowed */
61         if (!pwm_is_running(p))
62                 return -EPERM;
64         spin_lock_irqsave(&ep->lock, flags);
65         v = readw(ep->mmio_base + CAPTURE_CTRL2_REG);
66         v &= ~BIT(4);
67         writew(v, ep->mmio_base + CAPTURE_CTRL2_REG);
68         spin_unlock_irqrestore(&ep->lock, flags);
70         /* For PWM clock should be disabled on stop */
71         clk_disable(ep->clk);
72         clear_bit(FLAG_RUNNING, &p->flags);
74         return 0;
75 }
77 static int ecap_pwm_start(struct pwm_device *p)
78 {
79         int ret = 0;
80         unsigned long flags, v;
81         struct ecap_pwm *ep = to_ecap_pwm(p);
83         /* Trying to start a running PWM, not allowed */
84         if (pwm_is_running(p))
85                 return -EPERM;
87         /* For PWM clock should be enabled on start */
88         clk_enable(ep->clk);
90         spin_lock_irqsave(&ep->lock, flags);
91         v = readw(ep->mmio_base + CAPTURE_CTRL2_REG);
92         v |= BIT(4);
93         writew(v, ep->mmio_base + CAPTURE_CTRL2_REG);
94         spin_unlock_irqrestore(&ep->lock, flags);
95         set_bit(FLAG_RUNNING, &p->flags);
97         return ret;
98 }
100 static int ecap_pwm_set_polarity(struct pwm_device *p, char pol)
102         unsigned long flags, v;
103         struct ecap_pwm *ep = to_ecap_pwm(p);
105         clk_enable(ep->clk);
107         spin_lock_irqsave(&ep->lock, flags);
108         v = readw(ep->mmio_base + CAPTURE_CTRL2_REG);
109         v &= ~BIT(10);
110         v |= (!pol << 10);
111         writew(v, ep->mmio_base + CAPTURE_CTRL2_REG);
112         spin_unlock_irqrestore(&ep->lock, flags);
114         clk_disable(ep->clk);
115         return 0;
118 static int ecap_pwm_config_period(struct pwm_device *p)
120         unsigned long flags;
121         struct ecap_pwm *ep = to_ecap_pwm(p);
123          clk_enable(ep->clk);
125         spin_lock_irqsave(&ep->lock, flags);
126         writel((p->period_ticks) - 1, ep->mmio_base + CAPTURE_3_REG);
127         writew(ECTRL2_MDSL_ECAP | ECTRL2_SYNCOSEL_MASK | ECTRL2_CTRSTP_FREERUN,
128                         ep->mmio_base + CAPTURE_CTRL2_REG);
129         spin_unlock_irqrestore(&ep->lock, flags);
131         clk_disable(ep->clk);
132         return 0;
135 static int ecap_pwm_config_duty(struct pwm_device *p)
137         unsigned long flags;
138         struct ecap_pwm *ep = to_ecap_pwm(p);
140         clk_enable(ep->clk);
142         spin_lock_irqsave(&ep->lock, flags);
143         writew(ECTRL2_MDSL_ECAP | ECTRL2_SYNCOSEL_MASK | ECTRL2_CTRSTP_FREERUN,
144                         ep->mmio_base + CAPTURE_CTRL2_REG);
145         if (p->duty_ticks > 0) {
146                 writel(p->duty_ticks, ep->mmio_base + CAPTURE_4_REG);
147         } else {
148                 writel(p->duty_ticks, ep->mmio_base + CAPTURE_2_REG);
149                 writel(0, ep->mmio_base + TIMER_CTR_REG);
150         }
151         spin_unlock_irqrestore(&ep->lock, flags);
153         clk_disable(ep->clk);
154         return 0;
157 static int ecap_pwm_config(struct pwm_device *p,
158                                 struct pwm_config *c)
160         int ret = 0;
161         switch (c->config_mask) {
163         case BIT(PWM_CONFIG_DUTY_TICKS):
164                 p->duty_ticks = c->duty_ticks;
165                 ret = ecap_pwm_config_duty(p);
166                 break;
168         case BIT(PWM_CONFIG_PERIOD_TICKS):
169                 p->period_ticks = c->period_ticks;
170                 ret = ecap_pwm_config_period(p);
171                 break;
173         case BIT(PWM_CONFIG_POLARITY):
174                 ret = ecap_pwm_set_polarity(p, c->polarity);
175                 break;
177         case BIT(PWM_CONFIG_START):
178                 ret = ecap_pwm_start(p);
179                 break;
181         case BIT(PWM_CONFIG_STOP):
182                 ret = ecap_pwm_stop(p);
183                 break;
184         }
186         return ret;
189 static int ecap_pwm_request(struct pwm_device *p)
191         struct ecap_pwm *ep = to_ecap_pwm(p);
193         p->tick_hz = clk_get_rate(ep->clk);
194         return 0;
197 static int ecap_frequency_transition_cb(struct pwm_device *p)
199         struct ecap_pwm *ep = to_ecap_pwm(p);
200         unsigned long duty_ns, rate;
202         rate = clk_get_rate(ep->clk);
203         if (rate == p->tick_hz)
204                 return 0;
205         p->tick_hz = rate;
207         duty_ns = p->duty_ns;
208         if (pwm_is_running(p)) {
209                 pwm_stop(p);
210                 pwm_set_duty_ns(p, 0);
211                 pwm_set_period_ns(p, p->period_ns);
212                 pwm_set_duty_ns(p, duty_ns);
213                 pwm_start(p);
214         } else {
215                 pwm_set_duty_ns(p, 0);
216                 pwm_set_period_ns(p, p->period_ns);
217                 pwm_set_duty_ns(p, duty_ns);
218         }
219                 return 0;
222 static int ecap_probe(struct platform_device *pdev)
224         struct ecap_pwm *ep = NULL;
225         struct resource *r;
226         int ret = 0;
227         int val;
228         char con_id[PWM_CON_ID_STRING_LENGTH] = "epwmss";
229         struct pwmss_platform_data *pdata = (&pdev->dev)->platform_data;
231         ep = kzalloc(sizeof(*ep), GFP_KERNEL);
233         if (!ep) {
234                 dev_err(&pdev->dev, "failed to allocate memory\n");
235                 return -ENOMEM;
236         }
238         ep->version = pdata->version;
240         if (ep->version == PWM_VERSION_1) {
241                 sprintf(con_id, "%s%d_%s", con_id, pdev->id, "fck");
242                 ep->clk = clk_get(&pdev->dev, con_id);
243         } else
244                 ep->clk = clk_get(&pdev->dev, "ecap");
246         if (IS_ERR(ep->clk)) {
247                 ret = PTR_ERR(ep->clk);
248                 goto err_clk_get;
249         }
251         if (ep->version == PWM_VERSION_1) {
252                 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
254                 if (!r) {
255                         dev_err(&pdev->dev, "no memory resource defined\n");
256                         ret = -ENOMEM;
257                         goto err_get_resource;
258                 }
260                 ep->config_mem_base = ioremap(r->start, resource_size(r));
262                 if (!ep->config_mem_base) {
264                         dev_err(&pdev->dev, "failed to ioremap() registers\n");
265                         ret = -ENOMEM;
266                         goto err_get_resource;
267                 }
269                 clk_enable(ep->clk);
270                 val = readw(ep->config_mem_base + PWMSS_CLKCONFIG);
271                 val |= BIT(ECAP_CLK_EN);
272                 writew(val, ep->config_mem_base + PWMSS_CLKCONFIG);
273                 clk_disable(ep->clk);
274         }
276         spin_lock_init(&ep->lock);
277         ep->ops.config = ecap_pwm_config;
278         ep->ops.request = ecap_pwm_request;
279         ep->ops.freq_transition_notifier_cb = ecap_frequency_transition_cb;
281         if (ep->version == PWM_VERSION_1)
282                 r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
283         else
284                 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
286         if (!r) {
287                 dev_err(&pdev->dev, "no memory resource defined\n");
288                 ret = -ENODEV;
289                 goto err_request_mem;
290         }
292         r = request_mem_region(r->start, resource_size(r), pdev->name);
293         if (!r) {
294                 dev_err(&pdev->dev, "failed to request memory resource\n");
295                 ret = -EBUSY;
296                 goto err_request_mem;
297         }
299         ep->mmio_base = ioremap(r->start, resource_size(r));
300         if (!ep->mmio_base) {
301                 dev_err(&pdev->dev, "failed to ioremap() registers\n");
302                 ret = -ENODEV;
303                 goto err_ioremap;
304         }
306         ep->pwm.ops = &ep->ops;
307         pwm_set_drvdata(&ep->pwm, ep);
308         ret =  pwm_register(&ep->pwm, &pdev->dev, -1);
309         platform_set_drvdata(pdev, ep);
310         return 0;
312 err_ioremap:
313         release_mem_region(r->start, resource_size(r));
314 err_request_mem:
315         if (ep->version == PWM_VERSION_1) {
316                 iounmap(ep->config_mem_base);
317                 ep->config_mem_base = NULL;
318         }
319 err_get_resource:
320         clk_put(ep->clk);
321 err_clk_get:
322         kfree(ep);
323         return ret;
326 #ifdef CONFIG_PM
327 static int ecap_suspend(struct platform_device *pdev, pm_message_t state)
329         struct ecap_pwm *ep = platform_get_drvdata(pdev);
331         if (ep->clk->usecount > 0)
332                 clk_disable(ep->clk);
334         return 0;
337 static int ecap_resume(struct platform_device *pdev)
339         struct ecap_pwm *ep = platform_get_drvdata(pdev);
341         clk_enable(ep->clk);
343         return 0;
346 #else
347 #define ecap_suspend NULL
348 #define ecap_resume NULL
349 #endif
351 static int __devexit ecap_remove(struct platform_device *pdev)
353         struct ecap_pwm *ep = platform_get_drvdata(pdev);
354         struct resource *r;
355         struct pwmss_platform_data *pdata;
356         int val;
358         if (ep->version == PWM_VERSION_1) {
359                 pdata = (&pdev->dev)->platform_data;
360                 val = readw(ep->config_mem_base + PWMSS_CLKCONFIG);
361                 val &= ~BIT(ECAP_CLK_EN);
362                 writew(val, ep->config_mem_base + PWMSS_CLKCONFIG);
363                 iounmap(ep->config_mem_base);
364                 ep->config_mem_base = NULL;
365         }
367         pwm_unregister(&ep->pwm);
368         iounmap(ep->mmio_base);
370         if (ep->version == PWM_VERSION_1)
371                 r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
372         else
373                 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
374         release_mem_region(r->start, resource_size(r));
375         platform_set_drvdata(pdev, NULL);
376         clk_put(ep->clk);
377         kfree(ep);
379         return 0;
382 static struct platform_driver ecap_driver = {
383         .driver = {
384                 .name   = "ecap",
385                 .owner  = THIS_MODULE,
386         },
387         .probe          = ecap_probe,
388         .remove         = __devexit_p(ecap_remove),
389         .suspend        = ecap_suspend,
390         .resume         = ecap_resume,
391 };
393 static int __init ecap_init(void)
395         return platform_driver_register(&ecap_driver);
398 static void __exit ecap_exit(void)
400         platform_driver_unregister(&ecap_driver);
403 module_init(ecap_init);
404 module_exit(ecap_exit);
406 MODULE_AUTHOR("Texas Instruments");
407 MODULE_DESCRIPTION("Driver for Davinci eCAP peripheral");
408 MODULE_LICENSE("GPL v2");
409 MODULE_ALIAS("platform:ecap");