1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * PWM driver for Rockchip SoCs 4 * 5 * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com> 6 * Copyright (C) 2014 ROCKCHIP, Inc. 7 */ 8 9#include <linux/clk.h> 10#include <linux/io.h> 11#include <linux/module.h> 12#include <linux/of.h> 13#include <linux/of_device.h> 14#include <linux/pinctrl/consumer.h> 15#include <linux/platform_device.h> 16#include <linux/pwm.h> 17#include <linux/time.h> 18 19#define PWM_CTRL_TIMER_EN (1 << 0) 20#define PWM_CTRL_OUTPUT_EN (1 << 3) 21 22#define PWM_ENABLE (1 << 0) 23#define PWM_CONTINUOUS (1 << 1) 24#define PWM_DUTY_POSITIVE (1 << 3) 25#define PWM_DUTY_NEGATIVE (0 << 3) 26#define PWM_INACTIVE_NEGATIVE (0 << 4) 27#define PWM_INACTIVE_POSITIVE (1 << 4) 28#define PWM_POLARITY_MASK (PWM_DUTY_POSITIVE | PWM_INACTIVE_POSITIVE) 29#define PWM_OUTPUT_LEFT (0 << 5) 30#define PWM_OUTPUT_CENTER (1 << 5) 31#define PWM_LOCK_EN (1 << 6) 32#define PWM_LP_DISABLE (0 << 8) 33 34#define PWM_ONESHOT_COUNT_SHIFT 24 35#define PWM_ONESHOT_COUNT_MAX 256 36#define PWM_COUNT 2 37#define PWM_CELLS 3 38 39struct rockchip_pwm_chip { 40 struct pwm_chip chip; 41 struct clk *clk; 42 struct clk *pclk; 43 struct pinctrl *pinctrl; 44 struct pinctrl_state *active_state; 45 const struct rockchip_pwm_data *data; 46 void __iomem *base; 47 unsigned long clk_rate; 48 bool vop_pwm_en; /* indicate voppwm mirror register state */ 49 bool center_aligned; 50 bool oneshot; 51}; 52 53struct rockchip_pwm_regs { 54 unsigned long duty; 55 unsigned long period; 56 unsigned long cntr; 57 unsigned long ctrl; 58}; 59 60struct rockchip_pwm_data { 61 struct rockchip_pwm_regs regs; 62 unsigned int prescaler; 63 bool supports_polarity; 64 bool supports_lock; 65 bool vop_pwm; 66 u32 enable_conf; 67 u32 enable_conf_mask; 68}; 69 70static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c) 71{ 72 return container_of(c, struct rockchip_pwm_chip, chip); 73} 74 75static void rockchip_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state) 76{ 77 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 78 u32 enable_conf = pc->data->enable_conf; 79 u64 tmp; 80 u32 val; 81 int ret; 82 83 ret = clk_enable(pc->pclk); 84 if (ret) { 85 return; 86 } 87 88 tmp = readl_relaxed(pc->base + pc->data->regs.period); 89 tmp *= pc->data->prescaler * NSEC_PER_SEC; 90 state->period = DIV_ROUND_CLOSEST_ULL(tmp, pc->clk_rate); 91 92 tmp = readl_relaxed(pc->base + pc->data->regs.duty); 93 tmp *= pc->data->prescaler * NSEC_PER_SEC; 94 state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, pc->clk_rate); 95 96 val = readl_relaxed(pc->base + pc->data->regs.ctrl); 97 state->enabled = (val & enable_conf) == enable_conf; 98 99 if (pc->data->supports_polarity && !(val & PWM_DUTY_POSITIVE)) { 100 state->polarity = PWM_POLARITY_INVERSED; 101 } else { 102 state->polarity = PWM_POLARITY_NORMAL; 103 } 104 105 clk_disable(pc->pclk); 106} 107 108static void rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) 109{ 110 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 111 unsigned long period, duty; 112 unsigned long flags; 113 u64 div; 114 u32 ctrl; 115 116 /* 117 * Since period and duty cycle registers have a width of 32 118 * bits, every possible input period can be obtained using the 119 * default prescaler value for all practical clock rate values. 120 */ 121 div = (u64)pc->clk_rate * state->period; 122 period = DIV_ROUND_CLOSEST_ULL(div, pc->data->prescaler * NSEC_PER_SEC); 123 124 div = (u64)pc->clk_rate * state->duty_cycle; 125 duty = DIV_ROUND_CLOSEST_ULL(div, pc->data->prescaler * NSEC_PER_SEC); 126 127 local_irq_save(flags); 128 /* 129 * Lock the period and duty of previous configuration, then 130 * change the duty and period, that would not be effective. 131 */ 132 ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); 133 if (pc->data->vop_pwm) { 134 if (pc->vop_pwm_en) { 135 ctrl |= PWM_ENABLE; 136 } else { 137 ctrl &= ~PWM_ENABLE; 138 } 139 } 140 141#ifdef CONFIG_PWM_ROCKCHIP_ONESHOT 142 if (state->oneshot_count > PWM_ONESHOT_COUNT_MAX) { 143 pc->oneshot = false; 144 dev_err(chip->dev, "Oneshot_count value overflow.\n"); 145 } else if (state->oneshot_count > 0) { 146 pc->oneshot = true; 147 ctrl |= (state->oneshot_count - 1) << PWM_ONESHOT_COUNT_SHIFT; 148 } else { 149 pc->oneshot = false; 150 ctrl |= PWM_CONTINUOUS; 151 } 152#endif 153 154 if (pc->data->supports_lock) { 155 ctrl |= PWM_LOCK_EN; 156 writel_relaxed(ctrl, pc->base + pc->data->regs.ctrl); 157 } 158 159 writel(period, pc->base + pc->data->regs.period); 160 writel(duty, pc->base + pc->data->regs.duty); 161 162 if (pc->data->supports_polarity) { 163 ctrl &= ~PWM_POLARITY_MASK; 164 if (state->polarity == PWM_POLARITY_INVERSED) { 165 ctrl |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSITIVE; 166 } else { 167 ctrl |= PWM_DUTY_POSITIVE | PWM_INACTIVE_NEGATIVE; 168 } 169 } 170 171 /* 172 * Unlock and set polarity at the same time, 173 * the configuration of duty, period and polarity 174 * would be effective together at next period. 175 */ 176 if (pc->data->supports_lock) { 177 ctrl &= ~PWM_LOCK_EN; 178 } 179 180 writel(ctrl, pc->base + pc->data->regs.ctrl); 181 local_irq_restore(flags); 182} 183 184static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm, bool enable) 185{ 186 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 187 u32 enable_conf = pc->data->enable_conf; 188 int ret; 189 u32 val; 190 191 if (enable) { 192 ret = clk_enable(pc->clk); 193 if (ret) { 194 return ret; 195 } 196 } 197 198 val = readl_relaxed(pc->base + pc->data->regs.ctrl); 199 val &= ~pc->data->enable_conf_mask; 200 201 if (PWM_OUTPUT_CENTER & pc->data->enable_conf_mask) { 202 if (pc->center_aligned) { 203 val |= PWM_OUTPUT_CENTER; 204 } 205 } 206 207 if (enable) { 208 val |= enable_conf; 209 if (pc->oneshot) { 210 val &= ~PWM_CONTINUOUS; 211 } 212 } else { 213 val &= ~enable_conf; 214 } 215 216 writel_relaxed(val, pc->base + pc->data->regs.ctrl); 217 if (pc->data->vop_pwm) { 218 pc->vop_pwm_en = enable; 219 } 220 221 if (!enable) { 222 clk_disable(pc->clk); 223 } 224 225 return 0; 226} 227 228static int rockchip_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_state *state) 229{ 230 struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip); 231 struct pwm_state curstate; 232 bool enabled; 233 int ret = 0; 234 235 ret = clk_enable(pc->pclk); 236 if (ret) { 237 return ret; 238 } 239 240 pwm_get_state(pwm, &curstate); 241 enabled = curstate.enabled; 242 243 if (state->polarity != curstate.polarity && enabled && !pc->data->supports_lock) { 244 ret = rockchip_pwm_enable(chip, pwm, false); 245 if (ret) { 246 goto out; 247 } 248 enabled = false; 249 } 250 251 rockchip_pwm_config(chip, pwm, state); 252 if (state->enabled != enabled) { 253 ret = rockchip_pwm_enable(chip, pwm, state->enabled); 254 if (ret) { 255 goto out; 256 } 257 } 258 259 if (state->enabled) { 260 ret = pinctrl_select_state(pc->pinctrl, pc->active_state); 261 } 262out: 263 clk_disable(pc->pclk); 264 265 return ret; 266} 267 268static const struct pwm_ops rockchip_pwm_ops = { 269 .get_state = rockchip_pwm_get_state, 270 .apply = rockchip_pwm_apply, 271 .owner = THIS_MODULE, 272}; 273 274static const struct rockchip_pwm_data pwm_data_v1 = { 275 .regs = 276 { 277 .duty = 0x04, 278 .period = 0x08, 279 .cntr = 0x00, 280 .ctrl = 0x0c, 281 }, 282 .prescaler = 2, 283 .supports_polarity = false, 284 .supports_lock = false, 285 .vop_pwm = false, 286 .enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN, 287 .enable_conf_mask = BIT(1) | BIT(3), 288}; 289 290static const struct rockchip_pwm_data pwm_data_v2 = { 291 .regs = 292 { 293 .duty = 0x08, 294 .period = 0x04, 295 .cntr = 0x00, 296 .ctrl = 0x0c, 297 }, 298 .prescaler = 1, 299 .supports_polarity = true, 300 .supports_lock = false, 301 .vop_pwm = false, 302 .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | PWM_CONTINUOUS, 303 .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8), 304}; 305 306static const struct rockchip_pwm_data pwm_data_vop = { 307 .regs = 308 { 309 .duty = 0x08, 310 .period = 0x04, 311 .cntr = 0x0c, 312 .ctrl = 0x00, 313 }, 314 .prescaler = 1, 315 .supports_polarity = true, 316 .supports_lock = false, 317 .vop_pwm = true, 318 .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | PWM_CONTINUOUS, 319 .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8), 320}; 321 322static const struct rockchip_pwm_data pwm_data_v3 = { 323 .regs = 324 { 325 .duty = 0x08, 326 .period = 0x04, 327 .cntr = 0x00, 328 .ctrl = 0x0c, 329 }, 330 .prescaler = 1, 331 .supports_polarity = true, 332 .supports_lock = true, 333 .vop_pwm = false, 334 .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE | PWM_CONTINUOUS, 335 .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8), 336}; 337 338static const struct of_device_id rockchip_pwm_dt_ids[] = {{.compatible = "rockchip,rk2928-pwm", .data = &pwm_data_v1}, 339 {.compatible = "rockchip,rk3288-pwm", .data = &pwm_data_v2}, 340 {.compatible = "rockchip,vop-pwm", .data = &pwm_data_vop}, 341 {.compatible = "rockchip,rk3328-pwm", .data = &pwm_data_v3}, 342 {}}; 343MODULE_DEVICE_TABLE(of, rockchip_pwm_dt_ids); 344 345static int rockchip_pwm_probe(struct platform_device *pdev) 346{ 347 const struct of_device_id *id; 348 struct rockchip_pwm_chip *pc; 349 struct resource *r; 350 u32 enable_conf, ctrl; 351 bool enabled; 352 int ret, count; 353 354 id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev); 355 if (!id) { 356 return -EINVAL; 357 } 358 359 pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); 360 if (!pc) { 361 return -ENOMEM; 362 } 363 364 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 365 pc->base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); 366 if (IS_ERR(pc->base)) { 367 return PTR_ERR(pc->base); 368 } 369 370 pc->clk = devm_clk_get(&pdev->dev, "pwm"); 371 if (IS_ERR(pc->clk)) { 372 pc->clk = devm_clk_get(&pdev->dev, NULL); 373 if (IS_ERR(pc->clk)) { 374 return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk), "Can't get bus clk\n"); 375 } 376 } 377 378 count = of_count_phandle_with_args(pdev->dev.of_node, "clocks", "#clock-cells"); 379 if (count == PWM_COUNT) { 380 pc->pclk = devm_clk_get(&pdev->dev, "pclk"); 381 } else { 382 pc->pclk = pc->clk; 383 } 384 385 if (IS_ERR(pc->pclk)) { 386 ret = PTR_ERR(pc->pclk); 387 if (ret != -EPROBE_DEFER) { 388 dev_err(&pdev->dev, "Can't get APB clk: %d\n", ret); 389 } 390 return ret; 391 } 392 393 ret = clk_prepare_enable(pc->clk); 394 if (ret) { 395 dev_err(&pdev->dev, "Can't prepare enable bus clk: %d\n", ret); 396 return ret; 397 } 398 399 ret = clk_prepare_enable(pc->pclk); 400 if (ret) { 401 dev_err(&pdev->dev, "Can't prepare enable APB clk: %d\n", ret); 402 goto err_clk; 403 } 404 405 pc->pinctrl = devm_pinctrl_get(&pdev->dev); 406 if (IS_ERR(pc->pinctrl)) { 407 dev_err(&pdev->dev, "Get pinctrl failed!\n"); 408 return PTR_ERR(pc->pinctrl); 409 } 410 411 pc->active_state = pinctrl_lookup_state(pc->pinctrl, "active"); 412 if (IS_ERR(pc->active_state)) { 413 dev_err(&pdev->dev, "No active pinctrl state\n"); 414 return PTR_ERR(pc->active_state); 415 } 416 417 platform_set_drvdata(pdev, pc); 418 419 pc->data = id->data; 420 pc->chip.dev = &pdev->dev; 421 pc->chip.ops = &rockchip_pwm_ops; 422 pc->chip.base = -1; 423 pc->chip.npwm = 1; 424 pc->clk_rate = clk_get_rate(pc->clk); 425 426 if (pc->data->supports_polarity) { 427 pc->chip.of_xlate = of_pwm_xlate_with_flags; 428 pc->chip.of_pwm_n_cells = PWM_CELLS; 429 } 430 431 enable_conf = pc->data->enable_conf; 432 ctrl = readl_relaxed(pc->base + pc->data->regs.ctrl); 433 enabled = (ctrl & enable_conf) == enable_conf; 434 435 pc->center_aligned = device_property_read_bool(&pdev->dev, "center-aligned"); 436 437 ret = pwmchip_add(&pc->chip); 438 if (ret < 0) { 439 dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); 440 goto err_pclk; 441 } 442 443 /* Keep the PWM clk enabled if the PWM appears to be up and running. */ 444 if (!enabled) { 445 clk_disable(pc->clk); 446 } 447 448 clk_disable(pc->pclk); 449 450 return 0; 451 452err_pclk: 453 clk_disable_unprepare(pc->pclk); 454err_clk: 455 clk_disable_unprepare(pc->clk); 456 457 return ret; 458} 459 460static int rockchip_pwm_remove(struct platform_device *pdev) 461{ 462 struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev); 463 464 clk_unprepare(pc->pclk); 465 clk_unprepare(pc->clk); 466 467 return pwmchip_remove(&pc->chip); 468} 469 470static struct platform_driver rockchip_pwm_driver = { 471 .driver = 472 { 473 .name = "rockchip-pwm", 474 .of_match_table = rockchip_pwm_dt_ids, 475 }, 476 .probe = rockchip_pwm_probe, 477 .remove = rockchip_pwm_remove, 478}; 479#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT 480static int __init rockchip_pwm_driver_init(void) 481{ 482 return platform_driver_register(&rockchip_pwm_driver); 483} 484subsys_initcall(rockchip_pwm_driver_init); 485 486static void __exit rockchip_pwm_driver_exit(void) 487{ 488 platform_driver_unregister(&rockchip_pwm_driver); 489} 490module_exit(rockchip_pwm_driver_exit); 491#else 492module_platform_driver(rockchip_pwm_driver); 493#endif 494 495MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>"); 496MODULE_DESCRIPTION("Rockchip SoC PWM driver"); 497MODULE_LICENSE("GPL v2"); 498