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