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