1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * QNAP TS-409 Board Setup 4 * 5 * Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> 6 * 7 * Copyright (C) 2008 Sylver Bruneau <sylver.bruneau@gmail.com> 8 * Copyright (C) 2008 Martin Michlmayr <tbm@cyrius.com> 9 */ 10 #include <linux/gpio.h> 11 #include <linux/gpio/machine.h> 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/mv643xx_eth.h> 19 #include <linux/leds.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 <asm/mach-types.h> 25 #include <asm/mach/arch.h> 26 #include <asm/mach/pci.h> 27 #include "common.h" 28 #include "mpp.h" 29 #include "orion5x.h" 30 #include "tsx09-common.h" 31 32 /***************************************************************************** 33 * QNAP TS-409 Info 34 ****************************************************************************/ 35 36 /* 37 * QNAP TS-409 hardware : 38 * - Marvell 88F5281-D0 39 * - Marvell 88SX7042 SATA controller (PCIe) 40 * - Marvell 88E1118 Gigabit Ethernet PHY 41 * - RTC S35390A (@0x30) on I2C bus 42 * - 8MB NOR flash 43 * - 256MB of DDR-2 RAM 44 */ 45 46 /* 47 * 8MB NOR flash Device bus boot chip select 48 */ 49 50 #define QNAP_TS409_NOR_BOOT_BASE 0xff800000 51 #define QNAP_TS409_NOR_BOOT_SIZE SZ_8M 52 53 /**************************************************************************** 54 * 8MiB NOR flash. The struct mtd_partition is not in the same order as the 55 * partitions on the device because we want to keep compatibility with 56 * existing QNAP firmware. 57 * 58 * Layout as used by QNAP: 59 * [2] 0x00000000-0x00200000 : "Kernel" 60 * [3] 0x00200000-0x00600000 : "RootFS1" 61 * [4] 0x00600000-0x00700000 : "RootFS2" 62 * [6] 0x00700000-0x00760000 : "NAS Config" (read-only) 63 * [5] 0x00760000-0x00780000 : "U-Boot Config" 64 * [1] 0x00780000-0x00800000 : "U-Boot" (read-only) 65 ***************************************************************************/ 66 static struct mtd_partition qnap_ts409_partitions[] = { 67 { 68 .name = "U-Boot", 69 .size = 0x00080000, 70 .offset = 0x00780000, 71 .mask_flags = MTD_WRITEABLE, 72 }, { 73 .name = "Kernel", 74 .size = 0x00200000, 75 .offset = 0, 76 }, { 77 .name = "RootFS1", 78 .size = 0x00400000, 79 .offset = 0x00200000, 80 }, { 81 .name = "RootFS2", 82 .size = 0x00100000, 83 .offset = 0x00600000, 84 }, { 85 .name = "U-Boot Config", 86 .size = 0x00020000, 87 .offset = 0x00760000, 88 }, { 89 .name = "NAS Config", 90 .size = 0x00060000, 91 .offset = 0x00700000, 92 .mask_flags = MTD_WRITEABLE, 93 }, 94 }; 95 96 static struct physmap_flash_data qnap_ts409_nor_flash_data = { 97 .width = 1, 98 .parts = qnap_ts409_partitions, 99 .nr_parts = ARRAY_SIZE(qnap_ts409_partitions) 100 }; 101 102 static struct resource qnap_ts409_nor_flash_resource = { 103 .flags = IORESOURCE_MEM, 104 .start = QNAP_TS409_NOR_BOOT_BASE, 105 .end = QNAP_TS409_NOR_BOOT_BASE + QNAP_TS409_NOR_BOOT_SIZE - 1, 106 }; 107 108 static struct platform_device qnap_ts409_nor_flash = { 109 .name = "physmap-flash", 110 .id = 0, 111 .dev = { .platform_data = &qnap_ts409_nor_flash_data, }, 112 .num_resources = 1, 113 .resource = &qnap_ts409_nor_flash_resource, 114 }; 115 116 /***************************************************************************** 117 * PCI 118 ****************************************************************************/ 119 120 static int __init qnap_ts409_pci_map_irq(const struct pci_dev *dev, u8 slot, 121 u8 pin) 122 { 123 int irq; 124 125 /* 126 * Check for devices with hard-wired IRQs. 127 */ 128 irq = orion5x_pci_map_irq(dev, slot, pin); 129 if (irq != -1) 130 return irq; 131 132 /* 133 * PCI isn't used on the TS-409 134 */ 135 return -1; 136 } 137 138 static struct hw_pci qnap_ts409_pci __initdata = { 139 .nr_controllers = 2, 140 .setup = orion5x_pci_sys_setup, 141 .scan = orion5x_pci_sys_scan_bus, 142 .map_irq = qnap_ts409_pci_map_irq, 143 }; 144 145 static int __init qnap_ts409_pci_init(void) 146 { 147 if (machine_is_ts409()) 148 pci_common_init(&qnap_ts409_pci); 149 150 return 0; 151 } 152 153 subsys_initcall(qnap_ts409_pci_init); 154 155 /***************************************************************************** 156 * RTC S35390A on I2C bus 157 ****************************************************************************/ 158 159 #define TS409_RTC_GPIO 10 160 161 static struct i2c_board_info __initdata qnap_ts409_i2c_rtc = { 162 I2C_BOARD_INFO("s35390a", 0x30), 163 }; 164 165 /***************************************************************************** 166 * LEDs attached to GPIO 167 ****************************************************************************/ 168 169 static struct gpio_led ts409_led_pins[] = { 170 { 171 .name = "ts409:red:sata1", 172 }, { 173 .name = "ts409:red:sata2", 174 }, { 175 .name = "ts409:red:sata3", 176 }, { 177 .name = "ts409:red:sata4", 178 }, 179 }; 180 181 static struct gpiod_lookup_table ts409_leds_gpio_table = { 182 .dev_id = "leds-gpio", 183 .table = { 184 GPIO_LOOKUP_IDX("orion_gpio0", 4, NULL, 185 0, GPIO_ACTIVE_LOW), 186 GPIO_LOOKUP_IDX("orion_gpio0", 5, NULL, 187 1, GPIO_ACTIVE_LOW), 188 GPIO_LOOKUP_IDX("orion_gpio0", 6, NULL, 189 2, GPIO_ACTIVE_LOW), 190 GPIO_LOOKUP_IDX("orion_gpio0", 7, NULL, 191 3, GPIO_ACTIVE_LOW), 192 { }, 193 }, 194 }; 195 196 static struct gpio_led_platform_data ts409_led_data = { 197 .leds = ts409_led_pins, 198 .num_leds = ARRAY_SIZE(ts409_led_pins), 199 }; 200 201 static struct platform_device ts409_leds = { 202 .name = "leds-gpio", 203 .id = -1, 204 .dev = { 205 .platform_data = &ts409_led_data, 206 }, 207 }; 208 209 /**************************************************************************** 210 * GPIO Attached Keys 211 * Power button is attached to the PIC microcontroller 212 ****************************************************************************/ 213 214 #define QNAP_TS409_GPIO_KEY_RESET 14 215 #define QNAP_TS409_GPIO_KEY_MEDIA 15 216 217 static struct gpio_keys_button qnap_ts409_buttons[] = { 218 { 219 .code = KEY_RESTART, 220 .gpio = QNAP_TS409_GPIO_KEY_RESET, 221 .desc = "Reset Button", 222 .active_low = 1, 223 }, { 224 .code = KEY_COPY, 225 .gpio = QNAP_TS409_GPIO_KEY_MEDIA, 226 .desc = "USB Copy Button", 227 .active_low = 1, 228 }, 229 }; 230 231 static struct gpio_keys_platform_data qnap_ts409_button_data = { 232 .buttons = qnap_ts409_buttons, 233 .nbuttons = ARRAY_SIZE(qnap_ts409_buttons), 234 }; 235 236 static struct platform_device qnap_ts409_button_device = { 237 .name = "gpio-keys", 238 .id = -1, 239 .num_resources = 0, 240 .dev = { 241 .platform_data = &qnap_ts409_button_data, 242 }, 243 }; 244 245 /***************************************************************************** 246 * General Setup 247 ****************************************************************************/ 248 static unsigned int ts409_mpp_modes[] __initdata = { 249 MPP0_UNUSED, 250 MPP1_UNUSED, 251 MPP2_UNUSED, 252 MPP3_UNUSED, 253 MPP4_GPIO, /* HDD 1 status */ 254 MPP5_GPIO, /* HDD 2 status */ 255 MPP6_GPIO, /* HDD 3 status */ 256 MPP7_GPIO, /* HDD 4 status */ 257 MPP8_UNUSED, 258 MPP9_UNUSED, 259 MPP10_GPIO, /* RTC int */ 260 MPP11_UNUSED, 261 MPP12_UNUSED, 262 MPP13_UNUSED, 263 MPP14_GPIO, /* SW_RST */ 264 MPP15_GPIO, /* USB copy button */ 265 MPP16_UART, /* UART1 RXD */ 266 MPP17_UART, /* UART1 TXD */ 267 MPP18_UNUSED, 268 MPP19_UNUSED, 269 0, 270 }; 271 272 static void __init qnap_ts409_init(void) 273 { 274 /* 275 * Setup basic Orion functions. Need to be called early. 276 */ 277 orion5x_init(); 278 279 orion5x_mpp_conf(ts409_mpp_modes); 280 281 /* 282 * Configure peripherals. 283 */ 284 mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET, 285 ORION_MBUS_DEVBUS_BOOT_ATTR, 286 QNAP_TS409_NOR_BOOT_BASE, 287 QNAP_TS409_NOR_BOOT_SIZE); 288 platform_device_register(&qnap_ts409_nor_flash); 289 290 orion5x_ehci0_init(); 291 qnap_tsx09_find_mac_addr(QNAP_TS409_NOR_BOOT_BASE + 292 qnap_ts409_partitions[5].offset, 293 qnap_ts409_partitions[5].size); 294 orion5x_eth_init(&qnap_tsx09_eth_data); 295 orion5x_i2c_init(); 296 orion5x_uart0_init(); 297 orion5x_uart1_init(); 298 299 platform_device_register(&qnap_ts409_button_device); 300 301 /* Get RTC IRQ and register the chip */ 302 if (gpio_request(TS409_RTC_GPIO, "rtc") == 0) { 303 if (gpio_direction_input(TS409_RTC_GPIO) == 0) 304 qnap_ts409_i2c_rtc.irq = gpio_to_irq(TS409_RTC_GPIO); 305 else 306 gpio_free(TS409_RTC_GPIO); 307 } 308 if (qnap_ts409_i2c_rtc.irq == 0) 309 pr_warn("qnap_ts409_init: failed to get RTC IRQ\n"); 310 i2c_register_board_info(0, &qnap_ts409_i2c_rtc, 1); 311 gpiod_add_lookup_table(&ts409_leds_gpio_table); 312 platform_device_register(&ts409_leds); 313 314 /* register tsx09 specific power-off method */ 315 pm_power_off = qnap_tsx09_power_off; 316 } 317 318 MACHINE_START(TS409, "QNAP TS-409") 319 /* Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> */ 320 .atag_offset = 0x100, 321 .nr_irqs = ORION5X_NR_IRQS, 322 .init_machine = qnap_ts409_init, 323 .map_io = orion5x_map_io, 324 .init_early = orion5x_init_early, 325 .init_irq = orion5x_init_irq, 326 .init_time = orion5x_timer_init, 327 .fixup = tag_fixup_mem32, 328 .restart = orion5x_restart, 329 MACHINE_END 330
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.