Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v5.2-rc7 497 lines 13 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * drivers/net/ethernet/netx-eth.c 4 * 5 * Copyright (c) 2005 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix 6 */ 7 8#include <linux/init.h> 9#include <linux/interrupt.h> 10#include <linux/module.h> 11#include <linux/kernel.h> 12#include <linux/delay.h> 13 14#include <linux/netdevice.h> 15#include <linux/platform_device.h> 16#include <linux/etherdevice.h> 17#include <linux/skbuff.h> 18#include <linux/mii.h> 19 20#include <asm/io.h> 21#include <mach/hardware.h> 22#include <mach/netx-regs.h> 23#include <mach/pfifo.h> 24#include <mach/xc.h> 25#include <linux/platform_data/eth-netx.h> 26 27/* XC Fifo Offsets */ 28#define EMPTY_PTR_FIFO(xcno) (0 + ((xcno) << 3)) /* Index of the empty pointer FIFO */ 29#define IND_FIFO_PORT_HI(xcno) (1 + ((xcno) << 3)) /* Index of the FIFO where received */ 30 /* Data packages are indicated by XC */ 31#define IND_FIFO_PORT_LO(xcno) (2 + ((xcno) << 3)) /* Index of the FIFO where received */ 32 /* Data packages are indicated by XC */ 33#define REQ_FIFO_PORT_HI(xcno) (3 + ((xcno) << 3)) /* Index of the FIFO where Data packages */ 34 /* have to be indicated by ARM which */ 35 /* shall be sent */ 36#define REQ_FIFO_PORT_LO(xcno) (4 + ((xcno) << 3)) /* Index of the FIFO where Data packages */ 37 /* have to be indicated by ARM which shall */ 38 /* be sent */ 39#define CON_FIFO_PORT_HI(xcno) (5 + ((xcno) << 3)) /* Index of the FIFO where sent Data packages */ 40 /* are confirmed */ 41#define CON_FIFO_PORT_LO(xcno) (6 + ((xcno) << 3)) /* Index of the FIFO where sent Data */ 42 /* packages are confirmed */ 43#define PFIFO_MASK(xcno) (0x7f << (xcno*8)) 44 45#define FIFO_PTR_FRAMELEN_SHIFT 0 46#define FIFO_PTR_FRAMELEN_MASK (0x7ff << 0) 47#define FIFO_PTR_FRAMELEN(len) (((len) << 0) & FIFO_PTR_FRAMELEN_MASK) 48#define FIFO_PTR_TIMETRIG (1<<11) 49#define FIFO_PTR_MULTI_REQ 50#define FIFO_PTR_ORIGIN (1<<14) 51#define FIFO_PTR_VLAN (1<<15) 52#define FIFO_PTR_FRAMENO_SHIFT 16 53#define FIFO_PTR_FRAMENO_MASK (0x3f << 16) 54#define FIFO_PTR_FRAMENO(no) (((no) << 16) & FIFO_PTR_FRAMENO_MASK) 55#define FIFO_PTR_SEGMENT_SHIFT 22 56#define FIFO_PTR_SEGMENT_MASK (0xf << 22) 57#define FIFO_PTR_SEGMENT(seg) (((seg) & 0xf) << 22) 58#define FIFO_PTR_ERROR_SHIFT 28 59#define FIFO_PTR_ERROR_MASK (0xf << 28) 60 61#define ISR_LINK_STATUS_CHANGE (1<<4) 62#define ISR_IND_LO (1<<3) 63#define ISR_CON_LO (1<<2) 64#define ISR_IND_HI (1<<1) 65#define ISR_CON_HI (1<<0) 66 67#define ETH_MAC_LOCAL_CONFIG 0x1560 68#define ETH_MAC_4321 0x1564 69#define ETH_MAC_65 0x1568 70 71#define MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT 16 72#define MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK (0xf<<MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT) 73#define MAC_TRAFFIC_CLASS_ARRANGEMENT(x) (((x)<<MAC_TRAFFIC_CLASS_ARRANGEMENT_SHIFT) & MAC_TRAFFIC_CLASS_ARRANGEMENT_MASK) 74#define LOCAL_CONFIG_LINK_STATUS_IRQ_EN (1<<24) 75#define LOCAL_CONFIG_CON_LO_IRQ_EN (1<<23) 76#define LOCAL_CONFIG_CON_HI_IRQ_EN (1<<22) 77#define LOCAL_CONFIG_IND_LO_IRQ_EN (1<<21) 78#define LOCAL_CONFIG_IND_HI_IRQ_EN (1<<20) 79 80#define CARDNAME "netx-eth" 81 82/* LSB must be zero */ 83#define INTERNAL_PHY_ADR 0x1c 84 85struct netx_eth_priv { 86 void __iomem *sram_base, *xpec_base, *xmac_base; 87 int id; 88 struct mii_if_info mii; 89 u32 msg_enable; 90 struct xc *xc; 91 spinlock_t lock; 92}; 93 94static void netx_eth_set_multicast_list(struct net_device *ndev) 95{ 96 /* implement me */ 97} 98 99static int 100netx_eth_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev) 101{ 102 struct netx_eth_priv *priv = netdev_priv(ndev); 103 unsigned char *buf = skb->data; 104 unsigned int len = skb->len; 105 106 spin_lock_irq(&priv->lock); 107 memcpy_toio(priv->sram_base + 1560, (void *)buf, len); 108 if (len < 60) { 109 memset_io(priv->sram_base + 1560 + len, 0, 60 - len); 110 len = 60; 111 } 112 113 pfifo_push(REQ_FIFO_PORT_LO(priv->id), 114 FIFO_PTR_SEGMENT(priv->id) | 115 FIFO_PTR_FRAMENO(1) | 116 FIFO_PTR_FRAMELEN(len)); 117 118 ndev->stats.tx_packets++; 119 ndev->stats.tx_bytes += skb->len; 120 121 netif_stop_queue(ndev); 122 spin_unlock_irq(&priv->lock); 123 dev_kfree_skb(skb); 124 125 return NETDEV_TX_OK; 126} 127 128static void netx_eth_receive(struct net_device *ndev) 129{ 130 struct netx_eth_priv *priv = netdev_priv(ndev); 131 unsigned int val, frameno, seg, len; 132 unsigned char *data; 133 struct sk_buff *skb; 134 135 val = pfifo_pop(IND_FIFO_PORT_LO(priv->id)); 136 137 frameno = (val & FIFO_PTR_FRAMENO_MASK) >> FIFO_PTR_FRAMENO_SHIFT; 138 seg = (val & FIFO_PTR_SEGMENT_MASK) >> FIFO_PTR_SEGMENT_SHIFT; 139 len = (val & FIFO_PTR_FRAMELEN_MASK) >> FIFO_PTR_FRAMELEN_SHIFT; 140 141 skb = netdev_alloc_skb(ndev, len); 142 if (unlikely(skb == NULL)) { 143 ndev->stats.rx_dropped++; 144 return; 145 } 146 147 data = skb_put(skb, len); 148 149 memcpy_fromio(data, priv->sram_base + frameno * 1560, len); 150 151 pfifo_push(EMPTY_PTR_FIFO(priv->id), 152 FIFO_PTR_SEGMENT(seg) | FIFO_PTR_FRAMENO(frameno)); 153 154 skb->protocol = eth_type_trans(skb, ndev); 155 netif_rx(skb); 156 ndev->stats.rx_packets++; 157 ndev->stats.rx_bytes += len; 158} 159 160static irqreturn_t 161netx_eth_interrupt(int irq, void *dev_id) 162{ 163 struct net_device *ndev = dev_id; 164 struct netx_eth_priv *priv = netdev_priv(ndev); 165 int status; 166 unsigned long flags; 167 168 spin_lock_irqsave(&priv->lock, flags); 169 170 status = readl(NETX_PFIFO_XPEC_ISR(priv->id)); 171 while (status) { 172 int fill_level; 173 writel(status, NETX_PFIFO_XPEC_ISR(priv->id)); 174 175 if ((status & ISR_CON_HI) || (status & ISR_IND_HI)) 176 printk("%s: unexpected status: 0x%08x\n", 177 __func__, status); 178 179 fill_level = 180 readl(NETX_PFIFO_FILL_LEVEL(IND_FIFO_PORT_LO(priv->id))); 181 while (fill_level--) 182 netx_eth_receive(ndev); 183 184 if (status & ISR_CON_LO) 185 netif_wake_queue(ndev); 186 187 if (status & ISR_LINK_STATUS_CHANGE) 188 mii_check_media(&priv->mii, netif_msg_link(priv), 1); 189 190 status = readl(NETX_PFIFO_XPEC_ISR(priv->id)); 191 } 192 spin_unlock_irqrestore(&priv->lock, flags); 193 return IRQ_HANDLED; 194} 195 196static int netx_eth_open(struct net_device *ndev) 197{ 198 struct netx_eth_priv *priv = netdev_priv(ndev); 199 200 if (request_irq 201 (ndev->irq, netx_eth_interrupt, IRQF_SHARED, ndev->name, ndev)) 202 return -EAGAIN; 203 204 writel(ndev->dev_addr[0] | 205 ndev->dev_addr[1]<<8 | 206 ndev->dev_addr[2]<<16 | 207 ndev->dev_addr[3]<<24, 208 priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_4321); 209 writel(ndev->dev_addr[4] | 210 ndev->dev_addr[5]<<8, 211 priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_65); 212 213 writel(LOCAL_CONFIG_LINK_STATUS_IRQ_EN | 214 LOCAL_CONFIG_CON_LO_IRQ_EN | 215 LOCAL_CONFIG_CON_HI_IRQ_EN | 216 LOCAL_CONFIG_IND_LO_IRQ_EN | 217 LOCAL_CONFIG_IND_HI_IRQ_EN, 218 priv->xpec_base + NETX_XPEC_RAM_START_OFS + 219 ETH_MAC_LOCAL_CONFIG); 220 221 mii_check_media(&priv->mii, netif_msg_link(priv), 1); 222 netif_start_queue(ndev); 223 224 return 0; 225} 226 227static int netx_eth_close(struct net_device *ndev) 228{ 229 struct netx_eth_priv *priv = netdev_priv(ndev); 230 231 netif_stop_queue(ndev); 232 233 writel(0, 234 priv->xpec_base + NETX_XPEC_RAM_START_OFS + ETH_MAC_LOCAL_CONFIG); 235 236 free_irq(ndev->irq, ndev); 237 238 return 0; 239} 240 241static void netx_eth_timeout(struct net_device *ndev) 242{ 243 struct netx_eth_priv *priv = netdev_priv(ndev); 244 int i; 245 246 printk(KERN_ERR "%s: transmit timed out, resetting\n", ndev->name); 247 248 spin_lock_irq(&priv->lock); 249 250 xc_reset(priv->xc); 251 xc_start(priv->xc); 252 253 for (i=2; i<=18; i++) 254 pfifo_push(EMPTY_PTR_FIFO(priv->id), 255 FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id)); 256 257 spin_unlock_irq(&priv->lock); 258 259 netif_wake_queue(ndev); 260} 261 262static int 263netx_eth_phy_read(struct net_device *ndev, int phy_id, int reg) 264{ 265 unsigned int val; 266 267 val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) | 268 MIIMU_REGADDR(reg) | MIIMU_PHY_NRES; 269 270 writel(val, NETX_MIIMU); 271 while (readl(NETX_MIIMU) & MIIMU_SNRDY); 272 273 return readl(NETX_MIIMU) >> 16; 274 275} 276 277static void 278netx_eth_phy_write(struct net_device *ndev, int phy_id, int reg, int value) 279{ 280 unsigned int val; 281 282 val = MIIMU_SNRDY | MIIMU_PREAMBLE | MIIMU_PHYADDR(phy_id) | 283 MIIMU_REGADDR(reg) | MIIMU_PHY_NRES | MIIMU_OPMODE_WRITE | 284 MIIMU_DATA(value); 285 286 writel(val, NETX_MIIMU); 287 while (readl(NETX_MIIMU) & MIIMU_SNRDY); 288} 289 290static const struct net_device_ops netx_eth_netdev_ops = { 291 .ndo_open = netx_eth_open, 292 .ndo_stop = netx_eth_close, 293 .ndo_start_xmit = netx_eth_hard_start_xmit, 294 .ndo_tx_timeout = netx_eth_timeout, 295 .ndo_set_rx_mode = netx_eth_set_multicast_list, 296 .ndo_validate_addr = eth_validate_addr, 297 .ndo_set_mac_address = eth_mac_addr, 298}; 299 300static int netx_eth_enable(struct net_device *ndev) 301{ 302 struct netx_eth_priv *priv = netdev_priv(ndev); 303 unsigned int mac4321, mac65; 304 int running, i, ret; 305 bool inv_mac_addr = false; 306 307 ndev->netdev_ops = &netx_eth_netdev_ops; 308 ndev->watchdog_timeo = msecs_to_jiffies(5000); 309 310 priv->msg_enable = NETIF_MSG_LINK; 311 priv->mii.phy_id_mask = 0x1f; 312 priv->mii.reg_num_mask = 0x1f; 313 priv->mii.force_media = 0; 314 priv->mii.full_duplex = 0; 315 priv->mii.dev = ndev; 316 priv->mii.mdio_read = netx_eth_phy_read; 317 priv->mii.mdio_write = netx_eth_phy_write; 318 priv->mii.phy_id = INTERNAL_PHY_ADR + priv->id; 319 320 running = xc_running(priv->xc); 321 xc_stop(priv->xc); 322 323 /* if the xc engine is already running, assume the bootloader has 324 * loaded the firmware for us 325 */ 326 if (running) { 327 /* get Node Address from hardware */ 328 mac4321 = readl(priv->xpec_base + 329 NETX_XPEC_RAM_START_OFS + ETH_MAC_4321); 330 mac65 = readl(priv->xpec_base + 331 NETX_XPEC_RAM_START_OFS + ETH_MAC_65); 332 333 ndev->dev_addr[0] = mac4321 & 0xff; 334 ndev->dev_addr[1] = (mac4321 >> 8) & 0xff; 335 ndev->dev_addr[2] = (mac4321 >> 16) & 0xff; 336 ndev->dev_addr[3] = (mac4321 >> 24) & 0xff; 337 ndev->dev_addr[4] = mac65 & 0xff; 338 ndev->dev_addr[5] = (mac65 >> 8) & 0xff; 339 } else { 340 if (xc_request_firmware(priv->xc)) { 341 printk(CARDNAME ": requesting firmware failed\n"); 342 return -ENODEV; 343 } 344 } 345 346 xc_reset(priv->xc); 347 xc_start(priv->xc); 348 349 if (!is_valid_ether_addr(ndev->dev_addr)) 350 inv_mac_addr = true; 351 352 for (i=2; i<=18; i++) 353 pfifo_push(EMPTY_PTR_FIFO(priv->id), 354 FIFO_PTR_FRAMENO(i) | FIFO_PTR_SEGMENT(priv->id)); 355 356 ret = register_netdev(ndev); 357 if (inv_mac_addr) 358 printk("%s: Invalid ethernet MAC address. Please set using ip\n", 359 ndev->name); 360 361 return ret; 362} 363 364static int netx_eth_drv_probe(struct platform_device *pdev) 365{ 366 struct netx_eth_priv *priv; 367 struct net_device *ndev; 368 struct netxeth_platform_data *pdata; 369 int ret; 370 371 ndev = alloc_etherdev(sizeof (struct netx_eth_priv)); 372 if (!ndev) { 373 ret = -ENOMEM; 374 goto exit; 375 } 376 SET_NETDEV_DEV(ndev, &pdev->dev); 377 378 platform_set_drvdata(pdev, ndev); 379 380 priv = netdev_priv(ndev); 381 382 pdata = dev_get_platdata(&pdev->dev); 383 priv->xc = request_xc(pdata->xcno, &pdev->dev); 384 if (!priv->xc) { 385 dev_err(&pdev->dev, "unable to request xc engine\n"); 386 ret = -ENODEV; 387 goto exit_free_netdev; 388 } 389 390 ndev->irq = priv->xc->irq; 391 priv->id = pdev->id; 392 priv->xpec_base = priv->xc->xpec_base; 393 priv->xmac_base = priv->xc->xmac_base; 394 priv->sram_base = priv->xc->sram_base; 395 396 spin_lock_init(&priv->lock); 397 398 ret = pfifo_request(PFIFO_MASK(priv->id)); 399 if (ret) { 400 printk("unable to request PFIFO\n"); 401 goto exit_free_xc; 402 } 403 404 ret = netx_eth_enable(ndev); 405 if (ret) 406 goto exit_free_pfifo; 407 408 return 0; 409exit_free_pfifo: 410 pfifo_free(PFIFO_MASK(priv->id)); 411exit_free_xc: 412 free_xc(priv->xc); 413exit_free_netdev: 414 free_netdev(ndev); 415exit: 416 return ret; 417} 418 419static int netx_eth_drv_remove(struct platform_device *pdev) 420{ 421 struct net_device *ndev = platform_get_drvdata(pdev); 422 struct netx_eth_priv *priv = netdev_priv(ndev); 423 424 unregister_netdev(ndev); 425 xc_stop(priv->xc); 426 free_xc(priv->xc); 427 free_netdev(ndev); 428 pfifo_free(PFIFO_MASK(priv->id)); 429 430 return 0; 431} 432 433static int netx_eth_drv_suspend(struct platform_device *pdev, pm_message_t state) 434{ 435 dev_err(&pdev->dev, "suspend not implemented\n"); 436 return 0; 437} 438 439static int netx_eth_drv_resume(struct platform_device *pdev) 440{ 441 dev_err(&pdev->dev, "resume not implemented\n"); 442 return 0; 443} 444 445static struct platform_driver netx_eth_driver = { 446 .probe = netx_eth_drv_probe, 447 .remove = netx_eth_drv_remove, 448 .suspend = netx_eth_drv_suspend, 449 .resume = netx_eth_drv_resume, 450 .driver = { 451 .name = CARDNAME, 452 }, 453}; 454 455static int __init netx_eth_init(void) 456{ 457 unsigned int phy_control, val; 458 459 printk("NetX Ethernet driver\n"); 460 461 phy_control = PHY_CONTROL_PHY_ADDRESS(INTERNAL_PHY_ADR>>1) | 462 PHY_CONTROL_PHY1_MODE(PHY_MODE_ALL) | 463 PHY_CONTROL_PHY1_AUTOMDIX | 464 PHY_CONTROL_PHY1_EN | 465 PHY_CONTROL_PHY0_MODE(PHY_MODE_ALL) | 466 PHY_CONTROL_PHY0_AUTOMDIX | 467 PHY_CONTROL_PHY0_EN | 468 PHY_CONTROL_CLK_XLATIN; 469 470 val = readl(NETX_SYSTEM_IOC_ACCESS_KEY); 471 writel(val, NETX_SYSTEM_IOC_ACCESS_KEY); 472 473 writel(phy_control | PHY_CONTROL_RESET, NETX_SYSTEM_PHY_CONTROL); 474 udelay(100); 475 476 val = readl(NETX_SYSTEM_IOC_ACCESS_KEY); 477 writel(val, NETX_SYSTEM_IOC_ACCESS_KEY); 478 479 writel(phy_control, NETX_SYSTEM_PHY_CONTROL); 480 481 return platform_driver_register(&netx_eth_driver); 482} 483 484static void __exit netx_eth_cleanup(void) 485{ 486 platform_driver_unregister(&netx_eth_driver); 487} 488 489module_init(netx_eth_init); 490module_exit(netx_eth_cleanup); 491 492MODULE_AUTHOR("Sascha Hauer, Pengutronix"); 493MODULE_LICENSE("GPL"); 494MODULE_ALIAS("platform:" CARDNAME); 495MODULE_FIRMWARE("xc0.bin"); 496MODULE_FIRMWARE("xc1.bin"); 497MODULE_FIRMWARE("xc2.bin");