12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 247e9cffdSSylver Bruneau /* 347e9cffdSSylver Bruneau * QNAP TS-409 Board Setup 447e9cffdSSylver Bruneau * 547e9cffdSSylver Bruneau * Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> 647e9cffdSSylver Bruneau * 74a4e30afSMartin Michlmayr * Copyright (C) 2008 Sylver Bruneau <sylver.bruneau@gmail.com> 84a4e30afSMartin Michlmayr * Copyright (C) 2008 Martin Michlmayr <tbm@cyrius.com> 947e9cffdSSylver Bruneau */ 102f8163baSRussell King #include <linux/gpio.h> 113153eb8eSLinus Walleij #include <linux/gpio/machine.h> 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> 194a4e30afSMartin Michlmayr #include <linux/leds.h> 2047e9cffdSSylver Bruneau #include <linux/gpio_keys.h> 2147e9cffdSSylver Bruneau #include <linux/input.h> 2247e9cffdSSylver Bruneau #include <linux/i2c.h> 2347e9cffdSSylver Bruneau #include <linux/serial_reg.h> 2447e9cffdSSylver Bruneau #include <asm/mach-types.h> 2547e9cffdSSylver Bruneau #include <asm/mach/arch.h> 2647e9cffdSSylver Bruneau #include <asm/mach/pci.h> 2747e9cffdSSylver Bruneau #include "common.h" 2847e9cffdSSylver Bruneau #include "mpp.h" 29c22c2c60SArnd Bergmann #include "orion5x.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 5525985edcSLucas De Marchi * partitions on the device because we want to keep compatibility 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 120d5341942SRalf Baechle static int __init qnap_ts409_pci_map_irq(const struct pci_dev *dev, u8 slot, 121d5341942SRalf Baechle u8 pin) 12247e9cffdSSylver Bruneau { 12347e9cffdSSylver Bruneau int irq; 12447e9cffdSSylver Bruneau 12547e9cffdSSylver Bruneau /* 12647e9cffdSSylver Bruneau * Check for devices with hard-wired IRQs. 12747e9cffdSSylver Bruneau */ 12847e9cffdSSylver Bruneau irq = orion5x_pci_map_irq(dev, slot, pin); 12947e9cffdSSylver Bruneau if (irq != -1) 13047e9cffdSSylver Bruneau return irq; 13147e9cffdSSylver Bruneau 13247e9cffdSSylver Bruneau /* 13347e9cffdSSylver Bruneau * PCI isn't used on the TS-409 13447e9cffdSSylver Bruneau */ 13547e9cffdSSylver Bruneau return -1; 13647e9cffdSSylver Bruneau } 13747e9cffdSSylver Bruneau 13847e9cffdSSylver Bruneau static struct hw_pci qnap_ts409_pci __initdata = { 13947e9cffdSSylver Bruneau .nr_controllers = 2, 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 1654a4e30afSMartin Michlmayr /***************************************************************************** 1664a4e30afSMartin Michlmayr * LEDs attached to GPIO 1674a4e30afSMartin Michlmayr ****************************************************************************/ 1684a4e30afSMartin Michlmayr 1694a4e30afSMartin Michlmayr static struct gpio_led ts409_led_pins[] = { 1704a4e30afSMartin Michlmayr { 1714a4e30afSMartin Michlmayr .name = "ts409:red:sata1", 1724a4e30afSMartin Michlmayr }, { 1734a4e30afSMartin Michlmayr .name = "ts409:red:sata2", 1744a4e30afSMartin Michlmayr }, { 1754a4e30afSMartin Michlmayr .name = "ts409:red:sata3", 1764a4e30afSMartin Michlmayr }, { 1774a4e30afSMartin Michlmayr .name = "ts409:red:sata4", 1783153eb8eSLinus Walleij }, 1793153eb8eSLinus Walleij }; 1803153eb8eSLinus Walleij 1813153eb8eSLinus Walleij static struct gpiod_lookup_table ts409_leds_gpio_table = { 1823153eb8eSLinus Walleij .dev_id = "leds-gpio", 1833153eb8eSLinus Walleij .table = { 1843153eb8eSLinus Walleij GPIO_LOOKUP_IDX("orion_gpio0", 4, NULL, 1853153eb8eSLinus Walleij 0, GPIO_ACTIVE_LOW), 1863153eb8eSLinus Walleij GPIO_LOOKUP_IDX("orion_gpio0", 5, NULL, 1873153eb8eSLinus Walleij 1, GPIO_ACTIVE_LOW), 1883153eb8eSLinus Walleij GPIO_LOOKUP_IDX("orion_gpio0", 6, NULL, 1893153eb8eSLinus Walleij 2, GPIO_ACTIVE_LOW), 1903153eb8eSLinus Walleij GPIO_LOOKUP_IDX("orion_gpio0", 7, NULL, 1913153eb8eSLinus Walleij 3, GPIO_ACTIVE_LOW), 1923153eb8eSLinus Walleij { }, 1934a4e30afSMartin Michlmayr }, 1944a4e30afSMartin Michlmayr }; 1954a4e30afSMartin Michlmayr 1964a4e30afSMartin Michlmayr static struct gpio_led_platform_data ts409_led_data = { 1974a4e30afSMartin Michlmayr .leds = ts409_led_pins, 1984a4e30afSMartin Michlmayr .num_leds = ARRAY_SIZE(ts409_led_pins), 1994a4e30afSMartin Michlmayr }; 2004a4e30afSMartin Michlmayr 2014a4e30afSMartin Michlmayr static struct platform_device ts409_leds = { 2024a4e30afSMartin Michlmayr .name = "leds-gpio", 2034a4e30afSMartin Michlmayr .id = -1, 2044a4e30afSMartin Michlmayr .dev = { 2054a4e30afSMartin Michlmayr .platform_data = &ts409_led_data, 2064a4e30afSMartin Michlmayr }, 2074a4e30afSMartin Michlmayr }; 2084a4e30afSMartin Michlmayr 20947e9cffdSSylver Bruneau /**************************************************************************** 21047e9cffdSSylver Bruneau * GPIO Attached Keys 21147e9cffdSSylver Bruneau * Power button is attached to the PIC microcontroller 21247e9cffdSSylver Bruneau ****************************************************************************/ 21347e9cffdSSylver Bruneau 2145cebbd09SMartin Michlmayr #define QNAP_TS409_GPIO_KEY_RESET 14 21547e9cffdSSylver Bruneau #define QNAP_TS409_GPIO_KEY_MEDIA 15 21647e9cffdSSylver Bruneau 21747e9cffdSSylver Bruneau static struct gpio_keys_button qnap_ts409_buttons[] = { 21847e9cffdSSylver Bruneau { 2195cebbd09SMartin Michlmayr .code = KEY_RESTART, 2205cebbd09SMartin Michlmayr .gpio = QNAP_TS409_GPIO_KEY_RESET, 2215cebbd09SMartin Michlmayr .desc = "Reset Button", 2225cebbd09SMartin Michlmayr .active_low = 1, 2235cebbd09SMartin Michlmayr }, { 22428ca8c80SMartin Michlmayr .code = KEY_COPY, 22547e9cffdSSylver Bruneau .gpio = QNAP_TS409_GPIO_KEY_MEDIA, 22647e9cffdSSylver Bruneau .desc = "USB Copy Button", 22747e9cffdSSylver Bruneau .active_low = 1, 22847e9cffdSSylver Bruneau }, 22947e9cffdSSylver Bruneau }; 23047e9cffdSSylver Bruneau 23147e9cffdSSylver Bruneau static struct gpio_keys_platform_data qnap_ts409_button_data = { 23247e9cffdSSylver Bruneau .buttons = qnap_ts409_buttons, 23347e9cffdSSylver Bruneau .nbuttons = ARRAY_SIZE(qnap_ts409_buttons), 23447e9cffdSSylver Bruneau }; 23547e9cffdSSylver Bruneau 23647e9cffdSSylver Bruneau static struct platform_device qnap_ts409_button_device = { 23747e9cffdSSylver Bruneau .name = "gpio-keys", 23847e9cffdSSylver Bruneau .id = -1, 23947e9cffdSSylver Bruneau .num_resources = 0, 24047e9cffdSSylver Bruneau .dev = { 24147e9cffdSSylver Bruneau .platform_data = &qnap_ts409_button_data, 24247e9cffdSSylver Bruneau }, 24347e9cffdSSylver Bruneau }; 24447e9cffdSSylver Bruneau 24547e9cffdSSylver Bruneau /***************************************************************************** 24647e9cffdSSylver Bruneau * General Setup 24747e9cffdSSylver Bruneau ****************************************************************************/ 248554cdaefSAndrew Lunn static unsigned int ts409_mpp_modes[] __initdata = { 249554cdaefSAndrew Lunn MPP0_UNUSED, 250554cdaefSAndrew Lunn MPP1_UNUSED, 251554cdaefSAndrew Lunn MPP2_UNUSED, 252554cdaefSAndrew Lunn MPP3_UNUSED, 253554cdaefSAndrew Lunn MPP4_GPIO, /* HDD 1 status */ 254554cdaefSAndrew Lunn MPP5_GPIO, /* HDD 2 status */ 255554cdaefSAndrew Lunn MPP6_GPIO, /* HDD 3 status */ 256554cdaefSAndrew Lunn MPP7_GPIO, /* HDD 4 status */ 257554cdaefSAndrew Lunn MPP8_UNUSED, 258554cdaefSAndrew Lunn MPP9_UNUSED, 259554cdaefSAndrew Lunn MPP10_GPIO, /* RTC int */ 260554cdaefSAndrew Lunn MPP11_UNUSED, 261554cdaefSAndrew Lunn MPP12_UNUSED, 262554cdaefSAndrew Lunn MPP13_UNUSED, 263554cdaefSAndrew Lunn MPP14_GPIO, /* SW_RST */ 264554cdaefSAndrew Lunn MPP15_GPIO, /* USB copy button */ 265554cdaefSAndrew Lunn MPP16_UART, /* UART1 RXD */ 266554cdaefSAndrew Lunn MPP17_UART, /* UART1 TXD */ 267554cdaefSAndrew Lunn MPP18_UNUSED, 268554cdaefSAndrew Lunn MPP19_UNUSED, 269554cdaefSAndrew Lunn 0, 27047e9cffdSSylver Bruneau }; 27147e9cffdSSylver Bruneau 27247e9cffdSSylver Bruneau static void __init qnap_ts409_init(void) 27347e9cffdSSylver Bruneau { 27447e9cffdSSylver Bruneau /* 27547e9cffdSSylver Bruneau * Setup basic Orion functions. Need to be called early. 27647e9cffdSSylver Bruneau */ 27747e9cffdSSylver Bruneau orion5x_init(); 27847e9cffdSSylver Bruneau 27947e9cffdSSylver Bruneau orion5x_mpp_conf(ts409_mpp_modes); 28047e9cffdSSylver Bruneau 28147e9cffdSSylver Bruneau /* 28247e9cffdSSylver Bruneau * Configure peripherals. 28347e9cffdSSylver Bruneau */ 2844ca2c040SThomas Petazzoni mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET, 2854ca2c040SThomas Petazzoni ORION_MBUS_DEVBUS_BOOT_ATTR, 2864ca2c040SThomas Petazzoni QNAP_TS409_NOR_BOOT_BASE, 28735228e84SMartin Michlmayr QNAP_TS409_NOR_BOOT_SIZE); 28835228e84SMartin Michlmayr platform_device_register(&qnap_ts409_nor_flash); 28935228e84SMartin Michlmayr 29047e9cffdSSylver Bruneau orion5x_ehci0_init(); 291530c854aSSylver Bruneau qnap_tsx09_find_mac_addr(QNAP_TS409_NOR_BOOT_BASE + 292530c854aSSylver Bruneau qnap_ts409_partitions[5].offset, 293530c854aSSylver Bruneau qnap_ts409_partitions[5].size); 294530c854aSSylver Bruneau orion5x_eth_init(&qnap_tsx09_eth_data); 29547e9cffdSSylver Bruneau orion5x_i2c_init(); 29647e9cffdSSylver Bruneau orion5x_uart0_init(); 297e45772b2SMartin Michlmayr orion5x_uart1_init(); 29847e9cffdSSylver Bruneau 29947e9cffdSSylver Bruneau platform_device_register(&qnap_ts409_button_device); 30047e9cffdSSylver Bruneau 30147e9cffdSSylver Bruneau /* Get RTC IRQ and register the chip */ 30247e9cffdSSylver Bruneau if (gpio_request(TS409_RTC_GPIO, "rtc") == 0) { 30347e9cffdSSylver Bruneau if (gpio_direction_input(TS409_RTC_GPIO) == 0) 30447e9cffdSSylver Bruneau qnap_ts409_i2c_rtc.irq = gpio_to_irq(TS409_RTC_GPIO); 30547e9cffdSSylver Bruneau else 30647e9cffdSSylver Bruneau gpio_free(TS409_RTC_GPIO); 30747e9cffdSSylver Bruneau } 30847e9cffdSSylver Bruneau if (qnap_ts409_i2c_rtc.irq == 0) 3099d06d34bSJoe Perches pr_warn("qnap_ts409_init: failed to get RTC IRQ\n"); 31047e9cffdSSylver Bruneau i2c_register_board_info(0, &qnap_ts409_i2c_rtc, 1); 3113153eb8eSLinus Walleij gpiod_add_lookup_table(&ts409_leds_gpio_table); 3124a4e30afSMartin Michlmayr platform_device_register(&ts409_leds); 31347e9cffdSSylver Bruneau 314530c854aSSylver Bruneau /* register tsx09 specific power-off method */ 315*4bf23b96SAndrew Davis register_platform_power_off(qnap_tsx09_power_off); 31647e9cffdSSylver Bruneau } 31747e9cffdSSylver Bruneau 31847e9cffdSSylver Bruneau MACHINE_START(TS409, "QNAP TS-409") 31947e9cffdSSylver Bruneau /* Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> */ 32065aa1b1eSNicolas Pitre .atag_offset = 0x100, 3215cdbe5d2SArnd Bergmann .nr_irqs = ORION5X_NR_IRQS, 32247e9cffdSSylver Bruneau .init_machine = qnap_ts409_init, 32347e9cffdSSylver Bruneau .map_io = orion5x_map_io, 3244ee1f6b5SLennert Buytenhek .init_early = orion5x_init_early, 32547e9cffdSSylver Bruneau .init_irq = orion5x_init_irq, 3266bb27d73SStephen Warren .init_time = orion5x_timer_init, 32747e9cffdSSylver Bruneau .fixup = tag_fixup_mem32, 328764cbcc2SRussell King .restart = orion5x_restart, 32947e9cffdSSylver Bruneau MACHINE_END 330