1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright 2022 Markus Gothe <markus.gothe@genexis.eu> 4 * Copyright 2025 Christian Marangi <ansuelsmth@gmail.com> 5 * 6 * Limitations: 7 * - Only 8 concurrent waveform generators are available for 8 combinations of 8 * duty_cycle and period. Waveform generators are shared between 16 GPIO 9 * pins and 17 SIPO GPIO pins. 10 * - Supports only normal polarity. 11 * - On configuration the currently running period is completed. 12 * - Minimum supported period is 4 ms 13 * - Maximum supported period is 1s 14 */ 15 16 #include <linux/array_size.h> 17 #include <linux/bitfield.h> 18 #include <linux/bitmap.h> 19 #include <linux/err.h> 20 #include <linux/io.h> 21 #include <linux/iopoll.h> 22 #include <linux/math64.h> 23 #include <linux/mfd/syscon.h> 24 #include <linux/module.h> 25 #include <linux/mod_devicetable.h> 26 #include <linux/platform_device.h> 27 #include <linux/pwm.h> 28 #include <linux/regmap.h> 29 #include <linux/types.h> 30 31 #define AIROHA_PWM_REG_SGPIO_LED_DATA 0x0024 32 #define AIROHA_PWM_SGPIO_LED_DATA_SHIFT_FLAG BIT(31) 33 #define AIROHA_PWM_SGPIO_LED_DATA_DATA GENMASK(16, 0) 34 35 #define AIROHA_PWM_REG_SGPIO_CLK_DIVR 0x0028 36 #define AIROHA_PWM_SGPIO_CLK_DIVR GENMASK(1, 0) 37 #define AIROHA_PWM_SGPIO_CLK_DIVR_32 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 3) 38 #define AIROHA_PWM_SGPIO_CLK_DIVR_16 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 2) 39 #define AIROHA_PWM_SGPIO_CLK_DIVR_8 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 1) 40 #define AIROHA_PWM_SGPIO_CLK_DIVR_4 FIELD_PREP_CONST(AIROHA_PWM_SGPIO_CLK_DIVR, 0) 41 42 #define AIROHA_PWM_REG_SGPIO_CLK_DLY 0x002c 43 44 #define AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG 0x0030 45 #define AIROHA_PWM_SERIAL_GPIO_FLASH_MODE BIT(1) 46 #define AIROHA_PWM_SERIAL_GPIO_MODE_74HC164 BIT(0) 47 48 #define AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(_n) (0x003c + (4 * (_n))) 49 #define AIROHA_PWM_REG_GPIO_FLASH_PRD_SHIFT(_n) (16 * (_n)) 50 #define AIROHA_PWM_GPIO_FLASH_PRD_LOW GENMASK(15, 8) 51 #define AIROHA_PWM_GPIO_FLASH_PRD_HIGH GENMASK(7, 0) 52 53 #define AIROHA_PWM_REG_GPIO_FLASH_MAP(_n) (0x004c + (4 * (_n))) 54 #define AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(_n) (4 * (_n)) 55 #define AIROHA_PWM_GPIO_FLASH_EN BIT(3) 56 #define AIROHA_PWM_GPIO_FLASH_SET_ID GENMASK(2, 0) 57 58 /* Register map is equal to GPIO flash map */ 59 #define AIROHA_PWM_REG_SIPO_FLASH_MAP(_n) (0x0054 + (4 * (_n))) 60 61 #define AIROHA_PWM_REG_CYCLE_CFG_VALUE(_n) (0x0098 + (4 * (_n))) 62 #define AIROHA_PWM_REG_CYCLE_CFG_SHIFT(_n) (8 * (_n)) 63 #define AIROHA_PWM_WAVE_GEN_CYCLE GENMASK(7, 0) 64 65 /* GPIO/SIPO flash map handles 8 pins in one register */ 66 #define AIROHA_PWM_PINS_PER_FLASH_MAP 8 67 /* Cycle(Period) registers handles 4 generators in one 32-bit register */ 68 #define AIROHA_PWM_BUCKET_PER_CYCLE_CFG 4 69 /* Flash(Duty) producer handles 2 generators in one 32-bit register */ 70 #define AIROHA_PWM_BUCKET_PER_FLASH_PROD 2 71 72 #define AIROHA_PWM_NUM_BUCKETS 8 73 /* 74 * The first 16 GPIO pins, GPIO0-GPIO15, are mapped into 16 PWM channels, 0-15. 75 * The SIPO GPIO pins are 17 pins which are mapped into 17 PWM channels, 16-32. 76 * However, we've only got 8 concurrent waveform generators and can therefore 77 * only use up to 8 different combinations of duty cycle and period at a time. 78 */ 79 #define AIROHA_PWM_NUM_GPIO 16 80 #define AIROHA_PWM_NUM_SIPO 17 81 #define AIROHA_PWM_MAX_CHANNELS (AIROHA_PWM_NUM_GPIO + AIROHA_PWM_NUM_SIPO) 82 83 struct airoha_pwm_bucket { 84 /* Concurrent access protected by PWM core */ 85 int used; 86 u32 period_ticks; 87 u32 duty_ticks; 88 }; 89 90 struct airoha_pwm { 91 struct regmap *regmap; 92 93 DECLARE_BITMAP(initialized, AIROHA_PWM_MAX_CHANNELS); 94 95 struct airoha_pwm_bucket buckets[AIROHA_PWM_NUM_BUCKETS]; 96 97 /* Cache bucket used by each pwm channel */ 98 u8 channel_bucket[AIROHA_PWM_MAX_CHANNELS]; 99 }; 100 101 /* The PWM hardware supports periods between 4 ms and 1 s */ 102 #define AIROHA_PWM_PERIOD_TICK_NS (4 * NSEC_PER_MSEC) 103 #define AIROHA_PWM_PERIOD_MAX_NS (1 * NSEC_PER_SEC) 104 /* It is represented internally as 1/250 s between 1 and 250. Unit is ticks. */ 105 #define AIROHA_PWM_PERIOD_MIN 1 106 #define AIROHA_PWM_PERIOD_MAX 250 107 /* Duty cycle is relative with 255 corresponding to 100% */ 108 #define AIROHA_PWM_DUTY_FULL 255 109 110 static void airoha_pwm_get_flash_map_addr_and_shift(unsigned int hwpwm, 111 u32 *addr, u32 *shift) 112 { 113 unsigned int offset, hwpwm_bit; 114 115 if (hwpwm >= AIROHA_PWM_NUM_GPIO) { 116 unsigned int sipohwpwm = hwpwm - AIROHA_PWM_NUM_GPIO; 117 118 offset = sipohwpwm / AIROHA_PWM_PINS_PER_FLASH_MAP; 119 hwpwm_bit = sipohwpwm % AIROHA_PWM_PINS_PER_FLASH_MAP; 120 121 /* One FLASH_MAP register handles 8 pins */ 122 *shift = AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(hwpwm_bit); 123 *addr = AIROHA_PWM_REG_SIPO_FLASH_MAP(offset); 124 } else { 125 offset = hwpwm / AIROHA_PWM_PINS_PER_FLASH_MAP; 126 hwpwm_bit = hwpwm % AIROHA_PWM_PINS_PER_FLASH_MAP; 127 128 /* One FLASH_MAP register handles 8 pins */ 129 *shift = AIROHA_PWM_REG_GPIO_FLASH_MAP_SHIFT(hwpwm_bit); 130 *addr = AIROHA_PWM_REG_GPIO_FLASH_MAP(offset); 131 } 132 } 133 134 static u32 airoha_pwm_get_period_ticks_from_ns(u32 period_ns) 135 { 136 return period_ns / AIROHA_PWM_PERIOD_TICK_NS; 137 } 138 139 static u32 airoha_pwm_get_duty_ticks_from_ns(u32 period_ns, u32 duty_ns) 140 { 141 return mul_u64_u32_div(duty_ns, AIROHA_PWM_DUTY_FULL, period_ns); 142 } 143 144 static u32 airoha_pwm_get_period_ns_from_ticks(u32 period_tick) 145 { 146 return period_tick * AIROHA_PWM_PERIOD_TICK_NS; 147 } 148 149 static u32 airoha_pwm_get_duty_ns_from_ticks(u32 period_tick, u32 duty_tick) 150 { 151 u32 period_ns = period_tick * AIROHA_PWM_PERIOD_TICK_NS; 152 153 /* 154 * Overflow can't occur in multiplication as duty_tick is just 8 bit 155 * and period_ns is clamped to AIROHA_PWM_PERIOD_MAX_NS and fit in a 156 * u64. 157 */ 158 return DIV_U64_ROUND_UP(duty_tick * period_ns, AIROHA_PWM_DUTY_FULL); 159 } 160 161 static int airoha_pwm_get_bucket(struct airoha_pwm *pc, int bucket, 162 u64 *period_ns, u64 *duty_ns) 163 { 164 struct regmap *map = pc->regmap; 165 u32 period_tick, duty_tick; 166 unsigned int offset; 167 u32 shift, val; 168 int ret; 169 170 offset = bucket / AIROHA_PWM_BUCKET_PER_CYCLE_CFG; 171 shift = bucket % AIROHA_PWM_BUCKET_PER_CYCLE_CFG; 172 shift = AIROHA_PWM_REG_CYCLE_CFG_SHIFT(shift); 173 174 ret = regmap_read(map, AIROHA_PWM_REG_CYCLE_CFG_VALUE(offset), &val); 175 if (ret) 176 return ret; 177 178 period_tick = FIELD_GET(AIROHA_PWM_WAVE_GEN_CYCLE, val >> shift); 179 *period_ns = airoha_pwm_get_period_ns_from_ticks(period_tick); 180 181 offset = bucket / AIROHA_PWM_BUCKET_PER_FLASH_PROD; 182 shift = bucket % AIROHA_PWM_BUCKET_PER_FLASH_PROD; 183 shift = AIROHA_PWM_REG_GPIO_FLASH_PRD_SHIFT(shift); 184 185 ret = regmap_read(map, AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(offset), 186 &val); 187 if (ret) 188 return ret; 189 190 duty_tick = FIELD_GET(AIROHA_PWM_GPIO_FLASH_PRD_HIGH, val >> shift); 191 *duty_ns = airoha_pwm_get_duty_ns_from_ticks(period_tick, duty_tick); 192 193 return 0; 194 } 195 196 static int airoha_pwm_get_generator(struct airoha_pwm *pc, u32 duty_ticks, 197 u32 period_ticks) 198 { 199 int best = -ENOENT, unused = -ENOENT; 200 u32 duty_ns, best_duty_ns = 0; 201 u32 best_period_ticks = 0; 202 unsigned int i; 203 204 duty_ns = airoha_pwm_get_duty_ns_from_ticks(period_ticks, duty_ticks); 205 206 for (i = 0; i < ARRAY_SIZE(pc->buckets); i++) { 207 struct airoha_pwm_bucket *bucket = &pc->buckets[i]; 208 u32 bucket_period_ticks = bucket->period_ticks; 209 u32 bucket_duty_ticks = bucket->duty_ticks; 210 211 /* If found, save an unused bucket to return it later */ 212 if (!bucket->used) { 213 unused = i; 214 continue; 215 } 216 217 /* We found a matching bucket, exit early */ 218 if (duty_ticks == bucket_duty_ticks && 219 period_ticks == bucket_period_ticks) 220 return i; 221 222 /* 223 * Unlike duty cycle zero, which can be handled by 224 * disabling PWM, a generator is needed for full duty 225 * cycle but it can be reused regardless of period 226 */ 227 if (duty_ticks == AIROHA_PWM_DUTY_FULL && 228 bucket_duty_ticks == AIROHA_PWM_DUTY_FULL) 229 return i; 230 231 /* 232 * With an unused bucket available, skip searching for 233 * a bucket to recycle (closer to the requested period/duty) 234 */ 235 if (unused >= 0) 236 continue; 237 238 /* Ignore bucket with invalid period */ 239 if (bucket_period_ticks > period_ticks) 240 continue; 241 242 /* 243 * Search for a bucket closer to the requested period 244 * that has the maximal possible period that isn't bigger 245 * than the requested period. For that period pick the maximal 246 * duty cycle that isn't bigger than the requested duty_cycle. 247 */ 248 if (bucket_period_ticks >= best_period_ticks) { 249 u32 bucket_duty_ns = airoha_pwm_get_duty_ns_from_ticks(bucket_period_ticks, 250 bucket_duty_ticks); 251 252 /* Skip bucket that goes over the requested duty */ 253 if (bucket_duty_ns > duty_ns) 254 continue; 255 256 if (bucket_duty_ns > best_duty_ns) { 257 best_period_ticks = bucket_period_ticks; 258 best_duty_ns = bucket_duty_ns; 259 best = i; 260 } 261 } 262 } 263 264 /* Return an unused bucket or the best one found (if ever) */ 265 return unused >= 0 ? unused : best; 266 } 267 268 static void airoha_pwm_release_bucket_config(struct airoha_pwm *pc, 269 unsigned int hwpwm) 270 { 271 int bucket; 272 273 /* Nothing to clear, PWM channel never used */ 274 if (!test_bit(hwpwm, pc->initialized)) 275 return; 276 277 bucket = pc->channel_bucket[hwpwm]; 278 pc->buckets[bucket].used--; 279 } 280 281 static int airoha_pwm_apply_bucket_config(struct airoha_pwm *pc, unsigned int bucket, 282 u32 duty_ticks, u32 period_ticks) 283 { 284 u32 mask, shift, val; 285 u32 offset; 286 int ret; 287 288 offset = bucket / AIROHA_PWM_BUCKET_PER_CYCLE_CFG; 289 shift = bucket % AIROHA_PWM_BUCKET_PER_CYCLE_CFG; 290 shift = AIROHA_PWM_REG_CYCLE_CFG_SHIFT(shift); 291 292 /* Configure frequency divisor */ 293 mask = AIROHA_PWM_WAVE_GEN_CYCLE << shift; 294 val = FIELD_PREP(AIROHA_PWM_WAVE_GEN_CYCLE, period_ticks) << shift; 295 ret = regmap_update_bits(pc->regmap, AIROHA_PWM_REG_CYCLE_CFG_VALUE(offset), 296 mask, val); 297 if (ret) 298 return ret; 299 300 offset = bucket / AIROHA_PWM_BUCKET_PER_FLASH_PROD; 301 shift = bucket % AIROHA_PWM_BUCKET_PER_FLASH_PROD; 302 shift = AIROHA_PWM_REG_GPIO_FLASH_PRD_SHIFT(shift); 303 304 /* Configure duty cycle */ 305 mask = AIROHA_PWM_GPIO_FLASH_PRD_HIGH << shift; 306 val = FIELD_PREP(AIROHA_PWM_GPIO_FLASH_PRD_HIGH, duty_ticks) << shift; 307 ret = regmap_update_bits(pc->regmap, AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(offset), 308 mask, val); 309 if (ret) 310 return ret; 311 312 mask = AIROHA_PWM_GPIO_FLASH_PRD_LOW << shift; 313 val = FIELD_PREP(AIROHA_PWM_GPIO_FLASH_PRD_LOW, 314 AIROHA_PWM_DUTY_FULL - duty_ticks) << shift; 315 return regmap_update_bits(pc->regmap, AIROHA_PWM_REG_GPIO_FLASH_PRD_SET(offset), 316 mask, val); 317 } 318 319 static int airoha_pwm_consume_generator(struct airoha_pwm *pc, 320 u32 duty_ticks, u32 period_ticks, 321 unsigned int hwpwm) 322 { 323 bool config_bucket = false; 324 int bucket, ret; 325 326 /* 327 * Search for a bucket that already satisfies duty and period 328 * or an unused one. 329 * If not found, -ENOENT is returned. 330 */ 331 bucket = airoha_pwm_get_generator(pc, duty_ticks, period_ticks); 332 if (bucket < 0) 333 return bucket; 334 335 /* Release previous used bucket (if any) */ 336 airoha_pwm_release_bucket_config(pc, hwpwm); 337 338 if (!pc->buckets[bucket].used) 339 config_bucket = true; 340 pc->buckets[bucket].used++; 341 342 if (config_bucket) { 343 pc->buckets[bucket].period_ticks = period_ticks; 344 pc->buckets[bucket].duty_ticks = duty_ticks; 345 ret = airoha_pwm_apply_bucket_config(pc, bucket, 346 duty_ticks, 347 period_ticks); 348 if (ret) { 349 pc->buckets[bucket].used--; 350 return ret; 351 } 352 } 353 354 return bucket; 355 } 356 357 static int airoha_pwm_sipo_init(struct airoha_pwm *pc) 358 { 359 u32 val; 360 int ret; 361 362 ret = regmap_clear_bits(pc->regmap, AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG, 363 AIROHA_PWM_SERIAL_GPIO_MODE_74HC164); 364 if (ret) 365 return ret; 366 367 /* Configure shift register chip clock timings, use 32x divisor */ 368 ret = regmap_write(pc->regmap, AIROHA_PWM_REG_SGPIO_CLK_DIVR, 369 AIROHA_PWM_SGPIO_CLK_DIVR_32); 370 if (ret) 371 return ret; 372 373 /* 374 * Configure the shift register chip clock delay. This needs 375 * to be configured based on the chip characteristics when the SoC 376 * apply the shift register configuration. 377 * This doesn't affect actual PWM operation and is only specific to 378 * the shift register chip. 379 * 380 * For 74HC164 we set it to 0. 381 * 382 * For reference, the actual delay applied is the internal clock 383 * feed to the SGPIO chip + 1. 384 * 385 * From documentation is specified that clock delay should not be 386 * greater than (AIROHA_PWM_REG_SGPIO_CLK_DIVR / 2) - 1. 387 */ 388 ret = regmap_write(pc->regmap, AIROHA_PWM_REG_SGPIO_CLK_DLY, 0); 389 if (ret) 390 return ret; 391 392 /* 393 * It is necessary to explicitly shift out all zeros after muxing 394 * to initialize the shift register before enabling PWM 395 * mode because in PWM mode SIPO will not start shifting until 396 * it needs to output a non-zero value (bit 31 of led_data 397 * indicates shifting in progress and it must return to zero 398 * before led_data can be written or PWM mode can be set). 399 */ 400 ret = regmap_read_poll_timeout(pc->regmap, AIROHA_PWM_REG_SGPIO_LED_DATA, val, 401 !(val & AIROHA_PWM_SGPIO_LED_DATA_SHIFT_FLAG), 402 10, 200 * USEC_PER_MSEC); 403 if (ret) 404 return ret; 405 406 ret = regmap_clear_bits(pc->regmap, AIROHA_PWM_REG_SGPIO_LED_DATA, 407 AIROHA_PWM_SGPIO_LED_DATA_DATA); 408 if (ret) 409 return ret; 410 ret = regmap_read_poll_timeout(pc->regmap, AIROHA_PWM_REG_SGPIO_LED_DATA, val, 411 !(val & AIROHA_PWM_SGPIO_LED_DATA_SHIFT_FLAG), 412 10, 200 * USEC_PER_MSEC); 413 if (ret) 414 return ret; 415 416 /* Set SIPO in PWM mode */ 417 return regmap_set_bits(pc->regmap, AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG, 418 AIROHA_PWM_SERIAL_GPIO_FLASH_MODE); 419 } 420 421 static int airoha_pwm_config_flash_map(struct airoha_pwm *pc, 422 unsigned int hwpwm, int index) 423 { 424 unsigned int addr; 425 u32 shift; 426 int ret; 427 428 airoha_pwm_get_flash_map_addr_and_shift(hwpwm, &addr, &shift); 429 430 /* negative index means disable PWM channel */ 431 if (index < 0) { 432 /* 433 * If we need to disable the PWM, we just put low the 434 * GPIO. No need to setup buckets. 435 */ 436 return regmap_clear_bits(pc->regmap, addr, 437 AIROHA_PWM_GPIO_FLASH_EN << shift); 438 } 439 440 ret = regmap_update_bits(pc->regmap, addr, 441 AIROHA_PWM_GPIO_FLASH_SET_ID << shift, 442 FIELD_PREP(AIROHA_PWM_GPIO_FLASH_SET_ID, index) << shift); 443 if (ret) 444 return ret; 445 446 return regmap_set_bits(pc->regmap, addr, AIROHA_PWM_GPIO_FLASH_EN << shift); 447 } 448 449 static int airoha_pwm_config(struct airoha_pwm *pc, struct pwm_device *pwm, 450 u32 period_ticks, u32 duty_ticks) 451 { 452 unsigned int hwpwm = pwm->hwpwm; 453 int bucket, ret; 454 455 bucket = airoha_pwm_consume_generator(pc, duty_ticks, period_ticks, 456 hwpwm); 457 if (bucket < 0) 458 return bucket; 459 460 ret = airoha_pwm_config_flash_map(pc, hwpwm, bucket); 461 if (ret) { 462 pc->buckets[bucket].used--; 463 return ret; 464 } 465 466 __set_bit(hwpwm, pc->initialized); 467 pc->channel_bucket[hwpwm] = bucket; 468 469 /* 470 * SIPO are special GPIO attached to a shift register chip. The handling 471 * of this chip is internal to the SoC that takes care of applying the 472 * values based on the flash map. To apply a new flash map, it's needed 473 * to trigger a refresh on the shift register chip. 474 * If a SIPO is getting configuring , always reinit the shift register 475 * chip to make sure the correct flash map is applied. 476 * Skip reconfiguring the shift register if the related hwpwm 477 * is disabled (as it doesn't need to be mapped). 478 */ 479 if (hwpwm >= AIROHA_PWM_NUM_GPIO) { 480 ret = airoha_pwm_sipo_init(pc); 481 if (ret) { 482 airoha_pwm_release_bucket_config(pc, hwpwm); 483 return ret; 484 } 485 } 486 487 return 0; 488 } 489 490 static void airoha_pwm_disable(struct airoha_pwm *pc, struct pwm_device *pwm) 491 { 492 /* Disable PWM and release the bucket */ 493 airoha_pwm_config_flash_map(pc, pwm->hwpwm, -1); 494 airoha_pwm_release_bucket_config(pc, pwm->hwpwm); 495 496 __clear_bit(pwm->hwpwm, pc->initialized); 497 498 /* If no SIPO is used, disable the shift register chip */ 499 if (!bitmap_read(pc->initialized, 500 AIROHA_PWM_NUM_GPIO, AIROHA_PWM_NUM_SIPO)) 501 regmap_clear_bits(pc->regmap, AIROHA_PWM_REG_SIPO_FLASH_MODE_CFG, 502 AIROHA_PWM_SERIAL_GPIO_FLASH_MODE); 503 } 504 505 static int airoha_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 506 const struct pwm_state *state) 507 { 508 struct airoha_pwm *pc = pwmchip_get_drvdata(chip); 509 u32 period_ticks, duty_ticks; 510 u32 period_ns, duty_ns; 511 512 if (!state->enabled) { 513 airoha_pwm_disable(pc, pwm); 514 return 0; 515 } 516 517 /* Only normal polarity is supported */ 518 if (state->polarity == PWM_POLARITY_INVERSED) 519 return -EINVAL; 520 521 /* Exit early if period is less than minimum supported */ 522 if (state->period < AIROHA_PWM_PERIOD_TICK_NS) 523 return -EINVAL; 524 525 /* Clamp period to MAX supported value */ 526 if (state->period > AIROHA_PWM_PERIOD_MAX_NS) 527 period_ns = AIROHA_PWM_PERIOD_MAX_NS; 528 else 529 period_ns = state->period; 530 531 /* Validate duty to configured period */ 532 if (state->duty_cycle > period_ns) 533 duty_ns = period_ns; 534 else 535 duty_ns = state->duty_cycle; 536 537 /* Convert period ns to ticks */ 538 period_ticks = airoha_pwm_get_period_ticks_from_ns(period_ns); 539 /* Convert period ticks to ns again for cosistent duty tick calculation */ 540 period_ns = airoha_pwm_get_period_ns_from_ticks(period_ticks); 541 duty_ticks = airoha_pwm_get_duty_ticks_from_ns(period_ns, duty_ns); 542 543 return airoha_pwm_config(pc, pwm, period_ticks, duty_ticks); 544 } 545 546 static int airoha_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, 547 struct pwm_state *state) 548 { 549 struct airoha_pwm *pc = pwmchip_get_drvdata(chip); 550 int ret, hwpwm = pwm->hwpwm; 551 u32 addr, shift, val; 552 u8 bucket; 553 554 airoha_pwm_get_flash_map_addr_and_shift(hwpwm, &addr, &shift); 555 556 ret = regmap_read(pc->regmap, addr, &val); 557 if (ret) 558 return ret; 559 560 state->enabled = FIELD_GET(AIROHA_PWM_GPIO_FLASH_EN, val >> shift); 561 if (!state->enabled) 562 return 0; 563 564 state->polarity = PWM_POLARITY_NORMAL; 565 566 bucket = FIELD_GET(AIROHA_PWM_GPIO_FLASH_SET_ID, val >> shift); 567 return airoha_pwm_get_bucket(pc, bucket, &state->period, 568 &state->duty_cycle); 569 } 570 571 static const struct pwm_ops airoha_pwm_ops = { 572 .apply = airoha_pwm_apply, 573 .get_state = airoha_pwm_get_state, 574 }; 575 576 static int airoha_pwm_probe(struct platform_device *pdev) 577 { 578 struct device *dev = &pdev->dev; 579 struct airoha_pwm *pc; 580 struct pwm_chip *chip; 581 int ret; 582 583 chip = devm_pwmchip_alloc(dev, AIROHA_PWM_MAX_CHANNELS, sizeof(*pc)); 584 if (IS_ERR(chip)) 585 return PTR_ERR(chip); 586 587 chip->ops = &airoha_pwm_ops; 588 pc = pwmchip_get_drvdata(chip); 589 590 pc->regmap = device_node_to_regmap(dev_of_node(dev->parent)); 591 if (IS_ERR(pc->regmap)) 592 return dev_err_probe(dev, PTR_ERR(pc->regmap), "Failed to get PWM regmap\n"); 593 594 ret = devm_pwmchip_add(dev, chip); 595 if (ret) 596 return dev_err_probe(dev, ret, "Failed to add PWM chip\n"); 597 598 return 0; 599 } 600 601 static const struct of_device_id airoha_pwm_of_match[] = { 602 { .compatible = "airoha,en7581-pwm" }, 603 { /* sentinel */ } 604 }; 605 MODULE_DEVICE_TABLE(of, airoha_pwm_of_match); 606 607 static struct platform_driver airoha_pwm_driver = { 608 .driver = { 609 .name = "pwm-airoha", 610 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 611 .of_match_table = airoha_pwm_of_match, 612 }, 613 .probe = airoha_pwm_probe, 614 }; 615 module_platform_driver(airoha_pwm_driver); 616 617 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>"); 618 MODULE_AUTHOR("Markus Gothe <markus.gothe@genexis.eu>"); 619 MODULE_AUTHOR("Benjamin Larsson <benjamin.larsson@genexis.eu>"); 620 MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>"); 621 MODULE_DESCRIPTION("Airoha EN7581 PWM driver"); 622 MODULE_LICENSE("GPL"); 623