11cb19fbbSYork Sun /* 21cb19fbbSYork Sun * Copyright 2009-2012 Freescale Semiconductor, Inc. 31cb19fbbSYork Sun * 43aab0cd8SYork Sun * SPDX-License-Identifier: GPL-2.0+ 51cb19fbbSYork Sun */ 61cb19fbbSYork Sun 71cb19fbbSYork Sun #include <common.h> 81cb19fbbSYork Sun #include <command.h> 91cb19fbbSYork Sun #include <i2c.h> 101cb19fbbSYork Sun #include <netdev.h> 111cb19fbbSYork Sun #include <linux/compiler.h> 121cb19fbbSYork Sun #include <asm/mmu.h> 131cb19fbbSYork Sun #include <asm/processor.h> 141cb19fbbSYork Sun #include <asm/cache.h> 151cb19fbbSYork Sun #include <asm/immap_85xx.h> 161cb19fbbSYork Sun #include <asm/fsl_law.h> 171cb19fbbSYork Sun #include <asm/fsl_serdes.h> 181cb19fbbSYork Sun #include <asm/fsl_portals.h> 191cb19fbbSYork Sun #include <asm/fsl_liodn.h> 201cb19fbbSYork Sun #include <fm_eth.h> 211cb19fbbSYork Sun 221cb19fbbSYork Sun #include "../common/qixis.h" 231cb19fbbSYork Sun #include "../common/vsc3316_3308.h" 241cb19fbbSYork Sun #include "t4qds.h" 251cb19fbbSYork Sun #include "t4240qds_qixis.h" 261cb19fbbSYork Sun 271cb19fbbSYork Sun DECLARE_GLOBAL_DATA_PTR; 281cb19fbbSYork Sun 297d0d355fSShaohui Xie static int8_t vsc3316_fsm1_tx[8][2] = { {0, 0}, {1, 1}, {6, 6}, {7, 7}, 301cb19fbbSYork Sun {8, 8}, {9, 9}, {14, 14}, {15, 15} }; 311cb19fbbSYork Sun 327d0d355fSShaohui Xie static int8_t vsc3316_fsm2_tx[8][2] = { {2, 2}, {3, 3}, {4, 4}, {5, 5}, 331cb19fbbSYork Sun {10, 10}, {11, 11}, {12, 12}, {13, 13} }; 341cb19fbbSYork Sun 357d0d355fSShaohui Xie static int8_t vsc3316_fsm1_rx[8][2] = { {2, 12}, {3, 13}, {4, 5}, {5, 4}, 361cb19fbbSYork Sun {10, 11}, {11, 10}, {12, 2}, {13, 3} }; 371cb19fbbSYork Sun 387d0d355fSShaohui Xie static int8_t vsc3316_fsm2_rx[8][2] = { {0, 15}, {1, 14}, {6, 7}, {7, 6}, 391cb19fbbSYork Sun {8, 9}, {9, 8}, {14, 1}, {15, 0} }; 401cb19fbbSYork Sun 411cb19fbbSYork Sun int checkboard(void) 421cb19fbbSYork Sun { 431cb19fbbSYork Sun char buf[64]; 441cb19fbbSYork Sun u8 sw; 451cb19fbbSYork Sun struct cpu_type *cpu = gd->arch.cpu; 461cb19fbbSYork Sun unsigned int i; 471cb19fbbSYork Sun 481cb19fbbSYork Sun printf("Board: %sQDS, ", cpu->name); 491cb19fbbSYork Sun printf("Sys ID: 0x%02x, Sys Ver: 0x%02x, ", 501cb19fbbSYork Sun QIXIS_READ(id), QIXIS_READ(arch)); 511cb19fbbSYork Sun 521cb19fbbSYork Sun sw = QIXIS_READ(brdcfg[0]); 531cb19fbbSYork Sun sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT; 541cb19fbbSYork Sun 551cb19fbbSYork Sun if (sw < 0x8) 561cb19fbbSYork Sun printf("vBank: %d\n", sw); 571cb19fbbSYork Sun else if (sw == 0x8) 581cb19fbbSYork Sun puts("Promjet\n"); 591cb19fbbSYork Sun else if (sw == 0x9) 601cb19fbbSYork Sun puts("NAND\n"); 611cb19fbbSYork Sun else 621cb19fbbSYork Sun printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH); 631cb19fbbSYork Sun 641cb19fbbSYork Sun printf("FPGA: v%d (%s), build %d", 651cb19fbbSYork Sun (int)QIXIS_READ(scver), qixis_read_tag(buf), 661cb19fbbSYork Sun (int)qixis_read_minor()); 671cb19fbbSYork Sun /* the timestamp string contains "\n" at the end */ 681cb19fbbSYork Sun printf(" on %s", qixis_read_time(buf)); 691cb19fbbSYork Sun 701cb19fbbSYork Sun /* 711cb19fbbSYork Sun * Display the actual SERDES reference clocks as configured by the 721cb19fbbSYork Sun * dip switches on the board. Note that the SWx registers could 731cb19fbbSYork Sun * technically be set to force the reference clocks to match the 741cb19fbbSYork Sun * values that the SERDES expects (or vice versa). For now, however, 751cb19fbbSYork Sun * we just display both values and hope the user notices when they 761cb19fbbSYork Sun * don't match. 771cb19fbbSYork Sun */ 781cb19fbbSYork Sun puts("SERDES Reference Clocks: "); 791cb19fbbSYork Sun sw = QIXIS_READ(brdcfg[2]); 801cb19fbbSYork Sun for (i = 0; i < MAX_SERDES; i++) { 811cb19fbbSYork Sun static const char * const freq[] = { 821cb19fbbSYork Sun "100", "125", "156.25", "161.1328125"}; 831cb19fbbSYork Sun unsigned int clock = (sw >> (6 - 2 * i)) & 3; 841cb19fbbSYork Sun 851cb19fbbSYork Sun printf("SERDES%u=%sMHz ", i+1, freq[clock]); 861cb19fbbSYork Sun } 871cb19fbbSYork Sun puts("\n"); 881cb19fbbSYork Sun 891cb19fbbSYork Sun return 0; 901cb19fbbSYork Sun } 911cb19fbbSYork Sun 921cb19fbbSYork Sun int select_i2c_ch_pca9547(u8 ch) 931cb19fbbSYork Sun { 941cb19fbbSYork Sun int ret; 951cb19fbbSYork Sun 961cb19fbbSYork Sun ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1); 971cb19fbbSYork Sun if (ret) { 981cb19fbbSYork Sun puts("PCA: failed to select proper channel\n"); 991cb19fbbSYork Sun return ret; 1001cb19fbbSYork Sun } 1011cb19fbbSYork Sun 1021cb19fbbSYork Sun return 0; 1031cb19fbbSYork Sun } 1041cb19fbbSYork Sun 1051cb19fbbSYork Sun /* 1061cb19fbbSYork Sun * read_voltage from sensor on I2C bus 1071cb19fbbSYork Sun * We use average of 4 readings, waiting for 532us befor another reading 1081cb19fbbSYork Sun */ 1091cb19fbbSYork Sun #define NUM_READINGS 4 /* prefer to be power of 2 for efficiency */ 1101cb19fbbSYork Sun #define WAIT_FOR_ADC 532 /* wait for 532 microseconds for ADC */ 1111cb19fbbSYork Sun 1121cb19fbbSYork Sun static inline int read_voltage(void) 1131cb19fbbSYork Sun { 1141cb19fbbSYork Sun int i, ret, voltage_read = 0; 1151cb19fbbSYork Sun u16 vol_mon; 1161cb19fbbSYork Sun 1171cb19fbbSYork Sun for (i = 0; i < NUM_READINGS; i++) { 1181cb19fbbSYork Sun ret = i2c_read(I2C_VOL_MONITOR_ADDR, 1191cb19fbbSYork Sun I2C_VOL_MONITOR_BUS_V_OFFSET, 1, (void *)&vol_mon, 2); 1201cb19fbbSYork Sun if (ret) { 1211cb19fbbSYork Sun printf("VID: failed to read core voltage\n"); 1221cb19fbbSYork Sun return ret; 1231cb19fbbSYork Sun } 1241cb19fbbSYork Sun if (vol_mon & I2C_VOL_MONITOR_BUS_V_OVF) { 1251cb19fbbSYork Sun printf("VID: Core voltage sensor error\n"); 1261cb19fbbSYork Sun return -1; 1271cb19fbbSYork Sun } 1281cb19fbbSYork Sun debug("VID: bus voltage reads 0x%04x\n", vol_mon); 1291cb19fbbSYork Sun /* LSB = 4mv */ 1301cb19fbbSYork Sun voltage_read += (vol_mon >> I2C_VOL_MONITOR_BUS_V_SHIFT) * 4; 1311cb19fbbSYork Sun udelay(WAIT_FOR_ADC); 1321cb19fbbSYork Sun } 1331cb19fbbSYork Sun /* calculate the average */ 1341cb19fbbSYork Sun voltage_read /= NUM_READINGS; 1351cb19fbbSYork Sun 1361cb19fbbSYork Sun return voltage_read; 1371cb19fbbSYork Sun } 1381cb19fbbSYork Sun 1391cb19fbbSYork Sun /* 1401cb19fbbSYork Sun * We need to calculate how long before the voltage starts to drop or increase 1411cb19fbbSYork Sun * It returns with the loop count. Each loop takes several readings (532us) 1421cb19fbbSYork Sun */ 1431cb19fbbSYork Sun static inline int wait_for_voltage_change(int vdd_last) 1441cb19fbbSYork Sun { 1451cb19fbbSYork Sun int timeout, vdd_current; 1461cb19fbbSYork Sun 1471cb19fbbSYork Sun vdd_current = read_voltage(); 1481cb19fbbSYork Sun /* wait until voltage starts to drop */ 1491cb19fbbSYork Sun for (timeout = 0; abs(vdd_last - vdd_current) <= 4 && 1501cb19fbbSYork Sun timeout < 100; timeout++) { 1511cb19fbbSYork Sun vdd_current = read_voltage(); 1521cb19fbbSYork Sun } 1531cb19fbbSYork Sun if (timeout >= 100) { 1541cb19fbbSYork Sun printf("VID: Voltage adjustment timeout\n"); 1551cb19fbbSYork Sun return -1; 1561cb19fbbSYork Sun } 1571cb19fbbSYork Sun return timeout; 1581cb19fbbSYork Sun } 1591cb19fbbSYork Sun 1601cb19fbbSYork Sun /* 1611cb19fbbSYork Sun * argument 'wait' is the time we know the voltage difference can be measured 1621cb19fbbSYork Sun * this function keeps reading the voltage until it is stable 1631cb19fbbSYork Sun */ 1641cb19fbbSYork Sun static inline int wait_for_voltage_stable(int wait) 1651cb19fbbSYork Sun { 1661cb19fbbSYork Sun int timeout, vdd_current, vdd_last; 1671cb19fbbSYork Sun 1681cb19fbbSYork Sun vdd_last = read_voltage(); 1691cb19fbbSYork Sun udelay(wait * NUM_READINGS * WAIT_FOR_ADC); 1701cb19fbbSYork Sun /* wait until voltage is stable */ 1711cb19fbbSYork Sun vdd_current = read_voltage(); 1721cb19fbbSYork Sun for (timeout = 0; abs(vdd_last - vdd_current) >= 4 && 1731cb19fbbSYork Sun timeout < 100; timeout++) { 1741cb19fbbSYork Sun vdd_last = vdd_current; 1751cb19fbbSYork Sun udelay(wait * NUM_READINGS * WAIT_FOR_ADC); 1761cb19fbbSYork Sun vdd_current = read_voltage(); 1771cb19fbbSYork Sun } 1781cb19fbbSYork Sun if (timeout >= 100) { 1791cb19fbbSYork Sun printf("VID: Voltage adjustment timeout\n"); 1801cb19fbbSYork Sun return -1; 1811cb19fbbSYork Sun } 1821cb19fbbSYork Sun 1831cb19fbbSYork Sun return vdd_current; 1841cb19fbbSYork Sun } 1851cb19fbbSYork Sun 1861cb19fbbSYork Sun static inline int set_voltage(u8 vid) 1871cb19fbbSYork Sun { 1881cb19fbbSYork Sun int wait, vdd_last; 1891cb19fbbSYork Sun 1901cb19fbbSYork Sun vdd_last = read_voltage(); 1911cb19fbbSYork Sun QIXIS_WRITE(brdcfg[6], vid); 1921cb19fbbSYork Sun wait = wait_for_voltage_change(vdd_last); 1931cb19fbbSYork Sun if (wait < 0) 1941cb19fbbSYork Sun return -1; 1951cb19fbbSYork Sun debug("VID: Waited %d us\n", wait * NUM_READINGS * WAIT_FOR_ADC); 1961cb19fbbSYork Sun wait = wait ? wait : 1; 1971cb19fbbSYork Sun 1981cb19fbbSYork Sun vdd_last = wait_for_voltage_stable(wait); 1991cb19fbbSYork Sun if (vdd_last < 0) 2001cb19fbbSYork Sun return -1; 2011cb19fbbSYork Sun debug("VID: Current voltage is %d mV\n", vdd_last); 2021cb19fbbSYork Sun 2031cb19fbbSYork Sun return vdd_last; 2041cb19fbbSYork Sun } 2051cb19fbbSYork Sun 2061cb19fbbSYork Sun 2071cb19fbbSYork Sun static int adjust_vdd(ulong vdd_override) 2081cb19fbbSYork Sun { 2091cb19fbbSYork Sun int re_enable = disable_interrupts(); 2101cb19fbbSYork Sun ccsr_gur_t __iomem *gur = 2111cb19fbbSYork Sun (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 2121cb19fbbSYork Sun u32 fusesr; 2131cb19fbbSYork Sun u8 vid, vid_current; 2141cb19fbbSYork Sun int vdd_target, vdd_current, vdd_last; 2151cb19fbbSYork Sun int ret; 2161cb19fbbSYork Sun unsigned long vdd_string_override; 2171cb19fbbSYork Sun char *vdd_string; 2181cb19fbbSYork Sun static const uint16_t vdd[32] = { 2191cb19fbbSYork Sun 0, /* unused */ 2201cb19fbbSYork Sun 9875, /* 0.9875V */ 2211cb19fbbSYork Sun 9750, 2221cb19fbbSYork Sun 9625, 2231cb19fbbSYork Sun 9500, 2241cb19fbbSYork Sun 9375, 2251cb19fbbSYork Sun 9250, 2261cb19fbbSYork Sun 9125, 2271cb19fbbSYork Sun 9000, 2281cb19fbbSYork Sun 8875, 2291cb19fbbSYork Sun 8750, 2301cb19fbbSYork Sun 8625, 2311cb19fbbSYork Sun 8500, 2321cb19fbbSYork Sun 8375, 2331cb19fbbSYork Sun 8250, 2341cb19fbbSYork Sun 8125, 2351cb19fbbSYork Sun 10000, /* 1.0000V */ 2361cb19fbbSYork Sun 10125, 2371cb19fbbSYork Sun 10250, 2381cb19fbbSYork Sun 10375, 2391cb19fbbSYork Sun 10500, 2401cb19fbbSYork Sun 10625, 2411cb19fbbSYork Sun 10750, 2421cb19fbbSYork Sun 10875, 2431cb19fbbSYork Sun 11000, 2441cb19fbbSYork Sun 0, /* reserved */ 2451cb19fbbSYork Sun }; 2461cb19fbbSYork Sun struct vdd_drive { 2471cb19fbbSYork Sun u8 vid; 2481cb19fbbSYork Sun unsigned voltage; 2491cb19fbbSYork Sun }; 2501cb19fbbSYork Sun 2511cb19fbbSYork Sun ret = select_i2c_ch_pca9547(I2C_MUX_CH_VOL_MONITOR); 2521cb19fbbSYork Sun if (ret) { 2531cb19fbbSYork Sun debug("VID: I2c failed to switch channel\n"); 2541cb19fbbSYork Sun ret = -1; 2551cb19fbbSYork Sun goto exit; 2561cb19fbbSYork Sun } 2571cb19fbbSYork Sun 2581cb19fbbSYork Sun /* get the voltage ID from fuse status register */ 2591cb19fbbSYork Sun fusesr = in_be32(&gur->dcfg_fusesr); 2601cb19fbbSYork Sun vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_VID_SHIFT) & 2611cb19fbbSYork Sun FSL_CORENET_DCFG_FUSESR_VID_MASK; 2621cb19fbbSYork Sun if (vid == FSL_CORENET_DCFG_FUSESR_VID_MASK) { 2631cb19fbbSYork Sun vid = (fusesr >> FSL_CORENET_DCFG_FUSESR_ALTVID_SHIFT) & 2641cb19fbbSYork Sun FSL_CORENET_DCFG_FUSESR_ALTVID_MASK; 2651cb19fbbSYork Sun } 2661cb19fbbSYork Sun vdd_target = vdd[vid]; 2671cb19fbbSYork Sun 2681cb19fbbSYork Sun /* check override variable for overriding VDD */ 2691cb19fbbSYork Sun vdd_string = getenv("t4240qds_vdd_mv"); 2701cb19fbbSYork Sun if (vdd_override == 0 && vdd_string && 2711cb19fbbSYork Sun !strict_strtoul(vdd_string, 10, &vdd_string_override)) 2721cb19fbbSYork Sun vdd_override = vdd_string_override; 2731cb19fbbSYork Sun if (vdd_override >= 819 && vdd_override <= 1212) { 2741cb19fbbSYork Sun vdd_target = vdd_override * 10; /* convert to 1/10 mV */ 2751cb19fbbSYork Sun debug("VDD override is %lu\n", vdd_override); 2761cb19fbbSYork Sun } else if (vdd_override != 0) { 2771cb19fbbSYork Sun printf("Invalid value.\n"); 2781cb19fbbSYork Sun } 2791cb19fbbSYork Sun 2801cb19fbbSYork Sun if (vdd_target == 0) { 2811cb19fbbSYork Sun debug("VID: VID not used\n"); 2821cb19fbbSYork Sun ret = 0; 2831cb19fbbSYork Sun goto exit; 2841cb19fbbSYork Sun } else { 2851cb19fbbSYork Sun /* round up and divice by 10 to get a value in mV */ 2861cb19fbbSYork Sun vdd_target = DIV_ROUND_UP(vdd_target, 10); 2871cb19fbbSYork Sun debug("VID: vid = %d mV\n", vdd_target); 2881cb19fbbSYork Sun } 2891cb19fbbSYork Sun 2901cb19fbbSYork Sun /* 2911cb19fbbSYork Sun * Check current board VID setting 2921cb19fbbSYork Sun * Voltage regulator support output to 6.250mv step 2931cb19fbbSYork Sun * The highes voltage allowed for this board is (vid=0x40) 1.21250V 2941cb19fbbSYork Sun * the lowest is (vid=0x7f) 0.81875V 2951cb19fbbSYork Sun */ 2961cb19fbbSYork Sun vid_current = QIXIS_READ(brdcfg[6]); 2971cb19fbbSYork Sun vdd_current = 121250 - (vid_current - 0x40) * 625; 2981cb19fbbSYork Sun debug("VID: Current vid setting is (0x%x) %d mV\n", 2991cb19fbbSYork Sun vid_current, vdd_current/100); 3001cb19fbbSYork Sun 3011cb19fbbSYork Sun /* 3021cb19fbbSYork Sun * Read voltage monitor to check real voltage. 3031cb19fbbSYork Sun * Voltage monitor LSB is 4mv. 3041cb19fbbSYork Sun */ 3051cb19fbbSYork Sun vdd_last = read_voltage(); 3061cb19fbbSYork Sun if (vdd_last < 0) { 3071cb19fbbSYork Sun printf("VID: Could not read voltage sensor abort VID adjustment\n"); 3081cb19fbbSYork Sun ret = -1; 3091cb19fbbSYork Sun goto exit; 3101cb19fbbSYork Sun } 3111cb19fbbSYork Sun debug("VID: Core voltage is at %d mV\n", vdd_last); 3121cb19fbbSYork Sun /* 3131cb19fbbSYork Sun * Adjust voltage to at or 8mV above target. 3141cb19fbbSYork Sun * Each step of adjustment is 6.25mV. 3151cb19fbbSYork Sun * Stepping down too fast may cause over current. 3161cb19fbbSYork Sun */ 3171cb19fbbSYork Sun while (vdd_last > 0 && vid_current < 0x80 && 3181cb19fbbSYork Sun vdd_last > (vdd_target + 8)) { 3191cb19fbbSYork Sun vid_current++; 3201cb19fbbSYork Sun vdd_last = set_voltage(vid_current); 3211cb19fbbSYork Sun } 3221cb19fbbSYork Sun /* 3231cb19fbbSYork Sun * Check if we need to step up 3241cb19fbbSYork Sun * This happens when board voltage switch was set too low 3251cb19fbbSYork Sun */ 3261cb19fbbSYork Sun while (vdd_last > 0 && vid_current >= 0x40 && 3271cb19fbbSYork Sun vdd_last < vdd_target + 2) { 3281cb19fbbSYork Sun vid_current--; 3291cb19fbbSYork Sun vdd_last = set_voltage(vid_current); 3301cb19fbbSYork Sun } 3311cb19fbbSYork Sun if (vdd_last > 0) 3321cb19fbbSYork Sun printf("VID: Core voltage %d mV\n", vdd_last); 3331cb19fbbSYork Sun else 3341cb19fbbSYork Sun ret = -1; 3351cb19fbbSYork Sun 3361cb19fbbSYork Sun exit: 3371cb19fbbSYork Sun if (re_enable) 3381cb19fbbSYork Sun enable_interrupts(); 3391cb19fbbSYork Sun return ret; 3401cb19fbbSYork Sun } 3411cb19fbbSYork Sun 3421cb19fbbSYork Sun /* Configure Crossbar switches for Front-Side SerDes Ports */ 3431cb19fbbSYork Sun int config_frontside_crossbar_vsc3316(void) 3441cb19fbbSYork Sun { 3451cb19fbbSYork Sun ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 3461cb19fbbSYork Sun u32 srds_prtcl_s1, srds_prtcl_s2; 3471cb19fbbSYork Sun int ret; 3481cb19fbbSYork Sun 3491cb19fbbSYork Sun ret = select_i2c_ch_pca9547(I2C_MUX_CH_VSC3316_FS); 3501cb19fbbSYork Sun if (ret) 3511cb19fbbSYork Sun return ret; 3521cb19fbbSYork Sun 3531cb19fbbSYork Sun srds_prtcl_s1 = in_be32(&gur->rcwsr[4]) & 3541cb19fbbSYork Sun FSL_CORENET2_RCWSR4_SRDS1_PRTCL; 3551cb19fbbSYork Sun srds_prtcl_s1 >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT; 356ae3dcd04SShaohui Xie switch (srds_prtcl_s1) { 35794752f60SShaohui Xie case 37: 358ae3dcd04SShaohui Xie case 38: 359ae3dcd04SShaohui Xie /* swap first lane and third lane on slot1 */ 360ae3dcd04SShaohui Xie vsc3316_fsm1_tx[0][1] = 14; 361ae3dcd04SShaohui Xie vsc3316_fsm1_tx[6][1] = 0; 362ae3dcd04SShaohui Xie vsc3316_fsm1_rx[1][1] = 2; 363ae3dcd04SShaohui Xie vsc3316_fsm1_rx[6][1] = 13; 36494752f60SShaohui Xie case 39: 365ae3dcd04SShaohui Xie case 40: 36694752f60SShaohui Xie case 45: 367ae3dcd04SShaohui Xie case 46: 36894752f60SShaohui Xie case 47: 369ae3dcd04SShaohui Xie case 48: 370ae3dcd04SShaohui Xie /* swap first lane and third lane on slot2 */ 371ae3dcd04SShaohui Xie vsc3316_fsm1_tx[2][1] = 8; 372ae3dcd04SShaohui Xie vsc3316_fsm1_tx[4][1] = 6; 373ae3dcd04SShaohui Xie vsc3316_fsm1_rx[2][1] = 10; 374ae3dcd04SShaohui Xie vsc3316_fsm1_rx[5][1] = 5; 375ae3dcd04SShaohui Xie default: 3761cb19fbbSYork Sun ret = vsc3316_config(VSC3316_FSM_TX_ADDR, vsc3316_fsm1_tx, 8); 3771cb19fbbSYork Sun if (ret) 3781cb19fbbSYork Sun return ret; 3791cb19fbbSYork Sun ret = vsc3316_config(VSC3316_FSM_RX_ADDR, vsc3316_fsm1_rx, 8); 3801cb19fbbSYork Sun if (ret) 3811cb19fbbSYork Sun return ret; 382ae3dcd04SShaohui Xie break; 3831cb19fbbSYork Sun } 3841cb19fbbSYork Sun 3851cb19fbbSYork Sun srds_prtcl_s2 = in_be32(&gur->rcwsr[4]) & 3861cb19fbbSYork Sun FSL_CORENET2_RCWSR4_SRDS2_PRTCL; 3871cb19fbbSYork Sun srds_prtcl_s2 >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT; 388ae3dcd04SShaohui Xie switch (srds_prtcl_s2) { 38994752f60SShaohui Xie case 37: 390ae3dcd04SShaohui Xie case 38: 391ae3dcd04SShaohui Xie /* swap first lane and third lane on slot3 */ 392ae3dcd04SShaohui Xie vsc3316_fsm2_tx[2][1] = 11; 393ae3dcd04SShaohui Xie vsc3316_fsm2_tx[5][1] = 4; 394ae3dcd04SShaohui Xie vsc3316_fsm2_rx[2][1] = 9; 395ae3dcd04SShaohui Xie vsc3316_fsm2_rx[4][1] = 7; 39694752f60SShaohui Xie case 39: 397ae3dcd04SShaohui Xie case 40: 39894752f60SShaohui Xie case 45: 399ae3dcd04SShaohui Xie case 46: 40094752f60SShaohui Xie case 47: 401ae3dcd04SShaohui Xie case 48: 40294752f60SShaohui Xie case 49: 403ae3dcd04SShaohui Xie case 50: 40494752f60SShaohui Xie case 51: 405ae3dcd04SShaohui Xie case 52: 40694752f60SShaohui Xie case 53: 407ae3dcd04SShaohui Xie case 54: 408ae3dcd04SShaohui Xie /* swap first lane and third lane on slot4 */ 409ae3dcd04SShaohui Xie vsc3316_fsm2_tx[6][1] = 3; 410ae3dcd04SShaohui Xie vsc3316_fsm2_tx[1][1] = 12; 411ae3dcd04SShaohui Xie vsc3316_fsm2_rx[0][1] = 1; 412ae3dcd04SShaohui Xie vsc3316_fsm2_rx[6][1] = 15; 413ae3dcd04SShaohui Xie default: 4141cb19fbbSYork Sun ret = vsc3316_config(VSC3316_FSM_TX_ADDR, vsc3316_fsm2_tx, 8); 4151cb19fbbSYork Sun if (ret) 4161cb19fbbSYork Sun return ret; 4171cb19fbbSYork Sun ret = vsc3316_config(VSC3316_FSM_RX_ADDR, vsc3316_fsm2_rx, 8); 4181cb19fbbSYork Sun if (ret) 4191cb19fbbSYork Sun return ret; 420ae3dcd04SShaohui Xie break; 4211cb19fbbSYork Sun } 4221cb19fbbSYork Sun 4231cb19fbbSYork Sun return 0; 4241cb19fbbSYork Sun } 4251cb19fbbSYork Sun 4261cb19fbbSYork Sun int config_backside_crossbar_mux(void) 4271cb19fbbSYork Sun { 4281cb19fbbSYork Sun ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 4291cb19fbbSYork Sun u32 srds_prtcl_s3, srds_prtcl_s4; 4301cb19fbbSYork Sun u8 brdcfg; 4311cb19fbbSYork Sun 4321cb19fbbSYork Sun srds_prtcl_s3 = in_be32(&gur->rcwsr[4]) & 4331cb19fbbSYork Sun FSL_CORENET2_RCWSR4_SRDS3_PRTCL; 4341cb19fbbSYork Sun srds_prtcl_s3 >>= FSL_CORENET2_RCWSR4_SRDS3_PRTCL_SHIFT; 4351cb19fbbSYork Sun switch (srds_prtcl_s3) { 4361cb19fbbSYork Sun case 0: 4371cb19fbbSYork Sun /* SerDes3 is not enabled */ 4381cb19fbbSYork Sun break; 43994752f60SShaohui Xie case 1: 4401cb19fbbSYork Sun case 2: 4411cb19fbbSYork Sun case 9: 4421cb19fbbSYork Sun case 10: 4431cb19fbbSYork Sun /* SD3(0:7) => SLOT5(0:7) */ 4441cb19fbbSYork Sun brdcfg = QIXIS_READ(brdcfg[12]); 4451cb19fbbSYork Sun brdcfg &= ~BRDCFG12_SD3MX_MASK; 4461cb19fbbSYork Sun brdcfg |= BRDCFG12_SD3MX_SLOT5; 4471cb19fbbSYork Sun QIXIS_WRITE(brdcfg[12], brdcfg); 4481cb19fbbSYork Sun break; 44994752f60SShaohui Xie case 3: 4501cb19fbbSYork Sun case 4: 45194752f60SShaohui Xie case 5: 4521cb19fbbSYork Sun case 6: 45394752f60SShaohui Xie case 7: 4541cb19fbbSYork Sun case 8: 45594752f60SShaohui Xie case 11: 4561cb19fbbSYork Sun case 12: 45794752f60SShaohui Xie case 13: 4581cb19fbbSYork Sun case 14: 45994752f60SShaohui Xie case 15: 4601cb19fbbSYork Sun case 16: 4611cb19fbbSYork Sun case 17: 46294752f60SShaohui Xie case 18: 4631cb19fbbSYork Sun case 19: 4641cb19fbbSYork Sun case 20: 4651cb19fbbSYork Sun /* SD3(4:7) => SLOT6(0:3) */ 4661cb19fbbSYork Sun brdcfg = QIXIS_READ(brdcfg[12]); 4671cb19fbbSYork Sun brdcfg &= ~BRDCFG12_SD3MX_MASK; 4681cb19fbbSYork Sun brdcfg |= BRDCFG12_SD3MX_SLOT6; 4691cb19fbbSYork Sun QIXIS_WRITE(brdcfg[12], brdcfg); 4701cb19fbbSYork Sun break; 4711cb19fbbSYork Sun default: 4721cb19fbbSYork Sun printf("WARNING: unsupported for SerDes3 Protocol %d\n", 4731cb19fbbSYork Sun srds_prtcl_s3); 4741cb19fbbSYork Sun return -1; 4751cb19fbbSYork Sun } 4761cb19fbbSYork Sun 4771cb19fbbSYork Sun srds_prtcl_s4 = in_be32(&gur->rcwsr[4]) & 4781cb19fbbSYork Sun FSL_CORENET2_RCWSR4_SRDS4_PRTCL; 4791cb19fbbSYork Sun srds_prtcl_s4 >>= FSL_CORENET2_RCWSR4_SRDS4_PRTCL_SHIFT; 4801cb19fbbSYork Sun switch (srds_prtcl_s4) { 4811cb19fbbSYork Sun case 0: 4821cb19fbbSYork Sun /* SerDes4 is not enabled */ 4831cb19fbbSYork Sun break; 48494752f60SShaohui Xie case 1: 4851cb19fbbSYork Sun case 2: 4861cb19fbbSYork Sun /* 10b, SD4(0:7) => SLOT7(0:7) */ 4871cb19fbbSYork Sun brdcfg = QIXIS_READ(brdcfg[12]); 4881cb19fbbSYork Sun brdcfg &= ~BRDCFG12_SD4MX_MASK; 4891cb19fbbSYork Sun brdcfg |= BRDCFG12_SD4MX_SLOT7; 4901cb19fbbSYork Sun QIXIS_WRITE(brdcfg[12], brdcfg); 4911cb19fbbSYork Sun break; 49294752f60SShaohui Xie case 3: 4931cb19fbbSYork Sun case 4: 49494752f60SShaohui Xie case 5: 4951cb19fbbSYork Sun case 6: 49694752f60SShaohui Xie case 7: 4971cb19fbbSYork Sun case 8: 4981cb19fbbSYork Sun /* x1b, SD4(4:7) => SLOT8(0:3) */ 4991cb19fbbSYork Sun brdcfg = QIXIS_READ(brdcfg[12]); 5001cb19fbbSYork Sun brdcfg &= ~BRDCFG12_SD4MX_MASK; 5011cb19fbbSYork Sun brdcfg |= BRDCFG12_SD4MX_SLOT8; 5021cb19fbbSYork Sun QIXIS_WRITE(brdcfg[12], brdcfg); 5031cb19fbbSYork Sun break; 50494752f60SShaohui Xie case 9: 5051cb19fbbSYork Sun case 10: 50694752f60SShaohui Xie case 11: 5071cb19fbbSYork Sun case 12: 50894752f60SShaohui Xie case 13: 5091cb19fbbSYork Sun case 14: 51094752f60SShaohui Xie case 15: 5111cb19fbbSYork Sun case 16: 5121cb19fbbSYork Sun case 18: 5131cb19fbbSYork Sun /* 00b, SD4(4:5) => AURORA, SD4(6:7) => SATA */ 5141cb19fbbSYork Sun brdcfg = QIXIS_READ(brdcfg[12]); 5151cb19fbbSYork Sun brdcfg &= ~BRDCFG12_SD4MX_MASK; 5161cb19fbbSYork Sun brdcfg |= BRDCFG12_SD4MX_AURO_SATA; 5171cb19fbbSYork Sun QIXIS_WRITE(brdcfg[12], brdcfg); 5181cb19fbbSYork Sun break; 5191cb19fbbSYork Sun default: 5201cb19fbbSYork Sun printf("WARNING: unsupported for SerDes4 Protocol %d\n", 5211cb19fbbSYork Sun srds_prtcl_s4); 5221cb19fbbSYork Sun return -1; 5231cb19fbbSYork Sun } 5241cb19fbbSYork Sun 5251cb19fbbSYork Sun return 0; 5261cb19fbbSYork Sun } 5271cb19fbbSYork Sun 5281cb19fbbSYork Sun int board_early_init_r(void) 5291cb19fbbSYork Sun { 5301cb19fbbSYork Sun const unsigned int flashbase = CONFIG_SYS_FLASH_BASE; 5319d045682SYork Sun int flash_esel = find_tlb_idx((void *)flashbase, 1); 5321cb19fbbSYork Sun 5331cb19fbbSYork Sun /* 5341cb19fbbSYork Sun * Remap Boot flash + PROMJET region to caching-inhibited 5351cb19fbbSYork Sun * so that flash can be erased properly. 5361cb19fbbSYork Sun */ 5371cb19fbbSYork Sun 5381cb19fbbSYork Sun /* Flush d-cache and invalidate i-cache of any FLASH data */ 5391cb19fbbSYork Sun flush_dcache(); 5401cb19fbbSYork Sun invalidate_icache(); 5411cb19fbbSYork Sun 5429d045682SYork Sun if (flash_esel == -1) { 5439d045682SYork Sun /* very unlikely unless something is messed up */ 5449d045682SYork Sun puts("Error: Could not find TLB for FLASH BASE\n"); 5459d045682SYork Sun flash_esel = 2; /* give our best effort to continue */ 5469d045682SYork Sun } else { 5471cb19fbbSYork Sun /* invalidate existing TLB entry for flash + promjet */ 5481cb19fbbSYork Sun disable_tlb(flash_esel); 5499d045682SYork Sun } 5501cb19fbbSYork Sun 5511cb19fbbSYork Sun set_tlb(1, flashbase, CONFIG_SYS_FLASH_BASE_PHYS, 5521cb19fbbSYork Sun MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I|MAS2_G, 5531cb19fbbSYork Sun 0, flash_esel, BOOKE_PAGESZ_256M, 1); 5541cb19fbbSYork Sun 5551cb19fbbSYork Sun set_liodns(); 5561cb19fbbSYork Sun #ifdef CONFIG_SYS_DPAA_QBMAN 5571cb19fbbSYork Sun setup_portals(); 5581cb19fbbSYork Sun #endif 5591cb19fbbSYork Sun 5601cb19fbbSYork Sun /* Disable remote I2C connection to qixis fpga */ 5611cb19fbbSYork Sun QIXIS_WRITE(brdcfg[5], QIXIS_READ(brdcfg[5]) & ~BRDCFG5_IRE); 5621cb19fbbSYork Sun 5631cb19fbbSYork Sun /* 5641cb19fbbSYork Sun * Adjust core voltage according to voltage ID 5651cb19fbbSYork Sun * This function changes I2C mux to channel 2. 5661cb19fbbSYork Sun */ 5671cb19fbbSYork Sun if (adjust_vdd(0)) 5681cb19fbbSYork Sun printf("Warning: Adjusting core voltage failed.\n"); 5691cb19fbbSYork Sun 5701cb19fbbSYork Sun /* Configure board SERDES ports crossbar */ 5711cb19fbbSYork Sun config_frontside_crossbar_vsc3316(); 5721cb19fbbSYork Sun config_backside_crossbar_mux(); 5731cb19fbbSYork Sun select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT); 5741cb19fbbSYork Sun 5751cb19fbbSYork Sun return 0; 5761cb19fbbSYork Sun } 5771cb19fbbSYork Sun 5781cb19fbbSYork Sun unsigned long get_board_sys_clk(void) 5791cb19fbbSYork Sun { 5801cb19fbbSYork Sun u8 sysclk_conf = QIXIS_READ(brdcfg[1]); 5811cb19fbbSYork Sun #ifdef CONFIG_FSL_QIXIS_CLOCK_MEASUREMENT 5821cb19fbbSYork Sun /* use accurate clock measurement */ 5831cb19fbbSYork Sun int freq = QIXIS_READ(clk_freq[0]) << 8 | QIXIS_READ(clk_freq[1]); 5841cb19fbbSYork Sun int base = QIXIS_READ(clk_base[0]) << 8 | QIXIS_READ(clk_base[1]); 5851cb19fbbSYork Sun u32 val; 5861cb19fbbSYork Sun 5871cb19fbbSYork Sun val = freq * base; 5881cb19fbbSYork Sun if (val) { 5891cb19fbbSYork Sun debug("SYS Clock measurement is: %d\n", val); 5901cb19fbbSYork Sun return val; 5911cb19fbbSYork Sun } else { 5921cb19fbbSYork Sun printf("Warning: SYS clock measurement is invalid, using value from brdcfg1.\n"); 5931cb19fbbSYork Sun } 5941cb19fbbSYork Sun #endif 5951cb19fbbSYork Sun 5961cb19fbbSYork Sun switch (sysclk_conf & 0x0F) { 5971cb19fbbSYork Sun case QIXIS_SYSCLK_83: 5981cb19fbbSYork Sun return 83333333; 5991cb19fbbSYork Sun case QIXIS_SYSCLK_100: 6001cb19fbbSYork Sun return 100000000; 6011cb19fbbSYork Sun case QIXIS_SYSCLK_125: 6021cb19fbbSYork Sun return 125000000; 6031cb19fbbSYork Sun case QIXIS_SYSCLK_133: 6041cb19fbbSYork Sun return 133333333; 6051cb19fbbSYork Sun case QIXIS_SYSCLK_150: 6061cb19fbbSYork Sun return 150000000; 6071cb19fbbSYork Sun case QIXIS_SYSCLK_160: 6081cb19fbbSYork Sun return 160000000; 6091cb19fbbSYork Sun case QIXIS_SYSCLK_166: 6101cb19fbbSYork Sun return 166666666; 6111cb19fbbSYork Sun } 6121cb19fbbSYork Sun return 66666666; 6131cb19fbbSYork Sun } 6141cb19fbbSYork Sun 6151cb19fbbSYork Sun unsigned long get_board_ddr_clk(void) 6161cb19fbbSYork Sun { 6171cb19fbbSYork Sun u8 ddrclk_conf = QIXIS_READ(brdcfg[1]); 6181cb19fbbSYork Sun #ifdef CONFIG_FSL_QIXIS_CLOCK_MEASUREMENT 6191cb19fbbSYork Sun /* use accurate clock measurement */ 6201cb19fbbSYork Sun int freq = QIXIS_READ(clk_freq[2]) << 8 | QIXIS_READ(clk_freq[3]); 6211cb19fbbSYork Sun int base = QIXIS_READ(clk_base[0]) << 8 | QIXIS_READ(clk_base[1]); 6221cb19fbbSYork Sun u32 val; 6231cb19fbbSYork Sun 6241cb19fbbSYork Sun val = freq * base; 6251cb19fbbSYork Sun if (val) { 6261cb19fbbSYork Sun debug("DDR Clock measurement is: %d\n", val); 6271cb19fbbSYork Sun return val; 6281cb19fbbSYork Sun } else { 6291cb19fbbSYork Sun printf("Warning: DDR clock measurement is invalid, using value from brdcfg1.\n"); 6301cb19fbbSYork Sun } 6311cb19fbbSYork Sun #endif 6321cb19fbbSYork Sun 6331cb19fbbSYork Sun switch ((ddrclk_conf & 0x30) >> 4) { 6341cb19fbbSYork Sun case QIXIS_DDRCLK_100: 6351cb19fbbSYork Sun return 100000000; 6361cb19fbbSYork Sun case QIXIS_DDRCLK_125: 6371cb19fbbSYork Sun return 125000000; 6381cb19fbbSYork Sun case QIXIS_DDRCLK_133: 6391cb19fbbSYork Sun return 133333333; 6401cb19fbbSYork Sun } 6411cb19fbbSYork Sun return 66666666; 6421cb19fbbSYork Sun } 6431cb19fbbSYork Sun 6441cb19fbbSYork Sun int misc_init_r(void) 6451cb19fbbSYork Sun { 6461cb19fbbSYork Sun u8 sw; 647e55782ecSShaohui Xie void *srds_base = (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR; 648e55782ecSShaohui Xie serdes_corenet_t *srds_regs; 6491cb19fbbSYork Sun u32 actual[MAX_SERDES]; 650e55782ecSShaohui Xie u32 pllcr0, expected; 6511cb19fbbSYork Sun unsigned int i; 6521cb19fbbSYork Sun 6531cb19fbbSYork Sun sw = QIXIS_READ(brdcfg[2]); 6541cb19fbbSYork Sun for (i = 0; i < MAX_SERDES; i++) { 6551cb19fbbSYork Sun unsigned int clock = (sw >> (6 - 2 * i)) & 3; 6561cb19fbbSYork Sun switch (clock) { 6571cb19fbbSYork Sun case 0: 6581cb19fbbSYork Sun actual[i] = SRDS_PLLCR0_RFCK_SEL_100; 6591cb19fbbSYork Sun break; 6601cb19fbbSYork Sun case 1: 6611cb19fbbSYork Sun actual[i] = SRDS_PLLCR0_RFCK_SEL_125; 6621cb19fbbSYork Sun break; 6631cb19fbbSYork Sun case 2: 6641cb19fbbSYork Sun actual[i] = SRDS_PLLCR0_RFCK_SEL_156_25; 6651cb19fbbSYork Sun break; 6661cb19fbbSYork Sun case 3: 6671cb19fbbSYork Sun actual[i] = SRDS_PLLCR0_RFCK_SEL_161_13; 6681cb19fbbSYork Sun break; 6691cb19fbbSYork Sun } 6701cb19fbbSYork Sun } 6711cb19fbbSYork Sun 6721cb19fbbSYork Sun for (i = 0; i < MAX_SERDES; i++) { 673e55782ecSShaohui Xie srds_regs = srds_base + i * 0x1000; 674e55782ecSShaohui Xie pllcr0 = srds_regs->bank[0].pllcr0; 675e55782ecSShaohui Xie expected = pllcr0 & SRDS_PLLCR0_RFCK_SEL_MASK; 6761cb19fbbSYork Sun if (expected != actual[i]) { 6771cb19fbbSYork Sun printf("Warning: SERDES%u expects reference clock %sMHz, but actual is %sMHz\n", 6781cb19fbbSYork Sun i + 1, serdes_clock_to_string(expected), 6791cb19fbbSYork Sun serdes_clock_to_string(actual[i])); 6801cb19fbbSYork Sun } 6811cb19fbbSYork Sun } 6821cb19fbbSYork Sun 6831cb19fbbSYork Sun return 0; 6841cb19fbbSYork Sun } 6851cb19fbbSYork Sun 686*e895a4b0SSimon Glass int ft_board_setup(void *blob, bd_t *bd) 6871cb19fbbSYork Sun { 6881cb19fbbSYork Sun phys_addr_t base; 6891cb19fbbSYork Sun phys_size_t size; 6901cb19fbbSYork Sun 6911cb19fbbSYork Sun ft_cpu_setup(blob, bd); 6921cb19fbbSYork Sun 6931cb19fbbSYork Sun base = getenv_bootm_low(); 6941cb19fbbSYork Sun size = getenv_bootm_size(); 6951cb19fbbSYork Sun 6961cb19fbbSYork Sun fdt_fixup_memory(blob, (u64)base, (u64)size); 6971cb19fbbSYork Sun 6981cb19fbbSYork Sun #ifdef CONFIG_PCI 6991cb19fbbSYork Sun pci_of_setup(blob, bd); 7001cb19fbbSYork Sun #endif 7011cb19fbbSYork Sun 7021cb19fbbSYork Sun fdt_fixup_liodn(blob); 7031cb19fbbSYork Sun fdt_fixup_dr_usb(blob, bd); 7041cb19fbbSYork Sun 7051cb19fbbSYork Sun #ifdef CONFIG_SYS_DPAA_FMAN 7061cb19fbbSYork Sun fdt_fixup_fman_ethernet(blob); 7071cb19fbbSYork Sun fdt_fixup_board_enet(blob); 7081cb19fbbSYork Sun #endif 709*e895a4b0SSimon Glass 710*e895a4b0SSimon Glass return 0; 7111cb19fbbSYork Sun } 7121cb19fbbSYork Sun 7131cb19fbbSYork Sun /* 7141cb19fbbSYork Sun * This function is called by bdinfo to print detail board information. 7151cb19fbbSYork Sun * As an exmaple for future board, we organize the messages into 7161cb19fbbSYork Sun * several sections. If applicable, the message is in the format of 7171cb19fbbSYork Sun * <name> = <value> 7181cb19fbbSYork Sun * It should aligned with normal output of bdinfo command. 7191cb19fbbSYork Sun * 7201cb19fbbSYork Sun * Voltage: Core, DDR and another configurable voltages 7211cb19fbbSYork Sun * Clock : Critical clocks which are not printed already 7221cb19fbbSYork Sun * RCW : RCW source if not printed already 7231cb19fbbSYork Sun * Misc : Other important information not in above catagories 7241cb19fbbSYork Sun */ 7251cb19fbbSYork Sun void board_detail(void) 7261cb19fbbSYork Sun { 7271cb19fbbSYork Sun int i; 7281cb19fbbSYork Sun u8 brdcfg[16], dutcfg[16], rst_ctl; 7291cb19fbbSYork Sun int vdd, rcwsrc; 7301cb19fbbSYork Sun static const char * const clk[] = {"66.67", "100", "125", "133.33"}; 7311cb19fbbSYork Sun 7321cb19fbbSYork Sun for (i = 0; i < 16; i++) { 7331cb19fbbSYork Sun brdcfg[i] = qixis_read(offsetof(struct qixis, brdcfg[0]) + i); 7341cb19fbbSYork Sun dutcfg[i] = qixis_read(offsetof(struct qixis, dutcfg[0]) + i); 7351cb19fbbSYork Sun } 7361cb19fbbSYork Sun 7371cb19fbbSYork Sun /* Voltage secion */ 7381cb19fbbSYork Sun if (!select_i2c_ch_pca9547(I2C_MUX_CH_VOL_MONITOR)) { 7391cb19fbbSYork Sun vdd = read_voltage(); 7401cb19fbbSYork Sun if (vdd > 0) 7411cb19fbbSYork Sun printf("Core voltage= %d mV\n", vdd); 7421cb19fbbSYork Sun select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT); 7431cb19fbbSYork Sun } 7441cb19fbbSYork Sun 7451cb19fbbSYork Sun printf("XVDD = 1.%d V\n", ((brdcfg[8] & 0xf) - 4) * 5 + 25); 7461cb19fbbSYork Sun 7471cb19fbbSYork Sun /* clock section */ 7481cb19fbbSYork Sun printf("SYSCLK = %s MHz\nDDRCLK = %s MHz\n", 7491cb19fbbSYork Sun clk[(brdcfg[11] >> 2) & 0x3], clk[brdcfg[11] & 3]); 7501cb19fbbSYork Sun 7511cb19fbbSYork Sun /* RCW section */ 7521cb19fbbSYork Sun rcwsrc = (dutcfg[0] << 1) + (dutcfg[1] & 1); 7531cb19fbbSYork Sun puts("RCW source = "); 7541cb19fbbSYork Sun switch (rcwsrc) { 7551cb19fbbSYork Sun case 0x017: 7561cb19fbbSYork Sun case 0x01f: 7571cb19fbbSYork Sun puts("8-bit NOR\n"); 7581cb19fbbSYork Sun break; 7591cb19fbbSYork Sun case 0x027: 7601cb19fbbSYork Sun case 0x02F: 7611cb19fbbSYork Sun puts("16-bit NOR\n"); 7621cb19fbbSYork Sun break; 7631cb19fbbSYork Sun case 0x040: 7641cb19fbbSYork Sun puts("SDHC/eMMC\n"); 7651cb19fbbSYork Sun break; 7661cb19fbbSYork Sun case 0x044: 7671cb19fbbSYork Sun puts("SPI 16-bit addressing\n"); 7681cb19fbbSYork Sun break; 7691cb19fbbSYork Sun case 0x045: 7701cb19fbbSYork Sun puts("SPI 24-bit addressing\n"); 7711cb19fbbSYork Sun break; 7721cb19fbbSYork Sun case 0x048: 7731cb19fbbSYork Sun puts("I2C normal addressing\n"); 7741cb19fbbSYork Sun break; 7751cb19fbbSYork Sun case 0x049: 7761cb19fbbSYork Sun puts("I2C extended addressing\n"); 7771cb19fbbSYork Sun break; 7781cb19fbbSYork Sun case 0x108: 7791cb19fbbSYork Sun case 0x109: 7801cb19fbbSYork Sun case 0x10a: 7811cb19fbbSYork Sun case 0x10b: 7821cb19fbbSYork Sun puts("8-bit NAND, 2KB\n"); 7831cb19fbbSYork Sun break; 7841cb19fbbSYork Sun default: 7851cb19fbbSYork Sun if ((rcwsrc >= 0x080) && (rcwsrc <= 0x09f)) 7861cb19fbbSYork Sun puts("Hard-coded RCW\n"); 7871cb19fbbSYork Sun else if ((rcwsrc >= 0x110) && (rcwsrc <= 0x11f)) 7881cb19fbbSYork Sun puts("8-bit NAND, 4KB\n"); 7891cb19fbbSYork Sun else 7901cb19fbbSYork Sun puts("unknown\n"); 7911cb19fbbSYork Sun break; 7921cb19fbbSYork Sun } 7931cb19fbbSYork Sun 7941cb19fbbSYork Sun /* Misc section */ 7951cb19fbbSYork Sun rst_ctl = QIXIS_READ(rst_ctl); 7961cb19fbbSYork Sun puts("HRESET_REQ = "); 7971cb19fbbSYork Sun switch (rst_ctl & 0x30) { 7981cb19fbbSYork Sun case 0x00: 7991cb19fbbSYork Sun puts("Ignored\n"); 8001cb19fbbSYork Sun break; 8011cb19fbbSYork Sun case 0x10: 8021cb19fbbSYork Sun puts("Assert HRESET\n"); 8031cb19fbbSYork Sun break; 8041cb19fbbSYork Sun case 0x30: 8051cb19fbbSYork Sun puts("Reset system\n"); 8061cb19fbbSYork Sun break; 8071cb19fbbSYork Sun default: 8081cb19fbbSYork Sun puts("N/A\n"); 8091cb19fbbSYork Sun break; 8101cb19fbbSYork Sun } 8111cb19fbbSYork Sun } 8121cb19fbbSYork Sun 8131cb19fbbSYork Sun /* 8141cb19fbbSYork Sun * Reverse engineering switch settings. 8151cb19fbbSYork Sun * Some bits cannot be figured out. They will be displayed as 8161cb19fbbSYork Sun * underscore in binary format. mask[] has those bits. 8171cb19fbbSYork Sun * Some bits are calculated differently than the actual switches 8181cb19fbbSYork Sun * if booting with overriding by FPGA. 8191cb19fbbSYork Sun */ 8201cb19fbbSYork Sun void qixis_dump_switch(void) 8211cb19fbbSYork Sun { 8221cb19fbbSYork Sun int i; 8231cb19fbbSYork Sun u8 sw[9]; 8241cb19fbbSYork Sun 8251cb19fbbSYork Sun /* 8261cb19fbbSYork Sun * Any bit with 1 means that bit cannot be reverse engineered. 8271cb19fbbSYork Sun * It will be displayed as _ in binary format. 8281cb19fbbSYork Sun */ 8291cb19fbbSYork Sun static const u8 mask[] = {0, 0, 0, 0, 0, 0x1, 0xcf, 0x3f, 0x1f}; 8301cb19fbbSYork Sun char buf[10]; 8311cb19fbbSYork Sun u8 brdcfg[16], dutcfg[16]; 8321cb19fbbSYork Sun 8331cb19fbbSYork Sun for (i = 0; i < 16; i++) { 8341cb19fbbSYork Sun brdcfg[i] = qixis_read(offsetof(struct qixis, brdcfg[0]) + i); 8351cb19fbbSYork Sun dutcfg[i] = qixis_read(offsetof(struct qixis, dutcfg[0]) + i); 8361cb19fbbSYork Sun } 8371cb19fbbSYork Sun 8381cb19fbbSYork Sun sw[0] = dutcfg[0]; 8391cb19fbbSYork Sun sw[1] = (dutcfg[1] << 0x07) | 8401cb19fbbSYork Sun ((dutcfg[12] & 0xC0) >> 1) | 8411cb19fbbSYork Sun ((dutcfg[11] & 0xE0) >> 3) | 8421cb19fbbSYork Sun ((dutcfg[6] & 0x80) >> 6) | 8431cb19fbbSYork Sun ((dutcfg[1] & 0x80) >> 7); 8441cb19fbbSYork Sun sw[2] = ((brdcfg[1] & 0x0f) << 4) | 8451cb19fbbSYork Sun ((brdcfg[1] & 0x30) >> 2) | 8461cb19fbbSYork Sun ((brdcfg[1] & 0x40) >> 5) | 8471cb19fbbSYork Sun ((brdcfg[1] & 0x80) >> 7); 8481cb19fbbSYork Sun sw[3] = brdcfg[2]; 8491cb19fbbSYork Sun sw[4] = ((dutcfg[2] & 0x01) << 7) | 8501cb19fbbSYork Sun ((dutcfg[2] & 0x06) << 4) | 8511cb19fbbSYork Sun ((~QIXIS_READ(present)) & 0x10) | 8521cb19fbbSYork Sun ((brdcfg[3] & 0x80) >> 4) | 8531cb19fbbSYork Sun ((brdcfg[3] & 0x01) << 2) | 8541cb19fbbSYork Sun ((brdcfg[6] == 0x62) ? 3 : 8551cb19fbbSYork Sun ((brdcfg[6] == 0x5a) ? 2 : 8561cb19fbbSYork Sun ((brdcfg[6] == 0x5e) ? 1 : 0))); 8571cb19fbbSYork Sun sw[5] = ((brdcfg[0] & 0x0f) << 4) | 8581cb19fbbSYork Sun ((QIXIS_READ(rst_ctl) & 0x30) >> 2) | 8591cb19fbbSYork Sun ((brdcfg[0] & 0x40) >> 5); 8601cb19fbbSYork Sun sw[6] = (brdcfg[11] & 0x20) | 8611cb19fbbSYork Sun ((brdcfg[5] & 0x02) << 3); 8621cb19fbbSYork Sun sw[7] = (((~QIXIS_READ(rst_ctl)) & 0x40) << 1) | 8631cb19fbbSYork Sun ((brdcfg[5] & 0x10) << 2); 8641cb19fbbSYork Sun sw[8] = ((brdcfg[12] & 0x08) << 4) | 8651cb19fbbSYork Sun ((brdcfg[12] & 0x03) << 5); 8661cb19fbbSYork Sun 8671cb19fbbSYork Sun puts("DIP switch (reverse-engineering)\n"); 8681cb19fbbSYork Sun for (i = 0; i < 9; i++) { 8691cb19fbbSYork Sun printf("SW%d = 0b%s (0x%02x)\n", 8701cb19fbbSYork Sun i + 1, byte_to_binary_mask(sw[i], mask[i], buf), sw[i]); 8711cb19fbbSYork Sun } 8721cb19fbbSYork Sun } 8731cb19fbbSYork Sun 8741cb19fbbSYork Sun static int do_vdd_adjust(cmd_tbl_t *cmdtp, 8751cb19fbbSYork Sun int flag, int argc, 8761cb19fbbSYork Sun char * const argv[]) 8771cb19fbbSYork Sun { 8781cb19fbbSYork Sun ulong override; 8791cb19fbbSYork Sun 8801cb19fbbSYork Sun if (argc < 2) 8811cb19fbbSYork Sun return CMD_RET_USAGE; 8821cb19fbbSYork Sun if (!strict_strtoul(argv[1], 10, &override)) 8831cb19fbbSYork Sun adjust_vdd(override); /* the value is checked by callee */ 8841cb19fbbSYork Sun else 8851cb19fbbSYork Sun return CMD_RET_USAGE; 8861cb19fbbSYork Sun 8871cb19fbbSYork Sun return 0; 8881cb19fbbSYork Sun } 8891cb19fbbSYork Sun 8901cb19fbbSYork Sun U_BOOT_CMD( 8911cb19fbbSYork Sun vdd_override, 2, 0, do_vdd_adjust, 8921cb19fbbSYork Sun "Override VDD", 8931cb19fbbSYork Sun "- override with the voltage specified in mV, eg. 1050" 8941cb19fbbSYork Sun ); 895