summaryrefslogtreecommitdiff
path: root/plat/imx/common/imx8m/lpddr4_helper.c
blob: e9446aa04130536f921bb3c9777432246b7509d6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/*
 * Copyright 2018 NXP
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <debug.h>
#include <ddrc.h>
#include <dram.h>
#include <mmio.h>

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;
}