summaryrefslogtreecommitdiffstats
path: root/arch/mips/ralink
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/ralink')
-rw-r--r--arch/mips/ralink/Kconfig32
-rw-r--r--arch/mips/ralink/Makefile15
-rw-r--r--arch/mips/ralink/Platform10
-rw-r--r--arch/mips/ralink/clk.c72
-rw-r--r--arch/mips/ralink/common.h44
-rw-r--r--arch/mips/ralink/dts/Makefile1
-rw-r--r--arch/mips/ralink/dts/rt3050.dtsi106
-rw-r--r--arch/mips/ralink/dts/rt3052_eval.dts52
-rw-r--r--arch/mips/ralink/early_printk.c44
-rw-r--r--arch/mips/ralink/irq.c180
-rw-r--r--arch/mips/ralink/of.c107
-rw-r--r--arch/mips/ralink/prom.c69
-rw-r--r--arch/mips/ralink/reset.c44
-rw-r--r--arch/mips/ralink/rt305x.c242
14 files changed, 1018 insertions, 0 deletions
diff --git a/arch/mips/ralink/Kconfig b/arch/mips/ralink/Kconfig
new file mode 100644
index 000000000000..a0b0197cab0a
--- /dev/null
+++ b/arch/mips/ralink/Kconfig
@@ -0,0 +1,32 @@
+if RALINK
+
+choice
+ prompt "Ralink SoC selection"
+ default SOC_RT305X
+ help
+ Select Ralink MIPS SoC type.
+
+ config SOC_RT305X
+ bool "RT305x"
+ select USB_ARCH_HAS_HCD
+ select USB_ARCH_HAS_OHCI
+ select USB_ARCH_HAS_EHCI
+
+endchoice
+
+choice
+ prompt "Devicetree selection"
+ default DTB_RT_NONE
+ help
+ Select the devicetree.
+
+ config DTB_RT_NONE
+ bool "None"
+
+ config DTB_RT305X_EVAL
+ bool "RT305x eval kit"
+ depends on SOC_RT305X
+
+endchoice
+
+endif
diff --git a/arch/mips/ralink/Makefile b/arch/mips/ralink/Makefile
new file mode 100644
index 000000000000..939757f0e71f
--- /dev/null
+++ b/arch/mips/ralink/Makefile
@@ -0,0 +1,15 @@
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 as published
+# by the Free Software Foundation.#
+# Makefile for the Ralink common stuff
+#
+# Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
+# Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+
+obj-y := prom.o of.o reset.o clk.o irq.o
+
+obj-$(CONFIG_SOC_RT305X) += rt305x.o
+
+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+
+obj-y += dts/
diff --git a/arch/mips/ralink/Platform b/arch/mips/ralink/Platform
new file mode 100644
index 000000000000..6babd65765e6
--- /dev/null
+++ b/arch/mips/ralink/Platform
@@ -0,0 +1,10 @@
+#
+# Ralink SoC common stuff
+#
+core-$(CONFIG_RALINK) += arch/mips/ralink/
+cflags-$(CONFIG_RALINK) += -I$(srctree)/arch/mips/include/asm/mach-ralink
+
+#
+# Ralink RT305x
+#
+load-$(CONFIG_SOC_RT305X) += 0xffffffff80000000
diff --git a/arch/mips/ralink/clk.c b/arch/mips/ralink/clk.c
new file mode 100644
index 000000000000..8dfa22ff300b
--- /dev/null
+++ b/arch/mips/ralink/clk.c
@@ -0,0 +1,72 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clkdev.h>
+#include <linux/clk.h>
+
+#include <asm/time.h>
+
+#include "common.h"
+
+struct clk {
+ struct clk_lookup cl;
+ unsigned long rate;
+};
+
+void ralink_clk_add(const char *dev, unsigned long rate)
+{
+ struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
+
+ if (!clk)
+ panic("failed to add clock\n");
+
+ clk->cl.dev_id = dev;
+ clk->cl.clk = clk;
+
+ clk->rate = rate;
+
+ clkdev_add(&clk->cl);
+}
+
+/*
+ * Linux clock API
+ */
+int clk_enable(struct clk *clk)
+{
+ return 0;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ return clk->rate;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+void __init plat_time_init(void)
+{
+ struct clk *clk;
+
+ ralink_of_remap();
+
+ ralink_clk_init();
+ clk = clk_get_sys("cpu", NULL);
+ if (IS_ERR(clk))
+ panic("unable to get CPU clock, err=%ld", PTR_ERR(clk));
+ pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
+ mips_hpt_frequency = clk_get_rate(clk) / 2;
+ clk_put(clk);
+}
diff --git a/arch/mips/ralink/common.h b/arch/mips/ralink/common.h
new file mode 100644
index 000000000000..300990313e1b
--- /dev/null
+++ b/arch/mips/ralink/common.h
@@ -0,0 +1,44 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _RALINK_COMMON_H__
+#define _RALINK_COMMON_H__
+
+#define RAMIPS_SYS_TYPE_LEN 32
+
+struct ralink_pinmux_grp {
+ const char *name;
+ u32 mask;
+ int gpio_first;
+ int gpio_last;
+};
+
+struct ralink_pinmux {
+ struct ralink_pinmux_grp *mode;
+ struct ralink_pinmux_grp *uart;
+ int uart_shift;
+ void (*wdt_reset)(void);
+};
+extern struct ralink_pinmux gpio_pinmux;
+
+struct ralink_soc_info {
+ unsigned char sys_type[RAMIPS_SYS_TYPE_LEN];
+ unsigned char *compatible;
+};
+extern struct ralink_soc_info soc_info;
+
+extern void ralink_of_remap(void);
+
+extern void ralink_clk_init(void);
+extern void ralink_clk_add(const char *dev, unsigned long rate);
+
+extern void prom_soc_init(struct ralink_soc_info *soc_info);
+
+__iomem void *plat_of_remap_node(const char *node);
+
+#endif /* _RALINK_COMMON_H__ */
diff --git a/arch/mips/ralink/dts/Makefile b/arch/mips/ralink/dts/Makefile
new file mode 100644
index 000000000000..1a69fb300955
--- /dev/null
+++ b/arch/mips/ralink/dts/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_DTB_RT305X_EVAL) := rt3052_eval.dtb.o
diff --git a/arch/mips/ralink/dts/rt3050.dtsi b/arch/mips/ralink/dts/rt3050.dtsi
new file mode 100644
index 000000000000..069d0660e1dd
--- /dev/null
+++ b/arch/mips/ralink/dts/rt3050.dtsi
@@ -0,0 +1,106 @@
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "ralink,rt3050-soc", "ralink,rt3052-soc";
+
+ cpus {
+ cpu@0 {
+ compatible = "mips,mips24KEc";
+ };
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,57600 init=/init";
+ };
+
+ cpuintc: cpuintc@0 {
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ compatible = "mti,cpu-interrupt-controller";
+ };
+
+ palmbus@10000000 {
+ compatible = "palmbus";
+ reg = <0x10000000 0x200000>;
+ ranges = <0x0 0x10000000 0x1FFFFF>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ sysc@0 {
+ compatible = "ralink,rt3052-sysc", "ralink,rt3050-sysc";
+ reg = <0x0 0x100>;
+ };
+
+ timer@100 {
+ compatible = "ralink,rt3052-wdt", "ralink,rt2880-wdt";
+ reg = <0x100 0x100>;
+ };
+
+ intc: intc@200 {
+ compatible = "ralink,rt3052-intc", "ralink,rt2880-intc";
+ reg = <0x200 0x100>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-parent = <&cpuintc>;
+ interrupts = <2>;
+ };
+
+ memc@300 {
+ compatible = "ralink,rt3052-memc", "ralink,rt3050-memc";
+ reg = <0x300 0x100>;
+ };
+
+ gpio0: gpio@600 {
+ compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio";
+ reg = <0x600 0x34>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ ralink,ngpio = <24>;
+ ralink,regs = [ 00 04 08 0c
+ 20 24 28 2c
+ 30 34 ];
+ };
+
+ gpio1: gpio@638 {
+ compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio";
+ reg = <0x638 0x24>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ ralink,ngpio = <16>;
+ ralink,regs = [ 00 04 08 0c
+ 10 14 18 1c
+ 20 24 ];
+ };
+
+ gpio2: gpio@660 {
+ compatible = "ralink,rt3052-gpio", "ralink,rt2880-gpio";
+ reg = <0x660 0x24>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ ralink,ngpio = <12>;
+ ralink,regs = [ 00 04 08 0c
+ 10 14 18 1c
+ 20 24 ];
+ };
+
+ uartlite@c00 {
+ compatible = "ralink,rt3052-uart", "ralink,rt2880-uart", "ns16550a";
+ reg = <0xc00 0x100>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <12>;
+
+ reg-shift = <2>;
+ };
+ };
+};
diff --git a/arch/mips/ralink/dts/rt3052_eval.dts b/arch/mips/ralink/dts/rt3052_eval.dts
new file mode 100644
index 000000000000..148a590bc419
--- /dev/null
+++ b/arch/mips/ralink/dts/rt3052_eval.dts
@@ -0,0 +1,52 @@
+/dts-v1/;
+
+/include/ "rt3050.dtsi"
+
+/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "ralink,rt3052-eval-board", "ralink,rt3052-soc";
+ model = "Ralink RT3052 evaluation board";
+
+ memory@0 {
+ reg = <0x0 0x2000000>;
+ };
+
+ palmbus@10000000 {
+ sysc@0 {
+ ralink,pinmmux = "uartlite", "spi";
+ ralink,uartmux = "gpio";
+ ralink,wdtmux = <0>;
+ };
+ };
+
+ cfi@1f000000 {
+ compatible = "cfi-flash";
+ reg = <0x1f000000 0x800000>;
+
+ bank-width = <2>;
+ device-width = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "uboot";
+ reg = <0x0 0x30000>;
+ read-only;
+ };
+ partition@30000 {
+ label = "uboot-env";
+ reg = <0x30000 0x10000>;
+ read-only;
+ };
+ partition@40000 {
+ label = "calibration";
+ reg = <0x40000 0x10000>;
+ read-only;
+ };
+ partition@50000 {
+ label = "linux";
+ reg = <0x50000 0x7b0000>;
+ };
+ };
+};
diff --git a/arch/mips/ralink/early_printk.c b/arch/mips/ralink/early_printk.c
new file mode 100644
index 000000000000..c4ae47eb24ab
--- /dev/null
+++ b/arch/mips/ralink/early_printk.c
@@ -0,0 +1,44 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2011-2012 Gabor Juhos <juhosg@openwrt.org>
+ */
+
+#include <linux/io.h>
+#include <linux/serial_reg.h>
+
+#include <asm/addrspace.h>
+
+#define EARLY_UART_BASE 0x10000c00
+
+#define UART_REG_RX 0x00
+#define UART_REG_TX 0x04
+#define UART_REG_IER 0x08
+#define UART_REG_IIR 0x0c
+#define UART_REG_FCR 0x10
+#define UART_REG_LCR 0x14
+#define UART_REG_MCR 0x18
+#define UART_REG_LSR 0x1c
+
+static __iomem void *uart_membase = (__iomem void *) KSEG1ADDR(EARLY_UART_BASE);
+
+static inline void uart_w32(u32 val, unsigned reg)
+{
+ __raw_writel(val, uart_membase + reg);
+}
+
+static inline u32 uart_r32(unsigned reg)
+{
+ return __raw_readl(uart_membase + reg);
+}
+
+void prom_putchar(unsigned char ch)
+{
+ while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0)
+ ;
+ uart_w32(ch, UART_REG_TX);
+ while ((uart_r32(UART_REG_LSR) & UART_LSR_THRE) == 0)
+ ;
+}
diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c
new file mode 100644
index 000000000000..6d054c5ec9ab
--- /dev/null
+++ b/arch/mips/ralink/irq.c
@@ -0,0 +1,180 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.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 <asm/mipsregs.h>
+
+#include "common.h"
+
+/* INTC register offsets */
+#define INTC_REG_STATUS0 0x00
+#define INTC_REG_STATUS1 0x04
+#define INTC_REG_TYPE 0x20
+#define INTC_REG_RAW_STATUS 0x30
+#define INTC_REG_ENABLE 0x34
+#define INTC_REG_DISABLE 0x38
+
+#define INTC_INT_GLOBAL BIT(31)
+
+#define RALINK_CPU_IRQ_INTC (MIPS_CPU_IRQ_BASE + 2)
+#define RALINK_CPU_IRQ_FE (MIPS_CPU_IRQ_BASE + 5)
+#define RALINK_CPU_IRQ_WIFI (MIPS_CPU_IRQ_BASE + 6)
+#define RALINK_CPU_IRQ_COUNTER (MIPS_CPU_IRQ_BASE + 7)
+
+/* 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_INTC_IRQ_PERFC (RALINK_INTC_IRQ_BASE + 9)
+
+static void __iomem *rt_intc_membase;
+
+static inline void rt_intc_w32(u32 val, unsigned reg)
+{
+ __raw_writel(val, rt_intc_membase + reg);
+}
+
+static inline u32 rt_intc_r32(unsigned reg)
+{
+ return __raw_readl(rt_intc_membase + reg);
+}
+
+static void ralink_intc_irq_unmask(struct irq_data *d)
+{
+ rt_intc_w32(BIT(d->hwirq), INTC_REG_ENABLE);
+}
+
+static void ralink_intc_irq_mask(struct irq_data *d)
+{
+ rt_intc_w32(BIT(d->hwirq), INTC_REG_DISABLE);
+}
+
+static struct irq_chip ralink_intc_irq_chip = {
+ .name = "INTC",
+ .irq_unmask = ralink_intc_irq_unmask,
+ .irq_mask = ralink_intc_irq_mask,
+ .irq_mask_ack = ralink_intc_irq_mask,
+};
+
+unsigned int __cpuinit get_c0_compare_int(void)
+{
+ return CP0_LEGACY_COMPARE_IRQ;
+}
+
+static void ralink_intc_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+ u32 pending = rt_intc_r32(INTC_REG_STATUS0);
+
+ if (pending) {
+ struct irq_domain *domain = irq_get_handler_data(irq);
+ generic_handle_irq(irq_find_mapping(domain, __ffs(pending)));
+ } else {
+ spurious_interrupt();
+ }
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned long pending;
+
+ pending = read_c0_status() & read_c0_cause() & ST0_IM;
+
+ if (pending & STATUSF_IP7)
+ do_IRQ(RALINK_CPU_IRQ_COUNTER);
+
+ else if (pending & STATUSF_IP5)
+ do_IRQ(RALINK_CPU_IRQ_FE);
+
+ else if (pending & STATUSF_IP6)
+ do_IRQ(RALINK_CPU_IRQ_WIFI);
+
+ else if (pending & STATUSF_IP2)
+ do_IRQ(RALINK_CPU_IRQ_INTC);
+
+ else
+ spurious_interrupt();
+}
+
+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;
+ int irq;
+
+ irq = irq_of_parse_and_map(node, 0);
+ if (!irq)
+ panic("Failed to get INTC IRQ");
+
+ 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) < 0)
+ pr_err("Failed to request intc memory");
+
+ rt_intc_membase = ioremap_nocache(res.start,
+ resource_size(&res));
+ if (!rt_intc_membase)
+ panic("Failed to remap intc memory");
+
+ /* disable all interrupts */
+ rt_intc_w32(~0, INTC_REG_DISABLE);
+
+ /* route all INTC interrupts to MIPS HW0 interrupt */
+ rt_intc_w32(0, INTC_REG_TYPE);
+
+ 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");
+
+ rt_intc_w32(INTC_INT_GLOBAL, INTC_REG_ENABLE);
+
+ irq_set_chained_handler(irq, ralink_intc_irq_handler);
+ irq_set_handler_data(irq, domain);
+
+ cp0_perfcount_irq = irq_create_mapping(domain, 9);
+
+ return 0;
+}
+
+static struct of_device_id __initdata of_irq_ids[] = {
+ { .compatible = "mti,cpu-interrupt-controller", .data = mips_cpu_intc_init },
+ { .compatible = "ralink,rt2880-intc", .data = intc_of_init },
+ {},
+};
+
+void __init arch_init_irq(void)
+{
+ of_irq_init(of_irq_ids);
+}
+
diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c
new file mode 100644
index 000000000000..4165e70775be
--- /dev/null
+++ b/arch/mips/ralink/of.c
@@ -0,0 +1,107 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/init.h>
+#include <linux/of_fdt.h>
+#include <linux/kernel.h>
+#include <linux/bootmem.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+
+#include <asm/reboot.h>
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+
+#include "common.h"
+
+__iomem void *rt_sysc_membase;
+__iomem void *rt_memc_membase;
+
+extern struct boot_param_header __dtb_start;
+
+__iomem void *plat_of_remap_node(const char *node)
+{
+ struct resource res;
+ struct device_node *np;
+
+ np = of_find_compatible_node(NULL, NULL, node);
+ if (!np)
+ panic("Failed to find %s node", node);
+
+ if (of_address_to_resource(np, 0, &res))
+ panic("Failed to get resource for %s", node);
+
+ if ((request_mem_region(res.start,
+ resource_size(&res),
+ res.name) < 0))
+ panic("Failed to request resources for %s", node);
+
+ return ioremap_nocache(res.start, resource_size(&res));
+}
+
+void __init device_tree_init(void)
+{
+ unsigned long base, size;
+ void *fdt_copy;
+
+ if (!initial_boot_params)
+ return;
+
+ base = virt_to_phys((void *)initial_boot_params);
+ size = be32_to_cpu(initial_boot_params->totalsize);
+
+ /* Before we do anything, lets reserve the dt blob */
+ reserve_bootmem(base, size, BOOTMEM_DEFAULT);
+
+ /* The strings in the flattened tree are referenced directly by the
+ * device tree, so copy the flattened device tree from init memory
+ * to regular memory.
+ */
+ fdt_copy = alloc_bootmem(size);
+ memcpy(fdt_copy, initial_boot_params, size);
+ initial_boot_params = fdt_copy;
+
+ unflatten_device_tree();
+
+ /* free the space reserved for the dt blob */
+ free_bootmem(base, size);
+}
+
+void __init plat_mem_setup(void)
+{
+ set_io_port_base(KSEG1);
+
+ /*
+ * Load the builtin devicetree. This causes the chosen node to be
+ * parsed resulting in our memory appearing
+ */
+ __dt_setup_arch(&__dtb_start);
+}
+
+static int __init plat_of_setup(void)
+{
+ static struct of_device_id of_ids[3];
+ int len = sizeof(of_ids[0].compatible);
+
+ if (!of_have_populated_dt())
+ panic("device tree not present");
+
+ strncpy(of_ids[0].compatible, soc_info.compatible, len);
+ strncpy(of_ids[1].compatible, "palmbus", len);
+
+ if (of_platform_populate(NULL, of_ids, NULL, NULL))
+ panic("failed to populate DT\n");
+
+ return 0;
+}
+
+arch_initcall(plat_of_setup);
diff --git a/arch/mips/ralink/prom.c b/arch/mips/ralink/prom.c
new file mode 100644
index 000000000000..9c64f029d047
--- /dev/null
+++ b/arch/mips/ralink/prom.c
@@ -0,0 +1,69 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2010 Joonas Lahtinen <joonas.lahtinen@gmail.com>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/string.h>
+#include <linux/of_fdt.h>
+#include <linux/of_platform.h>
+
+#include <asm/bootinfo.h>
+#include <asm/addrspace.h>
+
+#include "common.h"
+
+struct ralink_soc_info soc_info;
+
+const char *get_system_type(void)
+{
+ return soc_info.sys_type;
+}
+
+static __init void prom_init_cmdline(int argc, char **argv)
+{
+ int i;
+
+ pr_debug("prom: fw_arg0=%08x fw_arg1=%08x fw_arg2=%08x fw_arg3=%08x\n",
+ (unsigned int)fw_arg0, (unsigned int)fw_arg1,
+ (unsigned int)fw_arg2, (unsigned int)fw_arg3);
+
+ argc = fw_arg0;
+ argv = (char **) KSEG1ADDR(fw_arg1);
+
+ if (!argv) {
+ pr_debug("argv=%p is invalid, skipping\n",
+ argv);
+ return;
+ }
+
+ for (i = 0; i < argc; i++) {
+ char *p = (char *) KSEG1ADDR(argv[i]);
+
+ if (CPHYSADDR(p) && *p) {
+ pr_debug("argv[%d]: %s\n", i, p);
+ strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
+ strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
+ }
+ }
+}
+
+void __init prom_init(void)
+{
+ int argc;
+ char **argv;
+
+ prom_soc_init(&soc_info);
+
+ pr_info("SoC Type: %s\n", get_system_type());
+
+ prom_init_cmdline(argc, argv);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
diff --git a/arch/mips/ralink/reset.c b/arch/mips/ralink/reset.c
new file mode 100644
index 000000000000..22120e512e7e
--- /dev/null
+++ b/arch/mips/ralink/reset.c
@@ -0,0 +1,44 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/pm.h>
+#include <linux/io.h>
+
+#include <asm/reboot.h>
+
+#include <asm/mach-ralink/ralink_regs.h>
+
+/* Reset Control */
+#define SYSC_REG_RESET_CTRL 0x034
+#define RSTCTL_RESET_SYSTEM BIT(0)
+
+static void ralink_restart(char *command)
+{
+ local_irq_disable();
+ rt_sysc_w32(RSTCTL_RESET_SYSTEM, SYSC_REG_RESET_CTRL);
+ unreachable();
+}
+
+static void ralink_halt(void)
+{
+ local_irq_disable();
+ unreachable();
+}
+
+static int __init mips_reboot_setup(void)
+{
+ _machine_restart = ralink_restart;
+ _machine_halt = ralink_halt;
+ pm_power_off = ralink_halt;
+
+ return 0;
+}
+
+arch_initcall(mips_reboot_setup);
diff --git a/arch/mips/ralink/rt305x.c b/arch/mips/ralink/rt305x.c
new file mode 100644
index 000000000000..0a4bbdcf59d9
--- /dev/null
+++ b/arch/mips/ralink/rt305x.c
@@ -0,0 +1,242 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Parts of this file are based on Ralink's 2.6.21 BSP
+ *
+ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/mipsregs.h>
+#include <asm/mach-ralink/ralink_regs.h>
+#include <asm/mach-ralink/rt305x.h>
+
+#include "common.h"
+
+enum rt305x_soc_type rt305x_soc;
+
+struct ralink_pinmux_grp mode_mux[] = {
+ {
+ .name = "i2c",
+ .mask = RT305X_GPIO_MODE_I2C,
+ .gpio_first = RT305X_GPIO_I2C_SD,
+ .gpio_last = RT305X_GPIO_I2C_SCLK,
+ }, {
+ .name = "spi",
+ .mask = RT305X_GPIO_MODE_SPI,
+ .gpio_first = RT305X_GPIO_SPI_EN,
+ .gpio_last = RT305X_GPIO_SPI_CLK,
+ }, {
+ .name = "uartlite",
+ .mask = RT305X_GPIO_MODE_UART1,
+ .gpio_first = RT305X_GPIO_UART1_TXD,
+ .gpio_last = RT305X_GPIO_UART1_RXD,
+ }, {
+ .name = "jtag",
+ .mask = RT305X_GPIO_MODE_JTAG,
+ .gpio_first = RT305X_GPIO_JTAG_TDO,
+ .gpio_last = RT305X_GPIO_JTAG_TDI,
+ }, {
+ .name = "mdio",
+ .mask = RT305X_GPIO_MODE_MDIO,
+ .gpio_first = RT305X_GPIO_MDIO_MDC,
+ .gpio_last = RT305X_GPIO_MDIO_MDIO,
+ }, {
+ .name = "sdram",
+ .mask = RT305X_GPIO_MODE_SDRAM,
+ .gpio_first = RT305X_GPIO_SDRAM_MD16,
+ .gpio_last = RT305X_GPIO_SDRAM_MD31,
+ }, {
+ .name = "rgmii",
+ .mask = RT305X_GPIO_MODE_RGMII,
+ .gpio_first = RT305X_GPIO_GE0_TXD0,
+ .gpio_last = RT305X_GPIO_GE0_RXCLK,
+ }, {0}
+};
+
+struct ralink_pinmux_grp uart_mux[] = {
+ {
+ .name = "uartf",
+ .mask = RT305X_GPIO_MODE_UARTF,
+ .gpio_first = RT305X_GPIO_7,
+ .gpio_last = RT305X_GPIO_14,
+ }, {
+ .name = "pcm uartf",
+ .mask = RT305X_GPIO_MODE_PCM_UARTF,
+ .gpio_first = RT305X_GPIO_7,
+ .gpio_last = RT305X_GPIO_14,
+ }, {
+ .name = "pcm i2s",
+ .mask = RT305X_GPIO_MODE_PCM_I2S,
+ .gpio_first = RT305X_GPIO_7,
+ .gpio_last = RT305X_GPIO_14,
+ }, {
+ .name = "i2s uartf",
+ .mask = RT305X_GPIO_MODE_I2S_UARTF,
+ .gpio_first = RT305X_GPIO_7,
+ .gpio_last = RT305X_GPIO_14,
+ }, {
+ .name = "pcm gpio",
+ .mask = RT305X_GPIO_MODE_PCM_GPIO,
+ .gpio_first = RT305X_GPIO_10,
+ .gpio_last = RT305X_GPIO_14,
+ }, {
+ .name = "gpio uartf",
+ .mask = RT305X_GPIO_MODE_GPIO_UARTF,
+ .gpio_first = RT305X_GPIO_7,
+ .gpio_last = RT305X_GPIO_14,
+ }, {
+ .name = "gpio i2s",
+ .mask = RT305X_GPIO_MODE_GPIO_I2S,
+ .gpio_first = RT305X_GPIO_7,
+ .gpio_last = RT305X_GPIO_14,
+ }, {
+ .name = "gpio",
+ .mask = RT305X_GPIO_MODE_GPIO,
+ }, {0}
+};
+
+void rt305x_wdt_reset(void)
+{
+ u32 t;
+
+ /* enable WDT reset output on pin SRAM_CS_N */
+ t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG);
+ t |= RT305X_SYSCFG_SRAM_CS0_MODE_WDT <<
+ RT305X_SYSCFG_SRAM_CS0_MODE_SHIFT;
+ rt_sysc_w32(t, SYSC_REG_SYSTEM_CONFIG);
+}
+
+struct ralink_pinmux gpio_pinmux = {
+ .mode = mode_mux,
+ .uart = uart_mux,
+ .uart_shift = RT305X_GPIO_MODE_UART0_SHIFT,
+ .wdt_reset = rt305x_wdt_reset,
+};
+
+void __init ralink_clk_init(void)
+{
+ unsigned long cpu_rate, sys_rate, wdt_rate, uart_rate;
+ u32 t = rt_sysc_r32(SYSC_REG_SYSTEM_CONFIG);
+
+ if (soc_is_rt305x() || soc_is_rt3350()) {
+ t = (t >> RT305X_SYSCFG_CPUCLK_SHIFT) &
+ RT305X_SYSCFG_CPUCLK_MASK;
+ switch (t) {
+ case RT305X_SYSCFG_CPUCLK_LOW:
+ cpu_rate = 320000000;
+ break;
+ case RT305X_SYSCFG_CPUCLK_HIGH:
+ cpu_rate = 384000000;
+ break;
+ }
+ sys_rate = uart_rate = wdt_rate = cpu_rate / 3;
+ } else if (soc_is_rt3352()) {
+ t = (t >> RT3352_SYSCFG0_CPUCLK_SHIFT) &
+ RT3352_SYSCFG0_CPUCLK_MASK;
+ switch (t) {
+ case RT3352_SYSCFG0_CPUCLK_LOW:
+ cpu_rate = 384000000;
+ break;
+ case RT3352_SYSCFG0_CPUCLK_HIGH:
+ cpu_rate = 400000000;
+ break;
+ }
+ sys_rate = wdt_rate = cpu_rate / 3;
+ uart_rate = 40000000;
+ } else if (soc_is_rt5350()) {
+ t = (t >> RT5350_SYSCFG0_CPUCLK_SHIFT) &
+ RT5350_SYSCFG0_CPUCLK_MASK;
+ switch (t) {
+ case RT5350_SYSCFG0_CPUCLK_360:
+ cpu_rate = 360000000;
+ sys_rate = cpu_rate / 3;
+ break;
+ case RT5350_SYSCFG0_CPUCLK_320:
+ cpu_rate = 320000000;
+ sys_rate = cpu_rate / 4;
+ break;
+ case RT5350_SYSCFG0_CPUCLK_300:
+ cpu_rate = 300000000;
+ sys_rate = cpu_rate / 3;
+ break;
+ default:
+ BUG();
+ }
+ uart_rate = 40000000;
+ wdt_rate = sys_rate;
+ } else {
+ BUG();
+ }
+
+ ralink_clk_add("cpu", cpu_rate);
+ ralink_clk_add("10000b00.spi", sys_rate);
+ ralink_clk_add("10000100.timer", wdt_rate);
+ ralink_clk_add("10000500.uart", uart_rate);
+ ralink_clk_add("10000c00.uartlite", uart_rate);
+}
+
+void __init ralink_of_remap(void)
+{
+ rt_sysc_membase = plat_of_remap_node("ralink,rt3050-sysc");
+ rt_memc_membase = plat_of_remap_node("ralink,rt3050-memc");
+
+ if (!rt_sysc_membase || !rt_memc_membase)
+ panic("Failed to remap core resources");
+}
+
+void prom_soc_init(struct ralink_soc_info *soc_info)
+{
+ void __iomem *sysc = (void __iomem *) KSEG1ADDR(RT305X_SYSC_BASE);
+ unsigned char *name;
+ u32 n0;
+ u32 n1;
+ u32 id;
+
+ n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0);
+ n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1);
+
+ if (n0 == RT3052_CHIP_NAME0 && n1 == RT3052_CHIP_NAME1) {
+ unsigned long icache_sets;
+
+ icache_sets = (read_c0_config1() >> 22) & 7;
+ if (icache_sets == 1) {
+ rt305x_soc = RT305X_SOC_RT3050;
+ name = "RT3050";
+ soc_info->compatible = "ralink,rt3050-soc";
+ } else {
+ rt305x_soc = RT305X_SOC_RT3052;
+ name = "RT3052";
+ soc_info->compatible = "ralink,rt3052-soc";
+ }
+ } else if (n0 == RT3350_CHIP_NAME0 && n1 == RT3350_CHIP_NAME1) {
+ rt305x_soc = RT305X_SOC_RT3350;
+ name = "RT3350";
+ soc_info->compatible = "ralink,rt3350-soc";
+ } else if (n0 == RT3352_CHIP_NAME0 && n1 == RT3352_CHIP_NAME1) {
+ rt305x_soc = RT305X_SOC_RT3352;
+ name = "RT3352";
+ soc_info->compatible = "ralink,rt3352-soc";
+ } else if (n0 == RT5350_CHIP_NAME0 && n1 == RT5350_CHIP_NAME1) {
+ rt305x_soc = RT305X_SOC_RT5350;
+ name = "RT5350";
+ soc_info->compatible = "ralink,rt5350-soc";
+ } else {
+ panic("rt305x: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
+ }
+
+ id = __raw_readl(sysc + SYSC_REG_CHIP_ID);
+
+ snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN,
+ "Ralink %s id:%u rev:%u",
+ name,
+ (id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK,
+ (id & CHIP_ID_REV_MASK));
+}