Skip to content

Commit 05a3c42

Browse files
gwendalcrEnric Balletbo i Serra
authored andcommitted
platform/chrome: cros-ec: Record event timestamp in the hard irq
To improve sensor timestamp precision, given EC and AP are in different time domains, the AP needs to try to record the exact moment an event was signalled to the AP by the EC as soon as possible after it happens. First thing in the hard irq is the best place for this. Signed-off-by: Gwendal Grignou <[email protected]> Acked-by: Jonathan Cameron <[email protected]> Acked-by: Lee Jones <[email protected]> Signed-off-by: Enric Balletbo i Serra <[email protected]>
1 parent d60ac88 commit 05a3c42

File tree

4 files changed

+47
-5
lines changed

4 files changed

+47
-5
lines changed

drivers/platform/chrome/cros_ec.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ static struct cros_ec_platform pd_p = {
3131
.cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX),
3232
};
3333

34+
static irqreturn_t ec_irq_handler(int irq, void *data)
35+
{
36+
struct cros_ec_device *ec_dev = data;
37+
38+
ec_dev->last_event_time = cros_ec_get_time_ns();
39+
40+
return IRQ_WAKE_THREAD;
41+
}
42+
3443
static irqreturn_t ec_irq_thread(int irq, void *data)
3544
{
3645
struct cros_ec_device *ec_dev = data;
@@ -141,9 +150,11 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
141150
}
142151

143152
if (ec_dev->irq) {
144-
err = devm_request_threaded_irq(dev, ec_dev->irq, NULL,
145-
ec_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
146-
"chromeos-ec", ec_dev);
153+
err = devm_request_threaded_irq(dev, ec_dev->irq,
154+
ec_irq_handler,
155+
ec_irq_thread,
156+
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
157+
"chromeos-ec", ec_dev);
147158
if (err) {
148159
dev_err(dev, "Failed to request IRQ %d: %d",
149160
ec_dev->irq, err);

drivers/platform/chrome/cros_ec_ishtp.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,13 +200,14 @@ static int ish_send(struct ishtp_cl_data *client_data,
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 @@ static void process_recv(struct ishtp_cl *cros_ish_cl,
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)
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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,8 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
313313
{
314314
struct cros_ec_device *ec_dev = data;
315315

316+
ec_dev->last_event_time = cros_ec_get_time_ns();
317+
316318
if (ec_dev->mkbp_event_supported &&
317319
cros_ec_get_next_event(ec_dev, NULL) > 0)
318320
blocking_notifier_call_chain(&ec_dev->event_notifier, 0,

include/linux/platform_data/cros_ec_proto.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ struct cros_ec_command {
122122
* @event_data: Raw payload transferred with the MKBP event.
123123
* @event_size: Size in bytes of the event data.
124124
* @host_event_wake_mask: Mask of host events that cause wake from suspend.
125+
* @last_event_time: exact time from the hard irq when we got notified of
126+
* a new event.
125127
* @ec: The platform_device used by the mfd driver to interface with the
126128
* main EC.
127129
* @pd: The platform_device used by the mfd driver to interface with the
@@ -162,6 +164,7 @@ struct cros_ec_device {
162164
int event_size;
163165
u32 host_event_wake_mask;
164166
u32 last_resume_result;
167+
ktime_t last_event_time;
165168

166169
/* The platform devices used by the mfd driver */
167170
struct platform_device *ec;
@@ -210,4 +213,17 @@ int cros_ec_check_features(struct cros_ec_dev *ec, int feature);
210213

211214
int cros_ec_get_sensor_count(struct cros_ec_dev *ec);
212215

216+
/**
217+
* cros_ec_get_time_ns() - Return time in ns.
218+
*
219+
* This is the function used to record the time for last_event_time in struct
220+
* cros_ec_device during the hard irq.
221+
*
222+
* Return: ktime_t format since boot.
223+
*/
224+
static inline ktime_t cros_ec_get_time_ns(void)
225+
{
226+
return ktime_get_boottime_ns();
227+
}
228+
213229
#endif /* __LINUX_CROS_EC_PROTO_H */

0 commit comments

Comments
 (0)