xref: /rk3399_ARM-atf/plat/marvell/armada/a8k/common/plat_ble_setup.c (revision 34d483565078e28b5a31995d9030787b14ad3801)
1 /*
2  * Copyright (C) 2018 Marvell International Ltd.
3  *
4  * SPDX-License-Identifier:     BSD-3-Clause
5  * https://spdx.org/licenses
6  */
7 
8 #include <common/debug.h>
9 #include <drivers/marvell/ap807_clocks_init.h>
10 #include <drivers/marvell/aro.h>
11 #include <drivers/marvell/ccu.h>
12 #include <drivers/marvell/io_win.h>
13 #include <drivers/marvell/mochi/ap_setup.h>
14 #include <drivers/marvell/mochi/cp110_setup.h>
15 
16 #include <armada_common.h>
17 #include <mv_ddr_if.h>
18 #include <mvebu_def.h>
19 #include <plat_marvell.h>
20 
21 /* Register for skip image use */
22 #define SCRATCH_PAD_REG2		0xF06F00A8
23 #define SCRATCH_PAD_SKIP_VAL		0x01
24 #define NUM_OF_GPIO_PER_REG 32
25 
26 #define MMAP_SAVE_AND_CONFIG		0
27 #define MMAP_RESTORE_SAVED		1
28 
29 /* SAR clock settings */
30 #define MVEBU_AP_GEN_MGMT_BASE		(MVEBU_RFU_BASE + 0x8000)
31 #define MVEBU_AP_SAR_REG_BASE(r)	(MVEBU_AP_GEN_MGMT_BASE + 0x200 +\
32 								((r) << 2))
33 
34 #define SAR_CLOCK_FREQ_MODE_OFFSET	(0)
35 #define SAR_CLOCK_FREQ_MODE_MASK	(0x1f << SAR_CLOCK_FREQ_MODE_OFFSET)
36 #define SAR_PIDI_LOW_SPEED_OFFSET	(20)
37 #define SAR_PIDI_LOW_SPEED_MASK		(1 << SAR_PIDI_LOW_SPEED_OFFSET)
38 #define SAR_PIDI_LOW_SPEED_SHIFT	(15)
39 #define SAR_PIDI_LOW_SPEED_SET		(1 << SAR_PIDI_LOW_SPEED_SHIFT)
40 
41 #define FREQ_MODE_AP_SAR_REG_NUM	(0)
42 #define SAR_CLOCK_FREQ_MODE(v)		(((v) & SAR_CLOCK_FREQ_MODE_MASK) >> \
43 					SAR_CLOCK_FREQ_MODE_OFFSET)
44 
45 #define AVS_I2C_EEPROM_ADDR		0x57	/* EEPROM */
46 #define AVS_EN_CTRL_REG			(MVEBU_AP_GEN_MGMT_BASE + 0x130)
47 #define AVS_ENABLE_OFFSET		(0)
48 #define AVS_SOFT_RESET_OFFSET		(2)
49 #define AVS_TARGET_DELTA_OFFSET		(21)
50 
51 #ifndef MVEBU_SOC_AP807
52 	/* AP806 SVC bits */
53 	#define AVS_LOW_VDD_LIMIT_OFFSET	(4)
54 	#define AVS_HIGH_VDD_LIMIT_OFFSET	(12)
55 	#define AVS_VDD_LOW_LIMIT_MASK	(0xFF << AVS_LOW_VDD_LIMIT_OFFSET)
56 	#define AVS_VDD_HIGH_LIMIT_MASK	(0xFF << AVS_HIGH_VDD_LIMIT_OFFSET)
57 #else
58 	/* AP807 SVC bits */
59 	#define AVS_LOW_VDD_LIMIT_OFFSET	(3)
60 	#define AVS_HIGH_VDD_LIMIT_OFFSET	(13)
61 	#define AVS_VDD_LOW_LIMIT_MASK	(0x3FF << AVS_LOW_VDD_LIMIT_OFFSET)
62 	#define AVS_VDD_HIGH_LIMIT_MASK	(0x3FF << AVS_HIGH_VDD_LIMIT_OFFSET)
63 #endif
64 
65 /* VDD limit is 0.9V for A70x0 @ CPU frequency < 1600MHz */
66 #define AVS_A7K_LOW_CLK_VALUE		((0x80 << AVS_TARGET_DELTA_OFFSET) | \
67 					 (0x1A << AVS_HIGH_VDD_LIMIT_OFFSET) | \
68 					 (0x1A << AVS_LOW_VDD_LIMIT_OFFSET) | \
69 					 (0x1 << AVS_SOFT_RESET_OFFSET) | \
70 					 (0x1 << AVS_ENABLE_OFFSET))
71 /* VDD limit is 1.0V for all A80x0 devices */
72 #define AVS_A8K_CLK_VALUE		((0x80 << AVS_TARGET_DELTA_OFFSET) | \
73 					 (0x24 << AVS_HIGH_VDD_LIMIT_OFFSET) | \
74 					 (0x24 << AVS_LOW_VDD_LIMIT_OFFSET) | \
75 					 (0x1 << AVS_SOFT_RESET_OFFSET) | \
76 					 (0x1 << AVS_ENABLE_OFFSET))
77 
78 /* VDD is 0.88V for 2GHz clock on CN913x devices */
79 #define AVS_AP807_CLK_VALUE		((0x80UL << 24) | \
80 					 (0x2dc << 13) | \
81 					 (0x2dc << 3) | \
82 					 (0x1 << AVS_SOFT_RESET_OFFSET) | \
83 					 (0x1 << AVS_ENABLE_OFFSET))
84 
85 #define MVEBU_AP_EFUSE_SRV_CTRL_REG	(MVEBU_AP_GEN_MGMT_BASE + 0x8)
86 #define EFUSE_SRV_CTRL_LD_SELECT_OFFS	6
87 #define EFUSE_SRV_CTRL_LD_SEL_USER_MASK	(1 << EFUSE_SRV_CTRL_LD_SELECT_OFFS)
88 
89 
90 /*
91  * - Identification information in the LD-0 eFuse:
92  *	DRO:           LD0[74:65] - Not used by the SW
93  *	Revision:      LD0[78:75] - Not used by the SW
94  *	Bin:           LD0[80:79] - Not used by the SW
95  *	SW Revision:   LD0[115:113]
96  *	Cluster 1 PWR: LD0[193] - if set to 1, power down CPU Cluster-1
97  *				  resulting in 2 CPUs active only (7020)
98  */
99 #define MVEBU_AP_LD_EFUSE_BASE		(MVEBU_AP_GEN_MGMT_BASE + 0xF00)
100 /* Bits [94:63] - 32 data bits total */
101 #define MVEBU_AP_LD0_94_63_EFUSE_OFFS	(MVEBU_AP_LD_EFUSE_BASE + 0x8)
102 /* Bits [125:95] - 31 data bits total, 32nd bit is parity for bits [125:63] */
103 #define MVEBU_AP_LD0_125_95_EFUSE_OFFS	(MVEBU_AP_LD_EFUSE_BASE + 0xC)
104 /* Bits [220:189] - 32 data bits total */
105 #define MVEBU_AP_LD0_220_189_EFUSE_OFFS	(MVEBU_AP_LD_EFUSE_BASE + 0x18)
106 /* Offsets for the above 2 fields combined into single 64-bit value [125:63] */
107 #define EFUSE_AP_LD0_DRO_OFFS		2		/* LD0[74:65] */
108 #define EFUSE_AP_LD0_DRO_MASK		0x3FF
109 #define EFUSE_AP_LD0_REVID_OFFS		12		/* LD0[78:75] */
110 #define EFUSE_AP_LD0_REVID_MASK		0xF
111 #define EFUSE_AP_LD0_BIN_OFFS		16		/* LD0[80:79] */
112 #define EFUSE_AP_LD0_BIN_MASK		0x3
113 #define EFUSE_AP_LD0_SWREV_MASK		0x7
114 
115 #ifndef MVEBU_SOC_AP807
116 	/* AP806 AVS work points in the LD0 eFuse
117 	 * SVC1 work point:     LD0[88:81]
118 	 * SVC2 work point:     LD0[96:89]
119 	 * SVC3 work point:     LD0[104:97]
120 	 * SVC4 work point:     LD0[112:105]
121 	 */
122 	#define EFUSE_AP_LD0_SVC1_OFFS		18	/* LD0[88:81] */
123 	#define EFUSE_AP_LD0_SVC2_OFFS		26	/* LD0[96:89] */
124 	#define EFUSE_AP_LD0_SVC3_OFFS		34	/* LD0[104:97] */
125 	#define EFUSE_AP_LD0_WP_MASK		0xFF
126 	#define EFUSE_AP_LD0_SWREV_OFFS		50	/* LD0[115:113] */
127 #else
128 	/* AP807 AVS work points in the LD0 eFuse
129 	 * SVC1 work point:     LD0[91:81]
130 	 * SVC2 work point:     LD0[102:92]
131 	 * SVC3 work point:     LD0[113:103]
132 	 */
133 	#define EFUSE_AP_LD0_SVC1_OFFS		18	/* LD0[91:81] */
134 	#define EFUSE_AP_LD0_SVC2_OFFS		29	/* LD0[102:92] */
135 	#define EFUSE_AP_LD0_SVC3_OFFS		40	/* LD0[113:103] */
136 	#define EFUSE_AP_LD0_WP_MASK		0x7FF	/* 10 data,1 parity */
137 	#define EFUSE_AP_LD0_SWREV_OFFS		51	/* LD0[116:114] */
138 #endif
139 
140 #define EFUSE_AP_LD0_SVC4_OFFS			42	/* LD0[112:105] */
141 
142 #define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS		4
143 
144 #if MARVELL_SVC_TEST
145 #define MVEBU_CP_MPP_CTRL37_OFFS	20
146 #define MVEBU_CP_MPP_CTRL38_OFFS	24
147 #define MVEBU_CP_MPP_I2C_FUNC		2
148 #define MVEBU_MPP_CTRL_MASK		0xf
149 #endif
150 
151 /* Return the AP revision of the chip */
152 static unsigned int ble_get_ap_type(void)
153 {
154 	unsigned int chip_rev_id;
155 
156 	chip_rev_id = mmio_read_32(MVEBU_CSS_GWD_CTRL_IIDR2_REG);
157 	chip_rev_id = ((chip_rev_id & GWD_IIDR2_CHIP_ID_MASK) >>
158 			GWD_IIDR2_CHIP_ID_OFFSET);
159 
160 	return chip_rev_id;
161 }
162 
163 /******************************************************************************
164  * The routine allows to save the CCU and IO windows configuration during DRAM
165  * setup and restore them afterwards before exiting the BLE stage.
166  * Such window configuration is required since not all default settings coming
167  * from the HW and the BootROM allow access to peripherals connected to
168  * all available CPn components.
169  * For instance, when the boot device is located on CP0, the IO window to CP1
170  * is not opened automatically by the HW and if the DRAM SPD is located on CP1
171  * i2c channel, it cannot be read at BLE stage.
172  * Therefore the DRAM init procedure have to provide access to all available
173  * CPn peripherals during the BLE stage by setting the CCU IO window to all
174  * CPnph addresses and by enabling the IO windows accordingly.
175  * Additionally this function configures the CCU GCR to DRAM, which allows
176  * usage or more than 4GB DRAM as it configured by the default CCU DRAM window.
177  *
178  * IN:
179  *	MMAP_SAVE_AND_CONFIG	- save the existing configuration and update it
180  *	MMAP_RESTORE_SAVED	- restore saved configuration
181  * OUT:
182  *	NONE
183  ****************************************************************************
184  */
185 static void ble_plat_mmap_config(int restore)
186 {
187 	if (restore == MMAP_RESTORE_SAVED) {
188 		/* Restore all orig. settings that were modified by BLE stage */
189 		ccu_restore_win_all(MVEBU_AP0);
190 		/* Restore CCU */
191 		iow_restore_win_all(MVEBU_AP0);
192 		return;
193 	}
194 
195 	/* Store original values */
196 	ccu_save_win_all(MVEBU_AP0);
197 	/* Save CCU */
198 	iow_save_win_all(MVEBU_AP0);
199 
200 	init_ccu(MVEBU_AP0);
201 	/* The configuration saved, now all the changes can be done */
202 	init_io_win(MVEBU_AP0);
203 }
204 
205 /****************************************************************************
206  * Setup Adaptive Voltage Switching - this is required for some platforms
207  ****************************************************************************
208  */
209 #if !MARVELL_SVC_TEST
210 static void ble_plat_avs_config(void)
211 {
212 	uint32_t freq_mode, device_id;
213 	uint32_t avs_val = 0;
214 
215 	freq_mode =
216 		SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
217 						 FREQ_MODE_AP_SAR_REG_NUM)));
218 	/* Check which SoC is running and act accordingly */
219 	if (ble_get_ap_type() == CHIP_ID_AP807) {
220 
221 		avs_val = AVS_AP807_CLK_VALUE;
222 
223 	} else {
224 		/* Check which SoC is running and act accordingly */
225 		device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
226 		switch (device_id) {
227 		case MVEBU_80X0_DEV_ID:
228 		case MVEBU_80X0_CP115_DEV_ID:
229 			/* Always fix the default AVS value on A80x0 */
230 			avs_val = AVS_A8K_CLK_VALUE;
231 			break;
232 		case MVEBU_70X0_DEV_ID:
233 		case MVEBU_70X0_CP115_DEV_ID:
234 			/* Fix AVS for CPU clocks lower than 1600MHz on A70x0 */
235 			if ((freq_mode > CPU_1600_DDR_900_RCLK_900_2) &&
236 			    (freq_mode < CPU_DDR_RCLK_INVALID))
237 				avs_val = AVS_A7K_LOW_CLK_VALUE;
238 			break;
239 		default:
240 			ERROR("Unsupported Device ID 0x%x\n", device_id);
241 			return;
242 		}
243 	}
244 
245 	if (avs_val) {
246 		VERBOSE("AVS: Setting AVS CTRL to 0x%x\n", avs_val);
247 		mmio_write_32(AVS_EN_CTRL_REG, avs_val);
248 	}
249 }
250 #endif
251 /******************************************************************************
252  * Update or override current AVS work point value using data stored in EEPROM
253  * This is only required by QA/validation flows and activated by
254  * MARVELL_SVC_TEST flag.
255  *
256  * The function is expected to be called twice.
257  *
258  * First time with AVS value of 0 for testing if the EEPROM requests completely
259  * override the AVS value and bypass the eFuse test
260  *
261  * Second time - with non-zero AVS value obtained from eFuses as an input.
262  * In this case the EEPROM may contain AVS correction value (either positive
263  * or negative) that is added to the input AVS value and returned back for
264  * further processing.
265  ******************************************************************************
266  */
267 static uint32_t avs_update_from_eeprom(uint32_t avs_workpoint)
268 {
269 	uint32_t new_wp = avs_workpoint;
270 #if MARVELL_SVC_TEST
271 	/* ---------------------------------------------------------------------
272 	 * EEPROM  |  Data description (avs_step)
273 	 * address |
274 	 * ---------------------------------------------------------------------
275 	 * 0x120   | AVS workpoint correction value
276 	 *         | if not 0 and not 0xff, correct the AVS taken from eFuse
277 	 *         | by the number of steps indicated by bit[6:0]
278 	 *         | bit[7] defines correction direction.
279 	 *         | If bit[7]=1, add the value from bit[6:0] to AVS workpoint,
280 	 *         | othervise substruct this value from AVS workpoint.
281 	 * ---------------------------------------------------------------------
282 	 * 0x121   | AVS workpoint override value
283 	 *         | Override the AVS workpoint with the value stored in this
284 	 *         | byte. When running on AP806, the AVS workpoint is 7 bits
285 	 *         | wide and override value is valid when bit[6:0] holds
286 	 *         | value greater than zero and smaller than 0x33.
287 	 *         | When running on AP807, the AVS workpoint is 10 bits wide.
288 	 *         | Additional 2 MSB bits are supplied by EEPROM byte 0x122.
289 	 *         | AVS override value is valid when byte @ 0x121 and bit[1:0]
290 	 *         | of byte @ 0x122 combined have non-zero value.
291 	 * ---------------------------------------------------------------------
292 	 * 0x122   | Extended AVS workpoint override value
293 	 *         | Valid only for AP807 platforms and must be less than 0x4
294 	 * ---------------------------------------------------------------------
295 	 */
296 	static uint8_t  avs_step[3] = {0};
297 	uintptr_t reg;
298 	uint32_t val;
299 	unsigned int ap_type = ble_get_ap_type();
300 
301 	/* Always happens on second call to this function */
302 	if (avs_workpoint != 0) {
303 		/* Get correction steps from the EEPROM */
304 		if ((avs_step[0] != 0) && (avs_step[0] != 0xff)) {
305 			NOTICE("AVS request to step %s by 0x%x from old 0x%x\n",
306 				avs_step[0] & 0x80 ? "DOWN" : "UP",
307 				avs_step[0] & 0x7f, new_wp);
308 			if (avs_step[0] & 0x80)
309 				new_wp -= avs_step[0] & 0x7f;
310 			else
311 				new_wp += avs_step[0] & 0x7f;
312 		}
313 
314 		return new_wp;
315 	}
316 
317 	/* AVS values are located in EEPROM
318 	 * at CP0 i2c bus #0, device 0x57 offset 0x120
319 	 * The SDA and SCK pins of CP0 i2c-0: MPP[38:37], i2c function 0x2.
320 	 */
321 	reg = MVEBU_CP_MPP_REGS(0, 4);
322 	val = mmio_read_32(reg);
323 	val &= ~((MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL37_OFFS) |
324 		 (MVEBU_MPP_CTRL_MASK << MVEBU_CP_MPP_CTRL38_OFFS));
325 	val |= (MVEBU_CP_MPP_I2C_FUNC << MVEBU_CP_MPP_CTRL37_OFFS) |
326 		(MVEBU_CP_MPP_I2C_FUNC << MVEBU_CP_MPP_CTRL38_OFFS);
327 	mmio_write_32(reg, val);
328 
329 	/* Init CP0 i2c-0 */
330 	i2c_init((void *)(MVEBU_CP0_I2C_BASE));
331 
332 	/* Read EEPROM only once at the fist call! */
333 	i2c_read(AVS_I2C_EEPROM_ADDR, 0x120, 2, avs_step, 3);
334 	NOTICE("== SVC test build ==\n");
335 	NOTICE("EEPROM holds values 0x%x, 0x%x and 0x%x\n",
336 		avs_step[0], avs_step[1], avs_step[2]);
337 
338 	/* Override the AVS value? */
339 	if ((ap_type != CHIP_ID_AP807) && (avs_step[1] < 0x33)) {
340 		/* AP806 - AVS is 7 bits */
341 		new_wp = avs_step[1];
342 
343 	} else if (ap_type == CHIP_ID_AP807 && (avs_step[2] < 0x4)) {
344 		/* AP807 - AVS is 10 bits */
345 		new_wp = avs_step[2];
346 		new_wp <<= 8;
347 		new_wp |= avs_step[1];
348 	}
349 
350 	if (new_wp == 0)
351 		NOTICE("Ignore BAD AVS Override value in EEPROM!\n");
352 	else
353 		NOTICE("Override AVS by EEPROM value 0x%x\n", new_wp);
354 #endif /* MARVELL_SVC_TEST */
355 	return new_wp;
356 }
357 
358 /****************************************************************************
359  * SVC flow - v0.10
360  * The feature is intended to configure AVS value according to eFuse values
361  * that are burned individually for each SoC during the test process.
362  * Primary AVS value is stored in HD efuse and processed on power on
363  * by the HW engine
364  * Secondary AVS value is located in LD efuse and contains 4 work points for
365  * various CPU frequencies.
366  * The Secondary AVS value is only taken into account if the SW Revision stored
367  * in the efuse is greater than 0 and the CPU is running in a certain speed.
368  ****************************************************************************
369  */
370 static void ble_plat_svc_config(void)
371 {
372 	uint32_t reg_val, avs_workpoint, freq_pidi_mode;
373 	uint64_t efuse;
374 	uint32_t device_id, single_cluster;
375 	uint16_t  svc[4], perr[4], i, sw_ver;
376 	uint8_t	 avs_data_bits, min_sw_ver, svc_fields;
377 	unsigned int ap_type;
378 
379 	/* Set access to LD0 */
380 	avs_workpoint = avs_update_from_eeprom(0);
381 	if (avs_workpoint)
382 		goto set_aws_wp;
383 
384 	/* Set access to LD0 */
385 	reg_val = mmio_read_32(MVEBU_AP_EFUSE_SRV_CTRL_REG);
386 	reg_val &= ~EFUSE_SRV_CTRL_LD_SELECT_OFFS;
387 	mmio_write_32(MVEBU_AP_EFUSE_SRV_CTRL_REG, reg_val);
388 
389 	/* Obtain the value of LD0[125:63] */
390 	efuse = mmio_read_32(MVEBU_AP_LD0_125_95_EFUSE_OFFS);
391 	efuse <<= 32;
392 	efuse |= mmio_read_32(MVEBU_AP_LD0_94_63_EFUSE_OFFS);
393 
394 	/* SW Revision:
395 	 * Starting from SW revision 1 the SVC flow is supported.
396 	 * SW version 0 (efuse not programmed) should follow the
397 	 * regular AVS update flow.
398 	 */
399 	sw_ver = (efuse >> EFUSE_AP_LD0_SWREV_OFFS) & EFUSE_AP_LD0_SWREV_MASK;
400 	if (sw_ver < 1) {
401 		NOTICE("SVC: SW Revision 0x%x. SVC is not supported\n", sw_ver);
402 #if MARVELL_SVC_TEST
403 		NOTICE("SVC_TEST: AVS bypassed\n");
404 
405 #else
406 		ble_plat_avs_config();
407 #endif
408 		return;
409 	}
410 
411 	/* Frequency mode from SAR */
412 	freq_pidi_mode = SAR_CLOCK_FREQ_MODE(
413 				mmio_read_32(
414 					MVEBU_AP_SAR_REG_BASE(
415 						FREQ_MODE_AP_SAR_REG_NUM)));
416 
417 	/* Decode all SVC work points */
418 	svc[0] = (efuse >> EFUSE_AP_LD0_SVC1_OFFS) & EFUSE_AP_LD0_WP_MASK;
419 	svc[1] = (efuse >> EFUSE_AP_LD0_SVC2_OFFS) & EFUSE_AP_LD0_WP_MASK;
420 	svc[2] = (efuse >> EFUSE_AP_LD0_SVC3_OFFS) & EFUSE_AP_LD0_WP_MASK;
421 
422 	/* Fetch AP type to distinguish between AP806 and AP807 */
423 	ap_type = ble_get_ap_type();
424 
425 	if (ap_type != CHIP_ID_AP807) {
426 		svc[3] = (efuse >> EFUSE_AP_LD0_SVC4_OFFS)
427 			 & EFUSE_AP_LD0_WP_MASK;
428 		INFO("SVC: Efuse WP: [0]=0x%x, [1]=0x%x, [2]=0x%x, [3]=0x%x\n",
429 		     svc[0], svc[1], svc[2], svc[3]);
430 		avs_data_bits = 7;
431 		min_sw_ver = 2; /* parity check from sw revision 2 */
432 		svc_fields = 4;
433 	} else {
434 		INFO("SVC: Efuse WP: [0]=0x%x, [1]=0x%x, [2]=0x%x\n",
435 		     svc[0], svc[1], svc[2]);
436 		avs_data_bits = 10;
437 		min_sw_ver = 1; /* parity check required from sw revision 1 */
438 		svc_fields = 3;
439 	}
440 
441 	/* Validate parity of SVC workpoint values */
442 	for (i = 0; i < svc_fields; i++) {
443 		uint8_t parity, bit;
444 		perr[i] = 0;
445 
446 		for (bit = 1, parity = (svc[i] & 1); bit < avs_data_bits; bit++)
447 			parity ^= (svc[i] >> bit) & 1;
448 
449 		/* From SW version 1 or 2 (AP806/AP807), check parity */
450 		if ((sw_ver >= min_sw_ver) &&
451 		    (parity != ((svc[i] >> avs_data_bits) & 1)))
452 			perr[i] = 1; /* register the error */
453 	}
454 
455 	single_cluster = mmio_read_32(MVEBU_AP_LD0_220_189_EFUSE_OFFS);
456 	single_cluster = (single_cluster >> EFUSE_AP_LD0_CLUSTER_DOWN_OFFS) & 1;
457 
458 	device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
459 	if (device_id == MVEBU_80X0_DEV_ID ||
460 	    device_id == MVEBU_80X0_CP115_DEV_ID) {
461 		/* A8040/A8020 */
462 		NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
463 			single_cluster == 0 ? "8040" : "8020", freq_pidi_mode);
464 		switch (freq_pidi_mode) {
465 		case CPU_1800_DDR_1050_RCLK_1050:
466 			if (perr[1])
467 				goto perror;
468 			avs_workpoint = svc[1];
469 			break;
470 		case CPU_1600_DDR_1050_RCLK_1050:
471 		case CPU_1600_DDR_900_RCLK_900_2:
472 			if (perr[2])
473 				goto perror;
474 			avs_workpoint = svc[2];
475 			break;
476 		case CPU_1300_DDR_800_RCLK_800:
477 		case CPU_1300_DDR_650_RCLK_650:
478 			if (perr[3])
479 				goto perror;
480 			avs_workpoint = svc[3];
481 			break;
482 		case CPU_2000_DDR_1200_RCLK_1200:
483 		case CPU_2000_DDR_1050_RCLK_1050:
484 		default:
485 			if (perr[0])
486 				goto perror;
487 			avs_workpoint = svc[0];
488 			break;
489 		}
490 	} else if (device_id == MVEBU_70X0_DEV_ID ||
491 		   device_id == MVEBU_70X0_CP115_DEV_ID) {
492 		/* A7040/A7020/A6040 */
493 		NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
494 			single_cluster == 0 ? "7040" : "7020", freq_pidi_mode);
495 		switch (freq_pidi_mode) {
496 		case CPU_1400_DDR_800_RCLK_800:
497 			if (single_cluster) {/* 7020 */
498 				if (perr[1])
499 					goto perror;
500 				avs_workpoint = svc[1];
501 			} else {
502 				if (perr[0])
503 					goto perror;
504 				avs_workpoint = svc[0];
505 			}
506 			break;
507 		case CPU_1200_DDR_800_RCLK_800:
508 			if (single_cluster) {/* 7020 */
509 				if (perr[2])
510 					goto perror;
511 				avs_workpoint = svc[2];
512 			} else {
513 				if (perr[1])
514 					goto perror;
515 				avs_workpoint = svc[1];
516 			}
517 			break;
518 		case CPU_800_DDR_800_RCLK_800:
519 		case CPU_1000_DDR_800_RCLK_800:
520 			if (single_cluster) {/* 7020 */
521 				if (perr[3])
522 					goto perror;
523 				avs_workpoint = svc[3];
524 			} else {
525 				if (perr[2])
526 					goto perror;
527 				avs_workpoint = svc[2];
528 			}
529 			break;
530 		case CPU_600_DDR_800_RCLK_800:
531 			if (perr[3])
532 				goto perror;
533 			avs_workpoint = svc[3]; /* Same for 6040 and 7020 */
534 			break;
535 		case CPU_1600_DDR_800_RCLK_800: /* 7020 only */
536 		default:
537 			if (single_cluster) {/* 7020 */
538 				if (perr[0])
539 					goto perror;
540 				avs_workpoint = svc[0];
541 			} else {
542 #if MARVELL_SVC_TEST
543 				reg_val = mmio_read_32(AVS_EN_CTRL_REG);
544 				avs_workpoint = (reg_val &
545 					AVS_VDD_LOW_LIMIT_MASK) >>
546 					AVS_LOW_VDD_LIMIT_OFFSET;
547 				NOTICE("7040 1600Mhz, avs = 0x%x\n",
548 					avs_workpoint);
549 #else
550 				NOTICE("SVC: AVS work point not changed\n");
551 				return;
552 #endif
553 			}
554 			break;
555 		}
556 	} else if (device_id == MVEBU_3900_DEV_ID) {
557 		NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
558 		       "3900", freq_pidi_mode);
559 		switch (freq_pidi_mode) {
560 		case CPU_1600_DDR_1200_RCLK_1200:
561 			if (perr[0])
562 				goto perror;
563 			avs_workpoint = svc[0];
564 			break;
565 		case CPU_1300_DDR_800_RCLK_800:
566 			if (perr[1])
567 				goto perror;
568 			avs_workpoint = svc[1];
569 			break;
570 		default:
571 			if (perr[0])
572 				goto perror;
573 			avs_workpoint = svc[0];
574 			break;
575 		}
576 	} else if (device_id == MVEBU_CN9130_DEV_ID) {
577 		NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
578 		       "CN913x", freq_pidi_mode);
579 		switch (freq_pidi_mode) {
580 		case CPU_2200_DDR_1200_RCLK_1200:
581 			if (perr[0])
582 				goto perror;
583 			avs_workpoint = svc[0];
584 			break;
585 		case CPU_2000_DDR_1200_RCLK_1200:
586 			if (perr[1])
587 				goto perror;
588 			avs_workpoint = svc[1];
589 			break;
590 		case CPU_1600_DDR_1200_RCLK_1200:
591 			if (perr[2])
592 				goto perror;
593 			avs_workpoint = svc[2];
594 			break;
595 		default:
596 			ERROR("SVC: Unsupported Frequency 0x%x\n",
597 				freq_pidi_mode);
598 			return;
599 
600 		}
601 	} else {
602 		ERROR("SVC: Unsupported Device ID 0x%x\n", device_id);
603 		return;
604 	}
605 
606 	/* Set AVS control if needed */
607 	if (avs_workpoint == 0) {
608 		ERROR("SVC: You are using a frequency setup which is\n");
609 		ERROR("Not supported by this device\n");
610 		ERROR("This may result in malfunction of the device\n");
611 		return;
612 	}
613 
614 	/* Remove parity bit */
615 	if (ap_type != CHIP_ID_AP807)
616 		avs_workpoint &= 0x7F;
617 	else
618 		avs_workpoint &= 0x3FF;
619 
620 	/* Update WP from EEPROM if needed */
621 	avs_workpoint = avs_update_from_eeprom(avs_workpoint);
622 
623 set_aws_wp:
624 	reg_val  = mmio_read_32(AVS_EN_CTRL_REG);
625 	NOTICE("SVC: AVS work point changed from 0x%x to 0x%x\n",
626 		(reg_val & AVS_VDD_LOW_LIMIT_MASK) >> AVS_LOW_VDD_LIMIT_OFFSET,
627 		avs_workpoint);
628 	reg_val &= ~(AVS_VDD_LOW_LIMIT_MASK | AVS_VDD_HIGH_LIMIT_MASK);
629 	reg_val |= 0x1 << AVS_ENABLE_OFFSET;
630 	reg_val |= avs_workpoint << AVS_HIGH_VDD_LIMIT_OFFSET;
631 	reg_val |= avs_workpoint << AVS_LOW_VDD_LIMIT_OFFSET;
632 	mmio_write_32(AVS_EN_CTRL_REG, reg_val);
633 	return;
634 
635 perror:
636 	ERROR("Failed SVC WP[%d] parity check!\n", i);
637 	ERROR("Ignoring the WP values\n");
638 }
639 
640 #if PLAT_RECOVERY_IMAGE_ENABLE
641 static int ble_skip_image_i2c(struct skip_image *skip_im)
642 {
643 	ERROR("skipping image using i2c is not supported\n");
644 	/* not supported */
645 	return 0;
646 }
647 
648 static int ble_skip_image_other(struct skip_image *skip_im)
649 {
650 	ERROR("implementation missing for skip image request\n");
651 	/* not supported, make your own implementation */
652 	return 0;
653 }
654 
655 static int ble_skip_image_gpio(struct skip_image *skip_im)
656 {
657 	unsigned int val;
658 	unsigned int mpp_address = 0;
659 	unsigned int offset = 0;
660 
661 	switch (skip_im->info.test.cp_ap) {
662 	case(CP):
663 		mpp_address = MVEBU_CP_GPIO_DATA_IN(skip_im->info.test.cp_index,
664 						    skip_im->info.gpio.num);
665 		if (skip_im->info.gpio.num > NUM_OF_GPIO_PER_REG)
666 			offset = skip_im->info.gpio.num - NUM_OF_GPIO_PER_REG;
667 		else
668 			offset = skip_im->info.gpio.num;
669 		break;
670 	case(AP):
671 		mpp_address = MVEBU_AP_GPIO_DATA_IN;
672 		offset = skip_im->info.gpio.num;
673 		break;
674 	}
675 
676 	val = mmio_read_32(mpp_address);
677 	val &= (1 << offset);
678 	if ((!val && skip_im->info.gpio.button_state == HIGH) ||
679 	    (val && skip_im->info.gpio.button_state == LOW)) {
680 		mmio_write_32(SCRATCH_PAD_REG2, SCRATCH_PAD_SKIP_VAL);
681 		return 1;
682 	}
683 
684 	return 0;
685 }
686 
687 /*
688  * This function checks if there's a skip image request:
689  * return values:
690  * 1: (true) images request been made.
691  * 0: (false) no image request been made.
692  */
693 static int  ble_skip_current_image(void)
694 {
695 	struct skip_image *skip_im;
696 
697 	/*fetching skip image info*/
698 	skip_im = (struct skip_image *)plat_marvell_get_skip_image_data();
699 
700 	if (skip_im == NULL)
701 		return 0;
702 
703 	/* check if skipping image request has already been made */
704 	if (mmio_read_32(SCRATCH_PAD_REG2) == SCRATCH_PAD_SKIP_VAL)
705 		return 0;
706 
707 	switch (skip_im->detection_method) {
708 	case GPIO:
709 		return ble_skip_image_gpio(skip_im);
710 	case I2C:
711 		return ble_skip_image_i2c(skip_im);
712 	case USER_DEFINED:
713 		return ble_skip_image_other(skip_im);
714 	}
715 
716 	return 0;
717 }
718 #endif
719 
720 
721 int ble_plat_setup(int *skip)
722 {
723 	int ret, cp;
724 	unsigned int freq_mode;
725 
726 	/* Power down unused CPUs */
727 	plat_marvell_early_cpu_powerdown();
728 
729 	/*
730 	 * Save the current CCU configuration and make required changes:
731 	 * - Allow access to DRAM larger than 4GB
732 	 * - Open memory access to all CPn peripherals
733 	 */
734 	ble_plat_mmap_config(MMAP_SAVE_AND_CONFIG);
735 
736 #if PLAT_RECOVERY_IMAGE_ENABLE
737 	/* Check if there's a skip request to bootRom recovery Image */
738 	if (ble_skip_current_image()) {
739 		/* close memory access to all CPn peripherals. */
740 		ble_plat_mmap_config(MMAP_RESTORE_SAVED);
741 		*skip = 1;
742 		return 0;
743 	}
744 #endif
745 	/* Do required CP-110 setups for BLE stage */
746 	cp110_ble_init(MVEBU_CP_REGS_BASE(0));
747 
748 	/* Config address for each cp other than cp0 */
749 	for (cp = 1; cp < CP_COUNT; cp++)
750 		update_cp110_default_win(cp);
751 
752 	/* Setup AVS */
753 	ble_plat_svc_config();
754 
755 	/* read clk option from sampled-at-reset register */
756 	freq_mode =
757 		SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
758 						 FREQ_MODE_AP_SAR_REG_NUM)));
759 
760 	/* work with PLL clock driver in AP807 */
761 	if (ble_get_ap_type() == CHIP_ID_AP807)
762 		ap807_clocks_init(freq_mode);
763 
764 	/* Do required AP setups for BLE stage */
765 	ap_ble_init();
766 
767 	/* Update DRAM topology (scan DIMM SPDs) */
768 	plat_marvell_dram_update_topology();
769 
770 	/* Kick it in */
771 	ret = dram_init();
772 
773 	/* Restore the original CCU configuration before exit from BLE */
774 	ble_plat_mmap_config(MMAP_RESTORE_SAVED);
775 
776 	return ret;
777 }
778