diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-12 12:46:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-12 12:46:32 -0400 |
commit | f47d633134f7033e3d0c667419d9f8afd69e308d (patch) | |
tree | a5242d86288599fda63ed79b2d131f5a298bb66f | |
parent | 004cc08675b761fd82288bab1b5ba5e1ca746eca (diff) | |
parent | 2794449576a6024e203eca5cc2c1a3ae33102b8e (diff) |
Merge tag 'tag-chrome-platform-for-v5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux
Pull chrome platform updates from Benson Leung:
- SPDX identifier cleanup for platform/chrome
- Cleanup series between mfd and chrome/platform, moving cros-ec
attributes from mfd/cros_ec_dev to sub-drivers in platform/chrome
- Wilco EC driver
- Maintainership change to new group repository
* tag 'tag-chrome-platform-for-v5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux:
platform/chrome: fix wilco-ec dependencies
platform/chrome: wilco_ec: Add RTC driver
platform/chrome: wilco_ec: Add support for raw commands in debugfs
platform/chrome: Add new driver for Wilco EC
platform/chrome: cros_ec: Remove cros_ec dependency in lpc_mec
MAINTAINERS: chrome-platform: change the git tree to a chrome-platform group git tree
platform/chrome: cros_ec_sysfs: remove pr_fmt() define
platform/chrome: cros_ec_lightbar: remove pr_fmt() define
platform/chrome: cros_kbd_led_backlight: switch to SPDX identifier
platform/chrome: cros_ec_spi: switch to SPDX identifier
platform/chrome: cros_ec_proto: switch to SPDX identifier
platform/chrome: cros_ec_lpc: switch to SPDX identifier
platform/chrome: cros_ec_i2c: switch to SPDX identifier
platform/chrome: cros_ec_vbc: switch to SPDX identifier
platform/chrome: cros_ec_sysfs: switch to SPDX identifier
platform/chrome: cros_ec_lightbar: switch to SPDX identifier
platform/chrome: cros_ec_debugfs: switch to SPDX identifier
platform/chrome: cromeos_pstore: switch to SPDX identifier
27 files changed, 1148 insertions, 312 deletions
diff --git a/Documentation/ABI/testing/debugfs-wilco-ec b/Documentation/ABI/testing/debugfs-wilco-ec new file mode 100644 index 000000000000..f814f112e213 --- /dev/null +++ b/Documentation/ABI/testing/debugfs-wilco-ec | |||
@@ -0,0 +1,23 @@ | |||
1 | What: /sys/kernel/debug/wilco_ec/raw | ||
2 | Date: January 2019 | ||
3 | KernelVersion: 5.1 | ||
4 | Description: | ||
5 | Write and read raw mailbox commands to the EC. | ||
6 | |||
7 | For writing: | ||
8 | Bytes 0-1 indicate the message type: | ||
9 | 00 F0 = Execute Legacy Command | ||
10 | 00 F2 = Read/Write NVRAM Property | ||
11 | Byte 2 provides the command code | ||
12 | Bytes 3+ consist of the data passed in the request | ||
13 | |||
14 | At least three bytes are required, for the msg type and command, | ||
15 | with additional bytes optional for additional data. | ||
16 | |||
17 | Example: | ||
18 | // Request EC info type 3 (EC firmware build date) | ||
19 | $ echo 00 f0 38 00 03 00 > raw | ||
20 | // View the result. The decoded ASCII result "12/21/18" is | ||
21 | // included after the raw hex. | ||
22 | $ cat raw | ||
23 | 00 31 32 2f 32 31 2f 31 38 00 38 00 01 00 2f 00 .12/21/18.8... | ||
diff --git a/MAINTAINERS b/MAINTAINERS index e2ec45968a16..4f004dc0a0f2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3755,7 +3755,7 @@ CHROME HARDWARE PLATFORM SUPPORT | |||
3755 | M: Benson Leung <bleung@chromium.org> | 3755 | M: Benson Leung <bleung@chromium.org> |
3756 | M: Enric Balletbo i Serra <enric.balletbo@collabora.com> | 3756 | M: Enric Balletbo i Serra <enric.balletbo@collabora.com> |
3757 | S: Maintained | 3757 | S: Maintained |
3758 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/bleung/chrome-platform.git | 3758 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux.git |
3759 | F: drivers/platform/chrome/ | 3759 | F: drivers/platform/chrome/ |
3760 | 3760 | ||
3761 | CHROMEOS EC SUBDRIVERS | 3761 | CHROMEOS EC SUBDRIVERS |
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig index 5e2fde5ff63d..9186d81a51cc 100644 --- a/drivers/platform/chrome/Kconfig +++ b/drivers/platform/chrome/Kconfig | |||
@@ -152,4 +152,6 @@ config CROS_EC_SYSFS | |||
152 | To compile this driver as a module, choose M here: the | 152 | To compile this driver as a module, choose M here: the |
153 | module will be called cros_ec_sysfs. | 153 | module will be called cros_ec_sysfs. |
154 | 154 | ||
155 | source "drivers/platform/chrome/wilco_ec/Kconfig" | ||
156 | |||
155 | endif # CHROMEOS_PLATFORMS | 157 | endif # CHROMEOS_PLATFORMS |
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile index fdbee501931b..1e2f0029b597 100644 --- a/drivers/platform/chrome/Makefile +++ b/drivers/platform/chrome/Makefile | |||
@@ -14,3 +14,5 @@ obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o | |||
14 | obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o | 14 | obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o |
15 | obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o | 15 | obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o |
16 | obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o | 16 | obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o |
17 | |||
18 | obj-$(CONFIG_WILCO_EC) += wilco_ec/ | ||
diff --git a/drivers/platform/chrome/chromeos_pstore.c b/drivers/platform/chrome/chromeos_pstore.c index b0693fdec8c6..d13770785fb5 100644 --- a/drivers/platform/chrome/chromeos_pstore.c +++ b/drivers/platform/chrome/chromeos_pstore.c | |||
@@ -1,12 +1,7 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | * chromeos_pstore.c - Driver to instantiate Chromebook ramoops device | 2 | // Driver to instantiate Chromebook ramoops device. |
3 | * | 3 | // |
4 | * Copyright (C) 2013 Google, Inc. | 4 | // Copyright (C) 2013 Google, Inc. |
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation, version 2 of the License. | ||
9 | */ | ||
10 | 5 | ||
11 | #include <linux/acpi.h> | 6 | #include <linux/acpi.h> |
12 | #include <linux/dmi.h> | 7 | #include <linux/dmi.h> |
@@ -138,5 +133,5 @@ static void __exit chromeos_pstore_exit(void) | |||
138 | module_init(chromeos_pstore_init); | 133 | module_init(chromeos_pstore_init); |
139 | module_exit(chromeos_pstore_exit); | 134 | module_exit(chromeos_pstore_exit); |
140 | 135 | ||
141 | MODULE_DESCRIPTION("Chrome OS pstore module"); | 136 | MODULE_DESCRIPTION("ChromeOS pstore module"); |
142 | MODULE_LICENSE("GPL"); | 137 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c index 6cacac53dfce..900c7073c46f 100644 --- a/drivers/platform/chrome/cros_ec_debugfs.c +++ b/drivers/platform/chrome/cros_ec_debugfs.c | |||
@@ -1,21 +1,7 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | * cros_ec_debugfs - debug logs for Chrome OS EC | 2 | // Debug logs for the ChromeOS EC |
3 | * | 3 | // |
4 | * Copyright 2015 Google, Inc. | 4 | // Copyright (C) 2015 Google, Inc. |
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | 5 | ||
20 | #include <linux/circ_buf.h> | 6 | #include <linux/circ_buf.h> |
21 | #include <linux/debugfs.h> | 7 | #include <linux/debugfs.h> |
diff --git a/drivers/platform/chrome/cros_ec_i2c.c b/drivers/platform/chrome/cros_ec_i2c.c index 9a009eaa4ada..61d75395f86d 100644 --- a/drivers/platform/chrome/cros_ec_i2c.c +++ b/drivers/platform/chrome/cros_ec_i2c.c | |||
@@ -1,17 +1,7 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | * ChromeOS EC multi-function device (I2C) | 2 | // I2C interface for ChromeOS Embedded Controller |
3 | * | 3 | // |
4 | * Copyright (C) 2012 Google, Inc | 4 | // Copyright (C) 2012 Google, Inc |
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | 5 | ||
16 | #include <linux/acpi.h> | 6 | #include <linux/acpi.h> |
17 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
@@ -372,5 +362,5 @@ static struct i2c_driver cros_ec_driver = { | |||
372 | 362 | ||
373 | module_i2c_driver(cros_ec_driver); | 363 | module_i2c_driver(cros_ec_driver); |
374 | 364 | ||
375 | MODULE_LICENSE("GPL"); | 365 | MODULE_LICENSE("GPL v2"); |
376 | MODULE_DESCRIPTION("ChromeOS EC multi function device"); | 366 | MODULE_DESCRIPTION("I2C interface for ChromeOS Embedded Controller"); |
diff --git a/drivers/platform/chrome/cros_ec_lightbar.c b/drivers/platform/chrome/cros_ec_lightbar.c index c3e4e6e5211d..d30a6650b0b5 100644 --- a/drivers/platform/chrome/cros_ec_lightbar.c +++ b/drivers/platform/chrome/cros_ec_lightbar.c | |||
@@ -1,23 +1,7 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | * cros_ec_lightbar - expose the Chromebook Pixel lightbar to userspace | 2 | // Expose the Chromebook Pixel lightbar to userspace |
3 | * | 3 | // |
4 | * Copyright (C) 2014 Google, Inc. | 4 | // Copyright (C) 2014 Google, Inc. |
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #define pr_fmt(fmt) "cros_ec_lightbar: " fmt | ||
21 | 5 | ||
22 | #include <linux/ctype.h> | 6 | #include <linux/ctype.h> |
23 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index 14684a56e40f..c9c240fbe7c6 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c | |||
@@ -1,25 +1,15 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | * cros_ec_lpc - LPC access to the Chrome OS Embedded Controller | 2 | // LPC interface for ChromeOS Embedded Controller |
3 | * | 3 | // |
4 | * Copyright (C) 2012-2015 Google, Inc | 4 | // Copyright (C) 2012-2015 Google, Inc |
5 | * | 5 | // |
6 | * This software is licensed under the terms of the GNU General Public | 6 | // This driver uses the ChromeOS EC byte-level message-based protocol for |
7 | * License version 2, as published by the Free Software Foundation, and | 7 | // communicating the keyboard state (which keys are pressed) from a keyboard EC |
8 | * may be copied, distributed, and modified under those terms. | 8 | // to the AP over some bus (such as i2c, lpc, spi). The EC does debouncing, |
9 | * | 9 | // but everything else (including deghosting) is done here. The main |
10 | * This program is distributed in the hope that it will be useful, | 10 | // motivation for this is to keep the EC firmware as simple as possible, since |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | // it cannot be easily upgraded and EC flash/IRAM space is relatively |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | // expensive. |
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * This driver uses the Chrome OS EC byte-level message-based protocol for | ||
16 | * communicating the keyboard state (which keys are pressed) from a keyboard EC | ||
17 | * to the AP over some bus (such as i2c, lpc, spi). The EC does debouncing, | ||
18 | * but everything else (including deghosting) is done here. The main | ||
19 | * motivation for this is to keep the EC firmware as simple as possible, since | ||
20 | * it cannot be easily upgraded and EC flash/IRAM space is relatively | ||
21 | * expensive. | ||
22 | */ | ||
23 | 13 | ||
24 | #include <linux/acpi.h> | 14 | #include <linux/acpi.h> |
25 | #include <linux/dmi.h> | 15 | #include <linux/dmi.h> |
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.c b/drivers/platform/chrome/cros_ec_lpc_mec.c index c4edfa83e493..d8890bafb55d 100644 --- a/drivers/platform/chrome/cros_ec_lpc_mec.c +++ b/drivers/platform/chrome/cros_ec_lpc_mec.c | |||
@@ -1,29 +1,10 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | * cros_ec_lpc_mec - LPC variant I/O for Microchip EC | 2 | // LPC variant I/O for Microchip EC |
3 | * | 3 | // |
4 | * Copyright (C) 2016 Google, Inc | 4 | // Copyright (C) 2016 Google, Inc |
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * This driver uses the Chrome OS EC byte-level message-based protocol for | ||
16 | * communicating the keyboard state (which keys are pressed) from a keyboard EC | ||
17 | * to the AP over some bus (such as i2c, lpc, spi). The EC does debouncing, | ||
18 | * but everything else (including deghosting) is done here. The main | ||
19 | * motivation for this is to keep the EC firmware as simple as possible, since | ||
20 | * it cannot be easily upgraded and EC flash/IRAM space is relatively | ||
21 | * expensive. | ||
22 | */ | ||
23 | 5 | ||
24 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
25 | #include <linux/io.h> | 7 | #include <linux/io.h> |
26 | #include <linux/mfd/cros_ec_commands.h> | ||
27 | #include <linux/mutex.h> | 8 | #include <linux/mutex.h> |
28 | #include <linux/types.h> | 9 | #include <linux/types.h> |
29 | 10 | ||
@@ -34,6 +15,7 @@ | |||
34 | * EC mutex because memmap data may be accessed without it being held. | 15 | * EC mutex because memmap data may be accessed without it being held. |
35 | */ | 16 | */ |
36 | static struct mutex io_mutex; | 17 | static struct mutex io_mutex; |
18 | static u16 mec_emi_base, mec_emi_end; | ||
37 | 19 | ||
38 | /* | 20 | /* |
39 | * cros_ec_lpc_mec_emi_write_address | 21 | * cros_ec_lpc_mec_emi_write_address |
@@ -46,10 +28,37 @@ static struct mutex io_mutex; | |||
46 | static void cros_ec_lpc_mec_emi_write_address(u16 addr, | 28 | static void cros_ec_lpc_mec_emi_write_address(u16 addr, |
47 | enum cros_ec_lpc_mec_emi_access_mode access_type) | 29 | enum cros_ec_lpc_mec_emi_access_mode access_type) |
48 | { | 30 | { |
49 | /* Address relative to start of EMI range */ | 31 | outb((addr & 0xfc) | access_type, MEC_EMI_EC_ADDRESS_B0(mec_emi_base)); |
50 | addr -= MEC_EMI_RANGE_START; | 32 | outb((addr >> 8) & 0x7f, MEC_EMI_EC_ADDRESS_B1(mec_emi_base)); |
51 | outb((addr & 0xfc) | access_type, MEC_EMI_EC_ADDRESS_B0); | 33 | } |
52 | outb((addr >> 8) & 0x7f, MEC_EMI_EC_ADDRESS_B1); | 34 | |
35 | /** | ||
36 | * cros_ec_lpc_mec_in_range() - Determine if addresses are in MEC EMI range. | ||
37 | * | ||
38 | * @offset: Address offset | ||
39 | * @length: Number of bytes to check | ||
40 | * | ||
41 | * Return: 1 if in range, 0 if not, and -EINVAL on failure | ||
42 | * such as the mec range not being initialized | ||
43 | */ | ||
44 | int cros_ec_lpc_mec_in_range(unsigned int offset, unsigned int length) | ||
45 | { | ||
46 | if (length == 0) | ||
47 | return -EINVAL; | ||
48 | |||
49 | if (WARN_ON(mec_emi_base == 0 || mec_emi_end == 0)) | ||
50 | return -EINVAL; | ||
51 | |||
52 | if (offset >= mec_emi_base && offset < mec_emi_end) { | ||
53 | if (WARN_ON(offset + length - 1 >= mec_emi_end)) | ||
54 | return -EINVAL; | ||
55 | return 1; | ||
56 | } | ||
57 | |||
58 | if (WARN_ON(offset + length > mec_emi_base && offset < mec_emi_end)) | ||
59 | return -EINVAL; | ||
60 | |||
61 | return 0; | ||
53 | } | 62 | } |
54 | 63 | ||
55 | /* | 64 | /* |
@@ -71,6 +80,11 @@ u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type, | |||
71 | u8 sum = 0; | 80 | u8 sum = 0; |
72 | enum cros_ec_lpc_mec_emi_access_mode access, new_access; | 81 | enum cros_ec_lpc_mec_emi_access_mode access, new_access; |
73 | 82 | ||
83 | /* Return checksum of 0 if window is not initialized */ | ||
84 | WARN_ON(mec_emi_base == 0 || mec_emi_end == 0); | ||
85 | if (mec_emi_base == 0 || mec_emi_end == 0) | ||
86 | return 0; | ||
87 | |||
74 | /* | 88 | /* |
75 | * Long access cannot be used on misaligned data since reading B0 loads | 89 | * Long access cannot be used on misaligned data since reading B0 loads |
76 | * the data register and writing B3 flushes. | 90 | * the data register and writing B3 flushes. |
@@ -86,9 +100,9 @@ u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type, | |||
86 | cros_ec_lpc_mec_emi_write_address(offset, access); | 100 | cros_ec_lpc_mec_emi_write_address(offset, access); |
87 | 101 | ||
88 | /* Skip bytes in case of misaligned offset */ | 102 | /* Skip bytes in case of misaligned offset */ |
89 | io_addr = MEC_EMI_EC_DATA_B0 + (offset & 0x3); | 103 | io_addr = MEC_EMI_EC_DATA_B0(mec_emi_base) + (offset & 0x3); |
90 | while (i < length) { | 104 | while (i < length) { |
91 | while (io_addr <= MEC_EMI_EC_DATA_B3) { | 105 | while (io_addr <= MEC_EMI_EC_DATA_B3(mec_emi_base)) { |
92 | if (io_type == MEC_IO_READ) | 106 | if (io_type == MEC_IO_READ) |
93 | buf[i] = inb(io_addr++); | 107 | buf[i] = inb(io_addr++); |
94 | else | 108 | else |
@@ -118,7 +132,7 @@ u8 cros_ec_lpc_io_bytes_mec(enum cros_ec_lpc_mec_io_type io_type, | |||
118 | } | 132 | } |
119 | 133 | ||
120 | /* Access [B0, B3] on each loop pass */ | 134 | /* Access [B0, B3] on each loop pass */ |
121 | io_addr = MEC_EMI_EC_DATA_B0; | 135 | io_addr = MEC_EMI_EC_DATA_B0(mec_emi_base); |
122 | } | 136 | } |
123 | 137 | ||
124 | done: | 138 | done: |
@@ -128,9 +142,11 @@ done: | |||
128 | } | 142 | } |
129 | EXPORT_SYMBOL(cros_ec_lpc_io_bytes_mec); | 143 | EXPORT_SYMBOL(cros_ec_lpc_io_bytes_mec); |
130 | 144 | ||
131 | void cros_ec_lpc_mec_init(void) | 145 | void cros_ec_lpc_mec_init(unsigned int base, unsigned int end) |
132 | { | 146 | { |
133 | mutex_init(&io_mutex); | 147 | mutex_init(&io_mutex); |
148 | mec_emi_base = base; | ||
149 | mec_emi_end = end; | ||
134 | } | 150 | } |
135 | EXPORT_SYMBOL(cros_ec_lpc_mec_init); | 151 | EXPORT_SYMBOL(cros_ec_lpc_mec_init); |
136 | 152 | ||
diff --git a/drivers/platform/chrome/cros_ec_lpc_mec.h b/drivers/platform/chrome/cros_ec_lpc_mec.h index 105068c0e919..aa1018f6b0f2 100644 --- a/drivers/platform/chrome/cros_ec_lpc_mec.h +++ b/drivers/platform/chrome/cros_ec_lpc_mec.h | |||
@@ -1,31 +1,13 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * cros_ec_lpc_mec - LPC variant I/O for Microchip EC | 3 | * LPC variant I/O for Microchip EC |
3 | * | 4 | * |
4 | * Copyright (C) 2016 Google, Inc | 5 | * Copyright (C) 2016 Google, Inc |
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * This driver uses the Chrome OS EC byte-level message-based protocol for | ||
16 | * communicating the keyboard state (which keys are pressed) from a keyboard EC | ||
17 | * to the AP over some bus (such as i2c, lpc, spi). The EC does debouncing, | ||
18 | * but everything else (including deghosting) is done here. The main | ||
19 | * motivation for this is to keep the EC firmware as simple as possible, since | ||
20 | * it cannot be easily upgraded and EC flash/IRAM space is relatively | ||
21 | * expensive. | ||
22 | */ | 6 | */ |
23 | 7 | ||
24 | #ifndef __CROS_EC_LPC_MEC_H | 8 | #ifndef __CROS_EC_LPC_MEC_H |
25 | #define __CROS_EC_LPC_MEC_H | 9 | #define __CROS_EC_LPC_MEC_H |
26 | 10 | ||
27 | #include <linux/mfd/cros_ec_commands.h> | ||
28 | |||
29 | enum cros_ec_lpc_mec_emi_access_mode { | 11 | enum cros_ec_lpc_mec_emi_access_mode { |
30 | /* 8-bit access */ | 12 | /* 8-bit access */ |
31 | ACCESS_TYPE_BYTE = 0x0, | 13 | ACCESS_TYPE_BYTE = 0x0, |
@@ -45,27 +27,23 @@ enum cros_ec_lpc_mec_io_type { | |||
45 | MEC_IO_WRITE, | 27 | MEC_IO_WRITE, |
46 | }; | 28 | }; |
47 | 29 | ||
48 | /* Access IO ranges 0x800 thru 0x9ff using EMI interface instead of LPC */ | ||
49 | #define MEC_EMI_RANGE_START EC_HOST_CMD_REGION0 | ||
50 | #define MEC_EMI_RANGE_END (EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE) | ||
51 | |||
52 | /* EMI registers are relative to base */ | 30 | /* EMI registers are relative to base */ |
53 | #define MEC_EMI_BASE 0x800 | 31 | #define MEC_EMI_HOST_TO_EC(MEC_EMI_BASE) ((MEC_EMI_BASE) + 0) |
54 | #define MEC_EMI_HOST_TO_EC (MEC_EMI_BASE + 0) | 32 | #define MEC_EMI_EC_TO_HOST(MEC_EMI_BASE) ((MEC_EMI_BASE) + 1) |
55 | #define MEC_EMI_EC_TO_HOST (MEC_EMI_BASE + 1) | 33 | #define MEC_EMI_EC_ADDRESS_B0(MEC_EMI_BASE) ((MEC_EMI_BASE) + 2) |
56 | #define MEC_EMI_EC_ADDRESS_B0 (MEC_EMI_BASE + 2) | 34 | #define MEC_EMI_EC_ADDRESS_B1(MEC_EMI_BASE) ((MEC_EMI_BASE) + 3) |
57 | #define MEC_EMI_EC_ADDRESS_B1 (MEC_EMI_BASE + 3) | 35 | #define MEC_EMI_EC_DATA_B0(MEC_EMI_BASE) ((MEC_EMI_BASE) + 4) |
58 | #define MEC_EMI_EC_DATA_B0 (MEC_EMI_BASE + 4) | 36 | #define MEC_EMI_EC_DATA_B1(MEC_EMI_BASE) ((MEC_EMI_BASE) + 5) |
59 | #define MEC_EMI_EC_DATA_B1 (MEC_EMI_BASE + 5) | 37 | #define MEC_EMI_EC_DATA_B2(MEC_EMI_BASE) ((MEC_EMI_BASE) + 6) |
60 | #define MEC_EMI_EC_DATA_B2 (MEC_EMI_BASE + 6) | 38 | #define MEC_EMI_EC_DATA_B3(MEC_EMI_BASE) ((MEC_EMI_BASE) + 7) |
61 | #define MEC_EMI_EC_DATA_B3 (MEC_EMI_BASE + 7) | ||
62 | 39 | ||
63 | /* | 40 | /** |
64 | * cros_ec_lpc_mec_init | 41 | * cros_ec_lpc_mec_init() - Initialize MEC I/O. |
65 | * | 42 | * |
66 | * Initialize MEC I/O. | 43 | * @base: MEC EMI Base address |
44 | * @end: MEC EMI End address | ||
67 | */ | 45 | */ |
68 | void cros_ec_lpc_mec_init(void); | 46 | void cros_ec_lpc_mec_init(unsigned int base, unsigned int end); |
69 | 47 | ||
70 | /* | 48 | /* |
71 | * cros_ec_lpc_mec_destroy | 49 | * cros_ec_lpc_mec_destroy |
@@ -75,6 +53,17 @@ void cros_ec_lpc_mec_init(void); | |||
75 | void cros_ec_lpc_mec_destroy(void); | 53 | void cros_ec_lpc_mec_destroy(void); |
76 | 54 | ||
77 | /** | 55 | /** |
56 | * cros_ec_lpc_mec_in_range() - Determine if addresses are in MEC EMI range. | ||
57 | * | ||
58 | * @offset: Address offset | ||
59 | * @length: Number of bytes to check | ||
60 | * | ||
61 | * Return: 1 if in range, 0 if not, and -EINVAL on failure | ||
62 | * such as the mec range not being initialized | ||
63 | */ | ||
64 | int cros_ec_lpc_mec_in_range(unsigned int offset, unsigned int length); | ||
65 | |||
66 | /** | ||
78 | * cros_ec_lpc_io_bytes_mec - Read / write bytes to MEC EMI port | 67 | * cros_ec_lpc_io_bytes_mec - Read / write bytes to MEC EMI port |
79 | * | 68 | * |
80 | * @io_type: MEC_IO_READ or MEC_IO_WRITE, depending on request | 69 | * @io_type: MEC_IO_READ or MEC_IO_WRITE, depending on request |
diff --git a/drivers/platform/chrome/cros_ec_lpc_reg.c b/drivers/platform/chrome/cros_ec_lpc_reg.c index fc23d535c404..0f5cd0ac8b49 100644 --- a/drivers/platform/chrome/cros_ec_lpc_reg.c +++ b/drivers/platform/chrome/cros_ec_lpc_reg.c | |||
@@ -1,25 +1,7 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | * cros_ec_lpc_reg - LPC access to the Chrome OS Embedded Controller | 2 | // LPC interface for ChromeOS Embedded Controller |
3 | * | 3 | // |
4 | * Copyright (C) 2016 Google, Inc | 4 | // Copyright (C) 2016 Google, Inc |
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * This driver uses the Chrome OS EC byte-level message-based protocol for | ||
16 | * communicating the keyboard state (which keys are pressed) from a keyboard EC | ||
17 | * to the AP over some bus (such as i2c, lpc, spi). The EC does debouncing, | ||
18 | * but everything else (including deghosting) is done here. The main | ||
19 | * motivation for this is to keep the EC firmware as simple as possible, since | ||
20 | * it cannot be easily upgraded and EC flash/IRAM space is relatively | ||
21 | * expensive. | ||
22 | */ | ||
23 | 5 | ||
24 | #include <linux/io.h> | 6 | #include <linux/io.h> |
25 | #include <linux/mfd/cros_ec.h> | 7 | #include <linux/mfd/cros_ec.h> |
@@ -59,51 +41,36 @@ static u8 lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg) | |||
59 | 41 | ||
60 | u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest) | 42 | u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest) |
61 | { | 43 | { |
62 | if (length == 0) | 44 | int in_range = cros_ec_lpc_mec_in_range(offset, length); |
63 | return 0; | ||
64 | |||
65 | /* Access desired range through EMI interface */ | ||
66 | if (offset >= MEC_EMI_RANGE_START && offset <= MEC_EMI_RANGE_END) { | ||
67 | /* Ensure we don't straddle EMI region */ | ||
68 | if (WARN_ON(offset + length - 1 > MEC_EMI_RANGE_END)) | ||
69 | return 0; | ||
70 | 45 | ||
71 | return cros_ec_lpc_io_bytes_mec(MEC_IO_READ, offset, length, | 46 | if (in_range < 0) |
72 | dest); | ||
73 | } | ||
74 | |||
75 | if (WARN_ON(offset + length > MEC_EMI_RANGE_START && | ||
76 | offset < MEC_EMI_RANGE_START)) | ||
77 | return 0; | 47 | return 0; |
78 | 48 | ||
79 | return lpc_read_bytes(offset, length, dest); | 49 | return in_range ? |
50 | cros_ec_lpc_io_bytes_mec(MEC_IO_READ, | ||
51 | offset - EC_HOST_CMD_REGION0, | ||
52 | length, dest) : | ||
53 | lpc_read_bytes(offset, length, dest); | ||
80 | } | 54 | } |
81 | 55 | ||
82 | u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg) | 56 | u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg) |
83 | { | 57 | { |
84 | if (length == 0) | 58 | int in_range = cros_ec_lpc_mec_in_range(offset, length); |
85 | return 0; | ||
86 | |||
87 | /* Access desired range through EMI interface */ | ||
88 | if (offset >= MEC_EMI_RANGE_START && offset <= MEC_EMI_RANGE_END) { | ||
89 | /* Ensure we don't straddle EMI region */ | ||
90 | if (WARN_ON(offset + length - 1 > MEC_EMI_RANGE_END)) | ||
91 | return 0; | ||
92 | 59 | ||
93 | return cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, offset, length, | 60 | if (in_range < 0) |
94 | msg); | ||
95 | } | ||
96 | |||
97 | if (WARN_ON(offset + length > MEC_EMI_RANGE_START && | ||
98 | offset < MEC_EMI_RANGE_START)) | ||
99 | return 0; | 61 | return 0; |
100 | 62 | ||
101 | return lpc_write_bytes(offset, length, msg); | 63 | return in_range ? |
64 | cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, | ||
65 | offset - EC_HOST_CMD_REGION0, | ||
66 | length, msg) : | ||
67 | lpc_write_bytes(offset, length, msg); | ||
102 | } | 68 | } |
103 | 69 | ||
104 | void cros_ec_lpc_reg_init(void) | 70 | void cros_ec_lpc_reg_init(void) |
105 | { | 71 | { |
106 | cros_ec_lpc_mec_init(); | 72 | cros_ec_lpc_mec_init(EC_HOST_CMD_REGION0, |
73 | EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE); | ||
107 | } | 74 | } |
108 | 75 | ||
109 | void cros_ec_lpc_reg_destroy(void) | 76 | void cros_ec_lpc_reg_destroy(void) |
diff --git a/drivers/platform/chrome/cros_ec_lpc_reg.h b/drivers/platform/chrome/cros_ec_lpc_reg.h index 1c12c38b306a..416fd2572182 100644 --- a/drivers/platform/chrome/cros_ec_lpc_reg.h +++ b/drivers/platform/chrome/cros_ec_lpc_reg.h | |||
@@ -1,24 +1,8 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * cros_ec_lpc_reg - LPC access to the Chrome OS Embedded Controller | 3 | * LPC interface for ChromeOS Embedded Controller |
3 | * | 4 | * |
4 | * Copyright (C) 2016 Google, Inc | 5 | * Copyright (C) 2016 Google, Inc |
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * This driver uses the Chrome OS EC byte-level message-based protocol for | ||
16 | * communicating the keyboard state (which keys are pressed) from a keyboard EC | ||
17 | * to the AP over some bus (such as i2c, lpc, spi). The EC does debouncing, | ||
18 | * but everything else (including deghosting) is done here. The main | ||
19 | * motivation for this is to keep the EC firmware as simple as possible, since | ||
20 | * it cannot be easily upgraded and EC flash/IRAM space is relatively | ||
21 | * expensive. | ||
22 | */ | 6 | */ |
23 | 7 | ||
24 | #ifndef __CROS_EC_LPC_REG_H | 8 | #ifndef __CROS_EC_LPC_REG_H |
diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index cc7baf0ecb3c..97a068dff192 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c | |||
@@ -1,18 +1,7 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | * ChromeOS EC communication protocol helper functions | 2 | // ChromeOS EC communication protocol helper functions |
3 | * | 3 | // |
4 | * Copyright (C) 2015 Google, Inc | 4 | // Copyright (C) 2015 Google, Inc |
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | 5 | ||
17 | #include <linux/mfd/cros_ec.h> | 6 | #include <linux/mfd/cros_ec.h> |
18 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
diff --git a/drivers/platform/chrome/cros_ec_spi.c b/drivers/platform/chrome/cros_ec_spi.c index 6cfbc2835beb..ffc38f9d4829 100644 --- a/drivers/platform/chrome/cros_ec_spi.c +++ b/drivers/platform/chrome/cros_ec_spi.c | |||
@@ -1,17 +1,7 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | * ChromeOS EC multi-function device (SPI) | 2 | // SPI interface for ChromeOS Embedded Controller |
3 | * | 3 | // |
4 | * Copyright (C) 2012 Google, Inc | 4 | // Copyright (C) 2012 Google, Inc |
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | 5 | ||
16 | #include <linux/delay.h> | 6 | #include <linux/delay.h> |
17 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
@@ -729,4 +719,4 @@ static struct spi_driver cros_ec_driver_spi = { | |||
729 | module_spi_driver(cros_ec_driver_spi); | 719 | module_spi_driver(cros_ec_driver_spi); |
730 | 720 | ||
731 | MODULE_LICENSE("GPL v2"); | 721 | MODULE_LICENSE("GPL v2"); |
732 | MODULE_DESCRIPTION("ChromeOS EC multi function device (SPI)"); | 722 | MODULE_DESCRIPTION("SPI interface for ChromeOS Embedded Controller"); |
diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c index 0ff5aa30c070..fe0b7614ae1b 100644 --- a/drivers/platform/chrome/cros_ec_sysfs.c +++ b/drivers/platform/chrome/cros_ec_sysfs.c | |||
@@ -1,23 +1,7 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | * cros_ec_sysfs - expose the Chrome OS EC through sysfs | 2 | // Expose the ChromeOS EC through sysfs |
3 | * | 3 | // |
4 | * Copyright (C) 2014 Google, Inc. | 4 | // Copyright (C) 2014 Google, Inc. |
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #define pr_fmt(fmt) "cros_ec_sysfs: " fmt | ||
21 | 5 | ||
22 | #include <linux/ctype.h> | 6 | #include <linux/ctype.h> |
23 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
@@ -389,5 +373,5 @@ static struct platform_driver cros_ec_sysfs_driver = { | |||
389 | module_platform_driver(cros_ec_sysfs_driver); | 373 | module_platform_driver(cros_ec_sysfs_driver); |
390 | 374 | ||
391 | MODULE_LICENSE("GPL"); | 375 | MODULE_LICENSE("GPL"); |
392 | MODULE_DESCRIPTION("ChromeOS EC control driver"); | 376 | MODULE_DESCRIPTION("Expose the ChromeOS EC through sysfs"); |
393 | MODULE_ALIAS("platform:" DRV_NAME); | 377 | MODULE_ALIAS("platform:" DRV_NAME); |
diff --git a/drivers/platform/chrome/cros_ec_vbc.c b/drivers/platform/chrome/cros_ec_vbc.c index af9bfe6f385c..8392a1ec33a7 100644 --- a/drivers/platform/chrome/cros_ec_vbc.c +++ b/drivers/platform/chrome/cros_ec_vbc.c | |||
@@ -1,22 +1,8 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | * cros_ec_vbc - Expose the vboot context nvram to userspace | 2 | // Expose the vboot context nvram to userspace |
3 | * | 3 | // |
4 | * Copyright (C) 2015 Collabora Ltd. | 4 | // Copyright (C) 2012 Google, Inc. |
5 | * | 5 | // Copyright (C) 2015 Collabora Ltd. |
6 | * based on vendor driver, | ||
7 | * | ||
8 | * Copyright (C) 2012 The Chromium OS Authors | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | */ | ||
20 | 6 | ||
21 | #include <linux/of.h> | 7 | #include <linux/of.h> |
22 | #include <linux/platform_device.h> | 8 | #include <linux/platform_device.h> |
diff --git a/drivers/platform/chrome/cros_kbd_led_backlight.c b/drivers/platform/chrome/cros_kbd_led_backlight.c index ca3e4da852b4..aa409f0201fb 100644 --- a/drivers/platform/chrome/cros_kbd_led_backlight.c +++ b/drivers/platform/chrome/cros_kbd_led_backlight.c | |||
@@ -1,18 +1,7 @@ | |||
1 | /* | 1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | * Keyboard backlight LED driver for Chrome OS. | 2 | // Keyboard backlight LED driver for ChromeOS |
3 | * | 3 | // |
4 | * Copyright (C) 2012 Google, Inc. | 4 | // Copyright (C) 2012 Google, Inc. |
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | 5 | ||
17 | #include <linux/acpi.h> | 6 | #include <linux/acpi.h> |
18 | #include <linux/leds.h> | 7 | #include <linux/leds.h> |
diff --git a/drivers/platform/chrome/wilco_ec/Kconfig b/drivers/platform/chrome/wilco_ec/Kconfig new file mode 100644 index 000000000000..e09e4cebe9b4 --- /dev/null +++ b/drivers/platform/chrome/wilco_ec/Kconfig | |||
@@ -0,0 +1,20 @@ | |||
1 | config WILCO_EC | ||
2 | tristate "ChromeOS Wilco Embedded Controller" | ||
3 | depends on ACPI && X86 && CROS_EC_LPC && CROS_EC_LPC_MEC | ||
4 | help | ||
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 | ||
7 | with a checksum. | ||
8 | |||
9 | To compile this driver as a module, choose M here: the | ||
10 | module will be called wilco_ec. | ||
11 | |||
12 | config WILCO_EC_DEBUGFS | ||
13 | tristate "Enable raw access to EC via debugfs" | ||
14 | depends on WILCO_EC | ||
15 | help | ||
16 | If you say Y here, you get support for sending raw commands to | ||
17 | the Wilco EC via debugfs. These commands do not do any byte | ||
18 | manipulation and allow for testing arbitrary commands. This | ||
19 | interface is intended for debug only and will not be present | ||
20 | on production devices. | ||
diff --git a/drivers/platform/chrome/wilco_ec/Makefile b/drivers/platform/chrome/wilco_ec/Makefile new file mode 100644 index 000000000000..063e7fb4ea17 --- /dev/null +++ b/drivers/platform/chrome/wilco_ec/Makefile | |||
@@ -0,0 +1,6 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | ||
2 | |||
3 | wilco_ec-objs := core.o mailbox.o | ||
4 | obj-$(CONFIG_WILCO_EC) += wilco_ec.o | ||
5 | wilco_ec_debugfs-objs := debugfs.o | ||
6 | obj-$(CONFIG_WILCO_EC_DEBUGFS) += wilco_ec_debugfs.o | ||
diff --git a/drivers/platform/chrome/wilco_ec/core.c b/drivers/platform/chrome/wilco_ec/core.c new file mode 100644 index 000000000000..05e1e2be1c91 --- /dev/null +++ b/drivers/platform/chrome/wilco_ec/core.c | |||
@@ -0,0 +1,136 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Core driver for Wilco Embedded Controller | ||
4 | * | ||
5 | * Copyright 2018 Google LLC | ||
6 | * | ||
7 | * This is the entry point for the drivers that control the Wilco EC. | ||
8 | * This driver is responsible for several tasks: | ||
9 | * - Initialize the register interface that is used by wilco_ec_mailbox() | ||
10 | * - Create a platform device which is picked up by the debugfs driver | ||
11 | * - Create a platform device which is picked up by the RTC driver | ||
12 | */ | ||
13 | |||
14 | #include <linux/acpi.h> | ||
15 | #include <linux/device.h> | ||
16 | #include <linux/ioport.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/platform_data/wilco-ec.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | |||
21 | #include "../cros_ec_lpc_mec.h" | ||
22 | |||
23 | #define DRV_NAME "wilco-ec" | ||
24 | |||
25 | static struct resource *wilco_get_resource(struct platform_device *pdev, | ||
26 | int index) | ||
27 | { | ||
28 | struct device *dev = &pdev->dev; | ||
29 | struct resource *res; | ||
30 | |||
31 | res = platform_get_resource(pdev, IORESOURCE_IO, index); | ||
32 | if (!res) { | ||
33 | dev_dbg(dev, "Couldn't find IO resource %d\n", index); | ||
34 | return res; | ||
35 | } | ||
36 | |||
37 | return devm_request_region(dev, res->start, resource_size(res), | ||
38 | dev_name(dev)); | ||
39 | } | ||
40 | |||
41 | static int wilco_ec_probe(struct platform_device *pdev) | ||
42 | { | ||
43 | struct device *dev = &pdev->dev; | ||
44 | struct wilco_ec_device *ec; | ||
45 | int ret; | ||
46 | |||
47 | ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL); | ||
48 | if (!ec) | ||
49 | return -ENOMEM; | ||
50 | |||
51 | platform_set_drvdata(pdev, ec); | ||
52 | ec->dev = dev; | ||
53 | mutex_init(&ec->mailbox_lock); | ||
54 | |||
55 | /* Largest data buffer size requirement is extended data response */ | ||
56 | ec->data_size = sizeof(struct wilco_ec_response) + | ||
57 | EC_MAILBOX_DATA_SIZE_EXTENDED; | ||
58 | ec->data_buffer = devm_kzalloc(dev, ec->data_size, GFP_KERNEL); | ||
59 | if (!ec->data_buffer) | ||
60 | return -ENOMEM; | ||
61 | |||
62 | /* Prepare access to IO regions provided by ACPI */ | ||
63 | ec->io_data = wilco_get_resource(pdev, 0); /* Host Data */ | ||
64 | ec->io_command = wilco_get_resource(pdev, 1); /* Host Command */ | ||
65 | ec->io_packet = wilco_get_resource(pdev, 2); /* MEC EMI */ | ||
66 | if (!ec->io_data || !ec->io_command || !ec->io_packet) | ||
67 | return -ENODEV; | ||
68 | |||
69 | /* Initialize cros_ec register interface for communication */ | ||
70 | cros_ec_lpc_mec_init(ec->io_packet->start, | ||
71 | ec->io_packet->start + EC_MAILBOX_DATA_SIZE); | ||
72 | |||
73 | /* | ||
74 | * Register a child device that will be found by the debugfs driver. | ||
75 | * Ignore failure. | ||
76 | */ | ||
77 | ec->debugfs_pdev = platform_device_register_data(dev, | ||
78 | "wilco-ec-debugfs", | ||
79 | PLATFORM_DEVID_AUTO, | ||
80 | NULL, 0); | ||
81 | |||
82 | /* Register a child device that will be found by the RTC driver. */ | ||
83 | ec->rtc_pdev = platform_device_register_data(dev, "rtc-wilco-ec", | ||
84 | PLATFORM_DEVID_AUTO, | ||
85 | NULL, 0); | ||
86 | if (IS_ERR(ec->rtc_pdev)) { | ||
87 | dev_err(dev, "Failed to create RTC platform device\n"); | ||
88 | ret = PTR_ERR(ec->rtc_pdev); | ||
89 | goto unregister_debugfs; | ||
90 | } | ||
91 | |||
92 | return 0; | ||
93 | |||
94 | unregister_debugfs: | ||
95 | if (ec->debugfs_pdev) | ||
96 | platform_device_unregister(ec->debugfs_pdev); | ||
97 | cros_ec_lpc_mec_destroy(); | ||
98 | return ret; | ||
99 | } | ||
100 | |||
101 | static int wilco_ec_remove(struct platform_device *pdev) | ||
102 | { | ||
103 | struct wilco_ec_device *ec = platform_get_drvdata(pdev); | ||
104 | |||
105 | platform_device_unregister(ec->rtc_pdev); | ||
106 | if (ec->debugfs_pdev) | ||
107 | platform_device_unregister(ec->debugfs_pdev); | ||
108 | |||
109 | /* Teardown cros_ec interface */ | ||
110 | cros_ec_lpc_mec_destroy(); | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static const struct acpi_device_id wilco_ec_acpi_device_ids[] = { | ||
116 | { "GOOG000C", 0 }, | ||
117 | { } | ||
118 | }; | ||
119 | MODULE_DEVICE_TABLE(acpi, wilco_ec_acpi_device_ids); | ||
120 | |||
121 | static struct platform_driver wilco_ec_driver = { | ||
122 | .driver = { | ||
123 | .name = DRV_NAME, | ||
124 | .acpi_match_table = wilco_ec_acpi_device_ids, | ||
125 | }, | ||
126 | .probe = wilco_ec_probe, | ||
127 | .remove = wilco_ec_remove, | ||
128 | }; | ||
129 | |||
130 | module_platform_driver(wilco_ec_driver); | ||
131 | |||
132 | MODULE_AUTHOR("Nick Crews <ncrews@chromium.org>"); | ||
133 | MODULE_AUTHOR("Duncan Laurie <dlaurie@chromium.org>"); | ||
134 | MODULE_LICENSE("GPL v2"); | ||
135 | MODULE_DESCRIPTION("ChromeOS Wilco Embedded Controller driver"); | ||
136 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/platform/chrome/wilco_ec/debugfs.c b/drivers/platform/chrome/wilco_ec/debugfs.c new file mode 100644 index 000000000000..c090db2cd5be --- /dev/null +++ b/drivers/platform/chrome/wilco_ec/debugfs.c | |||
@@ -0,0 +1,238 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * debugfs attributes for Wilco EC | ||
4 | * | ||
5 | * Copyright 2019 Google LLC | ||
6 | * | ||
7 | * There is only one attribute used for debugging, called raw. | ||
8 | * You can write a hexadecimal sentence to raw, and that series of bytes | ||
9 | * will be sent to the EC. Then, you can read the bytes of response | ||
10 | * by reading from raw. | ||
11 | * | ||
12 | * For writing: | ||
13 | * Bytes 0-1 indicate the message type: | ||
14 | * 00 F0 = Execute Legacy Command | ||
15 | * 00 F2 = Read/Write NVRAM Property | ||
16 | * Byte 2 provides the command code | ||
17 | * Bytes 3+ consist of the data passed in the request | ||
18 | * | ||
19 | * When referencing the EC interface spec, byte 2 corresponds to MBOX[0], | ||
20 | * byte 3 corresponds to MBOX[1], etc. | ||
21 | * | ||
22 | * At least three bytes are required, for the msg type and command, | ||
23 | * with additional bytes optional for additional data. | ||
24 | * | ||
25 | * Example: | ||
26 | * // Request EC info type 3 (EC firmware build date) | ||
27 | * $ echo 00 f0 38 00 03 00 > raw | ||
28 | * // View the result. The decoded ASCII result "12/21/18" is | ||
29 | * // included after the raw hex. | ||
30 | * $ cat raw | ||
31 | * 00 31 32 2f 32 31 2f 31 38 00 38 00 01 00 2f 00 .12/21/18.8... | ||
32 | */ | ||
33 | |||
34 | #include <linux/ctype.h> | ||
35 | #include <linux/debugfs.h> | ||
36 | #include <linux/fs.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/platform_data/wilco-ec.h> | ||
39 | #include <linux/platform_device.h> | ||
40 | |||
41 | #define DRV_NAME "wilco-ec-debugfs" | ||
42 | |||
43 | /* The 256 raw bytes will take up more space when represented as a hex string */ | ||
44 | #define FORMATTED_BUFFER_SIZE (EC_MAILBOX_DATA_SIZE_EXTENDED * 4) | ||
45 | |||
46 | struct wilco_ec_debugfs { | ||
47 | struct wilco_ec_device *ec; | ||
48 | struct dentry *dir; | ||
49 | size_t response_size; | ||
50 | u8 raw_data[EC_MAILBOX_DATA_SIZE_EXTENDED]; | ||
51 | u8 formatted_data[FORMATTED_BUFFER_SIZE]; | ||
52 | }; | ||
53 | static struct wilco_ec_debugfs *debug_info; | ||
54 | |||
55 | /** | ||
56 | * parse_hex_sentence() - Convert a ascii hex representation into byte array. | ||
57 | * @in: Input buffer of ascii. | ||
58 | * @isize: Length of input buffer. | ||
59 | * @out: Output buffer. | ||
60 | * @osize: Length of output buffer, e.g. max number of bytes to parse. | ||
61 | * | ||
62 | * An valid input is a series of ascii hexadecimal numbers, separated by spaces. | ||
63 | * An example valid input is | ||
64 | * " 00 f2 0 000076 6 0 ff" | ||
65 | * | ||
66 | * If an individual "word" within the hex sentence is longer than MAX_WORD_SIZE, | ||
67 | * then the sentence is illegal, and parsing will fail. | ||
68 | * | ||
69 | * Return: Number of bytes parsed, or negative error code on failure. | ||
70 | */ | ||
71 | static int parse_hex_sentence(const char *in, int isize, u8 *out, int osize) | ||
72 | { | ||
73 | int n_parsed = 0; | ||
74 | int word_start = 0; | ||
75 | int word_end; | ||
76 | int word_len; | ||
77 | /* Temp buffer for holding a "word" of chars that represents one byte */ | ||
78 | #define MAX_WORD_SIZE 16 | ||
79 | char tmp[MAX_WORD_SIZE + 1]; | ||
80 | u8 byte; | ||
81 | |||
82 | while (word_start < isize && n_parsed < osize) { | ||
83 | /* Find the start of the next word */ | ||
84 | while (word_start < isize && isspace(in[word_start])) | ||
85 | word_start++; | ||
86 | /* reached the end of the input before next word? */ | ||
87 | if (word_start >= isize) | ||
88 | break; | ||
89 | |||
90 | /* Find the end of this word */ | ||
91 | word_end = word_start; | ||
92 | while (word_end < isize && !isspace(in[word_end])) | ||
93 | word_end++; | ||
94 | |||
95 | /* Copy to a tmp NULL terminated string */ | ||
96 | word_len = word_end - word_start; | ||
97 | if (word_len > MAX_WORD_SIZE) | ||
98 | return -EINVAL; | ||
99 | memcpy(tmp, in + word_start, word_len); | ||
100 | tmp[word_len] = '\0'; | ||
101 | |||
102 | /* | ||
103 | * Convert from hex string, place in output. If fails to parse, | ||
104 | * just return -EINVAL because specific error code is only | ||
105 | * relevant for this one word, returning it would be confusing. | ||
106 | */ | ||
107 | if (kstrtou8(tmp, 16, &byte)) | ||
108 | return -EINVAL; | ||
109 | out[n_parsed++] = byte; | ||
110 | |||
111 | word_start = word_end; | ||
112 | } | ||
113 | return n_parsed; | ||
114 | } | ||
115 | |||
116 | /* The message type takes up two bytes*/ | ||
117 | #define TYPE_AND_DATA_SIZE ((EC_MAILBOX_DATA_SIZE) + 2) | ||
118 | |||
119 | static ssize_t raw_write(struct file *file, const char __user *user_buf, | ||
120 | size_t count, loff_t *ppos) | ||
121 | { | ||
122 | char *buf = debug_info->formatted_data; | ||
123 | struct wilco_ec_message msg; | ||
124 | u8 request_data[TYPE_AND_DATA_SIZE]; | ||
125 | ssize_t kcount; | ||
126 | int ret; | ||
127 | |||
128 | if (count > FORMATTED_BUFFER_SIZE) | ||
129 | return -EINVAL; | ||
130 | |||
131 | kcount = simple_write_to_buffer(buf, FORMATTED_BUFFER_SIZE, ppos, | ||
132 | user_buf, count); | ||
133 | if (kcount < 0) | ||
134 | return kcount; | ||
135 | |||
136 | ret = parse_hex_sentence(buf, kcount, request_data, TYPE_AND_DATA_SIZE); | ||
137 | if (ret < 0) | ||
138 | return ret; | ||
139 | /* Need at least two bytes for message type and one for command */ | ||
140 | if (ret < 3) | ||
141 | return -EINVAL; | ||
142 | |||
143 | /* Clear response data buffer */ | ||
144 | memset(debug_info->raw_data, '\0', EC_MAILBOX_DATA_SIZE_EXTENDED); | ||
145 | |||
146 | msg.type = request_data[0] << 8 | request_data[1]; | ||
147 | msg.flags = WILCO_EC_FLAG_RAW; | ||
148 | msg.command = request_data[2]; | ||
149 | msg.request_data = ret > 3 ? request_data + 3 : 0; | ||
150 | msg.request_size = ret - 3; | ||
151 | msg.response_data = debug_info->raw_data; | ||
152 | msg.response_size = EC_MAILBOX_DATA_SIZE; | ||
153 | |||
154 | /* Telemetry commands use extended response data */ | ||
155 | if (msg.type == WILCO_EC_MSG_TELEMETRY_LONG) { | ||
156 | msg.flags |= WILCO_EC_FLAG_EXTENDED_DATA; | ||
157 | msg.response_size = EC_MAILBOX_DATA_SIZE_EXTENDED; | ||
158 | } | ||
159 | |||
160 | ret = wilco_ec_mailbox(debug_info->ec, &msg); | ||
161 | if (ret < 0) | ||
162 | return ret; | ||
163 | debug_info->response_size = ret; | ||
164 | |||
165 | return count; | ||
166 | } | ||
167 | |||
168 | static ssize_t raw_read(struct file *file, char __user *user_buf, size_t count, | ||
169 | loff_t *ppos) | ||
170 | { | ||
171 | int fmt_len = 0; | ||
172 | |||
173 | if (debug_info->response_size) { | ||
174 | fmt_len = hex_dump_to_buffer(debug_info->raw_data, | ||
175 | debug_info->response_size, | ||
176 | 16, 1, debug_info->formatted_data, | ||
177 | FORMATTED_BUFFER_SIZE, true); | ||
178 | /* Only return response the first time it is read */ | ||
179 | debug_info->response_size = 0; | ||
180 | } | ||
181 | |||
182 | return simple_read_from_buffer(user_buf, count, ppos, | ||
183 | debug_info->formatted_data, fmt_len); | ||
184 | } | ||
185 | |||
186 | static const struct file_operations fops_raw = { | ||
187 | .owner = THIS_MODULE, | ||
188 | .read = raw_read, | ||
189 | .write = raw_write, | ||
190 | .llseek = no_llseek, | ||
191 | }; | ||
192 | |||
193 | /** | ||
194 | * wilco_ec_debugfs_probe() - Create the debugfs node | ||
195 | * @pdev: The platform device, probably created in core.c | ||
196 | * | ||
197 | * Try to create a debugfs node. If it fails, then we don't want to change | ||
198 | * behavior at all, this is for debugging after all. Just fail silently. | ||
199 | * | ||
200 | * Return: 0 always. | ||
201 | */ | ||
202 | static int wilco_ec_debugfs_probe(struct platform_device *pdev) | ||
203 | { | ||
204 | struct wilco_ec_device *ec = dev_get_drvdata(pdev->dev.parent); | ||
205 | |||
206 | debug_info = devm_kzalloc(&pdev->dev, sizeof(*debug_info), GFP_KERNEL); | ||
207 | if (!debug_info) | ||
208 | return 0; | ||
209 | debug_info->ec = ec; | ||
210 | debug_info->dir = debugfs_create_dir("wilco_ec", NULL); | ||
211 | if (!debug_info->dir) | ||
212 | return 0; | ||
213 | debugfs_create_file("raw", 0644, debug_info->dir, NULL, &fops_raw); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static int wilco_ec_debugfs_remove(struct platform_device *pdev) | ||
219 | { | ||
220 | debugfs_remove_recursive(debug_info->dir); | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static struct platform_driver wilco_ec_debugfs_driver = { | ||
226 | .driver = { | ||
227 | .name = DRV_NAME, | ||
228 | }, | ||
229 | .probe = wilco_ec_debugfs_probe, | ||
230 | .remove = wilco_ec_debugfs_remove, | ||
231 | }; | ||
232 | |||
233 | module_platform_driver(wilco_ec_debugfs_driver); | ||
234 | |||
235 | MODULE_ALIAS("platform:" DRV_NAME); | ||
236 | MODULE_AUTHOR("Nick Crews <ncrews@chromium.org>"); | ||
237 | MODULE_LICENSE("GPL v2"); | ||
238 | MODULE_DESCRIPTION("Wilco EC debugfs driver"); | ||
diff --git a/drivers/platform/chrome/wilco_ec/mailbox.c b/drivers/platform/chrome/wilco_ec/mailbox.c new file mode 100644 index 000000000000..f6ff29a11f1a --- /dev/null +++ b/drivers/platform/chrome/wilco_ec/mailbox.c | |||
@@ -0,0 +1,237 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * Mailbox interface for Wilco Embedded Controller | ||
4 | * | ||
5 | * Copyright 2018 Google LLC | ||
6 | * | ||
7 | * The Wilco EC is similar to a typical ChromeOS embedded controller. | ||
8 | * It uses the same MEC based low-level communication and a similar | ||
9 | * protocol, but with some important differences. The EC firmware does | ||
10 | * not support the same mailbox commands so it is not registered as a | ||
11 | * cros_ec device type. | ||
12 | * | ||
13 | * Most messages follow a standard format, but there are some exceptions | ||
14 | * and an interface is provided to do direct/raw transactions that do not | ||
15 | * make assumptions about byte placement. | ||
16 | */ | ||
17 | |||
18 | #include <linux/delay.h> | ||
19 | #include <linux/device.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <linux/platform_data/wilco-ec.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | |||
24 | #include "../cros_ec_lpc_mec.h" | ||
25 | |||
26 | /* Version of mailbox interface */ | ||
27 | #define EC_MAILBOX_VERSION 0 | ||
28 | |||
29 | /* Command to start mailbox transaction */ | ||
30 | #define EC_MAILBOX_START_COMMAND 0xda | ||
31 | |||
32 | /* Version of EC protocol */ | ||
33 | #define EC_MAILBOX_PROTO_VERSION 3 | ||
34 | |||
35 | /* Number of header bytes to be counted as data bytes */ | ||
36 | #define EC_MAILBOX_DATA_EXTRA 2 | ||
37 | |||
38 | /* Maximum timeout */ | ||
39 | #define EC_MAILBOX_TIMEOUT HZ | ||
40 | |||
41 | /* EC response flags */ | ||
42 | #define EC_CMDR_DATA BIT(0) /* Data ready for host to read */ | ||
43 | #define EC_CMDR_PENDING BIT(1) /* Write pending to EC */ | ||
44 | #define EC_CMDR_BUSY BIT(2) /* EC is busy processing a command */ | ||
45 | #define EC_CMDR_CMD BIT(3) /* Last host write was a command */ | ||
46 | |||
47 | /** | ||
48 | * wilco_ec_response_timed_out() - Wait for EC response. | ||
49 | * @ec: EC device. | ||
50 | * | ||
51 | * Return: true if EC timed out, false if EC did not time out. | ||
52 | */ | ||
53 | static bool wilco_ec_response_timed_out(struct wilco_ec_device *ec) | ||
54 | { | ||
55 | unsigned long timeout = jiffies + EC_MAILBOX_TIMEOUT; | ||
56 | |||
57 | do { | ||
58 | if (!(inb(ec->io_command->start) & | ||
59 | (EC_CMDR_PENDING | EC_CMDR_BUSY))) | ||
60 | return false; | ||
61 | usleep_range(100, 200); | ||
62 | } while (time_before(jiffies, timeout)); | ||
63 | |||
64 | return true; | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * wilco_ec_checksum() - Compute 8-bit checksum over data range. | ||
69 | * @data: Data to checksum. | ||
70 | * @size: Number of bytes to checksum. | ||
71 | * | ||
72 | * Return: 8-bit checksum of provided data. | ||
73 | */ | ||
74 | static u8 wilco_ec_checksum(const void *data, size_t size) | ||
75 | { | ||
76 | u8 *data_bytes = (u8 *)data; | ||
77 | u8 checksum = 0; | ||
78 | size_t i; | ||
79 | |||
80 | for (i = 0; i < size; i++) | ||
81 | checksum += data_bytes[i]; | ||
82 | |||
83 | return checksum; | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * wilco_ec_prepare() - Prepare the request structure for the EC. | ||
88 | * @msg: EC message with request information. | ||
89 | * @rq: EC request structure to fill. | ||
90 | */ | ||
91 | static void wilco_ec_prepare(struct wilco_ec_message *msg, | ||
92 | struct wilco_ec_request *rq) | ||
93 | { | ||
94 | memset(rq, 0, sizeof(*rq)); | ||
95 | |||
96 | /* Handle messages without trimming bytes from the request */ | ||
97 | if (msg->request_size && msg->flags & WILCO_EC_FLAG_RAW_REQUEST) { | ||
98 | rq->reserved_raw = *(u8 *)msg->request_data; | ||
99 | msg->request_size--; | ||
100 | memmove(msg->request_data, msg->request_data + 1, | ||
101 | msg->request_size); | ||
102 | } | ||
103 | |||
104 | /* Fill in request packet */ | ||
105 | rq->struct_version = EC_MAILBOX_PROTO_VERSION; | ||
106 | rq->mailbox_id = msg->type; | ||
107 | rq->mailbox_version = EC_MAILBOX_VERSION; | ||
108 | rq->data_size = msg->request_size + EC_MAILBOX_DATA_EXTRA; | ||
109 | rq->command = msg->command; | ||
110 | |||
111 | /* Checksum header and data */ | ||
112 | rq->checksum = wilco_ec_checksum(rq, sizeof(*rq)); | ||
113 | rq->checksum += wilco_ec_checksum(msg->request_data, msg->request_size); | ||
114 | rq->checksum = -rq->checksum; | ||
115 | } | ||
116 | |||
117 | /** | ||
118 | * wilco_ec_transfer() - Perform actual data transfer. | ||
119 | * @ec: EC device. | ||
120 | * @msg: EC message data for request and response. | ||
121 | * @rq: Filled in request structure | ||
122 | * | ||
123 | * Context: ec->mailbox_lock should be held while using this function. | ||
124 | * Return: number of bytes received or negative error code on failure. | ||
125 | */ | ||
126 | static int wilco_ec_transfer(struct wilco_ec_device *ec, | ||
127 | struct wilco_ec_message *msg, | ||
128 | struct wilco_ec_request *rq) | ||
129 | { | ||
130 | struct wilco_ec_response *rs; | ||
131 | u8 checksum; | ||
132 | u8 flag; | ||
133 | size_t size; | ||
134 | |||
135 | /* Write request header, then data */ | ||
136 | cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, 0, sizeof(*rq), (u8 *)rq); | ||
137 | cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE, sizeof(*rq), msg->request_size, | ||
138 | msg->request_data); | ||
139 | |||
140 | /* Start the command */ | ||
141 | outb(EC_MAILBOX_START_COMMAND, ec->io_command->start); | ||
142 | |||
143 | /* For some commands (eg shutdown) the EC will not respond, that's OK */ | ||
144 | if (msg->flags & WILCO_EC_FLAG_NO_RESPONSE) { | ||
145 | dev_dbg(ec->dev, "EC does not respond to this command\n"); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | /* Wait for it to complete */ | ||
150 | if (wilco_ec_response_timed_out(ec)) { | ||
151 | dev_dbg(ec->dev, "response timed out\n"); | ||
152 | return -ETIMEDOUT; | ||
153 | } | ||
154 | |||
155 | /* Check result */ | ||
156 | flag = inb(ec->io_data->start); | ||
157 | if (flag) { | ||
158 | dev_dbg(ec->dev, "bad response: 0x%02x\n", flag); | ||
159 | return -EIO; | ||
160 | } | ||
161 | |||
162 | if (msg->flags & WILCO_EC_FLAG_EXTENDED_DATA) | ||
163 | size = EC_MAILBOX_DATA_SIZE_EXTENDED; | ||
164 | else | ||
165 | size = EC_MAILBOX_DATA_SIZE; | ||
166 | |||
167 | /* Read back response */ | ||
168 | rs = ec->data_buffer; | ||
169 | checksum = cros_ec_lpc_io_bytes_mec(MEC_IO_READ, 0, | ||
170 | sizeof(*rs) + size, (u8 *)rs); | ||
171 | if (checksum) { | ||
172 | dev_dbg(ec->dev, "bad packet checksum 0x%02x\n", rs->checksum); | ||
173 | return -EBADMSG; | ||
174 | } | ||
175 | |||
176 | /* Check that the EC reported success */ | ||
177 | msg->result = rs->result; | ||
178 | if (msg->result) { | ||
179 | dev_dbg(ec->dev, "bad response: 0x%02x\n", msg->result); | ||
180 | return -EBADMSG; | ||
181 | } | ||
182 | |||
183 | /* Check the returned data size, skipping the header */ | ||
184 | if (rs->data_size != size) { | ||
185 | dev_dbg(ec->dev, "unexpected packet size (%u != %zu)", | ||
186 | rs->data_size, size); | ||
187 | return -EMSGSIZE; | ||
188 | } | ||
189 | |||
190 | /* Skip 1 response data byte unless specified */ | ||
191 | size = (msg->flags & WILCO_EC_FLAG_RAW_RESPONSE) ? 0 : 1; | ||
192 | if ((ssize_t) rs->data_size - size < msg->response_size) { | ||
193 | dev_dbg(ec->dev, "response data too short (%zd < %zu)", | ||
194 | (ssize_t) rs->data_size - size, msg->response_size); | ||
195 | return -EMSGSIZE; | ||
196 | } | ||
197 | |||
198 | /* Ignore response data bytes as requested */ | ||
199 | memcpy(msg->response_data, rs->data + size, msg->response_size); | ||
200 | |||
201 | /* Return actual amount of data received */ | ||
202 | return msg->response_size; | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * wilco_ec_mailbox() - Send EC request and receive EC response. | ||
207 | * @ec: EC device. | ||
208 | * @msg: EC message data for request and response. | ||
209 | * | ||
210 | * On entry msg->type, msg->flags, msg->command, msg->request_size, | ||
211 | * msg->response_size, and msg->request_data should all be filled in. | ||
212 | * | ||
213 | * On exit msg->result and msg->response_data will be filled. | ||
214 | * | ||
215 | * Return: number of bytes received or negative error code on failure. | ||
216 | */ | ||
217 | int wilco_ec_mailbox(struct wilco_ec_device *ec, struct wilco_ec_message *msg) | ||
218 | { | ||
219 | struct wilco_ec_request *rq; | ||
220 | int ret; | ||
221 | |||
222 | dev_dbg(ec->dev, "cmd=%02x type=%04x flags=%02x rslen=%zu rqlen=%zu\n", | ||
223 | msg->command, msg->type, msg->flags, msg->response_size, | ||
224 | msg->request_size); | ||
225 | |||
226 | /* Prepare request packet */ | ||
227 | rq = ec->data_buffer; | ||
228 | wilco_ec_prepare(msg, rq); | ||
229 | |||
230 | mutex_lock(&ec->mailbox_lock); | ||
231 | ret = wilco_ec_transfer(ec, msg, rq); | ||
232 | mutex_unlock(&ec->mailbox_lock); | ||
233 | |||
234 | return ret; | ||
235 | |||
236 | } | ||
237 | EXPORT_SYMBOL_GPL(wilco_ec_mailbox); | ||
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index e1a1f2b1cbba..a71734c41693 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -1864,4 +1864,15 @@ config RTC_DRV_GOLDFISH | |||
1864 | Goldfish is a code name for the virtual platform developed by Google | 1864 | Goldfish is a code name for the virtual platform developed by Google |
1865 | for Android emulation. | 1865 | for Android emulation. |
1866 | 1866 | ||
1867 | config RTC_DRV_WILCO_EC | ||
1868 | tristate "Wilco EC RTC" | ||
1869 | depends on WILCO_EC | ||
1870 | default m | ||
1871 | help | ||
1872 | If you say yes here, you get read/write support for the Real Time | ||
1873 | Clock on the Wilco Embedded Controller (Wilco is a kind of Chromebook) | ||
1874 | |||
1875 | This can also be built as a module. If so, the module will | ||
1876 | be named "rtc_wilco_ec". | ||
1877 | |||
1867 | endif # RTC_CLASS | 1878 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 1bf9f75a7865..fe3962496685 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -177,6 +177,7 @@ obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o | |||
177 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o | 177 | obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o |
178 | obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o | 178 | obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o |
179 | obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o | 179 | obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o |
180 | obj-$(CONFIG_RTC_DRV_WILCO_EC) += rtc-wilco-ec.o | ||
180 | obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o | 181 | obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o |
181 | obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o | 182 | obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o |
182 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o | 183 | obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o |
diff --git a/drivers/rtc/rtc-wilco-ec.c b/drivers/rtc/rtc-wilco-ec.c new file mode 100644 index 000000000000..e62bda0cb53e --- /dev/null +++ b/drivers/rtc/rtc-wilco-ec.c | |||
@@ -0,0 +1,177 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * RTC interface for Wilco Embedded Controller with R/W abilities | ||
4 | * | ||
5 | * Copyright 2018 Google LLC | ||
6 | * | ||
7 | * The corresponding platform device is typically registered in | ||
8 | * drivers/platform/chrome/wilco_ec/core.c | ||
9 | */ | ||
10 | |||
11 | #include <linux/bcd.h> | ||
12 | #include <linux/err.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/platform_data/wilco-ec.h> | ||
17 | #include <linux/rtc.h> | ||
18 | #include <linux/timekeeping.h> | ||
19 | |||
20 | #define EC_COMMAND_CMOS 0x7c | ||
21 | #define EC_CMOS_TOD_WRITE 0x02 | ||
22 | #define EC_CMOS_TOD_READ 0x08 | ||
23 | |||
24 | /** | ||
25 | * struct ec_rtc_read - Format of RTC returned by EC. | ||
26 | * @second: Second value (0..59) | ||
27 | * @minute: Minute value (0..59) | ||
28 | * @hour: Hour value (0..23) | ||
29 | * @day: Day value (1..31) | ||
30 | * @month: Month value (1..12) | ||
31 | * @year: Year value (full year % 100) | ||
32 | * @century: Century value (full year / 100) | ||
33 | * | ||
34 | * All values are presented in binary (not BCD). | ||
35 | */ | ||
36 | struct ec_rtc_read { | ||
37 | u8 second; | ||
38 | u8 minute; | ||
39 | u8 hour; | ||
40 | u8 day; | ||
41 | u8 month; | ||
42 | u8 year; | ||
43 | u8 century; | ||
44 | } __packed; | ||
45 | |||
46 | /** | ||
47 | * struct ec_rtc_write - Format of RTC sent to the EC. | ||
48 | * @param: EC_CMOS_TOD_WRITE | ||
49 | * @century: Century value (full year / 100) | ||
50 | * @year: Year value (full year % 100) | ||
51 | * @month: Month value (1..12) | ||
52 | * @day: Day value (1..31) | ||
53 | * @hour: Hour value (0..23) | ||
54 | * @minute: Minute value (0..59) | ||
55 | * @second: Second value (0..59) | ||
56 | * @weekday: Day of the week (0=Saturday) | ||
57 | * | ||
58 | * All values are presented in BCD. | ||
59 | */ | ||
60 | struct ec_rtc_write { | ||
61 | u8 param; | ||
62 | u8 century; | ||
63 | u8 year; | ||
64 | u8 month; | ||
65 | u8 day; | ||
66 | u8 hour; | ||
67 | u8 minute; | ||
68 | u8 second; | ||
69 | u8 weekday; | ||
70 | } __packed; | ||
71 | |||
72 | static int wilco_ec_rtc_read(struct device *dev, struct rtc_time *tm) | ||
73 | { | ||
74 | struct wilco_ec_device *ec = dev_get_drvdata(dev->parent); | ||
75 | u8 param = EC_CMOS_TOD_READ; | ||
76 | struct ec_rtc_read rtc; | ||
77 | struct wilco_ec_message msg = { | ||
78 | .type = WILCO_EC_MSG_LEGACY, | ||
79 | .flags = WILCO_EC_FLAG_RAW_RESPONSE, | ||
80 | .command = EC_COMMAND_CMOS, | ||
81 | .request_data = ¶m, | ||
82 | .request_size = sizeof(param), | ||
83 | .response_data = &rtc, | ||
84 | .response_size = sizeof(rtc), | ||
85 | }; | ||
86 | int ret; | ||
87 | |||
88 | ret = wilco_ec_mailbox(ec, &msg); | ||
89 | if (ret < 0) | ||
90 | return ret; | ||
91 | |||
92 | tm->tm_sec = rtc.second; | ||
93 | tm->tm_min = rtc.minute; | ||
94 | tm->tm_hour = rtc.hour; | ||
95 | tm->tm_mday = rtc.day; | ||
96 | tm->tm_mon = rtc.month - 1; | ||
97 | tm->tm_year = rtc.year + (rtc.century * 100) - 1900; | ||
98 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); | ||
99 | |||
100 | /* Don't compute day of week, we don't need it. */ | ||
101 | tm->tm_wday = -1; | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static int wilco_ec_rtc_write(struct device *dev, struct rtc_time *tm) | ||
107 | { | ||
108 | struct wilco_ec_device *ec = dev_get_drvdata(dev->parent); | ||
109 | struct ec_rtc_write rtc; | ||
110 | struct wilco_ec_message msg = { | ||
111 | .type = WILCO_EC_MSG_LEGACY, | ||
112 | .flags = WILCO_EC_FLAG_RAW_RESPONSE, | ||
113 | .command = EC_COMMAND_CMOS, | ||
114 | .request_data = &rtc, | ||
115 | .request_size = sizeof(rtc), | ||
116 | }; | ||
117 | int year = tm->tm_year + 1900; | ||
118 | /* | ||
119 | * Convert from 0=Sunday to 0=Saturday for the EC | ||
120 | * We DO need to set weekday because the EC controls battery charging | ||
121 | * schedules that depend on the day of the week. | ||
122 | */ | ||
123 | int wday = tm->tm_wday == 6 ? 0 : tm->tm_wday + 1; | ||
124 | int ret; | ||
125 | |||
126 | rtc.param = EC_CMOS_TOD_WRITE; | ||
127 | rtc.century = bin2bcd(year / 100); | ||
128 | rtc.year = bin2bcd(year % 100); | ||
129 | rtc.month = bin2bcd(tm->tm_mon + 1); | ||
130 | rtc.day = bin2bcd(tm->tm_mday); | ||
131 | rtc.hour = bin2bcd(tm->tm_hour); | ||
132 | rtc.minute = bin2bcd(tm->tm_min); | ||
133 | rtc.second = bin2bcd(tm->tm_sec); | ||
134 | rtc.weekday = bin2bcd(wday); | ||
135 | |||
136 | ret = wilco_ec_mailbox(ec, &msg); | ||
137 | if (ret < 0) | ||
138 | return ret; | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static const struct rtc_class_ops wilco_ec_rtc_ops = { | ||
144 | .read_time = wilco_ec_rtc_read, | ||
145 | .set_time = wilco_ec_rtc_write, | ||
146 | }; | ||
147 | |||
148 | static int wilco_ec_rtc_probe(struct platform_device *pdev) | ||
149 | { | ||
150 | struct rtc_device *rtc; | ||
151 | |||
152 | rtc = devm_rtc_allocate_device(&pdev->dev); | ||
153 | if (IS_ERR(rtc)) | ||
154 | return PTR_ERR(rtc); | ||
155 | |||
156 | rtc->ops = &wilco_ec_rtc_ops; | ||
157 | /* EC only supports this century */ | ||
158 | rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; | ||
159 | rtc->range_max = RTC_TIMESTAMP_END_2099; | ||
160 | rtc->owner = THIS_MODULE; | ||
161 | |||
162 | return rtc_register_device(rtc); | ||
163 | } | ||
164 | |||
165 | static struct platform_driver wilco_ec_rtc_driver = { | ||
166 | .driver = { | ||
167 | .name = "rtc-wilco-ec", | ||
168 | }, | ||
169 | .probe = wilco_ec_rtc_probe, | ||
170 | }; | ||
171 | |||
172 | module_platform_driver(wilco_ec_rtc_driver); | ||
173 | |||
174 | MODULE_ALIAS("platform:rtc-wilco-ec"); | ||
175 | MODULE_AUTHOR("Nick Crews <ncrews@chromium.org>"); | ||
176 | MODULE_LICENSE("GPL v2"); | ||
177 | MODULE_DESCRIPTION("Wilco EC RTC driver"); | ||
diff --git a/include/linux/platform_data/wilco-ec.h b/include/linux/platform_data/wilco-ec.h new file mode 100644 index 000000000000..446473a46b88 --- /dev/null +++ b/include/linux/platform_data/wilco-ec.h | |||
@@ -0,0 +1,144 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * ChromeOS Wilco Embedded Controller | ||
4 | * | ||
5 | * Copyright 2018 Google LLC | ||
6 | */ | ||
7 | |||
8 | #ifndef WILCO_EC_H | ||
9 | #define WILCO_EC_H | ||
10 | |||
11 | #include <linux/device.h> | ||
12 | #include <linux/kernel.h> | ||
13 | |||
14 | /* Message flags for using the mailbox() interface */ | ||
15 | #define WILCO_EC_FLAG_NO_RESPONSE BIT(0) /* EC does not respond */ | ||
16 | #define WILCO_EC_FLAG_EXTENDED_DATA BIT(1) /* EC returns 256 data bytes */ | ||
17 | #define WILCO_EC_FLAG_RAW_REQUEST BIT(2) /* Do not trim request data */ | ||
18 | #define WILCO_EC_FLAG_RAW_RESPONSE BIT(3) /* Do not trim response data */ | ||
19 | #define WILCO_EC_FLAG_RAW (WILCO_EC_FLAG_RAW_REQUEST | \ | ||
20 | WILCO_EC_FLAG_RAW_RESPONSE) | ||
21 | |||
22 | /* Normal commands have a maximum 32 bytes of data */ | ||
23 | #define EC_MAILBOX_DATA_SIZE 32 | ||
24 | /* Extended commands have 256 bytes of response data */ | ||
25 | #define EC_MAILBOX_DATA_SIZE_EXTENDED 256 | ||
26 | |||
27 | /** | ||
28 | * struct wilco_ec_device - Wilco Embedded Controller handle. | ||
29 | * @dev: Device handle. | ||
30 | * @mailbox_lock: Mutex to ensure one mailbox command at a time. | ||
31 | * @io_command: I/O port for mailbox command. Provided by ACPI. | ||
32 | * @io_data: I/O port for mailbox data. Provided by ACPI. | ||
33 | * @io_packet: I/O port for mailbox packet data. Provided by ACPI. | ||
34 | * @data_buffer: Buffer used for EC communication. The same buffer | ||
35 | * is used to hold the request and the response. | ||
36 | * @data_size: Size of the data buffer used for EC communication. | ||
37 | * @debugfs_pdev: The child platform_device used by the debugfs sub-driver. | ||
38 | * @rtc_pdev: The child platform_device used by the RTC sub-driver. | ||
39 | */ | ||
40 | struct wilco_ec_device { | ||
41 | struct device *dev; | ||
42 | struct mutex mailbox_lock; | ||
43 | struct resource *io_command; | ||
44 | struct resource *io_data; | ||
45 | struct resource *io_packet; | ||
46 | void *data_buffer; | ||
47 | size_t data_size; | ||
48 | struct platform_device *debugfs_pdev; | ||
49 | struct platform_device *rtc_pdev; | ||
50 | }; | ||
51 | |||
52 | /** | ||
53 | * struct wilco_ec_request - Mailbox request message format. | ||
54 | * @struct_version: Should be %EC_MAILBOX_PROTO_VERSION | ||
55 | * @checksum: Sum of all bytes must be 0. | ||
56 | * @mailbox_id: Mailbox identifier, specifies the command set. | ||
57 | * @mailbox_version: Mailbox interface version %EC_MAILBOX_VERSION | ||
58 | * @reserved: Set to zero. | ||
59 | * @data_size: Length of request, data + last 2 bytes of the header. | ||
60 | * @command: Mailbox command code, unique for each mailbox_id set. | ||
61 | * @reserved_raw: Set to zero for most commands, but is used by | ||
62 | * some command types and for raw commands. | ||
63 | */ | ||
64 | struct wilco_ec_request { | ||
65 | u8 struct_version; | ||
66 | u8 checksum; | ||
67 | u16 mailbox_id; | ||
68 | u8 mailbox_version; | ||
69 | u8 reserved; | ||
70 | u16 data_size; | ||
71 | u8 command; | ||
72 | u8 reserved_raw; | ||
73 | } __packed; | ||
74 | |||
75 | /** | ||
76 | * struct wilco_ec_response - Mailbox response message format. | ||
77 | * @struct_version: Should be %EC_MAILBOX_PROTO_VERSION | ||
78 | * @checksum: Sum of all bytes must be 0. | ||
79 | * @result: Result code from the EC. Non-zero indicates an error. | ||
80 | * @data_size: Length of the response data buffer. | ||
81 | * @reserved: Set to zero. | ||
82 | * @mbox0: EC returned data at offset 0 is unused (always 0) so this byte | ||
83 | * is treated as part of the header instead of the data. | ||
84 | * @data: Response data buffer. Max size is %EC_MAILBOX_DATA_SIZE_EXTENDED. | ||
85 | */ | ||
86 | struct wilco_ec_response { | ||
87 | u8 struct_version; | ||
88 | u8 checksum; | ||
89 | u16 result; | ||
90 | u16 data_size; | ||
91 | u8 reserved[2]; | ||
92 | u8 mbox0; | ||
93 | u8 data[0]; | ||
94 | } __packed; | ||
95 | |||
96 | /** | ||
97 | * enum wilco_ec_msg_type - Message type to select a set of command codes. | ||
98 | * @WILCO_EC_MSG_LEGACY: Legacy EC messages for standard EC behavior. | ||
99 | * @WILCO_EC_MSG_PROPERTY: Get/Set/Sync EC controlled NVRAM property. | ||
100 | * @WILCO_EC_MSG_TELEMETRY_SHORT: 32 bytes of telemetry data provided by the EC. | ||
101 | * @WILCO_EC_MSG_TELEMETRY_LONG: 256 bytes of telemetry data provided by the EC. | ||
102 | */ | ||
103 | enum wilco_ec_msg_type { | ||
104 | WILCO_EC_MSG_LEGACY = 0x00f0, | ||
105 | WILCO_EC_MSG_PROPERTY = 0x00f2, | ||
106 | WILCO_EC_MSG_TELEMETRY_SHORT = 0x00f5, | ||
107 | WILCO_EC_MSG_TELEMETRY_LONG = 0x00f6, | ||
108 | }; | ||
109 | |||
110 | /** | ||
111 | * struct wilco_ec_message - Request and response message. | ||
112 | * @type: Mailbox message type. | ||
113 | * @flags: Message flags, e.g. %WILCO_EC_FLAG_NO_RESPONSE. | ||
114 | * @command: Mailbox command code. | ||
115 | * @result: Result code from the EC. Non-zero indicates an error. | ||
116 | * @request_size: Number of bytes to send to the EC. | ||
117 | * @request_data: Buffer containing the request data. | ||
118 | * @response_size: Number of bytes expected from the EC. | ||
119 | * This is 32 by default and 256 if the flag | ||
120 | * is set for %WILCO_EC_FLAG_EXTENDED_DATA | ||
121 | * @response_data: Buffer containing the response data, should be | ||
122 | * response_size bytes and allocated by caller. | ||
123 | */ | ||
124 | struct wilco_ec_message { | ||
125 | enum wilco_ec_msg_type type; | ||
126 | u8 flags; | ||
127 | u8 command; | ||
128 | u8 result; | ||
129 | size_t request_size; | ||
130 | void *request_data; | ||
131 | size_t response_size; | ||
132 | void *response_data; | ||
133 | }; | ||
134 | |||
135 | /** | ||
136 | * wilco_ec_mailbox() - Send request to the EC and receive the response. | ||
137 | * @ec: Wilco EC device. | ||
138 | * @msg: Wilco EC message. | ||
139 | * | ||
140 | * Return: Number of bytes received or negative error code on failure. | ||
141 | */ | ||
142 | int wilco_ec_mailbox(struct wilco_ec_device *ec, struct wilco_ec_message *msg); | ||
143 | |||
144 | #endif /* WILCO_EC_H */ | ||