summaryrefslogtreecommitdiff
path: root/include/linux/platform_data/cros_ec_proto.h
blob: 8865e350c12a5f687f1f7dd0f09d96fb8fb22db3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * ChromeOS Embedded Controller protocol interface.
 *
 * Copyright (C) 2012 Google, Inc
 */

#ifndef __LINUX_CROS_EC_PROTO_H
#define __LINUX_CROS_EC_PROTO_H

#include <linux/device.h>
#include <linux/lockdep_types.h>
#include <linux/mutex.h>
#include <linux/notifier.h>

#include <linux/platform_data/cros_ec_commands.h>

#define CROS_EC_DEV_NAME	"cros_ec"
#define CROS_EC_DEV_FP_NAME	"cros_fp"
#define CROS_EC_DEV_ISH_NAME	"cros_ish"
#define CROS_EC_DEV_PD_NAME	"cros_pd"
#define CROS_EC_DEV_SCP_NAME	"cros_scp"
#define CROS_EC_DEV_TP_NAME	"cros_tp"

#define CROS_EC_DEV_EC_INDEX 0
#define CROS_EC_DEV_PD_INDEX 1

/*
 * The EC is unresponsive for a time after a reboot command.  Add a
 * simple delay to make sure that the bus stays locked.
 */
#define EC_REBOOT_DELAY_MS		50

/*
 * Max bus-specific overhead incurred by request/responses.
 * I2C requires 1 additional byte for requests.
 * I2C requires 2 additional bytes for responses.
 * SPI requires up to 32 additional bytes for responses.
 */
#define EC_PROTO_VERSION_UNKNOWN	0
#define EC_MAX_REQUEST_OVERHEAD		1
#define EC_MAX_RESPONSE_OVERHEAD	32

/*
 * EC panic is not covered by the standard (0-F) ACPI notify values.
 * Arbitrarily choosing B0 to notify ec panic, which is in the 84-BF
 * device specific ACPI notify range.
 */
#define ACPI_NOTIFY_CROS_EC_PANIC 0xB0

/*
 * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
 */
enum {
	EC_MSG_TX_HEADER_BYTES	= 3,
	EC_MSG_TX_TRAILER_BYTES	= 1,
	EC_MSG_TX_PROTO_BYTES	= EC_MSG_TX_HEADER_BYTES +
				  EC_MSG_TX_TRAILER_BYTES,
	EC_MSG_RX_PROTO_BYTES	= 3,

	/* Max length of messages for proto 2*/
	EC_PROTO2_MSG_BYTES	= EC_PROTO2_MAX_PARAM_SIZE +
				  EC_MSG_TX_PROTO_BYTES,

	EC_MAX_MSG_BYTES	= 64 * 1024,
};

/**
 * struct cros_ec_command - Information about a ChromeOS EC command.
 * @version: Command version number (often 0).
 * @command: Command to send (EC_CMD_...).
 * @outsize: Outgoing length in bytes.
 * @insize: Max number of bytes to accept from the EC.
 * @result: EC's response to the command (separate from communication failure).
 * @data: Where to put the incoming data from EC and outgoing data to EC.
 */
struct cros_ec_command {
	uint32_t version;
	uint32_t command;
	uint32_t outsize;
	uint32_t insize;
	uint32_t result;
	uint8_t data[];
};

/**
 * struct cros_ec_device - Information about a ChromeOS EC device.
 * @phys_name: Name of physical comms layer (e.g. 'i2c-4').
 * @dev: Device pointer for physical comms device
 * @cros_class: The class structure for this device.
 * @cmd_readmem: Direct read of the EC memory-mapped region, if supported.
 *     @offset: Is within EC_LPC_ADDR_MEMMAP region.
 *     @bytes: Number of bytes to read. zero means "read a string" (including
 *             the trailing '\0'). At most only EC_MEMMAP_SIZE bytes can be
 *             read. Caller must ensure that the buffer is large enough for the
 *             result when reading a string.
 * @max_request: Max size of message requested.
 * @max_response: Max size of message response.
 * @max_passthru: Max sice of passthru message.
 * @proto_version: The protocol version used for this device.
 * @priv: Private data.
 * @irq: Interrupt to use.
 * @id: Device id.
 * @din: Input buffer (for data from EC). This buffer will always be
 *       dword-aligned and include enough space for up to 7 word-alignment
 *       bytes also, so we can ensure that the body of the message is always
 *       dword-aligned (64-bit). We use this alignment to keep ARM and x86
 *       happy. Probably word alignment would be OK, there might be a small
 *       performance advantage to using dword.
 * @dout: Output buffer (for data to EC). This buffer will always be
 *        dword-aligned and include enough space for up to 7 word-alignment
 *        bytes also, so we can ensure that the body of the message is always
 *        dword-aligned (64-bit). We use this alignment to keep ARM and x86
 *        happy. Probably word alignment would be OK, there might be a small
 *        performance advantage to using dword.
 * @din_size: Size of din buffer to allocate (zero to use static din).
 * @dout_size: Size of dout buffer to allocate (zero to use static dout).
 * @wake_enabled: True if this device can wake the system from sleep.
 * @suspended: True if this device had been suspended.
 * @cmd_xfer: Send command to EC and get response.
 *            Returns the number of bytes received if the communication
 *            succeeded, but that doesn't mean the EC was happy with the
 *            command. The caller should check msg.result for the EC's result
 *            code.
 * @pkt_xfer: Send packet to EC and get response.
 * @lockdep_key: Lockdep class for each instance. Unused if CONFIG_LOCKDEP is
 *		 not enabled.
 * @lock: One transaction at a time.
 * @mkbp_event_supported: 0 if MKBP not supported. Otherwise its value is
 *                        the maximum supported version of the MKBP host event
 *                        command + 1.
 * @host_sleep_v1: True if this EC supports the sleep v1 command.
 * @event_notifier: Interrupt event notifier for transport devices.
 * @event_data: Raw payload transferred with the MKBP event.
 * @event_size: Size in bytes of the event data.
 * @host_event_wake_mask: Mask of host events that cause wake from suspend.
 * @suspend_timeout_ms: The timeout in milliseconds between when sleep event
 *                      is received and when the EC will declare sleep
 *                      transition failure if the sleep signal is not
 *                      asserted.  See also struct
 *                      ec_params_host_sleep_event_v1 in cros_ec_commands.h.
 * @last_resume_result: The number of sleep power signal transitions that
 *                      occurred since the suspend message. The high bit
 *                      indicates a timeout occurred.  See also struct
 *                      ec_response_host_sleep_event_v1 in cros_ec_commands.h.
 * @last_event_time: exact time from the hard irq when we got notified of
 *     a new event.
 * @notifier_ready: The notifier_block to let the kernel re-query EC
 *		    communication protocol when the EC sends
 *		    EC_HOST_EVENT_INTERFACE_READY.
 * @ec: The platform_device used by the mfd driver to interface with the
 *      main EC.
 * @pd: The platform_device used by the mfd driver to interface with the
 *      PD behind an EC.
 * @panic_notifier: EC panic notifier.
 */
