From: Greg Kroah-Hartman Date: Thu, 5 May 2016 09:02:34 +0000 (+0530) Subject: greybus: SDIO: convert to a gpbridge driver X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=dcd2086aa87e274e2f2f96eae449a27548637dd9;p=linux-beck.git greybus: SDIO: convert to a gpbridge driver This converts the SDIO 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 --- diff --git a/drivers/staging/greybus/gpbridge.c b/drivers/staging/greybus/gpbridge.c index a65ab1609127..d228e276f788 100644 --- a/drivers/staging/greybus/gpbridge.c +++ b/drivers/staging/greybus/gpbridge.c @@ -255,6 +255,7 @@ static const struct greybus_bundle_id gb_gpbridge_id_table[] = { { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_GPIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_I2C) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_PWM) }, + { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_UART) }, { }, }; @@ -295,8 +296,8 @@ static int __init gpbridge_init(void) pr_err("error initializing uart driver\n"); goto error_uart; } - if (gb_sdio_protocol_init()) { - pr_err("error initializing sdio protocol\n"); + if (gb_sdio_driver_init()) { + pr_err("error initializing sdio driver\n"); goto error_sdio; } if (gb_usb_protocol_init()) { @@ -319,7 +320,7 @@ error_spi: error_i2c: gb_usb_protocol_exit(); error_usb: - gb_sdio_protocol_exit(); + gb_sdio_driver_exit(); error_sdio: gb_uart_driver_exit(); error_uart: @@ -340,7 +341,7 @@ static void __exit gpbridge_exit(void) gb_spi_protocol_exit(); gb_i2c_driver_exit(); gb_usb_protocol_exit(); - gb_sdio_protocol_exit(); + gb_sdio_driver_exit(); gb_uart_driver_exit(); gb_pwm_driver_exit(); gb_gpio_driver_exit(); diff --git a/drivers/staging/greybus/gpbridge.h b/drivers/staging/greybus/gpbridge.h index f5161c56cc98..3f1d19eb35f3 100644 --- a/drivers/staging/greybus/gpbridge.h +++ b/drivers/staging/greybus/gpbridge.h @@ -75,8 +75,8 @@ extern void gb_pwm_driver_exit(void); extern int gb_uart_driver_init(void); extern void gb_uart_driver_exit(void); -extern int gb_sdio_protocol_init(void); -extern void gb_sdio_protocol_exit(void); +extern int gb_sdio_driver_init(void); +extern void gb_sdio_driver_exit(void); extern int gb_usb_protocol_init(void); extern void gb_usb_protocol_exit(void); diff --git a/drivers/staging/greybus/legacy.c b/drivers/staging/greybus/legacy.c index ee122ad2334a..d94282d2dbe5 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_USB) }, - { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SDIO) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_SPI) }, { GREYBUS_DEVICE_CLASS(GREYBUS_CLASS_CAMERA) }, { } diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index d4cbcb972e94..8ee4d4c5e73d 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -19,6 +19,7 @@ struct gb_sdio_host { struct gb_connection *connection; + struct gpbridge_device *gpbdev; struct mmc_host *mmc; struct mmc_request *mrq; struct mutex lock; /* lock for this host */ @@ -199,11 +200,12 @@ static int _gb_sdio_process_events(struct gb_sdio_host *host, u8 event) return 0; } -static int gb_sdio_event_recv(u8 type, struct gb_operation *op) +static int gb_sdio_request_handler(struct gb_operation *op) { struct gb_sdio_host *host = gb_connection_get_data(op->connection); struct gb_message *request; struct gb_sdio_event_request *payload; + u8 type = op->type; int ret = 0; u8 event; @@ -706,27 +708,47 @@ static const struct mmc_host_ops gb_sdio_ops = { .get_cd = gb_mmc_get_cd, }; -static int gb_sdio_connection_init(struct gb_connection *connection) +static int gb_sdio_probe(struct gpbridge_device *gpbdev, + const struct gpbridge_device_id *id) { + struct gb_connection *connection; struct mmc_host *mmc; struct gb_sdio_host *host; size_t max_buffer; int ret = 0; - mmc = mmc_alloc_host(sizeof(*host), &connection->bundle->dev); + mmc = mmc_alloc_host(sizeof(*host), &gpbdev->dev); if (!mmc) return -ENOMEM; + connection = gb_connection_create(gpbdev->bundle, + le16_to_cpu(gpbdev->cport_desc->id), + gb_sdio_request_handler); + if (IS_ERR(connection)) { + ret = PTR_ERR(connection); + goto exit_mmc_free; + } + host = mmc_priv(mmc); host->mmc = mmc; host->removed = true; host->connection = connection; gb_connection_set_data(connection, host); + host->gpbdev = gpbdev; + gb_gpbridge_set_data(gpbdev, host); + + ret = gb_connection_enable_tx(connection); + if (ret) + goto exit_connection_destroy; + + ret = gb_gpbridge_get_version(connection); + if (ret) + goto exit_connection_disable; ret = gb_sdio_get_caps(host); if (ret < 0) - goto free_mmc; + goto exit_connection_disable; mmc->ops = &gb_sdio_ops; @@ -740,45 +762,50 @@ static int gb_sdio_connection_init(struct gb_connection *connection) host->xfer_buffer = kzalloc(max_buffer, GFP_KERNEL); if (!host->xfer_buffer) { ret = -ENOMEM; - goto free_mmc; + goto exit_connection_disable; } mutex_init(&host->lock); spin_lock_init(&host->xfer); host->mrq_workqueue = alloc_workqueue("mmc-%s", 0, 1, - dev_name(&connection->bundle->dev)); + dev_name(&gpbdev->dev)); if (!host->mrq_workqueue) { ret = -ENOMEM; - goto free_buffer; + goto exit_buf_free; } INIT_WORK(&host->mrqwork, gb_sdio_mrq_work); + ret = gb_connection_enable(connection); + if (ret) + goto exit_wq_destroy; + ret = mmc_add_host(mmc); if (ret < 0) - goto free_work; + goto exit_wq_destroy; host->removed = false; ret = _gb_sdio_process_events(host, host->queued_events); host->queued_events = 0; return ret; -free_work: +exit_wq_destroy: destroy_workqueue(host->mrq_workqueue); -free_buffer: +exit_buf_free: kfree(host->xfer_buffer); -free_mmc: - gb_connection_set_data(connection, NULL); +exit_connection_disable: + gb_connection_disable(connection); +exit_connection_destroy: + gb_connection_destroy(connection); +exit_mmc_free: mmc_free_host(mmc); return ret; } -static void gb_sdio_connection_exit(struct gb_connection *connection) +static void gb_sdio_remove(struct gpbridge_device *gpbdev) { + struct gb_sdio_host *host = gb_gpbridge_get_data(gpbdev); + struct gb_connection *connection = host->connection; struct mmc_host *mmc; - struct gb_sdio_host *host = gb_connection_get_data(connection); - - if (!host) - return; mutex_lock(&host->lock); host->removed = true; @@ -788,19 +815,23 @@ static void gb_sdio_connection_exit(struct gb_connection *connection) flush_workqueue(host->mrq_workqueue); destroy_workqueue(host->mrq_workqueue); + gb_connection_disable_rx(connection); mmc_remove_host(mmc); + gb_connection_disable(connection); + gb_connection_destroy(connection); kfree(host->xfer_buffer); mmc_free_host(mmc); } -static struct gb_protocol sdio_protocol = { - .name = "sdio", - .id = GREYBUS_PROTOCOL_SDIO, - .major = GB_SDIO_VERSION_MAJOR, - .minor = GB_SDIO_VERSION_MINOR, - .connection_init = gb_sdio_connection_init, - .connection_exit = gb_sdio_connection_exit, - .request_recv = gb_sdio_event_recv, +static const struct gpbridge_device_id gb_sdio_id_table[] = { + { GPBRIDGE_PROTOCOL(GREYBUS_PROTOCOL_SDIO) }, + { }, }; -gb_builtin_protocol_driver(sdio_protocol); +static struct gpbridge_driver sdio_driver = { + .name = "sdio", + .probe = gb_sdio_probe, + .remove = gb_sdio_remove, + .id_table = gb_sdio_id_table, +}; +gb_gpbridge_builtin_driver(sdio_driver);