From 2c3c1048746a4622d8c89a29670120dc8fab93c4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:49:45 +0200 Subject: Adding upstream version 6.1.76. Signed-off-by: Daniel Baumann --- arch/arm/mach-orion5x/Kconfig | 187 +++++++ arch/arm/mach-orion5x/Makefile | 26 + arch/arm/mach-orion5x/board-d2net.c | 106 ++++ arch/arm/mach-orion5x/board-dt.c | 80 +++ arch/arm/mach-orion5x/board-mss2.c | 86 +++ arch/arm/mach-orion5x/board-rd88f5182.c | 113 ++++ arch/arm/mach-orion5x/bridge-regs.h | 30 + arch/arm/mach-orion5x/common.c | 388 +++++++++++++ arch/arm/mach-orion5x/common.h | 94 ++++ arch/arm/mach-orion5x/db88f5281-setup.c | 376 +++++++++++++ arch/arm/mach-orion5x/dns323-setup.c | 724 +++++++++++++++++++++++++ arch/arm/mach-orion5x/irq.c | 51 ++ arch/arm/mach-orion5x/irqs.h | 55 ++ arch/arm/mach-orion5x/kurobox_pro-setup.c | 407 ++++++++++++++ arch/arm/mach-orion5x/ls_hgl-setup.c | 275 ++++++++++ arch/arm/mach-orion5x/mpp.c | 41 ++ arch/arm/mach-orion5x/mpp.h | 130 +++++ arch/arm/mach-orion5x/mv2120-setup.c | 243 +++++++++ arch/arm/mach-orion5x/net2big-setup.c | 431 +++++++++++++++ arch/arm/mach-orion5x/orion5x.h | 143 +++++ arch/arm/mach-orion5x/pci.c | 601 ++++++++++++++++++++ arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c | 172 ++++++ arch/arm/mach-orion5x/rd88f5181l-ge-setup.c | 183 +++++++ arch/arm/mach-orion5x/rd88f5182-setup.c | 288 ++++++++++ arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c | 120 ++++ arch/arm/mach-orion5x/terastation_pro2-setup.c | 366 +++++++++++++ arch/arm/mach-orion5x/ts209-setup.c | 331 +++++++++++ arch/arm/mach-orion5x/ts409-setup.c | 320 +++++++++++ arch/arm/mach-orion5x/ts78xx-fpga.h | 42 ++ arch/arm/mach-orion5x/ts78xx-setup.c | 574 ++++++++++++++++++++ arch/arm/mach-orion5x/tsx09-common.c | 129 +++++ arch/arm/mach-orion5x/tsx09-common.h | 21 + arch/arm/mach-orion5x/wnr854t-setup.c | 175 ++++++ arch/arm/mach-orion5x/wrt350n-v2-setup.c | 263 +++++++++ 34 files changed, 7571 insertions(+) create mode 100644 arch/arm/mach-orion5x/Kconfig create mode 100644 arch/arm/mach-orion5x/Makefile create mode 100644 arch/arm/mach-orion5x/board-d2net.c create mode 100644 arch/arm/mach-orion5x/board-dt.c create mode 100644 arch/arm/mach-orion5x/board-mss2.c create mode 100644 arch/arm/mach-orion5x/board-rd88f5182.c create mode 100644 arch/arm/mach-orion5x/bridge-regs.h create mode 100644 arch/arm/mach-orion5x/common.c create mode 100644 arch/arm/mach-orion5x/common.h create mode 100644 arch/arm/mach-orion5x/db88f5281-setup.c create mode 100644 arch/arm/mach-orion5x/dns323-setup.c create mode 100644 arch/arm/mach-orion5x/irq.c create mode 100644 arch/arm/mach-orion5x/irqs.h create mode 100644 arch/arm/mach-orion5x/kurobox_pro-setup.c create mode 100644 arch/arm/mach-orion5x/ls_hgl-setup.c create mode 100644 arch/arm/mach-orion5x/mpp.c create mode 100644 arch/arm/mach-orion5x/mpp.h create mode 100644 arch/arm/mach-orion5x/mv2120-setup.c create mode 100644 arch/arm/mach-orion5x/net2big-setup.c create mode 100644 arch/arm/mach-orion5x/orion5x.h create mode 100644 arch/arm/mach-orion5x/pci.c create mode 100644 arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c create mode 100644 arch/arm/mach-orion5x/rd88f5181l-ge-setup.c create mode 100644 arch/arm/mach-orion5x/rd88f5182-setup.c create mode 100644 arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c create mode 100644 arch/arm/mach-orion5x/terastation_pro2-setup.c create mode 100644 arch/arm/mach-orion5x/ts209-setup.c create mode 100644 arch/arm/mach-orion5x/ts409-setup.c create mode 100644 arch/arm/mach-orion5x/ts78xx-fpga.h create mode 100644 arch/arm/mach-orion5x/ts78xx-setup.c create mode 100644 arch/arm/mach-orion5x/tsx09-common.c create mode 100644 arch/arm/mach-orion5x/tsx09-common.h create mode 100644 arch/arm/mach-orion5x/wnr854t-setup.c create mode 100644 arch/arm/mach-orion5x/wrt350n-v2-setup.c (limited to 'arch/arm/mach-orion5x') diff --git a/arch/arm/mach-orion5x/Kconfig b/arch/arm/mach-orion5x/Kconfig new file mode 100644 index 000000000..0044b2823 --- /dev/null +++ b/arch/arm/mach-orion5x/Kconfig @@ -0,0 +1,187 @@ +# SPDX-License-Identifier: GPL-2.0-only +menuconfig ARCH_ORION5X + bool "Marvell Orion" + depends on ARCH_MULTI_V5 + depends on CPU_LITTLE_ENDIAN + select CPU_FEROCEON + select GPIOLIB + select MVEBU_MBUS + select FORCE_PCI + select PCI_QUIRKS + select PHYLIB if NETDEVICES + select PLAT_ORION_LEGACY + help + Support for the following Marvell Orion 5x series SoCs: + Orion-1 (5181), Orion-VoIP (5181L), Orion-NAS (5182), + Orion-2 (5281), Orion-1-90 (6183). + +if ARCH_ORION5X + +config ARCH_ORION5X_DT + bool "Marvell Orion5x Flattened Device Tree" + select ORION_CLK + select ORION_IRQCHIP + select ORION_TIMER + select PINCTRL + select PINCTRL_ORION + help + Say 'Y' here if you want your kernel to support the + Marvell Orion5x using flattened device tree. + +config MACH_DB88F5281 + bool "Marvell Orion-2 Development Board" + select I2C_BOARDINFO if I2C + depends on ATAGS && UNUSED_BOARD_FILES + help + Say 'Y' here if you want your kernel to support the + Marvell Orion-2 (88F5281) Development Board + +config MACH_RD88F5182 + bool "Marvell Orion-NAS Reference Design" + select I2C_BOARDINFO if I2C + depends on ATAGS && UNUSED_BOARD_FILES + help + Say 'Y' here if you want your kernel to support the + Marvell Orion-NAS (88F5182) RD2 + +config MACH_RD88F5182_DT + bool "Marvell Orion-NAS Reference Design (Flattened Device Tree)" + select ARCH_ORION5X_DT + select I2C_BOARDINFO if I2C + help + Say 'Y' here if you want your kernel to support the Marvell + Orion-NAS (88F5182) RD2, Flattened Device Tree. + +config MACH_KUROBOX_PRO + bool "KuroBox Pro" + select I2C_BOARDINFO if I2C + depends on ATAGS + help + Say 'Y' here if you want your kernel to support the + KuroBox Pro platform. + +config MACH_DNS323 + bool "D-Link DNS-323" + select I2C_BOARDINFO if I2C + depends on ATAGS + help + Say 'Y' here if you want your kernel to support the + D-Link DNS-323 platform. + +config MACH_TS209 + bool "QNAP TS-109/TS-209" + depends on ATAGS + help + Say 'Y' here if you want your kernel to support the + QNAP TS-109/TS-209 platform. + +config MACH_TERASTATION_PRO2 + bool "Buffalo Terastation Pro II/Live" + depends on ATAGS + help + Say 'Y' here if you want your kernel to support the + Buffalo Terastation Pro II/Live platform. + +config MACH_LINKSTATION_PRO + bool "Buffalo Linkstation Pro/Live" + depends on ATAGS + select I2C_BOARDINFO if I2C + help + Say 'Y' here if you want your kernel to support the + Buffalo Linkstation Pro/Live platform. Both v1 and + v2 devices are supported. + +config MACH_LINKSTATION_MINI + bool "Buffalo Linkstation Mini (Flattened Device Tree)" + select ARCH_ORION5X_DT + help + Say 'Y' here if you want your kernel to support the + Buffalo Linkstation Mini (LS-WSGL) platform. + +config MACH_LINKSTATION_LS_HGL + bool "Buffalo Linkstation LS-HGL" + depends on ATAGS && UNUSED_BOARD_FILES + select I2C_BOARDINFO if I2C + help + Say 'Y' here if you want your kernel to support the + Buffalo Linkstation LS-HGL platform. + +config MACH_TS409 + bool "QNAP TS-409" + depends on ATAGS + help + Say 'Y' here if you want your kernel to support the + QNAP TS-409 platform. + +config MACH_WRT350N_V2 + bool "Linksys WRT350N v2" + depends on ATAGS && UNUSED_BOARD_FILES + help + Say 'Y' here if you want your kernel to support the + Linksys WRT350N v2 platform. + +config MACH_TS78XX + bool "Technologic Systems TS-78xx" + depends on ATAGS + help + Say 'Y' here if you want your kernel to support the + Technologic Systems TS-78xx platform. + +config MACH_MV2120 + bool "HP Media Vault mv2120" + depends on ATAGS + help + Say 'Y' here if you want your kernel to support the + HP Media Vault mv2120 or mv5100. + +config MACH_D2NET_DT + bool "LaCie d2 Network / Big Disk Network (Flattened Device Tree)" + select ARCH_ORION5X_DT + help + Say 'Y' here if you want your kernel to support the + LaCie d2 Network NAS. + +config MACH_NET2BIG + bool "LaCie 2Big Network" + depends on ATAGS + select I2C_BOARDINFO if I2C + help + Say 'Y' here if you want your kernel to support the + LaCie 2Big Network NAS. + +config MACH_MSS2_DT + bool "Maxtor Shared Storage II (Flattened Device Tree)" + select ARCH_ORION5X_DT + help + Say 'Y' here if you want your kernel to support the + Maxtor Shared Storage II platform. + +config MACH_WNR854T + bool "Netgear WNR854T" + depends on ATAGS && UNUSED_BOARD_FILES + help + Say 'Y' here if you want your kernel to support the + Netgear WNR854T platform. + +config MACH_RD88F5181L_GE + bool "Marvell Orion-VoIP GE Reference Design" + depends on ATAGS && UNUSED_BOARD_FILES + help + Say 'Y' here if you want your kernel to support the + Marvell Orion-VoIP GE (88F5181L) RD. + +config MACH_RD88F5181L_FXO + bool "Marvell Orion-VoIP FXO Reference Design" + depends on ATAGS && UNUSED_BOARD_FILES + help + Say 'Y' here if you want your kernel to support the + Marvell Orion-VoIP FXO (88F5181L) RD. + +config MACH_RD88F6183AP_GE + bool "Marvell Orion-1-90 AP GE Reference Design" + depends on ATAGS && UNUSED_BOARD_FILES + help + Say 'Y' here if you want your kernel to support the + Marvell Orion-1-90 (88F6183) AP GE RD. + +endif diff --git a/arch/arm/mach-orion5x/Makefile b/arch/arm/mach-orion5x/Makefile new file mode 100644 index 000000000..572c3520f --- /dev/null +++ b/arch/arm/mach-orion5x/Makefile @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: GPL-2.0 +ccflags-y := -I$(srctree)/arch/arm/plat-orion/include + +obj-y += common.o pci.o irq.o mpp.o +obj-$(CONFIG_MACH_DB88F5281) += db88f5281-setup.o +obj-$(CONFIG_MACH_RD88F5182) += rd88f5182-setup.o +obj-$(CONFIG_MACH_KUROBOX_PRO) += kurobox_pro-setup.o +obj-$(CONFIG_MACH_TERASTATION_PRO2) += terastation_pro2-setup.o +obj-$(CONFIG_MACH_LINKSTATION_PRO) += kurobox_pro-setup.o +obj-$(CONFIG_MACH_LINKSTATION_LS_HGL) += ls_hgl-setup.o +obj-$(CONFIG_MACH_DNS323) += dns323-setup.o +obj-$(CONFIG_MACH_TS209) += ts209-setup.o tsx09-common.o +obj-$(CONFIG_MACH_TS409) += ts409-setup.o tsx09-common.o +obj-$(CONFIG_MACH_WRT350N_V2) += wrt350n-v2-setup.o +obj-$(CONFIG_MACH_TS78XX) += ts78xx-setup.o +obj-$(CONFIG_MACH_MV2120) += mv2120-setup.o +obj-$(CONFIG_MACH_NET2BIG) += net2big-setup.o +obj-$(CONFIG_MACH_WNR854T) += wnr854t-setup.o +obj-$(CONFIG_MACH_RD88F5181L_GE) += rd88f5181l-ge-setup.o +obj-$(CONFIG_MACH_RD88F5181L_FXO) += rd88f5181l-fxo-setup.o +obj-$(CONFIG_MACH_RD88F6183AP_GE) += rd88f6183ap-ge-setup.o + +obj-$(CONFIG_ARCH_ORION5X_DT) += board-dt.o +obj-$(CONFIG_MACH_D2NET_DT) += board-d2net.o +obj-$(CONFIG_MACH_MSS2_DT) += board-mss2.o +obj-$(CONFIG_MACH_RD88F5182_DT) += board-rd88f5182.o diff --git a/arch/arm/mach-orion5x/board-d2net.c b/arch/arm/mach-orion5x/board-d2net.c new file mode 100644 index 000000000..0297e302d --- /dev/null +++ b/arch/arm/mach-orion5x/board-d2net.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * arch/arm/mach-orion5x/board-d2net.c + * + * LaCie d2Network and Big Disk Network NAS setup + * + * Copyright (C) 2009 Simon Guinot + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "orion5x.h" + +/***************************************************************************** + * LaCie d2 Network Info + ****************************************************************************/ + +/***************************************************************************** + * GPIO LED's + ****************************************************************************/ + +/* + * The blue front LED is wired to the CPLD and can blink in relation with the + * SATA activity. + * + * The following array detail the different LED registers and the combination + * of their possible values: + * + * led_off | blink_ctrl | SATA active | LED state + * | | | + * 1 | x | x | off + * 0 | 0 | 0 | off + * 0 | 1 | 0 | blink (rate 300ms) + * 0 | x | 1 | on + * + * Notes: The blue and the red front LED's can't be on at the same time. + * Red LED have priority. + */ + +#define D2NET_GPIO_RED_LED 6 +#define D2NET_GPIO_BLUE_LED_BLINK_CTRL 16 +#define D2NET_GPIO_BLUE_LED_OFF 23 + +static struct gpio_led d2net_leds[] = { + { + .name = "d2net:blue:sata", + .default_trigger = "default-on", + .gpio = D2NET_GPIO_BLUE_LED_OFF, + .active_low = 1, + }, + { + .name = "d2net:red:fail", + .gpio = D2NET_GPIO_RED_LED, + }, +}; + +static struct gpio_led_platform_data d2net_led_data = { + .num_leds = ARRAY_SIZE(d2net_leds), + .leds = d2net_leds, +}; + +static struct platform_device d2net_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &d2net_led_data, + }, +}; + +static void __init d2net_gpio_leds_init(void) +{ + int err; + + /* Configure register blink_ctrl to allow SATA activity LED blinking. */ + err = gpio_request(D2NET_GPIO_BLUE_LED_BLINK_CTRL, "blue LED blink"); + if (err == 0) { + err = gpio_direction_output(D2NET_GPIO_BLUE_LED_BLINK_CTRL, 1); + if (err) + gpio_free(D2NET_GPIO_BLUE_LED_BLINK_CTRL); + } + if (err) + pr_err("d2net: failed to configure blue LED blink GPIO\n"); + + platform_device_register(&d2net_gpio_leds); +} + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +void __init d2net_init(void) +{ + d2net_gpio_leds_init(); + + pr_notice("d2net: Flash write are not yet supported.\n"); +} diff --git a/arch/arm/mach-orion5x/board-dt.c b/arch/arm/mach-orion5x/board-dt.c new file mode 100644 index 000000000..be47492c6 --- /dev/null +++ b/arch/arm/mach-orion5x/board-dt.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2012 (C), Thomas Petazzoni + * + * arch/arm/mach-orion5x/board-dt.c + * + * Flattened Device Tree board initialization + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "orion5x.h" +#include "bridge-regs.h" +#include "common.h" + +static struct of_dev_auxdata orion5x_auxdata_lookup[] __initdata = { + OF_DEV_AUXDATA("marvell,orion-spi", 0xf1010600, "orion_spi.0", NULL), + OF_DEV_AUXDATA("marvell,mv64xxx-i2c", 0xf1011000, "mv64xxx_i2c.0", + NULL), + OF_DEV_AUXDATA("marvell,orion-wdt", 0xf1020300, "orion_wdt", NULL), + OF_DEV_AUXDATA("marvell,orion-sata", 0xf1080000, "sata_mv.0", NULL), + OF_DEV_AUXDATA("marvell,orion-crypto", 0xf1090000, "mv_crypto", NULL), + {}, +}; + +static void __init orion5x_dt_init(void) +{ + char *dev_name; + u32 dev, rev; + + orion5x_id(&dev, &rev, &dev_name); + printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, orion5x_tclk); + + BUG_ON(mvebu_mbus_dt_init(false)); + + /* + * Setup Orion address map + */ + orion5x_setup_wins(); + + /* + * Don't issue "Wait for Interrupt" instruction if we are + * running on D0 5281 silicon. + */ + if (dev == MV88F5281_DEV_ID && rev == MV88F5281_REV_D0) { + printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n"); + cpu_idle_poll_ctrl(true); + } + + if (of_machine_is_compatible("maxtor,shared-storage-2")) + mss2_init(); + + if (of_machine_is_compatible("lacie,d2-network")) + d2net_init(); + + of_platform_default_populate(NULL, orion5x_auxdata_lookup, NULL); +} + +static const char *orion5x_dt_compat[] = { + "marvell,orion5x", + NULL, +}; + +DT_MACHINE_START(ORION5X_DT, "Marvell Orion5x (Flattened Device Tree)") + /* Maintainer: Thomas Petazzoni */ + .map_io = orion5x_map_io, + .init_machine = orion5x_dt_init, + .restart = orion5x_restart, + .dt_compat = orion5x_dt_compat, +MACHINE_END diff --git a/arch/arm/mach-orion5x/board-mss2.c b/arch/arm/mach-orion5x/board-mss2.c new file mode 100644 index 000000000..b0f16d223 --- /dev/null +++ b/arch/arm/mach-orion5x/board-mss2.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Maxtor Shared Storage II Board Setup + * + * Maintainer: Sylver Bruneau + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "orion5x.h" +#include "bridge-regs.h" +#include "common.h" + +/***************************************************************************** + * Maxtor Shared Storage II Info + ****************************************************************************/ + +/**************************************************************************** + * PCI setup + ****************************************************************************/ +static int __init mss2_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + int irq; + + /* + * Check for devices with hard-wired IRQs. + */ + irq = orion5x_pci_map_irq(dev, slot, pin); + if (irq != -1) + return irq; + + return -1; +} + +static struct hw_pci mss2_pci __initdata = { + .nr_controllers = 2, + .setup = orion5x_pci_sys_setup, + .scan = orion5x_pci_sys_scan_bus, + .map_irq = mss2_pci_map_irq, +}; + +static int __init mss2_pci_init(void) +{ + if (machine_is_mss2()) + pci_common_init(&mss2_pci); + + return 0; +} +subsys_initcall(mss2_pci_init); + +/***************************************************************************** + * MSS2 power off method + ****************************************************************************/ +/* + * On the Maxtor Shared Storage II, the shutdown process is the following : + * - Userland modifies U-boot env to tell U-boot to go idle at next boot + * - The board reboots + * - U-boot starts and go into an idle mode until the user press "power" + */ +static void mss2_power_off(void) +{ + u32 reg; + + /* + * Enable and issue soft reset + */ + reg = readl(RSTOUTn_MASK); + reg |= 1 << 2; + writel(reg, RSTOUTn_MASK); + + reg = readl(CPU_SOFT_RESET); + reg |= 1; + writel(reg, CPU_SOFT_RESET); +} + +void __init mss2_init(void) +{ + /* register mss2 specific power-off method */ + pm_power_off = mss2_power_off; +} diff --git a/arch/arm/mach-orion5x/board-rd88f5182.c b/arch/arm/mach-orion5x/board-rd88f5182.c new file mode 100644 index 000000000..596601367 --- /dev/null +++ b/arch/arm/mach-orion5x/board-rd88f5182.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * arch/arm/mach-orion5x/rd88f5182-setup.c + * + * Marvell Orion-NAS Reference Design Setup + * + * Maintainer: Ronen Shitrit + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "orion5x.h" + +/***************************************************************************** + * RD-88F5182 Info + ****************************************************************************/ + +/* + * PCI + */ + +#define RD88F5182_PCI_SLOT0_OFFS 7 +#define RD88F5182_PCI_SLOT0_IRQ_A_PIN 7 +#define RD88F5182_PCI_SLOT0_IRQ_B_PIN 6 + +/***************************************************************************** + * PCI + ****************************************************************************/ + +static void __init rd88f5182_pci_preinit(void) +{ + int pin; + + /* + * Configure PCI GPIO IRQ pins + */ + pin = RD88F5182_PCI_SLOT0_IRQ_A_PIN; + if (gpio_request(pin, "PCI IntA") == 0) { + if (gpio_direction_input(pin) == 0) { + irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW); + } else { + printk(KERN_ERR "rd88f5182_pci_preinit failed to " + "set_irq_type pin %d\n", pin); + gpio_free(pin); + } + } else { + printk(KERN_ERR "rd88f5182_pci_preinit failed to request gpio %d\n", pin); + } + + pin = RD88F5182_PCI_SLOT0_IRQ_B_PIN; + if (gpio_request(pin, "PCI IntB") == 0) { + if (gpio_direction_input(pin) == 0) { + irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW); + } else { + printk(KERN_ERR "rd88f5182_pci_preinit failed to " + "set_irq_type pin %d\n", pin); + gpio_free(pin); + } + } else { + printk(KERN_ERR "rd88f5182_pci_preinit failed to gpio_request %d\n", pin); + } +} + +static int __init rd88f5182_pci_map_irq(const struct pci_dev *dev, u8 slot, + u8 pin) +{ + int irq; + + /* + * Check for devices with hard-wired IRQs. + */ + irq = orion5x_pci_map_irq(dev, slot, pin); + if (irq != -1) + return irq; + + /* + * PCI IRQs are connected via GPIOs + */ + switch (slot - RD88F5182_PCI_SLOT0_OFFS) { + case 0: + if (pin == 1) + return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_A_PIN); + else + return gpio_to_irq(RD88F5182_PCI_SLOT0_IRQ_B_PIN); + default: + return -1; + } +} + +static struct hw_pci rd88f5182_pci __initdata = { + .nr_controllers = 2, + .preinit = rd88f5182_pci_preinit, + .setup = orion5x_pci_sys_setup, + .scan = orion5x_pci_sys_scan_bus, + .map_irq = rd88f5182_pci_map_irq, +}; + +static int __init rd88f5182_pci_init(void) +{ + if (of_machine_is_compatible("marvell,rd-88f5182-nas")) + pci_common_init(&rd88f5182_pci); + + return 0; +} + +subsys_initcall(rd88f5182_pci_init); diff --git a/arch/arm/mach-orion5x/bridge-regs.h b/arch/arm/mach-orion5x/bridge-regs.h new file mode 100644 index 000000000..fe85bc5b1 --- /dev/null +++ b/arch/arm/mach-orion5x/bridge-regs.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Orion CPU Bridge Registers */ + +#ifndef __ASM_ARCH_BRIDGE_REGS_H +#define __ASM_ARCH_BRIDGE_REGS_H + +#include "orion5x.h" + +#define CPU_CONF (ORION5X_BRIDGE_VIRT_BASE + 0x100) + +#define CPU_CTRL (ORION5X_BRIDGE_VIRT_BASE + 0x104) + +#define RSTOUTn_MASK (ORION5X_BRIDGE_VIRT_BASE + 0x108) +#define RSTOUTn_MASK_PHYS (ORION5X_BRIDGE_PHYS_BASE + 0x108) + +#define CPU_SOFT_RESET (ORION5X_BRIDGE_VIRT_BASE + 0x10c) + +#define BRIDGE_CAUSE (ORION5X_BRIDGE_VIRT_BASE + 0x110) + +#define POWER_MNG_CTRL_REG (ORION5X_BRIDGE_VIRT_BASE + 0x11C) + +#define BRIDGE_INT_TIMER1_CLR (~0x0004) + +#define MAIN_IRQ_CAUSE (ORION5X_BRIDGE_VIRT_BASE + 0x200) + +#define MAIN_IRQ_MASK (ORION5X_BRIDGE_VIRT_BASE + 0x204) + +#define TIMER_VIRT_BASE (ORION5X_BRIDGE_VIRT_BASE + 0x300) +#define TIMER_PHYS_BASE (ORION5X_BRIDGE_PHYS_BASE + 0x300) +#endif diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c new file mode 100644 index 000000000..2e711b725 --- /dev/null +++ b/arch/arm/mach-orion5x/common.c @@ -0,0 +1,388 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * arch/arm/mach-orion5x/common.c + * + * Core functions for Marvell Orion 5x SoCs + * + * Maintainer: Tzachi Perelstein + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bridge-regs.h" +#include "common.h" +#include "orion5x.h" + +/***************************************************************************** + * I/O Address Mapping + ****************************************************************************/ +static struct map_desc orion5x_io_desc[] __initdata = { + { + .virtual = (unsigned long) ORION5X_REGS_VIRT_BASE, + .pfn = __phys_to_pfn(ORION5X_REGS_PHYS_BASE), + .length = ORION5X_REGS_SIZE, + .type = MT_DEVICE, + }, { + .virtual = (unsigned long) ORION5X_PCIE_WA_VIRT_BASE, + .pfn = __phys_to_pfn(ORION5X_PCIE_WA_PHYS_BASE), + .length = ORION5X_PCIE_WA_SIZE, + .type = MT_DEVICE, + }, +}; + +void __init orion5x_map_io(void) +{ + iotable_init(orion5x_io_desc, ARRAY_SIZE(orion5x_io_desc)); +} + + +/***************************************************************************** + * CLK tree + ****************************************************************************/ +static struct clk *tclk; + +void __init clk_init(void) +{ + tclk = clk_register_fixed_rate(NULL, "tclk", NULL, 0, orion5x_tclk); + + orion_clkdev_init(tclk); +} + +/***************************************************************************** + * EHCI0 + ****************************************************************************/ +void __init orion5x_ehci0_init(void) +{ + orion_ehci_init(ORION5X_USB0_PHYS_BASE, IRQ_ORION5X_USB0_CTRL, + EHCI_PHY_ORION); +} + + +/***************************************************************************** + * EHCI1 + ****************************************************************************/ +void __init orion5x_ehci1_init(void) +{ + orion_ehci_1_init(ORION5X_USB1_PHYS_BASE, IRQ_ORION5X_USB1_CTRL); +} + + +/***************************************************************************** + * GE00 + ****************************************************************************/ +void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data) +{ + orion_ge00_init(eth_data, + ORION5X_ETH_PHYS_BASE, IRQ_ORION5X_ETH_SUM, + IRQ_ORION5X_ETH_ERR, + MV643XX_TX_CSUM_DEFAULT_LIMIT); +} + + +/***************************************************************************** + * Ethernet switch + ****************************************************************************/ +void __init orion5x_eth_switch_init(struct dsa_chip_data *d) +{ + orion_ge00_switch_init(d); +} + + +/***************************************************************************** + * I2C + ****************************************************************************/ +void __init orion5x_i2c_init(void) +{ + orion_i2c_init(I2C_PHYS_BASE, IRQ_ORION5X_I2C, 8); + +} + + +/***************************************************************************** + * SATA + ****************************************************************************/ +void __init orion5x_sata_init(struct mv_sata_platform_data *sata_data) +{ + orion_sata_init(sata_data, ORION5X_SATA_PHYS_BASE, IRQ_ORION5X_SATA); +} + + +/***************************************************************************** + * SPI + ****************************************************************************/ +void __init orion5x_spi_init(void) +{ + orion_spi_init(SPI_PHYS_BASE); +} + + +/***************************************************************************** + * UART0 + ****************************************************************************/ +void __init orion5x_uart0_init(void) +{ + orion_uart0_init(UART0_VIRT_BASE, UART0_PHYS_BASE, + IRQ_ORION5X_UART0, tclk); +} + +/***************************************************************************** + * UART1 + ****************************************************************************/ +void __init orion5x_uart1_init(void) +{ + orion_uart1_init(UART1_VIRT_BASE, UART1_PHYS_BASE, + IRQ_ORION5X_UART1, tclk); +} + +/***************************************************************************** + * XOR engine + ****************************************************************************/ +void __init orion5x_xor_init(void) +{ + orion_xor0_init(ORION5X_XOR_PHYS_BASE, + ORION5X_XOR_PHYS_BASE + 0x200, + IRQ_ORION5X_XOR0, IRQ_ORION5X_XOR1); +} + +/***************************************************************************** + * Cryptographic Engines and Security Accelerator (CESA) + ****************************************************************************/ +static void __init orion5x_crypto_init(void) +{ + mvebu_mbus_add_window_by_id(ORION_MBUS_SRAM_TARGET, + ORION_MBUS_SRAM_ATTR, + ORION5X_SRAM_PHYS_BASE, + ORION5X_SRAM_SIZE); + orion_crypto_init(ORION5X_CRYPTO_PHYS_BASE, ORION5X_SRAM_PHYS_BASE, + SZ_8K, IRQ_ORION5X_CESA); +} + +/***************************************************************************** + * Watchdog + ****************************************************************************/ +static struct resource orion_wdt_resource[] = { + DEFINE_RES_MEM(TIMER_PHYS_BASE, 0x04), + DEFINE_RES_MEM(RSTOUTn_MASK_PHYS, 0x04), +}; + +static struct platform_device orion_wdt_device = { + .name = "orion_wdt", + .id = -1, + .num_resources = ARRAY_SIZE(orion_wdt_resource), + .resource = orion_wdt_resource, +}; + +static void __init orion5x_wdt_init(void) +{ + platform_device_register(&orion_wdt_device); +} + + +/***************************************************************************** + * Time handling + ****************************************************************************/ +void __init orion5x_init_early(void) +{ + u32 rev, dev; + const char *mbus_soc_name; + + orion_time_set_base(TIMER_VIRT_BASE); + + /* Initialize the MBUS driver */ + orion5x_pcie_id(&dev, &rev); + if (dev == MV88F5281_DEV_ID) + mbus_soc_name = "marvell,orion5x-88f5281-mbus"; + else if (dev == MV88F5182_DEV_ID) + mbus_soc_name = "marvell,orion5x-88f5182-mbus"; + else if (dev == MV88F5181_DEV_ID) + mbus_soc_name = "marvell,orion5x-88f5181-mbus"; + else if (dev == MV88F6183_DEV_ID) + mbus_soc_name = "marvell,orion5x-88f6183-mbus"; + else + mbus_soc_name = NULL; + mvebu_mbus_init(mbus_soc_name, ORION5X_BRIDGE_WINS_BASE, + ORION5X_BRIDGE_WINS_SZ, + ORION5X_DDR_WINS_BASE, ORION5X_DDR_WINS_SZ); +} + +void orion5x_setup_wins(void) +{ + /* + * The PCIe windows will no longer be statically allocated + * here once Orion5x is migrated to the pci-mvebu driver. + */ + mvebu_mbus_add_window_remap_by_id(ORION_MBUS_PCIE_IO_TARGET, + ORION_MBUS_PCIE_IO_ATTR, + ORION5X_PCIE_IO_PHYS_BASE, + ORION5X_PCIE_IO_SIZE, + ORION5X_PCIE_IO_BUS_BASE); + mvebu_mbus_add_window_by_id(ORION_MBUS_PCIE_MEM_TARGET, + ORION_MBUS_PCIE_MEM_ATTR, + ORION5X_PCIE_MEM_PHYS_BASE, + ORION5X_PCIE_MEM_SIZE); + mvebu_mbus_add_window_remap_by_id(ORION_MBUS_PCI_IO_TARGET, + ORION_MBUS_PCI_IO_ATTR, + ORION5X_PCI_IO_PHYS_BASE, + ORION5X_PCI_IO_SIZE, + ORION5X_PCI_IO_BUS_BASE); + mvebu_mbus_add_window_by_id(ORION_MBUS_PCI_MEM_TARGET, + ORION_MBUS_PCI_MEM_ATTR, + ORION5X_PCI_MEM_PHYS_BASE, + ORION5X_PCI_MEM_SIZE); +} + +int orion5x_tclk; + +static int __init orion5x_find_tclk(void) +{ + u32 dev, rev; + + orion5x_pcie_id(&dev, &rev); + if (dev == MV88F6183_DEV_ID && + (readl(MPP_RESET_SAMPLE) & 0x00000200) == 0) + return 133333333; + + return 166666667; +} + +void __init orion5x_timer_init(void) +{ + orion5x_tclk = orion5x_find_tclk(); + + orion_time_init(ORION5X_BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR, + IRQ_ORION5X_BRIDGE, orion5x_tclk); +} + + +/***************************************************************************** + * General + ****************************************************************************/ +/* + * Identify device ID and rev from PCIe configuration header space '0'. + */ +void __init orion5x_id(u32 *dev, u32 *rev, char **dev_name) +{ + orion5x_pcie_id(dev, rev); + + if (*dev == MV88F5281_DEV_ID) { + if (*rev == MV88F5281_REV_D2) { + *dev_name = "MV88F5281-D2"; + } else if (*rev == MV88F5281_REV_D1) { + *dev_name = "MV88F5281-D1"; + } else if (*rev == MV88F5281_REV_D0) { + *dev_name = "MV88F5281-D0"; + } else { + *dev_name = "MV88F5281-Rev-Unsupported"; + } + } else if (*dev == MV88F5182_DEV_ID) { + if (*rev == MV88F5182_REV_A2) { + *dev_name = "MV88F5182-A2"; + } else { + *dev_name = "MV88F5182-Rev-Unsupported"; + } + } else if (*dev == MV88F5181_DEV_ID) { + if (*rev == MV88F5181_REV_B1) { + *dev_name = "MV88F5181-Rev-B1"; + } else if (*rev == MV88F5181L_REV_A1) { + *dev_name = "MV88F5181L-Rev-A1"; + } else { + *dev_name = "MV88F5181(L)-Rev-Unsupported"; + } + } else if (*dev == MV88F6183_DEV_ID) { + if (*rev == MV88F6183_REV_B0) { + *dev_name = "MV88F6183-Rev-B0"; + } else { + *dev_name = "MV88F6183-Rev-Unsupported"; + } + } else { + *dev_name = "Device-Unknown"; + } +} + +void __init orion5x_init(void) +{ + char *dev_name; + u32 dev, rev; + + orion5x_id(&dev, &rev, &dev_name); + printk(KERN_INFO "Orion ID: %s. TCLK=%d.\n", dev_name, orion5x_tclk); + + /* + * Setup Orion address map + */ + orion5x_setup_wins(); + + /* Setup root of clk tree */ + clk_init(); + + /* + * Don't issue "Wait for Interrupt" instruction if we are + * running on D0 5281 silicon. + */ + if (dev == MV88F5281_DEV_ID && rev == MV88F5281_REV_D0) { + printk(KERN_INFO "Orion: Applying 5281 D0 WFI workaround.\n"); + cpu_idle_poll_ctrl(true); + } + + /* + * The 5082/5181l/5182/6082/6082l/6183 have crypto + * while 5180n/5181/5281 don't have crypto. + */ + if ((dev == MV88F5181_DEV_ID && rev >= MV88F5181L_REV_A0) || + dev == MV88F5182_DEV_ID || dev == MV88F6183_DEV_ID) + orion5x_crypto_init(); + + /* + * Register watchdog driver + */ + orion5x_wdt_init(); +} + +void orion5x_restart(enum reboot_mode mode, const char *cmd) +{ + /* + * Enable and issue soft reset + */ + orion5x_setbits(RSTOUTn_MASK, (1 << 2)); + orion5x_setbits(CPU_SOFT_RESET, 1); + mdelay(200); + orion5x_clrbits(CPU_SOFT_RESET, 1); +} + +/* + * Many orion-based systems have buggy bootloader implementations. + * This is a common fixup for bogus memory tags. + */ +void __init tag_fixup_mem32(struct tag *t, char **from) +{ + for (; t->hdr.size; t = tag_next(t)) + if (t->hdr.tag == ATAG_MEM && + (!t->u.mem.size || t->u.mem.size & ~PAGE_MASK || + t->u.mem.start & ~PAGE_MASK)) { + printk(KERN_WARNING + "Clearing invalid memory bank %dKB@0x%08x\n", + t->u.mem.size / 1024, t->u.mem.start); + t->hdr.tag = 0; + } +} diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h new file mode 100644 index 000000000..b9cfdb456 --- /dev/null +++ b/arch/arm/mach-orion5x/common.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ARCH_ORION5X_COMMON_H +#define __ARCH_ORION5X_COMMON_H + +#include + +struct dsa_chip_data; +struct mv643xx_eth_platform_data; +struct mv_sata_platform_data; + +#define ORION_MBUS_PCIE_MEM_TARGET 0x04 +#define ORION_MBUS_PCIE_MEM_ATTR 0x59 +#define ORION_MBUS_PCIE_IO_TARGET 0x04 +#define ORION_MBUS_PCIE_IO_ATTR 0x51 +#define ORION_MBUS_PCIE_WA_TARGET 0x04 +#define ORION_MBUS_PCIE_WA_ATTR 0x79 +#define ORION_MBUS_PCI_MEM_TARGET 0x03 +#define ORION_MBUS_PCI_MEM_ATTR 0x59 +#define ORION_MBUS_PCI_IO_TARGET 0x03 +#define ORION_MBUS_PCI_IO_ATTR 0x51 +#define ORION_MBUS_DEVBUS_BOOT_TARGET 0x01 +#define ORION_MBUS_DEVBUS_BOOT_ATTR 0x0f +#define ORION_MBUS_DEVBUS_TARGET(cs) 0x01 +#define ORION_MBUS_DEVBUS_ATTR(cs) (~(1 << cs)) +#define ORION_MBUS_SRAM_TARGET 0x09 +#define ORION_MBUS_SRAM_ATTR 0x00 + +/* + * Basic Orion init functions used early by machine-setup. + */ +void orion5x_map_io(void); +void orion5x_init_early(void); +void orion5x_init_irq(void); +void orion5x_init(void); +void orion5x_id(u32 *dev, u32 *rev, char **dev_name); +void clk_init(void); +extern int orion5x_tclk; +extern void orion5x_timer_init(void); + +void orion5x_setup_wins(void); + +void orion5x_ehci0_init(void); +void orion5x_ehci1_init(void); +void orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data); +void orion5x_eth_switch_init(struct dsa_chip_data *d); +void orion5x_i2c_init(void); +void orion5x_sata_init(struct mv_sata_platform_data *sata_data); +void orion5x_spi_init(void); +void orion5x_uart0_init(void); +void orion5x_uart1_init(void); +void orion5x_xor_init(void); +void orion5x_restart(enum reboot_mode, const char *); + +/* + * PCIe/PCI functions. + */ +struct pci_bus; +struct pci_host_bridge; +struct pci_sys_data; +struct pci_dev; + +void orion5x_pcie_id(u32 *dev, u32 *rev); +void orion5x_pci_disable(void); +void orion5x_pci_set_cardbus_mode(void); +int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys); +int orion5x_pci_sys_scan_bus(int nr, struct pci_host_bridge *bridge); +int orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); + +struct tag; +extern void __init tag_fixup_mem32(struct tag *, char **); + +#ifdef CONFIG_MACH_MSS2_DT +extern void mss2_init(void); +#else +static inline void mss2_init(void) {} +#endif + +#ifdef CONFIG_MACH_D2NET_DT +void d2net_init(void); +#else +static inline void d2net_init(void) {} +#endif + +/***************************************************************************** + * Helpers to access Orion registers + ****************************************************************************/ +/* + * These are not preempt-safe. Locks, if needed, must be taken + * care of by the caller. + */ +#define orion5x_setbits(r, mask) writel(readl(r) | (mask), (r)) +#define orion5x_clrbits(r, mask) writel(readl(r) & ~(mask), (r)) + +#endif diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c new file mode 100644 index 000000000..fe1a4cef1 --- /dev/null +++ b/arch/arm/mach-orion5x/db88f5281-setup.c @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * arch/arm/mach-orion5x/db88f5281-setup.c + * + * Marvell Orion-2 Development Board Setup + * + * Maintainer: Tzachi Perelstein + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "mpp.h" +#include "orion5x.h" + +/***************************************************************************** + * DB-88F5281 on board devices + ****************************************************************************/ + +/* + * 512K NOR flash Device bus boot chip select + */ + +#define DB88F5281_NOR_BOOT_BASE 0xf4000000 +#define DB88F5281_NOR_BOOT_SIZE SZ_512K + +/* + * 7-Segment on Device bus chip select 0 + */ + +#define DB88F5281_7SEG_BASE 0xfa000000 +#define DB88F5281_7SEG_SIZE SZ_1K + +/* + * 32M NOR flash on Device bus chip select 1 + */ + +#define DB88F5281_NOR_BASE 0xfc000000 +#define DB88F5281_NOR_SIZE SZ_32M + +/* + * 32M NAND flash on Device bus chip select 2 + */ + +#define DB88F5281_NAND_BASE 0xfa800000 +#define DB88F5281_NAND_SIZE SZ_1K + +/* + * PCI + */ + +#define DB88F5281_PCI_SLOT0_OFFS 7 +#define DB88F5281_PCI_SLOT0_IRQ_PIN 12 +#define DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN 13 + +/***************************************************************************** + * 512M NOR Flash on Device bus Boot CS + ****************************************************************************/ + +static struct physmap_flash_data db88f5281_boot_flash_data = { + .width = 1, /* 8 bit bus width */ +}; + +static struct resource db88f5281_boot_flash_resource = { + .flags = IORESOURCE_MEM, + .start = DB88F5281_NOR_BOOT_BASE, + .end = DB88F5281_NOR_BOOT_BASE + DB88F5281_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device db88f5281_boot_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &db88f5281_boot_flash_data, + }, + .num_resources = 1, + .resource = &db88f5281_boot_flash_resource, +}; + +/***************************************************************************** + * 32M NOR Flash on Device bus CS1 + ****************************************************************************/ + +static struct physmap_flash_data db88f5281_nor_flash_data = { + .width = 4, /* 32 bit bus width */ +}; + +static struct resource db88f5281_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = DB88F5281_NOR_BASE, + .end = DB88F5281_NOR_BASE + DB88F5281_NOR_SIZE - 1, +}; + +static struct platform_device db88f5281_nor_flash = { + .name = "physmap-flash", + .id = 1, + .dev = { + .platform_data = &db88f5281_nor_flash_data, + }, + .num_resources = 1, + .resource = &db88f5281_nor_flash_resource, +}; + +/***************************************************************************** + * 32M NAND Flash on Device bus CS2 + ****************************************************************************/ + +static struct mtd_partition db88f5281_nand_parts[] = { + { + .name = "kernel", + .offset = 0, + .size = SZ_2M, + }, { + .name = "root", + .offset = SZ_2M, + .size = (SZ_16M - SZ_2M), + }, { + .name = "user", + .offset = SZ_16M, + .size = SZ_8M, + }, { + .name = "recovery", + .offset = (SZ_16M + SZ_8M), + .size = SZ_8M, + }, +}; + +static struct resource db88f5281_nand_resource = { + .flags = IORESOURCE_MEM, + .start = DB88F5281_NAND_BASE, + .end = DB88F5281_NAND_BASE + DB88F5281_NAND_SIZE - 1, +}; + +static struct orion_nand_data db88f5281_nand_data = { + .parts = db88f5281_nand_parts, + .nr_parts = ARRAY_SIZE(db88f5281_nand_parts), + .cle = 0, + .ale = 1, + .width = 8, +}; + +static struct platform_device db88f5281_nand_flash = { + .name = "orion_nand", + .id = -1, + .dev = { + .platform_data = &db88f5281_nand_data, + }, + .resource = &db88f5281_nand_resource, + .num_resources = 1, +}; + +/***************************************************************************** + * 7-Segment on Device bus CS0 + * Dummy counter every 2 sec + ****************************************************************************/ + +static void __iomem *db88f5281_7seg; +static struct timer_list db88f5281_timer; + +static void db88f5281_7seg_event(struct timer_list *unused) +{ + static int count = 0; + writel(0, db88f5281_7seg + (count << 4)); + count = (count + 1) & 7; + mod_timer(&db88f5281_timer, jiffies + 2 * HZ); +} + +static int __init db88f5281_7seg_init(void) +{ + if (machine_is_db88f5281()) { + db88f5281_7seg = ioremap(DB88F5281_7SEG_BASE, + DB88F5281_7SEG_SIZE); + if (!db88f5281_7seg) { + printk(KERN_ERR "Failed to ioremap db88f5281_7seg\n"); + return -EIO; + } + timer_setup(&db88f5281_timer, db88f5281_7seg_event, 0); + mod_timer(&db88f5281_timer, jiffies + 2 * HZ); + } + + return 0; +} + +__initcall(db88f5281_7seg_init); + +/***************************************************************************** + * PCI + ****************************************************************************/ + +static void __init db88f5281_pci_preinit(void) +{ + int pin; + + /* + * Configure PCI GPIO IRQ pins + */ + pin = DB88F5281_PCI_SLOT0_IRQ_PIN; + if (gpio_request(pin, "PCI Int1") == 0) { + if (gpio_direction_input(pin) == 0) { + irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW); + } else { + printk(KERN_ERR "db88f5281_pci_preinit failed to " + "set_irq_type pin %d\n", pin); + gpio_free(pin); + } + } else { + printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin); + } + + pin = DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN; + if (gpio_request(pin, "PCI Int2") == 0) { + if (gpio_direction_input(pin) == 0) { + irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW); + } else { + printk(KERN_ERR "db88f5281_pci_preinit failed " + "to set_irq_type pin %d\n", pin); + gpio_free(pin); + } + } else { + printk(KERN_ERR "db88f5281_pci_preinit failed to gpio_request %d\n", pin); + } +} + +static int __init db88f5281_pci_map_irq(const struct pci_dev *dev, u8 slot, + u8 pin) +{ + int irq; + + /* + * Check for devices with hard-wired IRQs. + */ + irq = orion5x_pci_map_irq(dev, slot, pin); + if (irq != -1) + return irq; + + /* + * PCI IRQs are connected via GPIOs. + */ + switch (slot - DB88F5281_PCI_SLOT0_OFFS) { + case 0: + return gpio_to_irq(DB88F5281_PCI_SLOT0_IRQ_PIN); + case 1: + case 2: + return gpio_to_irq(DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN); + default: + return -1; + } +} + +static struct hw_pci db88f5281_pci __initdata = { + .nr_controllers = 2, + .preinit = db88f5281_pci_preinit, + .setup = orion5x_pci_sys_setup, + .scan = orion5x_pci_sys_scan_bus, + .map_irq = db88f5281_pci_map_irq, +}; + +static int __init db88f5281_pci_init(void) +{ + if (machine_is_db88f5281()) + pci_common_init(&db88f5281_pci); + + return 0; +} + +subsys_initcall(db88f5281_pci_init); + +/***************************************************************************** + * Ethernet + ****************************************************************************/ +static struct mv643xx_eth_platform_data db88f5281_eth_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +/***************************************************************************** + * RTC DS1339 on I2C bus + ****************************************************************************/ +static struct i2c_board_info __initdata db88f5281_i2c_rtc = { + I2C_BOARD_INFO("ds1339", 0x68), +}; + +/***************************************************************************** + * General Setup + ****************************************************************************/ +static unsigned int db88f5281_mpp_modes[] __initdata = { + MPP0_GPIO, /* USB Over Current */ + MPP1_GPIO, /* USB Vbat input */ + MPP2_PCI_ARB, /* PCI_REQn[2] */ + MPP3_PCI_ARB, /* PCI_GNTn[2] */ + MPP4_PCI_ARB, /* PCI_REQn[3] */ + MPP5_PCI_ARB, /* PCI_GNTn[3] */ + MPP6_GPIO, /* JP0, CON17.2 */ + MPP7_GPIO, /* JP1, CON17.1 */ + MPP8_GPIO, /* JP2, CON11.2 */ + MPP9_GPIO, /* JP3, CON11.3 */ + MPP10_GPIO, /* RTC int */ + MPP11_GPIO, /* Baud Rate Generator */ + MPP12_GPIO, /* PCI int 1 */ + MPP13_GPIO, /* PCI int 2 */ + MPP14_NAND, /* NAND_REn[2] */ + MPP15_NAND, /* NAND_WEn[2] */ + MPP16_UART, /* UART1_RX */ + MPP17_UART, /* UART1_TX */ + MPP18_UART, /* UART1_CTSn */ + MPP19_UART, /* UART1_RTSn */ + 0, +}; + +static void __init db88f5281_init(void) +{ + /* + * Basic Orion setup. Need to be called early. + */ + orion5x_init(); + + orion5x_mpp_conf(db88f5281_mpp_modes); + writel(0, MPP_DEV_CTRL); /* DEV_D[31:16] */ + + /* + * Configure peripherals. + */ + orion5x_ehci0_init(); + orion5x_eth_init(&db88f5281_eth_data); + orion5x_i2c_init(); + orion5x_uart0_init(); + orion5x_uart1_init(); + + mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET, + ORION_MBUS_DEVBUS_BOOT_ATTR, + DB88F5281_NOR_BOOT_BASE, + DB88F5281_NOR_BOOT_SIZE); + platform_device_register(&db88f5281_boot_flash); + + mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_TARGET(0), + ORION_MBUS_DEVBUS_ATTR(0), + DB88F5281_7SEG_BASE, + DB88F5281_7SEG_SIZE); + + mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_TARGET(1), + ORION_MBUS_DEVBUS_ATTR(1), + DB88F5281_NOR_BASE, + DB88F5281_NOR_SIZE); + platform_device_register(&db88f5281_nor_flash); + + mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_TARGET(2), + ORION_MBUS_DEVBUS_ATTR(2), + DB88F5281_NAND_BASE, + DB88F5281_NAND_SIZE); + platform_device_register(&db88f5281_nand_flash); + + i2c_register_board_info(0, &db88f5281_i2c_rtc, 1); +} + +MACHINE_START(DB88F5281, "Marvell Orion-2 Development Board") + /* Maintainer: Tzachi Perelstein */ + .atag_offset = 0x100, + .nr_irqs = ORION5X_NR_IRQS, + .init_machine = db88f5281_init, + .map_io = orion5x_map_io, + .init_early = orion5x_init_early, + .init_irq = orion5x_init_irq, + .init_time = orion5x_timer_init, + .restart = orion5x_restart, +MACHINE_END diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c new file mode 100644 index 000000000..d69259b6b --- /dev/null +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -0,0 +1,724 @@ +/* + * arch/arm/mach-orion5x/dns323-setup.c + * + * Copyright (C) 2007 Herbert Valerio Riedel + * + * Support for HW Rev C1: + * + * Copyright (C) 2010 Benjamin Herrenschmidt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "orion5x.h" +#include "common.h" +#include "mpp.h" + +/* Rev A1 and B1 */ +#define DNS323_GPIO_LED_RIGHT_AMBER 1 +#define DNS323_GPIO_LED_LEFT_AMBER 2 +#define DNS323_GPIO_SYSTEM_UP 3 +#define DNS323_GPIO_LED_POWER1 4 +#define DNS323_GPIO_LED_POWER2 5 +#define DNS323_GPIO_OVERTEMP 6 +#define DNS323_GPIO_RTC 7 +#define DNS323_GPIO_POWER_OFF 8 +#define DNS323_GPIO_KEY_POWER 9 +#define DNS323_GPIO_KEY_RESET 10 + +/* Rev C1 */ +#define DNS323C_GPIO_KEY_POWER 1 +#define DNS323C_GPIO_POWER_OFF 2 +#define DNS323C_GPIO_LED_RIGHT_AMBER 8 +#define DNS323C_GPIO_LED_LEFT_AMBER 9 +#define DNS323C_GPIO_LED_POWER 17 +#define DNS323C_GPIO_FAN_BIT1 18 +#define DNS323C_GPIO_FAN_BIT0 19 + +/* Exposed to userspace, do not change */ +enum { + DNS323_REV_A1, /* 0 */ + DNS323_REV_B1, /* 1 */ + DNS323_REV_C1, /* 2 */ +}; + + +/**************************************************************************** + * PCI setup + */ + +static int __init dns323_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + int irq; + + /* + * Check for devices with hard-wired IRQs. + */ + irq = orion5x_pci_map_irq(dev, slot, pin); + if (irq != -1) + return irq; + + return -1; +} + +static struct hw_pci dns323_pci __initdata = { + .nr_controllers = 2, + .setup = orion5x_pci_sys_setup, + .scan = orion5x_pci_sys_scan_bus, + .map_irq = dns323_pci_map_irq, +}; + +static int __init dns323_pci_init(void) +{ + /* Rev B1 and C1 doesn't really use its PCI bus, and initialising PCI + * gets in the way of initialising the SATA controller. + */ + if (machine_is_dns323() && system_rev == DNS323_REV_A1) + pci_common_init(&dns323_pci); + + return 0; +} + +subsys_initcall(dns323_pci_init); + +/**************************************************************************** + * 8MiB NOR flash (Spansion S29GL064M90TFIR4) + * + * Layout as used by D-Link: + * 0x00000000-0x00010000 : "MTD1" + * 0x00010000-0x00020000 : "MTD2" + * 0x00020000-0x001a0000 : "Linux Kernel" + * 0x001a0000-0x007d0000 : "File System" + * 0x007d0000-0x00800000 : "u-boot" + */ + +#define DNS323_NOR_BOOT_BASE 0xf4000000 +#define DNS323_NOR_BOOT_SIZE SZ_8M + +static struct mtd_partition dns323_partitions[] = { + { + .name = "MTD1", + .size = 0x00010000, + .offset = 0, + }, { + .name = "MTD2", + .size = 0x00010000, + .offset = 0x00010000, + }, { + .name = "Linux Kernel", + .size = 0x00180000, + .offset = 0x00020000, + }, { + .name = "File System", + .size = 0x00630000, + .offset = 0x001A0000, + }, { + .name = "u-boot", + .size = 0x00030000, + .offset = 0x007d0000, + }, +}; + +static struct physmap_flash_data dns323_nor_flash_data = { + .width = 1, + .parts = dns323_partitions, + .nr_parts = ARRAY_SIZE(dns323_partitions) +}; + +static struct resource dns323_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = DNS323_NOR_BOOT_BASE, + .end = DNS323_NOR_BOOT_BASE + DNS323_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device dns323_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &dns323_nor_flash_data, + }, + .resource = &dns323_nor_flash_resource, + .num_resources = 1, +}; + +/**************************************************************************** + * Ethernet + */ + +static struct mv643xx_eth_platform_data dns323_eth_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +/* dns323_parse_hex_*() taken from tsx09-common.c; should a common copy of these + * functions be kept somewhere? + */ +static int __init dns323_parse_hex_nibble(char n) +{ + if (n >= '0' && n <= '9') + return n - '0'; + + if (n >= 'A' && n <= 'F') + return n - 'A' + 10; + + if (n >= 'a' && n <= 'f') + return n - 'a' + 10; + + return -1; +} + +static int __init dns323_parse_hex_byte(const char *b) +{ + int hi; + int lo; + + hi = dns323_parse_hex_nibble(b[0]); + lo = dns323_parse_hex_nibble(b[1]); + + if (hi < 0 || lo < 0) + return -1; + + return (hi << 4) | lo; +} + +static int __init dns323_read_mac_addr(void) +{ + u_int8_t addr[6]; + int i; + char *mac_page; + + /* MAC address is stored as a regular ol' string in /dev/mtdblock4 + * (0x007d0000-0x00800000) starting at offset 196480 (0x2ff80). + */ + mac_page = ioremap(DNS323_NOR_BOOT_BASE + 0x7d0000 + 196480, 1024); + if (!mac_page) + return -ENOMEM; + + /* Sanity check the string we're looking at */ + for (i = 0; i < 5; i++) { + if (*(mac_page + (i * 3) + 2) != ':') { + goto error_fail; + } + } + + for (i = 0; i < 6; i++) { + int byte; + + byte = dns323_parse_hex_byte(mac_page + (i * 3)); + if (byte < 0) { + goto error_fail; + } + + addr[i] = byte; + } + + iounmap(mac_page); + printk("DNS-323: Found ethernet MAC address: %pM\n", addr); + + memcpy(dns323_eth_data.mac_addr, addr, 6); + + return 0; + +error_fail: + iounmap(mac_page); + return -EINVAL; +} + +/**************************************************************************** + * GPIO LEDs (simple - doesn't use hardware blinking support) + */ + +static struct gpio_led dns323ab_leds[] = { + { + .name = "power:blue", + .gpio = DNS323_GPIO_LED_POWER2, + .default_trigger = "default-on", + }, { + .name = "right:amber", + .gpio = DNS323_GPIO_LED_RIGHT_AMBER, + .active_low = 1, + }, { + .name = "left:amber", + .gpio = DNS323_GPIO_LED_LEFT_AMBER, + .active_low = 1, + }, +}; + + +static struct gpio_led dns323c_leds[] = { + { + .name = "power:blue", + .gpio = DNS323C_GPIO_LED_POWER, + .default_trigger = "timer", + .active_low = 1, + }, { + .name = "right:amber", + .gpio = DNS323C_GPIO_LED_RIGHT_AMBER, + .active_low = 1, + }, { + .name = "left:amber", + .gpio = DNS323C_GPIO_LED_LEFT_AMBER, + .active_low = 1, + }, +}; + + +static struct gpio_led_platform_data dns323ab_led_data = { + .num_leds = ARRAY_SIZE(dns323ab_leds), + .leds = dns323ab_leds, + .gpio_blink_set = orion_gpio_led_blink_set, +}; + +static struct gpio_led_platform_data dns323c_led_data = { + .num_leds = ARRAY_SIZE(dns323c_leds), + .leds = dns323c_leds, + .gpio_blink_set = orion_gpio_led_blink_set, +}; + +static struct platform_device dns323_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &dns323ab_led_data, + }, +}; + +/**************************************************************************** + * GPIO Attached Keys + */ + +static struct gpio_keys_button dns323ab_buttons[] = { + { + .code = KEY_RESTART, + .gpio = DNS323_GPIO_KEY_RESET, + .desc = "Reset Button", + .active_low = 1, + }, { + .code = KEY_POWER, + .gpio = DNS323_GPIO_KEY_POWER, + .desc = "Power Button", + .active_low = 1, + }, +}; + +static struct gpio_keys_platform_data dns323ab_button_data = { + .buttons = dns323ab_buttons, + .nbuttons = ARRAY_SIZE(dns323ab_buttons), +}; + +static struct gpio_keys_button dns323c_buttons[] = { + { + .code = KEY_POWER, + .gpio = DNS323C_GPIO_KEY_POWER, + .desc = "Power Button", + .active_low = 1, + }, +}; + +static struct gpio_keys_platform_data dns323c_button_data = { + .buttons = dns323c_buttons, + .nbuttons = ARRAY_SIZE(dns323c_buttons), +}; + +static struct platform_device dns323_button_device = { + .name = "gpio-keys", + .id = -1, + .num_resources = 0, + .dev = { + .platform_data = &dns323ab_button_data, + }, +}; + +/***************************************************************************** + * SATA + */ +static struct mv_sata_platform_data dns323_sata_data = { + .n_ports = 2, +}; + +/**************************************************************************** + * General Setup + */ +static unsigned int dns323a_mpp_modes[] __initdata = { + MPP0_PCIE_RST_OUTn, + MPP1_GPIO, /* right amber LED (sata ch0) */ + MPP2_GPIO, /* left amber LED (sata ch1) */ + MPP3_UNUSED, + MPP4_GPIO, /* power button LED */ + MPP5_GPIO, /* power button LED */ + MPP6_GPIO, /* GMT G751-2f overtemp */ + MPP7_GPIO, /* M41T80 nIRQ/OUT/SQW */ + MPP8_GPIO, /* triggers power off */ + MPP9_GPIO, /* power button switch */ + MPP10_GPIO, /* reset button switch */ + MPP11_UNUSED, + MPP12_UNUSED, + MPP13_UNUSED, + MPP14_UNUSED, + MPP15_UNUSED, + MPP16_UNUSED, + MPP17_UNUSED, + MPP18_UNUSED, + MPP19_UNUSED, + 0, +}; + +static unsigned int dns323b_mpp_modes[] __initdata = { + MPP0_UNUSED, + MPP1_GPIO, /* right amber LED (sata ch0) */ + MPP2_GPIO, /* left amber LED (sata ch1) */ + MPP3_GPIO, /* system up flag */ + MPP4_GPIO, /* power button LED */ + MPP5_GPIO, /* power button LED */ + MPP6_GPIO, /* GMT G751-2f overtemp */ + MPP7_GPIO, /* M41T80 nIRQ/OUT/SQW */ + MPP8_GPIO, /* triggers power off */ + MPP9_GPIO, /* power button switch */ + MPP10_GPIO, /* reset button switch */ + MPP11_UNUSED, + MPP12_SATA_LED, + MPP13_SATA_LED, + MPP14_SATA_LED, + MPP15_SATA_LED, + MPP16_UNUSED, + MPP17_UNUSED, + MPP18_UNUSED, + MPP19_UNUSED, + 0, +}; + +static unsigned int dns323c_mpp_modes[] __initdata = { + MPP0_GPIO, /* ? input */ + MPP1_GPIO, /* input power switch (0 = pressed) */ + MPP2_GPIO, /* output power off */ + MPP3_UNUSED, /* ? output */ + MPP4_UNUSED, /* ? output */ + MPP5_UNUSED, /* ? output */ + MPP6_UNUSED, /* ? output */ + MPP7_UNUSED, /* ? output */ + MPP8_GPIO, /* i/o right amber LED */ + MPP9_GPIO, /* i/o left amber LED */ + MPP10_GPIO, /* input */ + MPP11_UNUSED, + MPP12_SATA_LED, + MPP13_SATA_LED, + MPP14_SATA_LED, + MPP15_SATA_LED, + MPP16_UNUSED, + MPP17_GPIO, /* power button LED */ + MPP18_GPIO, /* fan speed bit 0 */ + MPP19_GPIO, /* fan speed bit 1 */ + 0, +}; + +/* Rev C1 Fan speed notes: + * + * The fan is controlled by 2 GPIOs on this board. The settings + * of the bits is as follow: + * + * GPIO 18 GPIO 19 Fan + * + * 0 0 stopped + * 0 1 low speed + * 1 0 high speed + * 1 1 don't do that (*) + * + * (*) I think the two bits control two feed-in resistors into a fixed + * PWN circuit, setting both bits will basically go a 'bit' faster + * than high speed, but d-link doesn't do it and you may get out of + * HW spec so don't do it. + */ + +/* + * On the DNS-323 A1 and B1 the following devices are attached via I2C: + * + * i2c addr | chip | description + * 0x3e | GMT G760Af | fan speed PWM controller + * 0x48 | GMT G751-2f | temp. sensor and therm. watchdog (LM75 compatible) + * 0x68 | ST M41T80 | RTC w/ alarm + */ +static struct i2c_board_info __initdata dns323ab_i2c_devices[] = { + { + I2C_BOARD_INFO("g760a", 0x3e), + }, { + I2C_BOARD_INFO("lm75", 0x48), + }, { + I2C_BOARD_INFO("m41t80", 0x68), + }, +}; + +/* + * On the DNS-323 C1 the following devices are attached via I2C: + * + * i2c addr | chip | description + * 0x48 | GMT G751-2f | temp. sensor and therm. watchdog (LM75 compatible) + * 0x68 | ST M41T80 | RTC w/ alarm + */ +static struct i2c_board_info __initdata dns323c_i2c_devices[] = { + { + I2C_BOARD_INFO("lm75", 0x48), + }, { + I2C_BOARD_INFO("m41t80", 0x68), + }, +}; + +/* DNS-323 rev. A specific power off method */ +static void dns323a_power_off(void) +{ + pr_info("DNS-323: Triggering power-off...\n"); + gpio_set_value(DNS323_GPIO_POWER_OFF, 1); +} + +/* DNS-323 rev B specific power off method */ +static void dns323b_power_off(void) +{ + pr_info("DNS-323: Triggering power-off...\n"); + /* Pin has to be changed to 1 and back to 0 to do actual power off. */ + gpio_set_value(DNS323_GPIO_POWER_OFF, 1); + mdelay(100); + gpio_set_value(DNS323_GPIO_POWER_OFF, 0); +} + +/* DNS-323 rev. C specific power off method */ +static void dns323c_power_off(void) +{ + pr_info("DNS-323: Triggering power-off...\n"); + gpio_set_value(DNS323C_GPIO_POWER_OFF, 1); +} + +static int dns323c_phy_fixup(struct phy_device *phy) +{ + phy->dev_flags |= MARVELL_PHY_M1118_DNS323_LEDS; + + return 0; +} + +static int __init dns323_identify_rev(void) +{ + u32 dev, rev, i, reg; + + pr_debug("DNS-323: Identifying board ... \n"); + + /* Rev A1 has a 5181 */ + orion5x_pcie_id(&dev, &rev); + if (dev == MV88F5181_DEV_ID) { + pr_debug("DNS-323: 5181 found, board is A1\n"); + return DNS323_REV_A1; + } + pr_debug("DNS-323: 5182 found, board is B1 or C1, checking PHY...\n"); + + /* Rev B1 and C1 both have 5182, let's poke at the eth PHY. This is + * a bit gross but we want to do that without links into the eth + * driver so let's poke at it directly. We default to rev B1 in + * case the accesses fail + */ + +#define ETH_SMI_REG (ORION5X_ETH_VIRT_BASE + 0x2000 + 0x004) +#define SMI_BUSY 0x10000000 +#define SMI_READ_VALID 0x08000000 +#define SMI_OPCODE_READ 0x04000000 +#define SMI_OPCODE_WRITE 0x00000000 + + for (i = 0; i < 1000; i++) { + reg = readl(ETH_SMI_REG); + if (!(reg & SMI_BUSY)) + break; + } + if (i >= 1000) { + pr_warn("DNS-323: Timeout accessing PHY, assuming rev B1\n"); + return DNS323_REV_B1; + } + writel((3 << 21) /* phy ID reg */ | + (8 << 16) /* phy addr */ | + SMI_OPCODE_READ, ETH_SMI_REG); + for (i = 0; i < 1000; i++) { + reg = readl(ETH_SMI_REG); + if (reg & SMI_READ_VALID) + break; + } + if (i >= 1000) { + pr_warn("DNS-323: Timeout reading PHY, assuming rev B1\n"); + return DNS323_REV_B1; + } + pr_debug("DNS-323: Ethernet PHY ID 0x%x\n", reg & 0xffff); + + /* Note: the Marvell tools mask the ID with 0x3f0 before comparison + * but I don't see that making a difference here, at least with + * any known Marvell PHY ID + */ + switch(reg & 0xfff0) { + case 0x0cc0: /* MV88E1111 */ + return DNS323_REV_B1; + case 0x0e10: /* MV88E1118 */ + return DNS323_REV_C1; + default: + pr_warn("DNS-323: Unknown PHY ID 0x%04x, assuming rev B1\n", + reg & 0xffff); + } + return DNS323_REV_B1; +} + +static void __init dns323_init(void) +{ + /* Setup basic Orion functions. Need to be called early. */ + orion5x_init(); + + /* Identify revision */ + system_rev = dns323_identify_rev(); + pr_info("DNS-323: Identified HW revision %c1\n", 'A' + system_rev); + + /* Just to be tricky, the 5182 has a completely different + * set of MPP modes to the 5181. + */ + switch(system_rev) { + case DNS323_REV_A1: + orion5x_mpp_conf(dns323a_mpp_modes); + writel(0, MPP_DEV_CTRL); /* DEV_D[31:16] */ + break; + case DNS323_REV_B1: + orion5x_mpp_conf(dns323b_mpp_modes); + break; + case DNS323_REV_C1: + orion5x_mpp_conf(dns323c_mpp_modes); + break; + } + + /* setup flash mapping + * CS3 holds a 8 MB Spansion S29GL064M90TFIR4 + */ + mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET, + ORION_MBUS_DEVBUS_BOOT_ATTR, + DNS323_NOR_BOOT_BASE, + DNS323_NOR_BOOT_SIZE); + platform_device_register(&dns323_nor_flash); + + /* Sort out LEDs, Buttons and i2c devices */ + switch(system_rev) { + case DNS323_REV_A1: + /* The 5181 power LED is active low and requires + * DNS323_GPIO_LED_POWER1 to also be low. + */ + dns323ab_leds[0].active_low = 1; + gpio_request(DNS323_GPIO_LED_POWER1, "Power Led Enable"); + gpio_direction_output(DNS323_GPIO_LED_POWER1, 0); + fallthrough; + case DNS323_REV_B1: + i2c_register_board_info(0, dns323ab_i2c_devices, + ARRAY_SIZE(dns323ab_i2c_devices)); + break; + case DNS323_REV_C1: + /* Hookup LEDs & Buttons */ + dns323_gpio_leds.dev.platform_data = &dns323c_led_data; + dns323_button_device.dev.platform_data = &dns323c_button_data; + + /* Hookup i2c devices and fan driver */ + i2c_register_board_info(0, dns323c_i2c_devices, + ARRAY_SIZE(dns323c_i2c_devices)); + platform_device_register_simple("dns323c-fan", 0, NULL, 0); + + /* Register fixup for the PHY LEDs */ + if (!IS_BUILTIN(CONFIG_PHYLIB)) + break; + phy_register_fixup_for_uid(MARVELL_PHY_ID_88E1118, + MARVELL_PHY_ID_MASK, + dns323c_phy_fixup); + } + + platform_device_register(&dns323_gpio_leds); + platform_device_register(&dns323_button_device); + + /* + * Configure peripherals. + */ + if (dns323_read_mac_addr() < 0) + printk("DNS-323: Failed to read MAC address\n"); + orion5x_ehci0_init(); + orion5x_eth_init(&dns323_eth_data); + orion5x_i2c_init(); + orion5x_uart0_init(); + + /* Remaining GPIOs */ + switch(system_rev) { + case DNS323_REV_A1: + /* Poweroff GPIO */ + if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 || + gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0) + pr_err("DNS-323: failed to setup power-off GPIO\n"); + pm_power_off = dns323a_power_off; + break; + case DNS323_REV_B1: + /* 5182 built-in SATA init */ + orion5x_sata_init(&dns323_sata_data); + + /* The DNS323 rev B1 has flag to indicate the system is up. + * Without this flag set, power LED will flash and cannot be + * controlled via leds-gpio. + */ + if (gpio_request(DNS323_GPIO_SYSTEM_UP, "SYS_READY") == 0) + gpio_direction_output(DNS323_GPIO_SYSTEM_UP, 1); + + /* Poweroff GPIO */ + if (gpio_request(DNS323_GPIO_POWER_OFF, "POWEROFF") != 0 || + gpio_direction_output(DNS323_GPIO_POWER_OFF, 0) != 0) + pr_err("DNS-323: failed to setup power-off GPIO\n"); + pm_power_off = dns323b_power_off; + break; + case DNS323_REV_C1: + /* 5182 built-in SATA init */ + orion5x_sata_init(&dns323_sata_data); + + /* Poweroff GPIO */ + if (gpio_request(DNS323C_GPIO_POWER_OFF, "POWEROFF") != 0 || + gpio_direction_output(DNS323C_GPIO_POWER_OFF, 0) != 0) + pr_err("DNS-323: failed to setup power-off GPIO\n"); + pm_power_off = dns323c_power_off; + + /* Now, -this- should theoretically be done by the sata_mv driver + * once I figure out what's going on there. Maybe the behaviour + * of the LEDs should be somewhat passed via the platform_data. + * for now, just whack the register and make the LEDs happy + * + * Note: AFAIK, rev B1 needs the same treatment but I'll let + * somebody else test it. + */ + writel(0x5, ORION5X_SATA_VIRT_BASE + 0x2c); + break; + } +} + +/* Warning: D-Link uses a wrong mach-type (=526) in their bootloader */ +MACHINE_START(DNS323, "D-Link DNS-323") + /* Maintainer: Herbert Valerio Riedel */ + .atag_offset = 0x100, + .nr_irqs = ORION5X_NR_IRQS, + .init_machine = dns323_init, + .map_io = orion5x_map_io, + .init_early = orion5x_init_early, + .init_irq = orion5x_init_irq, + .init_time = orion5x_timer_init, + .fixup = tag_fixup_mem32, + .restart = orion5x_restart, +MACHINE_END diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c new file mode 100644 index 000000000..e17727e53 --- /dev/null +++ b/arch/arm/mach-orion5x/irq.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * arch/arm/mach-orion5x/irq.c + * + * Core IRQ functions for Marvell Orion System On Chip + * + * Maintainer: Tzachi Perelstein + */ +#include +#include +#include +#include +#include +#include +#include +#include "bridge-regs.h" +#include "common.h" + +static int __initdata gpio0_irqs[4] = { + IRQ_ORION5X_GPIO_0_7, + IRQ_ORION5X_GPIO_8_15, + IRQ_ORION5X_GPIO_16_23, + IRQ_ORION5X_GPIO_24_31, +}; + +static asmlinkage void +__exception_irq_entry orion5x_legacy_handle_irq(struct pt_regs *regs) +{ + u32 stat; + + stat = readl_relaxed(MAIN_IRQ_CAUSE); + stat &= readl_relaxed(MAIN_IRQ_MASK); + if (stat) { + unsigned int hwirq = 1 + __fls(stat); + handle_IRQ(hwirq, regs); + return; + } +} + +void __init orion5x_init_irq(void) +{ + orion_irq_init(1, MAIN_IRQ_MASK); + + set_handle_irq(orion5x_legacy_handle_irq); + + /* + * Initialize gpiolib for GPIOs 0-31. + */ + orion_gpio_init(0, 32, GPIO_VIRT_BASE, 0, + IRQ_ORION5X_GPIO_START, gpio0_irqs); +} diff --git a/arch/arm/mach-orion5x/irqs.h b/arch/arm/mach-orion5x/irqs.h new file mode 100644 index 000000000..a70c47cfa --- /dev/null +++ b/arch/arm/mach-orion5x/irqs.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * IRQ definitions for Orion SoC + * + * Maintainer: Tzachi Perelstein + */ + +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H + +/* + * Orion Main Interrupt Controller + */ +#define IRQ_ORION5X_BRIDGE (1 + 0) +#define IRQ_ORION5X_DOORBELL_H2C (1 + 1) +#define IRQ_ORION5X_DOORBELL_C2H (1 + 2) +#define IRQ_ORION5X_UART0 (1 + 3) +#define IRQ_ORION5X_UART1 (1 + 4) +#define IRQ_ORION5X_I2C (1 + 5) +#define IRQ_ORION5X_GPIO_0_7 (1 + 6) +#define IRQ_ORION5X_GPIO_8_15 (1 + 7) +#define IRQ_ORION5X_GPIO_16_23 (1 + 8) +#define IRQ_ORION5X_GPIO_24_31 (1 + 9) +#define IRQ_ORION5X_PCIE0_ERR (1 + 10) +#define IRQ_ORION5X_PCIE0_INT (1 + 11) +#define IRQ_ORION5X_USB1_CTRL (1 + 12) +#define IRQ_ORION5X_DEV_BUS_ERR (1 + 14) +#define IRQ_ORION5X_PCI_ERR (1 + 15) +#define IRQ_ORION5X_USB_BR_ERR (1 + 16) +#define IRQ_ORION5X_USB0_CTRL (1 + 17) +#define IRQ_ORION5X_ETH_RX (1 + 18) +#define IRQ_ORION5X_ETH_TX (1 + 19) +#define IRQ_ORION5X_ETH_MISC (1 + 20) +#define IRQ_ORION5X_ETH_SUM (1 + 21) +#define IRQ_ORION5X_ETH_ERR (1 + 22) +#define IRQ_ORION5X_IDMA_ERR (1 + 23) +#define IRQ_ORION5X_IDMA_0 (1 + 24) +#define IRQ_ORION5X_IDMA_1 (1 + 25) +#define IRQ_ORION5X_IDMA_2 (1 + 26) +#define IRQ_ORION5X_IDMA_3 (1 + 27) +#define IRQ_ORION5X_CESA (1 + 28) +#define IRQ_ORION5X_SATA (1 + 29) +#define IRQ_ORION5X_XOR0 (1 + 30) +#define IRQ_ORION5X_XOR1 (1 + 31) + +/* + * Orion General Purpose Pins + */ +#define IRQ_ORION5X_GPIO_START 33 +#define NR_GPIO_IRQS 32 + +#define ORION5X_NR_IRQS (IRQ_ORION5X_GPIO_START + NR_GPIO_IRQS) + + +#endif diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c new file mode 100644 index 000000000..acba06618 --- /dev/null +++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c @@ -0,0 +1,407 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * arch/arm/mach-orion5x/kurobox_pro-setup.c + * + * Maintainer: Ronen Shitrit + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "mpp.h" +#include "orion5x.h" + +/***************************************************************************** + * KUROBOX-PRO Info + ****************************************************************************/ + +/* + * 256K NOR flash Device bus boot chip select + */ + +#define KUROBOX_PRO_NOR_BOOT_BASE 0xf4000000 +#define KUROBOX_PRO_NOR_BOOT_SIZE SZ_256K + +/* + * 256M NAND flash on Device bus chip select 1 + */ + +#define KUROBOX_PRO_NAND_BASE 0xfc000000 +#define KUROBOX_PRO_NAND_SIZE SZ_2M + +/***************************************************************************** + * 256MB NAND Flash on Device bus CS0 + ****************************************************************************/ + +static struct mtd_partition kurobox_pro_nand_parts[] = { + { + .name = "uImage", + .offset = 0, + .size = SZ_4M, + }, { + .name = "rootfs", + .offset = SZ_4M, + .size = SZ_64M, + }, { + .name = "extra", + .offset = SZ_4M + SZ_64M, + .size = SZ_256M - (SZ_4M + SZ_64M), + }, +}; + +static struct resource kurobox_pro_nand_resource = { + .flags = IORESOURCE_MEM, + .start = KUROBOX_PRO_NAND_BASE, + .end = KUROBOX_PRO_NAND_BASE + KUROBOX_PRO_NAND_SIZE - 1, +}; + +static struct orion_nand_data kurobox_pro_nand_data = { + .parts = kurobox_pro_nand_parts, + .nr_parts = ARRAY_SIZE(kurobox_pro_nand_parts), + .cle = 0, + .ale = 1, + .width = 8, +}; + +static struct platform_device kurobox_pro_nand_flash = { + .name = "orion_nand", + .id = -1, + .dev = { + .platform_data = &kurobox_pro_nand_data, + }, + .resource = &kurobox_pro_nand_resource, + .num_resources = 1, +}; + +/***************************************************************************** + * 256KB NOR Flash on BOOT Device + ****************************************************************************/ + +static struct physmap_flash_data kurobox_pro_nor_flash_data = { + .width = 1, +}; + +static struct resource kurobox_pro_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = KUROBOX_PRO_NOR_BOOT_BASE, + .end = KUROBOX_PRO_NOR_BOOT_BASE + KUROBOX_PRO_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device kurobox_pro_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &kurobox_pro_nor_flash_data, + }, + .num_resources = 1, + .resource = &kurobox_pro_nor_flash_resource, +}; + +/***************************************************************************** + * PCI + ****************************************************************************/ + +static int __init kurobox_pro_pci_map_irq(const struct pci_dev *dev, u8 slot, + u8 pin) +{ + int irq; + + /* + * Check for devices with hard-wired IRQs. + */ + irq = orion5x_pci_map_irq(dev, slot, pin); + if (irq != -1) + return irq; + + /* + * PCI isn't used on the Kuro + */ + return -1; +} + +static struct hw_pci kurobox_pro_pci __initdata = { + .nr_controllers = 2, + .setup = orion5x_pci_sys_setup, + .scan = orion5x_pci_sys_scan_bus, + .map_irq = kurobox_pro_pci_map_irq, +}; + +static int __init kurobox_pro_pci_init(void) +{ + if (machine_is_kurobox_pro()) { + orion5x_pci_disable(); + pci_common_init(&kurobox_pro_pci); + } + + return 0; +} + +subsys_initcall(kurobox_pro_pci_init); + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data kurobox_pro_eth_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +/***************************************************************************** + * RTC 5C372a on I2C bus + ****************************************************************************/ +static struct i2c_board_info __initdata kurobox_pro_i2c_rtc = { + I2C_BOARD_INFO("rs5c372a", 0x32), +}; + +/***************************************************************************** + * SATA + ****************************************************************************/ +static struct mv_sata_platform_data kurobox_pro_sata_data = { + .n_ports = 2, +}; + +/***************************************************************************** + * Kurobox Pro specific power off method via UART1-attached microcontroller + ****************************************************************************/ + +#define UART1_REG(x) (UART1_VIRT_BASE + ((UART_##x) << 2)) + +static int kurobox_pro_miconread(unsigned char *buf, int count) +{ + int i; + int timeout; + + for (i = 0; i < count; i++) { + timeout = 10; + + while (!(readl(UART1_REG(LSR)) & UART_LSR_DR)) { + if (--timeout == 0) + break; + udelay(1000); + } + + if (timeout == 0) + break; + buf[i] = readl(UART1_REG(RX)); + } + + /* return read bytes */ + return i; +} + +static int kurobox_pro_miconwrite(const unsigned char *buf, int count) +{ + int i = 0; + + while (count--) { + while (!(readl(UART1_REG(LSR)) & UART_LSR_THRE)) + barrier(); + writel(buf[i++], UART1_REG(TX)); + } + + return 0; +} + +static int kurobox_pro_miconsend(const unsigned char *data, int count) +{ + int i; + unsigned char checksum = 0; + unsigned char recv_buf[40]; + unsigned char send_buf[40]; + unsigned char correct_ack[3]; + int retry = 2; + + /* Generate checksum */ + for (i = 0; i < count; i++) + checksum -= data[i]; + + do { + /* Send data */ + kurobox_pro_miconwrite(data, count); + + /* send checksum */ + kurobox_pro_miconwrite(&checksum, 1); + + if (kurobox_pro_miconread(recv_buf, sizeof(recv_buf)) <= 3) { + printk(KERN_ERR ">%s: receive failed.\n", __func__); + + /* send preamble to clear the receive buffer */ + memset(&send_buf, 0xff, sizeof(send_buf)); + kurobox_pro_miconwrite(send_buf, sizeof(send_buf)); + + /* make dummy reads */ + mdelay(100); + kurobox_pro_miconread(recv_buf, sizeof(recv_buf)); + } else { + /* Generate expected ack */ + correct_ack[0] = 0x01; + correct_ack[1] = data[1]; + correct_ack[2] = 0x00; + + /* checksum Check */ + if ((recv_buf[0] + recv_buf[1] + recv_buf[2] + + recv_buf[3]) & 0xFF) { + printk(KERN_ERR ">%s: Checksum Error : " + "Received data[%02x, %02x, %02x, %02x]" + "\n", __func__, recv_buf[0], + recv_buf[1], recv_buf[2], recv_buf[3]); + } else { + /* Check Received Data */ + if (correct_ack[0] == recv_buf[0] && + correct_ack[1] == recv_buf[1] && + correct_ack[2] == recv_buf[2]) { + /* Interval for next command */ + mdelay(10); + + /* Receive ACK */ + return 0; + } + } + /* Received NAK or illegal Data */ + printk(KERN_ERR ">%s: Error : NAK or Illegal Data " + "Received\n", __func__); + } + } while (retry--); + + /* Interval for next command */ + mdelay(10); + + return -1; +} + +static void kurobox_pro_power_off(void) +{ + const unsigned char watchdogkill[] = {0x01, 0x35, 0x00}; + const unsigned char shutdownwait[] = {0x00, 0x0c}; + const unsigned char poweroff[] = {0x00, 0x06}; + /* 38400 baud divisor */ + const unsigned divisor = ((orion5x_tclk + (8 * 38400)) / (16 * 38400)); + + pr_info("%s: triggering power-off...\n", __func__); + + /* hijack uart1 and reset into sane state (38400,8n1,even parity) */ + writel(0x83, UART1_REG(LCR)); + writel(divisor & 0xff, UART1_REG(DLL)); + writel((divisor >> 8) & 0xff, UART1_REG(DLM)); + writel(0x1b, UART1_REG(LCR)); + writel(0x00, UART1_REG(IER)); + writel(0x07, UART1_REG(FCR)); + writel(0x00, UART1_REG(MCR)); + + /* Send the commands to shutdown the Kurobox Pro */ + kurobox_pro_miconsend(watchdogkill, sizeof(watchdogkill)) ; + kurobox_pro_miconsend(shutdownwait, sizeof(shutdownwait)) ; + kurobox_pro_miconsend(poweroff, sizeof(poweroff)); +} + +/***************************************************************************** + * General Setup + ****************************************************************************/ +static unsigned int kurobox_pro_mpp_modes[] __initdata = { + MPP0_UNUSED, + MPP1_UNUSED, + MPP2_GPIO, /* GPIO Micon */ + MPP3_GPIO, /* GPIO Rtc */ + MPP4_UNUSED, + MPP5_UNUSED, + MPP6_NAND, /* NAND Flash REn */ + MPP7_NAND, /* NAND Flash WEn */ + MPP8_UNUSED, + MPP9_UNUSED, + MPP10_UNUSED, + MPP11_UNUSED, + MPP12_SATA_LED, /* SATA 0 presence */ + MPP13_SATA_LED, /* SATA 1 presence */ + MPP14_SATA_LED, /* SATA 0 active */ + MPP15_SATA_LED, /* SATA 1 active */ + MPP16_UART, /* UART1 RXD */ + MPP17_UART, /* UART1 TXD */ + MPP18_UART, /* UART1 CTSn */ + MPP19_UART, /* UART1 RTSn */ + 0, +}; + +static void __init kurobox_pro_init(void) +{ + /* + * Setup basic Orion functions. Need to be called early. + */ + orion5x_init(); + + orion5x_mpp_conf(kurobox_pro_mpp_modes); + + /* + * Configure peripherals. + */ + orion5x_ehci0_init(); + orion5x_ehci1_init(); + orion5x_eth_init(&kurobox_pro_eth_data); + orion5x_i2c_init(); + orion5x_sata_init(&kurobox_pro_sata_data); + orion5x_uart0_init(); + orion5x_uart1_init(); + orion5x_xor_init(); + + mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET, + ORION_MBUS_DEVBUS_BOOT_ATTR, + KUROBOX_PRO_NOR_BOOT_BASE, + KUROBOX_PRO_NOR_BOOT_SIZE); + platform_device_register(&kurobox_pro_nor_flash); + + if (machine_is_kurobox_pro()) { + mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_TARGET(0), + ORION_MBUS_DEVBUS_ATTR(0), + KUROBOX_PRO_NAND_BASE, + KUROBOX_PRO_NAND_SIZE); + platform_device_register(&kurobox_pro_nand_flash); + } + + i2c_register_board_info(0, &kurobox_pro_i2c_rtc, 1); + + /* register Kurobox Pro specific power-off method */ + pm_power_off = kurobox_pro_power_off; +} + +#ifdef CONFIG_MACH_KUROBOX_PRO +MACHINE_START(KUROBOX_PRO, "Buffalo/Revogear Kurobox Pro") + /* Maintainer: Ronen Shitrit */ + .atag_offset = 0x100, + .nr_irqs = ORION5X_NR_IRQS, + .init_machine = kurobox_pro_init, + .map_io = orion5x_map_io, + .init_early = orion5x_init_early, + .init_irq = orion5x_init_irq, + .init_time = orion5x_timer_init, + .fixup = tag_fixup_mem32, + .restart = orion5x_restart, +MACHINE_END +#endif + +#ifdef CONFIG_MACH_LINKSTATION_PRO +MACHINE_START(LINKSTATION_PRO, "Buffalo Linkstation Pro/Live") + /* Maintainer: Byron Bradley */ + .atag_offset = 0x100, + .nr_irqs = ORION5X_NR_IRQS, + .init_machine = kurobox_pro_init, + .map_io = orion5x_map_io, + .init_early = orion5x_init_early, + .init_irq = orion5x_init_irq, + .init_time = orion5x_timer_init, + .fixup = tag_fixup_mem32, + .restart = orion5x_restart, +MACHINE_END +#endif diff --git a/arch/arm/mach-orion5x/ls_hgl-setup.c b/arch/arm/mach-orion5x/ls_hgl-setup.c new file mode 100644 index 000000000..af07f6174 --- /dev/null +++ b/arch/arm/mach-orion5x/ls_hgl-setup.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * arch/arm/mach-orion5x/ls_hgl-setup.c + * + * Maintainer: Zhu Qingsen + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "mpp.h" +#include "orion5x.h" + +/***************************************************************************** + * Linkstation LS-HGL Info + ****************************************************************************/ + +/* + * 256K NOR flash Device bus boot chip select + */ + +#define LS_HGL_NOR_BOOT_BASE 0xf4000000 +#define LS_HGL_NOR_BOOT_SIZE SZ_256K + +/***************************************************************************** + * 256KB NOR Flash on BOOT Device + ****************************************************************************/ + +static struct physmap_flash_data ls_hgl_nor_flash_data = { + .width = 1, +}; + +static struct resource ls_hgl_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = LS_HGL_NOR_BOOT_BASE, + .end = LS_HGL_NOR_BOOT_BASE + LS_HGL_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device ls_hgl_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &ls_hgl_nor_flash_data, + }, + .num_resources = 1, + .resource = &ls_hgl_nor_flash_resource, +}; + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data ls_hgl_eth_data = { + .phy_addr = 8, +}; + +/***************************************************************************** + * RTC 5C372a on I2C bus + ****************************************************************************/ + +static struct i2c_board_info __initdata ls_hgl_i2c_rtc = { + I2C_BOARD_INFO("rs5c372a", 0x32), +}; + +/***************************************************************************** + * LEDs attached to GPIO + ****************************************************************************/ + +#define LS_HGL_GPIO_LED_ALARM 2 +#define LS_HGL_GPIO_LED_INFO 3 +#define LS_HGL_GPIO_LED_FUNC 17 +#define LS_HGL_GPIO_LED_PWR 0 + + +static struct gpio_led ls_hgl_led_pins[] = { + { + .name = "alarm:red", + .gpio = LS_HGL_GPIO_LED_ALARM, + .active_low = 1, + }, { + .name = "info:amber", + .gpio = LS_HGL_GPIO_LED_INFO, + .active_low = 1, + }, { + .name = "func:blue:top", + .gpio = LS_HGL_GPIO_LED_FUNC, + .active_low = 1, + }, { + .name = "power:blue:bottom", + .gpio = LS_HGL_GPIO_LED_PWR, + }, +}; + +static struct gpio_led_platform_data ls_hgl_led_data = { + .leds = ls_hgl_led_pins, + .num_leds = ARRAY_SIZE(ls_hgl_led_pins), +}; + +static struct platform_device ls_hgl_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &ls_hgl_led_data, + }, +}; + +/**************************************************************************** + * GPIO Attached Keys + ****************************************************************************/ +#define LS_HGL_GPIO_KEY_FUNC 15 +#define LS_HGL_GPIO_KEY_POWER 8 +#define LS_HGL_GPIO_KEY_AUTOPOWER 10 + +#define LS_HGL_SW_POWER 0x00 +#define LS_HGL_SW_AUTOPOWER 0x01 + +static struct gpio_keys_button ls_hgl_buttons[] = { + { + .code = KEY_OPTION, + .gpio = LS_HGL_GPIO_KEY_FUNC, + .desc = "Function Button", + .active_low = 1, + }, { + .type = EV_SW, + .code = LS_HGL_SW_POWER, + .gpio = LS_HGL_GPIO_KEY_POWER, + .desc = "Power-on Switch", + .active_low = 1, + }, { + .type = EV_SW, + .code = LS_HGL_SW_AUTOPOWER, + .gpio = LS_HGL_GPIO_KEY_AUTOPOWER, + .desc = "Power-auto Switch", + .active_low = 1, + }, +}; + +static struct gpio_keys_platform_data ls_hgl_button_data = { + .buttons = ls_hgl_buttons, + .nbuttons = ARRAY_SIZE(ls_hgl_buttons), +}; + +static struct platform_device ls_hgl_button_device = { + .name = "gpio-keys", + .id = -1, + .num_resources = 0, + .dev = { + .platform_data = &ls_hgl_button_data, + }, +}; + + +/***************************************************************************** + * SATA + ****************************************************************************/ +static struct mv_sata_platform_data ls_hgl_sata_data = { + .n_ports = 2, +}; + + +/***************************************************************************** + * Linkstation LS-HGL specific power off method: reboot + ****************************************************************************/ +/* + * On the Linkstation LS-HGL, the shutdown process is following: + * - Userland monitors key events until the power switch goes to off position + * - The board reboots + * - U-boot starts and goes into an idle mode waiting for the user + * to move the switch to ON position + */ + +static void ls_hgl_power_off(void) +{ + orion5x_restart(REBOOT_HARD, NULL); +} + + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +#define LS_HGL_GPIO_USB_POWER 9 +#define LS_HGL_GPIO_AUTO_POWER 10 +#define LS_HGL_GPIO_POWER 8 + +#define LS_HGL_GPIO_HDD_POWER 1 + +static unsigned int ls_hgl_mpp_modes[] __initdata = { + MPP0_GPIO, /* LED_PWR */ + MPP1_GPIO, /* HDD_PWR */ + MPP2_GPIO, /* LED_ALARM */ + MPP3_GPIO, /* LED_INFO */ + MPP4_UNUSED, + MPP5_UNUSED, + MPP6_GPIO, /* FAN_LCK */ + MPP7_GPIO, /* INIT */ + MPP8_GPIO, /* POWER */ + MPP9_GPIO, /* USB_PWR */ + MPP10_GPIO, /* AUTO_POWER */ + MPP11_UNUSED, /* LED_ETH (dummy) */ + MPP12_UNUSED, + MPP13_UNUSED, + MPP14_UNUSED, + MPP15_GPIO, /* FUNC */ + MPP16_UNUSED, + MPP17_GPIO, /* LED_FUNC */ + MPP18_UNUSED, + MPP19_UNUSED, + 0, +}; + +static void __init ls_hgl_init(void) +{ + /* + * Setup basic Orion functions. Need to be called early. + */ + orion5x_init(); + + orion5x_mpp_conf(ls_hgl_mpp_modes); + + /* + * Configure peripherals. + */ + orion5x_ehci0_init(); + orion5x_ehci1_init(); + orion5x_eth_init(&ls_hgl_eth_data); + orion5x_i2c_init(); + orion5x_sata_init(&ls_hgl_sata_data); + orion5x_uart0_init(); + orion5x_xor_init(); + + mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET, + ORION_MBUS_DEVBUS_BOOT_ATTR, + LS_HGL_NOR_BOOT_BASE, + LS_HGL_NOR_BOOT_SIZE); + platform_device_register(&ls_hgl_nor_flash); + + platform_device_register(&ls_hgl_button_device); + + platform_device_register(&ls_hgl_leds); + + i2c_register_board_info(0, &ls_hgl_i2c_rtc, 1); + + /* enable USB power */ + gpio_set_value(LS_HGL_GPIO_USB_POWER, 1); + + /* register power-off method */ + pm_power_off = ls_hgl_power_off; + + pr_info("%s: finished\n", __func__); +} + +MACHINE_START(LINKSTATION_LS_HGL, "Buffalo Linkstation LS-HGL") + /* Maintainer: Zhu Qingsen */ + .atag_offset = 0x100, + .nr_irqs = ORION5X_NR_IRQS, + .init_machine = ls_hgl_init, + .map_io = orion5x_map_io, + .init_early = orion5x_init_early, + .init_irq = orion5x_init_irq, + .init_time = orion5x_timer_init, + .fixup = tag_fixup_mem32, + .restart = orion5x_restart, +MACHINE_END diff --git a/arch/arm/mach-orion5x/mpp.c b/arch/arm/mach-orion5x/mpp.c new file mode 100644 index 000000000..b9855dce6 --- /dev/null +++ b/arch/arm/mach-orion5x/mpp.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * arch/arm/mach-orion5x/mpp.c + * + * MPP functions for Marvell Orion 5x SoCs + */ + +#include +#include +#include +#include +#include "orion5x.h" +#include "mpp.h" +#include "common.h" + +static unsigned int __init orion5x_variant(void) +{ + u32 dev; + u32 rev; + + orion5x_pcie_id(&dev, &rev); + + if (dev == MV88F5181_DEV_ID) + return MPP_F5181_MASK; + + if (dev == MV88F5182_DEV_ID) + return MPP_F5182_MASK; + + if (dev == MV88F5281_DEV_ID) + return MPP_F5281_MASK; + + printk(KERN_ERR "MPP setup: unknown orion5x variant " + "(dev %#x rev %#x)\n", dev, rev); + return 0; +} + +void __init orion5x_mpp_conf(unsigned int *mpp_list) +{ + orion_mpp_conf(mpp_list, orion5x_variant(), + MPP_MAX, ORION5X_DEV_BUS_VIRT_BASE); +} diff --git a/arch/arm/mach-orion5x/mpp.h b/arch/arm/mach-orion5x/mpp.h new file mode 100644 index 000000000..be1c78663 --- /dev/null +++ b/arch/arm/mach-orion5x/mpp.h @@ -0,0 +1,130 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ARCH_ORION5X_MPP_H +#define __ARCH_ORION5X_MPP_H + +#define MPP(_num, _sel, _in, _out, _F5181l, _F5182, _F5281) ( \ + /* MPP number */ ((_num) & 0xff) | \ + /* MPP select value */ (((_sel) & 0xf) << 8) | \ + /* may be input signal */ ((!!(_in)) << 12) | \ + /* may be output signal */ ((!!(_out)) << 13) | \ + /* available on F5181l */ ((!!(_F5181l)) << 14) | \ + /* available on F5182 */ ((!!(_F5182)) << 15) | \ + /* available on F5281 */ ((!!(_F5281)) << 16)) + + /* num sel i o 5181 5182 5281 */ + +#define MPP_F5181_MASK MPP(0, 0x0, 0, 0, 1, 0, 0) +#define MPP_F5182_MASK MPP(0, 0x0, 0, 0, 0, 1, 0) +#define MPP_F5281_MASK MPP(0, 0x0, 0, 0, 0, 0, 1) + +#define MPP0_UNUSED MPP(0, 0x3, 0, 0, 1, 1, 1) +#define MPP0_GPIO MPP(0, 0x3, 1, 1, 1, 1, 1) +#define MPP0_PCIE_RST_OUTn MPP(0, 0x0, 0, 0, 1, 1, 1) +#define MPP0_PCI_ARB MPP(0, 0x2, 0, 0, 1, 1, 1) + +#define MPP1_UNUSED MPP(1, 0x0, 0, 0, 1, 1, 1) +#define MPP1_GPIO MPP(1, 0x0, 1, 1, 1, 1, 1) +#define MPP1_PCI_ARB MPP(1, 0x2, 0, 0, 1, 1, 1) + +#define MPP2_UNUSED MPP(2, 0x0, 0, 0, 1, 1, 1) +#define MPP2_GPIO MPP(2, 0x0, 1, 1, 1, 1, 1) +#define MPP2_PCI_ARB MPP(2, 0x2, 0, 0, 1, 1, 1) +#define MPP2_PCI_PMEn MPP(2, 0x3, 0, 0, 1, 1, 1) + +#define MPP3_UNUSED MPP(3, 0x0, 0, 0, 1, 1, 1) +#define MPP3_GPIO MPP(3, 0x0, 1, 1, 1, 1, 1) +#define MPP3_PCI_ARB MPP(3, 0x2, 0, 0, 1, 1, 1) + +#define MPP4_UNUSED MPP(4, 0x0, 0, 0, 1, 1, 1) +#define MPP4_GPIO MPP(4, 0x0, 1, 1, 1, 1, 1) +#define MPP4_PCI_ARB MPP(4, 0x2, 0, 0, 1, 1, 1) +#define MPP4_NAND MPP(4, 0x4, 0, 0, 0, 1, 1) +#define MPP4_SATA_LED MPP(4, 0x5, 0, 0, 0, 1, 0) + +#define MPP5_UNUSED MPP(5, 0x0, 0, 0, 1, 1, 1) +#define MPP5_GPIO MPP(5, 0x0, 1, 1, 1, 1, 1) +#define MPP5_PCI_ARB MPP(5, 0x2, 0, 0, 1, 1, 1) +#define MPP5_NAND MPP(5, 0x4, 0, 0, 0, 1, 1) +#define MPP5_SATA_LED MPP(5, 0x5, 0, 0, 0, 1, 0) + +#define MPP6_UNUSED MPP(6, 0x0, 0, 0, 1, 1, 1) +#define MPP6_GPIO MPP(6, 0x0, 1, 1, 1, 1, 1) +#define MPP6_PCI_ARB MPP(6, 0x2, 0, 0, 1, 1, 1) +#define MPP6_NAND MPP(6, 0x4, 0, 0, 0, 1, 1) +#define MPP6_PCI_CLK MPP(6, 0x5, 0, 0, 1, 0, 0) +#define MPP6_SATA_LED MPP(6, 0x5, 0, 0, 0, 1, 0) + +#define MPP7_UNUSED MPP(7, 0x0, 0, 0, 1, 1, 1) +#define MPP7_GPIO MPP(7, 0x0, 1, 1, 1, 1, 1) +#define MPP7_PCI_ARB MPP(7, 0x2, 0, 0, 1, 1, 1) +#define MPP7_NAND MPP(7, 0x4, 0, 0, 0, 1, 1) +#define MPP7_PCI_CLK MPP(7, 0x5, 0, 0, 1, 0, 0) +#define MPP7_SATA_LED MPP(7, 0x5, 0, 0, 0, 1, 0) + +#define MPP8_UNUSED MPP(8, 0x0, 0, 0, 1, 1, 1) +#define MPP8_GPIO MPP(8, 0x0, 1, 1, 1, 1, 1) +#define MPP8_GIGE MPP(8, 0x1, 0, 0, 1, 1, 1) + +#define MPP9_UNUSED MPP(9, 0x0, 0, 0, 1, 1, 1) +#define MPP9_GPIO MPP(9, 0x0, 1, 1, 1, 1, 1) +#define MPP9_GIGE MPP(9, 0x1, 0, 0, 1, 1, 1) + +#define MPP10_UNUSED MPP(10, 0x0, 0, 0, 1, 1, 1) +#define MPP10_GPIO MPP(10, 0x0, 1, 1, 1, 1, 1) +#define MPP10_GIGE MPP(10, 0x1, 0, 0, 1, 1, 1) + +#define MPP11_UNUSED MPP(11, 0x0, 0, 0, 1, 1, 1) +#define MPP11_GPIO MPP(11, 0x0, 1, 1, 1, 1, 1) +#define MPP11_GIGE MPP(11, 0x1, 0, 0, 1, 1, 1) + +#define MPP12_UNUSED MPP(12, 0x0, 0, 0, 1, 1, 1) +#define MPP12_GPIO MPP(12, 0x0, 1, 1, 1, 1, 1) +#define MPP12_GIGE MPP(12, 0x1, 0, 0, 1, 1, 1) +#define MPP12_NAND MPP(12, 0x4, 0, 0, 0, 1, 1) +#define MPP12_SATA_LED MPP(12, 0x5, 0, 0, 0, 1, 0) + +#define MPP13_UNUSED MPP(13, 0x0, 0, 0, 1, 1, 1) +#define MPP13_GPIO MPP(13, 0x0, 1, 1, 1, 1, 1) +#define MPP13_GIGE MPP(13, 0x1, 0, 0, 1, 1, 1) +#define MPP13_NAND MPP(13, 0x4, 0, 0, 0, 1, 1) +#define MPP13_SATA_LED MPP(13, 0x5, 0, 0, 0, 1, 0) + +#define MPP14_UNUSED MPP(14, 0x0, 0, 0, 1, 1, 1) +#define MPP14_GPIO MPP(14, 0x0, 1, 1, 1, 1, 1) +#define MPP14_GIGE MPP(14, 0x1, 0, 0, 1, 1, 1) +#define MPP14_NAND MPP(14, 0x4, 0, 0, 0, 1, 1) +#define MPP14_SATA_LED MPP(14, 0x5, 0, 0, 0, 1, 0) + +#define MPP15_UNUSED MPP(15, 0x0, 0, 0, 1, 1, 1) +#define MPP15_GPIO MPP(15, 0x0, 1, 1, 1, 1, 1) +#define MPP15_GIGE MPP(15, 0x1, 0, 0, 1, 1, 1) +#define MPP15_NAND MPP(15, 0x4, 0, 0, 0, 1, 1) +#define MPP15_SATA_LED MPP(15, 0x5, 0, 0, 0, 1, 0) + +#define MPP16_UNUSED MPP(16, 0x0, 0, 0, 1, 1, 1) +#define MPP16_GPIO MPP(16, 0x5, 1, 1, 0, 1, 0) +#define MPP16_GIGE MPP(16, 0x1, 0, 0, 1, 1, 1) +#define MPP16_NAND MPP(16, 0x4, 0, 0, 0, 1, 1) +#define MPP16_UART MPP(16, 0x0, 0, 0, 0, 1, 1) + +#define MPP17_UNUSED MPP(17, 0x0, 0, 0, 1, 1, 1) +#define MPP17_GPIO MPP(17, 0x5, 1, 1, 0, 1, 0) +#define MPP17_GIGE MPP(17, 0x1, 0, 0, 1, 1, 1) +#define MPP17_NAND MPP(17, 0x4, 0, 0, 0, 1, 1) +#define MPP17_UART MPP(17, 0x0, 0, 0, 0, 1, 1) + +#define MPP18_UNUSED MPP(18, 0x0, 0, 0, 1, 1, 1) +#define MPP18_GPIO MPP(18, 0x5, 1, 1, 0, 1, 0) +#define MPP18_GIGE MPP(18, 0x1, 0, 0, 1, 1, 1) +#define MPP18_UART MPP(18, 0x0, 0, 0, 0, 1, 1) + +#define MPP19_UNUSED MPP(19, 0x0, 0, 0, 1, 1, 1) +#define MPP19_GPIO MPP(19, 0x5, 1, 1, 0, 1, 0) +#define MPP19_GIGE MPP(19, 0x1, 0, 0, 1, 1, 1) +#define MPP19_UART MPP(19, 0x0, 0, 0, 0, 1, 1) + +#define MPP_MAX 19 + +void orion5x_mpp_conf(unsigned int *mpp_list); + +#endif diff --git a/arch/arm/mach-orion5x/mv2120-setup.c b/arch/arm/mach-orion5x/mv2120-setup.c new file mode 100644 index 000000000..2bf8ec75e --- /dev/null +++ b/arch/arm/mach-orion5x/mv2120-setup.c @@ -0,0 +1,243 @@ +/* + * Copyright (C) 2007 Herbert Valerio Riedel + * Copyright (C) 2008 Martin Michlmayr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "mpp.h" +#include "orion5x.h" + +#define MV2120_NOR_BOOT_BASE 0xf4000000 +#define MV2120_NOR_BOOT_SIZE SZ_512K + +#define MV2120_GPIO_RTC_IRQ 3 +#define MV2120_GPIO_KEY_RESET 17 +#define MV2120_GPIO_KEY_POWER 18 +#define MV2120_GPIO_POWER_OFF 19 + + +/***************************************************************************** + * Ethernet + ****************************************************************************/ +static struct mv643xx_eth_platform_data mv2120_eth_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +static struct mv_sata_platform_data mv2120_sata_data = { + .n_ports = 2, +}; + +static struct mtd_partition mv2120_partitions[] = { + { + .name = "firmware", + .size = 0x00080000, + .offset = 0, + }, +}; + +static struct physmap_flash_data mv2120_nor_flash_data = { + .width = 1, + .parts = mv2120_partitions, + .nr_parts = ARRAY_SIZE(mv2120_partitions) +}; + +static struct resource mv2120_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = MV2120_NOR_BOOT_BASE, + .end = MV2120_NOR_BOOT_BASE + MV2120_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device mv2120_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &mv2120_nor_flash_data, + }, + .resource = &mv2120_nor_flash_resource, + .num_resources = 1, +}; + +static struct gpio_keys_button mv2120_buttons[] = { + { + .code = KEY_RESTART, + .gpio = MV2120_GPIO_KEY_RESET, + .desc = "reset", + .active_low = 1, + }, { + .code = KEY_POWER, + .gpio = MV2120_GPIO_KEY_POWER, + .desc = "power", + .active_low = 1, + }, +}; + +static struct gpio_keys_platform_data mv2120_button_data = { + .buttons = mv2120_buttons, + .nbuttons = ARRAY_SIZE(mv2120_buttons), +}; + +static struct platform_device mv2120_button_device = { + .name = "gpio-keys", + .id = -1, + .num_resources = 0, + .dev = { + .platform_data = &mv2120_button_data, + }, +}; + + +/**************************************************************************** + * General Setup + ****************************************************************************/ +static unsigned int mv2120_mpp_modes[] __initdata = { + MPP0_GPIO, /* Sys status LED */ + MPP1_GPIO, /* Sys error LED */ + MPP2_GPIO, /* OverTemp interrupt */ + MPP3_GPIO, /* RTC interrupt */ + MPP4_GPIO, /* V_LED 5V */ + MPP5_GPIO, /* V_LED 3.3V */ + MPP6_UNUSED, + MPP7_UNUSED, + MPP8_GPIO, /* SATA 0 fail LED */ + MPP9_GPIO, /* SATA 1 fail LED */ + MPP10_UNUSED, + MPP11_UNUSED, + MPP12_SATA_LED, /* SATA 0 presence */ + MPP13_SATA_LED, /* SATA 1 presence */ + MPP14_SATA_LED, /* SATA 0 active */ + MPP15_SATA_LED, /* SATA 1 active */ + MPP16_UNUSED, + MPP17_GPIO, /* Reset button */ + MPP18_GPIO, /* Power button */ + MPP19_GPIO, /* Power off */ + 0, +}; + +static struct i2c_board_info __initdata mv2120_i2c_rtc = { + I2C_BOARD_INFO("pcf8563", 0x51), + .irq = 0, +}; + +static struct gpio_led mv2120_led_pins[] = { + { + .name = "mv2120:blue:health", + .gpio = 0, + }, + { + .name = "mv2120:red:health", + .gpio = 1, + }, + { + .name = "mv2120:led:bright", + .gpio = 4, + .default_trigger = "default-on", + }, + { + .name = "mv2120:led:dimmed", + .gpio = 5, + }, + { + .name = "mv2120:red:sata0", + .gpio = 8, + .active_low = 1, + }, + { + .name = "mv2120:red:sata1", + .gpio = 9, + .active_low = 1, + }, + +}; + +static struct gpio_led_platform_data mv2120_led_data = { + .leds = mv2120_led_pins, + .num_leds = ARRAY_SIZE(mv2120_led_pins), +}; + +static struct platform_device mv2120_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &mv2120_led_data, + } +}; + +static void mv2120_power_off(void) +{ + pr_info("%s: triggering power-off...\n", __func__); + gpio_set_value(MV2120_GPIO_POWER_OFF, 0); +} + +static void __init mv2120_init(void) +{ + /* Setup basic Orion functions. Need to be called early. */ + orion5x_init(); + + orion5x_mpp_conf(mv2120_mpp_modes); + + /* + * Configure peripherals. + */ + orion5x_ehci0_init(); + orion5x_ehci1_init(); + orion5x_eth_init(&mv2120_eth_data); + orion5x_i2c_init(); + orion5x_sata_init(&mv2120_sata_data); + orion5x_uart0_init(); + orion5x_xor_init(); + + mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET, + ORION_MBUS_DEVBUS_BOOT_ATTR, + MV2120_NOR_BOOT_BASE, + MV2120_NOR_BOOT_SIZE); + platform_device_register(&mv2120_nor_flash); + + platform_device_register(&mv2120_button_device); + + if (gpio_request(MV2120_GPIO_RTC_IRQ, "rtc") == 0) { + if (gpio_direction_input(MV2120_GPIO_RTC_IRQ) == 0) + mv2120_i2c_rtc.irq = gpio_to_irq(MV2120_GPIO_RTC_IRQ); + else + gpio_free(MV2120_GPIO_RTC_IRQ); + } + i2c_register_board_info(0, &mv2120_i2c_rtc, 1); + platform_device_register(&mv2120_leds); + + /* register mv2120 specific power-off method */ + if (gpio_request(MV2120_GPIO_POWER_OFF, "POWEROFF") != 0 || + gpio_direction_output(MV2120_GPIO_POWER_OFF, 1) != 0) + pr_err("mv2120: failed to setup power-off GPIO\n"); + pm_power_off = mv2120_power_off; +} + +/* Warning: HP uses a wrong mach-type (=526) in their bootloader */ +MACHINE_START(MV2120, "HP Media Vault mv2120") + /* Maintainer: Martin Michlmayr */ + .atag_offset = 0x100, + .nr_irqs = ORION5X_NR_IRQS, + .init_machine = mv2120_init, + .map_io = orion5x_map_io, + .init_early = orion5x_init_early, + .init_irq = orion5x_init_irq, + .init_time = orion5x_timer_init, + .fixup = tag_fixup_mem32, + .restart = orion5x_restart, +MACHINE_END diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c new file mode 100644 index 000000000..695cc683c --- /dev/null +++ b/arch/arm/mach-orion5x/net2big-setup.c @@ -0,0 +1,431 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * arch/arm/mach-orion5x/net2big-setup.c + * + * LaCie 2Big Network NAS setup + * + * Copyright (C) 2009 Simon Guinot + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "common.h" +#include "mpp.h" +#include "orion5x.h" + +/***************************************************************************** + * LaCie 2Big Network Info + ****************************************************************************/ + +/* + * 512KB NOR flash Device bus boot chip select + */ + +#define NET2BIG_NOR_BOOT_BASE 0xfff80000 +#define NET2BIG_NOR_BOOT_SIZE SZ_512K + +/***************************************************************************** + * 512KB NOR Flash on Boot Device + ****************************************************************************/ + +/* + * TODO: Check write support on flash MX29LV400CBTC-70G + */ + +static struct mtd_partition net2big_partitions[] = { + { + .name = "Full512kb", + .size = MTDPART_SIZ_FULL, + .offset = 0x00000000, + .mask_flags = MTD_WRITEABLE, + }, +}; + +static struct physmap_flash_data net2big_nor_flash_data = { + .width = 1, + .parts = net2big_partitions, + .nr_parts = ARRAY_SIZE(net2big_partitions), +}; + +static struct resource net2big_nor_flash_resource = { + .flags = IORESOURCE_MEM, + .start = NET2BIG_NOR_BOOT_BASE, + .end = NET2BIG_NOR_BOOT_BASE + + NET2BIG_NOR_BOOT_SIZE - 1, +}; + +static struct platform_device net2big_nor_flash = { + .name = "physmap-flash", + .id = 0, + .dev = { + .platform_data = &net2big_nor_flash_data, + }, + .num_resources = 1, + .resource = &net2big_nor_flash_resource, +}; + +/***************************************************************************** + * Ethernet + ****************************************************************************/ + +static struct mv643xx_eth_platform_data net2big_eth_data = { + .phy_addr = MV643XX_ETH_PHY_ADDR(8), +}; + +/***************************************************************************** + * I2C devices + ****************************************************************************/ + +/* + * i2c addr | chip | description + * 0x32 | Ricoh 5C372b | RTC + * 0x50 | HT24LC08 | eeprom (1kB) + */ +static struct i2c_board_info __initdata net2big_i2c_devices[] = { + { + I2C_BOARD_INFO("rs5c372b", 0x32), + }, { + I2C_BOARD_INFO("24c08", 0x50), + }, +}; + +/***************************************************************************** + * SATA + ****************************************************************************/ + +static struct mv_sata_platform_data net2big_sata_data = { + .n_ports = 2, +}; + +#define NET2BIG_GPIO_SATA_POWER_REQ 19 +#define NET2BIG_GPIO_SATA0_POWER 23 +#define NET2BIG_GPIO_SATA1_POWER 25 + +static void __init net2big_sata_power_init(void) +{ + int err; + + /* Configure GPIOs over MPP max number. */ + orion_gpio_set_valid(NET2BIG_GPIO_SATA0_POWER, 1); + orion_gpio_set_valid(NET2BIG_GPIO_SATA1_POWER, 1); + + err = gpio_request(NET2BIG_GPIO_SATA0_POWER, "SATA0 power status"); + if (err == 0) { + err = gpio_direction_input(NET2BIG_GPIO_SATA0_POWER); + if (err) + gpio_free(NET2BIG_GPIO_SATA0_POWER); + } + if (err) { + pr_err("net2big: failed to setup SATA0 power GPIO\n"); + return; + } + + err = gpio_request(NET2BIG_GPIO_SATA1_POWER, "SATA1 power status"); + if (err == 0) { + err = gpio_direction_input(NET2BIG_GPIO_SATA1_POWER); + if (err) + gpio_free(NET2BIG_GPIO_SATA1_POWER); + } + if (err) { + pr_err("net2big: failed to setup SATA1 power GPIO\n"); + goto err_free_1; + } + + err = gpio_request(NET2BIG_GPIO_SATA_POWER_REQ, "SATA power request"); + if (err == 0) { + err = gpio_direction_output(NET2BIG_GPIO_SATA_POWER_REQ, 0); + if (err) + gpio_free(NET2BIG_GPIO_SATA_POWER_REQ); + } + if (err) { + pr_err("net2big: failed to setup SATA power request GPIO\n"); + goto err_free_2; + } + + if (gpio_get_value(NET2BIG_GPIO_SATA0_POWER) && + gpio_get_value(NET2BIG_GPIO_SATA1_POWER)) { + return; + } + + /* + * SATA power up on both disk is done by pulling high the CPLD power + * request line. The 300ms delay is related to the CPLD clock and is + * needed to be sure that the CPLD has take into account the low line + * status. + */ + msleep(300); + gpio_set_value(NET2BIG_GPIO_SATA_POWER_REQ, 1); + pr_info("net2big: power up SATA hard disks\n"); + + return; + +err_free_2: + gpio_free(NET2BIG_GPIO_SATA1_POWER); +err_free_1: + gpio_free(NET2BIG_GPIO_SATA0_POWER); + + return; +} + +/***************************************************************************** + * GPIO LEDs + ****************************************************************************/ + +/* + * The power front LEDs (blue and red) and SATA red LEDs are controlled via a + * single GPIO line and are compatible with the leds-gpio driver. + * + * The SATA blue LEDs have some hardware blink capabilities which are detailed + * in the following array: + * + * SATAx blue LED | SATAx activity | LED state + * | | + * 0 | 0 | blink (rate 300ms) + * 1 | 0 | off + * ? | 1 | on + * + * Notes: The blue and the red front LED's can't be on at the same time. + * Blue LED have priority. + */ + +#define NET2BIG_GPIO_PWR_RED_LED 6 +#define NET2BIG_GPIO_PWR_BLUE_LED 16 +#define NET2BIG_GPIO_PWR_LED_BLINK_STOP 7 + +#define NET2BIG_GPIO_SATA0_RED_LED 11 +#define NET2BIG_GPIO_SATA1_RED_LED 10 + +#define NET2BIG_GPIO_SATA0_BLUE_LED 17 +#define NET2BIG_GPIO_SATA1_BLUE_LED 13 + +static struct gpio_led net2big_leds[] = { + { + .name = "net2big:red:power", + .gpio = NET2BIG_GPIO_PWR_RED_LED, + }, + { + .name = "net2big:blue:power", + .gpio = NET2BIG_GPIO_PWR_BLUE_LED, + }, + { + .name = "net2big:red:sata0", + .gpio = NET2BIG_GPIO_SATA0_RED_LED, + }, + { + .name = "net2big:red:sata1", + .gpio = NET2BIG_GPIO_SATA1_RED_LED, + }, +}; + +static struct gpio_led_platform_data net2big_led_data = { + .num_leds = ARRAY_SIZE(net2big_leds), + .leds = net2big_leds, +}; + +static struct platform_device net2big_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = &net2big_led_data, + }, +}; + +static void __init net2big_gpio_leds_init(void) +{ + int err; + + /* Stop initial CPLD slow red/blue blinking on power LED. */ + err = gpio_request(NET2BIG_GPIO_PWR_LED_BLINK_STOP, + "Power LED blink stop"); + if (err == 0) { + err = gpio_direction_output(NET2BIG_GPIO_PWR_LED_BLINK_STOP, 1); + if (err) + gpio_free(NET2BIG_GPIO_PWR_LED_BLINK_STOP); + } + if (err) + pr_err("net2big: failed to setup power LED blink GPIO\n"); + + /* + * Configure SATA0 and SATA1 blue LEDs to blink in relation with the + * hard disk activity. + */ + err = gpio_request(NET2BIG_GPIO_SATA0_BLUE_LED, + "SATA0 blue LED control"); + if (err == 0) { + err = gpio_direction_output(NET2BIG_GPIO_SATA0_BLUE_LED, 1); + if (err) + gpio_free(NET2BIG_GPIO_SATA0_BLUE_LED); + } + if (err) + pr_err("net2big: failed to setup SATA0 blue LED GPIO\n"); + + err = gpio_request(NET2BIG_GPIO_SATA1_BLUE_LED, + "SATA1 blue LED control"); + if (err == 0) { + err = gpio_direction_output(NET2BIG_GPIO_SATA1_BLUE_LED, 1); + if (err) + gpio_free(NET2BIG_GPIO_SATA1_BLUE_LED); + } + if (err) + pr_err("net2big: failed to setup SATA1 blue LED GPIO\n"); + + platform_device_register(&net2big_gpio_leds); +} + +/**************************************************************************** + * GPIO keys + ****************************************************************************/ + +#define NET2BIG_GPIO_PUSH_BUTTON 18 +#define NET2BIG_GPIO_POWER_SWITCH_ON 8 +#define NET2BIG_GPIO_POWER_SWITCH_OFF 9 + +#define NET2BIG_SWITCH_POWER_ON 0x1 +#define NET2BIG_SWITCH_POWER_OFF 0x2 + +static struct gpio_keys_button net2big_buttons[] = { + { + .type = EV_SW, + .code = NET2BIG_SWITCH_POWER_OFF, + .gpio = NET2BIG_GPIO_POWER_SWITCH_OFF, + .desc = "Power rocker switch (auto|off)", + .active_low = 0, + }, + { + .type = EV_SW, + .code = NET2BIG_SWITCH_POWER_ON, + .gpio = NET2BIG_GPIO_POWER_SWITCH_ON, + .desc = "Power rocker switch (on|auto)", + .active_low = 0, + }, + { + .type = EV_KEY, + .code = KEY_POWER, + .gpio = NET2BIG_GPIO_PUSH_BUTTON, + .desc = "Front Push Button", + .active_low = 0, + }, +}; + +static struct gpio_keys_platform_data net2big_button_data = { + .buttons = net2big_buttons, + .nbuttons = ARRAY_SIZE(net2big_buttons), +}; + +static struct platform_device net2big_gpio_buttons = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &net2big_button_data, + }, +}; + +/***************************************************************************** + * General Setup + ****************************************************************************/ + +static unsigned int net2big_mpp_modes[] __initdata = { + MPP0_GPIO, /* Raid mode (bit 0) */ + MPP1_GPIO, /* USB port 2 fuse (0 = Fail, 1 = Ok) */ + MPP2_GPIO, /* Raid mode (bit 1) */ + MPP3_GPIO, /* Board ID (bit 0) */ + MPP4_GPIO, /* Fan activity (0 = Off, 1 = On) */ + MPP5_GPIO, /* Fan fail detection */ + MPP6_GPIO, /* Red front LED (0 = Off, 1 = On) */ + MPP7_GPIO, /* Disable initial blinking on front LED */ + MPP8_GPIO, /* Rear power switch (on|auto) */ + MPP9_GPIO, /* Rear power switch (auto|off) */ + MPP10_GPIO, /* SATA 1 red LED (0 = Off, 1 = On) */ + MPP11_GPIO, /* SATA 0 red LED (0 = Off, 1 = On) */ + MPP12_GPIO, /* Board ID (bit 1) */ + MPP13_GPIO, /* SATA 1 blue LED blink control */ + MPP14_SATA_LED, + MPP15_SATA_LED, + MPP16_GPIO, /* Blue front LED control */ + MPP17_GPIO, /* SATA 0 blue LED blink control */ + MPP18_GPIO, /* Front button (0 = Released, 1 = Pushed ) */ + MPP19_GPIO, /* SATA{0,1} power On/Off request */ + 0, + /* 22: USB port 1 fuse (0 = Fail, 1 = Ok) */ + /* 23: SATA 0 power status */ + /* 24: Board power off */ + /* 25: SATA 1 power status */ +}; + +#define NET2BIG_GPIO_POWER_OFF 24 + +static void net2big_power_off(void) +{ + gpio_set_value(NET2BIG_GPIO_POWER_OFF, 1); +} + +static void __init net2big_init(void) +{ + /* + * Setup basic Orion functions. Need to be called early. + */ + orion5x_init(); + + orion5x_mpp_conf(net2big_mpp_modes); + + /* + * Configure peripherals. + */ + orion5x_ehci0_init(); + orion5x_ehci1_init(); + orion5x_eth_init(&net2big_eth_data); + orion5x_i2c_init(); + orion5x_uart0_init(); + orion5x_xor_init(); + + net2big_sata_power_init(); + orion5x_sata_init(&net2big_sata_data); + + mvebu_mbus_add_window_by_id(ORION_MBUS_DEVBUS_BOOT_TARGET, + ORION_MBUS_DEVBUS_BOOT_ATTR, + NET2BIG_NOR_BOOT_BASE, + NET2BIG_NOR_BOOT_SIZE); + platform_device_register(&net2big_nor_flash); + + platform_device_register(&net2big_gpio_buttons); + net2big_gpio_leds_init(); + + i2c_register_board_info(0, net2big_i2c_devices, + ARRAY_SIZE(net2big_i2c_devices)); + + orion_gpio_set_valid(NET2BIG_GPIO_POWER_OFF, 1); + + if (gpio_request(NET2BIG_GPIO_POWER_OFF, "power-off") == 0 && + gpio_direction_output(NET2BIG_GPIO_POWER_OFF, 0) == 0) + pm_power_off = net2big_power_off; + else + pr_err("net2big: failed to configure power-off GPIO\n"); + + pr_notice("net2big: Flash writing is not yet supported.\n"); +} + +/* Warning: LaCie use a wrong mach-type (0x20e=526) in their bootloader. */ +MACHINE_START(NET2BIG, "LaCie 2Big Network") + .atag_offset = 0x100, + .nr_irqs = ORION5X_NR_IRQS, + .init_machine = net2big_init, + .map_io = orion5x_map_io, + .init_early = orion5x_init_early, + .init_irq = orion5x_init_irq, + .init_time = orion5x_timer_init, + .fixup = tag_fixup_mem32, + .restart = orion5x_restart, +MACHINE_END diff --git a/arch/arm/mach-orion5x/orion5x.h b/arch/arm/mach-orion5x/orion5x.h new file mode 100644 index 000000000..26f1ccb8c --- /dev/null +++ b/arch/arm/mach-orion5x/orion5x.h @@ -0,0 +1,143 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Generic definitions of Orion SoC flavors: + * Orion-1, Orion-VoIP, Orion-NAS, Orion-2, and Orion-1-90. + * + * Maintainer: Tzachi Perelstein + */ + +#ifndef __ASM_ARCH_ORION5X_H +#define __ASM_ARCH_ORION5X_H + +#include "irqs.h" + +/***************************************************************************** + * Orion Address Maps + * + * phys + * e0000000 PCIe MEM space + * e8000000 PCI MEM space + * f0000000 PCIe WA space (Orion-1/Orion-NAS only) + * f1000000 on-chip peripheral registers + * f2000000 PCIe I/O space + * f2100000 PCI I/O space + * f2200000 SRAM dedicated for the crypto unit + * f4000000 device bus mappings (boot) + * fa000000 device bus mappings (cs0) + * fa800000 device bus mappings (cs2) + * fc000000 device bus mappings (cs0/cs1) + * + * virt phys size + * fec00000 f1000000 1M on-chip peripheral registers + * fee00000 f2000000 64K PCIe I/O space + * fee10000 f2100000 64K PCI I/O space + * fd000000 f0000000 16M PCIe WA space (Orion-1/Orion-NAS only) + ****************************************************************************/ +#define ORION5X_REGS_PHYS_BASE 0xf1000000 +#define ORION5X_REGS_VIRT_BASE IOMEM(0xfec00000) +#define ORION5X_REGS_SIZE SZ_1M + +#define ORION5X_PCIE_IO_PHYS_BASE 0xf2000000 +#define ORION5X_PCIE_IO_BUS_BASE 0x00000000 +#define ORION5X_PCIE_IO_SIZE SZ_64K + +#define ORION5X_PCI_IO_PHYS_BASE 0xf2100000 +#define ORION5X_PCI_IO_BUS_BASE 0x00010000 +#define ORION5X_PCI_IO_SIZE SZ_64K + +#define ORION5X_SRAM_PHYS_BASE (0xf2200000) +#define ORION5X_SRAM_SIZE SZ_8K + +/* Relevant only for Orion-1/Orion-NAS */ +#define ORION5X_PCIE_WA_PHYS_BASE 0xf0000000 +#define ORION5X_PCIE_WA_VIRT_BASE IOMEM(0xfd000000) +#define ORION5X_PCIE_WA_SIZE SZ_16M + +#define ORION5X_PCIE_MEM_PHYS_BASE 0xe0000000 +#define ORION5X_PCIE_MEM_SIZE SZ_128M + +#define ORION5X_PCI_MEM_PHYS_BASE 0xe8000000 +#define ORION5X_PCI_MEM_SIZE SZ_128M + +/******************************************************************************* + * Orion Registers Map + ******************************************************************************/ + +#define ORION5X_DDR_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x00000) +#define ORION5X_DDR_WINS_BASE (ORION5X_DDR_PHYS_BASE + 0x1500) +#define ORION5X_DDR_WINS_SZ (0x10) +#define ORION5X_DDR_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x00000) +#define ORION5X_DEV_BUS_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x10000) +#define ORION5X_DEV_BUS_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x10000) +#define ORION5X_DEV_BUS_REG(x) (ORION5X_DEV_BUS_VIRT_BASE + (x)) +#define GPIO_VIRT_BASE ORION5X_DEV_BUS_REG(0x0100) +#define SPI_PHYS_BASE (ORION5X_DEV_BUS_PHYS_BASE + 0x0600) +#define I2C_PHYS_BASE (ORION5X_DEV_BUS_PHYS_BASE + 0x1000) +#define UART0_PHYS_BASE (ORION5X_DEV_BUS_PHYS_BASE + 0x2000) +#define UART0_VIRT_BASE (ORION5X_DEV_BUS_VIRT_BASE + 0x2000) +#define UART1_PHYS_BASE (ORION5X_DEV_BUS_PHYS_BASE + 0x2100) +#define UART1_VIRT_BASE (ORION5X_DEV_BUS_VIRT_BASE + 0x2100) + +#define ORION5X_BRIDGE_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x20000) +#define ORION5X_BRIDGE_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x20000) +#define ORION5X_BRIDGE_WINS_BASE (ORION5X_BRIDGE_PHYS_BASE) +#define ORION5X_BRIDGE_WINS_SZ (0x80) + +#define ORION5X_PCI_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x30000) + +#define ORION5X_PCIE_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x40000) + +#define ORION5X_USB0_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x50000) +#define ORION5X_USB0_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x50000) + +#define ORION5X_XOR_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x60900) +#define ORION5X_XOR_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x60900) + +#define ORION5X_ETH_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x70000) +#define ORION5X_ETH_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x70000) + +#define ORION5X_SATA_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x80000) +#define ORION5X_SATA_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0x80000) + +#define ORION5X_CRYPTO_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0x90000) + +#define ORION5X_USB1_PHYS_BASE (ORION5X_REGS_PHYS_BASE + 0xa0000) +#define ORION5X_USB1_VIRT_BASE (ORION5X_REGS_VIRT_BASE + 0xa0000) + +/******************************************************************************* + * Device Bus Registers + ******************************************************************************/ +#define MPP_0_7_CTRL ORION5X_DEV_BUS_REG(0x000) +#define MPP_8_15_CTRL ORION5X_DEV_BUS_REG(0x004) +#define MPP_16_19_CTRL ORION5X_DEV_BUS_REG(0x050) +#define MPP_DEV_CTRL ORION5X_DEV_BUS_REG(0x008) +#define MPP_RESET_SAMPLE ORION5X_DEV_BUS_REG(0x010) +#define DEV_BANK_0_PARAM ORION5X_DEV_BUS_REG(0x45c) +#define DEV_BANK_1_PARAM ORION5X_DEV_BUS_REG(0x460) +#define DEV_BANK_2_PARAM ORION5X_DEV_BUS_REG(0x464) +#define DEV_BANK_BOOT_PARAM ORION5X_DEV_BUS_REG(0x46c) +#define DEV_BUS_CTRL ORION5X_DEV_BUS_REG(0x4c0) +#define DEV_BUS_INT_CAUSE ORION5X_DEV_BUS_REG(0x4d0) +#define DEV_BUS_INT_MASK ORION5X_DEV_BUS_REG(0x4d4) + +/******************************************************************************* + * Supported Devices & Revisions + ******************************************************************************/ +/* Orion-1 (88F5181) and Orion-VoIP (88F5181L) */ +#define MV88F5181_DEV_ID 0x5181 +#define MV88F5181_REV_B1 3 +#define MV88F5181L_REV_A0 8 +#define MV88F5181L_REV_A1 9 +/* Orion-NAS (88F5182) */ +#define MV88F5182_DEV_ID 0x5182 +#define MV88F5182_REV_A2 2 +/* Orion-2 (88F5281) */ +#define MV88F5281_DEV_ID 0x5281 +#define MV88F5281_REV_D0 4 +#define MV88F5281_REV_D1 5 +#define MV88F5281_REV_D2 6 +/* Orion-1-90 (88F6183) */ +#define MV88F6183_DEV_ID 0x6183 +#define MV88F6183_REV_B0 3 + +#endif diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c new file mode 100644 index 000000000..888fdc909 --- /dev/null +++ b/arch/arm/mach-orion5x/pci.c @@ -0,0 +1,601 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * arch/arm/mach-orion5x/pci.c + * + * PCI and PCIe functions for Marvell Orion System On Chip + * + * Maintainer: Tzachi Perelstein + */ + +#include +#include +#include +#include +#include