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,