blob: f11b5ac170436fbbe68586b651b63a7a77e779a7 [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
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008#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
Konstantin Porotchkin91db2902018-07-29 13:30:51 +030016#include <armada_common.h>
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030017#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
Christine Gharzuzi9a772df2018-06-25 13:39:37 +030026#define MMAP_SAVE_AND_CONFIG 0
27#define MMAP_RESTORE_SAVED 1
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030028
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
Konstantin Porotchkinf51f2512018-11-06 12:25:38 +020045#define AVS_I2C_EEPROM_ADDR 0x57 /* EEPROM */
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030046#define AVS_EN_CTRL_REG (MVEBU_AP_GEN_MGMT_BASE + 0x130)
47#define AVS_ENABLE_OFFSET (0)
48#define AVS_SOFT_RESET_OFFSET (2)
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030049#define AVS_TARGET_DELTA_OFFSET (21)
Christine Gharzuzi46a4fc62018-08-02 20:25:11 +030050
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
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030065/* 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))
Konstantin Porotchkinf51f2512018-11-06 12:25:38 +020077/* VDD limit is 0.82V for all A3900 devices
78 * AVS offsets are not the same as in A70x0
79 */
Justin Chadwellfed41a12019-07-03 14:04:33 +010080#define AVS_A3900_CLK_VALUE ((0x80u << 24) | \
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030081 (0x2c2 << 13) | \
82 (0x2c2 << 3) | \
83 (0x1 << AVS_SOFT_RESET_OFFSET) | \
84 (0x1 << AVS_ENABLE_OFFSET))
Christine Gharzuzi9a772df2018-06-25 13:39:37 +030085/* VDD is 0.88V for 2GHz clock */
Justin Chadwellfed41a12019-07-03 14:04:33 +010086#define AVS_A3900_HIGH_CLK_VALUE ((0x80u << 24) | \
Christine Gharzuzi9a772df2018-06-25 13:39:37 +030087 (0x2f5 << 13) | \
88 (0x2f5 << 3) | \
89 (0x1 << AVS_SOFT_RESET_OFFSET) | \
90 (0x1 << AVS_ENABLE_OFFSET))
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030091
Grzegorz Jaszczyka5d06272018-12-20 17:13:19 +010092#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
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +030098#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
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300102
103/*
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300104 * - 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
Christine Gharzuzi46a4fc62018-08-02 20:25:11 +0300129#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
Christine Gharzuzi9a772df2018-06-25 13:39:37 +0300152#define EFUSE_AP_LD0_SVC4_OFFS 42 /* LD0[112:105] */
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300153
Christine Gharzuzi9a772df2018-06-25 13:39:37 +0300154#define EFUSE_AP_LD0_CLUSTER_DOWN_OFFS 4
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300155
Konstantin Porotchkinf51f2512018-11-06 12:25:38 +0200156#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
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300163/* Return the AP revision of the chip */
164static 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 */
197static 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 */
Konstantin Porotchkinf51f2512018-11-06 12:25:38 +0200221#if !MARVELL_SVC_TEST
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300222static void ble_plat_avs_config(void)
223{
Christine Gharzuzi9a772df2018-06-25 13:39:37 +0300224 uint32_t freq_mode, device_id;
225 uint32_t avs_val = 0;
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300226
Christine Gharzuzi9a772df2018-06-25 13:39:37 +0300227 freq_mode =
228 SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
229 FREQ_MODE_AP_SAR_REG_NUM)));
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300230 /* Check which SoC is running and act accordingly */
231 if (ble_get_ap_type() == CHIP_ID_AP807) {
Christine Gharzuzi9a772df2018-06-25 13:39:37 +0300232 /* Increase CPU voltage for higher CPU clock */
Grzegorz Jaszczyka5d06272018-12-20 17:13:19 +0100233 switch (freq_mode) {
234 case CPU_2000_DDR_1200_RCLK_1200:
Christine Gharzuzi9a772df2018-06-25 13:39:37 +0300235 avs_val = AVS_A3900_HIGH_CLK_VALUE;
Grzegorz Jaszczyka5d06272018-12-20 17:13:19 +0100236 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:
Christine Gharzuzi9a772df2018-06-25 13:39:37 +0300243 avs_val = AVS_A3900_CLK_VALUE;
Grzegorz Jaszczyka5d06272018-12-20 17:13:19 +0100244 }
245
Christine Gharzuzi9a772df2018-06-25 13:39:37 +0300246 } 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 }
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300266 }
267
Christine Gharzuzi9a772df2018-06-25 13:39:37 +0300268 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);
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300271 }
272}
Konstantin Porotchkinf51f2512018-11-06 12:25:38 +0200273#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 */
290static 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}
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300380
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 */
393static 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;
Christine Gharzuzi46a4fc62018-08-02 20:25:11 +0300398 uint16_t svc[4], perr[4], i, sw_ver;
399 unsigned int ap_type;
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300400
401 /* Set access to LD0 */
Konstantin Porotchkinf51f2512018-11-06 12:25:38 +0200402 avs_workpoint = avs_update_from_eeprom(0);
403 if (avs_workpoint)
404 goto set_aws_wp;
405
406 /* Set access to LD0 */
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300407 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);
Konstantin Porotchkinf51f2512018-11-06 12:25:38 +0200424#if MARVELL_SVC_TEST
425 NOTICE("SVC_TEST: AVS bypassed\n");
426
427#else
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300428 ble_plat_avs_config();
Konstantin Porotchkinf51f2512018-11-06 12:25:38 +0200429#endif
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300430 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;
Christine Gharzuzi46a4fc62018-08-02 20:25:11 +0300443
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 }
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300456
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) {
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300481 case CPU_1800_DDR_1050_RCLK_1050:
482 if (perr[1])
483 goto perror;
484 avs_workpoint = svc[1];
485 break;
486 case CPU_1600_DDR_1050_RCLK_1050:
487 case CPU_1600_DDR_900_RCLK_900_2:
488 if (perr[2])
489 goto perror;
490 avs_workpoint = svc[2];
491 break;
492 case CPU_1300_DDR_800_RCLK_800:
493 case CPU_1300_DDR_650_RCLK_650:
494 if (perr[3])
495 goto perror;
496 avs_workpoint = svc[3];
497 break;
498 case CPU_2000_DDR_1200_RCLK_1200:
499 case CPU_2000_DDR_1050_RCLK_1050:
500 default:
501 if (perr[0])
502 goto perror;
503 avs_workpoint = svc[0];
504 break;
505 }
506 } else if (device_id == MVEBU_70X0_DEV_ID ||
507 device_id == MVEBU_70X0_CP115_DEV_ID) {
508 /* A7040/A7020/A6040 */
509 NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
510 single_cluster == 0 ? "7040" : "7020", freq_pidi_mode);
511 switch (freq_pidi_mode) {
512 case CPU_1400_DDR_800_RCLK_800:
513 if (single_cluster) {/* 7020 */
514 if (perr[1])
515 goto perror;
516 avs_workpoint = svc[1];
517 } else {
518 if (perr[0])
519 goto perror;
520 avs_workpoint = svc[0];
521 }
522 break;
523 case CPU_1200_DDR_800_RCLK_800:
524 if (single_cluster) {/* 7020 */
525 if (perr[2])
526 goto perror;
527 avs_workpoint = svc[2];
528 } else {
529 if (perr[1])
530 goto perror;
531 avs_workpoint = svc[1];
532 }
533 break;
534 case CPU_800_DDR_800_RCLK_800:
535 case CPU_1000_DDR_800_RCLK_800:
536 if (single_cluster) {/* 7020 */
537 if (perr[3])
538 goto perror;
539 avs_workpoint = svc[3];
540 } else {
541 if (perr[2])
542 goto perror;
543 avs_workpoint = svc[2];
544 }
545 break;
546 case CPU_600_DDR_800_RCLK_800:
547 if (perr[3])
548 goto perror;
549 avs_workpoint = svc[3]; /* Same for 6040 and 7020 */
550 break;
551 case CPU_1600_DDR_800_RCLK_800: /* 7020 only */
552 default:
553 if (single_cluster) {/* 7020 */
554 if (perr[0])
555 goto perror;
556 avs_workpoint = svc[0];
557 } else
558 avs_workpoint = 0;
559 break;
560 }
Christine Gharzuzi46a4fc62018-08-02 20:25:11 +0300561 } else if (device_id == MVEBU_3900_DEV_ID) {
562 NOTICE("SVC: DEV ID: %s, FREQ Mode: 0x%x\n",
563 "3900", freq_pidi_mode);
564 switch (freq_pidi_mode) {
565 case CPU_1600_DDR_1200_RCLK_1200:
566 if (perr[0])
567 goto perror;
568 avs_workpoint = svc[0];
569 break;
570 case CPU_1300_DDR_800_RCLK_800:
571 if (perr[1])
572 goto perror;
573 avs_workpoint = svc[1];
574 break;
575 default:
576 if (perr[0])
577 goto perror;
578 avs_workpoint = svc[0];
579 break;
580 }
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300581 } else {
582 ERROR("SVC: Unsupported Device ID 0x%x\n", device_id);
583 return;
584 }
585
586 /* Set AVS control if needed */
587 if (avs_workpoint == 0) {
588 ERROR("SVC: AVS work point not changed\n");
589 return;
590 }
591
592 /* Remove parity bit */
Christine Gharzuzi46a4fc62018-08-02 20:25:11 +0300593 if (ap_type != CHIP_ID_AP807)
594 avs_workpoint &= 0x7F;
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300595
Konstantin Porotchkinf51f2512018-11-06 12:25:38 +0200596 /* Update WP from EEPROM if needed */
597 avs_workpoint = avs_update_from_eeprom(avs_workpoint);
598
599set_aws_wp:
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300600 reg_val = mmio_read_32(AVS_EN_CTRL_REG);
601 NOTICE("SVC: AVS work point changed from 0x%x to 0x%x\n",
602 (reg_val & AVS_VDD_LOW_LIMIT_MASK) >> AVS_LOW_VDD_LIMIT_OFFSET,
603 avs_workpoint);
604 reg_val &= ~(AVS_VDD_LOW_LIMIT_MASK | AVS_VDD_HIGH_LIMIT_MASK);
605 reg_val |= 0x1 << AVS_ENABLE_OFFSET;
606 reg_val |= avs_workpoint << AVS_HIGH_VDD_LIMIT_OFFSET;
607 reg_val |= avs_workpoint << AVS_LOW_VDD_LIMIT_OFFSET;
608 mmio_write_32(AVS_EN_CTRL_REG, reg_val);
609 return;
610
611perror:
612 ERROR("Failed SVC WP[%d] parity check!\n", i);
613 ERROR("Ignoring the WP values\n");
614}
615
616#if PLAT_RECOVERY_IMAGE_ENABLE
617static int ble_skip_image_i2c(struct skip_image *skip_im)
618{
619 ERROR("skipping image using i2c is not supported\n");
620 /* not supported */
621 return 0;
622}
623
624static int ble_skip_image_other(struct skip_image *skip_im)
625{
626 ERROR("implementation missing for skip image request\n");
627 /* not supported, make your own implementation */
628 return 0;
629}
630
631static int ble_skip_image_gpio(struct skip_image *skip_im)
632{
633 unsigned int val;
634 unsigned int mpp_address = 0;
635 unsigned int offset = 0;
636
637 switch (skip_im->info.test.cp_ap) {
638 case(CP):
639 mpp_address = MVEBU_CP_GPIO_DATA_IN(skip_im->info.test.cp_index,
640 skip_im->info.gpio.num);
641 if (skip_im->info.gpio.num > NUM_OF_GPIO_PER_REG)
642 offset = skip_im->info.gpio.num - NUM_OF_GPIO_PER_REG;
643 else
644 offset = skip_im->info.gpio.num;
645 break;
646 case(AP):
647 mpp_address = MVEBU_AP_GPIO_DATA_IN;
648 offset = skip_im->info.gpio.num;
649 break;
650 }
651
652 val = mmio_read_32(mpp_address);
653 val &= (1 << offset);
654 if ((!val && skip_im->info.gpio.button_state == HIGH) ||
655 (val && skip_im->info.gpio.button_state == LOW)) {
656 mmio_write_32(SCRATCH_PAD_REG2, SCRATCH_PAD_SKIP_VAL);
657 return 1;
658 }
659
660 return 0;
661}
662
663/*
664 * This function checks if there's a skip image request:
665 * return values:
666 * 1: (true) images request been made.
667 * 0: (false) no image request been made.
668 */
669static int ble_skip_current_image(void)
670{
671 struct skip_image *skip_im;
672
673 /*fetching skip image info*/
674 skip_im = (struct skip_image *)plat_marvell_get_skip_image_data();
675
676 if (skip_im == NULL)
677 return 0;
678
679 /* check if skipping image request has already been made */
680 if (mmio_read_32(SCRATCH_PAD_REG2) == SCRATCH_PAD_SKIP_VAL)
681 return 0;
682
683 switch (skip_im->detection_method) {
684 case GPIO:
685 return ble_skip_image_gpio(skip_im);
686 case I2C:
687 return ble_skip_image_i2c(skip_im);
688 case USER_DEFINED:
689 return ble_skip_image_other(skip_im);
690 }
691
692 return 0;
693}
694#endif
695
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300696
697int ble_plat_setup(int *skip)
698{
699 int ret;
Christine Gharzuzi9a772df2018-06-25 13:39:37 +0300700 unsigned int freq_mode;
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300701
702 /* Power down unused CPUs */
703 plat_marvell_early_cpu_powerdown();
704
705 /*
706 * Save the current CCU configuration and make required changes:
707 * - Allow access to DRAM larger than 4GB
708 * - Open memory access to all CPn peripherals
709 */
710 ble_plat_mmap_config(MMAP_SAVE_AND_CONFIG);
711
712#if PLAT_RECOVERY_IMAGE_ENABLE
713 /* Check if there's a skip request to bootRom recovery Image */
714 if (ble_skip_current_image()) {
715 /* close memory access to all CPn peripherals. */
716 ble_plat_mmap_config(MMAP_RESTORE_SAVED);
717 *skip = 1;
718 return 0;
719 }
720#endif
721 /* Do required CP-110 setups for BLE stage */
722 cp110_ble_init(MVEBU_CP_REGS_BASE(0));
723
724 /* Setup AVS */
725 ble_plat_svc_config();
726
Christine Gharzuzi9a772df2018-06-25 13:39:37 +0300727 /* read clk option from sampled-at-reset register */
728 freq_mode =
729 SAR_CLOCK_FREQ_MODE(mmio_read_32(MVEBU_AP_SAR_REG_BASE(
730 FREQ_MODE_AP_SAR_REG_NUM)));
731
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300732 /* work with PLL clock driver in AP807 */
733 if (ble_get_ap_type() == CHIP_ID_AP807)
Christine Gharzuzi9a772df2018-06-25 13:39:37 +0300734 ap807_clocks_init(freq_mode);
Konstantin Porotchkinf69ec582018-06-07 18:31:14 +0300735
736 /* Do required AP setups for BLE stage */
737 ap_ble_init();
738
739 /* Update DRAM topology (scan DIMM SPDs) */
740 plat_marvell_dram_update_topology();
741
742 /* Kick it in */
743 ret = dram_init();
744
745 /* Restore the original CCU configuration before exit from BLE */
746 ble_plat_mmap_config(MMAP_RESTORE_SAVED);
747
748 return ret;
749}