diff options
Diffstat (limited to 'drivers/pwm/pwm-dwc.c')
| -rw-r--r-- | drivers/pwm/pwm-dwc.c | 77 | 
1 files changed, 46 insertions, 31 deletions
diff --git a/drivers/pwm/pwm-dwc.c b/drivers/pwm/pwm-dwc.c index 4929354f8cd9..676eaf8d7a53 100644 --- a/drivers/pwm/pwm-dwc.c +++ b/drivers/pwm/pwm-dwc.c @@ -25,39 +25,54 @@  #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, void __iomem *base, unsigned int offset)  { -	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); + +	dwc = to_dwc_pwm(chip); +	dwc->base = base + offset; + +	return devm_pwmchip_add(dev, chip); +} + +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; +	int i, ret;  	ret = pcim_enable_device(pci); -	if (ret) { -		dev_err(dev, "Failed to enable device (%pe)\n", ERR_PTR(ret)); -		return ret; -	} +	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; -	} - -	dwc->base = pcim_iomap_table(pci)[0]; -	if (!dwc->base) { -		dev_err(dev, "Base address missing\n"); -		return -ENOMEM; -	} - -	ret = devm_pwmchip_add(dev, &dwc->chip);  	if (ret) -		return ret; +		return dev_err_probe(dev, ret, "Failed to iomap PCI BAR\n"); + +	info = (const struct dwc_pwm_info *)id->driver_data; + +	for (i = 0; i < info->nr; i++) { +		/* +		 * No need to check for pcim_iomap_table() failure, +		 * pcim_iomap_regions() already does it for us. +		 */ +		ret = dwc_pwm_init_one(dev, pcim_iomap_table(pci)[0], i * info->size); +		if (ret) +			return ret; +	}  	pm_runtime_put(dev);  	pm_runtime_allow(dev); @@ -73,14 +88,14 @@ 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); +	struct pwm_chip *chip = dev_get_drvdata(dev); +	struct dwc_pwm *dwc = to_dwc_pwm(chip);  	int i;  	for (i = 0; i < DWC_TIMERS_TOTAL; i++) { -		if (dwc->chip.pwms[i].state.enabled) { +		if (chip->pwms[i].state.enabled) {  			dev_err(dev, "PWM %u in use by consumer (%s)\n", -				i, dwc->chip.pwms[i].label); +				i, chip->pwms[i].label);  			return -EBUSY;  		}  		dwc->ctx[i].cnt = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(i)); @@ -93,8 +108,8 @@ 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); +	struct pwm_chip *chip = dev_get_drvdata(dev); +	struct dwc_pwm *dwc = to_dwc_pwm(chip);  	int i;  	for (i = 0; i < DWC_TIMERS_TOTAL; i++) { @@ -109,7 +124,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 +135,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),  	},  };  | 
