diff options
-rw-r--r-- | drivers/input/keyboard/cros_ec_keyb.c | 58 | ||||
-rw-r--r-- | drivers/mfd/cros_ec.c | 35 | ||||
-rw-r--r-- | include/linux/mfd/cros_ec.h | 2 |
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 | */ |
47 | struct cros_ec_keyb { | 46 | struct 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 | ||
176 | static 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 | |||
184 | static 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 | |||
192 | static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state) | 174 | static 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 | ||
206 | static int cros_ec_keyb_work(struct notifier_block *nb, | 188 | static 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 | |||
207 | static 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 | |||
217 | static 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 | ||
221 | static int cros_ec_keyb_probe(struct platform_device *pdev) | 225 | static 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 | } |
63 | EXPORT_SYMBOL(cros_ec_check_result); | 63 | EXPORT_SYMBOL(cros_ec_check_result); |
64 | 64 | ||
65 | static 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 | |||
77 | static const struct mfd_cell cros_devs[] = { | 65 | static 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 | |||
133 | fail_mfd: | ||
134 | free_irq(ec_dev->irq, ec_dev); | ||
135 | |||
136 | return err; | ||
137 | } | 105 | } |
138 | EXPORT_SYMBOL(cros_ec_register); | 106 | EXPORT_SYMBOL(cros_ec_register); |
139 | 107 | ||
140 | int cros_ec_remove(struct cros_ec_device *ec_dev) | 108 | int 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 | ||