Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/bhnd/cores/chipc/chipc.c
Show First 20 Lines • Show All 104 Lines • ▼ Show 20 Lines | static const struct chipc_hint { | ||||
int type; | int type; | ||||
int rid; | int rid; | ||||
rman_res_t base; /* relative to parent resource */ | rman_res_t base; /* relative to parent resource */ | ||||
rman_res_t size; | rman_res_t size; | ||||
u_int port; /* ignored if SYS_RES_IRQ */ | u_int port; /* ignored if SYS_RES_IRQ */ | ||||
u_int region; | u_int region; | ||||
} chipc_hints[] = { | } chipc_hints[] = { | ||||
// FIXME: cfg/spi port1.1 mapping on siba(4) SoCs | // FIXME: cfg/spi port1.1 mapping on siba(4) SoCs | ||||
// FIXME: IRQ shouldn't be hardcoded | |||||
/* device unit type rid base size port,region */ | /* device unit type rid base size port,region */ | ||||
{ "bhnd_nvram", 0, SYS_RES_MEMORY, 0, CHIPC_SPROM_OTP, CHIPC_SPROM_OTP_SIZE, 0,0 }, | { "bhnd_nvram", 0, SYS_RES_MEMORY, 0, CHIPC_SPROM_OTP, CHIPC_SPROM_OTP_SIZE, 0,0 }, | ||||
{ "uart", 0, SYS_RES_MEMORY, 0, CHIPC_UART0_BASE, CHIPC_UART_SIZE, 0,0 }, | { "uart", 0, SYS_RES_MEMORY, 0, CHIPC_UART0_BASE, CHIPC_UART_SIZE, 0,0 }, | ||||
{ "uart", 0, SYS_RES_IRQ, 0, 0, RM_MAX_END }, | { "uart", 0, SYS_RES_IRQ, 0, 2, 1 }, | ||||
{ "uart", 1, SYS_RES_MEMORY, 0, CHIPC_UART1_BASE, CHIPC_UART_SIZE, 0,0 }, | { "uart", 1, SYS_RES_MEMORY, 0, CHIPC_UART1_BASE, CHIPC_UART_SIZE, 0,0 }, | ||||
{ "uart", 1, SYS_RES_IRQ, 0, 0, RM_MAX_END }, | { "uart", 1, SYS_RES_IRQ, 0, 2, 1 }, | ||||
{ "spi", 0, SYS_RES_MEMORY, 0, 0, RM_MAX_END, 1,1 }, | { "spi", 0, SYS_RES_MEMORY, 0, 0, RM_MAX_END, 1,1 }, | ||||
{ "spi", 0, SYS_RES_MEMORY, 1, CHIPC_SFLASH_BASE, CHIPC_SFLASH_SIZE, 0,0 }, | { "spi", 0, SYS_RES_MEMORY, 1, CHIPC_SFLASH_BASE, CHIPC_SFLASH_SIZE, 0,0 }, | ||||
{ "cfi", 0, SYS_RES_MEMORY, 0, 0, RM_MAX_END, 1,1}, | { "cfi", 0, SYS_RES_MEMORY, 0, 0, RM_MAX_END, 1,1}, | ||||
{ "cfi", 0, SYS_RES_MEMORY, 1, CHIPC_SFLASH_BASE, CHIPC_SFLASH_SIZE, 0,0 }, | { "cfi", 0, SYS_RES_MEMORY, 1, CHIPC_SFLASH_BASE, CHIPC_SFLASH_SIZE, 0,0 }, | ||||
{ NULL } | { NULL } | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 348 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static device_t | static device_t | ||||
chipc_add_child(device_t dev, u_int order, const char *name, int unit) | chipc_add_child(device_t dev, u_int order, const char *name, int unit) | ||||
{ | { | ||||
struct chipc_devinfo *dinfo; | struct chipc_devinfo *dinfo; | ||||
const struct chipc_hint *hint; | const struct chipc_hint *hint; | ||||
device_t child; | device_t child; | ||||
devclass_t child_dc; | |||||
int error; | int error; | ||||
int busrel_unit; | |||||
child = device_add_child_ordered(dev, order, name, unit); | child = device_add_child_ordered(dev, order, name, unit); | ||||
if (child == NULL) | if (child == NULL) | ||||
return (NULL); | return (NULL); | ||||
/* system-wide device unit */ | |||||
unit = device_get_unit(child); | |||||
child_dc = device_get_devclass(child); | |||||
busrel_unit = 0; | |||||
for (int i = 0; i < unit; i++) { | |||||
device_t tmp; | |||||
tmp = devclass_get_device(child_dc, i); | |||||
if (tmp != NULL && (device_get_parent(tmp) == dev)) | |||||
busrel_unit++; | |||||
} | |||||
/* bus-wide device unit (override unit for further hint matching) */ | |||||
unit = busrel_unit; | |||||
dinfo = malloc(sizeof(struct chipc_devinfo), M_BHND, M_NOWAIT); | dinfo = malloc(sizeof(struct chipc_devinfo), M_BHND, M_NOWAIT); | ||||
if (dinfo == NULL) { | if (dinfo == NULL) { | ||||
device_delete_child(dev, child); | device_delete_child(dev, child); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
resource_list_init(&dinfo->resources); | resource_list_init(&dinfo->resources); | ||||
device_set_ivars(child, dinfo); | device_set_ivars(child, dinfo); | ||||
/* Hint matching requires a device name */ | /* Hint matching requires a device name */ | ||||
if (name == NULL) | if (name == NULL) | ||||
return (child); | return (child); | ||||
/* Use hint table to set child resources */ | /* Use hint table to set child resources */ | ||||
for (hint = chipc_hints; hint->name != NULL; hint++) { | for (hint = chipc_hints; hint->name != NULL; hint++) { | ||||
bhnd_addr_t region_addr; | bhnd_addr_t region_addr; | ||||
bhnd_size_t region_size; | bhnd_size_t region_size; | ||||
/* Check device name */ | |||||
if (strcmp(hint->name, name) != 0) | if (strcmp(hint->name, name) != 0) | ||||
continue; | continue; | ||||
/* Check device unit */ | |||||
if (hint->unit >= 0 && unit != hint->unit) | |||||
continue; | |||||
switch (hint->type) { | switch (hint->type) { | ||||
case SYS_RES_IRQ: | case SYS_RES_IRQ: | ||||
/* Add child resource */ | /* Add child resource */ | ||||
error = bus_set_resource(child, hint->type, hint->rid, | error = bus_set_resource(child, hint->type, hint->rid, | ||||
hint->base, hint->size); | hint->base, hint->size); | ||||
if (error) { | if (error) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"bus_set_resource() failed for %s: %d\n", | "bus_set_resource() failed for %s: %d\n", | ||||
Show All 12 Lines | case SYS_RES_MEMORY: | ||||
"lookup of %s%u.%u failed: %d\n", | "lookup of %s%u.%u failed: %d\n", | ||||
bhnd_port_type_name(BHND_PORT_DEVICE), | bhnd_port_type_name(BHND_PORT_DEVICE), | ||||
hint->port, hint->region, error); | hint->port, hint->region, error); | ||||
goto failed; | goto failed; | ||||
} | } | ||||
/* Verify requested range is mappable */ | /* Verify requested range is mappable */ | ||||
if (hint->base > region_size || | if (hint->base > region_size || | ||||
hint->size > region_size || | (hint->size != RM_MAX_END && | ||||
region_size - hint->base < hint->size ) | (hint->size > region_size || | ||||
region_size - hint->base < hint->size ))) | |||||
{ | { | ||||
device_printf(dev, | device_printf(dev, | ||||
"%s%u.%u region cannot map requested range " | "%s%u.%u region cannot map requested range " | ||||
"%#jx+%#jx\n", | "%#jx+%#jx\n", | ||||
bhnd_port_type_name(BHND_PORT_DEVICE), | bhnd_port_type_name(BHND_PORT_DEVICE), | ||||
hint->port, hint->region, hint->base, | hint->port, hint->region, hint->base, | ||||
hint->size); | hint->size); | ||||
} | } | ||||
/* Add child resource */ | /* | ||||
error = bus_set_resource(child, hint->type, | * Add child resource. If hint doesn't define the end | ||||
hint->rid, region_addr + hint->base, hint->size); | * of resource window (RX_MAX_END), use end of region. | ||||
*/ | |||||
error = bus_set_resource(child, | |||||
hint->type, | |||||
hint->rid, region_addr + hint->base, | |||||
(hint->size == RM_MAX_END) ? | |||||
region_size - hint->base : | |||||
hint->size); | |||||
if (error) { | if (error) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"bus_set_resource() failed for %s: %d\n", | "bus_set_resource() failed for %s: %d\n", | ||||
device_get_nameunit(child), error); | device_get_nameunit(child), error); | ||||
goto failed; | goto failed; | ||||
} | } | ||||
break; | break; | ||||
default: | default: | ||||
▲ Show 20 Lines • Show All 189 Lines • ▼ Show 20 Lines | if (rle == NULL) { | ||||
"default resource %#x type %d for child %s " | "default resource %#x type %d for child %s " | ||||
"not found\n", *rid, type, | "not found\n", *rid, type, | ||||
device_get_nameunit(child)); | device_get_nameunit(child)); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
if (rle->res != NULL) { | if (rle->res != NULL) { | ||||
device_printf(dev, | device_printf(dev, | ||||
"resource entry %#x type %d for child %s is busy\n", | "resource entry %#x type %d for child %s is busy " | ||||
*rid, type, device_get_nameunit(child)); | "[%d]\n", | ||||
*rid, type, device_get_nameunit(child), | |||||
rman_get_flags(rle->res)); | |||||
return (NULL); | return (NULL); | ||||
} | } | ||||
start = rle->start; | start = rle->start; | ||||
end = rle->end; | end = rle->end; | ||||
count = ulmax(count, rle->count); | count = ulmax(count, rle->count); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | chipc_alloc_resource(device_t dev, device_t child, int type, | ||||
return (rv); | return (rv); | ||||
} | } | ||||
static int | static int | ||||
chipc_release_resource(device_t dev, device_t child, int type, int rid, | chipc_release_resource(device_t dev, device_t child, int type, int rid, | ||||
struct resource *r) | struct resource *r) | ||||
{ | { | ||||
struct chipc_softc *sc; | struct chipc_softc *sc; | ||||
struct chipc_region *cr; | struct chipc_region *cr; | ||||
struct rman *rm; | struct rman *rm; | ||||
struct resource_list_entry *rle; | |||||
int error; | int error; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
/* Handled by parent bus? */ | /* Handled by parent bus? */ | ||||
rm = chipc_get_rman(sc, type); | rm = chipc_get_rman(sc, type); | ||||
if (rm == NULL || !rman_is_region_manager(r, rm)) { | if (rm == NULL || !rman_is_region_manager(r, rm)) { | ||||
return (bus_generic_rl_release_resource(dev, child, type, rid, | return (bus_generic_rl_release_resource(dev, child, type, rid, | ||||
r)); | r)); | ||||
Show All 12 Lines | chipc_release_resource(device_t dev, device_t child, int type, int rid, | ||||
} | } | ||||
if ((error = rman_release_resource(r))) | if ((error = rman_release_resource(r))) | ||||
return (error); | return (error); | ||||
/* Drop allocation reference */ | /* Drop allocation reference */ | ||||
chipc_release_region(sc, cr, RF_ALLOCATED); | chipc_release_region(sc, cr, RF_ALLOCATED); | ||||
/* Clear reference from the resource list entry if exists */ | |||||
rle = resource_list_find(BUS_GET_RESOURCE_LIST(dev, child), type, rid); | |||||
if (rle != NULL) | |||||
rle->res = NULL; | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
chipc_adjust_resource(device_t dev, device_t child, int type, | chipc_adjust_resource(device_t dev, device_t child, int type, | ||||
struct resource *r, rman_res_t start, rman_res_t end) | struct resource *r, rman_res_t start, rman_res_t end) | ||||
{ | { | ||||
struct chipc_softc *sc; | struct chipc_softc *sc; | ||||
▲ Show 20 Lines • Show All 369 Lines • ▼ Show 20 Lines | chipc_write_chipctrl(device_t dev, uint32_t value, uint32_t mask) | ||||
cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL); | cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL); | ||||
cctrl = (cctrl & ~mask) | (value | mask); | cctrl = (cctrl & ~mask) | (value | mask); | ||||
bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl); | bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl); | ||||
CHIPC_UNLOCK(sc); | CHIPC_UNLOCK(sc); | ||||
} | } | ||||
static struct chipc_caps * | |||||
chipc_get_caps(device_t dev) | |||||
{ | |||||
struct chipc_softc *sc; | |||||
sc = device_get_softc(dev); | |||||
return (&sc->caps); | |||||
} | |||||
static device_method_t chipc_methods[] = { | static device_method_t chipc_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_probe, chipc_probe), | DEVMETHOD(device_probe, chipc_probe), | ||||
DEVMETHOD(device_attach, chipc_attach), | DEVMETHOD(device_attach, chipc_attach), | ||||
DEVMETHOD(device_detach, chipc_detach), | DEVMETHOD(device_detach, chipc_detach), | ||||
DEVMETHOD(device_suspend, chipc_suspend), | DEVMETHOD(device_suspend, chipc_suspend), | ||||
DEVMETHOD(device_resume, chipc_resume), | DEVMETHOD(device_resume, chipc_resume), | ||||
Show All 25 Lines | static device_method_t chipc_methods[] = { | ||||
/* BHND bus inteface */ | /* BHND bus inteface */ | ||||
DEVMETHOD(bhnd_bus_activate_resource, chipc_activate_bhnd_resource), | DEVMETHOD(bhnd_bus_activate_resource, chipc_activate_bhnd_resource), | ||||
/* ChipCommon interface */ | /* ChipCommon interface */ | ||||
DEVMETHOD(bhnd_chipc_nvram_src, chipc_nvram_src), | DEVMETHOD(bhnd_chipc_nvram_src, chipc_nvram_src), | ||||
DEVMETHOD(bhnd_chipc_write_chipctrl, chipc_write_chipctrl), | DEVMETHOD(bhnd_chipc_write_chipctrl, chipc_write_chipctrl), | ||||
DEVMETHOD(bhnd_chipc_enable_sprom, chipc_enable_sprom_pins), | DEVMETHOD(bhnd_chipc_enable_sprom, chipc_enable_sprom_pins), | ||||
DEVMETHOD(bhnd_chipc_disable_sprom, chipc_disable_sprom_pins), | DEVMETHOD(bhnd_chipc_disable_sprom, chipc_disable_sprom_pins), | ||||
DEVMETHOD(bhnd_chipc_get_caps, chipc_get_caps), | |||||
DEVMETHOD_END | DEVMETHOD_END | ||||
}; | }; | ||||
DEFINE_CLASS_0(bhnd_chipc, chipc_driver, chipc_methods, sizeof(struct chipc_softc)); | DEFINE_CLASS_0(bhnd_chipc, chipc_driver, chipc_methods, sizeof(struct chipc_softc)); | ||||
DRIVER_MODULE(bhnd_chipc, bhnd, chipc_driver, bhnd_chipc_devclass, 0, 0); | DRIVER_MODULE(bhnd_chipc, bhnd, chipc_driver, bhnd_chipc_devclass, 0, 0); | ||||
MODULE_DEPEND(bhnd_chipc, bhnd, 1, 1, 1); | MODULE_DEPEND(bhnd_chipc, bhnd, 1, 1, 1); | ||||
MODULE_VERSION(bhnd_chipc, 1); | MODULE_VERSION(bhnd_chipc, 1); |