162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * QNAP TS-409 Board Setup 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2008 Sylver Bruneau <sylver.bruneau@gmail.com> 862306a36Sopenharmony_ci * Copyright (C) 2008 Martin Michlmayr <tbm@cyrius.com> 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci#include <linux/gpio.h> 1162306a36Sopenharmony_ci#include <linux/kernel.h> 1262306a36Sopenharmony_ci#include <linux/init.h> 1362306a36Sopenharmony_ci#include <linux/platform_device.h> 1462306a36Sopenharmony_ci#include <linux/pci.h> 1562306a36Sopenharmony_ci#include <linux/irq.h> 1662306a36Sopenharmony_ci#include <linux/mtd/physmap.h> 1762306a36Sopenharmony_ci#include <linux/mv643xx_eth.h> 1862306a36Sopenharmony_ci#include <linux/leds.h> 1962306a36Sopenharmony_ci#include <linux/gpio_keys.h> 2062306a36Sopenharmony_ci#include <linux/input.h> 2162306a36Sopenharmony_ci#include <linux/i2c.h> 2262306a36Sopenharmony_ci#include <linux/serial_reg.h> 2362306a36Sopenharmony_ci#include <asm/mach-types.h> 2462306a36Sopenharmony_ci#include <asm/mach/arch.h> 2562306a36Sopenharmony_ci#include <asm/mach/pci.h> 2662306a36Sopenharmony_ci#include "common.h" 2762306a36Sopenharmony_ci#include "mpp.h" 2862306a36Sopenharmony_ci#include "orion5x.h" 2962306a36Sopenharmony_ci#include "tsx09-common.h" 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/***************************************************************************** 3262306a36Sopenharmony_ci * QNAP TS-409 Info 3362306a36Sopenharmony_ci ****************************************************************************/ 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/* 3662306a36Sopenharmony_ci * QNAP TS-409 hardware : 3762306a36Sopenharmony_ci * - Marvell 88F5281-D0 3862306a36Sopenharmony_ci * - Marvell 88SX7042 SATA controller (PCIe) 3962306a36Sopenharmony_ci * - Marvell 88E1118 Gigabit Ethernet PHY 4062306a36Sopenharmony_ci * - RTC S35390A (@0x30) on I2C bus 4162306a36Sopenharmony_ci * - 8MB NOR flash 4262306a36Sopenharmony_ci * - 256MB of DDR-2 RAM 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/* 4662306a36Sopenharmony_ci * 8MB NOR flash Device bus boot chip select 4762306a36Sopenharmony_ci */ 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define QNAP_TS409_NOR_BOOT_BASE 0xff800000 5062306a36Sopenharmony_ci#define QNAP_TS409_NOR_BOOT_SIZE SZ_8M 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/**************************************************************************** 5362306a36Sopenharmony_ci * 8MiB NOR flash. The struct mtd_partition is not in the same order as the 5462306a36Sopenharmony_ci * partitions on the device because we want to keep compatibility with 5562306a36Sopenharmony_ci * existing QNAP firmware. 5662306a36Sopenharmony_ci * 5762306a36Sopenharmony_ci * Layout as used by QNAP: 5862306a36Sopenharmony_ci * [2] 0x00000000-0x00200000 : "Kernel" 5962306a36Sopenharmony_ci * [3] 0x00200000-0x00600000 : "RootFS1" 6062306a36Sopenharmony_ci * [4] 0x00600000-0x00700000 : "RootFS2" 6162306a36Sopenharmony_ci * [6] 0x00700000-0x00760000 : "NAS Config" (read-only) 6262306a36Sopenharmony_ci * [5] 0x00760000-0x00780000 : "U-Boot Config" 6362306a36Sopenharmony_ci * [1] 0x00780000-0x00800000 : "U-Boot" (read-only) 6462306a36Sopenharmony_ci ***************************************************************************/ 6562306a36Sopenharmony_cistatic struct mtd_partition qnap_ts409_partitions[] = { 6662306a36Sopenharmony_ci { 6762306a36Sopenharmony_ci .name = "U-Boot", 6862306a36Sopenharmony_ci .size = 0x00080000, 6962306a36Sopenharmony_ci .offset = 0x00780000, 7062306a36Sopenharmony_ci .mask_flags = MTD_WRITEABLE, 7162306a36Sopenharmony_ci }, { 7262306a36Sopenharmony_ci .name = "Kernel", 7362306a36Sopenharmony_ci .size = 0x00200000, 7462306a36Sopenharmony_ci .offset = 0, 7562306a36Sopenharmony_ci }, { 7662306a36Sopenharmony_ci .name = "RootFS1", 7762306a36Sopenharmony_ci .size = 0x00400000, 7862306a36Sopenharmony_ci .offset = 0x00200000, 7962306a36Sopenharmony_ci }, { 8062306a36Sopenharmony_ci .name = "RootFS2", 8162306a36Sopenharmony_ci .size = 0x00100000, 8262306a36Sopenharmony_ci .offset = 0x00600000, 8362306a36Sopenharmony_ci }, { 8462306a36Sopenharmony_ci .name = "U-Boot Config", 8562306a36Sopenharmony_ci .size = 0x00020000, 8662306a36Sopenharmony_ci .offset = 0x00760000, 8762306a36Sopenharmony_ci }, { 8862306a36Sopenharmony_ci .name = "NAS Config", 8962306a36Sopenharmony_ci .size = 0x00060000, 9062306a36Sopenharmony_ci .offset = 0x00700000, 9162306a36Sopenharmony_ci .mask_flags = MTD_WRITEABLE, 9262306a36Sopenharmony_ci }, 9362306a36Sopenharmony_ci}; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic struct physmap_flash_data qnap_ts409_nor_flash_data = { 9662306a36Sopenharmony_ci .width = 1, 9762306a36Sopenharmony_ci .parts = qnap_ts409_partitions, 9862306a36Sopenharmony_ci .nr_parts = ARRAY_SIZE(qnap_ts409_partitions) 9962306a36Sopenharmony_ci}; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic struct resource qnap_ts409_nor_flash_resource = { 10262306a36Sopenharmony_ci .flags = IORESOURCE_MEM, 10362306a36Sopenharmony_ci .start = QNAP_TS409_NOR_BOOT_BASE, 10462306a36Sopenharmony_ci .end = QNAP_TS409_NOR_BOOT_BASE + QNAP_TS409_NOR_BOOT_SIZE - 1, 10562306a36Sopenharmony_ci}; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic struct platform_device qnap_ts409_nor_flash = { 10862306a36Sopenharmony_ci .name = "physmap-flash", 10962306a36Sopenharmony_ci .id = 0, 11062306a36Sopenharmony_ci .dev = { .platform_data = &qnap_ts409_nor_flash_data, }, 11162306a36Sopenharmony_ci .num_resources = 1, 11262306a36Sopenharmony_ci .resource = &qnap_ts409_nor_flash_resource, 11362306a36Sopenharmony_ci}; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/***************************************************************************** 11662306a36Sopenharmony_ci * PCI 11762306a36Sopenharmony_ci ****************************************************************************/ 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic int __init qnap_ts409_pci_map_irq(const struct pci_dev *dev, u8 slot, 12062306a36Sopenharmony_ci u8 pin) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci int irq; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci /* 12562306a36Sopenharmony_ci * Check for devices with hard-wired IRQs. 12662306a36Sopenharmony_ci */ 12762306a36Sopenharmony_ci irq = orion5x_pci_map_irq(dev, slot, pin); 12862306a36Sopenharmony_ci if (irq != -1) 12962306a36Sopenharmony_ci return irq; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* 13262306a36Sopenharmony_ci * PCI isn't used on the TS-409 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci return -1; 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic struct hw_pci qnap_ts409_pci __initdata = { 13862306a36Sopenharmony_ci .nr_controllers = 2, 13962306a36Sopenharmony_ci .setup = orion5x_pci_sys_setup, 14062306a36Sopenharmony_ci .scan = orion5x_pci_sys_scan_bus, 14162306a36Sopenharmony_ci .map_irq = qnap_ts409_pci_map_irq, 14262306a36Sopenharmony_ci}; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic int __init qnap_ts409_pci_init(void) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci if (machine_is_ts409()) 14762306a36Sopenharmony_ci pci_common_init(&qnap_ts409_pci); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci return 0; 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cisubsys_initcall(qnap_ts409_pci_init); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci/***************************************************************************** 15562306a36Sopenharmony_ci * RTC S35390A on I2C bus 15662306a36Sopenharmony_ci ****************************************************************************/ 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci#define TS409_RTC_GPIO 10 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic struct i2c_board_info __initdata qnap_ts409_i2c_rtc = { 16162306a36Sopenharmony_ci I2C_BOARD_INFO("s35390a", 0x30), 16262306a36Sopenharmony_ci}; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci/***************************************************************************** 16562306a36Sopenharmony_ci * LEDs attached to GPIO 16662306a36Sopenharmony_ci ****************************************************************************/ 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic struct gpio_led ts409_led_pins[] = { 16962306a36Sopenharmony_ci { 17062306a36Sopenharmony_ci .name = "ts409:red:sata1", 17162306a36Sopenharmony_ci .gpio = 4, 17262306a36Sopenharmony_ci .active_low = 1, 17362306a36Sopenharmony_ci }, { 17462306a36Sopenharmony_ci .name = "ts409:red:sata2", 17562306a36Sopenharmony_ci .gpio = 5, 17662306a36Sopenharmony_ci .active_low = 1, 17762306a36Sopenharmony_ci }, { 17862306a36Sopenharmony_ci .name = "ts409:red:sata3", 17962306a36Sopenharmony_ci .gpio = 6, 18062306a36Sopenharmony_ci .active_low = 1, 18162306a36Sopenharmony_ci }, { 18262306a36Sopenharmony_ci .name = "ts409:red:sata4", 18362306a36Sopenharmony_ci .gpio = 7, 18462306a36Sopenharmony_ci .active_low = 1, 18562306a36Sopenharmony_ci }, 18662306a36Sopenharmony_ci}; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic struct gpio_led_platform_data ts409_led_data = { 18962306a36Sopenharmony_ci .leds = ts409_led_pins, 19062306a36Sopenharmony_ci .num_leds = ARRAY_SIZE(ts409_led_pins), 19162306a36Sopenharmony_ci}; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_cistatic struct platform_device ts409_leds = { 19462306a36Sopenharmony_ci .name = "leds-gpio", 19562306a36Sopenharmony_ci .id = -1, 19662306a36Sopenharmony_ci .dev = { 19762306a36Sopenharmony_ci .platform_data = &ts409_led_data, 19862306a36Sopenharmony_ci }, 19962306a36Sopenharmony_ci}; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci/**************************************************************************** 20262306a36Sopenharmony_ci * GPIO Attached Keys 20362306a36Sopenharmony_ci * Power button is attached to the PIC microcontroller 20462306a36Sopenharmony_ci ****************************************************************************/ 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci#define QNAP_TS409_GPIO_KEY_RESET 14 20762306a36Sopenharmony_ci#define QNAP_TS409_GPIO_KEY_MEDIA 15 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_cistatic struct gpio_keys_button qnap_ts409_buttons[] = { 21062306a36Sopenharmony_ci { 21162306a36Sopenharmony_ci .code = KEY_RESTART, 21262306a36Sopenharmony_ci .gpio = QNAP_TS409_GPIO_KEY_RESET, 21362306a36Sopenharmony_ci .desc = "Reset Button", 21462306a36Sopenharmony_ci .active_low = 1, 21562306a36Sopenharmony_ci }, { 21662306a36Sopenharmony_ci .code = KEY_COPY, 21762306a36Sopenharmony_ci .gpio = QNAP_TS409_GPIO_KEY_MEDIA, 21862306a36Sopenharmony_ci .desc = "USB Copy Button", 21962306a36Sopenharmony_ci .active_low = 1, 22062306a36Sopenharmony_ci }, 22162306a36Sopenharmony_ci}; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_cistatic struct gpio_keys_platform_data qnap_ts409_button_data = { 22462306a36Sopenharmony_ci .buttons = qnap_ts409_buttons, 22562306a36Sopenharmony_ci .nbuttons = ARRAY_SIZE(qnap_ts409_buttons), 22662306a36Sopenharmony_ci}; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistatic struct platform_device qnap_ts409_button_device = { 22962306a36Sopenharmony_ci .name = "gpio-keys", 23062306a36Sopenharmony_ci .id = -1, 23162306a36Sopenharmony_ci .num_resources = 0, 23262306a36Sopenharmony_ci .dev = { 23362306a36Sopenharmony_ci .platform_data = &qnap_ts409_button_data, 23462306a36Sopenharmony_ci }, 23562306a36Sopenharmony_ci}; 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci/***************************************************************************** 23862306a36Sopenharmony_ci * General Setup 23962306a36Sopenharmony_ci ****************************************************************************/ 24062306a36Sopenharmony_cistatic unsigned int ts409_mpp_modes[] __initdata = { 24162306a36Sopenharmony_ci MPP0_UNUSED, 24262306a36Sopenharmony_ci MPP1_UNUSED, 24362306a36Sopenharmony_ci MPP2_UNUSED, 24462306a36Sopenharmony_ci MPP3_UNUSED, 24562306a36Sopenharmony_ci MPP4_GPIO, /* HDD 1 status */ 24662306a36Sopenharmony_ci MPP5_GPIO, /* HDD 2 status */ 24762306a36Sopenharmony_ci MPP6_GPIO, /* HDD 3 status */ 24862306a36Sopenharmony_ci MPP7_GPIO, /* HDD 4 status */ 24962306a36Sopenharmony_ci MPP8_UNUSED, 25062306a36Sopenharmony_ci MPP9_UNUSED, 25162306a36Sopenharmony_ci MPP10_GPIO, /* RTC int */ 25262306a36Sopenharmony_ci MPP11_UNUSED, 25362306a36Sopenharmony_ci MPP12_UNUSED, 25462306a36Sopenharmony_ci MPP13_UNUSED, 25562306a36Sopenharmony_ci MPP14_GPIO, /* SW_RST */ 25662306a36Sopenharmony_ci MPP15_GPIO, /* USB copy button */ 25762306a36Sopenharmony_ci MPP16_UART, /* UART1 RXD */ 25862306a36Sopenharmony_ci MPP17_UART, /* UART1 TXD */ 25962306a36Sopenharmony_ci MPP18_UNUSED, 26062306a36Sopenharmony_ci MPP19_UNUSED, 26162306a36Sopenharmony_ci 0, 26262306a36Sopenharmony_ci}; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic void __init qnap_ts409_init(void) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci /* 26762306a36Sopenharmony_ci * Setup basic Orion functions. Need to be called early. 26862306a36Sopenharmony_ci */ 26962306a36Sopenharmony_ci orion5x_init(); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci orion5x_mpp_conf(ts409_mpp_modes); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci /* 27462306a36Sopenharmony_ci * Configure peripherals. 27562306a36Sopenharmony_ci */ 27662306a36Sopenharmony_ci mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET, 27762306a36Sopenharmony_ci ORION_MBUS_DEVBUS_BOOT_ATTR, 27862306a36Sopenharmony_ci QNAP_TS409_NOR_BOOT_BASE, 27962306a36Sopenharmony_ci QNAP_TS409_NOR_BOOT_SIZE); 28062306a36Sopenharmony_ci platform_device_register(&qnap_ts409_nor_flash); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci orion5x_ehci0_init(); 28362306a36Sopenharmony_ci qnap_tsx09_find_mac_addr(QNAP_TS409_NOR_BOOT_BASE + 28462306a36Sopenharmony_ci qnap_ts409_partitions[5].offset, 28562306a36Sopenharmony_ci qnap_ts409_partitions[5].size); 28662306a36Sopenharmony_ci orion5x_eth_init(&qnap_tsx09_eth_data); 28762306a36Sopenharmony_ci orion5x_i2c_init(); 28862306a36Sopenharmony_ci orion5x_uart0_init(); 28962306a36Sopenharmony_ci orion5x_uart1_init(); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci platform_device_register(&qnap_ts409_button_device); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci /* Get RTC IRQ and register the chip */ 29462306a36Sopenharmony_ci if (gpio_request(TS409_RTC_GPIO, "rtc") == 0) { 29562306a36Sopenharmony_ci if (gpio_direction_input(TS409_RTC_GPIO) == 0) 29662306a36Sopenharmony_ci qnap_ts409_i2c_rtc.irq = gpio_to_irq(TS409_RTC_GPIO); 29762306a36Sopenharmony_ci else 29862306a36Sopenharmony_ci gpio_free(TS409_RTC_GPIO); 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci if (qnap_ts409_i2c_rtc.irq == 0) 30162306a36Sopenharmony_ci pr_warn("qnap_ts409_init: failed to get RTC IRQ\n"); 30262306a36Sopenharmony_ci i2c_register_board_info(0, &qnap_ts409_i2c_rtc, 1); 30362306a36Sopenharmony_ci platform_device_register(&ts409_leds); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci /* register tsx09 specific power-off method */ 30662306a36Sopenharmony_ci pm_power_off = qnap_tsx09_power_off; 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ciMACHINE_START(TS409, "QNAP TS-409") 31062306a36Sopenharmony_ci /* Maintainer: Sylver Bruneau <sylver.bruneau@gmail.com> */ 31162306a36Sopenharmony_ci .atag_offset = 0x100, 31262306a36Sopenharmony_ci .nr_irqs = ORION5X_NR_IRQS, 31362306a36Sopenharmony_ci .init_machine = qnap_ts409_init, 31462306a36Sopenharmony_ci .map_io = orion5x_map_io, 31562306a36Sopenharmony_ci .init_early = orion5x_init_early, 31662306a36Sopenharmony_ci .init_irq = orion5x_init_irq, 31762306a36Sopenharmony_ci .init_time = orion5x_timer_init, 31862306a36Sopenharmony_ci .fixup = tag_fixup_mem32, 31962306a36Sopenharmony_ci .restart = orion5x_restart, 32062306a36Sopenharmony_ciMACHINE_END 321