aboutsummaryrefslogtreecommitdiffstats
path: root/arch/unicore32/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-10 07:15:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-10 07:15:24 -0400
commit2474542f64432398f503373f53bdf620491bcfa8 (patch)
tree3c9744b138c2158757530814b35c23eed31cf6ce /arch/unicore32/kernel
parentc7a6ced9d8e8411bdafe83998474d185a79badc3 (diff)
parent85f8879ca4f3d26a7f473522101fb74a79bda3f2 (diff)
Merge tag 'for-3.7-rc1' of git://gitorious.org/linux-pwm/linux-pwm
Pull pwm changes from Thierry Reding: "All legacy PWM providers have now been moved to the PWM subsystem. The plan for 3.8 is to adapt all board files to provide a lookup table for PWM devices in order to get rid of the global namespace. Subsequently, users of the legacy pwm_request() and pwm_free() functions can be migrated to the new pwm_get() and pwm_put() functions. Once this has been completed, the legacy API and the compatibility code in the core can be removed. In addition to the above, these changes also add support for configuring the polarity of a PWM signal (currently only supported on ECAP and EHRPWM) and include a much needed rework of the i.MX driver. Managed functions to obtain and release a PWM device (devm_pwm_get() and devm_pwm_put()) have been added and the pwm-backlight driver has been updated to use them. If the PWM subsystem hasn't been enabled, dummy functions are provided that allow the subsystem to safely compile out. Some common checks on input parameters have been moved to the core and removed from the drivers. Finally, a small fix corrects the description of the PWM specifier's second cell in the device tree representation." * tag 'for-3.7-rc1' of git://gitorious.org/linux-pwm/linux-pwm: (23 commits) pwm: dt: Fix description of second PWM cell pwm: Check for negative duty-cycle and period pwm: Add Ingenic JZ4740 support MIPS: JZ4740: Export timer API pwm: Move PUV3 PWM driver to PWM framework unicore32: pwm: Use managed resource allocations unicore32: pwm: Remove unnecessary indirection unicore32: pwm: Use module_platform_driver() unicore32: pwm: Properly remap memory-mapped registers pwm-backlight: Use devm_pwm_get() instead of pwm_get() pwm: Move AB8500 PWM driver to PWM framework pwm: Fix compilation error when CONFIG_PWM is not defined pwm: i.MX: fix clock lookup pwm: i.MX: use per clock unconditionally pwm: i.MX: add devicetree support pwm: i.MX: Use module_platform_driver pwm: i.MX: add functions to enable/disable pwm. pwm: i.MX: remove unnecessary if in pwm_[en|dis]able pwm: i.MX: factor out SoC specific functions pwm: pwm-tiehrpwm: Add support for configuring polarity of PWM ...
Diffstat (limited to 'arch/unicore32/kernel')
-rw-r--r--arch/unicore32/kernel/Makefile1
-rw-r--r--arch/unicore32/kernel/pwm.c263
2 files changed, 0 insertions, 264 deletions
diff --git a/arch/unicore32/kernel/Makefile b/arch/unicore32/kernel/Makefile
index 324010156958..fa497e0efe5a 100644
--- a/arch/unicore32/kernel/Makefile
+++ b/arch/unicore32/kernel/Makefile
@@ -16,7 +16,6 @@ obj-$(CONFIG_UNICORE_FPU_F64) += fpu-ucf64.o
16obj-$(CONFIG_ARCH_PUV3) += clock.o irq.o time.o 16obj-$(CONFIG_ARCH_PUV3) += clock.o irq.o time.o
17 17
18obj-$(CONFIG_PUV3_GPIO) += gpio.o 18obj-$(CONFIG_PUV3_GPIO) += gpio.o
19obj-$(CONFIG_PUV3_PWM) += pwm.o
20obj-$(CONFIG_PUV3_PM) += pm.o sleep.o 19obj-$(CONFIG_PUV3_PM) += pm.o sleep.o
21obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate_asm.o 20obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate_asm.o
22 21
diff --git a/arch/unicore32/kernel/pwm.c b/arch/unicore32/kernel/pwm.c
deleted file mode 100644
index 4615d51e3ba6..000000000000
--- a/arch/unicore32/kernel/pwm.c
+++ /dev/null
@@ -1,263 +0,0 @@
1/*
2 * linux/arch/unicore32/kernel/pwm.c
3 *
4 * Code specific to PKUnity SoC and UniCore ISA
5 *
6 * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
7 * Copyright (C) 2001-2010 Guan Xuetao
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 version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/platform_device.h>
17#include <linux/slab.h>
18#include <linux/err.h>
19#include <linux/clk.h>
20#include <linux/io.h>
21#include <linux/pwm.h>
22
23#include <asm/div64.h>
24#include <mach/hardware.h>
25
26struct pwm_device {
27 struct list_head node;
28 struct platform_device *pdev;
29
30 const char *label;
31 struct clk *clk;
32 int clk_enabled;
33
34 unsigned int use_count;
35 unsigned int pwm_id;
36};
37
38/*
39 * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE
40 * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
41 */
42int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
43{
44 unsigned long long c;
45 unsigned long period_cycles, prescale, pv, dc;
46
47 if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
48 return -EINVAL;
49
50 c = clk_get_rate(pwm->clk);
51 c = c * period_ns;
52 do_div(c, 1000000000);
53 period_cycles = c;
54
55 if (period_cycles < 1)
56 period_cycles = 1;
57 prescale = (period_cycles - 1) / 1024;
58 pv = period_cycles / (prescale + 1) - 1;
59
60 if (prescale > 63)
61 return -EINVAL;
62
63 if (duty_ns == period_ns)
64 dc = OST_PWMDCCR_FDCYCLE;
65 else
66 dc = (pv + 1) * duty_ns / period_ns;
67
68 /* NOTE: the clock to PWM has to be enabled first
69 * before writing to the registers
70 */
71 clk_enable(pwm->clk);
72 OST_PWMPWCR = prescale;
73 OST_PWMDCCR = pv - dc;
74 OST_PWMPCR = pv;
75 clk_disable(pwm->clk);
76
77 return 0;
78}
79EXPORT_SYMBOL(pwm_config);
80
81int pwm_enable(struct pwm_device *pwm)
82{
83 int rc = 0;
84
85 if (!pwm->clk_enabled) {
86 rc = clk_enable(pwm->clk);
87 if (!rc)
88 pwm->clk_enabled = 1;
89 }
90 return rc;
91}
92EXPORT_SYMBOL(pwm_enable);
93
94void pwm_disable(struct pwm_device *pwm)
95{
96 if (pwm->clk_enabled) {
97 clk_disable(pwm->clk);
98 pwm->clk_enabled = 0;
99 }
100}
101EXPORT_SYMBOL(pwm_disable);
102
103static DEFINE_MUTEX(pwm_lock);
104static LIST_HEAD(pwm_list);
105
106struct pwm_device *pwm_request(int pwm_id, const char *label)
107{
108 struct pwm_device *pwm;
109 int found = 0;
110
111 mutex_lock(&pwm_lock);
112
113 list_for_each_entry(pwm, &pwm_list, node) {
114 if (pwm->pwm_id == pwm_id) {
115 found = 1;
116 break;
117 }
118 }
119
120 if (found) {
121 if (pwm->use_count == 0) {
122 pwm->use_count++;
123 pwm->label = label;
124 } else
125 pwm = ERR_PTR(-EBUSY);
126 } else
127 pwm = ERR_PTR(-ENOENT);
128
129 mutex_unlock(&pwm_lock);
130 return pwm;
131}
132EXPORT_SYMBOL(pwm_request);
133
134void pwm_free(struct pwm_device *pwm)
135{
136 mutex_lock(&pwm_lock);
137
138 if (pwm->use_count) {
139 pwm->use_count--;
140 pwm->label = NULL;
141 } else
142 pr_warning("PWM device already freed\n");
143
144 mutex_unlock(&pwm_lock);
145}
146EXPORT_SYMBOL(pwm_free);
147
148static inline void __add_pwm(struct pwm_device *pwm)
149{
150 mutex_lock(&pwm_lock);
151 list_add_tail(&pwm->node, &pwm_list);
152 mutex_unlock(&pwm_lock);
153}
154
155static struct pwm_device *pwm_probe(struct platform_device *pdev,
156 unsigned int pwm_id, struct pwm_device *parent_pwm)
157{
158 struct pwm_device *pwm;
159 struct resource *r;
160 int ret = 0;
161
162 pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL);
163 if (pwm == NULL) {
164 dev_err(&pdev->dev, "failed to allocate memory\n");
165 return ERR_PTR(-ENOMEM);
166 }
167
168 pwm->clk = clk_get(NULL, "OST_CLK");
169 if (IS_ERR(pwm->clk)) {
170 ret = PTR_ERR(pwm->clk);
171 goto err_free;
172 }
173 pwm->clk_enabled = 0;
174
175 pwm->use_count = 0;
176 pwm->pwm_id = pwm_id;
177 pwm->pdev = pdev;
178
179 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
180 if (r == NULL) {
181 dev_err(&pdev->dev, "no memory resource defined\n");
182 ret = -ENODEV;
183 goto err_free_clk;
184 }
185
186 r = request_mem_region(r->start, resource_size(r), pdev->name);
187 if (r == NULL) {
188 dev_err(&pdev->dev, "failed to request memory resource\n");
189 ret = -EBUSY;
190 goto err_free_clk;
191 }
192
193 __add_pwm(pwm);
194 platform_set_drvdata(pdev, pwm);
195 return pwm;
196
197err_free_clk:
198 clk_put(pwm->clk);
199err_free:
200 kfree(pwm);
201 return ERR_PTR(ret);
202}
203
204static int __devinit puv3_pwm_probe(struct platform_device *pdev)
205{
206 struct pwm_device *pwm = pwm_probe(pdev, pdev->id, NULL);
207
208 if (IS_ERR(pwm))
209 return PTR_ERR(pwm);
210
211 return 0;
212}
213
214static int __devexit pwm_remove(struct platform_device *pdev)
215{
216 struct pwm_device *pwm;
217 struct resource *r;
218
219 pwm = platform_get_drvdata(pdev);
220 if (pwm == NULL)
221 return -ENODEV;
222
223 mutex_lock(&pwm_lock);
224 list_del(&pwm->node);
225 mutex_unlock(&pwm_lock);
226
227 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
228 release_mem_region(r->start, resource_size(r));
229
230 clk_put(pwm->clk);
231 kfree(pwm);
232 return 0;
233}
234
235static struct platform_driver puv3_pwm_driver = {
236 .driver = {
237 .name = "PKUnity-v3-PWM",
238 },
239 .probe = puv3_pwm_probe,
240 .remove = __devexit_p(pwm_remove),
241};
242
243static int __init pwm_init(void)
244{
245 int ret = 0;
246
247 ret = platform_driver_register(&puv3_pwm_driver);
248 if (ret) {
249 printk(KERN_ERR "failed to register puv3_pwm_driver\n");
250 return ret;
251 }
252
253 return ret;
254}
255arch_initcall(pwm_init);
256
257static void __exit pwm_exit(void)
258{
259 platform_driver_unregister(&puv3_pwm_driver);
260}
261module_exit(pwm_exit);
262
263MODULE_LICENSE("GPL v2");