Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: cros_ec: Move protocol helpers out of the MFD driver

The MFD driver should only have the logic to instantiate its child devices
and setup any shared resources that will be used by the subdevices drivers.

The cros_ec MFD is more complex than expected since it also has helpers to
communicate with the EC. So the driver will only get more bigger as other
protocols are supported in the future. So move the communication protocol
helpers to its own driver as drivers/platform/chrome/cros_ec_proto.c.

Suggested-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
Tested-by: Heiko Stuebner <heiko@sntech.de>
Acked-by: Lee Jones <lee.jones@linaro.org>
Acked-by: Olof Johansson <olof@lixom.net>
Signed-off-by: Lee Jones <lee.jones@linaro.org>

authored by

Javier Martinez Canillas and committed by
Lee Jones
062476f2 256ab950

+129 -102
+1 -1
drivers/i2c/busses/Kconfig
··· 1103 1103 1104 1104 config I2C_CROS_EC_TUNNEL 1105 1105 tristate "ChromeOS EC tunnel I2C bus" 1106 - depends on MFD_CROS_EC 1106 + depends on CROS_EC_PROTO 1107 1107 help 1108 1108 If you say yes here you get an I2C bus that will tunnel i2c commands 1109 1109 through to the other side of the ChromeOS EC to the i2c bus
+1 -1
drivers/input/keyboard/Kconfig
··· 677 677 config KEYBOARD_CROS_EC 678 678 tristate "ChromeOS EC keyboard" 679 679 select INPUT_MATRIXKMAP 680 - depends on MFD_CROS_EC 680 + depends on CROS_EC_PROTO 681 681 help 682 682 Say Y here to enable the matrix keyboard used by ChromeOS devices 683 683 and implemented on the ChromeOS EC. You must enable one bus option
+4 -2
drivers/mfd/Kconfig
··· 94 94 config MFD_CROS_EC 95 95 tristate "ChromeOS Embedded Controller" 96 96 select MFD_CORE 97 + select CHROME_PLATFORMS 98 + select CROS_EC_PROTO 97 99 help 98 100 If you say Y here you get support for the ChromeOS Embedded 99 101 Controller (EC) providing keyboard, battery and power services. ··· 104 102 105 103 config MFD_CROS_EC_I2C 106 104 tristate "ChromeOS Embedded Controller (I2C)" 107 - depends on MFD_CROS_EC && I2C 105 + depends on MFD_CROS_EC && CROS_EC_PROTO && I2C 108 106 109 107 help 110 108 If you say Y here, you get support for talking to the ChromeOS ··· 114 112 115 113 config MFD_CROS_EC_SPI 116 114 tristate "ChromeOS Embedded Controller (SPI)" 117 - depends on MFD_CROS_EC && SPI && OF 115 + depends on MFD_CROS_EC && CROS_EC_PROTO && SPI && OF 118 116 119 117 ---help--- 120 118 If you say Y here, you get support for talking to the ChromeOS EC
-96
drivers/mfd/cros_ec.c
··· 23 23 #include <linux/module.h> 24 24 #include <linux/mfd/core.h> 25 25 #include <linux/mfd/cros_ec.h> 26 - #include <linux/mfd/cros_ec_commands.h> 27 - #include <linux/delay.h> 28 - 29 - #define EC_COMMAND_RETRIES 50 30 - 31 - int cros_ec_prepare_tx(struct cros_ec_device *ec_dev, 32 - struct cros_ec_command *msg) 33 - { 34 - uint8_t *out; 35 - int csum, i; 36 - 37 - BUG_ON(msg->outsize > EC_PROTO2_MAX_PARAM_SIZE); 38 - out = ec_dev->dout; 39 - out[0] = EC_CMD_VERSION0 + msg->version; 40 - out[1] = msg->command; 41 - out[2] = msg->outsize; 42 - csum = out[0] + out[1] + out[2]; 43 - for (i = 0; i < msg->outsize; i++) 44 - csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->data[i]; 45 - out[EC_MSG_TX_HEADER_BYTES + msg->outsize] = (uint8_t)(csum & 0xff); 46 - 47 - return EC_MSG_TX_PROTO_BYTES + msg->outsize; 48 - } 49 - EXPORT_SYMBOL(cros_ec_prepare_tx); 50 - 51 - int cros_ec_check_result(struct cros_ec_device *ec_dev, 52 - struct cros_ec_command *msg) 53 - { 54 - switch (msg->result) { 55 - case EC_RES_SUCCESS: 56 - return 0; 57 - case EC_RES_IN_PROGRESS: 58 - dev_dbg(ec_dev->dev, "command 0x%02x in progress\n", 59 - msg->command); 60 - return -EAGAIN; 61 - default: 62 - dev_dbg(ec_dev->dev, "command 0x%02x returned %d\n", 63 - msg->command, msg->result); 64 - return 0; 65 - } 66 - } 67 - EXPORT_SYMBOL(cros_ec_check_result); 68 - 69 - int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, 70 - struct cros_ec_command *msg) 71 - { 72 - int ret; 73 - 74 - mutex_lock(&ec_dev->lock); 75 - ret = ec_dev->cmd_xfer(ec_dev, msg); 76 - if (msg->result == EC_RES_IN_PROGRESS) { 77 - int i; 78 - struct cros_ec_command *status_msg; 79 - struct ec_response_get_comms_status *status; 80 - 81 - status_msg = kmalloc(sizeof(*status_msg) + sizeof(*status), 82 - GFP_KERNEL); 83 - if (!status_msg) { 84 - ret = -ENOMEM; 85 - goto exit; 86 - } 87 - 88 - status_msg->version = 0; 89 - status_msg->command = EC_CMD_GET_COMMS_STATUS; 90 - status_msg->insize = sizeof(*status); 91 - status_msg->outsize = 0; 92 - 93 - /* 94 - * Query the EC's status until it's no longer busy or 95 - * we encounter an error. 96 - */ 97 - for (i = 0; i < EC_COMMAND_RETRIES; i++) { 98 - usleep_range(10000, 11000); 99 - 100 - ret = ec_dev->cmd_xfer(ec_dev, status_msg); 101 - if (ret < 0) 102 - break; 103 - 104 - msg->result = status_msg->result; 105 - if (status_msg->result != EC_RES_SUCCESS) 106 - break; 107 - 108 - status = (struct ec_response_get_comms_status *) 109 - status_msg->data; 110 - if (!(status->flags & EC_COMMS_STATUS_PROCESSING)) 111 - break; 112 - } 113 - 114 - kfree(status_msg); 115 - } 116 - exit: 117 - mutex_unlock(&ec_dev->lock); 118 - 119 - return ret; 120 - } 121 - EXPORT_SYMBOL(cros_ec_cmd_xfer); 122 26 123 27 static const struct mfd_cell cros_devs[] = { 124 28 {
+7 -2
drivers/platform/chrome/Kconfig
··· 40 40 41 41 config CROS_EC_CHARDEV 42 42 tristate "Chrome OS Embedded Controller userspace device interface" 43 - depends on MFD_CROS_EC 43 + depends on CROS_EC_PROTO 44 44 ---help--- 45 45 This driver adds support to talk with the ChromeOS EC from userspace. 46 46 ··· 49 49 50 50 config CROS_EC_LPC 51 51 tristate "ChromeOS Embedded Controller (LPC)" 52 - depends on MFD_CROS_EC && (X86 || COMPILE_TEST) 52 + depends on MFD_CROS_EC && CROS_EC_PROTO && (X86 || COMPILE_TEST) 53 53 help 54 54 If you say Y here, you get support for talking to the ChromeOS EC 55 55 over an LPC bus. This uses a simple byte-level protocol with a ··· 58 58 59 59 To compile this driver as a module, choose M here: the 60 60 module will be called cros_ec_lpc. 61 + 62 + config CROS_EC_PROTO 63 + bool 64 + help 65 + ChromeOS EC communication protocol helpers. 61 66 62 67 endif # CHROMEOS_PLATFORMS
+1
drivers/platform/chrome/Makefile
··· 4 4 cros_ec_devs-objs := cros_ec_dev.o cros_ec_sysfs.o cros_ec_lightbar.o 5 5 obj-$(CONFIG_CROS_EC_CHARDEV) += cros_ec_devs.o 6 6 obj-$(CONFIG_CROS_EC_LPC) += cros_ec_lpc.o 7 + obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o
+115
drivers/platform/chrome/cros_ec_proto.c
··· 1 + /* 2 + * ChromeOS EC communication protocol helper functions 3 + * 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 + 17 + #include <linux/mfd/cros_ec.h> 18 + #include <linux/delay.h> 19 + #include <linux/device.h> 20 + #include <linux/module.h> 21 + #include <linux/slab.h> 22 + 23 + #define EC_COMMAND_RETRIES 50 24 + 25 + int cros_ec_prepare_tx(struct cros_ec_device *ec_dev, 26 + struct cros_ec_command *msg) 27 + { 28 + uint8_t *out; 29 + int csum, i; 30 + 31 + BUG_ON(msg->outsize > EC_PROTO2_MAX_PARAM_SIZE); 32 + out = ec_dev->dout; 33 + out[0] = EC_CMD_VERSION0 + msg->version; 34 + out[1] = msg->command; 35 + out[2] = msg->outsize; 36 + csum = out[0] + out[1] + out[2]; 37 + for (i = 0; i < msg->outsize; i++) 38 + csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->data[i]; 39 + out[EC_MSG_TX_HEADER_BYTES + msg->outsize] = (uint8_t)(csum & 0xff); 40 + 41 + return EC_MSG_TX_PROTO_BYTES + msg->outsize; 42 + } 43 + EXPORT_SYMBOL(cros_ec_prepare_tx); 44 + 45 + int cros_ec_check_result(struct cros_ec_device *ec_dev, 46 + struct cros_ec_command *msg) 47 + { 48 + switch (msg->result) { 49 + case EC_RES_SUCCESS: 50 + return 0; 51 + case EC_RES_IN_PROGRESS: 52 + dev_dbg(ec_dev->dev, "command 0x%02x in progress\n", 53 + msg->command); 54 + return -EAGAIN; 55 + default: 56 + dev_dbg(ec_dev->dev, "command 0x%02x returned %d\n", 57 + msg->command, msg->result); 58 + return 0; 59 + } 60 + } 61 + EXPORT_SYMBOL(cros_ec_check_result); 62 + 63 + int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, 64 + struct cros_ec_command *msg) 65 + { 66 + int ret; 67 + 68 + mutex_lock(&ec_dev->lock); 69 + ret = ec_dev->cmd_xfer(ec_dev, msg); 70 + if (msg->result == EC_RES_IN_PROGRESS) { 71 + int i; 72 + struct cros_ec_command *status_msg; 73 + struct ec_response_get_comms_status *status; 74 + 75 + status_msg = kmalloc(sizeof(*status_msg) + sizeof(*status), 76 + GFP_KERNEL); 77 + if (!status_msg) { 78 + ret = -ENOMEM; 79 + goto exit; 80 + } 81 + 82 + status_msg->version = 0; 83 + status_msg->command = EC_CMD_GET_COMMS_STATUS; 84 + status_msg->insize = sizeof(*status); 85 + status_msg->outsize = 0; 86 + 87 + /* 88 + * Query the EC's status until it's no longer busy or 89 + * we encounter an error. 90 + */ 91 + for (i = 0; i < EC_COMMAND_RETRIES; i++) { 92 + usleep_range(10000, 11000); 93 + 94 + ret = ec_dev->cmd_xfer(ec_dev, status_msg); 95 + if (ret < 0) 96 + break; 97 + 98 + msg->result = status_msg->result; 99 + if (status_msg->result != EC_RES_SUCCESS) 100 + break; 101 + 102 + status = (struct ec_response_get_comms_status *) 103 + status_msg->data; 104 + if (!(status->flags & EC_COMMS_STATUS_PROCESSING)) 105 + break; 106 + } 107 + 108 + kfree(status_msg); 109 + } 110 + exit: 111 + mutex_unlock(&ec_dev->lock); 112 + 113 + return ret; 114 + } 115 + EXPORT_SYMBOL(cros_ec_cmd_xfer);