1 /* $Date: 2005/11/12 02:13:49 $ $RCSfile: my3126.c,v $ $Revision: 1.15 $ */ 2 #include "cphy.h" 3 #include "elmer0.h" 4 #include "suni1x10gexp_regs.h" 5 6 /* Port Reset */ 7 static int my3126_reset(struct cphy *cphy, int wait) 8 { 9 /* 10 * This can be done through registers. It is not required since 11 * a full chip reset is used. 12 */ 13 return 0; 14 } 15 16 static int my3126_interrupt_enable(struct cphy *cphy) 17 { 18 schedule_delayed_work(&cphy->phy_update, HZ/30); 19 t1_tpi_read(cphy->adapter, A_ELMER0_GPO, &cphy->elmer_gpo); 20 return 0; 21 } 22 23 static int my3126_interrupt_disable(struct cphy *cphy) 24 { 25 cancel_delayed_work_sync(&cphy->phy_update); 26 return 0; 27 } 28 29 static int my3126_interrupt_clear(struct cphy *cphy) 30 { 31 return 0; 32 } 33 34 #define OFFSET(REG_ADDR) (REG_ADDR << 2) 35 36 static int my3126_interrupt_handler(struct cphy *cphy) 37 { 38 u32 val; 39 u16 val16; 40 u16 status; 41 u32 act_count; 42 adapter_t *adapter; 43 adapter = cphy->adapter; 44 45 if (cphy->count == 50) { 46 cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); 47 val16 = (u16) val; 48 status = cphy->bmsr ^ val16; 49 50 if (status & MDIO_STAT1_LSTATUS) 51 t1_link_changed(adapter, 0); 52 cphy->bmsr = val16; 53 54 /* We have only enabled link change interrupts so it 55 must be that 56 */ 57 cphy->count = 0; 58 } 59 60 t1_tpi_write(adapter, OFFSET(SUNI1x10GEXP_REG_MSTAT_CONTROL), 61 SUNI1x10GEXP_BITMSK_MSTAT_SNAP); 62 t1_tpi_read(adapter, 63 OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW), &act_count); 64 t1_tpi_read(adapter, 65 OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW), &val); 66 act_count += val; 67 68 /* Populate elmer_gpo with the register value */ 69 t1_tpi_read(adapter, A_ELMER0_GPO, &val); 70 cphy->elmer_gpo = val; 71 72 if ( (val & (1 << 8)) || (val & (1 << 19)) || 73 (cphy->act_count == act_count) || cphy->act_on ) { 74 if (is_T2(adapter)) 75 val |= (1 << 9); 76 else if (t1_is_T1B(adapter)) 77 val |= (1 << 20); 78 cphy->act_on = 0; 79 } else { 80 if (is_T2(adapter)) 81 val &= ~(1 << 9); 82 else if (t1_is_T1B(adapter)) 83 val &= ~(1 << 20); 84 cphy->act_on = 1; 85 } 86 87 t1_tpi_write(adapter, A_ELMER0_GPO, val); 88 89 cphy->elmer_gpo = val; 90 cphy->act_count = act_count; 91 cphy->count++; 92 93 return cphy_cause_link_change; 94 } 95 96 static void my3216_poll(struct work_struct *work) 97 { 98 struct cphy *cphy = container_of(work, struct cphy, phy_update.work); 99 100 my3126_interrupt_handler(cphy); 101 } 102 103 static int my3126_set_loopback(struct cphy *cphy, int on) 104 { 105 return 0; 106 } 107 108 /* To check the activity LED */ 109 static int my3126_get_link_status(struct cphy *cphy, 110 int *link_ok, int *speed, int *duplex, int *fc) 111 { 112 u32 val; 113 u16 val16; 114 adapter_t *adapter; 115 116 adapter = cphy->adapter; 117 cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); 118 val16 = (u16) val; 119 120 /* Populate elmer_gpo with the register value */ 121 t1_tpi_read(adapter, A_ELMER0_GPO, &val); 122 cphy->elmer_gpo = val; 123 124 *link_ok = (val16 & MDIO_STAT1_LSTATUS); 125 126 if (*link_ok) { 127 /* Turn on the LED. */ 128 if (is_T2(adapter)) 129 val &= ~(1 << 8); 130 else if (t1_is_T1B(adapter)) 131 val &= ~(1 << 19); 132 } else { 133 /* Turn off the LED. */ 134 if (is_T2(adapter)) 135 val |= (1 << 8); 136 else if (t1_is_T1B(adapter)) 137 val |= (1 << 19); 138 } 139 140 t1_tpi_write(adapter, A_ELMER0_GPO, val); 141 cphy->elmer_gpo = val; 142 *speed = SPEED_10000; 143 *duplex = DUPLEX_FULL; 144 145 /* need to add flow control */ 146 if (fc) 147 *fc = PAUSE_RX | PAUSE_TX; 148 149 return 0; 150 } 151 152 static void my3126_destroy(struct cphy *cphy) 153 { 154 kfree(cphy); 155 } 156 157 static const struct cphy_ops my3126_ops = { 158 .destroy = my3126_destroy, 159 .reset = my3126_reset, 160 .interrupt_enable = my3126_interrupt_enable, 161 .interrupt_disable = my3126_interrupt_disable, 162 .interrupt_clear = my3126_interrupt_clear, 163 .interrupt_handler = my3126_interrupt_handler, 164 .get_link_status = my3126_get_link_status, 165 .set_loopback = my3126_set_loopback, 166 .mmds = (MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | 167 MDIO_DEVS_PHYXS), 168 }; 169 170 static struct cphy *my3126_phy_create(struct net_device *dev, 171 int phy_addr, const struct mdio_ops *mdio_ops) 172 { 173 struct cphy *cphy = kzalloc(sizeof (*cphy), GFP_KERNEL); 174 175 if (!cphy) 176 return NULL; 177 178 cphy_init(cphy, dev, phy_addr, &my3126_ops, mdio_ops); 179 INIT_DELAYED_WORK(&cphy->phy_update, my3216_poll); 180 cphy->bmsr = 0; 181 182 return cphy; 183 } 184 185 /* Chip Reset */ 186 static int my3126_phy_reset(adapter_t * adapter) 187 { 188 u32 val; 189 190 t1_tpi_read(adapter, A_ELMER0_GPO, &val); 191 val &= ~4; 192 t1_tpi_write(adapter, A_ELMER0_GPO, val); 193 msleep(100); 194 195 t1_tpi_write(adapter, A_ELMER0_GPO, val | 4); 196 msleep(1000); 197 198 /* Now lets enable the Laser. Delay 100us */ 199 t1_tpi_read(adapter, A_ELMER0_GPO, &val); 200 val |= 0x8000; 201 t1_tpi_write(adapter, A_ELMER0_GPO, val); 202 udelay(100); 203 return 0; 204 } 205 206 const struct gphy t1_my3126_ops = { 207 .create = my3126_phy_create, 208 .reset = my3126_phy_reset 209 }; 210