From cf1d8bee59aa995fcc6514be7a67e9575bbe5498 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 5 May 2016 14:32:32 +0530 Subject: [PATCH] greybus: I2C: convert to a gpbridge driver This converts the I2C driver to be a gpbridge driver, moving it away from the "legacy" interface. Testing Done: Tested on gbsim. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Vaibhav Hiremath [vaibhav.hiremath@linaro.org: 1.Changed code to retain init/exit fns of drivers. 2.Exit path fix. 3. Fixed review comments] Reviewed-by: Viresh Kumar Tested-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/gpbridge.c | 9 ++-- drivers/staging/greybus/gpbridge.h | 4 +- drivers/staging/greybus/i2c.c | 71 +++++++++++++++++++++--------- drivers/staging/greybus/legacy.c | 1 - 4 files changed, 57 insertions(+), 28 deletions(-) diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index a446749789f9..e3c11cba3a51 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -252,6 +252,7 @@ static int gb_gpbridge_probe(struct gb_bundle *bundle, static const struct greybus_bundle_id gb_gpbridge_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_BRIDGED_PHY) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) }, { }, @@ -301,8 +302,8 @@ static int __init gpbridge_init(void) pr_err("error initializing usb protocol\n"); goto error_usb; } - if (gb_i2c_protocol_init()) { - pr_err("error initializing i2c protocol\n"); + if (gb_i2c_driver_init()) { + pr_err("error initializing i2c driver\n"); goto error_i2c; } if (gb_spi_protocol_init()) { @@ -313,7 +314,7 @@ static int __init gpbridge_init(void) return 0; error_spi: - gb_i2c_protocol_exit(); + gb_i2c_driver_exit(); error_i2c: gb_usb_protocol_exit(); error_usb: @@ -336,7 +337,7 @@ module_init(gpbridge_init); static void __exit gpbridge_exit(void) { gb_spi_protocol_exit(); - gb_i2c_protocol_exit(); + gb_i2c_driver_exit(); gb_usb_protocol_exit(); gb_sdio_protocol_exit(); gb_uart_driver_exit(); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index 8681bd33e671..a64e9cb35f5e 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -81,8 +81,8 @@ extern void gb_sdio_protocol_exit(void); extern int gb_usb_protocol_init(void); extern void gb_usb_protocol_exit(void); -extern int gb_i2c_protocol_init(void); -extern void gb_i2c_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); diff --git a/drivers/staging/greybus/i2c.c b/drivers/staging/greybus/i2c.c index 73b85815d1eb..b49e8b455ab1 100644 --- a/drivers/staging/greybus/i2c.c +++ b/drivers/staging/greybus/i2c.c @@ -17,6 +17,7 @@ struct gb_i2c_device { struct gb_connection *connection; + struct gpbridge_device *gpbdev; u32 functionality; @@ -71,6 +72,7 @@ static struct gb_operation * gb_i2c_operation_create(struct gb_connection *connection, struct i2c_msg *msgs, u32 msg_count) { + struct gb_i2c_device *gb_i2c_dev = gb_connection_get_data(connection); struct gb_i2c_transfer_request *request; struct gb_operation *operation; struct gb_i2c_transfer_op *op; @@ -83,7 +85,7 @@ gb_i2c_operation_create(struct gb_connection *connection, u32 i; if (msg_count > (u32)U16_MAX) { - dev_err(&connection->bundle->dev, "msg_count (%u) too big\n", + dev_err(&gb_i2c_dev->gpbdev->dev, "msg_count (%u) too big\n", msg_count); return NULL; } @@ -166,7 +168,7 @@ static int gb_i2c_transfer_operation(struct gb_i2c_device *gb_i2c_dev, struct i2c_msg *msgs, u32 msg_count) { struct gb_connection *connection = gb_i2c_dev->connection; - struct device *dev = &connection->bundle->dev; + struct device *dev = &gb_i2c_dev->gpbdev->dev; struct gb_operation *operation; int ret; @@ -240,8 +242,10 @@ static int gb_i2c_device_setup(struct gb_i2c_device *gb_i2c_dev) return gb_i2c_functionality_operation(gb_i2c_dev); } -static int gb_i2c_connection_init(struct gb_connection *connection) +static int gb_i2c_probe(struct gpbridge_device *gpbdev, + const struct gpbridge_device_id *id) { + struct gb_connection *connection; struct gb_i2c_device *gb_i2c_dev; struct i2c_adapter *adapter; int ret; @@ -250,12 +254,30 @@ static int gb_i2c_connection_init(struct gb_connection *connection) if (!gb_i2c_dev) return -ENOMEM; - gb_i2c_dev->connection = connection; /* refcount? */ + connection = gb_connection_create(gpbdev->bundle, + le16_to_cpu(gpbdev->cport_desc->id), + NULL); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto exit_i2cdev_free; + } + + gb_i2c_dev->connection = connection; gb_connection_set_data(connection, gb_i2c_dev); + gb_i2c_dev->gpbdev = gpbdev; + gb_gpbridge_set_data(gpbdev, gb_i2c_dev); + + ret = gb_connection_enable(connection); + if (ret) + goto exit_connection_destroy; + + ret = gb_gpbridge_get_version(connection); + if (ret) + goto exit_connection_disable; ret = gb_i2c_device_setup(gb_i2c_dev); if (ret) - goto out_err; + goto exit_connection_disable; /* Looks good; up our i2c adapter */ adapter = &gb_i2c_dev->adapter; @@ -264,39 +286,46 @@ static int gb_i2c_connection_init(struct gb_connection *connection) adapter->algo = &gb_i2c_algorithm; /* adapter->algo_data = what? */ - adapter->dev.parent = &connection->bundle->dev; + adapter->dev.parent = &gpbdev->dev; snprintf(adapter->name, sizeof(adapter->name), "Greybus i2c adapter"); i2c_set_adapdata(adapter, gb_i2c_dev); ret = i2c_add_adapter(adapter); if (ret) - goto out_err; + goto exit_connection_disable; return 0; -out_err: - /* kref_put(gb_i2c_dev->connection) */ + +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); +exit_i2cdev_free: kfree(gb_i2c_dev); return ret; } -static void gb_i2c_connection_exit(struct gb_connection *connection) +static void gb_i2c_remove(struct gpbridge_device *gpbdev) { - struct gb_i2c_device *gb_i2c_dev = gb_connection_get_data(connection); + struct gb_i2c_device *gb_i2c_dev = gb_gpbridge_get_data(gpbdev); + struct gb_connection *connection = gb_i2c_dev->connection; i2c_del_adapter(&gb_i2c_dev->adapter); - /* kref_put(gb_i2c_dev->connection) */ + gb_connection_disable(connection); + gb_connection_destroy(connection); kfree(gb_i2c_dev); } -static struct gb_protocol i2c_protocol = { - .name = "i2c", - .id = GREYBUS_PROTOCOL_I2C, - .major = GB_I2C_VERSION_MAJOR, - .minor = GB_I2C_VERSION_MINOR, - .connection_init = gb_i2c_connection_init, - .connection_exit = gb_i2c_connection_exit, - .request_recv = NULL, /* no incoming requests */ +static const struct gpbridge_device_id gb_i2c_id_table[] = { + { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_I2C) }, + { }, }; -gb_builtin_protocol_driver(i2c_protocol); +static struct gpbridge_driver i2c_driver = { + .name = "i2c", + .probe = gb_i2c_probe, + .remove = gb_i2c_remove, + .id_table = gb_i2c_id_table, +}; +gb_gpbridge_builtin_driver(i2c_driver); diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index f9bcdded9b6a..f734646fd30a 100644 --- a/drivers/staging/greybus/legacy.c +++ b/drivers/staging/greybus/legacy.c @@ -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_GPIO) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_USB) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, -- 2.39.2