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