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 */ 84*a46a2802SMike 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; 102f931551bSRalph Campbell in_page = addr % QSFP_PAGESIZE; 103f931551bSRalph Campbell if ((in_page + wlen) > QSFP_PAGESIZE) 104f931551bSRalph Campbell wlen = QSFP_PAGESIZE - in_page; 105f931551bSRalph Campbell ret = qib_twsi_blk_rd(dd, QSFP_DEV, addr, buff + cnt, wlen); 106f931551bSRalph Campbell /* Some QSFP's fail first try. Retry as experiment */ 107f931551bSRalph Campbell if (ret && cnt == 0 && ++pass < QSFP_MAX_RETRY) 108f931551bSRalph Campbell continue; 109f931551bSRalph Campbell if (ret) { 110f931551bSRalph Campbell /* qib_twsi_blk_rd() 1 for error, else 0 */ 111f931551bSRalph Campbell ret = -EIO; 112f931551bSRalph Campbell goto deselect; 113f931551bSRalph Campbell } 114f931551bSRalph Campbell addr += wlen; 115f931551bSRalph Campbell cnt += wlen; 116f931551bSRalph Campbell } 117f931551bSRalph Campbell ret = cnt; 118f931551bSRalph Campbell 119f931551bSRalph Campbell deselect: 120f931551bSRalph Campbell /* 121f931551bSRalph Campbell * Module could take up to 10 uSec after transfer before 122f931551bSRalph Campbell * ready to respond to MOD_SEL negation, and there is no way 123f931551bSRalph Campbell * to tell if it is ready, so we must wait. 124f931551bSRalph Campbell */ 125f931551bSRalph Campbell udelay(10); 126f931551bSRalph Campbell /* set QSFP MODSEL, RST. LP all high */ 127f931551bSRalph Campbell dd->f_gpio_mod(dd, mask, mask, mask); 128f931551bSRalph Campbell 129f931551bSRalph Campbell /* 130f931551bSRalph Campbell * Module could take up to 2 Msec to respond to MOD_SEL 131f931551bSRalph Campbell * going away, and there is no way to tell if it is ready. 132f931551bSRalph Campbell * so we must wait. 133f931551bSRalph Campbell */ 134f931551bSRalph Campbell if (stuck) 135f931551bSRalph Campbell qib_dev_err(dd, "QSFP interface bus stuck non-idle\n"); 136f931551bSRalph Campbell 137f931551bSRalph Campbell if (pass >= QSFP_MAX_RETRY && ret) 138f931551bSRalph Campbell qib_dev_porterr(dd, ppd->port, "QSFP failed even retrying\n"); 139f931551bSRalph Campbell else if (pass) 140f931551bSRalph Campbell qib_dev_porterr(dd, ppd->port, "QSFP retries: %d\n", pass); 141f931551bSRalph Campbell 142*a46a2802SMike Marciniszyn msleep(20); 143f931551bSRalph Campbell 144f931551bSRalph Campbell bail: 145f931551bSRalph Campbell mutex_unlock(&dd->eep_lock); 146f931551bSRalph Campbell 147f931551bSRalph Campbell no_unlock: 148f931551bSRalph Campbell return ret; 149f931551bSRalph Campbell } 150f931551bSRalph Campbell 151f931551bSRalph Campbell /* 152f931551bSRalph Campbell * qsfp_write 153f931551bSRalph Campbell * We do not ordinarily write the QSFP, but this is needed to select 154f931551bSRalph Campbell * the page on non-flat QSFPs, and possibly later unusual cases 155f931551bSRalph Campbell */ 156f931551bSRalph Campbell static int qib_qsfp_write(struct qib_pportdata *ppd, int addr, void *bp, 157f931551bSRalph Campbell int len) 158f931551bSRalph Campbell { 159f931551bSRalph Campbell struct qib_devdata *dd = ppd->dd; 160f931551bSRalph Campbell u32 out, mask; 161f931551bSRalph Campbell int ret, cnt; 162f931551bSRalph Campbell u8 *buff = bp; 163f931551bSRalph Campbell 164f931551bSRalph Campbell ret = mutex_lock_interruptible(&dd->eep_lock); 165f931551bSRalph Campbell if (ret) 166f931551bSRalph Campbell goto no_unlock; 167f931551bSRalph Campbell 168f931551bSRalph Campbell if (dd->twsi_eeprom_dev == QIB_TWSI_NO_DEV) { 169f931551bSRalph Campbell ret = -ENXIO; 170f931551bSRalph Campbell goto bail; 171f931551bSRalph Campbell } 172f931551bSRalph Campbell 173f931551bSRalph Campbell /* 174f931551bSRalph Campbell * We presume, if we are called at all, that this board has 175f931551bSRalph Campbell * QSFP. This is on the same i2c chain as the legacy parts, 176f931551bSRalph Campbell * but only responds if the module is selected via GPIO pins. 177f931551bSRalph Campbell * Further, there are very long setup and hold requirements 178f931551bSRalph Campbell * on MODSEL. 179f931551bSRalph Campbell */ 180f931551bSRalph Campbell mask = QSFP_GPIO_MOD_SEL_N | QSFP_GPIO_MOD_RST_N | QSFP_GPIO_LP_MODE; 181f931551bSRalph Campbell out = QSFP_GPIO_MOD_RST_N | QSFP_GPIO_LP_MODE; 182f931551bSRalph Campbell if (ppd->hw_pidx) { 183f931551bSRalph Campbell mask <<= QSFP_GPIO_PORT2_SHIFT; 184f931551bSRalph Campbell out <<= QSFP_GPIO_PORT2_SHIFT; 185f931551bSRalph Campbell } 186f931551bSRalph Campbell dd->f_gpio_mod(dd, out, mask, mask); 187f931551bSRalph Campbell 188f931551bSRalph Campbell /* 189f931551bSRalph Campbell * Module could take up to 2 Msec to respond to MOD_SEL, 190f931551bSRalph Campbell * and there is no way to tell if it is ready, so we must wait. 191f931551bSRalph Campbell */ 192*a46a2802SMike Marciniszyn msleep(20); 193f931551bSRalph Campbell 194f931551bSRalph Campbell /* Make sure TWSI bus is in sane state. */ 195f931551bSRalph Campbell ret = qib_twsi_reset(dd); 196f931551bSRalph Campbell if (ret) { 197f931551bSRalph Campbell qib_dev_porterr(dd, ppd->port, 198f931551bSRalph Campbell "QSFP interface Reset for write failed\n"); 199f931551bSRalph Campbell ret = -EIO; 200f931551bSRalph Campbell goto deselect; 201f931551bSRalph Campbell } 202f931551bSRalph Campbell 203f931551bSRalph Campbell /* All QSFP modules are at A0 */ 204f931551bSRalph Campbell 205f931551bSRalph Campbell cnt = 0; 206f931551bSRalph Campbell while (cnt < len) { 207f931551bSRalph Campbell unsigned in_page; 208f931551bSRalph Campbell int wlen = len - cnt; 209f931551bSRalph Campbell in_page = addr % QSFP_PAGESIZE; 210f931551bSRalph Campbell if ((in_page + wlen) > QSFP_PAGESIZE) 211f931551bSRalph Campbell wlen = QSFP_PAGESIZE - in_page; 212f931551bSRalph Campbell ret = qib_twsi_blk_wr(dd, QSFP_DEV, addr, buff + cnt, wlen); 213f931551bSRalph Campbell if (ret) { 214f931551bSRalph Campbell /* qib_twsi_blk_wr() 1 for error, else 0 */ 215f931551bSRalph Campbell ret = -EIO; 216f931551bSRalph Campbell goto deselect; 217f931551bSRalph Campbell } 218f931551bSRalph Campbell addr += wlen; 219f931551bSRalph Campbell cnt += wlen; 220f931551bSRalph Campbell } 221f931551bSRalph Campbell ret = cnt; 222f931551bSRalph Campbell 223f931551bSRalph Campbell deselect: 224f931551bSRalph Campbell /* 225f931551bSRalph Campbell * Module could take up to 10 uSec after transfer before 226f931551bSRalph Campbell * ready to respond to MOD_SEL negation, and there is no way 227f931551bSRalph Campbell * to tell if it is ready, so we must wait. 228f931551bSRalph Campbell */ 229f931551bSRalph Campbell udelay(10); 230f931551bSRalph Campbell /* set QSFP MODSEL, RST, LP high */ 231f931551bSRalph Campbell dd->f_gpio_mod(dd, mask, mask, mask); 232f931551bSRalph Campbell /* 233f931551bSRalph Campbell * Module could take up to 2 Msec to respond to MOD_SEL 234f931551bSRalph Campbell * going away, and there is no way to tell if it is ready. 235f931551bSRalph Campbell * so we must wait. 236f931551bSRalph Campbell */ 237*a46a2802SMike Marciniszyn msleep(20); 238f931551bSRalph Campbell 239f931551bSRalph Campbell bail: 240f931551bSRalph Campbell mutex_unlock(&dd->eep_lock); 241f931551bSRalph Campbell 242f931551bSRalph Campbell no_unlock: 243f931551bSRalph Campbell return ret; 244f931551bSRalph Campbell } 245f931551bSRalph Campbell 246f931551bSRalph Campbell /* 247f931551bSRalph Campbell * For validation, we want to check the checksums, even of the 248f931551bSRalph Campbell * fields we do not otherwise use. This function reads the bytes from 249f931551bSRalph Campbell * <first> to <next-1> and returns the 8lsbs of the sum, or <0 for errors 250f931551bSRalph Campbell */ 251f931551bSRalph Campbell static int qsfp_cks(struct qib_pportdata *ppd, int first, int next) 252f931551bSRalph Campbell { 253f931551bSRalph Campbell int ret; 254f931551bSRalph Campbell u16 cks; 255f931551bSRalph Campbell u8 bval; 256f931551bSRalph Campbell 257f931551bSRalph Campbell cks = 0; 258f931551bSRalph Campbell while (first < next) { 259f931551bSRalph Campbell ret = qsfp_read(ppd, first, &bval, 1); 260f931551bSRalph Campbell if (ret < 0) 261f931551bSRalph Campbell goto bail; 262f931551bSRalph Campbell cks += bval; 263f931551bSRalph Campbell ++first; 264f931551bSRalph Campbell } 265f931551bSRalph Campbell ret = cks & 0xFF; 266f931551bSRalph Campbell bail: 267f931551bSRalph Campbell return ret; 268f931551bSRalph Campbell 269f931551bSRalph Campbell } 270f931551bSRalph Campbell 271f931551bSRalph Campbell int qib_refresh_qsfp_cache(struct qib_pportdata *ppd, struct qib_qsfp_cache *cp) 272f931551bSRalph Campbell { 273f931551bSRalph Campbell int ret; 274f931551bSRalph Campbell int idx; 275f931551bSRalph Campbell u16 cks; 276f931551bSRalph Campbell u8 peek[4]; 277f931551bSRalph Campbell 278f931551bSRalph Campbell /* ensure sane contents on invalid reads, for cable swaps */ 279f931551bSRalph Campbell memset(cp, 0, sizeof(*cp)); 280f931551bSRalph Campbell 281dde05cbdSMitko Haralanov if (!qib_qsfp_mod_present(ppd)) { 282f931551bSRalph Campbell ret = -ENODEV; 283f931551bSRalph Campbell goto bail; 284f931551bSRalph Campbell } 285f931551bSRalph Campbell 286f931551bSRalph Campbell ret = qsfp_read(ppd, 0, peek, 3); 287f931551bSRalph Campbell if (ret < 0) 288f931551bSRalph Campbell goto bail; 289f931551bSRalph Campbell if ((peek[0] & 0xFE) != 0x0C) 290f931551bSRalph Campbell qib_dev_porterr(ppd->dd, ppd->port, 291f931551bSRalph Campbell "QSFP byte0 is 0x%02X, S/B 0x0C/D\n", peek[0]); 292f931551bSRalph Campbell 293f931551bSRalph Campbell if ((peek[2] & 2) == 0) { 294f931551bSRalph Campbell /* 295f931551bSRalph Campbell * If cable is paged, rather than "flat memory", we need to 296f931551bSRalph Campbell * set the page to zero, Even if it already appears to be zero. 297f931551bSRalph Campbell */ 298f931551bSRalph Campbell u8 poke = 0; 299f931551bSRalph Campbell ret = qib_qsfp_write(ppd, 127, &poke, 1); 300f931551bSRalph Campbell udelay(50); 301f931551bSRalph Campbell if (ret != 1) { 302f931551bSRalph Campbell qib_dev_porterr(ppd->dd, ppd->port, 303f931551bSRalph Campbell "Failed QSFP Page set\n"); 304f931551bSRalph Campbell goto bail; 305f931551bSRalph Campbell } 306f931551bSRalph Campbell } 307f931551bSRalph Campbell 308f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_MOD_ID_OFFS, &cp->id, 1); 309f931551bSRalph Campbell if (ret < 0) 310f931551bSRalph Campbell goto bail; 311f931551bSRalph Campbell if ((cp->id & 0xFE) != 0x0C) 312f931551bSRalph Campbell qib_dev_porterr(ppd->dd, ppd->port, 313f931551bSRalph Campbell "QSFP ID byte is 0x%02X, S/B 0x0C/D\n", cp->id); 314f931551bSRalph Campbell cks = cp->id; 315f931551bSRalph Campbell 316f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_MOD_PWR_OFFS, &cp->pwr, 1); 317f931551bSRalph Campbell if (ret < 0) 318f931551bSRalph Campbell goto bail; 319f931551bSRalph Campbell cks += cp->pwr; 320f931551bSRalph Campbell 321f931551bSRalph Campbell ret = qsfp_cks(ppd, QSFP_MOD_PWR_OFFS + 1, QSFP_MOD_LEN_OFFS); 322f931551bSRalph Campbell if (ret < 0) 323f931551bSRalph Campbell goto bail; 324f931551bSRalph Campbell cks += ret; 325f931551bSRalph Campbell 326f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_MOD_LEN_OFFS, &cp->len, 1); 327f931551bSRalph Campbell if (ret < 0) 328f931551bSRalph Campbell goto bail; 329f931551bSRalph Campbell cks += cp->len; 330f931551bSRalph Campbell 331f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_MOD_TECH_OFFS, &cp->tech, 1); 332f931551bSRalph Campbell if (ret < 0) 333f931551bSRalph Campbell goto bail; 334f931551bSRalph Campbell cks += cp->tech; 335f931551bSRalph Campbell 336f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_VEND_OFFS, &cp->vendor, QSFP_VEND_LEN); 337f931551bSRalph Campbell if (ret < 0) 338f931551bSRalph Campbell goto bail; 339f931551bSRalph Campbell for (idx = 0; idx < QSFP_VEND_LEN; ++idx) 340f931551bSRalph Campbell cks += cp->vendor[idx]; 341f931551bSRalph Campbell 342f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_IBXCV_OFFS, &cp->xt_xcv, 1); 343f931551bSRalph Campbell if (ret < 0) 344f931551bSRalph Campbell goto bail; 345f931551bSRalph Campbell cks += cp->xt_xcv; 346f931551bSRalph Campbell 347f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_VOUI_OFFS, &cp->oui, QSFP_VOUI_LEN); 348f931551bSRalph Campbell if (ret < 0) 349f931551bSRalph Campbell goto bail; 350f931551bSRalph Campbell for (idx = 0; idx < QSFP_VOUI_LEN; ++idx) 351f931551bSRalph Campbell cks += cp->oui[idx]; 352f931551bSRalph Campbell 353f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_PN_OFFS, &cp->partnum, QSFP_PN_LEN); 354f931551bSRalph Campbell if (ret < 0) 355f931551bSRalph Campbell goto bail; 356f931551bSRalph Campbell for (idx = 0; idx < QSFP_PN_LEN; ++idx) 357f931551bSRalph Campbell cks += cp->partnum[idx]; 358f931551bSRalph Campbell 359f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_REV_OFFS, &cp->rev, QSFP_REV_LEN); 360f931551bSRalph Campbell if (ret < 0) 361f931551bSRalph Campbell goto bail; 362f931551bSRalph Campbell for (idx = 0; idx < QSFP_REV_LEN; ++idx) 363f931551bSRalph Campbell cks += cp->rev[idx]; 364f931551bSRalph Campbell 365f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_ATTEN_OFFS, &cp->atten, QSFP_ATTEN_LEN); 366f931551bSRalph Campbell if (ret < 0) 367f931551bSRalph Campbell goto bail; 368f931551bSRalph Campbell for (idx = 0; idx < QSFP_ATTEN_LEN; ++idx) 369f931551bSRalph Campbell cks += cp->atten[idx]; 370f931551bSRalph Campbell 371f931551bSRalph Campbell ret = qsfp_cks(ppd, QSFP_ATTEN_OFFS + QSFP_ATTEN_LEN, QSFP_CC_OFFS); 372f931551bSRalph Campbell if (ret < 0) 373f931551bSRalph Campbell goto bail; 374f931551bSRalph Campbell cks += ret; 375f931551bSRalph Campbell 376f931551bSRalph Campbell cks &= 0xFF; 377f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_CC_OFFS, &cp->cks1, 1); 378f931551bSRalph Campbell if (ret < 0) 379f931551bSRalph Campbell goto bail; 380f931551bSRalph Campbell if (cks != cp->cks1) 381f931551bSRalph Campbell qib_dev_porterr(ppd->dd, ppd->port, 382f931551bSRalph Campbell "QSFP cks1 is %02X, computed %02X\n", cp->cks1, 383f931551bSRalph Campbell cks); 384f931551bSRalph Campbell 385f931551bSRalph Campbell /* Second checksum covers 192 to (serial, date, lot) */ 386f931551bSRalph Campbell ret = qsfp_cks(ppd, QSFP_CC_OFFS + 1, QSFP_SN_OFFS); 387f931551bSRalph Campbell if (ret < 0) 388f931551bSRalph Campbell goto bail; 389f931551bSRalph Campbell cks = ret; 390f931551bSRalph Campbell 391f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_SN_OFFS, &cp->serial, QSFP_SN_LEN); 392f931551bSRalph Campbell if (ret < 0) 393f931551bSRalph Campbell goto bail; 394f931551bSRalph Campbell for (idx = 0; idx < QSFP_SN_LEN; ++idx) 395f931551bSRalph Campbell cks += cp->serial[idx]; 396f931551bSRalph Campbell 397f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_DATE_OFFS, &cp->date, QSFP_DATE_LEN); 398f931551bSRalph Campbell if (ret < 0) 399f931551bSRalph Campbell goto bail; 400f931551bSRalph Campbell for (idx = 0; idx < QSFP_DATE_LEN; ++idx) 401f931551bSRalph Campbell cks += cp->date[idx]; 402f931551bSRalph Campbell 403f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_LOT_OFFS, &cp->lot, QSFP_LOT_LEN); 404f931551bSRalph Campbell if (ret < 0) 405f931551bSRalph Campbell goto bail; 406f931551bSRalph Campbell for (idx = 0; idx < QSFP_LOT_LEN; ++idx) 407f931551bSRalph Campbell cks += cp->lot[idx]; 408f931551bSRalph Campbell 409f931551bSRalph Campbell ret = qsfp_cks(ppd, QSFP_LOT_OFFS + QSFP_LOT_LEN, QSFP_CC_EXT_OFFS); 410f931551bSRalph Campbell if (ret < 0) 411f931551bSRalph Campbell goto bail; 412f931551bSRalph Campbell cks += ret; 413f931551bSRalph Campbell 414f931551bSRalph Campbell ret = qsfp_read(ppd, QSFP_CC_EXT_OFFS, &cp->cks2, 1); 415f931551bSRalph Campbell if (ret < 0) 416f931551bSRalph Campbell goto bail; 417f931551bSRalph Campbell cks &= 0xFF; 418f931551bSRalph Campbell if (cks != cp->cks2) 419f931551bSRalph Campbell qib_dev_porterr(ppd->dd, ppd->port, 420f931551bSRalph Campbell "QSFP cks2 is %02X, computed %02X\n", cp->cks2, 421f931551bSRalph Campbell cks); 422f931551bSRalph Campbell return 0; 423f931551bSRalph Campbell 424f931551bSRalph Campbell bail: 425f931551bSRalph Campbell cp->id = 0; 426f931551bSRalph Campbell return ret; 427f931551bSRalph Campbell } 428f931551bSRalph Campbell 429f931551bSRalph Campbell const char * const qib_qsfp_devtech[16] = { 430f931551bSRalph Campbell "850nm VCSEL", "1310nm VCSEL", "1550nm VCSEL", "1310nm FP", 431f931551bSRalph Campbell "1310nm DFB", "1550nm DFB", "1310nm EML", "1550nm EML", 432f931551bSRalph Campbell "Cu Misc", "1490nm DFB", "Cu NoEq", "Cu Eq", 433f931551bSRalph Campbell "Undef", "Cu Active BothEq", "Cu FarEq", "Cu NearEq" 434f931551bSRalph Campbell }; 435f931551bSRalph Campbell 436f931551bSRalph Campbell #define QSFP_DUMP_CHUNK 16 /* Holds longest string */ 437f931551bSRalph Campbell #define QSFP_DEFAULT_HDR_CNT 224 438f931551bSRalph Campbell 439f931551bSRalph Campbell static const char *pwr_codes = "1.5W2.0W2.5W3.5W"; 440f931551bSRalph Campbell 441dde05cbdSMitko Haralanov int qib_qsfp_mod_present(struct qib_pportdata *ppd) 442dde05cbdSMitko Haralanov { 443dde05cbdSMitko Haralanov u32 mask; 444dde05cbdSMitko Haralanov int ret; 445dde05cbdSMitko Haralanov 446dde05cbdSMitko Haralanov mask = QSFP_GPIO_MOD_PRS_N << 447dde05cbdSMitko Haralanov (ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT); 448dde05cbdSMitko Haralanov ret = ppd->dd->f_gpio_mod(ppd->dd, 0, 0, 0); 449dde05cbdSMitko Haralanov 450dde05cbdSMitko Haralanov return !((ret & mask) >> 451dde05cbdSMitko Haralanov ((ppd->hw_pidx * QSFP_GPIO_PORT2_SHIFT) + 3)); 452dde05cbdSMitko Haralanov } 453dde05cbdSMitko Haralanov 454f931551bSRalph Campbell /* 455f931551bSRalph Campbell * Initialize structures that control access to QSFP. Called once per port 456f931551bSRalph Campbell * on cards that support QSFP. 457f931551bSRalph Campbell */ 458f931551bSRalph Campbell void qib_qsfp_init(struct qib_qsfp_data *qd, 459f931551bSRalph Campbell void (*fevent)(struct work_struct *)) 460f931551bSRalph Campbell { 461f931551bSRalph Campbell u32 mask, highs; 462f931551bSRalph Campbell 463f931551bSRalph Campbell struct qib_devdata *dd = qd->ppd->dd; 464f931551bSRalph Campbell 465f931551bSRalph Campbell /* Initialize work struct for later QSFP events */ 466f931551bSRalph Campbell INIT_WORK(&qd->work, fevent); 467f931551bSRalph Campbell 468f931551bSRalph Campbell /* 469f931551bSRalph Campbell * Later, we may want more validation. For now, just set up pins and 470f931551bSRalph Campbell * blip reset. If module is present, call qib_refresh_qsfp_cache(), 471f931551bSRalph Campbell * to do further init. 472f931551bSRalph Campbell */ 473f931551bSRalph Campbell mask = QSFP_GPIO_MOD_SEL_N | QSFP_GPIO_MOD_RST_N | QSFP_GPIO_LP_MODE; 474f931551bSRalph Campbell highs = mask - QSFP_GPIO_MOD_RST_N; 475f931551bSRalph Campbell if (qd->ppd->hw_pidx) { 476f931551bSRalph Campbell mask <<= QSFP_GPIO_PORT2_SHIFT; 477f931551bSRalph Campbell highs <<= QSFP_GPIO_PORT2_SHIFT; 478f931551bSRalph Campbell } 479f931551bSRalph Campbell dd->f_gpio_mod(dd, highs, mask, mask); 480f931551bSRalph Campbell udelay(20); /* Generous RST dwell */ 481f931551bSRalph Campbell 482f931551bSRalph Campbell dd->f_gpio_mod(dd, mask, mask, mask); 483f931551bSRalph Campbell } 484f931551bSRalph Campbell 485f931551bSRalph Campbell void qib_qsfp_deinit(struct qib_qsfp_data *qd) 486f931551bSRalph Campbell { 487f931551bSRalph Campbell /* 488f0626710STejun Heo * There is nothing to do here for now. our work is scheduled 489f0626710STejun Heo * with queue_work(), and flush_workqueue() from remove_one 490f0626710STejun Heo * will block until all work setup with queue_work() 491f931551bSRalph Campbell * completes. 492f931551bSRalph Campbell */ 493f931551bSRalph Campbell } 494f931551bSRalph Campbell 495f931551bSRalph Campbell int qib_qsfp_dump(struct qib_pportdata *ppd, char *buf, int len) 496f931551bSRalph Campbell { 497f931551bSRalph Campbell struct qib_qsfp_cache cd; 498f931551bSRalph Campbell u8 bin_buff[QSFP_DUMP_CHUNK]; 499f931551bSRalph Campbell char lenstr[6]; 500f931551bSRalph Campbell int sofar, ret; 501f931551bSRalph Campbell int bidx = 0; 502f931551bSRalph Campbell 503f931551bSRalph Campbell sofar = 0; 504f931551bSRalph Campbell ret = qib_refresh_qsfp_cache(ppd, &cd); 505f931551bSRalph Campbell if (ret < 0) 506f931551bSRalph Campbell goto bail; 507f931551bSRalph Campbell 508f931551bSRalph Campbell lenstr[0] = ' '; 509f931551bSRalph Campbell lenstr[1] = '\0'; 510f931551bSRalph Campbell if (QSFP_IS_CU(cd.tech)) 511f931551bSRalph Campbell sprintf(lenstr, "%dM ", cd.len); 512f931551bSRalph Campbell 513f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "PWR:%.3sW\n", pwr_codes + 514f931551bSRalph Campbell (QSFP_PWR(cd.pwr) * 4)); 515f931551bSRalph Campbell 516f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "TECH:%s%s\n", lenstr, 517f931551bSRalph Campbell qib_qsfp_devtech[cd.tech >> 4]); 518f931551bSRalph Campbell 519f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Vendor:%.*s\n", 520f931551bSRalph Campbell QSFP_VEND_LEN, cd.vendor); 521f931551bSRalph Campbell 522f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "OUI:%06X\n", 523f931551bSRalph Campbell QSFP_OUI(cd.oui)); 524f931551bSRalph Campbell 525f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Part#:%.*s\n", 526f931551bSRalph Campbell QSFP_PN_LEN, cd.partnum); 527f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Rev:%.*s\n", 528f931551bSRalph Campbell QSFP_REV_LEN, cd.rev); 529f931551bSRalph Campbell if (QSFP_IS_CU(cd.tech)) 530f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Atten:%d, %d\n", 531f931551bSRalph Campbell QSFP_ATTEN_SDR(cd.atten), 532f931551bSRalph Campbell QSFP_ATTEN_DDR(cd.atten)); 533f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Serial:%.*s\n", 534f931551bSRalph Campbell QSFP_SN_LEN, cd.serial); 535f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Date:%.*s\n", 536f931551bSRalph Campbell QSFP_DATE_LEN, cd.date); 537f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "Lot:%.*s\n", 538f931551bSRalph Campbell QSFP_LOT_LEN, cd.date); 539f931551bSRalph Campbell 540f931551bSRalph Campbell while (bidx < QSFP_DEFAULT_HDR_CNT) { 541f931551bSRalph Campbell int iidx; 542f931551bSRalph Campbell ret = qsfp_read(ppd, bidx, bin_buff, QSFP_DUMP_CHUNK); 543f931551bSRalph Campbell if (ret < 0) 544f931551bSRalph Campbell goto bail; 545f931551bSRalph Campbell for (iidx = 0; iidx < ret; ++iidx) { 546f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len-sofar, " %02X", 547f931551bSRalph Campbell bin_buff[iidx]); 548f931551bSRalph Campbell } 549f931551bSRalph Campbell sofar += scnprintf(buf + sofar, len - sofar, "\n"); 550f931551bSRalph Campbell bidx += QSFP_DUMP_CHUNK; 551f931551bSRalph Campbell } 552f931551bSRalph Campbell ret = sofar; 553f931551bSRalph Campbell bail: 554f931551bSRalph Campbell return ret; 555f931551bSRalph Campbell } 556