1*799e125cSJiandong Zheng /* 2*799e125cSJiandong Zheng * Copyright 2014 Broadcom Corporation. 3*799e125cSJiandong Zheng * 4*799e125cSJiandong Zheng * SPDX-License-Identifier: GPL-2.0+ 5*799e125cSJiandong Zheng */ 6*799e125cSJiandong Zheng 7*799e125cSJiandong Zheng #ifdef BCM_GMAC_DEBUG 8*799e125cSJiandong Zheng #ifndef DEBUG 9*799e125cSJiandong Zheng #define DEBUG 10*799e125cSJiandong Zheng #endif 11*799e125cSJiandong Zheng #endif 12*799e125cSJiandong Zheng 13*799e125cSJiandong Zheng #include <config.h> 14*799e125cSJiandong Zheng #include <common.h> 15*799e125cSJiandong Zheng #include <malloc.h> 16*799e125cSJiandong Zheng #include <net.h> 17*799e125cSJiandong Zheng #include <asm/io.h> 18*799e125cSJiandong Zheng #include <phy.h> 19*799e125cSJiandong Zheng 20*799e125cSJiandong Zheng #include "bcm-sf2-eth.h" 21*799e125cSJiandong Zheng #include "bcm-sf2-eth-gmac.h" 22*799e125cSJiandong Zheng 23*799e125cSJiandong Zheng #define SPINWAIT(exp, us) { \ 24*799e125cSJiandong Zheng uint countdown = (us) + 9; \ 25*799e125cSJiandong Zheng while ((exp) && (countdown >= 10)) {\ 26*799e125cSJiandong Zheng udelay(10); \ 27*799e125cSJiandong Zheng countdown -= 10; \ 28*799e125cSJiandong Zheng } \ 29*799e125cSJiandong Zheng } 30*799e125cSJiandong Zheng 31*799e125cSJiandong Zheng static int gmac_disable_dma(struct eth_dma *dma, int dir); 32*799e125cSJiandong Zheng static int gmac_enable_dma(struct eth_dma *dma, int dir); 33*799e125cSJiandong Zheng 34*799e125cSJiandong Zheng /* DMA Descriptor */ 35*799e125cSJiandong Zheng typedef struct { 36*799e125cSJiandong Zheng /* misc control bits */ 37*799e125cSJiandong Zheng uint32_t ctrl1; 38*799e125cSJiandong Zheng /* buffer count and address extension */ 39*799e125cSJiandong Zheng uint32_t ctrl2; 40*799e125cSJiandong Zheng /* memory address of the date buffer, bits 31:0 */ 41*799e125cSJiandong Zheng uint32_t addrlow; 42*799e125cSJiandong Zheng /* memory address of the date buffer, bits 63:32 */ 43*799e125cSJiandong Zheng uint32_t addrhigh; 44*799e125cSJiandong Zheng } dma64dd_t; 45*799e125cSJiandong Zheng 46*799e125cSJiandong Zheng uint32_t g_dmactrlflags; 47*799e125cSJiandong Zheng 48*799e125cSJiandong Zheng static uint32_t dma_ctrlflags(uint32_t mask, uint32_t flags) 49*799e125cSJiandong Zheng { 50*799e125cSJiandong Zheng debug("%s enter\n", __func__); 51*799e125cSJiandong Zheng 52*799e125cSJiandong Zheng g_dmactrlflags &= ~mask; 53*799e125cSJiandong Zheng g_dmactrlflags |= flags; 54*799e125cSJiandong Zheng 55*799e125cSJiandong Zheng /* If trying to enable parity, check if parity is actually supported */ 56*799e125cSJiandong Zheng if (g_dmactrlflags & DMA_CTRL_PEN) { 57*799e125cSJiandong Zheng uint32_t control; 58*799e125cSJiandong Zheng 59*799e125cSJiandong Zheng control = readl(GMAC0_DMA_TX_CTRL_ADDR); 60*799e125cSJiandong Zheng writel(control | D64_XC_PD, GMAC0_DMA_TX_CTRL_ADDR); 61*799e125cSJiandong Zheng if (readl(GMAC0_DMA_TX_CTRL_ADDR) & D64_XC_PD) { 62*799e125cSJiandong Zheng /* 63*799e125cSJiandong Zheng * We *can* disable it, therefore it is supported; 64*799e125cSJiandong Zheng * restore control register 65*799e125cSJiandong Zheng */ 66*799e125cSJiandong Zheng writel(control, GMAC0_DMA_TX_CTRL_ADDR); 67*799e125cSJiandong Zheng } else { 68*799e125cSJiandong Zheng /* Not supported, don't allow it to be enabled */ 69*799e125cSJiandong Zheng g_dmactrlflags &= ~DMA_CTRL_PEN; 70*799e125cSJiandong Zheng } 71*799e125cSJiandong Zheng } 72*799e125cSJiandong Zheng 73*799e125cSJiandong Zheng return g_dmactrlflags; 74*799e125cSJiandong Zheng } 75*799e125cSJiandong Zheng 76*799e125cSJiandong Zheng static inline void reg32_clear_bits(uint32_t reg, uint32_t value) 77*799e125cSJiandong Zheng { 78*799e125cSJiandong Zheng uint32_t v = readl(reg); 79*799e125cSJiandong Zheng v &= ~(value); 80*799e125cSJiandong Zheng writel(v, reg); 81*799e125cSJiandong Zheng } 82*799e125cSJiandong Zheng 83*799e125cSJiandong Zheng static inline void reg32_set_bits(uint32_t reg, uint32_t value) 84*799e125cSJiandong Zheng { 85*799e125cSJiandong Zheng uint32_t v = readl(reg); 86*799e125cSJiandong Zheng v |= value; 87*799e125cSJiandong Zheng writel(v, reg); 88*799e125cSJiandong Zheng } 89*799e125cSJiandong Zheng 90*799e125cSJiandong Zheng #ifdef BCM_GMAC_DEBUG 91*799e125cSJiandong Zheng static void dma_tx_dump(struct eth_dma *dma) 92*799e125cSJiandong Zheng { 93*799e125cSJiandong Zheng dma64dd_t *descp = NULL; 94*799e125cSJiandong Zheng uint8_t *bufp; 95*799e125cSJiandong Zheng int i; 96*799e125cSJiandong Zheng 97*799e125cSJiandong Zheng printf("TX DMA Register:\n"); 98*799e125cSJiandong Zheng printf("control:0x%x; ptr:0x%x; addrl:0x%x; addrh:0x%x; stat0:0x%x, stat1:0x%x\n", 99*799e125cSJiandong Zheng readl(GMAC0_DMA_TX_CTRL_ADDR), 100*799e125cSJiandong Zheng readl(GMAC0_DMA_TX_PTR_ADDR), 101*799e125cSJiandong Zheng readl(GMAC0_DMA_TX_ADDR_LOW_ADDR), 102*799e125cSJiandong Zheng readl(GMAC0_DMA_TX_ADDR_HIGH_ADDR), 103*799e125cSJiandong Zheng readl(GMAC0_DMA_TX_STATUS0_ADDR), 104*799e125cSJiandong Zheng readl(GMAC0_DMA_TX_STATUS1_ADDR)); 105*799e125cSJiandong Zheng 106*799e125cSJiandong Zheng printf("TX Descriptors:\n"); 107*799e125cSJiandong Zheng for (i = 0; i < TX_BUF_NUM; i++) { 108*799e125cSJiandong Zheng descp = (dma64dd_t *)(dma->tx_desc_aligned) + i; 109*799e125cSJiandong Zheng printf("ctrl1:0x%08x; ctrl2:0x%08x; addr:0x%x 0x%08x\n", 110*799e125cSJiandong Zheng descp->ctrl1, descp->ctrl2, 111*799e125cSJiandong Zheng descp->addrhigh, descp->addrlow); 112*799e125cSJiandong Zheng } 113*799e125cSJiandong Zheng 114*799e125cSJiandong Zheng printf("TX Buffers:\n"); 115*799e125cSJiandong Zheng /* Initialize TX DMA descriptor table */ 116*799e125cSJiandong Zheng for (i = 0; i < TX_BUF_NUM; i++) { 117*799e125cSJiandong Zheng bufp = (uint8_t *)(dma->tx_buf + i * TX_BUF_SIZE); 118*799e125cSJiandong Zheng printf("buf%d:0x%x; ", i, (uint32_t)bufp); 119*799e125cSJiandong Zheng } 120*799e125cSJiandong Zheng printf("\n"); 121*799e125cSJiandong Zheng } 122*799e125cSJiandong Zheng 123*799e125cSJiandong Zheng static void dma_rx_dump(struct eth_dma *dma) 124*799e125cSJiandong Zheng { 125*799e125cSJiandong Zheng dma64dd_t *descp = NULL; 126*799e125cSJiandong Zheng uint8_t *bufp; 127*799e125cSJiandong Zheng int i; 128*799e125cSJiandong Zheng 129*799e125cSJiandong Zheng printf("RX DMA Register:\n"); 130*799e125cSJiandong Zheng printf("control:0x%x; ptr:0x%x; addrl:0x%x; addrh:0x%x; stat0:0x%x, stat1:0x%x\n", 131*799e125cSJiandong Zheng readl(GMAC0_DMA_RX_CTRL_ADDR), 132*799e125cSJiandong Zheng readl(GMAC0_DMA_RX_PTR_ADDR), 133*799e125cSJiandong Zheng readl(GMAC0_DMA_RX_ADDR_LOW_ADDR), 134*799e125cSJiandong Zheng readl(GMAC0_DMA_RX_ADDR_HIGH_ADDR), 135*799e125cSJiandong Zheng readl(GMAC0_DMA_RX_STATUS0_ADDR), 136*799e125cSJiandong Zheng readl(GMAC0_DMA_RX_STATUS1_ADDR)); 137*799e125cSJiandong Zheng 138*799e125cSJiandong Zheng printf("RX Descriptors:\n"); 139*799e125cSJiandong Zheng for (i = 0; i < RX_BUF_NUM; i++) { 140*799e125cSJiandong Zheng descp = (dma64dd_t *)(dma->rx_desc_aligned) + i; 141*799e125cSJiandong Zheng printf("ctrl1:0x%08x; ctrl2:0x%08x; addr:0x%x 0x%08x\n", 142*799e125cSJiandong Zheng descp->ctrl1, descp->ctrl2, 143*799e125cSJiandong Zheng descp->addrhigh, descp->addrlow); 144*799e125cSJiandong Zheng } 145*799e125cSJiandong Zheng 146*799e125cSJiandong Zheng printf("RX Buffers:\n"); 147*799e125cSJiandong Zheng for (i = 0; i < RX_BUF_NUM; i++) { 148*799e125cSJiandong Zheng bufp = dma->rx_buf + i * RX_BUF_SIZE; 149*799e125cSJiandong Zheng printf("buf%d:0x%x; ", i, (uint32_t)bufp); 150*799e125cSJiandong Zheng } 151*799e125cSJiandong Zheng printf("\n"); 152*799e125cSJiandong Zheng } 153*799e125cSJiandong Zheng #endif 154*799e125cSJiandong Zheng 155*799e125cSJiandong Zheng static int dma_tx_init(struct eth_dma *dma) 156*799e125cSJiandong Zheng { 157*799e125cSJiandong Zheng dma64dd_t *descp = NULL; 158*799e125cSJiandong Zheng uint8_t *bufp; 159*799e125cSJiandong Zheng int i; 160*799e125cSJiandong Zheng uint32_t ctrl; 161*799e125cSJiandong Zheng 162*799e125cSJiandong Zheng debug("%s enter\n", __func__); 163*799e125cSJiandong Zheng 164*799e125cSJiandong Zheng /* clear descriptor memory */ 165*799e125cSJiandong Zheng memset((void *)(dma->tx_desc_aligned), 0, 166*799e125cSJiandong Zheng TX_BUF_NUM * sizeof(dma64dd_t)); 167*799e125cSJiandong Zheng memset(dma->tx_buf, 0, TX_BUF_NUM * TX_BUF_SIZE); 168*799e125cSJiandong Zheng 169*799e125cSJiandong Zheng /* Initialize TX DMA descriptor table */ 170*799e125cSJiandong Zheng for (i = 0; i < TX_BUF_NUM; i++) { 171*799e125cSJiandong Zheng descp = (dma64dd_t *)(dma->tx_desc_aligned) + i; 172*799e125cSJiandong Zheng bufp = dma->tx_buf + i * TX_BUF_SIZE; 173*799e125cSJiandong Zheng /* clear buffer memory */ 174*799e125cSJiandong Zheng memset((void *)bufp, 0, TX_BUF_SIZE); 175*799e125cSJiandong Zheng 176*799e125cSJiandong Zheng ctrl = 0; 177*799e125cSJiandong Zheng /* if last descr set endOfTable */ 178*799e125cSJiandong Zheng if (i == (TX_BUF_NUM-1)) 179*799e125cSJiandong Zheng ctrl = D64_CTRL1_EOT; 180*799e125cSJiandong Zheng descp->ctrl1 = ctrl; 181*799e125cSJiandong Zheng descp->ctrl2 = 0; 182*799e125cSJiandong Zheng descp->addrlow = (uint32_t)bufp; 183*799e125cSJiandong Zheng descp->addrhigh = 0; 184*799e125cSJiandong Zheng } 185*799e125cSJiandong Zheng 186*799e125cSJiandong Zheng /* flush descriptor and buffer */ 187*799e125cSJiandong Zheng descp = dma->tx_desc_aligned; 188*799e125cSJiandong Zheng bufp = dma->tx_buf; 189*799e125cSJiandong Zheng flush_dcache_range((unsigned long)descp, 190*799e125cSJiandong Zheng (unsigned long)(descp + 191*799e125cSJiandong Zheng sizeof(dma64dd_t) * TX_BUF_NUM)); 192*799e125cSJiandong Zheng flush_dcache_range((unsigned long)(bufp), 193*799e125cSJiandong Zheng (unsigned long)(bufp + TX_BUF_SIZE * TX_BUF_NUM)); 194*799e125cSJiandong Zheng 195*799e125cSJiandong Zheng /* initialize the DMA channel */ 196*799e125cSJiandong Zheng writel((uint32_t)(dma->tx_desc_aligned), GMAC0_DMA_TX_ADDR_LOW_ADDR); 197*799e125cSJiandong Zheng writel(0, GMAC0_DMA_TX_ADDR_HIGH_ADDR); 198*799e125cSJiandong Zheng 199*799e125cSJiandong Zheng /* now update the dma last descriptor */ 200*799e125cSJiandong Zheng writel(((uint32_t)(dma->tx_desc_aligned)) & D64_XP_LD_MASK, 201*799e125cSJiandong Zheng GMAC0_DMA_TX_PTR_ADDR); 202*799e125cSJiandong Zheng 203*799e125cSJiandong Zheng return 0; 204*799e125cSJiandong Zheng } 205*799e125cSJiandong Zheng 206*799e125cSJiandong Zheng static int dma_rx_init(struct eth_dma *dma) 207*799e125cSJiandong Zheng { 208*799e125cSJiandong Zheng uint32_t last_desc; 209*799e125cSJiandong Zheng dma64dd_t *descp = NULL; 210*799e125cSJiandong Zheng uint8_t *bufp; 211*799e125cSJiandong Zheng uint32_t ctrl; 212*799e125cSJiandong Zheng int i; 213*799e125cSJiandong Zheng 214*799e125cSJiandong Zheng debug("%s enter\n", __func__); 215*799e125cSJiandong Zheng 216*799e125cSJiandong Zheng /* clear descriptor memory */ 217*799e125cSJiandong Zheng memset((void *)(dma->rx_desc_aligned), 0, 218*799e125cSJiandong Zheng RX_BUF_NUM * sizeof(dma64dd_t)); 219*799e125cSJiandong Zheng /* clear buffer memory */ 220*799e125cSJiandong Zheng memset(dma->rx_buf, 0, RX_BUF_NUM * RX_BUF_SIZE); 221*799e125cSJiandong Zheng 222*799e125cSJiandong Zheng /* Initialize RX DMA descriptor table */ 223*799e125cSJiandong Zheng for (i = 0; i < RX_BUF_NUM; i++) { 224*799e125cSJiandong Zheng descp = (dma64dd_t *)(dma->rx_desc_aligned) + i; 225*799e125cSJiandong Zheng bufp = dma->rx_buf + i * RX_BUF_SIZE; 226*799e125cSJiandong Zheng ctrl = 0; 227*799e125cSJiandong Zheng /* if last descr set endOfTable */ 228*799e125cSJiandong Zheng if (i == (RX_BUF_NUM - 1)) 229*799e125cSJiandong Zheng ctrl = D64_CTRL1_EOT; 230*799e125cSJiandong Zheng descp->ctrl1 = ctrl; 231*799e125cSJiandong Zheng descp->ctrl2 = RX_BUF_SIZE; 232*799e125cSJiandong Zheng descp->addrlow = (uint32_t)bufp; 233*799e125cSJiandong Zheng descp->addrhigh = 0; 234*799e125cSJiandong Zheng 235*799e125cSJiandong Zheng last_desc = ((uint32_t)(descp) & D64_XP_LD_MASK) 236*799e125cSJiandong Zheng + sizeof(dma64dd_t); 237*799e125cSJiandong Zheng } 238*799e125cSJiandong Zheng 239*799e125cSJiandong Zheng descp = dma->rx_desc_aligned; 240*799e125cSJiandong Zheng bufp = dma->rx_buf; 241*799e125cSJiandong Zheng /* flush descriptor and buffer */ 242*799e125cSJiandong Zheng flush_dcache_range((unsigned long)descp, 243*799e125cSJiandong Zheng (unsigned long)(descp + 244*799e125cSJiandong Zheng sizeof(dma64dd_t) * RX_BUF_NUM)); 245*799e125cSJiandong Zheng flush_dcache_range((unsigned long)(bufp), 246*799e125cSJiandong Zheng (unsigned long)(bufp + RX_BUF_SIZE * RX_BUF_NUM)); 247*799e125cSJiandong Zheng 248*799e125cSJiandong Zheng /* initailize the DMA channel */ 249*799e125cSJiandong Zheng writel((uint32_t)descp, GMAC0_DMA_RX_ADDR_LOW_ADDR); 250*799e125cSJiandong Zheng writel(0, GMAC0_DMA_RX_ADDR_HIGH_ADDR); 251*799e125cSJiandong Zheng 252*799e125cSJiandong Zheng /* now update the dma last descriptor */ 253*799e125cSJiandong Zheng writel(last_desc, GMAC0_DMA_RX_PTR_ADDR); 254*799e125cSJiandong Zheng 255*799e125cSJiandong Zheng return 0; 256*799e125cSJiandong Zheng } 257*799e125cSJiandong Zheng 258*799e125cSJiandong Zheng static int dma_init(struct eth_dma *dma) 259*799e125cSJiandong Zheng { 260*799e125cSJiandong Zheng debug(" %s enter\n", __func__); 261*799e125cSJiandong Zheng 262*799e125cSJiandong Zheng /* 263*799e125cSJiandong Zheng * Default flags: For backwards compatibility both 264*799e125cSJiandong Zheng * Rx Overflow Continue and Parity are DISABLED. 265*799e125cSJiandong Zheng */ 266*799e125cSJiandong Zheng dma_ctrlflags(DMA_CTRL_ROC | DMA_CTRL_PEN, 0); 267*799e125cSJiandong Zheng 268*799e125cSJiandong Zheng debug("rx burst len 0x%x\n", 269*799e125cSJiandong Zheng (readl(GMAC0_DMA_RX_CTRL_ADDR) & D64_RC_BL_MASK) 270*799e125cSJiandong Zheng >> D64_RC_BL_SHIFT); 271*799e125cSJiandong Zheng debug("tx burst len 0x%x\n", 272*799e125cSJiandong Zheng (readl(GMAC0_DMA_TX_CTRL_ADDR) & D64_XC_BL_MASK) 273*799e125cSJiandong Zheng >> D64_XC_BL_SHIFT); 274*799e125cSJiandong Zheng 275*799e125cSJiandong Zheng dma_tx_init(dma); 276*799e125cSJiandong Zheng dma_rx_init(dma); 277*799e125cSJiandong Zheng 278*799e125cSJiandong Zheng /* From end of chip_init() */ 279*799e125cSJiandong Zheng /* enable the overflow continue feature and disable parity */ 280*799e125cSJiandong Zheng dma_ctrlflags(DMA_CTRL_ROC | DMA_CTRL_PEN /* mask */, 281*799e125cSJiandong Zheng DMA_CTRL_ROC /* value */); 282*799e125cSJiandong Zheng 283*799e125cSJiandong Zheng return 0; 284*799e125cSJiandong Zheng } 285*799e125cSJiandong Zheng 286*799e125cSJiandong Zheng static int dma_deinit(struct eth_dma *dma) 287*799e125cSJiandong Zheng { 288*799e125cSJiandong Zheng debug(" %s enter\n", __func__); 289*799e125cSJiandong Zheng 290*799e125cSJiandong Zheng gmac_disable_dma(dma, MAC_DMA_RX); 291*799e125cSJiandong Zheng gmac_disable_dma(dma, MAC_DMA_TX); 292*799e125cSJiandong Zheng 293*799e125cSJiandong Zheng free(dma->tx_buf); 294*799e125cSJiandong Zheng dma->tx_buf = NULL; 295*799e125cSJiandong Zheng free(dma->tx_desc); 296*799e125cSJiandong Zheng dma->tx_desc = NULL; 297*799e125cSJiandong Zheng dma->tx_desc_aligned = NULL; 298*799e125cSJiandong Zheng 299*799e125cSJiandong Zheng free(dma->rx_buf); 300*799e125cSJiandong Zheng dma->rx_buf = NULL; 301*799e125cSJiandong Zheng free(dma->rx_desc); 302*799e125cSJiandong Zheng dma->rx_desc = NULL; 303*799e125cSJiandong Zheng dma->rx_desc_aligned = NULL; 304*799e125cSJiandong Zheng 305*799e125cSJiandong Zheng return 0; 306*799e125cSJiandong Zheng } 307*799e125cSJiandong Zheng 308*799e125cSJiandong Zheng int gmac_tx_packet(struct eth_dma *dma, void *packet, int length) 309*799e125cSJiandong Zheng { 310*799e125cSJiandong Zheng uint8_t *bufp = dma->tx_buf + dma->cur_tx_index * TX_BUF_SIZE; 311*799e125cSJiandong Zheng 312*799e125cSJiandong Zheng /* kick off the dma */ 313*799e125cSJiandong Zheng size_t len = length; 314*799e125cSJiandong Zheng int txout = dma->cur_tx_index; 315*799e125cSJiandong Zheng uint32_t flags; 316*799e125cSJiandong Zheng dma64dd_t *descp = NULL; 317*799e125cSJiandong Zheng uint32_t ctrl; 318*799e125cSJiandong Zheng uint32_t last_desc = (((uint32_t)dma->tx_desc_aligned) + 319*799e125cSJiandong Zheng sizeof(dma64dd_t)) & D64_XP_LD_MASK; 320*799e125cSJiandong Zheng size_t buflen; 321*799e125cSJiandong Zheng 322*799e125cSJiandong Zheng debug("%s enter\n", __func__); 323*799e125cSJiandong Zheng 324*799e125cSJiandong Zheng /* load the buffer */ 325*799e125cSJiandong Zheng memcpy(bufp, packet, len); 326*799e125cSJiandong Zheng 327*799e125cSJiandong Zheng /* Add 4 bytes for Ethernet FCS/CRC */ 328*799e125cSJiandong Zheng buflen = len + 4; 329*799e125cSJiandong Zheng 330*799e125cSJiandong Zheng ctrl = (buflen & D64_CTRL2_BC_MASK); 331*799e125cSJiandong Zheng 332*799e125cSJiandong Zheng /* the transmit will only be one frame or set SOF, EOF */ 333*799e125cSJiandong Zheng /* also set int on completion */ 334*799e125cSJiandong Zheng flags = D64_CTRL1_SOF | D64_CTRL1_IOC | D64_CTRL1_EOF; 335*799e125cSJiandong Zheng 336*799e125cSJiandong Zheng /* txout points to the descriptor to uset */ 337*799e125cSJiandong Zheng /* if last descriptor then set EOT */ 338*799e125cSJiandong Zheng if (txout == (TX_BUF_NUM - 1)) { 339*799e125cSJiandong Zheng flags |= D64_CTRL1_EOT; 340*799e125cSJiandong Zheng last_desc = ((uint32_t)(dma->tx_desc_aligned)) & D64_XP_LD_MASK; 341*799e125cSJiandong Zheng } 342*799e125cSJiandong Zheng 343*799e125cSJiandong Zheng /* write the descriptor */ 344*799e125cSJiandong Zheng descp = ((dma64dd_t *)(dma->tx_desc_aligned)) + txout; 345*799e125cSJiandong Zheng descp->addrlow = (uint32_t)bufp; 346*799e125cSJiandong Zheng descp->addrhigh = 0; 347*799e125cSJiandong Zheng descp->ctrl1 = flags; 348*799e125cSJiandong Zheng descp->ctrl2 = ctrl; 349*799e125cSJiandong Zheng 350*799e125cSJiandong Zheng /* flush descriptor and buffer */ 351*799e125cSJiandong Zheng flush_dcache_range((unsigned long)descp, 352*799e125cSJiandong Zheng (unsigned long)(descp + sizeof(dma64dd_t))); 353*799e125cSJiandong Zheng flush_dcache_range((unsigned long)bufp, 354*799e125cSJiandong Zheng (unsigned long)(bufp + TX_BUF_SIZE)); 355*799e125cSJiandong Zheng 356*799e125cSJiandong Zheng /* now update the dma last descriptor */ 357*799e125cSJiandong Zheng writel(last_desc, GMAC0_DMA_TX_PTR_ADDR); 358*799e125cSJiandong Zheng 359*799e125cSJiandong Zheng /* tx dma should be enabled so packet should go out */ 360*799e125cSJiandong Zheng 361*799e125cSJiandong Zheng /* update txout */ 362*799e125cSJiandong Zheng dma->cur_tx_index = (txout + 1) & (TX_BUF_NUM - 1); 363*799e125cSJiandong Zheng 364*799e125cSJiandong Zheng return 0; 365*799e125cSJiandong Zheng } 366*799e125cSJiandong Zheng 367*799e125cSJiandong Zheng bool gmac_check_tx_done(struct eth_dma *dma) 368*799e125cSJiandong Zheng { 369*799e125cSJiandong Zheng /* wait for tx to complete */ 370*799e125cSJiandong Zheng uint32_t intstatus; 371*799e125cSJiandong Zheng bool xfrdone = false; 372*799e125cSJiandong Zheng 373*799e125cSJiandong Zheng debug("%s enter\n", __func__); 374*799e125cSJiandong Zheng 375*799e125cSJiandong Zheng intstatus = readl(GMAC0_INT_STATUS_ADDR); 376*799e125cSJiandong Zheng 377*799e125cSJiandong Zheng debug("int(0x%x)\n", intstatus); 378*799e125cSJiandong Zheng if (intstatus & (I_XI0 | I_XI1 | I_XI2 | I_XI3)) { 379*799e125cSJiandong Zheng xfrdone = true; 380*799e125cSJiandong Zheng /* clear the int bits */ 381*799e125cSJiandong Zheng intstatus &= ~(I_XI0 | I_XI1 | I_XI2 | I_XI3); 382*799e125cSJiandong Zheng writel(intstatus, GMAC0_INT_STATUS_ADDR); 383*799e125cSJiandong Zheng } else { 384*799e125cSJiandong Zheng debug("Tx int(0x%x)\n", intstatus); 385*799e125cSJiandong Zheng } 386*799e125cSJiandong Zheng 387*799e125cSJiandong Zheng return xfrdone; 388*799e125cSJiandong Zheng } 389*799e125cSJiandong Zheng 390*799e125cSJiandong Zheng int gmac_check_rx_done(struct eth_dma *dma, uint8_t *buf) 391*799e125cSJiandong Zheng { 392*799e125cSJiandong Zheng void *bufp, *datap; 393*799e125cSJiandong Zheng size_t rcvlen = 0, buflen = 0; 394*799e125cSJiandong Zheng uint32_t stat0 = 0, stat1 = 0; 395*799e125cSJiandong Zheng uint32_t control, offset; 396*799e125cSJiandong Zheng uint8_t statbuf[HWRXOFF*2]; 397*799e125cSJiandong Zheng 398*799e125cSJiandong Zheng int index, curr, active; 399*799e125cSJiandong Zheng dma64dd_t *descp = NULL; 400*799e125cSJiandong Zheng 401*799e125cSJiandong Zheng /* udelay(50); */ 402*799e125cSJiandong Zheng 403*799e125cSJiandong Zheng /* 404*799e125cSJiandong Zheng * this api will check if a packet has been received. 405*799e125cSJiandong Zheng * If so it will return the address of the buffer and current 406*799e125cSJiandong Zheng * descriptor index will be incremented to the 407*799e125cSJiandong Zheng * next descriptor. Once done with the frame the buffer should be 408*799e125cSJiandong Zheng * added back onto the descriptor and the lastdscr should be updated 409*799e125cSJiandong Zheng * to this descriptor. 410*799e125cSJiandong Zheng */ 411*799e125cSJiandong Zheng index = dma->cur_rx_index; 412*799e125cSJiandong Zheng offset = (uint32_t)(dma->rx_desc_aligned); 413*799e125cSJiandong Zheng stat0 = readl(GMAC0_DMA_RX_STATUS0_ADDR) & D64_RS0_CD_MASK; 414*799e125cSJiandong Zheng stat1 = readl(GMAC0_DMA_RX_STATUS1_ADDR) & D64_RS0_CD_MASK; 415*799e125cSJiandong Zheng curr = ((stat0 - offset) & D64_RS0_CD_MASK) / sizeof(dma64dd_t); 416*799e125cSJiandong Zheng active = ((stat1 - offset) & D64_RS0_CD_MASK) / sizeof(dma64dd_t); 417*799e125cSJiandong Zheng 418*799e125cSJiandong Zheng /* check if any frame */ 419*799e125cSJiandong Zheng if (index == curr) 420*799e125cSJiandong Zheng return -1; 421*799e125cSJiandong Zheng 422*799e125cSJiandong Zheng debug("received packet\n"); 423*799e125cSJiandong Zheng debug("expect(0x%x) curr(0x%x) active(0x%x)\n", index, curr, active); 424*799e125cSJiandong Zheng /* remove warning */ 425*799e125cSJiandong Zheng if (index == active) 426*799e125cSJiandong Zheng ; 427*799e125cSJiandong Zheng 428*799e125cSJiandong Zheng /* get the packet pointer that corresponds to the rx descriptor */ 429*799e125cSJiandong Zheng bufp = dma->rx_buf + index * RX_BUF_SIZE; 430*799e125cSJiandong Zheng 431*799e125cSJiandong Zheng descp = (dma64dd_t *)(dma->rx_desc_aligned) + index; 432*799e125cSJiandong Zheng /* flush descriptor and buffer */ 433*799e125cSJiandong Zheng flush_dcache_range((unsigned long)descp, 434*799e125cSJiandong Zheng (unsigned long)(descp + sizeof(dma64dd_t))); 435*799e125cSJiandong Zheng flush_dcache_range((unsigned long)bufp, 436*799e125cSJiandong Zheng (unsigned long)(bufp + RX_BUF_SIZE)); 437*799e125cSJiandong Zheng 438*799e125cSJiandong Zheng buflen = (descp->ctrl2 & D64_CTRL2_BC_MASK); 439*799e125cSJiandong Zheng 440*799e125cSJiandong Zheng stat0 = readl(GMAC0_DMA_RX_STATUS0_ADDR); 441*799e125cSJiandong Zheng stat1 = readl(GMAC0_DMA_RX_STATUS1_ADDR); 442*799e125cSJiandong Zheng 443*799e125cSJiandong Zheng debug("bufp(0x%x) index(0x%x) buflen(0x%x) stat0(0x%x) stat1(0x%x)\n", 444*799e125cSJiandong Zheng (uint32_t)bufp, index, buflen, stat0, stat1); 445*799e125cSJiandong Zheng 446*799e125cSJiandong Zheng dma->cur_rx_index = (index + 1) & (RX_BUF_NUM - 1); 447*799e125cSJiandong Zheng 448*799e125cSJiandong Zheng /* get buffer offset */ 449*799e125cSJiandong Zheng control = readl(GMAC0_DMA_RX_CTRL_ADDR); 450*799e125cSJiandong Zheng offset = (control & D64_RC_RO_MASK) >> D64_RC_RO_SHIFT; 451*799e125cSJiandong Zheng rcvlen = *(uint16_t *)bufp; 452*799e125cSJiandong Zheng 453*799e125cSJiandong Zheng debug("Received %d bytes\n", rcvlen); 454*799e125cSJiandong Zheng /* copy status into temp buf then copy data from rx buffer */ 455*799e125cSJiandong Zheng memcpy(statbuf, bufp, offset); 456*799e125cSJiandong Zheng datap = (void *)((uint32_t)bufp + offset); 457*799e125cSJiandong Zheng memcpy(buf, datap, rcvlen); 458*799e125cSJiandong Zheng 459*799e125cSJiandong Zheng /* update descriptor that is being added back on ring */ 460*799e125cSJiandong Zheng descp->ctrl2 = RX_BUF_SIZE; 461*799e125cSJiandong Zheng descp->addrlow = (uint32_t)bufp; 462*799e125cSJiandong Zheng descp->addrhigh = 0; 463*799e125cSJiandong Zheng /* flush descriptor */ 464*799e125cSJiandong Zheng flush_dcache_range((unsigned long)descp, 465*799e125cSJiandong Zheng (unsigned long)(descp + sizeof(dma64dd_t))); 466*799e125cSJiandong Zheng 467*799e125cSJiandong Zheng /* set the lastdscr for the rx ring */ 468*799e125cSJiandong Zheng writel(((uint32_t)descp) & D64_XP_LD_MASK, GMAC0_DMA_RX_PTR_ADDR); 469*799e125cSJiandong Zheng 470*799e125cSJiandong Zheng return (int)rcvlen; 471*799e125cSJiandong Zheng } 472*799e125cSJiandong Zheng 473*799e125cSJiandong Zheng static int gmac_disable_dma(struct eth_dma *dma, int dir) 474*799e125cSJiandong Zheng { 475*799e125cSJiandong Zheng int status; 476*799e125cSJiandong Zheng 477*799e125cSJiandong Zheng debug("%s enter\n", __func__); 478*799e125cSJiandong Zheng 479*799e125cSJiandong Zheng if (dir == MAC_DMA_TX) { 480*799e125cSJiandong Zheng /* address PR8249/PR7577 issue */ 481*799e125cSJiandong Zheng /* suspend tx DMA first */ 482*799e125cSJiandong Zheng writel(D64_XC_SE, GMAC0_DMA_TX_CTRL_ADDR); 483*799e125cSJiandong Zheng SPINWAIT(((status = (readl(GMAC0_DMA_TX_STATUS0_ADDR) & 484*799e125cSJiandong Zheng D64_XS0_XS_MASK)) != 485*799e125cSJiandong Zheng D64_XS0_XS_DISABLED) && 486*799e125cSJiandong Zheng (status != D64_XS0_XS_IDLE) && 487*799e125cSJiandong Zheng (status != D64_XS0_XS_STOPPED), 10000); 488*799e125cSJiandong Zheng 489*799e125cSJiandong Zheng /* 490*799e125cSJiandong Zheng * PR2414 WAR: DMA engines are not disabled until 491*799e125cSJiandong Zheng * transfer finishes 492*799e125cSJiandong Zheng */ 493*799e125cSJiandong Zheng writel(0, GMAC0_DMA_TX_CTRL_ADDR); 494*799e125cSJiandong Zheng SPINWAIT(((status = (readl(GMAC0_DMA_TX_STATUS0_ADDR) & 495*799e125cSJiandong Zheng D64_XS0_XS_MASK)) != 496*799e125cSJiandong Zheng D64_XS0_XS_DISABLED), 10000); 497*799e125cSJiandong Zheng 498*799e125cSJiandong Zheng /* wait for the last transaction to complete */ 499*799e125cSJiandong Zheng udelay(2); 500*799e125cSJiandong Zheng 501*799e125cSJiandong Zheng status = (status == D64_XS0_XS_DISABLED); 502*799e125cSJiandong Zheng } else { 503*799e125cSJiandong Zheng /* 504*799e125cSJiandong Zheng * PR2414 WAR: DMA engines are not disabled until 505*799e125cSJiandong Zheng * transfer finishes 506*799e125cSJiandong Zheng */ 507*799e125cSJiandong Zheng writel(0, GMAC0_DMA_RX_CTRL_ADDR); 508*799e125cSJiandong Zheng SPINWAIT(((status = (readl(GMAC0_DMA_RX_STATUS0_ADDR) & 509*799e125cSJiandong Zheng D64_RS0_RS_MASK)) != 510*799e125cSJiandong Zheng D64_RS0_RS_DISABLED), 10000); 511*799e125cSJiandong Zheng 512*799e125cSJiandong Zheng status = (status == D64_RS0_RS_DISABLED); 513*799e125cSJiandong Zheng } 514*799e125cSJiandong Zheng 515*799e125cSJiandong Zheng return status; 516*799e125cSJiandong Zheng } 517*799e125cSJiandong Zheng 518*799e125cSJiandong Zheng static int gmac_enable_dma(struct eth_dma *dma, int dir) 519*799e125cSJiandong Zheng { 520*799e125cSJiandong Zheng uint32_t control; 521*799e125cSJiandong Zheng 522*799e125cSJiandong Zheng debug("%s enter\n", __func__); 523*799e125cSJiandong Zheng 524*799e125cSJiandong Zheng if (dir == MAC_DMA_TX) { 525*799e125cSJiandong Zheng dma->cur_tx_index = 0; 526*799e125cSJiandong Zheng 527*799e125cSJiandong Zheng /* 528*799e125cSJiandong Zheng * These bits 20:18 (burstLen) of control register can be 529*799e125cSJiandong Zheng * written but will take effect only if these bits are 530*799e125cSJiandong Zheng * valid. So this will not affect previous versions 531*799e125cSJiandong Zheng * of the DMA. They will continue to have those bits set to 0. 532*799e125cSJiandong Zheng */ 533*799e125cSJiandong Zheng control = readl(GMAC0_DMA_TX_CTRL_ADDR); 534*799e125cSJiandong Zheng 535*799e125cSJiandong Zheng control |= D64_XC_XE; 536*799e125cSJiandong Zheng if ((g_dmactrlflags & DMA_CTRL_PEN) == 0) 537*799e125cSJiandong Zheng control |= D64_XC_PD; 538*799e125cSJiandong Zheng 539*799e125cSJiandong Zheng writel(control, GMAC0_DMA_TX_CTRL_ADDR); 540*799e125cSJiandong Zheng 541*799e125cSJiandong Zheng /* initailize the DMA channel */ 542*799e125cSJiandong Zheng writel((uint32_t)(dma->tx_desc_aligned), 543*799e125cSJiandong Zheng GMAC0_DMA_TX_ADDR_LOW_ADDR); 544*799e125cSJiandong Zheng writel(0, GMAC0_DMA_TX_ADDR_HIGH_ADDR); 545*799e125cSJiandong Zheng } else { 546*799e125cSJiandong Zheng dma->cur_rx_index = 0; 547*799e125cSJiandong Zheng 548*799e125cSJiandong Zheng control = (readl(GMAC0_DMA_RX_CTRL_ADDR) & 549*799e125cSJiandong Zheng D64_RC_AE) | D64_RC_RE; 550*799e125cSJiandong Zheng 551*799e125cSJiandong Zheng if ((g_dmactrlflags & DMA_CTRL_PEN) == 0) 552*799e125cSJiandong Zheng control |= D64_RC_PD; 553*799e125cSJiandong Zheng 554*799e125cSJiandong Zheng if (g_dmactrlflags & DMA_CTRL_ROC) 555*799e125cSJiandong Zheng control |= D64_RC_OC; 556*799e125cSJiandong Zheng 557*799e125cSJiandong Zheng /* 558*799e125cSJiandong Zheng * These bits 20:18 (burstLen) of control register can be 559*799e125cSJiandong Zheng * written but will take effect only if these bits are 560*799e125cSJiandong Zheng * valid. So this will not affect previous versions 561*799e125cSJiandong Zheng * of the DMA. They will continue to have those bits set to 0. 562*799e125cSJiandong Zheng */ 563*799e125cSJiandong Zheng control &= ~D64_RC_BL_MASK; 564*799e125cSJiandong Zheng /* Keep default Rx burstlen */ 565*799e125cSJiandong Zheng control |= readl(GMAC0_DMA_RX_CTRL_ADDR) & D64_RC_BL_MASK; 566*799e125cSJiandong Zheng control |= HWRXOFF << D64_RC_RO_SHIFT; 567*799e125cSJiandong Zheng 568*799e125cSJiandong Zheng writel(control, GMAC0_DMA_RX_CTRL_ADDR); 569*799e125cSJiandong Zheng 570*799e125cSJiandong Zheng /* 571*799e125cSJiandong Zheng * the rx descriptor ring should have 572*799e125cSJiandong Zheng * the addresses set properly; 573*799e125cSJiandong Zheng * set the lastdscr for the rx ring 574*799e125cSJiandong Zheng */ 575*799e125cSJiandong Zheng writel(((uint32_t)(dma->rx_desc_aligned) + 576*799e125cSJiandong Zheng (RX_BUF_NUM - 1) * RX_BUF_SIZE) & 577*799e125cSJiandong Zheng D64_XP_LD_MASK, GMAC0_DMA_RX_PTR_ADDR); 578*799e125cSJiandong Zheng } 579*799e125cSJiandong Zheng 580*799e125cSJiandong Zheng return 0; 581*799e125cSJiandong Zheng } 582*799e125cSJiandong Zheng 583*799e125cSJiandong Zheng bool gmac_mii_busywait(unsigned int timeout) 584*799e125cSJiandong Zheng { 585*799e125cSJiandong Zheng uint32_t tmp = 0; 586*799e125cSJiandong Zheng 587*799e125cSJiandong Zheng while (timeout > 10) { 588*799e125cSJiandong Zheng tmp = readl(GMAC_MII_CTRL_ADDR); 589*799e125cSJiandong Zheng if (tmp & (1 << GMAC_MII_BUSY_SHIFT)) { 590*799e125cSJiandong Zheng udelay(10); 591*799e125cSJiandong Zheng timeout -= 10; 592*799e125cSJiandong Zheng } else { 593*799e125cSJiandong Zheng break; 594*799e125cSJiandong Zheng } 595*799e125cSJiandong Zheng } 596*799e125cSJiandong Zheng return tmp & (1 << GMAC_MII_BUSY_SHIFT); 597*799e125cSJiandong Zheng } 598*799e125cSJiandong Zheng 599*799e125cSJiandong Zheng int gmac_miiphy_read(const char *devname, unsigned char phyaddr, 600*799e125cSJiandong Zheng unsigned char reg, unsigned short *value) 601*799e125cSJiandong Zheng { 602*799e125cSJiandong Zheng uint32_t tmp = 0; 603*799e125cSJiandong Zheng 604*799e125cSJiandong Zheng (void)devname; 605*799e125cSJiandong Zheng 606*799e125cSJiandong Zheng /* Busy wait timeout is 1ms */ 607*799e125cSJiandong Zheng if (gmac_mii_busywait(1000)) { 608*799e125cSJiandong Zheng error("%s: Prepare MII read: MII/MDIO busy\n", __func__); 609*799e125cSJiandong Zheng return -1; 610*799e125cSJiandong Zheng } 611*799e125cSJiandong Zheng 612*799e125cSJiandong Zheng /* Read operation */ 613*799e125cSJiandong Zheng tmp = GMAC_MII_DATA_READ_CMD; 614*799e125cSJiandong Zheng tmp |= (phyaddr << GMAC_MII_PHY_ADDR_SHIFT) | 615*799e125cSJiandong Zheng (reg << GMAC_MII_PHY_REG_SHIFT); 616*799e125cSJiandong Zheng debug("MII read cmd 0x%x, phy 0x%x, reg 0x%x\n", tmp, phyaddr, reg); 617*799e125cSJiandong Zheng writel(tmp, GMAC_MII_DATA_ADDR); 618*799e125cSJiandong Zheng 619*799e125cSJiandong Zheng if (gmac_mii_busywait(1000)) { 620*799e125cSJiandong Zheng error("%s: MII read failure: MII/MDIO busy\n", __func__); 621*799e125cSJiandong Zheng return -1; 622*799e125cSJiandong Zheng } 623*799e125cSJiandong Zheng 624*799e125cSJiandong Zheng *value = readl(GMAC_MII_DATA_ADDR) & 0xffff; 625*799e125cSJiandong Zheng debug("MII read data 0x%x\n", *value); 626*799e125cSJiandong Zheng return 0; 627*799e125cSJiandong Zheng } 628*799e125cSJiandong Zheng 629*799e125cSJiandong Zheng int gmac_miiphy_write(const char *devname, unsigned char phyaddr, 630*799e125cSJiandong Zheng unsigned char reg, unsigned short value) 631*799e125cSJiandong Zheng { 632*799e125cSJiandong Zheng uint32_t tmp = 0; 633*799e125cSJiandong Zheng 634*799e125cSJiandong Zheng (void)devname; 635*799e125cSJiandong Zheng 636*799e125cSJiandong Zheng /* Busy wait timeout is 1ms */ 637*799e125cSJiandong Zheng if (gmac_mii_busywait(1000)) { 638*799e125cSJiandong Zheng error("%s: Prepare MII write: MII/MDIO busy\n", __func__); 639*799e125cSJiandong Zheng return -1; 640*799e125cSJiandong Zheng } 641*799e125cSJiandong Zheng 642*799e125cSJiandong Zheng /* Write operation */ 643*799e125cSJiandong Zheng tmp = GMAC_MII_DATA_WRITE_CMD | (value & 0xffff); 644*799e125cSJiandong Zheng tmp |= ((phyaddr << GMAC_MII_PHY_ADDR_SHIFT) | 645*799e125cSJiandong Zheng (reg << GMAC_MII_PHY_REG_SHIFT)); 646*799e125cSJiandong Zheng debug("MII write cmd 0x%x, phy 0x%x, reg 0x%x, data 0x%x\n", 647*799e125cSJiandong Zheng tmp, phyaddr, reg, value); 648*799e125cSJiandong Zheng writel(tmp, GMAC_MII_DATA_ADDR); 649*799e125cSJiandong Zheng 650*799e125cSJiandong Zheng if (gmac_mii_busywait(1000)) { 651*799e125cSJiandong Zheng error("%s: MII write failure: MII/MDIO busy\n", __func__); 652*799e125cSJiandong Zheng return -1; 653*799e125cSJiandong Zheng } 654*799e125cSJiandong Zheng 655*799e125cSJiandong Zheng return 0; 656*799e125cSJiandong Zheng } 657*799e125cSJiandong Zheng 658*799e125cSJiandong Zheng void gmac_init_reset(void) 659*799e125cSJiandong Zheng { 660*799e125cSJiandong Zheng debug("%s enter\n", __func__); 661*799e125cSJiandong Zheng 662*799e125cSJiandong Zheng /* set command config reg CC_SR */ 663*799e125cSJiandong Zheng reg32_set_bits(UNIMAC0_CMD_CFG_ADDR, CC_SR); 664*799e125cSJiandong Zheng udelay(GMAC_RESET_DELAY); 665*799e125cSJiandong Zheng } 666*799e125cSJiandong Zheng 667*799e125cSJiandong Zheng void gmac_clear_reset(void) 668*799e125cSJiandong Zheng { 669*799e125cSJiandong Zheng debug("%s enter\n", __func__); 670*799e125cSJiandong Zheng 671*799e125cSJiandong Zheng /* clear command config reg CC_SR */ 672*799e125cSJiandong Zheng reg32_clear_bits(UNIMAC0_CMD_CFG_ADDR, CC_SR); 673*799e125cSJiandong Zheng udelay(GMAC_RESET_DELAY); 674*799e125cSJiandong Zheng } 675*799e125cSJiandong Zheng 676*799e125cSJiandong Zheng static void gmac_enable_local(bool en) 677*799e125cSJiandong Zheng { 678*799e125cSJiandong Zheng uint32_t cmdcfg; 679*799e125cSJiandong Zheng 680*799e125cSJiandong Zheng debug("%s enter\n", __func__); 681*799e125cSJiandong Zheng 682*799e125cSJiandong Zheng /* read command config reg */ 683*799e125cSJiandong Zheng cmdcfg = readl(UNIMAC0_CMD_CFG_ADDR); 684*799e125cSJiandong Zheng 685*799e125cSJiandong Zheng /* put mac in reset */ 686*799e125cSJiandong Zheng gmac_init_reset(); 687*799e125cSJiandong Zheng 688*799e125cSJiandong Zheng cmdcfg |= CC_SR; 689*799e125cSJiandong Zheng 690*799e125cSJiandong Zheng /* first deassert rx_ena and tx_ena while in reset */ 691*799e125cSJiandong Zheng cmdcfg &= ~(CC_RE | CC_TE); 692*799e125cSJiandong Zheng /* write command config reg */ 693*799e125cSJiandong Zheng writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR); 694*799e125cSJiandong Zheng 695*799e125cSJiandong Zheng /* bring mac out of reset */ 696*799e125cSJiandong Zheng gmac_clear_reset(); 697*799e125cSJiandong Zheng 698*799e125cSJiandong Zheng /* if not enable exit now */ 699*799e125cSJiandong Zheng if (!en) 700*799e125cSJiandong Zheng return; 701*799e125cSJiandong Zheng 702*799e125cSJiandong Zheng /* enable the mac transmit and receive paths now */ 703*799e125cSJiandong Zheng udelay(2); 704*799e125cSJiandong Zheng cmdcfg &= ~CC_SR; 705*799e125cSJiandong Zheng cmdcfg |= (CC_RE | CC_TE); 706*799e125cSJiandong Zheng 707*799e125cSJiandong Zheng /* assert rx_ena and tx_ena when out of reset to enable the mac */ 708*799e125cSJiandong Zheng writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR); 709*799e125cSJiandong Zheng 710*799e125cSJiandong Zheng return; 711*799e125cSJiandong Zheng } 712*799e125cSJiandong Zheng 713*799e125cSJiandong Zheng int gmac_enable(void) 714*799e125cSJiandong Zheng { 715*799e125cSJiandong Zheng gmac_enable_local(1); 716*799e125cSJiandong Zheng 717*799e125cSJiandong Zheng /* clear interrupts */ 718*799e125cSJiandong Zheng writel(I_INTMASK, GMAC0_INT_STATUS_ADDR); 719*799e125cSJiandong Zheng return 0; 720*799e125cSJiandong Zheng } 721*799e125cSJiandong Zheng 722*799e125cSJiandong Zheng int gmac_disable(void) 723*799e125cSJiandong Zheng { 724*799e125cSJiandong Zheng gmac_enable_local(0); 725*799e125cSJiandong Zheng return 0; 726*799e125cSJiandong Zheng } 727*799e125cSJiandong Zheng 728*799e125cSJiandong Zheng int gmac_set_speed(int speed, int duplex) 729*799e125cSJiandong Zheng { 730*799e125cSJiandong Zheng uint32_t cmdcfg; 731*799e125cSJiandong Zheng uint32_t hd_ena; 732*799e125cSJiandong Zheng uint32_t speed_cfg; 733*799e125cSJiandong Zheng 734*799e125cSJiandong Zheng hd_ena = duplex ? 0 : CC_HD; 735*799e125cSJiandong Zheng if (speed == 1000) { 736*799e125cSJiandong Zheng speed_cfg = 2; 737*799e125cSJiandong Zheng } else if (speed == 100) { 738*799e125cSJiandong Zheng speed_cfg = 1; 739*799e125cSJiandong Zheng } else if (speed == 10) { 740*799e125cSJiandong Zheng speed_cfg = 0; 741*799e125cSJiandong Zheng } else { 742*799e125cSJiandong Zheng error("%s: Invalid GMAC speed(%d)!\n", __func__, speed); 743*799e125cSJiandong Zheng return -1; 744*799e125cSJiandong Zheng } 745*799e125cSJiandong Zheng 746*799e125cSJiandong Zheng cmdcfg = readl(UNIMAC0_CMD_CFG_ADDR); 747*799e125cSJiandong Zheng cmdcfg &= ~(CC_ES_MASK | CC_HD); 748*799e125cSJiandong Zheng cmdcfg |= ((speed_cfg << CC_ES_SHIFT) | hd_ena); 749*799e125cSJiandong Zheng 750*799e125cSJiandong Zheng printf("Change GMAC speed to %dMB\n", speed); 751*799e125cSJiandong Zheng debug("GMAC speed cfg 0x%x\n", cmdcfg); 752*799e125cSJiandong Zheng writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR); 753*799e125cSJiandong Zheng 754*799e125cSJiandong Zheng return 0; 755*799e125cSJiandong Zheng } 756*799e125cSJiandong Zheng 757*799e125cSJiandong Zheng int gmac_set_mac_addr(unsigned char *mac) 758*799e125cSJiandong Zheng { 759*799e125cSJiandong Zheng /* set our local address */ 760*799e125cSJiandong Zheng debug("GMAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 761*799e125cSJiandong Zheng mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 762*799e125cSJiandong Zheng writel(htonl(*(uint32_t *)mac), UNIMAC0_MAC_MSB_ADDR); 763*799e125cSJiandong Zheng writew(htons(*(uint32_t *)&mac[4]), UNIMAC0_MAC_LSB_ADDR); 764*799e125cSJiandong Zheng 765*799e125cSJiandong Zheng return 0; 766*799e125cSJiandong Zheng } 767*799e125cSJiandong Zheng 768*799e125cSJiandong Zheng int gmac_mac_init(struct eth_device *dev) 769*799e125cSJiandong Zheng { 770*799e125cSJiandong Zheng struct eth_info *eth = (struct eth_info *)(dev->priv); 771*799e125cSJiandong Zheng struct eth_dma *dma = &(eth->dma); 772*799e125cSJiandong Zheng 773*799e125cSJiandong Zheng uint32_t tmp; 774*799e125cSJiandong Zheng uint32_t cmdcfg; 775*799e125cSJiandong Zheng int chipid; 776*799e125cSJiandong Zheng 777*799e125cSJiandong Zheng debug("%s enter\n", __func__); 778*799e125cSJiandong Zheng 779*799e125cSJiandong Zheng /* Always use GMAC0 */ 780*799e125cSJiandong Zheng printf("Using GMAC%d\n", 0); 781*799e125cSJiandong Zheng 782*799e125cSJiandong Zheng /* Reset AMAC0 core */ 783*799e125cSJiandong Zheng writel(0, AMAC0_IDM_RESET_ADDR); 784*799e125cSJiandong Zheng tmp = readl(AMAC0_IO_CTRL_DIRECT_ADDR); 785*799e125cSJiandong Zheng /* Set clock */ 786*799e125cSJiandong Zheng tmp &= ~(1 << AMAC0_IO_CTRL_CLK_250_SEL_SHIFT); 787*799e125cSJiandong Zheng tmp |= (1 << AMAC0_IO_CTRL_GMII_MODE_SHIFT); 788*799e125cSJiandong Zheng /* Set Tx clock */ 789*799e125cSJiandong Zheng tmp &= ~(1 << AMAC0_IO_CTRL_DEST_SYNC_MODE_EN_SHIFT); 790*799e125cSJiandong Zheng writel(tmp, AMAC0_IO_CTRL_DIRECT_ADDR); 791*799e125cSJiandong Zheng 792*799e125cSJiandong Zheng /* reset gmac */ 793*799e125cSJiandong Zheng /* 794*799e125cSJiandong Zheng * As AMAC is just reset, NO need? 795*799e125cSJiandong Zheng * set eth_data into loopback mode to ensure no rx traffic 796*799e125cSJiandong Zheng * gmac_loopback(eth_data, TRUE); 797*799e125cSJiandong Zheng * ET_TRACE(("%s gmac loopback\n", __func__)); 798*799e125cSJiandong Zheng * udelay(1); 799*799e125cSJiandong Zheng */ 800*799e125cSJiandong Zheng 801*799e125cSJiandong Zheng cmdcfg = readl(UNIMAC0_CMD_CFG_ADDR); 802*799e125cSJiandong Zheng cmdcfg &= ~(CC_TE | CC_RE | CC_RPI | CC_TAI | CC_HD | CC_ML | 803*799e125cSJiandong Zheng CC_CFE | CC_RL | CC_RED | CC_PE | CC_TPI | 804*799e125cSJiandong Zheng CC_PAD_EN | CC_PF); 805*799e125cSJiandong Zheng cmdcfg |= (CC_PROM | CC_NLC | CC_CFE); 806*799e125cSJiandong Zheng /* put mac in reset */ 807*799e125cSJiandong Zheng gmac_init_reset(); 808*799e125cSJiandong Zheng writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR); 809*799e125cSJiandong Zheng gmac_clear_reset(); 810*799e125cSJiandong Zheng 811*799e125cSJiandong Zheng /* enable clear MIB on read */ 812*799e125cSJiandong Zheng reg32_set_bits(GMAC0_DEV_CTRL_ADDR, DC_MROR); 813*799e125cSJiandong Zheng /* PHY: set smi_master to drive mdc_clk */ 814*799e125cSJiandong Zheng reg32_set_bits(GMAC0_PHY_CTRL_ADDR, PC_MTE); 815*799e125cSJiandong Zheng 816*799e125cSJiandong Zheng /* clear persistent sw intstatus */ 817*799e125cSJiandong Zheng writel(0, GMAC0_INT_STATUS_ADDR); 818*799e125cSJiandong Zheng 819*799e125cSJiandong Zheng if (dma_init(dma) < 0) { 820*799e125cSJiandong Zheng error("%s: GMAC dma_init failed\n", __func__); 821*799e125cSJiandong Zheng goto err_exit; 822*799e125cSJiandong Zheng } 823*799e125cSJiandong Zheng 824*799e125cSJiandong Zheng chipid = CHIPID; 825*799e125cSJiandong Zheng printf("%s: Chip ID: 0x%x\n", __func__, chipid); 826*799e125cSJiandong Zheng 827*799e125cSJiandong Zheng /* set switch bypass mode */ 828*799e125cSJiandong Zheng tmp = readl(SWITCH_GLOBAL_CONFIG_ADDR); 829*799e125cSJiandong Zheng tmp |= (1 << CDRU_SWITCH_BYPASS_SWITCH_SHIFT); 830*799e125cSJiandong Zheng 831*799e125cSJiandong Zheng /* Switch mode */ 832*799e125cSJiandong Zheng /* tmp &= ~(1 << CDRU_SWITCH_BYPASS_SWITCH_SHIFT); */ 833*799e125cSJiandong Zheng 834*799e125cSJiandong Zheng writel(tmp, SWITCH_GLOBAL_CONFIG_ADDR); 835*799e125cSJiandong Zheng 836*799e125cSJiandong Zheng tmp = readl(CRMU_CHIP_IO_PAD_CONTROL_ADDR); 837*799e125cSJiandong Zheng tmp &= ~(1 << CDRU_IOMUX_FORCE_PAD_IN_SHIFT); 838*799e125cSJiandong Zheng writel(tmp, CRMU_CHIP_IO_PAD_CONTROL_ADDR); 839*799e125cSJiandong Zheng 840*799e125cSJiandong Zheng /* Set MDIO to internal GPHY */ 841*799e125cSJiandong Zheng tmp = readl(GMAC_MII_CTRL_ADDR); 842*799e125cSJiandong Zheng /* Select internal MDC/MDIO bus*/ 843*799e125cSJiandong Zheng tmp &= ~(1 << GMAC_MII_CTRL_BYP_SHIFT); 844*799e125cSJiandong Zheng /* select MDC/MDIO connecting to on-chip internal PHYs */ 845*799e125cSJiandong Zheng tmp &= ~(1 << GMAC_MII_CTRL_EXT_SHIFT); 846*799e125cSJiandong Zheng /* 847*799e125cSJiandong Zheng * give bit[6:0](MDCDIV) with required divisor to set 848*799e125cSJiandong Zheng * the MDC clock frequency, 66MHZ/0x1A=2.5MHZ 849*799e125cSJiandong Zheng */ 850*799e125cSJiandong Zheng tmp |= 0x1A; 851*799e125cSJiandong Zheng 852*799e125cSJiandong Zheng writel(tmp, GMAC_MII_CTRL_ADDR); 853*799e125cSJiandong Zheng 854*799e125cSJiandong Zheng if (gmac_mii_busywait(1000)) { 855*799e125cSJiandong Zheng error("%s: Configure MDIO: MII/MDIO busy\n", __func__); 856*799e125cSJiandong Zheng goto err_exit; 857*799e125cSJiandong Zheng } 858*799e125cSJiandong Zheng 859*799e125cSJiandong Zheng /* Configure GMAC0 */ 860*799e125cSJiandong Zheng /* enable one rx interrupt per received frame */ 861*799e125cSJiandong Zheng writel(1 << GMAC0_IRL_FRAMECOUNT_SHIFT, GMAC0_INTR_RECV_LAZY_ADDR); 862*799e125cSJiandong Zheng 863*799e125cSJiandong Zheng /* read command config reg */ 864*799e125cSJiandong Zheng cmdcfg = readl(UNIMAC0_CMD_CFG_ADDR); 865*799e125cSJiandong Zheng /* enable 802.3x tx flow control (honor received PAUSE frames) */ 866*799e125cSJiandong Zheng cmdcfg &= ~CC_RPI; 867*799e125cSJiandong Zheng /* enable promiscuous mode */ 868*799e125cSJiandong Zheng cmdcfg |= CC_PROM; 869*799e125cSJiandong Zheng /* Disable loopback mode */ 870*799e125cSJiandong Zheng cmdcfg &= ~CC_ML; 871*799e125cSJiandong Zheng /* set the speed */ 872*799e125cSJiandong Zheng cmdcfg &= ~(CC_ES_MASK | CC_HD); 873*799e125cSJiandong Zheng /* Set to 1Gbps and full duplex by default */ 874*799e125cSJiandong Zheng cmdcfg |= (2 << CC_ES_SHIFT); 875*799e125cSJiandong Zheng 876*799e125cSJiandong Zheng /* put mac in reset */ 877*799e125cSJiandong Zheng gmac_init_reset(); 878*799e125cSJiandong Zheng /* write register */ 879*799e125cSJiandong Zheng writel(cmdcfg, UNIMAC0_CMD_CFG_ADDR); 880*799e125cSJiandong Zheng /* bring mac out of reset */ 881*799e125cSJiandong Zheng gmac_clear_reset(); 882*799e125cSJiandong Zheng 883*799e125cSJiandong Zheng /* set max frame lengths; account for possible vlan tag */ 884*799e125cSJiandong Zheng writel(PKTSIZE + 32, UNIMAC0_FRM_LENGTH_ADDR); 885*799e125cSJiandong Zheng 886*799e125cSJiandong Zheng return 0; 887*799e125cSJiandong Zheng 888*799e125cSJiandong Zheng err_exit: 889*799e125cSJiandong Zheng dma_deinit(dma); 890*799e125cSJiandong Zheng return -1; 891*799e125cSJiandong Zheng } 892*799e125cSJiandong Zheng 893*799e125cSJiandong Zheng int gmac_add(struct eth_device *dev) 894*799e125cSJiandong Zheng { 895*799e125cSJiandong Zheng struct eth_info *eth = (struct eth_info *)(dev->priv); 896*799e125cSJiandong Zheng struct eth_dma *dma = &(eth->dma); 897*799e125cSJiandong Zheng void *tmp; 898*799e125cSJiandong Zheng 899*799e125cSJiandong Zheng /* 900*799e125cSJiandong Zheng * Desc has to be 16-byte aligned ? 901*799e125cSJiandong Zheng * If it is 8-byte aligned by malloc, fail Tx 902*799e125cSJiandong Zheng */ 903*799e125cSJiandong Zheng tmp = malloc(sizeof(dma64dd_t) * TX_BUF_NUM + 8); 904*799e125cSJiandong Zheng if (tmp == NULL) { 905*799e125cSJiandong Zheng printf("%s: Failed to allocate TX desc Buffer\n", __func__); 906*799e125cSJiandong Zheng return -1; 907*799e125cSJiandong Zheng } 908*799e125cSJiandong Zheng 909*799e125cSJiandong Zheng dma->tx_desc = (void *)tmp; 910*799e125cSJiandong Zheng dma->tx_desc_aligned = (void *)(((uint32_t)tmp) & (~0xf)); 911*799e125cSJiandong Zheng debug("TX Descriptor Buffer: %p; length: 0x%x\n", 912*799e125cSJiandong Zheng dma->tx_desc_aligned, sizeof(dma64dd_t) * TX_BUF_NUM); 913*799e125cSJiandong Zheng 914*799e125cSJiandong Zheng tmp = malloc(TX_BUF_SIZE * TX_BUF_NUM); 915*799e125cSJiandong Zheng if (tmp == NULL) { 916*799e125cSJiandong Zheng printf("%s: Failed to allocate TX Data Buffer\n", __func__); 917*799e125cSJiandong Zheng free(dma->tx_desc); 918*799e125cSJiandong Zheng return -1; 919*799e125cSJiandong Zheng } 920*799e125cSJiandong Zheng dma->tx_buf = (uint8_t *)tmp; 921*799e125cSJiandong Zheng debug("TX Data Buffer: %p; length: 0x%x\n", 922*799e125cSJiandong Zheng dma->tx_buf, TX_BUF_SIZE * TX_BUF_NUM); 923*799e125cSJiandong Zheng 924*799e125cSJiandong Zheng /* Desc has to be 16-byte aligned ? */ 925*799e125cSJiandong Zheng tmp = malloc(sizeof(dma64dd_t) * RX_BUF_NUM + 8); 926*799e125cSJiandong Zheng if (tmp == NULL) { 927*799e125cSJiandong Zheng printf("%s: Failed to allocate RX Descriptor\n", __func__); 928*799e125cSJiandong Zheng free(dma->tx_desc); 929*799e125cSJiandong Zheng free(dma->tx_buf); 930*799e125cSJiandong Zheng return -1; 931*799e125cSJiandong Zheng } 932*799e125cSJiandong Zheng dma->rx_desc = tmp; 933*799e125cSJiandong Zheng dma->rx_desc_aligned = (void *)(((uint32_t)tmp) & (~0xf)); 934*799e125cSJiandong Zheng debug("RX Descriptor Buffer: %p, length: 0x%x\n", 935*799e125cSJiandong Zheng dma->rx_desc_aligned, sizeof(dma64dd_t) * RX_BUF_NUM); 936*799e125cSJiandong Zheng 937*799e125cSJiandong Zheng tmp = malloc(RX_BUF_SIZE * RX_BUF_NUM); 938*799e125cSJiandong Zheng if (tmp == NULL) { 939*799e125cSJiandong Zheng printf("%s: Failed to allocate RX Data Buffer\n", __func__); 940*799e125cSJiandong Zheng free(dma->tx_desc); 941*799e125cSJiandong Zheng free(dma->tx_buf); 942*799e125cSJiandong Zheng free(dma->rx_desc); 943*799e125cSJiandong Zheng return -1; 944*799e125cSJiandong Zheng } 945*799e125cSJiandong Zheng dma->rx_buf = tmp; 946*799e125cSJiandong Zheng debug("RX Data Buffer: %p; length: 0x%x\n", 947*799e125cSJiandong Zheng dma->rx_buf, RX_BUF_SIZE * RX_BUF_NUM); 948*799e125cSJiandong Zheng 949*799e125cSJiandong Zheng g_dmactrlflags = 0; 950*799e125cSJiandong Zheng 951*799e125cSJiandong Zheng eth->phy_interface = PHY_INTERFACE_MODE_GMII; 952*799e125cSJiandong Zheng 953*799e125cSJiandong Zheng dma->tx_packet = gmac_tx_packet; 954*799e125cSJiandong Zheng dma->check_tx_done = gmac_check_tx_done; 955*799e125cSJiandong Zheng 956*799e125cSJiandong Zheng dma->check_rx_done = gmac_check_rx_done; 957*799e125cSJiandong Zheng 958*799e125cSJiandong Zheng dma->enable_dma = gmac_enable_dma; 959*799e125cSJiandong Zheng dma->disable_dma = gmac_disable_dma; 960*799e125cSJiandong Zheng 961*799e125cSJiandong Zheng eth->miiphy_read = gmac_miiphy_read; 962*799e125cSJiandong Zheng eth->miiphy_write = gmac_miiphy_write; 963*799e125cSJiandong Zheng 964*799e125cSJiandong Zheng eth->mac_init = gmac_mac_init; 965*799e125cSJiandong Zheng eth->disable_mac = gmac_disable; 966*799e125cSJiandong Zheng eth->enable_mac = gmac_enable; 967*799e125cSJiandong Zheng eth->set_mac_addr = gmac_set_mac_addr; 968*799e125cSJiandong Zheng eth->set_mac_speed = gmac_set_speed; 969*799e125cSJiandong Zheng 970*799e125cSJiandong Zheng return 0; 971*799e125cSJiandong Zheng } 972