summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig7
-rw-r--r--arch/arm/Makefile1
-rw-r--r--arch/arm/include/asm/arch-aspeed/timer.h54
-rw-r--r--arch/arm/include/asm/arch-aspeed/wdt.h99
-rw-r--r--arch/arm/mach-aspeed/Kconfig27
-rw-r--r--arch/arm/mach-aspeed/Makefile7
-rw-r--r--arch/arm/mach-aspeed/ast_wdt.c59
7 files changed, 254 insertions, 0 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index c04adfb..b0b6f78 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1007,8 +1007,15 @@ config TARGET_THUNDERX_88XX
select OF_CONTROL
select SYS_CACHE_SHIFT_7
+config ARCH_ASPEED
+ bool "Support Aspeed SoCs"
+ select OF_CONTROL
+ select DM
+
endchoice
+source "arch/arm/mach-aspeed/Kconfig"
+
source "arch/arm/mach-at91/Kconfig"
source "arch/arm/mach-bcm283x/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 4b8bf80..6fa9506 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -50,6 +50,7 @@ PLATFORM_CPPFLAGS += $(arch-y) $(tune-y)
# Machine directory name. This list is sorted alphanumerically
# by CONFIG_* macro name.
+machine-$(CONFIG_ARCH_ASPEED) += aspeed
machine-$(CONFIG_ARCH_AT91) += at91
machine-$(CONFIG_ARCH_BCM283X) += bcm283x
machine-$(CONFIG_ARCH_DAVINCI) += davinci
diff --git a/arch/arm/include/asm/arch-aspeed/timer.h b/arch/arm/include/asm/arch-aspeed/timer.h
new file mode 100644
index 0000000..87c5b35
--- /dev/null
+++ b/arch/arm/include/asm/arch-aspeed/timer.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#ifndef _ASM_ARCH_TIMER_H
+#define _ASM_ARCH_TIMER_H
+
+/* Each timer has 4 control bits in ctrl1 register.
+ * Timer1 uses bits 0:3, Timer2 uses bits 4:7 and so on,
+ * such that timer X uses bits (4 * X - 4):(4 * X - 1)
+ * If the timer does not support PWM, bit 4 is reserved.
+ */
+#define AST_TMC_EN (1 << 0)
+#define AST_TMC_1MHZ (1 << 1)
+#define AST_TMC_OVFINTR (1 << 2)
+#define AST_TMC_PWM (1 << 3)
+
+/* Timers are counted from 1 in the datasheet. */
+#define AST_TMC_CTRL1_SHIFT(n) (4 * ((n) - 1))
+
+#define AST_TMC_RATE (1000*1000)
+
+#ifndef __ASSEMBLY__
+
+/*
+ * All timers share control registers, which makes it harder to make them
+ * separate devices. Since only one timer is needed at the moment, making
+ * it this just one device.
+ */
+
+struct ast_timer_counter {
+ u32 status;
+ u32 reload_val;
+ u32 match1;
+ u32 match2;
+};
+
+struct ast_timer {
+ struct ast_timer_counter timers1[3];
+ u32 ctrl1;
+ u32 ctrl2;
+#ifdef CONFIG_ASPEED_AST2500
+ u32 ctrl3;
+ u32 ctrl1_clr;
+#else
+ u32 reserved[2];
+#endif
+ struct ast_timer_counter timers2[5];
+};
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_ARCH_TIMER_H */
diff --git a/arch/arm/include/asm/arch-aspeed/wdt.h b/arch/arm/include/asm/arch-aspeed/wdt.h
new file mode 100644
index 0000000..b292a0e
--- /dev/null
+++ b/arch/arm/include/asm/arch-aspeed/wdt.h
@@ -0,0 +1,99 @@
+/*
+ * (C) Copyright 2016 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_WDT_H
+#define _ASM_ARCH_WDT_H
+
+#define WDT_BASE 0x1e785000
+
+/*
+ * Special value that needs to be written to counter_restart register to
+ * (re)start the timer
+ */
+#define WDT_COUNTER_RESTART_VAL 0x4755
+
+/* Control register */
+#define WDT_CTRL_RESET_MODE_SHIFT 5
+#define WDT_CTRL_RESET_MODE_MASK 3
+
+#define WDT_CTRL_EN (1 << 0)
+#define WDT_CTRL_RESET (1 << 1)
+#define WDT_CTRL_CLK1MHZ (1 << 4)
+#define WDT_CTRL_2ND_BOOT (1 << 7)
+
+/* Values for Reset Mode */
+#define WDT_CTRL_RESET_SOC 0
+#define WDT_CTRL_RESET_CHIP 1
+#define WDT_CTRL_RESET_CPU 2
+#define WDT_CTRL_RESET_MASK 3
+
+/* Reset Mask register */
+#define WDT_RESET_ARM (1 << 0)
+#define WDT_RESET_COPROC (1 << 1)
+#define WDT_RESET_SDRAM (1 << 2)
+#define WDT_RESET_AHB (1 << 3)
+#define WDT_RESET_I2C (1 << 4)
+#define WDT_RESET_MAC1 (1 << 5)
+#define WDT_RESET_MAC2 (1 << 6)
+#define WDT_RESET_GCRT (1 << 7)
+#define WDT_RESET_USB20 (1 << 8)
+#define WDT_RESET_USB11_HOST (1 << 9)
+#define WDT_RESET_USB11_EHCI2 (1 << 10)
+#define WDT_RESET_VIDEO (1 << 11)
+#define WDT_RESET_HAC (1 << 12)
+#define WDT_RESET_LPC (1 << 13)
+#define WDT_RESET_SDSDIO (1 << 14)
+#define WDT_RESET_MIC (1 << 15)
+#define WDT_RESET_CRT2C (1 << 16)
+#define WDT_RESET_PWM (1 << 17)
+#define WDT_RESET_PECI (1 << 18)
+#define WDT_RESET_JTAG (1 << 19)
+#define WDT_RESET_ADC (1 << 20)
+#define WDT_RESET_GPIO (1 << 21)
+#define WDT_RESET_MCTP (1 << 22)
+#define WDT_RESET_XDMA (1 << 23)
+#define WDT_RESET_SPI (1 << 24)
+#define WDT_RESET_MISC (1 << 25)
+
+#ifndef __ASSEMBLY__
+struct ast_wdt {
+ u32 counter_status;
+ u32 counter_reload_val;
+ u32 counter_restart;
+ u32 ctrl;
+ u32 timeout_status;
+ u32 clr_timeout_status;
+ u32 reset_width;
+#ifdef CONFIG_ASPEED_AST2500
+ u32 reset_mask;
+#else
+ u32 reserved0;
+#endif
+};
+
+void wdt_stop(struct ast_wdt *wdt);
+void wdt_start(struct ast_wdt *wdt, u32 timeout);
+
+/**
+ * Reset peripherals specified by mask
+ *
+ * Note, that this is only supported by ast2500 SoC
+ *
+ * @wdt: watchdog to use for this reset
+ * @mask: reset mask.
+ */
+int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask);
+
+/**
+ * ast_get_wdt() - get a pointer to watchdog registers
+ *
+ * @wdt_number: 0-based WDT peripheral number
+ * @return pointer to registers or -ve error on error
+ */
+struct ast_wdt *ast_get_wdt(u8 wdt_number);
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_ARCH_WDT_H */
diff --git a/arch/arm/mach-aspeed/Kconfig b/arch/arm/mach-aspeed/Kconfig
new file mode 100644
index 0000000..b72ed89
--- /dev/null
+++ b/arch/arm/mach-aspeed/Kconfig
@@ -0,0 +1,27 @@
+if ARCH_ASPEED
+
+config SYS_ARCH
+ default "arm"
+
+config SYS_SOC
+ default "aspeed"
+
+config SYS_TEXT_BASE
+ default 0x00000000
+
+config ASPEED_AST2500
+ bool "Support Aspeed AST2500 SoC"
+ select CPU_ARM1176
+ help
+ The Aspeed AST2500 is a ARM-based SoC with arm1176 CPU.
+ It is used as Board Management Controller on many server boards,
+ which is enabled by support of LPC and eSPI peripherals.
+
+config WDT_NUM
+ int "Number of Watchdog Timers"
+ default 3 if ASPEED_AST2500
+ help
+ The number of Watchdot Timers on a SoC.
+ AST2500 has three WDTsk earlier versions have two or fewer.
+
+endif
diff --git a/arch/arm/mach-aspeed/Makefile b/arch/arm/mach-aspeed/Makefile
new file mode 100644
index 0000000..a14b8f7
--- /dev/null
+++ b/arch/arm/mach-aspeed/Makefile
@@ -0,0 +1,7 @@
+#
+# Copyright (c) 2016 Google, Inc
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+obj-$(CONFIG_ARCH_ASPEED) += ast_wdt.o
diff --git a/arch/arm/mach-aspeed/ast_wdt.c b/arch/arm/mach-aspeed/ast_wdt.c
new file mode 100644
index 0000000..22481ab
--- /dev/null
+++ b/arch/arm/mach-aspeed/ast_wdt.c
@@ -0,0 +1,59 @@
+/*
+ * (C) Copyright 2016 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/wdt.h>
+#include <linux/err.h>
+
+void wdt_stop(struct ast_wdt *wdt)
+{
+ clrbits_le32(&wdt->ctrl, WDT_CTRL_EN);
+}
+
+void wdt_start(struct ast_wdt *wdt, u32 timeout)
+{
+ writel(timeout, &wdt->counter_reload_val);
+ writel(WDT_COUNTER_RESTART_VAL, &wdt->counter_restart);
+ /*
+ * Setting CLK1MHZ bit is just for compatibility with ast2400 part.
+ * On ast2500 watchdog timer clock is fixed at 1MHz and the bit is
+ * read-only
+ */
+ setbits_le32(&wdt->ctrl,
+ WDT_CTRL_EN | WDT_CTRL_RESET | WDT_CTRL_CLK1MHZ);
+}
+
+struct ast_wdt *ast_get_wdt(u8 wdt_number)
+{
+ if (wdt_number > CONFIG_WDT_NUM - 1)
+ return ERR_PTR(-EINVAL);
+
+ return (struct ast_wdt *)(WDT_BASE +
+ sizeof(struct ast_wdt) * wdt_number);
+}
+
+int ast_wdt_reset_masked(struct ast_wdt *wdt, u32 mask)
+{
+#ifdef CONFIG_ASPEED_AST2500
+ if (!mask)
+ return -EINVAL;
+
+ writel(mask, &wdt->reset_mask);
+ clrbits_le32(&wdt->ctrl,
+ WDT_CTRL_RESET_MASK << WDT_CTRL_RESET_MODE_SHIFT);
+ wdt_start(wdt, 1);
+
+ /* Wait for WDT to reset */
+ while (readl(&wdt->ctrl) & WDT_CTRL_EN)
+ ;
+ wdt_stop(wdt);
+
+ return 0;
+#else
+ return -EINVAL;
+#endif
+}