Skip to content

Commit 6fe12cd

Browse files
BibbyHsiehwsakernel
authored andcommitted
i2c: core: support bus regulator controlling in adapter
Although in the most platforms, the bus power of i2c are alway on, some platforms disable the i2c bus power in order to meet low power request. We get and enable bulk regulator in i2c adapter device. Signed-off-by: Bibby Hsieh <[email protected]> Reviewed-by: Tomasz Figa <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 6aab46b commit 6fe12cd

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

drivers/i2c/i2c-core-base.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,12 +313,14 @@ static int i2c_smbus_host_notify_to_irq(const struct i2c_client *client)
313313
static int i2c_device_probe(struct device *dev)
314314
{
315315
struct i2c_client *client = i2c_verify_client(dev);
316+
struct i2c_adapter *adap;
316317
struct i2c_driver *driver;
317318
int status;
318319

319320
if (!client)
320321
return 0;
321322

323+
adap = client->adapter;
322324
driver = to_i2c_driver(dev->driver);
323325

324326
client->irq = client->init_irq;
@@ -378,6 +380,12 @@ static int i2c_device_probe(struct device *dev)
378380

379381
dev_dbg(dev, "probe\n");
380382

383+
status = regulator_enable(adap->bus_regulator);
384+
if (status < 0) {
385+
dev_err(&adap->dev, "Failed to enable power regulator\n");
386+
goto err_clear_wakeup_irq;
387+
}
388+
381389
status = of_clk_set_defaults(dev->of_node, false);
382390
if (status < 0)
383391
goto err_clear_wakeup_irq;
@@ -414,19 +422,23 @@ static int i2c_device_probe(struct device *dev)
414422
static int i2c_device_remove(struct device *dev)
415423
{
416424
struct i2c_client *client = i2c_verify_client(dev);
425+
struct i2c_adapter *adap;
417426
struct i2c_driver *driver;
418427
int status = 0;
419428

420429
if (!client || !dev->driver)
421430
return 0;
422431

432+
adap = client->adapter;
423433
driver = to_i2c_driver(dev->driver);
424434
if (driver->remove) {
425435
dev_dbg(dev, "remove\n");
426436
status = driver->remove(client);
427437
}
428438

429439
dev_pm_domain_detach(&client->dev, true);
440+
if (!pm_runtime_status_suspended(&client->dev))
441+
regulator_disable(adap->bus_regulator);
430442

431443
dev_pm_clear_wake_irq(&client->dev);
432444
device_init_wakeup(&client->dev, false);
@@ -438,6 +450,72 @@ static int i2c_device_remove(struct device *dev)
438450
return status;
439451
}
440452

453+
#ifdef CONFIG_PM_SLEEP
454+
static int i2c_resume_early(struct device *dev)
455+
{
456+
struct i2c_client *client = i2c_verify_client(dev);
457+
struct i2c_adapter *adap = client->adapter;
458+
int err;
459+
460+
if (!pm_runtime_status_suspended(&client->dev)) {
461+
err = regulator_enable(adap->bus_regulator);
462+
if (err)
463+
return err;
464+
}
465+
466+
return pm_generic_resume_early(&client->dev);
467+
}
468+
469+
static int i2c_suspend_late(struct device *dev)
470+
{
471+
struct i2c_client *client = i2c_verify_client(dev);
472+
struct i2c_adapter *adap = client->adapter;
473+
int err;
474+
475+
err = pm_generic_suspend_late(&client->dev);
476+
if (err)
477+
return err;
478+
479+
if (!pm_runtime_status_suspended(&client->dev))
480+
return regulator_disable(adap->bus_regulator);
481+
482+
return 0;
483+
}
484+
#endif
485+
486+
#ifdef CONFIG_PM
487+
static int i2c_runtime_resume(struct device *dev)
488+
{
489+
struct i2c_client *client = i2c_verify_client(dev);
490+
struct i2c_adapter *adap = client->adapter;
491+
int err;
492+
493+
err = regulator_enable(adap->bus_regulator);
494+
if (err)
495+
return err;
496+
497+
return pm_generic_runtime_resume(&client->dev);
498+
}
499+
500+
static int i2c_runtime_suspend(struct device *dev)
501+
{
502+
struct i2c_client *client = i2c_verify_client(dev);
503+
struct i2c_adapter *adap = client->adapter;
504+
int err;
505+
506+
err = pm_generic_runtime_suspend(&client->dev);
507+
if (err)
508+
return err;
509+
510+
return regulator_disable(adap->bus_regulator);
511+
}
512+
#endif
513+
514+
static const struct dev_pm_ops i2c_device_pm = {
515+
SET_LATE_SYSTEM_SLEEP_PM_OPS(i2c_suspend_late, i2c_resume_early)
516+
SET_RUNTIME_PM_OPS(i2c_runtime_suspend, i2c_runtime_resume, NULL)
517+
};
518+
441519
static void i2c_device_shutdown(struct device *dev)
442520
{
443521
struct i2c_client *client = i2c_verify_client(dev);
@@ -495,6 +573,7 @@ struct bus_type i2c_bus_type = {
495573
.probe = i2c_device_probe,
496574
.remove = i2c_device_remove,
497575
.shutdown = i2c_device_shutdown,
576+
.pm = &i2c_device_pm,
498577
};
499578
EXPORT_SYMBOL_GPL(i2c_bus_type);
500579

@@ -1333,6 +1412,11 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
13331412
if (res)
13341413
goto out_reg;
13351414

1415+
adap->bus_regulator = devm_regulator_get(&adap->dev, "bus");
1416+
if (IS_ERR(adap->bus_regulator)) {
1417+
res = PTR_ERR(adap->bus_regulator);
1418+
goto out_reg;
1419+
}
13361420
dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
13371421

13381422
pm_runtime_no_callbacks(&adap->dev);

include/linux/i2c.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <linux/device.h> /* for struct device */
1616
#include <linux/sched.h> /* for completion */
1717
#include <linux/mutex.h>
18+
#include <linux/regulator/consumer.h>
1819
#include <linux/rtmutex.h>
1920
#include <linux/irqdomain.h> /* for Host Notify IRQ */
2021
#include <linux/of.h> /* for struct device_node */
@@ -721,6 +722,7 @@ struct i2c_adapter {
721722
const struct i2c_adapter_quirks *quirks;
722723

723724
struct irq_domain *host_notify_domain;
725+
struct regulator *bus_regulator;
724726
};
725727
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
726728

0 commit comments

Comments
 (0)