From 203e0baedb984f1f206f853675cd169f9a646c72 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Mar 2018 15:31:28 -0700 Subject: platform/chrome: chromeos_laptop - add SPDX identifier Replace the original license statement with the SPDX identifier. Add also one line of description as recommended by the COPYING file. Signed-off-by: Dmitry Torokhov Signed-off-by: Benson Leung --- drivers/platform/chrome/chromeos_laptop.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index d8599736a41a..54a13c70e1d8 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -1,25 +1,8 @@ -/* - * chromeos_laptop.c - Driver to instantiate Chromebook i2c/smbus devices. - * - * Author : Benson Leung - * - * Copyright (C) 2012 Google, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ +// SPDX-License-Identifier: GPL-2.0+ +// Driver to instantiate Chromebook i2c/smbus devices. +// +// Copyright (C) 2012 Google, Inc. +// Author: Benson Leung #include #include -- cgit v1.2.3 From ed58f90c11696dee3a27fb56b00b507ad4cbad53 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Mar 2018 15:31:29 -0700 Subject: platform/chrome: chromeos_laptop - stop setting suspend mode for Atmel devices Atmel touch controller driver no longer respects suspend mode specified in platform data, so let's stop setting it. Signed-off-by: Dmitry Torokhov Signed-off-by: Benson Leung --- drivers/platform/chrome/chromeos_laptop.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 54a13c70e1d8..0a43f1833de3 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -100,7 +100,6 @@ static struct mxt_platform_data atmel_224s_tp_platform_data = { .irqflags = IRQF_TRIGGER_FALLING, .t19_num_keys = ARRAY_SIZE(mxt_t19_keys), .t19_keymap = mxt_t19_keys, - .suspend_mode = MXT_SUSPEND_T9_CTRL, }; static struct i2c_board_info atmel_224s_tp_device = { @@ -111,7 +110,6 @@ static struct i2c_board_info atmel_224s_tp_device = { static struct mxt_platform_data atmel_1664s_platform_data = { .irqflags = IRQF_TRIGGER_FALLING, - .suspend_mode = MXT_SUSPEND_T9_CTRL, }; static struct i2c_board_info atmel_1664s_device = { -- cgit v1.2.3 From 4f27f677c9541c02b7a62761f93bccbc404be8bb Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Mar 2018 15:31:30 -0700 Subject: platform/chrome: chromeos_laptop - introduce pr_fmt() Define pr_fmt() to standardize driver messages. Signed-off-by: Dmitry Torokhov Signed-off-by: Benson Leung --- drivers/platform/chrome/chromeos_laptop.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 0a43f1833de3..08ce7a105e76 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -4,6 +4,8 @@ // Copyright (C) 2012 Google, Inc. // Author: Benson Leung +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -139,15 +141,12 @@ static struct i2c_client *__add_probed_i2c_device( if (name) { dmi_dev = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD, name, NULL); if (!dmi_dev) { - pr_err("%s failed to dmi find device %s.\n", - __func__, - name); + pr_err("failed to dmi find device %s\n", name); return NULL; } dev_data = (struct dmi_dev_onboard *)dmi_dev->device_data; if (!dev_data) { - pr_err("%s failed to get data from dmi for %s.\n", - __func__, name); + pr_err("failed to get data from dmi for %s\n", name); return NULL; } info->irq = dev_data->instance; @@ -155,7 +154,7 @@ static struct i2c_client *__add_probed_i2c_device( adapter = i2c_get_adapter(bus); if (!adapter) { - pr_err("%s failed to get i2c adapter %d.\n", __func__, bus); + pr_err("failed to get i2c adapter %d\n", bus); return NULL; } @@ -174,19 +173,18 @@ static struct i2c_client *__add_probed_i2c_device( dummy = i2c_new_probed_device(adapter, &dummy_info, alt_addr_list, NULL); if (dummy) { - pr_debug("%s %d-%02x is probed at %02x\n", - __func__, bus, info->addr, dummy->addr); + pr_debug("%d-%02x is probed at %02x\n", + bus, info->addr, dummy->addr); i2c_unregister_device(dummy); client = i2c_new_device(adapter, info); } } if (!client) - pr_notice("%s failed to register device %d-%02x\n", - __func__, bus, info->addr); + pr_notice("failed to register device %d-%02x\n", + bus, info->addr); else - pr_debug("%s added i2c device %d-%02x\n", - __func__, bus, info->addr); + pr_debug("added i2c device %d-%02x\n", bus, info->addr); i2c_put_adapter(adapter); return client; @@ -227,7 +225,7 @@ static int find_i2c_adapter_num(enum i2c_adapter_type type) dev = bus_find_device(&i2c_bus_type, NULL, &lookup, __find_i2c_adap); if (!dev) { /* Adapters may appear later. Deferred probing will retry */ - pr_notice("%s: i2c adapter %s not found on system.\n", __func__, + pr_notice("i2c adapter %s not found on system.\n", lookup.name); return -ENODEV; } @@ -349,7 +347,7 @@ static int setup_tsl2563_als(enum i2c_adapter_type type) static int __init chromeos_laptop_dmi_matched(const struct dmi_system_id *id) { cros_laptop = (void *)id->driver_data; - pr_debug("DMI Matched %s.\n", id->ident); + pr_debug("DMI Matched %s\n", id->ident); /* Indicate to dmi_scan that processing is done. */ return 1; @@ -392,8 +390,7 @@ static int chromeos_laptop_probe(struct platform_device *pdev) ret = -EPROBE_DEFER; } else { /* Ran out of tries. */ - pr_notice("%s: Ran out of tries for device.\n", - __func__); + pr_notice("ran out of tries for device.\n"); i2c_dev->state = TIMEDOUT; } } else { @@ -600,7 +597,7 @@ static int __init chromeos_laptop_init(void) int ret; if (!dmi_check_system(chromeos_laptop_dmi_table)) { - pr_debug("%s unsupported system.\n", __func__); + pr_debug("unsupported system\n"); return -ENODEV; } -- cgit v1.2.3 From ab6c5600d8caf5ee9a8a5081344f055bc80bc271 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Mar 2018 15:31:31 -0700 Subject: platform/chrome: chromeos_laptop - factor out getting IRQ from DMI This will make code instantiating I2C device a bit clearer. Signed-off-by: Dmitry Torokhov Signed-off-by: Benson Leung --- drivers/platform/chrome/chromeos_laptop.c | 35 ++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 08ce7a105e76..96e962ff38e8 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -120,36 +120,47 @@ static struct i2c_board_info atmel_1664s_device = { .flags = I2C_CLIENT_WAKE, }; +static int chromeos_laptop_get_irq_from_dmi(const char *dmi_name) +{ + const struct dmi_device *dmi_dev; + const struct dmi_dev_onboard *dev_data; + + dmi_dev = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD, dmi_name, NULL); + if (!dmi_dev) { + pr_err("failed to find DMI device '%s'\n", dmi_name); + return -ENOENT; + } + + dev_data = dmi_dev->device_data; + if (!dev_data) { + pr_err("failed to get data from DMI for '%s'\n", dmi_name); + return -EINVAL; + } + + return dev_data->instance; +} + static struct i2c_client *__add_probed_i2c_device( const char *name, int bus, struct i2c_board_info *info, const unsigned short *alt_addr_list) { - const struct dmi_device *dmi_dev; - const struct dmi_dev_onboard *dev_data; struct i2c_adapter *adapter; struct i2c_client *client = NULL; const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END }; if (bus < 0) return NULL; + /* * If a name is specified, look for irq platform information stashed * in DMI_DEV_TYPE_DEV_ONBOARD by the Chrome OS custom system firmware. */ if (name) { - dmi_dev = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD, name, NULL); - if (!dmi_dev) { - pr_err("failed to dmi find device %s\n", name); - return NULL; - } - dev_data = (struct dmi_dev_onboard *)dmi_dev->device_data; - if (!dev_data) { - pr_err("failed to get data from dmi for %s\n", name); + info->irq = chromeos_laptop_get_irq_from_dmi(name); + if (info->irq < 0) return NULL; - } - info->irq = dev_data->instance; } adapter = i2c_get_adapter(bus); -- cgit v1.2.3 From 28cd38f105fc30ccda7a15170cbaa977d2601272 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Mar 2018 15:31:32 -0700 Subject: platform/chrome: chromeos_laptop - rework i2c peripherals initialization Instead of having separate setup() functions responsible for instantiating i2c client for each peripheral, let's generalize the behavior and use common code for instantiating all i2c peripherals. Signed-off-by: Dmitry Torokhov Signed-off-by: Benson Leung --- drivers/platform/chrome/chromeos_laptop.c | 467 +++++++++++++++--------------- 1 file changed, 235 insertions(+), 232 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 96e962ff38e8..2a81ae4c15c9 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -25,10 +25,6 @@ #define MAX_I2C_DEVICE_DEFERRALS 5 -static struct i2c_client *als; -static struct i2c_client *tp; -static struct i2c_client *ts; - static const char *i2c_adapter_names[] = { "SMBus I801 adapter", "i915 gmbus vga", @@ -50,12 +46,17 @@ enum i2c_peripheral_state { UNPROBED = 0, PROBED, TIMEDOUT, + FAILED, }; struct i2c_peripheral { - int (*add)(enum i2c_adapter_type type); + struct i2c_board_info board_info; + unsigned short alt_addr; + const char *dmi_name; enum i2c_adapter_type type; + enum i2c_peripheral_state state; + struct i2c_client *client; int tries; }; @@ -67,59 +68,6 @@ struct chromeos_laptop { static struct chromeos_laptop *cros_laptop; -static struct i2c_board_info cyapa_device = { - I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), - .flags = I2C_CLIENT_WAKE, -}; - -static struct i2c_board_info elantech_device = { - I2C_BOARD_INFO("elan_i2c", ELAN_TP_I2C_ADDR), - .flags = I2C_CLIENT_WAKE, -}; - -static struct i2c_board_info isl_als_device = { - I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), -}; - -static struct i2c_board_info tsl2583_als_device = { - I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR), -}; - -static struct i2c_board_info tsl2563_als_device = { - I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR), -}; - -static int mxt_t19_keys[] = { - KEY_RESERVED, - KEY_RESERVED, - KEY_RESERVED, - KEY_RESERVED, - KEY_RESERVED, - BTN_LEFT -}; - -static struct mxt_platform_data atmel_224s_tp_platform_data = { - .irqflags = IRQF_TRIGGER_FALLING, - .t19_num_keys = ARRAY_SIZE(mxt_t19_keys), - .t19_keymap = mxt_t19_keys, -}; - -static struct i2c_board_info atmel_224s_tp_device = { - I2C_BOARD_INFO("atmel_mxt_tp", ATMEL_TP_I2C_ADDR), - .platform_data = &atmel_224s_tp_platform_data, - .flags = I2C_CLIENT_WAKE, -}; - -static struct mxt_platform_data atmel_1664s_platform_data = { - .irqflags = IRQF_TRIGGER_FALLING, -}; - -static struct i2c_board_info atmel_1664s_device = { - I2C_BOARD_INFO("atmel_mxt_ts", ATMEL_TS_I2C_ADDR), - .platform_data = &atmel_1664s_platform_data, - .flags = I2C_CLIENT_WAKE, -}; - static int chromeos_laptop_get_irq_from_dmi(const char *dmi_name) { const struct dmi_device *dmi_dev; @@ -140,29 +88,15 @@ static int chromeos_laptop_get_irq_from_dmi(const char *dmi_name) return dev_data->instance; } -static struct i2c_client *__add_probed_i2c_device( - const char *name, - int bus, - struct i2c_board_info *info, - const unsigned short *alt_addr_list) +static struct i2c_client * +chromes_laptop_instantiate_i2c_device(int bus, + struct i2c_board_info *info, + unsigned short alt_addr) { struct i2c_adapter *adapter; struct i2c_client *client = NULL; const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END }; - if (bus < 0) - return NULL; - - /* - * If a name is specified, look for irq platform information stashed - * in DMI_DEV_TYPE_DEV_ONBOARD by the Chrome OS custom system firmware. - */ - if (name) { - info->irq = chromeos_laptop_get_irq_from_dmi(name); - if (info->irq < 0) - return NULL; - } - adapter = i2c_get_adapter(bus); if (!adapter) { pr_err("failed to get i2c adapter %d\n", bus); @@ -175,10 +109,13 @@ static struct i2c_client *__add_probed_i2c_device( * structure gets assigned primary address. */ client = i2c_new_probed_device(adapter, info, addr_list, NULL); - if (!client && alt_addr_list) { + if (!client && alt_addr) { struct i2c_board_info dummy_info = { I2C_BOARD_INFO("dummy", info->addr), }; + const unsigned short alt_addr_list[] = { + alt_addr, I2C_CLIENT_END + }; struct i2c_client *dummy; dummy = i2c_new_probed_device(adapter, &dummy_info, @@ -244,115 +181,53 @@ static int find_i2c_adapter_num(enum i2c_adapter_type type) return adapter->nr; } -/* - * Takes a list of addresses in addrs as such : - * { addr1, ... , addrn, I2C_CLIENT_END }; - * add_probed_i2c_device will use i2c_new_probed_device - * and probe for devices at all of the addresses listed. - * Returns NULL if no devices found. - * See Documentation/i2c/instantiating-devices for more information. - */ -static struct i2c_client *add_probed_i2c_device( - const char *name, - enum i2c_adapter_type type, - struct i2c_board_info *info, - const unsigned short *addrs) +static int chromeos_laptop_add_peripheral(struct i2c_peripheral *i2c_dev) { - return __add_probed_i2c_device(name, - find_i2c_adapter_num(type), - info, - addrs); -} + struct i2c_client *client; + int bus; + int irq; -/* - * Probes for a device at a single address, the one provided by - * info->addr. - * Returns NULL if no device found. - */ -static struct i2c_client *add_i2c_device(const char *name, - enum i2c_adapter_type type, - struct i2c_board_info *info) -{ - return __add_probed_i2c_device(name, - find_i2c_adapter_num(type), - info, - NULL); -} - -static int setup_cyapa_tp(enum i2c_adapter_type type) -{ - if (tp) - return 0; - - /* add cyapa touchpad */ - tp = add_i2c_device("trackpad", type, &cyapa_device); - return (!tp) ? -EAGAIN : 0; -} - -static int setup_atmel_224s_tp(enum i2c_adapter_type type) -{ - const unsigned short addr_list[] = { ATMEL_TP_I2C_BL_ADDR, - I2C_CLIENT_END }; - if (tp) - return 0; - - /* add atmel mxt touchpad */ - tp = add_probed_i2c_device("trackpad", type, - &atmel_224s_tp_device, addr_list); - return (!tp) ? -EAGAIN : 0; -} - -static int setup_elantech_tp(enum i2c_adapter_type type) -{ - if (tp) - return 0; - - /* add elantech touchpad */ - tp = add_i2c_device("trackpad", type, &elantech_device); - return (!tp) ? -EAGAIN : 0; -} - -static int setup_atmel_1664s_ts(enum i2c_adapter_type type) -{ - const unsigned short addr_list[] = { ATMEL_TS_I2C_BL_ADDR, - I2C_CLIENT_END }; - if (ts) - return 0; - - /* add atmel mxt touch device */ - ts = add_probed_i2c_device("touchscreen", type, - &atmel_1664s_device, addr_list); - return (!ts) ? -EAGAIN : 0; -} - -static int setup_isl29018_als(enum i2c_adapter_type type) -{ - if (als) - return 0; + /* + * Check that the i2c adapter is present. + * -EPROBE_DEFER if missing as the adapter may appear much + * later. + */ + bus = find_i2c_adapter_num(i2c_dev->type); + if (bus < 0) + return bus == -ENODEV ? -EPROBE_DEFER : bus; - /* add isl29018 light sensor */ - als = add_i2c_device("lightsensor", type, &isl_als_device); - return (!als) ? -EAGAIN : 0; -} + if (i2c_dev->dmi_name) { + irq = chromeos_laptop_get_irq_from_dmi(i2c_dev->dmi_name); + if (irq < 0) { + i2c_dev->state = FAILED; + return irq; + } -static int setup_tsl2583_als(enum i2c_adapter_type type) -{ - if (als) - return 0; + i2c_dev->board_info.irq = irq; + } - /* add tsl2583 light sensor */ - als = add_i2c_device(NULL, type, &tsl2583_als_device); - return (!als) ? -EAGAIN : 0; -} + client = chromes_laptop_instantiate_i2c_device(bus, + &i2c_dev->board_info, + i2c_dev->alt_addr); + if (!client) { + /* + * Set -EPROBE_DEFER a limited num of times + * if device is not successfully added. + */ + if (++i2c_dev->tries < MAX_I2C_DEVICE_DEFERRALS) { + return -EPROBE_DEFER; + } else { + /* Ran out of tries. */ + pr_notice("ran out of tries for device.\n"); + i2c_dev->state = TIMEDOUT; + return -EIO; + } + } -static int setup_tsl2563_als(enum i2c_adapter_type type) -{ - if (als) - return 0; + i2c_dev->client = client; + i2c_dev->state = PROBED; - /* add tsl2563 light sensor */ - als = add_i2c_device(NULL, type, &tsl2563_als_device); - return (!als) ? -EAGAIN : 0; + return 0; } static int __init chromeos_laptop_dmi_matched(const struct dmi_system_id *id) @@ -366,47 +241,22 @@ static int __init chromeos_laptop_dmi_matched(const struct dmi_system_id *id) static int chromeos_laptop_probe(struct platform_device *pdev) { + struct i2c_peripheral *i2c_dev; int i; int ret = 0; for (i = 0; i < MAX_I2C_PERIPHERALS; i++) { - struct i2c_peripheral *i2c_dev; - i2c_dev = &cros_laptop->i2c_peripherals[i]; /* No more peripherals. */ - if (i2c_dev->add == NULL) + if (!i2c_dev->board_info.addr) break; - if (i2c_dev->state == TIMEDOUT || i2c_dev->state == PROBED) + if (i2c_dev->state != UNPROBED) continue; - /* - * Check that the i2c adapter is present. - * -EPROBE_DEFER if missing as the adapter may appear much - * later. - */ - if (find_i2c_adapter_num(i2c_dev->type) == -ENODEV) { + if (chromeos_laptop_add_peripheral(i2c_dev) == -EPROBE_DEFER) ret = -EPROBE_DEFER; - continue; - } - - /* Add the device. */ - if (i2c_dev->add(i2c_dev->type) == -EAGAIN) { - /* - * Set -EPROBE_DEFER a limited num of times - * if device is not successfully added. - */ - if (++i2c_dev->tries < MAX_I2C_DEVICE_DEFERRALS) { - ret = -EPROBE_DEFER; - } else { - /* Ran out of tries. */ - pr_notice("ran out of tries for device.\n"); - i2c_dev->state = TIMEDOUT; - } - } else { - i2c_dev->state = PROBED; - } } return ret; @@ -415,91 +265,237 @@ static int chromeos_laptop_probe(struct platform_device *pdev) static struct chromeos_laptop samsung_series_5_550 = { .i2c_peripherals = { /* Touchpad. */ - { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, + { + .board_info = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, + }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_SMBUS, + }, /* Light Sensor. */ - { .add = setup_isl29018_als, I2C_ADAPTER_SMBUS }, + { + .board_info = { + I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), + }, + .dmi_name = "lightsensor", + .type = I2C_ADAPTER_SMBUS, + }, }, }; static struct chromeos_laptop samsung_series_5 = { .i2c_peripherals = { /* Light Sensor. */ - { .add = setup_tsl2583_als, I2C_ADAPTER_SMBUS }, + { + .board_info = { + I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR), + }, + .type = I2C_ADAPTER_SMBUS, + }, }, }; +static struct mxt_platform_data atmel_1664s_platform_data = { + .irqflags = IRQF_TRIGGER_FALLING, +}; + +static int chromebook_pixel_tp_keys[] = { + KEY_RESERVED, + KEY_RESERVED, + KEY_RESERVED, + KEY_RESERVED, + KEY_RESERVED, + BTN_LEFT +}; + +static struct mxt_platform_data chromebook_pixel_tp_platform_data = { + .irqflags = IRQF_TRIGGER_FALLING, + .t19_num_keys = ARRAY_SIZE(chromebook_pixel_tp_keys), + .t19_keymap = chromebook_pixel_tp_keys, +}; + static struct chromeos_laptop chromebook_pixel = { .i2c_peripherals = { /* Touch Screen. */ - { .add = setup_atmel_1664s_ts, I2C_ADAPTER_PANEL }, + { + .board_info = { + I2C_BOARD_INFO("atmel_mxt_ts", + ATMEL_TS_I2C_ADDR), + .platform_data = &atmel_1664s_platform_data, + .flags = I2C_CLIENT_WAKE, + }, + .dmi_name = "touchscreen", + .type = I2C_ADAPTER_PANEL, + .alt_addr = ATMEL_TS_I2C_BL_ADDR, + }, /* Touchpad. */ - { .add = setup_atmel_224s_tp, I2C_ADAPTER_VGADDC }, + { + .board_info = { + I2C_BOARD_INFO("atmel_mxt_tp", + ATMEL_TP_I2C_ADDR), + .platform_data = + &chromebook_pixel_tp_platform_data, + .flags = I2C_CLIENT_WAKE, + }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_VGADDC, + .alt_addr = ATMEL_TP_I2C_BL_ADDR, + }, /* Light Sensor. */ - { .add = setup_isl29018_als, I2C_ADAPTER_PANEL }, + { + .board_info = { + I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), + }, + .dmi_name = "lightsensor", + .type = I2C_ADAPTER_PANEL, + }, }, }; static struct chromeos_laptop hp_chromebook_14 = { .i2c_peripherals = { /* Touchpad. */ - { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 }, + { + .board_info = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, + }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_DESIGNWARE_0, + }, }, }; static struct chromeos_laptop dell_chromebook_11 = { .i2c_peripherals = { /* Touchpad. */ - { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 }, + { + .board_info = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, + }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_DESIGNWARE_0, + }, /* Elan Touchpad option. */ - { .add = setup_elantech_tp, I2C_ADAPTER_DESIGNWARE_0 }, + { + .board_info = { + I2C_BOARD_INFO("elan_i2c", ELAN_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, + }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_DESIGNWARE_0, + }, }, }; static struct chromeos_laptop toshiba_cb35 = { .i2c_peripherals = { /* Touchpad. */ - { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 }, + { + .board_info = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, + }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_DESIGNWARE_0, + }, }, }; static struct chromeos_laptop acer_c7_chromebook = { .i2c_peripherals = { /* Touchpad. */ - { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, + { + .board_info = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, + }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_SMBUS, + }, }, }; static struct chromeos_laptop acer_ac700 = { .i2c_peripherals = { /* Light Sensor. */ - { .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS }, + { + .board_info = { + I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR), + }, + .type = I2C_ADAPTER_SMBUS, + }, }, }; static struct chromeos_laptop acer_c720 = { .i2c_peripherals = { /* Touchscreen. */ - { .add = setup_atmel_1664s_ts, I2C_ADAPTER_DESIGNWARE_1 }, + { + .board_info = { + I2C_BOARD_INFO("atmel_mxt_ts", + ATMEL_TS_I2C_ADDR), + .platform_data = &atmel_1664s_platform_data, + .flags = I2C_CLIENT_WAKE, + }, + .dmi_name = "touchscreen", + .type = I2C_ADAPTER_DESIGNWARE_1, + .alt_addr = ATMEL_TS_I2C_BL_ADDR, + }, /* Touchpad. */ - { .add = setup_cyapa_tp, I2C_ADAPTER_DESIGNWARE_0 }, + { + .board_info = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, + }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_DESIGNWARE_0, + }, /* Elan Touchpad option. */ - { .add = setup_elantech_tp, I2C_ADAPTER_DESIGNWARE_0 }, + { + .board_info = { + I2C_BOARD_INFO("elan_i2c", ELAN_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, + }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_DESIGNWARE_0, + }, /* Light Sensor. */ - { .add = setup_isl29018_als, I2C_ADAPTER_DESIGNWARE_1 }, + { + .board_info = { + I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), + }, + .dmi_name = "lightsensor", + .type = I2C_ADAPTER_DESIGNWARE_1, + }, }, }; static struct chromeos_laptop hp_pavilion_14_chromebook = { .i2c_peripherals = { /* Touchpad. */ - { .add = setup_cyapa_tp, I2C_ADAPTER_SMBUS }, + { + .board_info = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, + }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_SMBUS, + }, }, }; static struct chromeos_laptop cr48 = { .i2c_peripherals = { /* Light Sensor. */ - { .add = setup_tsl2563_als, I2C_ADAPTER_SMBUS }, + { + .board_info = { + I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR), + }, + .type = I2C_ADAPTER_SMBUS, + }, }, }; @@ -637,15 +633,22 @@ fail_platform_device1: static void __exit chromeos_laptop_exit(void) { - if (als) - i2c_unregister_device(als); - if (tp) - i2c_unregister_device(tp); - if (ts) - i2c_unregister_device(ts); + struct i2c_peripheral *i2c_dev; + int i; platform_device_unregister(cros_platform_device); platform_driver_unregister(&cros_platform_driver); + + for (i = 0; i < MAX_I2C_PERIPHERALS; i++) { + i2c_dev = &cros_laptop->i2c_peripherals[i]; + + /* No more peripherals */ + if (!i2c_dev->board_info.type) + break; + + if (i2c_dev->state == PROBED) + i2c_unregister_device(i2c_dev->client); + } } module_init(chromeos_laptop_init); -- cgit v1.2.3 From 65582920d72d2562e44c07aa530586a3583477b9 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Mar 2018 15:31:33 -0700 Subject: platform/chrome: chromeos_laptop - parse DMI IRQ data once Instead of trying to parse DMI IRQ data every time we try to instantiate a device, let's do it once, when we identify the device we are working with. This allows us to mark chromeos_laptop_get_irq_from_dmi() as __init and discard it once module is initialized. Signed-off-by: Dmitry Torokhov Signed-off-by: Benson Leung --- drivers/platform/chrome/chromeos_laptop.c | 120 ++++++++++++++++-------------- 1 file changed, 64 insertions(+), 56 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 2a81ae4c15c9..d6d2bc6f3aaf 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -68,26 +68,6 @@ struct chromeos_laptop { static struct chromeos_laptop *cros_laptop; -static int chromeos_laptop_get_irq_from_dmi(const char *dmi_name) -{ - const struct dmi_device *dmi_dev; - const struct dmi_dev_onboard *dev_data; - - dmi_dev = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD, dmi_name, NULL); - if (!dmi_dev) { - pr_err("failed to find DMI device '%s'\n", dmi_name); - return -ENOENT; - } - - dev_data = dmi_dev->device_data; - if (!dev_data) { - pr_err("failed to get data from DMI for '%s'\n", dmi_name); - return -EINVAL; - } - - return dev_data->instance; -} - static struct i2c_client * chromes_laptop_instantiate_i2c_device(int bus, struct i2c_board_info *info, @@ -185,7 +165,6 @@ static int chromeos_laptop_add_peripheral(struct i2c_peripheral *i2c_dev) { struct i2c_client *client; int bus; - int irq; /* * Check that the i2c adapter is present. @@ -196,16 +175,6 @@ static int chromeos_laptop_add_peripheral(struct i2c_peripheral *i2c_dev) if (bus < 0) return bus == -ENODEV ? -EPROBE_DEFER : bus; - if (i2c_dev->dmi_name) { - irq = chromeos_laptop_get_irq_from_dmi(i2c_dev->dmi_name); - if (irq < 0) { - i2c_dev->state = FAILED; - return irq; - } - - i2c_dev->board_info.irq = irq; - } - client = chromes_laptop_instantiate_i2c_device(bus, &i2c_dev->board_info, i2c_dev->alt_addr); @@ -230,15 +199,6 @@ static int chromeos_laptop_add_peripheral(struct i2c_peripheral *i2c_dev) return 0; } -static int __init chromeos_laptop_dmi_matched(const struct dmi_system_id *id) -{ - cros_laptop = (void *)id->driver_data; - pr_debug("DMI Matched %s\n", id->ident); - - /* Indicate to dmi_scan that processing is done. */ - return 1; -} - static int chromeos_laptop_probe(struct platform_device *pdev) { struct i2c_peripheral *i2c_dev; @@ -499,10 +459,6 @@ static struct chromeos_laptop cr48 = { }, }; -#define _CBDD(board_) \ - .callback = chromeos_laptop_dmi_matched, \ - .driver_data = (void *)&board_ - static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = { { .ident = "Samsung Series 5 550", @@ -510,14 +466,14 @@ static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = { DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG"), DMI_MATCH(DMI_PRODUCT_NAME, "Lumpy"), }, - _CBDD(samsung_series_5_550), + .driver_data = (void *)&samsung_series_5_550, }, { .ident = "Samsung Series 5", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "Alex"), }, - _CBDD(samsung_series_5), + .driver_data = (void *)&samsung_series_5, }, { .ident = "Chromebook Pixel", @@ -525,7 +481,7 @@ static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = { DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), DMI_MATCH(DMI_PRODUCT_NAME, "Link"), }, - _CBDD(chromebook_pixel), + .driver_data = (void *)&chromebook_pixel, }, { .ident = "Wolf", @@ -533,7 +489,7 @@ static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = { DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"), DMI_MATCH(DMI_PRODUCT_NAME, "Wolf"), }, - _CBDD(dell_chromebook_11), + .driver_data = (void *)&dell_chromebook_11, }, { .ident = "HP Chromebook 14", @@ -541,7 +497,7 @@ static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = { DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"), DMI_MATCH(DMI_PRODUCT_NAME, "Falco"), }, - _CBDD(hp_chromebook_14), + .driver_data = (void *)&hp_chromebook_14, }, { .ident = "Toshiba CB35", @@ -549,42 +505,42 @@ static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = { DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"), DMI_MATCH(DMI_PRODUCT_NAME, "Leon"), }, - _CBDD(toshiba_cb35), + .driver_data = (void *)&toshiba_cb35, }, { .ident = "Acer C7 Chromebook", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "Parrot"), }, - _CBDD(acer_c7_chromebook), + .driver_data = (void *)&acer_c7_chromebook, }, { .ident = "Acer AC700", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), }, - _CBDD(acer_ac700), + .driver_data = (void *)&acer_ac700, }, { .ident = "Acer C720", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"), }, - _CBDD(acer_c720), + .driver_data = (void *)&acer_c720, }, { .ident = "HP Pavilion 14 Chromebook", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "Butterfly"), }, - _CBDD(hp_pavilion_14_chromebook), + .driver_data = (void *)&hp_pavilion_14_chromebook, }, { .ident = "Cr-48", .matches = { DMI_MATCH(DMI_PRODUCT_NAME, "Mario"), }, - _CBDD(cr48), + .driver_data = (void *)&cr48, }, { } }; @@ -599,15 +555,67 @@ static struct platform_driver cros_platform_driver = { .probe = chromeos_laptop_probe, }; +static int __init chromeos_laptop_get_irq_from_dmi(const char *dmi_name) +{ + const struct dmi_device *dmi_dev; + const struct dmi_dev_onboard *dev_data; + + dmi_dev = dmi_find_device(DMI_DEV_TYPE_DEV_ONBOARD, dmi_name, NULL); + if (!dmi_dev) { + pr_err("failed to find DMI device '%s'\n", dmi_name); + return -ENOENT; + } + + dev_data = dmi_dev->device_data; + if (!dev_data) { + pr_err("failed to get data from DMI for '%s'\n", dmi_name); + return -EINVAL; + } + + return dev_data->instance; +} + +static struct chromeos_laptop * __init +chromeos_laptop_prepare(const struct dmi_system_id *id) +{ + struct i2c_peripheral *i2c_dev; + int irq; + int i; + + cros_laptop = (void *)id->driver_data; + + for (i = 0; i < MAX_I2C_PERIPHERALS; i++) { + i2c_dev = &cros_laptop->i2c_peripherals[i]; + + if (!i2c_dev->dmi_name) + continue; + + irq = chromeos_laptop_get_irq_from_dmi(i2c_dev->dmi_name); + if (irq < 0) + return ERR_PTR(irq); + } + + return cros_laptop; +} + + static int __init chromeos_laptop_init(void) { + const struct dmi_system_id *dmi_id; int ret; - if (!dmi_check_system(chromeos_laptop_dmi_table)) { + dmi_id = dmi_first_match(chromeos_laptop_dmi_table); + if (!dmi_id) { pr_debug("unsupported system\n"); return -ENODEV; } + pr_debug("DMI Matched %s\n", dmi_id->ident); + + cros_laptop = chromeos_laptop_prepare(dmi_id->driver_data); + if (IS_ERR(cros_laptop)) + return PTR_ERR(cros_laptop); + ret = platform_driver_register(&cros_platform_driver); if (ret) return ret; -- cgit v1.2.3 From 8d88cb03c22e4cbde4c3020883f534e8ba7f5c79 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Mar 2018 15:31:34 -0700 Subject: platform/chrome: chromeos_laptop - use I2C notifier to create devices Instead of using platform device and deferrals to handle the case when i2C adapters appear late in the game, and not handling device unbinding all that well, let's switch to using I2C bus notifier to get told when a new I2C adapter appears in the system, and attempt to add appropriate devices at that time. In case when we have 2 Designware adapters in the system (Acer C720), instead of counting and hoping they get enumerate din the right order, let's switch to using their PCI devids (slot/function) that should be stable. Signed-off-by: Dmitry Torokhov Signed-off-by: Benson Leung --- drivers/platform/chrome/chromeos_laptop.c | 247 ++++++++++++------------------ 1 file changed, 102 insertions(+), 145 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index d6d2bc6f3aaf..e5015dfaa81e 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #define ATMEL_TP_I2C_ADDR 0x4b @@ -23,14 +24,11 @@ #define ISL_ALS_I2C_ADDR 0x44 #define TAOS_ALS_I2C_ADDR 0x29 -#define MAX_I2C_DEVICE_DEFERRALS 5 - static const char *i2c_adapter_names[] = { "SMBus I801 adapter", "i915 gmbus vga", "i915 gmbus panel", "Synopsys DesignWare I2C adapter", - "Synopsys DesignWare I2C adapter", }; /* Keep this enum consistent with i2c_adapter_names */ @@ -38,15 +36,7 @@ enum i2c_adapter_type { I2C_ADAPTER_SMBUS = 0, I2C_ADAPTER_VGADDC, I2C_ADAPTER_PANEL, - I2C_ADAPTER_DESIGNWARE_0, - I2C_ADAPTER_DESIGNWARE_1, -}; - -enum i2c_peripheral_state { - UNPROBED = 0, - PROBED, - TIMEDOUT, - FAILED, + I2C_ADAPTER_DESIGNWARE, }; struct i2c_peripheral { @@ -54,10 +44,9 @@ struct i2c_peripheral { unsigned short alt_addr; const char *dmi_name; enum i2c_adapter_type type; + u32 pci_devid; - enum i2c_peripheral_state state; struct i2c_client *client; - int tries; }; #define MAX_I2C_PERIPHERALS 4 @@ -69,19 +58,12 @@ struct chromeos_laptop { static struct chromeos_laptop *cros_laptop; static struct i2c_client * -chromes_laptop_instantiate_i2c_device(int bus, +chromes_laptop_instantiate_i2c_device(struct i2c_adapter *adapter, struct i2c_board_info *info, unsigned short alt_addr) { - struct i2c_adapter *adapter; - struct i2c_client *client = NULL; const unsigned short addr_list[] = { info->addr, I2C_CLIENT_END }; - - adapter = i2c_get_adapter(bus); - if (!adapter) { - pr_err("failed to get i2c adapter %d\n", bus); - return NULL; - } + struct i2c_client *client; /* * Add the i2c device. If we can't detect it at the primary @@ -102,126 +84,103 @@ chromes_laptop_instantiate_i2c_device(int bus, alt_addr_list, NULL); if (dummy) { pr_debug("%d-%02x is probed at %02x\n", - bus, info->addr, dummy->addr); + adapter->nr, info->addr, dummy->addr); i2c_unregister_device(dummy); client = i2c_new_device(adapter, info); } } if (!client) - pr_notice("failed to register device %d-%02x\n", - bus, info->addr); + pr_debug("failed to register device %d-%02x\n", + adapter->nr, info->addr); else - pr_debug("added i2c device %d-%02x\n", bus, info->addr); + pr_debug("added i2c device %d-%02x\n", + adapter->nr, info->addr); - i2c_put_adapter(adapter); return client; } -struct i2c_lookup { - const char *name; - int instance; - int n; -}; - -static int __find_i2c_adap(struct device *dev, void *data) +static bool chromeos_laptop_match_adapter_devid(struct device *dev, u32 devid) { - struct i2c_lookup *lookup = data; - static const char *prefix = "i2c-"; - struct i2c_adapter *adapter; + struct pci_dev *pdev; - if (strncmp(dev_name(dev), prefix, strlen(prefix)) != 0) - return 0; - adapter = to_i2c_adapter(dev); - if (strncmp(adapter->name, lookup->name, strlen(lookup->name)) == 0 && - lookup->n++ == lookup->instance) - return 1; - return 0; -} + if (!dev_is_pci(dev)) + return false; -static int find_i2c_adapter_num(enum i2c_adapter_type type) -{ - struct device *dev = NULL; - struct i2c_adapter *adapter; - struct i2c_lookup lookup; - - memset(&lookup, 0, sizeof(lookup)); - lookup.name = i2c_adapter_names[type]; - lookup.instance = (type == I2C_ADAPTER_DESIGNWARE_1) ? 1 : 0; - - /* find the adapter by name */ - dev = bus_find_device(&i2c_bus_type, NULL, &lookup, __find_i2c_adap); - if (!dev) { - /* Adapters may appear later. Deferred probing will retry */ - pr_notice("i2c adapter %s not found on system.\n", - lookup.name); - return -ENODEV; - } - adapter = to_i2c_adapter(dev); - return adapter->nr; + pdev = to_pci_dev(dev); + return devid == PCI_DEVID(pdev->bus->number, pdev->devfn); } -static int chromeos_laptop_add_peripheral(struct i2c_peripheral *i2c_dev) +static void chromeos_laptop_check_adapter(struct i2c_adapter *adapter) { - struct i2c_client *client; - int bus; + struct i2c_peripheral *i2c_dev; + int i; - /* - * Check that the i2c adapter is present. - * -EPROBE_DEFER if missing as the adapter may appear much - * later. - */ - bus = find_i2c_adapter_num(i2c_dev->type); - if (bus < 0) - return bus == -ENODEV ? -EPROBE_DEFER : bus; - - client = chromes_laptop_instantiate_i2c_device(bus, - &i2c_dev->board_info, - i2c_dev->alt_addr); - if (!client) { - /* - * Set -EPROBE_DEFER a limited num of times - * if device is not successfully added. - */ - if (++i2c_dev->tries < MAX_I2C_DEVICE_DEFERRALS) { - return -EPROBE_DEFER; - } else { - /* Ran out of tries. */ - pr_notice("ran out of tries for device.\n"); - i2c_dev->state = TIMEDOUT; - return -EIO; - } - } + for (i = 0; i < MAX_I2C_PERIPHERALS; i++) { + i2c_dev = &cros_laptop->i2c_peripherals[i]; - i2c_dev->client = client; - i2c_dev->state = PROBED; + /* No more peripherals */ + if (!i2c_dev->board_info.addr) + break; - return 0; + /* Skip devices already created */ + if (i2c_dev->client) + continue; + + if (strncmp(adapter->name, i2c_adapter_names[i2c_dev->type], + strlen(i2c_adapter_names[i2c_dev->type]))) + continue; + + if (i2c_dev->pci_devid && + !chromeos_laptop_match_adapter_devid(adapter->dev.parent, + i2c_dev->pci_devid)) { + continue; + } + + i2c_dev->client = + chromes_laptop_instantiate_i2c_device(adapter, + &i2c_dev->board_info, + i2c_dev->alt_addr); + } } -static int chromeos_laptop_probe(struct platform_device *pdev) +static void chromeos_laptop_detach_i2c_client(struct i2c_client *client) { struct i2c_peripheral *i2c_dev; int i; - int ret = 0; for (i = 0; i < MAX_I2C_PERIPHERALS; i++) { i2c_dev = &cros_laptop->i2c_peripherals[i]; - /* No more peripherals. */ - if (!i2c_dev->board_info.addr) - break; - - if (i2c_dev->state != UNPROBED) - continue; + if (i2c_dev->client == client) + i2c_dev->client = NULL; + } +} - if (chromeos_laptop_add_peripheral(i2c_dev) == -EPROBE_DEFER) - ret = -EPROBE_DEFER; +static int chromeos_laptop_i2c_notifier_call(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct device *dev = data; + + switch (action) { + case BUS_NOTIFY_ADD_DEVICE: + if (dev->type == &i2c_adapter_type) + chromeos_laptop_check_adapter(to_i2c_adapter(dev)); + break; + + case BUS_NOTIFY_REMOVED_DEVICE: + if (dev->type == &i2c_client_type) + chromeos_laptop_detach_i2c_client(to_i2c_client(dev)); + break; } - return ret; + return 0; } +static struct notifier_block chromeos_laptop_i2c_notifier = { + .notifier_call = chromeos_laptop_i2c_notifier_call, +}; + static struct chromeos_laptop samsung_series_5_550 = { .i2c_peripherals = { /* Touchpad. */ @@ -322,7 +281,7 @@ static struct chromeos_laptop hp_chromebook_14 = { .flags = I2C_CLIENT_WAKE, }, .dmi_name = "trackpad", - .type = I2C_ADAPTER_DESIGNWARE_0, + .type = I2C_ADAPTER_DESIGNWARE, }, }, }; @@ -336,7 +295,7 @@ static struct chromeos_laptop dell_chromebook_11 = { .flags = I2C_CLIENT_WAKE, }, .dmi_name = "trackpad", - .type = I2C_ADAPTER_DESIGNWARE_0, + .type = I2C_ADAPTER_DESIGNWARE, }, /* Elan Touchpad option. */ { @@ -345,7 +304,7 @@ static struct chromeos_laptop dell_chromebook_11 = { .flags = I2C_CLIENT_WAKE, }, .dmi_name = "trackpad", - .type = I2C_ADAPTER_DESIGNWARE_0, + .type = I2C_ADAPTER_DESIGNWARE, }, }, }; @@ -359,7 +318,7 @@ static struct chromeos_laptop toshiba_cb35 = { .flags = I2C_CLIENT_WAKE, }, .dmi_name = "trackpad", - .type = I2C_ADAPTER_DESIGNWARE_0, + .type = I2C_ADAPTER_DESIGNWARE, }, }, }; @@ -401,7 +360,8 @@ static struct chromeos_laptop acer_c720 = { .flags = I2C_CLIENT_WAKE, }, .dmi_name = "touchscreen", - .type = I2C_ADAPTER_DESIGNWARE_1, + .type = I2C_ADAPTER_DESIGNWARE, + .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)), .alt_addr = ATMEL_TS_I2C_BL_ADDR, }, /* Touchpad. */ @@ -411,7 +371,8 @@ static struct chromeos_laptop acer_c720 = { .flags = I2C_CLIENT_WAKE, }, .dmi_name = "trackpad", - .type = I2C_ADAPTER_DESIGNWARE_0, + .type = I2C_ADAPTER_DESIGNWARE, + .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x1)), }, /* Elan Touchpad option. */ { @@ -420,7 +381,8 @@ static struct chromeos_laptop acer_c720 = { .flags = I2C_CLIENT_WAKE, }, .dmi_name = "trackpad", - .type = I2C_ADAPTER_DESIGNWARE_0, + .type = I2C_ADAPTER_DESIGNWARE, + .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x1)), }, /* Light Sensor. */ { @@ -428,7 +390,8 @@ static struct chromeos_laptop acer_c720 = { I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), }, .dmi_name = "lightsensor", - .type = I2C_ADAPTER_DESIGNWARE_1, + .type = I2C_ADAPTER_DESIGNWARE, + .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)), }, }, }; @@ -546,14 +509,16 @@ static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = { }; MODULE_DEVICE_TABLE(dmi, chromeos_laptop_dmi_table); -static struct platform_device *cros_platform_device; +static int __init chromeos_laptop_scan_adapter(struct device *dev, void *data) +{ + struct i2c_adapter *adapter; -static struct platform_driver cros_platform_driver = { - .driver = { - .name = "chromeos_laptop", - }, - .probe = chromeos_laptop_probe, -}; + adapter = i2c_verify_adapter(dev); + if (adapter) + chromeos_laptop_check_adapter(adapter); + + return 0; +} static int __init chromeos_laptop_get_irq_from_dmi(const char *dmi_name) { @@ -602,7 +567,7 @@ chromeos_laptop_prepare(const struct dmi_system_id *id) static int __init chromeos_laptop_init(void) { const struct dmi_system_id *dmi_id; - int ret; + int error; dmi_id = dmi_first_match(chromeos_laptop_dmi_table); if (!dmi_id) { @@ -616,27 +581,20 @@ static int __init chromeos_laptop_init(void) if (IS_ERR(cros_laptop)) return PTR_ERR(cros_laptop); - ret = platform_driver_register(&cros_platform_driver); - if (ret) - return ret; - - cros_platform_device = platform_device_alloc("chromeos_laptop", -1); - if (!cros_platform_device) { - ret = -ENOMEM; - goto fail_platform_device1; + error = bus_register_notifier(&i2c_bus_type, + &chromeos_laptop_i2c_notifier); + if (error) { + pr_err("failed to register i2c bus notifier: %d\n", error); + return error; } - ret = platform_device_add(cros_platform_device); - if (ret) - goto fail_platform_device2; + /* + * Scan adapters that have been registered before we installed + * the notifier to make sure we do not miss any devices. + */ + i2c_for_each_dev(NULL, chromeos_laptop_scan_adapter); return 0; - -fail_platform_device2: - platform_device_put(cros_platform_device); -fail_platform_device1: - platform_driver_unregister(&cros_platform_driver); - return ret; } static void __exit chromeos_laptop_exit(void) @@ -644,8 +602,7 @@ static void __exit chromeos_laptop_exit(void) struct i2c_peripheral *i2c_dev; int i; - platform_device_unregister(cros_platform_device); - platform_driver_unregister(&cros_platform_driver); + bus_unregister_notifier(&i2c_bus_type, &chromeos_laptop_i2c_notifier); for (i = 0; i < MAX_I2C_PERIPHERALS; i++) { i2c_dev = &cros_laptop->i2c_peripherals[i]; @@ -654,7 +611,7 @@ static void __exit chromeos_laptop_exit(void) if (!i2c_dev->board_info.type) break; - if (i2c_dev->state == PROBED) + if (i2c_dev->client) i2c_unregister_device(i2c_dev->client); } } -- cgit v1.2.3 From e6215eeaa23c5d80a72caa91fc80795b9cde038f Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Mar 2018 15:31:35 -0700 Subject: platform/chrome: chromeos_laptop - rely on I2C to set up interrupt trigger Instead of passing interrupt flags via platform data to drivers, or hoping that drivers will do the right thing and set it up the way we need, let's set up IRQ resource and attach it to the I2C board info, and let I2C core set it up for us. Signed-off-by: Dmitry Torokhov Signed-off-by: Benson Leung --- drivers/platform/chrome/chromeos_laptop.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index e5015dfaa81e..1191c1a3a0cd 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -42,7 +43,11 @@ enum i2c_adapter_type { struct i2c_peripheral { struct i2c_board_info board_info; unsigned short alt_addr; + const char *dmi_name; + unsigned long irqflags; + struct resource irq_resource; + enum i2c_adapter_type type; u32 pci_devid; @@ -215,10 +220,6 @@ static struct chromeos_laptop samsung_series_5 = { }, }; -static struct mxt_platform_data atmel_1664s_platform_data = { - .irqflags = IRQF_TRIGGER_FALLING, -}; - static int chromebook_pixel_tp_keys[] = { KEY_RESERVED, KEY_RESERVED, @@ -229,7 +230,6 @@ static int chromebook_pixel_tp_keys[] = { }; static struct mxt_platform_data chromebook_pixel_tp_platform_data = { - .irqflags = IRQF_TRIGGER_FALLING, .t19_num_keys = ARRAY_SIZE(chromebook_pixel_tp_keys), .t19_keymap = chromebook_pixel_tp_keys, }; @@ -241,10 +241,10 @@ static struct chromeos_laptop chromebook_pixel = { .board_info = { I2C_BOARD_INFO("atmel_mxt_ts", ATMEL_TS_I2C_ADDR), - .platform_data = &atmel_1664s_platform_data, .flags = I2C_CLIENT_WAKE, }, .dmi_name = "touchscreen", + .irqflags = IRQF_TRIGGER_FALLING, .type = I2C_ADAPTER_PANEL, .alt_addr = ATMEL_TS_I2C_BL_ADDR, }, @@ -258,6 +258,7 @@ static struct chromeos_laptop chromebook_pixel = { .flags = I2C_CLIENT_WAKE, }, .dmi_name = "trackpad", + .irqflags = IRQF_TRIGGER_FALLING, .type = I2C_ADAPTER_VGADDC, .alt_addr = ATMEL_TP_I2C_BL_ADDR, }, @@ -356,10 +357,10 @@ static struct chromeos_laptop acer_c720 = { .board_info = { I2C_BOARD_INFO("atmel_mxt_ts", ATMEL_TS_I2C_ADDR), - .platform_data = &atmel_1664s_platform_data, .flags = I2C_CLIENT_WAKE, }, .dmi_name = "touchscreen", + .irqflags = IRQF_TRIGGER_FALLING, .type = I2C_ADAPTER_DESIGNWARE, .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)), .alt_addr = ATMEL_TS_I2C_BL_ADDR, @@ -558,6 +559,12 @@ chromeos_laptop_prepare(const struct dmi_system_id *id) irq = chromeos_laptop_get_irq_from_dmi(i2c_dev->dmi_name); if (irq < 0) return ERR_PTR(irq); + + i2c_dev->irq_resource = (struct resource) + DEFINE_RES_NAMED(irq, 1, NULL, + IORESOURCE_IRQ | i2c_dev->irqflags); + i2c_dev->board_info.resources = &i2c_dev->irq_resource; + i2c_dev->board_info.num_resources = 1; } return cros_laptop; -- cgit v1.2.3 From f00c1d199e05f4f633a3ae34f16f707257d56fcf Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Mar 2018 15:31:36 -0700 Subject: platform/chrome: chromeos_laptop - use device properties for Pixel Now that Atmel driver uses generic device properties we can use them instead of platform data when setting up touchpad on the original Google Pixel. Signed-off-by: Dmitry Torokhov Signed-off-by: Benson Leung --- drivers/platform/chrome/chromeos_laptop.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index 1191c1a3a0cd..fe83a2a4900e 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -8,13 +8,13 @@ #include #include -#include #include #include #include #include #include #include +#include #define ATMEL_TP_I2C_ADDR 0x4b #define ATMEL_TP_I2C_BL_ADDR 0x25 @@ -229,9 +229,9 @@ static int chromebook_pixel_tp_keys[] = { BTN_LEFT }; -static struct mxt_platform_data chromebook_pixel_tp_platform_data = { - .t19_num_keys = ARRAY_SIZE(chromebook_pixel_tp_keys), - .t19_keymap = chromebook_pixel_tp_keys, +static const struct property_entry chromebook_pixel_trackpad_props[] = { + PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", chromebook_pixel_tp_keys), + { } }; static struct chromeos_laptop chromebook_pixel = { @@ -253,8 +253,8 @@ static struct chromeos_laptop chromebook_pixel = { .board_info = { I2C_BOARD_INFO("atmel_mxt_tp", ATMEL_TP_I2C_ADDR), - .platform_data = - &chromebook_pixel_tp_platform_data, + .properties = + chromebook_pixel_trackpad_props, .flags = I2C_CLIENT_WAKE, }, .dmi_name = "trackpad", -- cgit v1.2.3 From c0bb0608ec79f8480432e169ccc3857dc7f7c205 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Tue, 20 Mar 2018 15:31:37 -0700 Subject: platform/chrome: chromeos_laptop - discard data for unneeded boards Mark board data as __intconst/__initdata and make a copy of appropriate entry once we identified the board we are running on. The rest of the data will be discarded once the kernel finished booting (or module finished loading). Signed-off-by: Dmitry Torokhov Signed-off-by: Benson Leung --- drivers/platform/chrome/chromeos_laptop.c | 476 +++++++++++++++++------------- 1 file changed, 264 insertions(+), 212 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/chromeos_laptop.c b/drivers/platform/chrome/chromeos_laptop.c index fe83a2a4900e..5c47f451e43b 100644 --- a/drivers/platform/chrome/chromeos_laptop.c +++ b/drivers/platform/chrome/chromeos_laptop.c @@ -54,13 +54,16 @@ struct i2c_peripheral { struct i2c_client *client; }; -#define MAX_I2C_PERIPHERALS 4 - struct chromeos_laptop { - struct i2c_peripheral i2c_peripherals[MAX_I2C_PERIPHERALS]; + /* + * Note that we can't mark this pointer as const because + * i2c_new_probed_device() changes passed in I2C board info, so. + */ + struct i2c_peripheral *i2c_peripherals; + unsigned int num_i2c_peripherals; }; -static struct chromeos_laptop *cros_laptop; +static const struct chromeos_laptop *cros_laptop; static struct i2c_client * chromes_laptop_instantiate_i2c_device(struct i2c_adapter *adapter, @@ -121,13 +124,9 @@ static void chromeos_laptop_check_adapter(struct i2c_adapter *adapter) struct i2c_peripheral *i2c_dev; int i; - for (i = 0; i < MAX_I2C_PERIPHERALS; i++) { + for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) { i2c_dev = &cros_laptop->i2c_peripherals[i]; - /* No more peripherals */ - if (!i2c_dev->board_info.addr) - break; - /* Skip devices already created */ if (i2c_dev->client) continue; @@ -154,7 +153,7 @@ static void chromeos_laptop_detach_i2c_client(struct i2c_client *client) struct i2c_peripheral *i2c_dev; int i; - for (i = 0; i < MAX_I2C_PERIPHERALS; i++) { + for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) { i2c_dev = &cros_laptop->i2c_peripherals[i]; if (i2c_dev->client == client) @@ -186,41 +185,45 @@ static struct notifier_block chromeos_laptop_i2c_notifier = { .notifier_call = chromeos_laptop_i2c_notifier_call, }; -static struct chromeos_laptop samsung_series_5_550 = { - .i2c_peripherals = { - /* Touchpad. */ - { - .board_info = { - I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), - .flags = I2C_CLIENT_WAKE, - }, - .dmi_name = "trackpad", - .type = I2C_ADAPTER_SMBUS, +#define DECLARE_CROS_LAPTOP(_name) \ +static const struct chromeos_laptop _name __initconst = { \ + .i2c_peripherals = _name##_peripherals, \ + .num_i2c_peripherals = ARRAY_SIZE(_name##_peripherals), \ +} + +static struct i2c_peripheral samsung_series_5_550_peripherals[] __initdata = { + /* Touchpad. */ + { + .board_info = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, }, - /* Light Sensor. */ - { - .board_info = { - I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), - }, - .dmi_name = "lightsensor", - .type = I2C_ADAPTER_SMBUS, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_SMBUS, + }, + /* Light Sensor. */ + { + .board_info = { + I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), }, + .dmi_name = "lightsensor", + .type = I2C_ADAPTER_SMBUS, }, }; +DECLARE_CROS_LAPTOP(samsung_series_5_550); -static struct chromeos_laptop samsung_series_5 = { - .i2c_peripherals = { - /* Light Sensor. */ - { - .board_info = { - I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR), - }, - .type = I2C_ADAPTER_SMBUS, +static struct i2c_peripheral samsung_series_5_peripherals[] __initdata = { + /* Light Sensor. */ + { + .board_info = { + I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR), }, + .type = I2C_ADAPTER_SMBUS, }, }; +DECLARE_CROS_LAPTOP(samsung_series_5); -static int chromebook_pixel_tp_keys[] = { +static const int chromebook_pixel_tp_keys[] __initconst = { KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, @@ -229,199 +232,192 @@ static int chromebook_pixel_tp_keys[] = { BTN_LEFT }; -static const struct property_entry chromebook_pixel_trackpad_props[] = { +static const struct property_entry +chromebook_pixel_trackpad_props[] __initconst = { PROPERTY_ENTRY_U32_ARRAY("linux,gpio-keymap", chromebook_pixel_tp_keys), { } }; -static struct chromeos_laptop chromebook_pixel = { - .i2c_peripherals = { - /* Touch Screen. */ - { - .board_info = { - I2C_BOARD_INFO("atmel_mxt_ts", - ATMEL_TS_I2C_ADDR), - .flags = I2C_CLIENT_WAKE, - }, - .dmi_name = "touchscreen", - .irqflags = IRQF_TRIGGER_FALLING, - .type = I2C_ADAPTER_PANEL, - .alt_addr = ATMEL_TS_I2C_BL_ADDR, +static struct i2c_peripheral chromebook_pixel_peripherals[] __initdata = { + /* Touch Screen. */ + { + .board_info = { + I2C_BOARD_INFO("atmel_mxt_ts", + ATMEL_TS_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, }, - /* Touchpad. */ - { - .board_info = { - I2C_BOARD_INFO("atmel_mxt_tp", - ATMEL_TP_I2C_ADDR), - .properties = - chromebook_pixel_trackpad_props, - .flags = I2C_CLIENT_WAKE, - }, - .dmi_name = "trackpad", - .irqflags = IRQF_TRIGGER_FALLING, - .type = I2C_ADAPTER_VGADDC, - .alt_addr = ATMEL_TP_I2C_BL_ADDR, + .dmi_name = "touchscreen", + .irqflags = IRQF_TRIGGER_FALLING, + .type = I2C_ADAPTER_PANEL, + .alt_addr = ATMEL_TS_I2C_BL_ADDR, + }, + /* Touchpad. */ + { + .board_info = { + I2C_BOARD_INFO("atmel_mxt_tp", + ATMEL_TP_I2C_ADDR), + .properties = + chromebook_pixel_trackpad_props, + .flags = I2C_CLIENT_WAKE, }, - /* Light Sensor. */ - { - .board_info = { - I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), - }, - .dmi_name = "lightsensor", - .type = I2C_ADAPTER_PANEL, + .dmi_name = "trackpad", + .irqflags = IRQF_TRIGGER_FALLING, + .type = I2C_ADAPTER_VGADDC, + .alt_addr = ATMEL_TP_I2C_BL_ADDR, + }, + /* Light Sensor. */ + { + .board_info = { + I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), }, + .dmi_name = "lightsensor", + .type = I2C_ADAPTER_PANEL, }, }; +DECLARE_CROS_LAPTOP(chromebook_pixel); -static struct chromeos_laptop hp_chromebook_14 = { - .i2c_peripherals = { - /* Touchpad. */ - { - .board_info = { - I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), - .flags = I2C_CLIENT_WAKE, - }, - .dmi_name = "trackpad", - .type = I2C_ADAPTER_DESIGNWARE, +static struct i2c_peripheral hp_chromebook_14_peripherals[] __initdata = { + /* Touchpad. */ + { + .board_info = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_DESIGNWARE, }, }; +DECLARE_CROS_LAPTOP(hp_chromebook_14); -static struct chromeos_laptop dell_chromebook_11 = { - .i2c_peripherals = { - /* Touchpad. */ - { - .board_info = { - I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), - .flags = I2C_CLIENT_WAKE, - }, - .dmi_name = "trackpad", - .type = I2C_ADAPTER_DESIGNWARE, +static struct i2c_peripheral dell_chromebook_11_peripherals[] __initdata = { + /* Touchpad. */ + { + .board_info = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, }, - /* Elan Touchpad option. */ - { - .board_info = { - I2C_BOARD_INFO("elan_i2c", ELAN_TP_I2C_ADDR), - .flags = I2C_CLIENT_WAKE, - }, - .dmi_name = "trackpad", - .type = I2C_ADAPTER_DESIGNWARE, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_DESIGNWARE, + }, + /* Elan Touchpad option. */ + { + .board_info = { + I2C_BOARD_INFO("elan_i2c", ELAN_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_DESIGNWARE, }, }; +DECLARE_CROS_LAPTOP(dell_chromebook_11); -static struct chromeos_laptop toshiba_cb35 = { - .i2c_peripherals = { - /* Touchpad. */ - { - .board_info = { - I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), - .flags = I2C_CLIENT_WAKE, - }, - .dmi_name = "trackpad", - .type = I2C_ADAPTER_DESIGNWARE, +static struct i2c_peripheral toshiba_cb35_peripherals[] __initdata = { + /* Touchpad. */ + { + .board_info = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_DESIGNWARE, }, }; +DECLARE_CROS_LAPTOP(toshiba_cb35); -static struct chromeos_laptop acer_c7_chromebook = { - .i2c_peripherals = { - /* Touchpad. */ - { - .board_info = { - I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), - .flags = I2C_CLIENT_WAKE, - }, - .dmi_name = "trackpad", - .type = I2C_ADAPTER_SMBUS, +static struct i2c_peripheral acer_c7_chromebook_peripherals[] __initdata = { + /* Touchpad. */ + { + .board_info = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_SMBUS, }, }; +DECLARE_CROS_LAPTOP(acer_c7_chromebook); -static struct chromeos_laptop acer_ac700 = { - .i2c_peripherals = { - /* Light Sensor. */ - { - .board_info = { - I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR), - }, - .type = I2C_ADAPTER_SMBUS, +static struct i2c_peripheral acer_ac700_peripherals[] __initdata = { + /* Light Sensor. */ + { + .board_info = { + I2C_BOARD_INFO("tsl2583", TAOS_ALS_I2C_ADDR), }, + .type = I2C_ADAPTER_SMBUS, }, }; +DECLARE_CROS_LAPTOP(acer_ac700); -static struct chromeos_laptop acer_c720 = { - .i2c_peripherals = { - /* Touchscreen. */ - { - .board_info = { - I2C_BOARD_INFO("atmel_mxt_ts", - ATMEL_TS_I2C_ADDR), - .flags = I2C_CLIENT_WAKE, - }, - .dmi_name = "touchscreen", - .irqflags = IRQF_TRIGGER_FALLING, - .type = I2C_ADAPTER_DESIGNWARE, - .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)), - .alt_addr = ATMEL_TS_I2C_BL_ADDR, +static struct i2c_peripheral acer_c720_peripherals[] __initdata = { + /* Touchscreen. */ + { + .board_info = { + I2C_BOARD_INFO("atmel_mxt_ts", + ATMEL_TS_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, }, - /* Touchpad. */ - { - .board_info = { - I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), - .flags = I2C_CLIENT_WAKE, - }, - .dmi_name = "trackpad", - .type = I2C_ADAPTER_DESIGNWARE, - .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x1)), + .dmi_name = "touchscreen", + .irqflags = IRQF_TRIGGER_FALLING, + .type = I2C_ADAPTER_DESIGNWARE, + .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)), + .alt_addr = ATMEL_TS_I2C_BL_ADDR, + }, + /* Touchpad. */ + { + .board_info = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, }, - /* Elan Touchpad option. */ - { - .board_info = { - I2C_BOARD_INFO("elan_i2c", ELAN_TP_I2C_ADDR), - .flags = I2C_CLIENT_WAKE, - }, - .dmi_name = "trackpad", - .type = I2C_ADAPTER_DESIGNWARE, - .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x1)), + .dmi_name = "trackpad", + .type = I2C_ADAPTER_DESIGNWARE, + .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x1)), + }, + /* Elan Touchpad option. */ + { + .board_info = { + I2C_BOARD_INFO("elan_i2c", ELAN_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, }, - /* Light Sensor. */ - { - .board_info = { - I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), - }, - .dmi_name = "lightsensor", - .type = I2C_ADAPTER_DESIGNWARE, - .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)), + .dmi_name = "trackpad", + .type = I2C_ADAPTER_DESIGNWARE, + .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x1)), + }, + /* Light Sensor. */ + { + .board_info = { + I2C_BOARD_INFO("isl29018", ISL_ALS_I2C_ADDR), }, + .dmi_name = "lightsensor", + .type = I2C_ADAPTER_DESIGNWARE, + .pci_devid = PCI_DEVID(0, PCI_DEVFN(0x15, 0x2)), }, }; +DECLARE_CROS_LAPTOP(acer_c720); -static struct chromeos_laptop hp_pavilion_14_chromebook = { - .i2c_peripherals = { - /* Touchpad. */ - { - .board_info = { - I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), - .flags = I2C_CLIENT_WAKE, - }, - .dmi_name = "trackpad", - .type = I2C_ADAPTER_SMBUS, +static struct i2c_peripheral +hp_pavilion_14_chromebook_peripherals[] __initdata = { + /* Touchpad. */ + { + .board_info = { + I2C_BOARD_INFO("cyapa", CYAPA_TP_I2C_ADDR), + .flags = I2C_CLIENT_WAKE, }, + .dmi_name = "trackpad", + .type = I2C_ADAPTER_SMBUS, }, }; +DECLARE_CROS_LAPTOP(hp_pavilion_14_chromebook); -static struct chromeos_laptop cr48 = { - .i2c_peripherals = { - /* Light Sensor. */ - { - .board_info = { - I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR), - }, - .type = I2C_ADAPTER_SMBUS, +static struct i2c_peripheral cr48_peripherals[] __initdata = { + /* Light Sensor. */ + { + .board_info = { + I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR), }, + .type = I2C_ADAPTER_SMBUS, }, }; +DECLARE_CROS_LAPTOP(cr48); static const struct dmi_system_id chromeos_laptop_dmi_table[] __initconst = { { @@ -541,24 +537,14 @@ static int __init chromeos_laptop_get_irq_from_dmi(const char *dmi_name) return dev_data->instance; } -static struct chromeos_laptop * __init -chromeos_laptop_prepare(const struct dmi_system_id *id) +static int __init chromeos_laptop_setup_irq(struct i2c_peripheral *i2c_dev) { - struct i2c_peripheral *i2c_dev; int irq; - int i; - - cros_laptop = (void *)id->driver_data; - - for (i = 0; i < MAX_I2C_PERIPHERALS; i++) { - i2c_dev = &cros_laptop->i2c_peripherals[i]; - - if (!i2c_dev->dmi_name) - continue; + if (i2c_dev->dmi_name) { irq = chromeos_laptop_get_irq_from_dmi(i2c_dev->dmi_name); if (irq < 0) - return ERR_PTR(irq); + return irq; i2c_dev->irq_resource = (struct resource) DEFINE_RES_NAMED(irq, 1, NULL, @@ -567,9 +553,87 @@ chromeos_laptop_prepare(const struct dmi_system_id *id) i2c_dev->board_info.num_resources = 1; } + return 0; +} + +static struct chromeos_laptop * __init +chromeos_laptop_prepare(const struct chromeos_laptop *src) +{ + struct chromeos_laptop *cros_laptop; + struct i2c_peripheral *i2c_dev; + struct i2c_board_info *info; + int error; + int i; + + cros_laptop = kzalloc(sizeof(*cros_laptop), GFP_KERNEL); + if (!cros_laptop) + return ERR_PTR(-ENOMEM); + + cros_laptop->i2c_peripherals = kmemdup(src->i2c_peripherals, + src->num_i2c_peripherals * + sizeof(*src->i2c_peripherals), + GFP_KERNEL); + if (!cros_laptop->i2c_peripherals) { + error = -ENOMEM; + goto err_free_cros_laptop; + } + + cros_laptop->num_i2c_peripherals = src->num_i2c_peripherals; + + for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) { + i2c_dev = &cros_laptop->i2c_peripherals[i]; + info = &i2c_dev->board_info; + + error = chromeos_laptop_setup_irq(i2c_dev); + if (error) + goto err_destroy_cros_peripherals; + + /* We need to deep-copy properties */ + if (info->properties) { + info->properties = + property_entries_dup(info->properties); + if (IS_ERR(info->properties)) { + error = PTR_ERR(info->properties); + goto err_destroy_cros_peripherals; + } + } + } + return cros_laptop; + +err_destroy_cros_peripherals: + while (--i >= 0) { + i2c_dev = &cros_laptop->i2c_peripherals[i]; + info = &i2c_dev->board_info; + if (info->properties) + property_entries_free(info->properties); + } + kfree(cros_laptop->i2c_peripherals); +err_free_cros_laptop: + kfree(cros_laptop); + return ERR_PTR(error); } +static void chromeos_laptop_destroy(const struct chromeos_laptop *cros_laptop) +{ + struct i2c_peripheral *i2c_dev; + struct i2c_board_info *info; + int i; + + for (i = 0; i < cros_laptop->num_i2c_peripherals; i++) { + i2c_dev = &cros_laptop->i2c_peripherals[i]; + info = &i2c_dev->board_info; + + if (i2c_dev->client) + i2c_unregister_device(i2c_dev->client); + + if (info->properties) + property_entries_free(info->properties); + } + + kfree(cros_laptop->i2c_peripherals); + kfree(cros_laptop); +} static int __init chromeos_laptop_init(void) { @@ -584,7 +648,7 @@ static int __init chromeos_laptop_init(void) pr_debug("DMI Matched %s\n", dmi_id->ident); - cros_laptop = chromeos_laptop_prepare(dmi_id->driver_data); + cros_laptop = chromeos_laptop_prepare((void *)dmi_id->driver_data); if (IS_ERR(cros_laptop)) return PTR_ERR(cros_laptop); @@ -592,6 +656,7 @@ static int __init chromeos_laptop_init(void) &chromeos_laptop_i2c_notifier); if (error) { pr_err("failed to register i2c bus notifier: %d\n", error); + chromeos_laptop_destroy(cros_laptop); return error; } @@ -606,21 +671,8 @@ static int __init chromeos_laptop_init(void) static void __exit chromeos_laptop_exit(void) { - struct i2c_peripheral *i2c_dev; - int i; - bus_unregister_notifier(&i2c_bus_type, &chromeos_laptop_i2c_notifier); - - for (i = 0; i < MAX_I2C_PERIPHERALS; i++) { - i2c_dev = &cros_laptop->i2c_peripherals[i]; - - /* No more peripherals */ - if (!i2c_dev->board_info.type) - break; - - if (i2c_dev->client) - i2c_unregister_device(i2c_dev->client); - } + chromeos_laptop_destroy(cros_laptop); } module_init(chromeos_laptop_init); -- cgit v1.2.3 From d6542b3916582375dde30344611fa920f51aed45 Mon Sep 17 00:00:00 2001 From: Wenkai Du Date: Thu, 22 Feb 2018 13:21:17 -0800 Subject: platform/chrome: cros_ec_lpc: wake up from s2idle on Chrome EC Chrome platform installed a Chrome EC notify handler which prevents default EC GPE handler getting called. Add pm_system_wakeup to the Chrome EC notify handler so wake up from s2idle can happen. Suggested-by: Rafael J. Wysocki Signed-off-by: Wenkai Du Signed-off-by: Benson Leung --- drivers/platform/chrome/cros_ec_lpc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index af89e82eecd2..2a40c2b1a7ff 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c @@ -31,6 +31,7 @@ #include #include #include +#include #define DRV_NAME "cros_ec_lpcs" #define ACPI_DRV_NAME "GOOG0004" @@ -235,6 +236,9 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data) cros_ec_get_next_event(ec_dev, NULL) > 0) blocking_notifier_call_chain(&ec_dev->event_notifier, 0, ec_dev); + + if (value == ACPI_NOTIFY_DEVICE_WAKE) + pm_system_wakeup(); } static int cros_ec_lpc_probe(struct platform_device *pdev) -- cgit v1.2.3 From f56db262e46d3368ee4e5c9e19797853cab382cd Mon Sep 17 00:00:00 2001 From: Salvatore Bellizzi Date: Wed, 7 Mar 2018 14:56:43 +0100 Subject: platform/chrome: cros_ec_lpc: Add support for Google devices using custom coreboot firmware This patch adds generic device information to the DMI table of the cros_ec_lpc driver, needed for Chromebooks/boxes using a custom coreboot firmware. The DMI info would not contain "Google_*" as BIOS version string, instead the system vendor string would still be "GOOGLE", so this seems to be a reasonable match for every Chromebook/box running a custom firmware. Signed-off-by: Salvatore Bellizzi Signed-off-by: Vittorio Gambaletta Signed-off-by: Benson Leung --- drivers/platform/chrome/cros_ec_lpc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c index 2a40c2b1a7ff..3682e1539251 100644 --- a/drivers/platform/chrome/cros_ec_lpc.c +++ b/drivers/platform/chrome/cros_ec_lpc.c @@ -345,6 +345,18 @@ static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = { DMI_MATCH(DMI_BIOS_VERSION, "Google_"), }, }, + { + /* + * If the box is running custom coreboot firmware then the + * DMI BIOS version string will not be matched by "Google_", + * but the system vendor string will still be matched by + * "GOOGLE". + */ + .matches = { + DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"), + DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"), + }, + }, { /* x86-link, the Chromebook Pixel. */ .matches = { -- cgit v1.2.3 From 311394248ca539c12b33d396b2944e03cd0d6bfc Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 23 Mar 2018 18:42:42 +0100 Subject: platform/chrome: cros_ec_sysfs: Modify error handling When accessing a sysfs attribute, if the EC command fails, -EPROTO is now returned instead of an error message as it is unlikely an app is parsing the error message to do something meaningful. Also, this patch makes use of cros_ec_cmd_xfer_status() instead of cros_ec_cmd_xfer() so an error message is printed in the syslog. Signed-off-by: Gwendal Grignou Signed-off-by: Enric Balletbo i Serra Signed-off-by: Benson Leung --- drivers/platform/chrome/cros_ec_sysfs.c | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c index da0a719d32f7..c03621e523a3 100644 --- a/drivers/platform/chrome/cros_ec_sysfs.c +++ b/drivers/platform/chrome/cros_ec_sysfs.c @@ -114,15 +114,9 @@ static ssize_t store_ec_reboot(struct device *dev, msg->command = EC_CMD_REBOOT_EC + ec->cmd_offset; msg->outsize = sizeof(*param); msg->insize = 0; - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); - if (ret < 0) { + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + if (ret < 0) count = ret; - goto exit; - } - if (msg->result != EC_RES_SUCCESS) { - dev_dbg(ec->dev, "EC result %d\n", msg->result); - count = -EINVAL; - } exit: kfree(msg); return count; @@ -150,17 +144,11 @@ static ssize_t show_ec_version(struct device *dev, msg->command = EC_CMD_GET_VERSION + ec->cmd_offset; msg->insize = sizeof(*r_ver); msg->outsize = 0; - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0) { count = ret; goto exit; } - if (msg->result != EC_RES_SUCCESS) { - count = scnprintf(buf, PAGE_SIZE, - "ERROR: EC returned %d\n", msg->result); - goto exit; - } - r_ver = (struct ec_response_get_version *)msg->data; /* Strings should be null-terminated, but let's be sure. */ r_ver->version_string_ro[sizeof(r_ver->version_string_ro) - 1] = '\0'; @@ -255,14 +243,9 @@ static ssize_t show_ec_flashinfo(struct device *dev, msg->command = EC_CMD_FLASH_INFO + ec->cmd_offset; msg->insize = sizeof(*resp); msg->outsize = 0; - ret = cros_ec_cmd_xfer(ec->ec_dev, msg); + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); if (ret < 0) goto exit; - if (msg->result != EC_RES_SUCCESS) { - ret = scnprintf(buf, PAGE_SIZE, - "ERROR: EC returned %d\n", msg->result); - goto exit; - } resp = (struct ec_response_flash_info *)msg->data; -- cgit v1.2.3 From 93afebbe694ecd0a22f065af2e2565e2dbd49025 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Fri, 23 Mar 2018 18:42:43 +0100 Subject: platform/chrome: cros_ec_sysfs: introduce to_cros_ec_dev define. Add a define to get the cros_ec_dev from device and use it. Suggested-by: Andy Shevchenko Signed-off-by: Enric Balletbo i Serra Reviewed-by: Andy Shevchenko Signed-off-by: Benson Leung --- drivers/platform/chrome/cros_ec_sysfs.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c index c03621e523a3..85bb9580439e 100644 --- a/drivers/platform/chrome/cros_ec_sysfs.c +++ b/drivers/platform/chrome/cros_ec_sysfs.c @@ -34,6 +34,8 @@ #include #include +#define to_cros_ec_dev(dev) container_of(dev, struct cros_ec_dev, class_dev) + /* Accessor functions */ static ssize_t show_ec_reboot(struct device *dev, @@ -70,8 +72,7 @@ static ssize_t store_ec_reboot(struct device *dev, int got_cmd = 0, offset = 0; int i; int ret; - struct cros_ec_dev *ec = container_of(dev, - struct cros_ec_dev, class_dev); + struct cros_ec_dev *ec = to_cros_ec_dev(dev); msg = kmalloc(sizeof(*msg) + sizeof(*param), GFP_KERNEL); if (!msg) @@ -132,8 +133,7 @@ static ssize_t show_ec_version(struct device *dev, struct cros_ec_command *msg; int ret; int count = 0; - struct cros_ec_dev *ec = container_of(dev, - struct cros_ec_dev, class_dev); + struct cros_ec_dev *ec = to_cros_ec_dev(dev); msg = kmalloc(sizeof(*msg) + EC_HOST_PARAM_SIZE, GFP_KERNEL); if (!msg) @@ -231,8 +231,7 @@ static ssize_t show_ec_flashinfo(struct device *dev, struct ec_response_flash_info *resp; struct cros_ec_command *msg; int ret; - struct cros_ec_dev *ec = container_of(dev, - struct cros_ec_dev, class_dev); + struct cros_ec_dev *ec = to_cros_ec_dev(dev); msg = kmalloc(sizeof(*msg) + sizeof(*resp), GFP_KERNEL); if (!msg) -- cgit v1.2.3 From 7d800c99ecfab57845c5ae29ed0aefb36c055c2b Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Fri, 23 Mar 2018 18:42:44 +0100 Subject: platform/chrome: cros_ec_sysfs: use permission-specific DEVICE_ATTR variants Use DEVICE_ATTR variants for read/write attributes. This simplifies the source code, improves readbility, and reduces the chance of inconsistencies. Suggested-by: Andy Shevchenko Signed-off-by: Enric Balletbo i Serra Reviewed-by: Andy Shevchenko Signed-off-by: Benson Leung --- drivers/platform/chrome/cros_ec_sysfs.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c index 85bb9580439e..78ae0d3760e4 100644 --- a/drivers/platform/chrome/cros_ec_sysfs.c +++ b/drivers/platform/chrome/cros_ec_sysfs.c @@ -38,8 +38,8 @@ /* Accessor functions */ -static ssize_t show_ec_reboot(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t reboot_show(struct device *dev, + struct device_attribute *attr, char *buf) { int count = 0; @@ -50,9 +50,9 @@ static ssize_t show_ec_reboot(struct device *dev, return count; } -static ssize_t store_ec_reboot(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t reboot_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { static const struct { const char * const str; @@ -123,8 +123,8 @@ exit: return count; } -static ssize_t show_ec_version(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t version_show(struct device *dev, + struct device_attribute *attr, char *buf) { static const char * const image_names[] = {"unknown", "RO", "RW"}; struct ec_response_get_version *r_ver; @@ -225,8 +225,8 @@ exit: return count; } -static ssize_t show_ec_flashinfo(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t flashinfo_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct ec_response_flash_info *resp; struct cros_ec_command *msg; @@ -260,9 +260,9 @@ exit: /* Module initialization */ -static DEVICE_ATTR(reboot, S_IWUSR | S_IRUGO, show_ec_reboot, store_ec_reboot); -static DEVICE_ATTR(version, S_IRUGO, show_ec_version, NULL); -static DEVICE_ATTR(flashinfo, S_IRUGO, show_ec_flashinfo, NULL); +static DEVICE_ATTR_RW(reboot); +static DEVICE_ATTR_RO(version); +static DEVICE_ATTR_RO(flashinfo); static struct attribute *__ec_attrs[] = { &dev_attr_reboot.attr, -- cgit v1.2.3 From f63192800ebd01099d3487f7fef1dd0ee0b18b45 Mon Sep 17 00:00:00 2001 From: Enric Balletbo i Serra Date: Fri, 23 Mar 2018 18:42:45 +0100 Subject: platform/chrome: cros_ec_debugfs: Use octal permissions '0444' Fixed the following checkpatch warning: WARNING: Symbolic permissions 'S_IRUGO' are not preferred. Consider using octal permissions '0444'. Signed-off-by: Enric Balletbo i Serra Suggested-by: Andy Shevchenko Reviewed-by: Andy Shevchenko Signed-off-by: Benson Leung --- drivers/platform/chrome/cros_ec_debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c index 0e88e18362c1..539403022568 100644 --- a/drivers/platform/chrome/cros_ec_debugfs.c +++ b/drivers/platform/chrome/cros_ec_debugfs.c @@ -288,7 +288,7 @@ static int cros_ec_create_console_log(struct cros_ec_debugfs *debug_info) init_waitqueue_head(&debug_info->log_wq); if (!debugfs_create_file("console_log", - S_IFREG | S_IRUGO, + S_IFREG | 0444, debug_info->dir, debug_info, &cros_ec_console_log_fops)) @@ -341,7 +341,7 @@ static int cros_ec_create_panicinfo(struct cros_ec_debugfs *debug_info) debug_info->panicinfo_blob.size = ret; if (!debugfs_create_blob("panicinfo", - S_IFREG | S_IRUGO, + S_IFREG | 0444, debug_info->dir, &debug_info->panicinfo_blob)) { ret = -ENOMEM; -- cgit v1.2.3 From b082b2e1454c3e0217d7cf70f2211966c3d54301 Mon Sep 17 00:00:00 2001 From: Shawn Nematbakhsh Date: Fri, 23 Mar 2018 18:42:46 +0100 Subject: platform/chrome: cros_ec_debugfs: Add PD port info to debugfs Add info useful for debugging USB-PD port state. Signed-off-by: Shawn Nematbakhsh Signed-off-by: Enric Balletbo i Serra Reviewed-by: Andy Shevchenko Acked-by: Lee Jones Signed-off-by: Benson Leung --- drivers/platform/chrome/cros_ec_debugfs.c | 72 +++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c index 539403022568..cc265ed8deb7 100644 --- a/drivers/platform/chrome/cros_ec_debugfs.c +++ b/drivers/platform/chrome/cros_ec_debugfs.c @@ -211,6 +211,58 @@ static int cros_ec_console_log_release(struct inode *inode, struct file *file) return 0; } +static ssize_t cros_ec_pdinfo_read(struct file *file, + char __user *user_buf, + size_t count, + loff_t *ppos) +{ + char read_buf[EC_USB_PD_MAX_PORTS * 40], *p = read_buf; + struct cros_ec_debugfs *debug_info = file->private_data; + struct cros_ec_device *ec_dev = debug_info->ec->ec_dev; + struct { + struct cros_ec_command msg; + union { + struct ec_response_usb_pd_control_v1 resp; + struct ec_params_usb_pd_control params; + }; + } __packed ec_buf; + struct cros_ec_command *msg; + struct ec_response_usb_pd_control_v1 *resp; + struct ec_params_usb_pd_control *params; + int i; + + msg = &ec_buf.msg; + params = (struct ec_params_usb_pd_control *)msg->data; + resp = (struct ec_response_usb_pd_control_v1 *)msg->data; + + msg->command = EC_CMD_USB_PD_CONTROL; + msg->version = 1; + msg->insize = sizeof(*resp); + msg->outsize = sizeof(*params); + + /* + * Read status from all PD ports until failure, typically caused + * by attempting to read status on a port that doesn't exist. + */ + for (i = 0; i < EC_USB_PD_MAX_PORTS; ++i) { + params->port = i; + params->role = 0; + params->mux = 0; + params->swap = 0; + + if (cros_ec_cmd_xfer_status(ec_dev, msg) < 0) + break; + + p += scnprintf(p, sizeof(read_buf) + read_buf - p, + "p%d: %s en:%.2x role:%.2x pol:%.2x\n", i, + resp->state, resp->enabled, resp->role, + resp->polarity); + } + + return simple_read_from_buffer(user_buf, count, ppos, + read_buf, p - read_buf); +} + const struct file_operations cros_ec_console_log_fops = { .owner = THIS_MODULE, .open = cros_ec_console_log_open, @@ -220,6 +272,13 @@ const struct file_operations cros_ec_console_log_fops = { .release = cros_ec_console_log_release, }; +const struct file_operations cros_ec_pdinfo_fops = { + .owner = THIS_MODULE, + .open = simple_open, + .read = cros_ec_pdinfo_read, + .llseek = default_llseek, +}; + static int ec_read_version_supported(struct cros_ec_dev *ec) { struct ec_params_get_cmd_versions_v1 *params; @@ -355,6 +414,15 @@ free: return ret; } +static int cros_ec_create_pdinfo(struct cros_ec_debugfs *debug_info) +{ + if (!debugfs_create_file("pdinfo", 0444, debug_info->dir, debug_info, + &cros_ec_pdinfo_fops)) + return -ENOMEM; + + return 0; +} + int cros_ec_debugfs_init(struct cros_ec_dev *ec) { struct cros_ec_platform *ec_platform = dev_get_platdata(ec->dev); @@ -379,6 +447,10 @@ int cros_ec_debugfs_init(struct cros_ec_dev *ec) if (ret) goto remove_debugfs; + ret = cros_ec_create_pdinfo(debug_info); + if (ret) + goto remove_debugfs; + ec->debug_info = debug_info; return 0; -- cgit v1.2.3 From c1d1e91aff3d1183d6b16a282c2575e3e006cee4 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 23 Mar 2018 18:42:47 +0100 Subject: platform/chrome: mfd/cros_ec_dev: Add sysfs entry to set keyboard wake lid angle This adds a sysfs attribute (/sys/class/chromeos/cros_ec/kb_wake_angle) used to set and get the keyboard wake lid angle. This attribute is present only if 2 accelerometers are controlled by the EC. This patch also moves the cros_ec features check before the device is added so the features map obtained from the EC is ready on time. Signed-off-by: Gwendal Grignou Signed-off-by: Enric Balletbo i Serra Reviewed-by: Andy Shevchenko Acked-by: Lee Jones Signed-off-by: Benson Leung --- drivers/platform/chrome/cros_ec_sysfs.c | 81 +++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'drivers/platform') diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c index 78ae0d3760e4..5a6db3fe213a 100644 --- a/drivers/platform/chrome/cros_ec_sysfs.c +++ b/drivers/platform/chrome/cros_ec_sysfs.c @@ -258,21 +258,102 @@ exit: return ret; } +/* Keyboard wake angle control */ +static ssize_t kb_wake_angle_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct cros_ec_dev *ec = to_cros_ec_dev(dev); + struct ec_response_motion_sense *resp; + struct ec_params_motion_sense *param; + struct cros_ec_command *msg; + int ret; + + msg = kmalloc(sizeof(*msg) + EC_HOST_PARAM_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + param = (struct ec_params_motion_sense *)msg->data; + msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; + msg->version = 2; + param->cmd = MOTIONSENSE_CMD_KB_WAKE_ANGLE; + param->kb_wake_angle.data = EC_MOTION_SENSE_NO_VALUE; + msg->outsize = sizeof(*param); + msg->insize = sizeof(*resp); + + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + if (ret < 0) + goto exit; + + resp = (struct ec_response_motion_sense *)msg->data; + ret = scnprintf(buf, PAGE_SIZE, "%d\n", resp->kb_wake_angle.ret); +exit: + kfree(msg); + return ret; +} + +static ssize_t kb_wake_angle_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct cros_ec_dev *ec = to_cros_ec_dev(dev); + struct ec_params_motion_sense *param; + struct cros_ec_command *msg; + u16 angle; + int ret; + + ret = kstrtou16(buf, 0, &angle); + if (ret) + return ret; + + msg = kmalloc(sizeof(*msg) + EC_HOST_PARAM_SIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + param = (struct ec_params_motion_sense *)msg->data; + msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; + msg->version = 2; + param->cmd = MOTIONSENSE_CMD_KB_WAKE_ANGLE; + param->kb_wake_angle.data = angle; + msg->outsize = sizeof(*param); + msg->insize = sizeof(struct ec_response_motion_sense); + + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); + kfree(msg); + if (ret < 0) + return ret; + return count; +} + /* Module initialization */ static DEVICE_ATTR_RW(reboot); static DEVICE_ATTR_RO(version); static DEVICE_ATTR_RO(flashinfo); +static DEVICE_ATTR_RW(kb_wake_angle); static struct attribute *__ec_attrs[] = { + &dev_attr_kb_wake_angle.attr, &dev_attr_reboot.attr, &dev_attr_version.attr, &dev_attr_flashinfo.attr, NULL, }; +static umode_t cros_ec_ctrl_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev = container_of(kobj, struct device, kobj); + struct cros_ec_dev *ec = to_cros_ec_dev(dev); + + if (a == &dev_attr_kb_wake_angle.attr && !ec->has_kb_wake_angle) + return 0; + + return a->mode; +} + struct attribute_group cros_ec_attr_group = { .attrs = __ec_attrs, + .is_visible = cros_ec_ctrl_visible, }; EXPORT_SYMBOL(cros_ec_attr_group); -- cgit v1.2.3