0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #include "common.h"
0031 #include "regs.h"
0032 #include "gmac.h"
0033 #include "elmer0.h"
0034 #include "suni1x10gexp_regs.h"
0035
0036 #include <linux/crc32.h>
0037 #include <linux/slab.h>
0038
0039 #define OFFSET(REG_ADDR) ((REG_ADDR) << 2)
0040
0041 #define IPG 12
0042 #define TXXG_CONF1_VAL ((IPG << SUNI1x10GEXP_BITOFF_TXXG_IPGT) | \
0043 SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN | SUNI1x10GEXP_BITMSK_TXXG_CRCEN | \
0044 SUNI1x10GEXP_BITMSK_TXXG_PADEN)
0045 #define RXXG_CONF1_VAL (SUNI1x10GEXP_BITMSK_RXXG_PUREP | 0x14 | \
0046 SUNI1x10GEXP_BITMSK_RXXG_FLCHK | SUNI1x10GEXP_BITMSK_RXXG_CRC_STRIP)
0047
0048
0049 #define STATS_TICK_SECS (15 * 60)
0050
0051 enum {
0052 RxOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW,
0053 RxUnicastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_4_LOW,
0054 RxMulticastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_5_LOW,
0055 RxBroadcastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_6_LOW,
0056 RxPAUSEMACCtrlFramesReceived = SUNI1x10GEXP_REG_MSTAT_COUNTER_8_LOW,
0057 RxFrameCheckSequenceErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_10_LOW,
0058 RxFramesLostDueToInternalMACErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_11_LOW,
0059 RxSymbolErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_12_LOW,
0060 RxInRangeLengthErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_13_LOW,
0061 RxFramesTooLongErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_15_LOW,
0062 RxJabbers = SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW,
0063 RxFragments = SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW,
0064 RxUndersizedFrames = SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW,
0065 RxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_25_LOW,
0066 RxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_26_LOW,
0067
0068 TxOctetsTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW,
0069 TxFramesLostDueToInternalMACTransmissionError = SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW,
0070 TxTransmitSystemError = SUNI1x10GEXP_REG_MSTAT_COUNTER_36_LOW,
0071 TxUnicastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW,
0072 TxMulticastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW,
0073 TxBroadcastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW,
0074 TxPAUSEMACCtrlFramesTransmitted = SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW,
0075 TxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_51_LOW,
0076 TxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_52_LOW
0077 };
0078
0079 struct _cmac_instance {
0080 u8 enabled;
0081 u8 fc;
0082 u8 mac_addr[6];
0083 };
0084
0085 static int pmread(struct cmac *cmac, u32 reg, u32 * data32)
0086 {
0087 t1_tpi_read(cmac->adapter, OFFSET(reg), data32);
0088 return 0;
0089 }
0090
0091 static int pmwrite(struct cmac *cmac, u32 reg, u32 data32)
0092 {
0093 t1_tpi_write(cmac->adapter, OFFSET(reg), data32);
0094 return 0;
0095 }
0096
0097
0098 static int pm3393_reset(struct cmac *cmac)
0099 {
0100 return 0;
0101 }
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111 static int pm3393_interrupt_enable(struct cmac *cmac)
0112 {
0113 u32 pl_intr;
0114
0115
0116
0117 pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0xffff);
0118 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0xffff);
0119 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0xffff);
0120 pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0xffff);
0121
0122
0123 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
0124 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
0125 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
0126 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
0127
0128 pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0xffff);
0129 pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0xffff);
0130 pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0xffff);
0131 pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0xffff);
0132 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0xffff);
0133 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0xffff);
0134 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0xffff);
0135 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0xffff);
0136 pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0xffff);
0137
0138
0139
0140
0141 pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE,
0142 0 );
0143
0144
0145 pl_intr = readl(cmac->adapter->regs + A_PL_ENABLE);
0146 pl_intr |= F_PL_INTR_EXT;
0147 writel(pl_intr, cmac->adapter->regs + A_PL_ENABLE);
0148 return 0;
0149 }
0150
0151 static int pm3393_interrupt_disable(struct cmac *cmac)
0152 {
0153 u32 elmer;
0154
0155
0156 pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0);
0157 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0);
0158 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0);
0159 pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0);
0160 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
0161 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
0162 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
0163 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
0164 pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0);
0165 pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0);
0166 pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0);
0167 pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0);
0168 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0);
0169 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0);
0170 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0);
0171 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0);
0172 pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0);
0173
0174
0175 pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE, 0);
0176
0177
0178 t1_tpi_read(cmac->adapter, A_ELMER0_INT_ENABLE, &elmer);
0179 elmer &= ~ELMER0_GP_BIT1;
0180 t1_tpi_write(cmac->adapter, A_ELMER0_INT_ENABLE, elmer);
0181
0182
0183
0184
0185
0186
0187 return 0;
0188 }
0189
0190 static int pm3393_interrupt_clear(struct cmac *cmac)
0191 {
0192 u32 elmer;
0193 u32 pl_intr;
0194 u32 val32;
0195
0196
0197
0198
0199 pmread(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_STATUS, &val32);
0200 pmread(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_STATUS, &val32);
0201 pmread(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_STATUS, &val32);
0202 pmread(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_STATUS, &val32);
0203 pmread(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT, &val32);
0204 pmread(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_STATUS, &val32);
0205 pmread(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_INTERRUPT, &val32);
0206 pmread(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_STATUS, &val32);
0207 pmread(cmac, SUNI1x10GEXP_REG_RXXG_INTERRUPT, &val32);
0208 pmread(cmac, SUNI1x10GEXP_REG_TXXG_INTERRUPT, &val32);
0209 pmread(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT, &val32);
0210 pmread(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_INDICATION,
0211 &val32);
0212 pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_STATUS, &val32);
0213 pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_CHANGE, &val32);
0214
0215
0216
0217 pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS, &val32);
0218
0219
0220
0221 t1_tpi_read(cmac->adapter, A_ELMER0_INT_CAUSE, &elmer);
0222 elmer |= ELMER0_GP_BIT1;
0223 t1_tpi_write(cmac->adapter, A_ELMER0_INT_CAUSE, elmer);
0224
0225
0226
0227 pl_intr = readl(cmac->adapter->regs + A_PL_CAUSE);
0228 pl_intr |= F_PL_INTR_EXT;
0229 writel(pl_intr, cmac->adapter->regs + A_PL_CAUSE);
0230
0231 return 0;
0232 }
0233
0234
0235 static int pm3393_interrupt_handler(struct cmac *cmac)
0236 {
0237 u32 master_intr_status;
0238
0239
0240 pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS,
0241 &master_intr_status);
0242 if (netif_msg_intr(cmac->adapter))
0243 dev_dbg(&cmac->adapter->pdev->dev, "PM3393 intr cause 0x%x\n",
0244 master_intr_status);
0245
0246
0247 pm3393_interrupt_clear(cmac);
0248
0249 return 0;
0250 }
0251
0252 static int pm3393_enable(struct cmac *cmac, int which)
0253 {
0254 if (which & MAC_DIRECTION_RX)
0255 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1,
0256 (RXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_RXXG_RXEN));
0257
0258 if (which & MAC_DIRECTION_TX) {
0259 u32 val = TXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_TXXG_TXEN0;
0260
0261 if (cmac->instance->fc & PAUSE_RX)
0262 val |= SUNI1x10GEXP_BITMSK_TXXG_FCRX;
0263 if (cmac->instance->fc & PAUSE_TX)
0264 val |= SUNI1x10GEXP_BITMSK_TXXG_FCTX;
0265 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, val);
0266 }
0267
0268 cmac->instance->enabled |= which;
0269 return 0;
0270 }
0271
0272 static int pm3393_enable_port(struct cmac *cmac, int which)
0273 {
0274
0275 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
0276 SUNI1x10GEXP_BITMSK_MSTAT_CLEAR);
0277 udelay(2);
0278 memset(&cmac->stats, 0, sizeof(struct cmac_statistics));
0279
0280 pm3393_enable(cmac, which);
0281
0282
0283
0284
0285
0286
0287 t1_link_changed(cmac->adapter, 0);
0288 return 0;
0289 }
0290
0291 static int pm3393_disable(struct cmac *cmac, int which)
0292 {
0293 if (which & MAC_DIRECTION_RX)
0294 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1, RXXG_CONF1_VAL);
0295 if (which & MAC_DIRECTION_TX)
0296 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, TXXG_CONF1_VAL);
0297
0298
0299
0300
0301
0302 udelay(20);
0303
0304 cmac->instance->enabled &= ~which;
0305 return 0;
0306 }
0307
0308 static int pm3393_loopback_enable(struct cmac *cmac)
0309 {
0310 return 0;
0311 }
0312
0313 static int pm3393_loopback_disable(struct cmac *cmac)
0314 {
0315 return 0;
0316 }
0317
0318 static int pm3393_set_mtu(struct cmac *cmac, int mtu)
0319 {
0320 int enabled = cmac->instance->enabled;
0321
0322 mtu += ETH_HLEN + ETH_FCS_LEN;
0323
0324
0325 if (enabled)
0326 pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
0327
0328 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH, mtu);
0329 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE, mtu);
0330
0331 if (enabled)
0332 pm3393_enable(cmac, enabled);
0333 return 0;
0334 }
0335
0336 static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm)
0337 {
0338 int enabled = cmac->instance->enabled & MAC_DIRECTION_RX;
0339 u32 rx_mode;
0340
0341
0342 if (enabled)
0343 pm3393_disable(cmac, MAC_DIRECTION_RX);
0344
0345 pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, &rx_mode);
0346 rx_mode &= ~(SUNI1x10GEXP_BITMSK_RXXG_PMODE |
0347 SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN);
0348 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2,
0349 (u16)rx_mode);
0350
0351 if (t1_rx_mode_promisc(rm)) {
0352
0353 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_PMODE;
0354 }
0355 if (t1_rx_mode_allmulti(rm)) {
0356
0357 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, 0xffff);
0358 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, 0xffff);
0359 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, 0xffff);
0360 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, 0xffff);
0361 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
0362 } else if (t1_rx_mode_mc_cnt(rm)) {
0363
0364 struct netdev_hw_addr *ha;
0365 int bit;
0366 u16 mc_filter[4] = { 0, };
0367
0368 netdev_for_each_mc_addr(ha, t1_get_netdev(rm)) {
0369
0370 bit = (ether_crc(ETH_ALEN, ha->addr) >> 23) & 0x3f;
0371 mc_filter[bit >> 4] |= 1 << (bit & 0xf);
0372 }
0373 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]);
0374 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, mc_filter[1]);
0375 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, mc_filter[2]);
0376 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, mc_filter[3]);
0377 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
0378 }
0379
0380 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, (u16)rx_mode);
0381
0382 if (enabled)
0383 pm3393_enable(cmac, MAC_DIRECTION_RX);
0384
0385 return 0;
0386 }
0387
0388 static int pm3393_get_speed_duplex_fc(struct cmac *cmac, int *speed,
0389 int *duplex, int *fc)
0390 {
0391 if (speed)
0392 *speed = SPEED_10000;
0393 if (duplex)
0394 *duplex = DUPLEX_FULL;
0395 if (fc)
0396 *fc = cmac->instance->fc;
0397 return 0;
0398 }
0399
0400 static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex,
0401 int fc)
0402 {
0403 if (speed >= 0 && speed != SPEED_10000)
0404 return -1;
0405 if (duplex >= 0 && duplex != DUPLEX_FULL)
0406 return -1;
0407 if (fc & ~(PAUSE_TX | PAUSE_RX))
0408 return -1;
0409
0410 if (fc != cmac->instance->fc) {
0411 cmac->instance->fc = (u8) fc;
0412 if (cmac->instance->enabled & MAC_DIRECTION_TX)
0413 pm3393_enable(cmac, MAC_DIRECTION_TX);
0414 }
0415 return 0;
0416 }
0417
0418 #define RMON_UPDATE(mac, name, stat_name) \
0419 { \
0420 t1_tpi_read((mac)->adapter, OFFSET(name), &val0); \
0421 t1_tpi_read((mac)->adapter, OFFSET((name)+1), &val1); \
0422 t1_tpi_read((mac)->adapter, OFFSET((name)+2), &val2); \
0423 (mac)->stats.stat_name = (u64)(val0 & 0xffff) | \
0424 ((u64)(val1 & 0xffff) << 16) | \
0425 ((u64)(val2 & 0xff) << 32) | \
0426 ((mac)->stats.stat_name & \
0427 0xffffff0000000000ULL); \
0428 if (ro & \
0429 (1ULL << ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2))) \
0430 (mac)->stats.stat_name += 1ULL << 40; \
0431 }
0432
0433 static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
0434 int flag)
0435 {
0436 u64 ro;
0437 u32 val0, val1, val2, val3;
0438
0439
0440 pmwrite(mac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
0441 SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
0442
0443
0444 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_0, &val0);
0445 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_1, &val1);
0446 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_2, &val2);
0447 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_3, &val3);
0448 ro = ((u64)val0 & 0xffff) | (((u64)val1 & 0xffff) << 16) |
0449 (((u64)val2 & 0xffff) << 32) | (((u64)val3 & 0xffff) << 48);
0450
0451
0452 RMON_UPDATE(mac, RxOctetsReceivedOK, RxOctetsOK);
0453 RMON_UPDATE(mac, RxUnicastFramesReceivedOK, RxUnicastFramesOK);
0454 RMON_UPDATE(mac, RxMulticastFramesReceivedOK, RxMulticastFramesOK);
0455 RMON_UPDATE(mac, RxBroadcastFramesReceivedOK, RxBroadcastFramesOK);
0456 RMON_UPDATE(mac, RxPAUSEMACCtrlFramesReceived, RxPauseFrames);
0457 RMON_UPDATE(mac, RxFrameCheckSequenceErrors, RxFCSErrors);
0458 RMON_UPDATE(mac, RxFramesLostDueToInternalMACErrors,
0459 RxInternalMACRcvError);
0460 RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors);
0461 RMON_UPDATE(mac, RxInRangeLengthErrors, RxInRangeLengthErrors);
0462 RMON_UPDATE(mac, RxFramesTooLongErrors , RxFrameTooLongErrors);
0463 RMON_UPDATE(mac, RxJabbers, RxJabberErrors);
0464 RMON_UPDATE(mac, RxFragments, RxRuntErrors);
0465 RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors);
0466 RMON_UPDATE(mac, RxJumboFramesReceivedOK, RxJumboFramesOK);
0467 RMON_UPDATE(mac, RxJumboOctetsReceivedOK, RxJumboOctetsOK);
0468
0469
0470 RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK);
0471 RMON_UPDATE(mac, TxFramesLostDueToInternalMACTransmissionError,
0472 TxInternalMACXmitError);
0473 RMON_UPDATE(mac, TxTransmitSystemError, TxFCSErrors);
0474 RMON_UPDATE(mac, TxUnicastFramesTransmittedOK, TxUnicastFramesOK);
0475 RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK);
0476 RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK);
0477 RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames);
0478 RMON_UPDATE(mac, TxJumboFramesReceivedOK, TxJumboFramesOK);
0479 RMON_UPDATE(mac, TxJumboOctetsReceivedOK, TxJumboOctetsOK);
0480
0481 return &mac->stats;
0482 }
0483
0484 static int pm3393_macaddress_get(struct cmac *cmac, u8 mac_addr[6])
0485 {
0486 memcpy(mac_addr, cmac->instance->mac_addr, ETH_ALEN);
0487 return 0;
0488 }
0489
0490 static int pm3393_macaddress_set(struct cmac *cmac, const u8 ma[6])
0491 {
0492 u32 val, lo, mid, hi, enabled = cmac->instance->enabled;
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513 memcpy(cmac->instance->mac_addr, ma, ETH_ALEN);
0514
0515 lo = ((u32) ma[1] << 8) | (u32) ma[0];
0516 mid = ((u32) ma[3] << 8) | (u32) ma[2];
0517 hi = ((u32) ma[5] << 8) | (u32) ma[4];
0518
0519
0520 if (enabled)
0521 pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
0522
0523
0524 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_15_0, lo);
0525 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_31_16, mid);
0526 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_47_32, hi);
0527
0528
0529 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_15_0, lo);
0530 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_31_16, mid);
0531 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_47_32, hi);
0532
0533
0534
0535
0536
0537 pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, &val);
0538 val &= 0xff0f;
0539 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
0540
0541 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_LOW, lo);
0542 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_MID, mid);
0543 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_HIGH, hi);
0544
0545 val |= 0x0090;
0546 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
0547
0548 if (enabled)
0549 pm3393_enable(cmac, enabled);
0550 return 0;
0551 }
0552
0553 static void pm3393_destroy(struct cmac *cmac)
0554 {
0555 kfree(cmac);
0556 }
0557
0558 static const struct cmac_ops pm3393_ops = {
0559 .destroy = pm3393_destroy,
0560 .reset = pm3393_reset,
0561 .interrupt_enable = pm3393_interrupt_enable,
0562 .interrupt_disable = pm3393_interrupt_disable,
0563 .interrupt_clear = pm3393_interrupt_clear,
0564 .interrupt_handler = pm3393_interrupt_handler,
0565 .enable = pm3393_enable_port,
0566 .disable = pm3393_disable,
0567 .loopback_enable = pm3393_loopback_enable,
0568 .loopback_disable = pm3393_loopback_disable,
0569 .set_mtu = pm3393_set_mtu,
0570 .set_rx_mode = pm3393_set_rx_mode,
0571 .get_speed_duplex_fc = pm3393_get_speed_duplex_fc,
0572 .set_speed_duplex_fc = pm3393_set_speed_duplex_fc,
0573 .statistics_update = pm3393_update_statistics,
0574 .macaddress_get = pm3393_macaddress_get,
0575 .macaddress_set = pm3393_macaddress_set
0576 };
0577
0578 static struct cmac *pm3393_mac_create(adapter_t *adapter, int index)
0579 {
0580 struct cmac *cmac;
0581
0582 cmac = kzalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL);
0583 if (!cmac)
0584 return NULL;
0585
0586 cmac->ops = &pm3393_ops;
0587 cmac->instance = (cmac_instance *) (cmac + 1);
0588 cmac->adapter = adapter;
0589 cmac->instance->fc = PAUSE_TX | PAUSE_RX;
0590
0591 t1_tpi_write(adapter, OFFSET(0x0001), 0x00008000);
0592 t1_tpi_write(adapter, OFFSET(0x0001), 0x00000000);
0593 t1_tpi_write(adapter, OFFSET(0x2308), 0x00009800);
0594 t1_tpi_write(adapter, OFFSET(0x2305), 0x00001001);
0595 t1_tpi_write(adapter, OFFSET(0x2320), 0x00008800);
0596 t1_tpi_write(adapter, OFFSET(0x2321), 0x00008800);
0597 t1_tpi_write(adapter, OFFSET(0x2322), 0x00008800);
0598 t1_tpi_write(adapter, OFFSET(0x2323), 0x00008800);
0599 t1_tpi_write(adapter, OFFSET(0x2324), 0x00008800);
0600 t1_tpi_write(adapter, OFFSET(0x2325), 0x00008800);
0601 t1_tpi_write(adapter, OFFSET(0x2326), 0x00008800);
0602 t1_tpi_write(adapter, OFFSET(0x2327), 0x00008800);
0603 t1_tpi_write(adapter, OFFSET(0x2328), 0x00008800);
0604 t1_tpi_write(adapter, OFFSET(0x2329), 0x00008800);
0605 t1_tpi_write(adapter, OFFSET(0x232a), 0x00008800);
0606 t1_tpi_write(adapter, OFFSET(0x232b), 0x00008800);
0607 t1_tpi_write(adapter, OFFSET(0x232c), 0x00008800);
0608 t1_tpi_write(adapter, OFFSET(0x232d), 0x00008800);
0609 t1_tpi_write(adapter, OFFSET(0x232e), 0x00008800);
0610 t1_tpi_write(adapter, OFFSET(0x232f), 0x00008800);
0611 t1_tpi_write(adapter, OFFSET(0x230d), 0x00009c00);
0612 t1_tpi_write(adapter, OFFSET(0x2304), 0x00000202);
0613
0614 t1_tpi_write(adapter, OFFSET(0x3200), 0x00008080);
0615 t1_tpi_write(adapter, OFFSET(0x3210), 0x00000000);
0616 t1_tpi_write(adapter, OFFSET(0x3203), 0x00000000);
0617 t1_tpi_write(adapter, OFFSET(0x3204), 0x00000040);
0618 t1_tpi_write(adapter, OFFSET(0x3205), 0x000002cc);
0619 t1_tpi_write(adapter, OFFSET(0x3206), 0x00000199);
0620 t1_tpi_write(adapter, OFFSET(0x3207), 0x00000240);
0621 t1_tpi_write(adapter, OFFSET(0x3202), 0x00000000);
0622 t1_tpi_write(adapter, OFFSET(0x3210), 0x00000001);
0623 t1_tpi_write(adapter, OFFSET(0x3208), 0x0000ffff);
0624 t1_tpi_write(adapter, OFFSET(0x320a), 0x0000ffff);
0625 t1_tpi_write(adapter, OFFSET(0x320c), 0x0000ffff);
0626 t1_tpi_write(adapter, OFFSET(0x320e), 0x0000ffff);
0627
0628 t1_tpi_write(adapter, OFFSET(0x2200), 0x0000c000);
0629 t1_tpi_write(adapter, OFFSET(0x2201), 0x00000000);
0630 t1_tpi_write(adapter, OFFSET(0x220e), 0x00000000);
0631 t1_tpi_write(adapter, OFFSET(0x220f), 0x00000100);
0632 t1_tpi_write(adapter, OFFSET(0x2210), 0x00000c00);
0633 t1_tpi_write(adapter, OFFSET(0x2211), 0x00000599);
0634 t1_tpi_write(adapter, OFFSET(0x220d), 0x00000000);
0635 t1_tpi_write(adapter, OFFSET(0x2201), 0x00000001);
0636 t1_tpi_write(adapter, OFFSET(0x2203), 0x0000ffff);
0637 t1_tpi_write(adapter, OFFSET(0x2205), 0x0000ffff);
0638 t1_tpi_write(adapter, OFFSET(0x2209), 0x0000ffff);
0639
0640 t1_tpi_write(adapter, OFFSET(0x2241), 0xfffffffe);
0641 t1_tpi_write(adapter, OFFSET(0x2242), 0x0000ffff);
0642 t1_tpi_write(adapter, OFFSET(0x2243), 0x00000008);
0643 t1_tpi_write(adapter, OFFSET(0x2244), 0x00000008);
0644 t1_tpi_write(adapter, OFFSET(0x2245), 0x00000008);
0645 t1_tpi_write(adapter, OFFSET(0x2240), 0x00000005);
0646
0647 t1_tpi_write(adapter, OFFSET(0x2280), 0x00002103);
0648 t1_tpi_write(adapter, OFFSET(0x2284), 0x00000000);
0649
0650 t1_tpi_write(adapter, OFFSET(0x3280), 0x00000087);
0651 t1_tpi_write(adapter, OFFSET(0x3282), 0x0000001f);
0652
0653 t1_tpi_write(adapter, OFFSET(0x3040), 0x0c32);
0654
0655 t1_tpi_write(adapter, OFFSET(0x304d), 0x8000);
0656 t1_tpi_write(adapter, OFFSET(0x2040), 0x059c);
0657 t1_tpi_write(adapter, OFFSET(0x2049), 0x0001);
0658 t1_tpi_write(adapter, OFFSET(0x2070), 0x0000);
0659
0660
0661
0662 t1_tpi_write(adapter, OFFSET(0x206e), 0x0000);
0663 t1_tpi_write(adapter, OFFSET(0x204a), 0xffff);
0664 t1_tpi_write(adapter, OFFSET(0x204b), 0xffff);
0665 t1_tpi_write(adapter, OFFSET(0x204c), 0xffff);
0666 t1_tpi_write(adapter, OFFSET(0x206e), 0x0009);
0667
0668 t1_tpi_write(adapter, OFFSET(0x0003), 0x0000);
0669 t1_tpi_write(adapter, OFFSET(0x0100), 0x0ff0);
0670 t1_tpi_write(adapter, OFFSET(0x0101), 0x0f0f);
0671
0672 return cmac;
0673 }
0674
0675 static int pm3393_mac_reset(adapter_t * adapter)
0676 {
0677 u32 val;
0678 u32 x;
0679 u32 is_pl4_reset_finished;
0680 u32 is_pl4_outof_lock;
0681 u32 is_xaui_mabc_pll_locked;
0682 u32 successful_reset;
0683 int i;
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714 successful_reset = 0;
0715 for (i = 0; i < 3 && !successful_reset; i++) {
0716
0717 t1_tpi_read(adapter, A_ELMER0_GPO, &val);
0718 val &= ~1;
0719 t1_tpi_write(adapter, A_ELMER0_GPO, val);
0720
0721
0722 msleep(1);
0723
0724
0725 msleep(1);
0726
0727
0728 msleep(2 );
0729
0730
0731 val |= 1;
0732 t1_tpi_write(adapter, A_ELMER0_GPO, val);
0733
0734
0735 msleep(15 );
0736
0737
0738 msleep(1);
0739
0740
0741
0742
0743 t1_tpi_read(adapter, OFFSET(SUNI1x10GEXP_REG_DEVICE_STATUS), &val);
0744 is_pl4_reset_finished = (val & SUNI1x10GEXP_BITMSK_TOP_EXPIRED);
0745
0746
0747
0748
0749
0750 x = (SUNI1x10GEXP_BITMSK_TOP_PL4_ID_DOOL
0751 |
0752 SUNI1x10GEXP_BITMSK_TOP_PL4_ID_ROOL |
0753 SUNI1x10GEXP_BITMSK_TOP_PL4_IS_ROOL |
0754 SUNI1x10GEXP_BITMSK_TOP_PL4_OUT_ROOL);
0755 is_pl4_outof_lock = (val & x);
0756
0757
0758
0759
0760 is_xaui_mabc_pll_locked =
0761 (val & SUNI1x10GEXP_BITMSK_TOP_SXRA_EXPIRED);
0762
0763 successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock
0764 && is_xaui_mabc_pll_locked);
0765
0766 if (netif_msg_hw(adapter))
0767 dev_dbg(&adapter->pdev->dev,
0768 "PM3393 HW reset %d: pl4_reset 0x%x, val 0x%x, "
0769 "is_pl4_outof_lock 0x%x, xaui_locked 0x%x\n",
0770 i, is_pl4_reset_finished, val,
0771 is_pl4_outof_lock, is_xaui_mabc_pll_locked);
0772 }
0773 return successful_reset ? 0 : 1;
0774 }
0775
0776 const struct gmac t1_pm3393_ops = {
0777 .stats_update_period = STATS_TICK_SECS,
0778 .create = pm3393_mac_create,
0779 .reset = pm3393_mac_reset,
0780 };