]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - sitara-epos/sitara-epos-kernel.git/blob - drivers/pwm/ecap.c
2964e02073899a569766c115c908539aa01f1b85
[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>
23 #include <linux/pm_runtime.h>
25 #include <plat/clock.h>
26 #include <plat/config_pwm.h>
28 #define TIMER_CTR_REG                   0x0
29 #define CAPTURE_2_REG                   0x0c
30 #define CAPTURE_3_REG                   0x10
31 #define CAPTURE_4_REG                   0x14
32 #define CAPTURE_CTRL2_REG               0x2A
34 #define ECTRL2_SYNCOSEL_MASK            (0x03 << 6)
36 #define ECTRL2_MDSL_ECAP                BIT(9)
37 #define ECTRL2_CTRSTP_FREERUN           BIT(4)
38 #define ECTRL2_PLSL_LOW                 BIT(10)
39 #define ECTRL2_SYNC_EN                  BIT(5)
41 struct ecap_pwm {
42         struct pwm_device pwm;
43         struct pwm_device_ops ops;
44         spinlock_t      lock;
45         struct clk      *clk;
46         void __iomem    *mmio_base;
47         u8 version;
48         void __iomem *config_mem_base;
49         struct device *dev;
50 };
52 static inline struct ecap_pwm *to_ecap_pwm(const struct pwm_device *p)
53 {
54         return pwm_get_drvdata(p);
55 }
57 static int ecap_pwm_stop(struct pwm_device *p)
58 {
59         unsigned long flags, v;
60         struct ecap_pwm *ep = to_ecap_pwm(p);
62         /* Trying to stop a non-running PWM, not allowed */
63         if (!pwm_is_running(p))
64                 return -EPERM;
66         spin_lock_irqsave(&ep->lock, flags);
67         v = readw(ep->mmio_base + CAPTURE_CTRL2_REG);
68         v &= ~ECTRL2_CTRSTP_FREERUN;
69         writew(v, ep->mmio_base + CAPTURE_CTRL2_REG);
70         spin_unlock_irqrestore(&ep->lock, flags);
72         /* For PWM clock should be disabled on stop */
73         pm_runtime_put_sync(ep->dev);
74         clear_bit(FLAG_RUNNING, &p->flags);
76         return 0;
77 }
79 static int ecap_pwm_start(struct pwm_device *p)
80 {
81         int ret = 0;
82         unsigned long flags, v;
83         struct ecap_pwm *ep = to_ecap_pwm(p);
85         /* Trying to start a running PWM, not allowed */
86         if (pwm_is_running(p))
87                 return -EPERM;
89         /* For PWM clock should be enabled on start */
90         pm_runtime_get_sync(ep->dev);
92         spin_lock_irqsave(&ep->lock, flags);
93         v = readw(ep->mmio_base + CAPTURE_CTRL2_REG);
94         v |= ECTRL2_CTRSTP_FREERUN;
95         writew(v, ep->mmio_base + CAPTURE_CTRL2_REG);
96         spin_unlock_irqrestore(&ep->lock, flags);
97         set_bit(FLAG_RUNNING, &p->flags);
99         return ret;
102 static int ecap_pwm_set_polarity(struct pwm_device *p, char pol)
104         unsigned long flags, v;
105         struct ecap_pwm *ep = to_ecap_pwm(p);
107         pm_runtime_get_sync(ep->dev);
109         spin_lock_irqsave(&ep->lock, flags);
110         v = readw(ep->mmio_base + CAPTURE_CTRL2_REG);
111         v &= ~ECTRL2_PLSL_LOW;
112         v |= (!pol << 10);
113         writew(v, ep->mmio_base + CAPTURE_CTRL2_REG);
114         spin_unlock_irqrestore(&ep->lock, flags);
116         pm_runtime_put_sync(ep->dev);
117         return 0;
120 static int ecap_pwm_config_period(struct pwm_device *p)
122         unsigned long flags, v;
123         struct ecap_pwm *ep = to_ecap_pwm(p);
125          pm_runtime_get_sync(ep->dev);
127         spin_lock_irqsave(&ep->lock, flags);
128         writel((p->period_ticks) - 1, ep->mmio_base + CAPTURE_3_REG);
129         v = readw(ep->mmio_base + CAPTURE_CTRL2_REG);
130         v |= (ECTRL2_MDSL_ECAP | ECTRL2_SYNCOSEL_MASK);
131         writew(v, ep->mmio_base + CAPTURE_CTRL2_REG);
132         spin_unlock_irqrestore(&ep->lock, flags);
134         pm_runtime_put_sync(ep->dev);
135         return 0;
138 static int ecap_pwm_config_duty(struct pwm_device *p)
140         unsigned long flags, v;
141         struct ecap_pwm *ep = to_ecap_pwm(p);
143         pm_runtime_get_sync(ep->dev);
145         spin_lock_irqsave(&ep->lock, flags);
146         v = readw(ep->mmio_base + CAPTURE_CTRL2_REG);
147         v |= (ECTRL2_MDSL_ECAP | ECTRL2_SYNCOSEL_MASK);
148         writew(v, ep->mmio_base + CAPTURE_CTRL2_REG);
150         if (p->duty_ticks > 0) {
151                 writel(p->duty_ticks, ep->mmio_base + CAPTURE_4_REG);
152         } else {
153                 writel(p->duty_ticks, ep->mmio_base + CAPTURE_2_REG);
154                 writel(0, ep->mmio_base + TIMER_CTR_REG);
155         }
156         spin_unlock_irqrestore(&ep->lock, flags);
158         pm_runtime_put_sync(ep->dev);
159         return 0;
162 static int ecap_pwm_config(struct pwm_device *p,
163                                 struct pwm_config *c)
165         int ret = 0;
166         switch (c->config_mask) {
168         case BIT(PWM_CONFIG_DUTY_TICKS):
169                 p->duty_ticks = c->duty_ticks;
170                 ret = ecap_pwm_config_duty(p);
171                 break;
173         case BIT(PWM_CONFIG_PERIOD_TICKS):
174                 p->period_ticks = c->period_ticks;
175                 ret = ecap_pwm_config_period(p);
176                 break;
178         case BIT(PWM_CONFIG_POLARITY):
179                 ret = ecap_pwm_set_polarity(p, c->polarity);
180                 break;
182         case BIT(PWM_CONFIG_START):
183                 ret = ecap_pwm_start(p);
184                 break;
186         case BIT(PWM_CONFIG_STOP):
187                 ret = ecap_pwm_stop(p);
188                 break;
189         }
191         return ret;
194 static int ecap_pwm_request(struct pwm_device *p)
196         struct ecap_pwm *ep = to_ecap_pwm(p);
198         p->tick_hz = clk_get_rate(ep->clk);
199         return 0;
202 static int ecap_frequency_transition_cb(struct pwm_device *p)
204         struct ecap_pwm *ep = to_ecap_pwm(p);
205         unsigned long duty_ns, rate;
207         rate = clk_get_rate(ep->clk);
208         if (rate == p->tick_hz)
209                 return 0;
210         p->tick_hz = rate;
212         duty_ns = p->duty_ns;
213         if (pwm_is_running(p)) {
214                 pwm_stop(p);
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                 pwm_start(p);
219         } else {
220                 pwm_set_duty_ns(p, 0);
221                 pwm_set_period_ns(p, p->period_ns);
222                 pwm_set_duty_ns(p, duty_ns);
223         }
224                 return 0;
227 static int ecap_probe(struct platform_device *pdev)
229         struct ecap_pwm *ep = NULL;
230         struct resource *r;
231         int ret = 0;
232         int val;
233         char con_id[PWM_CON_ID_STRING_LENGTH] = "epwmss";
234         struct pwmss_platform_data *pdata = (&pdev->dev)->platform_data;
236         ep = kzalloc(sizeof(*ep), GFP_KERNEL);
238         if (!ep) {
239                 dev_err(&pdev->dev, "failed to allocate memory\n");
240                 return -ENOMEM;
241         }
243         ep->version = pdata->version;
245         if (ep->version == PWM_VERSION_1) {
246                 sprintf(con_id, "%s%d_%s", con_id, pdev->id, "fck");
247                 ep->clk = clk_get(&pdev->dev, con_id);
248         } else
249                 ep->clk = clk_get(&pdev->dev, "ecap");
251         pm_runtime_enable(&pdev->dev);
252         ep->dev = &pdev->dev;
253         if (IS_ERR(ep->clk)) {
254                 ret = PTR_ERR(ep->clk);
255                 goto err_clk_get;
256         }
258         if (ep->version == PWM_VERSION_1) {
259                 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
261                 if (!r) {
262                         dev_err(&pdev->dev, "no memory resource defined\n");
263                         ret = -ENOMEM;
264                         goto err_get_resource;
265                 }
267                 ep->config_mem_base = ioremap(r->start, resource_size(r));
269                 if (!ep->config_mem_base) {
271                         dev_err(&pdev->dev, "failed to ioremap() registers\n");
272                         ret = -ENOMEM;
273                         goto err_get_resource;
274                 }
276                 pm_runtime_get_sync(ep->dev);
277                 val = readw(ep->config_mem_base + PWMSS_CLKCONFIG);
278                 val |= BIT(ECAP_CLK_EN);
279                 writew(val, ep->config_mem_base + PWMSS_CLKCONFIG);
280                 pm_runtime_put_sync(ep->dev);
281         }
283         spin_lock_init(&ep->lock);
284         ep->ops.config = ecap_pwm_config;
285         ep->ops.request = ecap_pwm_request;
286         ep->ops.freq_transition_notifier_cb = ecap_frequency_transition_cb;
288         if (ep->version == PWM_VERSION_1)
289                 r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
290         else
291                 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
293         if (!r) {
294                 dev_err(&pdev->dev, "no memory resource defined\n");
295                 ret = -ENODEV;
296                 goto err_request_mem;
297         }
299         r = request_mem_region(r->start, resource_size(r), pdev->name);
300         if (!r) {
301                 dev_err(&pdev->dev, "failed to request memory resource\n");
302                 ret = -EBUSY;
303                 goto err_request_mem;
304         }
306         ep->mmio_base = ioremap(r->start, resource_size(r));
307         if (!ep->mmio_base) {
308                 dev_err(&pdev->dev, "failed to ioremap() registers\n");
309                 ret = -ENODEV;
310                 goto err_ioremap;
311         }
313         ep->pwm.ops = &ep->ops;
314         pwm_set_drvdata(&ep->pwm, ep);
315         ret =  pwm_register(&ep->pwm, &pdev->dev, -1);
316         platform_set_drvdata(pdev, ep);
317         return 0;
319 err_ioremap:
320         release_mem_region(r->start, resource_size(r));
321 err_request_mem:
322         if (ep->version == PWM_VERSION_1) {
323                 iounmap(ep->config_mem_base);
324                 ep->config_mem_base = NULL;
325         }
326 err_get_resource:
327         clk_put(ep->clk);
328         pm_runtime_disable(&pdev->dev);
329 err_clk_get:
330         kfree(ep);
331         return ret;
334 #ifdef CONFIG_PM
335 static int ecap_suspend(struct platform_device *pdev, pm_message_t state)
337         struct ecap_pwm *ep = platform_get_drvdata(pdev);
339         if (ep->clk->usecount > 0)
340                 pm_runtime_put_sync(ep->dev);
342         return 0;
345 static int ecap_resume(struct platform_device *pdev)
347         struct ecap_pwm *ep = platform_get_drvdata(pdev);
349         pm_runtime_get_sync(ep->dev);
351         return 0;
354 #else
355 #define ecap_suspend NULL
356 #define ecap_resume NULL
357 #endif
359 static int __devexit ecap_remove(struct platform_device *pdev)
361         struct ecap_pwm *ep = platform_get_drvdata(pdev);
362         struct resource *r;
363         struct pwmss_platform_data *pdata;
364         int val;
366         if (ep->version == PWM_VERSION_1) {
367                 pdata = (&pdev->dev)->platform_data;
368                 val = readw(ep->config_mem_base + PWMSS_CLKCONFIG);
369                 val &= ~BIT(ECAP_CLK_EN);
370                 writew(val, ep->config_mem_base + PWMSS_CLKCONFIG);
371                 iounmap(ep->config_mem_base);
372                 ep->config_mem_base = NULL;
373         }
375         pwm_unregister(&ep->pwm);
376         iounmap(ep->mmio_base);
378         if (ep->version == PWM_VERSION_1)
379                 r = platform_get_resource(pdev, IORESOURCE_MEM, 1);
380         else
381                 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
382         release_mem_region(r->start, resource_size(r));
383         platform_set_drvdata(pdev, NULL);
384         clk_put(ep->clk);
385         pm_runtime_disable(&pdev->dev);
386         kfree(ep);
388         return 0;
391 static struct platform_driver ecap_driver = {
392         .driver = {
393                 .name   = "ecap",
394                 .owner  = THIS_MODULE,
395         },
396         .probe          = ecap_probe,
397         .remove         = __devexit_p(ecap_remove),
398         .suspend        = ecap_suspend,
399         .resume         = ecap_resume,
400 };
402 static int __init ecap_init(void)
404         return platform_driver_register(&ecap_driver);
407 static void __exit ecap_exit(void)
409         platform_driver_unregister(&ecap_driver);
412 module_init(ecap_init);
413 module_exit(ecap_exit);
415 MODULE_AUTHOR("Texas Instruments");
416 MODULE_DESCRIPTION("Driver for Davinci eCAP peripheral");
417 MODULE_LICENSE("GPL v2");
418 MODULE_ALIAS("platform:ecap");