drivers/misc/mei/vsc-tp.c

Source file repositories/reference/linux-study-clean/drivers/misc/mei/vsc-tp.c

File Facts

System
Linux kernel
Corpus path
drivers/misc/mei/vsc-tp.c
Extension
.c
Size
14552 bytes
Lines
578
Domain
Driver Families
Bucket
drivers/misc
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

struct vsc_tp_packet_hdr {
	__u8 sync;
	__u8 cmd;
	__le16 len;
	__le32 seq;
};

struct vsc_tp_packet {
	struct vsc_tp_packet_hdr hdr;
	__u8 buf[VSC_TP_MAX_XFER_SIZE - sizeof(struct vsc_tp_packet_hdr)];
};

struct vsc_tp {
	/* do the actual data transfer */
	struct spi_device *spi;

	/* bind with mei framework */
	struct platform_device *pdev;

	struct gpio_desc *wakeuphost;
	struct gpio_desc *resetfw;
	struct gpio_desc *wakeupfw;

	/* command sequence number */
	u32 seq;

	/* command buffer */
	struct vsc_tp_packet *tx_buf;
	struct vsc_tp_packet *rx_buf;

	atomic_t assert_cnt;
	wait_queue_head_t xfer_wait;
	struct work_struct event_work;

	vsc_tp_event_cb_t event_notify;
	void *event_notify_context;
	struct mutex event_notify_mutex;	/* protects event_notify + context */
	struct mutex mutex;			/* protects command download */
};

/* GPIO resources */
static const struct acpi_gpio_params wakeuphost_gpio = { 0, 0, false };
static const struct acpi_gpio_params wakeuphostint_gpio = { 1, 0, false };
static const struct acpi_gpio_params resetfw_gpio = { 2, 0, false };
static const struct acpi_gpio_params wakeupfw = { 3, 0, false };

static const struct acpi_gpio_mapping vsc_tp_acpi_gpios[] = {
	{ "wakeuphost-gpios", &wakeuphost_gpio, 1 },
	{ "wakeuphostint-gpios", &wakeuphostint_gpio, 1 },
	{ "resetfw-gpios", &resetfw_gpio, 1 },
	{ "wakeupfw-gpios", &wakeupfw, 1 },
	{}
};

static irqreturn_t vsc_tp_isr(int irq, void *data)
{
	struct vsc_tp *tp = data;

	atomic_inc(&tp->assert_cnt);

	wake_up(&tp->xfer_wait);

	schedule_work(&tp->event_work);

	return IRQ_HANDLED;
}

static void vsc_tp_event_work(struct work_struct *work)
{
	struct vsc_tp *tp = container_of(work, struct vsc_tp, event_work);

	guard(mutex)(&tp->event_notify_mutex);

	if (tp->event_notify)
		tp->event_notify(tp->event_notify_context);
}

/* wakeup firmware and wait for response */
static int vsc_tp_wakeup_request(struct vsc_tp *tp)
{
	int ret;

	gpiod_set_value_cansleep(tp->wakeupfw, 0);

	ret = wait_event_timeout(tp->xfer_wait,
				 atomic_read(&tp->assert_cnt),
				 VSC_TP_WAIT_FW_POLL_TIMEOUT);
	if (!ret)
		return -ETIMEDOUT;

Annotation

Implementation Notes