mb/google/sarien: Support multiple touchscreen at same address

The Sarien board may have different touchscreen devices that use the
same I2C slave address but have different requirements such as needing
a special driver or ACPI configuration.

In order to support this the devicetree may be configured with multiple
devices at the same address and at boot time the unused devices will be
disabled.

Because there is no GPIO for selecting the device that is present it can
instead be selected with Kconfig, or by setting a VPD key to the HID of
the touchscreen device that is present.  The default for Sarien devices
is to not enable a touchscreen for the OS.

The touchscreen selection is currently limited to the Sarien variant but
this also adds the touchscreen HID for Arcada to Kconfig so it would not
complain about the key not being set.

BUG=b:122019253
TEST=This was tested on a Sarien board by adding a second entry to the
devicetree at the same address.  Without this change the SSDT is not
loaded by the kernel because of the address conflict.  After this change
no touchscreen is enabled by default, but one can be selected with
Kconfig or by setting the 'touchscreen_hid' VPD key.

Change-Id: I4da12b1de0c551bcd89325fe0d8c66c6ffeb7afc
Signed-off-by: Duncan Laurie <dlaurie@google.com>
Reviewed-on: https://review.coreboot.org/c/31295
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
This commit is contained in:
Duncan Laurie 2019-02-08 16:43:48 -08:00 committed by Patrick Georgi
parent c8464748cd
commit f1690f0ec1
3 changed files with 79 additions and 1 deletions

View File

@ -97,6 +97,11 @@ config DEVICETREE
string
default "variants/$(CONFIG_VARIANT_DIR)/devicetree.cb"
config TOUCHSCREEN_HID
string "Specify the touchscreen HID enabled for the OS"
default "WCOM48E2" if BOARD_GOOGLE_ARCADA
default "NONE" if BOARD_GOOGLE_SARIEN
config VBOOT
select HAS_RECOVERY_MRC_CACHE
select MRC_CLEAR_NORMAL_CACHE_ON_RECOVERY_RETRAIN

View File

@ -14,6 +14,6 @@
##
bootblock-y += gpio.c
ramstage-y += gpio.c
ramstage-y += gpio.c ramstage.c
romstage-y += gpio.c
verstage-y += gpio.c

View File

@ -0,0 +1,73 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2019 Google LLC
*
* 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; version 2 of the License.
*
* 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.
*/
#include <bootstate.h>
#include <console/console.h>
#include <device/device.h>
#include <drivers/i2c/hid/chip.h>
#include <drivers/vpd/vpd.h>
#include <soc/pci_devs.h>
#include <string.h>
/*
* This board may have different touchscreen devices that are at the
* same I2C slave address but need different drivers or ACPI configuration.
*
* The default touchscreen to be enabled is specified in Kconfig by the
* ACPI HID of the device. If a board is connected to a different
* touchscreen device it can be enabled in Kconfig or by setting the
* VPD key 'touchscreen_hid'.
*/
#define TOUCHSCREEN_I2C_ADDR 0x10
#define TOUCHSCREEN_VPD_KEY "touchscreen_hid"
static void disable_unused_touchscreen(void *unused)
{
struct device *i2c0 = PCH_DEV_I2C0;
struct bus *i2c_slaves = i2c0->link_list;
struct device *slave = i2c_slaves->children;
char touchscreen_hid[9] = CONFIG_TOUCHSCREEN_HID;
struct drivers_i2c_hid_config *info;
/* Look for VPD key that indicates which touchscreen is present */
if (IS_ENABLED(CONFIG_VPD) &&
!vpd_gets(TOUCHSCREEN_VPD_KEY, touchscreen_hid,
ARRAY_SIZE(touchscreen_hid), VPD_ANY))
printk(BIOS_INFO, "%s: VPD key '%s' not found, default to %s\n",
__func__, TOUCHSCREEN_VPD_KEY, touchscreen_hid);
/* Go through all I2C slave devices on this bus */
while (slave) {
/* Find all the I2C slaves with the matching address */
if (slave->path.type == DEVICE_PATH_I2C &&
slave->path.i2c.device == TOUCHSCREEN_I2C_ADDR) {
info = slave->chip_info;
/* Disable all devices except the matching HID */
if (strncmp(info->generic.hid, touchscreen_hid,
ARRAY_SIZE(touchscreen_hid))) {
printk(BIOS_INFO, "%s: Disable %s\n", __func__,
info->generic.hid);
slave->enabled = 0;
} else {
printk(BIOS_INFO, "%s: Enable %s\n", __func__,
info->generic.hid);
}
}
slave = slave->sibling;
}
}
BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_ENTRY,
disable_unused_touchscreen, NULL);