41 changes: 39 additions & 2 deletions src/device/xhci.c
@@ -1,9 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */

#include <device/xhci.h>
#include <arch/mmio.h>
#include <console/console.h>
#include <device/pci_def.h>
#include <arch/mmio.h>
#include <device/xhci.h>
#include <string.h>

union xhci_ext_caps_header {
uint32_t val;
Expand Down Expand Up @@ -75,6 +76,42 @@ enum cb_err xhci_for_each_ext_cap(const struct device *device, void *context,
return CB_SUCCESS;
}

struct supported_usb_cap_context {
void *context;
void (*callback)(void *context, const struct xhci_supported_protocol *data);
};

static void xhci_supported_usb_cap_handler(void *context, const struct xhci_ext_cap *cap)
{
const struct xhci_supported_protocol *data;
struct supported_usb_cap_context *internal_context = context;

if (cap->cap_id != XHCI_ECP_CAP_ID_SUPP)
return;

data = &cap->supported_protocol;

if (memcmp(data->name, "USB ", 4)) {
printk(BIOS_DEBUG, "%s: Unknown Protocol: %.*s\n", __func__,
(int)sizeof(data->name), data->name);
return;
}

internal_context->callback(internal_context->context, data);
}

enum cb_err xhci_for_each_supported_usb_cap(
const struct device *device, void *context,
void (*callback)(void *context, const struct xhci_supported_protocol *data))
{
struct supported_usb_cap_context internal_context = {
.context = context,
.callback = callback,
};

return xhci_for_each_ext_cap(device, &internal_context, xhci_supported_usb_cap_handler);
}

void xhci_print_supported_protocol(const struct xhci_supported_protocol *supported_protocol)
{
printk(BIOS_DEBUG, "xHCI Supported Protocol:\n");
Expand Down
6 changes: 6 additions & 0 deletions src/drivers/amd/agesa/romstage.c
Expand Up @@ -107,3 +107,9 @@ asmlinkage void car_stage_entry(void)
{
romstage_main();
}

void *cbmem_top_chipset(void)
{
/* Top of CBMEM is at highest usable DRAM address below 4GiB. */
return (void *)restore_top_of_low_cacheable();
}
@@ -1,3 +1,3 @@
config DRIVERS_GENERIC_GENERIC
config DRIVERS_AMD_I2S_MACHINE_DEV
bool
depends on HAVE_ACPI_TABLES
1 change: 1 addition & 0 deletions src/drivers/amd/i2s_machine_dev/Makefile.inc
@@ -0,0 +1 @@
ramstage-$(CONFIG_DRIVERS_AMD_I2S_MACHINE_DEV) += i2s_machine_dev.c
19 changes: 19 additions & 0 deletions src/drivers/amd/i2s_machine_dev/chip.h
@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */

#ifndef __DRIVERS_AMD_I2S_MACHINE_DEV_H__
#define __DRIVERS_AMD_I2S_MACHINE_DEV_H__

#include <acpi/acpi_device.h>

struct drivers_amd_i2s_machine_dev_config {
/* ACPI _HID (required) */
const char *hid;

/* ACPI _UID */
unsigned int uid;

/* DMIC select GPIO (required) */
struct acpi_gpio dmic_select_gpio;
};

#endif /* ___DRIVERS_AMD_I2S_MACHINE_DEV_H__ */
92 changes: 92 additions & 0 deletions src/drivers/amd/i2s_machine_dev/i2s_machine_dev.c
@@ -0,0 +1,92 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */

#include <acpi/acpi_device.h>
#include <acpi/acpigen.h>
#include <device/device.h>
#include <string.h>
#include "chip.h"
#include <console/console.h>

#define AMD_I2S_ACPI_DESC "I2S machine driver"

static void i2s_machine_dev_fill_ssdt(const struct device *dev)
{
const char *scope = acpi_device_scope(dev);
struct acpi_dp *dsd;
const struct acpi_gpio *dmic_select_gpio;
const struct drivers_amd_i2s_machine_dev_config *cfg;
const char *path = acpi_device_path(dev);

cfg = config_of(dev);

dmic_select_gpio = &cfg->dmic_select_gpio;

if (cfg->hid == NULL) {
printk(BIOS_ERR, "%s: ERROR: HID required\n", dev_path(dev));
return;
}

if (dmic_select_gpio->pin_count == 0) {
printk(BIOS_ERR, "%s: ERROR: DMIC select GPIO required\n", dev_path(dev));
return;
}

acpigen_write_scope(scope); /* Scope */
acpigen_write_device(acpi_device_name(dev)); /* Device */
acpigen_write_name_string("_HID", cfg->hid);
acpigen_write_name_integer("_UID", cfg->uid);
acpigen_write_name_string("_DDN", AMD_I2S_ACPI_DESC);

acpigen_write_STA(acpi_device_status(dev));

/* Resources */
acpigen_write_name("_CRS");
acpigen_write_resourcetemplate_header();
acpi_device_write_gpio(dmic_select_gpio);
acpigen_write_resourcetemplate_footer();

dsd = acpi_dp_new_table("_DSD");
/*
* This GPIO is used to select DMIC0 or DMIC1 by the kernel driver. It does not
* really have a polarity since low and high control the selection of DMIC and
* hence does not have an active polarity.
* Kernel driver does not use the polarity field and instead treats the GPIO
* selection as follows:
* Set low (0) = Select DMIC0
* Set high (1) = Select DMIC1
*/
acpi_dp_add_gpio(dsd, "dmic-gpios", path,
0, /* Index = 0 (There is a single GPIO entry in _CRS). */
0, /* Pin = 0 (There is a single pin in the GPIO resource). */
0); /* Active low = 0 (Kernel driver does not use active polarity). */
acpi_dp_write(dsd);

acpigen_pop_len(); /* Device */
acpigen_pop_len(); /* Scope */

printk(BIOS_INFO, "%s: %s at %s\n", path, AMD_I2S_ACPI_DESC, dev_path(dev));
}

static const char *i2s_machine_dev_acpi_name(const struct device *dev)
{
static char name[5];
snprintf(name, sizeof(name), "I2S%X", dev->path.generic.id);
return name;
}

static struct device_operations i2s_machine_dev_ops = {
.read_resources = noop_read_resources,
.set_resources = noop_set_resources,
.acpi_name = i2s_machine_dev_acpi_name,
.acpi_fill_ssdt = i2s_machine_dev_fill_ssdt,
};

static void i2s_machine_dev_enable(struct device *dev)
{
dev->ops = &i2s_machine_dev_ops;
}

struct chip_operations drivers_amd_i2s_machine_dev_ops = {
CHIP_NAME("AMD I2S Machine Device")
.enable_dev = i2s_machine_dev_enable
};
40 changes: 0 additions & 40 deletions src/drivers/dec/21143/21143.c

This file was deleted.

2 changes: 0 additions & 2 deletions src/drivers/dec/21143/Kconfig

This file was deleted.

5 changes: 0 additions & 5 deletions src/drivers/dec/21143/Makefile.inc

This file was deleted.

1 change: 0 additions & 1 deletion src/drivers/generic/generic/Makefile.inc

This file was deleted.

35 changes: 0 additions & 35 deletions src/drivers/generic/generic/chip.h

This file was deleted.

83 changes: 0 additions & 83 deletions src/drivers/generic/generic/generic.c

This file was deleted.

28 changes: 26 additions & 2 deletions src/drivers/generic/gpio_keys/chip.h
Expand Up @@ -24,6 +24,28 @@ enum {
EV_ACT_DEASSERTED,
};

enum {
/*
* GPIO key uses SCI route to wake the system from suspend state. This is typically used
* when the input line is dual routed i.e. one for IRQ and other for SCI or if the GPIO
* controller is capable of handling the filtering for IRQ and SCI separately. This
* requires "wake" property to be provided by the board which represents the GPE # for
* wake. It is exposed as _PRW in ACPI tables.
*/
WAKEUP_ROUTE_SCI,
/*
* GPIO key uses GPIO controller IRQ route for wake. This is used when IRQ and wake are
* routed to the same pad and the GPIO controller is not capable of handling the trigger
* filtering separately for IRQ and wake. Kernel driver for gpio-keys takes care of
* reconfiguring the IRQ trigger as both edges when used in S0 and the edge requested by
* BIOS (as per wakeup_event_action) when entering suspend. In this case, _PRW is not
* exposed for the key device.
*/
WAKEUP_ROUTE_GPIO_IRQ,
/* GPIO key does not support wake. */
WAKEUP_ROUTE_DISABLED,
};

/* Details of the child node defining key */
struct key_info {
/* Device name of the child node - Mandatory */
Expand All @@ -37,8 +59,10 @@ struct key_info {
uint32_t linux_input_type;
/* Descriptive name of the key */
const char *label;
/* Wake GPE */
unsigned int wake;
/* Wakeup route (if any) for the key. See WAKEUP_ROUTE_* macros above. */
unsigned int wakeup_route;
/* Wake GPE -- SCI GPE # for wake. Required for WAKEUP_ROUTE_SCI. */
unsigned int wake_gpe;
/* Trigger for Wakeup Event Action as defined in EV_ACT_* enum */
unsigned int wakeup_event_action;
/* Can this key be disabled? */
Expand Down
9 changes: 6 additions & 3 deletions src/drivers/generic/gpio_keys/gpio_keys.c
Expand Up @@ -26,9 +26,12 @@ static struct acpi_dp *gpio_keys_add_child_node(
key->linux_input_type);
if (key->label)
acpi_dp_add_string(dsd, "label", key->label);
if (key->wake) {

if (key->wakeup_route == WAKEUP_ROUTE_SCI)
acpigen_write_PRW(key->wake_gpe, 3);

if (key->wakeup_route != WAKEUP_ROUTE_DISABLED) {
acpi_dp_add_integer(dsd, "wakeup-source", 1);
acpigen_write_PRW(key->wake, 3);
acpi_dp_add_integer(dsd, "wakeup-event-action",
key->wakeup_event_action);
}
Expand All @@ -40,7 +43,7 @@ static struct acpi_dp *gpio_keys_add_child_node(
acpi_dp_add_integer(dsd, "debounce-interval",
key->debounce_interval);
acpi_dp_add_gpio(dsd, "gpios", parent_path, 0, 0,
config->gpio.polarity);
config->gpio.active_low);

return dsd;
}
Expand Down
5 changes: 0 additions & 5 deletions src/drivers/generic/gpio_regulator/Kconfig

This file was deleted.

3 changes: 0 additions & 3 deletions src/drivers/generic/gpio_regulator/Makefile.inc

This file was deleted.

14 changes: 0 additions & 14 deletions src/drivers/generic/gpio_regulator/chip.h

This file was deleted.

75 changes: 0 additions & 75 deletions src/drivers/generic/gpio_regulator/gpio_regulator.c

This file was deleted.

2 changes: 1 addition & 1 deletion src/drivers/generic/max98357a/max98357a.c
Expand Up @@ -51,7 +51,7 @@ static void max98357a_fill_ssdt(const struct device *dev)
path = acpi_device_path(dev);
dp = acpi_dp_new_table("_DSD");
acpi_dp_add_gpio(dp, "sdmode-gpio", path, 0, 0,
config->sdmode_gpio.polarity);
config->sdmode_gpio.active_low);
acpi_dp_add_integer(dp, "sdmode-delay", config->sdmode_delay);
acpi_dp_write(dp);

Expand Down
2 changes: 0 additions & 2 deletions src/drivers/i2c/adt7463/Kconfig

This file was deleted.

1 change: 0 additions & 1 deletion src/drivers/i2c/adt7463/Makefile.inc

This file was deleted.

82 changes: 0 additions & 82 deletions src/drivers/i2c/adt7463/adt7463.c

This file was deleted.

1 change: 0 additions & 1 deletion src/drivers/i2c/at24rf08c/at24rf08c.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <types.h>
#include <device/device.h>
#include <device/smbus.h>
#include <console/console.h>
Expand Down
7 changes: 3 additions & 4 deletions src/drivers/i2c/generic/generic.c
Expand Up @@ -114,16 +114,15 @@ void i2c_generic_fill_ssdt(const struct device *dev,
if (irq_gpio_index != -1)
acpi_dp_add_gpio(dsd, "irq-gpios", path,
irq_gpio_index, 0,
config->irq_gpio.polarity ==
ACPI_GPIO_ACTIVE_LOW);
config->irq_gpio.active_low);
if (reset_gpio_index != -1)
acpi_dp_add_gpio(dsd, "reset-gpios", path,
reset_gpio_index, 0,
config->reset_gpio.polarity);
config->reset_gpio.active_low);
if (enable_gpio_index != -1)
acpi_dp_add_gpio(dsd, "enable-gpios", path,
enable_gpio_index, 0,
config->enable_gpio.polarity);
config->enable_gpio.active_low);
/* Add generic property list */
acpi_dp_add_property_list(dsd, config->property_list,
config->property_count);
Expand Down
1 change: 0 additions & 1 deletion src/drivers/i2c/rt1011/chip.h
Expand Up @@ -4,7 +4,6 @@
* Realtek RT1011 audio codec devicetree bindings
*/

#include <stdint.h>

struct drivers_i2c_rt1011_config {
const char *name; /* ACPI Device Name */
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/i2c/rt5663/rt5663.c
Expand Up @@ -53,7 +53,7 @@ static void rt5663_fill_ssdt(const struct device *dev)
dp = acpi_dp_new_table("_DSD");
if (config->irq_gpio.pin_count)
acpi_dp_add_gpio(dp, "irq-gpios", acpi_device_path(dev), 0, 0,
config->irq_gpio.polarity == ACPI_GPIO_ACTIVE_LOW);
config->irq_gpio.active_low);
RT5663_DP_INT("dc_offset_l_manual", config->dc_offset_l_manual);
RT5663_DP_INT("dc_offset_r_manual", config->dc_offset_r_manual);
RT5663_DP_INT("dc_offset_l_manual_mic", config->dc_offset_l_manual_mic);
Expand Down
2 changes: 0 additions & 2 deletions src/drivers/i2c/w83793/Kconfig

This file was deleted.

1 change: 0 additions & 1 deletion src/drivers/i2c/w83793/Makefile.inc

This file was deleted.

93 changes: 0 additions & 93 deletions src/drivers/i2c/w83793/chip.h

This file was deleted.

307 changes: 0 additions & 307 deletions src/drivers/i2c/w83793/w83793.c

This file was deleted.

6 changes: 0 additions & 6 deletions src/drivers/i2c/w83793/w83793.h

This file was deleted.

9 changes: 9 additions & 0 deletions src/drivers/intel/dptf/Kconfig
Expand Up @@ -5,3 +5,12 @@ config DRIVERS_INTEL_DPTF
help
When enabled, entries in the devicetree are used to generate
Intel DPTF Tables at runtime in the SSDT.

config DPTF_USE_EISA_HID
bool "If selected, use 'old' 7 character EISA IDs for DPTF _HID"
depends on DRIVERS_INTEL_DPTF
default n
help
When selected, all DPTF devices will use the "old" style of
_HIDs, which are 7-character EISA IDs. Otherwise, it will use
the "new" style, which are regular 8-character _HIDs.
47 changes: 47 additions & 0 deletions src/drivers/intel/dptf/chip.h
Expand Up @@ -3,7 +3,54 @@
#ifndef _DRIVERS_INTEL_DPTF_CHIP_H_
#define _DRIVERS_INTEL_DPTF_CHIP_H_

#include <acpi/acpigen_dptf.h>
#include <timer.h> /* for MSECS_PER_SEC */

#define DPTF_PASSIVE(src, tgt, tmp, prd) \
{.source = DPTF_##src, .target = DPTF_##tgt, .temp = (tmp), .period = (prd)}
#define DPTF_CRITICAL(src, tmp, typ) \
{.source = DPTF_##src, .temp = (tmp), .type = DPTF_CRITICAL_##typ}
#define TEMP_PCT(t, p) {.temp = (t), .fan_pct = (p)}

struct drivers_intel_dptf_config {
struct {
struct dptf_active_policy active[DPTF_MAX_ACTIVE_POLICIES];
struct dptf_critical_policy critical[DPTF_MAX_CRITICAL_POLICIES];
struct dptf_passive_policy passive[DPTF_MAX_PASSIVE_POLICIES];
} policies;

struct {
struct dptf_charger_perf charger_perf[DPTF_MAX_CHARGER_PERF_STATES];
struct dptf_fan_perf fan_perf[DPTF_MAX_FAN_PERF_STATES];
struct dptf_power_limits power_limits;
} controls;

/* Note that all values in this struct are optional */
struct {
struct {
/* True means _FSL is percentages, False means _FSL is Control values */
bool fine_grained_control;
/*
* Recommended minimum step size in percentage points to adjust fan
* speed when utilizing fine-grained control (1-9)
*/
uint8_t step_size;
/*
* True means the platform will issue a Notify (0x80) to the fan device
* if a a low fan speed is detected
*/
bool low_speed_notify;
} fan;
struct {
/*
* The amount of hysteresis implemented in circuitry or in the platform
* EC's firmware implementation (using the GTSH object)
*/
uint8_t hysteresis;
/* Name applied to TSR (using the _STR object) */
const char *desc;
} tsr[DPTF_MAX_TSR];
} options;
};

#endif /* _DRIVERS_INTEL_DPTF_CHIP_H_ */
228 changes: 214 additions & 14 deletions src/drivers/intel/dptf/dptf.c
Expand Up @@ -5,44 +5,244 @@
#include <device/device.h>
#include "chip.h"

/* Generic DPTF participants have a PTYP field to distinguish them */
enum dptf_generic_participant_type {
DPTF_GENERIC_PARTICIPANT_TYPE_TSR = 0x3,
DPTF_GENERIC_PARTICIPANT_TYPE_CHARGER = 0xB,
};

#define DEFAULT_CHARGER_STR "Battery Charger"

#define DPTF_DEVICE_HID_EISAID "INT3400"
#define GENERIC_HID_EISAID "INT3403"
#define FAN_HID_EISAID "INT3404"

#define DPTF_DEVICE_HID "INTC1040"
#define GENERIC_HID "INTC1043"
#define FAN_HID "INTC1044"

/*
* Helper method to determine if a device is "used" (called out anywhere as a source or a target
* of any policies, and therefore should be included in the ACPI tables.
*/
static bool is_participant_used(const struct drivers_intel_dptf_config *config,
enum dptf_participant participant)
{
int i;

/* Active? */
for (i = 0; i < DPTF_MAX_ACTIVE_POLICIES; ++i)
if (config->policies.active[i].target == participant)
return true;

/* Passive? */
for (i = 0; i < DPTF_MAX_PASSIVE_POLICIES; ++i)
if (config->policies.passive[i].source == participant ||
config->policies.passive[i].target == participant)
return true;

/* Critical? */
for (i = 0; i < DPTF_MAX_CRITICAL_POLICIES; ++i)
if (config->policies.critical[i].source == participant)
return true;

/* Check fan as well (its use is implicit in the Active policy) */
if (participant == DPTF_FAN && config->policies.active[0].target != DPTF_NONE)
return true;

return false;
}

static const char *dptf_acpi_name(const struct device *dev)
{
return "DPTF";
}

/* Add custom tables and methods to SSDT */
static void dptf_fill_ssdt(const struct device *dev)
static int get_STA_value(const struct drivers_intel_dptf_config *config,
enum dptf_participant participant)
{
struct drivers_intel_dptf_config *config = dev->chip_info;
return is_participant_used(config, participant) ?
ACPI_STATUS_DEVICE_ALL_ON :
ACPI_STATUS_DEVICE_ALL_OFF;
}

printk(BIOS_INFO, "\\_SB.DPTF: %s at %s\n", dev->chip_ops->name, dev_path(dev));
/* Devices with GENERIC _HID (distinguished by PTYP) */
static void dptf_write_generic_participant(const char *name,
enum dptf_generic_participant_type ptype,
const char *str, int sta_val)
{
/* Auto-incrementing UID for generic participants */
static int generic_uid = 0;

acpigen_write_device(name);
acpigen_write_name("_HID");
if (CONFIG(DPTF_USE_EISA_HID))
acpigen_emit_eisaid(GENERIC_HID_EISAID);
else
acpigen_write_string(GENERIC_HID);

acpigen_write_name_integer("_UID", generic_uid++);
acpigen_write_STA(sta_val);

if (str)
acpigen_write_name_string("_STR", str);

acpigen_write_name_integer("PTYP", ptype);

acpigen_pop_len(); /* Device */
}

/* Add static definitions of DPTF devices into the DSDT */
static void dptf_inject_dsdt(const struct device *dev)
/* \_SB.PCI0.TCPU */
static void write_tcpu(const struct device *pci_dev,
const struct drivers_intel_dptf_config *config)
{
const struct drivers_intel_dptf_config *config;
/* DPTF CPU device - \_SB.PCI0.TCPU */
acpigen_write_scope(TCPU_SCOPE);
acpigen_write_device("TCPU");
acpigen_write_ADR_pci_device(pci_dev);
acpigen_write_STA(get_STA_value(config, DPTF_CPU));
acpigen_pop_len(); /* Device */
acpigen_pop_len(); /* TCPU Scope */
}

config = dev->chip_info;
acpigen_write_scope("\\_SB");
/* \_SB.DPTF.TFN1 */
static void write_fan(const struct drivers_intel_dptf_config *config)
{
acpigen_write_device("TFN1");
acpigen_write_name("_HID");
if (CONFIG(DPTF_USE_EISA_HID))
acpigen_emit_eisaid(FAN_HID_EISAID);
else
acpigen_write_string(FAN_HID);

acpigen_write_name_integer("_UID", 0);
acpigen_write_STA(get_STA_value(config, DPTF_FAN));
acpigen_pop_len(); /* Device */
}

/* \_SB.DPTF.xxxx */
static void write_generic_devices(const struct drivers_intel_dptf_config *config)
{
enum dptf_participant participant;
char name[ACPI_NAME_BUFFER_SIZE];
int i;

/* Toplevel DPTF device */
dptf_write_generic_participant("TCHG", DPTF_GENERIC_PARTICIPANT_TYPE_CHARGER,
DEFAULT_CHARGER_STR, get_STA_value(config,
DPTF_CHARGER));

for (i = 0, participant = DPTF_TEMP_SENSOR_0; i < 4; ++i, ++participant) {
snprintf(name, sizeof(name), "TSR%1d", i);
dptf_write_generic_participant(name, DPTF_GENERIC_PARTICIPANT_TYPE_TSR,
NULL, get_STA_value(config, participant));
}
}

/* \_SB.DPTF - note: leaves the Scope open for child devices*/
static void write_open_dptf_device(const struct device *dev)
{
acpigen_write_scope("\\_SB");
acpigen_write_device(acpi_device_name(dev));
acpigen_write_name("_HID");
acpigen_emit_eisaid("INT3400");
if (CONFIG(DPTF_USE_EISA_HID))
acpigen_emit_eisaid(DPTF_DEVICE_HID_EISAID);
else
acpigen_write_string(DPTF_DEVICE_HID);

acpigen_write_name_integer("_UID", 0);
dptf_write_STA();
acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON);
}

acpigen_pop_len(); /* DPTF Device */
/* Add minimal definitions of DPTF devices into the SSDT */
static void write_device_definitions(const struct device *dev)
{
const struct drivers_intel_dptf_config *config;
struct device *parent;

/* The CPU device gets an _ADR that matches the ACPI PCI address for 00:04.00 */
parent = dev && dev->bus ? dev->bus->dev : NULL;
if (!parent || parent->path.type != DEVICE_PATH_PCI) {
printk(BIOS_ERR, "%s: DPTF objects must live under 00:04.0 PCI device\n",
__func__);
return;
}

config = config_of(dev);
write_tcpu(parent, config);
write_open_dptf_device(dev);
write_fan(config);
write_generic_devices(config);

acpigen_pop_len(); /* DPTF Device (write_open_dptf_device) */
acpigen_pop_len(); /* Scope */
}

/* Emites policy definitions for each policy type */
static void write_policies(const struct drivers_intel_dptf_config *config)
{
dptf_write_enabled_policies(config->policies.active, DPTF_MAX_ACTIVE_POLICIES,
config->policies.passive, DPTF_MAX_PASSIVE_POLICIES,
config->policies.critical, DPTF_MAX_CRITICAL_POLICIES);

dptf_write_active_policies(config->policies.active,
DPTF_MAX_ACTIVE_POLICIES);

dptf_write_passive_policies(config->policies.passive,
DPTF_MAX_PASSIVE_POLICIES);

dptf_write_critical_policies(config->policies.critical,
DPTF_MAX_CRITICAL_POLICIES);
}

/* Writes other static tables that are used by DPTF */
static void write_controls(const struct drivers_intel_dptf_config *config)
{
dptf_write_charger_perf(config->controls.charger_perf, DPTF_MAX_CHARGER_PERF_STATES);
dptf_write_fan_perf(config->controls.fan_perf, DPTF_MAX_FAN_PERF_STATES);
dptf_write_power_limits(&config->controls.power_limits);
}

/* Options to control the behavior of devices */
static void write_options(const struct drivers_intel_dptf_config *config)
{
enum dptf_participant p;
int i;

/* Fan options */
dptf_write_fan_options(config->options.fan.fine_grained_control,
config->options.fan.step_size,
config->options.fan.low_speed_notify);

/* TSR options */
for (p = DPTF_TEMP_SENSOR_0, i = 0; p <= DPTF_TEMP_SENSOR_3; ++p, ++i) {
if (is_participant_used(config, p) && (config->options.tsr[i].hysteresis ||
config->options.tsr[i].desc)) {
dptf_write_scope(p);
dptf_write_tsr_hysteresis(config->options.tsr[i].hysteresis);
dptf_write_STR(config->options.tsr[i].desc);
acpigen_pop_len(); /* Scope */
}
}
}

/* Add custom tables and methods to SSDT */
static void dptf_fill_ssdt(const struct device *dev)
{
struct drivers_intel_dptf_config *config = config_of(dev);

write_device_definitions(dev);
write_policies(config);
write_controls(config);
write_options(config);

printk(BIOS_INFO, DPTF_DEVICE_PATH ": %s at %s\n", dev->chip_ops->name, dev_path(dev));
}

static struct device_operations dptf_ops = {
.read_resources = noop_read_resources,
.set_resources = noop_set_resources,
.acpi_name = dptf_acpi_name,
.acpi_fill_ssdt = dptf_fill_ssdt,
.acpi_inject_dsdt = dptf_inject_dsdt,
};

static void dptf_enable_dev(struct device *dev)
Expand Down
1 change: 0 additions & 1 deletion src/drivers/intel/fsp1_1/include/fsp/car.h
Expand Up @@ -4,7 +4,6 @@
#define FSP1_1_CAR_H

#include <fsp/api.h>
#include <stdint.h>

/* Per stage calls from the above two functions. The void * return from
* cache_as_ram_stage_main() is the stack pointer to use in RAM after
Expand Down
5 changes: 4 additions & 1 deletion src/drivers/intel/fsp2_0/include/fsp/util.h
Expand Up @@ -12,6 +12,8 @@
#include <program_loading.h>
#include <types.h>

#define FSP_VER_LEN 30

struct hob_header {
uint16_t type;
uint16_t length;
Expand Down Expand Up @@ -85,7 +87,8 @@ const struct hob_resource *fsp_hob_header_to_resource(
const struct hob_header *fsp_next_hob(const struct hob_header *parent);
bool fsp_guid_compare(const uint8_t guid1[16], const uint8_t guid2[16]);
void fsp_find_bootloader_tolum(struct range_entry *re);

void fsp_get_version(char *buf);
void lb_string_platform_blob_version(struct lb_header *header);

/* Fill in header and validate sanity of component within region device. */
enum cb_err fsp_validate_component(struct fsp_header *hdr,
Expand Down
36 changes: 36 additions & 0 deletions src/drivers/intel/fsp2_0/util.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */

#include <boot/coreboot_tables.h>
#include <device/mmio.h>
#include <cbfs.h>
#include <cf9_reset.h>
Expand Down Expand Up @@ -208,3 +209,38 @@ enum cb_err fsp_load_component(struct fsp_load_descriptor *fspld, struct fsp_hea

return CB_SUCCESS;
}

/* Only call this function when FSP header has been read and validated */
void fsp_get_version(char *buf)
{
struct fsp_header *hdr = &fsps_hdr;
union {
uint32_t val;
struct {
uint8_t bld_num;
uint8_t revision;
uint8_t minor;
uint8_t major;
} rev;
} revision;

revision.val = hdr->fsp_revision;
snprintf(buf, FSP_VER_LEN, "%u.%u-%u.%u.%u.%u", (hdr->spec_version >> 4),
hdr->spec_version & 0xf, revision.rev.major,
revision.rev.minor, revision.rev.revision, revision.rev.bld_num);
}

/* Add FSP version to coreboot table LB_TAG_PLATFORM_BLOB_VERSION */
void lb_string_platform_blob_version(struct lb_header *header)
{
struct lb_string *rec;
size_t len;
char fsp_version[FSP_VER_LEN] = {0};

fsp_get_version(fsp_version);
rec = (struct lb_string *)lb_new_record(header);
rec->tag = LB_TAG_PLATFORM_BLOB_VERSION;
len = strlen(fsp_version);
rec->size = ALIGN_UP(sizeof(*rec) + len + 1, 8);
memcpy(rec->string, fsp_version, len+1);
}
15 changes: 8 additions & 7 deletions src/drivers/intel/gma/Kconfig
Expand Up @@ -68,6 +68,14 @@ config GFX_GMA_ANALOG_I2C_HDMI_C
config GFX_GMA_ANALOG_I2C_HDMI_D
bool

config GFX_GMA_IGNORE_PRESENCE_STRAPS
def_bool n
depends on MAINBOARD_HAS_LIBGFXINIT
help
libgfxinit uses the GPU presence straps to determine if a display port
is present/enabled. Select this option if a board doesn't correctly implement
these straps, causing libgfxinit to fail to detect an attached panel.

config GFX_GMA
def_bool y
depends on NORTHBRIDGE_INTEL_GM45 || NORTHBRIDGE_INTEL_X4X \
Expand Down Expand Up @@ -127,11 +135,4 @@ config GFX_GMA_ANALOG_I2C_PORT
digital displays. In that case, the EDID for a VGA display has to be
read over the I2C interface of the coupled digital port.

config GFX_GMA_IGNORE_PRESENCE_STRAPS
def_bool n
help
libgfxinit uses the GPU presence straps to determine if a display port
is present/enabled. Select this option if a board doesn't correctly implement
these straps, causing libgfxinit to fail to detect an attached panel.

endif
10 changes: 0 additions & 10 deletions src/drivers/intel/gma/i915_reg.h
Expand Up @@ -447,16 +447,6 @@
#define RING_WAIT_I8XX (1<<0) /* gen2, PRBx_HEAD */
#define RING_WAIT (1<<11) /* gen3+, PRBx_CTL */
#define RING_WAIT_SEMAPHORE (1<<10) /* gen6+ */
#if 0
#define PRB0_TAIL 0x02030
#define PRB0_HEAD 0x02034
#define PRB0_START 0x02038
#define PRB0_CTL 0x0203c
#define PRB1_TAIL 0x02040 /* 915+ only */
#define PRB1_HEAD 0x02044 /* 915+ only */
#define PRB1_START 0x02048 /* 915+ only */
#define PRB1_CTL 0x0204c /* 915+ only */
#endif
#define IPEIR_I965 0x02064
#define IPEHR_I965 0x02068
#define INSTDONE_I965 0x0206c
Expand Down
683 changes: 662 additions & 21 deletions src/drivers/intel/mipi_camera/camera.c

Large diffs are not rendered by default.

136 changes: 135 additions & 1 deletion src/drivers/intel/mipi_camera/chip.h
Expand Up @@ -4,14 +4,62 @@
#define __INTEL_MIPI_CAMERA_CHIP_H__

#include <stdint.h>
#include <acpi/acpi_pld.h>

#define MAX_PWDB_ENTRIES 12
#define DEFAULT_LINK_FREQ 450000000
#define MAX_PWDB_ENTRIES 12
#define MAX_PORT_ENTRIES 4
#define MAX_LINK_FREQ_ENTRIES 4
#define MAX_CLK_CONFIGS 2
#define MAX_GPIO_CONFIGS 4
#define MAX_PWR_OPS 5

#define SEQ_OPS_CLK_ENABLE(ind, delay) \
{ .type = IMGCLK, .index = (ind), .action = ENABLE, .delay_ms = (delay) }
#define SEQ_OPS_CLK_DISABLE(ind, delay) \
{ .type = IMGCLK, .index = (ind), .action = DISABLE, .delay_ms = (delay) }
#define SEQ_OPS_GPIO_ENABLE(ind, delay) \
{ .type = GPIO, .index = (ind), .action = ENABLE, .delay_ms = (delay) }
#define SEQ_OPS_GPIO_DISABLE(ind, delay) \
{ .type = GPIO, .index = (ind), .action = DISABLE, .delay_ms = (delay) }

enum camera_device_type {
DEV_TYPE_SENSOR = 0,
DEV_TYPE_VCM,
DEV_TYPE_ROM
};

enum intel_camera_platform_type {
PLATFORM_SKC = 9,
PLATFORM_CNL = 10
};

enum intel_camera_flash_type {
FLASH_DEFAULT = 0,
FLASH_DISABLE = 2,
FLASH_ENABLE = 3
};

enum intel_camera_led_type {
PRIVACY_LED_DEFAULT = 0,
PRIVACY_LED_A_16mA
};

enum intel_camera_mipi_info {
MIPI_INFO_SENSOR_DRIVER = 0,
MIPI_INFO_ACPI_DEFINED
};

#define CLK_FREQ_19_2MHZ 19200000
#define CLK_FREQ_24MHZ 24000000
#define CLK_FREQ_20MHZ 20000000

enum intel_camera_device_type {
INTEL_ACPI_CAMERA_CIO2,
INTEL_ACPI_CAMERA_IMGU,
INTEL_ACPI_CAMERA_SENSOR,
INTEL_ACPI_CAMERA_VCM,
INTEL_ACPI_CAMERA_NVM,
INTEL_ACPI_CAMERA_PMIC = 100,
};

Expand All @@ -21,6 +69,47 @@ enum intel_power_action_type {
INTEL_ACPI_CAMERA_GPIO,
};

enum ctrl_type {
IMGCLK = 1,
GPIO
};

enum action_type {
ENABLE = 1,
DISABLE
};

struct clk_config {
/* IMGCLKOUT_x being used for a port */
uint8_t clknum;
/* frequency setting: 0:24Mhz, 1:19.2 Mhz */
uint8_t freq;
} __packed;

struct gpio_config {
uint8_t gpio_num;
} __packed;

struct clock_ctrl_panel {
struct clk_config clks[MAX_CLK_CONFIGS];
} __packed;

struct gpio_ctrl_panel {
struct gpio_config gpio[MAX_GPIO_CONFIGS];
} __packed;

struct operation_type {
enum ctrl_type type;
uint8_t index;
enum action_type action;
uint32_t delay_ms;
} __packed;

struct operation_seq {
struct operation_type ops[MAX_PWR_OPS];
uint8_t ops_cnt;
} __packed;

struct intel_ssdb {
uint8_t version; /* Current version */
uint8_t sensor_card_sku; /* CRD Board type */
Expand Down Expand Up @@ -64,12 +153,16 @@ struct intel_ssdb {
uint8_t degree; /* Camera Orientation */
uint8_t mipi_define; /* MIPI info defined in ACPI or
sensor driver */
uint32_t mclk_speed; /* Clock info for sensor */
uint32_t mclk; /* Clock info for sensor */
uint8_t control_logic_id; /* PMIC device node used for
the camera sensor */
uint8_t mipi_data_format; /* MIPI data format */
uint8_t silicon_version; /* Silicon version */
uint8_t customer_id; /* Customer ID */
uint8_t mclk_port;
uint8_t reserved[13]; /* Pads SSDB out so the binary blob in ACPI is
the same size as seen on other firmwares.*/
} __packed;

struct intel_pwdb {
Expand All @@ -82,6 +175,11 @@ struct intel_pwdb {
} __packed;

struct drivers_intel_mipi_camera_config {
struct clock_ctrl_panel clk_panel;
struct gpio_ctrl_panel gpio_panel;
struct operation_seq on_seq;
struct operation_seq off_seq;

struct intel_ssdb ssdb;
struct intel_pwdb pwdb[MAX_PWDB_ENTRIES];
enum intel_camera_device_type device_type;
Expand All @@ -90,6 +188,42 @@ struct drivers_intel_mipi_camera_config {
const char *acpi_name;
const char *chip_name;
unsigned int acpi_uid;
const char *pr0;

/* Settings specific to CIO2 device */
uint32_t cio2_num_ports;
uint32_t cio2_lanes_used[MAX_PORT_ENTRIES];
const char *cio2_lane_endpoint[MAX_PORT_ENTRIES];
uint32_t cio2_prt[MAX_PORT_ENTRIES];

/* Settings specific to camera sensor */
bool disable_ssdb_defaults;

uint8_t num_freq_entries; /* # of elements in link_freq */
uint32_t link_freq[MAX_LINK_FREQ_ENTRIES];
const char *sensor_name; /* default "UNKNOWN" */
const char *remote_name; /* default "\_SB.PCI0.CIO2" */
const char *vcm_name; /* defaults to |vcm_address| device */
bool use_pld;
bool disable_pld_defaults;
struct acpi_pld pld;
uint16_t rom_address; /* I2C to use if ssdb.rom_type != 0 */
uint16_t vcm_address; /* I2C to use if ssdb.vcm_type != 0 */
/*
* Settings specific to nvram. Many values, if left as zero, will be assigned a default.
* Set disable_nvm_defaults to non-zero if you want to disable the defaulting behavior
* so you can use zero for a value.
*/
bool disable_nvm_defaults;
uint32_t nvm_size;
uint32_t nvm_pagesize;
uint32_t nvm_readonly;
uint32_t nvm_width;

/* Settings specific to vcm */
const char *vcm_compat;
/* Does the device have a power resource entries */
bool has_power_resource;
};

#endif
2 changes: 1 addition & 1 deletion src/drivers/intel/pmc_mux/Makefile.inc
@@ -1,2 +1,2 @@
subdirs-y += con
subdirs-y += conn
ramstage-$(CONFIG_DRIVERS_INTEL_PMC) += mux.c
2 changes: 0 additions & 2 deletions src/drivers/intel/pmc_mux/chip.h
Expand Up @@ -3,8 +3,6 @@
#ifndef __DRIVERS_INTEL_PMC_MUX_H__
#define __DRIVERS_INTEL_PMC_MUX_H__

extern struct chip_operations drivers_intel_pmc_mux_ops;

struct drivers_intel_pmc_mux_config {
};

Expand Down
1 change: 0 additions & 1 deletion src/drivers/intel/pmc_mux/con/Makefile.inc

This file was deleted.

1 change: 1 addition & 0 deletions src/drivers/intel/pmc_mux/conn/Makefile.inc
@@ -0,0 +1 @@
ramstage-$(CONFIG_DRIVERS_INTEL_PMC) += conn.c
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */

#ifndef __DRIVERS_INTEL_PMC_MUX_CON_H__
#define __DRIVERS_INTEL_PMC_MUX_CON_H__
#ifndef __DRIVERS_INTEL_PMC_MUX_CONN_H__
#define __DRIVERS_INTEL_PMC_MUX_CONN_H__

enum typec_orientation {
/* The orientation of the signal follows the orientation of the CC lines. */
Expand All @@ -12,7 +12,7 @@ enum typec_orientation {
TYPEC_ORIENTATION_REVERSE,
};

struct drivers_intel_pmc_mux_con_config {
struct drivers_intel_pmc_mux_conn_config {
/* 1-based port numbers (from SoC point of view) */
int usb2_port_number;
/* 1-based port numbers (from SoC point of view) */
Expand All @@ -23,4 +23,4 @@ struct drivers_intel_pmc_mux_con_config {
enum typec_orientation hsl_orientation;
};

#endif /* __DRIVERS_INTEL_PMC_MUX_CON_H__ */
#endif /* __DRIVERS_INTEL_PMC_MUX_CONN_H__ */
Expand Up @@ -5,7 +5,7 @@
#include <intelblocks/acpi.h>
#include "chip.h"

static const char *con_acpi_name(const struct device *dev)
static const char *conn_acpi_name(const struct device *dev)
{
static char name[5];
snprintf(name, sizeof(name), "CON%1X", dev->path.generic.id);
Expand All @@ -25,17 +25,24 @@ static const char *orientation_to_str(enum typec_orientation ori)
}
}

static void con_fill_ssdt(const struct device *dev)
static void conn_fill_ssdt(const struct device *dev)
{
struct drivers_intel_pmc_mux_con_config *config = dev->chip_info;
struct drivers_intel_pmc_mux_conn_config *config = dev->chip_info;
struct acpi_dp *dsd;
const char *scope;
const char *name;

if (!dev->enabled)
return;

/* Reference the existing scope and write CONx device */
acpigen_write_scope(acpi_device_scope(dev));
acpigen_write_device(acpi_device_name(dev));
scope = acpi_device_scope(dev);
name = acpi_device_name(dev);
if (!scope || !name)
return;

acpigen_write_scope(scope);
acpigen_write_device(name);

acpigen_write_name_integer("_ADR", dev->path.generic.id);

Expand Down Expand Up @@ -65,19 +72,19 @@ static void con_fill_ssdt(const struct device *dev)
dev_path(dev));
}

static struct device_operations con_dev_ops = {
static struct device_operations conn_dev_ops = {
.read_resources = noop_read_resources,
.set_resources = noop_set_resources,
.acpi_name = con_acpi_name,
.acpi_fill_ssdt = con_fill_ssdt,
.acpi_name = conn_acpi_name,
.acpi_fill_ssdt = conn_fill_ssdt,
};

static void con_enable(struct device *dev)
static void conn_enable(struct device *dev)
{
dev->ops = &con_dev_ops;
dev->ops = &conn_dev_ops;
}

struct chip_operations drivers_intel_pmc_mux_con_ops = {
CHIP_NAME("Intel PMC MUX CON Driver")
.enable_dev = con_enable,
struct chip_operations drivers_intel_pmc_mux_conn_ops = {
CHIP_NAME("Intel PMC MUX CONN Driver")
.enable_dev = conn_enable,
};
10 changes: 8 additions & 2 deletions src/drivers/intel/pmc_mux/mux.c
Expand Up @@ -13,8 +13,14 @@ static const char *mux_acpi_name(const struct device *dev)

static void mux_fill_ssdt(const struct device *dev)
{
acpigen_write_scope(acpi_device_scope(dev));
acpigen_write_device(acpi_device_name(dev));
const char *scope = acpi_device_scope(dev);
const char *name = acpi_device_name(dev);

if (!scope || !name)
return;

acpigen_write_scope(scope);
acpigen_write_device(name);

acpigen_write_name_string("_HID", TGL_PMC_MUX_HID);
acpigen_write_name_string("_DDN", dev->chip_ops->name);
Expand Down
1 change: 0 additions & 1 deletion src/drivers/intel/ptt/ptt.h
Expand Up @@ -8,7 +8,6 @@
* is still in the preboot phase.
*
*/
#include <stdint.h>
/*
* ptt_active
*
Expand Down
1 change: 0 additions & 1 deletion src/drivers/intel/soundwire/soundwire.c
Expand Up @@ -8,7 +8,6 @@
#include <device/path.h>
#include <device/soundwire.h>
#include <stdbool.h>
#include <stdint.h>

#include "soundwire.h"
#include "chip.h"
Expand Down
15 changes: 15 additions & 0 deletions src/drivers/ipmi/Kconfig
Expand Up @@ -18,3 +18,18 @@ config IPMI_FRU_SINGLE_RW_SZ
IPMB messages are limited to 32-bytes total. When the
data size is larger than this value, IPMI can complete
reading/writing the data over multiple commands.

config IPMI_KCS_ROMSTAGE
bool
default n
depends on IPMI_KCS
help
IPMI KCS support in romstage.

config BMC_KCS_BASE
hex
default 0xca2
depends on IPMI_KCS
help
The PNP base address of BMC KCS. It must be equal to the
pnp port value defined in devicetree for chip drivers/ipmi.
3 changes: 3 additions & 0 deletions src/drivers/ipmi/Makefile.inc
Expand Up @@ -2,3 +2,6 @@ ramstage-$(CONFIG_IPMI_KCS) += ipmi_kcs.c
ramstage-$(CONFIG_IPMI_KCS) += ipmi_kcs_ops.c
ramstage-$(CONFIG_IPMI_KCS) += ipmi_ops.c
ramstage-$(CONFIG_IPMI_KCS) += ipmi_fru.c
romstage-$(CONFIG_IPMI_KCS_ROMSTAGE) += ipmi_kcs_ops_premem.c
romstage-$(CONFIG_IPMI_KCS_ROMSTAGE) += ipmi_kcs.c
romstage-$(CONFIG_IPMI_KCS_ROMSTAGE) += ipmi_ops.c
179 changes: 165 additions & 14 deletions src/drivers/ipmi/ipmi_fru.c
Expand Up @@ -213,40 +213,44 @@ static enum cb_err read_fru_chassis_info_area(const int port, const uint8_t id,
return ret;
}

static void read_fru_board_info_area(const int port, const uint8_t id,
static enum cb_err read_fru_board_info_area(const int port, const uint8_t id,
uint8_t offset, struct fru_board_info *info)
{
uint8_t length;
struct ipmi_read_fru_data_req req;
uint8_t *data_ptr;
uint8_t *data_ptr, *end, *custom_data_ptr;
int ret = CB_SUCCESS;

offset = offset * OFFSET_LENGTH_MULTIPLIER;
if (!offset)
return;
return CB_ERR;

offset = offset * OFFSET_LENGTH_MULTIPLIER;
req.fru_device_id = id;
/* Read Board Info Area length first. */
req.fru_offset = offset + 1;
req.count = sizeof(length);
if (ipmi_read_fru(port, &req, &length) != CB_SUCCESS || !length) {
printk(BIOS_ERR, "%s failed, length: %d\n", __func__, length);
return;
return CB_ERR;
}
length = length * OFFSET_LENGTH_MULTIPLIER;
data_ptr = (uint8_t *)malloc(length);
if (!data_ptr) {
printk(BIOS_ERR, "malloc %d bytes for board info failed\n", length);
return;
return CB_ERR;
}

end = data_ptr + length;
/* Read Board Info Area data. */
req.fru_offset = offset;
req.count = length;
if (ipmi_read_fru(port, &req, data_ptr) != CB_SUCCESS) {
printk(BIOS_ERR, "%s failed to read fru\n", __func__);
ret = CB_ERR;
goto out;
}
if (checksum(data_ptr, length)) {
printk(BIOS_ERR, "Bad FRU board info checksum.\n");
ret = CB_ERR;
goto out;
}
printk(BIOS_DEBUG, "Read board manufacturer string\n");
Expand All @@ -265,45 +269,87 @@ static void read_fru_board_info_area(const int port, const uint8_t id,
data_ptr += length + 1;
length = read_data_string(data_ptr, &info->part_number);

printk(BIOS_DEBUG, "Read board FRU file ID string.\n");
data_ptr += length + 1;
length = read_data_string(data_ptr, &info->fru_file_id);

/* Check how many valid custom fields first. */
data_ptr += length + 1;
info->custom_count = 0;
custom_data_ptr = data_ptr;
while ((data_ptr < end) && ((data_ptr[0] != FRU_END_OF_FIELDS))) {
length = NUM_DATA_BYTES(data_ptr[0]);
if (length > 0)
info->custom_count++;
data_ptr += length + 1;
}
if (!info->custom_count)
goto out;

info->board_custom = malloc(info->custom_count * sizeof(char *));
if (!info->board_custom) {
printk(BIOS_ERR, "%s failed to malloc %ld bytes for "
"board custom data array.\n", __func__,
info->custom_count * sizeof(char *));
ret = CB_ERR;
goto out;
}

/* Start reading custom board data. */
data_ptr = custom_data_ptr;
int count = 0;
while ((data_ptr < end) && ((data_ptr[0] != FRU_END_OF_FIELDS))) {
length = NUM_DATA_BYTES(data_ptr[0]);
if (length > 0) {
length = read_data_string(data_ptr, info->board_custom + count);
count++;
}
data_ptr += length + 1;
}

out:
free(data_ptr);
return ret;
}

static void read_fru_product_info_area(const int port, const uint8_t id,
static enum cb_err read_fru_product_info_area(const int port, const uint8_t id,
uint8_t offset, struct fru_product_info *info)
{
uint8_t length;
struct ipmi_read_fru_data_req req;
uint8_t *data_ptr;
uint8_t *data_ptr, *end, *custom_data_ptr;
int ret = CB_SUCCESS;

offset = offset * OFFSET_LENGTH_MULTIPLIER;
if (!offset)
return;
return CB_ERR;

offset = offset * OFFSET_LENGTH_MULTIPLIER;
req.fru_device_id = id;
/* Read Product Info Area length first. */
req.fru_offset = offset + 1;
req.count = sizeof(length);
if (ipmi_read_fru(port, &req, &length) != CB_SUCCESS || !length) {
printk(BIOS_ERR, "%s failed, length: %d\n", __func__, length);
return;
return CB_ERR;
}
length = length * OFFSET_LENGTH_MULTIPLIER;
data_ptr = (uint8_t *)malloc(length);
if (!data_ptr) {
printk(BIOS_ERR, "malloc %d bytes for product info failed\n", length);
return;
return CB_ERR;
}

end = data_ptr + length;
/* Read Product Info Area data. */
req.fru_offset = offset;
req.count = length;
if (ipmi_read_fru(port, &req, data_ptr) != CB_SUCCESS) {
printk(BIOS_ERR, "%s failed to read fru\n", __func__);
ret = CB_ERR;
goto out;
}
if (checksum(data_ptr, length)) {
printk(BIOS_ERR, "Bad FRU product info checksum.\n");
ret = CB_ERR;
goto out;
}
printk(BIOS_DEBUG, "Read product manufacturer string.\n");
Expand All @@ -330,8 +376,47 @@ static void read_fru_product_info_area(const int port, const uint8_t id,
printk(BIOS_DEBUG, "Read asset tag string.\n");
length = read_data_string(data_ptr, &info->asset_tag);

printk(BIOS_DEBUG, "Read product FRU file ID string.\n");
data_ptr += length + 1;
length = read_data_string(data_ptr, &info->fru_file_id);

/* Check how many valid custom fields first. */
data_ptr += length + 1;
info->custom_count = 0;
custom_data_ptr = data_ptr;
while ((data_ptr < end) && ((data_ptr[0] != FRU_END_OF_FIELDS))) {
length = NUM_DATA_BYTES(data_ptr[0]);
if (length > 0)
info->custom_count++;
data_ptr += length + 1;
}
if (!info->custom_count)
goto out;

info->product_custom = malloc(info->custom_count * sizeof(char *));
if (!info->product_custom) {
printk(BIOS_ERR, "%s failed to malloc %ld bytes for "
"product custom data array.\n", __func__,
info->custom_count * sizeof(char *));
ret = CB_ERR;
goto out;
}

/* Start reading custom product data. */
data_ptr = custom_data_ptr;
int count = 0;
while ((data_ptr < end) && ((data_ptr[0] != FRU_END_OF_FIELDS))) {
length = NUM_DATA_BYTES(data_ptr[0]);
if (length > 0) {
length = read_data_string(data_ptr, info->product_custom + count);
count++;
}
data_ptr += length + 1;
}

out:
free(data_ptr);
return ret;
}

void read_fru_areas(const int port, const uint8_t id, uint16_t offset,
Expand Down Expand Up @@ -422,3 +507,69 @@ void read_fru_one_area(const int port, const uint8_t id, uint16_t offset,
break;
}
}

void print_fru_areas(struct fru_info_str *fru_info_str)
{
int count = 0;
if (fru_info_str == NULL) {
printk(BIOS_ERR, "FRU data is null pointer\n");
return;
}
struct fru_product_info prod_info = fru_info_str->prod_info;
struct fru_board_info board_info = fru_info_str->board_info;
struct fru_chassis_info chassis_info = fru_info_str->chassis_info;

printk(BIOS_DEBUG, "Printing Product Info Area...\n");
if (prod_info.manufacturer != NULL)
printk(BIOS_DEBUG, "manufacturer: %s\n", prod_info.manufacturer);
if (prod_info.product_name != NULL)
printk(BIOS_DEBUG, "product name: %s\n", prod_info.product_name);
if (prod_info.product_partnumber != NULL)
printk(BIOS_DEBUG, "product part numer: %s\n", prod_info.product_partnumber);
if (prod_info.product_version != NULL)
printk(BIOS_DEBUG, "product version: %s\n", prod_info.product_version);
if (prod_info.serial_number != NULL)
printk(BIOS_DEBUG, "serial number: %s\n", prod_info.serial_number);
if (prod_info.asset_tag != NULL)
printk(BIOS_DEBUG, "asset tag: %s\n", prod_info.asset_tag);
if (prod_info.fru_file_id != NULL)
printk(BIOS_DEBUG, "FRU file ID: %s\n", prod_info.fru_file_id);

for (count = 0; count < prod_info.custom_count; count++) {
if (*(prod_info.product_custom + count) != NULL)
printk(BIOS_DEBUG, "product custom data %i: %s\n", count,
*(prod_info.product_custom + count));
}

printk(BIOS_DEBUG, "Printing Board Info Area...\n");
if (board_info.manufacturer != NULL)
printk(BIOS_DEBUG, "manufacturer: %s\n", board_info.manufacturer);
if (board_info.product_name != NULL)
printk(BIOS_DEBUG, "product name: %s\n", board_info.product_name);
if (board_info.serial_number != NULL)
printk(BIOS_DEBUG, "serial number: %s\n", board_info.serial_number);
if (board_info.part_number != NULL)
printk(BIOS_DEBUG, "part number: %s\n", board_info.part_number);
if (board_info.fru_file_id != NULL)
printk(BIOS_DEBUG, "FRU file ID: %s\n", board_info.fru_file_id);

for (count = 0; count < board_info.custom_count; count++) {
if (*(board_info.board_custom + count) != NULL)
printk(BIOS_DEBUG, "board custom data %i: %s\n", count,
*(board_info.board_custom + count));
}

printk(BIOS_DEBUG, "Printing Chassis Info Area...\n");
printk(BIOS_DEBUG, "chassis type: 0x%x\n", chassis_info.chassis_type);
if (chassis_info.chassis_partnumber != NULL)
printk(BIOS_DEBUG, "part number: %s\n", chassis_info.chassis_partnumber);
if (chassis_info.serial_number != NULL)
printk(BIOS_DEBUG, "serial number: %s\n", chassis_info.serial_number);

for (count = 0; count < chassis_info.custom_count; count++) {
if (*(chassis_info.chassis_custom + count) != NULL)
printk(BIOS_DEBUG, "chassis custom data %i: %s\n", count,
*(chassis_info.chassis_custom + count));
}

}
4 changes: 4 additions & 0 deletions src/drivers/ipmi/ipmi_kcs.h
Expand Up @@ -29,6 +29,10 @@ extern int ipmi_kcs_message(int port, int netfn, int lun, int cmd,
const unsigned char *inmsg, int inlen,
unsigned char *outmsg, int outlen);

/* Run basic IPMI init functions in romstage from the provided PnP device,
* returns CB_SUCCESS on success and CB_ERR if an error occurred. */
enum cb_err ipmi_kcs_premem_init(const u16 port, const u16 device);

struct ipmi_rsp {
uint8_t lun;
uint8_t cmd;
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/ipmi/ipmi_kcs_ops.c
Expand Up @@ -88,7 +88,7 @@ static void ipmi_kcs_init(struct device *dev)
if (conf && conf->wait_for_bmc && conf->bmc_boot_timeout) {
struct stopwatch sw;
stopwatch_init_msecs_expire(&sw, conf->bmc_boot_timeout * 1000);
printk(BIOS_DEBUG, "IPMI: Waiting for BMC...\n");
printk(BIOS_INFO, "IPMI: Waiting for BMC...\n");

while (!stopwatch_expired(&sw)) {
if (inb(dev->path.pnp.port) != 0xff)
Expand Down
112 changes: 112 additions & 0 deletions src/drivers/ipmi/ipmi_kcs_ops_premem.c
@@ -0,0 +1,112 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <console/console.h>
#include <device/pnp.h>
#include <delay.h>
#include <timer.h>

#include "ipmi_kcs.h"
#include "chip.h"

static int ipmi_get_bmc_self_test_result(const struct device *dev,
struct ipmi_selftest_rsp *rsp)
{
int ret;

ret = ipmi_kcs_message(dev->path.pnp.port, IPMI_NETFN_APPLICATION, 0,
IPMI_BMC_GET_SELFTEST_RESULTS, NULL, 0, (u8 *)rsp,
sizeof(*rsp));

if (ret < sizeof(struct ipmi_rsp) || rsp->resp.completion_code) {
printk(BIOS_ERR, "IPMI: %s command failed (ret=%d resp=0x%x)\n",
__func__, ret, rsp->resp.completion_code);
return 1;
}
if (ret != sizeof(*rsp)) {
printk(BIOS_ERR, "IPMI: %s response truncated\n", __func__);
return 1;
}

return 0;
}

enum cb_err ipmi_kcs_premem_init(const u16 port, const u16 device)
{
const struct drivers_ipmi_config *conf = NULL;
struct ipmi_selftest_rsp selftestrsp = {0};
uint8_t retry_count;
const struct device *dev;

/* Find IPMI PNP device from devicetree in romstage */
dev = dev_find_slot_pnp(port, device);

if (!dev) {
printk(BIOS_ERR, "IPMI: Cannot find PNP device port: %x, device %x\n",
port, device);
return CB_ERR;
}
if (!dev->enabled) {
printk(BIOS_ERR, "IPMI: device is not enabled\n");
return CB_ERR;
}
printk(BIOS_DEBUG, "IPMI: romstage PNP KCS 0x%x\n", dev->path.pnp.port);
if (dev->chip_info)
conf = dev->chip_info;

if (conf && conf->wait_for_bmc && conf->bmc_boot_timeout) {
struct stopwatch sw;
stopwatch_init_msecs_expire(&sw, conf->bmc_boot_timeout * 1000);
printk(BIOS_DEBUG, "IPMI: Waiting for BMC...\n");

while (!stopwatch_expired(&sw)) {
if (inb(dev->path.pnp.port) != 0xff)
break;
mdelay(100);
}
if (stopwatch_expired(&sw)) {
printk(BIOS_INFO, "IPMI: Waiting for BMC timed out\n");
return CB_ERR;
}
}

printk(BIOS_INFO, "Get BMC self test result...");
if (conf && conf->bmc_boot_timeout) {
for (retry_count = 0; retry_count < conf->bmc_boot_timeout; retry_count++) {
if (!ipmi_get_bmc_self_test_result(dev, &selftestrsp))
break;

mdelay(1000);
}
} else {
/* At least run once */
ipmi_get_bmc_self_test_result(dev, &selftestrsp);
}

int ret = CB_ERR;
switch (selftestrsp.result) {
case IPMI_APP_SELFTEST_NO_ERROR: /* 0x55 */
printk(BIOS_DEBUG, "No Error\n");
ret = CB_SUCCESS;
break;
case IPMI_APP_SELFTEST_NOT_IMPLEMENTED: /* 0x56 */
printk(BIOS_DEBUG, "Function Not Implemented\n");
ret = CB_SUCCESS;
break;
case IPMI_APP_SELFTEST_ERROR: /* 0x57 */
printk(BIOS_ERR, "Corrupted or inaccessible data or device\n");
break;
case IPMI_APP_SELFTEST_FATAL_HW_ERROR: /* 0x58 */
printk(BIOS_ERR, "Fatal Hardware Error\n");
break;
case IPMI_APP_SELFTEST_RESERVED: /* 0xFF */
printk(BIOS_DEBUG, "Reserved\n");
ret = CB_SUCCESS;
break;

default: /* Other Device Specific Hardware Error */
printk(BIOS_ERR, "Device Specific Error 0x%x 0x%x\n", selftestrsp.result,
selftestrsp.param);
break;
}
return ret;
}
11 changes: 10 additions & 1 deletion src/drivers/ipmi/ipmi_ops.h
Expand Up @@ -109,21 +109,27 @@ struct fru_product_info {
char *product_version;
char *serial_number;
char *asset_tag;
char *fru_file_id;
char **product_custom;
int custom_count; /* Number of custom fields */
};

struct fru_board_info {
char *manufacturer;
char *product_name;
char *serial_number;
char *part_number;
char *fru_file_id;
char **board_custom;
int custom_count;
};

struct fru_chassis_info {
uint8_t chassis_type;
char *chassis_partnumber;
char *serial_number;
char **chassis_custom;
int custom_count; /* Number of custom fields */
int custom_count;
};

struct fru_info_str {
Expand Down Expand Up @@ -172,4 +178,7 @@ void read_fru_one_area(const int port, uint8_t id, uint16_t offset,
/* Add a SEL record entry, returns CB_SUCCESS on success and CB_ERR
* if an error occurred */
enum cb_err ipmi_add_sel(const int port, struct sel_event_record *sel);

/* Print all IPMI read FRU data */
void print_fru_areas(struct fru_info_str *fru_info_str);
#endif
1 change: 0 additions & 1 deletion src/drivers/lenovo/hybrid_graphics/hybrid_graphics.c
@@ -1,6 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <types.h>
#include <option.h>
#include <device/device.h>

Expand Down
12 changes: 12 additions & 0 deletions src/drivers/ocp/dmi/Kconfig
@@ -0,0 +1,12 @@
config OCP_DMI
bool
default n
depends on IPMI_KCS && GENERATE_SMBIOS_TABLES && XEON_SP_COMMON_BASE
help
It implements the SMBIOS IPMI FRU mapping table defined in
https://www.opencompute.org/documents/facebook-xeon-motherboard-v31
22.3 SMBIOS FRU mapping table

config FRU_DEVICE_ID
int
default 0
1 change: 1 addition & 0 deletions src/drivers/ocp/dmi/Makefile.inc
@@ -0,0 +1 @@
ramstage-$(CONFIG_OCP_DMI) += smbios.c
20 changes: 20 additions & 0 deletions src/drivers/ocp/dmi/ocp_dmi.h
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */

#ifndef __OCP_DMI_H
#define __OCP_DMI_H

#include <cpu/x86/msr.h>
#include <device/device.h>
#include <smbios.h>

#define TBF "To Be Filled By O.E.M."

extern msr_t xeon_sp_ppin[];

/* Override SMBIOS type 11 OEM string 1 to string 6 */
void ocp_oem_smbios_strings(struct device *dev, struct smbios_type11 *t);

/* This function allows adding the same repeated string to the table */
int smbios_add_oem_string(u8 *start, const char *str);

#endif
260 changes: 260 additions & 0 deletions src/drivers/ocp/dmi/smbios.c
@@ -0,0 +1,260 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */

#include <console/console.h>
#include <device/device.h>
#include <drivers/ipmi/ipmi_ops.h>
#include <delay.h>
#include <cpu/x86/mp.h>
#include <timer.h>
#include <stdio.h>
#include <string.h>
#include <soc/soc_util.h>
#include <soc/cpu.h>
#include <smbios.h>

#include "ocp_dmi.h"

#define PPIN_STR_LEN 17

struct fru_info_str fru_strings = {0};
/* The spec defines only at most 2 sockets */
msr_t xeon_sp_ppin[2] = {0};
static bool remote_ppin_done = false;

/* Override SMBIOS type 1 data. */
const char *smbios_system_manufacturer(void)
{
if (fru_strings.prod_info.manufacturer != NULL)
return (const char *)fru_strings.prod_info.manufacturer;
else
return CONFIG_MAINBOARD_SMBIOS_MANUFACTURER;
}

const char *smbios_system_product_name(void)
{
if (fru_strings.board_info.product_name != NULL)
return (const char *)fru_strings.prod_info.product_name;
else
return CONFIG_MAINBOARD_SMBIOS_PRODUCT_NAME;
}

const char *smbios_system_serial_number(void)
{
if (fru_strings.prod_info.serial_number != NULL)
return (const char *)fru_strings.prod_info.serial_number;
else
return CONFIG_MAINBOARD_SERIAL_NUMBER;
}

const char *smbios_system_version(void)
{
if (fru_strings.prod_info.product_version != NULL)
return (const char *)fru_strings.prod_info.product_version;
else
return CONFIG_MAINBOARD_VERSION;
}

/* Override SMBIOS type 1 uuid from the value from BMC. */
void smbios_system_set_uuid(u8 *uuid)
{
ipmi_get_system_guid(CONFIG_BMC_KCS_BASE, uuid);
}

/* Override SMBIOS type 2 data. */
const char *smbios_mainboard_version(void)
{
if (fru_strings.board_info.part_number != NULL)
return (const char *)fru_strings.board_info.part_number;
else
return CONFIG_MAINBOARD_VERSION;
}

const char *smbios_mainboard_manufacturer(void)
{
if (fru_strings.board_info.manufacturer != NULL)
return (const char *)fru_strings.board_info.manufacturer;
else
return CONFIG_MAINBOARD_SMBIOS_MANUFACTURER;
}

const char *smbios_mainboard_product_name(void)
{
if (fru_strings.board_info.product_name != NULL)
return (const char *)fru_strings.board_info.product_name;
else
return CONFIG_MAINBOARD_SMBIOS_PRODUCT_NAME;
}

const char *smbios_mainboard_serial_number(void)
{
if (fru_strings.board_info.serial_number != NULL)
return (const char *)fru_strings.board_info.serial_number;
else
return CONFIG_MAINBOARD_SERIAL_NUMBER;
}

/* Override SMBIOS type 2 and 3 asset_tag data. */
const char *smbios_mainboard_asset_tag(void)
{
if (fru_strings.prod_info.asset_tag != NULL)
return (const char *)fru_strings.prod_info.asset_tag;
else
return "";
}

/* Override SMBIOS type 3 data. */
smbios_enclosure_type smbios_mainboard_enclosure_type(void)
{
/* SMBIOS System Enclosure or Chassis Types are values from 0 to 20h. */
if (fru_strings.chassis_info.chassis_type <= 0x20)
return fru_strings.chassis_info.chassis_type;
else
return SMBIOS_ENCLOSURE_RACK_MOUNT_CHASSIS;
}

const char *smbios_chassis_version(void)
{
if (fru_strings.chassis_info.chassis_partnumber != NULL)
return fru_strings.chassis_info.chassis_partnumber;
else
return "";
}

const char *smbios_chassis_serial_number(void)
{
if (fru_strings.chassis_info.serial_number != NULL)
return fru_strings.chassis_info.serial_number;
else
return "";
}

/* Override SMBIOS type 4 processor serial numbers from FRU Chassis custom data. */
const char *smbios_processor_serial_number(void)
{
/* For now type 4 only creates for one CPU, so it can only write the serial number
* of CPU0.
*/
if (*fru_strings.chassis_info.chassis_custom != NULL)
return *fru_strings.chassis_info.chassis_custom;
else
return "";
}

static void read_remote_ppin(void *data)
{
*(msr_t *)data = read_msr_ppin();
remote_ppin_done = true;
}

static void wait_for_remote_ppin(void)
{
struct stopwatch sw;

stopwatch_init_msecs_expire(&sw, 500);
while (!stopwatch_expired(&sw)) {
if (remote_ppin_done)
break;
mdelay(100);
}
if (stopwatch_expired(&sw))
printk(BIOS_ERR, "Wait for read_remote_ppin() timeout\n");
}

int smbios_add_oem_string(u8 *start, const char *str)
{
int i = 1;
char *p = (char *)start;

if (*str == '\0')
return 0;

for (;;) {
if (!*p) {
strcpy(p, str);
p += strlen(str);
*p++ = '\0';
*p++ = '\0';
return i;
}

p += strlen(p)+1;
i++;
}
}

/* When the most significant 4 bits of PPIN hi/lo are 0, add '0' to the beginning */
static void ppin_string_fixup(int i, char *ppin)
{
if ((xeon_sp_ppin[i].hi & 0xf0000000) == 0) {
if ((xeon_sp_ppin[i].lo & 0xf0000000) == 0)
snprintf(ppin, PPIN_STR_LEN, "0%x0%x", xeon_sp_ppin[i].hi,
xeon_sp_ppin[i].lo);
else
snprintf(ppin, PPIN_STR_LEN, "0%x%x", xeon_sp_ppin[i].hi,
xeon_sp_ppin[i].lo);
} else if ((xeon_sp_ppin[i].lo & 0xf0000000) == 0) {
snprintf(ppin, PPIN_STR_LEN, "%x0%x", xeon_sp_ppin[i].hi, xeon_sp_ppin[i].lo);
} else {
snprintf(ppin, PPIN_STR_LEN, "%x%x", xeon_sp_ppin[i].hi, xeon_sp_ppin[i].lo);
}
}

/*
* Override SMBIOS type 11 OEM string 1 to string 6, the rest are project dependent
* and can be added in the mainboard code.
*/
void ocp_oem_smbios_strings(struct device *dev, struct smbios_type11 *t)
{
char ppin[PPIN_STR_LEN];

/* Add OEM string 1 to 4 */
if (fru_strings.board_info.custom_count > 0 &&
*fru_strings.board_info.board_custom != NULL)
t->count = smbios_add_oem_string(t->eos, *fru_strings.board_info.board_custom);
else
t->count = smbios_add_oem_string(t->eos, TBF);

if (fru_strings.prod_info.custom_count > 0 &&
*fru_strings.prod_info.product_custom != NULL)
t->count = smbios_add_oem_string(t->eos, *fru_strings.prod_info.product_custom);
else
t->count = smbios_add_oem_string(t->eos, TBF);

if (fru_strings.prod_info.custom_count > 1 &&
*(fru_strings.prod_info.product_custom + 1) != NULL)
t->count = smbios_add_oem_string(t->eos,
*(fru_strings.prod_info.product_custom + 1));
else
t->count = smbios_add_oem_string(t->eos, TBF);

if (fru_strings.prod_info.custom_count > 2 &&
*(fru_strings.prod_info.product_custom + 2) != NULL) {
t->count = smbios_add_oem_string(t->eos,
*(fru_strings.prod_info.product_custom + 2));
} else {
t->count = smbios_add_oem_string(t->eos, TBF);
}

/* Add CPU0 PPIN to OEM string 5 */
xeon_sp_ppin[0] = read_msr_ppin();
ppin_string_fixup(0, ppin);
t->count = smbios_add_oem_string(t->eos, ppin);

/* Add CPU1 PPIN to OEM string 6 */
if (CONFIG_MAX_SOCKET == 2 && CONFIG(PARALLEL_MP_AP_WORK)) {
/* Read the last CPU MSR */
if (mp_run_on_aps(read_remote_ppin, (void *)&xeon_sp_ppin[1],
get_platform_thread_count() - 1, 100 * USECS_PER_MSEC)) {
printk(BIOS_ERR, "Failed to read remote PPIN.\n");
t->count = smbios_add_oem_string(t->eos, TBF);
} else {
/* Wait for read_remote_ppin() to finish because it's executed
in parallel */
wait_for_remote_ppin();
ppin_string_fixup(1, ppin);
t->count = smbios_add_oem_string(t->eos, ppin);
}
} else {
t->count = smbios_add_oem_string(t->eos, "0000");
}
}
14 changes: 0 additions & 14 deletions src/drivers/pc80/pc/i8259.c
Expand Up @@ -108,18 +108,4 @@ void i8259_configure_irq_trigger(int int_num, int is_level_triggered)
/* Write new values */
outb((u8)(int_bits & 0xff), ELCR1);
outb((u8)(int_bits >> 8), ELCR2);

#ifdef PARANOID_IRQ_TRIGGERS
/* Try reading back the new values. This seems like an error
* but it is not. */
if (inb(ELCR1) != (int_bits & 0xff)) {
printk(BIOS_ERR, "%s: lower order bits are wrong: want 0x%x, got 0x%x\n",
__func__, (int_bits & 0xff), inb(ELCR1));
}

if (inb(ELCR2) != (int_bits >> 8)) {
printk(BIOS_ERR, "%s: higher order bits are wrong: want 0x%x, got 0x%x\n",
__func__, (int_bits>>8), inb(ELCR2));
}
#endif
}
1 change: 0 additions & 1 deletion src/drivers/pc80/pc/spkmodem.c
Expand Up @@ -2,7 +2,6 @@

#include <arch/io.h>
#include <console/spkmodem.h>
#include <cpu/x86/tsc.h>

#define SPEAKER_PIT_FREQUENCY 0x1234dd

Expand Down
15 changes: 5 additions & 10 deletions src/drivers/pc80/tpm/Kconfig
@@ -1,13 +1,14 @@
config LPC_TPM
config MAINBOARD_HAS_LPC_TPM
bool
default n
help
LPC TPM driver is enabled!
Board has LPC TPM support

if MAINBOARD_HAS_LPC_TPM

config TPM_TIS_BASE_ADDRESS
hex
default 0xfed40000
depends on LPC_TPM
help
This can be used to adjust the TPM memory base address.
The default is specified by the TCG PC Client Specific TPM
Expand All @@ -17,14 +18,8 @@ config TPM_TIS_BASE_ADDRESS
config TPM_PIRQ
hex
default 0x0
depends on LPC_TPM
help
This can be used to specify a PIRQ to use instead of SERIRQ,
which is needed for SPI TPM interrupt support on x86.

config MAINBOARD_HAS_LPC_TPM
bool
default n
select LPC_TPM
help
Board has LPC TPM support
endif
8 changes: 4 additions & 4 deletions src/drivers/pc80/tpm/Makefile.inc
@@ -1,4 +1,4 @@
verstage-$(CONFIG_LPC_TPM) += tis.c
romstage-$(CONFIG_LPC_TPM) += tis.c
ramstage-$(CONFIG_LPC_TPM) += tis.c
postcar-$(CONFIG_LPC_TPM) += tis.c
verstage-$(CONFIG_MAINBOARD_HAS_LPC_TPM) += tis.c
romstage-$(CONFIG_MAINBOARD_HAS_LPC_TPM) += tis.c
ramstage-$(CONFIG_MAINBOARD_HAS_LPC_TPM) += tis.c
postcar-$(CONFIG_MAINBOARD_HAS_LPC_TPM) += tis.c
7 changes: 4 additions & 3 deletions src/drivers/pc80/tpm/tis.c
Expand Up @@ -44,7 +44,7 @@

/* the macro accepts the locality value, but only locality 0 is operational */
#define TIS_REG(LOCALITY, REG) \
(void *)(CONFIG_TPM_TIS_BASE_ADDRESS + (LOCALITY << 12) + REG)
(void *)(uintptr_t)(CONFIG_TPM_TIS_BASE_ADDRESS + (LOCALITY << 12) + REG)

/* hardware registers' offsets */
#define TIS_REG_ACCESS 0x0
Expand Down Expand Up @@ -993,8 +993,9 @@ static struct pnp_info pnp_dev_info[] = {

static void enable_dev(struct device *dev)
{
pnp_enable_devices(dev, &lpc_tpm_ops,
ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
if (CONFIG(TPM1) || CONFIG(TPM2))
pnp_enable_devices(dev, &lpc_tpm_ops,
ARRAY_SIZE(pnp_dev_info), pnp_dev_info);
}

struct chip_operations drivers_pc80_tpm_ops = {
Expand Down
6 changes: 3 additions & 3 deletions src/drivers/spi/acpi/acpi.c
Expand Up @@ -139,15 +139,15 @@ static void spi_acpi_fill_ssdt_generator(const struct device *dev)
if (irq_gpio_index >= 0)
acpi_dp_add_gpio(dsd, "irq-gpios", path,
irq_gpio_index, 0,
config->irq_gpio.polarity);
config->irq_gpio.active_low);
if (reset_gpio_index >= 0)
acpi_dp_add_gpio(dsd, "reset-gpios", path,
reset_gpio_index, 0,
config->reset_gpio.polarity);
config->reset_gpio.active_low);
if (enable_gpio_index >= 0)
acpi_dp_add_gpio(dsd, "enable-gpios", path,
enable_gpio_index, 0,
config->enable_gpio.polarity);
config->enable_gpio.active_low);
acpi_dp_write(dsd);
}

Expand Down
42 changes: 0 additions & 42 deletions src/drivers/ti/tps65090/tps65090.c
Expand Up @@ -92,48 +92,6 @@ static int tps65090_fet_set(unsigned int bus, enum fet_id fet_id, int set)
return FET_ERR_NOT_READY;
}

/* FIXME(dhendrix): add timer API */
#if 0
int tps65090_fet_enable(unsigned int bus, enum fet_id fet_id)
{
int loops;
unsigned long start;
int ret = 0;

start = get_timer(0);
for (loops = 0; ; loops++) {
ret = tps65090_fet_set(bus, fet_id, 1);
if (!ret)
break;

if (get_timer(start) > 100)
break;

/* Turn it off and try again until we time out */
tps65090_fet_set(bus, fet_id, 0);
}

if (ret) {
printk(BIOS_DEBUG, "%s: FET%d failed to power on: time=%lums, "
"loops=%d\n", __func__, fet_id,
get_timer(start), loops);
} else if (loops) {
printk(BIOS_DEBUG, "%s: FET%d powered on after %lums, "
"loops=%d\n", __func__, fet_id,
get_timer(start), loops);
}
/*
* Unfortunately, there are some conditions where the power
* good bit will be 0, but the fet still comes up. One such
* case occurs with the lcd backlight. We'll just return 0 here
* and assume that the fet will eventually come up.
*/
if (ret == FET_ERR_NOT_READY)
ret = 0;

return ret;
}
#endif
int tps65090_fet_enable(unsigned int bus, enum fet_id fet_id)
{
int loops;
Expand Down
1 change: 0 additions & 1 deletion src/drivers/tpm/tpm.c
@@ -1,7 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpi.h>
#include <types.h>
#include <bootstate.h>
#include <security/tpm/tspi.h>

Expand Down
6 changes: 3 additions & 3 deletions src/drivers/uart/acpi/acpi.c
Expand Up @@ -103,15 +103,15 @@ static void uart_acpi_fill_ssdt(const struct device *dev)
if (irq_gpio_index >= 0)
acpi_dp_add_gpio(dsd, "irq-gpios", path,
irq_gpio_index, 0,
config->irq_gpio.polarity);
config->irq_gpio.active_low);
if (reset_gpio_index >= 0)
acpi_dp_add_gpio(dsd, "reset-gpios", path,
reset_gpio_index, 0,
config->reset_gpio.polarity);
config->reset_gpio.active_low);
if (enable_gpio_index >= 0)
acpi_dp_add_gpio(dsd, "enable-gpios", path,
enable_gpio_index, 0,
config->enable_gpio.polarity);
config->enable_gpio.active_low);
acpi_dp_write(dsd);
}

Expand Down
2 changes: 1 addition & 1 deletion src/drivers/usb/acpi/usb_acpi.c
Expand Up @@ -57,7 +57,7 @@ static void usb_acpi_fill_ssdt_generator(const struct device *dev)

dsd = acpi_dp_new_table("_DSD");
acpi_dp_add_gpio(dsd, "reset-gpio", path, 0, 0,
config->reset_gpio.polarity);
config->reset_gpio.active_low);
acpi_dp_write(dsd);
}

Expand Down
39 changes: 15 additions & 24 deletions src/drivers/usb/ehci_debug.c
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <stddef.h>
#include <stdint.h>
#include <console/console.h>
#include <console/usb.h>
#include <arch/io.h>
Expand Down Expand Up @@ -563,13 +563,6 @@ static int usbdebug_init_(uintptr_t ehci_bar, unsigned int offset, struct ehci_d
}
dprintk(BIOS_INFO, "EHCI debug port enabled.\n");

#if 0
/* Completely transfer the debug device to the debug controller */
portsc = read32(&ehci_regs->port_status[debug_port - 1]);
portsc &= ~PORT_PE;
write32(&ehci_regs->port_status[debug_port - 1], portsc);
#endif

dbgp_mdelay(100);

struct ehci_dbg_port *port = (void *)(uintptr_t)info->ehci_debug;
Expand All @@ -591,23 +584,21 @@ static int usbdebug_init_(uintptr_t ehci_bar, unsigned int offset, struct ehci_d
//return ret;

next_debug_port:
#if CONFIG_USBDEBUG_DEFAULT_PORT == 0
port_map_tried |= (1 << (debug_port - 1));
new_debug_port = ((debug_port-1 + 1) % n_ports) + 1;
if (port_map_tried != ((1 << n_ports) - 1)) {
ehci_debug_select_port(new_debug_port);
goto try_next_port;
}
if (--playtimes) {
ehci_debug_select_port(new_debug_port);
goto try_next_time;
if (CONFIG_USBDEBUG_DEFAULT_PORT == 0) {
port_map_tried |= (1 << (debug_port - 1));
new_debug_port = ((debug_port-1 + 1) % n_ports) + 1;
if (port_map_tried != ((1 << n_ports) - 1)) {
ehci_debug_select_port(new_debug_port);
goto try_next_port;
}
if (--playtimes) {
ehci_debug_select_port(new_debug_port);
goto try_next_time;
}
} else {
if (--playtimes)
goto try_next_time;
}
#else
if (0)
goto try_next_port;
if (--playtimes)
goto try_next_time;
#endif

return -10;
}
Expand Down
2 changes: 1 addition & 1 deletion src/drivers/usb/gadget.c
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <stddef.h>
#include <stdint.h>
#include <console/console.h>
#include <string.h>

Expand Down
6 changes: 6 additions & 0 deletions src/drivers/usb/pci_xhci/Kconfig
@@ -0,0 +1,6 @@
config DRIVERS_USB_PCI_XHCI
def_bool n
depends on HAVE_ACPI_TABLES
select XHCI_UTILS
help
PCI driver that generates ACPI nodes for an xHCI compatible controller.
1 change: 1 addition & 0 deletions src/drivers/usb/pci_xhci/Makefile.inc
@@ -0,0 +1 @@
ramstage-$(CONFIG_DRIVERS_USB_PCI_XHCI) += pci_xhci.c