summaryrefslogtreecommitdiffstats
path: root/drivers/staging/greybus/fw-core.c
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2016-05-14 23:42:24 +0530
committerGreg Kroah-Hartman <gregkh@google.com>2016-05-15 00:23:52 +0200
commite2386c9327ab30288f995fc23fb97a3f21b08787 (patch)
treea35628db9974c6461229632268ba5b04dae9a97c /drivers/staging/greybus/fw-core.c
parent96ba6740099b1f1a2732c86204d2931cda11d638 (diff)
downloadop-kernel-dev-e2386c9327ab30288f995fc23fb97a3f21b08787.zip
op-kernel-dev-e2386c9327ab30288f995fc23fb97a3f21b08787.tar.gz
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 <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/fw-core.c')
-rw-r--r--drivers/staging/greybus/fw-core.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/drivers/staging/greybus/fw-core.c b/drivers/staging/greybus/fw-core.c
index 0a456c5..90d3222 100644
--- a/drivers/staging/greybus/fw-core.c
+++ b/drivers/staging/greybus/fw-core.c
@@ -11,10 +11,12 @@
#include <linux/firmware.h>
#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)
{
@@ -85,6 +116,25 @@ static int gb_fw_core_probe(struct gb_bundle *bundle,
}
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",
protocol_id);
@@ -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);
OpenPOWER on IntegriCloud