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