aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/83xx
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/83xx')
-rw-r--r--arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c58
1 files changed, 57 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
index 70798ac911e..ef6537b8ed3 100644
--- a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
+++ b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
@@ -21,6 +21,8 @@
21#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/of_gpio.h> 22#include <linux/of_gpio.h>
23#include <linux/slab.h> 23#include <linux/slab.h>
24#include <linux/kthread.h>
25#include <linux/reboot.h>
24#include <asm/prom.h> 26#include <asm/prom.h>
25#include <asm/machdep.h> 27#include <asm/machdep.h>
26 28
@@ -30,6 +32,7 @@
30 */ 32 */
31#define MCU_REG_CTRL 0x20 33#define MCU_REG_CTRL 0x20
32#define MCU_CTRL_POFF 0x40 34#define MCU_CTRL_POFF 0x40
35#define MCU_CTRL_BTN 0x80
33 36
34#define MCU_NUM_GPIO 2 37#define MCU_NUM_GPIO 2
35 38
@@ -42,13 +45,55 @@ struct mcu {
42 45
43static struct mcu *glob_mcu; 46static struct mcu *glob_mcu;
44 47
48struct task_struct *shutdown_thread;
49static int shutdown_thread_fn(void *data)
50{
51 int ret;
52 struct mcu *mcu = glob_mcu;
53
54 while (!kthread_should_stop()) {
55 ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
56 if (ret < 0)
57 pr_err("MCU status reg read failed.\n");
58 mcu->reg_ctrl = ret;
59
60
61 if (mcu->reg_ctrl & MCU_CTRL_BTN) {
62 i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
63 mcu->reg_ctrl & ~MCU_CTRL_BTN);
64
65 ctrl_alt_del();
66 }
67
68 set_current_state(TASK_INTERRUPTIBLE);
69 schedule_timeout(HZ);
70 }
71
72 return 0;
73}
74
75static ssize_t show_status(struct device *d,
76 struct device_attribute *attr, char *buf)
77{
78 int ret;
79 struct mcu *mcu = glob_mcu;
80
81 ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
82 if (ret < 0)
83 return -ENODEV;
84 mcu->reg_ctrl = ret;
85
86 return sprintf(buf, "%02x\n", ret);
87}
88static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
89
45static void mcu_power_off(void) 90static void mcu_power_off(void)
46{ 91{
47 struct mcu *mcu = glob_mcu; 92 struct mcu *mcu = glob_mcu;
48 93
49 pr_info("Sending power-off request to the MCU...\n"); 94 pr_info("Sending power-off request to the MCU...\n");
50 mutex_lock(&mcu->lock); 95 mutex_lock(&mcu->lock);
51 i2c_smbus_write_byte_data(glob_mcu->client, MCU_REG_CTRL, 96 i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL,
52 mcu->reg_ctrl | MCU_CTRL_POFF); 97 mcu->reg_ctrl | MCU_CTRL_POFF);
53 mutex_unlock(&mcu->lock); 98 mutex_unlock(&mcu->lock);
54} 99}
@@ -130,6 +175,13 @@ static int __devinit mcu_probe(struct i2c_client *client,
130 dev_info(&client->dev, "will provide power-off service\n"); 175 dev_info(&client->dev, "will provide power-off service\n");
131 } 176 }
132 177
178 if (device_create_file(&client->dev, &dev_attr_status))
179 dev_err(&client->dev,
180 "couldn't create device file for status\n");
181
182 shutdown_thread = kthread_run(shutdown_thread_fn, NULL,
183 "mcu-i2c-shdn");
184
133 return 0; 185 return 0;
134err: 186err:
135 kfree(mcu); 187 kfree(mcu);
@@ -141,6 +193,10 @@ static int __devexit mcu_remove(struct i2c_client *client)
141 struct mcu *mcu = i2c_get_clientdata(client); 193 struct mcu *mcu = i2c_get_clientdata(client);
142 int ret; 194 int ret;
143 195
196 kthread_stop(shutdown_thread);
197
198 device_remove_file(&client->dev, &dev_attr_status);
199
144 if (glob_mcu == mcu) { 200 if (glob_mcu == mcu) {
145 ppc_md.power_off = NULL; 201 ppc_md.power_off = NULL;
146 glob_mcu = NULL; 202 glob_mcu = NULL;