mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
power sequencing updates for v7.2-rc1
Power Sequencing core:
- Add a helper allowing consumers to access the struct device object
associated with a pwrseq provider
- Print the power sequencing device's parent in debugfs to add more
debugging information
Driver updates:
- Extend/rework the M.2 power sequencing driver in order to allow it to
support more M.2 cards, not just WCN7850
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEkeUTLeW1Rh17omX8BZ0uy/82hMMFAmovtaoACgkQBZ0uy/82
hMMd+Q/9GRUyh5GW5PPZfWYxTps7riq7frye71DSg8ldUbWggaQcVGn04zjA8r09
+w6uwPzq8Bnkzi8x4ZhKSJk7qsj9FHNJzOp6B/+j6aeE7vTV4X7QAHnF57Wa4R2L
rae0Ub3AyqXzzyquDufuwND8HL8vTsbrxK3yYRCn9s2LjHyI7pZUUdo6K2t8nduu
Hlw9rCWJjom7s2kJuFakoPf6K+KVieMWm5xp5j6vy1CYrgAiN27R2mLMG53fjLND
LUhaoIyQM/Vly2Dtwe3GaqIbx74qBb41AWBMWkcTIn16q7YKonHg/3+sz3EVH2qE
w0/fch4codv5Ldvu/M1IRtOeGzrS5InbwpGr67VBbHZMOvHXacKoEHDrk5vmX3uA
Yr7G61R2NDtd1DQjkYTLETAzxQgzh14AB9VIwJT5b1yQaDAoEzdHSlYIUpLcQn1z
MleZVwcYBJplDTWR4wsn9QsQFgIXoL9f58hcTvETQwzJJArgH8zOnH1enyZxIvT6
fpQJivGAixyt/t8GUtUTnhHpTdr1ZNe7LAncKmVGM6ITw9n8w4JhpkspFyMp+TQW
HajdZHEeHwP4kvQ5WzuTlpSyprPqnGWrMkuWzoNzAXpXOZP2+QAjMX0nHTegqRv8
ysEhBiD3QpfPZuV6yPmHj4cbVIXH9lIAjodRvWKylYCFGzEPLYk=
=Hwkw
-----END PGP SIGNATURE-----
Merge tag 'pwrseq-updates-for-v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull power sequencing updates from Bartosz Golaszewski:
"A set of extensions to the M.2 pwrseq driver allowing it to work with
more cards than just the one from Qualcomm we supported initially.
There's also a tweak to debugfs output and a new function that will be
used by a bluetooth driver in the next cycle.
Power Sequencing core:
- Add a helper allowing consumers to access the struct device object
associated with a pwrseq provider
- Print the power sequencing device's parent in debugfs to add more
debugging information
Driver updates:
- Extend/rework the M.2 power sequencing driver in order to allow it
to support more M.2 cards, not just WCN7850"
* tag 'pwrseq-updates-for-v7.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux:
power: sequencing: pcie-m2: Add PCI ID 0x1103 for WCN6855 Bluetooth
power: sequencing: Add an API to return the pwrseq device's 'dev' pointer
power: sequencing: pcie-m2: Create BT node based on the pci_device_id[] table
power: sequencing: pcie-m2: Create serdev for PCI devices present before probe
power: sequencing: pcie-m2: Improve PCI device ID check
power: sequencing: pcie-m2: Allow creating serdev for multiple PCI devices
power: sequencing: pcie-m2: Fix inconsistent function prefixes
power: sequencing: print power sequencing device parent in debugfs
This commit is contained in:
commit
31e6aeafcd
|
|
@ -965,6 +965,29 @@ int pwrseq_power_off(struct pwrseq_desc *desc)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(pwrseq_power_off);
|
||||
|
||||
/**
|
||||
* pwrseq_to_device() - Get the pwrseq device pointer from a descriptor.
|
||||
* @desc: Descriptor referencing the power sequencer.
|
||||
*
|
||||
* Return the 'dev' pointer of the power sequencer device associated with @desc.
|
||||
* Consumer drivers can use this to query the pwrseq provider's device tree
|
||||
* node, for example to check for the existence of specific properties.
|
||||
*
|
||||
* Since pwrseq_get() already takes a reference to the pwrseq device, this
|
||||
* function does not take an additional reference.
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to the pwrseq struct device, or NULL if @desc is NULL.
|
||||
*/
|
||||
struct device *pwrseq_to_device(struct pwrseq_desc *desc)
|
||||
{
|
||||
if (!desc)
|
||||
return NULL;
|
||||
|
||||
return &desc->pwrseq->dev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pwrseq_to_device);
|
||||
|
||||
#if IS_ENABLED(CONFIG_DEBUG_FS)
|
||||
|
||||
struct pwrseq_debugfs_count_ctx {
|
||||
|
|
@ -1043,7 +1066,7 @@ static int pwrseq_debugfs_seq_show(struct seq_file *seq, void *data)
|
|||
struct pwrseq_target *target;
|
||||
struct pwrseq_unit *unit;
|
||||
|
||||
seq_printf(seq, "%s:\n", dev_name(dev));
|
||||
seq_printf(seq, "%s (%s):\n", dev_name(dev), dev_name(dev->parent));
|
||||
|
||||
seq_puts(seq, " targets:\n");
|
||||
list_for_each_entry(target, &pwrseq->targets, list)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
|
|
@ -19,6 +20,13 @@
|
|||
#include <linux/serdev.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct pwrseq_pci_dev {
|
||||
struct serdev_device *serdev;
|
||||
struct of_changeset *ocs;
|
||||
struct pci_dev *pdev;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
struct pwrseq_pcie_m2_pdata {
|
||||
const struct pwrseq_target_data **targets;
|
||||
};
|
||||
|
|
@ -32,9 +40,9 @@ struct pwrseq_pcie_m2_ctx {
|
|||
struct notifier_block nb;
|
||||
struct gpio_desc *w_disable1_gpio;
|
||||
struct gpio_desc *w_disable2_gpio;
|
||||
struct serdev_device *serdev;
|
||||
struct of_changeset *ocs;
|
||||
struct device *dev;
|
||||
struct list_head pci_devices;
|
||||
struct mutex list_lock;
|
||||
};
|
||||
|
||||
static int pwrseq_pcie_m2_vregs_enable(struct pwrseq_device *pwrseq)
|
||||
|
|
@ -177,39 +185,57 @@ static int pwrseq_pcie_m2_match(struct pwrseq_device *pwrseq,
|
|||
return PWRSEQ_NO_MATCH;
|
||||
}
|
||||
|
||||
static int pwrseq_m2_pcie_create_bt_node(struct pwrseq_pcie_m2_ctx *ctx,
|
||||
struct device_node *parent)
|
||||
static const struct pci_device_id pwrseq_m2_pci_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x1107),
|
||||
.driver_data = (kernel_ulong_t)"qcom,wcn7850-bt" },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x1103),
|
||||
.driver_data = (kernel_ulong_t)"qcom,wcn6855-bt" },
|
||||
{ } /* Sentinel */
|
||||
};
|
||||
|
||||
static int pwrseq_pcie_m2_create_bt_node(struct pwrseq_pcie_m2_ctx *ctx,
|
||||
struct pwrseq_pci_dev *pci_dev,
|
||||
struct device_node *parent,
|
||||
struct pci_dev *pdev)
|
||||
{
|
||||
const struct pci_device_id *id;
|
||||
struct device *dev = ctx->dev;
|
||||
const char *compatible;
|
||||
struct device_node *np;
|
||||
int ret;
|
||||
|
||||
ctx->ocs = kzalloc_obj(*ctx->ocs);
|
||||
if (!ctx->ocs)
|
||||
id = pci_match_id(pwrseq_m2_pci_ids, pdev);
|
||||
if (WARN_ON_ONCE(!id)) /* Shouldn't happen */
|
||||
return -ENODEV;
|
||||
|
||||
compatible = (const char *)id->driver_data;
|
||||
|
||||
pci_dev->ocs = kzalloc_obj(*pci_dev->ocs);
|
||||
if (!pci_dev->ocs)
|
||||
return -ENOMEM;
|
||||
|
||||
of_changeset_init(ctx->ocs);
|
||||
of_changeset_init(pci_dev->ocs);
|
||||
|
||||
np = of_changeset_create_node(ctx->ocs, parent, "bluetooth");
|
||||
np = of_changeset_create_node(pci_dev->ocs, parent, "bluetooth");
|
||||
if (!np) {
|
||||
dev_err(dev, "Failed to create bluetooth node\n");
|
||||
ret = -ENODEV;
|
||||
goto err_destroy_changeset;
|
||||
}
|
||||
|
||||
ret = of_changeset_add_prop_string(ctx->ocs, np, "compatible", "qcom,wcn7850-bt");
|
||||
ret = of_changeset_add_prop_string(pci_dev->ocs, np, "compatible", compatible);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to add bluetooth compatible: %d\n", ret);
|
||||
goto err_destroy_changeset;
|
||||
}
|
||||
|
||||
ret = of_changeset_apply(ctx->ocs);
|
||||
ret = of_changeset_apply(pci_dev->ocs);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to apply changeset: %d\n", ret);
|
||||
goto err_destroy_changeset;
|
||||
}
|
||||
|
||||
ret = device_add_of_node(&ctx->serdev->dev, np);
|
||||
ret = device_add_of_node(&pci_dev->serdev->dev, np);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to add OF node: %d\n", ret);
|
||||
goto err_revert_changeset;
|
||||
|
|
@ -218,19 +244,21 @@ static int pwrseq_m2_pcie_create_bt_node(struct pwrseq_pcie_m2_ctx *ctx,
|
|||
return 0;
|
||||
|
||||
err_revert_changeset:
|
||||
of_changeset_revert(ctx->ocs);
|
||||
of_changeset_revert(pci_dev->ocs);
|
||||
err_destroy_changeset:
|
||||
of_changeset_destroy(ctx->ocs);
|
||||
kfree(ctx->ocs);
|
||||
ctx->ocs = NULL;
|
||||
of_changeset_destroy(pci_dev->ocs);
|
||||
kfree(pci_dev->ocs);
|
||||
pci_dev->ocs = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pwrseq_pcie_m2_create_serdev(struct pwrseq_pcie_m2_ctx *ctx)
|
||||
static int pwrseq_pcie_m2_create_serdev_one(struct pwrseq_pcie_m2_ctx *ctx,
|
||||
struct pci_dev *pdev)
|
||||
{
|
||||
struct serdev_controller *serdev_ctrl;
|
||||
struct device *dev = ctx->dev;
|
||||
struct pwrseq_pci_dev *pci_dev;
|
||||
int ret;
|
||||
|
||||
struct device_node *serdev_parent __free(device_node) =
|
||||
|
|
@ -248,58 +276,100 @@ static int pwrseq_pcie_m2_create_serdev(struct pwrseq_pcie_m2_ctx *ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ctx->serdev = serdev_device_alloc(serdev_ctrl);
|
||||
if (!ctx->serdev) {
|
||||
/* Bail out if the serdev device was already created for the PCI dev */
|
||||
scoped_guard(mutex, &ctx->list_lock) {
|
||||
list_for_each_entry(pci_dev, &ctx->pci_devices, list) {
|
||||
if (pci_dev->pdev == pdev)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
pci_dev = kzalloc(sizeof(*pci_dev), GFP_KERNEL);
|
||||
if (!pci_dev) {
|
||||
ret = -ENOMEM;
|
||||
goto err_put_ctrl;
|
||||
}
|
||||
|
||||
ret = pwrseq_m2_pcie_create_bt_node(ctx, serdev_parent);
|
||||
pci_dev->serdev = serdev_device_alloc(serdev_ctrl);
|
||||
if (!pci_dev->serdev) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_pci_dev;
|
||||
}
|
||||
|
||||
ret = pwrseq_pcie_m2_create_bt_node(ctx, pci_dev, serdev_parent, pdev);
|
||||
if (ret)
|
||||
goto err_free_serdev;
|
||||
|
||||
ret = serdev_device_add(ctx->serdev);
|
||||
ret = serdev_device_add(pci_dev->serdev);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to add serdev for WCN7850: %d\n", ret);
|
||||
dev_err(dev, "Failed to add serdev for PCI device (%s): %d\n",
|
||||
pci_name(pdev), ret);
|
||||
goto err_free_dt_node;
|
||||
}
|
||||
|
||||
serdev_controller_put(serdev_ctrl);
|
||||
|
||||
pci_dev->pdev = pci_dev_get(pdev);
|
||||
|
||||
mutex_lock(&ctx->list_lock);
|
||||
list_add_tail(&pci_dev->list, &ctx->pci_devices);
|
||||
mutex_unlock(&ctx->list_lock);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_dt_node:
|
||||
device_remove_of_node(&ctx->serdev->dev);
|
||||
of_changeset_revert(ctx->ocs);
|
||||
of_changeset_destroy(ctx->ocs);
|
||||
kfree(ctx->ocs);
|
||||
ctx->ocs = NULL;
|
||||
device_remove_of_node(&pci_dev->serdev->dev);
|
||||
of_changeset_revert(pci_dev->ocs);
|
||||
of_changeset_destroy(pci_dev->ocs);
|
||||
kfree(pci_dev->ocs);
|
||||
pci_dev->ocs = NULL;
|
||||
err_free_serdev:
|
||||
serdev_device_put(ctx->serdev);
|
||||
ctx->serdev = NULL;
|
||||
serdev_device_put(pci_dev->serdev);
|
||||
pci_dev->serdev = NULL;
|
||||
err_free_pci_dev:
|
||||
kfree(pci_dev);
|
||||
err_put_ctrl:
|
||||
serdev_controller_put(serdev_ctrl);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void pwrseq_pcie_m2_remove_serdev(struct pwrseq_pcie_m2_ctx *ctx)
|
||||
static void __pwrseq_pcie_m2_remove_serdev(struct pwrseq_pcie_m2_ctx *ctx,
|
||||
struct pwrseq_pci_dev *pci_dev)
|
||||
{
|
||||
if (ctx->serdev) {
|
||||
device_remove_of_node(&ctx->serdev->dev);
|
||||
serdev_device_remove(ctx->serdev);
|
||||
ctx->serdev = NULL;
|
||||
if (pci_dev->serdev) {
|
||||
device_remove_of_node(&pci_dev->serdev->dev);
|
||||
serdev_device_remove(pci_dev->serdev);
|
||||
}
|
||||
|
||||
if (ctx->ocs) {
|
||||
of_changeset_revert(ctx->ocs);
|
||||
of_changeset_destroy(ctx->ocs);
|
||||
kfree(ctx->ocs);
|
||||
ctx->ocs = NULL;
|
||||
if (pci_dev->ocs) {
|
||||
of_changeset_revert(pci_dev->ocs);
|
||||
of_changeset_destroy(pci_dev->ocs);
|
||||
kfree(pci_dev->ocs);
|
||||
}
|
||||
|
||||
pci_dev_put(pci_dev->pdev);
|
||||
list_del(&pci_dev->list);
|
||||
kfree(pci_dev);
|
||||
}
|
||||
|
||||
static int pwrseq_m2_pcie_notify(struct notifier_block *nb, unsigned long action,
|
||||
static void pwrseq_pcie_m2_remove_serdev(struct pwrseq_pcie_m2_ctx *ctx,
|
||||
struct pci_dev *pdev)
|
||||
{
|
||||
struct pwrseq_pci_dev *pci_dev, *tmp;
|
||||
|
||||
mutex_lock(&ctx->list_lock);
|
||||
list_for_each_entry_safe(pci_dev, tmp, &ctx->pci_devices, list) {
|
||||
if (!pdev || pci_dev->pdev == pdev) {
|
||||
__pwrseq_pcie_m2_remove_serdev(ctx, pci_dev);
|
||||
if (pdev)
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&ctx->list_lock);
|
||||
}
|
||||
|
||||
static int pwrseq_pcie_m2_notify(struct notifier_block *nb, unsigned long action,
|
||||
void *data)
|
||||
{
|
||||
struct pwrseq_pcie_m2_ctx *ctx = container_of(nb, struct pwrseq_pcie_m2_ctx, nb);
|
||||
|
|
@ -318,17 +388,15 @@ static int pwrseq_m2_pcie_notify(struct notifier_block *nb, unsigned long action
|
|||
|
||||
switch (action) {
|
||||
case BUS_NOTIFY_ADD_DEVICE:
|
||||
/* Create serdev device for WCN7850 */
|
||||
if (pdev->vendor == PCI_VENDOR_ID_QCOM && pdev->device == 0x1107) {
|
||||
ret = pwrseq_pcie_m2_create_serdev(ctx);
|
||||
if (pci_match_id(pwrseq_m2_pci_ids, pdev)) {
|
||||
ret = pwrseq_pcie_m2_create_serdev_one(ctx, pdev);
|
||||
if (ret)
|
||||
return notifier_from_errno(ret);
|
||||
}
|
||||
break;
|
||||
case BUS_NOTIFY_REMOVED_DEVICE:
|
||||
/* Destroy serdev device for WCN7850 */
|
||||
if (pdev->vendor == PCI_VENDOR_ID_QCOM && pdev->device == 0x1107)
|
||||
pwrseq_pcie_m2_remove_serdev(ctx);
|
||||
if (pci_match_id(pwrseq_m2_pci_ids, pdev))
|
||||
pwrseq_pcie_m2_remove_serdev(ctx, pdev);
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -353,7 +421,7 @@ static bool pwrseq_pcie_m2_check_remote_node(struct device *dev, u8 port, u8 end
|
|||
* protocol device needs to be created manually with the help of the notifier
|
||||
* of the discoverable bus like PCIe.
|
||||
*/
|
||||
static int pwrseq_pcie_m2_register_notifier(struct pwrseq_pcie_m2_ctx *ctx, struct device *dev)
|
||||
static int pwrseq_pcie_m2_register_notifier(struct pwrseq_pcie_m2_ctx *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
|
@ -361,18 +429,56 @@ static int pwrseq_pcie_m2_register_notifier(struct pwrseq_pcie_m2_ctx *ctx, stru
|
|||
* Register a PCI notifier for Key E connector that has PCIe as Port
|
||||
* 0/Endpoint 0 interface and Serial as Port 3/Endpoint 0 interface.
|
||||
*/
|
||||
if (pwrseq_pcie_m2_check_remote_node(dev, 3, 0, "serial")) {
|
||||
if (pwrseq_pcie_m2_check_remote_node(dev, 0, 0, "pcie")) {
|
||||
ctx->dev = dev;
|
||||
ctx->nb.notifier_call = pwrseq_m2_pcie_notify;
|
||||
ret = bus_register_notifier(&pci_bus_type, &ctx->nb);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Failed to register notifier for serdev\n");
|
||||
if (!pwrseq_pcie_m2_check_remote_node(ctx->dev, 3, 0, "serial") ||
|
||||
!pwrseq_pcie_m2_check_remote_node(ctx->dev, 0, 0, "pcie"))
|
||||
return 0;
|
||||
|
||||
ctx->nb.notifier_call = pwrseq_pcie_m2_notify;
|
||||
ret = bus_register_notifier(&pci_bus_type, &ctx->nb);
|
||||
if (ret)
|
||||
return dev_err_probe(ctx->dev, ret,
|
||||
"Failed to register notifier for serdev\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pwrseq_pcie_m2_create_serdev(struct pwrseq_pcie_m2_ctx *ctx)
|
||||
{
|
||||
struct pci_dev *pdev = NULL;
|
||||
int ret;
|
||||
|
||||
if (!pwrseq_pcie_m2_check_remote_node(ctx->dev, 3, 0, "serial") ||
|
||||
!pwrseq_pcie_m2_check_remote_node(ctx->dev, 0, 0, "pcie"))
|
||||
return 0;
|
||||
|
||||
struct device_node *pci_parent __free(device_node) =
|
||||
of_graph_get_remote_node(dev_of_node(ctx->dev), 0, 0);
|
||||
if (!pci_parent)
|
||||
return 0;
|
||||
|
||||
/* Create serdev for existing PCI devices if required */
|
||||
for_each_pci_dev(pdev) {
|
||||
if (!pdev->dev.parent || pci_parent != pdev->dev.parent->of_node)
|
||||
continue;
|
||||
|
||||
if (!pci_match_id(pwrseq_m2_pci_ids, pdev))
|
||||
continue;
|
||||
|
||||
ret = pwrseq_pcie_m2_create_serdev_one(ctx, pdev);
|
||||
if (ret) {
|
||||
dev_err_probe(ctx->dev, ret,
|
||||
"Failed to create serdev for PCI device (%s)\n",
|
||||
pci_name(pdev));
|
||||
pci_dev_put(pdev);
|
||||
goto err_remove_serdev;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_remove_serdev:
|
||||
pwrseq_pcie_m2_remove_serdev(ctx, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pwrseq_pcie_m2_probe(struct platform_device *pdev)
|
||||
|
|
@ -432,16 +538,29 @@ static int pwrseq_pcie_m2_probe(struct platform_device *pdev)
|
|||
goto err_free_regulators;
|
||||
}
|
||||
|
||||
mutex_init(&ctx->list_lock);
|
||||
INIT_LIST_HEAD(&ctx->pci_devices);
|
||||
ctx->dev = dev;
|
||||
|
||||
/* Create serdev for available PCI devices (if required) */
|
||||
ret = pwrseq_pcie_m2_create_serdev(ctx);
|
||||
if (ret)
|
||||
goto err_destroy_mutex;
|
||||
|
||||
/*
|
||||
* Register a notifier for creating protocol devices for
|
||||
* non-discoverable busses like UART.
|
||||
*/
|
||||
ret = pwrseq_pcie_m2_register_notifier(ctx, dev);
|
||||
ret = pwrseq_pcie_m2_register_notifier(ctx);
|
||||
if (ret)
|
||||
goto err_free_regulators;
|
||||
goto err_remove_serdev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_remove_serdev:
|
||||
pwrseq_pcie_m2_remove_serdev(ctx, NULL);
|
||||
err_destroy_mutex:
|
||||
mutex_destroy(&ctx->list_lock);
|
||||
err_free_regulators:
|
||||
regulator_bulk_free(ctx->num_vregs, ctx->regs);
|
||||
|
||||
|
|
@ -453,7 +572,8 @@ static void pwrseq_pcie_m2_remove(struct platform_device *pdev)
|
|||
struct pwrseq_pcie_m2_ctx *ctx = platform_get_drvdata(pdev);
|
||||
|
||||
bus_unregister_notifier(&pci_bus_type, &ctx->nb);
|
||||
pwrseq_pcie_m2_remove_serdev(ctx);
|
||||
pwrseq_pcie_m2_remove_serdev(ctx, NULL);
|
||||
mutex_destroy(&ctx->list_lock);
|
||||
|
||||
regulator_bulk_free(ctx->num_vregs, ctx->regs);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ 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);
|
||||
|
||||
struct device *pwrseq_to_device(struct pwrseq_desc *desc);
|
||||
|
||||
#else /* CONFIG_POWER_SEQUENCING */
|
||||
|
||||
static inline struct pwrseq_desc * __must_check
|
||||
|
|
@ -51,6 +53,11 @@ static inline int pwrseq_power_off(struct pwrseq_desc *desc)
|
|||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline struct device *pwrseq_to_device(struct pwrseq_desc *desc)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_POWER_SEQUENCING */
|
||||
|
||||
#endif /* __POWER_SEQUENCING_CONSUMER_H__ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user