1f931551bSRalph Campbell /*
2f931551bSRalph Campbell * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved.
3f931551bSRalph Campbell * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
4f931551bSRalph Campbell *
5f931551bSRalph Campbell * This software is available to you under a choice of one of two
6f931551bSRalph Campbell * licenses. You may choose to be licensed under the terms of the GNU
7f931551bSRalph Campbell * General Public License (GPL) Version 2, available from the file
8f931551bSRalph Campbell * COPYING in the main directory of this source tree, or the
9f931551bSRalph Campbell * OpenIB.org BSD license below:
10f931551bSRalph Campbell *
11f931551bSRalph Campbell * Redistribution and use in source and binary forms, with or
12f931551bSRalph Campbell * without modification, are permitted provided that the following
13f931551bSRalph Campbell * conditions are met:
14f931551bSRalph Campbell *
15f931551bSRalph Campbell * - Redistributions of source code must retain the above
16f931551bSRalph Campbell * copyright notice, this list of conditions and the following
17f931551bSRalph Campbell * disclaimer.
18f931551bSRalph Campbell *
19f931551bSRalph Campbell * - Redistributions in binary form must reproduce the above
20f931551bSRalph Campbell * copyright notice, this list of conditions and the following
21f931551bSRalph Campbell * disclaimer in the documentation and/or other materials
22f931551bSRalph Campbell * provided with the distribution.
23f931551bSRalph Campbell *
24f931551bSRalph Campbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25f931551bSRalph Campbell * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26f931551bSRalph Campbell * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27f931551bSRalph Campbell * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28f931551bSRalph Campbell * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29f931551bSRalph Campbell * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30f931551bSRalph Campbell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31f931551bSRalph Campbell * SOFTWARE.
32f931551bSRalph Campbell */
33f931551bSRalph Campbell
34f931551bSRalph Campbell #include <linux/delay.h>
35f931551bSRalph Campbell #include <linux/pci.h>
36f931551bSRalph Campbell #include <linux/vmalloc.h>
37f931551bSRalph Campbell
38f931551bSRalph Campbell #include "qib.h"
39f931551bSRalph Campbell #include "qib_qsfp.h"
40f931551bSRalph Campbell
41f931551bSRalph Campbell /*
42f931551bSRalph Campbell * QSFP support for ib_qib driver, using "Two Wire Serial Interface" driver
43f931551bSRalph Campbell * in qib_twsi.c
44f931551bSRalph Campbell */
45f931551bSRalph Campbell #define QSFP_MAX_RETRY 4
46f931551bSRalph Campbell
qsfp_read(struct qib_pportdata * ppd,int addr,void * bp,int len)47f931551bSRalph Campbell static int qsfp_read(struct qib_pportdata *ppd, int addr, void *bp, int len)
48f931551bSRalph Campbell {
49f931551bSRalph Campbell struct qib_devdata *dd = ppd->dd;
50f931551bSRalph Campbell u32 out, mask;
51f931551bSRalph Campbell int ret, cnt, pass = 0;
52f931551bSRalph Campbell int stuck = 0;
53f931551bSRalph Campbell u8 *buff = bp;
54f931551bSRalph Campbell
55f931551bSRalph Campbell ret = mutex_lock_interruptible(&dd->eep_lock);
56f931551bSRalph Campbell if (ret)
57f931551bSRalph Campbell goto no_unlock;
58f931551bSRalph Campbell
59f931551bSRalph Campbell if (dd->twsi_eeprom_dev == QIB_TWSI_NO_DEV) {
60f931551bSRalph Campbell ret = -ENXIO;
61f931551bSRalph Campbell goto bail;
62f931551bSRalph Campbell }
63f931551bSRalph Campbell
64f931551bSRalph Campbell /*
65f931551bSRalph Campbell * We presume, if we are called at all, that this board has
66f931551bSRalph Campbell * QSFP. This is on the same i2c chain as the legacy parts,
67f931551bSRalph Campbell * but only responds if the module is selected via GPIO pins.
68f931551bSRalph Campbell * Further, there are very long setup and hold requirements
69f931551bSRalph Campbell * on MODSEL.
70f931551bSRalph Campbell */
71f931551bSRalph Campbell mask = QSFP_GPIO_MOD_SEL_N | QSFP_GPIO_MOD_RST_N | QSFP_GPIO_LP_MODE;
72f931551bSRalph Campbell out = QSFP_GPIO_MOD_RST_N | QSFP_GPIO_LP_MODE;
73f931551bSRalph Campbell if (ppd->hw_pidx) {
74f931551bSRalph Campbell mask <<= QSFP_GPIO_PORT2_SHIFT;
75f931551bSRalph Campbell out <<= QSFP_GPIO_PORT2_SHIFT;
76f931551bSRalph Campbell }
77f931551bSRalph Campbell
78f931551bSRalph Campbell dd->f_gpio_mod(dd, out, mask, mask);
79f931551bSRalph Campbell
80f931551bSRalph Campbell /*
81f931551bSRalph Campbell * Module could take up to 2 Msec to respond to MOD_SEL, and there
82f931551bSRalph Campbell * is no way to tell if it is ready, so we must wait.
83f931551bSRalph Campbell */
84a46a2802SMike Marciniszyn msleep(20);
85f931551bSRalph Campbell
86f931551bSRalph Campbell /* Make sure TWSI bus is in sane state. */
87f931551bSRalph Campbell ret = qib_twsi_reset(dd);
88f931551bSRalph Campbell if (ret) {
89f931551bSRalph Campbell qib_dev_porterr(dd, ppd->port,
90f931551bSRalph Campbell "QSFP interface Reset for read failed\n");
91f931551bSRalph Campbell ret = -EIO;
92f931551bSRalph Campbell stuck = 1;
93f931551bSRalph Campbell goto deselect;
94f931551bSRalph Campbell }
95f931551bSRalph Campbell
96f931551bSRalph Campbell /* All QSFP modules are at A0 */
97f931551bSRalph Campbell
98f931551bSRalph Campbell cnt = 0;
99f931551bSRalph Campbell while (cnt < len) {
100f931551bSRalph Campbell unsigned in_page;
101f931551bSRalph Campbell int wlen = len - cnt;
102da12c1f6SMike Marciniszyn
103f931551bSRalph Campbell in_page = addr % QSFP_PAGESIZE;
104f931551bSRalph Campbell if ((in_page + wlen) > QSFP_PAGESIZE)
105f931551bSRalph Campbell wlen = QSFP_PAGESIZE - in_page;
106f931551bSRalph Campbell ret = qib_twsi_blk_rd(dd, QSFP_DEV, addr, buff + cnt, wlen);
107f931551bSRalph Campbell /* Some QSFP's fail first try. Retry as experiment */
108f931551bSRalph Campbell if (ret && cnt == 0 && ++pass < QSFP_MAX_RETRY)
109f931551bSRalph Campbell continue;
110f931551bSRalph Campbell if (ret) {
111f931551bSRalph Campbell /* qib_twsi_blk_rd() 1 for error, else 0 */
112f931551bSRalph Campbell ret = -EIO;
113f931551bSRalph Campbell goto deselect;
114f931551bSRalph Campbell }
115f931551bSRalph Campbell addr += wlen;
116f931551bSRalph Campbell cnt += wlen;
117f931551bSRalph Campbell }
118f931551bSRalph Campbell ret = cnt;
119f931551bSRalph Campbell
120f931551bSRalph Campbell deselect:
121f931551bSRalph Campbell /*
122f931551bSRalph Campbell * Module could take up to 10 uSec after transfer before
123f931551bSRalph Campbell * ready to respond to MOD_SEL negation, and there is no way
124f931551bSRalph Campbell * to tell if it is ready, so we must wait.
125f931551bSRalph Campbell */
126f931551bSRalph Campbell udelay(10);
127f931551bSRalph Campbell /* set QSFP MODSEL, RST. LP all high */
128f931551bSRalph Campbell dd->f_gpio_mod(dd, mask, mask, mask);
129f931551bSRalph Campbell
130f931551bSRalph Campbell /*
131f931551bSRalph Campbell * Module could take up to 2 Msec to respond to MOD_SEL
132f931551bSRalph Campbell * going away, and there is no way to tell if it is ready.
133f931551bSRalph Campbell * so we must wait.
134f931551bSRalph Campbell */
135f931551bSRalph Campbell if (stuck)
136f931551bSRalph Campbell qib_dev_err(dd, "QSFP interface bus stuck non-idle\n");
137f931551bSRalph Campbell
138f931551bSRalph Campbell if (pass >= QSFP_MAX_RETRY && ret)
139f931551bSRalph Campbell qib_dev_porterr(dd, ppd->port, "QSFP failed even retrying\n");
140f931551bSRalph Campbell else if (pass)
141f931551bSRalph Campbell qib_dev_porterr(dd, ppd->port, "QSFP retries: %d\n", pass);
142f931551bSRalph Campbell
143a46a2802SMike Marciniszyn msleep(20);
144f931551bSRalph Campbell
145f931551bSRalph Campbell bail:
146f931551bSRalph Campbell mutex_unlock(&dd->eep_lock);
147f931551bSRalph Campbell
148f931551bSRalph Campbell no_unlock:
149f931551bSRalph Campbell return ret;
150f931551bSRalph Campbell }
151f931551bSRalph Campbell
152f931551bSRalph Campbell /*
153f931551bSRalph Campbell * qsfp_write
154f931551bSRalph Campbell * We do not ordinarily write the QSFP, but this is needed to select
155f931551bSRalph Campbell * the page on non-flat QSFPs, and possibly later unusual cases
156f931551bSRalph Campbell */
qib_qsfp_write(struct qib_pportdata * ppd,int addr,void * bp,int len)157f931551bSRalph Campbell static int qib_qsfp_write(struct qib_pportdata *ppd, int addr, void *bp,
158f931551bSRalph Campbell int len)
159f931551bSRalph Campbell {
160f931551bSRalph Campbell struct qib_devdata *dd = ppd->dd;
161f931551bSRalph Campbell u32 out, mask;
162f931551bSRalph Campbell int ret, cnt;
163f931551bSRalph Campbell u8 *buff = bp;
164f931551bSRalph Campbell
165f931551bSRalph Campbell ret = mutex_lock_interruptible(&dd->eep_lock);
166f931551bSRalph Campbell if (ret)
167f931551bSRalph Campbell goto no_unlock;
168f931551bSRalph Campbell
169f931551bSRalph Campbell if (dd->twsi_eeprom_dev == QIB_TWSI_NO_DEV) {
170f931551bSRalph Campbell ret = -ENXIO;
171f931551bSRalph Campbell goto bail;
172f931551bSRalph Campbell }
173f931551bSRalph Campbell
174f931551bSRalph Campbell /*
175f931551bSRalph Campbell * We presume, if we are called at all, that this board has
176f931551bSRalph Campbell * QSFP. This is on the same i2c chain as the legacy parts,
177f931551bSRalph Campbell * but only responds if the module is selected via GPIO pins.
178f931551bSRalph Campbell * Further, there are very long setup and hold requirements
179f931551bSRalph Campbell * on MODSEL.
180f931551bSRalph Campbell */
181f931551bSRalph Campbell mask = QSFP_GPIO_MOD_SEL_N | QSFP_GPIO_MOD_RST_N | QSFP_GPIO_LP_MODE;
182f931551bSRalph Campbell out = QSFP_GPIO_MOD_RST_N | QSFP_GPIO_LP_MODE;
183f931551bSRalph Campbell if (ppd->hw_pidx) {
184f931551bSRalph Campbell mask <<= QSFP_GPIO_PORT2_SHIFT;
185f931551bSRalph Campbell out <<= QSFP_GPIO_PORT2_SHIFT;
186f931551bSRalph Campbell }
187f931551bSRalph Campbell dd->f_gpio_mod(dd, out, mask, mask);
188f931551bSRalph Campbell
189f931551bSRalph Campbell /*
190f931551bSRalph Campbell * Module could take up to 2 Msec to respond to MOD_SEL,
191f931551bSRalph Campbell * and there is no way to tell if it is ready, so we must wait.
192f931551bSRalph Campbell */
193a46a2802SMike Marciniszyn msleep(20);
194f931551bSRalph Campbell
195f931551bSRalph Campbell /* Make sure TWSI bus is in sane state. */
196f931551bSRalph Campbell ret = qib_twsi_reset(dd);
197f931551bSRalph Campbell if (ret) {
198f931551bSRalph Campbell qib_dev_porterr(dd, ppd->port,
199f931551bSRalph Campbell "QSFP interface Reset for write failed\n");
200f931551bSRalph Campbell ret = -EIO;
201f931551bSRalph Campbell goto deselect;
202f931551bSRalph Campbell }
203f931551bSRalph Campbell
204f931551bSRalph Campbell /* All QSFP modules are at A0 */
205f931551bSRalph Campbell
206f931551bSRalph Campbell cnt = 0;
207f931551bSRalph Campbell while (cnt < len) {
208f931551bSRalph Campbell unsigned in_page;
209f931551bSRalph Campbell int wlen = len - cnt;
210da12c1f6SMike Marciniszyn
211f931551bSRalph Campbell in_page = addr % QSFP_PAGESIZE;
212f931551bSRalph Campbell if ((in_page + wlen) > QSFP_PAGESIZE)
213f931551bSRalph Campbell wlen = QSFP_PAGESIZE - in_page;
214f931551bSRalph Campbell ret = qib_twsi_blk_wr(dd, QSFP_DEV, addr, buff + cnt, wlen);
215f931551bSRalph Campbell if (ret) {
216f931551bSRalph Campbell /* qib_twsi_blk_wr() 1 for error, else 0 */
217f931551bSRalph Campbell ret = -EIO;
218f931551bSRalph Campbell goto deselect;
219f931551bSRalph Campbell }
220f931551bSRalph Campbell addr += wlen;
221f931551bSRalph Campbell cnt += wlen;
222f931551bSRalph Campbell }
223f931551bSRalph Campbell ret = cnt;
224f931551bSRalph Campbell
225f931551bSRalph Campbell deselect:
226f931551bSRalph Campbell /*
227f931551bSRalph Campbell * Module could take up to 10 uSec after transfer before
228f931551bSRalph Campbell * ready to respond to MOD_SEL negation, and there is no way
229f931551bSRalph Campbell * to tell if it is ready, so we must wait.
230f931551bSRalph Campbell */
231f931551bSRalph Campbell udelay(10);
232f931551bSRalph Campbell /* set QSFP MODSEL, RST, LP high */
233f931551bSRalph Campbell dd->f_gpio_mod(dd, mask, mask, mask);
234f931551bSRalph Campbell /*
235f931551bSRalph Campbell * Module could take up to 2 Msec to respond to MOD_SEL
236f931551bSRalph Campbell * going away, and there is no way to tell if it is ready.
237f931551bSRalph Campbell * so we must wait.
238f931551bSRalph Campbell */
239a46a2802SMike Marciniszyn msleep(20);
240f931551bSRalph Campbell
241f931551bSRalph Campbell bail:
242f931551bSRalph Campbell mutex_unlock(&dd->eep_lock);
243f931551bSRalph Campbell
244f931551bSRalph Campbell no_unlock:
245f931551bSRalph Campbell return ret;
246f931551bSRalph Campbell }
247f931551bSRalph Campbell
248f931551bSRalph Campbell /*
249f931551bSRalph Campbell * For validation, we want to check the checksums, even of the
250f931551bSRalph Campbell * fields we do not otherwise use. This function reads the bytes from
251f931551bSRalph Campbell * <first> to <next-1> and returns the 8lsbs of the sum, or <0 for errors
252f931551bSRalph Campbell */
qsfp_cks(struct qib_pportdata * ppd,int first,int next)253f931551bSRalph Campbell static int qsfp_cks(struct qib_pportdata *ppd, int first, int next)
254f931551bSRalph Campbell {
255f931551bSRalph Campbell int ret;
256f931551bSRalph Campbell u16 cks;
257f931551bSRalph Campbell u8 bval;
258f931551bSRalph Campbell
259f931551bSRalph Campbell cks = 0;
260f931551bSRalph Campbell while (first < next) {
261f931551bSRalph Campbell ret = qsfp_read(ppd, first, &bval, 1);
262f931551bSRalph Campbell if (ret < 0)
263f931551bSRalph Campbell goto bail;
264f931551bSRalph Campbell cks += bval;
265f931551bSRalph Campbell ++first;
266f931551bSRalph Campbell }
267f931551bSRalph Campbell ret = cks & 0xFF;
268f931551bSRalph Campbell bail:
269f931551bSRalph Campbell return ret;
270f931551bSRalph Campbell
271f931551bSRalph Campbell }
272f931551bSRalph Campbell
qib_refresh_qsfp_cache(struct qib_pportdata * ppd,struct qib_qsfp_cache * cp)273f931551bSRalph Campbell int qib_refresh_qsfp_cache(struct qib_pportdata *ppd, struct qib_qsfp_cache *cp)
274f931551bSRalph Campbell {
275f931551bSRalph Campbell int ret;
276f931551bSRalph Campbell int idx;
277f931551bSRalph Campbell u16 cks;
278f931551bSRalph Campbell u8 peek[4];
279f931551bSRalph Campbell
280f931551bSRalph Campbell /* ensure sane contents on invalid reads, for cable swaps */
281f931551bSRalph Campbell memset(cp, 0, sizeof(*cp));
282f931551bSRalph Campbell
283dde05cbdSMitko Haralanov if (!qib_qsfp_mod_present(ppd)) {
284f931551bSRalph Campbell ret = -ENODEV;
285f931551bSRalph Campbell goto bail;
286f931551bSRalph Campbell }
287f931551bSRalph Campbell
288f931551bSRalph Campbell ret = qsfp_read(ppd, 0, peek, 3);
289f931551bSRalph Campbell if (ret < 0)
290f931551bSRalph Campbell goto bail;
291f931551bSRalph Campbell if ((peek[0] & 0xFE) != 0x0C)
292f931551bSRalph Campbell qib_dev_porterr(ppd->dd, ppd->port,
293f931551bSRalph Campbell "QSFP byte0 is 0x%02X, S/B 0x0C/D\n", peek[0]);
294f931551bSRalph Campbell
295*57ab2512SEaswar Hariharan if ((peek[2] & 4) == 0) {
296f931551bSRalph Campbell /*
297f931551bSRalph Campbell * If cable is paged, rather than "flat memory", we need to
298f931551bSRalph Campbell * set the page to zero, Even if it already appears to be zero.
299f931551bSRalph Campbell */
300f931551bSRalph Campbell u8 poke = 0;
301da12c1f6SMike Marciniszyn
302f931551bSRalph Campbell ret = qib_qsfp_write(ppd, 127, &poke, 1);
303f931551bSRalph Campbell udelay(50);
304f931551bSRalph Campbell if (ret != 1) {
305f931551bSRalph Campbell qib_dev_porterr(ppd->dd, ppd->port,
306f931551bSRalph Campbell "Failed QSFP Page set\n");
307f931551bSRalph Campbell goto bail;
308f931551bSRalph Campbell }
309f931551bSRalph Campbell }
310f931551bSRalph Campbell
311f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_MOD_ID_OFFS, &cp->id, 1);
312f931551bSRalph Campbell if (ret < 0)
313f931551bSRalph Campbell goto bail;
314f931551bSRalph Campbell if ((cp->id & 0xFE) != 0x0C)
315f931551bSRalph Campbell qib_dev_porterr(ppd->dd, ppd->port,
316f931551bSRalph Campbell "QSFP ID byte is 0x%02X, S/B 0x0C/D\n", cp->id);
317f931551bSRalph Campbell cks = cp->id;
318f931551bSRalph Campbell
319f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_MOD_PWR_OFFS, &cp->pwr, 1);
320f931551bSRalph Campbell if (ret < 0)
321f931551bSRalph Campbell goto bail;
322f931551bSRalph Campbell cks += cp->pwr;
323f931551bSRalph Campbell
324f931551bSRalph Campbell ret = qsfp_cks(ppd, QSFP_MOD_PWR_OFFS + 1, QSFP_MOD_LEN_OFFS);
325f931551bSRalph Campbell if (ret < 0)
326f931551bSRalph Campbell goto bail;
327f931551bSRalph Campbell cks += ret;
328f931551bSRalph Campbell
329f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_MOD_LEN_OFFS, &cp->len, 1);
330f931551bSRalph Campbell if (ret < 0)
331f931551bSRalph Campbell goto bail;
332f931551bSRalph Campbell cks += cp->len;
333f931551bSRalph Campbell
334f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_MOD_TECH_OFFS, &cp->tech, 1);
335f931551bSRalph Campbell if (ret < 0)
336f931551bSRalph Campbell goto bail;
337f931551bSRalph Campbell cks += cp->tech;
338f931551bSRalph Campbell
339f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_VEND_OFFS, &cp->vendor, QSFP_VEND_LEN);
340f931551bSRalph Campbell if (ret < 0)
341f931551bSRalph Campbell goto bail;
342f931551bSRalph Campbell for (idx = 0; idx < QSFP_VEND_LEN; ++idx)
343f931551bSRalph Campbell cks += cp->vendor[idx];
344f931551bSRalph Campbell
345f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_IBXCV_OFFS, &cp->xt_xcv, 1);
346f931551bSRalph Campbell if (ret < 0)
347f931551bSRalph Campbell goto bail;
348f931551bSRalph Campbell cks += cp->xt_xcv;
349f931551bSRalph Campbell
350f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_VOUI_OFFS, &cp->oui, QSFP_VOUI_LEN);
351f931551bSRalph Campbell if (ret < 0)
352f931551bSRalph Campbell goto bail;
353f931551bSRalph Campbell for (idx = 0; idx < QSFP_VOUI_LEN; ++idx)
354f931551bSRalph Campbell cks += cp->oui[idx];
355f931551bSRalph Campbell
356f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_PN_OFFS, &cp->partnum, QSFP_PN_LEN);
357f931551bSRalph Campbell if (ret < 0)
358f931551bSRalph Campbell goto bail;
359f931551bSRalph Campbell for (idx = 0; idx < QSFP_PN_LEN; ++idx)
360f931551bSRalph Campbell cks += cp->partnum[idx];
361f931551bSRalph Campbell
362f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_REV_OFFS, &cp->rev, QSFP_REV_LEN);
363f931551bSRalph Campbell if (ret < 0)
364f931551bSRalph Campbell goto bail;
365f931551bSRalph Campbell for (idx = 0; idx < QSFP_REV_LEN; ++idx)
366f931551bSRalph Campbell cks += cp->rev[idx];
367f931551bSRalph Campbell
368f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_ATTEN_OFFS, &cp->atten, QSFP_ATTEN_LEN);
369f931551bSRalph Campbell if (ret < 0)
370f931551bSRalph Campbell goto bail;
371f931551bSRalph Campbell for (idx = 0; idx < QSFP_ATTEN_LEN; ++idx)
372f931551bSRalph Campbell cks += cp->atten[idx];
373f931551bSRalph Campbell
374f931551bSRalph Campbell ret = qsfp_cks(ppd, QSFP_ATTEN_OFFS + QSFP_ATTEN_LEN, QSFP_CC_OFFS);
375f931551bSRalph Campbell if (ret < 0)
376f931551bSRalph Campbell goto bail;
377f931551bSRalph Campbell cks += ret;
378f931551bSRalph Campbell
379f931551bSRalph Campbell cks &= 0xFF;
380f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_CC_OFFS, &cp->cks1, 1);
381f931551bSRalph Campbell if (ret < 0)
382f931551bSRalph Campbell goto bail;
383f931551bSRalph Campbell if (cks != cp->cks1)
384f931551bSRalph Campbell qib_dev_porterr(ppd->dd, ppd->port,
385f931551bSRalph Campbell "QSFP cks1 is %02X, computed %02X\n", cp->cks1,
386f931551bSRalph Campbell cks);
387f931551bSRalph Campbell
388f931551bSRalph Campbell /* Second checksum covers 192 to (serial, date, lot) */
389f931551bSRalph Campbell ret = qsfp_cks(ppd, QSFP_CC_OFFS + 1, QSFP_SN_OFFS);
390f931551bSRalph Campbell if (ret < 0)
391f931551bSRalph Campbell goto bail;
392f931551bSRalph Campbell cks = ret;
393f931551bSRalph Campbell
394f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_SN_OFFS, &cp->serial, QSFP_SN_LEN);
395f931551bSRalph Campbell if (ret < 0)
396f931551bSRalph Campbell goto bail;
397f931551bSRalph Campbell for (idx = 0; idx < QSFP_SN_LEN; ++idx)
398f931551bSRalph Campbell cks += cp->serial[idx];
399f931551bSRalph Campbell
400f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_DATE_OFFS, &cp->date, QSFP_DATE_LEN);
401f931551bSRalph Campbell if (ret < 0)
402f931551bSRalph Campbell goto bail;
403f931551bSRalph Campbell for (idx = 0; idx < QSFP_DATE_LEN; ++idx)
404f931551bSRalph Campbell cks += cp->date[idx];
405f931551bSRalph Campbell
406f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_LOT_OFFS, &cp->lot, QSFP_LOT_LEN);
407f931551bSRalph Campbell if (ret < 0)
408f931551bSRalph Campbell goto bail;
409f931551bSRalph Campbell for (idx = 0; idx < QSFP_LOT_LEN; ++idx)
410f931551bSRalph Campbell cks += cp->lot[idx];
411f931551bSRalph Campbell
412f931551bSRalph Campbell ret = qsfp_cks(ppd, QSFP_LOT_OFFS + QSFP_LOT_LEN, QSFP_CC_EXT_OFFS);
413f931551bSRalph Campbell if (ret < 0)
414f931551bSRalph Campbell goto bail;
415f931551bSRalph Campbell cks += ret;
416f931551bSRalph Campbell
417f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_CC_EXT_OFFS, &cp->cks2, 1);
418f931551bSRalph Campbell if (ret < 0)
419f931551bSRalph Campbell goto bail;
420f931551bSRalph Campbell cks &= 0xFF;
421f931551bSRalph Campbell if (cks != cp->cks2)
422f931551bSRalph Campbell qib_dev_porterr(ppd->dd, ppd->port,
423f931551bSRalph Campbell "QSFP cks2 is %02X, computed %02X\n", cp->cks2,
424f931551bSRalph Campbell cks);
425f931551bSRalph Campbell return 0;
426f931551bSRalph Campbell
427f931551bSRalph Campbell bail:
428f931551bSRalph Campbell cp->id = 0;
429f931551bSRalph Campbell return ret;
430f931551bSRalph Campbell }
431f931551bSRalph Campbell
432f931551bSRalph Campbell const char * const qib_qsfp_devtech[16] = {
433f931551bSRalph Campbell "850nm VCSEL", "1310nm VCSEL", "1550nm VCSEL", "1310nm FP",
434f931551bSRalph Campbell "1310nm DFB", "1550nm DFB", "1310nm EML", "1550nm EML",
435f931551bSRalph Campbell "Cu Misc", "1490nm DFB", "Cu NoEq", "Cu Eq",
436f931551bSRalph Campbell "Undef", "Cu Active BothEq", "Cu FarEq", "Cu NearEq"
437f931551bSRalph Campbell };
438f931551bSRalph Campbell
439f931551bSRalph Campbell #define QSFP_DUMP_CHUNK 16 /* Holds longest string */
440f931551bSRalph Campbell #define QSFP_DEFAULT_HDR_CNT 224
441f931551bSRalph Campbell
442f931551bSRalph Campbell static const char *pwr_codes = "1.5W2.0W2.5W3.5W";
443f931551bSRalph Campbell
qib_qsfp_mod_present(struct qib_pportdata * ppd)444dde05cbdSMitko Haralanov int qib_qsfp_mod_present(struct qib_pportdata *ppd)
445dde05cbdSMitko Haralanov {
446dde05cbdSMitko Haralanov u32 mask;
447dde05cbdSMitko Haralanov int ret;
448dde05cbdSMitko Haralanov
449dde05cbdSMitko Haralanov mask = QSFP_GPIO_MOD_PRS_N <<
450dde05cbdSMitko Haralanov (ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT);
451dde05cbdSMitko Haralanov ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0);
452dde05cbdSMitko Haralanov
453dde05cbdSMitko Haralanov return !((ret & mask) >>
454dde05cbdSMitko Haralanov ((ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT) + 3));
455dde05cbdSMitko Haralanov }
456dde05cbdSMitko Haralanov
457f931551bSRalph Campbell /*
458f931551bSRalph Campbell * Initialize structures that control access to QSFP. Called once per port
459f931551bSRalph Campbell * on cards that support QSFP.
460f931551bSRalph Campbell */
qib_qsfp_init(struct qib_qsfp_data * qd,void (* fevent)(struct work_struct *))461f931551bSRalph Campbell void qib_qsfp_init(struct qib_qsfp_data *qd,
462f931551bSRalph Campbell void (*fevent)(struct work_struct *))
463f931551bSRalph Campbell {
464f931551bSRalph Campbell u32 mask, highs;
465f931551bSRalph Campbell
466f931551bSRalph Campbell struct qib_devdata *dd = qd->ppd->dd;
467f931551bSRalph Campbell
468f931551bSRalph Campbell /* Initialize work struct for later QSFP events */
469f931551bSRalph Campbell INIT_WORK(&qd->work, fevent);
470f931551bSRalph Campbell
471f931551bSRalph Campbell /*
472f931551bSRalph Campbell * Later, we may want more validation. For now, just set up pins and
473f931551bSRalph Campbell * blip reset. If module is present, call qib_refresh_qsfp_cache(),
474f931551bSRalph Campbell * to do further init.
475f931551bSRalph Campbell */
476f931551bSRalph Campbell mask = QSFP_GPIO_MOD_SEL_N | QSFP_GPIO_MOD_RST_N | QSFP_GPIO_LP_MODE;
477f931551bSRalph Campbell highs = mask - QSFP_GPIO_MOD_RST_N;
478f931551bSRalph Campbell if (qd->ppd->hw_pidx) {
479f931551bSRalph Campbell mask <<= QSFP_GPIO_PORT2_SHIFT;
480f931551bSRalph Campbell highs <<= QSFP_GPIO_PORT2_SHIFT;
481f931551bSRalph Campbell }
482f931551bSRalph Campbell dd->f_gpio_mod(dd, highs, mask, mask);
483f931551bSRalph Campbell udelay(20); /* Generous RST dwell */
484f931551bSRalph Campbell
485f931551bSRalph Campbell dd->f_gpio_mod(dd, mask, mask, mask);
486f931551bSRalph Campbell }
487f931551bSRalph Campbell
qib_qsfp_dump(struct qib_pportdata * ppd,char * buf,int len)488f931551bSRalph Campbell int qib_qsfp_dump(struct qib_pportdata *ppd, char *buf, int len)
489f931551bSRalph Campbell {
490f931551bSRalph Campbell struct qib_qsfp_cache cd;
491f931551bSRalph Campbell u8 bin_buff[QSFP_DUMP_CHUNK];
492f931551bSRalph Campbell char lenstr[6];
493f931551bSRalph Campbell int sofar, ret;
494f931551bSRalph Campbell int bidx = 0;
495f931551bSRalph Campbell
496f931551bSRalph Campbell sofar = 0;
497f931551bSRalph Campbell ret = qib_refresh_qsfp_cache(ppd, &cd);
498f931551bSRalph Campbell if (ret < 0)
499f931551bSRalph Campbell goto bail;
500f931551bSRalph Campbell
501f931551bSRalph Campbell lenstr[0] = ' ';
502f931551bSRalph Campbell lenstr[1] = '\0';
503f931551bSRalph Campbell if (QSFP_IS_CU(cd.tech))
504f931551bSRalph Campbell sprintf(lenstr, "%dM ", cd.len);
505f931551bSRalph Campbell
506f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "PWR:%.3sW\n", pwr_codes +
507f931551bSRalph Campbell (QSFP_PWR(cd.pwr) * 4));
508f931551bSRalph Campbell
509f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "TECH:%s%s\n", lenstr,
510f931551bSRalph Campbell qib_qsfp_devtech[cd.tech >> 4]);
511f931551bSRalph Campbell
512f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Vendor:%.*s\n",
513f931551bSRalph Campbell QSFP_VEND_LEN, cd.vendor);
514f931551bSRalph Campbell
515f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "OUI:%06X\n",
516f931551bSRalph Campbell QSFP_OUI(cd.oui));
517f931551bSRalph Campbell
518f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Part#:%.*s\n",
519f931551bSRalph Campbell QSFP_PN_LEN, cd.partnum);
520f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Rev:%.*s\n",
521f931551bSRalph Campbell QSFP_REV_LEN, cd.rev);
522f931551bSRalph Campbell if (QSFP_IS_CU(cd.tech))
523f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Atten:%d, %d\n",
524f931551bSRalph Campbell QSFP_ATTEN_SDR(cd.atten),
525f931551bSRalph Campbell QSFP_ATTEN_DDR(cd.atten));
526f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Serial:%.*s\n",
527f931551bSRalph Campbell QSFP_SN_LEN, cd.serial);
528f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Date:%.*s\n",
529f931551bSRalph Campbell QSFP_DATE_LEN, cd.date);
530f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Lot:%.*s\n",
531*57ab2512SEaswar Hariharan QSFP_LOT_LEN, cd.lot);
532f931551bSRalph Campbell
533f931551bSRalph Campbell while (bidx < QSFP_DEFAULT_HDR_CNT) {
534f931551bSRalph Campbell int iidx;
535da12c1f6SMike Marciniszyn
536f931551bSRalph Campbell ret = qsfp_read(ppd, bidx, bin_buff, QSFP_DUMP_CHUNK);
537f931551bSRalph Campbell if (ret < 0)
538f931551bSRalph Campbell goto bail;
539f931551bSRalph Campbell for (iidx = 0; iidx < ret; ++iidx) {
540f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len-sofar, " %02X",
541f931551bSRalph Campbell bin_buff[iidx]);
542f931551bSRalph Campbell }
543f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "\n");
544f931551bSRalph Campbell bidx += QSFP_DUMP_CHUNK;
545f931551bSRalph Campbell }
546f931551bSRalph Campbell ret = sofar;
547f931551bSRalph Campbell bail:
548f931551bSRalph Campbell return ret;
549f931551bSRalph Campbell }
550