GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -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 = µblaze_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,
|
||||
};
|
||||
Reference in New Issue
Block a user