drivers/platform/chrome/cros_hps_i2c.c

Source file repositories/reference/linux-study-clean/drivers/platform/chrome/cros_hps_i2c.c

File Facts

System
Linux kernel
Corpus path
drivers/platform/chrome/cros_hps_i2c.c
Extension
.c
Size
4067 bytes
Lines
163
Domain
Driver Families
Bucket
drivers/platform
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations hps_fops = {
	.owner = THIS_MODULE,
	.open = hps_open,
	.release = hps_release,
};

static int hps_i2c_probe(struct i2c_client *client)
{
	struct hps_drvdata *hps;
	int ret;

	hps = devm_kzalloc(&client->dev, sizeof(*hps), GFP_KERNEL);
	if (!hps)
		return -ENOMEM;

	hps->misc_device.parent = &client->dev;
	hps->misc_device.minor = MISC_DYNAMIC_MINOR;
	hps->misc_device.name = "cros-hps";
	hps->misc_device.fops = &hps_fops;

	i2c_set_clientdata(client, hps);
	hps->client = client;

	/*
	 * HPS is powered on from firmware before entering the kernel, so we
	 * acquire the line with GPIOD_OUT_HIGH here to preserve the existing
	 * state. The peripheral is powered off after successful probe below.
	 */
	hps->enable_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_HIGH);
	if (IS_ERR(hps->enable_gpio)) {
		ret = PTR_ERR(hps->enable_gpio);
		dev_err(&client->dev, "failed to get enable gpio: %d\n", ret);
		return ret;
	}

	ret = misc_register(&hps->misc_device);
	if (ret) {
		dev_err(&client->dev, "failed to initialize misc device: %d\n", ret);
		return ret;
	}

	hps_set_power(hps, false);
	pm_runtime_enable(&client->dev);
	return 0;
}

static void hps_i2c_remove(struct i2c_client *client)
{
	struct hps_drvdata *hps = i2c_get_clientdata(client);

	pm_runtime_disable(&client->dev);
	misc_deregister(&hps->misc_device);

	/*
	 * Re-enable HPS, in order to return it to its default state
	 * (i.e. powered on).
	 */
	hps_set_power(hps, true);
}

static int hps_suspend(struct device *dev)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct hps_drvdata *hps = i2c_get_clientdata(client);

	hps_set_power(hps, false);
	return 0;
}

static int hps_resume(struct device *dev)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct hps_drvdata *hps = i2c_get_clientdata(client);

	hps_set_power(hps, true);
	return 0;
}
static DEFINE_RUNTIME_DEV_PM_OPS(hps_pm_ops, hps_suspend, hps_resume, NULL);

static const struct i2c_device_id hps_i2c_id[] = {
	{ .name = "cros-hps" },
	{ }
};
MODULE_DEVICE_TABLE(i2c, hps_i2c_id);

#ifdef CONFIG_ACPI
static const struct acpi_device_id hps_acpi_id[] = {
	{ HPS_ACPI_ID, 0 },
	{ }
};

Annotation

Implementation Notes