]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/cxgb/common/cxgb_vsc7323.c
This commit was generated by cvs2svn to compensate for changes in r171537,
[FreeBSD/FreeBSD.git] / sys / dev / cxgb / common / cxgb_vsc7323.c
1
2 /**************************************************************************
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 __FBSDID("$FreeBSD$");
33
34 #ifdef CONFIG_DEFINED
35 #include <common/cxgb_common.h>
36 #else
37 #include <dev/cxgb/common/cxgb_common.h>
38 #endif
39
40 enum {
41         ELMR_ADDR    = 0,
42         ELMR_STAT    = 1,
43         ELMR_DATA_LO = 2,
44         ELMR_DATA_HI = 3,
45
46         ELMR_MDIO_ADDR = 10
47 };
48
49 #define VSC_REG(block, subblock, reg) \
50         ((reg) | ((subblock) << 8) | ((block) << 12))
51
52 int t3_elmr_blk_write(adapter_t *adap, int start, const u32 *vals, int n)
53 {
54         int ret;
55         const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
56
57         ELMR_LOCK(adap);
58         ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
59         for ( ; !ret && n; n--, vals++) {
60                 ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO,
61                                 *vals & 0xffff);
62                 if (!ret)
63                         ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
64                                         *vals >> 16);
65         }
66         ELMR_UNLOCK(adap);
67         return ret;
68 }
69
70 static int elmr_write(adapter_t *adap, int addr, u32 val)
71 {
72         return t3_elmr_blk_write(adap, addr, &val, 1);
73 }
74
75 int t3_elmr_blk_read(adapter_t *adap, int start, u32 *vals, int n)
76 {
77         int ret;
78         unsigned int v;
79         const struct mdio_ops *mo = adapter_info(adap)->mdio_ops;
80
81         ELMR_LOCK(adap);
82
83         ret = mo->write(adap, ELMR_MDIO_ADDR, 0, ELMR_ADDR, start);
84         if (ret)
85                 goto out;
86         ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_STAT, &v);
87         if (ret)
88                 goto out;
89         if (v != 1) {
90                 ret = -ETIMEDOUT;
91                 goto out;
92         }
93
94         for ( ; !ret && n; n--, vals++) {
95                 ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_LO, vals);
96                 if (!ret) {
97                         ret = mo->read(adap, ELMR_MDIO_ADDR, 0, ELMR_DATA_HI,
98                                        &v);
99                         *vals |= v << 16;
100                 }
101         }
102 out:    ELMR_UNLOCK(adap);
103         return ret;
104 }
105
106 int t3_vsc7323_init(adapter_t *adap, int nports)
107 {
108         static struct addr_val_pair sys_avp[] = {
109                 { VSC_REG(7, 15, 0xf),  2 },
110                 { VSC_REG(7, 15, 0x19), 0xd6 },
111                 { VSC_REG(7, 15, 7),    0xc },
112                 { VSC_REG(7, 1, 0),     0x220 },
113         };
114         static struct addr_val_pair fifo_avp[] = {
115                 { VSC_REG(2, 0, 0x2f), 0 },
116                 { VSC_REG(2, 0, 0xf),  0xa0010291 },
117                 { VSC_REG(2, 1, 0x2f), 1 },
118                 { VSC_REG(2, 1, 0xf),  0xa026301 }
119         };
120         static struct addr_val_pair xg_avp[] = {
121                 { VSC_REG(1, 10, 0),    0x600b },
122                 { VSC_REG(1, 10, 1),    0x70600 }, //QUANTA = 96*1024*8/512
123                 { VSC_REG(1, 10, 2),    0x2710 },
124                 { VSC_REG(1, 10, 5),    0x65 },
125                 { VSC_REG(1, 10, 7),    0x23 },
126                 { VSC_REG(1, 10, 0x23), 0x800007bf },
127                 { VSC_REG(1, 10, 0x23), 0x000007bf },
128                 { VSC_REG(1, 10, 0x23), 0x800007bf },
129                 { VSC_REG(1, 10, 0x24), 4 }
130         };
131
132         int i, ret, ing_step, egr_step, ing_bot, egr_bot;
133
134         for (i = 0; i < ARRAY_SIZE(sys_avp); i++)
135                 if ((ret = t3_elmr_blk_write(adap, sys_avp[i].reg_addr,
136                                              &sys_avp[i].val, 1)))
137                         return ret;
138
139         ing_step = 0xc0 / nports;
140         egr_step = 0x40 / nports;
141         ing_bot = egr_bot = 0;
142 //      ing_wm = ing_step * 64;
143 //      egr_wm = egr_step * 64;
144
145         /* {ING,EGR}_CONTROL.CLR = 1 here */
146         for (i = 0; i < nports; i++) {
147                 if (
148                     (ret = elmr_write(adap, VSC_REG(2, 0, 0x10 + i),
149                                 ((ing_bot + ing_step) << 16) | ing_bot)) ||
150                     (ret = elmr_write(adap, VSC_REG(2, 0, 0x40 + i),
151                                 0x6000a00)) ||
152                     (ret = elmr_write(adap, VSC_REG(2, 0, 0x50 + i), 1)) ||
153                     (ret = elmr_write(adap, VSC_REG(2, 1, 0x10 + i),
154                                 ((egr_bot + egr_step) << 16) | egr_bot)) ||
155                     (ret = elmr_write(adap, VSC_REG(2, 1, 0x40 + i),
156                                 0x2000280)) ||
157                     (ret = elmr_write(adap, VSC_REG(2, 1, 0x50 + i), 0)))
158                         return ret;
159                 ing_bot += ing_step;
160                 egr_bot += egr_step;
161         }
162
163         for (i = 0; i < ARRAY_SIZE(fifo_avp); i++)
164                 if ((ret = t3_elmr_blk_write(adap, fifo_avp[i].reg_addr,
165                                              &fifo_avp[i].val, 1)))
166                         return ret;
167
168         for (i = 0; i < ARRAY_SIZE(xg_avp); i++)
169                 if ((ret = t3_elmr_blk_write(adap, xg_avp[i].reg_addr,
170                                              &xg_avp[i].val, 1)))
171                         return ret;
172
173         for (i = 0; i < nports; i++)
174                 if ((ret = elmr_write(adap, VSC_REG(1, i, 0), 0xa59c)) ||
175                     (ret = elmr_write(adap, VSC_REG(1, i, 5),
176                                  (i << 12) | 0x63)) ||
177                     (ret = elmr_write(adap, VSC_REG(1, i, 0xb), 0x96)) ||
178                     (ret = elmr_write(adap, VSC_REG(1, i, 0x15), 0x21)))
179                         return ret;
180         return ret;
181 }
182
183 int t3_vsc7323_set_speed_fc(adapter_t *adap, int speed, int fc, int port)
184 {
185         int mode, clk, r;
186
187         if (speed >= 0) {
188                 if (speed == SPEED_10)
189                         mode = clk = 1;
190                 else if (speed == SPEED_100)
191                         mode = 1, clk = 2;
192                 else if (speed == SPEED_1000)
193                         mode = clk = 3;
194                 else
195                         return -EINVAL;
196
197                 if ((r = elmr_write(adap, VSC_REG(1, port, 0),
198                                     0xa590 | (mode << 2))) ||
199                     (r = elmr_write(adap, VSC_REG(1, port, 0xb),
200                                     0x91 | (clk << 1))) ||
201                     (r = elmr_write(adap, VSC_REG(1, port, 0xb),
202                                     0x90 | (clk << 1))) ||
203                     (r = elmr_write(adap, VSC_REG(1, port, 0),
204                                     0xa593 | (mode << 2))))
205                         return r;
206         }
207
208         r = (fc & PAUSE_RX) ? 0x60200 : 0x20200; //QUANTA = 32*1024*8/512
209         if (fc & PAUSE_TX)
210                 r |= (1 << 19);
211         return elmr_write(adap, VSC_REG(1, port, 1), r);
212 }
213
214 int t3_vsc7323_set_mtu(adapter_t *adap, unsigned int mtu, int port)
215 {
216         return elmr_write(adap, VSC_REG(1, port, 2), mtu);
217 }
218
219 int t3_vsc7323_set_addr(adapter_t *adap, u8 addr[6], int port)
220 {
221         int ret;
222
223         ret = elmr_write(adap, VSC_REG(1, port, 3),
224                          (addr[0] << 16) | (addr[1] << 8) | addr[2]);
225         if (!ret)
226                 ret = elmr_write(adap, VSC_REG(1, port, 4),
227                                  (addr[3] << 16) | (addr[4] << 8) | addr[5]);
228         return ret;
229 }
230
231 int t3_vsc7323_enable(adapter_t *adap, int port, int which)
232 {
233         int ret;
234         unsigned int v, orig;
235
236         ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
237         if (!ret) {
238                 orig = v;
239                 if (which & MAC_DIRECTION_TX)
240                         v |= 1;
241                 if (which & MAC_DIRECTION_RX)
242                         v |= 2;
243                 if (v != orig)
244                         ret = elmr_write(adap, VSC_REG(1, port, 0), v);
245         }
246         return ret;
247 }
248
249 int t3_vsc7323_disable(adapter_t *adap, int port, int which)
250 {
251         int ret;
252         unsigned int v, orig;
253
254         ret = t3_elmr_blk_read(adap, VSC_REG(1, port, 0), &v, 1);
255         if (!ret) {
256                 orig = v;
257                 if (which & MAC_DIRECTION_TX)
258                         v &= ~1;
259                 if (which & MAC_DIRECTION_RX)
260                         v &= ~2;
261                 if (v != orig)
262                         ret = elmr_write(adap, VSC_REG(1, port, 0), v);
263         }
264         return ret;
265 }
266
267 #define STATS0_START 1
268 #define STATS1_START 0x24
269 #define NSTATS0 (0x1d - STATS0_START + 1)
270 #define NSTATS1 (0x2a - STATS1_START + 1)
271
272 const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac)
273 {
274         int ret;
275         u64 rx_ucast, tx_ucast;
276         u32 stats0[NSTATS0], stats1[NSTATS1];
277
278         ret = t3_elmr_blk_read(mac->adapter,
279                                VSC_REG(4, mac->ext_port, STATS0_START),
280                                stats0, NSTATS0);
281         if (!ret)
282                 ret = t3_elmr_blk_read(mac->adapter,
283                                        VSC_REG(4, mac->ext_port, STATS1_START),
284                                        stats1, NSTATS1);
285         if (ret)
286                 goto out;
287
288         /*
289          * HW counts Rx/Tx unicast frames but we want all the frames.
290          */
291         rx_ucast = mac->stats.rx_frames - mac->stats.rx_mcast_frames -
292                    mac->stats.rx_bcast_frames;
293         rx_ucast += (u64)(stats0[6 - STATS0_START] - (u32)rx_ucast);
294         tx_ucast = mac->stats.tx_frames - mac->stats.tx_mcast_frames -
295                    mac->stats.tx_bcast_frames;
296         tx_ucast += (u64)(stats0[27 - STATS0_START] - (u32)tx_ucast);
297
298 #define RMON_UPDATE(mac, name, hw_stat) \
299         mac->stats.name += (u64)((hw_stat) - (u32)(mac->stats.name))
300
301         RMON_UPDATE(mac, rx_octets, stats0[4 - STATS0_START]);
302         RMON_UPDATE(mac, rx_frames, stats0[6 - STATS0_START]);
303         RMON_UPDATE(mac, rx_frames, stats0[7 - STATS0_START]);
304         RMON_UPDATE(mac, rx_frames, stats0[8 - STATS0_START]);
305         RMON_UPDATE(mac, rx_mcast_frames, stats0[7 - STATS0_START]);
306         RMON_UPDATE(mac, rx_bcast_frames, stats0[8 - STATS0_START]);
307         RMON_UPDATE(mac, rx_fcs_errs, stats0[9 - STATS0_START]);
308         RMON_UPDATE(mac, rx_pause, stats0[2 - STATS0_START]);
309         RMON_UPDATE(mac, rx_jabber, stats0[16 - STATS0_START]);
310         RMON_UPDATE(mac, rx_short, stats0[11 - STATS0_START]);
311         RMON_UPDATE(mac, rx_symbol_errs, stats0[1 - STATS0_START]);
312         RMON_UPDATE(mac, rx_too_long, stats0[15 - STATS0_START]);
313
314         RMON_UPDATE(mac, rx_frames_64,        stats0[17 - STATS0_START]);
315         RMON_UPDATE(mac, rx_frames_65_127,    stats0[18 - STATS0_START]);
316         RMON_UPDATE(mac, rx_frames_128_255,   stats0[19 - STATS0_START]);
317         RMON_UPDATE(mac, rx_frames_256_511,   stats0[20 - STATS0_START]);
318         RMON_UPDATE(mac, rx_frames_512_1023,  stats0[21 - STATS0_START]);
319         RMON_UPDATE(mac, rx_frames_1024_1518, stats0[22 - STATS0_START]);
320         RMON_UPDATE(mac, rx_frames_1519_max,  stats0[23 - STATS0_START]);
321
322         RMON_UPDATE(mac, tx_octets, stats0[26 - STATS0_START]);
323         RMON_UPDATE(mac, tx_frames, stats0[27 - STATS0_START]);
324         RMON_UPDATE(mac, tx_frames, stats0[28 - STATS0_START]);
325         RMON_UPDATE(mac, tx_frames, stats0[29 - STATS0_START]);
326         RMON_UPDATE(mac, tx_mcast_frames, stats0[28 - STATS0_START]);
327         RMON_UPDATE(mac, tx_bcast_frames, stats0[29 - STATS0_START]);
328         RMON_UPDATE(mac, tx_pause, stats0[25 - STATS0_START]);
329
330         RMON_UPDATE(mac, tx_underrun, 0);
331
332         RMON_UPDATE(mac, tx_frames_64,        stats1[36 - STATS1_START]);
333         RMON_UPDATE(mac, tx_frames_65_127,    stats1[37 - STATS1_START]);
334         RMON_UPDATE(mac, tx_frames_128_255,   stats1[38 - STATS1_START]);
335         RMON_UPDATE(mac, tx_frames_256_511,   stats1[39 - STATS1_START]);
336         RMON_UPDATE(mac, tx_frames_512_1023,  stats1[40 - STATS1_START]);
337         RMON_UPDATE(mac, tx_frames_1024_1518, stats1[41 - STATS1_START]);
338         RMON_UPDATE(mac, tx_frames_1519_max,  stats1[42 - STATS1_START]);
339
340 #undef RMON_UPDATE
341
342         mac->stats.rx_frames = rx_ucast + mac->stats.rx_mcast_frames +
343                                mac->stats.rx_bcast_frames;
344         mac->stats.tx_frames = tx_ucast + mac->stats.tx_mcast_frames +
345                                mac->stats.tx_bcast_frames;
346 out:    return &mac->stats;
347 }