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.

pinctrl: realtek: Support system suspend and resume

Add system suspend and resume capabilities to the common Realtek pinctrl
library. This enables saving and restoring pin configurations during the
noirq phase for SoCs that define register ranges.

Signed-off-by: Tzuyi Chang <tychang@realtek.com>
Co-developed-by: Yu-Chun Lin <eleanor.lin@realtek.com>
Signed-off-by: Yu-Chun Lin <eleanor.lin@realtek.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>

authored by

Tzuyi Chang and committed by
Linus Walleij
9f6cfc93 aeeac6d3

+111
+98
drivers/pinctrl/realtek/pinctrl-rtd.c
··· 30 30 struct pinctrl_desc desc; 31 31 const struct rtd_pinctrl_desc *info; 32 32 struct regmap *regmap_pinctrl; 33 + u32 **saved_regs; 33 34 }; 34 35 35 36 /* custom pinconf parameters */ ··· 541 540 .use_relaxed_mmio = true, 542 541 }; 543 542 543 + static int rtd_pinctrl_init_pm(struct rtd_pinctrl *data) 544 + { 545 + const struct rtd_pin_range *pin_range = data->info->pin_range; 546 + struct device *dev = data->pcdev->dev; 547 + const struct rtd_reg_range *range; 548 + size_t num_entries; 549 + int i; 550 + 551 + data->saved_regs = devm_kcalloc(dev, pin_range->num_ranges, sizeof(u32 *), GFP_KERNEL); 552 + if (!data->saved_regs) 553 + return -ENOMEM; 554 + 555 + for (i = 0; i < pin_range->num_ranges; i++) { 556 + range = &pin_range->ranges[i]; 557 + num_entries = range->len / 4; 558 + 559 + data->saved_regs[i] = devm_kzalloc(dev, num_entries * sizeof(u32), GFP_KERNEL); 560 + if (!data->saved_regs[i]) 561 + return -ENOMEM; 562 + } 563 + 564 + return 0; 565 + } 566 + 544 567 int rtd_pinctrl_probe(struct platform_device *pdev, const struct rtd_pinctrl_desc *desc) 545 568 { 546 569 struct rtd_pinctrl *data; ··· 604 579 605 580 dev_dbg(&pdev->dev, "probed\n"); 606 581 582 + if (data->info->pin_range) { 583 + if (rtd_pinctrl_init_pm(data)) 584 + return -ENOMEM; 585 + } 586 + 607 587 return 0; 608 588 } 609 589 EXPORT_SYMBOL(rtd_pinctrl_probe); 590 + 591 + static int realtek_pinctrl_suspend(struct device *dev) 592 + { 593 + struct rtd_pinctrl *data = dev_get_drvdata(dev); 594 + const struct rtd_pin_range *pin_range = data->info->pin_range; 595 + const struct rtd_reg_range *range; 596 + u32 *range_regs; 597 + int count; 598 + int i, j; 599 + int ret; 600 + 601 + if (!data->saved_regs) 602 + return 0; 603 + 604 + for (i = 0; i < pin_range->num_ranges; i++) { 605 + range = &pin_range->ranges[i]; 606 + range_regs = data->saved_regs[i]; 607 + count = range->len / 4; 608 + 609 + for (j = 0; j < count; j++) { 610 + ret = regmap_read(data->regmap_pinctrl, range->offset + (j * 4), 611 + &range_regs[j]); 612 + if (ret) { 613 + dev_err(dev, "failed to store register 0x%x: %d\n", 614 + range->offset + (j * 4), ret); 615 + return ret; 616 + } 617 + } 618 + } 619 + 620 + return 0; 621 + } 622 + 623 + static int realtek_pinctrl_resume(struct device *dev) 624 + { 625 + struct rtd_pinctrl *data = dev_get_drvdata(dev); 626 + const struct rtd_pin_range *pin_range = data->info->pin_range; 627 + const struct rtd_reg_range *range; 628 + u32 *range_regs; 629 + int count; 630 + int i, j; 631 + int ret; 632 + 633 + if (!data->saved_regs) 634 + return 0; 635 + 636 + for (i = 0; i < pin_range->num_ranges; i++) { 637 + range = &pin_range->ranges[i]; 638 + range_regs = data->saved_regs[i]; 639 + count = range->len / 4; 640 + 641 + for (j = 0; j < count; j++) { 642 + ret = regmap_write(data->regmap_pinctrl, range->offset + (j * 4), 643 + range_regs[j]); 644 + if (ret) { 645 + dev_err(dev, "failed to restore register 0x%x: %d\n", 646 + range->offset + (j * 4), ret); 647 + return ret; 648 + } 649 + } 650 + } 651 + return 0; 652 + } 653 + 654 + const struct dev_pm_ops realtek_pinctrl_pm_ops = { 655 + NOIRQ_SYSTEM_SLEEP_PM_OPS(realtek_pinctrl_suspend, realtek_pinctrl_resume) 656 + }; 657 + EXPORT_SYMBOL_GPL(realtek_pinctrl_pm_ops); 610 658 611 659 MODULE_DESCRIPTION("Realtek DHC SoC pinctrl driver"); 612 660 MODULE_LICENSE("GPL");
+13
drivers/pinctrl/realtek/pinctrl-rtd.h
··· 47 47 unsigned int pdrive_maskbits; 48 48 }; 49 49 50 + struct rtd_reg_range { 51 + unsigned int offset; 52 + size_t len; 53 + }; 54 + 55 + struct rtd_pin_range { 56 + const struct rtd_reg_range *ranges; 57 + const int num_ranges; 58 + }; 59 + 50 60 struct rtd_pin_desc { 51 61 const char *name; 52 62 unsigned int mux_offset; ··· 129 119 unsigned int num_sconfigs; 130 120 struct rtd_pin_reg_list *lists; 131 121 unsigned int num_regs; 122 + const struct rtd_pin_range *pin_range; 132 123 }; 133 124 134 125 int rtd_pinctrl_probe(struct platform_device *pdev, const struct rtd_pinctrl_desc *desc); 126 + 127 + extern const struct dev_pm_ops realtek_pinctrl_pm_ops;