sb1250-mac.c revision 047fc56614f8f8d03fb64ef3be44f040aad25d56
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle * Copyright (C) 2001,2002,2003,2004 Broadcom Corporation 3f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * Copyright (c) 2006, 2007 Maciej W. Rozycki 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modify it under the terms of the GNU General Public License 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as published by the Free Software Foundation; either version 2 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the License, or (at your option) any later version. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details. 1474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This driver is designed for the Broadcom SiByte SOC built-in 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ethernet controllers. Written by Mitch Lichtenberg at Broadcom Corp. 22f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * 23f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * Updated to the driver model and the PHY abstraction layer 24f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * by Maciej W. Rozycki. 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 26f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 27f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <linux/bug.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h> 41f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <linux/err.h> 42f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <linux/ethtool.h> 43f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <linux/mii.h> 44f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <linux/phy.h> 45f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <linux/platform_device.h> 4670c71606190e9115e5f8363bfcd164c582eb314aPaul Gortmaker#include <linux/prefetch.h> 47f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cache.h> 49f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <asm/io.h> 50f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <asm/processor.h> /* Processor type for cache alignment. */ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Operational parameters that usually are not changed. */ 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONFIG_SBMAC_COALESCE 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Time in jiffies before concluding the transmitter is hung. */ 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_TIMEOUT (2*HZ) 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Mitch Lichtenberg (Broadcom Corp.)"); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Broadcom SiByte SOC GB Ethernet driver"); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* A few user-configurable values which may be modified when a driver 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds module is loaded. */ 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1 normal messages, 0 quiet .. 7 verbose. */ 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int debug = 1; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, int, S_IRUGO); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Debug messages"); 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SBMAC_COALESCE 72693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonstatic int int_pktcnt_tx = 255; 73693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonmodule_param(int_pktcnt_tx, int, S_IRUGO); 74693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark MasonMODULE_PARM_DESC(int_pktcnt_tx, "TX packet count"); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 76693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonstatic int int_timeout_tx = 255; 77693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonmodule_param(int_timeout_tx, int, S_IRUGO); 78693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark MasonMODULE_PARM_DESC(int_timeout_tx, "TX timeout value"); 79693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 80693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonstatic int int_pktcnt_rx = 64; 81693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonmodule_param(int_pktcnt_rx, int, S_IRUGO); 82693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark MasonMODULE_PARM_DESC(int_pktcnt_rx, "RX packet count"); 83693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 84693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonstatic int int_timeout_rx = 64; 85693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonmodule_param(int_timeout_rx, int, S_IRUGO); 86693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark MasonMODULE_PARM_DESC(int_timeout_rx, "RX timeout value"); 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 89f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <asm/sibyte/board.h> 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sibyte/sb1250.h> 91f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) 92f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#include <asm/sibyte/bcm1480_regs.h> 93f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#include <asm/sibyte/bcm1480_int.h> 94693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#define R_MAC_DMA_OODPKTLOST_RX R_MAC_DMA_OODPKTLOST 95f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sibyte/sb1250_regs.h> 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sibyte/sb1250_int.h> 98f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#else 990b1974de66f9ed44f1423449628f4926bf95b854Thomas Weber#error invalid SiByte MAC configuration 100f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#endif 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sibyte/sb1250_scd.h> 102f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#include <asm/sibyte/sb1250_mac.h> 103f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#include <asm/sibyte/sb1250_dma.h> 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 105f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) 106f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#define UNIT_INT(n) (K_BCM1480_INT_MAC_0 + ((n) * 2)) 107f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) 108f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#define UNIT_INT(n) (K_INT_MAC_0 + (n)) 109f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#else 1100b1974de66f9ed44f1423449628f4926bf95b854Thomas Weber#error invalid SiByte MAC configuration 111f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#endif 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 113f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#ifdef K_INT_PHY 114f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#define SBMAC_PHY_INT K_INT_PHY 115f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#else 116f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#define SBMAC_PHY_INT PHY_POLL 117f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#endif 118f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Simple types 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 123f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckienum sbmac_speed { 124f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_speed_none = 0, 125f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_speed_10 = SPEED_10, 126f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_speed_100 = SPEED_100, 127f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_speed_1000 = SPEED_1000, 128f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki}; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 130f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckienum sbmac_duplex { 131f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_duplex_none = -1, 132f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_duplex_half = DUPLEX_HALF, 133f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_duplex_full = DUPLEX_FULL, 134f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki}; 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 136f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckienum sbmac_fc { 137f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_fc_none, 138f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_fc_disabled, 139f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_fc_frame, 140f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_fc_collision, 141f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_fc_carrier, 142f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki}; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 144f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckienum sbmac_state { 145f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_state_uninit, 146f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_state_off, 147f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_state_on, 148f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_state_broken, 149f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki}; 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Macros 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SBDMA_NEXTBUF(d,f) ((((d)->f+1) == (d)->sbdma_dscrtable_end) ? \ 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (d)->sbdma_dscrtable : (d)->f+1) 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES) 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 163693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#define SBMAC_MAX_TXDESCR 256 164693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#define SBMAC_MAX_RXDESCR 256 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle#define ENET_PACKET_SIZE 1518 16774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle/*#define ENET_PACKET_SIZE 9216 */ 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DMA Descriptor structure 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistruct sbdmadscr { 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t dscr_a; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t dscr_b; 17673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki}; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DMA Controller structure 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistruct sbmacdma { 18374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This stuff is used to identify the channel and the registers 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * associated with it. 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 18873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbmac_softc *sbdma_eth; /* back pointer to associated 18973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki MAC */ 19073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int sbdma_channel; /* channel number */ 19173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int sbdma_txdir; /* direction (1=transmit) */ 19273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int sbdma_maxdescr; /* total # of descriptors 19373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki in ring */ 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SBMAC_COALESCE 19573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int sbdma_int_pktcnt; 19673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* # descriptors rx/tx 19773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki before interrupt */ 19873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int sbdma_int_timeout; 19973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* # usec rx/tx interrupt */ 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 20173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbdma_config0; /* DMA config register 0 */ 20273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbdma_config1; /* DMA config register 1 */ 20373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbdma_dscrbase; 20473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* descriptor base address */ 20573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbdma_dscrcnt; /* descriptor count register */ 20673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbdma_curdscr; /* current descriptor 20773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki address */ 20873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbdma_oodpktlost; 20973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* pkt drop (rx only) */ 21074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This stuff is for maintenance of the ring 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 21473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void *sbdma_dscrtable_unaligned; 21573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *sbdma_dscrtable; 21673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* base of descriptor table */ 21773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *sbdma_dscrtable_end; 21873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* end of descriptor table */ 21973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sk_buff **sbdma_ctxtable; 22073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* context table, one 22173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki per descr */ 22273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki dma_addr_t sbdma_dscrtable_phys; 22373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* and also the phys addr */ 22473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *sbdma_addptr; /* next dscr for sw to add */ 22573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *sbdma_remptr; /* next dscr for sw 22673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki to remove */ 22773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki}; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ethernet softc structure 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct sbmac_softc { 23574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Linux-specific things 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 23973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct net_device *sbm_dev; /* pointer to linux device */ 24073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct napi_struct napi; 241f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct phy_device *phy_dev; /* the associated PHY device */ 242298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek struct mii_bus *mii_bus; /* the MII bus */ 243f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int phy_irq[PHY_MAX_ADDR]; 24473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki spinlock_t sbm_lock; /* spin lock */ 24573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int sbm_devflags; /* current device flags */ 24674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Controller-specific things 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 25073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_base; /* MAC's base address */ 25173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_state sbm_state; /* current state */ 25274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 25373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_macenable; /* MAC Enable Register */ 25473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_maccfg; /* MAC Config Register */ 25573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_fifocfg; /* FIFO Config Register */ 25673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_framecfg; /* Frame Config Register */ 25773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_rxfilter; /* Receive Filter Register */ 25873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_isr; /* Interrupt Status Register */ 25973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_imr; /* Interrupt Mask Register */ 26073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_mdio; /* MDIO Register */ 26174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 26273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_speed sbm_speed; /* current speed */ 26373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_duplex sbm_duplex; /* current duplex */ 26473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_fc sbm_fc; /* cur. flow control setting */ 265f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int sbm_pause; /* current pause setting */ 266f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int sbm_link; /* current link state */ 26774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 268104bf3fb963cbc39c6675b23d46d2c9ab3f311d8Joe Perches unsigned char sbm_hwaddr[ETH_ALEN]; 26974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 27073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbmacdma sbm_txdma; /* only channel 0 for now */ 27173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbmacdma sbm_rxdma; 27273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int rx_hw_checksum; 27373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int sbe_idx; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Externs 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Prototypes 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_initctx(struct sbmacdma *d, struct sbmac_softc *s, int chan, 28673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int txrx, int maxdescr); 28773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_channel_start(struct sbmacdma *d, int rxtx); 288789585e968f07653a29a9e829aed20386043636cStephen Hemmingerstatic int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d, 289789585e968f07653a29a9e829aed20386043636cStephen Hemminger struct sk_buff *m); 29073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbdma_add_txbuffer(struct sbmacdma *d, struct sk_buff *m); 29173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_emptyring(struct sbmacdma *d); 292789585e968f07653a29a9e829aed20386043636cStephen Hemmingerstatic void sbdma_fillring(struct sbmac_softc *sc, struct sbmacdma *d); 29373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbdma_rx_process(struct sbmac_softc *sc, struct sbmacdma *d, 29473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int work_to_do, int poll); 29573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d, 29673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int poll); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_initctx(struct sbmac_softc *s); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_channel_start(struct sbmac_softc *s); 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_channel_stop(struct sbmac_softc *s); 30073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic enum sbmac_state sbmac_set_channel_state(struct sbmac_softc *, 30173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_state); 30273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbmac_promiscuous_mode(struct sbmac_softc *sc, int onoff); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic uint64_t sbmac_addr2reg(unsigned char *ptr); 30473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic irqreturn_t sbmac_intr(int irq, void *dev_instance); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_setmulti(struct sbmac_softc *sc); 307f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic int sbmac_init(struct platform_device *pldev, long long base); 30873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbmac_set_speed(struct sbmac_softc *s, enum sbmac_speed speed); 30973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbmac_set_duplex(struct sbmac_softc *s, enum sbmac_duplex duplex, 31073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_fc fc); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_open(struct net_device *dev); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_tx_timeout (struct net_device *dev); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_set_rx_mode(struct net_device *dev); 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_close(struct net_device *dev); 317bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemmingerstatic int sbmac_poll(struct napi_struct *napi, int budget); 318693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 319f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic void sbmac_mii_poll(struct net_device *dev); 32059b81827071a8ae7f399da533d268e1e33bfeeb7Ralf Baechlestatic int sbmac_mii_probe(struct net_device *dev); 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 322f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic void sbmac_mii_sync(void __iomem *sbm_mdio); 323f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic void sbmac_mii_senddata(void __iomem *sbm_mdio, unsigned int data, 32473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int bitcnt); 325f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic int sbmac_mii_read(struct mii_bus *bus, int phyaddr, int regidx); 326f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic int sbmac_mii_write(struct mii_bus *bus, int phyaddr, int regidx, 327f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki u16 val); 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Globals 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 334f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic char sbmac_string[] = "sb1250-mac"; 335f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 336f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic char sbmac_mdio_string[] = "sb1250-mac-mdio"; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MDIO constants 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MII_COMMAND_START 0x01 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MII_COMMAND_READ 0x02 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MII_COMMAND_WRITE 0x01 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MII_COMMAND_ACK 0x02 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M_MAC_MDIO_DIR_OUTPUT 0 /* for clarity */ 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ENABLE 1 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DISABLE 0 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 354f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * SBMAC_MII_SYNC(sbm_mdio) 35574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Synchronize with the MII - send a pattern of bits to the MII 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that will guarantee that it is ready to accept a command. 35874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 35974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 360f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * sbm_mdio - address of the MAC's MDIO register 36174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 366f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic void sbmac_mii_sync(void __iomem *sbm_mdio) 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cnt; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t bits; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int mac_mdio_genc; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 372f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC; 37374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT; 37574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 376f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(bits | mac_mdio_genc, sbm_mdio); 37774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (cnt = 0; cnt < 32; cnt++) { 379f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, sbm_mdio); 380f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(bits | mac_mdio_genc, sbm_mdio); 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 385f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * SBMAC_MII_SENDDATA(sbm_mdio, data, bitcnt) 38674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send some bits to the MII. The bits to be sent are right- 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * justified in the 'data' parameter. 38974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 39074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 391f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * sbm_mdio - address of the MAC's MDIO register 392f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * data - data to send 393f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * bitcnt - number of bits to send 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 396f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic void sbmac_mii_senddata(void __iomem *sbm_mdio, unsigned int data, 397f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int bitcnt) 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t bits; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int curmask; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int mac_mdio_genc; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 404f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC; 40574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bits = M_MAC_MDIO_DIR_OUTPUT; 407f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(bits | mac_mdio_genc, sbm_mdio); 40874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds curmask = 1 << (bitcnt - 1); 41074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < bitcnt; i++) { 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data & curmask) 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bits |= M_MAC_MDIO_OUT; 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else bits &= ~M_MAC_MDIO_OUT; 415f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(bits | mac_mdio_genc, sbm_mdio); 416f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, sbm_mdio); 417f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(bits | mac_mdio_genc, sbm_mdio); 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds curmask >>= 1; 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 425f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * SBMAC_MII_READ(bus, phyaddr, regidx) 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read a PHY register. 42774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 42874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 429f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * bus - MDIO bus handle 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * phyaddr - PHY's address 431f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * regnum - index of register to read 43274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 434f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * value read, or 0xffff if an error occurred. 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 437f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic int sbmac_mii_read(struct mii_bus *bus, int phyaddr, int regidx) 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 439f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct sbmac_softc *sc = (struct sbmac_softc *)bus->priv; 440f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki void __iomem *sbm_mdio = sc->sbm_mdio; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int idx; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int regval; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int mac_mdio_genc; 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Synchronize ourselves so that the PHY knows the next 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * thing coming down is a command 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 450f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_sync(sbm_mdio); 45174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send the data to the PHY. The sequence is 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a "start" command (2 bits) 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a "read" command (2 bits) 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the PHY addr (5 bits) 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the register index (5 bits) 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 459f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, MII_COMMAND_START, 2); 460f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, MII_COMMAND_READ, 2); 461f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, phyaddr, 5); 462f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, regidx, 5); 46374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 464f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC; 46574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 46674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switch the port around without a clock transition. 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 469f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio); 47074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send out a clock pulse to signal we want the status 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 474f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, 475f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbm_mdio); 476f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio); 47774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 47874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If an error occurred, the PHY will signal '1' back 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 481f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki error = __raw_readq(sbm_mdio) & M_MAC_MDIO_IN; 48274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 48374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Issue an 'idle' clock pulse, but keep the direction 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the same. 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 487f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, 488f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbm_mdio); 489f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio); 49074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regval = 0; 49274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < 16; idx++) { 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regval <<= 1; 49574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error == 0) { 497f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (__raw_readq(sbm_mdio) & M_MAC_MDIO_IN) 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regval |= 1; 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 50074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 501f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, 502f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbm_mdio); 503f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio); 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 50574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Switch back to output */ 507f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, sbm_mdio); 50874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error == 0) 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return regval; 511f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return 0xffff; 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 516f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * SBMAC_MII_WRITE(bus, phyaddr, regidx, regval) 51774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Write a value to a PHY register. 51974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 52074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 521f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * bus - MDIO bus handle 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * phyaddr - PHY to use 523f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * regidx - register within the PHY 524f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * regval - data to write to register 52574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 527f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * 0 for success 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 530f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic int sbmac_mii_write(struct mii_bus *bus, int phyaddr, int regidx, 531f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki u16 regval) 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 533f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct sbmac_softc *sc = (struct sbmac_softc *)bus->priv; 534f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki void __iomem *sbm_mdio = sc->sbm_mdio; 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int mac_mdio_genc; 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 537f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_sync(sbm_mdio); 53874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 539f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, MII_COMMAND_START, 2); 540f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, MII_COMMAND_WRITE, 2); 541f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, phyaddr, 5); 542f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, regidx, 5); 543f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, MII_COMMAND_ACK, 2); 544f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, regval, 16); 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 546f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 548f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, sbm_mdio); 549f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 550f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return 0; 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_INITCTX(d,s,chan,txrx,maxdescr) 55774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize a DMA channel context. Since there are potentially 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * eight DMA channels per MAC, it's nice to do this in a standard 56074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * way. 56174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 56274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 56373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki * d - struct sbmacdma (DMA channel context) 56473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki * s - struct sbmac_softc (pointer to a MAC) 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * chan - channel number (0..1 right now) 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * txrx - Identifies DMA_TX or DMA_RX for channel direction 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * maxdescr - number of descriptors 56874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 57373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_initctx(struct sbmacdma *d, struct sbmac_softc *s, int chan, 57473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int txrx, int maxdescr) 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 576693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#ifdef CONFIG_SBMAC_COALESCE 577693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason int int_pktcnt, int_timeout; 578693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#endif 579693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 58074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 58174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Save away interesting stuff in the structure 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 58374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_eth = s; 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_channel = chan; 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_txdir = txrx; 58774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* RMON clearing */ 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING; 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 593f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_BYTES); 594f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_COLLISIONS); 595f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_LATE_COL); 596f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_EX_COL); 597f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_FCS_ERROR); 598f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_ABORT); 599f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_BAD); 600f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_GOOD); 601f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_RUNT); 602f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_OVERSIZE); 603f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BYTES); 604f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_MCAST); 605f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BCAST); 606f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BAD); 607f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_GOOD); 608f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_RUNT); 609f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_OVERSIZE); 610f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_FCS_ERROR); 611f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_LENGTH_ERROR); 612f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_CODE_ERROR); 613f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_ALIGN_ERROR); 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 61674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * initialize register pointers 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 61874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 61974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle d->sbdma_config0 = 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0); 62174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle d->sbdma_config1 = 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1); 62374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle d->sbdma_dscrbase = 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE); 62574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle d->sbdma_dscrcnt = 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT); 62774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle d->sbdma_curdscr = 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR); 629693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (d->sbdma_txdir) 630693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason d->sbdma_oodpktlost = NULL; 631693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason else 632693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason d->sbdma_oodpktlost = 633693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_OODPKTLOST_RX); 63474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate memory for the ring 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 63874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_maxdescr = maxdescr; 64074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 64173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki d->sbdma_dscrtable_unaligned = kcalloc(d->sbdma_maxdescr + 1, 64273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki sizeof(*d->sbdma_dscrtable), 64373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki GFP_KERNEL); 64404115def6ad7ef51440365b65a7324fcb82d5d1dRalf Baechle 64504115def6ad7ef51440365b65a7324fcb82d5d1dRalf Baechle /* 64604115def6ad7ef51440365b65a7324fcb82d5d1dRalf Baechle * The descriptor table must be aligned to at least 16 bytes or the 64704115def6ad7ef51440365b65a7324fcb82d5d1dRalf Baechle * MAC will corrupt it. 64804115def6ad7ef51440365b65a7324fcb82d5d1dRalf Baechle */ 64973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki d->sbdma_dscrtable = (struct sbdmadscr *) 65073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki ALIGN((unsigned long)d->sbdma_dscrtable_unaligned, 65173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki sizeof(*d->sbdma_dscrtable)); 65274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr; 65474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_dscrtable_phys = virt_to_phys(d->sbdma_dscrtable); 65674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * And context table 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 66074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 661c477f3348abb5f6fb8b627cfdb1d7ae4b8fe613bMariusz Kozlowski d->sbdma_ctxtable = kcalloc(d->sbdma_maxdescr, 66273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki sizeof(*d->sbdma_ctxtable), GFP_KERNEL); 66374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SBMAC_COALESCE 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Setup Rx/Tx DMA coalescing defaults 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 669693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason int_pktcnt = (txrx == DMA_TX) ? int_pktcnt_tx : int_pktcnt_rx; 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ( int_pktcnt ) { 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_int_pktcnt = int_pktcnt; 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_int_pktcnt = 1; 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 67574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 676693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason int_timeout = (txrx == DMA_TX) ? int_timeout_tx : int_timeout_rx; 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ( int_timeout ) { 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_int_timeout = int_timeout; 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_int_timeout = 0; 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_CHANNEL_START(d) 68874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize the hardware registers for a DMA channel. 69074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 69174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * d - DMA channel to init (context must be previously init'd 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * rxtx - DMA_RX or DMA_TX depending on what type of channel 69474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 69973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_channel_start(struct sbmacdma *d, int rxtx) 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Turn on the DMA channel 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 70474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SBMAC_COALESCE 7062039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) | 7072039973af59889fea0d14362eae56792cfe8d25aRalf Baechle 0, d->sbdma_config1); 7082039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(M_DMA_EOP_INT_EN | 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_DMA_RINGSZ(d->sbdma_maxdescr) | 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_DMA_INT_PKTCNT(d->sbdma_int_pktcnt) | 7112039973af59889fea0d14362eae56792cfe8d25aRalf Baechle 0, d->sbdma_config0); 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 7132039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, d->sbdma_config1); 7142039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(V_DMA_RINGSZ(d->sbdma_maxdescr) | 7152039973af59889fea0d14362eae56792cfe8d25aRalf Baechle 0, d->sbdma_config0); 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7182039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(d->sbdma_dscrtable_phys, d->sbdma_dscrbase); 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize ring pointers 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_addptr = d->sbdma_dscrtable; 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_remptr = d->sbdma_dscrtable; 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_CHANNEL_STOP(d) 73074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize the hardware registers for a DMA channel. 73274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 73374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * d - DMA channel to init (context must be previously init'd 73574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 74073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_channel_stop(struct sbmacdma *d) 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Turn off the DMA channel 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 74574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7462039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, d->sbdma_config1); 74774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7482039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, d->sbdma_dscrbase); 74974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7502039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, d->sbdma_config0); 75174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Zero ring pointers 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 75574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7562039973af59889fea0d14362eae56792cfe8d25aRalf Baechle d->sbdma_addptr = NULL; 7572039973af59889fea0d14362eae56792cfe8d25aRalf Baechle d->sbdma_remptr = NULL; 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 760789585e968f07653a29a9e829aed20386043636cStephen Hemmingerstatic inline void sbdma_align_skb(struct sk_buff *skb, 761789585e968f07653a29a9e829aed20386043636cStephen Hemminger unsigned int power2, unsigned int offset) 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 763789585e968f07653a29a9e829aed20386043636cStephen Hemminger unsigned char *addr = skb->data; 764789585e968f07653a29a9e829aed20386043636cStephen Hemminger unsigned char *newaddr = PTR_ALIGN(addr, power2); 76574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 766789585e968f07653a29a9e829aed20386043636cStephen Hemminger skb_reserve(skb, newaddr - addr + offset); 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_ADD_RCVBUFFER(d,sb) 77274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Add a buffer to the specified DMA channel. For receive channels, 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this queues a buffer for inbound packets. 77574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 77674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 777789585e968f07653a29a9e829aed20386043636cStephen Hemminger * sc - softc structure 778789585e968f07653a29a9e829aed20386043636cStephen Hemminger * d - DMA channel descriptor 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sb - sk_buff to add, or NULL if we should allocate one 78074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 if buffer could not be added (ring is full) 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 if buffer added successfully 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 787789585e968f07653a29a9e829aed20386043636cStephen Hemmingerstatic int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d, 788789585e968f07653a29a9e829aed20386043636cStephen Hemminger struct sk_buff *sb) 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 790789585e968f07653a29a9e829aed20386043636cStephen Hemminger struct net_device *dev = sc->sbm_dev; 79173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *dsc; 79273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *nextdsc; 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *sb_new = NULL; 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int pktsize = ENET_PACKET_SIZE; 79574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get pointer to our current place in the ring */ 79774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dsc = d->sbdma_addptr; 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr); 80074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * figure out if the ring is full - if the next descriptor 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is the same as the one that we're going to remove from 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the ring, the ring is full 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 80674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nextdsc == d->sbdma_remptr) { 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOSPC; 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 81174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 81274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Allocate a sk_buff if we don't already have one. 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If we do have an sk_buff, reset it so that it's empty. 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: sk_buffs don't seem to be guaranteed to have any sort 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of alignment when they are allocated. Therefore, allocate enough 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * extra space to make sure that: 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1. the data does not start in the middle of a cache line. 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. The data does not end in the middle of a cache line 82174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 3. The buffer can be aligned such that the IP addresses are 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * naturally aligned. 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Remember, the SOCs MAC writes whole cache lines at a time, 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * without reading the old contents first. So, if the sk_buff's 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data portion starts in the middle of a cache line, the SOC 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DMA will trash the beginning (and ending) portions. 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 82974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sb == NULL) { 831789585e968f07653a29a9e829aed20386043636cStephen Hemminger sb_new = netdev_alloc_skb(dev, ENET_PACKET_SIZE + 832789585e968f07653a29a9e829aed20386043636cStephen Hemminger SMP_CACHE_BYTES * 2 + 833789585e968f07653a29a9e829aed20386043636cStephen Hemminger NET_IP_ALIGN); 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sb_new == NULL) { 835f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_info("%s: sk_buff allocation failed\n", 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_eth->sbm_dev->name); 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOBUFS; 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 840789585e968f07653a29a9e829aed20386043636cStephen Hemminger sbdma_align_skb(sb_new, SMP_CACHE_BYTES, NET_IP_ALIGN); 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb_new = sb; 84474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing special to reinit buffer, it's already aligned 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and sb->data already points to a good place. 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 84974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 85174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * fill in the descriptor 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 85374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SBMAC_COALESCE 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Do not interrupt per DMA transfer. 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 858689be43945e9ca7dd704522e55af1b8a73a994d3David S. Miller dsc->dscr_a = virt_to_phys(sb_new->data) | 859789585e968f07653a29a9e829aed20386043636cStephen Hemminger V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize + NET_IP_ALIGN)) | 0; 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 861689be43945e9ca7dd704522e55af1b8a73a994d3David S. Miller dsc->dscr_a = virt_to_phys(sb_new->data) | 862789585e968f07653a29a9e829aed20386043636cStephen Hemminger V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize + NET_IP_ALIGN)) | 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_DMA_DSCRA_INTERRUPT; 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* receiving: no options */ 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dsc->dscr_b = 0; 86874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 87074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * fill in the context 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 87274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb_new; 87474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 87574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 87674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * point at next packet 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 87874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_addptr = nextdsc; 88074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 88174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Give the buffer to the DMA engine. 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 88474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8852039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(1, d->sbdma_dscrcnt); 88674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* we did it */ 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_ADD_TXBUFFER(d,sb) 89274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Add a transmit buffer to the specified DMA channel, causing a 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transmit to start. 89574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 89674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * d - DMA channel descriptor 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sb - sk_buff to add 89974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 transmit queued successfully 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * otherwise error code 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 90673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbdma_add_txbuffer(struct sbmacdma *d, struct sk_buff *sb) 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 90873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *dsc; 90973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *nextdsc; 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t phys; 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t ncb; 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int length; 91374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get pointer to our current place in the ring */ 91574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dsc = d->sbdma_addptr; 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr); 91874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * figure out if the ring is full - if the next descriptor 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is the same as the one that we're going to remove from 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the ring, the ring is full 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 92474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nextdsc == d->sbdma_remptr) { 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOSPC; 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 92874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Under Linux, it's not necessary to copy/coalesce buffers 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * like it is on NetBSD. We think they're all contiguous, 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but that may not be true for GBE. 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 93474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds length = sb->len; 93674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fill in the descriptor. Note that the number of cache 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * blocks in the descriptor is the number of blocks 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * *spanned*, so we need to add in the offset (if any) 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * while doing the calculation. 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 94374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phys = virt_to_phys(sb->data); 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ncb = NUMCACHEBLKS(length+(phys & (SMP_CACHE_BYTES - 1))); 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 94774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle dsc->dscr_a = phys | 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_DMA_DSCRA_A_SIZE(ncb) | 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_SBMAC_COALESCE 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_DMA_DSCRA_INTERRUPT | 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_DMA_ETHTX_SOP; 95374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* transmitting: set outbound options and length */ 9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) | 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_DMA_DSCRB_PKT_SIZE(length); 95874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 96074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * fill in the context 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 96274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb; 96474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 96574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 96674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * point at next packet 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 96874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_addptr = nextdsc; 97074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 97174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Give the buffer to the DMA engine. 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 97474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9752039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(1, d->sbdma_dscrcnt); 97674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* we did it */ 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_EMPTYRING(d) 98574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Free all allocated sk_buffs on the specified DMA channel; 98774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 98874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * d - DMA channel 99074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 99573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_emptyring(struct sbmacdma *d) 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int idx; 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *sb; 99974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < d->sbdma_maxdescr; idx++) { 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb = d->sbdma_ctxtable[idx]; 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sb) { 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb(sb); 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_ctxtable[idx] = NULL; 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_FILLRING(d) 101274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fill the specified DMA channel (must be receive channel) 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with sk_buffs 101574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 101674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 1017789585e968f07653a29a9e829aed20386043636cStephen Hemminger * sc - softc structure 1018789585e968f07653a29a9e829aed20386043636cStephen Hemminger * d - DMA channel 101974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1024789585e968f07653a29a9e829aed20386043636cStephen Hemmingerstatic void sbdma_fillring(struct sbmac_softc *sc, struct sbmacdma *d) 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int idx; 102774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1028789585e968f07653a29a9e829aed20386043636cStephen Hemminger for (idx = 0; idx < SBMAC_MAX_RXDESCR - 1; idx++) { 1029789585e968f07653a29a9e829aed20386043636cStephen Hemminger if (sbdma_add_rcvbuffer(sc, d, NULL) != 0) 10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1034d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena#ifdef CONFIG_NET_POLL_CONTROLLER 1035d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxenastatic void sbmac_netpoll(struct net_device *netdev) 1036d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena{ 1037d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena struct sbmac_softc *sc = netdev_priv(netdev); 1038d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena int irq = sc->sbm_dev->irq; 1039d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena 1040d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena __raw_writeq(0, sc->sbm_imr); 1041d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena 10420da2f0f164f098bb4447c714b552ac1681b2d6e8Yoann Padioleau sbmac_intr(irq, netdev); 1043d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena 1044d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena#ifdef CONFIG_SBMAC_COALESCE 1045d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | 1046d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), 1047d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena sc->sbm_imr); 1048d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena#else 10497d2e3cb7000b883a8e489485ac249be572fe17b1Jeff Garzik __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) | 1050d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), sc->sbm_imr); 1051d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena#endif 1052d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena} 1053d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena#endif 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 1056693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * SBDMA_RX_PROCESS(sc,d,work_to_do,poll) 105774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 105874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Process "completed" receive buffers on the specified DMA channel. 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 106074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 1061693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * sc - softc structure 1062693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * d - DMA channel context 1063693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * work_to_do - no. of packets to process before enabling interrupt 1064693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * again (for NAPI) 1065693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * poll - 1: using polling (for NAPI) 106674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 107173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbdma_rx_process(struct sbmac_softc *sc, struct sbmacdma *d, 107273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int work_to_do, int poll) 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 107409f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik struct net_device *dev = sc->sbm_dev; 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int curidx; 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int hwidx; 107773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *dsc; 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *sb; 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 1080693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason int work_done = 0; 1081693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason int dropped = 0; 108274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1083693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason prefetch(d); 1084693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 1085693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonagain: 1086693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason /* Check if the HW dropped any frames */ 108709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_fifo_errors 1088693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason += __raw_readq(sc->sbm_rxdma.sbdma_oodpktlost) & 0xffff; 1089693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason __raw_writeq(0, sc->sbm_rxdma.sbdma_oodpktlost); 1090693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 1091693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason while (work_to_do-- > 0) { 109274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * figure out where we are (as an index) and where 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the hardware is (also as an index) 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 109674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * This could be done faster if (for example) the 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * descriptor table was page-aligned and contiguous in 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * both virtual and physical memory -- you could then 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * just compare the low-order bits of the virtual address 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (sbdma_remptr) and the physical address (sbdma_curdscr CSR) 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 110274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1103693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason dsc = d->sbdma_remptr; 1104693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason curidx = dsc - d->sbdma_dscrtable; 1105693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 1106693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason prefetch(dsc); 1107693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason prefetch(&d->sbdma_ctxtable[curidx]); 1108693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 110973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki hwidx = ((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) - 111073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki d->sbdma_dscrtable_phys) / 111173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki sizeof(*d->sbdma_dscrtable); 111274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If they're the same, that means we've processed all 11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the descriptors up to (but not including) the one that 11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the hardware is working on right now. 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 111874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (curidx == hwidx) 1120693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason goto done; 112174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Otherwise, get the packet's sk_buff ptr back 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 112574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb = d->sbdma_ctxtable[curidx]; 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_ctxtable[curidx] = NULL; 112874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b) - 4; 113074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check packet status. If good, process it. 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If not, silently drop it and put it back on the 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * receive ring. 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 113674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1137693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (likely (!(dsc->dscr_a & M_DMA_ETHRX_BAD))) { 113874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Add a new buffer to replace the old one. If we fail 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to allocate a buffer, we're going to drop this 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * packet and put it right back on the receive ring. 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 114474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1145789585e968f07653a29a9e829aed20386043636cStephen Hemminger if (unlikely(sbdma_add_rcvbuffer(sc, d, NULL) == 1146789585e968f07653a29a9e829aed20386043636cStephen Hemminger -ENOBUFS)) { 114709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_dropped++; 1148789585e968f07653a29a9e829aed20386043636cStephen Hemminger /* Re-add old buffer */ 1149789585e968f07653a29a9e829aed20386043636cStephen Hemminger sbdma_add_rcvbuffer(sc, d, sb); 1150693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason /* No point in continuing at the moment */ 1151693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason printk(KERN_ERR "dropped packet (1)\n"); 1152693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); 1153693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason goto done; 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set length into the packet 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_put(sb,len); 115974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Buffer has been replaced on the 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * receive ring. Pass the buffer to 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the kernel 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb->protocol = eth_type_trans(sb,d->sbdma_eth->sbm_dev); 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check hw IPv4/TCP checksum if supported */ 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sc->rx_hw_checksum == ENABLE) { 11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!((dsc->dscr_a) & M_DMA_ETHRX_BADIP4CS) && 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !((dsc->dscr_a) & M_DMA_ETHRX_BADTCPCS)) { 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb->ip_summed = CHECKSUM_UNNECESSARY; 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't need to set sb->csum */ 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1173bc8acf2c8c3e43fcc192762a9f964b3e9a17748bEric Dumazet skb_checksum_none_assert(sb); 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1176693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason prefetch(sb->data); 1177693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason prefetch((const void *)(((char *)sb->data)+32)); 1178693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (poll) 1179693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason dropped = netif_receive_skb(sb); 1180693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason else 1181693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason dropped = netif_rx(sb); 1182693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 1183693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (dropped == NET_RX_DROP) { 118409f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_dropped++; 1185693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); 1186693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason goto done; 1187693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason } 1188693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason else { 118909f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_bytes += len; 119009f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_packets++; 1191693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason } 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Packet was mangled somehow. Just drop it and 11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * put it back on the receive ring. 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 119809f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_errors++; 1199789585e968f07653a29a9e829aed20386043636cStephen Hemminger sbdma_add_rcvbuffer(sc, d, sb); 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 120174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 120274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 120374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * .. and advance to the next buffer. 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 120674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); 1208693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason work_done++; 1209693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason } 1210693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (!poll) { 1211693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason work_to_do = 32; 1212693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason goto again; /* collect fifo drop statistics again */ 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1214693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masondone: 1215693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason return work_done; 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_TX_PROCESS(sc,d) 122074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 122174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Process "completed" transmit buffers on the specified DMA channel. 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is normally called within the interrupt service routine. 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that this isn't really ideal for priority channels, since 122474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * it processes all of the packets on a given channel before 122574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * returning. 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 122774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sc - softc structure 1229693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * d - DMA channel context 1230693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * poll - 1: using polling (for NAPI) 123174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 123673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d, 123773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int poll) 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 123909f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik struct net_device *dev = sc->sbm_dev; 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int curidx; 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int hwidx; 124273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *dsc; 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *sb; 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 1245693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason int packets_handled = 0; 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&(sc->sbm_lock), flags); 124874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1249693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (d->sbdma_remptr == d->sbdma_addptr) 1250693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason goto end_unlock; 1251693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 125273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki hwidx = ((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) - 125373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki d->sbdma_dscrtable_phys) / sizeof(*d->sbdma_dscrtable); 1254693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (;;) { 125674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * figure out where we are (as an index) and where 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the hardware is (also as an index) 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 126074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * This could be done faster if (for example) the 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * descriptor table was page-aligned and contiguous in 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * both virtual and physical memory -- you could then 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * just compare the low-order bits of the virtual address 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (sbdma_remptr) and the physical address (sbdma_curdscr CSR) 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 126674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds curidx = d->sbdma_remptr - d->sbdma_dscrtable; 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If they're the same, that means we've processed all 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the descriptors up to (but not including) the one that 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the hardware is working on right now. 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 127474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (curidx == hwidx) 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 127774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Otherwise, get the packet's sk_buff ptr back 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 128174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dsc = &(d->sbdma_dscrtable[curidx]); 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb = d->sbdma_ctxtable[curidx]; 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_ctxtable[curidx] = NULL; 128574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Stats 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 128974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 129009f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_bytes += sb->len; 129109f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_packets++; 129274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for transmits, we just free buffers. 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 129674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb_irq(sb); 129874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 129974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * .. and advance to the next buffer. 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); 130474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1305693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason packets_handled++; 1306693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 130874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Decide if we should wake up the protocol or not. 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Other drivers seem to do this when we reach a low 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * watermark on the transmit queue. 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 131474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1315693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (packets_handled) 1316693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason netif_wake_queue(d->sbdma_eth->sbm_dev); 131774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1318693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonend_unlock: 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&(sc->sbm_lock), flags); 132074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_INITCTX(s) 132774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize an Ethernet context structure - this is called 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * once per MAC on the 1250. Memory is allocated here, so don't 13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * call it again from inside the ioctl routines that bring the 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * interface up/down 133274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 133374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * s - sbmac context structure 133574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_initctx(struct sbmac_softc *s) 13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 134274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 134374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 134474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * figure out the addresses of some ports 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 134674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_macenable = s->sbm_base + R_MAC_ENABLE; 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_maccfg = s->sbm_base + R_MAC_CFG; 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_fifocfg = s->sbm_base + R_MAC_THRSH_CFG; 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_framecfg = s->sbm_base + R_MAC_FRAMECFG; 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_rxfilter = s->sbm_base + R_MAC_ADFILTER_CFG; 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_isr = s->sbm_base + R_MAC_STATUS; 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_imr = s->sbm_base + R_MAC_INT_MASK; 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_mdio = s->sbm_base + R_MAC_MDIO; 13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize the DMA channels. Right now, only one per MAC is used 13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: Only do this _once_, as it allocates memory from the kernel! 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 136074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_initctx(&(s->sbm_txdma),s,0,DMA_TX,SBMAC_MAX_TXDESCR); 13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_initctx(&(s->sbm_rxdma),s,0,DMA_RX,SBMAC_MAX_RXDESCR); 136374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * initial state is OFF 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 136774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_state = sbmac_state_off; 136974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 137473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_uninitctx(struct sbmacdma *d) 13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1376693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (d->sbdma_dscrtable_unaligned) { 1377693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason kfree(d->sbdma_dscrtable_unaligned); 1378693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason d->sbdma_dscrtable_unaligned = d->sbdma_dscrtable = NULL; 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 138074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (d->sbdma_ctxtable) { 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(d->sbdma_ctxtable); 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_ctxtable = NULL; 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_uninitctx(struct sbmac_softc *sc) 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_uninitctx(&(sc->sbm_txdma)); 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_uninitctx(&(sc->sbm_rxdma)); 13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_CHANNEL_START(s) 139774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Start packet processing on this MAC. 139974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 140074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * s - sbmac structure 140274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_channel_start(struct sbmac_softc *s) 14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t reg; 141073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *port; 14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t cfg,fifo,framecfg; 14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int idx, th_value; 141374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Don't do this if running 14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s->sbm_state == sbmac_state_on) 14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 142074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bring the controller out of reset, but leave it off. 14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 142474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14252039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, s->sbm_macenable); 142674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ignore all received packets 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 143074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14312039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, s->sbm_rxfilter); 143274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 143374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Calculate values for various control registers. 14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 143674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg = M_MAC_RETRY_EN | 143874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle M_MAC_TX_HOLD_SOP_EN | 14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_TX_PAUSE_CNT_16K | 14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_MAC_AP_STAT_EN | 14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_MAC_FAST_SYNC | 14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_MAC_SS_EN | 14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0; 144474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 144574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Be sure that RD_THRSH+WR_THRSH <= 32 for pass1 pars 14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above 14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Use a larger RD_THRSH for gigabit 14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1450f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2) 14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds th_value = 28; 1452f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle else 1453f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle th_value = 64; 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */ 14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((s->sbm_speed == sbmac_speed_1000) 14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ? V_MAC_TX_RD_THRSH(th_value) : V_MAC_TX_RD_THRSH(4)) | 14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_TX_RL_THRSH(4) | 14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_RX_PL_THRSH(4) | 14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_RX_RD_THRSH(4) | /* Must be '4' */ 14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_RX_RL_THRSH(8) | 14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0; 14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framecfg = V_MAC_MIN_FRAMESZ_DEFAULT | 14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_MAX_FRAMESZ_DEFAULT | 14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_BACKOFF_SEL(1); 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 146974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Clear out the hash address map 14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 147174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = s->sbm_base + R_MAC_HASH_BASE; 14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < MAC_HASH_COUNT; idx++) { 14742039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, port); 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port += sizeof(uint64_t); 14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 147774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Clear out the exact-match table 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 148174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = s->sbm_base + R_MAC_ADDR_BASE; 14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < MAC_ADDR_COUNT; idx++) { 14842039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, port); 14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port += sizeof(uint64_t); 14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 148774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Clear out the DMA Channel mapping table registers 14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 149174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = s->sbm_base + R_MAC_CHUP0_BASE; 14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { 14942039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, port); 14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port += sizeof(uint64_t); 14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = s->sbm_base + R_MAC_CHLO0_BASE; 15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { 15012039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, port); 15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port += sizeof(uint64_t); 15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 150474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Program the hardware address. It goes into the hardware-address 15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * register as well as the first filter register. 15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 150974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg = sbmac_addr2reg(s->sbm_hwaddr); 151174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = s->sbm_base + R_MAC_ADDR_BASE; 15132039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, port); 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = s->sbm_base + R_MAC_ETHERNET_ADDR; 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS 15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Pass1 SOCs do not receive packets addressed to the 15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * destination address in the R_MAC_ETHERNET_ADDR register. 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the value to zero. 15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15222039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, port); 15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 15242039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, port); 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 152674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the receive filter for no packets, and write values 15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the various config registers 15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 153174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15322039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, s->sbm_rxfilter); 15332039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, s->sbm_imr); 15342039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(framecfg, s->sbm_framecfg); 15352039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(fifo, s->sbm_fifocfg); 15362039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(cfg, s->sbm_maccfg); 153774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize DMA channels (rings should be ok now) 15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 154174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_channel_start(&(s->sbm_rxdma), DMA_RX); 15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_channel_start(&(s->sbm_txdma), DMA_TX); 154474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Configure the speed, duplex, and flow control 15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_set_speed(s,s->sbm_speed); 15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_set_duplex(s,s->sbm_duplex,s->sbm_fc); 155174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fill the receive ring 15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 155574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1556789585e968f07653a29a9e829aed20386043636cStephen Hemminger sbdma_fillring(s, &(s->sbm_rxdma)); 155774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 155874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Turn on the rest of the bits in the enable register 156074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle */ 156174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1562f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) 1563f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle __raw_writeq(M_MAC_RXDMA_EN0 | 1564f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle M_MAC_TXDMA_EN0, s->sbm_macenable); 1565f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) 15662039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(M_MAC_RXDMA_EN0 | 15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_MAC_TXDMA_EN0 | 15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_MAC_RX_ENABLE | 15692039973af59889fea0d14362eae56792cfe8d25aRalf Baechle M_MAC_TX_ENABLE, s->sbm_macenable); 1570f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#else 15710b1974de66f9ed44f1423449628f4926bf95b854Thomas Weber#error invalid SiByte MAC configuration 1572f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#endif 15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SBMAC_COALESCE 15752039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | 15762039973af59889fea0d14362eae56792cfe8d25aRalf Baechle ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), s->sbm_imr); 15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 15782039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) | 15792039973af59889fea0d14362eae56792cfe8d25aRalf Baechle (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), s->sbm_imr); 15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 158174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 158274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 158374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Enable receiving unicasts and broadcasts 15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 158574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15862039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(M_MAC_UCAST_EN | M_MAC_BCAST_EN, s->sbm_rxfilter); 158774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 158974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * we're running now. 15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 159174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_state = sbmac_state_on; 159374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 159474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 159574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Program multicast addresses 15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 159774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_setmulti(s); 159974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 160074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 160174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * If channel was in promiscuous mode before, turn that on 16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 160374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s->sbm_devflags & IFF_PROMISC) { 16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_promiscuous_mode(s,1); 16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 160774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_CHANNEL_STOP(s) 161374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Stop packet processing on this MAC. 161574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 161674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * s - sbmac structure 161874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_channel_stop(struct sbmac_softc *s) 16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't do this if already stopped */ 162674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s->sbm_state == sbmac_state_off) 16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 162974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't accept any packets, disable all interrupts */ 163174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16322039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, s->sbm_rxfilter); 16332039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, s->sbm_imr); 163474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Turn off ticker */ 163674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XXX */ 163874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn off receiver and transmitter */ 164074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16412039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, s->sbm_macenable); 164274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We're stopped now. */ 164474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_state = sbmac_state_off; 164674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Stop DMA channels (rings should be ok now) 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 165074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_channel_stop(&(s->sbm_rxdma)); 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_channel_stop(&(s->sbm_txdma)); 165374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Empty the receive and transmit rings */ 165574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_emptyring(&(s->sbm_rxdma)); 16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_emptyring(&(s->sbm_txdma)); 165874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_SET_CHANNEL_STATE(state) 166374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the channel's state ON or OFF 166574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 166674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * state - new state 166874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * old state 16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 167273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic enum sbmac_state sbmac_set_channel_state(struct sbmac_softc *sc, 167373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_state state) 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 167573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_state oldstate = sc->sbm_state; 167674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If same as previous state, return 16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 168074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state == oldstate) { 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return oldstate; 16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 168474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 168674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * If new state is ON, turn channel on 16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 168874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state == sbmac_state_on) { 16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_channel_start(sc); 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_channel_stop(sc); 16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 169574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return previous state 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 169974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return oldstate; 17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_PROMISCUOUS_MODE(sc,onoff) 170674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Turn on or off promiscuous mode 170874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 170974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sc - softc 17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * onoff - 1 to turn on, 0 to turn off 171274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff) 17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t reg; 172074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sc->sbm_state != sbmac_state_on) 17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 172374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (onoff) { 17252039973af59889fea0d14362eae56792cfe8d25aRalf Baechle reg = __raw_readq(sc->sbm_rxfilter); 17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= M_MAC_ALLPKT_EN; 17272039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, sc->sbm_rxfilter); 172874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle } 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 17302039973af59889fea0d14362eae56792cfe8d25aRalf Baechle reg = __raw_readq(sc->sbm_rxfilter); 17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg &= ~M_MAC_ALLPKT_EN; 17322039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, sc->sbm_rxfilter); 17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_SETIPHDR_OFFSET(sc,onoff) 173874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the iphdr offset as 15 assuming ethernet encapsulation 174074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 174174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sc - softc 174374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_set_iphdr_offset(struct sbmac_softc *sc) 17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t reg; 175174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Hard code the off set to 15 for now */ 17532039973af59889fea0d14362eae56792cfe8d25aRalf Baechle reg = __raw_readq(sc->sbm_rxfilter); 17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15); 17552039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, sc->sbm_rxfilter); 175674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1757f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle /* BCM1250 pass1 didn't have hardware checksum. Everything 1758f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle later does. */ 1759f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2) { 17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sc->rx_hw_checksum = DISABLE; 1761f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle } else { 1762f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle sc->rx_hw_checksum = ENABLE; 17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_ADDR2REG(ptr) 176974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Convert six bytes into the 64-bit register value that 17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we typically write into the SBMAC's address/mcast registers 177274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 177374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ptr - pointer to 6 bytes 177574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * register value 17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic uint64_t sbmac_addr2reg(unsigned char *ptr) 17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t reg = 0; 178374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr += 6; 178574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 178674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle reg |= (uint64_t) *(--ptr); 17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg <<= 8; 178874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle reg |= (uint64_t) *(--ptr); 17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg <<= 8; 179074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle reg |= (uint64_t) *(--ptr); 17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg <<= 8; 179274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle reg |= (uint64_t) *(--ptr); 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg <<= 8; 179474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle reg |= (uint64_t) *(--ptr); 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg <<= 8; 179674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle reg |= (uint64_t) *(--ptr); 179774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return reg; 17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_SET_SPEED(s,speed) 180474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Configure LAN speed for the specified MAC. 18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Warning: must be called when MAC is off! 180774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 180874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * s - sbmac structure 181073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki * speed - speed to set MAC to (see enum sbmac_speed) 181174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 if successful 18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 indicates invalid parameters 18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbmac_set_speed(struct sbmac_softc *s, enum sbmac_speed speed) 18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t cfg; 18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t framecfg; 18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Save new current values 18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 182574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_speed = speed; 182774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s->sbm_state == sbmac_state_on) 18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* save for next restart */ 18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 183274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Read current register values 18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 183474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18352039973af59889fea0d14362eae56792cfe8d25aRalf Baechle cfg = __raw_readq(s->sbm_maccfg); 18362039973af59889fea0d14362eae56792cfe8d25aRalf Baechle framecfg = __raw_readq(s->sbm_framecfg); 183774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Mask out the stuff we want to change 18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 184174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL); 18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH | 18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_MAC_SLOT_SIZE); 184574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Now add in the new bits 18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 184974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (speed) { 18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_speed_10: 18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framecfg |= V_MAC_IFG_RX_10 | 18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_IFG_TX_10 | 18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds K_MAC_IFG_THRSH_10 | 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_SLOT_SIZE_10; 18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= V_MAC_SPEED_SEL_10MBPS; 18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 185874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_speed_100: 18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framecfg |= V_MAC_IFG_RX_100 | 18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_IFG_TX_100 | 18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_IFG_THRSH_100 | 18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_SLOT_SIZE_100; 18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= V_MAC_SPEED_SEL_100MBPS ; 18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 186674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_speed_1000: 18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framecfg |= V_MAC_IFG_RX_1000 | 18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_IFG_TX_1000 | 18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_IFG_THRSH_1000 | 18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_SLOT_SIZE_1000; 18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN; 18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 187474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 187874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 188074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Send the bits back to the hardware 18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 188274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18832039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(framecfg, s->sbm_framecfg); 18842039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(cfg, s->sbm_maccfg); 188574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_SET_DUPLEX(s,duplex,fc) 189174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set Ethernet duplex and flow control options for this MAC 18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Warning: must be called when MAC is off! 189474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 189574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * s - sbmac structure 189773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki * duplex - duplex setting (see enum sbmac_duplex) 189873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki * fc - flow control setting (see enum sbmac_fc) 189974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 if ok 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 if an invalid parameter combination was specified 19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 190573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbmac_set_duplex(struct sbmac_softc *s, enum sbmac_duplex duplex, 190673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_fc fc) 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t cfg; 190974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Save new current values 19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 191374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_duplex = duplex; 19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_fc = fc; 191674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s->sbm_state == sbmac_state_on) 19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* save for next restart */ 191974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 192174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Read current register values 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 192374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19242039973af59889fea0d14362eae56792cfe8d25aRalf Baechle cfg = __raw_readq(s->sbm_maccfg); 192574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Mask off the stuff we're about to change 19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 192974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN); 193174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 193274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (duplex) { 19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_duplex_half: 19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fc) { 19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_disabled: 19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED; 19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 193974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_collision: 19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED; 19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 194374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_carrier: 19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR; 19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 194774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_frame: /* not valid in half duplex */ 19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: /* invalid selection */ 19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 195374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_duplex_full: 19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fc) { 19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_disabled: 19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= V_MAC_FC_CMD_DISABLED; 19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 195974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_frame: 19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= V_MAC_FC_CMD_ENABLED; 19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 196374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_collision: /* not valid in full duplex */ 19651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_carrier: /* not valid in full duplex */ 19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 19681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1970f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki default: 1971f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return 0; 19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 197374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 197574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Send the bits back to the hardware 19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 197774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19782039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(cfg, s->sbm_maccfg); 197974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_INTR() 198874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Interrupt handler for MAC interrupts 199074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 199174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MAC structure 199374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 19977d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t sbmac_intr(int irq,void *dev_instance) 19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = (struct net_device *) dev_instance; 20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t isr; 20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int handled = 0; 20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2004693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason /* 2005693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * Read the ISR (this clears the bits in the real 2006693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * register, except for counter addr) 2007693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason */ 200874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2009693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason isr = __raw_readq(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR; 20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (isr == 0) 2012693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason return IRQ_RETVAL(0); 2013693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason handled = 1; 201474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2015693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason /* 2016693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * Transmits on channel 0 2017693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason */ 201874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2019bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) 2020693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason sbdma_tx_process(sc,&(sc->sbm_txdma), 0); 202174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2022693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) { 2023288379f050284087578b77e04f040b57db3db3f8Ben Hutchings if (napi_schedule_prep(&sc->napi)) { 2024693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason __raw_writeq(0, sc->sbm_imr); 2025288379f050284087578b77e04f040b57db3db3f8Ben Hutchings __napi_schedule(&sc->napi); 2026693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason /* Depend on the exit from poll to reenable intr */ 2027693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason } 2028693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason else { 2029693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason /* may leave some packets behind */ 2030693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason sbdma_rx_process(sc,&(sc->sbm_rxdma), 2031693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason SBMAC_MAX_RXDESCR * 2, 0); 20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_RETVAL(handled); 20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 20381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_START_TX(skb,dev) 203974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 204074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Start output on the specified interface. Basically, we 20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * queue as many buffers as we can until the ring fills up, or 20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we run off the end of the queue, whichever comes first. 204374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 204474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 204574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 204674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev) 20511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 2053be61ea52900b97800effbb68478915d73b5d4df2Weiwei Wang unsigned long flags; 205474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* lock eth irq */ 2056be61ea52900b97800effbb68478915d73b5d4df2Weiwei Wang spin_lock_irqsave(&sc->sbm_lock, flags); 205774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 205974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Put the buffer on the transmit ring. If we 20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * don't have room, stop the queue. 20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 206274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 20631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) { 20641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XXX save skb that we could not send */ 20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(dev); 2066be61ea52900b97800effbb68478915d73b5d4df2Weiwei Wang spin_unlock_irqrestore(&sc->sbm_lock, flags); 20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20685b548140225c6bbbbd560551dd1048b2c0ce58bePatrick McHardy return NETDEV_TX_BUSY; 20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 207074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2071be61ea52900b97800effbb68478915d73b5d4df2Weiwei Wang spin_unlock_irqrestore(&sc->sbm_lock, flags); 207274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 20736ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy return NETDEV_TX_OK; 20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 20771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_SETMULTI(sc) 207874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reprogram the multicast table into the hardware, given 20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the list of multicasts associated with the interface 20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * structure. 208274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 208374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 20841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sc - softc 208574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 20861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 20881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_setmulti(struct sbmac_softc *sc) 20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t reg; 209373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *port; 20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int idx; 209522bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko struct netdev_hw_addr *ha; 20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = sc->sbm_dev; 209774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 209874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Clear out entire multicast table. We do this by nuking 21001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the entire hash table and all the direct matches except 210174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * the first one, which is used for our station address 21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 210374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 1; idx < MAC_ADDR_COUNT; idx++) { 21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t)); 21062039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, port); 21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 210874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < MAC_HASH_COUNT; idx++) { 21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t)); 21112039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, port); 21121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 211374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Clear the filter to say we don't want any multicasts. 21161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 211774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21182039973af59889fea0d14362eae56792cfe8d25aRalf Baechle reg = __raw_readq(sc->sbm_rxfilter); 21191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg &= ~(M_MAC_MCAST_INV | M_MAC_MCAST_EN); 21202039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, sc->sbm_rxfilter); 212174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->flags & IFF_ALLMULTI) { 212374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 212474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Enable ALL multicasts. Do this by inverting the 212574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * multicast enable bit. 21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 21272039973af59889fea0d14362eae56792cfe8d25aRalf Baechle reg = __raw_readq(sc->sbm_rxfilter); 21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= (M_MAC_MCAST_INV | M_MAC_MCAST_EN); 21292039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, sc->sbm_rxfilter); 21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 213374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 213474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Progam new multicast entries. For now, only use the 21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * perfect filter. In the future we'll need to use the 21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hash filter if the perfect filter overflows 21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 213974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XXX only using perfect filter for now, need to use hash 21411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX if the table overflows */ 214274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds idx = 1; /* skip station address */ 214422bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko netdev_for_each_mc_addr(ha, dev) { 21455508590c193661bc1484ad7b952af5fceacea40dJiri Pirko if (idx == MAC_ADDR_COUNT) 21465508590c193661bc1484ad7b952af5fceacea40dJiri Pirko break; 214722bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko reg = sbmac_addr2reg(ha->addr); 21481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t)); 21492039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, port); 21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds idx++; 21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 215274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 215374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 21541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Enable the "accept multicast bits" if we programmed at least one 215574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * multicast. 21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 215774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (idx > 1) { 21592039973af59889fea0d14362eae56792cfe8d25aRalf Baechle reg = __raw_readq(sc->sbm_rxfilter); 21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= M_MAC_MCAST_EN; 21612039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, sc->sbm_rxfilter); 21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sb1250_change_mtu(struct net_device *_dev, int new_mtu) 21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_mtu > ENET_PACKET_SIZE) 21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds _dev->mtu = new_mtu; 2170f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_info("changing the mtu to %d\n", new_mtu); 21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2174b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalovstatic const struct net_device_ops sbmac_netdev_ops = { 2175b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_open = sbmac_open, 2176b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_stop = sbmac_close, 2177b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_start_xmit = sbmac_start_tx, 2178afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko .ndo_set_rx_mode = sbmac_set_rx_mode, 2179b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_tx_timeout = sbmac_tx_timeout, 2180b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_do_ioctl = sbmac_mii_ioctl, 2181b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_change_mtu = sb1250_change_mtu, 2182b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_validate_addr = eth_validate_addr, 2183b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_set_mac_address = eth_mac_addr, 2184b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov#ifdef CONFIG_NET_POLL_CONTROLLER 2185b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_poll_controller = sbmac_netpoll, 2186b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov#endif 2187b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov}; 2188b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov 21891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 21901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_INIT(dev) 219174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 21921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Attach routine - init hardware and hook ourselves into linux 219374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 219474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 21951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dev - net_device structure 219674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 21971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 21981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * status 21991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 22001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2201f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic int sbmac_init(struct platform_device *pldev, long long base) 22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2203c7ae011dc8306d982c25fb4f679752e790a08dc4Greg Kroah-Hartman struct net_device *dev = dev_get_drvdata(&pldev->dev); 2204f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int idx = pldev->id; 2205f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct sbmac_softc *sc = netdev_priv(dev); 22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *eaddr; 22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t ea_reg; 22081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 221074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 22111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sc->sbm_dev = dev; 22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sc->sbe_idx = idx; 221374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eaddr = sc->sbm_hwaddr; 221574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 221674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 2217877d03105d04b2c13e241130277fa69c8d2564f0Nick Andrew * Read the ethernet address. The firmware left this programmed 22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for us in the ethernet address register for each mac. 22191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 222074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 22212039973af59889fea0d14362eae56792cfe8d25aRalf Baechle ea_reg = __raw_readq(sc->sbm_base + R_MAC_ETHERNET_ADDR); 22222039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, sc->sbm_base + R_MAC_ETHERNET_ADDR); 22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 6; i++) { 22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eaddr[i] = (uint8_t) (ea_reg & 0xFF); 22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ea_reg >>= 8; 22261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 222774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 6; i++) { 22291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_addr[i] = eaddr[i]; 22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 223174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 223274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 22331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize context (get pointers to registers and stuff), then 22341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allocate the memory for the descriptor tables. 22351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 223674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 22371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_initctx(sc); 223874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set up Linux device callins 22411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 224274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 22431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&(sc->sbm_lock)); 224474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2245b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov dev->netdev_ops = &sbmac_netdev_ops; 2246b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov dev->watchdog_timeo = TX_TIMEOUT; 2247bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger 2248bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger netif_napi_add(dev, &sc->napi, sbmac_poll, 16); 22491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2250f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki dev->irq = UNIT_INT(idx); 2251f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 22521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This is needed for PASS2 for Rx H/W checksum feature */ 22531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_set_iphdr_offset(sc); 22541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2255298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek sc->mii_bus = mdiobus_alloc(); 2256298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek if (sc->mii_bus == NULL) { 225703f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior err = -ENOMEM; 225803f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior goto uninit_ctx; 2259298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek } 2260298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek 226103f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sc->mii_bus->name = sbmac_mdio_string; 2262446bbc4b5ee122c3a3a4954b144d031f0f9aa006Florian Fainelli snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", 2263446bbc4b5ee122c3a3a4954b144d031f0f9aa006Florian Fainelli pldev->name, idx); 226403f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sc->mii_bus->priv = sc; 226503f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sc->mii_bus->read = sbmac_mii_read; 226603f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sc->mii_bus->write = sbmac_mii_write; 226703f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sc->mii_bus->irq = sc->phy_irq; 226803f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior for (i = 0; i < PHY_MAX_ADDR; ++i) 226903f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sc->mii_bus->irq[i] = SBMAC_PHY_INT; 227003f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior 227103f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sc->mii_bus->parent = &pldev->dev; 227203f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior /* 227303f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior * Probe PHY address 227403f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior */ 227503f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior err = mdiobus_register(sc->mii_bus); 227603f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior if (err) { 227703f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior printk(KERN_ERR "%s: unable to register MDIO bus\n", 227803f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior dev->name); 227903f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior goto free_mdio; 228003f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior } 228103f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior dev_set_drvdata(&pldev->dev, sc->mii_bus); 228203f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior 22831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = register_netdev(dev); 2284f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (err) { 2285f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki printk(KERN_ERR "%s.%d: unable to register netdev\n", 2286f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_string, idx); 228703f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior goto unreg_mdio; 22881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2290f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_info("%s.%d: registered as %s\n", sbmac_string, idx, dev->name); 2291f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2292f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (sc->rx_hw_checksum == ENABLE) 2293f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_info("%s: enabling TCP rcv checksum\n", dev->name); 2294f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 22951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 22961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Display Ethernet address (this is called during the config 22971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * process so we need to finish off the config message that 22981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * was being displayed) 22991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2300e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %pM\n", 2301e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg dev->name, base, eaddr); 23021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2303f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return 0; 230403f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewiorunreg_mdio: 230503f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior mdiobus_unregister(sc->mii_bus); 230603f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior dev_set_drvdata(&pldev->dev, NULL); 230703f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewiorfree_mdio: 230803f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior mdiobus_free(sc->mii_bus); 230903f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewioruninit_ctx: 231003f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sbmac_uninitctx(sc); 231103f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior return err; 23121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 23131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_open(struct net_device *dev) 23161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 23171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 2318f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int err; 231974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2320f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (debug > 1) 2321f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_debug("%s: sbmac_open() irq %d.\n", dev->name, dev->irq); 232274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 232374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 23241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * map/route interrupt (clear status first, in case something 23251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * weird is pending; we haven't initialized the mac registers 23261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * yet) 23271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 23281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23292039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_readq(sc->sbm_isr); 2330a0607fd3a25ba1848a63a0d925e36d914735ab47Joe Perches err = request_irq(dev->irq, sbmac_intr, IRQF_SHARED, dev->name, dev); 2331f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (err) { 2332f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name, 2333f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki dev->irq); 2334f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki goto out_err; 2335f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki } 23361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2337f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_speed = sbmac_speed_none; 2338f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_duplex = sbmac_duplex_none; 2339f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_fc = sbmac_fc_none; 2340f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_pause = -1; 2341f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_link = 0; 2342bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger 234359b81827071a8ae7f399da533d268e1e33bfeeb7Ralf Baechle /* 2344f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * Attach to the PHY 23451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2346f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki err = sbmac_mii_probe(dev); 2347f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (err) 2348f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki goto out_unregister; 234974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 23501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 23511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Turn on the channel 23521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 23531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_set_channel_state(sc,sbmac_state_on); 235574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 23561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_start_queue(dev); 235774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 23581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_set_rx_mode(dev); 235974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2360f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki phy_start(sc->phy_dev); 2361f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2362f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki napi_enable(&sc->napi); 236374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 23641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2365f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2366f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckiout_unregister: 2367f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki free_irq(dev->irq, dev); 2368f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckiout_err: 2369f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return err; 23701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 23711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 237259b81827071a8ae7f399da533d268e1e33bfeeb7Ralf Baechlestatic int sbmac_mii_probe(struct net_device *dev) 237359b81827071a8ae7f399da533d268e1e33bfeeb7Ralf Baechle{ 2374f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct sbmac_softc *sc = netdev_priv(dev); 2375f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct phy_device *phy_dev; 237659b81827071a8ae7f399da533d268e1e33bfeeb7Ralf Baechle int i; 23771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2378f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki for (i = 0; i < PHY_MAX_ADDR; i++) { 2379298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek phy_dev = sc->mii_bus->phy_map[i]; 2380f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (phy_dev) 2381f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki break; 23821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2383f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (!phy_dev) { 2384f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki printk(KERN_ERR "%s: no PHY found\n", dev->name); 2385f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return -ENXIO; 23861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2388db1d7bf70f42124f73675fca62fe32f3ab1111b4Kay Sievers phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), &sbmac_mii_poll, 0, 2389f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki PHY_INTERFACE_MODE_GMII); 2390f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (IS_ERR(phy_dev)) { 2391f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki printk(KERN_ERR "%s: could not attach to PHY\n", dev->name); 2392f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return PTR_ERR(phy_dev); 23931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2395f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki /* Remove any features not supported by the controller */ 2396f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki phy_dev->supported &= SUPPORTED_10baseT_Half | 2397f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_10baseT_Full | 2398f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_100baseT_Half | 2399f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_100baseT_Full | 2400f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_1000baseT_Half | 2401f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_1000baseT_Full | 2402f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_Autoneg | 2403f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_MII | 2404f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_Pause | 2405f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_Asym_Pause; 2406f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki phy_dev->advertising = phy_dev->supported; 2407f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2408f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", 2409f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki dev->name, phy_dev->drv->name, 2410db1d7bf70f42124f73675fca62fe32f3ab1111b4Kay Sievers dev_name(&phy_dev->dev), phy_dev->irq); 2411f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2412f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->phy_dev = phy_dev; 24131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2414f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return 0; 24151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2418f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic void sbmac_mii_poll(struct net_device *dev) 24191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 2421f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct phy_device *phy_dev = sc->phy_dev; 2422f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki unsigned long flags; 2423f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki enum sbmac_fc fc; 2424f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int link_chg, speed_chg, duplex_chg, pause_chg, fc_chg; 2425f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2426f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki link_chg = (sc->sbm_link != phy_dev->link); 2427f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki speed_chg = (sc->sbm_speed != phy_dev->speed); 2428f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki duplex_chg = (sc->sbm_duplex != phy_dev->duplex); 2429f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pause_chg = (sc->sbm_pause != phy_dev->pause); 2430f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2431f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (!link_chg && !speed_chg && !duplex_chg && !pause_chg) 2432f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return; /* Hmmm... */ 2433f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2434f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (!phy_dev->link) { 2435f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (link_chg) { 2436f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_link = phy_dev->link; 2437f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_speed = sbmac_speed_none; 2438f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_duplex = sbmac_duplex_none; 2439f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_fc = sbmac_fc_disabled; 2440f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_pause = -1; 2441f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_info("%s: link unavailable\n", dev->name); 2442f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki } 2443f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return; 2444f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki } 24451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2446f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (phy_dev->duplex == DUPLEX_FULL) { 2447f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (phy_dev->pause) 2448f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki fc = sbmac_fc_frame; 2449f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki else 2450f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki fc = sbmac_fc_disabled; 2451f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki } else 2452f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki fc = sbmac_fc_collision; 2453f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki fc_chg = (sc->sbm_fc != fc); 245474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2455f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_info("%s: link available: %dbase-%cD\n", dev->name, phy_dev->speed, 2456f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki phy_dev->duplex == DUPLEX_FULL ? 'F' : 'H'); 245774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2458f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki spin_lock_irqsave(&sc->sbm_lock, flags); 245974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2460f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_speed = phy_dev->speed; 2461f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_duplex = phy_dev->duplex; 2462f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_fc = fc; 2463f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_pause = phy_dev->pause; 2464f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_link = phy_dev->link; 24651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2466f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if ((speed_chg || duplex_chg || fc_chg) && 2467f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_state != sbmac_state_off) { 2468f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki /* 2469f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * something changed, restart the channel 2470f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki */ 2471f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (debug > 1) 2472f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_debug("%s: restarting channel " 2473f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki "because PHY state changed\n", dev->name); 2474f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_channel_stop(sc); 2475f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_channel_start(sc); 24761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 247774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2478f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki spin_unlock_irqrestore(&sc->sbm_lock, flags); 24791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_tx_timeout (struct net_device *dev) 24831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 2485be61ea52900b97800effbb68478915d73b5d4df2Weiwei Wang unsigned long flags; 248674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2487be61ea52900b97800effbb68478915d73b5d4df2Weiwei Wang spin_lock_irqsave(&sc->sbm_lock, flags); 248874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 248974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 24901ae5dc342ac78d7a42965fd1f323815f6f5ef2c1Eric Dumazet dev->trans_start = jiffies; /* prevent tx timeout */ 249109f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_errors++; 249274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2493be61ea52900b97800effbb68478915d73b5d4df2Weiwei Wang spin_unlock_irqrestore(&sc->sbm_lock, flags); 24941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk (KERN_WARNING "%s: Transmit timed out\n",dev->name); 24961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_set_rx_mode(struct net_device *dev) 25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 25041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 25051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&sc->sbm_lock, flags); 25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((dev->flags ^ sc->sbm_devflags) & IFF_PROMISC) { 25081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 25091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Promiscuous changed. 25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 251174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 251274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle if (dev->flags & IFF_PROMISC) { 25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_promiscuous_mode(sc,1); 25141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 25161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_promiscuous_mode(sc,0); 25171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&sc->sbm_lock, flags); 252074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 25211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Program the multicasts. Do this every time. 25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 252474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 25251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_setmulti(sc); 252674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 25271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 25301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 253274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2533f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (!netif_running(dev) || !sc->phy_dev) 2534f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return -EINVAL; 253574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 253628b041139e344ecd0f144d6205b004ae354cfa1eRichard Cochran return phy_mii_ioctl(sc->phy_dev, rq, cmd); 25371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_close(struct net_device *dev) 25401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 25421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2543bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger napi_disable(&sc->napi); 2544bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger 2545f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki phy_stop(sc->phy_dev); 25461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2547f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_set_channel_state(sc, sbmac_state_off); 25481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(dev); 25501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (debug > 1) 2552f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_debug("%s: Shutting down ethercard\n", dev->name); 25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2554f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki phy_disconnect(sc->phy_dev); 2555f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->phy_dev = NULL; 2556f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki free_irq(dev->irq, dev); 25571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_emptyring(&(sc->sbm_txdma)); 25591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_emptyring(&(sc->sbm_rxdma)); 256074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 25611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 25621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2564bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemmingerstatic int sbmac_poll(struct napi_struct *napi, int budget) 2565693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason{ 2566bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger struct sbmac_softc *sc = container_of(napi, struct sbmac_softc, napi); 2567693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason int work_done; 25681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2569bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger work_done = sbdma_rx_process(sc, &(sc->sbm_rxdma), budget, 1); 2570693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason sbdma_tx_process(sc, &(sc->sbm_txdma), 1); 2571693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 2572bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger if (work_done < budget) { 2573288379f050284087578b77e04f040b57db3db3f8Ben Hutchings napi_complete(napi); 2574693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 2575693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#ifdef CONFIG_SBMAC_COALESCE 2576693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | 2577693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), 2578693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason sc->sbm_imr); 2579693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#else 2580693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) | 2581693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), sc->sbm_imr); 2582693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#endif 2583693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason } 2584693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 2585bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger return work_done; 2586693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason} 25871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2588f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2589047fc56614f8f8d03fb64ef3be44f040aad25d56Bill Pembertonstatic int sbmac_probe(struct platform_device *pldev) 2590f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki{ 2591f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct net_device *dev; 2592f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct sbmac_softc *sc; 2593f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki void __iomem *sbm_base; 2594f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct resource *res; 2595f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki u64 sbmac_orig_hwaddr; 2596f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int err; 2597f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2598f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki res = platform_get_resource(pldev, IORESOURCE_MEM, 0); 2599f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki BUG_ON(!res); 260028f65c11f2ffb3957259dece647a24f8ad2e241bJoe Perches sbm_base = ioremap_nocache(res->start, resource_size(res)); 2601f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (!sbm_base) { 2602f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki printk(KERN_ERR "%s: unable to map device registers\n", 2603db1d7bf70f42124f73675fca62fe32f3ab1111b4Kay Sievers dev_name(&pldev->dev)); 2604f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki err = -ENOMEM; 2605f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki goto out_out; 2606f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki } 2607f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2608f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki /* 2609f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * The R_MAC_ETHERNET_ADDR register will be set to some nonzero 2610f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * value for us by the firmware if we're going to use this MAC. 2611f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * If we find a zero, skip this MAC. 2612f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki */ 2613f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_orig_hwaddr = __raw_readq(sbm_base + R_MAC_ETHERNET_ADDR); 2614db1d7bf70f42124f73675fca62fe32f3ab1111b4Kay Sievers pr_debug("%s: %sconfiguring MAC at 0x%08Lx\n", dev_name(&pldev->dev), 2615f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_orig_hwaddr ? "" : "not ", (long long)res->start); 2616f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (sbmac_orig_hwaddr == 0) { 2617f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki err = 0; 2618f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki goto out_unmap; 2619f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki } 2620f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2621f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki /* 2622f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * Okay, cool. Initialize this MAC. 2623f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki */ 2624f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki dev = alloc_etherdev(sizeof(struct sbmac_softc)); 2625f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (!dev) { 2626f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki err = -ENOMEM; 2627f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki goto out_unmap; 2628f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki } 2629f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2630c7ae011dc8306d982c25fb4f679752e790a08dc4Greg Kroah-Hartman dev_set_drvdata(&pldev->dev, dev); 2631f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SET_NETDEV_DEV(dev, &pldev->dev); 2632f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2633f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc = netdev_priv(dev); 2634f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_base = sbm_base; 2635f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2636f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki err = sbmac_init(pldev, res->start); 2637f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (err) 2638f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki goto out_kfree; 2639f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2640f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return 0; 2641f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2642f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckiout_kfree: 2643f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki free_netdev(dev); 2644f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(sbmac_orig_hwaddr, sbm_base + R_MAC_ETHERNET_ADDR); 2645f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2646f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckiout_unmap: 2647f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki iounmap(sbm_base); 2648f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2649f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckiout_out: 2650f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return err; 2651f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki} 2652f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2653f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic int __exit sbmac_remove(struct platform_device *pldev) 2654f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki{ 2655c7ae011dc8306d982c25fb4f679752e790a08dc4Greg Kroah-Hartman struct net_device *dev = dev_get_drvdata(&pldev->dev); 2656f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct sbmac_softc *sc = netdev_priv(dev); 2657f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2658f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki unregister_netdev(dev); 2659f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_uninitctx(sc); 266003f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior mdiobus_unregister(sc->mii_bus); 2661298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek mdiobus_free(sc->mii_bus); 2662f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki iounmap(sc->sbm_base); 2663f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki free_netdev(dev); 2664f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2665f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return 0; 2666f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki} 2667f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2668f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic struct platform_driver sbmac_driver = { 2669f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki .probe = sbmac_probe, 2670f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki .remove = __exit_p(sbmac_remove), 2671f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki .driver = { 2672f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki .name = sbmac_string, 267333b665eeeb85956ccbdf31c4c31a4e2a31133c44Ralf Baechle .owner = THIS_MODULE, 2674f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki }, 2675f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki}; 26761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2677db62f684deeb291ab2533b99843d5df9a36b1f19Axel Linmodule_platform_driver(sbmac_driver); 2678