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