summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/fdt/files.fdt21
-rw-r--r--sys/dev/fdt/sunxireg.h140
-rw-r--r--sys/dev/fdt/sxiccmu.c792
-rw-r--r--sys/dev/fdt/sxiccmu_clocks.h180
-rw-r--r--sys/dev/fdt/sxiehci.c320
-rw-r--r--sys/dev/fdt/sximmc.c1099
-rw-r--r--sys/dev/fdt/sxipio.c452
-rw-r--r--sys/dev/fdt/sxipio_pins.h5756
-rw-r--r--sys/dev/fdt/sxipiovar.h45
-rw-r--r--sys/dev/fdt/sxirtc.c184
10 files changed, 8988 insertions, 1 deletions
diff --git a/sys/dev/fdt/files.fdt b/sys/dev/fdt/files.fdt
index bb184da34e8..e96b7100b5c 100644
--- a/sys/dev/fdt/files.fdt
+++ b/sys/dev/fdt/files.fdt
@@ -1,4 +1,4 @@
-# $OpenBSD: files.fdt,v 1.1 2017/01/03 19:57:01 kettenis Exp $
+# $OpenBSD: files.fdt,v 1.2 2017/01/21 08:26:49 patrick Exp $
#
# Config file and device description for machine-independent FDT code.
# Included by ports that need it.
@@ -6,3 +6,22 @@
device simplefb: wsemuldisplaydev, rasops15, rasops16, rasops24, rasops32
attach simplefb at fdt
file dev/fdt/simplefb.c simplefb
+
+device sxiccmu
+attach sxiccmu at fdt
+file dev/fdt/sxiccmu.c sxiccmu
+
+device sxipio {}: gpiobus
+attach sxipio at fdt
+file dev/fdt/sxipio.c sxipio
+
+device sxirtc
+attach sxirtc at fdt
+file dev/fdt/sxirtc.c sxirtc
+
+device sximmc: sdmmcbus
+attach sximmc at fdt
+file dev/fdt/sximmc.c sximmc
+
+attach ehci at fdt with sxiehci
+file dev/fdt/sxiehci.c sxiehci
diff --git a/sys/dev/fdt/sunxireg.h b/sys/dev/fdt/sunxireg.h
new file mode 100644
index 00000000000..83426392517
--- /dev/null
+++ b/sys/dev/fdt/sunxireg.h
@@ -0,0 +1,140 @@
+/* $OpenBSD: sunxireg.h,v 1.1 2017/01/21 08:26:49 patrick Exp $ */
+/*
+ * Copyright (c) 2013 Artturi Alm
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define SXIREAD1(sc, reg) \
+ (bus_space_read_1((sc)->sc_iot, (sc)->sc_ioh, (reg)))
+#define SXIWRITE1(sc, reg, val) \
+ bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+#define SXISET1(sc, reg, bits) \
+ SXIWRITE1((sc), (reg), SXIREAD1((sc), (reg)) | (bits))
+#define SXICLR1(sc, reg, bits) \
+ SXIWRITE1((sc), (reg), SXIREAD1((sc), (reg)) & ~(bits))
+#define SXICMS1(sc, reg, mask, bits) \
+ SXIWRITE1((sc), (reg), (SXIREAD1((sc), (reg)) & ~(mask)) | (bits))
+
+#define SXIREAD4(sc, reg) \
+ (bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (reg)))
+#define SXIWRITE4(sc, reg, val) \
+ bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (reg), (val))
+#define SXISET4(sc, reg, bits) \
+ SXIWRITE4((sc), (reg), SXIREAD4((sc), (reg)) | (bits))
+#define SXICLR4(sc, reg, bits) \
+ SXIWRITE4((sc), (reg), SXIREAD4((sc), (reg)) & ~(bits))
+#define SXICMS4(sc, reg, mask, bits) \
+ SXIWRITE4((sc), (reg), (SXIREAD4((sc), (reg)) & ~(mask)) | (bits))
+
+#define TIMER0_FREQUENCY (24000000)
+#define TIMER1_FREQUENCY (24000000)
+#define TIMER2_FREQUENCY (24000000)
+#define COUNTER_FREQUENCY (24000000)
+
+/* SRAM Controller / System Control */
+#define SYSCTRL_ADDR 0x01c00000
+#define SYSCTRL_SIZE 0x1000
+
+#define DMAC_ADDR 0x01c02000
+#define DMAC_SIZE 0x1000
+#define DMAC_IRQ 27
+
+#define SDMMC0_ADDR 0x01c0f000
+#define SDMMCx_SIZE 0x1000
+#define SDMMC0_IRQ 32
+
+#define SATA_ADDR 0x01c18000
+#define SATA_SIZE 0x1000
+#define SATA_IRQ 56
+
+#define TIMER_ADDR 0x01c20c00
+#define TIMERx_SIZE 0x200
+#define TIMER0_IRQ 22
+#define TIMER1_IRQ 23
+#define TIMER2_IRQ 24
+#define STATTIMER_IRQ TIMER1_IRQ /* XXX */
+
+#define WDOG_ADDR 0x01c20c90
+#define WDOG_SIZE 0x08
+#define WDOG_IRQ 24
+
+#define RTC_ADDR 0x01c20d00
+#define RTC_SIZE 0x20
+
+/* Clock Control Module/Unit */
+#define CCMU_ADDR 0x01c20000
+#define CCMU_SIZE 0x400
+
+#define PIO_ADDR 0x01c20800
+#define PIOx_SIZE 0x400
+#define PIO_IRQ 28
+
+/* Secure ID */
+#define SID_ADDR 0x01c23800
+#define SID_SIZE 0x400
+
+#define UARTx_SIZE 0x400
+#define UART0_ADDR 0x01c28000
+#define UART1_ADDR 0x01c28400
+#define UART2_ADDR 0x01c28800
+#define UART3_ADDR 0x01c28c00
+#define UART4_ADDR 0x01c29000
+#define UART5_ADDR 0x01c29400
+#define UART6_ADDR 0x01c29800
+#define UART7_ADDR 0x01c29c00
+#define UART0_IRQ 1
+#define UART1_IRQ 2
+#define UART2_IRQ 3
+#define UART3_IRQ 4
+#define UART4_IRQ 17
+#define UART5_IRQ 18
+#define UART6_IRQ 19
+#define UART7_IRQ 20
+
+#define USB0_ADDR 0x01c13000 /* usb otg */
+#define USB1_ADDR 0x01c14000 /* first port up from pcb */
+#define USB2_ADDR 0x01c1c000 /* 'top port' == above USB1 */
+#define USBx_SIZE 0x1000
+#define USB0_IRQ 38
+#define USB1_IRQ 39
+#define USB2_IRQ 40
+
+/* Ethernet MAC Controller */
+#define EMAC_ADDR 0x01c0b000
+#define EMAC_SIZE 0x1000
+#define EMAC_IRQ 55
+#define SXIESRAM_ADDR 0x00008000 /* combined area for EMAC fifos */
+#define SXIESRAM_SIZE 0x4000
+
+/* Security System */
+#define SS_ADDR 0x01c15000
+#define SS_SIZE 0x1000
+#define SS_IRQ 54
+
+/* GMAC */
+#define GMAC_ADDR 0x01c50000
+#define GMAC_SIZE 0x10000
+#define GMAC_IRQ 85
+
+/* A1x / Cortex-A8 */
+#define INTC_ADDR 0x01c20400
+#define INTC_SIZE 0x400
+
+/* A20 / Cortex-A7 */
+#define GIC_ADDR 0x01c80000 /* = periphbase */
+#define GIC_SIZE 0x8000
+#define CPUCONFG_ADDR 0x01c25c00 /* not in use */
+#define CPUCONFG_SIZE 0x200
+#define CPUCNTRS_ADDR 0x01c25e00 /* used by sxitimer */
+#define CPUCNTRS_SIZE 0x200
diff --git a/sys/dev/fdt/sxiccmu.c b/sys/dev/fdt/sxiccmu.c
new file mode 100644
index 00000000000..3d21773ac10
--- /dev/null
+++ b/sys/dev/fdt/sxiccmu.c
@@ -0,0 +1,792 @@
+/* $OpenBSD: sxiccmu.c,v 1.1 2017/01/21 08:26:49 patrick Exp $ */
+/*
+ * Copyright (c) 2007,2009 Dale Rahn <drahn@openbsd.org>
+ * Copyright (c) 2013 Artturi Alm
+ * Copyright (c) 2016 Mark Kettenis <kettenis@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/time.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#include <dev/fdt/sunxireg.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_clock.h>
+#include <dev/ofw/fdt.h>
+
+#ifdef DEBUG_CCMU
+#define DPRINTF(x) do { printf x; } while (0)
+#else
+#define DPRINTF(x)
+#endif
+
+struct sxiccmu_ccu_bit {
+ uint16_t reg;
+ uint8_t bit;
+ uint8_t parent;
+};
+
+#include "sxiccmu_clocks.h"
+
+struct sxiccmu_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
+ struct sxiccmu_ccu_bit *sc_gates;
+ int sc_ngates;
+ struct clock_device sc_cd;
+
+ struct sxiccmu_ccu_bit *sc_resets;
+ int sc_nresets;
+ struct reset_device sc_rd;
+
+ uint32_t (*sc_get_frequency)(struct sxiccmu_softc *,
+ uint32_t);
+ int (*sc_set_frequency)(struct sxiccmu_softc *,
+ uint32_t, uint32_t);
+};
+
+int sxiccmu_match(struct device *, void *, void *);
+void sxiccmu_attach(struct device *, struct device *, void *);
+
+struct cfattach sxiccmu_ca = {
+ sizeof (struct sxiccmu_softc), sxiccmu_match, sxiccmu_attach
+};
+
+struct cfdriver sxiccmu_cd = {
+ NULL, "sxiccmu", DV_DULL
+};
+
+void sxiccmu_attach_clock(struct sxiccmu_softc *, int);
+
+uint32_t sxiccmu_ccu_get_frequency(void *, uint32_t *);
+int sxiccmu_ccu_set_frequency(void *, uint32_t *, uint32_t);
+void sxiccmu_ccu_enable(void *, uint32_t *, int);
+void sxiccmu_ccu_reset(void *, uint32_t *, int);
+
+uint32_t sxiccmu_a64_get_frequency(struct sxiccmu_softc *, uint32_t);
+int sxiccmu_a64_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
+uint32_t sxiccmu_h3_get_frequency(struct sxiccmu_softc *, uint32_t);
+int sxiccmu_h3_set_frequency(struct sxiccmu_softc *, uint32_t, uint32_t);
+
+int
+sxiccmu_match(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+
+ if (faa->fa_node == OF_finddevice("/clocks")) {
+ int node = OF_parent(faa->fa_node);
+
+ return (OF_is_compatible(node, "allwinner,sun4i-a10") ||
+ OF_is_compatible(node, "allwinner,sun5i-a10s") ||
+ OF_is_compatible(node, "allwinner,sun5i-r8") ||
+ OF_is_compatible(node, "allwinner,sun50i-a64") ||
+ OF_is_compatible(node, "allwinner,sun7i-a20") ||
+ OF_is_compatible(node, "allwinner,sun8i-h3") ||
+ OF_is_compatible(node, "allwinner,sun9i-a80"));
+ }
+
+ return (OF_is_compatible(faa->fa_node, "allwinner,sun50i-a64-ccu") ||
+ OF_is_compatible(faa->fa_node, "allwinner,sun8i-h3-ccu"));
+}
+
+void
+sxiccmu_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct sxiccmu_softc *sc = (struct sxiccmu_softc *)self;
+ struct fdt_attach_args *faa = aux;
+ int node = faa->fa_node;
+
+ sc->sc_iot = faa->fa_iot;
+ if (faa->fa_nreg > 0 && bus_space_map(sc->sc_iot,
+ faa->fa_reg[0].addr, faa->fa_reg[0].size, 0, &sc->sc_ioh))
+ panic("%s: bus_space_map failed!", __func__);
+
+ printf("\n");
+
+ if (OF_is_compatible(node, "allwinner,sun50i-a64-ccu")) {
+ KASSERT(faa->fa_nreg > 0);
+ sc->sc_gates = sun50i_a64_gates;
+ sc->sc_ngates = nitems(sun50i_a64_gates);
+ sc->sc_resets = sun50i_a64_resets;
+ sc->sc_nresets = nitems(sun50i_a64_resets);
+ sc->sc_get_frequency = sxiccmu_a64_get_frequency;
+ sc->sc_set_frequency = sxiccmu_a64_set_frequency;
+ } else if (OF_is_compatible(node, "allwinner,sun8i-h3-ccu")) {
+ KASSERT(faa->fa_nreg > 0);
+ sc->sc_gates = sun8i_h3_gates;
+ sc->sc_ngates = nitems(sun8i_h3_gates);
+ sc->sc_resets = sun8i_h3_resets;
+ sc->sc_nresets = nitems(sun8i_h3_resets);
+ sc->sc_get_frequency = sxiccmu_h3_get_frequency;
+ sc->sc_set_frequency = sxiccmu_h3_set_frequency;
+ } else {
+ for (node = OF_child(node); node; node = OF_peer(node))
+ sxiccmu_attach_clock(sc, node);
+ }
+
+ if (sc->sc_gates) {
+ sc->sc_cd.cd_node = node;
+ sc->sc_cd.cd_cookie = sc;
+ sc->sc_cd.cd_get_frequency = sxiccmu_ccu_get_frequency;
+ sc->sc_cd.cd_set_frequency = sxiccmu_ccu_set_frequency;
+ sc->sc_cd.cd_enable = sxiccmu_ccu_enable;
+ clock_register(&sc->sc_cd);
+ }
+
+ if (sc->sc_resets) {
+ sc->sc_rd.rd_node = node;
+ sc->sc_rd.rd_cookie = sc;
+ sc->sc_rd.rd_reset = sxiccmu_ccu_reset;
+ reset_register(&sc->sc_rd);
+ }
+}
+
+/*
+ * Device trees for the Allwinner SoCs have basically a clock node per
+ * register of the clock control unit. Attaching a separate driver to
+ * each of them would be crazy, so we handle them here.
+ */
+
+struct sxiccmu_clock {
+ int sc_node;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+
+ struct clock_device sc_cd;
+ struct reset_device sc_rd;
+};
+
+struct sxiccmu_device {
+ const char *compat;
+ uint32_t (*get_frequency)(void *, uint32_t *);
+ int (*set_frequency)(void *, uint32_t *, uint32_t);
+ void (*enable)(void *, uint32_t *, int);
+ void (*reset)(void *, uint32_t *, int);
+};
+
+uint32_t sxiccmu_gen_get_frequency(void *, uint32_t *);
+uint32_t sxiccmu_osc_get_frequency(void *, uint32_t *);
+uint32_t sxiccmu_pll6_get_frequency(void *, uint32_t *);
+void sxiccmu_pll6_enable(void *, uint32_t *, int);
+uint32_t sxiccmu_apb1_get_frequency(void *, uint32_t *);
+int sxiccmu_gmac_set_frequency(void *, uint32_t *, uint32_t);
+int sxiccmu_mmc_set_frequency(void *, uint32_t *, uint32_t);
+void sxiccmu_mmc_enable(void *, uint32_t *, int);
+void sxiccmu_gate_enable(void *, uint32_t *, int);
+void sxiccmu_reset(void *, uint32_t *, int);
+
+struct sxiccmu_device sxiccmu_devices[] = {
+ {
+ .compat = "allwinner,sun4i-a10-osc-clk",
+ .get_frequency = sxiccmu_osc_get_frequency,
+ },
+ {
+ .compat = "allwinner,sun4i-a10-pll6-clk",
+ .get_frequency = sxiccmu_pll6_get_frequency,
+ .enable = sxiccmu_pll6_enable
+ },
+ {
+ .compat = "allwinner,sun4i-a10-apb1-clk",
+ .get_frequency = sxiccmu_apb1_get_frequency,
+ },
+ {
+ .compat = "allwinner,sun4i-a10-ahb-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun4i-a10-apb0-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun4i-a10-apb1-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun4i-a10-mmc-clk",
+ .set_frequency = sxiccmu_mmc_set_frequency,
+ .enable = sxiccmu_mmc_enable
+ },
+ {
+ .compat = "allwinner,sun4i-a10-usb-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable,
+ .reset = sxiccmu_reset
+ },
+ {
+ .compat = "allwinner,sun5i-a10s-ahb-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun5i-a10s-apb0-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun5i-a10s-apb1-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun5i-a13-ahb-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun5i-a13-apb0-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun5i-a13-apb1-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun5i-a13-usb-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable,
+ .reset = sxiccmu_reset
+ },
+ {
+ .compat = "allwinner,sun6i-a31-ahb1-reset",
+ .reset = sxiccmu_reset
+ },
+ {
+ .compat = "allwinner,sun6i-a31-clock-reset",
+ .reset = sxiccmu_reset
+ },
+ {
+ .compat = "allwinner,sun7i-a20-ahb-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun7i-a20-apb0-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun7i-a20-apb1-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun7i-a20-gmac-clk",
+ .set_frequency = sxiccmu_gmac_set_frequency
+ },
+ {
+ .compat = "allwinner,sun8i-h3-apb0-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun9i-a80-apb1-clk",
+ .get_frequency = sxiccmu_apb1_get_frequency,
+ },
+ {
+ .compat = "allwinner,sun9i-a80-ahb0-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun9i-a80-ahb1-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun9i-a80-ahb2-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun9i-a80-apb0-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun9i-a80-apb1-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun9i-a80-apbs-gates-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable
+ },
+ {
+ .compat = "allwinner,sun9i-a80-mmc-clk",
+ .set_frequency = sxiccmu_mmc_set_frequency,
+ .enable = sxiccmu_mmc_enable
+ },
+ {
+ .compat = "allwinner,sun9i-a80-usb-mod-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable,
+ .reset = sxiccmu_reset
+ },
+ {
+ .compat = "allwinner,sun9i-a80-usb-phy-clk",
+ .get_frequency = sxiccmu_gen_get_frequency,
+ .enable = sxiccmu_gate_enable,
+ .reset = sxiccmu_reset
+ },
+};
+
+void
+sxiccmu_attach_clock(struct sxiccmu_softc *sc, int node)
+{
+ struct sxiccmu_clock *clock;
+ uint32_t reg[2];
+ int i;
+
+ for (i = 0; i < nitems(sxiccmu_devices); i++)
+ if (OF_is_compatible(node, sxiccmu_devices[i].compat))
+ break;
+ if (i == nitems(sxiccmu_devices))
+ return;
+
+ clock = malloc(sizeof(*clock), M_DEVBUF, M_WAITOK);
+ clock->sc_node = node;
+
+ if (OF_getpropintarray(node, "reg", reg, sizeof(reg)) == sizeof(reg)) {
+ clock->sc_iot = sc->sc_iot;
+ if (bus_space_map(clock->sc_iot, reg[0], reg[1], 0,
+ &clock->sc_ioh)) {
+ printf("%s: can't map registers", sc->sc_dev.dv_xname);
+ free(clock, M_DEVBUF, sizeof(*clock));
+ return;
+ }
+ }
+
+ clock->sc_cd.cd_node = node;
+ clock->sc_cd.cd_cookie = clock;
+ clock->sc_cd.cd_get_frequency = sxiccmu_devices[i].get_frequency;
+ clock->sc_cd.cd_set_frequency = sxiccmu_devices[i].set_frequency;
+ clock->sc_cd.cd_enable = sxiccmu_devices[i].enable;
+ clock_register(&clock->sc_cd);
+
+ if (sxiccmu_devices[i].reset) {
+ clock->sc_rd.rd_node = node;
+ clock->sc_rd.rd_cookie = clock;
+ clock->sc_rd.rd_reset = sxiccmu_devices[i].reset;
+ reset_register(&clock->sc_rd);
+ }
+}
+
+/*
+ * A "generic" function that simply gets the clock frequency from the
+ * parent clock. Useful for clock gating devices that don't scale
+ * their clocks.
+ */
+uint32_t
+sxiccmu_gen_get_frequency(void *cookie, uint32_t *cells)
+{
+ struct sxiccmu_clock *sc = cookie;
+
+ return clock_get_frequency(sc->sc_node, NULL);
+}
+
+uint32_t
+sxiccmu_osc_get_frequency(void *cookie, uint32_t *cells)
+{
+ struct sxiccmu_clock *sc = cookie;
+
+ return OF_getpropint(sc->sc_node, "clock-frequency", 24000000);
+}
+
+#define CCU_PLL6_ENABLE (1U << 31)
+#define CCU_PLL6_BYPASS_EN (1U << 30)
+#define CCU_PLL6_SATA_CLK_EN (1U << 14)
+#define CCU_PLL6_FACTOR_N(x) (((x) >> 8) & 0x1f)
+#define CCU_PLL6_FACTOR_N_MASK (0x1f << 8)
+#define CCU_PLL6_FACTOR_N_SHIFT 8
+#define CCU_PLL6_FACTOR_K(x) (((x) >> 4) & 0x3)
+#define CCU_PLL6_FACTOR_K_MASK (0x3 << 4)
+#define CCU_PLL6_FACTOR_K_SHIFT 4
+#define CCU_PLL6_FACTOR_M(x) (((x) >> 0) & 0x3)
+#define CCU_PLL6_FACTOR_M_MASK (0x3 << 0)
+#define CCU_PLL6_FACTOR_M_SHIFT 0
+
+uint32_t
+sxiccmu_pll6_get_frequency(void *cookie, uint32_t *cells)
+{
+ struct sxiccmu_clock *sc = cookie;
+ uint32_t reg, k, m, n, freq;
+ uint32_t idx = cells[0];
+
+ /* XXX Assume bypass is disabled. */
+ reg = SXIREAD4(sc, 0);
+ k = CCU_PLL6_FACTOR_K(reg) + 1;
+ m = CCU_PLL6_FACTOR_M(reg) + 1;
+ n = CCU_PLL6_FACTOR_N(reg);
+
+ freq = clock_get_frequency_idx(sc->sc_node, 0);
+ switch (idx) {
+ case 0:
+ return (freq * n * k) / m / 6; /* pll6_sata */
+ case 1:
+ return (freq * n * k) / 2; /* pll6_other */
+ case 2:
+ return (freq * n * k); /* pll6 */
+ case 3:
+ return (freq * n * k) / 4; /* pll6_div_4 */
+ }
+
+ return 0;
+}
+
+void
+sxiccmu_pll6_enable(void *cookie, uint32_t *cells, int on)
+{
+ struct sxiccmu_clock *sc = cookie;
+ uint32_t idx = cells[0];
+ uint32_t reg;
+
+ /*
+ * Since this clock has several outputs, we never turn it off.
+ */
+
+ reg = SXIREAD4(sc, 0);
+ switch (idx) {
+ case 0: /* pll6_sata */
+ if (on)
+ reg |= CCU_PLL6_SATA_CLK_EN;
+ else
+ reg &= ~CCU_PLL6_SATA_CLK_EN;
+ /* FALLTHROUGH */
+ case 1: /* pll6_other */
+ case 2: /* pll6 */
+ case 3: /* pll6_div_4 */
+ if (on)
+ reg |= CCU_PLL6_ENABLE;
+ }
+ SXIWRITE4(sc, 0, reg);
+}
+
+#define CCU_APB1_CLK_RAT_N(x) (((x) >> 16) & 0x3)
+#define CCU_APB1_CLK_RAT_M(x) (((x) >> 0) & 0x1f)
+#define CCU_APB1_CLK_SRC_SEL(x) (((x) >> 24) & 0x3)
+
+uint32_t
+sxiccmu_apb1_get_frequency(void *cookie, uint32_t *cells)
+{
+ struct sxiccmu_clock *sc = cookie;
+ uint32_t reg, m, n, freq;
+ int idx;
+
+ reg = SXIREAD4(sc, 0);
+ m = CCU_APB1_CLK_RAT_M(reg);
+ n = CCU_APB1_CLK_RAT_N(reg);
+ idx = CCU_APB1_CLK_SRC_SEL(reg);
+
+ freq = clock_get_frequency_idx(sc->sc_node, idx);
+ return freq / (1 << n) / (m + 1);
+}
+
+#define CCU_GMAC_CLK_PIT (1 << 2)
+#define CCU_GMAC_CLK_TCS (3 << 0)
+#define CCU_GMAC_CLK_TCS_MII 0
+#define CCU_GMAC_CLK_TCS_EXT_125 1
+#define CCU_GMAC_CLK_TCS_INT_RGMII 2
+
+int
+sxiccmu_gmac_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
+{
+ struct sxiccmu_clock *sc = cookie;
+
+ switch (freq) {
+ case 25000000: /* MMI, 25 MHz */
+ SXICMS4(sc, 0, CCU_GMAC_CLK_PIT|CCU_GMAC_CLK_TCS,
+ CCU_GMAC_CLK_TCS_MII);
+ break;
+ case 125000000: /* RGMII, 125 MHz */
+ SXICMS4(sc, 0, CCU_GMAC_CLK_PIT|CCU_GMAC_CLK_TCS,
+ CCU_GMAC_CLK_PIT|CCU_GMAC_CLK_TCS_INT_RGMII);
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+#define CCU_SDx_SCLK_GATING (1U << 31)
+#define CCU_SDx_CLK_SRC_SEL_OSC24M (0 << 24)
+#define CCU_SDx_CLK_SRC_SEL_PLL6 (1 << 24)
+#define CCU_SDx_CLK_SRC_SEL_PLL5 (2 << 24)
+#define CCU_SDx_CLK_SRC_SEL_MASK (3 << 24)
+#define CCU_SDx_CLK_DIV_RATIO_N_MASK (3 << 16)
+#define CCU_SDx_CLK_DIV_RATIO_N_SHIFT 16
+#define CCU_SDx_CLK_DIV_RATIO_M_MASK (7 << 0)
+#define CCU_SDx_CLK_DIV_RATIO_M_SHIFT 0
+
+int
+sxiccmu_mmc_do_set_frequency(struct sxiccmu_clock *sc, uint32_t freq,
+ uint32_t parent_freq)
+{
+ uint32_t reg, m, n;
+ uint32_t clk_src;
+
+ switch (freq) {
+ case 400000:
+ n = 2, m = 15;
+ clk_src = CCU_SDx_CLK_SRC_SEL_OSC24M;
+ break;
+ case 25000000:
+ case 26000000:
+ case 50000000:
+ case 52000000:
+ n = 0, m = 0;
+ clk_src = CCU_SDx_CLK_SRC_SEL_PLL6;
+ while ((parent_freq / (1 << n) / 16) > freq)
+ n++;
+ while ((parent_freq / (1 << n) / (m + 1)) > freq)
+ m++;
+ break;
+ default:
+ return -1;
+ }
+
+ reg = SXIREAD4(sc, 0);
+ reg &= ~CCU_SDx_CLK_SRC_SEL_MASK;
+ reg |= clk_src;
+ reg &= ~CCU_SDx_CLK_DIV_RATIO_N_MASK;
+ reg |= n << CCU_SDx_CLK_DIV_RATIO_N_SHIFT;
+ reg &= ~CCU_SDx_CLK_DIV_RATIO_M_MASK;
+ reg |= m << CCU_SDx_CLK_DIV_RATIO_M_SHIFT;
+ SXIWRITE4(sc, 0, reg);
+
+ return 0;
+}
+
+int
+sxiccmu_mmc_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
+{
+ struct sxiccmu_clock *sc = cookie;
+ uint32_t parent_freq;
+
+ if (cells[0] != 0)
+ return -1;
+
+ parent_freq = clock_get_frequency_idx(sc->sc_node, 1);
+ return sxiccmu_mmc_do_set_frequency(sc, freq, parent_freq);
+}
+
+void
+sxiccmu_mmc_enable(void *cookie, uint32_t *cells, int on)
+{
+ struct sxiccmu_clock *sc = cookie;
+
+ if (cells[0] != 0)
+ return;
+
+ if (on)
+ SXISET4(sc, 0, CCU_SDx_SCLK_GATING);
+ else
+ SXICLR4(sc, 0, CCU_SDx_SCLK_GATING);
+}
+
+void
+sxiccmu_gate_enable(void *cookie, uint32_t *cells, int on)
+{
+ struct sxiccmu_clock *sc = cookie;
+ int reg = cells[0] / 32;
+ int bit = cells[0] % 32;
+
+ if (on) {
+ clock_enable(sc->sc_node, NULL);
+ SXISET4(sc, reg * 4, (1U << bit));
+ } else {
+ SXICLR4(sc, reg * 4, (1U << bit));
+ clock_disable(sc->sc_node, NULL);
+ }
+}
+
+void
+sxiccmu_reset(void *cookie, uint32_t *cells, int assert)
+{
+ struct sxiccmu_clock *sc = cookie;
+ int reg = cells[0] / 32;
+ int bit = cells[0] % 32;
+
+ if (assert)
+ SXICLR4(sc, reg * 4, (1U << bit));
+ else
+ SXISET4(sc, reg * 4, (1U << bit));
+}
+
+/*
+ * Device trees for the Allwinner A80 have most of the clock nodes
+ * replaced with a single clock control unit node.
+ */
+
+uint32_t
+sxiccmu_ccu_get_frequency(void *cookie, uint32_t *cells)
+{
+ struct sxiccmu_softc *sc = cookie;
+ uint32_t idx = cells[0];
+ uint32_t parent;
+
+ if (idx < sc->sc_ngates && sc->sc_gates[idx].parent) {
+ parent = sc->sc_gates[idx].parent;
+ return sxiccmu_ccu_get_frequency(sc, &parent);
+ }
+
+ return sc->sc_get_frequency(sc, idx);
+}
+
+uint32_t
+sxiccmu_a64_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
+{
+ switch (idx) {
+ case A64_CLK_PLL_PERIPH0:
+ /* XXX default value. */
+ return 600000000;
+ case A64_CLK_PLL_PERIPH0_2X:
+ return sxiccmu_a64_get_frequency(sc, A64_CLK_PLL_PERIPH0) * 2;
+ case A64_CLK_APB2:
+ /* XXX Controlled by a MUX. */
+ return 24000000;
+ }
+
+ printf("%s: 0x%08x\n", __func__, idx);
+ return 0;
+}
+
+uint32_t
+sxiccmu_h3_get_frequency(struct sxiccmu_softc *sc, uint32_t idx)
+{
+ switch (idx) {
+ case H3_CLK_PLL_PERIPH0:
+ /* XXX default value. */
+ return 600000000;
+ case H3_CLK_APB2:
+ /* XXX Controlled by a MUX. */
+ return 24000000;
+ }
+
+ printf("%s: 0x%08x\n", __func__, idx);
+ return 0;
+}
+
+int
+sxiccmu_ccu_set_frequency(void *cookie, uint32_t *cells, uint32_t freq)
+{
+ struct sxiccmu_softc *sc = cookie;
+ uint32_t idx = cells[0];
+
+ return sc->sc_set_frequency(sc, idx, freq);
+}
+
+int
+sxiccmu_a64_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
+{
+ struct sxiccmu_clock clock;
+ uint32_t parent, parent_freq;
+
+ switch (idx) {
+ case A64_CLK_MMC0:
+ case A64_CLK_MMC1:
+ case A64_CLK_MMC2:
+ clock.sc_iot = sc->sc_iot;
+ bus_space_subregion(sc->sc_iot, sc->sc_ioh,
+ sc->sc_gates[idx].reg, 4, &clock.sc_ioh);
+ parent = A64_CLK_PLL_PERIPH0_2X;
+ parent_freq = sxiccmu_ccu_get_frequency(sc, &parent);
+ return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq);
+ }
+
+ printf("%s: 0x%08x\n", __func__, idx);
+ return -1;
+}
+
+int
+sxiccmu_h3_set_frequency(struct sxiccmu_softc *sc, uint32_t idx, uint32_t freq)
+{
+ struct sxiccmu_clock clock;
+ uint32_t parent, parent_freq;
+
+ switch (idx) {
+ case H3_CLK_MMC0:
+ case H3_CLK_MMC1:
+ case H3_CLK_MMC2:
+ clock.sc_iot = sc->sc_iot;
+ bus_space_subregion(sc->sc_iot, sc->sc_ioh,
+ sc->sc_gates[idx].reg, 4, &clock.sc_ioh);
+ parent = H3_CLK_PLL_PERIPH0;
+ parent_freq = sxiccmu_ccu_get_frequency(sc, &parent);
+ return sxiccmu_mmc_do_set_frequency(&clock, freq, parent_freq);
+ }
+
+ printf("%s: 0x%08x\n", __func__, idx);
+ return -1;
+}
+
+void
+sxiccmu_ccu_enable(void *cookie, uint32_t *cells, int on)
+{
+ struct sxiccmu_softc *sc = cookie;
+ uint32_t idx = cells[0];
+ int reg, bit;
+
+ if (idx >= sc->sc_ngates || sc->sc_gates[idx].reg == 0) {
+ printf("%s: 0x%08x\n", __func__, cells[0]);
+ return;
+ }
+
+ reg = sc->sc_gates[idx].reg;
+ bit = sc->sc_gates[idx].bit;
+
+ if (on)
+ SXISET4(sc, reg, (1U << bit));
+ else
+ SXICLR4(sc, reg, (1U << bit));
+}
+
+void
+sxiccmu_ccu_reset(void *cookie, uint32_t *cells, int assert)
+{
+ struct sxiccmu_softc *sc = cookie;
+ uint32_t idx = cells[0];
+ int reg, bit;
+
+ if (idx >= sc->sc_nresets || sc->sc_resets[idx].reg == 0) {
+ printf("%s: 0x%08x\n", __func__, cells[0]);
+ return;
+ }
+
+ reg = sc->sc_resets[idx].reg;
+ bit = sc->sc_resets[idx].bit;
+
+ if (assert)
+ SXICLR4(sc, reg, (1U << bit));
+ else
+ SXISET4(sc, reg, (1U << bit));
+}
diff --git a/sys/dev/fdt/sxiccmu_clocks.h b/sys/dev/fdt/sxiccmu_clocks.h
new file mode 100644
index 00000000000..fdd0282623b
--- /dev/null
+++ b/sys/dev/fdt/sxiccmu_clocks.h
@@ -0,0 +1,180 @@
+/* Public Domain */
+
+
+/*
+ * Clocks Signals
+ */
+
+#define A64_CLK_PLL_PERIPH0 11
+#define A64_CLK_PLL_PERIPH0_2X 12
+
+#define A64_CLK_APB2 26
+
+#define A64_CLK_BUS_MMC0 31
+#define A64_CLK_BUS_MMC1 32
+#define A64_CLK_BUS_MMC2 33
+
+#define A64_CLK_BUS_EHCI0 42
+#define A64_CLK_BUS_EHCI1 43
+#define A64_CLK_BUS_OHCI0 44
+#define A64_CLK_BUS_OHCI1 45
+
+#define A64_CLK_BUS_UART0 67
+#define A64_CLK_BUS_UART1 68
+#define A64_CLK_BUS_UART2 69
+#define A64_CLK_BUS_UART3 70
+#define A64_CLK_BUS_UART4 71
+
+#define A64_CLK_MMC0 75
+#define A64_CLK_MMC1 76
+#define A64_CLK_MMC2 77
+
+#define A64_CLK_USB_OHCI0 91
+#define A64_CLK_USB_OHCI1 93
+#define A64_CLK_USB_PHY0 86
+#define A64_CLK_USB_PHY1 87
+
+struct sxiccmu_ccu_bit sun50i_a64_gates[] = {
+ [A64_CLK_BUS_MMC0] = { 0x0060, 8 },
+ [A64_CLK_BUS_MMC1] = { 0x0060, 9 },
+ [A64_CLK_BUS_MMC2] = { 0x0060, 10 },
+ [A64_CLK_BUS_EHCI0] = { 0x0060, 24 },
+ [A64_CLK_BUS_EHCI1] = { 0x0060, 25 },
+ [A64_CLK_BUS_OHCI0] = { 0x0060, 28 },
+ [A64_CLK_BUS_OHCI1] = { 0x0060, 29 },
+ [A64_CLK_BUS_UART0] = { 0x006c, 16, A64_CLK_APB2 },
+ [A64_CLK_BUS_UART1] = { 0x006c, 17, A64_CLK_APB2 },
+ [A64_CLK_BUS_UART2] = { 0x006c, 18, A64_CLK_APB2 },
+ [A64_CLK_BUS_UART3] = { 0x006c, 19, A64_CLK_APB2 },
+ [A64_CLK_BUS_UART4] = { 0x006c, 20, A64_CLK_APB2 },
+ [A64_CLK_MMC0] = { 0x0088, 31 },
+ [A64_CLK_MMC1] = { 0x008c, 31 },
+ [A64_CLK_MMC2] = { 0x0090, 31 },
+ [A64_CLK_USB_OHCI0] = { 0x00cc, 16 },
+ [A64_CLK_USB_OHCI1] = { 0x00cc, 17 },
+ [A64_CLK_USB_PHY0] = { 0x00cc, 8 },
+ [A64_CLK_USB_PHY1] = { 0x00cc, 9 },
+};
+
+#define H3_CLK_PLL_PERIPH0 9
+
+#define H3_CLK_APB2 18
+
+#define H3_CLK_BUS_MMC0 22
+#define H3_CLK_BUS_MMC1 23
+#define H3_CLK_BUS_MMC2 24
+
+#define H3_CLK_BUS_EHCI0 33
+#define H3_CLK_BUS_EHCI1 34
+#define H3_CLK_BUS_EHCI2 35
+#define H3_CLK_BUS_EHCI3 36
+#define H3_CLK_BUS_OHCI0 37
+#define H3_CLK_BUS_OHCI1 38
+#define H3_CLK_BUS_OHCI2 39
+#define H3_CLK_BUS_OHCI3 40
+
+#define H3_CLK_BUS_PIO 54
+
+#define H3_CLK_BUS_UART0 62
+#define H3_CLK_BUS_UART1 63
+#define H3_CLK_BUS_UART2 64
+#define H3_CLK_BUS_UART3 65
+
+#define H3_CLK_MMC0 71
+#define H3_CLK_MMC1 74
+#define H3_CLK_MMC2 77
+
+#define H3_CLK_USB_PHY0 88
+#define H3_CLK_USB_PHY1 89
+#define H3_CLK_USB_PHY2 90
+#define H3_CLK_USB_PHY3 91
+
+struct sxiccmu_ccu_bit sun8i_h3_gates[] = {
+ [H3_CLK_BUS_MMC0] = { 0x0060, 8 },
+ [H3_CLK_BUS_MMC1] = { 0x0060, 9 },
+ [H3_CLK_BUS_MMC2] = { 0x0060, 10 },
+ [H3_CLK_BUS_EHCI0] = { 0x0060, 24 },
+ [H3_CLK_BUS_EHCI1] = { 0x0060, 25 },
+ [H3_CLK_BUS_EHCI2] = { 0x0060, 26 },
+ [H3_CLK_BUS_EHCI3] = { 0x0060, 27 },
+ [H3_CLK_BUS_OHCI0] = { 0x0060, 28 },
+ [H3_CLK_BUS_OHCI1] = { 0x0060, 29 },
+ [H3_CLK_BUS_OHCI2] = { 0x0060, 30 },
+ [H3_CLK_BUS_OHCI3] = { 0x0060, 31 },
+ [H3_CLK_BUS_PIO] = { 0x0068, 5 },
+ [H3_CLK_BUS_UART0] = { 0x006c, 16, H3_CLK_APB2 },
+ [H3_CLK_BUS_UART1] = { 0x006c, 17, H3_CLK_APB2 },
+ [H3_CLK_BUS_UART2] = { 0x006c, 18, H3_CLK_APB2 },
+ [H3_CLK_BUS_UART3] = { 0x006c, 19, H3_CLK_APB2 },
+ [H3_CLK_MMC0] = { 0x0088, 31 },
+ [H3_CLK_MMC1] = { 0x008c, 31 },
+ [H3_CLK_MMC2] = { 0x0090, 31 },
+ [H3_CLK_USB_PHY0] = { 0x00cc, 8 },
+ [H3_CLK_USB_PHY1] = { 0x00cc, 9 },
+ [H3_CLK_USB_PHY2] = { 0x00cc, 10 },
+ [H3_CLK_USB_PHY3] = { 0x00cc, 11 },
+};
+
+/*
+ * Reset Signals
+ */
+
+#define A64_RST_USB_PHY0 0
+#define A64_RST_USB_PHY1 1
+
+#define A64_RST_BUS_MMC0 8
+#define A64_RST_BUS_MMC1 9
+#define A64_RST_BUS_MMC2 10
+
+#define A64_RST_BUS_EHCI0 19
+#define A64_RST_BUS_EHCI1 20
+#define A64_RST_BUS_OHCI0 21
+#define A64_RST_BUS_OHCI1 22
+
+struct sxiccmu_ccu_bit sun50i_a64_resets[] = {
+ [A64_RST_USB_PHY0] = { 0x00cc, 0 },
+ [A64_RST_USB_PHY1] = { 0x00cc, 1 },
+ [A64_RST_BUS_MMC0] = { 0x02c0, 8 },
+ [A64_RST_BUS_MMC1] = { 0x02c0, 9 },
+ [A64_RST_BUS_MMC2] = { 0x02c0, 10 },
+ [A64_RST_BUS_EHCI0] = { 0x02c0, 24 },
+ [A64_RST_BUS_EHCI1] = { 0x02c0, 25 },
+ [A64_RST_BUS_OHCI0] = { 0x02c0, 28 },
+ [A64_RST_BUS_OHCI1] = { 0x02c0, 29 },
+};
+
+#define H3_RST_USB_PHY0 0
+#define H3_RST_USB_PHY1 1
+#define H3_RST_USB_PHY2 2
+#define H3_RST_USB_PHY3 3
+
+#define H3_RST_BUS_MMC0 7
+#define H3_RST_BUS_MMC1 8
+#define H3_RST_BUS_MMC2 9
+
+#define H3_RST_BUS_EHCI0 18
+#define H3_RST_BUS_EHCI1 19
+#define H3_RST_BUS_EHCI2 20
+#define H3_RST_BUS_EHCI3 21
+#define H3_RST_BUS_OHCI0 22
+#define H3_RST_BUS_OHCI1 23
+#define H3_RST_BUS_OHCI2 24
+#define H3_RST_BUS_OHCI3 25
+
+struct sxiccmu_ccu_bit sun8i_h3_resets[] = {
+ [H3_RST_USB_PHY0] = { 0x00cc, 0 },
+ [H3_RST_USB_PHY1] = { 0x00cc, 1 },
+ [H3_RST_USB_PHY2] = { 0x00cc, 2 },
+ [H3_RST_USB_PHY3] = { 0x00cc, 3 },
+ [H3_RST_BUS_MMC0] = { 0x02c0, 8 },
+ [H3_RST_BUS_MMC1] = { 0x02c0, 9 },
+ [H3_RST_BUS_MMC2] = { 0x02c0, 10 },
+ [H3_RST_BUS_EHCI0] = { 0x02c0, 24 },
+ [H3_RST_BUS_EHCI1] = { 0x02c0, 25 },
+ [H3_RST_BUS_EHCI2] = { 0x02c0, 26 },
+ [H3_RST_BUS_EHCI3] = { 0x02c0, 27 },
+ [H3_RST_BUS_OHCI0] = { 0x02c0, 28 },
+ [H3_RST_BUS_OHCI1] = { 0x02c0, 29 },
+ [H3_RST_BUS_OHCI2] = { 0x02c0, 30 },
+ [H3_RST_BUS_OHCI3] = { 0x02c0, 31 },
+};
diff --git a/sys/dev/fdt/sxiehci.c b/sys/dev/fdt/sxiehci.c
new file mode 100644
index 00000000000..592387e6b67
--- /dev/null
+++ b/sys/dev/fdt/sxiehci.c
@@ -0,0 +1,320 @@
+/* $OpenBSD: sxiehci.c,v 1.1 2017/01/21 08:26:49 patrick Exp $ */
+
+/*
+ * Copyright (c) 2005 David Gwynne <dlg@openbsd.org>
+ * Copyright (c) 2016 Mark Kettenis <kettenis@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*-
+ * Copyright (c) 2011
+ * Ben Gray <ben.r.gray@gmail.com>.
+ * 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 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 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/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/rwlock.h>
+#include <sys/timeout.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_clock.h>
+#include <dev/ofw/ofw_pinctrl.h>
+#include <dev/ofw/ofw_regulator.h>
+#include <dev/ofw/fdt.h>
+
+#include <dev/usb/ehcireg.h>
+#include <dev/usb/ehcivar.h>
+
+#define USB_PMU_IRQ_ENABLE 0x800
+#define ULPI_BYPASS (1 << 0)
+#define AHB_INCRX_ALIGN (1 << 8)
+#define AHB_INCR4 (1 << 9)
+#define AHB_INCR8 (1 << 10)
+#define AHB_INCR16 (1 << 11)
+
+struct sxiehci_softc {
+ struct ehci_softc sc;
+ int sc_node;
+ void *sc_ih;
+};
+
+int sxiehci_match(struct device *, void *, void *);
+void sxiehci_attach(struct device *, struct device *, void *);
+int sxiehci_detach(struct device *, int);
+int sxiehci_activate(struct device *, int);
+
+struct cfattach sxiehci_ca = {
+ sizeof(struct sxiehci_softc), sxiehci_match, sxiehci_attach,
+ sxiehci_detach, sxiehci_activate
+};
+
+void sxiehci_attach_sun4i_phy(struct sxiehci_softc *);
+void sxiehci_attach_sun9i_phy(struct sxiehci_softc *);
+
+int
+sxiehci_match(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+
+ if (OF_is_compatible(faa->fa_node, "allwinner,sun4i-a10-ehci"))
+ return 1;
+ if (OF_is_compatible(faa->fa_node, "allwinner,sun5i-a13-ehci"))
+ return 1;
+ if (OF_is_compatible(faa->fa_node, "allwinner,sun50i-a64-ehci"))
+ return 1;
+ if (OF_is_compatible(faa->fa_node, "allwinner,sun7i-a20-ehci"))
+ return 1;
+ if (OF_is_compatible(faa->fa_node, "allwinner,sun8i-h3-ehci"))
+ return 1;
+ if (OF_is_compatible(faa->fa_node, "allwinner,sun9i-a80-ehci"))
+ return 1;
+
+ return 0;
+}
+
+void
+sxiehci_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct sxiehci_softc *sc = (struct sxiehci_softc *)self;
+ struct fdt_attach_args *faa = aux;
+ usbd_status r;
+ char *devname = sc->sc.sc_bus.bdev.dv_xname;
+
+ if (faa->fa_nreg < 1)
+ return;
+
+ sc->sc_node = faa->fa_node;
+ sc->sc.iot = faa->fa_iot;
+ sc->sc.sc_bus.dmatag = faa->fa_dmat;
+ sc->sc.sc_size = faa->fa_reg[0].size;
+
+ if (bus_space_map(sc->sc.iot, faa->fa_reg[0].addr,
+ faa->fa_reg[0].size, 0, &sc->sc.ioh)) {
+ printf(": cannot map mem space\n");
+ goto out;
+ }
+
+ printf("\n");
+
+ clock_enable_all(sc->sc_node);
+ reset_deassert_all(sc->sc_node);
+
+ if (OF_is_compatible(sc->sc_node, "allwinner,sun9i-a80-ehci"))
+ sxiehci_attach_sun9i_phy(sc);
+ else
+ sxiehci_attach_sun4i_phy(sc);
+
+ /* Disable interrupts, so we don't get any spurious ones. */
+ sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH);
+ EOWRITE2(&sc->sc, EHCI_USBINTR, 0);
+
+ sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_USB,
+ ehci_intr, &sc->sc, devname);
+ if (sc->sc_ih == NULL) {
+ printf(": unable to establish interrupt\n");
+ printf("XXX - disable ehci");
+#if 0
+ clock_disable_all(sc->sc_node);
+#endif
+ goto mem0;
+ }
+
+ strlcpy(sc->sc.sc_vendor, "Allwinner", sizeof(sc->sc.sc_vendor));
+ r = ehci_init(&sc->sc);
+ if (r != USBD_NORMAL_COMPLETION) {
+ printf("%s: init failed, error=%d\n", devname, r);
+ printf("XXX - disable ehci");
+#if 0
+ clock_disable_all(sc->sc_node);
+#endif
+ goto intr;
+ }
+
+ config_found(self, &sc->sc.sc_bus, usbctlprint);
+
+ goto out;
+
+intr:
+ arm_intr_disestablish(sc->sc_ih);
+ sc->sc_ih = NULL;
+mem0:
+ bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
+ sc->sc.sc_size = 0;
+out:
+ return;
+}
+
+void
+sxiehci_attach_sun4i_phy(struct sxiehci_softc *sc)
+{
+ uint32_t vbus_supply;
+ uint32_t phys[2];
+ char name[32];
+ uint32_t val;
+ int node;
+
+ val = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USB_PMU_IRQ_ENABLE);
+ val |= AHB_INCR8; /* AHB INCR8 enable */
+ val |= AHB_INCR4; /* AHB burst type INCR4 enable */
+ val |= AHB_INCRX_ALIGN; /* AHB INCRX align enable */
+ val |= ULPI_BYPASS; /* ULPI bypass enable */
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, USB_PMU_IRQ_ENABLE, val);
+
+ if (OF_getpropintarray(sc->sc_node, "phys", phys,
+ sizeof(phys)) != sizeof(phys))
+ return;
+
+ node = OF_getnodebyphandle(phys[0]);
+ if (node == -1)
+ return;
+
+ pinctrl_byname(node, "default");
+
+ /*
+ * On sun4i, sun5i and sun7i, there is a single clock. The
+ * more recent SoCs have a separate clock for each PHY.
+ */
+ if (OF_is_compatible(node, "allwinner,sun4i-a10-usb-phy") ||
+ OF_is_compatible(node, "allwinner,sun5i-a13-usb-phy") ||
+ OF_is_compatible(node, "allwinner,sun7i-a20-usb-phy")) {
+ clock_enable(node, "usb_phy");
+ } else {
+ snprintf(name, sizeof(name), "usb%d_phy", phys[1]);
+ clock_enable(node, name);
+ }
+
+ snprintf(name, sizeof(name), "usb%d_reset", phys[1]);
+ reset_deassert(node, name);
+
+ snprintf(name, sizeof(name), "usb%d_vbus-supply", phys[1]);
+ vbus_supply = OF_getpropint(node, name, 0);
+ if (vbus_supply)
+ regulator_enable(vbus_supply);
+}
+
+void
+sxiehci_attach_sun9i_phy(struct sxiehci_softc *sc)
+{
+ uint32_t phy_supply;
+ uint32_t phys[1];
+ uint32_t val;
+ int node;
+
+ if (OF_getpropintarray(sc->sc_node, "phys", phys,
+ sizeof(phys)) != sizeof(phys))
+ return;
+
+ node = OF_getnodebyphandle(phys[0]);
+ if (node == -1)
+ return;
+
+ pinctrl_byname(node, "default");
+ clock_enable(node, "phy");
+ reset_deassert(node, "phy");
+
+ val = bus_space_read_4(sc->sc.iot, sc->sc.ioh, USB_PMU_IRQ_ENABLE);
+ val |= AHB_INCR16;
+ val |= AHB_INCR8; /* AHB INCR8 enable */
+ val |= AHB_INCR4; /* AHB burst type INCR4 enable */
+ val |= AHB_INCRX_ALIGN; /* AHB INCRX align enable */
+ val |= ULPI_BYPASS; /* ULPI bypass enable */
+ bus_space_write_4(sc->sc.iot, sc->sc.ioh, USB_PMU_IRQ_ENABLE, val);
+
+ phy_supply = OF_getpropint(node, "phy-supply", 0);
+ if (phy_supply)
+ regulator_enable(phy_supply);
+}
+
+int
+sxiehci_detach(struct device *self, int flags)
+{
+ struct sxiehci_softc *sc = (struct sxiehci_softc *)self;
+ int rv;
+
+ rv = ehci_detach(self, flags);
+ if (rv)
+ return (rv);
+
+ if (sc->sc_ih != NULL) {
+ arm_intr_disestablish(sc->sc_ih);
+ sc->sc_ih = NULL;
+ }
+
+ if (sc->sc.sc_size) {
+ bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size);
+ sc->sc.sc_size = 0;
+ }
+ /* XXX */
+#if 0
+ sxiehci_detach_phy(sc);
+ clock_disable_all(sc->sc_node);
+#endif
+ return (0);
+}
+
+int
+sxiehci_activate(struct device *self, int act)
+{
+ struct sxiehci_softc *sc = (struct sxiehci_softc *)self;
+
+ switch (act) {
+ case DVACT_SUSPEND:
+ sc->sc.sc_bus.use_polling++;
+ /* FIXME */
+ sc->sc.sc_bus.use_polling--;
+ break;
+ case DVACT_RESUME:
+ sc->sc.sc_bus.use_polling++;
+ /* FIXME */
+ sc->sc.sc_bus.use_polling--;
+ break;
+ case DVACT_POWERDOWN:
+ ehci_reset(&sc->sc);
+ break;
+ }
+ return 0;
+}
diff --git a/sys/dev/fdt/sximmc.c b/sys/dev/fdt/sximmc.c
new file mode 100644
index 00000000000..39d339607ef
--- /dev/null
+++ b/sys/dev/fdt/sximmc.c
@@ -0,0 +1,1099 @@
+/* $OpenBSD: sximmc.c,v 1.1 2017/01/21 08:26:49 patrick Exp $ */
+/* $NetBSD: awin_mmc.c,v 1.23 2015/11/14 10:32:40 bouyer Exp $ */
+
+/*-
+ * Copyright (c) 2014 Jared D. McNeill <jmcneill@invisible.ca>
+ * 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 ``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 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/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/sdmmc/sdmmcvar.h>
+#include <dev/sdmmc/sdmmcchip.h>
+#include <dev/sdmmc/sdmmc_ioreg.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_clock.h>
+#include <dev/ofw/ofw_gpio.h>
+#include <dev/ofw/ofw_pinctrl.h>
+#include <dev/ofw/ofw_regulator.h>
+#include <dev/ofw/fdt.h>
+
+//#define SXIMMC_DEBUG
+
+#define SXIMMC_GCTRL 0x0000
+#define SXIMMC_CLKCR 0x0004
+#define SXIMMC_TIMEOUT 0x0008
+#define SXIMMC_WIDTH 0x000C
+#define SXIMMC_BLKSZ 0x0010
+#define SXIMMC_BYTECNT 0x0014
+#define SXIMMC_CMD 0x0018
+#define SXIMMC_ARG 0x001C
+#define SXIMMC_RESP0 0x0020
+#define SXIMMC_RESP1 0x0024
+#define SXIMMC_RESP2 0x0028
+#define SXIMMC_RESP3 0x002C
+#define SXIMMC_IMASK 0x0030
+#define SXIMMC_MINT 0x0034
+#define SXIMMC_RINT 0x0038
+#define SXIMMC_STATUS 0x003C
+#define SXIMMC_FTRGLEVEL 0x0040
+#define SXIMMC_FUNCSEL 0x0044
+#define SXIMMC_CBCR 0x0048
+#define SXIMMC_BBCR 0x004C
+#define SXIMMC_DBGC 0x0050
+#define SXIMMC_A12A 0x0058 /* A80 */
+#define SXIMMC_HWRST 0x0078 /* A80 */
+#define SXIMMC_DMAC 0x0080
+#define SXIMMC_DLBA 0x0084
+#define SXIMMC_IDST 0x0088
+#define SXIMMC_IDIE 0x008C
+#define SXIMMC_CHDA 0x0090
+#define SXIMMC_CBDA 0x0094
+#define SXIMMC_FIFO_A10 0x0100
+#define SXIMMC_FIFO_A31 0x0200
+
+#define SXIMMC_GCTRL_ACCESS_BY_AHB (1U << 31)
+#define SXIMMC_GCTRL_WAIT_MEM_ACCESS_DONE (1U << 30)
+#define SXIMMC_GCTRL_DDR_MODE (1U << 10)
+#define SXIMMC_GCTRL_DEBOUNCEEN (1U << 8)
+#define SXIMMC_GCTRL_DMAEN (1U << 5)
+#define SXIMMC_GCTRL_INTEN (1U << 4)
+#define SXIMMC_GCTRL_DMARESET (1U << 2)
+#define SXIMMC_GCTRL_FIFORESET (1U << 1)
+#define SXIMMC_GCTRL_SOFTRESET (1U << 0)
+#define SXIMMC_GCTRL_RESET \
+ (SXIMMC_GCTRL_SOFTRESET | SXIMMC_GCTRL_FIFORESET | \
+ SXIMMC_GCTRL_DMARESET)
+
+#define SXIMMC_CLKCR_LOWPOWERON (1U << 17)
+#define SXIMMC_CLKCR_CARDCLKON (1U << 16)
+#define SXIMMC_CLKCR_DIV 0x0000ffff
+
+#define SXIMMC_WIDTH_1 0
+#define SXIMMC_WIDTH_4 1
+#define SXIMMC_WIDTH_8 2
+
+#define SXIMMC_CMD_START (1U << 31)
+#define SXIMMC_CMD_USE_HOLD_REG (1U << 29)
+#define SXIMMC_CMD_VOL_SWITCH (1U << 28)
+#define SXIMMC_CMD_BOOT_ABORT (1U << 27)
+#define SXIMMC_CMD_BOOT_ACK_EXP (1U << 26)
+#define SXIMMC_CMD_ALT_BOOT_OPT (1U << 25)
+#define SXIMMC_CMD_ENBOOT (1U << 24)
+#define SXIMMC_CMD_CCS_EXP (1U << 23)
+#define SXIMMC_CMD_RD_CEATA_DEV (1U << 22)
+#define SXIMMC_CMD_UPCLK_ONLY (1U << 21)
+#define SXIMMC_CMD_SEND_INIT_SEQ (1U << 15)
+#define SXIMMC_CMD_STOP_ABORT_CMD (1U << 14)
+#define SXIMMC_CMD_WAIT_PRE_OVER (1U << 13)
+#define SXIMMC_CMD_SEND_AUTO_STOP (1U << 12)
+#define SXIMMC_CMD_SEQMOD (1U << 11)
+#define SXIMMC_CMD_WRITE (1U << 10)
+#define SXIMMC_CMD_DATA_EXP (1U << 9)
+#define SXIMMC_CMD_CHECK_RSP_CRC (1U << 8)
+#define SXIMMC_CMD_LONG_RSP (1U << 7)
+#define SXIMMC_CMD_RSP_EXP (1U << 6)
+
+#define SXIMMC_INT_CARD_REMOVE (1U << 31)
+#define SXIMMC_INT_CARD_INSERT (1U << 30)
+#define SXIMMC_INT_SDIO_INT (1U << 16)
+#define SXIMMC_INT_END_BIT_ERR (1U << 15)
+#define SXIMMC_INT_AUTO_CMD_DONE (1U << 14)
+#define SXIMMC_INT_START_BIT_ERR (1U << 13)
+#define SXIMMC_INT_HW_LOCKED (1U << 12)
+#define SXIMMC_INT_FIFO_RUN_ERR (1U << 11)
+#define SXIMMC_INT_VOL_CHG_DONE (1U << 10)
+#define SXIMMC_INT_DATA_STARVE (1U << 10)
+#define SXIMMC_INT_BOOT_START (1U << 9)
+#define SXIMMC_INT_DATA_TIMEOUT (1U << 9)
+#define SXIMMC_INT_ACK_RCV (1U << 8)
+#define SXIMMC_INT_RESP_TIMEOUT (1U << 8)
+#define SXIMMC_INT_DATA_CRC_ERR (1U << 7)
+#define SXIMMC_INT_RESP_CRC_ERR (1U << 6)
+#define SXIMMC_INT_RX_DATA_REQ (1U << 5)
+#define SXIMMC_INT_TX_DATA_REQ (1U << 4)
+#define SXIMMC_INT_DATA_OVER (1U << 3)
+#define SXIMMC_INT_CMD_DONE (1U << 2)
+#define SXIMMC_INT_RESP_ERR (1U << 1)
+#define SXIMMC_INT_ERROR \
+ (SXIMMC_INT_RESP_ERR | SXIMMC_INT_RESP_CRC_ERR | \
+ SXIMMC_INT_DATA_CRC_ERR | SXIMMC_INT_RESP_TIMEOUT | \
+ SXIMMC_INT_FIFO_RUN_ERR | SXIMMC_INT_HW_LOCKED | \
+ SXIMMC_INT_START_BIT_ERR | SXIMMC_INT_END_BIT_ERR)
+
+#define SXIMMC_STATUS_DMAREQ (1U << 31)
+#define SXIMMC_STATUS_DATA_FSM_BUSY (1U << 10)
+#define SXIMMC_STATUS_CARD_DATA_BUSY (1U << 9)
+#define SXIMMC_STATUS_CARD_PRESENT (1U << 8)
+#define SXIMMC_STATUS_FIFO_FULL (1U << 3)
+#define SXIMMC_STATUS_FIFO_EMPTY (1U << 2)
+#define SXIMMC_STATUS_TXWL_FLAG (1U << 1)
+#define SXIMMC_STATUS_RXWL_FLAG (1U << 0)
+
+#define SXIMMC_FUNCSEL_CEATA_DEV_INTEN (1U << 10)
+#define SXIMMC_FUNCSEL_SEND_AUTO_STOP_CCSD (1U << 9)
+#define SXIMMC_FUNCSEL_SEND_CCSD (1U << 8)
+#define SXIMMC_FUNCSEL_ABT_RD_DATA (1U << 2)
+#define SXIMMC_FUNCSEL_SDIO_RD_WAIT (1U << 1)
+#define SXIMMC_FUNCSEL_SEND_IRQ_RSP (1U << 0)
+
+#define SXIMMC_DMAC_REFETCH_DES (1U << 31)
+#define SXIMMC_DMAC_IDMA_ON (1U << 7)
+#define SXIMMC_DMAC_FIX_BURST (1U << 1)
+#define SXIMMC_DMAC_SOFTRESET (1U << 0)
+
+#define SXIMMC_IDST_HOST_ABT (1U << 10)
+#define SXIMMC_IDST_ABNORMAL_INT_SUM (1U << 9)
+#define SXIMMC_IDST_NORMAL_INT_SUM (1U << 8)
+#define SXIMMC_IDST_CARD_ERR_SUM (1U << 5)
+#define SXIMMC_IDST_DES_INVALID (1U << 4)
+#define SXIMMC_IDST_FATAL_BUS_ERR (1U << 2)
+#define SXIMMC_IDST_RECEIVE_INT (1U << 1)
+#define SXIMMC_IDST_TRANSMIT_INT (1U << 0)
+#define SXIMMC_IDST_ERROR \
+ (SXIMMC_IDST_ABNORMAL_INT_SUM | SXIMMC_IDST_CARD_ERR_SUM | \
+ SXIMMC_IDST_DES_INVALID | SXIMMC_IDST_FATAL_BUS_ERR)
+#define SXIMMC_IDST_COMPLETE \
+ (SXIMMC_IDST_RECEIVE_INT | SXIMMC_IDST_TRANSMIT_INT)
+
+struct sximmc_idma_descriptor {
+ uint32_t dma_config;
+#define SXIMMC_IDMA_CONFIG_DIC (1U << 1)
+#define SXIMMC_IDMA_CONFIG_LD (1U << 2)
+#define SXIMMC_IDMA_CONFIG_FD (1U << 3)
+#define SXIMMC_IDMA_CONFIG_CH (1U << 4)
+#define SXIMMC_IDMA_CONFIG_ER (1U << 5)
+#define SXIMMC_IDMA_CONFIG_CES (1U << 30)
+#define SXIMMC_IDMA_CONFIG_OWN (1U << 31)
+ uint32_t dma_buf_size;
+ uint32_t dma_buf_addr;
+ uint32_t dma_next;
+} __packed;
+
+#define SXIMMC_NDESC 32
+
+#define SXIMMC_DMA_FTRGLEVEL_A20 0x20070008
+#define SXIMMC_DMA_FTRGLEVEL_A80 0x200f0010
+
+int sximmc_match(struct device *, void *, void *);
+void sximmc_attach(struct device *, struct device *, void *);
+
+int sximmc_intr(void *);
+
+int sximmc_host_reset(sdmmc_chipset_handle_t);
+uint32_t sximmc_host_ocr(sdmmc_chipset_handle_t);
+int sximmc_host_maxblklen(sdmmc_chipset_handle_t);
+int sximmc_card_detect(sdmmc_chipset_handle_t);
+int sximmc_write_protect(sdmmc_chipset_handle_t);
+int sximmc_bus_power(sdmmc_chipset_handle_t, uint32_t);
+int sximmc_bus_clock(sdmmc_chipset_handle_t, int, int);
+int sximmc_bus_width(sdmmc_chipset_handle_t, int);
+void sximmc_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *);
+
+void sximmc_pwrseq_pre(uint32_t);
+void sximmc_pwrseq_post(uint32_t);
+
+struct sdmmc_chip_functions sximmc_chip_functions = {
+ .host_reset = sximmc_host_reset,
+ .host_ocr = sximmc_host_ocr,
+ .host_maxblklen = sximmc_host_maxblklen,
+ .card_detect = sximmc_card_detect,
+ .bus_power = sximmc_bus_power,
+ .bus_clock = sximmc_bus_clock,
+ .bus_width = sximmc_bus_width,
+ .exec_command = sximmc_exec_command,
+};
+
+struct sximmc_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_bst;
+ bus_space_handle_t sc_bsh;
+ bus_space_handle_t sc_clk_bsh;
+ bus_dma_tag_t sc_dmat;
+ int sc_node;
+
+ int sc_use_dma;
+
+ void *sc_ih;
+
+ struct device *sc_sdmmc_dev;
+
+ uint32_t sc_fifo_reg;
+ uint32_t sc_dma_ftrglevel;
+
+ uint32_t sc_idma_xferlen;
+ bus_dma_segment_t sc_idma_segs[1];
+ int sc_idma_nsegs;
+ bus_size_t sc_idma_size;
+ bus_dmamap_t sc_idma_map;
+ int sc_idma_ndesc;
+ char *sc_idma_desc;
+
+ uint32_t sc_intr_rint;
+ uint32_t sc_intr_mint;
+ uint32_t sc_idma_idst;
+
+ uint32_t sc_gpio[4];
+ uint32_t sc_vmmc;
+ uint32_t sc_pwrseq;
+ uint32_t sc_vdd;
+};
+
+struct cfdriver sximmc_cd = {
+ NULL, "sximmc", DV_DULL
+};
+
+struct cfattach sximmc_ca = {
+ sizeof(struct sximmc_softc), sximmc_match, sximmc_attach
+};
+
+#define MMC_WRITE(sc, reg, val) \
+ bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
+#define MMC_READ(sc, reg) \
+ bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
+
+int sximmc_set_clock(struct sximmc_softc *sc, u_int);
+
+int
+sximmc_match(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+
+ if (OF_is_compatible(faa->fa_node, "allwinner,sun4i-a10-mmc"))
+ return 1;
+ if (OF_is_compatible(faa->fa_node, "allwinner,sun5i-a13-mmc"))
+ return 1;
+ if (OF_is_compatible(faa->fa_node, "allwinner,sun7i-a20-mmc"))
+ return 1;
+ if (OF_is_compatible(faa->fa_node, "allwinner,sun9i-a80-mmc"))
+ return 1;
+
+ return 0;
+}
+
+int
+sximmc_idma_setup(struct sximmc_softc *sc)
+{
+ int error;
+
+ if (OF_is_compatible(sc->sc_node, "allwinner,sun4i-a10-mmc")) {
+ sc->sc_idma_xferlen = 0x2000;
+ } else {
+ sc->sc_idma_xferlen = 0x10000;
+ }
+
+ sc->sc_idma_ndesc = SXIMMC_NDESC;
+ sc->sc_idma_size = sizeof(struct sximmc_idma_descriptor) *
+ sc->sc_idma_ndesc;
+ error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_idma_size, 0,
+ sc->sc_idma_size, sc->sc_idma_segs, 1,
+ &sc->sc_idma_nsegs, BUS_DMA_WAITOK);
+ if (error)
+ return error;
+ error = bus_dmamem_map(sc->sc_dmat, sc->sc_idma_segs,
+ sc->sc_idma_nsegs, sc->sc_idma_size,
+ &sc->sc_idma_desc, BUS_DMA_WAITOK);
+ if (error)
+ goto free;
+ error = bus_dmamap_create(sc->sc_dmat, sc->sc_idma_size, 1,
+ sc->sc_idma_size, 0, BUS_DMA_WAITOK, &sc->sc_idma_map);
+ if (error)
+ goto unmap;
+ error = bus_dmamap_load(sc->sc_dmat, sc->sc_idma_map,
+ sc->sc_idma_desc, sc->sc_idma_size, NULL, BUS_DMA_WAITOK);
+ if (error)
+ goto destroy;
+ return 0;
+
+destroy:
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_idma_map);
+unmap:
+ bus_dmamem_unmap(sc->sc_dmat, sc->sc_idma_desc, sc->sc_idma_size);
+free:
+ bus_dmamem_free(sc->sc_dmat, sc->sc_idma_segs, sc->sc_idma_nsegs);
+ return error;
+}
+
+void
+sximmc_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct sximmc_softc *sc = (struct sximmc_softc *)self;
+ struct fdt_attach_args *faa = aux;
+ struct sdmmcbus_attach_args saa;
+ int node, width;
+
+ if (faa->fa_nreg < 1)
+ return;
+
+ sc->sc_node = faa->fa_node;
+ sc->sc_bst = faa->fa_iot;
+ sc->sc_dmat = faa->fa_dmat;
+
+ if (bus_space_map(sc->sc_bst, faa->fa_reg[0].addr,
+ faa->fa_reg[0].size, 0, &sc->sc_bsh)) {
+ printf(": can't map registers\n");
+ return;
+ }
+
+ sc->sc_use_dma = 1;
+
+ printf("\n");
+
+ pinctrl_byname(faa->fa_node, "default");
+
+ /* enable clock */
+ clock_enable(faa->fa_node, NULL);
+ delay(5000);
+
+ reset_deassert_all(faa->fa_node);
+
+ /*
+ * The FIFO register is in a different location on the
+ * Allwinner A31 and later generations. Unfortunately the
+ * compatible string wasn't changed, so we need to look at the
+ * root node to pick the right register.
+ *
+ * XXX Should we always use DMA (like Linux does) to avoid
+ * this issue?
+ */
+ node = OF_finddevice("/");
+ if (OF_is_compatible(node, "allwinner,sun4i-a10") ||
+ OF_is_compatible(node, "allwinner,sun5i-a10s") ||
+ OF_is_compatible(node, "allwinner,sun5i-a13") ||
+ OF_is_compatible(node, "allwinner,sun7i-a20"))
+ sc->sc_fifo_reg = SXIMMC_FIFO_A10;
+ else
+ sc->sc_fifo_reg = SXIMMC_FIFO_A31;
+
+ if (OF_is_compatible(sc->sc_node, "allwinner,sun9i-a80-mmc"))
+ sc->sc_dma_ftrglevel = SXIMMC_DMA_FTRGLEVEL_A80;
+ else
+ sc->sc_dma_ftrglevel = SXIMMC_DMA_FTRGLEVEL_A20;
+
+ if (sc->sc_use_dma) {
+ if (sximmc_idma_setup(sc) != 0) {
+ printf("%s: failed to setup DMA\n", self->dv_xname);
+ return;
+ }
+ }
+
+ OF_getpropintarray(sc->sc_node, "cd-gpios", sc->sc_gpio,
+ sizeof(sc->sc_gpio));
+ gpio_controller_config_pin(sc->sc_gpio, GPIO_CONFIG_INPUT);
+
+ sc->sc_vmmc = OF_getpropint(sc->sc_node, "vmmc-supply", 0);
+ sc->sc_pwrseq = OF_getpropint(sc->sc_node, "mmc-pwrseq", 0);
+
+ sc->sc_ih = arm_intr_establish_fdt(faa->fa_node, IPL_BIO,
+ sximmc_intr, sc, sc->sc_dev.dv_xname);
+ if (sc->sc_ih == NULL) {
+ printf(": can't to establish interrupt\n");
+ return;
+ }
+
+ sximmc_bus_width(sc, 1);
+ sximmc_set_clock(sc, 400);
+ sximmc_host_reset(sc);
+
+ memset(&saa, 0, sizeof(saa));
+ saa.saa_busname = "sdmmc";
+ saa.sct = &sximmc_chip_functions;
+ saa.sch = sc;
+#if 0
+ saa.saa_clkmin = 400;
+ saa.saa_clkmax = awin_chip_id() == AWIN_CHIP_ID_A80 ? 48000 : 50000;
+#endif
+
+ saa.caps = SMC_CAPS_SD_HIGHSPEED | SMC_CAPS_MMC_HIGHSPEED;
+
+ width = OF_getpropint(sc->sc_node, "bus-width", 1);
+ if (width >= 8)
+ saa.caps |= SMC_CAPS_8BIT_MODE;
+ if (width >= 4)
+ saa.caps |= SMC_CAPS_4BIT_MODE;
+
+ if (sc->sc_use_dma) {
+ saa.dmat = sc->sc_dmat;
+ saa.caps |= SMC_CAPS_DMA;
+ }
+
+ sc->sc_sdmmc_dev = config_found(self, &saa, NULL);
+}
+
+int
+sximmc_set_clock(struct sximmc_softc *sc, u_int freq)
+{
+ if (freq > 0) {
+ if (clock_set_frequency(sc->sc_node, "mmc", freq * 1000))
+ return EIO;
+ clock_enable(sc->sc_node, "mmc");
+ delay(20000);
+ } else
+ clock_disable(sc->sc_node, "mmc");
+
+ return 0;
+}
+
+
+int
+sximmc_intr(void *priv)
+{
+ struct sximmc_softc *sc = priv;
+ uint32_t idst, rint, mint;
+
+ idst = MMC_READ(sc, SXIMMC_IDST);
+ rint = MMC_READ(sc, SXIMMC_RINT);
+ mint = MMC_READ(sc, SXIMMC_MINT);
+ if (!idst && !rint && !mint)
+ return 0;
+
+ MMC_WRITE(sc, SXIMMC_IDST, idst);
+ MMC_WRITE(sc, SXIMMC_RINT, rint);
+ MMC_WRITE(sc, SXIMMC_MINT, mint);
+
+#ifdef SXIMMC_DEBUG
+ printf("%s: mmc intr idst=%08X rint=%08X mint=%08X\n",
+ sc->sc_dev.dv_xname, idst, rint, mint);
+#endif
+
+ if (idst) {
+ sc->sc_idma_idst |= idst;
+ wakeup(&sc->sc_idma_idst);
+ }
+
+ if (rint) {
+ sc->sc_intr_rint |= rint;
+ wakeup(&sc->sc_intr_rint);
+ }
+
+ return 1;
+}
+
+int
+sximmc_wait_rint(struct sximmc_softc *sc, uint32_t mask, int timeout)
+{
+ int retry;
+ int error;
+
+ splassert(IPL_BIO);
+
+ if (sc->sc_intr_rint & mask)
+ return 0;
+
+ retry = sc->sc_use_dma ? (timeout / hz) : 10000;
+
+ while (retry > 0) {
+ if (sc->sc_use_dma) {
+ error = tsleep(&sc->sc_intr_rint, PWAIT, "rint", hz);
+ if (error && error != EWOULDBLOCK)
+ return error;
+ if (sc->sc_intr_rint & mask)
+ return 0;
+ } else {
+ sc->sc_intr_rint |= MMC_READ(sc, SXIMMC_RINT);
+ if (sc->sc_intr_rint & mask)
+ return 0;
+ delay(1000);
+ }
+ --retry;
+ }
+
+ return ETIMEDOUT;
+}
+
+void
+sximmc_led(struct sximmc_softc *sc, int on)
+{
+}
+
+int
+sximmc_host_reset(sdmmc_chipset_handle_t sch)
+{
+ struct sximmc_softc *sc = sch;
+ int retry = 1000;
+
+#if 0
+ if (awin_chip_id() == AWIN_CHIP_ID_A80) {
+ if (sc->sc_mmc_port == 2 || sc->sc_mmc_port == 3) {
+ MMC_WRITE(sc, SXIMMC_HWRST, 0);
+ delay(10);
+ MMC_WRITE(sc, SXIMMC_HWRST, 1);
+ delay(300);
+ }
+ }
+#endif
+
+ MMC_WRITE(sc, SXIMMC_GCTRL,
+ MMC_READ(sc, SXIMMC_GCTRL) | SXIMMC_GCTRL_RESET);
+ while (--retry > 0) {
+ if (!(MMC_READ(sc, SXIMMC_GCTRL) & SXIMMC_GCTRL_RESET))
+ break;
+ delay(100);
+ }
+#ifdef SXIMMC_DEBUG
+ if (retry == 0)
+ printf("%s: host reset failed\n", sc->sc_dev.dv_xname);
+ else
+ printf("%s: host reset succeeded\n", sc->sc_dev.dv_xname);
+#endif
+
+ MMC_WRITE(sc, SXIMMC_TIMEOUT, 0xffffffff);
+
+ MMC_WRITE(sc, SXIMMC_IMASK,
+ SXIMMC_INT_CMD_DONE | SXIMMC_INT_ERROR |
+ SXIMMC_INT_DATA_OVER | SXIMMC_INT_AUTO_CMD_DONE);
+
+ MMC_WRITE(sc, SXIMMC_GCTRL,
+ MMC_READ(sc, SXIMMC_GCTRL) | SXIMMC_GCTRL_INTEN);
+
+ return 0;
+}
+
+uint32_t
+sximmc_host_ocr(sdmmc_chipset_handle_t sch)
+{
+#if 0
+ return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V | MMC_OCR_HCS;
+#else
+ return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V;
+#endif
+}
+
+int
+sximmc_host_maxblklen(sdmmc_chipset_handle_t sch)
+{
+#if 0
+ return 8192;
+#else
+ return 512;
+#endif
+}
+
+int
+sximmc_card_detect(sdmmc_chipset_handle_t sch)
+{
+ struct sximmc_softc *sc = sch;
+ int inverted, val;
+
+ if (OF_getproplen(sc->sc_node, "non-removable") == 0)
+ return 1;
+
+ val = gpio_controller_get_pin(sc->sc_gpio);
+
+ inverted = (OF_getproplen(sc->sc_node, "cd-inverted") == 0);
+ return inverted ? !val : val;;
+}
+
+int
+sximmc_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
+{
+ struct sximmc_softc *sc = sch;
+ uint32_t vdd = 0;
+
+ if (ISSET(ocr, MMC_OCR_3_2V_3_3V|MMC_OCR_3_3V_3_4V))
+ vdd = 3300000;
+
+ if (sc->sc_vdd == 0 && vdd > 0)
+ sximmc_pwrseq_pre(sc->sc_pwrseq);
+
+ /* enable mmc power */
+ if (sc->sc_vmmc && vdd > 0)
+ regulator_enable(sc->sc_vmmc);
+
+ if (sc->sc_vdd == 0 && vdd > 0)
+ sximmc_pwrseq_post(sc->sc_pwrseq);
+
+ sc->sc_vdd = vdd;
+ return 0;
+}
+
+int
+sximmc_update_clock(struct sximmc_softc *sc)
+{
+ uint32_t cmd;
+ int retry;
+
+#ifdef SXIMMC_DEBUG
+ printf("%s: update clock\n", sc->sc_dev.dv_xname);
+#endif
+
+ cmd = SXIMMC_CMD_START |
+ SXIMMC_CMD_UPCLK_ONLY |
+ SXIMMC_CMD_WAIT_PRE_OVER;
+ MMC_WRITE(sc, SXIMMC_CMD, cmd);
+ retry = 0xfffff;
+ while (--retry > 0) {
+ if (!(MMC_READ(sc, SXIMMC_CMD) & SXIMMC_CMD_START))
+ break;
+ delay(10);
+ }
+
+ if (retry == 0) {
+ printf("%s: timeout updating clock\n", sc->sc_dev.dv_xname);
+#ifdef SXIMMC_DEBUG
+ printf("GCTRL: 0x%08x\n", MMC_READ(sc, SXIMMC_GCTRL));
+ printf("CLKCR: 0x%08x\n", MMC_READ(sc, SXIMMC_CLKCR));
+ printf("TIMEOUT: 0x%08x\n", MMC_READ(sc, SXIMMC_TIMEOUT));
+ printf("WIDTH: 0x%08x\n", MMC_READ(sc, SXIMMC_WIDTH));
+ printf("CMD: 0x%08x\n", MMC_READ(sc, SXIMMC_CMD));
+ printf("MINT: 0x%08x\n", MMC_READ(sc, SXIMMC_MINT));
+ printf("RINT: 0x%08x\n", MMC_READ(sc, SXIMMC_RINT));
+ printf("STATUS: 0x%08x\n", MMC_READ(sc, SXIMMC_STATUS));
+#endif
+ return ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+int
+sximmc_bus_clock(sdmmc_chipset_handle_t sch, int freq, int timing)
+{
+ struct sximmc_softc *sc = sch;
+ uint32_t clkcr;
+
+ clkcr = MMC_READ(sc, SXIMMC_CLKCR);
+ if (clkcr & SXIMMC_CLKCR_CARDCLKON) {
+ clkcr &= ~SXIMMC_CLKCR_CARDCLKON;
+ MMC_WRITE(sc, SXIMMC_CLKCR, clkcr);
+ if (sximmc_update_clock(sc) != 0)
+ return 1;
+ }
+
+ if (freq) {
+ clkcr &= ~SXIMMC_CLKCR_DIV;
+ MMC_WRITE(sc, SXIMMC_CLKCR, clkcr);
+ if (sximmc_update_clock(sc) != 0)
+ return 1;
+
+ if (sximmc_set_clock(sc, freq) != 0)
+ return 1;
+
+ clkcr |= SXIMMC_CLKCR_CARDCLKON;
+ MMC_WRITE(sc, SXIMMC_CLKCR, clkcr);
+ if (sximmc_update_clock(sc) != 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+sximmc_bus_width(sdmmc_chipset_handle_t sch, int width)
+{
+ struct sximmc_softc *sc = sch;
+
+#ifdef SXIMMC_DEBUG
+ printf("%s: width = %d\n", sc->sc_dev.dv_xname, width);
+#endif
+
+ switch (width) {
+ case 1:
+ MMC_WRITE(sc, SXIMMC_WIDTH, SXIMMC_WIDTH_1);
+ break;
+ case 4:
+ MMC_WRITE(sc, SXIMMC_WIDTH, SXIMMC_WIDTH_4);
+ break;
+ case 8:
+ MMC_WRITE(sc, SXIMMC_WIDTH, SXIMMC_WIDTH_8);
+ break;
+ default:
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+sximmc_pio_wait(struct sximmc_softc *sc, struct sdmmc_command *cmd)
+{
+ int retry = 0xfffff;
+ uint32_t bit = (cmd->c_flags & SCF_CMD_READ) ?
+ SXIMMC_STATUS_FIFO_EMPTY : SXIMMC_STATUS_FIFO_FULL;
+
+ while (--retry > 0) {
+ uint32_t status = MMC_READ(sc, SXIMMC_STATUS);
+ if (!(status & bit))
+ return 0;
+ delay(10);
+ }
+
+ return ETIMEDOUT;
+}
+
+int
+sximmc_pio_transfer(struct sximmc_softc *sc, struct sdmmc_command *cmd)
+{
+ uint32_t *datap = (uint32_t *)cmd->c_data;
+ int i;
+
+ for (i = 0; i < (cmd->c_resid >> 2); i++) {
+ if (sximmc_pio_wait(sc, cmd))
+ return ETIMEDOUT;
+ if (cmd->c_flags & SCF_CMD_READ) {
+ datap[i] = MMC_READ(sc, sc->sc_fifo_reg);
+ } else {
+ MMC_WRITE(sc, sc->sc_fifo_reg, datap[i]);
+ }
+ }
+
+ return 0;
+}
+
+int
+sximmc_dma_prepare(struct sximmc_softc *sc, struct sdmmc_command *cmd)
+{
+ struct sximmc_idma_descriptor *dma = (void *)sc->sc_idma_desc;
+ bus_addr_t desc_paddr = sc->sc_idma_map->dm_segs[0].ds_addr;
+ bus_size_t off;
+ int desc, resid, seg;
+ uint32_t val;
+
+ desc = 0;
+ for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
+ bus_addr_t paddr = cmd->c_dmamap->dm_segs[seg].ds_addr;
+ bus_size_t len = cmd->c_dmamap->dm_segs[seg].ds_len;
+ resid = min(len, cmd->c_resid);
+ off = 0;
+ while (resid > 0) {
+ if (desc == sc->sc_idma_ndesc)
+ break;
+ len = min(sc->sc_idma_xferlen, resid);
+ dma[desc].dma_buf_size = htole32(len);
+ dma[desc].dma_buf_addr = htole32(paddr + off);
+ dma[desc].dma_config = htole32(SXIMMC_IDMA_CONFIG_CH |
+ SXIMMC_IDMA_CONFIG_OWN);
+ cmd->c_resid -= len;
+ resid -= len;
+ off += len;
+ if (desc == 0) {
+ dma[desc].dma_config |=
+ htole32(SXIMMC_IDMA_CONFIG_FD);
+ }
+ if (cmd->c_resid == 0) {
+ dma[desc].dma_config |=
+ htole32(SXIMMC_IDMA_CONFIG_LD);
+ dma[desc].dma_config |=
+ htole32(SXIMMC_IDMA_CONFIG_ER);
+ dma[desc].dma_next = 0;
+ } else {
+ dma[desc].dma_config |=
+ htole32(SXIMMC_IDMA_CONFIG_DIC);
+ dma[desc].dma_next = htole32(
+ desc_paddr + ((desc+1) *
+ sizeof(struct sximmc_idma_descriptor)));
+ }
+ ++desc;
+ }
+ }
+ if (desc == sc->sc_idma_ndesc) {
+ printf("%s: not enough descriptors for %d byte transfer!\n",
+ sc->sc_dev.dv_xname, cmd->c_datalen);
+ return EIO;
+ }
+
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0,
+ sc->sc_idma_size, BUS_DMASYNC_PREWRITE);
+
+ sc->sc_idma_idst = 0;
+
+ val = MMC_READ(sc, SXIMMC_GCTRL);
+ val |= SXIMMC_GCTRL_DMAEN;
+ val |= SXIMMC_GCTRL_INTEN;
+ MMC_WRITE(sc, SXIMMC_GCTRL, val);
+ val |= SXIMMC_GCTRL_DMARESET;
+ MMC_WRITE(sc, SXIMMC_GCTRL, val);
+ MMC_WRITE(sc, SXIMMC_DMAC, SXIMMC_DMAC_SOFTRESET);
+ MMC_WRITE(sc, SXIMMC_DMAC,
+ SXIMMC_DMAC_IDMA_ON|SXIMMC_DMAC_FIX_BURST);
+ val = MMC_READ(sc, SXIMMC_IDIE);
+ val &= ~(SXIMMC_IDST_RECEIVE_INT|SXIMMC_IDST_TRANSMIT_INT);
+ if (cmd->c_flags & SCF_CMD_READ)
+ val |= SXIMMC_IDST_RECEIVE_INT;
+ else
+ val |= SXIMMC_IDST_TRANSMIT_INT;
+ MMC_WRITE(sc, SXIMMC_IDIE, val);
+ MMC_WRITE(sc, SXIMMC_DLBA, desc_paddr);
+ MMC_WRITE(sc, SXIMMC_FTRGLEVEL, sc->sc_dma_ftrglevel);
+
+ return 0;
+}
+
+void
+sximmc_dma_complete(struct sximmc_softc *sc)
+{
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_idma_map, 0,
+ sc->sc_idma_size, BUS_DMASYNC_POSTWRITE);
+}
+
+void
+sximmc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
+{
+ struct sximmc_softc *sc = sch;
+ uint32_t cmdval = SXIMMC_CMD_START;
+ int retry;
+ int s;
+
+#ifdef SXIMMC_DEBUG
+ printf("%s: opcode %d flags 0x%x data %p datalen %d blklen %d\n",
+ sc->sc_dev.dv_xname, cmd->c_opcode, cmd->c_flags,
+ cmd->c_data, cmd->c_datalen, cmd->c_blklen);
+#endif
+
+ s = splbio();
+
+ if (cmd->c_opcode == 0)
+ cmdval |= SXIMMC_CMD_SEND_INIT_SEQ;
+ if (cmd->c_flags & SCF_RSP_PRESENT)
+ cmdval |= SXIMMC_CMD_RSP_EXP;
+ if (cmd->c_flags & SCF_RSP_136)
+ cmdval |= SXIMMC_CMD_LONG_RSP;
+ if (cmd->c_flags & SCF_RSP_CRC)
+ cmdval |= SXIMMC_CMD_CHECK_RSP_CRC;
+
+ if (cmd->c_datalen > 0) {
+ uint16_t blksize;
+ uint16_t blkcount;
+
+ cmdval |= SXIMMC_CMD_DATA_EXP | SXIMMC_CMD_WAIT_PRE_OVER;
+ if (!ISSET(cmd->c_flags, SCF_CMD_READ)) {
+ cmdval |= SXIMMC_CMD_WRITE;
+ }
+
+ blksize = MIN(cmd->c_datalen, cmd->c_blklen);
+ blkcount = cmd->c_datalen / blksize;
+ if (blkcount > 1) {
+ cmdval |= SXIMMC_CMD_SEND_AUTO_STOP;
+ }
+
+ MMC_WRITE(sc, SXIMMC_BLKSZ, blksize);
+ MMC_WRITE(sc, SXIMMC_BYTECNT, blkcount * blksize);
+ }
+
+ sc->sc_intr_rint = 0;
+
+#if 0
+ if (awin_chip_id() == AWIN_CHIP_ID_A80) {
+ MMC_WRITE(sc, SXIMMC_A12A,
+ (cmdval & SXIMMC_CMD_SEND_AUTO_STOP) ? 0 : 0xffff);
+ }
+#endif
+
+ MMC_WRITE(sc, SXIMMC_ARG, cmd->c_arg);
+
+#ifdef SXIMMC_DEBUG
+ printf("%s: cmdval = %08x\n", sc->sc_dev.dv_xname, cmdval);
+#endif
+
+ if (cmd->c_datalen == 0) {
+ MMC_WRITE(sc, SXIMMC_CMD, cmdval | cmd->c_opcode);
+ } else {
+ cmd->c_resid = cmd->c_datalen;
+ sximmc_led(sc, 0);
+ if (cmd->c_dmamap && sc->sc_use_dma) {
+ cmd->c_error = sximmc_dma_prepare(sc, cmd);
+ MMC_WRITE(sc, SXIMMC_CMD, cmdval | cmd->c_opcode);
+ if (cmd->c_error == 0) {
+ cmd->c_error = tsleep(&sc->sc_idma_idst,
+ PWAIT, "idma", hz*10);
+ }
+ sximmc_dma_complete(sc);
+ if (sc->sc_idma_idst & SXIMMC_IDST_ERROR) {
+ cmd->c_error = EIO;
+ } else if (!(sc->sc_idma_idst & SXIMMC_IDST_COMPLETE)) {
+ cmd->c_error = ETIMEDOUT;
+ }
+ } else {
+ splx(s);
+ MMC_WRITE(sc, SXIMMC_CMD, cmdval | cmd->c_opcode);
+ cmd->c_error = sximmc_pio_transfer(sc, cmd);
+ s = splbio();
+ }
+ sximmc_led(sc, 1);
+ if (cmd->c_error) {
+#ifdef SXIMMC_DEBUG
+ printf("%s: xfer failed, error %d\n",
+ sc->sc_dev.dv_xname, cmd->c_error);
+#endif
+ goto done;
+ }
+ }
+
+ cmd->c_error = sximmc_wait_rint(sc,
+ SXIMMC_INT_ERROR|SXIMMC_INT_CMD_DONE, hz * 10);
+ if (cmd->c_error == 0 && (sc->sc_intr_rint & SXIMMC_INT_ERROR)) {
+ if (sc->sc_intr_rint & SXIMMC_INT_RESP_TIMEOUT) {
+ cmd->c_error = ETIMEDOUT;
+ } else {
+ cmd->c_error = EIO;
+ }
+ }
+ if (cmd->c_error) {
+#ifdef SXIMMC_DEBUG
+ printf("%s: cmd failed, error %d\n",
+ sc->sc_dev.dv_xname, cmd->c_error);
+#endif
+ goto done;
+ }
+
+ if (cmd->c_datalen > 0) {
+ cmd->c_error = sximmc_wait_rint(sc,
+ SXIMMC_INT_ERROR|
+ SXIMMC_INT_AUTO_CMD_DONE|
+ SXIMMC_INT_DATA_OVER,
+ hz*10);
+ if (cmd->c_error == 0 &&
+ (sc->sc_intr_rint & SXIMMC_INT_ERROR)) {
+ cmd->c_error = ETIMEDOUT;
+ }
+ if (cmd->c_error) {
+#ifdef SXIMMC_DEBUG
+ printf("%s: data timeout, rint = %08x\n",
+ sc->sc_dev.dv_xname, sc->sc_intr_rint);
+#endif
+ cmd->c_error = ETIMEDOUT;
+ goto done;
+ }
+ }
+
+ if (cmd->c_flags & SCF_RSP_PRESENT) {
+ if (cmd->c_flags & SCF_RSP_136) {
+ cmd->c_resp[0] = MMC_READ(sc, SXIMMC_RESP0);
+ cmd->c_resp[1] = MMC_READ(sc, SXIMMC_RESP1);
+ cmd->c_resp[2] = MMC_READ(sc, SXIMMC_RESP2);
+ cmd->c_resp[3] = MMC_READ(sc, SXIMMC_RESP3);
+ if (cmd->c_flags & SCF_RSP_CRC) {
+ cmd->c_resp[0] = (cmd->c_resp[0] >> 8) |
+ (cmd->c_resp[1] << 24);
+ cmd->c_resp[1] = (cmd->c_resp[1] >> 8) |
+ (cmd->c_resp[2] << 24);
+ cmd->c_resp[2] = (cmd->c_resp[2] >> 8) |
+ (cmd->c_resp[3] << 24);
+ cmd->c_resp[3] = (cmd->c_resp[3] >> 8);
+ }
+ } else {
+ cmd->c_resp[0] = MMC_READ(sc, SXIMMC_RESP0);
+ }
+ }
+
+done:
+ cmd->c_flags |= SCF_ITSDONE;
+ splx(s);
+
+ if (cmd->c_error) {
+#ifdef SXIMMC_DEBUG
+ printf("%s: i/o error %d\n", sc->sc_dev.dv_xname,
+ cmd->c_error);
+#endif
+ MMC_WRITE(sc, SXIMMC_GCTRL,
+ MMC_READ(sc, SXIMMC_GCTRL) |
+ SXIMMC_GCTRL_DMARESET | SXIMMC_GCTRL_FIFORESET);
+ for (retry = 0; retry < 1000; retry++) {
+ if (!(MMC_READ(sc, SXIMMC_GCTRL) & SXIMMC_GCTRL_RESET))
+ break;
+ delay(10);
+ }
+ sximmc_host_reset(sc);
+ sximmc_update_clock(sc);
+ }
+
+ if (!cmd->c_dmamap || !sc->sc_use_dma) {
+ MMC_WRITE(sc, SXIMMC_GCTRL,
+ MMC_READ(sc, SXIMMC_GCTRL) | SXIMMC_GCTRL_FIFORESET);
+ }
+}
+
+void
+sximmc_pwrseq_pre(uint32_t phandle)
+{
+ uint32_t *gpios, *gpio;
+ int node;
+ int len;
+
+ node = OF_getnodebyphandle(phandle);
+ if (node == 0)
+ return;
+
+ if (!OF_is_compatible(node, "mmc-pwrseq-simple"))
+ return;
+
+ pinctrl_byname(node, "default");
+
+ clock_enable(node, "ext_clock");
+
+ len = OF_getproplen(node, "reset-gpios");
+ if (len <= 0)
+ return;
+
+ gpios = malloc(len, M_TEMP, M_WAITOK);
+ OF_getpropintarray(node, "reset-gpios", gpios, len);
+
+ gpio = gpios;
+ while (gpio && gpio < gpios + (len / sizeof(uint32_t))) {
+ gpio_controller_config_pin(gpio, GPIO_CONFIG_OUTPUT);
+ gpio_controller_set_pin(gpio, 1);
+ gpio = gpio_controller_next_pin(gpio);
+ }
+
+ free(gpios, M_TEMP, len);
+}
+
+void
+sximmc_pwrseq_post(uint32_t phandle)
+{
+ uint32_t *gpios, *gpio;
+ int node;
+ int len;
+
+ node = OF_getnodebyphandle(phandle);
+ if (node == 0)
+ return;
+
+ if (!OF_is_compatible(node, "mmc-pwrseq-simple"))
+ return;
+
+ len = OF_getproplen(node, "reset-gpios");
+ if (len <= 0)
+ return;
+
+ gpios = malloc(len, M_TEMP, M_WAITOK);
+ OF_getpropintarray(node, "reset-gpios", gpios, len);
+
+ gpio = gpios;
+ while (gpio && gpio < gpios + (len / sizeof(uint32_t))) {
+ gpio_controller_set_pin(gpio, 0);
+ gpio = gpio_controller_next_pin(gpio);
+ }
+
+ free(gpios, M_TEMP, len);
+}
diff --git a/sys/dev/fdt/sxipio.c b/sys/dev/fdt/sxipio.c
new file mode 100644
index 00000000000..ba173e2b8c1
--- /dev/null
+++ b/sys/dev/fdt/sxipio.c
@@ -0,0 +1,452 @@
+/* $OpenBSD: sxipio.c,v 1.1 2017/01/21 08:26:49 patrick Exp $ */
+/*
+ * Copyright (c) 2010 Miodrag Vallat.
+ * Copyright (c) 2013 Artturi Alm
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/gpio.h>
+#include <sys/evcount.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+#include <machine/intr.h>
+
+#include <dev/gpio/gpiovar.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_clock.h>
+#include <dev/ofw/ofw_gpio.h>
+#include <dev/ofw/ofw_pinctrl.h>
+#include <dev/ofw/fdt.h>
+
+#include <dev/fdt/sunxireg.h>
+#include <dev/fdt/sxipiovar.h>
+
+#include "gpio.h"
+
+#define SXIPIO_NPORT 9
+
+struct sxipio_softc;
+
+struct sxipio_gpio {
+ struct sxipio_softc *sc;
+ int port;
+};
+
+struct intrhand {
+ int (*ih_func)(void *); /* handler */
+ void *ih_arg; /* arg for handler */
+ int ih_ipl; /* IPL_* */
+ int ih_irq; /* IRQ number */
+ int ih_gpio; /* gpio pin */
+ struct evcount ih_count;
+ char *ih_name;
+};
+
+struct sxipio_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ void *sc_ih_h;
+ void *sc_ih_l;
+ int sc_max_il;
+ int sc_min_il;
+
+ struct sxipio_pin *sc_pins;
+ int sc_npins;
+ struct gpio_controller sc_gc;
+
+ struct sxipio_gpio sc_gpio[SXIPIO_NPORT];
+ struct gpio_chipset_tag sc_gpio_tag[SXIPIO_NPORT];
+ gpio_pin_t sc_gpio_pins[SXIPIO_NPORT][32];
+
+ struct intrhand *sc_handlers[32];
+};
+
+#define SXIPIO_CFG(port, pin) 0x00 + ((port) * 0x24) + (((pin) >> 3) * 0x04)
+#define SXIPIO_DAT(port) 0x10 + ((port) * 0x24)
+#define SXIPIO_DRV(port, pin) 0x14 + ((port) * 0x24) + (((pin) >> 4) * 0x04)
+#define SXIPIO_PUL(port, pin) 0x1c + ((port) * 0x24) + (((pin) >> 4) * 0x04)
+#define SXIPIO_INT_CFG0(port) 0x0200 + ((port) * 0x04)
+#define SXIPIO_INT_CTL 0x0210
+#define SXIPIO_INT_STA 0x0214
+#define SXIPIO_INT_DEB 0x0218 /* debounce register */
+
+#define SXIPIO_GPIO_IN 0
+#define SXIPIO_GPIO_OUT 1
+
+int sxipio_match(struct device *, void *, void *);
+void sxipio_attach(struct device *, struct device *, void *);
+
+struct cfattach sxipio_ca = {
+ sizeof (struct sxipio_softc), sxipio_match, sxipio_attach
+};
+
+struct cfdriver sxipio_cd = {
+ NULL, "sxipio", DV_DULL
+};
+
+void sxipio_attach_gpio(struct device *);
+int sxipio_pinctrl(uint32_t, void *);
+void sxipio_config_pin(void *, uint32_t *, int);
+int sxipio_get_pin(void *, uint32_t *);
+void sxipio_set_pin(void *, uint32_t *, int);
+
+#include "sxipio_pins.h"
+
+struct sxipio_pins {
+ const char *compat;
+ struct sxipio_pin *pins;
+ int npins;
+};
+
+struct sxipio_pins sxipio_pins[] = {
+ {
+ "allwinner,sun4i-a10-pinctrl",
+ sun4i_a10_pins, nitems(sun4i_a10_pins)
+ },
+ {
+ "allwinner,sun5i-a13-pinctrl",
+ sun5i_a13_pins, nitems(sun5i_a13_pins)
+ },
+ {
+ "allwinner,sun5i-a10s-pinctrl",
+ sun5i_a10s_pins, nitems(sun5i_a10s_pins)
+ },
+ {
+ "allwinner,sun7i-a20-pinctrl",
+ sun7i_a20_pins, nitems(sun7i_a20_pins)
+ },
+ {
+ "allwinner,sun8i-h3-pinctrl",
+ sun8i_h3_pins, nitems(sun8i_h3_pins)
+ },
+ {
+ "allwinner,sun8i-h3-r-pinctrl",
+ sun8i_h3_r_pins, nitems(sun8i_h3_r_pins)
+ },
+ {
+ "allwinner,sun9i-a80-pinctrl",
+ sun9i_a80_pins, nitems(sun9i_a80_pins)
+ },
+ {
+ "allwinner,sun9i-a80-r-pinctrl",
+ sun9i_a80_r_pins, nitems(sun9i_a80_r_pins)
+ },
+ {
+ "allwinner,sun50i-a64-pinctrl",
+ sun50i_a64_pins, nitems(sun50i_a64_pins)
+ }
+};
+
+int
+sxipio_match(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+ int i;
+
+ for (i = 0; i < nitems(sxipio_pins); i++) {
+ if (OF_is_compatible(faa->fa_node, sxipio_pins[i].compat))
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+sxipio_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct sxipio_softc *sc = (struct sxipio_softc *)self;
+ struct fdt_attach_args *faa = aux;
+ int i;
+
+ sc->sc_iot = faa->fa_iot;
+ if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
+ faa->fa_reg[0].size, 0, &sc->sc_ioh))
+ panic("%s: bus_space_map failed!", __func__);
+
+ clock_enable_all(faa->fa_node);
+ reset_deassert_all(faa->fa_node);
+
+ for (i = 0; i < nitems(sxipio_pins); i++) {
+ if (OF_is_compatible(faa->fa_node, sxipio_pins[i].compat)) {
+ sc->sc_pins = sxipio_pins[i].pins;
+ sc->sc_npins = sxipio_pins[i].npins;
+ break;
+ }
+ }
+
+ KASSERT(sc->sc_pins);
+ pinctrl_register(faa->fa_node, sxipio_pinctrl, sc);
+
+ sc->sc_gc.gc_node = faa->fa_node;
+ sc->sc_gc.gc_cookie = sc;
+ sc->sc_gc.gc_config_pin = sxipio_config_pin;
+ sc->sc_gc.gc_get_pin = sxipio_get_pin;
+ sc->sc_gc.gc_set_pin = sxipio_set_pin;
+ gpio_controller_register(&sc->sc_gc);
+
+ config_defer(self, sxipio_attach_gpio);
+
+ printf(": %d pins\n", sc->sc_npins);
+}
+
+
+int
+sxipio_pinctrl(uint32_t phandle, void *cookie)
+{
+ struct sxipio_softc *sc = cookie;
+ char func[32];
+ char *names, *name;
+ int port, pin, off;
+ int mux, drive, pull;
+ int node;
+ int len;
+ int i, j;
+ int s;
+
+ node = OF_getnodebyphandle(phandle);
+ if (node == 0)
+ return -1;
+
+ len = OF_getprop(node, "allwinner,function", func, sizeof(func));
+ if (len <= 0 || len >= sizeof(func))
+ return -1;
+
+ len = OF_getproplen(node, "allwinner,pins");
+ if (len <= 0)
+ return -1;
+
+ names = malloc(len, M_TEMP, M_WAITOK);
+ OF_getprop(node, "allwinner,pins", names, len);
+
+ drive = OF_getpropint(node, "allwinner,drive", 0);
+ pull = OF_getpropint(node, "allwinner,pull", 0);
+
+ name = names;
+ while (len > 0) {
+ /* Lookup the pin. */
+ for (i = 0; i < sc->sc_npins; i++) {
+ if (strcmp(name, sc->sc_pins[i].name) == 0)
+ break;
+ }
+ if (i >= sc->sc_npins)
+ goto err;
+
+ /* Lookup the function of the pin. */
+ for (j = 0; j < nitems(sc->sc_pins[i].funcs); j++) {
+ if (strcmp(func, sc->sc_pins[i].funcs[j].name) == 0)
+ break;
+ }
+ if (j > nitems(sc->sc_pins[i].funcs))
+ goto err;
+
+ port = sc->sc_pins[i].port;
+ pin = sc->sc_pins[i].pin;
+ mux = sc->sc_pins[i].funcs[j].mux;
+
+ s = splhigh();
+ off = (pin & 0x7) << 2;
+ SXICMS4(sc, SXIPIO_CFG(port, pin), 0x7 << off, mux << off);
+ off = (pin & 0xf) << 1;
+ SXICMS4(sc, SXIPIO_DRV(port, pin), 0x3 << off, drive << off);
+ SXICMS4(sc, SXIPIO_PUL(port, pin), 0x3 << off, pull << off);
+ splx(s);
+
+ len -= strlen(name) + 1;
+ name += strlen(name) + 1;
+ }
+
+ free(names, M_TEMP, len);
+ return 0;
+
+err:
+ free(names, M_TEMP, len);
+ return -1;
+}
+
+void
+sxipio_config_pin(void *cookie, uint32_t *cells, int config)
+{
+ struct sxipio_softc *sc = cookie;
+ uint32_t port = cells[0];
+ uint32_t pin = cells[1];
+ int mux, off;
+
+ if (port > SXIPIO_NPORT || pin > 32)
+ return;
+
+ mux = (config & GPIO_CONFIG_OUTPUT) ? 1 : 0;
+ off = (pin & 0x7) << 2;
+ SXICMS4(sc, SXIPIO_CFG(port, pin), 0x7 << off, mux << off);
+}
+
+int
+sxipio_get_pin(void *cookie, uint32_t *cells)
+{
+ struct sxipio_softc *sc = cookie;
+ uint32_t port = cells[0];
+ uint32_t pin = cells[1];
+ uint32_t flags = cells[2];
+ uint32_t reg;
+ int val;
+
+ if (port > SXIPIO_NPORT || pin > 32)
+ return 0;
+
+ reg = SXIREAD4(sc, SXIPIO_DAT(port));
+ reg &= (1 << pin);
+ val = (reg >> pin) & 1;
+ if (flags & GPIO_ACTIVE_LOW)
+ val = !val;
+ return val;
+}
+
+void
+sxipio_set_pin(void *cookie, uint32_t *cells, int val)
+{
+ struct sxipio_softc *sc = cookie;
+ uint32_t port = cells[0];
+ uint32_t pin = cells[1];
+ uint32_t flags = cells[2];
+ uint32_t reg;
+
+ if (port > SXIPIO_NPORT || pin > 32)
+ return;
+
+ reg = SXIREAD4(sc, SXIPIO_DAT(port));
+ if (flags & GPIO_ACTIVE_LOW)
+ val = !val;
+ if (val)
+ reg |= (1 << pin);
+ else
+ reg &= ~(1 << pin);
+ SXIWRITE4(sc, SXIPIO_DAT(port), reg);
+}
+
+/*
+ * GPIO support code
+ */
+
+int sxipio_pin_read(void *, int);
+void sxipio_pin_write(void *, int, int);
+void sxipio_pin_ctl(void *, int, int);
+
+static const struct gpio_chipset_tag sxipio_gpio_tag = {
+ .gp_pin_read = sxipio_pin_read,
+ .gp_pin_write = sxipio_pin_write,
+ .gp_pin_ctl = sxipio_pin_ctl
+};
+
+int
+sxipio_pin_read(void *cookie, int pin)
+{
+ struct sxipio_gpio *gpio = cookie;
+ uint32_t cells[3];
+
+ cells[0] = gpio->port;
+ cells[1] = pin;
+ cells[2] = 0;
+
+ return sxipio_get_pin(gpio->sc, cells) ? GPIO_PIN_HIGH : GPIO_PIN_LOW;
+}
+
+void
+sxipio_pin_write(void *cookie, int pin, int val)
+{
+ struct sxipio_gpio *gpio = cookie;
+ uint32_t cells[3];
+
+ cells[0] = gpio->port;
+ cells[1] = pin;
+ cells[2] = 0;
+
+ sxipio_set_pin(gpio->sc, cells, val);
+}
+
+void
+sxipio_pin_ctl(void *cookie, int pin, int flags)
+{
+ struct sxipio_gpio *gpio = cookie;
+ uint32_t cells[3];
+
+ cells[0] = gpio->port;
+ cells[1] = pin;
+ cells[2] = 0;
+
+ if (ISSET(flags, GPIO_PIN_OUTPUT))
+ sxipio_config_pin(gpio->sc, cells, GPIO_CONFIG_OUTPUT);
+ else
+ sxipio_config_pin(gpio->sc, cells, 0);
+}
+
+void
+sxipio_attach_gpio(struct device *parent)
+{
+ struct sxipio_softc *sc = (struct sxipio_softc *)parent;
+ struct gpiobus_attach_args gba;
+ uint32_t reg;
+ int port, pin;
+ int cfg, state;
+ int i;
+
+ for (i = 0; i < sc->sc_npins; i++) {
+ /* Skip pins that have no gpio function. */
+ if (strcmp(sc->sc_pins[i].funcs[0].name, "gpio_in") != 0 ||
+ strcmp(sc->sc_pins[i].funcs[1].name, "gpio_out") != 0)
+ continue;
+
+ port = sc->sc_pins[i].port;
+ pin = sc->sc_pins[i].pin;
+
+ /* Get pin configuration. */
+ reg = SXIREAD4(sc, SXIPIO_CFG(port, pin));
+ cfg = (reg >> (pin & 0x7)) & 0x7;
+
+ /* Skip pins that have been assigned other functions. */
+ if (cfg != SXIPIO_GPIO_IN && cfg != SXIPIO_GPIO_OUT)
+ continue;
+
+ /* Get pin state. */
+ reg = SXIREAD4(sc, SXIPIO_DAT(port));
+ state = (reg >> pin) & 1;
+
+ sc->sc_gpio_pins[port][pin].pin_caps =
+ GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
+ sc->sc_gpio_pins[port][pin].pin_flags =
+ GPIO_PIN_SET | (cfg ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT);
+ sc->sc_gpio_pins[port][pin].pin_state = state;
+ sc->sc_gpio_pins[port][pin].pin_num = pin;
+ }
+
+ for (i = 0; i <= port; i++) {
+ memcpy(&sc->sc_gpio_tag[i], &sxipio_gpio_tag, sizeof(sxipio_gpio_tag));
+ sc->sc_gpio_tag[i].gp_cookie = &sc->sc_gpio[i];
+ sc->sc_gpio[i].sc = sc;
+ sc->sc_gpio[i].port = i;
+
+ gba.gba_name = "gpio";
+ gba.gba_gc = &sc->sc_gpio_tag[i];
+ gba.gba_pins = &sc->sc_gpio_pins[i][0];
+ gba.gba_npins = 32;
+
+#if NGPIO > 0
+ config_found(&sc->sc_dev, &gba, gpiobus_print);
+#endif
+ }
+}
diff --git a/sys/dev/fdt/sxipio_pins.h b/sys/dev/fdt/sxipio_pins.h
new file mode 100644
index 00000000000..10f27f03e47
--- /dev/null
+++ b/sys/dev/fdt/sxipio_pins.h
@@ -0,0 +1,5756 @@
+/* Public Domain */
+
+
+struct sxipio_pin sun4i_a10_pins[] = {
+ { SXIPIO_PIN(A, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi1", 3 },
+ { "uart2", 4 },
+ } },
+ { SXIPIO_PIN(A, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi1", 3 },
+ { "uart2", 4 },
+ } },
+ { SXIPIO_PIN(A, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi1", 3 },
+ { "uart2", 4 },
+ } },
+ { SXIPIO_PIN(A, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi1", 3 },
+ { "uart2", 4 },
+ } },
+ { SXIPIO_PIN(A, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi1", 3 },
+ } },
+ { SXIPIO_PIN(A, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi3", 3 },
+ } },
+ { SXIPIO_PIN(A, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi3", 3 },
+ } },
+ { SXIPIO_PIN(A, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi3", 3 },
+ } },
+ { SXIPIO_PIN(A, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi3", 3 },
+ } },
+ { SXIPIO_PIN(A, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi3", 3 },
+ } },
+ { SXIPIO_PIN(A, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart1", 4 },
+ } },
+ { SXIPIO_PIN(A, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart1", 4 },
+ } },
+ { SXIPIO_PIN(A, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart6", 3 },
+ { "uart1", 4 },
+ } },
+ { SXIPIO_PIN(A, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart6", 3 },
+ { "uart1", 4 },
+ } },
+ { SXIPIO_PIN(A, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart7", 3 },
+ { "uart1", 4 },
+ } },
+ { SXIPIO_PIN(A, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart7", 3 },
+ { "uart1", 4 },
+ } },
+ { SXIPIO_PIN(A, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "can", 3 },
+ { "uart1", 4 },
+ } },
+ { SXIPIO_PIN(A, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "can", 3 },
+ { "uart1", 4 },
+ } },
+ { SXIPIO_PIN(B, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 },
+ } },
+ { SXIPIO_PIN(B, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 },
+ } },
+ { SXIPIO_PIN(B, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "pwm", 2 },
+ } },
+ { SXIPIO_PIN(B, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ir0", 2 },
+ { "spdif", 4 },
+ } },
+ { SXIPIO_PIN(B, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ir0", 2 },
+ } },
+ { SXIPIO_PIN(B, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s", 2 },
+ { "ac97", 3 },
+ } },
+ { SXIPIO_PIN(B, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s", 2 },
+ { "ac97", 3 },
+ } },
+ { SXIPIO_PIN(B, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s", 2 },
+ { "ac97", 3 },
+ } },
+ { SXIPIO_PIN(B, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s", 2 },
+ { "ac97", 3 },
+ } },
+ { SXIPIO_PIN(B, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s", 2 },
+ } },
+ { SXIPIO_PIN(B, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s", 2 },
+ } },
+ { SXIPIO_PIN(B, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s", 2 },
+ } },
+ { SXIPIO_PIN(B, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s", 2 },
+ { "ac97", 3 },
+ { "spdif", 4 },
+ } },
+ { SXIPIO_PIN(B, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "spdif", 4 },
+ } },
+ { SXIPIO_PIN(B, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(B, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(B, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(B, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(B, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c1", 2 },
+ } },
+ { SXIPIO_PIN(B, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c1", 2 },
+ } },
+ { SXIPIO_PIN(B, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c2", 2 },
+ } },
+ { SXIPIO_PIN(B, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c2", 2 },
+ } },
+ { SXIPIO_PIN(B, 22), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart0", 2 },
+ { "ir1", 3 },
+ } },
+ { SXIPIO_PIN(B, 23), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart0", 2 },
+ { "ir1", 3 },
+ } },
+ { SXIPIO_PIN(C, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi2", 3 },
+ } },
+ { SXIPIO_PIN(C, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi2", 3 },
+ } },
+ { SXIPIO_PIN(C, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi2", 3 },
+ } },
+ { SXIPIO_PIN(C, 22), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi2", 3 },
+ } },
+ { SXIPIO_PIN(C, 23), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 24), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(D, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "csi1", 3 },
+ } },
+ { SXIPIO_PIN(D, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "sim", 3 },
+ } },
+ { SXIPIO_PIN(D, 22), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "sim", 3 },
+ } },
+ { SXIPIO_PIN(D, 23), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "sim", 3 },
+ } },
+ { SXIPIO_PIN(D, 24), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "sim", 3 },
+ } },
+ { SXIPIO_PIN(D, 25), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "sim", 3 },
+ } },
+ { SXIPIO_PIN(D, 26), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "sim", 3 },
+ } },
+ { SXIPIO_PIN(D, 27), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "sim", 3 },
+ } },
+ { SXIPIO_PIN(E, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ { "sim", 4 },
+ } },
+ { SXIPIO_PIN(E, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(F, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 4 },
+ } },
+ { SXIPIO_PIN(F, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 4 },
+ } },
+ { SXIPIO_PIN(F, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "uart0", 4 },
+ } },
+ { SXIPIO_PIN(F, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 4 },
+ } },
+ { SXIPIO_PIN(F, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "uart0", 4 },
+ } },
+ { SXIPIO_PIN(F, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 4 },
+ } },
+ { SXIPIO_PIN(G, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "mmc1", 4 },
+ } },
+ { SXIPIO_PIN(G, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "mmc1", 4 },
+ } },
+ { SXIPIO_PIN(G, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "mmc1", 4 },
+ } },
+ { SXIPIO_PIN(G, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "mmc1", 4 },
+ } },
+ { SXIPIO_PIN(G, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "mmc1", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(G, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "mmc1", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(G, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "uart3", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(G, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "uart3", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(G, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "uart3", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(G, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "uart3", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(G, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "uart4", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(G, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "uart4", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(H, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "uart3", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "uart3", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "uart3", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "uart3", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "uart4", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "uart4", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "uart5", 4 },
+ { "ms", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "uart5", 4 },
+ { "ms", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "ms", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "ms", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "ms", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "ms", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "ps2", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "ps2", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "can", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "can", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 22), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "mmc1", 5 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 23), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "mmc1", 5 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 24), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "mmc1", 5 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 25), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "mmc1", 5 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 26), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "mmc1", 5 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 27), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "pata", 3 },
+ { "keypad", 4 },
+ { "mmc1", 5 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(I, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ } },
+ { SXIPIO_PIN(I, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ } },
+ { SXIPIO_PIN(I, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ } },
+ { SXIPIO_PIN(I, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "pwm", 2 },
+ } },
+ { SXIPIO_PIN(I, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc3", 2 },
+ } },
+ { SXIPIO_PIN(I, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc3", 2 },
+ } },
+ { SXIPIO_PIN(I, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc3", 2 },
+ } },
+ { SXIPIO_PIN(I, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc3", 2 },
+ } },
+ { SXIPIO_PIN(I, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc3", 2 },
+ } },
+ { SXIPIO_PIN(I, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc3", 2 },
+ } },
+ { SXIPIO_PIN(I, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi0", 2 },
+ { "uart5", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi0", 2 },
+ { "uart5", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi0", 2 },
+ { "uart6", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi0", 2 },
+ { "uart6", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi0", 2 },
+ { "ps2", 3 },
+ { "timer4", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "ps2", 3 },
+ { "timer5", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart2", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart2", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart2", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart2", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ps2", 2 },
+ { "uart7", 3 },
+ { "hdmi", 4 },
+ } },
+ { SXIPIO_PIN(I, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ps2", 2 },
+ { "uart7", 3 },
+ { "hdmi", 4 },
+ } },
+};
+
+struct sxipio_pin sun5i_a13_pins[] = {
+ { SXIPIO_PIN(B, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 },
+ } },
+ { SXIPIO_PIN(B, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 },
+ } },
+ { SXIPIO_PIN(B, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "pwm", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ir0", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ir0", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c1", 2 },
+ } },
+ { SXIPIO_PIN(B, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c1", 2 },
+ } },
+ { SXIPIO_PIN(B, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c2", 2 },
+ } },
+ { SXIPIO_PIN(B, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c2", 2 },
+ } },
+ { SXIPIO_PIN(C, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "uart3", 4 },
+ } },
+ { SXIPIO_PIN(D, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 22), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 23), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 24), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 25), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 26), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 27), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(E, 0), {
+ { "gpio_in", 0 },
+ { "csi0", 3 },
+ { "spi2", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 1), {
+ { "gpio_in", 0 },
+ { "csi0", 3 },
+ { "spi2", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 2), {
+ { "gpio_in", 0 },
+ { "csi0", 3 },
+ { "spi2", 4 },
+ } },
+ { SXIPIO_PIN(E, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 3 },
+ { "spi2", 4 },
+ } },
+ { SXIPIO_PIN(E, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 3 },
+ { "mmc2", 4 },
+ } },
+ { SXIPIO_PIN(E, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 3 },
+ { "mmc2", 4 },
+ } },
+ { SXIPIO_PIN(E, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 3 },
+ { "mmc2", 4 },
+ } },
+ { SXIPIO_PIN(E, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 3 },
+ { "mmc2", 4 },
+ } },
+ { SXIPIO_PIN(E, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 3 },
+ { "mmc2", 4 },
+ } },
+ { SXIPIO_PIN(E, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 3 },
+ { "mmc2", 4 },
+ } },
+ { SXIPIO_PIN(E, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 3 },
+ { "uart1", 4 },
+ } },
+ { SXIPIO_PIN(E, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 3 },
+ { "uart1", 4 },
+ } },
+ { SXIPIO_PIN(F, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ } },
+ { SXIPIO_PIN(F, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ } },
+ { SXIPIO_PIN(F, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ } },
+ { SXIPIO_PIN(F, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ } },
+ { SXIPIO_PIN(F, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ } },
+ { SXIPIO_PIN(F, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ } },
+ { SXIPIO_PIN(G, 0), {
+ { "gpio_in", 0 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 1), {
+ { "gpio_in", 0 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 2), {
+ { "gpio_in", 0 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "uart1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "uart1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart3", 3 },
+ { "irq", 6 },
+ } },
+};
+
+struct sxipio_pin sun5i_a10s_pins[] = {
+ { SXIPIO_PIN(A, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "ts0", 3 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "ts0", 3 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "ts0", 3 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "ts0", 3 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "ts0", 3 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "ts0", 3 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "ts0", 3 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "ts0", 3 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "ts0", 3 },
+ { "uart1", 4 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "ts0", 3 },
+ { "uart1", 4 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "ts0", 3 },
+ { "uart1", 4 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "ts0", 3 },
+ { "uart1", 4 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart1", 3 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart1", 3 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart1", 3 },
+ { "uart3", 4 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart1", 3 },
+ { "uart3", 4 },
+ { "keypad", 5 },
+ } },
+ { SXIPIO_PIN(A, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart2", 3 },
+ } },
+ { SXIPIO_PIN(A, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart2", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 },
+ } },
+ { SXIPIO_PIN(B, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 },
+ } },
+ { SXIPIO_PIN(B, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "pwm", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ir0", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ir0", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "jtag", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "jtag", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "jtag", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "jtag", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c1", 2 },
+ } },
+ { SXIPIO_PIN(B, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c1", 2 },
+ } },
+ { SXIPIO_PIN(B, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c2", 2 },
+ } },
+ { SXIPIO_PIN(B, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c2", 2 },
+ } },
+ { SXIPIO_PIN(B, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart0", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart0", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(C, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "uart3", 4 },
+ } },
+ { SXIPIO_PIN(C, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "uart3", 4 },
+ } },
+ { SXIPIO_PIN(C, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "uart2", 3 },
+ { "uart3", 4 },
+ } },
+ { SXIPIO_PIN(C, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "uart2", 3 },
+ { "uart3", 4 },
+ } },
+ { SXIPIO_PIN(D, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "uart2", 3 },
+ } },
+ { SXIPIO_PIN(D, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "uart2", 3 },
+ } },
+ { SXIPIO_PIN(D, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "uart2", 3 },
+ } },
+ { SXIPIO_PIN(D, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "uart2", 3 },
+ } },
+ { SXIPIO_PIN(D, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 22), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 23), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 24), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 25), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 26), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(D, 27), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 3 },
+ } },
+ { SXIPIO_PIN(E, 0), {
+ { "gpio_in", 0 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ { "spi2", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 1), {
+ { "gpio_in", 0 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ { "spi2", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 2), {
+ { "gpio_in", 0 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ { "spi2", 4 },
+ } },
+ { SXIPIO_PIN(E, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ { "spi2", 4 },
+ } },
+ { SXIPIO_PIN(E, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ { "mmc2", 4 },
+ } },
+ { SXIPIO_PIN(E, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ { "mmc2", 4 },
+ } },
+ { SXIPIO_PIN(E, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ { "mmc2", 4 },
+ } },
+ { SXIPIO_PIN(E, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ { "mmc2", 4 },
+ } },
+ { SXIPIO_PIN(E, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ { "mmc2", 4 },
+ } },
+ { SXIPIO_PIN(E, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ { "mmc2", 4 },
+ } },
+ { SXIPIO_PIN(E, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ { "uart1", 4 },
+ } },
+ { SXIPIO_PIN(E, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ { "uart1", 4 },
+ } },
+ { SXIPIO_PIN(F, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 4 },
+ } },
+ { SXIPIO_PIN(F, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 4 },
+ } },
+ { SXIPIO_PIN(F, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "uart0", 4 },
+ } },
+ { SXIPIO_PIN(F, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 4 },
+ } },
+ { SXIPIO_PIN(F, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "uart0", 4 },
+ } },
+ { SXIPIO_PIN(F, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 4 },
+ } },
+ { SXIPIO_PIN(G, 0), {
+ { "gpio_in", 0 },
+ { "gps", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 1), {
+ { "gpio_in", 0 },
+ { "gps", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 2), {
+ { "gpio_in", 0 },
+ { "gps", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "uart1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "uart1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "uart1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "uart1", 4 },
+ { "uart2", 5 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "uart2", 5 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "uart2", 5 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "pwm", 3 },
+ { "uart2", 5 },
+ { "irq", 6 },
+ } },
+};
+
+struct sxipio_pin sun7i_a20_pins[] = {
+ { SXIPIO_PIN(A, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi1", 3 },
+ { "uart2", 4 },
+ { "gmac", 5 },
+ } },
+ { SXIPIO_PIN(A, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi1", 3 },
+ { "uart2", 4 },
+ { "gmac", 5 },
+ } },
+ { SXIPIO_PIN(A, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi1", 3 },
+ { "uart2", 4 },
+ { "gmac", 5 },
+ } },
+ { SXIPIO_PIN(A, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi1", 3 },
+ { "uart2", 4 },
+ { "gmac", 5 },
+ } },
+ { SXIPIO_PIN(A, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi1", 3 },
+ { "gmac", 5 },
+ } },
+ { SXIPIO_PIN(A, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi3", 3 },
+ { "gmac", 5 },
+ } },
+ { SXIPIO_PIN(A, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi3", 3 },
+ { "gmac", 5 },
+ } },
+ { SXIPIO_PIN(A, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi3", 3 },
+ { "gmac", 5 },
+ } },
+ { SXIPIO_PIN(A, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi3", 3 },
+ { "gmac", 5 },
+ } },
+ { SXIPIO_PIN(A, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "spi3", 3 },
+ { "gmac", 5 },
+ { "i2s1", 6 },
+ } },
+ { SXIPIO_PIN(A, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart1", 4 },
+ { "gmac", 5 },
+ } },
+ { SXIPIO_PIN(A, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart1", 4 },
+ { "gmac", 5 },
+ } },
+ { SXIPIO_PIN(A, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart6", 3 },
+ { "uart1", 4 },
+ { "gmac", 5 },
+ } },
+ { SXIPIO_PIN(A, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart6", 3 },
+ { "uart1", 4 },
+ { "gmac", 5 },
+ } },
+ { SXIPIO_PIN(A, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart7", 3 },
+ { "uart1", 4 },
+ { "gmac", 5 },
+ { "i2s1", 6 },
+ } },
+ { SXIPIO_PIN(A, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "uart7", 3 },
+ { "uart1", 4 },
+ { "gmac", 5 },
+ { "i2s1", 6 },
+ } },
+ { SXIPIO_PIN(A, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "can", 3 },
+ { "uart1", 4 },
+ { "gmac", 5 },
+ { "i2s1", 6 },
+ } },
+ { SXIPIO_PIN(A, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ { "can", 3 },
+ { "uart1", 4 },
+ { "gmac", 5 },
+ { "i2s1", 6 },
+ } },
+ { SXIPIO_PIN(B, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 },
+ } },
+ { SXIPIO_PIN(B, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 },
+ } },
+ { SXIPIO_PIN(B, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "pwm", 2 },
+ } },
+ { SXIPIO_PIN(B, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ir0", 2 },
+ { "spdif", 4 },
+ } },
+ { SXIPIO_PIN(B, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ir0", 2 },
+ } },
+ { SXIPIO_PIN(B, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s0", 2 },
+ { "ac97", 3 },
+ } },
+ { SXIPIO_PIN(B, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s0", 2 },
+ { "ac97", 3 },
+ } },
+ { SXIPIO_PIN(B, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s0", 2 },
+ { "ac97", 3 },
+ } },
+ { SXIPIO_PIN(B, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s0", 2 },
+ { "ac97", 3 },
+ } },
+ { SXIPIO_PIN(B, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s0", 2 },
+ } },
+ { SXIPIO_PIN(B, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s0", 2 },
+ } },
+ { SXIPIO_PIN(B, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s0", 2 },
+ } },
+ { SXIPIO_PIN(B, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s0", 2 },
+ { "ac97", 3 },
+ { "spdif", 4 },
+ } },
+ { SXIPIO_PIN(B, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "spdif", 4 },
+ } },
+ { SXIPIO_PIN(B, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(B, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(B, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(B, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi2", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(B, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c1", 2 },
+ } },
+ { SXIPIO_PIN(B, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c1", 2 },
+ } },
+ { SXIPIO_PIN(B, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c2", 2 },
+ } },
+ { SXIPIO_PIN(B, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c2", 2 },
+ } },
+ { SXIPIO_PIN(B, 22), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart0", 2 },
+ { "ir1", 3 },
+ } },
+ { SXIPIO_PIN(B, 23), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart0", 2 },
+ { "ir1", 3 },
+ } },
+ { SXIPIO_PIN(C, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi2", 3 },
+ } },
+ { SXIPIO_PIN(C, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi2", 3 },
+ } },
+ { SXIPIO_PIN(C, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi2", 3 },
+ } },
+ { SXIPIO_PIN(C, 22), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi2", 3 },
+ } },
+ { SXIPIO_PIN(C, 23), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 24), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(D, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "csi1", 3 },
+ } },
+ { SXIPIO_PIN(D, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "sim", 3 },
+ } },
+ { SXIPIO_PIN(D, 22), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "sim", 3 },
+ } },
+ { SXIPIO_PIN(D, 23), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "sim", 3 },
+ } },
+ { SXIPIO_PIN(D, 24), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "sim", 3 },
+ } },
+ { SXIPIO_PIN(D, 25), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "sim", 3 },
+ } },
+ { SXIPIO_PIN(D, 26), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "sim", 3 },
+ } },
+ { SXIPIO_PIN(D, 27), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "sim", 3 },
+ } },
+ { SXIPIO_PIN(E, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ { "sim", 4 },
+ } },
+ { SXIPIO_PIN(E, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(E, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts0", 2 },
+ { "csi0", 3 },
+ } },
+ { SXIPIO_PIN(F, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 4 },
+ } },
+ { SXIPIO_PIN(F, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 4 },
+ } },
+ { SXIPIO_PIN(F, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "uart0", 4 },
+ } },
+ { SXIPIO_PIN(F, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 4 },
+ } },
+ { SXIPIO_PIN(F, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "uart0", 4 },
+ } },
+ { SXIPIO_PIN(F, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 4 },
+ } },
+ { SXIPIO_PIN(G, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "mmc1", 4 },
+ } },
+ { SXIPIO_PIN(G, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "mmc1", 4 },
+ } },
+ { SXIPIO_PIN(G, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "mmc1", 4 },
+ } },
+ { SXIPIO_PIN(G, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "mmc1", 4 },
+ } },
+ { SXIPIO_PIN(G, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "mmc1", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(G, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "mmc1", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(G, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "uart3", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(G, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "uart3", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(G, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "uart3", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(G, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "uart3", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(G, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "uart4", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(G, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ts1", 2 },
+ { "csi1", 3 },
+ { "uart4", 4 },
+ { "csi0", 5 },
+ } },
+ { SXIPIO_PIN(H, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "uart3", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "uart3", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "uart3", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "uart3", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "uart4", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "uart4", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "uart5", 4 },
+ { "ms", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "uart5", 4 },
+ { "ms", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "ms", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "ms", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "ms", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "ms", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "ps2", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "ps2", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "can", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "can", 4 },
+ { "irq", 6 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 22), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "mmc1", 5 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 23), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "mmc1", 5 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 24), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "mmc1", 5 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 25), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "mmc1", 5 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 26), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "mmc1", 5 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(H, 27), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd1", 2 },
+ { "emac", 3 },
+ { "keypad", 4 },
+ { "mmc1", 5 },
+ { "csi1", 7 },
+ } },
+ { SXIPIO_PIN(I, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c3", 3 },
+ } },
+ { SXIPIO_PIN(I, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c3", 3 },
+ } },
+ { SXIPIO_PIN(I, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c4", 3 },
+ } },
+ { SXIPIO_PIN(I, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "pwm", 2 },
+ { "i2c4", 3 },
+ } },
+ { SXIPIO_PIN(I, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc3", 2 },
+ } },
+ { SXIPIO_PIN(I, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc3", 2 },
+ } },
+ { SXIPIO_PIN(I, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc3", 2 },
+ } },
+ { SXIPIO_PIN(I, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc3", 2 },
+ } },
+ { SXIPIO_PIN(I, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc3", 2 },
+ } },
+ { SXIPIO_PIN(I, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc3", 2 },
+ } },
+ { SXIPIO_PIN(I, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi0", 2 },
+ { "uart5", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi0", 2 },
+ { "uart5", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi0", 2 },
+ { "uart6", 3 },
+ { "clk_out_a", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi0", 2 },
+ { "uart6", 3 },
+ { "clk_out_b", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi0", 2 },
+ { "ps2", 3 },
+ { "timer4", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "ps2", 3 },
+ { "timer5", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart2", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart2", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart2", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart2", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(I, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ps2", 2 },
+ { "uart7", 3 },
+ { "hdmi", 4 },
+ } },
+ { SXIPIO_PIN(I, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "ps2", 2 },
+ { "uart7", 3 },
+ { "hdmi", 4 },
+ } },
+};
+
+struct sxipio_pin sun8i_h3_pins[] = {
+ { SXIPIO_PIN(A, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart2", 2 },
+ { "jtag", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart2", 2 },
+ { "jtag", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart2", 2 },
+ { "jtag", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart2", 2 },
+ { "jtag", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart0", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart0", 2 },
+ { "pwm0", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "sim", 2 },
+ { "pwm1", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "sim", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "sim", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "sim", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "sim", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 },
+ { "di", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 },
+ { "di", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi1", 2 },
+ { "uart3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spdif", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s0", 2 },
+ { "i2c1", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s0", 2 },
+ { "i2c1", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s0", 2 },
+ { "sim", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s0", 2 },
+ { "sim", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(C, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(D, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(D, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 2 },
+ } },
+ { SXIPIO_PIN(E, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ } },
+ { SXIPIO_PIN(E, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ } },
+ { SXIPIO_PIN(E, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ } },
+ { SXIPIO_PIN(E, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ } },
+ { SXIPIO_PIN(E, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ } },
+ { SXIPIO_PIN(E, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ } },
+ { SXIPIO_PIN(E, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ } },
+ { SXIPIO_PIN(E, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ } },
+ { SXIPIO_PIN(E, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ } },
+ { SXIPIO_PIN(E, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ } },
+ { SXIPIO_PIN(E, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ } },
+ { SXIPIO_PIN(E, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ } },
+ { SXIPIO_PIN(E, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "i2c2", 3 },
+ } },
+ { SXIPIO_PIN(E, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "i2c2", 3 },
+ } },
+ { SXIPIO_PIN(E, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ } },
+ { SXIPIO_PIN(E, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ } },
+ { SXIPIO_PIN(F, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(F, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(F, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "uart0", 3 },
+ } },
+ { SXIPIO_PIN(F, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(F, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "uart0", 3 },
+ } },
+ { SXIPIO_PIN(F, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(F, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ } },
+ { SXIPIO_PIN(G, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2s1", 2 },
+ { "irq", 6 },
+ } },
+};
+
+struct sxipio_pin sun8i_h3_r_pins[] = {
+ { SXIPIO_PIN(L, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_twi", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_twi", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_uart", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_uart", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_jtag", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_jtag", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_jtag", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_jtag", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_pwm", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_cir_rx", 2 },
+ { "irq", 6 },
+ } },
+};
+
+struct sxipio_pin sun9i_a80_pins[] = {
+ { SXIPIO_PIN(A, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "uart1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "uart1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "uart1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "uart1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "uart1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "uart1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "uart1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "uart1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "eclk", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "eclk", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "clk_out_a", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "clk_out_b", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "pwm3", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "pwm3", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "spi1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "spi1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "spi1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(A, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "gmac", 2 },
+ { "spi1", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mcsi", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mcsi", 3 },
+ { "i2c4", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mcsi", 3 },
+ { "i2c4", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(C, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(C, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "nand0_b", 3 },
+ } },
+ { SXIPIO_PIN(C, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "nand0_b", 3 },
+ } },
+ { SXIPIO_PIN(C, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi0", 3 },
+ } },
+ { SXIPIO_PIN(D, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ } },
+ { SXIPIO_PIN(D, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds1", 3 },
+ } },
+ { SXIPIO_PIN(D, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 22), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 23), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 24), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 25), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 26), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(D, 27), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ } },
+ { SXIPIO_PIN(E, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "spi2", 3 },
+ { "uart5", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "spi2", 3 },
+ { "uart5", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "spi2", 3 },
+ { "uart5", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "spi2", 3 },
+ { "uart5", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "ts", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "i2c4", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(E, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi", 2 },
+ { "i2c4", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(F, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ } },
+ { SXIPIO_PIN(F, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ } },
+ { SXIPIO_PIN(F, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "uart0", 4 },
+ } },
+ { SXIPIO_PIN(F, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ } },
+ { SXIPIO_PIN(F, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "uart0", 4 },
+ } },
+ { SXIPIO_PIN(F, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ } },
+ { SXIPIO_PIN(G, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart2", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart2", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart2", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart2", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c3", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c3", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart4", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart4", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart4", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart4", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 },
+ } },
+ { SXIPIO_PIN(H, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 },
+ } },
+ { SXIPIO_PIN(H, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c1", 2 },
+ } },
+ { SXIPIO_PIN(H, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c1", 2 },
+ } },
+ { SXIPIO_PIN(H, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c2", 2 },
+ } },
+ { SXIPIO_PIN(H, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c2", 2 },
+ } },
+ { SXIPIO_PIN(H, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "pwm0", 2 },
+ } },
+ { SXIPIO_PIN(H, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "pwm1", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "pwm1", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "pwm2", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "pwm2", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart0", 2 },
+ { "spi3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart0", 2 },
+ { "spi3", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi3", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi3", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi3", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi3", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spi3", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "hdmi", 2 },
+ } },
+ { SXIPIO_PIN(H, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "hdmi", 2 },
+ } },
+ { SXIPIO_PIN(H, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "hdmi", 2 },
+ } },
+};
+
+struct sxipio_pin sun9i_a80_r_pins[] = {
+ { SXIPIO_PIN(L, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_uart", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_uart", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_jtag", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_jtag", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_jtag", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_jtag", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_cir_rx", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "1wire", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_ps2", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(L, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_ps2", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(M, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(M, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(M, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(M, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(M, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2s1", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(M, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2c1", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(M, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2c1", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(M, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2s0", 2 },
+ { "s_i2s1", 3 },
+ } },
+ { SXIPIO_PIN(M, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2s0", 2 },
+ { "s_i2s1", 3 },
+ } },
+ { SXIPIO_PIN(M, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2s0", 2 },
+ { "s_i2s1", 3 },
+ } },
+ { SXIPIO_PIN(M, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2s0", 2 },
+ { "s_i2s1", 3 },
+ } },
+ { SXIPIO_PIN(M, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2s0", 2 },
+ { "s_i2s1", 3 },
+ } },
+ { SXIPIO_PIN(M, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(N, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2c0", 2 },
+ { "s_rsb", 3 },
+ } },
+ { SXIPIO_PIN(N, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "s_i2c0", 2 },
+ { "s_rsb", 3 },
+ } },
+};
+
+struct sxipio_pin sun50i_a64_pins[] = {
+ { SXIPIO_PIN(B, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart2", 2 },
+ { "jtag", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart2", 2 },
+ { "jtag", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart2", 2 },
+ { "jtag", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart2", 2 },
+ { "i2s0", 3 },
+ { "jtag", 4 },
+ { "sim", 5 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "aif2", 2 },
+ { "i2s0", 3 },
+ { "sim", 5 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "aif2", 2 },
+ { "i2s0", 3 },
+ { "sim", 5 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "aif2", 2 },
+ { "i2s0", 3 },
+ { "sim", 5 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "aif2", 2 },
+ { "i2s0", 3 },
+ { "sim", 5 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart0", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(B, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart0", 4 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(C, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 4 },
+ } },
+ { SXIPIO_PIN(C, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ { "spi0", 4 },
+ } },
+ { SXIPIO_PIN(C, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 4 },
+ } },
+ { SXIPIO_PIN(C, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "spi0", 4 },
+ } },
+ { SXIPIO_PIN(C, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ } },
+ { SXIPIO_PIN(C, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(C, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "nand0", 2 },
+ { "mmc2", 3 },
+ } },
+ { SXIPIO_PIN(D, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "uart3", 3 },
+ { "spi1", 4 },
+ { "ccir", 5 },
+ } },
+ { SXIPIO_PIN(D, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "uart3", 3 },
+ { "spi1", 4 },
+ { "ccir", 5 },
+ } },
+ { SXIPIO_PIN(D, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "uart4", 3 },
+ { "spi1", 4 },
+ { "ccir", 5 },
+ } },
+ { SXIPIO_PIN(D, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "uart4", 3 },
+ { "spi1", 4 },
+ { "ccir", 5 },
+ } },
+ { SXIPIO_PIN(D, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "uart4", 3 },
+ { "ccir", 5 },
+ } },
+ { SXIPIO_PIN(D, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "uart4", 3 },
+ { "ccir", 5 },
+ } },
+ { SXIPIO_PIN(D, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "ccir", 5 },
+ } },
+ { SXIPIO_PIN(D, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "ccir", 5 },
+ } },
+ { SXIPIO_PIN(D, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 4 },
+ { "ccir", 5 },
+ } },
+ { SXIPIO_PIN(D, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 4 },
+ { "ccir", 5 },
+ } },
+ { SXIPIO_PIN(D, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 4 },
+ } },
+ { SXIPIO_PIN(D, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "emac", 4 },
+ } },
+ { SXIPIO_PIN(D, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ { "emac", 4 },
+ } },
+ { SXIPIO_PIN(D, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ { "emac", 4 },
+ } },
+ { SXIPIO_PIN(D, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ { "emac", 4 },
+ } },
+ { SXIPIO_PIN(D, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ { "emac", 4 },
+ { "ccir", 5 },
+ } },
+ { SXIPIO_PIN(D, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ { "emac", 4 },
+ { "ccir", 5 },
+ } },
+ { SXIPIO_PIN(D, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ { "emac", 4 },
+ } },
+ { SXIPIO_PIN(D, 18), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ { "emac", 4 },
+ } },
+ { SXIPIO_PIN(D, 19), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ { "emac", 4 },
+ } },
+ { SXIPIO_PIN(D, 20), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ { "emac", 4 },
+ } },
+ { SXIPIO_PIN(D, 21), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "lcd0", 2 },
+ { "lvds0", 3 },
+ { "emac", 4 },
+ } },
+ { SXIPIO_PIN(D, 22), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "pwm", 2 },
+ { "emac", 4 },
+ } },
+ { SXIPIO_PIN(D, 23), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "emac", 4 },
+ } },
+ { SXIPIO_PIN(D, 24), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ } },
+ { SXIPIO_PIN(E, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 2 },
+ { "ts0", 4 },
+ } },
+ { SXIPIO_PIN(E, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 2 },
+ { "ts0", 4 },
+ } },
+ { SXIPIO_PIN(E, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 2 },
+ { "ts0", 4 },
+ } },
+ { SXIPIO_PIN(E, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 2 },
+ { "ts0", 4 },
+ } },
+ { SXIPIO_PIN(E, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 2 },
+ { "ts0", 4 },
+ } },
+ { SXIPIO_PIN(E, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 2 },
+ { "ts0", 4 },
+ } },
+ { SXIPIO_PIN(E, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 2 },
+ { "ts0", 4 },
+ } },
+ { SXIPIO_PIN(E, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 2 },
+ { "ts0", 4 },
+ } },
+ { SXIPIO_PIN(E, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 2 },
+ { "ts0", 4 },
+ } },
+ { SXIPIO_PIN(E, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 2 },
+ { "ts0", 4 },
+ } },
+ { SXIPIO_PIN(E, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 2 },
+ { "ts0", 4 },
+ } },
+ { SXIPIO_PIN(E, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 2 },
+ { "ts0", 4 },
+ } },
+ { SXIPIO_PIN(E, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 2 },
+ } },
+ { SXIPIO_PIN(E, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "csi0", 2 },
+ } },
+ { SXIPIO_PIN(E, 14), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "pll", 2 },
+ { "i2c2", 3 },
+ } },
+ { SXIPIO_PIN(E, 15), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c2", 3 },
+ } },
+ { SXIPIO_PIN(E, 16), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ } },
+ { SXIPIO_PIN(E, 17), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ } },
+ { SXIPIO_PIN(F, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(F, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(F, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "uart0", 3 },
+ } },
+ { SXIPIO_PIN(F, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(F, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "uart0", 4 },
+ } },
+ { SXIPIO_PIN(F, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc0", 2 },
+ { "jtag", 3 },
+ } },
+ { SXIPIO_PIN(F, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ } },
+ { SXIPIO_PIN(G, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mmc1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "aif3", 2 },
+ { "i2s1", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "aif3", 2 },
+ { "i2s1", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 12), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "aif3", 2 },
+ { "i2s1", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(G, 13), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "aif3", 2 },
+ { "i2s1", 3 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 0), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 1), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c0", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 2), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 3), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "i2c1", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 4), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart3", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 5), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart3", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 6), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart3", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 7), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "uart3", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 8), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "spdif", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 9), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 10), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mic", 2 },
+ { "irq", 6 },
+ } },
+ { SXIPIO_PIN(H, 11), {
+ { "gpio_in", 0 },
+ { "gpio_out", 1 },
+ { "mic", 2 },
+ { "irq", 6 },
+ } },
+};
diff --git a/sys/dev/fdt/sxipiovar.h b/sys/dev/fdt/sxipiovar.h
new file mode 100644
index 00000000000..6b0da0313c7
--- /dev/null
+++ b/sys/dev/fdt/sxipiovar.h
@@ -0,0 +1,45 @@
+/* $OpenBSD: sxipiovar.h,v 1.1 2017/01/21 08:26:49 patrick Exp $ */
+/*
+ * Copyright (c) 2013 Artturi Alm
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/gpio.h>
+
+struct sxipio_func {
+ const char *name;
+ int mux;
+};
+
+struct sxipio_pin {
+ const char *name;
+ int port, pin;
+ struct sxipio_func funcs[8];
+};
+
+#define SXIPIO_PORT_A 0
+#define SXIPIO_PORT_B 1
+#define SXIPIO_PORT_C 2
+#define SXIPIO_PORT_D 3
+#define SXIPIO_PORT_E 4
+#define SXIPIO_PORT_F 5
+#define SXIPIO_PORT_G 6
+#define SXIPIO_PORT_H 7
+#define SXIPIO_PORT_I 8
+#define SXIPIO_PORT_L 0
+#define SXIPIO_PORT_M 1
+#define SXIPIO_PORT_N 2
+
+#define SXIPIO_PIN(port, pin) \
+ "P" #port #pin, SXIPIO_PORT_ ## port, pin
diff --git a/sys/dev/fdt/sxirtc.c b/sys/dev/fdt/sxirtc.c
new file mode 100644
index 00000000000..fd61fc043ee
--- /dev/null
+++ b/sys/dev/fdt/sxirtc.c
@@ -0,0 +1,184 @@
+/* $OpenBSD: sxirtc.c,v 1.1 2017/01/21 08:26:49 patrick Exp $ */
+/*
+ * Copyright (c) 2008 Mark Kettenis
+ * Copyright (c) 2013 Artturi Alm
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+
+#include <dev/clock_subr.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/fdt/sunxireg.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/fdt.h>
+
+#define SXIRTC_YYMMDD 0x04
+#define SXIRTC_HHMMSS 0x08
+#define SXIRTC_YYMMDD_A31 0x10
+#define SXIRTC_HHMMSS_A31 0x14
+
+#define LEAPYEAR(y) \
+ (((y) % 4 == 0 && \
+ (y) % 100 != 0) || \
+ (y) % 400 == 0)
+
+
+extern todr_chip_handle_t todr_handle;
+
+struct sxirtc_softc {
+ struct device sc_dev;
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ bus_size_t sc_yymmdd;
+ bus_size_t sc_hhmmss;
+ uint32_t base_year;
+ uint32_t year_mask;
+ uint32_t leap_shift;
+};
+
+int sxirtc_match(struct device *, void *, void *);
+void sxirtc_attach(struct device *, struct device *, void *);
+
+struct cfattach sxirtc_ca = {
+ sizeof(struct sxirtc_softc), sxirtc_match, sxirtc_attach
+};
+
+struct cfdriver sxirtc_cd = {
+ NULL, "sxirtc", DV_DULL
+};
+
+int sxirtc_gettime(todr_chip_handle_t, struct timeval *);
+int sxirtc_settime(todr_chip_handle_t, struct timeval *);
+
+int
+sxirtc_match(struct device *parent, void *match, void *aux)
+{
+ struct fdt_attach_args *faa = aux;
+
+ return (OF_is_compatible(faa->fa_node, "allwinner,sun4i-a10-rtc") ||
+ OF_is_compatible(faa->fa_node, "allwinner,sun7i-a20-rtc") ||
+ OF_is_compatible(faa->fa_node, "allwinner,sun6i-a31-rtc"));
+}
+
+void
+sxirtc_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct sxirtc_softc *sc = (struct sxirtc_softc *)self;
+ struct fdt_attach_args *faa = aux;
+ todr_chip_handle_t handle;
+
+ if (faa->fa_nreg < 1)
+ return;
+
+ handle = malloc(sizeof(struct todr_chip_handle), M_DEVBUF, M_NOWAIT);
+ if (handle == NULL)
+ panic("sxirtc_attach: couldn't allocate todr_handle");
+
+ sc->sc_iot = faa->fa_iot;
+ if (bus_space_map(sc->sc_iot, faa->fa_reg[0].addr,
+ faa->fa_reg[0].size, 0, &sc->sc_ioh))
+ panic("sxirtc_attach: bus_space_map failed!");
+
+ if (OF_is_compatible(faa->fa_node, "allwinner,sun6i-a31-rtc")) {
+ sc->sc_yymmdd = SXIRTC_YYMMDD_A31;
+ sc->sc_hhmmss = SXIRTC_HHMMSS_A31;
+ } else {
+ sc->sc_yymmdd = SXIRTC_YYMMDD;
+ sc->sc_hhmmss = SXIRTC_HHMMSS;
+ }
+
+ if (OF_is_compatible(faa->fa_node, "allwinner,sun7i-a20-rtc")) {
+ sc->base_year = 1970;
+ sc->year_mask = 0xff;
+ sc->leap_shift = 24;
+ } else {
+ sc->base_year = 2010;
+ sc->year_mask = 0x3f;
+ sc->leap_shift = 22;
+ }
+
+ handle->cookie = self;
+ handle->todr_gettime = sxirtc_gettime;
+ handle->todr_settime = sxirtc_settime;
+ handle->todr_getcal = NULL;
+ handle->todr_setcal = NULL;
+ handle->bus_cookie = NULL;
+ handle->todr_setwen = NULL;
+ todr_handle = handle;
+
+ printf("\n");
+}
+
+int
+sxirtc_gettime(todr_chip_handle_t handle, struct timeval *tv)
+{
+ struct sxirtc_softc *sc = (struct sxirtc_softc *)handle->cookie;
+ struct clock_ymdhms dt;
+ uint32_t reg;
+
+ reg = SXIREAD4(sc, sc->sc_hhmmss);
+ dt.dt_sec = reg & 0x3f;
+ dt.dt_min = reg >> 8 & 0x3f;
+ dt.dt_hour = reg >> 16 & 0x1f;
+ dt.dt_wday = reg >> 29 & 0x07;
+
+ reg = SXIREAD4(sc, sc->sc_yymmdd);
+ dt.dt_day = reg & 0x1f;
+ dt.dt_mon = reg >> 8 & 0x0f;
+ dt.dt_year = (reg >> 16 & sc->year_mask) + sc->base_year;
+
+ if (dt.dt_sec > 59 || dt.dt_min > 59 ||
+ dt.dt_hour > 23 || dt.dt_wday > 6 ||
+ dt.dt_day > 31 || dt.dt_day == 0 ||
+ dt.dt_mon > 12 || dt.dt_mon == 0)
+ return 1;
+
+ tv->tv_sec = clock_ymdhms_to_secs(&dt);
+ tv->tv_usec = 0;
+ return 0;
+}
+
+int
+sxirtc_settime(todr_chip_handle_t handle, struct timeval *tv)
+{
+ struct sxirtc_softc *sc = (struct sxirtc_softc *)handle->cookie;
+ struct clock_ymdhms dt;
+
+ clock_secs_to_ymdhms(tv->tv_sec, &dt);
+
+ if (dt.dt_sec > 59 || dt.dt_min > 59 ||
+ dt.dt_hour > 23 || dt.dt_wday > 6 ||
+ dt.dt_day > 31 || dt.dt_day == 0 ||
+ dt.dt_mon > 12 || dt.dt_mon == 0)
+ return 1;
+
+ SXICMS4(sc, sc->sc_hhmmss, 0xe0000000 | 0x1f0000 | 0x3f00 | 0x3f,
+ dt.dt_sec | (dt.dt_min << 8) | (dt.dt_hour << 16) |
+ (dt.dt_wday << 29));
+
+ SXICMS4(sc, sc->sc_yymmdd, 0x00400000 | (sc->year_mask << 16) |
+ 0x0f00 | 0x1f, dt.dt_day | (dt.dt_mon << 8) |
+ ((dt.dt_year - sc->base_year) << 16) |
+ (LEAPYEAR(dt.dt_year) << sc->leap_shift));
+
+ return 0;
+}