Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * DesignWare PWM Controller driver
0004  *
0005  * Copyright (C) 2018-2020 Intel Corporation
0006  *
0007  * Author: Felipe Balbi (Intel)
0008  * Author: Jarkko Nikula <jarkko.nikula@linux.intel.com>
0009  * Author: Raymond Tan <raymond.tan@intel.com>
0010  *
0011  * Limitations:
0012  * - The hardware cannot generate a 0 % or 100 % duty cycle. Both high and low
0013  *   periods are one or more input clock periods long.
0014  */
0015 
0016 #include <linux/bitops.h>
0017 #include <linux/export.h>
0018 #include <linux/kernel.h>
0019 #include <linux/module.h>
0020 #include <linux/pci.h>
0021 #include <linux/pm_runtime.h>
0022 #include <linux/pwm.h>
0023 
0024 #define DWC_TIM_LD_CNT(n)   ((n) * 0x14)
0025 #define DWC_TIM_LD_CNT2(n)  (((n) * 4) + 0xb0)
0026 #define DWC_TIM_CUR_VAL(n)  (((n) * 0x14) + 0x04)
0027 #define DWC_TIM_CTRL(n)     (((n) * 0x14) + 0x08)
0028 #define DWC_TIM_EOI(n)      (((n) * 0x14) + 0x0c)
0029 #define DWC_TIM_INT_STS(n)  (((n) * 0x14) + 0x10)
0030 
0031 #define DWC_TIMERS_INT_STS  0xa0
0032 #define DWC_TIMERS_EOI      0xa4
0033 #define DWC_TIMERS_RAW_INT_STS  0xa8
0034 #define DWC_TIMERS_COMP_VERSION 0xac
0035 
0036 #define DWC_TIMERS_TOTAL    8
0037 #define DWC_CLK_PERIOD_NS   10
0038 
0039 /* Timer Control Register */
0040 #define DWC_TIM_CTRL_EN     BIT(0)
0041 #define DWC_TIM_CTRL_MODE   BIT(1)
0042 #define DWC_TIM_CTRL_MODE_FREE  (0 << 1)
0043 #define DWC_TIM_CTRL_MODE_USER  (1 << 1)
0044 #define DWC_TIM_CTRL_INT_MASK   BIT(2)
0045 #define DWC_TIM_CTRL_PWM    BIT(3)
0046 
0047 struct dwc_pwm_ctx {
0048     u32 cnt;
0049     u32 cnt2;
0050     u32 ctrl;
0051 };
0052 
0053 struct dwc_pwm {
0054     struct pwm_chip chip;
0055     void __iomem *base;
0056     struct dwc_pwm_ctx ctx[DWC_TIMERS_TOTAL];
0057 };
0058 #define to_dwc_pwm(p)   (container_of((p), struct dwc_pwm, chip))
0059 
0060 static inline u32 dwc_pwm_readl(struct dwc_pwm *dwc, u32 offset)
0061 {
0062     return readl(dwc->base + offset);
0063 }
0064 
0065 static inline void dwc_pwm_writel(struct dwc_pwm *dwc, u32 value, u32 offset)
0066 {
0067     writel(value, dwc->base + offset);
0068 }
0069 
0070 static void __dwc_pwm_set_enable(struct dwc_pwm *dwc, int pwm, int enabled)
0071 {
0072     u32 reg;
0073 
0074     reg = dwc_pwm_readl(dwc, DWC_TIM_CTRL(pwm));
0075 
0076     if (enabled)
0077         reg |= DWC_TIM_CTRL_EN;
0078     else
0079         reg &= ~DWC_TIM_CTRL_EN;
0080 
0081     dwc_pwm_writel(dwc, reg, DWC_TIM_CTRL(pwm));
0082 }
0083 
0084 static int __dwc_pwm_configure_timer(struct dwc_pwm *dwc,
0085                      struct pwm_device *pwm,
0086                      const struct pwm_state *state)
0087 {
0088     u64 tmp;
0089     u32 ctrl;
0090     u32 high;
0091     u32 low;
0092 
0093     /*
0094      * Calculate width of low and high period in terms of input clock
0095      * periods and check are the result within HW limits between 1 and
0096      * 2^32 periods.
0097      */
0098     tmp = DIV_ROUND_CLOSEST_ULL(state->duty_cycle, DWC_CLK_PERIOD_NS);
0099     if (tmp < 1 || tmp > (1ULL << 32))
0100         return -ERANGE;
0101     low = tmp - 1;
0102 
0103     tmp = DIV_ROUND_CLOSEST_ULL(state->period - state->duty_cycle,
0104                     DWC_CLK_PERIOD_NS);
0105     if (tmp < 1 || tmp > (1ULL << 32))
0106         return -ERANGE;
0107     high = tmp - 1;
0108 
0109     /*
0110      * Specification says timer usage flow is to disable timer, then
0111      * program it followed by enable. It also says Load Count is loaded
0112      * into timer after it is enabled - either after a disable or
0113      * a reset. Based on measurements it happens also without disable
0114      * whenever Load Count is updated. But follow the specification.
0115      */
0116     __dwc_pwm_set_enable(dwc, pwm->hwpwm, false);
0117 
0118     /*
0119      * Write Load Count and Load Count 2 registers. Former defines the
0120      * width of low period and latter the width of high period in terms
0121      * multiple of input clock periods:
0122      * Width = ((Count + 1) * input clock period).
0123      */
0124     dwc_pwm_writel(dwc, low, DWC_TIM_LD_CNT(pwm->hwpwm));
0125     dwc_pwm_writel(dwc, high, DWC_TIM_LD_CNT2(pwm->hwpwm));
0126 
0127     /*
0128      * Set user-defined mode, timer reloads from Load Count registers
0129      * when it counts down to 0.
0130      * Set PWM mode, it makes output to toggle and width of low and high
0131      * periods are set by Load Count registers.
0132      */
0133     ctrl = DWC_TIM_CTRL_MODE_USER | DWC_TIM_CTRL_PWM;
0134     dwc_pwm_writel(dwc, ctrl, DWC_TIM_CTRL(pwm->hwpwm));
0135 
0136     /*
0137      * Enable timer. Output starts from low period.
0138      */
0139     __dwc_pwm_set_enable(dwc, pwm->hwpwm, state->enabled);
0140 
0141     return 0;
0142 }
0143 
0144 static int dwc_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
0145              const struct pwm_state *state)
0146 {
0147     struct dwc_pwm *dwc = to_dwc_pwm(chip);
0148 
0149     if (state->polarity != PWM_POLARITY_INVERSED)
0150         return -EINVAL;
0151 
0152     if (state->enabled) {
0153         if (!pwm->state.enabled)
0154             pm_runtime_get_sync(chip->dev);
0155         return __dwc_pwm_configure_timer(dwc, pwm, state);
0156     } else {
0157         if (pwm->state.enabled) {
0158             __dwc_pwm_set_enable(dwc, pwm->hwpwm, false);
0159             pm_runtime_put_sync(chip->dev);
0160         }
0161     }
0162 
0163     return 0;
0164 }
0165 
0166 static void dwc_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
0167                   struct pwm_state *state)
0168 {
0169     struct dwc_pwm *dwc = to_dwc_pwm(chip);
0170     u64 duty, period;
0171 
0172     pm_runtime_get_sync(chip->dev);
0173 
0174     state->enabled = !!(dwc_pwm_readl(dwc,
0175                 DWC_TIM_CTRL(pwm->hwpwm)) & DWC_TIM_CTRL_EN);
0176 
0177     duty = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(pwm->hwpwm));
0178     duty += 1;
0179     duty *= DWC_CLK_PERIOD_NS;
0180     state->duty_cycle = duty;
0181 
0182     period = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(pwm->hwpwm));
0183     period += 1;
0184     period *= DWC_CLK_PERIOD_NS;
0185     period += duty;
0186     state->period = period;
0187 
0188     state->polarity = PWM_POLARITY_INVERSED;
0189 
0190     pm_runtime_put_sync(chip->dev);
0191 }
0192 
0193 static const struct pwm_ops dwc_pwm_ops = {
0194     .apply = dwc_pwm_apply,
0195     .get_state = dwc_pwm_get_state,
0196     .owner = THIS_MODULE,
0197 };
0198 
0199 static int dwc_pwm_probe(struct pci_dev *pci, const struct pci_device_id *id)
0200 {
0201     struct device *dev = &pci->dev;
0202     struct dwc_pwm *dwc;
0203     int ret;
0204 
0205     dwc = devm_kzalloc(&pci->dev, sizeof(*dwc), GFP_KERNEL);
0206     if (!dwc)
0207         return -ENOMEM;
0208 
0209     ret = pcim_enable_device(pci);
0210     if (ret) {
0211         dev_err(&pci->dev,
0212             "Failed to enable device (%pe)\n", ERR_PTR(ret));
0213         return ret;
0214     }
0215 
0216     pci_set_master(pci);
0217 
0218     ret = pcim_iomap_regions(pci, BIT(0), pci_name(pci));
0219     if (ret) {
0220         dev_err(&pci->dev,
0221             "Failed to iomap PCI BAR (%pe)\n", ERR_PTR(ret));
0222         return ret;
0223     }
0224 
0225     dwc->base = pcim_iomap_table(pci)[0];
0226     if (!dwc->base) {
0227         dev_err(&pci->dev, "Base address missing\n");
0228         return -ENOMEM;
0229     }
0230 
0231     pci_set_drvdata(pci, dwc);
0232 
0233     dwc->chip.dev = dev;
0234     dwc->chip.ops = &dwc_pwm_ops;
0235     dwc->chip.npwm = DWC_TIMERS_TOTAL;
0236 
0237     ret = pwmchip_add(&dwc->chip);
0238     if (ret)
0239         return ret;
0240 
0241     pm_runtime_put(dev);
0242     pm_runtime_allow(dev);
0243 
0244     return 0;
0245 }
0246 
0247 static void dwc_pwm_remove(struct pci_dev *pci)
0248 {
0249     struct dwc_pwm *dwc = pci_get_drvdata(pci);
0250 
0251     pm_runtime_forbid(&pci->dev);
0252     pm_runtime_get_noresume(&pci->dev);
0253 
0254     pwmchip_remove(&dwc->chip);
0255 }
0256 
0257 #ifdef CONFIG_PM_SLEEP
0258 static int dwc_pwm_suspend(struct device *dev)
0259 {
0260     struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
0261     struct dwc_pwm *dwc = pci_get_drvdata(pdev);
0262     int i;
0263 
0264     for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
0265         if (dwc->chip.pwms[i].state.enabled) {
0266             dev_err(dev, "PWM %u in use by consumer (%s)\n",
0267                 i, dwc->chip.pwms[i].label);
0268             return -EBUSY;
0269         }
0270         dwc->ctx[i].cnt = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(i));
0271         dwc->ctx[i].cnt2 = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(i));
0272         dwc->ctx[i].ctrl = dwc_pwm_readl(dwc, DWC_TIM_CTRL(i));
0273     }
0274 
0275     return 0;
0276 }
0277 
0278 static int dwc_pwm_resume(struct device *dev)
0279 {
0280     struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
0281     struct dwc_pwm *dwc = pci_get_drvdata(pdev);
0282     int i;
0283 
0284     for (i = 0; i < DWC_TIMERS_TOTAL; i++) {
0285         dwc_pwm_writel(dwc, dwc->ctx[i].cnt, DWC_TIM_LD_CNT(i));
0286         dwc_pwm_writel(dwc, dwc->ctx[i].cnt2, DWC_TIM_LD_CNT2(i));
0287         dwc_pwm_writel(dwc, dwc->ctx[i].ctrl, DWC_TIM_CTRL(i));
0288     }
0289 
0290     return 0;
0291 }
0292 #endif
0293 
0294 static SIMPLE_DEV_PM_OPS(dwc_pwm_pm_ops, dwc_pwm_suspend, dwc_pwm_resume);
0295 
0296 static const struct pci_device_id dwc_pwm_id_table[] = {
0297     { PCI_VDEVICE(INTEL, 0x4bb7) }, /* Elkhart Lake */
0298     {  }    /* Terminating Entry */
0299 };
0300 MODULE_DEVICE_TABLE(pci, dwc_pwm_id_table);
0301 
0302 static struct pci_driver dwc_pwm_driver = {
0303     .name = "pwm-dwc",
0304     .probe = dwc_pwm_probe,
0305     .remove = dwc_pwm_remove,
0306     .id_table = dwc_pwm_id_table,
0307     .driver = {
0308         .pm = &dwc_pwm_pm_ops,
0309     },
0310 };
0311 
0312 module_pci_driver(dwc_pwm_driver);
0313 
0314 MODULE_AUTHOR("Felipe Balbi (Intel)");
0315 MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@linux.intel.com>");
0316 MODULE_AUTHOR("Raymond Tan <raymond.tan@intel.com>");
0317 MODULE_DESCRIPTION("DesignWare PWM Controller");
0318 MODULE_LICENSE("GPL");