Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/977
-gerrit
commit 9bf656b94d245b89d388fc63ff5512f32ad7b4ee
Author: Stefan Reinauer <reinauer(a)chromium.org>
Date: Mon Apr 30 16:42:07 2012 -0700
Fix SATA port map to only enable port 0
The sata controller comes up in legacy/normal mode and
is currently put into AHCI mode in romstage.
If that is removed and the controller is left alone until the
ramstage driver (like we do on Stumpy/Lumpy) then the resource
allocator will have configured the device for IDE mode with an
IO address in BAR5. Then when the ramstage driver puts the
controller into AHCI mode it will not have the correct resources
to do the rest of the AHCI setup.
So the controller mode needs to be changed in the enable stage
rather than in the init phase. This same register contains
the port map and it is a R/WO (write once) field so the configured
port map must be written at the same time. For non-AHCI mode
the devicetree map was ignored before but it is used now.
Since the port map register is now written at enable step it
does not need to be written again during init.
With this change the sata port map can be reduced to just port 0
and then U-boot does not have to probe all available ports.
Change-Id: I977952cd88797ab4cea79202e832ecbb5c37e0bd
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
---
src/southbridge/intel/bd82x6x/sata.c | 29 ++++++++++++++++++++++-------
1 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/src/southbridge/intel/bd82x6x/sata.c b/src/southbridge/intel/bd82x6x/sata.c
index ce5aea9..93dff91 100644
--- a/src/southbridge/intel/bd82x6x/sata.c
+++ b/src/southbridge/intel/bd82x6x/sata.c
@@ -48,8 +48,6 @@ static void sata_init(struct device *dev)
if (config->ide_legacy_combined) {
printk(BIOS_DEBUG, "SATA controller in combined mode.\n");
- /* Combine IDE - SATA configuration */
- pci_write_config16(dev, 0x90, 0x0000);
/* No AHCI: clear AHCI base */
pci_write_config32(dev, 0x24, 0x00000000);
@@ -88,9 +86,6 @@ static void sata_init(struct device *dev)
u32 abar;
printk(BIOS_DEBUG, "SATA controller in AHCI mode.\n");
- /* Set Sata Controller Mode. */
- pci_write_config16(dev, 0x90, 0x0060 |
- ((config->sata_port_map ^ 0x3f) << 8));
/* Set Interrupt Line */
/* Interrupt Pin is set by D31IP.PIP */
@@ -143,8 +138,6 @@ static void sata_init(struct device *dev)
write32(abar + 0xa0, reg32);
} else {
printk(BIOS_DEBUG, "SATA controller in plain mode.\n");
- /* Set Sata Controller Mode. No Mapping(?) */
- pci_write_config16(dev, 0x90, 0x0000);
/* No AHCI: clear AHCI base */
pci_write_config32(dev, 0x24, 0x00000000);
@@ -191,6 +184,27 @@ static void sata_init(struct device *dev)
}
}
+static void sata_enable(device_t dev)
+{
+ /* Get the chip configuration */
+ config_t *config = dev->chip_info;
+ u16 map = 0;
+
+ if (!config)
+ return;
+
+ /*
+ * Set SATA controller mode early so the resource allocator can
+ * properly assign IO/Memory resources for the controller.
+ */
+ if (config->sata_ahci)
+ map = 0x0060;
+
+ map |= (config->sata_port_map ^ 0x3f) << 8;
+
+ pci_write_config16(dev, 0x90, map);
+}
+
static void sata_set_subsystem(device_t dev, unsigned vendor, unsigned device)
{
if (!vendor || !device) {
@@ -211,6 +225,7 @@ static struct device_operations sata_ops = {
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = sata_init,
+ .enable = sata_enable,
.scan_bus = 0,
.ops_pci = &sata_pci_ops,
};
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/975
-gerrit
commit 22fe62dc4d4f662d067719bbac23dfb92891820e
Author: Vadim Bendebury <vbendeb(a)chromium.org>
Date: Wed Apr 18 15:47:32 2012 -0700
Sandybridge: Display platform information early
It is important to have the system configuration reported as early as
possible to have a better idea what exact chipset the platform is
running with.
This change adds code to have an early coreboot module report the CPU
and PCH information. CPU info includes the 32 bit feature information
word, the symbolic processor brand string, and information about some
features support, as obtained through CPUID instructions.
The PCH information includes the symbolic device name and PCI device
version.
Change-Id: If6c21ad5ffb76d7d57d89f4f87d04bdd7192480a
Signed-off-by: Vadim Bendebury <vbendeb(a)chromium.org>
---
src/northbridge/intel/sandybridge/Makefile.inc | 1 +
src/northbridge/intel/sandybridge/raminit.c | 2 +
.../intel/sandybridge/report_platform.c | 103 ++++++++++++++++++++
src/northbridge/intel/sandybridge/sandybridge.h | 1 +
4 files changed, 107 insertions(+), 0 deletions(-)
diff --git a/src/northbridge/intel/sandybridge/Makefile.inc b/src/northbridge/intel/sandybridge/Makefile.inc
index b72e9fa..79aa6ea 100644
--- a/src/northbridge/intel/sandybridge/Makefile.inc
+++ b/src/northbridge/intel/sandybridge/Makefile.inc
@@ -25,6 +25,7 @@ ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += acpi.c
romstage-y += udelay.c
romstage-y += raminit.c
romstage-y += early_init.c
+romstage-y += report_platform.c
romstage-y += ../../../arch/x86/lib/walkcbfs.S
smm-$(CONFIG_HAVE_SMI_HANDLER) += udelay.c
diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c
index bbb743f..e1d5d26 100644
--- a/src/northbridge/intel/sandybridge/raminit.c
+++ b/src/northbridge/intel/sandybridge/raminit.c
@@ -318,6 +318,8 @@ void sdram_initialize(struct pei_data *pei_data)
const char *target = "mrc.bin";
unsigned long entry;
+ report_platform_info();
+
/* Wait for ME to be ready */
intel_early_me_init();
intel_early_me_uma_size();
diff --git a/src/northbridge/intel/sandybridge/report_platform.c b/src/northbridge/intel/sandybridge/report_platform.c
new file mode 100644
index 0000000..d59cfe9
--- /dev/null
+++ b/src/northbridge/intel/sandybridge/report_platform.c
@@ -0,0 +1,103 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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; 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.
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <arch/cpu.h>
+#include <string.h>
+#include "southbridge/intel/bd82x6x/pch.h"
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include "sandybridge.h"
+
+static void report_cpu_info(void)
+{
+ struct cpuid_result cpuidr;
+ u32 i, index;
+ char cpu_string[50]; /* 48 bytes are reported */
+ int vt, txt, aes;
+ const char *mode[] = {"NOT ", ""};
+
+ index = 0x80000000;
+ cpuidr = cpuid(index);
+ if (cpuidr.eax < 0x80000004) {
+ strcpy(cpu_string, "Platform info not available");
+ } else {
+ u32 *p = (u32*) cpu_string;
+ for (i = 2; i <= 4 ; i++) {
+ cpuidr = cpuid(index + i);
+ *p++ = cpuidr.eax;
+ *p++ = cpuidr.ebx;
+ *p++ = cpuidr.ecx;
+ *p++ = cpuidr.edx;
+ }
+ }
+ cpuidr = cpuid(1);
+ printk(BIOS_DEBUG, "CPU id(%x): %s\n", cpuidr.eax, cpu_string);
+ aes = (cpuidr.ecx & (1 << 25)) ? 1 : 0;
+ txt = (cpuidr.ecx & (1 << 6)) ? 1 : 0;
+ vt = (cpuidr.ecx & (1 << 5)) ? 1 : 0;
+ printk(BIOS_DEBUG, "AES %ssupported, TXT %ssupported, VT %ssupported\n",
+ mode[aes], mode[txt], mode[vt]);
+}
+
+/* The PCI id name match comes from Intel document 472178 */
+static struct {
+ u16 dev_id;
+ const char *dev_name;
+} pch_table [] = {
+ {0x1E41, "Desktop Sample"},
+ {0x1E47, "Q77"},
+ {0x1E48, "Q75"},
+ {0x1E49, "B75"},
+ {0x1E44, "Z77"},
+ {0x1E46, "Z75"},
+ {0x1E4A, "H77"},
+ {0x1E53, "C216"},
+ {0x1E42, "Mobile Sample"},
+ {0x1E55, "QM77"},
+ {0x1E58, "UM77"},
+ {0x1E57, "HM77"},
+ {0x1E59, "HM76"},
+ {0x1E5d, "HM75"},
+ {0x1E43, "SFF Sample"},
+ {0x1E56, "QS77"},
+};
+
+static void report_pch_info(void)
+{
+ int i;
+ u16 dev_id = pci_read_config16(PCH_LPC_DEV, 2);
+
+
+ const char *pch_type = "Unknown";
+ for (i = 0; i < ARRAY_SIZE(pch_table); i++) {
+ if (pch_table[i].dev_id == dev_id) {
+ pch_type = pch_table[i].dev_name;
+ break;
+ }
+ }
+ printk (BIOS_DEBUG, "PCH type: %s rev id %x\n",
+ pch_type, pci_read_config8(PCH_LPC_DEV, 8));
+}
+
+void report_platform_info(void)
+{
+ report_cpu_info();
+ report_pch_info();
+}
diff --git a/src/northbridge/intel/sandybridge/sandybridge.h b/src/northbridge/intel/sandybridge/sandybridge.h
index 9ff6555..1aa3a11 100644
--- a/src/northbridge/intel/sandybridge/sandybridge.h
+++ b/src/northbridge/intel/sandybridge/sandybridge.h
@@ -218,6 +218,7 @@ void dump_pci_device(unsigned dev);
void dump_pci_devices(void);
void dump_spd_registers(void);
void dump_mem(unsigned start, unsigned end);
+void report_platform_info(void);
#endif /* !__SMM__ */
#endif
#endif
Stefan Reinauer (stefan.reinauer(a)coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/972
-gerrit
commit d3884c83a8cc31b3b3bae3eee92e4d429d4c8d52
Author: Stefan Reinauer <reinauer(a)chromium.org>
Date: Mon Apr 30 16:33:44 2012 -0700
Fix TPM driver to work with multiple vendor TPMs
Port u-boot patch for low-level driver:
- Fix bug in traversal of vendor name list.
- Sending "command ready" needs additional logic to handle
TPMs that need that bit set twice: once to empty the read
FIFOs and once to actualy set command ready.
Change-Id: I57c280266b2e966c5b90e4f9e968426a33b93cf1
Signed-off-by: Duncan Laurie <dlaurie(a)chromium.org>
---
src/drivers/pc80/tpm.c | 85 ++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 75 insertions(+), 10 deletions(-)
diff --git a/src/drivers/pc80/tpm.c b/src/drivers/pc80/tpm.c
index 17e1ed7..c7b5081 100644
--- a/src/drivers/pc80/tpm.c
+++ b/src/drivers/pc80/tpm.c
@@ -127,13 +127,31 @@ struct vendor_name {
const struct device_name* dev_names;
};
+static const struct device_name atmel_devices[] = {
+ {0x3204, "AT97SC3204"},
+ {0xffff}
+};
+
static const struct device_name infineon_devices[] = {
- {0xb, "SLB9635 TT 1.2"},
- {0}
+ {0x000b, "SLB9635 TT 1.2"},
+ {0xffff}
+};
+
+static const struct device_name nuvoton_devices[] = {
+ {0x00fe, "NPCT420AA V2"},
+ {0xffff}
+};
+
+static const struct device_name stmicro_devices[] = {
+ {0x0000, "ST33ZP24" },
+ {0xffff}
};
static const struct vendor_name vendor_names[] = {
+ {0x1114, "Atmel", atmel_devices},
{0x15d1, "Infineon", infineon_devices},
+ {0x1050, "Nuvoton", nuvoton_devices},
+ {0x104a, "ST Microelectronics", stmicro_devices},
};
/*
@@ -208,6 +226,44 @@ static u32 tis_wait_reg(u8 reg, u8 locality, u8 mask, u8 expected)
}
/*
+ * PC Client Specific TPM Interface Specification section 11.2.12:
+ *
+ * Software must be prepared to send two writes of a "1" to command ready
+ * field: the first to indicate successful read of all the data, thus
+ * clearing the data from the ReadFIFO and freeing the TPM's resources,
+ * and the second to indicate to the TPM it is about to send a new command.
+ *
+ * In practice not all TPMs behave the same so it is necessary to be
+ * flexible when trying to set command ready.
+ *
+ * Returns 0 on success if the TPM is ready for transactions.
+ * Returns TPM_TIMEOUT_ERR if the command ready bit does not get set.
+ */
+static int tis_command_ready(u8 locality)
+{
+ u32 status;
+
+ /* 1st attempt to set command ready */
+ tpm_write(TIS_STS_COMMAND_READY, locality, TIS_REG_STS);
+
+ /* Wait for response */
+ status = tpm_read(locality, TIS_REG_STS);
+
+ /* Check if command ready is set yet */
+ if (status & TIS_STS_COMMAND_READY)
+ return 0;
+
+ /* 2nd attempt to set command ready */
+ tpm_write(TIS_STS_COMMAND_READY, locality, TIS_REG_STS);
+
+ /* Wait for command ready to get set */
+ status = tis_wait_reg(TIS_REG_STS, locality,
+ TIS_STS_COMMAND_READY, TIS_STS_COMMAND_READY);
+
+ return (status == TPM_TIMEOUT_ERR) ? TPM_TIMEOUT_ERR : 0;
+}
+
+/*
* Probe the TPM device and try determining its manufacturer/device name.
*
* Returns 0 on success (the device is found or was found during an earlier
@@ -215,15 +271,17 @@ static u32 tis_wait_reg(u8 reg, u8 locality, u8 mask, u8 expected)
*/
static u32 tis_probe(void)
{
- u32 didvid = tpm_read(0, TIS_REG_DID_VID);
- int i;
const char *device_name = "unknown";
const char *vendor_name = device_name;
+ const struct device_name *dev;
+ u32 didvid;
u16 vid, did;
+ int i;
if (vendor_dev_id)
return 0; /* Already probed. */
+ didvid = tpm_read(0, TIS_REG_DID_VID);
if (!didvid || (didvid == 0xffffffff)) {
printf("%s: No TPM device found\n", __FUNCTION__);
return TPM_DRIVER_ERR;
@@ -238,11 +296,13 @@ static u32 tis_probe(void)
u16 known_did;
if (vid == vendor_names[i].vendor_id) {
vendor_name = vendor_names[i].vendor_name;
+ } else {
+ continue;
}
- while ((known_did = vendor_names[i].dev_names[j].dev_id) != 0) {
+ dev = &vendor_names[i].dev_names[j];
+ while ((known_did = dev->dev_id) != 0xffff) {
if (known_did == did) {
- device_name =
- vendor_names[i].dev_names[j].dev_name;
+ device_name = dev->dev_name;
break;
}
j++;
@@ -250,7 +310,7 @@ static u32 tis_probe(void)
break;
}
/* this will have to be converted into debug printout */
- TPM_DEBUG("Found TPM %s by %s\n", device_name, vendor_name);
+ printf("Found TPM %s by %s\n", device_name, vendor_name);
return 0;
}
@@ -446,7 +506,8 @@ static u32 tis_readresponse(u8 *buffer, size_t *len)
}
/* Tell the TPM that we are done. */
- tpm_write(TIS_STS_COMMAND_READY, locality, TIS_REG_STS);
+ if (tis_command_ready(locality) == TPM_TIMEOUT_ERR)
+ return TPM_DRIVER_ERR;
*len = offset;
return 0;
@@ -492,7 +553,11 @@ int tis_open(void)
return TPM_DRIVER_ERR;
}
- tpm_write(TIS_STS_COMMAND_READY, locality, TIS_REG_STS);
+ /* Certain TPMs seem to need some delay here or they hang... */
+ udelay(10);
+
+ if (tis_command_ready(locality) == TPM_TIMEOUT_ERR)
+ return TPM_DRIVER_ERR;
return 0;
}