From 1575ef18aea40ab1f6915917901a80ca780188a6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 7 Oct 2015 15:40:24 -0400 Subject: [PATCH] greybus: svc: skip setting flags for boot over unipro We need to skip setting E2EFC and other flags to the SVC connection create request, for all cports, on an interface that need to boot over unipro, i.e. interfaces required to download firmware. This also adds a FIXME as we need to do it differently for ES3. Tested-by: Eli Sennesh Signed-off-by: Viresh Kumar Signed-off by: Eli Sennesh Signed-off-by: Greg Kroah-Hartman --- drivers/staging/greybus/connection.c | 7 +++++-- drivers/staging/greybus/greybus_protocols.h | 7 +++++++ drivers/staging/greybus/interface.h | 3 +++ drivers/staging/greybus/svc.c | 26 ++++++++++++++++++++++++-- drivers/staging/greybus/svc.h | 2 +- 5 files changed, 40 insertions(+), 5 deletions(-) diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index 05a9b548b64a..6b56b3069fae 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -328,16 +328,19 @@ gb_connection_svc_connection_create(struct gb_connection *connection) { struct greybus_host_device *hd = connection->hd; struct gb_protocol *protocol = connection->protocol; + struct gb_interface *intf; int ret; if (protocol->flags & GB_PROTOCOL_SKIP_SVC_CONNECTION) return 0; + intf = connection->bundle->intf; ret = gb_svc_connection_create(hd->svc, hd->endo->ap_intf_id, connection->hd_cport_id, - connection->bundle->intf->interface_id, - connection->intf_cport_id); + intf->interface_id, + connection->intf_cport_id, + intf->boot_over_unipro); if (ret) { dev_err(&connection->dev, "failed to create svc connection: %d\n", ret); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index 4819cd0e229e..dbf409fa16f3 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -832,6 +832,13 @@ struct gb_svc_dme_peer_set_response { #define DME_ATTR_SELECTOR_INDEX 0 #define DME_ATTR_T_TST_SRC_INCREMENT 0x4083 +/* Return value from TST_SRC_INCREMENT */ +#define DME_TSI_SPI_BOOT_STARTED 0x02 +#define DME_TSI_TRUSTED_SPI_BOOT_FINISHED 0x03 +#define DME_TSI_UNTRUSTED_SPI_BOOT_FINISHED 0x04 +#define DME_TSI_UNIPRO_BOOT_STARTED 0x06 +#define DME_TSI_FALLBACK_UNIPRO_BOOT_STARTED 0x09 + struct gb_svc_route_create_request { __u8 intf1_id; __u8 dev1_id; diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index 42b5d0156cdc..9bce94f680a4 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -36,6 +36,9 @@ struct gb_interface { struct gb_module *module; struct greybus_host_device *hd; + + /* The interface needs to boot over unipro */ + bool boot_over_unipro; }; #define to_gb_interface(d) container_of(d, struct gb_interface, dev) diff --git a/drivers/staging/greybus/svc.c b/drivers/staging/greybus/svc.c index da2ffd655122..4b9eb383652c 100644 --- a/drivers/staging/greybus/svc.c +++ b/drivers/staging/greybus/svc.c @@ -207,6 +207,18 @@ static int gb_svc_read_and_clear_module_boot_status(struct gb_interface *intf) return -ENODEV; } + /* + * Check if the module needs to boot from unipro. + * For ES2: We need to check lowest 8 bits of 'value'. + * For ES3: We need to check highest 8 bits out of 32 of 'value'. + * + * FIXME: Add code to find if we are on ES2 or ES3 to have separate + * checks. + */ + if (value == DME_TSI_UNIPRO_BOOT_STARTED || + value == DME_TSI_FALLBACK_UNIPRO_BOOT_STARTED) + intf->boot_over_unipro = true; + return gb_svc_dme_peer_set(hd->svc, intf->interface_id, DME_ATTR_T_TST_SRC_INCREMENT, DME_ATTR_SELECTOR_INDEX, 0); @@ -214,7 +226,8 @@ static int gb_svc_read_and_clear_module_boot_status(struct gb_interface *intf) int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id) + u8 intf2_id, u16 cport2_id, + bool boot_over_unipro) { struct gb_svc_conn_create_request request; @@ -227,7 +240,16 @@ int gb_svc_connection_create(struct gb_svc *svc, * for now. */ request.tc = 0; - request.flags = CPORT_FLAGS_CSV_N | CPORT_FLAGS_E2EFC; + + /* + * We need to skip setting E2EFC and other flags to the connection + * create request, for all cports, on an interface that need to boot + * over unipro, i.e. interfaces required to download firmware. + */ + if (boot_over_unipro) + request.flags = CPORT_FLAGS_CSV_N | CPORT_FLAGS_CSD_N; + else + request.flags = CPORT_FLAGS_CSV_N | CPORT_FLAGS_E2EFC; return gb_operation_sync(svc->connection, GB_SVC_TYPE_CONN_CREATE, &request, sizeof(request), NULL, 0); diff --git a/drivers/staging/greybus/svc.h b/drivers/staging/greybus/svc.h index 75518f8a199e..3357d317e9d9 100644 --- a/drivers/staging/greybus/svc.h +++ b/drivers/staging/greybus/svc.h @@ -14,7 +14,7 @@ struct gb_svc; int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id); int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, - u8 intf2_id, u16 cport2_id); + u8 intf2_id, u16 cport2_id, bool boot_over_unipro); void gb_svc_connection_destroy(struct gb_svc *svc, u8 intf1_id, u16 cport1_id, u8 intf2_id, u16 cport2_id); int gb_svc_dme_peer_get(struct gb_svc *svc, u8 intf_id, u16 attr, u16 selector, -- 2.11.0