aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c58
-rw-r--r--drivers/mfd/cros_ec.c35
-rw-r--r--include/linux/mfd/cros_ec.h2
3 files changed, 34 insertions, 61 deletions
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index b8341ab99f55..791781ade4e7 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -24,8 +24,8 @@
24#include <linux/module.h> 24#include <linux/module.h>
25#include <linux/i2c.h> 25#include <linux/i2c.h>
26#include <linux/input.h> 26#include <linux/input.h>
27#include <linux/interrupt.h>
27#include <linux/kernel.h> 28#include <linux/kernel.h>
28#include <linux/notifier.h>
29#include <linux/platform_device.h> 29#include <linux/platform_device.h>
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/input/matrix_keypad.h> 31#include <linux/input/matrix_keypad.h>
@@ -42,7 +42,6 @@
42 * @dev: Device pointer 42 * @dev: Device pointer
43 * @idev: Input device 43 * @idev: Input device
44 * @ec: Top level ChromeOS device to use to talk to EC 44 * @ec: Top level ChromeOS device to use to talk to EC
45 * @event_notifier: interrupt event notifier for transport devices
46 */ 45 */
47struct cros_ec_keyb { 46struct cros_ec_keyb {
48 unsigned int rows; 47 unsigned int rows;
@@ -55,7 +54,6 @@ struct cros_ec_keyb {
55 struct device *dev; 54 struct device *dev;
56 struct input_dev *idev; 55 struct input_dev *idev;
57 struct cros_ec_device *ec; 56 struct cros_ec_device *ec;
58 struct notifier_block notifier;
59}; 57};
60 58
61 59
@@ -173,22 +171,6 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
173 input_sync(ckdev->idev); 171 input_sync(ckdev->idev);
174} 172}
175 173
176static int cros_ec_keyb_open(struct input_dev *dev)
177{
178 struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
179
180 return blocking_notifier_chain_register(&ckdev->ec->event_notifier,
181 &ckdev->notifier);
182}
183
184static void cros_ec_keyb_close(struct input_dev *dev)
185{
186 struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
187
188 blocking_notifier_chain_unregister(&ckdev->ec->event_notifier,
189 &ckdev->notifier);
190}
191
192static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state) 174static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
193{ 175{
194 struct cros_ec_command msg = { 176 struct cros_ec_command msg = {
@@ -203,19 +185,41 @@ static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
203 return ckdev->ec->cmd_xfer(ckdev->ec, &msg); 185 return ckdev->ec->cmd_xfer(ckdev->ec, &msg);
204} 186}
205 187
206static int cros_ec_keyb_work(struct notifier_block *nb, 188static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
207 unsigned long state, void *_notify)
208{ 189{
190 struct cros_ec_keyb *ckdev = data;
191 struct cros_ec_device *ec = ckdev->ec;
209 int ret; 192 int ret;
210 struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
211 notifier);
212 uint8_t kb_state[ckdev->cols]; 193 uint8_t kb_state[ckdev->cols];
213 194
195 if (device_may_wakeup(ec->dev))
196 pm_wakeup_event(ec->dev, 0);
197
214 ret = cros_ec_keyb_get_state(ckdev, kb_state); 198 ret = cros_ec_keyb_get_state(ckdev, kb_state);
215 if (ret >= 0) 199 if (ret >= 0)
216 cros_ec_keyb_process(ckdev, kb_state, ret); 200 cros_ec_keyb_process(ckdev, kb_state, ret);
201 else
202 dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
217 203
218 return NOTIFY_DONE; 204 return IRQ_HANDLED;
205}
206
207static int cros_ec_keyb_open(struct input_dev *dev)
208{
209 struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
210 struct cros_ec_device *ec = ckdev->ec;
211
212 return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
213 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
214 "cros_ec_keyb", ckdev);
215}
216
217static void cros_ec_keyb_close(struct input_dev *dev)
218{
219 struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
220 struct cros_ec_device *ec = ckdev->ec;
221
222 free_irq(ec->irq, ckdev);
219} 223}
220 224
221static int cros_ec_keyb_probe(struct platform_device *pdev) 225static int cros_ec_keyb_probe(struct platform_device *pdev)
@@ -246,8 +250,12 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
246 if (!idev) 250 if (!idev)
247 return -ENOMEM; 251 return -ENOMEM;
248 252
253 if (!ec->irq) {
254 dev_err(dev, "no EC IRQ specified\n");
255 return -EINVAL;
256 }
257
249 ckdev->ec = ec; 258 ckdev->ec = ec;
250 ckdev->notifier.notifier_call = cros_ec_keyb_work;
251 ckdev->dev = dev; 259 ckdev->dev = dev;
252 dev_set_drvdata(&pdev->dev, ckdev); 260 dev_set_drvdata(&pdev->dev, ckdev);
253 261
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 83e30c663578..4873f9c50452 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -62,18 +62,6 @@ int cros_ec_check_result(struct cros_ec_device *ec_dev,
62} 62}
63EXPORT_SYMBOL(cros_ec_check_result); 63EXPORT_SYMBOL(cros_ec_check_result);
64 64
65static irqreturn_t ec_irq_thread(int irq, void *data)
66{
67 struct cros_ec_device *ec_dev = data;
68
69 if (device_may_wakeup(ec_dev->dev))
70 pm_wakeup_event(ec_dev->dev, 0);
71
72 blocking_notifier_call_chain(&ec_dev->event_notifier, 1, ec_dev);
73
74 return IRQ_HANDLED;
75}
76
77static const struct mfd_cell cros_devs[] = { 65static const struct mfd_cell cros_devs[] = {
78 { 66 {
79 .name = "cros-ec-keyb", 67 .name = "cros-ec-keyb",
@@ -92,8 +80,6 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
92 struct device *dev = ec_dev->dev; 80 struct device *dev = ec_dev->dev;
93 int err = 0; 81 int err = 0;
94 82
95 BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier);
96
97 if (ec_dev->din_size) { 83 if (ec_dev->din_size) {
98 ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL); 84 ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
99 if (!ec_dev->din) 85 if (!ec_dev->din)
@@ -105,42 +91,23 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
105 return -ENOMEM; 91 return -ENOMEM;
106 } 92 }
107 93
108 if (!ec_dev->irq) {
109 dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq);
110 return err;
111 }
112
113 err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
114 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
115 "chromeos-ec", ec_dev);
116 if (err) {
117 dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
118 return err;
119 }
120
121 err = mfd_add_devices(dev, 0, cros_devs, 94 err = mfd_add_devices(dev, 0, cros_devs,
122 ARRAY_SIZE(cros_devs), 95 ARRAY_SIZE(cros_devs),
123 NULL, ec_dev->irq, NULL); 96 NULL, ec_dev->irq, NULL);
124 if (err) { 97 if (err) {
125 dev_err(dev, "failed to add mfd devices\n"); 98 dev_err(dev, "failed to add mfd devices\n");
126 goto fail_mfd; 99 return err;
127 } 100 }
128 101
129 dev_info(dev, "Chrome EC device registered\n"); 102 dev_info(dev, "Chrome EC device registered\n");
130 103
131 return 0; 104 return 0;
132
133fail_mfd:
134 free_irq(ec_dev->irq, ec_dev);
135
136 return err;
137} 105}
138EXPORT_SYMBOL(cros_ec_register); 106EXPORT_SYMBOL(cros_ec_register);
139 107
140int cros_ec_remove(struct cros_ec_device *ec_dev) 108int cros_ec_remove(struct cros_ec_device *ec_dev)
141{ 109{
142 mfd_remove_devices(ec_dev->dev); 110 mfd_remove_devices(ec_dev->dev);
143 free_irq(ec_dev->irq, ec_dev);
144 111
145 return 0; 112 return 0;
146} 113}
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 0ebf26fddbbb..fcbe9d129a9d 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -62,7 +62,6 @@ struct cros_ec_command {
62 * @dev: Device pointer 62 * @dev: Device pointer
63 * @was_wake_device: true if this device was set to wake the system from 63 * @was_wake_device: true if this device was set to wake the system from
64 * sleep at the last suspend 64 * sleep at the last suspend
65 * @event_notifier: interrupt event notifier for transport devices
66 * @cmd_xfer: send command to EC and get response 65 * @cmd_xfer: send command to EC and get response
67 * Returns the number of bytes received if the communication succeeded, but 66 * Returns the number of bytes received if the communication succeeded, but
68 * that doesn't mean the EC was happy with the command. The caller 67 * that doesn't mean the EC was happy with the command. The caller
@@ -93,7 +92,6 @@ struct cros_ec_device {
93 struct device *dev; 92 struct device *dev;
94 bool was_wake_device; 93 bool was_wake_device;
95 struct class *cros_class; 94 struct class *cros_class;
96 struct blocking_notifier_head event_notifier;
97 int (*cmd_xfer)(struct cros_ec_device *ec, 95 int (*cmd_xfer)(struct cros_ec_device *ec,
98 struct cros_ec_command *msg); 96 struct cros_ec_command *msg);
99 97