// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> * Driver for chargers which report their online status through a GPIO pin
*/
staticint set_charge_current_limit(struct gpio_charger *gpio_charger, int val)
{ struct gpio_mapping mapping; int ndescs = gpio_charger->current_limit_gpios->ndescs; struct gpio_desc **gpios = gpio_charger->current_limit_gpios->desc; int i;
if (!gpio_charger->current_limit_map_size) return -EINVAL;
for (i = 0; i < gpio_charger->current_limit_map_size; i++) { if (gpio_charger->current_limit_map[i].limit_ua <= val) break;
}
/* * If a valid charge current limit isn't found, default to smallest * current limitation for safety reasons.
*/ if (i >= gpio_charger->current_limit_map_size)
i = gpio_charger->current_limit_map_size - 1;
mapping = gpio_charger->current_limit_map[i];
for (i = 0; i < ndescs; i++) { bool val = (mapping.gpiodata >> i) & 1;
gpiod_set_value_cansleep(gpios[ndescs-i-1], val);
}
len = device_property_read_u32_array(dev, "charge-current-limit-mapping",
NULL, 0); if (len < 0) return len;
if (len == 0 || len % 2) {
dev_err(dev, "invalid charge-current-limit-mapping length\n"); return -EINVAL;
}
gpio_charger->current_limit_map = devm_kmalloc_array(dev,
len / 2, sizeof(*gpio_charger->current_limit_map), GFP_KERNEL); if (!gpio_charger->current_limit_map) return -ENOMEM;
gpio_charger->current_limit_map_size = len / 2;
len = device_property_read_u32_array(dev, "charge-current-limit-mapping",
(u32*) gpio_charger->current_limit_map, len); if (len < 0) return len;
set_def_limit = !device_property_read_u32(dev, "charge-current-limit-default-microamp",
&def_limit); for (i=0; i < gpio_charger->current_limit_map_size; i++) { if (gpio_charger->current_limit_map[i].limit_ua > cur_limit) {
dev_err(dev, "charge-current-limit-mapping not sorted by current in descending order\n"); return -EINVAL;
}
if (set_def_limit)
dev_warn(dev, "charge-current-limit-default-microamp %u not listed in charge-current-limit-mapping\n",
def_limit);
/* default to smallest current limitation for safety reasons */
len = gpio_charger->current_limit_map_size - 1;
set_charge_current_limit(gpio_charger,
gpio_charger->current_limit_map[len].limit_ua);
return 0;
}
/* * The entries will be overwritten by driver's probe routine depending * on the available features. This list ensures, that the array is big * enough for all optional features.
*/ staticenum power_supply_property gpio_charger_properties[] = {
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
};
/* * This will fetch a GPIO descriptor from device tree, ACPI or * boardfile descriptor tables. It's good to try this first.
*/
gpio_charger->gpiod = devm_gpiod_get_optional(dev, NULL, GPIOD_IN); if (IS_ERR(gpio_charger->gpiod)) { /* Just try again if this happens */ return dev_err_probe(dev, PTR_ERR(gpio_charger->gpiod), "error getting GPIO descriptor\n");
}
if (gpio_charger->gpiod) {
gpio_charger_properties[num_props] = POWER_SUPPLY_PROP_ONLINE;
num_props++;
}
charge_status = devm_gpiod_get_optional(dev, "charge-status", GPIOD_IN); if (IS_ERR(charge_status)) return PTR_ERR(charge_status); if (charge_status) {
gpio_charger->charge_status = charge_status;
gpio_charger_properties[num_props] = POWER_SUPPLY_PROP_STATUS;
num_props++;
}
ret = init_charge_current_limit(dev, gpio_charger); if (ret < 0) return ret; if (gpio_charger->current_limit_map) {
gpio_charger_properties[num_props] =
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX;
num_props++;
}
MODULE_AUTHOR("Lars-Peter Clausen ");
MODULE_DESCRIPTION("Driver for chargers only communicating via GPIO(s)");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:gpio-charger");
Messung V0.5
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet)
¤
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.