aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/ath79
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2011-02-14 05:55:18 -0500
committerIngo Molnar <mingo@elte.hu>2011-02-14 05:55:18 -0500
commitd2137d5af4259f50c19addb8246a186c9ffac325 (patch)
tree2f7e309f9cf8ef2f2698532c226edda38021fe69 /arch/mips/ath79
parentf005fe12b90c5b9fe180a09209a893e09affa8aa (diff)
parent795abaf1e4e188c4171e3cd3dbb11a9fcacaf505 (diff)
Merge branch 'linus' into x86/bootmem
Conflicts: arch/x86/mm/numa_64.c Merge reason: fix the conflict, update to latest -rc and pick up this dependent fix from Yinghai: e6d2e2b2b1e1: memblock: don't adjust size in memblock_find_base() Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/mips/ath79')
-rw-r--r--arch/mips/ath79/Kconfig50
-rw-r--r--arch/mips/ath79/Makefile28
-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.h31
-rw-r--r--arch/mips/ath79/dev-ar913x-wmac.c60
-rw-r--r--arch/mips/ath79/dev-ar913x-wmac.h17
-rw-r--r--arch/mips/ath79/dev-common.c77
-rw-r--r--arch/mips/ath79/dev-common.h18
-rw-r--r--arch/mips/ath79/dev-gpio-buttons.c58
-rw-r--r--arch/mips/ath79/dev-gpio-buttons.h23
-rw-r--r--arch/mips/ath79/dev-leds-gpio.c56
-rw-r--r--arch/mips/ath79/dev-leds-gpio.h21
-rw-r--r--arch/mips/ath79/dev-spi.c38
-rw-r--r--arch/mips/ath79/dev-spi.h22
-rw-r--r--arch/mips/ath79/early_printk.c36
-rw-r--r--arch/mips/ath79/gpio.c197
-rw-r--r--arch/mips/ath79/irq.c187
-rw-r--r--arch/mips/ath79/mach-ap81.c98
-rw-r--r--arch/mips/ath79/mach-pb44.c118
-rw-r--r--arch/mips/ath79/machtypes.h23
-rw-r--r--arch/mips/ath79/prom.c57
-rw-r--r--arch/mips/ath79/setup.c206
24 files changed, 1708 insertions, 0 deletions
diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig
new file mode 100644
index 000000000000..b05828260f7f
--- /dev/null
+++ b/arch/mips/ath79/Kconfig
@@ -0,0 +1,50 @@
1if ATH79
2
3menu "Atheros AR71XX/AR724X/AR913X machine selection"
4
5config ATH79_MACH_AP81
6 bool "Atheros AP81 reference board"
7 select SOC_AR913X
8 select ATH79_DEV_AR913X_WMAC
9 select ATH79_DEV_GPIO_BUTTONS
10 select ATH79_DEV_LEDS_GPIO
11 select ATH79_DEV_SPI
12 help
13 Say 'Y' here if you want your kernel to support the
14 Atheros AP81 reference board.
15
16config ATH79_MACH_PB44
17 bool "Atheros PB44 reference board"
18 select SOC_AR71XX
19 select ATH79_DEV_GPIO_BUTTONS
20 select ATH79_DEV_LEDS_GPIO
21 select ATH79_DEV_SPI
22 help
23 Say 'Y' here if you want your kernel to support the
24 Atheros PB44 reference board.
25
26endmenu
27
28config SOC_AR71XX
29 def_bool n
30
31config SOC_AR724X
32 def_bool n
33
34config SOC_AR913X
35 def_bool n
36
37config ATH79_DEV_AR913X_WMAC
38 depends on SOC_AR913X
39 def_bool n
40
41config ATH79_DEV_GPIO_BUTTONS
42 def_bool n
43
44config ATH79_DEV_LEDS_GPIO
45 def_bool n
46
47config ATH79_DEV_SPI
48 def_bool n
49
50endif
diff --git a/arch/mips/ath79/Makefile b/arch/mips/ath79/Makefile
new file mode 100644
index 000000000000..c33d4653007c
--- /dev/null
+++ b/arch/mips/ath79/Makefile
@@ -0,0 +1,28 @@
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 gpio.o
12
13obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
14
15#
16# Devices
17#
18obj-y += dev-common.o
19obj-$(CONFIG_ATH79_DEV_AR913X_WMAC) += dev-ar913x-wmac.o
20obj-$(CONFIG_ATH79_DEV_GPIO_BUTTONS) += dev-gpio-buttons.o
21obj-$(CONFIG_ATH79_DEV_LEDS_GPIO) += dev-leds-gpio.o
22obj-$(CONFIG_ATH79_DEV_SPI) += dev-spi.o
23
24#
25# Machines
26#
27obj-$(CONFIG_ATH79_MACH_AP81) += mach-ap81.o
28obj-$(CONFIG_ATH79_MACH_PB44) += mach-pb44.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..561906c2345e
--- /dev/null
+++ b/arch/mips/ath79/common.h
@@ -0,0 +1,31 @@
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
26void ath79_gpio_function_enable(u32 mask);
27void ath79_gpio_function_disable(u32 mask);
28void ath79_gpio_function_setup(u32 set, u32 clear);
29void ath79_gpio_init(void);
30
31#endif /* __ATH79_COMMON_H */
diff --git a/arch/mips/ath79/dev-ar913x-wmac.c b/arch/mips/ath79/dev-ar913x-wmac.c
new file mode 100644
index 000000000000..48f425a5ba28
--- /dev/null
+++ b/arch/mips/ath79/dev-ar913x-wmac.c
@@ -0,0 +1,60 @@
1/*
2 * Atheros AR913X SoC built-in WMAC device 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/init.h>
13#include <linux/delay.h>
14#include <linux/irq.h>
15#include <linux/platform_device.h>
16#include <linux/ath9k_platform.h>
17
18#include <asm/mach-ath79/ath79.h>
19#include <asm/mach-ath79/ar71xx_regs.h>
20#include "dev-ar913x-wmac.h"
21
22static struct ath9k_platform_data ar913x_wmac_data;
23
24static struct resource ar913x_wmac_resources[] = {
25 {
26 .start = AR913X_WMAC_BASE,
27 .end = AR913X_WMAC_BASE + AR913X_WMAC_SIZE - 1,
28 .flags = IORESOURCE_MEM,
29 }, {
30 .start = ATH79_CPU_IRQ_IP2,
31 .end = ATH79_CPU_IRQ_IP2,
32 .flags = IORESOURCE_IRQ,
33 },
34};
35
36static struct platform_device ar913x_wmac_device = {
37 .name = "ath9k",
38 .id = -1,
39 .resource = ar913x_wmac_resources,
40 .num_resources = ARRAY_SIZE(ar913x_wmac_resources),
41 .dev = {
42 .platform_data = &ar913x_wmac_data,
43 },
44};
45
46void __init ath79_register_ar913x_wmac(u8 *cal_data)
47{
48 if (cal_data)
49 memcpy(ar913x_wmac_data.eeprom_data, cal_data,
50 sizeof(ar913x_wmac_data.eeprom_data));
51
52 /* reset the WMAC */
53 ath79_device_reset_set(AR913X_RESET_AMBA2WMAC);
54 mdelay(10);
55
56 ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC);
57 mdelay(10);
58
59 platform_device_register(&ar913x_wmac_device);
60}
diff --git a/arch/mips/ath79/dev-ar913x-wmac.h b/arch/mips/ath79/dev-ar913x-wmac.h
new file mode 100644
index 000000000000..579d562bbda8
--- /dev/null
+++ b/arch/mips/ath79/dev-ar913x-wmac.h
@@ -0,0 +1,17 @@
1/*
2 * Atheros AR913X SoC built-in WMAC device 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#ifndef _ATH79_DEV_AR913X_WMAC_H
13#define _ATH79_DEV_AR913X_WMAC_H
14
15void ath79_register_ar913x_wmac(u8 *cal_data);
16
17#endif /* _ATH79_DEV_AR913X_WMAC_H */
diff --git a/arch/mips/ath79/dev-common.c b/arch/mips/ath79/dev-common.c
new file mode 100644
index 000000000000..3b82e325bebf
--- /dev/null
+++ b/arch/mips/ath79/dev-common.c
@@ -0,0 +1,77 @@
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}
68
69static struct platform_device ath79_wdt_device = {
70 .name = "ath79-wdt",
71 .id = -1,
72};
73
74void __init ath79_register_wdt(void)
75{
76 platform_device_register(&ath79_wdt_device);
77}
diff --git a/arch/mips/ath79/dev-common.h b/arch/mips/ath79/dev-common.h
new file mode 100644
index 000000000000..0f514e1affce
--- /dev/null
+++ b/arch/mips/ath79/dev-common.h
@@ -0,0 +1,18 @@
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);
16void ath79_register_wdt(void);
17
18#endif /* _ATH79_DEV_COMMON_H */
diff --git a/arch/mips/ath79/dev-gpio-buttons.c b/arch/mips/ath79/dev-gpio-buttons.c
new file mode 100644
index 000000000000..4b0168a11c01
--- /dev/null
+++ b/arch/mips/ath79/dev-gpio-buttons.c
@@ -0,0 +1,58 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X GPIO button 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/init.h"
13#include "linux/slab.h"
14#include <linux/platform_device.h>
15
16#include "dev-gpio-buttons.h"
17
18void __init ath79_register_gpio_keys_polled(int id,
19 unsigned poll_interval,
20 unsigned nbuttons,
21 struct gpio_keys_button *buttons)
22{
23 struct platform_device *pdev;
24 struct gpio_keys_platform_data pdata;
25 struct gpio_keys_button *p;
26 int err;
27
28 p = kmalloc(nbuttons * sizeof(*p), GFP_KERNEL);
29 if (!p)
30 return;
31
32 memcpy(p, buttons, nbuttons * sizeof(*p));
33
34 pdev = platform_device_alloc("gpio-keys-polled", id);
35 if (!pdev)
36 goto err_free_buttons;
37
38 memset(&pdata, 0, sizeof(pdata));
39 pdata.poll_interval = poll_interval;
40 pdata.nbuttons = nbuttons;
41 pdata.buttons = p;
42
43 err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
44 if (err)
45 goto err_put_pdev;
46
47 err = platform_device_add(pdev);
48 if (err)
49 goto err_put_pdev;
50
51 return;
52
53err_put_pdev:
54 platform_device_put(pdev);
55
56err_free_buttons:
57 kfree(p);
58}
diff --git a/arch/mips/ath79/dev-gpio-buttons.h b/arch/mips/ath79/dev-gpio-buttons.h
new file mode 100644
index 000000000000..481847ac1cba
--- /dev/null
+++ b/arch/mips/ath79/dev-gpio-buttons.h
@@ -0,0 +1,23 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X GPIO button 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#ifndef _ATH79_DEV_GPIO_BUTTONS_H
13#define _ATH79_DEV_GPIO_BUTTONS_H
14
15#include <linux/input.h>
16#include <linux/gpio_keys.h>
17
18void ath79_register_gpio_keys_polled(int id,
19 unsigned poll_interval,
20 unsigned nbuttons,
21 struct gpio_keys_button *buttons);
22
23#endif /* _ATH79_DEV_GPIO_BUTTONS_H */
diff --git a/arch/mips/ath79/dev-leds-gpio.c b/arch/mips/ath79/dev-leds-gpio.c
new file mode 100644
index 000000000000..cdade68dcd17
--- /dev/null
+++ b/arch/mips/ath79/dev-leds-gpio.c
@@ -0,0 +1,56 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X common GPIO LEDs 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/init.h>
13#include <linux/slab.h>
14#include <linux/platform_device.h>
15
16#include "dev-leds-gpio.h"
17
18void __init ath79_register_leds_gpio(int id,
19 unsigned num_leds,
20 struct gpio_led *leds)
21{
22 struct platform_device *pdev;
23 struct gpio_led_platform_data pdata;
24 struct gpio_led *p;
25 int err;
26
27 p = kmalloc(num_leds * sizeof(*p), GFP_KERNEL);
28 if (!p)
29 return;
30
31 memcpy(p, leds, num_leds * sizeof(*p));
32
33 pdev = platform_device_alloc("leds-gpio", id);
34 if (!pdev)
35 goto err_free_leds;
36
37 memset(&pdata, 0, sizeof(pdata));
38 pdata.num_leds = num_leds;
39 pdata.leds = p;
40
41 err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
42 if (err)
43 goto err_put_pdev;
44
45 err = platform_device_add(pdev);
46 if (err)
47 goto err_put_pdev;
48
49 return;
50
51err_put_pdev:
52 platform_device_put(pdev);
53
54err_free_leds:
55 kfree(p);
56}
diff --git a/arch/mips/ath79/dev-leds-gpio.h b/arch/mips/ath79/dev-leds-gpio.h
new file mode 100644
index 000000000000..6e5d8851ebcf
--- /dev/null
+++ b/arch/mips/ath79/dev-leds-gpio.h
@@ -0,0 +1,21 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X common GPIO LEDs 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#ifndef _ATH79_DEV_LEDS_GPIO_H
13#define _ATH79_DEV_LEDS_GPIO_H
14
15#include <linux/leds.h>
16
17void ath79_register_leds_gpio(int id,
18 unsigned num_leds,
19 struct gpio_led *leds);
20
21#endif /* _ATH79_DEV_LEDS_GPIO_H */
diff --git a/arch/mips/ath79/dev-spi.c b/arch/mips/ath79/dev-spi.c
new file mode 100644
index 000000000000..aa30163efbfd
--- /dev/null
+++ b/arch/mips/ath79/dev-spi.c
@@ -0,0 +1,38 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X SPI controller device
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/platform_device.h>
13#include <asm/mach-ath79/ar71xx_regs.h>
14#include "dev-spi.h"
15
16static struct resource ath79_spi_resources[] = {
17 {
18 .start = AR71XX_SPI_BASE,
19 .end = AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1,
20 .flags = IORESOURCE_MEM,
21 },
22};
23
24static struct platform_device ath79_spi_device = {
25 .name = "ath79-spi",
26 .id = -1,
27 .resource = ath79_spi_resources,
28 .num_resources = ARRAY_SIZE(ath79_spi_resources),
29};
30
31void __init ath79_register_spi(struct ath79_spi_platform_data *pdata,
32 struct spi_board_info const *info,
33 unsigned n)
34{
35 spi_register_board_info(info, n);
36 ath79_spi_device.dev.platform_data = pdata;
37 platform_device_register(&ath79_spi_device);
38}
diff --git a/arch/mips/ath79/dev-spi.h b/arch/mips/ath79/dev-spi.h
new file mode 100644
index 000000000000..d732565ca736
--- /dev/null
+++ b/arch/mips/ath79/dev-spi.h
@@ -0,0 +1,22 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X SPI controller device
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_SPI_H
13#define _ATH79_DEV_SPI_H
14
15#include <linux/spi/spi.h>
16#include <asm/mach-ath79/ath79_spi_platform.h>
17
18void ath79_register_spi(struct ath79_spi_platform_data *pdata,
19 struct spi_board_info const *info,
20 unsigned n);
21
22#endif /* _ATH79_DEV_SPI_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/gpio.c b/arch/mips/ath79/gpio.c
new file mode 100644
index 000000000000..a0c426b82123
--- /dev/null
+++ b/arch/mips/ath79/gpio.c
@@ -0,0 +1,197 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X GPIO API 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/kernel.h>
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/types.h>
16#include <linux/spinlock.h>
17#include <linux/io.h>
18#include <linux/ioport.h>
19#include <linux/gpio.h>
20
21#include <asm/mach-ath79/ar71xx_regs.h>
22#include <asm/mach-ath79/ath79.h>
23#include "common.h"
24
25static void __iomem *ath79_gpio_base;
26static unsigned long ath79_gpio_count;
27static DEFINE_SPINLOCK(ath79_gpio_lock);
28
29static void __ath79_gpio_set_value(unsigned gpio, int value)
30{
31 void __iomem *base = ath79_gpio_base;
32
33 if (value)
34 __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET);
35 else
36 __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR);
37}
38
39static int __ath79_gpio_get_value(unsigned gpio)
40{
41 return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1;
42}
43
44static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset)
45{
46 return __ath79_gpio_get_value(offset);
47}
48
49static void ath79_gpio_set_value(struct gpio_chip *chip,
50 unsigned offset, int value)
51{
52 __ath79_gpio_set_value(offset, value);
53}
54
55static int ath79_gpio_direction_input(struct gpio_chip *chip,
56 unsigned offset)
57{
58 void __iomem *base = ath79_gpio_base;
59 unsigned long flags;
60
61 spin_lock_irqsave(&ath79_gpio_lock, flags);
62
63 __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset),
64 base + AR71XX_GPIO_REG_OE);
65
66 spin_unlock_irqrestore(&ath79_gpio_lock, flags);
67
68 return 0;
69}
70
71static int ath79_gpio_direction_output(struct gpio_chip *chip,
72 unsigned offset, int value)
73{
74 void __iomem *base = ath79_gpio_base;
75 unsigned long flags;
76
77 spin_lock_irqsave(&ath79_gpio_lock, flags);
78
79 if (value)
80 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET);
81 else
82 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR);
83
84 __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset),
85 base + AR71XX_GPIO_REG_OE);
86
87 spin_unlock_irqrestore(&ath79_gpio_lock, flags);
88
89 return 0;
90}
91
92static struct gpio_chip ath79_gpio_chip = {
93 .label = "ath79",
94 .get = ath79_gpio_get_value,
95 .set = ath79_gpio_set_value,
96 .direction_input = ath79_gpio_direction_input,
97 .direction_output = ath79_gpio_direction_output,
98 .base = 0,
99};
100
101void ath79_gpio_function_enable(u32 mask)
102{
103 void __iomem *base = ath79_gpio_base;
104 unsigned long flags;
105
106 spin_lock_irqsave(&ath79_gpio_lock, flags);
107
108 __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) | mask,
109 base + AR71XX_GPIO_REG_FUNC);
110 /* flush write */
111 __raw_readl(base + AR71XX_GPIO_REG_FUNC);
112
113 spin_unlock_irqrestore(&ath79_gpio_lock, flags);
114}
115
116void ath79_gpio_function_disable(u32 mask)
117{
118 void __iomem *base = ath79_gpio_base;
119 unsigned long flags;
120
121 spin_lock_irqsave(&ath79_gpio_lock, flags);
122
123 __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~mask,
124 base + AR71XX_GPIO_REG_FUNC);
125 /* flush write */
126 __raw_readl(base + AR71XX_GPIO_REG_FUNC);
127
128 spin_unlock_irqrestore(&ath79_gpio_lock, flags);
129}
130
131void ath79_gpio_function_setup(u32 set, u32 clear)
132{
133 void __iomem *base = ath79_gpio_base;
134 unsigned long flags;
135
136 spin_lock_irqsave(&ath79_gpio_lock, flags);
137
138 __raw_writel((__raw_readl(base + AR71XX_GPIO_REG_FUNC) & ~clear) | set,
139 base + AR71XX_GPIO_REG_FUNC);
140 /* flush write */
141 __raw_readl(base + AR71XX_GPIO_REG_FUNC);
142
143 spin_unlock_irqrestore(&ath79_gpio_lock, flags);
144}
145
146void __init ath79_gpio_init(void)
147{
148 int err;
149
150 if (soc_is_ar71xx())
151 ath79_gpio_count = AR71XX_GPIO_COUNT;
152 else if (soc_is_ar724x())
153 ath79_gpio_count = AR724X_GPIO_COUNT;
154 else if (soc_is_ar913x())
155 ath79_gpio_count = AR913X_GPIO_COUNT;
156 else
157 BUG();
158
159 ath79_gpio_base = ioremap_nocache(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE);
160 ath79_gpio_chip.ngpio = ath79_gpio_count;
161
162 err = gpiochip_add(&ath79_gpio_chip);
163 if (err)
164 panic("cannot add AR71xx GPIO chip, error=%d", err);
165}
166
167int gpio_get_value(unsigned gpio)
168{
169 if (gpio < ath79_gpio_count)
170 return __ath79_gpio_get_value(gpio);
171
172 return __gpio_get_value(gpio);
173}
174EXPORT_SYMBOL(gpio_get_value);
175
176void gpio_set_value(unsigned gpio, int value)
177{
178 if (gpio < ath79_gpio_count)
179 __ath79_gpio_set_value(gpio, value);
180 else
181 __gpio_set_value(gpio, value);
182}
183EXPORT_SYMBOL(gpio_set_value);
184
185int gpio_to_irq(unsigned gpio)
186{
187 /* FIXME */
188 return -EINVAL;
189}
190EXPORT_SYMBOL(gpio_to_irq);
191
192int irq_to_gpio(unsigned irq)
193{
194 /* FIXME */
195 return -EINVAL;
196}
197EXPORT_SYMBOL(irq_to_gpio);
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/mach-ap81.c b/arch/mips/ath79/mach-ap81.c
new file mode 100644
index 000000000000..eee4c121deb4
--- /dev/null
+++ b/arch/mips/ath79/mach-ap81.c
@@ -0,0 +1,98 @@
1/*
2 * Atheros AP81 board support
3 *
4 * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2009 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 "machtypes.h"
13#include "dev-ar913x-wmac.h"
14#include "dev-gpio-buttons.h"
15#include "dev-leds-gpio.h"
16#include "dev-spi.h"
17
18#define AP81_GPIO_LED_STATUS 1
19#define AP81_GPIO_LED_AOSS 3
20#define AP81_GPIO_LED_WLAN 6
21#define AP81_GPIO_LED_POWER 14
22
23#define AP81_GPIO_BTN_SW4 12
24#define AP81_GPIO_BTN_SW1 21
25
26#define AP81_KEYS_POLL_INTERVAL 20 /* msecs */
27#define AP81_KEYS_DEBOUNCE_INTERVAL (3 * AP81_KEYS_POLL_INTERVAL)
28
29#define AP81_CAL_DATA_ADDR 0x1fff1000
30
31static struct gpio_led ap81_leds_gpio[] __initdata = {
32 {
33 .name = "ap81:green:status",
34 .gpio = AP81_GPIO_LED_STATUS,
35 .active_low = 1,
36 }, {
37 .name = "ap81:amber:aoss",
38 .gpio = AP81_GPIO_LED_AOSS,
39 .active_low = 1,
40 }, {
41 .name = "ap81:green:wlan",
42 .gpio = AP81_GPIO_LED_WLAN,
43 .active_low = 1,
44 }, {
45 .name = "ap81:green:power",
46 .gpio = AP81_GPIO_LED_POWER,
47 .active_low = 1,
48 }
49};
50
51static struct gpio_keys_button ap81_gpio_keys[] __initdata = {
52 {
53 .desc = "sw1",
54 .type = EV_KEY,
55 .code = BTN_0,
56 .debounce_interval = AP81_KEYS_DEBOUNCE_INTERVAL,
57 .gpio = AP81_GPIO_BTN_SW1,
58 .active_low = 1,
59 } , {
60 .desc = "sw4",
61 .type = EV_KEY,
62 .code = BTN_1,
63 .debounce_interval = AP81_KEYS_DEBOUNCE_INTERVAL,
64 .gpio = AP81_GPIO_BTN_SW4,
65 .active_low = 1,
66 }
67};
68
69static struct spi_board_info ap81_spi_info[] = {
70 {
71 .bus_num = 0,
72 .chip_select = 0,
73 .max_speed_hz = 25000000,
74 .modalias = "m25p64",
75 }
76};
77
78static struct ath79_spi_platform_data ap81_spi_data = {
79 .bus_num = 0,
80 .num_chipselect = 1,
81};
82
83static void __init ap81_setup(void)
84{
85 u8 *cal_data = (u8 *) KSEG1ADDR(AP81_CAL_DATA_ADDR);
86
87 ath79_register_leds_gpio(-1, ARRAY_SIZE(ap81_leds_gpio),
88 ap81_leds_gpio);
89 ath79_register_gpio_keys_polled(-1, AP81_KEYS_POLL_INTERVAL,
90 ARRAY_SIZE(ap81_gpio_keys),
91 ap81_gpio_keys);
92 ath79_register_spi(&ap81_spi_data, ap81_spi_info,
93 ARRAY_SIZE(ap81_spi_info));
94 ath79_register_ar913x_wmac(cal_data);
95}
96
97MIPS_MACHINE(ATH79_MACH_AP81, "AP81", "Atheros AP81 reference board",
98 ap81_setup);
diff --git a/arch/mips/ath79/mach-pb44.c b/arch/mips/ath79/mach-pb44.c
new file mode 100644
index 000000000000..ec7b7a135d53
--- /dev/null
+++ b/arch/mips/ath79/mach-pb44.c
@@ -0,0 +1,118 @@
1/*
2 * Atheros PB44 reference board support
3 *
4 * Copyright (C) 2009-2010 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/init.h>
12#include <linux/platform_device.h>
13#include <linux/i2c.h>
14#include <linux/i2c-gpio.h>
15#include <linux/i2c/pcf857x.h>
16
17#include "machtypes.h"
18#include "dev-gpio-buttons.h"
19#include "dev-leds-gpio.h"
20#include "dev-spi.h"
21
22#define PB44_GPIO_I2C_SCL 0
23#define PB44_GPIO_I2C_SDA 1
24
25#define PB44_GPIO_EXP_BASE 16
26#define PB44_GPIO_SW_RESET (PB44_GPIO_EXP_BASE + 6)
27#define PB44_GPIO_SW_JUMP (PB44_GPIO_EXP_BASE + 8)
28#define PB44_GPIO_LED_JUMP1 (PB44_GPIO_EXP_BASE + 9)
29#define PB44_GPIO_LED_JUMP2 (PB44_GPIO_EXP_BASE + 10)
30
31#define PB44_KEYS_POLL_INTERVAL 20 /* msecs */
32#define PB44_KEYS_DEBOUNCE_INTERVAL (3 * PB44_KEYS_POLL_INTERVAL)
33
34static struct i2c_gpio_platform_data pb44_i2c_gpio_data = {
35 .sda_pin = PB44_GPIO_I2C_SDA,
36 .scl_pin = PB44_GPIO_I2C_SCL,
37};
38
39static struct platform_device pb44_i2c_gpio_device = {
40 .name = "i2c-gpio",
41 .id = 0,
42 .dev = {
43 .platform_data = &pb44_i2c_gpio_data,
44 }
45};
46
47static struct pcf857x_platform_data pb44_pcf857x_data = {
48 .gpio_base = PB44_GPIO_EXP_BASE,
49};
50
51static struct i2c_board_info pb44_i2c_board_info[] __initdata = {
52 {
53 I2C_BOARD_INFO("pcf8575", 0x20),
54 .platform_data = &pb44_pcf857x_data,
55 },
56};
57
58static struct gpio_led pb44_leds_gpio[] __initdata = {
59 {
60 .name = "pb44:amber:jump1",
61 .gpio = PB44_GPIO_LED_JUMP1,
62 .active_low = 1,
63 }, {
64 .name = "pb44:green:jump2",
65 .gpio = PB44_GPIO_LED_JUMP2,
66 .active_low = 1,
67 },
68};
69
70static struct gpio_keys_button pb44_gpio_keys[] __initdata = {
71 {
72 .desc = "soft_reset",
73 .type = EV_KEY,
74 .code = KEY_RESTART,
75 .debounce_interval = PB44_KEYS_DEBOUNCE_INTERVAL,
76 .gpio = PB44_GPIO_SW_RESET,
77 .active_low = 1,
78 } , {
79 .desc = "jumpstart",
80 .type = EV_KEY,
81 .code = KEY_WPS_BUTTON,
82 .debounce_interval = PB44_KEYS_DEBOUNCE_INTERVAL,
83 .gpio = PB44_GPIO_SW_JUMP,
84 .active_low = 1,
85 }
86};
87
88static struct spi_board_info pb44_spi_info[] = {
89 {
90 .bus_num = 0,
91 .chip_select = 0,
92 .max_speed_hz = 25000000,
93 .modalias = "m25p64",
94 },
95};
96
97static struct ath79_spi_platform_data pb44_spi_data = {
98 .bus_num = 0,
99 .num_chipselect = 1,
100};
101
102static void __init pb44_init(void)
103{
104 i2c_register_board_info(0, pb44_i2c_board_info,
105 ARRAY_SIZE(pb44_i2c_board_info));
106 platform_device_register(&pb44_i2c_gpio_device);
107
108 ath79_register_leds_gpio(-1, ARRAY_SIZE(pb44_leds_gpio),
109 pb44_leds_gpio);
110 ath79_register_gpio_keys_polled(-1, PB44_KEYS_POLL_INTERVAL,
111 ARRAY_SIZE(pb44_gpio_keys),
112 pb44_gpio_keys);
113 ath79_register_spi(&pb44_spi_data, pb44_spi_info,
114 ARRAY_SIZE(pb44_spi_info));
115}
116
117MIPS_MACHINE(ATH79_MACH_PB44, "PB44", "Atheros PB44 reference board",
118 pb44_init);
diff --git a/arch/mips/ath79/machtypes.h b/arch/mips/ath79/machtypes.h
new file mode 100644
index 000000000000..3940fe470b2d
--- /dev/null
+++ b/arch/mips/ath79/machtypes.h
@@ -0,0 +1,23 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X machine type definitions
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_MACHTYPE_H
13#define _ATH79_MACHTYPE_H
14
15#include <asm/mips_machine.h>
16
17enum ath79_mach_type {
18 ATH79_MACH_GENERIC = 0,
19 ATH79_MACH_AP81, /* Atheros AP81 reference board */
20 ATH79_MACH_PB44, /* Atheros PB44 reference board */
21};
22
23#endif /* _ATH79_MACHTYPE_H */
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..159b42f106b0
--- /dev/null
+++ b/arch/mips/ath79/setup.c
@@ -0,0 +1,206 @@
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#include <asm/mips_machine.h>
24
25#include <asm/mach-ath79/ath79.h>
26#include <asm/mach-ath79/ar71xx_regs.h>
27#include "common.h"
28#include "dev-common.h"
29#include "machtypes.h"
30
31#define ATH79_SYS_TYPE_LEN 64
32
33#define AR71XX_BASE_FREQ 40000000
34#define AR724X_BASE_FREQ 5000000
35#define AR913X_BASE_FREQ 5000000
36
37static char ath79_sys_type[ATH79_SYS_TYPE_LEN];
38
39static void ath79_restart(char *command)
40{
41 ath79_device_reset_set(AR71XX_RESET_FULL_CHIP);
42 for (;;)
43 if (cpu_wait)
44 cpu_wait();
45}
46
47static void ath79_halt(void)
48{
49 while (1)
50 cpu_wait();
51}
52
53static void __init ath79_detect_mem_size(void)
54{
55 unsigned long size;
56
57 for (size = ATH79_MEM_SIZE_MIN; size < ATH79_MEM_SIZE_MAX;
58 size <<= 1) {
59 if (!memcmp(ath79_detect_mem_size,
60 ath79_detect_mem_size + size, 1024))
61 break;
62 }
63
64 add_memory_region(0, size, BOOT_MEM_RAM);
65}
66
67static void __init ath79_detect_sys_type(void)
68{
69 char *chip = "????";
70 u32 id;
71 u32 major;
72 u32 minor;
73 u32 rev = 0;
74
75 id = ath79_reset_rr(AR71XX_RESET_REG_REV_ID);
76 major = id & REV_ID_MAJOR_MASK;
77
78 switch (major) {
79 case REV_ID_MAJOR_AR71XX:
80 minor = id & AR71XX_REV_ID_MINOR_MASK;
81 rev = id >> AR71XX_REV_ID_REVISION_SHIFT;
82 rev &= AR71XX_REV_ID_REVISION_MASK;
83 switch (minor) {
84 case AR71XX_REV_ID_MINOR_AR7130:
85 ath79_soc = ATH79_SOC_AR7130;
86 chip = "7130";
87 break;
88
89 case AR71XX_REV_ID_MINOR_AR7141:
90 ath79_soc = ATH79_SOC_AR7141;
91 chip = "7141";
92 break;
93
94 case AR71XX_REV_ID_MINOR_AR7161:
95 ath79_soc = ATH79_SOC_AR7161;
96 chip = "7161";
97 break;
98 }
99 break;
100
101 case REV_ID_MAJOR_AR7240:
102 ath79_soc = ATH79_SOC_AR7240;
103 chip = "7240";
104 rev = (id & AR724X_REV_ID_REVISION_MASK);
105 break;
106
107 case REV_ID_MAJOR_AR7241:
108 ath79_soc = ATH79_SOC_AR7241;
109 chip = "7241";
110 rev = (id & AR724X_REV_ID_REVISION_MASK);
111 break;
112
113 case REV_ID_MAJOR_AR7242:
114 ath79_soc = ATH79_SOC_AR7242;
115 chip = "7242";
116 rev = (id & AR724X_REV_ID_REVISION_MASK);
117 break;
118
119 case REV_ID_MAJOR_AR913X:
120 minor = id & AR913X_REV_ID_MINOR_MASK;
121 rev = id >> AR913X_REV_ID_REVISION_SHIFT;
122 rev &= AR913X_REV_ID_REVISION_MASK;
123 switch (minor) {
124 case AR913X_REV_ID_MINOR_AR9130:
125 ath79_soc = ATH79_SOC_AR9130;
126 chip = "9130";
127 break;
128
129 case AR913X_REV_ID_MINOR_AR9132:
130 ath79_soc = ATH79_SOC_AR9132;
131 chip = "9132";
132 break;
133 }
134 break;
135
136 default:
137 panic("ath79: unknown SoC, id:0x%08x\n", id);
138 }
139
140 sprintf(ath79_sys_type, "Atheros AR%s rev %u", chip, rev);
141 pr_info("SoC: %s\n", ath79_sys_type);
142}
143
144const char *get_system_type(void)
145{
146 return ath79_sys_type;
147}
148
149unsigned int __cpuinit get_c0_compare_int(void)
150{
151 return CP0_LEGACY_COMPARE_IRQ;
152}
153
154void __init plat_mem_setup(void)
155{
156 set_io_port_base(KSEG1);
157
158 ath79_reset_base = ioremap_nocache(AR71XX_RESET_BASE,
159 AR71XX_RESET_SIZE);
160 ath79_pll_base = ioremap_nocache(AR71XX_PLL_BASE,
161 AR71XX_PLL_SIZE);
162 ath79_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE,
163 AR71XX_DDR_CTRL_SIZE);
164
165 ath79_detect_sys_type();
166 ath79_detect_mem_size();
167 ath79_clocks_init();
168
169 _machine_restart = ath79_restart;
170 _machine_halt = ath79_halt;
171 pm_power_off = ath79_halt;
172}
173
174void __init plat_time_init(void)
175{
176 struct clk *clk;
177
178 clk = clk_get(NULL, "cpu");
179 if (IS_ERR(clk))
180 panic("unable to get CPU clock, err=%ld", PTR_ERR(clk));
181
182 mips_hpt_frequency = clk_get_rate(clk) / 2;
183}
184
185static int __init ath79_setup(void)
186{
187 ath79_gpio_init();
188 ath79_register_uart();
189 ath79_register_wdt();
190
191 mips_machine_setup();
192
193 return 0;
194}
195
196arch_initcall(ath79_setup);
197
198static void __init ath79_generic_init(void)
199{
200 /* Nothing to do */
201}
202
203MIPS_MACHINE(ATH79_MACH_GENERIC,
204 "Generic",
205 "Generic AR71XX/AR724X/AR913X based board",
206 ath79_generic_init);