2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2010, Andrew Thompson <thompsa@FreeBSD.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice unmodified, this list of conditions, and the following
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * GPIO driver for Gateworks Cambria
34 * The Cambria PLD does not set the i2c ack bit after each write, if we used the
35 * regular iicbus interface it would abort the xfer after the address byte
36 * times out and not write our latch. To get around this we grab the iicbus and
37 * then do our own bit banging. This is a compromise to changing all the iicbb
38 * device methods to allow a flag to be passed down and is similir to how Linux
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
46 #include <sys/param.h>
47 #include <sys/systm.h>
50 #include <sys/kernel.h>
51 #include <sys/module.h>
54 #include <sys/mutex.h>
57 #include <arm/xscale/ixp425/ixp425reg.h>
58 #include <arm/xscale/ixp425/ixp425var.h>
59 #include <arm/xscale/ixp425/ixdp425reg.h>
61 #include <dev/gpio/gpiobusvar.h>
62 #include <dev/iicbus/iiconf.h>
63 #include <dev/iicbus/iicbus.h>
68 #define IIC_M_WR 0 /* write operation */
69 #define PLD_ADDR 0xac /* slave address */
73 #define GPIO_CONF_CLR(sc, reg, mask) \
74 GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, reg) &~ (mask))
75 #define GPIO_CONF_SET(sc, reg, mask) \
76 GPIO_CONF_WRITE_4(sc, reg, GPIO_CONF_READ_4(sc, reg) | (mask))
78 #define GPIO_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
79 #define GPIO_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
80 #define GPIO_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
83 struct cambria_gpio_softc {
86 bus_space_tag_t sc_iot;
87 bus_space_handle_t sc_gpio_ioh;
89 struct gpio_pin sc_pins[GPIO_PINS];
94 struct cambria_gpio_pin {
100 extern struct ixp425_softc *ixp425_softc;
102 static struct cambria_gpio_pin cambria_gpio_pins[GPIO_PINS] = {
103 { "PLD0", 0, GPIO_PIN_OUTPUT },
104 { "PLD1", 1, GPIO_PIN_OUTPUT },
105 { "PLD2", 2, GPIO_PIN_OUTPUT },
106 { "PLD3", 3, GPIO_PIN_OUTPUT },
107 { "PLD4", 4, GPIO_PIN_OUTPUT },
113 static int cambria_gpio_read(struct cambria_gpio_softc *, uint32_t, unsigned int *);
114 static int cambria_gpio_write(struct cambria_gpio_softc *);
119 static int cambria_gpio_probe(device_t dev);
120 static int cambria_gpio_attach(device_t dev);
121 static int cambria_gpio_detach(device_t dev);
126 static device_t cambria_gpio_get_bus(device_t);
127 static int cambria_gpio_pin_max(device_t dev, int *maxpin);
128 static int cambria_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps);
129 static int cambria_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t
131 static int cambria_gpio_pin_getname(device_t dev, uint32_t pin, char *name);
132 static int cambria_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags);
133 static int cambria_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value);
134 static int cambria_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val);
135 static int cambria_gpio_pin_toggle(device_t dev, uint32_t pin);
138 i2c_getsda(struct cambria_gpio_softc *sc)
143 GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
145 reg = GPIO_CONF_READ_4(sc, IXP425_GPIO_GPINR);
146 IXP4XX_GPIO_UNLOCK();
147 return (reg & GPIO_I2C_SDA_BIT);
151 i2c_setsda(struct cambria_gpio_softc *sc, int val)
155 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SDA_BIT);
157 GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
159 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SDA_BIT);
160 IXP4XX_GPIO_UNLOCK();
165 i2c_setscl(struct cambria_gpio_softc *sc, int val)
169 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOUTR, GPIO_I2C_SCL_BIT);
171 GPIO_CONF_SET(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
173 GPIO_CONF_CLR(sc, IXP425_GPIO_GPOER, GPIO_I2C_SCL_BIT);
174 IXP4XX_GPIO_UNLOCK();
179 i2c_sendstart(struct cambria_gpio_softc *sc)
188 i2c_sendstop(struct cambria_gpio_softc *sc)
197 i2c_sendbyte(struct cambria_gpio_softc *sc, u_char data)
201 for (i=7; i>=0; i--) {
202 i2c_setsda(sc, data & (1<<i));
212 i2c_readbyte(struct cambria_gpio_softc *sc)
215 unsigned char data=0;
228 cambria_gpio_read(struct cambria_gpio_softc *sc, uint32_t pin, unsigned int *val)
230 device_t dev = sc->sc_dev;
233 error = iicbus_request_bus(device_get_parent(dev), dev,
239 i2c_sendbyte(sc, PLD_ADDR | LSB);
240 *val = (i2c_readbyte(sc) & (1 << pin)) != 0;
243 iicbus_release_bus(device_get_parent(dev), dev);
249 cambria_gpio_write(struct cambria_gpio_softc *sc)
251 device_t dev = sc->sc_dev;
254 error = iicbus_request_bus(device_get_parent(dev), dev,
260 i2c_sendbyte(sc, PLD_ADDR & ~LSB);
261 i2c_sendbyte(sc, sc->sc_latch);
264 iicbus_release_bus(device_get_parent(dev), dev);
270 cambria_gpio_get_bus(device_t dev)
272 struct cambria_gpio_softc *sc;
274 sc = device_get_softc(dev);
276 return (sc->sc_busdev);
280 cambria_gpio_pin_max(device_t dev, int *maxpin)
283 *maxpin = GPIO_PINS - 1;
288 cambria_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
290 struct cambria_gpio_softc *sc = device_get_softc(dev);
292 if (pin >= GPIO_PINS)
295 *caps = sc->sc_pins[pin].gp_caps;
300 cambria_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
302 struct cambria_gpio_softc *sc = device_get_softc(dev);
304 if (pin >= GPIO_PINS)
307 *flags = sc->sc_pins[pin].gp_flags;
312 cambria_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
314 struct cambria_gpio_softc *sc = device_get_softc(dev);
316 if (pin >= GPIO_PINS)
319 memcpy(name, sc->sc_pins[pin].gp_name, GPIOMAXNAME);
324 cambria_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
326 struct cambria_gpio_softc *sc = device_get_softc(dev);
332 if (pin >= GPIO_PINS)
336 sc->sc_pins[pin].gp_flags = flags;
339 * Writing a logical one sets the signal high and writing a logical
340 * zero sets the signal low. To configure a digital I/O signal as an
341 * input, a logical one must first be written to the data bit to
342 * three-state the associated output.
344 if (flags & GPIO_PIN_INPUT || sc->sc_val & mask)
345 sc->sc_latch |= mask; /* input or output & high */
347 sc->sc_latch &= ~mask;
348 error = cambria_gpio_write(sc);
355 cambria_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
357 struct cambria_gpio_softc *sc = device_get_softc(dev);
363 if (pin >= GPIO_PINS)
371 if (sc->sc_pins[pin].gp_flags != GPIO_PIN_OUTPUT) {
372 /* just save, altering the latch will disable input */
378 sc->sc_latch |= mask;
380 sc->sc_latch &= ~mask;
381 error = cambria_gpio_write(sc);
388 cambria_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
390 struct cambria_gpio_softc *sc = device_get_softc(dev);
393 if (pin >= GPIO_PINS)
397 if (sc->sc_pins[pin].gp_flags == GPIO_PIN_OUTPUT)
398 *val = (sc->sc_latch & (1 << pin)) ? 1 : 0;
400 error = cambria_gpio_read(sc, pin, val);
407 cambria_gpio_pin_toggle(device_t dev, uint32_t pin)
409 struct cambria_gpio_softc *sc = device_get_softc(dev);
412 if (pin >= GPIO_PINS)
416 sc->sc_val ^= (1 << pin);
417 if (sc->sc_pins[pin].gp_flags == GPIO_PIN_OUTPUT) {
418 sc->sc_latch ^= (1 << pin);
419 error = cambria_gpio_write(sc);
427 cambria_gpio_probe(device_t dev)
430 device_set_desc(dev, "Gateworks Cambria GPIO driver");
435 cambria_gpio_attach(device_t dev)
437 struct cambria_gpio_softc *sc = device_get_softc(dev);
441 sc->sc_iot = ixp425_softc->sc_iot;
442 sc->sc_gpio_ioh = ixp425_softc->sc_gpio_ioh;
444 mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
446 for (pin = 0; pin < GPIO_PINS; pin++) {
447 struct cambria_gpio_pin *p = &cambria_gpio_pins[pin];
449 strncpy(sc->sc_pins[pin].gp_name, p->name, GPIOMAXNAME);
450 sc->sc_pins[pin].gp_pin = pin;
451 sc->sc_pins[pin].gp_caps = GPIO_PIN_INPUT|GPIO_PIN_OUTPUT;
452 sc->sc_pins[pin].gp_flags = 0;
453 cambria_gpio_pin_setflags(dev, pin, p->flags);
456 sc->sc_busdev = gpiobus_attach_bus(dev);
457 if (sc->sc_busdev == NULL) {
458 mtx_destroy(&sc->sc_mtx);
466 cambria_gpio_detach(device_t dev)
468 struct cambria_gpio_softc *sc = device_get_softc(dev);
470 KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
472 gpiobus_detach_bus(dev);
473 mtx_destroy(&sc->sc_mtx);
478 static device_method_t cambria_gpio_methods[] = {
479 DEVMETHOD(device_probe, cambria_gpio_probe),
480 DEVMETHOD(device_attach, cambria_gpio_attach),
481 DEVMETHOD(device_detach, cambria_gpio_detach),
484 DEVMETHOD(gpio_get_bus, cambria_gpio_get_bus),
485 DEVMETHOD(gpio_pin_max, cambria_gpio_pin_max),
486 DEVMETHOD(gpio_pin_getname, cambria_gpio_pin_getname),
487 DEVMETHOD(gpio_pin_getflags, cambria_gpio_pin_getflags),
488 DEVMETHOD(gpio_pin_getcaps, cambria_gpio_pin_getcaps),
489 DEVMETHOD(gpio_pin_setflags, cambria_gpio_pin_setflags),
490 DEVMETHOD(gpio_pin_get, cambria_gpio_pin_get),
491 DEVMETHOD(gpio_pin_set, cambria_gpio_pin_set),
492 DEVMETHOD(gpio_pin_toggle, cambria_gpio_pin_toggle),
496 static driver_t cambria_gpio_driver = {
498 cambria_gpio_methods,
499 sizeof(struct cambria_gpio_softc),
501 static devclass_t cambria_gpio_devclass;
503 DRIVER_MODULE(gpio_cambria, iicbus, cambria_gpio_driver, cambria_gpio_devclass, 0, 0);
504 MODULE_VERSION(gpio_cambria, 1);
505 MODULE_DEPEND(gpio_cambria, iicbus, 1, 1, 1);