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