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