Deleted Added
full compact
lpc_gpio.c (266152) lpc_gpio.c (278782)
1/*-
2 * Copyright (c) 2011 Jakub Wojciech Klama <jceel@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28/*
29 * GPIO on LPC32x0 consist of 4 ports:
30 * - Port0 with 8 input/output pins
31 * - Port1 with 24 input/output pins
32 * - Port2 with 13 input/output pins
33 * - Port3 with:
34 * - 26 input pins (GPI_00..GPI_09 + GPI_15..GPI_23 + GPI_25 + GPI_27..GPI_28)
35 * - 24 output pins (GPO_00..GPO_23)
36 * - 6 input/output pins (GPIO_00..GPIO_05)
37 *
38 * Pins are mapped to logical pin number as follows:
39 * [0..9] -> GPI_00..GPI_09 (port 3)
40 * [10..18] -> GPI_15..GPI_23 (port 3)
41 * [19] -> GPI_25 (port 3)
42 * [20..21] -> GPI_27..GPI_28 (port 3)
43 * [22..45] -> GPO_00..GPO_23 (port 3)
44 * [46..51] -> GPIO_00..GPIO_05 (port 3)
45 * [52..64] -> P2.0..P2.12 (port 2)
46 * [65..88] -> P1.0..P1.23 (port 1)
47 * [89..96] -> P0.0..P0.7 (port 0)
48 *
49 */
50
51
52#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2011 Jakub Wojciech Klama <jceel@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28/*
29 * GPIO on LPC32x0 consist of 4 ports:
30 * - Port0 with 8 input/output pins
31 * - Port1 with 24 input/output pins
32 * - Port2 with 13 input/output pins
33 * - Port3 with:
34 * - 26 input pins (GPI_00..GPI_09 + GPI_15..GPI_23 + GPI_25 + GPI_27..GPI_28)
35 * - 24 output pins (GPO_00..GPO_23)
36 * - 6 input/output pins (GPIO_00..GPIO_05)
37 *
38 * Pins are mapped to logical pin number as follows:
39 * [0..9] -> GPI_00..GPI_09 (port 3)
40 * [10..18] -> GPI_15..GPI_23 (port 3)
41 * [19] -> GPI_25 (port 3)
42 * [20..21] -> GPI_27..GPI_28 (port 3)
43 * [22..45] -> GPO_00..GPO_23 (port 3)
44 * [46..51] -> GPIO_00..GPIO_05 (port 3)
45 * [52..64] -> P2.0..P2.12 (port 2)
46 * [65..88] -> P1.0..P1.23 (port 1)
47 * [89..96] -> P0.0..P0.7 (port 0)
48 *
49 */
50
51
52#include <sys/cdefs.h>
53__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/lpc_gpio.c 266152 2014-05-15 16:11:06Z ian $");
53__FBSDID("$FreeBSD: stable/10/sys/arm/lpc/lpc_gpio.c 278782 2015-02-14 20:37:33Z loos $");
54
55#include <sys/param.h>
56#include <sys/systm.h>
57#include <sys/bio.h>
58#include <sys/bus.h>
59#include <sys/conf.h>
60#include <sys/endian.h>
61#include <sys/kernel.h>
62#include <sys/kthread.h>
63#include <sys/lock.h>
64#include <sys/malloc.h>
65#include <sys/module.h>
66#include <sys/mutex.h>
67#include <sys/queue.h>
68#include <sys/resource.h>
69#include <sys/rman.h>
70#include <sys/time.h>
71#include <sys/timetc.h>
72#include <sys/watchdog.h>
73#include <sys/gpio.h>
74
75#include <machine/bus.h>
76#include <machine/cpu.h>
77#include <machine/cpufunc.h>
78#include <machine/resource.h>
79#include <machine/intr.h>
80#include <machine/fdt.h>
81
82#include <dev/ofw/ofw_bus.h>
83#include <dev/ofw/ofw_bus_subr.h>
84
85#include <arm/lpc/lpcreg.h>
86#include <arm/lpc/lpcvar.h>
87
88#include "gpio_if.h"
89
90struct lpc_gpio_softc
91{
92 device_t lg_dev;
93 struct resource * lg_res;
94 bus_space_tag_t lg_bst;
95 bus_space_handle_t lg_bsh;
96};
97
98struct lpc_gpio_pinmap
99{
100 int lp_start_idx;
101 int lp_pin_count;
102 int lp_port;
103 int lp_start_bit;
104 int lp_flags;
105};
106
107static const struct lpc_gpio_pinmap lpc_gpio_pins[] = {
108 { 0, 10, 3, 0, GPIO_PIN_INPUT },
109 { 10, 9, 3, 15, GPIO_PIN_INPUT },
110 { 19, 1, 3, 25, GPIO_PIN_INPUT },
111 { 20, 2, 3, 27, GPIO_PIN_INPUT },
112 { 22, 24, 3, 0, GPIO_PIN_OUTPUT },
113 /*
114 * -1 below is to mark special case for Port3 GPIO pins, as they
115 * have other bits in Port 3 registers as inputs and as outputs
116 */
117 { 46, 6, 3, -1, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT },
118 { 52, 13, 2, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT },
119 { 65, 24, 1, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT },
120 { 89, 8, 0, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT },
121 { -1, -1, -1, -1, -1 },
122};
123
124#define LPC_GPIO_NPINS \
125 (LPC_GPIO_P0_COUNT + LPC_GPIO_P1_COUNT + \
126 LPC_GPIO_P2_COUNT + LPC_GPIO_P3_COUNT)
127
128#define LPC_GPIO_PIN_IDX(_map, _idx) \
129 (_idx - _map->lp_start_idx)
130
131#define LPC_GPIO_PIN_BIT(_map, _idx) \
132 (_map->lp_start_bit + LPC_GPIO_PIN_IDX(_map, _idx))
133
134static int lpc_gpio_probe(device_t);
135static int lpc_gpio_attach(device_t);
136static int lpc_gpio_detach(device_t);
137
138static int lpc_gpio_pin_max(device_t, int *);
139static int lpc_gpio_pin_getcaps(device_t, uint32_t, uint32_t *);
140static int lpc_gpio_pin_getflags(device_t, uint32_t, uint32_t *);
141static int lpc_gpio_pin_setflags(device_t, uint32_t, uint32_t);
142static int lpc_gpio_pin_getname(device_t, uint32_t, char *);
143static int lpc_gpio_pin_get(device_t, uint32_t, uint32_t *);
144static int lpc_gpio_pin_set(device_t, uint32_t, uint32_t);
145static int lpc_gpio_pin_toggle(device_t, uint32_t);
146
147static const struct lpc_gpio_pinmap *lpc_gpio_get_pinmap(int);
148
149static struct lpc_gpio_softc *lpc_gpio_sc = NULL;
150
151#define lpc_gpio_read_4(_sc, _reg) \
152 bus_space_read_4(_sc->lg_bst, _sc->lg_bsh, _reg)
153#define lpc_gpio_write_4(_sc, _reg, _val) \
154 bus_space_write_4(_sc->lg_bst, _sc->lg_bsh, _reg, _val)
155#define lpc_gpio_get_4(_sc, _test, _reg1, _reg2) \
156 lpc_gpio_read_4(_sc, ((_test) ? _reg1 : _reg2))
157#define lpc_gpio_set_4(_sc, _test, _reg1, _reg2, _val) \
158 lpc_gpio_write_4(_sc, ((_test) ? _reg1 : _reg2), _val)
159
160static int
161lpc_gpio_probe(device_t dev)
162{
163
164 if (!ofw_bus_status_okay(dev))
165 return (ENXIO);
166
167 if (!ofw_bus_is_compatible(dev, "lpc,gpio"))
168 return (ENXIO);
169
170 device_set_desc(dev, "LPC32x0 GPIO");
171 return (BUS_PROBE_DEFAULT);
172}
173
174static int
175lpc_gpio_attach(device_t dev)
176{
177 struct lpc_gpio_softc *sc = device_get_softc(dev);
178 int rid;
179
180 sc->lg_dev = dev;
181
182 rid = 0;
183 sc->lg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
184 RF_ACTIVE);
185 if (!sc->lg_res) {
186 device_printf(dev, "cannot allocate memory window\n");
187 return (ENXIO);
188 }
189
190 sc->lg_bst = rman_get_bustag(sc->lg_res);
191 sc->lg_bsh = rman_get_bushandle(sc->lg_res);
192
193 lpc_gpio_sc = sc;
194
54
55#include <sys/param.h>
56#include <sys/systm.h>
57#include <sys/bio.h>
58#include <sys/bus.h>
59#include <sys/conf.h>
60#include <sys/endian.h>
61#include <sys/kernel.h>
62#include <sys/kthread.h>
63#include <sys/lock.h>
64#include <sys/malloc.h>
65#include <sys/module.h>
66#include <sys/mutex.h>
67#include <sys/queue.h>
68#include <sys/resource.h>
69#include <sys/rman.h>
70#include <sys/time.h>
71#include <sys/timetc.h>
72#include <sys/watchdog.h>
73#include <sys/gpio.h>
74
75#include <machine/bus.h>
76#include <machine/cpu.h>
77#include <machine/cpufunc.h>
78#include <machine/resource.h>
79#include <machine/intr.h>
80#include <machine/fdt.h>
81
82#include <dev/ofw/ofw_bus.h>
83#include <dev/ofw/ofw_bus_subr.h>
84
85#include <arm/lpc/lpcreg.h>
86#include <arm/lpc/lpcvar.h>
87
88#include "gpio_if.h"
89
90struct lpc_gpio_softc
91{
92 device_t lg_dev;
93 struct resource * lg_res;
94 bus_space_tag_t lg_bst;
95 bus_space_handle_t lg_bsh;
96};
97
98struct lpc_gpio_pinmap
99{
100 int lp_start_idx;
101 int lp_pin_count;
102 int lp_port;
103 int lp_start_bit;
104 int lp_flags;
105};
106
107static const struct lpc_gpio_pinmap lpc_gpio_pins[] = {
108 { 0, 10, 3, 0, GPIO_PIN_INPUT },
109 { 10, 9, 3, 15, GPIO_PIN_INPUT },
110 { 19, 1, 3, 25, GPIO_PIN_INPUT },
111 { 20, 2, 3, 27, GPIO_PIN_INPUT },
112 { 22, 24, 3, 0, GPIO_PIN_OUTPUT },
113 /*
114 * -1 below is to mark special case for Port3 GPIO pins, as they
115 * have other bits in Port 3 registers as inputs and as outputs
116 */
117 { 46, 6, 3, -1, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT },
118 { 52, 13, 2, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT },
119 { 65, 24, 1, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT },
120 { 89, 8, 0, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT },
121 { -1, -1, -1, -1, -1 },
122};
123
124#define LPC_GPIO_NPINS \
125 (LPC_GPIO_P0_COUNT + LPC_GPIO_P1_COUNT + \
126 LPC_GPIO_P2_COUNT + LPC_GPIO_P3_COUNT)
127
128#define LPC_GPIO_PIN_IDX(_map, _idx) \
129 (_idx - _map->lp_start_idx)
130
131#define LPC_GPIO_PIN_BIT(_map, _idx) \
132 (_map->lp_start_bit + LPC_GPIO_PIN_IDX(_map, _idx))
133
134static int lpc_gpio_probe(device_t);
135static int lpc_gpio_attach(device_t);
136static int lpc_gpio_detach(device_t);
137
138static int lpc_gpio_pin_max(device_t, int *);
139static int lpc_gpio_pin_getcaps(device_t, uint32_t, uint32_t *);
140static int lpc_gpio_pin_getflags(device_t, uint32_t, uint32_t *);
141static int lpc_gpio_pin_setflags(device_t, uint32_t, uint32_t);
142static int lpc_gpio_pin_getname(device_t, uint32_t, char *);
143static int lpc_gpio_pin_get(device_t, uint32_t, uint32_t *);
144static int lpc_gpio_pin_set(device_t, uint32_t, uint32_t);
145static int lpc_gpio_pin_toggle(device_t, uint32_t);
146
147static const struct lpc_gpio_pinmap *lpc_gpio_get_pinmap(int);
148
149static struct lpc_gpio_softc *lpc_gpio_sc = NULL;
150
151#define lpc_gpio_read_4(_sc, _reg) \
152 bus_space_read_4(_sc->lg_bst, _sc->lg_bsh, _reg)
153#define lpc_gpio_write_4(_sc, _reg, _val) \
154 bus_space_write_4(_sc->lg_bst, _sc->lg_bsh, _reg, _val)
155#define lpc_gpio_get_4(_sc, _test, _reg1, _reg2) \
156 lpc_gpio_read_4(_sc, ((_test) ? _reg1 : _reg2))
157#define lpc_gpio_set_4(_sc, _test, _reg1, _reg2, _val) \
158 lpc_gpio_write_4(_sc, ((_test) ? _reg1 : _reg2), _val)
159
160static int
161lpc_gpio_probe(device_t dev)
162{
163
164 if (!ofw_bus_status_okay(dev))
165 return (ENXIO);
166
167 if (!ofw_bus_is_compatible(dev, "lpc,gpio"))
168 return (ENXIO);
169
170 device_set_desc(dev, "LPC32x0 GPIO");
171 return (BUS_PROBE_DEFAULT);
172}
173
174static int
175lpc_gpio_attach(device_t dev)
176{
177 struct lpc_gpio_softc *sc = device_get_softc(dev);
178 int rid;
179
180 sc->lg_dev = dev;
181
182 rid = 0;
183 sc->lg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
184 RF_ACTIVE);
185 if (!sc->lg_res) {
186 device_printf(dev, "cannot allocate memory window\n");
187 return (ENXIO);
188 }
189
190 sc->lg_bst = rman_get_bustag(sc->lg_res);
191 sc->lg_bsh = rman_get_bushandle(sc->lg_res);
192
193 lpc_gpio_sc = sc;
194
195 device_add_child(dev, "gpioc", device_get_unit(dev));
196 device_add_child(dev, "gpiobus", device_get_unit(dev));
195 device_add_child(dev, "gpioc", -1);
196 device_add_child(dev, "gpiobus", -1);
197
198 return (bus_generic_attach(dev));
199}
200
201static int
202lpc_gpio_detach(device_t dev)
203{
204 return (EBUSY);
205}
206
207static int
208lpc_gpio_pin_max(device_t dev, int *npins)
209{
210 *npins = LPC_GPIO_NPINS - 1;
211 return (0);
212}
213
214static int
215lpc_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
216{
217 const struct lpc_gpio_pinmap *map;
218
219 if (pin > LPC_GPIO_NPINS)
220 return (ENODEV);
221
222 map = lpc_gpio_get_pinmap(pin);
223
224 *caps = map->lp_flags;
225 return (0);
226}
227
228static int
229lpc_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
230{
231 struct lpc_gpio_softc *sc = device_get_softc(dev);
232 const struct lpc_gpio_pinmap *map;
233 uint32_t state;
234 int dir;
235
236 if (pin > LPC_GPIO_NPINS)
237 return (ENODEV);
238
239 map = lpc_gpio_get_pinmap(pin);
240
241 /* Check whether it's bidirectional pin */
242 if ((map->lp_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) !=
243 (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
244 *flags = map->lp_flags;
245 return (0);
246 }
247
248 switch (map->lp_port) {
249 case 0:
250 state = lpc_gpio_read_4(sc, LPC_GPIO_P0_DIR_STATE);
251 dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
252 break;
253 case 1:
254 state = lpc_gpio_read_4(sc, LPC_GPIO_P1_DIR_STATE);
255 dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
256 break;
257 case 2:
258 state = lpc_gpio_read_4(sc, LPC_GPIO_P2_DIR_STATE);
259 dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
260 break;
261 case 3:
262 state = lpc_gpio_read_4(sc, LPC_GPIO_P2_DIR_STATE);
263 dir = (state & (1 << (25 + LPC_GPIO_PIN_IDX(map, pin))));
264 break;
265 default:
266 panic("unknown GPIO port");
267 }
268
269 *flags = dir ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
270
271 return (0);
272}
273
274static int
275lpc_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
276{
277 struct lpc_gpio_softc *sc = device_get_softc(dev);
278 const struct lpc_gpio_pinmap *map;
279 uint32_t dir, state;
280
281 if (pin > LPC_GPIO_NPINS)
282 return (ENODEV);
283
284 map = lpc_gpio_get_pinmap(pin);
285
286 /* Check whether it's bidirectional pin */
287 if ((map->lp_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) !=
288 (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
289 return (ENOTSUP);
290
291 if (flags & GPIO_PIN_INPUT)
292 dir = 0;
293
294 if (flags & GPIO_PIN_OUTPUT)
295 dir = 1;
296
297 switch (map->lp_port) {
298 case 0:
299 state = (1 << LPC_GPIO_PIN_IDX(map, pin));
300 lpc_gpio_set_4(sc, dir, LPC_GPIO_P0_DIR_SET,
301 LPC_GPIO_P0_DIR_CLR, state);
302 break;
303 case 1:
304 state = (1 << LPC_GPIO_PIN_IDX(map, pin));
305 lpc_gpio_set_4(sc, dir, LPC_GPIO_P1_DIR_SET,
306 LPC_GPIO_P0_DIR_CLR, state);
307 break;
308 case 2:
309 state = (1 << LPC_GPIO_PIN_IDX(map, pin));
310 lpc_gpio_set_4(sc, dir, LPC_GPIO_P2_DIR_SET,
311 LPC_GPIO_P0_DIR_CLR, state);
312 break;
313 case 3:
314 state = (1 << (25 + (pin - map->lp_start_idx)));
315 lpc_gpio_set_4(sc, dir, LPC_GPIO_P2_DIR_SET,
316 LPC_GPIO_P0_DIR_CLR, state);
317 break;
318 }
319
320 return (0);
321}
322
323static int
324lpc_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
325{
326 const struct lpc_gpio_pinmap *map;
327 int idx;
328
329 map = lpc_gpio_get_pinmap(pin);
330 idx = LPC_GPIO_PIN_IDX(map, pin);
331
332 switch (map->lp_port) {
333 case 0:
334 case 1:
335 case 2:
336 snprintf(name, GPIOMAXNAME - 1, "P%d.%d", map->lp_port,
337 map->lp_start_bit + LPC_GPIO_PIN_IDX(map, pin));
338 break;
339 case 3:
340 if (map->lp_start_bit == -1) {
341 snprintf(name, GPIOMAXNAME - 1, "GPIO_%02d", idx);
342 break;
343 }
344
345 snprintf(name, GPIOMAXNAME - 1, "GP%c_%02d",
346 (map->lp_flags & GPIO_PIN_INPUT) ? 'I' : 'O',
347 map->lp_start_bit + idx);
348 break;
349 }
350
351 return (0);
352}
353
354static int
355lpc_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *value)
356{
357 struct lpc_gpio_softc *sc = device_get_softc(dev);
358 const struct lpc_gpio_pinmap *map;
359 uint32_t state, flags;
360 int dir;
361
362 map = lpc_gpio_get_pinmap(pin);
363
364 if (lpc_gpio_pin_getflags(dev, pin, &flags))
365 return (ENXIO);
366
367 if (flags & GPIO_PIN_OUTPUT)
368 dir = 1;
369
370 if (flags & GPIO_PIN_INPUT)
371 dir = 0;
372
373 switch (map->lp_port) {
374 case 0:
375 state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P0_OUTP_STATE,
376 LPC_GPIO_P0_INP_STATE);
377 *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
378 case 1:
379 state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P1_OUTP_STATE,
380 LPC_GPIO_P1_INP_STATE);
381 *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
382 case 2:
383 state = lpc_gpio_read_4(sc, LPC_GPIO_P2_INP_STATE);
384 *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
385 case 3:
386 state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P3_OUTP_STATE,
387 LPC_GPIO_P3_INP_STATE);
388 if (map->lp_start_bit == -1) {
389 if (dir)
390 *value = !!(state & (1 << (25 +
391 LPC_GPIO_PIN_IDX(map, pin))));
392 else
393 *value = !!(state & (1 << (10 +
394 LPC_GPIO_PIN_IDX(map, pin))));
395 }
396
397 *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
398 }
399
400 return (0);
401}
402
403static int
404lpc_gpio_pin_set(device_t dev, uint32_t pin, uint32_t value)
405{
406 struct lpc_gpio_softc *sc = device_get_softc(dev);
407 const struct lpc_gpio_pinmap *map;
408 uint32_t state, flags;
409
410 map = lpc_gpio_get_pinmap(pin);
411
412 if (lpc_gpio_pin_getflags(dev, pin, &flags))
413 return (ENXIO);
414
415 if ((flags & GPIO_PIN_OUTPUT) == 0)
416 return (EINVAL);
417
418 state = (1 << LPC_GPIO_PIN_BIT(map, pin));
419
420 switch (map->lp_port) {
421 case 0:
422 lpc_gpio_set_4(sc, value, LPC_GPIO_P0_OUTP_SET,
423 LPC_GPIO_P0_OUTP_CLR, state);
424 break;
425 case 1:
426 lpc_gpio_set_4(sc, value, LPC_GPIO_P1_OUTP_SET,
427 LPC_GPIO_P1_OUTP_CLR, state);
428 break;
429 case 2:
430 lpc_gpio_set_4(sc, value, LPC_GPIO_P2_OUTP_SET,
431 LPC_GPIO_P2_OUTP_CLR, state);
432 break;
433 case 3:
434 if (map->lp_start_bit == -1)
435 state = (1 << (25 + LPC_GPIO_PIN_IDX(map, pin)));
436
437 lpc_gpio_set_4(sc, value, LPC_GPIO_P3_OUTP_SET,
438 LPC_GPIO_P3_OUTP_CLR, state);
439 break;
440 }
441
442 return (0);
443}
444
445static int
446lpc_gpio_pin_toggle(device_t dev, uint32_t pin)
447{
448 const struct lpc_gpio_pinmap *map;
449 uint32_t flags;
450
451 map = lpc_gpio_get_pinmap(pin);
452
453 if (lpc_gpio_pin_getflags(dev, pin, &flags))
454 return (ENXIO);
455
456 if ((flags & GPIO_PIN_OUTPUT) == 0)
457 return (EINVAL);
458
459 panic("not implemented yet");
460
461 return (0);
462
463}
464
465static const struct lpc_gpio_pinmap *
466lpc_gpio_get_pinmap(int pin)
467{
468 const struct lpc_gpio_pinmap *map;
469
470 for (map = &lpc_gpio_pins[0]; map->lp_start_idx != -1; map++) {
471 if (pin >= map->lp_start_idx &&
472 pin < map->lp_start_idx + map->lp_pin_count)
473 return map;
474 }
475
476 panic("pin number %d out of range", pin);
477}
478
479int
480lpc_gpio_set_flags(device_t dev, int pin, int flags)
481{
482 if (lpc_gpio_sc == NULL)
483 return (ENXIO);
484
485 return lpc_gpio_pin_setflags(lpc_gpio_sc->lg_dev, pin, flags);
486}
487
488int
489lpc_gpio_set_state(device_t dev, int pin, int state)
490{
491 if (lpc_gpio_sc == NULL)
492 return (ENXIO);
493
494 return lpc_gpio_pin_set(lpc_gpio_sc->lg_dev, pin, state);
495}
496
497int
498lpc_gpio_get_state(device_t dev, int pin, int *state)
499{
500 if (lpc_gpio_sc == NULL)
501 return (ENXIO);
502
503 return lpc_gpio_pin_get(lpc_gpio_sc->lg_dev, pin, state);
504}
505
506void
507platform_gpio_init()
508{
509 bus_space_tag_t bst;
510 bus_space_handle_t bsh;
511
512 bst = fdtbus_bs_tag;
513
514 /* Preset SPI devices CS pins to one */
515 bus_space_map(bst, LPC_GPIO_PHYS_BASE, LPC_GPIO_SIZE, 0, &bsh);
516 bus_space_write_4(bst, bsh, LPC_GPIO_P3_OUTP_SET,
517 1 << (SSD1289_CS_PIN - LPC_GPIO_GPO_00(0)) |
518 1 << (SSD1289_DC_PIN - LPC_GPIO_GPO_00(0)) |
519 1 << (ADS7846_CS_PIN - LPC_GPIO_GPO_00(0)));
520 bus_space_unmap(bst, bsh, LPC_GPIO_SIZE);
521}
522
523static device_method_t lpc_gpio_methods[] = {
524 /* Device interface */
525 DEVMETHOD(device_probe, lpc_gpio_probe),
526 DEVMETHOD(device_attach, lpc_gpio_attach),
527 DEVMETHOD(device_detach, lpc_gpio_detach),
528
529 /* GPIO interface */
530 DEVMETHOD(gpio_pin_max, lpc_gpio_pin_max),
531 DEVMETHOD(gpio_pin_getcaps, lpc_gpio_pin_getcaps),
532 DEVMETHOD(gpio_pin_getflags, lpc_gpio_pin_getflags),
533 DEVMETHOD(gpio_pin_setflags, lpc_gpio_pin_setflags),
534 DEVMETHOD(gpio_pin_getname, lpc_gpio_pin_getname),
535 DEVMETHOD(gpio_pin_set, lpc_gpio_pin_set),
536 DEVMETHOD(gpio_pin_get, lpc_gpio_pin_get),
537 DEVMETHOD(gpio_pin_toggle, lpc_gpio_pin_toggle),
538
539 { 0, 0 }
540};
541
542static devclass_t lpc_gpio_devclass;
543
544static driver_t lpc_gpio_driver = {
545 "lpcgpio",
546 lpc_gpio_methods,
547 sizeof(struct lpc_gpio_softc),
548};
549
550extern devclass_t gpiobus_devclass, gpioc_devclass;
551extern driver_t gpiobus_driver, gpioc_driver;
552
553DRIVER_MODULE(lpcgpio, simplebus, lpc_gpio_driver, lpc_gpio_devclass, 0, 0);
554DRIVER_MODULE(gpiobus, lpcgpio, gpiobus_driver, gpiobus_devclass, 0, 0);
555DRIVER_MODULE(gpioc, lpcgpio, gpioc_driver, gpioc_devclass, 0, 0);
556MODULE_VERSION(lpcgpio, 1);
197
198 return (bus_generic_attach(dev));
199}
200
201static int
202lpc_gpio_detach(device_t dev)
203{
204 return (EBUSY);
205}
206
207static int
208lpc_gpio_pin_max(device_t dev, int *npins)
209{
210 *npins = LPC_GPIO_NPINS - 1;
211 return (0);
212}
213
214static int
215lpc_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
216{
217 const struct lpc_gpio_pinmap *map;
218
219 if (pin > LPC_GPIO_NPINS)
220 return (ENODEV);
221
222 map = lpc_gpio_get_pinmap(pin);
223
224 *caps = map->lp_flags;
225 return (0);
226}
227
228static int
229lpc_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
230{
231 struct lpc_gpio_softc *sc = device_get_softc(dev);
232 const struct lpc_gpio_pinmap *map;
233 uint32_t state;
234 int dir;
235
236 if (pin > LPC_GPIO_NPINS)
237 return (ENODEV);
238
239 map = lpc_gpio_get_pinmap(pin);
240
241 /* Check whether it's bidirectional pin */
242 if ((map->lp_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) !=
243 (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
244 *flags = map->lp_flags;
245 return (0);
246 }
247
248 switch (map->lp_port) {
249 case 0:
250 state = lpc_gpio_read_4(sc, LPC_GPIO_P0_DIR_STATE);
251 dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
252 break;
253 case 1:
254 state = lpc_gpio_read_4(sc, LPC_GPIO_P1_DIR_STATE);
255 dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
256 break;
257 case 2:
258 state = lpc_gpio_read_4(sc, LPC_GPIO_P2_DIR_STATE);
259 dir = (state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
260 break;
261 case 3:
262 state = lpc_gpio_read_4(sc, LPC_GPIO_P2_DIR_STATE);
263 dir = (state & (1 << (25 + LPC_GPIO_PIN_IDX(map, pin))));
264 break;
265 default:
266 panic("unknown GPIO port");
267 }
268
269 *flags = dir ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
270
271 return (0);
272}
273
274static int
275lpc_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
276{
277 struct lpc_gpio_softc *sc = device_get_softc(dev);
278 const struct lpc_gpio_pinmap *map;
279 uint32_t dir, state;
280
281 if (pin > LPC_GPIO_NPINS)
282 return (ENODEV);
283
284 map = lpc_gpio_get_pinmap(pin);
285
286 /* Check whether it's bidirectional pin */
287 if ((map->lp_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) !=
288 (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
289 return (ENOTSUP);
290
291 if (flags & GPIO_PIN_INPUT)
292 dir = 0;
293
294 if (flags & GPIO_PIN_OUTPUT)
295 dir = 1;
296
297 switch (map->lp_port) {
298 case 0:
299 state = (1 << LPC_GPIO_PIN_IDX(map, pin));
300 lpc_gpio_set_4(sc, dir, LPC_GPIO_P0_DIR_SET,
301 LPC_GPIO_P0_DIR_CLR, state);
302 break;
303 case 1:
304 state = (1 << LPC_GPIO_PIN_IDX(map, pin));
305 lpc_gpio_set_4(sc, dir, LPC_GPIO_P1_DIR_SET,
306 LPC_GPIO_P0_DIR_CLR, state);
307 break;
308 case 2:
309 state = (1 << LPC_GPIO_PIN_IDX(map, pin));
310 lpc_gpio_set_4(sc, dir, LPC_GPIO_P2_DIR_SET,
311 LPC_GPIO_P0_DIR_CLR, state);
312 break;
313 case 3:
314 state = (1 << (25 + (pin - map->lp_start_idx)));
315 lpc_gpio_set_4(sc, dir, LPC_GPIO_P2_DIR_SET,
316 LPC_GPIO_P0_DIR_CLR, state);
317 break;
318 }
319
320 return (0);
321}
322
323static int
324lpc_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
325{
326 const struct lpc_gpio_pinmap *map;
327 int idx;
328
329 map = lpc_gpio_get_pinmap(pin);
330 idx = LPC_GPIO_PIN_IDX(map, pin);
331
332 switch (map->lp_port) {
333 case 0:
334 case 1:
335 case 2:
336 snprintf(name, GPIOMAXNAME - 1, "P%d.%d", map->lp_port,
337 map->lp_start_bit + LPC_GPIO_PIN_IDX(map, pin));
338 break;
339 case 3:
340 if (map->lp_start_bit == -1) {
341 snprintf(name, GPIOMAXNAME - 1, "GPIO_%02d", idx);
342 break;
343 }
344
345 snprintf(name, GPIOMAXNAME - 1, "GP%c_%02d",
346 (map->lp_flags & GPIO_PIN_INPUT) ? 'I' : 'O',
347 map->lp_start_bit + idx);
348 break;
349 }
350
351 return (0);
352}
353
354static int
355lpc_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *value)
356{
357 struct lpc_gpio_softc *sc = device_get_softc(dev);
358 const struct lpc_gpio_pinmap *map;
359 uint32_t state, flags;
360 int dir;
361
362 map = lpc_gpio_get_pinmap(pin);
363
364 if (lpc_gpio_pin_getflags(dev, pin, &flags))
365 return (ENXIO);
366
367 if (flags & GPIO_PIN_OUTPUT)
368 dir = 1;
369
370 if (flags & GPIO_PIN_INPUT)
371 dir = 0;
372
373 switch (map->lp_port) {
374 case 0:
375 state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P0_OUTP_STATE,
376 LPC_GPIO_P0_INP_STATE);
377 *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
378 case 1:
379 state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P1_OUTP_STATE,
380 LPC_GPIO_P1_INP_STATE);
381 *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
382 case 2:
383 state = lpc_gpio_read_4(sc, LPC_GPIO_P2_INP_STATE);
384 *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
385 case 3:
386 state = lpc_gpio_get_4(sc, dir, LPC_GPIO_P3_OUTP_STATE,
387 LPC_GPIO_P3_INP_STATE);
388 if (map->lp_start_bit == -1) {
389 if (dir)
390 *value = !!(state & (1 << (25 +
391 LPC_GPIO_PIN_IDX(map, pin))));
392 else
393 *value = !!(state & (1 << (10 +
394 LPC_GPIO_PIN_IDX(map, pin))));
395 }
396
397 *value = !!(state & (1 << LPC_GPIO_PIN_BIT(map, pin)));
398 }
399
400 return (0);
401}
402
403static int
404lpc_gpio_pin_set(device_t dev, uint32_t pin, uint32_t value)
405{
406 struct lpc_gpio_softc *sc = device_get_softc(dev);
407 const struct lpc_gpio_pinmap *map;
408 uint32_t state, flags;
409
410 map = lpc_gpio_get_pinmap(pin);
411
412 if (lpc_gpio_pin_getflags(dev, pin, &flags))
413 return (ENXIO);
414
415 if ((flags & GPIO_PIN_OUTPUT) == 0)
416 return (EINVAL);
417
418 state = (1 << LPC_GPIO_PIN_BIT(map, pin));
419
420 switch (map->lp_port) {
421 case 0:
422 lpc_gpio_set_4(sc, value, LPC_GPIO_P0_OUTP_SET,
423 LPC_GPIO_P0_OUTP_CLR, state);
424 break;
425 case 1:
426 lpc_gpio_set_4(sc, value, LPC_GPIO_P1_OUTP_SET,
427 LPC_GPIO_P1_OUTP_CLR, state);
428 break;
429 case 2:
430 lpc_gpio_set_4(sc, value, LPC_GPIO_P2_OUTP_SET,
431 LPC_GPIO_P2_OUTP_CLR, state);
432 break;
433 case 3:
434 if (map->lp_start_bit == -1)
435 state = (1 << (25 + LPC_GPIO_PIN_IDX(map, pin)));
436
437 lpc_gpio_set_4(sc, value, LPC_GPIO_P3_OUTP_SET,
438 LPC_GPIO_P3_OUTP_CLR, state);
439 break;
440 }
441
442 return (0);
443}
444
445static int
446lpc_gpio_pin_toggle(device_t dev, uint32_t pin)
447{
448 const struct lpc_gpio_pinmap *map;
449 uint32_t flags;
450
451 map = lpc_gpio_get_pinmap(pin);
452
453 if (lpc_gpio_pin_getflags(dev, pin, &flags))
454 return (ENXIO);
455
456 if ((flags & GPIO_PIN_OUTPUT) == 0)
457 return (EINVAL);
458
459 panic("not implemented yet");
460
461 return (0);
462
463}
464
465static const struct lpc_gpio_pinmap *
466lpc_gpio_get_pinmap(int pin)
467{
468 const struct lpc_gpio_pinmap *map;
469
470 for (map = &lpc_gpio_pins[0]; map->lp_start_idx != -1; map++) {
471 if (pin >= map->lp_start_idx &&
472 pin < map->lp_start_idx + map->lp_pin_count)
473 return map;
474 }
475
476 panic("pin number %d out of range", pin);
477}
478
479int
480lpc_gpio_set_flags(device_t dev, int pin, int flags)
481{
482 if (lpc_gpio_sc == NULL)
483 return (ENXIO);
484
485 return lpc_gpio_pin_setflags(lpc_gpio_sc->lg_dev, pin, flags);
486}
487
488int
489lpc_gpio_set_state(device_t dev, int pin, int state)
490{
491 if (lpc_gpio_sc == NULL)
492 return (ENXIO);
493
494 return lpc_gpio_pin_set(lpc_gpio_sc->lg_dev, pin, state);
495}
496
497int
498lpc_gpio_get_state(device_t dev, int pin, int *state)
499{
500 if (lpc_gpio_sc == NULL)
501 return (ENXIO);
502
503 return lpc_gpio_pin_get(lpc_gpio_sc->lg_dev, pin, state);
504}
505
506void
507platform_gpio_init()
508{
509 bus_space_tag_t bst;
510 bus_space_handle_t bsh;
511
512 bst = fdtbus_bs_tag;
513
514 /* Preset SPI devices CS pins to one */
515 bus_space_map(bst, LPC_GPIO_PHYS_BASE, LPC_GPIO_SIZE, 0, &bsh);
516 bus_space_write_4(bst, bsh, LPC_GPIO_P3_OUTP_SET,
517 1 << (SSD1289_CS_PIN - LPC_GPIO_GPO_00(0)) |
518 1 << (SSD1289_DC_PIN - LPC_GPIO_GPO_00(0)) |
519 1 << (ADS7846_CS_PIN - LPC_GPIO_GPO_00(0)));
520 bus_space_unmap(bst, bsh, LPC_GPIO_SIZE);
521}
522
523static device_method_t lpc_gpio_methods[] = {
524 /* Device interface */
525 DEVMETHOD(device_probe, lpc_gpio_probe),
526 DEVMETHOD(device_attach, lpc_gpio_attach),
527 DEVMETHOD(device_detach, lpc_gpio_detach),
528
529 /* GPIO interface */
530 DEVMETHOD(gpio_pin_max, lpc_gpio_pin_max),
531 DEVMETHOD(gpio_pin_getcaps, lpc_gpio_pin_getcaps),
532 DEVMETHOD(gpio_pin_getflags, lpc_gpio_pin_getflags),
533 DEVMETHOD(gpio_pin_setflags, lpc_gpio_pin_setflags),
534 DEVMETHOD(gpio_pin_getname, lpc_gpio_pin_getname),
535 DEVMETHOD(gpio_pin_set, lpc_gpio_pin_set),
536 DEVMETHOD(gpio_pin_get, lpc_gpio_pin_get),
537 DEVMETHOD(gpio_pin_toggle, lpc_gpio_pin_toggle),
538
539 { 0, 0 }
540};
541
542static devclass_t lpc_gpio_devclass;
543
544static driver_t lpc_gpio_driver = {
545 "lpcgpio",
546 lpc_gpio_methods,
547 sizeof(struct lpc_gpio_softc),
548};
549
550extern devclass_t gpiobus_devclass, gpioc_devclass;
551extern driver_t gpiobus_driver, gpioc_driver;
552
553DRIVER_MODULE(lpcgpio, simplebus, lpc_gpio_driver, lpc_gpio_devclass, 0, 0);
554DRIVER_MODULE(gpiobus, lpcgpio, gpiobus_driver, gpiobus_devclass, 0, 0);
555DRIVER_MODULE(gpioc, lpcgpio, gpioc_driver, gpioc_devclass, 0, 0);
556MODULE_VERSION(lpcgpio, 1);