Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
- Move P2SB from Apollo Lake to a more generic location
- Add a function to find a device by drvdata in DM core
- Enhancement of DM IRQ uclass driver
- Add a clock driver for Intel devices
- Add support for ACPI general-purpose events
- Add a TPM driver for H1/Cr50
- Enable TPM on Google Chromebook Coral
  • Loading branch information
trini committed Feb 10, 2020
2 parents 5f2fe7d + 0f6a70e commit 4e5c468
Show file tree
Hide file tree
Showing 38 changed files with 1,640 additions and 94 deletions.
5 changes: 4 additions & 1 deletion arch/sandbox/dts/test.dts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
<&gpio_b 9 0xc 3 2 1>;
int-value = <1234>;
uint-value = <(-1234)>;
interrupts-extended = <&irq 3 0>;
};

junk {
Expand Down Expand Up @@ -357,8 +358,10 @@
vss-microvolts = <0>;
};

irq {
irq: irq {
compatible = "sandbox,irq";
interrupt-controller;
#interrupt-cells = <2>;
};

lcd {
Expand Down
4 changes: 4 additions & 0 deletions arch/sandbox/include/asm/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
#define PCI_EA_BAR2_MAGIC 0x72727272
#define PCI_EA_BAR4_MAGIC 0x74747474

enum {
SANDBOX_IRQN_PEND = 1, /* Interrupt number for 'pending' test */
};

/* System controller driver data */
enum {
SYSCON0 = 32,
Expand Down
40 changes: 40 additions & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,13 @@ config HAVE_ITSS
Select this to include the driver for the Interrupt Timer
Subsystem (ITSS) which is found on several Intel devices.

config HAVE_P2SB
bool "Enable P2SB"
help
Select this to include the driver for the Primary to
Sideband Bridge (P2SB) which is found on several Intel
devices.

menu "System tables"
depends on !EFI && !SYS_COREBOOT

Expand Down Expand Up @@ -916,4 +923,37 @@ config X86_OFFSET_SPL
depends on SPL && X86
default SPL_TEXT_BASE

config ACPI_GPE
bool "Support ACPI general-purpose events"
help
Enable a driver for ACPI GPEs to allow peripherals to send interrupts
via ACPI to the OS. In U-Boot this is only used when U-Boot itself
needs access to these interrupts. This can happen when it uses a
peripheral that is set up to use GPEs and so cannot use the normal
GPIO mechanism for polling an input.

See https://queue.acm.org/blogposting.cfm?id=18977 for more info

config SPL_ACPI_GPE
bool "Support ACPI general-purpose events in SPL"
help
Enable a driver for ACPI GPEs to allow peripherals to send interrupts
via ACPI to the OS. In U-Boot this is only used when U-Boot itself
needs access to these interrupts. This can happen when it uses a
peripheral that is set up to use GPEs and so cannot use the normal
GPIO mechanism for polling an input.

See https://queue.acm.org/blogposting.cfm?id=18977 for more info

config TPL_ACPI_GPE
bool "Support ACPI general-purpose events in TPL"
help
Enable a driver for ACPI GPEs to allow peripherals to send interrupts
via ACPI to the OS. In U-Boot this is only used when U-Boot itself
needs access to these interrupts. This can happen when it uses a
peripheral that is set up to use GPEs and so cannot use the normal
GPIO mechanism for polling an input.

See https://queue.acm.org/blogposting.cfm?id=18977 for more info

endmenu
1 change: 1 addition & 0 deletions arch/x86/cpu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ obj-$(CONFIG_INTEL_QUEENSBAY) += queensbay/
obj-$(CONFIG_INTEL_TANGIER) += tangier/
obj-$(CONFIG_APIC) += lapic.o ioapic.o
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += irq.o
obj-$(CONFIG_$(SPL_TPL_)ACPI_GPE) += acpi_gpe.o
obj-$(CONFIG_QFW) += qfw_cpu.o
ifndef CONFIG_$(SPL_)X86_64
obj-$(CONFIG_SMP) += mp_init.o
Expand Down
85 changes: 85 additions & 0 deletions arch/x86/cpu/acpi_gpe.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2019 Google, LLC
* Written by Simon Glass <[email protected]>
*/

#include <common.h>
#include <dm.h>
#include <irq.h>
#include <asm/io.h>

/**
* struct acpi_gpe_priv - private driver information
*
* @acpi_base: Base I/O address of ACPI registers
*/
struct acpi_gpe_priv {
ulong acpi_base;
};

#define GPE0_STS(x) (0x20 + ((x) * 4))

static int acpi_gpe_read_and_clear(struct irq *irq)
{
struct acpi_gpe_priv *priv = dev_get_priv(irq->dev);
u32 mask, sts;
ulong start;
int ret = 0;
int bank;

bank = irq->id / 32;
mask = 1 << (irq->id % 32);

/* Wait up to 1ms for GPE status to clear */
start = get_timer(0);
do {
if (get_timer(start) > 1)
return ret;

sts = inl(priv->acpi_base + GPE0_STS(bank));
if (sts & mask) {
outl(mask, priv->acpi_base + GPE0_STS(bank));
ret = 1;
}
} while (sts & mask);

return ret;
}

static int acpi_gpe_ofdata_to_platdata(struct udevice *dev)
{
struct acpi_gpe_priv *priv = dev_get_priv(dev);

priv->acpi_base = dev_read_addr(dev);
if (!priv->acpi_base || priv->acpi_base == FDT_ADDR_T_NONE)
return log_msg_ret("acpi_base", -EINVAL);

return 0;
}

static int acpi_gpe_of_xlate(struct irq *irq, struct ofnode_phandle_args *args)
{
irq->id = args->args[0];

return 0;
}

static const struct irq_ops acpi_gpe_ops = {
.read_and_clear = acpi_gpe_read_and_clear,
.of_xlate = acpi_gpe_of_xlate,
};

static const struct udevice_id acpi_gpe_ids[] = {
{ .compatible = "intel,acpi-gpe", .data = X86_IRQT_ACPI_GPE },
{ }
};

U_BOOT_DRIVER(acpi_gpe_drv) = {
.name = "acpi_gpe",
.id = UCLASS_IRQ,
.of_match = acpi_gpe_ids,
.ops = &acpi_gpe_ops,
.ofdata_to_platdata = acpi_gpe_ofdata_to_platdata,
.priv_auto_alloc_size = sizeof(struct acpi_gpe_priv),
};
5 changes: 5 additions & 0 deletions arch/x86/cpu/apollolake/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ config INTEL_APOLLOLAKE
imply INTEL_GPIO
imply SMP
imply HAVE_ITSS
imply HAVE_P2SB
imply CLK
imply CMD_CLK
imply CLK_INTEL
imply ACPI_GPE

if INTEL_APOLLOLAKE

Expand Down
1 change: 0 additions & 1 deletion arch/x86/cpu/apollolake/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ endif

obj-y += hostbridge.o
obj-y += lpc.o
obj-y += p2sb.o
obj-y += pch.o
obj-y += pmc.o
obj-y += uart.o
62 changes: 2 additions & 60 deletions arch/x86/cpu/apollolake/fsp_s.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,77 +24,20 @@
#define HIDE_BIT BIT(0)

#define INTEL_GSPI_MAX 3
#define INTEL_I2C_DEV_MAX 8
#define MAX_USB2_PORTS 8

enum {
CHIPSET_LOCKDOWN_FSP = 0, /* FSP handles locking per UPDs */
CHIPSET_LOCKDOWN_COREBOOT, /* coreboot handles locking */
};

enum i2c_speed {
I2C_SPEED_STANDARD = 100000,
I2C_SPEED_FAST = 400000,
I2C_SPEED_FAST_PLUS = 1000000,
I2C_SPEED_HIGH = 3400000,
I2C_SPEED_FAST_ULTRA = 5000000,
};

/*
* Timing values are in units of clock period, with the clock speed
* provided by the SOC
*
* TODO([email protected]): Connect this up to the I2C driver
*/
struct dw_i2c_speed_config {
enum i2c_speed speed;
/* SCL high and low period count */
u16 scl_lcnt;
u16 scl_hcnt;
/*
* SDA hold time should be 300ns in standard and fast modes
* and long enough for deterministic logic level change in
* fast-plus and high speed modes.
*
* [15:0] SDA TX Hold Time
* [23:16] SDA RX Hold Time
*/
u32 sda_hold;
};

/* Serial IRQ control. SERIRQ_QUIET is the default (0) */
enum serirq_mode {
SERIRQ_QUIET,
SERIRQ_CONTINUOUS,
SERIRQ_OFF,
};

/*
* This I2C controller has support for 3 independent speed configs but can
* support both FAST_PLUS and HIGH speeds through the same set of speed
* config registers. These are treated separately so the speed config values
* can be provided via ACPI to the OS.
*/
#define DW_I2C_SPEED_CONFIG_COUNT 4

struct dw_i2c_bus_config {
/* Bus should be enabled in TPL with temporary base */
int early_init;
/* Bus speed in Hz, default is I2C_SPEED_FAST (400 KHz) */
enum i2c_speed speed;
/*
* If rise_time_ns is non-zero the calculations for lcnt and hcnt
* registers take into account the times of the bus. However, if
* there is a match in speed_config those register values take
* precedence
*/
int rise_time_ns;
int fall_time_ns;
int data_hold_time_ns;
/* Specific bus speed configuration */
struct dw_i2c_speed_config speed_config[DW_I2C_SPEED_CONFIG_COUNT];
};

struct gspi_cfg {
/* Bus speed in MHz */
u32 speed_mhz;
Expand All @@ -110,7 +53,6 @@ struct gspi_cfg {
struct soc_intel_common_config {
int chipset_lockdown;
struct gspi_cfg gspi[INTEL_GSPI_MAX];
struct dw_i2c_bus_config i2c[INTEL_I2C_DEV_MAX];
};

enum pnp_settings {
Expand Down Expand Up @@ -593,7 +535,7 @@ int arch_fsps_preinit(void)
struct udevice *itss;
int ret;

ret = uclass_first_device_err(UCLASS_IRQ, &itss);
ret = irq_first_device_type(X86_IRQT_ITSS, &itss);
if (ret)
return log_msg_ret("no itss", ret);
/*
Expand Down Expand Up @@ -634,7 +576,7 @@ int arch_fsp_init_r(void)
if (ret)
return ret;

ret = uclass_first_device_err(UCLASS_IRQ, &itss);
ret = irq_first_device_type(X86_IRQT_ITSS, &itss);
if (ret)
return log_msg_ret("no itss", ret);
/* Restore GPIO IRQ polarities back to previous settings */
Expand Down
3 changes: 2 additions & 1 deletion arch/x86/cpu/i386/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <efi_loader.h>
#include <hang.h>
#include <init.h>
#include <irq.h>
#include <irq_func.h>
#include <asm/control_regs.h>
#include <asm/i8259.h>
Expand Down Expand Up @@ -264,7 +265,7 @@ int interrupt_init(void)
int ret;

/* Try to set up the interrupt router, but don't require one */
ret = uclass_first_device_err(UCLASS_IRQ, &dev);
ret = irq_first_device_type(X86_IRQT_BASE, &dev);
if (ret && ret != -ENODEV)
return ret;

Expand Down
1 change: 1 addition & 0 deletions arch/x86/cpu/intel_common/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ endif
endif
obj-y += pch.o
obj-$(CONFIG_HAVE_ITSS) += itss.o
obj-$(CONFIG_HAVE_P2SB) += p2sb.o

ifdef CONFIG_SPL
ifndef CONFIG_SPL_BUILD
Expand Down
12 changes: 11 additions & 1 deletion arch/x86/cpu/intel_common/itss.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,15 @@ static int route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num)
return -ENOENT;
}

static int itss_bind(struct udevice *dev)
{
/* This is not set with of-platdata, so set it manually */
if (CONFIG_IS_ENABLED(OF_PLATDATA))
dev->driver_data = X86_IRQT_ITSS;

return 0;
}

static int itss_ofdata_to_platdata(struct udevice *dev)
{
struct itss_priv *priv = dev_get_priv(dev);
Expand Down Expand Up @@ -199,7 +208,7 @@ static const struct irq_ops itss_ops = {
};

static const struct udevice_id itss_ids[] = {
{ .compatible = "intel,itss"},
{ .compatible = "intel,itss", .data = X86_IRQT_ITSS },
{ }
};

Expand All @@ -208,6 +217,7 @@ U_BOOT_DRIVER(itss_drv) = {
.id = UCLASS_IRQ,
.of_match = itss_ids,
.ops = &itss_ops,
.bind = itss_bind,
.ofdata_to_platdata = itss_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct itss_platdata),
.priv_auto_alloc_size = sizeof(struct itss_priv),
Expand Down
File renamed without changes.
3 changes: 2 additions & 1 deletion arch/x86/cpu/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
#include <irq.h>
#include <malloc.h>
#include <asm/io.h>
#include <asm/irq.h>
Expand Down Expand Up @@ -351,7 +352,7 @@ int irq_router_probe(struct udevice *dev)
}

static const struct udevice_id irq_router_ids[] = {
{ .compatible = "intel,irq-router" },
{ .compatible = "intel,irq-router", .data = X86_IRQT_BASE },
{ }
};

Expand Down
Loading

0 comments on commit 4e5c468

Please sign in to comment.