[arm/tegra] Correct PWM clock programming.
[linux-2.6.git] / arch / arm / mach-tegra / pwm.c
1 /*
2  * arch/arm/mach-tegra/pwm.c
3  *
4  * Tegra pulse-width-modulation controller driver
5  *
6  * Copyright (c) 2010, NVIDIA Corporation.
7  * Based on arch/arm/plat-mxc/pwm.c by Sascha Hauer <s.hauer@pengutronix.de>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
17  * more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22  */
23
24 #include <linux/clk.h>
25 #include <linux/err.h>
26 #include <linux/io.h>
27 #include <linux/module.h>
28 #include <linux/kernel.h>
29 #include <linux/platform_device.h>
30 #include <linux/pwm.h>
31 #include <linux/slab.h>
32
33 #define PWM_ENABLE      (1 << 31)
34 #define PWM_DUTY_WIDTH  8
35 #define PWM_DUTY_SHIFT  16
36 #define PWM_SCALE_WIDTH 13
37 #define PWM_SCALE_SHIFT 0
38
39 struct pwm_device {
40         struct list_head        node;
41         struct platform_device  *pdev;
42
43         const char              *label;
44         struct clk              *clk;
45
46         int                     clk_enb;
47         void __iomem            *mmio_base;
48
49         unsigned int            in_use;
50         unsigned int            id;
51 };
52
53 static DEFINE_MUTEX(pwm_lock);
54 static LIST_HEAD(pwm_list);
55
56 static inline int pwm_writel(struct pwm_device *pwm, unsigned long val)
57 {
58         int rc;
59
60         rc = clk_enable(pwm->clk);
61         if (WARN_ON(rc))
62                 return rc;
63         writel(val, pwm->mmio_base);
64         clk_disable(pwm->clk);
65         return 0;
66 }
67
68 int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
69 {
70         unsigned long long c;
71         unsigned long rate, hz;
72         u32 val = 0;
73
74         /* convert from duty_ns / period_ns to a fixed number of duty
75          * ticks per (1 << PWM_DUTY_WIDTH) cycles. */
76         c = duty_ns * ((1 << PWM_DUTY_WIDTH) - 1);
77         do_div(c, period_ns);
78
79         val = (u32)c << PWM_DUTY_SHIFT;
80
81         /* compute the prescaler value for which (1 << PWM_DUTY_WIDTH)
82          * cycles at the PWM clock rate will take period_ns nanoseconds. */
83         rate = clk_get_rate(pwm->clk) >> PWM_DUTY_WIDTH;
84         hz = 1000000000ul / period_ns;
85
86         rate = (rate + (hz / 2)) / hz;
87
88         if (rate >> PWM_SCALE_WIDTH)
89                 return -EINVAL;
90         /* Due to the PWM divider is zero-based, we need to minus 1 to get desired frequency*/
91         if (rate>0)
92             rate--;
93
94         val |= (rate << PWM_SCALE_SHIFT);
95
96         /* the struct clk may be shared across multiple PWM devices, so
97          * only enable the PWM if this device has been enabled */
98         if (pwm->clk_enb)
99                 val |= PWM_ENABLE;
100
101         return pwm_writel(pwm, val);
102 }
103 EXPORT_SYMBOL(pwm_config);
104
105 int pwm_enable(struct pwm_device *pwm)
106 {
107         int rc = 0;
108
109         mutex_lock(&pwm_lock);
110         if (!pwm->clk_enb) {
111                 rc = clk_enable(pwm->clk);
112                 if (!rc) {
113                         u32 val = readl(pwm->mmio_base);
114                         writel(val | PWM_ENABLE, pwm->mmio_base);
115                         pwm->clk_enb = 1;
116                 }
117         }
118         mutex_unlock(&pwm_lock);
119
120         return rc;
121 }
122 EXPORT_SYMBOL(pwm_enable);
123
124 void pwm_disable(struct pwm_device *pwm)
125 {
126         mutex_lock(&pwm_lock);
127         if (pwm->clk_enb) {
128                 u32 val = readl(pwm->mmio_base);
129                 writel(val & ~PWM_ENABLE, pwm->mmio_base);
130                 clk_disable(pwm->clk);
131                 pwm->clk_enb = 0;
132         } else
133                 dev_warn(&pwm->pdev->dev, "%s called on disabled PWM\n",
134                          __func__);
135         mutex_unlock(&pwm_lock);
136 }
137 EXPORT_SYMBOL(pwm_disable);
138
139 struct pwm_device *pwm_request(int pwm_id, const char *label)
140 {
141         struct pwm_device *pwm;
142         int found = 0;
143
144         mutex_lock(&pwm_lock);
145
146         list_for_each_entry(pwm, &pwm_list, node) {
147                 if (pwm->id == pwm_id) {
148                         found = 1;
149                         break;
150                 }
151         }
152
153         if (found) {
154                 if (!pwm->in_use) {
155                         pwm->in_use = 1;
156                         pwm->label = label;
157                 } else
158                         pwm = ERR_PTR(-EBUSY);
159         } else
160                 pwm = ERR_PTR(-ENOENT);
161
162         mutex_unlock(&pwm_lock);
163
164         return pwm;
165 }
166 EXPORT_SYMBOL(pwm_request);
167
168 void pwm_free(struct pwm_device *pwm)
169 {
170         mutex_lock(&pwm_lock);
171         if (pwm->in_use) {
172                 pwm->in_use = 0;
173                 pwm->label = NULL;
174         } else
175                 dev_warn(&pwm->pdev->dev, "PWM device already freed\n");
176
177         mutex_unlock(&pwm_lock);
178 }
179 EXPORT_SYMBOL(pwm_free);
180
181 static int tegra_pwm_probe(struct platform_device *pdev)
182 {
183         struct pwm_device *pwm;
184         struct resource *r;
185         int ret;
186
187         pwm = kzalloc(sizeof(*pwm), GFP_KERNEL);
188         if (!pwm) {
189                 dev_err(&pdev->dev, "failed to allocate memory\n");
190                 return -ENOMEM;
191         }
192         pwm->clk = clk_get(&pdev->dev, NULL);
193
194         if (IS_ERR(pwm->clk)) {
195                 ret = PTR_ERR(pwm->clk);
196                 goto err_free;
197         }
198
199         pwm->clk_enb = 0;
200         pwm->in_use = 0;
201         pwm->id = pdev->id;
202         pwm->pdev = pdev;
203
204         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
205         if (!r) {
206                 dev_err(&pdev->dev, "no memory resources defined\n");
207                 ret = -ENODEV;
208                 goto err_put_clk;
209         }
210
211         r = request_mem_region(r->start, resource_size(r), pdev->name);
212         if (!r) {
213                 dev_err(&pdev->dev, "failed to request memory\n");
214                 ret = -EBUSY;
215                 goto err_put_clk;
216         }
217
218         pwm->mmio_base = ioremap(r->start, resource_size(r));
219         if (!pwm->mmio_base) {
220                 dev_err(&pdev->dev, "failed to ioremap() region\n");
221                 ret = -ENODEV;
222                 goto err_free_mem;
223         }
224
225         platform_set_drvdata(pdev, pwm);
226
227         mutex_lock(&pwm_lock);
228         list_add_tail(&pwm->node, &pwm_list);
229         mutex_unlock(&pwm_lock);
230
231         return 0;
232
233 err_free_mem:
234         release_mem_region(r->start, resource_size(r));
235 err_put_clk:
236         clk_put(pwm->clk);
237 err_free:
238         kfree(pwm);
239         return ret;
240 }
241
242 static int __devexit tegra_pwm_remove(struct platform_device *pdev)
243 {
244         struct pwm_device *pwm = platform_get_drvdata(pdev);
245         struct resource *r;
246         int rc;
247
248         if (WARN_ON(!pwm))
249                 return -ENODEV;
250
251         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
252
253         mutex_lock(&pwm_lock);
254         if (pwm->in_use) {
255                 mutex_unlock(&pwm_lock);
256                 return -EBUSY;
257         }
258         list_del(&pwm->node);
259         mutex_unlock(&pwm_lock);
260
261         rc = pwm_writel(pwm, 0);
262
263         iounmap(pwm->mmio_base);
264         release_mem_region(r->start, resource_size(r));
265
266         if (pwm->clk_enb)
267                 clk_disable(pwm->clk);
268
269         clk_put(pwm->clk);
270
271         kfree(pwm);
272         return rc;
273 }
274
275 static struct platform_driver tegra_pwm_driver = {
276         .driver         = {
277                 .name   = "tegra_pwm",
278         },
279         .probe          = tegra_pwm_probe,
280         .remove         = __devexit_p(tegra_pwm_remove),
281 };
282
283 static int __init tegra_pwm_init(void)
284 {
285         return platform_driver_register(&tegra_pwm_driver);
286 }
287 subsys_initcall(tegra_pwm_init);
288
289 static void __exit tegra_pwm_exit(void)
290 {
291         platform_driver_unregister(&tegra_pwm_driver);
292 }
293 module_exit(tegra_pwm_exit);
294
295 MODULE_LICENSE("GPL v2");
296 MODULE_AUTHOR("NVIDIA Corporation");