1 /* $Date: 2005/10/22 00:42:59 $ $RCSfile: mac.c,v $ $Revision: 1.32 $ */
6 #define MAC_CSR_INTERFACE_GMII 0x0
7 #define MAC_CSR_INTERFACE_TBI 0x1
8 #define MAC_CSR_INTERFACE_MII 0x2
9 #define MAC_CSR_INTERFACE_RMII 0x3
11 /* Chelsio's MAC statistics. */
12 struct mac_statistics
{
15 u32 TxFramesTransmittedOK
;
18 u32 TxOctetsTransmittedOK
;
19 u32 TxFramesWithDeferredXmissions
;
21 u32 TxFramesAbortedDueToXSCollisions
;
22 u32 TxFramesLostDueToIntMACXmitError
;
24 u32 TxMulticastFrameXmittedOK
;
25 u32 TxBroadcastFramesXmittedOK
;
26 u32 TxFramesWithExcessiveDeferral
;
27 u32 TxPAUSEMACCtrlFramesTransmitted
;
30 u32 RxFramesReceivedOK
;
31 u32 RxFrameCheckSequenceErrors
;
32 u32 RxAlignmentErrors
;
33 u32 RxOctetsReceivedOK
;
34 u32 RxFramesLostDueToIntMACRcvError
;
35 u32 RxMulticastFramesReceivedOK
;
36 u32 RxBroadcastFramesReceivedOK
;
37 u32 RxInRangeLengthErrors
;
38 u32 RxTxOutOfRangeLengthField
;
39 u32 RxFrameTooLongErrors
;
40 u32 RxPAUSEMACCtrlFramesReceived
;
43 static int static_aPorts
[] = {
44 FPGA_GMAC_INTERRUPT_PORT0
,
45 FPGA_GMAC_INTERRUPT_PORT1
,
46 FPGA_GMAC_INTERRUPT_PORT2
,
47 FPGA_GMAC_INTERRUPT_PORT3
50 struct _cmac_instance
{
54 static int mac_intr_enable(struct cmac
*mac
)
58 if (t1_is_asic(mac
->adapter
)) {
61 /* We don't use the on chip MAC for ASIC products. */
65 /* Set parent gmac interrupt. */
66 mac_intr
= readl(mac
->adapter
->regs
+ A_PL_ENABLE
);
67 mac_intr
|= FPGA_PCIX_INTERRUPT_GMAC
;
68 writel(mac_intr
, mac
->adapter
->regs
+ A_PL_ENABLE
);
70 mac_intr
= readl(mac
->adapter
->regs
+ FPGA_GMAC_ADDR_INTERRUPT_ENABLE
);
71 mac_intr
|= static_aPorts
[mac
->instance
->index
];
73 mac
->adapter
->regs
+ FPGA_GMAC_ADDR_INTERRUPT_ENABLE
);
79 static int mac_intr_disable(struct cmac
*mac
)
83 if (t1_is_asic(mac
->adapter
)) {
86 /* We don't use the on chip MAC for ASIC products. */
90 /* Set parent gmac interrupt. */
91 mac_intr
= readl(mac
->adapter
->regs
+ A_PL_ENABLE
);
92 mac_intr
&= ~FPGA_PCIX_INTERRUPT_GMAC
;
93 writel(mac_intr
, mac
->adapter
->regs
+ A_PL_ENABLE
);
95 mac_intr
= readl(mac
->adapter
->regs
+ FPGA_GMAC_ADDR_INTERRUPT_ENABLE
);
96 mac_intr
&= ~(static_aPorts
[mac
->instance
->index
]);
98 mac
->adapter
->regs
+ FPGA_GMAC_ADDR_INTERRUPT_ENABLE
);
104 static int mac_intr_clear(struct cmac
*mac
)
108 if (t1_is_asic(mac
->adapter
)) {
111 /* We don't use the on chip MAC for ASIC products. */
115 /* Set parent gmac interrupt. */
116 writel(FPGA_PCIX_INTERRUPT_GMAC
,
117 mac
->adapter
->regs
+ A_PL_CAUSE
);
118 mac_intr
= readl(mac
->adapter
->regs
+ FPGA_GMAC_ADDR_INTERRUPT_CAUSE
);
119 mac_intr
|= (static_aPorts
[mac
->instance
->index
]);
121 mac
->adapter
->regs
+ FPGA_GMAC_ADDR_INTERRUPT_CAUSE
);
127 static int mac_get_address(struct cmac
*mac
, u8 addr
[6])
129 u32 data32_lo
, data32_hi
;
131 data32_lo
= readl(mac
->adapter
->regs
132 + MAC_REG_IDLO(mac
->instance
->index
));
133 data32_hi
= readl(mac
->adapter
->regs
134 + MAC_REG_IDHI(mac
->instance
->index
));
136 addr
[0] = (u8
) ((data32_hi
>> 8) & 0xFF);
137 addr
[1] = (u8
) ((data32_hi
) & 0xFF);
138 addr
[2] = (u8
) ((data32_lo
>> 24) & 0xFF);
139 addr
[3] = (u8
) ((data32_lo
>> 16) & 0xFF);
140 addr
[4] = (u8
) ((data32_lo
>> 8) & 0xFF);
141 addr
[5] = (u8
) ((data32_lo
) & 0xFF);
145 static int mac_reset(struct cmac
*mac
)
148 int mac_in_reset
, time_out
= 100;
149 int idx
= mac
->instance
->index
;
151 data32
= readl(mac
->adapter
->regs
+ MAC_REG_CSR(idx
));
152 writel(data32
| F_MAC_RESET
,
153 mac
->adapter
->regs
+ MAC_REG_CSR(idx
));
156 data32
= readl(mac
->adapter
->regs
+ MAC_REG_CSR(idx
));
158 mac_in_reset
= data32
& F_MAC_RESET
;
161 } while (mac_in_reset
&& --time_out
);
164 CH_ERR("%s: MAC %d reset timed out\n",
165 mac
->adapter
->name
, idx
);
172 static int mac_set_rx_mode(struct cmac
*mac
, struct t1_rx_mode
*rm
)
176 val
= readl(mac
->adapter
->regs
177 + MAC_REG_CSR(mac
->instance
->index
));
178 val
&= ~(F_MAC_PROMISC
| F_MAC_MC_ENABLE
);
179 val
|= V_MAC_PROMISC(t1_rx_mode_promisc(rm
) != 0);
180 val
|= V_MAC_MC_ENABLE(t1_rx_mode_allmulti(rm
) != 0);
182 mac
->adapter
->regs
+ MAC_REG_CSR(mac
->instance
->index
));
187 static int mac_set_speed_duplex_fc(struct cmac
*mac
, int speed
, int duplex
,
192 data32
= readl(mac
->adapter
->regs
193 + MAC_REG_CSR(mac
->instance
->index
));
194 data32
&= ~(F_MAC_HALF_DUPLEX
| V_MAC_SPEED(M_MAC_SPEED
) |
195 V_INTERFACE(M_INTERFACE
) | F_MAC_TX_PAUSE_ENABLE
|
196 F_MAC_RX_PAUSE_ENABLE
);
201 data32
|= V_INTERFACE(MAC_CSR_INTERFACE_MII
);
202 data32
|= V_MAC_SPEED(speed
== SPEED_10
? 0 : 1);
205 data32
|= V_INTERFACE(MAC_CSR_INTERFACE_GMII
);
206 data32
|= V_MAC_SPEED(2);
211 data32
|= V_MAC_HALF_DUPLEX(duplex
== DUPLEX_HALF
);
214 data32
|= V_MAC_RX_PAUSE_ENABLE((fc
& PAUSE_RX
) != 0);
215 data32
|= V_MAC_TX_PAUSE_ENABLE((fc
& PAUSE_TX
) != 0);
219 mac
->adapter
->regs
+ MAC_REG_CSR(mac
->instance
->index
));
223 static int mac_enable(struct cmac
*mac
, int which
)
227 val
= readl(mac
->adapter
->regs
228 + MAC_REG_CSR(mac
->instance
->index
));
229 if (which
& MAC_DIRECTION_RX
)
230 val
|= F_MAC_RX_ENABLE
;
231 if (which
& MAC_DIRECTION_TX
)
232 val
|= F_MAC_TX_ENABLE
;
234 mac
->adapter
->regs
+ MAC_REG_CSR(mac
->instance
->index
));
238 static int mac_disable(struct cmac
*mac
, int which
)
242 val
= readl(mac
->adapter
->regs
243 + MAC_REG_CSR(mac
->instance
->index
));
244 if (which
& MAC_DIRECTION_RX
)
245 val
&= ~F_MAC_RX_ENABLE
;
246 if (which
& MAC_DIRECTION_TX
)
247 val
&= ~F_MAC_TX_ENABLE
;
249 mac
->adapter
->regs
+ MAC_REG_CSR(mac
->instance
->index
));
254 static int mac_set_ifs(struct cmac
*mac
, u32 mode
)
256 t1_write_reg_4(mac
->adapter
,
257 MAC_REG_IFS(mac
->instance
->index
),
262 static int mac_enable_isl(struct cmac
*mac
)
264 u32 data32
= readl(mac
->adapter
->regs
265 + MAC_REG_CSR(mac
->instance
->index
));
266 data32
|= F_MAC_RX_ENABLE
| F_MAC_TX_ENABLE
;
267 t1_write_reg_4(mac
->adapter
,
268 MAC_REG_CSR(mac
->instance
->index
),
274 static int mac_set_mtu(struct cmac
*mac
, int mtu
)
278 writel(mtu
+ ETH_HLEN
+ VLAN_HLEN
,
279 mac
->adapter
->regs
+ MAC_REG_LARGEFRAMELENGTH(mac
->instance
->index
));
284 static const struct cmac_statistics
*mac_update_statistics(struct cmac
*mac
,
287 struct mac_statistics st
;
288 u32
*p
= (u32
*) & st
, i
;
291 mac
->adapter
->regs
+ MAC_REG_RMCNT(mac
->instance
->index
));
293 for (i
= 0; i
< sizeof(st
) / sizeof(u32
); i
++)
294 *p
++ = readl(mac
->adapter
->regs
295 + MAC_REG_RMDATA(mac
->instance
->index
));
297 /* XXX convert stats */
301 static void mac_destroy(struct cmac
*mac
)
306 static struct cmac_ops chelsio_mac_ops
= {
307 .destroy
= mac_destroy
,
309 .interrupt_enable
= mac_intr_enable
,
310 .interrupt_disable
= mac_intr_disable
,
311 .interrupt_clear
= mac_intr_clear
,
312 .enable
= mac_enable
,
313 .disable
= mac_disable
,
314 .set_mtu
= mac_set_mtu
,
315 .set_rx_mode
= mac_set_rx_mode
,
316 .set_speed_duplex_fc
= mac_set_speed_duplex_fc
,
317 .macaddress_get
= mac_get_address
,
318 .statistics_update
= mac_update_statistics
,
321 static struct cmac
*mac_create(adapter_t
*adapter
, int index
)
329 mac
= kzalloc(sizeof(*mac
) + sizeof(cmac_instance
), GFP_KERNEL
);
333 mac
->ops
= &chelsio_mac_ops
;
334 mac
->instance
= (cmac_instance
*) (mac
+ 1);
336 mac
->instance
->index
= index
;
337 mac
->adapter
= adapter
;
339 data32
= readl(adapter
->regs
+ MAC_REG_CSR(mac
->instance
->index
));
340 data32
&= ~(F_MAC_RESET
| F_MAC_PROMISC
| F_MAC_PROMISC
|
341 F_MAC_LB_ENABLE
| F_MAC_RX_ENABLE
| F_MAC_TX_ENABLE
);
342 data32
|= F_MAC_JUMBO_ENABLE
;
343 writel(data32
, adapter
->regs
+ MAC_REG_CSR(mac
->instance
->index
));
345 /* Initialize the random backoff seed. */
346 data32
= 0x55aa + (3 * index
);
348 adapter
->regs
+ MAC_REG_GMRANDBACKOFFSEED(mac
->instance
->index
));
350 /* Check to see if the mac address needs to be set manually. */
351 data32
= readl(adapter
->regs
+ MAC_REG_IDLO(mac
->instance
->index
));
352 if (data32
== 0 || data32
== 0xffffffff) {
354 * Add a default MAC address if we can't read one.
356 writel(0x43FFFFFF - index
,
357 adapter
->regs
+ MAC_REG_IDLO(mac
->instance
->index
));
359 adapter
->regs
+ MAC_REG_IDHI(mac
->instance
->index
));
362 (void) mac_set_mtu(mac
, 1500);
366 const struct gmac t1_chelsio_mac_ops
= {