Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/bhnd/bhnd.c
/*- | /*- | ||||
* Copyright (c) 2015 Landon Fuller <landon@landonf.org> | * Copyright (c) 2015-2016 Landon Fuller <landonf@FreeBSD.org> | ||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
* notice, this list of conditions and the following disclaimer, | * notice, this list of conditions and the following disclaimer, | ||||
* without modification. | * without modification. | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <machine/bus.h> | #include <machine/bus.h> | ||||
#include <sys/rman.h> | #include <sys/rman.h> | ||||
#include <machine/resource.h> | #include <machine/resource.h> | ||||
#include <dev/bhnd/cores/chipc/chipcvar.h> | #include <dev/bhnd/cores/chipc/chipcvar.h> | ||||
#include <dev/bhnd/cores/pmu/bhnd_pmu.h> | |||||
#include <dev/bhnd/cores/pmu/bhnd_pmureg.h> | |||||
#include "bhnd_chipc_if.h" | #include "bhnd_chipc_if.h" | ||||
#include "bhnd_nvram_if.h" | #include "bhnd_nvram_if.h" | ||||
#include "bhnd.h" | #include "bhnd.h" | ||||
#include "bhndvar.h" | #include "bhndvar.h" | ||||
MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures"); | MALLOC_DEFINE(M_BHND, "bhnd", "bhnd bus data structures"); | ||||
▲ Show 20 Lines • Show All 266 Lines • ▼ Show 20 Lines | |||||
* platform devices may not be attached until later bus passes, necessitating | * platform devices may not be attached until later bus passes, necessitating | ||||
* delayed initialization on our part. | * delayed initialization on our part. | ||||
*/ | */ | ||||
static int | static int | ||||
bhnd_finish_attach(struct bhnd_softc *sc) | bhnd_finish_attach(struct bhnd_softc *sc) | ||||
{ | { | ||||
struct chipc_caps *ccaps; | struct chipc_caps *ccaps; | ||||
GIANT_REQUIRED; /* newbus */ | GIANT_REQUIRED; /* for newbus */ | ||||
KASSERT(bus_current_pass >= BHND_FINISH_ATTACH_PASS, | KASSERT(bus_current_pass >= BHND_FINISH_ATTACH_PASS, | ||||
("bhnd_finish_attach() called in pass %d", bus_current_pass)); | ("bhnd_finish_attach() called in pass %d", bus_current_pass)); | ||||
KASSERT(!sc->attach_done, ("duplicate call to bhnd_finish_attach()")); | KASSERT(!sc->attach_done, ("duplicate call to bhnd_finish_attach()")); | ||||
/* Locate chipc device */ | /* Locate chipc device */ | ||||
if ((sc->chipc_dev = bhnd_find_chipc(sc)) == NULL) { | if ((sc->chipc_dev = bhnd_find_chipc(sc)) == NULL) { | ||||
device_printf(sc->dev, "error: ChipCommon device not found\n"); | device_printf(sc->dev, "error: ChipCommon device not found\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
ccaps = BHND_CHIPC_GET_CAPS(sc->chipc_dev); | ccaps = BHND_CHIPC_GET_CAPS(sc->chipc_dev); | ||||
/* Look for NVRAM device */ | /* Look for NVRAM device */ | ||||
if (ccaps->nvram_src != BHND_NVRAM_SRC_UNKNOWN) { | if (ccaps->nvram_src != BHND_NVRAM_SRC_UNKNOWN) { | ||||
if ((sc->nvram_dev = bhnd_find_nvram(sc)) == NULL) { | if ((sc->nvram_dev = bhnd_find_nvram(sc)) == NULL) { | ||||
device_printf(sc->dev, | device_printf(sc->dev, | ||||
"warning: NVRAM %s device not found\n", | "warning: NVRAM %s device not found\n", | ||||
bhnd_nvram_src_name(ccaps->nvram_src)); | bhnd_nvram_src_name(ccaps->nvram_src)); | ||||
} | } | ||||
} | } | ||||
/* Look for a PMU */ | /* Look for a PMU */ | ||||
if (ccaps->pmu) { | if (ccaps->pmu || ccaps->pwr_ctrl) { | ||||
if ((sc->pmu_dev = bhnd_find_pmu(sc)) == NULL) { | if ((sc->pmu_dev = bhnd_find_pmu(sc)) == NULL) { | ||||
device_printf(sc->dev, | device_printf(sc->dev, | ||||
"warning: PMU device not found\n"); | "attach failed: supported PMU not found\n"); | ||||
return (ENXIO); | |||||
} | } | ||||
} | } | ||||
/* Mark attach as completed */ | /* Mark attach as completed */ | ||||
sc->attach_done = true; | sc->attach_done = true; | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | found: | ||||
return (child); | return (child); | ||||
} | } | ||||
/* Locate the PMU device, if any */ | /* Locate the PMU device, if any */ | ||||
static device_t | static device_t | ||||
bhnd_find_pmu(struct bhnd_softc *sc) | bhnd_find_pmu(struct bhnd_softc *sc) | ||||
{ | { | ||||
struct chipc_caps *ccaps; | |||||
/* Make sure we're holding Giant for newbus */ | /* Make sure we're holding Giant for newbus */ | ||||
GIANT_REQUIRED; | GIANT_REQUIRED; | ||||
/* pmu_dev is initialized during attachment */ | /* pmu_dev is initialized during attachment */ | ||||
if (sc->attach_done) { | if (sc->attach_done) { | ||||
if (sc->pmu_dev == NULL) | if (sc->pmu_dev == NULL) | ||||
return (NULL); | return (NULL); | ||||
if (device_get_state(sc->pmu_dev) < DS_ATTACHING) | if (device_get_state(sc->pmu_dev) < DS_ATTACHING) | ||||
return (NULL); | return (NULL); | ||||
return (sc->pmu_dev); | return (sc->pmu_dev); | ||||
} | } | ||||
if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL) | |||||
return (NULL); | |||||
if (!ccaps->pmu) | |||||
return (NULL); | |||||
return (bhnd_find_platform_dev(sc, "bhnd_pmu")); | return (bhnd_find_platform_dev(sc, "bhnd_pmu")); | ||||
} | } | ||||
/* Locate the NVRAM device, if any */ | /* Locate the NVRAM device, if any */ | ||||
static device_t | static device_t | ||||
bhnd_find_nvram(struct bhnd_softc *sc) | bhnd_find_nvram(struct bhnd_softc *sc) | ||||
{ | { | ||||
struct chipc_caps *ccaps; | struct chipc_caps *ccaps; | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | case BHND_DEVCLASS_INVALID: | ||||
return (BHND_PROBE_DEFAULT); | return (BHND_PROBE_DEFAULT); | ||||
default: | default: | ||||
return (BHND_PROBE_DEFAULT); | return (BHND_PROBE_DEFAULT); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Default bhnd(4) bus driver implementation of BHND_BUS_ALLOC_PMU(). | |||||
*/ | |||||
int | |||||
bhnd_generic_alloc_pmu(device_t dev, device_t child) | |||||
{ | |||||
struct bhnd_softc *sc; | |||||
struct bhnd_resource *br; | |||||
struct chipc_caps *ccaps; | |||||
struct bhnd_devinfo *dinfo; | |||||
struct bhnd_core_pmu_info *pm; | |||||
struct resource_list *rl; | |||||
struct resource_list_entry *rle; | |||||
device_t pmu_dev; | |||||
bhnd_addr_t r_addr; | |||||
bhnd_size_t r_size; | |||||
bus_size_t pmu_regs; | |||||
int error; | |||||
GIANT_REQUIRED; /* for newbus */ | |||||
sc = device_get_softc(dev); | |||||
dinfo = device_get_ivars(child); | |||||
pmu_regs = BHND_CLK_CTL_ST; | |||||
if ((ccaps = bhnd_find_chipc_caps(sc)) == NULL) { | |||||
device_printf(sc->dev, "alloc_pmu failed: chipc " | |||||
"capabilities unavailable\n"); | |||||
return (ENXIO); | |||||
} | |||||
if ((pmu_dev = bhnd_find_pmu(sc)) == NULL) { | |||||
device_printf(sc->dev, | |||||
"pmu unavailable; cannot allocate request state\n"); | |||||
return (ENXIO); | |||||
} | |||||
/* already allocated? */ | |||||
if (dinfo->pmu_info != NULL) { | |||||
panic("duplicate PMU allocation for %s", | |||||
device_get_nameunit(child)); | |||||
} | |||||
/* Determine address+size of the core's PMU register block */ | |||||
error = bhnd_get_region_addr(child, BHND_PORT_DEVICE, 0, 0, &r_addr, | |||||
&r_size); | |||||
if (error) { | |||||
device_printf(sc->dev, "error fetching register block info for " | |||||
"%s: %d\n", device_get_nameunit(child), error); | |||||
return (error); | |||||
} | |||||
if (r_size < (pmu_regs + sizeof(uint32_t))) { | |||||
device_printf(sc->dev, "pmu offset %#jx would overrun %s " | |||||
"register block\n", (uintmax_t)pmu_regs, | |||||
device_get_nameunit(child)); | |||||
return (ENODEV); | |||||
} | |||||
/* Locate actual resource containing the core's register block */ | |||||
if ((rl = BUS_GET_RESOURCE_LIST(dev, child)) == NULL) { | |||||
device_printf(dev, "NULL resource list returned for %s\n", | |||||
device_get_nameunit(child)); | |||||
return (ENXIO); | |||||
} | |||||
if ((rle = resource_list_find(rl, SYS_RES_MEMORY, 0)) == NULL) { | |||||
device_printf(dev, "cannot locate core register resource " | |||||
"for %s\n", device_get_nameunit(child)); | |||||
return (ENXIO); | |||||
} | |||||
if (rle->res == NULL) { | |||||
device_printf(dev, "core register resource unallocated for " | |||||
"%s\n", device_get_nameunit(child)); | |||||
return (ENXIO); | |||||
} | |||||
if (r_addr+pmu_regs < rman_get_start(rle->res) || | |||||
r_addr+pmu_regs >= rman_get_end(rle->res)) | |||||
{ | |||||
device_printf(dev, "core register resource does not map PMU " | |||||
"registers at %#jx\n for %s\n", r_addr+pmu_regs, | |||||
device_get_nameunit(child)); | |||||
return (ENXIO); | |||||
} | |||||
/* Adjust PMU register offset relative to the actual start address | |||||
* of the core's register block allocation. | |||||
* | |||||
* XXX: The saved offset will be invalid if bus_adjust_resource is | |||||
* used to modify the resource's start address. | |||||
*/ | |||||
if (rman_get_start(rle->res) > r_addr) | |||||
pmu_regs -= rman_get_start(rle->res) - r_addr; | |||||
else | |||||
pmu_regs -= r_addr - rman_get_start(rle->res); | |||||
/* Allocate and initialize PMU info */ | |||||
br = malloc(sizeof(struct bhnd_resource), M_BHND, M_NOWAIT); | |||||
if (br == NULL) | |||||
return (ENOMEM); | |||||
br->res = rle->res; | |||||
br->direct = ((rman_get_flags(rle->res) & RF_ACTIVE) != 0); | |||||
pm = malloc(sizeof(*dinfo->pmu_info), M_BHND, M_NOWAIT); | |||||
if (pm == NULL) { | |||||
free(br, M_BHND); | |||||
return (ENOMEM); | |||||
} | |||||
pm->pm_dev = child; | |||||
pm->pm_pmu = pmu_dev; | |||||
pm->pm_res = br; | |||||
pm->pm_regs = pmu_regs; | |||||
dinfo->pmu_info = pm; | |||||
return (0); | |||||
} | |||||
/** | |||||
* Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_PMU(). | |||||
*/ | |||||
int | |||||
bhnd_generic_release_pmu(device_t dev, device_t child) | |||||
{ | |||||
struct bhnd_softc *sc; | |||||
struct bhnd_devinfo *dinfo; | |||||
device_t pmu; | |||||
int error; | |||||
GIANT_REQUIRED; /* for newbus */ | |||||
sc = device_get_softc(dev); | |||||
dinfo = device_get_ivars(child); | |||||
if ((pmu = bhnd_find_pmu(sc)) == NULL) { | |||||
device_printf(sc->dev, | |||||
"pmu unavailable; cannot release request state\n"); | |||||
return (ENXIO); | |||||
} | |||||
/* dispatch release request */ | |||||
if (dinfo->pmu_info == NULL) | |||||
panic("pmu over-release for %s", device_get_nameunit(child)); | |||||
if ((error = BHND_PMU_CORE_RELEASE(pmu, dinfo->pmu_info))) | |||||
return (error); | |||||
/* free PMU info */ | |||||
free(dinfo->pmu_info->pm_res, M_BHND); | |||||
free(dinfo->pmu_info, M_BHND); | |||||
dinfo->pmu_info = NULL; | |||||
return (0); | |||||
} | |||||
/** | |||||
* Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_CLOCK(). | |||||
*/ | |||||
int | |||||
bhnd_generic_request_clock(device_t dev, device_t child, bhnd_clock clock) | |||||
{ | |||||
struct bhnd_softc *sc; | |||||
struct bhnd_devinfo *dinfo; | |||||
struct bhnd_core_pmu_info *pm; | |||||
sc = device_get_softc(dev); | |||||
dinfo = device_get_ivars(child); | |||||
if ((pm = dinfo->pmu_info) == NULL) | |||||
panic("no active PMU request state"); | |||||
/* dispatch request to PMU */ | |||||
return (BHND_PMU_CORE_REQ_CLOCK(pm->pm_pmu, pm, clock)); | |||||
} | |||||
/** | |||||
* Default bhnd(4) bus driver implementation of BHND_BUS_ENABLE_CLOCKS(). | |||||
*/ | |||||
int | |||||
bhnd_generic_enable_clocks(device_t dev, device_t child, uint32_t clocks) | |||||
{ | |||||
struct bhnd_softc *sc; | |||||
struct bhnd_devinfo *dinfo; | |||||
struct bhnd_core_pmu_info *pm; | |||||
sc = device_get_softc(dev); | |||||
dinfo = device_get_ivars(child); | |||||
if ((pm = dinfo->pmu_info) == NULL) | |||||
panic("no active PMU request state"); | |||||
/* dispatch request to PMU */ | |||||
return (BHND_PMU_CORE_EN_CLOCKS(pm->pm_pmu, pm, clocks)); | |||||
} | |||||
/** | |||||
* Default bhnd(4) bus driver implementation of BHND_BUS_REQUEST_EXT_RSRC(). | |||||
*/ | |||||
int | |||||
bhnd_generic_request_ext_rsrc(device_t dev, device_t child, u_int rsrc) | |||||
{ | |||||
struct bhnd_softc *sc; | |||||
struct bhnd_devinfo *dinfo; | |||||
struct bhnd_core_pmu_info *pm; | |||||
sc = device_get_softc(dev); | |||||
dinfo = device_get_ivars(child); | |||||
if ((pm = dinfo->pmu_info) == NULL) | |||||
panic("no active PMU request state"); | |||||
/* dispatch request to PMU */ | |||||
return (BHND_PMU_CORE_REQ_EXT_RSRC(pm->pm_pmu, pm, rsrc)); | |||||
} | |||||
/** | |||||
* Default bhnd(4) bus driver implementation of BHND_BUS_RELEASE_EXT_RSRC(). | |||||
*/ | |||||
int | |||||
bhnd_generic_release_ext_rsrc(device_t dev, device_t child, u_int rsrc) | |||||
{ | |||||
struct bhnd_softc *sc; | |||||
struct bhnd_devinfo *dinfo; | |||||
struct bhnd_core_pmu_info *pm; | |||||
sc = device_get_softc(dev); | |||||
dinfo = device_get_ivars(child); | |||||
if ((pm = dinfo->pmu_info) == NULL) | |||||
panic("no active PMU request state"); | |||||
/* dispatch request to PMU */ | |||||
return (BHND_PMU_CORE_RELEASE_EXT_RSRC(pm->pm_pmu, pm, rsrc)); | |||||
} | |||||
/** | |||||
* Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID(). | * Default bhnd(4) bus driver implementation of BHND_BUS_IS_REGION_VALID(). | ||||
* | * | ||||
* This implementation assumes that port and region numbers are 0-indexed and | * This implementation assumes that port and region numbers are 0-indexed and | ||||
* are allocated non-sparsely, using BHND_BUS_GET_PORT_COUNT() and | * are allocated non-sparsely, using BHND_BUS_GET_PORT_COUNT() and | ||||
* BHND_BUS_GET_REGION_COUNT() to determine if @p port and @p region fall | * BHND_BUS_GET_REGION_COUNT() to determine if @p port and @p region fall | ||||
* within the defined range. | * within the defined range. | ||||
*/ | */ | ||||
static bool | static bool | ||||
▲ Show 20 Lines • Show All 173 Lines • ▼ Show 20 Lines | bhnd_generic_add_child(device_t dev, u_int order, const char *name, int unit) | ||||
if ((dinfo = BHND_BUS_ALLOC_DEVINFO(dev)) == NULL) { | if ((dinfo = BHND_BUS_ALLOC_DEVINFO(dev)) == NULL) { | ||||
device_delete_child(dev, child); | device_delete_child(dev, child); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
device_set_ivars(child, dinfo); | device_set_ivars(child, dinfo); | ||||
/* Inform concrete bus driver. */ | |||||
BHND_BUS_CHILD_ADDED(dev, child); | |||||
return (child); | return (child); | ||||
} | } | ||||
/** | /** | ||||
* Default bhnd(4) bus driver implementation of BHND_BUS_CHILD_ADDED(). | |||||
* | |||||
* This implementation manages internal bhnd(4) state, and must be called | |||||
* by subclassing drivers. | |||||
*/ | |||||
void | |||||
bhnd_generic_child_added(device_t dev, device_t child) | |||||
{ | |||||
} | |||||
/** | |||||
* Default bhnd(4) bus driver implementation of BUS_CHILD_DELETED(). | * Default bhnd(4) bus driver implementation of BUS_CHILD_DELETED(). | ||||
* | * | ||||
* This implementation manages internal bhnd(4) state, and must be called | * This implementation manages internal bhnd(4) state, and must be called | ||||
* by subclassing drivers. | * by subclassing drivers. | ||||
*/ | */ | ||||
void | void | ||||
bhnd_generic_child_deleted(device_t dev, device_t child) | bhnd_generic_child_deleted(device_t dev, device_t child) | ||||
{ | { | ||||
struct bhnd_softc *sc; | struct bhnd_softc *sc; | ||||
struct bhnd_devinfo *dinfo; | struct bhnd_devinfo *dinfo; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
/* Free device info */ | /* Free device info */ | ||||
if ((dinfo = device_get_ivars(child)) != NULL) | if ((dinfo = device_get_ivars(child)) != NULL) { | ||||
if (dinfo->pmu_info != NULL) { | |||||
/* Releasing PMU requests automatically would be nice, | |||||
* but we can't reference per-core PMU register | |||||
* resource after driver detach */ | |||||
panic("%s leaked device pmu state\n", | |||||
device_get_nameunit(child)); | |||||
} | |||||
BHND_BUS_FREE_DEVINFO(dev, dinfo); | BHND_BUS_FREE_DEVINFO(dev, dinfo); | ||||
} | |||||
/* Clean up platform device references */ | /* Clean up platform device references */ | ||||
if (sc->chipc_dev == child) { | if (sc->chipc_dev == child) { | ||||
sc->chipc_dev = NULL; | sc->chipc_dev = NULL; | ||||
} else if (sc->nvram_dev == child) { | } else if (sc->nvram_dev == child) { | ||||
sc->nvram_dev = NULL; | sc->nvram_dev = NULL; | ||||
} else if (sc->pmu_dev == child) { | } else if (sc->pmu_dev == child) { | ||||
sc->pmu_dev = NULL; | sc->pmu_dev = NULL; | ||||
▲ Show 20 Lines • Show All 144 Lines • ▼ Show 20 Lines | static device_method_t bhnd_methods[] = { | ||||
DEVMETHOD(bus_config_intr, bus_generic_config_intr), | DEVMETHOD(bus_config_intr, bus_generic_config_intr), | ||||
DEVMETHOD(bus_bind_intr, bus_generic_bind_intr), | DEVMETHOD(bus_bind_intr, bus_generic_bind_intr), | ||||
DEVMETHOD(bus_describe_intr, bus_generic_describe_intr), | DEVMETHOD(bus_describe_intr, bus_generic_describe_intr), | ||||
DEVMETHOD(bus_get_dma_tag, bus_generic_get_dma_tag), | DEVMETHOD(bus_get_dma_tag, bus_generic_get_dma_tag), | ||||
/* BHND interface */ | /* BHND interface */ | ||||
DEVMETHOD(bhnd_bus_get_chipid, bhnd_bus_generic_get_chipid), | DEVMETHOD(bhnd_bus_get_chipid, bhnd_bus_generic_get_chipid), | ||||
DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled), | |||||
DEVMETHOD(bhnd_bus_read_board_info, bhnd_bus_generic_read_board_info), | |||||
DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order), | DEVMETHOD(bhnd_bus_get_probe_order, bhnd_generic_get_probe_order), | ||||
DEVMETHOD(bhnd_bus_alloc_pmu, bhnd_generic_alloc_pmu), | |||||
DEVMETHOD(bhnd_bus_release_pmu, bhnd_generic_release_pmu), | |||||
DEVMETHOD(bhnd_bus_request_clock, bhnd_generic_request_clock), | |||||
DEVMETHOD(bhnd_bus_enable_clocks, bhnd_generic_enable_clocks), | |||||
DEVMETHOD(bhnd_bus_request_ext_rsrc, bhnd_generic_request_ext_rsrc), | |||||
DEVMETHOD(bhnd_bus_release_ext_rsrc, bhnd_generic_release_ext_rsrc), | |||||
DEVMETHOD(bhnd_bus_child_added, bhnd_generic_child_added), | |||||
DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid), | DEVMETHOD(bhnd_bus_is_region_valid, bhnd_generic_is_region_valid), | ||||
DEVMETHOD(bhnd_bus_is_hw_disabled, bhnd_bus_generic_is_hw_disabled), | |||||
DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_generic_get_nvram_var), | DEVMETHOD(bhnd_bus_get_nvram_var, bhnd_generic_get_nvram_var), | ||||
/* BHND interface (bus I/O) */ | /* BHND interface (bus I/O) */ | ||||
DEVMETHOD(bhnd_bus_read_1, bhnd_read_1), | DEVMETHOD(bhnd_bus_read_1, bhnd_read_1), | ||||
DEVMETHOD(bhnd_bus_read_2, bhnd_read_2), | DEVMETHOD(bhnd_bus_read_2, bhnd_read_2), | ||||
DEVMETHOD(bhnd_bus_read_4, bhnd_read_4), | DEVMETHOD(bhnd_bus_read_4, bhnd_read_4), | ||||
DEVMETHOD(bhnd_bus_write_1, bhnd_write_1), | DEVMETHOD(bhnd_bus_write_1, bhnd_write_1), | ||||
DEVMETHOD(bhnd_bus_write_2, bhnd_write_2), | DEVMETHOD(bhnd_bus_write_2, bhnd_write_2), | ||||
▲ Show 20 Lines • Show All 56 Lines • Show Last 20 Lines |