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