147e9cffdSSylver Bruneau /* 247e9cffdSSylver Bruneau * QNAP TS-409 Board Setup 347e9cffdSSylver Bruneau * 447e9cffdSSylver Bruneau * Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> 547e9cffdSSylver Bruneau * 647e9cffdSSylver Bruneau * This program is free software; you can redistribute it and/or 747e9cffdSSylver Bruneau * modify it under the terms of the GNU General Public License 847e9cffdSSylver Bruneau * as published by the Free Software Foundation; either version 947e9cffdSSylver Bruneau * 2 of the License, or (at your option) any later version. 1047e9cffdSSylver Bruneau */ 1147e9cffdSSylver Bruneau 1247e9cffdSSylver Bruneau #include <linux/kernel.h> 1347e9cffdSSylver Bruneau #include <linux/init.h> 1447e9cffdSSylver Bruneau #include <linux/platform_device.h> 1547e9cffdSSylver Bruneau #include <linux/pci.h> 1647e9cffdSSylver Bruneau #include <linux/irq.h> 1747e9cffdSSylver Bruneau #include <linux/mtd/physmap.h> 1847e9cffdSSylver Bruneau #include <linux/mv643xx_eth.h> 1947e9cffdSSylver Bruneau #include <linux/gpio_keys.h> 2047e9cffdSSylver Bruneau #include <linux/input.h> 2147e9cffdSSylver Bruneau #include <linux/i2c.h> 2247e9cffdSSylver Bruneau #include <linux/serial_reg.h> 2347e9cffdSSylver Bruneau #include <asm/mach-types.h> 2447e9cffdSSylver Bruneau #include <asm/gpio.h> 2547e9cffdSSylver Bruneau #include <asm/mach/arch.h> 2647e9cffdSSylver Bruneau #include <asm/mach/pci.h> 27*a09e64fbSRussell King #include <mach/orion5x.h> 2847e9cffdSSylver Bruneau #include "common.h" 2947e9cffdSSylver Bruneau #include "mpp.h" 30530c854aSSylver Bruneau #include "tsx09-common.h" 3147e9cffdSSylver Bruneau 3247e9cffdSSylver Bruneau /***************************************************************************** 3347e9cffdSSylver Bruneau * QNAP TS-409 Info 3447e9cffdSSylver Bruneau ****************************************************************************/ 3547e9cffdSSylver Bruneau 3647e9cffdSSylver Bruneau /* 3747e9cffdSSylver Bruneau * QNAP TS-409 hardware : 3847e9cffdSSylver Bruneau * - Marvell 88F5281-D0 3947e9cffdSSylver Bruneau * - Marvell 88SX7042 SATA controller (PCIe) 4047e9cffdSSylver Bruneau * - Marvell 88E1118 Gigabit Ethernet PHY 4147e9cffdSSylver Bruneau * - RTC S35390A (@0x30) on I2C bus 4247e9cffdSSylver Bruneau * - 8MB NOR flash 4347e9cffdSSylver Bruneau * - 256MB of DDR-2 RAM 4447e9cffdSSylver Bruneau */ 4547e9cffdSSylver Bruneau 4647e9cffdSSylver Bruneau /* 4747e9cffdSSylver Bruneau * 8MB NOR flash Device bus boot chip select 4847e9cffdSSylver Bruneau */ 4947e9cffdSSylver Bruneau 5047e9cffdSSylver Bruneau #define QNAP_TS409_NOR_BOOT_BASE 0xff800000 5147e9cffdSSylver Bruneau #define QNAP_TS409_NOR_BOOT_SIZE SZ_8M 5247e9cffdSSylver Bruneau 5347e9cffdSSylver Bruneau /**************************************************************************** 5447e9cffdSSylver Bruneau * 8MiB NOR flash. The struct mtd_partition is not in the same order as the 5547e9cffdSSylver Bruneau * partitions on the device because we want to keep compatability with 5647e9cffdSSylver Bruneau * existing QNAP firmware. 5747e9cffdSSylver Bruneau * 5847e9cffdSSylver Bruneau * Layout as used by QNAP: 5947e9cffdSSylver Bruneau * [2] 0x00000000-0x00200000 : "Kernel" 6047e9cffdSSylver Bruneau * [3] 0x00200000-0x00600000 : "RootFS1" 6147e9cffdSSylver Bruneau * [4] 0x00600000-0x00700000 : "RootFS2" 6247e9cffdSSylver Bruneau * [6] 0x00700000-0x00760000 : "NAS Config" (read-only) 6347e9cffdSSylver Bruneau * [5] 0x00760000-0x00780000 : "U-Boot Config" 6447e9cffdSSylver Bruneau * [1] 0x00780000-0x00800000 : "U-Boot" (read-only) 6547e9cffdSSylver Bruneau ***************************************************************************/ 6647e9cffdSSylver Bruneau static struct mtd_partition qnap_ts409_partitions[] = { 6747e9cffdSSylver Bruneau { 6847e9cffdSSylver Bruneau .name = "U-Boot", 6947e9cffdSSylver Bruneau .size = 0x00080000, 7047e9cffdSSylver Bruneau .offset = 0x00780000, 7147e9cffdSSylver Bruneau .mask_flags = MTD_WRITEABLE, 7247e9cffdSSylver Bruneau }, { 7347e9cffdSSylver Bruneau .name = "Kernel", 7447e9cffdSSylver Bruneau .size = 0x00200000, 7547e9cffdSSylver Bruneau .offset = 0, 7647e9cffdSSylver Bruneau }, { 7747e9cffdSSylver Bruneau .name = "RootFS1", 7847e9cffdSSylver Bruneau .size = 0x00400000, 7947e9cffdSSylver Bruneau .offset = 0x00200000, 8047e9cffdSSylver Bruneau }, { 8147e9cffdSSylver Bruneau .name = "RootFS2", 8247e9cffdSSylver Bruneau .size = 0x00100000, 8347e9cffdSSylver Bruneau .offset = 0x00600000, 8447e9cffdSSylver Bruneau }, { 8547e9cffdSSylver Bruneau .name = "U-Boot Config", 8647e9cffdSSylver Bruneau .size = 0x00020000, 8747e9cffdSSylver Bruneau .offset = 0x00760000, 8847e9cffdSSylver Bruneau }, { 8947e9cffdSSylver Bruneau .name = "NAS Config", 9047e9cffdSSylver Bruneau .size = 0x00060000, 9147e9cffdSSylver Bruneau .offset = 0x00700000, 9247e9cffdSSylver Bruneau .mask_flags = MTD_WRITEABLE, 9347e9cffdSSylver Bruneau }, 9447e9cffdSSylver Bruneau }; 9547e9cffdSSylver Bruneau 9647e9cffdSSylver Bruneau static struct physmap_flash_data qnap_ts409_nor_flash_data = { 9747e9cffdSSylver Bruneau .width = 1, 9847e9cffdSSylver Bruneau .parts = qnap_ts409_partitions, 9947e9cffdSSylver Bruneau .nr_parts = ARRAY_SIZE(qnap_ts409_partitions) 10047e9cffdSSylver Bruneau }; 10147e9cffdSSylver Bruneau 10247e9cffdSSylver Bruneau static struct resource qnap_ts409_nor_flash_resource = { 10347e9cffdSSylver Bruneau .flags = IORESOURCE_MEM, 10447e9cffdSSylver Bruneau .start = QNAP_TS409_NOR_BOOT_BASE, 10547e9cffdSSylver Bruneau .end = QNAP_TS409_NOR_BOOT_BASE + QNAP_TS409_NOR_BOOT_SIZE - 1, 10647e9cffdSSylver Bruneau }; 10747e9cffdSSylver Bruneau 10847e9cffdSSylver Bruneau static struct platform_device qnap_ts409_nor_flash = { 10947e9cffdSSylver Bruneau .name = "physmap-flash", 11047e9cffdSSylver Bruneau .id = 0, 11147e9cffdSSylver Bruneau .dev = { .platform_data = &qnap_ts409_nor_flash_data, }, 11247e9cffdSSylver Bruneau .num_resources = 1, 11347e9cffdSSylver Bruneau .resource = &qnap_ts409_nor_flash_resource, 11447e9cffdSSylver Bruneau }; 11547e9cffdSSylver Bruneau 11647e9cffdSSylver Bruneau /***************************************************************************** 11747e9cffdSSylver Bruneau * PCI 11847e9cffdSSylver Bruneau ****************************************************************************/ 11947e9cffdSSylver Bruneau 12047e9cffdSSylver Bruneau static int __init qnap_ts409_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) 12147e9cffdSSylver Bruneau { 12247e9cffdSSylver Bruneau int irq; 12347e9cffdSSylver Bruneau 12447e9cffdSSylver Bruneau /* 12547e9cffdSSylver Bruneau * Check for devices with hard-wired IRQs. 12647e9cffdSSylver Bruneau */ 12747e9cffdSSylver Bruneau irq = orion5x_pci_map_irq(dev, slot, pin); 12847e9cffdSSylver Bruneau if (irq != -1) 12947e9cffdSSylver Bruneau return irq; 13047e9cffdSSylver Bruneau 13147e9cffdSSylver Bruneau /* 13247e9cffdSSylver Bruneau * PCI isn't used on the TS-409 13347e9cffdSSylver Bruneau */ 13447e9cffdSSylver Bruneau return -1; 13547e9cffdSSylver Bruneau } 13647e9cffdSSylver Bruneau 13747e9cffdSSylver Bruneau static struct hw_pci qnap_ts409_pci __initdata = { 13847e9cffdSSylver Bruneau .nr_controllers = 2, 13947e9cffdSSylver Bruneau .swizzle = pci_std_swizzle, 14047e9cffdSSylver Bruneau .setup = orion5x_pci_sys_setup, 14147e9cffdSSylver Bruneau .scan = orion5x_pci_sys_scan_bus, 14247e9cffdSSylver Bruneau .map_irq = qnap_ts409_pci_map_irq, 14347e9cffdSSylver Bruneau }; 14447e9cffdSSylver Bruneau 14547e9cffdSSylver Bruneau static int __init qnap_ts409_pci_init(void) 14647e9cffdSSylver Bruneau { 14747e9cffdSSylver Bruneau if (machine_is_ts409()) 14847e9cffdSSylver Bruneau pci_common_init(&qnap_ts409_pci); 14947e9cffdSSylver Bruneau 15047e9cffdSSylver Bruneau return 0; 15147e9cffdSSylver Bruneau } 15247e9cffdSSylver Bruneau 15347e9cffdSSylver Bruneau subsys_initcall(qnap_ts409_pci_init); 15447e9cffdSSylver Bruneau 15547e9cffdSSylver Bruneau /***************************************************************************** 15647e9cffdSSylver Bruneau * RTC S35390A on I2C bus 15747e9cffdSSylver Bruneau ****************************************************************************/ 15847e9cffdSSylver Bruneau 15947e9cffdSSylver Bruneau #define TS409_RTC_GPIO 10 16047e9cffdSSylver Bruneau 16147e9cffdSSylver Bruneau static struct i2c_board_info __initdata qnap_ts409_i2c_rtc = { 16247e9cffdSSylver Bruneau I2C_BOARD_INFO("s35390a", 0x30), 16347e9cffdSSylver Bruneau }; 16447e9cffdSSylver Bruneau 16547e9cffdSSylver Bruneau /**************************************************************************** 16647e9cffdSSylver Bruneau * GPIO Attached Keys 16747e9cffdSSylver Bruneau * Power button is attached to the PIC microcontroller 16847e9cffdSSylver Bruneau ****************************************************************************/ 16947e9cffdSSylver Bruneau 17047e9cffdSSylver Bruneau #define QNAP_TS409_GPIO_KEY_MEDIA 15 17147e9cffdSSylver Bruneau 17247e9cffdSSylver Bruneau static struct gpio_keys_button qnap_ts409_buttons[] = { 17347e9cffdSSylver Bruneau { 17447e9cffdSSylver Bruneau .code = KEY_RESTART, 17547e9cffdSSylver Bruneau .gpio = QNAP_TS409_GPIO_KEY_MEDIA, 17647e9cffdSSylver Bruneau .desc = "USB Copy Button", 17747e9cffdSSylver Bruneau .active_low = 1, 17847e9cffdSSylver Bruneau }, 17947e9cffdSSylver Bruneau }; 18047e9cffdSSylver Bruneau 18147e9cffdSSylver Bruneau static struct gpio_keys_platform_data qnap_ts409_button_data = { 18247e9cffdSSylver Bruneau .buttons = qnap_ts409_buttons, 18347e9cffdSSylver Bruneau .nbuttons = ARRAY_SIZE(qnap_ts409_buttons), 18447e9cffdSSylver Bruneau }; 18547e9cffdSSylver Bruneau 18647e9cffdSSylver Bruneau static struct platform_device qnap_ts409_button_device = { 18747e9cffdSSylver Bruneau .name = "gpio-keys", 18847e9cffdSSylver Bruneau .id = -1, 18947e9cffdSSylver Bruneau .num_resources = 0, 19047e9cffdSSylver Bruneau .dev = { 19147e9cffdSSylver Bruneau .platform_data = &qnap_ts409_button_data, 19247e9cffdSSylver Bruneau }, 19347e9cffdSSylver Bruneau }; 19447e9cffdSSylver Bruneau 19547e9cffdSSylver Bruneau /***************************************************************************** 19647e9cffdSSylver Bruneau * General Setup 19747e9cffdSSylver Bruneau ****************************************************************************/ 19847e9cffdSSylver Bruneau static struct orion5x_mpp_mode ts409_mpp_modes[] __initdata = { 19947e9cffdSSylver Bruneau { 0, MPP_UNUSED }, 20047e9cffdSSylver Bruneau { 1, MPP_UNUSED }, 20147e9cffdSSylver Bruneau { 2, MPP_UNUSED }, 20247e9cffdSSylver Bruneau { 3, MPP_UNUSED }, 20347e9cffdSSylver Bruneau { 4, MPP_GPIO }, /* HDD 1 status */ 20447e9cffdSSylver Bruneau { 5, MPP_GPIO }, /* HDD 2 status */ 20547e9cffdSSylver Bruneau { 6, MPP_GPIO }, /* HDD 3 status */ 20647e9cffdSSylver Bruneau { 7, MPP_GPIO }, /* HDD 4 status */ 20747e9cffdSSylver Bruneau { 8, MPP_UNUSED }, 20847e9cffdSSylver Bruneau { 9, MPP_UNUSED }, 20947e9cffdSSylver Bruneau { 10, MPP_GPIO }, /* RTC int */ 21047e9cffdSSylver Bruneau { 11, MPP_UNUSED }, 21147e9cffdSSylver Bruneau { 12, MPP_UNUSED }, 21247e9cffdSSylver Bruneau { 13, MPP_UNUSED }, 21347e9cffdSSylver Bruneau { 14, MPP_GPIO }, /* SW_RST */ 21447e9cffdSSylver Bruneau { 15, MPP_GPIO }, /* USB copy button */ 21547e9cffdSSylver Bruneau { 16, MPP_UART }, /* UART1 RXD */ 21647e9cffdSSylver Bruneau { 17, MPP_UART }, /* UART1 TXD */ 21747e9cffdSSylver Bruneau { 18, MPP_UNUSED }, 21847e9cffdSSylver Bruneau { 19, MPP_UNUSED }, 21947e9cffdSSylver Bruneau { -1 }, 22047e9cffdSSylver Bruneau }; 22147e9cffdSSylver Bruneau 22247e9cffdSSylver Bruneau static void __init qnap_ts409_init(void) 22347e9cffdSSylver Bruneau { 22447e9cffdSSylver Bruneau /* 22547e9cffdSSylver Bruneau * Setup basic Orion functions. Need to be called early. 22647e9cffdSSylver Bruneau */ 22747e9cffdSSylver Bruneau orion5x_init(); 22847e9cffdSSylver Bruneau 22947e9cffdSSylver Bruneau orion5x_mpp_conf(ts409_mpp_modes); 23047e9cffdSSylver Bruneau 23147e9cffdSSylver Bruneau /* 23247e9cffdSSylver Bruneau * Configure peripherals. 23347e9cffdSSylver Bruneau */ 23447e9cffdSSylver Bruneau orion5x_ehci0_init(); 235530c854aSSylver Bruneau qnap_tsx09_find_mac_addr(QNAP_TS409_NOR_BOOT_BASE + 236530c854aSSylver Bruneau qnap_ts409_partitions[5].offset, 237530c854aSSylver Bruneau qnap_ts409_partitions[5].size); 238530c854aSSylver Bruneau orion5x_eth_init(&qnap_tsx09_eth_data); 23947e9cffdSSylver Bruneau orion5x_i2c_init(); 24047e9cffdSSylver Bruneau orion5x_uart0_init(); 24147e9cffdSSylver Bruneau 24247e9cffdSSylver Bruneau orion5x_setup_dev_boot_win(QNAP_TS409_NOR_BOOT_BASE, 24347e9cffdSSylver Bruneau QNAP_TS409_NOR_BOOT_SIZE); 24447e9cffdSSylver Bruneau platform_device_register(&qnap_ts409_nor_flash); 24547e9cffdSSylver Bruneau 24647e9cffdSSylver Bruneau platform_device_register(&qnap_ts409_button_device); 24747e9cffdSSylver Bruneau 24847e9cffdSSylver Bruneau /* Get RTC IRQ and register the chip */ 24947e9cffdSSylver Bruneau if (gpio_request(TS409_RTC_GPIO, "rtc") == 0) { 25047e9cffdSSylver Bruneau if (gpio_direction_input(TS409_RTC_GPIO) == 0) 25147e9cffdSSylver Bruneau qnap_ts409_i2c_rtc.irq = gpio_to_irq(TS409_RTC_GPIO); 25247e9cffdSSylver Bruneau else 25347e9cffdSSylver Bruneau gpio_free(TS409_RTC_GPIO); 25447e9cffdSSylver Bruneau } 25547e9cffdSSylver Bruneau if (qnap_ts409_i2c_rtc.irq == 0) 25647e9cffdSSylver Bruneau pr_warning("qnap_ts409_init: failed to get RTC IRQ\n"); 25747e9cffdSSylver Bruneau i2c_register_board_info(0, &qnap_ts409_i2c_rtc, 1); 25847e9cffdSSylver Bruneau 259530c854aSSylver Bruneau /* register tsx09 specific power-off method */ 260530c854aSSylver Bruneau pm_power_off = qnap_tsx09_power_off; 26147e9cffdSSylver Bruneau } 26247e9cffdSSylver Bruneau 26347e9cffdSSylver Bruneau MACHINE_START(TS409, "QNAP TS-409") 26447e9cffdSSylver Bruneau /* Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> */ 26547e9cffdSSylver Bruneau .phys_io = ORION5X_REGS_PHYS_BASE, 26647e9cffdSSylver Bruneau .io_pg_offst = ((ORION5X_REGS_VIRT_BASE) >> 18) & 0xFFFC, 26747e9cffdSSylver Bruneau .boot_params = 0x00000100, 26847e9cffdSSylver Bruneau .init_machine = qnap_ts409_init, 26947e9cffdSSylver Bruneau .map_io = orion5x_map_io, 27047e9cffdSSylver Bruneau .init_irq = orion5x_init_irq, 27147e9cffdSSylver Bruneau .timer = &orion5x_timer, 27247e9cffdSSylver Bruneau .fixup = tag_fixup_mem32, 27347e9cffdSSylver Bruneau MACHINE_END 274