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