power: sequencing: implement the pwrseq core
Implement the power sequencing subsystem allowing devices to share complex powering-up and down procedures. It's split into the consumer and provider parts but does not implement any new DT bindings so that the actual power sequencing is never revealed in the DT representation. Tested-by: Amit Pundir <amit.pundir@linaro.org> Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD, SM8650-QRD & SM8650-HDK Tested-by: Caleb Connolly <caleb.connolly@linaro.org> # OnePlus 8T Acked-by: Krzysztof Kozlowski <krzk@kernel.org> Link: https://lore.kernel.org/r/20240605123850.24857-2-brgl@bgdev.pl Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This commit is contained in:
parent
83a7eefedc
commit
249ebf3f65
@ -17890,6 +17890,14 @@ F: include/linux/pm_*
|
||||
F: include/linux/powercap.h
|
||||
F: kernel/configs/nopm.config
|
||||
|
||||
POWER SEQUENCING
|
||||
M: Bartosz Golaszewski <brgl@bgdev.pl>
|
||||
L: linux-pm@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux.git
|
||||
F: drivers/power/sequencing/
|
||||
F: include/linux/pwrseq/
|
||||
|
||||
POWER STATE COORDINATION INTERFACE (PSCI)
|
||||
M: Mark Rutland <mark.rutland@arm.com>
|
||||
M: Lorenzo Pieralisi <lpieralisi@kernel.org>
|
||||
|
@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
source "drivers/power/reset/Kconfig"
|
||||
source "drivers/power/sequencing/Kconfig"
|
||||
source "drivers/power/supply/Kconfig"
|
||||
|
@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_POWER_RESET) += reset/
|
||||
obj-$(CONFIG_POWER_SEQUENCING) += sequencing/
|
||||
obj-$(CONFIG_POWER_SUPPLY) += supply/
|
||||
|
12
drivers/power/sequencing/Kconfig
Normal file
12
drivers/power/sequencing/Kconfig
Normal file
@ -0,0 +1,12 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
menuconfig POWER_SEQUENCING
|
||||
tristate "Power Sequencing support"
|
||||
help
|
||||
Say Y here to enable the Power Sequencing subsystem.
|
||||
|
||||
This subsystem is designed to control power to devices that share
|
||||
complex resources and/or require specific power sequences to be run
|
||||
during power-up.
|
||||
|
||||
If unsure, say no.
|
4
drivers/power/sequencing/Makefile
Normal file
4
drivers/power/sequencing/Makefile
Normal file
@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
obj-$(CONFIG_POWER_SEQUENCING) += pwrseq-core.o
|
||||
pwrseq-core-y := core.o
|
1105
drivers/power/sequencing/core.c
Normal file
1105
drivers/power/sequencing/core.c
Normal file
File diff suppressed because it is too large
Load Diff
56
include/linux/pwrseq/consumer.h
Normal file
56
include/linux/pwrseq/consumer.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2024 Linaro Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __POWER_SEQUENCING_CONSUMER_H__
|
||||
#define __POWER_SEQUENCING_CONSUMER_H__
|
||||
|
||||
#include <linux/err.h>
|
||||
|
||||
struct device;
|
||||
struct pwrseq_desc;
|
||||
|
||||
#if IS_ENABLED(CONFIG_POWER_SEQUENCING)
|
||||
|
||||
struct pwrseq_desc * __must_check
|
||||
pwrseq_get(struct device *dev, const char *target);
|
||||
void pwrseq_put(struct pwrseq_desc *desc);
|
||||
|
||||
struct pwrseq_desc * __must_check
|
||||
devm_pwrseq_get(struct device *dev, const char *target);
|
||||
|
||||
int pwrseq_power_on(struct pwrseq_desc *desc);
|
||||
int pwrseq_power_off(struct pwrseq_desc *desc);
|
||||
|
||||
#else /* CONFIG_POWER_SEQUENCING */
|
||||
|
||||
static inline struct pwrseq_desc * __must_check
|
||||
pwrseq_get(struct device *dev, const char *target)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline void pwrseq_put(struct pwrseq_desc *desc)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct pwrseq_desc * __must_check
|
||||
devm_pwrseq_get(struct device *dev, const char *target)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline int pwrseq_power_on(struct pwrseq_desc *desc)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int pwrseq_power_off(struct pwrseq_desc *desc)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_POWER_SEQUENCING */
|
||||
|
||||
#endif /* __POWER_SEQUENCING_CONSUMER_H__ */
|
75
include/linux/pwrseq/provider.h
Normal file
75
include/linux/pwrseq/provider.h
Normal file
@ -0,0 +1,75 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2024 Linaro Ltd.
|
||||
*/
|
||||
|
||||
#ifndef __POWER_SEQUENCING_PROVIDER_H__
|
||||
#define __POWER_SEQUENCING_PROVIDER_H__
|
||||
|
||||
struct device;
|
||||
struct module;
|
||||
struct pwrseq_device;
|
||||
|
||||
typedef int (*pwrseq_power_state_func)(struct pwrseq_device *);
|
||||
typedef int (*pwrseq_match_func)(struct pwrseq_device *, struct device *);
|
||||
|
||||
/**
|
||||
* struct pwrseq_unit_data - Configuration of a single power sequencing
|
||||
* unit.
|
||||
* @name: Name of the unit.
|
||||
* @deps: Units that must be enabled before this one and disabled after it
|
||||
* in the order they come in this array. Must be NULL-terminated.
|
||||
* @enable: Callback running the part of the power-on sequence provided by
|
||||
* this unit.
|
||||
* @disable: Callback running the part of the power-off sequence provided
|
||||
* by this unit.
|
||||
*/
|
||||
struct pwrseq_unit_data {
|
||||
const char *name;
|
||||
const struct pwrseq_unit_data **deps;
|
||||
pwrseq_power_state_func enable;
|
||||
pwrseq_power_state_func disable;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pwrseq_target_data - Configuration of a power sequencing target.
|
||||
* @name: Name of the target.
|
||||
* @unit: Final unit that this target must reach in order to be considered
|
||||
* enabled.
|
||||
* @post_enable: Callback run after the target unit has been enabled, *after*
|
||||
* the state lock has been released. It's useful for implementing
|
||||
* boot-up delays without blocking other users from powering up
|
||||
* using the same power sequencer.
|
||||
*/
|
||||
struct pwrseq_target_data {
|
||||
const char *name;
|
||||
const struct pwrseq_unit_data *unit;
|
||||
pwrseq_power_state_func post_enable;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct pwrseq_config - Configuration used for registering a new provider.
|
||||
* @parent: Parent device for the sequencer. Must be set.
|
||||
* @owner: Module providing this device.
|
||||
* @drvdata: Private driver data.
|
||||
* @match: Provider callback used to match the consumer device to the sequencer.
|
||||
* @targets: Array of targets for this power sequencer. Must be NULL-terminated.
|
||||
*/
|
||||
struct pwrseq_config {
|
||||
struct device *parent;
|
||||
struct module *owner;
|
||||
void *drvdata;
|
||||
pwrseq_match_func match;
|
||||
const struct pwrseq_target_data **targets;
|
||||
};
|
||||
|
||||
struct pwrseq_device *
|
||||
pwrseq_device_register(const struct pwrseq_config *config);
|
||||
void pwrseq_device_unregister(struct pwrseq_device *pwrseq);
|
||||
struct pwrseq_device *
|
||||
devm_pwrseq_device_register(struct device *dev,
|
||||
const struct pwrseq_config *config);
|
||||
|
||||
void *pwrseq_device_get_drvdata(struct pwrseq_device *pwrseq);
|
||||
|
||||
#endif /* __POWER_SEQUENCING_PROVIDER_H__ */
|
Loading…
Reference in New Issue
Block a user