aboutsummaryrefslogtreecommitdiff
path: root/src/soc/mediatek/mt8192/dramc_pi_main.c
blob: 8eba016dd8347b761ccb61a945ec94c942b29da2 (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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* SPDX-License-Identifier: GPL-2.0-only */

#include <soc/dramc_pi_api.h>
#include <soc/dramc_register.h>
#include <soc/pll.h>
#include <soc/pll_common.h>
#include <soc/regulator.h>

static void set_vcore_voltage(const struct ddr_cali *cali)
{
	u32 vcore = get_vcore_value(cali);

	dramc_info("Set DRAM vcore voltage to %u\n", vcore);
	mainboard_set_regulator_vol(MTK_REGULATOR_VCORE, vcore);
}

static void get_dram_info_after_cal(struct ddr_cali *cali)
{
	u8 vendor_id, density, max_density = 0;
	u32 size_gb, max_size = 0;

	vendor_id = dramc_mode_reg_read_by_rank(CHANNEL_A, RANK_0, 5) & 0xff;
	dramc_info("Vendor id is %#x\n", vendor_id);

	for (u8 rk = RANK_0; rk < cali->support_ranks; rk++) {
		density = dramc_mode_reg_read_by_rank(CHANNEL_A, rk, 8) & 0xff;
		dramc_dbg("MR8 %#x\n", density);
		density = (density >> 2) & 0xf;

		switch (density) {
		/* these case values are from JESD209-4C MR8 Density OP[5:2] */
		case 0x0:
			size_gb = 4;
			break;
		case 0x1:
			size_gb = 6;
			break;
		case 0x2:
			size_gb = 8;
			break;
		case 0x3:
			size_gb = 12;
			break;
		case 0x4:
			size_gb = 16;
			break;
		case 0x5:
			size_gb = 24;
			break;
		case 0x6:
			size_gb = 32;
			break;
		case 0xC:
			size_gb = 2;
			break;
		default:
			dramc_err("Unexpected mode register density value: %#x\n", density);
			size_gb = 0;
			break;
		}
		if (size_gb > max_size) {
			max_size = size_gb;
			max_density = density;
		}
		dramc_dbg("RK%u size %uGb, density:%u\n", rk, size_gb, max_density);
	}

	cali->density = max_density;
}

static void dramc_calibration_all_channels(struct ddr_cali *cali)
{
}

static void mem_pll_init(void)
{
	SET32_BITFIELDS(&mtk_apmixed->mpll_con3, PLL_POWER_ISO_ENABLE, 3);

	udelay(30);
	SET32_BITFIELDS(&mtk_apmixed->mpll_con3, PLL_ISO_ENABLE, 0);

	udelay(1);
	SET32_BITFIELDS(&mtk_apmixed->mpll_con1, PLL_CON1, MPLL_CON1_FREQ);
	SET32_BITFIELDS(&mtk_apmixed->mpll_con0, PLL_ENABLE, 1);

	udelay(20);
	SET32_BITFIELDS(&mtk_apmixed->pllon_con0, MPLL_IOS_SEL, 0);
	SET32_BITFIELDS(&mtk_apmixed->pllon_con0, MPLL_EN_SEL, 0);
	SET32_BITFIELDS(&mtk_apmixed->pllon_con1, MPLL_PWR_SEL, 0);
	SET32_BITFIELDS(&mtk_apmixed->pllon_con2, MPLL_BY_ISO_DLY, 0);
	SET32_BITFIELDS(&mtk_apmixed->pllon_con3, MPLL_BY_PWR_DLY, 0);
}

void init_dram(const struct dramc_data *dparam)
{
	u32 bc_bak;
	u8 k_shuffle, k_shuffle_end;
	u8 pll_mode = 0;
	bool first_freq_k = true;

	struct ddr_cali cali = {0};
	struct mr_values mr_value;
	const struct ddr_base_info *ddr_info = &dparam->ddr_info;

	cali.pll_mode = &pll_mode;
	cali.mr_value = &mr_value;
	cali.support_ranks = ddr_info->support_ranks;
	cali.cbt_mode[RANK_0] = ddr_info->cbt_mode[RANK_0];
	cali.cbt_mode[RANK_1] = ddr_info->cbt_mode[RANK_1];
	cali.emi_config = &ddr_info->emi_config;

	dramc_set_broadcast(DRAMC_BROADCAST_ON);
	mem_pll_init();

	global_option_init(&cali);
	bc_bak = dramc_get_broadcast();
	dramc_set_broadcast(DRAMC_BROADCAST_OFF);
	emi_mdl_init(cali.emi_config);
	dramc_set_broadcast(bc_bak);

	dramc_sw_impedance_cal(ODT_OFF, &cali.impedance);
	dramc_sw_impedance_cal(ODT_ON, &cali.impedance);

	if (ddr_info->config_dvfs == DRAMC_ENABLE_DVFS)
		k_shuffle_end = CALI_SEQ_MAX;
	else
		k_shuffle_end = CALI_SEQ1;

	for (k_shuffle = CALI_SEQ0; k_shuffle < k_shuffle_end; k_shuffle++) {
		set_cali_datas(&cali, dparam, k_shuffle);
		set_vcore_voltage(&cali);
		dfs_init_for_calibration(&cali);

		if (first_freq_k)
			emi_init2();

		dramc_calibration_all_channels(&cali);

		/* only need to do once to get DDR's base information */
		if (first_freq_k)
			get_dram_info_after_cal(&cali);

		first_freq_k = false;
	}
}