drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
Extension
.c
Size
10363 bytes
Lines
418
Domain
Driver Families
Bucket
drivers/gpu
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

if (i2c && ver >= 0x30) {
			u8 auxidx = nvbios_rd08(bios, i2c + 4);
			if (id == NVKM_I2C_BUS_PRI)
				id = NVKM_I2C_BUS_CCB((auxidx & 0x0f) >> 0);
			else
				id = NVKM_I2C_BUS_CCB((auxidx & 0xf0) >> 4);
		} else {
			id = NVKM_I2C_BUS_CCB(2);
		}
	}

	list_for_each_entry(bus, &i2c->bus, head) {
		if (bus->id == id)
			return bus;
	}

	return NULL;
}

struct nvkm_i2c_aux *
nvkm_i2c_aux_find(struct nvkm_i2c *i2c, int id)
{
	struct nvkm_i2c_aux *aux;

	list_for_each_entry(aux, &i2c->aux, head) {
		if (aux->id == id)
			return aux;
	}

	return NULL;
}

static void
nvkm_i2c_intr_fini(struct nvkm_event *event, int type, int id)
{
	struct nvkm_i2c *i2c = container_of(event, typeof(*i2c), event);
	struct nvkm_i2c_aux *aux = nvkm_i2c_aux_find(i2c, id);
	if (aux)
		i2c->func->aux_mask(i2c, type, aux->intr, 0);
}

static void
nvkm_i2c_intr_init(struct nvkm_event *event, int type, int id)
{
	struct nvkm_i2c *i2c = container_of(event, typeof(*i2c), event);
	struct nvkm_i2c_aux *aux = nvkm_i2c_aux_find(i2c, id);
	if (aux)
		i2c->func->aux_mask(i2c, type, aux->intr, aux->intr);
}

static const struct nvkm_event_func
nvkm_i2c_intr_func = {
	.init = nvkm_i2c_intr_init,
	.fini = nvkm_i2c_intr_fini,
};

static void
nvkm_i2c_intr(struct nvkm_subdev *subdev)
{
	struct nvkm_i2c *i2c = nvkm_i2c(subdev);
	struct nvkm_i2c_aux *aux;
	u32 hi, lo, rq, tx;

	if (!i2c->func->aux_stat)
		return;

	i2c->func->aux_stat(i2c, &hi, &lo, &rq, &tx);
	if (!hi && !lo && !rq && !tx)
		return;

	list_for_each_entry(aux, &i2c->aux, head) {
		u32 mask = 0;
		if (hi & aux->intr) mask |= NVKM_I2C_PLUG;
		if (lo & aux->intr) mask |= NVKM_I2C_UNPLUG;
		if (rq & aux->intr) mask |= NVKM_I2C_IRQ;
		if (tx & aux->intr) mask |= NVKM_I2C_DONE;
		if (mask)
			nvkm_event_ntfy(&i2c->event, aux->id, mask);
	}
}

static int
nvkm_i2c_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
{
	struct nvkm_i2c *i2c = nvkm_i2c(subdev);
	struct nvkm_i2c_pad *pad;
	struct nvkm_i2c_bus *bus;
	struct nvkm_i2c_aux *aux;
	u32 mask;

Annotation

Implementation Notes