/* * Power up the specified port and reset PHY */ static int mv88361xx_powerup(struct mv88e61xx_config *swconfig, u32 prt) { char *name = swconfig->name; /* Write Copper Specific control reg1 (0x14) for- * Enable Phy power up * Energy Detect on (sense&Xmit NLP Periodically * reset other settings default */ WR_PHY(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_DATA, 0x3360); WR_PHY(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_CMD, (0x9410 | (prt << 5))); if (mv88e61xx_busychk(name)) return -1; /* Write PHY ctrl reg (0x0) to apply * Phy reset (set bit 15 low) * reset other default values */ WR_PHY(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_DATA, 0x1140); WR_PHY(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_CMD, (0x9400 | (prt << 5))); if (mv88e61xx_busychk(name)) return -1; return 0; }
/* * Default Setup for LED[0]_Control (ref: Table 46 Datasheet-3) * is set to "On-1000Mb/s Link, Off Else" * This function sets it to "On-Link, Blink-Activity, Off-NoLink" * * This is optional settings may be needed on some boards * to setup PHY LEDs default configuration to detect 10/100/1000Mb/s * Link status */ static int mv88361xx_led_init(struct mv88e61xx_config *swconfig, u32 prt) { char *name = swconfig->name; u16 reg; if (swconfig->led_init != MV88E61XX_LED_INIT_EN) return 0; /* set page address to 3 */ reg = 3; WR_PHY(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_DATA, reg); WR_PHY(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_CMD, (1 << MV88E61XX_BUSY_OFST | 1 << MV88E61XX_MODE_OFST | 1 << MV88E61XX_OP_OFST | prt << MV88E61XX_ADDR_OFST | 22)); if (mv88e61xx_busychk(name)) return -1; /* set LED Func Ctrl reg */ reg = 1; /* LED[0] On-Link, Blink-Activity, Off-NoLink */ WR_PHY(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_DATA, reg); WR_PHY(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_CMD, (1 << MV88E61XX_BUSY_OFST | 1 << MV88E61XX_MODE_OFST | 1 << MV88E61XX_OP_OFST | prt << MV88E61XX_ADDR_OFST | 16)); if (mv88e61xx_busychk(name)) return -1; /* set page address to 0 */ reg = 0; WR_PHY(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_DATA, reg); WR_PHY(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_CMD, (1 << MV88E61XX_BUSY_OFST | 1 << MV88E61XX_MODE_OFST | 1 << MV88E61XX_OP_OFST | prt << MV88E61XX_ADDR_OFST | 22)); if (mv88e61xx_busychk(name)) return -1; return 0; }
static inline int mv88e61xx_switch_miiphy_write(char *name, u32 phy, u32 reg, u16 data) { /* write switch data reg then cmd reg then check completion */ wr_switch_reg(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_DATA, data); wr_switch_reg(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_CMD, (MV88E61XX_PHY_WRITE_CMD | (phy << 5) | reg)); return mv88e61xx_busychk(name); }
static inline int mv88e61xx_switch_miiphy_read(char *name, u32 phy, u32 reg, u16 *data) { /* write switch cmd reg, check for completion */ wr_switch_reg(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_CMD, (MV88E61XX_PHY_READ_CMD | (phy << 5) | reg)); if (mv88e61xx_busychk(name)) return -1; /* read switch data reg and return success */ rd_switch_reg(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_DATA, data); return 0; }
/* * Reverse Transmit polarity for Media Dependent Interface * Pins (MDIP) bits in Copper Specific Control Register 3 * (Page 0, Reg 20 for each phy (except cpu port) * Reference: Section 1.1 Switch datasheet-3 * * This is optional settings may be needed on some boards * for PHY<->magnetics h/w tuning */ static int mv88361xx_reverse_mdipn(struct mv88e61xx_config *swconfig, u32 prt) { char *name = swconfig->name; u16 reg; if (swconfig->mdip != MV88E61XX_MDIP_REVERSE) return 0; reg = 0x0f; /*Reverse MDIP/N[3:0] bits */ WR_PHY(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_DATA, reg); WR_PHY(name, MV88E61XX_GLB2REG_DEVADR, MV88E61XX_PHY_CMD, (1 << MV88E61XX_BUSY_OFST | 1 << MV88E61XX_MODE_OFST | 1 << MV88E61XX_OP_OFST | prt << MV88E61XX_ADDR_OFST | 20)); if (mv88e61xx_busychk(name)) return -1; return 0; }