• 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/arch/arm/plat-stmp3xxx/
1/*
2 * Freescale STMP378X/STMP378X Pin Multiplexing
3 *
4 * Author: Vladislav Buzov <vbuzov@embeddedalley.com>
5 *
6 * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
7 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved.
8 */
9
10/*
11 * The code contained herein is licensed under the GNU General Public
12 * License. You may obtain a copy of the GNU General Public License
13 * Version 2 or later at the following locations:
14 *
15 * http://www.opensource.org/licenses/gpl-license.html
16 * http://www.gnu.org/copyleft/gpl.html
17 */
18#define DEBUG
19#include <linux/module.h>
20#include <linux/kernel.h>
21#include <linux/errno.h>
22#include <linux/sysdev.h>
23#include <linux/string.h>
24#include <linux/bitops.h>
25#include <linux/irq.h>
26
27#include <mach/hardware.h>
28#include <mach/platform.h>
29#include <mach/regs-pinctrl.h>
30#include <mach/pins.h>
31#include <mach/pinmux.h>
32
33#define NR_BANKS ARRAY_SIZE(pinmux_banks)
34static struct stmp3xxx_pinmux_bank pinmux_banks[] = {
35	[0] = {
36		.hw_muxsel = {
37			REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL0,
38			REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL1,
39		},
40		.hw_drive = {
41			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE0,
42			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE1,
43			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE2,
44			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE3,
45		},
46		.hw_pull = REGS_PINCTRL_BASE + HW_PINCTRL_PULL0,
47		.functions = { 0x0, 0x1, 0x2, 0x3 },
48		.strengths = { 0x0, 0x1, 0x2, 0x3, 0xff },
49
50		.hw_gpio_in = REGS_PINCTRL_BASE + HW_PINCTRL_DIN0,
51		.hw_gpio_out = REGS_PINCTRL_BASE + HW_PINCTRL_DOUT0,
52		.hw_gpio_doe = REGS_PINCTRL_BASE + HW_PINCTRL_DOE0,
53		.irq = IRQ_GPIO0,
54
55		.pin2irq = REGS_PINCTRL_BASE + HW_PINCTRL_PIN2IRQ0,
56		.irqstat = REGS_PINCTRL_BASE + HW_PINCTRL_IRQSTAT0,
57		.irqlevel = REGS_PINCTRL_BASE + HW_PINCTRL_IRQLEVEL0,
58		.irqpolarity = REGS_PINCTRL_BASE + HW_PINCTRL_IRQPOL0,
59		.irqen = REGS_PINCTRL_BASE + HW_PINCTRL_IRQEN0,
60	},
61	[1] = {
62		.hw_muxsel = {
63			REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL2,
64			REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL3,
65		},
66		.hw_drive = {
67			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE4,
68			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE5,
69			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE6,
70			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE7,
71		},
72		.hw_pull = REGS_PINCTRL_BASE + HW_PINCTRL_PULL1,
73		.functions = { 0x0, 0x1, 0x2, 0x3 },
74		.strengths = { 0x0, 0x1, 0x2, 0x3, 0xff },
75
76		.hw_gpio_in = REGS_PINCTRL_BASE + HW_PINCTRL_DIN1,
77		.hw_gpio_out = REGS_PINCTRL_BASE + HW_PINCTRL_DOUT1,
78		.hw_gpio_doe = REGS_PINCTRL_BASE + HW_PINCTRL_DOE1,
79		.irq = IRQ_GPIO1,
80
81		.pin2irq = REGS_PINCTRL_BASE + HW_PINCTRL_PIN2IRQ1,
82		.irqstat = REGS_PINCTRL_BASE + HW_PINCTRL_IRQSTAT1,
83		.irqlevel = REGS_PINCTRL_BASE + HW_PINCTRL_IRQLEVEL1,
84		.irqpolarity = REGS_PINCTRL_BASE + HW_PINCTRL_IRQPOL1,
85		.irqen = REGS_PINCTRL_BASE + HW_PINCTRL_IRQEN1,
86	},
87	[2] = {
88	       .hw_muxsel = {
89			REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL4,
90			REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL5,
91		},
92		.hw_drive = {
93			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE8,
94			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE9,
95			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE10,
96			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE11,
97		},
98		.hw_pull = REGS_PINCTRL_BASE + HW_PINCTRL_PULL2,
99		.functions = { 0x0, 0x1, 0x2, 0x3 },
100		.strengths = { 0x0, 0x1, 0x2, 0x1, 0x2 },
101
102		.hw_gpio_in = REGS_PINCTRL_BASE + HW_PINCTRL_DIN2,
103		.hw_gpio_out = REGS_PINCTRL_BASE + HW_PINCTRL_DOUT2,
104		.hw_gpio_doe = REGS_PINCTRL_BASE + HW_PINCTRL_DOE2,
105		.irq = IRQ_GPIO2,
106
107		.pin2irq = REGS_PINCTRL_BASE + HW_PINCTRL_PIN2IRQ2,
108		.irqstat = REGS_PINCTRL_BASE + HW_PINCTRL_IRQSTAT2,
109		.irqlevel = REGS_PINCTRL_BASE + HW_PINCTRL_IRQLEVEL2,
110		.irqpolarity = REGS_PINCTRL_BASE + HW_PINCTRL_IRQPOL2,
111		.irqen = REGS_PINCTRL_BASE + HW_PINCTRL_IRQEN2,
112	},
113	[3] = {
114	       .hw_muxsel = {
115		       REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL6,
116		       REGS_PINCTRL_BASE + HW_PINCTRL_MUXSEL7,
117	       },
118	       .hw_drive = {
119			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE12,
120			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE13,
121			REGS_PINCTRL_BASE + HW_PINCTRL_DRIVE14,
122			NULL,
123	       },
124	       .hw_pull = REGS_PINCTRL_BASE + HW_PINCTRL_PULL3,
125	       .functions = {0x0, 0x1, 0x2, 0x3},
126	       .strengths = {0x0, 0x1, 0x2, 0x3, 0xff},
127	},
128};
129
130static inline struct stmp3xxx_pinmux_bank *
131stmp3xxx_pinmux_bank(unsigned id, unsigned *bank, unsigned *pin)
132{
133	unsigned b, p;
134
135	b = STMP3XXX_PINID_TO_BANK(id);
136	p = STMP3XXX_PINID_TO_PINNUM(id);
137	BUG_ON(b >= NR_BANKS);
138	if (bank)
139		*bank = b;
140	if (pin)
141		*pin = p;
142	return &pinmux_banks[b];
143}
144
145/* Check if requested pin is owned by caller */
146static int stmp3xxx_check_pin(unsigned id, const char *label)
147{
148	unsigned pin;
149	struct stmp3xxx_pinmux_bank *pm = stmp3xxx_pinmux_bank(id, NULL, &pin);
150
151	if (!test_bit(pin, &pm->pin_map)) {
152		printk(KERN_WARNING
153		       "%s: Accessing free pin %x, caller %s\n",
154		       __func__, id, label);
155
156		return -EINVAL;
157	}
158
159	if (label && pm->pin_labels[pin] &&
160	    strcmp(label, pm->pin_labels[pin])) {
161		printk(KERN_WARNING
162		       "%s: Wrong pin owner %x, caller %s owner %s\n",
163		       __func__, id, label, pm->pin_labels[pin]);
164
165		return -EINVAL;
166	}
167	return 0;
168}
169
170void stmp3xxx_pin_strength(unsigned id, enum pin_strength strength,
171		const char *label)
172{
173	struct stmp3xxx_pinmux_bank *pbank;
174	void __iomem *hwdrive;
175	u32 shift, val;
176	u32 bank, pin;
177
178	pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
179	pr_debug("%s: label %s bank %d pin %d strength %d\n", __func__, label,
180		 bank, pin, strength);
181
182	hwdrive = pbank->hw_drive[pin / HW_DRIVE_PIN_NUM];
183	shift = (pin % HW_DRIVE_PIN_NUM) * HW_DRIVE_PIN_LEN;
184	val = pbank->strengths[strength];
185	if (val == 0xff) {
186		printk(KERN_WARNING
187		       "%s: strength is not supported for bank %d, caller %s",
188		       __func__, bank, label);
189		return;
190	}
191
192	if (stmp3xxx_check_pin(id, label))
193		return;
194
195	pr_debug("%s: writing 0x%x to 0x%p register\n", __func__,
196			val << shift, hwdrive);
197	stmp3xxx_clearl(HW_DRIVE_PINDRV_MASK << shift, hwdrive);
198	stmp3xxx_setl(val << shift, hwdrive);
199}
200
201void stmp3xxx_pin_voltage(unsigned id, enum pin_voltage voltage,
202			  const char *label)
203{
204	struct stmp3xxx_pinmux_bank *pbank;
205	void __iomem *hwdrive;
206	u32 shift;
207	u32 bank, pin;
208
209	pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
210	pr_debug("%s: label %s bank %d pin %d voltage %d\n", __func__, label,
211		 bank, pin, voltage);
212
213	hwdrive = pbank->hw_drive[pin / HW_DRIVE_PIN_NUM];
214	shift = (pin % HW_DRIVE_PIN_NUM) * HW_DRIVE_PIN_LEN;
215
216	if (stmp3xxx_check_pin(id, label))
217		return;
218
219	pr_debug("%s: changing 0x%x bit in 0x%p register\n",
220			__func__, HW_DRIVE_PINV_MASK << shift, hwdrive);
221	if (voltage == PIN_1_8V)
222		stmp3xxx_clearl(HW_DRIVE_PINV_MASK << shift, hwdrive);
223	else
224		stmp3xxx_setl(HW_DRIVE_PINV_MASK << shift, hwdrive);
225}
226
227void stmp3xxx_pin_pullup(unsigned id, int enable, const char *label)
228{
229	struct stmp3xxx_pinmux_bank *pbank;
230	void __iomem *hwpull;
231	u32 bank, pin;
232
233	pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
234	pr_debug("%s: label %s bank %d pin %d enable %d\n", __func__, label,
235		 bank, pin, enable);
236
237	hwpull = pbank->hw_pull;
238
239	if (stmp3xxx_check_pin(id, label))
240		return;
241
242	pr_debug("%s: changing 0x%x bit in 0x%p register\n",
243			__func__, 1 << pin, hwpull);
244	if (enable)
245		stmp3xxx_setl(1 << pin, hwpull);
246	else
247		stmp3xxx_clearl(1 << pin, hwpull);
248}
249
250int stmp3xxx_request_pin(unsigned id, enum pin_fun fun, const char *label)
251{
252	struct stmp3xxx_pinmux_bank *pbank;
253	u32 bank, pin;
254	int ret = 0;
255
256	pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
257	pr_debug("%s: label %s bank %d pin %d fun %d\n", __func__, label,
258		 bank, pin, fun);
259
260	if (test_bit(pin, &pbank->pin_map)) {
261		printk(KERN_WARNING
262		       "%s: CONFLICT DETECTED pin %d:%d caller %s owner %s\n",
263		       __func__, bank, pin, label, pbank->pin_labels[pin]);
264		return -EBUSY;
265	}
266
267	set_bit(pin, &pbank->pin_map);
268	pbank->pin_labels[pin] = label;
269
270	stmp3xxx_set_pin_type(id, fun);
271
272	return ret;
273}
274
275void stmp3xxx_set_pin_type(unsigned id, enum pin_fun fun)
276{
277	struct stmp3xxx_pinmux_bank *pbank;
278	void __iomem *hwmux;
279	u32 shift, val;
280	u32 bank, pin;
281
282	pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
283
284	hwmux = pbank->hw_muxsel[pin / HW_MUXSEL_PIN_NUM];
285	shift = (pin % HW_MUXSEL_PIN_NUM) * HW_MUXSEL_PIN_LEN;
286
287	val = pbank->functions[fun];
288	shift = (pin % HW_MUXSEL_PIN_NUM) * HW_MUXSEL_PIN_LEN;
289	pr_debug("%s: writing 0x%x to 0x%p register\n",
290			__func__, val << shift, hwmux);
291	stmp3xxx_clearl(HW_MUXSEL_PINFUN_MASK << shift, hwmux);
292	stmp3xxx_setl(val << shift, hwmux);
293}
294
295void stmp3xxx_release_pin(unsigned id, const char *label)
296{
297	struct stmp3xxx_pinmux_bank *pbank;
298	u32 bank, pin;
299
300	pbank = stmp3xxx_pinmux_bank(id, &bank, &pin);
301	pr_debug("%s: label %s bank %d pin %d\n", __func__, label, bank, pin);
302
303	if (stmp3xxx_check_pin(id, label))
304		return;
305
306	clear_bit(pin, &pbank->pin_map);
307	pbank->pin_labels[pin] = NULL;
308}
309
310int stmp3xxx_request_pin_group(struct pin_group *pin_group, const char *label)
311{
312	struct pin_desc *pin;
313	int p;
314	int err = 0;
315
316	/* Allocate and configure pins */
317	for (p = 0; p < pin_group->nr_pins; p++) {
318		pr_debug("%s: #%d\n", __func__, p);
319		pin = &pin_group->pins[p];
320
321		err = stmp3xxx_request_pin(pin->id, pin->fun, label);
322		if (err)
323			goto out_err;
324
325		stmp3xxx_pin_strength(pin->id, pin->strength, label);
326		stmp3xxx_pin_voltage(pin->id, pin->voltage, label);
327		stmp3xxx_pin_pullup(pin->id, pin->pullup, label);
328	}
329
330	return 0;
331
332out_err:
333	/* Release allocated pins in case of error */
334	while (--p >= 0) {
335		pr_debug("%s: releasing #%d\n", __func__, p);
336		stmp3xxx_release_pin(pin_group->pins[p].id, label);
337	}
338	return err;
339}
340EXPORT_SYMBOL(stmp3xxx_request_pin_group);
341
342void stmp3xxx_release_pin_group(struct pin_group *pin_group, const char *label)
343{
344	struct pin_desc *pin;
345	int p;
346
347	for (p = 0; p < pin_group->nr_pins; p++) {
348		pin = &pin_group->pins[p];
349		stmp3xxx_release_pin(pin->id, label);
350	}
351}
352EXPORT_SYMBOL(stmp3xxx_release_pin_group);
353
354static int stmp3xxx_irq_to_gpio(int irq,
355	struct stmp3xxx_pinmux_bank **bank, unsigned *gpio)
356{
357	struct stmp3xxx_pinmux_bank *pm;
358
359	for (pm = pinmux_banks; pm < pinmux_banks + NR_BANKS; pm++)
360		if (pm->virq <= irq && irq < pm->virq + 32) {
361			*bank = pm;
362			*gpio = irq - pm->virq;
363			return 0;
364		}
365	return -ENOENT;
366}
367
368static int stmp3xxx_set_irqtype(unsigned irq, unsigned type)
369{
370	struct stmp3xxx_pinmux_bank *pm;
371	unsigned gpio;
372	int l, p;
373
374	stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
375	switch (type) {
376	case IRQ_TYPE_EDGE_RISING:
377		l = 0; p = 1; break;
378	case IRQ_TYPE_EDGE_FALLING:
379		l = 0; p = 0; break;
380	case IRQ_TYPE_LEVEL_HIGH:
381		l = 1; p = 1; break;
382	case IRQ_TYPE_LEVEL_LOW:
383		l = 1; p = 0; break;
384	default:
385		pr_debug("%s: Incorrect GPIO interrupt type 0x%x\n",
386				__func__, type);
387		return -ENXIO;
388	}
389
390	if (l)
391		stmp3xxx_setl(1 << gpio, pm->irqlevel);
392	else
393		stmp3xxx_clearl(1 << gpio, pm->irqlevel);
394	if (p)
395		stmp3xxx_setl(1 << gpio, pm->irqpolarity);
396	else
397		stmp3xxx_clearl(1 << gpio, pm->irqpolarity);
398	return 0;
399}
400
401static void stmp3xxx_pin_ack_irq(unsigned irq)
402{
403	u32 stat;
404	struct stmp3xxx_pinmux_bank *pm;
405	unsigned gpio;
406
407	stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
408	stat = __raw_readl(pm->irqstat) & (1 << gpio);
409	stmp3xxx_clearl(stat, pm->irqstat);
410}
411
412static void stmp3xxx_pin_mask_irq(unsigned irq)
413{
414	struct stmp3xxx_pinmux_bank *pm;
415	unsigned gpio;
416
417	stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
418	stmp3xxx_clearl(1 << gpio, pm->irqen);
419	stmp3xxx_clearl(1 << gpio, pm->pin2irq);
420}
421
422static void stmp3xxx_pin_unmask_irq(unsigned irq)
423{
424	struct stmp3xxx_pinmux_bank *pm;
425	unsigned gpio;
426
427	stmp3xxx_irq_to_gpio(irq, &pm, &gpio);
428	stmp3xxx_setl(1 << gpio, pm->irqen);
429	stmp3xxx_setl(1 << gpio, pm->pin2irq);
430}
431
432static inline
433struct stmp3xxx_pinmux_bank *to_pinmux_bank(struct gpio_chip *chip)
434{
435	return container_of(chip, struct stmp3xxx_pinmux_bank, chip);
436}
437
438static int stmp3xxx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
439{
440	struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
441	return pm->virq + offset;
442}
443
444static int stmp3xxx_gpio_get(struct gpio_chip *chip, unsigned offset)
445{
446	struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
447	unsigned v;
448
449	v = __raw_readl(pm->hw_gpio_in) & (1 << offset);
450	return v ? 1 : 0;
451}
452
453static void stmp3xxx_gpio_set(struct gpio_chip *chip, unsigned offset, int v)
454{
455	struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
456
457	if (v)
458		stmp3xxx_setl(1 << offset, pm->hw_gpio_out);
459	else
460		stmp3xxx_clearl(1 << offset, pm->hw_gpio_out);
461}
462
463static int stmp3xxx_gpio_output(struct gpio_chip *chip, unsigned offset, int v)
464{
465	struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
466
467	stmp3xxx_setl(1 << offset, pm->hw_gpio_doe);
468	stmp3xxx_gpio_set(chip, offset, v);
469	return 0;
470}
471
472static int stmp3xxx_gpio_input(struct gpio_chip *chip, unsigned offset)
473{
474	struct stmp3xxx_pinmux_bank *pm = to_pinmux_bank(chip);
475
476	stmp3xxx_clearl(1 << offset, pm->hw_gpio_doe);
477	return 0;
478}
479
480static int stmp3xxx_gpio_request(struct gpio_chip *chip, unsigned offset)
481{
482	return stmp3xxx_request_pin(chip->base + offset, PIN_GPIO, "gpio");
483}
484
485static void stmp3xxx_gpio_free(struct gpio_chip *chip, unsigned offset)
486{
487	stmp3xxx_release_pin(chip->base + offset, "gpio");
488}
489
490static void stmp3xxx_gpio_irq(u32 irq, struct irq_desc *desc)
491{
492	struct stmp3xxx_pinmux_bank *pm = get_irq_data(irq);
493	int gpio_irq = pm->virq;
494	u32 stat = __raw_readl(pm->irqstat);
495
496	while (stat) {
497		if (stat & 1)
498			irq_desc[gpio_irq].handle_irq(gpio_irq,
499				&irq_desc[gpio_irq]);
500		gpio_irq++;
501		stat >>= 1;
502	}
503}
504
505static struct irq_chip gpio_irq_chip = {
506	.ack	= stmp3xxx_pin_ack_irq,
507	.mask	= stmp3xxx_pin_mask_irq,
508	.unmask	= stmp3xxx_pin_unmask_irq,
509	.set_type = stmp3xxx_set_irqtype,
510};
511
512int __init stmp3xxx_pinmux_init(int virtual_irq_start)
513{
514	int b, r = 0;
515	struct stmp3xxx_pinmux_bank *pm;
516	int virq;
517
518	for (b = 0; b < 3; b++) {
519		/* only banks 0,1,2 are allowed to GPIO */
520		pm = pinmux_banks + b;
521		pm->chip.base = 32 * b;
522		pm->chip.ngpio = 32;
523		pm->chip.owner = THIS_MODULE;
524		pm->chip.can_sleep = 1;
525		pm->chip.exported = 1;
526		pm->chip.to_irq = stmp3xxx_gpio_to_irq;
527		pm->chip.direction_input = stmp3xxx_gpio_input;
528		pm->chip.direction_output = stmp3xxx_gpio_output;
529		pm->chip.get = stmp3xxx_gpio_get;
530		pm->chip.set = stmp3xxx_gpio_set;
531		pm->chip.request = stmp3xxx_gpio_request;
532		pm->chip.free = stmp3xxx_gpio_free;
533		pm->virq = virtual_irq_start + b * 32;
534
535		for (virq = pm->virq; virq < pm->virq; virq++) {
536			gpio_irq_chip.mask(virq);
537			set_irq_chip(virq, &gpio_irq_chip);
538			set_irq_handler(virq, handle_level_irq);
539			set_irq_flags(virq, IRQF_VALID);
540		}
541		r = gpiochip_add(&pm->chip);
542		if (r < 0)
543			break;
544		set_irq_chained_handler(pm->irq, stmp3xxx_gpio_irq);
545		set_irq_data(pm->irq, pm);
546	}
547	return r;
548}
549
550MODULE_AUTHOR("Vladislav Buzov");
551MODULE_LICENSE("GPL");
552