mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
ARM: sunxi: support more Allwinner SoCs
So far we only supported the Allwinner A20 SoC. Add support for most of the other virtualization capable Allwinner SoCs by: - supporting the watchdog in newer (sun8i) SoCs - getting the watchdog address from DT - adding compatible strings for other 32-bit SoCs - adding compatible strings for 64-bit SoCs As all 64-bit SoCs support system reset via PSCI, we don't use the platform specific reset routine there. Should the 32-bit SoCs start to properly support the PSCI 0.2 SYSTEM_RESET call, we will use it for them automatically, as we try PSCI first, then fall back to platform reset. Signed-off-by: Andre Przywara <andre.przywara@arm.com> Signed-off-by: Stefano Stabellini <sstabellini@kernel.org> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
This commit is contained in:
1 parent
e2dfe4a037
commit
f17d2cd2ff
2 files changed
+87
-15
No files matched your search
@@ -5,6 +5,6 @@ obj-$(CONFIG_ARM_32) += midway.o
|
||||
obj-$(CONFIG_ARM_32) += omap5.o
|
||||
obj-$(CONFIG_ARM_32) += rcar2.o
|
||||
obj-$(CONFIG_ARM_64) += seattle.o
|
||||
obj-$(CONFIG_ARM_32) += sunxi.o
|
||||
obj-y += sunxi.o
|
||||
obj-$(CONFIG_ARM_64) += xgene-storm.o
|
||||
obj-$(CONFIG_ARM_64) += xilinx-zynqmp.o
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* xen/arch/arm/platforms/sunxi.c
|
||||
*
|
||||
* SUNXI (AllWinner A20/A31) specific settings
|
||||
* SUNXI (Allwinner ARM SoCs) specific settings
|
||||
*
|
||||
* Copyright (c) 2013 Citrix Systems.
|
||||
*
|
||||
@@ -22,36 +22,103 @@
|
||||
#include <asm/io.h>
|
||||
|
||||
/* Watchdog constants: */
|
||||
#define SUNXI_WDT_BASE 0x01c20c90
|
||||
#define SUNXI_WDT_MODE 0x04
|
||||
#define SUNXI_WDT_MODEADDR (SUNXI_WDT_BASE + SUNXI_WDT_MODE)
|
||||
#define SUNXI_WDT_MODE_REG 0x04
|
||||
#define SUNXI_WDT_MODE_EN (1 << 0)
|
||||
#define SUNXI_WDT_MODE_RST_EN (1 << 1)
|
||||
|
||||
#define SUNXI_WDT_CONFIG_SYSTEM_RESET (1 << 0)
|
||||
#define SUNXI_WDOG0_CFG_REG 0x14
|
||||
#define SUNXI_WDOG0_MODE_REG 0x18
|
||||
|
||||
static void __iomem *sunxi_map_watchdog(bool *new_wdt)
|
||||
{
|
||||
void __iomem *wdt;
|
||||
struct dt_device_node *node;
|
||||
paddr_t wdt_start, wdt_len;
|
||||
bool _new_wdt = false;
|
||||
int ret;
|
||||
|
||||
node = dt_find_compatible_node(NULL, NULL, "allwinner,sun6i-a31-wdt");
|
||||
if ( node )
|
||||
_new_wdt = true;
|
||||
else
|
||||
node = dt_find_compatible_node(NULL, NULL, "allwinner,sun4i-a10-wdt");
|
||||
|
||||
if ( !node )
|
||||
{
|
||||
dprintk(XENLOG_ERR, "Cannot find matching watchdog node in DT\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = dt_device_get_address(node, 0, &wdt_start, &wdt_len);
|
||||
if ( ret )
|
||||
{
|
||||
dprintk(XENLOG_ERR, "Cannot read watchdog register address\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wdt = ioremap_nocache(wdt_start & PAGE_MASK, PAGE_SIZE);
|
||||
if ( !wdt )
|
||||
{
|
||||
dprintk(XENLOG_ERR, "Unable to map watchdog register!\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( new_wdt )
|
||||
*new_wdt = _new_wdt;
|
||||
|
||||
return wdt + (wdt_start & ~PAGE_MASK);
|
||||
}
|
||||
|
||||
/* Enable watchdog to trigger a reset after 500 ms */
|
||||
static void sunxi_old_wdt_reset(void __iomem *wdt)
|
||||
{
|
||||
writel(SUNXI_WDT_MODE_EN | SUNXI_WDT_MODE_RST_EN,
|
||||
wdt + SUNXI_WDT_MODE_REG);
|
||||
}
|
||||
|
||||
static void sunxi_new_wdt_reset(void __iomem *wdt)
|
||||
{
|
||||
writel(SUNXI_WDT_CONFIG_SYSTEM_RESET, wdt + SUNXI_WDOG0_CFG_REG);
|
||||
writel(SUNXI_WDT_MODE_EN, wdt + SUNXI_WDOG0_MODE_REG);
|
||||
}
|
||||
|
||||
static void sunxi_reset(void)
|
||||
{
|
||||
void __iomem *wdt;
|
||||
bool is_new_wdt;
|
||||
|
||||
wdt = ioremap_nocache(SUNXI_WDT_MODEADDR & PAGE_MASK, PAGE_SIZE);
|
||||
wdt = sunxi_map_watchdog(&is_new_wdt);
|
||||
if ( !wdt )
|
||||
{
|
||||
dprintk(XENLOG_ERR, "Unable to map watchdog register!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable watchdog to trigger a reset after 500 ms: */
|
||||
writel(SUNXI_WDT_MODE_EN | SUNXI_WDT_MODE_RST_EN,
|
||||
wdt + (SUNXI_WDT_MODEADDR & ~PAGE_MASK));
|
||||
if ( is_new_wdt )
|
||||
sunxi_new_wdt_reset(wdt);
|
||||
else
|
||||
sunxi_old_wdt_reset(wdt);
|
||||
|
||||
iounmap(wdt);
|
||||
|
||||
for (;;)
|
||||
wfi();
|
||||
}
|
||||
|
||||
static const char * const sunxi_dt_compat[] __initconst =
|
||||
static const char * const sunxi_v7_dt_compat[] __initconst =
|
||||
{
|
||||
"allwinner,sun6i-a31",
|
||||
"allwinner,sun6i-a31s",
|
||||
"allwinner,sun7i-a20",
|
||||
"allwinner,sun8i-a23",
|
||||
"allwinner,sun8i-a33",
|
||||
"allwinner,sun8i-h2-plus",
|
||||
"allwinner,sun8i-h3",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char * const sunxi_v8_dt_compat[] __initconst =
|
||||
{
|
||||
"allwinner,sun50i-a64",
|
||||
"allwinner,sun50i-h5",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -65,12 +132,17 @@ static const struct dt_device_match sunxi_blacklist_dev[] __initconst =
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
PLATFORM_START(sunxi, "Allwinner A20")
|
||||
.compatible = sunxi_dt_compat,
|
||||
PLATFORM_START(sunxi_v7, "Allwinner ARMv7")
|
||||
.compatible = sunxi_v7_dt_compat,
|
||||
.blacklist_dev = sunxi_blacklist_dev,
|
||||
.reset = sunxi_reset,
|
||||
PLATFORM_END
|
||||
|
||||
PLATFORM_START(sunxi_v8, "Allwinner ARMv8")
|
||||
.compatible = sunxi_v8_dt_compat,
|
||||
.blacklist_dev = sunxi_blacklist_dev,
|
||||
PLATFORM_END
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||