diff options
| -rw-r--r-- | board/gdsys/405ep/iocon.c | 218 | 
1 files changed, 171 insertions, 47 deletions
| diff --git a/board/gdsys/405ep/iocon.c b/board/gdsys/405ep/iocon.c index 664b1e164..7a98e41d0 100644 --- a/board/gdsys/405ep/iocon.c +++ b/board/gdsys/405ep/iocon.c @@ -99,7 +99,6 @@ unsigned int mclink_fpgacount;  struct ihs_fpga *fpga_ptr[] = CONFIG_SYS_FPGA_PTR;  static int setup_88e1518(const char *bus, unsigned char addr); -static int verify_88e1518(const char *bus, unsigned char addr);  int fpga_set_reg(u32 fpga, u16 *reg, off_t regoff, u16 data)  { @@ -405,11 +404,7 @@ int last_stage_init(void)  			if ((mux_ch == 1) && !ch0_rgmii2_present)  				continue; -			if (!verify_88e1518(bb_miiphy_buses[0].name, mux_ch)) { -				printf("Fixup 88e1518 erratum on %s phy %u\n", -				       bb_miiphy_buses[0].name, mux_ch); -				setup_88e1518(bb_miiphy_buses[0].name, mux_ch); -			} +			setup_88e1518(bb_miiphy_buses[0].name, mux_ch);  		}  	} @@ -434,11 +429,7 @@ int last_stage_init(void)  		if (feature_carrier_speed == CARRIER_SPEED_1G) {  			miiphy_register(bb_miiphy_buses[k].name,  					bb_miiphy_read, bb_miiphy_write); -			if (!verify_88e1518(bb_miiphy_buses[k].name, 0)) { -				printf("Fixup 88e1518 erratum on %s\n", -				       bb_miiphy_buses[k].name); -				setup_88e1518(bb_miiphy_buses[k].name, 0); -			} +			setup_88e1518(bb_miiphy_buses[k].name, 0);  		}  	} @@ -652,56 +643,189 @@ struct bb_miiphy_bus bb_miiphy_buses[] = {  int bb_miiphy_buses_num = sizeof(bb_miiphy_buses) /  			  sizeof(bb_miiphy_buses[0]); +enum { +	MIICMD_SET, +	MIICMD_MODIFY, +	MIICMD_VERIFY_VALUE, +	MIICMD_WAIT_FOR_VALUE, +}; + +struct mii_setupcmd { +	u8 token; +	u8 reg; +	u16 data; +	u16 mask; +	u32 timeout; +}; +  /* - * Workaround for erratum mentioned in 88E1518 release notes + * verify we are talking to a 88e1518   */ +struct mii_setupcmd verify_88e1518[] = { +	{ MIICMD_SET, 22, 0x0000 }, +	{ MIICMD_VERIFY_VALUE, 2, 0x0141, 0xffff }, +	{ MIICMD_VERIFY_VALUE, 3, 0x0dd0, 0xfff0 }, +}; -static int verify_88e1518(const char *bus, unsigned char addr) +/* + * workaround for erratum mentioned in 88E1518 release notes + */ +struct mii_setupcmd fixup_88e1518[] = { +	{ MIICMD_SET, 22, 0x00ff }, +	{ MIICMD_SET, 17, 0x214b }, +	{ MIICMD_SET, 16, 0x2144 }, +	{ MIICMD_SET, 17, 0x0c28 }, +	{ MIICMD_SET, 16, 0x2146 }, +	{ MIICMD_SET, 17, 0xb233 }, +	{ MIICMD_SET, 16, 0x214d }, +	{ MIICMD_SET, 17, 0xcc0c }, +	{ MIICMD_SET, 16, 0x2159 }, +	{ MIICMD_SET, 22, 0x00fb }, +	{ MIICMD_SET,  7, 0xc00d }, +	{ MIICMD_SET, 22, 0x0000 }, +}; + +/* + * default initialization: + * - set RGMII receive timing to "receive clock transition when data stable" + * - set RGMII transmit timing to "transmit clock internally delayed" + * - set RGMII output impedance target to 78,8 Ohm + * - run output impedance calibration + * - set autonegotiation advertise to 1000FD only + */ +struct mii_setupcmd default_88e1518[] = { +	{ MIICMD_SET, 22, 0x0002 }, +	{ MIICMD_MODIFY, 21, 0x0030, 0x0030 }, +	{ MIICMD_MODIFY, 25, 0x0000, 0x0003 }, +	{ MIICMD_MODIFY, 24, 0x8000, 0x8000 }, +	{ MIICMD_WAIT_FOR_VALUE, 24, 0x4000, 0x4000, 2000 }, +	{ MIICMD_SET, 22, 0x0000 }, +	{ MIICMD_MODIFY, 4, 0x0000, 0x01e0 }, +	{ MIICMD_MODIFY, 9, 0x0200, 0x0300 }, +}; + +/* + * turn off CLK125 for PHY daughterboard + */ +struct mii_setupcmd ch1fix_88e1518[] = { +	{ MIICMD_SET, 22, 0x0002 }, +	{ MIICMD_MODIFY, 16, 0x0006, 0x0006 }, +	{ MIICMD_SET, 22, 0x0000 }, +}; + +/* + * perform copper software reset + */ +struct mii_setupcmd swreset_88e1518[] = { +	{ MIICMD_SET, 22, 0x0000 }, +	{ MIICMD_MODIFY, 0, 0x8000, 0x8000 }, +	{ MIICMD_WAIT_FOR_VALUE, 0, 0x0000, 0x8000, 2000 }, +}; + +static int process_setupcmd(const char *bus, unsigned char addr, +			    struct mii_setupcmd *setupcmd)  { -	u16 phy_id1, phy_id2; +	int res; +	u8 reg = setupcmd->reg; +	u16 data = setupcmd->data; +	u16 mask = setupcmd->mask; +	u32 timeout = setupcmd->timeout; +	u16 orig_data; +	unsigned long start; -	if (miiphy_read(bus, addr, 2, &phy_id1) || -	    miiphy_read(bus, addr, 3, &phy_id2)) { -		printf("Error reading from the PHY addr=%02x\n", addr); -		return -EIO; -	} +	debug("mii %s:%u reg %2u ", bus, addr, reg); -	if ((phy_id1 != 0x0141) || ((phy_id2 & 0xfff0) != 0x0dd0)) -		return -EINVAL; +	switch (setupcmd->token) { +	case MIICMD_MODIFY: +		res = miiphy_read(bus, addr, reg, &orig_data); +		if (res) +			break; +		debug("is %04x. (value %04x mask %04x) ", orig_data, data, +		      mask); +		data = (orig_data & ~mask) | (data & mask); +	case MIICMD_SET: +		debug("=> %04x\n", data); +		res = miiphy_write(bus, addr, reg, data); +		break; +	case MIICMD_VERIFY_VALUE: +		res = miiphy_read(bus, addr, reg, &orig_data); +		if (res) +			break; +		if ((orig_data & mask) != (data & mask)) +			res = -1; +		debug("(value %04x mask %04x) == %04x? %s\n", data, mask, +		      orig_data, res ? "FAIL" : "PASS"); +		break; +	case MIICMD_WAIT_FOR_VALUE: +		res = -1; +		start = get_timer(0); +		while ((res != 0) && (get_timer(start) < timeout)) { +			res = miiphy_read(bus, addr, reg, &orig_data); +			if (res) +				continue; +			if ((orig_data & mask) != (data & mask)) +				res = -1; +		} +		debug("(value %04x mask %04x) == %04x? %s after %lu ms\n", data, +		      mask, orig_data, res ? "FAIL" : "PASS", +		      get_timer(start)); +		break; +	default: +		res = -1; +		break; +	} -	return 0; +	return res;  } -struct regfix_88e1518 { -	u8 reg; -	u16 data; -} regfix_88e1518[] = { -	{ 22, 0x00ff }, -	{ 17, 0x214b }, -	{ 16, 0x2144 }, -	{ 17, 0x0c28 }, -	{ 16, 0x2146 }, -	{ 17, 0xb233 }, -	{ 16, 0x214d }, -	{ 17, 0xcc0c }, -	{ 16, 0x2159 }, -	{ 22, 0x00fb }, -	{  7, 0xc00d }, -	{ 22, 0x0000 }, -}; - -static int setup_88e1518(const char *bus, unsigned char addr) +static int process_setup(const char *bus, unsigned char addr, +			    struct mii_setupcmd *setupcmd, unsigned int count)  { +	int res = 0;  	unsigned int k; -	for (k = 0; k < ARRAY_SIZE(regfix_88e1518); ++k) { -		if (miiphy_write(bus, addr, -				 regfix_88e1518[k].reg, -				 regfix_88e1518[k].data)) { -			printf("Error writing to the PHY addr=%02x\n", addr); -			return -1; +	for (k = 0; k < count; ++k) { +		res = process_setupcmd(bus, addr, &setupcmd[k]); +		if (res) { +			printf("mii cmd %u on bus %s addr %u failed, aborting setup", +			       setupcmd[k].token, bus, addr); +			break;  		}  	} +	return res; +} + +static int setup_88e1518(const char *bus, unsigned char addr) +{ +	int res; + +	res = process_setup(bus, addr, +			    verify_88e1518, ARRAY_SIZE(verify_88e1518)); +	if (res) +		return res; + +	res = process_setup(bus, addr, +			    fixup_88e1518, ARRAY_SIZE(fixup_88e1518)); +	if (res) +		return res; + +	res = process_setup(bus, addr, +			    default_88e1518, ARRAY_SIZE(default_88e1518)); +	if (res) +		return res; + +	if (addr) { +		res = process_setup(bus, addr, +				    ch1fix_88e1518, ARRAY_SIZE(ch1fix_88e1518)); +		if (res) +			return res; +	} + +	res = process_setup(bus, addr, +			    swreset_88e1518, ARRAY_SIZE(swreset_88e1518)); +	if (res) +		return res; +  	return 0;  } |