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