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