Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

pwm: meson: Add generic compatible for meson8 to sm1

Introduce a new compatible support in the Amlogic PWM driver.

The PWM HW is actually the same for all SoCs supported so far. A specific
compatible is needed only because the clock sources of the PWMs are
hard-coded in the driver.

It is better to have the clock source described in DT but this changes the
bindings so a new compatible must be introduced.

When all supported platform have migrated to the new compatible, support
for the legacy ones may be removed from the driver.

The addition of this new compatible makes the old ones obsolete, as
described in the DT documentation.

Adding a callback to setup the clock will also make it easier to add
support for the new PWM HW found in a1, s4, c3 and t7 SoC families.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Link: https://lore.kernel.org/r/20240221151154.26452-6-jbrunet@baylibre.com
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

authored by

Jerome Brunet and committed by
Uwe Kleine-König
1031c2b4 141a8502

+121 -74
+121 -74
drivers/pwm/pwm-meson.c
··· 98 98 99 99 struct meson_pwm_data { 100 100 const char *const parent_names[MESON_NUM_MUX_PARENTS]; 101 + int (*channels_init)(struct pwm_chip *chip); 101 102 }; 102 103 103 104 struct meson_pwm { ··· 339 338 .get_state = meson_pwm_get_state, 340 339 }; 341 340 342 - static const struct meson_pwm_data pwm_meson8b_data = { 343 - .parent_names = { "xtal", NULL, "fclk_div4", "fclk_div3" }, 344 - }; 345 - 346 - /* 347 - * Only the 2 first inputs of the GXBB AO PWMs are valid 348 - * The last 2 are grounded 349 - */ 350 - static const struct meson_pwm_data pwm_gxbb_ao_data = { 351 - .parent_names = { "xtal", "clk81", NULL, NULL }, 352 - }; 353 - 354 - static const struct meson_pwm_data pwm_axg_ee_data = { 355 - .parent_names = { "xtal", "fclk_div5", "fclk_div4", "fclk_div3" }, 356 - }; 357 - 358 - static const struct meson_pwm_data pwm_axg_ao_data = { 359 - .parent_names = { "xtal", "axg_ao_clk81", "fclk_div4", "fclk_div5" }, 360 - }; 361 - 362 - static const struct meson_pwm_data pwm_g12a_ao_ab_data = { 363 - .parent_names = { "xtal", "g12a_ao_clk81", "fclk_div4", "fclk_div5" }, 364 - }; 365 - 366 - static const struct meson_pwm_data pwm_g12a_ao_cd_data = { 367 - .parent_names = { "xtal", "g12a_ao_clk81", NULL, NULL }, 368 - }; 369 - 370 - static const struct of_device_id meson_pwm_matches[] = { 371 - { 372 - .compatible = "amlogic,meson8b-pwm", 373 - .data = &pwm_meson8b_data 374 - }, 375 - { 376 - .compatible = "amlogic,meson-gxbb-pwm", 377 - .data = &pwm_meson8b_data 378 - }, 379 - { 380 - .compatible = "amlogic,meson-gxbb-ao-pwm", 381 - .data = &pwm_gxbb_ao_data 382 - }, 383 - { 384 - .compatible = "amlogic,meson-axg-ee-pwm", 385 - .data = &pwm_axg_ee_data 386 - }, 387 - { 388 - .compatible = "amlogic,meson-axg-ao-pwm", 389 - .data = &pwm_axg_ao_data 390 - }, 391 - { 392 - .compatible = "amlogic,meson-g12a-ee-pwm", 393 - .data = &pwm_meson8b_data 394 - }, 395 - { 396 - .compatible = "amlogic,meson-g12a-ao-pwm-ab", 397 - .data = &pwm_g12a_ao_ab_data 398 - }, 399 - { 400 - .compatible = "amlogic,meson-g12a-ao-pwm-cd", 401 - .data = &pwm_g12a_ao_cd_data 402 - }, 403 - {}, 404 - }; 405 - MODULE_DEVICE_TABLE(of, meson_pwm_matches); 406 - 407 - static int meson_pwm_init_channels(struct pwm_chip *chip) 341 + static int meson_pwm_init_clocks_meson8b(struct pwm_chip *chip, 342 + struct clk_parent_data *mux_parent_data) 408 343 { 409 344 struct meson_pwm *meson = to_meson_pwm(chip); 410 - struct clk_parent_data mux_parent_data[MESON_NUM_MUX_PARENTS] = {}; 411 345 struct device *dev = pwmchip_parent(chip); 412 346 unsigned int i; 413 347 char name[255]; 414 348 int err; 415 349 416 - for (i = 0; i < MESON_NUM_MUX_PARENTS; i++) { 417 - mux_parent_data[i].index = -1; 418 - mux_parent_data[i].name = meson->data->parent_names[i]; 419 - } 420 - 421 - for (i = 0; i < chip->npwm; i++) { 350 + for (i = 0; i < MESON_NUM_PWMS; i++) { 422 351 struct meson_pwm_channel *channel = &meson->channels[i]; 423 352 struct clk_parent_data div_parent = {}, gate_parent = {}; 424 353 struct clk_init_data init = {}; ··· 426 495 return 0; 427 496 } 428 497 498 + static int meson_pwm_init_channels_meson8b_legacy(struct pwm_chip *chip) 499 + { 500 + struct clk_parent_data mux_parent_data[MESON_NUM_MUX_PARENTS] = {}; 501 + struct meson_pwm *meson = to_meson_pwm(chip); 502 + int i; 503 + 504 + dev_warn_once(pwmchip_parent(chip), 505 + "using obsolete compatible, please consider updating dt\n"); 506 + 507 + for (i = 0; i < MESON_NUM_MUX_PARENTS; i++) { 508 + mux_parent_data[i].index = -1; 509 + mux_parent_data[i].name = meson->data->parent_names[i]; 510 + } 511 + 512 + return meson_pwm_init_clocks_meson8b(chip, mux_parent_data); 513 + } 514 + 515 + static int meson_pwm_init_channels_meson8b_v2(struct pwm_chip *chip) 516 + { 517 + struct clk_parent_data mux_parent_data[MESON_NUM_MUX_PARENTS] = {}; 518 + int i; 519 + 520 + /* 521 + * NOTE: Instead of relying on the hard coded names in the driver 522 + * as the legacy version, this relies on DT to provide the list of 523 + * clocks. 524 + * For once, using input numbers actually makes more sense than names. 525 + * Also DT requires clock-names to be explicitly ordered, so there is 526 + * no point bothering with clock names in this case. 527 + */ 528 + for (i = 0; i < MESON_NUM_MUX_PARENTS; i++) 529 + mux_parent_data[i].index = i; 530 + 531 + return meson_pwm_init_clocks_meson8b(chip, mux_parent_data); 532 + } 533 + 534 + static const struct meson_pwm_data pwm_meson8b_data = { 535 + .parent_names = { "xtal", NULL, "fclk_div4", "fclk_div3" }, 536 + .channels_init = meson_pwm_init_channels_meson8b_legacy, 537 + }; 538 + 539 + /* 540 + * Only the 2 first inputs of the GXBB AO PWMs are valid 541 + * The last 2 are grounded 542 + */ 543 + static const struct meson_pwm_data pwm_gxbb_ao_data = { 544 + .parent_names = { "xtal", "clk81", NULL, NULL }, 545 + .channels_init = meson_pwm_init_channels_meson8b_legacy, 546 + }; 547 + 548 + static const struct meson_pwm_data pwm_axg_ee_data = { 549 + .parent_names = { "xtal", "fclk_div5", "fclk_div4", "fclk_div3" }, 550 + .channels_init = meson_pwm_init_channels_meson8b_legacy, 551 + }; 552 + 553 + static const struct meson_pwm_data pwm_axg_ao_data = { 554 + .parent_names = { "xtal", "axg_ao_clk81", "fclk_div4", "fclk_div5" }, 555 + .channels_init = meson_pwm_init_channels_meson8b_legacy, 556 + }; 557 + 558 + static const struct meson_pwm_data pwm_g12a_ao_ab_data = { 559 + .parent_names = { "xtal", "g12a_ao_clk81", "fclk_div4", "fclk_div5" }, 560 + .channels_init = meson_pwm_init_channels_meson8b_legacy, 561 + }; 562 + 563 + static const struct meson_pwm_data pwm_g12a_ao_cd_data = { 564 + .parent_names = { "xtal", "g12a_ao_clk81", NULL, NULL }, 565 + .channels_init = meson_pwm_init_channels_meson8b_legacy, 566 + }; 567 + 568 + static const struct meson_pwm_data pwm_meson8_v2_data = { 569 + .channels_init = meson_pwm_init_channels_meson8b_v2, 570 + }; 571 + 572 + static const struct of_device_id meson_pwm_matches[] = { 573 + { 574 + .compatible = "amlogic,meson8-pwm-v2", 575 + .data = &pwm_meson8_v2_data 576 + }, 577 + /* The following compatibles are obsolete */ 578 + { 579 + .compatible = "amlogic,meson8b-pwm", 580 + .data = &pwm_meson8b_data 581 + }, 582 + { 583 + .compatible = "amlogic,meson-gxbb-pwm", 584 + .data = &pwm_meson8b_data 585 + }, 586 + { 587 + .compatible = "amlogic,meson-gxbb-ao-pwm", 588 + .data = &pwm_gxbb_ao_data 589 + }, 590 + { 591 + .compatible = "amlogic,meson-axg-ee-pwm", 592 + .data = &pwm_axg_ee_data 593 + }, 594 + { 595 + .compatible = "amlogic,meson-axg-ao-pwm", 596 + .data = &pwm_axg_ao_data 597 + }, 598 + { 599 + .compatible = "amlogic,meson-g12a-ee-pwm", 600 + .data = &pwm_meson8b_data 601 + }, 602 + { 603 + .compatible = "amlogic,meson-g12a-ao-pwm-ab", 604 + .data = &pwm_g12a_ao_ab_data 605 + }, 606 + { 607 + .compatible = "amlogic,meson-g12a-ao-pwm-cd", 608 + .data = &pwm_g12a_ao_cd_data 609 + }, 610 + {}, 611 + }; 612 + MODULE_DEVICE_TABLE(of, meson_pwm_matches); 613 + 429 614 static int meson_pwm_probe(struct platform_device *pdev) 430 615 { 431 616 struct pwm_chip *chip; ··· 562 515 563 516 meson->data = of_device_get_match_data(&pdev->dev); 564 517 565 - err = meson_pwm_init_channels(chip); 518 + err = meson->data->channels_init(chip); 566 519 if (err < 0) 567 520 return err; 568 521