Correctly handle nodes compatible with "syscon", "simple-bus".
Syscon can also have child nodes that share a registration file with it. To do this correctly, follow these steps: - subclass syscon from simplebus and expose it if the node is also "simple-bus" compatible. - block simplebus probe for this compatible string, so it's priority (bus pass) doesn't colide with syscon driver. While I'm in, also block "syscon", "simple-mfd" for the same reason. MFC after: 4 weeks
This commit is contained in:
parent
e399566123
commit
8dc348a479
@ -60,7 +60,7 @@ static int syscon_generic_write_4(struct syscon *syscon, bus_size_t offset,
|
|||||||
uint32_t val);
|
uint32_t val);
|
||||||
static int syscon_generic_modify_4(struct syscon *syscon, bus_size_t offset,
|
static int syscon_generic_modify_4(struct syscon *syscon, bus_size_t offset,
|
||||||
uint32_t clear_bits, uint32_t set_bits);
|
uint32_t clear_bits, uint32_t set_bits);
|
||||||
|
static int syscon_generic_detach(device_t dev);
|
||||||
/*
|
/*
|
||||||
* Generic syscon driver (FDT)
|
* Generic syscon driver (FDT)
|
||||||
*/
|
*/
|
||||||
@ -152,7 +152,7 @@ static int
|
|||||||
syscon_generic_attach(device_t dev)
|
syscon_generic_attach(device_t dev)
|
||||||
{
|
{
|
||||||
struct syscon_generic_softc *sc;
|
struct syscon_generic_softc *sc;
|
||||||
int rid;
|
int rid, rv;
|
||||||
|
|
||||||
sc = device_get_softc(dev);
|
sc = device_get_softc(dev);
|
||||||
sc->dev = dev;
|
sc->dev = dev;
|
||||||
@ -170,9 +170,20 @@ syscon_generic_attach(device_t dev)
|
|||||||
ofw_bus_get_node(dev));
|
ofw_bus_get_node(dev));
|
||||||
if (sc->syscon == NULL) {
|
if (sc->syscon == NULL) {
|
||||||
device_printf(dev, "Failed to create/register syscon\n");
|
device_printf(dev, "Failed to create/register syscon\n");
|
||||||
|
syscon_generic_detach(dev);
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
}
|
}
|
||||||
return (0);
|
if (ofw_bus_is_compatible(dev, "simple-bus")) {
|
||||||
|
rv = simplebus_attach_impl(sc->dev);
|
||||||
|
if (rv != 0) {
|
||||||
|
device_printf(dev, "Failed to create simplebus\n");
|
||||||
|
syscon_generic_detach(dev);
|
||||||
|
return (ENXIO);
|
||||||
|
}
|
||||||
|
sc->simplebus_attached = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (bus_generic_attach(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -185,7 +196,8 @@ syscon_generic_detach(device_t dev)
|
|||||||
syscon_unregister(sc->syscon);
|
syscon_unregister(sc->syscon);
|
||||||
free(sc->syscon, M_SYSCON);
|
free(sc->syscon, M_SYSCON);
|
||||||
}
|
}
|
||||||
|
if (sc->simplebus_attached)
|
||||||
|
simplebus_detach(dev);
|
||||||
SYSCON_LOCK_DESTROY(sc);
|
SYSCON_LOCK_DESTROY(sc);
|
||||||
|
|
||||||
if (sc->mem_res != NULL)
|
if (sc->mem_res != NULL)
|
||||||
@ -202,8 +214,8 @@ static device_method_t syscon_generic_dmethods[] = {
|
|||||||
DEVMETHOD_END
|
DEVMETHOD_END
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_CLASS_0(syscon_generic, syscon_generic_driver, syscon_generic_dmethods,
|
DEFINE_CLASS_1(syscon_generic_dev, syscon_generic_driver, syscon_generic_dmethods,
|
||||||
sizeof(struct syscon_generic_softc));
|
sizeof(struct syscon_generic_softc), simplebus_driver);
|
||||||
static devclass_t syscon_generic_devclass;
|
static devclass_t syscon_generic_devclass;
|
||||||
|
|
||||||
EARLY_DRIVER_MODULE(syscon_generic, simplebus, syscon_generic_driver,
|
EARLY_DRIVER_MODULE(syscon_generic, simplebus, syscon_generic_driver,
|
||||||
|
@ -29,11 +29,15 @@
|
|||||||
#ifndef DEV_SYSCON_GENERIC_H
|
#ifndef DEV_SYSCON_GENERIC_H
|
||||||
#define DEV_SYSCON_GENERIC_H
|
#define DEV_SYSCON_GENERIC_H
|
||||||
|
|
||||||
|
#include <dev/fdt/simplebus.h>
|
||||||
|
|
||||||
struct syscon_generic_softc {
|
struct syscon_generic_softc {
|
||||||
|
struct simplebus_softc simplebus;
|
||||||
device_t dev;
|
device_t dev;
|
||||||
struct syscon *syscon;
|
struct syscon *syscon;
|
||||||
struct resource *mem_res;
|
struct resource *mem_res;
|
||||||
struct mtx mtx;
|
struct mtx mtx;
|
||||||
|
bool simplebus_attached;
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_CLASS(syscon_generic_driver);
|
DECLARE_CLASS(syscon_generic_driver);
|
||||||
|
@ -116,6 +116,16 @@ simplebus_probe(device_t dev)
|
|||||||
|
|
||||||
if (!ofw_bus_status_okay(dev))
|
if (!ofw_bus_status_okay(dev))
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
/*
|
||||||
|
* XXX We should attach only to pure' compatible = "simple-bus"',
|
||||||
|
* without any other compatible string.
|
||||||
|
* For now, filter only know cases:
|
||||||
|
* "syscon", "simple-bus"; is handled by fdt/syscon driver
|
||||||
|
* "simple-mfd", "simple-bus"; is handled by fdt/simple-mfd driver
|
||||||
|
*/
|
||||||
|
if (ofw_bus_is_compatible(dev, "syscon") ||
|
||||||
|
ofw_bus_is_compatible(dev, "simple-mfd"))
|
||||||
|
return (ENXIO);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FDT data puts a "simple-bus" compatible string on many things that
|
* FDT data puts a "simple-bus" compatible string on many things that
|
||||||
|
Loading…
x
Reference in New Issue
Block a user