]> Git Repo - J-linux.git/blobdiff - drivers/pwm/pwm-dwc.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / pwm / pwm-dwc.c
index 4929354f8cd95c8b1bc37feccf4e92b3e541444c..fb3eadf6fbc464773b17c30235c51f5a4ff6917f 100644 (file)
 
 #include "pwm-dwc.h"
 
-static int dwc_pwm_probe(struct pci_dev *pci, const struct pci_device_id *id)
+/* Elkhart Lake */
+static const struct dwc_pwm_info ehl_pwm_info = {
+       .nr = 2,
+       .size = 0x1000,
+};
+
+static int dwc_pwm_init_one(struct device *dev, struct dwc_pwm_drvdata *ddata, unsigned int idx)
 {
-       struct device *dev = &pci->dev;
+       struct pwm_chip *chip;
        struct dwc_pwm *dwc;
        int ret;
 
-       dwc = dwc_pwm_alloc(dev);
-       if (!dwc)
-               return -ENOMEM;
+       chip = dwc_pwm_alloc(dev);
+       if (IS_ERR(chip))
+               return PTR_ERR(chip);
 
-       ret = pcim_enable_device(pci);
-       if (ret) {
-               dev_err(dev, "Failed to enable device (%pe)\n", ERR_PTR(ret));
+       dwc = to_dwc_pwm(chip);
+       dwc->base = ddata->io_base + (ddata->info->size * idx);
+
+       ret = devm_pwmchip_add(dev, chip);
+       if (ret)
                return ret;
-       }
+
+       ddata->chips[idx] = chip;
+       return 0;
+}
+
+static int dwc_pwm_probe(struct pci_dev *pci, const struct pci_device_id *id)
+{
+       const struct dwc_pwm_info *info;
+       struct device *dev = &pci->dev;
+       struct dwc_pwm_drvdata *ddata;
+       unsigned int idx;
+       int ret;
+
+       ret = pcim_enable_device(pci);
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to enable device\n");
 
        pci_set_master(pci);
 
        ret = pcim_iomap_regions(pci, BIT(0), pci_name(pci));
-       if (ret) {
-               dev_err(dev, "Failed to iomap PCI BAR (%pe)\n", ERR_PTR(ret));
-               return ret;
-       }
+       if (ret)
+               return dev_err_probe(dev, ret, "Failed to iomap PCI BAR\n");
 
-       dwc->base = pcim_iomap_table(pci)[0];
-       if (!dwc->base) {
-               dev_err(dev, "Base address missing\n");
+       info = (const struct dwc_pwm_info *)id->driver_data;
+       ddata = devm_kzalloc(dev, struct_size(ddata, chips, info->nr), GFP_KERNEL);
+       if (!ddata)
                return -ENOMEM;
+
+       /*
+        * No need to check for pcim_iomap_table() failure,
+        * pcim_iomap_regions() already does it for us.
+        */
+       ddata->io_base = pcim_iomap_table(pci)[0];
+       ddata->info = info;
+
+       for (idx = 0; idx < ddata->info->nr; idx++) {
+               ret = dwc_pwm_init_one(dev, ddata, idx);
+               if (ret)
+                       return ret;
        }
 
-       ret = devm_pwmchip_add(dev, &dwc->chip);
-       if (ret)
-               return ret;
+       dev_set_drvdata(dev, ddata);
 
        pm_runtime_put(dev);
        pm_runtime_allow(dev);
@@ -73,19 +104,24 @@ static void dwc_pwm_remove(struct pci_dev *pci)
 
 static int dwc_pwm_suspend(struct device *dev)
 {
-       struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
-       struct dwc_pwm *dwc = pci_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
-               if (dwc->chip.pwms[i].state.enabled) {
-                       dev_err(dev, "PWM %u in use by consumer (%s)\n",
-                               i, dwc->chip.pwms[i].label);
-                       return -EBUSY;
+       struct dwc_pwm_drvdata *ddata = dev_get_drvdata(dev);
+       unsigned int idx;
+
+       for (idx = 0; idx < ddata->info->nr; idx++) {
+               struct pwm_chip *chip = ddata->chips[idx];
+               struct dwc_pwm *dwc = to_dwc_pwm(chip);
+               unsigned int i;
+
+               for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
+                       if (chip->pwms[i].state.enabled) {
+                               dev_err(dev, "PWM %u in use by consumer (%s)\n",
+                                       i, chip->pwms[i].label);
+                               return -EBUSY;
+                       }
+                       dwc->ctx[i].cnt = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(i));
+                       dwc->ctx[i].cnt2 = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(i));
+                       dwc->ctx[i].ctrl = dwc_pwm_readl(dwc, DWC_TIM_CTRL(i));
                }
-               dwc->ctx[i].cnt = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(i));
-               dwc->ctx[i].cnt2 = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(i));
-               dwc->ctx[i].ctrl = dwc_pwm_readl(dwc, DWC_TIM_CTRL(i));
        }
 
        return 0;
@@ -93,14 +129,19 @@ static int dwc_pwm_suspend(struct device *dev)
 
 static int dwc_pwm_resume(struct device *dev)
 {
-       struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
-       struct dwc_pwm *dwc = pci_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
-               dwc_pwm_writel(dwc, dwc->ctx[i].cnt, DWC_TIM_LD_CNT(i));
-               dwc_pwm_writel(dwc, dwc->ctx[i].cnt2, DWC_TIM_LD_CNT2(i));
-               dwc_pwm_writel(dwc, dwc->ctx[i].ctrl, DWC_TIM_CTRL(i));
+       struct dwc_pwm_drvdata *ddata = dev_get_drvdata(dev);
+       unsigned int idx;
+
+       for (idx = 0; idx < ddata->info->nr; idx++) {
+               struct pwm_chip *chip = ddata->chips[idx];
+               struct dwc_pwm *dwc = to_dwc_pwm(chip);
+               unsigned int i;
+
+               for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
+                       dwc_pwm_writel(dwc, dwc->ctx[i].cnt, DWC_TIM_LD_CNT(i));
+                       dwc_pwm_writel(dwc, dwc->ctx[i].cnt2, DWC_TIM_LD_CNT2(i));
+                       dwc_pwm_writel(dwc, dwc->ctx[i].ctrl, DWC_TIM_CTRL(i));
+               }
        }
 
        return 0;
@@ -109,7 +150,7 @@ static int dwc_pwm_resume(struct device *dev)
 static DEFINE_SIMPLE_DEV_PM_OPS(dwc_pwm_pm_ops, dwc_pwm_suspend, dwc_pwm_resume);
 
 static const struct pci_device_id dwc_pwm_id_table[] = {
-       { PCI_VDEVICE(INTEL, 0x4bb7) }, /* Elkhart Lake */
+       { PCI_VDEVICE(INTEL, 0x4bb7), (kernel_ulong_t)&ehl_pwm_info },
        {  }    /* Terminating Entry */
 };
 MODULE_DEVICE_TABLE(pci, dwc_pwm_id_table);
@@ -120,7 +161,7 @@ static struct pci_driver dwc_pwm_driver = {
        .remove = dwc_pwm_remove,
        .id_table = dwc_pwm_id_table,
        .driver = {
-               .pm = pm_ptr(&dwc_pwm_pm_ops),
+               .pm = pm_sleep_ptr(&dwc_pwm_pm_ops),
        },
 };
 
This page took 0.030346 seconds and 4 git commands to generate.