aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/platform/chrome/Kconfig29
-rw-r--r--drivers/platform/chrome/Makefile3
-rw-r--r--drivers/platform/chrome/cros_ec_lpc.c158
-rw-r--r--drivers/platform/chrome/wilco_ec/Kconfig2
4 files changed, 95 insertions, 97 deletions
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 0b3c2b9ffd2f..8010e7e395ce 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -95,28 +95,17 @@ config CROS_EC_SPI
95 'pre-amble' bytes before the response actually starts. 95 'pre-amble' bytes before the response actually starts.
96 96
97config CROS_EC_LPC 97config CROS_EC_LPC
98 tristate "ChromeOS Embedded Controller (LPC)" 98 tristate "ChromeOS Embedded Controller (LPC)"
99 depends on MFD_CROS_EC && ACPI && (X86 || COMPILE_TEST) 99 depends on MFD_CROS_EC && ACPI && (X86 || COMPILE_TEST)
100 help
101 If you say Y here, you get support for talking to the ChromeOS EC
102 over an LPC bus. This uses a simple byte-level protocol with a
103 checksum. This is used for userspace access only. The kernel
104 typically has its own communication methods.
105
106 To compile this driver as a module, choose M here: the
107 module will be called cros_ec_lpc.
108
109config CROS_EC_LPC_MEC
110 bool "ChromeOS Embedded Controller LPC Microchip EC (MEC) variant"
111 depends on CROS_EC_LPC
112 default n
113 help 100 help
114 If you say Y here, a variant LPC protocol for the Microchip EC 101 If you say Y here, you get support for talking to the ChromeOS EC
115 will be used. Note that this variant is not backward compatible 102 over an LPC bus, including the LPC Microchip EC (MEC) variant.
116 with non-Microchip ECs. 103 This uses a simple byte-level protocol with a checksum. This is
104 used for userspace access only. The kernel typically has its own
105 communication methods.
117 106
118 If you have a ChromeOS Embedded Controller Microchip EC variant 107 To compile this driver as a module, choose M here: the
119 choose Y here. 108 module will be called cros_ec_lpcs.
120 109
121config CROS_EC_PROTO 110config CROS_EC_PROTO
122 bool 111 bool
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 5a2bcef4b07c..fd0af05cc14c 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -10,8 +10,7 @@ obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o
10obj-$(CONFIG_CROS_EC_ISHTP) += cros_ec_ishtp.o 10obj-$(CONFIG_CROS_EC_ISHTP) += cros_ec_ishtp.o
11obj-$(CONFIG_CROS_EC_RPMSG) += cros_ec_rpmsg.o 11obj-$(CONFIG_CROS_EC_RPMSG) += cros_ec_rpmsg.o
12obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o 12obj-$(CONFIG_CROS_EC_SPI) += cros_ec_spi.o
13cros_ec_lpcs-objs := cros_ec_lpc.o 13cros_ec_lpcs-objs := cros_ec_lpc.o cros_ec_lpc_mec.o
14cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
15obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpcs.o 14obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpcs.o
16obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o cros_ec_trace.o 15obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o cros_ec_trace.o
17obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT) += cros_kbd_led_backlight.o 16obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT) += cros_kbd_led_backlight.o
diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
index 8d06addec5e2..2c44c7f3322a 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -31,7 +31,26 @@
31/* True if ACPI device is present */ 31/* True if ACPI device is present */
32static bool cros_ec_lpc_acpi_device_found; 32static bool cros_ec_lpc_acpi_device_found;
33 33
34static u8 lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest) 34/**
35 * struct lpc_driver_ops - LPC driver operations
36 * @read: Copy length bytes from EC address offset into buffer dest. Returns
37 * the 8-bit checksum of all bytes read.
38 * @write: Copy length bytes from buffer msg into EC address offset. Returns
39 * the 8-bit checksum of all bytes written.
40 */
41struct lpc_driver_ops {
42 u8 (*read)(unsigned int offset, unsigned int length, u8 *dest);
43 u8 (*write)(unsigned int offset, unsigned int length, const u8 *msg);
44};
45
46static struct lpc_driver_ops cros_ec_lpc_ops = { };
47
48/*
49 * A generic instance of the read function of struct lpc_driver_ops, used for
50 * the LPC EC.
51 */
52static u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length,
53 u8 *dest)
35{ 54{
36 int sum = 0; 55 int sum = 0;
37 int i; 56 int i;
@@ -45,7 +64,12 @@ static u8 lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest)
45 return sum; 64 return sum;
46} 65}
47 66
48static u8 lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg) 67/*
68 * A generic instance of the write function of struct lpc_driver_ops, used for
69 * the LPC EC.
70 */
71static u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length,
72 const u8 *msg)
49{ 73{
50 int sum = 0; 74 int sum = 0;
51 int i; 75 int i;
@@ -59,10 +83,12 @@ static u8 lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg)
59 return sum; 83 return sum;
60} 84}
61 85
62#ifdef CONFIG_CROS_EC_LPC_MEC 86/*
63 87 * An instance of the read function of struct lpc_driver_ops, used for the
64static u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, 88 * MEC variant of LPC EC.
65 u8 *dest) 89 */
90static u8 cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length,
91 u8 *dest)
66{ 92{
67 int in_range = cros_ec_lpc_mec_in_range(offset, length); 93 int in_range = cros_ec_lpc_mec_in_range(offset, length);
68 94
@@ -73,11 +99,15 @@ static u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length,
73 cros_ec_lpc_io_bytes_mec(MEC_IO_READ, 99 cros_ec_lpc_io_bytes_mec(MEC_IO_READ,
74 offset - EC_HOST_CMD_REGION0, 100 offset - EC_HOST_CMD_REGION0,
75 length, dest) : 101 length, dest) :
76 lpc_read_bytes(offset, length, dest); 102 cros_ec_lpc_read_bytes(offset, length, dest);
77} 103}
78 104
79static u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, 105/*
80 u8 *msg) 106 * An instance of the write function of struct lpc_driver_ops, used for the
107 * MEC variant of LPC EC.
108 */
109static u8 cros_ec_lpc_mec_write_bytes(unsigned int offset, unsigned int length,
110 const u8 *msg)
81{ 111{
82 int in_range = cros_ec_lpc_mec_in_range(offset, length); 112 int in_range = cros_ec_lpc_mec_in_range(offset, length);
83 113
@@ -87,45 +117,10 @@ static u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length,
87 return in_range ? 117 return in_range ?
88 cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, 118 cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE,
89 offset - EC_HOST_CMD_REGION0, 119 offset - EC_HOST_CMD_REGION0,
90 length, msg) : 120 length, (u8 *)msg) :
91 lpc_write_bytes(offset, length, msg); 121 cros_ec_lpc_write_bytes(offset, length, msg);
92}
93
94static void cros_ec_lpc_reg_init(void)
95{
96 cros_ec_lpc_mec_init(EC_HOST_CMD_REGION0,
97 EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE);
98} 122}
99 123
100static void cros_ec_lpc_reg_destroy(void)
101{
102 cros_ec_lpc_mec_destroy();
103}
104
105#else /* CONFIG_CROS_EC_LPC_MEC */
106
107static u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length,
108 u8 *dest)
109{
110 return lpc_read_bytes(offset, length, dest);
111}
112
113static u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length,
114 u8 *msg)
115{
116 return lpc_write_bytes(offset, length, msg);
117}
118
119static void cros_ec_lpc_reg_init(void)
120{
121}
122
123static void cros_ec_lpc_reg_destroy(void)
124{
125}
126
127#endif /* CONFIG_CROS_EC_LPC_MEC */
128
129static int ec_response_timed_out(void) 124static int ec_response_timed_out(void)
130{ 125{
131 unsigned long one_second = jiffies + HZ; 126 unsigned long one_second = jiffies + HZ;
@@ -133,7 +128,7 @@ static int ec_response_timed_out(void)
133 128
134 usleep_range(200, 300); 129 usleep_range(200, 300);
135 do { 130 do {
136 if (!(cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_CMD, 1, &data) & 131 if (!(cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_CMD, 1, &data) &
137 EC_LPC_STATUS_BUSY_MASK)) 132 EC_LPC_STATUS_BUSY_MASK))
138 return 0; 133 return 0;
139 usleep_range(100, 200); 134 usleep_range(100, 200);
@@ -153,11 +148,11 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
153 ret = cros_ec_prepare_tx(ec, msg); 148 ret = cros_ec_prepare_tx(ec, msg);
154 149
155 /* Write buffer */ 150 /* Write buffer */
156 cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout); 151 cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
157 152
158 /* Here we go */ 153 /* Here we go */
159 sum = EC_COMMAND_PROTOCOL_3; 154 sum = EC_COMMAND_PROTOCOL_3;
160 cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, &sum); 155 cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
161 156
162 if (ec_response_timed_out()) { 157 if (ec_response_timed_out()) {
163 dev_warn(ec->dev, "EC responsed timed out\n"); 158 dev_warn(ec->dev, "EC responsed timed out\n");
@@ -166,15 +161,15 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
166 } 161 }
167 162
168 /* Check result */ 163 /* Check result */
169 msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, &sum); 164 msg->result = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
170 ret = cros_ec_check_result(ec, msg); 165 ret = cros_ec_check_result(ec, msg);
171 if (ret) 166 if (ret)
172 goto done; 167 goto done;
173 168
174 /* Read back response */ 169 /* Read back response */
175 dout = (u8 *)&response; 170 dout = (u8 *)&response;
176 sum = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(response), 171 sum = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET, sizeof(response),
177 dout); 172 dout);
178 173
179 msg->result = response.result; 174 msg->result = response.result;
180 175
@@ -187,9 +182,9 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
187 } 182 }
188 183
189 /* Read response and process checksum */ 184 /* Read response and process checksum */
190 sum += cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET + 185 sum += cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET +
191 sizeof(response), response.data_len, 186 sizeof(response), response.data_len,
192 msg->data); 187 msg->data);
193 188
194 if (sum) { 189 if (sum) {
195 dev_err(ec->dev, 190 dev_err(ec->dev,
@@ -229,17 +224,17 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
229 sum = msg->command + args.flags + args.command_version + args.data_size; 224 sum = msg->command + args.flags + args.command_version + args.data_size;
230 225
231 /* Copy data and update checksum */ 226 /* Copy data and update checksum */
232 sum += cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PARAM, msg->outsize, 227 sum += cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PARAM, msg->outsize,
233 msg->data); 228 msg->data);
234 229
235 /* Finalize checksum and write args */ 230 /* Finalize checksum and write args */
236 args.checksum = sum; 231 args.checksum = sum;
237 cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), 232 cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
238 (u8 *)&args); 233 (u8 *)&args);
239 234
240 /* Here we go */ 235 /* Here we go */
241 sum = msg->command; 236 sum = msg->command;
242 cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, &sum); 237 cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
243 238
244 if (ec_response_timed_out()) { 239 if (ec_response_timed_out()) {
245 dev_warn(ec->dev, "EC responsed timed out\n"); 240 dev_warn(ec->dev, "EC responsed timed out\n");
@@ -248,14 +243,13 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
248 } 243 }
249 244
250 /* Check result */ 245 /* Check result */
251 msg->result = cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, &sum); 246 msg->result = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
252 ret = cros_ec_check_result(ec, msg); 247 ret = cros_ec_check_result(ec, msg);
253 if (ret) 248 if (ret)
254 goto done; 249 goto done;
255 250
256 /* Read back args */ 251 /* Read back args */
257 cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), 252 cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8 *)&args);
258 (u8 *)&args);
259 253
260 if (args.data_size > msg->insize) { 254 if (args.data_size > msg->insize) {
261 dev_err(ec->dev, 255 dev_err(ec->dev,
@@ -269,8 +263,8 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
269 sum = msg->command + args.flags + args.command_version + args.data_size; 263 sum = msg->command + args.flags + args.command_version + args.data_size;
270 264
271 /* Read response and update checksum */ 265 /* Read response and update checksum */
272 sum += cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PARAM, args.data_size, 266 sum += cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PARAM, args.data_size,
273 msg->data); 267 msg->data);
274 268
275 /* Verify checksum */ 269 /* Verify checksum */
276 if (args.checksum != sum) { 270 if (args.checksum != sum) {
@@ -300,13 +294,13 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
300 294
301 /* fixed length */ 295 /* fixed length */
302 if (bytes) { 296 if (bytes) {
303 cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + offset, bytes, s); 297 cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + offset, bytes, s);
304 return bytes; 298 return bytes;
305 } 299 }
306 300
307 /* string */ 301 /* string */
308 for (; i < EC_MEMMAP_SIZE; i++, s++) { 302 for (; i < EC_MEMMAP_SIZE; i++, s++) {
309 cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + i, 1, s); 303 cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + i, 1, s);
310 cnt++; 304 cnt++;
311 if (!*s) 305 if (!*s)
312 break; 306 break;
@@ -343,10 +337,25 @@ static int cros_ec_lpc_probe(struct platform_device *pdev)
343 return -EBUSY; 337 return -EBUSY;
344 } 338 }
345 339
346 cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf); 340 /*
341 * Read the mapped ID twice, the first one is assuming the
342 * EC is a Microchip Embedded Controller (MEC) variant, if the
343 * protocol fails, fallback to the non MEC variant and try to
344 * read again the ID.
345 */
346 cros_ec_lpc_ops.read = cros_ec_lpc_mec_read_bytes;
347 cros_ec_lpc_ops.write = cros_ec_lpc_mec_write_bytes;
348 cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf);
347 if (buf[0] != 'E' || buf[1] != 'C') { 349 if (buf[0] != 'E' || buf[1] != 'C') {
348 dev_err(dev, "EC ID not detected\n"); 350 /* Re-assign read/write operations for the non MEC variant */
349 return -ENODEV; 351 cros_ec_lpc_ops.read = cros_ec_lpc_read_bytes;
352 cros_ec_lpc_ops.write = cros_ec_lpc_write_bytes;
353 cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2,
354 buf);
355 if (buf[0] != 'E' || buf[1] != 'C') {
356 dev_err(dev, "EC ID not detected\n");
357 return -ENODEV;
358 }
350 } 359 }
351 360
352 if (!devm_request_region(dev, EC_HOST_CMD_REGION0, 361 if (!devm_request_region(dev, EC_HOST_CMD_REGION0,
@@ -541,13 +550,14 @@ static int __init cros_ec_lpc_init(void)
541 return -ENODEV; 550 return -ENODEV;
542 } 551 }
543 552
544 cros_ec_lpc_reg_init(); 553 cros_ec_lpc_mec_init(EC_HOST_CMD_REGION0,
554 EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE);
545 555
546 /* Register the driver */ 556 /* Register the driver */
547 ret = platform_driver_register(&cros_ec_lpc_driver); 557 ret = platform_driver_register(&cros_ec_lpc_driver);
548 if (ret) { 558 if (ret) {
549 pr_err(DRV_NAME ": can't register driver: %d\n", ret); 559 pr_err(DRV_NAME ": can't register driver: %d\n", ret);
550 cros_ec_lpc_reg_destroy(); 560 cros_ec_lpc_mec_destroy();
551 return ret; 561 return ret;
552 } 562 }
553 563
@@ -557,7 +567,7 @@ static int __init cros_ec_lpc_init(void)
557 if (ret) { 567 if (ret) {
558 pr_err(DRV_NAME ": can't register device: %d\n", ret); 568 pr_err(DRV_NAME ": can't register device: %d\n", ret);
559 platform_driver_unregister(&cros_ec_lpc_driver); 569 platform_driver_unregister(&cros_ec_lpc_driver);
560 cros_ec_lpc_reg_destroy(); 570 cros_ec_lpc_mec_destroy();
561 } 571 }
562 } 572 }
563 573
@@ -569,7 +579,7 @@ static void __exit cros_ec_lpc_exit(void)
569 if (!cros_ec_lpc_acpi_device_found) 579 if (!cros_ec_lpc_acpi_device_found)
570 platform_device_unregister(&cros_ec_lpc_device); 580 platform_device_unregister(&cros_ec_lpc_device);
571 platform_driver_unregister(&cros_ec_lpc_driver); 581 platform_driver_unregister(&cros_ec_lpc_driver);
572 cros_ec_lpc_reg_destroy(); 582 cros_ec_lpc_mec_destroy();
573} 583}
574 584
575module_init(cros_ec_lpc_init); 585module_init(cros_ec_lpc_init);
diff --git a/drivers/platform/chrome/wilco_ec/Kconfig b/drivers/platform/chrome/wilco_ec/Kconfig
index 90336874af59..5b7e1801980c 100644
--- a/drivers/platform/chrome/wilco_ec/Kconfig
+++ b/drivers/platform/chrome/wilco_ec/Kconfig
@@ -1,6 +1,6 @@
1config WILCO_EC 1config WILCO_EC
2 tristate "ChromeOS Wilco Embedded Controller" 2 tristate "ChromeOS Wilco Embedded Controller"
3 depends on ACPI && X86 && CROS_EC_LPC && CROS_EC_LPC_MEC 3 depends on ACPI && X86 && CROS_EC_LPC
4 help 4 help
5 If you say Y here, you get support for talking to the ChromeOS 5 If you say Y here, you get support for talking to the ChromeOS
6 Wilco EC over an eSPI bus. This uses a simple byte-level protocol 6 Wilco EC over an eSPI bus. This uses a simple byte-level protocol