diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2017-01-21 08:26:50 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2017-01-21 08:26:50 +0000 |
commit | c120c2d8feb63c02d83db024965d5a26aed7ea6c (patch) | |
tree | 35737f92ee10fb981dc1b0344efecb23a0bab2fc /sys/dev | |
parent | bd81ee3cd8e1d2999ce379445c1de1acdf287390 (diff) |
Move Allwinner drivers that will soon be used by OpenBSD/arm64
to the new MI FDT driver directory.
"go ahead" kettenis@
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/fdt/files.fdt | 21 | ||||
-rw-r--r-- | sys/dev/fdt/sunxireg.h | 140 | ||||
-rw-r--r-- | sys/dev/fdt/sxiccmu.c | 792 | ||||
-rw-r--r-- | sys/dev/fdt/sxiccmu_clocks.h | 180 | ||||
-rw-r--r-- | sys/dev/fdt/sxiehci.c | 320 | ||||
-rw-r--r-- | sys/dev/fdt/sximmc.c | 1099 | ||||
-rw-r--r-- | sys/dev/fdt/sxipio.c | 452 | ||||
-rw-r--r-- | sys/dev/fdt/sxipio_pins.h | 5756 | ||||
-rw-r--r-- | sys/dev/fdt/sxipiovar.h | 45 | ||||
-rw-r--r-- | sys/dev/fdt/sxirtc.c | 184 |
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; +} |