aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/greybus/kernel_ver.h5
-rw-r--r--drivers/staging/greybus/spi.c6
-rw-r--r--drivers/staging/greybus/spilib.c29
3 files changed, 40 insertions, 0 deletions
diff --git a/drivers/staging/greybus/kernel_ver.h b/drivers/staging/greybus/kernel_ver.h
index 84beb2f6334c..24d5bcd2e0ff 100644
--- a/drivers/staging/greybus/kernel_ver.h
+++ b/drivers/staging/greybus/kernel_ver.h
@@ -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
diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c
index a82337931c0d..2e6e328bae9e 100644
--- a/drivers/staging/greybus/spi.c
+++ b/drivers/staging/greybus/spi.c
@@ -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 @@ exit_connection_destroy:
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);
diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c
index 527909b26d79..e4c82e0a322b 100644
--- a/drivers/staging/greybus/spilib.c
+++ b/drivers/staging/greybus/spilib.c
@@ -15,6 +15,7 @@
#include "greybus.h"
#include "spilib.h"
+#include "gbphy.h"
struct gb_spilib {
struct gb_connection *connection;
@@ -372,6 +373,26 @@ out:
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;