Allow the retrieving of the reserved pins state.

With this change, it is now possible to verify the pin function and level
of reserved pins (but not set them).

The use of reserved pins on Raspberry pi can lead to short circuits and
real damage to the SoC.

While here, remove duplicated code, make use of OF_getencprop_alloc()
instead of using fixed sized variables and reduce the dmesg spam by
printing reserved pin ranges (when possible) instead of printing each pin
in the range.
This commit is contained in:
Luiz Otavio O Souza 2015-01-30 14:35:04 +00:00
parent 9855acef2a
commit 99a2011188
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=277932

View File

@ -493,39 +493,6 @@ bcm_gpio_pin_toggle(device_t dev, uint32_t pin)
return (0);
}
static int
bcm_gpio_get_ro_pins(struct bcm_gpio_softc *sc)
{
int i, len;
pcell_t pins[BCM_GPIO_PINS];
phandle_t gpio;
/* Find the gpio node to start. */
gpio = ofw_bus_get_node(sc->sc_dev);
len = OF_getproplen(gpio, "broadcom,read-only");
if (len < 0 || len > sizeof(pins))
return (-1);
if (OF_getprop(gpio, "broadcom,read-only", &pins, len) < 0)
return (-1);
sc->sc_ro_npins = len / sizeof(pcell_t);
device_printf(sc->sc_dev, "read-only pins: ");
for (i = 0; i < sc->sc_ro_npins; i++) {
sc->sc_ro_pins[i] = fdt32_to_cpu(pins[i]);
if (i > 0)
printf(",");
printf("%d", sc->sc_ro_pins[i]);
}
if (i > 0)
printf(".");
printf("\n");
return (0);
}
static int
bcm_gpio_func_proc(SYSCTL_HANDLER_ARGS)
{
@ -545,7 +512,9 @@ bcm_gpio_func_proc(SYSCTL_HANDLER_ARGS)
error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
if (error != 0 || req->newptr == NULL)
return (error);
/* Ignore changes on read-only pins. */
if (bcm_gpio_pin_is_ro(sc, sc_sysctl->pin))
return (0);
/* Parse the user supplied string and check for a valid pin function. */
if (bcm_gpio_str_func(buf, &nfunc) != 0)
return (EINVAL);
@ -594,64 +563,83 @@ bcm_gpio_sysctl_init(struct bcm_gpio_softc *sc)
}
}
static int
bcm_gpio_get_ro_pins(struct bcm_gpio_softc *sc, phandle_t node,
const char *propname, const char *label)
{
int i, need_comma, npins, range_start, range_stop;
pcell_t *pins;
/* Get the property data. */
npins = OF_getencprop_alloc(node, propname, sizeof(*pins),
(void **)&pins);
if (npins < 0)
return (-1);
if (npins == 0) {
free(pins, M_OFWPROP);
return (0);
}
for (i = 0; i < npins; i++)
sc->sc_ro_pins[i + sc->sc_ro_npins] = pins[i];
sc->sc_ro_npins += npins;
need_comma = 0;
device_printf(sc->sc_dev, "%s pins: ", label);
range_start = range_stop = pins[0];
for (i = 1; i < npins; i++) {
if (pins[i] != range_stop + 1) {
if (need_comma)
printf(",");
if (range_start != range_stop)
printf("%d-%d", range_start, range_stop);
else
printf("%d", range_start);
range_start = range_stop = pins[i];
need_comma = 1;
} else
range_stop++;
}
if (need_comma)
printf(",");
if (range_start != range_stop)
printf("%d-%d.\n", range_start, range_stop);
else
printf("%d.\n", range_start);
free(pins, M_OFWPROP);
return (0);
}
static int
bcm_gpio_get_reserved_pins(struct bcm_gpio_softc *sc)
{
int i, j, len, npins;
pcell_t pins[BCM_GPIO_PINS];
char *name;
phandle_t gpio, node, reserved;
char name[32];
ssize_t len;
/* Get read-only pins. */
if (bcm_gpio_get_ro_pins(sc) != 0)
return (-1);
/* Find the gpio/reserved pins node to start. */
gpio = ofw_bus_get_node(sc->sc_dev);
node = OF_child(gpio);
/*
* Find reserved node
*/
if (bcm_gpio_get_ro_pins(sc, gpio, "broadcom,read-only",
"read-only") != 0)
return (-1);
/* Traverse the GPIO subnodes to find the reserved pins node. */
reserved = 0;
node = OF_child(gpio);
while ((node != 0) && (reserved == 0)) {
len = OF_getprop(node, "name", name,
sizeof(name) - 1);
name[len] = 0;
len = OF_getprop_alloc(node, "name", 1, (void **)&name);
if (len == -1)
return (-1);
if (strcmp(name, "reserved") == 0)
reserved = node;
free(name, M_OFWPROP);
node = OF_peer(node);
}
if (reserved == 0)
return (-1);
/* Get the reserved pins. */
len = OF_getproplen(reserved, "broadcom,pins");
if (len < 0 || len > sizeof(pins))
if (bcm_gpio_get_ro_pins(sc, reserved, "broadcom,pins",
"reserved") != 0)
return (-1);
if (OF_getprop(reserved, "broadcom,pins", &pins, len) < 0)
return (-1);
npins = len / sizeof(pcell_t);
j = 0;
device_printf(sc->sc_dev, "reserved pins: ");
for (i = 0; i < npins; i++) {
if (i > 0)
printf(",");
printf("%d", fdt32_to_cpu(pins[i]));
/* Some pins maybe already on the list of read-only pins. */
if (bcm_gpio_pin_is_ro(sc, fdt32_to_cpu(pins[i])))
continue;
sc->sc_ro_pins[j++ + sc->sc_ro_npins] = fdt32_to_cpu(pins[i]);
}
sc->sc_ro_npins += j;
if (i > 0)
printf(".");
printf("\n");
return (0);
}
@ -717,8 +705,6 @@ bcm_gpio_attach(device_t dev)
/* Initialize the software controlled pins. */
for (i = 0, j = 0; j < BCM_GPIO_PINS; j++) {
if (bcm_gpio_pin_is_ro(sc, j))
continue;
snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,
"pin %d", j);
func = bcm_gpio_get_function(sc, j);