0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 #include <linux/err.h>
0022 #include <linux/io.h>
0023 #include <linux/module.h>
0024 #include <linux/of_device.h>
0025 #include <linux/platform_device.h>
0026 #include <linux/pwm.h>
0027
0028 #define PIPGM_PCSR(ch) (0x400 + 4 * (ch))
0029 #define PIPGM_PDUT(ch) (0x420 + 4 * (ch))
0030 #define PIPGM_PWMC(ch) (0x440 + 4 * (ch))
0031
0032 #define PIPGM_PWMC_PWMACT BIT(5)
0033 #define PIPGM_PWMC_CLK_MASK GENMASK(1, 0)
0034 #define PIPGM_PWMC_POLARITY_MASK GENMASK(5, 5)
0035
0036 struct visconti_pwm_chip {
0037 struct pwm_chip chip;
0038 void __iomem *base;
0039 };
0040
0041 static inline struct visconti_pwm_chip *visconti_pwm_from_chip(struct pwm_chip *chip)
0042 {
0043 return container_of(chip, struct visconti_pwm_chip, chip);
0044 }
0045
0046 static int visconti_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
0047 const struct pwm_state *state)
0048 {
0049 struct visconti_pwm_chip *priv = visconti_pwm_from_chip(chip);
0050 u32 period, duty_cycle, pwmc0;
0051
0052 if (!state->enabled) {
0053 writel(0, priv->base + PIPGM_PCSR(pwm->hwpwm));
0054 return 0;
0055 }
0056
0057
0058
0059
0060
0061
0062
0063 if (state->period > (0xffff << 3) * 1000)
0064 period = (0xffff << 3) * 1000;
0065 else
0066 period = state->period;
0067
0068 if (state->duty_cycle > period)
0069 duty_cycle = period;
0070 else
0071 duty_cycle = state->duty_cycle;
0072
0073
0074
0075
0076
0077
0078 period /= 1000;
0079 duty_cycle /= 1000;
0080
0081 if (!period)
0082 return -ERANGE;
0083
0084
0085
0086
0087
0088
0089
0090 pwmc0 = fls(period >> 16);
0091 if (WARN_ON(pwmc0 > 3))
0092 return -EINVAL;
0093
0094 period >>= pwmc0;
0095 duty_cycle >>= pwmc0;
0096
0097 if (state->polarity == PWM_POLARITY_INVERSED)
0098 pwmc0 |= PIPGM_PWMC_PWMACT;
0099 writel(pwmc0, priv->base + PIPGM_PWMC(pwm->hwpwm));
0100 writel(duty_cycle, priv->base + PIPGM_PDUT(pwm->hwpwm));
0101 writel(period, priv->base + PIPGM_PCSR(pwm->hwpwm));
0102
0103 return 0;
0104 }
0105
0106 static void visconti_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
0107 struct pwm_state *state)
0108 {
0109 struct visconti_pwm_chip *priv = visconti_pwm_from_chip(chip);
0110 u32 period, duty, pwmc0, pwmc0_clk;
0111
0112 period = readl(priv->base + PIPGM_PCSR(pwm->hwpwm));
0113 duty = readl(priv->base + PIPGM_PDUT(pwm->hwpwm));
0114 pwmc0 = readl(priv->base + PIPGM_PWMC(pwm->hwpwm));
0115 pwmc0_clk = pwmc0 & PIPGM_PWMC_CLK_MASK;
0116
0117 state->period = (period << pwmc0_clk) * NSEC_PER_USEC;
0118 state->duty_cycle = (duty << pwmc0_clk) * NSEC_PER_USEC;
0119 if (pwmc0 & PIPGM_PWMC_POLARITY_MASK)
0120 state->polarity = PWM_POLARITY_INVERSED;
0121 else
0122 state->polarity = PWM_POLARITY_NORMAL;
0123
0124 state->enabled = true;
0125 }
0126
0127 static const struct pwm_ops visconti_pwm_ops = {
0128 .apply = visconti_pwm_apply,
0129 .get_state = visconti_pwm_get_state,
0130 .owner = THIS_MODULE,
0131 };
0132
0133 static int visconti_pwm_probe(struct platform_device *pdev)
0134 {
0135 struct device *dev = &pdev->dev;
0136 struct visconti_pwm_chip *priv;
0137 int ret;
0138
0139 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0140 if (!priv)
0141 return -ENOMEM;
0142
0143 priv->base = devm_platform_ioremap_resource(pdev, 0);
0144 if (IS_ERR(priv->base))
0145 return PTR_ERR(priv->base);
0146
0147 priv->chip.dev = dev;
0148 priv->chip.ops = &visconti_pwm_ops;
0149 priv->chip.npwm = 4;
0150
0151 ret = devm_pwmchip_add(&pdev->dev, &priv->chip);
0152 if (ret < 0)
0153 return dev_err_probe(&pdev->dev, ret, "Cannot register visconti PWM\n");
0154
0155 return 0;
0156 }
0157
0158 static const struct of_device_id visconti_pwm_of_match[] = {
0159 { .compatible = "toshiba,visconti-pwm", },
0160 { }
0161 };
0162 MODULE_DEVICE_TABLE(of, visconti_pwm_of_match);
0163
0164 static struct platform_driver visconti_pwm_driver = {
0165 .driver = {
0166 .name = "pwm-visconti",
0167 .of_match_table = visconti_pwm_of_match,
0168 },
0169 .probe = visconti_pwm_probe,
0170 };
0171 module_platform_driver(visconti_pwm_driver);
0172
0173 MODULE_LICENSE("GPL v2");
0174 MODULE_AUTHOR("Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>");
0175 MODULE_ALIAS("platform:pwm-visconti");