[RFC/PATCH] MIPS: ralink: adds support for RT6855 SoC family

From: Rafaël Carré
Date: Tue Oct 13 2020 - 10:10:53 EST


Add support code for rt6855 SOC.
The new irq-rt6855.c is based on irq.c

Signed-off-by: Rafaël Carré <funman@xxxxxxxxxxxx>
---
Hello,

I decided I wanted to make OpenWRT run on this Linksys WAP300N router.

With the help of a serial console and the vendor GPL sources dump the
router can now boot 5.9 and give me a console prompt.

As a MIPS and kernel newbie I am pretty stoked ;)

It is still missing quite a few devices: net (ethernet/wlan), watchdog,
button, leds, maybe something else.

The timer (used to update jiffies I guess?) is most likely already
setup by U-Boot. IIUC there is room for a second timer although I am
not sure if it's required.

The simple IRQ controller is based on the existing Ralink 'intc' one.
I even re-used the name, I guess intc stands for "INTerrupt Controller"

Please give me your comments and insights on this simple patch, and
let me know if it's worth upstreaming this or if I should just leave
this patch and the next ones in the OpenWRT tree.

Thanks

Rafaël


arch/mips/boot/dts/ralink/Makefile | 1 +
arch/mips/boot/dts/ralink/rt6855.dtsi | 64 ++++++++++
arch/mips/boot/dts/ralink/wap300n.dts | 18 +++
arch/mips/ralink/Kconfig | 11 +-
arch/mips/ralink/Makefile | 6 +-
arch/mips/ralink/Platform | 5 +
arch/mips/ralink/early_printk.c | 5 +-
arch/mips/ralink/irq-rt6855.c | 168 ++++++++++++++++++++++++++
arch/mips/ralink/rt6855.c | 48 ++++++++
9 files changed, 323 insertions(+), 3 deletions(-)
create mode 100644 arch/mips/boot/dts/ralink/rt6855.dtsi
create mode 100644 arch/mips/boot/dts/ralink/wap300n.dts
create mode 100644 arch/mips/ralink/irq-rt6855.c
create mode 100644 arch/mips/ralink/rt6855.c

