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 **)®); 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