162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Generic pwmlib implementation 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2011 Sascha Hauer <s.hauer@pengutronix.de> 662306a36Sopenharmony_ci * Copyright (C) 2011-2012 Avionic Design GmbH 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/acpi.h> 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/of.h> 1262306a36Sopenharmony_ci#include <linux/pwm.h> 1362306a36Sopenharmony_ci#include <linux/list.h> 1462306a36Sopenharmony_ci#include <linux/mutex.h> 1562306a36Sopenharmony_ci#include <linux/err.h> 1662306a36Sopenharmony_ci#include <linux/slab.h> 1762306a36Sopenharmony_ci#include <linux/device.h> 1862306a36Sopenharmony_ci#include <linux/debugfs.h> 1962306a36Sopenharmony_ci#include <linux/seq_file.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include <dt-bindings/pwm/pwm.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define CREATE_TRACE_POINTS 2462306a36Sopenharmony_ci#include <trace/events/pwm.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define MAX_PWMS 1024 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic DEFINE_MUTEX(pwm_lookup_lock); 2962306a36Sopenharmony_cistatic LIST_HEAD(pwm_lookup_list); 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/* protects access to pwm_chips and allocated_pwms */ 3262306a36Sopenharmony_cistatic DEFINE_MUTEX(pwm_lock); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic LIST_HEAD(pwm_chips); 3562306a36Sopenharmony_cistatic DECLARE_BITMAP(allocated_pwms, MAX_PWMS); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* Called with pwm_lock held */ 3862306a36Sopenharmony_cistatic int alloc_pwms(unsigned int count) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci unsigned int start; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci start = bitmap_find_next_zero_area(allocated_pwms, MAX_PWMS, 0, 4362306a36Sopenharmony_ci count, 0); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci if (start + count > MAX_PWMS) 4662306a36Sopenharmony_ci return -ENOSPC; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci bitmap_set(allocated_pwms, start, count); 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci return start; 5162306a36Sopenharmony_ci} 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* Called with pwm_lock held */ 5462306a36Sopenharmony_cistatic void free_pwms(struct pwm_chip *chip) 5562306a36Sopenharmony_ci{ 5662306a36Sopenharmony_ci bitmap_clear(allocated_pwms, chip->base, chip->npwm); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci kfree(chip->pwms); 5962306a36Sopenharmony_ci chip->pwms = NULL; 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic struct pwm_chip *pwmchip_find_by_name(const char *name) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci struct pwm_chip *chip; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci if (!name) 6762306a36Sopenharmony_ci return NULL; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci mutex_lock(&pwm_lock); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci list_for_each_entry(chip, &pwm_chips, list) { 7262306a36Sopenharmony_ci const char *chip_name = dev_name(chip->dev); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci if (chip_name && strcmp(chip_name, name) == 0) { 7562306a36Sopenharmony_ci mutex_unlock(&pwm_lock); 7662306a36Sopenharmony_ci return chip; 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci mutex_unlock(&pwm_lock); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci return NULL; 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic int pwm_device_request(struct pwm_device *pwm, const char *label) 8662306a36Sopenharmony_ci{ 8762306a36Sopenharmony_ci int err; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if (test_bit(PWMF_REQUESTED, &pwm->flags)) 9062306a36Sopenharmony_ci return -EBUSY; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci if (!try_module_get(pwm->chip->ops->owner)) 9362306a36Sopenharmony_ci return -ENODEV; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci if (pwm->chip->ops->request) { 9662306a36Sopenharmony_ci err = pwm->chip->ops->request(pwm->chip, pwm); 9762306a36Sopenharmony_ci if (err) { 9862306a36Sopenharmony_ci module_put(pwm->chip->ops->owner); 9962306a36Sopenharmony_ci return err; 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci if (pwm->chip->ops->get_state) { 10462306a36Sopenharmony_ci /* 10562306a36Sopenharmony_ci * Zero-initialize state because most drivers are unaware of 10662306a36Sopenharmony_ci * .usage_power. The other members of state are supposed to be 10762306a36Sopenharmony_ci * set by lowlevel drivers. We still initialize the whole 10862306a36Sopenharmony_ci * structure for simplicity even though this might paper over 10962306a36Sopenharmony_ci * faulty implementations of .get_state(). 11062306a36Sopenharmony_ci */ 11162306a36Sopenharmony_ci struct pwm_state state = { 0, }; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci err = pwm->chip->ops->get_state(pwm->chip, pwm, &state); 11462306a36Sopenharmony_ci trace_pwm_get(pwm, &state, err); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (!err) 11762306a36Sopenharmony_ci pwm->state = state; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_PWM_DEBUG)) 12062306a36Sopenharmony_ci pwm->last = pwm->state; 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci set_bit(PWMF_REQUESTED, &pwm->flags); 12462306a36Sopenharmony_ci pwm->label = label; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci return 0; 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistruct pwm_device * 13062306a36Sopenharmony_ciof_pwm_xlate_with_flags(struct pwm_chip *chip, const struct of_phandle_args *args) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci struct pwm_device *pwm; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci if (chip->of_pwm_n_cells < 2) 13562306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* flags in the third cell are optional */ 13862306a36Sopenharmony_ci if (args->args_count < 2) 13962306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci if (args->args[0] >= chip->npwm) 14262306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci pwm = pwm_request_from_chip(chip, args->args[0], NULL); 14562306a36Sopenharmony_ci if (IS_ERR(pwm)) 14662306a36Sopenharmony_ci return pwm; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci pwm->args.period = args->args[1]; 14962306a36Sopenharmony_ci pwm->args.polarity = PWM_POLARITY_NORMAL; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if (chip->of_pwm_n_cells >= 3) { 15262306a36Sopenharmony_ci if (args->args_count > 2 && args->args[2] & PWM_POLARITY_INVERTED) 15362306a36Sopenharmony_ci pwm->args.polarity = PWM_POLARITY_INVERSED; 15462306a36Sopenharmony_ci } 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci return pwm; 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(of_pwm_xlate_with_flags); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistruct pwm_device * 16162306a36Sopenharmony_ciof_pwm_single_xlate(struct pwm_chip *chip, const struct of_phandle_args *args) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci struct pwm_device *pwm; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci if (chip->of_pwm_n_cells < 1) 16662306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* validate that one cell is specified, optionally with flags */ 16962306a36Sopenharmony_ci if (args->args_count != 1 && args->args_count != 2) 17062306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci pwm = pwm_request_from_chip(chip, 0, NULL); 17362306a36Sopenharmony_ci if (IS_ERR(pwm)) 17462306a36Sopenharmony_ci return pwm; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci pwm->args.period = args->args[0]; 17762306a36Sopenharmony_ci pwm->args.polarity = PWM_POLARITY_NORMAL; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci if (args->args_count == 2 && args->args[1] & PWM_POLARITY_INVERTED) 18062306a36Sopenharmony_ci pwm->args.polarity = PWM_POLARITY_INVERSED; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci return pwm; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(of_pwm_single_xlate); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_cistatic void of_pwmchip_add(struct pwm_chip *chip) 18762306a36Sopenharmony_ci{ 18862306a36Sopenharmony_ci if (!chip->dev || !chip->dev->of_node) 18962306a36Sopenharmony_ci return; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci if (!chip->of_xlate) { 19262306a36Sopenharmony_ci u32 pwm_cells; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci if (of_property_read_u32(chip->dev->of_node, "#pwm-cells", 19562306a36Sopenharmony_ci &pwm_cells)) 19662306a36Sopenharmony_ci pwm_cells = 2; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci chip->of_xlate = of_pwm_xlate_with_flags; 19962306a36Sopenharmony_ci chip->of_pwm_n_cells = pwm_cells; 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci of_node_get(chip->dev->of_node); 20362306a36Sopenharmony_ci} 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_cistatic void of_pwmchip_remove(struct pwm_chip *chip) 20662306a36Sopenharmony_ci{ 20762306a36Sopenharmony_ci if (chip->dev) 20862306a36Sopenharmony_ci of_node_put(chip->dev->of_node); 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci/** 21262306a36Sopenharmony_ci * pwm_set_chip_data() - set private chip data for a PWM 21362306a36Sopenharmony_ci * @pwm: PWM device 21462306a36Sopenharmony_ci * @data: pointer to chip-specific data 21562306a36Sopenharmony_ci * 21662306a36Sopenharmony_ci * Returns: 0 on success or a negative error code on failure. 21762306a36Sopenharmony_ci */ 21862306a36Sopenharmony_ciint pwm_set_chip_data(struct pwm_device *pwm, void *data) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci if (!pwm) 22162306a36Sopenharmony_ci return -EINVAL; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci pwm->chip_data = data; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci return 0; 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pwm_set_chip_data); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci/** 23062306a36Sopenharmony_ci * pwm_get_chip_data() - get private chip data for a PWM 23162306a36Sopenharmony_ci * @pwm: PWM device 23262306a36Sopenharmony_ci * 23362306a36Sopenharmony_ci * Returns: A pointer to the chip-private data for the PWM device. 23462306a36Sopenharmony_ci */ 23562306a36Sopenharmony_civoid *pwm_get_chip_data(struct pwm_device *pwm) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci return pwm ? pwm->chip_data : NULL; 23862306a36Sopenharmony_ci} 23962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pwm_get_chip_data); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic bool pwm_ops_check(const struct pwm_chip *chip) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci const struct pwm_ops *ops = chip->ops; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci if (!ops->apply) 24662306a36Sopenharmony_ci return false; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_PWM_DEBUG) && !ops->get_state) 24962306a36Sopenharmony_ci dev_warn(chip->dev, 25062306a36Sopenharmony_ci "Please implement the .get_state() callback\n"); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci return true; 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci/** 25662306a36Sopenharmony_ci * pwmchip_add() - register a new PWM chip 25762306a36Sopenharmony_ci * @chip: the PWM chip to add 25862306a36Sopenharmony_ci * 25962306a36Sopenharmony_ci * Register a new PWM chip. 26062306a36Sopenharmony_ci * 26162306a36Sopenharmony_ci * Returns: 0 on success or a negative error code on failure. 26262306a36Sopenharmony_ci */ 26362306a36Sopenharmony_ciint pwmchip_add(struct pwm_chip *chip) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci struct pwm_device *pwm; 26662306a36Sopenharmony_ci unsigned int i; 26762306a36Sopenharmony_ci int ret; 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci if (!chip || !chip->dev || !chip->ops || !chip->npwm) 27062306a36Sopenharmony_ci return -EINVAL; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci if (!pwm_ops_check(chip)) 27362306a36Sopenharmony_ci return -EINVAL; 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci chip->pwms = kcalloc(chip->npwm, sizeof(*pwm), GFP_KERNEL); 27662306a36Sopenharmony_ci if (!chip->pwms) 27762306a36Sopenharmony_ci return -ENOMEM; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci mutex_lock(&pwm_lock); 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci ret = alloc_pwms(chip->npwm); 28262306a36Sopenharmony_ci if (ret < 0) { 28362306a36Sopenharmony_ci mutex_unlock(&pwm_lock); 28462306a36Sopenharmony_ci kfree(chip->pwms); 28562306a36Sopenharmony_ci return ret; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci chip->base = ret; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci for (i = 0; i < chip->npwm; i++) { 29162306a36Sopenharmony_ci pwm = &chip->pwms[i]; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci pwm->chip = chip; 29462306a36Sopenharmony_ci pwm->pwm = chip->base + i; 29562306a36Sopenharmony_ci pwm->hwpwm = i; 29662306a36Sopenharmony_ci } 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci list_add(&chip->list, &pwm_chips); 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci mutex_unlock(&pwm_lock); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_OF)) 30362306a36Sopenharmony_ci of_pwmchip_add(chip); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci pwmchip_sysfs_export(chip); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci return 0; 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pwmchip_add); 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci/** 31262306a36Sopenharmony_ci * pwmchip_remove() - remove a PWM chip 31362306a36Sopenharmony_ci * @chip: the PWM chip to remove 31462306a36Sopenharmony_ci * 31562306a36Sopenharmony_ci * Removes a PWM chip. 31662306a36Sopenharmony_ci */ 31762306a36Sopenharmony_civoid pwmchip_remove(struct pwm_chip *chip) 31862306a36Sopenharmony_ci{ 31962306a36Sopenharmony_ci pwmchip_sysfs_unexport(chip); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_OF)) 32262306a36Sopenharmony_ci of_pwmchip_remove(chip); 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci mutex_lock(&pwm_lock); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci list_del_init(&chip->list); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci free_pwms(chip); 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci mutex_unlock(&pwm_lock); 33162306a36Sopenharmony_ci} 33262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pwmchip_remove); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic void devm_pwmchip_remove(void *data) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci struct pwm_chip *chip = data; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci pwmchip_remove(chip); 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ciint devm_pwmchip_add(struct device *dev, struct pwm_chip *chip) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci int ret; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci ret = pwmchip_add(chip); 34662306a36Sopenharmony_ci if (ret) 34762306a36Sopenharmony_ci return ret; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci return devm_add_action_or_reset(dev, devm_pwmchip_remove, chip); 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_pwmchip_add); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci/** 35462306a36Sopenharmony_ci * pwm_request_from_chip() - request a PWM device relative to a PWM chip 35562306a36Sopenharmony_ci * @chip: PWM chip 35662306a36Sopenharmony_ci * @index: per-chip index of the PWM to request 35762306a36Sopenharmony_ci * @label: a literal description string of this PWM 35862306a36Sopenharmony_ci * 35962306a36Sopenharmony_ci * Returns: A pointer to the PWM device at the given index of the given PWM 36062306a36Sopenharmony_ci * chip. A negative error code is returned if the index is not valid for the 36162306a36Sopenharmony_ci * specified PWM chip or if the PWM device cannot be requested. 36262306a36Sopenharmony_ci */ 36362306a36Sopenharmony_cistruct pwm_device *pwm_request_from_chip(struct pwm_chip *chip, 36462306a36Sopenharmony_ci unsigned int index, 36562306a36Sopenharmony_ci const char *label) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci struct pwm_device *pwm; 36862306a36Sopenharmony_ci int err; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci if (!chip || index >= chip->npwm) 37162306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci mutex_lock(&pwm_lock); 37462306a36Sopenharmony_ci pwm = &chip->pwms[index]; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci err = pwm_device_request(pwm, label); 37762306a36Sopenharmony_ci if (err < 0) 37862306a36Sopenharmony_ci pwm = ERR_PTR(err); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci mutex_unlock(&pwm_lock); 38162306a36Sopenharmony_ci return pwm; 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pwm_request_from_chip); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_cistatic void pwm_apply_state_debug(struct pwm_device *pwm, 38662306a36Sopenharmony_ci const struct pwm_state *state) 38762306a36Sopenharmony_ci{ 38862306a36Sopenharmony_ci struct pwm_state *last = &pwm->last; 38962306a36Sopenharmony_ci struct pwm_chip *chip = pwm->chip; 39062306a36Sopenharmony_ci struct pwm_state s1 = { 0 }, s2 = { 0 }; 39162306a36Sopenharmony_ci int err; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_PWM_DEBUG)) 39462306a36Sopenharmony_ci return; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci /* No reasonable diagnosis possible without .get_state() */ 39762306a36Sopenharmony_ci if (!chip->ops->get_state) 39862306a36Sopenharmony_ci return; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci /* 40162306a36Sopenharmony_ci * *state was just applied. Read out the hardware state and do some 40262306a36Sopenharmony_ci * checks. 40362306a36Sopenharmony_ci */ 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci err = chip->ops->get_state(chip, pwm, &s1); 40662306a36Sopenharmony_ci trace_pwm_get(pwm, &s1, err); 40762306a36Sopenharmony_ci if (err) 40862306a36Sopenharmony_ci /* If that failed there isn't much to debug */ 40962306a36Sopenharmony_ci return; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci /* 41262306a36Sopenharmony_ci * The lowlevel driver either ignored .polarity (which is a bug) or as 41362306a36Sopenharmony_ci * best effort inverted .polarity and fixed .duty_cycle respectively. 41462306a36Sopenharmony_ci * Undo this inversion and fixup for further tests. 41562306a36Sopenharmony_ci */ 41662306a36Sopenharmony_ci if (s1.enabled && s1.polarity != state->polarity) { 41762306a36Sopenharmony_ci s2.polarity = state->polarity; 41862306a36Sopenharmony_ci s2.duty_cycle = s1.period - s1.duty_cycle; 41962306a36Sopenharmony_ci s2.period = s1.period; 42062306a36Sopenharmony_ci s2.enabled = s1.enabled; 42162306a36Sopenharmony_ci } else { 42262306a36Sopenharmony_ci s2 = s1; 42362306a36Sopenharmony_ci } 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci if (s2.polarity != state->polarity && 42662306a36Sopenharmony_ci state->duty_cycle < state->period) 42762306a36Sopenharmony_ci dev_warn(chip->dev, ".apply ignored .polarity\n"); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci if (state->enabled && 43062306a36Sopenharmony_ci last->polarity == state->polarity && 43162306a36Sopenharmony_ci last->period > s2.period && 43262306a36Sopenharmony_ci last->period <= state->period) 43362306a36Sopenharmony_ci dev_warn(chip->dev, 43462306a36Sopenharmony_ci ".apply didn't pick the best available period (requested: %llu, applied: %llu, possible: %llu)\n", 43562306a36Sopenharmony_ci state->period, s2.period, last->period); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci if (state->enabled && state->period < s2.period) 43862306a36Sopenharmony_ci dev_warn(chip->dev, 43962306a36Sopenharmony_ci ".apply is supposed to round down period (requested: %llu, applied: %llu)\n", 44062306a36Sopenharmony_ci state->period, s2.period); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci if (state->enabled && 44362306a36Sopenharmony_ci last->polarity == state->polarity && 44462306a36Sopenharmony_ci last->period == s2.period && 44562306a36Sopenharmony_ci last->duty_cycle > s2.duty_cycle && 44662306a36Sopenharmony_ci last->duty_cycle <= state->duty_cycle) 44762306a36Sopenharmony_ci dev_warn(chip->dev, 44862306a36Sopenharmony_ci ".apply didn't pick the best available duty cycle (requested: %llu/%llu, applied: %llu/%llu, possible: %llu/%llu)\n", 44962306a36Sopenharmony_ci state->duty_cycle, state->period, 45062306a36Sopenharmony_ci s2.duty_cycle, s2.period, 45162306a36Sopenharmony_ci last->duty_cycle, last->period); 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci if (state->enabled && state->duty_cycle < s2.duty_cycle) 45462306a36Sopenharmony_ci dev_warn(chip->dev, 45562306a36Sopenharmony_ci ".apply is supposed to round down duty_cycle (requested: %llu/%llu, applied: %llu/%llu)\n", 45662306a36Sopenharmony_ci state->duty_cycle, state->period, 45762306a36Sopenharmony_ci s2.duty_cycle, s2.period); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci if (!state->enabled && s2.enabled && s2.duty_cycle > 0) 46062306a36Sopenharmony_ci dev_warn(chip->dev, 46162306a36Sopenharmony_ci "requested disabled, but yielded enabled with duty > 0\n"); 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci /* reapply the state that the driver reported being configured. */ 46462306a36Sopenharmony_ci err = chip->ops->apply(chip, pwm, &s1); 46562306a36Sopenharmony_ci trace_pwm_apply(pwm, &s1, err); 46662306a36Sopenharmony_ci if (err) { 46762306a36Sopenharmony_ci *last = s1; 46862306a36Sopenharmony_ci dev_err(chip->dev, "failed to reapply current setting\n"); 46962306a36Sopenharmony_ci return; 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci *last = (struct pwm_state){ 0 }; 47362306a36Sopenharmony_ci err = chip->ops->get_state(chip, pwm, last); 47462306a36Sopenharmony_ci trace_pwm_get(pwm, last, err); 47562306a36Sopenharmony_ci if (err) 47662306a36Sopenharmony_ci return; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci /* reapplication of the current state should give an exact match */ 47962306a36Sopenharmony_ci if (s1.enabled != last->enabled || 48062306a36Sopenharmony_ci s1.polarity != last->polarity || 48162306a36Sopenharmony_ci (s1.enabled && s1.period != last->period) || 48262306a36Sopenharmony_ci (s1.enabled && s1.duty_cycle != last->duty_cycle)) { 48362306a36Sopenharmony_ci dev_err(chip->dev, 48462306a36Sopenharmony_ci ".apply is not idempotent (ena=%d pol=%d %llu/%llu) -> (ena=%d pol=%d %llu/%llu)\n", 48562306a36Sopenharmony_ci s1.enabled, s1.polarity, s1.duty_cycle, s1.period, 48662306a36Sopenharmony_ci last->enabled, last->polarity, last->duty_cycle, 48762306a36Sopenharmony_ci last->period); 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci} 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci/** 49262306a36Sopenharmony_ci * pwm_apply_state() - atomically apply a new state to a PWM device 49362306a36Sopenharmony_ci * @pwm: PWM device 49462306a36Sopenharmony_ci * @state: new state to apply 49562306a36Sopenharmony_ci */ 49662306a36Sopenharmony_ciint pwm_apply_state(struct pwm_device *pwm, const struct pwm_state *state) 49762306a36Sopenharmony_ci{ 49862306a36Sopenharmony_ci struct pwm_chip *chip; 49962306a36Sopenharmony_ci int err; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci /* 50262306a36Sopenharmony_ci * Some lowlevel driver's implementations of .apply() make use of 50362306a36Sopenharmony_ci * mutexes, also with some drivers only returning when the new 50462306a36Sopenharmony_ci * configuration is active calling pwm_apply_state() from atomic context 50562306a36Sopenharmony_ci * is a bad idea. So make it explicit that calling this function might 50662306a36Sopenharmony_ci * sleep. 50762306a36Sopenharmony_ci */ 50862306a36Sopenharmony_ci might_sleep(); 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci if (!pwm || !state || !state->period || 51162306a36Sopenharmony_ci state->duty_cycle > state->period) 51262306a36Sopenharmony_ci return -EINVAL; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci chip = pwm->chip; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci if (state->period == pwm->state.period && 51762306a36Sopenharmony_ci state->duty_cycle == pwm->state.duty_cycle && 51862306a36Sopenharmony_ci state->polarity == pwm->state.polarity && 51962306a36Sopenharmony_ci state->enabled == pwm->state.enabled && 52062306a36Sopenharmony_ci state->usage_power == pwm->state.usage_power) 52162306a36Sopenharmony_ci return 0; 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci err = chip->ops->apply(chip, pwm, state); 52462306a36Sopenharmony_ci trace_pwm_apply(pwm, state, err); 52562306a36Sopenharmony_ci if (err) 52662306a36Sopenharmony_ci return err; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci pwm->state = *state; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci /* 53162306a36Sopenharmony_ci * only do this after pwm->state was applied as some 53262306a36Sopenharmony_ci * implementations of .get_state depend on this 53362306a36Sopenharmony_ci */ 53462306a36Sopenharmony_ci pwm_apply_state_debug(pwm, state); 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci return 0; 53762306a36Sopenharmony_ci} 53862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pwm_apply_state); 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci/** 54162306a36Sopenharmony_ci * pwm_capture() - capture and report a PWM signal 54262306a36Sopenharmony_ci * @pwm: PWM device 54362306a36Sopenharmony_ci * @result: structure to fill with capture result 54462306a36Sopenharmony_ci * @timeout: time to wait, in milliseconds, before giving up on capture 54562306a36Sopenharmony_ci * 54662306a36Sopenharmony_ci * Returns: 0 on success or a negative error code on failure. 54762306a36Sopenharmony_ci */ 54862306a36Sopenharmony_ciint pwm_capture(struct pwm_device *pwm, struct pwm_capture *result, 54962306a36Sopenharmony_ci unsigned long timeout) 55062306a36Sopenharmony_ci{ 55162306a36Sopenharmony_ci int err; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci if (!pwm || !pwm->chip->ops) 55462306a36Sopenharmony_ci return -EINVAL; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci if (!pwm->chip->ops->capture) 55762306a36Sopenharmony_ci return -ENOSYS; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci mutex_lock(&pwm_lock); 56062306a36Sopenharmony_ci err = pwm->chip->ops->capture(pwm->chip, pwm, result, timeout); 56162306a36Sopenharmony_ci mutex_unlock(&pwm_lock); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci return err; 56462306a36Sopenharmony_ci} 56562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pwm_capture); 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci/** 56862306a36Sopenharmony_ci * pwm_adjust_config() - adjust the current PWM config to the PWM arguments 56962306a36Sopenharmony_ci * @pwm: PWM device 57062306a36Sopenharmony_ci * 57162306a36Sopenharmony_ci * This function will adjust the PWM config to the PWM arguments provided 57262306a36Sopenharmony_ci * by the DT or PWM lookup table. This is particularly useful to adapt 57362306a36Sopenharmony_ci * the bootloader config to the Linux one. 57462306a36Sopenharmony_ci */ 57562306a36Sopenharmony_ciint pwm_adjust_config(struct pwm_device *pwm) 57662306a36Sopenharmony_ci{ 57762306a36Sopenharmony_ci struct pwm_state state; 57862306a36Sopenharmony_ci struct pwm_args pargs; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci pwm_get_args(pwm, &pargs); 58162306a36Sopenharmony_ci pwm_get_state(pwm, &state); 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci /* 58462306a36Sopenharmony_ci * If the current period is zero it means that either the PWM driver 58562306a36Sopenharmony_ci * does not support initial state retrieval or the PWM has not yet 58662306a36Sopenharmony_ci * been configured. 58762306a36Sopenharmony_ci * 58862306a36Sopenharmony_ci * In either case, we setup the new period and polarity, and assign a 58962306a36Sopenharmony_ci * duty cycle of 0. 59062306a36Sopenharmony_ci */ 59162306a36Sopenharmony_ci if (!state.period) { 59262306a36Sopenharmony_ci state.duty_cycle = 0; 59362306a36Sopenharmony_ci state.period = pargs.period; 59462306a36Sopenharmony_ci state.polarity = pargs.polarity; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci return pwm_apply_state(pwm, &state); 59762306a36Sopenharmony_ci } 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci /* 60062306a36Sopenharmony_ci * Adjust the PWM duty cycle/period based on the period value provided 60162306a36Sopenharmony_ci * in PWM args. 60262306a36Sopenharmony_ci */ 60362306a36Sopenharmony_ci if (pargs.period != state.period) { 60462306a36Sopenharmony_ci u64 dutycycle = (u64)state.duty_cycle * pargs.period; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci do_div(dutycycle, state.period); 60762306a36Sopenharmony_ci state.duty_cycle = dutycycle; 60862306a36Sopenharmony_ci state.period = pargs.period; 60962306a36Sopenharmony_ci } 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci /* 61262306a36Sopenharmony_ci * If the polarity changed, we should also change the duty cycle. 61362306a36Sopenharmony_ci */ 61462306a36Sopenharmony_ci if (pargs.polarity != state.polarity) { 61562306a36Sopenharmony_ci state.polarity = pargs.polarity; 61662306a36Sopenharmony_ci state.duty_cycle = state.period - state.duty_cycle; 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci return pwm_apply_state(pwm, &state); 62062306a36Sopenharmony_ci} 62162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pwm_adjust_config); 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_cistatic struct pwm_chip *fwnode_to_pwmchip(struct fwnode_handle *fwnode) 62462306a36Sopenharmony_ci{ 62562306a36Sopenharmony_ci struct pwm_chip *chip; 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci mutex_lock(&pwm_lock); 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci list_for_each_entry(chip, &pwm_chips, list) 63062306a36Sopenharmony_ci if (chip->dev && device_match_fwnode(chip->dev, fwnode)) { 63162306a36Sopenharmony_ci mutex_unlock(&pwm_lock); 63262306a36Sopenharmony_ci return chip; 63362306a36Sopenharmony_ci } 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci mutex_unlock(&pwm_lock); 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci return ERR_PTR(-EPROBE_DEFER); 63862306a36Sopenharmony_ci} 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_cistatic struct device_link *pwm_device_link_add(struct device *dev, 64162306a36Sopenharmony_ci struct pwm_device *pwm) 64262306a36Sopenharmony_ci{ 64362306a36Sopenharmony_ci struct device_link *dl; 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci if (!dev) { 64662306a36Sopenharmony_ci /* 64762306a36Sopenharmony_ci * No device for the PWM consumer has been provided. It may 64862306a36Sopenharmony_ci * impact the PM sequence ordering: the PWM supplier may get 64962306a36Sopenharmony_ci * suspended before the consumer. 65062306a36Sopenharmony_ci */ 65162306a36Sopenharmony_ci dev_warn(pwm->chip->dev, 65262306a36Sopenharmony_ci "No consumer device specified to create a link to\n"); 65362306a36Sopenharmony_ci return NULL; 65462306a36Sopenharmony_ci } 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci dl = device_link_add(dev, pwm->chip->dev, DL_FLAG_AUTOREMOVE_CONSUMER); 65762306a36Sopenharmony_ci if (!dl) { 65862306a36Sopenharmony_ci dev_err(dev, "failed to create device link to %s\n", 65962306a36Sopenharmony_ci dev_name(pwm->chip->dev)); 66062306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci return dl; 66462306a36Sopenharmony_ci} 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci/** 66762306a36Sopenharmony_ci * of_pwm_get() - request a PWM via the PWM framework 66862306a36Sopenharmony_ci * @dev: device for PWM consumer 66962306a36Sopenharmony_ci * @np: device node to get the PWM from 67062306a36Sopenharmony_ci * @con_id: consumer name 67162306a36Sopenharmony_ci * 67262306a36Sopenharmony_ci * Returns the PWM device parsed from the phandle and index specified in the 67362306a36Sopenharmony_ci * "pwms" property of a device tree node or a negative error-code on failure. 67462306a36Sopenharmony_ci * Values parsed from the device tree are stored in the returned PWM device 67562306a36Sopenharmony_ci * object. 67662306a36Sopenharmony_ci * 67762306a36Sopenharmony_ci * If con_id is NULL, the first PWM device listed in the "pwms" property will 67862306a36Sopenharmony_ci * be requested. Otherwise the "pwm-names" property is used to do a reverse 67962306a36Sopenharmony_ci * lookup of the PWM index. This also means that the "pwm-names" property 68062306a36Sopenharmony_ci * becomes mandatory for devices that look up the PWM device via the con_id 68162306a36Sopenharmony_ci * parameter. 68262306a36Sopenharmony_ci * 68362306a36Sopenharmony_ci * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded 68462306a36Sopenharmony_ci * error code on failure. 68562306a36Sopenharmony_ci */ 68662306a36Sopenharmony_cistatic struct pwm_device *of_pwm_get(struct device *dev, struct device_node *np, 68762306a36Sopenharmony_ci const char *con_id) 68862306a36Sopenharmony_ci{ 68962306a36Sopenharmony_ci struct pwm_device *pwm = NULL; 69062306a36Sopenharmony_ci struct of_phandle_args args; 69162306a36Sopenharmony_ci struct device_link *dl; 69262306a36Sopenharmony_ci struct pwm_chip *chip; 69362306a36Sopenharmony_ci int index = 0; 69462306a36Sopenharmony_ci int err; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci if (con_id) { 69762306a36Sopenharmony_ci index = of_property_match_string(np, "pwm-names", con_id); 69862306a36Sopenharmony_ci if (index < 0) 69962306a36Sopenharmony_ci return ERR_PTR(index); 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci err = of_parse_phandle_with_args(np, "pwms", "#pwm-cells", index, 70362306a36Sopenharmony_ci &args); 70462306a36Sopenharmony_ci if (err) { 70562306a36Sopenharmony_ci pr_err("%s(): can't parse \"pwms\" property\n", __func__); 70662306a36Sopenharmony_ci return ERR_PTR(err); 70762306a36Sopenharmony_ci } 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci chip = fwnode_to_pwmchip(of_fwnode_handle(args.np)); 71062306a36Sopenharmony_ci if (IS_ERR(chip)) { 71162306a36Sopenharmony_ci if (PTR_ERR(chip) != -EPROBE_DEFER) 71262306a36Sopenharmony_ci pr_err("%s(): PWM chip not found\n", __func__); 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci pwm = ERR_CAST(chip); 71562306a36Sopenharmony_ci goto put; 71662306a36Sopenharmony_ci } 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci pwm = chip->of_xlate(chip, &args); 71962306a36Sopenharmony_ci if (IS_ERR(pwm)) 72062306a36Sopenharmony_ci goto put; 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci dl = pwm_device_link_add(dev, pwm); 72362306a36Sopenharmony_ci if (IS_ERR(dl)) { 72462306a36Sopenharmony_ci /* of_xlate ended up calling pwm_request_from_chip() */ 72562306a36Sopenharmony_ci pwm_put(pwm); 72662306a36Sopenharmony_ci pwm = ERR_CAST(dl); 72762306a36Sopenharmony_ci goto put; 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci /* 73162306a36Sopenharmony_ci * If a consumer name was not given, try to look it up from the 73262306a36Sopenharmony_ci * "pwm-names" property if it exists. Otherwise use the name of 73362306a36Sopenharmony_ci * the user device node. 73462306a36Sopenharmony_ci */ 73562306a36Sopenharmony_ci if (!con_id) { 73662306a36Sopenharmony_ci err = of_property_read_string_index(np, "pwm-names", index, 73762306a36Sopenharmony_ci &con_id); 73862306a36Sopenharmony_ci if (err < 0) 73962306a36Sopenharmony_ci con_id = np->name; 74062306a36Sopenharmony_ci } 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci pwm->label = con_id; 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ciput: 74562306a36Sopenharmony_ci of_node_put(args.np); 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci return pwm; 74862306a36Sopenharmony_ci} 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci/** 75162306a36Sopenharmony_ci * acpi_pwm_get() - request a PWM via parsing "pwms" property in ACPI 75262306a36Sopenharmony_ci * @fwnode: firmware node to get the "pwms" property from 75362306a36Sopenharmony_ci * 75462306a36Sopenharmony_ci * Returns the PWM device parsed from the fwnode and index specified in the 75562306a36Sopenharmony_ci * "pwms" property or a negative error-code on failure. 75662306a36Sopenharmony_ci * Values parsed from the device tree are stored in the returned PWM device 75762306a36Sopenharmony_ci * object. 75862306a36Sopenharmony_ci * 75962306a36Sopenharmony_ci * This is analogous to of_pwm_get() except con_id is not yet supported. 76062306a36Sopenharmony_ci * ACPI entries must look like 76162306a36Sopenharmony_ci * Package () {"pwms", Package () 76262306a36Sopenharmony_ci * { <PWM device reference>, <PWM index>, <PWM period> [, <PWM flags>]}} 76362306a36Sopenharmony_ci * 76462306a36Sopenharmony_ci * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded 76562306a36Sopenharmony_ci * error code on failure. 76662306a36Sopenharmony_ci */ 76762306a36Sopenharmony_cistatic struct pwm_device *acpi_pwm_get(const struct fwnode_handle *fwnode) 76862306a36Sopenharmony_ci{ 76962306a36Sopenharmony_ci struct pwm_device *pwm; 77062306a36Sopenharmony_ci struct fwnode_reference_args args; 77162306a36Sopenharmony_ci struct pwm_chip *chip; 77262306a36Sopenharmony_ci int ret; 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci memset(&args, 0, sizeof(args)); 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci ret = __acpi_node_get_property_reference(fwnode, "pwms", 0, 3, &args); 77762306a36Sopenharmony_ci if (ret < 0) 77862306a36Sopenharmony_ci return ERR_PTR(ret); 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci if (args.nargs < 2) 78162306a36Sopenharmony_ci return ERR_PTR(-EPROTO); 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci chip = fwnode_to_pwmchip(args.fwnode); 78462306a36Sopenharmony_ci if (IS_ERR(chip)) 78562306a36Sopenharmony_ci return ERR_CAST(chip); 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci pwm = pwm_request_from_chip(chip, args.args[0], NULL); 78862306a36Sopenharmony_ci if (IS_ERR(pwm)) 78962306a36Sopenharmony_ci return pwm; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci pwm->args.period = args.args[1]; 79262306a36Sopenharmony_ci pwm->args.polarity = PWM_POLARITY_NORMAL; 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci if (args.nargs > 2 && args.args[2] & PWM_POLARITY_INVERTED) 79562306a36Sopenharmony_ci pwm->args.polarity = PWM_POLARITY_INVERSED; 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_ci return pwm; 79862306a36Sopenharmony_ci} 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci/** 80162306a36Sopenharmony_ci * pwm_add_table() - register PWM device consumers 80262306a36Sopenharmony_ci * @table: array of consumers to register 80362306a36Sopenharmony_ci * @num: number of consumers in table 80462306a36Sopenharmony_ci */ 80562306a36Sopenharmony_civoid pwm_add_table(struct pwm_lookup *table, size_t num) 80662306a36Sopenharmony_ci{ 80762306a36Sopenharmony_ci mutex_lock(&pwm_lookup_lock); 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci while (num--) { 81062306a36Sopenharmony_ci list_add_tail(&table->list, &pwm_lookup_list); 81162306a36Sopenharmony_ci table++; 81262306a36Sopenharmony_ci } 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci mutex_unlock(&pwm_lookup_lock); 81562306a36Sopenharmony_ci} 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci/** 81862306a36Sopenharmony_ci * pwm_remove_table() - unregister PWM device consumers 81962306a36Sopenharmony_ci * @table: array of consumers to unregister 82062306a36Sopenharmony_ci * @num: number of consumers in table 82162306a36Sopenharmony_ci */ 82262306a36Sopenharmony_civoid pwm_remove_table(struct pwm_lookup *table, size_t num) 82362306a36Sopenharmony_ci{ 82462306a36Sopenharmony_ci mutex_lock(&pwm_lookup_lock); 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci while (num--) { 82762306a36Sopenharmony_ci list_del(&table->list); 82862306a36Sopenharmony_ci table++; 82962306a36Sopenharmony_ci } 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci mutex_unlock(&pwm_lookup_lock); 83262306a36Sopenharmony_ci} 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci/** 83562306a36Sopenharmony_ci * pwm_get() - look up and request a PWM device 83662306a36Sopenharmony_ci * @dev: device for PWM consumer 83762306a36Sopenharmony_ci * @con_id: consumer name 83862306a36Sopenharmony_ci * 83962306a36Sopenharmony_ci * Lookup is first attempted using DT. If the device was not instantiated from 84062306a36Sopenharmony_ci * a device tree, a PWM chip and a relative index is looked up via a table 84162306a36Sopenharmony_ci * supplied by board setup code (see pwm_add_table()). 84262306a36Sopenharmony_ci * 84362306a36Sopenharmony_ci * Once a PWM chip has been found the specified PWM device will be requested 84462306a36Sopenharmony_ci * and is ready to be used. 84562306a36Sopenharmony_ci * 84662306a36Sopenharmony_ci * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded 84762306a36Sopenharmony_ci * error code on failure. 84862306a36Sopenharmony_ci */ 84962306a36Sopenharmony_cistruct pwm_device *pwm_get(struct device *dev, const char *con_id) 85062306a36Sopenharmony_ci{ 85162306a36Sopenharmony_ci const struct fwnode_handle *fwnode = dev ? dev_fwnode(dev) : NULL; 85262306a36Sopenharmony_ci const char *dev_id = dev ? dev_name(dev) : NULL; 85362306a36Sopenharmony_ci struct pwm_device *pwm; 85462306a36Sopenharmony_ci struct pwm_chip *chip; 85562306a36Sopenharmony_ci struct device_link *dl; 85662306a36Sopenharmony_ci unsigned int best = 0; 85762306a36Sopenharmony_ci struct pwm_lookup *p, *chosen = NULL; 85862306a36Sopenharmony_ci unsigned int match; 85962306a36Sopenharmony_ci int err; 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci /* look up via DT first */ 86262306a36Sopenharmony_ci if (is_of_node(fwnode)) 86362306a36Sopenharmony_ci return of_pwm_get(dev, to_of_node(fwnode), con_id); 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci /* then lookup via ACPI */ 86662306a36Sopenharmony_ci if (is_acpi_node(fwnode)) { 86762306a36Sopenharmony_ci pwm = acpi_pwm_get(fwnode); 86862306a36Sopenharmony_ci if (!IS_ERR(pwm) || PTR_ERR(pwm) != -ENOENT) 86962306a36Sopenharmony_ci return pwm; 87062306a36Sopenharmony_ci } 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci /* 87362306a36Sopenharmony_ci * We look up the provider in the static table typically provided by 87462306a36Sopenharmony_ci * board setup code. We first try to lookup the consumer device by 87562306a36Sopenharmony_ci * name. If the consumer device was passed in as NULL or if no match 87662306a36Sopenharmony_ci * was found, we try to find the consumer by directly looking it up 87762306a36Sopenharmony_ci * by name. 87862306a36Sopenharmony_ci * 87962306a36Sopenharmony_ci * If a match is found, the provider PWM chip is looked up by name 88062306a36Sopenharmony_ci * and a PWM device is requested using the PWM device per-chip index. 88162306a36Sopenharmony_ci * 88262306a36Sopenharmony_ci * The lookup algorithm was shamelessly taken from the clock 88362306a36Sopenharmony_ci * framework: 88462306a36Sopenharmony_ci * 88562306a36Sopenharmony_ci * We do slightly fuzzy matching here: 88662306a36Sopenharmony_ci * An entry with a NULL ID is assumed to be a wildcard. 88762306a36Sopenharmony_ci * If an entry has a device ID, it must match 88862306a36Sopenharmony_ci * If an entry has a connection ID, it must match 88962306a36Sopenharmony_ci * Then we take the most specific entry - with the following order 89062306a36Sopenharmony_ci * of precedence: dev+con > dev only > con only. 89162306a36Sopenharmony_ci */ 89262306a36Sopenharmony_ci mutex_lock(&pwm_lookup_lock); 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci list_for_each_entry(p, &pwm_lookup_list, list) { 89562306a36Sopenharmony_ci match = 0; 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci if (p->dev_id) { 89862306a36Sopenharmony_ci if (!dev_id || strcmp(p->dev_id, dev_id)) 89962306a36Sopenharmony_ci continue; 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci match += 2; 90262306a36Sopenharmony_ci } 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci if (p->con_id) { 90562306a36Sopenharmony_ci if (!con_id || strcmp(p->con_id, con_id)) 90662306a36Sopenharmony_ci continue; 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci match += 1; 90962306a36Sopenharmony_ci } 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_ci if (match > best) { 91262306a36Sopenharmony_ci chosen = p; 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci if (match != 3) 91562306a36Sopenharmony_ci best = match; 91662306a36Sopenharmony_ci else 91762306a36Sopenharmony_ci break; 91862306a36Sopenharmony_ci } 91962306a36Sopenharmony_ci } 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci mutex_unlock(&pwm_lookup_lock); 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci if (!chosen) 92462306a36Sopenharmony_ci return ERR_PTR(-ENODEV); 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci chip = pwmchip_find_by_name(chosen->provider); 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci /* 92962306a36Sopenharmony_ci * If the lookup entry specifies a module, load the module and retry 93062306a36Sopenharmony_ci * the PWM chip lookup. This can be used to work around driver load 93162306a36Sopenharmony_ci * ordering issues if driver's can't be made to properly support the 93262306a36Sopenharmony_ci * deferred probe mechanism. 93362306a36Sopenharmony_ci */ 93462306a36Sopenharmony_ci if (!chip && chosen->module) { 93562306a36Sopenharmony_ci err = request_module(chosen->module); 93662306a36Sopenharmony_ci if (err == 0) 93762306a36Sopenharmony_ci chip = pwmchip_find_by_name(chosen->provider); 93862306a36Sopenharmony_ci } 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci if (!chip) 94162306a36Sopenharmony_ci return ERR_PTR(-EPROBE_DEFER); 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci pwm = pwm_request_from_chip(chip, chosen->index, con_id ?: dev_id); 94462306a36Sopenharmony_ci if (IS_ERR(pwm)) 94562306a36Sopenharmony_ci return pwm; 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci dl = pwm_device_link_add(dev, pwm); 94862306a36Sopenharmony_ci if (IS_ERR(dl)) { 94962306a36Sopenharmony_ci pwm_put(pwm); 95062306a36Sopenharmony_ci return ERR_CAST(dl); 95162306a36Sopenharmony_ci } 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci pwm->args.period = chosen->period; 95462306a36Sopenharmony_ci pwm->args.polarity = chosen->polarity; 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci return pwm; 95762306a36Sopenharmony_ci} 95862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pwm_get); 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci/** 96162306a36Sopenharmony_ci * pwm_put() - release a PWM device 96262306a36Sopenharmony_ci * @pwm: PWM device 96362306a36Sopenharmony_ci */ 96462306a36Sopenharmony_civoid pwm_put(struct pwm_device *pwm) 96562306a36Sopenharmony_ci{ 96662306a36Sopenharmony_ci if (!pwm) 96762306a36Sopenharmony_ci return; 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci mutex_lock(&pwm_lock); 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci if (!test_and_clear_bit(PWMF_REQUESTED, &pwm->flags)) { 97262306a36Sopenharmony_ci pr_warn("PWM device already freed\n"); 97362306a36Sopenharmony_ci goto out; 97462306a36Sopenharmony_ci } 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci if (pwm->chip->ops->free) 97762306a36Sopenharmony_ci pwm->chip->ops->free(pwm->chip, pwm); 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci pwm_set_chip_data(pwm, NULL); 98062306a36Sopenharmony_ci pwm->label = NULL; 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci module_put(pwm->chip->ops->owner); 98362306a36Sopenharmony_ciout: 98462306a36Sopenharmony_ci mutex_unlock(&pwm_lock); 98562306a36Sopenharmony_ci} 98662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pwm_put); 98762306a36Sopenharmony_ci 98862306a36Sopenharmony_cistatic void devm_pwm_release(void *pwm) 98962306a36Sopenharmony_ci{ 99062306a36Sopenharmony_ci pwm_put(pwm); 99162306a36Sopenharmony_ci} 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci/** 99462306a36Sopenharmony_ci * devm_pwm_get() - resource managed pwm_get() 99562306a36Sopenharmony_ci * @dev: device for PWM consumer 99662306a36Sopenharmony_ci * @con_id: consumer name 99762306a36Sopenharmony_ci * 99862306a36Sopenharmony_ci * This function performs like pwm_get() but the acquired PWM device will 99962306a36Sopenharmony_ci * automatically be released on driver detach. 100062306a36Sopenharmony_ci * 100162306a36Sopenharmony_ci * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded 100262306a36Sopenharmony_ci * error code on failure. 100362306a36Sopenharmony_ci */ 100462306a36Sopenharmony_cistruct pwm_device *devm_pwm_get(struct device *dev, const char *con_id) 100562306a36Sopenharmony_ci{ 100662306a36Sopenharmony_ci struct pwm_device *pwm; 100762306a36Sopenharmony_ci int ret; 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci pwm = pwm_get(dev, con_id); 101062306a36Sopenharmony_ci if (IS_ERR(pwm)) 101162306a36Sopenharmony_ci return pwm; 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci ret = devm_add_action_or_reset(dev, devm_pwm_release, pwm); 101462306a36Sopenharmony_ci if (ret) 101562306a36Sopenharmony_ci return ERR_PTR(ret); 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci return pwm; 101862306a36Sopenharmony_ci} 101962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_pwm_get); 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci/** 102262306a36Sopenharmony_ci * devm_fwnode_pwm_get() - request a resource managed PWM from firmware node 102362306a36Sopenharmony_ci * @dev: device for PWM consumer 102462306a36Sopenharmony_ci * @fwnode: firmware node to get the PWM from 102562306a36Sopenharmony_ci * @con_id: consumer name 102662306a36Sopenharmony_ci * 102762306a36Sopenharmony_ci * Returns the PWM device parsed from the firmware node. See of_pwm_get() and 102862306a36Sopenharmony_ci * acpi_pwm_get() for a detailed description. 102962306a36Sopenharmony_ci * 103062306a36Sopenharmony_ci * Returns: A pointer to the requested PWM device or an ERR_PTR()-encoded 103162306a36Sopenharmony_ci * error code on failure. 103262306a36Sopenharmony_ci */ 103362306a36Sopenharmony_cistruct pwm_device *devm_fwnode_pwm_get(struct device *dev, 103462306a36Sopenharmony_ci struct fwnode_handle *fwnode, 103562306a36Sopenharmony_ci const char *con_id) 103662306a36Sopenharmony_ci{ 103762306a36Sopenharmony_ci struct pwm_device *pwm = ERR_PTR(-ENODEV); 103862306a36Sopenharmony_ci int ret; 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci if (is_of_node(fwnode)) 104162306a36Sopenharmony_ci pwm = of_pwm_get(dev, to_of_node(fwnode), con_id); 104262306a36Sopenharmony_ci else if (is_acpi_node(fwnode)) 104362306a36Sopenharmony_ci pwm = acpi_pwm_get(fwnode); 104462306a36Sopenharmony_ci if (IS_ERR(pwm)) 104562306a36Sopenharmony_ci return pwm; 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci ret = devm_add_action_or_reset(dev, devm_pwm_release, pwm); 104862306a36Sopenharmony_ci if (ret) 104962306a36Sopenharmony_ci return ERR_PTR(ret); 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_ci return pwm; 105262306a36Sopenharmony_ci} 105362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_fwnode_pwm_get); 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS 105662306a36Sopenharmony_cistatic void pwm_dbg_show(struct pwm_chip *chip, struct seq_file *s) 105762306a36Sopenharmony_ci{ 105862306a36Sopenharmony_ci unsigned int i; 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci for (i = 0; i < chip->npwm; i++) { 106162306a36Sopenharmony_ci struct pwm_device *pwm = &chip->pwms[i]; 106262306a36Sopenharmony_ci struct pwm_state state; 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci pwm_get_state(pwm, &state); 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci seq_printf(s, " pwm-%-3d (%-20.20s):", i, pwm->label); 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci if (test_bit(PWMF_REQUESTED, &pwm->flags)) 106962306a36Sopenharmony_ci seq_puts(s, " requested"); 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci if (state.enabled) 107262306a36Sopenharmony_ci seq_puts(s, " enabled"); 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci seq_printf(s, " period: %llu ns", state.period); 107562306a36Sopenharmony_ci seq_printf(s, " duty: %llu ns", state.duty_cycle); 107662306a36Sopenharmony_ci seq_printf(s, " polarity: %s", 107762306a36Sopenharmony_ci state.polarity ? "inverse" : "normal"); 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci if (state.usage_power) 108062306a36Sopenharmony_ci seq_puts(s, " usage_power"); 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci seq_puts(s, "\n"); 108362306a36Sopenharmony_ci } 108462306a36Sopenharmony_ci} 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_cistatic void *pwm_seq_start(struct seq_file *s, loff_t *pos) 108762306a36Sopenharmony_ci{ 108862306a36Sopenharmony_ci mutex_lock(&pwm_lock); 108962306a36Sopenharmony_ci s->private = ""; 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci return seq_list_start(&pwm_chips, *pos); 109262306a36Sopenharmony_ci} 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_cistatic void *pwm_seq_next(struct seq_file *s, void *v, loff_t *pos) 109562306a36Sopenharmony_ci{ 109662306a36Sopenharmony_ci s->private = "\n"; 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci return seq_list_next(v, &pwm_chips, pos); 109962306a36Sopenharmony_ci} 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_cistatic void pwm_seq_stop(struct seq_file *s, void *v) 110262306a36Sopenharmony_ci{ 110362306a36Sopenharmony_ci mutex_unlock(&pwm_lock); 110462306a36Sopenharmony_ci} 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_cistatic int pwm_seq_show(struct seq_file *s, void *v) 110762306a36Sopenharmony_ci{ 110862306a36Sopenharmony_ci struct pwm_chip *chip = list_entry(v, struct pwm_chip, list); 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci seq_printf(s, "%s%s/%s, %d PWM device%s\n", (char *)s->private, 111162306a36Sopenharmony_ci chip->dev->bus ? chip->dev->bus->name : "no-bus", 111262306a36Sopenharmony_ci dev_name(chip->dev), chip->npwm, 111362306a36Sopenharmony_ci (chip->npwm != 1) ? "s" : ""); 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci pwm_dbg_show(chip, s); 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci return 0; 111862306a36Sopenharmony_ci} 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_cistatic const struct seq_operations pwm_debugfs_sops = { 112162306a36Sopenharmony_ci .start = pwm_seq_start, 112262306a36Sopenharmony_ci .next = pwm_seq_next, 112362306a36Sopenharmony_ci .stop = pwm_seq_stop, 112462306a36Sopenharmony_ci .show = pwm_seq_show, 112562306a36Sopenharmony_ci}; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ciDEFINE_SEQ_ATTRIBUTE(pwm_debugfs); 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_cistatic int __init pwm_debugfs_init(void) 113062306a36Sopenharmony_ci{ 113162306a36Sopenharmony_ci debugfs_create_file("pwm", 0444, NULL, NULL, &pwm_debugfs_fops); 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci return 0; 113462306a36Sopenharmony_ci} 113562306a36Sopenharmony_cisubsys_initcall(pwm_debugfs_init); 113662306a36Sopenharmony_ci#endif /* CONFIG_DEBUG_FS */ 1137