linux/drivers/mfd/wm831x-i2c.c
Mark Brown 5da721c87a mfd: Support software initiated shutdown of WM831x PMICs
In systems where there is no hardware signal from the processor to the
PMIC to initiate the final power off sequence we must initiate the
shutdown with a register write to the PMIC. Support such systems in the
driver. Since this may prevent a full shutdown of the system platform
data is used to enable the feature.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
2011-10-24 14:09:13 +02:00

120 lines
2.6 KiB
C

/*
* wm831x-i2c.c -- I2C access for Wolfson WM831x PMICs
*
* Copyright 2009,2010 Wolfson Microelectronics PLC.
*
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/mfd/core.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/pdata.h>
static int wm831x_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm831x *wm831x;
int ret;
wm831x = kzalloc(sizeof(struct wm831x), GFP_KERNEL);
if (wm831x == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, wm831x);
wm831x->dev = &i2c->dev;
wm831x->regmap = regmap_init_i2c(i2c, &wm831x_regmap_config);
if (IS_ERR(wm831x->regmap)) {
ret = PTR_ERR(wm831x->regmap);
dev_err(wm831x->dev, "Failed to allocate register map: %d\n",
ret);
kfree(wm831x);
return ret;
}
return wm831x_device_init(wm831x, id->driver_data, i2c->irq);
}
static int wm831x_i2c_remove(struct i2c_client *i2c)
{
struct wm831x *wm831x = i2c_get_clientdata(i2c);
wm831x_device_exit(wm831x);
return 0;
}
static int wm831x_i2c_suspend(struct device *dev)
{
struct wm831x *wm831x = dev_get_drvdata(dev);
return wm831x_device_suspend(wm831x);
}
static void wm831x_i2c_shutdown(struct i2c_client *i2c)
{
struct wm831x *wm831x = i2c_get_clientdata(i2c);
wm831x_device_shutdown(wm831x);
}
static const struct i2c_device_id wm831x_i2c_id[] = {
{ "wm8310", WM8310 },
{ "wm8311", WM8311 },
{ "wm8312", WM8312 },
{ "wm8320", WM8320 },
{ "wm8321", WM8321 },
{ "wm8325", WM8325 },
{ "wm8326", WM8326 },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm831x_i2c_id);
static const struct dev_pm_ops wm831x_pm_ops = {
.suspend = wm831x_i2c_suspend,
};
static struct i2c_driver wm831x_i2c_driver = {
.driver = {
.name = "wm831x",
.owner = THIS_MODULE,
.pm = &wm831x_pm_ops,
},
.probe = wm831x_i2c_probe,
.remove = wm831x_i2c_remove,
.shutdown = wm831x_i2c_shutdown,
.id_table = wm831x_i2c_id,
};
static int __init wm831x_i2c_init(void)
{
int ret;
ret = i2c_add_driver(&wm831x_i2c_driver);
if (ret != 0)
pr_err("Failed to register wm831x I2C driver: %d\n", ret);
return ret;
}
subsys_initcall(wm831x_i2c_init);
static void __exit wm831x_i2c_exit(void)
{
i2c_del_driver(&wm831x_i2c_driver);
}
module_exit(wm831x_i2c_exit);