drivers/nfc/nfcmrvl/spi.c

Source file repositories/reference/linux-study-clean/drivers/nfc/nfcmrvl/spi.c

File Facts

System
Linux kernel
Corpus path
drivers/nfc/nfcmrvl/spi.c
Extension
.c
Size
5132 bytes
Lines
211
Domain
Driver Families
Bucket
drivers/nfc
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

struct nfcmrvl_spi_drv_data {
	unsigned long flags;
	struct spi_device *spi;
	struct nci_spi *nci_spi;
	struct completion handshake_completion;
	struct nfcmrvl_private *priv;
};

static irqreturn_t nfcmrvl_spi_int_irq_thread_fn(int irq, void *drv_data_ptr)
{
	struct nfcmrvl_spi_drv_data *drv_data = drv_data_ptr;
	struct sk_buff *skb;

	/*
	 * Special case where we are waiting for SPI_INT deassertion to start a
	 * transfer.
	 */
	if (test_and_clear_bit(SPI_WAIT_HANDSHAKE, &drv_data->flags)) {
		complete(&drv_data->handshake_completion);
		return IRQ_HANDLED;
	}

	/* Normal case, SPI_INT deasserted by slave to trigger a master read */

	skb = nci_spi_read(drv_data->nci_spi);
	if (!skb) {
		nfc_err(&drv_data->spi->dev, "failed to read spi packet");
		return IRQ_HANDLED;
	}

	if (nfcmrvl_nci_recv_frame(drv_data->priv, skb) < 0)
		nfc_err(&drv_data->spi->dev, "corrupted RX packet");

	return IRQ_HANDLED;
}

static int nfcmrvl_spi_nci_open(struct nfcmrvl_private *priv)
{
	return 0;
}

static int nfcmrvl_spi_nci_close(struct nfcmrvl_private *priv)
{
	return 0;
}

static int nfcmrvl_spi_nci_send(struct nfcmrvl_private *priv,
				struct sk_buff *skb)
{
	struct nfcmrvl_spi_drv_data *drv_data = priv->drv_data;
	int err;

	/* Reinit completion for slave handshake */
	reinit_completion(&drv_data->handshake_completion);
	set_bit(SPI_WAIT_HANDSHAKE, &drv_data->flags);

	/*
	 * Append a dummy byte at the end of SPI frame. This is due to a
	 * specific DMA implementation in the controller
	 */
	skb_put(skb, 1);

	/* Send the SPI packet */
	err = nci_spi_send(drv_data->nci_spi, &drv_data->handshake_completion,
			   skb);
	if (err)
		nfc_err(priv->dev, "spi_send failed %d", err);

	return err;
}

static void nfcmrvl_spi_nci_update_config(struct nfcmrvl_private *priv,
					  const void *param)
{
	struct nfcmrvl_spi_drv_data *drv_data = priv->drv_data;
	const struct nfcmrvl_fw_spi_config *config = param;

	drv_data->nci_spi->xfer_speed_hz = config->clk;
}

static const struct nfcmrvl_if_ops spi_ops = {
	.nci_open = nfcmrvl_spi_nci_open,
	.nci_close = nfcmrvl_spi_nci_close,
	.nci_send = nfcmrvl_spi_nci_send,
	.nci_update_config = nfcmrvl_spi_nci_update_config,
};

static int nfcmrvl_spi_parse_dt(struct device_node *node,
				struct nfcmrvl_platform_data *pdata)
{

Annotation

Implementation Notes