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