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