1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2024 Linaro Ltd. 4 * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> 5 */ 6 7 #include <linux/device.h> 8 #include <linux/mod_devicetable.h> 9 #include <linux/module.h> 10 #include <linux/pci-pwrctrl.h> 11 #include <linux/platform_device.h> 12 #include <linux/regulator/consumer.h> 13 #include <linux/slab.h> 14 15 struct pci_pwrctrl_slot_data { 16 struct pci_pwrctrl ctx; 17 struct regulator_bulk_data *supplies; 18 int num_supplies; 19 }; 20 21 static void devm_pci_pwrctrl_slot_power_off(void *data) 22 { 23 struct pci_pwrctrl_slot_data *slot = data; 24 25 regulator_bulk_disable(slot->num_supplies, slot->supplies); 26 regulator_bulk_free(slot->num_supplies, slot->supplies); 27 } 28 29 static int pci_pwrctrl_slot_probe(struct platform_device *pdev) 30 { 31 struct pci_pwrctrl_slot_data *slot; 32 struct device *dev = &pdev->dev; 33 int ret; 34 35 slot = devm_kzalloc(dev, sizeof(*slot), GFP_KERNEL); 36 if (!slot) 37 return -ENOMEM; 38 39 ret = of_regulator_bulk_get_all(dev, dev_of_node(dev), 40 &slot->supplies); 41 if (ret < 0) { 42 dev_err_probe(dev, ret, "Failed to get slot regulators\n"); 43 return ret; 44 } 45 46 slot->num_supplies = ret; 47 ret = regulator_bulk_enable(slot->num_supplies, slot->supplies); 48 if (ret < 0) { 49 dev_err_probe(dev, ret, "Failed to enable slot regulators\n"); 50 goto err_regulator_free; 51 } 52 53 ret = devm_add_action_or_reset(dev, devm_pci_pwrctrl_slot_power_off, 54 slot); 55 if (ret) 56 goto err_regulator_disable; 57 58 pci_pwrctrl_init(&slot->ctx, dev); 59 60 ret = devm_pci_pwrctrl_device_set_ready(dev, &slot->ctx); 61 if (ret) 62 return dev_err_probe(dev, ret, "Failed to register pwrctrl driver\n"); 63 64 return 0; 65 66 err_regulator_disable: 67 regulator_bulk_disable(slot->num_supplies, slot->supplies); 68 err_regulator_free: 69 regulator_bulk_free(slot->num_supplies, slot->supplies); 70 71 return ret; 72 } 73 74 static const struct of_device_id pci_pwrctrl_slot_of_match[] = { 75 { 76 .compatible = "pciclass,0604", 77 }, 78 { } 79 }; 80 MODULE_DEVICE_TABLE(of, pci_pwrctrl_slot_of_match); 81 82 static struct platform_driver pci_pwrctrl_slot_driver = { 83 .driver = { 84 .name = "pci-pwrctrl-slot", 85 .of_match_table = pci_pwrctrl_slot_of_match, 86 }, 87 .probe = pci_pwrctrl_slot_probe, 88 }; 89 module_platform_driver(pci_pwrctrl_slot_driver); 90 91 MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>"); 92 MODULE_DESCRIPTION("Generic PCI Power Control driver for PCI Slots"); 93 MODULE_LICENSE("GPL"); 94