spibus.c revision 192059
1160370Simp#include <sys/cdefs.h> 2160370Simp__FBSDID("$FreeBSD: head/sys/dev/spibus/spibus.c 192059 2009-05-13 18:42:49Z gonzo $"); 3160370Simp 4160370Simp#include <sys/param.h> 5160370Simp#include <sys/systm.h> 6160370Simp#include <sys/malloc.h> 7160370Simp#include <sys/module.h> 8160370Simp#include <sys/kernel.h> 9160370Simp#include <sys/queue.h> 10160370Simp#include <sys/sysctl.h> 11160370Simp#include <sys/types.h> 12160370Simp 13160370Simp#include <sys/bus.h> 14160370Simp#include <machine/bus.h> 15160370Simp#include <sys/rman.h> 16160370Simp#include <machine/resource.h> 17160370Simp 18160370Simp#include <dev/spibus/spibusvar.h> 19160370Simp#include <dev/spibus/spi.h> 20160370Simp#include "spibus_if.h" 21160370Simp 22160370Simpstatic int 23160370Simpspibus_probe(device_t dev) 24160370Simp{ 25160370Simp device_set_desc(dev, "spibus bus"); 26160370Simp return (0); 27160370Simp} 28160370Simp 29160370Simpstatic int 30160370Simpspibus_attach(device_t dev) 31160370Simp{ 32160370Simp struct spibus_softc *sc = SPIBUS_SOFTC(dev); 33160370Simp 34160370Simp sc->dev = dev; 35160370Simp bus_enumerate_hinted_children(dev); 36160370Simp return (bus_generic_attach(dev)); 37160370Simp} 38160370Simp 39160370Simp/* 40160370Simp * Since this is not a self-enumerating bus, and since we always add 41160370Simp * children in attach, we have to always delete children here. 42160370Simp */ 43160370Simpstatic int 44160370Simpspibus_detach(device_t dev) 45160370Simp{ 46160370Simp int err, ndevs, i; 47160370Simp device_t *devlist; 48160370Simp 49160370Simp if ((err = bus_generic_detach(dev)) != 0) 50160370Simp return (err); 51160370Simp if ((err = device_get_children(dev, &devlist, &ndevs)) != 0) 52160370Simp return (err); 53160370Simp for (i = 0; i < ndevs; i++) 54160370Simp device_delete_child(dev, devlist[i]); 55160370Simp free(devlist, M_TEMP); 56160370Simp 57160370Simp return (0); 58160370Simp} 59160370Simp 60160370Simpstatic int 61160370Simpspibus_suspend(device_t dev) 62160370Simp{ 63160370Simp return (bus_generic_suspend(dev)); 64160370Simp} 65160370Simp 66160370Simpstatic 67160370Simpint 68160370Simpspibus_resume(device_t dev) 69160370Simp{ 70160370Simp return (bus_generic_resume(dev)); 71160370Simp} 72160370Simp 73160370Simpstatic int 74160370Simpspibus_print_child(device_t dev, device_t child) 75160370Simp{ 76160370Simp struct spibus_ivar *devi = SPIBUS_IVAR(child); 77160370Simp int retval = 0; 78160370Simp 79160370Simp retval += bus_print_child_header(dev, child); 80160370Simp retval += printf(" at cs %d", devi->cs); 81160370Simp retval += bus_print_child_footer(dev, child); 82160370Simp 83160370Simp return (retval); 84160370Simp} 85160370Simp 86160370Simpstatic void 87160370Simpspibus_probe_nomatch(device_t bus, device_t child) 88160370Simp{ 89160370Simp struct spibus_ivar *devi = SPIBUS_IVAR(child); 90160370Simp 91160370Simp device_printf(bus, "<unknown card>"); 92160370Simp printf(" at cs %d\n", devi->cs); 93160370Simp return; 94160370Simp} 95160370Simp 96160370Simpstatic int 97160370Simpspibus_child_location_str(device_t bus, device_t child, char *buf, 98160370Simp size_t buflen) 99160370Simp{ 100160370Simp struct spibus_ivar *devi = SPIBUS_IVAR(child); 101160370Simp 102160370Simp snprintf(buf, buflen, "cs=%d", devi->cs); 103160370Simp return (0); 104160370Simp} 105160370Simp 106160370Simpstatic int 107160370Simpspibus_child_pnpinfo_str(device_t bus, device_t child, char *buf, 108160370Simp size_t buflen) 109160370Simp{ 110160370Simp *buf = '\0'; 111160370Simp return (0); 112160370Simp} 113160370Simp 114160370Simpstatic int 115160370Simpspibus_read_ivar(device_t bus, device_t child, int which, u_char *result) 116160370Simp{ 117160370Simp struct spibus_ivar *devi = SPIBUS_IVAR(child); 118160370Simp 119160370Simp switch (which) { 120160370Simp default: 121160370Simp return (EINVAL); 122160370Simp case SPIBUS_IVAR_CS: 123160370Simp *(uint32_t *)result = devi->cs; 124160370Simp break; 125160370Simp } 126160370Simp return (0); 127160370Simp} 128160370Simp 129160370Simpstatic device_t 130160370Simpspibus_add_child(device_t dev, int order, const char *name, int unit) 131160370Simp{ 132160370Simp device_t child; 133160370Simp struct spibus_ivar *devi; 134160370Simp 135160370Simp child = device_add_child_ordered(dev, order, name, unit); 136160370Simp if (child == NULL) 137160370Simp return (child); 138160370Simp devi = malloc(sizeof(struct spibus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO); 139163527Simp if (devi == NULL) { 140163527Simp device_delete_child(dev, child); 141160370Simp return (0); 142163527Simp } 143160370Simp device_set_ivars(child, devi); 144160370Simp return (child); 145160370Simp} 146160370Simp 147160370Simpstatic void 148160370Simpspibus_hinted_child(device_t bus, const char *dname, int dunit) 149160370Simp{ 150160370Simp device_t child; 151160370Simp struct spibus_ivar *devi; 152160370Simp 153160370Simp child = BUS_ADD_CHILD(bus, 0, dname, dunit); 154160370Simp devi = SPIBUS_IVAR(child); 155160370Simp resource_int_value(dname, dunit, "cs", &devi->cs); 156160370Simp} 157160370Simp 158160370Simpstatic int 159160370Simpspibus_transfer_impl(device_t dev, device_t child, struct spi_command *cmd) 160160370Simp{ 161163527Simp return (SPIBUS_TRANSFER(device_get_parent(dev), child, cmd)); 162160370Simp} 163160370Simp 164160370Simpstatic device_method_t spibus_methods[] = { 165160370Simp /* Device interface */ 166160370Simp DEVMETHOD(device_probe, spibus_probe), 167160370Simp DEVMETHOD(device_attach, spibus_attach), 168160370Simp DEVMETHOD(device_detach, spibus_detach), 169160370Simp DEVMETHOD(device_shutdown, bus_generic_shutdown), 170160370Simp DEVMETHOD(device_suspend, spibus_suspend), 171160370Simp DEVMETHOD(device_resume, spibus_resume), 172160370Simp 173160370Simp /* Bus interface */ 174160370Simp DEVMETHOD(bus_add_child, spibus_add_child), 175160370Simp DEVMETHOD(bus_print_child, spibus_print_child), 176160370Simp DEVMETHOD(bus_driver_added, bus_generic_driver_added), 177160370Simp DEVMETHOD(bus_probe_nomatch, spibus_probe_nomatch), 178160370Simp DEVMETHOD(bus_read_ivar, spibus_read_ivar), 179160370Simp DEVMETHOD(bus_child_pnpinfo_str, spibus_child_pnpinfo_str), 180160370Simp DEVMETHOD(bus_child_location_str, spibus_child_location_str), 181160370Simp DEVMETHOD(bus_hinted_child, spibus_hinted_child), 182160370Simp 183160370Simp /* spibus interface */ 184160370Simp DEVMETHOD(spibus_transfer, spibus_transfer_impl), 185160370Simp 186160370Simp { 0, 0 } 187160370Simp}; 188160370Simp 189160370Simpstatic driver_t spibus_driver = { 190160370Simp "spibus", 191160370Simp spibus_methods, 192160370Simp sizeof(struct spibus_softc) 193160370Simp}; 194160370Simp 195160370Simpdevclass_t spibus_devclass; 196160370Simp 197192059SgonzoDRIVER_MODULE(spibus, spi, spibus_driver, spibus_devclass, 0, 0); 198160370SimpMODULE_VERSION(spibus, 1); 199