xref: /arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_uart.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2021-2023, STMicroelectronics - All Rights Reserved
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu #include <endian.h>
9*91f16700Schasinglulu #include <errno.h>
10*91f16700Schasinglulu #include <string.h>
11*91f16700Schasinglulu 
12*91f16700Schasinglulu #include <arch_helpers.h>
13*91f16700Schasinglulu #include <common/debug.h>
14*91f16700Schasinglulu #include <drivers/delay_timer.h>
15*91f16700Schasinglulu #include <drivers/st/stm32_iwdg.h>
16*91f16700Schasinglulu #include <drivers/st/stm32_uart.h>
17*91f16700Schasinglulu #include <drivers/st/stm32_uart_regs.h>
18*91f16700Schasinglulu #include <lib/mmio.h>
19*91f16700Schasinglulu #include <tools_share/firmware_image_package.h>
20*91f16700Schasinglulu 
21*91f16700Schasinglulu #include <platform_def.h>
22*91f16700Schasinglulu #include <stm32cubeprogrammer.h>
23*91f16700Schasinglulu 
24*91f16700Schasinglulu /* USART bootloader protocol version V4.0 */
25*91f16700Schasinglulu #define USART_BL_VERSION	0x40U
26*91f16700Schasinglulu 
27*91f16700Schasinglulu /* Command definition */
28*91f16700Schasinglulu #define GET_CMD_COMMAND		0x00U
29*91f16700Schasinglulu #define GET_VER_COMMAND		0x01U
30*91f16700Schasinglulu #define GET_ID_COMMAND		0x02U
31*91f16700Schasinglulu #define PHASE_COMMAND		0x03U
32*91f16700Schasinglulu #define READ_PART_COMMAND	0x12U
33*91f16700Schasinglulu #define START_COMMAND		0x21U
34*91f16700Schasinglulu #define DOWNLOAD_COMMAND	0x31U
35*91f16700Schasinglulu 
36*91f16700Schasinglulu /* Answer defines */
37*91f16700Schasinglulu #define INIT_BYTE		0x7FU
38*91f16700Schasinglulu #define ACK_BYTE		0x79U
39*91f16700Schasinglulu #define NACK_BYTE		0x1FU
40*91f16700Schasinglulu #define ABORT			0x5FU
41*91f16700Schasinglulu 
42*91f16700Schasinglulu #define UNDEFINED_DOWN_ADDR	U(0xFFFFFFFF)
43*91f16700Schasinglulu #define PROGRAMMER_TIMEOUT_US	20000U
44*91f16700Schasinglulu 
45*91f16700Schasinglulu static const uint8_t command_tab[] = {
46*91f16700Schasinglulu 	GET_CMD_COMMAND,
47*91f16700Schasinglulu 	GET_VER_COMMAND,
48*91f16700Schasinglulu 	GET_ID_COMMAND,
49*91f16700Schasinglulu 	PHASE_COMMAND,
50*91f16700Schasinglulu 	START_COMMAND,
51*91f16700Schasinglulu 	DOWNLOAD_COMMAND
52*91f16700Schasinglulu };
53*91f16700Schasinglulu 
54*91f16700Schasinglulu /* STM32CubeProgrammer over UART handle */
55*91f16700Schasinglulu struct stm32prog_uart_handle_s {
56*91f16700Schasinglulu 	struct stm32_uart_handle_s uart;
57*91f16700Schasinglulu 	uint32_t packet;
58*91f16700Schasinglulu 	uint8_t *addr;
59*91f16700Schasinglulu 	uint32_t len;
60*91f16700Schasinglulu 	uint8_t phase;
61*91f16700Schasinglulu 	/* Error msg buffer: max 255 in UART protocol, reduced in TF-A */
62*91f16700Schasinglulu 	uint8_t error[64];
63*91f16700Schasinglulu } handle;
64*91f16700Schasinglulu 
65*91f16700Schasinglulu /* Trace and handle unrecoverable UART protocol error */
66*91f16700Schasinglulu #define STM32PROG_ERROR(...) \
67*91f16700Schasinglulu 	{ \
68*91f16700Schasinglulu 		ERROR(__VA_ARGS__); \
69*91f16700Schasinglulu 		if (handle.phase != PHASE_RESET) { \
70*91f16700Schasinglulu 			snprintf((char *)&handle.error, sizeof(handle.error), __VA_ARGS__); \
71*91f16700Schasinglulu 			handle.phase = PHASE_RESET; \
72*91f16700Schasinglulu 			handle.addr = (uint8_t *)UNDEFINED_DOWN_ADDR; \
73*91f16700Schasinglulu 			handle.len = 0U; \
74*91f16700Schasinglulu 			handle.packet = 0U; \
75*91f16700Schasinglulu 		} \
76*91f16700Schasinglulu 	}
77*91f16700Schasinglulu 
78*91f16700Schasinglulu static int uart_write(const uint8_t *addr, uint16_t size)
79*91f16700Schasinglulu {
80*91f16700Schasinglulu 	while (size != 0U) {
81*91f16700Schasinglulu 		if (stm32_uart_putc(&handle.uart, *addr) != 0) {
82*91f16700Schasinglulu 			return -EIO;
83*91f16700Schasinglulu 		}
84*91f16700Schasinglulu 		size--;
85*91f16700Schasinglulu 		addr++;
86*91f16700Schasinglulu 	}
87*91f16700Schasinglulu 
88*91f16700Schasinglulu 	return 0;
89*91f16700Schasinglulu }
90*91f16700Schasinglulu 
91*91f16700Schasinglulu static int uart_write_8(uint8_t byte)
92*91f16700Schasinglulu {
93*91f16700Schasinglulu 	return stm32_uart_putc(&handle.uart, byte);
94*91f16700Schasinglulu }
95*91f16700Schasinglulu 
96*91f16700Schasinglulu static int uart_write_32(uint32_t value)
97*91f16700Schasinglulu {
98*91f16700Schasinglulu 	return uart_write((uint8_t *)&value, 4U);
99*91f16700Schasinglulu }
100*91f16700Schasinglulu 
101*91f16700Schasinglulu static int uart_read_8(uint8_t *byte)
102*91f16700Schasinglulu {
103*91f16700Schasinglulu 	int ret;
104*91f16700Schasinglulu 	uint64_t timeout_ref = timeout_init_us(PROGRAMMER_TIMEOUT_US);
105*91f16700Schasinglulu 
106*91f16700Schasinglulu 	do {
107*91f16700Schasinglulu 		ret = stm32_uart_getc(&handle.uart);
108*91f16700Schasinglulu 		if (ret == -EAGAIN) {
109*91f16700Schasinglulu 			if (timeout_elapsed(timeout_ref)) {
110*91f16700Schasinglulu 				return -ETIMEDOUT;
111*91f16700Schasinglulu 			}
112*91f16700Schasinglulu 		} else if (ret < 0) {
113*91f16700Schasinglulu 			return ret;
114*91f16700Schasinglulu 		}
115*91f16700Schasinglulu 	} while (ret == -EAGAIN);
116*91f16700Schasinglulu 
117*91f16700Schasinglulu 	*byte = (uint8_t)ret;
118*91f16700Schasinglulu 
119*91f16700Schasinglulu 	return 0;
120*91f16700Schasinglulu }
121*91f16700Schasinglulu 
122*91f16700Schasinglulu static int uart_send_result(uint8_t byte)
123*91f16700Schasinglulu {
124*91f16700Schasinglulu 	int ret;
125*91f16700Schasinglulu 
126*91f16700Schasinglulu 	/* Always flush fifo before to send result = read all pending data */
127*91f16700Schasinglulu 	do {
128*91f16700Schasinglulu 		ret = stm32_uart_getc(&handle.uart);
129*91f16700Schasinglulu 	} while (ret >= 0);
130*91f16700Schasinglulu 
131*91f16700Schasinglulu 	return uart_write_8(byte);
132*91f16700Schasinglulu }
133*91f16700Schasinglulu 
134*91f16700Schasinglulu static bool is_valid_header(fip_toc_header_t *header)
135*91f16700Schasinglulu {
136*91f16700Schasinglulu 	return (header->name == TOC_HEADER_NAME) &&
137*91f16700Schasinglulu 	       (header->serial_number != 0U);
138*91f16700Schasinglulu }
139*91f16700Schasinglulu 
140*91f16700Schasinglulu static int uart_receive_command(uint8_t *command)
141*91f16700Schasinglulu {
142*91f16700Schasinglulu 	uint8_t byte = 0U;
143*91f16700Schasinglulu 	uint8_t xor = 0U;
144*91f16700Schasinglulu 	unsigned int count;
145*91f16700Schasinglulu 	bool found = false;
146*91f16700Schasinglulu 	int ret;
147*91f16700Schasinglulu 
148*91f16700Schasinglulu 	/* Repeat read until something is received */
149*91f16700Schasinglulu 	do {
150*91f16700Schasinglulu 		stm32_iwdg_refresh();
151*91f16700Schasinglulu 		ret = uart_read_8(&byte);
152*91f16700Schasinglulu 	} while (ret == -ETIMEDOUT);
153*91f16700Schasinglulu 
154*91f16700Schasinglulu 	if (ret != 0) {
155*91f16700Schasinglulu 		return ret;
156*91f16700Schasinglulu 	}
157*91f16700Schasinglulu 
158*91f16700Schasinglulu 	/* Handle reconnection request */
159*91f16700Schasinglulu 	if (byte == INIT_BYTE) {
160*91f16700Schasinglulu 		*command = byte;
161*91f16700Schasinglulu 		return 0;
162*91f16700Schasinglulu 	}
163*91f16700Schasinglulu 
164*91f16700Schasinglulu 	for (count = 0U; count < ARRAY_SIZE(command_tab); count++) {
165*91f16700Schasinglulu 		if (command_tab[count] == byte) {
166*91f16700Schasinglulu 			found = true;
167*91f16700Schasinglulu 			break;
168*91f16700Schasinglulu 		}
169*91f16700Schasinglulu 	}
170*91f16700Schasinglulu 	if (!found) {
171*91f16700Schasinglulu 		VERBOSE("UART: Command unknown (byte=0x%x)\n", byte);
172*91f16700Schasinglulu 		return -EPROTO;
173*91f16700Schasinglulu 	}
174*91f16700Schasinglulu 
175*91f16700Schasinglulu 	ret = uart_read_8(&xor);
176*91f16700Schasinglulu 	if (ret != 0) {
177*91f16700Schasinglulu 		return ret;
178*91f16700Schasinglulu 	}
179*91f16700Schasinglulu 	if ((byte ^ xor) != 0xFF) {
180*91f16700Schasinglulu 		VERBOSE("UART: Command XOR check fail (byte=0x%x, xor=0x%x)\n",
181*91f16700Schasinglulu 			byte, xor);
182*91f16700Schasinglulu 		return -EPROTO;
183*91f16700Schasinglulu 	}
184*91f16700Schasinglulu 
185*91f16700Schasinglulu 	*command = byte;
186*91f16700Schasinglulu 
187*91f16700Schasinglulu 	return 0;
188*91f16700Schasinglulu }
189*91f16700Schasinglulu 
190*91f16700Schasinglulu static int get_cmd_command(void)
191*91f16700Schasinglulu {
192*91f16700Schasinglulu 	const uint8_t msg[2] = {
193*91f16700Schasinglulu 		sizeof(command_tab), /* Length of data - 1 */
194*91f16700Schasinglulu 		USART_BL_VERSION
195*91f16700Schasinglulu 	};
196*91f16700Schasinglulu 	int ret;
197*91f16700Schasinglulu 
198*91f16700Schasinglulu 	ret = uart_write(msg, sizeof(msg));
199*91f16700Schasinglulu 	if (ret != 0) {
200*91f16700Schasinglulu 		return ret;
201*91f16700Schasinglulu 	}
202*91f16700Schasinglulu 
203*91f16700Schasinglulu 	return uart_write(command_tab, sizeof(command_tab));
204*91f16700Schasinglulu }
205*91f16700Schasinglulu 
206*91f16700Schasinglulu static int get_version_command(void)
207*91f16700Schasinglulu {
208*91f16700Schasinglulu 	return uart_write_8(STM32_TF_VERSION);
209*91f16700Schasinglulu }
210*91f16700Schasinglulu 
211*91f16700Schasinglulu static int get_id_command(void)
212*91f16700Schasinglulu {
213*91f16700Schasinglulu 	uint8_t msg[3] = {
214*91f16700Schasinglulu 		sizeof(msg) - 1 /* Length of data - 1 */
215*91f16700Schasinglulu 	};
216*91f16700Schasinglulu 	uint32_t chip_id = stm32mp_get_chip_dev_id();
217*91f16700Schasinglulu 
218*91f16700Schasinglulu 	be16enc(&msg[1], chip_id);
219*91f16700Schasinglulu 
220*91f16700Schasinglulu 	return uart_write(msg, sizeof(msg));
221*91f16700Schasinglulu }
222*91f16700Schasinglulu 
223*91f16700Schasinglulu static int uart_send_phase(uint32_t address)
224*91f16700Schasinglulu {
225*91f16700Schasinglulu 	int ret;
226*91f16700Schasinglulu 	uint8_t msg_size = 5U; /* Length of data - 1 */
227*91f16700Schasinglulu 	uint8_t error_size = 0U;
228*91f16700Schasinglulu 
229*91f16700Schasinglulu 	/* Additional information only for RESET phase */
230*91f16700Schasinglulu 	if (handle.phase == PHASE_RESET) {
231*91f16700Schasinglulu 		error_size = strnlen((char *)&handle.error, sizeof(handle.error));
232*91f16700Schasinglulu 	}
233*91f16700Schasinglulu 	ret = uart_write_8(msg_size + error_size);
234*91f16700Schasinglulu 	if (ret != 0) {
235*91f16700Schasinglulu 		return ret;
236*91f16700Schasinglulu 	}
237*91f16700Schasinglulu 
238*91f16700Schasinglulu 	/* Send the ID of next partition */
239*91f16700Schasinglulu 	ret = uart_write_8(handle.phase);
240*91f16700Schasinglulu 	if (ret != 0) {
241*91f16700Schasinglulu 		return ret;
242*91f16700Schasinglulu 	}
243*91f16700Schasinglulu 
244*91f16700Schasinglulu 	/* Destination address */
245*91f16700Schasinglulu 	ret = uart_write_32(address);
246*91f16700Schasinglulu 	if (ret != 0) {
247*91f16700Schasinglulu 		return ret;
248*91f16700Schasinglulu 	}
249*91f16700Schasinglulu 
250*91f16700Schasinglulu 	ret = uart_write_8(error_size);
251*91f16700Schasinglulu 	if (ret != 0) {
252*91f16700Schasinglulu 		return ret;
253*91f16700Schasinglulu 	}
254*91f16700Schasinglulu 
255*91f16700Schasinglulu 	/* Additional information: message error */
256*91f16700Schasinglulu 	if (error_size > 0U) {
257*91f16700Schasinglulu 		ret = uart_write(handle.error, error_size);
258*91f16700Schasinglulu 	}
259*91f16700Schasinglulu 
260*91f16700Schasinglulu 	return ret;
261*91f16700Schasinglulu }
262*91f16700Schasinglulu 
263*91f16700Schasinglulu static int uart_download_part(void)
264*91f16700Schasinglulu {
265*91f16700Schasinglulu 	uint8_t operation = 0U;
266*91f16700Schasinglulu 	uint8_t xor;
267*91f16700Schasinglulu 	uint8_t byte = 0U;
268*91f16700Schasinglulu 	uint32_t packet_number = 0U;
269*91f16700Schasinglulu 	uint32_t packet_size = 0U;
270*91f16700Schasinglulu 	uint32_t i = 0U;
271*91f16700Schasinglulu 	int ret;
272*91f16700Schasinglulu 
273*91f16700Schasinglulu 	/* Get operation number */
274*91f16700Schasinglulu 	ret = uart_read_8(&operation);
275*91f16700Schasinglulu 	if (ret != 0) {
276*91f16700Schasinglulu 		return ret;
277*91f16700Schasinglulu 	}
278*91f16700Schasinglulu 
279*91f16700Schasinglulu 	xor = operation;
280*91f16700Schasinglulu 
281*91f16700Schasinglulu 	/* Get packet number */
282*91f16700Schasinglulu 	for (i = 3U; i != 0U; i--) {
283*91f16700Schasinglulu 		ret = uart_read_8(&byte);
284*91f16700Schasinglulu 		if (ret != 0) {
285*91f16700Schasinglulu 			return ret;
286*91f16700Schasinglulu 		}
287*91f16700Schasinglulu 
288*91f16700Schasinglulu 		xor ^= byte;
289*91f16700Schasinglulu 		packet_number = (packet_number << 8) | byte;
290*91f16700Schasinglulu 	}
291*91f16700Schasinglulu 
292*91f16700Schasinglulu 	if (packet_number != handle.packet) {
293*91f16700Schasinglulu 		WARN("UART: Bad packet number receive: %u, expected %u\n",
294*91f16700Schasinglulu 		     packet_number, handle.packet);
295*91f16700Schasinglulu 		return -EPROTO;
296*91f16700Schasinglulu 	}
297*91f16700Schasinglulu 
298*91f16700Schasinglulu 	/* Checksum */
299*91f16700Schasinglulu 	ret = uart_read_8(&byte);
300*91f16700Schasinglulu 	if (ret != 0) {
301*91f16700Schasinglulu 		return ret;
302*91f16700Schasinglulu 	}
303*91f16700Schasinglulu 	if (xor != byte) {
304*91f16700Schasinglulu 		VERBOSE("UART: Download Command checksum xor: %x, received %x\n",
305*91f16700Schasinglulu 			xor, byte);
306*91f16700Schasinglulu 		return -EPROTO;
307*91f16700Schasinglulu 	}
308*91f16700Schasinglulu 
309*91f16700Schasinglulu 	ret = uart_send_result(ACK_BYTE);
310*91f16700Schasinglulu 	if (ret != 0) {
311*91f16700Schasinglulu 		return ret;
312*91f16700Schasinglulu 	}
313*91f16700Schasinglulu 
314*91f16700Schasinglulu 	ret = uart_read_8(&byte);
315*91f16700Schasinglulu 	if (ret != 0) {
316*91f16700Schasinglulu 		return ret;
317*91f16700Schasinglulu 	}
318*91f16700Schasinglulu 	xor = byte;
319*91f16700Schasinglulu 	packet_size = byte + 1U;
320*91f16700Schasinglulu 	if (handle.len < packet_size) {
321*91f16700Schasinglulu 		STM32PROG_ERROR("Download overflow at %p\n", handle.addr + packet_size);
322*91f16700Schasinglulu 		return 0;
323*91f16700Schasinglulu 	}
324*91f16700Schasinglulu 
325*91f16700Schasinglulu 	for (i = 0U; i < packet_size; i++) {
326*91f16700Schasinglulu 		ret = uart_read_8(&byte);
327*91f16700Schasinglulu 		if (ret != 0) {
328*91f16700Schasinglulu 			return ret;
329*91f16700Schasinglulu 		}
330*91f16700Schasinglulu 
331*91f16700Schasinglulu 		*(handle.addr + i) = byte;
332*91f16700Schasinglulu 		xor ^= byte;
333*91f16700Schasinglulu 	}
334*91f16700Schasinglulu 
335*91f16700Schasinglulu 	/* Checksum */
336*91f16700Schasinglulu 	ret = uart_read_8(&byte) != 0;
337*91f16700Schasinglulu 	if (ret != 0) {
338*91f16700Schasinglulu 		return ret;
339*91f16700Schasinglulu 	}
340*91f16700Schasinglulu 	if (xor != byte) {
341*91f16700Schasinglulu 		VERBOSE("UART: Download Data checksum xor: %x, received %x\n",
342*91f16700Schasinglulu 			xor, byte);
343*91f16700Schasinglulu 		return -EPROTO;
344*91f16700Schasinglulu 	}
345*91f16700Schasinglulu 
346*91f16700Schasinglulu 	/* Packet treated */
347*91f16700Schasinglulu 	handle.packet++;
348*91f16700Schasinglulu 	handle.addr += packet_size;
349*91f16700Schasinglulu 	handle.len -= packet_size;
350*91f16700Schasinglulu 
351*91f16700Schasinglulu 	return 0;
352*91f16700Schasinglulu }
353*91f16700Schasinglulu 
354*91f16700Schasinglulu static int uart_start_cmd(uintptr_t buffer)
355*91f16700Schasinglulu {
356*91f16700Schasinglulu 	uint8_t byte = 0U;
357*91f16700Schasinglulu 	uint8_t xor = 0U;
358*91f16700Schasinglulu 	uint32_t i;
359*91f16700Schasinglulu 	uint32_t start_address = 0U;
360*91f16700Schasinglulu 	int ret;
361*91f16700Schasinglulu 
362*91f16700Schasinglulu 	/* Get address */
363*91f16700Schasinglulu 	for (i = 4U; i != 0U; i--) {
364*91f16700Schasinglulu 		ret = uart_read_8(&byte);
365*91f16700Schasinglulu 		if (ret != 0U) {
366*91f16700Schasinglulu 			return ret;
367*91f16700Schasinglulu 		}
368*91f16700Schasinglulu 
369*91f16700Schasinglulu 		xor ^= byte;
370*91f16700Schasinglulu 		start_address = (start_address << 8) | byte;
371*91f16700Schasinglulu 	}
372*91f16700Schasinglulu 
373*91f16700Schasinglulu 	/* Checksum */
374*91f16700Schasinglulu 	ret = uart_read_8(&byte);
375*91f16700Schasinglulu 	if (ret != 0) {
376*91f16700Schasinglulu 		return ret;
377*91f16700Schasinglulu 	}
378*91f16700Schasinglulu 
379*91f16700Schasinglulu 	if (xor != byte) {
380*91f16700Schasinglulu 		VERBOSE("UART: Start Command checksum xor: %x, received %x\n",
381*91f16700Schasinglulu 			xor, byte);
382*91f16700Schasinglulu 		return -EPROTO;
383*91f16700Schasinglulu 	}
384*91f16700Schasinglulu 
385*91f16700Schasinglulu 	if (start_address != UNDEFINED_DOWN_ADDR) {
386*91f16700Schasinglulu 		STM32PROG_ERROR("Invalid start at %x, for phase %u\n",
387*91f16700Schasinglulu 				start_address, handle.phase);
388*91f16700Schasinglulu 		return 0;
389*91f16700Schasinglulu 	}
390*91f16700Schasinglulu 
391*91f16700Schasinglulu 	if (!is_valid_header((fip_toc_header_t *)buffer)) {
392*91f16700Schasinglulu 		STM32PROG_ERROR("FIP Header check failed %lx, for phase %u\n",
393*91f16700Schasinglulu 				buffer, handle.phase);
394*91f16700Schasinglulu 		return -EIO;
395*91f16700Schasinglulu 	}
396*91f16700Schasinglulu 	VERBOSE("FIP header looks OK.\n");
397*91f16700Schasinglulu 
398*91f16700Schasinglulu 	return 0;
399*91f16700Schasinglulu }
400*91f16700Schasinglulu 
401*91f16700Schasinglulu static int uart_read(uint8_t id, uintptr_t buffer, size_t length)
402*91f16700Schasinglulu {
403*91f16700Schasinglulu 	bool start_done = false;
404*91f16700Schasinglulu 	int ret;
405*91f16700Schasinglulu 	uint8_t command = 0U;
406*91f16700Schasinglulu 
407*91f16700Schasinglulu 	handle.phase = id;
408*91f16700Schasinglulu 	handle.packet = 0U;
409*91f16700Schasinglulu 	handle.addr = (uint8_t *)buffer;
410*91f16700Schasinglulu 	handle.len = length;
411*91f16700Schasinglulu 
412*91f16700Schasinglulu 	INFO("UART: read phase %u at 0x%lx size 0x%zx\n",
413*91f16700Schasinglulu 	     id, buffer, length);
414*91f16700Schasinglulu 	while (!start_done) {
415*91f16700Schasinglulu 		ret = uart_receive_command(&command);
416*91f16700Schasinglulu 		if (ret != 0) {
417*91f16700Schasinglulu 			/* Delay to wait STM32CubeProgrammer end of transmission */
418*91f16700Schasinglulu 			mdelay(3);
419*91f16700Schasinglulu 
420*91f16700Schasinglulu 			ret = uart_send_result(NACK_BYTE);
421*91f16700Schasinglulu 			if (ret != 0U) {
422*91f16700Schasinglulu 				return ret;
423*91f16700Schasinglulu 			}
424*91f16700Schasinglulu 
425*91f16700Schasinglulu 			continue;
426*91f16700Schasinglulu 		}
427*91f16700Schasinglulu 
428*91f16700Schasinglulu 		uart_send_result(ACK_BYTE);
429*91f16700Schasinglulu 
430*91f16700Schasinglulu 		switch (command) {
431*91f16700Schasinglulu 		case INIT_BYTE:
432*91f16700Schasinglulu 			INFO("UART: Connected\n");
433*91f16700Schasinglulu 			/* Nothing to do */
434*91f16700Schasinglulu 			continue;
435*91f16700Schasinglulu 
436*91f16700Schasinglulu 		case GET_CMD_COMMAND:
437*91f16700Schasinglulu 			ret = get_cmd_command();
438*91f16700Schasinglulu 			break;
439*91f16700Schasinglulu 
440*91f16700Schasinglulu 		case GET_VER_COMMAND:
441*91f16700Schasinglulu 			ret = get_version_command();
442*91f16700Schasinglulu 			break;
443*91f16700Schasinglulu 
444*91f16700Schasinglulu 		case GET_ID_COMMAND:
445*91f16700Schasinglulu 			ret = get_id_command();
446*91f16700Schasinglulu 			break;
447*91f16700Schasinglulu 
448*91f16700Schasinglulu 		case PHASE_COMMAND:
449*91f16700Schasinglulu 			ret = uart_send_phase((uint32_t)buffer);
450*91f16700Schasinglulu 			if ((ret == 0) && (handle.phase == PHASE_RESET)) {
451*91f16700Schasinglulu 				start_done = true;
452*91f16700Schasinglulu 				INFO("UART: Reset\n");
453*91f16700Schasinglulu 			}
454*91f16700Schasinglulu 			break;
455*91f16700Schasinglulu 
456*91f16700Schasinglulu 		case DOWNLOAD_COMMAND:
457*91f16700Schasinglulu 			ret = uart_download_part();
458*91f16700Schasinglulu 			break;
459*91f16700Schasinglulu 
460*91f16700Schasinglulu 		case START_COMMAND:
461*91f16700Schasinglulu 			ret = uart_start_cmd(buffer);
462*91f16700Schasinglulu 			if ((ret == 0) && (handle.phase == id)) {
463*91f16700Schasinglulu 				INFO("UART: Start phase %u\n", handle.phase);
464*91f16700Schasinglulu 				start_done = true;
465*91f16700Schasinglulu 			}
466*91f16700Schasinglulu 			break;
467*91f16700Schasinglulu 
468*91f16700Schasinglulu 		default:
469*91f16700Schasinglulu 			WARN("UART: Unknown command\n");
470*91f16700Schasinglulu 			ret = -EINVAL;
471*91f16700Schasinglulu 			break;
472*91f16700Schasinglulu 		}
473*91f16700Schasinglulu 
474*91f16700Schasinglulu 		if (ret == 0) {
475*91f16700Schasinglulu 			ret = uart_send_result(ACK_BYTE);
476*91f16700Schasinglulu 		} else {
477*91f16700Schasinglulu 			ret = uart_send_result(NACK_BYTE);
478*91f16700Schasinglulu 		}
479*91f16700Schasinglulu 		if (ret != 0) {
480*91f16700Schasinglulu 			return ret;
481*91f16700Schasinglulu 		}
482*91f16700Schasinglulu 	}
483*91f16700Schasinglulu 
484*91f16700Schasinglulu 	stm32_uart_flush(&handle.uart);
485*91f16700Schasinglulu 
486*91f16700Schasinglulu 	return 0;
487*91f16700Schasinglulu }
488*91f16700Schasinglulu 
489*91f16700Schasinglulu /* Init UART: 115200, 8bit 1stop parity even and enable FIFO mode */
490*91f16700Schasinglulu const struct stm32_uart_init_s init = {
491*91f16700Schasinglulu 	.baud_rate = STM32MP_UART_BAUDRATE,
492*91f16700Schasinglulu 	.word_length = STM32_UART_WORDLENGTH_9B,
493*91f16700Schasinglulu 	.stop_bits = STM32_UART_STOPBITS_1,
494*91f16700Schasinglulu 	.parity = STM32_UART_PARITY_EVEN,
495*91f16700Schasinglulu 	.hw_flow_control = STM32_UART_HWCONTROL_NONE,
496*91f16700Schasinglulu 	.mode = STM32_UART_MODE_TX_RX,
497*91f16700Schasinglulu 	.fifo_mode = STM32_UART_FIFOMODE_EN,
498*91f16700Schasinglulu };
499*91f16700Schasinglulu 
500*91f16700Schasinglulu int stm32cubeprog_uart_load(uintptr_t instance, uintptr_t base, size_t len)
501*91f16700Schasinglulu {
502*91f16700Schasinglulu 	int ret;
503*91f16700Schasinglulu 
504*91f16700Schasinglulu 	if (stm32_uart_init(&handle.uart, instance, &init) != 0) {
505*91f16700Schasinglulu 		return -EIO;
506*91f16700Schasinglulu 	}
507*91f16700Schasinglulu 
508*91f16700Schasinglulu 	/*
509*91f16700Schasinglulu 	 * The following NACK_BYTE is written because STM32CubeProgrammer has
510*91f16700Schasinglulu 	 * already sent its command before TF-A has reached this point, and
511*91f16700Schasinglulu 	 * because FIFO was not configured by BootROM.
512*91f16700Schasinglulu 	 * The byte in the UART_RX register is then the checksum and not the
513*91f16700Schasinglulu 	 * command. NACK_BYTE has to be written, so that the programmer will
514*91f16700Schasinglulu 	 * re-send the good command.
515*91f16700Schasinglulu 	 */
516*91f16700Schasinglulu 	ret = uart_send_result(NACK_BYTE);
517*91f16700Schasinglulu 	if (ret != 0) {
518*91f16700Schasinglulu 		return ret;
519*91f16700Schasinglulu 	}
520*91f16700Schasinglulu 
521*91f16700Schasinglulu 	return uart_read(PHASE_SSBL, base, len);
522*91f16700Schasinglulu }
523