aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arm/mv/mv_ap806_clock.c30
-rw-r--r--sys/arm/mv/mv_ap806_gicp.c92
-rw-r--r--sys/arm/mv/mv_ap806_sei.c419
-rw-r--r--sys/arm/mv/mv_cp110_clock.c24
-rw-r--r--sys/arm/mv/mv_cp110_icu.c88
-rw-r--r--sys/arm/mv/mv_cp110_icu_bus.c78
-rw-r--r--sys/arm/mv/mv_thermal.c75
-rw-r--r--sys/arm/mv/mvebu_pinctrl.c30
-rw-r--r--sys/arm64/conf/GENERIC1
-rw-r--r--sys/conf/files.arm647
10 files changed, 718 insertions, 126 deletions
diff --git a/sys/arm/mv/mv_ap806_clock.c b/sys/arm/mv/mv_ap806_clock.c
index 1df07c0d4396..2516ce72d35c 100644
--- a/sys/arm/mv/mv_ap806_clock.c
+++ b/sys/arm/mv/mv_ap806_clock.c
@@ -44,12 +44,14 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/intr.h>
-#include <dev/fdt/simplebus.h>
+#include <dev/extres/clk/clk_fixed.h>
+#include <dev/extres/syscon/syscon.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <dev/extres/clk/clk_fixed.h>
+
+#include "syscon_if.h"
static struct clk_fixed_def ap806_clk_cluster_0 = {
.clkdef.id = 0,
@@ -92,23 +94,19 @@ static struct clk_fixed_def ap806_clk_sdio = {
};
struct mv_ap806_clock_softc {
- struct simplebus_softc simplebus_sc;
device_t dev;
- struct resource *res;
+ struct syscon *syscon;
};
-static struct resource_spec mv_ap806_clock_res_spec[] = {
- { SYS_RES_MEMORY, 0, RF_ACTIVE | RF_SHAREABLE },
- { -1, 0 }
-};
+
static struct ofw_compat_data compat_data[] = {
- {"marvell,ap806-clock", 1},
- {NULL, 0}
+ {"marvell,ap806-clock", 1},
+ {NULL, 0}
};
-#define RD4(sc, reg) bus_read_4((sc)->res, (reg))
-#define WR4(sc, reg, val) bus_write_4((sc)->res, (reg), (val))
+#define RD4(sc, reg) SYSCON_READ_4((sc)->syscon, (reg))
+#define WR4(sc, reg, val) SYSCON_WRITE_4((sc)->syscon, (reg), (val))
static int
mv_ap806_clock_probe(device_t dev)
@@ -135,8 +133,9 @@ mv_ap806_clock_attach(device_t dev)
sc = device_get_softc(dev);
sc->dev = dev;
- if (bus_alloc_resources(dev, mv_ap806_clock_res_spec, &sc->res) != 0) {
- device_printf(dev, "cannot allocate resources for device\n");
+ if (SYSCON_GET_HANDLE(sc->dev, &sc->syscon) != 0 ||
+ sc->syscon == NULL) {
+ device_printf(dev, "cannot get syscon for device\n");
return (ENXIO);
}
@@ -160,7 +159,8 @@ mv_ap806_clock_attach(device_t dev)
clock_freq = 1333000000;
break;
default:
- device_printf(dev, "Cannot guess clock freq with reg %x\n", reg & 0x1f);
+ device_printf(dev, "Cannot guess clock freq with reg %x\n",
+ reg & 0x1f);
return (ENXIO);
break;
};
diff --git a/sys/arm/mv/mv_ap806_gicp.c b/sys/arm/mv/mv_ap806_gicp.c
index 98494e88e65b..c876dda224a5 100644
--- a/sys/arm/mv/mv_ap806_gicp.c
+++ b/sys/arm/mv/mv_ap806_gicp.c
@@ -60,6 +60,7 @@ struct mv_ap806_gicp_softc {
ssize_t spi_ranges_cnt;
uint32_t *spi_ranges;
+ struct intr_map_data_fdt *parent_map_data;
};
static struct ofw_compat_data compat_data[] = {
@@ -96,11 +97,13 @@ mv_ap806_gicp_attach(device_t dev)
/* Look for our parent */
if ((intr_parent = ofw_bus_find_iparent(node)) == 0) {
- device_printf(dev, "Cannot find our parent interrupt controller\n");
+ device_printf(dev,
+ "Cannot find our parent interrupt controller\n");
return (ENXIO);
}
if ((sc->parent = OF_device_from_xref(intr_parent)) == NULL) {
- device_printf(dev, "cannot find parent interrupt controller device\n");
+ device_printf(dev,
+ "cannot find parent interrupt controller device\n");
return (ENXIO);
}
@@ -112,7 +115,10 @@ mv_ap806_gicp_attach(device_t dev)
device_printf(dev, "Cannot register GICP\n");
return (ENXIO);
}
-
+ /* Allocate GIC compatible mapping entry (3 cells) */
+ sc->parent_map_data = (struct intr_map_data_fdt *)intr_alloc_map_data(
+ INTR_MAP_DATA_FDT, sizeof(struct intr_map_data_fdt) +
+ + 3 * sizeof(phandle_t), M_WAITOK | M_ZERO);
OF_device_register_xref(xref, dev);
return (0);
@@ -125,6 +131,45 @@ mv_ap806_gicp_detach(device_t dev)
return (EBUSY);
}
+static struct intr_map_data *
+mv_ap806_gicp_convert_map_data(struct mv_ap806_gicp_softc *sc,
+ struct intr_map_data *data)
+{
+ struct intr_map_data_fdt *daf;
+ uint32_t i, irq_num, irq_type;
+
+ daf = (struct intr_map_data_fdt *)data;
+ if (daf->ncells != 2)
+ return (NULL);
+
+ irq_num = daf->cells[0];
+ irq_type = daf->cells[1];
+ if (irq_num >= MV_AP806_GICP_MAX_NIRQS)
+ return (NULL);
+
+ /* Construct GIC compatible mapping. */
+ sc->parent_map_data->ncells = 3;
+ sc->parent_map_data->cells[0] = 0; /* SPI */
+ sc->parent_map_data->cells[2] = irq_type;
+
+ /* Map the interrupt number to SPI number */
+ for (i = 0; i < sc->spi_ranges_cnt / 2; i += 2) {
+ if (irq_num < sc->spi_ranges[i + 1]) {
+ irq_num += sc->spi_ranges[i];
+ break;
+ }
+
+ irq_num -= sc->spi_ranges[i];
+ }
+
+ sc->parent_map_data->cells[1] = irq_num - 32;
+
+ return ((struct intr_map_data *)sc->parent_map_data);
+}
+
+
+
+
static int
mv_ap806_gicp_activate_intr(device_t dev, struct intr_irqsrc *isrc,
struct resource *res, struct intr_map_data *data)
@@ -132,6 +177,9 @@ mv_ap806_gicp_activate_intr(device_t dev, struct intr_irqsrc *isrc,
struct mv_ap806_gicp_softc *sc;
sc = device_get_softc(dev);
+ data = mv_ap806_gicp_convert_map_data(sc, data);
+ if (data == NULL)
+ return (EINVAL);
return (PIC_ACTIVATE_INTR(sc->parent, isrc, res, data));
}
@@ -161,36 +209,20 @@ mv_ap806_gicp_map_intr(device_t dev, struct intr_map_data *data,
struct intr_irqsrc **isrcp)
{
struct mv_ap806_gicp_softc *sc;
- struct intr_map_data_fdt *daf;
- uint32_t group, irq_num, irq_type;
- int i;
+ int ret;
sc = device_get_softc(dev);
if (data->type != INTR_MAP_DATA_FDT)
return (ENOTSUP);
- daf = (struct intr_map_data_fdt *)data;
- if (daf->ncells != 3 || daf->cells[0] >= MV_AP806_GICP_MAX_NIRQS)
+ data = mv_ap806_gicp_convert_map_data(sc, data);
+ if (data == NULL)
return (EINVAL);
- group = daf->cells[0];
- irq_num = daf->cells[1];
- irq_type = daf->cells[2];
-
- /* Map the interrupt number to spi number */
- for (i = 0; i < sc->spi_ranges_cnt / 2; i += 2) {
- if (irq_num < sc->spi_ranges[i + 1]) {
- irq_num += sc->spi_ranges[i];
- break;
- }
-
- irq_num -= sc->spi_ranges[i];
- }
-
- daf->cells[1] = irq_num - 32;
-
- return (PIC_MAP_INTR(sc->parent, data, isrcp));
+ ret = PIC_MAP_INTR(sc->parent, data, isrcp);
+ (*isrcp)->isrc_dev = sc->dev;
+ return(ret);
}
static int
@@ -201,6 +233,10 @@ mv_ap806_gicp_deactivate_intr(device_t dev, struct intr_irqsrc *isrc,
sc = device_get_softc(dev);
+ data = mv_ap806_gicp_convert_map_data(sc, data);
+ if (data == NULL)
+ return (EINVAL);
+
return (PIC_DEACTIVATE_INTR(sc->parent, isrc, res, data));
}
@@ -211,6 +247,9 @@ mv_ap806_gicp_setup_intr(device_t dev, struct intr_irqsrc *isrc,
struct mv_ap806_gicp_softc *sc;
sc = device_get_softc(dev);
+ data = mv_ap806_gicp_convert_map_data(sc, data);
+ if (data == NULL)
+ return (EINVAL);
return (PIC_SETUP_INTR(sc->parent, isrc, res, data));
}
@@ -222,6 +261,9 @@ mv_ap806_gicp_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
struct mv_ap806_gicp_softc *sc;
sc = device_get_softc(dev);
+ data = mv_ap806_gicp_convert_map_data(sc, data);
+ if (data == NULL)
+ return (EINVAL);
return (PIC_TEARDOWN_INTR(sc->parent, isrc, res, data));
}
diff --git a/sys/arm/mv/mv_ap806_sei.c b/sys/arm/mv/mv_ap806_sei.c
new file mode 100644
index 000000000000..8d3136c2203c
--- /dev/null
+++ b/sys/arm/mv/mv_ap806_sei.c
@@ -0,0 +1,419 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org>
+ *
+ * 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/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/rman.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <machine/resource.h>
+
+#include <dev/fdt/simplebus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include "pic_if.h"
+
+#define MV_AP806_SEI_LOCK(_sc) mtx_lock(&(_sc)->mtx)
+#define MV_AP806_SEI_UNLOCK(_sc) mtx_unlock(&(_sc)->mtx)
+#define MV_AP806_SEI_LOCK_INIT(_sc) mtx_init(&_sc->mtx, \
+ device_get_nameunit(_sc->dev), "mv_ap806_sei", MTX_DEF)
+#define MV_AP806_SEI_LOCK_DESTROY(_sc) mtx_destroy(&_sc->mtx);
+#define MV_AP806_SEI_ASSERT_LOCKED(_sc) mtx_assert(&_sc->mtx, MA_OWNED);
+#define MV_AP806_SEI_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->mtx, MA_NOTOWNED);
+
+#define MV_AP806_SEI_MAX_NIRQS 64
+#define GICP_SECR0 0x00
+#define GICP_SECR1 0x04
+#define GICP_SECR(i) (0x00 + (((i)/32) * 0x4))
+#define GICP_SECR_BIT(i) ((i) % 32)
+#define GICP_SEMR0 0x20
+#define GICP_SEMR1 0x24
+#define GICP_SEMR(i) (0x20 + (((i)/32) * 0x4))
+#define GICP_SEMR_BIT(i) ((i) % 32)
+
+
+
+struct mv_ap806_sei_irqsrc {
+ struct intr_irqsrc isrc;
+ u_int irq;
+};
+
+struct mv_ap806_sei_softc {
+ device_t dev;
+ struct resource *mem_res;
+ struct resource *irq_res;
+ void *irq_ih;
+ struct mtx mtx;
+
+ struct mv_ap806_sei_irqsrc *isrcs;
+};
+
+static struct ofw_compat_data compat_data[] = {
+ {"marvell,ap806-sei", 1},
+ {NULL, 0}
+};
+
+#define RD4(sc, reg) bus_read_4((sc)->mem_res, (reg))
+#define WR4(sc, reg, val) bus_write_4((sc)->mem_res, (reg), (val))
+
+static inline void
+mv_ap806_sei_isrc_mask(struct mv_ap806_sei_softc *sc,
+ struct mv_ap806_sei_irqsrc *sisrc, uint32_t val)
+{
+ uint32_t tmp;
+ int bit;
+
+ bit = GICP_SEMR_BIT(sisrc->irq);
+ MV_AP806_SEI_LOCK(sc);
+ tmp = RD4(sc, GICP_SEMR(sisrc->irq));
+ if (val != 0)
+ tmp |= 1 << bit;
+ else
+ tmp &= ~(1 << bit);
+ WR4(sc, GICP_SEMR(sisrc->irq), tmp);
+ MV_AP806_SEI_UNLOCK(sc);
+}
+
+static inline void
+mv_ap806_sei_isrc_eoi(struct mv_ap806_sei_softc *sc,
+ struct mv_ap806_sei_irqsrc *sisrc)
+{
+
+ WR4(sc, GICP_SECR(sisrc->irq), GICP_SECR_BIT(sisrc->irq));
+}
+
+static void
+mv_ap806_sei_enable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct mv_ap806_sei_softc *sc;
+ struct mv_ap806_sei_irqsrc *sisrc;
+
+ sc = device_get_softc(dev);
+ sisrc = (struct mv_ap806_sei_irqsrc *)isrc;
+ mv_ap806_sei_isrc_mask(sc, sisrc, 0);
+}
+
+static void
+mv_ap806_sei_disable_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct mv_ap806_sei_softc *sc;
+ struct mv_ap806_sei_irqsrc *sisrc;
+
+ sc = device_get_softc(dev);
+ sisrc = (struct mv_ap806_sei_irqsrc *)isrc;
+ mv_ap806_sei_isrc_mask(sc, sisrc, 1);
+}
+
+static int
+mv_ap806_sei_map(device_t dev, struct intr_map_data *data, u_int *irqp)
+{
+ struct mv_ap806_sei_softc *sc;
+ struct intr_map_data_fdt *daf;
+ u_int irq;
+
+ sc = device_get_softc(dev);
+
+ if (data->type != INTR_MAP_DATA_FDT)
+ return (ENOTSUP);
+
+ daf = (struct intr_map_data_fdt *)data;
+ if (daf->ncells != 1 || daf->cells[0] >= MV_AP806_SEI_MAX_NIRQS)
+ return (EINVAL);
+ irq = daf->cells[0];
+ if (irqp != NULL)
+ *irqp = irq;
+
+ return(0);
+}
+
+static int
+mv_ap806_sei_map_intr(device_t dev, struct intr_map_data *data,
+ struct intr_irqsrc **isrcp)
+{
+ struct mv_ap806_sei_softc *sc;
+ u_int irq;
+ int rv;
+
+ sc = device_get_softc(dev);
+ rv = mv_ap806_sei_map(dev, data, &irq);
+ if (rv == 0)
+ *isrcp = &sc->isrcs[irq].isrc;
+
+ return (rv);
+}
+
+
+
+static int
+mv_ap806_sei_setup_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ struct mv_ap806_sei_softc *sc;
+ struct mv_ap806_sei_irqsrc *sisrc;
+ u_int irq;
+ int rv;
+
+ sc = device_get_softc(dev);
+ sisrc = (struct mv_ap806_sei_irqsrc *)isrc;
+ if (data == NULL)
+ return (ENOTSUP);
+ rv = mv_ap806_sei_map(dev, data, &irq);
+ if (rv != 0)
+ return (rv);
+ if (irq != sisrc->irq)
+ return (EINVAL);
+ mv_ap806_sei_isrc_mask(sc, sisrc, 0);
+ return (0);
+}
+
+static int
+mv_ap806_sei_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
+ struct resource *res, struct intr_map_data *data)
+{
+ struct mv_ap806_sei_softc *sc;
+ struct mv_ap806_sei_irqsrc *sisrc;
+
+ sc = device_get_softc(dev);
+ sisrc = (struct mv_ap806_sei_irqsrc *)isrc;
+
+ mv_ap806_sei_isrc_mask(sc, sisrc, 1);
+ return (0);
+}
+
+static void
+mv_ap806_sei_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct mv_ap806_sei_softc *sc;
+ struct mv_ap806_sei_irqsrc *sisrc;
+
+ sc = device_get_softc(dev);
+ sisrc = (struct mv_ap806_sei_irqsrc *)isrc;
+
+ mv_ap806_sei_isrc_mask(sc, sisrc, 1);
+ mv_ap806_sei_isrc_eoi(sc, sisrc);
+}
+
+static void
+mv_ap806_sei_post_ithread(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct mv_ap806_sei_softc *sc;
+ struct mv_ap806_sei_irqsrc *sisrc;
+
+ sc = device_get_softc(dev);
+ sisrc = (struct mv_ap806_sei_irqsrc *)isrc;
+
+ mv_ap806_sei_isrc_mask(sc, sisrc, 1);
+}
+
+static void
+mv_ap806_sei_post_filter(device_t dev, struct intr_irqsrc *isrc)
+{
+ struct mv_ap806_sei_softc *sc;
+ struct mv_ap806_sei_irqsrc *sisrc;
+
+ sc = device_get_softc(dev);
+ sisrc = (struct mv_ap806_sei_irqsrc *)isrc;
+
+ mv_ap806_sei_isrc_mask(sc, sisrc, 1);
+ mv_ap806_sei_isrc_eoi(sc, sisrc);
+}
+
+/* ----------------------------------------------------------------------------
+ *
+ * B u s i n t e r f a c e
+ */
+static int
+mv_ap806_sei_intr(void *arg)
+{
+ struct mv_ap806_sei_softc *sc;
+ struct mv_ap806_sei_irqsrc *sirq;
+ struct trapframe *tf;
+ uint64_t cause;
+ u_int irq;
+
+ sc = (struct mv_ap806_sei_softc *)arg;
+ tf = curthread->td_intr_frame;
+ while (1) {
+ cause = RD4(sc, GICP_SECR1);
+ cause <<= 32;
+ cause |= RD4(sc, GICP_SECR0);
+
+ irq = ffsll(cause);
+ if (irq == 0) break;
+ irq--;
+ sirq = &sc->isrcs[irq];
+ if (intr_isrc_dispatch(&sirq->isrc, tf) != 0) {
+ mv_ap806_sei_isrc_mask(sc, sirq, 0);
+ mv_ap806_sei_isrc_eoi(sc, sirq);
+ device_printf(sc->dev,
+ "Stray irq %u disabled\n", irq);
+ }
+ }
+
+ return (FILTER_HANDLED);
+}
+
+
+static int
+mv_ap806_sei_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Marvell SEI");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+mv_ap806_sei_attach(device_t dev)
+{
+ struct mv_ap806_sei_softc *sc;
+ phandle_t xref, node;
+ uint32_t irq;
+ const char *name;
+ int rv, rid;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ node = ofw_bus_get_node(dev);
+ MV_AP806_SEI_LOCK_INIT(sc);
+
+ /* Allocate resources. */
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL) {
+ device_printf(dev, "Cannot allocate memory resources\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ rid = 0;
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "Cannot allocate IRQ resources\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ /* Mask all interrupts) */
+ WR4(sc, GICP_SEMR0, 0xFFFFFFFF);
+ WR4(sc, GICP_SEMR1, 0xFFFFFFFF);
+
+ /* Create all interrupt sources */
+ sc->isrcs = malloc(sizeof(*sc->isrcs) * MV_AP806_SEI_MAX_NIRQS,
+ M_DEVBUF, M_WAITOK | M_ZERO);
+ name = device_get_nameunit(sc->dev);
+ for (irq = 0; irq < MV_AP806_SEI_MAX_NIRQS; irq++) {
+ sc->isrcs[irq].irq = irq;
+ rv = intr_isrc_register(&sc->isrcs[irq].isrc,
+ sc->dev, 0, "%s,%u", name, irq);
+ if (rv != 0)
+ goto fail; /* XXX deregister ISRCs */
+ }
+ xref = OF_xref_from_node(node);;
+ if (intr_pic_register(dev, xref) == NULL) {
+ device_printf(dev, "Cannot register SEI\n");
+ rv = ENXIO;
+ goto fail;
+ }
+ if (bus_setup_intr(dev, sc->irq_res,INTR_TYPE_MISC | INTR_MPSAFE,
+ mv_ap806_sei_intr, NULL, sc, &sc->irq_ih)) {
+ device_printf(dev,
+ "Unable to register interrupt handler\n");
+ rv = ENXIO;
+ goto fail;
+ }
+
+ OF_device_register_xref(xref, dev);
+ return (0);
+
+fail:
+ if (sc->irq_ih != NULL)
+ bus_teardown_intr(dev, sc->irq_res, sc->irq_ih);
+ if (sc->irq_res != NULL)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ if (sc->mem_res != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res);
+ MV_AP806_SEI_LOCK_DESTROY(sc);
+ return (ENXIO);
+}
+
+static int
+mv_ap806_sei_detach(device_t dev)
+{
+
+ return (EBUSY);
+}
+
+
+static device_method_t mv_ap806_sei_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, mv_ap806_sei_probe),
+ DEVMETHOD(device_attach, mv_ap806_sei_attach),
+ DEVMETHOD(device_detach, mv_ap806_sei_detach),
+
+ /* Interrupt controller interface */
+ DEVMETHOD(pic_disable_intr, mv_ap806_sei_disable_intr),
+ DEVMETHOD(pic_enable_intr, mv_ap806_sei_enable_intr),
+ DEVMETHOD(pic_map_intr, mv_ap806_sei_map_intr),
+ DEVMETHOD(pic_setup_intr, mv_ap806_sei_setup_intr),
+ DEVMETHOD(pic_teardown_intr, mv_ap806_sei_teardown_intr),
+ DEVMETHOD(pic_post_filter, mv_ap806_sei_post_filter),
+ DEVMETHOD(pic_post_ithread, mv_ap806_sei_post_ithread),
+ DEVMETHOD(pic_pre_ithread, mv_ap806_sei_pre_ithread),
+
+ DEVMETHOD_END
+};
+
+static devclass_t mv_ap806_sei_devclass;
+
+static driver_t mv_ap806_sei_driver = {
+ "mv_ap806_sei",
+ mv_ap806_sei_methods,
+ sizeof(struct mv_ap806_sei_softc),
+};
+
+EARLY_DRIVER_MODULE(mv_ap806_sei, simplebus, mv_ap806_sei_driver,
+ mv_ap806_sei_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_MIDDLE);
diff --git a/sys/arm/mv/mv_cp110_clock.c b/sys/arm/mv/mv_cp110_clock.c
index 06165f3e8441..753dfaa045f6 100644
--- a/sys/arm/mv/mv_cp110_clock.c
+++ b/sys/arm/mv/mv_cp110_clock.c
@@ -44,17 +44,17 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/intr.h>
-#include <dev/fdt/simplebus.h>
+#include <dev/extres/clk/clk_fixed.h>
+#include <dev/extres/clk/clk_gate.h>
+#include <dev/extres/syscon/syscon.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <dev/extres/clk/clk_fixed.h>
-#include <dev/extres/clk/clk_gate.h>
-
#include <arm/mv/mv_cp110_clock.h>
#include "clkdev_if.h"
+#include "syscon_if.h"
/* Clocks */
static struct clk_fixed_def cp110_clk_pll_0 = {
@@ -126,24 +126,19 @@ static struct cp110_gate cp110_gates[] = {
};
struct mv_cp110_clock_softc {
- struct simplebus_softc simplebus_sc;
device_t dev;
- struct resource *res;
+ struct syscon *syscon;
struct mtx mtx;
};
-static struct resource_spec mv_cp110_clock_res_spec[] = {
- { SYS_RES_MEMORY, 0, RF_ACTIVE | RF_SHAREABLE },
- { -1, 0 }
-};
static struct ofw_compat_data compat_data[] = {
{"marvell,cp110-clock", 1},
{NULL, 0}
};
-#define RD4(sc, reg) bus_read_4((sc)->res, (reg))
-#define WR4(sc, reg, val) bus_write_4((sc)->res, (reg), (val))
+#define RD4(sc, reg) SYSCON_READ_4((sc)->syscon, (reg))
+#define WR4(sc, reg, val) SYSCON_WRITE_4((sc)->syscon, (reg), (val))
static char *
mv_cp110_clock_name(device_t dev, const char *name)
@@ -201,8 +196,9 @@ mv_cp110_clock_attach(device_t dev)
sc = device_get_softc(dev);
sc->dev = dev;
- if (bus_alloc_resources(dev, mv_cp110_clock_res_spec, &sc->res) != 0) {
- device_printf(dev, "cannot allocate resources for device\n");
+ if (SYSCON_GET_HANDLE(sc->dev, &sc->syscon) != 0 ||
+ sc->syscon == NULL) {
+ device_printf(dev, "cannot get syscon for device\n");
return (ENXIO);
}
diff --git a/sys/arm/mv/mv_cp110_icu.c b/sys/arm/mv/mv_cp110_icu.c
index 4d62670e3a68..e168b141d9e0 100644
--- a/sys/arm/mv/mv_cp110_icu.c
+++ b/sys/arm/mv/mv_cp110_icu.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <gnu/dts/include/dt-bindings/interrupt-controller/irq.h>
#include "pic_if.h"
#define ICU_GRP_NSR 0x0
@@ -72,6 +73,7 @@ struct mv_cp110_icu_softc {
device_t dev;
device_t parent;
struct resource *res;
+ struct intr_map_data_fdt *parent_map_data;
};
static struct resource_spec mv_cp110_icu_res_spec[] = {
@@ -80,8 +82,9 @@ static struct resource_spec mv_cp110_icu_res_spec[] = {
};
static struct ofw_compat_data compat_data[] = {
- {"marvell,cp110-icu", 1},
- {NULL, 0}
+ {"marvell,cp110-icu-nsr", 1},
+ {"marvell,cp110-icu-sei", 2},
+ {NULL, 0}
};
#define RD4(sc, reg) bus_read_4((sc)->res, (reg))
@@ -130,6 +133,11 @@ mv_cp110_icu_attach(device_t dev)
device_printf(dev, "Cannot register ICU\n");
goto fail;
}
+
+ /* Allocate GICP compatible mapping entry (2 cells) */
+ sc->parent_map_data = (struct intr_map_data_fdt *)intr_alloc_map_data(
+ INTR_MAP_DATA_FDT, sizeof(struct intr_map_data_fdt) +
+ + 3 * sizeof(phandle_t), M_WAITOK | M_ZERO);
return (0);
fail:
@@ -137,6 +145,35 @@ fail:
return (ENXIO);
}
+static struct intr_map_data *
+mv_cp110_icu_convert_map_data(struct mv_cp110_icu_softc *sc, struct intr_map_data *data)
+{
+ struct intr_map_data_fdt *daf;
+ uint32_t reg, irq_no, irq_type;
+
+ daf = (struct intr_map_data_fdt *)data;
+ if (daf->ncells != 2)
+ return (NULL);
+ irq_no = daf->cells[0];
+ irq_type = daf->cells[1];
+ if (irq_no >= MV_CP110_ICU_MAX_NIRQS)
+ return (NULL);
+ if (irq_type != IRQ_TYPE_LEVEL_HIGH &&
+ irq_type != IRQ_TYPE_EDGE_RISING)
+ return (NULL);
+
+ /* We rely on fact that ICU->GIC mapping is preset by bootstrap. */
+ reg = RD4(sc, ICU_INT_CFG(irq_no));
+
+ /* Construct GICP compatible mapping. */
+ sc->parent_map_data->ncells = 2;
+ sc->parent_map_data->cells[0] = reg & ICU_INT_MASK;
+ sc->parent_map_data->cells[1] = irq_type;
+
+ return ((struct intr_map_data *)sc->parent_map_data);
+}
+
+
static int
mv_cp110_icu_detach(device_t dev)
{
@@ -151,7 +188,9 @@ mv_cp110_icu_activate_intr(device_t dev, struct intr_irqsrc *isrc,
struct mv_cp110_icu_softc *sc;
sc = device_get_softc(dev);
-
+ data = mv_cp110_icu_convert_map_data(sc, data);
+ if (data == NULL)
+ return (EINVAL);
return (PIC_ACTIVATE_INTR(sc->parent, isrc, res, data));
}
@@ -159,7 +198,6 @@ static void
mv_cp110_icu_enable_intr(device_t dev, struct intr_irqsrc *isrc)
{
struct mv_cp110_icu_softc *sc;
-
sc = device_get_softc(dev);
PIC_ENABLE_INTR(sc->parent, isrc);
@@ -175,32 +213,43 @@ mv_cp110_icu_disable_intr(device_t dev, struct intr_irqsrc *isrc)
PIC_DISABLE_INTR(sc->parent, isrc);
}
+
+
static int
mv_cp110_icu_map_intr(device_t dev, struct intr_map_data *data,
struct intr_irqsrc **isrcp)
{
struct mv_cp110_icu_softc *sc;
struct intr_map_data_fdt *daf;
- uint32_t reg;
+ uint32_t reg, irq_no, irq_type;
+ int ret;
sc = device_get_softc(dev);
if (data->type != INTR_MAP_DATA_FDT)
return (ENOTSUP);
+ /* Parse original */
daf = (struct intr_map_data_fdt *)data;
- if (daf->ncells != 3 || daf->cells[0] >= MV_CP110_ICU_MAX_NIRQS)
+ if (daf->ncells != 2)
+ return (EINVAL);
+ irq_no = daf->cells[0];
+ irq_type = daf->cells[1];
+ data = mv_cp110_icu_convert_map_data(sc, data);
+ if (data == NULL)
return (EINVAL);
- reg = RD4(sc, ICU_INT_CFG(daf->cells[1]));
-
- if ((reg & ICU_INT_ENABLE) == 0) {
- reg |= ICU_INT_ENABLE;
- WR4(sc, ICU_INT_CFG(daf->cells[1]), reg);
- }
+ reg = RD4(sc, ICU_INT_CFG(irq_no));
+ reg |= ICU_INT_ENABLE;
+ if (irq_type == IRQ_TYPE_LEVEL_HIGH)
+ reg &= ~ICU_INT_EDGE;
+ else
+ reg |= ICU_INT_EDGE;
+ WR4(sc, ICU_INT_CFG(irq_no), reg);
- daf->cells[1] = reg & ICU_INT_MASK;
- return (PIC_MAP_INTR(sc->parent, data, isrcp));
+ ret = PIC_MAP_INTR(sc->parent, data, isrcp);
+ (*isrcp)->isrc_dev = sc->dev;
+ return (ret);
}
static int
@@ -210,6 +259,9 @@ mv_cp110_icu_deactivate_intr(device_t dev, struct intr_irqsrc *isrc,
struct mv_cp110_icu_softc *sc;
sc = device_get_softc(dev);
+ data = mv_cp110_icu_convert_map_data(sc, data);
+ if (data == NULL)
+ return (EINVAL);
return (PIC_DEACTIVATE_INTR(sc->parent, isrc, res, data));
}
@@ -221,6 +273,9 @@ mv_cp110_icu_setup_intr(device_t dev, struct intr_irqsrc *isrc,
struct mv_cp110_icu_softc *sc;
sc = device_get_softc(dev);
+ data = mv_cp110_icu_convert_map_data(sc, data);
+ if (data == NULL)
+ return (EINVAL);
return (PIC_SETUP_INTR(sc->parent, isrc, res, data));
}
@@ -232,6 +287,9 @@ mv_cp110_icu_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
struct mv_cp110_icu_softc *sc;
sc = device_get_softc(dev);
+ data = mv_cp110_icu_convert_map_data(sc, data);
+ if (data == NULL)
+ return (EINVAL);
return (PIC_TEARDOWN_INTR(sc->parent, isrc, res, data));
}
@@ -295,5 +353,5 @@ static driver_t mv_cp110_icu_driver = {
sizeof(struct mv_cp110_icu_softc),
};
-EARLY_DRIVER_MODULE(mv_cp110_icu, simplebus, mv_cp110_icu_driver,
+EARLY_DRIVER_MODULE(mv_cp110_icu, mv_cp110_icu_bus, mv_cp110_icu_driver,
mv_cp110_icu_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST);
diff --git a/sys/arm/mv/mv_cp110_icu_bus.c b/sys/arm/mv/mv_cp110_icu_bus.c
new file mode 100644
index 000000000000..c1c5f4ae7891
--- /dev/null
+++ b/sys/arm/mv/mv_cp110_icu_bus.c
@@ -0,0 +1,78 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org>
+ * All rights reserved.
+ *
+ * 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/kernel.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <machine/bus.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/extres/syscon/syscon.h>
+#include <dev/fdt/simple_mfd.h>
+
+static struct ofw_compat_data compat_data[] = {
+ {"marvell,cp110-icu", 1},
+ {NULL, 0}
+};
+
+static int
+mv_cp110_icu_bus_probe(device_t dev)
+{
+
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+ if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "Marvell Interrupt Consolidation Unit Bus");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static device_method_t mv_cp110_icu_bus_methods[] = {
+ DEVMETHOD(device_probe, mv_cp110_icu_bus_probe),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(mv_cp110_icu_bus, mv_cp110_icu_bus_driver,
+ mv_cp110_icu_bus_methods, sizeof(struct simple_mfd_softc),
+ simple_mfd_driver);
+
+static devclass_t mv_cp110_icu_bus_devclass;
+EARLY_DRIVER_MODULE(mv_cp110_icu_bus, simplebus, mv_cp110_icu_bus_driver,
+ mv_cp110_icu_bus_devclass, 0, 0, BUS_PASS_INTERRUPT);
+MODULE_VERSION(mv_cp110_icu_bus, 1);
diff --git a/sys/arm/mv/mv_thermal.c b/sys/arm/mv/mv_thermal.c
index 60eb854ac046..e8ddd045ffa6 100644
--- a/sys/arm/mv/mv_thermal.c
+++ b/sys/arm/mv/mv_thermal.c
@@ -44,13 +44,14 @@ __FBSDID("$FreeBSD$");
#include <machine/bus.h>
#include <machine/resource.h>
#include <machine/intr.h>
-
-#include <dev/fdt/simplebus.h>
+#include <dev/extres/syscon/syscon.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#define CONTROL0 0x00
+#include "syscon_if.h"
+
+#define CONTROL0 0 /* Offset in config->regs[] array */
#define CONTROL0_TSEN_START (1 << 0)
#define CONTROL0_TSEN_RESET (1 << 1)
#define CONTROL0_TSEN_EN (1 << 2)
@@ -62,12 +63,12 @@ __FBSDID("$FreeBSD$");
#define CONTROL0_MODE_EXTERNAL 0x2
#define CONTROL0_MODE_MASK 0x3
-#define CONTROL1 0x04
+#define CONTROL1 1 /* Offset in config->regs[] array */
/* This doesn't seems to work */
#define CONTROL1_TSEN_SENS_SHIFT 21
#define CONTROL1_TSEN_SENS_MASK 0x7
-#define STATUS 0x00
+#define STATUS 2 /* Offset in config->regs[] array */
#define STATUS_TEMP_MASK 0x3FF
enum mv_thermal_type {
@@ -77,6 +78,7 @@ enum mv_thermal_type {
struct mv_thermal_config {
enum mv_thermal_type type;
+ int regs[3];
int ncpus;
int64_t calib_mul;
int64_t calib_add;
@@ -87,15 +89,16 @@ struct mv_thermal_config {
struct mv_thermal_softc {
device_t dev;
- struct resource *res[2];
+ struct syscon *syscon;
struct mtx mtx;
- struct mv_thermal_config *config;
- int cur_sensor;
+ struct mv_thermal_config *config;
+ int cur_sensor;
};
static struct mv_thermal_config mv_ap806_config = {
.type = MV_AP806,
+ .regs = {0x84, 0x88, 0x8C},
.ncpus = 4,
.calib_mul = 423,
.calib_add = -150000,
@@ -106,6 +109,7 @@ static struct mv_thermal_config mv_ap806_config = {
static struct mv_thermal_config mv_cp110_config = {
.type = MV_CP110,
+ .regs = {0x70, 0x74, 0x78},
.calib_mul = 2000096,
.calib_add = 1172499100,
.calib_div = 420100,
@@ -113,22 +117,16 @@ static struct mv_thermal_config mv_cp110_config = {
.signed_value = false,
};
-static struct resource_spec mv_thermal_res_spec[] = {
- { SYS_RES_MEMORY, 0, RF_ACTIVE },
- { SYS_RES_MEMORY, 1, RF_ACTIVE },
- { -1, 0 }
-};
-
static struct ofw_compat_data compat_data[] = {
{"marvell,armada-ap806-thermal", (uintptr_t) &mv_ap806_config},
{"marvell,armada-cp110-thermal", (uintptr_t) &mv_cp110_config},
{NULL, 0}
};
-#define RD_STA(sc, reg) bus_read_4((sc)->res[0], (reg))
-#define WR_STA(sc, reg, val) bus_write_4((sc)->res[0], (reg), (val))
-#define RD_CON(sc, reg) bus_read_4((sc)->res[1], (reg))
-#define WR_CON(sc, reg, val) bus_write_4((sc)->res[1], (reg), (val))
+#define RD4(sc, reg) \
+ SYSCON_READ_4((sc)->syscon, sc->config->regs[reg])
+#define WR4(sc, reg, val) \
+ SYSCON_WRITE_4((sc)->syscon, sc->config->regs[reg], (val))
static inline int32_t sign_extend(uint32_t value, int index)
{
@@ -146,7 +144,7 @@ mv_thermal_wait_sensor(struct mv_thermal_softc *sc)
timeout = 100000;
while (--timeout > 0) {
- reg = RD_STA(sc, STATUS);
+ reg = RD4(sc, STATUS);
if ((reg & sc->config->valid_mask) == sc->config->valid_mask)
break;
DELAY(100);
@@ -167,12 +165,12 @@ mv_thermal_select_sensor(struct mv_thermal_softc *sc, int sensor)
return (0);
/* Stop the current reading and reset the module */
- reg = RD_CON(sc, CONTROL0);
+ reg = RD4(sc, CONTROL0);
reg &= ~(CONTROL0_TSEN_START | CONTROL0_TSEN_EN);
- WR_CON(sc, CONTROL0, reg);
+ WR4(sc, CONTROL0, reg);
/* Switch to the selected sensor */
- /*
+ /*
* NOTE : Datasheet says to use CONTROL1 for selecting
* but when doing so the sensors >0 are never ready
* Do what Linux does using undocumented bits in CONTROL0
@@ -185,13 +183,13 @@ mv_thermal_select_sensor(struct mv_thermal_softc *sc, int sensor)
reg &= ~(CONTROL0_CHANNEL_MASK << CONTROL0_CHANNEL_SHIFT);
reg |= (sensor - 1) << CONTROL0_CHANNEL_SHIFT;
}
- WR_CON(sc, CONTROL0, reg);
+ WR4(sc, CONTROL0, reg);
sc->cur_sensor = sensor;
/* Start the reading */
- reg = RD_CON(sc, CONTROL0);
+ reg = RD4(sc, CONTROL0);
reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_EN;
- WR_CON(sc, CONTROL0, reg);
+ WR4(sc, CONTROL0, reg);
return (mv_thermal_wait_sensor(sc));
}
@@ -206,7 +204,7 @@ mv_thermal_read_sensor(struct mv_thermal_softc *sc, int sensor, int *temp)
if (rv != 0)
return (rv);
- reg = RD_STA(sc, STATUS) & STATUS_TEMP_MASK;
+ reg = RD4(sc, STATUS) & STATUS_TEMP_MASK;
if (sc->config->signed_value)
sample = sign_extend(reg, fls(STATUS_TEMP_MASK) - 1);
@@ -225,14 +223,14 @@ ap806_init(struct mv_thermal_softc *sc)
uint32_t reg;
/* Start the temp capture/conversion */
- reg = RD_CON(sc, CONTROL0);
+ reg = RD4(sc, CONTROL0);
reg &= ~CONTROL0_TSEN_RESET;
reg |= CONTROL0_TSEN_START | CONTROL0_TSEN_EN;
/* Sample every ~2ms */
reg |= CONTROL0_OSR_MAX << CONTROL0_OSR_SHIFT;
- WR_CON(sc, CONTROL0, reg);
+ WR4(sc, CONTROL0, reg);
/* Since we just started the module wait for the sensor to be ready */
mv_thermal_wait_sensor(sc);
@@ -245,15 +243,15 @@ cp110_init(struct mv_thermal_softc *sc)
{
uint32_t reg;
- reg = RD_CON(sc, CONTROL1);
+ reg = RD4(sc, CONTROL1);
reg &= (1 << 7);
reg |= (1 << 8);
- WR_CON(sc, CONTROL1, reg);
+ WR4(sc, CONTROL1, reg);
/* Sample every ~2ms */
- reg = RD_CON(sc, CONTROL0);
+ reg = RD4(sc, CONTROL0);
reg |= CONTROL0_OSR_MAX << CONTROL0_OSR_SHIFT;
- WR_CON(sc, CONTROL0, reg);
+ WR4(sc, CONTROL0, reg);
return (0);
}
@@ -300,19 +298,24 @@ mv_thermal_attach(device_t dev)
struct mv_thermal_softc *sc;
struct sysctl_ctx_list *ctx;
struct sysctl_oid_list *oid;
+ phandle_t node;
char name[255];
char desc[255];
int i;
sc = device_get_softc(dev);
sc->dev = dev;
+ node = ofw_bus_get_node(dev);
- sc->config = (struct mv_thermal_config *)ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+ sc->config = (struct mv_thermal_config *)
+ ofw_bus_search_compatible(dev, compat_data)->ocd_data;
mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
- if (bus_alloc_resources(dev, mv_thermal_res_spec, sc->res) != 0) {
- device_printf(dev, "cannot allocate resources for device\n");
+
+ if (SYSCON_GET_HANDLE(sc->dev, &sc->syscon) != 0 ||
+ sc->syscon == NULL) {
+ device_printf(dev, "cannot get syscon for device\n");
return (ENXIO);
}
@@ -355,8 +358,6 @@ mv_thermal_detach(device_t dev)
sc = device_get_softc(dev);
- bus_release_resources(dev, mv_thermal_res_spec, sc->res);
-
return (0);
}
diff --git a/sys/arm/mv/mvebu_pinctrl.c b/sys/arm/mv/mvebu_pinctrl.c
index 3b183dc87674..1f9df8fbf3b6 100644
--- a/sys/arm/mv/mvebu_pinctrl.c
+++ b/sys/arm/mv/mvebu_pinctrl.c
@@ -44,14 +44,14 @@ __FBSDID("$FreeBSD$");
#include <machine/resource.h>
#include <machine/intr.h>
-#include <dev/fdt/simplebus.h>
+#include <dev/extres/syscon/syscon.h>
+
+#include <dev/fdt/fdt_pinctrl.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
-#include <dev/fdt/fdt_pinctrl.h>
-
-#include "opt_soc.h"
+#include "syscon_if.h"
#define PINS_PER_REG 8
#define BITS_PER_PIN 4
@@ -68,7 +68,6 @@ struct mv_padconf {
size_t npins;
};
-#ifdef SOC_MARVELL_8K
const static struct mv_pins ap806_pins[] = {
{"mpp0", {"gpio", "sdio", NULL, "spi0"}},
{"mpp1", {"gpio", "sdio", NULL, "spi0"}},
@@ -96,29 +95,22 @@ const struct mv_padconf ap806_padconf = {
.npins = nitems(ap806_pins),
.pins = ap806_pins,
};
-#endif
struct mv_pinctrl_softc {
device_t dev;
- struct resource *res;
+ struct syscon *syscon;
struct mv_padconf *padconf;
};
-static struct resource_spec mv_pinctrl_res_spec[] = {
- { SYS_RES_MEMORY, 0, RF_ACTIVE | RF_SHAREABLE },
- { -1, 0 }
-};
static struct ofw_compat_data compat_data[] = {
-#ifdef SOC_MARVELL_8K
{"marvell,ap806-pinctrl", (uintptr_t)&ap806_padconf},
-#endif
{NULL, 0}
};
-#define RD4(sc, reg) bus_read_4((sc)->res, (reg))
-#define WR4(sc, reg, val) bus_write_4((sc)->res, (reg), (val))
+#define RD4(sc, reg) SYSCON_READ_4((sc)->syscon, (reg))
+#define WR4(sc, reg, val) SYSCON_WRITE_4((sc)->syscon, (reg), (val))
static void
mv_pinctrl_configure_pin(struct mv_pinctrl_softc *sc, uint32_t pin,
@@ -200,10 +192,12 @@ mv_pinctrl_attach(device_t dev)
sc = device_get_softc(dev);
sc->dev = dev;
- sc->padconf = (struct mv_padconf *)ofw_bus_search_compatible(dev, compat_data)->ocd_data;
+ sc->padconf = (struct mv_padconf *)
+ ofw_bus_search_compatible(dev,compat_data)->ocd_data;
- if (bus_alloc_resources(dev, mv_pinctrl_res_spec, &sc->res) != 0) {
- device_printf(dev, "cannot allocate resources for device\n");
+ if (SYSCON_GET_HANDLE(sc->dev, &sc->syscon) != 0 ||
+ sc->syscon == NULL) {
+ device_printf(dev, "cannot get syscon for device\n");
return (ENXIO);
}
diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC
index 33e2bbf1ecc1..96db964b68c7 100644
--- a/sys/arm64/conf/GENERIC
+++ b/sys/arm64/conf/GENERIC
@@ -260,6 +260,7 @@ device aw_ccu # Allwinner clock controller
device aw_nmi # Allwinner NMI support
device mv_cp110_icu # Marvell CP110 ICU
device mv_ap806_gicp # Marvell AP806 GICP
+device mv_ap806_sei # Marvell AP806 SEI
# Real-time clock support
device aw_rtc # Allwinner Real-time Clock
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
index e8b724708e9b..ac05e28b77e6 100644
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -105,12 +105,15 @@ 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/a37x0_gpio.c optional a37x0_gpio gpio fdt
+arm/mv/armada38x/armada38x_rtc.c optional mv_rtc fdt
arm/mv/gpio.c optional mv_gpio fdt
arm/mv/mvebu_pinctrl.c optional mvebu_pinctrl fdt
-arm/mv/mv_cp110_icu.c optional mv_cp110_icu fdt
-arm/mv/mv_ap806_gicp.c optional mv_ap806_gicp fdt
arm/mv/mv_ap806_clock.c optional SOC_MARVELL_8K fdt
+arm/mv/mv_ap806_gicp.c optional mv_ap806_gicp fdt
+arm/mv/mv_ap806_sei.c optional mv_ap806_sei fdt
arm/mv/mv_cp110_clock.c optional SOC_MARVELL_8K fdt
+arm/mv/mv_cp110_icu.c optional mv_cp110_icu fdt
+arm/mv/mv_cp110_icu_bus.c optional mv_cp110_icu fdt
arm/mv/mv_thermal.c optional SOC_MARVELL_8K mv_thermal fdt
arm/mv/armada38x/armada38x_rtc.c optional mv_rtc fdt
arm/xilinx/uart_dev_cdnc.c optional uart soc_xilinx_zynq