1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39#include "common.h"
40#include "regs.h"
41#include "gmac.h"
42#include "elmer0.h"
43#include "suni1x10gexp_regs.h"
44
45#include <linux/crc32.h>
46#include <linux/slab.h>
47
48#define OFFSET(REG_ADDR) ((REG_ADDR) << 2)
49
50
51#define MAX_FRAME_SIZE 9600
52
53#define IPG 12
54#define TXXG_CONF1_VAL ((IPG << SUNI1x10GEXP_BITOFF_TXXG_IPGT) | \
55 SUNI1x10GEXP_BITMSK_TXXG_32BIT_ALIGN | SUNI1x10GEXP_BITMSK_TXXG_CRCEN | \
56 SUNI1x10GEXP_BITMSK_TXXG_PADEN)
57#define RXXG_CONF1_VAL (SUNI1x10GEXP_BITMSK_RXXG_PUREP | 0x14 | \
58 SUNI1x10GEXP_BITMSK_RXXG_FLCHK | SUNI1x10GEXP_BITMSK_RXXG_CRC_STRIP)
59
60
61#define STATS_TICK_SECS (15 * 60)
62
63enum {
64 RxOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW,
65 RxUnicastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_4_LOW,
66 RxMulticastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_5_LOW,
67 RxBroadcastFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_6_LOW,
68 RxPAUSEMACCtrlFramesReceived = SUNI1x10GEXP_REG_MSTAT_COUNTER_8_LOW,
69 RxFrameCheckSequenceErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_10_LOW,
70 RxFramesLostDueToInternalMACErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_11_LOW,
71 RxSymbolErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_12_LOW,
72 RxInRangeLengthErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_13_LOW,
73 RxFramesTooLongErrors = SUNI1x10GEXP_REG_MSTAT_COUNTER_15_LOW,
74 RxJabbers = SUNI1x10GEXP_REG_MSTAT_COUNTER_16_LOW,
75 RxFragments = SUNI1x10GEXP_REG_MSTAT_COUNTER_17_LOW,
76 RxUndersizedFrames = SUNI1x10GEXP_REG_MSTAT_COUNTER_18_LOW,
77 RxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_25_LOW,
78 RxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_26_LOW,
79
80 TxOctetsTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW,
81 TxFramesLostDueToInternalMACTransmissionError = SUNI1x10GEXP_REG_MSTAT_COUNTER_35_LOW,
82 TxTransmitSystemError = SUNI1x10GEXP_REG_MSTAT_COUNTER_36_LOW,
83 TxUnicastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_38_LOW,
84 TxMulticastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_40_LOW,
85 TxBroadcastFramesTransmittedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_42_LOW,
86 TxPAUSEMACCtrlFramesTransmitted = SUNI1x10GEXP_REG_MSTAT_COUNTER_43_LOW,
87 TxJumboFramesReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_51_LOW,
88 TxJumboOctetsReceivedOK = SUNI1x10GEXP_REG_MSTAT_COUNTER_52_LOW
89};
90
91struct _cmac_instance {
92 u8 enabled;
93 u8 fc;
94 u8 mac_addr[6];
95};
96
97static int pmread(struct cmac *cmac, u32 reg, u32 * data32)
98{
99 t1_tpi_read(cmac->adapter, OFFSET(reg), data32);
100 return 0;
101}
102
103static int pmwrite(struct cmac *cmac, u32 reg, u32 data32)
104{
105 t1_tpi_write(cmac->adapter, OFFSET(reg), data32);
106 return 0;
107}
108
109
110static int pm3393_reset(struct cmac *cmac)
111{
112 return 0;
113}
114
115
116
117
118
119
120
121
122
123static int pm3393_interrupt_enable(struct cmac *cmac)
124{
125 u32 pl_intr;
126
127
128
129 pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0xffff);
130 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0xffff);
131 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0xffff);
132 pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0xffff);
133
134
135 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
136 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
137 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
138 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
139
140 pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0xffff);
141 pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0xffff);
142 pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0xffff);
143 pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0xffff);
144 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0xffff);
145 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0xffff);
146 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0xffff);
147 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0xffff);
148 pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0xffff);
149
150
151
152
153 pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE,
154 0 );
155
156
157 pl_intr = readl(cmac->adapter->regs + A_PL_ENABLE);
158 pl_intr |= F_PL_INTR_EXT;
159 writel(pl_intr, cmac->adapter->regs + A_PL_ENABLE);
160 return 0;
161}
162
163static int pm3393_interrupt_disable(struct cmac *cmac)
164{
165 u32 elmer;
166
167
168 pmwrite(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_ENABLE, 0);
169 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_ENABLE, 0);
170 pmwrite(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_ENABLE, 0);
171 pmwrite(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_ENABLE, 0);
172 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_0, 0);
173 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_1, 0);
174 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_2, 0);
175 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_INTERRUPT_MASK_3, 0);
176 pmwrite(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_ENABLE, 0);
177 pmwrite(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT_MASK, 0);
178 pmwrite(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_ENABLE, 0);
179 pmwrite(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_ENABLE, 0);
180 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_3, 0);
181 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_MASK, 0);
182 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_3, 0);
183 pmwrite(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT_MASK, 0);
184 pmwrite(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_ENABLE, 0);
185
186
187 pmwrite(cmac, SUNI1x10GEXP_REG_GLOBAL_INTERRUPT_ENABLE, 0);
188
189
190 t1_tpi_read(cmac->adapter, A_ELMER0_INT_ENABLE, &elmer);
191 elmer &= ~ELMER0_GP_BIT1;
192 t1_tpi_write(cmac->adapter, A_ELMER0_INT_ENABLE, elmer);
193
194
195
196
197
198
199 return 0;
200}
201
202static int pm3393_interrupt_clear(struct cmac *cmac)
203{
204 u32 elmer;
205 u32 pl_intr;
206 u32 val32;
207
208
209
210
211 pmread(cmac, SUNI1x10GEXP_REG_SERDES_3125_INTERRUPT_STATUS, &val32);
212 pmread(cmac, SUNI1x10GEXP_REG_XRF_INTERRUPT_STATUS, &val32);
213 pmread(cmac, SUNI1x10GEXP_REG_XRF_DIAG_INTERRUPT_STATUS, &val32);
214 pmread(cmac, SUNI1x10GEXP_REG_RXOAM_INTERRUPT_STATUS, &val32);
215 pmread(cmac, SUNI1x10GEXP_REG_PL4ODP_INTERRUPT, &val32);
216 pmread(cmac, SUNI1x10GEXP_REG_XTEF_INTERRUPT_STATUS, &val32);
217 pmread(cmac, SUNI1x10GEXP_REG_IFLX_FIFO_OVERFLOW_INTERRUPT, &val32);
218 pmread(cmac, SUNI1x10GEXP_REG_TXOAM_INTERRUPT_STATUS, &val32);
219 pmread(cmac, SUNI1x10GEXP_REG_RXXG_INTERRUPT, &val32);
220 pmread(cmac, SUNI1x10GEXP_REG_TXXG_INTERRUPT, &val32);
221 pmread(cmac, SUNI1x10GEXP_REG_PL4IDU_INTERRUPT, &val32);
222 pmread(cmac, SUNI1x10GEXP_REG_EFLX_FIFO_OVERFLOW_ERROR_INDICATION,
223 &val32);
224 pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_STATUS, &val32);
225 pmread(cmac, SUNI1x10GEXP_REG_PL4IO_LOCK_DETECT_CHANGE, &val32);
226
227
228
229 pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS, &val32);
230
231
232
233 t1_tpi_read(cmac->adapter, A_ELMER0_INT_CAUSE, &elmer);
234 elmer |= ELMER0_GP_BIT1;
235 t1_tpi_write(cmac->adapter, A_ELMER0_INT_CAUSE, elmer);
236
237
238
239 pl_intr = readl(cmac->adapter->regs + A_PL_CAUSE);
240 pl_intr |= F_PL_INTR_EXT;
241 writel(pl_intr, cmac->adapter->regs + A_PL_CAUSE);
242
243 return 0;
244}
245
246
247static int pm3393_interrupt_handler(struct cmac *cmac)
248{
249 u32 master_intr_status;
250
251
252 pmread(cmac, SUNI1x10GEXP_REG_MASTER_INTERRUPT_STATUS,
253 &master_intr_status);
254 if (netif_msg_intr(cmac->adapter))
255 dev_dbg(&cmac->adapter->pdev->dev, "PM3393 intr cause 0x%x\n",
256 master_intr_status);
257
258
259 pm3393_interrupt_clear(cmac);
260
261 return 0;
262}
263
264static int pm3393_enable(struct cmac *cmac, int which)
265{
266 if (which & MAC_DIRECTION_RX)
267 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1,
268 (RXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_RXXG_RXEN));
269
270 if (which & MAC_DIRECTION_TX) {
271 u32 val = TXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_TXXG_TXEN0;
272
273 if (cmac->instance->fc & PAUSE_RX)
274 val |= SUNI1x10GEXP_BITMSK_TXXG_FCRX;
275 if (cmac->instance->fc & PAUSE_TX)
276 val |= SUNI1x10GEXP_BITMSK_TXXG_FCTX;
277 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, val);
278 }
279
280 cmac->instance->enabled |= which;
281 return 0;
282}
283
284static int pm3393_enable_port(struct cmac *cmac, int which)
285{
286
287 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
288 SUNI1x10GEXP_BITMSK_MSTAT_CLEAR);
289 udelay(2);
290 memset(&cmac->stats, 0, sizeof(struct cmac_statistics));
291
292 pm3393_enable(cmac, which);
293
294
295
296
297
298
299 t1_link_changed(cmac->adapter, 0);
300 return 0;
301}
302
303static int pm3393_disable(struct cmac *cmac, int which)
304{
305 if (which & MAC_DIRECTION_RX)
306 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1, RXXG_CONF1_VAL);
307 if (which & MAC_DIRECTION_TX)
308 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, TXXG_CONF1_VAL);
309
310
311
312
313
314 udelay(20);
315
316 cmac->instance->enabled &= ~which;
317 return 0;
318}
319
320static int pm3393_loopback_enable(struct cmac *cmac)
321{
322 return 0;
323}
324
325static int pm3393_loopback_disable(struct cmac *cmac)
326{
327 return 0;
328}
329
330static int pm3393_set_mtu(struct cmac *cmac, int mtu)
331{
332 int enabled = cmac->instance->enabled;
333
334
335 mtu += 14 + 4;
336 if (mtu > MAX_FRAME_SIZE)
337 return -EINVAL;
338
339
340 if (enabled)
341 pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
342
343 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH, mtu);
344 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE, mtu);
345
346 if (enabled)
347 pm3393_enable(cmac, enabled);
348 return 0;
349}
350
351static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm)
352{
353 int enabled = cmac->instance->enabled & MAC_DIRECTION_RX;
354 u32 rx_mode;
355
356
357 if (enabled)
358 pm3393_disable(cmac, MAC_DIRECTION_RX);
359
360 pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, &rx_mode);
361 rx_mode &= ~(SUNI1x10GEXP_BITMSK_RXXG_PMODE |
362 SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN);
363 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2,
364 (u16)rx_mode);
365
366 if (t1_rx_mode_promisc(rm)) {
367
368 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_PMODE;
369 }
370 if (t1_rx_mode_allmulti(rm)) {
371
372 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, 0xffff);
373 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, 0xffff);
374 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, 0xffff);
375 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, 0xffff);
376 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
377 } else if (t1_rx_mode_mc_cnt(rm)) {
378
379 struct netdev_hw_addr *ha;
380 int bit;
381 u16 mc_filter[4] = { 0, };
382
383 netdev_for_each_mc_addr(ha, t1_get_netdev(rm)) {
384
385 bit = (ether_crc(ETH_ALEN, ha->addr) >> 23) & 0x3f;
386 mc_filter[bit >> 4] |= 1 << (bit & 0xf);
387 }
388 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]);
389 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, mc_filter[1]);
390 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, mc_filter[2]);
391 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, mc_filter[3]);
392 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
393 }
394
395 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, (u16)rx_mode);
396
397 if (enabled)
398 pm3393_enable(cmac, MAC_DIRECTION_RX);
399
400 return 0;
401}
402
403static int pm3393_get_speed_duplex_fc(struct cmac *cmac, int *speed,
404 int *duplex, int *fc)
405{
406 if (speed)
407 *speed = SPEED_10000;
408 if (duplex)
409 *duplex = DUPLEX_FULL;
410 if (fc)
411 *fc = cmac->instance->fc;
412 return 0;
413}
414
415static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex,
416 int fc)
417{
418 if (speed >= 0 && speed != SPEED_10000)
419 return -1;
420 if (duplex >= 0 && duplex != DUPLEX_FULL)
421 return -1;
422 if (fc & ~(PAUSE_TX | PAUSE_RX))
423 return -1;
424
425 if (fc != cmac->instance->fc) {
426 cmac->instance->fc = (u8) fc;
427 if (cmac->instance->enabled & MAC_DIRECTION_TX)
428 pm3393_enable(cmac, MAC_DIRECTION_TX);
429 }
430 return 0;
431}
432
433#define RMON_UPDATE(mac, name, stat_name) \
434{ \
435 t1_tpi_read((mac)->adapter, OFFSET(name), &val0); \
436 t1_tpi_read((mac)->adapter, OFFSET((name)+1), &val1); \
437 t1_tpi_read((mac)->adapter, OFFSET((name)+2), &val2); \
438 (mac)->stats.stat_name = (u64)(val0 & 0xffff) | \
439 ((u64)(val1 & 0xffff) << 16) | \
440 ((u64)(val2 & 0xff) << 32) | \
441 ((mac)->stats.stat_name & \
442 0xffffff0000000000ULL); \
443 if (ro & \
444 (1ULL << ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2))) \
445 (mac)->stats.stat_name += 1ULL << 40; \
446}
447
448static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
449 int flag)
450{
451 u64 ro;
452 u32 val0, val1, val2, val3;
453
454
455 pmwrite(mac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
456 SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
457
458
459 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_0, &val0);
460 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_1, &val1);
461 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_2, &val2);
462 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_3, &val3);
463 ro = ((u64)val0 & 0xffff) | (((u64)val1 & 0xffff) << 16) |
464 (((u64)val2 & 0xffff) << 32) | (((u64)val3 & 0xffff) << 48);
465
466
467 RMON_UPDATE(mac, RxOctetsReceivedOK, RxOctetsOK);
468 RMON_UPDATE(mac, RxUnicastFramesReceivedOK, RxUnicastFramesOK);
469 RMON_UPDATE(mac, RxMulticastFramesReceivedOK, RxMulticastFramesOK);
470 RMON_UPDATE(mac, RxBroadcastFramesReceivedOK, RxBroadcastFramesOK);
471 RMON_UPDATE(mac, RxPAUSEMACCtrlFramesReceived, RxPauseFrames);
472 RMON_UPDATE(mac, RxFrameCheckSequenceErrors, RxFCSErrors);
473 RMON_UPDATE(mac, RxFramesLostDueToInternalMACErrors,
474 RxInternalMACRcvError);
475 RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors);
476 RMON_UPDATE(mac, RxInRangeLengthErrors, RxInRangeLengthErrors);
477 RMON_UPDATE(mac, RxFramesTooLongErrors , RxFrameTooLongErrors);
478 RMON_UPDATE(mac, RxJabbers, RxJabberErrors);
479 RMON_UPDATE(mac, RxFragments, RxRuntErrors);
480 RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors);
481 RMON_UPDATE(mac, RxJumboFramesReceivedOK, RxJumboFramesOK);
482 RMON_UPDATE(mac, RxJumboOctetsReceivedOK, RxJumboOctetsOK);
483
484
485 RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK);
486 RMON_UPDATE(mac, TxFramesLostDueToInternalMACTransmissionError,
487 TxInternalMACXmitError);
488 RMON_UPDATE(mac, TxTransmitSystemError, TxFCSErrors);
489 RMON_UPDATE(mac, TxUnicastFramesTransmittedOK, TxUnicastFramesOK);
490 RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK);
491 RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK);
492 RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames);
493 RMON_UPDATE(mac, TxJumboFramesReceivedOK, TxJumboFramesOK);
494 RMON_UPDATE(mac, TxJumboOctetsReceivedOK, TxJumboOctetsOK);
495
496 return &mac->stats;
497}
498
499static int pm3393_macaddress_get(struct cmac *cmac, u8 mac_addr[6])
500{
501 memcpy(mac_addr, cmac->instance->mac_addr, ETH_ALEN);
502 return 0;
503}
504
505static int pm3393_macaddress_set(struct cmac *cmac, u8 ma[6])
506{
507 u32 val, lo, mid, hi, enabled = cmac->instance->enabled;
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528 memcpy(cmac->instance->mac_addr, ma, ETH_ALEN);
529
530 lo = ((u32) ma[1] << 8) | (u32) ma[0];
531 mid = ((u32) ma[3] << 8) | (u32) ma[2];
532 hi = ((u32) ma[5] << 8) | (u32) ma[4];
533
534
535 if (enabled)
536 pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
537
538
539 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_15_0, lo);
540 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_31_16, mid);
541 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_47_32, hi);
542
543
544 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_15_0, lo);
545 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_31_16, mid);
546 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_47_32, hi);
547
548
549
550
551
552 pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, &val);
553 val &= 0xff0f;
554 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
555
556 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_LOW, lo);
557 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_MID, mid);
558 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_HIGH, hi);
559
560 val |= 0x0090;
561 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
562
563 if (enabled)
564 pm3393_enable(cmac, enabled);
565 return 0;
566}
567
568static void pm3393_destroy(struct cmac *cmac)
569{
570 kfree(cmac);
571}
572
573static struct cmac_ops pm3393_ops = {
574 .destroy = pm3393_destroy,
575 .reset = pm3393_reset,
576 .interrupt_enable = pm3393_interrupt_enable,
577 .interrupt_disable = pm3393_interrupt_disable,
578 .interrupt_clear = pm3393_interrupt_clear,
579 .interrupt_handler = pm3393_interrupt_handler,
580 .enable = pm3393_enable_port,
581 .disable = pm3393_disable,
582 .loopback_enable = pm3393_loopback_enable,
583 .loopback_disable = pm3393_loopback_disable,
584 .set_mtu = pm3393_set_mtu,
585 .set_rx_mode = pm3393_set_rx_mode,
586 .get_speed_duplex_fc = pm3393_get_speed_duplex_fc,
587 .set_speed_duplex_fc = pm3393_set_speed_duplex_fc,
588 .statistics_update = pm3393_update_statistics,
589 .macaddress_get = pm3393_macaddress_get,
590 .macaddress_set = pm3393_macaddress_set
591};
592
593static struct cmac *pm3393_mac_create(adapter_t *adapter, int index)
594{
595 struct cmac *cmac;
596
597 cmac = kzalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL);
598 if (!cmac)
599 return NULL;
600
601 cmac->ops = &pm3393_ops;
602 cmac->instance = (cmac_instance *) (cmac + 1);
603 cmac->adapter = adapter;
604 cmac->instance->fc = PAUSE_TX | PAUSE_RX;
605
606 t1_tpi_write(adapter, OFFSET(0x0001), 0x00008000);
607 t1_tpi_write(adapter, OFFSET(0x0001), 0x00000000);
608 t1_tpi_write(adapter, OFFSET(0x2308), 0x00009800);
609 t1_tpi_write(adapter, OFFSET(0x2305), 0x00001001);
610 t1_tpi_write(adapter, OFFSET(0x2320), 0x00008800);
611 t1_tpi_write(adapter, OFFSET(0x2321), 0x00008800);
612 t1_tpi_write(adapter, OFFSET(0x2322), 0x00008800);
613 t1_tpi_write(adapter, OFFSET(0x2323), 0x00008800);
614 t1_tpi_write(adapter, OFFSET(0x2324), 0x00008800);
615 t1_tpi_write(adapter, OFFSET(0x2325), 0x00008800);
616 t1_tpi_write(adapter, OFFSET(0x2326), 0x00008800);
617 t1_tpi_write(adapter, OFFSET(0x2327), 0x00008800);
618 t1_tpi_write(adapter, OFFSET(0x2328), 0x00008800);
619 t1_tpi_write(adapter, OFFSET(0x2329), 0x00008800);
620 t1_tpi_write(adapter, OFFSET(0x232a), 0x00008800);
621 t1_tpi_write(adapter, OFFSET(0x232b), 0x00008800);
622 t1_tpi_write(adapter, OFFSET(0x232c), 0x00008800);
623 t1_tpi_write(adapter, OFFSET(0x232d), 0x00008800);
624 t1_tpi_write(adapter, OFFSET(0x232e), 0x00008800);
625 t1_tpi_write(adapter, OFFSET(0x232f), 0x00008800);
626 t1_tpi_write(adapter, OFFSET(0x230d), 0x00009c00);
627 t1_tpi_write(adapter, OFFSET(0x2304), 0x00000202);
628
629 t1_tpi_write(adapter, OFFSET(0x3200), 0x00008080);
630 t1_tpi_write(adapter, OFFSET(0x3210), 0x00000000);
631 t1_tpi_write(adapter, OFFSET(0x3203), 0x00000000);
632 t1_tpi_write(adapter, OFFSET(0x3204), 0x00000040);
633 t1_tpi_write(adapter, OFFSET(0x3205), 0x000002cc);
634 t1_tpi_write(adapter, OFFSET(0x3206), 0x00000199);
635 t1_tpi_write(adapter, OFFSET(0x3207), 0x00000240);
636 t1_tpi_write(adapter, OFFSET(0x3202), 0x00000000);
637 t1_tpi_write(adapter, OFFSET(0x3210), 0x00000001);
638 t1_tpi_write(adapter, OFFSET(0x3208), 0x0000ffff);
639 t1_tpi_write(adapter, OFFSET(0x320a), 0x0000ffff);
640 t1_tpi_write(adapter, OFFSET(0x320c), 0x0000ffff);
641 t1_tpi_write(adapter, OFFSET(0x320e), 0x0000ffff);
642
643 t1_tpi_write(adapter, OFFSET(0x2200), 0x0000c000);
644 t1_tpi_write(adapter, OFFSET(0x2201), 0x00000000);
645 t1_tpi_write(adapter, OFFSET(0x220e), 0x00000000);
646 t1_tpi_write(adapter, OFFSET(0x220f), 0x00000100);
647 t1_tpi_write(adapter, OFFSET(0x2210), 0x00000c00);
648 t1_tpi_write(adapter, OFFSET(0x2211), 0x00000599);
649 t1_tpi_write(adapter, OFFSET(0x220d), 0x00000000);
650 t1_tpi_write(adapter, OFFSET(0x2201), 0x00000001);
651 t1_tpi_write(adapter, OFFSET(0x2203), 0x0000ffff);
652 t1_tpi_write(adapter, OFFSET(0x2205), 0x0000ffff);
653 t1_tpi_write(adapter, OFFSET(0x2209), 0x0000ffff);
654
655 t1_tpi_write(adapter, OFFSET(0x2241), 0xfffffffe);
656 t1_tpi_write(adapter, OFFSET(0x2242), 0x0000ffff);
657 t1_tpi_write(adapter, OFFSET(0x2243), 0x00000008);
658 t1_tpi_write(adapter, OFFSET(0x2244), 0x00000008);
659 t1_tpi_write(adapter, OFFSET(0x2245), 0x00000008);
660 t1_tpi_write(adapter, OFFSET(0x2240), 0x00000005);
661
662 t1_tpi_write(adapter, OFFSET(0x2280), 0x00002103);
663 t1_tpi_write(adapter, OFFSET(0x2284), 0x00000000);
664
665 t1_tpi_write(adapter, OFFSET(0x3280), 0x00000087);
666 t1_tpi_write(adapter, OFFSET(0x3282), 0x0000001f);
667
668 t1_tpi_write(adapter, OFFSET(0x3040), 0x0c32);
669
670 t1_tpi_write(adapter, OFFSET(0x304d), 0x8000);
671 t1_tpi_write(adapter, OFFSET(0x2040), 0x059c);
672 t1_tpi_write(adapter, OFFSET(0x2049), 0x0001);
673 t1_tpi_write(adapter, OFFSET(0x2070), 0x0000);
674
675
676
677 t1_tpi_write(adapter, OFFSET(0x206e), 0x0000);
678 t1_tpi_write(adapter, OFFSET(0x204a), 0xffff);
679 t1_tpi_write(adapter, OFFSET(0x204b), 0xffff);
680 t1_tpi_write(adapter, OFFSET(0x204c), 0xffff);
681 t1_tpi_write(adapter, OFFSET(0x206e), 0x0009);
682
683 t1_tpi_write(adapter, OFFSET(0x0003), 0x0000);
684 t1_tpi_write(adapter, OFFSET(0x0100), 0x0ff0);
685 t1_tpi_write(adapter, OFFSET(0x0101), 0x0f0f);
686
687 return cmac;
688}
689
690static int pm3393_mac_reset(adapter_t * adapter)
691{
692 u32 val;
693 u32 x;
694 u32 is_pl4_reset_finished;
695 u32 is_pl4_outof_lock;
696 u32 is_xaui_mabc_pll_locked;
697 u32 successful_reset;
698 int i;
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729 successful_reset = 0;
730 for (i = 0; i < 3 && !successful_reset; i++) {
731
732 t1_tpi_read(adapter, A_ELMER0_GPO, &val);
733 val &= ~1;
734 t1_tpi_write(adapter, A_ELMER0_GPO, val);
735
736
737 msleep(1);
738
739
740 msleep(1);
741
742
743 msleep(2 );
744
745
746 val |= 1;
747 t1_tpi_write(adapter, A_ELMER0_GPO, val);
748
749
750 msleep(15 );
751
752
753 msleep(1);
754
755
756
757
758 t1_tpi_read(adapter, OFFSET(SUNI1x10GEXP_REG_DEVICE_STATUS), &val);
759 is_pl4_reset_finished = (val & SUNI1x10GEXP_BITMSK_TOP_EXPIRED);
760
761
762
763
764
765 x = (SUNI1x10GEXP_BITMSK_TOP_PL4_ID_DOOL
766 |
767 SUNI1x10GEXP_BITMSK_TOP_PL4_ID_ROOL |
768 SUNI1x10GEXP_BITMSK_TOP_PL4_IS_ROOL |
769 SUNI1x10GEXP_BITMSK_TOP_PL4_OUT_ROOL);
770 is_pl4_outof_lock = (val & x);
771
772
773
774
775 is_xaui_mabc_pll_locked =
776 (val & SUNI1x10GEXP_BITMSK_TOP_SXRA_EXPIRED);
777
778 successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock
779 && is_xaui_mabc_pll_locked);
780
781 if (netif_msg_hw(adapter))
782 dev_dbg(&adapter->pdev->dev,
783 "PM3393 HW reset %d: pl4_reset 0x%x, val 0x%x, "
784 "is_pl4_outof_lock 0x%x, xaui_locked 0x%x\n",
785 i, is_pl4_reset_finished, val,
786 is_pl4_outof_lock, is_xaui_mabc_pll_locked);
787 }
788 return successful_reset ? 0 : 1;
789}
790
791const struct gmac t1_pm3393_ops = {
792 .stats_update_period = STATS_TICK_SECS,
793 .create = pm3393_mac_create,
794 .reset = pm3393_mac_reset,
795};
796