xref: /rk3399_ARM-atf/plat/brcm/board/stingray/driver/swreg.c (revision 4bd8c929b4bc6e1731c2892b38d4a8c43e8e89dc)
1f29d1e0cSSheetal Tigadoli /*
2f29d1e0cSSheetal Tigadoli  * Copyright (c) 2017 - 2020, Broadcom
3f29d1e0cSSheetal Tigadoli  *
4f29d1e0cSSheetal Tigadoli  * SPDX-License-Identifier: BSD-3-Clause
5f29d1e0cSSheetal Tigadoli  */
6f29d1e0cSSheetal Tigadoli 
7f29d1e0cSSheetal Tigadoli #include <assert.h>
8f29d1e0cSSheetal Tigadoli #include <errno.h>
9f29d1e0cSSheetal Tigadoli #include <stdint.h>
10f29d1e0cSSheetal Tigadoli 
11f29d1e0cSSheetal Tigadoli #include <common/debug.h>
12f29d1e0cSSheetal Tigadoli #include <drivers/delay_timer.h>
13f29d1e0cSSheetal Tigadoli #include <lib/mmio.h>
14f29d1e0cSSheetal Tigadoli 
15f29d1e0cSSheetal Tigadoli #include <sr_utils.h>
16f29d1e0cSSheetal Tigadoli #include <swreg.h>
17f29d1e0cSSheetal Tigadoli 
18f29d1e0cSSheetal Tigadoli #define MIN_VOLT                760000
19f29d1e0cSSheetal Tigadoli #define MAX_VOLT                1060000
20f29d1e0cSSheetal Tigadoli 
21f29d1e0cSSheetal Tigadoli #define BSTI_WRITE              0x1
22f29d1e0cSSheetal Tigadoli #define BSTI_READ               0x2
23f29d1e0cSSheetal Tigadoli #define BSTI_COMMAND_TA         0x2
24f29d1e0cSSheetal Tigadoli #define BSTI_COMMAND_DATA       0xFF
25f29d1e0cSSheetal Tigadoli #define BSTI_CONTROL_VAL        0x81
26f29d1e0cSSheetal Tigadoli #define BSTI_CONTROL_BUSY       0x100
27f29d1e0cSSheetal Tigadoli #define BSTI_TOGGLE_BIT         0x2
28f29d1e0cSSheetal Tigadoli #define BSTI_CONFI_DONE_MASK    0xFFFFFFFD
29f29d1e0cSSheetal Tigadoli #define BSTI_REG_DATA_MASK      0xFFFF
30f29d1e0cSSheetal Tigadoli #define BSTI_CMD(sb, op, pa, ra, ta, data) \
31f29d1e0cSSheetal Tigadoli 	((((sb) & 0x3) << 30) | (((op) & 0x3) << 28) | \
32f29d1e0cSSheetal Tigadoli 	(((pa) & 0x1F) << 23) | (((ra) & 0x1F) << 18) | \
33f29d1e0cSSheetal Tigadoli 	(((ta) & 0x3) << 16) | (data))
34f29d1e0cSSheetal Tigadoli 
35f29d1e0cSSheetal Tigadoli #define PHY_REG0        0x0
36f29d1e0cSSheetal Tigadoli #define PHY_REG1        0x1
37f29d1e0cSSheetal Tigadoli #define PHY_REG4        0x4
38f29d1e0cSSheetal Tigadoli #define PHY_REG5        0x5
39f29d1e0cSSheetal Tigadoli #define PHY_REG6        0x6
40f29d1e0cSSheetal Tigadoli #define PHY_REG7        0x7
41f29d1e0cSSheetal Tigadoli #define PHY_REGC        0xc
42f29d1e0cSSheetal Tigadoli 
43f29d1e0cSSheetal Tigadoli #define IHOST_VDDC_DATA 0x560
44f29d1e0cSSheetal Tigadoli #define DDR_CORE_DATA   0x2560
45f29d1e0cSSheetal Tigadoli #define UPDATE_POS_EDGE(data, set)    ((data) | ((set) << 1))
46f29d1e0cSSheetal Tigadoli 
47f29d1e0cSSheetal Tigadoli /*
48f29d1e0cSSheetal Tigadoli  * Formula for SR A2 reworked board:
49f29d1e0cSSheetal Tigadoli  * step = ((vol/(1.4117 * 0.98)) - 500000)/3125
50f29d1e0cSSheetal Tigadoli  * where,
51f29d1e0cSSheetal Tigadoli  *      vol    - input voltage
52f29d1e0cSSheetal Tigadoli  *      500000 - Reference voltage
53f29d1e0cSSheetal Tigadoli  *      3125   - one step value
54f29d1e0cSSheetal Tigadoli  */
55f29d1e0cSSheetal Tigadoli #define A2_VOL_REF         500000
56f29d1e0cSSheetal Tigadoli #define ONE_STEP_VALUE  3125
57f29d1e0cSSheetal Tigadoli #define VOL_DIV(vol)    (((vol*10000ull)/(14117*98ull)) * 100ull)
58f29d1e0cSSheetal Tigadoli #define STEP_VALUE(vol) \
59f29d1e0cSSheetal Tigadoli 	((((((VOL_DIV(vol)) - A2_VOL_REF) / ONE_STEP_VALUE) & 0xFF) << 8) | 4)
60f29d1e0cSSheetal Tigadoli 
61f29d1e0cSSheetal Tigadoli #define B0_VOL_REF         ((500000/100)*98)
62f29d1e0cSSheetal Tigadoli #define B0_ONE_STEP_VALUE  3125
63f29d1e0cSSheetal Tigadoli /*
64f29d1e0cSSheetal Tigadoli  * Formula for SR B0 chip for IHOST12/03 and VDDC_CORE
65f29d1e0cSSheetal Tigadoli  * step = ((vol/1.56) - (500000 * 0.98))/3125
66f29d1e0cSSheetal Tigadoli  * where,
67f29d1e0cSSheetal Tigadoli  *      vol    - input voltage
68f29d1e0cSSheetal Tigadoli  *      500000 - Reference voltage
69f29d1e0cSSheetal Tigadoli  *      3125   - one step value
70f29d1e0cSSheetal Tigadoli  */
71f29d1e0cSSheetal Tigadoli #define B0_VOL_DIV(vol)    (((vol)*100ull)/156)
72f29d1e0cSSheetal Tigadoli #define B0_STEP_VALUE(vol) \
73f29d1e0cSSheetal Tigadoli 	((((((B0_VOL_DIV(vol)) - B0_VOL_REF) / B0_ONE_STEP_VALUE) \
74f29d1e0cSSheetal Tigadoli 		& 0xFF) << 8) | 4)
75f29d1e0cSSheetal Tigadoli 
76f29d1e0cSSheetal Tigadoli /*
77f29d1e0cSSheetal Tigadoli  * Formula for SR B0 chip for DDR-CORE
78f29d1e0cSSheetal Tigadoli  * step = ((vol/1) - (500000 * 0.98))/3125
79f29d1e0cSSheetal Tigadoli  * where,
80f29d1e0cSSheetal Tigadoli  *      vol    - input voltage
81f29d1e0cSSheetal Tigadoli  *      500000 - Reference voltage
82f29d1e0cSSheetal Tigadoli  *      3125   - one step value
83f29d1e0cSSheetal Tigadoli  */
84f29d1e0cSSheetal Tigadoli #define B0_DDR_VDDC_VOL_DIV(vol)    ((vol)/1)
85f29d1e0cSSheetal Tigadoli #define B0_DDR_VDDC_STEP_VALUE(vol) \
86f29d1e0cSSheetal Tigadoli 	((((((B0_DDR_VDDC_VOL_DIV(vol)) - B0_VOL_REF) / B0_ONE_STEP_VALUE) \
87f29d1e0cSSheetal Tigadoli 		& 0xFF) << 8) | 4)
88f29d1e0cSSheetal Tigadoli 
89f29d1e0cSSheetal Tigadoli #define MAX_SWREG_CNT       8
90f29d1e0cSSheetal Tigadoli #define MAX_ADDR_PER_SWREG  16
91f29d1e0cSSheetal Tigadoli #define MAX_REG_ADDR        0xF
92f29d1e0cSSheetal Tigadoli #define MIN_REG_ADDR        0x0
93f29d1e0cSSheetal Tigadoli 
94f29d1e0cSSheetal Tigadoli static const char *sw_reg_name[MAX_SWREG_CNT] = {
95f29d1e0cSSheetal Tigadoli 	"DDR_VDDC",
96f29d1e0cSSheetal Tigadoli 	"IHOST03",
97f29d1e0cSSheetal Tigadoli 	"IHOST12",
98f29d1e0cSSheetal Tigadoli 	"IHOST_ARRAY",
99f29d1e0cSSheetal Tigadoli 	"DDRIO_SLAVE",
100f29d1e0cSSheetal Tigadoli 	"VDDC_CORE",
101f29d1e0cSSheetal Tigadoli 	"VDDC1",
102f29d1e0cSSheetal Tigadoli 	"DDRIO_MASTER"
103f29d1e0cSSheetal Tigadoli };
104f29d1e0cSSheetal Tigadoli 
105f29d1e0cSSheetal Tigadoli /* firmware values for all SWREG for 3.3V input operation */
106f29d1e0cSSheetal Tigadoli static const uint16_t swreg_fm_data_bx[MAX_SWREG_CNT][MAX_ADDR_PER_SWREG] = {
107f29d1e0cSSheetal Tigadoli 	/* DDR logic: Power Domains independent of 12v or 3p3v */
108f29d1e0cSSheetal Tigadoli 	{0x25E0, 0x2D54, 0x0EC6, 0x01EC, 0x28BB, 0x1144, 0x0200, 0x69C0,
109f29d1e0cSSheetal Tigadoli 	 0x0010, 0x0EDF, 0x90D7, 0x8000, 0x820C, 0x0003, 0x0001, 0x0000},
110f29d1e0cSSheetal Tigadoli 
111f29d1e0cSSheetal Tigadoli 	/* ihost03, 3p3V */
112f29d1e0cSSheetal Tigadoli 	{0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
113f29d1e0cSSheetal Tigadoli 	 0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
114f29d1e0cSSheetal Tigadoli 
115f29d1e0cSSheetal Tigadoli 	/* ihost12 3p3v */
116f29d1e0cSSheetal Tigadoli 	{0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
117f29d1e0cSSheetal Tigadoli 	 0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
118f29d1e0cSSheetal Tigadoli 
119f29d1e0cSSheetal Tigadoli 	/* ihost array */
120f29d1e0cSSheetal Tigadoli 	{0x25E0, 0x2D94, 0x0EC6, 0x01EC, 0x2ABB, 0x1144, 0x0340, 0x69C0,
121f29d1e0cSSheetal Tigadoli 	 0x0010, 0x0EDF, 0x90D7, 0x8000, 0x860C, 0x0003, 0x0001, 0x0000},
122f29d1e0cSSheetal Tigadoli 
123f29d1e0cSSheetal Tigadoli 	/* ddr io slave : 3p3v */
124f29d1e0cSSheetal Tigadoli 	{0x0560, 0x4438, 0x0000, 0x001F, 0x8028, 0x4444, 0x0300, 0x4380,
125f29d1e0cSSheetal Tigadoli 	 0x003F, 0x0FFF, 0x10D7, 0x8000, 0xA70C, 0x0003, 0x0001, 0x0000},
126f29d1e0cSSheetal Tigadoli 
127f29d1e0cSSheetal Tigadoli 	/* core master 3p3v */
128f29d1e0cSSheetal Tigadoli 	{0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
129f29d1e0cSSheetal Tigadoli 	 0x003F, 0x0FFF, 0x90D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
130f29d1e0cSSheetal Tigadoli 
131f29d1e0cSSheetal Tigadoli 	/* core slave 3p3v */
132f29d1e0cSSheetal Tigadoli 	{0x0560, 0x4438, 0x0000, 0x001F, 0x8028, 0x4444, 0x0300, 0x4380,
133f29d1e0cSSheetal Tigadoli 	 0x003F, 0x0FFF, 0x10D7, 0x8000, 0x240C, 0x0003, 0x0001, 0x0000},
134f29d1e0cSSheetal Tigadoli 
135f29d1e0cSSheetal Tigadoli 	/* ddr io master : 3p3v */
136f29d1e0cSSheetal Tigadoli 	{0x05E0, 0x39E5, 0x03C1, 0x007C, 0x8BA9, 0x4444, 0x3300, 0x6B80,
137f29d1e0cSSheetal Tigadoli 	 0x003F, 0x0FFF, 0x90D7, 0x8000, 0xA70C, 0x0003, 0x0001, 0x0000},
138f29d1e0cSSheetal Tigadoli };
139f29d1e0cSSheetal Tigadoli 
140f29d1e0cSSheetal Tigadoli #define FM_DATA swreg_fm_data_bx
141f29d1e0cSSheetal Tigadoli 
swreg_poll(void)142f29d1e0cSSheetal Tigadoli static int swreg_poll(void)
143f29d1e0cSSheetal Tigadoli {
144f29d1e0cSSheetal Tigadoli 	uint32_t data;
145f29d1e0cSSheetal Tigadoli 	int retry = 100;
146f29d1e0cSSheetal Tigadoli 
147f29d1e0cSSheetal Tigadoli 	do {
148f29d1e0cSSheetal Tigadoli 		data = mmio_read_32(BSTI_CONTROL_OFFSET);
149f29d1e0cSSheetal Tigadoli 		if ((data & BSTI_CONTROL_BUSY) != BSTI_CONTROL_BUSY)
150f29d1e0cSSheetal Tigadoli 			return 0;
151f29d1e0cSSheetal Tigadoli 		retry--;
152f29d1e0cSSheetal Tigadoli 		udelay(1);
153f29d1e0cSSheetal Tigadoli 	} while (retry > 0);
154f29d1e0cSSheetal Tigadoli 
155f29d1e0cSSheetal Tigadoli 	return -ETIMEDOUT;
156f29d1e0cSSheetal Tigadoli }
157f29d1e0cSSheetal Tigadoli 
write_swreg_config(enum sw_reg reg_id,uint32_t addr,uint32_t data)158f29d1e0cSSheetal Tigadoli static int write_swreg_config(enum sw_reg reg_id, uint32_t addr, uint32_t data)
159f29d1e0cSSheetal Tigadoli {
160f29d1e0cSSheetal Tigadoli 	uint32_t cmd;
161f29d1e0cSSheetal Tigadoli 	int ret;
162f29d1e0cSSheetal Tigadoli 
163f29d1e0cSSheetal Tigadoli 	cmd = BSTI_CMD(0x1, BSTI_WRITE, reg_id, addr, BSTI_COMMAND_TA, data);
164f29d1e0cSSheetal Tigadoli 	mmio_write_32(BSTI_CONTROL_OFFSET, BSTI_CONTROL_VAL);
165f29d1e0cSSheetal Tigadoli 	mmio_write_32(BSTI_COMMAND_OFFSET, cmd);
166f29d1e0cSSheetal Tigadoli 	ret = swreg_poll();
167f29d1e0cSSheetal Tigadoli 	if (ret) {
168f29d1e0cSSheetal Tigadoli 		ERROR("Failed to write swreg %s addr 0x%x\n",
169f29d1e0cSSheetal Tigadoli 			sw_reg_name[reg_id-1], addr);
170f29d1e0cSSheetal Tigadoli 		return ret;
171f29d1e0cSSheetal Tigadoli 	}
172f29d1e0cSSheetal Tigadoli 	return ret;
173f29d1e0cSSheetal Tigadoli }
174f29d1e0cSSheetal Tigadoli 
read_swreg_config(enum sw_reg reg_id,uint32_t addr,uint32_t * data)175f29d1e0cSSheetal Tigadoli static int read_swreg_config(enum sw_reg reg_id, uint32_t addr, uint32_t *data)
176f29d1e0cSSheetal Tigadoli {
177f29d1e0cSSheetal Tigadoli 	uint32_t cmd;
178f29d1e0cSSheetal Tigadoli 	int ret;
179f29d1e0cSSheetal Tigadoli 
180f29d1e0cSSheetal Tigadoli 	cmd = BSTI_CMD(0x1, BSTI_READ, reg_id, addr, BSTI_COMMAND_TA, PHY_REG0);
181f29d1e0cSSheetal Tigadoli 	mmio_write_32(BSTI_CONTROL_OFFSET, BSTI_CONTROL_VAL);
182f29d1e0cSSheetal Tigadoli 	mmio_write_32(BSTI_COMMAND_OFFSET, cmd);
183f29d1e0cSSheetal Tigadoli 	ret = swreg_poll();
184f29d1e0cSSheetal Tigadoli 	if (ret) {
185f29d1e0cSSheetal Tigadoli 		ERROR("Failed to read swreg %s addr 0x%x\n",
186f29d1e0cSSheetal Tigadoli 			sw_reg_name[reg_id-1], addr);
187f29d1e0cSSheetal Tigadoli 		return ret;
188f29d1e0cSSheetal Tigadoli 	}
189f29d1e0cSSheetal Tigadoli 
190f29d1e0cSSheetal Tigadoli 	*data = mmio_read_32(BSTI_COMMAND_OFFSET);
191f29d1e0cSSheetal Tigadoli 	*data &= BSTI_REG_DATA_MASK;
192f29d1e0cSSheetal Tigadoli 	return ret;
193f29d1e0cSSheetal Tigadoli }
194f29d1e0cSSheetal Tigadoli 
swreg_config_done(enum sw_reg reg_id)195f29d1e0cSSheetal Tigadoli static int swreg_config_done(enum sw_reg reg_id)
196f29d1e0cSSheetal Tigadoli {
197f29d1e0cSSheetal Tigadoli 	uint32_t read_data;
198f29d1e0cSSheetal Tigadoli 	int ret;
199f29d1e0cSSheetal Tigadoli 
200f29d1e0cSSheetal Tigadoli 	ret = read_swreg_config(reg_id, PHY_REG0, &read_data);
201f29d1e0cSSheetal Tigadoli 	if (ret)
202f29d1e0cSSheetal Tigadoli 		return ret;
203f29d1e0cSSheetal Tigadoli 
204f29d1e0cSSheetal Tigadoli 	read_data &= BSTI_CONFI_DONE_MASK;
205f29d1e0cSSheetal Tigadoli 	read_data |= BSTI_TOGGLE_BIT;
206f29d1e0cSSheetal Tigadoli 	ret = write_swreg_config(reg_id, PHY_REG0, read_data);
207f29d1e0cSSheetal Tigadoli 	if (ret)
208f29d1e0cSSheetal Tigadoli 		return ret;
209f29d1e0cSSheetal Tigadoli 
210f29d1e0cSSheetal Tigadoli 	ret = read_swreg_config(reg_id, PHY_REG0, &read_data);
211f29d1e0cSSheetal Tigadoli 	if (ret)
212f29d1e0cSSheetal Tigadoli 		return ret;
213f29d1e0cSSheetal Tigadoli 
214f29d1e0cSSheetal Tigadoli 	read_data &= BSTI_CONFI_DONE_MASK;
215f29d1e0cSSheetal Tigadoli 	ret = write_swreg_config(reg_id, PHY_REG0, read_data);
216f29d1e0cSSheetal Tigadoli 	if (ret)
217f29d1e0cSSheetal Tigadoli 		return ret;
218f29d1e0cSSheetal Tigadoli 
219f29d1e0cSSheetal Tigadoli 	return ret;
220f29d1e0cSSheetal Tigadoli }
221f29d1e0cSSheetal Tigadoli 
222f29d1e0cSSheetal Tigadoli #ifdef DUMP_SWREG
dump_swreg_firmware(void)223f29d1e0cSSheetal Tigadoli static void dump_swreg_firmware(void)
224f29d1e0cSSheetal Tigadoli {
225f29d1e0cSSheetal Tigadoli 	enum sw_reg reg_id;
226f29d1e0cSSheetal Tigadoli 	uint32_t data;
227f29d1e0cSSheetal Tigadoli 	int addr;
228f29d1e0cSSheetal Tigadoli 	int ret;
229f29d1e0cSSheetal Tigadoli 
230f29d1e0cSSheetal Tigadoli 	for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
231f29d1e0cSSheetal Tigadoli 		INFO("SWREG: %s\n", sw_reg_name[reg_id - 1]);
232f29d1e0cSSheetal Tigadoli 		for (addr = MIN_REG_ADDR; addr <= MAX_REG_ADDR; addr++) {
233f29d1e0cSSheetal Tigadoli 			ret = read_swreg_config(reg_id, addr, &data);
234f29d1e0cSSheetal Tigadoli 			if (ret)
235f29d1e0cSSheetal Tigadoli 				ERROR("Failed to read offset %d\n", addr);
236f29d1e0cSSheetal Tigadoli 			INFO("\t0x%x: 0x%04x\n", addr, data);
237f29d1e0cSSheetal Tigadoli 		}
238f29d1e0cSSheetal Tigadoli 	}
239f29d1e0cSSheetal Tigadoli }
240f29d1e0cSSheetal Tigadoli #endif
241f29d1e0cSSheetal Tigadoli 
set_swreg(enum sw_reg reg_id,uint32_t micro_volts)242f29d1e0cSSheetal Tigadoli int set_swreg(enum sw_reg reg_id, uint32_t micro_volts)
243f29d1e0cSSheetal Tigadoli {
244f29d1e0cSSheetal Tigadoli 	uint32_t step, programmed_step;
245f29d1e0cSSheetal Tigadoli 	uint32_t data = IHOST_VDDC_DATA;
246f29d1e0cSSheetal Tigadoli 	int ret;
247f29d1e0cSSheetal Tigadoli 
248f29d1e0cSSheetal Tigadoli 	if ((micro_volts > MAX_VOLT) || (micro_volts < MIN_VOLT)) {
249f29d1e0cSSheetal Tigadoli 		ERROR("input voltage out-of-range\n");
250f29d1e0cSSheetal Tigadoli 		ret = -EINVAL;
251f29d1e0cSSheetal Tigadoli 		goto failed;
252f29d1e0cSSheetal Tigadoli 	}
253f29d1e0cSSheetal Tigadoli 
254f29d1e0cSSheetal Tigadoli 	ret = read_swreg_config(reg_id, PHY_REGC, &programmed_step);
255f29d1e0cSSheetal Tigadoli 	if (ret)
256f29d1e0cSSheetal Tigadoli 		goto failed;
257f29d1e0cSSheetal Tigadoli 
258f29d1e0cSSheetal Tigadoli 	if (reg_id == DDR_VDDC)
259f29d1e0cSSheetal Tigadoli 		step = B0_DDR_VDDC_STEP_VALUE(micro_volts);
260f29d1e0cSSheetal Tigadoli 	else
261f29d1e0cSSheetal Tigadoli 		step = B0_STEP_VALUE(micro_volts);
262f29d1e0cSSheetal Tigadoli 
263f29d1e0cSSheetal Tigadoli 	if ((step >> 8) != (programmed_step >> 8)) {
264f29d1e0cSSheetal Tigadoli 		ret = write_swreg_config(reg_id, PHY_REGC, step);
265f29d1e0cSSheetal Tigadoli 		if (ret)
266f29d1e0cSSheetal Tigadoli 			goto failed;
267f29d1e0cSSheetal Tigadoli 
268f29d1e0cSSheetal Tigadoli 		if (reg_id == DDR_VDDC)
269f29d1e0cSSheetal Tigadoli 			data = DDR_CORE_DATA;
270f29d1e0cSSheetal Tigadoli 
271f29d1e0cSSheetal Tigadoli 		ret = write_swreg_config(reg_id, PHY_REG0,
272f29d1e0cSSheetal Tigadoli 					UPDATE_POS_EDGE(data, 1));
273f29d1e0cSSheetal Tigadoli 		if (ret)
274f29d1e0cSSheetal Tigadoli 			goto failed;
275f29d1e0cSSheetal Tigadoli 
276f29d1e0cSSheetal Tigadoli 		ret = write_swreg_config(reg_id, PHY_REG0,
277f29d1e0cSSheetal Tigadoli 					UPDATE_POS_EDGE(data, 0));
278f29d1e0cSSheetal Tigadoli 		if (ret)
279f29d1e0cSSheetal Tigadoli 			goto failed;
280f29d1e0cSSheetal Tigadoli 	}
281f29d1e0cSSheetal Tigadoli 
282f29d1e0cSSheetal Tigadoli 	INFO("%s voltage updated to %duV\n", sw_reg_name[reg_id-1],
283f29d1e0cSSheetal Tigadoli 		micro_volts);
284f29d1e0cSSheetal Tigadoli 	return ret;
285f29d1e0cSSheetal Tigadoli 
286f29d1e0cSSheetal Tigadoli failed:
287f29d1e0cSSheetal Tigadoli 	/*
288f29d1e0cSSheetal Tigadoli 	 * Stop booting if voltages are not set
289f29d1e0cSSheetal Tigadoli 	 * correctly. Booting will fail at random point
290f29d1e0cSSheetal Tigadoli 	 * if we continue with wrong voltage settings.
291f29d1e0cSSheetal Tigadoli 	 */
292f29d1e0cSSheetal Tigadoli 	ERROR("Failed to set %s voltage to %duV\n", sw_reg_name[reg_id-1],
293f29d1e0cSSheetal Tigadoli 		micro_volts);
294f29d1e0cSSheetal Tigadoli 	assert(0);
295f29d1e0cSSheetal Tigadoli 
296f29d1e0cSSheetal Tigadoli 	return ret;
297f29d1e0cSSheetal Tigadoli }
298f29d1e0cSSheetal Tigadoli 
299*1b491eeaSElyes Haouas /* Update SWREG firmware for all power domain for A2 chip */
swreg_firmware_update(void)300f29d1e0cSSheetal Tigadoli int swreg_firmware_update(void)
301f29d1e0cSSheetal Tigadoli {
302f29d1e0cSSheetal Tigadoli 	enum sw_reg reg_id;
303f29d1e0cSSheetal Tigadoli 	uint32_t data;
304f29d1e0cSSheetal Tigadoli 	int addr;
305f29d1e0cSSheetal Tigadoli 	int ret;
306f29d1e0cSSheetal Tigadoli 
307f29d1e0cSSheetal Tigadoli 	/* write firmware values */
308f29d1e0cSSheetal Tigadoli 	for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
309f29d1e0cSSheetal Tigadoli 		/* write higher location first */
310f29d1e0cSSheetal Tigadoli 		for (addr = MAX_REG_ADDR; addr >= MIN_REG_ADDR; addr--) {
311f29d1e0cSSheetal Tigadoli 			ret = write_swreg_config(reg_id, addr,
312f29d1e0cSSheetal Tigadoli 						 FM_DATA[reg_id - 1][addr]);
313f29d1e0cSSheetal Tigadoli 			if (ret)
314f29d1e0cSSheetal Tigadoli 				goto exit;
315f29d1e0cSSheetal Tigadoli 		}
316f29d1e0cSSheetal Tigadoli 	}
317f29d1e0cSSheetal Tigadoli 
318f29d1e0cSSheetal Tigadoli 	/* trigger SWREG firmware update */
319f29d1e0cSSheetal Tigadoli 	for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
320f29d1e0cSSheetal Tigadoli 		/*
321f29d1e0cSSheetal Tigadoli 		 * Slave regulator doesn't have to be updated,
322f29d1e0cSSheetal Tigadoli 		 * Updating Master is enough
323f29d1e0cSSheetal Tigadoli 		 */
324f29d1e0cSSheetal Tigadoli 		if ((reg_id == DDRIO_SLAVE) || (reg_id == VDDC1))
325f29d1e0cSSheetal Tigadoli 			continue;
326f29d1e0cSSheetal Tigadoli 
327f29d1e0cSSheetal Tigadoli 		ret = swreg_config_done(reg_id);
328f29d1e0cSSheetal Tigadoli 		if (ret) {
329f29d1e0cSSheetal Tigadoli 			ERROR("Failed to trigger SWREG firmware update for %s\n"
330f29d1e0cSSheetal Tigadoli 				, sw_reg_name[reg_id-1]);
331f29d1e0cSSheetal Tigadoli 			return ret;
332f29d1e0cSSheetal Tigadoli 		}
333f29d1e0cSSheetal Tigadoli 	}
334f29d1e0cSSheetal Tigadoli 
335f29d1e0cSSheetal Tigadoli 	for (reg_id = DDR_VDDC; reg_id <= DDRIO_MASTER; reg_id++) {
336f29d1e0cSSheetal Tigadoli 		/*
337f29d1e0cSSheetal Tigadoli 		 * IHOST_ARRAY will be used on some boards like STRATUS and
338f29d1e0cSSheetal Tigadoli 		 * there will not be any issue even if it is updated on other
339f29d1e0cSSheetal Tigadoli 		 * boards where it is not used.
340f29d1e0cSSheetal Tigadoli 		 */
341f29d1e0cSSheetal Tigadoli 		if (reg_id == IHOST_ARRAY)
342f29d1e0cSSheetal Tigadoli 			continue;
343f29d1e0cSSheetal Tigadoli 
344f29d1e0cSSheetal Tigadoli 		for (addr = MIN_REG_ADDR; addr <= MAX_REG_ADDR; addr++) {
345f29d1e0cSSheetal Tigadoli 			ret = read_swreg_config(reg_id, addr, &data);
346f29d1e0cSSheetal Tigadoli 			if (ret || (!ret &&
347f29d1e0cSSheetal Tigadoli 				(data != FM_DATA[reg_id - 1][addr]))) {
348f29d1e0cSSheetal Tigadoli 				ERROR("swreg fm update failed: %s at off %d\n",
349f29d1e0cSSheetal Tigadoli 					sw_reg_name[reg_id - 1], addr);
350f29d1e0cSSheetal Tigadoli 				ERROR("Read val: 0x%x, expected val: 0x%x\n",
351f29d1e0cSSheetal Tigadoli 					data, FM_DATA[reg_id - 1][addr]);
352f29d1e0cSSheetal Tigadoli 				return -1;
353f29d1e0cSSheetal Tigadoli 			}
354f29d1e0cSSheetal Tigadoli 		}
355f29d1e0cSSheetal Tigadoli 	}
356f29d1e0cSSheetal Tigadoli 
357f29d1e0cSSheetal Tigadoli 	INFO("Updated SWREG firmware\n");
358f29d1e0cSSheetal Tigadoli 
359f29d1e0cSSheetal Tigadoli #ifdef DUMP_SWREG
360f29d1e0cSSheetal Tigadoli 	dump_swreg_firmware();
361f29d1e0cSSheetal Tigadoli #endif
362f29d1e0cSSheetal Tigadoli 	return ret;
363f29d1e0cSSheetal Tigadoli 
364f29d1e0cSSheetal Tigadoli exit:
365f29d1e0cSSheetal Tigadoli 	/*
366f29d1e0cSSheetal Tigadoli 	 * Stop booting if swreg firmware update fails.
367f29d1e0cSSheetal Tigadoli 	 * Booting will fail at random point if we
368f29d1e0cSSheetal Tigadoli 	 * continue with wrong voltage settings.
369f29d1e0cSSheetal Tigadoli 	 */
370f29d1e0cSSheetal Tigadoli 	ERROR("Failed to update firmware for %s SWREG\n",
371f29d1e0cSSheetal Tigadoli 		sw_reg_name[reg_id-1]);
372f29d1e0cSSheetal Tigadoli 	assert(0);
373f29d1e0cSSheetal Tigadoli 
374f29d1e0cSSheetal Tigadoli 	return ret;
375f29d1e0cSSheetal Tigadoli }
376