led_dat->cdev.default_trigger = template->default_trigger;
led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod); if (!led_dat->can_sleep)
led_dat->cdev.brightness_set = gpio_led_set; else
led_dat->cdev.brightness_set_blocking = gpio_led_set_blocking;
led_dat->blinking = 0; if (blink_set) {
led_dat->platform_gpio_blink_set = blink_set;
led_dat->cdev.blink_set = gpio_blink_set;
} if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) {
state = gpiod_get_value_cansleep(led_dat->gpiod); if (state < 0) return state;
} else {
state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
}
led_dat->cdev.brightness = state;
led_dat->cdev.max_brightness = 1; if (!template->retain_state_suspended)
led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; if (template->panic_indicator)
led_dat->cdev.flags |= LED_PANIC_INDICATOR; if (template->retain_state_shutdown)
led_dat->cdev.flags |= LED_RETAIN_AT_SHUTDOWN;
ret = gpiod_direction_output(led_dat->gpiod, state); if (ret < 0) return ret;
if (template->name) {
led_dat->cdev.name = template->name;
ret = devm_led_classdev_register(parent, &led_dat->cdev);
} else {
init_data.fwnode = fwnode;
ret = devm_led_classdev_register_ext(parent, &led_dat->cdev,
&init_data);
}
if (ret) return ret;
pinctrl = devm_pinctrl_get_select_default(led_dat->cdev.dev);
ret = PTR_ERR_OR_ZERO(pinctrl); /* pinctrl-%d not present, not an error */ if (ret == -ENODEV)
ret = 0; if (ret) {
dev_warn(led_dat->cdev.dev, "Failed to select %pfw pinctrl: %d\n",
fwnode, ret);
}
return ret;
}
struct gpio_leds_priv { int num_leds; struct gpio_led_data leds[] __counted_by(num_leds);
};
/* * Acquire gpiod from DT with uninitialized label, which * will be updated after LED class device is registered, * Only then the final LED name is known.
*/
led.gpiod = devm_fwnode_gpiod_get(dev, child, NULL, GPIOD_ASIS,
NULL); if (IS_ERR(led.gpiod)) {
dev_err_probe(dev, PTR_ERR(led.gpiod), "Failed to get GPIO '%pfw'\n",
child); return ERR_CAST(led.gpiod);
}
if (fwnode_property_present(child, "retain-state-suspended"))
led.retain_state_suspended = 1; if (fwnode_property_present(child, "retain-state-shutdown"))
led.retain_state_shutdown = 1; if (fwnode_property_present(child, "panic-indicator"))
led.panic_indicator = 1;
ret = create_gpio_led(&led, led_dat, dev, child, NULL); if (ret < 0) return ERR_PTR(ret);
/* Set gpiod label to match the corresponding LED name. */
gpiod_set_consumer_name(led_dat->gpiod,
led_dat->cdev.dev->kobj.name);
used++;
}
priv->num_leds = used;
staticstruct gpio_desc *gpio_led_get_gpiod(struct device *dev, int idx, conststruct gpio_led *template)
{ struct gpio_desc *gpiod; int ret;
/* * This means the LED does not come from the device tree * or ACPI, so let's try just getting it by index from the * device, this will hit the board file, if any and get * the GPIO from there.
*/
gpiod = devm_gpiod_get_index_optional(dev, NULL, idx, GPIOD_OUT_LOW); if (IS_ERR(gpiod)) return gpiod; if (gpiod) {
gpiod_set_consumer_name(gpiod, template->name); return gpiod;
}
/* * This is the legacy code path for platform code that * still uses GPIO numbers. Ultimately we would like to get * rid of this block completely.
*/
/* skip leds that aren't available */ if (!gpio_is_valid(template->gpio)) return ERR_PTR(-ENOENT);
ret = devm_gpio_request_one(dev, template->gpio, GPIOF_OUT_INIT_LOW,
template->name); if (ret < 0) return ERR_PTR(ret);
gpiod = gpio_to_desc(template->gpio); if (!gpiod) return ERR_PTR(-EINVAL);
if (template->active_low ^ gpiod_is_active_low(gpiod))
gpiod_toggle_active_low(gpiod);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.