at91_pinctrl.c revision 297199
172445Sassar/*-
255682Smarkm * Copyright (c) 2014 Warner Losh.  All rights reserved.
372445Sassar *
455682Smarkm * Redistribution and use in source and binary forms, with or without
555682Smarkm * modification, are permitted provided that the following conditions
655682Smarkm * are met:
755682Smarkm * 1. Redistributions of source code must retain the above copyright
855682Smarkm *    notice, this list of conditions and the following disclaimer.
955682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1055682Smarkm *    notice, this list of conditions and the following disclaimer in the
1155682Smarkm *    documentation and/or other materials provided with the distribution.
1255682Smarkm *
1355682Smarkm * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1455682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1555682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1655682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
1755682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1855682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1955682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2055682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2155682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2255682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2355682Smarkm * SUCH DAMAGE.
2455682Smarkm */
2555682Smarkm
2655682Smarkm#include <sys/cdefs.h>
2755682Smarkm__FBSDID("$FreeBSD: head/sys/arm/at91/at91_pinctrl.c 297199 2016-03-22 22:25:08Z jhibbits $");
2855682Smarkm
2955682Smarkm#include <sys/param.h>
3055682Smarkm#include <sys/bus.h>
3155682Smarkm#include <sys/kernel.h>
3255682Smarkm#include <sys/module.h>
3355682Smarkm#include <sys/resource.h>
3455682Smarkm#include <sys/systm.h>
3555682Smarkm#include <sys/rman.h>
3655682Smarkm
3755682Smarkm#include <machine/bus.h>
3855682Smarkm
3955682Smarkm#include <arm/at91/at91var.h>
4055682Smarkm#include <arm/at91/at91_piovar.h>
4155682Smarkm
4255682Smarkm#include <dev/fdt/fdt_common.h>
4355682Smarkm#include <dev/fdt/fdt_pinctrl.h>
4455682Smarkm#include <dev/ofw/openfirm.h>
4555682Smarkm#include <dev/ofw/ofw_bus.h>
4672445Sassar#include <dev/ofw/ofw_bus_subr.h>
4755682Smarkm
4855682Smarkm#define BUS_PASS_PINMUX (BUS_PASS_INTERRUPT + 1)
4972445Sassar
5055682Smarkmstruct pinctrl_range {
5155682Smarkm	uint64_t bus;
5255682Smarkm	uint64_t host;
5355682Smarkm	uint64_t size;
5455682Smarkm};
5555682Smarkm
5655682Smarkmstruct pinctrl_softc {
5755682Smarkm	device_t dev;
5872445Sassar	phandle_t node;
5972445Sassar
6055682Smarkm	struct pinctrl_range *ranges;
6155682Smarkm	int nranges;
6255682Smarkm
6372445Sassar	pcell_t acells, scells;
6472445Sassar	int done_pinmux;
6572445Sassar};
6655682Smarkm
6755682Smarkmstruct pinctrl_devinfo {
6855682Smarkm	struct ofw_bus_devinfo	obdinfo;
6955682Smarkm	struct resource_list	rl;
7055682Smarkm};
7172445Sassar
7272445Sassarstatic int
7372445Sassarat91_pinctrl_probe(device_t dev)
7455682Smarkm{
7572445Sassar
7672445Sassar	if (!ofw_bus_is_compatible(dev, "atmel,at91rm9200-pinctrl"))
7772445Sassar		return (ENXIO);
7872445Sassar	device_set_desc(dev, "pincontrol bus");
7955682Smarkm        return (0);
8055682Smarkm}
8155682Smarkm
8272445Sassar/* XXX Make this a subclass of simplebus */
8355682Smarkm
8455682Smarkmstatic struct pinctrl_devinfo *
8555682Smarkmat91_pinctrl_setup_dinfo(device_t dev, phandle_t node)
8655682Smarkm{
8755682Smarkm	struct pinctrl_softc *sc;
8855682Smarkm	struct pinctrl_devinfo *ndi;
8972445Sassar	uint32_t *reg, *intr, icells;
9072445Sassar	uint64_t phys, size;
9155682Smarkm	phandle_t iparent;
9255682Smarkm	int i, j, k;
9355682Smarkm	int nintr;
9455682Smarkm	int nreg;
9555682Smarkm
9655682Smarkm	sc = device_get_softc(dev);
9755682Smarkm
9855682Smarkm	ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
9955682Smarkm	if (ofw_bus_gen_setup_devinfo(&ndi->obdinfo, node) != 0) {
10055682Smarkm		free(ndi, M_DEVBUF);
10172445Sassar		return (NULL);
10255682Smarkm	}
10355682Smarkm
10455682Smarkm	resource_list_init(&ndi->rl);
10572445Sassar	nreg = OF_getencprop_alloc(node, "reg", sizeof(*reg), (void **)&reg);
10655682Smarkm	if (nreg == -1)
10755682Smarkm		nreg = 0;
10855682Smarkm	if (nreg % (sc->acells + sc->scells) != 0) {
10955682Smarkm//		if (bootverbose)
11055682Smarkm			device_printf(dev, "Malformed reg property on <%s>\n",
11155682Smarkm			    ndi->obdinfo.obd_name);
11272445Sassar		nreg = 0;
11372445Sassar	}
11472445Sassar
11555682Smarkm	for (i = 0, k = 0; i < nreg; i += sc->acells + sc->scells, k++) {
11672445Sassar		phys = size = 0;
11772445Sassar		for (j = 0; j < sc->acells; j++) {
11872445Sassar			phys <<= 32;
11972445Sassar			phys |= reg[i + j];
12072445Sassar		}
12172445Sassar		for (j = 0; j < sc->scells; j++) {
12272445Sassar			size <<= 32;
12372445Sassar			size |= reg[i + sc->acells + j];
12472445Sassar		}
12555682Smarkm
12655682Smarkm		resource_list_add(&ndi->rl, SYS_RES_MEMORY, k,
12755682Smarkm		    phys, phys + size - 1, size);
12855682Smarkm	}
12972445Sassar	free(reg, M_OFWPROP);
13055682Smarkm
13155682Smarkm	nintr = OF_getencprop_alloc(node, "interrupts",  sizeof(*intr),
13255682Smarkm	    (void **)&intr);
13372445Sassar	if (nintr > 0) {
13472445Sassar		if (OF_searchencprop(node, "interrupt-parent", &iparent,
13555682Smarkm		    sizeof(iparent)) == -1) {
13655682Smarkm			device_printf(dev, "No interrupt-parent found, "
13755682Smarkm			    "assuming direct parent\n");
13855682Smarkm			iparent = OF_parent(node);
13955682Smarkm		}
14055682Smarkm		if (OF_searchencprop(OF_node_from_xref(iparent),
14155682Smarkm		    "#interrupt-cells", &icells, sizeof(icells)) == -1) {
14255682Smarkm			device_printf(dev, "Missing #interrupt-cells property,"
14355682Smarkm			    " assuming <1>\n");
14455682Smarkm			icells = 1;
14555682Smarkm		}
14655682Smarkm		if (icells < 1 || icells > nintr) {
14755682Smarkm			device_printf(dev, "Invalid #interrupt-cells property "
14855682Smarkm			    "value <%d>, assuming <1>\n", icells);
14955682Smarkm			icells = 1;
15055682Smarkm		}
15155682Smarkm		for (i = 0, k = 0; i < nintr; i += icells, k++) {
15255682Smarkm			intr[i] = ofw_bus_map_intr(dev, iparent, icells,
15355682Smarkm			    &intr[i]);
15472445Sassar			resource_list_add(&ndi->rl, SYS_RES_IRQ, k, intr[i],
15555682Smarkm			    intr[i], 1);
15655682Smarkm		}
15755682Smarkm		free(intr, M_OFWPROP);
15855682Smarkm	}
15955682Smarkm
16055682Smarkm	return (ndi);
16155682Smarkm}
16255682Smarkm
16372445Sassarstatic int
16472445Sassarat91_pinctrl_fill_ranges(phandle_t node, struct pinctrl_softc *sc)
16555682Smarkm{
16655682Smarkm	int host_address_cells;
16755682Smarkm	cell_t *base_ranges;
16855682Smarkm	ssize_t nbase_ranges;
16955682Smarkm	int err;
17055682Smarkm	int i, j, k;
17155682Smarkm
17255682Smarkm	err = OF_searchencprop(OF_parent(node), "#address-cells",
17372445Sassar	    &host_address_cells, sizeof(host_address_cells));
17472445Sassar	if (err <= 0)
17572445Sassar		return (-1);
17655682Smarkm
17755682Smarkm	nbase_ranges = OF_getproplen(node, "ranges");
17855682Smarkm	if (nbase_ranges < 0)
17955682Smarkm		return (-1);
18055682Smarkm	sc->nranges = nbase_ranges / sizeof(cell_t) /
18155682Smarkm	    (sc->acells + host_address_cells + sc->scells);
18272445Sassar	if (sc->nranges == 0)
18355682Smarkm		return (0);
18472445Sassar
18572445Sassar	sc->ranges = malloc(sc->nranges * sizeof(sc->ranges[0]),
18672445Sassar	    M_DEVBUF, M_WAITOK);
18755682Smarkm	base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
18855682Smarkm	OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
18955682Smarkm
19072445Sassar	for (i = 0, j = 0; i < sc->nranges; i++) {
19172445Sassar		sc->ranges[i].bus = 0;
19255682Smarkm		for (k = 0; k < sc->acells; k++) {
19355682Smarkm			sc->ranges[i].bus <<= 32;
19472445Sassar			sc->ranges[i].bus |= base_ranges[j++];
19572445Sassar		}
19672445Sassar		sc->ranges[i].host = 0;
19772445Sassar		for (k = 0; k < host_address_cells; k++) {
19872445Sassar			sc->ranges[i].host <<= 32;
19972445Sassar			sc->ranges[i].host |= base_ranges[j++];
20055682Smarkm		}
20172445Sassar		sc->ranges[i].size = 0;
20255682Smarkm		for (k = 0; k < sc->scells; k++) {
20355682Smarkm			sc->ranges[i].size <<= 32;
20455682Smarkm			sc->ranges[i].size |= base_ranges[j++];
20572445Sassar		}
20672445Sassar	}
20755682Smarkm
20855682Smarkm	free(base_ranges, M_DEVBUF);
20955682Smarkm	return (sc->nranges);
21055682Smarkm}
21155682Smarkm
21255682Smarkmstatic int
21355682Smarkmat91_pinctrl_attach(device_t dev)
21455682Smarkm{
21555682Smarkm	struct pinctrl_softc *sc;
21672445Sassar	struct pinctrl_devinfo *di;
21772445Sassar	phandle_t	node;
21855682Smarkm	device_t	cdev;
21972445Sassar
22072445Sassar	sc = device_get_softc(dev);
22155682Smarkm	node = ofw_bus_get_node(dev);
22255682Smarkm
22355682Smarkm	sc->dev = dev;
22455682Smarkm	sc->node = node;
22555682Smarkm
22655682Smarkm	/*
22772445Sassar	 * Some important numbers
22855682Smarkm	 */
22972445Sassar	sc->acells = 2;
23072445Sassar	OF_getencprop(node, "#address-cells", &sc->acells, sizeof(sc->acells));
23172445Sassar	sc->scells = 1;
23255682Smarkm	OF_getencprop(node, "#size-cells", &sc->scells, sizeof(sc->scells));
23355682Smarkm
23455682Smarkm	if (at91_pinctrl_fill_ranges(node, sc) < 0) {
23572445Sassar		device_printf(dev, "could not get ranges\n");
23655682Smarkm		return (ENXIO);
23755682Smarkm	}
23855682Smarkm
23972445Sassar	for (node = OF_child(node); node > 0; node = OF_peer(node)) {
24055682Smarkm		if ((di = at91_pinctrl_setup_dinfo(dev, node)) == NULL)
24155682Smarkm			continue;
24255682Smarkm		cdev = device_add_child(dev, NULL, -1);
24372445Sassar		if (cdev == NULL) {
24455682Smarkm			device_printf(dev, "<%s>: device_add_child failed\n",
24555682Smarkm			    di->obdinfo.obd_name);
24655682Smarkm			resource_list_free(&di->rl);
24755682Smarkm			ofw_bus_gen_destroy_devinfo(&di->obdinfo);
24855682Smarkm			free(di, M_DEVBUF);
24955682Smarkm			continue;
25055682Smarkm		}
25155682Smarkm		device_set_ivars(cdev, di);
25272445Sassar	}
25355682Smarkm
25472445Sassar	fdt_pinctrl_register(dev, "atmel,pins");
25572445Sassar
25655682Smarkm	return (bus_generic_attach(dev));
25772445Sassar}
25855682Smarkm
25972445Sassarstatic const struct ofw_bus_devinfo *
26055682Smarkmpinctrl_get_devinfo(device_t bus __unused, device_t child)
26172445Sassar{
26272445Sassar        struct pinctrl_devinfo *ndi;
26372445Sassar
26472445Sassar        ndi = device_get_ivars(child);
26572445Sassar        return (&ndi->obdinfo);
26672445Sassar}
26772445Sassar
26872445Sassarstatic struct resource *
26972445Sassarpinctrl_alloc_resource(device_t bus, device_t child, int type, int *rid,
27072445Sassar    u_long start, u_long end, u_long count, u_int flags)
27155682Smarkm{
27272445Sassar	struct pinctrl_softc *sc;
27372445Sassar	struct pinctrl_devinfo *di;
27472445Sassar	struct resource_list_entry *rle;
27572445Sassar	int j;
27672445Sassar
27772445Sassar	sc = device_get_softc(bus);
27872445Sassar
27955682Smarkm	/*
28055682Smarkm	 * Request for the default allocation with a given rid: use resource
28155682Smarkm	 * list stored in the local device info.
28255682Smarkm	 */
28355682Smarkm	if (RMAN_IS_DEFAULT_RANGE(start, end)) {
28455682Smarkm		if ((di = device_get_ivars(child)) == NULL)
28555682Smarkm			return (NULL);
28655682Smarkm
28755682Smarkm		if (type == SYS_RES_IOPORT)
28855682Smarkm			type = SYS_RES_MEMORY;
28955682Smarkm
29055682Smarkm		rle = resource_list_find(&di->rl, type, *rid);
29155682Smarkm		if (rle == NULL) {
29255682Smarkm//			if (bootverbose)
29355682Smarkm				device_printf(bus, "no default resources for "
29455682Smarkm				    "rid = %d, type = %d\n", *rid, type);
29555682Smarkm			return (NULL);
29655682Smarkm		}
29755682Smarkm		start = rle->start;
29855682Smarkm		end = rle->end;
29955682Smarkm		count = rle->count;
30055682Smarkm        }
30155682Smarkm
30255682Smarkm	if (type == SYS_RES_MEMORY) {
30355682Smarkm		/* Remap through ranges property */
30472445Sassar		for (j = 0; j < sc->nranges; j++) {
30572445Sassar			if (start >= sc->ranges[j].bus && end <
30672445Sassar			    sc->ranges[j].bus + sc->ranges[j].size) {
30772445Sassar				start -= sc->ranges[j].bus;
30872445Sassar				start += sc->ranges[j].host;
30972445Sassar				end -= sc->ranges[j].bus;
31055682Smarkm				end += sc->ranges[j].host;
31155682Smarkm				break;
31255682Smarkm			}
31372445Sassar		}
31472445Sassar		if (j == sc->nranges && sc->nranges != 0) {
31572445Sassar//			if (bootverbose)
31672445Sassar				device_printf(bus, "Could not map resource "
31772445Sassar				    "%#lx-%#lx\n", start, end);
31872445Sassar
31955682Smarkm			return (NULL);
32072445Sassar		}
32155682Smarkm	}
32272445Sassar
32372445Sassar	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
32455682Smarkm	    count, flags));
32555682Smarkm}
32672445Sassar
32772445Sassarstatic int
32872445Sassarpinctrl_print_res(struct pinctrl_devinfo *di)
32972445Sassar{
33072445Sassar	int rv;
33155682Smarkm
33255682Smarkm	rv = 0;
33372445Sassar	rv += resource_list_print_type(&di->rl, "mem", SYS_RES_MEMORY, "%#jx");
33455682Smarkm	rv += resource_list_print_type(&di->rl, "irq", SYS_RES_IRQ, "%jd");
33555682Smarkm	return (rv);
33655682Smarkm}
33755682Smarkm
33855682Smarkmstatic void
33955682Smarkmpinctrl_probe_nomatch(device_t bus, device_t child)
34055682Smarkm{
34155682Smarkm	const char *name, *type, *compat;
34255682Smarkm
34355682Smarkm//	if (!bootverbose)
34455682Smarkm		return;
34555682Smarkm
34655682Smarkm	name = ofw_bus_get_name(child);
34755682Smarkm	type = ofw_bus_get_type(child);
34855682Smarkm	compat = ofw_bus_get_compat(child);
34955682Smarkm
35072445Sassar	device_printf(bus, "<%s>", name != NULL ? name : "unknown");
35172445Sassar	pinctrl_print_res(device_get_ivars(child));
35255682Smarkm	if (!ofw_bus_status_okay(child))
35355682Smarkm		printf(" disabled");
35472445Sassar	if (type)
35572445Sassar		printf(" type %s", type);
35655682Smarkm	if (compat)
35755682Smarkm		printf(" compat %s", compat);
35855682Smarkm	printf(" (no driver attached)\n");
35955682Smarkm}
36055682Smarkm
36155682Smarkmstatic int
36255682Smarkmpinctrl_print_child(device_t bus, device_t child)
36355682Smarkm{
36455682Smarkm	int rv;
36555682Smarkm
36655682Smarkm	rv = bus_print_child_header(bus, child);
36755682Smarkm	rv += pinctrl_print_res(device_get_ivars(child));
36872445Sassar	if (!ofw_bus_status_okay(child))
36955682Smarkm		rv += printf(" disabled");
37055682Smarkm	rv += bus_print_child_footer(bus, child);
37155682Smarkm	return (rv);
37255682Smarkm}
37355682Smarkm
37455682Smarkmconst char *periphs[] = {"gpio", "periph A", "periph B", "periph C", "periph D", "periph E" };
37555682Smarkm
37655682Smarkmstruct pincfg {
37755682Smarkm	uint32_t unit;
37855682Smarkm	uint32_t pin;
37972445Sassar	uint32_t periph;
38055682Smarkm	uint32_t flags;
38155682Smarkm};
38255682Smarkm
38355682Smarkmstatic int
38472445Sassarpinctrl_configure_pins(device_t bus, phandle_t cfgxref)
38555682Smarkm{
38672445Sassar	struct pinctrl_softc *sc;
38755682Smarkm	struct pincfg *cfg, *cfgdata;
38855682Smarkm	char name[32];
38955682Smarkm	phandle_t node;
39055682Smarkm	ssize_t npins;
39155682Smarkm	int i;
39255682Smarkm
39355682Smarkm	sc = device_get_softc(bus);
39455682Smarkm	node = OF_node_from_xref(cfgxref);
39555682Smarkm	memset(name, 0, sizeof(name));
39655682Smarkm	OF_getprop(node, "name", name, sizeof(name));
39755682Smarkm	npins = OF_getencprop_alloc(node, "atmel,pins", sizeof(*cfgdata),
39872445Sassar	    (void **)&cfgdata);
39972445Sassar	if (npins < 0) {
40055682Smarkm		printf("We're doing it wrong %s\n", name);
40155682Smarkm		return (ENXIO);
40255682Smarkm	}
40355682Smarkm	if (npins == 0)
40455682Smarkm		return (0);
40572445Sassar	for (i = 0, cfg = cfgdata; i < npins; i++, cfg++) {
40655682Smarkm		uint32_t pio;
40755682Smarkm		pio = (0xfffffff & sc->ranges[0].bus) + 0x200 * cfg->unit;
40855682Smarkm		printf("P%c%d %s %#x\n", cfg->unit + 'A', cfg->pin,
40955682Smarkm		    periphs[cfg->periph], cfg->flags);
41072445Sassar		switch (cfg->periph) {
41172445Sassar		case 0:
41255682Smarkm			at91_pio_use_gpio(pio, 1u << cfg->pin);
41355682Smarkm			at91_pio_gpio_pullup(pio, 1u << cfg->pin,
41455682Smarkm			    !!(cfg->flags & 1));
41555682Smarkm			at91_pio_gpio_high_z(pio, 1u << cfg->pin,
41672445Sassar			    !!(cfg->flags & 2));
41755682Smarkm			at91_pio_gpio_set_deglitch(pio,
41855682Smarkm			    1u << cfg->pin, !!(cfg->flags & 4));
41955682Smarkm//			at91_pio_gpio_pulldown(pio, 1u << cfg->pin,
42055682Smarkm//			    !!(cfg->flags & 8));
42155682Smarkm//			at91_pio_gpio_dis_schmidt(pio,
42255682Smarkm//			    1u << cfg->pin, !!(cfg->flags & 16));
42355682Smarkm			break;
42455682Smarkm		case 1:
42572445Sassar			at91_pio_use_periph_a(pio, 1u << cfg->pin, cfg->flags);
42672445Sassar			break;
42755682Smarkm		case 2:
42855682Smarkm			at91_pio_use_periph_b(pio, 1u << cfg->pin, cfg->flags);
42955682Smarkm			break;
43055682Smarkm		}
43155682Smarkm	}
43255682Smarkm	free(cfgdata, M_OFWPROP);
43355682Smarkm	return (0);
43472445Sassar}
43555682Smarkm
43655682Smarkmstatic void
43755682Smarkmpinctrl_new_pass(device_t bus)
43855682Smarkm{
43955682Smarkm	struct pinctrl_softc *sc;
44055682Smarkm
44155682Smarkm	sc = device_get_softc(bus);
44255682Smarkm
44355682Smarkm	bus_generic_new_pass(bus);
44472445Sassar
44572445Sassar	if (sc->done_pinmux || bus_current_pass < BUS_PASS_PINMUX)
44672445Sassar		return;
44772445Sassar	sc->done_pinmux++;
44855682Smarkm
44955682Smarkm	fdt_pinctrl_configure_tree(bus);
45055682Smarkm}
45155682Smarkm
45255682Smarkmstatic device_method_t at91_pinctrl_methods[] = {
45355682Smarkm	DEVMETHOD(device_probe, at91_pinctrl_probe),
45455682Smarkm	DEVMETHOD(device_attach, at91_pinctrl_attach),
45555682Smarkm
45655682Smarkm	DEVMETHOD(bus_print_child,	pinctrl_print_child),
45755682Smarkm	DEVMETHOD(bus_probe_nomatch,	pinctrl_probe_nomatch),
45855682Smarkm	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
45972445Sassar	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
46072445Sassar	DEVMETHOD(bus_alloc_resource,	pinctrl_alloc_resource),
46155682Smarkm	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
46255682Smarkm	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
46355682Smarkm	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
46455682Smarkm	DEVMETHOD(bus_adjust_resource,	bus_generic_adjust_resource),
46555682Smarkm	DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
46655682Smarkm	DEVMETHOD(bus_new_pass,		pinctrl_new_pass),
46755682Smarkm
46855682Smarkm	/* ofw_bus interface */
46955682Smarkm	DEVMETHOD(ofw_bus_get_devinfo,	pinctrl_get_devinfo),
47055682Smarkm	DEVMETHOD(ofw_bus_get_compat,	ofw_bus_gen_get_compat),
47155682Smarkm	DEVMETHOD(ofw_bus_get_model,	ofw_bus_gen_get_model),
47255682Smarkm	DEVMETHOD(ofw_bus_get_name,	ofw_bus_gen_get_name),
47355682Smarkm	DEVMETHOD(ofw_bus_get_node,	ofw_bus_gen_get_node),
47455682Smarkm	DEVMETHOD(ofw_bus_get_type,	ofw_bus_gen_get_type),
47555682Smarkm
47655682Smarkm        /* fdt_pintrl interface */
47755682Smarkm	DEVMETHOD(fdt_pinctrl_configure,pinctrl_configure_pins),
47855682Smarkm	DEVMETHOD_END
47955682Smarkm};
48055682Smarkm
48155682Smarkmstatic driver_t at91_pinctrl_driver = {
48255682Smarkm	"at91_pinctrl",
48355682Smarkm	at91_pinctrl_methods,
48455682Smarkm	sizeof(struct pinctrl_softc),
48555682Smarkm};
48655682Smarkm
48755682Smarkmstatic devclass_t at91_pinctrl_devclass;
48855682Smarkm
48955682SmarkmEARLY_DRIVER_MODULE(at91_pinctrl, simplebus, at91_pinctrl_driver,
49055682Smarkm    at91_pinctrl_devclass, NULL, NULL, BUS_PASS_BUS);
49155682Smarkm
49255682Smarkm/*
49355682Smarkm * dummy driver to force pass BUS_PASS_PINMUX to happen.
49455682Smarkm */
49555682Smarkmstatic int
49655682Smarkmat91_pingroup_probe(device_t dev)
49755682Smarkm{
49855682Smarkm	return ENXIO;
49955682Smarkm}
50055682Smarkm
50155682Smarkmstatic device_method_t at91_pingroup_methods[] = {
50255682Smarkm	DEVMETHOD(device_probe, at91_pingroup_probe),
50355682Smarkm
50455682Smarkm	DEVMETHOD_END
50555682Smarkm};
50655682Smarkm
50755682Smarkm
50855682Smarkmstatic driver_t at91_pingroup_driver = {
50955682Smarkm	"at91_pingroup",
51055682Smarkm	at91_pingroup_methods,
51155682Smarkm	0,
51255682Smarkm};
51355682Smarkm
51455682Smarkmstatic devclass_t at91_pingroup_devclass;
51555682Smarkm
51655682SmarkmEARLY_DRIVER_MODULE(at91_pingroup, at91_pinctrl, at91_pingroup_driver,
51755682Smarkm    at91_pingroup_devclass, NULL, NULL, BUS_PASS_PINMUX);
51855682Smarkm