drivers/nfc/st-nci/i2c.c

Source file repositories/reference/linux-study-clean/drivers/nfc/st-nci/i2c.c

File Facts

System
Linux kernel
Corpus path
drivers/nfc/st-nci/i2c.c
Extension
.c
Size
6840 bytes
Lines
294
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 st_nci_i2c_phy {
	struct i2c_client *i2c_dev;
	struct llt_ndlc *ndlc;

	bool irq_active;

	struct gpio_desc *gpiod_reset;

	struct st_nci_se_status se_status;
};

static int st_nci_i2c_enable(void *phy_id)
{
	struct st_nci_i2c_phy *phy = phy_id;

	gpiod_set_value(phy->gpiod_reset, 0);
	usleep_range(10000, 15000);
	gpiod_set_value(phy->gpiod_reset, 1);
	usleep_range(80000, 85000);

	if (phy->ndlc->powered == 0 && phy->irq_active == 0) {
		enable_irq(phy->i2c_dev->irq);
		phy->irq_active = true;
	}

	return 0;
}

static void st_nci_i2c_disable(void *phy_id)
{
	struct st_nci_i2c_phy *phy = phy_id;

	disable_irq_nosync(phy->i2c_dev->irq);
	phy->irq_active = false;
}

/*
 * Writing a frame must not return the number of written bytes.
 * It must return either zero for success, or <0 for error.
 * In addition, it must not alter the skb
 */
static int st_nci_i2c_write(void *phy_id, struct sk_buff *skb)
{
	int r;
	struct st_nci_i2c_phy *phy = phy_id;
	struct i2c_client *client = phy->i2c_dev;

	if (phy->ndlc->hard_fault != 0)
		return phy->ndlc->hard_fault;

	r = i2c_master_send(client, skb->data, skb->len);
	if (r < 0) {  /* Retry, chip was in standby */
		usleep_range(1000, 4000);
		r = i2c_master_send(client, skb->data, skb->len);
	}

	if (r >= 0) {
		if (r != skb->len)
			r = -EREMOTEIO;
		else
			r = 0;
	}

	return r;
}

/*
 * Reads an ndlc frame and returns it in a newly allocated sk_buff.
 * returns:
 * 0 : if received frame is complete
 * -EREMOTEIO : i2c read error (fatal)
 * -EBADMSG : frame was incorrect and discarded
 * -ENOMEM : cannot allocate skb, frame dropped
 */
static int st_nci_i2c_read(struct st_nci_i2c_phy *phy,
				 struct sk_buff **skb)
{
	int r;
	u8 len;
	u8 buf[ST_NCI_I2C_MAX_SIZE];
	struct i2c_client *client = phy->i2c_dev;

	r = i2c_master_recv(client, buf, ST_NCI_I2C_MIN_SIZE);
	if (r < 0) {  /* Retry, chip was in standby */
		usleep_range(1000, 4000);
		r = i2c_master_recv(client, buf, ST_NCI_I2C_MIN_SIZE);
	}

	if (r != ST_NCI_I2C_MIN_SIZE)
		return -EREMOTEIO;

Annotation

Implementation Notes