xref: /linux/arch/m68k/coldfire/gpio.c (revision 96ac6d435100450f0565708d9b885ea2a7400e0a)
1 /*
2  * Coldfire generic GPIO support.
3  *
4  * (C) Copyright 2009, Steven King <sfking@fdwdc.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  */
15 
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/init.h>
19 #include <linux/device.h>
20 
21 #include <linux/io.h>
22 #include <asm/coldfire.h>
23 #include <asm/mcfsim.h>
24 #include <asm/mcfgpio.h>
25 
26 int __mcfgpio_get_value(unsigned gpio)
27 {
28 	return mcfgpio_read(__mcfgpio_ppdr(gpio)) & mcfgpio_bit(gpio);
29 }
30 EXPORT_SYMBOL(__mcfgpio_get_value);
31 
32 void __mcfgpio_set_value(unsigned gpio, int value)
33 {
34 	if (gpio < MCFGPIO_SCR_START) {
35 		unsigned long flags;
36 		MCFGPIO_PORTTYPE data;
37 
38 		local_irq_save(flags);
39 		data = mcfgpio_read(__mcfgpio_podr(gpio));
40 		if (value)
41 			data |= mcfgpio_bit(gpio);
42 		else
43 			data &= ~mcfgpio_bit(gpio);
44 		mcfgpio_write(data, __mcfgpio_podr(gpio));
45 		local_irq_restore(flags);
46 	} else {
47 		if (value)
48 			mcfgpio_write(mcfgpio_bit(gpio),
49 					MCFGPIO_SETR_PORT(gpio));
50 		else
51 			mcfgpio_write(~mcfgpio_bit(gpio),
52 					MCFGPIO_CLRR_PORT(gpio));
53 	}
54 }
55 EXPORT_SYMBOL(__mcfgpio_set_value);
56 
57 int __mcfgpio_direction_input(unsigned gpio)
58 {
59 	unsigned long flags;
60 	MCFGPIO_PORTTYPE dir;
61 
62 	local_irq_save(flags);
63 	dir = mcfgpio_read(__mcfgpio_pddr(gpio));
64 	dir &= ~mcfgpio_bit(gpio);
65 	mcfgpio_write(dir, __mcfgpio_pddr(gpio));
66 	local_irq_restore(flags);
67 
68 	return 0;
69 }
70 EXPORT_SYMBOL(__mcfgpio_direction_input);
71 
72 int __mcfgpio_direction_output(unsigned gpio, int value)
73 {
74 	unsigned long flags;
75 	MCFGPIO_PORTTYPE data;
76 
77 	local_irq_save(flags);
78 	data = mcfgpio_read(__mcfgpio_pddr(gpio));
79 	data |= mcfgpio_bit(gpio);
80 	mcfgpio_write(data, __mcfgpio_pddr(gpio));
81 
82 	/* now set the data to output */
83 	if (gpio < MCFGPIO_SCR_START) {
84 		data = mcfgpio_read(__mcfgpio_podr(gpio));
85 		if (value)
86 			data |= mcfgpio_bit(gpio);
87 		else
88 			data &= ~mcfgpio_bit(gpio);
89 		mcfgpio_write(data, __mcfgpio_podr(gpio));
90 	} else {
91 		 if (value)
92 			mcfgpio_write(mcfgpio_bit(gpio),
93 					MCFGPIO_SETR_PORT(gpio));
94 		 else
95 			 mcfgpio_write(~mcfgpio_bit(gpio),
96 					 MCFGPIO_CLRR_PORT(gpio));
97 	}
98 	local_irq_restore(flags);
99 	return 0;
100 }
101 EXPORT_SYMBOL(__mcfgpio_direction_output);
102 
103 int __mcfgpio_request(unsigned gpio)
104 {
105 	return 0;
106 }
107 EXPORT_SYMBOL(__mcfgpio_request);
108 
109 void __mcfgpio_free(unsigned gpio)
110 {
111 	__mcfgpio_direction_input(gpio);
112 }
113 EXPORT_SYMBOL(__mcfgpio_free);
114 
115 #ifdef CONFIG_GPIOLIB
116 
117 static int mcfgpio_direction_input(struct gpio_chip *chip, unsigned offset)
118 {
119 	return __mcfgpio_direction_input(offset);
120 }
121 
122 static int mcfgpio_get_value(struct gpio_chip *chip, unsigned offset)
123 {
124 	return !!__mcfgpio_get_value(offset);
125 }
126 
127 static int mcfgpio_direction_output(struct gpio_chip *chip, unsigned offset,
128 				    int value)
129 {
130 	return __mcfgpio_direction_output(offset, value);
131 }
132 
133 static void mcfgpio_set_value(struct gpio_chip *chip, unsigned offset,
134 			      int value)
135 {
136 	__mcfgpio_set_value(offset, value);
137 }
138 
139 static int mcfgpio_request(struct gpio_chip *chip, unsigned offset)
140 {
141 	return __mcfgpio_request(offset);
142 }
143 
144 static void mcfgpio_free(struct gpio_chip *chip, unsigned offset)
145 {
146 	__mcfgpio_free(offset);
147 }
148 
149 static int mcfgpio_to_irq(struct gpio_chip *chip, unsigned offset)
150 {
151 #if defined(MCFGPIO_IRQ_MIN)
152 	if ((offset >= MCFGPIO_IRQ_MIN) && (offset < MCFGPIO_IRQ_MAX))
153 #else
154 	if (offset < MCFGPIO_IRQ_MAX)
155 #endif
156 		return MCFGPIO_IRQ_VECBASE + offset;
157 	else
158 		return -EINVAL;
159 }
160 
161 static struct gpio_chip mcfgpio_chip = {
162 	.label			= "mcfgpio",
163 	.request		= mcfgpio_request,
164 	.free			= mcfgpio_free,
165 	.direction_input	= mcfgpio_direction_input,
166 	.direction_output	= mcfgpio_direction_output,
167 	.get			= mcfgpio_get_value,
168 	.set			= mcfgpio_set_value,
169 	.to_irq			= mcfgpio_to_irq,
170 	.base			= 0,
171 	.ngpio			= MCFGPIO_PIN_MAX,
172 };
173 
174 static int __init mcfgpio_sysinit(void)
175 {
176 	return gpiochip_add_data(&mcfgpio_chip, NULL);
177 }
178 
179 core_initcall(mcfgpio_sysinit);
180 #endif
181