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/init.h>
18
19#include <asm/coldfire.h>
20#include <asm/mcfsim.h>
21#include <asm/mcfgpio.h>
22
23static struct mcf_gpio_chip mcf_gpio_chips[] = {
24	{
25		.gpio_chip			= {
26			.label			= "PIRQ",
27			.request		= mcf_gpio_request,
28			.free			= mcf_gpio_free,
29			.direction_input	= mcf_gpio_direction_input,
30			.direction_output	= mcf_gpio_direction_output,
31			.get			= mcf_gpio_get_value,
32			.set			= mcf_gpio_set_value,
33			.ngpio			= 8,
34		},
35		.pddr				= (void __iomem *) MCFEPORT_EPDDR,
36		.podr				= (void __iomem *) MCFEPORT_EPDR,
37		.ppdr				= (void __iomem *) MCFEPORT_EPPDR,
38	},
39	{
40		.gpio_chip			= {
41			.label			= "FECH",
42			.request		= mcf_gpio_request,
43			.free			= mcf_gpio_free,
44			.direction_input	= mcf_gpio_direction_input,
45			.direction_output	= mcf_gpio_direction_output,
46			.get			= mcf_gpio_get_value,
47			.set			= mcf_gpio_set_value_fast,
48			.base			= 8,
49			.ngpio			= 8,
50		},
51		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECH,
52		.podr				= (void __iomem *) MCFGPIO_PODR_FECH,
53		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECH,
54		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECH,
55		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECH,
56	},
57	{
58		.gpio_chip			= {
59			.label			= "FECL",
60			.request		= mcf_gpio_request,
61			.free			= mcf_gpio_free,
62			.direction_input	= mcf_gpio_direction_input,
63			.direction_output	= mcf_gpio_direction_output,
64			.get			= mcf_gpio_get_value,
65			.set			= mcf_gpio_set_value_fast,
66			.base			= 16,
67			.ngpio			= 8,
68		},
69		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECL,
70		.podr				= (void __iomem *) MCFGPIO_PODR_FECL,
71		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECL,
72		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECL,
73		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECL,
74	},
75	{
76		.gpio_chip			= {
77			.label			= "SSI",
78			.request		= mcf_gpio_request,
79			.free			= mcf_gpio_free,
80			.direction_input	= mcf_gpio_direction_input,
81			.direction_output	= mcf_gpio_direction_output,
82			.get			= mcf_gpio_get_value,
83			.set			= mcf_gpio_set_value_fast,
84			.base			= 24,
85			.ngpio			= 5,
86		},
87		.pddr				= (void __iomem *) MCFGPIO_PDDR_SSI,
88		.podr				= (void __iomem *) MCFGPIO_PODR_SSI,
89		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_SSI,
90		.setr				= (void __iomem *) MCFGPIO_PPDSDR_SSI,
91		.clrr				= (void __iomem *) MCFGPIO_PCLRR_SSI,
92	},
93	{
94		.gpio_chip			= {
95			.label			= "BUSCTL",
96			.request		= mcf_gpio_request,
97			.free			= mcf_gpio_free,
98			.direction_input	= mcf_gpio_direction_input,
99			.direction_output	= mcf_gpio_direction_output,
100			.get			= mcf_gpio_get_value,
101			.set			= mcf_gpio_set_value_fast,
102			.base			= 32,
103			.ngpio			= 4,
104		},
105		.pddr				= (void __iomem *) MCFGPIO_PDDR_BUSCTL,
106		.podr				= (void __iomem *) MCFGPIO_PODR_BUSCTL,
107		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
108		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
109		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
110	},
111	{
112		.gpio_chip			= {
113			.label			= "BE",
114			.request		= mcf_gpio_request,
115			.free			= mcf_gpio_free,
116			.direction_input	= mcf_gpio_direction_input,
117			.direction_output	= mcf_gpio_direction_output,
118			.get			= mcf_gpio_get_value,
119			.set			= mcf_gpio_set_value_fast,
120			.base			= 40,
121			.ngpio			= 4,
122		},
123		.pddr				= (void __iomem *) MCFGPIO_PDDR_BE,
124		.podr				= (void __iomem *) MCFGPIO_PODR_BE,
125		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BE,
126		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BE,
127		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BE,
128	},
129	{
130		.gpio_chip			= {
131			.label			= "CS",
132			.request		= mcf_gpio_request,
133			.free			= mcf_gpio_free,
134			.direction_input	= mcf_gpio_direction_input,
135			.direction_output	= mcf_gpio_direction_output,
136			.get			= mcf_gpio_get_value,
137			.set			= mcf_gpio_set_value_fast,
138			.base			= 49,
139			.ngpio			= 5,
140		},
141		.pddr				= (void __iomem *) MCFGPIO_PDDR_CS,
142		.podr				= (void __iomem *) MCFGPIO_PODR_CS,
143		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
144		.setr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
145		.clrr				= (void __iomem *) MCFGPIO_PCLRR_CS,
146	},
147	{
148		.gpio_chip			= {
149			.label			= "PWM",
150			.request		= mcf_gpio_request,
151			.free			= mcf_gpio_free,
152			.direction_input	= mcf_gpio_direction_input,
153			.direction_output	= mcf_gpio_direction_output,
154			.get			= mcf_gpio_get_value,
155			.set			= mcf_gpio_set_value_fast,
156			.base			= 58,
157			.ngpio			= 4,
158		},
159		.pddr				= (void __iomem *) MCFGPIO_PDDR_PWM,
160		.podr				= (void __iomem *) MCFGPIO_PODR_PWM,
161		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_PWM,
162		.setr				= (void __iomem *) MCFGPIO_PPDSDR_PWM,
163		.clrr				= (void __iomem *) MCFGPIO_PCLRR_PWM,
164	},
165	{
166		.gpio_chip			= {
167			.label			= "FECI2C",
168			.request		= mcf_gpio_request,
169			.free			= mcf_gpio_free,
170			.direction_input	= mcf_gpio_direction_input,
171			.direction_output	= mcf_gpio_direction_output,
172			.get			= mcf_gpio_get_value,
173			.set			= mcf_gpio_set_value_fast,
174			.base			= 64,
175			.ngpio			= 4,
176		},
177		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECI2C,
178		.podr				= (void __iomem *) MCFGPIO_PODR_FECI2C,
179		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
180		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
181		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECI2C,
182	},
183	{
184		.gpio_chip			= {
185			.label			= "UART",
186			.request		= mcf_gpio_request,
187			.free			= mcf_gpio_free,
188			.direction_input	= mcf_gpio_direction_input,
189			.direction_output	= mcf_gpio_direction_output,
190			.get			= mcf_gpio_get_value,
191			.set			= mcf_gpio_set_value_fast,
192			.base			= 72,
193			.ngpio			= 8,
194		},
195		.pddr				= (void __iomem *) MCFGPIO_PDDR_UART,
196		.podr				= (void __iomem *) MCFGPIO_PODR_UART,
197		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UART,
198		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UART,
199		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UART,
200	},
201	{
202		.gpio_chip			= {
203			.label			= "QSPI",
204			.request		= mcf_gpio_request,
205			.free			= mcf_gpio_free,
206			.direction_input	= mcf_gpio_direction_input,
207			.direction_output	= mcf_gpio_direction_output,
208			.get			= mcf_gpio_get_value,
209			.set			= mcf_gpio_set_value_fast,
210			.base			= 80,
211			.ngpio			= 6,
212		},
213		.pddr				= (void __iomem *) MCFGPIO_PDDR_QSPI,
214		.podr				= (void __iomem *) MCFGPIO_PODR_QSPI,
215		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
216		.setr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
217		.clrr				= (void __iomem *) MCFGPIO_PCLRR_QSPI,
218	},
219	{
220		.gpio_chip			= {
221			.label			= "TIMER",
222			.request		= mcf_gpio_request,
223			.free			= mcf_gpio_free,
224			.direction_input	= mcf_gpio_direction_input,
225			.direction_output	= mcf_gpio_direction_output,
226			.get			= mcf_gpio_get_value,
227			.set			= mcf_gpio_set_value_fast,
228			.base			= 88,
229			.ngpio			= 4,
230		},
231		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMER,
232		.podr				= (void __iomem *) MCFGPIO_PODR_TIMER,
233		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
234		.setr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
235		.clrr				= (void __iomem *) MCFGPIO_PCLRR_TIMER,
236	},
237	{
238		.gpio_chip			= {
239			.label			= "LCDDATAH",
240			.request		= mcf_gpio_request,
241			.free			= mcf_gpio_free,
242			.direction_input	= mcf_gpio_direction_input,
243			.direction_output	= mcf_gpio_direction_output,
244			.get			= mcf_gpio_get_value,
245			.set			= mcf_gpio_set_value_fast,
246			.base			= 96,
247			.ngpio			= 2,
248		},
249		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDDATAH,
250		.podr				= (void __iomem *) MCFGPIO_PODR_LCDDATAH,
251		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAH,
252		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAH,
253		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDDATAH,
254	},
255	{
256		.gpio_chip			= {
257			.label			= "LCDDATAM",
258			.request		= mcf_gpio_request,
259			.free			= mcf_gpio_free,
260			.direction_input	= mcf_gpio_direction_input,
261			.direction_output	= mcf_gpio_direction_output,
262			.get			= mcf_gpio_get_value,
263			.set			= mcf_gpio_set_value_fast,
264			.base			= 104,
265			.ngpio			= 8,
266		},
267		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDDATAM,
268		.podr				= (void __iomem *) MCFGPIO_PODR_LCDDATAM,
269		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAM,
270		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAM,
271		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDDATAM,
272	},
273	{
274		.gpio_chip			= {
275			.label			= "LCDDATAL",
276			.request		= mcf_gpio_request,
277			.free			= mcf_gpio_free,
278			.direction_input	= mcf_gpio_direction_input,
279			.direction_output	= mcf_gpio_direction_output,
280			.get			= mcf_gpio_get_value,
281			.set			= mcf_gpio_set_value_fast,
282			.base			= 112,
283			.ngpio			= 8,
284		},
285		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDDATAL,
286		.podr				= (void __iomem *) MCFGPIO_PODR_LCDDATAL,
287		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAL,
288		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAL,
289		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDDATAL,
290	},
291	{
292		.gpio_chip			= {
293			.label			= "LCDCTLH",
294			.request		= mcf_gpio_request,
295			.free			= mcf_gpio_free,
296			.direction_input	= mcf_gpio_direction_input,
297			.direction_output	= mcf_gpio_direction_output,
298			.get			= mcf_gpio_get_value,
299			.set			= mcf_gpio_set_value_fast,
300			.base			= 120,
301			.ngpio			= 1,
302		},
303		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDCTLH,
304		.podr				= (void __iomem *) MCFGPIO_PODR_LCDCTLH,
305		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDCTLH,
306		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDCTLH,
307		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDCTLH,
308	},
309	{
310		.gpio_chip			= {
311			.label			= "LCDCTLL",
312			.request		= mcf_gpio_request,
313			.free			= mcf_gpio_free,
314			.direction_input	= mcf_gpio_direction_input,
315			.direction_output	= mcf_gpio_direction_output,
316			.get			= mcf_gpio_get_value,
317			.set			= mcf_gpio_set_value_fast,
318			.base			= 128,
319			.ngpio			= 8,
320		},
321		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDCTLL,
322		.podr				= (void __iomem *) MCFGPIO_PODR_LCDCTLL,
323		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDCTLL,
324		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDCTLL,
325		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDCTLL,
326	},
327};
328
329static int __init mcf_gpio_init(void)
330{
331	unsigned i = 0;
332	while (i < ARRAY_SIZE(mcf_gpio_chips))
333		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
334	return 0;
335}
336
337core_initcall(mcf_gpio_init);
338