mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-18 23:54:26 +08:00
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>
This commit is contained in:
parent
f09ee0451a
commit
5da721c87a
@ -24,6 +24,7 @@
|
|||||||
#include <linux/mfd/wm831x/irq.h>
|
#include <linux/mfd/wm831x/irq.h>
|
||||||
#include <linux/mfd/wm831x/auxadc.h>
|
#include <linux/mfd/wm831x/auxadc.h>
|
||||||
#include <linux/mfd/wm831x/otp.h>
|
#include <linux/mfd/wm831x/otp.h>
|
||||||
|
#include <linux/mfd/wm831x/pmu.h>
|
||||||
#include <linux/mfd/wm831x/regulator.h>
|
#include <linux/mfd/wm831x/regulator.h>
|
||||||
|
|
||||||
/* Current settings - values are 2*2^(reg_val/4) microamps. These are
|
/* Current settings - values are 2*2^(reg_val/4) microamps. These are
|
||||||
@ -1305,6 +1306,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
|
|||||||
mutex_init(&wm831x->io_lock);
|
mutex_init(&wm831x->io_lock);
|
||||||
mutex_init(&wm831x->key_lock);
|
mutex_init(&wm831x->key_lock);
|
||||||
dev_set_drvdata(wm831x->dev, wm831x);
|
dev_set_drvdata(wm831x->dev, wm831x);
|
||||||
|
wm831x->soft_shutdown = pdata->soft_shutdown;
|
||||||
|
|
||||||
ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
|
ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -1604,6 +1606,15 @@ int wm831x_device_suspend(struct wm831x *wm831x)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wm831x_device_shutdown(struct wm831x *wm831x)
|
||||||
|
{
|
||||||
|
if (wm831x->soft_shutdown) {
|
||||||
|
dev_info(wm831x->dev, "Initiating shutdown...\n");
|
||||||
|
wm831x_set_bits(wm831x, WM831X_POWER_STATE, WM831X_CHIP_ON, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(wm831x_device_shutdown);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC");
|
MODULE_DESCRIPTION("Core support for the WM831X AudioPlus PMIC");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_AUTHOR("Mark Brown");
|
MODULE_AUTHOR("Mark Brown");
|
||||||
|
@ -109,6 +109,13 @@ static int wm831x_i2c_suspend(struct device *dev)
|
|||||||
return wm831x_device_suspend(wm831x);
|
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[] = {
|
static const struct i2c_device_id wm831x_i2c_id[] = {
|
||||||
{ "wm8310", WM8310 },
|
{ "wm8310", WM8310 },
|
||||||
{ "wm8311", WM8311 },
|
{ "wm8311", WM8311 },
|
||||||
@ -133,6 +140,7 @@ static struct i2c_driver wm831x_i2c_driver = {
|
|||||||
},
|
},
|
||||||
.probe = wm831x_i2c_probe,
|
.probe = wm831x_i2c_probe,
|
||||||
.remove = wm831x_i2c_remove,
|
.remove = wm831x_i2c_remove,
|
||||||
|
.shutdown = wm831x_i2c_shutdown,
|
||||||
.id_table = wm831x_i2c_id,
|
.id_table = wm831x_i2c_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -121,6 +121,13 @@ static int wm831x_spi_suspend(struct device *dev)
|
|||||||
return wm831x_device_suspend(wm831x);
|
return wm831x_device_suspend(wm831x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wm831x_spi_shutdown(struct spi_device *spi)
|
||||||
|
{
|
||||||
|
struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
|
||||||
|
|
||||||
|
wm831x_device_shutdown(wm831x);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct dev_pm_ops wm831x_spi_pm = {
|
static const struct dev_pm_ops wm831x_spi_pm = {
|
||||||
.freeze = wm831x_spi_suspend,
|
.freeze = wm831x_spi_suspend,
|
||||||
.suspend = wm831x_spi_suspend,
|
.suspend = wm831x_spi_suspend,
|
||||||
@ -146,6 +153,7 @@ static struct spi_driver wm8311_spi_driver = {
|
|||||||
},
|
},
|
||||||
.probe = wm831x_spi_probe,
|
.probe = wm831x_spi_probe,
|
||||||
.remove = __devexit_p(wm831x_spi_remove),
|
.remove = __devexit_p(wm831x_spi_remove),
|
||||||
|
.shutdown = wm831x_spi_shutdown,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct spi_driver wm8312_spi_driver = {
|
static struct spi_driver wm8312_spi_driver = {
|
||||||
|
@ -374,6 +374,8 @@ struct wm831x {
|
|||||||
int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */
|
int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */
|
||||||
int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */
|
int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */
|
||||||
|
|
||||||
|
bool soft_shutdown;
|
||||||
|
|
||||||
/* Chip revision based flags */
|
/* Chip revision based flags */
|
||||||
unsigned has_gpio_ena:1; /* Has GPIO enable bit */
|
unsigned has_gpio_ena:1; /* Has GPIO enable bit */
|
||||||
unsigned has_cs_sts:1; /* Has current sink status bit */
|
unsigned has_cs_sts:1; /* Has current sink status bit */
|
||||||
@ -412,6 +414,7 @@ int wm831x_bulk_read(struct wm831x *wm831x, unsigned short reg,
|
|||||||
int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq);
|
int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq);
|
||||||
void wm831x_device_exit(struct wm831x *wm831x);
|
void wm831x_device_exit(struct wm831x *wm831x);
|
||||||
int wm831x_device_suspend(struct wm831x *wm831x);
|
int wm831x_device_suspend(struct wm831x *wm831x);
|
||||||
|
void wm831x_device_shutdown(struct wm831x *wm831x);
|
||||||
int wm831x_irq_init(struct wm831x *wm831x, int irq);
|
int wm831x_irq_init(struct wm831x *wm831x, int irq);
|
||||||
void wm831x_irq_exit(struct wm831x *wm831x);
|
void wm831x_irq_exit(struct wm831x *wm831x);
|
||||||
void wm831x_auxadc_init(struct wm831x *wm831x);
|
void wm831x_auxadc_init(struct wm831x *wm831x);
|
||||||
|
@ -123,6 +123,9 @@ struct wm831x_pdata {
|
|||||||
/** Disable the touchscreen */
|
/** Disable the touchscreen */
|
||||||
bool disable_touch;
|
bool disable_touch;
|
||||||
|
|
||||||
|
/** The driver should initiate a power off sequence during shutdown */
|
||||||
|
bool soft_shutdown;
|
||||||
|
|
||||||
int irq_base;
|
int irq_base;
|
||||||
int gpio_base;
|
int gpio_base;
|
||||||
int gpio_defaults[WM831X_GPIO_NUM];
|
int gpio_defaults[WM831X_GPIO_NUM];
|
||||||
|
Loading…
Reference in New Issue
Block a user