xref: /rk3399_rockchip-uboot/drivers/net/smc911x.c (revision de1b686b763aa8b87a86f6748ce9169e7fc0e4cd)
1*de1b686bSSascha Hauer /*
2*de1b686bSSascha Hauer  * SMSC LAN9[12]1[567] Network driver
3*de1b686bSSascha Hauer  *
4*de1b686bSSascha Hauer  * (c) 2007 Pengutronix, Sascha Hauer <s.hauer <at> pengutronix.de>
5*de1b686bSSascha Hauer  *
6*de1b686bSSascha Hauer  * See file CREDITS for list of people who contributed to this
7*de1b686bSSascha Hauer  * project.
8*de1b686bSSascha Hauer  *
9*de1b686bSSascha Hauer  * This program is free software; you can redistribute it and/or
10*de1b686bSSascha Hauer  * modify it under the terms of the GNU General Public License as
11*de1b686bSSascha Hauer  * published by the Free Software Foundation; either version 2 of
12*de1b686bSSascha Hauer  * the License, or (at your option) any later version.
13*de1b686bSSascha Hauer  *
14*de1b686bSSascha Hauer  * This program is distributed in the hope that it will be useful,
15*de1b686bSSascha Hauer  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16*de1b686bSSascha Hauer  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17*de1b686bSSascha Hauer  * GNU General Public License for more details.
18*de1b686bSSascha Hauer  *
19*de1b686bSSascha Hauer  * You should have received a copy of the GNU General Public License
20*de1b686bSSascha Hauer  * along with this program; if not, write to the Free Software
21*de1b686bSSascha Hauer  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22*de1b686bSSascha Hauer  * MA 02111-1307 USA
23*de1b686bSSascha Hauer  */
24*de1b686bSSascha Hauer 
25*de1b686bSSascha Hauer #include <common.h>
26*de1b686bSSascha Hauer 
27*de1b686bSSascha Hauer #ifdef CONFIG_DRIVER_SMC911X
28*de1b686bSSascha Hauer 
29*de1b686bSSascha Hauer #include <command.h>
30*de1b686bSSascha Hauer #include <net.h>
31*de1b686bSSascha Hauer #include <miiphy.h>
32*de1b686bSSascha Hauer 
33*de1b686bSSascha Hauer #define mdelay(n)       udelay((n)*1000)
34*de1b686bSSascha Hauer 
35*de1b686bSSascha Hauer #define __REG(x)     (*((volatile u32 *)(x)))
36*de1b686bSSascha Hauer 
37*de1b686bSSascha Hauer /* Below are the register offsets and bit definitions
38*de1b686bSSascha Hauer  * of the Lan911x memory space
39*de1b686bSSascha Hauer  */
40*de1b686bSSascha Hauer #define RX_DATA_FIFO		 __REG(CONFIG_DRIVER_SMC911X_BASE + 0x00)
41*de1b686bSSascha Hauer 
42*de1b686bSSascha Hauer #define TX_DATA_FIFO		 __REG(CONFIG_DRIVER_SMC911X_BASE + 0x20)
43*de1b686bSSascha Hauer #define	TX_CMD_A_INT_ON_COMP			(0x80000000)
44*de1b686bSSascha Hauer #define	TX_CMD_A_INT_BUF_END_ALGN		(0x03000000)
45*de1b686bSSascha Hauer #define	TX_CMD_A_INT_4_BYTE_ALGN		(0x00000000)
46*de1b686bSSascha Hauer #define	TX_CMD_A_INT_16_BYTE_ALGN		(0x01000000)
47*de1b686bSSascha Hauer #define	TX_CMD_A_INT_32_BYTE_ALGN		(0x02000000)
48*de1b686bSSascha Hauer #define	TX_CMD_A_INT_DATA_OFFSET		(0x001F0000)
49*de1b686bSSascha Hauer #define	TX_CMD_A_INT_FIRST_SEG			(0x00002000)
50*de1b686bSSascha Hauer #define	TX_CMD_A_INT_LAST_SEG			(0x00001000)
51*de1b686bSSascha Hauer #define	TX_CMD_A_BUF_SIZE			(0x000007FF)
52*de1b686bSSascha Hauer #define	TX_CMD_B_PKT_TAG			(0xFFFF0000)
53*de1b686bSSascha Hauer #define	TX_CMD_B_ADD_CRC_DISABLE		(0x00002000)
54*de1b686bSSascha Hauer #define	TX_CMD_B_DISABLE_PADDING		(0x00001000)
55*de1b686bSSascha Hauer #define	TX_CMD_B_PKT_BYTE_LENGTH		(0x000007FF)
56*de1b686bSSascha Hauer 
57*de1b686bSSascha Hauer #define RX_STATUS_FIFO		__REG(CONFIG_DRIVER_SMC911X_BASE + 0x40)
58*de1b686bSSascha Hauer #define	RX_STS_PKT_LEN				(0x3FFF0000)
59*de1b686bSSascha Hauer #define	RX_STS_ES				(0x00008000)
60*de1b686bSSascha Hauer #define	RX_STS_BCST				(0x00002000)
61*de1b686bSSascha Hauer #define	RX_STS_LEN_ERR				(0x00001000)
62*de1b686bSSascha Hauer #define	RX_STS_RUNT_ERR				(0x00000800)
63*de1b686bSSascha Hauer #define	RX_STS_MCAST				(0x00000400)
64*de1b686bSSascha Hauer #define	RX_STS_TOO_LONG				(0x00000080)
65*de1b686bSSascha Hauer #define	RX_STS_COLL				(0x00000040)
66*de1b686bSSascha Hauer #define	RX_STS_ETH_TYPE				(0x00000020)
67*de1b686bSSascha Hauer #define	RX_STS_WDOG_TMT				(0x00000010)
68*de1b686bSSascha Hauer #define	RX_STS_MII_ERR				(0x00000008)
69*de1b686bSSascha Hauer #define	RX_STS_DRIBBLING			(0x00000004)
70*de1b686bSSascha Hauer #define	RX_STS_CRC_ERR				(0x00000002)
71*de1b686bSSascha Hauer #define RX_STATUS_FIFO_PEEK 	__REG(CONFIG_DRIVER_SMC911X_BASE + 0x44)
72*de1b686bSSascha Hauer #define TX_STATUS_FIFO		__REG(CONFIG_DRIVER_SMC911X_BASE + 0x48)
73*de1b686bSSascha Hauer #define	TX_STS_TAG				(0xFFFF0000)
74*de1b686bSSascha Hauer #define	TX_STS_ES				(0x00008000)
75*de1b686bSSascha Hauer #define	TX_STS_LOC				(0x00000800)
76*de1b686bSSascha Hauer #define	TX_STS_NO_CARR				(0x00000400)
77*de1b686bSSascha Hauer #define	TX_STS_LATE_COLL			(0x00000200)
78*de1b686bSSascha Hauer #define	TX_STS_MANY_COLL			(0x00000100)
79*de1b686bSSascha Hauer #define	TX_STS_COLL_CNT				(0x00000078)
80*de1b686bSSascha Hauer #define	TX_STS_MANY_DEFER			(0x00000004)
81*de1b686bSSascha Hauer #define	TX_STS_UNDERRUN				(0x00000002)
82*de1b686bSSascha Hauer #define	TX_STS_DEFERRED				(0x00000001)
83*de1b686bSSascha Hauer #define TX_STATUS_FIFO_PEEK	__REG(CONFIG_DRIVER_SMC911X_BASE + 0x4C)
84*de1b686bSSascha Hauer #define ID_REV			__REG(CONFIG_DRIVER_SMC911X_BASE + 0x50)
85*de1b686bSSascha Hauer #define	ID_REV_CHIP_ID				(0xFFFF0000)  /* RO */
86*de1b686bSSascha Hauer #define	ID_REV_REV_ID				(0x0000FFFF)  /* RO */
87*de1b686bSSascha Hauer 
88*de1b686bSSascha Hauer #define INT_CFG			__REG(CONFIG_DRIVER_SMC911X_BASE + 0x54)
89*de1b686bSSascha Hauer #define	INT_CFG_INT_DEAS			(0xFF000000)  /* R/W */
90*de1b686bSSascha Hauer #define	INT_CFG_INT_DEAS_CLR			(0x00004000)
91*de1b686bSSascha Hauer #define	INT_CFG_INT_DEAS_STS			(0x00002000)
92*de1b686bSSascha Hauer #define	INT_CFG_IRQ_INT				(0x00001000)  /* RO */
93*de1b686bSSascha Hauer #define	INT_CFG_IRQ_EN				(0x00000100)  /* R/W */
94*de1b686bSSascha Hauer #define	INT_CFG_IRQ_POL				(0x00000010)  /* R/W Not Affected by SW Reset */
95*de1b686bSSascha Hauer #define	INT_CFG_IRQ_TYPE			(0x00000001)  /* R/W Not Affected by SW Reset */
96*de1b686bSSascha Hauer 
97*de1b686bSSascha Hauer #define INT_STS			__REG(CONFIG_DRIVER_SMC911X_BASE + 0x58)
98*de1b686bSSascha Hauer #define	INT_STS_SW_INT				(0x80000000)  /* R/WC */
99*de1b686bSSascha Hauer #define	INT_STS_TXSTOP_INT			(0x02000000)  /* R/WC */
100*de1b686bSSascha Hauer #define	INT_STS_RXSTOP_INT			(0x01000000)  /* R/WC */
101*de1b686bSSascha Hauer #define	INT_STS_RXDFH_INT			(0x00800000)  /* R/WC */
102*de1b686bSSascha Hauer #define	INT_STS_RXDF_INT			(0x00400000)  /* R/WC */
103*de1b686bSSascha Hauer #define	INT_STS_TX_IOC				(0x00200000)  /* R/WC */
104*de1b686bSSascha Hauer #define	INT_STS_RXD_INT				(0x00100000)  /* R/WC */
105*de1b686bSSascha Hauer #define	INT_STS_GPT_INT				(0x00080000)  /* R/WC */
106*de1b686bSSascha Hauer #define	INT_STS_PHY_INT				(0x00040000)  /* RO */
107*de1b686bSSascha Hauer #define	INT_STS_PME_INT				(0x00020000)  /* R/WC */
108*de1b686bSSascha Hauer #define	INT_STS_TXSO				(0x00010000)  /* R/WC */
109*de1b686bSSascha Hauer #define	INT_STS_RWT				(0x00008000)  /* R/WC */
110*de1b686bSSascha Hauer #define	INT_STS_RXE				(0x00004000)  /* R/WC */
111*de1b686bSSascha Hauer #define	INT_STS_TXE				(0x00002000)  /* R/WC */
112*de1b686bSSascha Hauer /*#define	INT_STS_ERX		(0x00001000)*/  /* R/WC */
113*de1b686bSSascha Hauer #define	INT_STS_TDFU				(0x00000800)  /* R/WC */
114*de1b686bSSascha Hauer #define	INT_STS_TDFO				(0x00000400)  /* R/WC */
115*de1b686bSSascha Hauer #define	INT_STS_TDFA				(0x00000200)  /* R/WC */
116*de1b686bSSascha Hauer #define	INT_STS_TSFF				(0x00000100)  /* R/WC */
117*de1b686bSSascha Hauer #define	INT_STS_TSFL				(0x00000080)  /* R/WC */
118*de1b686bSSascha Hauer /*#define	INT_STS_RXDF		(0x00000040)*/  /* R/WC */
119*de1b686bSSascha Hauer #define	INT_STS_RDFO				(0x00000040)  /* R/WC */
120*de1b686bSSascha Hauer #define	INT_STS_RDFL				(0x00000020)  /* R/WC */
121*de1b686bSSascha Hauer #define	INT_STS_RSFF				(0x00000010)  /* R/WC */
122*de1b686bSSascha Hauer #define	INT_STS_RSFL				(0x00000008)  /* R/WC */
123*de1b686bSSascha Hauer #define	INT_STS_GPIO2_INT			(0x00000004)  /* R/WC */
124*de1b686bSSascha Hauer #define	INT_STS_GPIO1_INT			(0x00000002)  /* R/WC */
125*de1b686bSSascha Hauer #define	INT_STS_GPIO0_INT			(0x00000001)  /* R/WC */
126*de1b686bSSascha Hauer #define INT_EN			__REG(CONFIG_DRIVER_SMC911X_BASE + 0x5C)
127*de1b686bSSascha Hauer #define	INT_EN_SW_INT_EN			(0x80000000)  /* R/W */
128*de1b686bSSascha Hauer #define	INT_EN_TXSTOP_INT_EN			(0x02000000)  /* R/W */
129*de1b686bSSascha Hauer #define	INT_EN_RXSTOP_INT_EN			(0x01000000)  /* R/W */
130*de1b686bSSascha Hauer #define	INT_EN_RXDFH_INT_EN			(0x00800000)  /* R/W */
131*de1b686bSSascha Hauer /*#define	INT_EN_RXDF_INT_EN		(0x00400000)*/  /* R/W */
132*de1b686bSSascha Hauer #define	INT_EN_TIOC_INT_EN			(0x00200000)  /* R/W */
133*de1b686bSSascha Hauer #define	INT_EN_RXD_INT_EN			(0x00100000)  /* R/W */
134*de1b686bSSascha Hauer #define	INT_EN_GPT_INT_EN			(0x00080000)  /* R/W */
135*de1b686bSSascha Hauer #define	INT_EN_PHY_INT_EN			(0x00040000)  /* R/W */
136*de1b686bSSascha Hauer #define	INT_EN_PME_INT_EN			(0x00020000)  /* R/W */
137*de1b686bSSascha Hauer #define	INT_EN_TXSO_EN				(0x00010000)  /* R/W */
138*de1b686bSSascha Hauer #define	INT_EN_RWT_EN				(0x00008000)  /* R/W */
139*de1b686bSSascha Hauer #define	INT_EN_RXE_EN				(0x00004000)  /* R/W */
140*de1b686bSSascha Hauer #define	INT_EN_TXE_EN				(0x00002000)  /* R/W */
141*de1b686bSSascha Hauer /*#define	INT_EN_ERX_EN			(0x00001000)*/  /* R/W */
142*de1b686bSSascha Hauer #define	INT_EN_TDFU_EN				(0x00000800)  /* R/W */
143*de1b686bSSascha Hauer #define	INT_EN_TDFO_EN				(0x00000400)  /* R/W */
144*de1b686bSSascha Hauer #define	INT_EN_TDFA_EN				(0x00000200)  /* R/W */
145*de1b686bSSascha Hauer #define	INT_EN_TSFF_EN				(0x00000100)  /* R/W */
146*de1b686bSSascha Hauer #define	INT_EN_TSFL_EN				(0x00000080)  /* R/W */
147*de1b686bSSascha Hauer /*#define	INT_EN_RXDF_EN			(0x00000040)*/  /* R/W */
148*de1b686bSSascha Hauer #define	INT_EN_RDFO_EN				(0x00000040)  /* R/W */
149*de1b686bSSascha Hauer #define	INT_EN_RDFL_EN				(0x00000020)  /* R/W */
150*de1b686bSSascha Hauer #define	INT_EN_RSFF_EN				(0x00000010)  /* R/W */
151*de1b686bSSascha Hauer #define	INT_EN_RSFL_EN				(0x00000008)  /* R/W */
152*de1b686bSSascha Hauer #define	INT_EN_GPIO2_INT			(0x00000004)  /* R/W */
153*de1b686bSSascha Hauer #define	INT_EN_GPIO1_INT			(0x00000002)  /* R/W */
154*de1b686bSSascha Hauer #define	INT_EN_GPIO0_INT			(0x00000001)  /* R/W */
155*de1b686bSSascha Hauer 
156*de1b686bSSascha Hauer #define BYTE_TEST		__REG(CONFIG_DRIVER_SMC911X_BASE + 0x64)
157*de1b686bSSascha Hauer #define FIFO_INT		__REG(CONFIG_DRIVER_SMC911X_BASE + 0x68)
158*de1b686bSSascha Hauer #define	FIFO_INT_TX_AVAIL_LEVEL			(0xFF000000)  /* R/W */
159*de1b686bSSascha Hauer #define	FIFO_INT_TX_STS_LEVEL			(0x00FF0000)  /* R/W */
160*de1b686bSSascha Hauer #define	FIFO_INT_RX_AVAIL_LEVEL			(0x0000FF00)  /* R/W */
161*de1b686bSSascha Hauer #define	FIFO_INT_RX_STS_LEVEL			(0x000000FF)  /* R/W */
162*de1b686bSSascha Hauer 
163*de1b686bSSascha Hauer #define RX_CFG			__REG(CONFIG_DRIVER_SMC911X_BASE + 0x6C)
164*de1b686bSSascha Hauer #define	RX_CFG_RX_END_ALGN			(0xC0000000)  /* R/W */
165*de1b686bSSascha Hauer #define		RX_CFG_RX_END_ALGN4		(0x00000000)  /* R/W */
166*de1b686bSSascha Hauer #define		RX_CFG_RX_END_ALGN16		(0x40000000)  /* R/W */
167*de1b686bSSascha Hauer #define		RX_CFG_RX_END_ALGN32		(0x80000000)  /* R/W */
168*de1b686bSSascha Hauer #define	RX_CFG_RX_DMA_CNT			(0x0FFF0000)  /* R/W */
169*de1b686bSSascha Hauer #define	RX_CFG_RX_DUMP				(0x00008000)  /* R/W */
170*de1b686bSSascha Hauer #define	RX_CFG_RXDOFF				(0x00001F00)  /* R/W */
171*de1b686bSSascha Hauer /*#define	RX_CFG_RXBAD			(0x00000001)*/  /* R/W */
172*de1b686bSSascha Hauer 
173*de1b686bSSascha Hauer #define TX_CFG			__REG(CONFIG_DRIVER_SMC911X_BASE + 0x70)
174*de1b686bSSascha Hauer /*#define	TX_CFG_TX_DMA_LVL		(0xE0000000)*/	 /* R/W */
175*de1b686bSSascha Hauer /*#define	TX_CFG_TX_DMA_CNT		(0x0FFF0000)*/	 /* R/W Self Clearing */
176*de1b686bSSascha Hauer #define	TX_CFG_TXS_DUMP				(0x00008000)  /* Self Clearing */
177*de1b686bSSascha Hauer #define	TX_CFG_TXD_DUMP				(0x00004000)  /* Self Clearing */
178*de1b686bSSascha Hauer #define	TX_CFG_TXSAO				(0x00000004)  /* R/W */
179*de1b686bSSascha Hauer #define	TX_CFG_TX_ON				(0x00000002)  /* R/W */
180*de1b686bSSascha Hauer #define	TX_CFG_STOP_TX				(0x00000001)  /* Self Clearing */
181*de1b686bSSascha Hauer 
182*de1b686bSSascha Hauer #define HW_CFG			__REG(CONFIG_DRIVER_SMC911X_BASE + 0x74)
183*de1b686bSSascha Hauer #define	HW_CFG_TTM				(0x00200000)  /* R/W */
184*de1b686bSSascha Hauer #define	HW_CFG_SF				(0x00100000)  /* R/W */
185*de1b686bSSascha Hauer #define	HW_CFG_TX_FIF_SZ			(0x000F0000)  /* R/W */
186*de1b686bSSascha Hauer #define	HW_CFG_TR				(0x00003000)  /* R/W */
187*de1b686bSSascha Hauer #define	HW_CFG_PHY_CLK_SEL			(0x00000060)  /* R/W */
188*de1b686bSSascha Hauer #define	HW_CFG_PHY_CLK_SEL_INT_PHY 		(0x00000000) /* R/W */
189*de1b686bSSascha Hauer #define	HW_CFG_PHY_CLK_SEL_EXT_PHY 		(0x00000020) /* R/W */
190*de1b686bSSascha Hauer #define	HW_CFG_PHY_CLK_SEL_CLK_DIS 		(0x00000040) /* R/W */
191*de1b686bSSascha Hauer #define	HW_CFG_SMI_SEL				(0x00000010)  /* R/W */
192*de1b686bSSascha Hauer #define	HW_CFG_EXT_PHY_DET			(0x00000008)  /* RO */
193*de1b686bSSascha Hauer #define	HW_CFG_EXT_PHY_EN			(0x00000004)  /* R/W */
194*de1b686bSSascha Hauer #define	HW_CFG_32_16_BIT_MODE			(0x00000004)  /* RO */
195*de1b686bSSascha Hauer #define	HW_CFG_SRST_TO				(0x00000002)  /* RO */
196*de1b686bSSascha Hauer #define	HW_CFG_SRST				(0x00000001)  /* Self Clearing */
197*de1b686bSSascha Hauer 
198*de1b686bSSascha Hauer #define RX_DP_CTRL		__REG(CONFIG_DRIVER_SMC911X_BASE + 0x78)
199*de1b686bSSascha Hauer #define	RX_DP_CTRL_RX_FFWD			(0x80000000)  /* R/W */
200*de1b686bSSascha Hauer #define	RX_DP_CTRL_FFWD_BUSY			(0x80000000)  /* RO */
201*de1b686bSSascha Hauer 
202*de1b686bSSascha Hauer #define RX_FIFO_INF		__REG(CONFIG_DRIVER_SMC911X_BASE + 0x7C)
203*de1b686bSSascha Hauer #define	 RX_FIFO_INF_RXSUSED			(0x00FF0000)  /* RO */
204*de1b686bSSascha Hauer #define	 RX_FIFO_INF_RXDUSED			(0x0000FFFF)  /* RO */
205*de1b686bSSascha Hauer 
206*de1b686bSSascha Hauer #define TX_FIFO_INF		__REG(CONFIG_DRIVER_SMC911X_BASE + 0x80)
207*de1b686bSSascha Hauer #define	TX_FIFO_INF_TSUSED			(0x00FF0000)  /* RO */
208*de1b686bSSascha Hauer #define	TX_FIFO_INF_TDFREE			(0x0000FFFF)  /* RO */
209*de1b686bSSascha Hauer 
210*de1b686bSSascha Hauer #define PMT_CTRL		__REG(CONFIG_DRIVER_SMC911X_BASE + 0x84)
211*de1b686bSSascha Hauer #define	PMT_CTRL_PM_MODE			(0x00003000)  /* Self Clearing */
212*de1b686bSSascha Hauer #define	PMT_CTRL_PHY_RST			(0x00000400)  /* Self Clearing */
213*de1b686bSSascha Hauer #define	PMT_CTRL_WOL_EN				(0x00000200)  /* R/W */
214*de1b686bSSascha Hauer #define	PMT_CTRL_ED_EN				(0x00000100)  /* R/W */
215*de1b686bSSascha Hauer #define	PMT_CTRL_PME_TYPE			(0x00000040)  /* R/W Not Affected by SW Reset */
216*de1b686bSSascha Hauer #define	PMT_CTRL_WUPS				(0x00000030)  /* R/WC */
217*de1b686bSSascha Hauer #define	PMT_CTRL_WUPS_NOWAKE			(0x00000000)  /* R/WC */
218*de1b686bSSascha Hauer #define	PMT_CTRL_WUPS_ED			(0x00000010)  /* R/WC */
219*de1b686bSSascha Hauer #define	PMT_CTRL_WUPS_WOL			(0x00000020)  /* R/WC */
220*de1b686bSSascha Hauer #define	PMT_CTRL_WUPS_MULTI			(0x00000030)  /* R/WC */
221*de1b686bSSascha Hauer #define	PMT_CTRL_PME_IND			(0x00000008)  /* R/W */
222*de1b686bSSascha Hauer #define	PMT_CTRL_PME_POL			(0x00000004)  /* R/W */
223*de1b686bSSascha Hauer #define	PMT_CTRL_PME_EN				(0x00000002)  /* R/W Not Affected by SW Reset */
224*de1b686bSSascha Hauer #define	PMT_CTRL_READY				(0x00000001)  /* RO */
225*de1b686bSSascha Hauer 
226*de1b686bSSascha Hauer #define GPIO_CFG		__REG(CONFIG_DRIVER_SMC911X_BASE + 0x88)
227*de1b686bSSascha Hauer #define	GPIO_CFG_LED3_EN			(0x40000000)  /* R/W */
228*de1b686bSSascha Hauer #define	GPIO_CFG_LED2_EN			(0x20000000)  /* R/W */
229*de1b686bSSascha Hauer #define	GPIO_CFG_LED1_EN			(0x10000000)  /* R/W */
230*de1b686bSSascha Hauer #define	GPIO_CFG_GPIO2_INT_POL			(0x04000000)  /* R/W */
231*de1b686bSSascha Hauer #define	GPIO_CFG_GPIO1_INT_POL			(0x02000000)  /* R/W */
232*de1b686bSSascha Hauer #define	GPIO_CFG_GPIO0_INT_POL			(0x01000000)  /* R/W */
233*de1b686bSSascha Hauer #define	GPIO_CFG_EEPR_EN			(0x00700000)  /* R/W */
234*de1b686bSSascha Hauer #define	GPIO_CFG_GPIOBUF2			(0x00040000)  /* R/W */
235*de1b686bSSascha Hauer #define	GPIO_CFG_GPIOBUF1			(0x00020000)  /* R/W */
236*de1b686bSSascha Hauer #define	GPIO_CFG_GPIOBUF0			(0x00010000)  /* R/W */
237*de1b686bSSascha Hauer #define	GPIO_CFG_GPIODIR2			(0x00000400)  /* R/W */
238*de1b686bSSascha Hauer #define	GPIO_CFG_GPIODIR1			(0x00000200)  /* R/W */
239*de1b686bSSascha Hauer #define	GPIO_CFG_GPIODIR0			(0x00000100)  /* R/W */
240*de1b686bSSascha Hauer #define	GPIO_CFG_GPIOD4				(0x00000010)  /* R/W */
241*de1b686bSSascha Hauer #define	GPIO_CFG_GPIOD3				(0x00000008)  /* R/W */
242*de1b686bSSascha Hauer #define	GPIO_CFG_GPIOD2				(0x00000004)  /* R/W */
243*de1b686bSSascha Hauer #define	GPIO_CFG_GPIOD1				(0x00000002)  /* R/W */
244*de1b686bSSascha Hauer #define	GPIO_CFG_GPIOD0				(0x00000001)  /* R/W */
245*de1b686bSSascha Hauer 
246*de1b686bSSascha Hauer #define GPT_CFG			__REG(CONFIG_DRIVER_SMC911X_BASE + 0x8C)
247*de1b686bSSascha Hauer #define	GPT_CFG_TIMER_EN			(0x20000000)  /* R/W */
248*de1b686bSSascha Hauer #define	GPT_CFG_GPT_LOAD			(0x0000FFFF)  /* R/W */
249*de1b686bSSascha Hauer 
250*de1b686bSSascha Hauer #define GPT_CNT			__REG(CONFIG_DRIVER_SMC911X_BASE + 0x90)
251*de1b686bSSascha Hauer #define	GPT_CNT_GPT_CNT				(0x0000FFFF)  /* RO */
252*de1b686bSSascha Hauer 
253*de1b686bSSascha Hauer #define ENDIAN			__REG(CONFIG_DRIVER_SMC911X_BASE + 0x98)
254*de1b686bSSascha Hauer #define FREE_RUN		__REG(CONFIG_DRIVER_SMC911X_BASE + 0x9C)
255*de1b686bSSascha Hauer #define RX_DROP			__REG(CONFIG_DRIVER_SMC911X_BASE + 0xA0)
256*de1b686bSSascha Hauer #define MAC_CSR_CMD		__REG(CONFIG_DRIVER_SMC911X_BASE + 0xA4)
257*de1b686bSSascha Hauer #define	 MAC_CSR_CMD_CSR_BUSY			(0x80000000)  /* Self Clearing */
258*de1b686bSSascha Hauer #define	 MAC_CSR_CMD_R_NOT_W			(0x40000000)  /* R/W */
259*de1b686bSSascha Hauer #define	 MAC_CSR_CMD_CSR_ADDR			(0x000000FF)  /* R/W */
260*de1b686bSSascha Hauer 
261*de1b686bSSascha Hauer #define MAC_CSR_DATA		__REG(CONFIG_DRIVER_SMC911X_BASE + 0xA8)
262*de1b686bSSascha Hauer #define AFC_CFG			__REG(CONFIG_DRIVER_SMC911X_BASE + 0xAC)
263*de1b686bSSascha Hauer #define		AFC_CFG_AFC_HI			(0x00FF0000)  /* R/W */
264*de1b686bSSascha Hauer #define		AFC_CFG_AFC_LO			(0x0000FF00)  /* R/W */
265*de1b686bSSascha Hauer #define		AFC_CFG_BACK_DUR		(0x000000F0)  /* R/W */
266*de1b686bSSascha Hauer #define		AFC_CFG_FCMULT			(0x00000008)  /* R/W */
267*de1b686bSSascha Hauer #define		AFC_CFG_FCBRD			(0x00000004)  /* R/W */
268*de1b686bSSascha Hauer #define		AFC_CFG_FCADD			(0x00000002)  /* R/W */
269*de1b686bSSascha Hauer #define		AFC_CFG_FCANY			(0x00000001)  /* R/W */
270*de1b686bSSascha Hauer 
271*de1b686bSSascha Hauer #define E2P_CMD			__REG(CONFIG_DRIVER_SMC911X_BASE + 0xB0)
272*de1b686bSSascha Hauer #define		E2P_CMD_EPC_BUSY		(0x80000000)  /* Self Clearing */
273*de1b686bSSascha Hauer #define		E2P_CMD_EPC_CMD			(0x70000000)  /* R/W */
274*de1b686bSSascha Hauer #define		E2P_CMD_EPC_CMD_READ		(0x00000000)  /* R/W */
275*de1b686bSSascha Hauer #define		E2P_CMD_EPC_CMD_EWDS		(0x10000000)  /* R/W */
276*de1b686bSSascha Hauer #define		E2P_CMD_EPC_CMD_EWEN		(0x20000000)  /* R/W */
277*de1b686bSSascha Hauer #define		E2P_CMD_EPC_CMD_WRITE		(0x30000000)  /* R/W */
278*de1b686bSSascha Hauer #define		E2P_CMD_EPC_CMD_WRAL		(0x40000000)  /* R/W */
279*de1b686bSSascha Hauer #define		E2P_CMD_EPC_CMD_ERASE		(0x50000000)  /* R/W */
280*de1b686bSSascha Hauer #define		E2P_CMD_EPC_CMD_ERAL		(0x60000000)  /* R/W */
281*de1b686bSSascha Hauer #define		E2P_CMD_EPC_CMD_RELOAD		(0x70000000)  /* R/W */
282*de1b686bSSascha Hauer #define		E2P_CMD_EPC_TIMEOUT		(0x00000200)  /* RO */
283*de1b686bSSascha Hauer #define		E2P_CMD_MAC_ADDR_LOADED		(0x00000100)  /* RO */
284*de1b686bSSascha Hauer #define		E2P_CMD_EPC_ADDR		(0x000000FF)  /* R/W */
285*de1b686bSSascha Hauer 
286*de1b686bSSascha Hauer #define E2P_DATA		__REG(CONFIG_DRIVER_SMC911X_BASE + 0xB4)
287*de1b686bSSascha Hauer #define	E2P_DATA_EEPROM_DATA			(0x000000FF)  /* R/W */
288*de1b686bSSascha Hauer /* end of LAN register offsets and bit definitions */
289*de1b686bSSascha Hauer 
290*de1b686bSSascha Hauer /* MAC Control and Status registers */
291*de1b686bSSascha Hauer #define MAC_CR			(0x01)  /* R/W */
292*de1b686bSSascha Hauer 
293*de1b686bSSascha Hauer /* MAC_CR - MAC Control Register */
294*de1b686bSSascha Hauer #define MAC_CR_RXALL			(0x80000000)
295*de1b686bSSascha Hauer /* TODO: delete this bit? It is not described in the data sheet. */
296*de1b686bSSascha Hauer #define MAC_CR_HBDIS			(0x10000000)
297*de1b686bSSascha Hauer #define MAC_CR_RCVOWN			(0x00800000)
298*de1b686bSSascha Hauer #define MAC_CR_LOOPBK			(0x00200000)
299*de1b686bSSascha Hauer #define MAC_CR_FDPX			(0x00100000)
300*de1b686bSSascha Hauer #define MAC_CR_MCPAS			(0x00080000)
301*de1b686bSSascha Hauer #define MAC_CR_PRMS			(0x00040000)
302*de1b686bSSascha Hauer #define MAC_CR_INVFILT			(0x00020000)
303*de1b686bSSascha Hauer #define MAC_CR_PASSBAD			(0x00010000)
304*de1b686bSSascha Hauer #define MAC_CR_HFILT			(0x00008000)
305*de1b686bSSascha Hauer #define MAC_CR_HPFILT			(0x00002000)
306*de1b686bSSascha Hauer #define MAC_CR_LCOLL			(0x00001000)
307*de1b686bSSascha Hauer #define MAC_CR_BCAST			(0x00000800)
308*de1b686bSSascha Hauer #define MAC_CR_DISRTY			(0x00000400)
309*de1b686bSSascha Hauer #define MAC_CR_PADSTR			(0x00000100)
310*de1b686bSSascha Hauer #define MAC_CR_BOLMT_MASK		(0x000000C0)
311*de1b686bSSascha Hauer #define MAC_CR_DFCHK			(0x00000020)
312*de1b686bSSascha Hauer #define MAC_CR_TXEN			(0x00000008)
313*de1b686bSSascha Hauer #define MAC_CR_RXEN			(0x00000004)
314*de1b686bSSascha Hauer 
315*de1b686bSSascha Hauer #define ADDRH			(0x02)	  /* R/W mask 0x0000FFFFUL */
316*de1b686bSSascha Hauer #define ADDRL			(0x03)	  /* R/W mask 0xFFFFFFFFUL */
317*de1b686bSSascha Hauer #define HASHH			(0x04)	  /* R/W */
318*de1b686bSSascha Hauer #define HASHL			(0x05)	  /* R/W */
319*de1b686bSSascha Hauer 
320*de1b686bSSascha Hauer #define MII_ACC			(0x06)	  /* R/W */
321*de1b686bSSascha Hauer #define MII_ACC_PHY_ADDR		(0x0000F800)
322*de1b686bSSascha Hauer #define MII_ACC_MIIRINDA		(0x000007C0)
323*de1b686bSSascha Hauer #define MII_ACC_MII_WRITE		(0x00000002)
324*de1b686bSSascha Hauer #define MII_ACC_MII_BUSY		(0x00000001)
325*de1b686bSSascha Hauer 
326*de1b686bSSascha Hauer #define MII_DATA		(0x07)	  /* R/W mask 0x0000FFFFUL */
327*de1b686bSSascha Hauer 
328*de1b686bSSascha Hauer #define FLOW			(0x08)	  /* R/W */
329*de1b686bSSascha Hauer #define FLOW_FCPT			(0xFFFF0000)
330*de1b686bSSascha Hauer #define FLOW_FCPASS			(0x00000004)
331*de1b686bSSascha Hauer #define FLOW_FCEN			(0x00000002)
332*de1b686bSSascha Hauer #define FLOW_FCBSY			(0x00000001)
333*de1b686bSSascha Hauer 
334*de1b686bSSascha Hauer #define VLAN1			(0x09)	  /* R/W mask 0x0000FFFFUL */
335*de1b686bSSascha Hauer #define VLAN1_VTI1			(0x0000ffff)
336*de1b686bSSascha Hauer 
337*de1b686bSSascha Hauer #define VLAN2			(0x0A)	  /* R/W mask 0x0000FFFFUL */
338*de1b686bSSascha Hauer #define VLAN2_VTI2			(0x0000ffff)
339*de1b686bSSascha Hauer 
340*de1b686bSSascha Hauer #define WUFF			(0x0B)	  /* WO */
341*de1b686bSSascha Hauer 
342*de1b686bSSascha Hauer #define WUCSR			(0x0C)	  /* R/W */
343*de1b686bSSascha Hauer #define WUCSR_GUE			(0x00000200)
344*de1b686bSSascha Hauer #define WUCSR_WUFR			(0x00000040)
345*de1b686bSSascha Hauer #define WUCSR_MPR			(0x00000020)
346*de1b686bSSascha Hauer #define WUCSR_WAKE_EN			(0x00000004)
347*de1b686bSSascha Hauer #define WUCSR_MPEN			(0x00000002)
348*de1b686bSSascha Hauer 
349*de1b686bSSascha Hauer /* Chip ID values */
350*de1b686bSSascha Hauer #define CHIP_9115	0x115
351*de1b686bSSascha Hauer #define CHIP_9116	0x116
352*de1b686bSSascha Hauer #define CHIP_9117	0x117
353*de1b686bSSascha Hauer #define CHIP_9118	0x118
354*de1b686bSSascha Hauer #define CHIP_9215	0x115a
355*de1b686bSSascha Hauer #define CHIP_9216	0x116a
356*de1b686bSSascha Hauer #define CHIP_9217	0x117a
357*de1b686bSSascha Hauer #define CHIP_9218	0x118a
358*de1b686bSSascha Hauer 
359*de1b686bSSascha Hauer struct chip_id {
360*de1b686bSSascha Hauer 	u16 id;
361*de1b686bSSascha Hauer 	char *name;
362*de1b686bSSascha Hauer };
363*de1b686bSSascha Hauer 
364*de1b686bSSascha Hauer static const struct chip_id chip_ids[] =  {
365*de1b686bSSascha Hauer 	{ CHIP_9115, "LAN9115" },
366*de1b686bSSascha Hauer 	{ CHIP_9116, "LAN9116" },
367*de1b686bSSascha Hauer 	{ CHIP_9117, "LAN9117" },
368*de1b686bSSascha Hauer 	{ CHIP_9118, "LAN9118" },
369*de1b686bSSascha Hauer 	{ CHIP_9215, "LAN9215" },
370*de1b686bSSascha Hauer 	{ CHIP_9216, "LAN9216" },
371*de1b686bSSascha Hauer 	{ CHIP_9217, "LAN9217" },
372*de1b686bSSascha Hauer 	{ CHIP_9218, "LAN9218" },
373*de1b686bSSascha Hauer 	{ 0, NULL },
374*de1b686bSSascha Hauer };
375*de1b686bSSascha Hauer 
376*de1b686bSSascha Hauer #define DRIVERNAME "smc911x"
377*de1b686bSSascha Hauer 
378*de1b686bSSascha Hauer u32 smc911x_get_mac_csr(u8 reg)
379*de1b686bSSascha Hauer {
380*de1b686bSSascha Hauer 	while (MAC_CSR_CMD & MAC_CSR_CMD_CSR_BUSY);
381*de1b686bSSascha Hauer 	MAC_CSR_CMD = MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_R_NOT_W | reg;
382*de1b686bSSascha Hauer 	while (MAC_CSR_CMD & MAC_CSR_CMD_CSR_BUSY);
383*de1b686bSSascha Hauer 
384*de1b686bSSascha Hauer 	return MAC_CSR_DATA;
385*de1b686bSSascha Hauer }
386*de1b686bSSascha Hauer 
387*de1b686bSSascha Hauer void smc911x_set_mac_csr(u8 reg, u32 data)
388*de1b686bSSascha Hauer {
389*de1b686bSSascha Hauer 	while (MAC_CSR_CMD & MAC_CSR_CMD_CSR_BUSY);
390*de1b686bSSascha Hauer 	MAC_CSR_DATA = data;
391*de1b686bSSascha Hauer 	MAC_CSR_CMD = MAC_CSR_CMD_CSR_BUSY | reg;
392*de1b686bSSascha Hauer 	while (MAC_CSR_CMD & MAC_CSR_CMD_CSR_BUSY);
393*de1b686bSSascha Hauer }
394*de1b686bSSascha Hauer 
395*de1b686bSSascha Hauer static int smx911x_handle_mac_address(bd_t *bd)
396*de1b686bSSascha Hauer {
397*de1b686bSSascha Hauer 	unsigned long addrh, addrl;
398*de1b686bSSascha Hauer 	unsigned char *m = bd->bi_enetaddr;
399*de1b686bSSascha Hauer 
400*de1b686bSSascha Hauer 	/* if the environment has a valid mac address then use it */
401*de1b686bSSascha Hauer 	if ((m[0] | m[1] | m[2] | m[3] | m[4] | m[5])) {
402*de1b686bSSascha Hauer 		addrl = m[0] | m[1] << 8 | m[2] << 16 | m[3] << 24;
403*de1b686bSSascha Hauer 		addrh = m[4] | m[5] << 8;
404*de1b686bSSascha Hauer 		smc911x_set_mac_csr(ADDRH, addrh);
405*de1b686bSSascha Hauer 		smc911x_set_mac_csr(ADDRL, addrl);
406*de1b686bSSascha Hauer 	} else {
407*de1b686bSSascha Hauer 		/* if not, try to get one from the eeprom */
408*de1b686bSSascha Hauer 		addrh = smc911x_get_mac_csr(ADDRH);
409*de1b686bSSascha Hauer 		addrl = smc911x_get_mac_csr(ADDRL);
410*de1b686bSSascha Hauer 
411*de1b686bSSascha Hauer 		m[0] = (addrl       ) & 0xff;
412*de1b686bSSascha Hauer 		m[1] = (addrl >>  8 ) & 0xff;
413*de1b686bSSascha Hauer 		m[2] = (addrl >> 16 ) & 0xff;
414*de1b686bSSascha Hauer 		m[3] = (addrl >> 24 ) & 0xff;
415*de1b686bSSascha Hauer 		m[4] = (addrh       ) & 0xff;
416*de1b686bSSascha Hauer 		m[5] = (addrh >>  8 ) & 0xff;
417*de1b686bSSascha Hauer 
418*de1b686bSSascha Hauer 		/* we get 0xff when there is no eeprom connected */
419*de1b686bSSascha Hauer 		if ((m[0] & m[1] & m[2] & m[3] & m[4] & m[5]) == 0xff) {
420*de1b686bSSascha Hauer 			printf(DRIVERNAME ": no valid mac address in environment "
421*de1b686bSSascha Hauer 				"and no eeprom found\n");
422*de1b686bSSascha Hauer 			return -1;
423*de1b686bSSascha Hauer 		}
424*de1b686bSSascha Hauer 	}
425*de1b686bSSascha Hauer 
426*de1b686bSSascha Hauer 	printf(DRIVERNAME ": MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
427*de1b686bSSascha Hauer 		m[0], m[1], m[2], m[3], m[4], m[5]);
428*de1b686bSSascha Hauer 
429*de1b686bSSascha Hauer 	return 0;
430*de1b686bSSascha Hauer }
431*de1b686bSSascha Hauer 
432*de1b686bSSascha Hauer static int smc911x_miiphy_read(u8 phy, u8 reg, u16 *val)
433*de1b686bSSascha Hauer {
434*de1b686bSSascha Hauer 	while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY);
435*de1b686bSSascha Hauer 
436*de1b686bSSascha Hauer 	smc911x_set_mac_csr( MII_ACC, phy << 11 | reg << 6 | MII_ACC_MII_BUSY);
437*de1b686bSSascha Hauer 
438*de1b686bSSascha Hauer 	while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY);
439*de1b686bSSascha Hauer 
440*de1b686bSSascha Hauer 	*val = smc911x_get_mac_csr(MII_DATA);
441*de1b686bSSascha Hauer 
442*de1b686bSSascha Hauer 	return 0;
443*de1b686bSSascha Hauer }
444*de1b686bSSascha Hauer 
445*de1b686bSSascha Hauer static int smc911x_miiphy_write(u8 phy, u8 reg, u16  val)
446*de1b686bSSascha Hauer {
447*de1b686bSSascha Hauer 	while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY);
448*de1b686bSSascha Hauer 
449*de1b686bSSascha Hauer 	smc911x_set_mac_csr(MII_DATA, val);
450*de1b686bSSascha Hauer 	smc911x_set_mac_csr(MII_ACC,
451*de1b686bSSascha Hauer 		phy << 11 | reg << 6 | MII_ACC_MII_BUSY | MII_ACC_MII_WRITE);
452*de1b686bSSascha Hauer 
453*de1b686bSSascha Hauer 	while (smc911x_get_mac_csr(MII_ACC) & MII_ACC_MII_BUSY);
454*de1b686bSSascha Hauer 	return 0;
455*de1b686bSSascha Hauer }
456*de1b686bSSascha Hauer 
457*de1b686bSSascha Hauer static int smc911x_phy_reset(void)
458*de1b686bSSascha Hauer {
459*de1b686bSSascha Hauer 	u32 reg;
460*de1b686bSSascha Hauer 
461*de1b686bSSascha Hauer 	reg = PMT_CTRL;
462*de1b686bSSascha Hauer 	reg &= ~0xfffff030;
463*de1b686bSSascha Hauer 	reg |= PMT_CTRL_PHY_RST;
464*de1b686bSSascha Hauer 	PMT_CTRL = reg;
465*de1b686bSSascha Hauer 
466*de1b686bSSascha Hauer 	mdelay(100);
467*de1b686bSSascha Hauer 
468*de1b686bSSascha Hauer 	return 0;
469*de1b686bSSascha Hauer }
470*de1b686bSSascha Hauer 
471*de1b686bSSascha Hauer static void smc911x_phy_configure(void)
472*de1b686bSSascha Hauer {
473*de1b686bSSascha Hauer 	int timeout;
474*de1b686bSSascha Hauer 	u16 status;
475*de1b686bSSascha Hauer 
476*de1b686bSSascha Hauer 	smc911x_phy_reset();
477*de1b686bSSascha Hauer 
478*de1b686bSSascha Hauer 	smc911x_miiphy_write(1, PHY_BMCR, PHY_BMCR_RESET);
479*de1b686bSSascha Hauer 	mdelay(1);
480*de1b686bSSascha Hauer 	smc911x_miiphy_write(1, PHY_ANAR, 0x01e1);
481*de1b686bSSascha Hauer 	smc911x_miiphy_write(1, PHY_BMCR, PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
482*de1b686bSSascha Hauer 
483*de1b686bSSascha Hauer 	timeout = 5000;
484*de1b686bSSascha Hauer 	do {
485*de1b686bSSascha Hauer 		mdelay(1);
486*de1b686bSSascha Hauer 		if ((timeout--) == 0)
487*de1b686bSSascha Hauer 			goto err_out;
488*de1b686bSSascha Hauer 
489*de1b686bSSascha Hauer 		if (smc911x_miiphy_read(1, PHY_BMSR, &status) != 0)
490*de1b686bSSascha Hauer 			goto err_out;
491*de1b686bSSascha Hauer 	} while (!(status & PHY_BMSR_LS));
492*de1b686bSSascha Hauer 
493*de1b686bSSascha Hauer 	printf(DRIVERNAME ": phy initialized\n");
494*de1b686bSSascha Hauer 
495*de1b686bSSascha Hauer 	return;
496*de1b686bSSascha Hauer 
497*de1b686bSSascha Hauer err_out:
498*de1b686bSSascha Hauer 	printf(DRIVERNAME ": autonegotiation timed out\n");
499*de1b686bSSascha Hauer }
500*de1b686bSSascha Hauer 
501*de1b686bSSascha Hauer static void smc911x_reset(void)
502*de1b686bSSascha Hauer {
503*de1b686bSSascha Hauer 	int timeout;
504*de1b686bSSascha Hauer 
505*de1b686bSSascha Hauer 	/* Take out of PM setting first */
506*de1b686bSSascha Hauer 	if (PMT_CTRL & PMT_CTRL_READY) {
507*de1b686bSSascha Hauer 		/* Write to the bytetest will take out of powerdown */
508*de1b686bSSascha Hauer 		BYTE_TEST = 0x0;
509*de1b686bSSascha Hauer 
510*de1b686bSSascha Hauer 		timeout = 10;
511*de1b686bSSascha Hauer 
512*de1b686bSSascha Hauer 		while ( timeout-- && !(PMT_CTRL & PMT_CTRL_READY))
513*de1b686bSSascha Hauer 			udelay(10);
514*de1b686bSSascha Hauer 		if (!timeout) {
515*de1b686bSSascha Hauer 			printf(DRIVERNAME
516*de1b686bSSascha Hauer 				": timeout waiting for PM restore\n");
517*de1b686bSSascha Hauer 			return;
518*de1b686bSSascha Hauer 		}
519*de1b686bSSascha Hauer 	}
520*de1b686bSSascha Hauer 
521*de1b686bSSascha Hauer 	/* Disable interrupts */
522*de1b686bSSascha Hauer 	INT_EN = 0;
523*de1b686bSSascha Hauer 
524*de1b686bSSascha Hauer 	HW_CFG = HW_CFG_SRST;
525*de1b686bSSascha Hauer 
526*de1b686bSSascha Hauer 	timeout = 1000;
527*de1b686bSSascha Hauer 	while (timeout-- && E2P_CMD & E2P_CMD_EPC_BUSY)
528*de1b686bSSascha Hauer 		udelay(10);
529*de1b686bSSascha Hauer 
530*de1b686bSSascha Hauer 	if(!timeout) {
531*de1b686bSSascha Hauer 		printf(DRIVERNAME ": reset timeout\n");
532*de1b686bSSascha Hauer 		return;
533*de1b686bSSascha Hauer 	}
534*de1b686bSSascha Hauer 
535*de1b686bSSascha Hauer 	/* Reset the FIFO level and flow control settings */
536*de1b686bSSascha Hauer 	smc911x_set_mac_csr(FLOW, FLOW_FCPT | FLOW_FCEN);
537*de1b686bSSascha Hauer 	AFC_CFG = 0x0050287F;
538*de1b686bSSascha Hauer 
539*de1b686bSSascha Hauer 	/* Set to LED outputs */
540*de1b686bSSascha Hauer 	GPIO_CFG = 0x70070000;
541*de1b686bSSascha Hauer }
542*de1b686bSSascha Hauer 
543*de1b686bSSascha Hauer static void smc911x_enable(void)
544*de1b686bSSascha Hauer {
545*de1b686bSSascha Hauer 	/* Enable TX */
546*de1b686bSSascha Hauer 	HW_CFG = 8 << 16 | HW_CFG_SF;
547*de1b686bSSascha Hauer 
548*de1b686bSSascha Hauer 	GPT_CFG = GPT_CFG_TIMER_EN | 10000;
549*de1b686bSSascha Hauer 
550*de1b686bSSascha Hauer 	TX_CFG = TX_CFG_TX_ON;
551*de1b686bSSascha Hauer 
552*de1b686bSSascha Hauer 	/* no padding to start of packets */
553*de1b686bSSascha Hauer 	RX_CFG = 0;
554*de1b686bSSascha Hauer 
555*de1b686bSSascha Hauer 	smc911x_set_mac_csr(MAC_CR, MAC_CR_TXEN | MAC_CR_RXEN | MAC_CR_HBDIS);
556*de1b686bSSascha Hauer 
557*de1b686bSSascha Hauer }
558*de1b686bSSascha Hauer 
559*de1b686bSSascha Hauer int eth_init(bd_t *bd)
560*de1b686bSSascha Hauer {
561*de1b686bSSascha Hauer 	unsigned long val, i;
562*de1b686bSSascha Hauer 
563*de1b686bSSascha Hauer 	printf(DRIVERNAME ": initializing\n");
564*de1b686bSSascha Hauer 
565*de1b686bSSascha Hauer 	val = BYTE_TEST;
566*de1b686bSSascha Hauer 	if(val != 0x87654321) {
567*de1b686bSSascha Hauer 		printf(DRIVERNAME ": Invalid chip endian 0x08%x\n", val);
568*de1b686bSSascha Hauer 		goto err_out;
569*de1b686bSSascha Hauer 	}
570*de1b686bSSascha Hauer 
571*de1b686bSSascha Hauer 	val = ID_REV >> 16;
572*de1b686bSSascha Hauer 	for(i = 0; chip_ids[i].id != 0; i++) {
573*de1b686bSSascha Hauer 		if (chip_ids[i].id == val) break;
574*de1b686bSSascha Hauer 	}
575*de1b686bSSascha Hauer 	if (!chip_ids[i].id) {
576*de1b686bSSascha Hauer 		printf(DRIVERNAME ": Unknown chip ID %04x\n", val);
577*de1b686bSSascha Hauer 		goto err_out;
578*de1b686bSSascha Hauer 	}
579*de1b686bSSascha Hauer 
580*de1b686bSSascha Hauer 	printf(DRIVERNAME ": detected %s controller\n", chip_ids[i].name);
581*de1b686bSSascha Hauer 
582*de1b686bSSascha Hauer 	smc911x_reset();
583*de1b686bSSascha Hauer 
584*de1b686bSSascha Hauer 	/* Configure the PHY, initialize the link state */
585*de1b686bSSascha Hauer 	smc911x_phy_configure();
586*de1b686bSSascha Hauer 
587*de1b686bSSascha Hauer 	if (smx911x_handle_mac_address(bd))
588*de1b686bSSascha Hauer 		goto err_out;
589*de1b686bSSascha Hauer 
590*de1b686bSSascha Hauer 	/* Turn on Tx + Rx */
591*de1b686bSSascha Hauer 	smc911x_enable();
592*de1b686bSSascha Hauer 
593*de1b686bSSascha Hauer 	return 0;
594*de1b686bSSascha Hauer 
595*de1b686bSSascha Hauer err_out:
596*de1b686bSSascha Hauer 	return -1;
597*de1b686bSSascha Hauer }
598*de1b686bSSascha Hauer 
599*de1b686bSSascha Hauer int eth_send(volatile void *packet, int length)
600*de1b686bSSascha Hauer {
601*de1b686bSSascha Hauer 	u32 *data = (u32*)packet;
602*de1b686bSSascha Hauer 	u32 tmplen;
603*de1b686bSSascha Hauer 	u32 status;
604*de1b686bSSascha Hauer 
605*de1b686bSSascha Hauer 	TX_DATA_FIFO = TX_CMD_A_INT_FIRST_SEG | TX_CMD_A_INT_LAST_SEG | length;
606*de1b686bSSascha Hauer 	TX_DATA_FIFO = length;
607*de1b686bSSascha Hauer 
608*de1b686bSSascha Hauer 	tmplen = (length + 3) / 4;
609*de1b686bSSascha Hauer 
610*de1b686bSSascha Hauer 	while(tmplen--)
611*de1b686bSSascha Hauer 		TX_DATA_FIFO = *data++;
612*de1b686bSSascha Hauer 
613*de1b686bSSascha Hauer 	/* wait for transmission */
614*de1b686bSSascha Hauer 	while (!((TX_FIFO_INF & TX_FIFO_INF_TSUSED) >> 16));
615*de1b686bSSascha Hauer 
616*de1b686bSSascha Hauer 	/* get status. Ignore 'no carrier' error, it has no meaning for
617*de1b686bSSascha Hauer 	 * full duplex operation
618*de1b686bSSascha Hauer 	 */
619*de1b686bSSascha Hauer 	status = TX_STATUS_FIFO & (TX_STS_LOC | TX_STS_LATE_COLL |
620*de1b686bSSascha Hauer 		TX_STS_MANY_COLL | TX_STS_MANY_DEFER | TX_STS_UNDERRUN);
621*de1b686bSSascha Hauer 
622*de1b686bSSascha Hauer 	if(!status)
623*de1b686bSSascha Hauer 		return 0;
624*de1b686bSSascha Hauer 
625*de1b686bSSascha Hauer 	printf(DRIVERNAME ": failed to send packet: %s%s%s%s%s\n",
626*de1b686bSSascha Hauer 		status & TX_STS_LOC ? "TX_STS_LOC " : "",
627*de1b686bSSascha Hauer 		status & TX_STS_LATE_COLL ? "TX_STS_LATE_COLL " : "",
628*de1b686bSSascha Hauer 		status & TX_STS_MANY_COLL ? "TX_STS_MANY_COLL " : "",
629*de1b686bSSascha Hauer 		status & TX_STS_MANY_DEFER ? "TX_STS_MANY_DEFER " : "",
630*de1b686bSSascha Hauer 		status & TX_STS_UNDERRUN ? "TX_STS_UNDERRUN" : "");
631*de1b686bSSascha Hauer 
632*de1b686bSSascha Hauer 	return -1;
633*de1b686bSSascha Hauer }
634*de1b686bSSascha Hauer 
635*de1b686bSSascha Hauer void eth_halt(void)
636*de1b686bSSascha Hauer {
637*de1b686bSSascha Hauer 	smc911x_reset();
638*de1b686bSSascha Hauer }
639*de1b686bSSascha Hauer 
640*de1b686bSSascha Hauer int eth_rx(void)
641*de1b686bSSascha Hauer {
642*de1b686bSSascha Hauer 	u32 *data = (u32 *)NetRxPackets[0];
643*de1b686bSSascha Hauer 	u32 pktlen, tmplen;
644*de1b686bSSascha Hauer 	u32 status;
645*de1b686bSSascha Hauer 
646*de1b686bSSascha Hauer 	if((RX_FIFO_INF & RX_FIFO_INF_RXSUSED) >> 16) {
647*de1b686bSSascha Hauer 		status = RX_STATUS_FIFO;
648*de1b686bSSascha Hauer 		pktlen = (status & RX_STS_PKT_LEN) >> 16;
649*de1b686bSSascha Hauer 
650*de1b686bSSascha Hauer 		RX_CFG = 0;
651*de1b686bSSascha Hauer 
652*de1b686bSSascha Hauer 		tmplen = (pktlen + 2+ 3) / 4;
653*de1b686bSSascha Hauer 		while(tmplen--)
654*de1b686bSSascha Hauer 			*data++ = RX_DATA_FIFO;
655*de1b686bSSascha Hauer 
656*de1b686bSSascha Hauer 		if(status & RX_STS_ES)
657*de1b686bSSascha Hauer 			printf(DRIVERNAME
658*de1b686bSSascha Hauer 				": dropped bad packet. Status: 0x%08x\n",
659*de1b686bSSascha Hauer 				status);
660*de1b686bSSascha Hauer 		else
661*de1b686bSSascha Hauer 			NetReceive(NetRxPackets[0], pktlen);
662*de1b686bSSascha Hauer 	}
663*de1b686bSSascha Hauer 
664*de1b686bSSascha Hauer 	return 0;
665*de1b686bSSascha Hauer }
666*de1b686bSSascha Hauer 
667*de1b686bSSascha Hauer #endif				/* CONFIG_DRIVER_SMC911X */
668