Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753780AbdFVTCp (ORCPT ); Thu, 22 Jun 2017 15:02:45 -0400 Received: from mail-pf0-f170.google.com ([209.85.192.170]:36263 "EHLO mail-pf0-f170.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753492AbdFVTCn (ORCPT ); Thu, 22 Jun 2017 15:02:43 -0400 Date: Thu, 22 Jun 2017 12:02:37 -0700 From: Benson Leung To: Enric Balletbo i Serra Cc: olof@lixom.net, bleung@chromium.org, linux-kernel@vger.kernel.org, lee.jones@linaro.org, Shawn Nematbakhsh , Thierry Escande Subject: Re: [PATCH RESEND 05/13] platform/chrome: cros_ec_lpc: Add R/W helpers to LPC protocol variants Message-ID: <20170622190237.GB78452@decatoncale.mtv.corp.google.com> References: <20170516161319.13257-1-enric.balletbo@collabora.com> <20170516161319.13257-6-enric.balletbo@collabora.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="ZfOjI3PrQbgiZnxM" Content-Disposition: inline In-Reply-To: <20170516161319.13257-6-enric.balletbo@collabora.com> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 14642 Lines: 449 --ZfOjI3PrQbgiZnxM Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Tue, May 16, 2017 at 06:13:11PM +0200, Enric Balletbo i Serra wrote: > From: Shawn Nematbakhsh >=20 > Call common functions for read / write to prepare support for future > LPC protocol variants which use different I/O ops than inb / outb. >=20 > Signed-off-by: Shawn Nematbakhsh > Signed-off-by: Thierry Escande Signed-off-by: Benson Leung Applied to my upcoming immutable branch. > --- > drivers/platform/chrome/Makefile | 3 +- > drivers/platform/chrome/cros_ec_lpc.c | 88 +++++++++++++------------= ------ > drivers/platform/chrome/cros_ec_lpc_reg.c | 64 ++++++++++++++++++++++ > include/linux/mfd/cros_ec_lpc_reg.h | 47 +++++++++++++++++ > 4 files changed, 151 insertions(+), 51 deletions(-) > create mode 100644 drivers/platform/chrome/cros_ec_lpc_reg.c > create mode 100644 include/linux/mfd/cros_ec_lpc_reg.h >=20 > diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/M= akefile > index 3870afe..61182fd 100644 > --- a/drivers/platform/chrome/Makefile > +++ b/drivers/platform/chrome/Makefile > @@ -5,6 +5,7 @@ cros_ec_devs-objs :=3D cros_ec_dev.o cros_ec_sysfs.o \ > cros_ec_lightbar.o cros_ec_vbc.o \ > cros_ec_debugfs.o > obj-$(CONFIG_CROS_EC_CHARDEV) +=3D cros_ec_devs.o > -obj-$(CONFIG_CROS_EC_LPC) +=3D cros_ec_lpc.o > +cros_ec_lpcs-objs :=3D cros_ec_lpc.o cros_ec_lpc_reg.o > +obj-$(CONFIG_CROS_EC_LPC) +=3D cros_ec_lpcs.o > obj-$(CONFIG_CROS_EC_PROTO) +=3D cros_ec_proto.o > obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT) +=3D cros_kbd_led_backlight.o > diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chr= ome/cros_ec_lpc.c > index f9a2454..6a782a6 100644 > --- a/drivers/platform/chrome/cros_ec_lpc.c > +++ b/drivers/platform/chrome/cros_ec_lpc.c > @@ -26,19 +26,22 @@ > #include > #include > #include > +#include > #include > #include > #include > =20 > -#define DRV_NAME "cros_ec_lpc" > +#define DRV_NAME "cros_ec_lpcs" > =20 > static int ec_response_timed_out(void) > { > unsigned long one_second =3D jiffies + HZ; > + u8 data; > =20 > usleep_range(200, 300); > do { > - if (!(inb(EC_LPC_ADDR_HOST_CMD) & EC_LPC_STATUS_BUSY_MASK)) > + if (!(cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_CMD, 1, &data) & > + EC_LPC_STATUS_BUSY_MASK)) > return 0; > usleep_range(100, 200); > } while (time_before(jiffies, one_second)); > @@ -51,21 +54,20 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device= *ec, > { > struct ec_host_request *request; > struct ec_host_response response; > - u8 sum =3D 0; > - int i; > + u8 sum; > int ret =3D 0; > u8 *dout; > =20 > ret =3D cros_ec_prepare_tx(ec, msg); > =20 > /* Write buffer */ > - for (i =3D 0; i < ret; i++) > - outb(ec->dout[i], EC_LPC_ADDR_HOST_PACKET + i); > + cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout); > =20 > request =3D (struct ec_host_request *)ec->dout; > =20 > /* Here we go */ > - outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD); > + sum =3D EC_COMMAND_PROTOCOL_3; > + cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, &sum); > =20 > if (ec_response_timed_out()) { > dev_warn(ec->dev, "EC responsed timed out\n"); > @@ -74,17 +76,15 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device= *ec, > } > =20 > /* Check result */ > - msg->result =3D inb(EC_LPC_ADDR_HOST_DATA); > + msg->result =3D cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, &sum); > ret =3D cros_ec_check_result(ec, msg); > if (ret) > goto done; > =20 > /* Read back response */ > dout =3D (u8 *)&response; > - for (i =3D 0; i < sizeof(response); i++) { > - dout[i] =3D inb(EC_LPC_ADDR_HOST_PACKET + i); > - sum +=3D dout[i]; > - } > + sum =3D cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(response= ), > + dout); > =20 > msg->result =3D response.result; > =20 > @@ -97,11 +97,9 @@ static int cros_ec_pkt_xfer_lpc(struct cros_ec_device = *ec, > } > =20 > /* Read response and process checksum */ > - for (i =3D 0; i < response.data_len; i++) { > - msg->data[i] =3D > - inb(EC_LPC_ADDR_HOST_PACKET + sizeof(response) + i); > - sum +=3D msg->data[i]; > - } > + sum +=3D cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PACKET + > + sizeof(response), response.data_len, > + msg->data); > =20 > if (sum) { > dev_err(ec->dev, > @@ -121,8 +119,7 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_device= *ec, > struct cros_ec_command *msg) > { > struct ec_lpc_host_args args; > - int csum; > - int i; > + u8 sum; > int ret =3D 0; > =20 > if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE || > @@ -139,24 +136,20 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_devi= ce *ec, > args.data_size =3D msg->outsize; > =20 > /* Initialize checksum */ > - csum =3D msg->command + args.flags + > - args.command_version + args.data_size; > + sum =3D msg->command + args.flags + args.command_version + args.data_si= ze; > =20 > /* Copy data and update checksum */ > - for (i =3D 0; i < msg->outsize; i++) { > - outb(msg->data[i], EC_LPC_ADDR_HOST_PARAM + i); > - csum +=3D msg->data[i]; > - } > + sum +=3D cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_PARAM, msg->outsize, > + msg->data); > =20 > /* Finalize checksum and write args */ > - args.checksum =3D csum & 0xFF; > - outb(args.flags, EC_LPC_ADDR_HOST_ARGS); > - outb(args.command_version, EC_LPC_ADDR_HOST_ARGS + 1); > - outb(args.data_size, EC_LPC_ADDR_HOST_ARGS + 2); > - outb(args.checksum, EC_LPC_ADDR_HOST_ARGS + 3); > + args.checksum =3D sum; > + cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), > + (u8 *)&args); > =20 > /* Here we go */ > - outb(msg->command, EC_LPC_ADDR_HOST_CMD); > + sum =3D msg->command; > + cros_ec_lpc_write_bytes(EC_LPC_ADDR_HOST_CMD, 1, &sum); > =20 > if (ec_response_timed_out()) { > dev_warn(ec->dev, "EC responsed timed out\n"); > @@ -165,16 +158,14 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_devi= ce *ec, > } > =20 > /* Check result */ > - msg->result =3D inb(EC_LPC_ADDR_HOST_DATA); > + msg->result =3D cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_DATA, 1, &sum); > ret =3D cros_ec_check_result(ec, msg); > if (ret) > goto done; > =20 > /* Read back args */ > - args.flags =3D inb(EC_LPC_ADDR_HOST_ARGS); > - args.command_version =3D inb(EC_LPC_ADDR_HOST_ARGS + 1); > - args.data_size =3D inb(EC_LPC_ADDR_HOST_ARGS + 2); > - args.checksum =3D inb(EC_LPC_ADDR_HOST_ARGS + 3); > + cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), > + (u8 *)&args); > =20 > if (args.data_size > msg->insize) { > dev_err(ec->dev, > @@ -185,20 +176,17 @@ static int cros_ec_cmd_xfer_lpc(struct cros_ec_devi= ce *ec, > } > =20 > /* Start calculating response checksum */ > - csum =3D msg->command + args.flags + > - args.command_version + args.data_size; > + sum =3D msg->command + args.flags + args.command_version + args.data_si= ze; > =20 > /* Read response and update checksum */ > - for (i =3D 0; i < args.data_size; i++) { > - msg->data[i] =3D inb(EC_LPC_ADDR_HOST_PARAM + i); > - csum +=3D msg->data[i]; > - } > + sum +=3D cros_ec_lpc_read_bytes(EC_LPC_ADDR_HOST_PARAM, args.data_size, > + msg->data); > =20 > /* Verify checksum */ > - if (args.checksum !=3D (csum & 0xFF)) { > + if (args.checksum !=3D sum) { > dev_err(ec->dev, > "bad packet checksum, expected %02x, got %02x\n", > - args.checksum, csum & 0xFF); > + args.checksum, sum); > ret =3D -EBADMSG; > goto done; > } > @@ -222,14 +210,13 @@ static int cros_ec_lpc_readmem(struct cros_ec_devic= e *ec, unsigned int offset, > =20 > /* fixed length */ > if (bytes) { > - for (; cnt < bytes; i++, s++, cnt++) > - *s =3D inb(EC_LPC_ADDR_MEMMAP + i); > - return cnt; > + cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + offset, bytes, s); > + return bytes; > } > =20 > /* string */ > for (; i < EC_MEMMAP_SIZE; i++, s++) { > - *s =3D inb(EC_LPC_ADDR_MEMMAP + i); > + cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + i, 1, s); > cnt++; > if (!*s) > break; > @@ -242,6 +229,7 @@ static int cros_ec_lpc_probe(struct platform_device *= pdev) > { > struct device *dev =3D &pdev->dev; > struct cros_ec_device *ec_dev; > + u8 buf[2]; > int ret; > =20 > if (!devm_request_region(dev, EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE, > @@ -250,8 +238,8 @@ static int cros_ec_lpc_probe(struct platform_device *= pdev) > return -EBUSY; > } > =20 > - if ((inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID) !=3D 'E') || > - (inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1) !=3D 'C')) { > + cros_ec_lpc_read_bytes(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf); > + if (buf[0] !=3D 'E' || buf[1] !=3D 'C') { > dev_err(dev, "EC ID not detected\n"); > return -ENODEV; > } > diff --git a/drivers/platform/chrome/cros_ec_lpc_reg.c b/drivers/platform= /chrome/cros_ec_lpc_reg.c > new file mode 100644 > index 0000000..03c9781 > --- /dev/null > +++ b/drivers/platform/chrome/cros_ec_lpc_reg.c > @@ -0,0 +1,64 @@ > +/* > + * cros_ec_lpc_reg - LPC access to the Chrome OS Embedded Controller > + * > + * Copyright (C) 2016 Google, Inc > + * > + * This software is licensed under the terms of the GNU General Public > + * License version 2, as published by the Free Software Foundation, and > + * may be copied, distributed, and modified under those terms. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * This driver uses the Chrome OS EC byte-level message-based protocol f= or > + * communicating the keyboard state (which keys are pressed) from a keyb= oard EC > + * to the AP over some bus (such as i2c, lpc, spi). The EC does debounc= ing, > + * but everything else (including deghosting) is done here. The main > + * motivation for this is to keep the EC firmware as simple as possible,= since > + * it cannot be easily upgraded and EC flash/IRAM space is relatively > + * expensive. > + */ > + > +#include > +#include > +#include > + > +static u8 lpc_read_bytes(unsigned int offset, unsigned int length, u8 *d= est) > +{ > + int i; > + int sum =3D 0; > + > + for (i =3D 0; i < length; ++i) { > + dest[i] =3D inb(offset + i); > + sum +=3D dest[i]; > + } > + > + /* Return checksum of all bytes read */ > + return sum; > +} > + > +static u8 lpc_write_bytes(unsigned int offset, unsigned int length, u8 *= msg) > +{ > + int i; > + int sum =3D 0; > + > + for (i =3D 0; i < length; ++i) { > + outb(msg[i], offset + i); > + sum +=3D msg[i]; > + } > + > + /* Return checksum of all bytes written */ > + return sum; > +} > + > +u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, u8 *= dest) > +{ > + return lpc_read_bytes(offset, length, dest); > +} > + > +u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, u8 = *msg) > +{ > + return lpc_write_bytes(offset, length, msg); > +} > diff --git a/include/linux/mfd/cros_ec_lpc_reg.h b/include/linux/mfd/cros= _ec_lpc_reg.h > new file mode 100644 > index 0000000..4089bd5 > --- /dev/null > +++ b/include/linux/mfd/cros_ec_lpc_reg.h > @@ -0,0 +1,47 @@ > +/* > + * cros_ec_lpc_reg - LPC access to the Chrome OS Embedded Controller > + * > + * Copyright (C) 2016 Google, Inc > + * > + * This software is licensed under the terms of the GNU General Public > + * License version 2, as published by the Free Software Foundation, and > + * may be copied, distributed, and modified under those terms. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * This driver uses the Chrome OS EC byte-level message-based protocol f= or > + * communicating the keyboard state (which keys are pressed) from a keyb= oard EC > + * to the AP over some bus (such as i2c, lpc, spi). The EC does debounc= ing, > + * but everything else (including deghosting) is done here. The main > + * motivation for this is to keep the EC firmware as simple as possible,= since > + * it cannot be easily upgraded and EC flash/IRAM space is relatively > + * expensive. > + */ > + > +#ifndef __LINUX_MFD_CROS_EC_REG_H > +#define __LINUX_MFD_CROS_EC_REG_H > + > +/** > + * cros_ec_lpc_read_bytes - Read bytes from a given LPC-mapped address. > + * Returns 8-bit checksum of all bytes read. > + * > + * @offset: Base read address > + * @length: Number of bytes to read > + * @dest: Destination buffer > + */ > +u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length, u8 *= dest); > + > +/** > + * cros_ec_lpc_write_bytes - Write bytes to a given LPC-mapped address. > + * Returns 8-bit checksum of all bytes written. > + * > + * @offset: Base write address > + * @length: Number of bytes to write > + * @msg: Write data buffer > + */ > +u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length, u8 = *msg); > + > +#endif /* __LINUX_MFD_CROS_EC_REG_H */ > --=20 > 2.9.3 >=20 --=20 Benson Leung Staff Software Engineer Chrome OS Kernel Google Inc. bleung@google.com Chromium OS Project bleung@chromium.org --ZfOjI3PrQbgiZnxM Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAEBCgAGBQJZTBRNAAoJEB8J9XsKL+ZYxv8P/jK2YJiceGur0UFS0ptc45Ze JADhEHkIWv00FAPRCMg6KctqQf7lRbaJPvm1/ip7ULodjRswnQ70HTzzQ/49bLT5 n0OP+nzSdLbahwN19z0z5GF/h6s1Nzjyr77z6LbZgkaCMGjB6He+JuSETvYaZq44 SyLC14MSKg5gLWI2TNVTg9i4o3aQ29MmWQwcZZAJMUWlJmYY7GVLDnV9xWOaxiK7 FMKuhqy2F5XwdJYxKnZB9Vr1W/u5H1GQlJQZeMy3OOejSRR3yCL7k/x0EncFpWK1 MAdH0jkMhku8AO8UAesCtzXFXYDa/yGpJtjbSVx+ax75mL5xYeoqd9zKw6ur0+0D OTfYqVMrRs3OKzZl48Y/GgpjHYreSw/wF8JRol2vV+9wBniB2yvBglrZ704EX0Wt NIxFvbEtUqslIry7bITMLaJRspziNTBucsjXXewXww6hQYFVEqLfOWlwiCmwXjxl 8FwKgN28bc6K+pHCyGZMu3lqtd/lAixDB4/2tAzVrErapj4VcbiC16WO4AibCMrV 8tvyGCbtsXrGYjEgFZaOBMl0NqsqeJx+EKm7ap3agFd3mZbI2jvOvwmvY+d3e/MN yVVi64wM0PGpp+azQhLSPEhTzGAOSvO3Hk7Vk16lua1w0n2g7+BbX3qjJzgHkybm owClouB/hC8qzFenuVCW =Ckvf -----END PGP SIGNATURE----- --ZfOjI3PrQbgiZnxM--