Commit e2386c93 authored by Viresh Kumar's avatar Viresh Kumar Committed by Greg Kroah-Hartman

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: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 96ba6740
......@@ -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)
{
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment