Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F106073986
D29520.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
19 KB
Referenced Files
None
Subscribers
None
D29520.diff
View Options
diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC
--- a/sys/arm64/conf/GENERIC
+++ b/sys/arm64/conf/GENERIC
@@ -182,7 +182,6 @@
device gpioled
device fdt_pinctrl
device gpioregulator
-device ls1046_gpio # LS1046A GPIO controller
device mv_gpio # Marvell GPIO controller
device mvebu_pinctrl # Marvell Pinmux Controller
device pl061 # Arm PL061 GPIO controller
diff --git a/sys/arm64/qoriq/ls1046_gpio.c b/sys/arm64/qoriq/ls1046_gpio.c
deleted file mode 100644
--- a/sys/arm64/qoriq/ls1046_gpio.c
+++ /dev/null
@@ -1,498 +0,0 @@
-/*-
- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
- *
- * Copyright (c) 2020 Alstom Group.
- * Copyright (c) 2020 Semihalf.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-
-#include <sys/bus.h>
-#include <sys/endian.h>
-#include <sys/gpio.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
-
-#include <dev/gpio/gpiobusvar.h>
-#include <dev/ofw/ofw_bus.h>
-#include <machine/bus.h>
-
-#include "gpio_if.h"
-
-/* constants */
-enum {
- DIRECTION = 0x0,
- OPEN_DRAIN = 0x4,
- DATA = 0x8,
- INT_EV = 0xC,
- INT_MASK = 0x10,
- INT_CTRL = 0x14
-};
-
-#define PIN_COUNT 32
-#define DEFAULT_CAPS \
- (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
- GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)
-#define GPIO(n) (1 << (31 - (n)))
-
-struct gpio_res {
- int mem_rid;
- struct resource *mem_res;
-};
-
-/* software context */
-struct gpio_softc {
- device_t dev;
- device_t busdev;
- struct gpio_res res;
- struct gpio_pin setup[PIN_COUNT];
- struct mtx mutex;
-};
-
-#define QORIQ_GPIO_LOCK(_sc) mtx_lock_spin(&(_sc)->mutex)
-#define QORIQ_GPIO_UNLOCK(_sc) mtx_unlock_spin(&(_sc)->mutex)
-#define QORIQ_GPIO_ASSERT_LOCKED(_sc) mtx_assert(&(_sc)->mutex, MA_OWNED)
-
-/* prototypes */
-/* helpers */
-static bool qoriq_make_gpio_res(device_t, struct gpio_res*);
-static uint32_t qoriq_gpio_reg_read(device_t, uint32_t);
-static void qoriq_gpio_reg_write(device_t, uint32_t, uint32_t);
-static void qoriq_gpio_set(device_t, uint32_t, uint32_t, uint32_t);
-static int qoriq_gpio_configure(device_t, uint32_t, uint32_t);
-
-/* GPIO API */
-static int qoriq_gpio_probe(device_t);
-static int qoriq_gpio_attach(device_t);
-static device_t qoriq_gpio_get_bus(device_t);
-static int qoriq_gpio_pin_max(device_t, int*);
-static int qoriq_gpio_pin_getname(device_t, uint32_t, char*);
-static int qoriq_gpio_pin_getflags(device_t, uint32_t, uint32_t*);
-static int qoriq_gpio_pin_setflags(device_t, uint32_t, uint32_t);
-static int qoriq_gpio_pin_getcaps(device_t, uint32_t, uint32_t*);
-static int qoriq_gpio_pin_get(device_t, uint32_t, uint32_t*);
-static int qoriq_gpio_pin_set(device_t, uint32_t, uint32_t);
-static int qoriq_gpio_pin_toggle(device_t, uint32_t);
-static int qoriq_gpio_map_gpios(device_t, phandle_t, phandle_t,
- int, pcell_t*, uint32_t*, uint32_t*);
-static int qoriq_gpio_pin_access_32(device_t, uint32_t, uint32_t, uint32_t,
- uint32_t*);
-static int qoriq_gpio_pin_config_32(device_t, uint32_t, uint32_t, uint32_t*);
-
-static device_method_t qoriq_gpio_methods[] = {
- DEVMETHOD(device_probe, qoriq_gpio_probe),
- DEVMETHOD(device_attach, qoriq_gpio_attach),
-
- /* GPIO protocol */
- DEVMETHOD(gpio_get_bus, qoriq_gpio_get_bus),
- DEVMETHOD(gpio_pin_max, qoriq_gpio_pin_max),
- DEVMETHOD(gpio_pin_getname, qoriq_gpio_pin_getname),
- DEVMETHOD(gpio_pin_getflags, qoriq_gpio_pin_getflags),
- DEVMETHOD(gpio_pin_setflags, qoriq_gpio_pin_setflags),
- DEVMETHOD(gpio_pin_getcaps, qoriq_gpio_pin_getcaps),
- DEVMETHOD(gpio_pin_get, qoriq_gpio_pin_get),
- DEVMETHOD(gpio_pin_set, qoriq_gpio_pin_set),
- DEVMETHOD(gpio_pin_toggle, qoriq_gpio_pin_toggle),
- DEVMETHOD(gpio_map_gpios, qoriq_gpio_map_gpios),
- DEVMETHOD(gpio_pin_access_32, qoriq_gpio_pin_access_32),
- DEVMETHOD(gpio_pin_config_32, qoriq_gpio_pin_config_32),
-
- DEVMETHOD_END
-};
-
-static driver_t gpio_driver = {
- "gpio",
- qoriq_gpio_methods,
- sizeof(struct gpio_softc),
-};
-
-static devclass_t gpio_devclass;
-
-DRIVER_MODULE(gpio, simplebus, gpio_driver, gpio_devclass, 0, 0);
-MODULE_VERSION(gpio, 1);
-
-/*
- * helpers
- */
-static bool
-qoriq_make_gpio_res(device_t dev, struct gpio_res *out)
-{
-
- out->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &out->mem_rid, RF_ACTIVE | RF_SHAREABLE);
-
- return (out->mem_res == NULL);
-}
-
-static uint32_t
-qoriq_gpio_reg_read(device_t dev, uint32_t reg)
-{
- struct gpio_softc *sc = device_get_softc(dev);
- uint32_t result;
-
- QORIQ_GPIO_ASSERT_LOCKED(sc);
- result = bus_read_4(sc->res.mem_res, reg);
-
- return be32toh(result);
-}
-
-static void
-qoriq_gpio_reg_write(device_t dev, uint32_t reg, uint32_t val)
-{
- struct gpio_softc *sc = device_get_softc(dev);
-
- QORIQ_GPIO_ASSERT_LOCKED(sc);
- val = htobe32(val);
-
- bus_write_4(sc->res.mem_res, reg, val);
- bus_barrier(sc->res.mem_res, reg, 4, BUS_SPACE_BARRIER_READ |
- BUS_SPACE_BARRIER_WRITE);
-}
-
-static void
-qoriq_gpio_set(device_t dev, uint32_t reg, uint32_t pin, uint32_t set)
-{
- uint32_t val;
-
- set = set != 0;
- val = (qoriq_gpio_reg_read(dev, reg) & ~(1U << pin)) | (set << pin);
- qoriq_gpio_reg_write(dev, reg, val);
-}
-
-static int
-qoriq_gpio_configure(device_t dev, uint32_t pin, uint32_t flags)
-{
- struct gpio_softc *sc = device_get_softc(dev);
- uint32_t newflags;
-
- if (pin >= PIN_COUNT)
- return (EINVAL);
-
- /*
- * Pin cannot function as input and output at the same time.
- * The same applies to open-drain and push-pull functionality.
- */
- if (((flags & GPIO_PIN_INPUT) && (flags & GPIO_PIN_OUTPUT)) ||
- ((flags & GPIO_PIN_OPENDRAIN) && (flags & GPIO_PIN_PUSHPULL)))
- return (EINVAL);
-
- QORIQ_GPIO_ASSERT_LOCKED(sc);
-
- if (flags & GPIO_PIN_INPUT) {
- newflags = GPIO_PIN_INPUT;
- qoriq_gpio_set(dev, DIRECTION, pin, 0);
- }
-
- if (flags & GPIO_PIN_OUTPUT) {
- newflags = GPIO_PIN_OUTPUT;
- qoriq_gpio_set(dev, DIRECTION, pin, 1);
-
- if (flags & GPIO_PIN_OPENDRAIN) {
- newflags |= GPIO_PIN_OPENDRAIN;
- qoriq_gpio_set(dev, OPEN_DRAIN, pin, 1);
- } else {
- newflags |= GPIO_PIN_PUSHPULL;
- qoriq_gpio_set(dev, OPEN_DRAIN, pin, 0);
- }
- }
-
- sc->setup[pin].gp_flags = newflags;
-
- return (0);
-}
-
-/* GPIO API */
-static int
-qoriq_gpio_probe(device_t dev)
-{
-
- if (!ofw_bus_status_okay(dev))
- return (ENXIO);
-
- if (!ofw_bus_is_compatible(dev, "fsl,qoriq-gpio"))
- return (ENXIO);
-
- device_set_desc(dev, "Integrated GPIO Controller");
-
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-qoriq_gpio_attach(device_t dev)
-{
- struct gpio_softc *sc = device_get_softc(dev);
- int i;
-
- if (qoriq_make_gpio_res(dev, &sc->res))
- return (ENXIO);
-
- for (i = 0; i < PIN_COUNT; i++)
- sc->setup[i].gp_caps = DEFAULT_CAPS;
-
- sc->dev = dev;
-
- sc->busdev = gpiobus_attach_bus(dev);
- if (sc->busdev == NULL)
- return (ENXIO);
-
- return (0);
-}
-
-static device_t
-qoriq_gpio_get_bus(device_t dev)
-{
- struct gpio_softc *softc = device_get_softc(dev);
-
- return (softc->busdev);
-}
-
-static int
-qoriq_gpio_pin_max(device_t dev, int *maxpin)
-{
-
- if (maxpin == NULL)
- return (EINVAL);
-
- *maxpin = PIN_COUNT - 1;
-
- return (0);
-}
-
-static int
-qoriq_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
-{
-
- if (name == NULL || pin >= PIN_COUNT)
- return (EINVAL);
-
- snprintf(name, GPIOMAXNAME, "pin %d", pin);
-
- return (0);
-}
-
-static int
-qoriq_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *pflags)
-{
- struct gpio_softc *sc = device_get_softc(dev);
-
- if (pflags == NULL || pin >= PIN_COUNT)
- return (EINVAL);
-
- QORIQ_GPIO_LOCK(sc);
- *pflags = sc->setup[pin].gp_flags;
- QORIQ_GPIO_UNLOCK(sc);
-
- return (0);
-}
-
-static int
-qoriq_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
-{
- struct gpio_softc *sc = device_get_softc(dev);
- int ret;
-
- if (pin >= PIN_COUNT)
- return (EINVAL);
-
- /* Check for unwanted flags. */
- QORIQ_GPIO_LOCK(sc);
-
- if ((flags & sc->setup[pin].gp_caps) != flags) {
- QORIQ_GPIO_UNLOCK(sc);
- return (EINVAL);
- }
-
- ret = qoriq_gpio_configure(dev, pin, flags);
-
- QORIQ_GPIO_UNLOCK(sc);
-
- return (ret);
-}
-
-static int
-qoriq_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
-{
- struct gpio_softc *sc = device_get_softc(dev);
-
- if (caps == NULL || pin >= PIN_COUNT)
- return (EINVAL);
-
- QORIQ_GPIO_LOCK(sc);
- *caps = sc->setup[pin].gp_caps;
- QORIQ_GPIO_UNLOCK(sc);
-
- return (0);
-}
-
-static int
-qoriq_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *value)
-{
- struct gpio_softc *sc = device_get_softc(dev);
-
- if (value == NULL || pin >= PIN_COUNT)
- return (EINVAL);
-
- QORIQ_GPIO_LOCK(sc);
- *value = (qoriq_gpio_reg_read(dev, DATA) & GPIO(pin)) != 0;
- QORIQ_GPIO_UNLOCK(sc);
-
- return (0);
-}
-
-static int
-qoriq_gpio_pin_set(device_t dev, uint32_t pin, uint32_t value)
-{
- struct gpio_softc *sc = device_get_softc(dev);
-
- if (pin >= PIN_COUNT)
- return (EINVAL);
-
- QORIQ_GPIO_LOCK(sc);
- qoriq_gpio_set(dev, DATA, pin, value);
- QORIQ_GPIO_UNLOCK(sc);
-
- return (0);
-}
-
-static int
-qoriq_gpio_pin_toggle(device_t dev, uint32_t pin)
-{
- struct gpio_softc *sc;
- uint32_t value;
-
- if (pin >= PIN_COUNT)
- return (EINVAL);
-
- sc = device_get_softc(dev);
-
- QORIQ_GPIO_LOCK(sc);
- value = qoriq_gpio_reg_read(dev, DATA) ^ (1 << pin);
- qoriq_gpio_reg_write(dev, DATA, value);
- QORIQ_GPIO_UNLOCK(sc);
-
- return (0);
-}
-
-static int
-qoriq_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
- pcell_t *gpios, uint32_t *pin, uint32_t *flags)
-{
- struct gpio_softc *sc = device_get_softc(bus);
- int err;
-
- if (gpios[0] >= PIN_COUNT)
- return (EINVAL);
-
- QORIQ_GPIO_LOCK(sc);
- err = qoriq_gpio_configure(bus, gpios[0], gpios[1]);
- QORIQ_GPIO_UNLOCK(sc);
-
- if (err != 0)
- return (err);
-
- *pin = gpios[0];
- *flags = gpios[1];
-
- return (0);
-}
-
-static int
-qoriq_gpio_pin_access_32(device_t dev, uint32_t first_pin, uint32_t clear_pins,
- uint32_t change_pins, uint32_t *orig_pins)
-{
- struct gpio_softc *sc;
- uint32_t hwstate;
-
- sc = device_get_softc(dev);
-
- if (first_pin != 0)
- return (EINVAL);
-
- QORIQ_GPIO_LOCK(sc);
- hwstate = qoriq_gpio_reg_read(dev, DATA);
- qoriq_gpio_reg_write(dev, DATA, (hwstate & ~clear_pins) ^ change_pins);
- QORIQ_GPIO_UNLOCK(sc);
-
- if (orig_pins != NULL)
- *orig_pins = hwstate;
-
- return (0);
-}
-
-static int
-qoriq_gpio_pin_config_32(device_t dev, uint32_t first_pin, uint32_t num_pins,
- uint32_t *pin_flags)
-{
- uint32_t dir, odr, mask, reg;
- struct gpio_softc *sc;
- uint32_t newflags[32];
- int i;
-
- if (first_pin != 0 || num_pins > PIN_COUNT)
- return (EINVAL);
-
- sc = device_get_softc(dev);
-
- dir = odr = mask = 0;
-
- for (i = 0; i < num_pins; i++) {
- newflags[i] = 0;
- mask |= (1 << i);
-
- if (pin_flags[i] & GPIO_PIN_INPUT) {
- newflags[i] = GPIO_PIN_INPUT;
- dir &= ~(1 << i);
- } else {
- newflags[i] = GPIO_PIN_OUTPUT;
- dir |= (1 << i);
-
- if (pin_flags[i] & GPIO_PIN_OPENDRAIN) {
- newflags[i] |= GPIO_PIN_OPENDRAIN;
- odr |= (1 << i);
- } else {
- newflags[i] |= GPIO_PIN_PUSHPULL;
- odr &= ~(1 << i);
- }
- }
- }
-
- QORIQ_GPIO_LOCK(sc);
-
- reg = (qoriq_gpio_reg_read(dev, DIRECTION) & ~mask) | dir;
- qoriq_gpio_reg_write(dev, DIRECTION, reg);
-
- reg = (qoriq_gpio_reg_read(dev, OPEN_DRAIN) & ~mask) | odr;
- qoriq_gpio_reg_write(dev, OPEN_DRAIN, reg);
-
- for (i = 0; i < num_pins; i++)
- sc->setup[i].gp_flags = newflags[i];
-
- QORIQ_GPIO_UNLOCK(sc);
-
- return (0);
-}
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -169,6 +169,7 @@
dev/gpio/pl061.c optional pl061 gpio
dev/gpio/pl061_acpi.c optional pl061 gpio acpi
dev/gpio/pl061_fdt.c optional pl061 gpio fdt
+dev/gpio/qoriq_gpio.c optional SOC_NXP_LS gpio fdt
dev/hwpmc/hwpmc_arm64.c optional hwpmc
dev/hwpmc/hwpmc_arm64_md.c optional hwpmc
@@ -494,7 +495,6 @@
# NXP
arm/freescale/vybrid/vf_i2c.c optional vf_i2c iicbus SOC_NXP_LS
-arm64/qoriq/ls1046_gpio.c optional ls1046_gpio gpio fdt SOC_NXP_LS
arm64/qoriq/qoriq_dw_pci.c optional pci fdt SOC_NXP_LS
arm64/qoriq/qoriq_therm.c optional pci fdt SOC_NXP_LS
arm64/qoriq/qoriq_therm_if.m optional pci fdt SOC_NXP_LS
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -24,6 +24,7 @@
dev/adb/adb_buttons.c optional adb
dev/agp/agp_apple.c optional agp powermac
dev/fb/fb.c optional sc
+dev/gpio/qoriq_gpio.c optional mpc85xx gpio
dev/hwpmc/hwpmc_e500.c optional hwpmc
dev/hwpmc/hwpmc_mpc7xxx.c optional hwpmc
dev/hwpmc/hwpmc_power8.c optional hwpmc
@@ -186,7 +187,6 @@
powerpc/mpc85xx/platform_mpc85xx.c optional mpc85xx
powerpc/mpc85xx/pci_mpc85xx.c optional pci mpc85xx
powerpc/mpc85xx/pci_mpc85xx_pcib.c optional pci mpc85xx
-powerpc/mpc85xx/qoriq_gpio.c optional mpc85xx gpio
powerpc/ofw/ofw_machdep.c standard
powerpc/ofw/ofw_pcibus.c optional pci
powerpc/ofw/ofw_pcib_pci.c optional pci
diff --git a/sys/powerpc/mpc85xx/qoriq_gpio.c b/sys/dev/gpio/qoriq_gpio.c
rename from sys/powerpc/mpc85xx/qoriq_gpio.c
rename to sys/dev/gpio/qoriq_gpio.c
--- a/sys/powerpc/mpc85xx/qoriq_gpio.c
+++ b/sys/dev/gpio/qoriq_gpio.c
@@ -1,4 +1,6 @@
/*-
+ * Copyright (c) 2020 Alstom Group.
+ * Copyright (c) 2020 Semihalf.
* Copyright (c) 2015 Justin Hibbits
* All rights reserved.
*
@@ -52,6 +54,8 @@
#define MAXPIN (31)
#define VALID_PIN(u) ((u) >= 0 && (u) <= MAXPIN)
+#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
+ GPIO_PIN_OPENDRAIN | GPIO_PIN_PUSHPULL)
#define GPIO_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
#define GPIO_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
@@ -66,12 +70,14 @@
#define GPIO_GPIER 0xc
#define GPIO_GPIMR 0x10
#define GPIO_GPICR 0x14
+#define GPIO_GPIBE 0x18
struct qoriq_gpio_softc {
device_t dev;
device_t busdev;
struct mtx sc_mtx;
struct resource *sc_mem; /* Memory resource */
+ struct gpio_pin sc_pins[MAXPIN + 1];
};
static device_t
@@ -96,11 +102,16 @@
static int
qoriq_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
{
+ struct qoriq_gpio_softc *sc;
+
+ sc = device_get_softc(dev);
if (!VALID_PIN(pin))
return (EINVAL);
- *caps = (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_OPENDRAIN);
+ GPIO_LOCK(sc);
+ *caps = sc->sc_pins[pin].gp_caps;
+ GPIO_UNLOCK(sc);
return (0);
}
@@ -135,6 +146,11 @@
return (EINVAL);
GPIO_LOCK(sc);
+ if ((flags & sc->sc_pins[pin].gp_caps) != flags) {
+ GPIO_UNLOCK(sc);
+ return (EINVAL);
+ }
+
if (flags & GPIO_PIN_INPUT) {
reg = bus_read_4(sc->sc_mem, GPIO_GPDIR);
reg &= ~(1 << (31 - pin));
@@ -151,10 +167,28 @@
reg &= ~(1 << (31 - pin));
bus_write_4(sc->sc_mem, GPIO_GPODR, reg);
}
+ sc->sc_pins[pin].gp_flags = flags;
GPIO_UNLOCK(sc);
return (0);
}
+static int
+qoriq_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *pflags)
+{
+ struct qoriq_gpio_softc *sc;
+
+ if (!VALID_PIN(pin))
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+
+ GPIO_LOCK(sc);
+ *pflags = sc->sc_pins[pin].gp_flags;
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
/* Set a specific output pin's value. */
static int
qoriq_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
@@ -233,13 +267,113 @@
return (0);
}
+static int
+qoriq_gpio_pin_access_32(device_t dev, uint32_t first_pin, uint32_t clear_pins,
+ uint32_t change_pins, uint32_t *orig_pins)
+{
+ struct qoriq_gpio_softc *sc;
+ uint32_t hwstate;
+
+ sc = device_get_softc(dev);
+
+ if (first_pin != 0)
+ return (EINVAL);
+
+ GPIO_LOCK(sc);
+ hwstate = bus_read_4(sc->sc_mem, GPIO_GPDAT);
+ bus_write_4(sc->sc_mem, GPIO_GPDAT,
+ (hwstate & ~clear_pins) ^ change_pins);
+ GPIO_UNLOCK(sc);
+
+ if (orig_pins != NULL)
+ *orig_pins = hwstate;
+
+ return (0);
+}
+
+static int
+qoriq_gpio_pin_config_32(device_t dev, uint32_t first_pin, uint32_t num_pins,
+ uint32_t *pin_flags)
+{
+ uint32_t dir, odr, mask, reg;
+ struct qoriq_gpio_softc *sc;
+ uint32_t newflags[32];
+ int i;
+
+ if (first_pin != 0 || !VALID_PIN(num_pins))
+ return (EINVAL);
+
+ sc = device_get_softc(dev);
+
+ dir = odr = mask = 0;
+
+ for (i = 0; i < num_pins; i++) {
+ newflags[i] = 0;
+ mask |= (1 << i);
+
+ if (pin_flags[i] & GPIO_PIN_INPUT) {
+ newflags[i] = GPIO_PIN_INPUT;
+ dir &= ~(1 << i);
+ } else {
+ newflags[i] = GPIO_PIN_OUTPUT;
+ dir |= (1 << i);
+
+ if (pin_flags[i] & GPIO_PIN_OPENDRAIN) {
+ newflags[i] |= GPIO_PIN_OPENDRAIN;
+ odr |= (1 << i);
+ } else {
+ newflags[i] |= GPIO_PIN_PUSHPULL;
+ odr &= ~(1 << i);
+ }
+ }
+ }
+
+ GPIO_LOCK(sc);
+
+ reg = (bus_read_4(sc->sc_mem, GPIO_GPDIR) & ~mask) | dir;
+ bus_write_4(sc->sc_mem, GPIO_GPDIR, reg);
+
+ reg = (bus_read_4(sc->sc_mem, GPIO_GPODR) & ~mask) | odr;
+ bus_write_4(sc->sc_mem, GPIO_GPODR, reg);
+
+ for (i = 0; i < num_pins; i++)
+ sc->sc_pins[i].gp_flags = newflags[i];
+
+ GPIO_UNLOCK(sc);
+
+ return (0);
+}
+
+static int
+qoriq_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
+ pcell_t *gpios, uint32_t *pin, uint32_t *flags)
+{
+ struct qoriq_gpio_softc *sc;
+ int err;
+
+ if (!VALID_PIN(gpios[0]))
+ return (EINVAL);
+
+ sc = device_get_softc(bus);
+ GPIO_LOCK(sc);
+ err = qoriq_gpio_pin_setflags(bus, gpios[0], gpios[1]);
+ GPIO_UNLOCK(sc);
+
+ if (err == 0) {
+ *pin = gpios[0];
+ *flags = gpios[1];
+ }
+
+ return (err);
+}
+
static int qoriq_gpio_detach(device_t dev);
static int
qoriq_gpio_attach(device_t dev)
{
struct qoriq_gpio_softc *sc = device_get_softc(dev);
- int rid;
+ int i, rid;
sc->dev = dev;
@@ -255,11 +389,21 @@
return (ENOMEM);
}
+ for (i = 0; i <= MAXPIN; i++)
+ sc->sc_pins[i].gp_caps = DEFAULT_CAPS;
+
sc->busdev = gpiobus_attach_bus(dev);
if (sc->busdev == NULL) {
qoriq_gpio_detach(dev);
return (ENOMEM);
}
+ /*
+ * Enable the GPIO Input Buffer for all GPIOs.
+ * This is safe on devices without a GPIBE register, because those
+ * devices ignore writes and read 0's in undefined portions of the map.
+ */
+ if (ofw_bus_is_compatible(dev, "fsl,qoriq-gpio"))
+ bus_write_4(sc->sc_mem, GPIO_GPIBE, 0xffffffff);
OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev);
@@ -297,9 +441,14 @@
DEVMETHOD(gpio_pin_getcaps, qoriq_gpio_pin_getcaps),
DEVMETHOD(gpio_pin_get, qoriq_gpio_pin_get),
DEVMETHOD(gpio_pin_set, qoriq_gpio_pin_set),
+ DEVMETHOD(gpio_pin_getflags, qoriq_gpio_pin_getflags),
DEVMETHOD(gpio_pin_setflags, qoriq_gpio_pin_setflags),
DEVMETHOD(gpio_pin_toggle, qoriq_gpio_pin_toggle),
+ DEVMETHOD(gpio_map_gpios, qoriq_gpio_map_gpios),
+ DEVMETHOD(gpio_pin_access_32, qoriq_gpio_pin_access_32),
+ DEVMETHOD(gpio_pin_config_32, qoriq_gpio_pin_config_32),
+
DEVMETHOD_END
};
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Dec 25, 11:13 PM (11 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15599370
Default Alt Text
D29520.diff (19 KB)
Attached To
Mode
D29520: Merge the QorIQ GPIO drivers between arm and powerpc
Attached
Detach File
Event Timeline
Log In to Comment