mirror of https://github.com/OpenIPC/firmware.git
				
				
				
			
		
			
				
	
	
		
			129 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Diff
		
	
	
			
		
		
	
	
			129 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Diff
		
	
	
| --- linux-4.9.37/drivers/spi/spi.c	2017-07-12 16:42:41.000000000 +0300
 | |
| +++ linux-4.9.y/drivers/spi/spi.c	2021-06-07 13:01:34.000000000 +0300
 | |
| @@ -323,11 +323,125 @@
 | |
|  	return 0;
 | |
|  }
 | |
|  
 | |
| +#ifdef CONFIG_PM_SLEEP
 | |
| +static int spi_legacy_suspend(struct device *dev, pm_message_t message)
 | |
| +{
 | |
| +	int			value = 0;
 | |
| +	struct spi_driver	*drv = to_spi_driver(dev->driver);
 | |
| +
 | |
| +	/* suspend will stop irqs and dma; no more i/o */
 | |
| +	if (drv) {
 | |
| +		if (drv->suspend)
 | |
| +			value = drv->suspend(to_spi_device(dev), message);
 | |
| +		else
 | |
| +			dev_dbg(dev, "... can't suspend\n");
 | |
| +	}
 | |
| +	return value;
 | |
| +}
 | |
| +
 | |
| +static int spi_legacy_resume(struct device *dev)
 | |
| +{
 | |
| +	int			value = 0;
 | |
| +	struct spi_driver	*drv = to_spi_driver(dev->driver);
 | |
| +
 | |
| +	/* resume may restart the i/o queue */
 | |
| +	if (drv) {
 | |
| +		if (drv->resume)
 | |
| +			value = drv->resume(to_spi_device(dev));
 | |
| +		else
 | |
| +			dev_dbg(dev, "... can't resume\n");
 | |
| +	}
 | |
| +	return value;
 | |
| +}
 | |
| +
 | |
| +static int spi_pm_suspend(struct device *dev)
 | |
| +{
 | |
| +	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 | |
| +
 | |
| +	if (pm)
 | |
| +		return pm_generic_suspend(dev);
 | |
| +	else
 | |
| +		return spi_legacy_suspend(dev, PMSG_SUSPEND);
 | |
| +}
 | |
| +
 | |
| +static int spi_pm_resume(struct device *dev)
 | |
| +{
 | |
| +	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 | |
| +
 | |
| +	if (pm)
 | |
| +		return pm_generic_resume(dev);
 | |
| +	else
 | |
| +		return spi_legacy_resume(dev);
 | |
| +}
 | |
| +
 | |
| +static int spi_pm_freeze(struct device *dev)
 | |
| +{
 | |
| +	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 | |
| +
 | |
| +	if (pm)
 | |
| +		return pm_generic_freeze(dev);
 | |
| +	else
 | |
| +		return spi_legacy_suspend(dev, PMSG_FREEZE);
 | |
| +}
 | |
| +
 | |
| +static int spi_pm_thaw(struct device *dev)
 | |
| +{
 | |
| +	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 | |
| +
 | |
| +	if (pm)
 | |
| +		return pm_generic_thaw(dev);
 | |
| +	else
 | |
| +		return spi_legacy_resume(dev);
 | |
| +}
 | |
| +
 | |
| +static int spi_pm_poweroff(struct device *dev)
 | |
| +{
 | |
| +	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 | |
| +
 | |
| +	if (pm)
 | |
| +		return pm_generic_poweroff(dev);
 | |
| +	else
 | |
| +		return spi_legacy_suspend(dev, PMSG_HIBERNATE);
 | |
| +}
 | |
| +
 | |
| +static int spi_pm_restore(struct device *dev)
 | |
| +{
 | |
| +	const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 | |
| +
 | |
| +	if (pm)
 | |
| +		return pm_generic_restore(dev);
 | |
| +	else
 | |
| +		return spi_legacy_resume(dev);
 | |
| +}
 | |
| +#else
 | |
| +#define spi_pm_suspend	NULL
 | |
| +#define spi_pm_resume	NULL
 | |
| +#define spi_pm_freeze	NULL
 | |
| +#define spi_pm_thaw	NULL
 | |
| +#define spi_pm_poweroff	NULL
 | |
| +#define spi_pm_restore	NULL
 | |
| +#endif
 | |
| +
 | |
| +static const struct dev_pm_ops spi_pm = {
 | |
| +	.suspend = spi_pm_suspend,
 | |
| +	.resume = spi_pm_resume,
 | |
| +	.freeze = spi_pm_freeze,
 | |
| +	.thaw = spi_pm_thaw,
 | |
| +	.poweroff = spi_pm_poweroff,
 | |
| +	.restore = spi_pm_restore,
 | |
| +	SET_RUNTIME_PM_OPS(
 | |
| +		pm_generic_runtime_suspend,
 | |
| +		pm_generic_runtime_resume,
 | |
| +		NULL
 | |
| +	)
 | |
| +};
 | |
| +
 | |
|  struct bus_type spi_bus_type = {
 | |
|  	.name		= "spi",
 | |
|  	.dev_groups	= spi_dev_groups,
 | |
|  	.match		= spi_match_device,
 | |
|  	.uevent		= spi_uevent,
 | |
| +	.pm		= &spi_pm,
 | |
|  };
 | |
|  EXPORT_SYMBOL_GPL(spi_bus_type);
 | |
|  
 |