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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c
Extension
.c
Size
6765 bytes
Lines
265
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 ((bus->i2c.algo == &i2c_bit_algo) && (info[i].udelay != 0)) {
			struct i2c_algo_bit_data *algo = bus->i2c.algo_data;
			BUS_DBG(bus, "%dms delay instead of %dms",
				     info[i].udelay, algo->udelay);
			orig_udelay = algo->udelay;
			algo->udelay = info[i].udelay;
		}

		if (nvkm_probe_i2c(&bus->i2c, info[i].dev.addr) &&
		    (!match || match(bus, &info[i].dev, data))) {
			BUS_DBG(bus, "detected %s: %s",
				what, info[i].dev.type);
			return i;
		}

		if (orig_udelay) {
			struct i2c_algo_bit_data *algo = bus->i2c.algo_data;
			algo->udelay = orig_udelay;
		}
	}

	BUS_DBG(bus, "no devices found.");
	return -ENODEV;
}

void
nvkm_i2c_bus_del(struct nvkm_i2c_bus **pbus)
{
	struct nvkm_i2c_bus *bus = *pbus;
	if (bus && !WARN_ON(!bus->func)) {
		BUS_TRACE(bus, "dtor");
		list_del(&bus->head);
		i2c_del_adapter(&bus->i2c);
		kfree(bus->i2c.algo_data);
		kfree(*pbus);
		*pbus = NULL;
	}
}

int
nvkm_i2c_bus_ctor(const struct nvkm_i2c_bus_func *func,
		  struct nvkm_i2c_pad *pad, int id,
		  struct nvkm_i2c_bus *bus)
{
	struct nvkm_device *device = pad->i2c->subdev.device;
	struct i2c_algo_bit_data *bit;
#ifndef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT
	const bool internal = false;
#else
	const bool internal = true;
#endif
	int ret;

	bus->func = func;
	bus->pad = pad;
	bus->id = id;
	mutex_init(&bus->mutex);
	list_add_tail(&bus->head, &pad->i2c->bus);
	BUS_TRACE(bus, "ctor");

	snprintf(bus->i2c.name, sizeof(bus->i2c.name), "nvkm-%s-bus-%04x",
		 dev_name(device->dev), id);
	bus->i2c.owner = THIS_MODULE;
	bus->i2c.dev.parent = device->dev;

	if ( bus->func->drive_scl &&
	    !nvkm_boolopt(device->cfgopt, "NvI2C", internal)) {
		if (!(bit = kzalloc_obj(*bit)))
			return -ENOMEM;
		bit->udelay = 10;
		bit->timeout = usecs_to_jiffies(2200);
		bit->data = bus;
		bit->pre_xfer = nvkm_i2c_bus_pre_xfer;
		bit->post_xfer = nvkm_i2c_bus_post_xfer;
		bit->setscl = nvkm_i2c_bus_setscl;
		bit->setsda = nvkm_i2c_bus_setsda;
		bit->getscl = nvkm_i2c_bus_getscl;
		bit->getsda = nvkm_i2c_bus_getsda;
		bus->i2c.algo_data = bit;
		ret = i2c_bit_add_bus(&bus->i2c);
	} else {
		bus->i2c.algo = &nvkm_i2c_bus_algo;
		ret = i2c_add_adapter(&bus->i2c);
	}

	return ret;
}

int
nvkm_i2c_bus_new_(const struct nvkm_i2c_bus_func *func,

Annotation

Implementation Notes