struct cros_ec_device {
	/* These are used by other drivers that want to talk to the EC */
	const char *phys_name;
	struct device *dev;
	struct class *cros_class;
	int (*cmd_readmem)(struct cros_ec_device *ec, unsigned int offset,
			   unsigned int bytes, void *dest);

	/* These are used to implement the platform-specific interface */
	u16 max_request;
	u16 max_response;
	u16 max_passthru;
	u16 proto_version;
	void *priv;
	int irq;
	u8 *din;
	u8 *dout;
	int din_size;
	int dout_size;
	bool wake_enabled;
	bool suspended;
	int (*cmd_xfer)(struct cros_ec_device *ec,
			struct cros_ec_command *msg);
	int (*pkt_xfer)(struct cros_ec_device *ec,
			struct cros_ec_command *msg);
	struct lock_class_key lockdep_key;
	struct mutex lock;
	u8 mkbp_event_supported;
	bool host_sleep_v1;
	struct blocking_notifier_head event_notifier;

	struct ec_response_get_next_event_v1 event_data;
	int event_size;
	u32 host_event_wake_mask;
	u32 last_resume_result;
	u16 suspend_timeout_ms;
	ktime_t last_event_time;
	struct notifier_block notifier_ready;

	/* The platform devices used by the mfd driver */
	struct platform_device *ec;
	struct platform_device *pd;

	struct blocking_notifier_head panic_notifier;
};

/**
 * struct cros_ec_platform - ChromeOS EC platform information.
 * @ec_name: Name of EC device (e.g. 'cros-ec', 'cros-pd', ...)
 *           used in /dev/ and sysfs.
 * @cmd_offset: Offset to apply for each command. Set when
 *              registering a device behind another one.
 */
struct cros_ec_platform {
	const char *ec_name;
	u16 cmd_offset;
};

/**
 * struct cros_ec_dev - ChromeOS EC device entry point.
 * @class_dev: Device structure used in sysfs.
 * @ec_dev: cros_ec_device structure to talk to the physical device.
 * @dev: Pointer to the platform device.
 * @debug_info: cros_ec_debugfs structure for debugging information.
 * @has_kb_wake_angle: True if at least 2 accelerometer are connected to the EC.
 * @cmd_offset: Offset to apply for each command.
 * @features: Features supported by the EC.
 */
struct cros_ec_dev {
	struct device class_dev;
	struct cros_ec_device *ec_dev;
	struct device *dev;
	struct cros_ec_debugfs *debug_info;
	bool has_kb_wake_angle;
	u16 cmd_offset;
	struct ec_response_get_features features;
};

#define to_cros_ec_dev(dev)  container_of(dev, struct cros_ec_dev, class_dev)

int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
		       struct cros_ec_command *msg);

int cros_ec_check_result(struct cros_ec_device *ec_dev,
			 struct cros_ec_command *msg);

int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
		     struct cros_ec_command *msg);

int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
			    struct cros_ec_command *msg);

int cros_ec_query_all(struct cros_ec_device *ec_dev);

int cros_ec_get_next_event(struct cros_ec_device *ec_dev,
			   bool *wake_event,
			   bool *has_more_events);

u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev);

bool cros_ec_check_features(struct cros_ec_dev *ec, int feature);

int cros_ec_get_sensor_count(struct cros_ec_dev *ec);

int cros_ec_cmd(struct cros_ec_device *ec_dev, unsigned int version, int command, const void *outdata,
		    size_t outsize, void *indata, size_t insize);

/**
 * cros_ec_get_time_ns() - Return time in ns.
 *
 * This is the function used to record the time for last_event_time in struct
 * cros_ec_device during the hard irq.
 *
 * Return: ktime_t format since boot.
 */
static inline ktime_t cros_ec_get_time_ns(void)
{
	return ktime_get_boottime_ns();
}

#endif /* __LINUX_CROS_EC_PROTO_H */