Commit 6ca6ca5d authored by Fabio Baltieri's avatar Fabio Baltieri Committed by Kumar Gala

powerpc/83xx: Add shutdown request support to MCU handling on MPC8349 MITX

This patch add support for calling ctrl_alt_del() when the power button is
pressed for more than about 2 seconds on some freescale MPC83xx evaluation
boards and reference design.

The code uses a kthread to poll the CTRL_BTN bit each second.

Also change Kconfig entry of the driver to bool, as device's gpio
registration is broken when loading as module.

Tested on an MPC8315E RDB board.
Signed-off-by: default avatarFabio Baltieri <fabio.baltieri@gmail.com>
Signed-off-by: default avatarKumar Gala <galak@kernel.crashing.org>
parent 43a327b7
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/kthread.h>
#include <linux/reboot.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/machdep.h> #include <asm/machdep.h>
...@@ -30,6 +32,7 @@ ...@@ -30,6 +32,7 @@
*/ */
#define MCU_REG_CTRL 0x20 #define MCU_REG_CTRL 0x20
#define MCU_CTRL_POFF 0x40 #define MCU_CTRL_POFF 0x40
#define MCU_CTRL_BTN 0x80
#define MCU_NUM_GPIO 2 #define MCU_NUM_GPIO 2
...@@ -42,13 +45,55 @@ struct mcu { ...@@ -42,13 +45,55 @@ struct mcu {
static struct mcu *glob_mcu; static struct mcu *glob_mcu;
struct task_struct *shutdown_thread;
static int shutdown_thread_fn(void *data)
{
int ret;
struct mcu *mcu = glob_mcu;
while (!kthread_should_stop()) {
ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
if (ret < 0)
pr_err("MCU status reg read failed.\n");
mcu->reg_ctrl = ret;
if (mcu->reg_ctrl & MCU_CTRL_BTN) {
i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
mcu->reg_ctrl & ~MCU_CTRL_BTN);
ctrl_alt_del();
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ);
}
return 0;
}
static ssize_t show_status(struct device *d,
struct device_attribute *attr, char *buf)
{
int ret;
struct mcu *mcu = glob_mcu;
ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
if (ret < 0)
return -ENODEV;
mcu->reg_ctrl = ret;
return sprintf(buf, "%02x\n", ret);
}
static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
static void mcu_power_off(void) static void mcu_power_off(void)
{ {
struct mcu *mcu = glob_mcu; struct mcu *mcu = glob_mcu;
pr_info("Sending power-off request to the MCU...\n"); pr_info("Sending power-off request to the MCU...\n");
mutex_lock(&mcu->lock); mutex_lock(&mcu->lock);
i2c_smbus_write_byte_data(glob_mcu->client, MCU_REG_CTRL, i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
mcu->reg_ctrl | MCU_CTRL_POFF); mcu->reg_ctrl | MCU_CTRL_POFF);
mutex_unlock(&mcu->lock); mutex_unlock(&mcu->lock);
} }
...@@ -130,6 +175,13 @@ static int __devinit mcu_probe(struct i2c_client *client, ...@@ -130,6 +175,13 @@ static int __devinit mcu_probe(struct i2c_client *client,
dev_info(&client->dev, "will provide power-off service\n"); dev_info(&client->dev, "will provide power-off service\n");
} }
if (device_create_file(&client->dev, &dev_attr_status))
dev_err(&client->dev,
"couldn't create device file for status\n");
shutdown_thread = kthread_run(shutdown_thread_fn, NULL,
"mcu-i2c-shdn");
return 0; return 0;
err: err:
kfree(mcu); kfree(mcu);
...@@ -141,6 +193,10 @@ static int __devexit mcu_remove(struct i2c_client *client) ...@@ -141,6 +193,10 @@ static int __devexit mcu_remove(struct i2c_client *client)
struct mcu *mcu = i2c_get_clientdata(client); struct mcu *mcu = i2c_get_clientdata(client);
int ret; int ret;
kthread_stop(shutdown_thread);
device_remove_file(&client->dev, &dev_attr_status);
if (glob_mcu == mcu) { if (glob_mcu == mcu) {
ppc_md.power_off = NULL; ppc_md.power_off = NULL;
glob_mcu = NULL; glob_mcu = NULL;
......
...@@ -346,7 +346,7 @@ config SIMPLE_GPIO ...@@ -346,7 +346,7 @@ config SIMPLE_GPIO
on-board peripherals. on-board peripherals.
config MCU_MPC8349EMITX config MCU_MPC8349EMITX
tristate "MPC8349E-mITX MCU driver" bool "MPC8349E-mITX MCU driver"
depends on I2C && PPC_83xx depends on I2C && PPC_83xx
select GENERIC_GPIO select GENERIC_GPIO
select ARCH_REQUIRE_GPIOLIB select ARCH_REQUIRE_GPIOLIB
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment