1352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger/* $Date: 2005/10/24 23:18:13 $ $RCSfile: mv88e1xxx.c,v $ $Revision: 1.49 $ */ 2352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger#include "common.h" 3352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger#include "mv88e1xxx.h" 4352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger#include "cphy.h" 5352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger#include "elmer0.h" 6352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 7352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger/* MV88E1XXX MDI crossover register values */ 8352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger#define CROSSOVER_MDI 0 9352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger#define CROSSOVER_MDIX 1 10352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger#define CROSSOVER_AUTO 3 11352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 12352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger#define INTR_ENABLE_MASK 0x6CA0 13352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 14352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger/* 15352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * Set the bits given by 'bitval' in PHY register 'reg'. 16352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger */ 17352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic void mdio_set_bit(struct cphy *cphy, int reg, u32 bitval) 18352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 19352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 val; 20352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 21352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_read(cphy, reg, &val); 22352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_write(cphy, reg, val | bitval); 23352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 24352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 25352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger/* 26352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * Clear the bits given by 'bitval' in PHY register 'reg'. 27352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger */ 28352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic void mdio_clear_bit(struct cphy *cphy, int reg, u32 bitval) 29352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 30352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 val; 31352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 32352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_read(cphy, reg, &val); 33352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_write(cphy, reg, val & ~bitval); 34352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 35352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 36352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger/* 37352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * NAME: phy_reset 38352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * 39352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * DESC: Reset the given PHY's port. NOTE: This is not a global 40352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * chip reset. 41352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * 42352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * PARAMS: cphy - Pointer to PHY instance data. 43352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * 4425985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * RETURN: 0 - Successful reset. 45352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * -1 - Timeout. 46352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger */ 47352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_reset(struct cphy *cphy, int wait) 48352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 49352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 ctl; 50352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger int time_out = 1000; 51352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 52352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger mdio_set_bit(cphy, MII_BMCR, BMCR_RESET); 53352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 54352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger do { 55352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_read(cphy, MII_BMCR, &ctl); 56352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger ctl &= BMCR_RESET; 57352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (ctl) 58352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger udelay(1); 59352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger } while (ctl && --time_out); 60352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 61352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return ctl ? -1 : 0; 62352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 63352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 64352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_interrupt_enable(struct cphy *cphy) 65352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 66352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger /* Enable PHY interrupts. */ 67352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_write(cphy, MV88E1XXX_INTERRUPT_ENABLE_REGISTER, 68352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger INTR_ENABLE_MASK); 69352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 70352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger /* Enable Marvell interrupts through Elmer0. */ 71352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (t1_is_asic(cphy->adapter)) { 72352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 elmer; 73352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 74352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer); 75352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger elmer |= ELMER0_GP_BIT1; 76356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu if (is_T2(cphy->adapter)) 77356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu elmer |= ELMER0_GP_BIT2 | ELMER0_GP_BIT3 | ELMER0_GP_BIT4; 78352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer); 79352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger } 80352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return 0; 81352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 82352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 83352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_interrupt_disable(struct cphy *cphy) 84352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 85352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger /* Disable all phy interrupts. */ 86352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_write(cphy, MV88E1XXX_INTERRUPT_ENABLE_REGISTER, 0); 87352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 88352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger /* Disable Marvell interrupts through Elmer0. */ 89352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (t1_is_asic(cphy->adapter)) { 90352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 elmer; 91352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 92352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger t1_tpi_read(cphy->adapter, A_ELMER0_INT_ENABLE, &elmer); 93352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger elmer &= ~ELMER0_GP_BIT1; 94356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu if (is_T2(cphy->adapter)) 95352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger elmer &= ~(ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4); 96352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger t1_tpi_write(cphy->adapter, A_ELMER0_INT_ENABLE, elmer); 97352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger } 98352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return 0; 99352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 100352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 101352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_interrupt_clear(struct cphy *cphy) 102352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 103352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 elmer; 104352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 105352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger /* Clear PHY interrupts by reading the register. */ 106352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_read(cphy, 107352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger MV88E1XXX_INTERRUPT_STATUS_REGISTER, &elmer); 108352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 109352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger /* Clear Marvell interrupts through Elmer0. */ 110352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (t1_is_asic(cphy->adapter)) { 111352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer); 112352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger elmer |= ELMER0_GP_BIT1; 113356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu if (is_T2(cphy->adapter)) 114352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger elmer |= ELMER0_GP_BIT2|ELMER0_GP_BIT3|ELMER0_GP_BIT4; 115352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer); 116352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger } 117352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return 0; 118352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 119352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 120352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger/* 121352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * Set the PHY speed and duplex. This also disables auto-negotiation, except 122352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * for 1Gb/s, where auto-negotiation is mandatory. 123352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger */ 124352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_set_speed_duplex(struct cphy *phy, int speed, int duplex) 125352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 126352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 ctl; 127352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 128352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_read(phy, MII_BMCR, &ctl); 129352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (speed >= 0) { 130352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger ctl &= ~(BMCR_SPEED100 | BMCR_SPEED1000 | BMCR_ANENABLE); 131352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (speed == SPEED_100) 132352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger ctl |= BMCR_SPEED100; 133352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger else if (speed == SPEED_1000) 134352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger ctl |= BMCR_SPEED1000; 135352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger } 136352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (duplex >= 0) { 137352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger ctl &= ~(BMCR_FULLDPLX | BMCR_ANENABLE); 138352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (duplex == DUPLEX_FULL) 139352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger ctl |= BMCR_FULLDPLX; 140352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger } 141352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (ctl & BMCR_SPEED1000) /* auto-negotiation required for 1Gb/s */ 142352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger ctl |= BMCR_ANENABLE; 143352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_write(phy, MII_BMCR, ctl); 144352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return 0; 145352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 146352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 147352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_crossover_set(struct cphy *cphy, int crossover) 148352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 149352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 data32; 150352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 151352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_read(cphy, 152352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger MV88E1XXX_SPECIFIC_CNTRL_REGISTER, &data32); 153352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger data32 &= ~V_PSCR_MDI_XOVER_MODE(M_PSCR_MDI_XOVER_MODE); 154352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger data32 |= V_PSCR_MDI_XOVER_MODE(crossover); 155352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_write(cphy, 156352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger MV88E1XXX_SPECIFIC_CNTRL_REGISTER, data32); 157352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return 0; 158352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 159352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 160352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_autoneg_enable(struct cphy *cphy) 161352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 162352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 ctl; 163352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 164352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) mv88e1xxx_crossover_set(cphy, CROSSOVER_AUTO); 165352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 166352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_read(cphy, MII_BMCR, &ctl); 167352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger /* restart autoneg for change to take effect */ 168352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger ctl |= BMCR_ANENABLE | BMCR_ANRESTART; 169352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_write(cphy, MII_BMCR, ctl); 170352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return 0; 171352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 172352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 173352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_autoneg_disable(struct cphy *cphy) 174352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 175352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 ctl; 176352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 177352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger /* 178352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * Crossover *must* be set to manual in order to disable auto-neg. 179352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * The Alaska FAQs document highlights this point. 180352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger */ 181352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) mv88e1xxx_crossover_set(cphy, CROSSOVER_MDI); 182352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 183352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger /* 184352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * Must include autoneg reset when disabling auto-neg. This 185352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * is described in the Alaska FAQ document. 186352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger */ 187352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_read(cphy, MII_BMCR, &ctl); 188352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger ctl &= ~BMCR_ANENABLE; 189352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_write(cphy, MII_BMCR, ctl | BMCR_ANRESTART); 190352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return 0; 191352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 192352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 193352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_autoneg_restart(struct cphy *cphy) 194352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 195352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger mdio_set_bit(cphy, MII_BMCR, BMCR_ANRESTART); 196352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return 0; 197352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 198352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 199352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_advertise(struct cphy *phy, unsigned int advertise_map) 200352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 201352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 val = 0; 202352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 203352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (advertise_map & 204352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full)) { 205352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_read(phy, MII_GBCR, &val); 206352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger val &= ~(GBCR_ADV_1000HALF | GBCR_ADV_1000FULL); 207352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (advertise_map & ADVERTISED_1000baseT_Half) 208352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger val |= GBCR_ADV_1000HALF; 209352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (advertise_map & ADVERTISED_1000baseT_Full) 210352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger val |= GBCR_ADV_1000FULL; 211352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger } 212352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_write(phy, MII_GBCR, val); 213352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 214352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger val = 1; 215352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (advertise_map & ADVERTISED_10baseT_Half) 216352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger val |= ADVERTISE_10HALF; 217352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (advertise_map & ADVERTISED_10baseT_Full) 218352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger val |= ADVERTISE_10FULL; 219352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (advertise_map & ADVERTISED_100baseT_Half) 220352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger val |= ADVERTISE_100HALF; 221352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (advertise_map & ADVERTISED_100baseT_Full) 222352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger val |= ADVERTISE_100FULL; 223352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (advertise_map & ADVERTISED_PAUSE) 224352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger val |= ADVERTISE_PAUSE; 225352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (advertise_map & ADVERTISED_ASYM_PAUSE) 226352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger val |= ADVERTISE_PAUSE_ASYM; 227352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_write(phy, MII_ADVERTISE, val); 228352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return 0; 229352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 230352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 231352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_set_loopback(struct cphy *cphy, int on) 232352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 233352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (on) 234352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger mdio_set_bit(cphy, MII_BMCR, BMCR_LOOPBACK); 235352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger else 236352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger mdio_clear_bit(cphy, MII_BMCR, BMCR_LOOPBACK); 237352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return 0; 238352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 239352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 240352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_get_link_status(struct cphy *cphy, int *link_ok, 241352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger int *speed, int *duplex, int *fc) 242352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 243352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 status; 244352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger int sp = -1, dplx = -1, pause = 0; 245352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 246352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_read(cphy, 247352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger MV88E1XXX_SPECIFIC_STATUS_REGISTER, &status); 248352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if ((status & V_PSSR_STATUS_RESOLVED) != 0) { 249352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (status & V_PSSR_RX_PAUSE) 250352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger pause |= PAUSE_RX; 251352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (status & V_PSSR_TX_PAUSE) 252352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger pause |= PAUSE_TX; 253352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger dplx = (status & V_PSSR_DUPLEX) ? DUPLEX_FULL : DUPLEX_HALF; 254352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger sp = G_PSSR_SPEED(status); 255352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (sp == 0) 256352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger sp = SPEED_10; 257352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger else if (sp == 1) 258352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger sp = SPEED_100; 259352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger else 260352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger sp = SPEED_1000; 261352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger } 262352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (link_ok) 263352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger *link_ok = (status & V_PSSR_LINK) != 0; 264352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (speed) 265352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger *speed = sp; 266352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (duplex) 267352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger *duplex = dplx; 268352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (fc) 269352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger *fc = pause; 270352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return 0; 271352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 272352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 273352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_downshift_set(struct cphy *cphy, int downshift_enable) 274352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 275352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 val; 276352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 277352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_read(cphy, 278352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger MV88E1XXX_EXT_PHY_SPECIFIC_CNTRL_REGISTER, &val); 279352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 280352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger /* 281352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * Set the downshift counter to 2 so we try to establish Gb link 282352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * twice before downshifting. 283352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger */ 284352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger val &= ~(V_DOWNSHIFT_ENABLE | V_DOWNSHIFT_CNT(M_DOWNSHIFT_CNT)); 285352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 286352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (downshift_enable) 287352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger val |= V_DOWNSHIFT_ENABLE | V_DOWNSHIFT_CNT(2); 288352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_write(cphy, 289352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger MV88E1XXX_EXT_PHY_SPECIFIC_CNTRL_REGISTER, val); 290352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return 0; 291352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 292352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 293352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_interrupt_handler(struct cphy *cphy) 294352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 295352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger int cphy_cause = 0; 296352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 status; 297352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 298352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger /* 299352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * Loop until cause reads zero. Need to handle bouncing interrupts. 300356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu */ 301352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger while (1) { 302352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger u32 cause; 303352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 304352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_read(cphy, 305352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger MV88E1XXX_INTERRUPT_STATUS_REGISTER, 306352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger &cause); 307352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger cause &= INTR_ENABLE_MASK; 308c697f83e8c880a1e69fb2a45a6e4aa0670e10602Francois Romieu if (!cause) 309c697f83e8c880a1e69fb2a45a6e4aa0670e10602Francois Romieu break; 310352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 311352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (cause & MV88E1XXX_INTR_LINK_CHNG) { 312352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_read(cphy, 313352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger MV88E1XXX_SPECIFIC_STATUS_REGISTER, &status); 314352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 315d7487421b629c5ca71ce23b10461ef0c3ad2c741Francois Romieu if (status & MV88E1XXX_INTR_LINK_CHNG) 316352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger cphy->state |= PHY_LINK_UP; 317d7487421b629c5ca71ce23b10461ef0c3ad2c741Francois Romieu else { 318352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger cphy->state &= ~PHY_LINK_UP; 319352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (cphy->state & PHY_AUTONEG_EN) 320352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger cphy->state &= ~PHY_AUTONEG_RDY; 321352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger cphy_cause |= cphy_cause_link_change; 322352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger } 323352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger } 324352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 325352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (cause & MV88E1XXX_INTR_AUTONEG_DONE) 326352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger cphy->state |= PHY_AUTONEG_RDY; 327352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 328352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if ((cphy->state & (PHY_LINK_UP | PHY_AUTONEG_RDY)) == 329352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (PHY_LINK_UP | PHY_AUTONEG_RDY)) 330352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger cphy_cause |= cphy_cause_link_change; 331352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger } 332352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return cphy_cause; 333352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 334352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 335352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic void mv88e1xxx_destroy(struct cphy *cphy) 336352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 337352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger kfree(cphy); 338352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 339352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 340352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic struct cphy_ops mv88e1xxx_ops = { 341352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger .destroy = mv88e1xxx_destroy, 342352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger .reset = mv88e1xxx_reset, 343352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger .interrupt_enable = mv88e1xxx_interrupt_enable, 344352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger .interrupt_disable = mv88e1xxx_interrupt_disable, 345352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger .interrupt_clear = mv88e1xxx_interrupt_clear, 346352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger .interrupt_handler = mv88e1xxx_interrupt_handler, 347352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger .autoneg_enable = mv88e1xxx_autoneg_enable, 348352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger .autoneg_disable = mv88e1xxx_autoneg_disable, 349352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger .autoneg_restart = mv88e1xxx_autoneg_restart, 350352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger .advertise = mv88e1xxx_advertise, 351352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger .set_loopback = mv88e1xxx_set_loopback, 352352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger .set_speed_duplex = mv88e1xxx_set_speed_duplex, 353352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger .get_link_status = mv88e1xxx_get_link_status, 354352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger}; 355352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 356703cebabd173a7fe533d6f21df0347b1f2a9a1e1Divy Le Raystatic struct cphy *mv88e1xxx_phy_create(struct net_device *dev, int phy_addr, 357459e536b1ddfd217ec8a3437a3214968a98223c7Stephen Hemminger const struct mdio_ops *mdio_ops) 358352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 359703cebabd173a7fe533d6f21df0347b1f2a9a1e1Divy Le Ray struct adapter *adapter = netdev_priv(dev); 360352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL); 361352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 362c697f83e8c880a1e69fb2a45a6e4aa0670e10602Francois Romieu if (!cphy) 363c697f83e8c880a1e69fb2a45a6e4aa0670e10602Francois Romieu return NULL; 364352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 365703cebabd173a7fe533d6f21df0347b1f2a9a1e1Divy Le Ray cphy_init(cphy, dev, phy_addr, &mv88e1xxx_ops, mdio_ops); 366352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 367352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger /* Configure particular PHY's to run in a different mode. */ 368352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if ((board_info(adapter)->caps & SUPPORTED_TP) && 369352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger board_info(adapter)->chip_phy == CHBT_PHY_88E1111) { 370352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger /* 371352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger * Configure the PHY transmitter as class A to reduce EMI. 372352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger */ 373352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_write(cphy, 374352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger MV88E1XXX_EXTENDED_ADDR_REGISTER, 0xB); 375352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_write(cphy, 376352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger MV88E1XXX_EXTENDED_REGISTER, 0x8004); 377352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger } 378352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) mv88e1xxx_downshift_set(cphy, 1); /* Enable downshift */ 379352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 380356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu /* LED */ 381352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger if (is_T2(adapter)) { 382352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger (void) simple_mdio_write(cphy, 383352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger MV88E1XXX_LED_CONTROL_REGISTER, 0x1); 384356bd1460d1e1c4e433e4114fdac02139bddf17cFrancois Romieu } 385352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 386352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return cphy; 387352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 388352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 389352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemmingerstatic int mv88e1xxx_phy_reset(adapter_t* adapter) 390352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger{ 391352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger return 0; 392352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger} 393352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger 394459e536b1ddfd217ec8a3437a3214968a98223c7Stephen Hemmingerconst struct gphy t1_mv88e1xxx_ops = { 395459e536b1ddfd217ec8a3437a3214968a98223c7Stephen Hemminger .create = mv88e1xxx_phy_create, 396459e536b1ddfd217ec8a3437a3214968a98223c7Stephen Hemminger .reset = mv88e1xxx_phy_reset 397352c417ddb593de757f0ee1fa490cb5444778c41Stephen Hemminger}; 398