Commit 4c615dcc authored by Axel Haslam's avatar Axel Haslam Committed by Alex Elder

greybus: spi: Add runtime_pm support

Add runtime operations to the spi driver so that the
module is woken up when an spi transfer is started
and put back to sleep when the transfer is done.

Testing Done: Let the module enter standby and initiate
an spi operation. The operation wakes up the module
and succeeds.
Signed-off-by: default avatarAxel Haslam <ahaslam@baylibre.com>
Signed-off-by: default avatarDavid Lin <dtwlin@google.com>
Reviewed-by: default avatarRui Miguel Silva <rui.silva@linaro.org>
Signed-off-by: default avatarAlex Elder <elder@linaro.org>
parent afa807b8
......@@ -313,6 +313,11 @@ static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev)
#define SPI_NOR_MODALIAS "m25p80"
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
/* Starting from this version, the spi core handles runtime pm automatically */
#define SPI_CORE_SUPPORT_PM
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
/**
* reinit_completion - reinitialize a completion structure
......
......@@ -35,6 +35,7 @@ static int gb_spi_probe(struct gbphy_device *gbphy_dev,
gb_gbphy_set_data(gbphy_dev, connection);
gbphy_runtime_put_autosuspend(gbphy_dev);
return 0;
exit_connection_disable:
......@@ -48,6 +49,11 @@ static int gb_spi_probe(struct gbphy_device *gbphy_dev,
static void gb_spi_remove(struct gbphy_device *gbphy_dev)
{
struct gb_connection *connection = gb_gbphy_get_data(gbphy_dev);
int ret;
ret = gbphy_runtime_get_sync(gbphy_dev);
if (ret)
gbphy_runtime_get_noresume(gbphy_dev);
gb_spilib_master_exit(connection);
gb_connection_disable(connection);
......
......@@ -15,6 +15,7 @@
#include "greybus.h"
#include "spilib.h"
#include "gbphy.h"
struct gb_spilib {
struct gb_connection *connection;
......@@ -372,6 +373,26 @@ static int gb_spi_transfer_one_message(struct spi_master *master,
return ret;
}
#ifndef SPI_CORE_SUPPORT_PM
static int gb_spi_prepare_transfer_hardware(struct spi_master *master)
{
struct gb_spilib *spi = spi_master_get_devdata(master);
struct gbphy_device *gbphy_dev = to_gbphy_dev(spi->parent);
return gbphy_runtime_get_sync(gbphy_dev);
}
static int gb_spi_unprepare_transfer_hardware(struct spi_master *master)
{
struct gb_spilib *spi = spi_master_get_devdata(master);
struct gbphy_device *gbphy_dev = to_gbphy_dev(spi->parent);
gbphy_runtime_put_autosuspend(gbphy_dev);
return 0;
}
#endif
static int gb_spi_setup(struct spi_device *spi)
{
/* Nothing to do for now */
......@@ -497,6 +518,14 @@ int gb_spilib_master_init(struct gb_connection *connection, struct device *dev)
master->setup = gb_spi_setup;
master->transfer_one_message = gb_spi_transfer_one_message;
#ifndef SPI_CORE_SUPPORT_PM
master->prepare_transfer_hardware = gb_spi_prepare_transfer_hardware;
master->unprepare_transfer_hardware =
gb_spi_unprepare_transfer_hardware;
#else
master->auto_runtime_pm = true;
#endif
ret = spi_register_master(master);
if (ret < 0)
goto exit_spi_put;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment