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 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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 */ 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