aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-18 17:28:48 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-18 17:28:48 -0500
commit5d7e8af3c5727626b9e7f909c778b9ac9b4a1809 (patch)
tree13d51e31ee070113538a6d26d9a52503ba4a3cd0
parentaa891f6b3f440402c6879ad1ecf332d318137422 (diff)
parent79aa18d557bef02171da42ee928c23509e6ef4f7 (diff)
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://git.linux-mips.org/pub/scm/upstream-linus: (26 commits) MIPS: Malta: enable Cirrus FB console MIPS: add CONFIG_VIRTUALIZATION for virtio support MIPS: Implement __read_mostly MIPS: ath79: add common WMAC device for AR913X based boards MIPS: ath79: Add initial support for the Atheros AP81 reference board MIPS: ath79: add common SPI controller device SPI: Add SPI controller driver for the Atheros AR71XX/AR724X/AR913X SoCs MIPS: ath79: add common GPIO buttons device MIPS: ath79: add common watchdog device MIPS: ath79: add common GPIO LEDs device MIPS: ath79: add initial support for the Atheros PB44 reference board MIPS: ath79: utilize the MIPS multi-machine support MIPS: ath79: add GPIOLIB support MIPS: Add initial support for the Atheros AR71XX/AR724X/AR931X SoCs MIPS: jump label: Add MIPS support. MIPS: Use WARN() in uasm for better diagnostics. MIPS: Optimize TLB handlers for Octeon CPUs MIPS: Add LDX and LWX instructions to uasm. MIPS: Use BBIT instructions in TLB handlers MIPS: Declare uasm bbit0 and bbit1 functions. ...
-rw-r--r--arch/mips/Kbuild.platforms1
-rw-r--r--arch/mips/Kconfig37
-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
-rw-r--r--arch/mips/configs/malta_defconfig3
-rw-r--r--arch/mips/include/asm/cache.h2
-rw-r--r--arch/mips/include/asm/cpu-info.h1
-rw-r--r--arch/mips/include/asm/inst.h14
-rw-r--r--arch/mips/include/asm/jump_label.h48
-rw-r--r--arch/mips/include/asm/mach-ath79/ar71xx_regs.h233
-rw-r--r--arch/mips/include/asm/mach-ath79/ath79.h96
-rw-r--r--arch/mips/include/asm/mach-ath79/ath79_spi_platform.h23
-rw-r--r--arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h56
-rw-r--r--arch/mips/include/asm/mach-ath79/gpio.h26
-rw-r--r--arch/mips/include/asm/mach-ath79/irq.h36
-rw-r--r--arch/mips/include/asm/mach-ath79/kernel-entry-init.h32
-rw-r--r--arch/mips/include/asm/mach-ath79/war.h25
-rw-r--r--arch/mips/include/asm/mips_machine.h54
-rw-r--r--arch/mips/include/asm/mmu_context.h8
-rw-r--r--arch/mips/include/asm/uasm.h7
-rw-r--r--arch/mips/kernel/Makefile3
-rw-r--r--arch/mips/kernel/cpu-probe.c2
-rw-r--r--arch/mips/kernel/jump_label.c54
-rw-r--r--arch/mips/kernel/mips_machine.c86
-rw-r--r--arch/mips/kernel/module.c5
-rw-r--r--arch/mips/kernel/proc.c9
-rw-r--r--arch/mips/kernel/setup.c2
-rw-r--r--arch/mips/kernel/traps.c2
-rw-r--r--arch/mips/kernel/vmlinux.lds.S7
-rw-r--r--arch/mips/mm/tlbex.c590
-rw-r--r--arch/mips/mm/uasm.c56
-rw-r--r--arch/mips/sibyte/common/sb_tbprof.c3
-rw-r--r--arch/mips/txx9/generic/pci.c7
-rw-r--r--drivers/spi/Kconfig8
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/ath79_spi.c292
58 files changed, 3408 insertions, 129 deletions
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index 78439b8a83c4..7ff9b5492041 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -2,6 +2,7 @@
2 2
3platforms += alchemy 3platforms += alchemy
4platforms += ar7 4platforms += ar7
5platforms += ath79
5platforms += bcm47xx 6platforms += bcm47xx
6platforms += bcm63xx 7platforms += bcm63xx
7platforms += cavium-octeon 8platforms += cavium-octeon
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index f489ec30e071..548e6cc3bc28 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -21,6 +21,7 @@ config MIPS
21 select HAVE_DMA_API_DEBUG 21 select HAVE_DMA_API_DEBUG
22 select HAVE_GENERIC_HARDIRQS 22 select HAVE_GENERIC_HARDIRQS
23 select GENERIC_IRQ_PROBE 23 select GENERIC_IRQ_PROBE
24 select HAVE_ARCH_JUMP_LABEL
24 25
25menu "Machine selection" 26menu "Machine selection"
26 27
@@ -65,6 +66,22 @@ config AR7
65 Support for the Texas Instruments AR7 System-on-a-Chip 66 Support for the Texas Instruments AR7 System-on-a-Chip
66 family: TNETD7100, 7200 and 7300. 67 family: TNETD7100, 7200 and 7300.
67 68
69config ATH79
70 bool "Atheros AR71XX/AR724X/AR913X based boards"
71 select ARCH_REQUIRE_GPIOLIB
72 select BOOT_RAW
73 select CEVT_R4K
74 select CSRC_R4K
75 select DMA_NONCOHERENT
76 select IRQ_CPU
77 select MIPS_MACHINE
78 select SYS_HAS_CPU_MIPS32_R2
79 select SYS_HAS_EARLY_PRINTK
80 select SYS_SUPPORTS_32BIT_KERNEL
81 select SYS_SUPPORTS_BIG_ENDIAN
82 help
83 Support for the Atheros AR71XX/AR724X/AR913X SoCs.
84
68config BCM47XX 85config BCM47XX
69 bool "Broadcom BCM47XX based boards" 86 bool "Broadcom BCM47XX based boards"
70 select CEVT_R4K 87 select CEVT_R4K
@@ -717,6 +734,7 @@ config CAVIUM_OCTEON_REFERENCE_BOARD
717endchoice 734endchoice
718 735
719source "arch/mips/alchemy/Kconfig" 736source "arch/mips/alchemy/Kconfig"
737source "arch/mips/ath79/Kconfig"
720source "arch/mips/bcm63xx/Kconfig" 738source "arch/mips/bcm63xx/Kconfig"
721source "arch/mips/jazz/Kconfig" 739source "arch/mips/jazz/Kconfig"
722source "arch/mips/jz4740/Kconfig" 740source "arch/mips/jz4740/Kconfig"
@@ -883,6 +901,9 @@ config MIPS_DISABLE_OBSOLETE_IDE
883config SYNC_R4K 901config SYNC_R4K
884 bool 902 bool
885 903
904config MIPS_MACHINE
905 def_bool n
906
886config NO_IOPORT 907config NO_IOPORT
887 def_bool n 908 def_bool n
888 909
@@ -2400,4 +2421,20 @@ source "security/Kconfig"
2400 2421
2401source "crypto/Kconfig" 2422source "crypto/Kconfig"
2402 2423
2424menuconfig VIRTUALIZATION
2425 bool "Virtualization"
2426 default n
2427 ---help---
2428 Say Y here to get to see options for using your Linux host to run other
2429 operating systems inside virtual machines (guests).
2430 This option alone does not add any kernel code.
2431
2432 If you say N, all options in this submenu will be skipped and disabled.
2433
2434if VIRTUALIZATION
2435
2436source drivers/virtio/Kconfig
2437
2438endif # VIRTUALIZATION
2439
2403source "lib/Kconfig" 2440source "lib/Kconfig"
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);
diff --git a/arch/mips/configs/malta_defconfig b/arch/mips/configs/malta_defconfig
index b455d0f36486..9d03b68aece8 100644
--- a/arch/mips/configs/malta_defconfig
+++ b/arch/mips/configs/malta_defconfig
@@ -369,7 +369,10 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
369CONFIG_SERIAL_8250=y 369CONFIG_SERIAL_8250=y
370CONFIG_SERIAL_8250_CONSOLE=y 370CONFIG_SERIAL_8250_CONSOLE=y
371# CONFIG_HWMON is not set 371# CONFIG_HWMON is not set
372CONFIG_FB=y
373CONFIG_FB_CIRRUS=y
372# CONFIG_VGA_CONSOLE is not set 374# CONFIG_VGA_CONSOLE is not set
375CONFIG_FRAMEBUFFER_CONSOLE=y
373CONFIG_HID=m 376CONFIG_HID=m
374CONFIG_LEDS_CLASS=m 377CONFIG_LEDS_CLASS=m
375CONFIG_LEDS_TRIGGER_TIMER=m 378CONFIG_LEDS_TRIGGER_TIMER=m
diff --git a/arch/mips/include/asm/cache.h b/arch/mips/include/asm/cache.h
index 37f175c42bb5..650ac9ba734c 100644
--- a/arch/mips/include/asm/cache.h
+++ b/arch/mips/include/asm/cache.h
@@ -17,4 +17,6 @@
17#define SMP_CACHE_SHIFT L1_CACHE_SHIFT 17#define SMP_CACHE_SHIFT L1_CACHE_SHIFT
18#define SMP_CACHE_BYTES L1_CACHE_BYTES 18#define SMP_CACHE_BYTES L1_CACHE_BYTES
19 19
20#define __read_mostly __attribute__((__section__(".data.read_mostly")))
21
20#endif /* _ASM_CACHE_H */ 22#endif /* _ASM_CACHE_H */
diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h
index b39def3f6e03..c454550eb0c0 100644
--- a/arch/mips/include/asm/cpu-info.h
+++ b/arch/mips/include/asm/cpu-info.h
@@ -78,6 +78,7 @@ struct cpuinfo_mips {
78 unsigned int watch_reg_use_cnt; /* Usable by ptrace */ 78 unsigned int watch_reg_use_cnt; /* Usable by ptrace */
79#define NUM_WATCH_REGS 4 79#define NUM_WATCH_REGS 4
80 u16 watch_reg_masks[NUM_WATCH_REGS]; 80 u16 watch_reg_masks[NUM_WATCH_REGS];
81 unsigned int kscratch_mask; /* Usable KScratch mask. */
81} __attribute__((aligned(SMP_CACHE_BYTES))); 82} __attribute__((aligned(SMP_CACHE_BYTES)));
82 83
83extern struct cpuinfo_mips cpu_data[]; 84extern struct cpuinfo_mips cpu_data[];
diff --git a/arch/mips/include/asm/inst.h b/arch/mips/include/asm/inst.h
index 444ff71aa0e8..7ebfc392e58d 100644
--- a/arch/mips/include/asm/inst.h
+++ b/arch/mips/include/asm/inst.h
@@ -72,6 +72,7 @@ enum spec2_op {
72enum spec3_op { 72enum spec3_op {
73 ext_op, dextm_op, dextu_op, dext_op, 73 ext_op, dextm_op, dextu_op, dext_op,
74 ins_op, dinsm_op, dinsu_op, dins_op, 74 ins_op, dinsm_op, dinsu_op, dins_op,
75 lx_op = 0x0a,
75 bshfl_op = 0x20, 76 bshfl_op = 0x20,
76 dbshfl_op = 0x24, 77 dbshfl_op = 0x24,
77 rdhwr_op = 0x3b 78 rdhwr_op = 0x3b
@@ -179,6 +180,19 @@ enum mad_func {
179}; 180};
180 181
181/* 182/*
183 * func field for special3 lx opcodes (Cavium Octeon).
184 */
185enum lx_func {
186 lwx_op = 0x00,
187 lhx_op = 0x04,
188 lbux_op = 0x06,
189 ldx_op = 0x08,
190 lwux_op = 0x10,
191 lhux_op = 0x14,
192 lbx_op = 0x16,
193};
194
195/*
182 * Damn ... bitfields depend from byteorder :-( 196 * Damn ... bitfields depend from byteorder :-(
183 */ 197 */
184#ifdef __MIPSEB__ 198#ifdef __MIPSEB__
diff --git a/arch/mips/include/asm/jump_label.h b/arch/mips/include/asm/jump_label.h
new file mode 100644
index 000000000000..7622ccf75076
--- /dev/null
+++ b/arch/mips/include/asm/jump_label.h
@@ -0,0 +1,48 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (c) 2010 Cavium Networks, Inc.
7 */
8#ifndef _ASM_MIPS_JUMP_LABEL_H
9#define _ASM_MIPS_JUMP_LABEL_H
10
11#include <linux/types.h>
12
13#ifdef __KERNEL__
14
15#define JUMP_LABEL_NOP_SIZE 4
16
17#ifdef CONFIG_64BIT
18#define WORD_INSN ".dword"
19#else
20#define WORD_INSN ".word"
21#endif
22
23#define JUMP_LABEL(key, label) \
24 do { \
25 asm goto("1:\tnop\n\t" \
26 "nop\n\t" \
27 ".pushsection __jump_table, \"a\"\n\t" \
28 WORD_INSN " 1b, %l[" #label "], %0\n\t" \
29 ".popsection\n\t" \
30 : : "i" (key) : : label); \
31 } while (0)
32
33
34#endif /* __KERNEL__ */
35
36#ifdef CONFIG_64BIT
37typedef u64 jump_label_t;
38#else
39typedef u32 jump_label_t;
40#endif
41
42struct jump_entry {
43 jump_label_t code;
44 jump_label_t target;
45 jump_label_t key;
46};
47
48#endif /* _ASM_MIPS_JUMP_LABEL_H */
diff --git a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
new file mode 100644
index 000000000000..cda1c8070b27
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
@@ -0,0 +1,233 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X SoC register definitions
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#ifndef __ASM_MACH_AR71XX_REGS_H
15#define __ASM_MACH_AR71XX_REGS_H
16
17#include <linux/types.h>
18#include <linux/init.h>
19#include <linux/io.h>
20#include <linux/bitops.h>
21
22#define AR71XX_APB_BASE 0x18000000
23#define AR71XX_SPI_BASE 0x1f000000
24#define AR71XX_SPI_SIZE 0x01000000
25
26#define AR71XX_DDR_CTRL_BASE (AR71XX_APB_BASE + 0x00000000)
27#define AR71XX_DDR_CTRL_SIZE 0x100
28#define AR71XX_UART_BASE (AR71XX_APB_BASE + 0x00020000)
29#define AR71XX_UART_SIZE 0x100
30#define AR71XX_GPIO_BASE (AR71XX_APB_BASE + 0x00040000)
31#define AR71XX_GPIO_SIZE 0x100
32#define AR71XX_PLL_BASE (AR71XX_APB_BASE + 0x00050000)
33#define AR71XX_PLL_SIZE 0x100
34#define AR71XX_RESET_BASE (AR71XX_APB_BASE + 0x00060000)
35#define AR71XX_RESET_SIZE 0x100
36
37#define AR913X_WMAC_BASE (AR71XX_APB_BASE + 0x000C0000)
38#define AR913X_WMAC_SIZE 0x30000
39
40/*
41 * DDR_CTRL block
42 */
43#define AR71XX_DDR_REG_PCI_WIN0 0x7c
44#define AR71XX_DDR_REG_PCI_WIN1 0x80
45#define AR71XX_DDR_REG_PCI_WIN2 0x84
46#define AR71XX_DDR_REG_PCI_WIN3 0x88
47#define AR71XX_DDR_REG_PCI_WIN4 0x8c
48#define AR71XX_DDR_REG_PCI_WIN5 0x90
49#define AR71XX_DDR_REG_PCI_WIN6 0x94
50#define AR71XX_DDR_REG_PCI_WIN7 0x98
51#define AR71XX_DDR_REG_FLUSH_GE0 0x9c
52#define AR71XX_DDR_REG_FLUSH_GE1 0xa0
53#define AR71XX_DDR_REG_FLUSH_USB 0xa4
54#define AR71XX_DDR_REG_FLUSH_PCI 0xa8
55
56#define AR724X_DDR_REG_FLUSH_GE0 0x7c
57#define AR724X_DDR_REG_FLUSH_GE1 0x80
58#define AR724X_DDR_REG_FLUSH_USB 0x84
59#define AR724X_DDR_REG_FLUSH_PCIE 0x88
60
61#define AR913X_DDR_REG_FLUSH_GE0 0x7c
62#define AR913X_DDR_REG_FLUSH_GE1 0x80
63#define AR913X_DDR_REG_FLUSH_USB 0x84
64#define AR913X_DDR_REG_FLUSH_WMAC 0x88
65
66/*
67 * PLL block
68 */
69#define AR71XX_PLL_REG_CPU_CONFIG 0x00
70#define AR71XX_PLL_REG_SEC_CONFIG 0x04
71#define AR71XX_PLL_REG_ETH0_INT_CLOCK 0x10
72#define AR71XX_PLL_REG_ETH1_INT_CLOCK 0x14
73
74#define AR71XX_PLL_DIV_SHIFT 3
75#define AR71XX_PLL_DIV_MASK 0x1f
76#define AR71XX_CPU_DIV_SHIFT 16
77#define AR71XX_CPU_DIV_MASK 0x3
78#define AR71XX_DDR_DIV_SHIFT 18
79#define AR71XX_DDR_DIV_MASK 0x3
80#define AR71XX_AHB_DIV_SHIFT 20
81#define AR71XX_AHB_DIV_MASK 0x7
82
83#define AR724X_PLL_REG_CPU_CONFIG 0x00
84#define AR724X_PLL_REG_PCIE_CONFIG 0x18
85
86#define AR724X_PLL_DIV_SHIFT 0
87#define AR724X_PLL_DIV_MASK 0x3ff
88#define AR724X_PLL_REF_DIV_SHIFT 10
89#define AR724X_PLL_REF_DIV_MASK 0xf
90#define AR724X_AHB_DIV_SHIFT 19
91#define AR724X_AHB_DIV_MASK 0x1
92#define AR724X_DDR_DIV_SHIFT 22
93#define AR724X_DDR_DIV_MASK 0x3
94
95#define AR913X_PLL_REG_CPU_CONFIG 0x00
96#define AR913X_PLL_REG_ETH_CONFIG 0x04
97#define AR913X_PLL_REG_ETH0_INT_CLOCK 0x14
98#define AR913X_PLL_REG_ETH1_INT_CLOCK 0x18
99
100#define AR913X_PLL_DIV_SHIFT 0
101#define AR913X_PLL_DIV_MASK 0x3ff
102#define AR913X_DDR_DIV_SHIFT 22
103#define AR913X_DDR_DIV_MASK 0x3
104#define AR913X_AHB_DIV_SHIFT 19
105#define AR913X_AHB_DIV_MASK 0x1
106
107/*
108 * RESET block
109 */
110#define AR71XX_RESET_REG_TIMER 0x00
111#define AR71XX_RESET_REG_TIMER_RELOAD 0x04
112#define AR71XX_RESET_REG_WDOG_CTRL 0x08
113#define AR71XX_RESET_REG_WDOG 0x0c
114#define AR71XX_RESET_REG_MISC_INT_STATUS 0x10
115#define AR71XX_RESET_REG_MISC_INT_ENABLE 0x14
116#define AR71XX_RESET_REG_PCI_INT_STATUS 0x18
117#define AR71XX_RESET_REG_PCI_INT_ENABLE 0x1c
118#define AR71XX_RESET_REG_GLOBAL_INT_STATUS 0x20
119#define AR71XX_RESET_REG_RESET_MODULE 0x24
120#define AR71XX_RESET_REG_PERFC_CTRL 0x2c
121#define AR71XX_RESET_REG_PERFC0 0x30
122#define AR71XX_RESET_REG_PERFC1 0x34
123#define AR71XX_RESET_REG_REV_ID 0x90
124
125#define AR913X_RESET_REG_GLOBAL_INT_STATUS 0x18
126#define AR913X_RESET_REG_RESET_MODULE 0x1c
127#define AR913X_RESET_REG_PERF_CTRL 0x20
128#define AR913X_RESET_REG_PERFC0 0x24
129#define AR913X_RESET_REG_PERFC1 0x28
130
131#define AR724X_RESET_REG_RESET_MODULE 0x1c
132
133#define MISC_INT_DMA BIT(7)
134#define MISC_INT_OHCI BIT(6)
135#define MISC_INT_PERFC BIT(5)
136#define MISC_INT_WDOG BIT(4)
137#define MISC_INT_UART BIT(3)
138#define MISC_INT_GPIO BIT(2)
139#define MISC_INT_ERROR BIT(1)
140#define MISC_INT_TIMER BIT(0)
141
142#define AR71XX_RESET_EXTERNAL BIT(28)
143#define AR71XX_RESET_FULL_CHIP BIT(24)
144#define AR71XX_RESET_CPU_NMI BIT(21)
145#define AR71XX_RESET_CPU_COLD BIT(20)
146#define AR71XX_RESET_DMA BIT(19)
147#define AR71XX_RESET_SLIC BIT(18)
148#define AR71XX_RESET_STEREO BIT(17)
149#define AR71XX_RESET_DDR BIT(16)
150#define AR71XX_RESET_GE1_MAC BIT(13)
151#define AR71XX_RESET_GE1_PHY BIT(12)
152#define AR71XX_RESET_USBSUS_OVERRIDE BIT(10)
153#define AR71XX_RESET_GE0_MAC BIT(9)
154#define AR71XX_RESET_GE0_PHY BIT(8)
155#define AR71XX_RESET_USB_OHCI_DLL BIT(6)
156#define AR71XX_RESET_USB_HOST BIT(5)
157#define AR71XX_RESET_USB_PHY BIT(4)
158#define AR71XX_RESET_PCI_BUS BIT(1)
159#define AR71XX_RESET_PCI_CORE BIT(0)
160
161#define AR724X_RESET_GE1_MDIO BIT(23)
162#define AR724X_RESET_GE0_MDIO BIT(22)
163#define AR724X_RESET_PCIE_PHY_SERIAL BIT(10)
164#define AR724X_RESET_PCIE_PHY BIT(7)
165#define AR724X_RESET_PCIE BIT(6)
166#define AR724X_RESET_OHCI_DLL BIT(3)
167
168#define AR913X_RESET_AMBA2WMAC BIT(22)
169
170#define REV_ID_MAJOR_MASK 0xfff0
171#define REV_ID_MAJOR_AR71XX 0x00a0
172#define REV_ID_MAJOR_AR913X 0x00b0
173#define REV_ID_MAJOR_AR7240 0x00c0
174#define REV_ID_MAJOR_AR7241 0x0100
175#define REV_ID_MAJOR_AR7242 0x1100
176
177#define AR71XX_REV_ID_MINOR_MASK 0x3
178#define AR71XX_REV_ID_MINOR_AR7130 0x0
179#define AR71XX_REV_ID_MINOR_AR7141 0x1
180#define AR71XX_REV_ID_MINOR_AR7161 0x2
181#define AR71XX_REV_ID_REVISION_MASK 0x3
182#define AR71XX_REV_ID_REVISION_SHIFT 2
183
184#define AR913X_REV_ID_MINOR_MASK 0x3
185#define AR913X_REV_ID_MINOR_AR9130 0x0
186#define AR913X_REV_ID_MINOR_AR9132 0x1
187#define AR913X_REV_ID_REVISION_MASK 0x3
188#define AR913X_REV_ID_REVISION_SHIFT 2
189
190#define AR724X_REV_ID_REVISION_MASK 0x3
191
192/*
193 * SPI block
194 */
195#define AR71XX_SPI_REG_FS 0x00 /* Function Select */
196#define AR71XX_SPI_REG_CTRL 0x04 /* SPI Control */
197#define AR71XX_SPI_REG_IOC 0x08 /* SPI I/O Control */
198#define AR71XX_SPI_REG_RDS 0x0c /* Read Data Shift */
199
200#define AR71XX_SPI_FS_GPIO BIT(0) /* Enable GPIO mode */
201
202#define AR71XX_SPI_CTRL_RD BIT(6) /* Remap Disable */
203#define AR71XX_SPI_CTRL_DIV_MASK 0x3f
204
205#define AR71XX_SPI_IOC_DO BIT(0) /* Data Out pin */
206#define AR71XX_SPI_IOC_CLK BIT(8) /* CLK pin */
207#define AR71XX_SPI_IOC_CS(n) BIT(16 + (n))
208#define AR71XX_SPI_IOC_CS0 AR71XX_SPI_IOC_CS(0)
209#define AR71XX_SPI_IOC_CS1 AR71XX_SPI_IOC_CS(1)
210#define AR71XX_SPI_IOC_CS2 AR71XX_SPI_IOC_CS(2)
211#define AR71XX_SPI_IOC_CS_ALL (AR71XX_SPI_IOC_CS0 | AR71XX_SPI_IOC_CS1 | \
212 AR71XX_SPI_IOC_CS2)
213
214/*
215 * GPIO block
216 */
217#define AR71XX_GPIO_REG_OE 0x00
218#define AR71XX_GPIO_REG_IN 0x04
219#define AR71XX_GPIO_REG_OUT 0x08
220#define AR71XX_GPIO_REG_SET 0x0c
221#define AR71XX_GPIO_REG_CLEAR 0x10
222#define AR71XX_GPIO_REG_INT_MODE 0x14
223#define AR71XX_GPIO_REG_INT_TYPE 0x18
224#define AR71XX_GPIO_REG_INT_POLARITY 0x1c
225#define AR71XX_GPIO_REG_INT_PENDING 0x20
226#define AR71XX_GPIO_REG_INT_ENABLE 0x24
227#define AR71XX_GPIO_REG_FUNC 0x28
228
229#define AR71XX_GPIO_COUNT 16
230#define AR724X_GPIO_COUNT 18
231#define AR913X_GPIO_COUNT 22
232
233#endif /* __ASM_MACH_AR71XX_REGS_H */
diff --git a/arch/mips/include/asm/mach-ath79/ath79.h b/arch/mips/include/asm/mach-ath79/ath79.h
new file mode 100644
index 000000000000..6a9f168506fe
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/ath79.h
@@ -0,0 +1,96 @@
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 __ASM_MACH_ATH79_H
15#define __ASM_MACH_ATH79_H
16
17#include <linux/types.h>
18#include <linux/io.h>
19
20enum ath79_soc_type {
21 ATH79_SOC_UNKNOWN,
22 ATH79_SOC_AR7130,
23 ATH79_SOC_AR7141,
24 ATH79_SOC_AR7161,
25 ATH79_SOC_AR7240,
26 ATH79_SOC_AR7241,
27 ATH79_SOC_AR7242,
28 ATH79_SOC_AR9130,
29 ATH79_SOC_AR9132
30};
31
32extern enum ath79_soc_type ath79_soc;
33
34static inline int soc_is_ar71xx(void)
35{
36 return (ath79_soc == ATH79_SOC_AR7130 ||
37 ath79_soc == ATH79_SOC_AR7141 ||
38 ath79_soc == ATH79_SOC_AR7161);
39}
40
41static inline int soc_is_ar724x(void)
42{
43 return (ath79_soc == ATH79_SOC_AR7240 ||
44 ath79_soc == ATH79_SOC_AR7241 ||
45 ath79_soc == ATH79_SOC_AR7242);
46}
47
48static inline int soc_is_ar7240(void)
49{
50 return (ath79_soc == ATH79_SOC_AR7240);
51}
52
53static inline int soc_is_ar7241(void)
54{
55 return (ath79_soc == ATH79_SOC_AR7241);
56}
57
58static inline int soc_is_ar7242(void)
59{
60 return (ath79_soc == ATH79_SOC_AR7242);
61}
62
63static inline int soc_is_ar913x(void)
64{
65 return (ath79_soc == ATH79_SOC_AR9130 ||
66 ath79_soc == ATH79_SOC_AR9132);
67}
68
69extern void __iomem *ath79_ddr_base;
70extern void __iomem *ath79_pll_base;
71extern void __iomem *ath79_reset_base;
72
73static inline void ath79_pll_wr(unsigned reg, u32 val)
74{
75 __raw_writel(val, ath79_pll_base + reg);
76}
77
78static inline u32 ath79_pll_rr(unsigned reg)
79{
80 return __raw_readl(ath79_pll_base + reg);
81}
82
83static inline void ath79_reset_wr(unsigned reg, u32 val)
84{
85 __raw_writel(val, ath79_reset_base + reg);
86}
87
88static inline u32 ath79_reset_rr(unsigned reg)
89{
90 return __raw_readl(ath79_reset_base + reg);
91}
92
93void ath79_device_reset_set(u32 mask);
94void ath79_device_reset_clear(u32 mask);
95
96#endif /* __ASM_MACH_ATH79_H */
diff --git a/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
new file mode 100644
index 000000000000..aa2283e602fc
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/ath79_spi_platform.h
@@ -0,0 +1,23 @@
1/*
2 * Platform data definition for Atheros AR71XX/AR724X/AR913X SPI controller
3 *
4 * Copyright (C) 2008-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#ifndef _ATH79_SPI_PLATFORM_H
12#define _ATH79_SPI_PLATFORM_H
13
14struct ath79_spi_platform_data {
15 unsigned bus_num;
16 unsigned num_chipselect;
17};
18
19struct ath79_spi_controller_data {
20 unsigned gpio;
21};
22
23#endif /* _ATH79_SPI_PLATFORM_H */
diff --git a/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h b/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
new file mode 100644
index 000000000000..4476fa03bf36
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
@@ -0,0 +1,56 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X specific CPU feature overrides
3 *
4 * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
5 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 *
7 * This file was derived from: include/asm-mips/cpu-features.h
8 * Copyright (C) 2003, 2004 Ralf Baechle
9 * Copyright (C) 2004 Maciej W. Rozycki
10 *
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License version 2 as published
13 * by the Free Software Foundation.
14 *
15 */
16#ifndef __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H
17#define __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H
18
19#define cpu_has_tlb 1
20#define cpu_has_4kex 1
21#define cpu_has_3k_cache 0
22#define cpu_has_4k_cache 1
23#define cpu_has_tx39_cache 0
24#define cpu_has_sb1_cache 0
25#define cpu_has_fpu 0
26#define cpu_has_32fpr 0
27#define cpu_has_counter 1
28#define cpu_has_watch 1
29#define cpu_has_divec 1
30
31#define cpu_has_prefetch 1
32#define cpu_has_ejtag 1
33#define cpu_has_llsc 1
34
35#define cpu_has_mips16 1
36#define cpu_has_mdmx 0
37#define cpu_has_mips3d 0
38#define cpu_has_smartmips 0
39
40#define cpu_has_mips32r1 1
41#define cpu_has_mips32r2 1
42#define cpu_has_mips64r1 0
43#define cpu_has_mips64r2 0
44
45#define cpu_has_dsp 0
46#define cpu_has_mipsmt 0
47
48#define cpu_has_64bits 0
49#define cpu_has_64bit_zero_reg 0
50#define cpu_has_64bit_gp_regs 0
51#define cpu_has_64bit_addresses 0
52
53#define cpu_dcache_line_size() 32
54#define cpu_icache_line_size() 32
55
56#endif /* __ASM_MACH_ATH79_CPU_FEATURE_OVERRIDES_H */
diff --git a/arch/mips/include/asm/mach-ath79/gpio.h b/arch/mips/include/asm/mach-ath79/gpio.h
new file mode 100644
index 000000000000..60dcb62785b4
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/gpio.h
@@ -0,0 +1,26 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X GPIO API 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
13#ifndef __ASM_MACH_ATH79_GPIO_H
14#define __ASM_MACH_ATH79_GPIO_H
15
16#define ARCH_NR_GPIOS 64
17#include <asm-generic/gpio.h>
18
19int gpio_to_irq(unsigned gpio);
20int irq_to_gpio(unsigned irq);
21int gpio_get_value(unsigned gpio);
22void gpio_set_value(unsigned gpio, int value);
23
24#define gpio_cansleep __gpio_cansleep
25
26#endif /* __ASM_MACH_ATH79_GPIO_H */
diff --git a/arch/mips/include/asm/mach-ath79/irq.h b/arch/mips/include/asm/mach-ath79/irq.h
new file mode 100644
index 000000000000..189bc6eb9c10
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/irq.h
@@ -0,0 +1,36 @@
1/*
2 * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
3 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published
7 * by the Free Software Foundation.
8 */
9#ifndef __ASM_MACH_ATH79_IRQ_H
10#define __ASM_MACH_ATH79_IRQ_H
11
12#define MIPS_CPU_IRQ_BASE 0
13#define NR_IRQS 16
14
15#define ATH79_MISC_IRQ_BASE 8
16#define ATH79_MISC_IRQ_COUNT 8
17
18#define ATH79_CPU_IRQ_IP2 (MIPS_CPU_IRQ_BASE + 2)
19#define ATH79_CPU_IRQ_USB (MIPS_CPU_IRQ_BASE + 3)
20#define ATH79_CPU_IRQ_GE0 (MIPS_CPU_IRQ_BASE + 4)
21#define ATH79_CPU_IRQ_GE1 (MIPS_CPU_IRQ_BASE + 5)
22#define ATH79_CPU_IRQ_MISC (MIPS_CPU_IRQ_BASE + 6)
23#define ATH79_CPU_IRQ_TIMER (MIPS_CPU_IRQ_BASE + 7)
24
25#define ATH79_MISC_IRQ_TIMER (ATH79_MISC_IRQ_BASE + 0)
26#define ATH79_MISC_IRQ_ERROR (ATH79_MISC_IRQ_BASE + 1)
27#define ATH79_MISC_IRQ_GPIO (ATH79_MISC_IRQ_BASE + 2)
28#define ATH79_MISC_IRQ_UART (ATH79_MISC_IRQ_BASE + 3)
29#define ATH79_MISC_IRQ_WDOG (ATH79_MISC_IRQ_BASE + 4)
30#define ATH79_MISC_IRQ_PERFC (ATH79_MISC_IRQ_BASE + 5)
31#define ATH79_MISC_IRQ_OHCI (ATH79_MISC_IRQ_BASE + 6)
32#define ATH79_MISC_IRQ_DMA (ATH79_MISC_IRQ_BASE + 7)
33
34#include_next <irq.h>
35
36#endif /* __ASM_MACH_ATH79_IRQ_H */
diff --git a/arch/mips/include/asm/mach-ath79/kernel-entry-init.h b/arch/mips/include/asm/mach-ath79/kernel-entry-init.h
new file mode 100644
index 000000000000..d8d046bccc8e
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/kernel-entry-init.h
@@ -0,0 +1,32 @@
1/*
2 * Atheros AR71XX/AR724X/AR913X specific kernel entry setup
3 *
4 * Copyright (C) 2009 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#ifndef __ASM_MACH_ATH79_KERNEL_ENTRY_H
12#define __ASM_MACH_ATH79_KERNEL_ENTRY_H
13
14 /*
15 * Some bootloaders set the 'Kseg0 coherency algorithm' to
16 * 'Cacheable, noncoherent, write-through, no write allocate'
17 * and this cause performance issues. Let's go and change it to
18 * 'Cacheable, noncoherent, write-back, write allocate'
19 */
20 .macro kernel_entry_setup
21 mfc0 t0, CP0_CONFIG
22 li t1, ~CONF_CM_CMASK
23 and t0, t1
24 ori t0, CONF_CM_CACHABLE_NONCOHERENT
25 mtc0 t0, CP0_CONFIG
26 nop
27 .endm
28
29 .macro smp_slave_setup
30 .endm
31
32#endif /* __ASM_MACH_ATH79_KERNEL_ENTRY_H */
diff --git a/arch/mips/include/asm/mach-ath79/war.h b/arch/mips/include/asm/mach-ath79/war.h
new file mode 100644
index 000000000000..323d9f1d8c45
--- /dev/null
+++ b/arch/mips/include/asm/mach-ath79/war.h
@@ -0,0 +1,25 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
7 */
8#ifndef __ASM_MACH_ATH79_WAR_H
9#define __ASM_MACH_ATH79_WAR_H
10
11#define R4600_V1_INDEX_ICACHEOP_WAR 0
12#define R4600_V1_HIT_CACHEOP_WAR 0
13#define R4600_V2_HIT_CACHEOP_WAR 0
14#define R5432_CP0_INTERRUPT_WAR 0
15#define BCM1250_M3_WAR 0
16#define SIBYTE_1956_WAR 0
17#define MIPS4K_ICACHE_REFILL_WAR 0
18#define MIPS_CACHE_SYNC_WAR 0
19#define TX49XX_ICACHE_INDEX_INV_WAR 0
20#define RM9000_CDEX_SMP_WAR 0
21#define ICACHE_REFILLS_WORKAROUND_WAR 0
22#define R10000_LLSC_WAR 0
23#define MIPS34K_MISSED_ITLB_WAR 0
24
25#endif /* __ASM_MACH_ATH79_WAR_H */
diff --git a/arch/mips/include/asm/mips_machine.h b/arch/mips/include/asm/mips_machine.h
new file mode 100644
index 000000000000..363bb352c7f7
--- /dev/null
+++ b/arch/mips/include/asm/mips_machine.h
@@ -0,0 +1,54 @@
1/*
2 * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published
6 * by the Free Software Foundation.
7 *
8 */
9
10#ifndef __ASM_MIPS_MACHINE_H
11#define __ASM_MIPS_MACHINE_H
12
13#include <linux/init.h>
14#include <linux/stddef.h>
15
16#include <asm/bootinfo.h>
17
18struct mips_machine {
19 unsigned long mach_type;
20 const char *mach_id;
21 const char *mach_name;
22 void (*mach_setup)(void);
23};
24
25#define MIPS_MACHINE(_type, _id, _name, _setup) \
26static const char machine_name_##_type[] __initconst \
27 __aligned(1) = _name; \
28static const char machine_id_##_type[] __initconst \
29 __aligned(1) = _id; \
30static struct mips_machine machine_##_type \
31 __used __section(.mips.machines.init) = \
32{ \
33 .mach_type = _type, \
34 .mach_id = machine_id_##_type, \
35 .mach_name = machine_name_##_type, \
36 .mach_setup = _setup, \
37};
38
39extern long __mips_machines_start;
40extern long __mips_machines_end;
41
42#ifdef CONFIG_MIPS_MACHINE
43int mips_machtype_setup(char *id) __init;
44void mips_machine_setup(void) __init;
45void mips_set_machine_name(const char *name) __init;
46char *mips_get_machine_name(void);
47#else
48static inline int mips_machtype_setup(char *id) { return 1; }
49static inline void mips_machine_setup(void) { }
50static inline void mips_set_machine_name(const char *name) { }
51static inline char *mips_get_machine_name(void) { return NULL; }
52#endif /* CONFIG_MIPS_MACHINE */
53
54#endif /* __ASM_MIPS_MACHINE_H */
diff --git a/arch/mips/include/asm/mmu_context.h b/arch/mips/include/asm/mmu_context.h
index d9592733a7ba..73c0d45798de 100644
--- a/arch/mips/include/asm/mmu_context.h
+++ b/arch/mips/include/asm/mmu_context.h
@@ -29,13 +29,7 @@
29#define TLBMISS_HANDLER_SETUP_PGD(pgd) \ 29#define TLBMISS_HANDLER_SETUP_PGD(pgd) \
30 tlbmiss_handler_setup_pgd((unsigned long)(pgd)) 30 tlbmiss_handler_setup_pgd((unsigned long)(pgd))
31 31
32static inline void tlbmiss_handler_setup_pgd(unsigned long pgd) 32extern void tlbmiss_handler_setup_pgd(unsigned long pgd);
33{
34 /* Check for swapper_pg_dir and convert to physical address. */
35 if ((pgd & CKSEG3) == CKSEG0)
36 pgd = CPHYSADDR(pgd);
37 write_c0_context(pgd << 11);
38}
39 33
40#define TLBMISS_HANDLER_SETUP() \ 34#define TLBMISS_HANDLER_SETUP() \
41 do { \ 35 do { \
diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h
index 892062d6d748..dcbd4bb417ec 100644
--- a/arch/mips/include/asm/uasm.h
+++ b/arch/mips/include/asm/uasm.h
@@ -115,7 +115,12 @@ Ip_0(_tlbwr);
115Ip_u3u1u2(_xor); 115Ip_u3u1u2(_xor);
116Ip_u2u1u3(_xori); 116Ip_u2u1u3(_xori);
117Ip_u2u1msbu3(_dins); 117Ip_u2u1msbu3(_dins);
118Ip_u2u1msbu3(_dinsm);
118Ip_u1(_syscall); 119Ip_u1(_syscall);
120Ip_u1u2s3(_bbit0);
121Ip_u1u2s3(_bbit1);
122Ip_u3u1u2(_lwx);
123Ip_u3u1u2(_ldx);
119 124
120/* Handle labels. */ 125/* Handle labels. */
121struct uasm_label { 126struct uasm_label {
@@ -153,6 +158,7 @@ static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \
153# define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_dsubu(buf, rs, rt, rd) 158# define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_dsubu(buf, rs, rt, rd)
154# define UASM_i_LL(buf, rs, rt, off) uasm_i_lld(buf, rs, rt, off) 159# define UASM_i_LL(buf, rs, rt, off) uasm_i_lld(buf, rs, rt, off)
155# define UASM_i_SC(buf, rs, rt, off) uasm_i_scd(buf, rs, rt, off) 160# define UASM_i_SC(buf, rs, rt, off) uasm_i_scd(buf, rs, rt, off)
161# define UASM_i_LWX(buf, rs, rt, rd) uasm_i_ldx(buf, rs, rt, rd)
156#else 162#else
157# define UASM_i_LW(buf, rs, rt, off) uasm_i_lw(buf, rs, rt, off) 163# define UASM_i_LW(buf, rs, rt, off) uasm_i_lw(buf, rs, rt, off)
158# define UASM_i_SW(buf, rs, rt, off) uasm_i_sw(buf, rs, rt, off) 164# define UASM_i_SW(buf, rs, rt, off) uasm_i_sw(buf, rs, rt, off)
@@ -167,6 +173,7 @@ static inline void __uasminit uasm_l##lb(struct uasm_label **lab, u32 *addr) \
167# define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_subu(buf, rs, rt, rd) 173# define UASM_i_SUBU(buf, rs, rt, rd) uasm_i_subu(buf, rs, rt, rd)
168# define UASM_i_LL(buf, rs, rt, off) uasm_i_ll(buf, rs, rt, off) 174# define UASM_i_LL(buf, rs, rt, off) uasm_i_ll(buf, rs, rt, off)
169# define UASM_i_SC(buf, rs, rt, off) uasm_i_sc(buf, rs, rt, off) 175# define UASM_i_SC(buf, rs, rt, off) uasm_i_sc(buf, rs, rt, off)
176# define UASM_i_LWX(buf, rs, rt, rd) uasm_i_lwx(buf, rs, rt, rd)
170#endif 177#endif
171 178
172#define uasm_i_b(buf, off) uasm_i_beq(buf, 0, 0, off) 179#define uasm_i_b(buf, off) uasm_i_beq(buf, 0, 0, off)
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 22b2e0e38617..cedee2bcbd18 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -95,6 +95,7 @@ obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o
95obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o 95obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
96obj-$(CONFIG_EARLY_PRINTK) += early_printk.o 96obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
97obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o 97obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o
98obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o
98 99
99obj-$(CONFIG_OF) += prom.o 100obj-$(CONFIG_OF) += prom.o
100 101
@@ -106,4 +107,6 @@ obj-$(CONFIG_MIPS_CPUFREQ) += cpufreq/
106 107
107obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o 108obj-$(CONFIG_HW_PERF_EVENTS) += perf_event.o
108 109
110obj-$(CONFIG_JUMP_LABEL) += jump_label.o
111
109CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS) 112CPPFLAGS_vmlinux.lds := $(KBUILD_CFLAGS)
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 68dae7b6b5db..f65d4c8c65a6 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -739,6 +739,8 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c)
739 && cpu_has_tlb) 739 && cpu_has_tlb)
740 c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40; 740 c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40;
741 741
742 c->kscratch_mask = (config4 >> 16) & 0xff;
743
742 return config4 & MIPS_CONF_M; 744 return config4 & MIPS_CONF_M;
743} 745}
744 746
diff --git a/arch/mips/kernel/jump_label.c b/arch/mips/kernel/jump_label.c
new file mode 100644
index 000000000000..6001610cfe55
--- /dev/null
+++ b/arch/mips/kernel/jump_label.c
@@ -0,0 +1,54 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (c) 2010 Cavium Networks, Inc.
7 */
8
9#include <linux/jump_label.h>
10#include <linux/kernel.h>
11#include <linux/memory.h>
12#include <linux/mutex.h>
13#include <linux/types.h>
14#include <linux/cpu.h>
15
16#include <asm/cacheflush.h>
17#include <asm/inst.h>
18
19#ifdef HAVE_JUMP_LABEL
20
21#define J_RANGE_MASK ((1ul << 28) - 1)
22
23void arch_jump_label_transform(struct jump_entry *e,
24 enum jump_label_type type)
25{
26 union mips_instruction insn;
27 union mips_instruction *insn_p =
28 (union mips_instruction *)(unsigned long)e->code;
29
30 /* Jump only works within a 256MB aligned region. */
31 BUG_ON((e->target & ~J_RANGE_MASK) != (e->code & ~J_RANGE_MASK));
32
33 /* Target must have 4 byte alignment. */
34 BUG_ON((e->target & 3) != 0);
35
36 if (type == JUMP_LABEL_ENABLE) {
37 insn.j_format.opcode = j_op;
38 insn.j_format.target = (e->target & J_RANGE_MASK) >> 2;
39 } else {
40 insn.word = 0; /* nop */
41 }
42
43 get_online_cpus();
44 mutex_lock(&text_mutex);
45 *insn_p = insn;
46
47 flush_icache_range((unsigned long)insn_p,
48 (unsigned long)insn_p + sizeof(*insn_p));
49
50 mutex_unlock(&text_mutex);
51 put_online_cpus();
52}
53
54#endif /* HAVE_JUMP_LABEL */
diff --git a/arch/mips/kernel/mips_machine.c b/arch/mips/kernel/mips_machine.c
new file mode 100644
index 000000000000..411a058d2c53
--- /dev/null
+++ b/arch/mips/kernel/mips_machine.c
@@ -0,0 +1,86 @@
1/*
2 * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 as published
6 * by the Free Software Foundation.
7 *
8 */
9#include <linux/mm.h>
10#include <linux/string.h>
11#include <linux/slab.h>
12
13#include <asm/mips_machine.h>
14
15static struct mips_machine *mips_machine __initdata;
16static char *mips_machine_name = "Unknown";
17
18#define for_each_machine(mach) \
19 for ((mach) = (struct mips_machine *)&__mips_machines_start; \
20 (mach) && \
21 (unsigned long)(mach) < (unsigned long)&__mips_machines_end; \
22 (mach)++)
23
24__init void mips_set_machine_name(const char *name)
25{
26 char *p;
27
28 if (name == NULL)
29 return;
30
31 p = kstrdup(name, GFP_KERNEL);
32 if (!p)
33 pr_err("MIPS: no memory for machine_name\n");
34
35 mips_machine_name = p;
36}
37
38char *mips_get_machine_name(void)
39{
40 return mips_machine_name;
41}
42
43__init int mips_machtype_setup(char *id)
44{
45 struct mips_machine *mach;
46
47 for_each_machine(mach) {
48 if (mach->mach_id == NULL)
49 continue;
50
51 if (strcmp(mach->mach_id, id) == 0) {
52 mips_machtype = mach->mach_type;
53 return 0;
54 }
55 }
56
57 pr_err("MIPS: no machine found for id '%s', supported machines:\n", id);
58 pr_err("%-24s %s\n", "id", "name");
59 for_each_machine(mach)
60 pr_err("%-24s %s\n", mach->mach_id, mach->mach_name);
61
62 return 1;
63}
64
65__setup("machtype=", mips_machtype_setup);
66
67__init void mips_machine_setup(void)
68{
69 struct mips_machine *mach;
70
71 for_each_machine(mach) {
72 if (mips_machtype == mach->mach_type) {
73 mips_machine = mach;
74 break;
75 }
76 }
77
78 if (!mips_machine)
79 return;
80
81 mips_set_machine_name(mips_machine->mach_name);
82 pr_info("MIPS: machine is %s\n", mips_machine_name);
83
84 if (mips_machine->mach_setup)
85 mips_machine->mach_setup();
86}
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index d87a72e9fac7..dd940b701963 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -30,6 +30,8 @@
30#include <linux/kernel.h> 30#include <linux/kernel.h>
31#include <linux/module.h> 31#include <linux/module.h>
32#include <linux/spinlock.h> 32#include <linux/spinlock.h>
33#include <linux/jump_label.h>
34
33#include <asm/pgtable.h> /* MODULE_START */ 35#include <asm/pgtable.h> /* MODULE_START */
34 36
35struct mips_hi16 { 37struct mips_hi16 {
@@ -382,6 +384,9 @@ int module_finalize(const Elf_Ehdr *hdr,
382 const Elf_Shdr *s; 384 const Elf_Shdr *s;
383 char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 385 char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
384 386
387 /* Make jump label nops. */
388 jump_label_apply_nops(me);
389
385 INIT_LIST_HEAD(&me->arch.dbe_list); 390 INIT_LIST_HEAD(&me->arch.dbe_list);
386 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { 391 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
387 if (strcmp("__dbe_table", secstrings + s->sh_name) != 0) 392 if (strcmp("__dbe_table", secstrings + s->sh_name) != 0)
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 26109c4d5170..e309665b6c81 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -12,6 +12,7 @@
12#include <asm/cpu-features.h> 12#include <asm/cpu-features.h>
13#include <asm/mipsregs.h> 13#include <asm/mipsregs.h>
14#include <asm/processor.h> 14#include <asm/processor.h>
15#include <asm/mips_machine.h>
15 16
16unsigned int vced_count, vcei_count; 17unsigned int vced_count, vcei_count;
17 18
@@ -31,8 +32,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
31 /* 32 /*
32 * For the first processor also print the system type 33 * For the first processor also print the system type
33 */ 34 */
34 if (n == 0) 35 if (n == 0) {
35 seq_printf(m, "system type\t\t: %s\n", get_system_type()); 36 seq_printf(m, "system type\t\t: %s\n", get_system_type());
37 if (mips_get_machine_name())
38 seq_printf(m, "machine\t\t\t: %s\n",
39 mips_get_machine_name());
40 }
36 41
37 seq_printf(m, "processor\t\t: %ld\n", n); 42 seq_printf(m, "processor\t\t: %ld\n", n);
38 sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n", 43 sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n",
@@ -69,6 +74,8 @@ static int show_cpuinfo(struct seq_file *m, void *v)
69 ); 74 );
70 seq_printf(m, "shadow register sets\t: %d\n", 75 seq_printf(m, "shadow register sets\t: %d\n",
71 cpu_data[n].srsets); 76 cpu_data[n].srsets);
77 seq_printf(m, "kscratch registers\t: %d\n",
78 hweight8(cpu_data[n].kscratch_mask));
72 seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core); 79 seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core);
73 80
74 sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", 81 sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index acd3f2c49c06..8ad1d5679f14 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -70,7 +70,7 @@ static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
70 * mips_io_port_base is the begin of the address space to which x86 style 70 * mips_io_port_base is the begin of the address space to which x86 style
71 * I/O ports are mapped. 71 * I/O ports are mapped.
72 */ 72 */
73const unsigned long mips_io_port_base __read_mostly = -1; 73const unsigned long mips_io_port_base = -1;
74EXPORT_SYMBOL(mips_io_port_base); 74EXPORT_SYMBOL(mips_io_port_base);
75 75
76static struct resource code_resource = { .name = "Kernel code", }; 76static struct resource code_resource = { .name = "Kernel code", };
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index e97104302541..71350f7f2d88 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1592,7 +1592,6 @@ void __cpuinit per_cpu_trap_init(void)
1592#endif /* CONFIG_MIPS_MT_SMTC */ 1592#endif /* CONFIG_MIPS_MT_SMTC */
1593 1593
1594 cpu_data[cpu].asid_cache = ASID_FIRST_VERSION; 1594 cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
1595 TLBMISS_HANDLER_SETUP();
1596 1595
1597 atomic_inc(&init_mm.mm_count); 1596 atomic_inc(&init_mm.mm_count);
1598 current->active_mm = &init_mm; 1597 current->active_mm = &init_mm;
@@ -1614,6 +1613,7 @@ void __cpuinit per_cpu_trap_init(void)
1614 write_c0_wired(0); 1613 write_c0_wired(0);
1615 } 1614 }
1616#endif /* CONFIG_MIPS_MT_SMTC */ 1615#endif /* CONFIG_MIPS_MT_SMTC */
1616 TLBMISS_HANDLER_SETUP();
1617} 1617}
1618 1618
1619/* Install CPU exception handler */ 1619/* Install CPU exception handler */
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index f25df73db923..570607b376b5 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -98,6 +98,13 @@ SECTIONS
98 INIT_TEXT_SECTION(PAGE_SIZE) 98 INIT_TEXT_SECTION(PAGE_SIZE)
99 INIT_DATA_SECTION(16) 99 INIT_DATA_SECTION(16)
100 100
101 . = ALIGN(4);
102 .mips.machines.init : AT(ADDR(.mips.machines.init) - LOAD_OFFSET) {
103 __mips_machines_start = .;
104 *(.mips.machines.init)
105 __mips_machines_end = .;
106 }
107
101 /* .exit.text is discarded at runtime, not link time, to deal with 108 /* .exit.text is discarded at runtime, not link time, to deal with
102 * references from .rodata 109 * references from .rodata
103 */ 110 */
diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c
index 93816f3bca67..083d3412d0bc 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -26,8 +26,10 @@
26#include <linux/smp.h> 26#include <linux/smp.h>
27#include <linux/string.h> 27#include <linux/string.h>
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/cache.h>
29 30
30#include <asm/mmu_context.h> 31#include <asm/cacheflush.h>
32#include <asm/pgtable.h>
31#include <asm/war.h> 33#include <asm/war.h>
32#include <asm/uasm.h> 34#include <asm/uasm.h>
33 35
@@ -63,6 +65,52 @@ static inline int __maybe_unused r10000_llsc_war(void)
63 return R10000_LLSC_WAR; 65 return R10000_LLSC_WAR;
64} 66}
65 67
68static int use_bbit_insns(void)
69{
70 switch (current_cpu_type()) {
71 case CPU_CAVIUM_OCTEON:
72 case CPU_CAVIUM_OCTEON_PLUS:
73 case CPU_CAVIUM_OCTEON2:
74 return 1;
75 default:
76 return 0;
77 }
78}
79
80static int use_lwx_insns(void)
81{
82 switch (current_cpu_type()) {
83 case CPU_CAVIUM_OCTEON2:
84 return 1;
85 default:
86 return 0;
87 }
88}
89#if defined(CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE) && \
90 CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE > 0
91static bool scratchpad_available(void)
92{
93 return true;
94}
95static int scratchpad_offset(int i)
96{
97 /*
98 * CVMSEG starts at address -32768 and extends for
99 * CAVIUM_OCTEON_CVMSEG_SIZE 128 byte cache lines.
100 */
101 i += 1; /* Kernel use starts at the top and works down. */
102 return CONFIG_CAVIUM_OCTEON_CVMSEG_SIZE * 128 - (8 * i) - 32768;
103}
104#else
105static bool scratchpad_available(void)
106{
107 return false;
108}
109static int scratchpad_offset(int i)
110{
111 BUG();
112}
113#endif
66/* 114/*
67 * Found by experiment: At least some revisions of the 4kc throw under 115 * Found by experiment: At least some revisions of the 4kc throw under
68 * some circumstances a machine check exception, triggered by invalid 116 * some circumstances a machine check exception, triggered by invalid
@@ -173,11 +221,41 @@ static struct uasm_reloc relocs[128] __cpuinitdata;
173static int check_for_high_segbits __cpuinitdata; 221static int check_for_high_segbits __cpuinitdata;
174#endif 222#endif
175 223
224static int check_for_high_segbits __cpuinitdata;
225
226static unsigned int kscratch_used_mask __cpuinitdata;
227
228static int __cpuinit allocate_kscratch(void)
229{
230 int r;
231 unsigned int a = cpu_data[0].kscratch_mask & ~kscratch_used_mask;
232
233 r = ffs(a);
234
235 if (r == 0)
236 return -1;
237
238 r--; /* make it zero based */
239
240 kscratch_used_mask |= (1 << r);
241
242 return r;
243}
244
245static int scratch_reg __cpuinitdata;
246static int pgd_reg __cpuinitdata;
247enum vmalloc64_mode {not_refill, refill_scratch, refill_noscratch};
248
176#ifndef CONFIG_MIPS_PGD_C0_CONTEXT 249#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
250
177/* 251/*
178 * CONFIG_MIPS_PGD_C0_CONTEXT implies 64 bit and lack of pgd_current, 252 * CONFIG_MIPS_PGD_C0_CONTEXT implies 64 bit and lack of pgd_current,
179 * we cannot do r3000 under these circumstances. 253 * we cannot do r3000 under these circumstances.
254 *
255 * Declare pgd_current here instead of including mmu_context.h to avoid type
256 * conflicts for tlbmiss_handler_setup_pgd
180 */ 257 */
258extern unsigned long pgd_current[];
181 259
182/* 260/*
183 * The R3000 TLB handler is simple. 261 * The R3000 TLB handler is simple.
@@ -440,21 +518,43 @@ static __cpuinit __maybe_unused void build_convert_pte_to_entrylo(u32 **p,
440static __cpuinit void build_restore_pagemask(u32 **p, 518static __cpuinit void build_restore_pagemask(u32 **p,
441 struct uasm_reloc **r, 519 struct uasm_reloc **r,
442 unsigned int tmp, 520 unsigned int tmp,
443 enum label_id lid) 521 enum label_id lid,
522 int restore_scratch)
444{ 523{
445 /* Reset default page size */ 524 if (restore_scratch) {
446 if (PM_DEFAULT_MASK >> 16) { 525 /* Reset default page size */
447 uasm_i_lui(p, tmp, PM_DEFAULT_MASK >> 16); 526 if (PM_DEFAULT_MASK >> 16) {
448 uasm_i_ori(p, tmp, tmp, PM_DEFAULT_MASK & 0xffff); 527 uasm_i_lui(p, tmp, PM_DEFAULT_MASK >> 16);
449 uasm_il_b(p, r, lid); 528 uasm_i_ori(p, tmp, tmp, PM_DEFAULT_MASK & 0xffff);
450 uasm_i_mtc0(p, tmp, C0_PAGEMASK); 529 uasm_i_mtc0(p, tmp, C0_PAGEMASK);
451 } else if (PM_DEFAULT_MASK) { 530 uasm_il_b(p, r, lid);
452 uasm_i_ori(p, tmp, 0, PM_DEFAULT_MASK); 531 } else if (PM_DEFAULT_MASK) {
453 uasm_il_b(p, r, lid); 532 uasm_i_ori(p, tmp, 0, PM_DEFAULT_MASK);
454 uasm_i_mtc0(p, tmp, C0_PAGEMASK); 533 uasm_i_mtc0(p, tmp, C0_PAGEMASK);
534 uasm_il_b(p, r, lid);
535 } else {
536 uasm_i_mtc0(p, 0, C0_PAGEMASK);
537 uasm_il_b(p, r, lid);
538 }
539 if (scratch_reg > 0)
540 UASM_i_MFC0(p, 1, 31, scratch_reg);
541 else
542 UASM_i_LW(p, 1, scratchpad_offset(0), 0);
455 } else { 543 } else {
456 uasm_il_b(p, r, lid); 544 /* Reset default page size */
457 uasm_i_mtc0(p, 0, C0_PAGEMASK); 545 if (PM_DEFAULT_MASK >> 16) {
546 uasm_i_lui(p, tmp, PM_DEFAULT_MASK >> 16);
547 uasm_i_ori(p, tmp, tmp, PM_DEFAULT_MASK & 0xffff);
548 uasm_il_b(p, r, lid);
549 uasm_i_mtc0(p, tmp, C0_PAGEMASK);
550 } else if (PM_DEFAULT_MASK) {
551 uasm_i_ori(p, tmp, 0, PM_DEFAULT_MASK);
552 uasm_il_b(p, r, lid);
553 uasm_i_mtc0(p, tmp, C0_PAGEMASK);
554 } else {
555 uasm_il_b(p, r, lid);
556 uasm_i_mtc0(p, 0, C0_PAGEMASK);
557 }
458 } 558 }
459} 559}
460 560
@@ -462,7 +562,8 @@ static __cpuinit void build_huge_tlb_write_entry(u32 **p,
462 struct uasm_label **l, 562 struct uasm_label **l,
463 struct uasm_reloc **r, 563 struct uasm_reloc **r,
464 unsigned int tmp, 564 unsigned int tmp,
465 enum tlb_write_entry wmode) 565 enum tlb_write_entry wmode,
566 int restore_scratch)
466{ 567{
467 /* Set huge page tlb entry size */ 568 /* Set huge page tlb entry size */
468 uasm_i_lui(p, tmp, PM_HUGE_MASK >> 16); 569 uasm_i_lui(p, tmp, PM_HUGE_MASK >> 16);
@@ -471,7 +572,7 @@ static __cpuinit void build_huge_tlb_write_entry(u32 **p,
471 572
472 build_tlb_write_entry(p, l, r, wmode); 573 build_tlb_write_entry(p, l, r, wmode);
473 574
474 build_restore_pagemask(p, r, tmp, label_leave); 575 build_restore_pagemask(p, r, tmp, label_leave, restore_scratch);
475} 576}
476 577
477/* 578/*
@@ -482,8 +583,12 @@ build_is_huge_pte(u32 **p, struct uasm_reloc **r, unsigned int tmp,
482 unsigned int pmd, int lid) 583 unsigned int pmd, int lid)
483{ 584{
484 UASM_i_LW(p, tmp, 0, pmd); 585 UASM_i_LW(p, tmp, 0, pmd);
485 uasm_i_andi(p, tmp, tmp, _PAGE_HUGE); 586 if (use_bbit_insns()) {
486 uasm_il_bnez(p, r, tmp, lid); 587 uasm_il_bbit1(p, r, tmp, ilog2(_PAGE_HUGE), lid);
588 } else {
589 uasm_i_andi(p, tmp, tmp, _PAGE_HUGE);
590 uasm_il_bnez(p, r, tmp, lid);
591 }
487} 592}
488 593
489static __cpuinit void build_huge_update_entries(u32 **p, 594static __cpuinit void build_huge_update_entries(u32 **p,
@@ -532,7 +637,7 @@ static __cpuinit void build_huge_handler_tail(u32 **p,
532 UASM_i_SW(p, pte, 0, ptr); 637 UASM_i_SW(p, pte, 0, ptr);
533#endif 638#endif
534 build_huge_update_entries(p, pte, ptr); 639 build_huge_update_entries(p, pte, ptr);
535 build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed); 640 build_huge_tlb_write_entry(p, l, r, pte, tlb_indexed, 0);
536} 641}
537#endif /* CONFIG_HUGETLB_PAGE */ 642#endif /* CONFIG_HUGETLB_PAGE */
538 643
@@ -573,13 +678,22 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
573 /* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */ 678 /* No uasm_i_nop needed here, since the next insn doesn't touch TMP. */
574 679
575#ifdef CONFIG_MIPS_PGD_C0_CONTEXT 680#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
576 /* 681 if (pgd_reg != -1) {
577 * &pgd << 11 stored in CONTEXT [23..63]. 682 /* pgd is in pgd_reg */
578 */ 683 UASM_i_MFC0(p, ptr, 31, pgd_reg);
579 UASM_i_MFC0(p, ptr, C0_CONTEXT); 684 } else {
580 uasm_i_dins(p, ptr, 0, 0, 23); /* Clear lower 23 bits of context. */ 685 /*
581 uasm_i_ori(p, ptr, ptr, 0x540); /* 1 0 1 0 1 << 6 xkphys cached */ 686 * &pgd << 11 stored in CONTEXT [23..63].
582 uasm_i_drotr(p, ptr, ptr, 11); 687 */
688 UASM_i_MFC0(p, ptr, C0_CONTEXT);
689
690 /* Clear lower 23 bits of context. */
691 uasm_i_dins(p, ptr, 0, 0, 23);
692
693 /* 1 0 1 0 1 << 6 xkphys cached */
694 uasm_i_ori(p, ptr, ptr, 0x540);
695 uasm_i_drotr(p, ptr, ptr, 11);
696 }
583#elif defined(CONFIG_SMP) 697#elif defined(CONFIG_SMP)
584# ifdef CONFIG_MIPS_MT_SMTC 698# ifdef CONFIG_MIPS_MT_SMTC
585 /* 699 /*
@@ -620,7 +734,6 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
620#endif 734#endif
621} 735}
622 736
623enum vmalloc64_mode {not_refill, refill};
624/* 737/*
625 * BVADDR is the faulting address, PTR is scratch. 738 * BVADDR is the faulting address, PTR is scratch.
626 * PTR will hold the pgd for vmalloc. 739 * PTR will hold the pgd for vmalloc.
@@ -638,7 +751,7 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
638 751
639 uasm_l_vmalloc(l, *p); 752 uasm_l_vmalloc(l, *p);
640 753
641 if (mode == refill && check_for_high_segbits) { 754 if (mode != not_refill && check_for_high_segbits) {
642 if (single_insn_swpd) { 755 if (single_insn_swpd) {
643 uasm_il_bltz(p, r, bvaddr, label_vmalloc_done); 756 uasm_il_bltz(p, r, bvaddr, label_vmalloc_done);
644 uasm_i_lui(p, ptr, uasm_rel_hi(swpd)); 757 uasm_i_lui(p, ptr, uasm_rel_hi(swpd));
@@ -661,7 +774,7 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
661 uasm_i_daddiu(p, ptr, ptr, uasm_rel_lo(swpd)); 774 uasm_i_daddiu(p, ptr, ptr, uasm_rel_lo(swpd));
662 } 775 }
663 } 776 }
664 if (mode == refill && check_for_high_segbits) { 777 if (mode != not_refill && check_for_high_segbits) {
665 uasm_l_large_segbits_fault(l, *p); 778 uasm_l_large_segbits_fault(l, *p);
666 /* 779 /*
667 * We get here if we are an xsseg address, or if we are 780 * We get here if we are an xsseg address, or if we are
@@ -677,7 +790,15 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
677 */ 790 */
678 UASM_i_LA(p, ptr, (unsigned long)tlb_do_page_fault_0); 791 UASM_i_LA(p, ptr, (unsigned long)tlb_do_page_fault_0);
679 uasm_i_jr(p, ptr); 792 uasm_i_jr(p, ptr);
680 uasm_i_nop(p); 793
794 if (mode == refill_scratch) {
795 if (scratch_reg > 0)
796 UASM_i_MFC0(p, 1, 31, scratch_reg);
797 else
798 UASM_i_LW(p, 1, scratchpad_offset(0), 0);
799 } else {
800 uasm_i_nop(p);
801 }
681 } 802 }
682} 803}
683 804
@@ -834,6 +955,185 @@ static void __cpuinit build_update_entries(u32 **p, unsigned int tmp,
834#endif 955#endif
835} 956}
836 957
958struct mips_huge_tlb_info {
959 int huge_pte;
960 int restore_scratch;
961};
962
963static struct mips_huge_tlb_info __cpuinit
964build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
965 struct uasm_reloc **r, unsigned int tmp,
966 unsigned int ptr, int c0_scratch)
967{
968 struct mips_huge_tlb_info rv;
969 unsigned int even, odd;
970 int vmalloc_branch_delay_filled = 0;
971 const int scratch = 1; /* Our extra working register */
972
973 rv.huge_pte = scratch;
974 rv.restore_scratch = 0;
975
976 if (check_for_high_segbits) {
977 UASM_i_MFC0(p, tmp, C0_BADVADDR);
978
979 if (pgd_reg != -1)
980 UASM_i_MFC0(p, ptr, 31, pgd_reg);
981 else
982 UASM_i_MFC0(p, ptr, C0_CONTEXT);
983
984 if (c0_scratch >= 0)
985 UASM_i_MTC0(p, scratch, 31, c0_scratch);
986 else
987 UASM_i_SW(p, scratch, scratchpad_offset(0), 0);
988
989 uasm_i_dsrl_safe(p, scratch, tmp,
990 PGDIR_SHIFT + PGD_ORDER + PAGE_SHIFT - 3);
991 uasm_il_bnez(p, r, scratch, label_vmalloc);
992
993 if (pgd_reg == -1) {
994 vmalloc_branch_delay_filled = 1;
995 /* Clear lower 23 bits of context. */
996 uasm_i_dins(p, ptr, 0, 0, 23);
997 }
998 } else {
999 if (pgd_reg != -1)
1000 UASM_i_MFC0(p, ptr, 31, pgd_reg);
1001 else
1002 UASM_i_MFC0(p, ptr, C0_CONTEXT);
1003
1004 UASM_i_MFC0(p, tmp, C0_BADVADDR);
1005
1006 if (c0_scratch >= 0)
1007 UASM_i_MTC0(p, scratch, 31, c0_scratch);
1008 else
1009 UASM_i_SW(p, scratch, scratchpad_offset(0), 0);
1010
1011 if (pgd_reg == -1)
1012 /* Clear lower 23 bits of context. */
1013 uasm_i_dins(p, ptr, 0, 0, 23);
1014
1015 uasm_il_bltz(p, r, tmp, label_vmalloc);
1016 }
1017
1018 if (pgd_reg == -1) {
1019 vmalloc_branch_delay_filled = 1;
1020 /* 1 0 1 0 1 << 6 xkphys cached */
1021 uasm_i_ori(p, ptr, ptr, 0x540);
1022 uasm_i_drotr(p, ptr, ptr, 11);
1023 }
1024
1025#ifdef __PAGETABLE_PMD_FOLDED
1026#define LOC_PTEP scratch
1027#else
1028#define LOC_PTEP ptr
1029#endif
1030
1031 if (!vmalloc_branch_delay_filled)
1032 /* get pgd offset in bytes */
1033 uasm_i_dsrl_safe(p, scratch, tmp, PGDIR_SHIFT - 3);
1034
1035 uasm_l_vmalloc_done(l, *p);
1036
1037 /*
1038 * tmp ptr
1039 * fall-through case = badvaddr *pgd_current
1040 * vmalloc case = badvaddr swapper_pg_dir
1041 */
1042
1043 if (vmalloc_branch_delay_filled)
1044 /* get pgd offset in bytes */
1045 uasm_i_dsrl_safe(p, scratch, tmp, PGDIR_SHIFT - 3);
1046
1047#ifdef __PAGETABLE_PMD_FOLDED
1048 GET_CONTEXT(p, tmp); /* get context reg */
1049#endif
1050 uasm_i_andi(p, scratch, scratch, (PTRS_PER_PGD - 1) << 3);
1051
1052 if (use_lwx_insns()) {
1053 UASM_i_LWX(p, LOC_PTEP, scratch, ptr);
1054 } else {
1055 uasm_i_daddu(p, ptr, ptr, scratch); /* add in pgd offset */
1056 uasm_i_ld(p, LOC_PTEP, 0, ptr); /* get pmd pointer */
1057 }
1058
1059#ifndef __PAGETABLE_PMD_FOLDED
1060 /* get pmd offset in bytes */
1061 uasm_i_dsrl_safe(p, scratch, tmp, PMD_SHIFT - 3);
1062 uasm_i_andi(p, scratch, scratch, (PTRS_PER_PMD - 1) << 3);
1063 GET_CONTEXT(p, tmp); /* get context reg */
1064
1065 if (use_lwx_insns()) {
1066 UASM_i_LWX(p, scratch, scratch, ptr);
1067 } else {
1068 uasm_i_daddu(p, ptr, ptr, scratch); /* add in pmd offset */
1069 UASM_i_LW(p, scratch, 0, ptr);
1070 }
1071#endif
1072 /* Adjust the context during the load latency. */
1073 build_adjust_context(p, tmp);
1074
1075#ifdef CONFIG_HUGETLB_PAGE
1076 uasm_il_bbit1(p, r, scratch, ilog2(_PAGE_HUGE), label_tlb_huge_update);
1077 /*
1078 * The in the LWX case we don't want to do the load in the
1079 * delay slot. It cannot issue in the same cycle and may be
1080 * speculative and unneeded.
1081 */
1082 if (use_lwx_insns())
1083 uasm_i_nop(p);
1084#endif /* CONFIG_HUGETLB_PAGE */
1085
1086
1087 /* build_update_entries */
1088 if (use_lwx_insns()) {
1089 even = ptr;
1090 odd = tmp;
1091 UASM_i_LWX(p, even, scratch, tmp);
1092 UASM_i_ADDIU(p, tmp, tmp, sizeof(pte_t));
1093 UASM_i_LWX(p, odd, scratch, tmp);
1094 } else {
1095 UASM_i_ADDU(p, ptr, scratch, tmp); /* add in offset */
1096 even = tmp;
1097 odd = ptr;
1098 UASM_i_LW(p, even, 0, ptr); /* get even pte */
1099 UASM_i_LW(p, odd, sizeof(pte_t), ptr); /* get odd pte */
1100 }
1101 if (kernel_uses_smartmips_rixi) {
1102 uasm_i_dsrl_safe(p, even, even, ilog2(_PAGE_NO_EXEC));
1103 uasm_i_dsrl_safe(p, odd, odd, ilog2(_PAGE_NO_EXEC));
1104 uasm_i_drotr(p, even, even,
1105 ilog2(_PAGE_GLOBAL) - ilog2(_PAGE_NO_EXEC));
1106 UASM_i_MTC0(p, even, C0_ENTRYLO0); /* load it */
1107 uasm_i_drotr(p, odd, odd,
1108 ilog2(_PAGE_GLOBAL) - ilog2(_PAGE_NO_EXEC));
1109 } else {
1110 uasm_i_dsrl_safe(p, even, even, ilog2(_PAGE_GLOBAL));
1111 UASM_i_MTC0(p, even, C0_ENTRYLO0); /* load it */
1112 uasm_i_dsrl_safe(p, odd, odd, ilog2(_PAGE_GLOBAL));
1113 }
1114 UASM_i_MTC0(p, odd, C0_ENTRYLO1); /* load it */
1115
1116 if (c0_scratch >= 0) {
1117 UASM_i_MFC0(p, scratch, 31, c0_scratch);
1118 build_tlb_write_entry(p, l, r, tlb_random);
1119 uasm_l_leave(l, *p);
1120 rv.restore_scratch = 1;
1121 } else if (PAGE_SHIFT == 14 || PAGE_SHIFT == 13) {
1122 build_tlb_write_entry(p, l, r, tlb_random);
1123 uasm_l_leave(l, *p);
1124 UASM_i_LW(p, scratch, scratchpad_offset(0), 0);
1125 } else {
1126 UASM_i_LW(p, scratch, scratchpad_offset(0), 0);
1127 build_tlb_write_entry(p, l, r, tlb_random);
1128 uasm_l_leave(l, *p);
1129 rv.restore_scratch = 1;
1130 }
1131
1132 uasm_i_eret(p); /* return from trap */
1133
1134 return rv;
1135}
1136
837/* 1137/*
838 * For a 64-bit kernel, we are using the 64-bit XTLB refill exception 1138 * For a 64-bit kernel, we are using the 64-bit XTLB refill exception
839 * because EXL == 0. If we wrap, we can also use the 32 instruction 1139 * because EXL == 0. If we wrap, we can also use the 32 instruction
@@ -849,54 +1149,67 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
849 struct uasm_reloc *r = relocs; 1149 struct uasm_reloc *r = relocs;
850 u32 *f; 1150 u32 *f;
851 unsigned int final_len; 1151 unsigned int final_len;
1152 struct mips_huge_tlb_info htlb_info;
1153 enum vmalloc64_mode vmalloc_mode;
852 1154
853 memset(tlb_handler, 0, sizeof(tlb_handler)); 1155 memset(tlb_handler, 0, sizeof(tlb_handler));
854 memset(labels, 0, sizeof(labels)); 1156 memset(labels, 0, sizeof(labels));
855 memset(relocs, 0, sizeof(relocs)); 1157 memset(relocs, 0, sizeof(relocs));
856 memset(final_handler, 0, sizeof(final_handler)); 1158 memset(final_handler, 0, sizeof(final_handler));
857 1159
858 /* 1160 if (scratch_reg == 0)
859 * create the plain linear handler 1161 scratch_reg = allocate_kscratch();
860 */
861 if (bcm1250_m3_war()) {
862 unsigned int segbits = 44;
863 1162
864 uasm_i_dmfc0(&p, K0, C0_BADVADDR); 1163 if ((scratch_reg > 0 || scratchpad_available()) && use_bbit_insns()) {
865 uasm_i_dmfc0(&p, K1, C0_ENTRYHI); 1164 htlb_info = build_fast_tlb_refill_handler(&p, &l, &r, K0, K1,
866 uasm_i_xor(&p, K0, K0, K1); 1165 scratch_reg);
867 uasm_i_dsrl_safe(&p, K1, K0, 62); 1166 vmalloc_mode = refill_scratch;
868 uasm_i_dsrl_safe(&p, K0, K0, 12 + 1); 1167 } else {
869 uasm_i_dsll_safe(&p, K0, K0, 64 + 12 + 1 - segbits); 1168 htlb_info.huge_pte = K0;
870 uasm_i_or(&p, K0, K0, K1); 1169 htlb_info.restore_scratch = 0;
871 uasm_il_bnez(&p, &r, K0, label_leave); 1170 vmalloc_mode = refill_noscratch;
872 /* No need for uasm_i_nop */ 1171 /*
873 } 1172 * create the plain linear handler
1173 */
1174 if (bcm1250_m3_war()) {
1175 unsigned int segbits = 44;
1176
1177 uasm_i_dmfc0(&p, K0, C0_BADVADDR);
1178 uasm_i_dmfc0(&p, K1, C0_ENTRYHI);
1179 uasm_i_xor(&p, K0, K0, K1);
1180 uasm_i_dsrl_safe(&p, K1, K0, 62);
1181 uasm_i_dsrl_safe(&p, K0, K0, 12 + 1);
1182 uasm_i_dsll_safe(&p, K0, K0, 64 + 12 + 1 - segbits);
1183 uasm_i_or(&p, K0, K0, K1);
1184 uasm_il_bnez(&p, &r, K0, label_leave);
1185 /* No need for uasm_i_nop */
1186 }
874 1187
875#ifdef CONFIG_64BIT 1188#ifdef CONFIG_64BIT
876 build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */ 1189 build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
877#else 1190#else
878 build_get_pgde32(&p, K0, K1); /* get pgd in K1 */ 1191 build_get_pgde32(&p, K0, K1); /* get pgd in K1 */
879#endif 1192#endif
880 1193
881#ifdef CONFIG_HUGETLB_PAGE 1194#ifdef CONFIG_HUGETLB_PAGE
882 build_is_huge_pte(&p, &r, K0, K1, label_tlb_huge_update); 1195 build_is_huge_pte(&p, &r, K0, K1, label_tlb_huge_update);
883#endif 1196#endif
884 1197
885 build_get_ptep(&p, K0, K1); 1198 build_get_ptep(&p, K0, K1);
886 build_update_entries(&p, K0, K1); 1199 build_update_entries(&p, K0, K1);
887 build_tlb_write_entry(&p, &l, &r, tlb_random); 1200 build_tlb_write_entry(&p, &l, &r, tlb_random);
888 uasm_l_leave(&l, p); 1201 uasm_l_leave(&l, p);
889 uasm_i_eret(&p); /* return from trap */ 1202 uasm_i_eret(&p); /* return from trap */
890 1203 }
891#ifdef CONFIG_HUGETLB_PAGE 1204#ifdef CONFIG_HUGETLB_PAGE
892 uasm_l_tlb_huge_update(&l, p); 1205 uasm_l_tlb_huge_update(&l, p);
893 UASM_i_LW(&p, K0, 0, K1); 1206 build_huge_update_entries(&p, htlb_info.huge_pte, K1);
894 build_huge_update_entries(&p, K0, K1); 1207 build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random,
895 build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random); 1208 htlb_info.restore_scratch);
896#endif 1209#endif
897 1210
898#ifdef CONFIG_64BIT 1211#ifdef CONFIG_64BIT
899 build_get_pgd_vmalloc64(&p, &l, &r, K0, K1, refill); 1212 build_get_pgd_vmalloc64(&p, &l, &r, K0, K1, vmalloc_mode);
900#endif 1213#endif
901 1214
902 /* 1215 /*
@@ -1014,6 +1327,55 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
1014u32 handle_tlbl[FASTPATH_SIZE] __cacheline_aligned; 1327u32 handle_tlbl[FASTPATH_SIZE] __cacheline_aligned;
1015u32 handle_tlbs[FASTPATH_SIZE] __cacheline_aligned; 1328u32 handle_tlbs[FASTPATH_SIZE] __cacheline_aligned;
1016u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned; 1329u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned;
1330#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
1331u32 tlbmiss_handler_setup_pgd[16] __cacheline_aligned;
1332
1333static void __cpuinit build_r4000_setup_pgd(void)
1334{
1335 const int a0 = 4;
1336 const int a1 = 5;
1337 u32 *p = tlbmiss_handler_setup_pgd;
1338 struct uasm_label *l = labels;
1339 struct uasm_reloc *r = relocs;
1340
1341 memset(tlbmiss_handler_setup_pgd, 0, sizeof(tlbmiss_handler_setup_pgd));
1342 memset(labels, 0, sizeof(labels));
1343 memset(relocs, 0, sizeof(relocs));
1344
1345 pgd_reg = allocate_kscratch();
1346
1347 if (pgd_reg == -1) {
1348 /* PGD << 11 in c0_Context */
1349 /*
1350 * If it is a ckseg0 address, convert to a physical
1351 * address. Shifting right by 29 and adding 4 will
1352 * result in zero for these addresses.
1353 *
1354 */
1355 UASM_i_SRA(&p, a1, a0, 29);
1356 UASM_i_ADDIU(&p, a1, a1, 4);
1357 uasm_il_bnez(&p, &r, a1, label_tlbl_goaround1);
1358 uasm_i_nop(&p);
1359 uasm_i_dinsm(&p, a0, 0, 29, 64 - 29);
1360 uasm_l_tlbl_goaround1(&l, p);
1361 UASM_i_SLL(&p, a0, a0, 11);
1362 uasm_i_jr(&p, 31);
1363 UASM_i_MTC0(&p, a0, C0_CONTEXT);
1364 } else {
1365 /* PGD in c0_KScratch */
1366 uasm_i_jr(&p, 31);
1367 UASM_i_MTC0(&p, a0, 31, pgd_reg);
1368 }
1369 if (p - tlbmiss_handler_setup_pgd > ARRAY_SIZE(tlbmiss_handler_setup_pgd))
1370 panic("tlbmiss_handler_setup_pgd space exceeded");
1371 uasm_resolve_relocs(relocs, labels);
1372 pr_debug("Wrote tlbmiss_handler_setup_pgd (%u instructions).\n",
1373 (unsigned int)(p - tlbmiss_handler_setup_pgd));
1374
1375 dump_handler(tlbmiss_handler_setup_pgd,
1376 ARRAY_SIZE(tlbmiss_handler_setup_pgd));
1377}
1378#endif
1017 1379
1018static void __cpuinit 1380static void __cpuinit
1019iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr) 1381iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
@@ -1100,14 +1462,20 @@ build_pte_present(u32 **p, struct uasm_reloc **r,
1100 unsigned int pte, unsigned int ptr, enum label_id lid) 1462 unsigned int pte, unsigned int ptr, enum label_id lid)
1101{ 1463{
1102 if (kernel_uses_smartmips_rixi) { 1464 if (kernel_uses_smartmips_rixi) {
1103 uasm_i_andi(p, pte, pte, _PAGE_PRESENT); 1465 if (use_bbit_insns()) {
1104 uasm_il_beqz(p, r, pte, lid); 1466 uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid);
1467 uasm_i_nop(p);
1468 } else {
1469 uasm_i_andi(p, pte, pte, _PAGE_PRESENT);
1470 uasm_il_beqz(p, r, pte, lid);
1471 iPTE_LW(p, pte, ptr);
1472 }
1105 } else { 1473 } else {
1106 uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ); 1474 uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
1107 uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ); 1475 uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_READ);
1108 uasm_il_bnez(p, r, pte, lid); 1476 uasm_il_bnez(p, r, pte, lid);
1477 iPTE_LW(p, pte, ptr);
1109 } 1478 }
1110 iPTE_LW(p, pte, ptr);
1111} 1479}
1112 1480
1113/* Make PTE valid, store result in PTR. */ 1481/* Make PTE valid, store result in PTR. */
@@ -1128,10 +1496,17 @@ static void __cpuinit
1128build_pte_writable(u32 **p, struct uasm_reloc **r, 1496build_pte_writable(u32 **p, struct uasm_reloc **r,
1129 unsigned int pte, unsigned int ptr, enum label_id lid) 1497 unsigned int pte, unsigned int ptr, enum label_id lid)
1130{ 1498{
1131 uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE); 1499 if (use_bbit_insns()) {
1132 uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE); 1500 uasm_il_bbit0(p, r, pte, ilog2(_PAGE_PRESENT), lid);
1133 uasm_il_bnez(p, r, pte, lid); 1501 uasm_i_nop(p);
1134 iPTE_LW(p, pte, ptr); 1502 uasm_il_bbit0(p, r, pte, ilog2(_PAGE_WRITE), lid);
1503 uasm_i_nop(p);
1504 } else {
1505 uasm_i_andi(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
1506 uasm_i_xori(p, pte, pte, _PAGE_PRESENT | _PAGE_WRITE);
1507 uasm_il_bnez(p, r, pte, lid);
1508 iPTE_LW(p, pte, ptr);
1509 }
1135} 1510}
1136 1511
1137/* Make PTE writable, update software status bits as well, then store 1512/* Make PTE writable, update software status bits as well, then store
@@ -1155,12 +1530,19 @@ static void __cpuinit
1155build_pte_modifiable(u32 **p, struct uasm_reloc **r, 1530build_pte_modifiable(u32 **p, struct uasm_reloc **r,
1156 unsigned int pte, unsigned int ptr, enum label_id lid) 1531 unsigned int pte, unsigned int ptr, enum label_id lid)
1157{ 1532{
1158 uasm_i_andi(p, pte, pte, _PAGE_WRITE); 1533 if (use_bbit_insns()) {
1159 uasm_il_beqz(p, r, pte, lid); 1534 uasm_il_bbit0(p, r, pte, ilog2(_PAGE_WRITE), lid);
1160 iPTE_LW(p, pte, ptr); 1535 uasm_i_nop(p);
1536 } else {
1537 uasm_i_andi(p, pte, pte, _PAGE_WRITE);
1538 uasm_il_beqz(p, r, pte, lid);
1539 iPTE_LW(p, pte, ptr);
1540 }
1161} 1541}
1162 1542
1163#ifndef CONFIG_MIPS_PGD_C0_CONTEXT 1543#ifndef CONFIG_MIPS_PGD_C0_CONTEXT
1544
1545
1164/* 1546/*
1165 * R3000 style TLB load/store/modify handlers. 1547 * R3000 style TLB load/store/modify handlers.
1166 */ 1548 */
@@ -1402,14 +1784,23 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
1402 * If the page is not _PAGE_VALID, RI or XI could not 1784 * If the page is not _PAGE_VALID, RI or XI could not
1403 * have triggered it. Skip the expensive test.. 1785 * have triggered it. Skip the expensive test..
1404 */ 1786 */
1405 uasm_i_andi(&p, K0, K0, _PAGE_VALID); 1787 if (use_bbit_insns()) {
1406 uasm_il_beqz(&p, &r, K0, label_tlbl_goaround1); 1788 uasm_il_bbit0(&p, &r, K0, ilog2(_PAGE_VALID),
1789 label_tlbl_goaround1);
1790 } else {
1791 uasm_i_andi(&p, K0, K0, _PAGE_VALID);
1792 uasm_il_beqz(&p, &r, K0, label_tlbl_goaround1);
1793 }
1407 uasm_i_nop(&p); 1794 uasm_i_nop(&p);
1408 1795
1409 uasm_i_tlbr(&p); 1796 uasm_i_tlbr(&p);
1410 /* Examine entrylo 0 or 1 based on ptr. */ 1797 /* Examine entrylo 0 or 1 based on ptr. */
1411 uasm_i_andi(&p, K0, K1, sizeof(pte_t)); 1798 if (use_bbit_insns()) {
1412 uasm_i_beqz(&p, K0, 8); 1799 uasm_i_bbit0(&p, K1, ilog2(sizeof(pte_t)), 8);
1800 } else {
1801 uasm_i_andi(&p, K0, K1, sizeof(pte_t));
1802 uasm_i_beqz(&p, K0, 8);
1803 }
1413 1804
1414 UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/ 1805 UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/
1415 UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */ 1806 UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */
@@ -1417,12 +1808,18 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
1417 * If the entryLo (now in K0) is valid (bit 1), RI or 1808 * If the entryLo (now in K0) is valid (bit 1), RI or
1418 * XI must have triggered it. 1809 * XI must have triggered it.
1419 */ 1810 */
1420 uasm_i_andi(&p, K0, K0, 2); 1811 if (use_bbit_insns()) {
1421 uasm_il_bnez(&p, &r, K0, label_nopage_tlbl); 1812 uasm_il_bbit1(&p, &r, K0, 1, label_nopage_tlbl);
1422 1813 /* Reload the PTE value */
1423 uasm_l_tlbl_goaround1(&l, p); 1814 iPTE_LW(&p, K0, K1);
1424 /* Reload the PTE value */ 1815 uasm_l_tlbl_goaround1(&l, p);
1425 iPTE_LW(&p, K0, K1); 1816 } else {
1817 uasm_i_andi(&p, K0, K0, 2);
1818 uasm_il_bnez(&p, &r, K0, label_nopage_tlbl);
1819 uasm_l_tlbl_goaround1(&l, p);
1820 /* Reload the PTE value */
1821 iPTE_LW(&p, K0, K1);
1822 }
1426 } 1823 }
1427 build_make_valid(&p, &r, K0, K1); 1824 build_make_valid(&p, &r, K0, K1);
1428 build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1); 1825 build_r4000_tlbchange_handler_tail(&p, &l, &r, K0, K1);
@@ -1442,23 +1839,35 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
1442 * If the page is not _PAGE_VALID, RI or XI could not 1839 * If the page is not _PAGE_VALID, RI or XI could not
1443 * have triggered it. Skip the expensive test.. 1840 * have triggered it. Skip the expensive test..
1444 */ 1841 */
1445 uasm_i_andi(&p, K0, K0, _PAGE_VALID); 1842 if (use_bbit_insns()) {
1446 uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2); 1843 uasm_il_bbit0(&p, &r, K0, ilog2(_PAGE_VALID),
1844 label_tlbl_goaround2);
1845 } else {
1846 uasm_i_andi(&p, K0, K0, _PAGE_VALID);
1847 uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2);
1848 }
1447 uasm_i_nop(&p); 1849 uasm_i_nop(&p);
1448 1850
1449 uasm_i_tlbr(&p); 1851 uasm_i_tlbr(&p);
1450 /* Examine entrylo 0 or 1 based on ptr. */ 1852 /* Examine entrylo 0 or 1 based on ptr. */
1451 uasm_i_andi(&p, K0, K1, sizeof(pte_t)); 1853 if (use_bbit_insns()) {
1452 uasm_i_beqz(&p, K0, 8); 1854 uasm_i_bbit0(&p, K1, ilog2(sizeof(pte_t)), 8);
1453 1855 } else {
1856 uasm_i_andi(&p, K0, K1, sizeof(pte_t));
1857 uasm_i_beqz(&p, K0, 8);
1858 }
1454 UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/ 1859 UASM_i_MFC0(&p, K0, C0_ENTRYLO0); /* load it in the delay slot*/
1455 UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */ 1860 UASM_i_MFC0(&p, K0, C0_ENTRYLO1); /* load it if ptr is odd */
1456 /* 1861 /*
1457 * If the entryLo (now in K0) is valid (bit 1), RI or 1862 * If the entryLo (now in K0) is valid (bit 1), RI or
1458 * XI must have triggered it. 1863 * XI must have triggered it.
1459 */ 1864 */
1460 uasm_i_andi(&p, K0, K0, 2); 1865 if (use_bbit_insns()) {
1461 uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2); 1866 uasm_il_bbit0(&p, &r, K0, 1, label_tlbl_goaround2);
1867 } else {
1868 uasm_i_andi(&p, K0, K0, 2);
1869 uasm_il_beqz(&p, &r, K0, label_tlbl_goaround2);
1870 }
1462 /* Reload the PTE value */ 1871 /* Reload the PTE value */
1463 iPTE_LW(&p, K0, K1); 1872 iPTE_LW(&p, K0, K1);
1464 1873
@@ -1466,7 +1875,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
1466 * We clobbered C0_PAGEMASK, restore it. On the other branch 1875 * We clobbered C0_PAGEMASK, restore it. On the other branch
1467 * it is restored in build_huge_tlb_write_entry. 1876 * it is restored in build_huge_tlb_write_entry.
1468 */ 1877 */
1469 build_restore_pagemask(&p, &r, K0, label_nopage_tlbl); 1878 build_restore_pagemask(&p, &r, K0, label_nopage_tlbl, 0);
1470 1879
1471 uasm_l_tlbl_goaround2(&l, p); 1880 uasm_l_tlbl_goaround2(&l, p);
1472 } 1881 }
@@ -1623,13 +2032,16 @@ void __cpuinit build_tlb_refill_handler(void)
1623 break; 2032 break;
1624 2033
1625 default: 2034 default:
1626 build_r4000_tlb_refill_handler();
1627 if (!run_once) { 2035 if (!run_once) {
2036#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
2037 build_r4000_setup_pgd();
2038#endif
1628 build_r4000_tlb_load_handler(); 2039 build_r4000_tlb_load_handler();
1629 build_r4000_tlb_store_handler(); 2040 build_r4000_tlb_store_handler();
1630 build_r4000_tlb_modify_handler(); 2041 build_r4000_tlb_modify_handler();
1631 run_once++; 2042 run_once++;
1632 } 2043 }
2044 build_r4000_tlb_refill_handler();
1633 } 2045 }
1634} 2046}
1635 2047
@@ -1641,4 +2053,8 @@ void __cpuinit flush_tlb_handlers(void)
1641 (unsigned long)handle_tlbs + sizeof(handle_tlbs)); 2053 (unsigned long)handle_tlbs + sizeof(handle_tlbs));
1642 local_flush_icache_range((unsigned long)handle_tlbm, 2054 local_flush_icache_range((unsigned long)handle_tlbm,
1643 (unsigned long)handle_tlbm + sizeof(handle_tlbm)); 2055 (unsigned long)handle_tlbm + sizeof(handle_tlbm));
2056#ifdef CONFIG_MIPS_PGD_C0_CONTEXT
2057 local_flush_icache_range((unsigned long)tlbmiss_handler_setup_pgd,
2058 (unsigned long)tlbmiss_handler_setup_pgd + sizeof(handle_tlbm));
2059#endif
1644} 2060}
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c
index 23afdebc8e5c..5fa185151fc8 100644
--- a/arch/mips/mm/uasm.c
+++ b/arch/mips/mm/uasm.c
@@ -68,7 +68,8 @@ enum opcode {
68 insn_pref, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll, 68 insn_pref, insn_rfe, insn_sc, insn_scd, insn_sd, insn_sll,
69 insn_sra, insn_srl, insn_rotr, insn_subu, insn_sw, insn_tlbp, 69 insn_sra, insn_srl, insn_rotr, insn_subu, insn_sw, insn_tlbp,
70 insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, 70 insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori,
71 insn_dins, insn_syscall, insn_bbit0, insn_bbit1 71 insn_dins, insn_dinsm, insn_syscall, insn_bbit0, insn_bbit1,
72 insn_lwx, insn_ldx
72}; 73};
73 74
74struct insn { 75struct insn {
@@ -142,9 +143,12 @@ static struct insn insn_table[] __uasminitdata = {
142 { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, 143 { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD },
143 { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, 144 { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
144 { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE }, 145 { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE },
146 { insn_dinsm, M(spec3_op, 0, 0, 0, 0, dinsm_op), RS | RT | RD | RE },
145 { insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM}, 147 { insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
146 { insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, 148 { insn_bbit0, M(lwc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
147 { insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM }, 149 { insn_bbit1, M(swc2_op, 0, 0, 0, 0, 0), RS | RT | BIMM },
150 { insn_lwx, M(spec3_op, 0, 0, 0, lwx_op, lx_op), RS | RT | RD },
151 { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
148 { insn_invalid, 0, 0 } 152 { insn_invalid, 0, 0 }
149}; 153};
150 154
@@ -152,91 +156,83 @@ static struct insn insn_table[] __uasminitdata = {
152 156
153static inline __uasminit u32 build_rs(u32 arg) 157static inline __uasminit u32 build_rs(u32 arg)
154{ 158{
155 if (arg & ~RS_MASK) 159 WARN(arg & ~RS_MASK, KERN_WARNING "Micro-assembler field overflow\n");
156 printk(KERN_WARNING "Micro-assembler field overflow\n");
157 160
158 return (arg & RS_MASK) << RS_SH; 161 return (arg & RS_MASK) << RS_SH;
159} 162}
160 163
161static inline __uasminit u32 build_rt(u32 arg) 164static inline __uasminit u32 build_rt(u32 arg)
162{ 165{
163 if (arg & ~RT_MASK) 166 WARN(arg & ~RT_MASK, KERN_WARNING "Micro-assembler field overflow\n");
164 printk(KERN_WARNING "Micro-assembler field overflow\n");
165 167
166 return (arg & RT_MASK) << RT_SH; 168 return (arg & RT_MASK) << RT_SH;
167} 169}
168 170
169static inline __uasminit u32 build_rd(u32 arg) 171static inline __uasminit u32 build_rd(u32 arg)
170{ 172{
171 if (arg & ~RD_MASK) 173 WARN(arg & ~RD_MASK, KERN_WARNING "Micro-assembler field overflow\n");
172 printk(KERN_WARNING "Micro-assembler field overflow\n");
173 174
174 return (arg & RD_MASK) << RD_SH; 175 return (arg & RD_MASK) << RD_SH;
175} 176}
176 177
177static inline __uasminit u32 build_re(u32 arg) 178static inline __uasminit u32 build_re(u32 arg)
178{ 179{
179 if (arg & ~RE_MASK) 180 WARN(arg & ~RE_MASK, KERN_WARNING "Micro-assembler field overflow\n");
180 printk(KERN_WARNING "Micro-assembler field overflow\n");
181 181
182 return (arg & RE_MASK) << RE_SH; 182 return (arg & RE_MASK) << RE_SH;
183} 183}
184 184
185static inline __uasminit u32 build_simm(s32 arg) 185static inline __uasminit u32 build_simm(s32 arg)
186{ 186{
187 if (arg > 0x7fff || arg < -0x8000) 187 WARN(arg > 0x7fff || arg < -0x8000,
188 printk(KERN_WARNING "Micro-assembler field overflow\n"); 188 KERN_WARNING "Micro-assembler field overflow\n");
189 189
190 return arg & 0xffff; 190 return arg & 0xffff;
191} 191}
192 192
193static inline __uasminit u32 build_uimm(u32 arg) 193static inline __uasminit u32 build_uimm(u32 arg)
194{ 194{
195 if (arg & ~IMM_MASK) 195 WARN(arg & ~IMM_MASK, KERN_WARNING "Micro-assembler field overflow\n");
196 printk(KERN_WARNING "Micro-assembler field overflow\n");
197 196
198 return arg & IMM_MASK; 197 return arg & IMM_MASK;
199} 198}
200 199
201static inline __uasminit u32 build_bimm(s32 arg) 200static inline __uasminit u32 build_bimm(s32 arg)
202{ 201{
203 if (arg > 0x1ffff || arg < -0x20000) 202 WARN(arg > 0x1ffff || arg < -0x20000,
204 printk(KERN_WARNING "Micro-assembler field overflow\n"); 203 KERN_WARNING "Micro-assembler field overflow\n");
205 204
206 if (arg & 0x3) 205 WARN(arg & 0x3, KERN_WARNING "Invalid micro-assembler branch target\n");
207 printk(KERN_WARNING "Invalid micro-assembler branch target\n");
208 206
209 return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff); 207 return ((arg < 0) ? (1 << 15) : 0) | ((arg >> 2) & 0x7fff);
210} 208}
211 209
212static inline __uasminit u32 build_jimm(u32 arg) 210static inline __uasminit u32 build_jimm(u32 arg)
213{ 211{
214 if (arg & ~((JIMM_MASK) << 2)) 212 WARN(arg & ~(JIMM_MASK << 2),
215 printk(KERN_WARNING "Micro-assembler field overflow\n"); 213 KERN_WARNING "Micro-assembler field overflow\n");
216 214
217 return (arg >> 2) & JIMM_MASK; 215 return (arg >> 2) & JIMM_MASK;
218} 216}
219 217
220static inline __uasminit u32 build_scimm(u32 arg) 218static inline __uasminit u32 build_scimm(u32 arg)
221{ 219{
222 if (arg & ~SCIMM_MASK) 220 WARN(arg & ~SCIMM_MASK,
223 printk(KERN_WARNING "Micro-assembler field overflow\n"); 221 KERN_WARNING "Micro-assembler field overflow\n");
224 222
225 return (arg & SCIMM_MASK) << SCIMM_SH; 223 return (arg & SCIMM_MASK) << SCIMM_SH;
226} 224}
227 225
228static inline __uasminit u32 build_func(u32 arg) 226static inline __uasminit u32 build_func(u32 arg)
229{ 227{
230 if (arg & ~FUNC_MASK) 228 WARN(arg & ~FUNC_MASK, KERN_WARNING "Micro-assembler field overflow\n");
231 printk(KERN_WARNING "Micro-assembler field overflow\n");
232 229
233 return arg & FUNC_MASK; 230 return arg & FUNC_MASK;
234} 231}
235 232
236static inline __uasminit u32 build_set(u32 arg) 233static inline __uasminit u32 build_set(u32 arg)
237{ 234{
238 if (arg & ~SET_MASK) 235 WARN(arg & ~SET_MASK, KERN_WARNING "Micro-assembler field overflow\n");
239 printk(KERN_WARNING "Micro-assembler field overflow\n");
240 236
241 return arg & SET_MASK; 237 return arg & SET_MASK;
242} 238}
@@ -340,6 +336,13 @@ Ip_u2u1msbu3(op) \
340} \ 336} \
341UASM_EXPORT_SYMBOL(uasm_i##op); 337UASM_EXPORT_SYMBOL(uasm_i##op);
342 338
339#define I_u2u1msb32u3(op) \
340Ip_u2u1msbu3(op) \
341{ \
342 build_insn(buf, insn##op, b, a, c+d-33, c); \
343} \
344UASM_EXPORT_SYMBOL(uasm_i##op);
345
343#define I_u1u2(op) \ 346#define I_u1u2(op) \
344Ip_u1u2(op) \ 347Ip_u1u2(op) \
345{ \ 348{ \
@@ -422,9 +425,12 @@ I_0(_tlbwr)
422I_u3u1u2(_xor) 425I_u3u1u2(_xor)
423I_u2u1u3(_xori) 426I_u2u1u3(_xori)
424I_u2u1msbu3(_dins); 427I_u2u1msbu3(_dins);
428I_u2u1msb32u3(_dinsm);
425I_u1(_syscall); 429I_u1(_syscall);
426I_u1u2s3(_bbit0); 430I_u1u2s3(_bbit0);
427I_u1u2s3(_bbit1); 431I_u1u2s3(_bbit1);
432I_u3u1u2(_lwx)
433I_u3u1u2(_ldx)
428 434
429#ifdef CONFIG_CPU_CAVIUM_OCTEON 435#ifdef CONFIG_CPU_CAVIUM_OCTEON
430#include <asm/octeon/octeon.h> 436#include <asm/octeon/octeon.h>
diff --git a/arch/mips/sibyte/common/sb_tbprof.c b/arch/mips/sibyte/common/sb_tbprof.c
index 87ccdb4b5ac9..48853ab5bcf0 100644
--- a/arch/mips/sibyte/common/sb_tbprof.c
+++ b/arch/mips/sibyte/common/sb_tbprof.c
@@ -410,14 +410,13 @@ static int sbprof_tb_open(struct inode *inode, struct file *filp)
410 return -EBUSY; 410 return -EBUSY;
411 411
412 memset(&sbp, 0, sizeof(struct sbprof_tb)); 412 memset(&sbp, 0, sizeof(struct sbprof_tb));
413 sbp.sbprof_tbbuf = vmalloc(MAX_TBSAMPLE_BYTES); 413 sbp.sbprof_tbbuf = vzalloc(MAX_TBSAMPLE_BYTES);
414 if (!sbp.sbprof_tbbuf) { 414 if (!sbp.sbprof_tbbuf) {
415 sbp.open = SB_CLOSED; 415 sbp.open = SB_CLOSED;
416 wmb(); 416 wmb();
417 return -ENOMEM; 417 return -ENOMEM;
418 } 418 }
419 419
420 memset(sbp.sbprof_tbbuf, 0, MAX_TBSAMPLE_BYTES);
421 init_waitqueue_head(&sbp.tb_sync); 420 init_waitqueue_head(&sbp.tb_sync);
422 init_waitqueue_head(&sbp.tb_read); 421 init_waitqueue_head(&sbp.tb_read);
423 mutex_init(&sbp.lock); 422 mutex_init(&sbp.lock);
diff --git a/arch/mips/txx9/generic/pci.c b/arch/mips/txx9/generic/pci.c
index 96e69a00ffc8..85a87de17eb4 100644
--- a/arch/mips/txx9/generic/pci.c
+++ b/arch/mips/txx9/generic/pci.c
@@ -213,11 +213,8 @@ txx9_alloc_pci_controller(struct pci_controller *pcic,
213 213
214 pcic->mem_offset = 0; /* busaddr == physaddr */ 214 pcic->mem_offset = 0; /* busaddr == physaddr */
215 215
216 printk(KERN_INFO "PCI: IO 0x%08llx-0x%08llx MEM 0x%08llx-0x%08llx\n", 216 printk(KERN_INFO "PCI: IO %pR MEM %pR\n",
217 (unsigned long long)pcic->mem_resource[1].start, 217 &pcic->mem_resource[1], &pcic->mem_resource[0]);
218 (unsigned long long)pcic->mem_resource[1].end,
219 (unsigned long long)pcic->mem_resource[0].start,
220 (unsigned long long)pcic->mem_resource[0].end);
221 218
222 /* register_pci_controller() will request MEM resource */ 219 /* register_pci_controller() will request MEM resource */
223 release_resource(&pcic->mem_resource[0]); 220 release_resource(&pcic->mem_resource[0]);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 13bfa9d48082..bb233a9cbad2 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -53,6 +53,14 @@ if SPI_MASTER
53 53
54comment "SPI Master Controller Drivers" 54comment "SPI Master Controller Drivers"
55 55
56config SPI_ATH79
57 tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver"
58 depends on ATH79 && GENERIC_GPIO
59 select SPI_BITBANG
60 help
61 This enables support for the SPI controller present on the
62 Atheros AR71XX/AR724X/AR913X SoCs.
63
56config SPI_ATMEL 64config SPI_ATMEL
57 tristate "Atmel SPI Controller" 65 tristate "Atmel SPI Controller"
58 depends on (ARCH_AT91 || AVR32) 66 depends on (ARCH_AT91 || AVR32)
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 3a42463c92a4..86d1b5f9bbd9 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_SPI_MASTER) += spi.o
10 10
11# SPI master controller drivers (bus) 11# SPI master controller drivers (bus)
12obj-$(CONFIG_SPI_ATMEL) += atmel_spi.o 12obj-$(CONFIG_SPI_ATMEL) += atmel_spi.o
13obj-$(CONFIG_SPI_ATH79) += ath79_spi.o
13obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.o 14obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.o
14obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o 15obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
15obj-$(CONFIG_SPI_AU1550) += au1550_spi.o 16obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c
new file mode 100644
index 000000000000..fcff810ea3b0
--- /dev/null
+++ b/drivers/spi/ath79_spi.c
@@ -0,0 +1,292 @@
1/*
2 * SPI controller driver for the Atheros AR71XX/AR724X/AR913X SoCs
3 *
4 * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org>
5 *
6 * This driver has been based on the spi-gpio.c:
7 * Copyright (C) 2006,2008 David Brownell
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 */
14
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/delay.h>
18#include <linux/spinlock.h>
19#include <linux/workqueue.h>
20#include <linux/platform_device.h>
21#include <linux/io.h>
22#include <linux/spi/spi.h>
23#include <linux/spi/spi_bitbang.h>
24#include <linux/bitops.h>
25#include <linux/gpio.h>
26
27#include <asm/mach-ath79/ar71xx_regs.h>
28#include <asm/mach-ath79/ath79_spi_platform.h>
29
30#define DRV_NAME "ath79-spi"
31
32struct ath79_spi {
33 struct spi_bitbang bitbang;
34 u32 ioc_base;
35 u32 reg_ctrl;
36 void __iomem *base;
37};
38
39static inline u32 ath79_spi_rr(struct ath79_spi *sp, unsigned reg)
40{
41 return ioread32(sp->base + reg);
42}
43
44static inline void ath79_spi_wr(struct ath79_spi *sp, unsigned reg, u32 val)
45{
46 iowrite32(val, sp->base + reg);
47}
48
49static inline struct ath79_spi *ath79_spidev_to_sp(struct spi_device *spi)
50{
51 return spi_master_get_devdata(spi->master);
52}
53
54static void ath79_spi_chipselect(struct spi_device *spi, int is_active)
55{
56 struct ath79_spi *sp = ath79_spidev_to_sp(spi);
57 int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active;
58
59 if (is_active) {
60 /* set initial clock polarity */
61 if (spi->mode & SPI_CPOL)
62 sp->ioc_base |= AR71XX_SPI_IOC_CLK;
63 else
64 sp->ioc_base &= ~AR71XX_SPI_IOC_CLK;
65
66 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
67 }
68
69 if (spi->chip_select) {
70 struct ath79_spi_controller_data *cdata = spi->controller_data;
71
72 /* SPI is normally active-low */
73 gpio_set_value(cdata->gpio, cs_high);
74 } else {
75 if (cs_high)
76 sp->ioc_base |= AR71XX_SPI_IOC_CS0;
77 else
78 sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
79
80 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
81 }
82
83}
84
85static int ath79_spi_setup_cs(struct spi_device *spi)
86{
87 struct ath79_spi *sp = ath79_spidev_to_sp(spi);
88 struct ath79_spi_controller_data *cdata;
89
90 cdata = spi->controller_data;
91 if (spi->chip_select && !cdata)
92 return -EINVAL;
93
94 /* enable GPIO mode */
95 ath79_spi_wr(sp, AR71XX_SPI_REG_FS, AR71XX_SPI_FS_GPIO);
96
97 /* save CTRL register */
98 sp->reg_ctrl = ath79_spi_rr(sp, AR71XX_SPI_REG_CTRL);
99 sp->ioc_base = ath79_spi_rr(sp, AR71XX_SPI_REG_IOC);
100
101 /* TODO: setup speed? */
102 ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, 0x43);
103
104 if (spi->chip_select) {
105 int status = 0;
106
107 status = gpio_request(cdata->gpio, dev_name(&spi->dev));
108 if (status)
109 return status;
110
111 status = gpio_direction_output(cdata->gpio,
112 spi->mode & SPI_CS_HIGH);
113 if (status) {
114 gpio_free(cdata->gpio);
115 return status;
116 }
117 } else {
118 if (spi->mode & SPI_CS_HIGH)
119 sp->ioc_base |= AR71XX_SPI_IOC_CS0;
120 else
121 sp->ioc_base &= ~AR71XX_SPI_IOC_CS0;
122 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, sp->ioc_base);
123 }
124
125 return 0;
126}
127
128static void ath79_spi_cleanup_cs(struct spi_device *spi)
129{
130 struct ath79_spi *sp = ath79_spidev_to_sp(spi);
131
132 if (spi->chip_select) {
133 struct ath79_spi_controller_data *cdata = spi->controller_data;
134 gpio_free(cdata->gpio);
135 }
136
137 /* restore CTRL register */
138 ath79_spi_wr(sp, AR71XX_SPI_REG_CTRL, sp->reg_ctrl);
139 /* disable GPIO mode */
140 ath79_spi_wr(sp, AR71XX_SPI_REG_FS, 0);
141}
142
143static int ath79_spi_setup(struct spi_device *spi)
144{
145 int status = 0;
146
147 if (spi->bits_per_word > 32)
148 return -EINVAL;
149
150 if (!spi->controller_state) {
151 status = ath79_spi_setup_cs(spi);
152 if (status)
153 return status;
154 }
155
156 status = spi_bitbang_setup(spi);
157 if (status && !spi->controller_state)
158 ath79_spi_cleanup_cs(spi);
159
160 return status;
161}
162
163static void ath79_spi_cleanup(struct spi_device *spi)
164{
165 ath79_spi_cleanup_cs(spi);
166 spi_bitbang_cleanup(spi);
167}
168
169static u32 ath79_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs,
170 u32 word, u8 bits)
171{
172 struct ath79_spi *sp = ath79_spidev_to_sp(spi);
173 u32 ioc = sp->ioc_base;
174
175 /* clock starts at inactive polarity */
176 for (word <<= (32 - bits); likely(bits); bits--) {
177 u32 out;
178
179 if (word & (1 << 31))
180 out = ioc | AR71XX_SPI_IOC_DO;
181 else
182 out = ioc & ~AR71XX_SPI_IOC_DO;
183
184 /* setup MSB (to slave) on trailing edge */
185 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out);
186 ath79_spi_wr(sp, AR71XX_SPI_REG_IOC, out | AR71XX_SPI_IOC_CLK);
187
188 word <<= 1;
189 }
190
191 return ath79_spi_rr(sp, AR71XX_SPI_REG_RDS);
192}
193
194static __devinit int ath79_spi_probe(struct platform_device *pdev)
195{
196 struct spi_master *master;
197 struct ath79_spi *sp;
198 struct ath79_spi_platform_data *pdata;
199 struct resource *r;
200 int ret;
201
202 master = spi_alloc_master(&pdev->dev, sizeof(*sp));
203 if (master == NULL) {
204 dev_err(&pdev->dev, "failed to allocate spi master\n");
205 return -ENOMEM;
206 }
207
208 sp = spi_master_get_devdata(master);
209 platform_set_drvdata(pdev, sp);
210
211 pdata = pdev->dev.platform_data;
212
213 master->setup = ath79_spi_setup;
214 master->cleanup = ath79_spi_cleanup;
215 if (pdata) {
216 master->bus_num = pdata->bus_num;
217 master->num_chipselect = pdata->num_chipselect;
218 } else {
219 master->bus_num = -1;
220 master->num_chipselect = 1;
221 }
222
223 sp->bitbang.master = spi_master_get(master);
224 sp->bitbang.chipselect = ath79_spi_chipselect;
225 sp->bitbang.txrx_word[SPI_MODE_0] = ath79_spi_txrx_mode0;
226 sp->bitbang.setup_transfer = spi_bitbang_setup_transfer;
227 sp->bitbang.flags = SPI_CS_HIGH;
228
229 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
230 if (r == NULL) {
231 ret = -ENOENT;
232 goto err_put_master;
233 }
234
235 sp->base = ioremap(r->start, r->end - r->start + 1);
236 if (!sp->base) {
237 ret = -ENXIO;
238 goto err_put_master;
239 }
240
241 ret = spi_bitbang_start(&sp->bitbang);
242 if (ret)
243 goto err_unmap;
244
245 return 0;
246
247err_unmap:
248 iounmap(sp->base);
249err_put_master:
250 platform_set_drvdata(pdev, NULL);
251 spi_master_put(sp->bitbang.master);
252
253 return ret;
254}
255
256static __devexit int ath79_spi_remove(struct platform_device *pdev)
257{
258 struct ath79_spi *sp = platform_get_drvdata(pdev);
259
260 spi_bitbang_stop(&sp->bitbang);
261 iounmap(sp->base);
262 platform_set_drvdata(pdev, NULL);
263 spi_master_put(sp->bitbang.master);
264
265 return 0;
266}
267
268static struct platform_driver ath79_spi_driver = {
269 .probe = ath79_spi_probe,
270 .remove = __devexit_p(ath79_spi_remove),
271 .driver = {
272 .name = DRV_NAME,
273 .owner = THIS_MODULE,
274 },
275};
276
277static __init int ath79_spi_init(void)
278{
279 return platform_driver_register(&ath79_spi_driver);
280}
281module_init(ath79_spi_init);
282
283static __exit void ath79_spi_exit(void)
284{
285 platform_driver_unregister(&ath79_spi_driver);
286}
287module_exit(ath79_spi_exit);
288
289MODULE_DESCRIPTION("SPI controller driver for Atheros AR71XX/AR724X/AR913X");
290MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
291MODULE_LICENSE("GPL v2");
292MODULE_ALIAS("platform:" DRV_NAME);