summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-03-12 12:46:32 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-12 12:46:32 -0400
commitf47d633134f7033e3d0c667419d9f8afd69e308d (patch)
treea5242d86288599fda63ed79b2d131f5a298bb66f
parent004cc08675b761fd82288bab1b5ba5e1ca746eca (diff)
parent2794449576a6024e203eca5cc2c1a3ae33102b8e (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
-rw-r--r--Documentation/ABI/testing/debugfs-wilco-ec23
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/platform/chrome/Kconfig2
-rw-r--r--drivers/platform/chrome/Makefile2
-rw-r--r--drivers/platform/chrome/chromeos_pstore.c17
-rw-r--r--drivers/platform/chrome/cros_ec_debugfs.c22
-rw-r--r--drivers/platform/chrome/cros_ec_i2c.c22
-rw-r--r--drivers/platform/chrome/cros_ec_lightbar.c24
-rw-r--r--drivers/platform/chrome/cros_ec_lpc.c34
-rw-r--r--drivers/platform/chrome/cros_ec_lpc_mec.c78
-rw-r--r--drivers/platform/chrome/cros_ec_lpc_mec.h63
-rw-r--r--drivers/platform/chrome/cros_ec_lpc_reg.c73
-rw-r--r--drivers/platform/chrome/cros_ec_lpc_reg.h20
-rw-r--r--drivers/platform/chrome/cros_ec_proto.c19
-rw-r--r--drivers/platform/chrome/cros_ec_spi.c20
-rw-r--r--drivers/platform/chrome/cros_ec_sysfs.c26
-rw-r--r--drivers/platform/chrome/cros_ec_vbc.c24
-rw-r--r--drivers/platform/chrome/cros_kbd_led_backlight.c19
-rw-r--r--drivers/platform/chrome/wilco_ec/Kconfig20
-rw-r--r--drivers/platform/chrome/wilco_ec/Makefile6
-rw-r--r--drivers/platform/chrome/wilco_ec/core.c136
-rw-r--r--drivers/platform/chrome/wilco_ec/debugfs.c238
-rw-r--r--drivers/platform/chrome/wilco_ec/mailbox.c237
-rw-r--r--drivers/rtc/Kconfig11
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/rtc-wilco-ec.c177
-rw-r--r--include/linux/platform_data/wilco-ec.h144
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 @@
1What: /sys/kernel/debug/wilco_ec/raw
2Date: January 2019
3KernelVersion: 5.1
4Description:
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
3755M: Benson Leung <bleung@chromium.org> 3755M: Benson Leung <bleung@chromium.org>
3756M: Enric Balletbo i Serra <enric.balletbo@collabora.com> 3756M: Enric Balletbo i Serra <enric.balletbo@collabora.com>
3757S: Maintained 3757S: Maintained
3758T: git git://git.kernel.org/pub/scm/linux/kernel/git/bleung/chrome-platform.git 3758T: git git://git.kernel.org/pub/scm/linux/kernel/git/chrome-platform/linux.git
3759F: drivers/platform/chrome/ 3759F: drivers/platform/chrome/
3760 3760
3761CHROMEOS EC SUBDRIVERS 3761CHROMEOS 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
155source "drivers/platform/chrome/wilco_ec/Kconfig"
156
155endif # CHROMEOS_PLATFORMS 157endif # 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
14obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o 14obj-$(CONFIG_CROS_EC_VBC) += cros_ec_vbc.o
15obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o 15obj-$(CONFIG_CROS_EC_DEBUGFS) += cros_ec_debugfs.o
16obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o 16obj-$(CONFIG_CROS_EC_SYSFS) += cros_ec_sysfs.o
17
18obj-$(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)
138module_init(chromeos_pstore_init); 133module_init(chromeos_pstore_init);
139module_exit(chromeos_pstore_exit); 134module_exit(chromeos_pstore_exit);
140 135
141MODULE_DESCRIPTION("Chrome OS pstore module"); 136MODULE_DESCRIPTION("ChromeOS pstore module");
142MODULE_LICENSE("GPL"); 137MODULE_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
373module_i2c_driver(cros_ec_driver); 363module_i2c_driver(cros_ec_driver);
374 364
375MODULE_LICENSE("GPL"); 365MODULE_LICENSE("GPL v2");
376MODULE_DESCRIPTION("ChromeOS EC multi function device"); 366MODULE_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 */
36static struct mutex io_mutex; 17static struct mutex io_mutex;
18static 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;
46static void cros_ec_lpc_mec_emi_write_address(u16 addr, 28static 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 */
44int 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
124done: 138done:
@@ -128,9 +142,11 @@ done:
128} 142}
129EXPORT_SYMBOL(cros_ec_lpc_io_bytes_mec); 143EXPORT_SYMBOL(cros_ec_lpc_io_bytes_mec);
130 144
131void cros_ec_lpc_mec_init(void) 145void 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}
135EXPORT_SYMBOL(cros_ec_lpc_mec_init); 151EXPORT_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
29enum cros_ec_lpc_mec_emi_access_mode { 11enum 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 */
68void cros_ec_lpc_mec_init(void); 46void 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);
75void cros_ec_lpc_mec_destroy(void); 53void 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 */
64int 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
60u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, u8 *dest) 42u8 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
82u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, u8 *msg) 56u8 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
104void cros_ec_lpc_reg_init(void) 70void 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
109void cros_ec_lpc_reg_destroy(void) 76void 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 = {
729module_spi_driver(cros_ec_driver_spi); 719module_spi_driver(cros_ec_driver_spi);
730 720
731MODULE_LICENSE("GPL v2"); 721MODULE_LICENSE("GPL v2");
732MODULE_DESCRIPTION("ChromeOS EC multi function device (SPI)"); 722MODULE_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 = {
389module_platform_driver(cros_ec_sysfs_driver); 373module_platform_driver(cros_ec_sysfs_driver);
390 374
391MODULE_LICENSE("GPL"); 375MODULE_LICENSE("GPL");
392MODULE_DESCRIPTION("ChromeOS EC control driver"); 376MODULE_DESCRIPTION("Expose the ChromeOS EC through sysfs");
393MODULE_ALIAS("platform:" DRV_NAME); 377MODULE_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 @@
1config 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
12config 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
3wilco_ec-objs := core.o mailbox.o
4obj-$(CONFIG_WILCO_EC) += wilco_ec.o
5wilco_ec_debugfs-objs := debugfs.o
6obj-$(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
25static 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
41static 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
94unregister_debugfs:
95 if (ec->debugfs_pdev)
96 platform_device_unregister(ec->debugfs_pdev);
97 cros_ec_lpc_mec_destroy();
98 return ret;
99}
100
101static 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
115static const struct acpi_device_id wilco_ec_acpi_device_ids[] = {
116 { "GOOG000C", 0 },
117 { }
118};
119MODULE_DEVICE_TABLE(acpi, wilco_ec_acpi_device_ids);
120
121static 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
130module_platform_driver(wilco_ec_driver);
131
132MODULE_AUTHOR("Nick Crews <ncrews@chromium.org>");
133MODULE_AUTHOR("Duncan Laurie <dlaurie@chromium.org>");
134MODULE_LICENSE("GPL v2");
135MODULE_DESCRIPTION("ChromeOS Wilco Embedded Controller driver");
136MODULE_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
46struct 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};
53static 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 */
71static 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
119static 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
168static 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
186static 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 */
202static 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
218static int wilco_ec_debugfs_remove(struct platform_device *pdev)
219{
220 debugfs_remove_recursive(debug_info->dir);
221
222 return 0;
223}
224
225static 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
233module_platform_driver(wilco_ec_debugfs_driver);
234
235MODULE_ALIAS("platform:" DRV_NAME);
236MODULE_AUTHOR("Nick Crews <ncrews@chromium.org>");
237MODULE_LICENSE("GPL v2");
238MODULE_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 */
53static 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 */
74static 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 */
91static 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 */
126static 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 */
217int 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}
237EXPORT_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
1867config 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
1867endif # RTC_CLASS 1878endif # 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
177obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o 177obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
178obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o 178obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o
179obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o 179obj-$(CONFIG_RTC_DRV_VT8500) += rtc-vt8500.o
180obj-$(CONFIG_RTC_DRV_WILCO_EC) += rtc-wilco-ec.o
180obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o 181obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
181obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o 182obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
182obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o 183obj-$(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 */
36struct 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 */
60struct 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
72static 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 = &param,
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
106static 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
143static 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
148static 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
165static struct platform_driver wilco_ec_rtc_driver = {
166 .driver = {
167 .name = "rtc-wilco-ec",
168 },
169 .probe = wilco_ec_rtc_probe,
170};
171
172module_platform_driver(wilco_ec_rtc_driver);
173
174MODULE_ALIAS("platform:rtc-wilco-ec");
175MODULE_AUTHOR("Nick Crews <ncrews@chromium.org>");
176MODULE_LICENSE("GPL v2");
177MODULE_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 */
40struct 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 */
64struct 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 */
86struct 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 */
103enum 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 */
124struct 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 */
142int wilco_ec_mailbox(struct wilco_ec_device *ec, struct wilco_ec_message *msg);
143
144#endif /* WILCO_EC_H */