1 /* 2 * Freescale FlexTimer Module (FTM) PWM Driver 3 * 4 * Copyright 2012-2013 Freescale Semiconductor, Inc. 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 */ 11 12 #include <linux/clk.h> 13 #include <linux/err.h> 14 #include <linux/io.h> 15 #include <linux/kernel.h> 16 #include <linux/module.h> 17 #include <linux/mutex.h> 18 #include <linux/of_address.h> 19 #include <linux/platform_device.h> 20 #include <linux/pwm.h> 21 #include <linux/slab.h> 22 23 #define FTM_SC 0x00 24 #define FTM_SC_CLK_MASK 0x3 25 #define FTM_SC_CLK_SHIFT 3 26 #define FTM_SC_CLK(c) (((c) + 1) << FTM_SC_CLK_SHIFT) 27 #define FTM_SC_PS_MASK 0x7 28 #define FTM_SC_PS_SHIFT 0 29 30 #define FTM_CNT 0x04 31 #define FTM_MOD 0x08 32 33 #define FTM_CSC_BASE 0x0C 34 #define FTM_CSC_MSB BIT(5) 35 #define FTM_CSC_MSA BIT(4) 36 #define FTM_CSC_ELSB BIT(3) 37 #define FTM_CSC_ELSA BIT(2) 38 #define FTM_CSC(_channel) (FTM_CSC_BASE + ((_channel) * 8)) 39 40 #define FTM_CV_BASE 0x10 41 #define FTM_CV(_channel) (FTM_CV_BASE + ((_channel) * 8)) 42 43 #define FTM_CNTIN 0x4C 44 #define FTM_STATUS 0x50 45 46 #define FTM_MODE 0x54 47 #define FTM_MODE_FTMEN BIT(0) 48 #define FTM_MODE_INIT BIT(2) 49 #define FTM_MODE_PWMSYNC BIT(3) 50 51 #define FTM_SYNC 0x58 52 #define FTM_OUTINIT 0x5C 53 #define FTM_OUTMASK 0x60 54 #define FTM_COMBINE 0x64 55 #define FTM_DEADTIME 0x68 56 #define FTM_EXTTRIG 0x6C 57 #define FTM_POL 0x70 58 #define FTM_FMS 0x74 59 #define FTM_FILTER 0x78 60 #define FTM_FLTCTRL 0x7C 61 #define FTM_QDCTRL 0x80 62 #define FTM_CONF 0x84 63 #define FTM_FLTPOL 0x88 64 #define FTM_SYNCONF 0x8C 65 #define FTM_INVCTRL 0x90 66 #define FTM_SWOCTRL 0x94 67 #define FTM_PWMLOAD 0x98 68 69 enum fsl_pwm_clk { 70 FSL_PWM_CLK_SYS, 71 FSL_PWM_CLK_FIX, 72 FSL_PWM_CLK_EXT, 73 FSL_PWM_CLK_CNTEN, 74 FSL_PWM_CLK_MAX 75 }; 76 77 struct fsl_pwm_chip { 78 struct pwm_chip chip; 79 80 struct mutex lock; 81 82 unsigned int use_count; 83 unsigned int cnt_select; 84 unsigned int clk_ps; 85 86 void __iomem *base; 87 88 int period_ns; 89 90 struct clk *clk[FSL_PWM_CLK_MAX]; 91 }; 92 93 static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip) 94 { 95 return container_of(chip, struct fsl_pwm_chip, chip); 96 } 97 98 static int fsl_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) 99 { 100 struct fsl_pwm_chip *fpc = to_fsl_chip(chip); 101 102 return clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]); 103 } 104 105 static void fsl_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm) 106 { 107 struct fsl_pwm_chip *fpc = to_fsl_chip(chip); 108 109 clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]); 110 } 111 112 static int fsl_pwm_calculate_default_ps(struct fsl_pwm_chip *fpc, 113 enum fsl_pwm_clk index) 114 { 115 unsigned long sys_rate, cnt_rate; 116 unsigned long long ratio; 117 118 sys_rate = clk_get_rate(fpc->clk[FSL_PWM_CLK_SYS]); 119 if (!sys_rate) 120 return -EINVAL; 121 122 cnt_rate = clk_get_rate(fpc->clk[fpc->cnt_select]); 123 if (!cnt_rate) 124 return -EINVAL; 125 126 switch (index) { 127 case FSL_PWM_CLK_SYS: 128 fpc->clk_ps = 1; 129 break; 130 case FSL_PWM_CLK_FIX: 131 ratio = 2 * cnt_rate - 1; 132 do_div(ratio, sys_rate); 133 fpc->clk_ps = ratio; 134 break; 135 case FSL_PWM_CLK_EXT: 136 ratio = 4 * cnt_rate - 1; 137 do_div(ratio, sys_rate); 138 fpc->clk_ps = ratio; 139 break; 140 default: 141 return -EINVAL; 142 } 143 144 return 0; 145 } 146 147 static unsigned long fsl_pwm_calculate_cycles(struct fsl_pwm_chip *fpc, 148 unsigned long period_ns) 149 { 150 unsigned long long c, c0; 151 152 c = clk_get_rate(fpc->clk[fpc->cnt_select]); 153 c = c * period_ns; 154 do_div(c, 1000000000UL); 155 156 do { 157 c0 = c; 158 do_div(c0, (1 << fpc->clk_ps)); 159 if (c0 <= 0xFFFF) 160 return (unsigned long)c0; 161 } while (++fpc->clk_ps < 8); 162 163 return 0; 164 } 165 166 static unsigned long fsl_pwm_calculate_period_cycles(struct fsl_pwm_chip *fpc, 167 unsigned long period_ns, 168 enum fsl_pwm_clk index) 169 { 170 int ret; 171 172 ret = fsl_pwm_calculate_default_ps(fpc, index); 173 if (ret) { 174 dev_err(fpc->chip.dev, 175 "failed to calculate default prescaler: %d\n", 176 ret); 177 return 0; 178 } 179 180 return fsl_pwm_calculate_cycles(fpc, period_ns); 181 } 182 183 static unsigned long fsl_pwm_calculate_period(struct fsl_pwm_chip *fpc, 184 unsigned long period_ns) 185 { 186 enum fsl_pwm_clk m0, m1; 187 unsigned long fix_rate, ext_rate, cycles; 188 189 cycles = fsl_pwm_calculate_period_cycles(fpc, period_ns, 190 FSL_PWM_CLK_SYS); 191 if (cycles) { 192 fpc->cnt_select = FSL_PWM_CLK_SYS; 193 return cycles; 194 } 195 196 fix_rate = clk_get_rate(fpc->clk[FSL_PWM_CLK_FIX]); 197 ext_rate = clk_get_rate(fpc->clk[FSL_PWM_CLK_EXT]); 198 199 if (fix_rate > ext_rate) { 200 m0 = FSL_PWM_CLK_FIX; 201 m1 = FSL_PWM_CLK_EXT; 202 } else { 203 m0 = FSL_PWM_CLK_EXT; 204 m1 = FSL_PWM_CLK_FIX; 205 } 206 207 cycles = fsl_pwm_calculate_period_cycles(fpc, period_ns, m0); 208 if (cycles) { 209 fpc->cnt_select = m0; 210 return cycles; 211 } 212 213 fpc->cnt_select = m1; 214 215 return fsl_pwm_calculate_period_cycles(fpc, period_ns, m1); 216 } 217 218 static unsigned long fsl_pwm_calculate_duty(struct fsl_pwm_chip *fpc, 219 unsigned long period_ns, 220 unsigned long duty_ns) 221 { 222 unsigned long long val, duty; 223 224 val = readl(fpc->base + FTM_MOD); 225 duty = duty_ns * (val + 1); 226 do_div(duty, period_ns); 227 228 return (unsigned long)duty; 229 } 230 231 static int fsl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 232 int duty_ns, int period_ns) 233 { 234 struct fsl_pwm_chip *fpc = to_fsl_chip(chip); 235 u32 val, period, duty; 236 237 mutex_lock(&fpc->lock); 238 239 /* 240 * The Freescale FTM controller supports only a single period for 241 * all PWM channels, therefore incompatible changes need to be 242 * refused. 243 */ 244 if (fpc->period_ns && fpc->period_ns != period_ns) { 245 dev_err(fpc->chip.dev, 246 "conflicting period requested for PWM %u\n", 247 pwm->hwpwm); 248 mutex_unlock(&fpc->lock); 249 return -EBUSY; 250 } 251 252 if (!fpc->period_ns && duty_ns) { 253 period = fsl_pwm_calculate_period(fpc, period_ns); 254 if (!period) { 255 dev_err(fpc->chip.dev, "failed to calculate period\n"); 256 mutex_unlock(&fpc->lock); 257 return -EINVAL; 258 } 259 260 val = readl(fpc->base + FTM_SC); 261 val &= ~(FTM_SC_PS_MASK << FTM_SC_PS_SHIFT); 262 val |= fpc->clk_ps; 263 writel(val, fpc->base + FTM_SC); 264 writel(period - 1, fpc->base + FTM_MOD); 265 266 fpc->period_ns = period_ns; 267 } 268 269 mutex_unlock(&fpc->lock); 270 271 duty = fsl_pwm_calculate_duty(fpc, period_ns, duty_ns); 272 273 writel(FTM_CSC_MSB | FTM_CSC_ELSB, fpc->base + FTM_CSC(pwm->hwpwm)); 274 writel(duty, fpc->base + FTM_CV(pwm->hwpwm)); 275 276 return 0; 277 } 278 279 static int fsl_pwm_set_polarity(struct pwm_chip *chip, 280 struct pwm_device *pwm, 281 enum pwm_polarity polarity) 282 { 283 struct fsl_pwm_chip *fpc = to_fsl_chip(chip); 284 u32 val; 285 286 val = readl(fpc->base + FTM_POL); 287 288 if (polarity == PWM_POLARITY_INVERSED) 289 val |= BIT(pwm->hwpwm); 290 else 291 val &= ~BIT(pwm->hwpwm); 292 293 writel(val, fpc->base + FTM_POL); 294 295 return 0; 296 } 297 298 static int fsl_counter_clock_enable(struct fsl_pwm_chip *fpc) 299 { 300 u32 val; 301 int ret; 302 303 if (fpc->use_count != 0) 304 return 0; 305 306 /* select counter clock source */ 307 val = readl(fpc->base + FTM_SC); 308 val &= ~(FTM_SC_CLK_MASK << FTM_SC_CLK_SHIFT); 309 val |= FTM_SC_CLK(fpc->cnt_select); 310 writel(val, fpc->base + FTM_SC); 311 312 ret = clk_prepare_enable(fpc->clk[fpc->cnt_select]); 313 if (ret) 314 return ret; 315 316 ret = clk_prepare_enable(fpc->clk[FSL_PWM_CLK_CNTEN]); 317 if (ret) { 318 clk_disable_unprepare(fpc->clk[fpc->cnt_select]); 319 return ret; 320 } 321 322 fpc->use_count++; 323 324 return 0; 325 } 326 327 static int fsl_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 328 { 329 struct fsl_pwm_chip *fpc = to_fsl_chip(chip); 330 u32 val; 331 int ret; 332 333 mutex_lock(&fpc->lock); 334 val = readl(fpc->base + FTM_OUTMASK); 335 val &= ~BIT(pwm->hwpwm); 336 writel(val, fpc->base + FTM_OUTMASK); 337 338 ret = fsl_counter_clock_enable(fpc); 339 mutex_unlock(&fpc->lock); 340 341 return ret; 342 } 343 344 static void fsl_counter_clock_disable(struct fsl_pwm_chip *fpc) 345 { 346 u32 val; 347 348 /* 349 * already disabled, do nothing 350 */ 351 if (fpc->use_count == 0) 352 return; 353 354 /* there are still users, so can't disable yet */ 355 if (--fpc->use_count > 0) 356 return; 357 358 /* no users left, disable PWM counter clock */ 359 val = readl(fpc->base + FTM_SC); 360 val &= ~(FTM_SC_CLK_MASK << FTM_SC_CLK_SHIFT); 361 writel(val, fpc->base + FTM_SC); 362 363 clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_CNTEN]); 364 clk_disable_unprepare(fpc->clk[fpc->cnt_select]); 365 } 366 367 static void fsl_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 368 { 369 struct fsl_pwm_chip *fpc = to_fsl_chip(chip); 370 u32 val; 371 372 mutex_lock(&fpc->lock); 373 val = readl(fpc->base + FTM_OUTMASK); 374 val |= BIT(pwm->hwpwm); 375 writel(val, fpc->base + FTM_OUTMASK); 376 377 fsl_counter_clock_disable(fpc); 378 379 val = readl(fpc->base + FTM_OUTMASK); 380 381 if ((val & 0xFF) == 0xFF) 382 fpc->period_ns = 0; 383 384 mutex_unlock(&fpc->lock); 385 } 386 387 static const struct pwm_ops fsl_pwm_ops = { 388 .request = fsl_pwm_request, 389 .free = fsl_pwm_free, 390 .config = fsl_pwm_config, 391 .set_polarity = fsl_pwm_set_polarity, 392 .enable = fsl_pwm_enable, 393 .disable = fsl_pwm_disable, 394 .owner = THIS_MODULE, 395 }; 396 397 static int fsl_pwm_init(struct fsl_pwm_chip *fpc) 398 { 399 int ret; 400 401 ret = clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]); 402 if (ret) 403 return ret; 404 405 writel(0x00, fpc->base + FTM_CNTIN); 406 writel(0x00, fpc->base + FTM_OUTINIT); 407 writel(0xFF, fpc->base + FTM_OUTMASK); 408 409 clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]); 410 411 return 0; 412 } 413 414 static int fsl_pwm_probe(struct platform_device *pdev) 415 { 416 struct fsl_pwm_chip *fpc; 417 struct resource *res; 418 int ret; 419 420 fpc = devm_kzalloc(&pdev->dev, sizeof(*fpc), GFP_KERNEL); 421 if (!fpc) 422 return -ENOMEM; 423 424 mutex_init(&fpc->lock); 425 426 fpc->chip.dev = &pdev->dev; 427 428 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 429 fpc->base = devm_ioremap_resource(&pdev->dev, res); 430 if (IS_ERR(fpc->base)) 431 return PTR_ERR(fpc->base); 432 433 fpc->clk[FSL_PWM_CLK_SYS] = devm_clk_get(&pdev->dev, "ftm_sys"); 434 if (IS_ERR(fpc->clk[FSL_PWM_CLK_SYS])) { 435 dev_err(&pdev->dev, "failed to get \"ftm_sys\" clock\n"); 436 return PTR_ERR(fpc->clk[FSL_PWM_CLK_SYS]); 437 } 438 439 fpc->clk[FSL_PWM_CLK_FIX] = devm_clk_get(fpc->chip.dev, "ftm_fix"); 440 if (IS_ERR(fpc->clk[FSL_PWM_CLK_FIX])) 441 return PTR_ERR(fpc->clk[FSL_PWM_CLK_FIX]); 442 443 fpc->clk[FSL_PWM_CLK_EXT] = devm_clk_get(fpc->chip.dev, "ftm_ext"); 444 if (IS_ERR(fpc->clk[FSL_PWM_CLK_EXT])) 445 return PTR_ERR(fpc->clk[FSL_PWM_CLK_EXT]); 446 447 fpc->clk[FSL_PWM_CLK_CNTEN] = 448 devm_clk_get(fpc->chip.dev, "ftm_cnt_clk_en"); 449 if (IS_ERR(fpc->clk[FSL_PWM_CLK_CNTEN])) 450 return PTR_ERR(fpc->clk[FSL_PWM_CLK_CNTEN]); 451 452 fpc->chip.ops = &fsl_pwm_ops; 453 fpc->chip.of_xlate = of_pwm_xlate_with_flags; 454 fpc->chip.of_pwm_n_cells = 3; 455 fpc->chip.base = -1; 456 fpc->chip.npwm = 8; 457 fpc->chip.can_sleep = true; 458 459 ret = pwmchip_add(&fpc->chip); 460 if (ret < 0) { 461 dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); 462 return ret; 463 } 464 465 platform_set_drvdata(pdev, fpc); 466 467 return fsl_pwm_init(fpc); 468 } 469 470 static int fsl_pwm_remove(struct platform_device *pdev) 471 { 472 struct fsl_pwm_chip *fpc = platform_get_drvdata(pdev); 473 474 return pwmchip_remove(&fpc->chip); 475 } 476 477 static const struct of_device_id fsl_pwm_dt_ids[] = { 478 { .compatible = "fsl,vf610-ftm-pwm", }, 479 { /* sentinel */ } 480 }; 481 MODULE_DEVICE_TABLE(of, fsl_pwm_dt_ids); 482 483 static struct platform_driver fsl_pwm_driver = { 484 .driver = { 485 .name = "fsl-ftm-pwm", 486 .of_match_table = fsl_pwm_dt_ids, 487 }, 488 .probe = fsl_pwm_probe, 489 .remove = fsl_pwm_remove, 490 }; 491 module_platform_driver(fsl_pwm_driver); 492 493 MODULE_DESCRIPTION("Freescale FlexTimer Module PWM Driver"); 494 MODULE_AUTHOR("Xiubo Li <Li.Xiubo@freescale.com>"); 495 MODULE_ALIAS("platform:fsl-ftm-pwm"); 496 MODULE_LICENSE("GPL"); 497