Duncan Laurie (dlaurie(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15017
-gerrit
commit cc24c90c546daa81d8e60607df19d17180ec9483
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Wed May 11 11:27:47 2016 -0700
generic: Add a Maxim 98357A codec driver
The Maxim Integrated 98357A codec is an I2S slave device that has no
control channel for configuration and instead provides a GPIO that is
used for channel selection and power down. This means it does not fit
into a bus hierarchy easily and is instead represented as a generic
device and found with a static bus scan using the devicetree.
This driver provides configuration options for passing the "sdmode" GPIO
descriptor as well as a second option for "sdmode delay" which can
configure the timing of the sdmode toggling in relation to the I2S
channel output.
In addition an GPIO can be provided to indicate to the driver whether
this device is present or not. This can be used for board designs that
may have different codec possibilities that are selected by HW strap.
Sample usage for this device driver:
device pci 1f.3 on
chip drivers/generic/max98357a
register "sdmode_gpio" = "ACPI_GPIO_OUTPUT(GPP_C6)"
register "sdmode_delay" = "100"
device generic 0 on end
end
end
Will result in the following code in the SSDT:
Scope (\_SB.PCI0.HDAS) {
Device (MAXM) {
Name (_HID, "MX98357A")
Name (_UID, Zero)
Name (_DDN, "Maxim Integrated 98357A Amplifier")
Method (_STA) { Return (0xF) }
Name (_CRS, ResourceTemplate () {
GpioIo (Exclusive, PullDefault, 0, 0, IoRestrictionOutputOnly,
"\\_SB.PCI0.GPIO", 0, ResourceConsumer)
})
Name (_DSD, Package () {
ToUUID ("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () { "maxim,sdmode-gpio", \_SB.PCI0.HDAS.MAXM, 0, 0, 0 }
Package () { "maxim,sdmode-delay", 100 }
Package () { "sdmode-delay", 100 }
}
})
}
}
Change-Id: Ia0bafe49bea9bbe4a3cc0f9f9cdb6f6390da57b5
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
---
src/drivers/generic/max98357a/Kconfig | 2 +
src/drivers/generic/max98357a/Makefile.inc | 1 +
src/drivers/generic/max98357a/chip.h | 13 ++++
src/drivers/generic/max98357a/max98357a.c | 109 +++++++++++++++++++++++++++++
4 files changed, 125 insertions(+)
diff --git a/src/drivers/generic/max98357a/Kconfig b/src/drivers/generic/max98357a/Kconfig
new file mode 100644
index 0000000..a7104f1
--- /dev/null
+++ b/src/drivers/generic/max98357a/Kconfig
@@ -0,0 +1,2 @@
+config DRIVERS_GENERIC_MAX98357A
+ bool
diff --git a/src/drivers/generic/max98357a/Makefile.inc b/src/drivers/generic/max98357a/Makefile.inc
new file mode 100644
index 0000000..529e24a
--- /dev/null
+++ b/src/drivers/generic/max98357a/Makefile.inc
@@ -0,0 +1 @@
+ramstage-$(CONFIG_DRIVERS_GENERIC_MAX98357A) += max98357a.c
diff --git a/src/drivers/generic/max98357a/chip.h b/src/drivers/generic/max98357a/chip.h
new file mode 100644
index 0000000..0abd616
--- /dev/null
+++ b/src/drivers/generic/max98357a/chip.h
@@ -0,0 +1,13 @@
+#include <arch/acpi_device.h>
+
+struct drivers_generic_max98357a_config {
+ /* SDMODE GPIO */
+ struct acpi_gpio sdmode_gpio;
+
+ /* SDMODE Delay */
+ unsigned sdmode_delay;
+
+ /* GPIO used to indicate if this device is present */
+ unsigned device_present_gpio;
+ unsigned device_present_gpio_invert;
+};
diff --git a/src/drivers/generic/max98357a/max98357a.c b/src/drivers/generic/max98357a/max98357a.c
new file mode 100644
index 0000000..331df4c
--- /dev/null
+++ b/src/drivers/generic/max98357a/max98357a.c
@@ -0,0 +1,109 @@
+/*
+ * 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 <console/console.h>
+#include <device/device.h>
+#include <device/path.h>
+#include <gpio.h>
+#include <stdint.h>
+#include <string.h>
+#include "chip.h"
+
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+
+#define MAX98357A_ACPI_NAME "MAXM"
+#define MAX98357A_ACPI_HID "MX98357A"
+
+static void max98357a_fill_ssdt(struct device *dev)
+{
+ struct drivers_generic_max98357a_config *config = dev->chip_info;
+ const char *path = acpi_device_path(dev);
+
+ if (!dev->enabled || !path)
+ return;
+
+ /* Device */
+ acpigen_write_scope(acpi_device_scope(dev));
+ acpigen_write_device(acpi_device_name(dev));
+ acpigen_write_name_string("_HID", MAX98357A_ACPI_HID);
+ acpigen_write_name_integer("_UID", 0);
+ acpigen_write_name_string("_DDN", dev->chip_ops->name);
+ acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
+
+ /* Resources */
+ acpigen_write_name("_CRS");
+ acpigen_write_resourcetemplate_header();
+ acpi_device_write_gpio(&config->sdmode_gpio);
+ acpigen_write_resourcetemplate_footer();
+
+ /* _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 */
+ acpi_dp_write_integer("sdmode-delay", config->sdmode_delay);
+ acpi_dp_write_footer();
+
+ acpigen_pop_len(); /* Device */
+ acpigen_pop_len(); /* Scope */
+
+ printk(BIOS_INFO, "%s: %s\n", path, dev->chip_ops->name);
+}
+
+static const char *max98357a_acpi_name(struct device *dev)
+{
+ return MAX98357A_ACPI_NAME;
+}
+#endif
+
+static struct device_operations max98357a_ops = {
+ .read_resources = DEVICE_NOOP,
+ .set_resources = DEVICE_NOOP,
+ .enable_resources = DEVICE_NOOP,
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+ .acpi_name = &max98357a_acpi_name,
+ .acpi_fill_ssdt_generator = &max98357a_fill_ssdt,
+#endif
+};
+
+static void max98357a_enable(struct device *dev)
+{
+ struct drivers_generic_max98357a_config *config = dev->chip_info;
+
+ /* Check if device is present by reading GPIO */
+ if (config->device_present_gpio) {
+ int present = gpio_get(config->device_present_gpio);
+ present ^= config->device_present_gpio_invert;
+
+ printk(BIOS_INFO, "%s is %spresent\n",
+ dev->chip_ops->name, present ? "" : "not ");
+
+ if (!present) {
+ dev->enabled = 0;
+ return;
+ }
+ }
+
+ dev->ops = &max98357a_ops;
+}
+
+struct chip_operations drivers_generic_max98357a_ops = {
+ CHIP_NAME("Maxim Integrated 98357A Amplifier")
+ .enable_dev = &max98357a_enable
+};
Duncan Laurie (dlaurie(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15016
-gerrit
commit 6acd74329393b77224c08ca0a668ec9ce99676a0
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Wed May 11 09:50:59 2016 -0700
i2c: Add a generic i2c driver
This adds a generic I2C driver that can be described in the devicetree
and used to generate ACPI objects in the SSDT based on the information
provided in the config registers.
The I2C bus can be configured and the device can provide an interrupt and
wake capability to the OS. A configuration option allows for a GPIO to
be provided that will be checked to determine if the device is preset on
the board before including it in the generated SSDT.
The driver is generic enough to be used for basic I2C devices that do
not have special configuration needs such as touchpads, touchscreens,
sensors, some audio codec/amplifiers, etc.
Sample usage for a touchpad device:
device pci 15.1 on
chip drivers/i2c/generic
register "hid" = ""ELAN0000""
register "desc" = "ELAN Touchpad"
register "irq" = "IRQ_EDGE_LOW(GPP_B3_IRQ)"
register "wake" = "GPE0_DW0_05"
device i2c 15.0 on end
end
end
Will result in the following code in the SSDT:
Scope (\_SB.PCI0.I2C1) {
Device (D015) {
Name (_HID, "ELAN0000")
Name (_UID, 0)
Name (_S0W, 4)
Name (_PRW, Package () { 5, 3 })
Method (_STA) { Return (0x0f) }
Name (_CRS, ResourceTemplate () {
I2cSerialBus (0x15, ControllerInitiated, 400000, AddressingMode7Bit,
"\\_S.PCI0.I2C1", 0, ResourceConsumer)
Interrupt (ResourceConsumer, Edge, ActiveLow) { 51 }
})
}
}
Change-Id: Ib32055720835b70e91ede5e4028ecd91894d70d5
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
---
src/drivers/i2c/generic/Kconfig | 2 +
src/drivers/i2c/generic/Makefile.inc | 1 +
src/drivers/i2c/generic/chip.h | 16 +++++
src/drivers/i2c/generic/generic.c | 124 +++++++++++++++++++++++++++++++++++
4 files changed, 143 insertions(+)
diff --git a/src/drivers/i2c/generic/Kconfig b/src/drivers/i2c/generic/Kconfig
new file mode 100644
index 0000000..a4c0104
--- /dev/null
+++ b/src/drivers/i2c/generic/Kconfig
@@ -0,0 +1,2 @@
+config DRIVERS_I2C_GENERIC
+ bool
diff --git a/src/drivers/i2c/generic/Makefile.inc b/src/drivers/i2c/generic/Makefile.inc
new file mode 100644
index 0000000..86cbc7b
--- /dev/null
+++ b/src/drivers/i2c/generic/Makefile.inc
@@ -0,0 +1 @@
+ramstage-$(CONFIG_DRIVERS_I2C_GENERIC) += generic.c
diff --git a/src/drivers/i2c/generic/chip.h b/src/drivers/i2c/generic/chip.h
new file mode 100644
index 0000000..84657d5
--- /dev/null
+++ b/src/drivers/i2c/generic/chip.h
@@ -0,0 +1,16 @@
+#include <arch/acpi_device.h>
+#include <device/i2c.h>
+
+struct drivers_i2c_generic_config {
+ const char *hid; /* ACPI _HID (required) */
+ const char *name; /* ACPI Device Name */
+ const char *desc; /* Device Description */
+ unsigned uid; /* ACPI _UID */
+ enum i2c_speed speed; /* Bus speed in Hz, default is I2C_SPEED_FAST */
+ unsigned wake; /* Wake GPE */
+ struct acpi_irq irq; /* Interrupt */
+
+ /* GPIO used to indicate if this device is present */
+ unsigned device_present_gpio;
+ unsigned device_present_gpio_invert;
+};
diff --git a/src/drivers/i2c/generic/generic.c b/src/drivers/i2c/generic/generic.c
new file mode 100644
index 0000000..1c10b0e
--- /dev/null
+++ b/src/drivers/i2c/generic/generic.c
@@ -0,0 +1,124 @@
+/*
+ * 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 <console/console.h>
+#include <device/i2c.h>
+#include <device/device.h>
+#include <device/path.h>
+#include <gpio.h>
+#include <stdint.h>
+#include <string.h>
+#include "chip.h"
+
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+static void i2c_generic_fill_ssdt(struct device *dev)
+{
+ struct drivers_i2c_generic_config *config = dev->chip_info;
+ const char *scope = acpi_device_scope(dev);
+ struct acpi_i2c i2c = {
+ .address = dev->path.i2c.device,
+ .mode_10bit = dev->path.i2c.mode_10bit,
+ .speed = config->bus_speed ? : I2C_SPEED_FAST,
+ .resource = scope,
+ };
+
+ if (!dev->enabled || !scope)
+ return;
+
+ if (!config->hid) {
+ printk(BIOS_ERR, "%s: ERROR: HID required\n", dev_path(dev));
+ return;
+ }
+
+ /* Device */
+ acpigen_write_scope(scope);
+ acpigen_write_device(acpi_device_name(dev));
+ acpigen_write_name_string("_HID", config->hid);
+ acpigen_write_name_integer("_UID", config->uid);
+ acpigen_write_name_string("_DDN", config->desc);
+ acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
+
+ /* Resources */
+ acpigen_write_name("_CRS");
+ acpigen_write_resourcetemplate_header();
+ acpi_device_write_i2c(&i2c);
+ acpi_device_write_interrupt(&config->irq);
+ acpigen_write_resourcetemplate_footer();
+
+ /* Wake capabilities */
+ if (config->wake) {
+ acpigen_write_name_integer("_S0W", 4);
+ acpigen_write_PRW(config->wake, 3);
+ }
+
+ acpigen_pop_len(); /* Device */
+ acpigen_pop_len(); /* Scope */
+
+ printk(BIOS_INFO, "%s: %s at %s\n", acpi_device_path(dev),
+ config->desc ? : dev->chip_ops->name, dev_path(dev));
+}
+
+/* Use name specified in config or build one from I2C address */
+static const char *i2c_generic_acpi_name(struct device *dev)
+{
+ struct drivers_i2c_generic_config *config = dev->chip_info;
+ static char name[5];
+
+ if (config->name)
+ return name;
+
+ snprintf(name, sizeof(name), "D%03.3X", dev->path.i2c.device);
+ name[4] = '\0';
+ return name;
+}
+#endif
+
+static struct device_operations i2c_generic_ops = {
+ .read_resources = DEVICE_NOOP,
+ .set_resources = DEVICE_NOOP,
+ .enable_resources = DEVICE_NOOP,
+#if IS_ENABLED(CONFIG_HAVE_ACPI_TABLES)
+ .acpi_name = &i2c_generic_acpi_name,
+ .acpi_fill_ssdt_generator = &i2c_generic_fill_ssdt,
+#endif
+};
+
+static void i2c_generic_enable(struct device *dev)
+{
+ struct drivers_i2c_generic_config *config = dev->chip_info;
+
+ /* Check if device is present by reading GPIO */
+ if (config->device_present_gpio) {
+ int present = gpio_get(config->device_present_gpio);
+ present ^= config->device_present_gpio_invert;
+
+ printk(BIOS_INFO, "%s is %spresent\n",
+ dev->chip_ops->name, present ? "" : "not ");
+
+ if (!present) {
+ dev->enabled = 0;
+ return;
+ }
+ }
+
+ dev->ops = &i2c_generic_ops;
+}
+
+struct chip_operations drivers_i2c_generic_ops = {
+ CHIP_NAME("I2C Device")
+ .enable_dev = &i2c_generic_enable
+};
Duncan Laurie (dlaurie(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15018
-gerrit
commit 6540fc4a4e6b2fc76245aa2aa33e6f060b8b001b
Author: Duncan Laurie <dlaurie(a)chromium.org>
Date: Wed May 11 13:52:43 2016 -0700
wrdd: Export WRDD info in the header
Export the WRDD spec revision and WiFi domain type in the header
file so it can be used to generate ACPI tables by wifi drivers.
Change-Id: I3222eca723c52fe74a004aa7bac7167264249fd1
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
---
src/include/wrdd.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/include/wrdd.h b/src/include/wrdd.h
index 97fa5dc..0ede015 100644
--- a/src/include/wrdd.h
+++ b/src/include/wrdd.h
@@ -18,6 +18,12 @@
#include <stdint.h>
+/* WRDD Spec Revision */
+#define WRDD_REVISION 0x0
+
+/* Domain type */
+#define WRDD_DOMAIN_TYPE_WIFI 0x7
+
/* Default regulatory domain ID */
#define WRDD_DEFAULT_REGULATORY_DOMAIN 0x4150
/* INDONESIA regulatory domain ID */
Furquan Shaikh (furquan(a)google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15049
-gerrit
commit 16485c5a60e1592aaf8a383ed064ecd83220db69
Author: Furquan Shaikh <furquan(a)google.com>
Date: Wed Jun 1 15:09:21 2016 -0700
intel/apollolake: Clear TSEG reg early in bootblock
TSEG register comes out of reset with a non-zero default value. This
causes issues when cbmem_top returns non-zero value based on TSEG read
before DRAM is initialized. Thus, clear TSEG reg early in bootblock to
avoid unwanted side-effects.
Change-Id: Id3c6c270774108e4caf56e2a07c5072edc65bb58
Signed-off-by: Furquan Shaikh <furquan(a)google.com>
---
src/soc/intel/apollolake/bootblock/bootblock.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/soc/intel/apollolake/bootblock/bootblock.c b/src/soc/intel/apollolake/bootblock/bootblock.c
index b8d6f22..68ce7ab 100644
--- a/src/soc/intel/apollolake/bootblock/bootblock.c
+++ b/src/soc/intel/apollolake/bootblock/bootblock.c
@@ -60,6 +60,12 @@ void asmlinkage bootblock_c_entry(uint32_t tsc_hi, uint32_t tsc_lo)
/* Set PCI Express BAR */
pci_io_write_config32(dev, PCIEXBAR, CONFIG_MMCONF_BASE_ADDRESS | 1);
+ /*
+ * Clear TSEG register - TSEG register comes out of reset with a
+ * non-zero default value. Clear this register to ensure that there are
+ * no surprises in CBMEM handling.
+ */
+ pci_write_config32(dev, TSEG, 0);
dev = P2SB_DEV;
/* BAR and MMIO enable for IOSF, so that GPIOs can be configured */
Furquan Shaikh (furquan(a)google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15045
-gerrit
commit bb9bc4398420b06fca1102e547dbef7a80b6193c
Author: Furquan Shaikh <furquan(a)google.com>
Date: Wed Jun 1 01:53:18 2016 -0700
cbfs: Use NO_XIP_EARLY_STAGES to decide if stage is XIP
Modern platforms like Apollolake do not use XIP for early stages. In
such cases, cbfs_prog_stage_load should check for NO_XIP_EARLY_STAGES
instead of relying on ARCH_X86 to decide if a stage is XIP.
Change-Id: I1729ce82b5f678ce8c37256090fcf353cc22b1ec
Signed-off-by: Furquan Shaikh <furquan(a)google.com>
---
src/Kconfig | 3 +--
src/lib/cbfs.c | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/Kconfig b/src/Kconfig
index f93c2cc..6e6e944 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -204,8 +204,7 @@ config NO_XIP_EARLY_STAGES
default n if ARCH_X86
default y
help
- Identify if --xip parameter needs to be passed into cbfstool for early
- stages.
+ Identify if early stages are eXecute-In-Place(XIP).
config EARLY_CBMEM_INIT
def_bool !LATE_CBMEM_INIT
diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c
index 764a6f7..aa652c2 100644
--- a/src/lib/cbfs.c
+++ b/src/lib/cbfs.c
@@ -192,7 +192,7 @@ int cbfs_prog_stage_load(struct prog *pstage)
/* Hacky way to not load programs over read only media. The stages
* that would hit this path initialize themselves. */
- if (ENV_VERSTAGE && IS_ENABLED(CONFIG_ARCH_X86) &&
+ if (ENV_VERSTAGE && !IS_ENABLED(CONFIG_NO_XIP_EARLY_STAGES) &&
IS_ENABLED(CONFIG_SPI_FLASH_MEMORY_MAPPED)) {
void *mapping = rdev_mmap(fh, foffset, fsize);
rdev_munmap(fh, mapping);