11ed2b3fcSJarkko Nikula // SPDX-License-Identifier: GPL-2.0
21ed2b3fcSJarkko Nikula /*
31ed2b3fcSJarkko Nikula * DesignWare PWM Controller driver
41ed2b3fcSJarkko Nikula *
51ed2b3fcSJarkko Nikula * Copyright (C) 2018-2020 Intel Corporation
61ed2b3fcSJarkko Nikula *
71ed2b3fcSJarkko Nikula * Author: Felipe Balbi (Intel)
81ed2b3fcSJarkko Nikula * Author: Jarkko Nikula <jarkko.nikula@linux.intel.com>
91ed2b3fcSJarkko Nikula * Author: Raymond Tan <raymond.tan@intel.com>
101ed2b3fcSJarkko Nikula *
111ed2b3fcSJarkko Nikula * Limitations:
121ed2b3fcSJarkko Nikula * - The hardware cannot generate a 0 % or 100 % duty cycle. Both high and low
131ed2b3fcSJarkko Nikula * periods are one or more input clock periods long.
141ed2b3fcSJarkko Nikula */
151ed2b3fcSJarkko Nikula
161ed2b3fcSJarkko Nikula #include <linux/bitops.h>
171ed2b3fcSJarkko Nikula #include <linux/export.h>
181ed2b3fcSJarkko Nikula #include <linux/kernel.h>
191ed2b3fcSJarkko Nikula #include <linux/module.h>
201ed2b3fcSJarkko Nikula #include <linux/pci.h>
211ed2b3fcSJarkko Nikula #include <linux/pm_runtime.h>
221ed2b3fcSJarkko Nikula #include <linux/pwm.h>
231ed2b3fcSJarkko Nikula
241ed2b3fcSJarkko Nikula #define DWC_TIM_LD_CNT(n) ((n) * 0x14)
251ed2b3fcSJarkko Nikula #define DWC_TIM_LD_CNT2(n) (((n) * 4) + 0xb0)
261ed2b3fcSJarkko Nikula #define DWC_TIM_CUR_VAL(n) (((n) * 0x14) + 0x04)
271ed2b3fcSJarkko Nikula #define DWC_TIM_CTRL(n) (((n) * 0x14) + 0x08)
281ed2b3fcSJarkko Nikula #define DWC_TIM_EOI(n) (((n) * 0x14) + 0x0c)
291ed2b3fcSJarkko Nikula #define DWC_TIM_INT_STS(n) (((n) * 0x14) + 0x10)
301ed2b3fcSJarkko Nikula
311ed2b3fcSJarkko Nikula #define DWC_TIMERS_INT_STS 0xa0
321ed2b3fcSJarkko Nikula #define DWC_TIMERS_EOI 0xa4
331ed2b3fcSJarkko Nikula #define DWC_TIMERS_RAW_INT_STS 0xa8
341ed2b3fcSJarkko Nikula #define DWC_TIMERS_COMP_VERSION 0xac
351ed2b3fcSJarkko Nikula
361ed2b3fcSJarkko Nikula #define DWC_TIMERS_TOTAL 8
371ed2b3fcSJarkko Nikula #define DWC_CLK_PERIOD_NS 10
381ed2b3fcSJarkko Nikula
391ed2b3fcSJarkko Nikula /* Timer Control Register */
401ed2b3fcSJarkko Nikula #define DWC_TIM_CTRL_EN BIT(0)
411ed2b3fcSJarkko Nikula #define DWC_TIM_CTRL_MODE BIT(1)
421ed2b3fcSJarkko Nikula #define DWC_TIM_CTRL_MODE_FREE (0 << 1)
431ed2b3fcSJarkko Nikula #define DWC_TIM_CTRL_MODE_USER (1 << 1)
441ed2b3fcSJarkko Nikula #define DWC_TIM_CTRL_INT_MASK BIT(2)
451ed2b3fcSJarkko Nikula #define DWC_TIM_CTRL_PWM BIT(3)
461ed2b3fcSJarkko Nikula
471ed2b3fcSJarkko Nikula struct dwc_pwm_ctx {
481ed2b3fcSJarkko Nikula u32 cnt;
491ed2b3fcSJarkko Nikula u32 cnt2;
501ed2b3fcSJarkko Nikula u32 ctrl;
511ed2b3fcSJarkko Nikula };
521ed2b3fcSJarkko Nikula
531ed2b3fcSJarkko Nikula struct dwc_pwm {
541ed2b3fcSJarkko Nikula struct pwm_chip chip;
551ed2b3fcSJarkko Nikula void __iomem *base;
561ed2b3fcSJarkko Nikula struct dwc_pwm_ctx ctx[DWC_TIMERS_TOTAL];
571ed2b3fcSJarkko Nikula };
581ed2b3fcSJarkko Nikula #define to_dwc_pwm(p) (container_of((p), struct dwc_pwm, chip))
591ed2b3fcSJarkko Nikula
dwc_pwm_readl(struct dwc_pwm * dwc,u32 offset)601ed2b3fcSJarkko Nikula static inline u32 dwc_pwm_readl(struct dwc_pwm *dwc, u32 offset)
611ed2b3fcSJarkko Nikula {
621ed2b3fcSJarkko Nikula return readl(dwc->base + offset);
631ed2b3fcSJarkko Nikula }
641ed2b3fcSJarkko Nikula
dwc_pwm_writel(struct dwc_pwm * dwc,u32 value,u32 offset)651ed2b3fcSJarkko Nikula static inline void dwc_pwm_writel(struct dwc_pwm *dwc, u32 value, u32 offset)
661ed2b3fcSJarkko Nikula {
671ed2b3fcSJarkko Nikula writel(value, dwc->base + offset);
681ed2b3fcSJarkko Nikula }
691ed2b3fcSJarkko Nikula
__dwc_pwm_set_enable(struct dwc_pwm * dwc,int pwm,int enabled)701ed2b3fcSJarkko Nikula static void __dwc_pwm_set_enable(struct dwc_pwm *dwc, int pwm, int enabled)
711ed2b3fcSJarkko Nikula {
721ed2b3fcSJarkko Nikula u32 reg;
731ed2b3fcSJarkko Nikula
741ed2b3fcSJarkko Nikula reg = dwc_pwm_readl(dwc, DWC_TIM_CTRL(pwm));
751ed2b3fcSJarkko Nikula
761ed2b3fcSJarkko Nikula if (enabled)
771ed2b3fcSJarkko Nikula reg |= DWC_TIM_CTRL_EN;
781ed2b3fcSJarkko Nikula else
791ed2b3fcSJarkko Nikula reg &= ~DWC_TIM_CTRL_EN;
801ed2b3fcSJarkko Nikula
811ed2b3fcSJarkko Nikula dwc_pwm_writel(dwc, reg, DWC_TIM_CTRL(pwm));
821ed2b3fcSJarkko Nikula }
831ed2b3fcSJarkko Nikula
__dwc_pwm_configure_timer(struct dwc_pwm * dwc,struct pwm_device * pwm,const struct pwm_state * state)841ed2b3fcSJarkko Nikula static int __dwc_pwm_configure_timer(struct dwc_pwm *dwc,
851ed2b3fcSJarkko Nikula struct pwm_device *pwm,
861ed2b3fcSJarkko Nikula const struct pwm_state *state)
871ed2b3fcSJarkko Nikula {
881ed2b3fcSJarkko Nikula u64 tmp;
891ed2b3fcSJarkko Nikula u32 ctrl;
901ed2b3fcSJarkko Nikula u32 high;
911ed2b3fcSJarkko Nikula u32 low;
921ed2b3fcSJarkko Nikula
931ed2b3fcSJarkko Nikula /*
941ed2b3fcSJarkko Nikula * Calculate width of low and high period in terms of input clock
951ed2b3fcSJarkko Nikula * periods and check are the result within HW limits between 1 and
961ed2b3fcSJarkko Nikula * 2^32 periods.
971ed2b3fcSJarkko Nikula */
981ed2b3fcSJarkko Nikula tmp = DIV_ROUND_CLOSEST_ULL(state->duty_cycle, DWC_CLK_PERIOD_NS);
991ed2b3fcSJarkko Nikula if (tmp < 1 || tmp > (1ULL << 32))
1001ed2b3fcSJarkko Nikula return -ERANGE;
1011ed2b3fcSJarkko Nikula low = tmp - 1;
1021ed2b3fcSJarkko Nikula
1031ed2b3fcSJarkko Nikula tmp = DIV_ROUND_CLOSEST_ULL(state->period - state->duty_cycle,
1041ed2b3fcSJarkko Nikula DWC_CLK_PERIOD_NS);
1051ed2b3fcSJarkko Nikula if (tmp < 1 || tmp > (1ULL << 32))
1061ed2b3fcSJarkko Nikula return -ERANGE;
1071ed2b3fcSJarkko Nikula high = tmp - 1;
1081ed2b3fcSJarkko Nikula
1091ed2b3fcSJarkko Nikula /*
1101ed2b3fcSJarkko Nikula * Specification says timer usage flow is to disable timer, then
1111ed2b3fcSJarkko Nikula * program it followed by enable. It also says Load Count is loaded
1121ed2b3fcSJarkko Nikula * into timer after it is enabled - either after a disable or
1131ed2b3fcSJarkko Nikula * a reset. Based on measurements it happens also without disable
1141ed2b3fcSJarkko Nikula * whenever Load Count is updated. But follow the specification.
1151ed2b3fcSJarkko Nikula */
1161ed2b3fcSJarkko Nikula __dwc_pwm_set_enable(dwc, pwm->hwpwm, false);
1171ed2b3fcSJarkko Nikula
1181ed2b3fcSJarkko Nikula /*
1191ed2b3fcSJarkko Nikula * Write Load Count and Load Count 2 registers. Former defines the
1201ed2b3fcSJarkko Nikula * width of low period and latter the width of high period in terms
1211ed2b3fcSJarkko Nikula * multiple of input clock periods:
1221ed2b3fcSJarkko Nikula * Width = ((Count + 1) * input clock period).
1231ed2b3fcSJarkko Nikula */
1241ed2b3fcSJarkko Nikula dwc_pwm_writel(dwc, low, DWC_TIM_LD_CNT(pwm->hwpwm));
1251ed2b3fcSJarkko Nikula dwc_pwm_writel(dwc, high, DWC_TIM_LD_CNT2(pwm->hwpwm));
1261ed2b3fcSJarkko Nikula
1271ed2b3fcSJarkko Nikula /*
1281ed2b3fcSJarkko Nikula * Set user-defined mode, timer reloads from Load Count registers
1291ed2b3fcSJarkko Nikula * when it counts down to 0.
1301ed2b3fcSJarkko Nikula * Set PWM mode, it makes output to toggle and width of low and high
1311ed2b3fcSJarkko Nikula * periods are set by Load Count registers.
1321ed2b3fcSJarkko Nikula */
1331ed2b3fcSJarkko Nikula ctrl = DWC_TIM_CTRL_MODE_USER | DWC_TIM_CTRL_PWM;
1341ed2b3fcSJarkko Nikula dwc_pwm_writel(dwc, ctrl, DWC_TIM_CTRL(pwm->hwpwm));
1351ed2b3fcSJarkko Nikula
1361ed2b3fcSJarkko Nikula /*
1371ed2b3fcSJarkko Nikula * Enable timer. Output starts from low period.
1381ed2b3fcSJarkko Nikula */
1391ed2b3fcSJarkko Nikula __dwc_pwm_set_enable(dwc, pwm->hwpwm, state->enabled);
1401ed2b3fcSJarkko Nikula
1411ed2b3fcSJarkko Nikula return 0;
1421ed2b3fcSJarkko Nikula }
1431ed2b3fcSJarkko Nikula
dwc_pwm_apply(struct pwm_chip * chip,struct pwm_device * pwm,const struct pwm_state * state)1441ed2b3fcSJarkko Nikula static int dwc_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
1451ed2b3fcSJarkko Nikula const struct pwm_state *state)
1461ed2b3fcSJarkko Nikula {
1471ed2b3fcSJarkko Nikula struct dwc_pwm *dwc = to_dwc_pwm(chip);
1481ed2b3fcSJarkko Nikula
1491ed2b3fcSJarkko Nikula if (state->polarity != PWM_POLARITY_INVERSED)
1501ed2b3fcSJarkko Nikula return -EINVAL;
1511ed2b3fcSJarkko Nikula
1521ed2b3fcSJarkko Nikula if (state->enabled) {
1531ed2b3fcSJarkko Nikula if (!pwm->state.enabled)
1541ed2b3fcSJarkko Nikula pm_runtime_get_sync(chip->dev);
1551ed2b3fcSJarkko Nikula return __dwc_pwm_configure_timer(dwc, pwm, state);
1561ed2b3fcSJarkko Nikula } else {
1571ed2b3fcSJarkko Nikula if (pwm->state.enabled) {
1581ed2b3fcSJarkko Nikula __dwc_pwm_set_enable(dwc, pwm->hwpwm, false);
1591ed2b3fcSJarkko Nikula pm_runtime_put_sync(chip->dev);
1601ed2b3fcSJarkko Nikula }
1611ed2b3fcSJarkko Nikula }
1621ed2b3fcSJarkko Nikula
1631ed2b3fcSJarkko Nikula return 0;
1641ed2b3fcSJarkko Nikula }
1651ed2b3fcSJarkko Nikula
dwc_pwm_get_state(struct pwm_chip * chip,struct pwm_device * pwm,struct pwm_state * state)1666c452cffSUwe Kleine-König static int dwc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
1671ed2b3fcSJarkko Nikula struct pwm_state *state)
1681ed2b3fcSJarkko Nikula {
1691ed2b3fcSJarkko Nikula struct dwc_pwm *dwc = to_dwc_pwm(chip);
1701ed2b3fcSJarkko Nikula u64 duty, period;
1711ed2b3fcSJarkko Nikula
1721ed2b3fcSJarkko Nikula pm_runtime_get_sync(chip->dev);
1731ed2b3fcSJarkko Nikula
1741ed2b3fcSJarkko Nikula state->enabled = !!(dwc_pwm_readl(dwc,
1751ed2b3fcSJarkko Nikula DWC_TIM_CTRL(pwm->hwpwm)) & DWC_TIM_CTRL_EN);
1761ed2b3fcSJarkko Nikula
1771ed2b3fcSJarkko Nikula duty = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(pwm->hwpwm));
1781ed2b3fcSJarkko Nikula duty += 1;
1791ed2b3fcSJarkko Nikula duty *= DWC_CLK_PERIOD_NS;
1801ed2b3fcSJarkko Nikula state->duty_cycle = duty;
1811ed2b3fcSJarkko Nikula
1821ed2b3fcSJarkko Nikula period = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(pwm->hwpwm));
1831ed2b3fcSJarkko Nikula period += 1;
1841ed2b3fcSJarkko Nikula period *= DWC_CLK_PERIOD_NS;
1851ed2b3fcSJarkko Nikula period += duty;
1861ed2b3fcSJarkko Nikula state->period = period;
1871ed2b3fcSJarkko Nikula
1881ed2b3fcSJarkko Nikula state->polarity = PWM_POLARITY_INVERSED;
1891ed2b3fcSJarkko Nikula
1901ed2b3fcSJarkko Nikula pm_runtime_put_sync(chip->dev);
1916c452cffSUwe Kleine-König
1926c452cffSUwe Kleine-König return 0;
1931ed2b3fcSJarkko Nikula }
1941ed2b3fcSJarkko Nikula
1951ed2b3fcSJarkko Nikula static const struct pwm_ops dwc_pwm_ops = {
1961ed2b3fcSJarkko Nikula .apply = dwc_pwm_apply,
1971ed2b3fcSJarkko Nikula .get_state = dwc_pwm_get_state,
1981ed2b3fcSJarkko Nikula .owner = THIS_MODULE,
1991ed2b3fcSJarkko Nikula };
2001ed2b3fcSJarkko Nikula
dwc_pwm_alloc(struct device * dev)201a357d149SBen Dooks static struct dwc_pwm *dwc_pwm_alloc(struct device *dev)
202a357d149SBen Dooks {
203a357d149SBen Dooks struct dwc_pwm *dwc;
204a357d149SBen Dooks
205a357d149SBen Dooks dwc = devm_kzalloc(dev, sizeof(*dwc), GFP_KERNEL);
206a357d149SBen Dooks if (!dwc)
207a357d149SBen Dooks return NULL;
208a357d149SBen Dooks
209a357d149SBen Dooks dwc->chip.dev = dev;
210a357d149SBen Dooks dwc->chip.ops = &dwc_pwm_ops;
211a357d149SBen Dooks dwc->chip.npwm = DWC_TIMERS_TOTAL;
212a357d149SBen Dooks
213a357d149SBen Dooks dev_set_drvdata(dev, dwc);
214a357d149SBen Dooks return dwc;
215a357d149SBen Dooks }
216a357d149SBen Dooks
dwc_pwm_probe(struct pci_dev * pci,const struct pci_device_id * id)2171ed2b3fcSJarkko Nikula static int dwc_pwm_probe(struct pci_dev *pci, const struct pci_device_id *id)
2181ed2b3fcSJarkko Nikula {
2191ed2b3fcSJarkko Nikula struct device *dev = &pci->dev;
2201ed2b3fcSJarkko Nikula struct dwc_pwm *dwc;
2211ed2b3fcSJarkko Nikula int ret;
2221ed2b3fcSJarkko Nikula
223a357d149SBen Dooks dwc = dwc_pwm_alloc(dev);
2241ed2b3fcSJarkko Nikula if (!dwc)
2251ed2b3fcSJarkko Nikula return -ENOMEM;
2261ed2b3fcSJarkko Nikula
2271ed2b3fcSJarkko Nikula ret = pcim_enable_device(pci);
2281ed2b3fcSJarkko Nikula if (ret) {
229f7c843d6SBen Dooks dev_err(dev, "Failed to enable device (%pe)\n", ERR_PTR(ret));
2301ed2b3fcSJarkko Nikula return ret;
2311ed2b3fcSJarkko Nikula }
2321ed2b3fcSJarkko Nikula
2331ed2b3fcSJarkko Nikula pci_set_master(pci);
2341ed2b3fcSJarkko Nikula
2351ed2b3fcSJarkko Nikula ret = pcim_iomap_regions(pci, BIT(0), pci_name(pci));
2361ed2b3fcSJarkko Nikula if (ret) {
237f7c843d6SBen Dooks dev_err(dev, "Failed to iomap PCI BAR (%pe)\n", ERR_PTR(ret));
2381ed2b3fcSJarkko Nikula return ret;
2391ed2b3fcSJarkko Nikula }
2401ed2b3fcSJarkko Nikula
2411ed2b3fcSJarkko Nikula dwc->base = pcim_iomap_table(pci)[0];
2421ed2b3fcSJarkko Nikula if (!dwc->base) {
243f7c843d6SBen Dooks dev_err(dev, "Base address missing\n");
2441ed2b3fcSJarkko Nikula return -ENOMEM;
2451ed2b3fcSJarkko Nikula }
2461ed2b3fcSJarkko Nikula
247*cf70d01aSBen Dooks ret = devm_pwmchip_add(dev, &dwc->chip);
2481ed2b3fcSJarkko Nikula if (ret)
2491ed2b3fcSJarkko Nikula return ret;
2501ed2b3fcSJarkko Nikula
2511ed2b3fcSJarkko Nikula pm_runtime_put(dev);
2521ed2b3fcSJarkko Nikula pm_runtime_allow(dev);
2531ed2b3fcSJarkko Nikula
2541ed2b3fcSJarkko Nikula return 0;
2551ed2b3fcSJarkko Nikula }
2561ed2b3fcSJarkko Nikula
dwc_pwm_remove(struct pci_dev * pci)2571ed2b3fcSJarkko Nikula static void dwc_pwm_remove(struct pci_dev *pci)
2581ed2b3fcSJarkko Nikula {
2591ed2b3fcSJarkko Nikula pm_runtime_forbid(&pci->dev);
2601ed2b3fcSJarkko Nikula pm_runtime_get_noresume(&pci->dev);
2611ed2b3fcSJarkko Nikula }
2621ed2b3fcSJarkko Nikula
2631ed2b3fcSJarkko Nikula #ifdef CONFIG_PM_SLEEP
dwc_pwm_suspend(struct device * dev)2641ed2b3fcSJarkko Nikula static int dwc_pwm_suspend(struct device *dev)
2651ed2b3fcSJarkko Nikula {
2661ed2b3fcSJarkko Nikula struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
2671ed2b3fcSJarkko Nikula struct dwc_pwm *dwc = pci_get_drvdata(pdev);
2681ed2b3fcSJarkko Nikula int i;
2691ed2b3fcSJarkko Nikula
2701ed2b3fcSJarkko Nikula for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
2711ed2b3fcSJarkko Nikula if (dwc->chip.pwms[i].state.enabled) {
2721ed2b3fcSJarkko Nikula dev_err(dev, "PWM %u in use by consumer (%s)\n",
2731ed2b3fcSJarkko Nikula i, dwc->chip.pwms[i].label);
2741ed2b3fcSJarkko Nikula return -EBUSY;
2751ed2b3fcSJarkko Nikula }
2761ed2b3fcSJarkko Nikula dwc->ctx[i].cnt = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(i));
2771ed2b3fcSJarkko Nikula dwc->ctx[i].cnt2 = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(i));
2781ed2b3fcSJarkko Nikula dwc->ctx[i].ctrl = dwc_pwm_readl(dwc, DWC_TIM_CTRL(i));
2791ed2b3fcSJarkko Nikula }
2801ed2b3fcSJarkko Nikula
2811ed2b3fcSJarkko Nikula return 0;
2821ed2b3fcSJarkko Nikula }
2831ed2b3fcSJarkko Nikula
dwc_pwm_resume(struct device * dev)2841ed2b3fcSJarkko Nikula static int dwc_pwm_resume(struct device *dev)
2851ed2b3fcSJarkko Nikula {
2861ed2b3fcSJarkko Nikula struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
2871ed2b3fcSJarkko Nikula struct dwc_pwm *dwc = pci_get_drvdata(pdev);
2881ed2b3fcSJarkko Nikula int i;
2891ed2b3fcSJarkko Nikula
2901ed2b3fcSJarkko Nikula for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
2911ed2b3fcSJarkko Nikula dwc_pwm_writel(dwc, dwc->ctx[i].cnt, DWC_TIM_LD_CNT(i));
2921ed2b3fcSJarkko Nikula dwc_pwm_writel(dwc, dwc->ctx[i].cnt2, DWC_TIM_LD_CNT2(i));
2931ed2b3fcSJarkko Nikula dwc_pwm_writel(dwc, dwc->ctx[i].ctrl, DWC_TIM_CTRL(i));
2941ed2b3fcSJarkko Nikula }
2951ed2b3fcSJarkko Nikula
2961ed2b3fcSJarkko Nikula return 0;
2971ed2b3fcSJarkko Nikula }
2981ed2b3fcSJarkko Nikula #endif
2991ed2b3fcSJarkko Nikula
3001ed2b3fcSJarkko Nikula static SIMPLE_DEV_PM_OPS(dwc_pwm_pm_ops, dwc_pwm_suspend, dwc_pwm_resume);
3011ed2b3fcSJarkko Nikula
3021ed2b3fcSJarkko Nikula static const struct pci_device_id dwc_pwm_id_table[] = {
3031ed2b3fcSJarkko Nikula { PCI_VDEVICE(INTEL, 0x4bb7) }, /* Elkhart Lake */
3041ed2b3fcSJarkko Nikula { } /* Terminating Entry */
3051ed2b3fcSJarkko Nikula };
3061ed2b3fcSJarkko Nikula MODULE_DEVICE_TABLE(pci, dwc_pwm_id_table);
3071ed2b3fcSJarkko Nikula
3081ed2b3fcSJarkko Nikula static struct pci_driver dwc_pwm_driver = {
3091ed2b3fcSJarkko Nikula .name = "pwm-dwc",
3101ed2b3fcSJarkko Nikula .probe = dwc_pwm_probe,
3111ed2b3fcSJarkko Nikula .remove = dwc_pwm_remove,
3121ed2b3fcSJarkko Nikula .id_table = dwc_pwm_id_table,
3131ed2b3fcSJarkko Nikula .driver = {
3141ed2b3fcSJarkko Nikula .pm = &dwc_pwm_pm_ops,
3151ed2b3fcSJarkko Nikula },
3161ed2b3fcSJarkko Nikula };
3171ed2b3fcSJarkko Nikula
3181ed2b3fcSJarkko Nikula module_pci_driver(dwc_pwm_driver);
3191ed2b3fcSJarkko Nikula
3201ed2b3fcSJarkko Nikula MODULE_AUTHOR("Felipe Balbi (Intel)");
3211ed2b3fcSJarkko Nikula MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@linux.intel.com>");
3221ed2b3fcSJarkko Nikula MODULE_AUTHOR("Raymond Tan <raymond.tan@intel.com>");
3231ed2b3fcSJarkko Nikula MODULE_DESCRIPTION("DesignWare PWM Controller");
3241ed2b3fcSJarkko Nikula MODULE_LICENSE("GPL");
325