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#include <linux/gpio.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/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/mach/arch.h> 27#include <asm/mach/pci.h> 28#include <mach/orion5x.h> 29#include "common.h" 30#include "mpp.h" 31#include "tsx09-common.h" 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 38 * partitions on the device because we want to keep compatibility with 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 ***************************************************************************/ 49static struct mtd_partition qnap_ts209_partitions[] = { 50 { 51 .name = "U-Boot", 52 .size = 0x00080000, 53 .offset = 0x00780000, 54 .mask_flags = MTD_WRITEABLE, 55 }, { 56 .name = "Kernel", 57 .size = 0x00200000, 58 .offset = 0, 59 }, { 60 .name = "RootFS1", 61 .size = 0x00400000, 62 .offset = 0x00200000, 63 }, { 64 .name = "RootFS2", 65 .size = 0x00100000, 66 .offset = 0x00600000, 67 }, { 68 .name = "U-Boot Config", 69 .size = 0x00020000, 70 .offset = 0x00760000, 71 }, { 72 .name = "NAS Config", 73 .size = 0x00060000, 74 .offset = 0x00700000, 75 .mask_flags = MTD_WRITEABLE, 76 }, 77}; 78 79static struct physmap_flash_data qnap_ts209_nor_flash_data = { 80 .width = 1, 81 .parts = qnap_ts209_partitions, 82 .nr_parts = ARRAY_SIZE(qnap_ts209_partitions) 83}; 84 85static struct resource qnap_ts209_nor_flash_resource = { 86 .flags = IORESOURCE_MEM, 87 .start = QNAP_TS209_NOR_BOOT_BASE, 88 .end = QNAP_TS209_NOR_BOOT_BASE + QNAP_TS209_NOR_BOOT_SIZE - 1, 89}; 90 91static struct platform_device qnap_ts209_nor_flash = { 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, 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 109static void __init qnap_ts209_pci_preinit(void) 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) { 119 irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW); 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) { 133 irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW); 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 145static int __init qnap_ts209_pci_map_irq(const struct pci_dev *dev, u8 slot, 146 u8 pin) 147{ 148 int irq; 149 150 /* 151 * Check for devices with hard-wired IRQs. 152 */ 153 irq = orion5x_pci_map_irq(dev, slot, pin); 154 if (irq != -1) 155 return irq; 156 157 /* 158 * PCI IRQs are connected via GPIOs. 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 170static struct hw_pci qnap_ts209_pci __initdata = { 171 .nr_controllers = 2, 172 .preinit = qnap_ts209_pci_preinit, 173 .setup = orion5x_pci_sys_setup, 174 .scan = orion5x_pci_sys_scan_bus, 175 .map_irq = qnap_ts209_pci_map_irq, 176}; 177 178static int __init qnap_ts209_pci_init(void) 179{ 180 if (machine_is_ts209()) 181 pci_common_init(&qnap_ts209_pci); 182 183 return 0; 184} 185 186subsys_initcall(qnap_ts209_pci_init); 187 188/***************************************************************************** 189 * RTC S35390A on I2C bus 190 ****************************************************************************/ 191 192#define TS209_RTC_GPIO 3 193 194static struct i2c_board_info __initdata qnap_ts209_i2c_rtc = { 195 I2C_BOARD_INFO("s35390a", 0x30), 196 .irq = 0, 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 207static struct gpio_keys_button qnap_ts209_buttons[] = { 208 { 209 .code = KEY_COPY, 210 .gpio = QNAP_TS209_GPIO_KEY_MEDIA, 211 .desc = "USB Copy Button", 212 .active_low = 1, 213 }, { 214 .code = KEY_RESTART, 215 .gpio = QNAP_TS209_GPIO_KEY_RESET, 216 .desc = "Reset Button", 217 .active_low = 1, 218 }, 219}; 220 221static struct gpio_keys_platform_data qnap_ts209_button_data = { 222 .buttons = qnap_ts209_buttons, 223 .nbuttons = ARRAY_SIZE(qnap_ts209_buttons), 224}; 225 226static struct platform_device qnap_ts209_button_device = { 227 .name = "gpio-keys", 228 .id = -1, 229 .num_resources = 0, 230 .dev = { 231 .platform_data = &qnap_ts209_button_data, 232 }, 233}; 234 235/***************************************************************************** 236 * SATA 237 ****************************************************************************/ 238static struct mv_sata_platform_data qnap_ts209_sata_data = { 239 .n_ports = 2, 240}; 241 242/***************************************************************************** 243 244 * General Setup 245 ****************************************************************************/ 246static 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, 268}; 269 270static void __init qnap_ts209_init(void) 271{ 272 /* 273 * Setup basic Orion functions. Need to be called early. 274 */ 275 orion5x_init(); 276 277 orion5x_mpp_conf(ts209_mpp_modes); 278 279 /* 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 */ 285 286 /* 287 * Configure peripherals. 288 */ 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); 293 platform_device_register(&qnap_ts209_nor_flash); 294 295 orion5x_ehci0_init(); 296 orion5x_ehci1_init(); 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); 301 orion5x_i2c_init(); 302 orion5x_sata_init(&qnap_ts209_sata_data); 303 orion5x_uart0_init(); 304 orion5x_uart1_init(); 305 orion5x_xor_init(); 306 307 platform_device_register(&qnap_ts209_button_device); 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_warn("qnap_ts209_init: failed to get RTC IRQ\n"); 318 i2c_register_board_info(0, &qnap_ts209_i2c_rtc, 1); 319 320 /* register tsx09 specific power-off method */ 321 pm_power_off = qnap_tsx09_power_off; 322} 323 324MACHINE_START(TS209, "QNAP TS-109/TS-209") 325 /* Maintainer: Byron Bradley <byron.bbradley@gmail.com> */ 326 .atag_offset = 0x100, 327 .init_machine = qnap_ts209_init, 328 .map_io = orion5x_map_io, 329 .init_early = orion5x_init_early, 330 .init_irq = orion5x_init_irq, 331 .init_time = orion5x_timer_init, 332 .fixup = tag_fixup_mem32, 333 .restart = orion5x_restart, 334MACHINE_END 335