123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- From 0c4cbd38a705bdeab11de4c84ad0ce8c3de8a81d Mon Sep 17 00:00:00 2001
- From: Claudiu Beznea <[email protected]>
- Date: Thu, 15 Apr 2021 13:49:50 +0300
- Subject: [PATCH 200/247] ARM: at91: pm: check for different controllers in
- at91_pm_modes_init()
- at91_pm_modes_init() checks for proper nodes in device tree and maps
- them accordingly. Up to SAMA7G5 all AT91 SoCs had the same mapping
- b/w power saving modes and different controllers needed in the
- final/first steps of suspend/resume. SAMA7G5 is not aligned with the
- old SoCs thus the code is adapted for this. This patch prepares
- the field for next commits.
- Signed-off-by: Claudiu Beznea <[email protected]>
- Signed-off-by: Nicolas Ferre <[email protected]>
- Link: https://lore.kernel.org/r/[email protected]
- ---
- arch/arm/mach-at91/pm.c | 143 +++++++++++++++++++++++++---------------
- 1 file changed, 91 insertions(+), 52 deletions(-)
- --- a/arch/arm/mach-at91/pm.c
- +++ b/arch/arm/mach-at91/pm.c
- @@ -57,6 +57,18 @@ struct at91_soc_pm {
- struct at91_pm_data data;
- };
-
- +/**
- + * enum at91_pm_iomaps: IOs that needs to be mapped for different PM modes
- + * @AT91_PM_IOMAP_SHDWC: SHDWC controller
- + * @AT91_PM_IOMAP_SFRBU: SFRBU controller
- + */
- +enum at91_pm_iomaps {
- + AT91_PM_IOMAP_SHDWC,
- + AT91_PM_IOMAP_SFRBU,
- +};
- +
- +#define AT91_PM_IOMAP(name) BIT(AT91_PM_IOMAP_##name)
- +
- static struct at91_soc_pm soc_pm = {
- .data = {
- .standby_mode = AT91_PM_STANDBY,
- @@ -671,24 +683,15 @@ static int __init at91_pm_backup_init(vo
- if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
- return 0;
-
- - np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
- - if (!np) {
- - pr_warn("%s: failed to find sfrbu!\n", __func__);
- - return ret;
- - }
- -
- - soc_pm.data.sfrbu = of_iomap(np, 0);
- - of_node_put(np);
- -
- np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam");
- if (!np)
- - goto securam_fail_no_ref_dev;
- + return ret;
-
- pdev = of_find_device_by_node(np);
- of_node_put(np);
- if (!pdev) {
- pr_warn("%s: failed to find securam device!\n", __func__);
- - goto securam_fail_no_ref_dev;
- + return ret;
- }
-
- sram_pool = gen_pool_get(&pdev->dev, NULL);
- @@ -712,64 +715,92 @@ static int __init at91_pm_backup_init(vo
-
- securam_fail:
- put_device(&pdev->dev);
- -securam_fail_no_ref_dev:
- - iounmap(soc_pm.data.sfrbu);
- - soc_pm.data.sfrbu = NULL;
- return ret;
- }
-
- -static void __init at91_pm_use_default_mode(int pm_mode)
- -{
- - if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP)
- - return;
- -
- - if (soc_pm.data.standby_mode == pm_mode)
- - soc_pm.data.standby_mode = AT91_PM_ULP0;
- - if (soc_pm.data.suspend_mode == pm_mode)
- - soc_pm.data.suspend_mode = AT91_PM_ULP0;
- -}
- -
- static const struct of_device_id atmel_shdwc_ids[] = {
- { .compatible = "atmel,sama5d2-shdwc" },
- { .compatible = "microchip,sam9x60-shdwc" },
- { /* sentinel. */ }
- };
-
- -static void __init at91_pm_modes_init(void)
- +static void __init at91_pm_modes_init(const u32 *maps, int len)
- {
- struct device_node *np;
- - int ret;
- + int ret, mode;
-
- - if (!at91_is_pm_mode_active(AT91_PM_BACKUP) &&
- - !at91_is_pm_mode_active(AT91_PM_ULP1))
- - return;
- + ret = at91_pm_backup_init();
- + if (ret) {
- + if (soc_pm.data.standby_mode == AT91_PM_BACKUP)
- + soc_pm.data.standby_mode = AT91_PM_ULP0;
- + if (soc_pm.data.suspend_mode == AT91_PM_BACKUP)
- + soc_pm.data.suspend_mode = AT91_PM_ULP0;
- + }
- +
- + if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC) ||
- + maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC)) {
- + np = of_find_matching_node(NULL, atmel_shdwc_ids);
- + if (!np) {
- + pr_warn("%s: failed to find shdwc!\n", __func__);
- +
- + /* Use ULP0 if it doesn't needs SHDWC.*/
- + if (!(maps[AT91_PM_ULP0] & AT91_PM_IOMAP(SHDWC)))
- + mode = AT91_PM_ULP0;
- + else
- + mode = AT91_PM_STANDBY;
- +
- + if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC))
- + soc_pm.data.standby_mode = mode;
- + if (maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC))
- + soc_pm.data.suspend_mode = mode;
- + } else {
- + soc_pm.data.shdwc = of_iomap(np, 0);
- + of_node_put(np);
- + }
- + }
-
- - np = of_find_matching_node(NULL, atmel_shdwc_ids);
- - if (!np) {
- - pr_warn("%s: failed to find shdwc!\n", __func__);
- - goto ulp1_default;
- + if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SFRBU) ||
- + maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU)) {
- + np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
- + if (!np) {
- + pr_warn("%s: failed to find sfrbu!\n", __func__);
- +
- + /*
- + * Use ULP0 if it doesn't need SHDWC or if SHDWC
- + * was already located.
- + */
- + if (!(maps[AT91_PM_ULP0] & AT91_PM_IOMAP(SHDWC)) ||
- + soc_pm.data.shdwc)
- + mode = AT91_PM_ULP0;
- + else
- + mode = AT91_PM_STANDBY;
- +
- + if (maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SFRBU))
- + soc_pm.data.standby_mode = mode;
- + if (maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU))
- + soc_pm.data.suspend_mode = mode;
- + } else {
- + soc_pm.data.sfrbu = of_iomap(np, 0);
- + of_node_put(np);
- + }
- }
-
- - soc_pm.data.shdwc = of_iomap(np, 0);
- - of_node_put(np);
- + /* Unmap all unnecessary. */
- + if (soc_pm.data.shdwc &&
- + !(maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SHDWC) ||
- + maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SHDWC))) {
- + iounmap(soc_pm.data.shdwc);
- + soc_pm.data.shdwc = NULL;
- + }
-
- - ret = at91_pm_backup_init();
- - if (ret) {
- - if (!at91_is_pm_mode_active(AT91_PM_ULP1))
- - goto unmap;
- - else
- - goto backup_default;
- + if (soc_pm.data.sfrbu &&
- + !(maps[soc_pm.data.standby_mode] & AT91_PM_IOMAP(SFRBU) ||
- + maps[soc_pm.data.suspend_mode] & AT91_PM_IOMAP(SFRBU))) {
- + iounmap(soc_pm.data.sfrbu);
- + soc_pm.data.sfrbu = NULL;
- }
-
- return;
- -
- -unmap:
- - iounmap(soc_pm.data.shdwc);
- - soc_pm.data.shdwc = NULL;
- -ulp1_default:
- - at91_pm_use_default_mode(AT91_PM_ULP1);
- -backup_default:
- - at91_pm_use_default_mode(AT91_PM_BACKUP);
- }
-
- struct pmc_info {
- @@ -936,13 +967,16 @@ void __init sam9x60_pm_init(void)
- static const int modes[] __initconst = {
- AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
- };
- + static const int iomaps[] __initconst = {
- + [AT91_PM_ULP1] = AT91_PM_IOMAP(SHDWC),
- + };
- int ret;
-
- if (!IS_ENABLED(CONFIG_SOC_SAM9X60))
- return;
-
- at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
- - at91_pm_modes_init();
- + at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
- ret = at91_dt_ramc();
- if (ret)
- return;
- @@ -999,13 +1033,18 @@ void __init sama5d2_pm_init(void)
- AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
- AT91_PM_BACKUP,
- };
- + static const u32 iomaps[] __initconst = {
- + [AT91_PM_ULP1] = AT91_PM_IOMAP(SHDWC),
- + [AT91_PM_BACKUP] = AT91_PM_IOMAP(SHDWC) |
- + AT91_PM_IOMAP(SFRBU),
- + };
- int ret;
-
- if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
- return;
-
- at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
- - at91_pm_modes_init();
- + at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
- ret = at91_dt_ramc();
- if (ret)
- return;
|