1f1df9364SStefan Roese /*
2f1df9364SStefan Roese * Copyright (C) Marvell International Ltd. and its affiliates
3f1df9364SStefan Roese *
4f1df9364SStefan Roese * SPDX-License-Identifier: GPL-2.0
5f1df9364SStefan Roese */
6f1df9364SStefan Roese
7f1df9364SStefan Roese #include <common.h>
8f1df9364SStefan Roese #include <i2c.h>
9f1df9364SStefan Roese #include <spl.h>
10f1df9364SStefan Roese #include <asm/io.h>
11f1df9364SStefan Roese #include <asm/arch/cpu.h>
12f1df9364SStefan Roese #include <asm/arch/soc.h>
13f1df9364SStefan Roese
14f1df9364SStefan Roese #include "ddr3_init.h"
15f1df9364SStefan Roese
16f1df9364SStefan Roese #define A38X_NUMBER_OF_INTERFACES 5
17f1df9364SStefan Roese
18f1df9364SStefan Roese #define SAR_DEV_ID_OFFS 27
19f1df9364SStefan Roese #define SAR_DEV_ID_MASK 0x7
20f1df9364SStefan Roese
21f1df9364SStefan Roese /* Termal Sensor Registers */
22f1df9364SStefan Roese #define TSEN_STATE_REG 0xe4070
23f1df9364SStefan Roese #define TSEN_STATE_OFFSET 31
24f1df9364SStefan Roese #define TSEN_STATE_MASK (0x1 << TSEN_STATE_OFFSET)
25f1df9364SStefan Roese #define TSEN_CONF_REG 0xe4074
26f1df9364SStefan Roese #define TSEN_CONF_RST_OFFSET 8
27f1df9364SStefan Roese #define TSEN_CONF_RST_MASK (0x1 << TSEN_CONF_RST_OFFSET)
28f1df9364SStefan Roese #define TSEN_STATUS_REG 0xe4078
29f1df9364SStefan Roese #define TSEN_STATUS_READOUT_VALID_OFFSET 10
30f1df9364SStefan Roese #define TSEN_STATUS_READOUT_VALID_MASK (0x1 << \
31f1df9364SStefan Roese TSEN_STATUS_READOUT_VALID_OFFSET)
32f1df9364SStefan Roese #define TSEN_STATUS_TEMP_OUT_OFFSET 0
33f1df9364SStefan Roese #define TSEN_STATUS_TEMP_OUT_MASK (0x3ff << TSEN_STATUS_TEMP_OUT_OFFSET)
34f1df9364SStefan Roese
35f1df9364SStefan Roese static struct dfx_access interface_map[] = {
36f1df9364SStefan Roese /* Pipe Client */
37f1df9364SStefan Roese { 0, 17 },
38f1df9364SStefan Roese { 1, 7 },
39f1df9364SStefan Roese { 1, 11 },
40f1df9364SStefan Roese { 0, 3 },
41f1df9364SStefan Roese { 1, 25 },
42f1df9364SStefan Roese { 0, 0 },
43f1df9364SStefan Roese { 0, 0 },
44f1df9364SStefan Roese { 0, 0 },
45f1df9364SStefan Roese { 0, 0 },
46f1df9364SStefan Roese { 0, 0 },
47f1df9364SStefan Roese { 0, 0 },
48f1df9364SStefan Roese { 0, 0 }
49f1df9364SStefan Roese };
50f1df9364SStefan Roese
51f1df9364SStefan Roese /* This array hold the board round trip delay (DQ and CK) per <interface,bus> */
52f1df9364SStefan Roese struct trip_delay_element a38x_board_round_trip_delay_array[] = {
53f1df9364SStefan Roese /* 1st board */
54f1df9364SStefan Roese /* Interface bus DQS-delay CK-delay */
55f1df9364SStefan Roese { 3952, 5060 },
56f1df9364SStefan Roese { 3192, 4493 },
57f1df9364SStefan Roese { 4785, 6677 },
58f1df9364SStefan Roese { 3413, 7267 },
59f1df9364SStefan Roese { 4282, 6086 }, /* ECC PUP */
60f1df9364SStefan Roese { 3952, 5134 },
61f1df9364SStefan Roese { 3192, 4567 },
62f1df9364SStefan Roese { 4785, 6751 },
63f1df9364SStefan Roese { 3413, 7341 },
64f1df9364SStefan Roese { 4282, 6160 }, /* ECC PUP */
65f1df9364SStefan Roese
66f1df9364SStefan Roese /* 2nd board */
67f1df9364SStefan Roese /* Interface bus DQS-delay CK-delay */
68f1df9364SStefan Roese { 3952, 5060 },
69f1df9364SStefan Roese { 3192, 4493 },
70f1df9364SStefan Roese { 4785, 6677 },
71f1df9364SStefan Roese { 3413, 7267 },
72f1df9364SStefan Roese { 4282, 6086 }, /* ECC PUP */
73f1df9364SStefan Roese { 3952, 5134 },
74f1df9364SStefan Roese { 3192, 4567 },
75f1df9364SStefan Roese { 4785, 6751 },
76f1df9364SStefan Roese { 3413, 7341 },
77f1df9364SStefan Roese { 4282, 6160 } /* ECC PUP */
78f1df9364SStefan Roese };
79f1df9364SStefan Roese
80f1df9364SStefan Roese #ifdef STATIC_ALGO_SUPPORT
81f1df9364SStefan Roese /* package trace */
82f1df9364SStefan Roese static struct trip_delay_element a38x_package_round_trip_delay_array[] = {
83f1df9364SStefan Roese /* IF BUS DQ_DELAY CK_DELAY */
84f1df9364SStefan Roese { 0, 0 },
85f1df9364SStefan Roese { 0, 0 },
86f1df9364SStefan Roese { 0, 0 },
87f1df9364SStefan Roese { 0, 0 },
88f1df9364SStefan Roese { 0, 0 },
89f1df9364SStefan Roese { 0, 0 },
90f1df9364SStefan Roese { 0, 0 },
91f1df9364SStefan Roese { 0, 0 },
92f1df9364SStefan Roese { 0, 0 },
93f1df9364SStefan Roese { 0, 0 },
94f1df9364SStefan Roese { 0, 0 },
95f1df9364SStefan Roese { 0, 0 },
96f1df9364SStefan Roese { 0, 0 },
97f1df9364SStefan Roese { 0, 0 },
98f1df9364SStefan Roese { 0, 0 },
99f1df9364SStefan Roese { 0, 0 },
100f1df9364SStefan Roese { 0, 0 },
101f1df9364SStefan Roese { 0, 0 },
102f1df9364SStefan Roese { 0, 0 },
103f1df9364SStefan Roese { 0, 0 }
104f1df9364SStefan Roese };
105f1df9364SStefan Roese
106f1df9364SStefan Roese static int a38x_silicon_delay_offset[] = {
107f1df9364SStefan Roese /* board 0 */
108f1df9364SStefan Roese 0,
109f1df9364SStefan Roese /* board 1 */
110f1df9364SStefan Roese 0,
111f1df9364SStefan Roese /* board 2 */
112f1df9364SStefan Roese 0
113f1df9364SStefan Roese };
114f1df9364SStefan Roese #endif
115f1df9364SStefan Roese
116f1df9364SStefan Roese static u8 a38x_bw_per_freq[DDR_FREQ_LIMIT] = {
117f1df9364SStefan Roese 0x3, /* DDR_FREQ_100 */
118f1df9364SStefan Roese 0x4, /* DDR_FREQ_400 */
119f1df9364SStefan Roese 0x4, /* DDR_FREQ_533 */
120f1df9364SStefan Roese 0x5, /* DDR_FREQ_667 */
121f1df9364SStefan Roese 0x5, /* DDR_FREQ_800 */
122f1df9364SStefan Roese 0x5, /* DDR_FREQ_933 */
123f1df9364SStefan Roese 0x5, /* DDR_FREQ_1066 */
124f1df9364SStefan Roese 0x3, /* DDR_FREQ_311 */
125f1df9364SStefan Roese 0x3, /* DDR_FREQ_333 */
126f1df9364SStefan Roese 0x4, /* DDR_FREQ_467 */
127f1df9364SStefan Roese 0x5, /* DDR_FREQ_850 */
128f1df9364SStefan Roese 0x5, /* DDR_FREQ_600 */
129f1df9364SStefan Roese 0x3, /* DDR_FREQ_300 */
130f1df9364SStefan Roese 0x5, /* DDR_FREQ_900 */
131f1df9364SStefan Roese 0x3, /* DDR_FREQ_360 */
132f1df9364SStefan Roese 0x5 /* DDR_FREQ_1000 */
133f1df9364SStefan Roese };
134f1df9364SStefan Roese
135f1df9364SStefan Roese static u8 a38x_rate_per_freq[DDR_FREQ_LIMIT] = {
136f1df9364SStefan Roese /*TBD*/ 0x1, /* DDR_FREQ_100 */
137f1df9364SStefan Roese 0x2, /* DDR_FREQ_400 */
138f1df9364SStefan Roese 0x2, /* DDR_FREQ_533 */
139f1df9364SStefan Roese 0x2, /* DDR_FREQ_667 */
140f1df9364SStefan Roese 0x2, /* DDR_FREQ_800 */
141f1df9364SStefan Roese 0x3, /* DDR_FREQ_933 */
142f1df9364SStefan Roese 0x3, /* DDR_FREQ_1066 */
143f1df9364SStefan Roese 0x1, /* DDR_FREQ_311 */
144f1df9364SStefan Roese 0x1, /* DDR_FREQ_333 */
145f1df9364SStefan Roese 0x2, /* DDR_FREQ_467 */
146f1df9364SStefan Roese 0x2, /* DDR_FREQ_850 */
147f1df9364SStefan Roese 0x2, /* DDR_FREQ_600 */
148f1df9364SStefan Roese 0x1, /* DDR_FREQ_300 */
149f1df9364SStefan Roese 0x2, /* DDR_FREQ_900 */
150f1df9364SStefan Roese 0x1, /* DDR_FREQ_360 */
151f1df9364SStefan Roese 0x2 /* DDR_FREQ_1000 */
152f1df9364SStefan Roese };
153f1df9364SStefan Roese
154f1df9364SStefan Roese static u16 a38x_vco_freq_per_sar[] = {
155f1df9364SStefan Roese 666, /* 0 */
156f1df9364SStefan Roese 1332,
157f1df9364SStefan Roese 800,
158f1df9364SStefan Roese 1600,
159f1df9364SStefan Roese 1066,
160f1df9364SStefan Roese 2132,
161f1df9364SStefan Roese 1200,
162f1df9364SStefan Roese 2400,
163f1df9364SStefan Roese 1332,
164f1df9364SStefan Roese 1332,
165f1df9364SStefan Roese 1500,
166f1df9364SStefan Roese 1500,
167f1df9364SStefan Roese 1600, /* 12 */
168f1df9364SStefan Roese 1600,
169f1df9364SStefan Roese 1700,
170f1df9364SStefan Roese 1700,
171f1df9364SStefan Roese 1866,
172f1df9364SStefan Roese 1866,
173f1df9364SStefan Roese 1800, /* 18 */
174f1df9364SStefan Roese 2000,
175f1df9364SStefan Roese 2000,
176f1df9364SStefan Roese 4000,
177f1df9364SStefan Roese 2132,
178f1df9364SStefan Roese 2132,
179f1df9364SStefan Roese 2300,
180f1df9364SStefan Roese 2300,
181f1df9364SStefan Roese 2400,
182f1df9364SStefan Roese 2400,
183f1df9364SStefan Roese 2500,
184f1df9364SStefan Roese 2500,
185f1df9364SStefan Roese 800
186f1df9364SStefan Roese };
187f1df9364SStefan Roese
188f1df9364SStefan Roese u32 pipe_multicast_mask;
189f1df9364SStefan Roese
190f1df9364SStefan Roese u32 dq_bit_map_2_phy_pin[] = {
191f1df9364SStefan Roese 1, 0, 2, 6, 9, 8, 3, 7, /* 0 */
192f1df9364SStefan Roese 8, 9, 1, 7, 2, 6, 3, 0, /* 1 */
193f1df9364SStefan Roese 3, 9, 7, 8, 1, 0, 2, 6, /* 2 */
194f1df9364SStefan Roese 1, 0, 6, 2, 8, 3, 7, 9, /* 3 */
195f1df9364SStefan Roese 0, 1, 2, 9, 7, 8, 3, 6, /* 4 */
196f1df9364SStefan Roese };
197f1df9364SStefan Roese
198f1df9364SStefan Roese static int ddr3_tip_a38x_set_divider(u8 dev_num, u32 if_id,
199f1df9364SStefan Roese enum hws_ddr_freq freq);
200f1df9364SStefan Roese
201f1df9364SStefan Roese /*
202f1df9364SStefan Roese * Read temperature TJ value
203f1df9364SStefan Roese */
ddr3_ctrl_get_junc_temp(u8 dev_num)204f1df9364SStefan Roese u32 ddr3_ctrl_get_junc_temp(u8 dev_num)
205f1df9364SStefan Roese {
206f1df9364SStefan Roese int reg = 0;
207f1df9364SStefan Roese
208f1df9364SStefan Roese /* Initiates TSEN hardware reset once */
209f1df9364SStefan Roese if ((reg_read(TSEN_CONF_REG) & TSEN_CONF_RST_MASK) == 0)
210f1df9364SStefan Roese reg_bit_set(TSEN_CONF_REG, TSEN_CONF_RST_MASK);
211f1df9364SStefan Roese mdelay(10);
212f1df9364SStefan Roese
213f1df9364SStefan Roese /* Check if the readout field is valid */
214f1df9364SStefan Roese if ((reg_read(TSEN_STATUS_REG) & TSEN_STATUS_READOUT_VALID_MASK) == 0) {
215f1df9364SStefan Roese printf("%s: TSEN not ready\n", __func__);
216f1df9364SStefan Roese return 0;
217f1df9364SStefan Roese }
218f1df9364SStefan Roese
219f1df9364SStefan Roese reg = reg_read(TSEN_STATUS_REG);
220f1df9364SStefan Roese reg = (reg & TSEN_STATUS_TEMP_OUT_MASK) >> TSEN_STATUS_TEMP_OUT_OFFSET;
221f1df9364SStefan Roese
222f1df9364SStefan Roese return ((((10000 * reg) / 21445) * 1000) - 272674) / 1000;
223f1df9364SStefan Roese }
224f1df9364SStefan Roese
225f1df9364SStefan Roese /*
226f1df9364SStefan Roese * Name: ddr3_tip_a38x_get_freq_config.
227f1df9364SStefan Roese * Desc:
228f1df9364SStefan Roese * Args:
229f1df9364SStefan Roese * Notes:
230f1df9364SStefan Roese * Returns: MV_OK if success, other error code if fail.
231f1df9364SStefan Roese */
ddr3_tip_a38x_get_freq_config(u8 dev_num,enum hws_ddr_freq freq,struct hws_tip_freq_config_info * freq_config_info)232f1df9364SStefan Roese int ddr3_tip_a38x_get_freq_config(u8 dev_num, enum hws_ddr_freq freq,
233f1df9364SStefan Roese struct hws_tip_freq_config_info
234f1df9364SStefan Roese *freq_config_info)
235f1df9364SStefan Roese {
236f1df9364SStefan Roese if (a38x_bw_per_freq[freq] == 0xff)
237f1df9364SStefan Roese return MV_NOT_SUPPORTED;
238f1df9364SStefan Roese
239f1df9364SStefan Roese if (freq_config_info == NULL)
240f1df9364SStefan Roese return MV_BAD_PARAM;
241f1df9364SStefan Roese
242f1df9364SStefan Roese freq_config_info->bw_per_freq = a38x_bw_per_freq[freq];
243f1df9364SStefan Roese freq_config_info->rate_per_freq = a38x_rate_per_freq[freq];
244f1df9364SStefan Roese freq_config_info->is_supported = 1;
245f1df9364SStefan Roese
246f1df9364SStefan Roese return MV_OK;
247f1df9364SStefan Roese }
248f1df9364SStefan Roese
249f1df9364SStefan Roese /*
250f1df9364SStefan Roese * Name: ddr3_tip_a38x_pipe_enable.
251f1df9364SStefan Roese * Desc:
252f1df9364SStefan Roese * Args:
253f1df9364SStefan Roese * Notes:
254f1df9364SStefan Roese * Returns: MV_OK if success, other error code if fail.
255f1df9364SStefan Roese */
ddr3_tip_a38x_pipe_enable(u8 dev_num,enum hws_access_type interface_access,u32 if_id,int enable)256f1df9364SStefan Roese int ddr3_tip_a38x_pipe_enable(u8 dev_num, enum hws_access_type interface_access,
257f1df9364SStefan Roese u32 if_id, int enable)
258f1df9364SStefan Roese {
259f1df9364SStefan Roese u32 data_value, pipe_enable_mask = 0;
260f1df9364SStefan Roese
261f1df9364SStefan Roese if (enable == 0) {
262f1df9364SStefan Roese pipe_enable_mask = 0;
263f1df9364SStefan Roese } else {
264f1df9364SStefan Roese if (interface_access == ACCESS_TYPE_MULTICAST)
265f1df9364SStefan Roese pipe_enable_mask = pipe_multicast_mask;
266f1df9364SStefan Roese else
267f1df9364SStefan Roese pipe_enable_mask = (1 << interface_map[if_id].pipe);
268f1df9364SStefan Roese }
269f1df9364SStefan Roese
270f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_reg_read
271f1df9364SStefan Roese (dev_num, PIPE_ENABLE_ADDR, &data_value, MASK_ALL_BITS));
272f1df9364SStefan Roese data_value = (data_value & (~0xff)) | pipe_enable_mask;
273f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_reg_write(dev_num, PIPE_ENABLE_ADDR, data_value));
274f1df9364SStefan Roese
275f1df9364SStefan Roese return MV_OK;
276f1df9364SStefan Roese }
277f1df9364SStefan Roese
278f1df9364SStefan Roese /*
279f1df9364SStefan Roese * Name: ddr3_tip_a38x_if_write.
280f1df9364SStefan Roese * Desc:
281f1df9364SStefan Roese * Args:
282f1df9364SStefan Roese * Notes:
283f1df9364SStefan Roese * Returns: MV_OK if success, other error code if fail.
284f1df9364SStefan Roese */
ddr3_tip_a38x_if_write(u8 dev_num,enum hws_access_type interface_access,u32 if_id,u32 reg_addr,u32 data_value,u32 mask)285f1df9364SStefan Roese int ddr3_tip_a38x_if_write(u8 dev_num, enum hws_access_type interface_access,
286f1df9364SStefan Roese u32 if_id, u32 reg_addr, u32 data_value,
287f1df9364SStefan Roese u32 mask)
288f1df9364SStefan Roese {
289f1df9364SStefan Roese u32 ui_data_read;
290f1df9364SStefan Roese
291f1df9364SStefan Roese if (mask != MASK_ALL_BITS) {
292f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_read
293f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, reg_addr,
294f1df9364SStefan Roese &ui_data_read, MASK_ALL_BITS));
295f1df9364SStefan Roese data_value = (ui_data_read & (~mask)) | (data_value & mask);
296f1df9364SStefan Roese }
297f1df9364SStefan Roese
298f1df9364SStefan Roese reg_write(reg_addr, data_value);
299f1df9364SStefan Roese
300f1df9364SStefan Roese return MV_OK;
301f1df9364SStefan Roese }
302f1df9364SStefan Roese
303f1df9364SStefan Roese /*
304f1df9364SStefan Roese * Name: ddr3_tip_a38x_if_read.
305f1df9364SStefan Roese * Desc:
306f1df9364SStefan Roese * Args:
307f1df9364SStefan Roese * Notes:
308f1df9364SStefan Roese * Returns: MV_OK if success, other error code if fail.
309f1df9364SStefan Roese */
ddr3_tip_a38x_if_read(u8 dev_num,enum hws_access_type interface_access,u32 if_id,u32 reg_addr,u32 * data,u32 mask)310f1df9364SStefan Roese int ddr3_tip_a38x_if_read(u8 dev_num, enum hws_access_type interface_access,
311f1df9364SStefan Roese u32 if_id, u32 reg_addr, u32 *data, u32 mask)
312f1df9364SStefan Roese {
313f1df9364SStefan Roese *data = reg_read(reg_addr) & mask;
314f1df9364SStefan Roese
315f1df9364SStefan Roese return MV_OK;
316f1df9364SStefan Roese }
317f1df9364SStefan Roese
318f1df9364SStefan Roese /*
319f1df9364SStefan Roese * Name: ddr3_tip_a38x_select_ddr_controller.
320f1df9364SStefan Roese * Desc: Enable/Disable access to Marvell's server.
321f1df9364SStefan Roese * Args: dev_num - device number
322f1df9364SStefan Roese * enable - whether to enable or disable the server
323f1df9364SStefan Roese * Notes:
324f1df9364SStefan Roese * Returns: MV_OK if success, other error code if fail.
325f1df9364SStefan Roese */
ddr3_tip_a38x_select_ddr_controller(u8 dev_num,int enable)326f1df9364SStefan Roese int ddr3_tip_a38x_select_ddr_controller(u8 dev_num, int enable)
327f1df9364SStefan Roese {
328f1df9364SStefan Roese u32 reg;
329f1df9364SStefan Roese
330f1df9364SStefan Roese reg = reg_read(CS_ENABLE_REG);
331f1df9364SStefan Roese
332f1df9364SStefan Roese if (enable)
333f1df9364SStefan Roese reg |= (1 << 6);
334f1df9364SStefan Roese else
335f1df9364SStefan Roese reg &= ~(1 << 6);
336f1df9364SStefan Roese
337f1df9364SStefan Roese reg_write(CS_ENABLE_REG, reg);
338f1df9364SStefan Roese
339f1df9364SStefan Roese return MV_OK;
340f1df9364SStefan Roese }
341f1df9364SStefan Roese
342f1df9364SStefan Roese /*
343f1df9364SStefan Roese * Name: ddr3_tip_init_a38x_silicon.
344f1df9364SStefan Roese * Desc: init Training SW DB.
345f1df9364SStefan Roese * Args:
346f1df9364SStefan Roese * Notes:
347f1df9364SStefan Roese * Returns: MV_OK if success, other error code if fail.
348f1df9364SStefan Roese */
ddr3_tip_init_a38x_silicon(u32 dev_num,u32 board_id)349f1df9364SStefan Roese static int ddr3_tip_init_a38x_silicon(u32 dev_num, u32 board_id)
350f1df9364SStefan Roese {
351f1df9364SStefan Roese struct hws_tip_config_func_db config_func;
352f1df9364SStefan Roese enum hws_ddr_freq ddr_freq;
353f1df9364SStefan Roese int status;
354f1df9364SStefan Roese struct hws_topology_map *tm = ddr3_get_topology_map();
355f1df9364SStefan Roese
356f1df9364SStefan Roese /* new read leveling version */
357f1df9364SStefan Roese config_func.tip_dunit_read_func = ddr3_tip_a38x_if_read;
358f1df9364SStefan Roese config_func.tip_dunit_write_func = ddr3_tip_a38x_if_write;
359f1df9364SStefan Roese config_func.tip_dunit_mux_select_func =
360f1df9364SStefan Roese ddr3_tip_a38x_select_ddr_controller;
361f1df9364SStefan Roese config_func.tip_get_freq_config_info_func =
362f1df9364SStefan Roese ddr3_tip_a38x_get_freq_config;
363f1df9364SStefan Roese config_func.tip_set_freq_divider_func = ddr3_tip_a38x_set_divider;
364f1df9364SStefan Roese config_func.tip_get_device_info_func = ddr3_tip_a38x_get_device_info;
365f1df9364SStefan Roese config_func.tip_get_temperature = ddr3_ctrl_get_junc_temp;
366f1df9364SStefan Roese
367f1df9364SStefan Roese ddr3_tip_init_config_func(dev_num, &config_func);
368f1df9364SStefan Roese
369f1df9364SStefan Roese ddr3_tip_register_dq_table(dev_num, dq_bit_map_2_phy_pin);
370f1df9364SStefan Roese
371f1df9364SStefan Roese #ifdef STATIC_ALGO_SUPPORT
372f1df9364SStefan Roese {
373f1df9364SStefan Roese struct hws_tip_static_config_info static_config;
374f1df9364SStefan Roese u32 board_offset =
375f1df9364SStefan Roese board_id * A38X_NUMBER_OF_INTERFACES *
376f1df9364SStefan Roese tm->num_of_bus_per_interface;
377f1df9364SStefan Roese
378f1df9364SStefan Roese static_config.silicon_delay =
379f1df9364SStefan Roese a38x_silicon_delay_offset[board_id];
380f1df9364SStefan Roese static_config.package_trace_arr =
381f1df9364SStefan Roese a38x_package_round_trip_delay_array;
382f1df9364SStefan Roese static_config.board_trace_arr =
383f1df9364SStefan Roese &a38x_board_round_trip_delay_array[board_offset];
384f1df9364SStefan Roese ddr3_tip_init_static_config_db(dev_num, &static_config);
385f1df9364SStefan Roese }
386f1df9364SStefan Roese #endif
387f1df9364SStefan Roese status = ddr3_tip_a38x_get_init_freq(dev_num, &ddr_freq);
388f1df9364SStefan Roese if (MV_OK != status) {
389f1df9364SStefan Roese DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR,
390f1df9364SStefan Roese ("DDR3 silicon get target frequency - FAILED 0x%x\n",
391f1df9364SStefan Roese status));
392f1df9364SStefan Roese return status;
393f1df9364SStefan Roese }
394f1df9364SStefan Roese
395f1df9364SStefan Roese rl_version = 1;
396f1df9364SStefan Roese mask_tune_func = (SET_LOW_FREQ_MASK_BIT |
397f1df9364SStefan Roese LOAD_PATTERN_MASK_BIT |
398f1df9364SStefan Roese SET_MEDIUM_FREQ_MASK_BIT | WRITE_LEVELING_MASK_BIT |
399f1df9364SStefan Roese /* LOAD_PATTERN_2_MASK_BIT | */
400f1df9364SStefan Roese WRITE_LEVELING_SUPP_MASK_BIT |
401f1df9364SStefan Roese READ_LEVELING_MASK_BIT |
402f1df9364SStefan Roese PBS_RX_MASK_BIT |
403f1df9364SStefan Roese PBS_TX_MASK_BIT |
404f1df9364SStefan Roese SET_TARGET_FREQ_MASK_BIT |
405f1df9364SStefan Roese WRITE_LEVELING_TF_MASK_BIT |
406f1df9364SStefan Roese WRITE_LEVELING_SUPP_TF_MASK_BIT |
407f1df9364SStefan Roese READ_LEVELING_TF_MASK_BIT |
408f1df9364SStefan Roese CENTRALIZATION_RX_MASK_BIT |
409f1df9364SStefan Roese CENTRALIZATION_TX_MASK_BIT);
410f1df9364SStefan Roese rl_mid_freq_wa = 1;
411f1df9364SStefan Roese
412f1df9364SStefan Roese if ((ddr_freq == DDR_FREQ_333) || (ddr_freq == DDR_FREQ_400)) {
413f1df9364SStefan Roese mask_tune_func = (WRITE_LEVELING_MASK_BIT |
414f1df9364SStefan Roese LOAD_PATTERN_2_MASK_BIT |
415f1df9364SStefan Roese WRITE_LEVELING_SUPP_MASK_BIT |
416f1df9364SStefan Roese READ_LEVELING_MASK_BIT |
417f1df9364SStefan Roese PBS_RX_MASK_BIT |
418f1df9364SStefan Roese PBS_TX_MASK_BIT |
419f1df9364SStefan Roese CENTRALIZATION_RX_MASK_BIT |
420f1df9364SStefan Roese CENTRALIZATION_TX_MASK_BIT);
421f1df9364SStefan Roese rl_mid_freq_wa = 0; /* WA not needed if 333/400 is TF */
422f1df9364SStefan Roese }
423f1df9364SStefan Roese
424f1df9364SStefan Roese /* Supplementary not supported for ECC modes */
425f1df9364SStefan Roese if (1 == ddr3_if_ecc_enabled()) {
426f1df9364SStefan Roese mask_tune_func &= ~WRITE_LEVELING_SUPP_TF_MASK_BIT;
427f1df9364SStefan Roese mask_tune_func &= ~WRITE_LEVELING_SUPP_MASK_BIT;
428f1df9364SStefan Roese mask_tune_func &= ~PBS_TX_MASK_BIT;
429f1df9364SStefan Roese mask_tune_func &= ~PBS_RX_MASK_BIT;
430f1df9364SStefan Roese }
431f1df9364SStefan Roese
432f1df9364SStefan Roese if (ck_delay == -1)
433f1df9364SStefan Roese ck_delay = 160;
434f1df9364SStefan Roese if (ck_delay_16 == -1)
435f1df9364SStefan Roese ck_delay_16 = 160;
436f1df9364SStefan Roese ca_delay = 0;
437f1df9364SStefan Roese delay_enable = 1;
438f1df9364SStefan Roese
439f1df9364SStefan Roese calibration_update_control = 1;
440f1df9364SStefan Roese
441f1df9364SStefan Roese init_freq = tm->interface_params[first_active_if].memory_freq;
442f1df9364SStefan Roese
443f1df9364SStefan Roese ddr3_tip_a38x_get_medium_freq(dev_num, &medium_freq);
444f1df9364SStefan Roese
445f1df9364SStefan Roese return MV_OK;
446f1df9364SStefan Roese }
447f1df9364SStefan Roese
ddr3_a38x_update_topology_map(u32 dev_num,struct hws_topology_map * tm)448f1df9364SStefan Roese int ddr3_a38x_update_topology_map(u32 dev_num, struct hws_topology_map *tm)
449f1df9364SStefan Roese {
450f1df9364SStefan Roese u32 if_id = 0;
451f1df9364SStefan Roese enum hws_ddr_freq freq;
452f1df9364SStefan Roese
453f1df9364SStefan Roese ddr3_tip_a38x_get_init_freq(dev_num, &freq);
454f1df9364SStefan Roese tm->interface_params[if_id].memory_freq = freq;
455f1df9364SStefan Roese
456f1df9364SStefan Roese /*
457f1df9364SStefan Roese * re-calc topology parameters according to topology updates
458f1df9364SStefan Roese * (if needed)
459f1df9364SStefan Roese */
460f1df9364SStefan Roese CHECK_STATUS(hws_ddr3_tip_load_topology_map(dev_num, tm));
461f1df9364SStefan Roese
462f1df9364SStefan Roese return MV_OK;
463f1df9364SStefan Roese }
464f1df9364SStefan Roese
ddr3_tip_init_a38x(u32 dev_num,u32 board_id)465f1df9364SStefan Roese int ddr3_tip_init_a38x(u32 dev_num, u32 board_id)
466f1df9364SStefan Roese {
467f1df9364SStefan Roese struct hws_topology_map *tm = ddr3_get_topology_map();
468f1df9364SStefan Roese
469f1df9364SStefan Roese if (NULL == tm)
470f1df9364SStefan Roese return MV_FAIL;
471f1df9364SStefan Roese
472f1df9364SStefan Roese ddr3_a38x_update_topology_map(dev_num, tm);
473f1df9364SStefan Roese ddr3_tip_init_a38x_silicon(dev_num, board_id);
474f1df9364SStefan Roese
475f1df9364SStefan Roese return MV_OK;
476f1df9364SStefan Roese }
477f1df9364SStefan Roese
ddr3_tip_a38x_get_init_freq(int dev_num,enum hws_ddr_freq * freq)478f1df9364SStefan Roese int ddr3_tip_a38x_get_init_freq(int dev_num, enum hws_ddr_freq *freq)
479f1df9364SStefan Roese {
480f1df9364SStefan Roese u32 reg;
481f1df9364SStefan Roese
482f1df9364SStefan Roese /* Read sample at reset setting */
483f1df9364SStefan Roese reg = (reg_read(REG_DEVICE_SAR1_ADDR) >>
484f1df9364SStefan Roese RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) &
485f1df9364SStefan Roese RST2_CPU_DDR_CLOCK_SELECT_IN_MASK;
486f1df9364SStefan Roese switch (reg) {
487f1df9364SStefan Roese case 0x0:
488f1df9364SStefan Roese case 0x1:
489f1df9364SStefan Roese *freq = DDR_FREQ_333;
490f1df9364SStefan Roese break;
491f1df9364SStefan Roese case 0x2:
492f1df9364SStefan Roese case 0x3:
493f1df9364SStefan Roese *freq = DDR_FREQ_400;
494f1df9364SStefan Roese break;
495f1df9364SStefan Roese case 0x4:
496f1df9364SStefan Roese case 0xd:
497f1df9364SStefan Roese *freq = DDR_FREQ_533;
498f1df9364SStefan Roese break;
499f1df9364SStefan Roese case 0x6:
500f1df9364SStefan Roese *freq = DDR_FREQ_600;
501f1df9364SStefan Roese break;
502f1df9364SStefan Roese case 0x8:
503f1df9364SStefan Roese case 0x11:
504f1df9364SStefan Roese case 0x14:
505f1df9364SStefan Roese *freq = DDR_FREQ_667;
506f1df9364SStefan Roese break;
507f1df9364SStefan Roese case 0xc:
508f1df9364SStefan Roese case 0x15:
509f1df9364SStefan Roese case 0x1b:
510f1df9364SStefan Roese *freq = DDR_FREQ_800;
511f1df9364SStefan Roese break;
512f1df9364SStefan Roese case 0x10:
513f1df9364SStefan Roese *freq = DDR_FREQ_933;
514f1df9364SStefan Roese break;
515f1df9364SStefan Roese case 0x12:
516f1df9364SStefan Roese *freq = DDR_FREQ_900;
517f1df9364SStefan Roese break;
518f1df9364SStefan Roese case 0x13:
519f1df9364SStefan Roese *freq = DDR_FREQ_900;
520f1df9364SStefan Roese break;
521f1df9364SStefan Roese default:
522f1df9364SStefan Roese *freq = 0;
523f1df9364SStefan Roese return MV_NOT_SUPPORTED;
524f1df9364SStefan Roese }
525f1df9364SStefan Roese
526f1df9364SStefan Roese return MV_OK;
527f1df9364SStefan Roese }
528f1df9364SStefan Roese
ddr3_tip_a38x_get_medium_freq(int dev_num,enum hws_ddr_freq * freq)529f1df9364SStefan Roese int ddr3_tip_a38x_get_medium_freq(int dev_num, enum hws_ddr_freq *freq)
530f1df9364SStefan Roese {
531f1df9364SStefan Roese u32 reg;
532f1df9364SStefan Roese
533f1df9364SStefan Roese /* Read sample at reset setting */
534f1df9364SStefan Roese reg = (reg_read(REG_DEVICE_SAR1_ADDR) >>
535f1df9364SStefan Roese RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) &
536f1df9364SStefan Roese RST2_CPU_DDR_CLOCK_SELECT_IN_MASK;
537f1df9364SStefan Roese switch (reg) {
538f1df9364SStefan Roese case 0x0:
539f1df9364SStefan Roese case 0x1:
540f1df9364SStefan Roese /* Medium is same as TF to run PBS in this freq */
541f1df9364SStefan Roese *freq = DDR_FREQ_333;
542f1df9364SStefan Roese break;
543f1df9364SStefan Roese case 0x2:
544f1df9364SStefan Roese case 0x3:
545f1df9364SStefan Roese /* Medium is same as TF to run PBS in this freq */
546f1df9364SStefan Roese *freq = DDR_FREQ_400;
547f1df9364SStefan Roese break;
548f1df9364SStefan Roese case 0x4:
549f1df9364SStefan Roese case 0xd:
550f1df9364SStefan Roese *freq = DDR_FREQ_533;
551f1df9364SStefan Roese break;
552f1df9364SStefan Roese case 0x8:
553f1df9364SStefan Roese case 0x11:
554f1df9364SStefan Roese case 0x14:
555f1df9364SStefan Roese *freq = DDR_FREQ_333;
556f1df9364SStefan Roese break;
557f1df9364SStefan Roese case 0xc:
558f1df9364SStefan Roese case 0x15:
559f1df9364SStefan Roese case 0x1b:
560f1df9364SStefan Roese *freq = DDR_FREQ_400;
561f1df9364SStefan Roese break;
562f1df9364SStefan Roese case 0x6:
563f1df9364SStefan Roese *freq = DDR_FREQ_300;
564f1df9364SStefan Roese break;
565f1df9364SStefan Roese case 0x12:
566f1df9364SStefan Roese *freq = DDR_FREQ_360;
567f1df9364SStefan Roese break;
568f1df9364SStefan Roese case 0x13:
569f1df9364SStefan Roese *freq = DDR_FREQ_400;
570f1df9364SStefan Roese break;
571f1df9364SStefan Roese default:
572f1df9364SStefan Roese *freq = 0;
573f1df9364SStefan Roese return MV_NOT_SUPPORTED;
574f1df9364SStefan Roese }
575f1df9364SStefan Roese
576f1df9364SStefan Roese return MV_OK;
577f1df9364SStefan Roese }
578f1df9364SStefan Roese
ddr3_tip_get_init_freq(void)579f1df9364SStefan Roese u32 ddr3_tip_get_init_freq(void)
580f1df9364SStefan Roese {
581f1df9364SStefan Roese enum hws_ddr_freq freq;
582f1df9364SStefan Roese
583f1df9364SStefan Roese ddr3_tip_a38x_get_init_freq(0, &freq);
584f1df9364SStefan Roese
585f1df9364SStefan Roese return freq;
586f1df9364SStefan Roese }
587f1df9364SStefan Roese
ddr3_tip_a38x_set_divider(u8 dev_num,u32 if_id,enum hws_ddr_freq frequency)588f1df9364SStefan Roese static int ddr3_tip_a38x_set_divider(u8 dev_num, u32 if_id,
589f1df9364SStefan Roese enum hws_ddr_freq frequency)
590f1df9364SStefan Roese {
591f1df9364SStefan Roese u32 divider = 0;
592f1df9364SStefan Roese u32 sar_val;
593f1df9364SStefan Roese
594f1df9364SStefan Roese if (if_id != 0) {
595f1df9364SStefan Roese DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR,
596f1df9364SStefan Roese ("A38x does not support interface 0x%x\n",
597f1df9364SStefan Roese if_id));
598f1df9364SStefan Roese return MV_BAD_PARAM;
599f1df9364SStefan Roese }
600f1df9364SStefan Roese
601f1df9364SStefan Roese /* get VCO freq index */
602f1df9364SStefan Roese sar_val = (reg_read(REG_DEVICE_SAR1_ADDR) >>
603f1df9364SStefan Roese RST2_CPU_DDR_CLOCK_SELECT_IN_OFFSET) &
604f1df9364SStefan Roese RST2_CPU_DDR_CLOCK_SELECT_IN_MASK;
605f1df9364SStefan Roese divider = a38x_vco_freq_per_sar[sar_val] / freq_val[frequency];
606f1df9364SStefan Roese
607f1df9364SStefan Roese /* Set Sync mode */
608f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
609f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x20220, 0x0,
610f1df9364SStefan Roese 0x1000));
611f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
612f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe42f4, 0x0,
613f1df9364SStefan Roese 0x200));
614f1df9364SStefan Roese
615f1df9364SStefan Roese /* cpupll_clkdiv_reset_mask */
616f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
617f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4264, 0x1f,
618f1df9364SStefan Roese 0xff));
619f1df9364SStefan Roese
620f1df9364SStefan Roese /* cpupll_clkdiv_reload_smooth */
621f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
622f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4260,
623f1df9364SStefan Roese (0x2 << 8), (0xff << 8)));
624f1df9364SStefan Roese
625f1df9364SStefan Roese /* cpupll_clkdiv_relax_en */
626f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
627f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4260,
628f1df9364SStefan Roese (0x2 << 24), (0xff << 24)));
629f1df9364SStefan Roese
630f1df9364SStefan Roese /* write the divider */
631f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
632f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4268,
633f1df9364SStefan Roese (divider << 8), (0x3f << 8)));
634f1df9364SStefan Roese
635f1df9364SStefan Roese /* set cpupll_clkdiv_reload_ratio */
636f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
637f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4264,
638f1df9364SStefan Roese (1 << 8), (1 << 8)));
639f1df9364SStefan Roese
640f1df9364SStefan Roese /* undet cpupll_clkdiv_reload_ratio */
641f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
642f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4264, 0,
643f1df9364SStefan Roese (1 << 8)));
644f1df9364SStefan Roese
645f1df9364SStefan Roese /* clear cpupll_clkdiv_reload_force */
646f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
647f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4260, 0,
648f1df9364SStefan Roese (0xff << 8)));
649f1df9364SStefan Roese
650f1df9364SStefan Roese /* clear cpupll_clkdiv_relax_en */
651f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
652f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4260, 0,
653f1df9364SStefan Roese (0xff << 24)));
654f1df9364SStefan Roese
655f1df9364SStefan Roese /* clear cpupll_clkdiv_reset_mask */
656f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
657f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0xe4264, 0,
658f1df9364SStefan Roese 0xff));
659f1df9364SStefan Roese
660f1df9364SStefan Roese /* Dunit training clock + 1:1 mode */
661f1df9364SStefan Roese if ((frequency == DDR_FREQ_LOW_FREQ) || (freq_val[frequency] <= 400)) {
662f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
663f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x18488,
664f1df9364SStefan Roese (1 << 16), (1 << 16)));
665f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
666f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1524,
667f1df9364SStefan Roese (0 << 15), (1 << 15)));
668f1df9364SStefan Roese } else {
669f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
670f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x18488,
671f1df9364SStefan Roese 0, (1 << 16)));
672f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_a38x_if_write
673f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1524,
674f1df9364SStefan Roese (1 << 15), (1 << 15)));
675f1df9364SStefan Roese }
676f1df9364SStefan Roese
677f1df9364SStefan Roese return MV_OK;
678f1df9364SStefan Roese }
679f1df9364SStefan Roese
680f1df9364SStefan Roese /*
681f1df9364SStefan Roese * external read from memory
682f1df9364SStefan Roese */
ddr3_tip_ext_read(u32 dev_num,u32 if_id,u32 reg_addr,u32 num_of_bursts,u32 * data)683f1df9364SStefan Roese int ddr3_tip_ext_read(u32 dev_num, u32 if_id, u32 reg_addr,
684f1df9364SStefan Roese u32 num_of_bursts, u32 *data)
685f1df9364SStefan Roese {
686f1df9364SStefan Roese u32 burst_num;
687f1df9364SStefan Roese
688f1df9364SStefan Roese for (burst_num = 0; burst_num < num_of_bursts * 8; burst_num++)
689f1df9364SStefan Roese data[burst_num] = readl(reg_addr + 4 * burst_num);
690f1df9364SStefan Roese
691f1df9364SStefan Roese return MV_OK;
692f1df9364SStefan Roese }
693f1df9364SStefan Roese
694f1df9364SStefan Roese /*
695f1df9364SStefan Roese * external write to memory
696f1df9364SStefan Roese */
ddr3_tip_ext_write(u32 dev_num,u32 if_id,u32 reg_addr,u32 num_of_bursts,u32 * data)697f1df9364SStefan Roese int ddr3_tip_ext_write(u32 dev_num, u32 if_id, u32 reg_addr,
698f1df9364SStefan Roese u32 num_of_bursts, u32 *data) {
699f1df9364SStefan Roese u32 burst_num;
700f1df9364SStefan Roese
701f1df9364SStefan Roese for (burst_num = 0; burst_num < num_of_bursts * 8; burst_num++)
702f1df9364SStefan Roese writel(data[burst_num], reg_addr + 4 * burst_num);
703f1df9364SStefan Roese
704f1df9364SStefan Roese return MV_OK;
705f1df9364SStefan Roese }
706f1df9364SStefan Roese
ddr3_silicon_pre_init(void)707f1df9364SStefan Roese int ddr3_silicon_pre_init(void)
708f1df9364SStefan Roese {
709*a4ca3799SMasahiro Yamada return ddr3_silicon_init();
710f1df9364SStefan Roese }
711f1df9364SStefan Roese
ddr3_post_run_alg(void)712f1df9364SStefan Roese int ddr3_post_run_alg(void)
713f1df9364SStefan Roese {
714f1df9364SStefan Roese return MV_OK;
715f1df9364SStefan Roese }
716f1df9364SStefan Roese
ddr3_silicon_post_init(void)717f1df9364SStefan Roese int ddr3_silicon_post_init(void)
718f1df9364SStefan Roese {
719f1df9364SStefan Roese struct hws_topology_map *tm = ddr3_get_topology_map();
720f1df9364SStefan Roese
721f1df9364SStefan Roese /* Set half bus width */
722f1df9364SStefan Roese if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask)) {
723f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_if_write
724f1df9364SStefan Roese (0, ACCESS_TYPE_UNICAST, PARAM_NOT_CARE,
725f1df9364SStefan Roese REG_SDRAM_CONFIG_ADDR, 0x0, 0x8000));
726f1df9364SStefan Roese }
727f1df9364SStefan Roese
728f1df9364SStefan Roese return MV_OK;
729f1df9364SStefan Roese }
730f1df9364SStefan Roese
ddr3_tip_a38x_get_device_info(u8 dev_num,struct ddr3_device_info * info_ptr)731f1df9364SStefan Roese int ddr3_tip_a38x_get_device_info(u8 dev_num, struct ddr3_device_info *info_ptr)
732f1df9364SStefan Roese {
733f1df9364SStefan Roese info_ptr->device_id = 0x6800;
734f1df9364SStefan Roese info_ptr->ck_delay = ck_delay;
735f1df9364SStefan Roese
736f1df9364SStefan Roese return MV_OK;
737f1df9364SStefan Roese }
738