drivers/staging/nvec/nvec.c

Source file repositories/reference/linux-study-clean/drivers/staging/nvec/nvec.c

File Facts

System
Linux kernel
Corpus path
drivers/staging/nvec/nvec.c
Extension
.c
Size
26108 bytes
Lines
970
Domain
Driver Families
Bucket
drivers/staging
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

if (atomic_xchg(&nvec->msg_pool[i].used, 1) == 0) {
			dev_vdbg(nvec->dev, "INFO: Allocate %i\n", i);
			return &nvec->msg_pool[i];
		}
	}

	dev_err(nvec->dev, "Could not allocate %s buffer\n",
		(category == NVEC_MSG_TX) ? "TX" : "RX");

	return NULL;
}

/**
 * nvec_msg_free:
 * @nvec: A &struct nvec_chip
 * @msg:  A message (must be allocated by nvec_msg_alloc() and belong to @nvec)
 *
 * Free the given message
 */
void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg)
{
	if (msg != &nvec->tx_scratch)
		dev_vdbg(nvec->dev, "INFO: Free %ti\n", msg - nvec->msg_pool);
	atomic_set(&msg->used, 0);
}
EXPORT_SYMBOL_GPL(nvec_msg_free);

/**
 * nvec_msg_is_event - Return %true if @msg is an event
 * @msg: A message
 */
static bool nvec_msg_is_event(struct nvec_msg *msg)
{
	return msg->data[0] >> 7;
}

/**
 * nvec_msg_size - Get the size of a message
 * @msg: The message to get the size for
 *
 * This only works for received messages, not for outgoing messages.
 */
static size_t nvec_msg_size(struct nvec_msg *msg)
{
	bool is_event = nvec_msg_is_event(msg);
	int event_length = (msg->data[0] & 0x60) >> 5;

	/* for variable size, payload size in byte 1 + count (1) + cmd (1) */
	if (!is_event || event_length == NVEC_VAR_SIZE)
		return (msg->pos || msg->size) ? (msg->data[1] + 2) : 0;
	else if (event_length == NVEC_2BYTES)
		return 2;
	else if (event_length == NVEC_3BYTES)
		return 3;
	return 0;
}

/**
 * nvec_gpio_set_value - Set the GPIO value
 * @nvec: A &struct nvec_chip
 * @value: The value to write (0 or 1)
 *
 * Like gpio_set_value(), but generating debugging information
 */
static void nvec_gpio_set_value(struct nvec_chip *nvec, int value)
{
	dev_dbg(nvec->dev, "GPIO changed from %u to %u\n",
		gpiod_get_value(nvec->gpiod), value);
	gpiod_set_value(nvec->gpiod, value);
}

/**
 * nvec_write_async - Asynchronously write a message to NVEC
 * @nvec: An nvec_chip instance
 * @data: The message data, starting with the request type
 * @size: The size of @data
 *
 * Queue a single message to be transferred to the embedded controller
 * and return immediately.
 *
 * Returns: 0 on success, a negative error code on failure. If a failure
 * occurred, the nvec driver may print an error.
 */
int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data,
		     short size)
{
	struct nvec_msg *msg;
	unsigned long flags;

	msg = nvec_msg_alloc(nvec, NVEC_MSG_TX);

Annotation

Implementation Notes