**Approach (high level)**1. Define a clear Device Tree binding (YAML) with required/optional properties and types.2. Add compatible string to DT node and overlays.3. In driver probe parse DT properties, allocate resources with devm_ APIs, register with i2c subsystem, enable runtime PM and implement suspend/resume.4. Test with overlays and runtime/power-cycle tests on dev board.**Example DT binding (bindings/myvendor,my-i2c-peripheral.yaml)**yaml
title: "MyVendor I2C peripheral"
properties:
compatible:
const: "myvendor,my-i2c-peripheral"
reg:
description: "I2C address"
type: integer
gpios:
description: "Reset GPIO"
type: phandle
clocks:
description: "Optional clock"
type: phandle
required:
- compatible
- reg
**Device Tree node / overlay snippet**dts
mydevice@50 {
compatible = "myvendor,my-i2c-peripheral";
reg = <0x50>;
reset-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
clocks = <&clk IMX8MM_CLK>;
};
**Probe skeleton (key parts)**c
static int my_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct my_data *d;
int ret;
d = devm_kzalloc(dev, sizeof(*d), GFP_KERNEL);
d->client = client;
ret = of_property_read_u32(dev->of_node, "reg", &d->i2c_addr);
if (ret) return ret;
d->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(d->reset)) return PTR_ERR(d->reset);
d->clk = devm_clk_get_optional(dev, NULL);
if (IS_ERR(d->clk)) return PTR_ERR(d->clk);
d->vdd = devm_regulator_get_optional(dev, "vdd");
if (IS_ERR(d->vdd)) return PTR_ERR(d->vdd);
if (d->vdd) {
ret = regulator_enable(d->vdd);
if (ret) return ret;
}
pm_runtime_enable(dev);
ret = pm_runtime_get_sync(dev);
if (ret < 0) goto pm_disable;
/* device init via I2C transactions using client */
pm_runtime_put(dev);
return 0;
pm_disable:
pm_runtime_disable(dev);
return ret;
}
**Key points & reasoning**- Use of_property_read_* (u32/u32_array/string) to validate DT and fail probe early when required props missing.- Use devm_ APIs (devm_kzalloc, devm_gpiod_get*, devm_clk_get*, devm_regulator_get*) so cleanup is automatic on driver remove/fail.- Register driver with i2c subsystem via i2c_driver struct (probe/remove, id_table, of_match_table).- Runtime PM: call pm_runtime_enable in probe, use pm_runtime_get_sync/put for active operations and pm_runtime_disable on remove. Also implement suspend/resume ops if needed.**Testing strategy**- Create device-tree overlays for different configurations (clock/no-clock, different GPIOs).- Bootboard tests: verify probe success (dmesg), GPIO toggles, I2C transactions with i2cget/i2cset, regulator/clocks enabled.- Power tests: suspend/resume, runtime PM idle timeout behavior, cold boot with/without regulator present.- Automated boot-time tests: a small userspace test that reads a known register on boot and reports pass/fail; run across reboots and with overlays.This demonstrates safe resource ownership, robust DT parsing, correct registration with the i2c core, and practical test coverage for boot/runtime power behavior.