drivers/net/ethernet/intel/ice/ice_gnss.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/intel/ice/ice_gnss.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/intel/ice/ice_gnss.c
Extension
.c
Size
9507 bytes
Lines
404
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2021-2022, Intel Corporation. */

#include "ice.h"
#include "ice_lib.h"

/**
 * ice_gnss_do_write - Write data to internal GNSS receiver
 * @pf: board private structure
 * @buf: command buffer
 * @size: command buffer size
 *
 * Write UBX command data to the GNSS receiver
 *
 * Return:
 * * number of bytes written - success
 * * negative - error code
 */
static int
ice_gnss_do_write(struct ice_pf *pf, const unsigned char *buf, unsigned int size)
{
	struct ice_aqc_link_topo_addr link_topo;
	struct ice_hw *hw = &pf->hw;
	unsigned int offset = 0;
	int err = 0;

	memset(&link_topo, 0, sizeof(struct ice_aqc_link_topo_addr));
	link_topo.topo_params.index = ICE_E810T_GNSS_I2C_BUS;
	link_topo.topo_params.node_type_ctx |=
		FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M,
			   ICE_AQC_LINK_TOPO_NODE_CTX_OVERRIDE);

	/* It's not possible to write a single byte to u-blox.
	 * Write all bytes in a loop until there are 6 or less bytes left. If
	 * there are exactly 6 bytes left, the last write would be only a byte.
	 * In this case, do 4+2 bytes writes instead of 5+1. Otherwise, do the
	 * last 2 to 5 bytes write.
	 */
	while (size - offset > ICE_GNSS_UBX_WRITE_BYTES + 1) {
		err = ice_aq_write_i2c(hw, link_topo, ICE_GNSS_UBX_I2C_BUS_ADDR,
				       cpu_to_le16(buf[offset]),
				       ICE_MAX_I2C_WRITE_BYTES,
				       &buf[offset + 1], NULL);
		if (err)
			goto err_out;

		offset += ICE_GNSS_UBX_WRITE_BYTES;
	}

	/* Single byte would be written. Write 4 bytes instead of 5. */
	if (size - offset == ICE_GNSS_UBX_WRITE_BYTES + 1) {
		err = ice_aq_write_i2c(hw, link_topo, ICE_GNSS_UBX_I2C_BUS_ADDR,
				       cpu_to_le16(buf[offset]),
				       ICE_MAX_I2C_WRITE_BYTES - 1,
				       &buf[offset + 1], NULL);
		if (err)
			goto err_out;

		offset += ICE_GNSS_UBX_WRITE_BYTES - 1;
	}

	/* Do the last write, 2 to 5 bytes. */
	err = ice_aq_write_i2c(hw, link_topo, ICE_GNSS_UBX_I2C_BUS_ADDR,
			       cpu_to_le16(buf[offset]), size - offset - 1,
			       &buf[offset + 1], NULL);
	if (err)
		goto err_out;

	return size;

err_out:
	dev_err(ice_pf_to_dev(pf), "GNSS failed to write, offset=%u, size=%u, err=%d\n",
		offset, size, err);

	return err;
}

/**
 * ice_gnss_read - Read data from internal GNSS module
 * @work: GNSS read work structure
 *
 * Read the data from internal GNSS receiver, write it to gnss_dev.
 */
static void ice_gnss_read(struct kthread_work *work)
{
	struct gnss_serial *gnss = container_of(work, struct gnss_serial,
						read_work.work);
	unsigned long delay = ICE_GNSS_POLL_DATA_DELAY_TIME;
	unsigned int i, bytes_read, data_len, count;
	struct ice_aqc_link_topo_addr link_topo;

Annotation

Implementation Notes