]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/arm/xscale/ixp425/cambria_gpio.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / arm / xscale / ixp425 / cambria_gpio.c
1 /*-
2  * Copyright (c) 2010, Andrew Thompson <thompsa@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 unmodified, this list of conditions, and the following
10  *    disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 /*
29  * GPIO driver for Gateworks Cambria
30  *
31  * Note:
32  * The Cambria PLD does not set the i2c ack bit after each write, if we used the
33  * regular iicbus interface it would abort the xfer after the address byte
34  * times out and not write our latch. To get around this we grab the iicbus and
35  * then do our own bit banging. This is a comprimise to changing all the iicbb
36  * device methods to allow a flag to be passed down and is similir to how Linux
37  * does it.
38  *
39  */
40
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/bus.h>
47
48 #include <sys/kernel.h>
49 #include <sys/module.h>
50 #include <sys/rman.h>
51 #include <sys/lock.h>
52 #include <sys/mutex.h>
53 #include <sys/gpio.h>
54
55 #include <arm/xscale/ixp425/ixp425reg.h>
56 #include <arm/xscale/ixp425/ixp425var.h>
57 #include <arm/xscale/ixp425/ixdp425reg.h>
58
59 #include <dev/iicbus/iiconf.h>
60 #include <dev/iicbus/iicbus.h>
61
62 #include "iicbb_if.h"
63 #include "gpio_if.h"
64
65 #define IIC_M_WR        0       /* write operation */
66 #define PLD_ADDR        0xac    /* slave address */
67
68 #define I2C_DELAY       10
69
70 #define GPIO_CONF_CLR(sc, reg, mask)    \
71         GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, reg) &~ (mask))
72 #define GPIO_CONF_SET(sc, reg, mask)    \
73         GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, reg) | (mask))
74
75 #define GPIO_LOCK(_sc)          mtx_lock(&(_sc)->sc_mtx)
76 #define GPIO_UNLOCK(_sc)        mtx_unlock(&(_sc)->sc_mtx)
77 #define GPIO_LOCK_ASSERT(_sc)   mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
78
79 #define GPIO_PINS               5
80 struct cambria_gpio_softc {
81         device_t                sc_dev;
82         bus_space_tag_t         sc_iot;
83         bus_space_handle_t      sc_gpio_ioh;
84         struct mtx              sc_mtx;
85         struct gpio_pin         sc_pins[GPIO_PINS];
86         uint8_t                 sc_latch;
87         uint8_t                 sc_val;
88 };
89
90 struct cambria_gpio_pin {
91         const char *name;
92         int pin;
93         int flags;
94 };
95
96 extern struct ixp425_softc *ixp425_softc;
97
98 static struct cambria_gpio_pin cambria_gpio_pins[GPIO_PINS] = {
99         { "PLD0", 0, GPIO_PIN_OUTPUT },
100         { "PLD1", 1, GPIO_PIN_OUTPUT },
101         { "PLD2", 2, GPIO_PIN_OUTPUT },
102         { "PLD3", 3, GPIO_PIN_OUTPUT },
103         { "PLD4", 4, GPIO_PIN_OUTPUT },
104 };
105
106 /*
107  * Helpers
108  */
109 static int cambria_gpio_read(struct cambria_gpio_softc *, uint32_t, unsigned int *);
110 static int cambria_gpio_write(struct cambria_gpio_softc *);
111
112 /*
113  * Driver stuff
114  */
115 static int cambria_gpio_probe(device_t dev);
116 static int cambria_gpio_attach(device_t dev);
117 static int cambria_gpio_detach(device_t dev);
118
119 /*
120  * GPIO interface
121  */
122 static int cambria_gpio_pin_max(device_t dev, int *maxpin);
123 static int cambria_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
124 static int cambria_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t
125     *flags);
126 static int cambria_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
127 static int cambria_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
128 static int cambria_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
129 static int cambria_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
130 static int cambria_gpio_pin_toggle(device_t dev, uint32_t pin);
131
132 static int
133 i2c_getsda(struct cambria_gpio_softc *sc)
134 {
135         uint32_t reg;
136
137         IXP4XX_GPIO_LOCK();
138         GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
139
140         reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR);
141         IXP4XX_GPIO_UNLOCK();
142         return (reg & GPIO_I2C_SDA_BIT);
143 }
144
145 static void
146 i2c_setsda(struct cambria_gpio_softc *sc, int val)
147 {
148
149         IXP4XX_GPIO_LOCK();
150         GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SDA_BIT);
151         if (val)
152                 GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
153         else
154                 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
155         IXP4XX_GPIO_UNLOCK();
156         DELAY(I2C_DELAY);
157 }
158
159 static void
160 i2c_setscl(struct cambria_gpio_softc *sc, int val)
161 {
162
163         IXP4XX_GPIO_LOCK();
164         GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SCL_BIT);
165         if (val)
166                 GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
167         else
168                 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
169         IXP4XX_GPIO_UNLOCK();
170         DELAY(I2C_DELAY);
171 }
172
173 static void
174 i2c_sendstart(struct cambria_gpio_softc *sc)
175 {
176         i2c_setsda(sc, 1);
177         i2c_setscl(sc, 1);
178         i2c_setsda(sc, 0);
179         i2c_setscl(sc, 0);
180 }
181
182 static void
183 i2c_sendstop(struct cambria_gpio_softc *sc)
184 {
185         i2c_setscl(sc, 1);
186         i2c_setsda(sc, 1);
187         i2c_setscl(sc, 0);
188         i2c_setsda(sc, 0);
189 }
190
191 static void
192 i2c_sendbyte(struct cambria_gpio_softc *sc, u_char data)
193 {
194         int i;
195
196         for (i=7; i>=0; i--) {
197                 i2c_setsda(sc, data & (1<<i));
198                 i2c_setscl(sc, 1);
199                 i2c_setscl(sc, 0);
200         }
201         i2c_setscl(sc, 1);
202         i2c_getsda(sc);
203         i2c_setscl(sc, 0);
204 }
205
206 static u_char
207 i2c_readbyte(struct cambria_gpio_softc *sc)
208 {
209         int i;
210         unsigned char data=0;
211
212         for (i=7; i>=0; i--)
213         {
214                 i2c_setscl(sc, 1);
215                 if (i2c_getsda(sc))
216                         data |= (1<<i);
217                 i2c_setscl(sc, 0);
218         }
219         return data;
220 }
221
222 static int
223 cambria_gpio_read(struct cambria_gpio_softc *sc, uint32_t pin, unsigned int *val)
224 {
225         device_t dev = sc->sc_dev;
226         int error;
227
228         error = iicbus_request_bus(device_get_parent(dev), dev,
229             IIC_DONTWAIT);
230         if (error)
231                 return (error);
232
233         i2c_sendstart(sc);
234         i2c_sendbyte(sc, PLD_ADDR | LSB);
235         *val = (i2c_readbyte(sc) & (1 << pin)) != 0;
236         i2c_sendstop(sc);
237
238         iicbus_release_bus(device_get_parent(dev), dev);
239
240         return (0);
241 }
242
243 static int
244 cambria_gpio_write(struct cambria_gpio_softc *sc)
245 {
246         device_t dev = sc->sc_dev;
247         int error;
248
249         error = iicbus_request_bus(device_get_parent(dev), dev,
250             IIC_DONTWAIT);
251         if (error)
252                 return (error);
253
254         i2c_sendstart(sc);
255         i2c_sendbyte(sc, PLD_ADDR & ~LSB);
256         i2c_sendbyte(sc, sc->sc_latch);
257         i2c_sendstop(sc);
258
259         iicbus_release_bus(device_get_parent(dev), dev);
260
261         return (0);
262 }
263
264 static int
265 cambria_gpio_pin_max(device_t dev, int *maxpin)
266 {
267
268         *maxpin = GPIO_PINS - 1;
269         return (0);
270 }
271
272 static int
273 cambria_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
274 {
275         struct cambria_gpio_softc *sc = device_get_softc(dev);
276
277         if (pin >= GPIO_PINS)
278                 return (EINVAL);
279
280         *caps = sc->sc_pins[pin].gp_caps;
281         return (0);
282 }
283
284 static int
285 cambria_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
286 {
287         struct cambria_gpio_softc *sc = device_get_softc(dev);
288
289         if (pin >= GPIO_PINS)
290                 return (EINVAL);
291
292         *flags = sc->sc_pins[pin].gp_flags;
293         return (0);
294 }
295
296 static int
297 cambria_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
298 {
299         struct cambria_gpio_softc *sc = device_get_softc(dev);
300
301         if (pin >= GPIO_PINS)
302                 return (EINVAL);
303
304         memcpy(name, sc->sc_pins[pin].gp_name, GPIOMAXNAME);
305         return (0);
306 }
307
308 static int
309 cambria_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
310 {
311         struct cambria_gpio_softc *sc = device_get_softc(dev);
312         int error;
313         uint8_t mask;
314
315         mask = 1 << pin;
316
317         if (pin >= GPIO_PINS)
318                 return (EINVAL);
319
320         /* Check for unwanted flags. */
321         if ((flags & sc->sc_pins[pin].gp_caps) != flags)
322                 return (EINVAL);
323
324         /* Can't mix input/output together */
325         if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) ==
326             (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT))
327                 return (EINVAL);
328
329         GPIO_LOCK(sc);
330         sc->sc_pins[pin].gp_flags = flags;
331
332         /*
333          * Writing a logical one sets the signal high and writing a logical
334          * zero sets the signal low. To configure a digital I/O signal as an
335          * input, a logical one must first be written to the data bit to
336          * three-state the associated output.
337          */
338         if (flags & GPIO_PIN_INPUT || sc->sc_val & mask)
339                 sc->sc_latch |= mask; /* input or output & high */
340         else
341                 sc->sc_latch &= ~mask;
342         error = cambria_gpio_write(sc);
343         GPIO_UNLOCK(sc);
344
345         return (error);
346 }
347
348 static int
349 cambria_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
350 {
351         struct cambria_gpio_softc *sc = device_get_softc(dev);
352         int error;
353         uint8_t mask;
354
355         mask = 1 << pin;
356
357         if (pin >= GPIO_PINS)
358                 return (EINVAL);
359         GPIO_LOCK(sc);
360         if (value)
361                 sc->sc_val |= mask;
362         else
363                 sc->sc_val &= ~mask;
364
365         if (sc->sc_pins[pin].gp_flags != GPIO_PIN_OUTPUT) {
366                 /* just save, altering the latch will disable input */
367                 GPIO_UNLOCK(sc);
368                 return (0);
369         }
370
371         if (value)
372                 sc->sc_latch |= mask;
373         else
374                 sc->sc_latch &= ~mask;
375         error = cambria_gpio_write(sc);
376         GPIO_UNLOCK(sc);
377
378         return (error);
379 }
380
381 static int
382 cambria_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
383 {
384         struct cambria_gpio_softc *sc = device_get_softc(dev);
385         int error = 0;
386
387         if (pin >= GPIO_PINS)
388                 return (EINVAL);
389
390         GPIO_LOCK(sc);
391         if (sc->sc_pins[pin].gp_flags == GPIO_PIN_OUTPUT)
392                 *val = (sc->sc_latch & (1 << pin)) ? 1 : 0;
393         else
394                 error = cambria_gpio_read(sc, pin, val);
395         GPIO_UNLOCK(sc);
396
397         return (error);
398 }
399
400 static int
401 cambria_gpio_pin_toggle(device_t dev, uint32_t pin)
402 {
403         struct cambria_gpio_softc *sc = device_get_softc(dev);
404         int error = 0;
405
406         if (pin >= GPIO_PINS)
407                 return (EINVAL);
408
409         GPIO_LOCK(sc);
410         sc->sc_val ^= (1 << pin);
411         if (sc->sc_pins[pin].gp_flags == GPIO_PIN_OUTPUT) {
412                 sc->sc_latch ^= (1 << pin);
413                 error = cambria_gpio_write(sc);
414         }
415         GPIO_UNLOCK(sc);
416
417         return (error);
418 }
419
420 static int
421 cambria_gpio_probe(device_t dev)
422 {
423
424         device_set_desc(dev, "Gateworks Cambria GPIO driver");
425         return (0);
426 }
427
428 static int
429 cambria_gpio_attach(device_t dev)
430 {
431         struct cambria_gpio_softc *sc = device_get_softc(dev);
432         int pin;
433
434         sc->sc_dev = dev;
435         sc->sc_iot = ixp425_softc->sc_iot;
436         sc->sc_gpio_ioh = ixp425_softc->sc_gpio_ioh;
437
438         mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
439
440         for (pin = 0; pin < GPIO_PINS; pin++) {
441                 struct cambria_gpio_pin *p = &cambria_gpio_pins[pin];
442
443                 strncpy(sc->sc_pins[pin].gp_name, p->name, GPIOMAXNAME);
444                 sc->sc_pins[pin].gp_pin = pin;
445                 sc->sc_pins[pin].gp_caps = GPIO_PIN_INPUT|GPIO_PIN_OUTPUT;
446                 sc->sc_pins[pin].gp_flags = 0;
447                 cambria_gpio_pin_setflags(dev, pin, p->flags);
448         }
449
450         device_add_child(dev, "gpioc", device_get_unit(dev));
451         device_add_child(dev, "gpiobus", device_get_unit(dev));
452         return (bus_generic_attach(dev));
453 }
454
455 static int
456 cambria_gpio_detach(device_t dev)
457 {
458         struct cambria_gpio_softc *sc = device_get_softc(dev);
459
460         KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
461
462         bus_generic_detach(dev);
463
464         mtx_destroy(&sc->sc_mtx);
465
466         return(0);
467 }
468
469 static device_method_t cambria_gpio_methods[] = {
470         DEVMETHOD(device_probe, cambria_gpio_probe),
471         DEVMETHOD(device_attach, cambria_gpio_attach),
472         DEVMETHOD(device_detach, cambria_gpio_detach),
473
474         /* GPIO protocol */
475         DEVMETHOD(gpio_pin_max, cambria_gpio_pin_max),
476         DEVMETHOD(gpio_pin_getname, cambria_gpio_pin_getname),
477         DEVMETHOD(gpio_pin_getflags, cambria_gpio_pin_getflags),
478         DEVMETHOD(gpio_pin_getcaps, cambria_gpio_pin_getcaps),
479         DEVMETHOD(gpio_pin_setflags, cambria_gpio_pin_setflags),
480         DEVMETHOD(gpio_pin_get, cambria_gpio_pin_get),
481         DEVMETHOD(gpio_pin_set, cambria_gpio_pin_set),
482         DEVMETHOD(gpio_pin_toggle, cambria_gpio_pin_toggle),
483         {0, 0},
484 };
485
486 static driver_t cambria_gpio_driver = {
487         "gpio_cambria",
488         cambria_gpio_methods,
489         sizeof(struct cambria_gpio_softc),
490 };
491 static devclass_t cambria_gpio_devclass;
492 extern devclass_t gpiobus_devclass, gpioc_devclass;
493 extern driver_t gpiobus_driver, gpioc_driver;
494
495 DRIVER_MODULE(gpio_cambria, iicbus, cambria_gpio_driver, cambria_gpio_devclass, 0, 0);
496 DRIVER_MODULE(gpiobus, gpio_cambria, gpiobus_driver, gpiobus_devclass, 0, 0);
497 DRIVER_MODULE(gpioc, gpio_cambria, gpioc_driver, gpioc_devclass, 0, 0);
498 MODULE_VERSION(gpio_cambria, 1);
499 MODULE_DEPEND(gpio_cambria, iicbus, 1, 1, 1);