1/*
2 *  Driver for NEC VR4100 series General-purpose I/O Unit.
3 *
4 *  Copyright (C) 2002 MontaVista Software Inc.
5 *	Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
6 *  Copyright (C) 2003-2007  Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
7 *
8 *  This program is free software; you can redistribute it and/or modify
9 *  it under the terms of the GNU General Public License as published by
10 *  the Free Software Foundation; either version 2 of the License, or
11 *  (at your option) any later version.
12 *
13 *  This program is distributed in the hope that it will be useful,
14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *  GNU General Public License for more details.
17 *
18 *  You should have received a copy of the GNU General Public License
19 *  along with this program; if not, write to the Free Software
20 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 */
22#include <linux/errno.h>
23#include <linux/fs.h>
24#include <linux/init.h>
25#include <linux/interrupt.h>
26#include <linux/irq.h>
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/platform_device.h>
30#include <linux/spinlock.h>
31#include <linux/types.h>
32
33#include <asm/io.h>
34#include <asm/vr41xx/giu.h>
35#include <asm/vr41xx/irq.h>
36#include <asm/vr41xx/vr41xx.h>
37
38MODULE_AUTHOR("Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>");
39MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
40MODULE_LICENSE("GPL");
41
42static int major;	/* default is dynamic major device number */
43module_param(major, int, 0);
44MODULE_PARM_DESC(major, "Major device number");
45
46#define GIUIOSELL	0x00
47#define GIUIOSELH	0x02
48#define GIUPIODL	0x04
49#define GIUPIODH	0x06
50#define GIUINTSTATL	0x08
51#define GIUINTSTATH	0x0a
52#define GIUINTENL	0x0c
53#define GIUINTENH	0x0e
54#define GIUINTTYPL	0x10
55#define GIUINTTYPH	0x12
56#define GIUINTALSELL	0x14
57#define GIUINTALSELH	0x16
58#define GIUINTHTSELL	0x18
59#define GIUINTHTSELH	0x1a
60#define GIUPODATL	0x1c
61#define GIUPODATEN	0x1c
62#define GIUPODATH	0x1e
63 #define PIOEN0		0x0100
64 #define PIOEN1		0x0200
65#define GIUPODAT	0x1e
66#define GIUFEDGEINHL	0x20
67#define GIUFEDGEINHH	0x22
68#define GIUREDGEINHL	0x24
69#define GIUREDGEINHH	0x26
70
71#define GIUUSEUPDN	0x1e0
72#define GIUTERMUPDN	0x1e2
73
74#define GPIO_HAS_PULLUPDOWN_IO		0x0001
75#define GPIO_HAS_OUTPUT_ENABLE		0x0002
76#define GPIO_HAS_INTERRUPT_EDGE_SELECT	0x0100
77
78static spinlock_t giu_lock;
79static unsigned long giu_flags;
80static unsigned int giu_nr_pins;
81
82static void __iomem *giu_base;
83
84#define giu_read(offset)		readw(giu_base + (offset))
85#define giu_write(offset, value)	writew((value), giu_base + (offset))
86
87#define GPIO_PIN_OF_IRQ(irq)	((irq) - GIU_IRQ_BASE)
88#define GIUINT_HIGH_OFFSET	16
89#define GIUINT_HIGH_MAX		32
90
91static inline uint16_t giu_set(uint16_t offset, uint16_t set)
92{
93	uint16_t data;
94
95	data = giu_read(offset);
96	data |= set;
97	giu_write(offset, data);
98
99	return data;
100}
101
102static inline uint16_t giu_clear(uint16_t offset, uint16_t clear)
103{
104	uint16_t data;
105
106	data = giu_read(offset);
107	data &= ~clear;
108	giu_write(offset, data);
109
110	return data;
111}
112
113static void ack_giuint_low(unsigned int irq)
114{
115	giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq));
116}
117
118static void mask_giuint_low(unsigned int irq)
119{
120	giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
121}
122
123static void mask_ack_giuint_low(unsigned int irq)
124{
125	unsigned int pin;
126
127	pin = GPIO_PIN_OF_IRQ(irq);
128	giu_clear(GIUINTENL, 1 << pin);
129	giu_write(GIUINTSTATL, 1 << pin);
130}
131
132static void unmask_giuint_low(unsigned int irq)
133{
134	giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
135}
136
137static struct irq_chip giuint_low_irq_chip = {
138	.name		= "GIUINTL",
139	.ack		= ack_giuint_low,
140	.mask		= mask_giuint_low,
141	.mask_ack	= mask_ack_giuint_low,
142	.unmask		= unmask_giuint_low,
143};
144
145static void ack_giuint_high(unsigned int irq)
146{
147	giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
148}
149
150static void mask_giuint_high(unsigned int irq)
151{
152	giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
153}
154
155static void mask_ack_giuint_high(unsigned int irq)
156{
157	unsigned int pin;
158
159	pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
160	giu_clear(GIUINTENH, 1 << pin);
161	giu_write(GIUINTSTATH, 1 << pin);
162}
163
164static void unmask_giuint_high(unsigned int irq)
165{
166	giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
167}
168
169static struct irq_chip giuint_high_irq_chip = {
170	.name		= "GIUINTH",
171	.ack		= ack_giuint_high,
172	.mask		= mask_giuint_high,
173	.mask_ack	= mask_ack_giuint_high,
174	.unmask		= unmask_giuint_high,
175};
176
177static int giu_get_irq(unsigned int irq)
178{
179	uint16_t pendl, pendh, maskl, maskh;
180	int i;
181
182	pendl = giu_read(GIUINTSTATL);
183	pendh = giu_read(GIUINTSTATH);
184	maskl = giu_read(GIUINTENL);
185	maskh = giu_read(GIUINTENH);
186
187	maskl &= pendl;
188	maskh &= pendh;
189
190	if (maskl) {
191		for (i = 0; i < 16; i++) {
192			if (maskl & (1 << i))
193				return GIU_IRQ(i);
194		}
195	} else if (maskh) {
196		for (i = 0; i < 16; i++) {
197			if (maskh & (1 << i))
198				return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
199		}
200	}
201
202	printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
203	       maskl, pendl, maskh, pendh);
204
205	atomic_inc(&irq_err_count);
206
207	return -EINVAL;
208}
209
210void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal)
211{
212	uint16_t mask;
213
214	if (pin < GIUINT_HIGH_OFFSET) {
215		mask = 1 << pin;
216		if (trigger != IRQ_TRIGGER_LEVEL) {
217        		giu_set(GIUINTTYPL, mask);
218			if (signal == IRQ_SIGNAL_HOLD)
219				giu_set(GIUINTHTSELL, mask);
220			else
221				giu_clear(GIUINTHTSELL, mask);
222			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
223				switch (trigger) {
224				case IRQ_TRIGGER_EDGE_FALLING:
225					giu_set(GIUFEDGEINHL, mask);
226					giu_clear(GIUREDGEINHL, mask);
227					break;
228				case IRQ_TRIGGER_EDGE_RISING:
229					giu_clear(GIUFEDGEINHL, mask);
230					giu_set(GIUREDGEINHL, mask);
231					break;
232				default:
233					giu_set(GIUFEDGEINHL, mask);
234					giu_set(GIUREDGEINHL, mask);
235					break;
236				}
237			}
238			set_irq_chip_and_handler(GIU_IRQ(pin),
239			                         &giuint_low_irq_chip,
240			                         handle_edge_irq);
241		} else {
242			giu_clear(GIUINTTYPL, mask);
243			giu_clear(GIUINTHTSELL, mask);
244			set_irq_chip_and_handler(GIU_IRQ(pin),
245			                         &giuint_low_irq_chip,
246			                         handle_level_irq);
247		}
248		giu_write(GIUINTSTATL, mask);
249	} else if (pin < GIUINT_HIGH_MAX) {
250		mask = 1 << (pin - GIUINT_HIGH_OFFSET);
251		if (trigger != IRQ_TRIGGER_LEVEL) {
252			giu_set(GIUINTTYPH, mask);
253			if (signal == IRQ_SIGNAL_HOLD)
254				giu_set(GIUINTHTSELH, mask);
255			else
256				giu_clear(GIUINTHTSELH, mask);
257			if (giu_flags & GPIO_HAS_INTERRUPT_EDGE_SELECT) {
258				switch (trigger) {
259				case IRQ_TRIGGER_EDGE_FALLING:
260					giu_set(GIUFEDGEINHH, mask);
261					giu_clear(GIUREDGEINHH, mask);
262					break;
263				case IRQ_TRIGGER_EDGE_RISING:
264					giu_clear(GIUFEDGEINHH, mask);
265					giu_set(GIUREDGEINHH, mask);
266					break;
267				default:
268					giu_set(GIUFEDGEINHH, mask);
269					giu_set(GIUREDGEINHH, mask);
270					break;
271				}
272			}
273			set_irq_chip_and_handler(GIU_IRQ(pin),
274			                         &giuint_high_irq_chip,
275			                         handle_edge_irq);
276		} else {
277			giu_clear(GIUINTTYPH, mask);
278			giu_clear(GIUINTHTSELH, mask);
279			set_irq_chip_and_handler(GIU_IRQ(pin),
280			                         &giuint_high_irq_chip,
281			                         handle_level_irq);
282		}
283		giu_write(GIUINTSTATH, mask);
284	}
285}
286EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
287
288void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
289{
290	uint16_t mask;
291
292	if (pin < GIUINT_HIGH_OFFSET) {
293		mask = 1 << pin;
294		if (level == IRQ_LEVEL_HIGH)
295			giu_set(GIUINTALSELL, mask);
296		else
297			giu_clear(GIUINTALSELL, mask);
298		giu_write(GIUINTSTATL, mask);
299	} else if (pin < GIUINT_HIGH_MAX) {
300		mask = 1 << (pin - GIUINT_HIGH_OFFSET);
301		if (level == IRQ_LEVEL_HIGH)
302			giu_set(GIUINTALSELH, mask);
303		else
304			giu_clear(GIUINTALSELH, mask);
305		giu_write(GIUINTSTATH, mask);
306	}
307}
308EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
309
310gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
311{
312	uint16_t reg, mask;
313
314	if (pin >= giu_nr_pins)
315		return GPIO_DATA_INVAL;
316
317	if (pin < 16) {
318		reg = giu_read(GIUPIODL);
319		mask = (uint16_t)1 << pin;
320	} else if (pin < 32) {
321		reg = giu_read(GIUPIODH);
322		mask = (uint16_t)1 << (pin - 16);
323	} else if (pin < 48) {
324		reg = giu_read(GIUPODATL);
325		mask = (uint16_t)1 << (pin - 32);
326	} else {
327		reg = giu_read(GIUPODATH);
328		mask = (uint16_t)1 << (pin - 48);
329	}
330
331	if (reg & mask)
332		return GPIO_DATA_HIGH;
333
334	return GPIO_DATA_LOW;
335}
336EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);
337
338int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
339{
340	uint16_t offset, mask, reg;
341	unsigned long flags;
342
343	if (pin >= giu_nr_pins)
344		return -EINVAL;
345
346	if (pin < 16) {
347		offset = GIUPIODL;
348		mask = (uint16_t)1 << pin;
349	} else if (pin < 32) {
350		offset = GIUPIODH;
351		mask = (uint16_t)1 << (pin - 16);
352	} else if (pin < 48) {
353		offset = GIUPODATL;
354		mask = (uint16_t)1 << (pin - 32);
355	} else {
356		offset = GIUPODATH;
357		mask = (uint16_t)1 << (pin - 48);
358	}
359
360	spin_lock_irqsave(&giu_lock, flags);
361
362	reg = giu_read(offset);
363	if (data == GPIO_DATA_HIGH)
364		reg |= mask;
365	else
366		reg &= ~mask;
367	giu_write(offset, reg);
368
369	spin_unlock_irqrestore(&giu_lock, flags);
370
371	return 0;
372}
373EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);
374
375int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
376{
377	uint16_t offset, mask, reg;
378	unsigned long flags;
379
380	if (pin >= giu_nr_pins)
381		return -EINVAL;
382
383	if (pin < 16) {
384		offset = GIUIOSELL;
385		mask = (uint16_t)1 << pin;
386	} else if (pin < 32) {
387		offset = GIUIOSELH;
388		mask = (uint16_t)1 << (pin - 16);
389	} else {
390		if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
391			offset = GIUPODATEN;
392			mask = (uint16_t)1 << (pin - 32);
393		} else {
394			switch (pin) {
395			case 48:
396				offset = GIUPODATH;
397				mask = PIOEN0;
398				break;
399			case 49:
400				offset = GIUPODATH;
401				mask = PIOEN1;
402				break;
403			default:
404				return -EINVAL;
405			}
406		}
407	}
408
409	spin_lock_irqsave(&giu_lock, flags);
410
411	reg = giu_read(offset);
412	if (dir == GPIO_OUTPUT)
413		reg |= mask;
414	else
415		reg &= ~mask;
416	giu_write(offset, reg);
417
418	spin_unlock_irqrestore(&giu_lock, flags);
419
420	return 0;
421}
422EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);
423
424int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
425{
426	uint16_t reg, mask;
427	unsigned long flags;
428
429	if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
430		return -EPERM;
431
432	if (pin >= 15)
433		return -EINVAL;
434
435	mask = (uint16_t)1 << pin;
436
437	spin_lock_irqsave(&giu_lock, flags);
438
439	if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
440		reg = giu_read(GIUTERMUPDN);
441		if (pull == GPIO_PULL_UP)
442			reg |= mask;
443		else
444			reg &= ~mask;
445		giu_write(GIUTERMUPDN, reg);
446
447		reg = giu_read(GIUUSEUPDN);
448		reg |= mask;
449		giu_write(GIUUSEUPDN, reg);
450	} else {
451		reg = giu_read(GIUUSEUPDN);
452		reg &= ~mask;
453		giu_write(GIUUSEUPDN, reg);
454	}
455
456	spin_unlock_irqrestore(&giu_lock, flags);
457
458	return 0;
459}
460EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
461
462static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
463                         loff_t *ppos)
464{
465	unsigned int pin;
466	char value = '0';
467
468	pin = iminor(file->f_path.dentry->d_inode);
469	if (pin >= giu_nr_pins)
470		return -EBADF;
471
472	if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH)
473		value = '1';
474
475	if (len <= 0)
476		return -EFAULT;
477
478	if (put_user(value, buf))
479		return -EFAULT;
480
481	return 1;
482}
483
484static ssize_t gpio_write(struct file *file, const char __user *data,
485                          size_t len, loff_t *ppos)
486{
487	unsigned int pin;
488	size_t i;
489	char c;
490	int retval = 0;
491
492	pin = iminor(file->f_path.dentry->d_inode);
493	if (pin >= giu_nr_pins)
494		return -EBADF;
495
496	for (i = 0; i < len; i++) {
497		if (get_user(c, data + i))
498			return -EFAULT;
499
500		switch (c) {
501		case '0':
502			retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW);
503			break;
504		case '1':
505			retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH);
506			break;
507		case 'D':
508			printk(KERN_INFO "GPIO%d: pull down\n", pin);
509			retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN);
510			break;
511		case 'd':
512			printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
513			retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
514			break;
515		case 'I':
516			printk(KERN_INFO "GPIO%d: input\n", pin);
517			retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT);
518			break;
519		case 'O':
520			printk(KERN_INFO "GPIO%d: output\n", pin);
521			retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT);
522			break;
523		case 'o':
524			printk(KERN_INFO "GPIO%d: output disable\n", pin);
525			retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE);
526			break;
527		case 'P':
528			printk(KERN_INFO "GPIO%d: pull up\n", pin);
529			retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP);
530			break;
531		case 'p':
532			printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
533			retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
534			break;
535		default:
536			break;
537		}
538
539		if (retval < 0)
540			break;
541	}
542
543	return i;
544}
545
546static int gpio_open(struct inode *inode, struct file *file)
547{
548	unsigned int pin;
549
550	pin = iminor(inode);
551	if (pin >= giu_nr_pins)
552		return -EBADF;
553
554	return nonseekable_open(inode, file);
555}
556
557static int gpio_release(struct inode *inode, struct file *file)
558{
559	unsigned int pin;
560
561	pin = iminor(inode);
562	if (pin >= giu_nr_pins)
563		return -EBADF;
564
565	return 0;
566}
567
568static const struct file_operations gpio_fops = {
569	.owner		= THIS_MODULE,
570	.read		= gpio_read,
571	.write		= gpio_write,
572	.open		= gpio_open,
573	.release	= gpio_release,
574};
575
576static int __devinit giu_probe(struct platform_device *dev)
577{
578	struct resource *res;
579	unsigned int trigger, i, pin;
580	struct irq_chip *chip;
581	int irq, retval;
582
583	switch (dev->id) {
584	case GPIO_50PINS_PULLUPDOWN:
585		giu_flags = GPIO_HAS_PULLUPDOWN_IO;
586		giu_nr_pins = 50;
587		break;
588	case GPIO_36PINS:
589		giu_nr_pins = 36;
590		break;
591	case GPIO_48PINS_EDGE_SELECT:
592		giu_flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
593		giu_nr_pins = 48;
594		break;
595	default:
596		printk(KERN_ERR "GIU: unknown ID %d\n", dev->id);
597		return -ENODEV;
598	}
599
600	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
601	if (!res)
602		return -EBUSY;
603
604	giu_base = ioremap(res->start, res->end - res->start + 1);
605	if (!giu_base)
606		return -ENOMEM;
607
608	retval = register_chrdev(major, "GIU", &gpio_fops);
609	if (retval < 0) {
610		iounmap(giu_base);
611		giu_base = NULL;
612		return retval;
613	}
614
615	if (major == 0) {
616		major = retval;
617		printk(KERN_INFO "GIU: major number %d\n", major);
618	}
619
620	spin_lock_init(&giu_lock);
621
622	giu_write(GIUINTENL, 0);
623	giu_write(GIUINTENH, 0);
624
625	trigger = giu_read(GIUINTTYPH) << 16;
626	trigger |= giu_read(GIUINTTYPL);
627	for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
628		pin = GPIO_PIN_OF_IRQ(i);
629		if (pin < GIUINT_HIGH_OFFSET)
630			chip = &giuint_low_irq_chip;
631		else
632			chip = &giuint_high_irq_chip;
633
634		if (trigger & (1 << pin))
635			set_irq_chip_and_handler(i, chip, handle_edge_irq);
636		else
637			set_irq_chip_and_handler(i, chip, handle_level_irq);
638
639	}
640
641	irq = platform_get_irq(dev, 0);
642	if (irq < 0 || irq >= NR_IRQS)
643		return -EBUSY;
644
645	return cascade_irq(irq, giu_get_irq);
646}
647
648static int __devexit giu_remove(struct platform_device *dev)
649{
650	if (giu_base) {
651		iounmap(giu_base);
652		giu_base = NULL;
653	}
654
655	return 0;
656}
657
658static struct platform_driver giu_device_driver = {
659	.probe		= giu_probe,
660	.remove		= __devexit_p(giu_remove),
661	.driver		= {
662		.name	= "GIU",
663		.owner	= THIS_MODULE,
664	},
665};
666
667static int __init vr41xx_giu_init(void)
668{
669	return platform_driver_register(&giu_device_driver);
670}
671
672static void __exit vr41xx_giu_exit(void)
673{
674	platform_driver_unregister(&giu_device_driver);
675}
676
677module_init(vr41xx_giu_init);
678module_exit(vr41xx_giu_exit);
679