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>
This commit is contained in:
parent
adac4b9594
commit
92bcaddea3
@ -38,7 +38,7 @@ static int gb_fw_spi_connection_init(struct gb_connection *connection)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = gb_spilib_master_init(connection, &connection->bundle->dev);
|
ret = gb_spilib_master_init(connection, &connection->bundle->dev, NULL);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
gb_connection_disable(connection);
|
gb_connection_disable(connection);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -13,6 +13,27 @@
|
|||||||
#include "gbphy.h"
|
#include "gbphy.h"
|
||||||
#include "spilib.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,
|
static int gb_spi_probe(struct gbphy_device *gbphy_dev,
|
||||||
const struct gbphy_device_id *id)
|
const struct gbphy_device_id *id)
|
||||||
{
|
{
|
||||||
@ -29,7 +50,7 @@ static int gb_spi_probe(struct gbphy_device *gbphy_dev,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto exit_connection_destroy;
|
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)
|
if (ret)
|
||||||
goto exit_connection_disable;
|
goto exit_connection_disable;
|
||||||
|
|
||||||
|
@ -15,13 +15,13 @@
|
|||||||
|
|
||||||
#include "greybus.h"
|
#include "greybus.h"
|
||||||
#include "spilib.h"
|
#include "spilib.h"
|
||||||
#include "gbphy.h"
|
|
||||||
|
|
||||||
struct gb_spilib {
|
struct gb_spilib {
|
||||||
struct gb_connection *connection;
|
struct gb_connection *connection;
|
||||||
struct device *parent;
|
struct device *parent;
|
||||||
struct spi_transfer *first_xfer;
|
struct spi_transfer *first_xfer;
|
||||||
struct spi_transfer *last_xfer;
|
struct spi_transfer *last_xfer;
|
||||||
|
struct spilib_ops *ops;
|
||||||
u32 rx_xfer_offset;
|
u32 rx_xfer_offset;
|
||||||
u32 tx_xfer_offset;
|
u32 tx_xfer_offset;
|
||||||
u32 last_xfer_size;
|
u32 last_xfer_size;
|
||||||
@ -373,25 +373,21 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SPI_CORE_SUPPORT_PM
|
|
||||||
static int gb_spi_prepare_transfer_hardware(struct spi_master *master)
|
static int gb_spi_prepare_transfer_hardware(struct spi_master *master)
|
||||||
{
|
{
|
||||||
struct gb_spilib *spi = spi_master_get_devdata(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)
|
static int gb_spi_unprepare_transfer_hardware(struct spi_master *master)
|
||||||
{
|
{
|
||||||
struct gb_spilib *spi = spi_master_get_devdata(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;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static int gb_spi_setup(struct spi_device *spi)
|
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;
|
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 gb_spilib *spi;
|
||||||
struct spi_master *master;
|
struct spi_master *master;
|
||||||
@ -501,6 +498,7 @@ int gb_spilib_master_init(struct gb_connection *connection, struct device *dev)
|
|||||||
spi->connection = connection;
|
spi->connection = connection;
|
||||||
gb_connection_set_data(connection, master);
|
gb_connection_set_data(connection, master);
|
||||||
spi->parent = dev;
|
spi->parent = dev;
|
||||||
|
spi->ops = ops;
|
||||||
|
|
||||||
/* get master configuration */
|
/* get master configuration */
|
||||||
ret = gb_spi_get_master_config(spi);
|
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->setup = gb_spi_setup;
|
||||||
master->transfer_one_message = gb_spi_transfer_one_message;
|
master->transfer_one_message = gb_spi_transfer_one_message;
|
||||||
|
|
||||||
#ifndef SPI_CORE_SUPPORT_PM
|
if (ops && ops->prepare_transfer_hardware) {
|
||||||
master->prepare_transfer_hardware = gb_spi_prepare_transfer_hardware;
|
master->prepare_transfer_hardware =
|
||||||
master->unprepare_transfer_hardware =
|
gb_spi_prepare_transfer_hardware;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ops && ops->unprepare_transfer_hardware) {
|
||||||
|
master->unprepare_transfer_hardware =
|
||||||
gb_spi_unprepare_transfer_hardware;
|
gb_spi_unprepare_transfer_hardware;
|
||||||
#else
|
}
|
||||||
|
|
||||||
|
#ifdef SPI_CORE_SUPPORT_PM
|
||||||
master->auto_runtime_pm = true;
|
master->auto_runtime_pm = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -10,9 +10,15 @@
|
|||||||
#ifndef __SPILIB_H
|
#ifndef __SPILIB_H
|
||||||
#define __SPILIB_H
|
#define __SPILIB_H
|
||||||
|
|
||||||
|
struct device;
|
||||||
struct gb_connection;
|
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);
|
void gb_spilib_master_exit(struct gb_connection *connection);
|
||||||
|
|
||||||
#endif /* __SPILIB_H */
|
#endif /* __SPILIB_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user