147e9cffdSSylver Bruneau /* 247e9cffdSSylver Bruneau * QNAP TS-409 Board Setup 347e9cffdSSylver Bruneau * 447e9cffdSSylver Bruneau * Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> 547e9cffdSSylver Bruneau * 64a4e30afSMartin Michlmayr * Copyright (C) 2008 Sylver Bruneau <sylver.bruneau@gmail.com> 74a4e30afSMartin Michlmayr * Copyright (C) 2008 Martin Michlmayr <tbm@cyrius.com> 84a4e30afSMartin Michlmayr * 947e9cffdSSylver Bruneau * This program is free software; you can redistribute it and/or 1047e9cffdSSylver Bruneau * modify it under the terms of the GNU General Public License 1147e9cffdSSylver Bruneau * as published by the Free Software Foundation; either version 1247e9cffdSSylver Bruneau * 2 of the License, or (at your option) any later version. 1347e9cffdSSylver Bruneau */ 1447e9cffdSSylver Bruneau 1547e9cffdSSylver Bruneau #include <linux/kernel.h> 1647e9cffdSSylver Bruneau #include <linux/init.h> 1747e9cffdSSylver Bruneau #include <linux/platform_device.h> 1847e9cffdSSylver Bruneau #include <linux/pci.h> 1947e9cffdSSylver Bruneau #include <linux/irq.h> 2047e9cffdSSylver Bruneau #include <linux/mtd/physmap.h> 2147e9cffdSSylver Bruneau #include <linux/mv643xx_eth.h> 224a4e30afSMartin Michlmayr #include <linux/leds.h> 2347e9cffdSSylver Bruneau #include <linux/gpio_keys.h> 2447e9cffdSSylver Bruneau #include <linux/input.h> 2547e9cffdSSylver Bruneau #include <linux/i2c.h> 2647e9cffdSSylver Bruneau #include <linux/serial_reg.h> 2747e9cffdSSylver Bruneau #include <asm/mach-types.h> 2847e9cffdSSylver Bruneau #include <asm/gpio.h> 2947e9cffdSSylver Bruneau #include <asm/mach/arch.h> 3047e9cffdSSylver Bruneau #include <asm/mach/pci.h> 31a09e64fbSRussell King #include <mach/orion5x.h> 3247e9cffdSSylver Bruneau #include "common.h" 3347e9cffdSSylver Bruneau #include "mpp.h" 34530c854aSSylver Bruneau #include "tsx09-common.h" 3547e9cffdSSylver Bruneau 3647e9cffdSSylver Bruneau /***************************************************************************** 3747e9cffdSSylver Bruneau * QNAP TS-409 Info 3847e9cffdSSylver Bruneau ****************************************************************************/ 3947e9cffdSSylver Bruneau 4047e9cffdSSylver Bruneau /* 4147e9cffdSSylver Bruneau * QNAP TS-409 hardware : 4247e9cffdSSylver Bruneau * - Marvell 88F5281-D0 4347e9cffdSSylver Bruneau * - Marvell 88SX7042 SATA controller (PCIe) 4447e9cffdSSylver Bruneau * - Marvell 88E1118 Gigabit Ethernet PHY 4547e9cffdSSylver Bruneau * - RTC S35390A (@0x30) on I2C bus 4647e9cffdSSylver Bruneau * - 8MB NOR flash 4747e9cffdSSylver Bruneau * - 256MB of DDR-2 RAM 4847e9cffdSSylver Bruneau */ 4947e9cffdSSylver Bruneau 5047e9cffdSSylver Bruneau /* 5147e9cffdSSylver Bruneau * 8MB NOR flash Device bus boot chip select 5247e9cffdSSylver Bruneau */ 5347e9cffdSSylver Bruneau 5447e9cffdSSylver Bruneau #define QNAP_TS409_NOR_BOOT_BASE 0xff800000 5547e9cffdSSylver Bruneau #define QNAP_TS409_NOR_BOOT_SIZE SZ_8M 5647e9cffdSSylver Bruneau 5747e9cffdSSylver Bruneau /**************************************************************************** 5847e9cffdSSylver Bruneau * 8MiB NOR flash. The struct mtd_partition is not in the same order as the 5947e9cffdSSylver Bruneau * partitions on the device because we want to keep compatability with 6047e9cffdSSylver Bruneau * existing QNAP firmware. 6147e9cffdSSylver Bruneau * 6247e9cffdSSylver Bruneau * Layout as used by QNAP: 6347e9cffdSSylver Bruneau * [2] 0x00000000-0x00200000 : "Kernel" 6447e9cffdSSylver Bruneau * [3] 0x00200000-0x00600000 : "RootFS1" 6547e9cffdSSylver Bruneau * [4] 0x00600000-0x00700000 : "RootFS2" 6647e9cffdSSylver Bruneau * [6] 0x00700000-0x00760000 : "NAS Config" (read-only) 6747e9cffdSSylver Bruneau * [5] 0x00760000-0x00780000 : "U-Boot Config" 6847e9cffdSSylver Bruneau * [1] 0x00780000-0x00800000 : "U-Boot" (read-only) 6947e9cffdSSylver Bruneau ***************************************************************************/ 7047e9cffdSSylver Bruneau static struct mtd_partition qnap_ts409_partitions[] = { 7147e9cffdSSylver Bruneau { 7247e9cffdSSylver Bruneau .name = "U-Boot", 7347e9cffdSSylver Bruneau .size = 0x00080000, 7447e9cffdSSylver Bruneau .offset = 0x00780000, 7547e9cffdSSylver Bruneau .mask_flags = MTD_WRITEABLE, 7647e9cffdSSylver Bruneau }, { 7747e9cffdSSylver Bruneau .name = "Kernel", 7847e9cffdSSylver Bruneau .size = 0x00200000, 7947e9cffdSSylver Bruneau .offset = 0, 8047e9cffdSSylver Bruneau }, { 8147e9cffdSSylver Bruneau .name = "RootFS1", 8247e9cffdSSylver Bruneau .size = 0x00400000, 8347e9cffdSSylver Bruneau .offset = 0x00200000, 8447e9cffdSSylver Bruneau }, { 8547e9cffdSSylver Bruneau .name = "RootFS2", 8647e9cffdSSylver Bruneau .size = 0x00100000, 8747e9cffdSSylver Bruneau .offset = 0x00600000, 8847e9cffdSSylver Bruneau }, { 8947e9cffdSSylver Bruneau .name = "U-Boot Config", 9047e9cffdSSylver Bruneau .size = 0x00020000, 9147e9cffdSSylver Bruneau .offset = 0x00760000, 9247e9cffdSSylver Bruneau }, { 9347e9cffdSSylver Bruneau .name = "NAS Config", 9447e9cffdSSylver Bruneau .size = 0x00060000, 9547e9cffdSSylver Bruneau .offset = 0x00700000, 9647e9cffdSSylver Bruneau .mask_flags = MTD_WRITEABLE, 9747e9cffdSSylver Bruneau }, 9847e9cffdSSylver Bruneau }; 9947e9cffdSSylver Bruneau 10047e9cffdSSylver Bruneau static struct physmap_flash_data qnap_ts409_nor_flash_data = { 10147e9cffdSSylver Bruneau .width = 1, 10247e9cffdSSylver Bruneau .parts = qnap_ts409_partitions, 10347e9cffdSSylver Bruneau .nr_parts = ARRAY_SIZE(qnap_ts409_partitions) 10447e9cffdSSylver Bruneau }; 10547e9cffdSSylver Bruneau 10647e9cffdSSylver Bruneau static struct resource qnap_ts409_nor_flash_resource = { 10747e9cffdSSylver Bruneau .flags = IORESOURCE_MEM, 10847e9cffdSSylver Bruneau .start = QNAP_TS409_NOR_BOOT_BASE, 10947e9cffdSSylver Bruneau .end = QNAP_TS409_NOR_BOOT_BASE + QNAP_TS409_NOR_BOOT_SIZE - 1, 11047e9cffdSSylver Bruneau }; 11147e9cffdSSylver Bruneau 11247e9cffdSSylver Bruneau static struct platform_device qnap_ts409_nor_flash = { 11347e9cffdSSylver Bruneau .name = "physmap-flash", 11447e9cffdSSylver Bruneau .id = 0, 11547e9cffdSSylver Bruneau .dev = { .platform_data = &qnap_ts409_nor_flash_data, }, 11647e9cffdSSylver Bruneau .num_resources = 1, 11747e9cffdSSylver Bruneau .resource = &qnap_ts409_nor_flash_resource, 11847e9cffdSSylver Bruneau }; 11947e9cffdSSylver Bruneau 12047e9cffdSSylver Bruneau /***************************************************************************** 12147e9cffdSSylver Bruneau * PCI 12247e9cffdSSylver Bruneau ****************************************************************************/ 12347e9cffdSSylver Bruneau 12447e9cffdSSylver Bruneau static int __init qnap_ts409_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) 12547e9cffdSSylver Bruneau { 12647e9cffdSSylver Bruneau int irq; 12747e9cffdSSylver Bruneau 12847e9cffdSSylver Bruneau /* 12947e9cffdSSylver Bruneau * Check for devices with hard-wired IRQs. 13047e9cffdSSylver Bruneau */ 13147e9cffdSSylver Bruneau irq = orion5x_pci_map_irq(dev, slot, pin); 13247e9cffdSSylver Bruneau if (irq != -1) 13347e9cffdSSylver Bruneau return irq; 13447e9cffdSSylver Bruneau 13547e9cffdSSylver Bruneau /* 13647e9cffdSSylver Bruneau * PCI isn't used on the TS-409 13747e9cffdSSylver Bruneau */ 13847e9cffdSSylver Bruneau return -1; 13947e9cffdSSylver Bruneau } 14047e9cffdSSylver Bruneau 14147e9cffdSSylver Bruneau static struct hw_pci qnap_ts409_pci __initdata = { 14247e9cffdSSylver Bruneau .nr_controllers = 2, 14347e9cffdSSylver Bruneau .swizzle = pci_std_swizzle, 14447e9cffdSSylver Bruneau .setup = orion5x_pci_sys_setup, 14547e9cffdSSylver Bruneau .scan = orion5x_pci_sys_scan_bus, 14647e9cffdSSylver Bruneau .map_irq = qnap_ts409_pci_map_irq, 14747e9cffdSSylver Bruneau }; 14847e9cffdSSylver Bruneau 14947e9cffdSSylver Bruneau static int __init qnap_ts409_pci_init(void) 15047e9cffdSSylver Bruneau { 15147e9cffdSSylver Bruneau if (machine_is_ts409()) 15247e9cffdSSylver Bruneau pci_common_init(&qnap_ts409_pci); 15347e9cffdSSylver Bruneau 15447e9cffdSSylver Bruneau return 0; 15547e9cffdSSylver Bruneau } 15647e9cffdSSylver Bruneau 15747e9cffdSSylver Bruneau subsys_initcall(qnap_ts409_pci_init); 15847e9cffdSSylver Bruneau 15947e9cffdSSylver Bruneau /***************************************************************************** 16047e9cffdSSylver Bruneau * RTC S35390A on I2C bus 16147e9cffdSSylver Bruneau ****************************************************************************/ 16247e9cffdSSylver Bruneau 16347e9cffdSSylver Bruneau #define TS409_RTC_GPIO 10 16447e9cffdSSylver Bruneau 16547e9cffdSSylver Bruneau static struct i2c_board_info __initdata qnap_ts409_i2c_rtc = { 16647e9cffdSSylver Bruneau I2C_BOARD_INFO("s35390a", 0x30), 16747e9cffdSSylver Bruneau }; 16847e9cffdSSylver Bruneau 1694a4e30afSMartin Michlmayr /***************************************************************************** 1704a4e30afSMartin Michlmayr * LEDs attached to GPIO 1714a4e30afSMartin Michlmayr ****************************************************************************/ 1724a4e30afSMartin Michlmayr 1734a4e30afSMartin Michlmayr static struct gpio_led ts409_led_pins[] = { 1744a4e30afSMartin Michlmayr { 1754a4e30afSMartin Michlmayr .name = "ts409:red:sata1", 1764a4e30afSMartin Michlmayr .gpio = 4, 1774a4e30afSMartin Michlmayr .active_low = 1, 1784a4e30afSMartin Michlmayr }, { 1794a4e30afSMartin Michlmayr .name = "ts409:red:sata2", 1804a4e30afSMartin Michlmayr .gpio = 5, 1814a4e30afSMartin Michlmayr .active_low = 1, 1824a4e30afSMartin Michlmayr }, { 1834a4e30afSMartin Michlmayr .name = "ts409:red:sata3", 1844a4e30afSMartin Michlmayr .gpio = 6, 1854a4e30afSMartin Michlmayr .active_low = 1, 1864a4e30afSMartin Michlmayr }, { 1874a4e30afSMartin Michlmayr .name = "ts409:red:sata4", 1884a4e30afSMartin Michlmayr .gpio = 7, 1894a4e30afSMartin Michlmayr .active_low = 1, 1904a4e30afSMartin Michlmayr }, 1914a4e30afSMartin Michlmayr }; 1924a4e30afSMartin Michlmayr 1934a4e30afSMartin Michlmayr static struct gpio_led_platform_data ts409_led_data = { 1944a4e30afSMartin Michlmayr .leds = ts409_led_pins, 1954a4e30afSMartin Michlmayr .num_leds = ARRAY_SIZE(ts409_led_pins), 1964a4e30afSMartin Michlmayr }; 1974a4e30afSMartin Michlmayr 1984a4e30afSMartin Michlmayr static struct platform_device ts409_leds = { 1994a4e30afSMartin Michlmayr .name = "leds-gpio", 2004a4e30afSMartin Michlmayr .id = -1, 2014a4e30afSMartin Michlmayr .dev = { 2024a4e30afSMartin Michlmayr .platform_data = &ts409_led_data, 2034a4e30afSMartin Michlmayr }, 2044a4e30afSMartin Michlmayr }; 2054a4e30afSMartin Michlmayr 20647e9cffdSSylver Bruneau /**************************************************************************** 20747e9cffdSSylver Bruneau * GPIO Attached Keys 20847e9cffdSSylver Bruneau * Power button is attached to the PIC microcontroller 20947e9cffdSSylver Bruneau ****************************************************************************/ 21047e9cffdSSylver Bruneau 211*5cebbd09SMartin Michlmayr #define QNAP_TS409_GPIO_KEY_RESET 14 21247e9cffdSSylver Bruneau #define QNAP_TS409_GPIO_KEY_MEDIA 15 21347e9cffdSSylver Bruneau 21447e9cffdSSylver Bruneau static struct gpio_keys_button qnap_ts409_buttons[] = { 21547e9cffdSSylver Bruneau { 216*5cebbd09SMartin Michlmayr .code = KEY_RESTART, 217*5cebbd09SMartin Michlmayr .gpio = QNAP_TS409_GPIO_KEY_RESET, 218*5cebbd09SMartin Michlmayr .desc = "Reset Button", 219*5cebbd09SMartin Michlmayr .active_low = 1, 220*5cebbd09SMartin Michlmayr }, { 22128ca8c80SMartin Michlmayr .code = KEY_COPY, 22247e9cffdSSylver Bruneau .gpio = QNAP_TS409_GPIO_KEY_MEDIA, 22347e9cffdSSylver Bruneau .desc = "USB Copy Button", 22447e9cffdSSylver Bruneau .active_low = 1, 22547e9cffdSSylver Bruneau }, 22647e9cffdSSylver Bruneau }; 22747e9cffdSSylver Bruneau 22847e9cffdSSylver Bruneau static struct gpio_keys_platform_data qnap_ts409_button_data = { 22947e9cffdSSylver Bruneau .buttons = qnap_ts409_buttons, 23047e9cffdSSylver Bruneau .nbuttons = ARRAY_SIZE(qnap_ts409_buttons), 23147e9cffdSSylver Bruneau }; 23247e9cffdSSylver Bruneau 23347e9cffdSSylver Bruneau static struct platform_device qnap_ts409_button_device = { 23447e9cffdSSylver Bruneau .name = "gpio-keys", 23547e9cffdSSylver Bruneau .id = -1, 23647e9cffdSSylver Bruneau .num_resources = 0, 23747e9cffdSSylver Bruneau .dev = { 23847e9cffdSSylver Bruneau .platform_data = &qnap_ts409_button_data, 23947e9cffdSSylver Bruneau }, 24047e9cffdSSylver Bruneau }; 24147e9cffdSSylver Bruneau 24247e9cffdSSylver Bruneau /***************************************************************************** 24347e9cffdSSylver Bruneau * General Setup 24447e9cffdSSylver Bruneau ****************************************************************************/ 24547e9cffdSSylver Bruneau static struct orion5x_mpp_mode ts409_mpp_modes[] __initdata = { 24647e9cffdSSylver Bruneau { 0, MPP_UNUSED }, 24747e9cffdSSylver Bruneau { 1, MPP_UNUSED }, 24847e9cffdSSylver Bruneau { 2, MPP_UNUSED }, 24947e9cffdSSylver Bruneau { 3, MPP_UNUSED }, 25047e9cffdSSylver Bruneau { 4, MPP_GPIO }, /* HDD 1 status */ 25147e9cffdSSylver Bruneau { 5, MPP_GPIO }, /* HDD 2 status */ 25247e9cffdSSylver Bruneau { 6, MPP_GPIO }, /* HDD 3 status */ 25347e9cffdSSylver Bruneau { 7, MPP_GPIO }, /* HDD 4 status */ 25447e9cffdSSylver Bruneau { 8, MPP_UNUSED }, 25547e9cffdSSylver Bruneau { 9, MPP_UNUSED }, 25647e9cffdSSylver Bruneau { 10, MPP_GPIO }, /* RTC int */ 25747e9cffdSSylver Bruneau { 11, MPP_UNUSED }, 25847e9cffdSSylver Bruneau { 12, MPP_UNUSED }, 25947e9cffdSSylver Bruneau { 13, MPP_UNUSED }, 26047e9cffdSSylver Bruneau { 14, MPP_GPIO }, /* SW_RST */ 26147e9cffdSSylver Bruneau { 15, MPP_GPIO }, /* USB copy button */ 26247e9cffdSSylver Bruneau { 16, MPP_UART }, /* UART1 RXD */ 26347e9cffdSSylver Bruneau { 17, MPP_UART }, /* UART1 TXD */ 26447e9cffdSSylver Bruneau { 18, MPP_UNUSED }, 26547e9cffdSSylver Bruneau { 19, MPP_UNUSED }, 26647e9cffdSSylver Bruneau { -1 }, 26747e9cffdSSylver Bruneau }; 26847e9cffdSSylver Bruneau 26947e9cffdSSylver Bruneau static void __init qnap_ts409_init(void) 27047e9cffdSSylver Bruneau { 27147e9cffdSSylver Bruneau /* 27247e9cffdSSylver Bruneau * Setup basic Orion functions. Need to be called early. 27347e9cffdSSylver Bruneau */ 27447e9cffdSSylver Bruneau orion5x_init(); 27547e9cffdSSylver Bruneau 27647e9cffdSSylver Bruneau orion5x_mpp_conf(ts409_mpp_modes); 27747e9cffdSSylver Bruneau 27847e9cffdSSylver Bruneau /* 27947e9cffdSSylver Bruneau * Configure peripherals. 28047e9cffdSSylver Bruneau */ 28147e9cffdSSylver Bruneau orion5x_ehci0_init(); 282530c854aSSylver Bruneau qnap_tsx09_find_mac_addr(QNAP_TS409_NOR_BOOT_BASE + 283530c854aSSylver Bruneau qnap_ts409_partitions[5].offset, 284530c854aSSylver Bruneau qnap_ts409_partitions[5].size); 285530c854aSSylver Bruneau orion5x_eth_init(&qnap_tsx09_eth_data); 28647e9cffdSSylver Bruneau orion5x_i2c_init(); 28747e9cffdSSylver Bruneau orion5x_uart0_init(); 28847e9cffdSSylver Bruneau 28947e9cffdSSylver Bruneau orion5x_setup_dev_boot_win(QNAP_TS409_NOR_BOOT_BASE, 29047e9cffdSSylver Bruneau QNAP_TS409_NOR_BOOT_SIZE); 29147e9cffdSSylver Bruneau platform_device_register(&qnap_ts409_nor_flash); 29247e9cffdSSylver Bruneau 29347e9cffdSSylver Bruneau platform_device_register(&qnap_ts409_button_device); 29447e9cffdSSylver Bruneau 29547e9cffdSSylver Bruneau /* Get RTC IRQ and register the chip */ 29647e9cffdSSylver Bruneau if (gpio_request(TS409_RTC_GPIO, "rtc") == 0) { 29747e9cffdSSylver Bruneau if (gpio_direction_input(TS409_RTC_GPIO) == 0) 29847e9cffdSSylver Bruneau qnap_ts409_i2c_rtc.irq = gpio_to_irq(TS409_RTC_GPIO); 29947e9cffdSSylver Bruneau else 30047e9cffdSSylver Bruneau gpio_free(TS409_RTC_GPIO); 30147e9cffdSSylver Bruneau } 30247e9cffdSSylver Bruneau if (qnap_ts409_i2c_rtc.irq == 0) 30347e9cffdSSylver Bruneau pr_warning("qnap_ts409_init: failed to get RTC IRQ\n"); 30447e9cffdSSylver Bruneau i2c_register_board_info(0, &qnap_ts409_i2c_rtc, 1); 3054a4e30afSMartin Michlmayr platform_device_register(&ts409_leds); 30647e9cffdSSylver Bruneau 307530c854aSSylver Bruneau /* register tsx09 specific power-off method */ 308530c854aSSylver Bruneau pm_power_off = qnap_tsx09_power_off; 30947e9cffdSSylver Bruneau } 31047e9cffdSSylver Bruneau 31147e9cffdSSylver Bruneau MACHINE_START(TS409, "QNAP TS-409") 31247e9cffdSSylver Bruneau /* Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> */ 31347e9cffdSSylver Bruneau .phys_io = ORION5X_REGS_PHYS_BASE, 31447e9cffdSSylver Bruneau .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC, 31547e9cffdSSylver Bruneau .boot_params = 0x00000100, 31647e9cffdSSylver Bruneau .init_machine = qnap_ts409_init, 31747e9cffdSSylver Bruneau .map_io = orion5x_map_io, 31847e9cffdSSylver Bruneau .init_irq = orion5x_init_irq, 31947e9cffdSSylver Bruneau .timer = &orion5x_timer, 32047e9cffdSSylver Bruneau .fixup = tag_fixup_mem32, 32147e9cffdSSylver Bruneau MACHINE_END 322