xref: /rk3399_ARM-atf/plat/st/stm32mp2/stm32mp2_usb_dfu.c (revision c8e1a2d9d27d4f7e3a919b7994e82f2a886f3e6a)
12e905c06SYann Gautier /*
2*6d1366e5SPatrick Delaunay  * Copyright (c) 2024-2025, STMicroelectronics - All Rights Reserved
32e905c06SYann Gautier  *
42e905c06SYann Gautier  * SPDX-License-Identifier: BSD-3-Clause
52e905c06SYann Gautier  */
62e905c06SYann Gautier 
7*6d1366e5SPatrick Delaunay #include <limits.h>
82e905c06SYann Gautier #include <stddef.h>
9*6d1366e5SPatrick Delaunay #include <string.h>
102e905c06SYann Gautier 
11*6d1366e5SPatrick Delaunay #include <common/debug.h>
12*6d1366e5SPatrick Delaunay #include <drivers/st/usb_dwc3.h>
132e905c06SYann Gautier #include <drivers/usb_device.h>
142e905c06SYann Gautier 
15*6d1366e5SPatrick Delaunay #include <platform_def.h>
16*6d1366e5SPatrick Delaunay #include <stm32cubeprogrammer.h>
17*6d1366e5SPatrick Delaunay #include <stm32mp_common.h>
182e905c06SYann Gautier #include <usb_dfu.h>
192e905c06SYann Gautier 
20*6d1366e5SPatrick Delaunay /*  String size (1 byte) + type (1 byte) + 24 UTF16 characters: 2 bytes each */
21*6d1366e5SPatrick Delaunay #define SIZ_STRING_SERIAL U(24)
22*6d1366e5SPatrick Delaunay #define USB_SIZ_STRING_SERIAL (1U + 1U + (SIZ_STRING_SERIAL * 2U))
23*6d1366e5SPatrick Delaunay #define USBD_MAX_STR_DESC_SIZ U(0x100)
24*6d1366e5SPatrick Delaunay #define USBD_VID U(0x0483)
25*6d1366e5SPatrick Delaunay #define USBD_PID U(0xDF11)
26*6d1366e5SPatrick Delaunay #define USBD_LANGID_STRING U(0x409)
27*6d1366e5SPatrick Delaunay #define USBD_MANUFACTURER_STRING "STMicroelectronics"
28*6d1366e5SPatrick Delaunay #define USBD_CONFIGURATION_STRING "DFU Config"
29*6d1366e5SPatrick Delaunay #define USBD_INTERFACE_STRING "DFU Interface"
30*6d1366e5SPatrick Delaunay 
31*6d1366e5SPatrick Delaunay #define USB_DFU_ITF_NUM U(3)
32*6d1366e5SPatrick Delaunay 
33*6d1366e5SPatrick Delaunay #define USB_DFU_CONFIG_DESC_SIZ USB_DFU_DESC_SIZ(USB_DFU_ITF_NUM)
34*6d1366e5SPatrick Delaunay 
35*6d1366e5SPatrick Delaunay /* DFU devices */
36*6d1366e5SPatrick Delaunay static struct usb_dfu_handle usb_dfu_handle;
37*6d1366e5SPatrick Delaunay 
38*6d1366e5SPatrick Delaunay /* USB Standard Device Descriptor */
39*6d1366e5SPatrick Delaunay static const uint8_t usb_stm32mp2_desc[USB_LEN_DEV_DESC] = {
40*6d1366e5SPatrick Delaunay 	USB_LEN_DEV_DESC, /* bLength */
41*6d1366e5SPatrick Delaunay 	USB_DESC_TYPE_DEVICE, /* bDescriptorType */
42*6d1366e5SPatrick Delaunay 	0x00, /* bcdUSB */
43*6d1366e5SPatrick Delaunay 	0x02, /* version */
44*6d1366e5SPatrick Delaunay 	0x00, /* bDeviceClass */
45*6d1366e5SPatrick Delaunay 	0x00, /* bDeviceSubClass */
46*6d1366e5SPatrick Delaunay 	0x00, /* bDeviceProtocol */
47*6d1366e5SPatrick Delaunay 	USB_MAX_EP0_SIZE, /* bMaxPacketSize */
48*6d1366e5SPatrick Delaunay 	LOBYTE(USBD_VID), /* idVendor */
49*6d1366e5SPatrick Delaunay 	HIBYTE(USBD_VID), /* idVendor */
50*6d1366e5SPatrick Delaunay 	LOBYTE(USBD_PID), /* idVendor */
51*6d1366e5SPatrick Delaunay 	HIBYTE(USBD_PID), /* idVendor */
52*6d1366e5SPatrick Delaunay 	0x00, /* bcdDevice rel. 2.00 */
53*6d1366e5SPatrick Delaunay 	0x02,
54*6d1366e5SPatrick Delaunay 	USBD_IDX_MFC_STR, /* Index of manufacturer string */
55*6d1366e5SPatrick Delaunay 	USBD_IDX_PRODUCT_STR, /* Index of product string */
56*6d1366e5SPatrick Delaunay 	USBD_IDX_SERIAL_STR, /* Index of serial number string */
57*6d1366e5SPatrick Delaunay 	USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */
58*6d1366e5SPatrick Delaunay }; /* USB_DeviceDescriptor */
59*6d1366e5SPatrick Delaunay 
60*6d1366e5SPatrick Delaunay /* USB Standard String Descriptor */
61*6d1366e5SPatrick Delaunay static const uint8_t usb_stm32mp2_lang_id_desc[USB_LEN_LANGID_STR_DESC] = {
62*6d1366e5SPatrick Delaunay 	USB_LEN_LANGID_STR_DESC,
63*6d1366e5SPatrick Delaunay 	USB_DESC_TYPE_STRING,
64*6d1366e5SPatrick Delaunay 	LOBYTE(USBD_LANGID_STRING),
65*6d1366e5SPatrick Delaunay 	HIBYTE(USBD_LANGID_STRING),
66*6d1366e5SPatrick Delaunay };
67*6d1366e5SPatrick Delaunay 
68*6d1366e5SPatrick Delaunay /* USB Standard Device Descriptor */
69*6d1366e5SPatrick Delaunay static const uint8_t usbd_stm32mp2_qualifier_desc[USB_LEN_DEV_QUALIFIER_DESC] = {
70*6d1366e5SPatrick Delaunay 	USB_LEN_DEV_QUALIFIER_DESC,
71*6d1366e5SPatrick Delaunay 	USB_DESC_TYPE_DEVICE_QUALIFIER,
72*6d1366e5SPatrick Delaunay 	0x00,
73*6d1366e5SPatrick Delaunay 	0x02,
74*6d1366e5SPatrick Delaunay 	0x00,
75*6d1366e5SPatrick Delaunay 	0x00,
76*6d1366e5SPatrick Delaunay 	0x00,
77*6d1366e5SPatrick Delaunay 	0x40,
78*6d1366e5SPatrick Delaunay 	0x01,
79*6d1366e5SPatrick Delaunay 	0x00,
80*6d1366e5SPatrick Delaunay };
81*6d1366e5SPatrick Delaunay 
82*6d1366e5SPatrick Delaunay /* USB serial number: build dynamically */
83*6d1366e5SPatrick Delaunay static uint8_t usb_stm32mp2_serial[USB_SIZ_STRING_SERIAL + 1];
84*6d1366e5SPatrick Delaunay 
85*6d1366e5SPatrick Delaunay /* USB DFU device Configuration Descriptor */
86*6d1366e5SPatrick Delaunay static const uint8_t usb_stm32mp2_config_desc[USB_DFU_CONFIG_DESC_SIZ] = {
87*6d1366e5SPatrick Delaunay 	0x09, /* bLength: Configuration Descriptor size */
88*6d1366e5SPatrick Delaunay 	USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
89*6d1366e5SPatrick Delaunay 	USB_DFU_CONFIG_DESC_SIZ, /* wTotalLength: Bytes returned */
90*6d1366e5SPatrick Delaunay 	0x00, 0x01, /* bNumInterfaces: 1 interface */
91*6d1366e5SPatrick Delaunay 	0x01, /* bConfigurationValue: Configuration value */
92*6d1366e5SPatrick Delaunay 	0x02, /* iConfiguration: Index of string descriptor for configuration */
93*6d1366e5SPatrick Delaunay 	0xC0, /* bmAttributes: bus powered and Supprts Remote Wakeup */
94*6d1366e5SPatrick Delaunay 	0x32, /* MaxPower 100 mA: this current is used for detecting Vbus */
95*6d1366e5SPatrick Delaunay 
96*6d1366e5SPatrick Delaunay 	/* Descriptor of DFU interface 0 Alternate setting 0..N */
97*6d1366e5SPatrick Delaunay 	USBD_DFU_IF_DESC(0), USBD_DFU_IF_DESC(1), USBD_DFU_IF_DESC(2),
98*6d1366e5SPatrick Delaunay 	/* DFU Functional Descriptor */
99*6d1366e5SPatrick Delaunay 	0x09, /* blength = 9 Bytes */
100*6d1366e5SPatrick Delaunay 	DFU_DESCRIPTOR_TYPE, /* DFU Functional Descriptor */
101*6d1366e5SPatrick Delaunay 	DFU_BM_ATTRIBUTE, /* bmAttribute for DFU */
102*6d1366e5SPatrick Delaunay 	0xFF, /* DetachTimeOut = 255 ms */
103*6d1366e5SPatrick Delaunay 	0x00,
104*6d1366e5SPatrick Delaunay 	/* WARNING: In DMA mode the multiple MPS packets feature
105*6d1366e5SPatrick Delaunay 	 *  is still not supported ==> In this case,
106*6d1366e5SPatrick Delaunay 	 *  when using DMA USBD_DFU_XFER_SIZE should be set
107*6d1366e5SPatrick Delaunay 	 *  to 64 in usbd_conf.h
108*6d1366e5SPatrick Delaunay 	 */
109*6d1366e5SPatrick Delaunay 	TRANSFER_SIZE_BYTES(USBD_DFU_XFER_SIZE), /* TransferSize = 1024 Byte */
110*6d1366e5SPatrick Delaunay 	((USB_DFU_VERSION >> 0) & 0xFF), /* bcdDFUVersion */
111*6d1366e5SPatrick Delaunay 	((USB_DFU_VERSION >> 8) & 0xFF)
112*6d1366e5SPatrick Delaunay };
113*6d1366e5SPatrick Delaunay 
114*6d1366e5SPatrick Delaunay const char *const if_desc_string[USB_DFU_ITF_NUM] = {
115*6d1366e5SPatrick Delaunay 	"@DDR FIP /0x02/1*32Ke", "@FIP /0x03/1*16Me", "@virtual /0xF1/1*512Ba"
116*6d1366e5SPatrick Delaunay };
117*6d1366e5SPatrick Delaunay 
118*6d1366e5SPatrick Delaunay /* Buffer to build the unicode string provided to USB device stack */
119*6d1366e5SPatrick Delaunay static uint8_t usb_str_dec[USBD_MAX_STR_DESC_SIZ];
120*6d1366e5SPatrick Delaunay 
121*6d1366e5SPatrick Delaunay /*
122*6d1366e5SPatrick Delaunay  * Convert Ascii string into unicode one
123*6d1366e5SPatrick Delaunay  * desc : descriptor buffer
124*6d1366e5SPatrick Delaunay  * unicode : Formatted string buffer (unicode)
125*6d1366e5SPatrick Delaunay  * len : descriptor length
126*6d1366e5SPatrick Delaunay  */
stm32mp2_get_string(const char * desc,uint8_t * unicode,uint16_t * len)127*6d1366e5SPatrick Delaunay static void stm32mp2_get_string(const char *desc, uint8_t *unicode,
128*6d1366e5SPatrick Delaunay 				uint16_t *len)
1292e905c06SYann Gautier {
130*6d1366e5SPatrick Delaunay 	uint8_t idx = 0U;
131*6d1366e5SPatrick Delaunay 
132*6d1366e5SPatrick Delaunay 	if (desc == NULL) {
133*6d1366e5SPatrick Delaunay 		return;
134*6d1366e5SPatrick Delaunay 	}
135*6d1366e5SPatrick Delaunay 
136*6d1366e5SPatrick Delaunay 	*len = strlen(desc) * 2U + 2U;
137*6d1366e5SPatrick Delaunay 	unicode[idx++] = *len;
138*6d1366e5SPatrick Delaunay 	unicode[idx++] = USB_DESC_TYPE_STRING;
139*6d1366e5SPatrick Delaunay 
140*6d1366e5SPatrick Delaunay 	while (*desc != '\0') {
141*6d1366e5SPatrick Delaunay 		unicode[idx++] = *desc++;
142*6d1366e5SPatrick Delaunay 		unicode[idx++] = 0x00U;
143*6d1366e5SPatrick Delaunay 	}
144*6d1366e5SPatrick Delaunay }
145*6d1366e5SPatrick Delaunay 
146*6d1366e5SPatrick Delaunay /*
147*6d1366e5SPatrick Delaunay  * Create the serial number string descriptor
148*6d1366e5SPatrick Delaunay  */
update_serial_num_string(void)149*6d1366e5SPatrick Delaunay static void update_serial_num_string(void)
150*6d1366e5SPatrick Delaunay {
151*6d1366e5SPatrick Delaunay 	char serial_string[SIZ_STRING_SERIAL + 2U];
152*6d1366e5SPatrick Delaunay 	/* serial number is set to 0 */
153*6d1366e5SPatrick Delaunay 	uint32_t deviceserial[UID_WORD_NB] = { 0U, 0U, 0U };
154*6d1366e5SPatrick Delaunay 	uint16_t length;
155*6d1366e5SPatrick Delaunay 
156*6d1366e5SPatrick Delaunay 	if (stm32_get_uid_otp(deviceserial) != 0) {
157*6d1366e5SPatrick Delaunay 		return;
158*6d1366e5SPatrick Delaunay 	}
159*6d1366e5SPatrick Delaunay 
160*6d1366e5SPatrick Delaunay 	/* build serial number with OTP value as in ROM code */
161*6d1366e5SPatrick Delaunay 	snprintf(serial_string, sizeof(serial_string), "%08X%08X%08X",
162*6d1366e5SPatrick Delaunay 		 deviceserial[0], deviceserial[1], deviceserial[2]);
163*6d1366e5SPatrick Delaunay 
164*6d1366e5SPatrick Delaunay 	length = USB_SIZ_STRING_SERIAL;
165*6d1366e5SPatrick Delaunay 	stm32mp2_get_string(serial_string, usb_stm32mp2_serial, &length);
166*6d1366e5SPatrick Delaunay }
167*6d1366e5SPatrick Delaunay 
168*6d1366e5SPatrick Delaunay /*
169*6d1366e5SPatrick Delaunay  * Return Device Qualifier descriptor
170*6d1366e5SPatrick Delaunay  * length : pointer data length
171*6d1366e5SPatrick Delaunay  * return : pointer to descriptor buffer
172*6d1366e5SPatrick Delaunay  */
stm32mp2_get_qualifier_desc(uint16_t * length)173*6d1366e5SPatrick Delaunay static uint8_t *stm32mp2_get_qualifier_desc(uint16_t *length)
174*6d1366e5SPatrick Delaunay {
175*6d1366e5SPatrick Delaunay 	*length = sizeof(usbd_stm32mp2_qualifier_desc);
176*6d1366e5SPatrick Delaunay 
177*6d1366e5SPatrick Delaunay 	return (uint8_t *)usbd_stm32mp2_qualifier_desc;
178*6d1366e5SPatrick Delaunay }
179*6d1366e5SPatrick Delaunay 
180*6d1366e5SPatrick Delaunay /*
181*6d1366e5SPatrick Delaunay  * Return configuration descriptor
182*6d1366e5SPatrick Delaunay  * length : pointer data length
183*6d1366e5SPatrick Delaunay  * return : pointer to descriptor buffer
184*6d1366e5SPatrick Delaunay  */
stm32mp2_get_config_desc(uint16_t * length)185*6d1366e5SPatrick Delaunay static uint8_t *stm32mp2_get_config_desc(uint16_t *length)
186*6d1366e5SPatrick Delaunay {
187*6d1366e5SPatrick Delaunay 	*length = sizeof(usb_stm32mp2_config_desc);
188*6d1366e5SPatrick Delaunay 
189*6d1366e5SPatrick Delaunay 	return (uint8_t *)usb_stm32mp2_config_desc;
190*6d1366e5SPatrick Delaunay }
191*6d1366e5SPatrick Delaunay 
192*6d1366e5SPatrick Delaunay /*
193*6d1366e5SPatrick Delaunay  * Returns the device descriptor.
194*6d1366e5SPatrick Delaunay  * length: Pointer to data length variable
195*6d1366e5SPatrick Delaunay  * return : Pointer to descriptor buffer
196*6d1366e5SPatrick Delaunay  */
stm32mp2_device_desc(uint16_t * length)197*6d1366e5SPatrick Delaunay static uint8_t *stm32mp2_device_desc(uint16_t *length)
198*6d1366e5SPatrick Delaunay {
199*6d1366e5SPatrick Delaunay 	*length = sizeof(usb_stm32mp2_desc);
200*6d1366e5SPatrick Delaunay 
201*6d1366e5SPatrick Delaunay 	return (uint8_t *)usb_stm32mp2_desc;
202*6d1366e5SPatrick Delaunay }
203*6d1366e5SPatrick Delaunay 
204*6d1366e5SPatrick Delaunay /*
205*6d1366e5SPatrick Delaunay  * Returns the LangID string descriptor.
206*6d1366e5SPatrick Delaunay  * length: Pointer to data length variable
207*6d1366e5SPatrick Delaunay  * return : Pointer to descriptor buffer
208*6d1366e5SPatrick Delaunay  */
stm32mp2_lang_id_desc(uint16_t * length)209*6d1366e5SPatrick Delaunay static uint8_t *stm32mp2_lang_id_desc(uint16_t *length)
210*6d1366e5SPatrick Delaunay {
211*6d1366e5SPatrick Delaunay 	*length = sizeof(usb_stm32mp2_lang_id_desc);
212*6d1366e5SPatrick Delaunay 
213*6d1366e5SPatrick Delaunay 	return (uint8_t *)usb_stm32mp2_lang_id_desc;
214*6d1366e5SPatrick Delaunay }
215*6d1366e5SPatrick Delaunay 
216*6d1366e5SPatrick Delaunay /*
217*6d1366e5SPatrick Delaunay  *  Returns the product string descriptor.
218*6d1366e5SPatrick Delaunay  * length: Pointer to data length variable
219*6d1366e5SPatrick Delaunay  * return : Pointer to descriptor buffer
220*6d1366e5SPatrick Delaunay  */
stm32mp2_product_desc(uint16_t * length)221*6d1366e5SPatrick Delaunay static uint8_t *stm32mp2_product_desc(uint16_t *length)
222*6d1366e5SPatrick Delaunay {
223*6d1366e5SPatrick Delaunay 	char name[STM32_SOC_NAME_SIZE];
224*6d1366e5SPatrick Delaunay 	char product[128];
225*6d1366e5SPatrick Delaunay 	uint32_t chip_id;
226*6d1366e5SPatrick Delaunay 	uint32_t chip_version;
227*6d1366e5SPatrick Delaunay 
228*6d1366e5SPatrick Delaunay 	stm32mp_get_soc_name(name);
229*6d1366e5SPatrick Delaunay 	chip_id = stm32mp_get_chip_dev_id();
230*6d1366e5SPatrick Delaunay 	chip_version = stm32mp_get_chip_version();
231*6d1366e5SPatrick Delaunay 
232*6d1366e5SPatrick Delaunay 	snprintf(product, sizeof(product),
233*6d1366e5SPatrick Delaunay 		 "DFU @Device ID /0x%03X, @Revision ID /0x%04X, @Name /%s,",
234*6d1366e5SPatrick Delaunay 		 chip_id, chip_version, name);
235*6d1366e5SPatrick Delaunay 
236*6d1366e5SPatrick Delaunay 	stm32mp2_get_string(product, usb_str_dec, length);
237*6d1366e5SPatrick Delaunay 
238*6d1366e5SPatrick Delaunay 	return usb_str_dec;
239*6d1366e5SPatrick Delaunay }
240*6d1366e5SPatrick Delaunay 
241*6d1366e5SPatrick Delaunay /*
242*6d1366e5SPatrick Delaunay  * Returns the manufacturer string descriptor.
243*6d1366e5SPatrick Delaunay  * length: Pointer to data length variable
244*6d1366e5SPatrick Delaunay  * return : Pointer to descriptor buffer
245*6d1366e5SPatrick Delaunay  */
stm32mp2_manufacturer_desc(uint16_t * length)246*6d1366e5SPatrick Delaunay static uint8_t *stm32mp2_manufacturer_desc(uint16_t *length)
247*6d1366e5SPatrick Delaunay {
248*6d1366e5SPatrick Delaunay 	stm32mp2_get_string(USBD_MANUFACTURER_STRING, usb_str_dec, length);
249*6d1366e5SPatrick Delaunay 
250*6d1366e5SPatrick Delaunay 	return usb_str_dec;
251*6d1366e5SPatrick Delaunay }
252*6d1366e5SPatrick Delaunay 
253*6d1366e5SPatrick Delaunay /*
254*6d1366e5SPatrick Delaunay  * Returns the serial number string descriptor.
255*6d1366e5SPatrick Delaunay  * length: Pointer to data length variable
256*6d1366e5SPatrick Delaunay  * return : Pointer to descriptor buffer
257*6d1366e5SPatrick Delaunay  */
stm32mp2_serial_desc(uint16_t * length)258*6d1366e5SPatrick Delaunay static uint8_t *stm32mp2_serial_desc(uint16_t *length)
259*6d1366e5SPatrick Delaunay {
260*6d1366e5SPatrick Delaunay 	*length = USB_SIZ_STRING_SERIAL;
261*6d1366e5SPatrick Delaunay 
262*6d1366e5SPatrick Delaunay 	return (uint8_t *)usb_stm32mp2_serial;
263*6d1366e5SPatrick Delaunay }
264*6d1366e5SPatrick Delaunay 
265*6d1366e5SPatrick Delaunay /*
266*6d1366e5SPatrick Delaunay  * Returns the configuration string descriptor.
267*6d1366e5SPatrick Delaunay  * length: Pointer to data length variable
268*6d1366e5SPatrick Delaunay  * return : Pointer to descriptor buffer
269*6d1366e5SPatrick Delaunay  */
stm32mp2_config_desc(uint16_t * length)270*6d1366e5SPatrick Delaunay static uint8_t *stm32mp2_config_desc(uint16_t *length)
271*6d1366e5SPatrick Delaunay {
272*6d1366e5SPatrick Delaunay 	stm32mp2_get_string(USBD_CONFIGURATION_STRING, usb_str_dec, length);
273*6d1366e5SPatrick Delaunay 
274*6d1366e5SPatrick Delaunay 	return usb_str_dec;
275*6d1366e5SPatrick Delaunay }
276*6d1366e5SPatrick Delaunay 
277*6d1366e5SPatrick Delaunay /*
278*6d1366e5SPatrick Delaunay  * Returns the interface string descriptor.
279*6d1366e5SPatrick Delaunay  * length : Pointer to data length variable
280*6d1366e5SPatrick Delaunay  * return : Pointer to descriptor buffer
281*6d1366e5SPatrick Delaunay  */
stm32mp2_interface_desc(uint16_t * length)282*6d1366e5SPatrick Delaunay static uint8_t *stm32mp2_interface_desc(uint16_t *length)
283*6d1366e5SPatrick Delaunay {
284*6d1366e5SPatrick Delaunay 	stm32mp2_get_string(USBD_INTERFACE_STRING, usb_str_dec, length);
285*6d1366e5SPatrick Delaunay 
286*6d1366e5SPatrick Delaunay 	return usb_str_dec;
287*6d1366e5SPatrick Delaunay }
288*6d1366e5SPatrick Delaunay 
289*6d1366e5SPatrick Delaunay /*
290*6d1366e5SPatrick Delaunay  * Manages the transfer of memory interfaces string descriptors.
291*6d1366e5SPatrick Delaunay  * index: descriptor index
292*6d1366e5SPatrick Delaunay  * length : pointer data length
293*6d1366e5SPatrick Delaunay  * return : pointer to the descriptor table or NULL if the descriptor
294*6d1366e5SPatrick Delaunay  *          is not supported.
295*6d1366e5SPatrick Delaunay  */
stm32mp2_get_usr_desc(uint8_t index,uint16_t * length)296*6d1366e5SPatrick Delaunay static uint8_t *stm32mp2_get_usr_desc(uint8_t index, uint16_t *length)
297*6d1366e5SPatrick Delaunay {
298*6d1366e5SPatrick Delaunay 	if (index >= ARRAY_SIZE(if_desc_string)) {
2992e905c06SYann Gautier 		return NULL;
3002e905c06SYann Gautier 	}
3012e905c06SYann Gautier 
302*6d1366e5SPatrick Delaunay 	stm32mp2_get_string(if_desc_string[index], usb_str_dec, length);
303*6d1366e5SPatrick Delaunay 
304*6d1366e5SPatrick Delaunay 	return usb_str_dec;
305*6d1366e5SPatrick Delaunay }
306*6d1366e5SPatrick Delaunay 
307*6d1366e5SPatrick Delaunay static const struct usb_desc dfu_desc = {
308*6d1366e5SPatrick Delaunay 	.get_device_desc = stm32mp2_device_desc,
309*6d1366e5SPatrick Delaunay 	.get_lang_id_desc = stm32mp2_lang_id_desc,
310*6d1366e5SPatrick Delaunay 	.get_manufacturer_desc = stm32mp2_manufacturer_desc,
311*6d1366e5SPatrick Delaunay 	.get_product_desc = stm32mp2_product_desc,
312*6d1366e5SPatrick Delaunay 	.get_configuration_desc = stm32mp2_config_desc,
313*6d1366e5SPatrick Delaunay 	.get_serial_desc = stm32mp2_serial_desc,
314*6d1366e5SPatrick Delaunay 	.get_interface_desc = stm32mp2_interface_desc,
315*6d1366e5SPatrick Delaunay 	.get_usr_desc = stm32mp2_get_usr_desc,
316*6d1366e5SPatrick Delaunay 	.get_config_desc = stm32mp2_get_config_desc,
317*6d1366e5SPatrick Delaunay 	.get_device_qualifier_desc = stm32mp2_get_qualifier_desc,
318*6d1366e5SPatrick Delaunay 	/* only HS is supported, as ROM code */
319*6d1366e5SPatrick Delaunay 	.get_other_speed_config_desc = NULL,
320*6d1366e5SPatrick Delaunay };
321*6d1366e5SPatrick Delaunay 
322*6d1366e5SPatrick Delaunay static struct usb_handle usb_core_handle;
323*6d1366e5SPatrick Delaunay static struct pcd_handle pcd_handle;
324*6d1366e5SPatrick Delaunay static dwc3_handle_t dwc3_handle;
325*6d1366e5SPatrick Delaunay 
usb_dfu_plat_init(void)326*6d1366e5SPatrick Delaunay struct usb_handle *usb_dfu_plat_init(void)
327*6d1366e5SPatrick Delaunay {
328*6d1366e5SPatrick Delaunay 	/* prepare USB Driver */
329*6d1366e5SPatrick Delaunay 	pcd_handle.in_ep[0].maxpacket = USB_MAX_EP0_SIZE;
330*6d1366e5SPatrick Delaunay 	pcd_handle.out_ep[0].maxpacket = USB_MAX_EP0_SIZE;
331*6d1366e5SPatrick Delaunay 	usb_dwc3_init_driver(&usb_core_handle, &pcd_handle, &dwc3_handle,
332*6d1366e5SPatrick Delaunay 			     (void *)USB_DWC3_BASE);
333*6d1366e5SPatrick Delaunay 
334*6d1366e5SPatrick Delaunay 	/* keep the configuration from ROM code */
335*6d1366e5SPatrick Delaunay 	usb_core_handle.ep0_state = USBD_EP0_DATA_IN;
336*6d1366e5SPatrick Delaunay 	usb_core_handle.dev_state = USBD_STATE_CONFIGURED;
337*6d1366e5SPatrick Delaunay 
338*6d1366e5SPatrick Delaunay 	/* Update the serial number string descriptor from the unique ID */
339*6d1366e5SPatrick Delaunay 	update_serial_num_string();
340*6d1366e5SPatrick Delaunay 
341*6d1366e5SPatrick Delaunay 	/* Prepare USB DFU stack */
342*6d1366e5SPatrick Delaunay 	usb_dfu_register(&usb_core_handle, &usb_dfu_handle);
343*6d1366e5SPatrick Delaunay 
344*6d1366e5SPatrick Delaunay 	/* Register DFU descriptor in USB stack */
345*6d1366e5SPatrick Delaunay 	register_platform(&usb_core_handle, &dfu_desc);
346*6d1366e5SPatrick Delaunay 
347*6d1366e5SPatrick Delaunay 	return &usb_core_handle;
348*6d1366e5SPatrick Delaunay }
349*6d1366e5SPatrick Delaunay 
350*6d1366e5SPatrick Delaunay /* Link between USB alternate and STM32CubeProgramer phase */
usb_dfu_get_phase(uint8_t alt)3512e905c06SYann Gautier uint8_t usb_dfu_get_phase(uint8_t alt)
3522e905c06SYann Gautier {
353*6d1366e5SPatrick Delaunay 	uint8_t ret;
354*6d1366e5SPatrick Delaunay 
355*6d1366e5SPatrick Delaunay 	switch (alt) {
356*6d1366e5SPatrick Delaunay 	case 0:
357*6d1366e5SPatrick Delaunay 		ret = PHASE_DDR_FW;
358*6d1366e5SPatrick Delaunay 		break;
359*6d1366e5SPatrick Delaunay 	case 1:
360*6d1366e5SPatrick Delaunay 		ret = PHASE_SSBL;
361*6d1366e5SPatrick Delaunay 		break;
362*6d1366e5SPatrick Delaunay 	case 2:
363*6d1366e5SPatrick Delaunay 		ret = PHASE_CMD;
364*6d1366e5SPatrick Delaunay 		break;
365*6d1366e5SPatrick Delaunay 	default:
366*6d1366e5SPatrick Delaunay 		ret = PHASE_RESET;
367*6d1366e5SPatrick Delaunay 		break;
368*6d1366e5SPatrick Delaunay 	}
369*6d1366e5SPatrick Delaunay 
370*6d1366e5SPatrick Delaunay 	return ret;
3712e905c06SYann Gautier }
372