/* * Copyright 2018 NXP * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include void lpddr4_mr_write(uint32_t mr_rank, uint32_t mr_addr, uint32_t mr_data) { uint32_t tmp; /* * 1. Poll MRSTAT.mr_wr_busy until it is 0. This checks that there * is no outstanding MR transaction. No * writes should be performed to MRCTRL0 and MRCTRL1 if MRSTAT.mr_wr_busy = 1. */ do { tmp = mmio_read_32(DDRC_MRSTAT(0)); } while(tmp & 0x1); /* * 2. Write the MRCTRL0.mr_type, MRCTRL0.mr_addr, * MRCTRL0.mr_rank and (for MRWs) * MRCTRL1.mr_data to define the MR transaction. */ mmio_write_32(DDRC_MRCTRL0(0), (mr_rank << 4)); mmio_write_32(DDRC_MRCTRL1(0), (mr_addr << 8) | mr_data); mmio_setbits_32(DDRC_MRCTRL0(0), (1 << 31)); } uint32_t lpddr4_mr_read(uint32_t mr_rank, uint32_t mr_addr) { uint32_t tmp, mr_data; mmio_write_32(DRC_PERF_MON_MRR0_DAT(0), 0x1); do { tmp = mmio_read_32(DDRC_MRSTAT(0)); } while(tmp & 0x1); mmio_write_32(DDRC_MRCTRL0(0), (mr_rank << 4) | 0x1); mmio_write_32(DDRC_MRCTRL1(0), (mr_addr << 8)); mmio_setbits_32(DDRC_MRCTRL0(0), (1 << 31)); do { tmp = mmio_read_32(DRC_PERF_MON_MRR0_DAT(0)); } while((tmp & 0x8) == 0); tmp = mmio_read_32(DRC_PERF_MON_MRR1_DAT(0)); mr_data = tmp & 0xff; mmio_write_32(DRC_PERF_MON_MRR0_DAT(0), 0x4); return mr_data; }