diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2016-07-21 14:45:06 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@google.com> | 2016-07-21 19:03:05 -0700 |
commit | 92bcaddea3197e477bb37439805fcb5a2f9942d7 (patch) | |
tree | c38580b183820a61bd7f7579591116175d833157 /drivers/staging | |
parent | adac4b95941189ca301759a67da4a132fc2804d5 (diff) |
greybus: spilib: make spilib independent of gbphy
spilib is used by multiple users currently (spi.c and fw-core.c) but
commit aa52b62a0556 broke that hierarchy and introduced gbphy dependent
code in spilib.
This may have unreliable consequences as we are doing following
operation unconditionally now:
gbphy_dev = to_gbphy_dev(spi->parent);
gbphy_runtime_get_sync(gbphy_dev);
which may not go well when the parent is of type &bundle->dev
(fw-core.c).
This patch introduces spilib_ops and lets the users of the core register
them. This shall have no functional change for the spi.c usecase and
shall fix the unreliable results for the fw-core.c usecase.
Tested by writing to mtd0 dev and verifying (with print messages) that
the below routines are getting called for a gpbridge-test module.
Fixes: aa52b62a0556 ("spi: Add runtime_pm support")
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/greybus/fw-core.c | 2 | ||||
-rw-r--r-- | drivers/staging/greybus/spi.c | 23 | ||||
-rw-r--r-- | drivers/staging/greybus/spilib.c | 28 | ||||
-rw-r--r-- | drivers/staging/greybus/spilib.h | 8 |
4 files changed, 46 insertions, 15 deletions
diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c index 963973242be0..19f92fb0331b 100644 --- a/drivers/staging/greybus/fw-core.c +++ b/drivers/staging/greybus/fw-core.c @@ -38,7 +38,7 @@ static int gb_fw_spi_connection_init(struct gb_connection *connection) if (ret) return ret; - ret = gb_spilib_master_init(connection, &connection->bundle->dev); + ret = gb_spilib_master_init(connection, &connection->bundle->dev, NULL); if (ret) { gb_connection_disable(connection); return ret; diff --git a/drivers/staging/greybus/spi.c b/drivers/staging/greybus/spi.c index 2e6e328bae9e..bb76b3c0118d 100644 --- a/drivers/staging/greybus/spi.c +++ b/drivers/staging/greybus/spi.c @@ -13,6 +13,27 @@ #include "gbphy.h" #include "spilib.h" +#ifndef SPI_CORE_SUPPORT_PM +static int gbphy_spi_prepare_transfer_hardware(struct device *dev) +{ + return gbphy_runtime_get_sync(to_gbphy_dev(dev)); +} + +static void gbphy_spi_unprepare_transfer_hardware(struct device *dev) +{ + gbphy_runtime_put_autosuspend(to_gbphy_dev(dev)); +} + +static struct spilib_ops __spilib_ops = { + .prepare_transfer_hardware = gbphy_spi_prepare_transfer_hardware, + .unprepare_transfer_hardware = gbphy_spi_unprepare_transfer_hardware, +}; + +static struct spilib_ops *spilib_ops = &__spilib_ops; +#else +static struct spilib_ops *spilib_ops = NULL; +#endif + static int gb_spi_probe(struct gbphy_device *gbphy_dev, const struct gbphy_device_id *id) { @@ -29,7 +50,7 @@ static int gb_spi_probe(struct gbphy_device *gbphy_dev, if (ret) goto exit_connection_destroy; - ret = gb_spilib_master_init(connection, &gbphy_dev->dev); + ret = gb_spilib_master_init(connection, &gbphy_dev->dev, spilib_ops); if (ret) goto exit_connection_disable; diff --git a/drivers/staging/greybus/spilib.c b/drivers/staging/greybus/spilib.c index e4c82e0a322b..9427c313dd4e 100644 --- a/drivers/staging/greybus/spilib.c +++ b/drivers/staging/greybus/spilib.c @@ -15,13 +15,13 @@ #include "greybus.h" #include "spilib.h" -#include "gbphy.h" struct gb_spilib { struct gb_connection *connection; struct device *parent; struct spi_transfer *first_xfer; struct spi_transfer *last_xfer; + struct spilib_ops *ops; u32 rx_xfer_offset; u32 tx_xfer_offset; u32 last_xfer_size; @@ -373,25 +373,21 @@ 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); + return spi->ops->prepare_transfer_hardware(spi->parent); } 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); + spi->ops->unprepare_transfer_hardware(spi->parent); return 0; } -#endif static int gb_spi_setup(struct spi_device *spi) { @@ -483,7 +479,8 @@ static int gb_spi_setup_device(struct gb_spilib *spi, u8 cs) return 0; } -int gb_spilib_master_init(struct gb_connection *connection, struct device *dev) +int gb_spilib_master_init(struct gb_connection *connection, struct device *dev, + struct spilib_ops *ops) { struct gb_spilib *spi; struct spi_master *master; @@ -501,6 +498,7 @@ int gb_spilib_master_init(struct gb_connection *connection, struct device *dev) spi->connection = connection; gb_connection_set_data(connection, master); spi->parent = dev; + spi->ops = ops; /* get master configuration */ ret = gb_spi_get_master_config(spi); @@ -518,11 +516,17 @@ 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 = + if (ops && ops->prepare_transfer_hardware) { + master->prepare_transfer_hardware = + gb_spi_prepare_transfer_hardware; + } + + if (ops && ops->unprepare_transfer_hardware) { + master->unprepare_transfer_hardware = gb_spi_unprepare_transfer_hardware; -#else + } + +#ifdef SPI_CORE_SUPPORT_PM master->auto_runtime_pm = true; #endif diff --git a/drivers/staging/greybus/spilib.h b/drivers/staging/greybus/spilib.h index 9be1b3189834..566d0dde7f79 100644 --- a/drivers/staging/greybus/spilib.h +++ b/drivers/staging/greybus/spilib.h @@ -10,9 +10,15 @@ #ifndef __SPILIB_H #define __SPILIB_H +struct device; struct gb_connection; -int gb_spilib_master_init(struct gb_connection *connection, struct device *dev); +struct spilib_ops { + int (*prepare_transfer_hardware)(struct device *dev); + void (*unprepare_transfer_hardware)(struct device *dev); +}; + +int gb_spilib_master_init(struct gb_connection *connection, struct device *dev, struct spilib_ops *ops); void gb_spilib_master_exit(struct gb_connection *connection); #endif /* __SPILIB_H */ |