/* for the given bus number, return the CSR for reading an i2c line */ staticinline u32 i2c_in_csr(u32 bus_num)
{ return bus_num ? ASIC_QSFP2_IN : ASIC_QSFP1_IN;
}
/* for the given bus number, return the CSR for writing an i2c line */ staticinline u32 i2c_oe_csr(u32 bus_num)
{ return bus_num ? ASIC_QSFP2_OE : ASIC_QSFP1_OE;
}
target_oe = i2c_oe_csr(bus->num);
reg = read_csr(dd, target_oe); /* * The OE bit value is inverted and connected to the pin. When * OE is 0 the pin is left to be pulled up, when the OE is 1 * the pin is driven low. This matches the "open drain" or "open * collector" convention.
*/ if (state)
reg &= ~QSFP_HFI0_I2CDAT; else
reg |= QSFP_HFI0_I2CDAT;
write_csr(dd, target_oe, reg); /* do a read to force the write into the chip */
(void)read_csr(dd, target_oe);
}
target_oe = i2c_oe_csr(bus->num);
reg = read_csr(dd, target_oe); /* * The OE bit value is inverted and connected to the pin. When * OE is 0 the pin is left to be pulled up, when the OE is 1 * the pin is driven low. This matches the "open drain" or "open * collector" convention.
*/ if (state)
reg &= ~QSFP_HFI0_I2CCLK; else
reg |= QSFP_HFI0_I2CCLK;
write_csr(dd, target_oe, reg); /* do a read to force the write into the chip */
(void)read_csr(dd, target_oe);
}
/* * Allocate and initialize the given i2c bus number. * Returns NULL on failure.
*/ staticstruct hfi1_i2c_bus *init_i2c_bus(struct hfi1_devdata *dd, struct hfi1_asic_data *ad, int num)
{ struct hfi1_i2c_bus *bus; int ret;
bus = kzalloc(sizeof(*bus), GFP_KERNEL); if (!bus) return NULL;
bus->controlling_dd = dd;
bus->num = num; /* our bus number */
/* * Caller must hold the i2c chain resource. * * Return number of bytes written, or -errno.
*/ int i2c_write(struct hfi1_pportdata *ppd, u32 target, int i2c_addr, int offset, void *bp, int len)
{ int ret;
if (!check_chip_resource(ppd->dd, i2c_target(target), __func__)) return -EACCES;
ret = __i2c_write(ppd, target, i2c_addr, offset, bp, len); if (ret) return ret;
return len;
}
/* * Raw i2c read. No set-up or lock checking. * * Return 0 on success, -errno on error.
*/ staticint __i2c_read(struct hfi1_pportdata *ppd, u32 target, int i2c_addr, int offset, void *bp, int len)
{ struct hfi1_devdata *dd = ppd->dd; struct hfi1_i2c_bus *bus;
u8 slave_addr; int offset_size;
/* * Caller must hold the i2c chain resource. * * Return number of bytes read, or -errno.
*/ int i2c_read(struct hfi1_pportdata *ppd, u32 target, int i2c_addr, int offset, void *bp, int len)
{ int ret;
if (!check_chip_resource(ppd->dd, i2c_target(target), __func__)) return -EACCES;
ret = __i2c_read(ppd, target, i2c_addr, offset, bp, len); if (ret) return ret;
return len;
}
/* * Write page n, offset m of QSFP memory as defined by SFF 8636 * by writing @addr = ((256 * n) + m) * * Caller must hold the i2c chain resource. * * Return number of bytes written or -errno.
*/ int qsfp_write(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp, int len)
{ int count = 0; int offset; int nwrite; int ret = 0;
u8 page;
if (!check_chip_resource(ppd->dd, i2c_target(target), __func__)) return -EACCES;
while (count < len) { /* * Set the qsfp page based on a zero-based address * and a page size of QSFP_PAGESIZE bytes.
*/
page = (u8)(addr / QSFP_PAGESIZE);
ret = __i2c_write(ppd, target, QSFP_DEV | QSFP_OFFSET_SIZE,
QSFP_PAGE_SELECT_BYTE_OFFS, &page, 1); /* QSFPs require a 5-10msec delay after write operations */
mdelay(5); if (ret) {
hfi1_dev_porterr(ppd->dd, ppd->port, "QSFP chain %d can't write QSFP_PAGE_SELECT_BYTE: %d\n",
target, ret); break;
}
offset = addr % QSFP_PAGESIZE;
nwrite = len - count; /* truncate write to boundary if crossing boundary */ if (((addr % QSFP_RW_BOUNDARY) + nwrite) > QSFP_RW_BOUNDARY)
nwrite = QSFP_RW_BOUNDARY - (addr % QSFP_RW_BOUNDARY);
ret = __i2c_write(ppd, target, QSFP_DEV | QSFP_OFFSET_SIZE,
offset, bp + count, nwrite); /* QSFPs require a 5-10msec delay after write operations */
mdelay(5); if (ret) /* stop on error */ break;
count += nwrite;
addr += nwrite;
}
if (ret < 0) return ret; return count;
}
/* * Access page n, offset m of QSFP memory as defined by SFF 8636 * by reading @addr = ((256 * n) + m) * * Caller must hold the i2c chain resource. * * Return the number of bytes read or -errno.
*/ int qsfp_read(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp, int len)
{ int count = 0; int offset; int nread; int ret = 0;
u8 page;
if (!check_chip_resource(ppd->dd, i2c_target(target), __func__)) return -EACCES;
while (count < len) { /* * Set the qsfp page based on a zero-based address * and a page size of QSFP_PAGESIZE bytes.
*/
page = (u8)(addr / QSFP_PAGESIZE);
ret = __i2c_write(ppd, target, QSFP_DEV | QSFP_OFFSET_SIZE,
QSFP_PAGE_SELECT_BYTE_OFFS, &page, 1); /* QSFPs require a 5-10msec delay after write operations */
mdelay(5); if (ret) {
hfi1_dev_porterr(ppd->dd, ppd->port, "QSFP chain %d can't write QSFP_PAGE_SELECT_BYTE: %d\n",
target, ret); break;
}
offset = addr % QSFP_PAGESIZE;
nread = len - count; /* truncate read to boundary if crossing boundary */ if (((addr % QSFP_RW_BOUNDARY) + nread) > QSFP_RW_BOUNDARY)
nread = QSFP_RW_BOUNDARY - (addr % QSFP_RW_BOUNDARY);
ret = __i2c_read(ppd, target, QSFP_DEV | QSFP_OFFSET_SIZE,
offset, bp + count, nread); if (ret) /* stop on error */ break;
count += nread;
addr += nread;
}
if (ret < 0) return ret; return count;
}
/* * Perform a stand-alone single QSFP read. Acquire the resource, do the * read, then release the resource.
*/ int one_qsfp_read(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp, int len)
{ struct hfi1_devdata *dd = ppd->dd;
u32 resource = qsfp_resource(dd); int ret;
ret = acquire_chip_resource(dd, resource, QSFP_WAIT); if (ret) return ret;
ret = qsfp_read(ppd, target, addr, bp, len);
release_chip_resource(dd, resource);
return ret;
}
/* * This function caches the QSFP memory range in 128 byte chunks. * As an example, the next byte after address 255 is byte 128 from * upper page 01H (if existing) rather than byte 0 from lower page 00H. * Access page n, offset m of QSFP memory as defined by SFF 8636 * in the cache by reading byte ((128 * n) + m) * The calls to qsfp_{read,write} in this function correctly handle the * address map difference between this mapping and the mapping implemented * by those functions * * The caller must be holding the QSFP i2c chain resource.
*/ int refresh_qsfp_cache(struct hfi1_pportdata *ppd, struct qsfp_data *cp)
{
u32 target = ppd->dd->hfi1_id; int ret; unsignedlong flags;
u8 *cache = &cp->cache[0];
#define QSFP_PWR(pbyte) (((pbyte) >> 6) & 3) #define QSFP_HIGH_PWR(pbyte) ((pbyte) & 3) /* For use with QSFP_HIGH_PWR macro */ #define QSFP_HIGH_PWR_UNUSED 0 /* Bits [1:0] = 00 implies low power module */
/* * Takes power class byte [Page 00 Byte 129] in SFF 8636 * Returns power class as integer (1 through 7, per SFF 8636 rev 2.4)
*/ int get_qsfp_power_class(u8 power_byte)
{ if (QSFP_HIGH_PWR(power_byte) == QSFP_HIGH_PWR_UNUSED) /* power classes count from 1, their bit encodings from 0 */ return (QSFP_PWR(power_byte) + 1); /* * 00 in the high power classes stands for unused, bringing * balance to the off-by-1 offset above, we add 4 here to * account for the difference between the low and high power * groups
*/ return (QSFP_HIGH_PWR(power_byte) + 4);
}
/* * This function maps QSFP memory addresses in 128 byte chunks in the following * fashion per the CableInfo SMA query definition in the IBA 1.3 spec/OPA Gen 1 * spec * For addr 000-127, lower page 00h * For addr 128-255, upper page 00h * For addr 256-383, upper page 01h * For addr 384-511, upper page 02h * For addr 512-639, upper page 03h * * For addresses beyond this range, it returns the invalid range of data buffer * set to 0. * For upper pages that are optional, if they are not valid, returns the * particular range of bytes in the data buffer set to 0.
*/ int get_cable_info(struct hfi1_devdata *dd, u32 port_num, u32 addr, u32 len,
u8 *data)
{ struct hfi1_pportdata *ppd;
u32 excess_len = len; int ret = 0, offset = 0;
if (port_num > dd->num_pports || port_num < 1) {
dd_dev_info(dd, "%s: Invalid port number %d\n",
__func__, port_num);
ret = -EINVAL; goto set_zeroes;
}
ppd = dd->pport + (port_num - 1); if (!qsfp_mod_present(ppd)) {
ret = -ENODEV; goto set_zeroes;
}
if (!ppd->qsfp_info.cache_valid) {
ret = -EINVAL; goto set_zeroes;
}
if (addr >= (QSFP_MAX_NUM_PAGES * 128)) {
ret = -ERANGE; goto set_zeroes;
}
if (addr <= QSFP_MONITOR_VAL_END &&
(addr + len) >= QSFP_MONITOR_VAL_START) { /* Overlap with the dynamic channel monitor range */ if (addr < QSFP_MONITOR_VAL_START) { if (addr + len <= QSFP_MONITOR_VAL_END)
len = addr + len - QSFP_MONITOR_VAL_START; else
len = QSFP_MONITOR_RANGE;
offset = QSFP_MONITOR_VAL_START - addr;
addr = QSFP_MONITOR_VAL_START;
} elseif (addr == QSFP_MONITOR_VAL_START) {
offset = 0; if (addr + len > QSFP_MONITOR_VAL_END)
len = QSFP_MONITOR_RANGE;
} else {
offset = 0; if (addr + len > QSFP_MONITOR_VAL_END)
len = QSFP_MONITOR_VAL_END - addr + 1;
} /* Refresh the values of the dynamic monitors from the cable */
ret = one_qsfp_read(ppd, dd->hfi1_id, addr, data + offset, len); if (ret != len) {
ret = -EAGAIN; goto set_zeroes;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.