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