0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/err.h>
0011 #include <linux/io.h>
0012 #include <linux/ioport.h>
0013 #include <linux/kernel.h>
0014 #include <linux/module.h>
0015 #include <linux/clk.h>
0016 #include <linux/of.h>
0017 #include <linux/of_device.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/pwm.h>
0020 #include <linux/slab.h>
0021 #include <linux/types.h>
0022
0023
0024 #define PWMCON 0x00
0025 #define PWMHDUR 0x04
0026 #define PWMLDUR 0x08
0027 #define PWMGDUR 0x0c
0028 #define PWMWAVENUM 0x28
0029 #define PWMDWIDTH 0x2c
0030 #define PWM45DWIDTH_FIXUP 0x30
0031 #define PWMTHRES 0x30
0032 #define PWM45THRES_FIXUP 0x34
0033 #define PWM_CK_26M_SEL 0x210
0034
0035 #define PWM_CLK_DIV_MAX 7
0036
0037 struct pwm_mediatek_of_data {
0038 unsigned int num_pwms;
0039 bool pwm45_fixup;
0040 bool has_ck_26m_sel;
0041 };
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 struct pwm_mediatek_chip {
0054 struct pwm_chip chip;
0055 void __iomem *regs;
0056 struct clk *clk_top;
0057 struct clk *clk_main;
0058 struct clk **clk_pwms;
0059 const struct pwm_mediatek_of_data *soc;
0060 };
0061
0062 static const unsigned int pwm_mediatek_reg_offset[] = {
0063 0x0010, 0x0050, 0x0090, 0x00d0, 0x0110, 0x0150, 0x0190, 0x0220
0064 };
0065
0066 static inline struct pwm_mediatek_chip *
0067 to_pwm_mediatek_chip(struct pwm_chip *chip)
0068 {
0069 return container_of(chip, struct pwm_mediatek_chip, chip);
0070 }
0071
0072 static int pwm_mediatek_clk_enable(struct pwm_chip *chip,
0073 struct pwm_device *pwm)
0074 {
0075 struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
0076 int ret;
0077
0078 ret = clk_prepare_enable(pc->clk_top);
0079 if (ret < 0)
0080 return ret;
0081
0082 ret = clk_prepare_enable(pc->clk_main);
0083 if (ret < 0)
0084 goto disable_clk_top;
0085
0086 ret = clk_prepare_enable(pc->clk_pwms[pwm->hwpwm]);
0087 if (ret < 0)
0088 goto disable_clk_main;
0089
0090 return 0;
0091
0092 disable_clk_main:
0093 clk_disable_unprepare(pc->clk_main);
0094 disable_clk_top:
0095 clk_disable_unprepare(pc->clk_top);
0096
0097 return ret;
0098 }
0099
0100 static void pwm_mediatek_clk_disable(struct pwm_chip *chip,
0101 struct pwm_device *pwm)
0102 {
0103 struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
0104
0105 clk_disable_unprepare(pc->clk_pwms[pwm->hwpwm]);
0106 clk_disable_unprepare(pc->clk_main);
0107 clk_disable_unprepare(pc->clk_top);
0108 }
0109
0110 static inline void pwm_mediatek_writel(struct pwm_mediatek_chip *chip,
0111 unsigned int num, unsigned int offset,
0112 u32 value)
0113 {
0114 writel(value, chip->regs + pwm_mediatek_reg_offset[num] + offset);
0115 }
0116
0117 static int pwm_mediatek_config(struct pwm_chip *chip, struct pwm_device *pwm,
0118 int duty_ns, int period_ns)
0119 {
0120 struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
0121 u32 clkdiv = 0, cnt_period, cnt_duty, reg_width = PWMDWIDTH,
0122 reg_thres = PWMTHRES;
0123 u64 resolution;
0124 int ret;
0125
0126 ret = pwm_mediatek_clk_enable(chip, pwm);
0127
0128 if (ret < 0)
0129 return ret;
0130
0131
0132 if (pc->soc->has_ck_26m_sel)
0133 writel(0, pc->regs + PWM_CK_26M_SEL);
0134
0135
0136 resolution = (u64)NSEC_PER_SEC * 1000;
0137 do_div(resolution, clk_get_rate(pc->clk_pwms[pwm->hwpwm]));
0138
0139 cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000, resolution);
0140 while (cnt_period > 8191) {
0141 resolution *= 2;
0142 clkdiv++;
0143 cnt_period = DIV_ROUND_CLOSEST_ULL((u64)period_ns * 1000,
0144 resolution);
0145 }
0146
0147 if (clkdiv > PWM_CLK_DIV_MAX) {
0148 pwm_mediatek_clk_disable(chip, pwm);
0149 dev_err(chip->dev, "period of %d ns not supported\n", period_ns);
0150 return -EINVAL;
0151 }
0152
0153 if (pc->soc->pwm45_fixup && pwm->hwpwm > 2) {
0154
0155
0156
0157
0158 reg_width = PWM45DWIDTH_FIXUP;
0159 reg_thres = PWM45THRES_FIXUP;
0160 }
0161
0162 cnt_duty = DIV_ROUND_CLOSEST_ULL((u64)duty_ns * 1000, resolution);
0163 pwm_mediatek_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | clkdiv);
0164 pwm_mediatek_writel(pc, pwm->hwpwm, reg_width, cnt_period);
0165 pwm_mediatek_writel(pc, pwm->hwpwm, reg_thres, cnt_duty);
0166
0167 pwm_mediatek_clk_disable(chip, pwm);
0168
0169 return 0;
0170 }
0171
0172 static int pwm_mediatek_enable(struct pwm_chip *chip, struct pwm_device *pwm)
0173 {
0174 struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
0175 u32 value;
0176 int ret;
0177
0178 ret = pwm_mediatek_clk_enable(chip, pwm);
0179 if (ret < 0)
0180 return ret;
0181
0182 value = readl(pc->regs);
0183 value |= BIT(pwm->hwpwm);
0184 writel(value, pc->regs);
0185
0186 return 0;
0187 }
0188
0189 static void pwm_mediatek_disable(struct pwm_chip *chip, struct pwm_device *pwm)
0190 {
0191 struct pwm_mediatek_chip *pc = to_pwm_mediatek_chip(chip);
0192 u32 value;
0193
0194 value = readl(pc->regs);
0195 value &= ~BIT(pwm->hwpwm);
0196 writel(value, pc->regs);
0197
0198 pwm_mediatek_clk_disable(chip, pwm);
0199 }
0200
0201 static int pwm_mediatek_apply(struct pwm_chip *chip, struct pwm_device *pwm,
0202 const struct pwm_state *state)
0203 {
0204 int err;
0205
0206 if (state->polarity != PWM_POLARITY_NORMAL)
0207 return -EINVAL;
0208
0209 if (!state->enabled) {
0210 if (pwm->state.enabled)
0211 pwm_mediatek_disable(chip, pwm);
0212
0213 return 0;
0214 }
0215
0216 err = pwm_mediatek_config(pwm->chip, pwm, state->duty_cycle, state->period);
0217 if (err)
0218 return err;
0219
0220 if (!pwm->state.enabled)
0221 err = pwm_mediatek_enable(chip, pwm);
0222
0223 return err;
0224 }
0225
0226 static const struct pwm_ops pwm_mediatek_ops = {
0227 .apply = pwm_mediatek_apply,
0228 .owner = THIS_MODULE,
0229 };
0230
0231 static int pwm_mediatek_probe(struct platform_device *pdev)
0232 {
0233 struct pwm_mediatek_chip *pc;
0234 unsigned int i;
0235 int ret;
0236
0237 pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
0238 if (!pc)
0239 return -ENOMEM;
0240
0241 pc->soc = of_device_get_match_data(&pdev->dev);
0242
0243 pc->regs = devm_platform_ioremap_resource(pdev, 0);
0244 if (IS_ERR(pc->regs))
0245 return PTR_ERR(pc->regs);
0246
0247 pc->clk_pwms = devm_kmalloc_array(&pdev->dev, pc->soc->num_pwms,
0248 sizeof(*pc->clk_pwms), GFP_KERNEL);
0249 if (!pc->clk_pwms)
0250 return -ENOMEM;
0251
0252 pc->clk_top = devm_clk_get(&pdev->dev, "top");
0253 if (IS_ERR(pc->clk_top))
0254 return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_top),
0255 "Failed to get top clock\n");
0256
0257 pc->clk_main = devm_clk_get(&pdev->dev, "main");
0258 if (IS_ERR(pc->clk_main))
0259 return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_main),
0260 "Failed to get main clock\n");
0261
0262 for (i = 0; i < pc->soc->num_pwms; i++) {
0263 char name[8];
0264
0265 snprintf(name, sizeof(name), "pwm%d", i + 1);
0266
0267 pc->clk_pwms[i] = devm_clk_get(&pdev->dev, name);
0268 if (IS_ERR(pc->clk_pwms[i]))
0269 return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk_pwms[i]),
0270 "Failed to get %s clock\n", name);
0271 }
0272
0273 pc->chip.dev = &pdev->dev;
0274 pc->chip.ops = &pwm_mediatek_ops;
0275 pc->chip.npwm = pc->soc->num_pwms;
0276
0277 ret = devm_pwmchip_add(&pdev->dev, &pc->chip);
0278 if (ret < 0)
0279 return dev_err_probe(&pdev->dev, ret, "pwmchip_add() failed\n");
0280
0281 return 0;
0282 }
0283
0284 static const struct pwm_mediatek_of_data mt2712_pwm_data = {
0285 .num_pwms = 8,
0286 .pwm45_fixup = false,
0287 .has_ck_26m_sel = false,
0288 };
0289
0290 static const struct pwm_mediatek_of_data mt6795_pwm_data = {
0291 .num_pwms = 7,
0292 .pwm45_fixup = false,
0293 .has_ck_26m_sel = false,
0294 };
0295
0296 static const struct pwm_mediatek_of_data mt7622_pwm_data = {
0297 .num_pwms = 6,
0298 .pwm45_fixup = false,
0299 .has_ck_26m_sel = false,
0300 };
0301
0302 static const struct pwm_mediatek_of_data mt7623_pwm_data = {
0303 .num_pwms = 5,
0304 .pwm45_fixup = true,
0305 .has_ck_26m_sel = false,
0306 };
0307
0308 static const struct pwm_mediatek_of_data mt7628_pwm_data = {
0309 .num_pwms = 4,
0310 .pwm45_fixup = true,
0311 .has_ck_26m_sel = false,
0312 };
0313
0314 static const struct pwm_mediatek_of_data mt7629_pwm_data = {
0315 .num_pwms = 1,
0316 .pwm45_fixup = false,
0317 .has_ck_26m_sel = false,
0318 };
0319
0320 static const struct pwm_mediatek_of_data mt8183_pwm_data = {
0321 .num_pwms = 4,
0322 .pwm45_fixup = false,
0323 .has_ck_26m_sel = true,
0324 };
0325
0326 static const struct pwm_mediatek_of_data mt8365_pwm_data = {
0327 .num_pwms = 3,
0328 .pwm45_fixup = false,
0329 .has_ck_26m_sel = true,
0330 };
0331
0332 static const struct pwm_mediatek_of_data mt8516_pwm_data = {
0333 .num_pwms = 5,
0334 .pwm45_fixup = false,
0335 .has_ck_26m_sel = true,
0336 };
0337
0338 static const struct of_device_id pwm_mediatek_of_match[] = {
0339 { .compatible = "mediatek,mt2712-pwm", .data = &mt2712_pwm_data },
0340 { .compatible = "mediatek,mt6795-pwm", .data = &mt6795_pwm_data },
0341 { .compatible = "mediatek,mt7622-pwm", .data = &mt7622_pwm_data },
0342 { .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data },
0343 { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data },
0344 { .compatible = "mediatek,mt7629-pwm", .data = &mt7629_pwm_data },
0345 { .compatible = "mediatek,mt8183-pwm", .data = &mt8183_pwm_data },
0346 { .compatible = "mediatek,mt8365-pwm", .data = &mt8365_pwm_data },
0347 { .compatible = "mediatek,mt8516-pwm", .data = &mt8516_pwm_data },
0348 { },
0349 };
0350 MODULE_DEVICE_TABLE(of, pwm_mediatek_of_match);
0351
0352 static struct platform_driver pwm_mediatek_driver = {
0353 .driver = {
0354 .name = "pwm-mediatek",
0355 .of_match_table = pwm_mediatek_of_match,
0356 },
0357 .probe = pwm_mediatek_probe,
0358 };
0359 module_platform_driver(pwm_mediatek_driver);
0360
0361 MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
0362 MODULE_LICENSE("GPL v2");