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