|
@@ -7,6 +7,7 @@
|
|
|
|
|
|
#include <common.h>
|
|
|
#include <command.h>
|
|
|
+#include <errno.h>
|
|
|
#include <asm/processor.h>
|
|
|
#include <asm/io.h>
|
|
|
#include <asm/ppc4xx-gpio.h>
|
|
@@ -15,6 +16,15 @@
|
|
|
#include <gdsys_fpga.h>
|
|
|
|
|
|
#include "../common/osd.h"
|
|
|
+#include "../common/mclink.h"
|
|
|
+
|
|
|
+#include <i2c.h>
|
|
|
+#include <pca953x.h>
|
|
|
+#include <pca9698.h>
|
|
|
+
|
|
|
+#include <miiphy.h>
|
|
|
+
|
|
|
+DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
|
|
#define LATCH0_BASE (CONFIG_SYS_LATCH_BASE)
|
|
|
#define LATCH1_BASE (CONFIG_SYS_LATCH_BASE + 0x100)
|
|
@@ -31,11 +41,20 @@ enum {
|
|
|
HWVER_100 = 0,
|
|
|
HWVER_104 = 1,
|
|
|
HWVER_110 = 2,
|
|
|
+ HWVER_120 = 3,
|
|
|
+ HWVER_200 = 4,
|
|
|
+ HWVER_210 = 5,
|
|
|
+};
|
|
|
+
|
|
|
+enum {
|
|
|
+ FPGA_HWVER_200 = 0,
|
|
|
+ FPGA_HWVER_210 = 1,
|
|
|
};
|
|
|
|
|
|
enum {
|
|
|
COMPRESSION_NONE = 0,
|
|
|
- COMPRESSION_TYPE1_DELTA,
|
|
|
+ COMPRESSION_TYPE1_DELTA = 1,
|
|
|
+ COMPRESSION_TYPE1_TYPE2_DELTA = 3,
|
|
|
};
|
|
|
|
|
|
enum {
|
|
@@ -51,10 +70,71 @@ enum {
|
|
|
|
|
|
enum {
|
|
|
RAM_DDR2_32 = 0,
|
|
|
+ RAM_DDR3_32 = 1,
|
|
|
+};
|
|
|
+
|
|
|
+enum {
|
|
|
+ MCFPGA_DONE = 1 << 0,
|
|
|
+ MCFPGA_INIT_N = 1 << 1,
|
|
|
+ MCFPGA_PROGRAM_N = 1 << 2,
|
|
|
+ MCFPGA_UPDATE_ENABLE_N = 1 << 3,
|
|
|
+ MCFPGA_RESET_N = 1 << 4,
|
|
|
+};
|
|
|
+
|
|
|
+enum {
|
|
|
+ GPIO_MDC = 1 << 14,
|
|
|
+ GPIO_MDIO = 1 << 15,
|
|
|
};
|
|
|
|
|
|
+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)
|
|
|
+{
|
|
|
+ int res;
|
|
|
+
|
|
|
+ switch (fpga) {
|
|
|
+ case 0:
|
|
|
+ out_le16(reg, data);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ res = mclink_send(fpga - 1, regoff, data);
|
|
|
+ if (res < 0) {
|
|
|
+ printf("mclink_send reg %02lx data %04x returned %d\n",
|
|
|
+ regoff, data, res);
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int fpga_get_reg(u32 fpga, u16 *reg, off_t regoff, u16 *data)
|
|
|
+{
|
|
|
+ int res;
|
|
|
+
|
|
|
+ switch (fpga) {
|
|
|
+ case 0:
|
|
|
+ *data = in_le16(reg);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ if (fpga > mclink_fpgacount)
|
|
|
+ return -EINVAL;
|
|
|
+ res = mclink_receive(fpga - 1, regoff, data);
|
|
|
+ if (res < 0) {
|
|
|
+ printf("mclink_receive reg %02lx returned %d\n",
|
|
|
+ regoff, res);
|
|
|
+ return res;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Check Board Identity:
|
|
|
*/
|
|
@@ -76,7 +156,7 @@ int checkboard(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void print_fpga_info(void)
|
|
|
+static void print_fpga_info(unsigned int fpga)
|
|
|
{
|
|
|
u16 versions;
|
|
|
u16 fpga_version;
|
|
@@ -90,13 +170,13 @@ static void print_fpga_info(void)
|
|
|
unsigned feature_ramconfig;
|
|
|
unsigned feature_carriers;
|
|
|
unsigned feature_video_channels;
|
|
|
+ int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM;
|
|
|
|
|
|
FPGA_GET_REG(0, versions, &versions);
|
|
|
FPGA_GET_REG(0, fpga_version, &fpga_version);
|
|
|
FPGA_GET_REG(0, fpga_features, &fpga_features);
|
|
|
|
|
|
unit_type = (versions & 0xf000) >> 12;
|
|
|
- hardware_version = versions & 0x000f;
|
|
|
feature_compression = (fpga_features & 0xe000) >> 13;
|
|
|
feature_osd = fpga_features & (1<<11);
|
|
|
feature_audio = (fpga_features & 0x0600) >> 9;
|
|
@@ -105,6 +185,9 @@ static void print_fpga_info(void)
|
|
|
feature_carriers = (fpga_features & 0x000c) >> 2;
|
|
|
feature_video_channels = fpga_features & 0x0003;
|
|
|
|
|
|
+ if (legacy)
|
|
|
+ printf("legacy ");
|
|
|
+
|
|
|
switch (unit_type) {
|
|
|
case UNITTYPE_MAIN_USER:
|
|
|
printf("Mainchannel");
|
|
@@ -119,27 +202,68 @@ static void print_fpga_info(void)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- switch (hardware_version) {
|
|
|
- case HWVER_100:
|
|
|
- printf(" HW-Ver 1.00\n");
|
|
|
- break;
|
|
|
-
|
|
|
- case HWVER_104:
|
|
|
- printf(" HW-Ver 1.04\n");
|
|
|
- break;
|
|
|
-
|
|
|
- case HWVER_110:
|
|
|
- printf(" HW-Ver 1.10\n");
|
|
|
- break;
|
|
|
+ if (unit_type == UNITTYPE_MAIN_USER) {
|
|
|
+ if (legacy)
|
|
|
+ hardware_version =
|
|
|
+ (in_le16((void *)LATCH2_BASE)>>8) & 0x0f;
|
|
|
+ else
|
|
|
+ hardware_version =
|
|
|
+ (!!pca9698_get_value(0x20, 24) << 0)
|
|
|
+ | (!!pca9698_get_value(0x20, 25) << 1)
|
|
|
+ | (!!pca9698_get_value(0x20, 26) << 2)
|
|
|
+ | (!!pca9698_get_value(0x20, 27) << 3);
|
|
|
+ switch (hardware_version) {
|
|
|
+ case HWVER_100:
|
|
|
+ printf(" HW-Ver 1.00,");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case HWVER_104:
|
|
|
+ printf(" HW-Ver 1.04,");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case HWVER_110:
|
|
|
+ printf(" HW-Ver 1.10,");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case HWVER_120:
|
|
|
+ printf(" HW-Ver 1.20-1.21,");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case HWVER_200:
|
|
|
+ printf(" HW-Ver 2.00,");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case HWVER_210:
|
|
|
+ printf(" HW-Ver 2.10,");
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ printf(" HW-Ver %d(not supported),",
|
|
|
+ hardware_version);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- default:
|
|
|
- printf(" HW-Ver %d(not supported)\n",
|
|
|
- hardware_version);
|
|
|
- break;
|
|
|
+ if (unit_type == UNITTYPE_VIDEO_USER) {
|
|
|
+ hardware_version = versions & 0x000f;
|
|
|
+ switch (hardware_version) {
|
|
|
+ case FPGA_HWVER_200:
|
|
|
+ printf(" HW-Ver 2.00,");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case FPGA_HWVER_210:
|
|
|
+ printf(" HW-Ver 2.10,");
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ printf(" HW-Ver %d(not supported),",
|
|
|
+ hardware_version);
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- printf(" FPGA V %d.%02d, features:",
|
|
|
- fpga_version / 100, fpga_version % 100);
|
|
|
+ printf(" FPGA V %d.%02d\n features:",
|
|
|
+ fpga_version / 100, fpga_version % 100);
|
|
|
|
|
|
|
|
|
switch (feature_compression) {
|
|
@@ -151,6 +275,10 @@ static void print_fpga_info(void)
|
|
|
printf(" type1-deltacompression");
|
|
|
break;
|
|
|
|
|
|
+ case COMPRESSION_TYPE1_TYPE2_DELTA:
|
|
|
+ printf(" type1-deltacompression, type2-inlinecompression");
|
|
|
+ break;
|
|
|
+
|
|
|
default:
|
|
|
printf(" compression %d(not supported)", feature_compression);
|
|
|
break;
|
|
@@ -197,6 +325,10 @@ static void print_fpga_info(void)
|
|
|
printf(", RAM 32 bit DDR2");
|
|
|
break;
|
|
|
|
|
|
+ case RAM_DDR3_32:
|
|
|
+ printf(", RAM 32 bit DDR3");
|
|
|
+ break;
|
|
|
+
|
|
|
default:
|
|
|
printf(", RAM %d(not supported)", feature_ramconfig);
|
|
|
break;
|
|
@@ -209,46 +341,117 @@ static void print_fpga_info(void)
|
|
|
|
|
|
int last_stage_init(void)
|
|
|
{
|
|
|
- print_fpga_info();
|
|
|
+ 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);
|
|
|
+
|
|
|
+ /* wait for FPGA done */
|
|
|
+ for (k = 0; k < ARRAY_SIZE(mclink_controllers); ++k) {
|
|
|
+ unsigned int ctr = 0;
|
|
|
+
|
|
|
+ if (i2c_probe(mclink_controllers[k]))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ while (!(pca953x_get_val(mclink_controllers[k])
|
|
|
+ & MCFPGA_DONE)) {
|
|
|
+ udelay(100000);
|
|
|
+ if (ctr++ > 5) {
|
|
|
+ printf("no done for mclink_controller %d\n", k);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- return osd_probe(0);
|
|
|
+ /* wait for slave-PLLs to be up and running */
|
|
|
+ udelay(500000);
|
|
|
+
|
|
|
+ mclink_fpgacount = CONFIG_SYS_MCLINK_MAX;
|
|
|
+ slaves = mclink_probe();
|
|
|
+ mclink_fpgacount = 0;
|
|
|
+
|
|
|
+ if (slaves <= 0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ mclink_fpgacount = slaves;
|
|
|
+
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* provide access to fpga gpios (for I2C bitbang)
|
|
|
* (these may look all too simple but make iocon.h much more readable)
|
|
|
*/
|
|
|
-void fpga_gpio_set(int pin)
|
|
|
+void fpga_gpio_set(unsigned int bus, int pin)
|
|
|
{
|
|
|
- FPGA_SET_REG(0, gpio.set, pin);
|
|
|
+ FPGA_SET_REG(bus, gpio.set, pin);
|
|
|
}
|
|
|
|
|
|
-void fpga_gpio_clear(int pin)
|
|
|
+void fpga_gpio_clear(unsigned int bus, int pin)
|
|
|
{
|
|
|
- FPGA_SET_REG(0, gpio.clear, pin);
|
|
|
+ FPGA_SET_REG(bus, gpio.clear, pin);
|
|
|
}
|
|
|
|
|
|
-int fpga_gpio_get(int pin)
|
|
|
+int fpga_gpio_get(unsigned int bus, int pin)
|
|
|
{
|
|
|
u16 val;
|
|
|
|
|
|
- FPGA_GET_REG(0, gpio.read, &val);
|
|
|
+ FPGA_GET_REG(bus, gpio.read, &val);
|
|
|
|
|
|
return val & pin;
|
|
|
}
|
|
|
|
|
|
void gd405ep_init(void)
|
|
|
{
|
|
|
+ unsigned int k;
|
|
|
+
|
|
|
+ if (i2c_probe(0x20)) { /* i2c_probe returns 0 on success */
|
|
|
+ for (k = 0; k < CONFIG_SYS_FPGA_COUNT; ++k)
|
|
|
+ gd->arch.fpga_state[k] |= FPGA_STATE_PLATFORM;
|
|
|
+ } else {
|
|
|
+ pca9698_direction_output(0x20, 4, 1);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void gd405ep_set_fpga_reset(unsigned state)
|
|
|
{
|
|
|
- if (state) {
|
|
|
- out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_RESET);
|
|
|
- out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_RESET);
|
|
|
+ int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM;
|
|
|
+
|
|
|
+ if (legacy) {
|
|
|
+ if (state) {
|
|
|
+ out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_RESET);
|
|
|
+ out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_RESET);
|
|
|
+ } else {
|
|
|
+ out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_BOOT);
|
|
|
+ out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_BOOT);
|
|
|
+ }
|
|
|
} else {
|
|
|
- out_le16((void *)LATCH0_BASE, CONFIG_SYS_LATCH0_BOOT);
|
|
|
- out_le16((void *)LATCH1_BASE, CONFIG_SYS_LATCH1_BOOT);
|
|
|
+ pca9698_set_value(0x20, 4, state ? 0 : 1);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -263,5 +466,200 @@ void gd405ep_setup_hw(void)
|
|
|
|
|
|
int gd405ep_get_fpga_done(unsigned fpga)
|
|
|
{
|
|
|
- return in_le16((void *)LATCH2_BASE) & CONFIG_SYS_FPGA_DONE(fpga);
|
|
|
+ int legacy = get_fpga_state(0) & FPGA_STATE_PLATFORM;
|
|
|
+
|
|
|
+ if (legacy)
|
|
|
+ return in_le16((void *)LATCH2_BASE)
|
|
|
+ & CONFIG_SYS_FPGA_DONE(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, gpio.set, GPIO_MDIO);
|
|
|
+ else
|
|
|
+ FPGA_SET_REG(fpga_mii->fpga, 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, 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, gpio.set, GPIO_MDIO);
|
|
|
+ else
|
|
|
+ FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
|
|
|
+
|
|
|
+ fpga_mii->mdio = v;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
|
|
|
+{
|
|
|
+ u16 gpio;
|
|
|
+ struct fpga_mii *fpga_mii = bus->priv;
|
|
|
+
|
|
|
+ FPGA_GET_REG(fpga_mii->fpga, gpio.read, &gpio);
|
|
|
+
|
|
|
+ *v = ((gpio & 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, gpio.set, GPIO_MDC);
|
|
|
+ else
|
|
|
+ FPGA_SET_REG(fpga_mii->fpga, 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;
|
|
|
}
|