Commit | Line | Data |
---|---|---|
3faf2ee8 BB |
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> | |
8f86dda3 | 23 | #include <linux/serial_reg.h> |
ee44391e | 24 | #include <linux/ata_platform.h> |
3faf2ee8 BB |
25 | #include <asm/mach-types.h> |
26 | #include <asm/gpio.h> | |
27 | #include <asm/mach/arch.h> | |
28 | #include <asm/mach/pci.h> | |
a09e64fb | 29 | #include <mach/orion5x.h> |
3faf2ee8 | 30 | #include "common.h" |
19cfd5c0 | 31 | #include "mpp.h" |
530c854a | 32 | #include "tsx09-common.h" |
3faf2ee8 BB |
33 | |
34 | #define QNAP_TS209_NOR_BOOT_BASE 0xf4000000 | |
35 | #define QNAP_TS209_NOR_BOOT_SIZE SZ_8M | |
36 | ||
37 | /**************************************************************************** | |
38 | * 8MiB NOR flash. The struct mtd_partition is not in the same order as the | |
39 | * partitions on the device because we want to keep compatability with | |
40 | * existing QNAP firmware. | |
41 | * | |
42 | * Layout as used by QNAP: | |
43 | * [2] 0x00000000-0x00200000 : "Kernel" | |
44 | * [3] 0x00200000-0x00600000 : "RootFS1" | |
45 | * [4] 0x00600000-0x00700000 : "RootFS2" | |
46 | * [6] 0x00700000-0x00760000 : "NAS Config" (read-only) | |
47 | * [5] 0x00760000-0x00780000 : "U-Boot Config" | |
48 | * [1] 0x00780000-0x00800000 : "U-Boot" (read-only) | |
49 | ***************************************************************************/ | |
50 | static struct mtd_partition qnap_ts209_partitions[] = { | |
51 | { | |
e7068ad3 LB |
52 | .name = "U-Boot", |
53 | .size = 0x00080000, | |
54 | .offset = 0x00780000, | |
55 | .mask_flags = MTD_WRITEABLE, | |
3faf2ee8 | 56 | }, { |
e7068ad3 LB |
57 | .name = "Kernel", |
58 | .size = 0x00200000, | |
59 | .offset = 0, | |
3faf2ee8 | 60 | }, { |
e7068ad3 LB |
61 | .name = "RootFS1", |
62 | .size = 0x00400000, | |
63 | .offset = 0x00200000, | |
3faf2ee8 | 64 | }, { |
e7068ad3 LB |
65 | .name = "RootFS2", |
66 | .size = 0x00100000, | |
67 | .offset = 0x00600000, | |
3faf2ee8 | 68 | }, { |
e7068ad3 LB |
69 | .name = "U-Boot Config", |
70 | .size = 0x00020000, | |
71 | .offset = 0x00760000, | |
3faf2ee8 | 72 | }, { |
e7068ad3 LB |
73 | .name = "NAS Config", |
74 | .size = 0x00060000, | |
75 | .offset = 0x00700000, | |
76 | .mask_flags = MTD_WRITEABLE, | |
77 | }, | |
3faf2ee8 BB |
78 | }; |
79 | ||
80 | static struct physmap_flash_data qnap_ts209_nor_flash_data = { | |
e7068ad3 LB |
81 | .width = 1, |
82 | .parts = qnap_ts209_partitions, | |
83 | .nr_parts = ARRAY_SIZE(qnap_ts209_partitions) | |
3faf2ee8 BB |
84 | }; |
85 | ||
86 | static struct resource qnap_ts209_nor_flash_resource = { | |
e7068ad3 LB |
87 | .flags = IORESOURCE_MEM, |
88 | .start = QNAP_TS209_NOR_BOOT_BASE, | |
89 | .end = QNAP_TS209_NOR_BOOT_BASE + QNAP_TS209_NOR_BOOT_SIZE - 1, | |
3faf2ee8 BB |
90 | }; |
91 | ||
92 | static struct platform_device qnap_ts209_nor_flash = { | |
e7068ad3 LB |
93 | .name = "physmap-flash", |
94 | .id = 0, | |
95 | .dev = { | |
96 | .platform_data = &qnap_ts209_nor_flash_data, | |
97 | }, | |
98 | .resource = &qnap_ts209_nor_flash_resource, | |
99 | .num_resources = 1, | |
3faf2ee8 BB |
100 | }; |
101 | ||
102 | /***************************************************************************** | |
103 | * PCI | |
104 | ****************************************************************************/ | |
105 | ||
106 | #define QNAP_TS209_PCI_SLOT0_OFFS 7 | |
107 | #define QNAP_TS209_PCI_SLOT0_IRQ_PIN 6 | |
108 | #define QNAP_TS209_PCI_SLOT1_IRQ_PIN 7 | |
109 | ||
110 | void __init qnap_ts209_pci_preinit(void) | |
111 | { | |
112 | int pin; | |
113 | ||
114 | /* | |
115 | * Configure PCI GPIO IRQ pins | |
116 | */ | |
117 | pin = QNAP_TS209_PCI_SLOT0_IRQ_PIN; | |
118 | if (gpio_request(pin, "PCI Int1") == 0) { | |
119 | if (gpio_direction_input(pin) == 0) { | |
6cab4860 | 120 | set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW); |
3faf2ee8 BB |
121 | } else { |
122 | printk(KERN_ERR "qnap_ts209_pci_preinit failed to " | |
123 | "set_irq_type pin %d\n", pin); | |
124 | gpio_free(pin); | |
125 | } | |
126 | } else { | |
127 | printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request " | |
128 | "%d\n", pin); | |
129 | } | |
130 | ||
131 | pin = QNAP_TS209_PCI_SLOT1_IRQ_PIN; | |
132 | if (gpio_request(pin, "PCI Int2") == 0) { | |
133 | if (gpio_direction_input(pin) == 0) { | |
6cab4860 | 134 | set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW); |
3faf2ee8 BB |
135 | } else { |
136 | printk(KERN_ERR "qnap_ts209_pci_preinit failed " | |
137 | "to set_irq_type pin %d\n", pin); | |
138 | gpio_free(pin); | |
139 | } | |
140 | } else { | |
141 | printk(KERN_ERR "qnap_ts209_pci_preinit failed to gpio_request " | |
142 | "%d\n", pin); | |
143 | } | |
144 | } | |
145 | ||
146 | static int __init qnap_ts209_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) | |
147 | { | |
92b913b0 LB |
148 | int irq; |
149 | ||
3faf2ee8 | 150 | /* |
92b913b0 | 151 | * Check for devices with hard-wired IRQs. |
3faf2ee8 | 152 | */ |
92b913b0 LB |
153 | irq = orion5x_pci_map_irq(dev, slot, pin); |
154 | if (irq != -1) | |
155 | return irq; | |
3faf2ee8 BB |
156 | |
157 | /* | |
92b913b0 | 158 | * PCI IRQs are connected via GPIOs. |
3faf2ee8 BB |
159 | */ |
160 | switch (slot - QNAP_TS209_PCI_SLOT0_OFFS) { | |
161 | case 0: | |
162 | return gpio_to_irq(QNAP_TS209_PCI_SLOT0_IRQ_PIN); | |
163 | case 1: | |
164 | return gpio_to_irq(QNAP_TS209_PCI_SLOT1_IRQ_PIN); | |
165 | default: | |
166 | return -1; | |
167 | } | |
168 | } | |
169 | ||
170 | static struct hw_pci qnap_ts209_pci __initdata = { | |
e7068ad3 LB |
171 | .nr_controllers = 2, |
172 | .preinit = qnap_ts209_pci_preinit, | |
173 | .swizzle = pci_std_swizzle, | |
174 | .setup = orion5x_pci_sys_setup, | |
175 | .scan = orion5x_pci_sys_scan_bus, | |
176 | .map_irq = qnap_ts209_pci_map_irq, | |
3faf2ee8 BB |
177 | }; |
178 | ||
179 | static int __init qnap_ts209_pci_init(void) | |
180 | { | |
181 | if (machine_is_ts_x09()) | |
182 | pci_common_init(&qnap_ts209_pci); | |
183 | ||
184 | return 0; | |
185 | } | |
186 | ||
187 | subsys_initcall(qnap_ts209_pci_init); | |
188 | ||
3faf2ee8 BB |
189 | /***************************************************************************** |
190 | * RTC S35390A on I2C bus | |
191 | ****************************************************************************/ | |
59e8ce57 BB |
192 | |
193 | #define TS209_RTC_GPIO 3 | |
194 | ||
3faf2ee8 | 195 | static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = { |
3760f736 | 196 | I2C_BOARD_INFO("s35390a", 0x30), |
e7068ad3 | 197 | .irq = 0, |
3faf2ee8 BB |
198 | }; |
199 | ||
200 | /**************************************************************************** | |
201 | * GPIO Attached Keys | |
202 | * Power button is attached to the PIC microcontroller | |
203 | ****************************************************************************/ | |
204 | ||
205 | #define QNAP_TS209_GPIO_KEY_MEDIA 1 | |
206 | #define QNAP_TS209_GPIO_KEY_RESET 2 | |
207 | ||
208 | static struct gpio_keys_button qnap_ts209_buttons[] = { | |
209 | { | |
28ca8c80 | 210 | .code = KEY_COPY, |
3faf2ee8 BB |
211 | .gpio = QNAP_TS209_GPIO_KEY_MEDIA, |
212 | .desc = "USB Copy Button", | |
213 | .active_low = 1, | |
e7068ad3 | 214 | }, { |
28ca8c80 | 215 | .code = KEY_RESTART, |
3faf2ee8 BB |
216 | .gpio = QNAP_TS209_GPIO_KEY_RESET, |
217 | .desc = "Reset Button", | |
218 | .active_low = 1, | |
e7068ad3 | 219 | }, |
3faf2ee8 BB |
220 | }; |
221 | ||
222 | static struct gpio_keys_platform_data qnap_ts209_button_data = { | |
223 | .buttons = qnap_ts209_buttons, | |
e7068ad3 | 224 | .nbuttons = ARRAY_SIZE(qnap_ts209_buttons), |
3faf2ee8 BB |
225 | }; |
226 | ||
227 | static struct platform_device qnap_ts209_button_device = { | |
228 | .name = "gpio-keys", | |
229 | .id = -1, | |
230 | .num_resources = 0, | |
e7068ad3 LB |
231 | .dev = { |
232 | .platform_data = &qnap_ts209_button_data, | |
233 | }, | |
3faf2ee8 BB |
234 | }; |
235 | ||
236 | /***************************************************************************** | |
ee44391e BB |
237 | * SATA |
238 | ****************************************************************************/ | |
239 | static struct mv_sata_platform_data qnap_ts209_sata_data = { | |
e7068ad3 | 240 | .n_ports = 2, |
ee44391e BB |
241 | }; |
242 | ||
243 | /***************************************************************************** | |
244 | ||
3faf2ee8 BB |
245 | * General Setup |
246 | ****************************************************************************/ | |
19cfd5c0 LB |
247 | static struct orion5x_mpp_mode ts209_mpp_modes[] __initdata = { |
248 | { 0, MPP_UNUSED }, | |
249 | { 1, MPP_GPIO }, /* USB copy button */ | |
250 | { 2, MPP_GPIO }, /* Load defaults button */ | |
251 | { 3, MPP_GPIO }, /* GPIO RTC */ | |
252 | { 4, MPP_UNUSED }, | |
253 | { 5, MPP_UNUSED }, | |
254 | { 6, MPP_GPIO }, /* PCI Int A */ | |
255 | { 7, MPP_GPIO }, /* PCI Int B */ | |
256 | { 8, MPP_UNUSED }, | |
257 | { 9, MPP_UNUSED }, | |
258 | { 10, MPP_UNUSED }, | |
259 | { 11, MPP_UNUSED }, | |
260 | { 12, MPP_SATA_LED }, /* SATA 0 presence */ | |
261 | { 13, MPP_SATA_LED }, /* SATA 1 presence */ | |
262 | { 14, MPP_SATA_LED }, /* SATA 0 active */ | |
263 | { 15, MPP_SATA_LED }, /* SATA 1 active */ | |
264 | { 16, MPP_UART }, /* UART1 RXD */ | |
265 | { 17, MPP_UART }, /* UART1 TXD */ | |
266 | { 18, MPP_GPIO }, /* SW_RST */ | |
267 | { 19, MPP_UNUSED }, | |
268 | { -1 }, | |
269 | }; | |
270 | ||
3faf2ee8 BB |
271 | static void __init qnap_ts209_init(void) |
272 | { | |
273 | /* | |
274 | * Setup basic Orion functions. Need to be called early. | |
275 | */ | |
9dd0b194 | 276 | orion5x_init(); |
3faf2ee8 | 277 | |
19cfd5c0 LB |
278 | orion5x_mpp_conf(ts209_mpp_modes); |
279 | ||
3faf2ee8 | 280 | /* |
3faf2ee8 BB |
281 | * MPP[20] PCI clock 0 |
282 | * MPP[21] PCI clock 1 | |
283 | * MPP[22] USB 0 over current | |
284 | * MPP[23-25] Reserved | |
285 | */ | |
3faf2ee8 | 286 | |
044f6c7c LB |
287 | /* |
288 | * Configure peripherals. | |
289 | */ | |
35228e84 MM |
290 | orion5x_setup_dev_boot_win(QNAP_TS209_NOR_BOOT_BASE, |
291 | QNAP_TS209_NOR_BOOT_SIZE); | |
292 | platform_device_register(&qnap_ts209_nor_flash); | |
293 | ||
044f6c7c LB |
294 | orion5x_ehci0_init(); |
295 | orion5x_ehci1_init(); | |
530c854a SB |
296 | qnap_tsx09_find_mac_addr(QNAP_TS209_NOR_BOOT_BASE + |
297 | qnap_ts209_partitions[5].offset, | |
298 | qnap_ts209_partitions[5].size); | |
299 | orion5x_eth_init(&qnap_tsx09_eth_data); | |
044f6c7c LB |
300 | orion5x_i2c_init(); |
301 | orion5x_sata_init(&qnap_ts209_sata_data); | |
302 | orion5x_uart0_init(); | |
e45772b2 | 303 | orion5x_uart1_init(); |
1d5a1a6e | 304 | orion5x_xor_init(); |
044f6c7c | 305 | |
044f6c7c | 306 | platform_device_register(&qnap_ts209_button_device); |
59e8ce57 BB |
307 | |
308 | /* Get RTC IRQ and register the chip */ | |
309 | if (gpio_request(TS209_RTC_GPIO, "rtc") == 0) { | |
310 | if (gpio_direction_input(TS209_RTC_GPIO) == 0) | |
311 | qnap_ts209_i2c_rtc.irq = gpio_to_irq(TS209_RTC_GPIO); | |
312 | else | |
313 | gpio_free(TS209_RTC_GPIO); | |
314 | } | |
315 | if (qnap_ts209_i2c_rtc.irq == 0) | |
316 | pr_warning("qnap_ts209_init: failed to get RTC IRQ\n"); | |
3faf2ee8 | 317 | i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1); |
59e8ce57 | 318 | |
530c854a SB |
319 | /* register tsx09 specific power-off method */ |
320 | pm_power_off = qnap_tsx09_power_off; | |
3faf2ee8 BB |
321 | } |
322 | ||
323 | MACHINE_START(TS209, "QNAP TS-109/TS-209") | |
e7068ad3 | 324 | /* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */ |
9dd0b194 LB |
325 | .phys_io = ORION5X_REGS_PHYS_BASE, |
326 | .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC, | |
3faf2ee8 BB |
327 | .boot_params = 0x00000100, |
328 | .init_machine = qnap_ts209_init, | |
9dd0b194 LB |
329 | .map_io = orion5x_map_io, |
330 | .init_irq = orion5x_init_irq, | |
331 | .timer = &orion5x_timer, | |
be73a347 | 332 | .fixup = tag_fixup_mem32, |
3faf2ee8 | 333 | MACHINE_END |