xref: /rk3399_rockchip-uboot/drivers/usb/eth/r8152.c (revision 9dc8ba19c50fc0b1623c654bcfe6caa903a4c36c)
1*9dc8ba19STed Chen /*
2*9dc8ba19STed Chen  * Copyright (c) 2015 Realtek Semiconductor Corp. All rights reserved.
3*9dc8ba19STed Chen  *
4*9dc8ba19STed Chen  * SPDX-License-Identifier:	GPL-2.0
5*9dc8ba19STed Chen  *
6*9dc8ba19STed Chen   */
7*9dc8ba19STed Chen 
8*9dc8ba19STed Chen #include <common.h>
9*9dc8ba19STed Chen #include <errno.h>
10*9dc8ba19STed Chen #include <malloc.h>
11*9dc8ba19STed Chen #include <usb.h>
12*9dc8ba19STed Chen #include <usb/lin_gadget_compat.h>
13*9dc8ba19STed Chen #include <linux/mii.h>
14*9dc8ba19STed Chen #include <linux/bitops.h>
15*9dc8ba19STed Chen #include "usb_ether.h"
16*9dc8ba19STed Chen #include "r8152.h"
17*9dc8ba19STed Chen 
18*9dc8ba19STed Chen /* local vars */
19*9dc8ba19STed Chen static int curr_eth_dev; /* index for name of next device detected */
20*9dc8ba19STed Chen 
21*9dc8ba19STed Chen struct r8152_dongle {
22*9dc8ba19STed Chen 	unsigned short vendor;
23*9dc8ba19STed Chen 	unsigned short product;
24*9dc8ba19STed Chen };
25*9dc8ba19STed Chen 
26*9dc8ba19STed Chen struct r8152_version {
27*9dc8ba19STed Chen 	unsigned short tcr;
28*9dc8ba19STed Chen 	unsigned short version;
29*9dc8ba19STed Chen 	bool           gmii;
30*9dc8ba19STed Chen };
31*9dc8ba19STed Chen 
32*9dc8ba19STed Chen static const struct r8152_dongle const r8152_dongles[] = {
33*9dc8ba19STed Chen 	/* Realtek */
34*9dc8ba19STed Chen 	{ 0x0bda, 0x8050 },
35*9dc8ba19STed Chen 	{ 0x0bda, 0x8152 },
36*9dc8ba19STed Chen 	{ 0x0bda, 0x8153 },
37*9dc8ba19STed Chen 
38*9dc8ba19STed Chen 	/* Samsung */
39*9dc8ba19STed Chen 	{ 0x04e8, 0xa101 },
40*9dc8ba19STed Chen 
41*9dc8ba19STed Chen 	/* Lenovo */
42*9dc8ba19STed Chen 	{ 0x17ef, 0x304f },
43*9dc8ba19STed Chen 	{ 0x17ef, 0x3052 },
44*9dc8ba19STed Chen 	{ 0x17ef, 0x3054 },
45*9dc8ba19STed Chen 	{ 0x17ef, 0x3057 },
46*9dc8ba19STed Chen 	{ 0x17ef, 0x7205 },
47*9dc8ba19STed Chen 	{ 0x17ef, 0x720a },
48*9dc8ba19STed Chen 	{ 0x17ef, 0x720b },
49*9dc8ba19STed Chen 	{ 0x17ef, 0x720c },
50*9dc8ba19STed Chen 
51*9dc8ba19STed Chen 	/* TP-LINK */
52*9dc8ba19STed Chen 	{ 0x2357, 0x0601 },
53*9dc8ba19STed Chen 
54*9dc8ba19STed Chen 	/* Nvidia */
55*9dc8ba19STed Chen 	{ 0x0955, 0x09ff },
56*9dc8ba19STed Chen };
57*9dc8ba19STed Chen 
58*9dc8ba19STed Chen static const struct r8152_version const r8152_versions[] = {
59*9dc8ba19STed Chen 	{ 0x4c00, RTL_VER_01, 0 },
60*9dc8ba19STed Chen 	{ 0x4c10, RTL_VER_02, 0 },
61*9dc8ba19STed Chen 	{ 0x5c00, RTL_VER_03, 1 },
62*9dc8ba19STed Chen 	{ 0x5c10, RTL_VER_04, 1 },
63*9dc8ba19STed Chen 	{ 0x5c20, RTL_VER_05, 1 },
64*9dc8ba19STed Chen 	{ 0x5c30, RTL_VER_06, 1 },
65*9dc8ba19STed Chen 	{ 0x4800, RTL_VER_07, 0 },
66*9dc8ba19STed Chen };
67*9dc8ba19STed Chen 
68*9dc8ba19STed Chen static
69*9dc8ba19STed Chen int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
70*9dc8ba19STed Chen {
71*9dc8ba19STed Chen 	return usb_control_msg(tp->udev, usb_rcvctrlpipe(tp->udev, 0),
72*9dc8ba19STed Chen 			       RTL8152_REQ_GET_REGS, RTL8152_REQT_READ,
73*9dc8ba19STed Chen 			       value, index, data, size, 500);
74*9dc8ba19STed Chen }
75*9dc8ba19STed Chen 
76*9dc8ba19STed Chen static
77*9dc8ba19STed Chen int set_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
78*9dc8ba19STed Chen {
79*9dc8ba19STed Chen 	return usb_control_msg(tp->udev, usb_sndctrlpipe(tp->udev, 0),
80*9dc8ba19STed Chen 			       RTL8152_REQ_SET_REGS, RTL8152_REQT_WRITE,
81*9dc8ba19STed Chen 			       value, index, data, size, 500);
82*9dc8ba19STed Chen }
83*9dc8ba19STed Chen 
84*9dc8ba19STed Chen int generic_ocp_read(struct r8152 *tp, u16 index, u16 size,
85*9dc8ba19STed Chen 		     void *data, u16 type)
86*9dc8ba19STed Chen {
87*9dc8ba19STed Chen 	u16 burst_size = 64;
88*9dc8ba19STed Chen 	int ret;
89*9dc8ba19STed Chen 	int txsize;
90*9dc8ba19STed Chen 
91*9dc8ba19STed Chen 	/* both size and index must be 4 bytes align */
92*9dc8ba19STed Chen 	if ((size & 3) || !size || (index & 3) || !data)
93*9dc8ba19STed Chen 		return -EINVAL;
94*9dc8ba19STed Chen 
95*9dc8ba19STed Chen 	if (index + size > 0xffff)
96*9dc8ba19STed Chen 		return -EINVAL;
97*9dc8ba19STed Chen 
98*9dc8ba19STed Chen 	while (size) {
99*9dc8ba19STed Chen 		txsize = min(size, burst_size);
100*9dc8ba19STed Chen 		ret = get_registers(tp, index, type, txsize, data);
101*9dc8ba19STed Chen 		if (ret < 0)
102*9dc8ba19STed Chen 			break;
103*9dc8ba19STed Chen 
104*9dc8ba19STed Chen 		index += txsize;
105*9dc8ba19STed Chen 		data += txsize;
106*9dc8ba19STed Chen 		size -= txsize;
107*9dc8ba19STed Chen 	}
108*9dc8ba19STed Chen 
109*9dc8ba19STed Chen 	return ret;
110*9dc8ba19STed Chen }
111*9dc8ba19STed Chen 
112*9dc8ba19STed Chen int generic_ocp_write(struct r8152 *tp, u16 index, u16 byteen,
113*9dc8ba19STed Chen 		      u16 size, void *data, u16 type)
114*9dc8ba19STed Chen {
115*9dc8ba19STed Chen 	int ret;
116*9dc8ba19STed Chen 	u16 byteen_start, byteen_end, byte_en_to_hw;
117*9dc8ba19STed Chen 	u16 burst_size = 512;
118*9dc8ba19STed Chen 	int txsize;
119*9dc8ba19STed Chen 
120*9dc8ba19STed Chen 	/* both size and index must be 4 bytes align */
121*9dc8ba19STed Chen 	if ((size & 3) || !size || (index & 3) || !data)
122*9dc8ba19STed Chen 		return -EINVAL;
123*9dc8ba19STed Chen 
124*9dc8ba19STed Chen 	if (index + size > 0xffff)
125*9dc8ba19STed Chen 		return -EINVAL;
126*9dc8ba19STed Chen 
127*9dc8ba19STed Chen 	byteen_start = byteen & BYTE_EN_START_MASK;
128*9dc8ba19STed Chen 	byteen_end = byteen & BYTE_EN_END_MASK;
129*9dc8ba19STed Chen 
130*9dc8ba19STed Chen 	byte_en_to_hw = byteen_start | (byteen_start << 4);
131*9dc8ba19STed Chen 	ret = set_registers(tp, index, type | byte_en_to_hw, 4, data);
132*9dc8ba19STed Chen 	if (ret < 0)
133*9dc8ba19STed Chen 		return ret;
134*9dc8ba19STed Chen 
135*9dc8ba19STed Chen 	index += 4;
136*9dc8ba19STed Chen 	data += 4;
137*9dc8ba19STed Chen 	size -= 4;
138*9dc8ba19STed Chen 
139*9dc8ba19STed Chen 	if (size) {
140*9dc8ba19STed Chen 		size -= 4;
141*9dc8ba19STed Chen 
142*9dc8ba19STed Chen 		while (size) {
143*9dc8ba19STed Chen 			txsize = min(size, burst_size);
144*9dc8ba19STed Chen 
145*9dc8ba19STed Chen 			ret = set_registers(tp, index,
146*9dc8ba19STed Chen 					    type | BYTE_EN_DWORD,
147*9dc8ba19STed Chen 					    txsize, data);
148*9dc8ba19STed Chen 			if (ret < 0)
149*9dc8ba19STed Chen 				return ret;
150*9dc8ba19STed Chen 
151*9dc8ba19STed Chen 			index += txsize;
152*9dc8ba19STed Chen 			data += txsize;
153*9dc8ba19STed Chen 			size -= txsize;
154*9dc8ba19STed Chen 		}
155*9dc8ba19STed Chen 
156*9dc8ba19STed Chen 		byte_en_to_hw = byteen_end | (byteen_end >> 4);
157*9dc8ba19STed Chen 		ret = set_registers(tp, index, type | byte_en_to_hw, 4, data);
158*9dc8ba19STed Chen 		if (ret < 0)
159*9dc8ba19STed Chen 			return ret;
160*9dc8ba19STed Chen 	}
161*9dc8ba19STed Chen 
162*9dc8ba19STed Chen 	return ret;
163*9dc8ba19STed Chen }
164*9dc8ba19STed Chen 
165*9dc8ba19STed Chen int pla_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
166*9dc8ba19STed Chen {
167*9dc8ba19STed Chen 	return generic_ocp_read(tp, index, size, data, MCU_TYPE_PLA);
168*9dc8ba19STed Chen }
169*9dc8ba19STed Chen 
170*9dc8ba19STed Chen int pla_ocp_write(struct r8152 *tp, u16 index, u16 byteen, u16 size, void *data)
171*9dc8ba19STed Chen {
172*9dc8ba19STed Chen 	return generic_ocp_write(tp, index, byteen, size, data, MCU_TYPE_PLA);
173*9dc8ba19STed Chen }
174*9dc8ba19STed Chen 
175*9dc8ba19STed Chen int usb_ocp_read(struct r8152 *tp, u16 index, u16 size, void *data)
176*9dc8ba19STed Chen {
177*9dc8ba19STed Chen 	return generic_ocp_read(tp, index, size, data, MCU_TYPE_USB);
178*9dc8ba19STed Chen }
179*9dc8ba19STed Chen 
180*9dc8ba19STed Chen int usb_ocp_write(struct r8152 *tp, u16 index, u16 byteen, u16 size, void *data)
181*9dc8ba19STed Chen {
182*9dc8ba19STed Chen 	return generic_ocp_write(tp, index, byteen, size, data, MCU_TYPE_USB);
183*9dc8ba19STed Chen }
184*9dc8ba19STed Chen 
185*9dc8ba19STed Chen u32 ocp_read_dword(struct r8152 *tp, u16 type, u16 index)
186*9dc8ba19STed Chen {
187*9dc8ba19STed Chen 	__le32 data;
188*9dc8ba19STed Chen 
189*9dc8ba19STed Chen 	generic_ocp_read(tp, index, sizeof(data), &data, type);
190*9dc8ba19STed Chen 
191*9dc8ba19STed Chen 	return __le32_to_cpu(data);
192*9dc8ba19STed Chen }
193*9dc8ba19STed Chen 
194*9dc8ba19STed Chen void ocp_write_dword(struct r8152 *tp, u16 type, u16 index, u32 data)
195*9dc8ba19STed Chen {
196*9dc8ba19STed Chen 	__le32 tmp = __cpu_to_le32(data);
197*9dc8ba19STed Chen 
198*9dc8ba19STed Chen 	generic_ocp_write(tp, index, BYTE_EN_DWORD, sizeof(tmp), &tmp, type);
199*9dc8ba19STed Chen }
200*9dc8ba19STed Chen 
201*9dc8ba19STed Chen u16 ocp_read_word(struct r8152 *tp, u16 type, u16 index)
202*9dc8ba19STed Chen {
203*9dc8ba19STed Chen 	u32 data;
204*9dc8ba19STed Chen 	__le32 tmp;
205*9dc8ba19STed Chen 	u8 shift = index & 2;
206*9dc8ba19STed Chen 
207*9dc8ba19STed Chen 	index &= ~3;
208*9dc8ba19STed Chen 
209*9dc8ba19STed Chen 	generic_ocp_read(tp, index, sizeof(tmp), &tmp, type);
210*9dc8ba19STed Chen 
211*9dc8ba19STed Chen 	data = __le32_to_cpu(tmp);
212*9dc8ba19STed Chen 	data >>= (shift * 8);
213*9dc8ba19STed Chen 	data &= 0xffff;
214*9dc8ba19STed Chen 
215*9dc8ba19STed Chen 	return data;
216*9dc8ba19STed Chen }
217*9dc8ba19STed Chen 
218*9dc8ba19STed Chen void ocp_write_word(struct r8152 *tp, u16 type, u16 index, u32 data)
219*9dc8ba19STed Chen {
220*9dc8ba19STed Chen 	u32 mask = 0xffff;
221*9dc8ba19STed Chen 	__le32 tmp;
222*9dc8ba19STed Chen 	u16 byen = BYTE_EN_WORD;
223*9dc8ba19STed Chen 	u8 shift = index & 2;
224*9dc8ba19STed Chen 
225*9dc8ba19STed Chen 	data &= mask;
226*9dc8ba19STed Chen 
227*9dc8ba19STed Chen 	if (index & 2) {
228*9dc8ba19STed Chen 		byen <<= shift;
229*9dc8ba19STed Chen 		mask <<= (shift * 8);
230*9dc8ba19STed Chen 		data <<= (shift * 8);
231*9dc8ba19STed Chen 		index &= ~3;
232*9dc8ba19STed Chen 	}
233*9dc8ba19STed Chen 
234*9dc8ba19STed Chen 	tmp = __cpu_to_le32(data);
235*9dc8ba19STed Chen 
236*9dc8ba19STed Chen 	generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type);
237*9dc8ba19STed Chen }
238*9dc8ba19STed Chen 
239*9dc8ba19STed Chen u8 ocp_read_byte(struct r8152 *tp, u16 type, u16 index)
240*9dc8ba19STed Chen {
241*9dc8ba19STed Chen 	u32 data;
242*9dc8ba19STed Chen 	__le32 tmp;
243*9dc8ba19STed Chen 	u8 shift = index & 3;
244*9dc8ba19STed Chen 
245*9dc8ba19STed Chen 	index &= ~3;
246*9dc8ba19STed Chen 
247*9dc8ba19STed Chen 	generic_ocp_read(tp, index, sizeof(tmp), &tmp, type);
248*9dc8ba19STed Chen 
249*9dc8ba19STed Chen 	data = __le32_to_cpu(tmp);
250*9dc8ba19STed Chen 	data >>= (shift * 8);
251*9dc8ba19STed Chen 	data &= 0xff;
252*9dc8ba19STed Chen 
253*9dc8ba19STed Chen 	return data;
254*9dc8ba19STed Chen }
255*9dc8ba19STed Chen 
256*9dc8ba19STed Chen void ocp_write_byte(struct r8152 *tp, u16 type, u16 index, u32 data)
257*9dc8ba19STed Chen {
258*9dc8ba19STed Chen 	u32 mask = 0xff;
259*9dc8ba19STed Chen 	__le32 tmp;
260*9dc8ba19STed Chen 	u16 byen = BYTE_EN_BYTE;
261*9dc8ba19STed Chen 	u8 shift = index & 3;
262*9dc8ba19STed Chen 
263*9dc8ba19STed Chen 	data &= mask;
264*9dc8ba19STed Chen 
265*9dc8ba19STed Chen 	if (index & 3) {
266*9dc8ba19STed Chen 		byen <<= shift;
267*9dc8ba19STed Chen 		mask <<= (shift * 8);
268*9dc8ba19STed Chen 		data <<= (shift * 8);
269*9dc8ba19STed Chen 		index &= ~3;
270*9dc8ba19STed Chen 	}
271*9dc8ba19STed Chen 
272*9dc8ba19STed Chen 	tmp = __cpu_to_le32(data);
273*9dc8ba19STed Chen 
274*9dc8ba19STed Chen 	generic_ocp_write(tp, index, byen, sizeof(tmp), &tmp, type);
275*9dc8ba19STed Chen }
276*9dc8ba19STed Chen 
277*9dc8ba19STed Chen u16 ocp_reg_read(struct r8152 *tp, u16 addr)
278*9dc8ba19STed Chen {
279*9dc8ba19STed Chen 	u16 ocp_base, ocp_index;
280*9dc8ba19STed Chen 
281*9dc8ba19STed Chen 	ocp_base = addr & 0xf000;
282*9dc8ba19STed Chen 	if (ocp_base != tp->ocp_base) {
283*9dc8ba19STed Chen 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
284*9dc8ba19STed Chen 		tp->ocp_base = ocp_base;
285*9dc8ba19STed Chen 	}
286*9dc8ba19STed Chen 
287*9dc8ba19STed Chen 	ocp_index = (addr & 0x0fff) | 0xb000;
288*9dc8ba19STed Chen 	return ocp_read_word(tp, MCU_TYPE_PLA, ocp_index);
289*9dc8ba19STed Chen }
290*9dc8ba19STed Chen 
291*9dc8ba19STed Chen void ocp_reg_write(struct r8152 *tp, u16 addr, u16 data)
292*9dc8ba19STed Chen {
293*9dc8ba19STed Chen 	u16 ocp_base, ocp_index;
294*9dc8ba19STed Chen 
295*9dc8ba19STed Chen 	ocp_base = addr & 0xf000;
296*9dc8ba19STed Chen 	if (ocp_base != tp->ocp_base) {
297*9dc8ba19STed Chen 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_OCP_GPHY_BASE, ocp_base);
298*9dc8ba19STed Chen 		tp->ocp_base = ocp_base;
299*9dc8ba19STed Chen 	}
300*9dc8ba19STed Chen 
301*9dc8ba19STed Chen 	ocp_index = (addr & 0x0fff) | 0xb000;
302*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, ocp_index, data);
303*9dc8ba19STed Chen }
304*9dc8ba19STed Chen 
305*9dc8ba19STed Chen static void r8152_mdio_write(struct r8152 *tp, u32 reg_addr, u32 value)
306*9dc8ba19STed Chen {
307*9dc8ba19STed Chen 	ocp_reg_write(tp, OCP_BASE_MII + reg_addr * 2, value);
308*9dc8ba19STed Chen }
309*9dc8ba19STed Chen 
310*9dc8ba19STed Chen static int r8152_mdio_read(struct r8152 *tp, u32 reg_addr)
311*9dc8ba19STed Chen {
312*9dc8ba19STed Chen 	return ocp_reg_read(tp, OCP_BASE_MII + reg_addr * 2);
313*9dc8ba19STed Chen }
314*9dc8ba19STed Chen 
315*9dc8ba19STed Chen void sram_write(struct r8152 *tp, u16 addr, u16 data)
316*9dc8ba19STed Chen {
317*9dc8ba19STed Chen 	ocp_reg_write(tp, OCP_SRAM_ADDR, addr);
318*9dc8ba19STed Chen 	ocp_reg_write(tp, OCP_SRAM_DATA, data);
319*9dc8ba19STed Chen }
320*9dc8ba19STed Chen 
321*9dc8ba19STed Chen int r8152_wait_for_bit(struct r8152 *tp, bool ocp_reg, u16 type, u16 index,
322*9dc8ba19STed Chen 		       const u32 mask, bool set, unsigned int timeout)
323*9dc8ba19STed Chen {
324*9dc8ba19STed Chen 	u32 val;
325*9dc8ba19STed Chen 
326*9dc8ba19STed Chen 	while (--timeout) {
327*9dc8ba19STed Chen 		if (ocp_reg)
328*9dc8ba19STed Chen 			val = ocp_reg_read(tp, index);
329*9dc8ba19STed Chen 		else
330*9dc8ba19STed Chen 			val = ocp_read_dword(tp, type, index);
331*9dc8ba19STed Chen 
332*9dc8ba19STed Chen 		if (!set)
333*9dc8ba19STed Chen 			val = ~val;
334*9dc8ba19STed Chen 
335*9dc8ba19STed Chen 		if ((val & mask) == mask)
336*9dc8ba19STed Chen 			return 0;
337*9dc8ba19STed Chen 
338*9dc8ba19STed Chen 		mdelay(1);
339*9dc8ba19STed Chen 	}
340*9dc8ba19STed Chen 
341*9dc8ba19STed Chen 	debug("%s: Timeout (index=%04x mask=%08x timeout=%d)\n",
342*9dc8ba19STed Chen 	      __func__, index, mask, timeout);
343*9dc8ba19STed Chen 
344*9dc8ba19STed Chen 	return -ETIMEDOUT;
345*9dc8ba19STed Chen }
346*9dc8ba19STed Chen 
347*9dc8ba19STed Chen static void r8152b_reset_packet_filter(struct r8152 *tp)
348*9dc8ba19STed Chen {
349*9dc8ba19STed Chen 	u32 ocp_data;
350*9dc8ba19STed Chen 
351*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_FMC);
352*9dc8ba19STed Chen 	ocp_data &= ~FMC_FCR_MCU_EN;
353*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_FMC, ocp_data);
354*9dc8ba19STed Chen 	ocp_data |= FMC_FCR_MCU_EN;
355*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_FMC, ocp_data);
356*9dc8ba19STed Chen }
357*9dc8ba19STed Chen 
358*9dc8ba19STed Chen static void rtl8152_wait_fifo_empty(struct r8152 *tp)
359*9dc8ba19STed Chen {
360*9dc8ba19STed Chen 	int ret;
361*9dc8ba19STed Chen 
362*9dc8ba19STed Chen 	ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_PHY_PWR,
363*9dc8ba19STed Chen 				 PLA_PHY_PWR_TXEMP, 1, R8152_WAIT_TIMEOUT);
364*9dc8ba19STed Chen 	if (ret)
365*9dc8ba19STed Chen 		debug("Timeout waiting for FIFO empty\n");
366*9dc8ba19STed Chen 
367*9dc8ba19STed Chen 	ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_TCR0,
368*9dc8ba19STed Chen 				 TCR0_TX_EMPTY, 1, R8152_WAIT_TIMEOUT);
369*9dc8ba19STed Chen 	if (ret)
370*9dc8ba19STed Chen 		debug("Timeout waiting for TX empty\n");
371*9dc8ba19STed Chen }
372*9dc8ba19STed Chen 
373*9dc8ba19STed Chen static void rtl8152_nic_reset(struct r8152 *tp)
374*9dc8ba19STed Chen {
375*9dc8ba19STed Chen 	int ret;
376*9dc8ba19STed Chen 	u32 ocp_data;
377*9dc8ba19STed Chen 
378*9dc8ba19STed Chen 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, BIST_CTRL);
379*9dc8ba19STed Chen 	ocp_data |= BIST_CTRL_SW_RESET;
380*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, BIST_CTRL, ocp_data);
381*9dc8ba19STed Chen 
382*9dc8ba19STed Chen 	ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, BIST_CTRL,
383*9dc8ba19STed Chen 				 BIST_CTRL_SW_RESET, 0, R8152_WAIT_TIMEOUT);
384*9dc8ba19STed Chen 	if (ret)
385*9dc8ba19STed Chen 		debug("Timeout waiting for NIC reset\n");
386*9dc8ba19STed Chen }
387*9dc8ba19STed Chen 
388*9dc8ba19STed Chen static u8 rtl8152_get_speed(struct r8152 *tp)
389*9dc8ba19STed Chen {
390*9dc8ba19STed Chen 	return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS);
391*9dc8ba19STed Chen }
392*9dc8ba19STed Chen 
393*9dc8ba19STed Chen static void rtl_set_eee_plus(struct r8152 *tp)
394*9dc8ba19STed Chen {
395*9dc8ba19STed Chen 	u32 ocp_data;
396*9dc8ba19STed Chen 
397*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR);
398*9dc8ba19STed Chen 	ocp_data &= ~EEEP_CR_EEEP_TX;
399*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR, ocp_data);
400*9dc8ba19STed Chen }
401*9dc8ba19STed Chen 
402*9dc8ba19STed Chen static void rxdy_gated_en(struct r8152 *tp, bool enable)
403*9dc8ba19STed Chen {
404*9dc8ba19STed Chen 	u32 ocp_data;
405*9dc8ba19STed Chen 
406*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_MISC_1);
407*9dc8ba19STed Chen 	if (enable)
408*9dc8ba19STed Chen 		ocp_data |= RXDY_GATED_EN;
409*9dc8ba19STed Chen 	else
410*9dc8ba19STed Chen 		ocp_data &= ~RXDY_GATED_EN;
411*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_MISC_1, ocp_data);
412*9dc8ba19STed Chen }
413*9dc8ba19STed Chen 
414*9dc8ba19STed Chen static void rtl8152_set_rx_mode(struct r8152 *tp)
415*9dc8ba19STed Chen {
416*9dc8ba19STed Chen 	u32 ocp_data;
417*9dc8ba19STed Chen 	__le32 tmp[2];
418*9dc8ba19STed Chen 
419*9dc8ba19STed Chen 	tmp[0] = 0xffffffff;
420*9dc8ba19STed Chen 	tmp[1] = 0xffffffff;
421*9dc8ba19STed Chen 
422*9dc8ba19STed Chen 	pla_ocp_write(tp, PLA_MAR, BYTE_EN_DWORD, sizeof(tmp), tmp);
423*9dc8ba19STed Chen 
424*9dc8ba19STed Chen 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
425*9dc8ba19STed Chen 	ocp_data |= RCR_APM | RCR_AM | RCR_AB;
426*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
427*9dc8ba19STed Chen }
428*9dc8ba19STed Chen 
429*9dc8ba19STed Chen static int rtl_enable(struct r8152 *tp)
430*9dc8ba19STed Chen {
431*9dc8ba19STed Chen 	u32 ocp_data;
432*9dc8ba19STed Chen 
433*9dc8ba19STed Chen 	r8152b_reset_packet_filter(tp);
434*9dc8ba19STed Chen 
435*9dc8ba19STed Chen 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_CR);
436*9dc8ba19STed Chen 	ocp_data |= PLA_CR_RE | PLA_CR_TE;
437*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, ocp_data);
438*9dc8ba19STed Chen 
439*9dc8ba19STed Chen 	rxdy_gated_en(tp, false);
440*9dc8ba19STed Chen 
441*9dc8ba19STed Chen 	rtl8152_set_rx_mode(tp);
442*9dc8ba19STed Chen 
443*9dc8ba19STed Chen 	return 0;
444*9dc8ba19STed Chen }
445*9dc8ba19STed Chen 
446*9dc8ba19STed Chen static int rtl8152_enable(struct r8152 *tp)
447*9dc8ba19STed Chen {
448*9dc8ba19STed Chen 	rtl_set_eee_plus(tp);
449*9dc8ba19STed Chen 
450*9dc8ba19STed Chen 	return rtl_enable(tp);
451*9dc8ba19STed Chen }
452*9dc8ba19STed Chen 
453*9dc8ba19STed Chen static void r8153_set_rx_early_timeout(struct r8152 *tp)
454*9dc8ba19STed Chen {
455*9dc8ba19STed Chen 	u32 ocp_data = tp->coalesce / 8;
456*9dc8ba19STed Chen 
457*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_TIMEOUT, ocp_data);
458*9dc8ba19STed Chen }
459*9dc8ba19STed Chen 
460*9dc8ba19STed Chen static void r8153_set_rx_early_size(struct r8152 *tp)
461*9dc8ba19STed Chen {
462*9dc8ba19STed Chen 	u32 ocp_data = (RTL8152_AGG_BUF_SZ - RTL8153_RMS) / 4;
463*9dc8ba19STed Chen 
464*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, USB_RX_EARLY_SIZE, ocp_data);
465*9dc8ba19STed Chen }
466*9dc8ba19STed Chen 
467*9dc8ba19STed Chen static int rtl8153_enable(struct r8152 *tp)
468*9dc8ba19STed Chen {
469*9dc8ba19STed Chen 	rtl_set_eee_plus(tp);
470*9dc8ba19STed Chen 	r8153_set_rx_early_timeout(tp);
471*9dc8ba19STed Chen 	r8153_set_rx_early_size(tp);
472*9dc8ba19STed Chen 
473*9dc8ba19STed Chen 	return rtl_enable(tp);
474*9dc8ba19STed Chen }
475*9dc8ba19STed Chen 
476*9dc8ba19STed Chen static void rtl_disable(struct r8152 *tp)
477*9dc8ba19STed Chen {
478*9dc8ba19STed Chen 	u32 ocp_data;
479*9dc8ba19STed Chen 
480*9dc8ba19STed Chen 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
481*9dc8ba19STed Chen 	ocp_data &= ~RCR_ACPT_ALL;
482*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
483*9dc8ba19STed Chen 
484*9dc8ba19STed Chen 	rxdy_gated_en(tp, true);
485*9dc8ba19STed Chen 
486*9dc8ba19STed Chen 	rtl8152_wait_fifo_empty(tp);
487*9dc8ba19STed Chen 	rtl8152_nic_reset(tp);
488*9dc8ba19STed Chen }
489*9dc8ba19STed Chen 
490*9dc8ba19STed Chen static void r8152_power_cut_en(struct r8152 *tp, bool enable)
491*9dc8ba19STed Chen {
492*9dc8ba19STed Chen 	u32 ocp_data;
493*9dc8ba19STed Chen 
494*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_UPS_CTRL);
495*9dc8ba19STed Chen 	if (enable)
496*9dc8ba19STed Chen 		ocp_data |= POWER_CUT;
497*9dc8ba19STed Chen 	else
498*9dc8ba19STed Chen 		ocp_data &= ~POWER_CUT;
499*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, USB_UPS_CTRL, ocp_data);
500*9dc8ba19STed Chen 
501*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS);
502*9dc8ba19STed Chen 	ocp_data &= ~RESUME_INDICATE;
503*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, USB_PM_CTRL_STATUS, ocp_data);
504*9dc8ba19STed Chen }
505*9dc8ba19STed Chen 
506*9dc8ba19STed Chen static void rtl_rx_vlan_en(struct r8152 *tp, bool enable)
507*9dc8ba19STed Chen {
508*9dc8ba19STed Chen 	u32 ocp_data;
509*9dc8ba19STed Chen 
510*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_CPCR);
511*9dc8ba19STed Chen 	if (enable)
512*9dc8ba19STed Chen 		ocp_data |= CPCR_RX_VLAN;
513*9dc8ba19STed Chen 	else
514*9dc8ba19STed Chen 		ocp_data &= ~CPCR_RX_VLAN;
515*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_CPCR, ocp_data);
516*9dc8ba19STed Chen }
517*9dc8ba19STed Chen 
518*9dc8ba19STed Chen static void r8153_u1u2en(struct r8152 *tp, bool enable)
519*9dc8ba19STed Chen {
520*9dc8ba19STed Chen 	u8 u1u2[8];
521*9dc8ba19STed Chen 
522*9dc8ba19STed Chen 	if (enable)
523*9dc8ba19STed Chen 		memset(u1u2, 0xff, sizeof(u1u2));
524*9dc8ba19STed Chen 	else
525*9dc8ba19STed Chen 		memset(u1u2, 0x00, sizeof(u1u2));
526*9dc8ba19STed Chen 
527*9dc8ba19STed Chen 	usb_ocp_write(tp, USB_TOLERANCE, BYTE_EN_SIX_BYTES, sizeof(u1u2), u1u2);
528*9dc8ba19STed Chen }
529*9dc8ba19STed Chen 
530*9dc8ba19STed Chen static void r8153_u2p3en(struct r8152 *tp, bool enable)
531*9dc8ba19STed Chen {
532*9dc8ba19STed Chen 	u32 ocp_data;
533*9dc8ba19STed Chen 
534*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL);
535*9dc8ba19STed Chen 	if (enable && tp->version != RTL_VER_03 && tp->version != RTL_VER_04)
536*9dc8ba19STed Chen 		ocp_data |= U2P3_ENABLE;
537*9dc8ba19STed Chen 	else
538*9dc8ba19STed Chen 		ocp_data &= ~U2P3_ENABLE;
539*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data);
540*9dc8ba19STed Chen }
541*9dc8ba19STed Chen 
542*9dc8ba19STed Chen static void r8153_power_cut_en(struct r8152 *tp, bool enable)
543*9dc8ba19STed Chen {
544*9dc8ba19STed Chen 	u32 ocp_data;
545*9dc8ba19STed Chen 
546*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_POWER_CUT);
547*9dc8ba19STed Chen 	if (enable)
548*9dc8ba19STed Chen 		ocp_data |= PWR_EN | PHASE2_EN;
549*9dc8ba19STed Chen 	else
550*9dc8ba19STed Chen 		ocp_data &= ~(PWR_EN | PHASE2_EN);
551*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data);
552*9dc8ba19STed Chen 
553*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
554*9dc8ba19STed Chen 	ocp_data &= ~PCUT_STATUS;
555*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data);
556*9dc8ba19STed Chen }
557*9dc8ba19STed Chen 
558*9dc8ba19STed Chen static int r8152_read_mac(struct r8152 *tp, unsigned char *macaddr)
559*9dc8ba19STed Chen {
560*9dc8ba19STed Chen 	int ret;
561*9dc8ba19STed Chen 	unsigned char enetaddr[8] = {0};
562*9dc8ba19STed Chen 
563*9dc8ba19STed Chen 	ret = pla_ocp_read(tp, PLA_IDR, 8, enetaddr);
564*9dc8ba19STed Chen 	if (ret < 0)
565*9dc8ba19STed Chen 		return ret;
566*9dc8ba19STed Chen 
567*9dc8ba19STed Chen 	memcpy(macaddr, enetaddr, ETH_ALEN);
568*9dc8ba19STed Chen 	return 0;
569*9dc8ba19STed Chen }
570*9dc8ba19STed Chen 
571*9dc8ba19STed Chen static void r8152b_disable_aldps(struct r8152 *tp)
572*9dc8ba19STed Chen {
573*9dc8ba19STed Chen 	ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPDNPS | LINKENA | DIS_SDSAVE);
574*9dc8ba19STed Chen 	mdelay(20);
575*9dc8ba19STed Chen }
576*9dc8ba19STed Chen 
577*9dc8ba19STed Chen static void r8152b_enable_aldps(struct r8152 *tp)
578*9dc8ba19STed Chen {
579*9dc8ba19STed Chen 	ocp_reg_write(tp, OCP_ALDPS_CONFIG, ENPWRSAVE | ENPDNPS |
580*9dc8ba19STed Chen 		LINKENA | DIS_SDSAVE);
581*9dc8ba19STed Chen }
582*9dc8ba19STed Chen 
583*9dc8ba19STed Chen static void rtl8152_disable(struct r8152 *tp)
584*9dc8ba19STed Chen {
585*9dc8ba19STed Chen 	r8152b_disable_aldps(tp);
586*9dc8ba19STed Chen 	rtl_disable(tp);
587*9dc8ba19STed Chen 	r8152b_enable_aldps(tp);
588*9dc8ba19STed Chen }
589*9dc8ba19STed Chen 
590*9dc8ba19STed Chen static void r8152b_hw_phy_cfg(struct r8152 *tp)
591*9dc8ba19STed Chen {
592*9dc8ba19STed Chen 	u16 data;
593*9dc8ba19STed Chen 
594*9dc8ba19STed Chen 	data = r8152_mdio_read(tp, MII_BMCR);
595*9dc8ba19STed Chen 	if (data & BMCR_PDOWN) {
596*9dc8ba19STed Chen 		data &= ~BMCR_PDOWN;
597*9dc8ba19STed Chen 		r8152_mdio_write(tp, MII_BMCR, data);
598*9dc8ba19STed Chen 	}
599*9dc8ba19STed Chen 
600*9dc8ba19STed Chen 	r8152b_firmware(tp);
601*9dc8ba19STed Chen }
602*9dc8ba19STed Chen 
603*9dc8ba19STed Chen static void rtl8152_reinit_ll(struct r8152 *tp)
604*9dc8ba19STed Chen {
605*9dc8ba19STed Chen 	u32 ocp_data;
606*9dc8ba19STed Chen 	int ret;
607*9dc8ba19STed Chen 
608*9dc8ba19STed Chen 	ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_PHY_PWR,
609*9dc8ba19STed Chen 				 PLA_PHY_PWR_LLR, 1, R8152_WAIT_TIMEOUT);
610*9dc8ba19STed Chen 	if (ret)
611*9dc8ba19STed Chen 		debug("Timeout waiting for link list ready\n");
612*9dc8ba19STed Chen 
613*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
614*9dc8ba19STed Chen 	ocp_data |= RE_INIT_LL;
615*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
616*9dc8ba19STed Chen 
617*9dc8ba19STed Chen 	ret = r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_PHY_PWR,
618*9dc8ba19STed Chen 				 PLA_PHY_PWR_LLR, 1, R8152_WAIT_TIMEOUT);
619*9dc8ba19STed Chen 	if (ret)
620*9dc8ba19STed Chen 		debug("Timeout waiting for link list ready\n");
621*9dc8ba19STed Chen }
622*9dc8ba19STed Chen 
623*9dc8ba19STed Chen static void r8152b_exit_oob(struct r8152 *tp)
624*9dc8ba19STed Chen {
625*9dc8ba19STed Chen 	u32 ocp_data;
626*9dc8ba19STed Chen 
627*9dc8ba19STed Chen 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
628*9dc8ba19STed Chen 	ocp_data &= ~RCR_ACPT_ALL;
629*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
630*9dc8ba19STed Chen 
631*9dc8ba19STed Chen 	rxdy_gated_en(tp, true);
632*9dc8ba19STed Chen 	r8152b_hw_phy_cfg(tp);
633*9dc8ba19STed Chen 
634*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
635*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CR, 0x00);
636*9dc8ba19STed Chen 
637*9dc8ba19STed Chen 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
638*9dc8ba19STed Chen 	ocp_data &= ~NOW_IS_OOB;
639*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
640*9dc8ba19STed Chen 
641*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
642*9dc8ba19STed Chen 	ocp_data &= ~MCU_BORW_EN;
643*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
644*9dc8ba19STed Chen 
645*9dc8ba19STed Chen 	rtl8152_reinit_ll(tp);
646*9dc8ba19STed Chen 	rtl8152_nic_reset(tp);
647*9dc8ba19STed Chen 
648*9dc8ba19STed Chen 	/* rx share fifo credit full threshold */
649*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL);
650*9dc8ba19STed Chen 
651*9dc8ba19STed Chen 	if (tp->udev->speed == USB_SPEED_FULL ||
652*9dc8ba19STed Chen 	    tp->udev->speed == USB_SPEED_LOW) {
653*9dc8ba19STed Chen 		/* rx share fifo credit near full threshold */
654*9dc8ba19STed Chen 		ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
655*9dc8ba19STed Chen 				RXFIFO_THR2_FULL);
656*9dc8ba19STed Chen 		ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2,
657*9dc8ba19STed Chen 				RXFIFO_THR3_FULL);
658*9dc8ba19STed Chen 	} else {
659*9dc8ba19STed Chen 		/* rx share fifo credit near full threshold */
660*9dc8ba19STed Chen 		ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1,
661*9dc8ba19STed Chen 				RXFIFO_THR2_HIGH);
662*9dc8ba19STed Chen 		ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2,
663*9dc8ba19STed Chen 				RXFIFO_THR3_HIGH);
664*9dc8ba19STed Chen 	}
665*9dc8ba19STed Chen 
666*9dc8ba19STed Chen 	/* TX share fifo free credit full threshold */
667*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL);
668*9dc8ba19STed Chen 
669*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_USB, USB_TX_AGG, TX_AGG_MAX_THRESHOLD);
670*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_USB, USB_RX_BUF_TH, RX_THR_HIGH);
671*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_USB, USB_TX_DMA,
672*9dc8ba19STed Chen 			TEST_MODE_DISABLE | TX_SIZE_ADJUST1);
673*9dc8ba19STed Chen 
674*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
675*9dc8ba19STed Chen 
676*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0);
677*9dc8ba19STed Chen 	ocp_data |= TCR0_AUTO_FIFO;
678*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR0, ocp_data);
679*9dc8ba19STed Chen }
680*9dc8ba19STed Chen 
681*9dc8ba19STed Chen static void r8152b_enter_oob(struct r8152 *tp)
682*9dc8ba19STed Chen {
683*9dc8ba19STed Chen 	u32 ocp_data;
684*9dc8ba19STed Chen 
685*9dc8ba19STed Chen 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
686*9dc8ba19STed Chen 	ocp_data &= ~NOW_IS_OOB;
687*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
688*9dc8ba19STed Chen 
689*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_OOB);
690*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_OOB);
691*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_OOB);
692*9dc8ba19STed Chen 
693*9dc8ba19STed Chen 	rtl_disable(tp);
694*9dc8ba19STed Chen 
695*9dc8ba19STed Chen 	rtl8152_reinit_ll(tp);
696*9dc8ba19STed Chen 
697*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, RTL8152_RMS);
698*9dc8ba19STed Chen 
699*9dc8ba19STed Chen 	rtl_rx_vlan_en(tp, false);
700*9dc8ba19STed Chen 
701*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
702*9dc8ba19STed Chen 	ocp_data |= ALDPS_PROXY_MODE;
703*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
704*9dc8ba19STed Chen 
705*9dc8ba19STed Chen 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
706*9dc8ba19STed Chen 	ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
707*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
708*9dc8ba19STed Chen 
709*9dc8ba19STed Chen 	rxdy_gated_en(tp, false);
710*9dc8ba19STed Chen 
711*9dc8ba19STed Chen 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
712*9dc8ba19STed Chen 	ocp_data |= RCR_APM | RCR_AM | RCR_AB;
713*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
714*9dc8ba19STed Chen }
715*9dc8ba19STed Chen 
716*9dc8ba19STed Chen static void r8153_hw_phy_cfg(struct r8152 *tp)
717*9dc8ba19STed Chen {
718*9dc8ba19STed Chen 	u32 ocp_data;
719*9dc8ba19STed Chen 	u16 data;
720*9dc8ba19STed Chen 
721*9dc8ba19STed Chen 	if (tp->version == RTL_VER_03 || tp->version == RTL_VER_04 ||
722*9dc8ba19STed Chen 	    tp->version == RTL_VER_05)
723*9dc8ba19STed Chen 		ocp_reg_write(tp, OCP_ADC_CFG, CKADSEL_L | ADC_EN | EN_EMI_L);
724*9dc8ba19STed Chen 
725*9dc8ba19STed Chen 	data = r8152_mdio_read(tp, MII_BMCR);
726*9dc8ba19STed Chen 	if (data & BMCR_PDOWN) {
727*9dc8ba19STed Chen 		data &= ~BMCR_PDOWN;
728*9dc8ba19STed Chen 		r8152_mdio_write(tp, MII_BMCR, data);
729*9dc8ba19STed Chen 	}
730*9dc8ba19STed Chen 
731*9dc8ba19STed Chen 	r8153_firmware(tp);
732*9dc8ba19STed Chen 
733*9dc8ba19STed Chen 	if (tp->version == RTL_VER_03) {
734*9dc8ba19STed Chen 		data = ocp_reg_read(tp, OCP_EEE_CFG);
735*9dc8ba19STed Chen 		data &= ~CTAP_SHORT_EN;
736*9dc8ba19STed Chen 		ocp_reg_write(tp, OCP_EEE_CFG, data);
737*9dc8ba19STed Chen 	}
738*9dc8ba19STed Chen 
739*9dc8ba19STed Chen 	data = ocp_reg_read(tp, OCP_POWER_CFG);
740*9dc8ba19STed Chen 	data |= EEE_CLKDIV_EN;
741*9dc8ba19STed Chen 	ocp_reg_write(tp, OCP_POWER_CFG, data);
742*9dc8ba19STed Chen 
743*9dc8ba19STed Chen 	data = ocp_reg_read(tp, OCP_DOWN_SPEED);
744*9dc8ba19STed Chen 	data |= EN_10M_BGOFF;
745*9dc8ba19STed Chen 	ocp_reg_write(tp, OCP_DOWN_SPEED, data);
746*9dc8ba19STed Chen 	data = ocp_reg_read(tp, OCP_POWER_CFG);
747*9dc8ba19STed Chen 	data |= EN_10M_PLLOFF;
748*9dc8ba19STed Chen 	ocp_reg_write(tp, OCP_POWER_CFG, data);
749*9dc8ba19STed Chen 	sram_write(tp, SRAM_IMPEDANCE, 0x0b13);
750*9dc8ba19STed Chen 
751*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR);
752*9dc8ba19STed Chen 	ocp_data |= PFM_PWM_SWITCH;
753*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
754*9dc8ba19STed Chen 
755*9dc8ba19STed Chen 	/* Enable LPF corner auto tune */
756*9dc8ba19STed Chen 	sram_write(tp, SRAM_LPF_CFG, 0xf70f);
757*9dc8ba19STed Chen 
758*9dc8ba19STed Chen 	/* Adjust 10M Amplitude */
759*9dc8ba19STed Chen 	sram_write(tp, SRAM_10M_AMP1, 0x00af);
760*9dc8ba19STed Chen 	sram_write(tp, SRAM_10M_AMP2, 0x0208);
761*9dc8ba19STed Chen }
762*9dc8ba19STed Chen 
763*9dc8ba19STed Chen static void r8153_first_init(struct r8152 *tp)
764*9dc8ba19STed Chen {
765*9dc8ba19STed Chen 	u32 ocp_data;
766*9dc8ba19STed Chen 
767*9dc8ba19STed Chen 	rxdy_gated_en(tp, true);
768*9dc8ba19STed Chen 
769*9dc8ba19STed Chen 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
770*9dc8ba19STed Chen 	ocp_data &= ~RCR_ACPT_ALL;
771*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
772*9dc8ba19STed Chen 
773*9dc8ba19STed Chen 	r8153_hw_phy_cfg(tp);
774*9dc8ba19STed Chen 
775*9dc8ba19STed Chen 	rtl8152_nic_reset(tp);
776*9dc8ba19STed Chen 
777*9dc8ba19STed Chen 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
778*9dc8ba19STed Chen 	ocp_data &= ~NOW_IS_OOB;
779*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
780*9dc8ba19STed Chen 
781*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7);
782*9dc8ba19STed Chen 	ocp_data &= ~MCU_BORW_EN;
783*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_SFF_STS_7, ocp_data);
784*9dc8ba19STed Chen 
785*9dc8ba19STed Chen 	rtl8152_reinit_ll(tp);
786*9dc8ba19STed Chen 
787*9dc8ba19STed Chen 	rtl_rx_vlan_en(tp, false);
788*9dc8ba19STed Chen 
789*9dc8ba19STed Chen 	ocp_data = RTL8153_RMS;
790*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data);
791*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_MTPS, MTPS_JUMBO);
792*9dc8ba19STed Chen 
793*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR0);
794*9dc8ba19STed Chen 	ocp_data |= TCR0_AUTO_FIFO;
795*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TCR0, ocp_data);
796*9dc8ba19STed Chen 
797*9dc8ba19STed Chen 	rtl8152_nic_reset(tp);
798*9dc8ba19STed Chen 
799*9dc8ba19STed Chen 	/* rx share fifo credit full threshold */
800*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_NORMAL);
801*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_NORMAL);
802*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_NORMAL);
803*9dc8ba19STed Chen 	/* TX share fifo free credit full threshold */
804*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_TXFIFO_CTRL, TXFIFO_THR_NORMAL2);
805*9dc8ba19STed Chen 
806*9dc8ba19STed Chen 	/* rx aggregation */
807*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
808*9dc8ba19STed Chen 
809*9dc8ba19STed Chen 	ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
810*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
811*9dc8ba19STed Chen }
812*9dc8ba19STed Chen 
813*9dc8ba19STed Chen static void r8153_enter_oob(struct r8152 *tp)
814*9dc8ba19STed Chen {
815*9dc8ba19STed Chen 	u32 ocp_data;
816*9dc8ba19STed Chen 
817*9dc8ba19STed Chen 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
818*9dc8ba19STed Chen 	ocp_data &= ~NOW_IS_OOB;
819*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
820*9dc8ba19STed Chen 
821*9dc8ba19STed Chen 	rtl_disable(tp);
822*9dc8ba19STed Chen 
823*9dc8ba19STed Chen 	rtl8152_reinit_ll(tp);
824*9dc8ba19STed Chen 
825*9dc8ba19STed Chen 	ocp_data = RTL8153_RMS;
826*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RMS, ocp_data);
827*9dc8ba19STed Chen 
828*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG);
829*9dc8ba19STed Chen 	ocp_data &= ~TEREDO_WAKE_MASK;
830*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_TEREDO_CFG, ocp_data);
831*9dc8ba19STed Chen 
832*9dc8ba19STed Chen 	rtl_rx_vlan_en(tp, false);
833*9dc8ba19STed Chen 
834*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PAL_BDC_CR);
835*9dc8ba19STed Chen 	ocp_data |= ALDPS_PROXY_MODE;
836*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PAL_BDC_CR, ocp_data);
837*9dc8ba19STed Chen 
838*9dc8ba19STed Chen 	ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL);
839*9dc8ba19STed Chen 	ocp_data |= NOW_IS_OOB | DIS_MCU_CLROOB;
840*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
841*9dc8ba19STed Chen 
842*9dc8ba19STed Chen 	rxdy_gated_en(tp, false);
843*9dc8ba19STed Chen 
844*9dc8ba19STed Chen 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR);
845*9dc8ba19STed Chen 	ocp_data |= RCR_APM | RCR_AM | RCR_AB;
846*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data);
847*9dc8ba19STed Chen }
848*9dc8ba19STed Chen 
849*9dc8ba19STed Chen static void r8153_disable_aldps(struct r8152 *tp)
850*9dc8ba19STed Chen {
851*9dc8ba19STed Chen 	u16 data;
852*9dc8ba19STed Chen 
853*9dc8ba19STed Chen 	data = ocp_reg_read(tp, OCP_POWER_CFG);
854*9dc8ba19STed Chen 	data &= ~EN_ALDPS;
855*9dc8ba19STed Chen 	ocp_reg_write(tp, OCP_POWER_CFG, data);
856*9dc8ba19STed Chen 	mdelay(20);
857*9dc8ba19STed Chen }
858*9dc8ba19STed Chen 
859*9dc8ba19STed Chen static void rtl8153_disable(struct r8152 *tp)
860*9dc8ba19STed Chen {
861*9dc8ba19STed Chen 	r8153_disable_aldps(tp);
862*9dc8ba19STed Chen 	rtl_disable(tp);
863*9dc8ba19STed Chen }
864*9dc8ba19STed Chen 
865*9dc8ba19STed Chen static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
866*9dc8ba19STed Chen {
867*9dc8ba19STed Chen 	u16 bmcr, anar, gbcr;
868*9dc8ba19STed Chen 
869*9dc8ba19STed Chen 	anar = r8152_mdio_read(tp, MII_ADVERTISE);
870*9dc8ba19STed Chen 	anar &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
871*9dc8ba19STed Chen 		  ADVERTISE_100HALF | ADVERTISE_100FULL);
872*9dc8ba19STed Chen 	if (tp->supports_gmii) {
873*9dc8ba19STed Chen 		gbcr = r8152_mdio_read(tp, MII_CTRL1000);
874*9dc8ba19STed Chen 		gbcr &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF);
875*9dc8ba19STed Chen 	} else {
876*9dc8ba19STed Chen 		gbcr = 0;
877*9dc8ba19STed Chen 	}
878*9dc8ba19STed Chen 
879*9dc8ba19STed Chen 	if (autoneg == AUTONEG_DISABLE) {
880*9dc8ba19STed Chen 		if (speed == SPEED_10) {
881*9dc8ba19STed Chen 			bmcr = 0;
882*9dc8ba19STed Chen 			anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
883*9dc8ba19STed Chen 		} else if (speed == SPEED_100) {
884*9dc8ba19STed Chen 			bmcr = BMCR_SPEED100;
885*9dc8ba19STed Chen 			anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
886*9dc8ba19STed Chen 		} else if (speed == SPEED_1000 && tp->supports_gmii) {
887*9dc8ba19STed Chen 			bmcr = BMCR_SPEED1000;
888*9dc8ba19STed Chen 			gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
889*9dc8ba19STed Chen 		} else {
890*9dc8ba19STed Chen 			return -EINVAL;
891*9dc8ba19STed Chen 		}
892*9dc8ba19STed Chen 
893*9dc8ba19STed Chen 		if (duplex == DUPLEX_FULL)
894*9dc8ba19STed Chen 			bmcr |= BMCR_FULLDPLX;
895*9dc8ba19STed Chen 	} else {
896*9dc8ba19STed Chen 		if (speed == SPEED_10) {
897*9dc8ba19STed Chen 			if (duplex == DUPLEX_FULL)
898*9dc8ba19STed Chen 				anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
899*9dc8ba19STed Chen 			else
900*9dc8ba19STed Chen 				anar |= ADVERTISE_10HALF;
901*9dc8ba19STed Chen 		} else if (speed == SPEED_100) {
902*9dc8ba19STed Chen 			if (duplex == DUPLEX_FULL) {
903*9dc8ba19STed Chen 				anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
904*9dc8ba19STed Chen 				anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
905*9dc8ba19STed Chen 			} else {
906*9dc8ba19STed Chen 				anar |= ADVERTISE_10HALF;
907*9dc8ba19STed Chen 				anar |= ADVERTISE_100HALF;
908*9dc8ba19STed Chen 			}
909*9dc8ba19STed Chen 		} else if (speed == SPEED_1000 && tp->supports_gmii) {
910*9dc8ba19STed Chen 			if (duplex == DUPLEX_FULL) {
911*9dc8ba19STed Chen 				anar |= ADVERTISE_10HALF | ADVERTISE_10FULL;
912*9dc8ba19STed Chen 				anar |= ADVERTISE_100HALF | ADVERTISE_100FULL;
913*9dc8ba19STed Chen 				gbcr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF;
914*9dc8ba19STed Chen 			} else {
915*9dc8ba19STed Chen 				anar |= ADVERTISE_10HALF;
916*9dc8ba19STed Chen 				anar |= ADVERTISE_100HALF;
917*9dc8ba19STed Chen 				gbcr |= ADVERTISE_1000HALF;
918*9dc8ba19STed Chen 			}
919*9dc8ba19STed Chen 		} else {
920*9dc8ba19STed Chen 			return -EINVAL;
921*9dc8ba19STed Chen 		}
922*9dc8ba19STed Chen 
923*9dc8ba19STed Chen 		bmcr = BMCR_ANENABLE | BMCR_ANRESTART;
924*9dc8ba19STed Chen 	}
925*9dc8ba19STed Chen 
926*9dc8ba19STed Chen 	if (tp->supports_gmii)
927*9dc8ba19STed Chen 		r8152_mdio_write(tp, MII_CTRL1000, gbcr);
928*9dc8ba19STed Chen 
929*9dc8ba19STed Chen 	r8152_mdio_write(tp, MII_ADVERTISE, anar);
930*9dc8ba19STed Chen 	r8152_mdio_write(tp, MII_BMCR, bmcr);
931*9dc8ba19STed Chen 
932*9dc8ba19STed Chen 	return 0;
933*9dc8ba19STed Chen }
934*9dc8ba19STed Chen 
935*9dc8ba19STed Chen static void rtl8152_up(struct r8152 *tp)
936*9dc8ba19STed Chen {
937*9dc8ba19STed Chen 	r8152b_disable_aldps(tp);
938*9dc8ba19STed Chen 	r8152b_exit_oob(tp);
939*9dc8ba19STed Chen 	r8152b_enable_aldps(tp);
940*9dc8ba19STed Chen }
941*9dc8ba19STed Chen 
942*9dc8ba19STed Chen static void rtl8152_down(struct r8152 *tp)
943*9dc8ba19STed Chen {
944*9dc8ba19STed Chen 	r8152_power_cut_en(tp, false);
945*9dc8ba19STed Chen 	r8152b_disable_aldps(tp);
946*9dc8ba19STed Chen 	r8152b_enter_oob(tp);
947*9dc8ba19STed Chen 	r8152b_enable_aldps(tp);
948*9dc8ba19STed Chen }
949*9dc8ba19STed Chen 
950*9dc8ba19STed Chen static void rtl8153_up(struct r8152 *tp)
951*9dc8ba19STed Chen {
952*9dc8ba19STed Chen 	r8153_u1u2en(tp, false);
953*9dc8ba19STed Chen 	r8153_disable_aldps(tp);
954*9dc8ba19STed Chen 	r8153_first_init(tp);
955*9dc8ba19STed Chen 	r8153_u2p3en(tp, false);
956*9dc8ba19STed Chen }
957*9dc8ba19STed Chen 
958*9dc8ba19STed Chen static void rtl8153_down(struct r8152 *tp)
959*9dc8ba19STed Chen {
960*9dc8ba19STed Chen 	r8153_u1u2en(tp, false);
961*9dc8ba19STed Chen 	r8153_u2p3en(tp, false);
962*9dc8ba19STed Chen 	r8153_power_cut_en(tp, false);
963*9dc8ba19STed Chen 	r8153_disable_aldps(tp);
964*9dc8ba19STed Chen 	r8153_enter_oob(tp);
965*9dc8ba19STed Chen }
966*9dc8ba19STed Chen 
967*9dc8ba19STed Chen static void r8152b_get_version(struct r8152 *tp)
968*9dc8ba19STed Chen {
969*9dc8ba19STed Chen 	u32 ocp_data;
970*9dc8ba19STed Chen 	u16 tcr;
971*9dc8ba19STed Chen 	int i;
972*9dc8ba19STed Chen 
973*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_TCR1);
974*9dc8ba19STed Chen 	tcr = (u16)(ocp_data & VERSION_MASK);
975*9dc8ba19STed Chen 
976*9dc8ba19STed Chen 	for (i = 0; i < ARRAY_SIZE(r8152_versions); i++) {
977*9dc8ba19STed Chen 		if (tcr == r8152_versions[i].tcr) {
978*9dc8ba19STed Chen 			/* Found a supported version */
979*9dc8ba19STed Chen 			tp->version = r8152_versions[i].version;
980*9dc8ba19STed Chen 			tp->supports_gmii = r8152_versions[i].gmii;
981*9dc8ba19STed Chen 			break;
982*9dc8ba19STed Chen 		}
983*9dc8ba19STed Chen 	}
984*9dc8ba19STed Chen 
985*9dc8ba19STed Chen 	if (tp->version == RTL_VER_UNKNOWN)
986*9dc8ba19STed Chen 		debug("r8152 Unknown tcr version 0x%04x\n", tcr);
987*9dc8ba19STed Chen }
988*9dc8ba19STed Chen 
989*9dc8ba19STed Chen static void r8152b_enable_fc(struct r8152 *tp)
990*9dc8ba19STed Chen {
991*9dc8ba19STed Chen 	u16 anar;
992*9dc8ba19STed Chen 	anar = r8152_mdio_read(tp, MII_ADVERTISE);
993*9dc8ba19STed Chen 	anar |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
994*9dc8ba19STed Chen 	r8152_mdio_write(tp, MII_ADVERTISE, anar);
995*9dc8ba19STed Chen }
996*9dc8ba19STed Chen 
997*9dc8ba19STed Chen static void rtl_tally_reset(struct r8152 *tp)
998*9dc8ba19STed Chen {
999*9dc8ba19STed Chen 	u32 ocp_data;
1000*9dc8ba19STed Chen 
1001*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY);
1002*9dc8ba19STed Chen 	ocp_data |= TALLY_RESET;
1003*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_RSTTALLY, ocp_data);
1004*9dc8ba19STed Chen }
1005*9dc8ba19STed Chen 
1006*9dc8ba19STed Chen static void r8152b_init(struct r8152 *tp)
1007*9dc8ba19STed Chen {
1008*9dc8ba19STed Chen 	u32 ocp_data;
1009*9dc8ba19STed Chen 
1010*9dc8ba19STed Chen 	r8152b_disable_aldps(tp);
1011*9dc8ba19STed Chen 
1012*9dc8ba19STed Chen 	if (tp->version == RTL_VER_01) {
1013*9dc8ba19STed Chen 		ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);
1014*9dc8ba19STed Chen 		ocp_data &= ~LED_MODE_MASK;
1015*9dc8ba19STed Chen 		ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data);
1016*9dc8ba19STed Chen 	}
1017*9dc8ba19STed Chen 
1018*9dc8ba19STed Chen 	r8152_power_cut_en(tp, false);
1019*9dc8ba19STed Chen 
1020*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR);
1021*9dc8ba19STed Chen 	ocp_data |= TX_10M_IDLE_EN | PFM_PWM_SWITCH;
1022*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_PHY_PWR, ocp_data);
1023*9dc8ba19STed Chen 	ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL);
1024*9dc8ba19STed Chen 	ocp_data &= ~MCU_CLK_RATIO_MASK;
1025*9dc8ba19STed Chen 	ocp_data |= MCU_CLK_RATIO | D3_CLK_GATED_EN;
1026*9dc8ba19STed Chen 	ocp_write_dword(tp, MCU_TYPE_PLA, PLA_MAC_PWR_CTRL, ocp_data);
1027*9dc8ba19STed Chen 	ocp_data = GPHY_STS_MSK | SPEED_DOWN_MSK |
1028*9dc8ba19STed Chen 		   SPDWN_RXDV_MSK | SPDWN_LINKCHG_MSK;
1029*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_GPHY_INTR_IMR, ocp_data);
1030*9dc8ba19STed Chen 
1031*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_TIMER);
1032*9dc8ba19STed Chen 	ocp_data |= BIT(15);
1033*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, USB_USB_TIMER, ocp_data);
1034*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, 0xcbfc, 0x03e8);
1035*9dc8ba19STed Chen 	ocp_data &= ~BIT(15);
1036*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, USB_USB_TIMER, ocp_data);
1037*9dc8ba19STed Chen 
1038*9dc8ba19STed Chen 	r8152b_enable_fc(tp);
1039*9dc8ba19STed Chen 	rtl_tally_reset(tp);
1040*9dc8ba19STed Chen 
1041*9dc8ba19STed Chen 	/* enable rx aggregation */
1042*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_USB_CTRL);
1043*9dc8ba19STed Chen 
1044*9dc8ba19STed Chen 	ocp_data &= ~(RX_AGG_DISABLE | RX_ZERO_EN);
1045*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, USB_USB_CTRL, ocp_data);
1046*9dc8ba19STed Chen }
1047*9dc8ba19STed Chen 
1048*9dc8ba19STed Chen static void r8153_init(struct r8152 *tp)
1049*9dc8ba19STed Chen {
1050*9dc8ba19STed Chen 	int i;
1051*9dc8ba19STed Chen 	u32 ocp_data;
1052*9dc8ba19STed Chen 
1053*9dc8ba19STed Chen 	r8153_disable_aldps(tp);
1054*9dc8ba19STed Chen 	r8153_u1u2en(tp, false);
1055*9dc8ba19STed Chen 
1056*9dc8ba19STed Chen 	r8152_wait_for_bit(tp, 0, MCU_TYPE_PLA, PLA_BOOT_CTRL,
1057*9dc8ba19STed Chen 			   AUTOLOAD_DONE, 1, R8152_WAIT_TIMEOUT);
1058*9dc8ba19STed Chen 
1059*9dc8ba19STed Chen 	for (i = 0; i < R8152_WAIT_TIMEOUT; i++) {
1060*9dc8ba19STed Chen 		ocp_data = ocp_reg_read(tp, OCP_PHY_STATUS) & PHY_STAT_MASK;
1061*9dc8ba19STed Chen 		if (ocp_data == PHY_STAT_LAN_ON || ocp_data == PHY_STAT_PWRDN)
1062*9dc8ba19STed Chen 			break;
1063*9dc8ba19STed Chen 
1064*9dc8ba19STed Chen 		mdelay(1);
1065*9dc8ba19STed Chen 	}
1066*9dc8ba19STed Chen 
1067*9dc8ba19STed Chen 	r8153_u2p3en(tp, false);
1068*9dc8ba19STed Chen 
1069*9dc8ba19STed Chen 	if (tp->version == RTL_VER_04) {
1070*9dc8ba19STed Chen 		ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_SSPHYLINK2);
1071*9dc8ba19STed Chen 		ocp_data &= ~pwd_dn_scale_mask;
1072*9dc8ba19STed Chen 		ocp_data |= pwd_dn_scale(96);
1073*9dc8ba19STed Chen 		ocp_write_word(tp, MCU_TYPE_USB, USB_SSPHYLINK2, ocp_data);
1074*9dc8ba19STed Chen 
1075*9dc8ba19STed Chen 		ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_USB2PHY);
1076*9dc8ba19STed Chen 		ocp_data |= USB2PHY_L1 | USB2PHY_SUSPEND;
1077*9dc8ba19STed Chen 		ocp_write_byte(tp, MCU_TYPE_USB, USB_USB2PHY, ocp_data);
1078*9dc8ba19STed Chen 	} else if (tp->version == RTL_VER_05) {
1079*9dc8ba19STed Chen 		ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_DMY_REG0);
1080*9dc8ba19STed Chen 		ocp_data &= ~ECM_ALDPS;
1081*9dc8ba19STed Chen 		ocp_write_byte(tp, MCU_TYPE_PLA, PLA_DMY_REG0, ocp_data);
1082*9dc8ba19STed Chen 
1083*9dc8ba19STed Chen 		ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1);
1084*9dc8ba19STed Chen 		if (ocp_read_word(tp, MCU_TYPE_USB, USB_BURST_SIZE) == 0)
1085*9dc8ba19STed Chen 			ocp_data &= ~DYNAMIC_BURST;
1086*9dc8ba19STed Chen 		else
1087*9dc8ba19STed Chen 			ocp_data |= DYNAMIC_BURST;
1088*9dc8ba19STed Chen 		ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1, ocp_data);
1089*9dc8ba19STed Chen 	} else if (tp->version == RTL_VER_06) {
1090*9dc8ba19STed Chen 		ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1);
1091*9dc8ba19STed Chen 		if (ocp_read_word(tp, MCU_TYPE_USB, USB_BURST_SIZE) == 0)
1092*9dc8ba19STed Chen 			ocp_data &= ~DYNAMIC_BURST;
1093*9dc8ba19STed Chen 		else
1094*9dc8ba19STed Chen 			ocp_data |= DYNAMIC_BURST;
1095*9dc8ba19STed Chen 		ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY1, ocp_data);
1096*9dc8ba19STed Chen 	}
1097*9dc8ba19STed Chen 
1098*9dc8ba19STed Chen 	ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY2);
1099*9dc8ba19STed Chen 	ocp_data |= EP4_FULL_FC;
1100*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_USB, USB_CSR_DUMMY2, ocp_data);
1101*9dc8ba19STed Chen 
1102*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL);
1103*9dc8ba19STed Chen 	ocp_data &= ~TIMER11_EN;
1104*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, USB_WDT11_CTRL, ocp_data);
1105*9dc8ba19STed Chen 
1106*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE);
1107*9dc8ba19STed Chen 	ocp_data &= ~LED_MODE_MASK;
1108*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE, ocp_data);
1109*9dc8ba19STed Chen 
1110*9dc8ba19STed Chen 	ocp_data = FIFO_EMPTY_1FB | ROK_EXIT_LPM;
1111*9dc8ba19STed Chen 	if (tp->version == RTL_VER_04 && tp->udev->speed != USB_SPEED_SUPER)
1112*9dc8ba19STed Chen 		ocp_data |= LPM_TIMER_500MS;
1113*9dc8ba19STed Chen 	else
1114*9dc8ba19STed Chen 		ocp_data |= LPM_TIMER_500US;
1115*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_USB, USB_LPM_CTRL, ocp_data);
1116*9dc8ba19STed Chen 
1117*9dc8ba19STed Chen 	ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2);
1118*9dc8ba19STed Chen 	ocp_data &= ~SEN_VAL_MASK;
1119*9dc8ba19STed Chen 	ocp_data |= SEN_VAL_NORMAL | SEL_RXIDLE;
1120*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, USB_AFE_CTRL2, ocp_data);
1121*9dc8ba19STed Chen 
1122*9dc8ba19STed Chen 	ocp_write_word(tp, MCU_TYPE_USB, USB_CONNECT_TIMER, 0x0001);
1123*9dc8ba19STed Chen 
1124*9dc8ba19STed Chen 	r8153_power_cut_en(tp, false);
1125*9dc8ba19STed Chen 
1126*9dc8ba19STed Chen 	r8152b_enable_fc(tp);
1127*9dc8ba19STed Chen 	rtl_tally_reset(tp);
1128*9dc8ba19STed Chen }
1129*9dc8ba19STed Chen 
1130*9dc8ba19STed Chen static void rtl8152_unload(struct r8152 *tp)
1131*9dc8ba19STed Chen {
1132*9dc8ba19STed Chen 	if (tp->version != RTL_VER_01)
1133*9dc8ba19STed Chen 		r8152_power_cut_en(tp, true);
1134*9dc8ba19STed Chen }
1135*9dc8ba19STed Chen 
1136*9dc8ba19STed Chen static void rtl8153_unload(struct r8152 *tp)
1137*9dc8ba19STed Chen {
1138*9dc8ba19STed Chen 	r8153_power_cut_en(tp, false);
1139*9dc8ba19STed Chen }
1140*9dc8ba19STed Chen 
1141*9dc8ba19STed Chen static int rtl_ops_init(struct r8152 *tp)
1142*9dc8ba19STed Chen {
1143*9dc8ba19STed Chen 	struct rtl_ops *ops = &tp->rtl_ops;
1144*9dc8ba19STed Chen 	int ret = 0;
1145*9dc8ba19STed Chen 
1146*9dc8ba19STed Chen 	switch (tp->version) {
1147*9dc8ba19STed Chen 	case RTL_VER_01:
1148*9dc8ba19STed Chen 	case RTL_VER_02:
1149*9dc8ba19STed Chen 	case RTL_VER_07:
1150*9dc8ba19STed Chen 		ops->init		= r8152b_init;
1151*9dc8ba19STed Chen 		ops->enable		= rtl8152_enable;
1152*9dc8ba19STed Chen 		ops->disable		= rtl8152_disable;
1153*9dc8ba19STed Chen 		ops->up			= rtl8152_up;
1154*9dc8ba19STed Chen 		ops->down		= rtl8152_down;
1155*9dc8ba19STed Chen 		ops->unload		= rtl8152_unload;
1156*9dc8ba19STed Chen 		break;
1157*9dc8ba19STed Chen 
1158*9dc8ba19STed Chen 	case RTL_VER_03:
1159*9dc8ba19STed Chen 	case RTL_VER_04:
1160*9dc8ba19STed Chen 	case RTL_VER_05:
1161*9dc8ba19STed Chen 	case RTL_VER_06:
1162*9dc8ba19STed Chen 		ops->init		= r8153_init;
1163*9dc8ba19STed Chen 		ops->enable		= rtl8153_enable;
1164*9dc8ba19STed Chen 		ops->disable		= rtl8153_disable;
1165*9dc8ba19STed Chen 		ops->up			= rtl8153_up;
1166*9dc8ba19STed Chen 		ops->down		= rtl8153_down;
1167*9dc8ba19STed Chen 		ops->unload		= rtl8153_unload;
1168*9dc8ba19STed Chen 		break;
1169*9dc8ba19STed Chen 
1170*9dc8ba19STed Chen 	default:
1171*9dc8ba19STed Chen 		ret = -ENODEV;
1172*9dc8ba19STed Chen 		printf("r8152 Unknown Device\n");
1173*9dc8ba19STed Chen 		break;
1174*9dc8ba19STed Chen 	}
1175*9dc8ba19STed Chen 
1176*9dc8ba19STed Chen 	return ret;
1177*9dc8ba19STed Chen }
1178*9dc8ba19STed Chen 
1179*9dc8ba19STed Chen static int r8152_init(struct eth_device *eth, bd_t *bd)
1180*9dc8ba19STed Chen {
1181*9dc8ba19STed Chen 	struct ueth_data *dev = (struct ueth_data *)eth->priv;
1182*9dc8ba19STed Chen 	struct r8152 *tp = (struct r8152 *)dev->dev_priv;
1183*9dc8ba19STed Chen 
1184*9dc8ba19STed Chen 	u8 speed;
1185*9dc8ba19STed Chen 	int timeout = 0;
1186*9dc8ba19STed Chen 	int link_detected;
1187*9dc8ba19STed Chen 
1188*9dc8ba19STed Chen 	debug("** %s()\n", __func__);
1189*9dc8ba19STed Chen 
1190*9dc8ba19STed Chen 	do {
1191*9dc8ba19STed Chen 		speed = rtl8152_get_speed(tp);
1192*9dc8ba19STed Chen 
1193*9dc8ba19STed Chen 		link_detected = speed & LINK_STATUS;
1194*9dc8ba19STed Chen 		if (!link_detected) {
1195*9dc8ba19STed Chen 			if (timeout == 0)
1196*9dc8ba19STed Chen 				printf("Waiting for Ethernet connection... ");
1197*9dc8ba19STed Chen 			mdelay(TIMEOUT_RESOLUTION);
1198*9dc8ba19STed Chen 			timeout += TIMEOUT_RESOLUTION;
1199*9dc8ba19STed Chen 		}
1200*9dc8ba19STed Chen 	} while (!link_detected && timeout < PHY_CONNECT_TIMEOUT);
1201*9dc8ba19STed Chen 	if (link_detected) {
1202*9dc8ba19STed Chen 		tp->rtl_ops.enable(tp);
1203*9dc8ba19STed Chen 
1204*9dc8ba19STed Chen 		if (timeout != 0)
1205*9dc8ba19STed Chen 			printf("done.\n");
1206*9dc8ba19STed Chen 	} else {
1207*9dc8ba19STed Chen 		printf("unable to connect.\n");
1208*9dc8ba19STed Chen 	}
1209*9dc8ba19STed Chen 
1210*9dc8ba19STed Chen 	return 0;
1211*9dc8ba19STed Chen }
1212*9dc8ba19STed Chen 
1213*9dc8ba19STed Chen static int r8152_send(struct eth_device *eth, void *packet, int length)
1214*9dc8ba19STed Chen {
1215*9dc8ba19STed Chen 	struct ueth_data *dev = (struct ueth_data *)eth->priv;
1216*9dc8ba19STed Chen 
1217*9dc8ba19STed Chen 	u32 opts1, opts2 = 0;
1218*9dc8ba19STed Chen 
1219*9dc8ba19STed Chen 	int err;
1220*9dc8ba19STed Chen 
1221*9dc8ba19STed Chen 	int actual_len;
1222*9dc8ba19STed Chen 	unsigned char msg[PKTSIZE + sizeof(struct tx_desc)];
1223*9dc8ba19STed Chen 	struct tx_desc *tx_desc = (struct tx_desc *)msg;
1224*9dc8ba19STed Chen 
1225*9dc8ba19STed Chen 	debug("** %s(), len %d\n", __func__, length);
1226*9dc8ba19STed Chen 
1227*9dc8ba19STed Chen 	opts1 = length | TX_FS | TX_LS;
1228*9dc8ba19STed Chen 
1229*9dc8ba19STed Chen 	tx_desc->opts2 = cpu_to_le32(opts2);
1230*9dc8ba19STed Chen 	tx_desc->opts1 = cpu_to_le32(opts1);
1231*9dc8ba19STed Chen 
1232*9dc8ba19STed Chen 	memcpy(msg + sizeof(struct tx_desc), (void *)packet, length);
1233*9dc8ba19STed Chen 
1234*9dc8ba19STed Chen 	err = usb_bulk_msg(dev->pusb_dev,
1235*9dc8ba19STed Chen 				usb_sndbulkpipe(dev->pusb_dev, dev->ep_out),
1236*9dc8ba19STed Chen 				(void *)msg,
1237*9dc8ba19STed Chen 				length + sizeof(struct tx_desc),
1238*9dc8ba19STed Chen 				&actual_len,
1239*9dc8ba19STed Chen 				USB_BULK_SEND_TIMEOUT);
1240*9dc8ba19STed Chen 	debug("Tx: len = %zu, actual = %u, err = %d\n",
1241*9dc8ba19STed Chen 	      length + sizeof(struct tx_desc), actual_len, err);
1242*9dc8ba19STed Chen 
1243*9dc8ba19STed Chen 	return err;
1244*9dc8ba19STed Chen }
1245*9dc8ba19STed Chen 
1246*9dc8ba19STed Chen static int r8152_recv(struct eth_device *eth)
1247*9dc8ba19STed Chen {
1248*9dc8ba19STed Chen 	struct ueth_data *dev = (struct ueth_data *)eth->priv;
1249*9dc8ba19STed Chen 
1250*9dc8ba19STed Chen 	static unsigned char  recv_buf[RTL8152_AGG_BUF_SZ];
1251*9dc8ba19STed Chen 	unsigned char *pkt_ptr;
1252*9dc8ba19STed Chen 	int err;
1253*9dc8ba19STed Chen 	int actual_len;
1254*9dc8ba19STed Chen 	u16 packet_len;
1255*9dc8ba19STed Chen 
1256*9dc8ba19STed Chen 	u32 bytes_process = 0;
1257*9dc8ba19STed Chen 	struct rx_desc *rx_desc;
1258*9dc8ba19STed Chen 
1259*9dc8ba19STed Chen 	debug("** %s()\n", __func__);
1260*9dc8ba19STed Chen 
1261*9dc8ba19STed Chen 	err = usb_bulk_msg(dev->pusb_dev,
1262*9dc8ba19STed Chen 				usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in),
1263*9dc8ba19STed Chen 				(void *)recv_buf,
1264*9dc8ba19STed Chen 				RTL8152_AGG_BUF_SZ,
1265*9dc8ba19STed Chen 				&actual_len,
1266*9dc8ba19STed Chen 				USB_BULK_RECV_TIMEOUT);
1267*9dc8ba19STed Chen 	debug("Rx: len = %u, actual = %u, err = %d\n", RTL8152_AGG_BUF_SZ,
1268*9dc8ba19STed Chen 	      actual_len, err);
1269*9dc8ba19STed Chen 	if (err != 0) {
1270*9dc8ba19STed Chen 		debug("Rx: failed to receive\n");
1271*9dc8ba19STed Chen 		return -1;
1272*9dc8ba19STed Chen 	}
1273*9dc8ba19STed Chen 	if (actual_len > RTL8152_AGG_BUF_SZ) {
1274*9dc8ba19STed Chen 		debug("Rx: received too many bytes %d\n", actual_len);
1275*9dc8ba19STed Chen 		return -1;
1276*9dc8ba19STed Chen 	}
1277*9dc8ba19STed Chen 
1278*9dc8ba19STed Chen 	while (bytes_process < actual_len) {
1279*9dc8ba19STed Chen 		rx_desc = (struct rx_desc *)(recv_buf + bytes_process);
1280*9dc8ba19STed Chen 		pkt_ptr = recv_buf + sizeof(struct rx_desc) + bytes_process;
1281*9dc8ba19STed Chen 
1282*9dc8ba19STed Chen 		packet_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK;
1283*9dc8ba19STed Chen 		packet_len -= CRC_SIZE;
1284*9dc8ba19STed Chen 
1285*9dc8ba19STed Chen 		net_process_received_packet(pkt_ptr, packet_len);
1286*9dc8ba19STed Chen 
1287*9dc8ba19STed Chen 		bytes_process +=
1288*9dc8ba19STed Chen 			(packet_len + sizeof(struct rx_desc) + CRC_SIZE);
1289*9dc8ba19STed Chen 
1290*9dc8ba19STed Chen 		if (bytes_process % 8)
1291*9dc8ba19STed Chen 			bytes_process = bytes_process + 8 - (bytes_process % 8);
1292*9dc8ba19STed Chen 	}
1293*9dc8ba19STed Chen 
1294*9dc8ba19STed Chen 	return 0;
1295*9dc8ba19STed Chen }
1296*9dc8ba19STed Chen 
1297*9dc8ba19STed Chen static void r8152_halt(struct eth_device *eth)
1298*9dc8ba19STed Chen {
1299*9dc8ba19STed Chen 	struct ueth_data *dev = (struct ueth_data *)eth->priv;
1300*9dc8ba19STed Chen 	struct r8152 *tp = (struct r8152 *)dev->dev_priv;
1301*9dc8ba19STed Chen 
1302*9dc8ba19STed Chen 	debug("** %s()\n", __func__);
1303*9dc8ba19STed Chen 
1304*9dc8ba19STed Chen 	tp->rtl_ops.disable(tp);
1305*9dc8ba19STed Chen }
1306*9dc8ba19STed Chen 
1307*9dc8ba19STed Chen static int r8152_write_hwaddr(struct eth_device *eth)
1308*9dc8ba19STed Chen {
1309*9dc8ba19STed Chen 	struct ueth_data *dev = (struct ueth_data *)eth->priv;
1310*9dc8ba19STed Chen 	struct r8152 *tp = (struct r8152 *)dev->dev_priv;
1311*9dc8ba19STed Chen 
1312*9dc8ba19STed Chen 	unsigned char enetaddr[8] = {0};
1313*9dc8ba19STed Chen 
1314*9dc8ba19STed Chen 	memcpy(enetaddr, eth->enetaddr, ETH_ALEN);
1315*9dc8ba19STed Chen 
1316*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
1317*9dc8ba19STed Chen 	pla_ocp_write(tp, PLA_IDR, BYTE_EN_SIX_BYTES, 8, enetaddr);
1318*9dc8ba19STed Chen 	ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
1319*9dc8ba19STed Chen 
1320*9dc8ba19STed Chen 	debug("MAC %pM\n", eth->enetaddr);
1321*9dc8ba19STed Chen 	return 0;
1322*9dc8ba19STed Chen }
1323*9dc8ba19STed Chen 
1324*9dc8ba19STed Chen void r8152_eth_before_probe(void)
1325*9dc8ba19STed Chen {
1326*9dc8ba19STed Chen 	curr_eth_dev = 0;
1327*9dc8ba19STed Chen }
1328*9dc8ba19STed Chen 
1329*9dc8ba19STed Chen /* Probe to see if a new device is actually an realtek device */
1330*9dc8ba19STed Chen int r8152_eth_probe(struct usb_device *dev, unsigned int ifnum,
1331*9dc8ba19STed Chen 		      struct ueth_data *ss)
1332*9dc8ba19STed Chen {
1333*9dc8ba19STed Chen 	struct usb_interface *iface;
1334*9dc8ba19STed Chen 	struct usb_interface_descriptor *iface_desc;
1335*9dc8ba19STed Chen 	int ep_in_found = 0, ep_out_found = 0;
1336*9dc8ba19STed Chen 	int i;
1337*9dc8ba19STed Chen 
1338*9dc8ba19STed Chen 	struct r8152 *tp;
1339*9dc8ba19STed Chen 
1340*9dc8ba19STed Chen 	/* let's examine the device now */
1341*9dc8ba19STed Chen 	iface = &dev->config.if_desc[ifnum];
1342*9dc8ba19STed Chen 	iface_desc = &dev->config.if_desc[ifnum].desc;
1343*9dc8ba19STed Chen 
1344*9dc8ba19STed Chen 	for (i = 0; i < ARRAY_SIZE(r8152_dongles); i++) {
1345*9dc8ba19STed Chen 		if (dev->descriptor.idVendor == r8152_dongles[i].vendor &&
1346*9dc8ba19STed Chen 		    dev->descriptor.idProduct == r8152_dongles[i].product)
1347*9dc8ba19STed Chen 			/* Found a supported dongle */
1348*9dc8ba19STed Chen 			break;
1349*9dc8ba19STed Chen 	}
1350*9dc8ba19STed Chen 
1351*9dc8ba19STed Chen 	if (i == ARRAY_SIZE(r8152_dongles))
1352*9dc8ba19STed Chen 		return 0;
1353*9dc8ba19STed Chen 
1354*9dc8ba19STed Chen 	memset(ss, 0, sizeof(struct ueth_data));
1355*9dc8ba19STed Chen 
1356*9dc8ba19STed Chen 	/* At this point, we know we've got a live one */
1357*9dc8ba19STed Chen 	debug("\n\nUSB Ethernet device detected: %#04x:%#04x\n",
1358*9dc8ba19STed Chen 	      dev->descriptor.idVendor, dev->descriptor.idProduct);
1359*9dc8ba19STed Chen 
1360*9dc8ba19STed Chen 	/* Initialize the ueth_data structure with some useful info */
1361*9dc8ba19STed Chen 	ss->ifnum = ifnum;
1362*9dc8ba19STed Chen 	ss->pusb_dev = dev;
1363*9dc8ba19STed Chen 	ss->subclass = iface_desc->bInterfaceSubClass;
1364*9dc8ba19STed Chen 	ss->protocol = iface_desc->bInterfaceProtocol;
1365*9dc8ba19STed Chen 
1366*9dc8ba19STed Chen 	/* alloc driver private */
1367*9dc8ba19STed Chen 	ss->dev_priv = calloc(1, sizeof(struct r8152));
1368*9dc8ba19STed Chen 
1369*9dc8ba19STed Chen 	if (!ss->dev_priv)
1370*9dc8ba19STed Chen 		return 0;
1371*9dc8ba19STed Chen 
1372*9dc8ba19STed Chen 	/*
1373*9dc8ba19STed Chen 	 * We are expecting a minimum of 3 endpoints - in, out (bulk), and
1374*9dc8ba19STed Chen 	 * int. We will ignore any others.
1375*9dc8ba19STed Chen 	 */
1376*9dc8ba19STed Chen 	for (i = 0; i < iface_desc->bNumEndpoints; i++) {
1377*9dc8ba19STed Chen 		/* is it an BULK endpoint? */
1378*9dc8ba19STed Chen 		if ((iface->ep_desc[i].bmAttributes &
1379*9dc8ba19STed Chen 		     USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
1380*9dc8ba19STed Chen 			u8 ep_addr = iface->ep_desc[i].bEndpointAddress;
1381*9dc8ba19STed Chen 			if ((ep_addr & USB_DIR_IN) && !ep_in_found) {
1382*9dc8ba19STed Chen 				ss->ep_in = ep_addr &
1383*9dc8ba19STed Chen 					USB_ENDPOINT_NUMBER_MASK;
1384*9dc8ba19STed Chen 				ep_in_found = 1;
1385*9dc8ba19STed Chen 			} else {
1386*9dc8ba19STed Chen 				if (!ep_out_found) {
1387*9dc8ba19STed Chen 					ss->ep_out = ep_addr &
1388*9dc8ba19STed Chen 						USB_ENDPOINT_NUMBER_MASK;
1389*9dc8ba19STed Chen 					ep_out_found = 1;
1390*9dc8ba19STed Chen 				}
1391*9dc8ba19STed Chen 			}
1392*9dc8ba19STed Chen 		}
1393*9dc8ba19STed Chen 
1394*9dc8ba19STed Chen 		/* is it an interrupt endpoint? */
1395*9dc8ba19STed Chen 		if ((iface->ep_desc[i].bmAttributes &
1396*9dc8ba19STed Chen 		    USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
1397*9dc8ba19STed Chen 			ss->ep_int = iface->ep_desc[i].bEndpointAddress &
1398*9dc8ba19STed Chen 				USB_ENDPOINT_NUMBER_MASK;
1399*9dc8ba19STed Chen 			ss->irqinterval = iface->ep_desc[i].bInterval;
1400*9dc8ba19STed Chen 		}
1401*9dc8ba19STed Chen 	}
1402*9dc8ba19STed Chen 
1403*9dc8ba19STed Chen 	debug("Endpoints In %d Out %d Int %d\n",
1404*9dc8ba19STed Chen 	      ss->ep_in, ss->ep_out, ss->ep_int);
1405*9dc8ba19STed Chen 
1406*9dc8ba19STed Chen 	/* Do some basic sanity checks, and bail if we find a problem */
1407*9dc8ba19STed Chen 	if (usb_set_interface(dev, iface_desc->bInterfaceNumber, 0) ||
1408*9dc8ba19STed Chen 	    !ss->ep_in || !ss->ep_out || !ss->ep_int) {
1409*9dc8ba19STed Chen 		debug("Problems with device\n");
1410*9dc8ba19STed Chen 		return 0;
1411*9dc8ba19STed Chen 	}
1412*9dc8ba19STed Chen 
1413*9dc8ba19STed Chen 	dev->privptr = (void *)ss;
1414*9dc8ba19STed Chen 
1415*9dc8ba19STed Chen 	tp = ss->dev_priv;
1416*9dc8ba19STed Chen 	tp->udev = dev;
1417*9dc8ba19STed Chen 	tp->intf = iface;
1418*9dc8ba19STed Chen 
1419*9dc8ba19STed Chen 	r8152b_get_version(tp);
1420*9dc8ba19STed Chen 
1421*9dc8ba19STed Chen 	if (rtl_ops_init(tp))
1422*9dc8ba19STed Chen 		return 0;
1423*9dc8ba19STed Chen 
1424*9dc8ba19STed Chen 	tp->rtl_ops.init(tp);
1425*9dc8ba19STed Chen 	tp->rtl_ops.up(tp);
1426*9dc8ba19STed Chen 
1427*9dc8ba19STed Chen 	rtl8152_set_speed(tp, AUTONEG_ENABLE,
1428*9dc8ba19STed Chen 			  tp->supports_gmii ? SPEED_1000 : SPEED_100,
1429*9dc8ba19STed Chen 			  DUPLEX_FULL);
1430*9dc8ba19STed Chen 
1431*9dc8ba19STed Chen 	return 1;
1432*9dc8ba19STed Chen }
1433*9dc8ba19STed Chen 
1434*9dc8ba19STed Chen int r8152_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
1435*9dc8ba19STed Chen 				struct eth_device *eth)
1436*9dc8ba19STed Chen {
1437*9dc8ba19STed Chen 	if (!eth) {
1438*9dc8ba19STed Chen 		debug("%s: missing parameter.\n", __func__);
1439*9dc8ba19STed Chen 		return 0;
1440*9dc8ba19STed Chen 	}
1441*9dc8ba19STed Chen 
1442*9dc8ba19STed Chen 	sprintf(eth->name, "%s#%d", R8152_BASE_NAME, curr_eth_dev++);
1443*9dc8ba19STed Chen 	eth->init = r8152_init;
1444*9dc8ba19STed Chen 	eth->send = r8152_send;
1445*9dc8ba19STed Chen 	eth->recv = r8152_recv;
1446*9dc8ba19STed Chen 	eth->halt = r8152_halt;
1447*9dc8ba19STed Chen 	eth->write_hwaddr = r8152_write_hwaddr;
1448*9dc8ba19STed Chen 	eth->priv = ss;
1449*9dc8ba19STed Chen 
1450*9dc8ba19STed Chen 	/* Get the MAC address */
1451*9dc8ba19STed Chen 	if (r8152_read_mac(ss->dev_priv, eth->enetaddr) < 0)
1452*9dc8ba19STed Chen 		return 0;
1453*9dc8ba19STed Chen 
1454*9dc8ba19STed Chen 	debug("MAC %pM\n", eth->enetaddr);
1455*9dc8ba19STed Chen 	return 1;
1456*9dc8ba19STed Chen }
1457