static int i2c_device_probe(struct device *dev)
{
struct i2c_client *client = i2c_verify_client(dev);
+ struct i2c_adapter *adap;
struct i2c_driver *driver;
int status;
if (!client)
return 0;
+ adap = client->adapter;
driver = to_i2c_driver(dev->driver);
client->irq = client->init_irq;
dev_dbg(dev, "probe\n");
+ status = regulator_enable(adap->bus_regulator);
+ if (status < 0) {
+ dev_err(&adap->dev, "Failed to enable power regulator\n");
+ goto err_clear_wakeup_irq;
+ }
+
status = of_clk_set_defaults(dev->of_node, false);
if (status < 0)
goto err_clear_wakeup_irq;
static int i2c_device_remove(struct device *dev)
{
struct i2c_client *client = i2c_verify_client(dev);
+ struct i2c_adapter *adap;
struct i2c_driver *driver;
int status = 0;
if (!client || !dev->driver)
return 0;
+ adap = client->adapter;
driver = to_i2c_driver(dev->driver);
if (driver->remove) {
dev_dbg(dev, "remove\n");
}
dev_pm_domain_detach(&client->dev, true);
+ if (!pm_runtime_status_suspended(&client->dev))
+ regulator_disable(adap->bus_regulator);
dev_pm_clear_wake_irq(&client->dev);
device_init_wakeup(&client->dev, false);
return status;
}
+#ifdef CONFIG_PM_SLEEP
+static int i2c_resume_early(struct device *dev)
+{
+ struct i2c_client *client = i2c_verify_client(dev);
+ struct i2c_adapter *adap = client->adapter;
+ int err;
+
+ if (!pm_runtime_status_suspended(&client->dev)) {
+ err = regulator_enable(adap->bus_regulator);
+ if (err)
+ return err;
+ }
+
+ return pm_generic_resume_early(&client->dev);
+}
+
+static int i2c_suspend_late(struct device *dev)
+{
+ struct i2c_client *client = i2c_verify_client(dev);
+ struct i2c_adapter *adap = client->adapter;
+ int err;
+
+ err = pm_generic_suspend_late(&client->dev);
+ if (err)
+ return err;
+
+ if (!pm_runtime_status_suspended(&client->dev))
+ return regulator_disable(adap->bus_regulator);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_PM
+static int i2c_runtime_resume(struct device *dev)
+{
+ struct i2c_client *client = i2c_verify_client(dev);
+ struct i2c_adapter *adap = client->adapter;
+ int err;
+
+ err = regulator_enable(adap->bus_regulator);
+ if (err)
+ return err;
+
+ return pm_generic_runtime_resume(&client->dev);
+}
+
+static int i2c_runtime_suspend(struct device *dev)
+{
+ struct i2c_client *client = i2c_verify_client(dev);
+ struct i2c_adapter *adap = client->adapter;
+ int err;
+
+ err = pm_generic_runtime_suspend(&client->dev);
+ if (err)
+ return err;
+
+ return regulator_disable(adap->bus_regulator);
+}
+#endif
+
+static const struct dev_pm_ops i2c_device_pm = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(i2c_suspend_late, i2c_resume_early)
+ SET_RUNTIME_PM_OPS(i2c_runtime_suspend, i2c_runtime_resume, NULL)
+};
+
static void i2c_device_shutdown(struct device *dev)
{
struct i2c_client *client = i2c_verify_client(dev);
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
+ .pm = &i2c_device_pm,
};
EXPORT_SYMBOL_GPL(i2c_bus_type);
if (res)
goto out_reg;
+ adap->bus_regulator = devm_regulator_get(&adap->dev, "bus");
+ if (IS_ERR(adap->bus_regulator)) {
+ res = PTR_ERR(adap->bus_regulator);
+ goto out_reg;
+ }
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
pm_runtime_no_callbacks(&adap->dev);