blob: 0cd62cbdb2ec4f2fe69dfbf5b7c43b51e9f89e02 [file] [log] [blame]
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +03001/*
2 * Copyright (C) 2018 Marvell International Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 * https://spdx.org/licenses
6 */
7
8#include <a8k_common.h>
9#include <ap_setup.h>
10#include <aro.h>
11#include <ccu.h>
12#include <cp110_setup.h>
13#include <debug.h>
14#include <io_win.h>
15#include <mv_ddr_if.h>
16#include <mvebu_def.h>
17#include <plat_marvell.h>
18
19/* Register for skip image use */
20#define SCRATCH_PAD_REG2 0xF06F00A8
21#define SCRATCH_PAD_SKIP_VAL 0x01
22#define NUM_OF_GPIO_PER_REG 32
23
24#define MMAP_SAVE_AND_CONFIG 0
25#define MMAP_RESTORE_SAVED 1
26
27/* SAR clock settings */
28#define MVEBU_AP_GEN_MGMT_BASE (MVEBU_RFU_BASE + 0x8000)
29#define MVEBU_AP_SAR_REG_BASE(r) (MVEBU_AP_GEN_MGMT_BASE + 0x200 +\
30 ((r) << 2))
31
32#define SAR_CLOCK_FREQ_MODE_OFFSET (0)
33#define SAR_CLOCK_FREQ_MODE_MASK (0x1f << SAR_CLOCK_FREQ_MODE_OFFSET)
34#define SAR_PIDI_LOW_SPEED_OFFSET (20)
35#define SAR_PIDI_LOW_SPEED_MASK (1 << SAR_PIDI_LOW_SPEED_OFFSET)
36#define SAR_PIDI_LOW_SPEED_SHIFT (15)
37#define SAR_PIDI_LOW_SPEED_SET (1 << SAR_PIDI_LOW_SPEED_SHIFT)
38
39#define FREQ_MODE_AP_SAR_REG_NUM (0)
40#define SAR_CLOCK_FREQ_MODE(v) (((v) & SAR_CLOCK_FREQ_MODE_MASK) >> \
41 SAR_CLOCK_FREQ_MODE_OFFSET)
42
43#define AVS_EN_CTRL_REG (MVEBU_AP_GEN_MGMT_BASE + 0x130)
44#define AVS_ENABLE_OFFSET (0)
45#define AVS_SOFT_RESET_OFFSET (2)
46#define AVS_LOW_VDD_LIMIT_OFFSET (4)
47#define AVS_HIGH_VDD_LIMIT_OFFSET (12)
48#define AVS_TARGET_DELTA_OFFSET (21)
49#define AVS_VDD_LOW_LIMIT_MASK (0xFF << AVS_LOW_VDD_LIMIT_OFFSET)
50#define AVS_VDD_HIGH_LIMIT_MASK (0xFF << AVS_HIGH_VDD_LIMIT_OFFSET)
51/* VDD limit is 0.9V for A70x0 @ CPU frequency < 1600MHz */
52#define AVS_A7K_LOW_CLK_VALUE ((0x80 << AVS_TARGET_DELTA_OFFSET) | \
53 (0x1A << AVS_HIGH_VDD_LIMIT_OFFSET) | \
54 (0x1A << AVS_LOW_VDD_LIMIT_OFFSET) | \
55 (0x1 << AVS_SOFT_RESET_OFFSET) | \
56 (0x1 << AVS_ENABLE_OFFSET))
57/* VDD limit is 1.0V for all A80x0 devices */
58#define AVS_A8K_CLK_VALUE ((0x80 << AVS_TARGET_DELTA_OFFSET) | \
59 (0x24 << AVS_HIGH_VDD_LIMIT_OFFSET) | \
60 (0x24 << AVS_LOW_VDD_LIMIT_OFFSET) | \
61 (0x1 << AVS_SOFT_RESET_OFFSET) | \
62 (0x1 << AVS_ENABLE_OFFSET))
63
64#define AVS_A3900_CLK_VALUE ((0x80 << 24) | \
65 (0x2c2 << 13) | \
66 (0x2c2 << 3) | \
67 (0x1 << AVS_SOFT_RESET_OFFSET) | \
68 (0x1 << AVS_ENABLE_OFFSET))
69
70#define MVEBU_AP_EFUSE_SRV_CTRL_REG (MVEBU_AP_GEN_MGMT_BASE + 0x8)
71#define EFUSE_SRV_CTRL_LD_SELECT_OFFS 6
72#define EFUSE_SRV_CTRL_LD_SEL_USER_MASK (1 << EFUSE_SRV_CTRL_LD_SELECT_OFFS)
73
74/* Notify bootloader on DRAM setup */
75#define AP807_CPU_ARO_0_CTRL_0 (MVEBU_RFU_BASE + 0x82A8)
76#define AP807_CPU_ARO_1_CTRL_0 (MVEBU_RFU_BASE + 0x8D00)
77
78/* 0 - ARO clock is enabled, 1 - ARO clock is disabled */
79#define AP807_CPU_ARO_CLK_EN_OFFSET 0
80#define AP807_CPU_ARO_CLK_EN_MASK (0x1 << AP807_CPU_ARO_CLK_EN_OFFSET)
81
82/* 0 - ARO is the clock source, 1 - PLL is the clock source */
83#define AP807_CPU_ARO_SEL_PLL_OFFSET 5
84#define AP807_CPU_ARO_SEL_PLL_MASK (0x1 << AP807_CPU_ARO_SEL_PLL_OFFSET)
85
86/*
87 * - AVS work points in the LD0 eFuse:
88 * SVC1 work point: LD0[88:81]
89 * SVC2 work point: LD0[96:89]
90 * SVC3 work point: LD0[104:97]
91 * SVC4 work point: LD0[112:105]
92 * - Identification information in the LD-0 eFuse:
93 * DRO: LD0[74:65] - Not used by the SW
94 * Revision: LD0[78:75] - Not used by the SW
95 * Bin: LD0[80:79] - Not used by the SW
96 * SW Revision: LD0[115:113]
97 * Cluster 1 PWR: LD0[193] - if set to 1, power down CPU Cluster-1
98 * resulting in 2 CPUs active only (7020)
99 */
100#define MVEBU_AP_LD_EFUSE_BASE (MVEBU_AP_GEN_MGMT_BASE + 0xF00)
101/* Bits [94:63] - 32 data bits total */
102#define MVEBU_AP_LD0_94_63_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0x8)
103/* Bits [125:95] - 31 data bits total, 32nd bit is parity for bits [125:63] */
104#define MVEBU_AP_LD0_125_95_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0xC)
105/* Bits [220:189] - 32 data bits total */
106#define MVEBU_AP_LD0_220_189_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0x18)
107/* Offsets for the above 2 fields combined into single 64-bit value [125:63] */
108#define EFUSE_AP_LD0_DRO_OFFS 2 /* LD0[74:65] */
109#define EFUSE_AP_LD0_DRO_MASK 0x3FF
110#define EFUSE_AP_LD0_REVID_OFFS 12 /* LD0[78:75] */
111#define EFUSE_AP_LD0_REVID_MASK 0xF
112#define EFUSE_AP_LD0_BIN_OFFS 16 /* LD0[80:79] */
113#define EFUSE_AP_LD0_BIN_MASK 0x3
114#define EFUSE_AP_LD0_SWREV_OFFS 50 /* LD0[115:113] */
115#define EFUSE_AP_LD0_SWREV_MASK 0x7
116
117#define EFUSE_AP_LD0_SVC1_OFFS 18 /* LD0[88:81] */
118#define EFUSE_AP_LD0_SVC2_OFFS 26 /* LD0[96:89] */
119#define EFUSE_AP_LD0_SVC3_OFFS 34 /* LD0[104:97] */
120#define EFUSE_AP_LD0_SVC4_OFFS 42 /* LD0[112:105] */
121#define EFUSE_AP_LD0_WP_MASK 0xFF
122
123#define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS 4
124
125/* Return the AP revision of the chip */
126static unsigned int ble_get_ap_type(void)
127{
128 unsigned int chip_rev_id;
129
130 chip_rev_id = mmio_read_32(MVEBU_CSS_GWD_CTRL_IIDR2_REG);
131 chip_rev_id = ((chip_rev_id & GWD_IIDR2_CHIP_ID_MASK) >>
132 GWD_IIDR2_CHIP_ID_OFFSET);
133
134 return chip_rev_id;
135}
136
137/******************************************************************************
138 * The routine allows to save the CCU and IO windows configuration during DRAM
139 * setup and restore them afterwards before exiting the BLE stage.
140 * Such window configuration is required since not all default settings coming
141 * from the HW and the BootROM allow access to peripherals connected to
142 * all available CPn components.
143 * For instance, when the boot device is located on CP0, the IO window to CP1
144 * is not opened automatically by the HW and if the DRAM SPD is located on CP1
145 * i2c channel, it cannot be read at BLE stage.
146 * Therefore the DRAM init procedure have to provide access to all available
147 * CPn peripherals during the BLE stage by setting the CCU IO window to all
148 * CPnph addresses and by enabling the IO windows accordingly.
149 * Additionally this function configures the CCU GCR to DRAM, which allows
150 * usage or more than 4GB DRAM as it configured by the default CCU DRAM window.
151 *
152 * IN:
153 * MMAP_SAVE_AND_CONFIG - save the existing configuration and update it
154 * MMAP_RESTORE_SAVED - restore saved configuration
155 * OUT:
156 * NONE
157 ****************************************************************************
158 */
159static void ble_plat_mmap_config(int restore)
160{
161 if (restore == MMAP_RESTORE_SAVED) {
162 /* Restore all orig. settings that were modified by BLE stage */
163 ccu_restore_win_all(MVEBU_AP0);
164 /* Restore CCU */
165 iow_restore_win_all(MVEBU_AP0);
166 return;
167 }
168
169 /* Store original values */
170 ccu_save_win_all(MVEBU_AP0);
171 /* Save CCU */
172 iow_save_win_all(MVEBU_AP0);
173
174 init_ccu(MVEBU_AP0);
175 /* The configuration saved, now all the changes can be done */
176 init_io_win(MVEBU_AP0);
177}
178
179/****************************************************************************
180 * Setup Adaptive Voltage Switching - this is required for some platforms
181 ****************************************************************************
182 */
183static void ble_plat_avs_config(void)
184{
185 uint32_t reg_val, device_id;
186
187 /* Check which SoC is running and act accordingly */
188 if (ble_get_ap_type() == CHIP_ID_AP807) {
189 VERBOSE("AVS: Setting AP807 AVS CTRL to 0x%x\n",
190 AVS_A3900_CLK_VALUE);
191 mmio_write_32(AVS_EN_CTRL_REG, AVS_A3900_CLK_VALUE);
192 return;
193 }
194
195 /* Check which SoC is running and act accordingly */
196 device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
197 switch (device_id) {
198 case MVEBU_80X0_DEV_ID:
199 case MVEBU_80X0_CP115_DEV_ID:
200 /* Set the new AVS value - fix the default one on A80x0 */
201 mmio_write_32(AVS_EN_CTRL_REG, AVS_A8K_CLK_VALUE);
202 break;
203 case MVEBU_70X0_DEV_ID:
204 case MVEBU_70X0_CP115_DEV_ID:
205 /* Only fix AVS for CPU clocks lower than 1600MHz on A70x0 */
206 reg_val = mmio_read_32(MVEBU_AP_SAR_REG_BASE(
207 FREQ_MODE_AP_SAR_REG_NUM));
208 reg_val &= SAR_CLOCK_FREQ_MODE_MASK;
209 reg_val >>= SAR_CLOCK_FREQ_MODE_OFFSET;
210 if ((reg_val > CPU_1600_DDR_900_RCLK_900_2) &&
211 (reg_val < CPU_DDR_RCLK_INVALID))
212 mmio_write_32(AVS_EN_CTRL_REG, AVS_A7K_LOW_CLK_VALUE);
213 break;
214 default:
215 ERROR("Unsupported Device ID 0x%x\n", device_id);
216 }
217}
218
219/****************************************************************************
220 * SVC flow - v0.10
221 * The feature is intended to configure AVS value according to eFuse values
222 * that are burned individually for each SoC during the test process.
223 * Primary AVS value is stored in HD efuse and processed on power on
224 * by the HW engine
225 * Secondary AVS value is located in LD efuse and contains 4 work points for
226 * various CPU frequencies.
227 * The Secondary AVS value is only taken into account if the SW Revision stored
228 * in the efuse is greater than 0 and the CPU is running in a certain speed.
229 ****************************************************************************
230 */
231static void ble_plat_svc_config(void)
232{
233 uint32_t reg_val, avs_workpoint, freq_pidi_mode;
234 uint64_t efuse;
235 uint32_t device_id, single_cluster;
236 uint8_t svc[4], perr[4], i, sw_ver;
237
238 /* Due to a bug in A3900 device_id skip SVC config
239 * TODO: add SVC config once it is decided for a3900
240 */
241 if (ble_get_ap_type() == CHIP_ID_AP807) {
242 NOTICE("SVC: SVC is not supported on AP807\n");
243 ble_plat_avs_config();
244 return;
245 }
246
247 /* Set access to LD0 */
248 reg_val = mmio_read_32(MVEBU_AP_EFUSE_SRV_CTRL_REG);
249 reg_val &= ~EFUSE_SRV_CTRL_LD_SELECT_OFFS;
250 mmio_write_32(MVEBU_AP_EFUSE_SRV_CTRL_REG, reg_val);
251
252 /* Obtain the value of LD0[125:63] */
253 efuse = mmio_read_32(MVEBU_AP_LD0_125_95_EFUSE_OFFS);
254 efuse <<= 32;
255 efuse |= mmio_read_32(MVEBU_AP_LD0_94_63_EFUSE_OFFS);
256
257 /* SW Revision:
258 * Starting from SW revision 1 the SVC flow is supported.
259 * SW version 0 (efuse not programmed) should follow the
260 * regular AVS update flow.
261 */
262 sw_ver = (efuse >> EFUSE_AP_LD0_SWREV_OFFS) & EFUSE_AP_LD0_SWREV_MASK;
263 if (sw_ver < 1) {
264 NOTICE("SVC: SW Revision 0x%x. SVC is not supported\n", sw_ver);
265 ble_plat_avs_config();
266 return;
267 }
268
269 /* Frequency mode from SAR */
270 freq_pidi_mode = SAR_CLOCK_FREQ_MODE(
271 mmio_read_32(
272 MVEBU_AP_SAR_REG_BASE(
273 FREQ_MODE_AP_SAR_REG_NUM)));
274
275 /* Decode all SVC work points */
276 svc[0] = (efuse >> EFUSE_AP_LD0_SVC1_OFFS) & EFUSE_AP_LD0_WP_MASK;
277 svc[1] = (efuse >> EFUSE_AP_LD0_SVC2_OFFS) & EFUSE_AP_LD0_WP_MASK;
278 svc[2] = (efuse >> EFUSE_AP_LD0_SVC3_OFFS) & EFUSE_AP_LD0_WP_MASK;
279 svc[3] = (efuse >> EFUSE_AP_LD0_SVC4_OFFS) & EFUSE_AP_LD0_WP_MASK;
280 INFO("SVC: Efuse WP: [0]=0x%x, [1]=0x%x, [2]=0x%x, [3]=0x%x\n",
281 svc[0], svc[1], svc[2], svc[3]);
282
283 /* Validate parity of SVC workpoint values */
284 for (i = 0; i < 4; i++) {
285 uint8_t parity, bit;
286
287 perr[i] = 0;
288
289 for (bit = 1, parity = svc[i] & 1; bit < 7; bit++)
290 parity ^= (svc[i] >> bit) & 1;
291
292 /* Starting from SW version 2, the parity check is mandatory */
293 if ((sw_ver > 1) && (parity != ((svc[i] >> 7) & 1)))
294 perr[i] = 1; /* register the error */
295 }
296
297 single_cluster = mmio_read_32(MVEBU_AP_LD0_220_189_EFUSE_OFFS);
298 single_cluster = (single_cluster >> EFUSE_AP_LD0_CLUSTER_DOWN_OFFS) & 1;
299
300 device_id = cp110_device_id_get(MVEBU_CP_REGS_BASE(0));
301 if (device_id == MVEBU_80X0_DEV_ID ||
302 device_id == MVEBU_80X0_CP115_DEV_ID) {
303 /* A8040/A8020 */
304 NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
305 single_cluster == 0 ? "8040" : "8020", freq_pidi_mode);
306 switch (freq_pidi_mode) {
307 case CPU_1800_DDR_1200_RCLK_1200:
308 case CPU_1800_DDR_1050_RCLK_1050:
309 if (perr[1])
310 goto perror;
311 avs_workpoint = svc[1];
312 break;
313 case CPU_1600_DDR_1050_RCLK_1050:
314 case CPU_1600_DDR_900_RCLK_900_2:
315 if (perr[2])
316 goto perror;
317 avs_workpoint = svc[2];
318 break;
319 case CPU_1300_DDR_800_RCLK_800:
320 case CPU_1300_DDR_650_RCLK_650:
321 if (perr[3])
322 goto perror;
323 avs_workpoint = svc[3];
324 break;
325 case CPU_2000_DDR_1200_RCLK_1200:
326 case CPU_2000_DDR_1050_RCLK_1050:
327 default:
328 if (perr[0])
329 goto perror;
330 avs_workpoint = svc[0];
331 break;
332 }
333 } else if (device_id == MVEBU_70X0_DEV_ID ||
334 device_id == MVEBU_70X0_CP115_DEV_ID) {
335 /* A7040/A7020/A6040 */
336 NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
337 single_cluster == 0 ? "7040" : "7020", freq_pidi_mode);
338 switch (freq_pidi_mode) {
339 case CPU_1400_DDR_800_RCLK_800:
340 if (single_cluster) {/* 7020 */
341 if (perr[1])
342 goto perror;
343 avs_workpoint = svc[1];
344 } else {
345 if (perr[0])
346 goto perror;
347 avs_workpoint = svc[0];
348 }
349 break;
350 case CPU_1200_DDR_800_RCLK_800:
351 if (single_cluster) {/* 7020 */
352 if (perr[2])
353 goto perror;
354 avs_workpoint = svc[2];
355 } else {
356 if (perr[1])
357 goto perror;
358 avs_workpoint = svc[1];
359 }
360 break;
361 case CPU_800_DDR_800_RCLK_800:
362 case CPU_1000_DDR_800_RCLK_800:
363 if (single_cluster) {/* 7020 */
364 if (perr[3])
365 goto perror;
366 avs_workpoint = svc[3];
367 } else {
368 if (perr[2])
369 goto perror;
370 avs_workpoint = svc[2];
371 }
372 break;
373 case CPU_600_DDR_800_RCLK_800:
374 if (perr[3])
375 goto perror;
376 avs_workpoint = svc[3]; /* Same for 6040 and 7020 */
377 break;
378 case CPU_1600_DDR_800_RCLK_800: /* 7020 only */
379 default:
380 if (single_cluster) {/* 7020 */
381 if (perr[0])
382 goto perror;
383 avs_workpoint = svc[0];
384 } else
385 avs_workpoint = 0;
386 break;
387 }
388 } else {
389 ERROR("SVC: Unsupported Device ID 0x%x\n", device_id);
390 return;
391 }
392
393 /* Set AVS control if needed */
394 if (avs_workpoint == 0) {
395 ERROR("SVC: AVS work point not changed\n");
396 return;
397 }
398
399 /* Remove parity bit */
400 avs_workpoint &= 0x7F;
401
402 reg_val = mmio_read_32(AVS_EN_CTRL_REG);
403 NOTICE("SVC: AVS work point changed from 0x%x to 0x%x\n",
404 (reg_val & AVS_VDD_LOW_LIMIT_MASK) >> AVS_LOW_VDD_LIMIT_OFFSET,
405 avs_workpoint);
406 reg_val &= ~(AVS_VDD_LOW_LIMIT_MASK | AVS_VDD_HIGH_LIMIT_MASK);
407 reg_val |= 0x1 << AVS_ENABLE_OFFSET;
408 reg_val |= avs_workpoint << AVS_HIGH_VDD_LIMIT_OFFSET;
409 reg_val |= avs_workpoint << AVS_LOW_VDD_LIMIT_OFFSET;
410 mmio_write_32(AVS_EN_CTRL_REG, reg_val);
411 return;
412
413perror:
414 ERROR("Failed SVC WP[%d] parity check!\n", i);
415 ERROR("Ignoring the WP values\n");
416}
417
418#if PLAT_RECOVERY_IMAGE_ENABLE
419static int ble_skip_image_i2c(struct skip_image *skip_im)
420{
421 ERROR("skipping image using i2c is not supported\n");
422 /* not supported */
423 return 0;
424}
425
426static int ble_skip_image_other(struct skip_image *skip_im)
427{
428 ERROR("implementation missing for skip image request\n");
429 /* not supported, make your own implementation */
430 return 0;
431}
432
433static int ble_skip_image_gpio(struct skip_image *skip_im)
434{
435 unsigned int val;
436 unsigned int mpp_address = 0;
437 unsigned int offset = 0;
438
439 switch (skip_im->info.test.cp_ap) {
440 case(CP):
441 mpp_address = MVEBU_CP_GPIO_DATA_IN(skip_im->info.test.cp_index,
442 skip_im->info.gpio.num);
443 if (skip_im->info.gpio.num > NUM_OF_GPIO_PER_REG)
444 offset = skip_im->info.gpio.num - NUM_OF_GPIO_PER_REG;
445 else
446 offset = skip_im->info.gpio.num;
447 break;
448 case(AP):
449 mpp_address = MVEBU_AP_GPIO_DATA_IN;
450 offset = skip_im->info.gpio.num;
451 break;
452 }
453
454 val = mmio_read_32(mpp_address);
455 val &= (1 << offset);
456 if ((!val && skip_im->info.gpio.button_state == HIGH) ||
457 (val && skip_im->info.gpio.button_state == LOW)) {
458 mmio_write_32(SCRATCH_PAD_REG2, SCRATCH_PAD_SKIP_VAL);
459 return 1;
460 }
461
462 return 0;
463}
464
465/*
466 * This function checks if there's a skip image request:
467 * return values:
468 * 1: (true) images request been made.
469 * 0: (false) no image request been made.
470 */
471static int ble_skip_current_image(void)
472{
473 struct skip_image *skip_im;
474
475 /*fetching skip image info*/
476 skip_im = (struct skip_image *)plat_marvell_get_skip_image_data();
477
478 if (skip_im == NULL)
479 return 0;
480
481 /* check if skipping image request has already been made */
482 if (mmio_read_32(SCRATCH_PAD_REG2) == SCRATCH_PAD_SKIP_VAL)
483 return 0;
484
485 switch (skip_im->detection_method) {
486 case GPIO:
487 return ble_skip_image_gpio(skip_im);
488 case I2C:
489 return ble_skip_image_i2c(skip_im);
490 case USER_DEFINED:
491 return ble_skip_image_other(skip_im);
492 }
493
494 return 0;
495}
496#endif
497
498/* Switch to ARO from PLL in ap807 */
499static void aro_to_pll(void)
500{
501 unsigned int reg;
502
503 /* switch from ARO to PLL */
504 reg = mmio_read_32(AP807_CPU_ARO_0_CTRL_0);
505 reg |= AP807_CPU_ARO_SEL_PLL_MASK;
506 mmio_write_32(AP807_CPU_ARO_0_CTRL_0, reg);
507
508 reg = mmio_read_32(AP807_CPU_ARO_1_CTRL_0);
509 reg |= AP807_CPU_ARO_SEL_PLL_MASK;
510 mmio_write_32(AP807_CPU_ARO_1_CTRL_0, reg);
511
512 mdelay(1000);
513
514 /* disable ARO clk driver */
515 reg = mmio_read_32(AP807_CPU_ARO_0_CTRL_0);
516 reg |= (AP807_CPU_ARO_CLK_EN_MASK);
517 mmio_write_32(AP807_CPU_ARO_0_CTRL_0, reg);
518
519 reg = mmio_read_32(AP807_CPU_ARO_1_CTRL_0);
520 reg |= (AP807_CPU_ARO_CLK_EN_MASK);
521 mmio_write_32(AP807_CPU_ARO_1_CTRL_0, reg);
522}
523
524int ble_plat_setup(int *skip)
525{
526 int ret;
527
528 /* Power down unused CPUs */
529 plat_marvell_early_cpu_powerdown();
530
531 /*
532 * Save the current CCU configuration and make required changes:
533 * - Allow access to DRAM larger than 4GB
534 * - Open memory access to all CPn peripherals
535 */
536 ble_plat_mmap_config(MMAP_SAVE_AND_CONFIG);
537
538#if PLAT_RECOVERY_IMAGE_ENABLE
539 /* Check if there's a skip request to bootRom recovery Image */
540 if (ble_skip_current_image()) {
541 /* close memory access to all CPn peripherals. */
542 ble_plat_mmap_config(MMAP_RESTORE_SAVED);
543 *skip = 1;
544 return 0;
545 }
546#endif
547 /* Do required CP-110 setups for BLE stage */
548 cp110_ble_init(MVEBU_CP_REGS_BASE(0));
549
550 /* Setup AVS */
551 ble_plat_svc_config();
552
553 /* work with PLL clock driver in AP807 */
554 if (ble_get_ap_type() == CHIP_ID_AP807)
555 aro_to_pll();
556
557 /* Do required AP setups for BLE stage */
558 ap_ble_init();
559
560 /* Update DRAM topology (scan DIMM SPDs) */
561 plat_marvell_dram_update_topology();
562
563 /* Kick it in */
564 ret = dram_init();
565
566 /* Restore the original CCU configuration before exit from BLE */
567 ble_plat_mmap_config(MMAP_RESTORE_SAVED);
568
569 return ret;
570}