Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 // Copyright (C) 2016 Broadcom
0003 
0004 #include <linux/clk.h>
0005 #include <linux/delay.h>
0006 #include <linux/err.h>
0007 #include <linux/io.h>
0008 #include <linux/math64.h>
0009 #include <linux/module.h>
0010 #include <linux/of.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/pwm.h>
0013 
0014 #define IPROC_PWM_CTRL_OFFSET           0x00
0015 #define IPROC_PWM_CTRL_TYPE_SHIFT(ch)       (15 + (ch))
0016 #define IPROC_PWM_CTRL_POLARITY_SHIFT(ch)   (8 + (ch))
0017 #define IPROC_PWM_CTRL_EN_SHIFT(ch)     (ch)
0018 
0019 #define IPROC_PWM_PERIOD_OFFSET(ch)     (0x04 + ((ch) << 3))
0020 #define IPROC_PWM_PERIOD_MIN            0x02
0021 #define IPROC_PWM_PERIOD_MAX            0xffff
0022 
0023 #define IPROC_PWM_DUTY_CYCLE_OFFSET(ch)     (0x08 + ((ch) << 3))
0024 #define IPROC_PWM_DUTY_CYCLE_MIN        0x00
0025 #define IPROC_PWM_DUTY_CYCLE_MAX        0xffff
0026 
0027 #define IPROC_PWM_PRESCALE_OFFSET       0x24
0028 #define IPROC_PWM_PRESCALE_BITS         0x06
0029 #define IPROC_PWM_PRESCALE_SHIFT(ch)        ((3 - (ch)) * \
0030                          IPROC_PWM_PRESCALE_BITS)
0031 #define IPROC_PWM_PRESCALE_MASK(ch)     (IPROC_PWM_PRESCALE_MAX << \
0032                          IPROC_PWM_PRESCALE_SHIFT(ch))
0033 #define IPROC_PWM_PRESCALE_MIN          0x00
0034 #define IPROC_PWM_PRESCALE_MAX          0x3f
0035 
0036 struct iproc_pwmc {
0037     struct pwm_chip chip;
0038     void __iomem *base;
0039     struct clk *clk;
0040 };
0041 
0042 static inline struct iproc_pwmc *to_iproc_pwmc(struct pwm_chip *chip)
0043 {
0044     return container_of(chip, struct iproc_pwmc, chip);
0045 }
0046 
0047 static void iproc_pwmc_enable(struct iproc_pwmc *ip, unsigned int channel)
0048 {
0049     u32 value;
0050 
0051     value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
0052     value |= 1 << IPROC_PWM_CTRL_EN_SHIFT(channel);
0053     writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
0054 
0055     /* must be a 400 ns delay between clearing and setting enable bit */
0056     ndelay(400);
0057 }
0058 
0059 static void iproc_pwmc_disable(struct iproc_pwmc *ip, unsigned int channel)
0060 {
0061     u32 value;
0062 
0063     value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
0064     value &= ~(1 << IPROC_PWM_CTRL_EN_SHIFT(channel));
0065     writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
0066 
0067     /* must be a 400 ns delay between clearing and setting enable bit */
0068     ndelay(400);
0069 }
0070 
0071 static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
0072                  struct pwm_state *state)
0073 {
0074     struct iproc_pwmc *ip = to_iproc_pwmc(chip);
0075     u64 tmp, multi, rate;
0076     u32 value, prescale;
0077 
0078     value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
0079 
0080     if (value & BIT(IPROC_PWM_CTRL_EN_SHIFT(pwm->hwpwm)))
0081         state->enabled = true;
0082     else
0083         state->enabled = false;
0084 
0085     if (value & BIT(IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm)))
0086         state->polarity = PWM_POLARITY_NORMAL;
0087     else
0088         state->polarity = PWM_POLARITY_INVERSED;
0089 
0090     rate = clk_get_rate(ip->clk);
0091     if (rate == 0) {
0092         state->period = 0;
0093         state->duty_cycle = 0;
0094         return;
0095     }
0096 
0097     value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
0098     prescale = value >> IPROC_PWM_PRESCALE_SHIFT(pwm->hwpwm);
0099     prescale &= IPROC_PWM_PRESCALE_MAX;
0100 
0101     multi = NSEC_PER_SEC * (prescale + 1);
0102 
0103     value = readl(ip->base + IPROC_PWM_PERIOD_OFFSET(pwm->hwpwm));
0104     tmp = (value & IPROC_PWM_PERIOD_MAX) * multi;
0105     state->period = div64_u64(tmp, rate);
0106 
0107     value = readl(ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm));
0108     tmp = (value & IPROC_PWM_PERIOD_MAX) * multi;
0109     state->duty_cycle = div64_u64(tmp, rate);
0110 }
0111 
0112 static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm,
0113                 const struct pwm_state *state)
0114 {
0115     unsigned long prescale = IPROC_PWM_PRESCALE_MIN;
0116     struct iproc_pwmc *ip = to_iproc_pwmc(chip);
0117     u32 value, period, duty;
0118     u64 rate;
0119 
0120     rate = clk_get_rate(ip->clk);
0121 
0122     /*
0123      * Find period count, duty count and prescale to suit duty_cycle and
0124      * period. This is done according to formulas described below:
0125      *
0126      * period_ns = 10^9 * (PRESCALE + 1) * PC / PWM_CLK_RATE
0127      * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
0128      *
0129      * PC = (PWM_CLK_RATE * period_ns) / (10^9 * (PRESCALE + 1))
0130      * DC = (PWM_CLK_RATE * duty_ns) / (10^9 * (PRESCALE + 1))
0131      */
0132     while (1) {
0133         u64 value, div;
0134 
0135         div = NSEC_PER_SEC * (prescale + 1);
0136         value = rate * state->period;
0137         period = div64_u64(value, div);
0138         value = rate * state->duty_cycle;
0139         duty = div64_u64(value, div);
0140 
0141         if (period < IPROC_PWM_PERIOD_MIN)
0142             return -EINVAL;
0143 
0144         if (period <= IPROC_PWM_PERIOD_MAX &&
0145              duty <= IPROC_PWM_DUTY_CYCLE_MAX)
0146             break;
0147 
0148         /* Otherwise, increase prescale and recalculate counts */
0149         if (++prescale > IPROC_PWM_PRESCALE_MAX)
0150             return -EINVAL;
0151     }
0152 
0153     iproc_pwmc_disable(ip, pwm->hwpwm);
0154 
0155     /* Set prescale */
0156     value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
0157     value &= ~IPROC_PWM_PRESCALE_MASK(pwm->hwpwm);
0158     value |= prescale << IPROC_PWM_PRESCALE_SHIFT(pwm->hwpwm);
0159     writel(value, ip->base + IPROC_PWM_PRESCALE_OFFSET);
0160 
0161     /* set period and duty cycle */
0162     writel(period, ip->base + IPROC_PWM_PERIOD_OFFSET(pwm->hwpwm));
0163     writel(duty, ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(pwm->hwpwm));
0164 
0165     /* set polarity */
0166     value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
0167 
0168     if (state->polarity == PWM_POLARITY_NORMAL)
0169         value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm);
0170     else
0171         value &= ~(1 << IPROC_PWM_CTRL_POLARITY_SHIFT(pwm->hwpwm));
0172 
0173     writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
0174 
0175     if (state->enabled)
0176         iproc_pwmc_enable(ip, pwm->hwpwm);
0177 
0178     return 0;
0179 }
0180 
0181 static const struct pwm_ops iproc_pwm_ops = {
0182     .apply = iproc_pwmc_apply,
0183     .get_state = iproc_pwmc_get_state,
0184     .owner = THIS_MODULE,
0185 };
0186 
0187 static int iproc_pwmc_probe(struct platform_device *pdev)
0188 {
0189     struct iproc_pwmc *ip;
0190     unsigned int i;
0191     u32 value;
0192     int ret;
0193 
0194     ip = devm_kzalloc(&pdev->dev, sizeof(*ip), GFP_KERNEL);
0195     if (!ip)
0196         return -ENOMEM;
0197 
0198     platform_set_drvdata(pdev, ip);
0199 
0200     ip->chip.dev = &pdev->dev;
0201     ip->chip.ops = &iproc_pwm_ops;
0202     ip->chip.npwm = 4;
0203 
0204     ip->base = devm_platform_ioremap_resource(pdev, 0);
0205     if (IS_ERR(ip->base))
0206         return PTR_ERR(ip->base);
0207 
0208     ip->clk = devm_clk_get(&pdev->dev, NULL);
0209     if (IS_ERR(ip->clk)) {
0210         dev_err(&pdev->dev, "failed to get clock: %ld\n",
0211             PTR_ERR(ip->clk));
0212         return PTR_ERR(ip->clk);
0213     }
0214 
0215     ret = clk_prepare_enable(ip->clk);
0216     if (ret < 0) {
0217         dev_err(&pdev->dev, "failed to enable clock: %d\n", ret);
0218         return ret;
0219     }
0220 
0221     /* Set full drive and normal polarity for all channels */
0222     value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
0223 
0224     for (i = 0; i < ip->chip.npwm; i++) {
0225         value &= ~(1 << IPROC_PWM_CTRL_TYPE_SHIFT(i));
0226         value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(i);
0227     }
0228 
0229     writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
0230 
0231     ret = pwmchip_add(&ip->chip);
0232     if (ret < 0) {
0233         dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
0234         clk_disable_unprepare(ip->clk);
0235     }
0236 
0237     return ret;
0238 }
0239 
0240 static int iproc_pwmc_remove(struct platform_device *pdev)
0241 {
0242     struct iproc_pwmc *ip = platform_get_drvdata(pdev);
0243 
0244     pwmchip_remove(&ip->chip);
0245 
0246     clk_disable_unprepare(ip->clk);
0247 
0248     return 0;
0249 }
0250 
0251 static const struct of_device_id bcm_iproc_pwmc_dt[] = {
0252     { .compatible = "brcm,iproc-pwm" },
0253     { },
0254 };
0255 MODULE_DEVICE_TABLE(of, bcm_iproc_pwmc_dt);
0256 
0257 static struct platform_driver iproc_pwmc_driver = {
0258     .driver = {
0259         .name = "bcm-iproc-pwm",
0260         .of_match_table = bcm_iproc_pwmc_dt,
0261     },
0262     .probe = iproc_pwmc_probe,
0263     .remove = iproc_pwmc_remove,
0264 };
0265 module_platform_driver(iproc_pwmc_driver);
0266 
0267 MODULE_AUTHOR("Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>");
0268 MODULE_DESCRIPTION("Broadcom iProc PWM driver");
0269 MODULE_LICENSE("GPL v2");