svn commit: r342013 - in head/sys: arm/mv arm64/conf conf
Emmanuel Vadot
manu at FreeBSD.org
Wed Dec 12 22:02:58 UTC 2018
Author: manu
Date: Wed Dec 12 22:02:57 2018
New Revision: 342013
URL: https://svnweb.freebsd.org/changeset/base/342013
Log:
arm64: mv_gpio: Add Marvell 8K support
While here put the interrupts setup in it's own function
Sponsored by: Rubicon Communications, LCC ("Netgate")
Modified:
head/sys/arm/mv/gpio.c
head/sys/arm64/conf/GENERIC
head/sys/conf/files.arm64
Modified: head/sys/arm/mv/gpio.c
==============================================================================
--- head/sys/arm/mv/gpio.c Wed Dec 12 22:01:06 2018 (r342012)
+++ head/sys/arm/mv/gpio.c Wed Dec 12 22:02:57 2018 (r342013)
@@ -60,6 +60,10 @@ __FBSDID("$FreeBSD$");
#include "gpio_if.h"
+#ifdef __aarch64__
+#include "opt_soc.h"
+#endif
+
#define GPIO_MAX_INTR_COUNT 8
#define GPIO_PINS_PER_REG 32
#define GPIO_GENERIC_CAP (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \
@@ -74,6 +78,7 @@ __FBSDID("$FreeBSD$");
#define DEBOUNCE_CHECK_TICKS ((hz / 1000) * DEBOUNCE_CHECK_MS)
struct mv_gpio_softc {
+ device_t dev;
device_t sc_busdev;
struct resource * mem_res;
int mem_rid;
@@ -83,6 +88,7 @@ struct mv_gpio_softc {
void *ih_cookie[GPIO_MAX_INTR_COUNT];
bus_space_tag_t bst;
bus_space_handle_t bsh;
+ uint32_t offset;
struct mtx mutex;
uint8_t pin_num; /* number of GPIO pins */
uint8_t irq_num; /* number of real IRQs occupied by GPIO controller */
@@ -189,9 +195,12 @@ static devclass_t mv_gpio_devclass;
DRIVER_MODULE(mv_gpio, simplebus, mv_gpio_driver, mv_gpio_devclass, 0, 0);
-struct ofw_compat_data gpio_controllers[] = {
- { "mrvl,gpio", (uintptr_t)true },
- { "marvell,orion-gpio", (uintptr_t)true },
+struct ofw_compat_data compat_data[] = {
+ { "mrvl,gpio", 1 },
+ { "marvell,orion-gpio", 1 },
+#ifdef SOC_MARVELL_8K
+ { "marvell,armada-8k-gpio", 1 },
+#endif
{ NULL, 0 }
};
@@ -201,7 +210,7 @@ mv_gpio_probe(device_t dev)
if (!ofw_bus_status_okay(dev))
return (ENXIO);
- if (ofw_bus_search_compatible(dev, gpio_controllers)->ocd_data == 0)
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
device_set_desc(dev, "Marvell Integrated GPIO Controller");
@@ -209,61 +218,75 @@ mv_gpio_probe(device_t dev)
}
static int
-mv_gpio_attach(device_t dev)
+mv_gpio_setup_interrupts(struct mv_gpio_softc *sc, phandle_t node)
{
- int i, size;
- struct mv_gpio_softc *sc;
- pcell_t pincnt = 0;
- pcell_t irq_cells = 0;
phandle_t iparent;
+ pcell_t irq_cells;
+ int i, size;
- sc = (struct mv_gpio_softc *)device_get_softc(dev);
- if (sc == NULL)
- return (ENXIO);
-
- if (OF_getencprop(ofw_bus_get_node(dev), "pin-count", &pincnt,
- sizeof(pcell_t)) >= 0 ||
- OF_getencprop(ofw_bus_get_node(dev), "ngpios", &pincnt,
- sizeof(pcell_t)) >= 0) {
- sc->pin_num = MIN(pincnt, MV_GPIO_MAX_NPINS);
- if (bootverbose)
- device_printf(dev, "%d pins available\n", sc->pin_num);
- } else {
- device_printf(dev, "ERROR: no pin-count or ngpios entry found!\n");
- return (ENXIO);
- }
-
- /* Assign generic capabilities to every gpio pin */
- for(i = 0; i < sc->pin_num; i++)
- sc->gpio_setup[i].gp_caps = GPIO_GENERIC_CAP;
-
/* Find root interrupt controller */
- iparent = ofw_bus_find_iparent(ofw_bus_get_node(dev));
+ iparent = ofw_bus_find_iparent(node);
if (iparent == 0) {
- device_printf(dev, "No interrupt-parrent found. "
+ device_printf(sc->dev, "No interrupt-parrent found. "
"Error in DTB\n");
return (ENXIO);
} else {
/* While at parent - store interrupt cells prop */
if (OF_searchencprop(OF_node_from_xref(iparent),
"#interrupt-cells", &irq_cells, sizeof(irq_cells)) == -1) {
- device_printf(dev, "DTB: Missing #interrupt-cells "
+ device_printf(sc->dev, "DTB: Missing #interrupt-cells "
"property in interrupt parent node\n");
return (ENXIO);
}
}
- size = OF_getproplen(ofw_bus_get_node(dev), "interrupts");
+ size = OF_getproplen(node, "interrupts");
if (size != -1) {
size = size / sizeof(pcell_t);
size = size / irq_cells;
sc->irq_num = size;
- device_printf(dev, "%d IRQs available\n", sc->irq_num);
+ device_printf(sc->dev, "%d IRQs available\n", sc->irq_num);
} else {
- device_printf(dev, "ERROR: no interrupts entry found!\n");
+ device_printf(sc->dev, "ERROR: no interrupts entry found!\n");
return (ENXIO);
}
+ for (i = 0; i < sc->irq_num; i++) {
+ sc->irq_rid[i] = i;
+ sc->irq_res[i] = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ,
+ &sc->irq_rid[i], RF_ACTIVE);
+ if (!sc->irq_res[i]) {
+ mtx_destroy(&sc->mutex);
+ device_printf(sc->dev,
+ "could not allocate gpio%d interrupt\n", i+1);
+ return (ENXIO);
+ }
+ }
+
+ device_printf(sc->dev, "Disable interrupts (offset = %x + EDGE(0x18)\n", sc->offset);
+ /* Disable all interrupts */
+ bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_EDGE_MASK, 0);
+ device_printf(sc->dev, "Disable interrupts (offset = %x + LEV(0x1C))\n", sc->offset);
+ bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_LEV_MASK, 0);
+
+ for (i = 0; i < sc->irq_num; i++) {
+ device_printf(sc->dev, "Setup intr %d\n", i);
+ if (bus_setup_intr(sc->dev, sc->irq_res[i],
+ INTR_TYPE_MISC,
+ (driver_filter_t *)mv_gpio_intr, NULL,
+ sc, &sc->ih_cookie[i]) != 0) {
+ mtx_destroy(&sc->mutex);
+ bus_release_resource(sc->dev, SYS_RES_IRQ,
+ sc->irq_rid[i], sc->irq_res[i]);
+ device_printf(sc->dev, "could not set up intr %d\n", i);
+ return (ENXIO);
+ }
+ }
+
+ /* Clear interrupt status. */
+ device_printf(sc->dev, "Clear int status (offset = %x)\n", sc->offset);
+ bus_space_write_4(sc->bst, sc->bsh, sc->offset + GPIO_INT_CAUSE, 0);
+
sc->debounce_callouts = (struct callout **)malloc(sc->pin_num *
sizeof(struct callout *), M_DEVBUF, M_WAITOK | M_ZERO);
if (sc->debounce_callouts == NULL)
@@ -274,11 +297,46 @@ mv_gpio_attach(device_t dev)
if (sc->debounce_counters == NULL)
return (ENOMEM);
+ return (0);
+}
+
+static int
+mv_gpio_attach(device_t dev)
+{
+ int i, rv;
+ struct mv_gpio_softc *sc;
+ phandle_t node;
+ pcell_t pincnt = 0;
+
+ sc = (struct mv_gpio_softc *)device_get_softc(dev);
+ if (sc == NULL)
+ return (ENXIO);
+
+ node = ofw_bus_get_node(dev);
+ sc->dev = dev;
+
+ if (OF_getencprop(node, "pin-count", &pincnt, sizeof(pcell_t)) >= 0 ||
+ OF_getencprop(node, "ngpios", &pincnt, sizeof(pcell_t)) >= 0) {
+ sc->pin_num = MIN(pincnt, MV_GPIO_MAX_NPINS);
+ if (bootverbose)
+ device_printf(dev, "%d pins available\n", sc->pin_num);
+ } else {
+ device_printf(dev, "ERROR: no pin-count or ngpios entry found!\n");
+ return (ENXIO);
+ }
+
+ if (OF_getencprop(node, "offset", &sc->offset, sizeof(sc->offset)) == -1)
+ sc->offset = 0;
+
+ /* Assign generic capabilities to every gpio pin */
+ for(i = 0; i < sc->pin_num; i++)
+ sc->gpio_setup[i].gp_caps = GPIO_GENERIC_CAP;
+
mtx_init(&sc->mutex, device_get_nameunit(dev), NULL, MTX_SPIN);
sc->mem_rid = 0;
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
- RF_ACTIVE);
+ RF_ACTIVE | RF_SHAREABLE );
if (!sc->mem_res) {
mtx_destroy(&sc->mutex);
@@ -289,38 +347,10 @@ mv_gpio_attach(device_t dev)
sc->bst = rman_get_bustag(sc->mem_res);
sc->bsh = rman_get_bushandle(sc->mem_res);
- for (i = 0; i < sc->irq_num; i++) {
- sc->irq_rid[i] = i;
- sc->irq_res[i] = bus_alloc_resource_any(dev, SYS_RES_IRQ,
- &sc->irq_rid[i], RF_ACTIVE);
- if (!sc->irq_res[i]) {
- mtx_destroy(&sc->mutex);
- device_printf(dev,
- "could not allocate gpio%d interrupt\n", i+1);
- return (ENXIO);
- }
- }
+ rv = mv_gpio_setup_interrupts(sc, node);
+ if (rv != 0)
+ return (rv);
- /* Disable all interrupts */
- bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_EDGE_MASK, 0);
- bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_LEV_MASK, 0);
-
- for (i = 0; i < sc->irq_num; i++) {
- if (bus_setup_intr(dev, sc->irq_res[i],
- INTR_TYPE_MISC,
- (driver_filter_t *)mv_gpio_intr, NULL,
- sc, &sc->ih_cookie[i]) != 0) {
- mtx_destroy(&sc->mutex);
- bus_release_resource(dev, SYS_RES_IRQ,
- sc->irq_rid[i], sc->irq_res[i]);
- device_printf(dev, "could not set up intr %d\n", i);
- return (ENXIO);
- }
- }
-
- /* Clear interrupt status. */
- bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_CAUSE, 0);
-
sc->sc_busdev = gpiobus_attach_bus(dev);
if (sc->sc_busdev == NULL) {
mtx_destroy(&sc->mutex);
@@ -540,6 +570,8 @@ mv_gpio_configure(device_t dev, uint32_t pin, uint32_t
return (EINVAL);
if (mask & MV_GPIO_IN_DEBOUNCE) {
+ if (sc->irq_num == 0)
+ return (EINVAL);
error = mv_gpio_debounce_prepare(dev, pin);
if (error != 0)
return (error);
@@ -845,7 +877,7 @@ mv_gpio_reg_read(device_t dev, uint32_t reg)
struct mv_gpio_softc *sc;
sc = (struct mv_gpio_softc *)device_get_softc(dev);
- return (bus_space_read_4(sc->bst, sc->bsh, reg));
+ return (bus_space_read_4(sc->bst, sc->bsh, sc->offset + reg));
}
static void
@@ -854,7 +886,7 @@ mv_gpio_reg_write(device_t dev, uint32_t reg, uint32_t
struct mv_gpio_softc *sc;
sc = (struct mv_gpio_softc *)device_get_softc(dev);
- bus_space_write_4(sc->bst, sc->bsh, reg, val);
+ bus_space_write_4(sc->bst, sc->bsh, sc->offset + reg, val);
}
static void
Modified: head/sys/arm64/conf/GENERIC
==============================================================================
--- head/sys/arm64/conf/GENERIC Wed Dec 12 22:01:06 2018 (r342012)
+++ head/sys/arm64/conf/GENERIC Wed Dec 12 22:02:57 2018 (r342013)
@@ -204,6 +204,7 @@ device aw_gpio # Allwinner GPIO controller
device gpio
device gpioled
device fdt_pinctrl
+device mv_gpio # Marvell GPIO controller
device mvebu_pinctrl # Marvell Pinmux Controller
# I2C
Modified: head/sys/conf/files.arm64
==============================================================================
--- head/sys/conf/files.arm64 Wed Dec 12 22:01:06 2018 (r342012)
+++ head/sys/conf/files.arm64 Wed Dec 12 22:02:57 2018 (r342013)
@@ -89,6 +89,7 @@ arm/broadcom/bcm2835/bcm2835_vcio.c optional soc_brcm
arm/broadcom/bcm2835/bcm2835_wdog.c optional soc_brcm_bcm2837 fdt
arm/broadcom/bcm2835/bcm2836.c optional soc_brcm_bcm2837 fdt
arm/broadcom/bcm2835/bcm283x_dwc_fdt.c optional dwcotg fdt soc_brcm_bcm2837
+arm/mv/gpio.c optional mv_gpio fdt
arm/mv/mvebu_pinctrl.c optional mvebu_pinctrl fdt
arm/mv/mv_ap806_clock.c optional SOC_MARVELL_8K fdt
arm/mv/armada38x/armada38x_rtc.c optional mv_rtc fdt
More information about the svn-src-all
mailing list