1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun // LPC interface for ChromeOS Embedded Controller
3*4882a593Smuzhiyun //
4*4882a593Smuzhiyun // Copyright (C) 2012-2015 Google, Inc
5*4882a593Smuzhiyun //
6*4882a593Smuzhiyun // This driver uses the ChromeOS EC byte-level message-based protocol for
7*4882a593Smuzhiyun // communicating the keyboard state (which keys are pressed) from a keyboard EC
8*4882a593Smuzhiyun // to the AP over some bus (such as i2c, lpc, spi). The EC does debouncing,
9*4882a593Smuzhiyun // but everything else (including deghosting) is done here. The main
10*4882a593Smuzhiyun // motivation for this is to keep the EC firmware as simple as possible, since
11*4882a593Smuzhiyun // it cannot be easily upgraded and EC flash/IRAM space is relatively
12*4882a593Smuzhiyun // expensive.
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <linux/acpi.h>
15*4882a593Smuzhiyun #include <linux/dmi.h>
16*4882a593Smuzhiyun #include <linux/delay.h>
17*4882a593Smuzhiyun #include <linux/io.h>
18*4882a593Smuzhiyun #include <linux/interrupt.h>
19*4882a593Smuzhiyun #include <linux/module.h>
20*4882a593Smuzhiyun #include <linux/platform_data/cros_ec_commands.h>
21*4882a593Smuzhiyun #include <linux/platform_data/cros_ec_proto.h>
22*4882a593Smuzhiyun #include <linux/platform_device.h>
23*4882a593Smuzhiyun #include <linux/printk.h>
24*4882a593Smuzhiyun #include <linux/suspend.h>
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #include "cros_ec.h"
27*4882a593Smuzhiyun #include "cros_ec_lpc_mec.h"
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun #define DRV_NAME "cros_ec_lpcs"
30*4882a593Smuzhiyun #define ACPI_DRV_NAME "GOOG0004"
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /* True if ACPI device is present */
33*4882a593Smuzhiyun static bool cros_ec_lpc_acpi_device_found;
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun /**
36*4882a593Smuzhiyun * struct lpc_driver_ops - LPC driver operations
37*4882a593Smuzhiyun * @read: Copy length bytes from EC address offset into buffer dest. Returns
38*4882a593Smuzhiyun * the 8-bit checksum of all bytes read.
39*4882a593Smuzhiyun * @write: Copy length bytes from buffer msg into EC address offset. Returns
40*4882a593Smuzhiyun * the 8-bit checksum of all bytes written.
41*4882a593Smuzhiyun */
42*4882a593Smuzhiyun struct lpc_driver_ops {
43*4882a593Smuzhiyun u8 (*read)(unsigned int offset, unsigned int length, u8 *dest);
44*4882a593Smuzhiyun u8 (*write)(unsigned int offset, unsigned int length, const u8 *msg);
45*4882a593Smuzhiyun };
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun static struct lpc_driver_ops cros_ec_lpc_ops = { };
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun /*
50*4882a593Smuzhiyun * A generic instance of the read function of struct lpc_driver_ops, used for
51*4882a593Smuzhiyun * the LPC EC.
52*4882a593Smuzhiyun */
cros_ec_lpc_read_bytes(unsigned int offset,unsigned int length,u8 * dest)53*4882a593Smuzhiyun static u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length,
54*4882a593Smuzhiyun u8 *dest)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun int sum = 0;
57*4882a593Smuzhiyun int i;
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun for (i = 0; i < length; ++i) {
60*4882a593Smuzhiyun dest[i] = inb(offset + i);
61*4882a593Smuzhiyun sum += dest[i];
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun /* Return checksum of all bytes read */
65*4882a593Smuzhiyun return sum;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /*
69*4882a593Smuzhiyun * A generic instance of the write function of struct lpc_driver_ops, used for
70*4882a593Smuzhiyun * the LPC EC.
71*4882a593Smuzhiyun */
cros_ec_lpc_write_bytes(unsigned int offset,unsigned int length,const u8 * msg)72*4882a593Smuzhiyun static u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length,
73*4882a593Smuzhiyun const u8 *msg)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun int sum = 0;
76*4882a593Smuzhiyun int i;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun for (i = 0; i < length; ++i) {
79*4882a593Smuzhiyun outb(msg[i], offset + i);
80*4882a593Smuzhiyun sum += msg[i];
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun /* Return checksum of all bytes written */
84*4882a593Smuzhiyun return sum;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun /*
88*4882a593Smuzhiyun * An instance of the read function of struct lpc_driver_ops, used for the
89*4882a593Smuzhiyun * MEC variant of LPC EC.
90*4882a593Smuzhiyun */
cros_ec_lpc_mec_read_bytes(unsigned int offset,unsigned int length,u8 * dest)91*4882a593Smuzhiyun static u8 cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length,
92*4882a593Smuzhiyun u8 *dest)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun int in_range = cros_ec_lpc_mec_in_range(offset, length);
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun if (in_range < 0)
97*4882a593Smuzhiyun return 0;
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun return in_range ?
100*4882a593Smuzhiyun cros_ec_lpc_io_bytes_mec(MEC_IO_READ,
101*4882a593Smuzhiyun offset - EC_HOST_CMD_REGION0,
102*4882a593Smuzhiyun length, dest) :
103*4882a593Smuzhiyun cros_ec_lpc_read_bytes(offset, length, dest);
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun /*
107*4882a593Smuzhiyun * An instance of the write function of struct lpc_driver_ops, used for the
108*4882a593Smuzhiyun * MEC variant of LPC EC.
109*4882a593Smuzhiyun */
cros_ec_lpc_mec_write_bytes(unsigned int offset,unsigned int length,const u8 * msg)110*4882a593Smuzhiyun static u8 cros_ec_lpc_mec_write_bytes(unsigned int offset, unsigned int length,
111*4882a593Smuzhiyun const u8 *msg)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun int in_range = cros_ec_lpc_mec_in_range(offset, length);
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun if (in_range < 0)
116*4882a593Smuzhiyun return 0;
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun return in_range ?
119*4882a593Smuzhiyun cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE,
120*4882a593Smuzhiyun offset - EC_HOST_CMD_REGION0,
121*4882a593Smuzhiyun length, (u8 *)msg) :
122*4882a593Smuzhiyun cros_ec_lpc_write_bytes(offset, length, msg);
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
ec_response_timed_out(void)125*4882a593Smuzhiyun static int ec_response_timed_out(void)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun unsigned long one_second = jiffies + HZ;
128*4882a593Smuzhiyun u8 data;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun usleep_range(200, 300);
131*4882a593Smuzhiyun do {
132*4882a593Smuzhiyun if (!(cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_CMD, 1, &data) &
133*4882a593Smuzhiyun EC_LPC_STATUS_BUSY_MASK))
134*4882a593Smuzhiyun return 0;
135*4882a593Smuzhiyun usleep_range(100, 200);
136*4882a593Smuzhiyun } while (time_before(jiffies, one_second));
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun return 1;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
cros_ec_pkt_xfer_lpc(struct cros_ec_device * ec,struct cros_ec_command * msg)141*4882a593Smuzhiyun static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
142*4882a593Smuzhiyun struct cros_ec_command *msg)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun struct ec_host_response response;
145*4882a593Smuzhiyun u8 sum;
146*4882a593Smuzhiyun int ret = 0;
147*4882a593Smuzhiyun u8 *dout;
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun ret = cros_ec_prepare_tx(ec, msg);
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun /* Write buffer */
152*4882a593Smuzhiyun cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /* Here we go */
155*4882a593Smuzhiyun sum = EC_COMMAND_PROTOCOL_3;
156*4882a593Smuzhiyun cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun if (ec_response_timed_out()) {
159*4882a593Smuzhiyun dev_warn(ec->dev, "EC responsed timed out\n");
160*4882a593Smuzhiyun ret = -EIO;
161*4882a593Smuzhiyun goto done;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun /* Check result */
165*4882a593Smuzhiyun msg->result = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
166*4882a593Smuzhiyun ret = cros_ec_check_result(ec, msg);
167*4882a593Smuzhiyun if (ret)
168*4882a593Smuzhiyun goto done;
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun /* Read back response */
171*4882a593Smuzhiyun dout = (u8 *)&response;
172*4882a593Smuzhiyun sum = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET, sizeof(response),
173*4882a593Smuzhiyun dout);
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun msg->result = response.result;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun if (response.data_len > msg->insize) {
178*4882a593Smuzhiyun dev_err(ec->dev,
179*4882a593Smuzhiyun "packet too long (%d bytes, expected %d)",
180*4882a593Smuzhiyun response.data_len, msg->insize);
181*4882a593Smuzhiyun ret = -EMSGSIZE;
182*4882a593Smuzhiyun goto done;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun /* Read response and process checksum */
186*4882a593Smuzhiyun sum += cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET +
187*4882a593Smuzhiyun sizeof(response), response.data_len,
188*4882a593Smuzhiyun msg->data);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun if (sum) {
191*4882a593Smuzhiyun dev_err(ec->dev,
192*4882a593Smuzhiyun "bad packet checksum %02x\n",
193*4882a593Smuzhiyun response.checksum);
194*4882a593Smuzhiyun ret = -EBADMSG;
195*4882a593Smuzhiyun goto done;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun /* Return actual amount of data received */
199*4882a593Smuzhiyun ret = response.data_len;
200*4882a593Smuzhiyun done:
201*4882a593Smuzhiyun return ret;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
cros_ec_cmd_xfer_lpc(struct cros_ec_device * ec,struct cros_ec_command * msg)204*4882a593Smuzhiyun static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
205*4882a593Smuzhiyun struct cros_ec_command *msg)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun struct ec_lpc_host_args args;
208*4882a593Smuzhiyun u8 sum;
209*4882a593Smuzhiyun int ret = 0;
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE ||
212*4882a593Smuzhiyun msg->insize > EC_PROTO2_MAX_PARAM_SIZE) {
213*4882a593Smuzhiyun dev_err(ec->dev,
214*4882a593Smuzhiyun "invalid buffer sizes (out %d, in %d)\n",
215*4882a593Smuzhiyun msg->outsize, msg->insize);
216*4882a593Smuzhiyun return -EINVAL;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun /* Now actually send the command to the EC and get the result */
220*4882a593Smuzhiyun args.flags = EC_HOST_ARGS_FLAG_FROM_HOST;
221*4882a593Smuzhiyun args.command_version = msg->version;
222*4882a593Smuzhiyun args.data_size = msg->outsize;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun /* Initialize checksum */
225*4882a593Smuzhiyun sum = msg->command + args.flags + args.command_version + args.data_size;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun /* Copy data and update checksum */
228*4882a593Smuzhiyun sum += cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PARAM, msg->outsize,
229*4882a593Smuzhiyun msg->data);
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun /* Finalize checksum and write args */
232*4882a593Smuzhiyun args.checksum = sum;
233*4882a593Smuzhiyun cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
234*4882a593Smuzhiyun (u8 *)&args);
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun /* Here we go */
237*4882a593Smuzhiyun sum = msg->command;
238*4882a593Smuzhiyun cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun if (ec_response_timed_out()) {
241*4882a593Smuzhiyun dev_warn(ec->dev, "EC responsed timed out\n");
242*4882a593Smuzhiyun ret = -EIO;
243*4882a593Smuzhiyun goto done;
244*4882a593Smuzhiyun }
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun /* Check result */
247*4882a593Smuzhiyun msg->result = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
248*4882a593Smuzhiyun ret = cros_ec_check_result(ec, msg);
249*4882a593Smuzhiyun if (ret)
250*4882a593Smuzhiyun goto done;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun /* Read back args */
253*4882a593Smuzhiyun cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8 *)&args);
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun if (args.data_size > msg->insize) {
256*4882a593Smuzhiyun dev_err(ec->dev,
257*4882a593Smuzhiyun "packet too long (%d bytes, expected %d)",
258*4882a593Smuzhiyun args.data_size, msg->insize);
259*4882a593Smuzhiyun ret = -ENOSPC;
260*4882a593Smuzhiyun goto done;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun /* Start calculating response checksum */
264*4882a593Smuzhiyun sum = msg->command + args.flags + args.command_version + args.data_size;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun /* Read response and update checksum */
267*4882a593Smuzhiyun sum += cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PARAM, args.data_size,
268*4882a593Smuzhiyun msg->data);
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun /* Verify checksum */
271*4882a593Smuzhiyun if (args.checksum != sum) {
272*4882a593Smuzhiyun dev_err(ec->dev,
273*4882a593Smuzhiyun "bad packet checksum, expected %02x, got %02x\n",
274*4882a593Smuzhiyun args.checksum, sum);
275*4882a593Smuzhiyun ret = -EBADMSG;
276*4882a593Smuzhiyun goto done;
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun /* Return actual amount of data received */
280*4882a593Smuzhiyun ret = args.data_size;
281*4882a593Smuzhiyun done:
282*4882a593Smuzhiyun return ret;
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun /* Returns num bytes read, or negative on error. Doesn't need locking. */
cros_ec_lpc_readmem(struct cros_ec_device * ec,unsigned int offset,unsigned int bytes,void * dest)286*4882a593Smuzhiyun static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
287*4882a593Smuzhiyun unsigned int bytes, void *dest)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun int i = offset;
290*4882a593Smuzhiyun char *s = dest;
291*4882a593Smuzhiyun int cnt = 0;
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun if (offset >= EC_MEMMAP_SIZE - bytes)
294*4882a593Smuzhiyun return -EINVAL;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun /* fixed length */
297*4882a593Smuzhiyun if (bytes) {
298*4882a593Smuzhiyun cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + offset, bytes, s);
299*4882a593Smuzhiyun return bytes;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun /* string */
303*4882a593Smuzhiyun for (; i < EC_MEMMAP_SIZE; i++, s++) {
304*4882a593Smuzhiyun cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + i, 1, s);
305*4882a593Smuzhiyun cnt++;
306*4882a593Smuzhiyun if (!*s)
307*4882a593Smuzhiyun break;
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun return cnt;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
cros_ec_lpc_acpi_notify(acpi_handle device,u32 value,void * data)313*4882a593Smuzhiyun static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun struct cros_ec_device *ec_dev = data;
316*4882a593Smuzhiyun bool ec_has_more_events;
317*4882a593Smuzhiyun int ret;
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun ec_dev->last_event_time = cros_ec_get_time_ns();
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun if (ec_dev->mkbp_event_supported)
322*4882a593Smuzhiyun do {
323*4882a593Smuzhiyun ret = cros_ec_get_next_event(ec_dev, NULL,
324*4882a593Smuzhiyun &ec_has_more_events);
325*4882a593Smuzhiyun if (ret > 0)
326*4882a593Smuzhiyun blocking_notifier_call_chain(
327*4882a593Smuzhiyun &ec_dev->event_notifier, 0,
328*4882a593Smuzhiyun ec_dev);
329*4882a593Smuzhiyun } while (ec_has_more_events);
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun if (value == ACPI_NOTIFY_DEVICE_WAKE)
332*4882a593Smuzhiyun pm_system_wakeup();
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun
cros_ec_lpc_probe(struct platform_device * pdev)335*4882a593Smuzhiyun static int cros_ec_lpc_probe(struct platform_device *pdev)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun struct device *dev = &pdev->dev;
338*4882a593Smuzhiyun struct acpi_device *adev;
339*4882a593Smuzhiyun acpi_status status;
340*4882a593Smuzhiyun struct cros_ec_device *ec_dev;
341*4882a593Smuzhiyun u8 buf[2];
342*4882a593Smuzhiyun int irq, ret;
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun if (!devm_request_region(dev, EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE,
345*4882a593Smuzhiyun dev_name(dev))) {
346*4882a593Smuzhiyun dev_err(dev, "couldn't reserve memmap region\n");
347*4882a593Smuzhiyun return -EBUSY;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun /*
351*4882a593Smuzhiyun * Read the mapped ID twice, the first one is assuming the
352*4882a593Smuzhiyun * EC is a Microchip Embedded Controller (MEC) variant, if the
353*4882a593Smuzhiyun * protocol fails, fallback to the non MEC variant and try to
354*4882a593Smuzhiyun * read again the ID.
355*4882a593Smuzhiyun */
356*4882a593Smuzhiyun cros_ec_lpc_ops.read = cros_ec_lpc_mec_read_bytes;
357*4882a593Smuzhiyun cros_ec_lpc_ops.write = cros_ec_lpc_mec_write_bytes;
358*4882a593Smuzhiyun cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf);
359*4882a593Smuzhiyun if (buf[0] != 'E' || buf[1] != 'C') {
360*4882a593Smuzhiyun /* Re-assign read/write operations for the non MEC variant */
361*4882a593Smuzhiyun cros_ec_lpc_ops.read = cros_ec_lpc_read_bytes;
362*4882a593Smuzhiyun cros_ec_lpc_ops.write = cros_ec_lpc_write_bytes;
363*4882a593Smuzhiyun cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2,
364*4882a593Smuzhiyun buf);
365*4882a593Smuzhiyun if (buf[0] != 'E' || buf[1] != 'C') {
366*4882a593Smuzhiyun dev_err(dev, "EC ID not detected\n");
367*4882a593Smuzhiyun return -ENODEV;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun if (!devm_request_region(dev, EC_HOST_CMD_REGION0,
372*4882a593Smuzhiyun EC_HOST_CMD_REGION_SIZE, dev_name(dev))) {
373*4882a593Smuzhiyun dev_err(dev, "couldn't reserve region0\n");
374*4882a593Smuzhiyun return -EBUSY;
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun if (!devm_request_region(dev, EC_HOST_CMD_REGION1,
377*4882a593Smuzhiyun EC_HOST_CMD_REGION_SIZE, dev_name(dev))) {
378*4882a593Smuzhiyun dev_err(dev, "couldn't reserve region1\n");
379*4882a593Smuzhiyun return -EBUSY;
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
383*4882a593Smuzhiyun if (!ec_dev)
384*4882a593Smuzhiyun return -ENOMEM;
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun platform_set_drvdata(pdev, ec_dev);
387*4882a593Smuzhiyun ec_dev->dev = dev;
388*4882a593Smuzhiyun ec_dev->phys_name = dev_name(dev);
389*4882a593Smuzhiyun ec_dev->cmd_xfer = cros_ec_cmd_xfer_lpc;
390*4882a593Smuzhiyun ec_dev->pkt_xfer = cros_ec_pkt_xfer_lpc;
391*4882a593Smuzhiyun ec_dev->cmd_readmem = cros_ec_lpc_readmem;
392*4882a593Smuzhiyun ec_dev->din_size = sizeof(struct ec_host_response) +
393*4882a593Smuzhiyun sizeof(struct ec_response_get_protocol_info);
394*4882a593Smuzhiyun ec_dev->dout_size = sizeof(struct ec_host_request);
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun /*
397*4882a593Smuzhiyun * Some boards do not have an IRQ allotted for cros_ec_lpc,
398*4882a593Smuzhiyun * which makes ENXIO an expected (and safe) scenario.
399*4882a593Smuzhiyun */
400*4882a593Smuzhiyun irq = platform_get_irq_optional(pdev, 0);
401*4882a593Smuzhiyun if (irq > 0)
402*4882a593Smuzhiyun ec_dev->irq = irq;
403*4882a593Smuzhiyun else if (irq != -ENXIO) {
404*4882a593Smuzhiyun dev_err(dev, "couldn't retrieve IRQ number (%d)\n", irq);
405*4882a593Smuzhiyun return irq;
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun
408*4882a593Smuzhiyun ret = cros_ec_register(ec_dev);
409*4882a593Smuzhiyun if (ret) {
410*4882a593Smuzhiyun dev_err(dev, "couldn't register ec_dev (%d)\n", ret);
411*4882a593Smuzhiyun return ret;
412*4882a593Smuzhiyun }
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun /*
415*4882a593Smuzhiyun * Connect a notify handler to process MKBP messages if we have a
416*4882a593Smuzhiyun * companion ACPI device.
417*4882a593Smuzhiyun */
418*4882a593Smuzhiyun adev = ACPI_COMPANION(dev);
419*4882a593Smuzhiyun if (adev) {
420*4882a593Smuzhiyun status = acpi_install_notify_handler(adev->handle,
421*4882a593Smuzhiyun ACPI_ALL_NOTIFY,
422*4882a593Smuzhiyun cros_ec_lpc_acpi_notify,
423*4882a593Smuzhiyun ec_dev);
424*4882a593Smuzhiyun if (ACPI_FAILURE(status))
425*4882a593Smuzhiyun dev_warn(dev, "Failed to register notifier %08x\n",
426*4882a593Smuzhiyun status);
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun
429*4882a593Smuzhiyun return 0;
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun
cros_ec_lpc_remove(struct platform_device * pdev)432*4882a593Smuzhiyun static int cros_ec_lpc_remove(struct platform_device *pdev)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun struct cros_ec_device *ec_dev = platform_get_drvdata(pdev);
435*4882a593Smuzhiyun struct acpi_device *adev;
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun adev = ACPI_COMPANION(&pdev->dev);
438*4882a593Smuzhiyun if (adev)
439*4882a593Smuzhiyun acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,
440*4882a593Smuzhiyun cros_ec_lpc_acpi_notify);
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun return cros_ec_unregister(ec_dev);
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = {
446*4882a593Smuzhiyun { ACPI_DRV_NAME, 0 },
447*4882a593Smuzhiyun { }
448*4882a593Smuzhiyun };
449*4882a593Smuzhiyun MODULE_DEVICE_TABLE(acpi, cros_ec_lpc_acpi_device_ids);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = {
452*4882a593Smuzhiyun {
453*4882a593Smuzhiyun /*
454*4882a593Smuzhiyun * Today all Chromebooks/boxes ship with Google_* as version and
455*4882a593Smuzhiyun * coreboot as bios vendor. No other systems with this
456*4882a593Smuzhiyun * combination are known to date.
457*4882a593Smuzhiyun */
458*4882a593Smuzhiyun .matches = {
459*4882a593Smuzhiyun DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
460*4882a593Smuzhiyun DMI_MATCH(DMI_BIOS_VERSION, "Google_"),
461*4882a593Smuzhiyun },
462*4882a593Smuzhiyun },
463*4882a593Smuzhiyun {
464*4882a593Smuzhiyun /*
465*4882a593Smuzhiyun * If the box is running custom coreboot firmware then the
466*4882a593Smuzhiyun * DMI BIOS version string will not be matched by "Google_",
467*4882a593Smuzhiyun * but the system vendor string will still be matched by
468*4882a593Smuzhiyun * "GOOGLE".
469*4882a593Smuzhiyun */
470*4882a593Smuzhiyun .matches = {
471*4882a593Smuzhiyun DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
472*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
473*4882a593Smuzhiyun },
474*4882a593Smuzhiyun },
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun /* x86-link, the Chromebook Pixel. */
477*4882a593Smuzhiyun .matches = {
478*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
479*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
480*4882a593Smuzhiyun },
481*4882a593Smuzhiyun },
482*4882a593Smuzhiyun {
483*4882a593Smuzhiyun /* x86-samus, the Chromebook Pixel 2. */
484*4882a593Smuzhiyun .matches = {
485*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
486*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
487*4882a593Smuzhiyun },
488*4882a593Smuzhiyun },
489*4882a593Smuzhiyun {
490*4882a593Smuzhiyun /* x86-peppy, the Acer C720 Chromebook. */
491*4882a593Smuzhiyun .matches = {
492*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
493*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
494*4882a593Smuzhiyun },
495*4882a593Smuzhiyun },
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun /* x86-glimmer, the Lenovo Thinkpad Yoga 11e. */
498*4882a593Smuzhiyun .matches = {
499*4882a593Smuzhiyun DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
500*4882a593Smuzhiyun DMI_MATCH(DMI_PRODUCT_NAME, "Glimmer"),
501*4882a593Smuzhiyun },
502*4882a593Smuzhiyun },
503*4882a593Smuzhiyun { /* sentinel */ }
504*4882a593Smuzhiyun };
505*4882a593Smuzhiyun MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table);
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
cros_ec_lpc_suspend(struct device * dev)508*4882a593Smuzhiyun static int cros_ec_lpc_suspend(struct device *dev)
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
511*4882a593Smuzhiyun
512*4882a593Smuzhiyun return cros_ec_suspend(ec_dev);
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun
cros_ec_lpc_resume(struct device * dev)515*4882a593Smuzhiyun static int cros_ec_lpc_resume(struct device *dev)
516*4882a593Smuzhiyun {
517*4882a593Smuzhiyun struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun return cros_ec_resume(ec_dev);
520*4882a593Smuzhiyun }
521*4882a593Smuzhiyun #endif
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun static const struct dev_pm_ops cros_ec_lpc_pm_ops = {
524*4882a593Smuzhiyun SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_lpc_suspend, cros_ec_lpc_resume)
525*4882a593Smuzhiyun };
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun static struct platform_driver cros_ec_lpc_driver = {
528*4882a593Smuzhiyun .driver = {
529*4882a593Smuzhiyun .name = DRV_NAME,
530*4882a593Smuzhiyun .acpi_match_table = cros_ec_lpc_acpi_device_ids,
531*4882a593Smuzhiyun .pm = &cros_ec_lpc_pm_ops,
532*4882a593Smuzhiyun },
533*4882a593Smuzhiyun .probe = cros_ec_lpc_probe,
534*4882a593Smuzhiyun .remove = cros_ec_lpc_remove,
535*4882a593Smuzhiyun };
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun static struct platform_device cros_ec_lpc_device = {
538*4882a593Smuzhiyun .name = DRV_NAME
539*4882a593Smuzhiyun };
540*4882a593Smuzhiyun
cros_ec_lpc_parse_device(acpi_handle handle,u32 level,void * context,void ** retval)541*4882a593Smuzhiyun static acpi_status cros_ec_lpc_parse_device(acpi_handle handle, u32 level,
542*4882a593Smuzhiyun void *context, void **retval)
543*4882a593Smuzhiyun {
544*4882a593Smuzhiyun *(bool *)context = true;
545*4882a593Smuzhiyun return AE_CTRL_TERMINATE;
546*4882a593Smuzhiyun }
547*4882a593Smuzhiyun
cros_ec_lpc_init(void)548*4882a593Smuzhiyun static int __init cros_ec_lpc_init(void)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun int ret;
551*4882a593Smuzhiyun acpi_status status;
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun status = acpi_get_devices(ACPI_DRV_NAME, cros_ec_lpc_parse_device,
554*4882a593Smuzhiyun &cros_ec_lpc_acpi_device_found, NULL);
555*4882a593Smuzhiyun if (ACPI_FAILURE(status))
556*4882a593Smuzhiyun pr_warn(DRV_NAME ": Looking for %s failed\n", ACPI_DRV_NAME);
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun if (!cros_ec_lpc_acpi_device_found &&
559*4882a593Smuzhiyun !dmi_check_system(cros_ec_lpc_dmi_table)) {
560*4882a593Smuzhiyun pr_err(DRV_NAME ": unsupported system.\n");
561*4882a593Smuzhiyun return -ENODEV;
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun cros_ec_lpc_mec_init(EC_HOST_CMD_REGION0,
565*4882a593Smuzhiyun EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE);
566*4882a593Smuzhiyun
567*4882a593Smuzhiyun /* Register the driver */
568*4882a593Smuzhiyun ret = platform_driver_register(&cros_ec_lpc_driver);
569*4882a593Smuzhiyun if (ret) {
570*4882a593Smuzhiyun pr_err(DRV_NAME ": can't register driver: %d\n", ret);
571*4882a593Smuzhiyun cros_ec_lpc_mec_destroy();
572*4882a593Smuzhiyun return ret;
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun
575*4882a593Smuzhiyun if (!cros_ec_lpc_acpi_device_found) {
576*4882a593Smuzhiyun /* Register the device, and it'll get hooked up automatically */
577*4882a593Smuzhiyun ret = platform_device_register(&cros_ec_lpc_device);
578*4882a593Smuzhiyun if (ret) {
579*4882a593Smuzhiyun pr_err(DRV_NAME ": can't register device: %d\n", ret);
580*4882a593Smuzhiyun platform_driver_unregister(&cros_ec_lpc_driver);
581*4882a593Smuzhiyun cros_ec_lpc_mec_destroy();
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun }
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun return ret;
586*4882a593Smuzhiyun }
587*4882a593Smuzhiyun
cros_ec_lpc_exit(void)588*4882a593Smuzhiyun static void __exit cros_ec_lpc_exit(void)
589*4882a593Smuzhiyun {
590*4882a593Smuzhiyun if (!cros_ec_lpc_acpi_device_found)
591*4882a593Smuzhiyun platform_device_unregister(&cros_ec_lpc_device);
592*4882a593Smuzhiyun platform_driver_unregister(&cros_ec_lpc_driver);
593*4882a593Smuzhiyun cros_ec_lpc_mec_destroy();
594*4882a593Smuzhiyun }
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun module_init(cros_ec_lpc_init);
597*4882a593Smuzhiyun module_exit(cros_ec_lpc_exit);
598*4882a593Smuzhiyun
599*4882a593Smuzhiyun MODULE_LICENSE("GPL");
600*4882a593Smuzhiyun MODULE_DESCRIPTION("ChromeOS EC LPC driver");
601