diff options
-rw-r--r-- | drivers/net/ethernet/ti/Makefile | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/netcp_ethss.c | 1714 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/netcp_sgmii.c | 131 |
3 files changed, 1847 insertions, 1 deletions
diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile index 4e8a8e41f69f..6d4dde8d8fdc 100644 --- a/drivers/net/ethernet/ti/Makefile +++ b/drivers/net/ethernet/ti/Makefile | |||
@@ -12,4 +12,5 @@ obj-$(CONFIG_TI_CPSW) += ti_cpsw.o | |||
12 | ti_cpsw-y := cpsw_ale.o cpsw.o cpts.o | 12 | ti_cpsw-y := cpsw_ale.o cpsw.o cpts.o |
13 | 13 | ||
14 | obj-$(CONFIG_TI_KEYSTONE_NETCP) += keystone_netcp.o | 14 | obj-$(CONFIG_TI_KEYSTONE_NETCP) += keystone_netcp.o |
15 | keystone_netcp-y := netcp_core.o | 15 | keystone_netcp-y := netcp_core.o netcp_ethss.o netcp_sgmii.o \ |
16 | cpsw_ale.o cpts.o | ||
diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c new file mode 100644 index 000000000000..58f00c572546 --- /dev/null +++ b/drivers/net/ethernet/ti/netcp_ethss.c | |||
@@ -0,0 +1,1714 @@ | |||
1 | /* | ||
2 | * Keystone GBE subsystem code | ||
3 | * | ||
4 | * Copyright (C) 2014 Texas Instruments Incorporated | ||
5 | * Authors: Sandeep Nair <sandeep_n@ti.com> | ||
6 | * Sandeep Paulraj <s-paulraj@ti.com> | ||
7 | * Cyril Chemparathy <cyril@ti.com> | ||
8 | * Santosh Shilimkar <santosh.shilimkar@ti.com> | ||
9 | * Wingman Kwok <w-kwok2@ti.com> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or | ||
12 | * modify it under the terms of the GNU General Public License as | ||
13 | * published by the Free Software Foundation version 2. | ||
14 | * | ||
15 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
16 | * kind, whether express or implied; without even the implied warranty | ||
17 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | */ | ||
20 | |||
21 | #include <linux/io.h> | ||
22 | #include <linux/of_mdio.h> | ||
23 | #include <linux/of_address.h> | ||
24 | #include <linux/if_vlan.h> | ||
25 | #include <linux/ethtool.h> | ||
26 | |||
27 | #include "cpsw_ale.h" | ||
28 | #include "netcp.h" | ||
29 | |||
30 | #define NETCP_DRIVER_NAME "TI KeyStone Ethernet Driver" | ||
31 | #define NETCP_DRIVER_VERSION "v1.0" | ||
32 | |||
33 | #define GBE_IDENT(reg) ((reg >> 16) & 0xffff) | ||
34 | #define GBE_MAJOR_VERSION(reg) (reg >> 8 & 0x7) | ||
35 | #define GBE_MINOR_VERSION(reg) (reg & 0xff) | ||
36 | #define GBE_RTL_VERSION(reg) ((reg >> 11) & 0x1f) | ||
37 | |||
38 | /* 1G Ethernet SS defines */ | ||
39 | #define GBE_MODULE_NAME "netcp-gbe" | ||
40 | #define GBE_SS_VERSION_14 0x4ed21104 | ||
41 | |||
42 | #define GBE13_SGMII_MODULE_OFFSET 0x100 | ||
43 | #define GBE13_SGMII34_MODULE_OFFSET 0x400 | ||
44 | #define GBE13_SWITCH_MODULE_OFFSET 0x800 | ||
45 | #define GBE13_HOST_PORT_OFFSET 0x834 | ||
46 | #define GBE13_SLAVE_PORT_OFFSET 0x860 | ||
47 | #define GBE13_EMAC_OFFSET 0x900 | ||
48 | #define GBE13_SLAVE_PORT2_OFFSET 0xa00 | ||
49 | #define GBE13_HW_STATS_OFFSET 0xb00 | ||
50 | #define GBE13_ALE_OFFSET 0xe00 | ||
51 | #define GBE13_HOST_PORT_NUM 0 | ||
52 | #define GBE13_NUM_SLAVES 4 | ||
53 | #define GBE13_NUM_ALE_PORTS (GBE13_NUM_SLAVES + 1) | ||
54 | #define GBE13_NUM_ALE_ENTRIES 1024 | ||
55 | |||
56 | #define GBE_TIMER_INTERVAL (HZ / 2) | ||
57 | |||
58 | /* Soft reset register values */ | ||
59 | #define SOFT_RESET_MASK BIT(0) | ||
60 | #define SOFT_RESET BIT(0) | ||
61 | #define DEVICE_EMACSL_RESET_POLL_COUNT 100 | ||
62 | #define GMACSL_RET_WARN_RESET_INCOMPLETE -2 | ||
63 | |||
64 | #define MACSL_RX_ENABLE_CSF BIT(23) | ||
65 | #define MACSL_ENABLE_EXT_CTL BIT(18) | ||
66 | #define MACSL_GIG_MODE BIT(7) | ||
67 | #define MACSL_GMII_ENABLE BIT(5) | ||
68 | #define MACSL_FULLDUPLEX BIT(0) | ||
69 | |||
70 | #define GBE_CTL_P0_ENABLE BIT(2) | ||
71 | #define GBE_REG_VAL_STAT_ENABLE_ALL 0xff | ||
72 | #define GBE_STATS_CD_SEL BIT(28) | ||
73 | |||
74 | #define GBE_PORT_MASK(x) (BIT(x) - 1) | ||
75 | #define GBE_MASK_NO_PORTS 0 | ||
76 | |||
77 | #define GBE_DEF_1G_MAC_CONTROL \ | ||
78 | (MACSL_GIG_MODE | MACSL_GMII_ENABLE | \ | ||
79 | MACSL_ENABLE_EXT_CTL | MACSL_RX_ENABLE_CSF) | ||
80 | |||
81 | #define GBE_STATSA_MODULE 0 | ||
82 | #define GBE_STATSB_MODULE 1 | ||
83 | #define GBE_STATSC_MODULE 2 | ||
84 | #define GBE_STATSD_MODULE 3 | ||
85 | |||
86 | #define MAX_SLAVES GBE13_NUM_SLAVES | ||
87 | /* s: 0-based slave_port */ | ||
88 | #define SGMII_BASE(s) \ | ||
89 | (((s) < 2) ? gbe_dev->sgmii_port_regs : gbe_dev->sgmii_port34_regs) | ||
90 | |||
91 | #define GBE_TX_QUEUE 648 | ||
92 | #define GBE_TXHOOK_ORDER 0 | ||
93 | #define GBE_DEFAULT_ALE_AGEOUT 30 | ||
94 | #define NETCP_LINK_STATE_INVALID -1 | ||
95 | |||
96 | #define GBE_SET_REG_OFS(p, rb, rn) p->rb##_ofs.rn = \ | ||
97 | offsetof(struct gbe##_##rb, rn) | ||
98 | #define GBE_REG_ADDR(p, rb, rn) (p->rb + p->rb##_ofs.rn) | ||
99 | |||
100 | struct gbe_ss_regs { | ||
101 | u32 id_ver; | ||
102 | u32 synce_count; | ||
103 | u32 synce_mux; | ||
104 | }; | ||
105 | |||
106 | struct gbe_ss_regs_ofs { | ||
107 | u16 id_ver; | ||
108 | u16 control; | ||
109 | }; | ||
110 | |||
111 | struct gbe_switch_regs { | ||
112 | u32 id_ver; | ||
113 | u32 control; | ||
114 | u32 soft_reset; | ||
115 | u32 stat_port_en; | ||
116 | u32 ptype; | ||
117 | u32 soft_idle; | ||
118 | u32 thru_rate; | ||
119 | u32 gap_thresh; | ||
120 | u32 tx_start_wds; | ||
121 | u32 flow_control; | ||
122 | }; | ||
123 | |||
124 | struct gbe_switch_regs_ofs { | ||
125 | u16 id_ver; | ||
126 | u16 control; | ||
127 | u16 soft_reset; | ||
128 | u16 emcontrol; | ||
129 | u16 stat_port_en; | ||
130 | u16 ptype; | ||
131 | u16 flow_control; | ||
132 | }; | ||
133 | |||
134 | struct gbe_port_regs { | ||
135 | u32 max_blks; | ||
136 | u32 blk_cnt; | ||
137 | u32 port_vlan; | ||
138 | u32 tx_pri_map; | ||
139 | u32 sa_lo; | ||
140 | u32 sa_hi; | ||
141 | u32 ts_ctl; | ||
142 | u32 ts_seq_ltype; | ||
143 | u32 ts_vlan; | ||
144 | u32 ts_ctl_ltype2; | ||
145 | u32 ts_ctl2; | ||
146 | }; | ||
147 | |||
148 | struct gbe_port_regs_ofs { | ||
149 | u16 port_vlan; | ||
150 | u16 tx_pri_map; | ||
151 | u16 sa_lo; | ||
152 | u16 sa_hi; | ||
153 | u16 ts_ctl; | ||
154 | u16 ts_seq_ltype; | ||
155 | u16 ts_vlan; | ||
156 | u16 ts_ctl_ltype2; | ||
157 | u16 ts_ctl2; | ||
158 | }; | ||
159 | |||
160 | struct gbe_host_port_regs { | ||
161 | u32 src_id; | ||
162 | u32 port_vlan; | ||
163 | u32 rx_pri_map; | ||
164 | u32 rx_maxlen; | ||
165 | }; | ||
166 | |||
167 | struct gbe_host_port_regs_ofs { | ||
168 | u16 port_vlan; | ||
169 | u16 tx_pri_map; | ||
170 | u16 rx_maxlen; | ||
171 | }; | ||
172 | |||
173 | struct gbe_emac_regs { | ||
174 | u32 id_ver; | ||
175 | u32 mac_control; | ||
176 | u32 mac_status; | ||
177 | u32 soft_reset; | ||
178 | u32 rx_maxlen; | ||
179 | u32 __reserved_0; | ||
180 | u32 rx_pause; | ||
181 | u32 tx_pause; | ||
182 | u32 __reserved_1; | ||
183 | u32 rx_pri_map; | ||
184 | u32 rsvd[6]; | ||
185 | }; | ||
186 | |||
187 | struct gbe_emac_regs_ofs { | ||
188 | u16 mac_control; | ||
189 | u16 soft_reset; | ||
190 | u16 rx_maxlen; | ||
191 | }; | ||
192 | |||
193 | struct gbe_hw_stats { | ||
194 | u32 rx_good_frames; | ||
195 | u32 rx_broadcast_frames; | ||
196 | u32 rx_multicast_frames; | ||
197 | u32 rx_pause_frames; | ||
198 | u32 rx_crc_errors; | ||
199 | u32 rx_align_code_errors; | ||
200 | u32 rx_oversized_frames; | ||
201 | u32 rx_jabber_frames; | ||
202 | u32 rx_undersized_frames; | ||
203 | u32 rx_fragments; | ||
204 | u32 __pad_0[2]; | ||
205 | u32 rx_bytes; | ||
206 | u32 tx_good_frames; | ||
207 | u32 tx_broadcast_frames; | ||
208 | u32 tx_multicast_frames; | ||
209 | u32 tx_pause_frames; | ||
210 | u32 tx_deferred_frames; | ||
211 | u32 tx_collision_frames; | ||
212 | u32 tx_single_coll_frames; | ||
213 | u32 tx_mult_coll_frames; | ||
214 | u32 tx_excessive_collisions; | ||
215 | u32 tx_late_collisions; | ||
216 | u32 tx_underrun; | ||
217 | u32 tx_carrier_sense_errors; | ||
218 | u32 tx_bytes; | ||
219 | u32 tx_64byte_frames; | ||
220 | u32 tx_65_to_127byte_frames; | ||
221 | u32 tx_128_to_255byte_frames; | ||
222 | u32 tx_256_to_511byte_frames; | ||
223 | u32 tx_512_to_1023byte_frames; | ||
224 | u32 tx_1024byte_frames; | ||
225 | u32 net_bytes; | ||
226 | u32 rx_sof_overruns; | ||
227 | u32 rx_mof_overruns; | ||
228 | u32 rx_dma_overruns; | ||
229 | }; | ||
230 | |||
231 | #define GBE13_NUM_HW_STAT_ENTRIES (sizeof(struct gbe_hw_stats)/sizeof(u32)) | ||
232 | #define GBE13_NUM_HW_STATS_MOD 2 | ||
233 | #define GBE_MAX_HW_STAT_MODS 3 | ||
234 | #define GBE_HW_STATS_REG_MAP_SZ 0x100 | ||
235 | |||
236 | struct gbe_slave { | ||
237 | void __iomem *port_regs; | ||
238 | void __iomem *emac_regs; | ||
239 | struct gbe_port_regs_ofs port_regs_ofs; | ||
240 | struct gbe_emac_regs_ofs emac_regs_ofs; | ||
241 | int slave_num; /* 0 based logical number */ | ||
242 | int port_num; /* actual port number */ | ||
243 | atomic_t link_state; | ||
244 | bool open; | ||
245 | struct phy_device *phy; | ||
246 | u32 link_interface; | ||
247 | u32 mac_control; | ||
248 | u8 phy_port_t; | ||
249 | struct device_node *phy_node; | ||
250 | struct list_head slave_list; | ||
251 | }; | ||
252 | |||
253 | struct gbe_priv { | ||
254 | struct device *dev; | ||
255 | struct netcp_device *netcp_device; | ||
256 | struct timer_list timer; | ||
257 | u32 num_slaves; | ||
258 | u32 ale_entries; | ||
259 | u32 ale_ports; | ||
260 | bool enable_ale; | ||
261 | struct netcp_tx_pipe tx_pipe; | ||
262 | |||
263 | int host_port; | ||
264 | u32 rx_packet_max; | ||
265 | u32 ss_version; | ||
266 | |||
267 | void __iomem *ss_regs; | ||
268 | void __iomem *switch_regs; | ||
269 | void __iomem *host_port_regs; | ||
270 | void __iomem *ale_reg; | ||
271 | void __iomem *sgmii_port_regs; | ||
272 | void __iomem *sgmii_port34_regs; | ||
273 | void __iomem *xgbe_serdes_regs; | ||
274 | void __iomem *hw_stats_regs[GBE_MAX_HW_STAT_MODS]; | ||
275 | |||
276 | struct gbe_ss_regs_ofs ss_regs_ofs; | ||
277 | struct gbe_switch_regs_ofs switch_regs_ofs; | ||
278 | struct gbe_host_port_regs_ofs host_port_regs_ofs; | ||
279 | |||
280 | struct cpsw_ale *ale; | ||
281 | unsigned int tx_queue_id; | ||
282 | const char *dma_chan_name; | ||
283 | |||
284 | struct list_head gbe_intf_head; | ||
285 | struct list_head secondary_slaves; | ||
286 | struct net_device *dummy_ndev; | ||
287 | |||
288 | u64 *hw_stats; | ||
289 | const struct netcp_ethtool_stat *et_stats; | ||
290 | int num_et_stats; | ||
291 | /* Lock for updating the hwstats */ | ||
292 | spinlock_t hw_stats_lock; | ||
293 | }; | ||
294 | |||
295 | struct gbe_intf { | ||
296 | struct net_device *ndev; | ||
297 | struct device *dev; | ||
298 | struct gbe_priv *gbe_dev; | ||
299 | struct netcp_tx_pipe tx_pipe; | ||
300 | struct gbe_slave *slave; | ||
301 | struct list_head gbe_intf_list; | ||
302 | unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; | ||
303 | }; | ||
304 | |||
305 | static struct netcp_module gbe_module; | ||
306 | |||
307 | /* Statistic management */ | ||
308 | struct netcp_ethtool_stat { | ||
309 | char desc[ETH_GSTRING_LEN]; | ||
310 | int type; | ||
311 | u32 size; | ||
312 | int offset; | ||
313 | }; | ||
314 | |||
315 | #define GBE_STATSA_INFO(field) "GBE_A:"#field, GBE_STATSA_MODULE,\ | ||
316 | FIELD_SIZEOF(struct gbe_hw_stats, field), \ | ||
317 | offsetof(struct gbe_hw_stats, field) | ||
318 | |||
319 | #define GBE_STATSB_INFO(field) "GBE_B:"#field, GBE_STATSB_MODULE,\ | ||
320 | FIELD_SIZEOF(struct gbe_hw_stats, field), \ | ||
321 | offsetof(struct gbe_hw_stats, field) | ||
322 | |||
323 | #define GBE_STATSC_INFO(field) "GBE_C:"#field, GBE_STATSC_MODULE,\ | ||
324 | FIELD_SIZEOF(struct gbe_hw_stats, field), \ | ||
325 | offsetof(struct gbe_hw_stats, field) | ||
326 | |||
327 | #define GBE_STATSD_INFO(field) "GBE_D:"#field, GBE_STATSD_MODULE,\ | ||
328 | FIELD_SIZEOF(struct gbe_hw_stats, field), \ | ||
329 | offsetof(struct gbe_hw_stats, field) | ||
330 | |||
331 | static const struct netcp_ethtool_stat gbe13_et_stats[] = { | ||
332 | /* GBE module A */ | ||
333 | {GBE_STATSA_INFO(rx_good_frames)}, | ||
334 | {GBE_STATSA_INFO(rx_broadcast_frames)}, | ||
335 | {GBE_STATSA_INFO(rx_multicast_frames)}, | ||
336 | {GBE_STATSA_INFO(rx_pause_frames)}, | ||
337 | {GBE_STATSA_INFO(rx_crc_errors)}, | ||
338 | {GBE_STATSA_INFO(rx_align_code_errors)}, | ||
339 | {GBE_STATSA_INFO(rx_oversized_frames)}, | ||
340 | {GBE_STATSA_INFO(rx_jabber_frames)}, | ||
341 | {GBE_STATSA_INFO(rx_undersized_frames)}, | ||
342 | {GBE_STATSA_INFO(rx_fragments)}, | ||
343 | {GBE_STATSA_INFO(rx_bytes)}, | ||
344 | {GBE_STATSA_INFO(tx_good_frames)}, | ||
345 | {GBE_STATSA_INFO(tx_broadcast_frames)}, | ||
346 | {GBE_STATSA_INFO(tx_multicast_frames)}, | ||
347 | {GBE_STATSA_INFO(tx_pause_frames)}, | ||
348 | {GBE_STATSA_INFO(tx_deferred_frames)}, | ||
349 | {GBE_STATSA_INFO(tx_collision_frames)}, | ||
350 | {GBE_STATSA_INFO(tx_single_coll_frames)}, | ||
351 | {GBE_STATSA_INFO(tx_mult_coll_frames)}, | ||
352 | {GBE_STATSA_INFO(tx_excessive_collisions)}, | ||
353 | {GBE_STATSA_INFO(tx_late_collisions)}, | ||
354 | {GBE_STATSA_INFO(tx_underrun)}, | ||
355 | {GBE_STATSA_INFO(tx_carrier_sense_errors)}, | ||
356 | {GBE_STATSA_INFO(tx_bytes)}, | ||
357 | {GBE_STATSA_INFO(tx_64byte_frames)}, | ||
358 | {GBE_STATSA_INFO(tx_65_to_127byte_frames)}, | ||
359 | {GBE_STATSA_INFO(tx_128_to_255byte_frames)}, | ||
360 | {GBE_STATSA_INFO(tx_256_to_511byte_frames)}, | ||
361 | {GBE_STATSA_INFO(tx_512_to_1023byte_frames)}, | ||
362 | {GBE_STATSA_INFO(tx_1024byte_frames)}, | ||
363 | {GBE_STATSA_INFO(net_bytes)}, | ||
364 | {GBE_STATSA_INFO(rx_sof_overruns)}, | ||
365 | {GBE_STATSA_INFO(rx_mof_overruns)}, | ||
366 | {GBE_STATSA_INFO(rx_dma_overruns)}, | ||
367 | /* GBE module B */ | ||
368 | {GBE_STATSB_INFO(rx_good_frames)}, | ||
369 | {GBE_STATSB_INFO(rx_broadcast_frames)}, | ||
370 | {GBE_STATSB_INFO(rx_multicast_frames)}, | ||
371 | {GBE_STATSB_INFO(rx_pause_frames)}, | ||
372 | {GBE_STATSB_INFO(rx_crc_errors)}, | ||
373 | {GBE_STATSB_INFO(rx_align_code_errors)}, | ||
374 | {GBE_STATSB_INFO(rx_oversized_frames)}, | ||
375 | {GBE_STATSB_INFO(rx_jabber_frames)}, | ||
376 | {GBE_STATSB_INFO(rx_undersized_frames)}, | ||
377 | {GBE_STATSB_INFO(rx_fragments)}, | ||
378 | {GBE_STATSB_INFO(rx_bytes)}, | ||
379 | {GBE_STATSB_INFO(tx_good_frames)}, | ||
380 | {GBE_STATSB_INFO(tx_broadcast_frames)}, | ||
381 | {GBE_STATSB_INFO(tx_multicast_frames)}, | ||
382 | {GBE_STATSB_INFO(tx_pause_frames)}, | ||
383 | {GBE_STATSB_INFO(tx_deferred_frames)}, | ||
384 | {GBE_STATSB_INFO(tx_collision_frames)}, | ||
385 | {GBE_STATSB_INFO(tx_single_coll_frames)}, | ||
386 | {GBE_STATSB_INFO(tx_mult_coll_frames)}, | ||
387 | {GBE_STATSB_INFO(tx_excessive_collisions)}, | ||
388 | {GBE_STATSB_INFO(tx_late_collisions)}, | ||
389 | {GBE_STATSB_INFO(tx_underrun)}, | ||
390 | {GBE_STATSB_INFO(tx_carrier_sense_errors)}, | ||
391 | {GBE_STATSB_INFO(tx_bytes)}, | ||
392 | {GBE_STATSB_INFO(tx_64byte_frames)}, | ||
393 | {GBE_STATSB_INFO(tx_65_to_127byte_frames)}, | ||
394 | {GBE_STATSB_INFO(tx_128_to_255byte_frames)}, | ||
395 | {GBE_STATSB_INFO(tx_256_to_511byte_frames)}, | ||
396 | {GBE_STATSB_INFO(tx_512_to_1023byte_frames)}, | ||
397 | {GBE_STATSB_INFO(tx_1024byte_frames)}, | ||
398 | {GBE_STATSB_INFO(net_bytes)}, | ||
399 | {GBE_STATSB_INFO(rx_sof_overruns)}, | ||
400 | {GBE_STATSB_INFO(rx_mof_overruns)}, | ||
401 | {GBE_STATSB_INFO(rx_dma_overruns)}, | ||
402 | /* GBE module C */ | ||
403 | {GBE_STATSC_INFO(rx_good_frames)}, | ||
404 | {GBE_STATSC_INFO(rx_broadcast_frames)}, | ||
405 | {GBE_STATSC_INFO(rx_multicast_frames)}, | ||
406 | {GBE_STATSC_INFO(rx_pause_frames)}, | ||
407 | {GBE_STATSC_INFO(rx_crc_errors)}, | ||
408 | {GBE_STATSC_INFO(rx_align_code_errors)}, | ||
409 | {GBE_STATSC_INFO(rx_oversized_frames)}, | ||
410 | {GBE_STATSC_INFO(rx_jabber_frames)}, | ||
411 | {GBE_STATSC_INFO(rx_undersized_frames)}, | ||
412 | {GBE_STATSC_INFO(rx_fragments)}, | ||
413 | {GBE_STATSC_INFO(rx_bytes)}, | ||
414 | {GBE_STATSC_INFO(tx_good_frames)}, | ||
415 | {GBE_STATSC_INFO(tx_broadcast_frames)}, | ||
416 | {GBE_STATSC_INFO(tx_multicast_frames)}, | ||
417 | {GBE_STATSC_INFO(tx_pause_frames)}, | ||
418 | {GBE_STATSC_INFO(tx_deferred_frames)}, | ||
419 | {GBE_STATSC_INFO(tx_collision_frames)}, | ||
420 | {GBE_STATSC_INFO(tx_single_coll_frames)}, | ||
421 | {GBE_STATSC_INFO(tx_mult_coll_frames)}, | ||
422 | {GBE_STATSC_INFO(tx_excessive_collisions)}, | ||
423 | {GBE_STATSC_INFO(tx_late_collisions)}, | ||
424 | {GBE_STATSC_INFO(tx_underrun)}, | ||
425 | {GBE_STATSC_INFO(tx_carrier_sense_errors)}, | ||
426 | {GBE_STATSC_INFO(tx_bytes)}, | ||
427 | {GBE_STATSC_INFO(tx_64byte_frames)}, | ||
428 | {GBE_STATSC_INFO(tx_65_to_127byte_frames)}, | ||
429 | {GBE_STATSC_INFO(tx_128_to_255byte_frames)}, | ||
430 | {GBE_STATSC_INFO(tx_256_to_511byte_frames)}, | ||
431 | {GBE_STATSC_INFO(tx_512_to_1023byte_frames)}, | ||
432 | {GBE_STATSC_INFO(tx_1024byte_frames)}, | ||
433 | {GBE_STATSC_INFO(net_bytes)}, | ||
434 | {GBE_STATSC_INFO(rx_sof_overruns)}, | ||
435 | {GBE_STATSC_INFO(rx_mof_overruns)}, | ||
436 | {GBE_STATSC_INFO(rx_dma_overruns)}, | ||
437 | /* GBE module D */ | ||
438 | {GBE_STATSD_INFO(rx_good_frames)}, | ||
439 | {GBE_STATSD_INFO(rx_broadcast_frames)}, | ||
440 | {GBE_STATSD_INFO(rx_multicast_frames)}, | ||
441 | {GBE_STATSD_INFO(rx_pause_frames)}, | ||
442 | {GBE_STATSD_INFO(rx_crc_errors)}, | ||
443 | {GBE_STATSD_INFO(rx_align_code_errors)}, | ||
444 | {GBE_STATSD_INFO(rx_oversized_frames)}, | ||
445 | {GBE_STATSD_INFO(rx_jabber_frames)}, | ||
446 | {GBE_STATSD_INFO(rx_undersized_frames)}, | ||
447 | {GBE_STATSD_INFO(rx_fragments)}, | ||
448 | {GBE_STATSD_INFO(rx_bytes)}, | ||
449 | {GBE_STATSD_INFO(tx_good_frames)}, | ||
450 | {GBE_STATSD_INFO(tx_broadcast_frames)}, | ||
451 | {GBE_STATSD_INFO(tx_multicast_frames)}, | ||
452 | {GBE_STATSD_INFO(tx_pause_frames)}, | ||
453 | {GBE_STATSD_INFO(tx_deferred_frames)}, | ||
454 | {GBE_STATSD_INFO(tx_collision_frames)}, | ||
455 | {GBE_STATSD_INFO(tx_single_coll_frames)}, | ||
456 | {GBE_STATSD_INFO(tx_mult_coll_frames)}, | ||
457 | {GBE_STATSD_INFO(tx_excessive_collisions)}, | ||
458 | {GBE_STATSD_INFO(tx_late_collisions)}, | ||
459 | {GBE_STATSD_INFO(tx_underrun)}, | ||
460 | {GBE_STATSD_INFO(tx_carrier_sense_errors)}, | ||
461 | {GBE_STATSD_INFO(tx_bytes)}, | ||
462 | {GBE_STATSD_INFO(tx_64byte_frames)}, | ||
463 | {GBE_STATSD_INFO(tx_65_to_127byte_frames)}, | ||
464 | {GBE_STATSD_INFO(tx_128_to_255byte_frames)}, | ||
465 | {GBE_STATSD_INFO(tx_256_to_511byte_frames)}, | ||
466 | {GBE_STATSD_INFO(tx_512_to_1023byte_frames)}, | ||
467 | {GBE_STATSD_INFO(tx_1024byte_frames)}, | ||
468 | {GBE_STATSD_INFO(net_bytes)}, | ||
469 | {GBE_STATSD_INFO(rx_sof_overruns)}, | ||
470 | {GBE_STATSD_INFO(rx_mof_overruns)}, | ||
471 | {GBE_STATSD_INFO(rx_dma_overruns)}, | ||
472 | }; | ||
473 | |||
474 | #define for_each_intf(i, priv) \ | ||
475 | list_for_each_entry((i), &(priv)->gbe_intf_head, gbe_intf_list) | ||
476 | |||
477 | #define for_each_sec_slave(slave, priv) \ | ||
478 | list_for_each_entry((slave), &(priv)->secondary_slaves, slave_list) | ||
479 | |||
480 | #define first_sec_slave(priv) \ | ||
481 | list_first_entry(&priv->secondary_slaves, \ | ||
482 | struct gbe_slave, slave_list) | ||
483 | |||
484 | static void keystone_get_drvinfo(struct net_device *ndev, | ||
485 | struct ethtool_drvinfo *info) | ||
486 | { | ||
487 | strncpy(info->driver, NETCP_DRIVER_NAME, sizeof(info->driver)); | ||
488 | strncpy(info->version, NETCP_DRIVER_VERSION, sizeof(info->version)); | ||
489 | } | ||
490 | |||
491 | static u32 keystone_get_msglevel(struct net_device *ndev) | ||
492 | { | ||
493 | struct netcp_intf *netcp = netdev_priv(ndev); | ||
494 | |||
495 | return netcp->msg_enable; | ||
496 | } | ||
497 | |||
498 | static void keystone_set_msglevel(struct net_device *ndev, u32 value) | ||
499 | { | ||
500 | struct netcp_intf *netcp = netdev_priv(ndev); | ||
501 | |||
502 | netcp->msg_enable = value; | ||
503 | } | ||
504 | |||
505 | static void keystone_get_stat_strings(struct net_device *ndev, | ||
506 | uint32_t stringset, uint8_t *data) | ||
507 | { | ||
508 | struct netcp_intf *netcp = netdev_priv(ndev); | ||
509 | struct gbe_intf *gbe_intf; | ||
510 | struct gbe_priv *gbe_dev; | ||
511 | int i; | ||
512 | |||
513 | gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp); | ||
514 | if (!gbe_intf) | ||
515 | return; | ||
516 | gbe_dev = gbe_intf->gbe_dev; | ||
517 | |||
518 | switch (stringset) { | ||
519 | case ETH_SS_STATS: | ||
520 | for (i = 0; i < gbe_dev->num_et_stats; i++) { | ||
521 | memcpy(data, gbe_dev->et_stats[i].desc, | ||
522 | ETH_GSTRING_LEN); | ||
523 | data += ETH_GSTRING_LEN; | ||
524 | } | ||
525 | break; | ||
526 | case ETH_SS_TEST: | ||
527 | break; | ||
528 | } | ||
529 | } | ||
530 | |||
531 | static int keystone_get_sset_count(struct net_device *ndev, int stringset) | ||
532 | { | ||
533 | struct netcp_intf *netcp = netdev_priv(ndev); | ||
534 | struct gbe_intf *gbe_intf; | ||
535 | struct gbe_priv *gbe_dev; | ||
536 | |||
537 | gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp); | ||
538 | if (!gbe_intf) | ||
539 | return -EINVAL; | ||
540 | gbe_dev = gbe_intf->gbe_dev; | ||
541 | |||
542 | switch (stringset) { | ||
543 | case ETH_SS_TEST: | ||
544 | return 0; | ||
545 | case ETH_SS_STATS: | ||
546 | return gbe_dev->num_et_stats; | ||
547 | default: | ||
548 | return -EINVAL; | ||
549 | } | ||
550 | } | ||
551 | |||
552 | static void gbe_update_stats(struct gbe_priv *gbe_dev, uint64_t *data) | ||
553 | { | ||
554 | void __iomem *base = NULL; | ||
555 | u32 __iomem *p; | ||
556 | u32 tmp = 0; | ||
557 | int i; | ||
558 | |||
559 | for (i = 0; i < gbe_dev->num_et_stats; i++) { | ||
560 | base = gbe_dev->hw_stats_regs[gbe_dev->et_stats[i].type]; | ||
561 | p = base + gbe_dev->et_stats[i].offset; | ||
562 | tmp = readl(p); | ||
563 | gbe_dev->hw_stats[i] = gbe_dev->hw_stats[i] + tmp; | ||
564 | if (data) | ||
565 | data[i] = gbe_dev->hw_stats[i]; | ||
566 | /* write-to-decrement: | ||
567 | * new register value = old register value - write value | ||
568 | */ | ||
569 | writel(tmp, p); | ||
570 | } | ||
571 | } | ||
572 | |||
573 | static void gbe_update_stats_ver14(struct gbe_priv *gbe_dev, uint64_t *data) | ||
574 | { | ||
575 | void __iomem *gbe_statsa = gbe_dev->hw_stats_regs[0]; | ||
576 | void __iomem *gbe_statsb = gbe_dev->hw_stats_regs[1]; | ||
577 | u64 *hw_stats = &gbe_dev->hw_stats[0]; | ||
578 | void __iomem *base = NULL; | ||
579 | u32 __iomem *p; | ||
580 | u32 tmp = 0, val, pair_size = (gbe_dev->num_et_stats / 2); | ||
581 | int i, j, pair; | ||
582 | |||
583 | for (pair = 0; pair < 2; pair++) { | ||
584 | val = readl(GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en)); | ||
585 | |||
586 | if (pair == 0) | ||
587 | val &= ~GBE_STATS_CD_SEL; | ||
588 | else | ||
589 | val |= GBE_STATS_CD_SEL; | ||
590 | |||
591 | /* make the stat modules visible */ | ||
592 | writel(val, GBE_REG_ADDR(gbe_dev, switch_regs, stat_port_en)); | ||
593 | |||
594 | for (i = 0; i < pair_size; i++) { | ||
595 | j = pair * pair_size + i; | ||
596 | switch (gbe_dev->et_stats[j].type) { | ||
597 | case GBE_STATSA_MODULE: | ||
598 | case GBE_STATSC_MODULE: | ||
599 | base = gbe_statsa; | ||
600 | break; | ||
601 | case GBE_STATSB_MODULE: | ||
602 | case GBE_STATSD_MODULE: | ||
603 | base = gbe_statsb; | ||
604 | break; | ||
605 | } | ||
606 | |||
607 | p = base + gbe_dev->et_stats[j].offset; | ||
608 | tmp = readl(p); | ||
609 | hw_stats[j] += tmp; | ||
610 | if (data) | ||
611 | data[j] = hw_stats[j]; | ||
612 | /* write-to-decrement: | ||
613 | * new register value = old register value - write value | ||
614 | */ | ||
615 | writel(tmp, p); | ||
616 | } | ||
617 | } | ||
618 | } | ||
619 | |||
620 | static void keystone_get_ethtool_stats(struct net_device *ndev, | ||
621 | struct ethtool_stats *stats, | ||
622 | uint64_t *data) | ||
623 | { | ||
624 | struct netcp_intf *netcp = netdev_priv(ndev); | ||
625 | struct gbe_intf *gbe_intf; | ||
626 | struct gbe_priv *gbe_dev; | ||
627 | |||
628 | gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp); | ||
629 | if (!gbe_intf) | ||
630 | return; | ||
631 | |||
632 | gbe_dev = gbe_intf->gbe_dev; | ||
633 | spin_lock_bh(&gbe_dev->hw_stats_lock); | ||
634 | gbe_update_stats_ver14(gbe_dev, data); | ||
635 | spin_unlock_bh(&gbe_dev->hw_stats_lock); | ||
636 | } | ||
637 | |||
638 | static int keystone_get_settings(struct net_device *ndev, | ||
639 | struct ethtool_cmd *cmd) | ||
640 | { | ||
641 | struct netcp_intf *netcp = netdev_priv(ndev); | ||
642 | struct phy_device *phy = ndev->phydev; | ||
643 | struct gbe_intf *gbe_intf; | ||
644 | int ret; | ||
645 | |||
646 | if (!phy) | ||
647 | return -EINVAL; | ||
648 | |||
649 | gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp); | ||
650 | if (!gbe_intf) | ||
651 | return -EINVAL; | ||
652 | |||
653 | if (!gbe_intf->slave) | ||
654 | return -EINVAL; | ||
655 | |||
656 | ret = phy_ethtool_gset(phy, cmd); | ||
657 | if (!ret) | ||
658 | cmd->port = gbe_intf->slave->phy_port_t; | ||
659 | |||
660 | return ret; | ||
661 | } | ||
662 | |||
663 | static int keystone_set_settings(struct net_device *ndev, | ||
664 | struct ethtool_cmd *cmd) | ||
665 | { | ||
666 | struct netcp_intf *netcp = netdev_priv(ndev); | ||
667 | struct phy_device *phy = ndev->phydev; | ||
668 | struct gbe_intf *gbe_intf; | ||
669 | u32 features = cmd->advertising & cmd->supported; | ||
670 | |||
671 | if (!phy) | ||
672 | return -EINVAL; | ||
673 | |||
674 | gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp); | ||
675 | if (!gbe_intf) | ||
676 | return -EINVAL; | ||
677 | |||
678 | if (!gbe_intf->slave) | ||
679 | return -EINVAL; | ||
680 | |||
681 | if (cmd->port != gbe_intf->slave->phy_port_t) { | ||
682 | if ((cmd->port == PORT_TP) && !(features & ADVERTISED_TP)) | ||
683 | return -EINVAL; | ||
684 | |||
685 | if ((cmd->port == PORT_AUI) && !(features & ADVERTISED_AUI)) | ||
686 | return -EINVAL; | ||
687 | |||
688 | if ((cmd->port == PORT_BNC) && !(features & ADVERTISED_BNC)) | ||
689 | return -EINVAL; | ||
690 | |||
691 | if ((cmd->port == PORT_MII) && !(features & ADVERTISED_MII)) | ||
692 | return -EINVAL; | ||
693 | |||
694 | if ((cmd->port == PORT_FIBRE) && !(features & ADVERTISED_FIBRE)) | ||
695 | return -EINVAL; | ||
696 | } | ||
697 | |||
698 | gbe_intf->slave->phy_port_t = cmd->port; | ||
699 | return phy_ethtool_sset(phy, cmd); | ||
700 | } | ||
701 | |||
702 | static const struct ethtool_ops keystone_ethtool_ops = { | ||
703 | .get_drvinfo = keystone_get_drvinfo, | ||
704 | .get_link = ethtool_op_get_link, | ||
705 | .get_msglevel = keystone_get_msglevel, | ||
706 | .set_msglevel = keystone_set_msglevel, | ||
707 | .get_strings = keystone_get_stat_strings, | ||
708 | .get_sset_count = keystone_get_sset_count, | ||
709 | .get_ethtool_stats = keystone_get_ethtool_stats, | ||
710 | .get_settings = keystone_get_settings, | ||
711 | .set_settings = keystone_set_settings, | ||
712 | }; | ||
713 | |||
714 | #define mac_hi(mac) (((mac)[0] << 0) | ((mac)[1] << 8) | \ | ||
715 | ((mac)[2] << 16) | ((mac)[3] << 24)) | ||
716 | #define mac_lo(mac) (((mac)[4] << 0) | ((mac)[5] << 8)) | ||
717 | |||
718 | static void gbe_set_slave_mac(struct gbe_slave *slave, | ||
719 | struct gbe_intf *gbe_intf) | ||
720 | { | ||
721 | struct net_device *ndev = gbe_intf->ndev; | ||
722 | |||
723 | writel(mac_hi(ndev->dev_addr), GBE_REG_ADDR(slave, port_regs, sa_hi)); | ||
724 | writel(mac_lo(ndev->dev_addr), GBE_REG_ADDR(slave, port_regs, sa_lo)); | ||
725 | } | ||
726 | |||
727 | static int gbe_get_slave_port(struct gbe_priv *priv, u32 slave_num) | ||
728 | { | ||
729 | if (priv->host_port == 0) | ||
730 | return slave_num + 1; | ||
731 | |||
732 | return slave_num; | ||
733 | } | ||
734 | |||
735 | static void netcp_ethss_link_state_action(struct gbe_priv *gbe_dev, | ||
736 | struct net_device *ndev, | ||
737 | struct gbe_slave *slave, | ||
738 | int up) | ||
739 | { | ||
740 | struct phy_device *phy = slave->phy; | ||
741 | u32 mac_control = 0; | ||
742 | |||
743 | if (up) { | ||
744 | mac_control = slave->mac_control; | ||
745 | if (phy && (phy->speed == SPEED_1000)) | ||
746 | mac_control |= MACSL_GIG_MODE; | ||
747 | |||
748 | writel(mac_control, GBE_REG_ADDR(slave, emac_regs, | ||
749 | mac_control)); | ||
750 | |||
751 | cpsw_ale_control_set(gbe_dev->ale, slave->port_num, | ||
752 | ALE_PORT_STATE, | ||
753 | ALE_PORT_STATE_FORWARD); | ||
754 | |||
755 | if (ndev && slave->open) | ||
756 | netif_carrier_on(ndev); | ||
757 | } else { | ||
758 | writel(mac_control, GBE_REG_ADDR(slave, emac_regs, | ||
759 | mac_control)); | ||
760 | cpsw_ale_control_set(gbe_dev->ale, slave->port_num, | ||
761 | ALE_PORT_STATE, | ||
762 | ALE_PORT_STATE_DISABLE); | ||
763 | if (ndev) | ||
764 | netif_carrier_off(ndev); | ||
765 | } | ||
766 | |||
767 | if (phy) | ||
768 | phy_print_status(phy); | ||
769 | } | ||
770 | |||
771 | static bool gbe_phy_link_status(struct gbe_slave *slave) | ||
772 | { | ||
773 | return !slave->phy || slave->phy->link; | ||
774 | } | ||
775 | |||
776 | static void netcp_ethss_update_link_state(struct gbe_priv *gbe_dev, | ||
777 | struct gbe_slave *slave, | ||
778 | struct net_device *ndev) | ||
779 | { | ||
780 | int sp = slave->slave_num; | ||
781 | int phy_link_state, sgmii_link_state = 1, link_state; | ||
782 | |||
783 | if (!slave->open) | ||
784 | return; | ||
785 | |||
786 | sgmii_link_state = netcp_sgmii_get_port_link(SGMII_BASE(sp), sp); | ||
787 | phy_link_state = gbe_phy_link_status(slave); | ||
788 | link_state = phy_link_state & sgmii_link_state; | ||
789 | |||
790 | if (atomic_xchg(&slave->link_state, link_state) != link_state) | ||
791 | netcp_ethss_link_state_action(gbe_dev, ndev, slave, | ||
792 | link_state); | ||
793 | } | ||
794 | |||
795 | static void gbe_adjust_link(struct net_device *ndev) | ||
796 | { | ||
797 | struct netcp_intf *netcp = netdev_priv(ndev); | ||
798 | struct gbe_intf *gbe_intf; | ||
799 | |||
800 | gbe_intf = netcp_module_get_intf_data(&gbe_module, netcp); | ||
801 | if (!gbe_intf) | ||
802 | return; | ||
803 | |||
804 | netcp_ethss_update_link_state(gbe_intf->gbe_dev, gbe_intf->slave, | ||
805 | ndev); | ||
806 | } | ||
807 | |||
808 | static void gbe_adjust_link_sec_slaves(struct net_device *ndev) | ||
809 | { | ||
810 | struct gbe_priv *gbe_dev = netdev_priv(ndev); | ||
811 | struct gbe_slave *slave; | ||
812 | |||
813 | for_each_sec_slave(slave, gbe_dev) | ||
814 | netcp_ethss_update_link_state(gbe_dev, slave, NULL); | ||
815 | } | ||
816 | |||
817 | /* Reset EMAC | ||
818 | * Soft reset is set and polled until clear, or until a timeout occurs | ||
819 | */ | ||
820 | static int gbe_port_reset(struct gbe_slave *slave) | ||
821 | { | ||
822 | u32 i, v; | ||
823 | |||
824 | /* Set the soft reset bit */ | ||
825 | writel(SOFT_RESET, GBE_REG_ADDR(slave, emac_regs, soft_reset)); | ||
826 | |||
827 | /* Wait for the bit to clear */ | ||
828 | for (i = 0; i < DEVICE_EMACSL_RESET_POLL_COUNT; i++) { | ||
829 | v = readl(GBE_REG_ADDR(slave, emac_regs, soft_reset)); | ||
830 | if ((v & SOFT_RESET_MASK) != SOFT_RESET) | ||
831 | return 0; | ||
832 | } | ||
833 | |||
834 | /* Timeout on the reset */ | ||
835 | return GMACSL_RET_WARN_RESET_INCOMPLETE; | ||
836 | } | ||
837 | |||
838 | /* Configure EMAC */ | ||
839 | static void gbe_port_config(struct gbe_priv *gbe_dev, struct gbe_slave *slave, | ||
840 | int max_rx_len) | ||
841 | { | ||
842 | if (max_rx_len > NETCP_MAX_FRAME_SIZE) | ||
843 | max_rx_len = NETCP_MAX_FRAME_SIZE; | ||
844 | |||
845 | writel(max_rx_len, GBE_REG_ADDR(slave, emac_regs, rx_maxlen)); | ||
846 | writel(slave->mac_control, GBE_REG_ADDR(slave, emac_regs, mac_control)); | ||
847 | } | ||
848 | |||
849 | static void gbe_slave_stop(struct gbe_intf *intf) | ||
850 | { | ||
851 | struct gbe_priv *gbe_dev = intf->gbe_dev; | ||
852 | struct gbe_slave *slave = intf->slave; | ||
853 | |||
854 | gbe_port_reset(slave); | ||
855 | /* Disable forwarding */ | ||
856 | cpsw_ale_control_set(gbe_dev->ale, slave->port_num, | ||
857 | ALE_PORT_STATE, ALE_PORT_STATE_DISABLE); | ||
858 | cpsw_ale_del_mcast(gbe_dev->ale, intf->ndev->broadcast, | ||
859 | 1 << slave->port_num, 0, 0); | ||
860 | |||
861 | if (!slave->phy) | ||
862 | return; | ||
863 | |||
864 | phy_stop(slave->phy); | ||
865 | phy_disconnect(slave->phy); | ||
866 | slave->phy = NULL; | ||
867 | } | ||
868 | |||
869 | static void gbe_sgmii_config(struct gbe_priv *priv, struct gbe_slave *slave) | ||
870 | { | ||
871 | void __iomem *sgmii_port_regs; | ||
872 | |||
873 | sgmii_port_regs = priv->sgmii_port_regs; | ||
874 | if ((priv->ss_version == GBE_SS_VERSION_14) && (slave->slave_num >= 2)) | ||
875 | sgmii_port_regs = priv->sgmii_port34_regs; | ||
876 | |||
877 | netcp_sgmii_reset(sgmii_port_regs, slave->slave_num); | ||
878 | netcp_sgmii_config(sgmii_port_regs, slave->slave_num, | ||
879 | slave->link_interface); | ||
880 | } | ||
881 | |||
882 | static int gbe_slave_open(struct gbe_intf *gbe_intf) | ||
883 | { | ||
884 | struct gbe_priv *priv = gbe_intf->gbe_dev; | ||
885 | struct gbe_slave *slave = gbe_intf->slave; | ||
886 | phy_interface_t phy_mode; | ||
887 | bool has_phy = false; | ||
888 | |||
889 | void (*hndlr)(struct net_device *) = gbe_adjust_link; | ||
890 | |||
891 | gbe_sgmii_config(priv, slave); | ||
892 | gbe_port_reset(slave); | ||
893 | gbe_port_config(priv, slave, priv->rx_packet_max); | ||
894 | gbe_set_slave_mac(slave, gbe_intf); | ||
895 | /* enable forwarding */ | ||
896 | cpsw_ale_control_set(priv->ale, slave->port_num, | ||
897 | ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); | ||
898 | cpsw_ale_add_mcast(priv->ale, gbe_intf->ndev->broadcast, | ||
899 | 1 << slave->port_num, 0, 0, ALE_MCAST_FWD_2); | ||
900 | |||
901 | if (slave->link_interface == SGMII_LINK_MAC_PHY) { | ||
902 | has_phy = true; | ||
903 | phy_mode = PHY_INTERFACE_MODE_SGMII; | ||
904 | slave->phy_port_t = PORT_MII; | ||
905 | } else if (slave->link_interface == XGMII_LINK_MAC_PHY) { | ||
906 | has_phy = true; | ||
907 | phy_mode = PHY_INTERFACE_MODE_NA; | ||
908 | slave->phy_port_t = PORT_FIBRE; | ||
909 | } | ||
910 | |||
911 | if (has_phy) { | ||
912 | slave->phy = of_phy_connect(gbe_intf->ndev, | ||
913 | slave->phy_node, | ||
914 | hndlr, 0, | ||
915 | phy_mode); | ||
916 | if (!slave->phy) { | ||
917 | dev_err(priv->dev, "phy not found on slave %d\n", | ||
918 | slave->slave_num); | ||
919 | return -ENODEV; | ||
920 | } | ||
921 | dev_dbg(priv->dev, "phy found: id is: 0x%s\n", | ||
922 | dev_name(&slave->phy->dev)); | ||
923 | phy_start(slave->phy); | ||
924 | phy_read_status(slave->phy); | ||
925 | } | ||
926 | return 0; | ||
927 | } | ||
928 | |||
929 | static void gbe_init_host_port(struct gbe_priv *priv) | ||
930 | { | ||
931 | int bypass_en = 1; | ||
932 | /* Max length register */ | ||
933 | writel(NETCP_MAX_FRAME_SIZE, GBE_REG_ADDR(priv, host_port_regs, | ||
934 | rx_maxlen)); | ||
935 | |||
936 | cpsw_ale_start(priv->ale); | ||
937 | |||
938 | if (priv->enable_ale) | ||
939 | bypass_en = 0; | ||
940 | |||
941 | cpsw_ale_control_set(priv->ale, 0, ALE_BYPASS, bypass_en); | ||
942 | |||
943 | cpsw_ale_control_set(priv->ale, 0, ALE_NO_PORT_VLAN, 1); | ||
944 | |||
945 | cpsw_ale_control_set(priv->ale, priv->host_port, | ||
946 | ALE_PORT_STATE, ALE_PORT_STATE_FORWARD); | ||
947 | |||
948 | cpsw_ale_control_set(priv->ale, 0, | ||
949 | ALE_PORT_UNKNOWN_VLAN_MEMBER, | ||
950 | GBE_PORT_MASK(priv->ale_ports)); | ||
951 | |||
952 | cpsw_ale_control_set(priv->ale, 0, | ||
953 | ALE_PORT_UNKNOWN_MCAST_FLOOD, | ||
954 | GBE_PORT_MASK(priv->ale_ports - 1)); | ||
955 | |||
956 | cpsw_ale_control_set(priv->ale, 0, | ||
957 | ALE_PORT_UNKNOWN_REG_MCAST_FLOOD, | ||
958 | GBE_PORT_MASK(priv->ale_ports)); | ||
959 | |||
960 | cpsw_ale_control_set(priv->ale, 0, | ||
961 | ALE_PORT_UNTAGGED_EGRESS, | ||
962 | GBE_PORT_MASK(priv->ale_ports)); | ||
963 | } | ||
964 | |||
965 | static void gbe_add_mcast_addr(struct gbe_intf *gbe_intf, u8 *addr) | ||
966 | { | ||
967 | struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; | ||
968 | u16 vlan_id; | ||
969 | |||
970 | cpsw_ale_add_mcast(gbe_dev->ale, addr, | ||
971 | GBE_PORT_MASK(gbe_dev->ale_ports), 0, 0, | ||
972 | ALE_MCAST_FWD_2); | ||
973 | for_each_set_bit(vlan_id, gbe_intf->active_vlans, VLAN_N_VID) { | ||
974 | cpsw_ale_add_mcast(gbe_dev->ale, addr, | ||
975 | GBE_PORT_MASK(gbe_dev->ale_ports), | ||
976 | ALE_VLAN, vlan_id, ALE_MCAST_FWD_2); | ||
977 | } | ||
978 | } | ||
979 | |||
980 | static void gbe_add_ucast_addr(struct gbe_intf *gbe_intf, u8 *addr) | ||
981 | { | ||
982 | struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; | ||
983 | u16 vlan_id; | ||
984 | |||
985 | cpsw_ale_add_ucast(gbe_dev->ale, addr, gbe_dev->host_port, 0, 0); | ||
986 | |||
987 | for_each_set_bit(vlan_id, gbe_intf->active_vlans, VLAN_N_VID) | ||
988 | cpsw_ale_add_ucast(gbe_dev->ale, addr, gbe_dev->host_port, | ||
989 | ALE_VLAN, vlan_id); | ||
990 | } | ||
991 | |||
992 | static void gbe_del_mcast_addr(struct gbe_intf *gbe_intf, u8 *addr) | ||
993 | { | ||
994 | struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; | ||
995 | u16 vlan_id; | ||
996 | |||
997 | cpsw_ale_del_mcast(gbe_dev->ale, addr, 0, 0, 0); | ||
998 | |||
999 | for_each_set_bit(vlan_id, gbe_intf->active_vlans, VLAN_N_VID) { | ||
1000 | cpsw_ale_del_mcast(gbe_dev->ale, addr, 0, ALE_VLAN, vlan_id); | ||
1001 | } | ||
1002 | } | ||
1003 | |||
1004 | static void gbe_del_ucast_addr(struct gbe_intf *gbe_intf, u8 *addr) | ||
1005 | { | ||
1006 | struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; | ||
1007 | u16 vlan_id; | ||
1008 | |||
1009 | cpsw_ale_del_ucast(gbe_dev->ale, addr, gbe_dev->host_port, 0, 0); | ||
1010 | |||
1011 | for_each_set_bit(vlan_id, gbe_intf->active_vlans, VLAN_N_VID) { | ||
1012 | cpsw_ale_del_ucast(gbe_dev->ale, addr, gbe_dev->host_port, | ||
1013 | ALE_VLAN, vlan_id); | ||
1014 | } | ||
1015 | } | ||
1016 | |||
1017 | static int gbe_add_addr(void *intf_priv, struct netcp_addr *naddr) | ||
1018 | { | ||
1019 | struct gbe_intf *gbe_intf = intf_priv; | ||
1020 | struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; | ||
1021 | |||
1022 | dev_dbg(gbe_dev->dev, "ethss adding address %pM, type %d\n", | ||
1023 | naddr->addr, naddr->type); | ||
1024 | |||
1025 | switch (naddr->type) { | ||
1026 | case ADDR_MCAST: | ||
1027 | case ADDR_BCAST: | ||
1028 | gbe_add_mcast_addr(gbe_intf, naddr->addr); | ||
1029 | break; | ||
1030 | case ADDR_UCAST: | ||
1031 | case ADDR_DEV: | ||
1032 | gbe_add_ucast_addr(gbe_intf, naddr->addr); | ||
1033 | break; | ||
1034 | case ADDR_ANY: | ||
1035 | /* nothing to do for promiscuous */ | ||
1036 | default: | ||
1037 | break; | ||
1038 | } | ||
1039 | |||
1040 | return 0; | ||
1041 | } | ||
1042 | |||
1043 | static int gbe_del_addr(void *intf_priv, struct netcp_addr *naddr) | ||
1044 | { | ||
1045 | struct gbe_intf *gbe_intf = intf_priv; | ||
1046 | struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; | ||
1047 | |||
1048 | dev_dbg(gbe_dev->dev, "ethss deleting address %pM, type %d\n", | ||
1049 | naddr->addr, naddr->type); | ||
1050 | |||
1051 | switch (naddr->type) { | ||
1052 | case ADDR_MCAST: | ||
1053 | case ADDR_BCAST: | ||
1054 | gbe_del_mcast_addr(gbe_intf, naddr->addr); | ||
1055 | break; | ||
1056 | case ADDR_UCAST: | ||
1057 | case ADDR_DEV: | ||
1058 | gbe_del_ucast_addr(gbe_intf, naddr->addr); | ||
1059 | break; | ||
1060 | case ADDR_ANY: | ||
1061 | /* nothing to do for promiscuous */ | ||
1062 | default: | ||
1063 | break; | ||
1064 | } | ||
1065 | |||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1069 | static int gbe_add_vid(void *intf_priv, int vid) | ||
1070 | { | ||
1071 | struct gbe_intf *gbe_intf = intf_priv; | ||
1072 | struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; | ||
1073 | |||
1074 | set_bit(vid, gbe_intf->active_vlans); | ||
1075 | |||
1076 | cpsw_ale_add_vlan(gbe_dev->ale, vid, | ||
1077 | GBE_PORT_MASK(gbe_dev->ale_ports), | ||
1078 | GBE_MASK_NO_PORTS, | ||
1079 | GBE_PORT_MASK(gbe_dev->ale_ports), | ||
1080 | GBE_PORT_MASK(gbe_dev->ale_ports - 1)); | ||
1081 | |||
1082 | return 0; | ||
1083 | } | ||
1084 | |||
1085 | static int gbe_del_vid(void *intf_priv, int vid) | ||
1086 | { | ||
1087 | struct gbe_intf *gbe_intf = intf_priv; | ||
1088 | struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; | ||
1089 | |||
1090 | cpsw_ale_del_vlan(gbe_dev->ale, vid, 0); | ||
1091 | clear_bit(vid, gbe_intf->active_vlans); | ||
1092 | return 0; | ||
1093 | } | ||
1094 | |||
1095 | static int gbe_ioctl(void *intf_priv, struct ifreq *req, int cmd) | ||
1096 | { | ||
1097 | struct gbe_intf *gbe_intf = intf_priv; | ||
1098 | struct phy_device *phy = gbe_intf->slave->phy; | ||
1099 | int ret = -EOPNOTSUPP; | ||
1100 | |||
1101 | if (phy) | ||
1102 | ret = phy_mii_ioctl(phy, req, cmd); | ||
1103 | |||
1104 | return ret; | ||
1105 | } | ||
1106 | |||
1107 | static void netcp_ethss_timer(unsigned long arg) | ||
1108 | { | ||
1109 | struct gbe_priv *gbe_dev = (struct gbe_priv *)arg; | ||
1110 | struct gbe_intf *gbe_intf; | ||
1111 | struct gbe_slave *slave; | ||
1112 | |||
1113 | /* Check & update SGMII link state of interfaces */ | ||
1114 | for_each_intf(gbe_intf, gbe_dev) { | ||
1115 | if (!gbe_intf->slave->open) | ||
1116 | continue; | ||
1117 | netcp_ethss_update_link_state(gbe_dev, gbe_intf->slave, | ||
1118 | gbe_intf->ndev); | ||
1119 | } | ||
1120 | |||
1121 | /* Check & update SGMII link state of secondary ports */ | ||
1122 | for_each_sec_slave(slave, gbe_dev) { | ||
1123 | netcp_ethss_update_link_state(gbe_dev, slave, NULL); | ||
1124 | } | ||
1125 | |||
1126 | spin_lock_bh(&gbe_dev->hw_stats_lock); | ||
1127 | |||
1128 | if (gbe_dev->ss_version == GBE_SS_VERSION_14) | ||
1129 | gbe_update_stats_ver14(gbe_dev, NULL); | ||
1130 | else | ||
1131 | gbe_update_stats(gbe_dev, NULL); | ||
1132 | |||
1133 | spin_unlock_bh(&gbe_dev->hw_stats_lock); | ||
1134 | |||
1135 | gbe_dev->timer.expires = jiffies + GBE_TIMER_INTERVAL; | ||
1136 | add_timer(&gbe_dev->timer); | ||
1137 | } | ||
1138 | |||
1139 | static int gbe_tx_hook(int order, void *data, struct netcp_packet *p_info) | ||
1140 | { | ||
1141 | struct gbe_intf *gbe_intf = data; | ||
1142 | |||
1143 | p_info->tx_pipe = &gbe_intf->tx_pipe; | ||
1144 | return 0; | ||
1145 | } | ||
1146 | |||
1147 | static int gbe_open(void *intf_priv, struct net_device *ndev) | ||
1148 | { | ||
1149 | struct gbe_intf *gbe_intf = intf_priv; | ||
1150 | struct gbe_priv *gbe_dev = gbe_intf->gbe_dev; | ||
1151 | struct netcp_intf *netcp = netdev_priv(ndev); | ||
1152 | struct gbe_slave *slave = gbe_intf->slave; | ||
1153 | int port_num = slave->port_num; | ||
1154 | u32 reg; | ||
1155 | int ret; | ||
1156 | |||
1157 | reg = readl(GBE_REG_ADDR(gbe_dev, switch_regs, id_ver)); | ||
1158 | dev_dbg(gbe_dev->dev, "initializing gbe version %d.%d (%d) GBE identification value 0x%x\n", | ||
1159 | GBE_MAJOR_VERSION(reg), GBE_MINOR_VERSION(reg), | ||
1160 | GBE_RTL_VERSION(reg), GBE_IDENT(reg)); | ||
1161 | |||
1162 | if (gbe_dev->enable_ale) | ||
1163 | gbe_intf->tx_pipe.dma_psflags = 0; | ||
1164 | else | ||
1165 | gbe_intf->tx_pipe.dma_psflags = port_num; | ||
1166 | |||
1167 | dev_dbg(gbe_dev->dev, "opened TX channel %s: %p with psflags %d\n", | ||
1168 | gbe_intf->tx_pipe.dma_chan_name, | ||
1169 | gbe_intf->tx_pipe.dma_channel, | ||
1170 | gbe_intf->tx_pipe.dma_psflags); | ||
1171 | |||
1172 | gbe_slave_stop(gbe_intf); | ||
1173 | |||
1174 | /* disable priority elevation and enable statistics on all ports */ | ||
1175 | writel(0, GBE_REG_ADDR(gbe_dev, switch_regs, ptype)); | ||
1176 | |||
1177 | /* Control register */ | ||
1178 | writel(GBE_CTL_P0_ENABLE, GBE_REG_ADDR(gbe_dev, switch_regs, control)); | ||
1179 | |||
1180 | /* All statistics enabled and STAT AB visible by default */ | ||
1181 | writel(GBE_REG_VAL_STAT_ENABLE_ALL, GBE_REG_ADDR(gbe_dev, switch_regs, | ||
1182 | stat_port_en)); | ||
1183 | |||
1184 | ret = gbe_slave_open(gbe_intf); | ||
1185 | if (ret) | ||
1186 | goto fail; | ||
1187 | |||
1188 | netcp_register_txhook(netcp, GBE_TXHOOK_ORDER, gbe_tx_hook, | ||
1189 | gbe_intf); | ||
1190 | |||
1191 | slave->open = true; | ||
1192 | netcp_ethss_update_link_state(gbe_dev, slave, ndev); | ||
1193 | return 0; | ||
1194 | |||
1195 | fail: | ||
1196 | gbe_slave_stop(gbe_intf); | ||
1197 | return ret; | ||
1198 | } | ||
1199 | |||
1200 | static int gbe_close(void *intf_priv, struct net_device *ndev) | ||
1201 | { | ||
1202 | struct gbe_intf *gbe_intf = intf_priv; | ||
1203 | struct netcp_intf *netcp = netdev_priv(ndev); | ||
1204 | |||
1205 | gbe_slave_stop(gbe_intf); | ||
1206 | netcp_unregister_txhook(netcp, GBE_TXHOOK_ORDER, gbe_tx_hook, | ||
1207 | gbe_intf); | ||
1208 | |||
1209 | gbe_intf->slave->open = false; | ||
1210 | atomic_set(&gbe_intf->slave->link_state, NETCP_LINK_STATE_INVALID); | ||
1211 | return 0; | ||
1212 | } | ||
1213 | |||
1214 | static int init_slave(struct gbe_priv *gbe_dev, struct gbe_slave *slave, | ||
1215 | struct device_node *node) | ||
1216 | { | ||
1217 | int port_reg_num; | ||
1218 | u32 port_reg_ofs, emac_reg_ofs; | ||
1219 | |||
1220 | if (of_property_read_u32(node, "slave-port", &slave->slave_num)) { | ||
1221 | dev_err(gbe_dev->dev, "missing slave-port parameter\n"); | ||
1222 | return -EINVAL; | ||
1223 | } | ||
1224 | |||
1225 | if (of_property_read_u32(node, "link-interface", | ||
1226 | &slave->link_interface)) { | ||
1227 | dev_warn(gbe_dev->dev, | ||
1228 | "missing link-interface value defaulting to 1G mac-phy link\n"); | ||
1229 | slave->link_interface = SGMII_LINK_MAC_PHY; | ||
1230 | } | ||
1231 | |||
1232 | slave->open = false; | ||
1233 | slave->phy_node = of_parse_phandle(node, "phy-handle", 0); | ||
1234 | slave->port_num = gbe_get_slave_port(gbe_dev, slave->slave_num); | ||
1235 | |||
1236 | slave->mac_control = GBE_DEF_1G_MAC_CONTROL; | ||
1237 | |||
1238 | /* Emac regs memmap are contiguous but port regs are not */ | ||
1239 | port_reg_num = slave->slave_num; | ||
1240 | if (gbe_dev->ss_version == GBE_SS_VERSION_14) { | ||
1241 | if (slave->slave_num > 1) { | ||
1242 | port_reg_ofs = GBE13_SLAVE_PORT2_OFFSET; | ||
1243 | port_reg_num -= 2; | ||
1244 | } else { | ||
1245 | port_reg_ofs = GBE13_SLAVE_PORT_OFFSET; | ||
1246 | } | ||
1247 | } else { | ||
1248 | dev_err(gbe_dev->dev, "unknown ethss(0x%x)\n", | ||
1249 | gbe_dev->ss_version); | ||
1250 | return -EINVAL; | ||
1251 | } | ||
1252 | |||
1253 | if (gbe_dev->ss_version == GBE_SS_VERSION_14) | ||
1254 | emac_reg_ofs = GBE13_EMAC_OFFSET; | ||
1255 | |||
1256 | slave->port_regs = gbe_dev->ss_regs + port_reg_ofs + | ||
1257 | (0x30 * port_reg_num); | ||
1258 | slave->emac_regs = gbe_dev->ss_regs + emac_reg_ofs + | ||
1259 | (0x40 * slave->slave_num); | ||
1260 | |||
1261 | if (gbe_dev->ss_version == GBE_SS_VERSION_14) { | ||
1262 | /* Initialize slave port register offsets */ | ||
1263 | GBE_SET_REG_OFS(slave, port_regs, port_vlan); | ||
1264 | GBE_SET_REG_OFS(slave, port_regs, tx_pri_map); | ||
1265 | GBE_SET_REG_OFS(slave, port_regs, sa_lo); | ||
1266 | GBE_SET_REG_OFS(slave, port_regs, sa_hi); | ||
1267 | GBE_SET_REG_OFS(slave, port_regs, ts_ctl); | ||
1268 | GBE_SET_REG_OFS(slave, port_regs, ts_seq_ltype); | ||
1269 | GBE_SET_REG_OFS(slave, port_regs, ts_vlan); | ||
1270 | GBE_SET_REG_OFS(slave, port_regs, ts_ctl_ltype2); | ||
1271 | GBE_SET_REG_OFS(slave, port_regs, ts_ctl2); | ||
1272 | |||
1273 | /* Initialize EMAC register offsets */ | ||
1274 | GBE_SET_REG_OFS(slave, emac_regs, mac_control); | ||
1275 | GBE_SET_REG_OFS(slave, emac_regs, soft_reset); | ||
1276 | GBE_SET_REG_OFS(slave, emac_regs, rx_maxlen); | ||
1277 | |||
1278 | } else { | ||
1279 | dev_err(gbe_dev->dev, "unknown ethss(0x%x)\n", | ||
1280 | gbe_dev->ss_version); | ||
1281 | return -EINVAL; | ||
1282 | } | ||
1283 | |||
1284 | atomic_set(&slave->link_state, NETCP_LINK_STATE_INVALID); | ||
1285 | return 0; | ||
1286 | } | ||
1287 | |||
1288 | static void init_secondary_ports(struct gbe_priv *gbe_dev, | ||
1289 | struct device_node *node) | ||
1290 | { | ||
1291 | struct device *dev = gbe_dev->dev; | ||
1292 | phy_interface_t phy_mode; | ||
1293 | struct gbe_priv **priv; | ||
1294 | struct device_node *port; | ||
1295 | struct gbe_slave *slave; | ||
1296 | bool mac_phy_link = false; | ||
1297 | |||
1298 | for_each_child_of_node(node, port) { | ||
1299 | slave = devm_kzalloc(dev, sizeof(*slave), GFP_KERNEL); | ||
1300 | if (!slave) { | ||
1301 | dev_err(dev, | ||
1302 | "memomry alloc failed for secondary port(%s), skipping...\n", | ||
1303 | port->name); | ||
1304 | continue; | ||
1305 | } | ||
1306 | |||
1307 | if (init_slave(gbe_dev, slave, port)) { | ||
1308 | dev_err(dev, | ||
1309 | "Failed to initialize secondary port(%s), skipping...\n", | ||
1310 | port->name); | ||
1311 | devm_kfree(dev, slave); | ||
1312 | continue; | ||
1313 | } | ||
1314 | |||
1315 | gbe_sgmii_config(gbe_dev, slave); | ||
1316 | gbe_port_reset(slave); | ||
1317 | gbe_port_config(gbe_dev, slave, gbe_dev->rx_packet_max); | ||
1318 | list_add_tail(&slave->slave_list, &gbe_dev->secondary_slaves); | ||
1319 | gbe_dev->num_slaves++; | ||
1320 | if (slave->link_interface == SGMII_LINK_MAC_PHY) | ||
1321 | mac_phy_link = true; | ||
1322 | |||
1323 | slave->open = true; | ||
1324 | } | ||
1325 | |||
1326 | /* of_phy_connect() is needed only for MAC-PHY interface */ | ||
1327 | if (!mac_phy_link) | ||
1328 | return; | ||
1329 | |||
1330 | /* Allocate dummy netdev device for attaching to phy device */ | ||
1331 | gbe_dev->dummy_ndev = alloc_netdev(sizeof(gbe_dev), "dummy", | ||
1332 | NET_NAME_UNKNOWN, ether_setup); | ||
1333 | if (!gbe_dev->dummy_ndev) { | ||
1334 | dev_err(dev, | ||
1335 | "Failed to allocate dummy netdev for secondary ports, skipping phy_connect()...\n"); | ||
1336 | return; | ||
1337 | } | ||
1338 | priv = netdev_priv(gbe_dev->dummy_ndev); | ||
1339 | *priv = gbe_dev; | ||
1340 | |||
1341 | if (slave->link_interface == SGMII_LINK_MAC_PHY) { | ||
1342 | phy_mode = PHY_INTERFACE_MODE_SGMII; | ||
1343 | slave->phy_port_t = PORT_MII; | ||
1344 | } else { | ||
1345 | phy_mode = PHY_INTERFACE_MODE_NA; | ||
1346 | slave->phy_port_t = PORT_FIBRE; | ||
1347 | } | ||
1348 | |||
1349 | for_each_sec_slave(slave, gbe_dev) { | ||
1350 | if (slave->link_interface != SGMII_LINK_MAC_PHY) | ||
1351 | continue; | ||
1352 | slave->phy = | ||
1353 | of_phy_connect(gbe_dev->dummy_ndev, | ||
1354 | slave->phy_node, | ||
1355 | gbe_adjust_link_sec_slaves, | ||
1356 | 0, phy_mode); | ||
1357 | if (!slave->phy) { | ||
1358 | dev_err(dev, "phy not found for slave %d\n", | ||
1359 | slave->slave_num); | ||
1360 | slave->phy = NULL; | ||
1361 | } else { | ||
1362 | dev_dbg(dev, "phy found: id is: 0x%s\n", | ||
1363 | dev_name(&slave->phy->dev)); | ||
1364 | phy_start(slave->phy); | ||
1365 | phy_read_status(slave->phy); | ||
1366 | } | ||
1367 | } | ||
1368 | } | ||
1369 | |||
1370 | static void free_secondary_ports(struct gbe_priv *gbe_dev) | ||
1371 | { | ||
1372 | struct gbe_slave *slave; | ||
1373 | |||
1374 | for (;;) { | ||
1375 | slave = first_sec_slave(gbe_dev); | ||
1376 | if (!slave) | ||
1377 | break; | ||
1378 | if (slave->phy) | ||
1379 | phy_disconnect(slave->phy); | ||
1380 | list_del(&slave->slave_list); | ||
1381 | } | ||
1382 | if (gbe_dev->dummy_ndev) | ||
1383 | free_netdev(gbe_dev->dummy_ndev); | ||
1384 | } | ||
1385 | |||
1386 | static int get_gbe_resource_version(struct gbe_priv *gbe_dev, | ||
1387 | struct device_node *node) | ||
1388 | { | ||
1389 | struct resource res; | ||
1390 | void __iomem *regs; | ||
1391 | int ret; | ||
1392 | |||
1393 | ret = of_address_to_resource(node, 0, &res); | ||
1394 | if (ret) { | ||
1395 | dev_err(gbe_dev->dev, "Can't translate of node(%s) address\n", | ||
1396 | node->name); | ||
1397 | return ret; | ||
1398 | } | ||
1399 | |||
1400 | regs = devm_ioremap_resource(gbe_dev->dev, &res); | ||
1401 | if (IS_ERR(regs)) { | ||
1402 | dev_err(gbe_dev->dev, "Failed to map gbe register base\n"); | ||
1403 | return PTR_ERR(regs); | ||
1404 | } | ||
1405 | gbe_dev->ss_regs = regs; | ||
1406 | gbe_dev->ss_version = readl(gbe_dev->ss_regs); | ||
1407 | return 0; | ||
1408 | } | ||
1409 | |||
1410 | static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev, | ||
1411 | struct device_node *node) | ||
1412 | { | ||
1413 | void __iomem *regs; | ||
1414 | int i; | ||
1415 | |||
1416 | gbe_dev->hw_stats = devm_kzalloc(gbe_dev->dev, | ||
1417 | GBE13_NUM_HW_STAT_ENTRIES * | ||
1418 | GBE13_NUM_SLAVES * sizeof(u64), | ||
1419 | GFP_KERNEL); | ||
1420 | if (!gbe_dev->hw_stats) { | ||
1421 | dev_err(gbe_dev->dev, "hw_stats memory allocation failed\n"); | ||
1422 | return -ENOMEM; | ||
1423 | } | ||
1424 | |||
1425 | regs = gbe_dev->ss_regs; | ||
1426 | gbe_dev->sgmii_port_regs = regs + GBE13_SGMII_MODULE_OFFSET; | ||
1427 | gbe_dev->sgmii_port34_regs = regs + GBE13_SGMII34_MODULE_OFFSET; | ||
1428 | gbe_dev->switch_regs = regs + GBE13_SWITCH_MODULE_OFFSET; | ||
1429 | gbe_dev->host_port_regs = regs + GBE13_HOST_PORT_OFFSET; | ||
1430 | |||
1431 | for (i = 0; i < GBE13_NUM_HW_STATS_MOD; i++) | ||
1432 | gbe_dev->hw_stats_regs[i] = regs + GBE13_HW_STATS_OFFSET + | ||
1433 | (GBE_HW_STATS_REG_MAP_SZ * i); | ||
1434 | |||
1435 | gbe_dev->ale_reg = regs + GBE13_ALE_OFFSET; | ||
1436 | gbe_dev->ale_ports = GBE13_NUM_ALE_PORTS; | ||
1437 | gbe_dev->host_port = GBE13_HOST_PORT_NUM; | ||
1438 | gbe_dev->ale_entries = GBE13_NUM_ALE_ENTRIES; | ||
1439 | gbe_dev->et_stats = gbe13_et_stats; | ||
1440 | gbe_dev->num_et_stats = ARRAY_SIZE(gbe13_et_stats); | ||
1441 | |||
1442 | /* Subsystem registers */ | ||
1443 | GBE_SET_REG_OFS(gbe_dev, ss_regs, id_ver); | ||
1444 | |||
1445 | /* Switch module registers */ | ||
1446 | GBE_SET_REG_OFS(gbe_dev, switch_regs, id_ver); | ||
1447 | GBE_SET_REG_OFS(gbe_dev, switch_regs, control); | ||
1448 | GBE_SET_REG_OFS(gbe_dev, switch_regs, soft_reset); | ||
1449 | GBE_SET_REG_OFS(gbe_dev, switch_regs, stat_port_en); | ||
1450 | GBE_SET_REG_OFS(gbe_dev, switch_regs, ptype); | ||
1451 | GBE_SET_REG_OFS(gbe_dev, switch_regs, flow_control); | ||
1452 | |||
1453 | /* Host port registers */ | ||
1454 | GBE_SET_REG_OFS(gbe_dev, host_port_regs, port_vlan); | ||
1455 | GBE_SET_REG_OFS(gbe_dev, host_port_regs, rx_maxlen); | ||
1456 | return 0; | ||
1457 | } | ||
1458 | |||
1459 | static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, | ||
1460 | struct device_node *node, void **inst_priv) | ||
1461 | { | ||
1462 | struct device_node *interfaces, *interface; | ||
1463 | struct device_node *secondary_ports; | ||
1464 | struct cpsw_ale_params ale_params; | ||
1465 | struct gbe_priv *gbe_dev; | ||
1466 | u32 slave_num; | ||
1467 | int ret = 0; | ||
1468 | |||
1469 | if (!node) { | ||
1470 | dev_err(dev, "device tree info unavailable\n"); | ||
1471 | return -ENODEV; | ||
1472 | } | ||
1473 | |||
1474 | gbe_dev = devm_kzalloc(dev, sizeof(struct gbe_priv), GFP_KERNEL); | ||
1475 | if (!gbe_dev) | ||
1476 | return -ENOMEM; | ||
1477 | |||
1478 | gbe_dev->dev = dev; | ||
1479 | gbe_dev->netcp_device = netcp_device; | ||
1480 | gbe_dev->rx_packet_max = NETCP_MAX_FRAME_SIZE; | ||
1481 | |||
1482 | /* init the hw stats lock */ | ||
1483 | spin_lock_init(&gbe_dev->hw_stats_lock); | ||
1484 | |||
1485 | if (of_find_property(node, "enable-ale", NULL)) { | ||
1486 | gbe_dev->enable_ale = true; | ||
1487 | dev_info(dev, "ALE enabled\n"); | ||
1488 | } else { | ||
1489 | gbe_dev->enable_ale = false; | ||
1490 | dev_dbg(dev, "ALE bypass enabled*\n"); | ||
1491 | } | ||
1492 | |||
1493 | ret = of_property_read_u32(node, "tx-queue", | ||
1494 | &gbe_dev->tx_queue_id); | ||
1495 | if (ret < 0) { | ||
1496 | dev_err(dev, "missing tx_queue parameter\n"); | ||
1497 | gbe_dev->tx_queue_id = GBE_TX_QUEUE; | ||
1498 | } | ||
1499 | |||
1500 | ret = of_property_read_string(node, "tx-channel", | ||
1501 | &gbe_dev->dma_chan_name); | ||
1502 | if (ret < 0) { | ||
1503 | dev_err(dev, "missing \"tx-channel\" parameter\n"); | ||
1504 | ret = -ENODEV; | ||
1505 | goto quit; | ||
1506 | } | ||
1507 | |||
1508 | if (!strcmp(node->name, "gbe")) { | ||
1509 | ret = get_gbe_resource_version(gbe_dev, node); | ||
1510 | if (ret) | ||
1511 | goto quit; | ||
1512 | |||
1513 | ret = set_gbe_ethss14_priv(gbe_dev, node); | ||
1514 | if (ret) | ||
1515 | goto quit; | ||
1516 | } else { | ||
1517 | dev_err(dev, "unknown GBE node(%s)\n", node->name); | ||
1518 | ret = -ENODEV; | ||
1519 | goto quit; | ||
1520 | } | ||
1521 | |||
1522 | interfaces = of_get_child_by_name(node, "interfaces"); | ||
1523 | if (!interfaces) | ||
1524 | dev_err(dev, "could not find interfaces\n"); | ||
1525 | |||
1526 | ret = netcp_txpipe_init(&gbe_dev->tx_pipe, netcp_device, | ||
1527 | gbe_dev->dma_chan_name, gbe_dev->tx_queue_id); | ||
1528 | if (ret) | ||
1529 | goto quit; | ||
1530 | |||
1531 | ret = netcp_txpipe_open(&gbe_dev->tx_pipe); | ||
1532 | if (ret) | ||
1533 | goto quit; | ||
1534 | |||
1535 | /* Create network interfaces */ | ||
1536 | INIT_LIST_HEAD(&gbe_dev->gbe_intf_head); | ||
1537 | for_each_child_of_node(interfaces, interface) { | ||
1538 | ret = of_property_read_u32(interface, "slave-port", &slave_num); | ||
1539 | if (ret) { | ||
1540 | dev_err(dev, "missing slave-port parameter, skipping interface configuration for %s\n", | ||
1541 | interface->name); | ||
1542 | continue; | ||
1543 | } | ||
1544 | gbe_dev->num_slaves++; | ||
1545 | } | ||
1546 | |||
1547 | if (!gbe_dev->num_slaves) | ||
1548 | dev_warn(dev, "No network interface configured\n"); | ||
1549 | |||
1550 | /* Initialize Secondary slave ports */ | ||
1551 | secondary_ports = of_get_child_by_name(node, "secondary-slave-ports"); | ||
1552 | INIT_LIST_HEAD(&gbe_dev->secondary_slaves); | ||
1553 | if (secondary_ports) | ||
1554 | init_secondary_ports(gbe_dev, secondary_ports); | ||
1555 | of_node_put(secondary_ports); | ||
1556 | |||
1557 | if (!gbe_dev->num_slaves) { | ||
1558 | dev_err(dev, "No network interface or secondary ports configured\n"); | ||
1559 | ret = -ENODEV; | ||
1560 | goto quit; | ||
1561 | } | ||
1562 | |||
1563 | memset(&ale_params, 0, sizeof(ale_params)); | ||
1564 | ale_params.dev = gbe_dev->dev; | ||
1565 | ale_params.ale_regs = gbe_dev->ale_reg; | ||
1566 | ale_params.ale_ageout = GBE_DEFAULT_ALE_AGEOUT; | ||
1567 | ale_params.ale_entries = gbe_dev->ale_entries; | ||
1568 | ale_params.ale_ports = gbe_dev->ale_ports; | ||
1569 | |||
1570 | gbe_dev->ale = cpsw_ale_create(&ale_params); | ||
1571 | if (!gbe_dev->ale) { | ||
1572 | dev_err(gbe_dev->dev, "error initializing ale engine\n"); | ||
1573 | ret = -ENODEV; | ||
1574 | goto quit; | ||
1575 | } else { | ||
1576 | dev_dbg(gbe_dev->dev, "Created a gbe ale engine\n"); | ||
1577 | } | ||
1578 | |||
1579 | /* initialize host port */ | ||
1580 | gbe_init_host_port(gbe_dev); | ||
1581 | |||
1582 | init_timer(&gbe_dev->timer); | ||
1583 | gbe_dev->timer.data = (unsigned long)gbe_dev; | ||
1584 | gbe_dev->timer.function = netcp_ethss_timer; | ||
1585 | gbe_dev->timer.expires = jiffies + GBE_TIMER_INTERVAL; | ||
1586 | add_timer(&gbe_dev->timer); | ||
1587 | *inst_priv = gbe_dev; | ||
1588 | return 0; | ||
1589 | |||
1590 | quit: | ||
1591 | if (gbe_dev->hw_stats) | ||
1592 | devm_kfree(dev, gbe_dev->hw_stats); | ||
1593 | if (gbe_dev->ale) | ||
1594 | cpsw_ale_destroy(gbe_dev->ale); | ||
1595 | if (gbe_dev->ss_regs) | ||
1596 | devm_iounmap(dev, gbe_dev->ss_regs); | ||
1597 | if (interfaces) | ||
1598 | of_node_put(interfaces); | ||
1599 | devm_kfree(dev, gbe_dev); | ||
1600 | return ret; | ||
1601 | } | ||
1602 | |||
1603 | static int gbe_attach(void *inst_priv, struct net_device *ndev, | ||
1604 | struct device_node *node, void **intf_priv) | ||
1605 | { | ||
1606 | struct gbe_priv *gbe_dev = inst_priv; | ||
1607 | struct gbe_intf *gbe_intf; | ||
1608 | int ret; | ||
1609 | |||
1610 | if (!node) { | ||
1611 | dev_err(gbe_dev->dev, "interface node not available\n"); | ||
1612 | return -ENODEV; | ||
1613 | } | ||
1614 | |||
1615 | gbe_intf = devm_kzalloc(gbe_dev->dev, sizeof(*gbe_intf), GFP_KERNEL); | ||
1616 | if (!gbe_intf) | ||
1617 | return -ENOMEM; | ||
1618 | |||
1619 | gbe_intf->ndev = ndev; | ||
1620 | gbe_intf->dev = gbe_dev->dev; | ||
1621 | gbe_intf->gbe_dev = gbe_dev; | ||
1622 | |||
1623 | gbe_intf->slave = devm_kzalloc(gbe_dev->dev, | ||
1624 | sizeof(*gbe_intf->slave), | ||
1625 | GFP_KERNEL); | ||
1626 | if (!gbe_intf->slave) { | ||
1627 | ret = -ENOMEM; | ||
1628 | goto fail; | ||
1629 | } | ||
1630 | |||
1631 | if (init_slave(gbe_dev, gbe_intf->slave, node)) { | ||
1632 | ret = -ENODEV; | ||
1633 | goto fail; | ||
1634 | } | ||
1635 | |||
1636 | gbe_intf->tx_pipe = gbe_dev->tx_pipe; | ||
1637 | ndev->ethtool_ops = &keystone_ethtool_ops; | ||
1638 | list_add_tail(&gbe_intf->gbe_intf_list, &gbe_dev->gbe_intf_head); | ||
1639 | *intf_priv = gbe_intf; | ||
1640 | return 0; | ||
1641 | |||
1642 | fail: | ||
1643 | if (gbe_intf->slave) | ||
1644 | devm_kfree(gbe_dev->dev, gbe_intf->slave); | ||
1645 | if (gbe_intf) | ||
1646 | devm_kfree(gbe_dev->dev, gbe_intf); | ||
1647 | return ret; | ||
1648 | } | ||
1649 | |||
1650 | static int gbe_release(void *intf_priv) | ||
1651 | { | ||
1652 | struct gbe_intf *gbe_intf = intf_priv; | ||
1653 | |||
1654 | gbe_intf->ndev->ethtool_ops = NULL; | ||
1655 | list_del(&gbe_intf->gbe_intf_list); | ||
1656 | devm_kfree(gbe_intf->dev, gbe_intf->slave); | ||
1657 | devm_kfree(gbe_intf->dev, gbe_intf); | ||
1658 | return 0; | ||
1659 | } | ||
1660 | |||
1661 | static int gbe_remove(struct netcp_device *netcp_device, void *inst_priv) | ||
1662 | { | ||
1663 | struct gbe_priv *gbe_dev = inst_priv; | ||
1664 | |||
1665 | del_timer_sync(&gbe_dev->timer); | ||
1666 | cpsw_ale_stop(gbe_dev->ale); | ||
1667 | cpsw_ale_destroy(gbe_dev->ale); | ||
1668 | netcp_txpipe_close(&gbe_dev->tx_pipe); | ||
1669 | free_secondary_ports(gbe_dev); | ||
1670 | |||
1671 | if (!list_empty(&gbe_dev->gbe_intf_head)) | ||
1672 | dev_alert(gbe_dev->dev, "unreleased ethss interfaces present\n"); | ||
1673 | |||
1674 | devm_kfree(gbe_dev->dev, gbe_dev->hw_stats); | ||
1675 | devm_iounmap(gbe_dev->dev, gbe_dev->ss_regs); | ||
1676 | memset(gbe_dev, 0x00, sizeof(*gbe_dev)); | ||
1677 | devm_kfree(gbe_dev->dev, gbe_dev); | ||
1678 | return 0; | ||
1679 | } | ||
1680 | |||
1681 | static struct netcp_module gbe_module = { | ||
1682 | .name = GBE_MODULE_NAME, | ||
1683 | .owner = THIS_MODULE, | ||
1684 | .primary = true, | ||
1685 | .probe = gbe_probe, | ||
1686 | .open = gbe_open, | ||
1687 | .close = gbe_close, | ||
1688 | .remove = gbe_remove, | ||
1689 | .attach = gbe_attach, | ||
1690 | .release = gbe_release, | ||
1691 | .add_addr = gbe_add_addr, | ||
1692 | .del_addr = gbe_del_addr, | ||
1693 | .add_vid = gbe_add_vid, | ||
1694 | .del_vid = gbe_del_vid, | ||
1695 | .ioctl = gbe_ioctl, | ||
1696 | }; | ||
1697 | |||
1698 | static int __init keystone_gbe_init(void) | ||
1699 | { | ||
1700 | int ret; | ||
1701 | |||
1702 | ret = netcp_register_module(&gbe_module); | ||
1703 | if (ret) | ||
1704 | return ret; | ||
1705 | |||
1706 | return 0; | ||
1707 | } | ||
1708 | module_init(keystone_gbe_init); | ||
1709 | |||
1710 | static void __exit keystone_gbe_exit(void) | ||
1711 | { | ||
1712 | netcp_unregister_module(&gbe_module); | ||
1713 | } | ||
1714 | module_exit(keystone_gbe_exit); | ||
diff --git a/drivers/net/ethernet/ti/netcp_sgmii.c b/drivers/net/ethernet/ti/netcp_sgmii.c new file mode 100644 index 000000000000..dbeb14266e2f --- /dev/null +++ b/drivers/net/ethernet/ti/netcp_sgmii.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * SGMI module initialisation | ||
3 | * | ||
4 | * Copyright (C) 2014 Texas Instruments Incorporated | ||
5 | * Authors: Sandeep Nair <sandeep_n@ti.com> | ||
6 | * Sandeep Paulraj <s-paulraj@ti.com> | ||
7 | * Wingman Kwok <w-kwok2@ti.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License as | ||
11 | * published by the Free Software Foundation version 2. | ||
12 | * | ||
13 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
14 | * kind, whether express or implied; without even the implied warranty | ||
15 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | */ | ||
18 | |||
19 | #include "netcp.h" | ||
20 | |||
21 | #define SGMII_REG_STATUS_LOCK BIT(4) | ||
22 | #define SGMII_REG_STATUS_LINK BIT(0) | ||
23 | #define SGMII_REG_STATUS_AUTONEG BIT(2) | ||
24 | #define SGMII_REG_CONTROL_AUTONEG BIT(0) | ||
25 | |||
26 | #define SGMII23_OFFSET(x) ((x - 2) * 0x100) | ||
27 | #define SGMII_OFFSET(x) ((x <= 1) ? (x * 0x100) : (SGMII23_OFFSET(x))) | ||
28 | |||
29 | /* SGMII registers */ | ||
30 | #define SGMII_SRESET_REG(x) (SGMII_OFFSET(x) + 0x004) | ||
31 | #define SGMII_CTL_REG(x) (SGMII_OFFSET(x) + 0x010) | ||
32 | #define SGMII_STATUS_REG(x) (SGMII_OFFSET(x) + 0x014) | ||
33 | #define SGMII_MRADV_REG(x) (SGMII_OFFSET(x) + 0x018) | ||
34 | |||
35 | static void sgmii_write_reg(void __iomem *base, int reg, u32 val) | ||
36 | { | ||
37 | writel(val, base + reg); | ||
38 | } | ||
39 | |||
40 | static u32 sgmii_read_reg(void __iomem *base, int reg) | ||
41 | { | ||
42 | return readl(base + reg); | ||
43 | } | ||
44 | |||
45 | static void sgmii_write_reg_bit(void __iomem *base, int reg, u32 val) | ||
46 | { | ||
47 | writel((readl(base + reg) | val), base + reg); | ||
48 | } | ||
49 | |||
50 | /* port is 0 based */ | ||
51 | int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port) | ||
52 | { | ||
53 | /* Soft reset */ | ||
54 | sgmii_write_reg_bit(sgmii_ofs, SGMII_SRESET_REG(port), 0x1); | ||
55 | while (sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port)) != 0x0) | ||
56 | ; | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port) | ||
61 | { | ||
62 | u32 status = 0, link = 0; | ||
63 | |||
64 | status = sgmii_read_reg(sgmii_ofs, SGMII_STATUS_REG(port)); | ||
65 | if ((status & SGMII_REG_STATUS_LINK) != 0) | ||
66 | link = 1; | ||
67 | return link; | ||
68 | } | ||
69 | |||
70 | int netcp_sgmii_config(void __iomem *sgmii_ofs, int port, u32 interface) | ||
71 | { | ||
72 | unsigned int i, status, mask; | ||
73 | u32 mr_adv_ability; | ||
74 | u32 control; | ||
75 | |||
76 | switch (interface) { | ||
77 | case SGMII_LINK_MAC_MAC_AUTONEG: | ||
78 | mr_adv_ability = 0x9801; | ||
79 | control = 0x21; | ||
80 | break; | ||
81 | |||
82 | case SGMII_LINK_MAC_PHY: | ||
83 | case SGMII_LINK_MAC_PHY_NO_MDIO: | ||
84 | mr_adv_ability = 1; | ||
85 | control = 1; | ||
86 | break; | ||
87 | |||
88 | case SGMII_LINK_MAC_MAC_FORCED: | ||
89 | mr_adv_ability = 0x9801; | ||
90 | control = 0x20; | ||
91 | break; | ||
92 | |||
93 | case SGMII_LINK_MAC_FIBER: | ||
94 | mr_adv_ability = 0x20; | ||
95 | control = 0x1; | ||
96 | break; | ||
97 | |||
98 | default: | ||
99 | WARN_ONCE(1, "Invalid sgmii interface: %d\n", interface); | ||
100 | return -EINVAL; | ||
101 | } | ||
102 | |||
103 | sgmii_write_reg(sgmii_ofs, SGMII_CTL_REG(port), 0); | ||
104 | |||
105 | /* Wait for the SerDes pll to lock */ | ||
106 | for (i = 0; i < 1000; i++) { | ||
107 | usleep_range(1000, 2000); | ||
108 | status = sgmii_read_reg(sgmii_ofs, SGMII_STATUS_REG(port)); | ||
109 | if ((status & SGMII_REG_STATUS_LOCK) != 0) | ||
110 | break; | ||
111 | } | ||
112 | |||
113 | if ((status & SGMII_REG_STATUS_LOCK) == 0) | ||
114 | pr_err("serdes PLL not locked\n"); | ||
115 | |||
116 | sgmii_write_reg(sgmii_ofs, SGMII_MRADV_REG(port), mr_adv_ability); | ||
117 | sgmii_write_reg(sgmii_ofs, SGMII_CTL_REG(port), control); | ||
118 | |||
119 | mask = SGMII_REG_STATUS_LINK; | ||
120 | if (control & SGMII_REG_CONTROL_AUTONEG) | ||
121 | mask |= SGMII_REG_STATUS_AUTONEG; | ||
122 | |||
123 | for (i = 0; i < 1000; i++) { | ||
124 | usleep_range(200, 500); | ||
125 | status = sgmii_read_reg(sgmii_ofs, SGMII_STATUS_REG(port)); | ||
126 | if ((status & mask) == mask) | ||
127 | break; | ||
128 | } | ||
129 | |||
130 | return 0; | ||
131 | } | ||