426 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Imagination Technologies Pulse Width Modulator driver4 *5 * Copyright (c) 2014-2015, Imagination Technologies6 *7 * Based on drivers/pwm/pwm-tegra.c, Copyright (c) 2010, NVIDIA Corporation8 */9 10#include <linux/clk.h>11#include <linux/err.h>12#include <linux/io.h>13#include <linux/mfd/syscon.h>14#include <linux/module.h>15#include <linux/of.h>16#include <linux/platform_device.h>17#include <linux/pm_runtime.h>18#include <linux/property.h>19#include <linux/pwm.h>20#include <linux/regmap.h>21#include <linux/slab.h>22 23/* PWM registers */24#define PWM_CTRL_CFG 0x000025#define PWM_CTRL_CFG_NO_SUB_DIV 026#define PWM_CTRL_CFG_SUB_DIV0 127#define PWM_CTRL_CFG_SUB_DIV1 228#define PWM_CTRL_CFG_SUB_DIV0_DIV1 329#define PWM_CTRL_CFG_DIV_SHIFT(ch) ((ch) * 2 + 4)30#define PWM_CTRL_CFG_DIV_MASK 0x331 32#define PWM_CH_CFG(ch) (0x4 + (ch) * 4)33#define PWM_CH_CFG_TMBASE_SHIFT 034#define PWM_CH_CFG_DUTY_SHIFT 1635 36#define PERIP_PWM_PDM_CONTROL 0x014037#define PERIP_PWM_PDM_CONTROL_CH_MASK 0x138#define PERIP_PWM_PDM_CONTROL_CH_SHIFT(ch) ((ch) * 4)39 40#define IMG_PWM_PM_TIMEOUT 1000 /* ms */41 42/*43 * PWM period is specified with a timebase register,44 * in number of step periods. The PWM duty cycle is also45 * specified in step periods, in the [0, $timebase] range.46 * In other words, the timebase imposes the duty cycle47 * resolution. Therefore, let's constraint the timebase to48 * a minimum value to allow a sane range of duty cycle values.49 * Imposing a minimum timebase, will impose a maximum PWM frequency.50 *51 * The value chosen is completely arbitrary.52 */53#define MIN_TMBASE_STEPS 1654 55#define IMG_PWM_NPWM 456 57struct img_pwm_soc_data {58 u32 max_timebase;59};60 61struct img_pwm_chip {62 struct clk *pwm_clk;63 struct clk *sys_clk;64 void __iomem *base;65 struct regmap *periph_regs;66 int max_period_ns;67 int min_period_ns;68 const struct img_pwm_soc_data *data;69 u32 suspend_ctrl_cfg;70 u32 suspend_ch_cfg[IMG_PWM_NPWM];71};72 73static inline struct img_pwm_chip *to_img_pwm_chip(struct pwm_chip *chip)74{75 return pwmchip_get_drvdata(chip);76}77 78static inline void img_pwm_writel(struct img_pwm_chip *imgchip,79 u32 reg, u32 val)80{81 writel(val, imgchip->base + reg);82}83 84static inline u32 img_pwm_readl(struct img_pwm_chip *imgchip, u32 reg)85{86 return readl(imgchip->base + reg);87}88 89static int img_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,90 int duty_ns, int period_ns)91{92 u32 val, div, duty, timebase;93 unsigned long mul, output_clk_hz, input_clk_hz;94 struct img_pwm_chip *imgchip = to_img_pwm_chip(chip);95 unsigned int max_timebase = imgchip->data->max_timebase;96 int ret;97 98 if (period_ns < imgchip->min_period_ns ||99 period_ns > imgchip->max_period_ns) {100 dev_err(pwmchip_parent(chip), "configured period not in range\n");101 return -ERANGE;102 }103 104 input_clk_hz = clk_get_rate(imgchip->pwm_clk);105 output_clk_hz = DIV_ROUND_UP(NSEC_PER_SEC, period_ns);106 107 mul = DIV_ROUND_UP(input_clk_hz, output_clk_hz);108 if (mul <= max_timebase) {109 div = PWM_CTRL_CFG_NO_SUB_DIV;110 timebase = DIV_ROUND_UP(mul, 1);111 } else if (mul <= max_timebase * 8) {112 div = PWM_CTRL_CFG_SUB_DIV0;113 timebase = DIV_ROUND_UP(mul, 8);114 } else if (mul <= max_timebase * 64) {115 div = PWM_CTRL_CFG_SUB_DIV1;116 timebase = DIV_ROUND_UP(mul, 64);117 } else if (mul <= max_timebase * 512) {118 div = PWM_CTRL_CFG_SUB_DIV0_DIV1;119 timebase = DIV_ROUND_UP(mul, 512);120 } else {121 dev_err(pwmchip_parent(chip),122 "failed to configure timebase steps/divider value\n");123 return -EINVAL;124 }125 126 duty = DIV_ROUND_UP(timebase * duty_ns, period_ns);127 128 ret = pm_runtime_resume_and_get(pwmchip_parent(chip));129 if (ret < 0)130 return ret;131 132 val = img_pwm_readl(imgchip, PWM_CTRL_CFG);133 val &= ~(PWM_CTRL_CFG_DIV_MASK << PWM_CTRL_CFG_DIV_SHIFT(pwm->hwpwm));134 val |= (div & PWM_CTRL_CFG_DIV_MASK) <<135 PWM_CTRL_CFG_DIV_SHIFT(pwm->hwpwm);136 img_pwm_writel(imgchip, PWM_CTRL_CFG, val);137 138 val = (duty << PWM_CH_CFG_DUTY_SHIFT) |139 (timebase << PWM_CH_CFG_TMBASE_SHIFT);140 img_pwm_writel(imgchip, PWM_CH_CFG(pwm->hwpwm), val);141 142 pm_runtime_mark_last_busy(pwmchip_parent(chip));143 pm_runtime_put_autosuspend(pwmchip_parent(chip));144 145 return 0;146}147 148static int img_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)149{150 u32 val;151 struct img_pwm_chip *imgchip = to_img_pwm_chip(chip);152 int ret;153 154 ret = pm_runtime_resume_and_get(pwmchip_parent(chip));155 if (ret < 0)156 return ret;157 158 val = img_pwm_readl(imgchip, PWM_CTRL_CFG);159 val |= BIT(pwm->hwpwm);160 img_pwm_writel(imgchip, PWM_CTRL_CFG, val);161 162 regmap_clear_bits(imgchip->periph_regs, PERIP_PWM_PDM_CONTROL,163 PERIP_PWM_PDM_CONTROL_CH_MASK <<164 PERIP_PWM_PDM_CONTROL_CH_SHIFT(pwm->hwpwm));165 166 return 0;167}168 169static void img_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)170{171 u32 val;172 struct img_pwm_chip *imgchip = to_img_pwm_chip(chip);173 174 val = img_pwm_readl(imgchip, PWM_CTRL_CFG);175 val &= ~BIT(pwm->hwpwm);176 img_pwm_writel(imgchip, PWM_CTRL_CFG, val);177 178 pm_runtime_mark_last_busy(pwmchip_parent(chip));179 pm_runtime_put_autosuspend(pwmchip_parent(chip));180}181 182static int img_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,183 const struct pwm_state *state)184{185 int err;186 187 if (state->polarity != PWM_POLARITY_NORMAL)188 return -EINVAL;189 190 if (!state->enabled) {191 if (pwm->state.enabled)192 img_pwm_disable(chip, pwm);193 194 return 0;195 }196 197 err = img_pwm_config(chip, pwm, state->duty_cycle, state->period);198 if (err)199 return err;200 201 if (!pwm->state.enabled)202 err = img_pwm_enable(chip, pwm);203 204 return err;205}206 207static const struct pwm_ops img_pwm_ops = {208 .apply = img_pwm_apply,209};210 211static const struct img_pwm_soc_data pistachio_pwm = {212 .max_timebase = 255,213};214 215static const struct of_device_id img_pwm_of_match[] = {216 {217 .compatible = "img,pistachio-pwm",218 .data = &pistachio_pwm,219 },220 { }221};222MODULE_DEVICE_TABLE(of, img_pwm_of_match);223 224static int img_pwm_runtime_suspend(struct device *dev)225{226 struct pwm_chip *chip = dev_get_drvdata(dev);227 struct img_pwm_chip *imgchip = to_img_pwm_chip(chip);228 229 clk_disable_unprepare(imgchip->pwm_clk);230 clk_disable_unprepare(imgchip->sys_clk);231 232 return 0;233}234 235static int img_pwm_runtime_resume(struct device *dev)236{237 struct pwm_chip *chip = dev_get_drvdata(dev);238 struct img_pwm_chip *imgchip = to_img_pwm_chip(chip);239 int ret;240 241 ret = clk_prepare_enable(imgchip->sys_clk);242 if (ret < 0) {243 dev_err(dev, "could not prepare or enable sys clock\n");244 return ret;245 }246 247 ret = clk_prepare_enable(imgchip->pwm_clk);248 if (ret < 0) {249 dev_err(dev, "could not prepare or enable pwm clock\n");250 clk_disable_unprepare(imgchip->sys_clk);251 return ret;252 }253 254 return 0;255}256 257static int img_pwm_probe(struct platform_device *pdev)258{259 int ret;260 u64 val;261 unsigned long clk_rate;262 struct pwm_chip *chip;263 struct img_pwm_chip *imgchip;264 265 chip = devm_pwmchip_alloc(&pdev->dev, IMG_PWM_NPWM, sizeof(*imgchip));266 if (IS_ERR(chip))267 return PTR_ERR(chip);268 imgchip = to_img_pwm_chip(chip);269 270 imgchip->base = devm_platform_ioremap_resource(pdev, 0);271 if (IS_ERR(imgchip->base))272 return PTR_ERR(imgchip->base);273 274 imgchip->data = device_get_match_data(&pdev->dev);275 276 imgchip->periph_regs = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,277 "img,cr-periph");278 if (IS_ERR(imgchip->periph_regs))279 return PTR_ERR(imgchip->periph_regs);280 281 imgchip->sys_clk = devm_clk_get(&pdev->dev, "sys");282 if (IS_ERR(imgchip->sys_clk)) {283 dev_err(&pdev->dev, "failed to get system clock\n");284 return PTR_ERR(imgchip->sys_clk);285 }286 287 imgchip->pwm_clk = devm_clk_get(&pdev->dev, "pwm");288 if (IS_ERR(imgchip->pwm_clk)) {289 dev_err(&pdev->dev, "failed to get pwm clock\n");290 return PTR_ERR(imgchip->pwm_clk);291 }292 293 platform_set_drvdata(pdev, chip);294 295 pm_runtime_set_autosuspend_delay(&pdev->dev, IMG_PWM_PM_TIMEOUT);296 pm_runtime_use_autosuspend(&pdev->dev);297 pm_runtime_enable(&pdev->dev);298 if (!pm_runtime_enabled(&pdev->dev)) {299 ret = img_pwm_runtime_resume(&pdev->dev);300 if (ret)301 goto err_pm_disable;302 }303 304 clk_rate = clk_get_rate(imgchip->pwm_clk);305 if (!clk_rate) {306 dev_err(&pdev->dev, "imgchip clock has no frequency\n");307 ret = -EINVAL;308 goto err_suspend;309 }310 311 /* The maximum input clock divider is 512 */312 val = (u64)NSEC_PER_SEC * 512 * imgchip->data->max_timebase;313 do_div(val, clk_rate);314 imgchip->max_period_ns = val;315 316 val = (u64)NSEC_PER_SEC * MIN_TMBASE_STEPS;317 do_div(val, clk_rate);318 imgchip->min_period_ns = val;319 320 chip->ops = &img_pwm_ops;321 322 ret = pwmchip_add(chip);323 if (ret < 0) {324 dev_err(&pdev->dev, "pwmchip_add failed: %d\n", ret);325 goto err_suspend;326 }327 328 return 0;329 330err_suspend:331 if (!pm_runtime_enabled(&pdev->dev))332 img_pwm_runtime_suspend(&pdev->dev);333err_pm_disable:334 pm_runtime_disable(&pdev->dev);335 pm_runtime_dont_use_autosuspend(&pdev->dev);336 return ret;337}338 339static void img_pwm_remove(struct platform_device *pdev)340{341 struct pwm_chip *chip = platform_get_drvdata(pdev);342 343 pm_runtime_disable(&pdev->dev);344 if (!pm_runtime_status_suspended(&pdev->dev))345 img_pwm_runtime_suspend(&pdev->dev);346 347 pwmchip_remove(chip);348}349 350#ifdef CONFIG_PM_SLEEP351static int img_pwm_suspend(struct device *dev)352{353 struct pwm_chip *chip = dev_get_drvdata(dev);354 struct img_pwm_chip *imgchip = to_img_pwm_chip(chip);355 int i, ret;356 357 if (pm_runtime_status_suspended(dev)) {358 ret = img_pwm_runtime_resume(dev);359 if (ret)360 return ret;361 }362 363 for (i = 0; i < chip->npwm; i++)364 imgchip->suspend_ch_cfg[i] = img_pwm_readl(imgchip,365 PWM_CH_CFG(i));366 367 imgchip->suspend_ctrl_cfg = img_pwm_readl(imgchip, PWM_CTRL_CFG);368 369 img_pwm_runtime_suspend(dev);370 371 return 0;372}373 374static int img_pwm_resume(struct device *dev)375{376 struct pwm_chip *chip = dev_get_drvdata(dev);377 struct img_pwm_chip *imgchip = to_img_pwm_chip(chip);378 int ret;379 int i;380 381 ret = img_pwm_runtime_resume(dev);382 if (ret)383 return ret;384 385 for (i = 0; i < chip->npwm; i++)386 img_pwm_writel(imgchip, PWM_CH_CFG(i),387 imgchip->suspend_ch_cfg[i]);388 389 img_pwm_writel(imgchip, PWM_CTRL_CFG, imgchip->suspend_ctrl_cfg);390 391 for (i = 0; i < chip->npwm; i++)392 if (imgchip->suspend_ctrl_cfg & BIT(i))393 regmap_clear_bits(imgchip->periph_regs,394 PERIP_PWM_PDM_CONTROL,395 PERIP_PWM_PDM_CONTROL_CH_MASK <<396 PERIP_PWM_PDM_CONTROL_CH_SHIFT(i));397 398 if (pm_runtime_status_suspended(dev))399 img_pwm_runtime_suspend(dev);400 401 return 0;402}403#endif /* CONFIG_PM */404 405static const struct dev_pm_ops img_pwm_pm_ops = {406 SET_RUNTIME_PM_OPS(img_pwm_runtime_suspend,407 img_pwm_runtime_resume,408 NULL)409 SET_SYSTEM_SLEEP_PM_OPS(img_pwm_suspend, img_pwm_resume)410};411 412static struct platform_driver img_pwm_driver = {413 .driver = {414 .name = "img-pwm",415 .pm = &img_pwm_pm_ops,416 .of_match_table = img_pwm_of_match,417 },418 .probe = img_pwm_probe,419 .remove = img_pwm_remove,420};421module_platform_driver(img_pwm_driver);422 423MODULE_AUTHOR("Sai Masarapu <Sai.Masarapu@imgtec.com>");424MODULE_DESCRIPTION("Imagination Technologies PWM DAC driver");425MODULE_LICENSE("GPL v2");426