GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,127 @@
#
# System reset devices
#
menu "System reset device drivers"
config SYSRESET
bool "Enable support for system reset drivers"
depends on DM
help
Enable system reset drivers which can be used to reset the CPU or
board. Each driver can provide a reset method which will be called
to effect a reset. The uclass will try all available drivers when
reset_walk() is called.
config SPL_SYSRESET
bool "Enable support for system reset drivers in SPL mode"
depends on SYSRESET && SPL_DM
help
Enable system reset drivers which can be used to reset the CPU or
board. Each driver can provide a reset method which will be called
to effect a reset. The uclass will try all available drivers when
reset_walk() is called.
config TPL_SYSRESET
bool "Enable support for system reset drivers in TPL mode"
depends on SYSRESET && TPL_DM
help
Enable system reset drivers which can be used to reset the CPU or
board. Each driver can provide a reset method which will be called
to effect a reset. The uclass will try all available drivers when
reset_walk() is called.
if SYSRESET
if CMD_POWEROFF
config SYSRESET_CMD_POWEROFF
bool "sysreset implementation of the poweroff command"
help
This should be selected by the appropriate PMIC driver if
the poweroff command is enabled.
endif
config SYSRESET_GPIO
bool "Enable support for GPIO reset driver"
select DM_GPIO
help
Reset support via GPIO pin connected reset logic. This is used for
example on Microblaze where reset logic can be controlled via GPIO
pin which triggers cpu reset.
config SYSRESET_MICROBLAZE
bool "Enable support for Microblaze soft reset"
depends on MICROBLAZE
help
This is soft reset on Microblaze which does jump to 0x0 address.
config SYSRESET_PSCI
bool "Enable support for PSCI System Reset"
depends on ARM_PSCI_FW
select SPL_ARM_PSCI_FW if SPL
help
Enable PSCI SYSTEM_RESET function call. To use this, PSCI firmware
must be running on your system.
config SYSRESET_SOCFPGA
bool "Enable support for Intel SOCFPGA family"
depends on ARCH_SOCFPGA && (TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10)
help
This enables the system reset driver support for Intel SOCFPGA SoCs
(Cyclone 5, Arria 5 and Arria 10).
config SYSRESET_SOCFPGA_S10
bool "Enable support for Intel SOCFPGA Stratix 10"
depends on ARCH_SOCFPGA && TARGET_SOCFPGA_STRATIX10
help
This enables the system reset driver support for Intel SOCFPGA
Stratix SoCs.
config SYSRESET_TI_SCI
bool "TI System Control Interface (TI SCI) system reset driver"
depends on TI_SCI_PROTOCOL
help
This enables the system reset driver support over TI System Control
Interface available on some new TI's SoCs.
endif
config SYSRESET_SYSCON
bool "Enable support for mfd syscon reboot driver"
select REGMAP
select SYSCON
help
Reboot support for generic SYSCON mapped register reset.
config SYSRESET_WATCHDOG
bool "Enable support for watchdog reboot driver"
select WDT
help
Reboot support for generic watchdog reset.
config SYSRESET_X86
bool "Enable support for x86 processor reboot driver"
depends on X86
help
Reboot support for generic x86 processor reset.
config SYSRESET_SPL_X86
bool "Enable support for x86 processor reboot driver in SPL"
depends on X86
help
Reboot support for generic x86 processor reset in SPL.
config SYSRESET_TPL_X86
bool "Enable support for x86 processor reboot driver in TPL"
depends on X86
help
Reboot support for generic x86 processor reset in TPL.
config SYSRESET_MPC83XX
bool "Enable support MPC83xx SoC family reboot driver"
help
Reboot support for NXP MPC83xx SoCs.
endmenu
@@ -0,0 +1,20 @@
# SPDX-License-Identifier: GPL-2.0+
#
# (C) Copyright 2016 Cadence Design Systems Inc.
obj-$(CONFIG_$(SPL_TPL_)SYSRESET) += sysreset-uclass.o
obj-$(CONFIG_ARCH_ASPEED) += sysreset_ast.o
obj-$(CONFIG_ARCH_ROCKCHIP) += sysreset_rockchip.o
obj-$(CONFIG_ARCH_STI) += sysreset_sti.o
obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
obj-$(CONFIG_SYSRESET_GPIO) += sysreset_gpio.o
obj-$(CONFIG_SYSRESET_MPC83XX) += sysreset_mpc83xx.o
obj-$(CONFIG_SYSRESET_MICROBLAZE) += sysreset_microblaze.o
obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o
obj-$(CONFIG_SYSRESET_SOCFPGA) += sysreset_socfpga.o
obj-$(CONFIG_SYSRESET_SOCFPGA_S10) += sysreset_socfpga_s10.o
obj-$(CONFIG_SYSRESET_TI_SCI) += sysreset-ti-sci.o
obj-$(CONFIG_SYSRESET_SYSCON) += sysreset_syscon.o
obj-$(CONFIG_SYSRESET_WATCHDOG) += sysreset_watchdog.o
obj-$(CONFIG_$(SPL_TPL_)SYSRESET_X86) += sysreset_x86.o
obj-$(CONFIG_TARGET_XTFPGA) += sysreset_xtfpga.o
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Texas Instruments System Control Interface (TI SCI) system reset driver
*
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
* Andreas Dannenberg <dannenberg@ti.com>
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <sysreset.h>
#include <linux/soc/ti/ti_sci_protocol.h>
/**
* struct ti_sci_sysreset_data - sysreset controller information structure
* @sci: TI SCI handle used for communication with system controller
*/
struct ti_sci_sysreset_data {
const struct ti_sci_handle *sci;
};
static int ti_sci_sysreset_probe(struct udevice *dev)
{
struct ti_sci_sysreset_data *data = dev_get_priv(dev);
debug("%s(dev=%p)\n", __func__, dev);
if (!data)
return -ENOMEM;
/* Store handle for communication with the system controller */
data->sci = ti_sci_get_handle(dev);
if (IS_ERR(data->sci))
return PTR_ERR(data->sci);
return 0;
}
static int ti_sci_sysreset_request(struct udevice *dev, enum sysreset_t type)
{
struct ti_sci_sysreset_data *data = dev_get_priv(dev);
const struct ti_sci_handle *sci = data->sci;
const struct ti_sci_core_ops *cops = &sci->ops.core_ops;
int ret;
debug("%s(dev=%p, type=%d)\n", __func__, dev, type);
ret = cops->reboot_device(sci);
if (ret)
dev_err(rst->dev, "%s: reboot_device failed (%d)\n",
__func__, ret);
return ret;
}
static struct sysreset_ops ti_sci_sysreset_ops = {
.request = ti_sci_sysreset_request,
};
static const struct udevice_id ti_sci_sysreset_of_match[] = {
{ .compatible = "ti,sci-sysreset", },
{ /* sentinel */ },
};
U_BOOT_DRIVER(ti_sci_sysreset) = {
.name = "ti-sci-sysreset",
.id = UCLASS_SYSRESET,
.of_match = ti_sci_sysreset_of_match,
.probe = ti_sci_sysreset_probe,
.priv_auto_alloc_size = sizeof(struct ti_sci_sysreset_data),
.ops = &ti_sci_sysreset_ops,
};
@@ -0,0 +1,158 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2015 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*/
#define LOG_CATEGORY UCLASS_SYSRESET
#include <common.h>
#include <sysreset.h>
#include <dm.h>
#include <errno.h>
#include <regmap.h>
#include <dm/device-internal.h>
#include <dm/lists.h>
#include <dm/root.h>
#include <linux/err.h>
int sysreset_request(struct udevice *dev, enum sysreset_t type)
{
struct sysreset_ops *ops = sysreset_get_ops(dev);
if (!ops->request)
return -ENOSYS;
return ops->request(dev, type);
}
int sysreset_get_status(struct udevice *dev, char *buf, int size)
{
struct sysreset_ops *ops = sysreset_get_ops(dev);
if (!ops->get_status)
return -ENOSYS;
return ops->get_status(dev, buf, size);
}
int sysreset_get_last(struct udevice *dev)
{
struct sysreset_ops *ops = sysreset_get_ops(dev);
if (!ops->get_last)
return -ENOSYS;
return ops->get_last(dev);
}
int sysreset_walk(enum sysreset_t type)
{
struct udevice *dev;
int ret = -ENOSYS;
while (ret != -EINPROGRESS && type < SYSRESET_COUNT) {
for (uclass_first_device(UCLASS_SYSRESET, &dev);
dev;
uclass_next_device(&dev)) {
ret = sysreset_request(dev, type);
if (ret == -EINPROGRESS)
break;
}
type++;
}
return ret;
}
int sysreset_get_last_walk(void)
{
struct udevice *dev;
int value = -ENOENT;
for (uclass_first_device(UCLASS_SYSRESET, &dev);
dev;
uclass_next_device(&dev)) {
int ret;
ret = sysreset_get_last(dev);
if (ret >= 0) {
value = ret;
break;
}
}
return value;
}
void sysreset_walk_halt(enum sysreset_t type)
{
int ret;
ret = sysreset_walk(type);
/* Wait for the reset to take effect */
if (ret == -EINPROGRESS)
mdelay(100);
/* Still no reset? Give up */
log_err("System reset not supported on this platform\n");
hang();
}
/**
* reset_cpu() - calls sysreset_walk(SYSRESET_WARM)
*/
void reset_cpu(ulong addr)
{
sysreset_walk_halt(SYSRESET_WARM);
}
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
printf("resetting ...\n");
sysreset_walk_halt(SYSRESET_COLD);
return 0;
}
#if IS_ENABLED(CONFIG_SYSRESET_CMD_POWEROFF)
int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
int ret;
puts("poweroff ...\n");
mdelay(100);
ret = sysreset_walk(SYSRESET_POWER_OFF);
if (ret == -EINPROGRESS)
mdelay(1000);
/*NOTREACHED when power off*/
return CMD_RET_FAILURE;
}
#endif
static int sysreset_post_bind(struct udevice *dev)
{
#if defined(CONFIG_NEEDS_MANUAL_RELOC)
struct sysreset_ops *ops = sysreset_get_ops(dev);
static int reloc_done;
if (!reloc_done) {
if (ops->request)
ops->request += gd->reloc_off;
reloc_done++;
}
#endif
return 0;
}
UCLASS_DRIVER(sysreset) = {
.id = UCLASS_SYSRESET,
.name = "sysreset",
.post_bind = sysreset_post_bind,
};
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: GPL-2.0
/*
* (C) Copyright 2016 Google, Inc
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <sysreset.h>
#include <wdt.h>
#include <asm/io.h>
#include <asm/arch/wdt.h>
#include <linux/err.h>
static int ast_sysreset_request(struct udevice *dev, enum sysreset_t type)
{
struct udevice *wdt;
u32 reset_mode;
int ret = uclass_first_device(UCLASS_WDT, &wdt);
if (ret)
return ret;
switch (type) {
case SYSRESET_WARM:
reset_mode = WDT_CTRL_RESET_CPU;
break;
case SYSRESET_COLD:
reset_mode = WDT_CTRL_RESET_CHIP;
break;
default:
return -EPROTONOSUPPORT;
}
ret = wdt_expire_now(wdt, reset_mode);
if (ret) {
debug("Sysreset failed: %d", ret);
return ret;
}
return -EINPROGRESS;
}
static struct sysreset_ops ast_sysreset = {
.request = ast_sysreset_request,
};
U_BOOT_DRIVER(sysreset_ast) = {
.name = "ast_sysreset",
.id = UCLASS_SYSRESET,
.ops = &ast_sysreset,
};
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2018 Xilinx, Inc. - Michal Simek
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <sysreset.h>
#include <asm/gpio.h>
struct gpio_reboot_priv {
struct gpio_desc gpio;
};
static int gpio_reboot_request(struct udevice *dev, enum sysreset_t type)
{
struct gpio_reboot_priv *priv = dev_get_priv(dev);
/*
* When debug log is enabled please make sure that chars won't end up
* in output fifo. Or you can append udelay(); to get enough time
* to HW to emit output fifo.
*/
debug("GPIO reset\n");
/* Writing 1 respects polarity (active high/low) based on gpio->flags */
return dm_gpio_set_value(&priv->gpio, 1);
}
static struct sysreset_ops gpio_reboot_ops = {
.request = gpio_reboot_request,
};
int gpio_reboot_probe(struct udevice *dev)
{
struct gpio_reboot_priv *priv = dev_get_priv(dev);
/*
* Linux kernel DT binding contain others optional properties
* which are not supported now
*/
return gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT);
}
static const struct udevice_id led_gpio_ids[] = {
{ .compatible = "gpio-restart" },
{ }
};
U_BOOT_DRIVER(gpio_reboot) = {
.id = UCLASS_SYSRESET,
.name = "gpio_restart",
.of_match = led_gpio_ids,
.ops = &gpio_reboot_ops,
.priv_auto_alloc_size = sizeof(struct gpio_reboot_priv),
.probe = gpio_reboot_probe,
};
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2018 Xilinx, Inc. - Michal Simek
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <sysreset.h>
#include <linux/err.h>
static int microblaze_sysreset_request(struct udevice *dev,
enum sysreset_t type)
{
puts("Microblaze soft reset sysreset\n");
__asm__ __volatile__ (" mts rmsr, r0;" \
"bra r0");
return -EINPROGRESS;
}
static struct sysreset_ops microblaze_sysreset = {
.request = microblaze_sysreset_request,
};
U_BOOT_DRIVER(sysreset_microblaze) = {
.id = UCLASS_SYSRESET,
.name = "mb_soft_reset",
.ops = &microblaze_sysreset,
};
@@ -0,0 +1,212 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2018
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
*/
#include <common.h>
#include <dm.h>
#include <sysreset.h>
#include <wait_bit.h>
#include "sysreset_mpc83xx.h"
/* Magic 4-byte word to enable reset ('RSTE' in ASCII) */
static const u32 RPR_MAGIC = 0x52535445;
/* Wait at most 2000ms for reset control enable bit */
static const uint RESET_WAIT_TIMEOUT = 2000;
/**
* __do_reset() - Execute the system reset
*
* Return: The functions resets the system, and never returns.
*/
static int __do_reset(void)
{
ulong msr;
int res;
immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
puts("Resetting the board.\n");
/* Interrupts and MMU off */
msr = mfmsr();
msr &= ~(MSR_EE | MSR_IR | MSR_DR);
mtmsr(msr);
/* Enable Reset Control Reg */
out_be32(&immap->reset.rpr, RPR_MAGIC);
sync();
isync();
/* Confirm Reset Control Reg is enabled */
res = wait_for_bit_be32(&immap->reset.rcer, RCER_CRE, true,
RESET_WAIT_TIMEOUT, false);
if (res) {
debug("%s: Timed out waiting for reset control to be set\n",
__func__);
return res;
}
udelay(200);
/* Perform reset, only one bit */
out_be32(&immap->reset.rcr, RCR_SWHR);
/* Never executes */
return 0;
}
static int mpc83xx_sysreset_request(struct udevice *dev, enum sysreset_t type)
{
switch (type) {
case SYSRESET_WARM:
case SYSRESET_COLD:
return __do_reset();
default:
return -EPROTONOSUPPORT;
}
return -EINPROGRESS;
}
/**
* print_83xx_arb_event() - Print arbiter events to buffer
* @force: Print arbiter events, even if none are indicated by the system
* @buf: The buffer to receive the printed arbiter event information
* @size: The size of the buffer to receive the printed arbiter event
* information in bytes
*
* Return: Number of bytes printed to buffer, -ve on error
*/
static int print_83xx_arb_event(bool force, char *buf, int size)
{
int etype = (gd->arch.arbiter_event_attributes & AEATR_EVENT)
>> AEATR_EVENT_SHIFT;
int mstr_id = (gd->arch.arbiter_event_attributes & AEATR_MSTR_ID)
>> AEATR_MSTR_ID_SHIFT;
int tbst = (gd->arch.arbiter_event_attributes & AEATR_TBST)
>> AEATR_TBST_SHIFT;
int tsize = (gd->arch.arbiter_event_attributes & AEATR_TSIZE)
>> AEATR_TSIZE_SHIFT;
int ttype = (gd->arch.arbiter_event_attributes & AEATR_TTYPE)
>> AEATR_TTYPE_SHIFT;
int tsize_val = (tbst << 3) | tsize;
int tsize_bytes = tbst ? (tsize ? tsize : 8) : 16 + 8 * tsize;
int res = 0;
/*
* If we don't force output, and there is no event (event address ==
* 0), then don't print anything
*/
if (!force && !gd->arch.arbiter_event_address)
return 0;
if (CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_FULL)) {
res = snprintf(buf, size,
"Arbiter Event Status:\n"
" %s: 0x%08lX\n"
" %s: 0x%1x = %s\n"
" %s: 0x%02x = %s\n"
" %s: 0x%1x = %d bytes\n"
" %s: 0x%02x = %s\n",
"Event Address", gd->arch.arbiter_event_address,
"Event Type", etype, event[etype],
"Master ID", mstr_id, master[mstr_id],
"Transfer Size", tsize_val, tsize_bytes,
"Transfer Type", ttype, transfer[ttype]);
} else if (CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_BRIEF)) {
res = snprintf(buf, size,
"Arbiter Event Status: AEATR=0x%08lX, AEADR=0x%08lX\n",
gd->arch.arbiter_event_attributes,
gd->arch.arbiter_event_address);
}
return res;
}
static int mpc83xx_sysreset_get_status(struct udevice *dev, char *buf, int size)
{
/* Ad-hoc data structure to map RSR bit values to their descriptions */
static const struct {
/* Bit mask for the bit in question */
ulong mask;
/* Description of the bitmask in question */
char *desc;
} bits[] = {
{
RSR_SWSR, "Software Soft"}, {
RSR_SWHR, "Software Hard"}, {
RSR_JSRS, "JTAG Soft"}, {
RSR_CSHR, "Check Stop"}, {
RSR_SWRS, "Software Watchdog"}, {
RSR_BMRS, "Bus Monitor"}, {
RSR_SRS, "External/Internal Soft"}, {
RSR_HRS, "External/Internal Hard"}
};
int res;
ulong rsr = gd->arch.reset_status;
int i;
char *sep;
res = snprintf(buf, size, "Reset Status:");
if (res < 0) {
debug("%s: Could not write reset status message (err = %d)\n",
dev->name, res);
return -EIO;
}
buf += res;
size -= res;
sep = " ";
for (i = 0; i < ARRAY_SIZE(bits); i++)
/* Print description of set bits */
if (rsr & bits[i].mask) {
res = snprintf(buf, size, "%s%s%s", sep, bits[i].desc,
(i == ARRAY_SIZE(bits) - 1) ? "\n" : "");
if (res < 0) {
debug("%s: Could not write reset status message (err = %d)\n",
dev->name, res);
return -EIO;
}
buf += res;
size -= res;
sep = ", ";
}
/*
* TODO(mario.six@gdsys.cc): Move this into a dedicated
* arbiter driver
*/
if (CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_FULL) ||
CONFIG_IS_ENABLED(CONFIG_DISPLAY_AER_BRIEF)) {
/*
* If there was a bus monitor reset event, we force the arbiter
* event to be printed
*/
res = print_83xx_arb_event(rsr & RSR_BMRS, buf, size);
if (res < 0) {
debug("%s: Could not write arbiter event message (err = %d)\n",
dev->name, res);
return -EIO;
}
buf += res;
size -= res;
}
snprintf(buf, size, "\n");
return 0;
}
static struct sysreset_ops mpc83xx_sysreset = {
.request = mpc83xx_sysreset_request,
.get_status = mpc83xx_sysreset_get_status,
};
U_BOOT_DRIVER(sysreset_mpc83xx) = {
.name = "mpc83xx_sysreset",
.id = UCLASS_SYSRESET,
.ops = &mpc83xx_sysreset,
};
@@ -0,0 +1,103 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2018
* Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
*/
#ifndef _SYSRESET_MPC83XX_H_
#define _SYSRESET_MPC83XX_H_
/*
* String array for all possible event types; indexed by the EVENT field of the
* AEATR register.
*/
static const char * const event[] = {
"Address Time Out",
"Data Time Out",
"Address Only Transfer Type",
"External Control Word Transfer Type",
"Reserved Transfer Type",
"Transfer Error",
"reserved",
"reserved"
};
/*
* String array for all possible master IDs, which reflects the source of the
* transaction that caused the error; indexed by the MSTR_ID field of the AEATR
* register.
*/
static const char * const master[] = {
"e300 Core Data Transaction",
"reserved",
"e300 Core Instruction Fetch",
"reserved",
"TSEC1",
"TSEC2",
"USB MPH",
"USB DR",
"Encryption Core",
"I2C Boot Sequencer",
"JTAG",
"reserved",
"eSDHC",
"PCI1",
"PCI2",
"DMA",
"QUICC Engine 00",
"QUICC Engine 01",
"QUICC Engine 10",
"QUICC Engine 11",
"reserved",
"reserved",
"reserved",
"reserved",
"SATA1",
"SATA2",
"SATA3",
"SATA4",
"reserved",
"PCI Express 1",
"PCI Express 2",
"TDM-DMAC"
};
/*
* String array for all possible transfer types; indexed by the TTYPE field of
* the AEATR register.
*/
static const char * const transfer[] = {
"Address-only, Clean Block",
"Address-only, lwarx reservation set",
"Single-beat or Burst write",
"reserved",
"Address-only, Flush Block",
"reserved",
"Burst write",
"reserved",
"Address-only, sync",
"Address-only, tlbsync",
"Single-beat or Burst read",
"Single-beat or Burst read",
"Address-only, Kill Block",
"Address-only, icbi",
"Burst read",
"reserved",
"Address-only, eieio",
"reserved",
"Single-beat write",
"reserved",
"ecowx - Illegal single-beat write",
"reserved",
"reserved",
"reserved",
"Address-only, TLB Invalidate",
"reserved",
"Single-beat or Burst read",
"reserved",
"eciwx - Illegal single-beat read",
"reserved",
"Burst read",
"reserved"
};
#endif /* _SYSRESET_MPC83XX_H_ */
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Masahiro Yamada <yamada.masahiro@socionext.com>
*/
#include <common.h>
#include <dm.h>
#include <sysreset.h>
#include <linux/errno.h>
#include <linux/psci.h>
static int psci_sysreset_request(struct udevice *dev, enum sysreset_t type)
{
unsigned long function_id;
switch (type) {
case SYSRESET_WARM:
case SYSRESET_COLD:
function_id = PSCI_0_2_FN_SYSTEM_RESET;
break;
case SYSRESET_POWER_OFF:
function_id = PSCI_0_2_FN_SYSTEM_OFF;
break;
default:
return -ENOSYS;
}
invoke_psci_fn(function_id, 0, 0, 0);
return -EINPROGRESS;
}
static struct sysreset_ops psci_sysreset_ops = {
.request = psci_sysreset_request,
};
U_BOOT_DRIVER(psci_sysreset) = {
.name = "psci-sysreset",
.id = UCLASS_SYSRESET,
.ops = &psci_sysreset_ops,
};
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: GPL-2.0
/*
* (C) Copyright 2017 Rockchip Electronics Co., Ltd
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <sysreset.h>
#include <asm/io.h>
#include <asm/arch-rockchip/clock.h>
#include <asm/arch-rockchip/cru_rk3328.h>
#include <asm/arch-rockchip/hardware.h>
#include <linux/err.h>
int rockchip_sysreset_request(struct udevice *dev, enum sysreset_t type)
{
struct sysreset_reg *offset = dev_get_priv(dev);
unsigned long cru_base = (unsigned long)rockchip_get_cru();
if (IS_ERR_VALUE(cru_base))
return (int)cru_base;
switch (type) {
case SYSRESET_WARM:
writel(0xeca8, cru_base + offset->glb_srst_snd_value);
break;
case SYSRESET_COLD:
writel(0xfdb9, cru_base + offset->glb_srst_fst_value);
break;
default:
return -EPROTONOSUPPORT;
}
return -EINPROGRESS;
}
static struct sysreset_ops rockchip_sysreset = {
.request = rockchip_sysreset_request,
};
U_BOOT_DRIVER(sysreset_rockchip) = {
.name = "rockchip_sysreset",
.id = UCLASS_SYSRESET,
.ops = &rockchip_sysreset,
};
@@ -0,0 +1,136 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2015 Google, Inc
* Written by Simon Glass <sjg@chromium.org>
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <sysreset.h>
#include <asm/state.h>
#include <asm/test.h>
static int sandbox_warm_sysreset_request(struct udevice *dev,
enum sysreset_t type)
{
struct sandbox_state *state = state_get_current();
switch (type) {
case SYSRESET_WARM:
state->last_sysreset = type;
break;
default:
return -ENOSYS;
}
if (!state->sysreset_allowed[type])
return -EACCES;
return -EINPROGRESS;
}
int sandbox_warm_sysreset_get_status(struct udevice *dev, char *buf, int size)
{
strlcpy(buf, "Reset Status: WARM", size);
return 0;
}
int sandbox_warm_sysreset_get_last(struct udevice *dev)
{
return SYSRESET_WARM;
}
static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type)
{
struct sandbox_state *state = state_get_current();
/*
* If we have a device tree, the device we created from platform data
* (see the U_BOOT_DEVICE() declaration below) should not do anything.
* If we are that device, return an error.
*/
if (state->fdt_fname && !dev_of_valid(dev))
return -ENODEV;
switch (type) {
case SYSRESET_COLD:
state->last_sysreset = type;
break;
case SYSRESET_POWER_OFF:
state->last_sysreset = type;
if (!state->sysreset_allowed[type])
return -EACCES;
sandbox_exit();
break;
case SYSRESET_POWER:
if (!state->sysreset_allowed[type])
return -EACCES;
sandbox_exit();
default:
return -ENOSYS;
}
if (!state->sysreset_allowed[type])
return -EACCES;
return -EINPROGRESS;
}
int sandbox_sysreset_get_status(struct udevice *dev, char *buf, int size)
{
strlcpy(buf, "Reset Status: COLD", size);
return 0;
}
int sandbox_sysreset_get_last(struct udevice *dev)
{
struct sandbox_state *state = state_get_current();
/*
* The first phase is a power reset, after that we assume we don't
* know.
*/
return state->jumped_fname ? SYSRESET_WARM : SYSRESET_POWER;
}
static struct sysreset_ops sandbox_sysreset_ops = {
.request = sandbox_sysreset_request,
.get_status = sandbox_sysreset_get_status,
.get_last = sandbox_sysreset_get_last,
};
static const struct udevice_id sandbox_sysreset_ids[] = {
{ .compatible = "sandbox,reset" },
{ }
};
U_BOOT_DRIVER(sysreset_sandbox) = {
.name = "sysreset_sandbox",
.id = UCLASS_SYSRESET,
.of_match = sandbox_sysreset_ids,
.ops = &sandbox_sysreset_ops,
};
static struct sysreset_ops sandbox_warm_sysreset_ops = {
.request = sandbox_warm_sysreset_request,
.get_status = sandbox_warm_sysreset_get_status,
.get_last = sandbox_warm_sysreset_get_last,
};
static const struct udevice_id sandbox_warm_sysreset_ids[] = {
{ .compatible = "sandbox,warm-reset" },
{ }
};
U_BOOT_DRIVER(warm_sysreset_sandbox) = {
.name = "warm_sysreset_sandbox",
.id = UCLASS_SYSRESET,
.of_match = sandbox_warm_sysreset_ids,
.ops = &sandbox_warm_sysreset_ops,
};
/* This is here in case we don't have a device tree */
U_BOOT_DEVICE(sysreset_sandbox_non_fdt) = {
.name = "sysreset_sandbox",
};
@@ -0,0 +1,56 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2019 Pepperl+Fuchs
* Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <sysreset.h>
#include <asm/io.h>
#include <asm/arch/reset_manager.h>
struct socfpga_sysreset_data {
struct socfpga_reset_manager *rstmgr_base;
};
static int socfpga_sysreset_request(struct udevice *dev,
enum sysreset_t type)
{
struct socfpga_sysreset_data *data = dev_get_priv(dev);
switch (type) {
case SYSRESET_WARM:
writel(BIT(RSTMGR_CTRL_SWWARMRSTREQ_LSB),
&data->rstmgr_base->ctrl);
break;
case SYSRESET_COLD:
writel(BIT(RSTMGR_CTRL_SWCOLDRSTREQ_LSB),
&data->rstmgr_base->ctrl);
break;
default:
return -EPROTONOSUPPORT;
}
return -EINPROGRESS;
}
static int socfpga_sysreset_probe(struct udevice *dev)
{
struct socfpga_sysreset_data *data = dev_get_priv(dev);
data->rstmgr_base = devfdt_get_addr_ptr(dev);
return 0;
}
static struct sysreset_ops socfpga_sysreset = {
.request = socfpga_sysreset_request,
};
U_BOOT_DRIVER(sysreset_socfpga) = {
.id = UCLASS_SYSRESET,
.name = "socfpga_sysreset",
.priv_auto_alloc_size = sizeof(struct socfpga_sysreset_data),
.ops = &socfpga_sysreset,
.probe = socfpga_sysreset_probe,
};
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2019 Pepperl+Fuchs
* Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <sysreset.h>
#include <asm/arch/mailbox_s10.h>
static int socfpga_sysreset_request(struct udevice *dev,
enum sysreset_t type)
{
puts("Mailbox: Issuing mailbox cmd REBOOT_HPS\n");
mbox_reset_cold();
return -EINPROGRESS;
}
static struct sysreset_ops socfpga_sysreset = {
.request = socfpga_sysreset_request,
};
U_BOOT_DRIVER(sysreset_socfpga) = {
.id = UCLASS_SYSRESET,
.name = "socfpga_sysreset",
.ops = &socfpga_sysreset,
};
@@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017, STMicroelectronics - All Rights Reserved
* Author(s): Patrice Chotard, <patrice.chotard@st.com> for STMicroelectronics.
*/
#include <common.h>
#include <dm.h>
#include <regmap.h>
#include <syscon.h>
#include <sysreset.h>
#include <asm/io.h>
DECLARE_GLOBAL_DATA_PTR;
struct sti_sysreset_priv {
phys_addr_t base;
};
static int sti_sysreset_request(struct udevice *dev, enum sysreset_t type)
{
struct sti_sysreset_priv *priv = dev_get_priv(dev);
generic_clear_bit(0, (void __iomem *)priv->base);
return -EINPROGRESS;
}
static int sti_sysreset_probe(struct udevice *dev)
{
struct sti_sysreset_priv *priv = dev_get_priv(dev);
struct udevice *syscon;
struct regmap *regmap;
struct fdtdec_phandle_args syscfg_phandle;
int ret;
/* get corresponding syscon phandle */
ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev),
"st,syscfg", NULL, 0, 0,
&syscfg_phandle);
if (ret < 0) {
pr_err("Can't get syscfg phandle: %d\n", ret);
return ret;
}
ret = uclass_get_device_by_of_offset(UCLASS_SYSCON,
syscfg_phandle.node,
&syscon);
if (ret) {
pr_err("%s: uclass_get_device_by_of_offset failed: %d\n",
__func__, ret);
return ret;
}
regmap = syscon_get_regmap(syscon);
if (!regmap) {
pr_err("unable to get regmap for %s\n", syscon->name);
return -ENODEV;
}
priv->base = regmap->ranges[0].start;
return 0;
}
static struct sysreset_ops sti_sysreset = {
.request = sti_sysreset_request,
};
static const struct udevice_id sti_sysreset_ids[] = {
{ .compatible = "st,stih407-restart" },
{ }
};
U_BOOT_DRIVER(sysreset_sti) = {
.name = "sysreset_sti",
.id = UCLASS_SYSRESET,
.ops = &sti_sysreset,
.probe = sti_sysreset_probe,
.of_match = sti_sysreset_ids,
.priv_auto_alloc_size = sizeof(struct sti_sysreset_priv),
};
@@ -0,0 +1,69 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
*
* Derived from linux/drivers/power/reset/syscon-reboot.c:
* Copyright (C) 2013, Applied Micro Circuits Corporation
* Author: Feng Kan <fkan@apm.com>
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <regmap.h>
#include <sysreset.h>
#include <syscon.h>
struct syscon_reboot_priv {
struct regmap *regmap;
unsigned int offset;
unsigned int mask;
};
static int syscon_reboot_request(struct udevice *dev, enum sysreset_t type)
{
struct syscon_reboot_priv *priv = dev_get_priv(dev);
ulong driver_data = dev_get_driver_data(dev);
if (type != driver_data)
return -EPROTONOSUPPORT;
regmap_write(priv->regmap, priv->offset, priv->mask);
return -EINPROGRESS;
}
static struct sysreset_ops syscon_reboot_ops = {
.request = syscon_reboot_request,
};
int syscon_reboot_probe(struct udevice *dev)
{
struct syscon_reboot_priv *priv = dev_get_priv(dev);
priv->regmap = syscon_regmap_lookup_by_phandle(dev, "regmap");
if (IS_ERR(priv->regmap)) {
pr_err("unable to find regmap\n");
return -ENODEV;
}
priv->offset = dev_read_u32_default(dev, "offset", 0);
priv->mask = dev_read_u32_default(dev, "mask", 0);
return 0;
}
static const struct udevice_id syscon_reboot_ids[] = {
{ .compatible = "syscon-reboot", .data = SYSRESET_COLD },
{ .compatible = "syscon-poweroff", .data = SYSRESET_POWER_OFF },
{ /* sentinel */ }
};
U_BOOT_DRIVER(syscon_reboot) = {
.name = "syscon_reboot",
.id = UCLASS_SYSRESET,
.of_match = syscon_reboot_ids,
.probe = syscon_reboot_probe,
.priv_auto_alloc_size = sizeof(struct syscon_reboot_priv),
.ops = &syscon_reboot_ops,
};
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Álvaro Fernández Rojas <noltari@gmail.com>
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <sysreset.h>
#include <wdt.h>
struct wdt_reboot_priv {
struct udevice *wdt;
};
static int wdt_reboot_request(struct udevice *dev, enum sysreset_t type)
{
struct wdt_reboot_priv *priv = dev_get_priv(dev);
int ret;
ret = wdt_expire_now(priv->wdt, 0);
if (ret)
return ret;
return -EINPROGRESS;
}
static struct sysreset_ops wdt_reboot_ops = {
.request = wdt_reboot_request,
};
int wdt_reboot_probe(struct udevice *dev)
{
struct wdt_reboot_priv *priv = dev_get_priv(dev);
int err;
err = uclass_get_device_by_phandle(UCLASS_WDT, dev,
"wdt", &priv->wdt);
if (err) {
pr_err("unable to find wdt device\n");
return err;
}
return 0;
}
static const struct udevice_id wdt_reboot_ids[] = {
{ .compatible = "wdt-reboot" },
{ /* sentinel */ }
};
U_BOOT_DRIVER(wdt_reboot) = {
.name = "wdt_reboot",
.id = UCLASS_SYSRESET,
.of_match = wdt_reboot_ids,
.ops = &wdt_reboot_ops,
.priv_auto_alloc_size = sizeof(struct wdt_reboot_priv),
.probe = wdt_reboot_probe,
};
@@ -0,0 +1,158 @@
// 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 <acpi_s3.h>
#include <dm.h>
#include <efi_loader.h>
#include <pch.h>
#include <sysreset.h>
#include <asm/io.h>
#include <asm/processor.h>
struct x86_sysreset_platdata {
struct udevice *pch;
};
/*
* Power down the machine by using the power management sleep control
* of the chipset. This will currently only work on Intel chipsets.
* However, adapting it to new chipsets is fairly simple. You will
* have to find the IO address of the power management register block
* in your southbridge, and look up the appropriate SLP_TYP_S5 value
* from your southbridge's data sheet.
*
* This function never returns.
*/
int pch_sysreset_power_off(struct udevice *dev)
{
struct x86_sysreset_platdata *plat = dev_get_platdata(dev);
struct pch_pmbase_info pm;
u32 reg32;
int ret;
if (!plat->pch)
return -ENOENT;
ret = pch_ioctl(plat->pch, PCH_REQ_PMBASE_INFO, &pm, sizeof(pm));
if (ret)
return ret;
/*
* Mask interrupts or system might stay in a coma, not executing code
* anymore, but not powered off either.
*/
asm("cli");
/*
* Avoid any GPI waking the system from S5* or the system might stay in
* a coma
*/
outl(0x00000000, pm.base + pm.gpio0_en_ofs);
/* Clear Power Button Status */
outw(PWRBTN_STS, pm.base + pm.pm1_sts_ofs);
/* PMBASE + 4, Bit 10-12, Sleeping Type, * set to 111 -> S5, soft_off */
reg32 = inl(pm.base + pm.pm1_cnt_ofs);
/* Set Sleeping Type to S5 (poweroff) */
reg32 &= ~(SLP_EN | SLP_TYP);
reg32 |= SLP_TYP_S5;
outl(reg32, pm.base + pm.pm1_cnt_ofs);
/* Now set the Sleep Enable bit */
reg32 |= SLP_EN;
outl(reg32, pm.base + pm.pm1_cnt_ofs);
for (;;)
asm("hlt");
}
static int x86_sysreset_request(struct udevice *dev, enum sysreset_t type)
{
int value;
int ret;
switch (type) {
case SYSRESET_WARM:
value = SYS_RST | RST_CPU;
break;
case SYSRESET_COLD:
value = SYS_RST | RST_CPU | FULL_RST;
break;
case SYSRESET_POWER_OFF:
ret = pch_sysreset_power_off(dev);
if (ret)
return ret;
return -EINPROGRESS;
default:
return -ENOSYS;
}
outb(value, IO_PORT_RESET);
return -EINPROGRESS;
}
static int x86_sysreset_get_last(struct udevice *dev)
{
return SYSRESET_POWER;
}
#ifdef CONFIG_EFI_LOADER
void __efi_runtime EFIAPI efi_reset_system(
enum efi_reset_type reset_type,
efi_status_t reset_status,
unsigned long data_size, void *reset_data)
{
int value;
/*
* inline this code since we are not caused in the context of a
* udevice and passing NULL to x86_sysreset_request() is too horrible.
*/
if (reset_type == EFI_RESET_COLD ||
reset_type == EFI_RESET_PLATFORM_SPECIFIC)
value = SYS_RST | RST_CPU | FULL_RST;
else /* assume EFI_RESET_WARM since we cannot return an error */
value = SYS_RST | RST_CPU;
outb(value, IO_PORT_RESET);
/* TODO EFI_RESET_SHUTDOWN */
while (1) { }
}
#endif
static int x86_sysreset_probe(struct udevice *dev)
{
struct x86_sysreset_platdata *plat = dev_get_platdata(dev);
/* Locate the PCH if there is one. It isn't essential */
uclass_first_device(UCLASS_PCH, &plat->pch);
return 0;
}
static const struct udevice_id x86_sysreset_ids[] = {
{ .compatible = "x86,reset" },
{ }
};
static struct sysreset_ops x86_sysreset_ops = {
.request = x86_sysreset_request,
.get_last = x86_sysreset_get_last,
};
U_BOOT_DRIVER(x86_sysreset) = {
.name = "x86-sysreset",
.id = UCLASS_SYSRESET,
.of_match = x86_sysreset_ids,
.ops = &x86_sysreset_ops,
.probe = x86_sysreset_probe,
.platdata_auto_alloc_size = sizeof(struct x86_sysreset_platdata),
};
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Cadence Tensilica xtfpga system reset driver.
*
* (C) Copyright 2016 Cadence Design Systems Inc.
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <sysreset.h>
#include <asm/io.h>
static int xtfpga_reset_request(struct udevice *dev, enum sysreset_t type)
{
switch (type) {
case SYSRESET_COLD:
writel(CONFIG_SYS_FPGAREG_RESET_CODE,
CONFIG_SYS_FPGAREG_RESET);
break;
default:
return -EPROTONOSUPPORT;
}
return -EINPROGRESS;
}
static struct sysreset_ops xtfpga_sysreset_ops = {
.request = xtfpga_reset_request,
};
U_BOOT_DRIVER(xtfpga_sysreset) = {
.name = "xtfpga_sysreset",
.id = UCLASS_SYSRESET,
.ops = &xtfpga_sysreset_ops,
};