MFp4: Make the iicbus fully hinted. We no longer automatically add
some devices (and not others). To get instances onto the iicbus, one now needs hints or an identify routine. We also do not probe the bus for devices because many iic devices cannot be safely probed (and when they can, the probe order turns out to be somewhat difficult to get right). # I'm not 100% sure that the iicsmb removal is right. Please contact me if # this causes difficulty.
This commit is contained in:
parent
99a1402117
commit
d4fa68402e
@ -249,9 +249,8 @@ iicioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *t
|
||||
if (!sc)
|
||||
return (EINVAL);
|
||||
|
||||
if ((error = iicbus_request_bus(device_get_parent(iicdev), iicdev,
|
||||
(flags & O_NONBLOCK) ? IIC_DONTWAIT :
|
||||
(IIC_WAIT | IIC_INTR))))
|
||||
if ((error = iicbus_request_bus(parent, iicdev,
|
||||
(flags & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR))))
|
||||
return (error);
|
||||
|
||||
switch (cmd) {
|
||||
@ -314,7 +313,7 @@ iicioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *t
|
||||
if (!(m->flags & IIC_M_RD))
|
||||
copyin(usrbufs[i], m->buf, m->len);
|
||||
}
|
||||
error = iicbus_transfer(parent, (struct iic_msg *)buf, d->nmsgs);
|
||||
error = iicbus_transfer(iicdev, (struct iic_msg *)buf, d->nmsgs);
|
||||
/* Copyout all read segments, free up kernel buffers */
|
||||
for (i = 0; i < d->nmsgs; i++) {
|
||||
m = &((struct iic_msg *)buf)[i];
|
||||
@ -328,7 +327,7 @@ iicioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *t
|
||||
error = ENOTTY;
|
||||
}
|
||||
|
||||
iicbus_release_bus(device_get_parent(iicdev), iicdev);
|
||||
iicbus_release_bus(parent, iicdev);
|
||||
|
||||
if (buf != NULL)
|
||||
free(buf, M_TEMP);
|
||||
|
@ -34,52 +34,18 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
|
||||
#include <dev/iicbus/iiconf.h>
|
||||
#include <dev/iicbus/iicbus.h>
|
||||
|
||||
#include "iicbus_if.h"
|
||||
|
||||
#define DEVTOIICBUS(dev) ((struct iicbus_device*)device_get_ivars(dev))
|
||||
|
||||
devclass_t iicbus_devclass;
|
||||
|
||||
/* See comments below for why auto-scanning is a bad idea. */
|
||||
#define SCAN_IICBUS 0
|
||||
|
||||
/*
|
||||
* Device methods
|
||||
*/
|
||||
static int iicbus_probe(device_t);
|
||||
static int iicbus_attach(device_t);
|
||||
static int iicbus_detach(device_t);
|
||||
static int iicbus_add_child(device_t dev, int order, const char *name, int unit);
|
||||
|
||||
static device_method_t iicbus_methods[] = {
|
||||
/* device interface */
|
||||
DEVMETHOD(device_probe, iicbus_probe),
|
||||
DEVMETHOD(device_attach, iicbus_attach),
|
||||
DEVMETHOD(device_detach, iicbus_detach),
|
||||
|
||||
/* bus interface */
|
||||
DEVMETHOD(bus_add_child, iicbus_add_child),
|
||||
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
|
||||
DEVMETHOD(bus_print_child, bus_generic_print_child),
|
||||
|
||||
DEVMETHOD(iicbus_transfer, iicbus_transfer_gen),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
driver_t iicbus_driver = {
|
||||
"iicbus",
|
||||
iicbus_methods,
|
||||
sizeof(struct iicbus_softc),
|
||||
};
|
||||
|
||||
static int
|
||||
iicbus_probe(device_t dev)
|
||||
{
|
||||
@ -121,7 +87,9 @@ iicbus_attach(device_t dev)
|
||||
#if SCAN_IICBUS
|
||||
unsigned char addr;
|
||||
#endif
|
||||
struct iicbus_softc *sc = IICBUS_SOFTC(dev);
|
||||
|
||||
sc->dev = dev;
|
||||
iicbus_reset(dev, IIC_FASTEST, 0, NULL);
|
||||
|
||||
/* device probing is meaningless since the bus is supposed to be
|
||||
@ -140,15 +108,13 @@ iicbus_attach(device_t dev)
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
device_add_child(dev, "ic", -1);
|
||||
device_add_child(dev, "iicsmb", -1);
|
||||
device_add_child(dev, "ds1672", -1);
|
||||
device_add_child(dev, "ad7418", -1);
|
||||
#if 0
|
||||
/* Always attach the iicsmb children */
|
||||
BUS_ADD_CHILD(dev, 0, "iicsmb", -1);
|
||||
/* attach any known device */
|
||||
device_add_child(dev, "iic", -1);
|
||||
#endif
|
||||
BUS_ADD_CHILD(dev, 0, "iic", -1);
|
||||
/* Attach the wired devices via hints */
|
||||
bus_enumerate_hinted_children(dev);
|
||||
/* Now probe and attach them */
|
||||
bus_generic_attach(dev);
|
||||
return (0);
|
||||
}
|
||||
@ -163,12 +129,89 @@ iicbus_detach(device_t dev)
|
||||
}
|
||||
|
||||
static int
|
||||
iicbus_print_child(device_t dev, device_t child)
|
||||
{
|
||||
struct iicbus_ivar *devi = IICBUS_IVAR(child);
|
||||
int retval = 0;
|
||||
|
||||
retval += bus_print_child_header(dev, child);
|
||||
if (devi->addr != 0)
|
||||
retval += printf(" at addr %#x", devi->addr);
|
||||
retval += bus_print_child_footer(dev, child);
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
static void
|
||||
iicbus_probe_nomatch(device_t bus, device_t child)
|
||||
{
|
||||
struct iicbus_ivar *devi = IICBUS_IVAR(child);
|
||||
|
||||
device_printf(bus, "<unknown card>");
|
||||
printf(" at addr %#x\n", devi->addr);
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
iicbus_child_location_str(device_t bus, device_t child, char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
struct iicbus_ivar *devi = IICBUS_IVAR(child);
|
||||
|
||||
snprintf(buf, buflen, "addr=%#x", devi->addr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
iicbus_child_pnpinfo_str(device_t bus, device_t child, char *buf,
|
||||
size_t buflen)
|
||||
{
|
||||
*buf = '\0';
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
iicbus_read_ivar(device_t bus, device_t child, int which, u_char *result)
|
||||
{
|
||||
struct iicbus_ivar *devi = IICBUS_IVAR(child);
|
||||
|
||||
switch (which) {
|
||||
default:
|
||||
return (EINVAL);
|
||||
case IICBUS_IVAR_ADDR:
|
||||
*(uint32_t *)result = devi->addr;
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_t
|
||||
iicbus_add_child(device_t dev, int order, const char *name, int unit)
|
||||
{
|
||||
device_t child;
|
||||
struct iicbus_ivar *devi;
|
||||
|
||||
device_add_child_ordered(dev, order, name, unit);
|
||||
bus_generic_attach(dev);
|
||||
return (0);
|
||||
child = device_add_child_ordered(dev, order, name, unit);
|
||||
if (child == NULL)
|
||||
return (child);
|
||||
devi = malloc(sizeof(struct iicbus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
if (devi == NULL) {
|
||||
device_delete_child(dev, child);
|
||||
return (0);
|
||||
}
|
||||
device_set_ivars(child, devi);
|
||||
return (child);
|
||||
}
|
||||
|
||||
static void
|
||||
iicbus_hinted_child(device_t bus, const char *dname, int dunit)
|
||||
{
|
||||
device_t child;
|
||||
struct iicbus_ivar *devi;
|
||||
|
||||
child = BUS_ADD_CHILD(bus, 0, dname, dunit);
|
||||
devi = IICBUS_IVAR(child);
|
||||
resource_int_value(dname, dunit, "addr", &devi->addr);
|
||||
}
|
||||
|
||||
int
|
||||
@ -192,6 +235,36 @@ iicbus_null_repeated_start(device_t dev, u_char addr)
|
||||
return (IIC_ENOTSUPP);
|
||||
}
|
||||
|
||||
static device_method_t iicbus_methods[] = {
|
||||
/* device interface */
|
||||
DEVMETHOD(device_probe, iicbus_probe),
|
||||
DEVMETHOD(device_attach, iicbus_attach),
|
||||
DEVMETHOD(device_detach, iicbus_detach),
|
||||
|
||||
/* bus interface */
|
||||
DEVMETHOD(bus_add_child, iicbus_add_child),
|
||||
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
|
||||
DEVMETHOD(bus_print_child, iicbus_print_child),
|
||||
DEVMETHOD(bus_probe_nomatch, iicbus_probe_nomatch),
|
||||
DEVMETHOD(bus_read_ivar, iicbus_read_ivar),
|
||||
DEVMETHOD(bus_child_pnpinfo_str, iicbus_child_pnpinfo_str),
|
||||
DEVMETHOD(bus_child_location_str, iicbus_child_location_str),
|
||||
DEVMETHOD(bus_hinted_child, iicbus_hinted_child),
|
||||
|
||||
/* iicbus interface */
|
||||
DEVMETHOD(iicbus_transfer, iicbus_transfer),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
driver_t iicbus_driver = {
|
||||
"iicbus",
|
||||
iicbus_methods,
|
||||
sizeof(struct iicbus_softc),
|
||||
};
|
||||
|
||||
devclass_t iicbus_devclass;
|
||||
|
||||
DRIVER_MODULE(iicbus, envctrl, iicbus_driver, iicbus_devclass, 0, 0);
|
||||
DRIVER_MODULE(iicbus, iicbb, iicbus_driver, iicbus_devclass, 0, 0);
|
||||
MODULE_VERSION(iicbus, IICBUS_MODVER);
|
||||
|
Loading…
Reference in New Issue
Block a user