1 /* 2 * Copyright 2008-2012 Freescale Semiconductor Inc. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * * Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * * Redistributions in binary form must reproduce the above copyright 9 * notice, this list of conditions and the following disclaimer in the 10 * documentation and/or other materials provided with the distribution. 11 * * Neither the name of Freescale Semiconductor nor the 12 * names of its contributors may be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * 16 * ALTERNATIVELY, this software may be distributed under the terms of the 17 * GNU General Public License ("GPL") as published by the Free Software 18 * Foundation, either version 2 of that License or (at your option) any 19 * later version. 20 * 21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 34 #include "fsl_fman_tgec.h" 35 36 37 void fman_tgec_set_mac_address(struct tgec_regs *regs, uint8_t *adr) 38 { 39 uint32_t tmp0, tmp1; 40 41 tmp0 = (uint32_t)(adr[0] | 42 adr[1] << 8 | 43 adr[2] << 16 | 44 adr[3] << 24); 45 tmp1 = (uint32_t)(adr[4] | adr[5] << 8); 46 iowrite32be(tmp0, ®s->mac_addr_0); 47 iowrite32be(tmp1, ®s->mac_addr_1); 48 } 49 50 void fman_tgec_reset_stat(struct tgec_regs *regs) 51 { 52 uint32_t tmp; 53 54 tmp = ioread32be(®s->command_config); 55 56 tmp |= CMD_CFG_STAT_CLR; 57 58 iowrite32be(tmp, ®s->command_config); 59 60 while (ioread32be(®s->command_config) & CMD_CFG_STAT_CLR) ; 61 } 62 63 #define GET_TGEC_CNTR_64(bn) \ 64 (((uint64_t)ioread32be(®s->bn ## _u) << 32) | \ 65 ioread32be(®s->bn ## _l)) 66 67 uint64_t fman_tgec_get_counter(struct tgec_regs *regs, enum tgec_counters reg_name) 68 { 69 uint64_t ret_val; 70 71 switch (reg_name) { 72 case E_TGEC_COUNTER_R64: 73 ret_val = GET_TGEC_CNTR_64(r64); 74 break; 75 case E_TGEC_COUNTER_R127: 76 ret_val = GET_TGEC_CNTR_64(r127); 77 break; 78 case E_TGEC_COUNTER_R255: 79 ret_val = GET_TGEC_CNTR_64(r255); 80 break; 81 case E_TGEC_COUNTER_R511: 82 ret_val = GET_TGEC_CNTR_64(r511); 83 break; 84 case E_TGEC_COUNTER_R1023: 85 ret_val = GET_TGEC_CNTR_64(r1023); 86 break; 87 case E_TGEC_COUNTER_R1518: 88 ret_val = GET_TGEC_CNTR_64(r1518); 89 break; 90 case E_TGEC_COUNTER_R1519X: 91 ret_val = GET_TGEC_CNTR_64(r1519x); 92 break; 93 case E_TGEC_COUNTER_TRFRG: 94 ret_val = GET_TGEC_CNTR_64(trfrg); 95 break; 96 case E_TGEC_COUNTER_TRJBR: 97 ret_val = GET_TGEC_CNTR_64(trjbr); 98 break; 99 case E_TGEC_COUNTER_RDRP: 100 ret_val = GET_TGEC_CNTR_64(rdrp); 101 break; 102 case E_TGEC_COUNTER_RALN: 103 ret_val = GET_TGEC_CNTR_64(raln); 104 break; 105 case E_TGEC_COUNTER_TRUND: 106 ret_val = GET_TGEC_CNTR_64(trund); 107 break; 108 case E_TGEC_COUNTER_TROVR: 109 ret_val = GET_TGEC_CNTR_64(trovr); 110 break; 111 case E_TGEC_COUNTER_RXPF: 112 ret_val = GET_TGEC_CNTR_64(rxpf); 113 break; 114 case E_TGEC_COUNTER_TXPF: 115 ret_val = GET_TGEC_CNTR_64(txpf); 116 break; 117 case E_TGEC_COUNTER_ROCT: 118 ret_val = GET_TGEC_CNTR_64(roct); 119 break; 120 case E_TGEC_COUNTER_RMCA: 121 ret_val = GET_TGEC_CNTR_64(rmca); 122 break; 123 case E_TGEC_COUNTER_RBCA: 124 ret_val = GET_TGEC_CNTR_64(rbca); 125 break; 126 case E_TGEC_COUNTER_RPKT: 127 ret_val = GET_TGEC_CNTR_64(rpkt); 128 break; 129 case E_TGEC_COUNTER_RUCA: 130 ret_val = GET_TGEC_CNTR_64(ruca); 131 break; 132 case E_TGEC_COUNTER_RERR: 133 ret_val = GET_TGEC_CNTR_64(rerr); 134 break; 135 case E_TGEC_COUNTER_TOCT: 136 ret_val = GET_TGEC_CNTR_64(toct); 137 break; 138 case E_TGEC_COUNTER_TMCA: 139 ret_val = GET_TGEC_CNTR_64(tmca); 140 break; 141 case E_TGEC_COUNTER_TBCA: 142 ret_val = GET_TGEC_CNTR_64(tbca); 143 break; 144 case E_TGEC_COUNTER_TUCA: 145 ret_val = GET_TGEC_CNTR_64(tuca); 146 break; 147 case E_TGEC_COUNTER_TERR: 148 ret_val = GET_TGEC_CNTR_64(terr); 149 break; 150 default: 151 ret_val = 0; 152 } 153 154 return ret_val; 155 } 156 157 void fman_tgec_enable(struct tgec_regs *regs, bool apply_rx, bool apply_tx) 158 { 159 uint32_t tmp; 160 161 tmp = ioread32be(®s->command_config); 162 if (apply_rx) 163 tmp |= CMD_CFG_RX_EN; 164 if (apply_tx) 165 tmp |= CMD_CFG_TX_EN; 166 iowrite32be(tmp, ®s->command_config); 167 } 168 169 void fman_tgec_disable(struct tgec_regs *regs, bool apply_rx, bool apply_tx) 170 { 171 uint32_t tmp_reg_32; 172 173 tmp_reg_32 = ioread32be(®s->command_config); 174 if (apply_rx) 175 tmp_reg_32 &= ~CMD_CFG_RX_EN; 176 if (apply_tx) 177 tmp_reg_32 &= ~CMD_CFG_TX_EN; 178 iowrite32be(tmp_reg_32, ®s->command_config); 179 } 180 181 void fman_tgec_set_promiscuous(struct tgec_regs *regs, bool val) 182 { 183 uint32_t tmp; 184 185 tmp = ioread32be(®s->command_config); 186 if (val) 187 tmp |= CMD_CFG_PROMIS_EN; 188 else 189 tmp &= ~CMD_CFG_PROMIS_EN; 190 iowrite32be(tmp, ®s->command_config); 191 } 192 193 void fman_tgec_reset_filter_table(struct tgec_regs *regs) 194 { 195 uint32_t i; 196 for (i = 0; i < 512; i++) 197 iowrite32be(i & ~TGEC_HASH_MCAST_EN, ®s->hashtable_ctrl); 198 } 199 200 void fman_tgec_set_hash_table_entry(struct tgec_regs *regs, uint32_t crc) 201 { 202 uint32_t hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK; /* Take 9 MSB bits */ 203 iowrite32be(hash | TGEC_HASH_MCAST_EN, ®s->hashtable_ctrl); 204 } 205 206 void fman_tgec_set_hash_table(struct tgec_regs *regs, uint32_t value) 207 { 208 iowrite32be(value, ®s->hashtable_ctrl); 209 } 210 211 void fman_tgec_set_tx_pause_frames(struct tgec_regs *regs, uint16_t pause_time) 212 { 213 iowrite32be((uint32_t)pause_time, ®s->pause_quant); 214 } 215 216 void fman_tgec_set_rx_ignore_pause_frames(struct tgec_regs *regs, bool en) 217 { 218 uint32_t tmp; 219 220 tmp = ioread32be(®s->command_config); 221 if (en) 222 tmp |= CMD_CFG_PAUSE_IGNORE; 223 else 224 tmp &= ~CMD_CFG_PAUSE_IGNORE; 225 iowrite32be(tmp, ®s->command_config); 226 } 227 228 void fman_tgec_enable_1588_time_stamp(struct tgec_regs *regs, bool en) 229 { 230 uint32_t tmp; 231 232 tmp = ioread32be(®s->command_config); 233 if (en) 234 tmp |= CMD_CFG_EN_TIMESTAMP; 235 else 236 tmp &= ~CMD_CFG_EN_TIMESTAMP; 237 iowrite32be(tmp, ®s->command_config); 238 } 239 240 uint32_t fman_tgec_get_event(struct tgec_regs *regs, uint32_t ev_mask) 241 { 242 return ioread32be(®s->ievent) & ev_mask; 243 } 244 245 void fman_tgec_ack_event(struct tgec_regs *regs, uint32_t ev_mask) 246 { 247 iowrite32be(ev_mask, ®s->ievent); 248 } 249 250 uint32_t fman_tgec_get_interrupt_mask(struct tgec_regs *regs) 251 { 252 return ioread32be(®s->imask); 253 } 254 255 void fman_tgec_add_addr_in_paddr(struct tgec_regs *regs, uint8_t *adr) 256 { 257 uint32_t tmp0, tmp1; 258 259 tmp0 = (uint32_t)(adr[0] | 260 adr[1] << 8 | 261 adr[2] << 16 | 262 adr[3] << 24); 263 tmp1 = (uint32_t)(adr[4] | adr[5] << 8); 264 iowrite32be(tmp0, ®s->mac_addr_2); 265 iowrite32be(tmp1, ®s->mac_addr_3); 266 } 267 268 void fman_tgec_clear_addr_in_paddr(struct tgec_regs *regs) 269 { 270 iowrite32be(0, ®s->mac_addr_2); 271 iowrite32be(0, ®s->mac_addr_3); 272 } 273 274 uint32_t fman_tgec_get_revision(struct tgec_regs *regs) 275 { 276 return ioread32be(®s->tgec_id); 277 } 278 279 void fman_tgec_enable_interrupt(struct tgec_regs *regs, uint32_t ev_mask) 280 { 281 iowrite32be(ioread32be(®s->imask) | ev_mask, ®s->imask); 282 } 283 284 void fman_tgec_disable_interrupt(struct tgec_regs *regs, uint32_t ev_mask) 285 { 286 iowrite32be(ioread32be(®s->imask) & ~ev_mask, ®s->imask); 287 } 288 289 uint16_t fman_tgec_get_max_frame_len(struct tgec_regs *regs) 290 { 291 return (uint16_t) ioread32be(®s->maxfrm); 292 } 293 294 void fman_tgec_defconfig(struct tgec_cfg *cfg) 295 { 296 cfg->wan_mode_enable = DEFAULT_WAN_MODE_ENABLE; 297 cfg->promiscuous_mode_enable = DEFAULT_PROMISCUOUS_MODE_ENABLE; 298 cfg->pause_forward_enable = DEFAULT_PAUSE_FORWARD_ENABLE; 299 cfg->pause_ignore = DEFAULT_PAUSE_IGNORE; 300 cfg->tx_addr_ins_enable = DEFAULT_TX_ADDR_INS_ENABLE; 301 cfg->loopback_enable = DEFAULT_LOOPBACK_ENABLE; 302 cfg->cmd_frame_enable = DEFAULT_CMD_FRAME_ENABLE; 303 cfg->rx_error_discard = DEFAULT_RX_ERROR_DISCARD; 304 cfg->send_idle_enable = DEFAULT_SEND_IDLE_ENABLE; 305 cfg->no_length_check_enable = DEFAULT_NO_LENGTH_CHECK_ENABLE; 306 cfg->lgth_check_nostdr = DEFAULT_LGTH_CHECK_NOSTDR; 307 cfg->time_stamp_enable = DEFAULT_TIME_STAMP_ENABLE; 308 cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH; 309 cfg->max_frame_length = DEFAULT_MAX_FRAME_LENGTH; 310 cfg->pause_quant = DEFAULT_PAUSE_QUANT; 311 #ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 312 cfg->skip_fman11_workaround = FALSE; 313 #endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ 314 } 315 316 int fman_tgec_init(struct tgec_regs *regs, struct tgec_cfg *cfg, 317 uint32_t exception_mask) 318 { 319 uint32_t tmp; 320 321 /* Config */ 322 tmp = 0x40; /* CRC forward */ 323 if (cfg->wan_mode_enable) 324 tmp |= CMD_CFG_WAN_MODE; 325 if (cfg->promiscuous_mode_enable) 326 tmp |= CMD_CFG_PROMIS_EN; 327 if (cfg->pause_forward_enable) 328 tmp |= CMD_CFG_PAUSE_FWD; 329 if (cfg->pause_ignore) 330 tmp |= CMD_CFG_PAUSE_IGNORE; 331 if (cfg->tx_addr_ins_enable) 332 tmp |= CMD_CFG_TX_ADDR_INS; 333 if (cfg->loopback_enable) 334 tmp |= CMD_CFG_LOOPBACK_EN; 335 if (cfg->cmd_frame_enable) 336 tmp |= CMD_CFG_CMD_FRM_EN; 337 if (cfg->rx_error_discard) 338 tmp |= CMD_CFG_RX_ER_DISC; 339 if (cfg->send_idle_enable) 340 tmp |= CMD_CFG_SEND_IDLE; 341 if (cfg->no_length_check_enable) 342 tmp |= CMD_CFG_NO_LEN_CHK; 343 if (cfg->time_stamp_enable) 344 tmp |= CMD_CFG_EN_TIMESTAMP; 345 iowrite32be(tmp, ®s->command_config); 346 347 /* Max Frame Length */ 348 iowrite32be((uint32_t)cfg->max_frame_length, ®s->maxfrm); 349 /* Pause Time */ 350 iowrite32be(cfg->pause_quant, ®s->pause_quant); 351 352 /* clear all pending events and set-up interrupts */ 353 fman_tgec_ack_event(regs, 0xffffffff); 354 fman_tgec_enable_interrupt(regs, exception_mask); 355 356 return 0; 357 } 358 359 void fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(struct tgec_regs *regs) 360 { 361 uint32_t tmp; 362 363 /* restore the default tx ipg Length */ 364 tmp = (ioread32be(®s->tx_ipg_len) & ~TGEC_TX_IPG_LENGTH_MASK) | 12; 365 366 iowrite32be(tmp, ®s->tx_ipg_len); 367 } 368