diff options
author | Wingman Kwok <w-kwok2@ti.com> | 2015-01-15 19:12:52 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-01-19 15:07:39 -0500 |
commit | 90cff9e2da9f7be6d7847001f430c3e5f8e9532e (patch) | |
tree | ebc07f415869066ebe05ee3bf77ba0f9ddb8c37f | |
parent | 6f8d3f33385cf809eaf816e56302f84a66e2d003 (diff) |
net: netcp: Enhance GBE driver to support 10G Ethernet
This patch enhances the NetCP gbe driver to support 10GbE subsystem
available in Keystone NetCP. The 3-port 10GbE switch sub-module contains
the following components:- 10GbE Switch, MDIO Module, 2 PCS-R Modules
(10GBase-R) and 2 SGMII modules (10/100/1000Base-T). The GBE driver
together with netcp core driver provides support for 10G Ethernet
on Keystone SoCs.
10GbE hardware spec is available at
http://www.ti.com/general/docs/lit/getliterature.tsp?baseLiteratureNumber=spruhj5&fileType=pdf
Cc: David Miller <davem@davemloft.net>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Santosh Shilimkar <santosh.shilimkar@kernel.org>
Cc: Pawel Moll <pawel.moll@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Ian Campbell <ijc+devicetree@hellion.org.uk>
Cc: Kumar Gala <galak@codeaurora.org>
Signed-off-by: Wingman Kwok <w-kwok2@ti.com>
Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/ti/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/netcp_ethss.c | 470 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/netcp_xgbepcsr.c | 501 |
3 files changed, 958 insertions, 15 deletions
diff --git a/drivers/net/ethernet/ti/Makefile b/drivers/net/ethernet/ti/Makefile index 6d4dde8d8fdc..465d03ddf441 100644 --- a/drivers/net/ethernet/ti/Makefile +++ b/drivers/net/ethernet/ti/Makefile | |||
@@ -13,4 +13,4 @@ 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 netcp_ethss.o netcp_sgmii.o \ | 15 | keystone_netcp-y := netcp_core.o netcp_ethss.o netcp_sgmii.o \ |
16 | cpsw_ale.o cpts.o | 16 | netcp_xgbepcsr.o cpsw_ale.o cpts.o |
diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c index 58f00c572546..fa1041a78b46 100644 --- a/drivers/net/ethernet/ti/netcp_ethss.c +++ b/drivers/net/ethernet/ti/netcp_ethss.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Keystone GBE subsystem code | 2 | * Keystone GBE and XGBE subsystem code |
3 | * | 3 | * |
4 | * Copyright (C) 2014 Texas Instruments Incorporated | 4 | * Copyright (C) 2014 Texas Instruments Incorporated |
5 | * Authors: Sandeep Nair <sandeep_n@ti.com> | 5 | * Authors: Sandeep Nair <sandeep_n@ti.com> |
@@ -53,6 +53,23 @@ | |||
53 | #define GBE13_NUM_ALE_PORTS (GBE13_NUM_SLAVES + 1) | 53 | #define GBE13_NUM_ALE_PORTS (GBE13_NUM_SLAVES + 1) |
54 | #define GBE13_NUM_ALE_ENTRIES 1024 | 54 | #define GBE13_NUM_ALE_ENTRIES 1024 |
55 | 55 | ||
56 | /* 10G Ethernet SS defines */ | ||
57 | #define XGBE_MODULE_NAME "netcp-xgbe" | ||
58 | #define XGBE_SS_VERSION_10 0x4ee42100 | ||
59 | |||
60 | #define XGBE_SERDES_REG_INDEX 1 | ||
61 | #define XGBE10_SGMII_MODULE_OFFSET 0x100 | ||
62 | #define XGBE10_SWITCH_MODULE_OFFSET 0x1000 | ||
63 | #define XGBE10_HOST_PORT_OFFSET 0x1034 | ||
64 | #define XGBE10_SLAVE_PORT_OFFSET 0x1064 | ||
65 | #define XGBE10_EMAC_OFFSET 0x1400 | ||
66 | #define XGBE10_ALE_OFFSET 0x1700 | ||
67 | #define XGBE10_HW_STATS_OFFSET 0x1800 | ||
68 | #define XGBE10_HOST_PORT_NUM 0 | ||
69 | #define XGBE10_NUM_SLAVES 2 | ||
70 | #define XGBE10_NUM_ALE_PORTS (XGBE10_NUM_SLAVES + 1) | ||
71 | #define XGBE10_NUM_ALE_ENTRIES 1024 | ||
72 | |||
56 | #define GBE_TIMER_INTERVAL (HZ / 2) | 73 | #define GBE_TIMER_INTERVAL (HZ / 2) |
57 | 74 | ||
58 | /* Soft reset register values */ | 75 | /* Soft reset register values */ |
@@ -63,12 +80,15 @@ | |||
63 | 80 | ||
64 | #define MACSL_RX_ENABLE_CSF BIT(23) | 81 | #define MACSL_RX_ENABLE_CSF BIT(23) |
65 | #define MACSL_ENABLE_EXT_CTL BIT(18) | 82 | #define MACSL_ENABLE_EXT_CTL BIT(18) |
83 | #define MACSL_XGMII_ENABLE BIT(13) | ||
84 | #define MACSL_XGIG_MODE BIT(8) | ||
66 | #define MACSL_GIG_MODE BIT(7) | 85 | #define MACSL_GIG_MODE BIT(7) |
67 | #define MACSL_GMII_ENABLE BIT(5) | 86 | #define MACSL_GMII_ENABLE BIT(5) |
68 | #define MACSL_FULLDUPLEX BIT(0) | 87 | #define MACSL_FULLDUPLEX BIT(0) |
69 | 88 | ||
70 | #define GBE_CTL_P0_ENABLE BIT(2) | 89 | #define GBE_CTL_P0_ENABLE BIT(2) |
71 | #define GBE_REG_VAL_STAT_ENABLE_ALL 0xff | 90 | #define GBE_REG_VAL_STAT_ENABLE_ALL 0xff |
91 | #define XGBE_REG_VAL_STAT_ENABLE_ALL 0xf | ||
72 | #define GBE_STATS_CD_SEL BIT(28) | 92 | #define GBE_STATS_CD_SEL BIT(28) |
73 | 93 | ||
74 | #define GBE_PORT_MASK(x) (BIT(x) - 1) | 94 | #define GBE_PORT_MASK(x) (BIT(x) - 1) |
@@ -78,11 +98,19 @@ | |||
78 | (MACSL_GIG_MODE | MACSL_GMII_ENABLE | \ | 98 | (MACSL_GIG_MODE | MACSL_GMII_ENABLE | \ |
79 | MACSL_ENABLE_EXT_CTL | MACSL_RX_ENABLE_CSF) | 99 | MACSL_ENABLE_EXT_CTL | MACSL_RX_ENABLE_CSF) |
80 | 100 | ||
101 | #define GBE_DEF_10G_MAC_CONTROL \ | ||
102 | (MACSL_XGIG_MODE | MACSL_XGMII_ENABLE | \ | ||
103 | MACSL_ENABLE_EXT_CTL | MACSL_RX_ENABLE_CSF) | ||
104 | |||
81 | #define GBE_STATSA_MODULE 0 | 105 | #define GBE_STATSA_MODULE 0 |
82 | #define GBE_STATSB_MODULE 1 | 106 | #define GBE_STATSB_MODULE 1 |
83 | #define GBE_STATSC_MODULE 2 | 107 | #define GBE_STATSC_MODULE 2 |
84 | #define GBE_STATSD_MODULE 3 | 108 | #define GBE_STATSD_MODULE 3 |
85 | 109 | ||
110 | #define XGBE_STATS0_MODULE 0 | ||
111 | #define XGBE_STATS1_MODULE 1 | ||
112 | #define XGBE_STATS2_MODULE 2 | ||
113 | |||
86 | #define MAX_SLAVES GBE13_NUM_SLAVES | 114 | #define MAX_SLAVES GBE13_NUM_SLAVES |
87 | /* s: 0-based slave_port */ | 115 | /* s: 0-based slave_port */ |
88 | #define SGMII_BASE(s) \ | 116 | #define SGMII_BASE(s) \ |
@@ -91,12 +119,144 @@ | |||
91 | #define GBE_TX_QUEUE 648 | 119 | #define GBE_TX_QUEUE 648 |
92 | #define GBE_TXHOOK_ORDER 0 | 120 | #define GBE_TXHOOK_ORDER 0 |
93 | #define GBE_DEFAULT_ALE_AGEOUT 30 | 121 | #define GBE_DEFAULT_ALE_AGEOUT 30 |
122 | #define SLAVE_LINK_IS_XGMII(s) ((s)->link_interface >= XGMII_LINK_MAC_PHY) | ||
94 | #define NETCP_LINK_STATE_INVALID -1 | 123 | #define NETCP_LINK_STATE_INVALID -1 |
95 | 124 | ||
96 | #define GBE_SET_REG_OFS(p, rb, rn) p->rb##_ofs.rn = \ | 125 | #define GBE_SET_REG_OFS(p, rb, rn) p->rb##_ofs.rn = \ |
97 | offsetof(struct gbe##_##rb, rn) | 126 | offsetof(struct gbe##_##rb, rn) |
127 | #define XGBE_SET_REG_OFS(p, rb, rn) p->rb##_ofs.rn = \ | ||
128 | offsetof(struct xgbe##_##rb, rn) | ||
98 | #define GBE_REG_ADDR(p, rb, rn) (p->rb + p->rb##_ofs.rn) | 129 | #define GBE_REG_ADDR(p, rb, rn) (p->rb + p->rb##_ofs.rn) |
99 | 130 | ||
131 | struct xgbe_ss_regs { | ||
132 | u32 id_ver; | ||
133 | u32 synce_count; | ||
134 | u32 synce_mux; | ||
135 | u32 control; | ||
136 | }; | ||
137 | |||
138 | struct xgbe_switch_regs { | ||
139 | u32 id_ver; | ||
140 | u32 control; | ||
141 | u32 emcontrol; | ||
142 | u32 stat_port_en; | ||
143 | u32 ptype; | ||
144 | u32 soft_idle; | ||
145 | u32 thru_rate; | ||
146 | u32 gap_thresh; | ||
147 | u32 tx_start_wds; | ||
148 | u32 flow_control; | ||
149 | u32 cppi_thresh; | ||
150 | }; | ||
151 | |||
152 | struct xgbe_port_regs { | ||
153 | u32 blk_cnt; | ||
154 | u32 port_vlan; | ||
155 | u32 tx_pri_map; | ||
156 | u32 sa_lo; | ||
157 | u32 sa_hi; | ||
158 | u32 ts_ctl; | ||
159 | u32 ts_seq_ltype; | ||
160 | u32 ts_vlan; | ||
161 | u32 ts_ctl_ltype2; | ||
162 | u32 ts_ctl2; | ||
163 | u32 control; | ||
164 | }; | ||
165 | |||
166 | struct xgbe_host_port_regs { | ||
167 | u32 blk_cnt; | ||
168 | u32 port_vlan; | ||
169 | u32 tx_pri_map; | ||
170 | u32 src_id; | ||
171 | u32 rx_pri_map; | ||
172 | u32 rx_maxlen; | ||
173 | }; | ||
174 | |||
175 | struct xgbe_emac_regs { | ||
176 | u32 id_ver; | ||
177 | u32 mac_control; | ||
178 | u32 mac_status; | ||
179 | u32 soft_reset; | ||
180 | u32 rx_maxlen; | ||
181 | u32 __reserved_0; | ||
182 | u32 rx_pause; | ||
183 | u32 tx_pause; | ||
184 | u32 em_control; | ||
185 | u32 __reserved_1; | ||
186 | u32 tx_gap; | ||
187 | u32 rsvd[4]; | ||
188 | }; | ||
189 | |||
190 | struct xgbe_host_hw_stats { | ||
191 | u32 rx_good_frames; | ||
192 | u32 rx_broadcast_frames; | ||
193 | u32 rx_multicast_frames; | ||
194 | u32 __rsvd_0[3]; | ||
195 | u32 rx_oversized_frames; | ||
196 | u32 __rsvd_1; | ||
197 | u32 rx_undersized_frames; | ||
198 | u32 __rsvd_2; | ||
199 | u32 overrun_type4; | ||
200 | u32 overrun_type5; | ||
201 | u32 rx_bytes; | ||
202 | u32 tx_good_frames; | ||
203 | u32 tx_broadcast_frames; | ||
204 | u32 tx_multicast_frames; | ||
205 | u32 __rsvd_3[9]; | ||
206 | u32 tx_bytes; | ||
207 | u32 tx_64byte_frames; | ||
208 | u32 tx_65_to_127byte_frames; | ||
209 | u32 tx_128_to_255byte_frames; | ||
210 | u32 tx_256_to_511byte_frames; | ||
211 | u32 tx_512_to_1023byte_frames; | ||
212 | u32 tx_1024byte_frames; | ||
213 | u32 net_bytes; | ||
214 | u32 rx_sof_overruns; | ||
215 | u32 rx_mof_overruns; | ||
216 | u32 rx_dma_overruns; | ||
217 | }; | ||
218 | |||
219 | struct xgbe_hw_stats { | ||
220 | u32 rx_good_frames; | ||
221 | u32 rx_broadcast_frames; | ||
222 | u32 rx_multicast_frames; | ||
223 | u32 rx_pause_frames; | ||
224 | u32 rx_crc_errors; | ||
225 | u32 rx_align_code_errors; | ||
226 | u32 rx_oversized_frames; | ||
227 | u32 rx_jabber_frames; | ||
228 | u32 rx_undersized_frames; | ||
229 | u32 rx_fragments; | ||
230 | u32 overrun_type4; | ||
231 | u32 overrun_type5; | ||
232 | u32 rx_bytes; | ||
233 | u32 tx_good_frames; | ||
234 | u32 tx_broadcast_frames; | ||
235 | u32 tx_multicast_frames; | ||
236 | u32 tx_pause_frames; | ||
237 | u32 tx_deferred_frames; | ||
238 | u32 tx_collision_frames; | ||
239 | u32 tx_single_coll_frames; | ||
240 | u32 tx_mult_coll_frames; | ||
241 | u32 tx_excessive_collisions; | ||
242 | u32 tx_late_collisions; | ||
243 | u32 tx_underrun; | ||
244 | u32 tx_carrier_sense_errors; | ||
245 | u32 tx_bytes; | ||
246 | u32 tx_64byte_frames; | ||
247 | u32 tx_65_to_127byte_frames; | ||
248 | u32 tx_128_to_255byte_frames; | ||
249 | u32 tx_256_to_511byte_frames; | ||
250 | u32 tx_512_to_1023byte_frames; | ||
251 | u32 tx_1024byte_frames; | ||
252 | u32 net_bytes; | ||
253 | u32 rx_sof_overruns; | ||
254 | u32 rx_mof_overruns; | ||
255 | u32 rx_dma_overruns; | ||
256 | }; | ||
257 | |||
258 | #define XGBE10_NUM_STAT_ENTRIES (sizeof(struct xgbe_hw_stats)/sizeof(u32)) | ||
259 | |||
100 | struct gbe_ss_regs { | 260 | struct gbe_ss_regs { |
101 | u32 id_ver; | 261 | u32 id_ver; |
102 | u32 synce_count; | 262 | u32 synce_count; |
@@ -230,6 +390,7 @@ struct gbe_hw_stats { | |||
230 | 390 | ||
231 | #define GBE13_NUM_HW_STAT_ENTRIES (sizeof(struct gbe_hw_stats)/sizeof(u32)) | 391 | #define GBE13_NUM_HW_STAT_ENTRIES (sizeof(struct gbe_hw_stats)/sizeof(u32)) |
232 | #define GBE13_NUM_HW_STATS_MOD 2 | 392 | #define GBE13_NUM_HW_STATS_MOD 2 |
393 | #define XGBE10_NUM_HW_STATS_MOD 3 | ||
233 | #define GBE_MAX_HW_STAT_MODS 3 | 394 | #define GBE_MAX_HW_STAT_MODS 3 |
234 | #define GBE_HW_STATS_REG_MAP_SZ 0x100 | 395 | #define GBE_HW_STATS_REG_MAP_SZ 0x100 |
235 | 396 | ||
@@ -303,6 +464,7 @@ struct gbe_intf { | |||
303 | }; | 464 | }; |
304 | 465 | ||
305 | static struct netcp_module gbe_module; | 466 | static struct netcp_module gbe_module; |
467 | static struct netcp_module xgbe_module; | ||
306 | 468 | ||
307 | /* Statistic management */ | 469 | /* Statistic management */ |
308 | struct netcp_ethtool_stat { | 470 | struct netcp_ethtool_stat { |
@@ -471,6 +633,118 @@ static const struct netcp_ethtool_stat gbe13_et_stats[] = { | |||
471 | {GBE_STATSD_INFO(rx_dma_overruns)}, | 633 | {GBE_STATSD_INFO(rx_dma_overruns)}, |
472 | }; | 634 | }; |
473 | 635 | ||
636 | #define XGBE_STATS0_INFO(field) "GBE_0:"#field, XGBE_STATS0_MODULE, \ | ||
637 | FIELD_SIZEOF(struct xgbe_hw_stats, field), \ | ||
638 | offsetof(struct xgbe_hw_stats, field) | ||
639 | |||
640 | #define XGBE_STATS1_INFO(field) "GBE_1:"#field, XGBE_STATS1_MODULE, \ | ||
641 | FIELD_SIZEOF(struct xgbe_hw_stats, field), \ | ||
642 | offsetof(struct xgbe_hw_stats, field) | ||
643 | |||
644 | #define XGBE_STATS2_INFO(field) "GBE_2:"#field, XGBE_STATS2_MODULE, \ | ||
645 | FIELD_SIZEOF(struct xgbe_hw_stats, field), \ | ||
646 | offsetof(struct xgbe_hw_stats, field) | ||
647 | |||
648 | static const struct netcp_ethtool_stat xgbe10_et_stats[] = { | ||
649 | /* GBE module 0 */ | ||
650 | {XGBE_STATS0_INFO(rx_good_frames)}, | ||
651 | {XGBE_STATS0_INFO(rx_broadcast_frames)}, | ||
652 | {XGBE_STATS0_INFO(rx_multicast_frames)}, | ||
653 | {XGBE_STATS0_INFO(rx_oversized_frames)}, | ||
654 | {XGBE_STATS0_INFO(rx_undersized_frames)}, | ||
655 | {XGBE_STATS0_INFO(overrun_type4)}, | ||
656 | {XGBE_STATS0_INFO(overrun_type5)}, | ||
657 | {XGBE_STATS0_INFO(rx_bytes)}, | ||
658 | {XGBE_STATS0_INFO(tx_good_frames)}, | ||
659 | {XGBE_STATS0_INFO(tx_broadcast_frames)}, | ||
660 | {XGBE_STATS0_INFO(tx_multicast_frames)}, | ||
661 | {XGBE_STATS0_INFO(tx_bytes)}, | ||
662 | {XGBE_STATS0_INFO(tx_64byte_frames)}, | ||
663 | {XGBE_STATS0_INFO(tx_65_to_127byte_frames)}, | ||
664 | {XGBE_STATS0_INFO(tx_128_to_255byte_frames)}, | ||
665 | {XGBE_STATS0_INFO(tx_256_to_511byte_frames)}, | ||
666 | {XGBE_STATS0_INFO(tx_512_to_1023byte_frames)}, | ||
667 | {XGBE_STATS0_INFO(tx_1024byte_frames)}, | ||
668 | {XGBE_STATS0_INFO(net_bytes)}, | ||
669 | {XGBE_STATS0_INFO(rx_sof_overruns)}, | ||
670 | {XGBE_STATS0_INFO(rx_mof_overruns)}, | ||
671 | {XGBE_STATS0_INFO(rx_dma_overruns)}, | ||
672 | /* XGBE module 1 */ | ||
673 | {XGBE_STATS1_INFO(rx_good_frames)}, | ||
674 | {XGBE_STATS1_INFO(rx_broadcast_frames)}, | ||
675 | {XGBE_STATS1_INFO(rx_multicast_frames)}, | ||
676 | {XGBE_STATS1_INFO(rx_pause_frames)}, | ||
677 | {XGBE_STATS1_INFO(rx_crc_errors)}, | ||
678 | {XGBE_STATS1_INFO(rx_align_code_errors)}, | ||
679 | {XGBE_STATS1_INFO(rx_oversized_frames)}, | ||
680 | {XGBE_STATS1_INFO(rx_jabber_frames)}, | ||
681 | {XGBE_STATS1_INFO(rx_undersized_frames)}, | ||
682 | {XGBE_STATS1_INFO(rx_fragments)}, | ||
683 | {XGBE_STATS1_INFO(overrun_type4)}, | ||
684 | {XGBE_STATS1_INFO(overrun_type5)}, | ||
685 | {XGBE_STATS1_INFO(rx_bytes)}, | ||
686 | {XGBE_STATS1_INFO(tx_good_frames)}, | ||
687 | {XGBE_STATS1_INFO(tx_broadcast_frames)}, | ||
688 | {XGBE_STATS1_INFO(tx_multicast_frames)}, | ||
689 | {XGBE_STATS1_INFO(tx_pause_frames)}, | ||
690 | {XGBE_STATS1_INFO(tx_deferred_frames)}, | ||
691 | {XGBE_STATS1_INFO(tx_collision_frames)}, | ||
692 | {XGBE_STATS1_INFO(tx_single_coll_frames)}, | ||
693 | {XGBE_STATS1_INFO(tx_mult_coll_frames)}, | ||
694 | {XGBE_STATS1_INFO(tx_excessive_collisions)}, | ||
695 | {XGBE_STATS1_INFO(tx_late_collisions)}, | ||
696 | {XGBE_STATS1_INFO(tx_underrun)}, | ||
697 | {XGBE_STATS1_INFO(tx_carrier_sense_errors)}, | ||
698 | {XGBE_STATS1_INFO(tx_bytes)}, | ||
699 | {XGBE_STATS1_INFO(tx_64byte_frames)}, | ||
700 | {XGBE_STATS1_INFO(tx_65_to_127byte_frames)}, | ||
701 | {XGBE_STATS1_INFO(tx_128_to_255byte_frames)}, | ||
702 | {XGBE_STATS1_INFO(tx_256_to_511byte_frames)}, | ||
703 | {XGBE_STATS1_INFO(tx_512_to_1023byte_frames)}, | ||
704 | {XGBE_STATS1_INFO(tx_1024byte_frames)}, | ||
705 | {XGBE_STATS1_INFO(net_bytes)}, | ||
706 | {XGBE_STATS1_INFO(rx_sof_overruns)}, | ||
707 | {XGBE_STATS1_INFO(rx_mof_overruns)}, | ||
708 | {XGBE_STATS1_INFO(rx_dma_overruns)}, | ||
709 | /* XGBE module 2 */ | ||
710 | {XGBE_STATS2_INFO(rx_good_frames)}, | ||
711 | {XGBE_STATS2_INFO(rx_broadcast_frames)}, | ||
712 | {XGBE_STATS2_INFO(rx_multicast_frames)}, | ||
713 | {XGBE_STATS2_INFO(rx_pause_frames)}, | ||
714 | {XGBE_STATS2_INFO(rx_crc_errors)}, | ||
715 | {XGBE_STATS2_INFO(rx_align_code_errors)}, | ||
716 | {XGBE_STATS2_INFO(rx_oversized_frames)}, | ||
717 | {XGBE_STATS2_INFO(rx_jabber_frames)}, | ||
718 | {XGBE_STATS2_INFO(rx_undersized_frames)}, | ||
719 | {XGBE_STATS2_INFO(rx_fragments)}, | ||
720 | {XGBE_STATS2_INFO(overrun_type4)}, | ||
721 | {XGBE_STATS2_INFO(overrun_type5)}, | ||
722 | {XGBE_STATS2_INFO(rx_bytes)}, | ||
723 | {XGBE_STATS2_INFO(tx_good_frames)}, | ||
724 | {XGBE_STATS2_INFO(tx_broadcast_frames)}, | ||
725 | {XGBE_STATS2_INFO(tx_multicast_frames)}, | ||
726 | {XGBE_STATS2_INFO(tx_pause_frames)}, | ||
727 | {XGBE_STATS2_INFO(tx_deferred_frames)}, | ||
728 | {XGBE_STATS2_INFO(tx_collision_frames)}, | ||
729 | {XGBE_STATS2_INFO(tx_single_coll_frames)}, | ||
730 | {XGBE_STATS2_INFO(tx_mult_coll_frames)}, | ||
731 | {XGBE_STATS2_INFO(tx_excessive_collisions)}, | ||
732 | {XGBE_STATS2_INFO(tx_late_collisions)}, | ||
733 | {XGBE_STATS2_INFO(tx_underrun)}, | ||
734 | {XGBE_STATS2_INFO(tx_carrier_sense_errors)}, | ||
735 | {XGBE_STATS2_INFO(tx_bytes)}, | ||
736 | {XGBE_STATS2_INFO(tx_64byte_frames)}, | ||
737 | {XGBE_STATS2_INFO(tx_65_to_127byte_frames)}, | ||
738 | {XGBE_STATS2_INFO(tx_128_to_255byte_frames)}, | ||
739 | {XGBE_STATS2_INFO(tx_256_to_511byte_frames)}, | ||
740 | {XGBE_STATS2_INFO(tx_512_to_1023byte_frames)}, | ||
741 | {XGBE_STATS2_INFO(tx_1024byte_frames)}, | ||
742 | {XGBE_STATS2_INFO(net_bytes)}, | ||
743 | {XGBE_STATS2_INFO(rx_sof_overruns)}, | ||
744 | {XGBE_STATS2_INFO(rx_mof_overruns)}, | ||
745 | {XGBE_STATS2_INFO(rx_dma_overruns)}, | ||
746 | }; | ||
747 | |||
474 | #define for_each_intf(i, priv) \ | 748 | #define for_each_intf(i, priv) \ |
475 | list_for_each_entry((i), &(priv)->gbe_intf_head, gbe_intf_list) | 749 | list_for_each_entry((i), &(priv)->gbe_intf_head, gbe_intf_list) |
476 | 750 | ||
@@ -631,7 +905,10 @@ static void keystone_get_ethtool_stats(struct net_device *ndev, | |||
631 | 905 | ||
632 | gbe_dev = gbe_intf->gbe_dev; | 906 | gbe_dev = gbe_intf->gbe_dev; |
633 | spin_lock_bh(&gbe_dev->hw_stats_lock); | 907 | spin_lock_bh(&gbe_dev->hw_stats_lock); |
634 | gbe_update_stats_ver14(gbe_dev, data); | 908 | if (gbe_dev->ss_version == GBE_SS_VERSION_14) |
909 | gbe_update_stats_ver14(gbe_dev, data); | ||
910 | else | ||
911 | gbe_update_stats(gbe_dev, data); | ||
635 | spin_unlock_bh(&gbe_dev->hw_stats_lock); | 912 | spin_unlock_bh(&gbe_dev->hw_stats_lock); |
636 | } | 913 | } |
637 | 914 | ||
@@ -742,8 +1019,13 @@ static void netcp_ethss_link_state_action(struct gbe_priv *gbe_dev, | |||
742 | 1019 | ||
743 | if (up) { | 1020 | if (up) { |
744 | mac_control = slave->mac_control; | 1021 | mac_control = slave->mac_control; |
745 | if (phy && (phy->speed == SPEED_1000)) | 1022 | if (phy && (phy->speed == SPEED_1000)) { |
746 | mac_control |= MACSL_GIG_MODE; | 1023 | mac_control |= MACSL_GIG_MODE; |
1024 | mac_control &= ~MACSL_XGIG_MODE; | ||
1025 | } else if (phy && (phy->speed == SPEED_10000)) { | ||
1026 | mac_control |= MACSL_XGIG_MODE; | ||
1027 | mac_control &= ~MACSL_GIG_MODE; | ||
1028 | } | ||
747 | 1029 | ||
748 | writel(mac_control, GBE_REG_ADDR(slave, emac_regs, | 1030 | writel(mac_control, GBE_REG_ADDR(slave, emac_regs, |
749 | mac_control)); | 1031 | mac_control)); |
@@ -783,7 +1065,9 @@ static void netcp_ethss_update_link_state(struct gbe_priv *gbe_dev, | |||
783 | if (!slave->open) | 1065 | if (!slave->open) |
784 | return; | 1066 | return; |
785 | 1067 | ||
786 | sgmii_link_state = netcp_sgmii_get_port_link(SGMII_BASE(sp), sp); | 1068 | if (!SLAVE_LINK_IS_XGMII(slave)) |
1069 | sgmii_link_state = netcp_sgmii_get_port_link(SGMII_BASE(sp), | ||
1070 | sp); | ||
787 | phy_link_state = gbe_phy_link_status(slave); | 1071 | phy_link_state = gbe_phy_link_status(slave); |
788 | link_state = phy_link_state & sgmii_link_state; | 1072 | link_state = phy_link_state & sgmii_link_state; |
789 | 1073 | ||
@@ -792,6 +1076,19 @@ static void netcp_ethss_update_link_state(struct gbe_priv *gbe_dev, | |||
792 | link_state); | 1076 | link_state); |
793 | } | 1077 | } |
794 | 1078 | ||
1079 | static void xgbe_adjust_link(struct net_device *ndev) | ||
1080 | { | ||
1081 | struct netcp_intf *netcp = netdev_priv(ndev); | ||
1082 | struct gbe_intf *gbe_intf; | ||
1083 | |||
1084 | gbe_intf = netcp_module_get_intf_data(&xgbe_module, netcp); | ||
1085 | if (!gbe_intf) | ||
1086 | return; | ||
1087 | |||
1088 | netcp_ethss_update_link_state(gbe_intf->gbe_dev, gbe_intf->slave, | ||
1089 | ndev); | ||
1090 | } | ||
1091 | |||
795 | static void gbe_adjust_link(struct net_device *ndev) | 1092 | static void gbe_adjust_link(struct net_device *ndev) |
796 | { | 1093 | { |
797 | struct netcp_intf *netcp = netdev_priv(ndev); | 1094 | struct netcp_intf *netcp = netdev_priv(ndev); |
@@ -839,9 +1136,19 @@ static int gbe_port_reset(struct gbe_slave *slave) | |||
839 | static void gbe_port_config(struct gbe_priv *gbe_dev, struct gbe_slave *slave, | 1136 | static void gbe_port_config(struct gbe_priv *gbe_dev, struct gbe_slave *slave, |
840 | int max_rx_len) | 1137 | int max_rx_len) |
841 | { | 1138 | { |
1139 | u32 xgmii_mode; | ||
1140 | |||
842 | if (max_rx_len > NETCP_MAX_FRAME_SIZE) | 1141 | if (max_rx_len > NETCP_MAX_FRAME_SIZE) |
843 | max_rx_len = NETCP_MAX_FRAME_SIZE; | 1142 | max_rx_len = NETCP_MAX_FRAME_SIZE; |
844 | 1143 | ||
1144 | /* Enable correct MII mode at SS level */ | ||
1145 | if ((gbe_dev->ss_version == XGBE_SS_VERSION_10) && | ||
1146 | (slave->link_interface >= XGMII_LINK_MAC_PHY)) { | ||
1147 | xgmii_mode = readl(GBE_REG_ADDR(gbe_dev, ss_regs, control)); | ||
1148 | xgmii_mode |= (1 << slave->slave_num); | ||
1149 | writel(xgmii_mode, GBE_REG_ADDR(gbe_dev, ss_regs, control)); | ||
1150 | } | ||
1151 | |||
845 | writel(max_rx_len, GBE_REG_ADDR(slave, emac_regs, rx_maxlen)); | 1152 | 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)); | 1153 | writel(slave->mac_control, GBE_REG_ADDR(slave, emac_regs, mac_control)); |
847 | } | 1154 | } |
@@ -874,9 +1181,11 @@ static void gbe_sgmii_config(struct gbe_priv *priv, struct gbe_slave *slave) | |||
874 | if ((priv->ss_version == GBE_SS_VERSION_14) && (slave->slave_num >= 2)) | 1181 | if ((priv->ss_version == GBE_SS_VERSION_14) && (slave->slave_num >= 2)) |
875 | sgmii_port_regs = priv->sgmii_port34_regs; | 1182 | sgmii_port_regs = priv->sgmii_port34_regs; |
876 | 1183 | ||
877 | netcp_sgmii_reset(sgmii_port_regs, slave->slave_num); | 1184 | if (!SLAVE_LINK_IS_XGMII(slave)) { |
878 | netcp_sgmii_config(sgmii_port_regs, slave->slave_num, | 1185 | netcp_sgmii_reset(sgmii_port_regs, slave->slave_num); |
879 | slave->link_interface); | 1186 | netcp_sgmii_config(sgmii_port_regs, slave->slave_num, |
1187 | slave->link_interface); | ||
1188 | } | ||
880 | } | 1189 | } |
881 | 1190 | ||
882 | static int gbe_slave_open(struct gbe_intf *gbe_intf) | 1191 | static int gbe_slave_open(struct gbe_intf *gbe_intf) |
@@ -909,6 +1218,9 @@ static int gbe_slave_open(struct gbe_intf *gbe_intf) | |||
909 | } | 1218 | } |
910 | 1219 | ||
911 | if (has_phy) { | 1220 | if (has_phy) { |
1221 | if (priv->ss_version == XGBE_SS_VERSION_10) | ||
1222 | hndlr = xgbe_adjust_link; | ||
1223 | |||
912 | slave->phy = of_phy_connect(gbe_intf->ndev, | 1224 | slave->phy = of_phy_connect(gbe_intf->ndev, |
913 | slave->phy_node, | 1225 | slave->phy_node, |
914 | hndlr, 0, | 1226 | hndlr, 0, |
@@ -1233,7 +1545,10 @@ static int init_slave(struct gbe_priv *gbe_dev, struct gbe_slave *slave, | |||
1233 | slave->phy_node = of_parse_phandle(node, "phy-handle", 0); | 1545 | slave->phy_node = of_parse_phandle(node, "phy-handle", 0); |
1234 | slave->port_num = gbe_get_slave_port(gbe_dev, slave->slave_num); | 1546 | slave->port_num = gbe_get_slave_port(gbe_dev, slave->slave_num); |
1235 | 1547 | ||
1236 | slave->mac_control = GBE_DEF_1G_MAC_CONTROL; | 1548 | if (slave->link_interface >= XGMII_LINK_MAC_PHY) |
1549 | slave->mac_control = GBE_DEF_10G_MAC_CONTROL; | ||
1550 | else | ||
1551 | slave->mac_control = GBE_DEF_1G_MAC_CONTROL; | ||
1237 | 1552 | ||
1238 | /* Emac regs memmap are contiguous but port regs are not */ | 1553 | /* Emac regs memmap are contiguous but port regs are not */ |
1239 | port_reg_num = slave->slave_num; | 1554 | port_reg_num = slave->slave_num; |
@@ -1244,6 +1559,8 @@ static int init_slave(struct gbe_priv *gbe_dev, struct gbe_slave *slave, | |||
1244 | } else { | 1559 | } else { |
1245 | port_reg_ofs = GBE13_SLAVE_PORT_OFFSET; | 1560 | port_reg_ofs = GBE13_SLAVE_PORT_OFFSET; |
1246 | } | 1561 | } |
1562 | } else if (gbe_dev->ss_version == XGBE_SS_VERSION_10) { | ||
1563 | port_reg_ofs = XGBE10_SLAVE_PORT_OFFSET; | ||
1247 | } else { | 1564 | } else { |
1248 | dev_err(gbe_dev->dev, "unknown ethss(0x%x)\n", | 1565 | dev_err(gbe_dev->dev, "unknown ethss(0x%x)\n", |
1249 | gbe_dev->ss_version); | 1566 | gbe_dev->ss_version); |
@@ -1252,6 +1569,8 @@ static int init_slave(struct gbe_priv *gbe_dev, struct gbe_slave *slave, | |||
1252 | 1569 | ||
1253 | if (gbe_dev->ss_version == GBE_SS_VERSION_14) | 1570 | if (gbe_dev->ss_version == GBE_SS_VERSION_14) |
1254 | emac_reg_ofs = GBE13_EMAC_OFFSET; | 1571 | emac_reg_ofs = GBE13_EMAC_OFFSET; |
1572 | else if (gbe_dev->ss_version == XGBE_SS_VERSION_10) | ||
1573 | emac_reg_ofs = XGBE10_EMAC_OFFSET; | ||
1255 | 1574 | ||
1256 | slave->port_regs = gbe_dev->ss_regs + port_reg_ofs + | 1575 | slave->port_regs = gbe_dev->ss_regs + port_reg_ofs + |
1257 | (0x30 * port_reg_num); | 1576 | (0x30 * port_reg_num); |
@@ -1275,10 +1594,22 @@ static int init_slave(struct gbe_priv *gbe_dev, struct gbe_slave *slave, | |||
1275 | GBE_SET_REG_OFS(slave, emac_regs, soft_reset); | 1594 | GBE_SET_REG_OFS(slave, emac_regs, soft_reset); |
1276 | GBE_SET_REG_OFS(slave, emac_regs, rx_maxlen); | 1595 | GBE_SET_REG_OFS(slave, emac_regs, rx_maxlen); |
1277 | 1596 | ||
1278 | } else { | 1597 | } else if (gbe_dev->ss_version == XGBE_SS_VERSION_10) { |
1279 | dev_err(gbe_dev->dev, "unknown ethss(0x%x)\n", | 1598 | /* Initialize slave port register offsets */ |
1280 | gbe_dev->ss_version); | 1599 | XGBE_SET_REG_OFS(slave, port_regs, port_vlan); |
1281 | return -EINVAL; | 1600 | XGBE_SET_REG_OFS(slave, port_regs, tx_pri_map); |
1601 | XGBE_SET_REG_OFS(slave, port_regs, sa_lo); | ||
1602 | XGBE_SET_REG_OFS(slave, port_regs, sa_hi); | ||
1603 | XGBE_SET_REG_OFS(slave, port_regs, ts_ctl); | ||
1604 | XGBE_SET_REG_OFS(slave, port_regs, ts_seq_ltype); | ||
1605 | XGBE_SET_REG_OFS(slave, port_regs, ts_vlan); | ||
1606 | XGBE_SET_REG_OFS(slave, port_regs, ts_ctl_ltype2); | ||
1607 | XGBE_SET_REG_OFS(slave, port_regs, ts_ctl2); | ||
1608 | |||
1609 | /* Initialize EMAC register offsets */ | ||
1610 | XGBE_SET_REG_OFS(slave, emac_regs, mac_control); | ||
1611 | XGBE_SET_REG_OFS(slave, emac_regs, soft_reset); | ||
1612 | XGBE_SET_REG_OFS(slave, emac_regs, rx_maxlen); | ||
1282 | } | 1613 | } |
1283 | 1614 | ||
1284 | atomic_set(&slave->link_state, NETCP_LINK_STATE_INVALID); | 1615 | atomic_set(&slave->link_state, NETCP_LINK_STATE_INVALID); |
@@ -1317,7 +1648,8 @@ static void init_secondary_ports(struct gbe_priv *gbe_dev, | |||
1317 | gbe_port_config(gbe_dev, slave, gbe_dev->rx_packet_max); | 1648 | gbe_port_config(gbe_dev, slave, gbe_dev->rx_packet_max); |
1318 | list_add_tail(&slave->slave_list, &gbe_dev->secondary_slaves); | 1649 | list_add_tail(&slave->slave_list, &gbe_dev->secondary_slaves); |
1319 | gbe_dev->num_slaves++; | 1650 | gbe_dev->num_slaves++; |
1320 | if (slave->link_interface == SGMII_LINK_MAC_PHY) | 1651 | if ((slave->link_interface == SGMII_LINK_MAC_PHY) || |
1652 | (slave->link_interface == XGMII_LINK_MAC_PHY)) | ||
1321 | mac_phy_link = true; | 1653 | mac_phy_link = true; |
1322 | 1654 | ||
1323 | slave->open = true; | 1655 | slave->open = true; |
@@ -1347,7 +1679,8 @@ static void init_secondary_ports(struct gbe_priv *gbe_dev, | |||
1347 | } | 1679 | } |
1348 | 1680 | ||
1349 | for_each_sec_slave(slave, gbe_dev) { | 1681 | for_each_sec_slave(slave, gbe_dev) { |
1350 | if (slave->link_interface != SGMII_LINK_MAC_PHY) | 1682 | if ((slave->link_interface != SGMII_LINK_MAC_PHY) && |
1683 | (slave->link_interface != XGMII_LINK_MAC_PHY)) | ||
1351 | continue; | 1684 | continue; |
1352 | slave->phy = | 1685 | slave->phy = |
1353 | of_phy_connect(gbe_dev->dummy_ndev, | 1686 | of_phy_connect(gbe_dev->dummy_ndev, |
@@ -1383,6 +1716,85 @@ static void free_secondary_ports(struct gbe_priv *gbe_dev) | |||
1383 | free_netdev(gbe_dev->dummy_ndev); | 1716 | free_netdev(gbe_dev->dummy_ndev); |
1384 | } | 1717 | } |
1385 | 1718 | ||
1719 | static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev, | ||
1720 | struct device_node *node) | ||
1721 | { | ||
1722 | struct resource res; | ||
1723 | void __iomem *regs; | ||
1724 | int ret, i; | ||
1725 | |||
1726 | ret = of_address_to_resource(node, 0, &res); | ||
1727 | if (ret) { | ||
1728 | dev_err(gbe_dev->dev, "Can't translate of node(%s) address for xgbe subsystem regs\n", | ||
1729 | node->name); | ||
1730 | return ret; | ||
1731 | } | ||
1732 | |||
1733 | regs = devm_ioremap_resource(gbe_dev->dev, &res); | ||
1734 | if (IS_ERR(regs)) { | ||
1735 | dev_err(gbe_dev->dev, "Failed to map xgbe register base\n"); | ||
1736 | return PTR_ERR(regs); | ||
1737 | } | ||
1738 | gbe_dev->ss_regs = regs; | ||
1739 | |||
1740 | ret = of_address_to_resource(node, XGBE_SERDES_REG_INDEX, &res); | ||
1741 | if (ret) { | ||
1742 | dev_err(gbe_dev->dev, "Can't translate of node(%s) address for xgbe serdes regs\n", | ||
1743 | node->name); | ||
1744 | return ret; | ||
1745 | } | ||
1746 | |||
1747 | regs = devm_ioremap_resource(gbe_dev->dev, &res); | ||
1748 | if (IS_ERR(regs)) { | ||
1749 | dev_err(gbe_dev->dev, "Failed to map xgbe serdes register base\n"); | ||
1750 | return PTR_ERR(regs); | ||
1751 | } | ||
1752 | gbe_dev->xgbe_serdes_regs = regs; | ||
1753 | |||
1754 | gbe_dev->hw_stats = devm_kzalloc(gbe_dev->dev, | ||
1755 | XGBE10_NUM_STAT_ENTRIES * | ||
1756 | (XGBE10_NUM_SLAVES + 1) * sizeof(u64), | ||
1757 | GFP_KERNEL); | ||
1758 | if (!gbe_dev->hw_stats) { | ||
1759 | dev_err(gbe_dev->dev, "hw_stats memory allocation failed\n"); | ||
1760 | return -ENOMEM; | ||
1761 | } | ||
1762 | |||
1763 | gbe_dev->ss_version = XGBE_SS_VERSION_10; | ||
1764 | gbe_dev->sgmii_port_regs = gbe_dev->ss_regs + | ||
1765 | XGBE10_SGMII_MODULE_OFFSET; | ||
1766 | gbe_dev->switch_regs = gbe_dev->ss_regs + XGBE10_SWITCH_MODULE_OFFSET; | ||
1767 | gbe_dev->host_port_regs = gbe_dev->ss_regs + XGBE10_HOST_PORT_OFFSET; | ||
1768 | |||
1769 | for (i = 0; i < XGBE10_NUM_HW_STATS_MOD; i++) | ||
1770 | gbe_dev->hw_stats_regs[i] = gbe_dev->ss_regs + | ||
1771 | XGBE10_HW_STATS_OFFSET + (GBE_HW_STATS_REG_MAP_SZ * i); | ||
1772 | |||
1773 | gbe_dev->ale_reg = gbe_dev->ss_regs + XGBE10_ALE_OFFSET; | ||
1774 | gbe_dev->ale_ports = XGBE10_NUM_ALE_PORTS; | ||
1775 | gbe_dev->host_port = XGBE10_HOST_PORT_NUM; | ||
1776 | gbe_dev->ale_entries = XGBE10_NUM_ALE_ENTRIES; | ||
1777 | gbe_dev->et_stats = xgbe10_et_stats; | ||
1778 | gbe_dev->num_et_stats = ARRAY_SIZE(xgbe10_et_stats); | ||
1779 | |||
1780 | /* Subsystem registers */ | ||
1781 | XGBE_SET_REG_OFS(gbe_dev, ss_regs, id_ver); | ||
1782 | XGBE_SET_REG_OFS(gbe_dev, ss_regs, control); | ||
1783 | |||
1784 | /* Switch module registers */ | ||
1785 | XGBE_SET_REG_OFS(gbe_dev, switch_regs, id_ver); | ||
1786 | XGBE_SET_REG_OFS(gbe_dev, switch_regs, control); | ||
1787 | XGBE_SET_REG_OFS(gbe_dev, switch_regs, ptype); | ||
1788 | XGBE_SET_REG_OFS(gbe_dev, switch_regs, stat_port_en); | ||
1789 | XGBE_SET_REG_OFS(gbe_dev, switch_regs, flow_control); | ||
1790 | |||
1791 | /* Host port registers */ | ||
1792 | XGBE_SET_REG_OFS(gbe_dev, host_port_regs, port_vlan); | ||
1793 | XGBE_SET_REG_OFS(gbe_dev, host_port_regs, tx_pri_map); | ||
1794 | XGBE_SET_REG_OFS(gbe_dev, host_port_regs, rx_maxlen); | ||
1795 | return 0; | ||
1796 | } | ||
1797 | |||
1386 | static int get_gbe_resource_version(struct gbe_priv *gbe_dev, | 1798 | static int get_gbe_resource_version(struct gbe_priv *gbe_dev, |
1387 | struct device_node *node) | 1799 | struct device_node *node) |
1388 | { | 1800 | { |
@@ -1513,6 +1925,14 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev, | |||
1513 | ret = set_gbe_ethss14_priv(gbe_dev, node); | 1925 | ret = set_gbe_ethss14_priv(gbe_dev, node); |
1514 | if (ret) | 1926 | if (ret) |
1515 | goto quit; | 1927 | goto quit; |
1928 | } else if (!strcmp(node->name, "xgbe")) { | ||
1929 | ret = set_xgbe_ethss10_priv(gbe_dev, node); | ||
1930 | if (ret) | ||
1931 | goto quit; | ||
1932 | ret = netcp_xgbe_serdes_init(gbe_dev->xgbe_serdes_regs, | ||
1933 | gbe_dev->ss_regs); | ||
1934 | if (ret) | ||
1935 | goto quit; | ||
1516 | } else { | 1936 | } else { |
1517 | dev_err(dev, "unknown GBE node(%s)\n", node->name); | 1937 | dev_err(dev, "unknown GBE node(%s)\n", node->name); |
1518 | ret = -ENODEV; | 1938 | ret = -ENODEV; |
@@ -1695,6 +2115,23 @@ static struct netcp_module gbe_module = { | |||
1695 | .ioctl = gbe_ioctl, | 2115 | .ioctl = gbe_ioctl, |
1696 | }; | 2116 | }; |
1697 | 2117 | ||
2118 | static struct netcp_module xgbe_module = { | ||
2119 | .name = XGBE_MODULE_NAME, | ||
2120 | .owner = THIS_MODULE, | ||
2121 | .primary = true, | ||
2122 | .probe = gbe_probe, | ||
2123 | .open = gbe_open, | ||
2124 | .close = gbe_close, | ||
2125 | .remove = gbe_remove, | ||
2126 | .attach = gbe_attach, | ||
2127 | .release = gbe_release, | ||
2128 | .add_addr = gbe_add_addr, | ||
2129 | .del_addr = gbe_del_addr, | ||
2130 | .add_vid = gbe_add_vid, | ||
2131 | .del_vid = gbe_del_vid, | ||
2132 | .ioctl = gbe_ioctl, | ||
2133 | }; | ||
2134 | |||
1698 | static int __init keystone_gbe_init(void) | 2135 | static int __init keystone_gbe_init(void) |
1699 | { | 2136 | { |
1700 | int ret; | 2137 | int ret; |
@@ -1703,6 +2140,10 @@ static int __init keystone_gbe_init(void) | |||
1703 | if (ret) | 2140 | if (ret) |
1704 | return ret; | 2141 | return ret; |
1705 | 2142 | ||
2143 | ret = netcp_register_module(&xgbe_module); | ||
2144 | if (ret) | ||
2145 | return ret; | ||
2146 | |||
1706 | return 0; | 2147 | return 0; |
1707 | } | 2148 | } |
1708 | module_init(keystone_gbe_init); | 2149 | module_init(keystone_gbe_init); |
@@ -1710,5 +2151,6 @@ module_init(keystone_gbe_init); | |||
1710 | static void __exit keystone_gbe_exit(void) | 2151 | static void __exit keystone_gbe_exit(void) |
1711 | { | 2152 | { |
1712 | netcp_unregister_module(&gbe_module); | 2153 | netcp_unregister_module(&gbe_module); |
2154 | netcp_unregister_module(&xgbe_module); | ||
1713 | } | 2155 | } |
1714 | module_exit(keystone_gbe_exit); | 2156 | module_exit(keystone_gbe_exit); |
diff --git a/drivers/net/ethernet/ti/netcp_xgbepcsr.c b/drivers/net/ethernet/ti/netcp_xgbepcsr.c new file mode 100644 index 000000000000..33571acc52b6 --- /dev/null +++ b/drivers/net/ethernet/ti/netcp_xgbepcsr.c | |||
@@ -0,0 +1,501 @@ | |||
1 | /* | ||
2 | * XGE PCSR module initialisation | ||
3 | * | ||
4 | * Copyright (C) 2014 Texas Instruments Incorporated | ||
5 | * Authors: Sandeep Nair <sandeep_n@ti.com> | ||
6 | * WingMan Kwok <w-kwok2@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation version 2. | ||
11 | * | ||
12 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
13 | * kind, whether express or implied; without even the implied warranty | ||
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | #include "netcp.h" | ||
18 | |||
19 | /* XGBE registers */ | ||
20 | #define XGBE_CTRL_OFFSET 0x0c | ||
21 | #define XGBE_SGMII_1_OFFSET 0x0114 | ||
22 | #define XGBE_SGMII_2_OFFSET 0x0214 | ||
23 | |||
24 | /* PCS-R registers */ | ||
25 | #define PCSR_CPU_CTRL_OFFSET 0x1fd0 | ||
26 | #define POR_EN BIT(29) | ||
27 | |||
28 | #define reg_rmw(addr, value, mask) \ | ||
29 | writel(((readl(addr) & (~(mask))) | \ | ||
30 | (value & (mask))), (addr)) | ||
31 | |||
32 | /* bit mask of width w at offset s */ | ||
33 | #define MASK_WID_SH(w, s) (((1 << w) - 1) << s) | ||
34 | |||
35 | /* shift value v to offset s */ | ||
36 | #define VAL_SH(v, s) (v << s) | ||
37 | |||
38 | #define PHY_A(serdes) 0 | ||
39 | |||
40 | struct serdes_cfg { | ||
41 | u32 ofs; | ||
42 | u32 val; | ||
43 | u32 mask; | ||
44 | }; | ||
45 | |||
46 | static struct serdes_cfg cfg_phyb_1p25g_156p25mhz_cmu0[] = { | ||
47 | {0x0000, 0x00800002, 0x00ff00ff}, | ||
48 | {0x0014, 0x00003838, 0x0000ffff}, | ||
49 | {0x0060, 0x1c44e438, 0xffffffff}, | ||
50 | {0x0064, 0x00c18400, 0x00ffffff}, | ||
51 | {0x0068, 0x17078200, 0xffffff00}, | ||
52 | {0x006c, 0x00000014, 0x000000ff}, | ||
53 | {0x0078, 0x0000c000, 0x0000ff00}, | ||
54 | {0x0000, 0x00000003, 0x000000ff}, | ||
55 | }; | ||
56 | |||
57 | static struct serdes_cfg cfg_phyb_10p3125g_156p25mhz_cmu1[] = { | ||
58 | {0x0c00, 0x00030002, 0x00ff00ff}, | ||
59 | {0x0c14, 0x00005252, 0x0000ffff}, | ||
60 | {0x0c28, 0x80000000, 0xff000000}, | ||
61 | {0x0c2c, 0x000000f6, 0x000000ff}, | ||
62 | {0x0c3c, 0x04000405, 0xff00ffff}, | ||
63 | {0x0c40, 0xc0800000, 0xffff0000}, | ||
64 | {0x0c44, 0x5a202062, 0xffffffff}, | ||
65 | {0x0c48, 0x40040424, 0xffffffff}, | ||
66 | {0x0c4c, 0x00004002, 0x0000ffff}, | ||
67 | {0x0c50, 0x19001c00, 0xff00ff00}, | ||
68 | {0x0c54, 0x00002100, 0x0000ff00}, | ||
69 | {0x0c58, 0x00000060, 0x000000ff}, | ||
70 | {0x0c60, 0x80131e7c, 0xffffffff}, | ||
71 | {0x0c64, 0x8400cb02, 0xff00ffff}, | ||
72 | {0x0c68, 0x17078200, 0xffffff00}, | ||
73 | {0x0c6c, 0x00000016, 0x000000ff}, | ||
74 | {0x0c74, 0x00000400, 0x0000ff00}, | ||
75 | {0x0c78, 0x0000c000, 0x0000ff00}, | ||
76 | {0x0c00, 0x00000003, 0x000000ff}, | ||
77 | }; | ||
78 | |||
79 | static struct serdes_cfg cfg_phyb_10p3125g_16bit_lane[] = { | ||
80 | {0x0204, 0x00000080, 0x000000ff}, | ||
81 | {0x0208, 0x0000920d, 0x0000ffff}, | ||
82 | {0x0204, 0xfc000000, 0xff000000}, | ||
83 | {0x0208, 0x00009104, 0x0000ffff}, | ||
84 | {0x0210, 0x1a000000, 0xff000000}, | ||
85 | {0x0214, 0x00006b58, 0x00ffffff}, | ||
86 | {0x0218, 0x75800084, 0xffff00ff}, | ||
87 | {0x022c, 0x00300000, 0x00ff0000}, | ||
88 | {0x0230, 0x00003800, 0x0000ff00}, | ||
89 | {0x024c, 0x008f0000, 0x00ff0000}, | ||
90 | {0x0250, 0x30000000, 0xff000000}, | ||
91 | {0x0260, 0x00000002, 0x000000ff}, | ||
92 | {0x0264, 0x00000057, 0x000000ff}, | ||
93 | {0x0268, 0x00575700, 0x00ffff00}, | ||
94 | {0x0278, 0xff000000, 0xff000000}, | ||
95 | {0x0280, 0x00500050, 0x00ff00ff}, | ||
96 | {0x0284, 0x00001f15, 0x0000ffff}, | ||
97 | {0x028c, 0x00006f00, 0x0000ff00}, | ||
98 | {0x0294, 0x00000000, 0xffffff00}, | ||
99 | {0x0298, 0x00002640, 0xff00ffff}, | ||
100 | {0x029c, 0x00000003, 0x000000ff}, | ||
101 | {0x02a4, 0x00000f13, 0x0000ffff}, | ||
102 | {0x02a8, 0x0001b600, 0x00ffff00}, | ||
103 | {0x0380, 0x00000030, 0x000000ff}, | ||
104 | {0x03c0, 0x00000200, 0x0000ff00}, | ||
105 | {0x03cc, 0x00000018, 0x000000ff}, | ||
106 | {0x03cc, 0x00000000, 0x000000ff}, | ||
107 | }; | ||
108 | |||
109 | static struct serdes_cfg cfg_phyb_10p3125g_comlane[] = { | ||
110 | {0x0a00, 0x00000800, 0x0000ff00}, | ||
111 | {0x0a84, 0x00000000, 0x000000ff}, | ||
112 | {0x0a8c, 0x00130000, 0x00ff0000}, | ||
113 | {0x0a90, 0x77a00000, 0xffff0000}, | ||
114 | {0x0a94, 0x00007777, 0x0000ffff}, | ||
115 | {0x0b08, 0x000f0000, 0xffff0000}, | ||
116 | {0x0b0c, 0x000f0000, 0x00ffffff}, | ||
117 | {0x0b10, 0xbe000000, 0xff000000}, | ||
118 | {0x0b14, 0x000000ff, 0x000000ff}, | ||
119 | {0x0b18, 0x00000014, 0x000000ff}, | ||
120 | {0x0b5c, 0x981b0000, 0xffff0000}, | ||
121 | {0x0b64, 0x00001100, 0x0000ff00}, | ||
122 | {0x0b78, 0x00000c00, 0x0000ff00}, | ||
123 | {0x0abc, 0xff000000, 0xff000000}, | ||
124 | {0x0ac0, 0x0000008b, 0x000000ff}, | ||
125 | }; | ||
126 | |||
127 | static struct serdes_cfg cfg_cm_c1_c2[] = { | ||
128 | {0x0208, 0x00000000, 0x00000f00}, | ||
129 | {0x0208, 0x00000000, 0x0000001f}, | ||
130 | {0x0204, 0x00000000, 0x00040000}, | ||
131 | {0x0208, 0x000000a0, 0x000000e0}, | ||
132 | }; | ||
133 | |||
134 | static void netcp_xgbe_serdes_cmu_init(void __iomem *serdes_regs) | ||
135 | { | ||
136 | int i; | ||
137 | |||
138 | /* cmu0 setup */ | ||
139 | for (i = 0; i < ARRAY_SIZE(cfg_phyb_1p25g_156p25mhz_cmu0); i++) { | ||
140 | reg_rmw(serdes_regs + cfg_phyb_1p25g_156p25mhz_cmu0[i].ofs, | ||
141 | cfg_phyb_1p25g_156p25mhz_cmu0[i].val, | ||
142 | cfg_phyb_1p25g_156p25mhz_cmu0[i].mask); | ||
143 | } | ||
144 | |||
145 | /* cmu1 setup */ | ||
146 | for (i = 0; i < ARRAY_SIZE(cfg_phyb_10p3125g_156p25mhz_cmu1); i++) { | ||
147 | reg_rmw(serdes_regs + cfg_phyb_10p3125g_156p25mhz_cmu1[i].ofs, | ||
148 | cfg_phyb_10p3125g_156p25mhz_cmu1[i].val, | ||
149 | cfg_phyb_10p3125g_156p25mhz_cmu1[i].mask); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | /* lane is 0 based */ | ||
154 | static void netcp_xgbe_serdes_lane_config( | ||
155 | void __iomem *serdes_regs, int lane) | ||
156 | { | ||
157 | int i; | ||
158 | |||
159 | /* lane setup */ | ||
160 | for (i = 0; i < ARRAY_SIZE(cfg_phyb_10p3125g_16bit_lane); i++) { | ||
161 | reg_rmw(serdes_regs + | ||
162 | cfg_phyb_10p3125g_16bit_lane[i].ofs + | ||
163 | (0x200 * lane), | ||
164 | cfg_phyb_10p3125g_16bit_lane[i].val, | ||
165 | cfg_phyb_10p3125g_16bit_lane[i].mask); | ||
166 | } | ||
167 | |||
168 | /* disable auto negotiation*/ | ||
169 | reg_rmw(serdes_regs + (0x200 * lane) + 0x0380, | ||
170 | 0x00000000, 0x00000010); | ||
171 | |||
172 | /* disable link training */ | ||
173 | reg_rmw(serdes_regs + (0x200 * lane) + 0x03c0, | ||
174 | 0x00000000, 0x00000200); | ||
175 | } | ||
176 | |||
177 | static void netcp_xgbe_serdes_com_enable(void __iomem *serdes_regs) | ||
178 | { | ||
179 | int i; | ||
180 | |||
181 | for (i = 0; i < ARRAY_SIZE(cfg_phyb_10p3125g_comlane); i++) { | ||
182 | reg_rmw(serdes_regs + cfg_phyb_10p3125g_comlane[i].ofs, | ||
183 | cfg_phyb_10p3125g_comlane[i].val, | ||
184 | cfg_phyb_10p3125g_comlane[i].mask); | ||
185 | } | ||
186 | } | ||
187 | |||
188 | static void netcp_xgbe_serdes_lane_enable( | ||
189 | void __iomem *serdes_regs, int lane) | ||
190 | { | ||
191 | /* Set Lane Control Rate */ | ||
192 | writel(0xe0e9e038, serdes_regs + 0x1fe0 + (4 * lane)); | ||
193 | } | ||
194 | |||
195 | static void netcp_xgbe_serdes_phyb_rst_clr(void __iomem *serdes_regs) | ||
196 | { | ||
197 | reg_rmw(serdes_regs + 0x0a00, 0x0000001f, 0x000000ff); | ||
198 | } | ||
199 | |||
200 | static void netcp_xgbe_serdes_pll_disable(void __iomem *serdes_regs) | ||
201 | { | ||
202 | writel(0x88000000, serdes_regs + 0x1ff4); | ||
203 | } | ||
204 | |||
205 | static void netcp_xgbe_serdes_pll_enable(void __iomem *serdes_regs) | ||
206 | { | ||
207 | netcp_xgbe_serdes_phyb_rst_clr(serdes_regs); | ||
208 | writel(0xee000000, serdes_regs + 0x1ff4); | ||
209 | } | ||
210 | |||
211 | static int netcp_xgbe_wait_pll_locked(void __iomem *sw_regs) | ||
212 | { | ||
213 | unsigned long timeout; | ||
214 | int ret = 0; | ||
215 | u32 val_1, val_0; | ||
216 | |||
217 | timeout = jiffies + msecs_to_jiffies(500); | ||
218 | do { | ||
219 | val_0 = (readl(sw_regs + XGBE_SGMII_1_OFFSET) & BIT(4)); | ||
220 | val_1 = (readl(sw_regs + XGBE_SGMII_2_OFFSET) & BIT(4)); | ||
221 | |||
222 | if (val_1 && val_0) | ||
223 | return 0; | ||
224 | |||
225 | if (time_after(jiffies, timeout)) { | ||
226 | ret = -ETIMEDOUT; | ||
227 | break; | ||
228 | } | ||
229 | |||
230 | cpu_relax(); | ||
231 | } while (true); | ||
232 | |||
233 | pr_err("XGBE serdes not locked: time out.\n"); | ||
234 | return ret; | ||
235 | } | ||
236 | |||
237 | static void netcp_xgbe_serdes_enable_xgmii_port(void __iomem *sw_regs) | ||
238 | { | ||
239 | writel(0x03, sw_regs + XGBE_CTRL_OFFSET); | ||
240 | } | ||
241 | |||
242 | static u32 netcp_xgbe_serdes_read_tbus_val(void __iomem *serdes_regs) | ||
243 | { | ||
244 | u32 tmp; | ||
245 | |||
246 | if (PHY_A(serdes_regs)) { | ||
247 | tmp = (readl(serdes_regs + 0x0ec) >> 24) & 0x0ff; | ||
248 | tmp |= ((readl(serdes_regs + 0x0fc) >> 16) & 0x00f00); | ||
249 | } else { | ||
250 | tmp = (readl(serdes_regs + 0x0f8) >> 16) & 0x0fff; | ||
251 | } | ||
252 | |||
253 | return tmp; | ||
254 | } | ||
255 | |||
256 | static void netcp_xgbe_serdes_write_tbus_addr(void __iomem *serdes_regs, | ||
257 | int select, int ofs) | ||
258 | { | ||
259 | if (PHY_A(serdes_regs)) { | ||
260 | reg_rmw(serdes_regs + 0x0008, ((select << 5) + ofs) << 24, | ||
261 | ~0x00ffffff); | ||
262 | return; | ||
263 | } | ||
264 | |||
265 | /* For 2 lane Phy-B, lane0 is actually lane1 */ | ||
266 | switch (select) { | ||
267 | case 1: | ||
268 | select = 2; | ||
269 | break; | ||
270 | case 2: | ||
271 | select = 3; | ||
272 | break; | ||
273 | default: | ||
274 | return; | ||
275 | } | ||
276 | |||
277 | reg_rmw(serdes_regs + 0x00fc, ((select << 8) + ofs) << 16, ~0xf800ffff); | ||
278 | } | ||
279 | |||
280 | static u32 netcp_xgbe_serdes_read_select_tbus(void __iomem *serdes_regs, | ||
281 | int select, int ofs) | ||
282 | { | ||
283 | /* Set tbus address */ | ||
284 | netcp_xgbe_serdes_write_tbus_addr(serdes_regs, select, ofs); | ||
285 | /* Get TBUS Value */ | ||
286 | return netcp_xgbe_serdes_read_tbus_val(serdes_regs); | ||
287 | } | ||
288 | |||
289 | static void netcp_xgbe_serdes_reset_cdr(void __iomem *serdes_regs, | ||
290 | void __iomem *sig_detect_reg, int lane) | ||
291 | { | ||
292 | u32 tmp, dlpf, tbus; | ||
293 | |||
294 | /*Get the DLPF values */ | ||
295 | tmp = netcp_xgbe_serdes_read_select_tbus( | ||
296 | serdes_regs, lane + 1, 5); | ||
297 | |||
298 | dlpf = tmp >> 2; | ||
299 | |||
300 | if (dlpf < 400 || dlpf > 700) { | ||
301 | reg_rmw(sig_detect_reg, VAL_SH(2, 1), MASK_WID_SH(2, 1)); | ||
302 | mdelay(1); | ||
303 | reg_rmw(sig_detect_reg, VAL_SH(0, 1), MASK_WID_SH(2, 1)); | ||
304 | } else { | ||
305 | tbus = netcp_xgbe_serdes_read_select_tbus(serdes_regs, lane + | ||
306 | 1, 0xe); | ||
307 | |||
308 | pr_debug("XGBE: CDR centered, DLPF: %4d,%d,%d.\n", | ||
309 | tmp >> 2, tmp & 3, (tbus >> 2) & 3); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | /* Call every 100 ms */ | ||
314 | static int netcp_xgbe_check_link_status(void __iomem *serdes_regs, | ||
315 | void __iomem *sw_regs, u32 lanes, | ||
316 | u32 *current_state, u32 *lane_down) | ||
317 | { | ||
318 | void __iomem *pcsr_base = sw_regs + 0x0600; | ||
319 | void __iomem *sig_detect_reg; | ||
320 | u32 pcsr_rx_stat, blk_lock, blk_errs; | ||
321 | int loss, i, status = 1; | ||
322 | |||
323 | for (i = 0; i < lanes; i++) { | ||
324 | /* Get the Loss bit */ | ||
325 | loss = readl(serdes_regs + 0x1fc0 + 0x20 + (i * 0x04)) & 0x1; | ||
326 | |||
327 | /* Get Block Errors and Block Lock bits */ | ||
328 | pcsr_rx_stat = readl(pcsr_base + 0x0c + (i * 0x80)); | ||
329 | blk_lock = (pcsr_rx_stat >> 30) & 0x1; | ||
330 | blk_errs = (pcsr_rx_stat >> 16) & 0x0ff; | ||
331 | |||
332 | /* Get Signal Detect Overlay Address */ | ||
333 | sig_detect_reg = serdes_regs + (i * 0x200) + 0x200 + 0x04; | ||
334 | |||
335 | /* If Block errors maxed out, attempt recovery! */ | ||
336 | if (blk_errs == 0x0ff) | ||
337 | blk_lock = 0; | ||
338 | |||
339 | switch (current_state[i]) { | ||
340 | case 0: | ||
341 | /* if good link lock the signal detect ON! */ | ||
342 | if (!loss && blk_lock) { | ||
343 | pr_debug("XGBE PCSR Linked Lane: %d\n", i); | ||
344 | reg_rmw(sig_detect_reg, VAL_SH(3, 1), | ||
345 | MASK_WID_SH(2, 1)); | ||
346 | current_state[i] = 1; | ||
347 | } else if (!blk_lock) { | ||
348 | /* if no lock, then reset CDR */ | ||
349 | pr_debug("XGBE PCSR Recover Lane: %d\n", i); | ||
350 | netcp_xgbe_serdes_reset_cdr(serdes_regs, | ||
351 | sig_detect_reg, i); | ||
352 | } | ||
353 | break; | ||
354 | |||
355 | case 1: | ||
356 | if (!blk_lock) { | ||
357 | /* Link Lost? */ | ||
358 | lane_down[i] = 1; | ||
359 | current_state[i] = 2; | ||
360 | } | ||
361 | break; | ||
362 | |||
363 | case 2: | ||
364 | if (blk_lock) | ||
365 | /* Nope just noise */ | ||
366 | current_state[i] = 1; | ||
367 | else { | ||
368 | /* Lost the block lock, reset CDR if it is | ||
369 | * not centered and go back to sync state | ||
370 | */ | ||
371 | netcp_xgbe_serdes_reset_cdr(serdes_regs, | ||
372 | sig_detect_reg, i); | ||
373 | current_state[i] = 0; | ||
374 | } | ||
375 | break; | ||
376 | |||
377 | default: | ||
378 | pr_err("XGBE: unknown current_state[%d] %d\n", | ||
379 | i, current_state[i]); | ||
380 | break; | ||
381 | } | ||
382 | |||
383 | if (blk_errs > 0) { | ||
384 | /* Reset the Error counts! */ | ||
385 | reg_rmw(pcsr_base + 0x08 + (i * 0x80), VAL_SH(0x19, 0), | ||
386 | MASK_WID_SH(8, 0)); | ||
387 | |||
388 | reg_rmw(pcsr_base + 0x08 + (i * 0x80), VAL_SH(0x00, 0), | ||
389 | MASK_WID_SH(8, 0)); | ||
390 | } | ||
391 | |||
392 | status &= (current_state[i] == 1); | ||
393 | } | ||
394 | |||
395 | return status; | ||
396 | } | ||
397 | |||
398 | static int netcp_xgbe_serdes_check_lane(void __iomem *serdes_regs, | ||
399 | void __iomem *sw_regs) | ||
400 | { | ||
401 | u32 current_state[2] = {0, 0}; | ||
402 | int retries = 0, link_up; | ||
403 | u32 lane_down[2]; | ||
404 | |||
405 | do { | ||
406 | lane_down[0] = 0; | ||
407 | lane_down[1] = 0; | ||
408 | |||
409 | link_up = netcp_xgbe_check_link_status(serdes_regs, sw_regs, 2, | ||
410 | current_state, | ||
411 | lane_down); | ||
412 | |||
413 | /* if we did not get link up then wait 100ms before calling | ||
414 | * it again | ||
415 | */ | ||
416 | if (link_up) | ||
417 | break; | ||
418 | |||
419 | if (lane_down[0]) | ||
420 | pr_debug("XGBE: detected link down on lane 0\n"); | ||
421 | |||
422 | if (lane_down[1]) | ||
423 | pr_debug("XGBE: detected link down on lane 1\n"); | ||
424 | |||
425 | if (++retries > 1) { | ||
426 | pr_debug("XGBE: timeout waiting for serdes link up\n"); | ||
427 | return -ETIMEDOUT; | ||
428 | } | ||
429 | mdelay(100); | ||
430 | } while (!link_up); | ||
431 | |||
432 | pr_debug("XGBE: PCSR link is up\n"); | ||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static void netcp_xgbe_serdes_setup_cm_c1_c2(void __iomem *serdes_regs, | ||
437 | int lane, int cm, int c1, int c2) | ||
438 | { | ||
439 | int i; | ||
440 | |||
441 | for (i = 0; i < ARRAY_SIZE(cfg_cm_c1_c2); i++) { | ||
442 | reg_rmw(serdes_regs + cfg_cm_c1_c2[i].ofs + (0x200 * lane), | ||
443 | cfg_cm_c1_c2[i].val, | ||
444 | cfg_cm_c1_c2[i].mask); | ||
445 | } | ||
446 | } | ||
447 | |||
448 | static void netcp_xgbe_reset_serdes(void __iomem *serdes_regs) | ||
449 | { | ||
450 | /* Toggle the POR_EN bit in CONFIG.CPU_CTRL */ | ||
451 | /* enable POR_EN bit */ | ||
452 | reg_rmw(serdes_regs + PCSR_CPU_CTRL_OFFSET, POR_EN, POR_EN); | ||
453 | usleep_range(10, 100); | ||
454 | |||
455 | /* disable POR_EN bit */ | ||
456 | reg_rmw(serdes_regs + PCSR_CPU_CTRL_OFFSET, 0, POR_EN); | ||
457 | usleep_range(10, 100); | ||
458 | } | ||
459 | |||
460 | static int netcp_xgbe_serdes_config(void __iomem *serdes_regs, | ||
461 | void __iomem *sw_regs) | ||
462 | { | ||
463 | u32 ret, i; | ||
464 | |||
465 | netcp_xgbe_serdes_pll_disable(serdes_regs); | ||
466 | netcp_xgbe_serdes_cmu_init(serdes_regs); | ||
467 | |||
468 | for (i = 0; i < 2; i++) | ||
469 | netcp_xgbe_serdes_lane_config(serdes_regs, i); | ||
470 | |||
471 | netcp_xgbe_serdes_com_enable(serdes_regs); | ||
472 | /* This is EVM + RTM-BOC specific */ | ||
473 | for (i = 0; i < 2; i++) | ||
474 | netcp_xgbe_serdes_setup_cm_c1_c2(serdes_regs, i, 0, 0, 5); | ||
475 | |||
476 | netcp_xgbe_serdes_pll_enable(serdes_regs); | ||
477 | for (i = 0; i < 2; i++) | ||
478 | netcp_xgbe_serdes_lane_enable(serdes_regs, i); | ||
479 | |||
480 | /* SB PLL Status Poll */ | ||
481 | ret = netcp_xgbe_wait_pll_locked(sw_regs); | ||
482 | if (ret) | ||
483 | return ret; | ||
484 | |||
485 | netcp_xgbe_serdes_enable_xgmii_port(sw_regs); | ||
486 | netcp_xgbe_serdes_check_lane(serdes_regs, sw_regs); | ||
487 | return ret; | ||
488 | } | ||
489 | |||
490 | int netcp_xgbe_serdes_init(void __iomem *serdes_regs, void __iomem *xgbe_regs) | ||
491 | { | ||
492 | u32 val; | ||
493 | |||
494 | /* read COMLANE bits 4:0 */ | ||
495 | val = readl(serdes_regs + 0xa00); | ||
496 | if (val & 0x1f) { | ||
497 | pr_debug("XGBE: serdes already in operation - reset\n"); | ||
498 | netcp_xgbe_reset_serdes(serdes_regs); | ||
499 | } | ||
500 | return netcp_xgbe_serdes_config(serdes_regs, xgbe_regs); | ||
501 | } | ||