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

Signed-off-by: Rafaël Carré <fun...@videolan.org>
---
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 <juh...@openwrt.org>
+ * Copyright (C) 2013 John Crispin <j...@phrozen.org>
+ */
+
+#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.bur...@mips.com>
+ */
+
+#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

Reply via email to