drivers/sbus/char/bbc_i2c.c

Source file repositories/reference/linux-study-clean/drivers/sbus/char/bbc_i2c.c

File Facts

System
Linux kernel
Corpus path
drivers/sbus/char/bbc_i2c.c
Extension
.c
Size
9705 bytes
Lines
423
Domain
Driver Families
Bucket
drivers/sbus
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 (bp->devs[i].device == op) {
			bp->devs[i].client_claimed = val;
			return;
		}
	}
}

#define claim_device(BP,ECHILD)		set_device_claimage(BP,ECHILD,1)
#define release_device(BP,ECHILD)	set_device_claimage(BP,ECHILD,0)

struct platform_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index)
{
	struct platform_device *op = NULL;
	int curidx = 0, i;

	for (i = 0; i < NUM_CHILDREN; i++) {
		if (!(op = bp->devs[i].device))
			break;
		if (curidx == index)
			goto out;
		op = NULL;
		curidx++;
	}

out:
	if (curidx == index)
		return op;
	return NULL;
}

struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct platform_device *op)
{
	struct bbc_i2c_client *client;
	const u32 *reg;

	client = kzalloc_obj(*client);
	if (!client)
		return NULL;
	client->bp = bp;
	client->op = op;

	reg = of_get_property(op->dev.of_node, "reg", NULL);
	if (!reg) {
		kfree(client);
		return NULL;
	}

	client->bus = reg[0];
	client->address = reg[1];

	claim_device(bp, op);

	return client;
}

void bbc_i2c_detach(struct bbc_i2c_client *client)
{
	struct bbc_i2c_bus *bp = client->bp;
	struct platform_device *op = client->op;

	release_device(bp, op);
	kfree(client);
}

static int wait_for_pin(struct bbc_i2c_bus *bp, u8 *status)
{
	DECLARE_WAITQUEUE(wait, current);
	int limit = 32;
	int ret = 1;

	bp->waiting = 1;
	add_wait_queue(&bp->wq, &wait);
	while (limit-- > 0) {
		long val;

		val = wait_event_interruptible_timeout(
				bp->wq,
				(((*status = readb(bp->i2c_control_regs + 0))
				  & I2C_PCF_PIN) == 0),
				msecs_to_jiffies(250));
		if (val > 0) {
			ret = 0;
			break;
		}
	}
	remove_wait_queue(&bp->wq, &wait);
	bp->waiting = 0;

	return ret;
}

Annotation

Implementation Notes