xref: /rk3399_ARM-atf/drivers/nxp/ddr/s32cc/ddr_utils.c (revision 30c8a20d3c5a2163eb676da7f0d575d3a9499fed)
1 /*
2  * Copyright 2020-2025 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <errno.h>
7 
8 #include <common/debug.h>
9 #include <ddr_utils.h>
10 #include <mmio_poll.h>
11 
12 static uint32_t get_mail(uint32_t *mail);
13 static uint32_t ack_mail(void);
14 
15 /* Wait until firmware finishes execution and return training result */
16 uint32_t wait_firmware_execution(void)
17 {
18 	uint32_t timeout_us = DEFAULT_TIMEOUT_US, ret = NO_ERR, mail = 0;
19 	uint64_t timeout = timeout_init_us(timeout_us);
20 	bool loop_continue = true;
21 	bool timeout_expired;
22 
23 	do {
24 		ret = get_mail(&mail);
25 		if (ret != NO_ERR) {
26 			loop_continue = false;
27 		} else if (mail == TRAINING_FAILED_MSG) {
28 			/* Training stage failed */
29 			ret = TRAINING_FAILED;
30 			loop_continue = false;
31 		} else if (mail == TRAINING_OK_MSG) {
32 			loop_continue = false;
33 		} else {
34 			/* Continue waiting for training result */
35 		}
36 		timeout_expired = timeout_elapsed(timeout);
37 		if (timeout_expired) {
38 			ret = TRAINING_FAILED;
39 			loop_continue = false;
40 		}
41 		/* Continue loop if no exit condition met and timeout not elapsed */
42 	} while (loop_continue);
43 
44 	return ret;
45 }
46 
47 /* Acknowledge received message */
48 static uint32_t ack_mail(void)
49 {
50 	uint32_t timeout = DEFAULT_TIMEOUT_US;
51 	uint32_t uct_reg;
52 	int err;
53 
54 	/* ACK message */
55 	mmio_write_32(DDR_PHYA_DCTWRITEPROT, APBONLY_DCTWRITEPROT_ACK_EN);
56 
57 	err = mmio_read_32_poll_timeout(DDR_PHYA_APBONLY_UCTSHADOWREGS, uct_reg,
58 					(uct_reg & UCT_WRITE_PROT_SHADOW_MASK) !=
59 					UCT_WRITE_PROT_SHADOW_ACK,
60 					timeout);
61 	if (err != 0) {
62 		ERROR("DDR PHY did not acknowledge write protection\n");
63 		return TIMEOUT_ERR;
64 	}
65 
66 	mmio_write_32(DDR_PHYA_DCTWRITEPROT, APBONLY_DCTWRITEPROT_ACK_DIS);
67 
68 	return NO_ERR;
69 }
70 
71 /* Read available message from DDR PHY microcontroller */
72 static uint32_t get_mail(uint32_t *mail)
73 {
74 	uint32_t uct_reg, timeout = DEFAULT_TIMEOUT_US;
75 	int err;
76 
77 	err = mmio_read_32_poll_timeout(DDR_PHYA_APBONLY_UCTSHADOWREGS, uct_reg,
78 					(uct_reg & UCT_WRITE_PROT_SHADOW_MASK) ==
79 					UCT_WRITE_PROT_SHADOW_ACK,
80 					timeout);
81 	if (err != 0) {
82 		ERROR("DDR PHY did not acknowledge UCT write protection\n");
83 		return TIMEOUT_ERR;
84 	}
85 
86 	*mail = mmio_read_32(DDR_PHYA_APBONLY_UCTWRITEONLYSHADOW);
87 	/* ACK */
88 	return ack_mail();
89 }
90