blob: cd355cc8409ba04b526f0100ca514c9953f44a42 [file] [log] [blame]
developer29b37c52020-04-21 09:28:34 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2020 MediaTek Inc.
4 *
5 * Author: Weijie Gao <weijie.gao@mediatek.com>
6 */
7
8#include <common.h>
9#include <linux/bitops.h>
10#include <linux/io.h>
11#include <linux/sizes.h>
12#include <mach/ddr.h>
13#include <mach/mc.h>
14
15#define DDR_BW_TEST_PAT 0xaa5555aa
16
17static const u32 dram_size[] = {
18 [DRAM_8MB] = SZ_8M,
19 [DRAM_16MB] = SZ_16M,
20 [DRAM_32MB] = SZ_32M,
21 [DRAM_64MB] = SZ_64M,
22 [DRAM_128MB] = SZ_128M,
23 [DRAM_256MB] = SZ_256M,
24};
25
26static void dram_test_write(u32 addr, u32 val)
27{
28 volatile ulong *target = (volatile ulong *)(KSEG1 + addr);
29
30 sync();
31 *target = val;
32 sync();
33}
34
35static u32 dram_test_read(u32 addr)
36{
37 volatile ulong *target = (volatile ulong *)(KSEG1 + addr);
38 u32 val;
39
40 sync();
41 val = *target;
42 sync();
43
44 return val;
45}
46
47static int dram_addr_test_bit(u32 bit)
48{
49 u32 val;
50
51 dram_test_write(0, 0);
52 dram_test_write(BIT(bit), DDR_BW_TEST_PAT);
53 val = dram_test_read(0);
54
55 if (val == DDR_BW_TEST_PAT)
56 return 1;
57
58 return 0;
59}
60
61static void mc_ddr_init(void __iomem *memc, const struct mc_ddr_cfg *cfg,
62 u32 dq_dly, u32 dqs_dly, mc_reset_t mc_reset, u32 bw)
63{
64 u32 val;
65
66 mc_reset(1);
67 __udelay(200);
68 mc_reset(0);
69
70 clrbits_32(memc + MEMCTL_SDRAM_CFG1_REG, RBC_MAPPING);
71
72 writel(cfg->cfg2, memc + MEMCTL_DDR_CFG2_REG);
73 writel(cfg->cfg3, memc + MEMCTL_DDR_CFG3_REG);
74 writel(cfg->cfg4, memc + MEMCTL_DDR_CFG4_REG);
75 writel(dq_dly, memc + MEMCTL_DDR_DQ_DLY_REG);
76 writel(dqs_dly, memc + MEMCTL_DDR_DQS_DLY_REG);
77
78 writel(cfg->cfg0, memc + MEMCTL_DDR_CFG0_REG);
79
80 val = cfg->cfg1;
81 if (bw) {
82 val &= ~IND_SDRAM_WIDTH_M;
83 val |= (bw << IND_SDRAM_WIDTH_S) & IND_SDRAM_WIDTH_M;
84 }
85
86 writel(val, memc + MEMCTL_DDR_CFG1_REG);
87
88 clrsetbits_32(memc + MEMCTL_PWR_SAVE_CNT_REG, SR_TAR_CNT_M,
89 1 << SR_TAR_CNT_S);
90
91 setbits_32(memc + MEMCTL_DDR_SELF_REFRESH_REG, SR_AUTO_EN);
92}
93
94void ddr1_init(struct mc_ddr_init_param *param)
95{
96 enum mc_dram_size sz;
97 u32 bw = 0;
98
99 /* First initialization, determine bus width */
100 mc_ddr_init(param->memc, &param->cfgs[DRAM_8MB], param->dq_dly,
101 param->dqs_dly, param->mc_reset, IND_SDRAM_WIDTH_16BIT);
102
103 /* Test bus width */
104 dram_test_write(0, DDR_BW_TEST_PAT);
105 if (dram_test_read(0) == DDR_BW_TEST_PAT)
106 bw = IND_SDRAM_WIDTH_16BIT;
107 else
108 bw = IND_SDRAM_WIDTH_8BIT;
109
110 /* Second initialization, determine DDR capacity */
111 mc_ddr_init(param->memc, &param->cfgs[DRAM_128MB], param->dq_dly,
112 param->dqs_dly, param->mc_reset, bw);
113
114 if (dram_addr_test_bit(9)) {
115 sz = DRAM_8MB;
116 } else {
117 if (dram_addr_test_bit(10)) {
118 if (dram_addr_test_bit(23))
119 sz = DRAM_16MB;
120 else
121 sz = DRAM_32MB;
122 } else {
123 if (dram_addr_test_bit(24))
124 sz = DRAM_64MB;
125 else
126 sz = DRAM_128MB;
127 }
128 }
129
130 /* Final initialization, with DDR calibration */
131 mc_ddr_init(param->memc, &param->cfgs[sz], param->dq_dly,
132 param->dqs_dly, param->mc_reset, bw);
133
134 /* Return actual DDR configuration */
135 param->memsize = dram_size[sz];
136 param->bus_width = bw;
137}
138
139void ddr2_init(struct mc_ddr_init_param *param)
140{
141 enum mc_dram_size sz;
142 u32 bw = 0;
143
144 /* First initialization, determine bus width */
145 mc_ddr_init(param->memc, &param->cfgs[DRAM_32MB], param->dq_dly,
146 param->dqs_dly, param->mc_reset, IND_SDRAM_WIDTH_16BIT);
147
148 /* Test bus width */
149 dram_test_write(0, DDR_BW_TEST_PAT);
150 if (dram_test_read(0) == DDR_BW_TEST_PAT)
151 bw = IND_SDRAM_WIDTH_16BIT;
152 else
153 bw = IND_SDRAM_WIDTH_8BIT;
154
155 /* Second initialization, determine DDR capacity */
156 mc_ddr_init(param->memc, &param->cfgs[DRAM_256MB], param->dq_dly,
157 param->dqs_dly, param->mc_reset, bw);
158
159 if (bw == IND_SDRAM_WIDTH_16BIT) {
160 if (dram_addr_test_bit(10)) {
161 sz = DRAM_32MB;
162 } else {
163 if (dram_addr_test_bit(24)) {
164 if (dram_addr_test_bit(27))
165 sz = DRAM_64MB;
166 else
167 sz = DRAM_128MB;
168 } else {
169 sz = DRAM_256MB;
170 }
171 }
172 } else {
173 if (dram_addr_test_bit(23)) {
174 sz = DRAM_32MB;
175 } else {
176 if (dram_addr_test_bit(24)) {
177 if (dram_addr_test_bit(27))
178 sz = DRAM_64MB;
179 else
180 sz = DRAM_128MB;
181 } else {
182 sz = DRAM_256MB;
183 }
184 }
185 }
186
187 /* Final initialization, with DDR calibration */
188 mc_ddr_init(param->memc, &param->cfgs[sz], param->dq_dly,
189 param->dqs_dly, param->mc_reset, bw);
190
191 /* Return actual DDR configuration */
192 param->memsize = dram_size[sz];
193 param->bus_width = bw;
194}