1*8ee443b8SBin Meng /* 2*8ee443b8SBin Meng * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com> 3*8ee443b8SBin Meng * 4*8ee443b8SBin Meng * Intel Platform Controller Hub EG20T (codename Topcliff) GMAC Driver 5*8ee443b8SBin Meng * 6*8ee443b8SBin Meng * SPDX-License-Identifier: GPL-2.0+ 7*8ee443b8SBin Meng */ 8*8ee443b8SBin Meng 9*8ee443b8SBin Meng #include <common.h> 10*8ee443b8SBin Meng #include <errno.h> 11*8ee443b8SBin Meng #include <asm/io.h> 12*8ee443b8SBin Meng #include <pci.h> 13*8ee443b8SBin Meng #include <malloc.h> 14*8ee443b8SBin Meng #include <miiphy.h> 15*8ee443b8SBin Meng #include "pch_gbe.h" 16*8ee443b8SBin Meng 17*8ee443b8SBin Meng #if !defined(CONFIG_PHYLIB) 18*8ee443b8SBin Meng # error "PCH Gigabit Ethernet driver requires PHYLIB - missing CONFIG_PHYLIB" 19*8ee443b8SBin Meng #endif 20*8ee443b8SBin Meng 21*8ee443b8SBin Meng static struct pci_device_id supported[] = { 22*8ee443b8SBin Meng { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_GBE }, 23*8ee443b8SBin Meng { } 24*8ee443b8SBin Meng }; 25*8ee443b8SBin Meng 26*8ee443b8SBin Meng static void pch_gbe_mac_read(struct pch_gbe_regs *mac_regs, u8 *addr) 27*8ee443b8SBin Meng { 28*8ee443b8SBin Meng u32 macid_hi, macid_lo; 29*8ee443b8SBin Meng 30*8ee443b8SBin Meng macid_hi = readl(&mac_regs->mac_adr[0].high); 31*8ee443b8SBin Meng macid_lo = readl(&mac_regs->mac_adr[0].low) & 0xffff; 32*8ee443b8SBin Meng debug("pch_gbe: macid_hi %#x macid_lo %#x\n", macid_hi, macid_lo); 33*8ee443b8SBin Meng 34*8ee443b8SBin Meng addr[0] = (u8)(macid_hi & 0xff); 35*8ee443b8SBin Meng addr[1] = (u8)((macid_hi >> 8) & 0xff); 36*8ee443b8SBin Meng addr[2] = (u8)((macid_hi >> 16) & 0xff); 37*8ee443b8SBin Meng addr[3] = (u8)((macid_hi >> 24) & 0xff); 38*8ee443b8SBin Meng addr[4] = (u8)(macid_lo & 0xff); 39*8ee443b8SBin Meng addr[5] = (u8)((macid_lo >> 8) & 0xff); 40*8ee443b8SBin Meng } 41*8ee443b8SBin Meng 42*8ee443b8SBin Meng static int pch_gbe_mac_write(struct pch_gbe_regs *mac_regs, u8 *addr) 43*8ee443b8SBin Meng { 44*8ee443b8SBin Meng u32 macid_hi, macid_lo; 45*8ee443b8SBin Meng ulong start; 46*8ee443b8SBin Meng 47*8ee443b8SBin Meng macid_hi = addr[0] + (addr[1] << 8) + (addr[2] << 16) + (addr[3] << 24); 48*8ee443b8SBin Meng macid_lo = addr[4] + (addr[5] << 8); 49*8ee443b8SBin Meng 50*8ee443b8SBin Meng writel(macid_hi, &mac_regs->mac_adr[0].high); 51*8ee443b8SBin Meng writel(macid_lo, &mac_regs->mac_adr[0].low); 52*8ee443b8SBin Meng writel(0xfffe, &mac_regs->addr_mask); 53*8ee443b8SBin Meng 54*8ee443b8SBin Meng start = get_timer(0); 55*8ee443b8SBin Meng while (get_timer(start) < PCH_GBE_TIMEOUT) { 56*8ee443b8SBin Meng if (!(readl(&mac_regs->addr_mask) & PCH_GBE_BUSY)) 57*8ee443b8SBin Meng return 0; 58*8ee443b8SBin Meng 59*8ee443b8SBin Meng udelay(10); 60*8ee443b8SBin Meng } 61*8ee443b8SBin Meng 62*8ee443b8SBin Meng return -ETIME; 63*8ee443b8SBin Meng } 64*8ee443b8SBin Meng 65*8ee443b8SBin Meng static int pch_gbe_reset(struct eth_device *dev) 66*8ee443b8SBin Meng { 67*8ee443b8SBin Meng struct pch_gbe_priv *priv = dev->priv; 68*8ee443b8SBin Meng struct pch_gbe_regs *mac_regs = priv->mac_regs; 69*8ee443b8SBin Meng ulong start; 70*8ee443b8SBin Meng 71*8ee443b8SBin Meng priv->rx_idx = 0; 72*8ee443b8SBin Meng priv->tx_idx = 0; 73*8ee443b8SBin Meng 74*8ee443b8SBin Meng writel(PCH_GBE_ALL_RST, &mac_regs->reset); 75*8ee443b8SBin Meng 76*8ee443b8SBin Meng /* 77*8ee443b8SBin Meng * Configure the MAC to RGMII mode after reset 78*8ee443b8SBin Meng * 79*8ee443b8SBin Meng * For some unknown reason, we must do the configuration here right 80*8ee443b8SBin Meng * after resetting the whole MAC, otherwise the reset bit in the RESET 81*8ee443b8SBin Meng * register will never be cleared by the hardware. And there is another 82*8ee443b8SBin Meng * way of having the same magic, that is to configure the MODE register 83*8ee443b8SBin Meng * to have the MAC work in MII/GMII mode, which is how current Linux 84*8ee443b8SBin Meng * pch_gbe driver does. Since anyway we need program the MAC to RGMII 85*8ee443b8SBin Meng * mode in the driver, we just do it here. 86*8ee443b8SBin Meng * 87*8ee443b8SBin Meng * Note: this behavior is not documented in the hardware manual. 88*8ee443b8SBin Meng */ 89*8ee443b8SBin Meng writel(PCH_GBE_RGMII_MODE_RGMII | PCH_GBE_CHIP_TYPE_INTERNAL, 90*8ee443b8SBin Meng &mac_regs->rgmii_ctrl); 91*8ee443b8SBin Meng 92*8ee443b8SBin Meng start = get_timer(0); 93*8ee443b8SBin Meng while (get_timer(start) < PCH_GBE_TIMEOUT) { 94*8ee443b8SBin Meng if (!(readl(&mac_regs->reset) & PCH_GBE_ALL_RST)) { 95*8ee443b8SBin Meng /* 96*8ee443b8SBin Meng * Soft reset clears hardware MAC address registers, 97*8ee443b8SBin Meng * so we have to reload MAC address here in order to 98*8ee443b8SBin Meng * make linux pch_gbe driver happy. 99*8ee443b8SBin Meng */ 100*8ee443b8SBin Meng return pch_gbe_mac_write(mac_regs, dev->enetaddr); 101*8ee443b8SBin Meng } 102*8ee443b8SBin Meng 103*8ee443b8SBin Meng udelay(10); 104*8ee443b8SBin Meng } 105*8ee443b8SBin Meng 106*8ee443b8SBin Meng debug("pch_gbe: reset timeout\n"); 107*8ee443b8SBin Meng return -ETIME; 108*8ee443b8SBin Meng } 109*8ee443b8SBin Meng 110*8ee443b8SBin Meng static void pch_gbe_rx_descs_init(struct eth_device *dev) 111*8ee443b8SBin Meng { 112*8ee443b8SBin Meng struct pch_gbe_priv *priv = dev->priv; 113*8ee443b8SBin Meng struct pch_gbe_regs *mac_regs = priv->mac_regs; 114*8ee443b8SBin Meng struct pch_gbe_rx_desc *rx_desc = &priv->rx_desc[0]; 115*8ee443b8SBin Meng int i; 116*8ee443b8SBin Meng 117*8ee443b8SBin Meng memset(rx_desc, 0, sizeof(struct pch_gbe_rx_desc) * PCH_GBE_DESC_NUM); 118*8ee443b8SBin Meng for (i = 0; i < PCH_GBE_DESC_NUM; i++) 119*8ee443b8SBin Meng rx_desc->buffer_addr = pci_phys_to_mem(priv->bdf, 120*8ee443b8SBin Meng (u32)(priv->rx_buff[i])); 121*8ee443b8SBin Meng 122*8ee443b8SBin Meng writel(pci_phys_to_mem(priv->bdf, (u32)rx_desc), 123*8ee443b8SBin Meng &mac_regs->rx_dsc_base); 124*8ee443b8SBin Meng writel(sizeof(struct pch_gbe_rx_desc) * (PCH_GBE_DESC_NUM - 1), 125*8ee443b8SBin Meng &mac_regs->rx_dsc_size); 126*8ee443b8SBin Meng 127*8ee443b8SBin Meng writel(pci_phys_to_mem(priv->bdf, (u32)(rx_desc + 1)), 128*8ee443b8SBin Meng &mac_regs->rx_dsc_sw_p); 129*8ee443b8SBin Meng } 130*8ee443b8SBin Meng 131*8ee443b8SBin Meng static void pch_gbe_tx_descs_init(struct eth_device *dev) 132*8ee443b8SBin Meng { 133*8ee443b8SBin Meng struct pch_gbe_priv *priv = dev->priv; 134*8ee443b8SBin Meng struct pch_gbe_regs *mac_regs = priv->mac_regs; 135*8ee443b8SBin Meng struct pch_gbe_tx_desc *tx_desc = &priv->tx_desc[0]; 136*8ee443b8SBin Meng 137*8ee443b8SBin Meng memset(tx_desc, 0, sizeof(struct pch_gbe_tx_desc) * PCH_GBE_DESC_NUM); 138*8ee443b8SBin Meng 139*8ee443b8SBin Meng writel(pci_phys_to_mem(priv->bdf, (u32)tx_desc), 140*8ee443b8SBin Meng &mac_regs->tx_dsc_base); 141*8ee443b8SBin Meng writel(sizeof(struct pch_gbe_tx_desc) * (PCH_GBE_DESC_NUM - 1), 142*8ee443b8SBin Meng &mac_regs->tx_dsc_size); 143*8ee443b8SBin Meng writel(pci_phys_to_mem(priv->bdf, (u32)(tx_desc + 1)), 144*8ee443b8SBin Meng &mac_regs->tx_dsc_sw_p); 145*8ee443b8SBin Meng } 146*8ee443b8SBin Meng 147*8ee443b8SBin Meng static void pch_gbe_adjust_link(struct pch_gbe_regs *mac_regs, 148*8ee443b8SBin Meng struct phy_device *phydev) 149*8ee443b8SBin Meng { 150*8ee443b8SBin Meng if (!phydev->link) { 151*8ee443b8SBin Meng printf("%s: No link.\n", phydev->dev->name); 152*8ee443b8SBin Meng return; 153*8ee443b8SBin Meng } 154*8ee443b8SBin Meng 155*8ee443b8SBin Meng clrbits_le32(&mac_regs->rgmii_ctrl, 156*8ee443b8SBin Meng PCH_GBE_RGMII_RATE_2_5M | PCH_GBE_CRS_SEL); 157*8ee443b8SBin Meng clrbits_le32(&mac_regs->mode, 158*8ee443b8SBin Meng PCH_GBE_MODE_GMII_ETHER | PCH_GBE_MODE_FULL_DUPLEX); 159*8ee443b8SBin Meng 160*8ee443b8SBin Meng switch (phydev->speed) { 161*8ee443b8SBin Meng case 1000: 162*8ee443b8SBin Meng setbits_le32(&mac_regs->rgmii_ctrl, PCH_GBE_RGMII_RATE_125M); 163*8ee443b8SBin Meng setbits_le32(&mac_regs->mode, PCH_GBE_MODE_GMII_ETHER); 164*8ee443b8SBin Meng break; 165*8ee443b8SBin Meng case 100: 166*8ee443b8SBin Meng setbits_le32(&mac_regs->rgmii_ctrl, PCH_GBE_RGMII_RATE_25M); 167*8ee443b8SBin Meng setbits_le32(&mac_regs->mode, PCH_GBE_MODE_MII_ETHER); 168*8ee443b8SBin Meng break; 169*8ee443b8SBin Meng case 10: 170*8ee443b8SBin Meng setbits_le32(&mac_regs->rgmii_ctrl, PCH_GBE_RGMII_RATE_2_5M); 171*8ee443b8SBin Meng setbits_le32(&mac_regs->mode, PCH_GBE_MODE_MII_ETHER); 172*8ee443b8SBin Meng break; 173*8ee443b8SBin Meng } 174*8ee443b8SBin Meng 175*8ee443b8SBin Meng if (phydev->duplex) { 176*8ee443b8SBin Meng setbits_le32(&mac_regs->rgmii_ctrl, PCH_GBE_CRS_SEL); 177*8ee443b8SBin Meng setbits_le32(&mac_regs->mode, PCH_GBE_MODE_FULL_DUPLEX); 178*8ee443b8SBin Meng } 179*8ee443b8SBin Meng 180*8ee443b8SBin Meng printf("Speed: %d, %s duplex\n", phydev->speed, 181*8ee443b8SBin Meng (phydev->duplex) ? "full" : "half"); 182*8ee443b8SBin Meng 183*8ee443b8SBin Meng return; 184*8ee443b8SBin Meng } 185*8ee443b8SBin Meng 186*8ee443b8SBin Meng static int pch_gbe_init(struct eth_device *dev, bd_t *bis) 187*8ee443b8SBin Meng { 188*8ee443b8SBin Meng struct pch_gbe_priv *priv = dev->priv; 189*8ee443b8SBin Meng struct pch_gbe_regs *mac_regs = priv->mac_regs; 190*8ee443b8SBin Meng 191*8ee443b8SBin Meng if (pch_gbe_reset(dev)) 192*8ee443b8SBin Meng return -1; 193*8ee443b8SBin Meng 194*8ee443b8SBin Meng pch_gbe_rx_descs_init(dev); 195*8ee443b8SBin Meng pch_gbe_tx_descs_init(dev); 196*8ee443b8SBin Meng 197*8ee443b8SBin Meng /* Enable frame bursting */ 198*8ee443b8SBin Meng writel(PCH_GBE_MODE_FR_BST, &mac_regs->mode); 199*8ee443b8SBin Meng /* Disable TCP/IP accelerator */ 200*8ee443b8SBin Meng writel(PCH_GBE_RX_TCPIPACC_OFF, &mac_regs->tcpip_acc); 201*8ee443b8SBin Meng /* Disable RX flow control */ 202*8ee443b8SBin Meng writel(0, &mac_regs->rx_fctrl); 203*8ee443b8SBin Meng /* Configure RX/TX mode */ 204*8ee443b8SBin Meng writel(PCH_GBE_RH_ALM_EMP_16 | PCH_GBE_RH_ALM_FULL_16 | 205*8ee443b8SBin Meng PCH_GBE_RH_RD_TRG_32, &mac_regs->rx_mode); 206*8ee443b8SBin Meng writel(PCH_GBE_TM_TH_TX_STRT_32 | PCH_GBE_TM_TH_ALM_EMP_16 | 207*8ee443b8SBin Meng PCH_GBE_TM_TH_ALM_FULL_32 | PCH_GBE_TM_ST_AND_FD | 208*8ee443b8SBin Meng PCH_GBE_TM_SHORT_PKT, &mac_regs->tx_mode); 209*8ee443b8SBin Meng 210*8ee443b8SBin Meng /* Start up the PHY */ 211*8ee443b8SBin Meng if (phy_startup(priv->phydev)) { 212*8ee443b8SBin Meng printf("Could not initialize PHY %s\n", 213*8ee443b8SBin Meng priv->phydev->dev->name); 214*8ee443b8SBin Meng return -1; 215*8ee443b8SBin Meng } 216*8ee443b8SBin Meng 217*8ee443b8SBin Meng pch_gbe_adjust_link(mac_regs, priv->phydev); 218*8ee443b8SBin Meng 219*8ee443b8SBin Meng if (!priv->phydev->link) 220*8ee443b8SBin Meng return -1; 221*8ee443b8SBin Meng 222*8ee443b8SBin Meng /* Enable TX & RX */ 223*8ee443b8SBin Meng writel(PCH_GBE_RX_DMA_EN | PCH_GBE_TX_DMA_EN, &mac_regs->dma_ctrl); 224*8ee443b8SBin Meng writel(PCH_GBE_MRE_MAC_RX_EN, &mac_regs->mac_rx_en); 225*8ee443b8SBin Meng 226*8ee443b8SBin Meng return 0; 227*8ee443b8SBin Meng } 228*8ee443b8SBin Meng 229*8ee443b8SBin Meng static void pch_gbe_halt(struct eth_device *dev) 230*8ee443b8SBin Meng { 231*8ee443b8SBin Meng struct pch_gbe_priv *priv = dev->priv; 232*8ee443b8SBin Meng 233*8ee443b8SBin Meng pch_gbe_reset(dev); 234*8ee443b8SBin Meng 235*8ee443b8SBin Meng phy_shutdown(priv->phydev); 236*8ee443b8SBin Meng } 237*8ee443b8SBin Meng 238*8ee443b8SBin Meng static int pch_gbe_send(struct eth_device *dev, void *packet, int length) 239*8ee443b8SBin Meng { 240*8ee443b8SBin Meng struct pch_gbe_priv *priv = dev->priv; 241*8ee443b8SBin Meng struct pch_gbe_regs *mac_regs = priv->mac_regs; 242*8ee443b8SBin Meng struct pch_gbe_tx_desc *tx_head, *tx_desc; 243*8ee443b8SBin Meng u16 frame_ctrl = 0; 244*8ee443b8SBin Meng u32 int_st; 245*8ee443b8SBin Meng ulong start; 246*8ee443b8SBin Meng 247*8ee443b8SBin Meng tx_head = &priv->tx_desc[0]; 248*8ee443b8SBin Meng tx_desc = &priv->tx_desc[priv->tx_idx]; 249*8ee443b8SBin Meng 250*8ee443b8SBin Meng if (length < 64) 251*8ee443b8SBin Meng frame_ctrl |= PCH_GBE_TXD_CTRL_APAD; 252*8ee443b8SBin Meng 253*8ee443b8SBin Meng tx_desc->buffer_addr = pci_phys_to_mem(priv->bdf, (u32)packet); 254*8ee443b8SBin Meng tx_desc->length = length; 255*8ee443b8SBin Meng tx_desc->tx_words_eob = length + 3; 256*8ee443b8SBin Meng tx_desc->tx_frame_ctrl = frame_ctrl; 257*8ee443b8SBin Meng tx_desc->dma_status = 0; 258*8ee443b8SBin Meng tx_desc->gbec_status = 0; 259*8ee443b8SBin Meng 260*8ee443b8SBin Meng /* Test the wrap-around condition */ 261*8ee443b8SBin Meng if (++priv->tx_idx >= PCH_GBE_DESC_NUM) 262*8ee443b8SBin Meng priv->tx_idx = 0; 263*8ee443b8SBin Meng 264*8ee443b8SBin Meng writel(pci_phys_to_mem(priv->bdf, (u32)(tx_head + priv->tx_idx)), 265*8ee443b8SBin Meng &mac_regs->tx_dsc_sw_p); 266*8ee443b8SBin Meng 267*8ee443b8SBin Meng start = get_timer(0); 268*8ee443b8SBin Meng while (get_timer(start) < PCH_GBE_TIMEOUT) { 269*8ee443b8SBin Meng int_st = readl(&mac_regs->int_st); 270*8ee443b8SBin Meng if (int_st & PCH_GBE_INT_TX_CMPLT) 271*8ee443b8SBin Meng return 0; 272*8ee443b8SBin Meng 273*8ee443b8SBin Meng udelay(10); 274*8ee443b8SBin Meng } 275*8ee443b8SBin Meng 276*8ee443b8SBin Meng debug("pch_gbe: sent failed\n"); 277*8ee443b8SBin Meng return -ETIME; 278*8ee443b8SBin Meng } 279*8ee443b8SBin Meng 280*8ee443b8SBin Meng static int pch_gbe_recv(struct eth_device *dev) 281*8ee443b8SBin Meng { 282*8ee443b8SBin Meng struct pch_gbe_priv *priv = dev->priv; 283*8ee443b8SBin Meng struct pch_gbe_regs *mac_regs = priv->mac_regs; 284*8ee443b8SBin Meng struct pch_gbe_rx_desc *rx_head, *rx_desc; 285*8ee443b8SBin Meng u32 hw_desc, buffer_addr, length; 286*8ee443b8SBin Meng int rx_swp; 287*8ee443b8SBin Meng 288*8ee443b8SBin Meng rx_head = &priv->rx_desc[0]; 289*8ee443b8SBin Meng rx_desc = &priv->rx_desc[priv->rx_idx]; 290*8ee443b8SBin Meng 291*8ee443b8SBin Meng readl(&mac_regs->int_st); 292*8ee443b8SBin Meng hw_desc = readl(&mac_regs->rx_dsc_hw_p_hld); 293*8ee443b8SBin Meng 294*8ee443b8SBin Meng /* Just return if not receiving any packet */ 295*8ee443b8SBin Meng if ((u32)rx_desc == hw_desc) 296*8ee443b8SBin Meng return 0; 297*8ee443b8SBin Meng 298*8ee443b8SBin Meng buffer_addr = pci_mem_to_phys(priv->bdf, rx_desc->buffer_addr); 299*8ee443b8SBin Meng length = rx_desc->rx_words_eob - 3 - ETH_FCS_LEN; 300*8ee443b8SBin Meng NetReceive((uchar *)buffer_addr, length); 301*8ee443b8SBin Meng 302*8ee443b8SBin Meng /* Test the wrap-around condition */ 303*8ee443b8SBin Meng if (++priv->rx_idx >= PCH_GBE_DESC_NUM) 304*8ee443b8SBin Meng priv->rx_idx = 0; 305*8ee443b8SBin Meng rx_swp = priv->rx_idx; 306*8ee443b8SBin Meng if (++rx_swp >= PCH_GBE_DESC_NUM) 307*8ee443b8SBin Meng rx_swp = 0; 308*8ee443b8SBin Meng 309*8ee443b8SBin Meng writel(pci_phys_to_mem(priv->bdf, (u32)(rx_head + rx_swp)), 310*8ee443b8SBin Meng &mac_regs->rx_dsc_sw_p); 311*8ee443b8SBin Meng 312*8ee443b8SBin Meng return length; 313*8ee443b8SBin Meng } 314*8ee443b8SBin Meng 315*8ee443b8SBin Meng static int pch_gbe_mdio_ready(struct pch_gbe_regs *mac_regs) 316*8ee443b8SBin Meng { 317*8ee443b8SBin Meng ulong start = get_timer(0); 318*8ee443b8SBin Meng 319*8ee443b8SBin Meng while (get_timer(start) < PCH_GBE_TIMEOUT) { 320*8ee443b8SBin Meng if (readl(&mac_regs->miim) & PCH_GBE_MIIM_OPER_READY) 321*8ee443b8SBin Meng return 0; 322*8ee443b8SBin Meng 323*8ee443b8SBin Meng udelay(10); 324*8ee443b8SBin Meng } 325*8ee443b8SBin Meng 326*8ee443b8SBin Meng return -ETIME; 327*8ee443b8SBin Meng } 328*8ee443b8SBin Meng 329*8ee443b8SBin Meng static int pch_gbe_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) 330*8ee443b8SBin Meng { 331*8ee443b8SBin Meng struct pch_gbe_regs *mac_regs = bus->priv; 332*8ee443b8SBin Meng u32 miim; 333*8ee443b8SBin Meng 334*8ee443b8SBin Meng if (pch_gbe_mdio_ready(mac_regs)) 335*8ee443b8SBin Meng return -ETIME; 336*8ee443b8SBin Meng 337*8ee443b8SBin Meng miim = (addr << PCH_GBE_MIIM_PHY_ADDR_SHIFT) | 338*8ee443b8SBin Meng (reg << PCH_GBE_MIIM_REG_ADDR_SHIFT) | 339*8ee443b8SBin Meng PCH_GBE_MIIM_OPER_READ; 340*8ee443b8SBin Meng writel(miim, &mac_regs->miim); 341*8ee443b8SBin Meng 342*8ee443b8SBin Meng if (pch_gbe_mdio_ready(mac_regs)) 343*8ee443b8SBin Meng return -ETIME; 344*8ee443b8SBin Meng 345*8ee443b8SBin Meng return readl(&mac_regs->miim) & 0xffff; 346*8ee443b8SBin Meng } 347*8ee443b8SBin Meng 348*8ee443b8SBin Meng static int pch_gbe_mdio_write(struct mii_dev *bus, int addr, int devad, 349*8ee443b8SBin Meng int reg, u16 val) 350*8ee443b8SBin Meng { 351*8ee443b8SBin Meng struct pch_gbe_regs *mac_regs = bus->priv; 352*8ee443b8SBin Meng u32 miim; 353*8ee443b8SBin Meng 354*8ee443b8SBin Meng if (pch_gbe_mdio_ready(mac_regs)) 355*8ee443b8SBin Meng return -ETIME; 356*8ee443b8SBin Meng 357*8ee443b8SBin Meng miim = (addr << PCH_GBE_MIIM_PHY_ADDR_SHIFT) | 358*8ee443b8SBin Meng (reg << PCH_GBE_MIIM_REG_ADDR_SHIFT) | 359*8ee443b8SBin Meng PCH_GBE_MIIM_OPER_WRITE | val; 360*8ee443b8SBin Meng writel(miim, &mac_regs->miim); 361*8ee443b8SBin Meng 362*8ee443b8SBin Meng if (pch_gbe_mdio_ready(mac_regs)) 363*8ee443b8SBin Meng return -ETIME; 364*8ee443b8SBin Meng else 365*8ee443b8SBin Meng return 0; 366*8ee443b8SBin Meng } 367*8ee443b8SBin Meng 368*8ee443b8SBin Meng static int pch_gbe_mdio_init(char *name, struct pch_gbe_regs *mac_regs) 369*8ee443b8SBin Meng { 370*8ee443b8SBin Meng struct mii_dev *bus; 371*8ee443b8SBin Meng 372*8ee443b8SBin Meng bus = mdio_alloc(); 373*8ee443b8SBin Meng if (!bus) { 374*8ee443b8SBin Meng debug("pch_gbe: failed to allocate MDIO bus\n"); 375*8ee443b8SBin Meng return -ENOMEM; 376*8ee443b8SBin Meng } 377*8ee443b8SBin Meng 378*8ee443b8SBin Meng bus->read = pch_gbe_mdio_read; 379*8ee443b8SBin Meng bus->write = pch_gbe_mdio_write; 380*8ee443b8SBin Meng sprintf(bus->name, name); 381*8ee443b8SBin Meng 382*8ee443b8SBin Meng bus->priv = (void *)mac_regs; 383*8ee443b8SBin Meng 384*8ee443b8SBin Meng return mdio_register(bus); 385*8ee443b8SBin Meng } 386*8ee443b8SBin Meng 387*8ee443b8SBin Meng static int pch_gbe_phy_init(struct eth_device *dev) 388*8ee443b8SBin Meng { 389*8ee443b8SBin Meng struct pch_gbe_priv *priv = dev->priv; 390*8ee443b8SBin Meng struct phy_device *phydev; 391*8ee443b8SBin Meng int mask = 0xffffffff; 392*8ee443b8SBin Meng 393*8ee443b8SBin Meng phydev = phy_find_by_mask(priv->bus, mask, priv->interface); 394*8ee443b8SBin Meng if (!phydev) { 395*8ee443b8SBin Meng printf("pch_gbe: cannot find the phy\n"); 396*8ee443b8SBin Meng return -1; 397*8ee443b8SBin Meng } 398*8ee443b8SBin Meng 399*8ee443b8SBin Meng phy_connect_dev(phydev, dev); 400*8ee443b8SBin Meng 401*8ee443b8SBin Meng phydev->supported &= PHY_GBIT_FEATURES; 402*8ee443b8SBin Meng phydev->advertising = phydev->supported; 403*8ee443b8SBin Meng 404*8ee443b8SBin Meng priv->phydev = phydev; 405*8ee443b8SBin Meng phy_config(phydev); 406*8ee443b8SBin Meng 407*8ee443b8SBin Meng return 1; 408*8ee443b8SBin Meng } 409*8ee443b8SBin Meng 410*8ee443b8SBin Meng int pch_gbe_register(bd_t *bis) 411*8ee443b8SBin Meng { 412*8ee443b8SBin Meng struct eth_device *dev; 413*8ee443b8SBin Meng struct pch_gbe_priv *priv; 414*8ee443b8SBin Meng pci_dev_t devno; 415*8ee443b8SBin Meng u32 iobase; 416*8ee443b8SBin Meng 417*8ee443b8SBin Meng devno = pci_find_devices(supported, 0); 418*8ee443b8SBin Meng if (devno == -1) 419*8ee443b8SBin Meng return -ENODEV; 420*8ee443b8SBin Meng 421*8ee443b8SBin Meng dev = (struct eth_device *)malloc(sizeof(*dev)); 422*8ee443b8SBin Meng if (!dev) 423*8ee443b8SBin Meng return -ENOMEM; 424*8ee443b8SBin Meng memset(dev, 0, sizeof(*dev)); 425*8ee443b8SBin Meng 426*8ee443b8SBin Meng /* 427*8ee443b8SBin Meng * The priv structure contains the descriptors and frame buffers which 428*8ee443b8SBin Meng * need a strict buswidth alignment (64 bytes) 429*8ee443b8SBin Meng */ 430*8ee443b8SBin Meng priv = (struct pch_gbe_priv *)memalign(PCH_GBE_ALIGN_SIZE, 431*8ee443b8SBin Meng sizeof(*priv)); 432*8ee443b8SBin Meng if (!priv) { 433*8ee443b8SBin Meng free(dev); 434*8ee443b8SBin Meng return -ENOMEM; 435*8ee443b8SBin Meng } 436*8ee443b8SBin Meng memset(priv, 0, sizeof(*priv)); 437*8ee443b8SBin Meng 438*8ee443b8SBin Meng dev->priv = priv; 439*8ee443b8SBin Meng priv->dev = dev; 440*8ee443b8SBin Meng priv->bdf = devno; 441*8ee443b8SBin Meng 442*8ee443b8SBin Meng pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase); 443*8ee443b8SBin Meng iobase &= PCI_BASE_ADDRESS_MEM_MASK; 444*8ee443b8SBin Meng iobase = pci_mem_to_phys(devno, iobase); 445*8ee443b8SBin Meng 446*8ee443b8SBin Meng dev->iobase = iobase; 447*8ee443b8SBin Meng priv->mac_regs = (struct pch_gbe_regs *)iobase; 448*8ee443b8SBin Meng 449*8ee443b8SBin Meng sprintf(dev->name, "pch_gbe.%x", iobase); 450*8ee443b8SBin Meng 451*8ee443b8SBin Meng /* Read MAC address from SROM and initialize dev->enetaddr with it */ 452*8ee443b8SBin Meng pch_gbe_mac_read(priv->mac_regs, dev->enetaddr); 453*8ee443b8SBin Meng 454*8ee443b8SBin Meng dev->init = pch_gbe_init; 455*8ee443b8SBin Meng dev->halt = pch_gbe_halt; 456*8ee443b8SBin Meng dev->send = pch_gbe_send; 457*8ee443b8SBin Meng dev->recv = pch_gbe_recv; 458*8ee443b8SBin Meng 459*8ee443b8SBin Meng eth_register(dev); 460*8ee443b8SBin Meng 461*8ee443b8SBin Meng priv->interface = PHY_INTERFACE_MODE_RGMII; 462*8ee443b8SBin Meng pch_gbe_mdio_init(dev->name, priv->mac_regs); 463*8ee443b8SBin Meng priv->bus = miiphy_get_dev_by_name(dev->name); 464*8ee443b8SBin Meng 465*8ee443b8SBin Meng return pch_gbe_phy_init(dev); 466*8ee443b8SBin Meng } 467