1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2024 Linaro Ltd. 4 */ 5 6 #include <linux/device.h> 7 #include <linux/mod_devicetable.h> 8 #include <linux/module.h> 9 #include <linux/of.h> 10 #include <linux/pci-pwrctrl.h> 11 #include <linux/platform_device.h> 12 #include <linux/pwrseq/consumer.h> 13 #include <linux/slab.h> 14 #include <linux/types.h> 15 16 struct pci_pwrctl_pwrseq_data { 17 struct pci_pwrctl ctx; 18 struct pwrseq_desc *pwrseq; 19 }; 20 21 static void devm_pci_pwrctl_pwrseq_power_off(void *data) 22 { 23 struct pwrseq_desc *pwrseq = data; 24 25 pwrseq_power_off(pwrseq); 26 } 27 28 static int pci_pwrctl_pwrseq_probe(struct platform_device *pdev) 29 { 30 struct pci_pwrctl_pwrseq_data *data; 31 struct device *dev = &pdev->dev; 32 int ret; 33 34 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 35 if (!data) 36 return -ENOMEM; 37 38 data->pwrseq = devm_pwrseq_get(dev, of_device_get_match_data(dev)); 39 if (IS_ERR(data->pwrseq)) 40 return dev_err_probe(dev, PTR_ERR(data->pwrseq), 41 "Failed to get the power sequencer\n"); 42 43 ret = pwrseq_power_on(data->pwrseq); 44 if (ret) 45 return dev_err_probe(dev, ret, 46 "Failed to power-on the device\n"); 47 48 ret = devm_add_action_or_reset(dev, devm_pci_pwrctl_pwrseq_power_off, 49 data->pwrseq); 50 if (ret) 51 return ret; 52 53 pci_pwrctl_init(&data->ctx, dev); 54 55 ret = devm_pci_pwrctl_device_set_ready(dev, &data->ctx); 56 if (ret) 57 return dev_err_probe(dev, ret, 58 "Failed to register the pwrctl wrapper\n"); 59 60 return 0; 61 } 62 63 static const struct of_device_id pci_pwrctl_pwrseq_of_match[] = { 64 { 65 /* ATH11K in QCA6390 package. */ 66 .compatible = "pci17cb,1101", 67 .data = "wlan", 68 }, 69 { 70 /* ATH11K in WCN6855 package. */ 71 .compatible = "pci17cb,1103", 72 .data = "wlan", 73 }, 74 { 75 /* ATH12K in WCN7850 package. */ 76 .compatible = "pci17cb,1107", 77 .data = "wlan", 78 }, 79 { } 80 }; 81 MODULE_DEVICE_TABLE(of, pci_pwrctl_pwrseq_of_match); 82 83 static struct platform_driver pci_pwrctl_pwrseq_driver = { 84 .driver = { 85 .name = "pci-pwrctl-pwrseq", 86 .of_match_table = pci_pwrctl_pwrseq_of_match, 87 }, 88 .probe = pci_pwrctl_pwrseq_probe, 89 }; 90 module_platform_driver(pci_pwrctl_pwrseq_driver); 91 92 MODULE_AUTHOR("Bartosz Golaszewski <bartosz.golaszewski@linaro.org>"); 93 MODULE_DESCRIPTION("Generic PCI Power Control module for power sequenced devices"); 94 MODULE_LICENSE("GPL"); 95