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