History

Merge tag 'tag-ib-chrome-mfd-iio-input-5.5' into chrome-platform-5.5

IB between mfd, iio, input and chrome platform for cros-ec-sensorhub

Enric Balletbo i Serra committed 6 years ago

Commit 5ec966d2 parents c2ce4d2 99cdb2417 files · +636 −421Browse files

Unified · Split

17 files
  1. drivers/iio/accel/cros_ec_accel_legacy.c +0 −6
  2. drivers/iio/common/cros_ec_sensors/Kconfig +1 −1
  3. drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c +0 −6
  4. drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +3 −1
  5. drivers/iio/light/cros_ec_light_prox.c +0 −6
  6. drivers/input/keyboard/cros_ec_keyb.c +2 −4
  7. drivers/mfd/cros_ec_dev.c +12 −223
  8. drivers/platform/chrome/Kconfig +12 −0
  9. drivers/platform/chrome/Makefile +1 −0
  10. drivers/platform/chrome/cros_ec.c +76 −8
  11. drivers/platform/chrome/cros_ec_ishtp.c +19 −6
  12. drivers/platform/chrome/cros_ec_lpc.c +13 −4
  13. drivers/platform/chrome/cros_ec_proto.c +237 −30
  14. drivers/platform/chrome/cros_ec_rpmsg.c +4 −15
  15. drivers/platform/chrome/cros_ec_sensorhub.c +199 −0
  16. include/linux/platform_data/cros_ec_proto.h +27 −111
  17. include/linux/platform_data/cros_ec_sensorhub.h +30 −0
