• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/misc/
1#include <linux/module.h>
2#include <linux/clk.h>
3#include <linux/err.h>
4#include <linux/slab.h>
5#include <linux/io.h>
6#include <linux/interrupt.h>
7#include <linux/platform_device.h>
8#include <linux/atmel_pwm.h>
9
10
11/*
12 * This is a simple driver for the PWM controller found in various newer
13 * Atmel SOCs, including the AVR32 series and the AT91sam9263.
14 *
15 * Chips with current Linux ports have only 4 PWM channels, out of max 32.
16 * AT32UC3A and AT32UC3B chips have 7 channels (but currently no Linux).
17 * Docs are inconsistent about the width of the channel counter registers;
18 * it's at least 16 bits, but several places say 20 bits.
19 */
20#define	PWM_NCHAN	4		/* max 32 */
21
22struct pwm {
23	spinlock_t		lock;
24	struct platform_device	*pdev;
25	u32			mask;
26	int			irq;
27	void __iomem		*base;
28	struct clk		*clk;
29	struct pwm_channel	*channel[PWM_NCHAN];
30	void			(*handler[PWM_NCHAN])(struct pwm_channel *);
31};
32
33
34/* global PWM controller registers */
35#define PWM_MR		0x00
36#define PWM_ENA		0x04
37#define PWM_DIS		0x08
38#define PWM_SR		0x0c
39#define PWM_IER		0x10
40#define PWM_IDR		0x14
41#define PWM_IMR		0x18
42#define PWM_ISR		0x1c
43
44static inline void pwm_writel(const struct pwm *p, unsigned offset, u32 val)
45{
46	__raw_writel(val, p->base + offset);
47}
48
49static inline u32 pwm_readl(const struct pwm *p, unsigned offset)
50{
51	return __raw_readl(p->base + offset);
52}
53
54static inline void __iomem *pwmc_regs(const struct pwm *p, int index)
55{
56	return p->base + 0x200 + index * 0x20;
57}
58
59static struct pwm *pwm;
60
61static void pwm_dumpregs(struct pwm_channel *ch, char *tag)
62{
63	struct device	*dev = &pwm->pdev->dev;
64
65	dev_dbg(dev, "%s: mr %08x, sr %08x, imr %08x\n",
66		tag,
67		pwm_readl(pwm, PWM_MR),
68		pwm_readl(pwm, PWM_SR),
69		pwm_readl(pwm, PWM_IMR));
70	dev_dbg(dev,
71		"pwm ch%d - mr %08x, dty %u, prd %u, cnt %u\n",
72		ch->index,
73		pwm_channel_readl(ch, PWM_CMR),
74		pwm_channel_readl(ch, PWM_CDTY),
75		pwm_channel_readl(ch, PWM_CPRD),
76		pwm_channel_readl(ch, PWM_CCNT));
77}
78
79
80/**
81 * pwm_channel_alloc - allocate an unused PWM channel
82 * @index: identifies the channel
83 * @ch: structure to be initialized
84 *
85 * Drivers allocate PWM channels according to the board's wiring, and
86 * matching board-specific setup code.  Returns zero or negative errno.
87 */
88int pwm_channel_alloc(int index, struct pwm_channel *ch)
89{
90	unsigned long	flags;
91	int		status = 0;
92
93	/* insist on PWM init, with this signal pinned out */
94	if (!pwm || !(pwm->mask & 1 << index))
95		return -ENODEV;
96
97	if (index < 0 || index >= PWM_NCHAN || !ch)
98		return -EINVAL;
99	memset(ch, 0, sizeof *ch);
100
101	spin_lock_irqsave(&pwm->lock, flags);
102	if (pwm->channel[index])
103		status = -EBUSY;
104	else {
105		clk_enable(pwm->clk);
106
107		ch->regs = pwmc_regs(pwm, index);
108		ch->index = index;
109
110		/* REVISIT: ap7000 seems to go 2x as fast as we expect!! */
111		ch->mck = clk_get_rate(pwm->clk);
112
113		pwm->channel[index] = ch;
114		pwm->handler[index] = NULL;
115
116		/* channel and irq are always disabled when we return */
117		pwm_writel(pwm, PWM_DIS, 1 << index);
118		pwm_writel(pwm, PWM_IDR, 1 << index);
119	}
120	spin_unlock_irqrestore(&pwm->lock, flags);
121	return status;
122}
123EXPORT_SYMBOL(pwm_channel_alloc);
124
125static int pwmcheck(struct pwm_channel *ch)
126{
127	int		index;
128
129	if (!pwm)
130		return -ENODEV;
131	if (!ch)
132		return -EINVAL;
133	index = ch->index;
134	if (index < 0 || index >= PWM_NCHAN || pwm->channel[index] != ch)
135		return -EINVAL;
136
137	return index;
138}
139
140/**
141 * pwm_channel_free - release a previously allocated channel
142 * @ch: the channel being released
143 *
144 * The channel is completely shut down (counter and IRQ disabled),
145 * and made available for re-use.  Returns zero, or negative errno.
146 */
147int pwm_channel_free(struct pwm_channel *ch)
148{
149	unsigned long	flags;
150	int		t;
151
152	spin_lock_irqsave(&pwm->lock, flags);
153	t = pwmcheck(ch);
154	if (t >= 0) {
155		pwm->channel[t] = NULL;
156		pwm->handler[t] = NULL;
157
158		/* channel and irq are always disabled when we return */
159		pwm_writel(pwm, PWM_DIS, 1 << t);
160		pwm_writel(pwm, PWM_IDR, 1 << t);
161
162		clk_disable(pwm->clk);
163		t = 0;
164	}
165	spin_unlock_irqrestore(&pwm->lock, flags);
166	return t;
167}
168EXPORT_SYMBOL(pwm_channel_free);
169
170int __pwm_channel_onoff(struct pwm_channel *ch, int enabled)
171{
172	unsigned long	flags;
173	int		t;
174
175	/* OMITTED FUNCTIONALITY:  starting several channels in synch */
176
177	spin_lock_irqsave(&pwm->lock, flags);
178	t = pwmcheck(ch);
179	if (t >= 0) {
180		pwm_writel(pwm, enabled ? PWM_ENA : PWM_DIS, 1 << t);
181		t = 0;
182		pwm_dumpregs(ch, enabled ? "enable" : "disable");
183	}
184	spin_unlock_irqrestore(&pwm->lock, flags);
185
186	return t;
187}
188EXPORT_SYMBOL(__pwm_channel_onoff);
189
190/**
191 * pwm_clk_alloc - allocate and configure CLKA or CLKB
192 * @prescale: from 0..10, the power of two used to divide MCK
193 * @div: from 1..255, the linear divisor to use
194 *
195 * Returns PWM_CPR_CLKA, PWM_CPR_CLKB, or negative errno.  The allocated
196 * clock will run with a period of (2^prescale * div) / MCK, or twice as
197 * long if center aligned PWM output is used.  The clock must later be
198 * deconfigured using pwm_clk_free().
199 */
200int pwm_clk_alloc(unsigned prescale, unsigned div)
201{
202	unsigned long	flags;
203	u32		mr;
204	u32		val = (prescale << 8) | div;
205	int		ret = -EBUSY;
206
207	if (prescale >= 10 || div == 0 || div > 255)
208		return -EINVAL;
209
210	spin_lock_irqsave(&pwm->lock, flags);
211	mr = pwm_readl(pwm, PWM_MR);
212	if ((mr & 0xffff) == 0) {
213		mr |= val;
214		ret = PWM_CPR_CLKA;
215	} else if ((mr & (0xffff << 16)) == 0) {
216		mr |= val << 16;
217		ret = PWM_CPR_CLKB;
218	}
219	if (ret > 0)
220		pwm_writel(pwm, PWM_MR, mr);
221	spin_unlock_irqrestore(&pwm->lock, flags);
222	return ret;
223}
224EXPORT_SYMBOL(pwm_clk_alloc);
225
226/**
227 * pwm_clk_free - deconfigure and release CLKA or CLKB
228 *
229 * Reverses the effect of pwm_clk_alloc().
230 */
231void pwm_clk_free(unsigned clk)
232{
233	unsigned long	flags;
234	u32		mr;
235
236	spin_lock_irqsave(&pwm->lock, flags);
237	mr = pwm_readl(pwm, PWM_MR);
238	if (clk == PWM_CPR_CLKA)
239		pwm_writel(pwm, PWM_MR, mr & ~(0xffff << 0));
240	if (clk == PWM_CPR_CLKB)
241		pwm_writel(pwm, PWM_MR, mr & ~(0xffff << 16));
242	spin_unlock_irqrestore(&pwm->lock, flags);
243}
244EXPORT_SYMBOL(pwm_clk_free);
245
246/**
247 * pwm_channel_handler - manage channel's IRQ handler
248 * @ch: the channel
249 * @handler: the handler to use, possibly NULL
250 *
251 * If the handler is non-null, the handler will be called after every
252 * period of this PWM channel.  If the handler is null, this channel
253 * won't generate an IRQ.
254 */
255int pwm_channel_handler(struct pwm_channel *ch,
256		void (*handler)(struct pwm_channel *ch))
257{
258	unsigned long	flags;
259	int		t;
260
261	spin_lock_irqsave(&pwm->lock, flags);
262	t = pwmcheck(ch);
263	if (t >= 0) {
264		pwm->handler[t] = handler;
265		pwm_writel(pwm, handler ? PWM_IER : PWM_IDR, 1 << t);
266		t = 0;
267	}
268	spin_unlock_irqrestore(&pwm->lock, flags);
269
270	return t;
271}
272EXPORT_SYMBOL(pwm_channel_handler);
273
274static irqreturn_t pwm_irq(int id, void *_pwm)
275{
276	struct pwm	*p = _pwm;
277	irqreturn_t	handled = IRQ_NONE;
278	u32		irqstat;
279	int		index;
280
281	spin_lock(&p->lock);
282
283	/* ack irqs, then handle them */
284	irqstat = pwm_readl(pwm, PWM_ISR);
285
286	while (irqstat) {
287		struct pwm_channel *ch;
288		void (*handler)(struct pwm_channel *ch);
289
290		index = ffs(irqstat) - 1;
291		irqstat &= ~(1 << index);
292		ch = pwm->channel[index];
293		handler = pwm->handler[index];
294		if (handler && ch) {
295			spin_unlock(&p->lock);
296			handler(ch);
297			spin_lock(&p->lock);
298			handled = IRQ_HANDLED;
299		}
300	}
301
302	spin_unlock(&p->lock);
303	return handled;
304}
305
306static int __init pwm_probe(struct platform_device *pdev)
307{
308	struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
309	int irq = platform_get_irq(pdev, 0);
310	u32 *mp = pdev->dev.platform_data;
311	struct pwm *p;
312	int status = -EIO;
313
314	if (pwm)
315		return -EBUSY;
316	if (!r || irq < 0 || !mp || !*mp)
317		return -ENODEV;
318	if (*mp & ~((1<<PWM_NCHAN)-1)) {
319		dev_warn(&pdev->dev, "mask 0x%x ... more than %d channels\n",
320			*mp, PWM_NCHAN);
321		return -EINVAL;
322	}
323
324	p = kzalloc(sizeof(*p), GFP_KERNEL);
325	if (!p)
326		return -ENOMEM;
327
328	spin_lock_init(&p->lock);
329	p->pdev = pdev;
330	p->mask = *mp;
331	p->irq = irq;
332	p->base = ioremap(r->start, r->end - r->start + 1);
333	if (!p->base)
334		goto fail;
335	p->clk = clk_get(&pdev->dev, "pwm_clk");
336	if (IS_ERR(p->clk)) {
337		status = PTR_ERR(p->clk);
338		p->clk = NULL;
339		goto fail;
340	}
341
342	status = request_irq(irq, pwm_irq, 0, pdev->name, p);
343	if (status < 0)
344		goto fail;
345
346	pwm = p;
347	platform_set_drvdata(pdev, p);
348
349	return 0;
350
351fail:
352	if (p->clk)
353		clk_put(p->clk);
354	if (p->base)
355		iounmap(p->base);
356
357	kfree(p);
358	return status;
359}
360
361static int __exit pwm_remove(struct platform_device *pdev)
362{
363	struct pwm *p = platform_get_drvdata(pdev);
364
365	if (p != pwm)
366		return -EINVAL;
367
368	clk_enable(pwm->clk);
369	pwm_writel(pwm, PWM_DIS, (1 << PWM_NCHAN) - 1);
370	pwm_writel(pwm, PWM_IDR, (1 << PWM_NCHAN) - 1);
371	clk_disable(pwm->clk);
372
373	pwm = NULL;
374
375	free_irq(p->irq, p);
376	clk_put(p->clk);
377	iounmap(p->base);
378	kfree(p);
379
380	return 0;
381}
382
383static struct platform_driver atmel_pwm_driver = {
384	.driver = {
385		.name = "atmel_pwm",
386		.owner = THIS_MODULE,
387	},
388	.remove = __exit_p(pwm_remove),
389
390	/* NOTE: PWM can keep running in AVR32 "idle" and "frozen" states;
391	 * and all AT91sam9263 states, albeit at reduced clock rate if
392	 * MCK becomes the slow clock (i.e. what Linux labels STR).
393	 */
394};
395
396static int __init pwm_init(void)
397{
398	return platform_driver_probe(&atmel_pwm_driver, pwm_probe);
399}
400module_init(pwm_init);
401
402static void __exit pwm_exit(void)
403{
404	platform_driver_unregister(&atmel_pwm_driver);
405}
406module_exit(pwm_exit);
407
408MODULE_DESCRIPTION("Driver for AT32/AT91 PWM module");
409MODULE_LICENSE("GPL");
410MODULE_ALIAS("platform:atmel_pwm");
411