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_e810t(hw, ICE_PCA9575_P0_IN, &data); 401 if (err || !!(data & ICE_E810T_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 } 413