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