drivers/iio/accel/cros_ec_accel_legacy.c+0−6
@@ -163,16 +163,10 @@ static const struct iio_chan_spec cros_ec_accel_legacy_channels[] = { · 162 unmodified lines
163163 static int cros_ec_accel_legacy_probe(struct platform_device *pdev)
164164 {
165165 struct device *dev = &pdev->dev;
166− struct cros_ec_dev *ec = dev_get_drvdata(dev->parent);
167166 struct iio_dev *indio_dev;
168167 struct cros_ec_sensors_core_state *state;
169168 int ret;
170169
171− if (!ec || !ec->ec_dev) {
172− dev_warn(&pdev->dev, "No EC device found.\n");
173− return -EINVAL;
174− }
175−
176170 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state));
177171 if (!indio_dev)
178172 return -ENOMEM;
drivers/iio/common/cros_ec_sensors/Kconfig+1−1
@@ -4,7 +4,7 @@ · 3 unmodified lines
44 #
55 config IIO_CROS_EC_SENSORS_CORE
66 tristate "ChromeOS EC Sensors Core"
7− depends on SYSFS && CROS_EC
7+ depends on SYSFS && CROS_EC_SENSORHUB
88 select IIO_BUFFER
99 select IIO_TRIGGERED_BUFFER
1010 help
drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c+0−6
@@ -222,17 +222,11 @@ static const struct iio_info ec_sensors_info = { · 221 unmodified lines
222222 static int cros_ec_sensors_probe(struct platform_device *pdev)
223223 {
224224 struct device *dev = &pdev->dev;
225− struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
226225 struct iio_dev *indio_dev;
227226 struct cros_ec_sensors_state *state;
228227 struct iio_chan_spec *channel;
229228 int ret, i;
230229
231− if (!ec_dev || !ec_dev->ec_dev) {
232− dev_warn(&pdev->dev, "No CROS EC device found.\n");
233− return -EINVAL;
234− }
235−
236230 indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state));
237231 if (!indio_dev)
238232 return -ENOMEM;
drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c+3−1
@@ -18,6 +18,7 @@ · 17 unmodified lines
1818 #include <linux/slab.h>
1919 #include <linux/platform_data/cros_ec_commands.h>
2020 #include <linux/platform_data/cros_ec_proto.h>
21+#include <linux/platform_data/cros_ec_sensorhub.h>
2122 #include <linux/platform_device.h>
2223
2324 static char *cros_ec_loc[] = {
@@ -88,7 +89,8 @@ int cros_ec_sensors_core_init(struct platform_device *pdev, · 64 unmodified lines
8889 {
8990 struct device *dev = &pdev->dev;
9091 struct cros_ec_sensors_core_state *state = iio_priv(indio_dev);
91− struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent);
92+ struct cros_ec_sensorhub *sensor_hub = dev_get_drvdata(dev->parent);
93+ struct cros_ec_dev *ec = sensor_hub->ec;
9294 struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
9395 u32 ver_mask;
9496 int ret, i;
drivers/iio/light/cros_ec_light_prox.c+0−6
@@ -169,17 +169,11 @@ static const struct iio_info cros_ec_light_prox_info = { · 168 unmodified lines
169169 static int cros_ec_light_prox_probe(struct platform_device *pdev)
170170 {
171171 struct device *dev = &pdev->dev;
172− struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
173172 struct iio_dev *indio_dev;
174173 struct cros_ec_light_prox_state *state;
175174 struct iio_chan_spec *channel;
176175 int ret;
177176
178− if (!ec_dev || !ec_dev->ec_dev) {
179− dev_warn(dev, "No CROS EC device found.\n");
180− return -EINVAL;
181− }
182−
183177 indio_dev = devm_iio_device_alloc(dev, sizeof(*state));
184178 if (!indio_dev)
185179 return -ENOMEM;
drivers/input/keyboard/cros_ec_keyb.c+2−4
@@ -226,8 +226,6 @@ static int cros_ec_keyb_work(struct notifier_block *nb, · 225 unmodified lines
226226 {
227227 struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
228228 notifier);
229− uint8_t mkbp_event_type = ckdev->ec->event_data.event_type &
230− EC_MKBP_EVENT_TYPE_MASK;
231229 u32 val;
232230 unsigned int ev_type;
233231
@@ -239,7 +237,7 @@ static int cros_ec_keyb_work(struct notifier_block *nb, · 5 unmodified lines
239237 if (queued_during_suspend && !device_may_wakeup(ckdev->dev))
240238 return NOTIFY_OK;
241239
242− switch (mkbp_event_type) {
240+ switch (ckdev->ec->event_data.event_type) {
243241 case EC_MKBP_EVENT_KEY_MATRIX:
244242 pm_wakeup_event(ckdev->dev, 0);
245243
@@ -266,7 +264,7 @@ static int cros_ec_keyb_work(struct notifier_block *nb, · 20 unmodified lines
266264 case EC_MKBP_EVENT_SWITCH:
267265 pm_wakeup_event(ckdev->dev, 0);
268266
269− if (mkbp_event_type == EC_MKBP_EVENT_BUTTON) {
267+ if (ckdev->ec->event_data.event_type == EC_MKBP_EVENT_BUTTON) {
270268 val = get_unaligned_le32(
271269 &ckdev->ec->event_data.data.buttons);
272270 ev_type = EV_KEY;
drivers/mfd/cros_ec_dev.c+12−223
@@ -78,6 +78,10 @@ static const struct mfd_cell cros_ec_rtc_cells[] = { · 77 unmodified lines
7878 { .name = "cros-ec-rtc", },
7979 };
8080
81+static const struct mfd_cell cros_ec_sensorhub_cells[] = {
82+ { .name = "cros-ec-sensorhub", },
83+};
84+
8185 static const struct mfd_cell cros_usbpd_charger_cells[] = {
8286 { .name = "cros-usbpd-charger", },
8387 { .name = "cros-usbpd-logger", },
@@ -112,229 +116,11 @@ static const struct mfd_cell cros_ec_vbc_cells[] = { · 28 unmodified lines
112116 { .name = "cros-ec-vbc", }
113117 };
114118
115−static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
116−{
117− struct cros_ec_command *msg;
118− int ret;
119−
120− if (ec->features[0] == -1U && ec->features[1] == -1U) {
121− /* features bitmap not read yet */
122− msg = kzalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
123− if (!msg)
124− return -ENOMEM;
125−
126− msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
127− msg->insize = sizeof(ec->features);
128−
129− ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
130− if (ret < 0) {
131− dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
132− ret, msg->result);
133− memset(ec->features, 0, sizeof(ec->features));
134− } else {
135− memcpy(ec->features, msg->data, sizeof(ec->features));
136− }
137−
138− dev_dbg(ec->dev, "EC features %08x %08x\n",
139− ec->features[0], ec->features[1]);
140−
141− kfree(msg);
142− }
143−
144− return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature);
145−}
146−
147119 static void cros_ec_class_release(struct device *dev)
148120 {
149121 kfree(to_cros_ec_dev(dev));
150122 }
151123
152−static void cros_ec_sensors_register(struct cros_ec_dev *ec)
153−{
154− /*
155− * Issue a command to get the number of sensor reported.
156− * Build an array of sensors driver and register them all.
157− */
158− int ret, i, id, sensor_num;
159− struct mfd_cell *sensor_cells;
160− struct cros_ec_sensor_platform *sensor_platforms;
161− int sensor_type[MOTIONSENSE_TYPE_MAX];
162− struct ec_params_motion_sense *params;
163− struct ec_response_motion_sense *resp;
164− struct cros_ec_command *msg;
165−
166− msg = kzalloc(sizeof(struct cros_ec_command) +
167− max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
168− if (msg == NULL)
169− return;
170−
171− msg->version = 2;
172− msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
173− msg->outsize = sizeof(*params);
174− msg->insize = sizeof(*resp);
175−
176− params = (struct ec_params_motion_sense *)msg->data;
177− params->cmd = MOTIONSENSE_CMD_DUMP;
178−
179− ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
180− if (ret < 0) {
181− dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n",
182− ret, msg->result);
183− goto error;
184− }
185−
186− resp = (struct ec_response_motion_sense *)msg->data;
187− sensor_num = resp->dump.sensor_count;
188− /*
189− * Allocate 2 extra sensors if lid angle sensor and/or FIFO are needed.
190− */
191− sensor_cells = kcalloc(sensor_num + 2, sizeof(struct mfd_cell),
192− GFP_KERNEL);
193− if (sensor_cells == NULL)
194− goto error;
195−
196− sensor_platforms = kcalloc(sensor_num,
197− sizeof(struct cros_ec_sensor_platform),
198− GFP_KERNEL);
199− if (sensor_platforms == NULL)
200− goto error_platforms;
201−
202− memset(sensor_type, 0, sizeof(sensor_type));
203− id = 0;
204− for (i = 0; i < sensor_num; i++) {
205− params->cmd = MOTIONSENSE_CMD_INFO;
206− params->info.sensor_num = i;
207− ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
208− if (ret < 0) {
209− dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n",
210− i, ret, msg->result);
211− continue;
212− }
213− switch (resp->info.type) {
214− case MOTIONSENSE_TYPE_ACCEL:
215− sensor_cells[id].name = "cros-ec-accel";
216− break;
217− case MOTIONSENSE_TYPE_BARO:
218− sensor_cells[id].name = "cros-ec-baro";
219− break;
220− case MOTIONSENSE_TYPE_GYRO:
221− sensor_cells[id].name = "cros-ec-gyro";
222− break;
223− case MOTIONSENSE_TYPE_MAG:
224− sensor_cells[id].name = "cros-ec-mag";
225− break;
226− case MOTIONSENSE_TYPE_PROX:
227− sensor_cells[id].name = "cros-ec-prox";
228− break;
229− case MOTIONSENSE_TYPE_LIGHT:
230− sensor_cells[id].name = "cros-ec-light";
231− break;
232− case MOTIONSENSE_TYPE_ACTIVITY:
233− sensor_cells[id].name = "cros-ec-activity";
234− break;
235− default:
236− dev_warn(ec->dev, "unknown type %d\n", resp->info.type);
237− continue;
238− }
239− sensor_platforms[id].sensor_num = i;
240− sensor_cells[id].id = sensor_type[resp->info.type];
241− sensor_cells[id].platform_data = &sensor_platforms[id];
242− sensor_cells[id].pdata_size =
243− sizeof(struct cros_ec_sensor_platform);
244−
245− sensor_type[resp->info.type]++;
246− id++;
247− }
248−
249− if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2)
250− ec->has_kb_wake_angle = true;
251−
252− if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
253− sensor_cells[id].name = "cros-ec-ring";
254− id++;
255− }
256− if (cros_ec_check_features(ec,
257− EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS)) {
258− sensor_cells[id].name = "cros-ec-lid-angle";
259− id++;
260− }
261−
262− ret = mfd_add_devices(ec->dev, 0, sensor_cells, id,
263− NULL, 0, NULL);
264− if (ret)
265− dev_err(ec->dev, "failed to add EC sensors\n");
266−
267− kfree(sensor_platforms);
268−error_platforms:
269− kfree(sensor_cells);
270−error:
271− kfree(msg);
272−}
273−
274−static struct cros_ec_sensor_platform sensor_platforms[] = {
275− { .sensor_num = 0 },
276− { .sensor_num = 1 }
277−};
278−
279−static const struct mfd_cell cros_ec_accel_legacy_cells[] = {
280− {
281− .name = "cros-ec-accel-legacy",
282− .platform_data = &sensor_platforms[0],
283− .pdata_size = sizeof(struct cros_ec_sensor_platform),
284− },
285− {
286− .name = "cros-ec-accel-legacy",
287− .platform_data = &sensor_platforms[1],
288− .pdata_size = sizeof(struct cros_ec_sensor_platform),
289− }
290−};
291−
292−static void cros_ec_accel_legacy_register(struct cros_ec_dev *ec)
293−{
294− struct cros_ec_device *ec_dev = ec->ec_dev;
295− u8 status;
296− int ret;
297−
298− /*
299− * ECs that need legacy support are the main EC, directly connected to
300− * the AP.
301− */
302− if (ec->cmd_offset != 0)
303− return;
304−
305− /*
306− * Check if EC supports direct memory reads and if EC has
307− * accelerometers.
308− */
309− if (ec_dev->cmd_readmem) {
310− ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS, 1,
311− &status);
312− if (ret < 0) {
313− dev_warn(ec->dev, "EC direct read error.\n");
314− return;
315− }
316−
317− /* Check if EC has accelerometers. */
318− if (!(status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT)) {
319− dev_info(ec->dev, "EC does not have accelerometers.\n");
320− return;
321− }
322− }
323−
324− /*
325− * The device may still support accelerometers:
326− * it would be an older ARM based device that do not suppor the
327− * EC_CMD_GET_FEATURES command.
328− *
329− * Register 2 accelerometers, we will fail in the IIO driver if there
330− * are no sensors.
331− */
332− ret = mfd_add_hotplug_devices(ec->dev, cros_ec_accel_legacy_cells,
333− ARRAY_SIZE(cros_ec_accel_legacy_cells));
334− if (ret)
335− dev_err(ec_dev->dev, "failed to add EC sensors\n");
336−}
337−
338124 static int ec_device_probe(struct platform_device *pdev)
339125 {
340126 int retval = -ENOMEM;
@@ -390,11 +176,14 @@ static int ec_device_probe(struct platform_device *pdev) · 49 unmodified lines
390176 goto failed;
391177
392178 /* check whether this EC is a sensor hub. */
393− if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
394− cros_ec_sensors_register(ec);
395− else
396− /* Workaroud for older EC firmware */
397− cros_ec_accel_legacy_register(ec);
179+ if (cros_ec_get_sensor_count(ec) > 0) {
180+ retval = mfd_add_hotplug_devices(ec->dev,
181+ cros_ec_sensorhub_cells,
182+ ARRAY_SIZE(cros_ec_sensorhub_cells));
183+ if (retval)
184+ dev_err(ec->dev, "failed to add %s subdevice: %d\n",
185+ cros_ec_sensorhub_cells->name, retval);
186+ }
398187
399188 /*
400189 * The following subdevices can be detected by sending the
drivers/platform/chrome/Kconfig+12−0
@@ -190,6 +190,18 @@ config CROS_EC_DEBUGFS · 189 unmodified lines
190190 To compile this driver as a module, choose M here: the
191191 module will be called cros_ec_debugfs.
192192
193+config CROS_EC_SENSORHUB
194+ tristate "ChromeOS EC MEMS Sensor Hub"
195+ depends on CROS_EC
196+ help
197+ Allow loading IIO sensors. This driver is loaded by MFD and will in
198+ turn query the EC and register the sensors.
199+ It also spreads the sensor data coming from the EC to the IIO sensor
200+ object.
201+
202+ To compile this driver as a module, choose M here: the
203+ module will be called cros_ec_sensorhub.
204+
193205 config CROS_EC_SYSFS
194206 tristate "ChromeOS EC control and information through sysfs"
195207 depends on MFD_CROS_EC_DEV && SYSFS
drivers/platform/chrome/Makefile+1−0
@@ -19,6 +19,7 @@ obj-$(CONFIG_CROS_EC_CHARDEV) += cros_ec_chardev.o · 18 unmodified lines
1919 obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o
2020 obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o
2121 obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o
22+obj-$(CONFIG_CROS_EC_SENSORHUB) += cros_ec_sensorhub.o
2223 obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o
2324 obj-$(CONFIG_CROS_USBPD_LOGGER) += cros_usbpd_logger.o
2425
drivers/platform/chrome/cros_ec.c+76−8
@@ -31,13 +31,32 @@ static struct cros_ec_platform pd_p = { · 30 unmodified lines
3131 .cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX),
3232 };
3333
34−static irqreturn_t ec_irq_thread(int irq, void *data)
34+static irqreturn_t ec_irq_handler(int irq, void *data)
3535 {
3636 struct cros_ec_device *ec_dev = data;
37− bool wake_event = true;
37+
38+ ec_dev->last_event_time = cros_ec_get_time_ns();
39+
40+ return IRQ_WAKE_THREAD;
41+}
42+
43+/**
44+ * cros_ec_handle_event() - process and forward pending events on EC
45+ * @ec_dev: Device with events to process.
46+ *
47+ * Call this function in a loop when the kernel is notified that the EC has
48+ * pending events.
49+ *
50+ * Return: true if more events are still pending and this function should be
51+ * called again.
52+ */
53+bool cros_ec_handle_event(struct cros_ec_device *ec_dev)
54+{
55+ bool wake_event;
56+ bool ec_has_more_events;
3857 int ret;
3958
40− ret = cros_ec_get_next_event(ec_dev, &wake_event);
59+ ret = cros_ec_get_next_event(ec_dev, &wake_event, &ec_has_more_events);
4160
4261 /*
4362 * Signal only if wake host events or any interrupt if
@@ -50,6 +69,20 @@ static irqreturn_t ec_irq_thread(int irq, void *data) · 6 unmodified lines
5069 if (ret > 0)
5170 blocking_notifier_call_chain(&ec_dev->event_notifier,
5271 0, ec_dev);
72+
73+ return ec_has_more_events;
74+}
75+EXPORT_SYMBOL(cros_ec_handle_event);
76+
77+static irqreturn_t ec_irq_thread(int irq, void *data)
78+{
79+ struct cros_ec_device *ec_dev = data;
80+ bool ec_has_more_events;
81+
82+ do {
83+ ec_has_more_events = cros_ec_handle_event(ec_dev);
84+ } while (ec_has_more_events);
85+
5386 return IRQ_HANDLED;
5487 }
5588
@@ -104,6 +137,15 @@ static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event) · 48 unmodified lines
104137 return ret;
105138 }
106139
140+/**
141+ * cros_ec_register() - Register a new ChromeOS EC, using the provided info.
142+ * @ec_dev: Device to register.
143+ *
144+ * Before calling this, allocate a pointer to a new device and then fill
145+ * in all the fields up to the --private-- marker.
146+ *
147+ * Return: 0 on success or negative error code.
148+ */
107149 int cros_ec_register(struct cros_ec_device *ec_dev)
108150 {
109151 struct device *dev = ec_dev->dev;
@@ -131,10 +173,12 @@ int cros_ec_register(struct cros_ec_device *ec_dev) · 21 unmodified lines
131173 return err;
132174 }
133175
134− if (ec_dev->irq) {
135− err = devm_request_threaded_irq(dev, ec_dev->irq, NULL,
136− ec_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
137− "chromeos-ec", ec_dev);
176+ if (ec_dev->irq > 0) {
177+ err = devm_request_threaded_irq(dev, ec_dev->irq,
178+ ec_irq_handler,
179+ ec_irq_thread,
180+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
181+ "chromeos-ec", ec_dev);
138182 if (err) {
139183 dev_err(dev, "Failed to request IRQ %d: %d",
140184 ec_dev->irq, err);
@@ -198,6 +242,14 @@ int cros_ec_register(struct cros_ec_device *ec_dev) · 57 unmodified lines
198242 }
199243 EXPORT_SYMBOL(cros_ec_register);
200244
245+/**
246+ * cros_ec_unregister() - Remove a ChromeOS EC.
247+ * @ec_dev: Device to unregister.
248+ *
249+ * Call this to deregister a ChromeOS EC, then clean up any private data.
250+ *
251+ * Return: 0 on success or negative error code.
252+ */
201253 int cros_ec_unregister(struct cros_ec_device *ec_dev)
202254 {
203255 if (ec_dev->pd)
@@ -209,6 +261,14 @@ int cros_ec_unregister(struct cros_ec_device *ec_dev) · 5 unmodified lines
209261 EXPORT_SYMBOL(cros_ec_unregister);
210262
211263 #ifdef CONFIG_PM_SLEEP
264+/**
265+ * cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device.
266+ * @ec_dev: Device to suspend.
267+ *
268+ * This can be called by drivers to handle a suspend event.
269+ *
270+ * Return: 0 on success or negative error code.
271+ */
212272 int cros_ec_suspend(struct cros_ec_device *ec_dev)
213273 {
214274 struct device *dev = ec_dev->dev;
@@ -238,11 +298,19 @@ EXPORT_SYMBOL(cros_ec_suspend); · 23 unmodified lines
238298 static void cros_ec_report_events_during_suspend(struct cros_ec_device *ec_dev)
239299 {
240300 while (ec_dev->mkbp_event_supported &&
241− cros_ec_get_next_event(ec_dev, NULL) > 0)
301+ cros_ec_get_next_event(ec_dev, NULL, NULL) > 0)
242302 blocking_notifier_call_chain(&ec_dev->event_notifier,
243303 1, ec_dev);
244304 }
245305
306+/**
307+ * cros_ec_resume() - Handle a resume operation for the ChromeOS EC device.
308+ * @ec_dev: Device to resume.
309+ *
310+ * This can be called by drivers to handle a resume event.
311+ *
312+ * Return: 0 on success or negative error code.
313+ */
246314 int cros_ec_resume(struct cros_ec_device *ec_dev)
247315 {
248316 int ret;
drivers/platform/chrome/cros_ec_ishtp.c+19−6
@@ -136,11 +136,11 @@ static void ish_evt_handler(struct work_struct *work) · 135 unmodified lines
136136 struct ishtp_cl_data *client_data =
137137 container_of(work, struct ishtp_cl_data, work_ec_evt);
138138 struct cros_ec_device *ec_dev = client_data->ec_dev;
139+ bool ec_has_more_events;
139140
140− if (cros_ec_get_next_event(ec_dev, NULL) > 0) {
141− blocking_notifier_call_chain(&ec_dev->event_notifier,
142− 0, ec_dev);
143− }
141+ do {
142+ ec_has_more_events = cros_ec_handle_event(ec_dev);
143+ } while (ec_has_more_events);
144144 }
145145
146146 /**
@@ -200,13 +200,14 @@ static int ish_send(struct ishtp_cl_data *client_data, · 53 unmodified lines
200200 * process_recv() - Received and parse incoming packet
201201 * @cros_ish_cl: Client instance to get stats
202202 * @rb_in_proc: Host interface message buffer
203+ * @timestamp: Timestamp of when parent callback started
203204 *
204205 * Parse the incoming packet. If it is a response packet then it will
205206 * update per instance flags and wake up the caller waiting to for the
206207 * response. If it is an event packet then it will schedule event work.
207208 */
208209 static void process_recv(struct ishtp_cl *cros_ish_cl,
209− struct ishtp_cl_rb *rb_in_proc)
210+ struct ishtp_cl_rb *rb_in_proc, ktime_t timestamp)
210211 {
211212 size_t data_len = rb_in_proc->buf_idx;
212213 struct ishtp_cl_data *client_data =
@@ -295,6 +296,11 @@ error_wake_up: · 82 unmodified lines
295296 break;
296297
297298 case CROS_MKBP_EVENT:
299+ /*
300+ * Set timestamp from beginning of function since we actually
301+ * got an incoming MKBP event
302+ */
303+ client_data->ec_dev->last_event_time = timestamp;
298304 /* The event system doesn't send any data in buffer */
299305 schedule_work(&client_data->work_ec_evt);
300306
@@ -322,10 +328,17 @@ static void ish_event_cb(struct ishtp_cl_device *cl_device) · 21 unmodified lines
322328 {
323329 struct ishtp_cl_rb *rb_in_proc;
324330 struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
331+ ktime_t timestamp;
332+
333+ /*
334+ * Take timestamp as close to hardware interrupt as possible for sensor
335+ * timestamps.
336+ */
337+ timestamp = cros_ec_get_time_ns();
325338
326339 while ((rb_in_proc = ishtp_cl_rx_get_rb(cros_ish_cl)) != NULL) {
327340 /* Decide what to do with received data */
328− process_recv(cros_ish_cl, rb_in_proc);
341+ process_recv(cros_ish_cl, rb_in_proc, timestamp);
329342 }
330343 }
331344
drivers/platform/chrome/cros_ec_lpc.c+13−4
@@ -312,11 +312,20 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset, · 311 unmodified lines
312312 static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
313313 {
314314 struct cros_ec_device *ec_dev = data;
315+ bool ec_has_more_events;
316+ int ret;
315317
316− if (ec_dev->mkbp_event_supported &&
317− cros_ec_get_next_event(ec_dev, NULL) > 0)
318− blocking_notifier_call_chain(&ec_dev->event_notifier, 0,
319− ec_dev);
318+ ec_dev->last_event_time = cros_ec_get_time_ns();
319+
320+ if (ec_dev->mkbp_event_supported)
321+ do {
322+ ret = cros_ec_get_next_event(ec_dev, NULL,
323+ &ec_has_more_events);
324+ if (ret > 0)
325+ blocking_notifier_call_chain(
326+ &ec_dev->event_notifier, 0,
327+ ec_dev);
328+ } while (ec_has_more_events);
320329
321330 if (value == ACPI_NOTIFY_DEVICE_WAKE)
322331 pm_system_wakeup();
drivers/platform/chrome/cros_ec_proto.c+237−30
@@ -117,6 +117,17 @@ static int send_command(struct cros_ec_device *ec_dev, · 116 unmodified lines
117117 return ret;
118118 }
119119
120+/**
121+ * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer.
122+ * @ec_dev: Device to register.
123+ * @msg: Message to write.
124+ *
125+ * This is intended to be used by all ChromeOS EC drivers, but at present
126+ * only SPI uses it. Once LPC uses the same protocol it can start using it.
127+ * I2C could use it now, with a refactor of the existing code.
128+ *
129+ * Return: 0 on success or negative error code.
130+ */
120131 int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
121132 struct cros_ec_command *msg)
122133 {
@@ -141,6 +152,16 @@ int cros_ec_prepare_tx(struct cros_ec_device *ec_dev, · 18 unmodified lines
141152 }
142153 EXPORT_SYMBOL(cros_ec_prepare_tx);
143154
155+/**
156+ * cros_ec_check_result() - Check ec_msg->result.
157+ * @ec_dev: EC device.
158+ * @msg: Message to check.
159+ *
160+ * This is used by ChromeOS EC drivers to check the ec_msg->result for
161+ * errors and to warn about them.
162+ *
163+ * Return: 0 on success or negative error code.
164+ */
144165 int cros_ec_check_result(struct cros_ec_device *ec_dev,
145166 struct cros_ec_command *msg)
146167 {
@@ -326,6 +347,13 @@ static int cros_ec_get_host_command_version_mask(struct cros_ec_device *ec_dev, · 179 unmodified lines
326347 return ret;
327348 }
328349
350+/**
351+ * cros_ec_query_all() - Query the protocol version supported by the
352+ * ChromeOS EC.
353+ * @ec_dev: Device to register.
354+ *
355+ * Return: 0 on success or negative error code.
356+ */
329357 int cros_ec_query_all(struct cros_ec_device *ec_dev)
330358 {
331359 struct device *dev = ec_dev->dev;
@@ -428,7 +456,10 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev) · 96 unmodified lines
428456 if (ret < 0 || ver_mask == 0)
429457 ec_dev->mkbp_event_supported = 0;
430458 else
431− ec_dev->mkbp_event_supported = 1;
459+ ec_dev->mkbp_event_supported = fls(ver_mask);
460+
461+ dev_dbg(ec_dev->dev, "MKBP support version %u\n",
462+ ec_dev->mkbp_event_supported - 1);
432463
433464 /* Probe if host sleep v1 is supported for S0ix failure detection. */
434465 ret = cros_ec_get_host_command_version_mask(ec_dev,
@@ -453,6 +484,16 @@ exit: · 18 unmodified lines
453484 }
454485 EXPORT_SYMBOL(cros_ec_query_all);
455486
487+/**
488+ * cros_ec_cmd_xfer() - Send a command to the ChromeOS EC.
489+ * @ec_dev: EC device.
490+ * @msg: Message to write.
491+ *
492+ * Call this to send a command to the ChromeOS EC. This should be used
493+ * instead of calling the EC's cmd_xfer() callback directly.
494+ *
495+ * Return: 0 on success or negative error code.
496+ */
456497 int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
457498 struct cros_ec_command *msg)
458499 {
@@ -500,6 +541,18 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, · 41 unmodified lines
500541 }
501542 EXPORT_SYMBOL(cros_ec_cmd_xfer);
502543
544+/**
545+ * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
546+ * @ec_dev: EC device.
547+ * @msg: Message to write.
548+ *
549+ * This function is identical to cros_ec_cmd_xfer, except it returns success
550+ * status only if both the command was transmitted successfully and the EC
551+ * replied with success status. It's not necessary to check msg->result when
552+ * using this function.
553+ *
554+ * Return: The number of bytes transferred on success or negative error code.
555+ */
503556 int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
504557 struct cros_ec_command *msg)
505558 {
@@ -519,6 +572,7 @@ EXPORT_SYMBOL(cros_ec_cmd_xfer_status); · 13 unmodified lines
519572
520573 static int get_next_event_xfer(struct cros_ec_device *ec_dev,
521574 struct cros_ec_command *msg,
575+ struct ec_response_get_next_event_v1 *event,
522576 int version, uint32_t size)
523577 {
524578 int ret;
@@ -531,7 +585,7 @@ static int get_next_event_xfer(struct cros_ec_device *ec_dev, · 6 unmodified lines
531585 ret = cros_ec_cmd_xfer(ec_dev, msg);
532586 if (ret > 0) {
533587 ec_dev->event_size = ret - 1;
534− memcpy(&ec_dev->event_data, msg->data, ret);
588+ ec_dev->event_data = *event;
535589 }
536590
537591 return ret;
@@ -539,30 +593,26 @@ static int get_next_event_xfer(struct cros_ec_device *ec_dev, · 1 unmodified line
539593
540594 static int get_next_event(struct cros_ec_device *ec_dev)
541595 {
542− u8 buffer[sizeof(struct cros_ec_command) + sizeof(ec_dev->event_data)];
543− struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
544− static int cmd_version = 1;
545− int ret;
596+ struct {
597+ struct cros_ec_command msg;
598+ struct ec_response_get_next_event_v1 event;
599+ } __packed buf;
600+ struct cros_ec_command *msg = &buf.msg;
601+ struct ec_response_get_next_event_v1 *event = &buf.event;
602+ const int cmd_version = ec_dev->mkbp_event_supported - 1;
546603
604+ memset(msg, 0, sizeof(*msg));
547605 if (ec_dev->suspended) {
548606 dev_dbg(ec_dev->dev, "Device suspended.\n");
549607 return -EHOSTDOWN;
550608 }
551609
552− if (cmd_version == 1) {
553− ret = get_next_event_xfer(ec_dev, msg, cmd_version,
554− sizeof(struct ec_response_get_next_event_v1));
555− if (ret < 0 || msg->result != EC_RES_INVALID_VERSION)
556− return ret;
557−
558− /* Fallback to version 0 for future send attempts */
559− cmd_version = 0;
560− }
561−
562− ret = get_next_event_xfer(ec_dev, msg, cmd_version,
610+ if (cmd_version == 0)
611+ return get_next_event_xfer(ec_dev, msg, event, 0,
563612 sizeof(struct ec_response_get_next_event));
564613
565− return ret;
614+ return get_next_event_xfer(ec_dev, msg, event, cmd_version,
615+ sizeof(struct ec_response_get_next_event_v1));
566616 }
567617
568618 static int get_keyboard_state_event(struct cros_ec_device *ec_dev)
@@ -584,27 +634,60 @@ static int get_keyboard_state_event(struct cros_ec_device *ec_dev) · 15 unmodified lines
584634 return ec_dev->event_size;
585635 }
586636
587−int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event)
637+/**
638+ * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC.
639+ * @ec_dev: Device to fetch event from.
640+ * @wake_event: Pointer to a bool set to true upon return if the event might be
641+ * treated as a wake event. Ignored if null.
642+ * @has_more_events: Pointer to bool set to true if more than one event is
643+ * pending.
644+ * Some EC will set this flag to indicate cros_ec_get_next_event()
645+ * can be called multiple times in a row.
646+ * It is an optimization to prevent issuing a EC command for
647+ * nothing or wait for another interrupt from the EC to process
648+ * the next message.
649+ * Ignored if null.
650+ *
651+ * Return: negative error code on errors; 0 for no data; or else number of
652+ * bytes received (i.e., an event was retrieved successfully). Event types are
653+ * written out to @ec_dev->event_data.event_type on success.
654+ */
655+int cros_ec_get_next_event(struct cros_ec_device *ec_dev,
656+ bool *wake_event,
657+ bool *has_more_events)
588658 {
589659 u8 event_type;
590660 u32 host_event;
591661 int ret;
592662
593− if (!ec_dev->mkbp_event_supported) {
594− ret = get_keyboard_state_event(ec_dev);
595− if (ret <= 0)
596− return ret;
663+ /*
664+ * Default value for wake_event.
665+ * Wake up on keyboard event, wake up for spurious interrupt or link
666+ * error to the EC.
667+ */
668+ if (wake_event)
669+ *wake_event = true;
597670
598− if (wake_event)
599− *wake_event = true;
671+ /*
672+ * Default value for has_more_events.
673+ * EC will raise another interrupt if AP does not process all events
674+ * anyway.
675+ */
676+ if (has_more_events)
677+ *has_more_events = false;
600678
601− return ret;
602− }
679+ if (!ec_dev->mkbp_event_supported)
680+ return get_keyboard_state_event(ec_dev);
603681
604682 ret = get_next_event(ec_dev);
605683 if (ret <= 0)
606684 return ret;
607685
686+ if (has_more_events)
687+ *has_more_events = ec_dev->event_data.event_type &
688+ EC_MKBP_HAS_MORE_EVENTS;
689+ ec_dev->event_data.event_type &= EC_MKBP_EVENT_TYPE_MASK;
690+
608691 if (wake_event) {
609692 event_type = ec_dev->event_data.event_type;
610693 host_event = cros_ec_get_host_event(ec_dev);
@@ -619,15 +702,22 @@ int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event) · 8 unmodified lines
619702 else if (host_event &&
620703 !(host_event & ec_dev->host_event_wake_mask))
621704 *wake_event = false;
622− /* Consider all other events as wake events. */
623− else
624− *wake_event = true;
625705 }
626706
627707 return ret;
628708 }
629709 EXPORT_SYMBOL(cros_ec_get_next_event);
630710
711+/**
712+ * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC.
713+ * @ec_dev: Device to fetch event from.
714+ *
715+ * When MKBP is supported, when the EC raises an interrupt, we collect the
716+ * events raised and call the functions in the ec notifier. This function
717+ * is a helper to know which events are raised.
718+ *
719+ * Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*.
720+ */
631721 u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev)
632722 {
633723 u32 host_event;
@@ -647,3 +737,120 @@ u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev) · 13 unmodified lines
647737 return host_event;
648738 }
649739 EXPORT_SYMBOL(cros_ec_get_host_event);
740+
741+/**
742+ * cros_ec_check_features() - Test for the presence of EC features
743+ *
744+ * @ec: EC device, does not have to be connected directly to the AP,
745+ * can be daisy chained through another device.
746+ * @feature: One of ec_feature_code bit.
747+ *
748+ * Call this function to test whether the ChromeOS EC supports a feature.
749+ *
750+ * Return: 1 if supported, 0 if not
751+ */
752+int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
753+{
754+ struct cros_ec_command *msg;
755+ int ret;
756+
757+ if (ec->features[0] == -1U && ec->features[1] == -1U) {
758+ /* features bitmap not read yet */
759+ msg = kzalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
760+ if (!msg)
761+ return -ENOMEM;
762+
763+ msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
764+ msg->insize = sizeof(ec->features);
765+
766+ ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
767+ if (ret < 0) {
768+ dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
769+ ret, msg->result);
770+ memset(ec->features, 0, sizeof(ec->features));
771+ } else {
772+ memcpy(ec->features, msg->data, sizeof(ec->features));
773+ }
774+
775+ dev_dbg(ec->dev, "EC features %08x %08x\n",
776+ ec->features[0], ec->features[1]);
777+
778+ kfree(msg);
779+ }
780+
781+ return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature);
782+}
783+EXPORT_SYMBOL_GPL(cros_ec_check_features);
784+
785+/**
786+ * cros_ec_get_sensor_count() - Return the number of MEMS sensors supported.
787+ *
788+ * @ec: EC device, does not have to be connected directly to the AP,
789+ * can be daisy chained through another device.
790+ * Return: < 0 in case of error.
791+ */
792+int cros_ec_get_sensor_count(struct cros_ec_dev *ec)
793+{
794+ /*
795+ * Issue a command to get the number of sensor reported.
796+ * If not supported, check for legacy mode.
797+ */
798+ int ret, sensor_count;
799+ struct ec_params_motion_sense *params;
800+ struct ec_response_motion_sense *resp;
801+ struct cros_ec_command *msg;
802+ struct cros_ec_device *ec_dev = ec->ec_dev;
803+ u8 status;
804+
805+ msg = kzalloc(sizeof(*msg) + max(sizeof(*params), sizeof(*resp)),
806+ GFP_KERNEL);
807+ if (!msg)
808+ return -ENOMEM;
809+
810+ msg->version = 1;
811+ msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
812+ msg->outsize = sizeof(*params);
813+ msg->insize = sizeof(*resp);
814+
815+ params = (struct ec_params_motion_sense *)msg->data;
816+ params->cmd = MOTIONSENSE_CMD_DUMP;
817+
818+ ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
819+ if (ret < 0) {
820+ sensor_count = ret;
821+ } else if (msg->result != EC_RES_SUCCESS) {
822+ sensor_count = -EPROTO;
823+ } else {
824+ resp = (struct ec_response_motion_sense *)msg->data;
825+ sensor_count = resp->dump.sensor_count;
826+ }
827+ kfree(msg);
828+
829+ /*
830+ * Check legacy mode: Let's find out if sensors are accessible
831+ * via LPC interface.
832+ */
833+ if (sensor_count == -EPROTO &&
834+ ec->cmd_offset == 0 &&
835+ ec_dev->cmd_readmem) {
836+ ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS,
837+ 1, &status);
838+ if (ret >= 0 &&
839+ (status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT)) {
840+ /*
841+ * We have 2 sensors, one in the lid, one in the base.
842+ */
843+ sensor_count = 2;
844+ } else {
845+ /*
846+ * EC uses LPC interface and no sensors are presented.
847+ */
848+ sensor_count = 0;
849+ }
850+ } else if (sensor_count == -EPROTO) {
851+ /* EC responded, but does not understand DUMP command. */
852+ sensor_count = 0;
853+ }
854+ return sensor_count;
855+}
856+EXPORT_SYMBOL_GPL(cros_ec_get_sensor_count);
drivers/platform/chrome/cros_ec_rpmsg.c+4−15
@@ -143,22 +143,11 @@ cros_ec_rpmsg_host_event_function(struct work_struct *host_event_work) · 142 unmodified lines
143143 struct cros_ec_rpmsg,
144144 host_event_work);
145145 struct cros_ec_device *ec_dev = dev_get_drvdata(&ec_rpmsg->rpdev->dev);
146− bool wake_event = true;
147− int ret;
148−
149− ret = cros_ec_get_next_event(ec_dev, &wake_event);
150−
151− /*
152− * Signal only if wake host events or any interrupt if
153− * cros_ec_get_next_event() returned an error (default value for
154− * wake_event is true)
155− */
156− if (wake_event && device_may_wakeup(ec_dev->dev))
157− pm_wakeup_event(ec_dev->dev, 0);
146+ bool ec_has_more_events;
158147
159− if (ret > 0)
160− blocking_notifier_call_chain(&ec_dev->event_notifier,
161− 0, ec_dev);
148+ do {
149+ ec_has_more_events = cros_ec_handle_event(ec_dev);
150+ } while (ec_has_more_events);
162151 }
163152
164153 static int cros_ec_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
drivers/platform/chrome/cros_ec_sensorhub.c+199−0
@@ -0,0 +1,199 @@
1+// SPDX-License-Identifier: GPL-2.0
2+/*
3+ * Sensor HUB driver that discovers sensors behind a ChromeOS Embedded
4+ * Controller.
5+ *
6+ * Copyright 2019 Google LLC
7+ */
8+
9+#include <linux/init.h>
10+#include <linux/device.h>
11+#include <linux/module.h>
12+#include <linux/mfd/cros_ec.h>
13+#include <linux/platform_data/cros_ec_commands.h>
14+#include <linux/platform_data/cros_ec_proto.h>
15+#include <linux/platform_data/cros_ec_sensorhub.h>
16+#include <linux/platform_device.h>
17+#include <linux/slab.h>
18+#include <linux/types.h>
19+
20+#define DRV_NAME "cros-ec-sensorhub"
21+
22+static void cros_ec_sensorhub_free_sensor(void *arg)
23+{
24+ struct platform_device *pdev = arg;
25+
26+ platform_device_unregister(pdev);
27+}
28+
29+static int cros_ec_sensorhub_allocate_sensor(struct device *parent,
30+ char *sensor_name,
31+ int sensor_num)
32+{
33+ struct cros_ec_sensor_platform sensor_platforms = {
34+ .sensor_num = sensor_num,
35+ };
36+ struct platform_device *pdev;
37+
38+ pdev = platform_device_register_data(parent, sensor_name,
39+ PLATFORM_DEVID_AUTO,
40+ &sensor_platforms,
41+ sizeof(sensor_platforms));
42+ if (IS_ERR(pdev))
43+ return PTR_ERR(pdev);
44+
45+ return devm_add_action_or_reset(parent,
46+ cros_ec_sensorhub_free_sensor,
47+ pdev);
48+}
49+
50+static int cros_ec_sensorhub_register(struct device *dev,
51+ struct cros_ec_sensorhub *sensorhub)
52+{
53+ int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 };
54+ struct cros_ec_dev *ec = sensorhub->ec;
55+ struct ec_params_motion_sense *params;
56+ struct ec_response_motion_sense *resp;
57+ struct cros_ec_command *msg;
58+ int ret, i, sensor_num;
59+ char *name;
60+
61+ sensor_num = cros_ec_get_sensor_count(ec);
62+ if (sensor_num < 0) {
63+ dev_err(dev,
64+ "Unable to retrieve sensor information (err:%d)\n",
65+ sensor_num);
66+ return sensor_num;
67+ }
68+
69+ if (sensor_num == 0) {
70+ dev_err(dev, "Zero sensors reported.\n");
71+ return -EINVAL;
72+ }
73+
74+ /* Prepare a message to send INFO command to each sensor. */
75+ msg = kzalloc(sizeof(*msg) + max(sizeof(*params), sizeof(*resp)),
76+ GFP_KERNEL);
77+ if (!msg)
78+ return -ENOMEM;
79+
80+ msg->version = 1;
81+ msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
82+ msg->outsize = sizeof(*params);
83+ msg->insize = sizeof(*resp);
84+ params = (struct ec_params_motion_sense *)msg->data;
85+ resp = (struct ec_response_motion_sense *)msg->data;
86+
87+ for (i = 0; i < sensor_num; i++) {
88+ params->cmd = MOTIONSENSE_CMD_INFO;
89+ params->info.sensor_num = i;
90+
91+ ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
92+ if (ret < 0) {
93+ dev_warn(dev, "no info for EC sensor %d : %d/%d\n",
94+ i, ret, msg->result);
95+ continue;
96+ }
97+
98+ switch (resp->info.type) {
99+ case MOTIONSENSE_TYPE_ACCEL:
100+ name = "cros-ec-accel";
101+ break;
102+ case MOTIONSENSE_TYPE_BARO:
103+ name = "cros-ec-baro";
104+ break;
105+ case MOTIONSENSE_TYPE_GYRO:
106+ name = "cros-ec-gyro";
107+ break;
108+ case MOTIONSENSE_TYPE_MAG:
109+ name = "cros-ec-mag";
110+ break;
111+ case MOTIONSENSE_TYPE_PROX:
112+ name = "cros-ec-prox";
113+ break;
114+ case MOTIONSENSE_TYPE_LIGHT:
115+ name = "cros-ec-light";
116+ break;
117+ case MOTIONSENSE_TYPE_ACTIVITY:
118+ name = "cros-ec-activity";
119+ break;
120+ default:
121+ dev_warn(dev, "unknown type %d\n", resp->info.type);
122+ continue;
123+ }
124+
125+ ret = cros_ec_sensorhub_allocate_sensor(dev, name, i);
126+ if (ret)
127+ goto error;
128+
129+ sensor_type[resp->info.type]++;
130+ }
131+
132+ if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2)
133+ ec->has_kb_wake_angle = true;
134+
135+ if (cros_ec_check_features(ec,
136+ EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS)) {
137+ ret = cros_ec_sensorhub_allocate_sensor(dev,
138+ "cros-ec-lid-angle",
139+ 0);
140+ if (ret)
141+ goto error;
142+ }
143+
144+ kfree(msg);
145+ return 0;
146+
147+error:
148+ kfree(msg);
149+ return ret;
150+}
151+
152+static int cros_ec_sensorhub_probe(struct platform_device *pdev)
153+{
154+ struct device *dev = &pdev->dev;
155+ struct cros_ec_sensorhub *data;
156+ int ret;
157+ int i;
158+
159+ data = devm_kzalloc(dev, sizeof(struct cros_ec_sensorhub), GFP_KERNEL);
160+ if (!data)
161+ return -ENOMEM;
162+
163+ data->ec = dev_get_drvdata(dev->parent);
164+ dev_set_drvdata(dev, data);
165+
166+ /* Check whether this EC is a sensor hub. */
167+ if (cros_ec_check_features(data->ec, EC_FEATURE_MOTION_SENSE)) {
168+ ret = cros_ec_sensorhub_register(dev, data);
169+ if (ret)
170+ return ret;
171+ } else {
172+ /*
173+ * If the device has sensors but does not claim to
174+ * be a sensor hub, we are in legacy mode.
175+ */
176+ for (i = 0; i < 2; i++) {
177+ ret = cros_ec_sensorhub_allocate_sensor(dev,
178+ "cros-ec-accel-legacy", i);
179+ if (ret)
180+ return ret;
181+ }
182+ }
183+
184+ return 0;
185+}
186+
187+static struct platform_driver cros_ec_sensorhub_driver = {
188+ .driver = {
189+ .name = DRV_NAME,
190+ },
191+ .probe = cros_ec_sensorhub_probe,
192+};
193+
194+module_platform_driver(cros_ec_sensorhub_driver);
195+
196+MODULE_ALIAS("platform:" DRV_NAME);
197+MODULE_AUTHOR("Gwendal Grignou <gwendal@chromium.org>");
198+MODULE_DESCRIPTION("ChromeOS EC MEMS Sensor Hub Driver");
199+MODULE_LICENSE("GPL");
include/linux/platform_data/cros_ec_proto.h+27−111
@@ -12,6 +12,7 @@ · 11 unmodified lines
1212 #include <linux/mutex.h>
1313 #include <linux/notifier.h>
1414
15+#include <linux/mfd/cros_ec.h>
1516 #include <linux/platform_data/cros_ec_commands.h>
1617
1718 #define CROS_EC_DEV_NAME "cros_ec"
@@ -115,12 +116,16 @@ struct cros_ec_command { · 97 unmodified lines
115116 * code.
116117 * @pkt_xfer: Send packet to EC and get response.
117118 * @lock: One transaction at a time.
118− * @mkbp_event_supported: True if this EC supports the MKBP event protocol.
119+ * @mkbp_event_supported: 0 if MKBP not supported. Otherwise its value is
120+ * the maximum supported version of the MKBP host event
121+ * command + 1.
119122 * @host_sleep_v1: True if this EC supports the sleep v1 command.
120123 * @event_notifier: Interrupt event notifier for transport devices.
121124 * @event_data: Raw payload transferred with the MKBP event.
122125 * @event_size: Size in bytes of the event data.
123126 * @host_event_wake_mask: Mask of host events that cause wake from suspend.
127+ * @last_event_time: exact time from the hard irq when we got notified of
128+ * a new event.
124129 * @ec: The platform_device used by the mfd driver to interface with the
125130 * main EC.
126131 * @pd: The platform_device used by the mfd driver to interface with the
@@ -153,7 +158,7 @@ struct cros_ec_device { · 26 unmodified lines
153158 int (*pkt_xfer)(struct cros_ec_device *ec,
154159 struct cros_ec_command *msg);
155160 struct mutex lock;
156− bool mkbp_event_supported;
161+ u8 mkbp_event_supported;
157162 bool host_sleep_v1;
158163 struct blocking_notifier_head event_notifier;
159164
@@ -161,20 +166,13 @@ struct cros_ec_device { · 1 unmodified line
161166 int event_size;
162167 u32 host_event_wake_mask;
163168 u32 last_resume_result;
169+ ktime_t last_event_time;
164170
165171 /* The platform devices used by the mfd driver */
166172 struct platform_device *ec;
167173 struct platform_device *pd;
168174 };
169175
170−/**
171− * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information.
172− * @sensor_num: Id of the sensor, as reported by the EC.
173− */
174−struct cros_ec_sensor_platform {
175− u8 sensor_num;
176−};
177−
178176 /**
179177 * struct cros_ec_platform - ChromeOS EC platform information.
180178 * @ec_name: Name of EC device (e.g. 'cros-ec', 'cros-pd', ...)
@@ -187,133 +185,51 @@ struct cros_ec_platform { · 6 unmodified lines
187185 u16 cmd_offset;
188186 };
189187
190−/**
191− * cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device.
192− * @ec_dev: Device to suspend.
193− *
194− * This can be called by drivers to handle a suspend event.
195− *
196− * Return: 0 on success or negative error code.
197− */
198188 int cros_ec_suspend(struct cros_ec_device *ec_dev);
199189
200−/**
201− * cros_ec_resume() - Handle a resume operation for the ChromeOS EC device.
202− * @ec_dev: Device to resume.
203− *
204− * This can be called by drivers to handle a resume event.
205− *
206− * Return: 0 on success or negative error code.
207− */
208190 int cros_ec_resume(struct cros_ec_device *ec_dev);
209191
210−/**
211− * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer.
212− * @ec_dev: Device to register.
213− * @msg: Message to write.
214− *
215− * This is intended to be used by all ChromeOS EC drivers, but at present
216− * only SPI uses it. Once LPC uses the same protocol it can start using it.
217− * I2C could use it now, with a refactor of the existing code.
218− *
219− * Return: 0 on success or negative error code.
220− */
221192 int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
222193 struct cros_ec_command *msg);
223194
224−/**
225− * cros_ec_check_result() - Check ec_msg->result.
226− * @ec_dev: EC device.
227− * @msg: Message to check.
228− *
229− * This is used by ChromeOS EC drivers to check the ec_msg->result for
230− * errors and to warn about them.
231− *
232− * Return: 0 on success or negative error code.
233− */
234195 int cros_ec_check_result(struct cros_ec_device *ec_dev,
235196 struct cros_ec_command *msg);
236197
237−/**
238− * cros_ec_cmd_xfer() - Send a command to the ChromeOS EC.
239− * @ec_dev: EC device.
240− * @msg: Message to write.
241− *
242− * Call this to send a command to the ChromeOS EC. This should be used
243− * instead of calling the EC's cmd_xfer() callback directly.
244− *
245− * Return: 0 on success or negative error code.
246− */
247198 int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
248199 struct cros_ec_command *msg);
249200
250−/**
251− * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
252− * @ec_dev: EC device.
253− * @msg: Message to write.
254− *
255− * This function is identical to cros_ec_cmd_xfer, except it returns success
256− * status only if both the command was transmitted successfully and the EC
257− * replied with success status. It's not necessary to check msg->result when
258− * using this function.
259− *
260− * Return: The number of bytes transferred on success or negative error code.
261− */
262201 int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
263202 struct cros_ec_command *msg);
264203
265−/**
266− * cros_ec_register() - Register a new ChromeOS EC, using the provided info.
267− * @ec_dev: Device to register.
268− *
269− * Before calling this, allocate a pointer to a new device and then fill
270− * in all the fields up to the --private-- marker.
271− *
272− * Return: 0 on success or negative error code.
273− */
274204 int cros_ec_register(struct cros_ec_device *ec_dev);
275205
276−/**
277− * cros_ec_unregister() - Remove a ChromeOS EC.
278− * @ec_dev: Device to unregister.
279− *
280− * Call this to deregister a ChromeOS EC, then clean up any private data.
281− *
282− * Return: 0 on success or negative error code.
283− */
284206 int cros_ec_unregister(struct cros_ec_device *ec_dev);
285207
286−/**
287− * cros_ec_query_all() - Query the protocol version supported by the
288− * ChromeOS EC.
289− * @ec_dev: Device to register.
290− *
291− * Return: 0 on success or negative error code.
292− */
293208 int cros_ec_query_all(struct cros_ec_device *ec_dev);
294209
295−/**
296− * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC.
297− * @ec_dev: Device to fetch event from.
298− * @wake_event: Pointer to a bool set to true upon return if the event might be
299− * treated as a wake event. Ignored if null.
300− *
301− * Return: negative error code on errors; 0 for no data; or else number of
302− * bytes received (i.e., an event was retrieved successfully). Event types are
303− * written out to @ec_dev->event_data.event_type on success.
304− */
305−int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event);
210+int cros_ec_get_next_event(struct cros_ec_device *ec_dev,
211+ bool *wake_event,
212+ bool *has_more_events);
213+
214+u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev);
215+
216+int cros_ec_check_features(struct cros_ec_dev *ec, int feature);
217+
218+int cros_ec_get_sensor_count(struct cros_ec_dev *ec);
219+
220+bool cros_ec_handle_event(struct cros_ec_device *ec_dev);
306221
307222 /**
308− * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC.
309− * @ec_dev: Device to fetch event from.
223+ * cros_ec_get_time_ns() - Return time in ns.
310224 *
311− * When MKBP is supported, when the EC raises an interrupt, we collect the
312− * events raised and call the functions in the ec notifier. This function
313− * is a helper to know which events are raised.
225+ * This is the function used to record the time for last_event_time in struct
226+ * cros_ec_device during the hard irq.
314227 *
315− * Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*.
228+ * Return: ktime_t format since boot.
316229 */
317−u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev);
230+static inline ktime_t cros_ec_get_time_ns(void)
231+{
232+ return ktime_get_boottime_ns();
233+}
318234
319235 #endif /* __LINUX_CROS_EC_PROTO_H */
include/linux/platform_data/cros_ec_sensorhub.h+30−0
@@ -0,0 +1,30 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+/*
3+ * Chrome OS EC MEMS Sensor Hub driver.
4+ *
5+ * Copyright 2019 Google LLC
6+ */
7+
8+#ifndef __LINUX_PLATFORM_DATA_CROS_EC_SENSORHUB_H
9+#define __LINUX_PLATFORM_DATA_CROS_EC_SENSORHUB_H
10+
11+#include <linux/platform_data/cros_ec_commands.h>
12+
13+/**
14+ * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information.
15+ * @sensor_num: Id of the sensor, as reported by the EC.
16+ */
17+struct cros_ec_sensor_platform {
18+ u8 sensor_num;
19+};
20+
21+/**
22+ * struct cros_ec_sensorhub - Sensor Hub device data.
23+ *
24+ * @ec: Embedded Controller where the hub is located.
25+ */
26+struct cros_ec_sensorhub {
27+ struct cros_ec_dev *ec;
28+};
29+
30+#endif /* __LINUX_PLATFORM_DATA_CROS_EC_SENSORHUB_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t