
From: Dirk Eibach eibach@gdsys.de
Marvell 88E1518 has an erratum that requires fixing up. This patch checks for presence of this phy and adds code for fixup.
Signed-off-by: Dirk Eibach dirk.eibach@gdsys.cc --- Changes in v2: None
board/gdsys/405ep/iocon.c | 214 +++++++++++++++++++++++++++++++++++++++++++++ include/configs/iocon.h | 3 + 2 files changed, 217 insertions(+), 0 deletions(-)
diff --git a/board/gdsys/405ep/iocon.c b/board/gdsys/405ep/iocon.c index 0ab8772..bf84ae8 100644 --- a/board/gdsys/405ep/iocon.c +++ b/board/gdsys/405ep/iocon.c @@ -38,6 +38,8 @@ #include <pca953x.h> #include <pca9698.h>
+#include <miiphy.h> + DECLARE_GLOBAL_DATA_PTR;
#define LATCH0_BASE (CONFIG_SYS_LATCH_BASE) @@ -95,8 +97,16 @@ enum { MCFPGA_RESET_N = 1 << 4, };
+enum { + GPIO_MDC = 1 << 14, + GPIO_MDIO = 1 << 15, +}; + unsigned int mclink_fpgacount;
+static int setup_88e1518(const char *bus, unsigned char addr); +static int verify_88e1518(const char *bus, unsigned char addr); + void fpga_set_reg(unsigned int fpga, u16 reg, u16 data) { int res; @@ -339,6 +349,7 @@ int last_stage_init(void) int slaves; unsigned int k; unsigned char mclink_controllers[] = { 0x24, 0x25, 0x26 }; + int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM;
print_fpga_info(0); osd_probe(0); @@ -360,6 +371,16 @@ int last_stage_init(void) } }
+ if (!legacy) { + miiphy_register(bb_miiphy_buses[0].name, bb_miiphy_read, + bb_miiphy_write); + if (!verify_88e1518(bb_miiphy_buses[0].name, 0)) { + printf("Fixup 88e1518 erratum on %s\n", + bb_miiphy_buses[0].name); + setup_88e1518(bb_miiphy_buses[0].name, 0); + } + } + /* wait for slave-PLLs to be up and running */ udelay(500000);
@@ -375,6 +396,13 @@ int last_stage_init(void) for (k = 1; k <= slaves; ++k) { print_fpga_info(k); osd_probe(k); + 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); + } }
return 0; @@ -446,3 +474,189 @@ int gd405ep_get_fpga_done(unsigned fpga) else return pca9698_get_value(0x20, 20); } + +/* + * FPGA MII bitbang implementation + */ + +struct fpga_mii { + unsigned fpga; + int mdio; +} fpga_mii[] = { + { 0, 1}, + { 1, 1}, + { 2, 1}, + { 3, 1}, +}; + +static int mii_dummy_init(struct bb_miiphy_bus *bus) +{ + return 0; +} + +static int mii_mdio_active(struct bb_miiphy_bus *bus) +{ + struct fpga_mii *fpga_mii = bus->priv; + + if (fpga_mii->mdio) + fpga_set_reg(fpga_mii->fpga, REG(gpio.set), GPIO_MDIO); + else + fpga_set_reg(fpga_mii->fpga, REG(gpio.clear), GPIO_MDIO); + + return 0; +} + +static int mii_mdio_tristate(struct bb_miiphy_bus *bus) +{ + struct fpga_mii *fpga_mii = bus->priv; + + fpga_set_reg(fpga_mii->fpga, REG(gpio.set), GPIO_MDIO); + + return 0; +} + +static int mii_set_mdio(struct bb_miiphy_bus *bus, int v) +{ + struct fpga_mii *fpga_mii = bus->priv; + + if (v) + fpga_set_reg(fpga_mii->fpga, REG(gpio.set), GPIO_MDIO); + else + fpga_set_reg(fpga_mii->fpga, REG(gpio.clear), GPIO_MDIO); + + fpga_mii->mdio = v; + + return 0; +} + +static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v) +{ + struct fpga_mii *fpga_mii = bus->priv; + + *v = ((fpga_get_reg(fpga_mii->fpga, REG(gpio.read)) & GPIO_MDIO) != 0); + + return 0; +} + +static int mii_set_mdc(struct bb_miiphy_bus *bus, int v) +{ + struct fpga_mii *fpga_mii = bus->priv; + + if (v) + fpga_set_reg(fpga_mii->fpga, REG(gpio.set), GPIO_MDC); + else + fpga_set_reg(fpga_mii->fpga, REG(gpio.clear), GPIO_MDC); + + return 0; +} + +static int mii_delay(struct bb_miiphy_bus *bus) +{ + udelay(1); + + return 0; +} + +struct bb_miiphy_bus bb_miiphy_buses[] = { + { + .name = "trans1", + .init = mii_dummy_init, + .mdio_active = mii_mdio_active, + .mdio_tristate = mii_mdio_tristate, + .set_mdio = mii_set_mdio, + .get_mdio = mii_get_mdio, + .set_mdc = mii_set_mdc, + .delay = mii_delay, + .priv = &fpga_mii[0], + }, + { + .name = "trans2", + .init = mii_dummy_init, + .mdio_active = mii_mdio_active, + .mdio_tristate = mii_mdio_tristate, + .set_mdio = mii_set_mdio, + .get_mdio = mii_get_mdio, + .set_mdc = mii_set_mdc, + .delay = mii_delay, + .priv = &fpga_mii[1], + }, + { + .name = "trans3", + .init = mii_dummy_init, + .mdio_active = mii_mdio_active, + .mdio_tristate = mii_mdio_tristate, + .set_mdio = mii_set_mdio, + .get_mdio = mii_get_mdio, + .set_mdc = mii_set_mdc, + .delay = mii_delay, + .priv = &fpga_mii[2], + }, + { + .name = "trans4", + .init = mii_dummy_init, + .mdio_active = mii_mdio_active, + .mdio_tristate = mii_mdio_tristate, + .set_mdio = mii_set_mdio, + .get_mdio = mii_get_mdio, + .set_mdc = mii_set_mdc, + .delay = mii_delay, + .priv = &fpga_mii[3], + }, +}; + +int bb_miiphy_buses_num = sizeof(bb_miiphy_buses) / + sizeof(bb_miiphy_buses[0]); + +/* + * Workaround for erratum mentioned in 88E1518 release notes + */ + +static int verify_88e1518(const char *bus, unsigned char addr) +{ + u16 phy_id1, phy_id2; + + 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; + } + + if ((phy_id1 != 0x0141) || ((phy_id2 & 0xfff0) != 0x0dd0)) + return -EINVAL; + + return 0; +} + +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) +{ + 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; + } + } + + return 0; +} diff --git a/include/configs/iocon.h b/include/configs/iocon.h index 921ac05..d5f48d3 100644 --- a/include/configs/iocon.h +++ b/include/configs/iocon.h @@ -295,4 +295,7 @@ int fpga_gpio_get(unsigned int bus, int pin); #define CONFIG_SYS_CH7301 #define CONFIG_SYS_OSD_SCREENS 1
+#define CONFIG_BITBANGMII /* bit-bang MII PHY management */ +#define CONFIG_BITBANGMII_MULTI + #endif /* __CONFIG_H */