Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/gpio/gpiobus.c
Show All 33 Lines | |||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/gpio.h> | #include <sys/gpio.h> | ||||
#ifdef INTRNG | #ifdef INTRNG | ||||
#include <sys/intr.h> | #include <sys/intr.h> | ||||
#endif | #endif | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/sbuf.h> | |||||
#include <dev/gpio/gpiobusvar.h> | #include <dev/gpio/gpiobusvar.h> | ||||
#include "gpiobus_if.h" | #include "gpiobus_if.h" | ||||
#undef GPIOBUS_DEBUG | #undef GPIOBUS_DEBUG | ||||
#ifdef GPIOBUS_DEBUG | #ifdef GPIOBUS_DEBUG | ||||
#define dprintf printf | #define dprintf printf | ||||
#else | #else | ||||
#define dprintf(x, arg...) | #define dprintf(x, arg...) | ||||
#endif | #endif | ||||
static void gpiobus_print_pins(struct gpiobus_ivar *, char *, size_t); | static void gpiobus_print_pins(struct gpiobus_ivar *, struct sbuf *); | ||||
static int gpiobus_parse_pins(struct gpiobus_softc *, device_t, int); | static int gpiobus_parse_pins(struct gpiobus_softc *, device_t, int); | ||||
static int gpiobus_probe(device_t); | static int gpiobus_probe(device_t); | ||||
static int gpiobus_attach(device_t); | static int gpiobus_attach(device_t); | ||||
static int gpiobus_detach(device_t); | static int gpiobus_detach(device_t); | ||||
static int gpiobus_suspend(device_t); | static int gpiobus_suspend(device_t); | ||||
static int gpiobus_resume(device_t); | static int gpiobus_resume(device_t); | ||||
static void gpiobus_probe_nomatch(device_t, device_t); | static void gpiobus_probe_nomatch(device_t, device_t); | ||||
static int gpiobus_print_child(device_t, device_t); | static int gpiobus_print_child(device_t, device_t); | ||||
static int gpiobus_child_location_str(device_t, device_t, char *, size_t); | static int gpiobus_child_location(device_t, device_t, struct sbuf *); | ||||
static int gpiobus_child_pnpinfo_str(device_t, device_t, char *, size_t); | |||||
static device_t gpiobus_add_child(device_t, u_int, const char *, int); | static device_t gpiobus_add_child(device_t, u_int, const char *, int); | ||||
static void gpiobus_hinted_child(device_t, const char *, int); | static void gpiobus_hinted_child(device_t, const char *, int); | ||||
/* | /* | ||||
* GPIOBUS interface | * GPIOBUS interface | ||||
*/ | */ | ||||
static int gpiobus_acquire_bus(device_t, device_t, int); | static int gpiobus_acquire_bus(device_t, device_t, int); | ||||
static void gpiobus_release_bus(device_t, device_t); | static void gpiobus_release_bus(device_t, device_t); | ||||
▲ Show 20 Lines • Show All 187 Lines • ▼ Show 20 Lines | gpio_pin_setflags(gpio_pin_t pin, uint32_t flags) | ||||
KASSERT(pin != NULL, ("GPIO pin is NULL.")); | KASSERT(pin != NULL, ("GPIO pin is NULL.")); | ||||
KASSERT(pin->dev != NULL, ("GPIO pin device is NULL.")); | KASSERT(pin->dev != NULL, ("GPIO pin device is NULL.")); | ||||
rv = GPIO_PIN_SETFLAGS(pin->dev, pin->pin, flags); | rv = GPIO_PIN_SETFLAGS(pin->dev, pin->pin, flags); | ||||
return (rv); | return (rv); | ||||
} | } | ||||
static void | static void | ||||
gpiobus_print_pins(struct gpiobus_ivar *devi, char *buf, size_t buflen) | gpiobus_print_pins(struct gpiobus_ivar *devi, struct sbuf *sb) | ||||
{ | { | ||||
char tmp[128]; | |||||
int i, range_start, range_stop, need_coma; | int i, range_start, range_stop, need_coma; | ||||
if (devi->npins == 0) | if (devi->npins == 0) | ||||
return; | return; | ||||
need_coma = 0; | need_coma = 0; | ||||
range_start = range_stop = devi->pins[0]; | range_start = range_stop = devi->pins[0]; | ||||
for (i = 1; i < devi->npins; i++) { | for (i = 1; i < devi->npins; i++) { | ||||
if (devi->pins[i] != (range_stop + 1)) { | if (devi->pins[i] != (range_stop + 1)) { | ||||
if (need_coma) | if (need_coma) | ||||
strlcat(buf, ",", buflen); | sbuf_cat(sb, ","); | ||||
memset(tmp, 0, sizeof(tmp)); | |||||
if (range_start != range_stop) | if (range_start != range_stop) | ||||
snprintf(tmp, sizeof(tmp) - 1, "%d-%d", | sbuf_printf(sb, "%d-%d", range_start, range_stop); | ||||
range_start, range_stop); | |||||
else | else | ||||
snprintf(tmp, sizeof(tmp) - 1, "%d", | sbuf_printf(sb, "%d", range_start); | ||||
range_start); | |||||
strlcat(buf, tmp, buflen); | |||||
range_start = range_stop = devi->pins[i]; | range_start = range_stop = devi->pins[i]; | ||||
need_coma = 1; | need_coma = 1; | ||||
} | } | ||||
else | else | ||||
range_stop++; | range_stop++; | ||||
} | } | ||||
if (need_coma) | if (need_coma) | ||||
strlcat(buf, ",", buflen); | sbuf_cat(sb, ","); | ||||
memset(tmp, 0, sizeof(tmp)); | |||||
if (range_start != range_stop) | if (range_start != range_stop) | ||||
snprintf(tmp, sizeof(tmp) - 1, "%d-%d", | sbuf_printf(sb, "%d-%d", range_start, range_stop); | ||||
range_start, range_stop); | |||||
else | else | ||||
snprintf(tmp, sizeof(tmp) - 1, "%d", | sbuf_printf(sb, "%d", range_start); | ||||
range_start); | |||||
strlcat(buf, tmp, buflen); | |||||
} | } | ||||
device_t | device_t | ||||
gpiobus_attach_bus(device_t dev) | gpiobus_attach_bus(device_t dev) | ||||
{ | { | ||||
device_t busdev; | device_t busdev; | ||||
busdev = device_add_child(dev, "gpiobus", -1); | busdev = device_add_child(dev, "gpiobus", -1); | ||||
▲ Show 20 Lines • Show All 322 Lines • ▼ Show 20 Lines | gpiobus_resume(device_t dev) | ||||
return (bus_generic_resume(dev)); | return (bus_generic_resume(dev)); | ||||
} | } | ||||
static void | static void | ||||
gpiobus_probe_nomatch(device_t dev, device_t child) | gpiobus_probe_nomatch(device_t dev, device_t child) | ||||
{ | { | ||||
char pins[128]; | char pins[128]; | ||||
struct sbuf sb; | |||||
struct gpiobus_ivar *devi; | struct gpiobus_ivar *devi; | ||||
devi = GPIOBUS_IVAR(child); | devi = GPIOBUS_IVAR(child); | ||||
memset(pins, 0, sizeof(pins)); | sbuf_new(&sb, pins, sizeof(pins), SBUF_FIXEDLEN); | ||||
gpiobus_print_pins(devi, pins, sizeof(pins)); | gpiobus_print_pins(devi, &sb); | ||||
if (devi->npins > 1) | sbuf_finish(&sb); | ||||
device_printf(dev, "<unknown device> at pins %s", pins); | device_printf(dev, "<unknown device> at pin%s %s", | ||||
else | devi->npins > 1 ? "s" : "", sbuf_data(&sb)); | ||||
device_printf(dev, "<unknown device> at pin %s", pins); | |||||
resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%jd"); | resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%jd"); | ||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||
static int | static int | ||||
gpiobus_print_child(device_t dev, device_t child) | gpiobus_print_child(device_t dev, device_t child) | ||||
{ | { | ||||
char pins[128]; | char pins[128]; | ||||
struct sbuf sb; | |||||
int retval = 0; | int retval = 0; | ||||
struct gpiobus_ivar *devi; | struct gpiobus_ivar *devi; | ||||
devi = GPIOBUS_IVAR(child); | devi = GPIOBUS_IVAR(child); | ||||
memset(pins, 0, sizeof(pins)); | |||||
retval += bus_print_child_header(dev, child); | retval += bus_print_child_header(dev, child); | ||||
if (devi->npins > 0) { | if (devi->npins > 0) { | ||||
if (devi->npins > 1) | if (devi->npins > 1) | ||||
retval += printf(" at pins "); | retval += printf(" at pins "); | ||||
else | else | ||||
retval += printf(" at pin "); | retval += printf(" at pin "); | ||||
gpiobus_print_pins(devi, pins, sizeof(pins)); | sbuf_new(&sb, pins, sizeof(pins), SBUF_FIXEDLEN); | ||||
retval += printf("%s", pins); | gpiobus_print_pins(devi, &sb); | ||||
sbuf_finish(&sb); | |||||
retval += printf("%s", sbuf_data(&sb)); | |||||
} | } | ||||
resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%jd"); | resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%jd"); | ||||
retval += bus_print_child_footer(dev, child); | retval += bus_print_child_footer(dev, child); | ||||
return (retval); | return (retval); | ||||
} | } | ||||
static int | static int | ||||
gpiobus_child_location_str(device_t bus, device_t child, char *buf, | gpiobus_child_location(device_t bus, device_t child, struct sbuf *sb) | ||||
size_t buflen) | |||||
{ | { | ||||
struct gpiobus_ivar *devi; | struct gpiobus_ivar *devi; | ||||
devi = GPIOBUS_IVAR(child); | devi = GPIOBUS_IVAR(child); | ||||
if (devi->npins > 1) | sbuf_printf(sb, "pins="); | ||||
strlcpy(buf, "pins=", buflen); | gpiobus_print_pins(devi, sb); | ||||
else | |||||
strlcpy(buf, "pin=", buflen); | |||||
gpiobus_print_pins(devi, buf, buflen); | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | |||||
gpiobus_child_pnpinfo_str(device_t bus, device_t child, char *buf, | |||||
size_t buflen) | |||||
{ | |||||
*buf = '\0'; | |||||
return (0); | |||||
} | |||||
static device_t | static device_t | ||||
gpiobus_add_child(device_t dev, u_int order, const char *name, int unit) | gpiobus_add_child(device_t dev, u_int order, const char *name, int unit) | ||||
{ | { | ||||
device_t child; | device_t child; | ||||
struct gpiobus_ivar *devi; | struct gpiobus_ivar *devi; | ||||
child = device_add_child_ordered(dev, order, name, unit); | child = device_add_child_ordered(dev, order, name, unit); | ||||
if (child == NULL) | if (child == NULL) | ||||
▲ Show 20 Lines • Show All 387 Lines • ▼ Show 20 Lines | static device_method_t gpiobus_methods[] = { | ||||
DEVMETHOD(bus_release_resource, gpiobus_release_resource), | DEVMETHOD(bus_release_resource, gpiobus_release_resource), | ||||
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), | DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), | ||||
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), | DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), | ||||
DEVMETHOD(bus_get_resource_list, gpiobus_get_resource_list), | DEVMETHOD(bus_get_resource_list, gpiobus_get_resource_list), | ||||
DEVMETHOD(bus_add_child, gpiobus_add_child), | DEVMETHOD(bus_add_child, gpiobus_add_child), | ||||
DEVMETHOD(bus_rescan, gpiobus_rescan), | DEVMETHOD(bus_rescan, gpiobus_rescan), | ||||
DEVMETHOD(bus_probe_nomatch, gpiobus_probe_nomatch), | DEVMETHOD(bus_probe_nomatch, gpiobus_probe_nomatch), | ||||
DEVMETHOD(bus_print_child, gpiobus_print_child), | DEVMETHOD(bus_print_child, gpiobus_print_child), | ||||
DEVMETHOD(bus_child_pnpinfo_str, gpiobus_child_pnpinfo_str), | DEVMETHOD(bus_child_location, gpiobus_child_location), | ||||
DEVMETHOD(bus_child_location_str, gpiobus_child_location_str), | |||||
DEVMETHOD(bus_hinted_child, gpiobus_hinted_child), | DEVMETHOD(bus_hinted_child, gpiobus_hinted_child), | ||||
DEVMETHOD(bus_read_ivar, gpiobus_read_ivar), | DEVMETHOD(bus_read_ivar, gpiobus_read_ivar), | ||||
DEVMETHOD(bus_write_ivar, gpiobus_write_ivar), | DEVMETHOD(bus_write_ivar, gpiobus_write_ivar), | ||||
/* GPIO protocol */ | /* GPIO protocol */ | ||||
DEVMETHOD(gpiobus_acquire_bus, gpiobus_acquire_bus), | DEVMETHOD(gpiobus_acquire_bus, gpiobus_acquire_bus), | ||||
DEVMETHOD(gpiobus_release_bus, gpiobus_release_bus), | DEVMETHOD(gpiobus_release_bus, gpiobus_release_bus), | ||||
DEVMETHOD(gpiobus_pin_getflags, gpiobus_pin_getflags), | DEVMETHOD(gpiobus_pin_getflags, gpiobus_pin_getflags), | ||||
Show All 22 Lines |