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 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 */ 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 */ 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 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 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 */ 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 488f931551bSRalph Campbell void qib_qsfp_deinit(struct qib_qsfp_data *qd) 489f931551bSRalph Campbell { 490f931551bSRalph Campbell /* 491f0626710STejun Heo * There is nothing to do here for now. our work is scheduled 492f0626710STejun Heo * with queue_work(), and flush_workqueue() from remove_one 493f0626710STejun Heo * will block until all work setup with queue_work() 494f931551bSRalph Campbell * completes. 495f931551bSRalph Campbell */ 496f931551bSRalph Campbell } 497f931551bSRalph Campbell 498f931551bSRalph Campbell int qib_qsfp_dump(struct qib_pportdata *ppd, char *buf, int len) 499f931551bSRalph Campbell { 500f931551bSRalph Campbell struct qib_qsfp_cache cd; 501f931551bSRalph Campbell u8 bin_buff[QSFP_DUMP_CHUNK]; 502f931551bSRalph Campbell char lenstr[6]; 503f931551bSRalph Campbell int sofar, ret; 504f931551bSRalph Campbell int bidx = 0; 505f931551bSRalph Campbell 506f931551bSRalph Campbell sofar = 0; 507f931551bSRalph Campbell ret = qib_refresh_qsfp_cache(ppd, &cd); 508f931551bSRalph Campbell if (ret < 0) 509f931551bSRalph Campbell goto bail; 510f931551bSRalph Campbell 511f931551bSRalph Campbell lenstr[0] = ' '; 512f931551bSRalph Campbell lenstr[1] = '\0'; 513f931551bSRalph Campbell if (QSFP_IS_CU(cd.tech)) 514f931551bSRalph Campbell sprintf(lenstr, "%dM ", cd.len); 515f931551bSRalph Campbell 516f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "PWR:%.3sW\n", pwr_codes + 517f931551bSRalph Campbell (QSFP_PWR(cd.pwr) * 4)); 518f931551bSRalph Campbell 519f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "TECH:%s%s\n", lenstr, 520f931551bSRalph Campbell qib_qsfp_devtech[cd.tech >> 4]); 521f931551bSRalph Campbell 522f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Vendor:%.*s\n", 523f931551bSRalph Campbell QSFP_VEND_LEN, cd.vendor); 524f931551bSRalph Campbell 525f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "OUI:%06X\n", 526f931551bSRalph Campbell QSFP_OUI(cd.oui)); 527f931551bSRalph Campbell 528f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Part#:%.*s\n", 529f931551bSRalph Campbell QSFP_PN_LEN, cd.partnum); 530f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Rev:%.*s\n", 531f931551bSRalph Campbell QSFP_REV_LEN, cd.rev); 532f931551bSRalph Campbell if (QSFP_IS_CU(cd.tech)) 533f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Atten:%d, %d\n", 534f931551bSRalph Campbell QSFP_ATTEN_SDR(cd.atten), 535f931551bSRalph Campbell QSFP_ATTEN_DDR(cd.atten)); 536f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Serial:%.*s\n", 537f931551bSRalph Campbell QSFP_SN_LEN, cd.serial); 538f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Date:%.*s\n", 539f931551bSRalph Campbell QSFP_DATE_LEN, cd.date); 540f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Lot:%.*s\n", 541*57ab2512SEaswar Hariharan QSFP_LOT_LEN, cd.lot); 542f931551bSRalph Campbell 543f931551bSRalph Campbell while (bidx < QSFP_DEFAULT_HDR_CNT) { 544f931551bSRalph Campbell int iidx; 545da12c1f6SMike Marciniszyn 546f931551bSRalph Campbell ret = qsfp_read(ppd, bidx, bin_buff, QSFP_DUMP_CHUNK); 547f931551bSRalph Campbell if (ret < 0) 548f931551bSRalph Campbell goto bail; 549f931551bSRalph Campbell for (iidx = 0; iidx < ret; ++iidx) { 550f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len-sofar, " %02X", 551f931551bSRalph Campbell bin_buff[iidx]); 552f931551bSRalph Campbell } 553f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "\n"); 554f931551bSRalph Campbell bidx += QSFP_DUMP_CHUNK; 555f931551bSRalph Campbell } 556f931551bSRalph Campbell ret = sofar; 557f931551bSRalph Campbell bail: 558f931551bSRalph Campbell return ret; 559f931551bSRalph Campbell } 560