^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright(c) 2015, 2016 Intel Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * This file is provided under a dual BSD/GPLv2 license. When using or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * redistributing this file, you may do so under either license.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * GPL LICENSE SUMMARY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * it under the terms of version 2 of the GNU General Public License as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * published by the Free Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * This program is distributed in the hope that it will be useful, but
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * BSD LICENSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * Redistribution and use in source and binary forms, with or without
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * modification, are permitted provided that the following conditions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * are met:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * - Redistributions of source code must retain the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * notice, this list of conditions and the following disclaimer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * - Redistributions in binary form must reproduce the above copyright
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * notice, this list of conditions and the following disclaimer in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * the documentation and/or other materials provided with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * distribution.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * - Neither the name of Intel Corporation nor the names of its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * contributors may be used to endorse or promote products derived
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * from this software without specific prior written permission.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #include "hfi.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /* for the given bus number, return the CSR for reading an i2c line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) static inline u32 i2c_in_csr(u32 bus_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return bus_num ? ASIC_QSFP2_IN : ASIC_QSFP1_IN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) /* for the given bus number, return the CSR for writing an i2c line */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static inline u32 i2c_oe_csr(u32 bus_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return bus_num ? ASIC_QSFP2_OE : ASIC_QSFP1_OE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static void hfi1_setsda(void *data, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct hfi1_i2c_bus *bus = (struct hfi1_i2c_bus *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct hfi1_devdata *dd = bus->controlling_dd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) u64 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) u32 target_oe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) target_oe = i2c_oe_csr(bus->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) reg = read_csr(dd, target_oe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * The OE bit value is inverted and connected to the pin. When
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * OE is 0 the pin is left to be pulled up, when the OE is 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * the pin is driven low. This matches the "open drain" or "open
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * collector" convention.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) reg &= ~QSFP_HFI0_I2CDAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) reg |= QSFP_HFI0_I2CDAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) write_csr(dd, target_oe, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* do a read to force the write into the chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) (void)read_csr(dd, target_oe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static void hfi1_setscl(void *data, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct hfi1_i2c_bus *bus = (struct hfi1_i2c_bus *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) struct hfi1_devdata *dd = bus->controlling_dd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) u64 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) u32 target_oe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) target_oe = i2c_oe_csr(bus->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) reg = read_csr(dd, target_oe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * The OE bit value is inverted and connected to the pin. When
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * OE is 0 the pin is left to be pulled up, when the OE is 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * the pin is driven low. This matches the "open drain" or "open
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * collector" convention.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) reg &= ~QSFP_HFI0_I2CCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) reg |= QSFP_HFI0_I2CCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) write_csr(dd, target_oe, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) /* do a read to force the write into the chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) (void)read_csr(dd, target_oe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static int hfi1_getsda(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct hfi1_i2c_bus *bus = (struct hfi1_i2c_bus *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) u64 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) u32 target_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) hfi1_setsda(data, 1); /* clear OE so we do not pull line down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) udelay(2); /* 1us pull up + 250ns hold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) target_in = i2c_in_csr(bus->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) reg = read_csr(bus->controlling_dd, target_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) return !!(reg & QSFP_HFI0_I2CDAT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static int hfi1_getscl(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) struct hfi1_i2c_bus *bus = (struct hfi1_i2c_bus *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) u64 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) u32 target_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) hfi1_setscl(data, 1); /* clear OE so we do not pull line down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) udelay(2); /* 1us pull up + 250ns hold */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) target_in = i2c_in_csr(bus->num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) reg = read_csr(bus->controlling_dd, target_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return !!(reg & QSFP_HFI0_I2CCLK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * Allocate and initialize the given i2c bus number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * Returns NULL on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static struct hfi1_i2c_bus *init_i2c_bus(struct hfi1_devdata *dd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct hfi1_asic_data *ad, int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct hfi1_i2c_bus *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) bus = kzalloc(sizeof(*bus), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (!bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) bus->controlling_dd = dd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) bus->num = num; /* our bus number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) bus->algo.setsda = hfi1_setsda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) bus->algo.setscl = hfi1_setscl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) bus->algo.getsda = hfi1_getsda;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) bus->algo.getscl = hfi1_getscl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) bus->algo.udelay = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) bus->algo.timeout = usecs_to_jiffies(100000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) bus->algo.data = bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) bus->adapter.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) bus->adapter.algo_data = &bus->algo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) bus->adapter.dev.parent = &dd->pcidev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) snprintf(bus->adapter.name, sizeof(bus->adapter.name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) "hfi1_i2c%d", num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) ret = i2c_bit_add_bus(&bus->adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) dd_dev_info(dd, "%s: unable to add i2c bus %d, err %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) __func__, num, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) kfree(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * Initialize i2c buses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * Return 0 on success, -errno on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) int set_up_i2c(struct hfi1_devdata *dd, struct hfi1_asic_data *ad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ad->i2c_bus0 = init_i2c_bus(dd, ad, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) ad->i2c_bus1 = init_i2c_bus(dd, ad, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (!ad->i2c_bus0 || !ad->i2c_bus1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) static void clean_i2c_bus(struct hfi1_i2c_bus *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (bus) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) i2c_del_adapter(&bus->adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) kfree(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) void clean_up_i2c(struct hfi1_devdata *dd, struct hfi1_asic_data *ad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (!ad)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) clean_i2c_bus(ad->i2c_bus0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) ad->i2c_bus0 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) clean_i2c_bus(ad->i2c_bus1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ad->i2c_bus1 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static int i2c_bus_write(struct hfi1_devdata *dd, struct hfi1_i2c_bus *i2c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) u8 slave_addr, int offset, int offset_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) u8 *data, u16 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) int num_msgs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) u8 offset_bytes[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct i2c_msg msgs[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) switch (offset_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) num_msgs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) msgs[0].addr = slave_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) msgs[0].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) msgs[0].len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) msgs[0].buf = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) offset_bytes[1] = (offset >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) num_msgs = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) offset_bytes[0] = offset & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) msgs[0].addr = slave_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) msgs[0].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) msgs[0].len = offset_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) msgs[0].buf = offset_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) msgs[1].addr = slave_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) msgs[1].flags = I2C_M_NOSTART,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) msgs[1].len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) msgs[1].buf = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) i2c->controlling_dd = dd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) ret = i2c_transfer(&i2c->adapter, msgs, num_msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (ret != num_msgs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) dd_dev_err(dd, "%s: bus %d, i2c slave 0x%x, offset 0x%x, len 0x%x; write failed, ret %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) __func__, i2c->num, slave_addr, offset, len, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return ret < 0 ? ret : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static int i2c_bus_read(struct hfi1_devdata *dd, struct hfi1_i2c_bus *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) u8 slave_addr, int offset, int offset_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) u8 *data, u16 len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) int num_msgs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) u8 offset_bytes[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct i2c_msg msgs[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) switch (offset_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) num_msgs = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) msgs[0].addr = slave_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) msgs[0].flags = I2C_M_RD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) msgs[0].len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) msgs[0].buf = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) offset_bytes[1] = (offset >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) num_msgs = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) offset_bytes[0] = offset & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) msgs[0].addr = slave_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) msgs[0].flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) msgs[0].len = offset_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) msgs[0].buf = offset_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) msgs[1].addr = slave_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) msgs[1].flags = I2C_M_RD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) msgs[1].len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) msgs[1].buf = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) bus->controlling_dd = dd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) ret = i2c_transfer(&bus->adapter, msgs, num_msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (ret != num_msgs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) dd_dev_err(dd, "%s: bus %d, i2c slave 0x%x, offset 0x%x, len 0x%x; read failed, ret %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) __func__, bus->num, slave_addr, offset, len, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) return ret < 0 ? ret : -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * Raw i2c write. No set-up or lock checking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) * Return 0 on success, -errno on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static int __i2c_write(struct hfi1_pportdata *ppd, u32 target, int i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int offset, void *bp, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct hfi1_devdata *dd = ppd->dd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct hfi1_i2c_bus *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) u8 slave_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) int offset_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) bus = target ? dd->asic_data->i2c_bus1 : dd->asic_data->i2c_bus0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) slave_addr = (i2c_addr & 0xff) >> 1; /* convert to 7-bit addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) offset_size = (i2c_addr >> 8) & 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return i2c_bus_write(dd, bus, slave_addr, offset, offset_size, bp, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) * Caller must hold the i2c chain resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) * Return number of bytes written, or -errno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) int i2c_write(struct hfi1_pportdata *ppd, u32 target, int i2c_addr, int offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) void *bp, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) if (!check_chip_resource(ppd->dd, i2c_target(target), __func__))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) ret = __i2c_write(ppd, target, i2c_addr, offset, bp, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * Raw i2c read. No set-up or lock checking.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) * Return 0 on success, -errno on error.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static int __i2c_read(struct hfi1_pportdata *ppd, u32 target, int i2c_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) int offset, void *bp, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) struct hfi1_devdata *dd = ppd->dd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) struct hfi1_i2c_bus *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) u8 slave_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) int offset_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) bus = target ? dd->asic_data->i2c_bus1 : dd->asic_data->i2c_bus0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) slave_addr = (i2c_addr & 0xff) >> 1; /* convert to 7-bit addr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) offset_size = (i2c_addr >> 8) & 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return i2c_bus_read(dd, bus, slave_addr, offset, offset_size, bp, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * Caller must hold the i2c chain resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * Return number of bytes read, or -errno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) int i2c_read(struct hfi1_pportdata *ppd, u32 target, int i2c_addr, int offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) void *bp, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (!check_chip_resource(ppd->dd, i2c_target(target), __func__))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) ret = __i2c_read(ppd, target, i2c_addr, offset, bp, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * Write page n, offset m of QSFP memory as defined by SFF 8636
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) * by writing @addr = ((256 * n) + m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * Caller must hold the i2c chain resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * Return number of bytes written or -errno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) int qsfp_write(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) int nwrite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) u8 page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (!check_chip_resource(ppd->dd, i2c_target(target), __func__))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) while (count < len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * Set the qsfp page based on a zero-based address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * and a page size of QSFP_PAGESIZE bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) page = (u8)(addr / QSFP_PAGESIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) ret = __i2c_write(ppd, target, QSFP_DEV | QSFP_OFFSET_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) QSFP_PAGE_SELECT_BYTE_OFFS, &page, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) /* QSFPs require a 5-10msec delay after write operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) hfi1_dev_porterr(ppd->dd, ppd->port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) "QSFP chain %d can't write QSFP_PAGE_SELECT_BYTE: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) target, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) offset = addr % QSFP_PAGESIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) nwrite = len - count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /* truncate write to boundary if crossing boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (((addr % QSFP_RW_BOUNDARY) + nwrite) > QSFP_RW_BOUNDARY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) nwrite = QSFP_RW_BOUNDARY - (addr % QSFP_RW_BOUNDARY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) ret = __i2c_write(ppd, target, QSFP_DEV | QSFP_OFFSET_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) offset, bp + count, nwrite);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* QSFPs require a 5-10msec delay after write operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (ret) /* stop on error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) count += nwrite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) addr += nwrite;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * Perform a stand-alone single QSFP write. Acquire the resource, do the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * write, then release the resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) int one_qsfp_write(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct hfi1_devdata *dd = ppd->dd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) u32 resource = qsfp_resource(dd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ret = acquire_chip_resource(dd, resource, QSFP_WAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) ret = qsfp_write(ppd, target, addr, bp, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) release_chip_resource(dd, resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * Access page n, offset m of QSFP memory as defined by SFF 8636
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * by reading @addr = ((256 * n) + m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * Caller must hold the i2c chain resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * Return the number of bytes read or -errno.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) int qsfp_read(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) int nread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) u8 page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (!check_chip_resource(ppd->dd, i2c_target(target), __func__))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) while (count < len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * Set the qsfp page based on a zero-based address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * and a page size of QSFP_PAGESIZE bytes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) page = (u8)(addr / QSFP_PAGESIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) ret = __i2c_write(ppd, target, QSFP_DEV | QSFP_OFFSET_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) QSFP_PAGE_SELECT_BYTE_OFFS, &page, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /* QSFPs require a 5-10msec delay after write operations */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) mdelay(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) hfi1_dev_porterr(ppd->dd, ppd->port,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) "QSFP chain %d can't write QSFP_PAGE_SELECT_BYTE: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) target, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) offset = addr % QSFP_PAGESIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) nread = len - count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) /* truncate read to boundary if crossing boundary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (((addr % QSFP_RW_BOUNDARY) + nread) > QSFP_RW_BOUNDARY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) nread = QSFP_RW_BOUNDARY - (addr % QSFP_RW_BOUNDARY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) ret = __i2c_read(ppd, target, QSFP_DEV | QSFP_OFFSET_SIZE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) offset, bp + count, nread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) if (ret) /* stop on error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) count += nread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) addr += nread;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) * Perform a stand-alone single QSFP read. Acquire the resource, do the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) * read, then release the resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) int one_qsfp_read(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) struct hfi1_devdata *dd = ppd->dd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) u32 resource = qsfp_resource(dd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) ret = acquire_chip_resource(dd, resource, QSFP_WAIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) ret = qsfp_read(ppd, target, addr, bp, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) release_chip_resource(dd, resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) * This function caches the QSFP memory range in 128 byte chunks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * As an example, the next byte after address 255 is byte 128 from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) * upper page 01H (if existing) rather than byte 0 from lower page 00H.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * Access page n, offset m of QSFP memory as defined by SFF 8636
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) * in the cache by reading byte ((128 * n) + m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) * The calls to qsfp_{read,write} in this function correctly handle the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) * address map difference between this mapping and the mapping implemented
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) * by those functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) * The caller must be holding the QSFP i2c chain resource.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) int refresh_qsfp_cache(struct hfi1_pportdata *ppd, struct qsfp_data *cp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) u32 target = ppd->dd->hfi1_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) u8 *cache = &cp->cache[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /* ensure sane contents on invalid reads, for cable swaps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) memset(cache, 0, (QSFP_MAX_NUM_PAGES * 128));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) spin_lock_irqsave(&ppd->qsfp_info.qsfp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) ppd->qsfp_info.cache_valid = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) spin_unlock_irqrestore(&ppd->qsfp_info.qsfp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) if (!qsfp_mod_present(ppd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) ret = qsfp_read(ppd, target, 0, cache, QSFP_PAGESIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (ret != QSFP_PAGESIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) dd_dev_info(ppd->dd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) "%s: Page 0 read failed, expected %d, got %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) __func__, QSFP_PAGESIZE, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) /* Is paging enabled? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (!(cache[2] & 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) /* Paging enabled, page 03 required */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) if ((cache[195] & 0xC0) == 0xC0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /* all */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) ret = qsfp_read(ppd, target, 384, cache + 256, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (ret <= 0 || ret != 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) dd_dev_info(ppd->dd, "%s failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) ret = qsfp_read(ppd, target, 640, cache + 384, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (ret <= 0 || ret != 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) dd_dev_info(ppd->dd, "%s failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) ret = qsfp_read(ppd, target, 896, cache + 512, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) if (ret <= 0 || ret != 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) dd_dev_info(ppd->dd, "%s failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) } else if ((cache[195] & 0x80) == 0x80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* only page 2 and 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) ret = qsfp_read(ppd, target, 640, cache + 384, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (ret <= 0 || ret != 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) dd_dev_info(ppd->dd, "%s failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ret = qsfp_read(ppd, target, 896, cache + 512, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (ret <= 0 || ret != 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) dd_dev_info(ppd->dd, "%s failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) } else if ((cache[195] & 0x40) == 0x40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) /* only page 1 and 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) ret = qsfp_read(ppd, target, 384, cache + 256, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (ret <= 0 || ret != 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) dd_dev_info(ppd->dd, "%s failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) ret = qsfp_read(ppd, target, 896, cache + 512, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) if (ret <= 0 || ret != 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) dd_dev_info(ppd->dd, "%s failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) /* only page 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) ret = qsfp_read(ppd, target, 896, cache + 512, 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (ret <= 0 || ret != 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) dd_dev_info(ppd->dd, "%s failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) goto bail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) spin_lock_irqsave(&ppd->qsfp_info.qsfp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) ppd->qsfp_info.cache_valid = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) ppd->qsfp_info.cache_refresh_required = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) spin_unlock_irqrestore(&ppd->qsfp_info.qsfp_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) bail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) memset(cache, 0, (QSFP_MAX_NUM_PAGES * 128));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) const char * const hfi1_qsfp_devtech[16] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) "850nm VCSEL", "1310nm VCSEL", "1550nm VCSEL", "1310nm FP",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) "1310nm DFB", "1550nm DFB", "1310nm EML", "1550nm EML",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) "Cu Misc", "1490nm DFB", "Cu NoEq", "Cu Eq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) "Undef", "Cu Active BothEq", "Cu FarEq", "Cu NearEq"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) #define QSFP_DUMP_CHUNK 16 /* Holds longest string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) #define QSFP_DEFAULT_HDR_CNT 224
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) #define QSFP_PWR(pbyte) (((pbyte) >> 6) & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) #define QSFP_HIGH_PWR(pbyte) ((pbyte) & 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) /* For use with QSFP_HIGH_PWR macro */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) #define QSFP_HIGH_PWR_UNUSED 0 /* Bits [1:0] = 00 implies low power module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * Takes power class byte [Page 00 Byte 129] in SFF 8636
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * Returns power class as integer (1 through 7, per SFF 8636 rev 2.4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) int get_qsfp_power_class(u8 power_byte)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (QSFP_HIGH_PWR(power_byte) == QSFP_HIGH_PWR_UNUSED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) /* power classes count from 1, their bit encodings from 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) return (QSFP_PWR(power_byte) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * 00 in the high power classes stands for unused, bringing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * balance to the off-by-1 offset above, we add 4 here to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * account for the difference between the low and high power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * groups
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) return (QSFP_HIGH_PWR(power_byte) + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) int qsfp_mod_present(struct hfi1_pportdata *ppd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) struct hfi1_devdata *dd = ppd->dd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) u64 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) reg = read_csr(dd, dd->hfi1_id ? ASIC_QSFP2_IN : ASIC_QSFP1_IN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return !(reg & QSFP_HFI0_MODPRST_N);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) * This function maps QSFP memory addresses in 128 byte chunks in the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) * fashion per the CableInfo SMA query definition in the IBA 1.3 spec/OPA Gen 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) * spec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * For addr 000-127, lower page 00h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) * For addr 128-255, upper page 00h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) * For addr 256-383, upper page 01h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) * For addr 384-511, upper page 02h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) * For addr 512-639, upper page 03h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) * For addresses beyond this range, it returns the invalid range of data buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * set to 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) * For upper pages that are optional, if they are not valid, returns the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * particular range of bytes in the data buffer set to 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) int get_cable_info(struct hfi1_devdata *dd, u32 port_num, u32 addr, u32 len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) u8 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct hfi1_pportdata *ppd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) u32 excess_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) int ret = 0, offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if (port_num > dd->num_pports || port_num < 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) dd_dev_info(dd, "%s: Invalid port number %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) __func__, port_num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) goto set_zeroes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) ppd = dd->pport + (port_num - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) if (!qsfp_mod_present(ppd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) goto set_zeroes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (!ppd->qsfp_info.cache_valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) goto set_zeroes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (addr >= (QSFP_MAX_NUM_PAGES * 128)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) ret = -ERANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) goto set_zeroes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if ((addr + len) > (QSFP_MAX_NUM_PAGES * 128)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) excess_len = (addr + len) - (QSFP_MAX_NUM_PAGES * 128);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) memcpy(data, &ppd->qsfp_info.cache[addr], (len - excess_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) data += (len - excess_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) goto set_zeroes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) memcpy(data, &ppd->qsfp_info.cache[addr], len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (addr <= QSFP_MONITOR_VAL_END &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) (addr + len) >= QSFP_MONITOR_VAL_START) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) /* Overlap with the dynamic channel monitor range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (addr < QSFP_MONITOR_VAL_START) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) if (addr + len <= QSFP_MONITOR_VAL_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) len = addr + len - QSFP_MONITOR_VAL_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) len = QSFP_MONITOR_RANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) offset = QSFP_MONITOR_VAL_START - addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) addr = QSFP_MONITOR_VAL_START;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) } else if (addr == QSFP_MONITOR_VAL_START) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (addr + len > QSFP_MONITOR_VAL_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) len = QSFP_MONITOR_RANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (addr + len > QSFP_MONITOR_VAL_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) len = QSFP_MONITOR_VAL_END - addr + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) /* Refresh the values of the dynamic monitors from the cable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) ret = one_qsfp_read(ppd, dd->hfi1_id, addr, data + offset, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) if (ret != len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) ret = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) goto set_zeroes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) set_zeroes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) memset(data, 0, excess_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) static const char *pwr_codes[8] = {"N/AW",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) "1.5W",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) "2.0W",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) "2.5W",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) "3.5W",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) "4.0W",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) "4.5W",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) "5.0W"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) int qsfp_dump(struct hfi1_pportdata *ppd, char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) u8 *cache = &ppd->qsfp_info.cache[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) u8 bin_buff[QSFP_DUMP_CHUNK];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) char lenstr[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) int sofar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) int bidx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) u8 *atten = &cache[QSFP_ATTEN_OFFS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) u8 *vendor_oui = &cache[QSFP_VOUI_OFFS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) u8 power_byte = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) sofar = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) lenstr[0] = ' ';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) lenstr[1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (ppd->qsfp_info.cache_valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) if (QSFP_IS_CU(cache[QSFP_MOD_TECH_OFFS]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) snprintf(lenstr, sizeof(lenstr), "%dM ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) cache[QSFP_MOD_LEN_OFFS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) power_byte = cache[QSFP_MOD_PWR_OFFS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) sofar += scnprintf(buf + sofar, len - sofar, "PWR:%.3sW\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) pwr_codes[get_qsfp_power_class(power_byte)]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) sofar += scnprintf(buf + sofar, len - sofar, "TECH:%s%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) lenstr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) hfi1_qsfp_devtech[(cache[QSFP_MOD_TECH_OFFS]) >> 4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) sofar += scnprintf(buf + sofar, len - sofar, "Vendor:%.*s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) QSFP_VEND_LEN, &cache[QSFP_VEND_OFFS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) sofar += scnprintf(buf + sofar, len - sofar, "OUI:%06X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) QSFP_OUI(vendor_oui));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) sofar += scnprintf(buf + sofar, len - sofar, "Part#:%.*s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) QSFP_PN_LEN, &cache[QSFP_PN_OFFS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) sofar += scnprintf(buf + sofar, len - sofar, "Rev:%.*s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) QSFP_REV_LEN, &cache[QSFP_REV_OFFS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (QSFP_IS_CU(cache[QSFP_MOD_TECH_OFFS]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) sofar += scnprintf(buf + sofar, len - sofar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) "Atten:%d, %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) QSFP_ATTEN_SDR(atten),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) QSFP_ATTEN_DDR(atten));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) sofar += scnprintf(buf + sofar, len - sofar, "Serial:%.*s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) QSFP_SN_LEN, &cache[QSFP_SN_OFFS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) sofar += scnprintf(buf + sofar, len - sofar, "Date:%.*s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) QSFP_DATE_LEN, &cache[QSFP_DATE_OFFS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) sofar += scnprintf(buf + sofar, len - sofar, "Lot:%.*s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) QSFP_LOT_LEN, &cache[QSFP_LOT_OFFS]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) while (bidx < QSFP_DEFAULT_HDR_CNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) int iidx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) memcpy(bin_buff, &cache[bidx], QSFP_DUMP_CHUNK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) for (iidx = 0; iidx < QSFP_DUMP_CHUNK; ++iidx) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) sofar += scnprintf(buf + sofar, len - sofar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) " %02X", bin_buff[iidx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) sofar += scnprintf(buf + sofar, len - sofar, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) bidx += QSFP_DUMP_CHUNK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return sofar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }