1*2874c5fdSThomas 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> 1147e9cffdSSylver Bruneau #include <linux/kernel.h> 1247e9cffdSSylver Bruneau #include <linux/init.h> 1347e9cffdSSylver Bruneau #include <linux/platform_device.h> 1447e9cffdSSylver Bruneau #include <linux/pci.h> 1547e9cffdSSylver Bruneau #include <linux/irq.h> 1647e9cffdSSylver Bruneau #include <linux/mtd/physmap.h> 1747e9cffdSSylver Bruneau #include <linux/mv643xx_eth.h> 184a4e30afSMartin Michlmayr #include <linux/leds.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/mach/arch.h> 2547e9cffdSSylver Bruneau #include <asm/mach/pci.h> 2647e9cffdSSylver Bruneau #include "common.h" 2747e9cffdSSylver Bruneau #include "mpp.h" 28c22c2c60SArnd Bergmann #include "orion5x.h" 29530c854aSSylver Bruneau #include "tsx09-common.h" 3047e9cffdSSylver Bruneau 3147e9cffdSSylver Bruneau /***************************************************************************** 3247e9cffdSSylver Bruneau * QNAP TS-409 Info 3347e9cffdSSylver Bruneau ****************************************************************************/ 3447e9cffdSSylver Bruneau 3547e9cffdSSylver Bruneau /* 3647e9cffdSSylver Bruneau * QNAP TS-409 hardware : 3747e9cffdSSylver Bruneau * - Marvell 88F5281-D0 3847e9cffdSSylver Bruneau * - Marvell 88SX7042 SATA controller (PCIe) 3947e9cffdSSylver Bruneau * - Marvell 88E1118 Gigabit Ethernet PHY 4047e9cffdSSylver Bruneau * - RTC S35390A (@0x30) on I2C bus 4147e9cffdSSylver Bruneau * - 8MB NOR flash 4247e9cffdSSylver Bruneau * - 256MB of DDR-2 RAM 4347e9cffdSSylver Bruneau */ 4447e9cffdSSylver Bruneau 4547e9cffdSSylver Bruneau /* 4647e9cffdSSylver Bruneau * 8MB NOR flash Device bus boot chip select 4747e9cffdSSylver Bruneau */ 4847e9cffdSSylver Bruneau 4947e9cffdSSylver Bruneau #define QNAP_TS409_NOR_BOOT_BASE 0xff800000 5047e9cffdSSylver Bruneau #define QNAP_TS409_NOR_BOOT_SIZE SZ_8M 5147e9cffdSSylver Bruneau 5247e9cffdSSylver Bruneau /**************************************************************************** 5347e9cffdSSylver Bruneau * 8MiB NOR flash. The struct mtd_partition is not in the same order as the 5425985edcSLucas De Marchi * partitions on the device because we want to keep compatibility with 5547e9cffdSSylver Bruneau * existing QNAP firmware. 5647e9cffdSSylver Bruneau * 5747e9cffdSSylver Bruneau * Layout as used by QNAP: 5847e9cffdSSylver Bruneau * [2] 0x00000000-0x00200000 : "Kernel" 5947e9cffdSSylver Bruneau * [3] 0x00200000-0x00600000 : "RootFS1" 6047e9cffdSSylver Bruneau * [4] 0x00600000-0x00700000 : "RootFS2" 6147e9cffdSSylver Bruneau * [6] 0x00700000-0x00760000 : "NAS Config" (read-only) 6247e9cffdSSylver Bruneau * [5] 0x00760000-0x00780000 : "U-Boot Config" 6347e9cffdSSylver Bruneau * [1] 0x00780000-0x00800000 : "U-Boot" (read-only) 6447e9cffdSSylver Bruneau ***************************************************************************/ 6547e9cffdSSylver Bruneau static struct mtd_partition qnap_ts409_partitions[] = { 6647e9cffdSSylver Bruneau { 6747e9cffdSSylver Bruneau .name = "U-Boot", 6847e9cffdSSylver Bruneau .size = 0x00080000, 6947e9cffdSSylver Bruneau .offset = 0x00780000, 7047e9cffdSSylver Bruneau .mask_flags = MTD_WRITEABLE, 7147e9cffdSSylver Bruneau }, { 7247e9cffdSSylver Bruneau .name = "Kernel", 7347e9cffdSSylver Bruneau .size = 0x00200000, 7447e9cffdSSylver Bruneau .offset = 0, 7547e9cffdSSylver Bruneau }, { 7647e9cffdSSylver Bruneau .name = "RootFS1", 7747e9cffdSSylver Bruneau .size = 0x00400000, 7847e9cffdSSylver Bruneau .offset = 0x00200000, 7947e9cffdSSylver Bruneau }, { 8047e9cffdSSylver Bruneau .name = "RootFS2", 8147e9cffdSSylver Bruneau .size = 0x00100000, 8247e9cffdSSylver Bruneau .offset = 0x00600000, 8347e9cffdSSylver Bruneau }, { 8447e9cffdSSylver Bruneau .name = "U-Boot Config", 8547e9cffdSSylver Bruneau .size = 0x00020000, 8647e9cffdSSylver Bruneau .offset = 0x00760000, 8747e9cffdSSylver Bruneau }, { 8847e9cffdSSylver Bruneau .name = "NAS Config", 8947e9cffdSSylver Bruneau .size = 0x00060000, 9047e9cffdSSylver Bruneau .offset = 0x00700000, 9147e9cffdSSylver Bruneau .mask_flags = MTD_WRITEABLE, 9247e9cffdSSylver Bruneau }, 9347e9cffdSSylver Bruneau }; 9447e9cffdSSylver Bruneau 9547e9cffdSSylver Bruneau static struct physmap_flash_data qnap_ts409_nor_flash_data = { 9647e9cffdSSylver Bruneau .width = 1, 9747e9cffdSSylver Bruneau .parts = qnap_ts409_partitions, 9847e9cffdSSylver Bruneau .nr_parts = ARRAY_SIZE(qnap_ts409_partitions) 9947e9cffdSSylver Bruneau }; 10047e9cffdSSylver Bruneau 10147e9cffdSSylver Bruneau static struct resource qnap_ts409_nor_flash_resource = { 10247e9cffdSSylver Bruneau .flags = IORESOURCE_MEM, 10347e9cffdSSylver Bruneau .start = QNAP_TS409_NOR_BOOT_BASE, 10447e9cffdSSylver Bruneau .end = QNAP_TS409_NOR_BOOT_BASE + QNAP_TS409_NOR_BOOT_SIZE - 1, 10547e9cffdSSylver Bruneau }; 10647e9cffdSSylver Bruneau 10747e9cffdSSylver Bruneau static struct platform_device qnap_ts409_nor_flash = { 10847e9cffdSSylver Bruneau .name = "physmap-flash", 10947e9cffdSSylver Bruneau .id = 0, 11047e9cffdSSylver Bruneau .dev = { .platform_data = &qnap_ts409_nor_flash_data, }, 11147e9cffdSSylver Bruneau .num_resources = 1, 11247e9cffdSSylver Bruneau .resource = &qnap_ts409_nor_flash_resource, 11347e9cffdSSylver Bruneau }; 11447e9cffdSSylver Bruneau 11547e9cffdSSylver Bruneau /***************************************************************************** 11647e9cffdSSylver Bruneau * PCI 11747e9cffdSSylver Bruneau ****************************************************************************/ 11847e9cffdSSylver Bruneau 119d5341942SRalf Baechle static int __init qnap_ts409_pci_map_irq(const struct pci_dev *dev, u8 slot, 120d5341942SRalf Baechle 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 .setup = orion5x_pci_sys_setup, 14047e9cffdSSylver Bruneau .scan = orion5x_pci_sys_scan_bus, 14147e9cffdSSylver Bruneau .map_irq = qnap_ts409_pci_map_irq, 14247e9cffdSSylver Bruneau }; 14347e9cffdSSylver Bruneau 14447e9cffdSSylver Bruneau static int __init qnap_ts409_pci_init(void) 14547e9cffdSSylver Bruneau { 14647e9cffdSSylver Bruneau if (machine_is_ts409()) 14747e9cffdSSylver Bruneau pci_common_init(&qnap_ts409_pci); 14847e9cffdSSylver Bruneau 14947e9cffdSSylver Bruneau return 0; 15047e9cffdSSylver Bruneau } 15147e9cffdSSylver Bruneau 15247e9cffdSSylver Bruneau subsys_initcall(qnap_ts409_pci_init); 15347e9cffdSSylver Bruneau 15447e9cffdSSylver Bruneau /***************************************************************************** 15547e9cffdSSylver Bruneau * RTC S35390A on I2C bus 15647e9cffdSSylver Bruneau ****************************************************************************/ 15747e9cffdSSylver Bruneau 15847e9cffdSSylver Bruneau #define TS409_RTC_GPIO 10 15947e9cffdSSylver Bruneau 16047e9cffdSSylver Bruneau static struct i2c_board_info __initdata qnap_ts409_i2c_rtc = { 16147e9cffdSSylver Bruneau I2C_BOARD_INFO("s35390a", 0x30), 16247e9cffdSSylver Bruneau }; 16347e9cffdSSylver Bruneau 1644a4e30afSMartin Michlmayr /***************************************************************************** 1654a4e30afSMartin Michlmayr * LEDs attached to GPIO 1664a4e30afSMartin Michlmayr ****************************************************************************/ 1674a4e30afSMartin Michlmayr 1684a4e30afSMartin Michlmayr static struct gpio_led ts409_led_pins[] = { 1694a4e30afSMartin Michlmayr { 1704a4e30afSMartin Michlmayr .name = "ts409:red:sata1", 1714a4e30afSMartin Michlmayr .gpio = 4, 1724a4e30afSMartin Michlmayr .active_low = 1, 1734a4e30afSMartin Michlmayr }, { 1744a4e30afSMartin Michlmayr .name = "ts409:red:sata2", 1754a4e30afSMartin Michlmayr .gpio = 5, 1764a4e30afSMartin Michlmayr .active_low = 1, 1774a4e30afSMartin Michlmayr }, { 1784a4e30afSMartin Michlmayr .name = "ts409:red:sata3", 1794a4e30afSMartin Michlmayr .gpio = 6, 1804a4e30afSMartin Michlmayr .active_low = 1, 1814a4e30afSMartin Michlmayr }, { 1824a4e30afSMartin Michlmayr .name = "ts409:red:sata4", 1834a4e30afSMartin Michlmayr .gpio = 7, 1844a4e30afSMartin Michlmayr .active_low = 1, 1854a4e30afSMartin Michlmayr }, 1864a4e30afSMartin Michlmayr }; 1874a4e30afSMartin Michlmayr 1884a4e30afSMartin Michlmayr static struct gpio_led_platform_data ts409_led_data = { 1894a4e30afSMartin Michlmayr .leds = ts409_led_pins, 1904a4e30afSMartin Michlmayr .num_leds = ARRAY_SIZE(ts409_led_pins), 1914a4e30afSMartin Michlmayr }; 1924a4e30afSMartin Michlmayr 1934a4e30afSMartin Michlmayr static struct platform_device ts409_leds = { 1944a4e30afSMartin Michlmayr .name = "leds-gpio", 1954a4e30afSMartin Michlmayr .id = -1, 1964a4e30afSMartin Michlmayr .dev = { 1974a4e30afSMartin Michlmayr .platform_data = &ts409_led_data, 1984a4e30afSMartin Michlmayr }, 1994a4e30afSMartin Michlmayr }; 2004a4e30afSMartin Michlmayr 20147e9cffdSSylver Bruneau /**************************************************************************** 20247e9cffdSSylver Bruneau * GPIO Attached Keys 20347e9cffdSSylver Bruneau * Power button is attached to the PIC microcontroller 20447e9cffdSSylver Bruneau ****************************************************************************/ 20547e9cffdSSylver Bruneau 2065cebbd09SMartin Michlmayr #define QNAP_TS409_GPIO_KEY_RESET 14 20747e9cffdSSylver Bruneau #define QNAP_TS409_GPIO_KEY_MEDIA 15 20847e9cffdSSylver Bruneau 20947e9cffdSSylver Bruneau static struct gpio_keys_button qnap_ts409_buttons[] = { 21047e9cffdSSylver Bruneau { 2115cebbd09SMartin Michlmayr .code = KEY_RESTART, 2125cebbd09SMartin Michlmayr .gpio = QNAP_TS409_GPIO_KEY_RESET, 2135cebbd09SMartin Michlmayr .desc = "Reset Button", 2145cebbd09SMartin Michlmayr .active_low = 1, 2155cebbd09SMartin Michlmayr }, { 21628ca8c80SMartin Michlmayr .code = KEY_COPY, 21747e9cffdSSylver Bruneau .gpio = QNAP_TS409_GPIO_KEY_MEDIA, 21847e9cffdSSylver Bruneau .desc = "USB Copy Button", 21947e9cffdSSylver Bruneau .active_low = 1, 22047e9cffdSSylver Bruneau }, 22147e9cffdSSylver Bruneau }; 22247e9cffdSSylver Bruneau 22347e9cffdSSylver Bruneau static struct gpio_keys_platform_data qnap_ts409_button_data = { 22447e9cffdSSylver Bruneau .buttons = qnap_ts409_buttons, 22547e9cffdSSylver Bruneau .nbuttons = ARRAY_SIZE(qnap_ts409_buttons), 22647e9cffdSSylver Bruneau }; 22747e9cffdSSylver Bruneau 22847e9cffdSSylver Bruneau static struct platform_device qnap_ts409_button_device = { 22947e9cffdSSylver Bruneau .name = "gpio-keys", 23047e9cffdSSylver Bruneau .id = -1, 23147e9cffdSSylver Bruneau .num_resources = 0, 23247e9cffdSSylver Bruneau .dev = { 23347e9cffdSSylver Bruneau .platform_data = &qnap_ts409_button_data, 23447e9cffdSSylver Bruneau }, 23547e9cffdSSylver Bruneau }; 23647e9cffdSSylver Bruneau 23747e9cffdSSylver Bruneau /***************************************************************************** 23847e9cffdSSylver Bruneau * General Setup 23947e9cffdSSylver Bruneau ****************************************************************************/ 240554cdaefSAndrew Lunn static unsigned int ts409_mpp_modes[] __initdata = { 241554cdaefSAndrew Lunn MPP0_UNUSED, 242554cdaefSAndrew Lunn MPP1_UNUSED, 243554cdaefSAndrew Lunn MPP2_UNUSED, 244554cdaefSAndrew Lunn MPP3_UNUSED, 245554cdaefSAndrew Lunn MPP4_GPIO, /* HDD 1 status */ 246554cdaefSAndrew Lunn MPP5_GPIO, /* HDD 2 status */ 247554cdaefSAndrew Lunn MPP6_GPIO, /* HDD 3 status */ 248554cdaefSAndrew Lunn MPP7_GPIO, /* HDD 4 status */ 249554cdaefSAndrew Lunn MPP8_UNUSED, 250554cdaefSAndrew Lunn MPP9_UNUSED, 251554cdaefSAndrew Lunn MPP10_GPIO, /* RTC int */ 252554cdaefSAndrew Lunn MPP11_UNUSED, 253554cdaefSAndrew Lunn MPP12_UNUSED, 254554cdaefSAndrew Lunn MPP13_UNUSED, 255554cdaefSAndrew Lunn MPP14_GPIO, /* SW_RST */ 256554cdaefSAndrew Lunn MPP15_GPIO, /* USB copy button */ 257554cdaefSAndrew Lunn MPP16_UART, /* UART1 RXD */ 258554cdaefSAndrew Lunn MPP17_UART, /* UART1 TXD */ 259554cdaefSAndrew Lunn MPP18_UNUSED, 260554cdaefSAndrew Lunn MPP19_UNUSED, 261554cdaefSAndrew Lunn 0, 26247e9cffdSSylver Bruneau }; 26347e9cffdSSylver Bruneau 26447e9cffdSSylver Bruneau static void __init qnap_ts409_init(void) 26547e9cffdSSylver Bruneau { 26647e9cffdSSylver Bruneau /* 26747e9cffdSSylver Bruneau * Setup basic Orion functions. Need to be called early. 26847e9cffdSSylver Bruneau */ 26947e9cffdSSylver Bruneau orion5x_init(); 27047e9cffdSSylver Bruneau 27147e9cffdSSylver Bruneau orion5x_mpp_conf(ts409_mpp_modes); 27247e9cffdSSylver Bruneau 27347e9cffdSSylver Bruneau /* 27447e9cffdSSylver Bruneau * Configure peripherals. 27547e9cffdSSylver Bruneau */ 2764ca2c040SThomas Petazzoni mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET, 2774ca2c040SThomas Petazzoni ORION_MBUS_DEVBUS_BOOT_ATTR, 2784ca2c040SThomas Petazzoni QNAP_TS409_NOR_BOOT_BASE, 27935228e84SMartin Michlmayr QNAP_TS409_NOR_BOOT_SIZE); 28035228e84SMartin Michlmayr platform_device_register(&qnap_ts409_nor_flash); 28135228e84SMartin Michlmayr 28247e9cffdSSylver Bruneau orion5x_ehci0_init(); 283530c854aSSylver Bruneau qnap_tsx09_find_mac_addr(QNAP_TS409_NOR_BOOT_BASE + 284530c854aSSylver Bruneau qnap_ts409_partitions[5].offset, 285530c854aSSylver Bruneau qnap_ts409_partitions[5].size); 286530c854aSSylver Bruneau orion5x_eth_init(&qnap_tsx09_eth_data); 28747e9cffdSSylver Bruneau orion5x_i2c_init(); 28847e9cffdSSylver Bruneau orion5x_uart0_init(); 289e45772b2SMartin Michlmayr orion5x_uart1_init(); 29047e9cffdSSylver Bruneau 29147e9cffdSSylver Bruneau platform_device_register(&qnap_ts409_button_device); 29247e9cffdSSylver Bruneau 29347e9cffdSSylver Bruneau /* Get RTC IRQ and register the chip */ 29447e9cffdSSylver Bruneau if (gpio_request(TS409_RTC_GPIO, "rtc") == 0) { 29547e9cffdSSylver Bruneau if (gpio_direction_input(TS409_RTC_GPIO) == 0) 29647e9cffdSSylver Bruneau qnap_ts409_i2c_rtc.irq = gpio_to_irq(TS409_RTC_GPIO); 29747e9cffdSSylver Bruneau else 29847e9cffdSSylver Bruneau gpio_free(TS409_RTC_GPIO); 29947e9cffdSSylver Bruneau } 30047e9cffdSSylver Bruneau if (qnap_ts409_i2c_rtc.irq == 0) 3019d06d34bSJoe Perches pr_warn("qnap_ts409_init: failed to get RTC IRQ\n"); 30247e9cffdSSylver Bruneau i2c_register_board_info(0, &qnap_ts409_i2c_rtc, 1); 3034a4e30afSMartin Michlmayr platform_device_register(&ts409_leds); 30447e9cffdSSylver Bruneau 305530c854aSSylver Bruneau /* register tsx09 specific power-off method */ 306530c854aSSylver Bruneau pm_power_off = qnap_tsx09_power_off; 30747e9cffdSSylver Bruneau } 30847e9cffdSSylver Bruneau 30947e9cffdSSylver Bruneau MACHINE_START(TS409, "QNAP TS-409") 31047e9cffdSSylver Bruneau /* Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> */ 31165aa1b1eSNicolas Pitre .atag_offset = 0x100, 3125cdbe5d2SArnd Bergmann .nr_irqs = ORION5X_NR_IRQS, 31347e9cffdSSylver Bruneau .init_machine = qnap_ts409_init, 31447e9cffdSSylver Bruneau .map_io = orion5x_map_io, 3154ee1f6b5SLennert Buytenhek .init_early = orion5x_init_early, 31647e9cffdSSylver Bruneau .init_irq = orion5x_init_irq, 3176bb27d73SStephen Warren .init_time = orion5x_timer_init, 31847e9cffdSSylver Bruneau .fixup = tag_fixup_mem32, 319764cbcc2SRussell King .restart = orion5x_restart, 32047e9cffdSSylver Bruneau MACHINE_END 321