1*1cb19fbbSYork Sun /* 2*1cb19fbbSYork Sun * Copyright 2009-2012 Freescale Semiconductor, Inc. 3*1cb19fbbSYork Sun * 4*1cb19fbbSYork Sun * See file CREDITS for list of people who contributed to this 5*1cb19fbbSYork Sun * project. 6*1cb19fbbSYork Sun * 7*1cb19fbbSYork Sun * This program is free software; you can redistribute it and/or 8*1cb19fbbSYork Sun * modify it under the terms of the GNU General Public License as 9*1cb19fbbSYork Sun * published by the Free Software Foundation; either version 2 of 10*1cb19fbbSYork Sun * the License, or (at your option) any later version. 11*1cb19fbbSYork Sun * 12*1cb19fbbSYork Sun * This program is distributed in the hope that it will be useful, 13*1cb19fbbSYork Sun * but WITHOUT ANY WARRANTY; without even the implied warranty of 14*1cb19fbbSYork Sun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*1cb19fbbSYork Sun * GNU General Public License for more details. 16*1cb19fbbSYork Sun * 17*1cb19fbbSYork Sun * You should have received a copy of the GNU General Public License 18*1cb19fbbSYork Sun * along with this program; if not, write to the Free Software 19*1cb19fbbSYork Sun * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20*1cb19fbbSYork Sun * MA 02111-1307 USA 21*1cb19fbbSYork Sun */ 22*1cb19fbbSYork Sun 23*1cb19fbbSYork Sun #include <common.h> 24*1cb19fbbSYork Sun #include <command.h> 25*1cb19fbbSYork Sun #include <i2c.h> 26*1cb19fbbSYork Sun #include <netdev.h> 27*1cb19fbbSYork Sun #include <linux/compiler.h> 28*1cb19fbbSYork Sun #include <asm/mmu.h> 29*1cb19fbbSYork Sun #include <asm/processor.h> 30*1cb19fbbSYork Sun #include <asm/cache.h> 31*1cb19fbbSYork Sun #include <asm/immap_85xx.h> 32*1cb19fbbSYork Sun #include <asm/fsl_law.h> 33*1cb19fbbSYork Sun #include <asm/fsl_serdes.h> 34*1cb19fbbSYork Sun #include <asm/fsl_portals.h> 35*1cb19fbbSYork Sun #include <asm/fsl_liodn.h> 36*1cb19fbbSYork Sun #include <fm_eth.h> 37*1cb19fbbSYork Sun 38*1cb19fbbSYork Sun #include "../common/qixis.h" 39*1cb19fbbSYork Sun #include "../common/vsc3316_3308.h" 40*1cb19fbbSYork Sun #include "t4qds.h" 41*1cb19fbbSYork Sun #include "t4240qds_qixis.h" 42*1cb19fbbSYork Sun 43*1cb19fbbSYork Sun DECLARE_GLOBAL_DATA_PTR; 44*1cb19fbbSYork Sun 45*1cb19fbbSYork Sun static const int8_t vsc3316_fsm1_tx[8][2] = { {0, 0}, {1, 1}, {6, 6}, {7, 7}, 46*1cb19fbbSYork Sun {8, 8}, {9, 9}, {14, 14}, {15, 15} }; 47*1cb19fbbSYork Sun 48*1cb19fbbSYork Sun static const int8_t vsc3316_fsm2_tx[8][2] = { {2, 2}, {3, 3}, {4, 4}, {5, 5}, 49*1cb19fbbSYork Sun {10, 10}, {11, 11}, {12, 12}, {13, 13} }; 50*1cb19fbbSYork Sun 51*1cb19fbbSYork Sun static const int8_t vsc3316_fsm1_rx[8][2] = { {2, 12}, {3, 13}, {4, 5}, {5, 4}, 52*1cb19fbbSYork Sun {10, 11}, {11, 10}, {12, 2}, {13, 3} }; 53*1cb19fbbSYork Sun 54*1cb19fbbSYork Sun static const int8_t vsc3316_fsm2_rx[8][2] = { {0, 15}, {1, 14}, {6, 7}, {7, 6}, 55*1cb19fbbSYork Sun {8, 9}, {9, 8}, {14, 1}, {15, 0} }; 56*1cb19fbbSYork Sun 57*1cb19fbbSYork Sun int checkboard(void) 58*1cb19fbbSYork Sun { 59*1cb19fbbSYork Sun char buf[64]; 60*1cb19fbbSYork Sun u8 sw; 61*1cb19fbbSYork Sun struct cpu_type *cpu = gd->arch.cpu; 62*1cb19fbbSYork Sun unsigned int i; 63*1cb19fbbSYork Sun 64*1cb19fbbSYork Sun printf("Board: %sQDS, ", cpu->name); 65*1cb19fbbSYork Sun printf("Sys ID: 0x%02x, Sys Ver: 0x%02x, ", 66*1cb19fbbSYork Sun QIXIS_READ(id), QIXIS_READ(arch)); 67*1cb19fbbSYork Sun 68*1cb19fbbSYork Sun sw = QIXIS_READ(brdcfg[0]); 69*1cb19fbbSYork Sun sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT; 70*1cb19fbbSYork Sun 71*1cb19fbbSYork Sun if (sw < 0x8) 72*1cb19fbbSYork Sun printf("vBank: %d\n", sw); 73*1cb19fbbSYork Sun else if (sw == 0x8) 74*1cb19fbbSYork Sun puts("Promjet\n"); 75*1cb19fbbSYork Sun else if (sw == 0x9) 76*1cb19fbbSYork Sun puts("NAND\n"); 77*1cb19fbbSYork Sun else 78*1cb19fbbSYork Sun printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH); 79*1cb19fbbSYork Sun 80*1cb19fbbSYork Sun printf("FPGA: v%d (%s), build %d", 81*1cb19fbbSYork Sun (int)QIXIS_READ(scver), qixis_read_tag(buf), 82*1cb19fbbSYork Sun (int)qixis_read_minor()); 83*1cb19fbbSYork Sun /* the timestamp string contains "\n" at the end */ 84*1cb19fbbSYork Sun printf(" on %s", qixis_read_time(buf)); 85*1cb19fbbSYork Sun 86*1cb19fbbSYork Sun /* 87*1cb19fbbSYork Sun * Display the actual SERDES reference clocks as configured by the 88*1cb19fbbSYork Sun * dip switches on the board. Note that the SWx registers could 89*1cb19fbbSYork Sun * technically be set to force the reference clocks to match the 90*1cb19fbbSYork Sun * values that the SERDES expects (or vice versa). For now, however, 91*1cb19fbbSYork Sun * we just display both values and hope the user notices when they 92*1cb19fbbSYork Sun * don't match. 93*1cb19fbbSYork Sun */ 94*1cb19fbbSYork Sun puts("SERDES Reference Clocks: "); 95*1cb19fbbSYork Sun sw = QIXIS_READ(brdcfg[2]); 96*1cb19fbbSYork Sun for (i = 0; i < MAX_SERDES; i++) { 97*1cb19fbbSYork Sun static const char * const freq[] = { 98*1cb19fbbSYork Sun "100", "125", "156.25", "161.1328125"}; 99*1cb19fbbSYork Sun unsigned int clock = (sw >> (6 - 2 * i)) & 3; 100*1cb19fbbSYork Sun 101*1cb19fbbSYork Sun printf("SERDES%u=%sMHz ", i+1, freq[clock]); 102*1cb19fbbSYork Sun } 103*1cb19fbbSYork Sun puts("\n"); 104*1cb19fbbSYork Sun 105*1cb19fbbSYork Sun return 0; 106*1cb19fbbSYork Sun } 107*1cb19fbbSYork Sun 108*1cb19fbbSYork Sun int select_i2c_ch_pca9547(u8 ch) 109*1cb19fbbSYork Sun { 110*1cb19fbbSYork Sun int ret; 111*1cb19fbbSYork Sun 112*1cb19fbbSYork Sun ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1); 113*1cb19fbbSYork Sun if (ret) { 114*1cb19fbbSYork Sun puts("PCA: failed to select proper channel\n"); 115*1cb19fbbSYork Sun return ret; 116*1cb19fbbSYork Sun } 117*1cb19fbbSYork Sun 118*1cb19fbbSYork Sun return 0; 119*1cb19fbbSYork Sun } 120*1cb19fbbSYork Sun 121*1cb19fbbSYork Sun /* 122*1cb19fbbSYork Sun * read_voltage from sensor on I2C bus 123*1cb19fbbSYork Sun * We use average of 4 readings, waiting for 532us befor another reading 124*1cb19fbbSYork Sun */ 125*1cb19fbbSYork Sun #define NUM_READINGS 4 /* prefer to be power of 2 for efficiency */ 126*1cb19fbbSYork Sun #define WAIT_FOR_ADC 532 /* wait for 532 microseconds for ADC */ 127*1cb19fbbSYork Sun 128*1cb19fbbSYork Sun static inline int read_voltage(void) 129*1cb19fbbSYork Sun { 130*1cb19fbbSYork Sun int i, ret, voltage_read = 0; 131*1cb19fbbSYork Sun u16 vol_mon; 132*1cb19fbbSYork Sun 133*1cb19fbbSYork Sun for (i = 0; i < NUM_READINGS; i++) { 134*1cb19fbbSYork Sun ret = i2c_read(I2C_VOL_MONITOR_ADDR, 135*1cb19fbbSYork Sun I2C_VOL_MONITOR_BUS_V_OFFSET, 1, (void *)&vol_mon, 2); 136*1cb19fbbSYork Sun if (ret) { 137*1cb19fbbSYork Sun printf("VID: failed to read core voltage\n"); 138*1cb19fbbSYork Sun return ret; 139*1cb19fbbSYork Sun } 140*1cb19fbbSYork Sun if (vol_mon & I2C_VOL_MONITOR_BUS_V_OVF) { 141*1cb19fbbSYork Sun printf("VID: Core voltage sensor error\n"); 142*1cb19fbbSYork Sun return -1; 143*1cb19fbbSYork Sun } 144*1cb19fbbSYork Sun debug("VID: bus voltage reads 0x%04x\n", vol_mon); 145*1cb19fbbSYork Sun /* LSB = 4mv */ 146*1cb19fbbSYork Sun voltage_read += (vol_mon >> I2C_VOL_MONITOR_BUS_V_SHIFT) * 4; 147*1cb19fbbSYork Sun udelay(WAIT_FOR_ADC); 148*1cb19fbbSYork Sun } 149*1cb19fbbSYork Sun /* calculate the average */ 150*1cb19fbbSYork Sun voltage_read /= NUM_READINGS; 151*1cb19fbbSYork Sun 152*1cb19fbbSYork Sun return voltage_read; 153*1cb19fbbSYork Sun } 154*1cb19fbbSYork Sun 155*1cb19fbbSYork Sun /* 156*1cb19fbbSYork Sun * We need to calculate how long before the voltage starts to drop or increase 157*1cb19fbbSYork Sun * It returns with the loop count. Each loop takes several readings (532us) 158*1cb19fbbSYork Sun */ 159*1cb19fbbSYork Sun static inline int wait_for_voltage_change(int vdd_last) 160*1cb19fbbSYork Sun { 161*1cb19fbbSYork Sun int timeout, vdd_current; 162*1cb19fbbSYork Sun 163*1cb19fbbSYork Sun vdd_current = read_voltage(); 164*1cb19fbbSYork Sun /* wait until voltage starts to drop */ 165*1cb19fbbSYork Sun for (timeout = 0; abs(vdd_last - vdd_current) <= 4 && 166*1cb19fbbSYork Sun timeout < 100; timeout++) { 167*1cb19fbbSYork Sun vdd_current = read_voltage(); 168*1cb19fbbSYork Sun } 169*1cb19fbbSYork Sun if (timeout >= 100) { 170*1cb19fbbSYork Sun printf("VID: Voltage adjustment timeout\n"); 171*1cb19fbbSYork Sun return -1; 172*1cb19fbbSYork Sun } 173*1cb19fbbSYork Sun return timeout; 174*1cb19fbbSYork Sun } 175*1cb19fbbSYork Sun 176*1cb19fbbSYork Sun /* 177*1cb19fbbSYork Sun * argument 'wait' is the time we know the voltage difference can be measured 178*1cb19fbbSYork Sun * this function keeps reading the voltage until it is stable 179*1cb19fbbSYork Sun */ 180*1cb19fbbSYork Sun static inline int wait_for_voltage_stable(int wait) 181*1cb19fbbSYork Sun { 182*1cb19fbbSYork Sun int timeout, vdd_current, vdd_last; 183*1cb19fbbSYork Sun 184*1cb19fbbSYork Sun vdd_last = read_voltage(); 185*1cb19fbbSYork Sun udelay(wait * NUM_READINGS * WAIT_FOR_ADC); 186*1cb19fbbSYork Sun /* wait until voltage is stable */ 187*1cb19fbbSYork Sun vdd_current = read_voltage(); 188*1cb19fbbSYork Sun for (timeout = 0; abs(vdd_last - vdd_current) >= 4 && 189*1cb19fbbSYork Sun timeout < 100; timeout++) { 190*1cb19fbbSYork Sun vdd_last = vdd_current; 191*1cb19fbbSYork Sun udelay(wait * NUM_READINGS * WAIT_FOR_ADC); 192*1cb19fbbSYork Sun vdd_current = read_voltage(); 193*1cb19fbbSYork Sun } 194*1cb19fbbSYork Sun if (timeout >= 100) { 195*1cb19fbbSYork Sun printf("VID: Voltage adjustment timeout\n"); 196*1cb19fbbSYork Sun return -1; 197*1cb19fbbSYork Sun } 198*1cb19fbbSYork Sun 199*1cb19fbbSYork Sun return vdd_current; 200*1cb19fbbSYork Sun } 201*1cb19fbbSYork Sun 202*1cb19fbbSYork Sun static inline int set_voltage(u8 vid) 203*1cb19fbbSYork Sun { 204*1cb19fbbSYork Sun int wait, vdd_last; 205*1cb19fbbSYork Sun 206*1cb19fbbSYork Sun vdd_last = read_voltage(); 207*1cb19fbbSYork Sun QIXIS_WRITE(brdcfg[6], vid); 208*1cb19fbbSYork Sun wait = wait_for_voltage_change(vdd_last); 209*1cb19fbbSYork Sun if (wait < 0) 210*1cb19fbbSYork Sun return -1; 211*1cb19fbbSYork Sun debug("VID: Waited %d us\n", wait * NUM_READINGS * WAIT_FOR_ADC); 212*1cb19fbbSYork Sun wait = wait ? wait : 1; 213*1cb19fbbSYork Sun 214*1cb19fbbSYork Sun vdd_last = wait_for_voltage_stable(wait); 215*1cb19fbbSYork Sun if (vdd_last < 0) 216*1cb19fbbSYork Sun return -1; 217*1cb19fbbSYork Sun debug("VID: Current voltage is %d mV\n", vdd_last); 218*1cb19fbbSYork Sun 219*1cb19fbbSYork Sun return vdd_last; 220*1cb19fbbSYork Sun } 221*1cb19fbbSYork Sun 222*1cb19fbbSYork Sun 223*1cb19fbbSYork Sun static int adjust_vdd(ulong vdd_override) 224*1cb19fbbSYork Sun { 225*1cb19fbbSYork Sun int re_enable = disable_interrupts(); 226*1cb19fbbSYork Sun ccsr_gur_t __iomem *gur = 227*1cb19fbbSYork Sun (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 228*1cb19fbbSYork Sun u32 fusesr; 229*1cb19fbbSYork Sun u8 vid, vid_current; 230*1cb19fbbSYork Sun int vdd_target, vdd_current, vdd_last; 231*1cb19fbbSYork Sun int ret; 232*1cb19fbbSYork Sun unsigned long vdd_string_override; 233*1cb19fbbSYork Sun char *vdd_string; 234*1cb19fbbSYork Sun static const uint16_t vdd[32] = { 235*1cb19fbbSYork Sun 0, /* unused */ 236*1cb19fbbSYork Sun 9875, /* 0.9875V */ 237*1cb19fbbSYork Sun 9750, 238*1cb19fbbSYork Sun 9625, 239*1cb19fbbSYork Sun 9500, 240*1cb19fbbSYork Sun 9375, 241*1cb19fbbSYork Sun 9250, 242*1cb19fbbSYork Sun 9125, 243*1cb19fbbSYork Sun 9000, 244*1cb19fbbSYork Sun 8875, 245*1cb19fbbSYork Sun 8750, 246*1cb19fbbSYork Sun 8625, 247*1cb19fbbSYork Sun 8500, 248*1cb19fbbSYork Sun 8375, 249*1cb19fbbSYork Sun 8250, 250*1cb19fbbSYork Sun 8125, 251*1cb19fbbSYork Sun 10000, /* 1.0000V */ 252*1cb19fbbSYork Sun 10125, 253*1cb19fbbSYork Sun 10250, 254*1cb19fbbSYork Sun 10375, 255*1cb19fbbSYork Sun 10500, 256*1cb19fbbSYork Sun 10625, 257*1cb19fbbSYork Sun 10750, 258*1cb19fbbSYork Sun 10875, 259*1cb19fbbSYork Sun 11000, 260*1cb19fbbSYork Sun 0, /* reserved */ 261*1cb19fbbSYork Sun }; 262*1cb19fbbSYork Sun struct vdd_drive { 263*1cb19fbbSYork Sun u8 vid; 264*1cb19fbbSYork Sun unsigned voltage; 265*1cb19fbbSYork Sun }; 266*1cb19fbbSYork Sun 267*1cb19fbbSYork Sun ret = select_i2c_ch_pca9547(I2C_MUX_CH_VOL_MONITOR); 268*1cb19fbbSYork Sun if (ret) { 269*1cb19fbbSYork Sun debug("VID: I2c failed to switch channel\n"); 270*1cb19fbbSYork Sun ret = -1; 271*1cb19fbbSYork Sun goto exit; 272*1cb19fbbSYork Sun } 273*1cb19fbbSYork Sun 274*1cb19fbbSYork Sun /* get the voltage ID from fuse status register */ 275*1cb19fbbSYork Sun fusesr = in_be32(&gur->dcfg_fusesr); 276*1cb19fbbSYork Sun vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_VID_SHIFT) & 277*1cb19fbbSYork Sun FSL_CORENET_DCFG_FUSESR_VID_MASK; 278*1cb19fbbSYork Sun if (vid == FSL_CORENET_DCFG_FUSESR_VID_MASK) { 279*1cb19fbbSYork Sun vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_ALTVID_SHIFT) & 280*1cb19fbbSYork Sun FSL_CORENET_DCFG_FUSESR_ALTVID_MASK; 281*1cb19fbbSYork Sun } 282*1cb19fbbSYork Sun vdd_target = vdd[vid]; 283*1cb19fbbSYork Sun 284*1cb19fbbSYork Sun /* check override variable for overriding VDD */ 285*1cb19fbbSYork Sun vdd_string = getenv("t4240qds_vdd_mv"); 286*1cb19fbbSYork Sun if (vdd_override == 0 && vdd_string && 287*1cb19fbbSYork Sun !strict_strtoul(vdd_string, 10, &vdd_string_override)) 288*1cb19fbbSYork Sun vdd_override = vdd_string_override; 289*1cb19fbbSYork Sun if (vdd_override >= 819 && vdd_override <= 1212) { 290*1cb19fbbSYork Sun vdd_target = vdd_override * 10; /* convert to 1/10 mV */ 291*1cb19fbbSYork Sun debug("VDD override is %lu\n", vdd_override); 292*1cb19fbbSYork Sun } else if (vdd_override != 0) { 293*1cb19fbbSYork Sun printf("Invalid value.\n"); 294*1cb19fbbSYork Sun } 295*1cb19fbbSYork Sun 296*1cb19fbbSYork Sun if (vdd_target == 0) { 297*1cb19fbbSYork Sun debug("VID: VID not used\n"); 298*1cb19fbbSYork Sun ret = 0; 299*1cb19fbbSYork Sun goto exit; 300*1cb19fbbSYork Sun } else { 301*1cb19fbbSYork Sun /* round up and divice by 10 to get a value in mV */ 302*1cb19fbbSYork Sun vdd_target = DIV_ROUND_UP(vdd_target, 10); 303*1cb19fbbSYork Sun debug("VID: vid = %d mV\n", vdd_target); 304*1cb19fbbSYork Sun } 305*1cb19fbbSYork Sun 306*1cb19fbbSYork Sun /* 307*1cb19fbbSYork Sun * Check current board VID setting 308*1cb19fbbSYork Sun * Voltage regulator support output to 6.250mv step 309*1cb19fbbSYork Sun * The highes voltage allowed for this board is (vid=0x40) 1.21250V 310*1cb19fbbSYork Sun * the lowest is (vid=0x7f) 0.81875V 311*1cb19fbbSYork Sun */ 312*1cb19fbbSYork Sun vid_current = QIXIS_READ(brdcfg[6]); 313*1cb19fbbSYork Sun vdd_current = 121250 - (vid_current - 0x40) * 625; 314*1cb19fbbSYork Sun debug("VID: Current vid setting is (0x%x) %d mV\n", 315*1cb19fbbSYork Sun vid_current, vdd_current/100); 316*1cb19fbbSYork Sun 317*1cb19fbbSYork Sun /* 318*1cb19fbbSYork Sun * Read voltage monitor to check real voltage. 319*1cb19fbbSYork Sun * Voltage monitor LSB is 4mv. 320*1cb19fbbSYork Sun */ 321*1cb19fbbSYork Sun vdd_last = read_voltage(); 322*1cb19fbbSYork Sun if (vdd_last < 0) { 323*1cb19fbbSYork Sun printf("VID: Could not read voltage sensor abort VID adjustment\n"); 324*1cb19fbbSYork Sun ret = -1; 325*1cb19fbbSYork Sun goto exit; 326*1cb19fbbSYork Sun } 327*1cb19fbbSYork Sun debug("VID: Core voltage is at %d mV\n", vdd_last); 328*1cb19fbbSYork Sun /* 329*1cb19fbbSYork Sun * Adjust voltage to at or 8mV above target. 330*1cb19fbbSYork Sun * Each step of adjustment is 6.25mV. 331*1cb19fbbSYork Sun * Stepping down too fast may cause over current. 332*1cb19fbbSYork Sun */ 333*1cb19fbbSYork Sun while (vdd_last > 0 && vid_current < 0x80 && 334*1cb19fbbSYork Sun vdd_last > (vdd_target + 8)) { 335*1cb19fbbSYork Sun vid_current++; 336*1cb19fbbSYork Sun vdd_last = set_voltage(vid_current); 337*1cb19fbbSYork Sun } 338*1cb19fbbSYork Sun /* 339*1cb19fbbSYork Sun * Check if we need to step up 340*1cb19fbbSYork Sun * This happens when board voltage switch was set too low 341*1cb19fbbSYork Sun */ 342*1cb19fbbSYork Sun while (vdd_last > 0 && vid_current >= 0x40 && 343*1cb19fbbSYork Sun vdd_last < vdd_target + 2) { 344*1cb19fbbSYork Sun vid_current--; 345*1cb19fbbSYork Sun vdd_last = set_voltage(vid_current); 346*1cb19fbbSYork Sun } 347*1cb19fbbSYork Sun if (vdd_last > 0) 348*1cb19fbbSYork Sun printf("VID: Core voltage %d mV\n", vdd_last); 349*1cb19fbbSYork Sun else 350*1cb19fbbSYork Sun ret = -1; 351*1cb19fbbSYork Sun 352*1cb19fbbSYork Sun exit: 353*1cb19fbbSYork Sun if (re_enable) 354*1cb19fbbSYork Sun enable_interrupts(); 355*1cb19fbbSYork Sun return ret; 356*1cb19fbbSYork Sun } 357*1cb19fbbSYork Sun 358*1cb19fbbSYork Sun /* Configure Crossbar switches for Front-Side SerDes Ports */ 359*1cb19fbbSYork Sun int config_frontside_crossbar_vsc3316(void) 360*1cb19fbbSYork Sun { 361*1cb19fbbSYork Sun ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 362*1cb19fbbSYork Sun u32 srds_prtcl_s1, srds_prtcl_s2; 363*1cb19fbbSYork Sun int ret; 364*1cb19fbbSYork Sun 365*1cb19fbbSYork Sun ret = select_i2c_ch_pca9547(I2C_MUX_CH_VSC3316_FS); 366*1cb19fbbSYork Sun if (ret) 367*1cb19fbbSYork Sun return ret; 368*1cb19fbbSYork Sun 369*1cb19fbbSYork Sun srds_prtcl_s1 = in_be32(&gur->rcwsr[4]) & 370*1cb19fbbSYork Sun FSL_CORENET2_RCWSR4_SRDS1_PRTCL; 371*1cb19fbbSYork Sun srds_prtcl_s1 >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT; 372*1cb19fbbSYork Sun if (srds_prtcl_s1) { 373*1cb19fbbSYork Sun ret = vsc3316_config(VSC3316_FSM_TX_ADDR, vsc3316_fsm1_tx, 8); 374*1cb19fbbSYork Sun if (ret) 375*1cb19fbbSYork Sun return ret; 376*1cb19fbbSYork Sun ret = vsc3316_config(VSC3316_FSM_RX_ADDR, vsc3316_fsm1_rx, 8); 377*1cb19fbbSYork Sun if (ret) 378*1cb19fbbSYork Sun return ret; 379*1cb19fbbSYork Sun } 380*1cb19fbbSYork Sun 381*1cb19fbbSYork Sun srds_prtcl_s2 = in_be32(&gur->rcwsr[4]) & 382*1cb19fbbSYork Sun FSL_CORENET2_RCWSR4_SRDS2_PRTCL; 383*1cb19fbbSYork Sun srds_prtcl_s2 >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT; 384*1cb19fbbSYork Sun if (srds_prtcl_s2) { 385*1cb19fbbSYork Sun ret = vsc3316_config(VSC3316_FSM_TX_ADDR, vsc3316_fsm2_tx, 8); 386*1cb19fbbSYork Sun if (ret) 387*1cb19fbbSYork Sun return ret; 388*1cb19fbbSYork Sun ret = vsc3316_config(VSC3316_FSM_RX_ADDR, vsc3316_fsm2_rx, 8); 389*1cb19fbbSYork Sun if (ret) 390*1cb19fbbSYork Sun return ret; 391*1cb19fbbSYork Sun } 392*1cb19fbbSYork Sun 393*1cb19fbbSYork Sun return 0; 394*1cb19fbbSYork Sun } 395*1cb19fbbSYork Sun 396*1cb19fbbSYork Sun int config_backside_crossbar_mux(void) 397*1cb19fbbSYork Sun { 398*1cb19fbbSYork Sun ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 399*1cb19fbbSYork Sun u32 srds_prtcl_s3, srds_prtcl_s4; 400*1cb19fbbSYork Sun u8 brdcfg; 401*1cb19fbbSYork Sun 402*1cb19fbbSYork Sun srds_prtcl_s3 = in_be32(&gur->rcwsr[4]) & 403*1cb19fbbSYork Sun FSL_CORENET2_RCWSR4_SRDS3_PRTCL; 404*1cb19fbbSYork Sun srds_prtcl_s3 >>= FSL_CORENET2_RCWSR4_SRDS3_PRTCL_SHIFT; 405*1cb19fbbSYork Sun switch (srds_prtcl_s3) { 406*1cb19fbbSYork Sun case 0: 407*1cb19fbbSYork Sun /* SerDes3 is not enabled */ 408*1cb19fbbSYork Sun break; 409*1cb19fbbSYork Sun case 2: 410*1cb19fbbSYork Sun case 9: 411*1cb19fbbSYork Sun case 10: 412*1cb19fbbSYork Sun /* SD3(0:7) => SLOT5(0:7) */ 413*1cb19fbbSYork Sun brdcfg = QIXIS_READ(brdcfg[12]); 414*1cb19fbbSYork Sun brdcfg &= ~BRDCFG12_SD3MX_MASK; 415*1cb19fbbSYork Sun brdcfg |= BRDCFG12_SD3MX_SLOT5; 416*1cb19fbbSYork Sun QIXIS_WRITE(brdcfg[12], brdcfg); 417*1cb19fbbSYork Sun break; 418*1cb19fbbSYork Sun case 4: 419*1cb19fbbSYork Sun case 6: 420*1cb19fbbSYork Sun case 8: 421*1cb19fbbSYork Sun case 12: 422*1cb19fbbSYork Sun case 14: 423*1cb19fbbSYork Sun case 16: 424*1cb19fbbSYork Sun case 17: 425*1cb19fbbSYork Sun case 19: 426*1cb19fbbSYork Sun case 20: 427*1cb19fbbSYork Sun /* SD3(4:7) => SLOT6(0:3) */ 428*1cb19fbbSYork Sun brdcfg = QIXIS_READ(brdcfg[12]); 429*1cb19fbbSYork Sun brdcfg &= ~BRDCFG12_SD3MX_MASK; 430*1cb19fbbSYork Sun brdcfg |= BRDCFG12_SD3MX_SLOT6; 431*1cb19fbbSYork Sun QIXIS_WRITE(brdcfg[12], brdcfg); 432*1cb19fbbSYork Sun break; 433*1cb19fbbSYork Sun default: 434*1cb19fbbSYork Sun printf("WARNING: unsupported for SerDes3 Protocol %d\n", 435*1cb19fbbSYork Sun srds_prtcl_s3); 436*1cb19fbbSYork Sun return -1; 437*1cb19fbbSYork Sun } 438*1cb19fbbSYork Sun 439*1cb19fbbSYork Sun srds_prtcl_s4 = in_be32(&gur->rcwsr[4]) & 440*1cb19fbbSYork Sun FSL_CORENET2_RCWSR4_SRDS4_PRTCL; 441*1cb19fbbSYork Sun srds_prtcl_s4 >>= FSL_CORENET2_RCWSR4_SRDS4_PRTCL_SHIFT; 442*1cb19fbbSYork Sun switch (srds_prtcl_s4) { 443*1cb19fbbSYork Sun case 0: 444*1cb19fbbSYork Sun /* SerDes4 is not enabled */ 445*1cb19fbbSYork Sun break; 446*1cb19fbbSYork Sun case 2: 447*1cb19fbbSYork Sun /* 10b, SD4(0:7) => SLOT7(0:7) */ 448*1cb19fbbSYork Sun brdcfg = QIXIS_READ(brdcfg[12]); 449*1cb19fbbSYork Sun brdcfg &= ~BRDCFG12_SD4MX_MASK; 450*1cb19fbbSYork Sun brdcfg |= BRDCFG12_SD4MX_SLOT7; 451*1cb19fbbSYork Sun QIXIS_WRITE(brdcfg[12], brdcfg); 452*1cb19fbbSYork Sun break; 453*1cb19fbbSYork Sun case 4: 454*1cb19fbbSYork Sun case 6: 455*1cb19fbbSYork Sun case 8: 456*1cb19fbbSYork Sun /* x1b, SD4(4:7) => SLOT8(0:3) */ 457*1cb19fbbSYork Sun brdcfg = QIXIS_READ(brdcfg[12]); 458*1cb19fbbSYork Sun brdcfg &= ~BRDCFG12_SD4MX_MASK; 459*1cb19fbbSYork Sun brdcfg |= BRDCFG12_SD4MX_SLOT8; 460*1cb19fbbSYork Sun QIXIS_WRITE(brdcfg[12], brdcfg); 461*1cb19fbbSYork Sun break; 462*1cb19fbbSYork Sun case 10: 463*1cb19fbbSYork Sun case 12: 464*1cb19fbbSYork Sun case 14: 465*1cb19fbbSYork Sun case 16: 466*1cb19fbbSYork Sun case 18: 467*1cb19fbbSYork Sun /* 00b, SD4(4:5) => AURORA, SD4(6:7) => SATA */ 468*1cb19fbbSYork Sun brdcfg = QIXIS_READ(brdcfg[12]); 469*1cb19fbbSYork Sun brdcfg &= ~BRDCFG12_SD4MX_MASK; 470*1cb19fbbSYork Sun brdcfg |= BRDCFG12_SD4MX_AURO_SATA; 471*1cb19fbbSYork Sun QIXIS_WRITE(brdcfg[12], brdcfg); 472*1cb19fbbSYork Sun break; 473*1cb19fbbSYork Sun default: 474*1cb19fbbSYork Sun printf("WARNING: unsupported for SerDes4 Protocol %d\n", 475*1cb19fbbSYork Sun srds_prtcl_s4); 476*1cb19fbbSYork Sun return -1; 477*1cb19fbbSYork Sun } 478*1cb19fbbSYork Sun 479*1cb19fbbSYork Sun return 0; 480*1cb19fbbSYork Sun } 481*1cb19fbbSYork Sun 482*1cb19fbbSYork Sun int board_early_init_r(void) 483*1cb19fbbSYork Sun { 484*1cb19fbbSYork Sun const unsigned int flashbase = CONFIG_SYS_FLASH_BASE; 485*1cb19fbbSYork Sun const u8 flash_esel = find_tlb_idx((void *)flashbase, 1); 486*1cb19fbbSYork Sun 487*1cb19fbbSYork Sun /* 488*1cb19fbbSYork Sun * Remap Boot flash + PROMJET region to caching-inhibited 489*1cb19fbbSYork Sun * so that flash can be erased properly. 490*1cb19fbbSYork Sun */ 491*1cb19fbbSYork Sun 492*1cb19fbbSYork Sun /* Flush d-cache and invalidate i-cache of any FLASH data */ 493*1cb19fbbSYork Sun flush_dcache(); 494*1cb19fbbSYork Sun invalidate_icache(); 495*1cb19fbbSYork Sun 496*1cb19fbbSYork Sun /* invalidate existing TLB entry for flash + promjet */ 497*1cb19fbbSYork Sun disable_tlb(flash_esel); 498*1cb19fbbSYork Sun 499*1cb19fbbSYork Sun set_tlb(1, flashbase, CONFIG_SYS_FLASH_BASE_PHYS, 500*1cb19fbbSYork Sun MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, 501*1cb19fbbSYork Sun 0, flash_esel, BOOKE_PAGESZ_256M, 1); 502*1cb19fbbSYork Sun 503*1cb19fbbSYork Sun set_liodns(); 504*1cb19fbbSYork Sun #ifdef CONFIG_SYS_DPAA_QBMAN 505*1cb19fbbSYork Sun setup_portals(); 506*1cb19fbbSYork Sun #endif 507*1cb19fbbSYork Sun 508*1cb19fbbSYork Sun /* Disable remote I2C connection to qixis fpga */ 509*1cb19fbbSYork Sun QIXIS_WRITE(brdcfg[5], QIXIS_READ(brdcfg[5]) & ~BRDCFG5_IRE); 510*1cb19fbbSYork Sun 511*1cb19fbbSYork Sun /* 512*1cb19fbbSYork Sun * Adjust core voltage according to voltage ID 513*1cb19fbbSYork Sun * This function changes I2C mux to channel 2. 514*1cb19fbbSYork Sun */ 515*1cb19fbbSYork Sun if (adjust_vdd(0)) 516*1cb19fbbSYork Sun printf("Warning: Adjusting core voltage failed.\n"); 517*1cb19fbbSYork Sun 518*1cb19fbbSYork Sun /* Configure board SERDES ports crossbar */ 519*1cb19fbbSYork Sun config_frontside_crossbar_vsc3316(); 520*1cb19fbbSYork Sun config_backside_crossbar_mux(); 521*1cb19fbbSYork Sun select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT); 522*1cb19fbbSYork Sun 523*1cb19fbbSYork Sun return 0; 524*1cb19fbbSYork Sun } 525*1cb19fbbSYork Sun 526*1cb19fbbSYork Sun unsigned long get_board_sys_clk(void) 527*1cb19fbbSYork Sun { 528*1cb19fbbSYork Sun u8 sysclk_conf = QIXIS_READ(brdcfg[1]); 529*1cb19fbbSYork Sun #ifdef CONFIG_FSL_QIXIS_CLOCK_MEASUREMENT 530*1cb19fbbSYork Sun /* use accurate clock measurement */ 531*1cb19fbbSYork Sun int freq = QIXIS_READ(clk_freq[0]) << 8 | QIXIS_READ(clk_freq[1]); 532*1cb19fbbSYork Sun int base = QIXIS_READ(clk_base[0]) << 8 | QIXIS_READ(clk_base[1]); 533*1cb19fbbSYork Sun u32 val; 534*1cb19fbbSYork Sun 535*1cb19fbbSYork Sun val = freq * base; 536*1cb19fbbSYork Sun if (val) { 537*1cb19fbbSYork Sun debug("SYS Clock measurement is: %d\n", val); 538*1cb19fbbSYork Sun return val; 539*1cb19fbbSYork Sun } else { 540*1cb19fbbSYork Sun printf("Warning: SYS clock measurement is invalid, using value from brdcfg1.\n"); 541*1cb19fbbSYork Sun } 542*1cb19fbbSYork Sun #endif 543*1cb19fbbSYork Sun 544*1cb19fbbSYork Sun switch (sysclk_conf & 0x0F) { 545*1cb19fbbSYork Sun case QIXIS_SYSCLK_83: 546*1cb19fbbSYork Sun return 83333333; 547*1cb19fbbSYork Sun case QIXIS_SYSCLK_100: 548*1cb19fbbSYork Sun return 100000000; 549*1cb19fbbSYork Sun case QIXIS_SYSCLK_125: 550*1cb19fbbSYork Sun return 125000000; 551*1cb19fbbSYork Sun case QIXIS_SYSCLK_133: 552*1cb19fbbSYork Sun return 133333333; 553*1cb19fbbSYork Sun case QIXIS_SYSCLK_150: 554*1cb19fbbSYork Sun return 150000000; 555*1cb19fbbSYork Sun case QIXIS_SYSCLK_160: 556*1cb19fbbSYork Sun return 160000000; 557*1cb19fbbSYork Sun case QIXIS_SYSCLK_166: 558*1cb19fbbSYork Sun return 166666666; 559*1cb19fbbSYork Sun } 560*1cb19fbbSYork Sun return 66666666; 561*1cb19fbbSYork Sun } 562*1cb19fbbSYork Sun 563*1cb19fbbSYork Sun unsigned long get_board_ddr_clk(void) 564*1cb19fbbSYork Sun { 565*1cb19fbbSYork Sun u8 ddrclk_conf = QIXIS_READ(brdcfg[1]); 566*1cb19fbbSYork Sun #ifdef CONFIG_FSL_QIXIS_CLOCK_MEASUREMENT 567*1cb19fbbSYork Sun /* use accurate clock measurement */ 568*1cb19fbbSYork Sun int freq = QIXIS_READ(clk_freq[2]) << 8 | QIXIS_READ(clk_freq[3]); 569*1cb19fbbSYork Sun int base = QIXIS_READ(clk_base[0]) << 8 | QIXIS_READ(clk_base[1]); 570*1cb19fbbSYork Sun u32 val; 571*1cb19fbbSYork Sun 572*1cb19fbbSYork Sun val = freq * base; 573*1cb19fbbSYork Sun if (val) { 574*1cb19fbbSYork Sun debug("DDR Clock measurement is: %d\n", val); 575*1cb19fbbSYork Sun return val; 576*1cb19fbbSYork Sun } else { 577*1cb19fbbSYork Sun printf("Warning: DDR clock measurement is invalid, using value from brdcfg1.\n"); 578*1cb19fbbSYork Sun } 579*1cb19fbbSYork Sun #endif 580*1cb19fbbSYork Sun 581*1cb19fbbSYork Sun switch ((ddrclk_conf & 0x30) >> 4) { 582*1cb19fbbSYork Sun case QIXIS_DDRCLK_100: 583*1cb19fbbSYork Sun return 100000000; 584*1cb19fbbSYork Sun case QIXIS_DDRCLK_125: 585*1cb19fbbSYork Sun return 125000000; 586*1cb19fbbSYork Sun case QIXIS_DDRCLK_133: 587*1cb19fbbSYork Sun return 133333333; 588*1cb19fbbSYork Sun } 589*1cb19fbbSYork Sun return 66666666; 590*1cb19fbbSYork Sun } 591*1cb19fbbSYork Sun 592*1cb19fbbSYork Sun static const char *serdes_clock_to_string(u32 clock) 593*1cb19fbbSYork Sun { 594*1cb19fbbSYork Sun switch (clock) { 595*1cb19fbbSYork Sun case SRDS_PLLCR0_RFCK_SEL_100: 596*1cb19fbbSYork Sun return "100"; 597*1cb19fbbSYork Sun case SRDS_PLLCR0_RFCK_SEL_125: 598*1cb19fbbSYork Sun return "125"; 599*1cb19fbbSYork Sun case SRDS_PLLCR0_RFCK_SEL_156_25: 600*1cb19fbbSYork Sun return "156.25"; 601*1cb19fbbSYork Sun case SRDS_PLLCR0_RFCK_SEL_161_13: 602*1cb19fbbSYork Sun return "161.1328125"; 603*1cb19fbbSYork Sun default: 604*1cb19fbbSYork Sun return "???"; 605*1cb19fbbSYork Sun } 606*1cb19fbbSYork Sun } 607*1cb19fbbSYork Sun 608*1cb19fbbSYork Sun int misc_init_r(void) 609*1cb19fbbSYork Sun { 610*1cb19fbbSYork Sun u8 sw; 611*1cb19fbbSYork Sun serdes_corenet_t *srds_regs = 612*1cb19fbbSYork Sun (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR; 613*1cb19fbbSYork Sun u32 actual[MAX_SERDES]; 614*1cb19fbbSYork Sun unsigned int i; 615*1cb19fbbSYork Sun 616*1cb19fbbSYork Sun sw = QIXIS_READ(brdcfg[2]); 617*1cb19fbbSYork Sun for (i = 0; i < MAX_SERDES; i++) { 618*1cb19fbbSYork Sun unsigned int clock = (sw >> (6 - 2 * i)) & 3; 619*1cb19fbbSYork Sun switch (clock) { 620*1cb19fbbSYork Sun case 0: 621*1cb19fbbSYork Sun actual[i] = SRDS_PLLCR0_RFCK_SEL_100; 622*1cb19fbbSYork Sun break; 623*1cb19fbbSYork Sun case 1: 624*1cb19fbbSYork Sun actual[i] = SRDS_PLLCR0_RFCK_SEL_125; 625*1cb19fbbSYork Sun break; 626*1cb19fbbSYork Sun case 2: 627*1cb19fbbSYork Sun actual[i] = SRDS_PLLCR0_RFCK_SEL_156_25; 628*1cb19fbbSYork Sun break; 629*1cb19fbbSYork Sun case 3: 630*1cb19fbbSYork Sun actual[i] = SRDS_PLLCR0_RFCK_SEL_161_13; 631*1cb19fbbSYork Sun break; 632*1cb19fbbSYork Sun } 633*1cb19fbbSYork Sun } 634*1cb19fbbSYork Sun 635*1cb19fbbSYork Sun for (i = 0; i < MAX_SERDES; i++) { 636*1cb19fbbSYork Sun u32 pllcr0 = srds_regs->bank[i].pllcr0; 637*1cb19fbbSYork Sun u32 expected = pllcr0 & SRDS_PLLCR0_RFCK_SEL_MASK; 638*1cb19fbbSYork Sun if (expected != actual[i]) { 639*1cb19fbbSYork Sun printf("Warning: SERDES%u expects reference clock %sMHz, but actual is %sMHz\n", 640*1cb19fbbSYork Sun i + 1, serdes_clock_to_string(expected), 641*1cb19fbbSYork Sun serdes_clock_to_string(actual[i])); 642*1cb19fbbSYork Sun } 643*1cb19fbbSYork Sun } 644*1cb19fbbSYork Sun 645*1cb19fbbSYork Sun return 0; 646*1cb19fbbSYork Sun } 647*1cb19fbbSYork Sun 648*1cb19fbbSYork Sun void ft_board_setup(void *blob, bd_t *bd) 649*1cb19fbbSYork Sun { 650*1cb19fbbSYork Sun phys_addr_t base; 651*1cb19fbbSYork Sun phys_size_t size; 652*1cb19fbbSYork Sun 653*1cb19fbbSYork Sun ft_cpu_setup(blob, bd); 654*1cb19fbbSYork Sun 655*1cb19fbbSYork Sun base = getenv_bootm_low(); 656*1cb19fbbSYork Sun size = getenv_bootm_size(); 657*1cb19fbbSYork Sun 658*1cb19fbbSYork Sun fdt_fixup_memory(blob, (u64)base, (u64)size); 659*1cb19fbbSYork Sun 660*1cb19fbbSYork Sun #ifdef CONFIG_PCI 661*1cb19fbbSYork Sun pci_of_setup(blob, bd); 662*1cb19fbbSYork Sun #endif 663*1cb19fbbSYork Sun 664*1cb19fbbSYork Sun fdt_fixup_liodn(blob); 665*1cb19fbbSYork Sun fdt_fixup_dr_usb(blob, bd); 666*1cb19fbbSYork Sun 667*1cb19fbbSYork Sun #ifdef CONFIG_SYS_DPAA_FMAN 668*1cb19fbbSYork Sun fdt_fixup_fman_ethernet(blob); 669*1cb19fbbSYork Sun fdt_fixup_board_enet(blob); 670*1cb19fbbSYork Sun #endif 671*1cb19fbbSYork Sun } 672*1cb19fbbSYork Sun 673*1cb19fbbSYork Sun /* 674*1cb19fbbSYork Sun * This function is called by bdinfo to print detail board information. 675*1cb19fbbSYork Sun * As an exmaple for future board, we organize the messages into 676*1cb19fbbSYork Sun * several sections. If applicable, the message is in the format of 677*1cb19fbbSYork Sun * <name> = <value> 678*1cb19fbbSYork Sun * It should aligned with normal output of bdinfo command. 679*1cb19fbbSYork Sun * 680*1cb19fbbSYork Sun * Voltage: Core, DDR and another configurable voltages 681*1cb19fbbSYork Sun * Clock : Critical clocks which are not printed already 682*1cb19fbbSYork Sun * RCW : RCW source if not printed already 683*1cb19fbbSYork Sun * Misc : Other important information not in above catagories 684*1cb19fbbSYork Sun */ 685*1cb19fbbSYork Sun void board_detail(void) 686*1cb19fbbSYork Sun { 687*1cb19fbbSYork Sun int i; 688*1cb19fbbSYork Sun u8 brdcfg[16], dutcfg[16], rst_ctl; 689*1cb19fbbSYork Sun int vdd, rcwsrc; 690*1cb19fbbSYork Sun static const char * const clk[] = {"66.67", "100", "125", "133.33"}; 691*1cb19fbbSYork Sun 692*1cb19fbbSYork Sun for (i = 0; i < 16; i++) { 693*1cb19fbbSYork Sun brdcfg[i] = qixis_read(offsetof(struct qixis, brdcfg[0]) + i); 694*1cb19fbbSYork Sun dutcfg[i] = qixis_read(offsetof(struct qixis, dutcfg[0]) + i); 695*1cb19fbbSYork Sun } 696*1cb19fbbSYork Sun 697*1cb19fbbSYork Sun /* Voltage secion */ 698*1cb19fbbSYork Sun if (!select_i2c_ch_pca9547(I2C_MUX_CH_VOL_MONITOR)) { 699*1cb19fbbSYork Sun vdd = read_voltage(); 700*1cb19fbbSYork Sun if (vdd > 0) 701*1cb19fbbSYork Sun printf("Core voltage= %d mV\n", vdd); 702*1cb19fbbSYork Sun select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT); 703*1cb19fbbSYork Sun } 704*1cb19fbbSYork Sun 705*1cb19fbbSYork Sun printf("XVDD = 1.%d V\n", ((brdcfg[8] & 0xf) - 4) * 5 + 25); 706*1cb19fbbSYork Sun 707*1cb19fbbSYork Sun /* clock section */ 708*1cb19fbbSYork Sun printf("SYSCLK = %s MHz\nDDRCLK = %s MHz\n", 709*1cb19fbbSYork Sun clk[(brdcfg[11] >> 2) & 0x3], clk[brdcfg[11] & 3]); 710*1cb19fbbSYork Sun 711*1cb19fbbSYork Sun /* RCW section */ 712*1cb19fbbSYork Sun rcwsrc = (dutcfg[0] << 1) + (dutcfg[1] & 1); 713*1cb19fbbSYork Sun puts("RCW source = "); 714*1cb19fbbSYork Sun switch (rcwsrc) { 715*1cb19fbbSYork Sun case 0x017: 716*1cb19fbbSYork Sun case 0x01f: 717*1cb19fbbSYork Sun puts("8-bit NOR\n"); 718*1cb19fbbSYork Sun break; 719*1cb19fbbSYork Sun case 0x027: 720*1cb19fbbSYork Sun case 0x02F: 721*1cb19fbbSYork Sun puts("16-bit NOR\n"); 722*1cb19fbbSYork Sun break; 723*1cb19fbbSYork Sun case 0x040: 724*1cb19fbbSYork Sun puts("SDHC/eMMC\n"); 725*1cb19fbbSYork Sun break; 726*1cb19fbbSYork Sun case 0x044: 727*1cb19fbbSYork Sun puts("SPI 16-bit addressing\n"); 728*1cb19fbbSYork Sun break; 729*1cb19fbbSYork Sun case 0x045: 730*1cb19fbbSYork Sun puts("SPI 24-bit addressing\n"); 731*1cb19fbbSYork Sun break; 732*1cb19fbbSYork Sun case 0x048: 733*1cb19fbbSYork Sun puts("I2C normal addressing\n"); 734*1cb19fbbSYork Sun break; 735*1cb19fbbSYork Sun case 0x049: 736*1cb19fbbSYork Sun puts("I2C extended addressing\n"); 737*1cb19fbbSYork Sun break; 738*1cb19fbbSYork Sun case 0x108: 739*1cb19fbbSYork Sun case 0x109: 740*1cb19fbbSYork Sun case 0x10a: 741*1cb19fbbSYork Sun case 0x10b: 742*1cb19fbbSYork Sun puts("8-bit NAND, 2KB\n"); 743*1cb19fbbSYork Sun break; 744*1cb19fbbSYork Sun default: 745*1cb19fbbSYork Sun if ((rcwsrc >= 0x080) && (rcwsrc <= 0x09f)) 746*1cb19fbbSYork Sun puts("Hard-coded RCW\n"); 747*1cb19fbbSYork Sun else if ((rcwsrc >= 0x110) && (rcwsrc <= 0x11f)) 748*1cb19fbbSYork Sun puts("8-bit NAND, 4KB\n"); 749*1cb19fbbSYork Sun else 750*1cb19fbbSYork Sun puts("unknown\n"); 751*1cb19fbbSYork Sun break; 752*1cb19fbbSYork Sun } 753*1cb19fbbSYork Sun 754*1cb19fbbSYork Sun /* Misc section */ 755*1cb19fbbSYork Sun rst_ctl = QIXIS_READ(rst_ctl); 756*1cb19fbbSYork Sun puts("HRESET_REQ = "); 757*1cb19fbbSYork Sun switch (rst_ctl & 0x30) { 758*1cb19fbbSYork Sun case 0x00: 759*1cb19fbbSYork Sun puts("Ignored\n"); 760*1cb19fbbSYork Sun break; 761*1cb19fbbSYork Sun case 0x10: 762*1cb19fbbSYork Sun puts("Assert HRESET\n"); 763*1cb19fbbSYork Sun break; 764*1cb19fbbSYork Sun case 0x30: 765*1cb19fbbSYork Sun puts("Reset system\n"); 766*1cb19fbbSYork Sun break; 767*1cb19fbbSYork Sun default: 768*1cb19fbbSYork Sun puts("N/A\n"); 769*1cb19fbbSYork Sun break; 770*1cb19fbbSYork Sun } 771*1cb19fbbSYork Sun } 772*1cb19fbbSYork Sun 773*1cb19fbbSYork Sun /* 774*1cb19fbbSYork Sun * Reverse engineering switch settings. 775*1cb19fbbSYork Sun * Some bits cannot be figured out. They will be displayed as 776*1cb19fbbSYork Sun * underscore in binary format. mask[] has those bits. 777*1cb19fbbSYork Sun * Some bits are calculated differently than the actual switches 778*1cb19fbbSYork Sun * if booting with overriding by FPGA. 779*1cb19fbbSYork Sun */ 780*1cb19fbbSYork Sun void qixis_dump_switch(void) 781*1cb19fbbSYork Sun { 782*1cb19fbbSYork Sun int i; 783*1cb19fbbSYork Sun u8 sw[9]; 784*1cb19fbbSYork Sun 785*1cb19fbbSYork Sun /* 786*1cb19fbbSYork Sun * Any bit with 1 means that bit cannot be reverse engineered. 787*1cb19fbbSYork Sun * It will be displayed as _ in binary format. 788*1cb19fbbSYork Sun */ 789*1cb19fbbSYork Sun static const u8 mask[] = {0, 0, 0, 0, 0, 0x1, 0xcf, 0x3f, 0x1f}; 790*1cb19fbbSYork Sun char buf[10]; 791*1cb19fbbSYork Sun u8 brdcfg[16], dutcfg[16]; 792*1cb19fbbSYork Sun 793*1cb19fbbSYork Sun for (i = 0; i < 16; i++) { 794*1cb19fbbSYork Sun brdcfg[i] = qixis_read(offsetof(struct qixis, brdcfg[0]) + i); 795*1cb19fbbSYork Sun dutcfg[i] = qixis_read(offsetof(struct qixis, dutcfg[0]) + i); 796*1cb19fbbSYork Sun } 797*1cb19fbbSYork Sun 798*1cb19fbbSYork Sun sw[0] = dutcfg[0]; 799*1cb19fbbSYork Sun sw[1] = (dutcfg[1] << 0x07) | 800*1cb19fbbSYork Sun ((dutcfg[12] & 0xC0) >> 1) | 801*1cb19fbbSYork Sun ((dutcfg[11] & 0xE0) >> 3) | 802*1cb19fbbSYork Sun ((dutcfg[6] & 0x80) >> 6) | 803*1cb19fbbSYork Sun ((dutcfg[1] & 0x80) >> 7); 804*1cb19fbbSYork Sun sw[2] = ((brdcfg[1] & 0x0f) << 4) | 805*1cb19fbbSYork Sun ((brdcfg[1] & 0x30) >> 2) | 806*1cb19fbbSYork Sun ((brdcfg[1] & 0x40) >> 5) | 807*1cb19fbbSYork Sun ((brdcfg[1] & 0x80) >> 7); 808*1cb19fbbSYork Sun sw[3] = brdcfg[2]; 809*1cb19fbbSYork Sun sw[4] = ((dutcfg[2] & 0x01) << 7) | 810*1cb19fbbSYork Sun ((dutcfg[2] & 0x06) << 4) | 811*1cb19fbbSYork Sun ((~QIXIS_READ(present)) & 0x10) | 812*1cb19fbbSYork Sun ((brdcfg[3] & 0x80) >> 4) | 813*1cb19fbbSYork Sun ((brdcfg[3] & 0x01) << 2) | 814*1cb19fbbSYork Sun ((brdcfg[6] == 0x62) ? 3 : 815*1cb19fbbSYork Sun ((brdcfg[6] == 0x5a) ? 2 : 816*1cb19fbbSYork Sun ((brdcfg[6] == 0x5e) ? 1 : 0))); 817*1cb19fbbSYork Sun sw[5] = ((brdcfg[0] & 0x0f) << 4) | 818*1cb19fbbSYork Sun ((QIXIS_READ(rst_ctl) & 0x30) >> 2) | 819*1cb19fbbSYork Sun ((brdcfg[0] & 0x40) >> 5); 820*1cb19fbbSYork Sun sw[6] = (brdcfg[11] & 0x20) | 821*1cb19fbbSYork Sun ((brdcfg[5] & 0x02) << 3); 822*1cb19fbbSYork Sun sw[7] = (((~QIXIS_READ(rst_ctl)) & 0x40) << 1) | 823*1cb19fbbSYork Sun ((brdcfg[5] & 0x10) << 2); 824*1cb19fbbSYork Sun sw[8] = ((brdcfg[12] & 0x08) << 4) | 825*1cb19fbbSYork Sun ((brdcfg[12] & 0x03) << 5); 826*1cb19fbbSYork Sun 827*1cb19fbbSYork Sun puts("DIP switch (reverse-engineering)\n"); 828*1cb19fbbSYork Sun for (i = 0; i < 9; i++) { 829*1cb19fbbSYork Sun printf("SW%d = 0b%s (0x%02x)\n", 830*1cb19fbbSYork Sun i + 1, byte_to_binary_mask(sw[i], mask[i], buf), sw[i]); 831*1cb19fbbSYork Sun } 832*1cb19fbbSYork Sun } 833*1cb19fbbSYork Sun 834*1cb19fbbSYork Sun static int do_vdd_adjust(cmd_tbl_t *cmdtp, 835*1cb19fbbSYork Sun int flag, int argc, 836*1cb19fbbSYork Sun char * const argv[]) 837*1cb19fbbSYork Sun { 838*1cb19fbbSYork Sun ulong override; 839*1cb19fbbSYork Sun 840*1cb19fbbSYork Sun if (argc < 2) 841*1cb19fbbSYork Sun return CMD_RET_USAGE; 842*1cb19fbbSYork Sun if (!strict_strtoul(argv[1], 10, &override)) 843*1cb19fbbSYork Sun adjust_vdd(override); /* the value is checked by callee */ 844*1cb19fbbSYork Sun else 845*1cb19fbbSYork Sun return CMD_RET_USAGE; 846*1cb19fbbSYork Sun 847*1cb19fbbSYork Sun return 0; 848*1cb19fbbSYork Sun } 849*1cb19fbbSYork Sun 850*1cb19fbbSYork Sun U_BOOT_CMD( 851*1cb19fbbSYork Sun vdd_override, 2, 0, do_vdd_adjust, 852*1cb19fbbSYork Sun "Override VDD", 853*1cb19fbbSYork Sun "- override with the voltage specified in mV, eg. 1050" 854*1cb19fbbSYork Sun ); 855