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 160ab75ae81da249988bf3c7a38e0a48d4b9be1e0cJeff Kirsher * along with this program; if not, see <http://www.gnu.org/licenses/>. 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This driver is designed for the Broadcom SiByte SOC built-in 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ethernet controllers. Written by Mitch Lichtenberg at Broadcom Corp. 21f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * 22f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * Updated to the driver model and the PHY abstraction layer 23f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * by Maciej W. Rozycki. 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 25f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 26f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <linux/bug.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/timer.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h> 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h> 39f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <linux/err.h> 40f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <linux/ethtool.h> 41f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <linux/mii.h> 42f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <linux/phy.h> 43f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <linux/platform_device.h> 4470c71606190e9115e5f8363bfcd164c582eb314aPaul Gortmaker#include <linux/prefetch.h> 45f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cache.h> 47f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <asm/io.h> 48f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <asm/processor.h> /* Processor type for cache alignment. */ 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Operational parameters that usually are not changed. */ 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CONFIG_SBMAC_COALESCE 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Time in jiffies before concluding the transmitter is hung. */ 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_TIMEOUT (2*HZ) 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Mitch Lichtenberg (Broadcom Corp.)"); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Broadcom SiByte SOC GB Ethernet driver"); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* A few user-configurable values which may be modified when a driver 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds module is loaded. */ 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1 normal messages, 0 quiet .. 7 verbose. */ 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int debug = 1; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, int, S_IRUGO); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "Debug messages"); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SBMAC_COALESCE 70693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonstatic int int_pktcnt_tx = 255; 71693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonmodule_param(int_pktcnt_tx, int, S_IRUGO); 72693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark MasonMODULE_PARM_DESC(int_pktcnt_tx, "TX packet count"); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 74693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonstatic int int_timeout_tx = 255; 75693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonmodule_param(int_timeout_tx, int, S_IRUGO); 76693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark MasonMODULE_PARM_DESC(int_timeout_tx, "TX timeout value"); 77693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 78693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonstatic int int_pktcnt_rx = 64; 79693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonmodule_param(int_pktcnt_rx, int, S_IRUGO); 80693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark MasonMODULE_PARM_DESC(int_pktcnt_rx, "RX packet count"); 81693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 82693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonstatic int int_timeout_rx = 64; 83693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonmodule_param(int_timeout_rx, int, S_IRUGO); 84693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark MasonMODULE_PARM_DESC(int_timeout_rx, "RX timeout value"); 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 87f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#include <asm/sibyte/board.h> 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sibyte/sb1250.h> 89f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) 90f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#include <asm/sibyte/bcm1480_regs.h> 91f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#include <asm/sibyte/bcm1480_int.h> 92693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#define R_MAC_DMA_OODPKTLOST_RX R_MAC_DMA_OODPKTLOST 93f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sibyte/sb1250_regs.h> 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sibyte/sb1250_int.h> 96f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#else 970b1974de66f9ed44f1423449628f4926bf95b854Thomas Weber#error invalid SiByte MAC configuration 98f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#endif 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sibyte/sb1250_scd.h> 100f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#include <asm/sibyte/sb1250_mac.h> 101f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#include <asm/sibyte/sb1250_dma.h> 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 103f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) 104f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#define UNIT_INT(n) (K_BCM1480_INT_MAC_0 + ((n) * 2)) 105f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) 106f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#define UNIT_INT(n) (K_INT_MAC_0 + (n)) 107f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#else 1080b1974de66f9ed44f1423449628f4926bf95b854Thomas Weber#error invalid SiByte MAC configuration 109f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#endif 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#ifdef K_INT_PHY 112f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#define SBMAC_PHY_INT K_INT_PHY 113f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#else 114f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#define SBMAC_PHY_INT PHY_POLL 115f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki#endif 116f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Simple types 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckienum sbmac_speed { 122f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_speed_none = 0, 123f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_speed_10 = SPEED_10, 124f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_speed_100 = SPEED_100, 125f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_speed_1000 = SPEED_1000, 126f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki}; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 128f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckienum sbmac_duplex { 129f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_duplex_none = -1, 130f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_duplex_half = DUPLEX_HALF, 131f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_duplex_full = DUPLEX_FULL, 132f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki}; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 134f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckienum sbmac_fc { 135f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_fc_none, 136f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_fc_disabled, 137f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_fc_frame, 138f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_fc_collision, 139f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_fc_carrier, 140f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki}; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 142f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckienum sbmac_state { 143f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_state_uninit, 144f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_state_off, 145f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_state_on, 146f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_state_broken, 147f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki}; 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Macros 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SBDMA_NEXTBUF(d,f) ((((d)->f+1) == (d)->sbdma_dscrtable_end) ? \ 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (d)->sbdma_dscrtable : (d)->f+1) 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES) 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 161693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#define SBMAC_MAX_TXDESCR 256 162693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#define SBMAC_MAX_RXDESCR 256 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle#define ENET_PACKET_SIZE 1518 16574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle/*#define ENET_PACKET_SIZE 9216 */ 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DMA Descriptor structure 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistruct sbdmadscr { 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t dscr_a; 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t dscr_b; 17473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki}; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DMA Controller structure 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistruct sbmacdma { 18174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This stuff is used to identify the channel and the registers 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * associated with it. 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 18673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbmac_softc *sbdma_eth; /* back pointer to associated 18773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki MAC */ 18873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int sbdma_channel; /* channel number */ 18973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int sbdma_txdir; /* direction (1=transmit) */ 19073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int sbdma_maxdescr; /* total # of descriptors 19173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki in ring */ 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SBMAC_COALESCE 19373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int sbdma_int_pktcnt; 19473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* # descriptors rx/tx 19573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki before interrupt */ 19673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int sbdma_int_timeout; 19773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* # usec rx/tx interrupt */ 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 19973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbdma_config0; /* DMA config register 0 */ 20073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbdma_config1; /* DMA config register 1 */ 20173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbdma_dscrbase; 20273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* descriptor base address */ 20373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbdma_dscrcnt; /* descriptor count register */ 20473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbdma_curdscr; /* current descriptor 20573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki address */ 20673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbdma_oodpktlost; 20773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* pkt drop (rx only) */ 20874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This stuff is for maintenance of the ring 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 21273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void *sbdma_dscrtable_unaligned; 21373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *sbdma_dscrtable; 21473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* base of descriptor table */ 21573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *sbdma_dscrtable_end; 21673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* end of descriptor table */ 21773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sk_buff **sbdma_ctxtable; 21873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* context table, one 21973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki per descr */ 22073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki dma_addr_t sbdma_dscrtable_phys; 22173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki /* and also the phys addr */ 22273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *sbdma_addptr; /* next dscr for sw to add */ 22373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *sbdma_remptr; /* next dscr for sw 22473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki to remove */ 22573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki}; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ethernet softc structure 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct sbmac_softc { 23374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Linux-specific things 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 23773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct net_device *sbm_dev; /* pointer to linux device */ 23873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct napi_struct napi; 239f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct phy_device *phy_dev; /* the associated PHY device */ 240298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek struct mii_bus *mii_bus; /* the MII bus */ 241f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int phy_irq[PHY_MAX_ADDR]; 24273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki spinlock_t sbm_lock; /* spin lock */ 24373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int sbm_devflags; /* current device flags */ 24474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Controller-specific things 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 24873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_base; /* MAC's base address */ 24973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_state sbm_state; /* current state */ 25074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 25173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_macenable; /* MAC Enable Register */ 25273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_maccfg; /* MAC Config Register */ 25373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_fifocfg; /* FIFO Config Register */ 25473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_framecfg; /* Frame Config Register */ 25573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_rxfilter; /* Receive Filter Register */ 25673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_isr; /* Interrupt Status Register */ 25773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_imr; /* Interrupt Mask Register */ 25873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *sbm_mdio; /* MDIO Register */ 25974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 26073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_speed sbm_speed; /* current speed */ 26173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_duplex sbm_duplex; /* current duplex */ 26273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_fc sbm_fc; /* cur. flow control setting */ 263f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int sbm_pause; /* current pause setting */ 264f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int sbm_link; /* current link state */ 26574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 266104bf3fb963cbc39c6675b23d46d2c9ab3f311d8Joe Perches unsigned char sbm_hwaddr[ETH_ALEN]; 26774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 26873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbmacdma sbm_txdma; /* only channel 0 for now */ 26973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbmacdma sbm_rxdma; 27073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int rx_hw_checksum; 27173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int sbe_idx; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Externs 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Prototypes 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 28373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_initctx(struct sbmacdma *d, struct sbmac_softc *s, int chan, 28473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int txrx, int maxdescr); 28573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_channel_start(struct sbmacdma *d, int rxtx); 286789585e968f07653a29a9e829aed20386043636cStephen Hemmingerstatic int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d, 287789585e968f07653a29a9e829aed20386043636cStephen Hemminger struct sk_buff *m); 28873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbdma_add_txbuffer(struct sbmacdma *d, struct sk_buff *m); 28973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_emptyring(struct sbmacdma *d); 290789585e968f07653a29a9e829aed20386043636cStephen Hemmingerstatic void sbdma_fillring(struct sbmac_softc *sc, struct sbmacdma *d); 29173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbdma_rx_process(struct sbmac_softc *sc, struct sbmacdma *d, 29273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int work_to_do, int poll); 29373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d, 29473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int poll); 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_initctx(struct sbmac_softc *s); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_channel_start(struct sbmac_softc *s); 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_channel_stop(struct sbmac_softc *s); 29873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic enum sbmac_state sbmac_set_channel_state(struct sbmac_softc *, 29973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_state); 30073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbmac_promiscuous_mode(struct sbmac_softc *sc, int onoff); 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic uint64_t sbmac_addr2reg(unsigned char *ptr); 30273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic irqreturn_t sbmac_intr(int irq, void *dev_instance); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_setmulti(struct sbmac_softc *sc); 305f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic int sbmac_init(struct platform_device *pldev, long long base); 30673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbmac_set_speed(struct sbmac_softc *s, enum sbmac_speed speed); 30773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbmac_set_duplex(struct sbmac_softc *s, enum sbmac_duplex duplex, 30873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_fc fc); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_open(struct net_device *dev); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_tx_timeout (struct net_device *dev); 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_set_rx_mode(struct net_device *dev); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_close(struct net_device *dev); 315bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemmingerstatic int sbmac_poll(struct napi_struct *napi, int budget); 316693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 317f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic void sbmac_mii_poll(struct net_device *dev); 31859b81827071a8ae7f399da533d268e1e33bfeeb7Ralf Baechlestatic int sbmac_mii_probe(struct net_device *dev); 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 320f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic void sbmac_mii_sync(void __iomem *sbm_mdio); 321f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic void sbmac_mii_senddata(void __iomem *sbm_mdio, unsigned int data, 32273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int bitcnt); 323f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic int sbmac_mii_read(struct mii_bus *bus, int phyaddr, int regidx); 324f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic int sbmac_mii_write(struct mii_bus *bus, int phyaddr, int regidx, 325f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki u16 val); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Globals 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 332f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic char sbmac_string[] = "sb1250-mac"; 333f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 334f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic char sbmac_mdio_string[] = "sb1250-mac-mdio"; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MDIO constants 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MII_COMMAND_START 0x01 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MII_COMMAND_READ 0x02 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MII_COMMAND_WRITE 0x01 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MII_COMMAND_ACK 0x02 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define M_MAC_MDIO_DIR_OUTPUT 0 /* for clarity */ 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ENABLE 1 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DISABLE 0 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 352f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * SBMAC_MII_SYNC(sbm_mdio) 35374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Synchronize with the MII - send a pattern of bits to the MII 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * that will guarantee that it is ready to accept a command. 35674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 35774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 358f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * sbm_mdio - address of the MAC's MDIO register 35974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 364f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic void sbmac_mii_sync(void __iomem *sbm_mdio) 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cnt; 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t bits; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int mac_mdio_genc; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 370f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC; 37174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT; 37374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 374f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(bits | mac_mdio_genc, sbm_mdio); 37574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (cnt = 0; cnt < 32; cnt++) { 377f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, sbm_mdio); 378f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(bits | mac_mdio_genc, sbm_mdio); 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 383f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * SBMAC_MII_SENDDATA(sbm_mdio, data, bitcnt) 38474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send some bits to the MII. The bits to be sent are right- 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * justified in the 'data' parameter. 38774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 38874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 389f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * sbm_mdio - address of the MAC's MDIO register 390f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * data - data to send 391f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * bitcnt - number of bits to send 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 394f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic void sbmac_mii_senddata(void __iomem *sbm_mdio, unsigned int data, 395f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int bitcnt) 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t bits; 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int curmask; 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int mac_mdio_genc; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 402f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC; 40374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bits = M_MAC_MDIO_DIR_OUTPUT; 405f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(bits | mac_mdio_genc, sbm_mdio); 40674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds curmask = 1 << (bitcnt - 1); 40874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < bitcnt; i++) { 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (data & curmask) 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bits |= M_MAC_MDIO_OUT; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else bits &= ~M_MAC_MDIO_OUT; 413f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(bits | mac_mdio_genc, sbm_mdio); 414f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, sbm_mdio); 415f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(bits | mac_mdio_genc, sbm_mdio); 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds curmask >>= 1; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 423f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * SBMAC_MII_READ(bus, phyaddr, regidx) 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Read a PHY register. 42574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 42674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 427f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * bus - MDIO bus handle 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * phyaddr - PHY's address 429f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * regnum - index of register to read 43074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 432f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * value read, or 0xffff if an error occurred. 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 435f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic int sbmac_mii_read(struct mii_bus *bus, int phyaddr, int regidx) 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 437f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct sbmac_softc *sc = (struct sbmac_softc *)bus->priv; 438f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki void __iomem *sbm_mdio = sc->sbm_mdio; 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int idx; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int error; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int regval; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int mac_mdio_genc; 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Synchronize ourselves so that the PHY knows the next 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * thing coming down is a command 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 448f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_sync(sbm_mdio); 44974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send the data to the PHY. The sequence is 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a "start" command (2 bits) 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * a "read" command (2 bits) 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the PHY addr (5 bits) 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the register index (5 bits) 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 457f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, MII_COMMAND_START, 2); 458f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, MII_COMMAND_READ, 2); 459f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, phyaddr, 5); 460f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, regidx, 5); 46174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 462f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC; 46374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 46474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Switch the port around without a clock transition. 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 467f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio); 46874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Send out a clock pulse to signal we want the status 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 472f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, 473f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbm_mdio); 474f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio); 47574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 47674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If an error occurred, the PHY will signal '1' back 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 479f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki error = __raw_readq(sbm_mdio) & M_MAC_MDIO_IN; 48074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 48174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Issue an 'idle' clock pulse, but keep the direction 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the same. 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 485f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, 486f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbm_mdio); 487f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio); 48874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regval = 0; 49074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < 16; idx++) { 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regval <<= 1; 49374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error == 0) { 495f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (__raw_readq(sbm_mdio) & M_MAC_MDIO_IN) 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regval |= 1; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 49874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 499f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc, 500f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbm_mdio); 501f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio); 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 50374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Switch back to output */ 505f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, sbm_mdio); 50674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (error == 0) 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return regval; 509f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return 0xffff; 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 514f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * SBMAC_MII_WRITE(bus, phyaddr, regidx, regval) 51574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Write a value to a PHY register. 51774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 51874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 519f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * bus - MDIO bus handle 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * phyaddr - PHY to use 521f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * regidx - register within the PHY 522f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * regval - data to write to register 52374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 525f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * 0 for success 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 528f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic int sbmac_mii_write(struct mii_bus *bus, int phyaddr, int regidx, 529f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki u16 regval) 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 531f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct sbmac_softc *sc = (struct sbmac_softc *)bus->priv; 532f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki void __iomem *sbm_mdio = sc->sbm_mdio; 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int mac_mdio_genc; 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 535f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_sync(sbm_mdio); 53674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 537f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, MII_COMMAND_START, 2); 538f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, MII_COMMAND_WRITE, 2); 539f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, phyaddr, 5); 540f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, regidx, 5); 541f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, MII_COMMAND_ACK, 2); 542f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_mii_senddata(sbm_mdio, regval, 16); 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 544f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 546f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, sbm_mdio); 547f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 548f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return 0; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_INITCTX(d,s,chan,txrx,maxdescr) 55574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize a DMA channel context. Since there are potentially 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * eight DMA channels per MAC, it's nice to do this in a standard 55874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * way. 55974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 56074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 56173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki * d - struct sbmacdma (DMA channel context) 56273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki * s - struct sbmac_softc (pointer to a MAC) 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * chan - channel number (0..1 right now) 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * txrx - Identifies DMA_TX or DMA_RX for channel direction 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * maxdescr - number of descriptors 56674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 57173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_initctx(struct sbmacdma *d, struct sbmac_softc *s, int chan, 57273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int txrx, int maxdescr) 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 574693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#ifdef CONFIG_SBMAC_COALESCE 575693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason int int_pktcnt, int_timeout; 576693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#endif 577693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 57874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 57974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Save away interesting stuff in the structure 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 58174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_eth = s; 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_channel = chan; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_txdir = txrx; 58574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* RMON clearing */ 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING; 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 591f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_BYTES); 592f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_COLLISIONS); 593f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_LATE_COL); 594f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_EX_COL); 595f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_FCS_ERROR); 596f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_ABORT); 597f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_BAD); 598f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_GOOD); 599f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_RUNT); 600f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_OVERSIZE); 601f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BYTES); 602f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_MCAST); 603f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BCAST); 604f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BAD); 605f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_GOOD); 606f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_RUNT); 607f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_OVERSIZE); 608f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_FCS_ERROR); 609f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_LENGTH_ERROR); 610f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_CODE_ERROR); 611f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_ALIGN_ERROR); 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 61374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 61474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * initialize register pointers 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 61674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 61774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle d->sbdma_config0 = 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0); 61974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle d->sbdma_config1 = 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1); 62174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle d->sbdma_dscrbase = 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE); 62374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle d->sbdma_dscrcnt = 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT); 62574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle d->sbdma_curdscr = 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR); 627693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (d->sbdma_txdir) 628693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason d->sbdma_oodpktlost = NULL; 629693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason else 630693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason d->sbdma_oodpktlost = 631693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_OODPKTLOST_RX); 63274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate memory for the ring 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 63674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_maxdescr = maxdescr; 63874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 63973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki d->sbdma_dscrtable_unaligned = kcalloc(d->sbdma_maxdescr + 1, 64073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki sizeof(*d->sbdma_dscrtable), 64173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki GFP_KERNEL); 64204115def6ad7ef51440365b65a7324fcb82d5d1dRalf Baechle 64304115def6ad7ef51440365b65a7324fcb82d5d1dRalf Baechle /* 64404115def6ad7ef51440365b65a7324fcb82d5d1dRalf Baechle * The descriptor table must be aligned to at least 16 bytes or the 64504115def6ad7ef51440365b65a7324fcb82d5d1dRalf Baechle * MAC will corrupt it. 64604115def6ad7ef51440365b65a7324fcb82d5d1dRalf Baechle */ 64773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki d->sbdma_dscrtable = (struct sbdmadscr *) 64873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki ALIGN((unsigned long)d->sbdma_dscrtable_unaligned, 64973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki sizeof(*d->sbdma_dscrtable)); 65074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr; 65274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_dscrtable_phys = virt_to_phys(d->sbdma_dscrtable); 65474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * And context table 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 65874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 659c477f3348abb5f6fb8b627cfdb1d7ae4b8fe613bMariusz Kozlowski d->sbdma_ctxtable = kcalloc(d->sbdma_maxdescr, 66073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki sizeof(*d->sbdma_ctxtable), GFP_KERNEL); 66174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SBMAC_COALESCE 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Setup Rx/Tx DMA coalescing defaults 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 667693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason int_pktcnt = (txrx == DMA_TX) ? int_pktcnt_tx : int_pktcnt_rx; 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ( int_pktcnt ) { 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_int_pktcnt = int_pktcnt; 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_int_pktcnt = 1; 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 67374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 674693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason int_timeout = (txrx == DMA_TX) ? int_timeout_tx : int_timeout_rx; 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ( int_timeout ) { 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_int_timeout = int_timeout; 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_int_timeout = 0; 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_CHANNEL_START(d) 68674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize the hardware registers for a DMA channel. 68874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 68974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * d - DMA channel to init (context must be previously init'd 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * rxtx - DMA_RX or DMA_TX depending on what type of channel 69274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 69773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_channel_start(struct sbmacdma *d, int rxtx) 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Turn on the DMA channel 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 70274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SBMAC_COALESCE 7042039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) | 7052039973af59889fea0d14362eae56792cfe8d25aRalf Baechle 0, d->sbdma_config1); 7062039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(M_DMA_EOP_INT_EN | 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_DMA_RINGSZ(d->sbdma_maxdescr) | 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_DMA_INT_PKTCNT(d->sbdma_int_pktcnt) | 7092039973af59889fea0d14362eae56792cfe8d25aRalf Baechle 0, d->sbdma_config0); 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 7112039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, d->sbdma_config1); 7122039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(V_DMA_RINGSZ(d->sbdma_maxdescr) | 7132039973af59889fea0d14362eae56792cfe8d25aRalf Baechle 0, d->sbdma_config0); 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7162039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(d->sbdma_dscrtable_phys, d->sbdma_dscrbase); 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize ring pointers 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_addptr = d->sbdma_dscrtable; 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_remptr = d->sbdma_dscrtable; 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_CHANNEL_STOP(d) 72874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize the hardware registers for a DMA channel. 73074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 73174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * d - DMA channel to init (context must be previously init'd 73374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 73873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_channel_stop(struct sbmacdma *d) 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Turn off the DMA channel 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 74374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7442039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, d->sbdma_config1); 74574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7462039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, d->sbdma_dscrbase); 74774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7482039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, d->sbdma_config0); 74974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Zero ring pointers 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 75374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7542039973af59889fea0d14362eae56792cfe8d25aRalf Baechle d->sbdma_addptr = NULL; 7552039973af59889fea0d14362eae56792cfe8d25aRalf Baechle d->sbdma_remptr = NULL; 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 758789585e968f07653a29a9e829aed20386043636cStephen Hemmingerstatic inline void sbdma_align_skb(struct sk_buff *skb, 759789585e968f07653a29a9e829aed20386043636cStephen Hemminger unsigned int power2, unsigned int offset) 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 761789585e968f07653a29a9e829aed20386043636cStephen Hemminger unsigned char *addr = skb->data; 762789585e968f07653a29a9e829aed20386043636cStephen Hemminger unsigned char *newaddr = PTR_ALIGN(addr, power2); 76374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 764789585e968f07653a29a9e829aed20386043636cStephen Hemminger skb_reserve(skb, newaddr - addr + offset); 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_ADD_RCVBUFFER(d,sb) 77074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Add a buffer to the specified DMA channel. For receive channels, 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * this queues a buffer for inbound packets. 77374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 77474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 775789585e968f07653a29a9e829aed20386043636cStephen Hemminger * sc - softc structure 776789585e968f07653a29a9e829aed20386043636cStephen Hemminger * d - DMA channel descriptor 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sb - sk_buff to add, or NULL if we should allocate one 77874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 if buffer could not be added (ring is full) 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 if buffer added successfully 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 785789585e968f07653a29a9e829aed20386043636cStephen Hemmingerstatic int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d, 786789585e968f07653a29a9e829aed20386043636cStephen Hemminger struct sk_buff *sb) 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 788789585e968f07653a29a9e829aed20386043636cStephen Hemminger struct net_device *dev = sc->sbm_dev; 78973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *dsc; 79073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *nextdsc; 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *sb_new = NULL; 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int pktsize = ENET_PACKET_SIZE; 79374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get pointer to our current place in the ring */ 79574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dsc = d->sbdma_addptr; 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr); 79874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * figure out if the ring is full - if the next descriptor 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is the same as the one that we're going to remove from 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the ring, the ring is full 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 80474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nextdsc == d->sbdma_remptr) { 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOSPC; 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 80974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 81074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Allocate a sk_buff if we don't already have one. 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If we do have an sk_buff, reset it so that it's empty. 8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: sk_buffs don't seem to be guaranteed to have any sort 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of alignment when they are allocated. Therefore, allocate enough 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * extra space to make sure that: 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1. the data does not start in the middle of a cache line. 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. The data does not end in the middle of a cache line 81974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 3. The buffer can be aligned such that the IP addresses are 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * naturally aligned. 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Remember, the SOCs MAC writes whole cache lines at a time, 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * without reading the old contents first. So, if the sk_buff's 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * data portion starts in the middle of a cache line, the SOC 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * DMA will trash the beginning (and ending) portions. 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 82774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sb == NULL) { 829789585e968f07653a29a9e829aed20386043636cStephen Hemminger sb_new = netdev_alloc_skb(dev, ENET_PACKET_SIZE + 830789585e968f07653a29a9e829aed20386043636cStephen Hemminger SMP_CACHE_BYTES * 2 + 831789585e968f07653a29a9e829aed20386043636cStephen Hemminger NET_IP_ALIGN); 832720a43efd30f04a0a492c85fb997361c44fbae05Joe Perches if (sb_new == NULL) 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOBUFS; 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 835789585e968f07653a29a9e829aed20386043636cStephen Hemminger sbdma_align_skb(sb_new, SMP_CACHE_BYTES, NET_IP_ALIGN); 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb_new = sb; 83974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing special to reinit buffer, it's already aligned 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and sb->data already points to a good place. 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 84474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 84674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * fill in the descriptor 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 84874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SBMAC_COALESCE 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Do not interrupt per DMA transfer. 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 853689be43945e9ca7dd704522e55af1b8a73a994d3David S. Miller dsc->dscr_a = virt_to_phys(sb_new->data) | 854789585e968f07653a29a9e829aed20386043636cStephen Hemminger V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize + NET_IP_ALIGN)) | 0; 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 856689be43945e9ca7dd704522e55af1b8a73a994d3David S. Miller dsc->dscr_a = virt_to_phys(sb_new->data) | 857789585e968f07653a29a9e829aed20386043636cStephen Hemminger V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize + NET_IP_ALIGN)) | 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_DMA_DSCRA_INTERRUPT; 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* receiving: no options */ 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dsc->dscr_b = 0; 86374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 86574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * fill in the context 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 86774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb_new; 86974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 87074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 87174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * point at next packet 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 87374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_addptr = nextdsc; 87574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 87674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Give the buffer to the DMA engine. 8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 87974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8802039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(1, d->sbdma_dscrcnt); 88174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* we did it */ 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_ADD_TXBUFFER(d,sb) 88774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Add a transmit buffer to the specified DMA channel, causing a 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * transmit to start. 89074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 89174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * d - DMA channel descriptor 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sb - sk_buff to add 89474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 transmit queued successfully 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * otherwise error code 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 90173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbdma_add_txbuffer(struct sbmacdma *d, struct sk_buff *sb) 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 90373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *dsc; 90473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *nextdsc; 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t phys; 9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t ncb; 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int length; 90874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* get pointer to our current place in the ring */ 91074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dsc = d->sbdma_addptr; 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr); 91374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * figure out if the ring is full - if the next descriptor 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is the same as the one that we're going to remove from 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the ring, the ring is full 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 91974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (nextdsc == d->sbdma_remptr) { 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOSPC; 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 92374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Under Linux, it's not necessary to copy/coalesce buffers 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * like it is on NetBSD. We think they're all contiguous, 9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but that may not be true for GBE. 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 92974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds length = sb->len; 93174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fill in the descriptor. Note that the number of cache 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * blocks in the descriptor is the number of blocks 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * *spanned*, so we need to add in the offset (if any) 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * while doing the calculation. 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 93874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds phys = virt_to_phys(sb->data); 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ncb = NUMCACHEBLKS(length+(phys & (SMP_CACHE_BYTES - 1))); 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 94274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle dsc->dscr_a = phys | 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_DMA_DSCRA_A_SIZE(ncb) | 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef CONFIG_SBMAC_COALESCE 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_DMA_DSCRA_INTERRUPT | 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_DMA_ETHTX_SOP; 94874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* transmitting: set outbound options and length */ 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) | 9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_DMA_DSCRB_PKT_SIZE(length); 95374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 95574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * fill in the context 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 95774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb; 95974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 96074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 96174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * point at next packet 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 96374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_addptr = nextdsc; 96574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 96674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Give the buffer to the DMA engine. 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 96974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9702039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(1, d->sbdma_dscrcnt); 97174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* we did it */ 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_EMPTYRING(d) 98074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Free all allocated sk_buffs on the specified DMA channel; 98274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 98374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * d - DMA channel 98574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 99073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_emptyring(struct sbmacdma *d) 9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int idx; 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *sb; 99474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < d->sbdma_maxdescr; idx++) { 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb = d->sbdma_ctxtable[idx]; 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sb) { 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb(sb); 9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_ctxtable[idx] = NULL; 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_FILLRING(d) 100774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fill the specified DMA channel (must be receive channel) 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * with sk_buffs 101074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 101174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 1012789585e968f07653a29a9e829aed20386043636cStephen Hemminger * sc - softc structure 1013789585e968f07653a29a9e829aed20386043636cStephen Hemminger * d - DMA channel 101474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1019789585e968f07653a29a9e829aed20386043636cStephen Hemmingerstatic void sbdma_fillring(struct sbmac_softc *sc, struct sbmacdma *d) 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int idx; 102274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1023789585e968f07653a29a9e829aed20386043636cStephen Hemminger for (idx = 0; idx < SBMAC_MAX_RXDESCR - 1; idx++) { 1024789585e968f07653a29a9e829aed20386043636cStephen Hemminger if (sbdma_add_rcvbuffer(sc, d, NULL) != 0) 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1029d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena#ifdef CONFIG_NET_POLL_CONTROLLER 1030d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxenastatic void sbmac_netpoll(struct net_device *netdev) 1031d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena{ 1032d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena struct sbmac_softc *sc = netdev_priv(netdev); 1033d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena int irq = sc->sbm_dev->irq; 1034d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena 1035d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena __raw_writeq(0, sc->sbm_imr); 1036d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena 10370da2f0f164f098bb4447c714b552ac1681b2d6e8Yoann Padioleau sbmac_intr(irq, netdev); 1038d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena 1039d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena#ifdef CONFIG_SBMAC_COALESCE 1040d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | 1041d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), 1042d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena sc->sbm_imr); 1043d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena#else 10447d2e3cb7000b883a8e489485ac249be572fe17b1Jeff Garzik __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) | 1045d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), sc->sbm_imr); 1046d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena#endif 1047d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena} 1048d68300182828596016d7a6c0f23a912f07d9d0dfDeepak Saxena#endif 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 1051693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * SBDMA_RX_PROCESS(sc,d,work_to_do,poll) 105274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 105374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Process "completed" receive buffers on the specified DMA channel. 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 105574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 1056693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * sc - softc structure 1057693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * d - DMA channel context 1058693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * work_to_do - no. of packets to process before enabling interrupt 1059693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * again (for NAPI) 1060693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * poll - 1: using polling (for NAPI) 106174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 106673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbdma_rx_process(struct sbmac_softc *sc, struct sbmacdma *d, 106773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int work_to_do, int poll) 10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 106909f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik struct net_device *dev = sc->sbm_dev; 10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int curidx; 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int hwidx; 107273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *dsc; 10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *sb; 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int len; 1075693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason int work_done = 0; 1076693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason int dropped = 0; 107774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1078693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason prefetch(d); 1079693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 1080693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonagain: 1081693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason /* Check if the HW dropped any frames */ 108209f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_fifo_errors 1083693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason += __raw_readq(sc->sbm_rxdma.sbdma_oodpktlost) & 0xffff; 1084693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason __raw_writeq(0, sc->sbm_rxdma.sbdma_oodpktlost); 1085693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 1086693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason while (work_to_do-- > 0) { 108774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * figure out where we are (as an index) and where 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the hardware is (also as an index) 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 109174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * This could be done faster if (for example) the 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * descriptor table was page-aligned and contiguous in 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * both virtual and physical memory -- you could then 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * just compare the low-order bits of the virtual address 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (sbdma_remptr) and the physical address (sbdma_curdscr CSR) 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 109774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1098693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason dsc = d->sbdma_remptr; 1099693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason curidx = dsc - d->sbdma_dscrtable; 1100693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 1101693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason prefetch(dsc); 1102693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason prefetch(&d->sbdma_ctxtable[curidx]); 1103693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 110473d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki hwidx = ((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) - 110573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki d->sbdma_dscrtable_phys) / 110673d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki sizeof(*d->sbdma_dscrtable); 110774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If they're the same, that means we've processed all 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the descriptors up to (but not including) the one that 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the hardware is working on right now. 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 111374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (curidx == hwidx) 1115693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason goto done; 111674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Otherwise, get the packet's sk_buff ptr back 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 112074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb = d->sbdma_ctxtable[curidx]; 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_ctxtable[curidx] = NULL; 112374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len = (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b) - 4; 112574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Check packet status. If good, process it. 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If not, silently drop it and put it back on the 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * receive ring. 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 113174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1132693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (likely (!(dsc->dscr_a & M_DMA_ETHRX_BAD))) { 113374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Add a new buffer to replace the old one. If we fail 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to allocate a buffer, we're going to drop this 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * packet and put it right back on the receive ring. 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 113974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1140789585e968f07653a29a9e829aed20386043636cStephen Hemminger if (unlikely(sbdma_add_rcvbuffer(sc, d, NULL) == 1141789585e968f07653a29a9e829aed20386043636cStephen Hemminger -ENOBUFS)) { 114209f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_dropped++; 1143789585e968f07653a29a9e829aed20386043636cStephen Hemminger /* Re-add old buffer */ 1144789585e968f07653a29a9e829aed20386043636cStephen Hemminger sbdma_add_rcvbuffer(sc, d, sb); 1145693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason /* No point in continuing at the moment */ 1146693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason printk(KERN_ERR "dropped packet (1)\n"); 1147693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); 1148693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason goto done; 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set length into the packet 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_put(sb,len); 115474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Buffer has been replaced on the 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * receive ring. Pass the buffer to 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the kernel 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb->protocol = eth_type_trans(sb,d->sbdma_eth->sbm_dev); 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check hw IPv4/TCP checksum if supported */ 11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sc->rx_hw_checksum == ENABLE) { 11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!((dsc->dscr_a) & M_DMA_ETHRX_BADIP4CS) && 11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !((dsc->dscr_a) & M_DMA_ETHRX_BADTCPCS)) { 11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb->ip_summed = CHECKSUM_UNNECESSARY; 11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't need to set sb->csum */ 11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1168bc8acf2c8c3e43fcc192762a9f964b3e9a17748bEric Dumazet skb_checksum_none_assert(sb); 11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1171693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason prefetch(sb->data); 1172693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason prefetch((const void *)(((char *)sb->data)+32)); 1173693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (poll) 1174693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason dropped = netif_receive_skb(sb); 1175693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason else 1176693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason dropped = netif_rx(sb); 1177693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 1178693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (dropped == NET_RX_DROP) { 117909f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_dropped++; 1180693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); 1181693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason goto done; 1182693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason } 1183693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason else { 118409f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_bytes += len; 118509f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_packets++; 1186693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason } 11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Packet was mangled somehow. Just drop it and 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * put it back on the receive ring. 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 119309f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.rx_errors++; 1194789585e968f07653a29a9e829aed20386043636cStephen Hemminger sbdma_add_rcvbuffer(sc, d, sb); 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 119674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 119774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 119874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * .. and advance to the next buffer. 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 120174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); 1203693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason work_done++; 1204693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason } 1205693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (!poll) { 1206693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason work_to_do = 32; 1207693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason goto again; /* collect fifo drop statistics again */ 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1209693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masondone: 1210693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason return work_done; 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBDMA_TX_PROCESS(sc,d) 121574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 121674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Process "completed" transmit buffers on the specified DMA channel. 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is normally called within the interrupt service routine. 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note that this isn't really ideal for priority channels, since 121974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * it processes all of the packets on a given channel before 122074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * returning. 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 122274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sc - softc structure 1224693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * d - DMA channel context 1225693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * poll - 1: using polling (for NAPI) 122674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 123173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d, 123273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki int poll) 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 123409f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik struct net_device *dev = sc->sbm_dev; 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int curidx; 12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int hwidx; 123773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki struct sbdmadscr *dsc; 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *sb; 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 1240693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason int packets_handled = 0; 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&(sc->sbm_lock), flags); 124374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1244693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (d->sbdma_remptr == d->sbdma_addptr) 1245693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason goto end_unlock; 1246693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 124773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki hwidx = ((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) - 124873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki d->sbdma_dscrtable_phys) / sizeof(*d->sbdma_dscrtable); 1249693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (;;) { 125174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * figure out where we are (as an index) and where 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the hardware is (also as an index) 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 125574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * This could be done faster if (for example) the 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * descriptor table was page-aligned and contiguous in 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * both virtual and physical memory -- you could then 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * just compare the low-order bits of the virtual address 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (sbdma_remptr) and the physical address (sbdma_curdscr CSR) 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 126174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds curidx = d->sbdma_remptr - d->sbdma_dscrtable; 12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If they're the same, that means we've processed all 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the descriptors up to (but not including) the one that 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the hardware is working on right now. 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 126974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (curidx == hwidx) 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 127274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Otherwise, get the packet's sk_buff ptr back 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 127674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dsc = &(d->sbdma_dscrtable[curidx]); 12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sb = d->sbdma_ctxtable[curidx]; 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_ctxtable[curidx] = NULL; 128074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Stats 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 128474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 128509f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_bytes += sb->len; 128609f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_packets++; 128774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for transmits, we just free buffers. 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 129174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb_irq(sb); 129374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 129474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * .. and advance to the next buffer. 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr); 129974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1300693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason packets_handled++; 1301693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 130374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Decide if we should wake up the protocol or not. 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Other drivers seem to do this when we reach a low 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * watermark on the transmit queue. 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 130974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1310693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (packets_handled) 1311693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason netif_wake_queue(d->sbdma_eth->sbm_dev); 131274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1313693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Masonend_unlock: 13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&(sc->sbm_lock), flags); 131574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_INITCTX(s) 132274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize an Ethernet context structure - this is called 13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * once per MAC on the 1250. Memory is allocated here, so don't 13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * call it again from inside the ioctl routines that bring the 13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * interface up/down 132774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 132874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * s - sbmac context structure 133074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_initctx(struct sbmac_softc *s) 13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 133774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 133874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 133974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * figure out the addresses of some ports 13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 134174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_macenable = s->sbm_base + R_MAC_ENABLE; 13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_maccfg = s->sbm_base + R_MAC_CFG; 13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_fifocfg = s->sbm_base + R_MAC_THRSH_CFG; 13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_framecfg = s->sbm_base + R_MAC_FRAMECFG; 13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_rxfilter = s->sbm_base + R_MAC_ADFILTER_CFG; 13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_isr = s->sbm_base + R_MAC_STATUS; 13481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_imr = s->sbm_base + R_MAC_INT_MASK; 13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_mdio = s->sbm_base + R_MAC_MDIO; 13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize the DMA channels. Right now, only one per MAC is used 13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: Only do this _once_, as it allocates memory from the kernel! 13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 135574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_initctx(&(s->sbm_txdma),s,0,DMA_TX,SBMAC_MAX_TXDESCR); 13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_initctx(&(s->sbm_rxdma),s,0,DMA_RX,SBMAC_MAX_RXDESCR); 135874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * initial state is OFF 13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 136274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_state = sbmac_state_off; 136474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 136973d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic void sbdma_uninitctx(struct sbmacdma *d) 13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1371693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (d->sbdma_dscrtable_unaligned) { 1372693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason kfree(d->sbdma_dscrtable_unaligned); 1373693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason d->sbdma_dscrtable_unaligned = d->sbdma_dscrtable = NULL; 13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 137574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (d->sbdma_ctxtable) { 13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(d->sbdma_ctxtable); 13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d->sbdma_ctxtable = NULL; 13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_uninitctx(struct sbmac_softc *sc) 13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_uninitctx(&(sc->sbm_txdma)); 13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_uninitctx(&(sc->sbm_rxdma)); 13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_CHANNEL_START(s) 139274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Start packet processing on this MAC. 139474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 139574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * s - sbmac structure 139774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_channel_start(struct sbmac_softc *s) 14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t reg; 140573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *port; 14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t cfg,fifo,framecfg; 14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int idx, th_value; 140874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Don't do this if running 14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s->sbm_state == sbmac_state_on) 14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 141574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Bring the controller out of reset, but leave it off. 14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 141974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14202039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, s->sbm_macenable); 142174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Ignore all received packets 14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 142574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14262039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, s->sbm_rxfilter); 142774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 142874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Calculate values for various control registers. 14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 143174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg = M_MAC_RETRY_EN | 143374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle M_MAC_TX_HOLD_SOP_EN | 14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_TX_PAUSE_CNT_16K | 14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_MAC_AP_STAT_EN | 14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_MAC_FAST_SYNC | 14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_MAC_SS_EN | 14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0; 143974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 144074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Be sure that RD_THRSH+WR_THRSH <= 32 for pass1 pars 14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above 14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Use a larger RD_THRSH for gigabit 14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1445f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2) 14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds th_value = 28; 1447f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle else 1448f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle th_value = 64; 14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */ 14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((s->sbm_speed == sbmac_speed_1000) 14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ? V_MAC_TX_RD_THRSH(th_value) : V_MAC_TX_RD_THRSH(4)) | 14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_TX_RL_THRSH(4) | 14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_RX_PL_THRSH(4) | 14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_RX_RD_THRSH(4) | /* Must be '4' */ 14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_RX_RL_THRSH(8) | 14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0; 14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framecfg = V_MAC_MIN_FRAMESZ_DEFAULT | 14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_MAX_FRAMESZ_DEFAULT | 14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_BACKOFF_SEL(1); 14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 146474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Clear out the hash address map 14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 146674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = s->sbm_base + R_MAC_HASH_BASE; 14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < MAC_HASH_COUNT; idx++) { 14692039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, port); 14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port += sizeof(uint64_t); 14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 147274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Clear out the exact-match table 14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 147674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = s->sbm_base + R_MAC_ADDR_BASE; 14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < MAC_ADDR_COUNT; idx++) { 14792039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, port); 14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port += sizeof(uint64_t); 14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 148274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Clear out the DMA Channel mapping table registers 14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 148674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = s->sbm_base + R_MAC_CHUP0_BASE; 14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { 14892039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, port); 14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port += sizeof(uint64_t); 14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = s->sbm_base + R_MAC_CHLO0_BASE; 14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { 14962039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, port); 14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port += sizeof(uint64_t); 14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 149974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Program the hardware address. It goes into the hardware-address 15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * register as well as the first filter register. 15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 150474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg = sbmac_addr2reg(s->sbm_hwaddr); 150674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = s->sbm_base + R_MAC_ADDR_BASE; 15082039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, port); 15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = s->sbm_base + R_MAC_ETHERNET_ADDR; 15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS 15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Pass1 SOCs do not receive packets addressed to the 15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * destination address in the R_MAC_ETHERNET_ADDR register. 15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the value to zero. 15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15172039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, port); 15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 15192039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, port); 15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 152174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the receive filter for no packets, and write values 15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * to the various config registers 15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 152674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15272039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, s->sbm_rxfilter); 15282039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, s->sbm_imr); 15292039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(framecfg, s->sbm_framecfg); 15302039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(fifo, s->sbm_fifocfg); 15312039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(cfg, s->sbm_maccfg); 153274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize DMA channels (rings should be ok now) 15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 153674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_channel_start(&(s->sbm_rxdma), DMA_RX); 15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_channel_start(&(s->sbm_txdma), DMA_TX); 153974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Configure the speed, duplex, and flow control 15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_set_speed(s,s->sbm_speed); 15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_set_duplex(s,s->sbm_duplex,s->sbm_fc); 154674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Fill the receive ring 15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 155074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1551789585e968f07653a29a9e829aed20386043636cStephen Hemminger sbdma_fillring(s, &(s->sbm_rxdma)); 155274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 155374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Turn on the rest of the bits in the enable register 155574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle */ 155674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1557f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80) 1558f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle __raw_writeq(M_MAC_RXDMA_EN0 | 1559f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle M_MAC_TXDMA_EN0, s->sbm_macenable); 1560f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X) 15612039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(M_MAC_RXDMA_EN0 | 15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_MAC_TXDMA_EN0 | 15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_MAC_RX_ENABLE | 15642039973af59889fea0d14362eae56792cfe8d25aRalf Baechle M_MAC_TX_ENABLE, s->sbm_macenable); 1565f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#else 15660b1974de66f9ed44f1423449628f4926bf95b854Thomas Weber#error invalid SiByte MAC configuration 1567f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle#endif 15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SBMAC_COALESCE 15702039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | 15712039973af59889fea0d14362eae56792cfe8d25aRalf Baechle ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), s->sbm_imr); 15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 15732039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) | 15742039973af59889fea0d14362eae56792cfe8d25aRalf Baechle (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), s->sbm_imr); 15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 157674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 157774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 157874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Enable receiving unicasts and broadcasts 15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 158074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15812039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(M_MAC_UCAST_EN | M_MAC_BCAST_EN, s->sbm_rxfilter); 158274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 158474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * we're running now. 15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 158674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_state = sbmac_state_on; 158874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 158974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 159074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Program multicast addresses 15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 159274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_setmulti(s); 159474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 159574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 159674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * If channel was in promiscuous mode before, turn that on 15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 159874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s->sbm_devflags & IFF_PROMISC) { 16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_promiscuous_mode(s,1); 16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 160274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_CHANNEL_STOP(s) 160874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Stop packet processing on this MAC. 161074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 161174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * s - sbmac structure 161374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_channel_stop(struct sbmac_softc *s) 16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't do this if already stopped */ 162174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s->sbm_state == sbmac_state_off) 16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 162474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* don't accept any packets, disable all interrupts */ 162674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16272039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, s->sbm_rxfilter); 16282039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, s->sbm_imr); 162974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Turn off ticker */ 163174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XXX */ 163374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* turn off receiver and transmitter */ 163574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16362039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, s->sbm_macenable); 163774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We're stopped now. */ 163974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_state = sbmac_state_off; 164174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Stop DMA channels (rings should be ok now) 16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 164574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_channel_stop(&(s->sbm_rxdma)); 16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_channel_stop(&(s->sbm_txdma)); 164874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Empty the receive and transmit rings */ 165074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_emptyring(&(s->sbm_rxdma)); 16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_emptyring(&(s->sbm_txdma)); 165374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_SET_CHANNEL_STATE(state) 165874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the channel's state ON or OFF 166074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 166174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * state - new state 166374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * old state 16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 166773d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic enum sbmac_state sbmac_set_channel_state(struct sbmac_softc *sc, 166873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_state state) 16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 167073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_state oldstate = sc->sbm_state; 167174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * If same as previous state, return 16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 167574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state == oldstate) { 16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return oldstate; 16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 167974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 168174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * If new state is ON, turn channel on 16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 168374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (state == sbmac_state_on) { 16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_channel_start(sc); 16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_channel_stop(sc); 16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 169074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return previous state 16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 169474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return oldstate; 16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_PROMISCUOUS_MODE(sc,onoff) 170174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Turn on or off promiscuous mode 170374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 170474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sc - softc 17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * onoff - 1 to turn on, 0 to turn off 170774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff) 17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t reg; 171574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sc->sbm_state != sbmac_state_on) 17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 171874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (onoff) { 17202039973af59889fea0d14362eae56792cfe8d25aRalf Baechle reg = __raw_readq(sc->sbm_rxfilter); 17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= M_MAC_ALLPKT_EN; 17222039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, sc->sbm_rxfilter); 172374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle } 17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 17252039973af59889fea0d14362eae56792cfe8d25aRalf Baechle reg = __raw_readq(sc->sbm_rxfilter); 17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg &= ~M_MAC_ALLPKT_EN; 17272039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, sc->sbm_rxfilter); 17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_SETIPHDR_OFFSET(sc,onoff) 173374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set the iphdr offset as 15 assuming ethernet encapsulation 173574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 173674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sc - softc 173874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_set_iphdr_offset(struct sbmac_softc *sc) 17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t reg; 174674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Hard code the off set to 15 for now */ 17482039973af59889fea0d14362eae56792cfe8d25aRalf Baechle reg = __raw_readq(sc->sbm_rxfilter); 17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15); 17502039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, sc->sbm_rxfilter); 175174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 1752f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle /* BCM1250 pass1 didn't have hardware checksum. Everything 1753f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle later does. */ 1754f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2) { 17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sc->rx_hw_checksum = DISABLE; 1756f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle } else { 1757f90fdc3cce3d8c8ed09615dc68cb789655078803Ralf Baechle sc->rx_hw_checksum = ENABLE; 17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_ADDR2REG(ptr) 176474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Convert six bytes into the 64-bit register value that 17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we typically write into the SBMAC's address/mcast registers 176774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 176874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ptr - pointer to 6 bytes 177074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * register value 17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic uint64_t sbmac_addr2reg(unsigned char *ptr) 17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t reg = 0; 177874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ptr += 6; 178074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 178174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle reg |= (uint64_t) *(--ptr); 17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg <<= 8; 178374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle reg |= (uint64_t) *(--ptr); 17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg <<= 8; 178574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle reg |= (uint64_t) *(--ptr); 17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg <<= 8; 178774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle reg |= (uint64_t) *(--ptr); 17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg <<= 8; 178974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle reg |= (uint64_t) *(--ptr); 17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg <<= 8; 179174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle reg |= (uint64_t) *(--ptr); 179274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return reg; 17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_SET_SPEED(s,speed) 179974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Configure LAN speed for the specified MAC. 18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Warning: must be called when MAC is off! 180274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 180374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * s - sbmac structure 180573d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki * speed - speed to set MAC to (see enum sbmac_speed) 180674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 if successful 18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 indicates invalid parameters 18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbmac_set_speed(struct sbmac_softc *s, enum sbmac_speed speed) 18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t cfg; 18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t framecfg; 18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Save new current values 18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 182074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_speed = speed; 182274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s->sbm_state == sbmac_state_on) 18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* save for next restart */ 18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 182774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Read current register values 18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 182974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18302039973af59889fea0d14362eae56792cfe8d25aRalf Baechle cfg = __raw_readq(s->sbm_maccfg); 18312039973af59889fea0d14362eae56792cfe8d25aRalf Baechle framecfg = __raw_readq(s->sbm_framecfg); 183274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Mask out the stuff we want to change 18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 183674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL); 18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH | 18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds M_MAC_SLOT_SIZE); 184074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Now add in the new bits 18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 184474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (speed) { 18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_speed_10: 18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framecfg |= V_MAC_IFG_RX_10 | 18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_IFG_TX_10 | 18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds K_MAC_IFG_THRSH_10 | 18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_SLOT_SIZE_10; 18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= V_MAC_SPEED_SEL_10MBPS; 18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 185374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_speed_100: 18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framecfg |= V_MAC_IFG_RX_100 | 18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_IFG_TX_100 | 18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_IFG_THRSH_100 | 18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_SLOT_SIZE_100; 18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= V_MAC_SPEED_SEL_100MBPS ; 18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 186174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_speed_1000: 18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds framecfg |= V_MAC_IFG_RX_1000 | 18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_IFG_TX_1000 | 18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_IFG_THRSH_1000 | 18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds V_MAC_SLOT_SIZE_1000; 18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN; 18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 186974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 187374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 187574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Send the bits back to the hardware 18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 187774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18782039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(framecfg, s->sbm_framecfg); 18792039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(cfg, s->sbm_maccfg); 188074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_SET_DUPLEX(s,duplex,fc) 188674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set Ethernet duplex and flow control options for this MAC 18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Warning: must be called when MAC is off! 188974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 189074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * s - sbmac structure 189273d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki * duplex - duplex setting (see enum sbmac_duplex) 189373d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki * fc - flow control setting (see enum sbmac_fc) 189474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1 if ok 18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 0 if an invalid parameter combination was specified 18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 190073d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozyckistatic int sbmac_set_duplex(struct sbmac_softc *s, enum sbmac_duplex duplex, 190173d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki enum sbmac_fc fc) 19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t cfg; 190474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Save new current values 19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 190874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_duplex = duplex; 19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s->sbm_fc = fc; 191174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (s->sbm_state == sbmac_state_on) 19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* save for next restart */ 191474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 191674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Read current register values 19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 191874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19192039973af59889fea0d14362eae56792cfe8d25aRalf Baechle cfg = __raw_readq(s->sbm_maccfg); 192074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Mask off the stuff we're about to change 19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 192474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN); 192674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 192774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (duplex) { 19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_duplex_half: 19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fc) { 19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_disabled: 19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED; 19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 193474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_collision: 19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED; 19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 193874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_carrier: 19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR; 19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 194274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_frame: /* not valid in half duplex */ 19441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: /* invalid selection */ 19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 194874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_duplex_full: 19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fc) { 19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_disabled: 19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= V_MAC_FC_CMD_DISABLED; 19531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 195474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_frame: 19561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cfg |= V_MAC_FC_CMD_ENABLED; 19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 195874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_collision: /* not valid in full duplex */ 19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case sbmac_fc_carrier: /* not valid in full duplex */ 19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 19621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1965f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki default: 1966f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return 0; 19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 196874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 197074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Send the bits back to the hardware 19711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 197274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19732039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(cfg, s->sbm_maccfg); 197474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 1; 19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 19771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_INTR() 198374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Interrupt handler for MAC interrupts 198574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 198674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MAC structure 198874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 19927d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t sbmac_intr(int irq,void *dev_instance) 19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = (struct net_device *) dev_instance; 19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t isr; 19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int handled = 0; 19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1999693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason /* 2000693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * Read the ISR (this clears the bits in the real 2001693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * register, except for counter addr) 2002693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason */ 200374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2004693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason isr = __raw_readq(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR; 20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2006693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (isr == 0) 2007693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason return IRQ_RETVAL(0); 2008693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason handled = 1; 200974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2010693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason /* 2011693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason * Transmits on channel 0 2012693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason */ 201374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2014bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) 2015693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason sbdma_tx_process(sc,&(sc->sbm_txdma), 0); 201674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2017693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) { 2018288379f050284087578b77e04f040b57db3db3f8Ben Hutchings if (napi_schedule_prep(&sc->napi)) { 2019693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason __raw_writeq(0, sc->sbm_imr); 2020288379f050284087578b77e04f040b57db3db3f8Ben Hutchings __napi_schedule(&sc->napi); 2021693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason /* Depend on the exit from poll to reenable intr */ 2022693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason } 2023693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason else { 2024693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason /* may leave some packets behind */ 2025693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason sbdma_rx_process(sc,&(sc->sbm_rxdma), 2026693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason SBMAC_MAX_RXDESCR * 2, 0); 20271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_RETVAL(handled); 20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_START_TX(skb,dev) 203474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 203574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Start output on the specified interface. Basically, we 20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * queue as many buffers as we can until the ring fills up, or 20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * we run off the end of the queue, whichever comes first. 203874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 203974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 204074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 204174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev) 20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 2048be61ea52900b97800effbb68478915d73b5d4df2Weiwei Wang unsigned long flags; 204974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* lock eth irq */ 2051be61ea52900b97800effbb68478915d73b5d4df2Weiwei Wang spin_lock_irqsave(&sc->sbm_lock, flags); 205274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 205474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Put the buffer on the transmit ring. If we 20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * don't have room, stop the queue. 20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 205774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) { 20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XXX save skb that we could not send */ 20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(dev); 2061be61ea52900b97800effbb68478915d73b5d4df2Weiwei Wang spin_unlock_irqrestore(&sc->sbm_lock, flags); 20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20635b548140225c6bbbbd560551dd1048b2c0ce58bePatrick McHardy return NETDEV_TX_BUSY; 20641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 206574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2066be61ea52900b97800effbb68478915d73b5d4df2Weiwei Wang spin_unlock_irqrestore(&sc->sbm_lock, flags); 206774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 20686ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy return NETDEV_TX_OK; 20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_SETMULTI(sc) 207374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reprogram the multicast table into the hardware, given 20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the list of multicasts associated with the interface 20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * structure. 207774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 207874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * sc - softc 208074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * nothing 20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 20841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 20851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_setmulti(struct sbmac_softc *sc) 20861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t reg; 208873d7396980176a5f4515be2f6e39ee417d2369baMaciej W. Rozycki void __iomem *port; 20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int idx; 209022bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko struct netdev_hw_addr *ha; 20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = sc->sbm_dev; 209274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 209374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Clear out entire multicast table. We do this by nuking 20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the entire hash table and all the direct matches except 209674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * the first one, which is used for our station address 20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 209874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 1; idx < MAC_ADDR_COUNT; idx++) { 21001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t)); 21012039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, port); 21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 210374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (idx = 0; idx < MAC_HASH_COUNT; idx++) { 21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t)); 21062039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, port); 21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 210874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Clear the filter to say we don't want any multicasts. 21111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 211274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21132039973af59889fea0d14362eae56792cfe8d25aRalf Baechle reg = __raw_readq(sc->sbm_rxfilter); 21141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg &= ~(M_MAC_MCAST_INV | M_MAC_MCAST_EN); 21152039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, sc->sbm_rxfilter); 211674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->flags & IFF_ALLMULTI) { 211874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 211974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Enable ALL multicasts. Do this by inverting the 212074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * multicast enable bit. 21211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 21222039973af59889fea0d14362eae56792cfe8d25aRalf Baechle reg = __raw_readq(sc->sbm_rxfilter); 21231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= (M_MAC_MCAST_INV | M_MAC_MCAST_EN); 21242039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, sc->sbm_rxfilter); 21251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 212874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 212974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Progam new multicast entries. For now, only use the 21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * perfect filter. In the future we'll need to use the 21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hash filter if the perfect filter overflows 21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 213474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XXX only using perfect filter for now, need to use hash 21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * XXX if the table overflows */ 213774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds idx = 1; /* skip station address */ 213922bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko netdev_for_each_mc_addr(ha, dev) { 21405508590c193661bc1484ad7b952af5fceacea40dJiri Pirko if (idx == MAC_ADDR_COUNT) 21415508590c193661bc1484ad7b952af5fceacea40dJiri Pirko break; 214222bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko reg = sbmac_addr2reg(ha->addr); 21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t)); 21442039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, port); 21451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds idx++; 21461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 214774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 214874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 21491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Enable the "accept multicast bits" if we programmed at least one 215074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * multicast. 21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 215274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (idx > 1) { 21542039973af59889fea0d14362eae56792cfe8d25aRalf Baechle reg = __raw_readq(sc->sbm_rxfilter); 21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg |= M_MAC_MCAST_EN; 21562039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(reg, sc->sbm_rxfilter); 21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sb1250_change_mtu(struct net_device *_dev, int new_mtu) 21611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_mtu > ENET_PACKET_SIZE) 21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds _dev->mtu = new_mtu; 2165f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_info("changing the mtu to %d\n", new_mtu); 21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2169b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalovstatic const struct net_device_ops sbmac_netdev_ops = { 2170b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_open = sbmac_open, 2171b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_stop = sbmac_close, 2172b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_start_xmit = sbmac_start_tx, 2173afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko .ndo_set_rx_mode = sbmac_set_rx_mode, 2174b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_tx_timeout = sbmac_tx_timeout, 2175b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_do_ioctl = sbmac_mii_ioctl, 2176b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_change_mtu = sb1250_change_mtu, 2177b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_validate_addr = eth_validate_addr, 2178b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_set_mac_address = eth_mac_addr, 2179b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov#ifdef CONFIG_NET_POLL_CONTROLLER 2180b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov .ndo_poll_controller = sbmac_netpoll, 2181b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov#endif 2182b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov}; 2183b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov 21841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************** 21851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SBMAC_INIT(dev) 218674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 21871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Attach routine - init hardware and hook ourselves into linux 218874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 218974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * Input parameters: 21901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * dev - net_device structure 219174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle * 21921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return value: 21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * status 21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ********************************************************************* */ 21951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2196f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic int sbmac_init(struct platform_device *pldev, long long base) 21971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 21988513fbd880093f00a47e85a552f14ca2de8d84d6Jingoo Han struct net_device *dev = platform_get_drvdata(pldev); 2199f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int idx = pldev->id; 2200f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct sbmac_softc *sc = netdev_priv(dev); 22011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char *eaddr; 22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds uint64_t ea_reg; 22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 22041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 220574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sc->sbm_dev = dev; 22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sc->sbe_idx = idx; 220874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eaddr = sc->sbm_hwaddr; 221074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 221174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 2212877d03105d04b2c13e241130277fa69c8d2564f0Nick Andrew * Read the ethernet address. The firmware left this programmed 22131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for us in the ethernet address register for each mac. 22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 221574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 22162039973af59889fea0d14362eae56792cfe8d25aRalf Baechle ea_reg = __raw_readq(sc->sbm_base + R_MAC_ETHERNET_ADDR); 22172039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_writeq(0, sc->sbm_base + R_MAC_ETHERNET_ADDR); 22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 6; i++) { 22191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds eaddr[i] = (uint8_t) (ea_reg & 0xFF); 22201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ea_reg >>= 8; 22211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 222274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 6; i++) { 22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dev_addr[i] = eaddr[i]; 22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 222674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 222774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Initialize context (get pointers to registers and stuff), then 22291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * allocate the memory for the descriptor tables. 22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 223174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 22321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_initctx(sc); 223374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 22341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 22351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set up Linux device callins 22361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 223774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 22381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&(sc->sbm_lock)); 223974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2240b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov dev->netdev_ops = &sbmac_netdev_ops; 2241b4cf3421afce25655233cf66f6ec545baa8cb6aeAlexander Beregalov dev->watchdog_timeo = TX_TIMEOUT; 2242bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger 2243bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger netif_napi_add(dev, &sc->napi, sbmac_poll, 16); 22441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2245f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki dev->irq = UNIT_INT(idx); 2246f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 22471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This is needed for PASS2 for Rx H/W checksum feature */ 22481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_set_iphdr_offset(sc); 22491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2250298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek sc->mii_bus = mdiobus_alloc(); 2251298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek if (sc->mii_bus == NULL) { 225203f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior err = -ENOMEM; 225303f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior goto uninit_ctx; 2254298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek } 2255298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek 225603f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sc->mii_bus->name = sbmac_mdio_string; 2257446bbc4b5ee122c3a3a4954b144d031f0f9aa006Florian Fainelli snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x", 2258446bbc4b5ee122c3a3a4954b144d031f0f9aa006Florian Fainelli pldev->name, idx); 225903f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sc->mii_bus->priv = sc; 226003f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sc->mii_bus->read = sbmac_mii_read; 226103f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sc->mii_bus->write = sbmac_mii_write; 226203f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sc->mii_bus->irq = sc->phy_irq; 226303f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior for (i = 0; i < PHY_MAX_ADDR; ++i) 226403f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sc->mii_bus->irq[i] = SBMAC_PHY_INT; 226503f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior 226603f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sc->mii_bus->parent = &pldev->dev; 226703f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior /* 226803f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior * Probe PHY address 226903f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior */ 227003f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior err = mdiobus_register(sc->mii_bus); 227103f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior if (err) { 227203f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior printk(KERN_ERR "%s: unable to register MDIO bus\n", 227303f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior dev->name); 227403f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior goto free_mdio; 227503f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior } 22768513fbd880093f00a47e85a552f14ca2de8d84d6Jingoo Han platform_set_drvdata(pldev, sc->mii_bus); 227703f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior 22781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = register_netdev(dev); 2279f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (err) { 2280f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki printk(KERN_ERR "%s.%d: unable to register netdev\n", 2281f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_string, idx); 228203f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior goto unreg_mdio; 22831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 22841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2285f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_info("%s.%d: registered as %s\n", sbmac_string, idx, dev->name); 2286f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2287f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (sc->rx_hw_checksum == ENABLE) 2288f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_info("%s: enabling TCP rcv checksum\n", dev->name); 2289f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 22901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 22911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Display Ethernet address (this is called during the config 22921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * process so we need to finish off the config message that 22931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * was being displayed) 22941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2295e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %pM\n", 2296e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg dev->name, base, eaddr); 22971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2298f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return 0; 229903f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewiorunreg_mdio: 230003f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior mdiobus_unregister(sc->mii_bus); 230103f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewiorfree_mdio: 230203f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior mdiobus_free(sc->mii_bus); 230303f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewioruninit_ctx: 230403f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior sbmac_uninitctx(sc); 230503f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior return err; 23061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 23071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_open(struct net_device *dev) 23101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 23111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 2312f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int err; 231374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2314f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (debug > 1) 2315f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_debug("%s: sbmac_open() irq %d.\n", dev->name, dev->irq); 231674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 231774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle /* 23181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * map/route interrupt (clear status first, in case something 23191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * weird is pending; we haven't initialized the mac registers 23201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * yet) 23211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 23221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23232039973af59889fea0d14362eae56792cfe8d25aRalf Baechle __raw_readq(sc->sbm_isr); 2324a0607fd3a25ba1848a63a0d925e36d914735ab47Joe Perches err = request_irq(dev->irq, sbmac_intr, IRQF_SHARED, dev->name, dev); 2325f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (err) { 2326f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name, 2327f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki dev->irq); 2328f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki goto out_err; 2329f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki } 23301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2331f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_speed = sbmac_speed_none; 2332f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_duplex = sbmac_duplex_none; 2333f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_fc = sbmac_fc_none; 2334f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_pause = -1; 2335f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_link = 0; 2336bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger 233759b81827071a8ae7f399da533d268e1e33bfeeb7Ralf Baechle /* 2338f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * Attach to the PHY 23391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2340f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki err = sbmac_mii_probe(dev); 2341f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (err) 2342f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki goto out_unregister; 234374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 23441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 23451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Turn on the channel 23461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 23471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 23481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_set_channel_state(sc,sbmac_state_on); 234974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 23501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_start_queue(dev); 235174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 23521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_set_rx_mode(dev); 235374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2354f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki phy_start(sc->phy_dev); 2355f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2356f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki napi_enable(&sc->napi); 235774b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 23581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2359f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2360f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckiout_unregister: 2361f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki free_irq(dev->irq, dev); 2362f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckiout_err: 2363f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return err; 23641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 23651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 236659b81827071a8ae7f399da533d268e1e33bfeeb7Ralf Baechlestatic int sbmac_mii_probe(struct net_device *dev) 236759b81827071a8ae7f399da533d268e1e33bfeeb7Ralf Baechle{ 2368f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct sbmac_softc *sc = netdev_priv(dev); 2369f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct phy_device *phy_dev; 237059b81827071a8ae7f399da533d268e1e33bfeeb7Ralf Baechle int i; 23711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2372f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki for (i = 0; i < PHY_MAX_ADDR; i++) { 2373298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek phy_dev = sc->mii_bus->phy_map[i]; 2374f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (phy_dev) 2375f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki break; 23761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2377f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (!phy_dev) { 2378f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki printk(KERN_ERR "%s: no PHY found\n", dev->name); 2379f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return -ENXIO; 23801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2382f9a8f83b04e0c362a2fc660dbad980d24af209fcFlorian Fainelli phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), &sbmac_mii_poll, 2383f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki PHY_INTERFACE_MODE_GMII); 2384f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (IS_ERR(phy_dev)) { 2385f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki printk(KERN_ERR "%s: could not attach to PHY\n", dev->name); 2386f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return PTR_ERR(phy_dev); 23871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 23881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2389f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki /* Remove any features not supported by the controller */ 2390f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki phy_dev->supported &= SUPPORTED_10baseT_Half | 2391f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_10baseT_Full | 2392f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_100baseT_Half | 2393f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_100baseT_Full | 2394f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_1000baseT_Half | 2395f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_1000baseT_Full | 2396f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_Autoneg | 2397f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_MII | 2398f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_Pause | 2399f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SUPPORTED_Asym_Pause; 2400f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki phy_dev->advertising = phy_dev->supported; 2401f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2402f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", 2403f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki dev->name, phy_dev->drv->name, 2404db1d7bf70f42124f73675fca62fe32f3ab1111b4Kay Sievers dev_name(&phy_dev->dev), phy_dev->irq); 2405f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2406f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->phy_dev = phy_dev; 24071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2408f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return 0; 24091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2412f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic void sbmac_mii_poll(struct net_device *dev) 24131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 2415f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct phy_device *phy_dev = sc->phy_dev; 2416f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki unsigned long flags; 2417f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki enum sbmac_fc fc; 2418f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int link_chg, speed_chg, duplex_chg, pause_chg, fc_chg; 2419f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2420f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki link_chg = (sc->sbm_link != phy_dev->link); 2421f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki speed_chg = (sc->sbm_speed != phy_dev->speed); 2422f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki duplex_chg = (sc->sbm_duplex != phy_dev->duplex); 2423f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pause_chg = (sc->sbm_pause != phy_dev->pause); 2424f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2425f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (!link_chg && !speed_chg && !duplex_chg && !pause_chg) 2426f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return; /* Hmmm... */ 2427f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2428f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (!phy_dev->link) { 2429f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (link_chg) { 2430f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_link = phy_dev->link; 2431f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_speed = sbmac_speed_none; 2432f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_duplex = sbmac_duplex_none; 2433f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_fc = sbmac_fc_disabled; 2434f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_pause = -1; 2435f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_info("%s: link unavailable\n", dev->name); 2436f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki } 2437f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return; 2438f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki } 24391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2440f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (phy_dev->duplex == DUPLEX_FULL) { 2441f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (phy_dev->pause) 2442f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki fc = sbmac_fc_frame; 2443f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki else 2444f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki fc = sbmac_fc_disabled; 2445f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki } else 2446f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki fc = sbmac_fc_collision; 2447f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki fc_chg = (sc->sbm_fc != fc); 244874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2449f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_info("%s: link available: %dbase-%cD\n", dev->name, phy_dev->speed, 2450f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki phy_dev->duplex == DUPLEX_FULL ? 'F' : 'H'); 245174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2452f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki spin_lock_irqsave(&sc->sbm_lock, flags); 245374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2454f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_speed = phy_dev->speed; 2455f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_duplex = phy_dev->duplex; 2456f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_fc = fc; 2457f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_pause = phy_dev->pause; 2458f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_link = phy_dev->link; 24591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2460f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if ((speed_chg || duplex_chg || fc_chg) && 2461f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_state != sbmac_state_off) { 2462f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki /* 2463f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * something changed, restart the channel 2464f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki */ 2465f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (debug > 1) 2466f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_debug("%s: restarting channel " 2467f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki "because PHY state changed\n", dev->name); 2468f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_channel_stop(sc); 2469f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_channel_start(sc); 24701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 247174b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2472f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki spin_unlock_irqrestore(&sc->sbm_lock, flags); 24731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_tx_timeout (struct net_device *dev) 24771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 2479be61ea52900b97800effbb68478915d73b5d4df2Weiwei Wang unsigned long flags; 248074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2481be61ea52900b97800effbb68478915d73b5d4df2Weiwei Wang spin_lock_irqsave(&sc->sbm_lock, flags); 248274b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 248374b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 24841ae5dc342ac78d7a42965fd1f323815f6f5ef2c1Eric Dumazet dev->trans_start = jiffies; /* prevent tx timeout */ 248509f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik dev->stats.tx_errors++; 248674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2487be61ea52900b97800effbb68478915d73b5d4df2Weiwei Wang spin_unlock_irqrestore(&sc->sbm_lock, flags); 24881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk (KERN_WARNING "%s: Transmit timed out\n",dev->name); 24901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 24911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sbmac_set_rx_mode(struct net_device *dev) 24961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 24971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&sc->sbm_lock, flags); 25011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((dev->flags ^ sc->sbm_devflags) & IFF_PROMISC) { 25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Promiscuous changed. 25041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 250574b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 250674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle if (dev->flags & IFF_PROMISC) { 25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_promiscuous_mode(sc,1); 25081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_promiscuous_mode(sc,0); 25111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&sc->sbm_lock, flags); 251474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 25151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 25161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Program the multicasts. Do this every time. 25171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 251874b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 25191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbmac_setmulti(sc); 252074b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 25211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 25241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 252674b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 2527f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (!netif_running(dev) || !sc->phy_dev) 2528f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return -EINVAL; 252974b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 253028b041139e344ecd0f144d6205b004ae354cfa1eRichard Cochran return phy_mii_ioctl(sc->phy_dev, rq, cmd); 25311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sbmac_close(struct net_device *dev) 25341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 25351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sbmac_softc *sc = netdev_priv(dev); 25361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2537bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger napi_disable(&sc->napi); 2538bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger 2539f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki phy_stop(sc->phy_dev); 25401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2541f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_set_channel_state(sc, sbmac_state_off); 25421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(dev); 25441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2545f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (debug > 1) 2546f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki pr_debug("%s: Shutting down ethercard\n", dev->name); 25471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2548f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki phy_disconnect(sc->phy_dev); 2549f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->phy_dev = NULL; 2550f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki free_irq(dev->irq, dev); 25511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 25521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_emptyring(&(sc->sbm_txdma)); 25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbdma_emptyring(&(sc->sbm_rxdma)); 255474b0247fbd4b6ed1693a420d85cf50267d840ef4Ralf Baechle 25551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 25561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 25571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2558bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemmingerstatic int sbmac_poll(struct napi_struct *napi, int budget) 2559693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason{ 2560bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger struct sbmac_softc *sc = container_of(napi, struct sbmac_softc, napi); 2561693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason int work_done; 25621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2563bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger work_done = sbdma_rx_process(sc, &(sc->sbm_rxdma), budget, 1); 2564693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason sbdma_tx_process(sc, &(sc->sbm_txdma), 1); 2565693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 2566bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger if (work_done < budget) { 2567288379f050284087578b77e04f040b57db3db3f8Ben Hutchings napi_complete(napi); 2568693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 2569693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#ifdef CONFIG_SBMAC_COALESCE 2570693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | 2571693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), 2572693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason sc->sbm_imr); 2573693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#else 2574693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) | 2575693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), sc->sbm_imr); 2576693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason#endif 2577693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason } 2578693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason 2579bea3348eef27e6044b6161fd04c3152215f96411Stephen Hemminger return work_done; 2580693aa9470d8273a0ded8b211a8f5f7c0835adf30Mark Mason} 25811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2582f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2583047fc56614f8f8d03fb64ef3be44f040aad25d56Bill Pembertonstatic int sbmac_probe(struct platform_device *pldev) 2584f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki{ 2585f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct net_device *dev; 2586f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct sbmac_softc *sc; 2587f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki void __iomem *sbm_base; 2588f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct resource *res; 2589f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki u64 sbmac_orig_hwaddr; 2590f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki int err; 2591f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2592f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki res = platform_get_resource(pldev, IORESOURCE_MEM, 0); 2593f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki BUG_ON(!res); 259428f65c11f2ffb3957259dece647a24f8ad2e241bJoe Perches sbm_base = ioremap_nocache(res->start, resource_size(res)); 2595f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (!sbm_base) { 2596f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki printk(KERN_ERR "%s: unable to map device registers\n", 2597db1d7bf70f42124f73675fca62fe32f3ab1111b4Kay Sievers dev_name(&pldev->dev)); 2598f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki err = -ENOMEM; 2599f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki goto out_out; 2600f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki } 2601f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2602f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki /* 2603f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * The R_MAC_ETHERNET_ADDR register will be set to some nonzero 2604f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * value for us by the firmware if we're going to use this MAC. 2605f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * If we find a zero, skip this MAC. 2606f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki */ 2607f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_orig_hwaddr = __raw_readq(sbm_base + R_MAC_ETHERNET_ADDR); 2608db1d7bf70f42124f73675fca62fe32f3ab1111b4Kay Sievers pr_debug("%s: %sconfiguring MAC at 0x%08Lx\n", dev_name(&pldev->dev), 2609f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_orig_hwaddr ? "" : "not ", (long long)res->start); 2610f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (sbmac_orig_hwaddr == 0) { 2611f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki err = 0; 2612f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki goto out_unmap; 2613f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki } 2614f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2615f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki /* 2616f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki * Okay, cool. Initialize this MAC. 2617f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki */ 2618f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki dev = alloc_etherdev(sizeof(struct sbmac_softc)); 2619f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (!dev) { 2620f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki err = -ENOMEM; 2621f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki goto out_unmap; 2622f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki } 2623f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 26248513fbd880093f00a47e85a552f14ca2de8d84d6Jingoo Han platform_set_drvdata(pldev, dev); 2625f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki SET_NETDEV_DEV(dev, &pldev->dev); 2626f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2627f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc = netdev_priv(dev); 2628f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sc->sbm_base = sbm_base; 2629f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2630f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki err = sbmac_init(pldev, res->start); 2631f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki if (err) 2632f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki goto out_kfree; 2633f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2634f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return 0; 2635f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2636f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckiout_kfree: 2637f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki free_netdev(dev); 2638f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki __raw_writeq(sbmac_orig_hwaddr, sbm_base + R_MAC_ETHERNET_ADDR); 2639f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2640f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckiout_unmap: 2641f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki iounmap(sbm_base); 2642f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2643f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckiout_out: 2644f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return err; 2645f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki} 2646f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2647f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic int __exit sbmac_remove(struct platform_device *pldev) 2648f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki{ 26498513fbd880093f00a47e85a552f14ca2de8d84d6Jingoo Han struct net_device *dev = platform_get_drvdata(pldev); 2650f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki struct sbmac_softc *sc = netdev_priv(dev); 2651f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2652f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki unregister_netdev(dev); 2653f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki sbmac_uninitctx(sc); 265403f80cc3f24e1dcdbdba081ed5daf5575aac6180Sebastian Siewior mdiobus_unregister(sc->mii_bus); 2655298cf9beb9679522de995e249eccbd82f7c51999Lennert Buytenhek mdiobus_free(sc->mii_bus); 2656f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki iounmap(sc->sbm_base); 2657f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki free_netdev(dev); 2658f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2659f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki return 0; 2660f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki} 2661f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki 2662f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozyckistatic struct platform_driver sbmac_driver = { 2663f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki .probe = sbmac_probe, 2664f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki .remove = __exit_p(sbmac_remove), 2665f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki .driver = { 2666f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki .name = sbmac_string, 266733b665eeeb85956ccbdf31c4c31a4e2a31133c44Ralf Baechle .owner = THIS_MODULE, 2668f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki }, 2669f5279ffdce9bcff938451303126971098e23aab3Maciej W. Rozycki}; 26701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671db62f684deeb291ab2533b99843d5df9a36b1f19Axel Linmodule_platform_driver(sbmac_driver); 2672