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:
Andre Przywara authored and Stefano Stabellini committed 2017-10-10 17:30:32 -07:00
1 parent e2dfe4a037
commit f17d2cd2ff
2 files changed
+87 -15

No files matched your search

+1 -1
View File
@@ -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
+86 -14
View File
@@ -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
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.