brintos

brintos / linux-shallow public Read only

0
0
Text · 26.3 KiB · 0ffc259 Raw
1107 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2024 Linaro Ltd.4 */5 6#include <linux/bug.h>7#include <linux/cleanup.h>8#include <linux/debugfs.h>9#include <linux/device.h>10#include <linux/err.h>11#include <linux/export.h>12#include <linux/idr.h>13#include <linux/kernel.h>14#include <linux/kref.h>15#include <linux/list.h>16#include <linux/lockdep.h>17#include <linux/module.h>18#include <linux/mutex.h>19#include <linux/property.h>20#include <linux/pwrseq/consumer.h>21#include <linux/pwrseq/provider.h>22#include <linux/radix-tree.h>23#include <linux/rwsem.h>24#include <linux/slab.h>25 26/*27 * Power-sequencing framework for linux.28 *29 * This subsystem allows power sequence providers to register a set of targets30 * that consumers may request and power-up/down.31 *32 * Glossary:33 *34 * Unit - a unit is a discreet chunk of a power sequence. For instance one unit35 * may enable a set of regulators, another may enable a specific GPIO. Units36 * can define dependencies in the form of other units that must be enabled37 * before it itself can be.38 *39 * Target - a target is a set of units (composed of the "final" unit and its40 * dependencies) that a consumer selects by its name when requesting a handle41 * to the power sequencer. Via the dependency system, multiple targets may42 * share the same parts of a power sequence but ignore parts that are43 * irrelevant.44 *45 * Descriptor - a handle passed by the pwrseq core to every consumer that46 * serves as the entry point to the provider layer. It ensures coherence47 * between different users and keeps reference counting consistent.48 *49 * Each provider must define a .match() callback whose role is to determine50 * whether a potential consumer is in fact associated with this sequencer.51 * This allows creating abstraction layers on top of regular device-tree52 * resources like regulators, clocks and other nodes connected to the consumer53 * via phandle.54 */55 56static DEFINE_IDA(pwrseq_ida);57 58/*59 * Protects the device list on the pwrseq bus from concurrent modifications60 * but allows simultaneous read-only access.61 */62static DECLARE_RWSEM(pwrseq_sem);63 64/**65 * struct pwrseq_unit - Private power-sequence unit data.66 * @ref: Reference count for this object. When it goes to 0, the object is67 *       destroyed.68 * @name: Name of this target.69 * @list: Link to siblings on the list of all units of a single sequencer.70 * @deps: List of units on which this unit depends.71 * @enable: Callback running the part of the power-on sequence provided by72 *          this unit.73 * @disable: Callback running the part of the power-off sequence provided74 *           by this unit.75 * @enable_count: Current number of users that enabled this unit. May be the76 *                consumer of the power sequencer or other units that depend77 *                on this one.78 */79struct pwrseq_unit {80	struct kref ref;81	const char *name;82	struct list_head list;83	struct list_head deps;84	pwrseq_power_state_func enable;85	pwrseq_power_state_func disable;86	unsigned int enable_count;87};88 89static struct pwrseq_unit *pwrseq_unit_new(const struct pwrseq_unit_data *data)90{91	struct pwrseq_unit *unit;92 93	unit = kzalloc(sizeof(*unit), GFP_KERNEL);94	if (!unit)95		return NULL;96 97	unit->name = kstrdup_const(data->name, GFP_KERNEL);98	if (!unit->name) {99		kfree(unit);100		return NULL;101	}102 103	kref_init(&unit->ref);104	INIT_LIST_HEAD(&unit->deps);105	unit->enable = data->enable;106	unit->disable = data->disable;107 108	return unit;109}110 111static struct pwrseq_unit *pwrseq_unit_get(struct pwrseq_unit *unit)112{113	kref_get(&unit->ref);114 115	return unit;116}117 118static void pwrseq_unit_release(struct kref *ref);119 120static void pwrseq_unit_put(struct pwrseq_unit *unit)121{122	kref_put(&unit->ref, pwrseq_unit_release);123}124 125/**126 * struct pwrseq_unit_dep - Wrapper around a reference to the unit structure127 *                          allowing to keep it on multiple dependency lists128 *                          in different units.129 * @list: Siblings on the list.130 * @unit: Address of the referenced unit.131 */132struct pwrseq_unit_dep {133	struct list_head list;134	struct pwrseq_unit *unit;135};136 137static struct pwrseq_unit_dep *pwrseq_unit_dep_new(struct pwrseq_unit *unit)138{139	struct pwrseq_unit_dep *dep;140 141	dep = kzalloc(sizeof(*dep), GFP_KERNEL);142	if (!dep)143		return NULL;144 145	dep->unit = unit;146 147	return dep;148}149 150static void pwrseq_unit_dep_free(struct pwrseq_unit_dep *ref)151{152	pwrseq_unit_put(ref->unit);153	kfree(ref);154}155 156static void pwrseq_unit_free_deps(struct list_head *list)157{158	struct pwrseq_unit_dep *dep, *next;159 160	list_for_each_entry_safe(dep, next, list, list) {161		list_del(&dep->list);162		pwrseq_unit_dep_free(dep);163	}164}165 166static void pwrseq_unit_release(struct kref *ref)167{168	struct pwrseq_unit *unit = container_of(ref, struct pwrseq_unit, ref);169 170	pwrseq_unit_free_deps(&unit->deps);171	list_del(&unit->list);172	kfree_const(unit->name);173	kfree(unit);174}175 176/**177 * struct pwrseq_target - Private power-sequence target data.178 * @list: Siblings on the list of all targets exposed by a power sequencer.179 * @name: Name of the target.180 * @unit: Final unit for this target.181 * @post_enable: Callback run after the target unit has been enabled, *after*182 *               the state lock has been released. It's useful for implementing183 *               boot-up delays without blocking other users from powering up184 *               using the same power sequencer.185 */186struct pwrseq_target {187	struct list_head list;188	const char *name;189	struct pwrseq_unit *unit;190	pwrseq_power_state_func post_enable;191};192 193static struct pwrseq_target *194pwrseq_target_new(const struct pwrseq_target_data *data)195{196	struct pwrseq_target *target;197 198	target = kzalloc(sizeof(*target), GFP_KERNEL);199	if (!target)200		return NULL;201 202	target->name = kstrdup_const(data->name, GFP_KERNEL);203	if (!target->name) {204		kfree(target);205		return NULL;206	}207 208	target->post_enable = data->post_enable;209 210	return target;211}212 213static void pwrseq_target_free(struct pwrseq_target *target)214{215	if (!IS_ERR_OR_NULL(target->unit))216		pwrseq_unit_put(target->unit);217	kfree_const(target->name);218	kfree(target);219}220 221/**222 * struct pwrseq_device - Private power sequencing data.223 * @dev: Device struct associated with this sequencer.224 * @id: Device ID.225 * @owner: Prevents removal of active power sequencing providers.226 * @rw_lock: Protects the device from being unregistered while in use.227 * @state_lock: Prevents multiple users running the power sequence at the same228 *              time.229 * @match: Power sequencer matching callback.230 * @targets: List of targets exposed by this sequencer.231 * @units: List of all units supported by this sequencer.232 */233struct pwrseq_device {234	struct device dev;235	int id;236	struct module *owner;237	struct rw_semaphore rw_lock;238	struct mutex state_lock;239	pwrseq_match_func match;240	struct list_head targets;241	struct list_head units;242};243 244static struct pwrseq_device *to_pwrseq_device(struct device *dev)245{246	return container_of(dev, struct pwrseq_device, dev);247}248 249static struct pwrseq_device *pwrseq_device_get(struct pwrseq_device *pwrseq)250{251	get_device(&pwrseq->dev);252 253	return pwrseq;254}255 256static void pwrseq_device_put(struct pwrseq_device *pwrseq)257{258	put_device(&pwrseq->dev);259}260 261/**262 * struct pwrseq_desc - Wraps access to the pwrseq_device and ensures that one263 *                      user cannot break the reference counting for others.264 * @pwrseq: Reference to the power sequencing device.265 * @target: Reference to the target this descriptor allows to control.266 * @powered_on: Power state set by the holder of the descriptor (not necessarily267 * corresponding to the actual power state of the device).268 */269struct pwrseq_desc {270	struct pwrseq_device *pwrseq;271	struct pwrseq_target *target;272	bool powered_on;273};274 275static const struct bus_type pwrseq_bus = {276	.name = "pwrseq",277};278 279static void pwrseq_release(struct device *dev)280{281	struct pwrseq_device *pwrseq = to_pwrseq_device(dev);282	struct pwrseq_target *target, *pos;283 284	list_for_each_entry_safe(target, pos, &pwrseq->targets, list) {285		list_del(&target->list);286		pwrseq_target_free(target);287	}288 289	mutex_destroy(&pwrseq->state_lock);290	ida_free(&pwrseq_ida, pwrseq->id);291	kfree(pwrseq);292}293 294static const struct device_type pwrseq_device_type = {295	.name = "power_sequencer",296	.release = pwrseq_release,297};298 299static int pwrseq_check_unit_deps(const struct pwrseq_unit_data *data,300				  struct radix_tree_root *visited_units)301{302	const struct pwrseq_unit_data *tmp, **cur;303	int ret;304 305	ret = radix_tree_insert(visited_units, (unsigned long)data,306				(void *)data);307	if (ret)308		return ret;309 310	for (cur = data->deps; cur && *cur; cur++) {311		tmp = radix_tree_lookup(visited_units, (unsigned long)*cur);312		if (tmp) {313			WARN(1, "Circular dependency in power sequencing flow detected!\n");314			return -EINVAL;315		}316 317		ret = pwrseq_check_unit_deps(*cur, visited_units);318		if (ret)319			return ret;320	}321 322	return 0;323}324 325static int pwrseq_check_target_deps(const struct pwrseq_target_data *data)326{327	struct radix_tree_root visited_units;328	struct radix_tree_iter iter;329	void __rcu **slot;330	int ret;331 332	if (!data->unit)333		return -EINVAL;334 335	INIT_RADIX_TREE(&visited_units, GFP_KERNEL);336	ret = pwrseq_check_unit_deps(data->unit, &visited_units);337	radix_tree_for_each_slot(slot, &visited_units, &iter, 0)338		radix_tree_delete(&visited_units, iter.index);339 340	return ret;341}342 343static int pwrseq_unit_setup_deps(const struct pwrseq_unit_data **data,344				  struct list_head *dep_list,345				  struct list_head *unit_list,346				  struct radix_tree_root *processed_units);347 348static struct pwrseq_unit *349pwrseq_unit_setup(const struct pwrseq_unit_data *data,350		  struct list_head *unit_list,351		  struct radix_tree_root *processed_units)352{353	struct pwrseq_unit *unit;354	int ret;355 356	unit = radix_tree_lookup(processed_units, (unsigned long)data);357	if (unit)358		return pwrseq_unit_get(unit);359 360	unit = pwrseq_unit_new(data);361	if (!unit)362		return ERR_PTR(-ENOMEM);363 364	if (data->deps) {365		ret = pwrseq_unit_setup_deps(data->deps, &unit->deps,366					     unit_list, processed_units);367		if (ret) {368			pwrseq_unit_put(unit);369			return ERR_PTR(ret);370		}371	}372 373	ret = radix_tree_insert(processed_units, (unsigned long)data, unit);374	if (ret) {375		pwrseq_unit_put(unit);376		return ERR_PTR(ret);377	}378 379	list_add_tail(&unit->list, unit_list);380 381	return unit;382}383 384static int pwrseq_unit_setup_deps(const struct pwrseq_unit_data **data,385				  struct list_head *dep_list,386				  struct list_head *unit_list,387				  struct radix_tree_root *processed_units)388{389	const struct pwrseq_unit_data *pos;390	struct pwrseq_unit_dep *dep;391	struct pwrseq_unit *unit;392	int i;393 394	for (i = 0; data[i]; i++) {395		pos = data[i];396 397		unit = pwrseq_unit_setup(pos, unit_list, processed_units);398		if (IS_ERR(unit))399			return PTR_ERR(unit);400 401		dep = pwrseq_unit_dep_new(unit);402		if (!dep) {403			pwrseq_unit_put(unit);404			return -ENOMEM;405		}406 407		list_add_tail(&dep->list, dep_list);408	}409 410	return 0;411}412 413static int pwrseq_do_setup_targets(const struct pwrseq_target_data **data,414				   struct pwrseq_device *pwrseq,415				   struct radix_tree_root *processed_units)416{417	const struct pwrseq_target_data *pos;418	struct pwrseq_target *target;419	int ret, i;420 421	for (i = 0; data[i]; i++) {422		pos = data[i];423 424		ret = pwrseq_check_target_deps(pos);425		if (ret)426			return ret;427 428		target = pwrseq_target_new(pos);429		if (!target)430			return -ENOMEM;431 432		target->unit = pwrseq_unit_setup(pos->unit, &pwrseq->units,433						 processed_units);434		if (IS_ERR(target->unit)) {435			ret = PTR_ERR(target->unit);436			pwrseq_target_free(target);437			return ret;438		}439 440		list_add_tail(&target->list, &pwrseq->targets);441	}442 443	return 0;444}445 446static int pwrseq_setup_targets(const struct pwrseq_target_data **targets,447				struct pwrseq_device *pwrseq)448{449	struct radix_tree_root processed_units;450	struct radix_tree_iter iter;451	void __rcu **slot;452	int ret;453 454	INIT_RADIX_TREE(&processed_units, GFP_KERNEL);455	ret = pwrseq_do_setup_targets(targets, pwrseq, &processed_units);456	radix_tree_for_each_slot(slot, &processed_units, &iter, 0)457		radix_tree_delete(&processed_units, iter.index);458 459	return ret;460}461 462/**463 * pwrseq_device_register() - Register a new power sequencer.464 * @config: Configuration of the new power sequencing device.465 *466 * The config structure is only used during the call and can be freed after467 * the function returns. The config structure *must* have the parent device468 * as well as the match() callback and at least one target set.469 *470 * Returns:471 * Returns the address of the new pwrseq device or ERR_PTR() on failure.472 */473struct pwrseq_device *474pwrseq_device_register(const struct pwrseq_config *config)475{476	struct pwrseq_device *pwrseq;477	int ret, id;478 479	if (!config->parent || !config->match || !config->targets ||480	    !config->targets[0])481		return ERR_PTR(-EINVAL);482 483	pwrseq = kzalloc(sizeof(*pwrseq), GFP_KERNEL);484	if (!pwrseq)485		return ERR_PTR(-ENOMEM);486 487	pwrseq->dev.type = &pwrseq_device_type;488	pwrseq->dev.bus = &pwrseq_bus;489	pwrseq->dev.parent = config->parent;490	device_set_node(&pwrseq->dev, dev_fwnode(config->parent));491	dev_set_drvdata(&pwrseq->dev, config->drvdata);492 493	id = ida_alloc(&pwrseq_ida, GFP_KERNEL);494	if (id < 0) {495		kfree(pwrseq);496		return ERR_PTR(id);497	}498 499	pwrseq->id = id;500 501	/*502	 * From this point onwards the device's release() callback is503	 * responsible for freeing resources.504	 */505	device_initialize(&pwrseq->dev);506 507	ret = dev_set_name(&pwrseq->dev, "pwrseq.%d", pwrseq->id);508	if (ret)509		goto err_put_pwrseq;510 511	pwrseq->owner = config->owner ?: THIS_MODULE;512	pwrseq->match = config->match;513 514	init_rwsem(&pwrseq->rw_lock);515	mutex_init(&pwrseq->state_lock);516	INIT_LIST_HEAD(&pwrseq->targets);517	INIT_LIST_HEAD(&pwrseq->units);518 519	ret = pwrseq_setup_targets(config->targets, pwrseq);520	if (ret)521		goto err_put_pwrseq;522 523	scoped_guard(rwsem_write, &pwrseq_sem) {524		ret = device_add(&pwrseq->dev);525		if (ret)526			goto err_put_pwrseq;527	}528 529	return pwrseq;530 531err_put_pwrseq:532	pwrseq_device_put(pwrseq);533	return ERR_PTR(ret);534}535EXPORT_SYMBOL_GPL(pwrseq_device_register);536 537/**538 * pwrseq_device_unregister() - Unregister the power sequencer.539 * @pwrseq: Power sequencer to unregister.540 */541void pwrseq_device_unregister(struct pwrseq_device *pwrseq)542{543	struct device *dev = &pwrseq->dev;544	struct pwrseq_target *target;545 546	scoped_guard(mutex, &pwrseq->state_lock) {547		guard(rwsem_write)(&pwrseq->rw_lock);548 549		list_for_each_entry(target, &pwrseq->targets, list)550			WARN(target->unit->enable_count,551			     "REMOVING POWER SEQUENCER WITH ACTIVE USERS\n");552 553		guard(rwsem_write)(&pwrseq_sem);554 555		device_del(dev);556	}557 558	pwrseq_device_put(pwrseq);559}560EXPORT_SYMBOL_GPL(pwrseq_device_unregister);561 562static void devm_pwrseq_device_unregister(void *data)563{564	struct pwrseq_device *pwrseq = data;565 566	pwrseq_device_unregister(pwrseq);567}568 569/**570 * devm_pwrseq_device_register() - Managed variant of pwrseq_device_register().571 * @dev: Managing device.572 * @config: Configuration of the new power sequencing device.573 *574 * Returns:575 * Returns the address of the new pwrseq device or ERR_PTR() on failure.576 */577struct pwrseq_device *578devm_pwrseq_device_register(struct device *dev,579			    const struct pwrseq_config *config)580{581	struct pwrseq_device *pwrseq;582	int ret;583 584	pwrseq = pwrseq_device_register(config);585	if (IS_ERR(pwrseq))586		return pwrseq;587 588	ret = devm_add_action_or_reset(dev, devm_pwrseq_device_unregister,589				       pwrseq);590	if (ret)591		return ERR_PTR(ret);592 593	return pwrseq;594}595EXPORT_SYMBOL_GPL(devm_pwrseq_device_register);596 597/**598 * pwrseq_device_get_drvdata() - Get the driver private data associated with599 *                               this sequencer.600 * @pwrseq: Power sequencer object.601 *602 * Returns:603 * Address of the private driver data.604 */605void *pwrseq_device_get_drvdata(struct pwrseq_device *pwrseq)606{607	return dev_get_drvdata(&pwrseq->dev);608}609EXPORT_SYMBOL_GPL(pwrseq_device_get_drvdata);610 611struct pwrseq_match_data {612	struct pwrseq_desc *desc;613	struct device *dev;614	const char *target;615};616 617static int pwrseq_match_device(struct device *pwrseq_dev, void *data)618{619	struct pwrseq_device *pwrseq = to_pwrseq_device(pwrseq_dev);620	struct pwrseq_match_data *match_data = data;621	struct pwrseq_target *target;622	int ret;623 624	lockdep_assert_held_read(&pwrseq_sem);625 626	guard(rwsem_read)(&pwrseq->rw_lock);627	if (!device_is_registered(&pwrseq->dev))628		return 0;629 630	ret = pwrseq->match(pwrseq, match_data->dev);631	if (ret <= 0)632		return ret;633 634	/* We got the matching device, let's find the right target. */635	list_for_each_entry(target, &pwrseq->targets, list) {636		if (strcmp(target->name, match_data->target))637			continue;638 639		match_data->desc->target = target;640	}641 642	/*643	 * This device does not have this target. No point in deferring as it644	 * will not get a new target dynamically later.645	 */646	if (!match_data->desc->target)647		return -ENOENT;648 649	if (!try_module_get(pwrseq->owner))650		return -EPROBE_DEFER;651 652	match_data->desc->pwrseq = pwrseq_device_get(pwrseq);653 654	return 1;655}656 657/**658 * pwrseq_get() - Get the power sequencer associated with this device.659 * @dev: Device for which to get the sequencer.660 * @target: Name of the target exposed by the sequencer this device wants to661 *          reach.662 *663 * Returns:664 * New power sequencer descriptor for use by the consumer driver or ERR_PTR()665 * on failure.666 */667struct pwrseq_desc *pwrseq_get(struct device *dev, const char *target)668{669	struct pwrseq_match_data match_data;670	int ret;671 672	struct pwrseq_desc *desc __free(kfree) = kzalloc(sizeof(*desc),673							 GFP_KERNEL);674	if (!desc)675		return ERR_PTR(-ENOMEM);676 677	match_data.desc = desc;678	match_data.dev = dev;679	match_data.target = target;680 681	guard(rwsem_read)(&pwrseq_sem);682 683	ret = bus_for_each_dev(&pwrseq_bus, NULL, &match_data,684			       pwrseq_match_device);685	if (ret < 0)686		return ERR_PTR(ret);687	if (ret == 0)688		/* No device matched. */689		return ERR_PTR(-EPROBE_DEFER);690 691	return_ptr(desc);692}693EXPORT_SYMBOL_GPL(pwrseq_get);694 695/**696 * pwrseq_put() - Release the power sequencer descriptor.697 * @desc: Descriptor to release.698 */699void pwrseq_put(struct pwrseq_desc *desc)700{701	struct pwrseq_device *pwrseq;702 703	if (!desc)704		return;705 706	pwrseq = desc->pwrseq;707 708	if (desc->powered_on)709		pwrseq_power_off(desc);710 711	kfree(desc);712	module_put(pwrseq->owner);713	pwrseq_device_put(pwrseq);714}715EXPORT_SYMBOL_GPL(pwrseq_put);716 717static void devm_pwrseq_put(void *data)718{719	struct pwrseq_desc *desc = data;720 721	pwrseq_put(desc);722}723 724/**725 * devm_pwrseq_get() - Managed variant of pwrseq_get().726 * @dev: Device for which to get the sequencer and which also manages its727 *       lifetime.728 * @target: Name of the target exposed by the sequencer this device wants to729 *          reach.730 *731 * Returns:732 * New power sequencer descriptor for use by the consumer driver or ERR_PTR()733 * on failure.734 */735struct pwrseq_desc *devm_pwrseq_get(struct device *dev, const char *target)736{737	struct pwrseq_desc *desc;738	int ret;739 740	desc = pwrseq_get(dev, target);741	if (IS_ERR(desc))742		return desc;743 744	ret = devm_add_action_or_reset(dev, devm_pwrseq_put, desc);745	if (ret)746		return ERR_PTR(ret);747 748	return desc;749}750EXPORT_SYMBOL_GPL(devm_pwrseq_get);751 752static int pwrseq_unit_enable(struct pwrseq_device *pwrseq,753			      struct pwrseq_unit *target);754static int pwrseq_unit_disable(struct pwrseq_device *pwrseq,755			       struct pwrseq_unit *target);756 757static int pwrseq_unit_enable_deps(struct pwrseq_device *pwrseq,758				   struct list_head *list)759{760	struct pwrseq_unit_dep *pos;761	int ret = 0;762 763	list_for_each_entry(pos, list, list) {764		ret = pwrseq_unit_enable(pwrseq, pos->unit);765		if (ret) {766			list_for_each_entry_continue_reverse(pos, list, list)767				pwrseq_unit_disable(pwrseq, pos->unit);768			break;769		}770	}771 772	return ret;773}774 775static int pwrseq_unit_disable_deps(struct pwrseq_device *pwrseq,776				    struct list_head *list)777{778	struct pwrseq_unit_dep *pos;779	int ret = 0;780 781	list_for_each_entry_reverse(pos, list, list) {782		ret = pwrseq_unit_disable(pwrseq, pos->unit);783		if (ret) {784			list_for_each_entry_continue(pos, list, list)785				pwrseq_unit_enable(pwrseq, pos->unit);786			break;787		}788	}789 790	return ret;791}792 793static int pwrseq_unit_enable(struct pwrseq_device *pwrseq,794			      struct pwrseq_unit *unit)795{796	int ret;797 798	lockdep_assert_held_read(&pwrseq->rw_lock);799	lockdep_assert_held(&pwrseq->state_lock);800 801	if (unit->enable_count != 0) {802		unit->enable_count++;803		return 0;804	}805 806	ret = pwrseq_unit_enable_deps(pwrseq, &unit->deps);807	if (ret) {808		dev_err(&pwrseq->dev,809			"Failed to enable dependencies before power-on for target '%s': %d\n",810			unit->name, ret);811		return ret;812	}813 814	if (unit->enable) {815		ret = unit->enable(pwrseq);816		if (ret) {817			dev_err(&pwrseq->dev,818				"Failed to enable target '%s': %d\n",819				unit->name, ret);820			pwrseq_unit_disable_deps(pwrseq, &unit->deps);821			return ret;822		}823	}824 825	unit->enable_count++;826 827	return 0;828}829 830static int pwrseq_unit_disable(struct pwrseq_device *pwrseq,831			       struct pwrseq_unit *unit)832{833	int ret;834 835	lockdep_assert_held_read(&pwrseq->rw_lock);836	lockdep_assert_held(&pwrseq->state_lock);837 838	if (unit->enable_count == 0) {839		WARN(1, "Unmatched power-off for target '%s'\n",840		     unit->name);841		return -EBUSY;842	}843 844	if (unit->enable_count != 1) {845		unit->enable_count--;846		return 0;847	}848 849	if (unit->disable) {850		ret = unit->disable(pwrseq);851		if (ret) {852			dev_err(&pwrseq->dev,853				"Failed to disable target '%s': %d\n",854				unit->name, ret);855			return ret;856		}857	}858 859	ret = pwrseq_unit_disable_deps(pwrseq, &unit->deps);860	if (ret) {861		dev_err(&pwrseq->dev,862			"Failed to disable dependencies after power-off for target '%s': %d\n",863			unit->name, ret);864		if (unit->enable)865			unit->enable(pwrseq);866		return ret;867	}868 869	unit->enable_count--;870 871	return 0;872}873 874/**875 * pwrseq_power_on() - Issue a power-on request on behalf of the consumer876 *                     device.877 * @desc: Descriptor referencing the power sequencer.878 *879 * This function tells the power sequencer that the consumer wants to be880 * powered-up. The sequencer may already have powered-up the device in which881 * case the function returns 0. If the power-up sequence is already in882 * progress, the function will block until it's done and return 0. If this is883 * the first request, the device will be powered up.884 *885 * Returns:886 * 0 on success, negative error number on failure.887 */888int pwrseq_power_on(struct pwrseq_desc *desc)889{890	struct pwrseq_device *pwrseq;891	struct pwrseq_target *target;892	struct pwrseq_unit *unit;893	int ret;894 895	might_sleep();896 897	if (!desc || desc->powered_on)898		return 0;899 900	pwrseq = desc->pwrseq;901	target = desc->target;902	unit = target->unit;903 904	guard(rwsem_read)(&pwrseq->rw_lock);905	if (!device_is_registered(&pwrseq->dev))906		return -ENODEV;907 908	scoped_guard(mutex, &pwrseq->state_lock) {909		ret = pwrseq_unit_enable(pwrseq, unit);910		if (!ret)911			desc->powered_on = true;912	}913 914	if (target->post_enable) {915		ret = target->post_enable(pwrseq);916		if (ret) {917			pwrseq_unit_disable(pwrseq, unit);918			desc->powered_on = false;919		}920	}921 922	return ret;923}924EXPORT_SYMBOL_GPL(pwrseq_power_on);925 926/**927 * pwrseq_power_off() - Issue a power-off request on behalf of the consumer928 *                      device.929 * @desc: Descriptor referencing the power sequencer.930 *931 * This undoes the effects of pwrseq_power_on(). It issues a power-off request932 * on behalf of the consumer and when the last remaining user does so, the933 * power-down sequence will be started. If one is in progress, the function934 * will block until it's complete and then return.935 *936 * Returns:937 * 0 on success, negative error number on failure.938 */939int pwrseq_power_off(struct pwrseq_desc *desc)940{941	struct pwrseq_device *pwrseq;942	struct pwrseq_unit *unit;943	int ret;944 945	might_sleep();946 947	if (!desc || !desc->powered_on)948		return 0;949 950	pwrseq = desc->pwrseq;951	unit = desc->target->unit;952 953	guard(rwsem_read)(&pwrseq->rw_lock);954	if (!device_is_registered(&pwrseq->dev))955		return -ENODEV;956 957	guard(mutex)(&pwrseq->state_lock);958 959	ret = pwrseq_unit_disable(pwrseq, unit);960	if (!ret)961		desc->powered_on = false;962 963	return ret;964}965EXPORT_SYMBOL_GPL(pwrseq_power_off);966 967#if IS_ENABLED(CONFIG_DEBUG_FS)968 969struct pwrseq_debugfs_count_ctx {970	struct device *dev;971	loff_t index;972};973 974static int pwrseq_debugfs_seq_count(struct device *dev, void *data)975{976	struct pwrseq_debugfs_count_ctx *ctx = data;977 978	ctx->dev = dev;979 980	return ctx->index-- ? 0 : 1;981}982 983static void *pwrseq_debugfs_seq_start(struct seq_file *seq, loff_t *pos)984{985	struct pwrseq_debugfs_count_ctx ctx;986 987	ctx.dev = NULL;988	ctx.index = *pos;989 990	/*991	 * We're holding the lock for the entire printout so no need to fiddle992	 * with device reference count.993	 */994	down_read(&pwrseq_sem);995 996	bus_for_each_dev(&pwrseq_bus, NULL, &ctx, pwrseq_debugfs_seq_count);997	if (!ctx.index)998		return NULL;999 1000	return ctx.dev;1001}1002 1003static void *pwrseq_debugfs_seq_next(struct seq_file *seq, void *data,1004				     loff_t *pos)1005{1006	struct device *curr = data;1007 1008	++*pos;1009 1010	struct device *next __free(put_device) =1011			bus_find_next_device(&pwrseq_bus, curr);1012	return next;1013}1014 1015static void pwrseq_debugfs_seq_show_target(struct seq_file *seq,1016					   struct pwrseq_target *target)1017{1018	seq_printf(seq, "    target: [%s] (target unit: [%s])\n",1019		   target->name, target->unit->name);1020}1021 1022static void pwrseq_debugfs_seq_show_unit(struct seq_file *seq,1023					 struct pwrseq_unit *unit)1024{1025	struct pwrseq_unit_dep *ref;1026 1027	seq_printf(seq, "    unit: [%s] - enable count: %u\n",1028		   unit->name, unit->enable_count);1029 1030	if (list_empty(&unit->deps))1031		return;1032 1033	seq_puts(seq, "      dependencies:\n");1034	list_for_each_entry(ref, &unit->deps, list)1035		seq_printf(seq, "        [%s]\n", ref->unit->name);1036}1037 1038static int pwrseq_debugfs_seq_show(struct seq_file *seq, void *data)1039{1040	struct device *dev = data;1041	struct pwrseq_device *pwrseq = to_pwrseq_device(dev);1042	struct pwrseq_target *target;1043	struct pwrseq_unit *unit;1044 1045	seq_printf(seq, "%s:\n", dev_name(dev));1046 1047	seq_puts(seq, "  targets:\n");1048	list_for_each_entry(target, &pwrseq->targets, list)1049		pwrseq_debugfs_seq_show_target(seq, target);1050 1051	seq_puts(seq, "  units:\n");1052	list_for_each_entry(unit, &pwrseq->units, list)1053		pwrseq_debugfs_seq_show_unit(seq, unit);1054 1055	return 0;1056}1057 1058static void pwrseq_debugfs_seq_stop(struct seq_file *seq, void *data)1059{1060	up_read(&pwrseq_sem);1061}1062 1063static const struct seq_operations pwrseq_debugfs_sops = {1064	.start = pwrseq_debugfs_seq_start,1065	.next = pwrseq_debugfs_seq_next,1066	.show = pwrseq_debugfs_seq_show,1067	.stop = pwrseq_debugfs_seq_stop,1068};1069DEFINE_SEQ_ATTRIBUTE(pwrseq_debugfs);1070 1071static struct dentry *pwrseq_debugfs_dentry;1072 1073#endif /* CONFIG_DEBUG_FS */1074 1075static int __init pwrseq_init(void)1076{1077	int ret;1078 1079	ret = bus_register(&pwrseq_bus);1080	if (ret) {1081		pr_err("Failed to register the power sequencer bus\n");1082		return ret;1083	}1084 1085#if IS_ENABLED(CONFIG_DEBUG_FS)1086	pwrseq_debugfs_dentry = debugfs_create_file("pwrseq", 0444, NULL, NULL,1087						    &pwrseq_debugfs_fops);1088#endif  /* CONFIG_DEBUG_FS */1089 1090	return 0;1091}1092subsys_initcall(pwrseq_init);1093 1094static void __exit pwrseq_exit(void)1095{1096#if IS_ENABLED(CONFIG_DEBUG_FS)1097	debugfs_remove_recursive(pwrseq_debugfs_dentry);1098#endif  /* CONFIG_DEBUG_FS */1099 1100	bus_unregister(&pwrseq_bus);1101}1102module_exit(pwrseq_exit);1103 1104MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>");1105MODULE_DESCRIPTION("Power Sequencing subsystem core");1106MODULE_LICENSE("GPL");1107