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