Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm/broadcom/bcm2835/bcm2835_firmware.c
Show All 32 Lines | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <dev/fdt/simplebus.h> | |||||
#include <dev/ofw/ofw_bus.h> | #include <dev/ofw/ofw_bus.h> | ||||
#include <dev/ofw/ofw_bus_subr.h> | #include <dev/ofw/ofw_bus_subr.h> | ||||
#include <arm/broadcom/bcm2835/bcm2835_firmware.h> | #include <arm/broadcom/bcm2835/bcm2835_firmware.h> | ||||
#include <arm/broadcom/bcm2835/bcm2835_mbox.h> | #include <arm/broadcom/bcm2835/bcm2835_mbox.h> | ||||
#include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h> | #include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h> | ||||
#include <arm/broadcom/bcm2835/bcm2835_vcbus.h> | #include <arm/broadcom/bcm2835/bcm2835_vcbus.h> | ||||
struct bcm2835_firmware_softc { | struct bcm2835_firmware_softc { | ||||
device_t sc_dev; | struct simplebus_softc sc; | ||||
phandle_t sc_mbox; | phandle_t sc_mbox; | ||||
}; | }; | ||||
static struct ofw_compat_data compat_data[] = { | static struct ofw_compat_data compat_data[] = { | ||||
{"raspberrypi,bcm2835-firmware", 1}, | {"raspberrypi,bcm2835-firmware", 1}, | ||||
{NULL, 0} | {NULL, 0} | ||||
}; | }; | ||||
Show All 18 Lines | bcm2835_firmware_attach(device_t dev) | ||||
struct bcm2835_firmware_softc *sc; | struct bcm2835_firmware_softc *sc; | ||||
struct sysctl_ctx_list *ctx; | struct sysctl_ctx_list *ctx; | ||||
struct sysctl_oid *tree_node; | struct sysctl_oid *tree_node; | ||||
struct sysctl_oid_list *tree; | struct sysctl_oid_list *tree; | ||||
phandle_t node, mbox; | phandle_t node, mbox; | ||||
int rv; | int rv; | ||||
sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
sc->sc_dev = dev; | |||||
node = ofw_bus_get_node(dev); | node = ofw_bus_get_node(dev); | ||||
rv = OF_getencprop(node, "mboxes", &mbox, sizeof(mbox)); | rv = OF_getencprop(node, "mboxes", &mbox, sizeof(mbox)); | ||||
if (rv <= 0) { | if (rv <= 0) { | ||||
device_printf(dev, "can't read mboxes property\n"); | device_printf(dev, "can't read mboxes property\n"); | ||||
return (ENXIO); | return (ENXIO); | ||||
} | } | ||||
sc->sc_mbox = mbox; | sc->sc_mbox = mbox; | ||||
OF_device_register_xref(OF_xref_from_node(node), dev); | OF_device_register_xref(OF_xref_from_node(node), dev); | ||||
ctx = device_get_sysctl_ctx(sc->sc_dev); | ctx = device_get_sysctl_ctx(dev); | ||||
tree_node = device_get_sysctl_tree(sc->sc_dev); | tree_node = device_get_sysctl_tree(dev); | ||||
tree = SYSCTL_CHILDREN(tree_node); | tree = SYSCTL_CHILDREN(tree_node); | ||||
SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "revision", | SYSCTL_ADD_PROC(ctx, tree, OID_AUTO, "revision", | ||||
CTLTYPE_UINT | CTLFLAG_RD, sc, sizeof(*sc), | CTLTYPE_UINT | CTLFLAG_RD, sc, sizeof(*sc), | ||||
sysctl_bcm2835_firmware_get_revision, "IU", | sysctl_bcm2835_firmware_get_revision, "IU", | ||||
"Firmware revision"); | "Firmware revision"); | ||||
return (0); | |||||
/* The firmwaare doesn't have a ranges property */ | |||||
sc->sc.flags |= SB_FLAG_NO_RANGES; | |||||
return (simplebus_attach(dev)); | |||||
} | } | ||||
int | int | ||||
bcm2835_firmware_property(device_t dev, uint32_t prop, void *data, size_t len) | bcm2835_firmware_property(device_t dev, uint32_t prop, void *data, size_t len) | ||||
{ | { | ||||
struct { | struct { | ||||
struct bcm2835_mbox_hdr hdr; | struct bcm2835_mbox_hdr hdr; | ||||
struct bcm2835_mbox_tag_hdr tag_hdr; | struct bcm2835_mbox_tag_hdr tag_hdr; | ||||
Show All 32 Lines | |||||
static int | static int | ||||
sysctl_bcm2835_firmware_get_revision(SYSCTL_HANDLER_ARGS) | sysctl_bcm2835_firmware_get_revision(SYSCTL_HANDLER_ARGS) | ||||
{ | { | ||||
struct bcm2835_firmware_softc *sc = arg1; | struct bcm2835_firmware_softc *sc = arg1; | ||||
uint32_t rev; | uint32_t rev; | ||||
int err; | int err; | ||||
if (bcm2835_firmware_property(sc->sc_dev, | if (bcm2835_firmware_property(sc->sc.dev, | ||||
BCM2835_MBOX_TAG_FIRMWARE_REVISION, &rev, sizeof(rev)) != 0) | BCM2835_MBOX_TAG_FIRMWARE_REVISION, &rev, sizeof(rev)) != 0) | ||||
return (ENXIO); | return (ENXIO); | ||||
err = sysctl_handle_int(oidp, &rev, sizeof(rev), req); | err = sysctl_handle_int(oidp, &rev, sizeof(rev), req); | ||||
if (err || !req->newptr) /* error || read request */ | if (err || !req->newptr) /* error || read request */ | ||||
return (err); | return (err); | ||||
/* write request */ | /* write request */ | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
static device_method_t bcm2835_firmware_methods[] = { | static device_method_t bcm2835_firmware_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_probe, bcm2835_firmware_probe), | DEVMETHOD(device_probe, bcm2835_firmware_probe), | ||||
DEVMETHOD(device_attach, bcm2835_firmware_attach), | DEVMETHOD(device_attach, bcm2835_firmware_attach), | ||||
DEVMETHOD_END | DEVMETHOD_END | ||||
}; | }; | ||||
static devclass_t bcm2835_firmware_devclass; | static devclass_t bcm2835_firmware_devclass; | ||||
static driver_t bcm2835_firmware_driver = { | DEFINE_CLASS_1(bcm2835_firmware, bcm2835_firmware_driver, | ||||
"bcm2835_firmware", | bcm2835_firmware_methods, sizeof(struct bcm2835_firmware_softc), | ||||
bcm2835_firmware_methods, | simplebus_driver); | ||||
sizeof(struct bcm2835_firmware_softc), | |||||
}; | |||||
EARLY_DRIVER_MODULE(bcm2835_firmware, simplebus, bcm2835_firmware_driver, | EARLY_DRIVER_MODULE(bcm2835_firmware, simplebus, bcm2835_firmware_driver, | ||||
bcm2835_firmware_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST); | bcm2835_firmware_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LAST); | ||||
MODULE_DEPEND(bcm2835_firmware, mbox, 1, 1, 1); | MODULE_DEPEND(bcm2835_firmware, mbox, 1, 1, 1); |