xref: /linux/drivers/net/ethernet/intel/ice/ice_gnss.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2021-2022, Intel Corporation. */
3 
4 #include "ice.h"
5 #include <linux/slab.h>
6 #include "ice_lib.h"
7 
8 /**
9  * ice_gnss_do_write - Write data to internal GNSS receiver
10  * @pf: board private structure
11  * @buf: command buffer
12  * @size: command buffer size
13  *
14  * Write UBX command data to the GNSS receiver
15  *
16  * Return:
17  * * number of bytes written - success
18  * * negative - error code
19  */
20 static int
ice_gnss_do_write(struct ice_pf * pf,const unsigned char * buf,unsigned int size)21 ice_gnss_do_write(struct ice_pf *pf, const unsigned char *buf, unsigned int size)
22 {
23 	struct ice_aqc_link_topo_addr link_topo;
24 	struct ice_hw *hw = &pf->hw;
25 	unsigned int offset = 0;
26 	int err = 0;
27 
28 	memset(&link_topo, 0, sizeof(struct ice_aqc_link_topo_addr));
29 	link_topo.topo_params.index = ICE_E810T_GNSS_I2C_BUS;
30 	link_topo.topo_params.node_type_ctx |=
31 		FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M,
32 			   ICE_AQC_LINK_TOPO_NODE_CTX_OVERRIDE);
33 
34 	/* It's not possible to write a single byte to u-blox.
35 	 * Write all bytes in a loop until there are 6 or less bytes left. If
36 	 * there are exactly 6 bytes left, the last write would be only a byte.
37 	 * In this case, do 4+2 bytes writes instead of 5+1. Otherwise, do the
38 	 * last 2 to 5 bytes write.
39 	 */
40 	while (size - offset > ICE_GNSS_UBX_WRITE_BYTES + 1) {
41 		err = ice_aq_write_i2c(hw, link_topo, ICE_GNSS_UBX_I2C_BUS_ADDR,
42 				       cpu_to_le16(buf[offset]),
43 				       ICE_MAX_I2C_WRITE_BYTES,
44 				       &buf[offset + 1], NULL);
45 		if (err)
46 			goto err_out;
47 
48 		offset += ICE_GNSS_UBX_WRITE_BYTES;
49 	}
50 
51 	/* Single byte would be written. Write 4 bytes instead of 5. */
52 	if (size - offset == ICE_GNSS_UBX_WRITE_BYTES + 1) {
53 		err = ice_aq_write_i2c(hw, link_topo, ICE_GNSS_UBX_I2C_BUS_ADDR,
54 				       cpu_to_le16(buf[offset]),
55 				       ICE_MAX_I2C_WRITE_BYTES - 1,
56 				       &buf[offset + 1], NULL);
57 		if (err)
58 			goto err_out;
59 
60 		offset += ICE_GNSS_UBX_WRITE_BYTES - 1;
61 	}
62 
63 	/* Do the last write, 2 to 5 bytes. */
64 	err = ice_aq_write_i2c(hw, link_topo, ICE_GNSS_UBX_I2C_BUS_ADDR,
65 			       cpu_to_le16(buf[offset]), size - offset - 1,
66 			       &buf[offset + 1], NULL);
67 	if (err)
68 		goto err_out;
69 
70 	return size;
71 
72 err_out:
73 	dev_err(ice_pf_to_dev(pf), "GNSS failed to write, offset=%u, size=%u, err=%d\n",
74 		offset, size, err);
75 
76 	return err;
77 }
78 
79 /**
80  * ice_gnss_read - Read data from internal GNSS module
81  * @work: GNSS read work structure
82  *
83  * Read the data from internal GNSS receiver, write it to gnss_dev.
84  */
ice_gnss_read(struct kthread_work * work)85 static void ice_gnss_read(struct kthread_work *work)
86 {
87 	struct gnss_serial *gnss = container_of(work, struct gnss_serial,
88 						read_work.work);
89 	unsigned long delay = ICE_GNSS_POLL_DATA_DELAY_TIME;
90 	unsigned int i, bytes_read, data_len, count;
91 	struct ice_aqc_link_topo_addr link_topo;
92 	struct ice_pf *pf;
93 	struct ice_hw *hw;
94 	__be16 data_len_b;
95 	char *buf = NULL;
96 	u8 i2c_params;
97 	int err = 0;
98 
99 	pf = gnss->back;
100 	if (!pf || !test_bit(ICE_FLAG_GNSS, pf->flags))
101 		return;
102 
103 	hw = &pf->hw;
104 
105 	memset(&link_topo, 0, sizeof(struct ice_aqc_link_topo_addr));
106 	link_topo.topo_params.index = ICE_E810T_GNSS_I2C_BUS;
107 	link_topo.topo_params.node_type_ctx |=
108 		FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M,
109 			   ICE_AQC_LINK_TOPO_NODE_CTX_OVERRIDE);
110 
111 	i2c_params = ICE_GNSS_UBX_DATA_LEN_WIDTH |
112 		     ICE_AQC_I2C_USE_REPEATED_START;
113 
114 	err = ice_aq_read_i2c(hw, link_topo, ICE_GNSS_UBX_I2C_BUS_ADDR,
115 			      cpu_to_le16(ICE_GNSS_UBX_DATA_LEN_H),
116 			      i2c_params, (u8 *)&data_len_b, NULL);
117 	if (err)
118 		goto requeue;
119 
120 	data_len = be16_to_cpu(data_len_b);
121 	if (data_len == 0 || data_len == U16_MAX)
122 		goto requeue;
123 
124 	/* The u-blox has data_len bytes for us to read */
125 
126 	data_len = min_t(typeof(data_len), data_len, PAGE_SIZE);
127 
128 	buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
129 	if (!buf) {
130 		err = -ENOMEM;
131 		goto requeue;
132 	}
133 
134 	/* Read received data */
135 	for (i = 0; i < data_len; i += bytes_read) {
136 		unsigned int bytes_left = data_len - i;
137 
138 		bytes_read = min_t(typeof(bytes_left), bytes_left,
139 				   ICE_MAX_I2C_DATA_SIZE);
140 
141 		err = ice_aq_read_i2c(hw, link_topo, ICE_GNSS_UBX_I2C_BUS_ADDR,
142 				      cpu_to_le16(ICE_GNSS_UBX_EMPTY_DATA),
143 				      bytes_read, &buf[i], NULL);
144 		if (err)
145 			goto free_buf;
146 	}
147 
148 	count = gnss_insert_raw(pf->gnss_dev, buf, i);
149 	if (count != i)
150 		dev_warn(ice_pf_to_dev(pf),
151 			 "gnss_insert_raw ret=%d size=%d\n",
152 			 count, i);
153 	delay = ICE_GNSS_TIMER_DELAY_TIME;
154 free_buf:
155 	kfree(buf);
156 requeue:
157 	kthread_queue_delayed_work(gnss->kworker, &gnss->read_work, delay);
158 	if (err)
159 		dev_dbg(ice_pf_to_dev(pf), "GNSS failed to read err=%d\n", err);
160 }
161 
162 /**
163  * ice_gnss_struct_init - Initialize GNSS receiver
164  * @pf: Board private structure
165  *
166  * Initialize GNSS structures and workers.
167  *
168  * Return:
169  * * pointer to initialized gnss_serial struct - success
170  * * NULL - error
171  */
ice_gnss_struct_init(struct ice_pf * pf)172 static struct gnss_serial *ice_gnss_struct_init(struct ice_pf *pf)
173 {
174 	struct device *dev = ice_pf_to_dev(pf);
175 	struct kthread_worker *kworker;
176 	struct gnss_serial *gnss;
177 
178 	gnss = kzalloc_obj(*gnss);
179 	if (!gnss)
180 		return NULL;
181 
182 	gnss->back = pf;
183 	pf->gnss_serial = gnss;
184 
185 	kthread_init_delayed_work(&gnss->read_work, ice_gnss_read);
186 	kworker = kthread_run_worker(0, "ice-gnss-%s", dev_name(dev));
187 	if (IS_ERR(kworker)) {
188 		kfree(gnss);
189 		return NULL;
190 	}
191 
192 	gnss->kworker = kworker;
193 
194 	return gnss;
195 }
196 
197 /**
198  * ice_gnss_open - Open GNSS device
199  * @gdev: pointer to the gnss device struct
200  *
201  * Open GNSS device and start filling the read buffer for consumer.
202  *
203  * Return:
204  * * 0 - success
205  * * negative - error code
206  */
ice_gnss_open(struct gnss_device * gdev)207 static int ice_gnss_open(struct gnss_device *gdev)
208 {
209 	struct ice_pf *pf = gnss_get_drvdata(gdev);
210 	struct gnss_serial *gnss;
211 
212 	if (!pf)
213 		return -EFAULT;
214 
215 	if (!test_bit(ICE_FLAG_GNSS, pf->flags))
216 		return -EFAULT;
217 
218 	gnss = pf->gnss_serial;
219 	if (!gnss)
220 		return -ENODEV;
221 
222 	kthread_queue_delayed_work(gnss->kworker, &gnss->read_work, 0);
223 
224 	return 0;
225 }
226 
227 /**
228  * ice_gnss_close - Close GNSS device
229  * @gdev: pointer to the gnss device struct
230  *
231  * Close GNSS device, cancel worker, stop filling the read buffer.
232  */
ice_gnss_close(struct gnss_device * gdev)233 static void ice_gnss_close(struct gnss_device *gdev)
234 {
235 	struct ice_pf *pf = gnss_get_drvdata(gdev);
236 	struct gnss_serial *gnss;
237 
238 	if (!pf)
239 		return;
240 
241 	gnss = pf->gnss_serial;
242 	if (!gnss)
243 		return;
244 
245 	kthread_cancel_delayed_work_sync(&gnss->read_work);
246 }
247 
248 /**
249  * ice_gnss_write - Write to GNSS device
250  * @gdev: pointer to the gnss device struct
251  * @buf: pointer to the user data
252  * @count: size of the buffer to be sent to the GNSS device
253  *
254  * Return:
255  * * number of written bytes - success
256  * * negative - error code
257  */
258 static int
ice_gnss_write(struct gnss_device * gdev,const unsigned char * buf,size_t count)259 ice_gnss_write(struct gnss_device *gdev, const unsigned char *buf,
260 	       size_t count)
261 {
262 	struct ice_pf *pf = gnss_get_drvdata(gdev);
263 	struct gnss_serial *gnss;
264 
265 	/* We cannot write a single byte using our I2C implementation. */
266 	if (count <= 1 || count > ICE_GNSS_TTY_WRITE_BUF)
267 		return -EINVAL;
268 
269 	if (!pf)
270 		return -EFAULT;
271 
272 	if (!test_bit(ICE_FLAG_GNSS, pf->flags))
273 		return -EFAULT;
274 
275 	gnss = pf->gnss_serial;
276 	if (!gnss)
277 		return -ENODEV;
278 
279 	return ice_gnss_do_write(pf, buf, count);
280 }
281 
282 static const struct gnss_operations ice_gnss_ops = {
283 	.open = ice_gnss_open,
284 	.close = ice_gnss_close,
285 	.write_raw = ice_gnss_write,
286 };
287 
288 /**
289  * ice_gnss_register - Register GNSS receiver
290  * @pf: Board private structure
291  *
292  * Allocate and register GNSS receiver in the Linux GNSS subsystem.
293  *
294  * Return:
295  * * 0 - success
296  * * negative - error code
297  */
ice_gnss_register(struct ice_pf * pf)298 static int ice_gnss_register(struct ice_pf *pf)
299 {
300 	struct gnss_device *gdev;
301 	int ret;
302 
303 	gdev = gnss_allocate_device(ice_pf_to_dev(pf));
304 	if (!gdev) {
305 		dev_err(ice_pf_to_dev(pf),
306 			"gnss_allocate_device returns NULL\n");
307 		return -ENOMEM;
308 	}
309 
310 	gdev->ops = &ice_gnss_ops;
311 	gdev->type = GNSS_TYPE_UBX;
312 	gnss_set_drvdata(gdev, pf);
313 	ret = gnss_register_device(gdev);
314 	if (ret) {
315 		dev_err(ice_pf_to_dev(pf), "gnss_register_device err=%d\n",
316 			ret);
317 		gnss_put_device(gdev);
318 	} else {
319 		pf->gnss_dev = gdev;
320 	}
321 
322 	return ret;
323 }
324 
325 /**
326  * ice_gnss_deregister - Deregister GNSS receiver
327  * @pf: Board private structure
328  *
329  * Deregister GNSS receiver from the Linux GNSS subsystem,
330  * release its resources.
331  */
ice_gnss_deregister(struct ice_pf * pf)332 static void ice_gnss_deregister(struct ice_pf *pf)
333 {
334 	if (pf->gnss_dev) {
335 		gnss_deregister_device(pf->gnss_dev);
336 		gnss_put_device(pf->gnss_dev);
337 		pf->gnss_dev = NULL;
338 	}
339 }
340 
341 /**
342  * ice_gnss_init - Initialize GNSS support
343  * @pf: Board private structure
344  */
ice_gnss_init(struct ice_pf * pf)345 void ice_gnss_init(struct ice_pf *pf)
346 {
347 	int ret;
348 
349 	pf->gnss_serial = ice_gnss_struct_init(pf);
350 	if (!pf->gnss_serial)
351 		return;
352 
353 	ret = ice_gnss_register(pf);
354 	if (!ret) {
355 		set_bit(ICE_FLAG_GNSS, pf->flags);
356 		dev_info(ice_pf_to_dev(pf), "GNSS init successful\n");
357 	} else {
358 		ice_gnss_exit(pf);
359 		dev_err(ice_pf_to_dev(pf), "GNSS init failure\n");
360 	}
361 }
362 
363 /**
364  * ice_gnss_exit - Disable GNSS TTY support
365  * @pf: Board private structure
366  */
ice_gnss_exit(struct ice_pf * pf)367 void ice_gnss_exit(struct ice_pf *pf)
368 {
369 	ice_gnss_deregister(pf);
370 	clear_bit(ICE_FLAG_GNSS, pf->flags);
371 
372 	if (pf->gnss_serial) {
373 		struct gnss_serial *gnss = pf->gnss_serial;
374 
375 		kthread_cancel_delayed_work_sync(&gnss->read_work);
376 		kthread_destroy_worker(gnss->kworker);
377 		gnss->kworker = NULL;
378 
379 		kfree(gnss);
380 		pf->gnss_serial = NULL;
381 	}
382 }
383 
384 /**
385  * ice_gnss_is_module_present - Check if GNSS HW is present
386  * @hw: pointer to HW struct
387  *
388  * Return: true when GNSS is present, false otherwise.
389  */
ice_gnss_is_module_present(struct ice_hw * hw)390 bool ice_gnss_is_module_present(struct ice_hw *hw)
391 {
392 	int err;
393 	u8 data;
394 
395 	if (!hw->func_caps.ts_func_info.src_tmr_owned ||
396 	    !ice_is_gps_in_netlist(hw))
397 		return false;
398 
399 	err = ice_read_pca9575_reg(hw, ICE_PCA9575_P0_IN, &data);
400 	if (err || !!(data & ICE_P0_GNSS_PRSNT_N))
401 		return false;
402 
403 	return true;
404 }
405