1 /**************************************************************************
2 SPDX-License-Identifier: BSD-2-Clause
3
4 Copyright (c) 2007, Chelsio Inc.
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 1. Redistributions of source code must retain the above copyright notice,
11 this list of conditions and the following disclaimer.
12
13 2. Neither the name of the Chelsio Corporation nor the names of its
14 contributors may be used to endorse or promote products derived from
15 this software without specific prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 POSSIBILITY OF SUCH DAMAGE.
28
29 ***************************************************************************/
30
31 #include <sys/cdefs.h>
32 #include <common/cxgb_common.h>
33
34 enum {
35 ELMR_ADDR = 0,
36 ELMR_STAT = 1,
37 ELMR_DATA_LO = 2,
38 ELMR_DATA_HI = 3,
39
40 ELMR_THRES0 = 0xe000,
41 ELMR_BW = 0xe00c,
42 ELMR_FIFO_SZ = 0xe00d,
43 ELMR_STATS = 0xf000,
44
45 ELMR_MDIO_ADDR = 10
46 };
47
48 #define VSC_REG(block, subblock, reg) \
49 ((reg) | ((subblock) << 8) | ((block) << 12))
50
t3_elmr_blk_write(adapter_t * adap,int start,const u32 * vals,int n)51 int t3_elmr_blk_write(adapter_t *adap, int start, const u32 *vals, int n)
52 {
53 int ret;
54 const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
55
56 ELMR_LOCK(adap);
57 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
58 for ( ; !ret && n; n--, vals++) {
59 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO,
60 *vals & 0xffff);
61 if (!ret)
62 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
63 *vals >> 16);
64 }
65 ELMR_UNLOCK(adap);
66 return ret;
67 }
68
elmr_write(adapter_t * adap,int addr,u32 val)69 static int elmr_write(adapter_t *adap, int addr, u32 val)
70 {
71 return t3_elmr_blk_write(adap, addr, &val, 1);
72 }
73
t3_elmr_blk_read(adapter_t * adap,int start,u32 * vals,int n)74 int t3_elmr_blk_read(adapter_t *adap, int start, u32 *vals, int n)
75 {
76 int i, ret;
77 unsigned int v;
78 const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
79
80 ELMR_LOCK(adap);
81
82 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
83 if (ret)
84 goto out;
85
86 for (i = 0; i < 5; i++) {
87 ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_STAT, &v);
88 if (ret)
89 goto out;
90 if (v == 1)
91 break;
92 udelay(5);
93 }
94 if (v != 1) {
95 ret = -ETIMEDOUT;
96 goto out;
97 }
98
99 for ( ; !ret && n; n--, vals++) {
100 ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO, vals);
101 if (!ret) {
102 ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
103 &v);
104 *vals |= v << 16;
105 }
106 }
107 out: ELMR_UNLOCK(adap);
108 return ret;
109 }
110
t3_vsc7323_init(adapter_t * adap,int nports)111 int t3_vsc7323_init(adapter_t *adap, int nports)
112 {
113 static struct addr_val_pair sys_avp[] = {
114 { VSC_REG(7, 15, 0xf), 2 },
115 { VSC_REG(7, 15, 0x19), 0xd6 },
116 { VSC_REG(7, 15, 7), 0xc },
117 { VSC_REG(7, 1, 0), 0x220 },
118 };
119 static struct addr_val_pair fifo_avp[] = {
120 { VSC_REG(2, 0, 0x2f), 0 },
121 { VSC_REG(2, 0, 0xf), 0xa0010291 },
122 { VSC_REG(2, 1, 0x2f), 1 },
123 { VSC_REG(2, 1, 0xf), 0xa026301 }
124 };
125 static struct addr_val_pair xg_avp[] = {
126 { VSC_REG(1, 10, 0), 0x600b },
127 { VSC_REG(1, 10, 1), 0x70600 }, //QUANTA = 96*1024*8/512
128 { VSC_REG(1, 10, 2), 0x2710 },
129 { VSC_REG(1, 10, 5), 0x65 },
130 { VSC_REG(1, 10, 7), 0x23 },
131 { VSC_REG(1, 10, 0x23), 0x800007bf },
132 { VSC_REG(1, 10, 0x23), 0x000007bf },
133 { VSC_REG(1, 10, 0x23), 0x800007bf },
134 { VSC_REG(1, 10, 0x24), 4 }
135 };
136
137 int i, ret, ing_step, egr_step, ing_bot, egr_bot;
138
139 for (i = 0; i < ARRAY_SIZE(sys_avp); i++)
140 if ((ret = t3_elmr_blk_write(adap, sys_avp[i].reg_addr,
141 &sys_avp[i].val, 1)))
142 return ret;
143
144 ing_step = 0xc0 / nports;
145 egr_step = 0x40 / nports;
146 ing_bot = egr_bot = 0;
147 // ing_wm = ing_step * 64;
148 // egr_wm = egr_step * 64;
149
150 /* {ING,EGR}_CONTROL.CLR = 1 here */
151 for (i = 0; i < nports; i++) {
152 if (
153 (ret = elmr_write(adap, VSC_REG(2, 0, 0x10 + i),
154 ((ing_bot + ing_step) << 16) | ing_bot)) ||
155 (ret = elmr_write(adap, VSC_REG(2, 0, 0x40 + i),
156 0x6000bc0)) ||
157 (ret = elmr_write(adap, VSC_REG(2, 0, 0x50 + i), 1)) ||
158 (ret = elmr_write(adap, VSC_REG(2, 1, 0x10 + i),
159 ((egr_bot + egr_step) << 16) | egr_bot)) ||
160 (ret = elmr_write(adap, VSC_REG(2, 1, 0x40 + i),
161 0x2000280)) ||
162 (ret = elmr_write(adap, VSC_REG(2, 1, 0x50 + i), 0)))
163 return ret;
164 ing_bot += ing_step;
165 egr_bot += egr_step;
166 }
167
168 for (i = 0; i < ARRAY_SIZE(fifo_avp); i++)
169 if ((ret = t3_elmr_blk_write(adap, fifo_avp[i].reg_addr,
170 &fifo_avp[i].val, 1)))
171 return ret;
172
173 for (i = 0; i < ARRAY_SIZE(xg_avp); i++)
174 if ((ret = t3_elmr_blk_write(adap, xg_avp[i].reg_addr,
175 &xg_avp[i].val, 1)))
176 return ret;
177
178 for (i = 0; i < nports; i++)
179 if ((ret = elmr_write(adap, VSC_REG(1, i, 0), 0xa59c)) ||
180 (ret = elmr_write(adap, VSC_REG(1, i, 5),
181 (i << 12) | 0x63)) ||
182 (ret = elmr_write(adap, VSC_REG(1, i, 0xb), 0x96)) ||
183 (ret = elmr_write(adap, VSC_REG(1, i, 0x15), 0x21)) ||
184 (ret = elmr_write(adap, ELMR_THRES0 + i, 768)))
185 return ret;
186
187 if ((ret = elmr_write(adap, ELMR_BW, 7)))
188 return ret;
189
190 return ret;
191 }
192
t3_vsc7323_set_speed_fc(adapter_t * adap,int speed,int fc,int port)193 int t3_vsc7323_set_speed_fc(adapter_t *adap, int speed, int fc, int port)
194 {
195 int mode, clk, r;
196
197 if (speed >= 0) {
198 if (speed == SPEED_10)
199 mode = clk = 1;
200 else if (speed == SPEED_100)
201 mode = 1, clk = 2;
202 else if (speed == SPEED_1000)
203 mode = clk = 3;
204 else
205 return -EINVAL;
206
207 if ((r = elmr_write(adap, VSC_REG(1, port, 0),
208 0xa590 | (mode << 2))) ||
209 (r = elmr_write(adap, VSC_REG(1, port, 0xb),
210 0x91 | (clk << 1))) ||
211 (r = elmr_write(adap, VSC_REG(1, port, 0xb),
212 0x90 | (clk << 1))) ||
213 (r = elmr_write(adap, VSC_REG(1, port, 0),
214 0xa593 | (mode << 2))))
215 return r;
216 }
217
218 r = (fc & PAUSE_RX) ? 0x60200 : 0x20200; //QUANTA = 32*1024*8/512
219 if (fc & PAUSE_TX)
220 r |= (1 << 19);
221 return elmr_write(adap, VSC_REG(1, port, 1), r);
222 }
223
t3_vsc7323_set_mtu(adapter_t * adap,unsigned int mtu,int port)224 int t3_vsc7323_set_mtu(adapter_t *adap, unsigned int mtu, int port)
225 {
226 return elmr_write(adap, VSC_REG(1, port, 2), mtu);
227 }
228
t3_vsc7323_set_addr(adapter_t * adap,u8 addr[6],int port)229 int t3_vsc7323_set_addr(adapter_t *adap, u8 addr[6], int port)
230 {
231 int ret;
232
233 ret = elmr_write(adap, VSC_REG(1, port, 3),
234 (addr[0] << 16) | (addr[1] << 8) | addr[2]);
235 if (!ret)
236 ret = elmr_write(adap, VSC_REG(1, port, 4),
237 (addr[3] << 16) | (addr[4] << 8) | addr[5]);
238 return ret;
239 }
240
t3_vsc7323_enable(adapter_t * adap,int port,int which)241 int t3_vsc7323_enable(adapter_t *adap, int port, int which)
242 {
243 int ret;
244 unsigned int v, orig;
245
246 ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
247 if (!ret) {
248 orig = v;
249 if (which & MAC_DIRECTION_TX)
250 v |= 1;
251 if (which & MAC_DIRECTION_RX)
252 v |= 2;
253 if (v != orig)
254 ret = elmr_write(adap, VSC_REG(1, port, 0), v);
255 }
256 return ret;
257 }
258
t3_vsc7323_disable(adapter_t * adap,int port,int which)259 int t3_vsc7323_disable(adapter_t *adap, int port, int which)
260 {
261 int ret;
262 unsigned int v, orig;
263
264 ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
265 if (!ret) {
266 orig = v;
267 if (which & MAC_DIRECTION_TX)
268 v &= ~1;
269 if (which & MAC_DIRECTION_RX)
270 v &= ~2;
271 if (v != orig)
272 ret = elmr_write(adap, VSC_REG(1, port, 0), v);
273 }
274 return ret;
275 }
276
277 #define STATS0_START 1
278 #define STATS1_START 0x24
279 #define NSTATS0 (0x1d - STATS0_START + 1)
280 #define NSTATS1 (0x2a - STATS1_START + 1)
281
282 #define ELMR_STAT(port, reg) (ELMR_STATS + port * 0x40 + reg)
283
t3_vsc7323_update_stats(struct cmac * mac)284 const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac)
285 {
286 int ret;
287 u64 rx_ucast, tx_ucast;
288 u32 stats0[NSTATS0], stats1[NSTATS1];
289
290 ret = t3_elmr_blk_read(mac->adapter,
291 ELMR_STAT(mac->ext_port, STATS0_START),
292 stats0, NSTATS0);
293 if (!ret)
294 ret = t3_elmr_blk_read(mac->adapter,
295 ELMR_STAT(mac->ext_port, STATS1_START),
296 stats1, NSTATS1);
297 if (ret)
298 goto out;
299
300 /*
301 * HW counts Rx/Tx unicast frames but we want all the frames.
302 */
303 rx_ucast = mac->stats.rx_frames - mac->stats.rx_mcast_frames -
304 mac->stats.rx_bcast_frames;
305 rx_ucast += (u64)(stats0[6 - STATS0_START] - (u32)rx_ucast);
306 tx_ucast = mac->stats.tx_frames - mac->stats.tx_mcast_frames -
307 mac->stats.tx_bcast_frames;
308 tx_ucast += (u64)(stats0[27 - STATS0_START] - (u32)tx_ucast);
309
310 #define RMON_UPDATE(mac, name, hw_stat) \
311 mac->stats.name += (u64)((hw_stat) - (u32)(mac->stats.name))
312
313 RMON_UPDATE(mac, rx_octets, stats0[4 - STATS0_START]);
314 RMON_UPDATE(mac, rx_frames, stats0[6 - STATS0_START]);
315 RMON_UPDATE(mac, rx_frames, stats0[7 - STATS0_START]);
316 RMON_UPDATE(mac, rx_frames, stats0[8 - STATS0_START]);
317 RMON_UPDATE(mac, rx_mcast_frames, stats0[7 - STATS0_START]);
318 RMON_UPDATE(mac, rx_bcast_frames, stats0[8 - STATS0_START]);
319 RMON_UPDATE(mac, rx_fcs_errs, stats0[9 - STATS0_START]);
320 RMON_UPDATE(mac, rx_pause, stats0[2 - STATS0_START]);
321 RMON_UPDATE(mac, rx_jabber, stats0[16 - STATS0_START]);
322 RMON_UPDATE(mac, rx_short, stats0[11 - STATS0_START]);
323 RMON_UPDATE(mac, rx_symbol_errs, stats0[1 - STATS0_START]);
324 RMON_UPDATE(mac, rx_too_long, stats0[15 - STATS0_START]);
325
326 RMON_UPDATE(mac, rx_frames_64, stats0[17 - STATS0_START]);
327 RMON_UPDATE(mac, rx_frames_65_127, stats0[18 - STATS0_START]);
328 RMON_UPDATE(mac, rx_frames_128_255, stats0[19 - STATS0_START]);
329 RMON_UPDATE(mac, rx_frames_256_511, stats0[20 - STATS0_START]);
330 RMON_UPDATE(mac, rx_frames_512_1023, stats0[21 - STATS0_START]);
331 RMON_UPDATE(mac, rx_frames_1024_1518, stats0[22 - STATS0_START]);
332 RMON_UPDATE(mac, rx_frames_1519_max, stats0[23 - STATS0_START]);
333
334 RMON_UPDATE(mac, tx_octets, stats0[26 - STATS0_START]);
335 RMON_UPDATE(mac, tx_frames, stats0[27 - STATS0_START]);
336 RMON_UPDATE(mac, tx_frames, stats0[28 - STATS0_START]);
337 RMON_UPDATE(mac, tx_frames, stats0[29 - STATS0_START]);
338 RMON_UPDATE(mac, tx_mcast_frames, stats0[28 - STATS0_START]);
339 RMON_UPDATE(mac, tx_bcast_frames, stats0[29 - STATS0_START]);
340 RMON_UPDATE(mac, tx_pause, stats0[25 - STATS0_START]);
341
342 RMON_UPDATE(mac, tx_underrun, 0);
343
344 RMON_UPDATE(mac, tx_frames_64, stats1[36 - STATS1_START]);
345 RMON_UPDATE(mac, tx_frames_65_127, stats1[37 - STATS1_START]);
346 RMON_UPDATE(mac, tx_frames_128_255, stats1[38 - STATS1_START]);
347 RMON_UPDATE(mac, tx_frames_256_511, stats1[39 - STATS1_START]);
348 RMON_UPDATE(mac, tx_frames_512_1023, stats1[40 - STATS1_START]);
349 RMON_UPDATE(mac, tx_frames_1024_1518, stats1[41 - STATS1_START]);
350 RMON_UPDATE(mac, tx_frames_1519_max, stats1[42 - STATS1_START]);
351
352 #undef RMON_UPDATE
353
354 mac->stats.rx_frames = rx_ucast + mac->stats.rx_mcast_frames +
355 mac->stats.rx_bcast_frames;
356 mac->stats.tx_frames = tx_ucast + mac->stats.tx_mcast_frames +
357 mac->stats.tx_bcast_frames;
358 out: return &mac->stats;
359 }
360