commit
e0ed8332fa
@ -0,0 +1,48 @@ |
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> |
||||
* |
||||
* Reset driver for tangier processor |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <dm.h> |
||||
#include <sysreset.h> |
||||
#include <asm/scu.h> |
||||
|
||||
static int tangier_sysreset_request(struct udevice *dev, enum sysreset_t type) |
||||
{ |
||||
int value; |
||||
|
||||
switch (type) { |
||||
case SYSRESET_WARM: |
||||
value = IPCMSG_WARM_RESET; |
||||
break; |
||||
case SYSRESET_COLD: |
||||
value = IPCMSG_COLD_RESET; |
||||
break; |
||||
default: |
||||
return -ENOSYS; |
||||
} |
||||
|
||||
scu_ipc_simple_command(value, 0); |
||||
|
||||
return -EINPROGRESS; |
||||
} |
||||
|
||||
static const struct udevice_id tangier_sysreset_ids[] = { |
||||
{ .compatible = "intel,reset-tangier" }, |
||||
{ } |
||||
}; |
||||
|
||||
static struct sysreset_ops tangier_sysreset_ops = { |
||||
.request = tangier_sysreset_request, |
||||
}; |
||||
|
||||
U_BOOT_DRIVER(tangier_sysreset) = { |
||||
.name = "tangier-sysreset", |
||||
.id = UCLASS_SYSRESET, |
||||
.of_match = tangier_sysreset_ids, |
||||
.ops = &tangier_sysreset_ops, |
||||
.flags = DM_FLAG_PRE_RELOC, |
||||
}; |
@ -0,0 +1,6 @@ |
||||
/ { |
||||
reset { |
||||
compatible = "x86,reset"; |
||||
u-boot,dm-pre-reloc; |
||||
}; |
||||
}; |
@ -0,0 +1,41 @@ |
||||
/* SPDX-License-Identifier: GPL-2.0+ */ |
||||
/*
|
||||
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> |
||||
*/ |
||||
|
||||
#ifndef __ASM_ACPI_H__ |
||||
#define __ASM_ACPI_H__ |
||||
|
||||
struct acpi_fadt; |
||||
|
||||
/**
|
||||
* acpi_find_fadt() - find ACPI FADT table in the system memory |
||||
* |
||||
* This routine parses the ACPI table to locate the ACPI FADT table. |
||||
* |
||||
* @return: a pointer to the ACPI FADT table in the system memory |
||||
*/ |
||||
struct acpi_fadt *acpi_find_fadt(void); |
||||
|
||||
/**
|
||||
* acpi_find_wakeup_vector() - find OS installed wake up vector address |
||||
* |
||||
* This routine parses the ACPI table to locate the wake up vector installed |
||||
* by the OS previously. |
||||
* |
||||
* @fadt: a pointer to the ACPI FADT table in the system memory |
||||
* @return: wake up vector address installed by the OS |
||||
*/ |
||||
void *acpi_find_wakeup_vector(struct acpi_fadt *fadt); |
||||
|
||||
/**
|
||||
* enter_acpi_mode() - enter into ACPI mode |
||||
* |
||||
* This programs the ACPI-defined PM1_CNT register to enable SCI interrupt |
||||
* so that the whole system swiches to ACPI mode. |
||||
* |
||||
* @pm1_cnt: PM1_CNT register I/O address |
||||
*/ |
||||
void enter_acpi_mode(int pm1_cnt); |
||||
|
||||
#endif /* __ASM_ACPI_H__ */ |
@ -0,0 +1,108 @@ |
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <asm/acpi_table.h> |
||||
#include <asm/io.h> |
||||
#include <asm/tables.h> |
||||
|
||||
static struct acpi_rsdp *acpi_valid_rsdp(struct acpi_rsdp *rsdp) |
||||
{ |
||||
if (strncmp((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) |
||||
return NULL; |
||||
|
||||
debug("Looking on %p for valid checksum\n", rsdp); |
||||
|
||||
if (table_compute_checksum((void *)rsdp, 20) != 0) |
||||
return NULL; |
||||
debug("acpi rsdp checksum 1 passed\n"); |
||||
|
||||
if ((rsdp->revision > 1) && |
||||
(table_compute_checksum((void *)rsdp, rsdp->length) != 0)) |
||||
return NULL; |
||||
debug("acpi rsdp checksum 2 passed\n"); |
||||
|
||||
return rsdp; |
||||
} |
||||
|
||||
struct acpi_fadt *acpi_find_fadt(void) |
||||
{ |
||||
char *p, *end; |
||||
struct acpi_rsdp *rsdp = NULL; |
||||
struct acpi_rsdt *rsdt; |
||||
struct acpi_fadt *fadt = NULL; |
||||
int i; |
||||
|
||||
/* Find RSDP */ |
||||
for (p = (char *)ROM_TABLE_ADDR; p < (char *)ROM_TABLE_END; p += 16) { |
||||
rsdp = acpi_valid_rsdp((struct acpi_rsdp *)p); |
||||
if (rsdp) |
||||
break; |
||||
} |
||||
|
||||
if (!rsdp) |
||||
return NULL; |
||||
|
||||
debug("RSDP found at %p\n", rsdp); |
||||
rsdt = (struct acpi_rsdt *)(uintptr_t)rsdp->rsdt_address; |
||||
|
||||
end = (char *)rsdt + rsdt->header.length; |
||||
debug("RSDT found at %p ends at %p\n", rsdt, end); |
||||
|
||||
for (i = 0; ((char *)&rsdt->entry[i]) < end; i++) { |
||||
fadt = (struct acpi_fadt *)(uintptr_t)rsdt->entry[i]; |
||||
if (strncmp((char *)fadt, "FACP", 4) == 0) |
||||
break; |
||||
fadt = NULL; |
||||
} |
||||
|
||||
if (!fadt) |
||||
return NULL; |
||||
|
||||
debug("FADT found at %p\n", fadt); |
||||
return fadt; |
||||
} |
||||
|
||||
void *acpi_find_wakeup_vector(struct acpi_fadt *fadt) |
||||
{ |
||||
struct acpi_facs *facs; |
||||
void *wake_vec; |
||||
|
||||
debug("Trying to find the wakeup vector...\n"); |
||||
|
||||
facs = (struct acpi_facs *)(uintptr_t)fadt->firmware_ctrl; |
||||
|
||||
if (!facs) { |
||||
debug("No FACS found, wake up from S3 not possible.\n"); |
||||
return NULL; |
||||
} |
||||
|
||||
debug("FACS found at %p\n", facs); |
||||
wake_vec = (void *)(uintptr_t)facs->firmware_waking_vector; |
||||
debug("OS waking vector is %p\n", wake_vec); |
||||
|
||||
return wake_vec; |
||||
} |
||||
|
||||
void enter_acpi_mode(int pm1_cnt) |
||||
{ |
||||
u16 val = inw(pm1_cnt); |
||||
|
||||
/*
|
||||
* PM1_CNT register bit0 selects the power management event to be |
||||
* either an SCI or SMI interrupt. When this bit is set, then power |
||||
* management events will generate an SCI interrupt. When this bit |
||||
* is reset power management events will generate an SMI interrupt. |
||||
* |
||||
* Per ACPI spec, it is the responsibility of the hardware to set |
||||
* or reset this bit. OSPM always preserves this bit position. |
||||
* |
||||
* U-Boot does not support SMI. And we don't have plan to support |
||||
* anything running in SMM within U-Boot. To create a legacy-free |
||||
* system, and expose ourselves to OSPM as working under ACPI mode |
||||
* already, turn this bit on. |
||||
*/ |
||||
outw(val | PM1_CNT_SCI_EN, pm1_cnt); |
||||
} |
@ -0,0 +1,49 @@ |
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> |
||||
* |
||||
* Generic reset driver for x86 processor |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <dm.h> |
||||
#include <sysreset.h> |
||||
#include <asm/io.h> |
||||
#include <asm/processor.h> |
||||
|
||||
static int x86_sysreset_request(struct udevice *dev, enum sysreset_t type) |
||||
{ |
||||
int value; |
||||
|
||||
switch (type) { |
||||
case SYSRESET_WARM: |
||||
value = SYS_RST | RST_CPU; |
||||
break; |
||||
case SYSRESET_COLD: |
||||
value = SYS_RST | RST_CPU | FULL_RST; |
||||
break; |
||||
default: |
||||
return -ENOSYS; |
||||
} |
||||
|
||||
outb(value, IO_PORT_RESET); |
||||
|
||||
return -EINPROGRESS; |
||||
} |
||||
|
||||
static const struct udevice_id x86_sysreset_ids[] = { |
||||
{ .compatible = "x86,reset" }, |
||||
{ } |
||||
}; |
||||
|
||||
static struct sysreset_ops x86_sysreset_ops = { |
||||
.request = x86_sysreset_request, |
||||
}; |
||||
|
||||
U_BOOT_DRIVER(x86_sysreset) = { |
||||
.name = "x86-sysreset", |
||||
.id = UCLASS_SYSRESET, |
||||
.of_match = x86_sysreset_ids, |
||||
.ops = &x86_sysreset_ops, |
||||
.flags = DM_FLAG_PRE_RELOC, |
||||
}; |
Loading…
Reference in new issue