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