mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 21:44:27 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			239 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			239 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From 0c4cbd38a705bdeab11de4c84ad0ce8c3de8a81d Mon Sep 17 00:00:00 2001
 | |
| From: Claudiu Beznea <claudiu.beznea@microchip.com>
 | |
| 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 <claudiu.beznea@microchip.com>
 | |
| Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com>
 | |
| Link: https://lore.kernel.org/r/20210415105010.569620-5-claudiu.beznea@microchip.com
 | |
| ---
 | |
|  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;
 |