diff --git a/arch/mips/boot/dts/ralink/Makefile b/arch/mips/boot/dts/ralink/Makefile
index 6c26dfa0a903..08c612190936 100644
--- a/arch/mips/boot/dts/ralink/Makefile
+++ b/arch/mips/boot/dts/ralink/Makefile
@@ -3,6 +3,7 @@ dtb-$(CONFIG_DTB_RT2880_EVAL) += rt2880_eval.dtb
dtb-$(CONFIG_DTB_RT305X_EVAL) += rt3052_eval.dtb
dtb-$(CONFIG_DTB_RT3883_EVAL) += rt3883_eval.dtb
dtb-$(CONFIG_DTB_MT7620A_EVAL) += mt7620a_eval.dtb
+dtb-$(CONFIG_DTB_WAP300N) += wap300n.dtb
dtb-$(CONFIG_DTB_OMEGA2P) += omega2p.dtb
dtb-$(CONFIG_DTB_VOCORE2) += vocore2.dtb
diff --git a/arch/mips/boot/dts/ralink/rt6855.dtsi b/arch/mips/boot/dts/ralink/rt6855.dtsi
new file mode 100644
index 000000000000..745808ee1e37
--- /dev/null
+++ b/arch/mips/boot/dts/ralink/rt6855.dtsi
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "ralink,rt6855-soc";
+
+ cpus {
+ cpu@0 {
+ compatible = "mips,mips4KEc";
+ };
+ };
+
+ cpuintc: cpuintc {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ palmbus@1fb20000 {
+ compatible = "palmbus";
+ reg = <0x1fb20000 0xe0000>;
+ ranges = <0x0 0x1fb20000 0xDFFFF>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ sysc@0 {
+ compatible = "ralink,rt6855-sysc", "ralink,rt3050-sysc";
+ reg = <0x0 0x100>;
+ };
+
+ intc: intc@20000 {
+ compatible = "ralink,rt6855-intc", "ralink,rt2880-intc";
+ reg = <0x20000 0x100>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&cpuintc>;
+ };
+
+ memc@300 {
+ compatible = "ralink,rt6855-memc", "ralink,rt3050-memc";
+ reg = <0x300 0x100>;
+ };
+
+ uart: uart@d0000 {
+ compatible = "ns8250";
+ reg = <0xd0000 0x30>;
+ interrupts = <0>;
+
+ clock-frequency = <921600>;
+
+ reg-io-width = <4>;
+ reg-shift = <2>;
+ no-loopback-test;
+
+ status = "okay";
+
+ interrupt-parent = <&intc>;
+ };
+ };
+};
diff --git a/arch/mips/boot/dts/ralink/wap300n.dts b/arch/mips/boot/dts/ralink/wap300n.dts
new file mode 100644
index 000000000000..d923946c4abe
--- /dev/null
+++ b/arch/mips/boot/dts/ralink/wap300n.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+
+/include/ "rt6855.dtsi"
+
+/ {
+ compatible = "ralink,rt6855-soc";
+ model = "Linksys WAP300n";
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x20000 0x3fe0000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,57600";
+ };
+};
diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
index c10d8b233ab1..3d40d9432e8e 100644
--- a/arch/mips/ralink/Kconfig
+++ b/arch/mips/ralink/Kconfig
@@ -16,7 +16,7 @@ config RALINK_ILL_ACC
config IRQ_INTC
bool
default y
- depends on !SOC_MT7621
+ depends on !SOC_MT7621 && !SOC_RT6855
choice
prompt "Ralink SoC selection"
@@ -39,6 +39,10 @@ choice
select HAVE_LEGACY_CLK
select HAVE_PCI
+ config SOC_RT6855
+ bool "RT6855"
+ select HAVE_LEGACY_CLK
+
config SOC_MT7620
bool "MT7620/8"
select CPU_MIPSR2_IRQ_VI
@@ -98,6 +102,11 @@ choice
depends on SOC_MT7620
select BUILTIN_DTB
+ config DTB_WAP300N
+ bool "WAP300N"
+ depends on SOC_RT6855
+ select BUILTIN_DTB
+
endchoice
endif
diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile
index 26fabbdea1f1..2d5a17a87d3e 100644
--- a/arch/mips/ralink/Makefile
+++ b/arch/mips/ralink/Makefile
@@ -7,7 +7,10 @@
obj-y := prom.o of.o reset.o
ifndef CONFIG_MIPS_GIC
- obj-y += clk.o timer.o
+obj-y += clk.o
+ifndef CONFIG_SOC_RT6855
+ obj-y += timer.o
+endif
endif
obj-$(CONFIG_CLKEVT_RT3352) += cevt-rt3352.o
@@ -22,6 +25,7 @@ obj-$(CONFIG_SOC_RT305X) += rt305x.o
obj-$(CONFIG_SOC_RT3883) += rt3883.o
obj-$(CONFIG_SOC_MT7620) += mt7620.o
obj-$(CONFIG_SOC_MT7621) += mt7621.o
+obj-$(CONFIG_SOC_RT6855) += rt6855.o irq-rt6855.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform
index 02ee0791481d..7fa42eac44b1 100644
--- a/arch/mips/ralink/Platform
+++ b/arch/mips/ralink/Platform
@@ -21,6 +21,11 @@ cflags-$(CONFIG_SOC_RT305X) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt
load-$(CONFIG_SOC_RT3883) += 0xffffffff80000000
cflags-$(CONFIG_SOC_RT3883) += -I$(srctree)/arch/mips/include/asm/mach-ralink/rt3883
+# Ralink RT6855
+#
+load-$(CONFIG_SOC_RT6855) += 0xffffffff80020000
+cflags-$(CONFIG_SOC_RT6855) += $(call as-option,-Wa$(comma)-mno-fix-loongson3-llsc,)
+
#
# Ralink MT7620
#
diff --git a/arch/mips/ralink/early_printk.c b/arch/mips/ralink/early_printk.c
index eb4fac25eaf6..eb5f04809e8a 100644
--- a/arch/mips/ralink/early_printk.c
+++ b/arch/mips/ralink/early_printk.c
@@ -16,6 +16,9 @@
#elif defined(CONFIG_SOC_MT7621)
#define EARLY_UART_BASE 0x1E000c00
#define CHIPID_BASE 0x1E000004
+#elif defined(CONFIG_SOC_RT6855)
+#define EARLY_UART_BASE 0x1FBF0000
+#define CHIPID_BASE 0x1E000004
#else
#define EARLY_UART_BASE 0x10000c00
#define CHIPID_BASE 0x10000004
@@ -74,7 +77,7 @@ void prom_putchar(char ch)
init_complete = 1;
}
- if (IS_ENABLED(CONFIG_SOC_MT7621) || soc_is_mt7628()) {
+ if (IS_ENABLED(CONFIG_SOC_MT7621) || soc_is_mt7628() || IS_ENABLED(CONFIG_SOC_RT6855)) {
uart_w32((unsigned char)ch, UART_TX);
while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0)
;
diff --git a/arch/mips/ralink/irq-rt6855.c b/arch/mips/ralink/irq-rt6855.c
new file mode 100644
index 000000000000..7e5bb330d837
--- /dev/null
+++ b/arch/mips/ralink/irq-rt6855.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *
+ * Copyright (C) 2009 Gabor Juhos <juhosg@xxxxxxxxxxx>
+ * Copyright (C) 2013 John Crispin <john@xxxxxxxxxxx>
+ */
+
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq_cpu.h>
+#include <ioremap.h>
+#include <asm/mipsregs.h>
+
+#include "common.h"
+
+/* we have a cascade of 8 irqs */
+#define RALINK_INTC_IRQ_BASE 8
+
+/* we have 32 SoC irqs */
+#define RALINK_INTC_IRQ_COUNT 32
+
+#define RALINK_SOC_IRQ_TIMER 30
+
+enum rt_intc_regs_enum {
+ INTC_REG_MASK = 0,
+ INTC_REG_PRIO,
+};
+
+static u32 rt_intc_regs[] = {
+ [INTC_REG_MASK] = 0x04,
+ [INTC_REG_PRIO] = 0x10,
+};
+
+static DEFINE_SPINLOCK(rt6855_irq_lock);
+
+static void __iomem *rt_intc_membase;
+
+static inline void rt_intc_w32(u32 val, unsigned reg)
+{
+ __raw_writel(val, rt_intc_membase + rt_intc_regs[reg]);
+}
+
+static inline void rt_intc_prio_w8(u32 val, unsigned prio)
+{
+ __raw_writeb(val, rt_intc_membase + rt_intc_regs[INTC_REG_PRIO] + prio);
+}
+
+static inline u32 rt_intc_r32(unsigned reg)
+{
+ return __raw_readl(rt_intc_membase + rt_intc_regs[reg]);
+}
+
+static void ralink_intc_irq_unmask(struct irq_data *d)
+{
+ unsigned long flags;
+ u32 mask;
+
+ spin_lock_irqsave(&rt6855_irq_lock, flags);
+
+ mask = rt_intc_r32(INTC_REG_MASK);
+ mask |= BIT(d->hwirq);
+ rt_intc_w32(mask, INTC_REG_MASK);
+
+ spin_unlock_irqrestore(&rt6855_irq_lock, flags);
+}
+
+static void ralink_intc_irq_mask(struct irq_data *d)
+{
+ unsigned long flags;
+ u32 mask;
+
+ spin_lock_irqsave(&rt6855_irq_lock, flags);
+
+ mask = rt_intc_r32(INTC_REG_MASK);
+ mask &= ~BIT(d->hwirq);
+ rt_intc_w32(mask, INTC_REG_MASK);
+
+ spin_unlock_irqrestore(&rt6855_irq_lock, flags);
+}
+
+static struct irq_chip ralink_intc_irq_chip = {
+ .name = "INTC",
+ .irq_ack = ralink_intc_irq_mask,
+ .irq_mask = ralink_intc_irq_mask,
+ .irq_mask_ack = ralink_intc_irq_mask,
+ .irq_unmask = ralink_intc_irq_unmask,
+ .irq_eoi = ralink_intc_irq_unmask,
+};
+
+unsigned int get_c0_compare_int(void)
+{
+ return RALINK_INTC_IRQ_BASE + RALINK_SOC_IRQ_TIMER;
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned long pending;
+
+ pending = (read_c0_status() & read_c0_cause() & ST0_IM) >> 10;
+
+ do_IRQ(pending + RALINK_INTC_IRQ_BASE - 1);
+}
+
+static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
+{
+ irq_set_chip_and_handler(irq, &ralink_intc_irq_chip, handle_level_irq);
+
+ return 0;
+}
+
+static const struct irq_domain_ops irq_domain_ops = {
+ .xlate = irq_domain_xlate_onecell,
+ .map = intc_map,
+};
+
+static int __init intc_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct resource res;
+ struct irq_domain *domain;
+
+ if (!of_property_read_u32_array(node, "ralink,intc-registers",
+ rt_intc_regs, 2))
+ pr_info("intc: using register map from devicetree\n");
+
+ if (of_address_to_resource(node, 0, &res))
+ panic("Failed to get intc memory range");
+
+ if (!request_mem_region(res.start, resource_size(&res),
+ res.name))
+ pr_err("Failed to request intc memory");
+
+ rt_intc_membase = ioremap(res.start,
+ resource_size(&res));
+ if (!rt_intc_membase)
+ panic("Failed to remap intc memory");
+
+ rt_intc_prio_w8(RALINK_SOC_IRQ_TIMER, 1);
+
+ clear_c0_status(ST0_IM);
+ clear_c0_cause(CAUSEF_IP);
+
+ domain = irq_domain_add_legacy(node, RALINK_INTC_IRQ_COUNT,
+ RALINK_INTC_IRQ_BASE, 0, &irq_domain_ops, NULL);
+ if (!domain)
+ panic("Failed to add irqdomain");
+
+ set_c0_status(ST0_IM);
+
+ return 0;
+}
+
+static struct of_device_id __initdata of_irq_ids[] = {
+ { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_irq_of_init },
+ { .compatible = "ralink,rt6855-intc", .data = intc_of_init },
+ {},
+};
+
+void __init arch_init_irq(void)
+{
+ of_irq_init(of_irq_ids);
+}
diff --git a/arch/mips/ralink/rt6855.c b/arch/mips/ralink/rt6855.c
new file mode 100644
index 000000000000..46cc496aa8e9
--- /dev/null
+++ b/arch/mips/ralink/rt6855.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2016 Imagination Technologies
+ * Author: Paul Burton <paul.burton@xxxxxxxx>
+ */
+
+#include <linux/clk.h>
+#include <linux/clocksource.h>
+#include <linux/init.h>
+#include <linux/irqchip.h>
+#include <linux/of_clk.h>
+#include <linux/of_fdt.h>
+#include <linux/serial_reg.h>
+
+#include <asm/bootinfo.h>
+#include <asm/fw/fw.h>
+#include <asm/irq_cpu.h>
+#include <asm/machine.h>
+#include <asm/mips-cps.h>
+#include <asm/prom.h>
+#include <asm/smp-ops.h>
+#include <asm/time.h>
+
+#include <asm/mach-ralink/ralink_regs.h>
+
+#include "common.h"
+
+void prom_soc_init(struct ralink_soc_info *soc_info)
+{
+ soc_info->mem_size_min = 64;
+ soc_info->mem_size_max = 64;
+ soc_info->compatible = "ralink,rt6855-soc";
+ soc_info->mem_base = 0x20000;
+}
+
+void __init ralink_of_remap(void)
+{
+ rt_sysc_membase = plat_of_remap_node("ralink,rt6855-sysc");
+ rt_memc_membase = plat_of_remap_node("ralink,rt6855-memc");
+
+ if (!rt_sysc_membase || !rt_memc_membase)
+ panic("Failed to remap core resources");
+}
+
+void __init ralink_clk_init(void)
+{
+ ralink_clk_add("cpu", 700000000);
+}
--
2.27.0