1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * SMSC LAN9[12]1[567] Network driver 4 * 5 * (c) 2007 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de> 6 */ 7 8 #include <common.h> 9 #include <command.h> 10 #include <malloc.h> 11 #include <net.h> 12 #include <miiphy.h> 13 14 #include "smc911x.h" 15 16 u32 pkt_data_pull(struct eth_device *dev, u32 addr) \ 17 __attribute__ ((weak, alias ("smc911x_reg_read"))); 18 void pkt_data_push(struct eth_device *dev, u32 addr, u32 val) \ 19 __attribute__ ((weak, alias ("smc911x_reg_write"))); 20 21 static void smc911x_handle_mac_address(struct eth_device *dev) 22 { 23 unsigned long addrh, addrl; 24 uchar *m = dev->enetaddr; 25 26 addrl = m[0] | (m[1] << 8) | (m[2] << 16) | (m[3] << 24); 27 addrh = m[4] | (m[5] << 8); 28 smc911x_set_mac_csr(dev, ADDRL, addrl); 29 smc911x_set_mac_csr(dev, ADDRH, addrh); 30 31 printf(DRIVERNAME ": MAC %pM\n", m); 32 } 33 34 static int smc911x_eth_phy_read(struct eth_device *dev, 35 u8 phy, u8 reg, u16 *val) 36 { 37 while (smc911x_get_mac_csr(dev, MII_ACC) & MII_ACC_MII_BUSY) 38 ; 39 40 smc911x_set_mac_csr(dev, MII_ACC, phy << 11 | reg << 6 | 41 MII_ACC_MII_BUSY); 42 43 while (smc911x_get_mac_csr(dev, MII_ACC) & MII_ACC_MII_BUSY) 44 ; 45 46 *val = smc911x_get_mac_csr(dev, MII_DATA); 47 48 return 0; 49 } 50 51 static int smc911x_eth_phy_write(struct eth_device *dev, 52 u8 phy, u8 reg, u16 val) 53 { 54 while (smc911x_get_mac_csr(dev, MII_ACC) & MII_ACC_MII_BUSY) 55 ; 56 57 smc911x_set_mac_csr(dev, MII_DATA, val); 58 smc911x_set_mac_csr(dev, MII_ACC, 59 phy << 11 | reg << 6 | MII_ACC_MII_BUSY | MII_ACC_MII_WRITE); 60 61 while (smc911x_get_mac_csr(dev, MII_ACC) & MII_ACC_MII_BUSY) 62 ; 63 return 0; 64 } 65 66 static int smc911x_phy_reset(struct eth_device *dev) 67 { 68 u32 reg; 69 70 reg = smc911x_reg_read(dev, PMT_CTRL); 71 reg &= ~0xfffff030; 72 reg |= PMT_CTRL_PHY_RST; 73 smc911x_reg_write(dev, PMT_CTRL, reg); 74 75 mdelay(100); 76 77 return 0; 78 } 79 80 static void smc911x_phy_configure(struct eth_device *dev) 81 { 82 int timeout; 83 u16 status; 84 85 smc911x_phy_reset(dev); 86 87 smc911x_eth_phy_write(dev, 1, MII_BMCR, BMCR_RESET); 88 mdelay(1); 89 smc911x_eth_phy_write(dev, 1, MII_ADVERTISE, 0x01e1); 90 smc911x_eth_phy_write(dev, 1, MII_BMCR, BMCR_ANENABLE | 91 BMCR_ANRESTART); 92 93 timeout = 5000; 94 do { 95 mdelay(1); 96 if ((timeout--) == 0) 97 goto err_out; 98 99 if (smc911x_eth_phy_read(dev, 1, MII_BMSR, &status) != 0) 100 goto err_out; 101 } while (!(status & BMSR_LSTATUS)); 102 103 printf(DRIVERNAME ": phy initialized\n"); 104 105 return; 106 107 err_out: 108 printf(DRIVERNAME ": autonegotiation timed out\n"); 109 } 110 111 static void smc911x_enable(struct eth_device *dev) 112 { 113 /* Enable TX */ 114 smc911x_reg_write(dev, HW_CFG, 8 << 16 | HW_CFG_SF); 115 116 smc911x_reg_write(dev, GPT_CFG, GPT_CFG_TIMER_EN | 10000); 117 118 smc911x_reg_write(dev, TX_CFG, TX_CFG_TX_ON); 119 120 /* no padding to start of packets */ 121 smc911x_reg_write(dev, RX_CFG, 0); 122 123 smc911x_set_mac_csr(dev, MAC_CR, MAC_CR_TXEN | MAC_CR_RXEN | 124 MAC_CR_HBDIS); 125 126 } 127 128 static int smc911x_init(struct eth_device *dev, bd_t * bd) 129 { 130 struct chip_id *id = dev->priv; 131 132 printf(DRIVERNAME ": detected %s controller\n", id->name); 133 134 smc911x_reset(dev); 135 136 /* Configure the PHY, initialize the link state */ 137 smc911x_phy_configure(dev); 138 139 smc911x_handle_mac_address(dev); 140 141 /* Turn on Tx + Rx */ 142 smc911x_enable(dev); 143 144 return 0; 145 } 146 147 static int smc911x_send(struct eth_device *dev, void *packet, int length) 148 { 149 u32 *data = (u32*)packet; 150 u32 tmplen; 151 u32 status; 152 153 smc911x_reg_write(dev, TX_DATA_FIFO, TX_CMD_A_INT_FIRST_SEG | 154 TX_CMD_A_INT_LAST_SEG | length); 155 smc911x_reg_write(dev, TX_DATA_FIFO, length); 156 157 tmplen = (length + 3) / 4; 158 159 while (tmplen--) 160 pkt_data_push(dev, TX_DATA_FIFO, *data++); 161 162 /* wait for transmission */ 163 while (!((smc911x_reg_read(dev, TX_FIFO_INF) & 164 TX_FIFO_INF_TSUSED) >> 16)); 165 166 /* get status. Ignore 'no carrier' error, it has no meaning for 167 * full duplex operation 168 */ 169 status = smc911x_reg_read(dev, TX_STATUS_FIFO) & 170 (TX_STS_LOC | TX_STS_LATE_COLL | TX_STS_MANY_COLL | 171 TX_STS_MANY_DEFER | TX_STS_UNDERRUN); 172 173 if (!status) 174 return 0; 175 176 printf(DRIVERNAME ": failed to send packet: %s%s%s%s%s\n", 177 status & TX_STS_LOC ? "TX_STS_LOC " : "", 178 status & TX_STS_LATE_COLL ? "TX_STS_LATE_COLL " : "", 179 status & TX_STS_MANY_COLL ? "TX_STS_MANY_COLL " : "", 180 status & TX_STS_MANY_DEFER ? "TX_STS_MANY_DEFER " : "", 181 status & TX_STS_UNDERRUN ? "TX_STS_UNDERRUN" : ""); 182 183 return -1; 184 } 185 186 static void smc911x_halt(struct eth_device *dev) 187 { 188 smc911x_reset(dev); 189 smc911x_handle_mac_address(dev); 190 } 191 192 static int smc911x_rx(struct eth_device *dev) 193 { 194 u32 *data = (u32 *)net_rx_packets[0]; 195 u32 pktlen, tmplen; 196 u32 status; 197 198 if ((smc911x_reg_read(dev, RX_FIFO_INF) & RX_FIFO_INF_RXSUSED) >> 16) { 199 status = smc911x_reg_read(dev, RX_STATUS_FIFO); 200 pktlen = (status & RX_STS_PKT_LEN) >> 16; 201 202 smc911x_reg_write(dev, RX_CFG, 0); 203 204 tmplen = (pktlen + 3) / 4; 205 while (tmplen--) 206 *data++ = pkt_data_pull(dev, RX_DATA_FIFO); 207 208 if (status & RX_STS_ES) 209 printf(DRIVERNAME 210 ": dropped bad packet. Status: 0x%08x\n", 211 status); 212 else 213 net_process_received_packet(net_rx_packets[0], pktlen); 214 } 215 216 return 0; 217 } 218 219 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) 220 /* wrapper for smc911x_eth_phy_read */ 221 static int smc911x_miiphy_read(struct mii_dev *bus, int phy, int devad, 222 int reg) 223 { 224 u16 val = 0; 225 struct eth_device *dev = eth_get_dev_by_name(bus->name); 226 if (dev) { 227 int retval = smc911x_eth_phy_read(dev, phy, reg, &val); 228 if (retval < 0) 229 return retval; 230 return val; 231 } 232 return -ENODEV; 233 } 234 /* wrapper for smc911x_eth_phy_write */ 235 static int smc911x_miiphy_write(struct mii_dev *bus, int phy, int devad, 236 int reg, u16 val) 237 { 238 struct eth_device *dev = eth_get_dev_by_name(bus->name); 239 if (dev) 240 return smc911x_eth_phy_write(dev, phy, reg, val); 241 return -ENODEV; 242 } 243 #endif 244 245 int smc911x_initialize(u8 dev_num, int base_addr) 246 { 247 unsigned long addrl, addrh; 248 struct eth_device *dev; 249 250 dev = malloc(sizeof(*dev)); 251 if (!dev) { 252 return -1; 253 } 254 memset(dev, 0, sizeof(*dev)); 255 256 dev->iobase = base_addr; 257 258 /* Try to detect chip. Will fail if not present. */ 259 if (smc911x_detect_chip(dev)) { 260 free(dev); 261 return 0; 262 } 263 264 addrh = smc911x_get_mac_csr(dev, ADDRH); 265 addrl = smc911x_get_mac_csr(dev, ADDRL); 266 if (!(addrl == 0xffffffff && addrh == 0x0000ffff)) { 267 /* address is obtained from optional eeprom */ 268 dev->enetaddr[0] = addrl; 269 dev->enetaddr[1] = addrl >> 8; 270 dev->enetaddr[2] = addrl >> 16; 271 dev->enetaddr[3] = addrl >> 24; 272 dev->enetaddr[4] = addrh; 273 dev->enetaddr[5] = addrh >> 8; 274 } 275 276 dev->init = smc911x_init; 277 dev->halt = smc911x_halt; 278 dev->send = smc911x_send; 279 dev->recv = smc911x_rx; 280 sprintf(dev->name, "%s-%hu", DRIVERNAME, dev_num); 281 282 eth_register(dev); 283 284 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) 285 int retval; 286 struct mii_dev *mdiodev = mdio_alloc(); 287 if (!mdiodev) 288 return -ENOMEM; 289 strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); 290 mdiodev->read = smc911x_miiphy_read; 291 mdiodev->write = smc911x_miiphy_write; 292 293 retval = mdio_register(mdiodev); 294 if (retval < 0) 295 return retval; 296 #endif 297 298 return 1; 299 } 300