Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ba3e6700 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

greybus: SPI: convert to a gpbridge driver



This converts the SPI driver to be a gpbridge driver, moving it away
from the "legacy" interface.

Testing Done: Tested on gbsim.

Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
Signed-off-by: default avatarVaibhav Hiremath <vaibhav.hiremath@linaro.org>
[vaibhav.hiremath@linaro.org: 1.Changed code to retain init/exit fns of
drivers. 2.Exit path fix. 3. Fixed review comments]
Reviewed-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Tested-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent dcd2086a
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -256,6 +256,7 @@ static const struct greybus_bundle_id gb_gpbridge_id_table[] = {
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) },
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) },
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) },
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) },
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) },
	{ },
};
@@ -308,8 +309,8 @@ static int __init gpbridge_init(void)
		pr_err("error initializing i2c driver\n");
		goto error_i2c;
	}
	if (gb_spi_protocol_init()) {
		pr_err("error initializing spi protocol\n");
	if (gb_spi_driver_init()) {
		pr_err("error initializing spi driver\n");
		goto error_spi;
	}

@@ -338,7 +339,7 @@ module_init(gpbridge_init);

static void __exit gpbridge_exit(void)
{
	gb_spi_protocol_exit();
	gb_spi_driver_exit();
	gb_i2c_driver_exit();
	gb_usb_protocol_exit();
	gb_sdio_driver_exit();
+2 −2
Original line number Diff line number Diff line
@@ -84,8 +84,8 @@ extern void gb_usb_protocol_exit(void);
extern int gb_i2c_driver_init(void);
extern void gb_i2c_driver_exit(void);

extern int gb_spi_protocol_init(void);
extern void gb_spi_protocol_exit(void);
extern int gb_spi_driver_init(void);
extern void gb_spi_driver_exit(void);

#endif /* __GPBRIDGE_H */
+0 −1
Original line number Diff line number Diff line
@@ -237,7 +237,6 @@ static void legacy_disconnect(struct gb_bundle *bundle)

static const struct greybus_bundle_id legacy_id_table[] = {
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) },
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) },
	{ GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) },
	{ }
};
+56 −23
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

struct gb_spi {
	struct gb_connection	*connection;
	struct gpbridge_device	*gpbdev;
	struct spi_transfer	*first_xfer;
	struct spi_transfer	*last_xfer;
	u32			rx_xfer_offset;
@@ -174,7 +175,7 @@ gb_spi_operation_create(struct gb_spi *spi, struct gb_connection *connection,
		spi->last_xfer = xfer;

		if (!xfer->tx_buf && !xfer->rx_buf) {
			dev_err(&connection->bundle->dev,
			dev_err(&spi->gpbdev->dev,
				"bufferless transfer, length %u\n", xfer->len);
			msg->state = GB_SPI_STATE_MSG_ERROR;
			return NULL;
@@ -342,7 +343,7 @@ static int gb_spi_transfer_one_message(struct spi_master *master,
			if (response)
				gb_spi_decode_response(spi, msg, response);
		} else {
			dev_err(&connection->bundle->dev,
			dev_err(&spi->gpbdev->dev,
				"transfer operation failed: %d\n", ret);
			msg->state = GB_SPI_STATE_MSG_ERROR;
		}
@@ -450,28 +451,48 @@ static int gb_spi_setup_device(struct gb_spi *spi, u8 cs)
	return 0;
}

static int gb_spi_connection_init(struct gb_connection *connection)
static int gb_spi_probe(struct gpbridge_device *gpbdev,
			const struct gpbridge_device_id *id)
{
	struct gb_connection *connection;
	struct gb_spi *spi;
	struct spi_master *master;
	int ret;
	u8 i;

	/* Allocate master with space for data */
	master = spi_alloc_master(&connection->bundle->dev, sizeof(*spi));
	master = spi_alloc_master(&gpbdev->dev, sizeof(*spi));
	if (!master) {
		dev_err(&connection->bundle->dev, "cannot alloc SPI master\n");
		dev_err(&gpbdev->dev, "cannot alloc SPI master\n");
		return -ENOMEM;
	}

	connection = gb_connection_create(gpbdev->bundle,
					  le16_to_cpu(gpbdev->cport_desc->id),
					  NULL);
	if (IS_ERR(connection)) {
		ret = PTR_ERR(connection);
		goto exit_spi_put;
	}

	spi = spi_master_get_devdata(master);
	spi->connection = connection;
	gb_connection_set_data(connection, master);
	spi->gpbdev = gpbdev;
	gb_gpbridge_set_data(gpbdev, master);

	ret = gb_connection_enable(connection);
	if (ret)
		goto exit_connection_destroy;

	ret = gb_gpbridge_get_version(connection);
	if (ret)
		goto exit_connection_disable;

	/* get master configuration */
	ret = gb_spi_get_master_config(spi);
	if (ret)
		goto out_put_master;
		goto exit_connection_disable;

	master->bus_num = -1; /* Allow spi-core to allocate it dynamically */
	master->num_chipselect = spi->num_chipselect;
@@ -486,42 +507,54 @@ static int gb_spi_connection_init(struct gb_connection *connection)

	ret = spi_register_master(master);
	if (ret < 0)
		goto out_put_master;
		goto exit_connection_disable;

	/* now, fetch the devices configuration */
	for (i = 0; i < spi->num_chipselect; i++) {
		ret = gb_spi_setup_device(spi, i);
		if (ret < 0) {
			dev_err(&connection->bundle->dev,
				"failed to allocated spi device: %d\n", ret);
			spi_unregister_master(master);
			break;
			dev_err(&gpbdev->dev,
				"failed to allocate spi device %d: %d\n",
				i, ret);
			goto exit_spi_unregister;
		}
	}

	return ret;

out_put_master:
exit_spi_unregister:
	spi_unregister_master(master);
exit_connection_disable:
	gb_connection_disable(connection);
exit_connection_destroy:
	gb_connection_destroy(connection);
exit_spi_put:
	spi_master_put(master);

	return ret;
}

static void gb_spi_connection_exit(struct gb_connection *connection)
static void gb_spi_remove(struct gpbridge_device *gpbdev)
{
	struct spi_master *master = gb_connection_get_data(connection);
	struct spi_master *master = gb_gpbridge_get_data(gpbdev);
	struct gb_spi *spi = spi_master_get_devdata(master);
	struct gb_connection *connection = spi->connection;

	spi_unregister_master(master);
	gb_connection_disable(connection);
	gb_connection_destroy(connection);
	spi_master_put(master);
}

static struct gb_protocol spi_protocol = {
	.name			= "spi",
	.id			= GREYBUS_PROTOCOL_SPI,
	.major			= GB_SPI_VERSION_MAJOR,
	.minor			= GB_SPI_VERSION_MINOR,
	.connection_init	= gb_spi_connection_init,
	.connection_exit	= gb_spi_connection_exit,
	.request_recv		= NULL,
static const struct gpbridge_device_id gb_spi_id_table[] = {
	{ GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_SPI) },
	{ },
};

gb_builtin_protocol_driver(spi_protocol);
static struct gpbridge_driver spi_driver = {
	.name		= "spi",
	.probe		= gb_spi_probe,
	.remove		= gb_spi_remove,
	.id_table	= gb_spi_id_table,
};
gb_gpbridge_builtin_driver(spi_driver);