18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * QNAP TS-409 Board Setup 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 2008 Sylver Bruneau <sylver.bruneau@gmail.com> 88c2ecf20Sopenharmony_ci * Copyright (C) 2008 Martin Michlmayr <tbm@cyrius.com> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci#include <linux/gpio.h> 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/init.h> 138c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 148c2ecf20Sopenharmony_ci#include <linux/pci.h> 158c2ecf20Sopenharmony_ci#include <linux/irq.h> 168c2ecf20Sopenharmony_ci#include <linux/mtd/physmap.h> 178c2ecf20Sopenharmony_ci#include <linux/mv643xx_eth.h> 188c2ecf20Sopenharmony_ci#include <linux/leds.h> 198c2ecf20Sopenharmony_ci#include <linux/gpio_keys.h> 208c2ecf20Sopenharmony_ci#include <linux/input.h> 218c2ecf20Sopenharmony_ci#include <linux/i2c.h> 228c2ecf20Sopenharmony_ci#include <linux/serial_reg.h> 238c2ecf20Sopenharmony_ci#include <asm/mach-types.h> 248c2ecf20Sopenharmony_ci#include <asm/mach/arch.h> 258c2ecf20Sopenharmony_ci#include <asm/mach/pci.h> 268c2ecf20Sopenharmony_ci#include "common.h" 278c2ecf20Sopenharmony_ci#include "mpp.h" 288c2ecf20Sopenharmony_ci#include "orion5x.h" 298c2ecf20Sopenharmony_ci#include "tsx09-common.h" 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci/***************************************************************************** 328c2ecf20Sopenharmony_ci * QNAP TS-409 Info 338c2ecf20Sopenharmony_ci ****************************************************************************/ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* 368c2ecf20Sopenharmony_ci * QNAP TS-409 hardware : 378c2ecf20Sopenharmony_ci * - Marvell 88F5281-D0 388c2ecf20Sopenharmony_ci * - Marvell 88SX7042 SATA controller (PCIe) 398c2ecf20Sopenharmony_ci * - Marvell 88E1118 Gigabit Ethernet PHY 408c2ecf20Sopenharmony_ci * - RTC S35390A (@0x30) on I2C bus 418c2ecf20Sopenharmony_ci * - 8MB NOR flash 428c2ecf20Sopenharmony_ci * - 256MB of DDR-2 RAM 438c2ecf20Sopenharmony_ci */ 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci/* 468c2ecf20Sopenharmony_ci * 8MB NOR flash Device bus boot chip select 478c2ecf20Sopenharmony_ci */ 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci#define QNAP_TS409_NOR_BOOT_BASE 0xff800000 508c2ecf20Sopenharmony_ci#define QNAP_TS409_NOR_BOOT_SIZE SZ_8M 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/**************************************************************************** 538c2ecf20Sopenharmony_ci * 8MiB NOR flash. The struct mtd_partition is not in the same order as the 548c2ecf20Sopenharmony_ci * partitions on the device because we want to keep compatibility with 558c2ecf20Sopenharmony_ci * existing QNAP firmware. 568c2ecf20Sopenharmony_ci * 578c2ecf20Sopenharmony_ci * Layout as used by QNAP: 588c2ecf20Sopenharmony_ci * [2] 0x00000000-0x00200000 : "Kernel" 598c2ecf20Sopenharmony_ci * [3] 0x00200000-0x00600000 : "RootFS1" 608c2ecf20Sopenharmony_ci * [4] 0x00600000-0x00700000 : "RootFS2" 618c2ecf20Sopenharmony_ci * [6] 0x00700000-0x00760000 : "NAS Config" (read-only) 628c2ecf20Sopenharmony_ci * [5] 0x00760000-0x00780000 : "U-Boot Config" 638c2ecf20Sopenharmony_ci * [1] 0x00780000-0x00800000 : "U-Boot" (read-only) 648c2ecf20Sopenharmony_ci ***************************************************************************/ 658c2ecf20Sopenharmony_cistatic struct mtd_partition qnap_ts409_partitions[] = { 668c2ecf20Sopenharmony_ci { 678c2ecf20Sopenharmony_ci .name = "U-Boot", 688c2ecf20Sopenharmony_ci .size = 0x00080000, 698c2ecf20Sopenharmony_ci .offset = 0x00780000, 708c2ecf20Sopenharmony_ci .mask_flags = MTD_WRITEABLE, 718c2ecf20Sopenharmony_ci }, { 728c2ecf20Sopenharmony_ci .name = "Kernel", 738c2ecf20Sopenharmony_ci .size = 0x00200000, 748c2ecf20Sopenharmony_ci .offset = 0, 758c2ecf20Sopenharmony_ci }, { 768c2ecf20Sopenharmony_ci .name = "RootFS1", 778c2ecf20Sopenharmony_ci .size = 0x00400000, 788c2ecf20Sopenharmony_ci .offset = 0x00200000, 798c2ecf20Sopenharmony_ci }, { 808c2ecf20Sopenharmony_ci .name = "RootFS2", 818c2ecf20Sopenharmony_ci .size = 0x00100000, 828c2ecf20Sopenharmony_ci .offset = 0x00600000, 838c2ecf20Sopenharmony_ci }, { 848c2ecf20Sopenharmony_ci .name = "U-Boot Config", 858c2ecf20Sopenharmony_ci .size = 0x00020000, 868c2ecf20Sopenharmony_ci .offset = 0x00760000, 878c2ecf20Sopenharmony_ci }, { 888c2ecf20Sopenharmony_ci .name = "NAS Config", 898c2ecf20Sopenharmony_ci .size = 0x00060000, 908c2ecf20Sopenharmony_ci .offset = 0x00700000, 918c2ecf20Sopenharmony_ci .mask_flags = MTD_WRITEABLE, 928c2ecf20Sopenharmony_ci }, 938c2ecf20Sopenharmony_ci}; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic struct physmap_flash_data qnap_ts409_nor_flash_data = { 968c2ecf20Sopenharmony_ci .width = 1, 978c2ecf20Sopenharmony_ci .parts = qnap_ts409_partitions, 988c2ecf20Sopenharmony_ci .nr_parts = ARRAY_SIZE(qnap_ts409_partitions) 998c2ecf20Sopenharmony_ci}; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_cistatic struct resource qnap_ts409_nor_flash_resource = { 1028c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM, 1038c2ecf20Sopenharmony_ci .start = QNAP_TS409_NOR_BOOT_BASE, 1048c2ecf20Sopenharmony_ci .end = QNAP_TS409_NOR_BOOT_BASE + QNAP_TS409_NOR_BOOT_SIZE - 1, 1058c2ecf20Sopenharmony_ci}; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic struct platform_device qnap_ts409_nor_flash = { 1088c2ecf20Sopenharmony_ci .name = "physmap-flash", 1098c2ecf20Sopenharmony_ci .id = 0, 1108c2ecf20Sopenharmony_ci .dev = { .platform_data = &qnap_ts409_nor_flash_data, }, 1118c2ecf20Sopenharmony_ci .num_resources = 1, 1128c2ecf20Sopenharmony_ci .resource = &qnap_ts409_nor_flash_resource, 1138c2ecf20Sopenharmony_ci}; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci/***************************************************************************** 1168c2ecf20Sopenharmony_ci * PCI 1178c2ecf20Sopenharmony_ci ****************************************************************************/ 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic int __init qnap_ts409_pci_map_irq(const struct pci_dev *dev, u8 slot, 1208c2ecf20Sopenharmony_ci u8 pin) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci int irq; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci /* 1258c2ecf20Sopenharmony_ci * Check for devices with hard-wired IRQs. 1268c2ecf20Sopenharmony_ci */ 1278c2ecf20Sopenharmony_ci irq = orion5x_pci_map_irq(dev, slot, pin); 1288c2ecf20Sopenharmony_ci if (irq != -1) 1298c2ecf20Sopenharmony_ci return irq; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci /* 1328c2ecf20Sopenharmony_ci * PCI isn't used on the TS-409 1338c2ecf20Sopenharmony_ci */ 1348c2ecf20Sopenharmony_ci return -1; 1358c2ecf20Sopenharmony_ci} 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cistatic struct hw_pci qnap_ts409_pci __initdata = { 1388c2ecf20Sopenharmony_ci .nr_controllers = 2, 1398c2ecf20Sopenharmony_ci .setup = orion5x_pci_sys_setup, 1408c2ecf20Sopenharmony_ci .scan = orion5x_pci_sys_scan_bus, 1418c2ecf20Sopenharmony_ci .map_irq = qnap_ts409_pci_map_irq, 1428c2ecf20Sopenharmony_ci}; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic int __init qnap_ts409_pci_init(void) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci if (machine_is_ts409()) 1478c2ecf20Sopenharmony_ci pci_common_init(&qnap_ts409_pci); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci return 0; 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cisubsys_initcall(qnap_ts409_pci_init); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci/***************************************************************************** 1558c2ecf20Sopenharmony_ci * RTC S35390A on I2C bus 1568c2ecf20Sopenharmony_ci ****************************************************************************/ 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci#define TS409_RTC_GPIO 10 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cistatic struct i2c_board_info __initdata qnap_ts409_i2c_rtc = { 1618c2ecf20Sopenharmony_ci I2C_BOARD_INFO("s35390a", 0x30), 1628c2ecf20Sopenharmony_ci}; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci/***************************************************************************** 1658c2ecf20Sopenharmony_ci * LEDs attached to GPIO 1668c2ecf20Sopenharmony_ci ****************************************************************************/ 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic struct gpio_led ts409_led_pins[] = { 1698c2ecf20Sopenharmony_ci { 1708c2ecf20Sopenharmony_ci .name = "ts409:red:sata1", 1718c2ecf20Sopenharmony_ci .gpio = 4, 1728c2ecf20Sopenharmony_ci .active_low = 1, 1738c2ecf20Sopenharmony_ci }, { 1748c2ecf20Sopenharmony_ci .name = "ts409:red:sata2", 1758c2ecf20Sopenharmony_ci .gpio = 5, 1768c2ecf20Sopenharmony_ci .active_low = 1, 1778c2ecf20Sopenharmony_ci }, { 1788c2ecf20Sopenharmony_ci .name = "ts409:red:sata3", 1798c2ecf20Sopenharmony_ci .gpio = 6, 1808c2ecf20Sopenharmony_ci .active_low = 1, 1818c2ecf20Sopenharmony_ci }, { 1828c2ecf20Sopenharmony_ci .name = "ts409:red:sata4", 1838c2ecf20Sopenharmony_ci .gpio = 7, 1848c2ecf20Sopenharmony_ci .active_low = 1, 1858c2ecf20Sopenharmony_ci }, 1868c2ecf20Sopenharmony_ci}; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic struct gpio_led_platform_data ts409_led_data = { 1898c2ecf20Sopenharmony_ci .leds = ts409_led_pins, 1908c2ecf20Sopenharmony_ci .num_leds = ARRAY_SIZE(ts409_led_pins), 1918c2ecf20Sopenharmony_ci}; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic struct platform_device ts409_leds = { 1948c2ecf20Sopenharmony_ci .name = "leds-gpio", 1958c2ecf20Sopenharmony_ci .id = -1, 1968c2ecf20Sopenharmony_ci .dev = { 1978c2ecf20Sopenharmony_ci .platform_data = &ts409_led_data, 1988c2ecf20Sopenharmony_ci }, 1998c2ecf20Sopenharmony_ci}; 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci/**************************************************************************** 2028c2ecf20Sopenharmony_ci * GPIO Attached Keys 2038c2ecf20Sopenharmony_ci * Power button is attached to the PIC microcontroller 2048c2ecf20Sopenharmony_ci ****************************************************************************/ 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci#define QNAP_TS409_GPIO_KEY_RESET 14 2078c2ecf20Sopenharmony_ci#define QNAP_TS409_GPIO_KEY_MEDIA 15 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic struct gpio_keys_button qnap_ts409_buttons[] = { 2108c2ecf20Sopenharmony_ci { 2118c2ecf20Sopenharmony_ci .code = KEY_RESTART, 2128c2ecf20Sopenharmony_ci .gpio = QNAP_TS409_GPIO_KEY_RESET, 2138c2ecf20Sopenharmony_ci .desc = "Reset Button", 2148c2ecf20Sopenharmony_ci .active_low = 1, 2158c2ecf20Sopenharmony_ci }, { 2168c2ecf20Sopenharmony_ci .code = KEY_COPY, 2178c2ecf20Sopenharmony_ci .gpio = QNAP_TS409_GPIO_KEY_MEDIA, 2188c2ecf20Sopenharmony_ci .desc = "USB Copy Button", 2198c2ecf20Sopenharmony_ci .active_low = 1, 2208c2ecf20Sopenharmony_ci }, 2218c2ecf20Sopenharmony_ci}; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_cistatic struct gpio_keys_platform_data qnap_ts409_button_data = { 2248c2ecf20Sopenharmony_ci .buttons = qnap_ts409_buttons, 2258c2ecf20Sopenharmony_ci .nbuttons = ARRAY_SIZE(qnap_ts409_buttons), 2268c2ecf20Sopenharmony_ci}; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic struct platform_device qnap_ts409_button_device = { 2298c2ecf20Sopenharmony_ci .name = "gpio-keys", 2308c2ecf20Sopenharmony_ci .id = -1, 2318c2ecf20Sopenharmony_ci .num_resources = 0, 2328c2ecf20Sopenharmony_ci .dev = { 2338c2ecf20Sopenharmony_ci .platform_data = &qnap_ts409_button_data, 2348c2ecf20Sopenharmony_ci }, 2358c2ecf20Sopenharmony_ci}; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci/***************************************************************************** 2388c2ecf20Sopenharmony_ci * General Setup 2398c2ecf20Sopenharmony_ci ****************************************************************************/ 2408c2ecf20Sopenharmony_cistatic unsigned int ts409_mpp_modes[] __initdata = { 2418c2ecf20Sopenharmony_ci MPP0_UNUSED, 2428c2ecf20Sopenharmony_ci MPP1_UNUSED, 2438c2ecf20Sopenharmony_ci MPP2_UNUSED, 2448c2ecf20Sopenharmony_ci MPP3_UNUSED, 2458c2ecf20Sopenharmony_ci MPP4_GPIO, /* HDD 1 status */ 2468c2ecf20Sopenharmony_ci MPP5_GPIO, /* HDD 2 status */ 2478c2ecf20Sopenharmony_ci MPP6_GPIO, /* HDD 3 status */ 2488c2ecf20Sopenharmony_ci MPP7_GPIO, /* HDD 4 status */ 2498c2ecf20Sopenharmony_ci MPP8_UNUSED, 2508c2ecf20Sopenharmony_ci MPP9_UNUSED, 2518c2ecf20Sopenharmony_ci MPP10_GPIO, /* RTC int */ 2528c2ecf20Sopenharmony_ci MPP11_UNUSED, 2538c2ecf20Sopenharmony_ci MPP12_UNUSED, 2548c2ecf20Sopenharmony_ci MPP13_UNUSED, 2558c2ecf20Sopenharmony_ci MPP14_GPIO, /* SW_RST */ 2568c2ecf20Sopenharmony_ci MPP15_GPIO, /* USB copy button */ 2578c2ecf20Sopenharmony_ci MPP16_UART, /* UART1 RXD */ 2588c2ecf20Sopenharmony_ci MPP17_UART, /* UART1 TXD */ 2598c2ecf20Sopenharmony_ci MPP18_UNUSED, 2608c2ecf20Sopenharmony_ci MPP19_UNUSED, 2618c2ecf20Sopenharmony_ci 0, 2628c2ecf20Sopenharmony_ci}; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_cistatic void __init qnap_ts409_init(void) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci /* 2678c2ecf20Sopenharmony_ci * Setup basic Orion functions. Need to be called early. 2688c2ecf20Sopenharmony_ci */ 2698c2ecf20Sopenharmony_ci orion5x_init(); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci orion5x_mpp_conf(ts409_mpp_modes); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci /* 2748c2ecf20Sopenharmony_ci * Configure peripherals. 2758c2ecf20Sopenharmony_ci */ 2768c2ecf20Sopenharmony_ci mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET, 2778c2ecf20Sopenharmony_ci ORION_MBUS_DEVBUS_BOOT_ATTR, 2788c2ecf20Sopenharmony_ci QNAP_TS409_NOR_BOOT_BASE, 2798c2ecf20Sopenharmony_ci QNAP_TS409_NOR_BOOT_SIZE); 2808c2ecf20Sopenharmony_ci platform_device_register(&qnap_ts409_nor_flash); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci orion5x_ehci0_init(); 2838c2ecf20Sopenharmony_ci qnap_tsx09_find_mac_addr(QNAP_TS409_NOR_BOOT_BASE + 2848c2ecf20Sopenharmony_ci qnap_ts409_partitions[5].offset, 2858c2ecf20Sopenharmony_ci qnap_ts409_partitions[5].size); 2868c2ecf20Sopenharmony_ci orion5x_eth_init(&qnap_tsx09_eth_data); 2878c2ecf20Sopenharmony_ci orion5x_i2c_init(); 2888c2ecf20Sopenharmony_ci orion5x_uart0_init(); 2898c2ecf20Sopenharmony_ci orion5x_uart1_init(); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci platform_device_register(&qnap_ts409_button_device); 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* Get RTC IRQ and register the chip */ 2948c2ecf20Sopenharmony_ci if (gpio_request(TS409_RTC_GPIO, "rtc") == 0) { 2958c2ecf20Sopenharmony_ci if (gpio_direction_input(TS409_RTC_GPIO) == 0) 2968c2ecf20Sopenharmony_ci qnap_ts409_i2c_rtc.irq = gpio_to_irq(TS409_RTC_GPIO); 2978c2ecf20Sopenharmony_ci else 2988c2ecf20Sopenharmony_ci gpio_free(TS409_RTC_GPIO); 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci if (qnap_ts409_i2c_rtc.irq == 0) 3018c2ecf20Sopenharmony_ci pr_warn("qnap_ts409_init: failed to get RTC IRQ\n"); 3028c2ecf20Sopenharmony_ci i2c_register_board_info(0, &qnap_ts409_i2c_rtc, 1); 3038c2ecf20Sopenharmony_ci platform_device_register(&ts409_leds); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci /* register tsx09 specific power-off method */ 3068c2ecf20Sopenharmony_ci pm_power_off = qnap_tsx09_power_off; 3078c2ecf20Sopenharmony_ci} 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ciMACHINE_START(TS409, "QNAP TS-409") 3108c2ecf20Sopenharmony_ci /* Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> */ 3118c2ecf20Sopenharmony_ci .atag_offset = 0x100, 3128c2ecf20Sopenharmony_ci .nr_irqs = ORION5X_NR_IRQS, 3138c2ecf20Sopenharmony_ci .init_machine = qnap_ts409_init, 3148c2ecf20Sopenharmony_ci .map_io = orion5x_map_io, 3158c2ecf20Sopenharmony_ci .init_early = orion5x_init_early, 3168c2ecf20Sopenharmony_ci .init_irq = orion5x_init_irq, 3178c2ecf20Sopenharmony_ci .init_time = orion5x_timer_init, 3188c2ecf20Sopenharmony_ci .fixup = tag_fixup_mem32, 3198c2ecf20Sopenharmony_ci .restart = orion5x_restart, 3208c2ecf20Sopenharmony_ciMACHINE_END 321