Werner Zeh (werner.zeh(a)siemens.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15516
-gerrit
commit 268dd2ab07b0b15886c94bd744e271bd9b8985ba
Author: Werner Zeh <werner.zeh(a)siemens.com>
Date: Wed Jun 29 07:53:47 2016 +0200
intel/i210: Change API for function mainboard_get_mac_address()
The function mainboard_get_mac_address() is used to get a MAC address
for a given i210 PCI device. Instead of passing pure numbers for PCI
bus, device and function pass the device pointer to this function. In
this way the function can retrieve the needed values itself as well as
have the pointer to the device tree so that PCI path can be evaluated
there.
Change-Id: I2335d995651baa5e23a0448f5f32310dcd394f9b
Signed-off-by: Werner Zeh <werner.zeh(a)siemens.com>
---
src/drivers/intel/i210/i210.c | 10 +---------
src/drivers/intel/i210/i210.h | 8 ++++++++
src/mainboard/siemens/mc_tcu3/mainboard.c | 5 ++---
src/vendorcode/siemens/hwilib/hwilib.h | 5 +++--
4 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/src/drivers/intel/i210/i210.c b/src/drivers/intel/i210/i210.c
index c5e0c4e..c55eecc 100644
--- a/src/drivers/intel/i210/i210.c
+++ b/src/drivers/intel/i210/i210.c
@@ -14,20 +14,13 @@
*/
#include "i210.h"
-#include <device/device.h>
#include <console/console.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <string.h>
-#include <types.h>
#include <delay.h>
-/* We need one function we can call to get a MAC address to use */
-/* This function can be coded somewhere else but must exist. */
-extern enum cb_err mainboard_get_mac_address(uint16_t bus, uint8_t devfn,
- uint8_t mac[6]);
-
/* This is a private function to wait for a bit mask in a given register */
/* To avoid endless loops, a time-out is implemented here. */
static int wait_done(uint32_t* reg, uint32_t mask)
@@ -202,8 +195,7 @@ static void init(struct device *dev)
enum cb_err status;
/*Check first whether there is a valid MAC address available */
- status = mainboard_get_mac_address(dev->bus->subordinate,
- dev->path.pci.devfn, adr_to_set);
+ status = mainboard_get_mac_address(dev, adr_to_set);
if (status != CB_SUCCESS) {
printk(BIOS_ERR, "I210: No valid MAC address found\n");
return;
diff --git a/src/drivers/intel/i210/i210.h b/src/drivers/intel/i210/i210.h
index b19b584..e3179b7 100644
--- a/src/drivers/intel/i210/i210.h
+++ b/src/drivers/intel/i210/i210.h
@@ -16,6 +16,9 @@
#ifndef _INTEL_I210_H_
#define _INTEL_I210_H_
+#include <types.h>
+#include <device/device.h>
+
#define I210_PCI_MEM_BAR_OFFSET 0x10
#define I210_REG_EECTRL 0x12010 /* Offset for EEPROM control reg */
#define I210_FLUPD 0x800000 /* Start flash update bit */
@@ -38,4 +41,9 @@
#define I210_CHECKSUM_ERROR 0x00000010
#define I210_FLASH_UPDATE_ERROR 0x00000020
+/* We need one function we can call to get a MAC address to use */
+/* This function can be coded somewhere else but must exist. */
+extern enum cb_err mainboard_get_mac_address(struct device *dev,
+ uint8_t mac[6]);
+
#endif /* _INTEL_I210_H_ */
diff --git a/src/mainboard/siemens/mc_tcu3/mainboard.c b/src/mainboard/siemens/mc_tcu3/mainboard.c
index 009c34d..83a0ae0 100644
--- a/src/mainboard/siemens/mc_tcu3/mainboard.c
+++ b/src/mainboard/siemens/mc_tcu3/mainboard.c
@@ -35,12 +35,11 @@
/** \brief This function will search for a MAC address which can be assigned
* to a MACPHY.
- * @param pci_bdf Bus, device and function of the given PCI-device
+ * @param dev pointer to PCI device
* @param mac buffer where to store the MAC address
* @return cb_err CB_ERR or CB_SUCCESS
*/
-enum cb_err mainboard_get_mac_address(uint16_t bus, uint8_t devfn,
- uint8_t mac[6])
+extern enum cb_err mainboard_get_mac_address(struct device *dev, uint8_t mac[6])
{
uint8_t mac_adr[6];
uint32_t i;
diff --git a/src/vendorcode/siemens/hwilib/hwilib.h b/src/vendorcode/siemens/hwilib/hwilib.h
index d858091..9ccb3fe 100644
--- a/src/vendorcode/siemens/hwilib/hwilib.h
+++ b/src/vendorcode/siemens/hwilib/hwilib.h
@@ -17,6 +17,7 @@
#define SIEMENS_HWI_LIB_H_
#include <types.h>
+#include <device/device.h>
/* Declare all supported fields which can be get with hwilib. */
@@ -136,6 +137,6 @@ enum cb_err hwilib_find_blocks (const char *hwi_filename);
uint32_t hwilib_get_field (hwinfo_field_t field, uint8_t *data, uint32_t maxlen);
/* This functions needs to be implemented for every mainboard that uses i210. */
-enum cb_err mainboard_get_mac_address(uint16_t bus, uint8_t devfn,
- uint8_t mac[6]);
+extern enum cb_err mainboard_get_mac_address(struct device *dev,
+ uint8_t mac[6]);
#endif /* SIEMENS_HWI_LIB_H_ */
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 5a9ad5ee94a64e40c1e48191ee55ae80521ece47
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 varible, 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/15513
-gerrit
commit 29c3add5742097dac955f9c03b45d1c24326097b
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 verifiying 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
---
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 749c15b..8fd2967 100644
--- a/src/soc/intel/apollolake/Kconfig
+++ b/src/soc/intel/apollolake/Kconfig
@@ -21,6 +21,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..8a61eb7 100644
--- a/src/soc/intel/apollolake/gpio.c
+++ b/src/soc/intel/apollolake/gpio.c
@@ -115,6 +115,24 @@ void gpio_set(gpio_t gpio_num, int value)
iosf_write(comm->port, config_offset, reg);
}
+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;
+}
+
const char *gpio_acpi_path(gpio_t gpio_num)
{
const struct pad_community *comm = gpio_get_community(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/15512
-gerrit
commit 17c908cc8881c54167503a7525d802c200a7e2ff
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 funtion 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
---
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..ec229db 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 the
+ * input with no change.
+ */
+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..eeb6306 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 for ACPI pin is to return unmodified input */
+__attribute__((weak)) uint16_t gpio_acpi_pin(gpio_t gpio)
+{
+ return gpio;
+}
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 b39c47fdcdc653241b24ba2efb4bd3226f80fa66
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Mon Jun 27 11:05:16 2016 -0700
google/reef: ACPI: Move trackpad 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 d64598d..c271f78 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 beea3aac33bab98d97932ca42aa001480fe8c4cb
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 natuarlly 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 | 154 +++++++++++++++++++++++++++
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, 351 insertions(+), 2 deletions(-)
diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig
index 98ce7d8..749c15b 100644
--- a/src/soc/intel/apollolake/Kconfig
+++ b/src/soc/intel/apollolake/Kconfig
@@ -38,8 +38,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
@@ -93,6 +94,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 7326f14..c639eec 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
@@ -68,6 +70,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..78f8911
--- /dev/null
+++ b/src/soc/intel/apollolake/i2c.c
@@ -0,0 +1,154 @@
+/*
+ * 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 <string.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;
+ struct lpss_i2c_speed_config *sptr, sgen;
+ int i, bus = i2c_dev_to_bus(dev);
+ enum i2c_speed speeds[LPSS_I2C_SPEED_CONFIG_COUNT] = {
+ I2C_SPEED_STANDARD,
+ I2C_SPEED_FAST,
+ I2C_SPEED_FAST_PLUS,
+ I2C_SPEED_HIGH,
+ };
+
+ if (!config || bus < 0)
+ return;
+
+ /* I2C device is defined in the DSDT so use existing device scope */
+ acpigen_write_scope(acpi_device_path(dev));
+
+ /* Report timing values for the OS driver */
+ for (i = 0; i < LPSS_I2C_SPEED_CONFIG_COUNT; i++) {
+ /* Generate speed config for default case */
+ if (lpss_i2c_gen_speed_config(speeds[i], &sgen) < 0)
+ continue;
+
+ /* Apply board specific override for this speed if found */
+ for (sptr = config->i2c[bus].speed_config;
+ sptr && sptr->speed; sptr++) {
+ if (sptr->speed == speeds[i]) {
+ memcpy(&sgen, sptr, sizeof(sgen));
+ break;
+ }
+ }
+
+ /* Generate ACPI based on selected speed config */
+ lpss_i2c_acpi_write_speed_config(&sgen);
+ }
+
+ 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_ */
the following patch was just integrated into master:
commit 66c20c4dfa0e84b4998b4125dfe153f9c9e09c13
Author: Werner Zeh <werner.zeh(a)siemens.com>
Date: Tue Jun 28 14:31:30 2016 +0200
vendorcode/siemens: Add extended info block support to hwilib
Add support for a fourth info block type to hwilib. This block
provides new values and is now variable in length.
Change-Id: Ia928b4a98b806ba3e80fb576b78f60bb8f2ea3fc
Signed-off-by: Werner Zeh <werner.zeh(a)siemens.com>
Reviewed-on: https://review.coreboot.org/15478
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin(a)chromium.org>
See https://review.coreboot.org/15478 for details.
-gerrit
Werner Zeh (werner.zeh(a)siemens.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15495
-gerrit
commit ab703e064e5d4ae46dc6ad94a90107149e5bb61b
Author: Werner Zeh <werner.zeh(a)siemens.com>
Date: Wed Jun 29 07:17:21 2016 +0200
fsp_broadwell_de: Enable Super I/O address range decode
If there is an external 16550 like UART, one needs to enable
the appropriate address ranges before console_init() is called
so that the init sequence can reach the external UART. Otherwise
the UART will only start working in ramstage and will produce
unreadable characters in romstage due to the lack of initialization.
Tested-on: Siemens MC_BDX1
Change-Id: Iafc5b5b6df14916c5ed778928521d4a8f539cf46
Signed-off-by: Werner Zeh <werner.zeh(a)siemens.com>
---
src/soc/intel/fsp_broadwell_de/include/soc/lpc.h | 4 +++-
src/soc/intel/fsp_broadwell_de/romstage/romstage.c | 7 +++++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/soc/intel/fsp_broadwell_de/include/soc/lpc.h b/src/soc/intel/fsp_broadwell_de/include/soc/lpc.h
index 2c02ebd..0408f7f 100644
--- a/src/soc/intel/fsp_broadwell_de/include/soc/lpc.h
+++ b/src/soc/intel/fsp_broadwell_de/include/soc/lpc.h
@@ -21,6 +21,8 @@
#define REVID 0x08
#define PIRQ_RCR1 0x60
#define PIRQ_RCR2 0x68
+#define LPC_IO_DEC 0x80
+#define LPC_EN 0x82
#define GEN_PMCON_1 0xA0
#define GEN_PMCON_2 0xA2
#define GEN_PMCON_3 0xA4
@@ -83,4 +85,4 @@
#define TCO_TMR_HALT (1 << 11)
#define TCO_TMR 0x70
-#endif /* _SOC_LPC_H_ */
\ No newline at end of file
+#endif /* _SOC_LPC_H_ */
diff --git a/src/soc/intel/fsp_broadwell_de/romstage/romstage.c b/src/soc/intel/fsp_broadwell_de/romstage/romstage.c
index dc883a4..64a262d 100644
--- a/src/soc/intel/fsp_broadwell_de/romstage/romstage.c
+++ b/src/soc/intel/fsp_broadwell_de/romstage/romstage.c
@@ -48,6 +48,13 @@ static void init_rtc(void)
void *asmlinkage main(FSP_INFO_HEADER *fsp_info_header)
{
post_code(0x40);
+ if (!IS_ENABLED(CONFIG_INTEGRATED_UART)) {
+ /* Enable decoding of I/O locations for Super I/O devices */
+ pci_write_config16(PCI_DEV(0x0, LPC_DEV, LPC_FUNC),
+ LPC_IO_DEC, 0x0010);
+ pci_write_config16(PCI_DEV(0x0, LPC_DEV, LPC_FUNC),
+ LPC_EN, 0x340f);
+ }
console_init();
init_rtc();