mirror of https://gitee.com/openkylin/linux.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 <gregkh@google.com> Signed-off-by: Vaibhav 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: Viresh Kumar <viresh.kumar@linaro.org> Tested-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
parent
315bea0e96
commit
dcd2086aa8
|
@ -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 @@ static int __init gpbridge_init(void)
|
|||
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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) },
|
||||
{ }
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue