Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }