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