aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-orion5x
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@wantstofly.org>2008-03-27 14:51:41 -0400
committerNicolas Pitre <nico@marvell.com>2008-03-27 14:51:41 -0400
commit9dd0b194bf6804b1998f0fe261b2606ec7b58d72 (patch)
treec9fd5ab51dc256818c24a8a771dc068d021039e2 /arch/arm/mach-orion5x
parent159ffb3a04f6bc619643af680df406faafd0199d (diff)
Orion: orion -> orion5x rename
Do a global s/orion/orion5x/ of the Orion 5x-specific bits (i.e. not the plat-orion bits.) Signed-off-by: Lennert Buytenhek <buytenh@marvell.com> Reviewed-by: Tzachi Perelstein <tzachi@marvell.com> Acked-by: Saeed Bishara <saeed@marvell.com> Acked-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Nicolas Pitre <nico@marvell.com>
Diffstat (limited to 'arch/arm/mach-orion5x')
-rw-r--r--arch/arm/mach-orion5x/Kconfig41
-rw-r--r--arch/arm/mach-orion5x/Makefile6
-rw-r--r--arch/arm/mach-orion5x/Makefile.boot3
-rw-r--r--arch/arm/mach-orion5x/addr-map.c240
-rw-r--r--arch/arm/mach-orion5x/common.c391
-rw-r--r--arch/arm/mach-orion5x/common.h72
-rw-r--r--arch/arm/mach-orion5x/db88f5281-setup.c361
-rw-r--r--arch/arm/mach-orion5x/dns323-setup.c320
-rw-r--r--arch/arm/mach-orion5x/gpio.c226
-rw-r--r--arch/arm/mach-orion5x/irq.c211
-rw-r--r--arch/arm/mach-orion5x/kurobox_pro-setup.c243
-rw-r--r--arch/arm/mach-orion5x/pci.c559
-rw-r--r--arch/arm/mach-orion5x/rd88f5182-setup.c312
-rw-r--r--arch/arm/mach-orion5x/ts209-setup.c359
14 files changed, 3344 insertions, 0 deletions
diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig
new file mode 100644
index 00000000000..01c66957d8f
--- /dev/null
+++ b/arch/arm/mach-orion5x/Kconfig
@@ -0,0 +1,41 @@
1if ARCH_ORION5X
2
3menu "Orion Implementations"
4
5config MACH_DB88F5281
6 bool "Marvell Orion-2 Development Board"
7 select I2C_BOARDINFO
8 help
9 Say 'Y' here if you want your kernel to support the
10 Marvell Orion-2 (88F5281) Development Board
11
12config MACH_RD88F5182
13 bool "Marvell Orion-NAS Reference Design"
14 select I2C_BOARDINFO
15 help
16 Say 'Y' here if you want your kernel to support the
17 Marvell Orion-NAS (88F5182) RD2
18
19config MACH_KUROBOX_PRO
20 bool "KuroBox Pro"
21 select I2C_BOARDINFO
22 help
23 Say 'Y' here if you want your kernel to support the
24 KuroBox Pro platform.
25
26config MACH_DNS323
27 bool "D-Link DNS-323"
28 select I2C_BOARDINFO
29 help
30 Say 'Y' here if you want your kernel to support the
31 D-Link DNS-323 platform.
32
33config MACH_TS209
34 bool "QNAP TS-109/TS-209"
35 help
36 Say 'Y' here if you want your kernel to support the
37 QNAP TS-109/TS-209 platform.
38
39endmenu
40
41endif
diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile
new file mode 100644
index 00000000000..d894caa5060
--- /dev/null
+++ b/arch/arm/mach-orion5x/Makefile
@@ -0,0 +1,6 @@
1obj-y += common.o addr-map.o pci.o gpio.o irq.o
2obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o
3obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o
4obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o
5obj-$(CONFIG_MACH_DNS323) += dns323-setup.o
6obj-$(CONFIG_MACH_TS209) += ts209-setup.o
diff --git a/arch/arm/mach-orion5x/Makefile.boot b/arch/arm/mach-orion5x/Makefile.boot
new file mode 100644
index 00000000000..67039c3e0c4
--- /dev/null
+++ b/arch/arm/mach-orion5x/Makefile.boot
@@ -0,0 +1,3 @@
1 zreladdr-y := 0x00008000
2params_phys-y := 0x00000100
3initrd_phys-y := 0x00800000
diff --git a/arch/arm/mach-orion5x/addr-map.c b/arch/arm/mach-orion5x/addr-map.c
new file mode 100644
index 00000000000..6b179371e0a
--- /dev/null
+++ b/arch/arm/mach-orion5x/addr-map.c
@@ -0,0 +1,240 @@
1/*
2 * arch/arm/mach-orion5x/addr-map.c
3 *
4 * Address map functions for Marvell Orion 5x SoCs
5 *
6 * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/mbus.h>
16#include <asm/hardware.h>
17#include <asm/io.h>
18#include "common.h"
19
20/*
21 * The Orion has fully programable address map. There's a separate address
22 * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIE, USB,
23 * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own
24 * address decode windows that allow it to access any of the Orion resources.
25 *
26 * CPU address decoding --
27 * Linux assumes that it is the boot loader that already setup the access to
28 * DDR and internal registers.
29 * Setup access to PCI and PCI-E IO/MEM space is issued by this file.
30 * Setup access to various devices located on the device bus interface (e.g.
31 * flashes, RTC, etc) should be issued by machine-setup.c according to
32 * specific board population (by using orion5x_setup_*_win()).
33 *
34 * Non-CPU Masters address decoding --
35 * Unlike the CPU, we setup the access from Orion's master interfaces to DDR
36 * banks only (the typical use case).
37 * Setup access for each master to DDR is issued by common.c.
38 *
39 * Note: although orion_setbits() and orion_clrbits() are not atomic
40 * no locking is necessary here since code in this file is only called
41 * at boot time when there is no concurrency issues.
42 */
43
44/*
45 * Generic Address Decode Windows bit settings
46 */
47#define TARGET_DDR 0
48#define TARGET_DEV_BUS 1
49#define TARGET_PCI 3
50#define TARGET_PCIE 4
51#define ATTR_DDR_CS(n) (((n) ==0) ? 0xe : \
52 ((n) == 1) ? 0xd : \
53 ((n) == 2) ? 0xb : \
54 ((n) == 3) ? 0x7 : 0xf)
55#define ATTR_PCIE_MEM 0x59
56#define ATTR_PCIE_IO 0x51
57#define ATTR_PCIE_WA 0x79
58#define ATTR_PCI_MEM 0x59
59#define ATTR_PCI_IO 0x51
60#define ATTR_DEV_CS0 0x1e
61#define ATTR_DEV_CS1 0x1d
62#define ATTR_DEV_CS2 0x1b
63#define ATTR_DEV_BOOT 0xf
64#define WIN_EN 1
65
66/*
67 * Helpers to get DDR bank info
68 */
69#define DDR_BASE_CS(n) ORION5X_DDR_REG(0x1500 + ((n) * 8))
70#define DDR_SIZE_CS(n) ORION5X_DDR_REG(0x1504 + ((n) * 8))
71#define DDR_MAX_CS 4
72#define DDR_REG_TO_SIZE(reg) (((reg) | 0xffffff) + 1)
73#define DDR_REG_TO_BASE(reg) ((reg) & 0xff000000)
74#define DDR_BANK_EN 1
75
76/*
77 * CPU Address Decode Windows registers
78 */
79#define CPU_WIN_CTRL(n) ORION5X_BRIDGE_REG(0x000 | ((n) << 4))
80#define CPU_WIN_BASE(n) ORION5X_BRIDGE_REG(0x004 | ((n) << 4))
81#define CPU_WIN_REMAP_LO(n) ORION5X_BRIDGE_REG(0x008 | ((n) << 4))
82#define CPU_WIN_REMAP_HI(n) ORION5X_BRIDGE_REG(0x00c | ((n) << 4))
83
84/*
85 * Gigabit Ethernet Address Decode Windows registers
86 */
87#define ETH_WIN_BASE(win) ORION5X_ETH_REG(0x200 + ((win) * 8))
88#define ETH_WIN_SIZE(win) ORION5X_ETH_REG(0x204 + ((win) * 8))
89#define ETH_WIN_REMAP(win) ORION5X_ETH_REG(0x280 + ((win) * 4))
90#define ETH_WIN_EN ORION5X_ETH_REG(0x290)
91#define ETH_WIN_PROT ORION5X_ETH_REG(0x294)
92#define ETH_MAX_WIN 6
93#define ETH_MAX_REMAP_WIN 4
94
95
96struct mbus_dram_target_info orion5x_mbus_dram_info;
97
98static int __init orion5x_cpu_win_can_remap(int win)
99{
100 u32 dev, rev;
101
102 orion5x_pcie_id(&dev, &rev);
103 if ((dev == MV88F5281_DEV_ID && win < 4)
104 || (dev == MV88F5182_DEV_ID && win < 2)
105 || (dev == MV88F5181_DEV_ID && win < 2))
106 return 1;
107
108 return 0;
109}
110
111static void __init setup_cpu_win(int win, u32 base, u32 size,
112 u8 target, u8 attr, int remap)
113{
114 orion5x_write(CPU_WIN_BASE(win), base & 0xffff0000);
115 orion5x_write(CPU_WIN_CTRL(win),
116 ((size - 1) & 0xffff0000) | (attr << 8) | (target << 4) | 1);
117
118 if (orion5x_cpu_win_can_remap(win)) {
119 if (remap < 0)
120 remap = base;
121
122 orion5x_write(CPU_WIN_REMAP_LO(win), remap & 0xffff0000);
123 orion5x_write(CPU_WIN_REMAP_HI(win), 0);
124 }
125}
126
127void __init orion5x_setup_cpu_mbus_bridge(void)
128{
129 int i;
130 int cs;
131
132 /*
133 * First, disable and clear windows.
134 */
135 for (i = 0; i < 8; i++) {
136 orion5x_write(CPU_WIN_BASE(i), 0);
137 orion5x_write(CPU_WIN_CTRL(i), 0);
138 if (orion5x_cpu_win_can_remap(i)) {
139 orion5x_write(CPU_WIN_REMAP_LO(i), 0);
140 orion5x_write(CPU_WIN_REMAP_HI(i), 0);
141 }
142 }
143
144 /*
145 * Setup windows for PCI+PCIe IO+MEM space.
146 */
147 setup_cpu_win(0, ORION5X_PCIE_IO_PHYS_BASE, ORION5X_PCIE_IO_SIZE,
148 TARGET_PCIE, ATTR_PCIE_IO, ORION5X_PCIE_IO_BUS_BASE);
149 setup_cpu_win(1, ORION5X_PCI_IO_PHYS_BASE, ORION5X_PCI_IO_SIZE,
150 TARGET_PCI, ATTR_PCI_IO, ORION5X_PCI_IO_BUS_BASE);
151 setup_cpu_win(2, ORION5X_PCIE_MEM_PHYS_BASE, ORION5X_PCIE_MEM_SIZE,
152 TARGET_PCIE, ATTR_PCIE_MEM, -1);
153 setup_cpu_win(3, ORION5X_PCI_MEM_PHYS_BASE, ORION5X_PCI_MEM_SIZE,
154 TARGET_PCI, ATTR_PCI_MEM, -1);
155
156 /*
157 * Setup MBUS dram target info.
158 */
159 orion5x_mbus_dram_info.mbus_dram_target_id = TARGET_DDR;
160
161 for (i = 0, cs = 0; i < 4; i++) {
162 u32 base = readl(DDR_BASE_CS(i));
163 u32 size = readl(DDR_SIZE_CS(i));
164
165 /*
166 * Chip select enabled?
167 */
168 if (size & 1) {
169 struct mbus_dram_window *w;
170
171 w = &orion5x_mbus_dram_info.cs[cs++];
172 w->cs_index = i;
173 w->mbus_attr = 0xf & ~(1 << i);
174 w->base = base & 0xff000000;
175 w->size = (size | 0x00ffffff) + 1;
176 }
177 }
178 orion5x_mbus_dram_info.num_cs = cs;
179}
180
181void __init orion5x_setup_dev_boot_win(u32 base, u32 size)
182{
183 setup_cpu_win(4, base, size, TARGET_DEV_BUS, ATTR_DEV_BOOT, -1);
184}
185
186void __init orion5x_setup_dev0_win(u32 base, u32 size)
187{
188 setup_cpu_win(5, base, size, TARGET_DEV_BUS, ATTR_DEV_CS0, -1);
189}
190
191void __init orion5x_setup_dev1_win(u32 base, u32 size)
192{
193 setup_cpu_win(6, base, size, TARGET_DEV_BUS, ATTR_DEV_CS1, -1);
194}
195
196void __init orion5x_setup_dev2_win(u32 base, u32 size)
197{
198 setup_cpu_win(7, base, size, TARGET_DEV_BUS, ATTR_DEV_CS2, -1);
199}
200
201void __init orion5x_setup_pcie_wa_win(u32 base, u32 size)
202{
203 setup_cpu_win(7, base, size, TARGET_PCIE, ATTR_PCIE_WA, -1);
204}
205
206void __init orion5x_setup_eth_wins(void)
207{
208 int i;
209
210 /*
211 * First, disable and clear windows
212 */
213 for (i = 0; i < ETH_MAX_WIN; i++) {
214 orion5x_write(ETH_WIN_BASE(i), 0);
215 orion5x_write(ETH_WIN_SIZE(i), 0);
216 orion5x_setbits(ETH_WIN_EN, 1 << i);
217 orion5x_clrbits(ETH_WIN_PROT, 0x3 << (i * 2));
218 if (i < ETH_MAX_REMAP_WIN)
219 orion5x_write(ETH_WIN_REMAP(i), 0);
220 }
221
222 /*
223 * Setup windows for DDR banks.
224 */
225 for (i = 0; i < DDR_MAX_CS; i++) {
226 u32 base, size;
227 size = orion5x_read(DDR_SIZE_CS(i));
228 base = orion5x_read(DDR_BASE_CS(i));
229 if (size & DDR_BANK_EN) {
230 base = DDR_REG_TO_BASE(base);
231 size = DDR_REG_TO_SIZE(size);
232 orion5x_write(ETH_WIN_SIZE(i), (size-1) & 0xffff0000);
233 orion5x_write(ETH_WIN_BASE(i), (base & 0xffff0000) |
234 (ATTR_DDR_CS(i) << 8) |
235 TARGET_DDR);
236 orion5x_clrbits(ETH_WIN_EN, 1 << i);
237 orion5x_setbits(ETH_WIN_PROT, 0x3 << (i * 2));
238 }
239 }
240}
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
new file mode 100644
index 00000000000..439c7784af0
--- /dev/null
+++ b/arch/arm/mach-orion5x/common.c
@@ -0,0 +1,391 @@
1/*
2 * arch/arm/mach-orion5x/common.c
3 *
4 * Core functions for Marvell Orion 5x SoCs
5 *
6 * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/serial_8250.h>
17#include <linux/mbus.h>
18#include <linux/mv643xx_eth.h>
19#include <linux/mv643xx_i2c.h>
20#include <linux/ata_platform.h>
21#include <asm/page.h>
22#include <asm/setup.h>
23#include <asm/timex.h>
24#include <asm/mach/arch.h>
25#include <asm/mach/map.h>
26#include <asm/mach/time.h>
27#include <asm/arch/hardware.h>
28#include <asm/arch/orion5x.h>
29#include <asm/plat-orion/ehci-orion.h>
30#include <asm/plat-orion/orion_nand.h>
31#include <asm/plat-orion/time.h>
32#include "common.h"
33
34/*****************************************************************************
35 * I/O Address Mapping
36 ****************************************************************************/
37static struct map_desc orion5x_io_desc[] __initdata = {
38 {
39 .virtual = ORION5X_REGS_VIRT_BASE,
40 .pfn = __phys_to_pfn(ORION5X_REGS_PHYS_BASE),
41 .length = ORION5X_REGS_SIZE,
42 .type = MT_DEVICE
43 },
44 {
45 .virtual = ORION5X_PCIE_IO_VIRT_BASE,
46 .pfn = __phys_to_pfn(ORION5X_PCIE_IO_PHYS_BASE),
47 .length = ORION5X_PCIE_IO_SIZE,
48 .type = MT_DEVICE
49 },
50 {
51 .virtual = ORION5X_PCI_IO_VIRT_BASE,
52 .pfn = __phys_to_pfn(ORION5X_PCI_IO_PHYS_BASE),
53 .length = ORION5X_PCI_IO_SIZE,
54 .type = MT_DEVICE
55 },
56 {
57 .virtual = ORION5X_PCIE_WA_VIRT_BASE,
58 .pfn = __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE),
59 .length = ORION5X_PCIE_WA_SIZE,
60 .type = MT_DEVICE
61 },
62};
63
64void __init orion5x_map_io(void)
65{
66 iotable_init(orion5x_io_desc, ARRAY_SIZE(orion5x_io_desc));
67}
68
69/*****************************************************************************
70 * UART
71 ****************************************************************************/
72
73static struct resource orion5x_uart_resources[] = {
74 {
75 .start = UART0_PHYS_BASE,
76 .end = UART0_PHYS_BASE + 0xff,
77 .flags = IORESOURCE_MEM,
78 },
79 {
80 .start = IRQ_ORION5X_UART0,
81 .end = IRQ_ORION5X_UART0,
82 .flags = IORESOURCE_IRQ,
83 },
84 {
85 .start = UART1_PHYS_BASE,
86 .end = UART1_PHYS_BASE + 0xff,
87 .flags = IORESOURCE_MEM,
88 },
89 {
90 .start = IRQ_ORION5X_UART1,
91 .end = IRQ_ORION5X_UART1,
92 .flags = IORESOURCE_IRQ,
93 },
94};
95
96static struct plat_serial8250_port orion5x_uart_data[] = {
97 {
98 .mapbase = UART0_PHYS_BASE,
99 .membase = (char *)UART0_VIRT_BASE,
100 .irq = IRQ_ORION5X_UART0,
101 .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
102 .iotype = UPIO_MEM,
103 .regshift = 2,
104 .uartclk = ORION5X_TCLK,
105 },
106 {
107 .mapbase = UART1_PHYS_BASE,
108 .membase = (char *)UART1_VIRT_BASE,
109 .irq = IRQ_ORION5X_UART1,
110 .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
111 .iotype = UPIO_MEM,
112 .regshift = 2,
113 .uartclk = ORION5X_TCLK,
114 },
115 { },
116};
117
118static struct platform_device orion5x_uart = {
119 .name = "serial8250",
120 .id = PLAT8250_DEV_PLATFORM,
121 .dev = {
122 .platform_data = orion5x_uart_data,
123 },
124 .resource = orion5x_uart_resources,
125 .num_resources = ARRAY_SIZE(orion5x_uart_resources),
126};
127
128/*******************************************************************************
129 * USB Controller - 2 interfaces
130 ******************************************************************************/
131
132static struct resource orion5x_ehci0_resources[] = {
133 {
134 .start = ORION5X_USB0_PHYS_BASE,
135 .end = ORION5X_USB0_PHYS_BASE + SZ_4K,
136 .flags = IORESOURCE_MEM,
137 },
138 {
139 .start = IRQ_ORION5X_USB0_CTRL,
140 .end = IRQ_ORION5X_USB0_CTRL,
141 .flags = IORESOURCE_IRQ,
142 },
143};
144
145static struct resource orion5x_ehci1_resources[] = {
146 {
147 .start = ORION5X_USB1_PHYS_BASE,
148 .end = ORION5X_USB1_PHYS_BASE + SZ_4K,
149 .flags = IORESOURCE_MEM,
150 },
151 {
152 .start = IRQ_ORION5X_USB1_CTRL,
153 .end = IRQ_ORION5X_USB1_CTRL,
154 .flags = IORESOURCE_IRQ,
155 },
156};
157
158static struct orion_ehci_data orion5x_ehci_data = {
159 .dram = &orion5x_mbus_dram_info,
160};
161
162static u64 ehci_dmamask = 0xffffffffUL;
163
164static struct platform_device orion5x_ehci0 = {
165 .name = "orion-ehci",
166 .id = 0,
167 .dev = {
168 .dma_mask = &ehci_dmamask,
169 .coherent_dma_mask = 0xffffffff,
170 .platform_data = &orion5x_ehci_data,
171 },
172 .resource = orion5x_ehci0_resources,
173 .num_resources = ARRAY_SIZE(orion5x_ehci0_resources),
174};
175
176static struct platform_device orion5x_ehci1 = {
177 .name = "orion-ehci",
178 .id = 1,
179 .dev = {
180 .dma_mask = &ehci_dmamask,
181 .coherent_dma_mask = 0xffffffff,
182 .platform_data = &orion5x_ehci_data,
183 },
184 .resource = orion5x_ehci1_resources,
185 .num_resources = ARRAY_SIZE(orion5x_ehci1_resources),
186};
187
188/*****************************************************************************
189 * Gigabit Ethernet port
190 * (The Orion and Discovery (MV643xx) families use the same Ethernet driver)
191 ****************************************************************************/
192
193static struct resource orion5x_eth_shared_resources[] = {
194 {
195 .start = ORION5X_ETH_PHYS_BASE + 0x2000,
196 .end = ORION5X_ETH_PHYS_BASE + 0x3fff,
197 .flags = IORESOURCE_MEM,
198 },
199};
200
201static struct platform_device orion5x_eth_shared = {
202 .name = MV643XX_ETH_SHARED_NAME,
203 .id = 0,
204 .num_resources = 1,
205 .resource = orion5x_eth_shared_resources,
206};
207
208static struct resource orion5x_eth_resources[] = {
209 {
210 .name = "eth irq",
211 .start = IRQ_ORION5X_ETH_SUM,
212 .end = IRQ_ORION5X_ETH_SUM,
213 .flags = IORESOURCE_IRQ,
214 }
215};
216
217static struct platform_device orion5x_eth = {
218 .name = MV643XX_ETH_NAME,
219 .id = 0,
220 .num_resources = 1,
221 .resource = orion5x_eth_resources,
222};
223
224void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
225{
226 orion5x_eth.dev.platform_data = eth_data;
227 platform_device_register(&orion5x_eth_shared);
228 platform_device_register(&orion5x_eth);
229}
230
231/*****************************************************************************
232 * I2C controller
233 * (The Orion and Discovery (MV643xx) families share the same I2C controller)
234 ****************************************************************************/
235
236static struct mv64xxx_i2c_pdata orion5x_i2c_pdata = {
237 .freq_m = 8, /* assumes 166 MHz TCLK */
238 .freq_n = 3,
239 .timeout = 1000, /* Default timeout of 1 second */
240};
241
242static struct resource orion5x_i2c_resources[] = {
243 {
244 .name = "i2c base",
245 .start = I2C_PHYS_BASE,
246 .end = I2C_PHYS_BASE + 0x20 -1,
247 .flags = IORESOURCE_MEM,
248 },
249 {
250 .name = "i2c irq",
251 .start = IRQ_ORION5X_I2C,
252 .end = IRQ_ORION5X_I2C,
253 .flags = IORESOURCE_IRQ,
254 },
255};
256
257static struct platform_device orion5x_i2c = {
258 .name = MV64XXX_I2C_CTLR_NAME,
259 .id = 0,
260 .num_resources = ARRAY_SIZE(orion5x_i2c_resources),
261 .resource = orion5x_i2c_resources,
262 .dev = {
263 .platform_data = &orion5x_i2c_pdata,
264 },
265};
266
267/*****************************************************************************
268 * Sata port
269 ****************************************************************************/
270static struct resource orion5x_sata_resources[] = {
271 {
272 .name = "sata base",
273 .start = ORION5X_SATA_PHYS_BASE,
274 .end = ORION5X_SATA_PHYS_BASE + 0x5000 - 1,
275 .flags = IORESOURCE_MEM,
276 },
277 {
278 .name = "sata irq",
279 .start = IRQ_ORION5X_SATA,
280 .end = IRQ_ORION5X_SATA,
281 .flags = IORESOURCE_IRQ,
282 },
283};
284
285static struct platform_device orion5x_sata = {
286 .name = "sata_mv",
287 .id = 0,
288 .dev = {
289 .coherent_dma_mask = 0xffffffff,
290 },
291 .num_resources = ARRAY_SIZE(orion5x_sata_resources),
292 .resource = orion5x_sata_resources,
293};
294
295void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data)
296{
297 sata_data->dram = &orion5x_mbus_dram_info;
298 orion5x_sata.dev.platform_data = sata_data;
299 platform_device_register(&orion5x_sata);
300}
301
302/*****************************************************************************
303 * Time handling
304 ****************************************************************************/
305
306static void orion5x_timer_init(void)
307{
308 orion_time_init(IRQ_ORION5X_BRIDGE, ORION5X_TCLK);
309}
310
311struct sys_timer orion5x_timer = {
312 .init = orion5x_timer_init,
313};
314
315/*****************************************************************************
316 * General
317 ****************************************************************************/
318
319/*
320 * Identify device ID and rev from PCIE configuration header space '0'.
321 */
322static void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name)
323{
324 orion5x_pcie_id(dev, rev);
325
326 if (*dev == MV88F5281_DEV_ID) {
327 if (*rev == MV88F5281_REV_D2) {
328 *dev_name = "MV88F5281-D2";
329 } else if (*rev == MV88F5281_REV_D1) {
330 *dev_name = "MV88F5281-D1";
331 } else {
332 *dev_name = "MV88F5281-Rev-Unsupported";
333 }
334 } else if (*dev == MV88F5182_DEV_ID) {
335 if (*rev == MV88F5182_REV_A2) {
336 *dev_name = "MV88F5182-A2";
337 } else {
338 *dev_name = "MV88F5182-Rev-Unsupported";
339 }
340 } else if (*dev == MV88F5181_DEV_ID) {
341 if (*rev == MV88F5181_REV_B1) {
342 *dev_name = "MV88F5181-Rev-B1";
343 } else {
344 *dev_name = "MV88F5181-Rev-Unsupported";
345 }
346 } else {
347 *dev_name = "Device-Unknown";
348 }
349}
350
351void __init orion5x_init(void)
352{
353 char *dev_name;
354 u32 dev, rev;
355
356 orion5x_id(&dev, &rev, &dev_name);
357 printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, ORION5X_TCLK);
358
359 /*
360 * Setup Orion address map
361 */
362 orion5x_setup_cpu_mbus_bridge();
363 orion5x_setup_eth_wins();
364
365 /*
366 * Register devices.
367 */
368 platform_device_register(&orion5x_uart);
369 platform_device_register(&orion5x_ehci0);
370 if (dev == MV88F5182_DEV_ID)
371 platform_device_register(&orion5x_ehci1);
372 platform_device_register(&orion5x_i2c);
373}
374
375/*
376 * Many orion-based systems have buggy bootloader implementations.
377 * This is a common fixup for bogus memory tags.
378 */
379void __init tag_fixup_mem32(struct machine_desc *mdesc, struct tag *t,
380 char **from, struct meminfo *meminfo)
381{
382 for (; t->hdr.size; t = tag_next(t))
383 if (t->hdr.tag == ATAG_MEM &&
384 (!t->u.mem.size || t->u.mem.size & ~PAGE_MASK ||
385 t->u.mem.start & ~PAGE_MASK)) {
386 printk(KERN_WARNING
387 "Clearing invalid memory bank %dKB@0x%08x\n",
388 t->u.mem.size / 1024, t->u.mem.start);
389 t->hdr.tag = 0;
390 }
391}
diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
new file mode 100644
index 00000000000..f4c4c9a72a7
--- /dev/null
+++ b/arch/arm/mach-orion5x/common.h
@@ -0,0 +1,72 @@
1#ifndef __ARCH_ORION5X_COMMON_H
2#define __ARCH_ORION5X_COMMON_H
3
4/*
5 * Basic Orion init functions used early by machine-setup.
6 */
7
8void orion5x_map_io(void);
9void orion5x_init_irq(void);
10void orion5x_init(void);
11extern struct sys_timer orion5x_timer;
12
13/*
14 * Enumerations and functions for Orion windows mapping. Used by Orion core
15 * functions to map its interfaces and by the machine-setup to map its on-
16 * board devices. Details in /mach-orion/addr-map.c
17 */
18extern struct mbus_dram_target_info orion5x_mbus_dram_info;
19void orion5x_setup_cpu_mbus_bridge(void);
20void orion5x_setup_dev_boot_win(u32 base, u32 size);
21void orion5x_setup_dev0_win(u32 base, u32 size);
22void orion5x_setup_dev1_win(u32 base, u32 size);
23void orion5x_setup_dev2_win(u32 base, u32 size);
24void orion5x_setup_pcie_wa_win(u32 base, u32 size);
25void orion5x_setup_eth_wins(void);
26
27/*
28 * Shared code used internally by other Orion core functions.
29 * (/mach-orion/pci.c)
30 */
31
32struct pci_sys_data;
33struct pci_bus;
34
35void orion5x_pcie_id(u32 *dev, u32 *rev);
36int orion5x_pcie_local_bus_nr(void);
37int orion5x_pci_local_bus_nr(void);
38int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys);
39struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys);
40
41/*
42 * Valid GPIO pins according to MPP setup, used by machine-setup.
43 * (/mach-orion/gpio.c).
44 */
45
46void orion5x_gpio_set_valid_pins(u32 pins);
47void gpio_display(void); /* debug */
48
49/*
50 * Pull in Orion Ethernet platform_data, used by machine-setup
51 */
52
53struct mv643xx_eth_platform_data;
54
55void orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data);
56
57/*
58 * Orion Sata platform_data, used by machine-setup
59 */
60
61struct mv_sata_platform_data;
62
63void orion5x_sata_init(struct mv_sata_platform_data *sata_data);
64
65struct machine_desc;
66struct meminfo;
67struct tag;
68extern void __init tag_fixup_mem32(struct machine_desc *, struct tag *,
69 char **, struct meminfo *);
70
71
72#endif
diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c
new file mode 100644
index 00000000000..872aed37232
--- /dev/null
+++ b/arch/arm/mach-orion5x/db88f5281-setup.c
@@ -0,0 +1,361 @@
1/*
2 * arch/arm/mach-orion5x/db88f5281-setup.c
3 *
4 * Marvell Orion-2 Development Board Setup
5 *
6 * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/pci.h>
17#include <linux/irq.h>
18#include <linux/mtd/physmap.h>
19#include <linux/mtd/nand.h>
20#include <linux/timer.h>
21#include <linux/mv643xx_eth.h>
22#include <linux/i2c.h>
23#include <asm/mach-types.h>
24#include <asm/gpio.h>
25#include <asm/mach/arch.h>
26#include <asm/mach/pci.h>
27#include <asm/arch/orion5x.h>
28#include <asm/plat-orion/orion_nand.h>
29#include "common.h"
30
31/*****************************************************************************
32 * DB-88F5281 on board devices
33 ****************************************************************************/
34
35/*
36 * 512K NOR flash Device bus boot chip select
37 */
38
39#define DB88F5281_NOR_BOOT_BASE 0xf4000000
40#define DB88F5281_NOR_BOOT_SIZE SZ_512K
41
42/*
43 * 7-Segment on Device bus chip select 0
44 */
45
46#define DB88F5281_7SEG_BASE 0xfa000000
47#define DB88F5281_7SEG_SIZE SZ_1K
48
49/*
50 * 32M NOR flash on Device bus chip select 1
51 */
52
53#define DB88F5281_NOR_BASE 0xfc000000
54#define DB88F5281_NOR_SIZE SZ_32M
55
56/*
57 * 32M NAND flash on Device bus chip select 2
58 */
59
60#define DB88F5281_NAND_BASE 0xfa800000
61#define DB88F5281_NAND_SIZE SZ_1K
62
63/*
64 * PCI
65 */
66
67#define DB88F5281_PCI_SLOT0_OFFS 7
68#define DB88F5281_PCI_SLOT0_IRQ_PIN 12
69#define DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN 13
70
71/*****************************************************************************
72 * 512M NOR Flash on Device bus Boot CS
73 ****************************************************************************/
74
75static struct physmap_flash_data db88f5281_boot_flash_data = {
76 .width = 1, /* 8 bit bus width */
77};
78
79static struct resource db88f5281_boot_flash_resource = {
80 .flags = IORESOURCE_MEM,
81 .start = DB88F5281_NOR_BOOT_BASE,
82 .end = DB88F5281_NOR_BOOT_BASE + DB88F5281_NOR_BOOT_SIZE - 1,
83};
84
85static struct platform_device db88f5281_boot_flash = {
86 .name = "physmap-flash",
87 .id = 0,
88 .dev = {
89 .platform_data = &db88f5281_boot_flash_data,
90 },
91 .num_resources = 1,
92 .resource = &db88f5281_boot_flash_resource,
93};
94
95/*****************************************************************************
96 * 32M NOR Flash on Device bus CS1
97 ****************************************************************************/
98
99static struct physmap_flash_data db88f5281_nor_flash_data = {
100 .width = 4, /* 32 bit bus width */
101};
102
103static struct resource db88f5281_nor_flash_resource = {
104 .flags = IORESOURCE_MEM,
105 .start = DB88F5281_NOR_BASE,
106 .end = DB88F5281_NOR_BASE + DB88F5281_NOR_SIZE - 1,
107};
108
109static struct platform_device db88f5281_nor_flash = {
110 .name = "physmap-flash",
111 .id = 1,
112 .dev = {
113 .platform_data = &db88f5281_nor_flash_data,
114 },
115 .num_resources = 1,
116 .resource = &db88f5281_nor_flash_resource,
117};
118
119/*****************************************************************************
120 * 32M NAND Flash on Device bus CS2
121 ****************************************************************************/
122
123static struct mtd_partition db88f5281_nand_parts[] = {
124 {
125 .name = "kernel",
126 .offset = 0,
127 .size = SZ_2M,
128 },
129 {
130 .name = "root",
131 .offset = SZ_2M,
132 .size = (SZ_16M - SZ_2M),
133 },
134 {
135 .name = "user",
136 .offset = SZ_16M,
137 .size = SZ_8M,
138 },
139 {
140 .name = "recovery",
141 .offset = (SZ_16M + SZ_8M),
142 .size = SZ_8M,
143 },
144};
145
146static struct resource db88f5281_nand_resource = {
147 .flags = IORESOURCE_MEM,
148 .start = DB88F5281_NAND_BASE,
149 .end = DB88F5281_NAND_BASE + DB88F5281_NAND_SIZE - 1,
150};
151
152static struct orion_nand_data db88f5281_nand_data = {
153 .parts = db88f5281_nand_parts,
154 .nr_parts = ARRAY_SIZE(db88f5281_nand_parts),
155 .cle = 0,
156 .ale = 1,
157 .width = 8,
158};
159
160static struct platform_device db88f5281_nand_flash = {
161 .name = "orion_nand",
162 .id = -1,
163 .dev = {
164 .platform_data = &db88f5281_nand_data,
165 },
166 .resource = &db88f5281_nand_resource,
167 .num_resources = 1,
168};
169
170/*****************************************************************************
171 * 7-Segment on Device bus CS0
172 * Dummy counter every 2 sec
173 ****************************************************************************/
174
175static void __iomem *db88f5281_7seg;
176static struct timer_list db88f5281_timer;
177
178static void db88f5281_7seg_event(unsigned long data)
179{
180 static int count = 0;
181 writel(0, db88f5281_7seg + (count << 4));
182 count = (count + 1) & 7;
183 mod_timer(&db88f5281_timer, jiffies + 2 * HZ);
184}
185
186static int __init db88f5281_7seg_init(void)
187{
188 if (machine_is_db88f5281()) {
189 db88f5281_7seg = ioremap(DB88F5281_7SEG_BASE,
190 DB88F5281_7SEG_SIZE);
191 if (!db88f5281_7seg) {
192 printk(KERN_ERR "Failed to ioremap db88f5281_7seg\n");
193 return -EIO;
194 }
195 setup_timer(&db88f5281_timer, db88f5281_7seg_event, 0);
196 mod_timer(&db88f5281_timer, jiffies + 2 * HZ);
197 }
198
199 return 0;
200}
201
202__initcall(db88f5281_7seg_init);
203
204/*****************************************************************************
205 * PCI
206 ****************************************************************************/
207
208void __init db88f5281_pci_preinit(void)
209{
210 int pin;
211
212 /*
213 * Configure PCI GPIO IRQ pins
214 */
215 pin = DB88F5281_PCI_SLOT0_IRQ_PIN;
216 if (gpio_request(pin, "PCI Int1") == 0) {
217 if (gpio_direction_input(pin) == 0) {
218 set_irq_type(gpio_to_irq(pin), IRQT_LOW);
219 } else {
220 printk(KERN_ERR "db88f5281_pci_preinit faield to "
221 "set_irq_type pin %d\n", pin);
222 gpio_free(pin);
223 }
224 } else {
225 printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin);
226 }
227
228 pin = DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN;
229 if (gpio_request(pin, "PCI Int2") == 0) {
230 if (gpio_direction_input(pin) == 0) {
231 set_irq_type(gpio_to_irq(pin), IRQT_LOW);
232 } else {
233 printk(KERN_ERR "db88f5281_pci_preinit faield "
234 "to set_irq_type pin %d\n", pin);
235 gpio_free(pin);
236 }
237 } else {
238 printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin);
239 }
240}
241
242static int __init db88f5281_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
243{
244 /*
245 * PCIE IRQ is connected internally (not GPIO)
246 */
247 if (dev->bus->number == orion5x_pcie_local_bus_nr())
248 return IRQ_ORION5X_PCIE0_INT;
249
250 /*
251 * PCI IRQs are connected via GPIOs
252 */
253 switch (slot - DB88F5281_PCI_SLOT0_OFFS) {
254 case 0:
255 return gpio_to_irq(DB88F5281_PCI_SLOT0_IRQ_PIN);
256 case 1:
257 case 2:
258 return gpio_to_irq(DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN);
259 default:
260 return -1;
261 }
262}
263
264static struct hw_pci db88f5281_pci __initdata = {
265 .nr_controllers = 2,
266 .preinit = db88f5281_pci_preinit,
267 .swizzle = pci_std_swizzle,
268 .setup = orion5x_pci_sys_setup,
269 .scan = orion5x_pci_sys_scan_bus,
270 .map_irq = db88f5281_pci_map_irq,
271};
272
273static int __init db88f5281_pci_init(void)
274{
275 if (machine_is_db88f5281())
276 pci_common_init(&db88f5281_pci);
277
278 return 0;
279}
280
281subsys_initcall(db88f5281_pci_init);
282
283/*****************************************************************************
284 * Ethernet
285 ****************************************************************************/
286static struct mv643xx_eth_platform_data db88f5281_eth_data = {
287 .phy_addr = 8,
288 .force_phy_addr = 1,
289};
290
291/*****************************************************************************
292 * RTC DS1339 on I2C bus
293 ****************************************************************************/
294static struct i2c_board_info __initdata db88f5281_i2c_rtc = {
295 .driver_name = "rtc-ds1307",
296 .type = "ds1339",
297 .addr = 0x68,
298};
299
300/*****************************************************************************
301 * General Setup
302 ****************************************************************************/
303
304static struct platform_device *db88f5281_devs[] __initdata = {
305 &db88f5281_boot_flash,
306 &db88f5281_nor_flash,
307 &db88f5281_nand_flash,
308};
309
310static void __init db88f5281_init(void)
311{
312 /*
313 * Basic Orion setup. Need to be called early.
314 */
315 orion5x_init();
316
317 /*
318 * Setup the CPU address decode windows for our on-board devices
319 */
320 orion5x_setup_dev_boot_win(DB88F5281_NOR_BOOT_BASE,
321 DB88F5281_NOR_BOOT_SIZE);
322 orion5x_setup_dev0_win(DB88F5281_7SEG_BASE, DB88F5281_7SEG_SIZE);
323 orion5x_setup_dev1_win(DB88F5281_NOR_BASE, DB88F5281_NOR_SIZE);
324 orion5x_setup_dev2_win(DB88F5281_NAND_BASE, DB88F5281_NAND_SIZE);
325
326 /*
327 * Setup Multiplexing Pins:
328 * MPP0: GPIO (USB Over Current) MPP1: GPIO (USB Vbat input)
329 * MPP2: PCI_REQn[2] MPP3: PCI_GNTn[2]
330 * MPP4: PCI_REQn[3] MPP5: PCI_GNTn[3]
331 * MPP6: GPIO (JP0, CON17.2) MPP7: GPIO (JP1, CON17.1)
332 * MPP8: GPIO (JP2, CON11.2) MPP9: GPIO (JP3, CON11.3)
333 * MPP10: GPIO (RTC int) MPP11: GPIO (Baud Rate Generator)
334 * MPP12: GPIO (PCI int 1) MPP13: GPIO (PCI int 2)
335 * MPP14: NAND_REn[2] MPP15: NAND_WEn[2]
336 * MPP16: UART1_RX MPP17: UART1_TX
337 * MPP18: UART1_CTS MPP19: UART1_RTS
338 * MPP-DEV: DEV_D[16:31]
339 */
340 orion5x_write(MPP_0_7_CTRL, 0x00222203);
341 orion5x_write(MPP_8_15_CTRL, 0x44000000);
342 orion5x_write(MPP_16_19_CTRL, 0);
343 orion5x_write(MPP_DEV_CTRL, 0);
344
345 orion5x_gpio_set_valid_pins(0x00003fc3);
346
347 platform_add_devices(db88f5281_devs, ARRAY_SIZE(db88f5281_devs));
348 i2c_register_board_info(0, &db88f5281_i2c_rtc, 1);
349 orion5x_eth_init(&db88f5281_eth_data);
350}
351
352MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board")
353 /* Maintainer: Tzachi Perelstein <tzachi@marvell.com> */
354 .phys_io = ORION5X_REGS_PHYS_BASE,
355 .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xfffc,
356 .boot_params = 0x00000100,
357 .init_machine = db88f5281_init,
358 .map_io = orion5x_map_io,
359 .init_irq = orion5x_init_irq,
360 .timer = &orion5x_timer,
361MACHINE_END
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
new file mode 100644
index 00000000000..d67790ef236
--- /dev/null
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -0,0 +1,320 @@
1/*
2 * arch/arm/mach-orion5x/dns323-setup.c
3 *
4 * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
10 *
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/pci.h>
17#include <linux/irq.h>
18#include <linux/mtd/physmap.h>
19#include <linux/mv643xx_eth.h>
20#include <linux/leds.h>
21#include <linux/gpio_keys.h>
22#include <linux/input.h>
23#include <linux/i2c.h>
24#include <asm/mach-types.h>
25#include <asm/gpio.h>
26#include <asm/mach/arch.h>
27#include <asm/mach/pci.h>
28#include <asm/arch/orion5x.h>
29#include "common.h"
30
31#define DNS323_GPIO_LED_RIGHT_AMBER 1
32#define DNS323_GPIO_LED_LEFT_AMBER 2
33#define DNS323_GPIO_LED_POWER 5
34#define DNS323_GPIO_OVERTEMP 6
35#define DNS323_GPIO_RTC 7
36#define DNS323_GPIO_POWER_OFF 8
37#define DNS323_GPIO_KEY_POWER 9
38#define DNS323_GPIO_KEY_RESET 10
39
40/****************************************************************************
41 * PCI setup
42 */
43
44static int __init dns323_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
45{
46 /* PCI-E */
47 if (dev->bus->number == orion5x_pcie_local_bus_nr())
48 return IRQ_ORION5X_PCIE0_INT;
49
50 pr_err("%s: requested mapping for unknown bus\n", __func__);
51
52 return -1;
53}
54
55static struct hw_pci dns323_pci __initdata = {
56 .nr_controllers = 1,
57 .swizzle = pci_std_swizzle,
58 .setup = orion5x_pci_sys_setup,
59 .scan = orion5x_pci_sys_scan_bus,
60 .map_irq = dns323_pci_map_irq,
61};
62
63static int __init dns323_pci_init(void)
64{
65 if (machine_is_dns323())
66 pci_common_init(&dns323_pci);
67
68 return 0;
69}
70
71subsys_initcall(dns323_pci_init);
72
73/****************************************************************************
74 * Ethernet
75 */
76
77static struct mv643xx_eth_platform_data dns323_eth_data = {
78 .phy_addr = 8,
79 .force_phy_addr = 1,
80};
81
82/****************************************************************************
83 * 8MiB NOR flash (Spansion S29GL064M90TFIR4)
84 *
85 * Layout as used by D-Link:
86 * 0x00000000-0x00010000 : "MTD1"
87 * 0x00010000-0x00020000 : "MTD2"
88 * 0x00020000-0x001a0000 : "Linux Kernel"
89 * 0x001a0000-0x007d0000 : "File System"
90 * 0x007d0000-0x00800000 : "u-boot"
91 */
92
93#define DNS323_NOR_BOOT_BASE 0xf4000000
94#define DNS323_NOR_BOOT_SIZE SZ_8M
95
96static struct mtd_partition dns323_partitions[] = {
97 {
98 .name = "MTD1",
99 .size = 0x00010000,
100 .offset = 0,
101 }, {
102 .name = "MTD2",
103 .size = 0x00010000,
104 .offset = 0x00010000,
105 }, {
106 .name = "Linux Kernel",
107 .size = 0x00180000,
108 .offset = 0x00020000,
109 }, {
110 .name = "File System",
111 .size = 0x00630000,
112 .offset = 0x001A0000,
113 }, {
114 .name = "u-boot",
115 .size = 0x00030000,
116 .offset = 0x007d0000,
117 }
118};
119
120static struct physmap_flash_data dns323_nor_flash_data = {
121 .width = 1,
122 .parts = dns323_partitions,
123 .nr_parts = ARRAY_SIZE(dns323_partitions)
124};
125
126static struct resource dns323_nor_flash_resource = {
127 .flags = IORESOURCE_MEM,
128 .start = DNS323_NOR_BOOT_BASE,
129 .end = DNS323_NOR_BOOT_BASE + DNS323_NOR_BOOT_SIZE - 1,
130};
131
132static struct platform_device dns323_nor_flash = {
133 .name = "physmap-flash",
134 .id = 0,
135 .dev = { .platform_data = &dns323_nor_flash_data, },
136 .resource = &dns323_nor_flash_resource,
137 .num_resources = 1,
138};
139
140/****************************************************************************
141 * GPIO LEDs (simple - doesn't use hardware blinking support)
142 */
143
144static struct gpio_led dns323_leds[] = {
145 {
146 .name = "power:blue",
147 .gpio = DNS323_GPIO_LED_POWER,
148 .active_low = 1,
149 }, {
150 .name = "right:amber",
151 .gpio = DNS323_GPIO_LED_RIGHT_AMBER,
152 .active_low = 1,
153 }, {
154 .name = "left:amber",
155 .gpio = DNS323_GPIO_LED_LEFT_AMBER,
156 .active_low = 1,
157 },
158};
159
160static struct gpio_led_platform_data dns323_led_data = {
161 .num_leds = ARRAY_SIZE(dns323_leds),
162 .leds = dns323_leds,
163};
164
165static struct platform_device dns323_gpio_leds = {
166 .name = "leds-gpio",
167 .id = -1,
168 .dev = { .platform_data = &dns323_led_data, },
169};
170
171/****************************************************************************
172 * GPIO Attached Keys
173 */
174
175static struct gpio_keys_button dns323_buttons[] = {
176 {
177 .code = KEY_RESTART,
178 .gpio = DNS323_GPIO_KEY_RESET,
179 .desc = "Reset Button",
180 .active_low = 1,
181 },
182 {
183 .code = KEY_POWER,
184 .gpio = DNS323_GPIO_KEY_POWER,
185 .desc = "Power Button",
186 .active_low = 1,
187 }
188};
189
190static struct gpio_keys_platform_data dns323_button_data = {
191 .buttons = dns323_buttons,
192 .nbuttons = ARRAY_SIZE(dns323_buttons),
193};
194
195static struct platform_device dns323_button_device = {
196 .name = "gpio-keys",
197 .id = -1,
198 .num_resources = 0,
199 .dev = { .platform_data = &dns323_button_data, },
200};
201
202/****************************************************************************
203 * General Setup
204 */
205
206static struct platform_device *dns323_plat_devices[] __initdata = {
207 &dns323_nor_flash,
208 &dns323_gpio_leds,
209 &dns323_button_device,
210};
211
212/*
213 * On the DNS-323 the following devices are attached via I2C:
214 *
215 * i2c addr | chip | description
216 * 0x3e | GMT G760Af | fan speed PWM controller
217 * 0x48 | GMT G751-2f | temp. sensor and therm. watchdog (LM75 compatible)
218 * 0x68 | ST M41T80 | RTC w/ alarm
219 */
220static struct i2c_board_info __initdata dns323_i2c_devices[] = {
221 {
222 I2C_BOARD_INFO("g760a", 0x3e),
223 .type = "g760a",
224 },
225#if 0
226 /* this entry requires the new-style driver model lm75 driver,
227 * for the meantime "insmod lm75.ko force_lm75=0,0x48" is needed */
228 {
229 I2C_BOARD_INFO("lm75", 0x48),
230 .type = "g751",
231 },
232#endif
233 {
234 I2C_BOARD_INFO("rtc-m41t80", 0x68),
235 .type = "m41t80",
236 }
237};
238
239/* DNS-323 specific power off method */
240static void dns323_power_off(void)
241{
242 pr_info("%s: triggering power-off...\n", __func__);
243 gpio_set_value(DNS323_GPIO_POWER_OFF, 1);
244}
245
246static void __init dns323_init(void)
247{
248 /* Setup basic Orion functions. Need to be called early. */
249 orion5x_init();
250
251 /* setup flash mapping
252 * CS3 holds a 8 MB Spansion S29GL064M90TFIR4
253 */
254 orion5x_setup_dev_boot_win(DNS323_NOR_BOOT_BASE, DNS323_NOR_BOOT_SIZE);
255
256 /* DNS-323 has a Marvell 88X7042 SATA controller attached via PCIE
257 *
258 * Open a special address decode windows for the PCIE WA.
259 */
260 orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
261 ORION5X_PCIE_WA_SIZE);
262
263 /* set MPP to 0 as D-Link's 2.6.12.6 kernel did */
264 orion5x_write(MPP_0_7_CTRL, 0);
265 orion5x_write(MPP_8_15_CTRL, 0);
266 orion5x_write(MPP_16_19_CTRL, 0);
267 orion5x_write(MPP_DEV_CTRL, 0);
268
269 /* Define used GPIO pins
270
271 GPIO Map:
272
273 | 0 | | PEX_RST_OUT (not controlled by GPIO)
274 | 1 | Out | right amber LED (= sata ch0 LED) (low-active)
275 | 2 | Out | left amber LED (= sata ch1 LED) (low-active)
276 | 3 | Out | //unknown//
277 | 4 | Out | power button LED (low-active, together with pin #5)
278 | 5 | Out | power button LED (low-active, together with pin #4)
279 | 6 | In | GMT G751-2f overtemp. shutdown signal (low-active)
280 | 7 | In | M41T80 nIRQ/OUT/SQW signal
281 | 8 | Out | triggers power off (high-active)
282 | 9 | In | power button switch (low-active)
283 | 10 | In | reset button switch (low-active)
284 | 11 | Out | //unknown//
285 | 12 | Out | //unknown//
286 | 13 | Out | //unknown//
287 | 14 | Out | //unknown//
288 | 15 | Out | //unknown//
289 */
290 orion5x_gpio_set_valid_pins(0x07f6);
291
292 /* register dns323 specific power-off method */
293 if ((gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0)
294 || (gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0))
295 pr_err("DNS323: failed to setup power-off GPIO\n");
296
297 pm_power_off = dns323_power_off;
298
299 /* register flash and other platform devices */
300 platform_add_devices(dns323_plat_devices,
301 ARRAY_SIZE(dns323_plat_devices));
302
303 i2c_register_board_info(0, dns323_i2c_devices,
304 ARRAY_SIZE(dns323_i2c_devices));
305
306 orion5x_eth_init(&dns323_eth_data);
307}
308
309/* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */
310MACHINE_START(DNS323, "D-Link DNS-323")
311 /* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
312 .phys_io = ORION5X_REGS_PHYS_BASE,
313 .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
314 .boot_params = 0x00000100,
315 .init_machine = dns323_init,
316 .map_io = orion5x_map_io,
317 .init_irq = orion5x_init_irq,
318 .timer = &orion5x_timer,
319 .fixup = tag_fixup_mem32,
320MACHINE_END
diff --git a/arch/arm/mach-orion5x/gpio.c b/arch/arm/mach-orion5x/gpio.c
new file mode 100644
index 00000000000..8108c316c42
--- /dev/null
+++ b/arch/arm/mach-orion5x/gpio.c
@@ -0,0 +1,226 @@
1/*
2 * arch/arm/mach-orion5x/gpio.c
3 *
4 * GPIO functions for Marvell Orion System On Chip
5 *
6 * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/spinlock.h>
17#include <linux/bitops.h>
18#include <asm/gpio.h>
19#include <asm/io.h>
20#include <asm/arch/orion5x.h>
21#include "common.h"
22
23static DEFINE_SPINLOCK(gpio_lock);
24static unsigned long gpio_valid[BITS_TO_LONGS(GPIO_MAX)];
25static const char *gpio_label[GPIO_MAX]; /* non null for allocated GPIOs */
26
27void __init orion5x_gpio_set_valid_pins(u32 pins)
28{
29 gpio_valid[0] = pins;
30}
31
32/*
33 * GENERIC_GPIO primitives
34 */
35int gpio_direction_input(unsigned pin)
36{
37 unsigned long flags;
38
39 if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
40 pr_debug("%s: invalid GPIO %d\n", __func__, pin);
41 return -EINVAL;
42 }
43
44 spin_lock_irqsave(&gpio_lock, flags);
45
46 /*
47 * Some callers might have not used the gpio_request(),
48 * so flag this pin as requested now.
49 */
50 if (!gpio_label[pin])
51 gpio_label[pin] = "?";
52
53 orion5x_setbits(GPIO_IO_CONF, 1 << pin);
54
55 spin_unlock_irqrestore(&gpio_lock, flags);
56 return 0;
57}
58EXPORT_SYMBOL(gpio_direction_input);
59
60int gpio_direction_output(unsigned pin, int value)
61{
62 unsigned long flags;
63 int mask;
64
65 if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
66 pr_debug("%s: invalid GPIO %d\n", __func__, pin);
67 return -EINVAL;
68 }
69
70 spin_lock_irqsave(&gpio_lock, flags);
71
72 /*
73 * Some callers might have not used the gpio_request(),
74 * so flag this pin as requested now.
75 */
76 if (!gpio_label[pin])
77 gpio_label[pin] = "?";
78
79 mask = 1 << pin;
80 orion5x_clrbits(GPIO_BLINK_EN, mask);
81 if (value)
82 orion5x_setbits(GPIO_OUT, mask);
83 else
84 orion5x_clrbits(GPIO_OUT, mask);
85 orion5x_clrbits(GPIO_IO_CONF, mask);
86
87 spin_unlock_irqrestore(&gpio_lock, flags);
88 return 0;
89}
90EXPORT_SYMBOL(gpio_direction_output);
91
92int gpio_get_value(unsigned pin)
93{
94 int val, mask = 1 << pin;
95
96 if (orion5x_read(GPIO_IO_CONF) & mask)
97 val = orion5x_read(GPIO_DATA_IN) ^ orion5x_read(GPIO_IN_POL);
98 else
99 val = orion5x_read(GPIO_OUT);
100
101 return val & mask;
102}
103EXPORT_SYMBOL(gpio_get_value);
104
105void gpio_set_value(unsigned pin, int value)
106{
107 unsigned long flags;
108 int mask = 1 << pin;
109
110 spin_lock_irqsave(&gpio_lock, flags);
111
112 orion5x_clrbits(GPIO_BLINK_EN, mask);
113 if (value)
114 orion5x_setbits(GPIO_OUT, mask);
115 else
116 orion5x_clrbits(GPIO_OUT, mask);
117
118 spin_unlock_irqrestore(&gpio_lock, flags);
119}
120EXPORT_SYMBOL(gpio_set_value);
121
122void orion5x_gpio_set_blink(unsigned pin, int blink)
123{
124 unsigned long flags;
125 int mask = 1 << pin;
126
127 spin_lock_irqsave(&gpio_lock, flags);
128
129 orion5x_clrbits(GPIO_OUT, mask);
130 if (blink)
131 orion5x_setbits(GPIO_BLINK_EN, mask);
132 else
133 orion5x_clrbits(GPIO_BLINK_EN, mask);
134
135 spin_unlock_irqrestore(&gpio_lock, flags);
136}
137EXPORT_SYMBOL(orion5x_gpio_set_blink);
138
139int gpio_request(unsigned pin, const char *label)
140{
141 int ret = 0;
142 unsigned long flags;
143
144 if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
145 pr_debug("%s: invalid GPIO %d\n", __func__, pin);
146 return -EINVAL;
147 }
148
149 spin_lock_irqsave(&gpio_lock, flags);
150
151 if (gpio_label[pin]) {
152 pr_debug("%s: GPIO %d already used as %s\n",
153 __func__, pin, gpio_label[pin]);
154 ret = -EBUSY;
155 } else
156 gpio_label[pin] = label ? label : "?";
157
158 spin_unlock_irqrestore(&gpio_lock, flags);
159 return ret;
160}
161EXPORT_SYMBOL(gpio_request);
162
163void gpio_free(unsigned pin)
164{
165 if (pin >= GPIO_MAX || !test_bit(pin, gpio_valid)) {
166 pr_debug("%s: invalid GPIO %d\n", __func__, pin);
167 return;
168 }
169
170 if (!gpio_label[pin])
171 pr_warning("%s: GPIO %d already freed\n", __func__, pin);
172 else
173 gpio_label[pin] = NULL;
174}
175EXPORT_SYMBOL(gpio_free);
176
177/* Debug helper */
178void gpio_display(void)
179{
180 int i;
181
182 for (i = 0; i < GPIO_MAX; i++) {
183 printk(KERN_DEBUG "Pin-%d: ", i);
184
185 if (!test_bit(i, gpio_valid)) {
186 printk("non-GPIO\n");
187 } else if (!gpio_label[i]) {
188 printk("GPIO, free\n");
189 } else {
190 printk("GPIO, used by %s, ", gpio_label[i]);
191 if (orion5x_read(GPIO_IO_CONF) & (1 << i)) {
192 printk("input, active %s, level %s, edge %s\n",
193 ((orion5x_read(GPIO_IN_POL) >> i) & 1) ? "low" : "high",
194 ((orion5x_read(GPIO_LEVEL_MASK) >> i) & 1) ? "enabled" : "masked",
195 ((orion5x_read(GPIO_EDGE_MASK) >> i) & 1) ? "enabled" : "masked");
196 } else {
197 printk("output, val=%d\n", (orion5x_read(GPIO_OUT) >> i) & 1);
198 }
199 }
200 }
201
202 printk(KERN_DEBUG "MPP_0_7_CTRL (0x%08x) = 0x%08x\n",
203 MPP_0_7_CTRL, orion5x_read(MPP_0_7_CTRL));
204 printk(KERN_DEBUG "MPP_8_15_CTRL (0x%08x) = 0x%08x\n",
205 MPP_8_15_CTRL, orion5x_read(MPP_8_15_CTRL));
206 printk(KERN_DEBUG "MPP_16_19_CTRL (0x%08x) = 0x%08x\n",
207 MPP_16_19_CTRL, orion5x_read(MPP_16_19_CTRL));
208 printk(KERN_DEBUG "MPP_DEV_CTRL (0x%08x) = 0x%08x\n",
209 MPP_DEV_CTRL, orion5x_read(MPP_DEV_CTRL));
210 printk(KERN_DEBUG "GPIO_OUT (0x%08x) = 0x%08x\n",
211 GPIO_OUT, orion5x_read(GPIO_OUT));
212 printk(KERN_DEBUG "GPIO_IO_CONF (0x%08x) = 0x%08x\n",
213 GPIO_IO_CONF, orion5x_read(GPIO_IO_CONF));
214 printk(KERN_DEBUG "GPIO_BLINK_EN (0x%08x) = 0x%08x\n",
215 GPIO_BLINK_EN, orion5x_read(GPIO_BLINK_EN));
216 printk(KERN_DEBUG "GPIO_IN_POL (0x%08x) = 0x%08x\n",
217 GPIO_IN_POL, orion5x_read(GPIO_IN_POL));
218 printk(KERN_DEBUG "GPIO_DATA_IN (0x%08x) = 0x%08x\n",
219 GPIO_DATA_IN, orion5x_read(GPIO_DATA_IN));
220 printk(KERN_DEBUG "GPIO_LEVEL_MASK (0x%08x) = 0x%08x\n",
221 GPIO_LEVEL_MASK, orion5x_read(GPIO_LEVEL_MASK));
222 printk(KERN_DEBUG "GPIO_EDGE_CAUSE (0x%08x) = 0x%08x\n",
223 GPIO_EDGE_CAUSE, orion5x_read(GPIO_EDGE_CAUSE));
224 printk(KERN_DEBUG "GPIO_EDGE_MASK (0x%08x) = 0x%08x\n",
225 GPIO_EDGE_MASK, orion5x_read(GPIO_EDGE_MASK));
226}
diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c
new file mode 100644
index 00000000000..dd21f38c5d3
--- /dev/null
+++ b/arch/arm/mach-orion5x/irq.c
@@ -0,0 +1,211 @@
1/*
2 * arch/arm/mach-orion5x/irq.c
3 *
4 * Core IRQ functions for Marvell Orion System On Chip
5 *
6 * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/irq.h>
16#include <asm/gpio.h>
17#include <asm/io.h>
18#include <asm/arch/orion5x.h>
19#include <asm/plat-orion/irq.h>
20#include "common.h"
21
22/*****************************************************************************
23 * Orion GPIO IRQ
24 *
25 * GPIO_IN_POL register controlls whether GPIO_DATA_IN will hold the same
26 * value of the line or the opposite value.
27 *
28 * Level IRQ handlers: DATA_IN is used directly as cause register.
29 * Interrupt are masked by LEVEL_MASK registers.
30 * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE.
31 * Interrupt are masked by EDGE_MASK registers.
32 * Both-edge handlers: Similar to regular Edge handlers, but also swaps
33 * the polarity to catch the next line transaction.
34 * This is a race condition that might not perfectly
35 * work on some use cases.
36 *
37 * Every eight GPIO lines are grouped (OR'ed) before going up to main
38 * cause register.
39 *
40 * EDGE cause mask
41 * data-in /--------| |-----| |----\
42 * -----| |----- ---- to main cause reg
43 * X \----------------| |----/
44 * polarity LEVEL mask
45 *
46 ****************************************************************************/
47static void orion5x_gpio_irq_ack(u32 irq)
48{
49 int pin = irq_to_gpio(irq);
50 if (irq_desc[irq].status & IRQ_LEVEL)
51 /*
52 * Mask bit for level interrupt
53 */
54 orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
55 else
56 /*
57 * Clear casue bit for egde interrupt
58 */
59 orion5x_clrbits(GPIO_EDGE_CAUSE, 1 << pin);
60}
61
62static void orion5x_gpio_irq_mask(u32 irq)
63{
64 int pin = irq_to_gpio(irq);
65 if (irq_desc[irq].status & IRQ_LEVEL)
66 orion5x_clrbits(GPIO_LEVEL_MASK, 1 << pin);
67 else
68 orion5x_clrbits(GPIO_EDGE_MASK, 1 << pin);
69}
70
71static void orion5x_gpio_irq_unmask(u32 irq)
72{
73 int pin = irq_to_gpio(irq);
74 if (irq_desc[irq].status & IRQ_LEVEL)
75 orion5x_setbits(GPIO_LEVEL_MASK, 1 << pin);
76 else
77 orion5x_setbits(GPIO_EDGE_MASK, 1 << pin);
78}
79
80static int orion5x_gpio_set_irq_type(u32 irq, u32 type)
81{
82 int pin = irq_to_gpio(irq);
83 struct irq_desc *desc;
84
85 if ((orion5x_read(GPIO_IO_CONF) & (1 << pin)) == 0) {
86 printk(KERN_ERR "orion5x_gpio_set_irq_type failed "
87 "(irq %d, pin %d).\n", irq, pin);
88 return -EINVAL;
89 }
90
91 desc = irq_desc + irq;
92
93 switch (type) {
94 case IRQT_HIGH:
95 desc->handle_irq = handle_level_irq;
96 desc->status |= IRQ_LEVEL;
97 orion5x_clrbits(GPIO_IN_POL, (1 << pin));
98 break;
99 case IRQT_LOW:
100 desc->handle_irq = handle_level_irq;
101 desc->status |= IRQ_LEVEL;
102 orion5x_setbits(GPIO_IN_POL, (1 << pin));
103 break;
104 case IRQT_RISING:
105 desc->handle_irq = handle_edge_irq;
106 desc->status &= ~IRQ_LEVEL;
107 orion5x_clrbits(GPIO_IN_POL, (1 << pin));
108 break;
109 case IRQT_FALLING:
110 desc->handle_irq = handle_edge_irq;
111 desc->status &= ~IRQ_LEVEL;
112 orion5x_setbits(GPIO_IN_POL, (1 << pin));
113 break;
114 case IRQT_BOTHEDGE:
115 desc->handle_irq = handle_edge_irq;
116 desc->status &= ~IRQ_LEVEL;
117 /*
118 * set initial polarity based on current input level
119 */
120 if ((orion5x_read(GPIO_IN_POL) ^ orion5x_read(GPIO_DATA_IN))
121 & (1 << pin))
122 orion5x_setbits(GPIO_IN_POL, (1 << pin)); /* falling */
123 else
124 orion5x_clrbits(GPIO_IN_POL, (1 << pin)); /* rising */
125
126 break;
127 default:
128 printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
129 return -EINVAL;
130 }
131
132 desc->status &= ~IRQ_TYPE_SENSE_MASK;
133 desc->status |= type & IRQ_TYPE_SENSE_MASK;
134
135 return 0;
136}
137
138static struct irq_chip orion5x_gpio_irq_chip = {
139 .name = "Orion-IRQ-GPIO",
140 .ack = orion5x_gpio_irq_ack,
141 .mask = orion5x_gpio_irq_mask,
142 .unmask = orion5x_gpio_irq_unmask,
143 .set_type = orion5x_gpio_set_irq_type,
144};
145
146static void orion5x_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
147{
148 u32 cause, offs, pin;
149
150 BUG_ON(irq < IRQ_ORION5X_GPIO_0_7 || irq > IRQ_ORION5X_GPIO_24_31);
151 offs = (irq - IRQ_ORION5X_GPIO_0_7) * 8;
152 cause = (orion5x_read(GPIO_DATA_IN) & orion5x_read(GPIO_LEVEL_MASK)) |
153 (orion5x_read(GPIO_EDGE_CAUSE) & orion5x_read(GPIO_EDGE_MASK));
154
155 for (pin = offs; pin < offs + 8; pin++) {
156 if (cause & (1 << pin)) {
157 irq = gpio_to_irq(pin);
158 desc = irq_desc + irq;
159 if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQT_BOTHEDGE) {
160 /* Swap polarity (race with GPIO line) */
161 u32 polarity = orion5x_read(GPIO_IN_POL);
162 polarity ^= 1 << pin;
163 orion5x_write(GPIO_IN_POL, polarity);
164 }
165 desc_handle_irq(irq, desc);
166 }
167 }
168}
169
170static void __init orion5x_init_gpio_irq(void)
171{
172 int i;
173 struct irq_desc *desc;
174
175 /*
176 * Mask and clear GPIO IRQ interrupts
177 */
178 orion5x_write(GPIO_LEVEL_MASK, 0x0);
179 orion5x_write(GPIO_EDGE_MASK, 0x0);
180 orion5x_write(GPIO_EDGE_CAUSE, 0x0);
181
182 /*
183 * Register chained level handlers for GPIO IRQs by default.
184 * User can use set_type() if he wants to use edge types handlers.
185 */
186 for (i = IRQ_ORION5X_GPIO_START; i < NR_IRQS; i++) {
187 set_irq_chip(i, &orion5x_gpio_irq_chip);
188 set_irq_handler(i, handle_level_irq);
189 desc = irq_desc + i;
190 desc->status |= IRQ_LEVEL;
191 set_irq_flags(i, IRQF_VALID);
192 }
193 set_irq_chained_handler(IRQ_ORION5X_GPIO_0_7, orion5x_gpio_irq_handler);
194 set_irq_chained_handler(IRQ_ORION5X_GPIO_8_15, orion5x_gpio_irq_handler);
195 set_irq_chained_handler(IRQ_ORION5X_GPIO_16_23, orion5x_gpio_irq_handler);
196 set_irq_chained_handler(IRQ_ORION5X_GPIO_24_31, orion5x_gpio_irq_handler);
197}
198
199/*****************************************************************************
200 * Orion Main IRQ
201 ****************************************************************************/
202static void __init orion5x_init_main_irq(void)
203{
204 orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK);
205}
206
207void __init orion5x_init_irq(void)
208{
209 orion5x_init_main_irq();
210 orion5x_init_gpio_irq();
211}
diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c
new file mode 100644
index 00000000000..8ad4390b4b7
--- /dev/null
+++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
@@ -0,0 +1,243 @@
1/*
2 * arch/arm/mach-orion5x/kurobox_pro-setup.c
3 *
4 * Maintainer: Ronen Shitrit <rshitrit@marvell.com>
5 *
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
9 */
10
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/platform_device.h>
14#include <linux/pci.h>
15#include <linux/irq.h>
16#include <linux/mtd/physmap.h>
17#include <linux/mtd/nand.h>
18#include <linux/mv643xx_eth.h>
19#include <linux/i2c.h>
20#include <linux/ata_platform.h>
21#include <asm/mach-types.h>
22#include <asm/gpio.h>
23#include <asm/mach/arch.h>
24#include <asm/mach/pci.h>
25#include <asm/arch/orion5x.h>
26#include <asm/plat-orion/orion_nand.h>
27#include "common.h"
28
29/*****************************************************************************
30 * KUROBOX-PRO Info
31 ****************************************************************************/
32
33/*
34 * 256K NOR flash Device bus boot chip select
35 */
36
37#define KUROBOX_PRO_NOR_BOOT_BASE 0xf4000000
38#define KUROBOX_PRO_NOR_BOOT_SIZE SZ_256K
39
40/*
41 * 256M NAND flash on Device bus chip select 1
42 */
43
44#define KUROBOX_PRO_NAND_BASE 0xfc000000
45#define KUROBOX_PRO_NAND_SIZE SZ_2M
46
47/*****************************************************************************
48 * 256MB NAND Flash on Device bus CS0
49 ****************************************************************************/
50
51static struct mtd_partition kurobox_pro_nand_parts[] = {
52 {
53 .name = "uImage",
54 .offset = 0,
55 .size = SZ_4M,
56 },
57 {
58 .name = "rootfs",
59 .offset = SZ_4M,
60 .size = SZ_64M,
61 },
62 {
63 .name = "extra",
64 .offset = SZ_4M + SZ_64M,
65 .size = SZ_256M - (SZ_4M + SZ_64M),
66 },
67};
68
69static struct resource kurobox_pro_nand_resource = {
70 .flags = IORESOURCE_MEM,
71 .start = KUROBOX_PRO_NAND_BASE,
72 .end = KUROBOX_PRO_NAND_BASE + KUROBOX_PRO_NAND_SIZE - 1,
73};
74
75static struct orion_nand_data kurobox_pro_nand_data = {
76 .parts = kurobox_pro_nand_parts,
77 .nr_parts = ARRAY_SIZE(kurobox_pro_nand_parts),
78 .cle = 0,
79 .ale = 1,
80 .width = 8,
81};
82
83static struct platform_device kurobox_pro_nand_flash = {
84 .name = "orion_nand",
85 .id = -1,
86 .dev = {
87 .platform_data = &kurobox_pro_nand_data,
88 },
89 .resource = &kurobox_pro_nand_resource,
90 .num_resources = 1,
91};
92
93/*****************************************************************************
94 * 256KB NOR Flash on BOOT Device
95 ****************************************************************************/
96
97static struct physmap_flash_data kurobox_pro_nor_flash_data = {
98 .width = 1,
99};
100
101static struct resource kurobox_pro_nor_flash_resource = {
102 .flags = IORESOURCE_MEM,
103 .start = KUROBOX_PRO_NOR_BOOT_BASE,
104 .end = KUROBOX_PRO_NOR_BOOT_BASE + KUROBOX_PRO_NOR_BOOT_SIZE - 1,
105};
106
107static struct platform_device kurobox_pro_nor_flash = {
108 .name = "physmap-flash",
109 .id = 0,
110 .dev = {
111 .platform_data = &kurobox_pro_nor_flash_data,
112 },
113 .num_resources = 1,
114 .resource = &kurobox_pro_nor_flash_resource,
115};
116
117/*****************************************************************************
118 * PCI
119 ****************************************************************************/
120
121static int __init kurobox_pro_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
122{
123 /*
124 * PCI isn't used on the Kuro
125 */
126 if (dev->bus->number == orion5x_pcie_local_bus_nr())
127 return IRQ_ORION5X_PCIE0_INT;
128 else
129 printk(KERN_ERR "kurobox_pro_pci_map_irq failed, unknown bus\n");
130
131 return -1;
132}
133
134static struct hw_pci kurobox_pro_pci __initdata = {
135 .nr_controllers = 1,
136 .swizzle = pci_std_swizzle,
137 .setup = orion5x_pci_sys_setup,
138 .scan = orion5x_pci_sys_scan_bus,
139 .map_irq = kurobox_pro_pci_map_irq,
140};
141
142static int __init kurobox_pro_pci_init(void)
143{
144 if (machine_is_kurobox_pro())
145 pci_common_init(&kurobox_pro_pci);
146
147 return 0;
148}
149
150subsys_initcall(kurobox_pro_pci_init);
151
152/*****************************************************************************
153 * Ethernet
154 ****************************************************************************/
155
156static struct mv643xx_eth_platform_data kurobox_pro_eth_data = {
157 .phy_addr = 8,
158 .force_phy_addr = 1,
159};
160
161/*****************************************************************************
162 * RTC 5C372a on I2C bus
163 ****************************************************************************/
164static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = {
165 .driver_name = "rtc-rs5c372",
166 .type = "rs5c372a",
167 .addr = 0x32,
168};
169
170/*****************************************************************************
171 * SATA
172 ****************************************************************************/
173static struct mv_sata_platform_data kurobox_pro_sata_data = {
174 .n_ports = 2,
175};
176
177/*****************************************************************************
178 * General Setup
179 ****************************************************************************/
180
181static struct platform_device *kurobox_pro_devices[] __initdata = {
182 &kurobox_pro_nor_flash,
183 &kurobox_pro_nand_flash,
184};
185
186static void __init kurobox_pro_init(void)
187{
188 /*
189 * Setup basic Orion functions. Need to be called early.
190 */
191 orion5x_init();
192
193 /*
194 * Setup the CPU address decode windows for our devices
195 */
196 orion5x_setup_dev_boot_win(KUROBOX_PRO_NOR_BOOT_BASE,
197 KUROBOX_PRO_NOR_BOOT_SIZE);
198 orion5x_setup_dev0_win(KUROBOX_PRO_NAND_BASE, KUROBOX_PRO_NAND_SIZE);
199
200 /*
201 * Open a special address decode windows for the PCIE WA.
202 */
203 orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
204 ORION5X_PCIE_WA_SIZE);
205
206 /*
207 * Setup Multiplexing Pins --
208 * MPP[0-1] Not used
209 * MPP[2] GPIO Micon
210 * MPP[3] GPIO RTC
211 * MPP[4-5] Not used
212 * MPP[6] Nand Flash REn
213 * MPP[7] Nand Flash WEn
214 * MPP[8-11] Not used
215 * MPP[12] SATA 0 presence Indication
216 * MPP[13] SATA 1 presence Indication
217 * MPP[14] SATA 0 active Indication
218 * MPP[15] SATA 1 active indication
219 * MPP[16-19] Not used
220 */
221 orion5x_write(MPP_0_7_CTRL, 0x44220003);
222 orion5x_write(MPP_8_15_CTRL, 0x55550000);
223 orion5x_write(MPP_16_19_CTRL, 0x0);
224
225 orion5x_gpio_set_valid_pins(0x0000000c);
226
227 platform_add_devices(kurobox_pro_devices, ARRAY_SIZE(kurobox_pro_devices));
228 i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1);
229 orion5x_eth_init(&kurobox_pro_eth_data);
230 orion5x_sata_init(&kurobox_pro_sata_data);
231}
232
233MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro")
234 /* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
235 .phys_io = ORION5X_REGS_PHYS_BASE,
236 .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
237 .boot_params = 0x00000100,
238 .init_machine = kurobox_pro_init,
239 .map_io = orion5x_map_io,
240 .init_irq = orion5x_init_irq,
241 .timer = &orion5x_timer,
242 .fixup = tag_fixup_mem32,
243MACHINE_END
diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
new file mode 100644
index 00000000000..27b4afc8f48
--- /dev/null
+++ b/arch/arm/mach-orion5x/pci.c
@@ -0,0 +1,559 @@
1/*
2 * arch/arm/mach-orion5x/pci.c
3 *
4 * PCI and PCIe functions for Marvell Orion System On Chip
5 *
6 * Maintainer: Tzachi Perelstein <tzachi@marvell.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/kernel.h>
14#include <linux/pci.h>
15#include <linux/mbus.h>
16#include <asm/mach/pci.h>
17#include <asm/plat-orion/pcie.h>
18#include "common.h"
19
20/*****************************************************************************
21 * Orion has one PCIe controller and one PCI controller.
22 *
23 * Note1: The local PCIe bus number is '0'. The local PCI bus number
24 * follows the scanned PCIe bridged busses, if any.
25 *
26 * Note2: It is possible for PCI/PCIe agents to access many subsystem's
27 * space, by configuring BARs and Address Decode Windows, e.g. flashes on
28 * device bus, Orion registers, etc. However this code only enable the
29 * access to DDR banks.
30 ****************************************************************************/
31
32
33/*****************************************************************************
34 * PCIe controller
35 ****************************************************************************/
36#define PCIE_BASE ((void __iomem *)ORION5X_PCIE_VIRT_BASE)
37
38void __init orion5x_pcie_id(u32 *dev, u32 *rev)
39{
40 *dev = orion_pcie_dev_id(PCIE_BASE);
41 *rev = orion_pcie_rev(PCIE_BASE);
42}
43
44int orion5x_pcie_local_bus_nr(void)
45{
46 return orion_pcie_get_local_bus_nr(PCIE_BASE);
47}
48
49static int pcie_valid_config(int bus, int dev)
50{
51 /*
52 * Don't go out when trying to access --
53 * 1. nonexisting device on local bus
54 * 2. where there's no device connected (no link)
55 */
56 if (bus == 0 && dev == 0)
57 return 1;
58
59 if (!orion_pcie_link_up(PCIE_BASE))
60 return 0;
61
62 if (bus == 0 && dev != 1)
63 return 0;
64
65 return 1;
66}
67
68
69/*
70 * PCIe config cycles are done by programming the PCIE_CONF_ADDR register
71 * and then reading the PCIE_CONF_DATA register. Need to make sure these
72 * transactions are atomic.
73 */
74static DEFINE_SPINLOCK(orion5x_pcie_lock);
75
76static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
77 int size, u32 *val)
78{
79 unsigned long flags;
80 int ret;
81
82 if (pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) {
83 *val = 0xffffffff;
84 return PCIBIOS_DEVICE_NOT_FOUND;
85 }
86
87 spin_lock_irqsave(&orion5x_pcie_lock, flags);
88 ret = orion_pcie_rd_conf(PCIE_BASE, bus, devfn, where, size, val);
89 spin_unlock_irqrestore(&orion5x_pcie_lock, flags);
90
91 return ret;
92}
93
94static int pcie_rd_conf_wa(struct pci_bus *bus, u32 devfn,
95 int where, int size, u32 *val)
96{
97 int ret;
98
99 if (pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0) {
100 *val = 0xffffffff;
101 return PCIBIOS_DEVICE_NOT_FOUND;
102 }
103
104 /*
105 * We only support access to the non-extended configuration
106 * space when using the WA access method (or we would have to
107 * sacrifice 256M of CPU virtual address space.)
108 */
109 if (where >= 0x100) {
110 *val = 0xffffffff;
111 return PCIBIOS_DEVICE_NOT_FOUND;
112 }
113
114 ret = orion_pcie_rd_conf_wa((void __iomem *)ORION5X_PCIE_WA_VIRT_BASE,
115 bus, devfn, where, size, val);
116
117 return ret;
118}
119
120static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
121 int where, int size, u32 val)
122{
123 unsigned long flags;
124 int ret;
125
126 if (pcie_valid_config(bus->number, PCI_SLOT(devfn)) == 0)
127 return PCIBIOS_DEVICE_NOT_FOUND;
128
129 spin_lock_irqsave(&orion5x_pcie_lock, flags);
130 ret = orion_pcie_wr_conf(PCIE_BASE, bus, devfn, where, size, val);
131 spin_unlock_irqrestore(&orion5x_pcie_lock, flags);
132
133 return ret;
134}
135
136static struct pci_ops pcie_ops = {
137 .read = pcie_rd_conf,
138 .write = pcie_wr_conf,
139};
140
141
142static int __init pcie_setup(struct pci_sys_data *sys)
143{
144 struct resource *res;
145 int dev;
146
147 /*
148 * Generic PCIe unit setup.
149 */
150 orion_pcie_setup(PCIE_BASE, &orion5x_mbus_dram_info);
151
152 /*
153 * Check whether to apply Orion-1/Orion-NAS PCIe config
154 * read transaction workaround.
155 */
156 dev = orion_pcie_dev_id(PCIE_BASE);
157 if (dev == MV88F5181_DEV_ID || dev == MV88F5182_DEV_ID) {
158 printk(KERN_NOTICE "Applying Orion-1/Orion-NAS PCIe config "
159 "read transaction workaround\n");
160 pcie_ops.read = pcie_rd_conf_wa;
161 }
162
163 /*
164 * Request resources.
165 */
166 res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
167 if (!res)
168 panic("pcie_setup unable to alloc resources");
169
170 /*
171 * IORESOURCE_IO
172 */
173 res[0].name = "PCIe I/O Space";
174 res[0].flags = IORESOURCE_IO;
175 res[0].start = ORION5X_PCIE_IO_BUS_BASE;
176 res[0].end = res[0].start + ORION5X_PCIE_IO_SIZE - 1;
177 if (request_resource(&ioport_resource, &res[0]))
178 panic("Request PCIe IO resource failed\n");
179 sys->resource[0] = &res[0];
180
181 /*
182 * IORESOURCE_MEM
183 */
184 res[1].name = "PCIe Memory Space";
185 res[1].flags = IORESOURCE_MEM;
186 res[1].start = ORION5X_PCIE_MEM_PHYS_BASE;
187 res[1].end = res[1].start + ORION5X_PCIE_MEM_SIZE - 1;
188 if (request_resource(&iomem_resource, &res[1]))
189 panic("Request PCIe Memory resource failed\n");
190 sys->resource[1] = &res[1];
191
192 sys->resource[2] = NULL;
193 sys->io_offset = 0;
194
195 return 1;
196}
197
198/*****************************************************************************
199 * PCI controller
200 ****************************************************************************/
201#define PCI_MODE ORION5X_PCI_REG(0xd00)
202#define PCI_CMD ORION5X_PCI_REG(0xc00)
203#define PCI_P2P_CONF ORION5X_PCI_REG(0x1d14)
204#define PCI_CONF_ADDR ORION5X_PCI_REG(0xc78)
205#define PCI_CONF_DATA ORION5X_PCI_REG(0xc7c)
206
207/*
208 * PCI_MODE bits
209 */
210#define PCI_MODE_64BIT (1 << 2)
211#define PCI_MODE_PCIX ((1 << 4) | (1 << 5))
212
213/*
214 * PCI_CMD bits
215 */
216#define PCI_CMD_HOST_REORDER (1 << 29)
217
218/*
219 * PCI_P2P_CONF bits
220 */
221#define PCI_P2P_BUS_OFFS 16
222#define PCI_P2P_BUS_MASK (0xff << PCI_P2P_BUS_OFFS)
223#define PCI_P2P_DEV_OFFS 24
224#define PCI_P2P_DEV_MASK (0x1f << PCI_P2P_DEV_OFFS)
225
226/*
227 * PCI_CONF_ADDR bits
228 */
229#define PCI_CONF_REG(reg) ((reg) & 0xfc)
230#define PCI_CONF_FUNC(func) (((func) & 0x3) << 8)
231#define PCI_CONF_DEV(dev) (((dev) & 0x1f) << 11)
232#define PCI_CONF_BUS(bus) (((bus) & 0xff) << 16)
233#define PCI_CONF_ADDR_EN (1 << 31)
234
235/*
236 * Internal configuration space
237 */
238#define PCI_CONF_FUNC_STAT_CMD 0
239#define PCI_CONF_REG_STAT_CMD 4
240#define PCIX_STAT 0x64
241#define PCIX_STAT_BUS_OFFS 8
242#define PCIX_STAT_BUS_MASK (0xff << PCIX_STAT_BUS_OFFS)
243
244/*
245 * PCI Address Decode Windows registers
246 */
247#define PCI_BAR_SIZE_DDR_CS(n) (((n) == 0) ? ORION5X_PCI_REG(0xc08) : \
248 ((n) == 1) ? ORION5X_PCI_REG(0xd08) : \
249 ((n) == 2) ? ORION5X_PCI_REG(0xc0c) : \
250 ((n) == 3) ? ORION5X_PCI_REG(0xd0c) : 0)
251#define PCI_BAR_REMAP_DDR_CS(n) (((n) ==0) ? ORION5X_PCI_REG(0xc48) : \
252 ((n) == 1) ? ORION5X_PCI_REG(0xd48) : \
253 ((n) == 2) ? ORION5X_PCI_REG(0xc4c) : \
254 ((n) == 3) ? ORION5X_PCI_REG(0xd4c) : 0)
255#define PCI_BAR_ENABLE ORION5X_PCI_REG(0xc3c)
256#define PCI_ADDR_DECODE_CTRL ORION5X_PCI_REG(0xd3c)
257
258/*
259 * PCI configuration helpers for BAR settings
260 */
261#define PCI_CONF_FUNC_BAR_CS(n) ((n) >> 1)
262#define PCI_CONF_REG_BAR_LO_CS(n) (((n) & 1) ? 0x18 : 0x10)
263#define PCI_CONF_REG_BAR_HI_CS(n) (((n) & 1) ? 0x1c : 0x14)
264
265/*
266 * PCI config cycles are done by programming the PCI_CONF_ADDR register
267 * and then reading the PCI_CONF_DATA register. Need to make sure these
268 * transactions are atomic.
269 */
270static DEFINE_SPINLOCK(orion5x_pci_lock);
271
272int orion5x_pci_local_bus_nr(void)
273{
274 u32 conf = orion5x_read(PCI_P2P_CONF);
275 return((conf & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS);
276}
277
278static int orion5x_pci_hw_rd_conf(int bus, int dev, u32 func,
279 u32 where, u32 size, u32 *val)
280{
281 unsigned long flags;
282 spin_lock_irqsave(&orion5x_pci_lock, flags);
283
284 orion5x_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) |
285 PCI_CONF_DEV(dev) | PCI_CONF_REG(where) |
286 PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN);
287
288 *val = orion5x_read(PCI_CONF_DATA);
289
290 if (size == 1)
291 *val = (*val >> (8*(where & 0x3))) & 0xff;
292 else if (size == 2)
293 *val = (*val >> (8*(where & 0x3))) & 0xffff;
294
295 spin_unlock_irqrestore(&orion5x_pci_lock, flags);
296
297 return PCIBIOS_SUCCESSFUL;
298}
299
300static int orion5x_pci_hw_wr_conf(int bus, int dev, u32 func,
301 u32 where, u32 size, u32 val)
302{
303 unsigned long flags;
304 int ret = PCIBIOS_SUCCESSFUL;
305
306 spin_lock_irqsave(&orion5x_pci_lock, flags);
307
308 orion5x_write(PCI_CONF_ADDR, PCI_CONF_BUS(bus) |
309 PCI_CONF_DEV(dev) | PCI_CONF_REG(where) |
310 PCI_CONF_FUNC(func) | PCI_CONF_ADDR_EN);
311
312 if (size == 4) {
313 __raw_writel(val, PCI_CONF_DATA);
314 } else if (size == 2) {
315 __raw_writew(val, PCI_CONF_DATA + (where & 0x3));
316 } else if (size == 1) {
317 __raw_writeb(val, PCI_CONF_DATA + (where & 0x3));
318 } else {
319 ret = PCIBIOS_BAD_REGISTER_NUMBER;
320 }
321
322 spin_unlock_irqrestore(&orion5x_pci_lock, flags);
323
324 return ret;
325}
326
327static int orion5x_pci_rd_conf(struct pci_bus *bus, u32 devfn,
328 int where, int size, u32 *val)
329{
330 /*
331 * Don't go out for local device
332 */
333 if (bus->number == orion5x_pci_local_bus_nr() &&
334 PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0) {
335 *val = 0xffffffff;
336 return PCIBIOS_DEVICE_NOT_FOUND;
337 }
338
339 return orion5x_pci_hw_rd_conf(bus->number, PCI_SLOT(devfn),
340 PCI_FUNC(devfn), where, size, val);
341}
342
343static int orion5x_pci_wr_conf(struct pci_bus *bus, u32 devfn,
344 int where, int size, u32 val)
345{
346 if (bus->number == orion5x_pci_local_bus_nr() &&
347 PCI_SLOT(devfn) == 0 && PCI_FUNC(devfn) != 0)
348 return PCIBIOS_DEVICE_NOT_FOUND;
349
350 return orion5x_pci_hw_wr_conf(bus->number, PCI_SLOT(devfn),
351 PCI_FUNC(devfn), where, size, val);
352}
353
354static struct pci_ops pci_ops = {
355 .read = orion5x_pci_rd_conf,
356 .write = orion5x_pci_wr_conf,
357};
358
359static void __init orion5x_pci_set_bus_nr(int nr)
360{
361 u32 p2p = orion5x_read(PCI_P2P_CONF);
362
363 if (orion5x_read(PCI_MODE) & PCI_MODE_PCIX) {
364 /*
365 * PCI-X mode
366 */
367 u32 pcix_status, bus, dev;
368 bus = (p2p & PCI_P2P_BUS_MASK) >> PCI_P2P_BUS_OFFS;
369 dev = (p2p & PCI_P2P_DEV_MASK) >> PCI_P2P_DEV_OFFS;
370 orion5x_pci_hw_rd_conf(bus, dev, 0, PCIX_STAT, 4, &pcix_status);
371 pcix_status &= ~PCIX_STAT_BUS_MASK;
372 pcix_status |= (nr << PCIX_STAT_BUS_OFFS);
373 orion5x_pci_hw_wr_conf(bus, dev, 0, PCIX_STAT, 4, pcix_status);
374 } else {
375 /*
376 * PCI Conventional mode
377 */
378 p2p &= ~PCI_P2P_BUS_MASK;
379 p2p |= (nr << PCI_P2P_BUS_OFFS);
380 orion5x_write(PCI_P2P_CONF, p2p);
381 }
382}
383
384static void __init orion5x_pci_master_slave_enable(void)
385{
386 int bus_nr, func, reg;
387 u32 val;
388
389 bus_nr = orion5x_pci_local_bus_nr();
390 func = PCI_CONF_FUNC_STAT_CMD;
391 reg = PCI_CONF_REG_STAT_CMD;
392 orion5x_pci_hw_rd_conf(bus_nr, 0, func, reg, 4, &val);
393 val |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
394 orion5x_pci_hw_wr_conf(bus_nr, 0, func, reg, 4, val | 0x7);
395}
396
397static void __init orion5x_setup_pci_wins(struct mbus_dram_target_info *dram)
398{
399 u32 win_enable;
400 int bus;
401 int i;
402
403 /*
404 * First, disable windows.
405 */
406 win_enable = 0xffffffff;
407 orion5x_write(PCI_BAR_ENABLE, win_enable);
408
409 /*
410 * Setup windows for DDR banks.
411 */
412 bus = orion5x_pci_local_bus_nr();
413
414 for (i = 0; i < dram->num_cs; i++) {
415 struct mbus_dram_window *cs = dram->cs + i;
416 u32 func = PCI_CONF_FUNC_BAR_CS(cs->cs_index);
417 u32 reg;
418 u32 val;
419
420 /*
421 * Write DRAM bank base address register.
422 */
423 reg = PCI_CONF_REG_BAR_LO_CS(cs->cs_index);
424 orion5x_pci_hw_rd_conf(bus, 0, func, reg, 4, &val);
425 val = (cs->base & 0xfffff000) | (val & 0xfff);
426 orion5x_pci_hw_wr_conf(bus, 0, func, reg, 4, val);
427
428 /*
429 * Write DRAM bank size register.
430 */
431 reg = PCI_CONF_REG_BAR_HI_CS(cs->cs_index);
432 orion5x_pci_hw_wr_conf(bus, 0, func, reg, 4, 0);
433 orion5x_write(PCI_BAR_SIZE_DDR_CS(cs->cs_index),
434 (cs->size - 1) & 0xfffff000);
435 orion5x_write(PCI_BAR_REMAP_DDR_CS(cs->cs_index),
436 cs->base & 0xfffff000);
437
438 /*
439 * Enable decode window for this chip select.
440 */
441 win_enable &= ~(1 << cs->cs_index);
442 }
443
444 /*
445 * Re-enable decode windows.
446 */
447 orion5x_write(PCI_BAR_ENABLE, win_enable);
448
449 /*
450 * Disable automatic update of address remaping when writing to BARs.
451 */
452 orion5x_setbits(PCI_ADDR_DECODE_CTRL, 1);
453}
454
455static int __init pci_setup(struct pci_sys_data *sys)
456{
457 struct resource *res;
458
459 /*
460 * Point PCI unit MBUS decode windows to DRAM space.
461 */
462 orion5x_setup_pci_wins(&orion5x_mbus_dram_info);
463
464 /*
465 * Master + Slave enable
466 */
467 orion5x_pci_master_slave_enable();
468
469 /*
470 * Force ordering
471 */
472 orion5x_setbits(PCI_CMD, PCI_CMD_HOST_REORDER);
473
474 /*
475 * Request resources
476 */
477 res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
478 if (!res)
479 panic("pci_setup unable to alloc resources");
480
481 /*
482 * IORESOURCE_IO
483 */
484 res[0].name = "PCI I/O Space";
485 res[0].flags = IORESOURCE_IO;
486 res[0].start = ORION5X_PCI_IO_BUS_BASE;
487 res[0].end = res[0].start + ORION5X_PCI_IO_SIZE - 1;
488 if (request_resource(&ioport_resource, &res[0]))
489 panic("Request PCI IO resource failed\n");
490 sys->resource[0] = &res[0];
491
492 /*
493 * IORESOURCE_MEM
494 */
495 res[1].name = "PCI Memory Space";
496 res[1].flags = IORESOURCE_MEM;
497 res[1].start = ORION5X_PCI_MEM_PHYS_BASE;
498 res[1].end = res[1].start + ORION5X_PCI_MEM_SIZE - 1;
499 if (request_resource(&iomem_resource, &res[1]))
500 panic("Request PCI Memory resource failed\n");
501 sys->resource[1] = &res[1];
502
503 sys->resource[2] = NULL;
504 sys->io_offset = 0;
505
506 return 1;
507}
508
509
510/*****************************************************************************
511 * General PCIe + PCI
512 ****************************************************************************/
513static void __devinit rc_pci_fixup(struct pci_dev *dev)
514{
515 /*
516 * Prevent enumeration of root complex.
517 */
518 if (dev->bus->parent == NULL && dev->devfn == 0) {
519 int i;
520
521 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
522 dev->resource[i].start = 0;
523 dev->resource[i].end = 0;
524 dev->resource[i].flags = 0;
525 }
526 }
527}
528DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
529
530int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys)
531{
532 int ret = 0;
533
534 if (nr == 0) {
535 orion_pcie_set_local_bus_nr(PCIE_BASE, sys->busnr);
536 ret = pcie_setup(sys);
537 } else if (nr == 1) {
538 orion5x_pci_set_bus_nr(sys->busnr);
539 ret = pci_setup(sys);
540 }
541
542 return ret;
543}
544
545struct pci_bus __init *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys)
546{
547 struct pci_bus *bus;
548
549 if (nr == 0) {
550 bus = pci_scan_bus(sys->busnr, &pcie_ops, sys);
551 } else if (nr == 1) {
552 bus = pci_scan_bus(sys->busnr, &pci_ops, sys);
553 } else {
554 bus = NULL;
555 BUG();
556 }
557
558 return bus;
559}
diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c
new file mode 100644
index 00000000000..37e8b2dc3ed
--- /dev/null
+++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
@@ -0,0 +1,312 @@
1/*
2 * arch/arm/mach-orion5x/rd88f5182-setup.c
3 *
4 * Marvell Orion-NAS Reference Design Setup
5 *
6 * Maintainer: Ronen Shitrit <rshitrit@marvell.com>
7 *
8 * This file is licensed under the terms of the GNU General Public
9 * License version 2. This program is licensed "as is" without any
10 * warranty of any kind, whether express or implied.
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/pci.h>
17#include <linux/irq.h>
18#include <linux/mtd/physmap.h>
19#include <linux/mv643xx_eth.h>
20#include <linux/ata_platform.h>
21#include <linux/i2c.h>
22#include <asm/mach-types.h>
23#include <asm/gpio.h>
24#include <asm/leds.h>
25#include <asm/mach/arch.h>
26#include <asm/mach/pci.h>
27#include <asm/arch/orion5x.h>
28#include "common.h"
29
30/*****************************************************************************
31 * RD-88F5182 Info
32 ****************************************************************************/
33
34/*
35 * 512K NOR flash Device bus boot chip select
36 */
37
38#define RD88F5182_NOR_BOOT_BASE 0xf4000000
39#define RD88F5182_NOR_BOOT_SIZE SZ_512K
40
41/*
42 * 16M NOR flash on Device bus chip select 1
43 */
44
45#define RD88F5182_NOR_BASE 0xfc000000
46#define RD88F5182_NOR_SIZE SZ_16M
47
48/*
49 * PCI
50 */
51
52#define RD88F5182_PCI_SLOT0_OFFS 7
53#define RD88F5182_PCI_SLOT0_IRQ_A_PIN 7
54#define RD88F5182_PCI_SLOT0_IRQ_B_PIN 6
55
56/*
57 * GPIO Debug LED
58 */
59
60#define RD88F5182_GPIO_DBG_LED 0
61
62/*****************************************************************************
63 * 16M NOR Flash on Device bus CS1
64 ****************************************************************************/
65
66static struct physmap_flash_data rd88f5182_nor_flash_data = {
67 .width = 1,
68};
69
70static struct resource rd88f5182_nor_flash_resource = {
71 .flags = IORESOURCE_MEM,
72 .start = RD88F5182_NOR_BASE,
73 .end = RD88F5182_NOR_BASE + RD88F5182_NOR_SIZE - 1,
74};
75
76static struct platform_device rd88f5182_nor_flash = {
77 .name = "physmap-flash",
78 .id = 0,
79 .dev = {
80 .platform_data = &rd88f5182_nor_flash_data,
81 },
82 .num_resources = 1,
83 .resource = &rd88f5182_nor_flash_resource,
84};
85
86#ifdef CONFIG_LEDS
87
88/*****************************************************************************
89 * Use GPIO debug led as CPU active indication
90 ****************************************************************************/
91
92static void rd88f5182_dbgled_event(led_event_t evt)
93{
94 int val;
95
96 if (evt == led_idle_end)
97 val = 1;
98 else if (evt == led_idle_start)
99 val = 0;
100 else
101 return;
102
103 gpio_set_value(RD88F5182_GPIO_DBG_LED, val);
104}
105
106static int __init rd88f5182_dbgled_init(void)
107{
108 int pin;
109
110 if (machine_is_rd88f5182()) {
111 pin = RD88F5182_GPIO_DBG_LED;
112
113 if (gpio_request(pin, "DBGLED") == 0) {
114 if (gpio_direction_output(pin, 0) != 0) {
115 printk(KERN_ERR "rd88f5182_dbgled_init failed "
116 "to set output pin %d\n", pin);
117 gpio_free(pin);
118 return 0;
119 }
120 } else {
121 printk(KERN_ERR "rd88f5182_dbgled_init failed "
122 "to request gpio %d\n", pin);
123 return 0;
124 }
125
126 leds_event = rd88f5182_dbgled_event;
127 }
128 return 0;
129}
130
131__initcall(rd88f5182_dbgled_init);
132
133#endif
134
135/*****************************************************************************
136 * PCI
137 ****************************************************************************/
138
139void __init rd88f5182_pci_preinit(void)
140{
141 int pin;
142
143 /*
144 * Configure PCI GPIO IRQ pins
145 */
146 pin = RD88F5182_PCI_SLOT0_IRQ_A_PIN;
147 if (gpio_request(pin, "PCI IntA") == 0) {
148 if (gpio_direction_input(pin) == 0) {
149 set_irq_type(gpio_to_irq(pin), IRQT_LOW);
150 } else {
151 printk(KERN_ERR "rd88f5182_pci_preinit faield to "
152 "set_irq_type pin %d\n", pin);
153 gpio_free(pin);
154 }
155 } else {
156 printk(KERN_ERR "rd88f5182_pci_preinit failed to request gpio %d\n", pin);
157 }
158
159 pin = RD88F5182_PCI_SLOT0_IRQ_B_PIN;
160 if (gpio_request(pin, "PCI IntB") == 0) {
161 if (gpio_direction_input(pin) == 0) {
162 set_irq_type(gpio_to_irq(pin), IRQT_LOW);
163 } else {
164 printk(KERN_ERR "rd88f5182_pci_preinit faield to "
165 "set_irq_type pin %d\n", pin);
166 gpio_free(pin);
167 }
168 } else {
169 printk(KERN_ERR "rd88f5182_pci_preinit failed to gpio_request %d\n", pin);
170 }
171}
172
173static int __init rd88f5182_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
174{
175 /*
176 * PCI-E isn't used on the RD2
177 */
178 if (dev->bus->number == orion5x_pcie_local_bus_nr())
179 return IRQ_ORION5X_PCIE0_INT;
180
181 /*
182 * PCI IRQs are connected via GPIOs
183 */
184 switch (slot - RD88F5182_PCI_SLOT0_OFFS) {
185 case 0:
186 if (pin == 1)
187 return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_A_PIN);
188 else
189 return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_B_PIN);
190 default:
191 return -1;
192 }
193}
194
195static struct hw_pci rd88f5182_pci __initdata = {
196 .nr_controllers = 2,
197 .preinit = rd88f5182_pci_preinit,
198 .swizzle = pci_std_swizzle,
199 .setup = orion5x_pci_sys_setup,
200 .scan = orion5x_pci_sys_scan_bus,
201 .map_irq = rd88f5182_pci_map_irq,
202};
203
204static int __init rd88f5182_pci_init(void)
205{
206 if (machine_is_rd88f5182())
207 pci_common_init(&rd88f5182_pci);
208
209 return 0;
210}
211
212subsys_initcall(rd88f5182_pci_init);
213
214/*****************************************************************************
215 * Ethernet
216 ****************************************************************************/
217
218static struct mv643xx_eth_platform_data rd88f5182_eth_data = {
219 .phy_addr = 8,
220 .force_phy_addr = 1,
221};
222
223/*****************************************************************************
224 * RTC DS1338 on I2C bus
225 ****************************************************************************/
226static struct i2c_board_info __initdata rd88f5182_i2c_rtc = {
227 .driver_name = "rtc-ds1307",
228 .type = "ds1338",
229 .addr = 0x68,
230};
231
232/*****************************************************************************
233 * Sata
234 ****************************************************************************/
235static struct mv_sata_platform_data rd88f5182_sata_data = {
236 .n_ports = 2,
237};
238
239/*****************************************************************************
240 * General Setup
241 ****************************************************************************/
242
243static struct platform_device *rd88f5182_devices[] __initdata = {
244 &rd88f5182_nor_flash,
245};
246
247static void __init rd88f5182_init(void)
248{
249 /*
250 * Setup basic Orion functions. Need to be called early.
251 */
252 orion5x_init();
253
254 /*
255 * Setup the CPU address decode windows for our devices
256 */
257 orion5x_setup_dev_boot_win(RD88F5182_NOR_BOOT_BASE,
258 RD88F5182_NOR_BOOT_SIZE);
259 orion5x_setup_dev1_win(RD88F5182_NOR_BASE, RD88F5182_NOR_SIZE);
260
261 /*
262 * Open a special address decode windows for the PCIE WA.
263 */
264 orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
265 ORION5X_PCIE_WA_SIZE);
266
267 /*
268 * Setup Multiplexing Pins --
269 * MPP[0] Debug Led (GPIO - Out)
270 * MPP[1] Debug Led (GPIO - Out)
271 * MPP[2] N/A
272 * MPP[3] RTC_Int (GPIO - In)
273 * MPP[4] GPIO
274 * MPP[5] GPIO
275 * MPP[6] PCI_intA (GPIO - In)
276 * MPP[7] PCI_intB (GPIO - In)
277 * MPP[8-11] N/A
278 * MPP[12] SATA 0 presence Indication
279 * MPP[13] SATA 1 presence Indication
280 * MPP[14] SATA 0 active Indication
281 * MPP[15] SATA 1 active indication
282 * MPP[16-19] Not used
283 * MPP[20] PCI Clock to MV88F5182
284 * MPP[21] PCI Clock to mini PCI CON11
285 * MPP[22] USB 0 over current indication
286 * MPP[23] USB 1 over current indication
287 * MPP[24] USB 1 over current enable
288 * MPP[25] USB 0 over current enable
289 */
290
291 orion5x_write(MPP_0_7_CTRL, 0x00000003);
292 orion5x_write(MPP_8_15_CTRL, 0x55550000);
293 orion5x_write(MPP_16_19_CTRL, 0x5555);
294
295 orion5x_gpio_set_valid_pins(0x000000fb);
296
297 platform_add_devices(rd88f5182_devices, ARRAY_SIZE(rd88f5182_devices));
298 i2c_register_board_info(0, &rd88f5182_i2c_rtc, 1);
299 orion5x_eth_init(&rd88f5182_eth_data);
300 orion5x_sata_init(&rd88f5182_sata_data);
301}
302
303MACHINE_START(RD88F5182, "Marvell Orion-NAS Reference Design")
304 /* Maintainer: Ronen Shitrit <rshitrit@marvell.com> */
305 .phys_io = ORION5X_REGS_PHYS_BASE,
306 .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
307 .boot_params = 0x00000100,
308 .init_machine = rd88f5182_init,
309 .map_io = orion5x_map_io,
310 .init_irq = orion5x_init_irq,
311 .timer = &orion5x_timer,
312MACHINE_END
diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c
new file mode 100644
index 00000000000..71b0cffa2fe
--- /dev/null
+++ b/arch/arm/mach-orion5x/ts209-setup.c
@@ -0,0 +1,359 @@
1/*
2 * QNAP TS-109/TS-209 Board Setup
3 *
4 * Maintainer: Byron Bradley <byron.bbradley@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/kernel.h>
13#include <linux/init.h>
14#include <linux/platform_device.h>
15#include <linux/pci.h>
16#include <linux/irq.h>
17#include <linux/mtd/physmap.h>
18#include <linux/mtd/nand.h>
19#include <linux/mv643xx_eth.h>
20#include <linux/gpio_keys.h>
21#include <linux/input.h>
22#include <linux/i2c.h>
23#include <linux/serial_reg.h>
24#include <linux/ata_platform.h>
25#include <asm/mach-types.h>
26#include <asm/gpio.h>
27#include <asm/mach/arch.h>
28#include <asm/mach/pci.h>
29#include <asm/arch/orion5x.h>
30#include "common.h"
31
32#define QNAP_TS209_NOR_BOOT_BASE 0xf4000000
33#define QNAP_TS209_NOR_BOOT_SIZE SZ_8M
34
35/****************************************************************************
36 * 8MiB NOR flash. The struct mtd_partition is not in the same order as the
37 * partitions on the device because we want to keep compatability with
38 * existing QNAP firmware.
39 *
40 * Layout as used by QNAP:
41 * [2] 0x00000000-0x00200000 : "Kernel"
42 * [3] 0x00200000-0x00600000 : "RootFS1"
43 * [4] 0x00600000-0x00700000 : "RootFS2"
44 * [6] 0x00700000-0x00760000 : "NAS Config" (read-only)
45 * [5] 0x00760000-0x00780000 : "U-Boot Config"
46 * [1] 0x00780000-0x00800000 : "U-Boot" (read-only)
47 ***************************************************************************/
48static struct mtd_partition qnap_ts209_partitions[] = {
49 {
50 .name = "U-Boot",
51 .size = 0x00080000,
52 .offset = 0x00780000,
53 .mask_flags = MTD_WRITEABLE,
54 }, {
55 .name = "Kernel",
56 .size = 0x00200000,
57 .offset = 0,
58 }, {
59 .name = "RootFS1",
60 .size = 0x00400000,
61 .offset = 0x00200000,
62 }, {
63 .name = "RootFS2",
64 .size = 0x00100000,
65 .offset = 0x00600000,
66 }, {
67 .name = "U-Boot Config",
68 .size = 0x00020000,
69 .offset = 0x00760000,
70 }, {
71 .name = "NAS Config",
72 .size = 0x00060000,
73 .offset = 0x00700000,
74 .mask_flags = MTD_WRITEABLE,
75 }
76};
77
78static struct physmap_flash_data qnap_ts209_nor_flash_data = {
79 .width = 1,
80 .parts = qnap_ts209_partitions,
81 .nr_parts = ARRAY_SIZE(qnap_ts209_partitions)
82};
83
84static struct resource qnap_ts209_nor_flash_resource = {
85 .flags = IORESOURCE_MEM,
86 .start = QNAP_TS209_NOR_BOOT_BASE,
87 .end = QNAP_TS209_NOR_BOOT_BASE + QNAP_TS209_NOR_BOOT_SIZE - 1,
88};
89
90static struct platform_device qnap_ts209_nor_flash = {
91 .name = "physmap-flash",
92 .id = 0,
93 .dev = { .platform_data = &qnap_ts209_nor_flash_data, },
94 .resource = &qnap_ts209_nor_flash_resource,
95 .num_resources = 1,
96};
97
98/*****************************************************************************
99 * PCI
100 ****************************************************************************/
101
102#define QNAP_TS209_PCI_SLOT0_OFFS 7
103#define QNAP_TS209_PCI_SLOT0_IRQ_PIN 6
104#define QNAP_TS209_PCI_SLOT1_IRQ_PIN 7
105
106void __init qnap_ts209_pci_preinit(void)
107{
108 int pin;
109
110 /*
111 * Configure PCI GPIO IRQ pins
112 */
113 pin = QNAP_TS209_PCI_SLOT0_IRQ_PIN;
114 if (gpio_request(pin, "PCI Int1") == 0) {
115 if (gpio_direction_input(pin) == 0) {
116 set_irq_type(gpio_to_irq(pin), IRQT_LOW);
117 } else {
118 printk(KERN_ERR "qnap_ts209_pci_preinit failed to "
119 "set_irq_type pin %d\n", pin);
120 gpio_free(pin);
121 }
122 } else {
123 printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request "
124 "%d\n", pin);
125 }
126
127 pin = QNAP_TS209_PCI_SLOT1_IRQ_PIN;
128 if (gpio_request(pin, "PCI Int2") == 0) {
129 if (gpio_direction_input(pin) == 0) {
130 set_irq_type(gpio_to_irq(pin), IRQT_LOW);
131 } else {
132 printk(KERN_ERR "qnap_ts209_pci_preinit failed "
133 "to set_irq_type pin %d\n", pin);
134 gpio_free(pin);
135 }
136 } else {
137 printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request "
138 "%d\n", pin);
139 }
140}
141
142static int __init qnap_ts209_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
143{
144 /*
145 * PCIE IRQ is connected internally (not GPIO)
146 */
147 if (dev->bus->number == orion5x_pcie_local_bus_nr())
148 return IRQ_ORION5X_PCIE0_INT;
149
150 /*
151 * PCI IRQs are connected via GPIOs
152 */
153 switch (slot - QNAP_TS209_PCI_SLOT0_OFFS) {
154 case 0:
155 return gpio_to_irq(QNAP_TS209_PCI_SLOT0_IRQ_PIN);
156 case 1:
157 return gpio_to_irq(QNAP_TS209_PCI_SLOT1_IRQ_PIN);
158 default:
159 return -1;
160 }
161}
162
163static struct hw_pci qnap_ts209_pci __initdata = {
164 .nr_controllers = 2,
165 .preinit = qnap_ts209_pci_preinit,
166 .swizzle = pci_std_swizzle,
167 .setup = orion5x_pci_sys_setup,
168 .scan = orion5x_pci_sys_scan_bus,
169 .map_irq = qnap_ts209_pci_map_irq,
170};
171
172static int __init qnap_ts209_pci_init(void)
173{
174 if (machine_is_ts_x09())
175 pci_common_init(&qnap_ts209_pci);
176
177 return 0;
178}
179
180subsys_initcall(qnap_ts209_pci_init);
181
182/*****************************************************************************
183 * Ethernet
184 ****************************************************************************/
185
186static struct mv643xx_eth_platform_data qnap_ts209_eth_data = {
187 .phy_addr = 8,
188 .force_phy_addr = 1,
189};
190
191/*****************************************************************************
192 * RTC S35390A on I2C bus
193 ****************************************************************************/
194
195#define TS209_RTC_GPIO 3
196
197static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = {
198 .driver_name = "rtc-s35390a",
199 .addr = 0x30,
200 .irq = 0,
201};
202
203/****************************************************************************
204 * GPIO Attached Keys
205 * Power button is attached to the PIC microcontroller
206 ****************************************************************************/
207
208#define QNAP_TS209_GPIO_KEY_MEDIA 1
209#define QNAP_TS209_GPIO_KEY_RESET 2
210
211static struct gpio_keys_button qnap_ts209_buttons[] = {
212 {
213 .code = KEY_RESTART,
214 .gpio = QNAP_TS209_GPIO_KEY_MEDIA,
215 .desc = "USB Copy Button",
216 .active_low = 1,
217 },
218 {
219 .code = KEY_POWER,
220 .gpio = QNAP_TS209_GPIO_KEY_RESET,
221 .desc = "Reset Button",
222 .active_low = 1,
223 }
224};
225
226static struct gpio_keys_platform_data qnap_ts209_button_data = {
227 .buttons = qnap_ts209_buttons,
228 .nbuttons = ARRAY_SIZE(qnap_ts209_buttons),
229};
230
231static struct platform_device qnap_ts209_button_device = {
232 .name = "gpio-keys",
233 .id = -1,
234 .num_resources = 0,
235 .dev = { .platform_data = &qnap_ts209_button_data, },
236};
237
238/*****************************************************************************
239 * SATA
240 ****************************************************************************/
241static struct mv_sata_platform_data qnap_ts209_sata_data = {
242 .n_ports = 2,
243};
244
245/*****************************************************************************
246
247 * General Setup
248 ****************************************************************************/
249
250static struct platform_device *qnap_ts209_devices[] __initdata = {
251 &qnap_ts209_nor_flash,
252 &qnap_ts209_button_device,
253};
254
255/*
256 * QNAP TS-[12]09 specific power off method via UART1-attached PIC
257 */
258
259#define UART1_REG(x) (UART1_VIRT_BASE + ((UART_##x) << 2))
260
261static void qnap_ts209_power_off(void)
262{
263 /* 19200 baud divisor */
264 const unsigned divisor = ((ORION5X_TCLK + (8 * 19200)) / (16 * 19200));
265
266 pr_info("%s: triggering power-off...\n", __func__);
267
268 /* hijack uart1 and reset into sane state (19200,8n1) */
269 orion5x_write(UART1_REG(LCR), 0x83);
270 orion5x_write(UART1_REG(DLL), divisor & 0xff);
271 orion5x_write(UART1_REG(DLM), (divisor >> 8) & 0xff);
272 orion5x_write(UART1_REG(LCR), 0x03);
273 orion5x_write(UART1_REG(IER), 0x00);
274 orion5x_write(UART1_REG(FCR), 0x00);
275 orion5x_write(UART1_REG(MCR), 0x00);
276
277 /* send the power-off command 'A' to PIC */
278 orion5x_write(UART1_REG(TX), 'A');
279}
280
281static void __init qnap_ts209_init(void)
282{
283 /*
284 * Setup basic Orion functions. Need to be called early.
285 */
286 orion5x_init();
287
288 /*
289 * Setup flash mapping
290 */
291 orion5x_setup_dev_boot_win(QNAP_TS209_NOR_BOOT_BASE,
292 QNAP_TS209_NOR_BOOT_SIZE);
293
294 /*
295 * Open a special address decode windows for the PCIE WA.
296 */
297 orion5x_setup_pcie_wa_win(ORION5X_PCIE_WA_PHYS_BASE,
298 ORION5X_PCIE_WA_SIZE);
299
300 /*
301 * Setup Multiplexing Pins --
302 * MPP[0] Reserved
303 * MPP[1] USB copy button (0 active)
304 * MPP[2] Load defaults button (0 active)
305 * MPP[3] GPIO RTC
306 * MPP[4-5] Reserved
307 * MPP[6] PCI Int A
308 * MPP[7] PCI Int B
309 * MPP[8-11] Reserved
310 * MPP[12] SATA 0 presence
311 * MPP[13] SATA 1 presence
312 * MPP[14] SATA 0 active
313 * MPP[15] SATA 1 active
314 * MPP[16] UART1 RXD
315 * MPP[17] UART1 TXD
316 * MPP[18] SW_RST (0 active)
317 * MPP[19] Reserved
318 * MPP[20] PCI clock 0
319 * MPP[21] PCI clock 1
320 * MPP[22] USB 0 over current
321 * MPP[23-25] Reserved
322 */
323 orion5x_write(MPP_0_7_CTRL, 0x3);
324 orion5x_write(MPP_8_15_CTRL, 0x55550000);
325 orion5x_write(MPP_16_19_CTRL, 0x5500);
326 orion5x_gpio_set_valid_pins(0x3cc0fff);
327
328 /* register ts209 specific power-off method */
329 pm_power_off = qnap_ts209_power_off;
330
331 platform_add_devices(qnap_ts209_devices,
332 ARRAY_SIZE(qnap_ts209_devices));
333
334 /* Get RTC IRQ and register the chip */
335 if (gpio_request(TS209_RTC_GPIO, "rtc") == 0) {
336 if (gpio_direction_input(TS209_RTC_GPIO) == 0)
337 qnap_ts209_i2c_rtc.irq = gpio_to_irq(TS209_RTC_GPIO);
338 else
339 gpio_free(TS209_RTC_GPIO);
340 }
341 if (qnap_ts209_i2c_rtc.irq == 0)
342 pr_warning("qnap_ts209_init: failed to get RTC IRQ\n");
343 i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1);
344
345 orion5x_eth_init(&qnap_ts209_eth_data);
346 orion5x_sata_init(&qnap_ts209_sata_data);
347}
348
349MACHINE_START(TS209, "QNAP TS-109/TS-209")
350 /* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */
351 .phys_io = ORION5X_REGS_PHYS_BASE,
352 .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC,
353 .boot_params = 0x00000100,
354 .init_machine = qnap_ts209_init,
355 .map_io = orion5x_map_io,
356 .init_irq = orion5x_init_irq,
357 .timer = &orion5x_timer,
358 .fixup = tag_fixup_mem32,
359MACHINE_END