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