ice_gnss.c 9.5 KB

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