From 72b58f2eb12ad4aa0c59481d0911dc5e39180eb5 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Wed, 26 Nov 2014 09:00:08 +0000 Subject: add new target 'oxnas' This is the oxnas target previously developed at http://gitorious.org/openwrt-oxnas Basically, this consolidates the changes and addtionas from http://github.org/kref/linux-oxnas into a new OpenWrt hardware target 'oxnas' adding support for PLX Technology NAS7820/NAS7821/NAS7825/... formally known as Oxford Semiconductor OXE810SE/OXE815/OX820/... For now there are 4 supported boards: Cloud Engines Pogoplug V3 (without PCIe) fully supported Cloud Engines Pogoplug Pro (with PCIe) fully supported MitraStar STG-212 aka ZyXEL NSA-212, aka Medion Akoya P89625 / P89636 / P89626 / P89630, aka Medion MD 86407 / MD 86805 / MD 86517 / MD 86587 fully supported, see http://wiki.openwrt.org/toh/medion/md86587 Shuttle KD-20 partially supported (S-ATA driver lacks support for 2nd port) Signed-off-by: Daniel Golle SVN-Revision: 43388 --- .../oxnas/files/arch/arm/boot/dts/ox820-kd20.dts | 136 ++++++++ .../files/arch/arm/boot/dts/ox820-pogoplug-pro.dts | 86 ++++++ .../files/arch/arm/boot/dts/ox820-pogoplug-v3.dts | 83 +++++ .../oxnas/files/arch/arm/boot/dts/ox820-stg212.dts | 91 ++++++ .../linux/oxnas/files/arch/arm/boot/dts/ox820.dtsi | 342 +++++++++++++++++++++ .../oxnas/files/arch/arm/configs/ox820_defconfig | 104 +++++++ .../linux/oxnas/files/arch/arm/mach-oxnas/Kconfig | 24 ++ .../linux/oxnas/files/arch/arm/mach-oxnas/Makefile | 8 + .../oxnas/files/arch/arm/mach-oxnas/Makefile.boot | 2 + target/linux/oxnas/files/arch/arm/mach-oxnas/fiq.S | 87 ++++++ .../oxnas/files/arch/arm/mach-oxnas/headsmp.S | 27 ++ .../oxnas/files/arch/arm/mach-oxnas/hotplug.c | 112 +++++++ .../arch/arm/mach-oxnas/include/mach/hardware.h | 233 ++++++++++++++ .../files/arch/arm/mach-oxnas/include/mach/iomap.h | 33 ++ .../files/arch/arm/mach-oxnas/include/mach/irqs.h | 7 + .../files/arch/arm/mach-oxnas/include/mach/smp.h | 34 ++ .../files/arch/arm/mach-oxnas/include/mach/timex.h | 6 + .../arch/arm/mach-oxnas/include/mach/uncompress.h | 32 ++ .../files/arch/arm/mach-oxnas/include/mach/utils.h | 34 ++ .../oxnas/files/arch/arm/mach-oxnas/mach-ox820.c | 284 +++++++++++++++++ .../oxnas/files/arch/arm/mach-oxnas/platsmp.c | 315 +++++++++++++++++++ 21 files changed, 2080 insertions(+) create mode 100644 target/linux/oxnas/files/arch/arm/boot/dts/ox820-kd20.dts create mode 100644 target/linux/oxnas/files/arch/arm/boot/dts/ox820-pogoplug-pro.dts create mode 100644 target/linux/oxnas/files/arch/arm/boot/dts/ox820-pogoplug-v3.dts create mode 100644 target/linux/oxnas/files/arch/arm/boot/dts/ox820-stg212.dts create mode 100644 target/linux/oxnas/files/arch/arm/boot/dts/ox820.dtsi create mode 100644 target/linux/oxnas/files/arch/arm/configs/ox820_defconfig create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/Kconfig create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/Makefile create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/Makefile.boot create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/fiq.S create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/headsmp.S create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/hotplug.c create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/hardware.h create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/iomap.h create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/irqs.h create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/smp.h create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/timex.h create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/uncompress.h create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/utils.h create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/mach-ox820.c create mode 100644 target/linux/oxnas/files/arch/arm/mach-oxnas/platsmp.c (limited to 'target/linux/oxnas/files/arch') diff --git a/target/linux/oxnas/files/arch/arm/boot/dts/ox820-kd20.dts b/target/linux/oxnas/files/arch/arm/boot/dts/ox820-kd20.dts new file mode 100644 index 0000000000..e7ee5871c4 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/boot/dts/ox820-kd20.dts @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2014 Daniel Golle + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/dts-v1/; +#include "ox820.dtsi" + +/ { + model = "Shuttle KD20"; + + chosen { + bootargs = "console=ttyS0,115200n8 earlyprintk=serial"; + }; + + pcie-controller@47C00000 { + status = "okay"; + }; + + uart@44200000 { + status = "okay"; + }; + + sata@45900000 { + status = "okay"; + }; + + nand@41000000 { + status = "okay"; + + partition@0 { + label = "boot"; + reg = <0x00000000 0x00e00000>; + /*read-only;*/ + }; + + partition@e00000 { + label = "ubi"; + reg = <0x00e00000 0x07200000>; + }; + }; + + ethernet@40400000 { + status = "okay"; + snps,phy-addr = <1>; + phy-mode = "rgmii-id"; + }; + + ehci@40200100 { + status = "okay"; + }; + + i2c-gpio { + compatible = "i2c-gpio"; + gpios = <&GPIOB 9 0 &GPIOB 10 0>; + i2c-gpio,delay-us = <10>; + #address-cells = <1>; + #size-cells = <0>; + pcf8563: rtc@51 { + compatible = "nxp,pcf8563"; + reg = <0x51>; + }; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + power { + label = "power"; + gpios = <&GPIOA 10 1>; + linux,code = <116>; + }; + reset { + label = "reset"; + gpios = <&GPIOA 11 1>; + linux,code = <0x198>; + }; + eject1 { + label = "eject1"; + gpios = <&GPIOA 5 1>; + linux,code = <161>; + }; + eject2 { + label = "eject2"; + gpios = <&GPIOA 6 1>; + linux,code = <162>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + status { + label = "kd20:blue:status"; + gpios = <&GPIOB 16 0>; + }; + status2 { + label = "kd20:red:status"; + gpios = <&GPIOB 17 0>; + }; + hdd1blue { + label = "kd20:blue:hdd1"; + gpios = <&GPIOA 27 0>; + }; + hdd1red { + label = "kd20:red:hdd1"; + gpios = <&GPIOB 4 0>; + }; + hdd2blue { + label = "kd20:blue:hdd2"; + gpios = <&GPIOB 6 0>; + }; + hdd2red { + label = "kd20:red:hdd2"; + gpios = <&GPIOB 7 0>; + }; + usb { + label = "kd20:blue:usb"; + gpios = <&GPIOB 8 0>; + }; + buzzer { + label = "kd20:buzzer"; + gpios = <&GPIOB 11 0>; + }; + }; + + gpio-fan { + compatible = "gpio-fan"; + gpios = <&GPIOA 2 1>; + }; +}; diff --git a/target/linux/oxnas/files/arch/arm/boot/dts/ox820-pogoplug-pro.dts b/target/linux/oxnas/files/arch/arm/boot/dts/ox820-pogoplug-pro.dts new file mode 100644 index 0000000000..f3730c32a6 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/boot/dts/ox820-pogoplug-pro.dts @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2013 Ma Haijun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/dts-v1/; +#include "ox820.dtsi" + +/ { + model = "Pogoplug Pro"; + + chosen { + bootargs = "console=ttyS0,115200n8 earlyprintk=serial"; + }; + + pcie-controller@47C00000 { + status = "okay"; + }; + + uart@44200000 { + status = "okay"; + }; + + sata@45900000 { + status = "okay"; + }; + + nand@41000000 { + status = "okay"; + + partition@0 { + label = "boot"; + reg = <0x00000000 0x00e00000>; + /*read-only;*/ + }; + + partition@e00000 { + label = "ubi"; + reg = <0x00e00000 0x07200000>; + }; + }; + + ethernet@40400000 { + status = "okay"; + }; + + ehci@40200100 { + status = "okay"; + }; + + pinctrl { + leds { + pinctrl_leds: leds-0 { + plxtech,pins = + <0 2 0 0 /* MF_A2 */ + 1 16 0 0 /* MF_B16 */ + 1 17 0 0>; /* MF_B17 */ + }; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_leds>; + + blue { + label = "pogoplug:blue:internal"; + gpios = <&GPIOA 2 0>; + + }; + + orange { + label = "pogoplug:orange:usr"; + gpios = <&GPIOB 16 1>; + }; + + green { + label = "pogoplug:green:usr"; + gpios = <&GPIOB 17 1>; + }; + }; +}; diff --git a/target/linux/oxnas/files/arch/arm/boot/dts/ox820-pogoplug-v3.dts b/target/linux/oxnas/files/arch/arm/boot/dts/ox820-pogoplug-v3.dts new file mode 100644 index 0000000000..802913273b --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/boot/dts/ox820-pogoplug-v3.dts @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014 Daniel Golle + * Copyright (C) 2013 Ma Haijun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/dts-v1/; +#include "ox820.dtsi" + +/ { + model = "Pogoplug V3"; + + chosen { + bootargs = "console=ttyS0,115200n8 earlyprintk=serial"; + }; + + uart@44200000 { + status = "okay"; + }; + + sata@45900000 { + status = "okay"; + }; + + nand@41000000 { + status = "okay"; + + partition@0 { + label = "boot"; + reg = <0x00000000 0x00e00000>; + /*read-only;*/ + }; + + partition@e00000 { + label = "ubi"; + reg = <0x00e00000 0x07200000>; + }; + }; + + ethernet@40400000 { + status = "okay"; + }; + + ehci@40200100 { + status = "okay"; + }; + + pinctrl { + leds { + pinctrl_leds: leds-0 { + plxtech,pins = + <0 2 0 0 /* MF_A2 */ + 1 16 0 0 /* MF_B16 */ + 1 17 0 0>; /* MF_B17 */ + }; + }; + }; + + leds { + compatible = "gpio-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_leds>; + + blue { + label = "pogoplug:blue:internal"; + gpios = <&GPIOA 2 0>; + }; + + orange { + label = "pogoplug:orange:usr"; + gpios = <&GPIOB 16 1>; + }; + + green { + label = "pogoplug:green:usr"; + gpios = <&GPIOB 17 1>; + }; + }; + +}; diff --git a/target/linux/oxnas/files/arch/arm/boot/dts/ox820-stg212.dts b/target/linux/oxnas/files/arch/arm/boot/dts/ox820-stg212.dts new file mode 100644 index 0000000000..5d838065ce --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/boot/dts/ox820-stg212.dts @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2013 OpenWrt.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/dts-v1/; + +#include "ox820.dtsi" + +/ { + model = "MitraStar Technology Corp. STG-212"; + + chosen { + bootargs = "console=ttyS0,115200n8 earlyprintk=serial"; + }; + + uart@44200000 { + status = "okay"; + }; + + sata@45900000 { + status = "okay"; + }; + + nand@41000000 { + status = "okay"; + + partition@0 { + label = "boot"; + reg = <0x00000000 0x00e00000>; + /*read-only;*/ + }; + + partition@e00000 { + label = "ubi"; + reg = <0x00e00000 0x07200000>; + }; + }; + + ethernet@40400000 { + status = "okay"; + }; + + ehci@40200100 { + status = "okay"; + }; + + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <100>; + + reset { + label = "reset"; + gpios = <&GPIOB 11 1>; + linux,code = <0x198>; + }; + copy { + label = "copy"; + gpios = <&GPIOB 13 1>; + linux,code = <0x85>; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + status { + label = "zyxel:blue:status"; + gpios = <&GPIOB 5 0>; + }; + status2 { + label = "zyxel:red:status"; + gpios = <&GPIOB 6 1>; + }; + copy { + label = "zyxel:orange:copy"; + gpios = <&GPIOB 8 1>; + }; + }; + + i2c-gpio { + compatible = "i2c-gpio"; + gpios = <&GPIOB 9 0 &GPIOB 10 0>; + i2c-gpio,delay-us = <10>; + }; + +}; diff --git a/target/linux/oxnas/files/arch/arm/boot/dts/ox820.dtsi b/target/linux/oxnas/files/arch/arm/boot/dts/ox820.dtsi new file mode 100644 index 0000000000..0a643a4e81 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/boot/dts/ox820.dtsi @@ -0,0 +1,342 @@ +/* + * Copyright (C) 2013 Ma Haijun + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/include/ "skeleton.dtsi" + +/ { + compatible = "plxtech,nas7820", "plxtech,nas782x"; + interrupt-parent = <&gic>; + + aliases { + serial0 = &uart0; + /* alias to determine bank index */ + gpio0 = &GPIOA; + gpio1 = &GPIOB; + + ethernet0 = &gmac; + }; + + cpus { + cpu@0 { + compatible = "arm,arm11mpcore"; + }; + cpu@1 { + compatible = "arm,arm11mpcore"; + }; + }; + + gic: gic@47001000 { + compatible = "arm,arm11mp-gic"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x47001000 0x1000>, + <0x47000100 0x0100>; + }; + + rst: reset-controller@44E00034 { + compatible = "plxtech,nas782x-reset"; + #reset-cells = <1>; + reg = <0x44E00034 0x8>; /* currently not used */ + }; + + rps: rps@44400000 { + compatible = "plxtech,nas782x-rps"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x44400000 0x14>; + interrupts = <0 5 0x304>; + }; + + /* external oscillator */ + osc: oscillator { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + }; + + sysclk: sysclk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clock-div = <4>; + clock-mult = <1>; + clocks = <&osc>; + }; + + plla: plla@44e001f0 { + compatible = "plxtech,nas782x-plla"; + #clock-cells = <0>; + clocks = <&osc>; + reg = <0x44e001f0 0x10>; + }; + + pllb: pllb@44f001f0 { + compatible = "plxtech,nas782x-pllb"; + #clock-cells = <0>; + clocks = <&osc>; + reg = <0x44f001f0 0x10>; + resets = <&rst 31>; + }; + + stdclk: stdclk { + compatible = "plxtech,nas782x-stdclk"; + #clock-cells = <1>; + clocks = <&osc>; + }; + + twdclk: twdclk { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + clocks = <&plla>; + }; + + gmacclk: gmacclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <125000000>; + }; + + pinctrl { + /* act as a simple bus, so children will be probed automatically */ + #address-cells = <1>; + #size-cells = <1>; + compatible = "plxtech,nas782x-pinctrl", "simple-bus"; + ranges; + + plxtech,mux-mask = < + 0xFFFFFFFF 0xCC0FFDF9 0xFC000E60 0x0F03F7E0 0xF00C0FE0 + 0x0003FFFF 0x00037FFF 0x0003FFF8 0x00000F00 0x0003F7F3 + >; + + GPIOA: gpio@44000000 { + compatible = "plxtech,nas782x-gpio"; + reg = <0x44000000 0x100>, <0x44E00000 0x200>; + interrupts = <0 21 0x304>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + #gpio-lines = <32>; /* real gpio pin count */ + }; + + GPIOB: gpio@44100000 { + compatible = "plxtech,nas782x-gpio"; + reg = <0x44100000 0x100>, <0x44F00000 0x200>; + interrupts = <0 22 0x304>; + #gpio-cells = <2>; + gpio-controller; + interrupt-controller; + #interrupt-cells = <2>; + #gpio-lines = <18>; /* real gpio pin count */ + }; + + uart0 { + pinctrl_uart0: uart0-0 { + plxtech,pins = + <0 30 5 0 /* MF_A30 PINMUX_ALT PINMUX_UARTA_SIN */ + 0 31 5 0>; /* MF_A31 PINMUX_ALT PINMUX_UARTA_SOUT */ + }; + }; + + gmac0 { + pinctrl_gmac0: gmac0-0 { + plxtech,pins = + <0 3 1 0 /* MF_A3 PINMUX_2 PINMUX_MACA_MDC */ + 0 4 1 0>; /* MF_A4 PINMUX_2 PINMUX_MACA_MDIO */ + }; + }; + + nand0 { + pinctrl_nand0: nand0-0 { + plxtech,pins = + <0 12 1 0 /* MF_A12 PINMUX_2 PINMUX_STATIC_DATA0 */ + 0 13 1 0 /* MF_A13 PINMUX_2 PINMUX_STATIC_DATA1 */ + 0 14 1 0 /* MF_A14 PINMUX_2 PINMUX_STATIC_DATA2 */ + 0 15 1 0 /* MF_A15 PINMUX_2 PINMUX_STATIC_DATA3 */ + 0 16 1 0 /* MF_A16 PINMUX_2 PINMUX_STATIC_DATA4 */ + 0 17 1 0 /* MF_A17 PINMUX_2 PINMUX_STATIC_DATA5 */ + 0 18 1 0 /* MF_A18 PINMUX_2 PINMUX_STATIC_DATA6 */ + 0 19 1 0 /* MF_A19 PINMUX_2 PINMUX_STATIC_DATA7 */ + + 0 20 1 0 /* MF_A20 PINMUX_2 PINMUX_STATIC_NWE */ + 0 21 1 0 /* MF_A21 PINMUX_2 PINMUX_STATIC_NOE */ + 0 22 1 0 /* MF_A22 PINMUX_2 PINMUX_STATIC_NCS */ + 0 23 1 0 /* MF_A23 PINMUX_2 PINMUX_STATIC_ADDR18 */ + 0 24 1 0>; /* MF_A24 PINMUX_2 PINMUX_STATIC_ADDR19 */ + }; + }; + }; + + pcie-controller@47C00000 { + compatible = "plxtech,nas782x-pcie"; + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + + /* flag & space bus address host address size */ + ranges = < 0x82000000 0 0x48000000 0x48000000 0 0x2000000 + 0xC2000000 0 0x4A000000 0x4A000000 0 0x1E00000 + 0x81000000 0 0x4BE00000 0x4BE00000 0 0x0100000 + 0x80000000 0 0x4BF00000 0x4BF00000 0 0x0100000>; + + bus-range = <0x00 0x7f>; + + /* cfg inbound translator phy*/ + reg = <0x47C00000 0x1000>, <0x47D00000 0x100>, <0x44A00000 0x10>; + + #interrupt-cells = <1>; + /* wild card mask, match all bus address & interrupt specifier */ + /* format: bus address mask, interrupt specifier mask */ + /* each bit 1 means need match, 0 means ignored when match */ + interrupt-map-mask = <0 0 0 0>; + /* format: a list of: bus address, interrupt specifier, + * parent interrupt controller & specifier */ + interrupt-map = <0 0 0 0 &gic 0 19 0x304>; + + gpios = <&GPIOB 12 0>; + clocks = <&stdclk 8>, <&pllb>; + clock-names = "pcie", "busclk"; + resets = <&rst 7>, <&rst 14>; + reset-names = "pcie", "phy"; + + plxtech,pcie-hcsl-bit = <2>; + plxtech,pcie-ctrl-offset = <0x120>; + plxtech,pcie-outbound-offset = <0x138>; + status = "disabled"; + }; + + pcie-controller@47E00000 { + compatible = "plxtech,nas782x-pcie"; + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + + /* flag & space bus address host address size */ + ranges = < 0x82000000 0 0x4C000000 0x4C000000 0 0x2000000 + 0xC2000000 0 0x4E000000 0x4E000000 0 0x1E00000 + 0x81000000 0 0x4FE00000 0x4FE00000 0 0x0100000 + 0x80000000 0 0x4FF00000 0x4FF00000 0 0x0100000>; + + bus-range = <0x80 0xff>; + + /* cfg inbound translator phy*/ + reg = <0x47E00000 0x1000>, <0x47F00000 0x100>, <0x44A00000 0x10>; + + #interrupt-cells = <1>; + /* wild card mask, match all bus address & interrupt specifier */ + /* format: bus address mask, interrupt specifier mask */ + /* each bit 1 means need match, 0 means ignored when match */ + interrupt-map-mask = <0 0 0 0>; + /* format: a list of: bus address, interrupt specifier, + * parent interrupt controller & specifier */ + interrupt-map = <0 0 0 0 &gic 0 20 0x304>; + + /* gpios = <&GPIOB 12 0>; */ + clocks = <&stdclk 11>, <&pllb>; + clock-names = "pcie", "busclk"; + resets = <&rst 23>, <&rst 14>; + reset-names = "pcie", "phy"; + + plxtech,pcie-hcsl-bit = <3>; + plxtech,pcie-ctrl-offset = <0x124>; + plxtech,pcie-outbound-offset = <0x174>; + status = "disabled"; + }; + + local-timer@47000600 { + compatible = "arm,arm11mp-twd-timer"; + reg = <0x47000600 0x20>; + interrupts = <1 13 0x304>; /* percpu, irq 29, cpu mask 3, level high */ + clocks = <&twdclk>; + }; + + watchdog@47000620 { + compatible = "mpcore_wdt"; + reg = <0x47000620 0x20>; + interrupts = <1 14 0x304>; /* percpu, irq 30, cpu mask 3, level high */ + clocks = <&twdclk>; + }; + + timer@44400200 { + compatible = "plxtech,nas782x-rps-timer"; + reg = <0x44400200 0x40>; + clocks = <&sysclk>; + }; + + uart0: uart@44200000 { + compatible = "ns16550a"; + reg = <0x44200000 0x100>; + clock-frequency = <6250000>; + interrupts = <0 23 0x304>; + reg-shift = <0>; + fifo-size = <16>; + reg-io-width = <1>; + current-speed = <115200>; + no-loopback-test; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart0>; + status = "disabled"; + }; + + sata@45900000 { + compatible = "plxtech,nas782x-sata"; + /* port sgdma core */ + reg = <0x45900000 0x100>, <0x459B0000 0x10>, <0x459E0000 0x2000>, + /* phy descriptors (optional) */ + <0x44900000 0x0C>, <0x50000000 0x1000>; + interrupts = <0 18 0x304>; + clocks = <&stdclk 4>; + resets = <&rst 11>, <&rst 12>, <&rst 13>; + reset-names = "sata", "link", "phy"; + status = "disabled"; + }; + + nand@41000000 { + compatible = "plxtech,nand-nas782x", "gen_nand"; + reg = <0x41000000 0x100000>, <0x41C00000 0x20>; + nand-ecc-mode = "soft"; + clocks = <&stdclk 9>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_nand0>; + resets = <&rst 15>; + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; + }; + + gmac: ethernet@40400000 { + compatible = "plxtech,nas782x-gmac", "snps,dwmac"; + reg = <0x40400000 0x2000>; + interrupts = <0 8 0x304>, <0 17 0x304>; + interrupt-names = "macirq", "eth_wake_irq"; + mac-address = [000000000000]; /* Filled in by U-Boot */ + phy-mode = "rgmii"; + clocks = <&stdclk 7>, <&gmacclk>; + clock-names = "gmac", "stmmaceth"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gmac0>; + resets = <&rst 6>; + status = "disabled"; + }; + + ehci@40200100 { + compatible = "plxtech,nas782x-ehci"; + reg = <0x40200100 0xf00>; + interrupts = <0 7 0x304>; + clocks = <&stdclk 6>, <&pllb>, <&stdclk 12>; + clock-names = "usb", "refsrc", "phyref"; + resets = <&rst 4>, <&rst 5>, <&rst 26>; + reset-names = "host", "phya", "phyb"; + /* Otherwise ref300 is used, which is derived from sata phy + * in that case, usb depends on sata initialization */ + /* FIXME: how to make this dependency explicit ? */ + plxtch,ehci_use_pllb; + status = "disabled"; + }; +}; diff --git a/target/linux/oxnas/files/arch/arm/configs/ox820_defconfig b/target/linux/oxnas/files/arch/arm/configs/ox820_defconfig new file mode 100644 index 0000000000..bb0a9d68a8 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/configs/ox820_defconfig @@ -0,0 +1,104 @@ +CONFIG_CROSS_COMPILE="arm-linux-gnueabi-" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_IRQ_TIME_ACCOUNTING=y +CONFIG_CGROUPS=y +CONFIG_NAMESPACES=y +CONFIG_EMBEDDED=y +# CONFIG_COMPAT_BRK is not set +CONFIG_JUMP_LABEL=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_ARCH_OXNAS=y +# CONFIG_DMA_CACHE_RWFO is not set +CONFIG_DMA_CACHE_FIQ_BROADCAST=y +CONFIG_PCI=y +CONFIG_PCI_OXNAS=y +CONFIG_SMP=y +# CONFIG_SMP_ON_UP is not set +CONFIG_NR_CPUS=2 +CONFIG_HOTPLUG_CPU=y +CONFIG_AEABI=y +# CONFIG_OABI_COMPAT is not set +CONFIG_UACCESS_WITH_MEMCPY=y +CONFIG_USE_OF=y +CONFIG_BINFMT_MISC=y +# CONFIG_SUSPEND is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IPV6=y +CONFIG_CFG80211=y +CONFIG_MAC80211=y +CONFIG_MAC80211_RC_PID=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_OXNAS=y +CONFIG_MTD_UBI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_MULTI_LUN=y +CONFIG_ATA=y +CONFIG_SATA_OXNAS=y +CONFIG_NETDEVICES=y +CONFIG_STMMAC_ETH=y +CONFIG_STMMAC_DEBUG_FS=y +CONFIG_STMMAC_DA=y +CONFIG_ATH_CARDS=y +CONFIG_ATH9K=y +CONFIG_ATH9K_LEGACY_RATE_CONTROL=y +# CONFIG_RTL_CARDS is not set +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=1 +CONFIG_SERIAL_8250_RUNTIME_UARTS=1 +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_GPIO_SYSFS=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_OXNAS=y +CONFIG_USB_STORAGE=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_COMMON_CLK_DEBUG=y +CONFIG_EXT2_FS=y +CONFIG_EXT4_FS=y +CONFIG_FUSE_FS=y +CONFIG_VFAT_FS=y +CONFIG_NTFS_FS=m +CONFIG_NTFS_RW=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_UBIFS_FS=y +CONFIG_NFS_FS=y +CONFIG_ROOT_NFS=y +CONFIG_PRINTK_TIME=y +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +# CONFIG_FTRACE is not set +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_LL=y +CONFIG_DEBUG_LL_UART_8250=y +CONFIG_DEBUG_UART_PHYS=0x44200000 +CONFIG_DEBUG_UART_VIRT=0xF0000000 +CONFIG_DEBUG_UART_8250_SHIFT=0 +CONFIG_EARLY_PRINTK=y +CONFIG_CRYPTO_ANSI_CPRNG=y diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/Kconfig b/target/linux/oxnas/files/arch/arm/mach-oxnas/Kconfig new file mode 100644 index 0000000000..eb96f1b74c --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/Kconfig @@ -0,0 +1,24 @@ +choice + prompt "Oxnas platform type" + default MACH_OXNAS + depends on ARCH_OXNAS + +config MACH_OX820 + bool "Generic NAS7820 Support" + select ARM_GIC + select GENERIC_CLOCKEVENTS + select CPU_V6K + select HAVE_ARM_SCU if SMP + select HAVE_ARM_TWD if SMP + select HAVE_SMP + select PLXTECH_RPS + select CLKSRC_OF + select CLKSRC_RPS_TIMER + select USB_ARCH_HAS_EHCI + select PINCTRL_OXNAS + select PINCTRL + select RESET_CONTROLLER_OXNAS + help + Include support for the ox820 platform. + +endchoice diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/Makefile b/target/linux/oxnas/files/arch/arm/mach-oxnas/Makefile new file mode 100644 index 0000000000..6862c34981 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the linux kernel. +# + +obj-$(CONFIG_MACH_OX820) += mach-ox820.o +obj-$(CONFIG_SMP) += platsmp.o headsmp.o +obj-$(CONFIG_DMA_CACHE_FIQ_BROADCAST) += fiq.o +obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/Makefile.boot b/target/linux/oxnas/files/arch/arm/mach-oxnas/Makefile.boot new file mode 100644 index 0000000000..b52e473d64 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/Makefile.boot @@ -0,0 +1,2 @@ + zreladdr-y += 0x60008000 +params_phys-y := 0x60000100 diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/fiq.S b/target/linux/oxnas/files/arch/arm/mach-oxnas/fiq.S new file mode 100644 index 0000000000..6acd5a7394 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/fiq.S @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2012 Gateworks Corporation + * Chris Lang + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +#define D_CACHE_LINE_SIZE 32 + + .text + +/* + * R8 - DMA Start Address + * R9 - DMA Length + * R10 - DMA Direction + * R11 - DMA type + * R12 - fiq_buffer Address +*/ + + .global ox820_fiq_end +ENTRY(ox820_fiq_start) + str r8, [r13] + + ldmia r12, {r8, r9, r10} + and r11, r10, #0x3000000 + and r10, r10, #0xff + + teq r11, #0x1000000 + beq ox820_dma_map_area + teq r11, #0x2000000 + beq ox820_dma_unmap_area + /* fall through */ +ox820_dma_flush_range: + bic r8, r8, #D_CACHE_LINE_SIZE - 1 +1: + mcr p15, 0, r8, c7, c14, 1 @ clean & invalidate D line + add r8, r8, #D_CACHE_LINE_SIZE + cmp r8, r9 + blo 1b + /* fall through */ +ox820_fiq_exit: + mov r8, #0 + str r8, [r12, #8] + mcr p15, 0, r8, c7, c10, 4 @ drain write buffer + subs pc, lr, #4 + +ox820_dma_map_area: + add r9, r9, r8 + teq r10, #DMA_FROM_DEVICE + beq ox820_dma_inv_range + teq r10, #DMA_TO_DEVICE + bne ox820_dma_flush_range + /* fall through */ +ox820_dma_clean_range: + bic r8, r8, #D_CACHE_LINE_SIZE - 1 +1: + mcr p15, 0, r8, c7, c10, 1 @ clean D line + add r8, r8, #D_CACHE_LINE_SIZE + cmp r8, r9 + blo 1b + b ox820_fiq_exit + +ox820_dma_unmap_area: + add r9, r9, r8 + teq r10, #DMA_TO_DEVICE + beq ox820_fiq_exit + /* fall through */ +ox820_dma_inv_range: + tst r8, #D_CACHE_LINE_SIZE - 1 + bic r8, r8, #D_CACHE_LINE_SIZE - 1 + mcrne p15, 0, r8, c7, c10, 1 @ clean D line + tst r9, #D_CACHE_LINE_SIZE - 1 + bic r9, r9, #D_CACHE_LINE_SIZE - 1 + mcrne p15, 0, r9, c7, c14, 1 @ clean & invalidate D line +1: + mcr p15, 0, r8, c7, c6, 1 @ invalidate D line + add r8, r8, #D_CACHE_LINE_SIZE + cmp r8, r9 + blo 1b + b ox820_fiq_exit + +ox820_fiq_end: diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/headsmp.S b/target/linux/oxnas/files/arch/arm/mach-oxnas/headsmp.S new file mode 100644 index 0000000000..a63edae62b --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/headsmp.S @@ -0,0 +1,27 @@ +/* + * linux/arch/arm/mach-ox820/headsmp.S + * + * Copyright (c) 2003 ARM Limited + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include + + __INIT + +/* + * OX820 specific entry point for secondary CPUs. + */ +ENTRY(ox820_secondary_startup) + mov r4, #0 + /* invalidate both caches and branch target cache */ + mcr p15, 0, r4, c7, c7, 0 + /* + * we've been released from the holding pen: secondary_stack + * should now contain the SVC stack for this core + */ + b secondary_startup diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/hotplug.c b/target/linux/oxnas/files/arch/arm/mach-oxnas/hotplug.c new file mode 100644 index 0000000000..861beee7b3 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/hotplug.c @@ -0,0 +1,112 @@ +/* + * linux/arch/arm/mach-realview/hotplug.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +#include +#include +#include + +static inline void cpu_enter_lowpower(void) +{ + unsigned int v; + + asm volatile( + " mcr p15, 0, %1, c7, c5, 0\n" + " mcr p15, 0, %1, c7, c10, 4\n" + /* + * Turn off coherency + */ + " mrc p15, 0, %0, c1, c0, 1\n" + " bic %0, %0, #0x20\n" + " mcr p15, 0, %0, c1, c0, 1\n" + " mrc p15, 0, %0, c1, c0, 0\n" + " bic %0, %0, %2\n" + " mcr p15, 0, %0, c1, c0, 0\n" + : "=&r" (v) + : "r" (0), "Ir" (CR_C) + : "cc"); +} + +static inline void cpu_leave_lowpower(void) +{ + unsigned int v; + + asm volatile("mrc p15, 0, %0, c1, c0, 0\n" + " orr %0, %0, %1\n" + " mcr p15, 0, %0, c1, c0, 0\n" + " mrc p15, 0, %0, c1, c0, 1\n" + " orr %0, %0, #0x20\n" + " mcr p15, 0, %0, c1, c0, 1\n" + : "=&r" (v) + : "Ir" (CR_C) + : "cc"); +} + +static inline void platform_do_lowpower(unsigned int cpu, int *spurious) +{ + /* + * there is no power-control hardware on this platform, so all + * we can do is put the core into WFI; this is safe as the calling + * code will have already disabled interrupts + */ + for (;;) { + /* + * here's the WFI + */ + asm(".word 0xe320f003\n" + : + : + : "memory", "cc"); + + if (read_pen_release() == cpu_logical_map(cpu)) { + /* + * OK, proper wakeup, we're done + */ + break; + } + + /* + * Getting here, means that we have come out of WFI without + * having been woken up - this shouldn't happen + * + * Just note it happening - when we're woken, we can report + * its occurrence. + */ + (*spurious)++; + } +} + +/* + * platform-specific code to shutdown a CPU + * + * Called with IRQs disabled + */ +void __ref ox820_cpu_die(unsigned int cpu) +{ + int spurious = 0; + + /* + * we're ready for shutdown now, so do it + */ + cpu_enter_lowpower(); + platform_do_lowpower(cpu, &spurious); + + /* + * bring this CPU back into the world of cache + * coherency, and then restore interrupts + */ + cpu_leave_lowpower(); + + if (spurious) + pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious); +} diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/hardware.h b/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/hardware.h new file mode 100644 index 0000000000..caae772c31 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/hardware.h @@ -0,0 +1,233 @@ +/* + * arch/arm/mach-0x820/include/mach/hardware.h + * + * Copyright (C) 2009 Oxford Semiconductor Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_ARCH_HARDWARE_H +#define __ASM_ARCH_HARDWARE_H + +#include +#include + +/* + * Location of flags and vectors in SRAM for controlling the booting of the + * secondary ARM11 processors. + */ + +#define OXNAS_SCU_BASE_VA OXNAS_PERCPU_BASE_VA +#define OXNAS_GICN_BASE_VA(n) (OXNAS_PERCPU_BASE_VA + 0x200 + n*0x100) + +#define HOLDINGPEN_CPU IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xc8) +#define HOLDINGPEN_LOCATION IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xc4) + +/** + * System block reset and clock control + */ +#define SYS_CTRL_PCI_STAT IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x20) +#define SYSCTRL_CLK_STAT IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x24) +#define SYS_CTRL_CLK_SET_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x2C) +#define SYS_CTRL_CLK_CLR_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x30) +#define SYS_CTRL_RST_SET_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x34) +#define SYS_CTRL_RST_CLR_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x38) + +#define SYS_CTRL_PLLSYS_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x48) +#define SYS_CTRL_CLK_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x64) +#define SYS_CTRL_PLLSYS_KEY_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x6C) +#define SYS_CTRL_GMAC_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x78) +#define SYS_CTRL_GMAC_DELAY_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x100) + +/* Scratch registers */ +#define SYS_CTRL_SCRATCHWORD0 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xc4) +#define SYS_CTRL_SCRATCHWORD1 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xc8) +#define SYS_CTRL_SCRATCHWORD2 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xcc) +#define SYS_CTRL_SCRATCHWORD3 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xd0) + +#define SYS_CTRL_PLLA_CTRL0 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x1F0) +#define SYS_CTRL_PLLA_CTRL1 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x1F4) +#define SYS_CTRL_PLLA_CTRL2 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x1F8) +#define SYS_CTRL_PLLA_CTRL3 IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x1FC) + +#define SYS_CTRL_USBHSMPH_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x40) +#define SYS_CTRL_USBHSMPH_STAT IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x44) +#define SYS_CTRL_REF300_DIV IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xF8) +#define SYS_CTRL_USBHSPHY_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x84) +#define SYS_CTRL_USB_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x90) + +/* pcie */ +#define SYS_CTRL_HCSL_CTRL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x114) + +/* System control multi-function pin function selection */ +#define SYS_CTRL_SECONDARY_SEL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x14) +#define SYS_CTRL_TERTIARY_SEL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x8c) +#define SYS_CTRL_QUATERNARY_SEL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x94) +#define SYS_CTRL_DEBUG_SEL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0x9c) +#define SYS_CTRL_ALTERNATIVE_SEL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xa4) +#define SYS_CTRL_PULLUP_SEL IOMEM(OXNAS_SYSCRTL_BASE_VA + 0xac) + +/* Secure control multi-function pin function selection */ +#define SEC_CTRL_SECONDARY_SEL IOMEM(OXNAS_SECCRTL_BASE_VA + 0x14) +#define SEC_CTRL_TERTIARY_SEL IOMEM(OXNAS_SECCRTL_BASE_VA + 0x8c) +#define SEC_CTRL_QUATERNARY_SEL IOMEM(OXNAS_SECCRTL_BASE_VA + 0x94) +#define SEC_CTRL_DEBUG_SEL IOMEM(OXNAS_SECCRTL_BASE_VA + 0x9c) +#define SEC_CTRL_ALTERNATIVE_SEL IOMEM(OXNAS_SECCRTL_BASE_VA + 0xa4) +#define SEC_CTRL_PULLUP_SEL IOMEM(OXNAS_SECCRTL_BASE_VA + 0xac) + +#define SEC_CTRL_COPRO_CTRL IOMEM(OXNAS_SECCRTL_BASE_VA + 0x68) +#define SEC_CTRL_SECURE_CTRL IOMEM(OXNAS_SECCRTL_BASE_VA + 0x98) +#define SEC_CTRL_LEON_DEBUG IOMEM(OXNAS_SECCRTL_BASE_VA + 0xF0) +#define SEC_CTRL_PLLB_DIV_CTRL IOMEM(OXNAS_SECCRTL_BASE_VA + 0xF8) +#define SEC_CTRL_PLLB_CTRL0 IOMEM(OXNAS_SECCRTL_BASE_VA + 0x1F0) +#define SEC_CTRL_PLLB_CTRL1 IOMEM(OXNAS_SECCRTL_BASE_VA + 0x1F4) +#define SEC_CTRL_PLLB_CTRL8 IOMEM(OXNAS_SECCRTL_BASE_VA + 0x1F4) + +#define RPSA_IRQ_SOFT IOMEM(OXNAS_RPSA_BASE_VA + 0x10) +#define RPSA_FIQ_ENABLE IOMEM(OXNAS_RPSA_BASE_VA + 0x108) +#define RPSA_FIQ_DISABLE IOMEM(OXNAS_RPSA_BASE_VA + 0x10C) +#define RPSA_FIQ_IRQ_TO_FIQ IOMEM(OXNAS_RPSA_BASE_VA + 0x1FC) + +#define RPSC_IRQ_SOFT IOMEM(OXNAS_RPSC_BASE_VA + 0x10) +#define RPSC_FIQ_ENABLE IOMEM(OXNAS_RPSC_BASE_VA + 0x108) +#define RPSC_FIQ_DISABLE IOMEM(OXNAS_RPSC_BASE_VA + 0x10C) +#define RPSC_FIQ_IRQ_TO_FIQ IOMEM(OXNAS_RPSC_BASE_VA + 0x1FC) + +#define RPSA_TIMER2_VAL IOMEM(OXNAS_RPSA_BASE_VA + 0x224) + +#define REF300_DIV_INT_SHIFT 8 +#define REF300_DIV_FRAC_SHIFT 0 +#define REF300_DIV_INT(val) ((val) << REF300_DIV_INT_SHIFT) +#define REF300_DIV_FRAC(val) ((val) << REF300_DIV_FRAC_SHIFT) + +#define USBHSPHY_SUSPENDM_MANUAL_ENABLE 16 +#define USBHSPHY_SUSPENDM_MANUAL_STATE 15 +#define USBHSPHY_ATE_ESET 14 +#define USBHSPHY_TEST_DIN 6 +#define USBHSPHY_TEST_ADD 2 +#define USBHSPHY_TEST_DOUT_SEL 1 +#define USBHSPHY_TEST_CLK 0 + +#define USB_CTRL_USBAPHY_CKSEL_SHIFT 5 +#define USB_CLK_XTAL0_XTAL1 (0 << USB_CTRL_USBAPHY_CKSEL_SHIFT) +#define USB_CLK_XTAL0 (1 << USB_CTRL_USBAPHY_CKSEL_SHIFT) +#define USB_CLK_INTERNAL (2 << USB_CTRL_USBAPHY_CKSEL_SHIFT) + +#define USBAMUX_DEVICE BIT(4) + +#define USBPHY_REFCLKDIV_SHIFT 2 +#define USB_PHY_REF_12MHZ (0 << USBPHY_REFCLKDIV_SHIFT) +#define USB_PHY_REF_24MHZ (1 << USBPHY_REFCLKDIV_SHIFT) +#define USB_PHY_REF_48MHZ (2 << USBPHY_REFCLKDIV_SHIFT) + +#define USB_CTRL_USB_CKO_SEL_BIT 0 + +#define USB_INT_CLK_XTAL 0 +#define USB_INT_CLK_REF300 2 +#define USB_INT_CLK_PLLB 3 + +#define SYS_CTRL_GMAC_CKEN_RX_IN 14 +#define SYS_CTRL_GMAC_CKEN_RXN_OUT 13 +#define SYS_CTRL_GMAC_CKEN_RX_OUT 12 +#define SYS_CTRL_GMAC_CKEN_TX_IN 10 +#define SYS_CTRL_GMAC_CKEN_TXN_OUT 9 +#define SYS_CTRL_GMAC_CKEN_TX_OUT 8 +#define SYS_CTRL_GMAC_RX_SOURCE 7 +#define SYS_CTRL_GMAC_TX_SOURCE 6 +#define SYS_CTRL_GMAC_LOW_TX_SOURCE 4 +#define SYS_CTRL_GMAC_AUTO_TX_SOURCE 3 +#define SYS_CTRL_GMAC_RGMII 2 +#define SYS_CTRL_GMAC_SIMPLE_MUX 1 +#define SYS_CTRL_GMAC_CKEN_GTX 0 +#define SYS_CTRL_GMAC_TX_VARDELAY_SHIFT 0 +#define SYS_CTRL_GMAC_TXN_VARDELAY_SHIFT 8 +#define SYS_CTRL_GMAC_RX_VARDELAY_SHIFT 16 +#define SYS_CTRL_GMAC_RXN_VARDELAY_SHIFT 24 +#define SYS_CTRL_GMAC_TX_VARDELAY(d) ((d)< + +#define OXNAS_UART1_BASE 0x44200000 +#define OXNAS_UART1_SIZE SZ_32 +#define OXNAS_UART1_BASE_VA 0xF0000000 + +#define OXNAS_UART2_BASE 0x44300000 +#define OXNAS_UART2_SIZE SZ_32 + +#define OXNAS_PERCPU_BASE 0x47000000 +#define OXNAS_PERCPU_SIZE SZ_8K +#define OXNAS_PERCPU_BASE_VA 0xF0002000 + +#define OXNAS_SYSCRTL_BASE 0x44E00000 +#define OXNAS_SYSCRTL_SIZE SZ_4K +#define OXNAS_SYSCRTL_BASE_VA 0xF0004000 + +#define OXNAS_SECCRTL_BASE 0x44F00000 +#define OXNAS_SECCRTL_SIZE SZ_4K +#define OXNAS_SECCRTL_BASE_VA 0xF0005000 + +#define OXNAS_RPSA_BASE 0x44400000 +#define OXNAS_RPSA_SIZE SZ_4K +#define OXNAS_RPSA_BASE_VA 0xF0006000 + +#define OXNAS_RPSC_BASE 0x44500000 +#define OXNAS_RPSC_SIZE SZ_4K +#define OXNAS_RPSC_BASE_VA 0xF0007000 + +#endif diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/irqs.h b/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/irqs.h new file mode 100644 index 0000000000..bcafd10ae0 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/irqs.h @@ -0,0 +1,7 @@ +#ifndef __ASM_ARCH_IRQS_H +#define __ASM_ARCH_IRQS_H + +#define IRQ_SOFT 1 +#define NR_IRQS 160 + +#endif diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/smp.h b/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/smp.h new file mode 100644 index 0000000000..1128635963 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/smp.h @@ -0,0 +1,34 @@ +/* + * smp.h + * + * Created on: Sep 24, 2013 + * Author: mahaijun + */ + +#ifndef _NAS782X_SMP_H_ +#define _NAS782X_SMP_H_ + +#include + +extern void ox820_secondary_startup(void); +extern void ox820_cpu_die(unsigned int cpu); + +static inline void write_pen_release(int val) +{ + writel(val, HOLDINGPEN_CPU); +} + +static inline int read_pen_release(void) +{ + return readl(HOLDINGPEN_CPU); +} + +extern struct smp_operations ox820_smp_ops; + +extern unsigned char ox820_fiq_start, ox820_fiq_end; +extern void v6_dma_map_area(const void *, size_t, int); +extern void v6_dma_unmap_area(const void *, size_t, int); +extern void v6_dma_flush_range(const void *, const void *); +extern void v6_flush_kern_dcache_area(void *, size_t); + +#endif /* _NAS782X_SMP_H_ */ diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/timex.h b/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/timex.h new file mode 100644 index 0000000000..4133594d16 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/timex.h @@ -0,0 +1,6 @@ +#ifndef __ASM_ARCH_TIMEX_H +#define __ASM_ARCH_TIMEX_H + +#define CLOCK_TICK_RATE 6250000 + +#endif diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/uncompress.h b/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/uncompress.h new file mode 100644 index 0000000000..fbc372787e --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/uncompress.h @@ -0,0 +1,32 @@ +/* linux/include/asm-arm/arch-oxnas/uncompress.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_UNCOMPRESS_H +#define __ASM_ARCH_UNCOMPRESS_H + +#define OXNAS_UART1_BASE 0x44200000 + +static inline void putc(int c) +{ + static volatile unsigned char *uart = + (volatile unsigned char *)OXNAS_UART1_BASE; + + while (!(uart[5] & 0x20)) { /* LSR reg THR empty bit */ + barrier(); + } + uart[0] = c; /* THR register */ +} + +static inline void flush(void) +{ +} + +#define arch_decomp_setup() + +#define arch_decomp_wdog() + +#endif /* __ASM_ARCH_UNCOMPRESS_H */ diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/utils.h b/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/utils.h new file mode 100644 index 0000000000..910d7019c7 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/include/mach/utils.h @@ -0,0 +1,34 @@ +#ifndef _NAS782X_UTILS_H +#define _NAS782X_UTILS_H + +#include +#include + +static inline void oxnas_register_clear_mask(void __iomem *p, unsigned mask) +{ + u32 val = readl_relaxed(p); + + val &= ~mask; + writel_relaxed(val, p); +} + +static inline void oxnas_register_set_mask(void __iomem *p, unsigned mask) +{ + u32 val = readl_relaxed(p); + + val |= mask; + writel_relaxed(val, p); +} + +static inline void oxnas_register_value_mask(void __iomem *p, + unsigned mask, unsigned new_value) +{ + /* TODO sanity check mask & new_value = new_value */ + u32 val = readl_relaxed(p); + + val &= ~mask; + val |= new_value; + writel_relaxed(val, p); +} + +#endif /* _NAS782X_UTILS_H */ diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/mach-ox820.c b/target/linux/oxnas/files/arch/arm/mach-oxnas/mach-ox820.c new file mode 100644 index 0000000000..4b247b6b56 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/mach-ox820.c @@ -0,0 +1,284 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct map_desc ox820_io_desc[] __initdata = { + { + .virtual = (unsigned long)OXNAS_PERCPU_BASE_VA, + .pfn = __phys_to_pfn(OXNAS_PERCPU_BASE), + .length = OXNAS_PERCPU_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = (unsigned long)OXNAS_SYSCRTL_BASE_VA, + .pfn = __phys_to_pfn(OXNAS_SYSCRTL_BASE), + .length = OXNAS_SYSCRTL_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = (unsigned long)OXNAS_SECCRTL_BASE_VA, + .pfn = __phys_to_pfn(OXNAS_SECCRTL_BASE), + .length = OXNAS_SECCRTL_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = (unsigned long)OXNAS_RPSA_BASE_VA, + .pfn = __phys_to_pfn(OXNAS_RPSA_BASE), + .length = OXNAS_RPSA_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = (unsigned long)OXNAS_RPSC_BASE_VA, + .pfn = __phys_to_pfn(OXNAS_RPSC_BASE), + .length = OXNAS_RPSC_SIZE, + .type = MT_DEVICE, + }, +}; + +void __init ox820_map_common_io(void) +{ + debug_ll_io_init(); + iotable_init(ox820_io_desc, ARRAY_SIZE(ox820_io_desc)); +} + +struct plat_gmac_data { + struct plat_stmmacenet_data stmmac; + struct clk *clk; +}; + +void *ox820_gmac_setup(struct platform_device *pdev) +{ + struct plat_gmac_data *pdata = pdev->dev.platform_data; + + pdata->clk = clk_get(&pdev->dev, "gmac"); + return (void *) pdata->clk; +}; + +int ox820_gmac_init(struct platform_device *pdev, void *priv) +{ + int ret; + unsigned value; + + ret = device_reset(&pdev->dev); + if (ret) + return ret; + + if (IS_ERR(priv)) + return PTR_ERR(priv); + clk_prepare_enable(priv); + + value = readl(SYS_CTRL_GMAC_CTRL); + + /* Enable GMII_GTXCLK to follow GMII_REFCLK, required for gigabit PHY */ + value |= BIT(SYS_CTRL_GMAC_CKEN_GTX); + /* Use simple mux for 25/125 Mhz clock switching */ + value |= BIT(SYS_CTRL_GMAC_SIMPLE_MUX); + /* set auto switch tx clock source */ + value |= BIT(SYS_CTRL_GMAC_AUTO_TX_SOURCE); + /* enable tx & rx vardelay */ + value |= BIT(SYS_CTRL_GMAC_CKEN_TX_OUT); + value |= BIT(SYS_CTRL_GMAC_CKEN_TXN_OUT); + value |= BIT(SYS_CTRL_GMAC_CKEN_TX_IN); + value |= BIT(SYS_CTRL_GMAC_CKEN_RX_OUT); + value |= BIT(SYS_CTRL_GMAC_CKEN_RXN_OUT); + value |= BIT(SYS_CTRL_GMAC_CKEN_RX_IN); + writel(value, SYS_CTRL_GMAC_CTRL); + + /* set tx & rx vardelay */ + value = 0; + value |= SYS_CTRL_GMAC_TX_VARDELAY(4); + value |= SYS_CTRL_GMAC_TXN_VARDELAY(2); + value |= SYS_CTRL_GMAC_RX_VARDELAY(10); + value |= SYS_CTRL_GMAC_RXN_VARDELAY(8); + writel(value, SYS_CTRL_GMAC_DELAY_CTRL); + + return 0; +} + +void ox820_gmac_exit(struct platform_device *pdev, void *priv) +{ + struct reset_control *rstc; + + clk_disable_unprepare(priv); + clk_put(priv); + + rstc = reset_control_get(&pdev->dev, NULL); + if (!IS_ERR(rstc)) { + reset_control_assert(rstc); + reset_control_put(rstc); + } +} + +static int __init ox820_ether_init(void) +{ + struct device_node *node; + struct platform_device *pdev; + struct plat_gmac_data *pdata; + + node = of_find_compatible_node(NULL, NULL, "plxtech,nas782x-gmac"); + if (!node) + return -ENOENT; + + pdev = of_find_device_by_node(node); + of_node_put(node); + + if (!pdev) + return -EINVAL; + + pdata = kzalloc(sizeof(struct plat_gmac_data), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + pdata->stmmac.setup = ox820_gmac_setup; + pdata->stmmac.init = ox820_gmac_init; + pdata->stmmac.exit = ox820_gmac_exit; + pdev->dev.platform_data = pdata; + + return 0; +} + +static void __init ox820_dt_init(void) +{ + int ret; + + ret = of_platform_populate(NULL, of_default_bus_match_table, NULL, + NULL); + + if (ret) { + pr_err("of_platform_populate failed: %d\n", ret); + BUG(); + } + + ret = ox820_ether_init(); + + if (ret) + pr_info("ox820_ether_init failed: %d\n", ret); +} + +static void __init ox820_timer_init(void) +{ + of_clk_init(NULL); + clocksource_of_init(); +} + +void ox820_init_early(void) +{ + +} + +void ox820_assert_system_reset(enum reboot_mode mode, const char *cmd) +{ + u32 value; + +/* Assert reset to cores as per power on defaults + * Don't touch the DDR interface as things will come to an impromptu stop + * NB Possibly should be asserting reset for PLLB, but there are timing + * concerns here according to the docs */ + value = BIT(SYS_CTRL_RST_COPRO) | + BIT(SYS_CTRL_RST_USBHS) | + BIT(SYS_CTRL_RST_USBHSPHYA) | + BIT(SYS_CTRL_RST_MACA) | + BIT(SYS_CTRL_RST_PCIEA) | + BIT(SYS_CTRL_RST_SGDMA) | + BIT(SYS_CTRL_RST_CIPHER) | + BIT(SYS_CTRL_RST_SATA) | + BIT(SYS_CTRL_RST_SATA_LINK) | + BIT(SYS_CTRL_RST_SATA_PHY) | + BIT(SYS_CTRL_RST_PCIEPHY) | + BIT(SYS_CTRL_RST_STATIC) | + BIT(SYS_CTRL_RST_UART1) | + BIT(SYS_CTRL_RST_UART2) | + BIT(SYS_CTRL_RST_MISC) | + BIT(SYS_CTRL_RST_I2S) | + BIT(SYS_CTRL_RST_SD) | + BIT(SYS_CTRL_RST_MACB) | + BIT(SYS_CTRL_RST_PCIEB) | + BIT(SYS_CTRL_RST_VIDEO) | + BIT(SYS_CTRL_RST_USBHSPHYB) | + BIT(SYS_CTRL_RST_USBDEV); + + writel(value, SYS_CTRL_RST_SET_CTRL); + + /* Release reset to cores as per power on defaults */ + writel(BIT(SYS_CTRL_RST_GPIO), SYS_CTRL_RST_CLR_CTRL); + + /* Disable clocks to cores as per power-on defaults - must leave DDR + * related clocks enabled otherwise we'll stop rather abruptly. */ + value = + BIT(SYS_CTRL_CLK_COPRO) | + BIT(SYS_CTRL_CLK_DMA) | + BIT(SYS_CTRL_CLK_CIPHER) | + BIT(SYS_CTRL_CLK_SD) | + BIT(SYS_CTRL_CLK_SATA) | + BIT(SYS_CTRL_CLK_I2S) | + BIT(SYS_CTRL_CLK_USBHS) | + BIT(SYS_CTRL_CLK_MAC) | + BIT(SYS_CTRL_CLK_PCIEA) | + BIT(SYS_CTRL_CLK_STATIC) | + BIT(SYS_CTRL_CLK_MACB) | + BIT(SYS_CTRL_CLK_PCIEB) | + BIT(SYS_CTRL_CLK_REF600) | + BIT(SYS_CTRL_CLK_USBDEV); + + writel(value, SYS_CTRL_CLK_CLR_CTRL); + + /* Enable clocks to cores as per power-on defaults */ + + /* Set sys-control pin mux'ing as per power-on defaults */ + writel(0, SYS_CTRL_SECONDARY_SEL); + writel(0, SYS_CTRL_TERTIARY_SEL); + writel(0, SYS_CTRL_QUATERNARY_SEL); + writel(0, SYS_CTRL_DEBUG_SEL); + writel(0, SYS_CTRL_ALTERNATIVE_SEL); + writel(0, SYS_CTRL_PULLUP_SEL); + + writel(0, SYS_CTRL_SECONDARY_SEL); + writel(0, SYS_CTRL_TERTIARY_SEL); + writel(0, SYS_CTRL_QUATERNARY_SEL); + writel(0, SYS_CTRL_DEBUG_SEL); + writel(0, SYS_CTRL_ALTERNATIVE_SEL); + writel(0, SYS_CTRL_PULLUP_SEL); + + /* No need to save any state, as the ROM loader can determine whether + * reset is due to power cycling or programatic action, just hit the + * (self-clearing) CPU reset bit of the block reset register */ + value = + BIT(SYS_CTRL_RST_SCU) | + BIT(SYS_CTRL_RST_ARM0) | + BIT(SYS_CTRL_RST_ARM1); + + writel(value, SYS_CTRL_RST_SET_CTRL); +} + +static const char * const ox820_dt_board_compat[] = { + "plxtech,nas7820", + "plxtech,nas7821", + "plxtech,nas7825", + NULL +}; + +DT_MACHINE_START(OX820_DT, "PLXTECH NAS782X SoC (Flattened Device Tree)") + .map_io = ox820_map_common_io, + .smp = smp_ops(ox820_smp_ops), + .init_early = ox820_init_early, + .init_time = ox820_timer_init, + .init_machine = ox820_dt_init, + .restart = ox820_assert_system_reset, + .dt_compat = ox820_dt_board_compat, +MACHINE_END diff --git a/target/linux/oxnas/files/arch/arm/mach-oxnas/platsmp.c b/target/linux/oxnas/files/arch/arm/mach-oxnas/platsmp.c new file mode 100644 index 0000000000..c41a3d1d16 --- /dev/null +++ b/target/linux/oxnas/files/arch/arm/mach-oxnas/platsmp.c @@ -0,0 +1,315 @@ +/* + * arch/arm/mach-ox820/platsmp.c + * + * Copyright (C) 2002 ARM Ltd. + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef CONFIG_DMA_CACHE_FIQ_BROADCAST + +#define FIQ_GENERATE 0x00000002 +#define OXNAS_MAP_AREA 0x01000000 +#define OXNAS_UNMAP_AREA 0x02000000 +#define OXNAS_FLUSH_RANGE 0x03000000 + +struct fiq_req { + union { + struct { + const void *addr; + size_t size; + } map; + struct { + const void *addr; + size_t size; + } unmap; + struct { + const void *start; + const void *end; + } flush; + }; + volatile uint flags; + void __iomem *reg; +} ____cacheline_aligned; + +static struct fiq_handler fh = { + .name = "oxnas-fiq" +}; + +DEFINE_PER_CPU(struct fiq_req, fiq_data); + +static inline void __cpuinit ox820_set_fiq_regs(unsigned int cpu) +{ + struct pt_regs FIQ_regs; + struct fiq_req *fiq_req = &per_cpu(fiq_data, !cpu); + + FIQ_regs.ARM_r8 = 0; + FIQ_regs.ARM_ip = (unsigned int)fiq_req; + FIQ_regs.ARM_sp = (int)(cpu ? RPSC_IRQ_SOFT : RPSA_IRQ_SOFT); + fiq_req->reg = cpu ? RPSC_IRQ_SOFT : RPSA_IRQ_SOFT; + + set_fiq_regs(&FIQ_regs); +} + +static void __init ox820_init_fiq(void) +{ + void *fiqhandler_start; + unsigned int fiqhandler_length; + int ret; + + fiqhandler_start = &ox820_fiq_start; + fiqhandler_length = &ox820_fiq_end - &ox820_fiq_start; + + ret = claim_fiq(&fh); + + if (ret) + return; + + set_fiq_handler(fiqhandler_start, fiqhandler_length); + + writel(IRQ_SOFT, RPSA_FIQ_IRQ_TO_FIQ); + writel(1, RPSA_FIQ_ENABLE); + writel(IRQ_SOFT, RPSC_FIQ_IRQ_TO_FIQ); + writel(1, RPSC_FIQ_ENABLE); +} + +void fiq_dma_map_area(const void *addr, size_t size, int dir) +{ + unsigned long flags; + struct fiq_req *req; + + raw_local_irq_save(flags); + /* currently, not possible to take cpu0 down, so only check cpu1 */ + if (!cpu_online(1)) { + raw_local_irq_restore(flags); + v6_dma_map_area(addr, size, dir); + return; + } + + req = this_cpu_ptr(&fiq_data); + req->map.addr = addr; + req->map.size = size; + req->flags = dir | OXNAS_MAP_AREA; + smp_mb(); + + writel_relaxed(FIQ_GENERATE, req->reg); + + v6_dma_map_area(addr, size, dir); + while (req->flags) + barrier(); + + raw_local_irq_restore(flags); +} + +void fiq_dma_unmap_area(const void *addr, size_t size, int dir) +{ + unsigned long flags; + struct fiq_req *req; + + raw_local_irq_save(flags); + /* currently, not possible to take cpu0 down, so only check cpu1 */ + if (!cpu_online(1)) { + raw_local_irq_restore(flags); + v6_dma_unmap_area(addr, size, dir); + return; + } + + req = this_cpu_ptr(&fiq_data); + req->unmap.addr = addr; + req->unmap.size = size; + req->flags = dir | OXNAS_UNMAP_AREA; + smp_mb(); + + writel_relaxed(FIQ_GENERATE, req->reg); + + v6_dma_unmap_area(addr, size, dir); + while (req->flags) + barrier(); + + raw_local_irq_restore(flags); +} + +void fiq_dma_flush_range(const void *start, const void *end) +{ + unsigned long flags; + struct fiq_req *req; + + raw_local_irq_save(flags); + /* currently, not possible to take cpu0 down, so only check cpu1 */ + if (!cpu_online(1)) { + raw_local_irq_restore(flags); + v6_dma_flush_range(start, end); + return; + } + + req = this_cpu_ptr(&fiq_data); + + req->flush.start = start; + req->flush.end = end; + req->flags = OXNAS_FLUSH_RANGE; + smp_mb(); + + writel_relaxed(FIQ_GENERATE, req->reg); + + v6_dma_flush_range(start, end); + + while (req->flags) + barrier(); + + raw_local_irq_restore(flags); +} + +void fiq_flush_kern_dcache_area(void *addr, size_t size) +{ + fiq_dma_flush_range(addr, addr + size); +} +#else + +#define ox820_set_fiq_regs(cpu) do {} while (0) /* nothing */ +#define ox820_init_fiq() do {} while (0) /* nothing */ + +#endif /* DMA_CACHE_FIQ_BROADCAST */ + +static DEFINE_SPINLOCK(boot_lock); + +void __cpuinit ox820_secondary_init(unsigned int cpu) +{ + /* + * Setup Secondary Core FIQ regs + */ + ox820_set_fiq_regs(1); + + /* + * let the primary processor know we're out of the + * pen, then head off into the C entry point + */ + write_pen_release(-1); + + /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); + spin_unlock(&boot_lock); +} + +int __cpuinit ox820_boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + unsigned long timeout; + + /* + * Set synchronisation state between this boot processor + * and the secondary one + */ + spin_lock(&boot_lock); + + /* + * This is really belt and braces; we hold unintended secondary + * CPUs in the holding pen until we're ready for them. However, + * since we haven't sent them a soft interrupt, they shouldn't + * be there. + */ + write_pen_release(cpu); + + writel(1, IOMEM(OXNAS_GICN_BASE_VA(cpu) + GIC_CPU_CTRL)); + + /* + * Send the secondary CPU a soft interrupt, thereby causing + * the boot monitor to read the system wide flags register, + * and branch to the address found there. + */ + + arch_send_wakeup_ipi_mask(cpumask_of(cpu)); + timeout = jiffies + (1 * HZ); + while (time_before(jiffies, timeout)) { + smp_rmb(); + if (read_pen_release() == -1) + break; + + udelay(10); + } + + /* + * now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + spin_unlock(&boot_lock); + + return read_pen_release() != -1 ? -ENOSYS : 0; +} + +void *scu_base_addr(void) +{ + return IOMEM(OXNAS_SCU_BASE_VA); +} + +/* + * Initialise the CPU possible map early - this describes the CPUs + * which may be present or become present in the system. + */ +static void __init ox820_smp_init_cpus(void) +{ + void __iomem *scu_base = scu_base_addr(); + unsigned int i, ncores; + + ncores = scu_base ? scu_get_core_count(scu_base) : 1; + + /* sanity check */ + if (ncores > nr_cpu_ids) { + pr_warn("SMP: %u cores greater than maximum (%u), clipping\n", + ncores, nr_cpu_ids); + ncores = nr_cpu_ids; + } + + for (i = 0; i < ncores; i++) + set_cpu_possible(i, true); +} + +static void __init ox820_smp_prepare_cpus(unsigned int max_cpus) +{ + + scu_enable(scu_base_addr()); + + /* + * Write the address of secondary startup into the + * system-wide flags register. The BootMonitor waits + * until it receives a soft interrupt, and then the + * secondary CPU branches to this address. + */ + writel(virt_to_phys(ox820_secondary_startup), + HOLDINGPEN_LOCATION); + ox820_init_fiq(); + + ox820_set_fiq_regs(0); +} + +struct smp_operations ox820_smp_ops __initdata = { + .smp_init_cpus = ox820_smp_init_cpus, + .smp_prepare_cpus = ox820_smp_prepare_cpus, + .smp_secondary_init = ox820_secondary_init, + .smp_boot_secondary = ox820_boot_secondary, +#ifdef CONFIG_HOTPLUG_CPU + .cpu_die = ox820_cpu_die, +#endif +}; -- cgit v1.2.3