Duncan Laurie (dlaurie(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15512
-gerrit
commit 332c7fdeecd5b877fad3de4a89ddcb059815ec44
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Wed Jun 29 10:47:22 2016 -0700
gpio: Add support for translating gpio_t into ACPI pin
Add a function for an SOC to define that will allow it to map the
SOC-specific gpio_t value into an appropriate ACPI pin. The exact
behavior depends on the GPIO implementation in the SOC, but it can
be used to provide a pin number that is relative to the community or
bank that a GPIO resides in.
Change-Id: Icb97ccf7d6a9034877614d49166bc9e4fe659bcf
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
---
src/arch/x86/acpi_device.c | 9 +++++++--
src/include/gpio.h | 10 ++++++++++
src/lib/gpio.c | 6 ++++++
3 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/src/arch/x86/acpi_device.c b/src/arch/x86/acpi_device.c
index 69d44f3..940d871 100644
--- a/src/arch/x86/acpi_device.c
+++ b/src/arch/x86/acpi_device.c
@@ -314,8 +314,13 @@ void acpi_device_write_gpio(const struct acpi_gpio *gpio)
acpi_device_fill_from_len(pin_table_offset, start);
/* Pin Table, one word for each pin */
- for (pin = 0; pin < gpio->pin_count; pin++)
- acpigen_emit_word(gpio->pins[pin]);
+ for (pin = 0; pin < gpio->pin_count; pin++) {
+ uint16_t acpi_pin = gpio->pins[pin];
+#if IS_ENABLED(CONFIG_GENERIC_GPIO_LIB)
+ acpi_pin = gpio_acpi_pin(acpi_pin);
+#endif
+ acpigen_emit_word(acpi_pin);
+ }
/* Fill in Resource Source Name Offset */
acpi_device_fill_from_len(resource_offset, start);
diff --git a/src/include/gpio.h b/src/include/gpio.h
index 3f462df..69a0828 100644
--- a/src/include/gpio.h
+++ b/src/include/gpio.h
@@ -41,6 +41,16 @@ int _gpio_base3_value(gpio_t gpio[], int num_gpio, int binary_first);
const char *gpio_acpi_path(gpio_t gpio);
/*
+ * This function may be implemented by SoC/board code to provide
+ * a mapping from the internal representation of a GPIO to the 16bit
+ * value used in an ACPI GPIO pin table entry.
+ *
+ * If not implemented by the SOC the default handler will return 0
+ * because the underlying type of gpio_t is unknown.
+ */
+uint16_t gpio_acpi_pin(gpio_t gpio);
+
+/*
* Read the value presented by the set of GPIOs, when each pin is interpreted
* as a base-2 digit (LOW = 0, HIGH = 1).
*
diff --git a/src/lib/gpio.c b/src/lib/gpio.c
index b0a5f4d..81d6f6b 100644
--- a/src/lib/gpio.c
+++ b/src/lib/gpio.c
@@ -145,3 +145,9 @@ __attribute__((weak)) const char *gpio_acpi_path(gpio_t gpio)
{
return NULL;
}
+
+/* Default handler returns 0 because type of gpio_t is unknown */
+__attribute__((weak)) uint16_t gpio_acpi_pin(gpio_t gpio)
+{
+ return 0;
+}
Duncan Laurie (dlaurie(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15513
-gerrit
commit aacca207662db212ddbd0ef9a2480701c420be81
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Wed Jun 29 10:47:48 2016 -0700
soc/intel/apollolake: Add function to translate gpio_t into ACPI pin
There are four GPIO communities in this SOC and they are implemented
as separate ACPI devices. This means the pin number that is used in
an ACPI GPIO declaration needs to be relative to the community that
the pin resides in. Also select GENERIC_GPIO_LIB in the SOC Kconfig
so this function actually gets used.
This was tested on the reef mainboard by verifying the output of the
SSDT for the Maxim 98357A codec that the assigned GPIO_76 is listed
as pin 0x24 which is the value relative to the Northwest community.
Change-Id: Iad2ab8eccf4c91185a075ffce8d41c81f06c1113
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
---
src/soc/intel/apollolake/Kconfig | 1 +
src/soc/intel/apollolake/gpio.c | 18 ++++++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig
index cce06eb..364c331 100644
--- a/src/soc/intel/apollolake/Kconfig
+++ b/src/soc/intel/apollolake/Kconfig
@@ -24,6 +24,7 @@ config CPU_SPECIFIC_OPTIONS
select C_ENVIRONMENT_BOOTBLOCK
select COLLECT_TIMESTAMPS
select COMMON_FADT
+ select GENERIC_GPIO_LIB
select HAVE_INTEL_FIRMWARE
select HAVE_SMI_HANDLER
select MMCONF_SUPPORT
diff --git a/src/soc/intel/apollolake/gpio.c b/src/soc/intel/apollolake/gpio.c
index d0ef648..ac0d83b 100644
--- a/src/soc/intel/apollolake/gpio.c
+++ b/src/soc/intel/apollolake/gpio.c
@@ -132,3 +132,21 @@ const char *gpio_acpi_path(gpio_t gpio_num)
return NULL;
}
+
+uint16_t gpio_acpi_pin(gpio_t gpio_num)
+{
+ const struct pad_community *comm = gpio_get_community(gpio_num);
+
+ switch (comm->port) {
+ case GPIO_NORTH:
+ return PAD_N(gpio_num);
+ case GPIO_NORTHWEST:
+ return PAD_NW(gpio_num);
+ case GPIO_WEST:
+ return PAD_W(gpio_num);
+ case GPIO_SOUTHWEST:
+ return PAD_SW(gpio_num);
+ }
+
+ return gpio_num;
+}
Duncan Laurie (dlaurie(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15514
-gerrit
commit 7c2a1bb0e269046e5d85e30a976d621d9878d2a7
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Wed Jun 29 22:34:01 2016 -0700
drivers/generic/max98357a: Fix naming and ACPI path handling
The upstream kernel driver is not using the of-style naming for
sdmode-gpio so remove the maxim prefix, and remove the duplicate
entry for the sdmode-delay value as well.
Also fix the usage of the path variable, since the device path uses
a static variable it can't be assigned that early or it will be
overwritten by later calls.
This results in the following output for the _DSD when tested on
reef mainboard:
Name (_DSD, Package (0x02)
{
ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301")
Package (0x02)
{
Package (0x02)
{
"sdmode-gpio",
Package (0x04)
{
\_SB.PCI0.HDAS.MAXM,
Zero,
Zero,
Zero
}
},
Package (0x02)
{
"sdmode-delay",
Zero
}
}
})
Change-Id: Iab33182a5f64c89151966f5e79f4f7c30840c46f
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
---
src/drivers/generic/max98357a/max98357a.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/drivers/generic/max98357a/max98357a.c b/src/drivers/generic/max98357a/max98357a.c
index cbd7efd..0d522d4 100644
--- a/src/drivers/generic/max98357a/max98357a.c
+++ b/src/drivers/generic/max98357a/max98357a.c
@@ -31,9 +31,9 @@
static void max98357a_fill_ssdt(struct device *dev)
{
struct drivers_generic_max98357a_config *config = dev->chip_info;
- const char *path = acpi_device_path(dev);
+ const char *path;
- if (!dev->enabled || !path || !config)
+ if (!dev->enabled || !config)
return;
/* Device */
@@ -53,10 +53,8 @@ static void max98357a_fill_ssdt(struct device *dev)
/* _DSD for devicetree properties */
acpi_dp_write_header();
/* This points to the first pin in the first gpio entry in _CRS */
- acpi_dp_write_gpio("maxim,sdmode-gpio", path, 0, 0, 0);
- /* This is the correctly formatted Device Property name */
- acpi_dp_write_integer("maxim,sdmode-delay", config->sdmode_delay);
- /* This is used by the chromium kernel but is not upstream */
+ path = acpi_device_path(dev);
+ acpi_dp_write_gpio("sdmode-gpio", path, 0, 0, 0);
acpi_dp_write_integer("sdmode-delay", config->sdmode_delay);
acpi_dp_write_footer();
Duncan Laurie (dlaurie(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15481
-gerrit
commit c369f6d97b9881cd398e8028f11ac877ccba89ba
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Mon Jun 27 11:05:16 2016 -0700
google/reef: ACPI: Move touchpad to SSDT and remove TPM
Instantiate the touchpad using the drivers/i2c/generic device driver
to generate the ACPI object in the SSDT.
There is not currently a separate wake pin for this device, this will
be added in EVT hardware.
This was tested on the reef board by ensuring that the touchpad device
continues to work in the OS.
Also remove the LPC TPM from the DSDT as it is not present.
Change-Id: I3151a28f628e66f63033398d6fab9fd8f5dfc37b
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
---
src/mainboard/google/reef/Kconfig | 3 ++
src/mainboard/google/reef/acpi/mainboard.asl | 48 +---------------------------
src/mainboard/google/reef/devicetree.cb | 9 +++++-
3 files changed, 12 insertions(+), 48 deletions(-)
diff --git a/src/mainboard/google/reef/Kconfig b/src/mainboard/google/reef/Kconfig
index ded75bb..194a6ba 100644
--- a/src/mainboard/google/reef/Kconfig
+++ b/src/mainboard/google/reef/Kconfig
@@ -25,6 +25,9 @@ config CHROMEOS
select VBOOT_OPROM_MATTERS
select VIRTUAL_DEV_SWITCH
+config DRIVERS_I2C_GENERIC
+ default y
+
config MAINBOARD_DIR
string
default google/reef
diff --git a/src/mainboard/google/reef/acpi/mainboard.asl b/src/mainboard/google/reef/acpi/mainboard.asl
index 5471488..5b6e976 100644
--- a/src/mainboard/google/reef/acpi/mainboard.asl
+++ b/src/mainboard/google/reef/acpi/mainboard.asl
@@ -33,54 +33,8 @@ Scope (\_SB)
}
}
-Scope (\_SB.PCI0.I2C4)
-{
- /* Standard Mode: HCNT, LCNT, SDA Hold Register */
- /* SDA Hold register value of 40 indicates
- * sda hold time of 0.3us for ic_clk of 133MHz
- */
- Name (SSCN, Package () { 0, 0, 40 })
-
- /* Fast Mode: HCNT, LCNT, SDA Hold Register */
- /* SDA Hold register value of 40 indicates
- * sda hold time of 0.3us for ic_clk of 133MHz
- */
- Name (FMCN, Package () { 0, 0, 40 })
-
- Device (ETPA)
- {
- Name (_HID, "ELAN0000")
- Name (_DDN, "Elan Touchpad")
- Name (_UID, 1)
- Name (ISTP, 1) /* Touchpad */
-
- Name (_CRS, ResourceTemplate()
- {
- I2cSerialBus (
- 0x15, // SlaveAddress
- ControllerInitiated, // SlaveMode
- 400000, // ConnectionSpeed
- AddressingMode7Bit, // AddressingMode
- "\\_SB.PCI0.I2C4", // ResourceSource
- )
- Interrupt (ResourceConsumer, Edge, ActiveLow)
- {
- TOUCHPAD_INT
- }
- })
-
- Method (_STA)
- {
- Return (0xF)
- }
- }
-}
-
-/*
- * LPC Trusted Platform Module
- */
Scope (\_SB.PCI0.LPCB)
{
- #include <drivers/pc80/tpm/acpi/tpm.asl>
+ /* Chrome OS Embedded Controller */
#include "ec.asl"
}
diff --git a/src/mainboard/google/reef/devicetree.cb b/src/mainboard/google/reef/devicetree.cb
index d2b295f..e0831f4 100644
--- a/src/mainboard/google/reef/devicetree.cb
+++ b/src/mainboard/google/reef/devicetree.cb
@@ -61,7 +61,14 @@ chip soc/intel/apollolake
device pci 16.1 on end # - I2C 1
device pci 16.2 on end # - I2C 2
device pci 16.3 on end # - I2C 3
- device pci 17.0 on end # - I2C 4
+ device pci 17.0 on
+ chip drivers/i2c/generic
+ register "hid" = ""ELAN0000""
+ register "desc" = ""ELAN Touchpad""
+ register "irq" = "IRQ_EDGE_LOW(GPIO_18_IRQ)"
+ device i2c 15 on end
+ end
+ end # - I2C 4
device pci 17.1 on end # - I2C 5
device pci 17.2 on end # - I2C 6
device pci 17.3 on end # - I2C 7
Duncan Laurie (dlaurie(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15480
-gerrit
commit 04f7c8e19572deb97515ff392b6c9e6b0be5dfde
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Mon Jun 27 10:57:13 2016 -0700
soc/intel/apollolake: Add support for LPSS I2C driver
Support the I2C interfaces on this SOC using the Intel common lpss_i2c
driver. The controllers are supported in pre-ram environments by
setting a temporary base address in bootblock and in ramstage using
the naturally enumerated base address.
The base speed of this controller is 133MHz and the SCL/SDA timing
values that are reported to the OS are calculated using that clock.
This was tested on a google/reef board doing I2C transactions to the
trackpad both in verstage and in ramstage.
Change-Id: I0a9d62cd1007caa95cdf4754f30c30aaff9f78f9
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
---
src/soc/intel/apollolake/Kconfig | 8 +-
src/soc/intel/apollolake/Makefile.inc | 3 +
src/soc/intel/apollolake/chip.h | 17 ++++
src/soc/intel/apollolake/i2c.c | 126 +++++++++++++++++++++++++++
src/soc/intel/apollolake/i2c_early.c | 116 ++++++++++++++++++++++++
src/soc/intel/apollolake/include/soc/i2c.h | 50 +++++++++++
src/soc/intel/apollolake/include/soc/iomap.h | 5 +-
7 files changed, 323 insertions(+), 2 deletions(-)
diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig
index 8e33015..cce06eb 100644
--- a/src/soc/intel/apollolake/Kconfig
+++ b/src/soc/intel/apollolake/Kconfig
@@ -41,8 +41,9 @@ config CPU_SPECIFIC_OPTIONS
select RELOCATABLE_RAMSTAGE # Build fails if this is not selected
select SMM_TSEG
select SOC_INTEL_COMMON
- select SOC_INTEL_COMMON_SMI
select SOC_INTEL_COMMON_ACPI
+ select SOC_INTEL_COMMON_LPSS_I2C
+ select SOC_INTEL_COMMON_SMI
select SPI_FLASH
select UDELAY_TSC
select TSC_CONSTANT_RATE
@@ -96,6 +97,11 @@ config CPU_ADDR_BITS
int
default 36
+config SOC_INTEL_COMMON_LPSS_I2C_CLOCK_MHZ
+ depends on SOC_INTEL_COMMON_LPSS_I2C
+ int
+ default 133
+
config CONSOLE_UART_BASE_ADDRESS
depends on CONSOLE_SERIAL
hex "MMIO base address for UART"
diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc
index 030e35c..a64ee78 100644
--- a/src/soc/intel/apollolake/Makefile.inc
+++ b/src/soc/intel/apollolake/Makefile.inc
@@ -23,6 +23,7 @@ bootblock-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
romstage-y += car.c
romstage-$(CONFIG_PLATFORM_USES_FSP2_0) += romstage.c
romstage-y += gpio.c
+romstage-y += i2c_early.c
romstage-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
romstage-y += lpc_lib.c
romstage-y += memmap.c
@@ -45,6 +46,7 @@ ramstage-y += cpu.c
ramstage-y += chip.c
ramstage-y += gpio.c
ramstage-y += graphics.c
+ramstage-y += i2c.c
ramstage-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
ramstage-y += lpc.c
ramstage-y += lpc_lib.c
@@ -69,6 +71,7 @@ postcar-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
postcar-y += tsc_freq.c
verstage-y += car.c
+verstage-y += i2c_early.c
verstage-y += memmap.c
verstage-y += mmap_boot.c
verstage-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
diff --git a/src/soc/intel/apollolake/chip.h b/src/soc/intel/apollolake/chip.h
index ef82c53..c83f973 100644
--- a/src/soc/intel/apollolake/chip.h
+++ b/src/soc/intel/apollolake/chip.h
@@ -18,7 +18,21 @@
#ifndef _SOC_APOLLOLAKE_CHIP_H_
#define _SOC_APOLLOLAKE_CHIP_H_
+#include <soc/gpio.h>
+#include <soc/intel/common/lpss_i2c.h>
+#include <device/i2c.h>
+
#define CLKREQ_DISABLED 0xf
+#define APOLLOLAKE_I2C_DEV_MAX 8
+
+struct apollolake_i2c_config {
+ /* Bus should be enabled prior to ramstage with temporary base */
+ int early_init;
+ /* Bus speed in Hz, default is I2C_SPEED_FAST (400 KHz) */
+ enum i2c_speed speed;
+ /* Specific bus speed configuration */
+ struct lpss_i2c_speed_config speed_config[LPSS_I2C_SPEED_CONFIG_COUNT];
+};
/* Serial IRQ control. SERIRQ_QUIET is the default (0). */
enum serirq_mode {
@@ -79,6 +93,9 @@ struct soc_intel_apollolake_config {
/* Integrated Sensor Hub */
uint8_t integrated_sensor_hub_enable;
+
+ /* I2C bus configuration */
+ struct apollolake_i2c_config i2c[APOLLOLAKE_I2C_DEV_MAX];
};
#endif /* _SOC_APOLLOLAKE_CHIP_H_ */
diff --git a/src/soc/intel/apollolake/i2c.c b/src/soc/intel/apollolake/i2c.c
new file mode 100644
index 0000000..1c16a06
--- /dev/null
+++ b/src/soc/intel/apollolake/i2c.c
@@ -0,0 +1,126 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 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; 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 <arch/acpi_device.h>
+#include <arch/acpigen.h>
+#include <device/device.h>
+#include <device/i2c.h>
+#include <device/pci.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <soc/i2c.h>
+#include <soc/intel/common/lpss_i2c.h>
+#include <soc/pci_devs.h>
+#include <soc/pci_ids.h>
+#include "chip.h"
+
+uintptr_t lpss_i2c_base_address(unsigned bus)
+{
+ unsigned devfn;
+ struct device *dev;
+ struct resource *res;
+
+ /* bus -> devfn */
+ devfn = i2c_bus_to_devfn(bus);
+ if (devfn >= 0) {
+ /* devfn -> dev */
+ dev = dev_find_slot(0, devfn);
+ if (dev) {
+ /* dev -> bar0 */
+ res = find_resource(dev, PCI_BASE_ADDRESS_0);
+ if (res)
+ return res->base;
+ }
+ }
+
+ return (uintptr_t)NULL;
+}
+
+static int i2c_dev_to_bus(struct device *dev)
+{
+ return i2c_devfn_to_bus(dev->path.pci.devfn);
+}
+
+/*
+ * The device should already be enabled and out of reset,
+ * either from early init in coreboot or FSP-S.
+ */
+static void i2c_dev_init(struct device *dev)
+{
+ struct soc_intel_apollolake_config *config = dev->chip_info;
+ const struct lpss_i2c_speed_config *sptr;
+ enum i2c_speed speed;
+ int i, bus = i2c_dev_to_bus(dev);
+
+ if (!config || bus < 0)
+ return;
+
+ speed = config->i2c[bus].speed ? : I2C_SPEED_FAST;
+ lpss_i2c_init(bus, speed);
+
+ /* Apply custom speed config if it has been set by the board */
+ for (i = 0; i < LPSS_I2C_SPEED_CONFIG_COUNT; i++) {
+ sptr = &config->i2c[bus].speed_config[i];
+ if (sptr->speed == speed) {
+ lpss_i2c_set_speed_config(bus, sptr);
+ break;
+ }
+ }
+}
+
+static void i2c_fill_ssdt(struct device *dev)
+{
+ struct soc_intel_apollolake_config *config = dev->chip_info;
+ int bus = i2c_dev_to_bus(dev);
+
+ if (!config || bus < 0)
+ return;
+
+ acpigen_write_scope(acpi_device_path(dev));
+ lpss_i2c_acpi_fill_ssdt(config->i2c[bus].speed_config);
+ acpigen_pop_len();
+}
+
+static struct i2c_bus_operations i2c_bus_ops = {
+ .dev_to_bus = &i2c_dev_to_bus,
+};
+
+static struct device_operations i2c_dev_ops = {
+ .read_resources = &pci_dev_read_resources,
+ .set_resources = &pci_dev_set_resources,
+ .enable_resources = &pci_dev_enable_resources,
+ .scan_bus = &scan_smbus,
+ .ops_i2c_bus = &i2c_bus_ops,
+ .init = &i2c_dev_init,
+ .acpi_fill_ssdt_generator = &i2c_fill_ssdt,
+};
+
+static const unsigned short pci_device_ids[] = {
+ PCI_DEVICE_ID_APOLLOLAKE_I2C0,
+ PCI_DEVICE_ID_APOLLOLAKE_I2C1,
+ PCI_DEVICE_ID_APOLLOLAKE_I2C2,
+ PCI_DEVICE_ID_APOLLOLAKE_I2C3,
+ PCI_DEVICE_ID_APOLLOLAKE_I2C4,
+ PCI_DEVICE_ID_APOLLOLAKE_I2C5,
+ PCI_DEVICE_ID_APOLLOLAKE_I2C6,
+ PCI_DEVICE_ID_APOLLOLAKE_I2C7,
+ 0,
+};
+
+static const struct pci_driver pch_i2c __pci_driver = {
+ .ops = &i2c_dev_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .devices = pci_device_ids,
+};
diff --git a/src/soc/intel/apollolake/i2c_early.c b/src/soc/intel/apollolake/i2c_early.c
new file mode 100644
index 0000000..968e993
--- /dev/null
+++ b/src/soc/intel/apollolake/i2c_early.c
@@ -0,0 +1,116 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 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; 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 <arch/io.h>
+#include <commonlib/helpers.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/i2c.h>
+#include <device/pci_def.h>
+#include <soc/intel/common/lpss_i2c.h>
+#include <soc/i2c.h>
+#include <soc/iomap.h>
+#include <soc/pci_devs.h>
+#include "chip.h"
+
+static int i2c_early_init_bus(unsigned bus)
+{
+ ROMSTAGE_CONST struct soc_intel_apollolake_config *config;
+ ROMSTAGE_CONST struct device *tree_dev;
+ const struct lpss_i2c_speed_config *sptr;
+ enum i2c_speed speed;
+ pci_devfn_t dev;
+ unsigned devfn;
+ uintptr_t base;
+ uint32_t value;
+ void *reg;
+
+ /* Find the PCI device for this bus controller */
+ devfn = i2c_bus_to_devfn(bus);
+ if (devfn < 0) {
+ printk(BIOS_ERR, "I2C%u device not found\n", bus);
+ return -1;
+ }
+
+ /* Look up the controller device in the devicetree */
+ dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ tree_dev = dev_find_slot(0, devfn);
+ if (!tree_dev || !tree_dev->enabled) {
+ printk(BIOS_ERR, "I2C%u device not enabled\n", bus);
+ return -1;
+ }
+
+ /* Skip if not enabled for early init */
+ config = tree_dev->chip_info;
+ if (!config || !config->i2c[bus].early_init) {
+ printk(BIOS_ERR, "I2C%u not enabled for early init\n", bus);
+ return -1;
+ }
+
+ /* Prepare early base address for access before memory */
+ base = PRERAM_I2C_BASE_ADDRESS(bus);
+ pci_write_config32(dev, PCI_BASE_ADDRESS_0, base);
+ pci_write_config32(dev, PCI_COMMAND,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+ /* Take device out of reset */
+ reg = (void *)(base + I2C_LPSS_REG_RESET);
+ value = read32(reg);
+ value |= I2C_LPSS_RESET_RELEASE_HC;
+ write32(reg, value);
+
+ /* Initialize the controller */
+ speed = config->i2c[bus].speed ? : I2C_SPEED_FAST;
+ if (lpss_i2c_init(bus, speed) < 0) {
+ printk(BIOS_ERR, "I2C%u failed to initialize\n", bus);
+ return -1;
+ }
+
+ /* Apply custom speed config if it has been set by the board */
+ for (value = 0; value < LPSS_I2C_SPEED_CONFIG_COUNT; value++) {
+ sptr = &config->i2c[bus].speed_config[value];
+ if (sptr->speed == speed) {
+ lpss_i2c_set_speed_config(bus, sptr);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+uintptr_t lpss_i2c_base_address(unsigned bus)
+{
+ unsigned devfn;
+ pci_devfn_t dev;
+ uintptr_t base;
+
+ /* Find device+function for this controller */
+ devfn = i2c_bus_to_devfn(bus);
+ if (devfn < 0)
+ return (uintptr_t)NULL;
+
+ /* Form a PCI address for this device */
+ dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+ /* Read the first base address for this device */
+ base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), 16);
+
+ /* Attempt to initialize bus if base is not set yet */
+ if (!base && !i2c_early_init_bus(bus))
+ base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0),
+ 16);
+
+ return base;
+}
diff --git a/src/soc/intel/apollolake/include/soc/i2c.h b/src/soc/intel/apollolake/include/soc/i2c.h
new file mode 100644
index 0000000..da700f2
--- /dev/null
+++ b/src/soc/intel/apollolake/include/soc/i2c.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2016 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.
+ */
+
+#ifndef _SOC_APOLLOLAKE_I2C_H_
+#define _SOC_APOLLOLAKE_I2C_H_
+
+#include <device/pci_def.h>
+#include <soc/pci_devs.h>
+
+/* I2C Controller Reset in MMIO private region */
+#define I2C_LPSS_REG_RESET 0x204
+#define I2C_LPSS_RESET_RELEASE_HC ((1 << 1) | (1 << 0))
+#define I2C_LPSS_RESET_RELEASE_IDMA (1 << 2)
+
+/* Convert I2C bus number to PCI device and function */
+static inline int i2c_bus_to_devfn(unsigned bus)
+{
+ if (bus >= 0 && bus <= 3)
+ return PCI_DEVFN(LPSS_DEV_SLOT_I2C_D0, bus);
+ else if (bus >= 4 && bus <= 7)
+ return PCI_DEVFN(LPSS_DEV_SLOT_I2C_D1, (bus - 4));
+ else
+ return -1;
+}
+
+/* Convert PCI device and function to I2C bus number */
+static inline int i2c_devfn_to_bus(unsigned devfn)
+{
+ if (PCI_SLOT(devfn) == LPSS_DEV_SLOT_I2C_D0)
+ return PCI_FUNC(devfn);
+ else if (PCI_SLOT(devfn) == LPSS_DEV_SLOT_I2C_D1)
+ return PCI_FUNC(devfn) + 4;
+ else
+ return -1;
+}
+
+#endif /* _SOC_APOLLOLAKE_I2C_H_ */
diff --git a/src/soc/intel/apollolake/include/soc/iomap.h b/src/soc/intel/apollolake/include/soc/iomap.h
index 716c2a6..e9caeca 100644
--- a/src/soc/intel/apollolake/include/soc/iomap.h
+++ b/src/soc/intel/apollolake/include/soc/iomap.h
@@ -31,6 +31,9 @@
#define PMC_BAR1 0xfe044000
/* Temporary BAR for SPI until PCI enumeration assigns a BAR in ramstage. */
-#define PRERAM_SPI_BASE_ADDRESS 0xfe010000
+#define PRERAM_SPI_BASE_ADDRESS 0xfe010000
+
+/* Temporary BAR for early I2C bus access */
+#define PRERAM_I2C_BASE_ADDRESS(x) (0xfe020000 + (0x1000 * (x)))
#endif /* _SOC_APOLLOLAKE_IOMAP_H_ */
Duncan Laurie (dlaurie(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15521
-gerrit
commit c9360847990aba71f1d183002a669cb582a418d0
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Thu Jun 30 14:37:37 2016 -0700
acpi_device: Have acpi_device_scope() use a separate buffer
Have the different acpi_device_ path functions use a different static
buffer so they can be called interchangeably.
Change-Id: I270a80f66880861d5847bd586a16a73f8f1e2511
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
---
src/arch/x86/acpi_device.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/arch/x86/acpi_device.c b/src/arch/x86/acpi_device.c
index 940d871..f8f6a6d 100644
--- a/src/arch/x86/acpi_device.c
+++ b/src/arch/x86/acpi_device.c
@@ -121,10 +121,15 @@ const char *acpi_device_path(struct device *dev)
/* Return the path of the parent device as the ACPI Scope for this device */
const char *acpi_device_scope(struct device *dev)
{
+ static char buf[DEVICE_PATH_MAX] = {};
+
if (!dev || !dev->bus || !dev->bus->dev)
return NULL;
- return acpi_device_path(dev->bus->dev);
+ if (acpi_device_path_fill(dev->bus->dev, buf, sizeof(buf), 0) <= 0)
+ return NULL;
+
+ return buf;
}
/* Concatentate the device path and provided name suffix */
Duncan Laurie (dlaurie(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15520
-gerrit
commit 63b3d58503a635f8bfc51e1f37f784ff94c0ce8c
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Thu Jun 30 09:34:24 2016 -0700
soc/intel/skylake: Add function for gpio_t to ACPI pin translation
Add the function defined in gpio.h to translate a gpio_t into a
value for use in an ACPI GPIO pin table.
For skylake this just returns the gpio_t value as the pins are
translated directly and they are all in the same ACPI device.
Change-Id: I00fad1cafec2f2d63dce9f7779063be0532649c7
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
---
src/soc/intel/skylake/gpio.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/soc/intel/skylake/gpio.c b/src/soc/intel/skylake/gpio.c
index 78495c6..5b9babf 100644
--- a/src/soc/intel/skylake/gpio.c
+++ b/src/soc/intel/skylake/gpio.c
@@ -408,3 +408,8 @@ const char *gpio_acpi_path(gpio_t gpio_num)
{
return "\\_SB.PCI0.GPIO";
}
+
+uint16_t gpio_acpi_pin(gpio_t gpio_num)
+{
+ return gpio_num;
+}
the following patch was just integrated into master:
commit e1a022ade46a6b8885e52b680f790235547242d8
Author: Jonathan Neuschäfer <j.neuschaefer(a)gmx.net>
Date: Thu Jun 30 00:32:02 2016 +0200
util/kconfig: Fix gconfig build
This linker error was the problem:
build/util/kconfig/zconf.tab.o: In function `conf_read_simple':
/home/jn/dev/coreboot/util/kconfig/confdata.c:413: undefined reference to `kconfig_warnings'
/home/jn/dev/coreboot/util/kconfig/confdata.c:413: undefined reference to `kconfig_warnings'
build/util/kconfig/zconf.tab.o: In function `sym_calc_value':
/home/jn/dev/coreboot/util/kconfig/symbol.c:388: undefined reference to `kconfig_warnings'
/home/jn/dev/coreboot/util/kconfig/symbol.c:388: undefined reference to `kconfig_warnings'
collect2: error: ld returned 1 exit status
/home/jn/dev/coreboot/util/kconfig/Makefile:339: recipe for target 'build/util/kconfig/gconf' failed
make: *** [build/util/kconfig/gconf] Error 1
Change-Id: I4a667c7c15b35618fb9ad536f2be5044b8031ab4
Signed-off-by: Jonathan Neuschäfer <j.neuschaefer(a)gmx.net>
Reviewed-on: https://review.coreboot.org/15505
Tested-by: build bot (Jenkins)
Reviewed-by: Idwer Vollering <vidwer(a)gmail.com>
Reviewed-by: Patrick Georgi <pgeorgi(a)google.com>
See https://review.coreboot.org/15505 for details.
-gerrit
the following patch was just integrated into master:
commit 222381e390191d7a4476642ae0e544c96349a096
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Tue Jun 21 10:41:19 2016 -0700
skylake: Generate ACPI timing values for I2C devices
Have the Skylake SOC generate ACPI timing values for the enabled I2C
controllers instead of passing it in the DSDT with static timings.
The timing values are generated from the controller clock speed and
are more accurate than the hardcoded values that were in the ASL which
were originally copied from Broadwell where the controller is running
at a different clock speed...
Additionally it is now possible for a board to override the values
using devicetree.cb. If zero is passed in for SCL HCNT or LCNT then
the kernel will generate its own timing using the same forumla, but if
the SDA hold time value is zero the kernel will NOT generate a correct
value and the SDA hold time may be incorrect.
This was tested on the Chell platform to ensure all the I2C devices on
the board are still operational with these new timing values.
Change-Id: I4feb3df9e083592792f8fadd7105e081a984a906
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
Reviewed-on: https://review.coreboot.org/15291
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
See https://review.coreboot.org/15291 for details.
-gerrit