aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/ath79
diff options
context:
space:
mode:
authorGabor Juhos <juhosg@openwrt.org>2011-01-04 15:28:14 -0500
committerRalf Baechle <ralf@linux-mips.org>2011-01-18 13:30:24 -0500
commitd4a67d9dc8a5a80c4ec1814791af8c0252c158b8 (patch)
tree28c9797f2ec5bf46325e1d5dd7db675ac0ac6713 /arch/mips/ath79
parent94bb0c1ab293c298a8852e4f10c4215bad6daa9b (diff)
MIPS: Add initial support for the Atheros AR71XX/AR724X/AR931X SoCs
This patch adds initial support for various Atheros SoCs based on the MIPS 24Kc core. The following models are supported at the moment: - AR7130 - AR7141 - AR7161 - AR9130 - AR9132 - AR7240 - AR7241 - AR7242 The current patch contains minimal support only, but the resulting kernel can boot into user-space with using of an initramfs image on various boards which are using these SoCs. Support for more built-in devices and individual boards will be implemented in further patches. Signed-off-by: Gabor Juhos <juhosg@openwrt.org> Signed-off-by: Imre Kaloz <kaloz@openwrt.org> Cc: linux-mips@linux-mips.org Cc: Luis R. Rodriguez <lrodriguez@atheros.com> Cc: Cliff Holden <Cliff.Holden@Atheros.com> Cc: Kathy Giori <Kathy.Giori@Atheros.com> Patchwork: https://patchwork.linux-mips.org/patch/1947/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/ath79')
-rw-r--r--arch/mips/ath79/Kconfig12
-rw-r--r--arch/mips/ath79/Makefile18
-rw-r--r--arch/mips/ath79/Platform7
-rw-r--r--arch/mips/ath79/clock.c183
-rw-r--r--arch/mips/ath79/common.c97
-rw-r--r--arch/mips/ath79/common.h26
-rw-r--r--arch/mips/ath79/dev-common.c67
-rw-r--r--arch/mips/ath79/dev-common.h17
-rw-r--r--arch/mips/ath79/early_printk.c36
-rw-r--r--arch/mips/ath79/irq.c187
-rw-r--r--arch/mips/ath79/prom.c57
-rw-r--r--arch/mips/ath79/setup.c190
12 files changed, 897 insertions, 0 deletions
diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
new file mode 100644
index 000000000000..50b933446cc0
--- /dev/null
+++ b/arch/mips/ath79/Kconfig
@@ -0,0 +1,12 @@
1if ATH79
2
3config SOC_AR71XX
4 def_bool n
5
6config SOC_AR724X
7 def_bool n
8
9config SOC_AR913X
10 def_bool n
11
12endif
diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
new file mode 100644
index 000000000000..31e0f83ddf68
--- /dev/null
+++ b/arch/mips/ath79/Makefile
@@ -0,0 +1,18 @@
1#
2# Makefile for the Atheros AR71XX/AR724X/AR913X specific parts of the kernel
3#
4# Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
5# Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6#
7# This program is free software; you can redistribute it and/or modify it
8# under the terms of the GNU General Public License version 2 as published
9# by the Free Software Foundation.
10
11obj-y := prom.o setup.o irq.o common.o clock.o
12
13obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
14
15#
16# Devices
17#
18obj-y += dev-common.o
diff --git a/arch/mips/ath79/Platform b/arch/mips/ath79/Platform
new file mode 100644
index 000000000000..2bd663647d27
--- /dev/null
+++ b/arch/mips/ath79/Platform
@@ -0,0 +1,7 @@
1#
2# Atheros AR71xx/AR724x/AR913x
3#
4
5platform-$(CONFIG_ATH79) += ath79/
6cflags-$(CONFIG_ATH79) += -I$(srctree)/arch/mips/include/asm/mach-ath79
7load-$(CONFIG_ATH79) = 0xffffffff80060000
diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c
new file mode 100644
index 000000000000..680bde99a26c
--- /dev/null
+++ b/arch/mips/ath79/clock.c
@@ -0,0 +1,183 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X common routines
3 *
4 * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published
8 * by the Free Software Foundation.
9 */
10
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/err.h>
15#include <linux/clk.h>
16
17#include <asm/mach-ath79/ath79.h>
18#include <asm/mach-ath79/ar71xx_regs.h>
19#include "common.h"
20
21#define AR71XX_BASE_FREQ 40000000
22#define AR724X_BASE_FREQ 5000000
23#define AR913X_BASE_FREQ 5000000
24
25struct clk {
26 unsigned long rate;
27};
28
29static struct clk ath79_ref_clk;
30static struct clk ath79_cpu_clk;
31static struct clk ath79_ddr_clk;
32static struct clk ath79_ahb_clk;
33static struct clk ath79_wdt_clk;
34static struct clk ath79_uart_clk;
35
36static void __init ar71xx_clocks_init(void)
37{
38 u32 pll;
39 u32 freq;
40 u32 div;
41
42 ath79_ref_clk.rate = AR71XX_BASE_FREQ;
43
44 pll = ath79_pll_rr(AR71XX_PLL_REG_CPU_CONFIG);
45
46 div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1;
47 freq = div * ath79_ref_clk.rate;
48
49 div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1;
50 ath79_cpu_clk.rate = freq / div;
51
52 div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1;
53 ath79_ddr_clk.rate = freq / div;
54
55 div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2;
56 ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;
57
58 ath79_wdt_clk.rate = ath79_ahb_clk.rate;
59 ath79_uart_clk.rate = ath79_ahb_clk.rate;
60}
61
62static void __init ar724x_clocks_init(void)
63{
64 u32 pll;
65 u32 freq;
66 u32 div;
67
68 ath79_ref_clk.rate = AR724X_BASE_FREQ;
69 pll = ath79_pll_rr(AR724X_PLL_REG_CPU_CONFIG);
70
71 div = ((pll >> AR724X_PLL_DIV_SHIFT) & AR724X_PLL_DIV_MASK);
72 freq = div * ath79_ref_clk.rate;
73
74 div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK);
75 freq *= div;
76
77 ath79_cpu_clk.rate = freq;
78
79 div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1;
80 ath79_ddr_clk.rate = freq / div;
81
82 div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2;
83 ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;
84
85 ath79_wdt_clk.rate = ath79_ahb_clk.rate;
86 ath79_uart_clk.rate = ath79_ahb_clk.rate;
87}
88
89static void __init ar913x_clocks_init(void)
90{
91 u32 pll;
92 u32 freq;
93 u32 div;
94
95 ath79_ref_clk.rate = AR913X_BASE_FREQ;
96 pll = ath79_pll_rr(AR913X_PLL_REG_CPU_CONFIG);
97
98 div = ((pll >> AR913X_PLL_DIV_SHIFT) & AR913X_PLL_DIV_MASK);
99 freq = div * ath79_ref_clk.rate;
100
101 ath79_cpu_clk.rate = freq;
102
103 div = ((pll >> AR913X_DDR_DIV_SHIFT) & AR913X_DDR_DIV_MASK) + 1;
104 ath79_ddr_clk.rate = freq / div;
105
106 div = (((pll >> AR913X_AHB_DIV_SHIFT) & AR913X_AHB_DIV_MASK) + 1) * 2;
107 ath79_ahb_clk.rate = ath79_cpu_clk.rate / div;
108
109 ath79_wdt_clk.rate = ath79_ahb_clk.rate;
110 ath79_uart_clk.rate = ath79_ahb_clk.rate;
111}
112
113void __init ath79_clocks_init(void)
114{
115 if (soc_is_ar71xx())
116 ar71xx_clocks_init();
117 else if (soc_is_ar724x())
118 ar724x_clocks_init();
119 else if (soc_is_ar913x())
120 ar913x_clocks_init();
121 else
122 BUG();
123
124 pr_info("Clocks: CPU:%lu.%03luMHz, DDR:%lu.%03luMHz, AHB:%lu.%03luMHz, "
125 "Ref:%lu.%03luMHz",
126 ath79_cpu_clk.rate / 1000000,
127 (ath79_cpu_clk.rate / 1000) % 1000,
128 ath79_ddr_clk.rate / 1000000,
129 (ath79_ddr_clk.rate / 1000) % 1000,
130 ath79_ahb_clk.rate / 1000000,
131 (ath79_ahb_clk.rate / 1000) % 1000,
132 ath79_ref_clk.rate / 1000000,
133 (ath79_ref_clk.rate / 1000) % 1000);
134}
135
136/*
137 * Linux clock API
138 */
139struct clk *clk_get(struct device *dev, const char *id)
140{
141 if (!strcmp(id, "ref"))
142 return &ath79_ref_clk;
143
144 if (!strcmp(id, "cpu"))
145 return &ath79_cpu_clk;
146
147 if (!strcmp(id, "ddr"))
148 return &ath79_ddr_clk;
149
150 if (!strcmp(id, "ahb"))
151 return &ath79_ahb_clk;
152
153 if (!strcmp(id, "wdt"))
154 return &ath79_wdt_clk;
155
156 if (!strcmp(id, "uart"))
157 return &ath79_uart_clk;
158
159 return ERR_PTR(-ENOENT);
160}
161EXPORT_SYMBOL(clk_get);
162
163int clk_enable(struct clk *clk)
164{
165 return 0;
166}
167EXPORT_SYMBOL(clk_enable);
168
169void clk_disable(struct clk *clk)
170{
171}
172EXPORT_SYMBOL(clk_disable);
173
174unsigned long clk_get_rate(struct clk *clk)
175{
176 return clk->rate;
177}
178EXPORT_SYMBOL(clk_get_rate);
179
180void clk_put(struct clk *clk)
181{
182}
183EXPORT_SYMBOL(clk_put);
diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c
new file mode 100644
index 000000000000..58f60e722a03
--- /dev/null
+++ b/arch/mips/ath79/common.c
@@ -0,0 +1,97 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X common routines
3 *
4 * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published
9 * by the Free Software Foundation.
10 */
11
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/types.h>
15#include <linux/spinlock.h>
16
17#include <asm/mach-ath79/ath79.h>
18#include <asm/mach-ath79/ar71xx_regs.h>
19#include "common.h"
20
21static DEFINE_SPINLOCK(ath79_device_reset_lock);
22
23u32 ath79_cpu_freq;
24EXPORT_SYMBOL_GPL(ath79_cpu_freq);
25
26u32 ath79_ahb_freq;
27EXPORT_SYMBOL_GPL(ath79_ahb_freq);
28
29u32 ath79_ddr_freq;
30EXPORT_SYMBOL_GPL(ath79_ddr_freq);
31
32enum ath79_soc_type ath79_soc;
33
34void __iomem *ath79_pll_base;
35void __iomem *ath79_reset_base;
36EXPORT_SYMBOL_GPL(ath79_reset_base);
37void __iomem *ath79_ddr_base;
38
39void ath79_ddr_wb_flush(u32 reg)
40{
41 void __iomem *flush_reg = ath79_ddr_base + reg;
42
43 /* Flush the DDR write buffer. */
44 __raw_writel(0x1, flush_reg);
45 while (__raw_readl(flush_reg) & 0x1)
46 ;
47
48 /* It must be run twice. */
49 __raw_writel(0x1, flush_reg);
50 while (__raw_readl(flush_reg) & 0x1)
51 ;
52}
53EXPORT_SYMBOL_GPL(ath79_ddr_wb_flush);
54
55void ath79_device_reset_set(u32 mask)
56{
57 unsigned long flags;
58 u32 reg;
59 u32 t;
60
61 if (soc_is_ar71xx())
62 reg = AR71XX_RESET_REG_RESET_MODULE;
63 else if (soc_is_ar724x())
64 reg = AR724X_RESET_REG_RESET_MODULE;
65 else if (soc_is_ar913x())
66 reg = AR913X_RESET_REG_RESET_MODULE;
67 else
68 BUG();
69
70 spin_lock_irqsave(&ath79_device_reset_lock, flags);
71 t = ath79_reset_rr(reg);
72 ath79_reset_wr(reg, t | mask);
73 spin_unlock_irqrestore(&ath79_device_reset_lock, flags);
74}
75EXPORT_SYMBOL_GPL(ath79_device_reset_set);
76
77void ath79_device_reset_clear(u32 mask)
78{
79 unsigned long flags;
80 u32 reg;
81 u32 t;
82
83 if (soc_is_ar71xx())
84 reg = AR71XX_RESET_REG_RESET_MODULE;
85 else if (soc_is_ar724x())
86 reg = AR724X_RESET_REG_RESET_MODULE;
87 else if (soc_is_ar913x())
88 reg = AR913X_RESET_REG_RESET_MODULE;
89 else
90 BUG();
91
92 spin_lock_irqsave(&ath79_device_reset_lock, flags);
93 t = ath79_reset_rr(reg);
94 ath79_reset_wr(reg, t & ~mask);
95 spin_unlock_irqrestore(&ath79_device_reset_lock, flags);
96}
97EXPORT_SYMBOL_GPL(ath79_device_reset_clear);
diff --git a/arch/mips/ath79/common.h b/arch/mips/ath79/common.h
new file mode 100644
index 000000000000..612a6b5d8702
--- /dev/null
+++ b/arch/mips/ath79/common.h
@@ -0,0 +1,26 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X common definitions
3 *
4 * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 *
7 * Parts of this file are based on Atheros' 2.6.15 BSP
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published
11 * by the Free Software Foundation.
12 */
13
14#ifndef __ATH79_COMMON_H
15#define __ATH79_COMMON_H
16
17#include <linux/types.h>
18#include <linux/init.h>
19
20#define ATH79_MEM_SIZE_MIN (2 * 1024 * 1024)
21#define ATH79_MEM_SIZE_MAX (128 * 1024 * 1024)
22
23void ath79_clocks_init(void);
24void ath79_ddr_wb_flush(unsigned int reg);
25
26#endif /* __ATH79_COMMON_H */
diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c
new file mode 100644
index 000000000000..3cfa10065d68
--- /dev/null
+++ b/arch/mips/ath79/dev-common.c
@@ -0,0 +1,67 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X common devices
3 *
4 * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 *
7 * Parts of this file are based on Atheros' 2.6.15 BSP
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published
11 * by the Free Software Foundation.
12 */
13
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/platform_device.h>
17#include <linux/serial_8250.h>
18#include <linux/clk.h>
19#include <linux/err.h>
20
21#include <asm/mach-ath79/ath79.h>
22#include <asm/mach-ath79/ar71xx_regs.h>
23#include "common.h"
24#include "dev-common.h"
25
26static struct resource ath79_uart_resources[] = {
27 {
28 .start = AR71XX_UART_BASE,
29 .end = AR71XX_UART_BASE + AR71XX_UART_SIZE - 1,
30 .flags = IORESOURCE_MEM,
31 },
32};
33
34#define AR71XX_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP)
35static struct plat_serial8250_port ath79_uart_data[] = {
36 {
37 .mapbase = AR71XX_UART_BASE,
38 .irq = ATH79_MISC_IRQ_UART,
39 .flags = AR71XX_UART_FLAGS,
40 .iotype = UPIO_MEM32,
41 .regshift = 2,
42 }, {
43 /* terminating entry */
44 }
45};
46
47static struct platform_device ath79_uart_device = {
48 .name = "serial8250",
49 .id = PLAT8250_DEV_PLATFORM,
50 .resource = ath79_uart_resources,
51 .num_resources = ARRAY_SIZE(ath79_uart_resources),
52 .dev = {
53 .platform_data = ath79_uart_data
54 },
55};
56
57void __init ath79_register_uart(void)
58{
59 struct clk *clk;
60
61 clk = clk_get(NULL, "uart");
62 if (IS_ERR(clk))
63 panic("unable to get UART clock, err=%ld", PTR_ERR(clk));
64
65 ath79_uart_data[0].uartclk = clk_get_rate(clk);
66 platform_device_register(&ath79_uart_device);
67}
diff --git a/arch/mips/ath79/dev-common.h b/arch/mips/ath79/dev-common.h
new file mode 100644
index 000000000000..248622cc7cd6
--- /dev/null
+++ b/arch/mips/ath79/dev-common.h
@@ -0,0 +1,17 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X common devices
3 *
4 * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published
9 * by the Free Software Foundation.
10 */
11
12#ifndef _ATH79_DEV_COMMON_H
13#define _ATH79_DEV_COMMON_H
14
15void ath79_register_uart(void);
16
17#endif /* _ATH79_DEV_COMMON_H */
diff --git a/arch/mips/ath79/early_printk.c b/arch/mips/ath79/early_printk.c
new file mode 100644
index 000000000000..7499b0e9df26
--- /dev/null
+++ b/arch/mips/ath79/early_printk.c
@@ -0,0 +1,36 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X SoC early printk support
3 *
4 * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published
9 * by the Free Software Foundation.
10 */
11
12#include <linux/io.h>
13#include <linux/serial_reg.h>
14#include <asm/addrspace.h>
15
16#include <asm/mach-ath79/ar71xx_regs.h>
17
18static inline void prom_wait_thre(void __iomem *base)
19{
20 u32 lsr;
21
22 do {
23 lsr = __raw_readl(base + UART_LSR * 4);
24 if (lsr & UART_LSR_THRE)
25 break;
26 } while (1);
27}
28
29void prom_putchar(unsigned char ch)
30{
31 void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE));
32
33 prom_wait_thre(base);
34 __raw_writel(ch, base + UART_TX * 4);
35 prom_wait_thre(base);
36}
diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c
new file mode 100644
index 000000000000..1bf7f719ba53
--- /dev/null
+++ b/arch/mips/ath79/irq.c
@@ -0,0 +1,187 @@
1/*
2 * Atheros AR71xx/AR724x/AR913x specific interrupt handling
3 *
4 * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 *
7 * Parts of this file are based on Atheros' 2.6.15 BSP
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published
11 * by the Free Software Foundation.
12 */
13
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/interrupt.h>
17#include <linux/irq.h>
18
19#include <asm/irq_cpu.h>
20#include <asm/mipsregs.h>
21
22#include <asm/mach-ath79/ath79.h>
23#include <asm/mach-ath79/ar71xx_regs.h>
24#include "common.h"
25
26static unsigned int ath79_ip2_flush_reg;
27static unsigned int ath79_ip3_flush_reg;
28
29static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc)
30{
31 void __iomem *base = ath79_reset_base;
32 u32 pending;
33
34 pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) &
35 __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
36
37 if (pending & MISC_INT_UART)
38 generic_handle_irq(ATH79_MISC_IRQ_UART);
39
40 else if (pending & MISC_INT_DMA)
41 generic_handle_irq(ATH79_MISC_IRQ_DMA);
42
43 else if (pending & MISC_INT_PERFC)
44 generic_handle_irq(ATH79_MISC_IRQ_PERFC);
45
46 else if (pending & MISC_INT_TIMER)
47 generic_handle_irq(ATH79_MISC_IRQ_TIMER);
48
49 else if (pending & MISC_INT_OHCI)
50 generic_handle_irq(ATH79_MISC_IRQ_OHCI);
51
52 else if (pending & MISC_INT_ERROR)
53 generic_handle_irq(ATH79_MISC_IRQ_ERROR);
54
55 else if (pending & MISC_INT_GPIO)
56 generic_handle_irq(ATH79_MISC_IRQ_GPIO);
57
58 else if (pending & MISC_INT_WDOG)
59 generic_handle_irq(ATH79_MISC_IRQ_WDOG);
60
61 else
62 spurious_interrupt();
63}
64
65static void ar71xx_misc_irq_unmask(unsigned int irq)
66{
67 void __iomem *base = ath79_reset_base;
68 u32 t;
69
70 irq -= ATH79_MISC_IRQ_BASE;
71
72 t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
73 __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
74
75 /* flush write */
76 __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
77}
78
79static void ar71xx_misc_irq_mask(unsigned int irq)
80{
81 void __iomem *base = ath79_reset_base;
82 u32 t;
83
84 irq -= ATH79_MISC_IRQ_BASE;
85
86 t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
87 __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
88
89 /* flush write */
90 __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
91}
92
93static void ar724x_misc_irq_ack(unsigned int irq)
94{
95 void __iomem *base = ath79_reset_base;
96 u32 t;
97
98 irq -= ATH79_MISC_IRQ_BASE;
99
100 t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
101 __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_STATUS);
102
103 /* flush write */
104 __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
105}
106
107static struct irq_chip ath79_misc_irq_chip = {
108 .name = "MISC",
109 .unmask = ar71xx_misc_irq_unmask,
110 .mask = ar71xx_misc_irq_mask,
111};
112
113static void __init ath79_misc_irq_init(void)
114{
115 void __iomem *base = ath79_reset_base;
116 int i;
117
118 __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
119 __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
120
121 if (soc_is_ar71xx() || soc_is_ar913x())
122 ath79_misc_irq_chip.mask_ack = ar71xx_misc_irq_mask;
123 else if (soc_is_ar724x())
124 ath79_misc_irq_chip.ack = ar724x_misc_irq_ack;
125 else
126 BUG();
127
128 for (i = ATH79_MISC_IRQ_BASE;
129 i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) {
130 irq_desc[i].status = IRQ_DISABLED;
131 set_irq_chip_and_handler(i, &ath79_misc_irq_chip,
132 handle_level_irq);
133 }
134
135 set_irq_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler);
136}
137
138asmlinkage void plat_irq_dispatch(void)
139{
140 unsigned long pending;
141
142 pending = read_c0_status() & read_c0_cause() & ST0_IM;
143
144 if (pending & STATUSF_IP7)
145 do_IRQ(ATH79_CPU_IRQ_TIMER);
146
147 else if (pending & STATUSF_IP2) {
148 ath79_ddr_wb_flush(ath79_ip2_flush_reg);
149 do_IRQ(ATH79_CPU_IRQ_IP2);
150 }
151
152 else if (pending & STATUSF_IP4)
153 do_IRQ(ATH79_CPU_IRQ_GE0);
154
155 else if (pending & STATUSF_IP5)
156 do_IRQ(ATH79_CPU_IRQ_GE1);
157
158 else if (pending & STATUSF_IP3) {
159 ath79_ddr_wb_flush(ath79_ip3_flush_reg);
160 do_IRQ(ATH79_CPU_IRQ_USB);
161 }
162
163 else if (pending & STATUSF_IP6)
164 do_IRQ(ATH79_CPU_IRQ_MISC);
165
166 else
167 spurious_interrupt();
168}
169
170void __init arch_init_irq(void)
171{
172 if (soc_is_ar71xx()) {
173 ath79_ip2_flush_reg = AR71XX_DDR_REG_FLUSH_PCI;
174 ath79_ip3_flush_reg = AR71XX_DDR_REG_FLUSH_USB;
175 } else if (soc_is_ar724x()) {
176 ath79_ip2_flush_reg = AR724X_DDR_REG_FLUSH_PCIE;
177 ath79_ip3_flush_reg = AR724X_DDR_REG_FLUSH_USB;
178 } else if (soc_is_ar913x()) {
179 ath79_ip2_flush_reg = AR913X_DDR_REG_FLUSH_WMAC;
180 ath79_ip3_flush_reg = AR913X_DDR_REG_FLUSH_USB;
181 } else
182 BUG();
183
184 cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC;
185 mips_cpu_irq_init();
186 ath79_misc_irq_init();
187}
diff --git a/arch/mips/ath79/prom.c b/arch/mips/ath79/prom.c
new file mode 100644
index 000000000000..e9cbd7c2918f
--- /dev/null
+++ b/arch/mips/ath79/prom.c
@@ -0,0 +1,57 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X specific prom routines
3 *
4 * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published
9 * by the Free Software Foundation.
10 */
11
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/io.h>
15#include <linux/string.h>
16
17#include <asm/bootinfo.h>
18#include <asm/addrspace.h>
19
20#include "common.h"
21
22static inline int is_valid_ram_addr(void *addr)
23{
24 if (((u32) addr > KSEG0) &&
25 ((u32) addr < (KSEG0 + ATH79_MEM_SIZE_MAX)))
26 return 1;
27
28 if (((u32) addr > KSEG1) &&
29 ((u32) addr < (KSEG1 + ATH79_MEM_SIZE_MAX)))
30 return 1;
31
32 return 0;
33}
34
35static __init void ath79_prom_init_cmdline(int argc, char **argv)
36{
37 int i;
38
39 if (!is_valid_ram_addr(argv))
40 return;
41
42 for (i = 0; i < argc; i++)
43 if (is_valid_ram_addr(argv[i])) {
44 strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
45 strlcat(arcs_cmdline, argv[i], sizeof(arcs_cmdline));
46 }
47}
48
49void __init prom_init(void)
50{
51 ath79_prom_init_cmdline(fw_arg0, (char **)fw_arg1);
52}
53
54void __init prom_free_prom_memory(void)
55{
56 /* We do not have to prom memory to free */
57}
diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
new file mode 100644
index 000000000000..175def860165
--- /dev/null
+++ b/arch/mips/ath79/setup.c
@@ -0,0 +1,190 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X specific setup
3 *
4 * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 *
7 * Parts of this file are based on Atheros' 2.6.15 BSP
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as published
11 * by the Free Software Foundation.
12 */
13
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/bootmem.h>
17#include <linux/err.h>
18#include <linux/clk.h>
19
20#include <asm/bootinfo.h>
21#include <asm/time.h> /* for mips_hpt_frequency */
22#include <asm/reboot.h> /* for _machine_{restart,halt} */
23
24#include <asm/mach-ath79/ath79.h>
25#include <asm/mach-ath79/ar71xx_regs.h>
26#include "common.h"
27#include "dev-common.h"
28
29#define ATH79_SYS_TYPE_LEN 64
30
31#define AR71XX_BASE_FREQ 40000000
32#define AR724X_BASE_FREQ 5000000
33#define AR913X_BASE_FREQ 5000000
34
35static char ath79_sys_type[ATH79_SYS_TYPE_LEN];
36
37static void ath79_restart(char *command)
38{
39 ath79_device_reset_set(AR71XX_RESET_FULL_CHIP);
40 for (;;)
41 if (cpu_wait)
42 cpu_wait();
43}
44
45static void ath79_halt(void)
46{
47 while (1)
48 cpu_wait();
49}
50
51static void __init ath79_detect_mem_size(void)
52{
53 unsigned long size;
54
55 for (size = ATH79_MEM_SIZE_MIN; size < ATH79_MEM_SIZE_MAX;
56 size <<= 1) {
57 if (!memcmp(ath79_detect_mem_size,
58 ath79_detect_mem_size + size, 1024))
59 break;
60 }
61
62 add_memory_region(0, size, BOOT_MEM_RAM);
63}
64
65static void __init ath79_detect_sys_type(void)
66{
67 char *chip = "????";
68 u32 id;
69 u32 major;
70 u32 minor;
71 u32 rev = 0;
72
73 id = ath79_reset_rr(AR71XX_RESET_REG_REV_ID);
74 major = id & REV_ID_MAJOR_MASK;
75
76 switch (major) {
77 case REV_ID_MAJOR_AR71XX:
78 minor = id & AR71XX_REV_ID_MINOR_MASK;
79 rev = id >> AR71XX_REV_ID_REVISION_SHIFT;
80 rev &= AR71XX_REV_ID_REVISION_MASK;
81 switch (minor) {
82 case AR71XX_REV_ID_MINOR_AR7130:
83 ath79_soc = ATH79_SOC_AR7130;
84 chip = "7130";
85 break;
86
87 case AR71XX_REV_ID_MINOR_AR7141:
88 ath79_soc = ATH79_SOC_AR7141;
89 chip = "7141";
90 break;
91
92 case AR71XX_REV_ID_MINOR_AR7161:
93 ath79_soc = ATH79_SOC_AR7161;
94 chip = "7161";
95 break;
96 }
97 break;
98
99 case REV_ID_MAJOR_AR7240:
100 ath79_soc = ATH79_SOC_AR7240;
101 chip = "7240";
102 rev = (id & AR724X_REV_ID_REVISION_MASK);
103 break;
104
105 case REV_ID_MAJOR_AR7241:
106 ath79_soc = ATH79_SOC_AR7241;
107 chip = "7241";
108 rev = (id & AR724X_REV_ID_REVISION_MASK);
109 break;
110
111 case REV_ID_MAJOR_AR7242:
112 ath79_soc = ATH79_SOC_AR7242;
113 chip = "7242";
114 rev = (id & AR724X_REV_ID_REVISION_MASK);
115 break;
116
117 case REV_ID_MAJOR_AR913X:
118 minor = id & AR913X_REV_ID_MINOR_MASK;
119 rev = id >> AR913X_REV_ID_REVISION_SHIFT;
120 rev &= AR913X_REV_ID_REVISION_MASK;
121 switch (minor) {
122 case AR913X_REV_ID_MINOR_AR9130:
123 ath79_soc = ATH79_SOC_AR9130;
124 chip = "9130";
125 break;
126
127 case AR913X_REV_ID_MINOR_AR9132:
128 ath79_soc = ATH79_SOC_AR9132;
129 chip = "9132";
130 break;
131 }
132 break;
133
134 default:
135 panic("ath79: unknown SoC, id:0x%08x\n", id);
136 }
137
138 sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev);
139 pr_info("SoC: %s\n", ath79_sys_type);
140}
141
142const char *get_system_type(void)
143{
144 return ath79_sys_type;
145}
146
147unsigned int __cpuinit get_c0_compare_int(void)
148{
149 return CP0_LEGACY_COMPARE_IRQ;
150}
151
152void __init plat_mem_setup(void)
153{
154 set_io_port_base(KSEG1);
155
156 ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE,
157 AR71XX_RESET_SIZE);
158 ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
159 AR71XX_PLL_SIZE);
160
161 ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE,
162 AR71XX_DDR_CTRL_SIZE);
163
164 ath79_detect_sys_type();
165 ath79_detect_mem_size();
166 ath79_clocks_init();
167
168 _machine_restart = ath79_restart;
169 _machine_halt = ath79_halt;
170 pm_power_off = ath79_halt;
171}
172
173void __init plat_time_init(void)
174{
175 struct clk *clk;
176
177 clk = clk_get(NULL, "cpu");
178 if (IS_ERR(clk))
179 panic("unable to get CPU clock, err=%ld", PTR_ERR(clk));
180
181 mips_hpt_frequency = clk_get_rate(clk) / 2;
182}
183
184static int __init ath79_setup(void)
185{
186 ath79_register_uart();
187 return 0;
188}
189
190arch_initcall(ath79_setup);