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
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 CH_DBG(cmac->adapter, INTR, "PM3393 intr cause 0x%x\n",
255 master_intr_status);
256
257
258 pm3393_interrupt_clear(cmac);
259
260 return 0;
261}
262
263static int pm3393_enable(struct cmac *cmac, int which)
264{
265 if (which & MAC_DIRECTION_RX)
266 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1,
267 (RXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_RXXG_RXEN));
268
269 if (which & MAC_DIRECTION_TX) {
270 u32 val = TXXG_CONF1_VAL | SUNI1x10GEXP_BITMSK_TXXG_TXEN0;
271
272 if (cmac->instance->fc & PAUSE_RX)
273 val |= SUNI1x10GEXP_BITMSK_TXXG_FCRX;
274 if (cmac->instance->fc & PAUSE_TX)
275 val |= SUNI1x10GEXP_BITMSK_TXXG_FCTX;
276 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, val);
277 }
278
279 cmac->instance->enabled |= which;
280 return 0;
281}
282
283static int pm3393_enable_port(struct cmac *cmac, int which)
284{
285
286 pmwrite(cmac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
287 SUNI1x10GEXP_BITMSK_MSTAT_CLEAR);
288 udelay(2);
289 memset(&cmac->stats, 0, sizeof(struct cmac_statistics));
290
291 pm3393_enable(cmac, which);
292
293
294
295
296
297
298 t1_link_changed(cmac->adapter, 0);
299 return 0;
300}
301
302static int pm3393_disable(struct cmac *cmac, int which)
303{
304 if (which & MAC_DIRECTION_RX)
305 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_CONFIG_1, RXXG_CONF1_VAL);
306 if (which & MAC_DIRECTION_TX)
307 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_CONFIG_1, TXXG_CONF1_VAL);
308
309
310
311
312
313 udelay(20);
314
315 cmac->instance->enabled &= ~which;
316 return 0;
317}
318
319static int pm3393_loopback_enable(struct cmac *cmac)
320{
321 return 0;
322}
323
324static int pm3393_loopback_disable(struct cmac *cmac)
325{
326 return 0;
327}
328
329static int pm3393_set_mtu(struct cmac *cmac, int mtu)
330{
331 int enabled = cmac->instance->enabled;
332
333
334 mtu += 14 + 4;
335 if (mtu > MAX_FRAME_SIZE)
336 return -EINVAL;
337
338
339 if (enabled)
340 pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
341
342 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MAX_FRAME_LENGTH, mtu);
343 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_MAX_FRAME_SIZE, mtu);
344
345 if (enabled)
346 pm3393_enable(cmac, enabled);
347 return 0;
348}
349
350static int pm3393_set_rx_mode(struct cmac *cmac, struct t1_rx_mode *rm)
351{
352 int enabled = cmac->instance->enabled & MAC_DIRECTION_RX;
353 u32 rx_mode;
354
355
356 if (enabled)
357 pm3393_disable(cmac, MAC_DIRECTION_RX);
358
359 pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, &rx_mode);
360 rx_mode &= ~(SUNI1x10GEXP_BITMSK_RXXG_PMODE |
361 SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN);
362 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2,
363 (u16)rx_mode);
364
365 if (t1_rx_mode_promisc(rm)) {
366
367 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_PMODE;
368 }
369 if (t1_rx_mode_allmulti(rm)) {
370
371 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, 0xffff);
372 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, 0xffff);
373 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, 0xffff);
374 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, 0xffff);
375 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
376 } else if (t1_rx_mode_mc_cnt(rm)) {
377
378 u8 *addr;
379 int bit;
380 u16 mc_filter[4] = { 0, };
381
382 while ((addr = t1_get_next_mcaddr(rm))) {
383 bit = (ether_crc(ETH_ALEN, addr) >> 23) & 0x3f;
384 mc_filter[bit >> 4] |= 1 << (bit & 0xf);
385 }
386 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_LOW, mc_filter[0]);
387 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDLOW, mc_filter[1]);
388 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_MIDHIGH, mc_filter[2]);
389 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_MULTICAST_HASH_HIGH, mc_filter[3]);
390 rx_mode |= SUNI1x10GEXP_BITMSK_RXXG_MHASH_EN;
391 }
392
393 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_2, (u16)rx_mode);
394
395 if (enabled)
396 pm3393_enable(cmac, MAC_DIRECTION_RX);
397
398 return 0;
399}
400
401static int pm3393_get_speed_duplex_fc(struct cmac *cmac, int *speed,
402 int *duplex, int *fc)
403{
404 if (speed)
405 *speed = SPEED_10000;
406 if (duplex)
407 *duplex = DUPLEX_FULL;
408 if (fc)
409 *fc = cmac->instance->fc;
410 return 0;
411}
412
413static int pm3393_set_speed_duplex_fc(struct cmac *cmac, int speed, int duplex,
414 int fc)
415{
416 if (speed >= 0 && speed != SPEED_10000)
417 return -1;
418 if (duplex >= 0 && duplex != DUPLEX_FULL)
419 return -1;
420 if (fc & ~(PAUSE_TX | PAUSE_RX))
421 return -1;
422
423 if (fc != cmac->instance->fc) {
424 cmac->instance->fc = (u8) fc;
425 if (cmac->instance->enabled & MAC_DIRECTION_TX)
426 pm3393_enable(cmac, MAC_DIRECTION_TX);
427 }
428 return 0;
429}
430
431#define RMON_UPDATE(mac, name, stat_name) \
432{ \
433 t1_tpi_read((mac)->adapter, OFFSET(name), &val0); \
434 t1_tpi_read((mac)->adapter, OFFSET((name)+1), &val1); \
435 t1_tpi_read((mac)->adapter, OFFSET((name)+2), &val2); \
436 (mac)->stats.stat_name = (u64)(val0 & 0xffff) | \
437 ((u64)(val1 & 0xffff) << 16) | \
438 ((u64)(val2 & 0xff) << 32) | \
439 ((mac)->stats.stat_name & \
440 0xffffff0000000000ULL); \
441 if (ro & \
442 (1ULL << ((name - SUNI1x10GEXP_REG_MSTAT_COUNTER_0_LOW) >> 2))) \
443 (mac)->stats.stat_name += 1ULL << 40; \
444}
445
446static const struct cmac_statistics *pm3393_update_statistics(struct cmac *mac,
447 int flag)
448{
449 u64 ro;
450 u32 val0, val1, val2, val3;
451
452
453 pmwrite(mac, SUNI1x10GEXP_REG_MSTAT_CONTROL,
454 SUNI1x10GEXP_BITMSK_MSTAT_SNAP);
455
456
457 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_0, &val0);
458 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_1, &val1);
459 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_2, &val2);
460 pmread(mac, SUNI1x10GEXP_REG_MSTAT_COUNTER_ROLLOVER_3, &val3);
461 ro = ((u64)val0 & 0xffff) | (((u64)val1 & 0xffff) << 16) |
462 (((u64)val2 & 0xffff) << 32) | (((u64)val3 & 0xffff) << 48);
463
464
465 RMON_UPDATE(mac, RxOctetsReceivedOK, RxOctetsOK);
466 RMON_UPDATE(mac, RxUnicastFramesReceivedOK, RxUnicastFramesOK);
467 RMON_UPDATE(mac, RxMulticastFramesReceivedOK, RxMulticastFramesOK);
468 RMON_UPDATE(mac, RxBroadcastFramesReceivedOK, RxBroadcastFramesOK);
469 RMON_UPDATE(mac, RxPAUSEMACCtrlFramesReceived, RxPauseFrames);
470 RMON_UPDATE(mac, RxFrameCheckSequenceErrors, RxFCSErrors);
471 RMON_UPDATE(mac, RxFramesLostDueToInternalMACErrors,
472 RxInternalMACRcvError);
473 RMON_UPDATE(mac, RxSymbolErrors, RxSymbolErrors);
474 RMON_UPDATE(mac, RxInRangeLengthErrors, RxInRangeLengthErrors);
475 RMON_UPDATE(mac, RxFramesTooLongErrors , RxFrameTooLongErrors);
476 RMON_UPDATE(mac, RxJabbers, RxJabberErrors);
477 RMON_UPDATE(mac, RxFragments, RxRuntErrors);
478 RMON_UPDATE(mac, RxUndersizedFrames, RxRuntErrors);
479 RMON_UPDATE(mac, RxJumboFramesReceivedOK, RxJumboFramesOK);
480 RMON_UPDATE(mac, RxJumboOctetsReceivedOK, RxJumboOctetsOK);
481
482
483 RMON_UPDATE(mac, TxOctetsTransmittedOK, TxOctetsOK);
484 RMON_UPDATE(mac, TxFramesLostDueToInternalMACTransmissionError,
485 TxInternalMACXmitError);
486 RMON_UPDATE(mac, TxTransmitSystemError, TxFCSErrors);
487 RMON_UPDATE(mac, TxUnicastFramesTransmittedOK, TxUnicastFramesOK);
488 RMON_UPDATE(mac, TxMulticastFramesTransmittedOK, TxMulticastFramesOK);
489 RMON_UPDATE(mac, TxBroadcastFramesTransmittedOK, TxBroadcastFramesOK);
490 RMON_UPDATE(mac, TxPAUSEMACCtrlFramesTransmitted, TxPauseFrames);
491 RMON_UPDATE(mac, TxJumboFramesReceivedOK, TxJumboFramesOK);
492 RMON_UPDATE(mac, TxJumboOctetsReceivedOK, TxJumboOctetsOK);
493
494 return &mac->stats;
495}
496
497static int pm3393_macaddress_get(struct cmac *cmac, u8 mac_addr[6])
498{
499 memcpy(mac_addr, cmac->instance->mac_addr, 6);
500 return 0;
501}
502
503static int pm3393_macaddress_set(struct cmac *cmac, u8 ma[6])
504{
505 u32 val, lo, mid, hi, enabled = cmac->instance->enabled;
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526 memcpy(cmac->instance->mac_addr, ma, 6);
527
528 lo = ((u32) ma[1] << 8) | (u32) ma[0];
529 mid = ((u32) ma[3] << 8) | (u32) ma[2];
530 hi = ((u32) ma[5] << 8) | (u32) ma[4];
531
532
533 if (enabled)
534 pm3393_disable(cmac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
535
536
537 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_15_0, lo);
538 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_31_16, mid);
539 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_SA_47_32, hi);
540
541
542 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_15_0, lo);
543 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_31_16, mid);
544 pmwrite(cmac, SUNI1x10GEXP_REG_TXXG_SA_47_32, hi);
545
546
547
548
549
550 pmread(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, &val);
551 val &= 0xff0f;
552 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
553
554 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_LOW, lo);
555 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_MID, mid);
556 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_EXACT_MATCH_ADDR_1_HIGH, hi);
557
558 val |= 0x0090;
559 pmwrite(cmac, SUNI1x10GEXP_REG_RXXG_ADDRESS_FILTER_CONTROL_0, val);
560
561 if (enabled)
562 pm3393_enable(cmac, enabled);
563 return 0;
564}
565
566static void pm3393_destroy(struct cmac *cmac)
567{
568 kfree(cmac);
569}
570
571static struct cmac_ops pm3393_ops = {
572 .destroy = pm3393_destroy,
573 .reset = pm3393_reset,
574 .interrupt_enable = pm3393_interrupt_enable,
575 .interrupt_disable = pm3393_interrupt_disable,
576 .interrupt_clear = pm3393_interrupt_clear,
577 .interrupt_handler = pm3393_interrupt_handler,
578 .enable = pm3393_enable_port,
579 .disable = pm3393_disable,
580 .loopback_enable = pm3393_loopback_enable,
581 .loopback_disable = pm3393_loopback_disable,
582 .set_mtu = pm3393_set_mtu,
583 .set_rx_mode = pm3393_set_rx_mode,
584 .get_speed_duplex_fc = pm3393_get_speed_duplex_fc,
585 .set_speed_duplex_fc = pm3393_set_speed_duplex_fc,
586 .statistics_update = pm3393_update_statistics,
587 .macaddress_get = pm3393_macaddress_get,
588 .macaddress_set = pm3393_macaddress_set
589};
590
591static struct cmac *pm3393_mac_create(adapter_t *adapter, int index)
592{
593 struct cmac *cmac;
594
595 cmac = kzalloc(sizeof(*cmac) + sizeof(cmac_instance), GFP_KERNEL);
596 if (!cmac)
597 return NULL;
598
599 cmac->ops = &pm3393_ops;
600 cmac->instance = (cmac_instance *) (cmac + 1);
601 cmac->adapter = adapter;
602 cmac->instance->fc = PAUSE_TX | PAUSE_RX;
603
604 t1_tpi_write(adapter, OFFSET(0x0001), 0x00008000);
605 t1_tpi_write(adapter, OFFSET(0x0001), 0x00000000);
606 t1_tpi_write(adapter, OFFSET(0x2308), 0x00009800);
607 t1_tpi_write(adapter, OFFSET(0x2305), 0x00001001);
608 t1_tpi_write(adapter, OFFSET(0x2320), 0x00008800);
609 t1_tpi_write(adapter, OFFSET(0x2321), 0x00008800);
610 t1_tpi_write(adapter, OFFSET(0x2322), 0x00008800);
611 t1_tpi_write(adapter, OFFSET(0x2323), 0x00008800);
612 t1_tpi_write(adapter, OFFSET(0x2324), 0x00008800);
613 t1_tpi_write(adapter, OFFSET(0x2325), 0x00008800);
614 t1_tpi_write(adapter, OFFSET(0x2326), 0x00008800);
615 t1_tpi_write(adapter, OFFSET(0x2327), 0x00008800);
616 t1_tpi_write(adapter, OFFSET(0x2328), 0x00008800);
617 t1_tpi_write(adapter, OFFSET(0x2329), 0x00008800);
618 t1_tpi_write(adapter, OFFSET(0x232a), 0x00008800);
619 t1_tpi_write(adapter, OFFSET(0x232b), 0x00008800);
620 t1_tpi_write(adapter, OFFSET(0x232c), 0x00008800);
621 t1_tpi_write(adapter, OFFSET(0x232d), 0x00008800);
622 t1_tpi_write(adapter, OFFSET(0x232e), 0x00008800);
623 t1_tpi_write(adapter, OFFSET(0x232f), 0x00008800);
624 t1_tpi_write(adapter, OFFSET(0x230d), 0x00009c00);
625 t1_tpi_write(adapter, OFFSET(0x2304), 0x00000202);
626
627 t1_tpi_write(adapter, OFFSET(0x3200), 0x00008080);
628 t1_tpi_write(adapter, OFFSET(0x3210), 0x00000000);
629 t1_tpi_write(adapter, OFFSET(0x3203), 0x00000000);
630 t1_tpi_write(adapter, OFFSET(0x3204), 0x00000040);
631 t1_tpi_write(adapter, OFFSET(0x3205), 0x000002cc);
632 t1_tpi_write(adapter, OFFSET(0x3206), 0x00000199);
633 t1_tpi_write(adapter, OFFSET(0x3207), 0x00000240);
634 t1_tpi_write(adapter, OFFSET(0x3202), 0x00000000);
635 t1_tpi_write(adapter, OFFSET(0x3210), 0x00000001);
636 t1_tpi_write(adapter, OFFSET(0x3208), 0x0000ffff);
637 t1_tpi_write(adapter, OFFSET(0x320a), 0x0000ffff);
638 t1_tpi_write(adapter, OFFSET(0x320c), 0x0000ffff);
639 t1_tpi_write(adapter, OFFSET(0x320e), 0x0000ffff);
640
641 t1_tpi_write(adapter, OFFSET(0x2200), 0x0000c000);
642 t1_tpi_write(adapter, OFFSET(0x2201), 0x00000000);
643 t1_tpi_write(adapter, OFFSET(0x220e), 0x00000000);
644 t1_tpi_write(adapter, OFFSET(0x220f), 0x00000100);
645 t1_tpi_write(adapter, OFFSET(0x2210), 0x00000c00);
646 t1_tpi_write(adapter, OFFSET(0x2211), 0x00000599);
647 t1_tpi_write(adapter, OFFSET(0x220d), 0x00000000);
648 t1_tpi_write(adapter, OFFSET(0x2201), 0x00000001);
649 t1_tpi_write(adapter, OFFSET(0x2203), 0x0000ffff);
650 t1_tpi_write(adapter, OFFSET(0x2205), 0x0000ffff);
651 t1_tpi_write(adapter, OFFSET(0x2209), 0x0000ffff);
652
653 t1_tpi_write(adapter, OFFSET(0x2241), 0xfffffffe);
654 t1_tpi_write(adapter, OFFSET(0x2242), 0x0000ffff);
655 t1_tpi_write(adapter, OFFSET(0x2243), 0x00000008);
656 t1_tpi_write(adapter, OFFSET(0x2244), 0x00000008);
657 t1_tpi_write(adapter, OFFSET(0x2245), 0x00000008);
658 t1_tpi_write(adapter, OFFSET(0x2240), 0x00000005);
659
660 t1_tpi_write(adapter, OFFSET(0x2280), 0x00002103);
661 t1_tpi_write(adapter, OFFSET(0x2284), 0x00000000);
662
663 t1_tpi_write(adapter, OFFSET(0x3280), 0x00000087);
664 t1_tpi_write(adapter, OFFSET(0x3282), 0x0000001f);
665
666 t1_tpi_write(adapter, OFFSET(0x3040), 0x0c32);
667
668 t1_tpi_write(adapter, OFFSET(0x304d), 0x8000);
669 t1_tpi_write(adapter, OFFSET(0x2040), 0x059c);
670 t1_tpi_write(adapter, OFFSET(0x2049), 0x0001);
671 t1_tpi_write(adapter, OFFSET(0x2070), 0x0000);
672
673
674
675 t1_tpi_write(adapter, OFFSET(0x206e), 0x0000);
676 t1_tpi_write(adapter, OFFSET(0x204a), 0xffff);
677 t1_tpi_write(adapter, OFFSET(0x204b), 0xffff);
678 t1_tpi_write(adapter, OFFSET(0x204c), 0xffff);
679 t1_tpi_write(adapter, OFFSET(0x206e), 0x0009);
680
681 t1_tpi_write(adapter, OFFSET(0x0003), 0x0000);
682 t1_tpi_write(adapter, OFFSET(0x0100), 0x0ff0);
683 t1_tpi_write(adapter, OFFSET(0x0101), 0x0f0f);
684
685 return cmac;
686}
687
688static int pm3393_mac_reset(adapter_t * adapter)
689{
690 u32 val;
691 u32 x;
692 u32 is_pl4_reset_finished;
693 u32 is_pl4_outof_lock;
694 u32 is_xaui_mabc_pll_locked;
695 u32 successful_reset;
696 int i;
697
698
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 successful_reset = 0;
728 for (i = 0; i < 3 && !successful_reset; i++) {
729
730 t1_tpi_read(adapter, A_ELMER0_GPO, &val);
731 val &= ~1;
732 t1_tpi_write(adapter, A_ELMER0_GPO, val);
733
734
735 msleep(1);
736
737
738 msleep(1);
739
740
741 msleep(2 );
742
743
744 val |= 1;
745 t1_tpi_write(adapter, A_ELMER0_GPO, val);
746
747
748 msleep(15 );
749
750
751 msleep(1);
752
753
754
755
756 t1_tpi_read(adapter, OFFSET(SUNI1x10GEXP_REG_DEVICE_STATUS), &val);
757 is_pl4_reset_finished = (val & SUNI1x10GEXP_BITMSK_TOP_EXPIRED);
758
759
760
761
762
763 x = (SUNI1x10GEXP_BITMSK_TOP_PL4_ID_DOOL
764 |
765 SUNI1x10GEXP_BITMSK_TOP_PL4_ID_ROOL |
766 SUNI1x10GEXP_BITMSK_TOP_PL4_IS_ROOL |
767 SUNI1x10GEXP_BITMSK_TOP_PL4_OUT_ROOL);
768 is_pl4_outof_lock = (val & x);
769
770
771
772
773 is_xaui_mabc_pll_locked =
774 (val & SUNI1x10GEXP_BITMSK_TOP_SXRA_EXPIRED);
775
776 successful_reset = (is_pl4_reset_finished && !is_pl4_outof_lock
777 && is_xaui_mabc_pll_locked);
778
779 CH_DBG(adapter, HW,
780 "PM3393 HW reset %d: pl4_reset 0x%x, val 0x%x, "
781 "is_pl4_outof_lock 0x%x, xaui_locked 0x%x\n",
782 i, is_pl4_reset_finished, val, is_pl4_outof_lock,
783 is_xaui_mabc_pll_locked);
784 }
785 return successful_reset ? 0 : 1;
786}
787
788const struct gmac t1_pm3393_ops = {
789 .stats_update_period = STATS_TICK_SECS,
790 .create = pm3393_mac_create,
791 .reset = pm3393_mac_reset,
792};
793