1 /******************************************************************************* 2 This is the driver for the GMAC on-chip Ethernet controller for ST SoCs. 3 DWC Ether MAC 10/100/1000 Universal version 3.41a has been used for 4 developing this code. 5 6 This contains the functions to handle the dma. 7 8 Copyright (C) 2007-2009 STMicroelectronics Ltd 9 10 This program is free software; you can redistribute it and/or modify it 11 under the terms and conditions of the GNU General Public License, 12 version 2, as published by the Free Software Foundation. 13 14 This program is distributed in the hope it will be useful, but WITHOUT 15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17 more details. 18 19 You should have received a copy of the GNU General Public License along with 20 this program; if not, write to the Free Software Foundation, Inc., 21 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 22 23 The full GNU General Public License is included in this distribution in 24 the file called "COPYING". 25 26 Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 27 *******************************************************************************/ 28 29 #include <asm/io.h> 30 #include "dwmac1000.h" 31 #include "dwmac_dma.h" 32 33 static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi) 34 { 35 u32 value = readl(ioaddr + DMA_AXI_BUS_MODE); 36 int i; 37 38 pr_info("dwmac1000: Master AXI performs %s burst length\n", 39 !(value & DMA_AXI_UNDEF) ? "fixed" : "any"); 40 41 if (axi->axi_lpi_en) 42 value |= DMA_AXI_EN_LPI; 43 if (axi->axi_xit_frm) 44 value |= DMA_AXI_LPI_XIT_FRM; 45 46 value |= (axi->axi_wr_osr_lmt & DMA_AXI_WR_OSR_LMT_MASK) << 47 DMA_AXI_WR_OSR_LMT_SHIFT; 48 49 value |= (axi->axi_rd_osr_lmt & DMA_AXI_RD_OSR_LMT_MASK) << 50 DMA_AXI_RD_OSR_LMT_SHIFT; 51 52 /* Depending on the UNDEF bit the Master AXI will perform any burst 53 * length according to the BLEN programmed (by default all BLEN are 54 * set). 55 */ 56 for (i = 0; i < AXI_BLEN; i++) { 57 switch (axi->axi_blen[i]) { 58 case 256: 59 value |= DMA_AXI_BLEN256; 60 break; 61 case 128: 62 value |= DMA_AXI_BLEN128; 63 break; 64 case 64: 65 value |= DMA_AXI_BLEN64; 66 break; 67 case 32: 68 value |= DMA_AXI_BLEN32; 69 break; 70 case 16: 71 value |= DMA_AXI_BLEN16; 72 break; 73 case 8: 74 value |= DMA_AXI_BLEN8; 75 break; 76 case 4: 77 value |= DMA_AXI_BLEN4; 78 break; 79 } 80 } 81 82 writel(value, ioaddr + DMA_AXI_BUS_MODE); 83 } 84 85 static void dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb, 86 int aal, u32 dma_tx, u32 dma_rx, int atds) 87 { 88 u32 value = readl(ioaddr + DMA_BUS_MODE); 89 90 /* 91 * Set the DMA PBL (Programmable Burst Length) mode. 92 * 93 * Note: before stmmac core 3.50 this mode bit was 4xPBL, and 94 * post 3.5 mode bit acts as 8*PBL. 95 * 96 * This configuration doesn't take care about the Separate PBL 97 * so only the bits: 13-8 are programmed with the PBL passed from the 98 * platform. 99 */ 100 value |= DMA_BUS_MODE_MAXPBL; 101 value &= ~DMA_BUS_MODE_PBL_MASK; 102 value |= (pbl << DMA_BUS_MODE_PBL_SHIFT); 103 104 /* Set the Fixed burst mode */ 105 if (fb) 106 value |= DMA_BUS_MODE_FB; 107 108 /* Mixed Burst has no effect when fb is set */ 109 if (mb) 110 value |= DMA_BUS_MODE_MB; 111 112 if (atds) 113 value |= DMA_BUS_MODE_ATDS; 114 115 if (aal) 116 value |= DMA_BUS_MODE_AAL; 117 118 writel(value, ioaddr + DMA_BUS_MODE); 119 120 /* Mask interrupts by writing to CSR7 */ 121 writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA); 122 123 /* RX/TX descriptor base address lists must be written into 124 * DMA CSR3 and CSR4, respectively 125 */ 126 writel(dma_tx, ioaddr + DMA_TX_BASE_ADDR); 127 writel(dma_rx, ioaddr + DMA_RCV_BASE_ADDR); 128 } 129 130 static u32 dwmac1000_configure_fc(u32 csr6, int rxfifosz) 131 { 132 csr6 &= ~DMA_CONTROL_RFA_MASK; 133 csr6 &= ~DMA_CONTROL_RFD_MASK; 134 135 /* Leave flow control disabled if receive fifo size is less than 136 * 4K or 0. Otherwise, send XOFF when fifo is 1K less than full, 137 * and send XON when 2K less than full. 138 */ 139 if (rxfifosz < 4096) { 140 csr6 &= ~DMA_CONTROL_EFC; 141 pr_debug("GMAC: disabling flow control, rxfifo too small(%d)\n", 142 rxfifosz); 143 } else { 144 csr6 |= DMA_CONTROL_EFC; 145 csr6 |= RFA_FULL_MINUS_1K; 146 csr6 |= RFD_FULL_MINUS_2K; 147 } 148 return csr6; 149 } 150 151 static void dwmac1000_dma_operation_mode(void __iomem *ioaddr, int txmode, 152 int rxmode, int rxfifosz) 153 { 154 u32 csr6 = readl(ioaddr + DMA_CONTROL); 155 156 if (txmode == SF_DMA_MODE) { 157 pr_debug("GMAC: enable TX store and forward mode\n"); 158 /* Transmit COE type 2 cannot be done in cut-through mode. */ 159 csr6 |= DMA_CONTROL_TSF; 160 /* Operating on second frame increase the performance 161 * especially when transmit store-and-forward is used. 162 */ 163 csr6 |= DMA_CONTROL_OSF; 164 } else { 165 pr_debug("GMAC: disabling TX SF (threshold %d)\n", txmode); 166 csr6 &= ~DMA_CONTROL_TSF; 167 csr6 &= DMA_CONTROL_TC_TX_MASK; 168 /* Set the transmit threshold */ 169 if (txmode <= 32) 170 csr6 |= DMA_CONTROL_TTC_32; 171 else if (txmode <= 64) 172 csr6 |= DMA_CONTROL_TTC_64; 173 else if (txmode <= 128) 174 csr6 |= DMA_CONTROL_TTC_128; 175 else if (txmode <= 192) 176 csr6 |= DMA_CONTROL_TTC_192; 177 else 178 csr6 |= DMA_CONTROL_TTC_256; 179 } 180 181 if (rxmode == SF_DMA_MODE) { 182 pr_debug("GMAC: enable RX store and forward mode\n"); 183 csr6 |= DMA_CONTROL_RSF; 184 } else { 185 pr_debug("GMAC: disable RX SF mode (threshold %d)\n", rxmode); 186 csr6 &= ~DMA_CONTROL_RSF; 187 csr6 &= DMA_CONTROL_TC_RX_MASK; 188 if (rxmode <= 32) 189 csr6 |= DMA_CONTROL_RTC_32; 190 else if (rxmode <= 64) 191 csr6 |= DMA_CONTROL_RTC_64; 192 else if (rxmode <= 96) 193 csr6 |= DMA_CONTROL_RTC_96; 194 else 195 csr6 |= DMA_CONTROL_RTC_128; 196 } 197 198 /* Configure flow control based on rx fifo size */ 199 csr6 = dwmac1000_configure_fc(csr6, rxfifosz); 200 201 writel(csr6, ioaddr + DMA_CONTROL); 202 } 203 204 static void dwmac1000_dump_dma_regs(void __iomem *ioaddr) 205 { 206 int i; 207 pr_info(" DMA registers\n"); 208 for (i = 0; i < 22; i++) { 209 if ((i < 9) || (i > 17)) { 210 int offset = i * 4; 211 pr_err("\t Reg No. %d (offset 0x%x): 0x%08x\n", i, 212 (DMA_BUS_MODE + offset), 213 readl(ioaddr + DMA_BUS_MODE + offset)); 214 } 215 } 216 } 217 218 static void dwmac1000_get_hw_feature(void __iomem *ioaddr, 219 struct dma_features *dma_cap) 220 { 221 u32 hw_cap = readl(ioaddr + DMA_HW_FEATURE); 222 223 dma_cap->mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL); 224 dma_cap->mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1; 225 dma_cap->half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2; 226 dma_cap->hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4; 227 dma_cap->multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5; 228 dma_cap->pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6; 229 dma_cap->sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8; 230 dma_cap->pmt_remote_wake_up = (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9; 231 dma_cap->pmt_magic_frame = (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10; 232 /* MMC */ 233 dma_cap->rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11; 234 /* IEEE 1588-2002 */ 235 dma_cap->time_stamp = 236 (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12; 237 /* IEEE 1588-2008 */ 238 dma_cap->atime_stamp = (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13; 239 /* 802.3az - Energy-Efficient Ethernet (EEE) */ 240 dma_cap->eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14; 241 dma_cap->av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15; 242 /* TX and RX csum */ 243 dma_cap->tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16; 244 dma_cap->rx_coe_type1 = (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17; 245 dma_cap->rx_coe_type2 = (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18; 246 dma_cap->rxfifo_over_2048 = (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19; 247 /* TX and RX number of channels */ 248 dma_cap->number_rx_channel = (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20; 249 dma_cap->number_tx_channel = (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22; 250 /* Alternate (enhanced) DESC mode */ 251 dma_cap->enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24; 252 } 253 254 static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt) 255 { 256 writel(riwt, ioaddr + DMA_RX_WATCHDOG); 257 } 258 259 const struct stmmac_dma_ops dwmac1000_dma_ops = { 260 .reset = dwmac_dma_reset, 261 .init = dwmac1000_dma_init, 262 .axi = dwmac1000_dma_axi, 263 .dump_regs = dwmac1000_dump_dma_regs, 264 .dma_mode = dwmac1000_dma_operation_mode, 265 .enable_dma_transmission = dwmac_enable_dma_transmission, 266 .enable_dma_irq = dwmac_enable_dma_irq, 267 .disable_dma_irq = dwmac_disable_dma_irq, 268 .start_tx = dwmac_dma_start_tx, 269 .stop_tx = dwmac_dma_stop_tx, 270 .start_rx = dwmac_dma_start_rx, 271 .stop_rx = dwmac_dma_stop_rx, 272 .dma_interrupt = dwmac_dma_interrupt, 273 .get_hw_feature = dwmac1000_get_hw_feature, 274 .rx_watchdog = dwmac1000_rx_watchdog, 275 }; 276