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