From: Viresh Kumar Date: Sat, 14 May 2016 18:12:24 +0000 (+0530) Subject: greybus: firmware: Add SPI protocol support X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=e2386c9327ab30288f995fc23fb97a3f21b08787;p=linux-beck.git greybus: firmware: Add SPI protocol support This patch adds SPI Protocol support to firmware core, which allows the AP to access an SPI flash memory present with an Interface. Tested by using the API from fw-management driver and compiling it. Signed-off-by: Viresh Kumar Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c index 0a456c547c52..90d32227a490 100644 --- a/drivers/staging/greybus/fw-core.c +++ b/drivers/staging/greybus/fw-core.c @@ -11,10 +11,12 @@ #include #include "firmware.h" #include "greybus.h" +#include "spilib.h" struct gb_fw_core { struct gb_connection *download_connection; struct gb_connection *mgmt_connection; + struct gb_connection *spi_connection; }; struct gb_connection *to_fw_mgmt_connection(struct device *dev) @@ -24,6 +26,35 @@ struct gb_connection *to_fw_mgmt_connection(struct device *dev) return fw_core->mgmt_connection; } +static int gb_fw_spi_connection_init(struct gb_connection *connection) +{ + int ret; + + if (!connection) + return 0; + + ret = gb_connection_enable(connection); + if (ret) + return ret; + + ret = gb_spilib_master_init(connection, &connection->bundle->dev); + if (ret) { + gb_connection_disable(connection); + return ret; + } + + return 0; +} + +static void gb_fw_spi_connection_exit(struct gb_connection *connection) +{ + if (!connection) + return; + + gb_spilib_master_exit(connection); + gb_connection_disable(connection); +} + static int gb_fw_core_probe(struct gb_bundle *bundle, const struct greybus_bundle_id *id) { @@ -84,6 +115,25 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, fw_core->download_connection = connection; } + break; + case GREYBUS_PROTOCOL_SPI: + /* Disallow multiple SPI CPorts */ + if (fw_core->spi_connection) { + dev_err(&bundle->dev, + "multiple SPI CPorts found\n"); + ret = -EINVAL; + goto err_destroy_connections; + } + + connection = gb_connection_create(bundle, cport_id, + NULL); + if (IS_ERR(connection)) { + dev_err(&bundle->dev, "failed to create SPI connection (%ld)\n", + PTR_ERR(connection)); + } else { + fw_core->spi_connection = connection; + } + break; default: dev_err(&bundle->dev, "invalid protocol id (0x%02x)\n", @@ -109,6 +159,15 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, fw_core->download_connection = NULL; } + ret = gb_fw_spi_connection_init(fw_core->spi_connection); + if (ret) { + /* We may still be able to work with the Interface */ + dev_err(&bundle->dev, "failed to initialize SPI connection, disable it (%d)\n", + ret); + gb_connection_destroy(fw_core->spi_connection); + fw_core->spi_connection = NULL; + } + ret = gb_fw_mgmt_connection_init(fw_core->mgmt_connection); if (ret) { /* We may still be able to work with the Interface */ @@ -122,9 +181,11 @@ static int gb_fw_core_probe(struct gb_bundle *bundle, return 0; err_exit_connections: + gb_fw_spi_connection_exit(fw_core->spi_connection); gb_fw_download_connection_exit(fw_core->download_connection); err_destroy_connections: gb_connection_destroy(fw_core->mgmt_connection); + gb_connection_destroy(fw_core->spi_connection); gb_connection_destroy(fw_core->download_connection); err_free_fw_core: kfree(fw_core); @@ -137,9 +198,11 @@ static void gb_fw_core_disconnect(struct gb_bundle *bundle) struct gb_fw_core *fw_core = greybus_get_drvdata(bundle); gb_fw_mgmt_connection_exit(fw_core->mgmt_connection); + gb_fw_spi_connection_exit(fw_core->spi_connection); gb_fw_download_connection_exit(fw_core->download_connection); gb_connection_destroy(fw_core->mgmt_connection); + gb_connection_destroy(fw_core->spi_connection); gb_connection_destroy(fw_core->download_connection); kfree(fw_core);