Re: [Xen-devel] [PATCH] ARM: sunxi: support more Allwinner SoCs

2017-10-10 Thread Stefano Stabellini
On Sat, 7 Oct 2017, Andre Przywara wrote:
> 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 

Reviewed-by: Stefano Stabellini 

There were a couple of tabs, which I fixed on commit.


> ---
> Hi,
> 
> this is based on staging, which has the required UART fix.
> Tested on:
> - BananaPi M1 (A20)
> - OrangePi Zero (H2+, which is almost the same as H3)
> - OrangePi PC 2 (H5, arm64)
> - Pine64+ (A64, arm64)
> 
> On the 64-bit boards I could boot into Dom0 prompt.
> I had issues with U-Boot's fdt command on the two 32-bit boards, so couldn't
> inject the Dom0 magic into the DT. But at least Xen booted and reset
> worked with both the "old" and "new" watchdog.
> The newer boards require "clk_ignore_unused" on the Linux command line at
> the moment, I will try to find a more sustainable solution next week.
> Will try to update the Wiki later on.
> 
> Please let me know if this is worth splitting up into multiple patches
> (watchdog address from DT, new watchdog support, arm64 support).
> 
> Many thanks to Awais for the idea and his original patch, and for testing
> this one!
> 
> Cheers,
> Andre.
> 
>  xen/arch/arm/platforms/Makefile |  2 +-
>  xen/arch/arm/platforms/sunxi.c  | 96 
> +++--
>  2 files changed, 85 insertions(+), 13 deletions(-)
> 
> diff --git a/xen/arch/arm/platforms/Makefile b/xen/arch/arm/platforms/Makefile
> index 49fa683780..53a47e48d2 100644
> --- a/xen/arch/arm/platforms/Makefile
> +++ b/xen/arch/arm/platforms/Makefile
> @@ -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
> diff --git a/xen/arch/arm/platforms/sunxi.c b/xen/arch/arm/platforms/sunxi.c
> index 0ba7b3d9b4..c8a3e8eec8 100644
> --- a/xen/arch/arm/platforms/sunxi.c
> +++ b/xen/arch/arm/platforms/sunxi.c
> @@ -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 
>  
>  /* Watchdog constants: */
> -#define SUNXI_WDT_BASE0x01c20c90
> -#define SUNXI_WDT_MODE0x04
> -#define SUNXI_WDT_MODEADDR(SUNXI_WDT_BASE + SUNXI_WDT_MODE)
> +#define SUNXI_WDT_MODE_REG0x04
>  #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_REG0x18
>  
> -static void sunxi_reset(void)
> +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;
> +}
>  
> -wdt = ioremap_nocache(SUNXI_WDT_MODEADDR & PAGE_MASK, PAGE_SIZE);
> +ret = dt_device_get_address(node, 0, _start, _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;
> +return NULL;
>  }
>  
> -/* Enable watchdog to trigger a reset after 500 ms: */
> +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_MODEADDR & ~PAGE_MASK));
> +   wdt + SUNXI_WDT_MODE_REG);
> +}
> +
> +static void sunxi_new_wdt_reset(void __iomem *wdt)
> +{
> +

[Xen-devel] [PATCH] ARM: sunxi: support more Allwinner SoCs

2017-10-06 Thread Andre Przywara
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 
---
Hi,

this is based on staging, which has the required UART fix.
Tested on:
- BananaPi M1 (A20)
- OrangePi Zero (H2+, which is almost the same as H3)
- OrangePi PC 2 (H5, arm64)
- Pine64+ (A64, arm64)

On the 64-bit boards I could boot into Dom0 prompt.
I had issues with U-Boot's fdt command on the two 32-bit boards, so couldn't
inject the Dom0 magic into the DT. But at least Xen booted and reset
worked with both the "old" and "new" watchdog.
The newer boards require "clk_ignore_unused" on the Linux command line at
the moment, I will try to find a more sustainable solution next week.
Will try to update the Wiki later on.

Please let me know if this is worth splitting up into multiple patches
(watchdog address from DT, new watchdog support, arm64 support).

Many thanks to Awais for the idea and his original patch, and for testing
this one!

Cheers,
Andre.

 xen/arch/arm/platforms/Makefile |  2 +-
 xen/arch/arm/platforms/sunxi.c  | 96 +++--
 2 files changed, 85 insertions(+), 13 deletions(-)

diff --git a/xen/arch/arm/platforms/Makefile b/xen/arch/arm/platforms/Makefile
index 49fa683780..53a47e48d2 100644
--- a/xen/arch/arm/platforms/Makefile
+++ b/xen/arch/arm/platforms/Makefile
@@ -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
diff --git a/xen/arch/arm/platforms/sunxi.c b/xen/arch/arm/platforms/sunxi.c
index 0ba7b3d9b4..c8a3e8eec8 100644
--- a/xen/arch/arm/platforms/sunxi.c
+++ b/xen/arch/arm/platforms/sunxi.c
@@ -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 
 
 /* Watchdog constants: */
-#define SUNXI_WDT_BASE0x01c20c90
-#define SUNXI_WDT_MODE0x04
-#define SUNXI_WDT_MODEADDR(SUNXI_WDT_BASE + SUNXI_WDT_MODE)
+#define SUNXI_WDT_MODE_REG0x04
 #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_REG0x18
 
-static void sunxi_reset(void)
+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;
+}
 
-wdt = ioremap_nocache(SUNXI_WDT_MODEADDR & PAGE_MASK, PAGE_SIZE);
+ret = dt_device_get_address(node, 0, _start, _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;
+return NULL;
 }
 
-/* Enable watchdog to trigger a reset after 500 ms: */
+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_MODEADDR & ~PAGE_MASK));
+   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 = sunxi_map_watchdog(_new_wdt);
+if ( !wdt )
+return;
+
+if ( is_new_wdt )
+sunxi_new_wdt_reset(wdt);
+else
+sunxi_old_wdt_reset(wdt);
+
 iounmap(wdt);
 
 for (;;)
 wfi();
 }