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