oxnas: import from openwrt/main

oxnas will be dropped in the main repo, so lets add it here in case
anyone needs it still.

Signed-off-by: Nick Hainke <vincent@systemli.org>
This commit is contained in:
Nick Hainke 2024-04-24 14:08:12 +02:00
parent 5d2306e287
commit 26a4bfdef0
36 changed files with 6406 additions and 0 deletions

20
oxnas/Makefile Normal file
View File

@ -0,0 +1,20 @@
include $(TOPDIR)/rules.mk
ARCH:=arm
BOARD:=oxnas
BOARDNAME:=PLXTECH/Oxford NAS782x/OX8xx
SUBTARGETS:=ox810se ox820
FEATURES:=gpio ramdisk rtc squashfs
DEVICE_TYPE:=nas
KERNEL_PATCHVER:=5.15
include $(INCLUDE_DIR)/target.mk
DEFAULT_PACKAGES += \
kmod-button-hotplug kmod-input-gpio-keys-polled \
kmod-leds-gpio uboot-envtools
KERNELNAME:=zImage dtbs
$(eval $(call BuildTarget))

View File

@ -0,0 +1,60 @@
. /lib/functions/uci-defaults.sh
. /lib/functions/system.sh
bootloader_cmdline_var() {
local param
local pval
for arg in $(cat /proc/device-tree/chosen/bootloader-args); do
param="$(echo $arg | cut -d'=' -f 1)"
pval="$(echo $arg | cut -d'=' -f 2-)"
if [ "$param" = "$1" ]; then
echo "$pval"
fi
done
}
legacy_boot_mac_adr() {
local macstr
local oIFS
macstr="$(bootloader_cmdline_var mac_adr)"
oIFS="$IFS"
IFS=","
set -- $macstr
printf "%02x:%02x:%02x:%02x:%02x:%02x" $1 $2 $3 $4 $5 $6
IFS="$oIFS"
}
oxnas_setup_interfaces()
{
local board="$1"
case $board in
*)
ucidef_set_interface_lan "eth0" "dhcp"
;;
esac
}
oxnas_setup_macs()
{
local board="$1"
local lan_mac=""
case $board in
shuttle,kd20)
lan_mac="$(legacy_boot_mac_adr)"
;;
esac
[ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac
}
board_config_update
board=$(board_name)
oxnas_setup_interfaces $board
oxnas_setup_macs $board
board_config_flush
exit 0

View File

@ -0,0 +1,22 @@
#!/bin/sh /etc/rc.common
START=99
get_irq() {
local name="$1"
grep -m 1 "$name" /proc/interrupts | cut -d: -f1 | sed 's, *,,'
}
set_irq_affinity() {
local name="$1"
local val="$2"
local irq="$(get_irq "$name")"
[ -n "$irq" ] || return
echo "$val" > "/proc/irq/$irq/smp_affinity"
}
start() {
set_irq_affinity ehci_hcd 2
set_irq_affinity xhci_hcd 2
set_irq_affinity sata 2
}

View File

@ -0,0 +1,9 @@
REQUIRE_IMAGE_METADATA=1
platform_check_image() {
return 0
}
platform_do_upgrade() {
nand_do_upgrade $1
}

291
oxnas/config-5.15 Normal file
View File

@ -0,0 +1,291 @@
CONFIG_ALIGNMENT_TRAP=y
CONFIG_ARCH_32BIT_OFF_T=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_KEEP_MEMBLOCK=y
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
CONFIG_ARCH_MULTIPLATFORM=y
CONFIG_ARCH_MULTI_CPU_AUTO=y
# CONFIG_ARCH_MULTI_V4 is not set
# CONFIG_ARCH_MULTI_V4T is not set
CONFIG_ARCH_MULTI_V4_V5=y
CONFIG_ARCH_MULTI_V5=y
CONFIG_ARCH_NR_GPIO=0
CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
CONFIG_ARCH_OXNAS=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARM=y
CONFIG_ARM_APPENDED_DTB=y
CONFIG_ARM_ATAG_DTB_COMPAT=y
# CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER is not set
CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE=y
CONFIG_ARM_CPU_SUSPEND=y
CONFIG_ARM_CRYPTO=y
CONFIG_ARM_HAS_SG_CHAIN=y
CONFIG_ARM_L1_CACHE_SHIFT=5
CONFIG_ARM_PATCH_PHYS_VIRT=y
# CONFIG_ARM_SMMU is not set
CONFIG_ARM_THUMB=y
CONFIG_ARM_UNWIND=y
CONFIG_ATAGS=y
CONFIG_AUTO_ZRELADDR=y
CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y
CONFIG_BLK_DEBUG_FS=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=16
CONFIG_BLK_DEV_RAM_SIZE=65536
CONFIG_BLK_PM=y
CONFIG_CLKSRC_MMIO=y
CONFIG_CLONE_BACKWARDS=y
CONFIG_CMA=y
CONFIG_CMA_ALIGNMENT=8
CONFIG_CMA_AREAS=7
# CONFIG_CMA_DEBUG is not set
# CONFIG_CMA_DEBUGFS is not set
CONFIG_CMA_SIZE_MBYTES=64
# CONFIG_CMA_SIZE_SEL_MAX is not set
CONFIG_CMA_SIZE_SEL_MBYTES=y
# CONFIG_CMA_SIZE_SEL_MIN is not set
# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set
# CONFIG_CMA_SYSFS is not set
CONFIG_CMDLINE_PARTITION=y
CONFIG_COMMON_CLK=y
CONFIG_COMMON_CLK_OXNAS=y
CONFIG_COMPAT_32BIT_TIME=y
CONFIG_CONTIG_ALLOC=y
CONFIG_COREDUMP=y
CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
CONFIG_CPU_32v5=y
CONFIG_CPU_ABRT_EV5TJ=y
CONFIG_CPU_ARM926T=y
# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
CONFIG_CPU_CACHE_VIVT=y
CONFIG_CPU_COPY_V4WB=y
CONFIG_CPU_CP15=y
CONFIG_CPU_CP15_MMU=y
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
CONFIG_CPU_PABRT_LEGACY=y
CONFIG_CPU_PM=y
CONFIG_CPU_THUMB_CAPABLE=y
CONFIG_CPU_TLB_V4WBI=y
CONFIG_CPU_USE_DOMAINS=y
CONFIG_CRASH_CORE=y
CONFIG_CRC16=y
# CONFIG_CRC32_SARWATE is not set
CONFIG_CRC32_SLICEBY8=y
CONFIG_CROSS_MEMORY_ATTACH=y
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
CONFIG_CRYPTO_LZ4=y
CONFIG_CRYPTO_RNG2=y
CONFIG_DEBUG_ALIGN_RODATA=y
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_LZ4=y
CONFIG_DECOMPRESS_LZMA=y
CONFIG_DECOMPRESS_LZO=y
CONFIG_DECOMPRESS_XZ=y
CONFIG_DMA_CMA=y
CONFIG_DMA_OPS=y
CONFIG_DMA_REMAP=y
CONFIG_DNOTIFY=y
CONFIG_DTC=y
CONFIG_DWMAC_GENERIC=y
CONFIG_DWMAC_OXNAS=y
CONFIG_EDAC_ATOMIC_SCRUB=y
CONFIG_EDAC_SUPPORT=y
CONFIG_ELF_CORE=y
CONFIG_FAT_FS=y
CONFIG_FIXED_PHY=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_FREEZER=y
CONFIG_FWNODE_MDIO=y
# CONFIG_FW_CACHE is not set
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_GENERIC_ATOMIC64=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_EARLY_IOREMAP=y
CONFIG_GENERIC_IDLE_POLL_SETUP=y
CONFIG_GENERIC_IRQ_MULTI_HANDLER=y
CONFIG_GENERIC_IRQ_SHOW=y
CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y
CONFIG_GENERIC_PCI_IOMAP=y
CONFIG_GENERIC_PHY=y
CONFIG_GENERIC_PINCONF=y
CONFIG_GENERIC_SCHED_CLOCK=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_GENERIC_STRNCPY_FROM_USER=y
CONFIG_GENERIC_STRNLEN_USER=y
CONFIG_GPIOLIB_IRQCHIP=y
CONFIG_GPIO_CDEV=y
CONFIG_GPIO_GENERIC=y
CONFIG_GPIO_GENERIC_PLATFORM=y
CONFIG_HANDLE_DOMAIN_IRQ=y
CONFIG_HARDIRQS_SW_RESEND=y
CONFIG_HAS_DMA=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT_MAP=y
CONFIG_HID=y
CONFIG_HID_GENERIC=y
CONFIG_HWMON=y
CONFIG_HZ_FIXED=0
CONFIG_ICPLUS_PHY=y
CONFIG_INET_DIAG=y
# CONFIG_INET_DIAG_DESTROY is not set
# CONFIG_INET_RAW_DIAG is not set
CONFIG_INET_TCP_DIAG=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_INPUT=y
# CONFIG_IOMMU_DEBUGFS is not set
# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set
# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set
CONFIG_IOMMU_SUPPORT=y
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_WORK=y
# CONFIG_ISDN is not set
# CONFIG_JFFS2_FS is not set
CONFIG_KALLSYMS=y
CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_XZ is not set
CONFIG_KEXEC=y
CONFIG_KEXEC_CORE=y
# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LIBFDT=y
CONFIG_LOCALVERSION_AUTO=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_LZ4_COMPRESS=y
CONFIG_LZ4_DECOMPRESS=y
CONFIG_LZO_DECOMPRESS=y
# CONFIG_MACH_OX810SE is not set
CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
CONFIG_MEMFD_CREATE=y
CONFIG_MEMORY_ISOLATION=y
CONFIG_MFD_SYSCON=y
CONFIG_MIGRATION=y
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_NEED_KUSER_HELPERS=y
CONFIG_NEED_PER_CPU_KM=y
CONFIG_NET_PTP_CLASSIFY=y
CONFIG_NET_SELFTESTS=y
CONFIG_NLS=y
CONFIG_NO_HZ=y
CONFIG_NO_HZ_COMMON=y
CONFIG_NO_HZ_IDLE=y
CONFIG_OF=y
CONFIG_OF_ADDRESS=y
CONFIG_OF_EARLY_FLATTREE=y
CONFIG_OF_FLATTREE=y
CONFIG_OF_GPIO=y
CONFIG_OF_IRQ=y
CONFIG_OF_KOBJ=y
CONFIG_OF_MDIO=y
CONFIG_OLD_SIGACTION=y
CONFIG_OLD_SIGSUSPEND3=y
CONFIG_OXNAS_RPS_TIMER=y
CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PAGE_POOL=y
# CONFIG_PANIC_ON_OOPS is not set
CONFIG_PANIC_ON_OOPS_VALUE=0
CONFIG_PANIC_TIMEOUT=0
CONFIG_PCS_XPCS=y
CONFIG_PERF_USE_VMALLOC=y
CONFIG_PGTABLE_LEVELS=2
CONFIG_PHYLIB=y
CONFIG_PHYLINK=y
CONFIG_PHY_OXNAS=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_OXNAS=y
# CONFIG_PINCTRL_SINGLE is not set
CONFIG_PM=y
CONFIG_PM_CLK=y
CONFIG_PM_SLEEP=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_OXNAS=y
CONFIG_PPS=y
CONFIG_PTP_1588_CLOCK=y
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
CONFIG_RAS=y
CONFIG_RATIONAL=y
CONFIG_RCU_TRACE=y
CONFIG_RD_BZIP2=y
CONFIG_RD_GZIP=y
CONFIG_RD_LZ4=y
CONFIG_RD_LZMA=y
CONFIG_RD_LZO=y
CONFIG_RD_XZ=y
CONFIG_REALTEK_PHY=y
CONFIG_REGMAP=y
CONFIG_REGMAP_MMIO=y
CONFIG_RESET_CONTROLLER=y
CONFIG_RESET_OXNAS=y
CONFIG_SCHED_DEBUG=y
CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
CONFIG_SERIAL_8250_FSL=y
CONFIG_SERIAL_8250_NR_UARTS=4
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIO=y
CONFIG_SERIO_LIBPS2=y
CONFIG_SERIO_SERPORT=y
CONFIG_SGL_ALLOC=y
CONFIG_SOCK_DIAG=y
CONFIG_SPARSE_IRQ=y
CONFIG_SPLIT_PTLOCK_CPUS=999999
CONFIG_SRCU=y
CONFIG_STACKTRACE=y
CONFIG_STMMAC_ETH=y
CONFIG_STMMAC_PLATFORM=y
# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_SUSPEND=y
CONFIG_SUSPEND_FREEZER=y
CONFIG_SWPHY=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
CONFIG_THERMAL=y
CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
CONFIG_THERMAL_GOV_STEP_WISE=y
CONFIG_THERMAL_HWMON=y
CONFIG_THERMAL_OF=y
CONFIG_TICK_CPU_ACCOUNTING=y
CONFIG_TIMER_OF=y
CONFIG_TIMER_PROBE=y
CONFIG_TINY_SRCU=y
CONFIG_TRACE_CLOCK=y
CONFIG_UEVENT_HELPER_PATH=""
CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
CONFIG_UNWINDER_ARM=y
CONFIG_USB_SUPPORT=y
CONFIG_USE_OF=y
CONFIG_VERSATILE_FPGA_IRQ=y
CONFIG_VERSATILE_FPGA_IRQ_NR=4
CONFIG_VFAT_FS=y
# CONFIG_VFP is not set
CONFIG_VM_EVENT_COUNTERS=y
# CONFIG_WATCHDOG is not set
# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
CONFIG_XZ_DEC_ARM=y
CONFIG_XZ_DEC_BCJ=y
CONFIG_XZ_DEC_IA64=y
CONFIG_XZ_DEC_POWERPC=y
CONFIG_XZ_DEC_SPARC=y
CONFIG_XZ_DEC_X86=y
CONFIG_ZBOOT_ROM_BSS=0
CONFIG_ZBOOT_ROM_TEXT=0
CONFIG_ZLIB_INFLATE=y

View File

@ -0,0 +1,167 @@
/dts-v1/;
#include "ox820.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
/ {
model = "Akitio MyCloud";
compatible = "akitio,mycloud", "oxsemi,ox820";
chosen {
bootargs = "earlyprintk console=ttyS0,115200";
stdout-path = "serial0:115200n8";
};
memory {
/* 128Mbytes DDR */
reg = <0x60000000 0x8000000>;
};
aliases {
serial0 = &uart0;
gpio0 = &gpio0;
gpio1 = &gpio1;
led-boot = &led_status;
led-failsafe = &led_status;
led-running = &led_status;
led-upgrade = &led_status;
};
i2c-gpio {
compatible = "i2c-gpio";
gpios = <&gpio1 9 GPIO_ACTIVE_HIGH
&gpio1 10 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c>;
i2c-gpio,delay-us = <10>;
#address-cells = <1>;
#size-cells = <0>;
ds1307: rtc@68 {
compatible = "dallas,ds1307";
reg = <0x68>;
};
};
keys {
compatible = "gpio-keys-polled";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_buttons>;
#address-cells = <1>;
#size-cells = <0>;
poll-interval = <100>;
power {
label = "power";
gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
linux,code = <KEY_POWER>;
};
reset {
label = "reset";
gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};
};
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_leds>;
led_status: status {
label = "akitio:red:status";
gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
};
};
gpio-poweroff {
compatible = "gpio-poweroff";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_poweroff>;
gpios = <&gpio1 13 GPIO_SINGLE_ENDED>;
};
};
&pinctrl {
pinctrl_i2c: i2c-0 {
i2c {
pins = "gpio41", "gpio42"; /* MF_B9, MF_B10 */
function = "gpio";
/* ToDo: find a way to set debounce for those pins */
};
};
pinctrl_buttons: buttons-0 {
buttons {
pins = "gpio11", "gpio38"; /* MF_A11, MF_B6 GPIO */
function = "gpio";
};
};
pinctrl_leds: leds-0 {
leds {
pins = "gpio29"; /* MF_A29 GPIO */
function = "gpio";
};
};
pinctrl_poweroff: poweroff-0 {
poweroff {
pins = "gpio45"; /* MF_B13 GPIO */
function = "gpio";
};
};
};
&uart0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart0>;
};
&nandc {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_nand>;
nand@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
nand-ecc-mode = "soft";
nand-ecc-algo = "hamming";
partition@0 {
label = "boot";
reg = <0x0 0x26c0000>;
};
partition@26c0000 {
label = "ubi";
reg = <0x26c0000 0xd940000>;
};
};
};
&etha {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_etha_mdio>;
};
&ehci {
status = "okay";
};
&sata {
status = "okay";
nr-ports = <2>;
};
&pcie_phy {
status = "okay";
};
&pcie0 {
status = "okay";
};

View File

@ -0,0 +1,131 @@
/*
* cloudengines-pogoplug-series-3.dtsi - Device tree file for Cloud Engines PogoPlug Series 3
*
* Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
*
* Licensed under GPLv2 or later
*/
/dts-v1/;
#include "ox820.dtsi"
#include <dt-bindings/gpio/gpio.h>
/ {
model = "Cloud Engines PogoPlug Pro";
compatible = "cloudengines,pogoplugpro", "oxsemi,ox820";
chosen {
bootargs = "earlyprintk console=ttyS0,115200";
stdout-path = "serial0:115200n8";
};
memory {
/* 128Mbytes DDR */
reg = <0x60000000 0x8000000>;
};
aliases {
serial0 = &uart0;
gpio0 = &gpio0;
gpio1 = &gpio1;
led-boot = &led_status;
led-failsafe = &led_warn;
led-running = &led_act;
led-upgrade = &led_warn;
};
leds {
compatible = "gpio-leds";
led_status: blue {
label = "pogoplug:blue";
gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
default-state = "keep";
};
led_warn: orange {
label = "pogoplug:orange";
gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;
default-state = "keep";
};
led_act: green {
label = "pogoplug:green";
gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
default-state = "keep";
};
};
};
&uart0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart0>;
};
&nandc {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_nand>;
nand@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
nand-ecc-mode = "soft";
nand-ecc-algo = "hamming";
partition@0 {
label = "stage1";
reg = <0x00000000 0x00040000>;
read-only;
};
partition@40000 {
label = "u-boot";
reg = <0x00040000 0x00380000>;
read-only;
};
partition@3c0000 {
label = "u-boot-env";
reg = <0x003c0000 0x00080000>;
};
partition@440000 {
label = "kernel";
reg = <0x00440000 0x009c0000>;
};
partition@e00000 {
label = "ubi";
reg = <0x00e00000 0x07200000>;
};
};
};
&ehci {
status = "okay";
};
&etha {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_etha_mdio>;
};
&sata {
status = "okay";
};
&pcie_phy {
status = "okay";
};
&pcie0 {
status = "okay";
};

View File

@ -0,0 +1,139 @@
/dts-v1/;
#include "ox820.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
/ {
model = "MitraStar Technology Corp. STG-212";
compatible = "mitrastar,stg-212", "oxsemi,ox820";
chosen {
bootargs = "earlyprintk console=ttyS0,115200";
stdout-path = "serial0:115200n8";
};
memory {
/* 128Mbytes DDR */
reg = <0x60000000 0x8000000>;
};
aliases {
serial0 = &uart0;
gpio0 = &gpio0;
gpio1 = &gpio1;
led-boot = &led_status;
led-failsafe = &led_warn;
led-running = &led_status;
led-upgrade = &led_warn;
};
keys {
compatible = "gpio-keys-polled";
#address-cells = <1>;
#size-cells = <0>;
poll-interval = <100>;
reset {
label = "reset";
gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};
copy {
label = "copy";
gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
linux,code = <KEY_COPY>;
};
};
leds {
compatible = "gpio-leds";
led_status: status {
label = "zyxel:blue:status";
gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
};
led_warn: status2 {
label = "zyxel:red:status";
gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
};
copy {
label = "zyxel:orange:copy";
gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
trigger-sources = <&ehci_port1>, <&ehci_port2>;
linux,default-trigger = "usbport";
};
};
i2c-gpio {
compatible = "i2c-gpio";
gpios = <&gpio1 9 GPIO_ACTIVE_HIGH
&gpio1 10 GPIO_ACTIVE_HIGH>;
i2c-gpio,delay-us = <10>;
};
};
&uart0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart0>;
};
&nandc {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_nand>;
nand@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
nand-ecc-mode = "soft";
nand-ecc-algo = "hamming";
partition@0 {
label = "stage1";
reg = <0x00000000 0x00040000>;
read-only;
};
partition@40000 {
label = "u-boot";
reg = <0x00040000 0x00380000>;
read-only;
};
partition@3c0000 {
label = "u-boot-env";
reg = <0x003c0000 0x00080000>;
};
partition@440000 {
label = "kernel";
reg = <0x00440000 0x009c0000>;
};
partition@e00000 {
label = "ubi";
reg = <0x00e00000 0x07200000>;
};
};
};
&etha {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_etha_mdio>;
};
&ehci {
status = "okay";
};
&sata {
status = "okay";
};

View File

@ -0,0 +1,251 @@
/dts-v1/;
#include "ox820.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include <dt-bindings/thermal/thermal.h>
/ {
model = "Shuttle KD20";
compatible = "shuttle,kd20", "oxsemi,ox820";
chosen {
bootargs = "earlyprintk console=ttyS0,115200";
stdout-path = "serial0:115200n8";
};
memory {
/* 256Mbytes DDR */
reg = <0x60000000 0x10000000>;
};
aliases {
serial0 = &uart0;
gpio0 = &gpio0;
gpio1 = &gpio1;
led-boot = &led_status;
led-failsafe = &led_warn;
led-running = &led_status;
led-upgrade = &led_warn;
};
thermal-zones {
chassis-thermal {
/* Poll every 20 seconds */
polling-delay = <20000>;
/* Poll every 2nd second when cooling */
polling-delay-passive = <2000>;
thermal-sensors = <&hdd0_temp>, <&hdd1_temp>;
trips {
chassis_alert0: chassis-alert0 {
/* At 43 degrees turn on fan */
temperature = <43000>;
hysteresis = <3000>;
type = "active";
};
chassis_alert1: chassis-alert1 {
/* At 60 degrees emergency shutdown */
temperature = <60000>;
hysteresis = <2000>;
type = "critical";
};
};
cooling-maps {
map0 {
trip = <&chassis_alert0>;
cooling-device = <&system_fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
};
i2c-gpio {
compatible = "i2c-gpio";
sda-gpios = <&gpio1 9 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
sck-gpios = <&gpio1 10 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
i2c-gpio,delay-us = <10>;
#address-cells = <1>;
#size-cells = <0>;
rtc0: rtc@51 {
compatible = "nxp,pcf8563";
reg = <0x51>;
};
};
keys {
compatible = "gpio-keys-polled";
#address-cells = <1>;
#size-cells = <0>;
poll-interval = <100>;
power {
label = "power";
gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
linux,code = <KEY_POWER>;
};
reset {
label = "reset";
gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
linux,code = <KEY_RESTART>;
};
eject1 {
label = "eject1";
gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
linux,code = <KEY_EJECTCD>;
};
eject2 {
label = "eject2";
gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
linux,code = <162>;
};
};
leds {
compatible = "gpio-leds";
led_status: status {
label = "kd20:blue:status";
gpios = <&gpio1 16 GPIO_ACTIVE_HIGH>;
};
led_warn: status2 {
label = "kd20:red:status";
gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
};
hdd1blue {
label = "kd20:blue:hdd1";
gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "ata1";
};
hdd1red {
label = "kd20:red:hdd1";
gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
};
hdd2blue {
label = "kd20:blue:hdd2";
gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "ata2";
};
hdd2red {
label = "kd20:red:hdd2";
gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
};
usb {
label = "kd20:blue:usb";
gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
trigger-sources = <&ehci_port1>, <&ehci_port2>;
linux,default-trigger = "usbport";
};
};
beeper: beeper {
compatible = "gpio-beeper";
gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
};
system_fan: gpio-fan {
compatible = "gpio-fan";
gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
gpio-fan,speed-map = <0 0
3000 1>;
#cooling-cells = <2>;
};
gpio-poweroff {
compatible = "gpio-poweroff";
gpios = <&gpio0 9 GPIO_ACTIVE_HIGH>;
};
};
&uart0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart0>;
};
&nandc {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_nand>;
nand@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <1>;
nand-ecc-mode = "soft";
nand-ecc-algo = "hamming";
partition@0 {
label = "stage1";
reg = <0x00000000 0x00040000>;
read-only;
};
partition@40000 {
label = "u-boot";
reg = <0x00040000 0x001e0000>;
read-only;
};
partition@220000 {
label = "u-boot-env";
reg = <0x00220000 0x00020000>;
};
partition@240000 {
label = "initrd";
reg = <0x00240000 0x00600000>;
};
partition@840000 {
label = "kernel";
reg = <0x00840000 0x007C0000>;
};
partition@e00000 {
label = "ubi";
reg = <0x01000000 0x07000000>;
};
};
};
&etha {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_etha_mdio>;
};
&ehci {
status = "okay";
};
&sata {
status = "okay";
nr-ports = <2>;
hdd0_temp: sata-port@0 {
reg = <0>;
#thermal-sensor-cells = <0>;
};
hdd1_temp: sata-port@1 {
reg = <1>;
#thermal-sensor-cells = <0>;
};
};
&pcie_phy {
status = "okay";
};
&pcie0 {
status = "okay";
};

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,674 @@
/*
* PCIe driver for PLX NAS782X SoCs
*
* Author: Ma Haijun <mahaijuns@gmail.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/clk.h>
#include <linux/module.h>
#include <linux/mbus.h>
#include <linux/mfd/syscon.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/phy.h>
#include <linux/phy/phy.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/io.h>
#include <linux/sizes.h>
#include "../pci.h"
#define SYS_CTRL_HCSL_CTRL_REGOFFSET 0x114
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);
}
#define VERSION_ID_MAGIC 0x082510b5
#define LINK_UP_TIMEOUT_SECONDS 1
#define NUM_CONTROLLERS 1
enum {
PCIE_DEVICE_TYPE_MASK = 0x0F,
PCIE_DEVICE_TYPE_ENDPOINT = 0,
PCIE_DEVICE_TYPE_LEGACY_ENDPOINT = 1,
PCIE_DEVICE_TYPE_ROOT = 4,
PCIE_LTSSM = BIT(4),
PCIE_READY_ENTR_L23 = BIT(9),
PCIE_LINK_UP = BIT(11),
PCIE_OBTRANS = BIT(12),
};
/* core config registers */
enum {
PCI_CONFIG_VERSION_DEVICEID = 0,
PCI_CONFIG_COMMAND_STATUS = 4,
};
/* inbound config registers */
enum {
IB_ADDR_XLATE_ENABLE = 0xFC,
/* bits */
ENABLE_IN_ADDR_TRANS = BIT(0),
};
/* outbound config registers, offset relative to PCIE_POM0_MEM_ADDR */
enum {
PCIE_POM0_MEM_ADDR = 0,
PCIE_POM1_MEM_ADDR = 4,
PCIE_IN0_MEM_ADDR = 8,
PCIE_IN1_MEM_ADDR = 12,
PCIE_IN_IO_ADDR = 16,
PCIE_IN_CFG0_ADDR = 20,
PCIE_IN_CFG1_ADDR = 24,
PCIE_IN_MSG_ADDR = 28,
PCIE_IN0_MEM_LIMIT = 32,
PCIE_IN1_MEM_LIMIT = 36,
PCIE_IN_IO_LIMIT = 40,
PCIE_IN_CFG0_LIMIT = 44,
PCIE_IN_CFG1_LIMIT = 48,
PCIE_IN_MSG_LIMIT = 52,
PCIE_AHB_SLAVE_CTRL = 56,
PCIE_SLAVE_BE_SHIFT = 22,
};
#define PCIE_SLAVE_BE(val) ((val) << PCIE_SLAVE_BE_SHIFT)
#define PCIE_SLAVE_BE_MASK PCIE_SLAVE_BE(0xF)
struct oxnas_pcie_shared {
/* seems all access are serialized, no lock required */
int refcount;
};
/* Structure representing one PCIe interfaces */
struct oxnas_pcie {
void __iomem *cfgbase;
void __iomem *base;
void __iomem *inbound;
struct regmap *sys_ctrl;
unsigned int outbound_offset;
unsigned int pcie_ctrl_offset;
struct phy *phy;
int haslink;
struct platform_device *pdev;
struct resource io;
struct resource cfg;
struct resource pre_mem; /* prefetchable */
struct resource non_mem; /* non-prefetchable */
struct resource busn; /* max available bus numbers */
int card_reset; /* gpio pin, optional */
unsigned hcsl_en; /* hcsl pci enable bit */
struct clk *clk;
struct clk *busclk; /* for pcie bus, actually the PLLB */
void *private_data[1];
spinlock_t lock;
};
static struct oxnas_pcie_shared pcie_shared = {
.refcount = 0,
};
static inline struct oxnas_pcie *sys_to_pcie(struct pci_sys_data *sys)
{
return sys->private_data;
}
static inline void set_out_lanes(struct oxnas_pcie *pcie, unsigned lanes)
{
regmap_update_bits(pcie->sys_ctrl, pcie->outbound_offset + PCIE_AHB_SLAVE_CTRL,
PCIE_SLAVE_BE_MASK, PCIE_SLAVE_BE(lanes));
wmb();
}
static int oxnas_pcie_link_up(struct oxnas_pcie *pcie)
{
unsigned long end;
unsigned int val;
/* Poll for PCIE link up */
end = jiffies + (LINK_UP_TIMEOUT_SECONDS * HZ);
while (!time_after(jiffies, end)) {
regmap_read(pcie->sys_ctrl, pcie->pcie_ctrl_offset, &val);
if (val & PCIE_LINK_UP)
return 1;
}
return 0;
}
static void oxnas_pcie_setup_hw(struct oxnas_pcie *pcie)
{
/* We won't have any inbound address translation. This allows PCI
* devices to access anywhere in the AHB address map. Might be regarded
* as a bit dangerous, but let's get things working before we worry
* about that
*/
oxnas_register_clear_mask(pcie->inbound + IB_ADDR_XLATE_ENABLE,
ENABLE_IN_ADDR_TRANS);
wmb();
/*
* Program outbound translation windows
*
* Outbound window is what is referred to as "PCI client" region in HRM
*
* Could use the larger alternative address space to get >>64M regions
* for graphics cards etc., but will not bother at this point.
*
* IP bug means that AMBA window size must be a power of 2
*
* Set mem0 window for first 16MB of outbound window non-prefetchable
* Set mem1 window for second 16MB of outbound window prefetchable
* Set io window for next 16MB of outbound window
* Set cfg0 for final 1MB of outbound window
*
* Ignore mem1, cfg1 and msg windows for now as no obvious use cases for
* 820 that would need them
*
* Probably ideally want no offset between mem0 window start as seen by
* ARM and as seen on PCI bus and get Linux to assign memory regions to
* PCI devices using the same "PCI client" region start address as seen
* by ARM
*/
/* Set PCIeA mem0 region to be 1st 16MB of the 64MB PCIeA window */
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN0_MEM_ADDR, pcie->non_mem.start);
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN0_MEM_LIMIT, pcie->non_mem.end);
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_POM0_MEM_ADDR, pcie->non_mem.start);
/* Set PCIeA mem1 region to be 2nd 16MB of the 64MB PCIeA window */
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN1_MEM_ADDR, pcie->pre_mem.start);
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN1_MEM_LIMIT, pcie->pre_mem.end);
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_POM1_MEM_ADDR, pcie->pre_mem.start);
/* Set PCIeA io to be third 16M region of the 64MB PCIeA window*/
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN_IO_ADDR, pcie->io.start);
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN_IO_LIMIT, pcie->io.end);
/* Set PCIeA cgf0 to be last 16M region of the 64MB PCIeA window*/
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN_CFG0_ADDR, pcie->cfg.start);
regmap_write(pcie->sys_ctrl, pcie->outbound_offset + PCIE_IN_CFG0_LIMIT, pcie->cfg.end);
wmb();
/* Enable outbound address translation */
regmap_write_bits(pcie->sys_ctrl, pcie->pcie_ctrl_offset, PCIE_OBTRANS, PCIE_OBTRANS);
wmb();
/*
* Program PCIe command register for core to:
* enable memory space
* enable bus master
* enable io
*/
writel_relaxed(7, pcie->base + PCI_CONFIG_COMMAND_STATUS);
/* which is which */
wmb();
}
static unsigned oxnas_pcie_cfg_to_offset(
struct pci_sys_data *sys,
unsigned char bus_number,
unsigned int devfn,
int where)
{
unsigned int function = PCI_FUNC(devfn);
unsigned int slot = PCI_SLOT(devfn);
unsigned char bus_number_offset;
bus_number_offset = bus_number - sys->busnr;
/*
* We'll assume for now that the offset, function, slot, bus encoding
* should map onto linear, contiguous addresses in PCIe config space,
* albeit that the majority will be unused as only slot 0 is valid for
* any PCIe bus and most devices have only function 0
*
* Could be that PCIe in fact works by not encoding the slot number into
* the config space address as it's known that only slot 0 is valid.
* We'll have to experiment if/when we get a PCIe switch connected to
* the PCIe host
*/
return (bus_number_offset << 20) | (slot << 15) | (function << 12) |
(where & ~3);
}
/* PCI configuration space write function */
static int oxnas_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
int where, int size, u32 val)
{
unsigned long flags;
struct oxnas_pcie *pcie = sys_to_pcie(bus->sysdata);
unsigned offset;
u32 value;
u32 lanes;
/* Only a single device per bus for PCIe point-to-point links */
if (PCI_SLOT(devfn) > 0)
return PCIBIOS_DEVICE_NOT_FOUND;
if (!pcie->haslink)
return PCIBIOS_DEVICE_NOT_FOUND;
offset = oxnas_pcie_cfg_to_offset(bus->sysdata, bus->number, devfn,
where);
value = val << (8 * (where & 3));
lanes = (0xf >> (4-size)) << (where & 3);
/* it race with mem and io write, but the possibility is low, normally
* all config writes happens at driver initialize stage, wont interleave
* with others.
* and many pcie cards use dword (4bytes) access mem/io access only,
* so not bother to copy that ugly work-around now. */
spin_lock_irqsave(&pcie->lock, flags);
set_out_lanes(pcie, lanes);
writel_relaxed(value, pcie->cfgbase + offset);
set_out_lanes(pcie, 0xf);
spin_unlock_irqrestore(&pcie->lock, flags);
return PCIBIOS_SUCCESSFUL;
}
/* PCI configuration space read function */
static int oxnas_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
int size, u32 *val)
{
struct oxnas_pcie *pcie = sys_to_pcie(bus->sysdata);
unsigned offset;
u32 value;
u32 left_bytes, right_bytes;
/* Only a single device per bus for PCIe point-to-point links */
if (PCI_SLOT(devfn) > 0) {
*val = 0xffffffff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
if (!pcie->haslink) {
*val = 0xffffffff;
return PCIBIOS_DEVICE_NOT_FOUND;
}
offset = oxnas_pcie_cfg_to_offset(bus->sysdata, bus->number, devfn,
where);
value = readl_relaxed(pcie->cfgbase + offset);
left_bytes = where & 3;
right_bytes = 4 - left_bytes - size;
value <<= right_bytes * 8;
value >>= (left_bytes + right_bytes) * 8;
*val = value;
return PCIBIOS_SUCCESSFUL;
}
static struct pci_ops oxnas_pcie_ops = {
.read = oxnas_pcie_rd_conf,
.write = oxnas_pcie_wr_conf,
};
static int oxnas_pcie_setup(int nr, struct pci_sys_data *sys)
{
struct oxnas_pcie *pcie = sys_to_pcie(sys);
pci_add_resource_offset(&sys->resources, &pcie->non_mem, sys->mem_offset);
pci_add_resource_offset(&sys->resources, &pcie->pre_mem, sys->mem_offset);
pci_add_resource_offset(&sys->resources, &pcie->io, sys->io_offset);
pci_add_resource(&sys->resources, &pcie->busn);
if (sys->busnr == 0) { /* default one */
sys->busnr = pcie->busn.start;
}
/* do not use devm_ioremap_resource, it does not like cfg resource */
pcie->cfgbase = devm_ioremap(&pcie->pdev->dev, pcie->cfg.start,
resource_size(&pcie->cfg));
if (!pcie->cfgbase)
return -ENOMEM;
oxnas_pcie_setup_hw(pcie);
return 1;
}
static void oxnas_pcie_enable(struct device *dev, struct oxnas_pcie *pcie)
{
struct hw_pci hw;
int i;
memset(&hw, 0, sizeof(hw));
for (i = 0; i < NUM_CONTROLLERS; i++)
pcie->private_data[i] = pcie;
hw.nr_controllers = NUM_CONTROLLERS;
/* I think use stack pointer is a bad idea though it is valid in this case */
hw.private_data = pcie->private_data;
hw.setup = oxnas_pcie_setup;
hw.map_irq = of_irq_parse_and_map_pci;
hw.ops = &oxnas_pcie_ops;
/* pass dev to maintain of tree, interrupt mapping rely on this */
pci_common_init_dev(dev, &hw);
}
static int oxnas_pcie_shared_init(struct platform_device *pdev, struct oxnas_pcie *pcie)
{
if (++pcie_shared.refcount == 1) {
phy_init(pcie->phy);
phy_power_on(pcie->phy);
return 0;
} else {
return 0;
}
}
#if 0
/* maybe we will call it when enter low power state */
static void oxnas_pcie_shared_deinit(struct platform_device *pdev)
{
if (--pcie_shared.refcount == 0) {
/* no cleanup needed */;
}
}
#endif
static int
oxnas_pcie_map_registers(struct platform_device *pdev,
struct device_node *np,
struct oxnas_pcie *pcie)
{
struct resource regs;
int ret = 0;
u32 outbound_ctrl_offset;
u32 pcie_ctrl_offset;
ret = of_address_to_resource(np, 0, &regs);
if (ret) {
dev_err(&pdev->dev, "failed to parse base register space\n");
return -EINVAL;
}
pcie->base = devm_ioremap_resource(&pdev->dev, &regs);
if (!pcie->base) {
dev_err(&pdev->dev, "failed to map base register space\n");
return -ENOMEM;
}
ret = of_address_to_resource(np, 1, &regs);
if (ret) {
dev_err(&pdev->dev, "failed to parse inbound register space\n");
return -EINVAL;
}
pcie->inbound = devm_ioremap_resource(&pdev->dev, &regs);
if (!pcie->inbound) {
dev_err(&pdev->dev, "failed to map inbound register space\n");
return -ENOMEM;
}
pcie->phy = devm_of_phy_get(&pdev->dev, np, NULL);
if (IS_ERR(pcie->phy)) {
if (PTR_ERR(pcie->phy) == -EPROBE_DEFER) {
dev_err(&pdev->dev, "failed to probe phy\n");
return PTR_ERR(pcie->phy);
}
dev_warn(&pdev->dev, "phy not attached\n");
pcie->phy = NULL;
}
if (of_property_read_u32(np, "plxtech,pcie-outbound-offset",
&outbound_ctrl_offset)) {
dev_err(&pdev->dev, "failed to parse outbound register offset\n");
return -EINVAL;
}
pcie->outbound_offset = outbound_ctrl_offset;
if (of_property_read_u32(np, "plxtech,pcie-ctrl-offset",
&pcie_ctrl_offset)) {
dev_err(&pdev->dev, "failed to parse pcie-ctrl register offset\n");
return -EINVAL;
}
pcie->pcie_ctrl_offset = pcie_ctrl_offset;
return 0;
}
static int oxnas_pcie_init_res(struct platform_device *pdev,
struct oxnas_pcie *pcie,
struct device_node *np)
{
struct of_pci_range range;
struct of_pci_range_parser parser;
int ret;
if (of_pci_range_parser_init(&parser, np))
return -EINVAL;
/* Get the I/O and memory ranges from DT */
for_each_of_pci_range(&parser, &range) {
unsigned long restype = range.flags & IORESOURCE_TYPE_BITS;
if (restype == IORESOURCE_IO) {
of_pci_range_to_resource(&range, np, &pcie->io);
pcie->io.name = "I/O";
}
if (restype == IORESOURCE_MEM) {
if (range.flags & IORESOURCE_PREFETCH) {
of_pci_range_to_resource(&range, np, &pcie->pre_mem);
pcie->pre_mem.name = "PRE MEM";
} else {
of_pci_range_to_resource(&range, np, &pcie->non_mem);
pcie->non_mem.name = "NON MEM";
}
}
if (restype == 0)
of_pci_range_to_resource(&range, np, &pcie->cfg);
}
/* Get the bus range */
ret = of_pci_parse_bus_range(np, &pcie->busn);
if (ret) {
dev_err(&pdev->dev, "failed to parse bus-range property: %d\n",
ret);
return ret;
}
pcie->card_reset = of_get_gpio(np, 0);
if (pcie->card_reset < 0)
dev_info(&pdev->dev, "card reset gpio pin not exists\n");
if (of_property_read_u32(np, "plxtech,pcie-hcsl-bit", &pcie->hcsl_en))
return -EINVAL;
pcie->clk = of_clk_get_by_name(np, "pcie");
if (IS_ERR(pcie->clk)) {
return PTR_ERR(pcie->clk);
}
pcie->busclk = of_clk_get_by_name(np, "busclk");
if (IS_ERR(pcie->busclk)) {
clk_put(pcie->clk);
return PTR_ERR(pcie->busclk);
}
return 0;
}
static void oxnas_pcie_init_hw(struct platform_device *pdev,
struct oxnas_pcie *pcie)
{
u32 version_id;
int ret;
clk_prepare_enable(pcie->busclk);
/* reset PCIe cards use hard-wired gpio pin */
if (pcie->card_reset >= 0 &&
!gpio_direction_output(pcie->card_reset, 0)) {
wmb();
mdelay(10);
/* must tri-state the pin to pull it up */
gpio_direction_input(pcie->card_reset);
wmb();
mdelay(100);
}
/* ToDo: use phy power-on port... */
regmap_update_bits(pcie->sys_ctrl, SYS_CTRL_HCSL_CTRL_REGOFFSET,
BIT(pcie->hcsl_en), BIT(pcie->hcsl_en));
/* core */
ret = device_reset(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "core reset failed %d\n", ret);
return;
}
/* Start PCIe core clocks */
clk_prepare_enable(pcie->clk);
version_id = readl_relaxed(pcie->base + PCI_CONFIG_VERSION_DEVICEID);
dev_info(&pdev->dev, "PCIe version/deviceID 0x%x\n", version_id);
if (version_id != VERSION_ID_MAGIC) {
dev_info(&pdev->dev, "PCIe controller not found\n");
pcie->haslink = 0;
return;
}
/* allow entry to L23 state */
regmap_write_bits(pcie->sys_ctrl, pcie->pcie_ctrl_offset,
PCIE_READY_ENTR_L23, PCIE_READY_ENTR_L23);
/* Set PCIe core into RootCore mode */
regmap_write_bits(pcie->sys_ctrl, pcie->pcie_ctrl_offset,
PCIE_DEVICE_TYPE_MASK, PCIE_DEVICE_TYPE_ROOT);
wmb();
/* Bring up the PCI core */
regmap_write_bits(pcie->sys_ctrl, pcie->pcie_ctrl_offset,
PCIE_LTSSM, PCIE_LTSSM);
wmb();
}
static int oxnas_pcie_probe(struct platform_device *pdev)
{
struct oxnas_pcie *pcie;
struct device_node *np = pdev->dev.of_node;
int ret;
pcie = devm_kzalloc(&pdev->dev, sizeof(struct oxnas_pcie),
GFP_KERNEL);
if (!pcie)
return -ENOMEM;
pcie->pdev = pdev;
pcie->haslink = 1;
spin_lock_init(&pcie->lock);
pcie->sys_ctrl = syscon_regmap_lookup_by_compatible("oxsemi,ox820-sys-ctrl");
if (IS_ERR(pcie->sys_ctrl))
return PTR_ERR(pcie->sys_ctrl);
ret = oxnas_pcie_init_res(pdev, pcie, np);
if (ret)
return ret;
if (pcie->card_reset >= 0) {
ret = gpio_request_one(pcie->card_reset, GPIOF_DIR_IN,
dev_name(&pdev->dev));
if (ret) {
dev_err(&pdev->dev, "cannot request gpio pin %d\n",
pcie->card_reset);
return ret;
}
}
ret = oxnas_pcie_map_registers(pdev, np, pcie);
if (ret) {
dev_err(&pdev->dev, "cannot map registers\n");
goto err_free_gpio;
}
ret = oxnas_pcie_shared_init(pdev, pcie);
if (ret)
goto err_free_gpio;
/* if hw not found, haslink cleared */
oxnas_pcie_init_hw(pdev, pcie);
if (pcie->haslink && oxnas_pcie_link_up(pcie)) {
pcie->haslink = 1;
dev_info(&pdev->dev, "link up\n");
} else {
pcie->haslink = 0;
dev_info(&pdev->dev, "link down\n");
}
/* should we register our controller even when pcie->haslink is 0 ? */
/* register the controller with framework */
oxnas_pcie_enable(&pdev->dev, pcie);
return 0;
err_free_gpio:
if (pcie->card_reset)
gpio_free(pcie->card_reset);
return ret;
}
static const struct of_device_id oxnas_pcie_of_match_table[] = {
{ .compatible = "plxtech,nas782x-pcie", },
{},
};
static struct platform_driver oxnas_pcie_driver = {
.driver = {
.name = "oxnas-pcie",
.suppress_bind_attrs = true,
.of_match_table = oxnas_pcie_of_match_table,
},
.probe = oxnas_pcie_probe,
};
builtin_platform_driver(oxnas_pcie_driver);

View File

@ -0,0 +1,148 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019 Daniel Golle <daniel@makrotopia.org>
*
*/
#include <dt-bindings/phy/phy.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/mfd/syscon.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#define ADDR_VAL(val) ((val) & 0xFFFF)
#define DATA_VAL(val) ((val) & 0xFFFF)
#define SYS_CTRL_HCSL_CTRL_REGOFFSET 0x114
enum {
HCSL_BIAS_ON = BIT(0),
HCSL_PCIE_EN = BIT(1),
HCSL_PCIEA_EN = BIT(2),
HCSL_PCIEB_EN = BIT(3),
};
enum {
/* pcie phy reg offset */
PHY_ADDR = 0,
PHY_DATA = 4,
/* phy data reg bits */
READ_EN = BIT(16),
WRITE_EN = BIT(17),
CAP_DATA = BIT(18),
};
struct oxnas_pcie_phy {
struct device *dev;
void __iomem *membase;
const struct phy_ops *ops;
struct regmap *sys_ctrl;
struct reset_control *rstc;
};
static int oxnas_pcie_phy_init(struct phy *phy)
{
struct oxnas_pcie_phy *pciephy = phy_get_drvdata(phy);
int ret;
/* generate clocks from HCSL buffers, shared parts */
regmap_write(pciephy->sys_ctrl, SYS_CTRL_HCSL_CTRL_REGOFFSET, HCSL_BIAS_ON|HCSL_PCIE_EN);
/* Ensure PCIe PHY is properly reset */
ret = reset_control_reset(pciephy->rstc);
if (ret) {
dev_err(pciephy->dev, "phy reset failed %d\n", ret);
return ret;
}
return 0;
}
static int oxnas_pcie_phy_power_on(struct phy *phy)
{
struct oxnas_pcie_phy *pciephy = phy_get_drvdata(phy);
/* Enable PCIe Pre-Emphasis: What these value means? */
writel(ADDR_VAL(0x0014), pciephy->membase + PHY_ADDR);
writel(DATA_VAL(0xce10) | CAP_DATA, pciephy->membase + PHY_DATA);
writel(DATA_VAL(0xce10) | WRITE_EN, pciephy->membase + PHY_DATA);
writel(ADDR_VAL(0x2004), pciephy->membase + PHY_ADDR);
writel(DATA_VAL(0x82c7) | CAP_DATA, pciephy->membase + PHY_DATA);
writel(DATA_VAL(0x82c7) | WRITE_EN, pciephy->membase + PHY_DATA);
return 0;
}
static const struct phy_ops ops = {
.init = oxnas_pcie_phy_init,
.power_on = oxnas_pcie_phy_power_on,
.owner = THIS_MODULE,
};
static int oxnas_pcie_phy_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = pdev->dev.of_node;
struct phy *generic_phy;
struct phy_provider *phy_provider;
struct oxnas_pcie_phy *pciephy;
struct regmap *sys_ctrl;
struct reset_control *rstc;
void __iomem *membase;
membase = of_iomap(np, 0);
if (IS_ERR(membase))
return PTR_ERR(membase);
sys_ctrl = syscon_regmap_lookup_by_compatible("oxsemi,ox820-sys-ctrl");
if (IS_ERR(sys_ctrl))
return PTR_ERR(sys_ctrl);
rstc = devm_reset_control_get_shared(dev, "phy");
if (IS_ERR(rstc))
return PTR_ERR(rstc);
pciephy = devm_kzalloc(dev, sizeof(*pciephy), GFP_KERNEL);
if (!pciephy)
return -ENOMEM;
pciephy->sys_ctrl = sys_ctrl;
pciephy->rstc = rstc;
pciephy->membase = membase;
pciephy->dev = dev;
pciephy->ops = &ops;
generic_phy = devm_phy_create(dev, dev->of_node, pciephy->ops);
if (IS_ERR(generic_phy)) {
dev_err(dev, "failed to create PHY\n");
return PTR_ERR(generic_phy);
}
phy_set_drvdata(generic_phy, pciephy);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
return PTR_ERR_OR_ZERO(phy_provider);
}
static const struct of_device_id oxnas_pcie_phy_id_table[] = {
{ .compatible = "oxsemi,ox820-pcie-phy" },
{ },
};
static struct platform_driver oxnas_pcie_phy_driver = {
.probe = oxnas_pcie_phy_probe,
.driver = {
.name = "ox820-pcie-phy",
.of_match_table = oxnas_pcie_phy_id_table,
},
};
builtin_platform_driver(oxnas_pcie_phy_driver);

View File

@ -0,0 +1,229 @@
// SPDX-License-Identifier: (GPL-2.0)
/*
* oxnas SoC reset driver
* based on:
* Microsemi MIPS SoC reset driver
* and ox820_assert_system_reset() written by Ma Hajun <mahaijuns@gmail.com>
*
* License: GPL
* Copyright (c) 2013 Ma Hajun <mahaijuns@gmail.com>
* Copyright (c) 2017 Microsemi Corporation
* Copyright (c) 2019 Daniel Golle <daniel@makrotopia.org>
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/notifier.h>
#include <linux/mfd/syscon.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/reboot.h>
#include <linux/regmap.h>
/* bit numbers of reset control register */
#define OX820_SYS_CTRL_RST_SCU 0
#define OX820_SYS_CTRL_RST_COPRO 1
#define OX820_SYS_CTRL_RST_ARM0 2
#define OX820_SYS_CTRL_RST_ARM1 3
#define OX820_SYS_CTRL_RST_USBHS 4
#define OX820_SYS_CTRL_RST_USBHSPHYA 5
#define OX820_SYS_CTRL_RST_MACA 6
#define OX820_SYS_CTRL_RST_MAC OX820_SYS_CTRL_RST_MACA
#define OX820_SYS_CTRL_RST_PCIEA 7
#define OX820_SYS_CTRL_RST_SGDMA 8
#define OX820_SYS_CTRL_RST_CIPHER 9
#define OX820_SYS_CTRL_RST_DDR 10
#define OX820_SYS_CTRL_RST_SATA 11
#define OX820_SYS_CTRL_RST_SATA_LINK 12
#define OX820_SYS_CTRL_RST_SATA_PHY 13
#define OX820_SYS_CTRL_RST_PCIEPHY 14
#define OX820_SYS_CTRL_RST_STATIC 15
#define OX820_SYS_CTRL_RST_GPIO 16
#define OX820_SYS_CTRL_RST_UART1 17
#define OX820_SYS_CTRL_RST_UART2 18
#define OX820_SYS_CTRL_RST_MISC 19
#define OX820_SYS_CTRL_RST_I2S 20
#define OX820_SYS_CTRL_RST_SD 21
#define OX820_SYS_CTRL_RST_MACB 22
#define OX820_SYS_CTRL_RST_PCIEB 23
#define OX820_SYS_CTRL_RST_VIDEO 24
#define OX820_SYS_CTRL_RST_DDR_PHY 25
#define OX820_SYS_CTRL_RST_USBHSPHYB 26
#define OX820_SYS_CTRL_RST_USBDEV 27
#define OX820_SYS_CTRL_RST_ARMDBG 29
#define OX820_SYS_CTRL_RST_PLLA 30
#define OX820_SYS_CTRL_RST_PLLB 31
/* bit numbers of clock control register */
#define OX820_SYS_CTRL_CLK_COPRO 0
#define OX820_SYS_CTRL_CLK_DMA 1
#define OX820_SYS_CTRL_CLK_CIPHER 2
#define OX820_SYS_CTRL_CLK_SD 3
#define OX820_SYS_CTRL_CLK_SATA 4
#define OX820_SYS_CTRL_CLK_I2S 5
#define OX820_SYS_CTRL_CLK_USBHS 6
#define OX820_SYS_CTRL_CLK_MACA 7
#define OX820_SYS_CTRL_CLK_MAC OX820_SYS_CTRL_CLK_MACA
#define OX820_SYS_CTRL_CLK_PCIEA 8
#define OX820_SYS_CTRL_CLK_STATIC 9
#define OX820_SYS_CTRL_CLK_MACB 10
#define OX820_SYS_CTRL_CLK_PCIEB 11
#define OX820_SYS_CTRL_CLK_REF600 12
#define OX820_SYS_CTRL_CLK_USBDEV 13
#define OX820_SYS_CTRL_CLK_DDR 14
#define OX820_SYS_CTRL_CLK_DDRPHY 15
#define OX820_SYS_CTRL_CLK_DDRCK 16
/* Regmap offsets */
#define OX820_CLK_SET_REGOFFSET 0x2c
#define OX820_CLK_CLR_REGOFFSET 0x30
#define OX820_RST_SET_REGOFFSET 0x34
#define OX820_RST_CLR_REGOFFSET 0x38
#define OX820_SECONDARY_SEL_REGOFFSET 0x14
#define OX820_TERTIARY_SEL_REGOFFSET 0x8c
#define OX820_QUATERNARY_SEL_REGOFFSET 0x94
#define OX820_DEBUG_SEL_REGOFFSET 0x9c
#define OX820_ALTERNATIVE_SEL_REGOFFSET 0xa4
#define OX820_PULLUP_SEL_REGOFFSET 0xac
#define OX820_SEC_SECONDARY_SEL_REGOFFSET 0x100014
#define OX820_SEC_TERTIARY_SEL_REGOFFSET 0x10008c
#define OX820_SEC_QUATERNARY_SEL_REGOFFSET 0x100094
#define OX820_SEC_DEBUG_SEL_REGOFFSET 0x10009c
#define OX820_SEC_ALTERNATIVE_SEL_REGOFFSET 0x1000a4
#define OX820_SEC_PULLUP_SEL_REGOFFSET 0x1000ac
struct oxnas_restart_context {
struct regmap *sys_ctrl;
struct notifier_block restart_handler;
};
static int ox820_restart_handle(struct notifier_block *this,
unsigned long mode, void *cmd)
{
struct oxnas_restart_context *ctx = container_of(this, struct
oxnas_restart_context,
restart_handler);
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(OX820_SYS_CTRL_RST_COPRO) |
BIT(OX820_SYS_CTRL_RST_USBHS) |
BIT(OX820_SYS_CTRL_RST_USBHSPHYA) |
BIT(OX820_SYS_CTRL_RST_MACA) |
BIT(OX820_SYS_CTRL_RST_PCIEA) |
BIT(OX820_SYS_CTRL_RST_SGDMA) |
BIT(OX820_SYS_CTRL_RST_CIPHER) |
BIT(OX820_SYS_CTRL_RST_SATA) |
BIT(OX820_SYS_CTRL_RST_SATA_LINK) |
BIT(OX820_SYS_CTRL_RST_SATA_PHY) |
BIT(OX820_SYS_CTRL_RST_PCIEPHY) |
BIT(OX820_SYS_CTRL_RST_STATIC) |
BIT(OX820_SYS_CTRL_RST_UART1) |
BIT(OX820_SYS_CTRL_RST_UART2) |
BIT(OX820_SYS_CTRL_RST_MISC) |
BIT(OX820_SYS_CTRL_RST_I2S) |
BIT(OX820_SYS_CTRL_RST_SD) |
BIT(OX820_SYS_CTRL_RST_MACB) |
BIT(OX820_SYS_CTRL_RST_PCIEB) |
BIT(OX820_SYS_CTRL_RST_VIDEO) |
BIT(OX820_SYS_CTRL_RST_USBHSPHYB) |
BIT(OX820_SYS_CTRL_RST_USBDEV);
regmap_write(ctx->sys_ctrl, OX820_RST_SET_REGOFFSET, value);
/* Release reset to cores as per power on defaults */
regmap_write(ctx->sys_ctrl, OX820_RST_CLR_REGOFFSET, BIT(OX820_SYS_CTRL_RST_GPIO));
/* Disable clocks to cores as per power-on defaults - must leave DDR
* related clocks enabled otherwise we'll stop rather abruptly. */
value =
BIT(OX820_SYS_CTRL_CLK_COPRO) |
BIT(OX820_SYS_CTRL_CLK_DMA) |
BIT(OX820_SYS_CTRL_CLK_CIPHER) |
BIT(OX820_SYS_CTRL_CLK_SD) |
BIT(OX820_SYS_CTRL_CLK_SATA) |
BIT(OX820_SYS_CTRL_CLK_I2S) |
BIT(OX820_SYS_CTRL_CLK_USBHS) |
BIT(OX820_SYS_CTRL_CLK_MAC) |
BIT(OX820_SYS_CTRL_CLK_PCIEA) |
BIT(OX820_SYS_CTRL_CLK_STATIC) |
BIT(OX820_SYS_CTRL_CLK_MACB) |
BIT(OX820_SYS_CTRL_CLK_PCIEB) |
BIT(OX820_SYS_CTRL_CLK_REF600) |
BIT(OX820_SYS_CTRL_CLK_USBDEV);
regmap_write(ctx->sys_ctrl, OX820_CLK_CLR_REGOFFSET, value);
/* Enable clocks to cores as per power-on defaults */
/* Set sys-control pin mux'ing as per power-on defaults */
regmap_write(ctx->sys_ctrl, OX820_SECONDARY_SEL_REGOFFSET, 0);
regmap_write(ctx->sys_ctrl, OX820_TERTIARY_SEL_REGOFFSET, 0);
regmap_write(ctx->sys_ctrl, OX820_QUATERNARY_SEL_REGOFFSET, 0);
regmap_write(ctx->sys_ctrl, OX820_DEBUG_SEL_REGOFFSET, 0);
regmap_write(ctx->sys_ctrl, OX820_ALTERNATIVE_SEL_REGOFFSET, 0);
regmap_write(ctx->sys_ctrl, OX820_PULLUP_SEL_REGOFFSET, 0);
regmap_write(ctx->sys_ctrl, OX820_SEC_SECONDARY_SEL_REGOFFSET, 0);
regmap_write(ctx->sys_ctrl, OX820_SEC_TERTIARY_SEL_REGOFFSET, 0);
regmap_write(ctx->sys_ctrl, OX820_SEC_QUATERNARY_SEL_REGOFFSET, 0);
regmap_write(ctx->sys_ctrl, OX820_SEC_DEBUG_SEL_REGOFFSET, 0);
regmap_write(ctx->sys_ctrl, OX820_SEC_ALTERNATIVE_SEL_REGOFFSET, 0);
regmap_write(ctx->sys_ctrl, OX820_SEC_PULLUP_SEL_REGOFFSET, 0);
/* 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(OX820_SYS_CTRL_RST_SCU) |
BIT(OX820_SYS_CTRL_RST_ARM0) |
BIT(OX820_SYS_CTRL_RST_ARM1);
regmap_write(ctx->sys_ctrl, OX820_RST_SET_REGOFFSET, value);
pr_emerg("Unable to restart system\n");
return NOTIFY_DONE;
}
static int ox820_restart_probe(struct platform_device *pdev)
{
struct oxnas_restart_context *ctx;
struct regmap *sys_ctrl;
struct device *dev = &pdev->dev;
int err = 0;
sys_ctrl = syscon_node_to_regmap(pdev->dev.of_node);
if (IS_ERR(sys_ctrl))
return PTR_ERR(sys_ctrl);
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
ctx->sys_ctrl = sys_ctrl;
ctx->restart_handler.notifier_call = ox820_restart_handle;
ctx->restart_handler.priority = 192;
err = register_restart_handler(&ctx->restart_handler);
if (err)
dev_err(dev, "can't register restart notifier (err=%d)\n", err);
return err;
}
static const struct of_device_id ox820_restart_of_match[] = {
{ .compatible = "oxsemi,ox820-sys-ctrl" },
{}
};
static struct platform_driver ox820_restart_driver = {
.probe = ox820_restart_probe,
.driver = {
.name = "ox820-chip-reset",
.of_match_table = ox820_restart_of_match,
},
};
builtin_platform_driver(ox820_restart_driver);

View File

@ -0,0 +1,368 @@
/*
* drivers/usb/host/ehci-oxnas.c
*
* Tzachi Perelstein <tzachi@marvell.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/mfd/syscon.h>
#include <linux/usb.h>
#include <linux/usb/hcd.h>
#include <linux/dma-mapping.h>
#include <linux/clk.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#define USBHSMPH_CTRL_REGOFFSET 0x40
#define USBHSMPH_STAT_REGOFFSET 0x44
#define REF300_DIV_REGOFFSET 0xF8
#define USBHSPHY_CTRL_REGOFFSET 0x84
#define USB_CTRL_REGOFFSET 0x90
#define PLLB_DIV_CTRL_REGOFFSET 0x1000F8
#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 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 PLLB_BYPASS 1
#define PLLB_ENSAT 3
#define PLLB_OUTDIV 4
#define PLLB_REFDIV 8
#define PLLB_DIV_INT_SHIFT 8
#define PLLB_DIV_FRAC_SHIFT 0
#define PLLB_DIV_INT(val) ((val) << PLLB_DIV_INT_SHIFT)
#define PLLB_DIV_FRAC(val) ((val) << PLLB_DIV_FRAC_SHIFT)
#include "ehci.h"
struct oxnas_hcd {
struct clk *clk;
struct clk *refsrc;
struct clk *phyref;
int use_pllb;
int use_phya;
struct reset_control *rst_host;
struct reset_control *rst_phya;
struct reset_control *rst_phyb;
struct regmap *syscon;
};
#define DRIVER_DESC "Oxnas On-Chip EHCI Host Controller"
static struct hc_driver __read_mostly oxnas_hc_driver;
static void start_oxnas_usb_ehci(struct oxnas_hcd *oxnas)
{
if (oxnas->use_pllb) {
/* enable pllb */
clk_prepare_enable(oxnas->refsrc);
/* enable ref600 */
clk_prepare_enable(oxnas->phyref);
/* 600MHz pllb divider for 12MHz */
regmap_write_bits(oxnas->syscon, PLLB_DIV_CTRL_REGOFFSET, 0xffff, PLLB_DIV_INT(50) | PLLB_DIV_FRAC(0));
} else {
/* ref 300 divider for 12MHz */
regmap_write_bits(oxnas->syscon, REF300_DIV_REGOFFSET, 0xffff, REF300_DIV_INT(25) | REF300_DIV_FRAC(0));
}
/* Ensure the USB block is properly reset */
reset_control_reset(oxnas->rst_host);
reset_control_reset(oxnas->rst_phya);
reset_control_reset(oxnas->rst_phyb);
/* Force the high speed clock to be generated all the time, via serial
programming of the USB HS PHY */
regmap_write_bits(oxnas->syscon, USBHSPHY_CTRL_REGOFFSET, 0xffff,
(2UL << USBHSPHY_TEST_ADD) |
(0xe0UL << USBHSPHY_TEST_DIN));
regmap_write_bits(oxnas->syscon, USBHSPHY_CTRL_REGOFFSET, 0xffff,
(1UL << USBHSPHY_TEST_CLK) |
(2UL << USBHSPHY_TEST_ADD) |
(0xe0UL << USBHSPHY_TEST_DIN));
regmap_write_bits(oxnas->syscon, USBHSPHY_CTRL_REGOFFSET, 0xffff,
(0xfUL << USBHSPHY_TEST_ADD) |
(0xaaUL << USBHSPHY_TEST_DIN));
regmap_write_bits(oxnas->syscon, USBHSPHY_CTRL_REGOFFSET, 0xffff,
(1UL << USBHSPHY_TEST_CLK) |
(0xfUL << USBHSPHY_TEST_ADD) |
(0xaaUL << USBHSPHY_TEST_DIN));
if (oxnas->use_pllb) /* use pllb clock */
regmap_write_bits(oxnas->syscon, USB_CTRL_REGOFFSET, 0xffff,
USB_CLK_INTERNAL | USB_INT_CLK_PLLB);
else /* use ref300 derived clock */
regmap_write_bits(oxnas->syscon, USB_CTRL_REGOFFSET, 0xffff,
USB_CLK_INTERNAL | USB_INT_CLK_REF300);
if (oxnas->use_phya) {
/* Configure USB PHYA as a host */
regmap_update_bits(oxnas->syscon, USB_CTRL_REGOFFSET, USBAMUX_DEVICE, 0);
}
/* Enable the clock to the USB block */
clk_prepare_enable(oxnas->clk);
}
static void stop_oxnas_usb_ehci(struct oxnas_hcd *oxnas)
{
reset_control_assert(oxnas->rst_host);
reset_control_assert(oxnas->rst_phya);
reset_control_assert(oxnas->rst_phyb);
if (oxnas->use_pllb) {
clk_disable_unprepare(oxnas->phyref);
clk_disable_unprepare(oxnas->refsrc);
}
clk_disable_unprepare(oxnas->clk);
}
static int ehci_oxnas_reset(struct usb_hcd *hcd)
{
#define txttfill_tuning reserved2[0]
struct ehci_hcd *ehci;
u32 tmp;
int retval = ehci_setup(hcd);
if (retval)
return retval;
ehci = hcd_to_ehci(hcd);
tmp = ehci_readl(ehci, &ehci->regs->txfill_tuning);
tmp &= ~0x00ff0000;
tmp |= 0x003f0000; /* set burst pre load count to 0x40 (63 * 4 bytes) */
tmp |= 0x16; /* set sheduler overhead to 22 * 1.267us (HS) or 22 * 6.33us (FS/LS)*/
ehci_writel(ehci, tmp, &ehci->regs->txfill_tuning);
tmp = ehci_readl(ehci, &ehci->regs->txttfill_tuning);
tmp |= 0x2; /* set sheduler overhead to 2 * 6.333us */
ehci_writel(ehci, tmp, &ehci->regs->txttfill_tuning);
return retval;
}
static int ehci_oxnas_drv_probe(struct platform_device *ofdev)
{
struct device_node *np = ofdev->dev.of_node;
struct usb_hcd *hcd;
struct ehci_hcd *ehci;
struct resource res;
struct oxnas_hcd *oxnas;
int irq, err;
struct reset_control *rstc;
if (usb_disabled())
return -ENODEV;
if (!ofdev->dev.dma_mask)
ofdev->dev.dma_mask = &ofdev->dev.coherent_dma_mask;
if (!ofdev->dev.coherent_dma_mask)
ofdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
hcd = usb_create_hcd(&oxnas_hc_driver, &ofdev->dev,
dev_name(&ofdev->dev));
if (!hcd)
return -ENOMEM;
err = of_address_to_resource(np, 0, &res);
if (err)
goto err_res;
hcd->rsrc_start = res.start;
hcd->rsrc_len = resource_size(&res);
hcd->regs = devm_ioremap_resource(&ofdev->dev, &res);
if (IS_ERR(hcd->regs)) {
dev_err(&ofdev->dev, "devm_ioremap_resource failed\n");
err = PTR_ERR(hcd->regs);
goto err_ioremap;
}
oxnas = (struct oxnas_hcd *)hcd_to_ehci(hcd)->priv;
oxnas->use_pllb = of_property_read_bool(np, "oxsemi,ehci_use_pllb");
oxnas->use_phya = of_property_read_bool(np, "oxsemi,ehci_use_phya");
oxnas->syscon = syscon_regmap_lookup_by_phandle(np, "oxsemi,sys-ctrl");
if (IS_ERR(oxnas->syscon)) {
err = PTR_ERR(oxnas->syscon);
goto err_syscon;
}
oxnas->clk = of_clk_get_by_name(np, "usb");
if (IS_ERR(oxnas->clk)) {
err = PTR_ERR(oxnas->clk);
goto err_clk;
}
if (oxnas->use_pllb) {
oxnas->refsrc = of_clk_get_by_name(np, "refsrc");
if (IS_ERR(oxnas->refsrc)) {
err = PTR_ERR(oxnas->refsrc);
goto err_refsrc;
}
oxnas->phyref = of_clk_get_by_name(np, "phyref");
if (IS_ERR(oxnas->refsrc)) {
err = PTR_ERR(oxnas->refsrc);
goto err_phyref;
}
} else {
oxnas->refsrc = NULL;
oxnas->phyref = NULL;
}
rstc = devm_reset_control_get(&ofdev->dev, "host");
if (IS_ERR(rstc)) {
err = PTR_ERR(rstc);
goto err_rst;
}
oxnas->rst_host = rstc;
rstc = devm_reset_control_get(&ofdev->dev, "phya");
if (IS_ERR(rstc)) {
err = PTR_ERR(rstc);
goto err_rst;
}
oxnas->rst_phya = rstc;
rstc = devm_reset_control_get(&ofdev->dev, "phyb");
if (IS_ERR(rstc)) {
err = PTR_ERR(rstc);
goto err_rst;
}
oxnas->rst_phyb = rstc;
irq = irq_of_parse_and_map(np, 0);
if (!irq) {
dev_err(&ofdev->dev, "irq_of_parse_and_map failed\n");
err = -EBUSY;
goto err_irq;
}
hcd->has_tt = 1;
ehci = hcd_to_ehci(hcd);
ehci->caps = hcd->regs;
start_oxnas_usb_ehci(oxnas);
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err)
goto err_hcd;
return 0;
err_hcd:
stop_oxnas_usb_ehci(oxnas);
err_irq:
err_rst:
if (oxnas->phyref)
clk_put(oxnas->phyref);
err_phyref:
if (oxnas->refsrc)
clk_put(oxnas->refsrc);
err_refsrc:
clk_put(oxnas->clk);
err_syscon:
err_clk:
err_ioremap:
err_res:
usb_put_hcd(hcd);
return err;
}
static int ehci_oxnas_drv_remove(struct platform_device *pdev)
{
struct usb_hcd *hcd = platform_get_drvdata(pdev);
struct oxnas_hcd *oxnas = (struct oxnas_hcd *)hcd_to_ehci(hcd)->priv;
usb_remove_hcd(hcd);
if (oxnas->use_pllb) {
clk_disable_unprepare(oxnas->phyref);
clk_put(oxnas->phyref);
clk_disable_unprepare(oxnas->refsrc);
clk_put(oxnas->refsrc);
}
clk_disable_unprepare(oxnas->clk);
usb_put_hcd(hcd);
return 0;
}
static const struct of_device_id oxnas_ehci_dt_ids[] = {
{ .compatible = "plxtech,nas782x-ehci" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, oxnas_ehci_dt_ids);
static struct platform_driver ehci_oxnas_driver = {
.probe = ehci_oxnas_drv_probe,
.remove = ehci_oxnas_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver.name = "oxnas-ehci",
.driver.of_match_table = oxnas_ehci_dt_ids,
};
static const struct ehci_driver_overrides oxnas_overrides __initconst = {
.reset = ehci_oxnas_reset,
.extra_priv_size = sizeof(struct oxnas_hcd),
};
static int __init ehci_oxnas_init(void)
{
if (usb_disabled())
return -ENODEV;
ehci_init_driver(&oxnas_hc_driver, &oxnas_overrides);
return platform_driver_register(&ehci_oxnas_driver);
}
module_init(ehci_oxnas_init);
static void __exit ehci_oxnas_cleanup(void)
{
platform_driver_unregister(&ehci_oxnas_driver);
}
module_exit(ehci_oxnas_cleanup);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_ALIAS("platform:oxnas-ehci");
MODULE_LICENSE("GPL");

9
oxnas/image/Makefile Normal file
View File

@ -0,0 +1,9 @@
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/image.mk
VMLINUX:=$(BIN_DIR)/$(IMG_PREFIX)-vmlinux
UIMAGE:=$(BIN_DIR)/$(IMG_PREFIX)-uImage
include $(SUBTARGET).mk
$(eval $(call BuildImage))

20
oxnas/image/ox810se.mk Normal file
View File

@ -0,0 +1,20 @@
KERNEL_LOADADDR := 0x48008000
define Device/Default
KERNEL_NAME := zImage
KERNEL_SUFFIX := -uImage
KERNEL_INSTALL := 1
FILESYSTEMS := squashfs ext4
PROFILES := Default
DEVICE_DTS := ox810se-$(subst _,-,$(1))
IMAGES := sysupgrade.tar
IMAGE/sysupgrade.tar := sysupgrade-tar | append-metadata
endef
define Device/wd_mbwe
DEVICE_VENDOR := Western Digital
DEVICE_MODEL := My Book
DEVICE_VARIANT := World Edition
KERNEL := kernel-bin | append-dtb | uImage none
endef
TARGET_DEVICES += wd_mbwe

84
oxnas/image/ox820.mk Normal file
View File

@ -0,0 +1,84 @@
UBIFS_OPTS := -m 2048 -e 126KiB -c 4096
KERNEL_LOADADDR := 0x60008000
define Device/Default
KERNEL_NAME := zImage
KERNEL_SUFFIX := -uImage
KERNEL_INSTALL := 1
BLOCKSIZE := 128k
PAGESIZE := 2048
SUBPAGESIZE := 512
FILESYSTEMS := squashfs ubifs
PROFILES := Default
DEVICE_DTS := ox820-$(subst _,-,$(1))
KERNEL := kernel-bin | append-dtb | uImage none
IMAGES := ubinized.bin sysupgrade.tar
IMAGE/ubinized.bin := append-ubi
IMAGE/sysupgrade.tar := sysupgrade-tar | append-metadata
endef
define Build/omninas-factory
rm -rf $@.tmp $@.dummy $@.dummy.gz
mkdir -p $@.tmp
$(CP) $@ $@.tmp/uImage
dd if=/dev/zero bs=64k count=4 of=$@.dummy
gzip $@.dummy
mkimage -A arm -T ramdisk -C gzip -n "dummy" \
-d $@.dummy.gz \
$@.tmp/rdimg.gz
echo 2.35.20140102 > $@.tmp/version ; echo >> $@.tmp/version
chmod 0744 $@.tmp/*
$(TAR) -C $@.tmp -czvf $@ \
$(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") .
endef
define Build/encrypt-3des
openssl enc -des3 -a -k $(1) -in $@ -out $@.new && mv $@.new $@
endef
define Device/akitio_mycloud
DEVICE_VENDOR := Akitio
DEVICE_MODEL := MyCloud Mini
SUPPORTED_DEVICES += akitio
DEVICE_PACKAGES := kmod-ata-oxnas-sata kmod-i2c-gpio kmod-rtc-ds1307 \
kmod-usb2-oxnas kmod-usb-ledtrig-usbport
endef
TARGET_DEVICES += akitio_mycloud
define Device/cloudengines_pogoplugpro
DEVICE_VENDOR := Cloud Engines
DEVICE_MODEL := PogoPlug Pro (with mPCIe)
SUPPORTED_DEVICES += pogoplug-pro
DEVICE_PACKAGES := kmod-usb2-oxnas kmod-usb-ledtrig-usbport \
kmod-ata-oxnas-sata kmod-rt2800-pci wpad-basic-mbedtls
endef
TARGET_DEVICES += cloudengines_pogoplugpro
define Device/cloudengines_pogoplug-series-3
DEVICE_VENDOR := Cloud Engines
DEVICE_MODEL := PogoPlug Series V3 (without mPCIe)
SUPPORTED_DEVICES += cloudengines,pogoplugv3 pogoplug-v3
DEVICE_PACKAGES := kmod-usb2-oxnas kmod-usb-ledtrig-usbport \
kmod-ata-oxnas-sata
endef
TARGET_DEVICES += cloudengines_pogoplug-series-3
define Device/shuttle_kd20
DEVICE_VENDOR := Shuttle
DEVICE_MODEL := KD20
SUPPORTED_DEVICES += kd20
DEVICE_PACKAGES := kmod-usb2-oxnas kmod-usb3 kmod-usb-ledtrig-usbport \
kmod-i2c-gpio kmod-rtc-pcf8563 kmod-gpio-beeper kmod-hwmon-drivetemp \
kmod-hwmon-gpiofan kmod-ata-oxnas-sata kmod-md-mod kmod-md-raid0 \
kmod-md-raid1 kmod-fs-ext4 kmod-fs-xfs
endef
TARGET_DEVICES += shuttle_kd20
define Device/mitrastar_stg-212
DEVICE_VENDOR := MitraStar
DEVICE_MODEL := STG-212
SUPPORTED_DEVICES += stg212
DEVICE_PACKAGES := kmod-ata-oxnas-sata kmod-fs-ext4 kmod-fs-xfs \
kmod-usb2-oxnas kmod-usb-ledtrig-usbport
endef
TARGET_DEVICES += mitrastar_stg-212

29
oxnas/modules.mk Normal file
View File

@ -0,0 +1,29 @@
define KernelPackage/ata-oxnas-sata
TITLE:=oxnas Serial ATA support
KCONFIG:=CONFIG_SATA_OXNAS
FILES:=$(LINUX_DIR)/drivers/ata/sata_oxnas.ko
AUTOLOAD:=$(call AutoLoad,41,sata_oxnas,1)
$(call AddDepends/ata,@TARGET_oxnas)
endef
define KernelPackage/ata-oxnas-sata/description
SATA support for OX934 core found in the OX8xx/PLX782x SoCs
endef
$(eval $(call KernelPackage,ata-oxnas-sata))
define KernelPackage/usb2-oxnas
TITLE:=OX820 EHCI driver
KCONFIG:=CONFIG_USB_EHCI_OXNAS
FILES:=$(LINUX_DIR)/drivers/usb/host/ehci-oxnas.ko
AUTOLOAD:=$(call AutoLoad,55,ehci-oxnas,1)
$(call AddDepends/usb,@TARGET_oxnas_ox820 +kmod-usb2)
endef
define KernelPackage/usb2-oxnas/description
This driver provides USB Device Controller support for the
EHCI USB host built-in to the OX820 SoC.
endef
$(eval $(call KernelPackage,usb2-oxnas))

View File

@ -0,0 +1,8 @@
# CONFIG_CACHE_L2X0 is not set
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_MENU=y
CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y
# CONFIG_DEBUG_UNCOMPRESS is not set
CONFIG_EXT4_FS=y
CONFIG_FS_MBCACHE=y
CONFIG_MACH_OX810SE=y

View File

@ -0,0 +1,10 @@
define Profile/Default
NAME:=Default Profile
PRIORITY:=1
endef
define Profile/Default/Description
Default package set compatible with most boards.
endef
$(eval $(call Profile,Default))

9
oxnas/ox810se/target.mk Normal file
View File

@ -0,0 +1,9 @@
FEATURES+=source-only
SUBTARGET:=ox810se
BOARDNAME:=OX810SE
CPU_TYPE:=arm926ej-s
define Target/Description
Oxford OX810SE
endef

View File

@ -0,0 +1,95 @@
CONFIG_ARCH_HAS_TICK_BROADCAST=y
# CONFIG_ARCH_MULTI_CPU_AUTO is not set
CONFIG_ARCH_MULTI_V6=y
CONFIG_ARCH_MULTI_V6_V7=y
CONFIG_ARCH_WANT_LIBATA_LEDS=y
CONFIG_ARM_GIC=y
CONFIG_ARM_HEAVY_MB=y
CONFIG_ATA_LEDS=y
CONFIG_CACHE_L2X0=y
# CONFIG_CACHE_L2X0_PMU is not set
CONFIG_CPU_32v6=y
CONFIG_CPU_32v6K=y
CONFIG_CPU_ABRT_EV6=y
# CONFIG_CPU_BPREDICT_DISABLE is not set
CONFIG_CPU_CACHE_V6=y
CONFIG_CPU_CACHE_VIPT=y
CONFIG_CPU_COPY_V6=y
CONFIG_CPU_HAS_ASID=y
# CONFIG_CPU_HOTPLUG_STATE_CONTROL is not set
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_MENU=y
CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y
CONFIG_CPU_PABRT_V6=y
CONFIG_CPU_RMAP=y
CONFIG_CPU_TLB_V6=y
CONFIG_CPU_V6K=y
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_DEBUG_LL=y
CONFIG_DEBUG_LL_INCLUDE="debug/8250.S"
CONFIG_DEBUG_LL_UART_8250=y
# CONFIG_DEBUG_UART_8250 is not set
# CONFIG_DEBUG_UART_8250_FLOW_CONTROL is not set
CONFIG_DEBUG_UART_8250_SHIFT=0
CONFIG_DEBUG_UART_PHYS=0x44200000
CONFIG_DEBUG_UART_VIRT=0xf4200000
CONFIG_DEBUG_UNCOMPRESS=y
CONFIG_DMA_CACHE_RWFO=y
CONFIG_FORCE_MAX_ZONEORDER=12
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_HAVE_ARM_SCU=y
CONFIG_HAVE_ARM_TWD=y
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_HW_BREAKPOINT=y
CONFIG_HAVE_SMP=y
CONFIG_HOTPLUG_CPU=y
CONFIG_LOCK_SPIN_ON_OWNER=y
CONFIG_MACH_OX820=y
CONFIG_MIGHT_HAVE_CACHE_L2X0=y
CONFIG_MIGHT_HAVE_PCI=y
# CONFIG_MTD_CFI is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_CORE=y
CONFIG_MTD_NAND_ECC=y
# CONFIG_MTD_NAND_ECC_SW_BCH is not set
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
# CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC is not set
CONFIG_MTD_NAND_OXNAS=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_UBI=y
CONFIG_MTD_UBI_BEB_LIMIT=20
CONFIG_MTD_UBI_BLOCK=y
CONFIG_MTD_UBI_WL_THRESHOLD=4096
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_NET_FLOW_LIMIT=y
CONFIG_NR_CPUS=16
CONFIG_OUTER_CACHE=y
CONFIG_OUTER_CACHE_SYNC=y
CONFIG_PCI=y
CONFIG_PCIEAER=y
CONFIG_PCIEPORTBUS=y
CONFIG_PCIE_OXNAS=y
CONFIG_PCIE_PME=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DOMAINS_GENERIC=y
CONFIG_PCI_MSI=y
CONFIG_PCI_MSI_IRQ_DOMAIN=y
# CONFIG_PL310_ERRATA_588369 is not set
# CONFIG_PL310_ERRATA_727915 is not set
# CONFIG_PL310_ERRATA_753970 is not set
# CONFIG_PL310_ERRATA_769419 is not set
CONFIG_PM_SLEEP_SMP=y
CONFIG_RFS_ACCEL=y
CONFIG_RPS=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
CONFIG_SMP=y
CONFIG_SMP_ON_UP=y
CONFIG_TREE_RCU=y
CONFIG_TREE_SRCU=y
CONFIG_UBIFS_FS=y
CONFIG_UBIFS_FS_SECURITY=y
CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress-ox820.h"
CONFIG_XPS=y

View File

@ -0,0 +1,17 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2016 OpenWrt.org
define Profile/Default
NAME:=Default Profile
PRIORITY:=1
PACKAGES:=\
kmod-i2c-gpio kmod-gpio-beeper kmod-hwmon-gpiofan \
kmod-rtc-pcf8563 kmod-rtc-ds1307 kmod-usb3
endef
define Profile/Default/Description
Default package set compatible with most boards.
endef
$(eval $(call Profile,Default))

8
oxnas/ox820/target.mk Normal file
View File

@ -0,0 +1,8 @@
SUBTARGET:=ox820
BOARDNAME:=OX820/NAS782x
CPU_TYPE:=mpcore
FEATURES+=nand pci pcie ubifs usb
define Target/Description
Oxford/PLXTECH OX820/NAS782x
endef

View File

@ -0,0 +1,82 @@
- add compatible string
- add console to bootargs
- add led aliases
- adjust nand partition table
---
--- a/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
+++ b/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
@@ -11,10 +11,10 @@
/ {
model = "Cloud Engines PogoPlug Series 3";
- compatible = "cloudengines,pogoplugv3", "oxsemi,ox820";
+ compatible = "cloudengines,pogoplug-series-3", "cloudengines,pogoplugv3", "oxsemi,ox820";
chosen {
- bootargs = "earlyprintk";
+ bootargs = "earlyprintk console=ttyS0,115200";
stdout-path = "serial0:115200n8";
};
@@ -27,24 +27,28 @@
serial0 = &uart0;
gpio0 = &gpio0;
gpio1 = &gpio1;
+ led-boot = &led_status;
+ led-failsafe = &led_warn;
+ led-running = &led_act;
+ led-upgrade = &led_warn;
};
leds {
compatible = "gpio-leds";
- blue {
+ led_status: blue {
label = "pogoplug:blue";
gpios = <&gpio0 2 0>;
default-state = "keep";
};
- orange {
+ led_warn: orange {
label = "pogoplug:orange";
gpios = <&gpio1 16 1>;
default-state = "keep";
};
- green {
+ led_act: green {
label = "pogoplug:green";
gpios = <&gpio1 17 1>;
default-state = "keep";
@@ -73,11 +77,27 @@
nand-ecc-algo = "hamming";
partition@0 {
- label = "boot";
- reg = <0x00000000 0x00e00000>;
+ label = "stage1";
+ reg = <0x00000000 0x00040000>;
read-only;
};
+ partition@40000 {
+ label = "u-boot";
+ reg = <0x00040000 0x00380000>;
+ read-only;
+ };
+
+ partition@3c0000 {
+ label = "u-boot-env";
+ reg = <0x003c0000 0x00080000>;
+ };
+
+ partition@440000 {
+ label = "kernel";
+ reg = <0x00440000 0x009c0000>;
+ };
+
partition@e00000 {
label = "ubi";
reg = <0x00e00000 0x07200000>;

View File

@ -0,0 +1,63 @@
From 552ed4955c1fee1109bf5ba137dc35a411a1448c Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Fri, 1 Jun 2018 02:41:15 +0200
Subject: [PATCH] arm: ox820: remove left-overs
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/clk/clk-oxnas.c | 2 --
include/dt-bindings/clock/oxsemi,ox820.h | 32 +++++++++++-------------
2 files changed, 14 insertions(+), 20 deletions(-)
--- a/drivers/clk/clk-oxnas.c
+++ b/drivers/clk/clk-oxnas.c
@@ -29,8 +29,6 @@ struct oxnas_stdclk_data {
struct clk_hw_onecell_data *onecell_data;
struct clk_oxnas_gate **gates;
unsigned int ngates;
- struct clk_oxnas_pll **plls;
- unsigned int nplls;
};
/* Regmap offsets */
--- a/include/dt-bindings/clock/oxsemi,ox820.h
+++ b/include/dt-bindings/clock/oxsemi,ox820.h
@@ -6,24 +6,20 @@
#ifndef DT_CLOCK_OXSEMI_OX820_H
#define DT_CLOCK_OXSEMI_OX820_H
-/* PLLs */
-#define CLK_820_PLLA 0
-#define CLK_820_PLLB 1
-
/* Gate Clocks */
-#define CLK_820_LEON 2
-#define CLK_820_DMA_SGDMA 3
-#define CLK_820_CIPHER 4
-#define CLK_820_SD 5
-#define CLK_820_SATA 6
-#define CLK_820_AUDIO 7
-#define CLK_820_USBMPH 8
-#define CLK_820_ETHA 9
-#define CLK_820_PCIEA 10
-#define CLK_820_NAND 11
-#define CLK_820_PCIEB 12
-#define CLK_820_ETHB 13
-#define CLK_820_REF600 14
-#define CLK_820_USBDEV 15
+#define CLK_820_LEON 0
+#define CLK_820_DMA_SGDMA 1
+#define CLK_820_CIPHER 2
+#define CLK_820_SD 3
+#define CLK_820_SATA 4
+#define CLK_820_AUDIO 5
+#define CLK_820_USBMPH 6
+#define CLK_820_ETHA 7
+#define CLK_820_PCIEA 8
+#define CLK_820_NAND 9
+#define CLK_820_PCIEB 10
+#define CLK_820_ETHB 11
+#define CLK_820_REF600 12
+#define CLK_820_USBDEV 13
#endif /* DT_CLOCK_OXSEMI_OX820_H */

View File

@ -0,0 +1,273 @@
--- a/drivers/clk/clk-oxnas.c
+++ b/drivers/clk/clk-oxnas.c
@@ -5,19 +5,42 @@
* Copyright (C) 2016 Neil Armstrong <narmstrong@baylibre.com>
*/
+#include <linux/clk.h>
+#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/stringify.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
+#include <linux/reset.h>
#include <dt-bindings/clock/oxsemi,ox810se.h>
#include <dt-bindings/clock/oxsemi,ox820.h>
+#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 PLLB_BYPASS 1
+#define PLLB_ENSAT 3
+#define PLLB_OUTDIV 4
+#define PLLB_REFDIV 8
+#define PLLB_DIV_INT_SHIFT 8
+#define PLLB_DIV_FRAC_SHIFT 0
+#define PLLB_DIV_INT(val) ((val) << PLLB_DIV_INT_SHIFT)
+#define PLLB_DIV_FRAC(val) ((val) << PLLB_DIV_FRAC_SHIFT)
+
+#define PLLA_REFDIV_MASK 0x3F
+#define PLLA_REFDIV_SHIFT 8
+#define PLLA_OUTDIV_MASK 0x7
+#define PLLA_OUTDIV_SHIFT 4
+
/* Standard regmap gate clocks */
struct clk_oxnas_gate {
struct clk_hw hw;
@@ -36,6 +59,135 @@ struct oxnas_stdclk_data {
#define CLK_SET_REGOFFSET 0x2c
#define CLK_CLR_REGOFFSET 0x30
+#define PLLA_CTRL0_REGOFFSET 0x1f0
+#define PLLA_CTRL1_REGOFFSET 0x1f4
+#define PLLB_CTRL0_REGOFFSET 0x1001f0
+#define MHZ (1000 * 1000)
+
+struct clk_oxnas_pll {
+ struct clk_hw hw;
+ struct device_node *devnode;
+ struct reset_control *rstc;
+ struct regmap *syscon;
+};
+
+#define to_clk_oxnas_pll(_hw) container_of(_hw, struct clk_oxnas_pll, hw)
+
+static unsigned long plla_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_oxnas_pll *plla = to_clk_oxnas_pll(hw);
+ unsigned long fin = parent_rate;
+ unsigned long refdiv, outdiv;
+ unsigned int pll0, fbdiv;
+
+ BUG_ON(regmap_read(plla->syscon, PLLA_CTRL0_REGOFFSET, &pll0));
+
+ refdiv = (pll0 >> PLLA_REFDIV_SHIFT) & PLLA_REFDIV_MASK;
+ refdiv += 1;
+ outdiv = (pll0 >> PLLA_OUTDIV_SHIFT) & PLLA_OUTDIV_MASK;
+ outdiv += 1;
+
+ BUG_ON(regmap_read(plla->syscon, PLLA_CTRL1_REGOFFSET, &fbdiv));
+ /* seems we will not be here when pll is bypassed, so ignore this
+ * case */
+
+ return fin / MHZ * fbdiv / (refdiv * outdiv) / 32768 * MHZ;
+}
+
+static const char *pll_clk_parents[] = {
+ "oscillator",
+};
+
+static struct clk_ops plla_ops = {
+ .recalc_rate = plla_clk_recalc_rate,
+};
+
+static struct clk_init_data clk_plla_init = {
+ .name = "plla",
+ .ops = &plla_ops,
+ .parent_names = pll_clk_parents,
+ .num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
+static int pllb_clk_is_prepared(struct clk_hw *hw)
+{
+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
+
+ return !!pllb->rstc;
+}
+
+static int pllb_clk_prepare(struct clk_hw *hw)
+{
+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
+
+ pllb->rstc = of_reset_control_get(pllb->devnode, NULL);
+
+ return IS_ERR(pllb->rstc) ? PTR_ERR(pllb->rstc) : 0;
+}
+
+static void pllb_clk_unprepare(struct clk_hw *hw)
+{
+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
+
+ BUG_ON(IS_ERR(pllb->rstc));
+
+ reset_control_put(pllb->rstc);
+ pllb->rstc = NULL;
+}
+
+static int pllb_clk_enable(struct clk_hw *hw)
+{
+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
+
+ BUG_ON(IS_ERR(pllb->rstc));
+
+ /* put PLL into bypass */
+ regmap_update_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, BIT(PLLB_BYPASS), BIT(PLLB_BYPASS));
+ wmb();
+ udelay(10);
+ reset_control_assert(pllb->rstc);
+ udelay(10);
+ /* set PLL B control information */
+ regmap_write_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, 0xffff,
+ (1 << PLLB_ENSAT) | (1 << PLLB_OUTDIV) | (2 << PLLB_REFDIV));
+ reset_control_deassert(pllb->rstc);
+ udelay(100);
+ regmap_update_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, BIT(PLLB_BYPASS), 0);
+
+ return 0;
+}
+
+static void pllb_clk_disable(struct clk_hw *hw)
+{
+ struct clk_oxnas_pll *pllb = to_clk_oxnas_pll(hw);
+
+ BUG_ON(IS_ERR(pllb->rstc));
+
+ /* put PLL into bypass */
+ regmap_update_bits(pllb->syscon, PLLB_CTRL0_REGOFFSET, BIT(PLLB_BYPASS), BIT(PLLB_BYPASS));
+
+ wmb();
+ udelay(10);
+
+ reset_control_assert(pllb->rstc);
+}
+
+static struct clk_ops pllb_ops = {
+ .prepare = pllb_clk_prepare,
+ .unprepare = pllb_clk_unprepare,
+ .is_prepared = pllb_clk_is_prepared,
+ .enable = pllb_clk_enable,
+ .disable = pllb_clk_disable,
+};
+
+static struct clk_init_data clk_pllb_init = {
+ .name = "pllb",
+ .ops = &pllb_ops,
+ .parent_names = pll_clk_parents,
+ .num_parents = ARRAY_SIZE(pll_clk_parents),
+};
+
static inline struct clk_oxnas_gate *to_clk_oxnas_gate(struct clk_hw *hw)
{
return container_of(hw, struct clk_oxnas_gate, hw);
@@ -251,3 +403,42 @@ static struct platform_driver oxnas_stdc
},
};
builtin_platform_driver(oxnas_stdclk_driver);
+
+void __init oxnas_init_plla(struct device_node *np)
+{
+ struct clk *clk;
+ struct clk_oxnas_pll *plla;
+
+ plla = kmalloc(sizeof(*plla), GFP_KERNEL);
+ BUG_ON(!plla);
+
+ plla->syscon = syscon_node_to_regmap(of_get_parent(np));
+ plla->hw.init = &clk_plla_init;
+ plla->devnode = np;
+ plla->rstc = NULL;
+ clk = clk_register(NULL, &plla->hw);
+ BUG_ON(IS_ERR(clk));
+ /* mark it as enabled */
+ clk_prepare_enable(clk);
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(oxnas_plla, "plxtech,nas782x-plla", oxnas_init_plla);
+
+void __init oxnas_init_pllb(struct device_node *np)
+{
+ struct clk *clk;
+ struct clk_oxnas_pll *pllb;
+
+ pllb = kmalloc(sizeof(*pllb), GFP_KERNEL);
+ BUG_ON(!pllb);
+
+ pllb->syscon = syscon_node_to_regmap(of_get_parent(np));
+ pllb->hw.init = &clk_pllb_init;
+ pllb->devnode = np;
+ pllb->rstc = NULL;
+
+ clk = clk_register(NULL, &pllb->hw);
+ BUG_ON(IS_ERR(clk));
+ of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+CLK_OF_DECLARE(oxnas_pllb, "plxtech,nas782x-pllb", oxnas_init_pllb);
--- a/arch/arm/boot/dts/ox820.dtsi
+++ b/arch/arm/boot/dts/ox820.dtsi
@@ -61,12 +61,6 @@
clocks = <&osc>;
};
- plla: plla {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <850000000>;
- };
-
armclk: armclk {
compatible = "fixed-factor-clock";
#clock-cells = <0>;
@@ -266,6 +260,19 @@
compatible = "oxsemi,ox820-stdclk", "oxsemi,ox810se-stdclk";
#clock-cells = <1>;
};
+
+ plla: plla {
+ compatible = "plxtech,nas782x-plla";
+ #clock-cells = <0>;
+ clocks = <&osc>;
+ };
+
+ pllb: pllb {
+ compatible = "plxtech,nas782x-pllb";
+ #clock-cells = <0>;
+ clocks = <&osc>;
+ resets = <&reset RESET_PLLB>;
+ };
};
};
@@ -287,6 +294,13 @@
clocks = <&armclk>;
};
+ watchdog@620 {
+ compatible = "mpcore_wdt";
+ reg = <0x620 0x20>;
+ interrupts = <GIC_PPI 14 (GIC_CPU_MASK_RAW(3)|IRQ_TYPE_LEVEL_HIGH)>;
+ clocks = <&armclk>;
+ };
+
gic: interrupt-controller@1000 {
compatible = "arm,arm11mp-gic";
interrupt-controller;

View File

@ -0,0 +1,25 @@
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -148,6 +148,12 @@ config POWER_RESET_OXNAS
help
Restart support for OXNAS/PLXTECH OX820 SoC.
+config POWER_RESET_OXNAS
+ bool "OXNAS SoC restart driver"
+ depends on ARCH_OXNAS
+ help
+ Restart support for OXNAS boards.
+
config POWER_RESET_PIIX4_POWEROFF
tristate "Intel PIIX4 power-off driver"
depends on PCI
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_POWER_RESET_QCOM_PON) += qc
obj-$(CONFIG_POWER_RESET_OCELOT_RESET) += ocelot-reset.o
obj-$(CONFIG_POWER_RESET_PIIX4_POWEROFF) += piix4-poweroff.o
obj-$(CONFIG_POWER_RESET_LTC2952) += ltc2952-poweroff.o
+obj-$(CONFIG_POWER_RESET_OXNAS) += oxnas-restart.o
obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
obj-$(CONFIG_POWER_RESET_REGULATOR) += regulator-poweroff.o
obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o

View File

@ -0,0 +1,44 @@
--- a/arch/arm/boot/dts/ox820.dtsi
+++ b/arch/arm/boot/dts/ox820.dtsi
@@ -247,6 +247,15 @@
};
};
+ pcie_phy: pcie-phy@a00000 {
+ compatible = "oxsemi,ox820-pcie-phy";
+ reg = <0xa00000 0x10>;
+ #phy-cells = <0>;
+ resets = <&reset RESET_PCIEPHY>;
+ reset-names = "phy";
+ status = "disabled";
+ };
+
sys: sys-ctrl@e00000 {
compatible = "oxsemi,ox820-sys-ctrl", "syscon", "simple-mfd";
reg = <0xe00000 0x200000>;
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -35,6 +35,13 @@ config PHY_LPC18XX_USB_OTG
This driver is need for USB0 support on LPC18xx/43xx and takes
care of enabling and clock setup.
+config PHY_OXNAS
+ tristate "Oxford Semi. OX820 PCI-E PHY support"
+ depends on HAS_IOMEM && OF && (ARM || COMPILE_TEST)
+ select GENERIC_PHY
+ help
+ This option enables support for OXNAS OX820 SoC PCIE PHY.
+
config PHY_PISTACHIO_USB
tristate "IMG Pistachio USB2.0 PHY driver"
depends on MIPS || COMPILE_TEST
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_GENERIC_PHY_MIPI_DPHY) += phy-core-mipi-dphy.o
obj-$(CONFIG_PHY_CAN_TRANSCEIVER) += phy-can-transceiver.o
obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o
+obj-$(CONFIG_PHY_OXNAS) += phy-oxnas-pcie.o
obj-$(CONFIG_PHY_XGENE) += phy-xgene.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
obj-$(CONFIG_USB_LGM_PHY) += phy-lgm-usb.o

View File

@ -0,0 +1,122 @@
--- a/drivers/pci/controller/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -312,6 +312,11 @@ config PCIE_HISI_ERR
Say Y here if you want error handling support
for the PCIe controller's errors on HiSilicon HIP SoCs
+config PCIE_OXNAS
+ bool "PLX Oxnas PCIe controller"
+ depends on ARCH_OXNAS
+ select PCIEPORTBUS
+
source "drivers/pci/controller/dwc/Kconfig"
source "drivers/pci/controller/mobiveil/Kconfig"
source "drivers/pci/controller/cadence/Kconfig"
--- a/drivers/pci/controller/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie
obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
obj-$(CONFIG_PCIE_MEDIATEK_GEN3) += pcie-mediatek-gen3.o
obj-$(CONFIG_PCIE_MICROCHIP_HOST) += pcie-microchip-host.o
+obj-$(CONFIG_PCIE_OXNAS) += pcie-oxnas.o
obj-$(CONFIG_VMD) += vmd.o
obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o
obj-$(CONFIG_PCI_LOONGSON) += pci-loongson.o
--- a/arch/arm/boot/dts/ox820.dtsi
+++ b/arch/arm/boot/dts/ox820.dtsi
@@ -289,7 +289,7 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
- ranges = <0 0x47000000 0x1000000>;
+ ranges = <0 0x47000000 0x2000>;
scu: scu@0 {
compatible = "arm,arm11mp-scu";
@@ -318,5 +318,86 @@
<0x100 0x500>;
};
};
+
+ pcie0: pcie@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 */
+ reg = <0x47c00000 0x1000>, <0x47d00000 0x100>;
+
+ phys = <&pcie_phy>;
+ phy-names = "pcie-phy";
+
+ #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 = <&gpio1 12 0>;
+ clocks = <&stdclk CLK_820_PCIEA>, <&pllb>;
+ clock-names = "pcie", "busclk";
+ resets = <&reset RESET_PCIEA>;
+ reset-names = "pcie";
+
+ plxtech,pcie-hcsl-bit = <2>;
+ plxtech,pcie-ctrl-offset = <0x120>;
+ plxtech,pcie-outbound-offset = <0x138>;
+ status = "disabled";
+ };
+
+ pcie1: pcie@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 */
+ reg = <0x47e00000 0x1000>, <0x47f00000 0x100>;
+
+ phys = <&pcie_phy>;
+ phy-names = "pcie-phy";
+
+ #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 = <&gpio1 12 0>; */
+ clocks = <&stdclk CLK_820_PCIEB>, <&pllb>;
+ clock-names = "pcie", "busclk";
+ resets = <&reset RESET_PCIEB>;
+ reset-names = "pcie";
+
+ plxtech,pcie-hcsl-bit = <3>;
+ plxtech,pcie-ctrl-offset = <0x124>;
+ plxtech,pcie-outbound-offset = <0x174>;
+ status = "disabled";
+ };
};
};

View File

@ -0,0 +1,60 @@
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -568,6 +568,14 @@ config SATA_VITESSE
If unsure, say N.
+config SATA_OXNAS
+ tristate "PLXTECH NAS782X SATA support"
+ select SATA_HOST
+ help
+ This option enables support for Nas782x Serial ATA controller.
+
+ If unsure, say N.
+
comment "PATA SFF controllers with BMDMA"
config PATA_ALI
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_SATA_SVW) += sata_svw.o
obj-$(CONFIG_SATA_ULI) += sata_uli.o
obj-$(CONFIG_SATA_VIA) += sata_via.o
obj-$(CONFIG_SATA_VITESSE) += sata_vsc.o
+obj-$(CONFIG_SATA_OXNAS) += sata_oxnas.o
# SFF PATA w/ BMDMA
obj-$(CONFIG_PATA_ALI) += pata_ali.o
--- a/arch/arm/boot/dts/ox820.dtsi
+++ b/arch/arm/boot/dts/ox820.dtsi
@@ -399,5 +399,20 @@
plxtech,pcie-outbound-offset = <0x174>;
status = "disabled";
};
+
+ sata: sata@45900000 {
+ compatible = "plxtech,nas782x-sata";
+ /* ports dmactl sgdma */
+ reg = <0x45900000 0x20000>, <0x459A0000 0x40>, <0x459B0000 0x20>,
+ /* core phy descriptors (optional) */
+ <0x459E0000 0x2000>, <0x44900000 0x0C>, <0x50000000 0x1000>;
+ interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&stdclk CLK_820_SATA>;
+ resets = <&reset RESET_SATA>, <&reset RESET_SATA_LINK>, <&reset RESET_SATA_PHY>;
+ reset-names = "sata", "link", "phy";
+ nr-ports = <1>;
+ status = "disabled";
+ };
+
};
};
--- a/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
+++ b/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
@@ -111,3 +111,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_etha_mdio>;
};
+
+&sata {
+ status = "okay";
+};

View File

@ -0,0 +1,10 @@
--- a/arch/arm/mach-oxnas/Kconfig
+++ b/arch/arm/mach-oxnas/Kconfig
@@ -2,6 +2,7 @@
menuconfig ARCH_OXNAS
bool "Oxford Semiconductor OXNAS Family SoCs"
select ARCH_HAS_RESET_CONTROLLER
+ select ARCH_WANT_LIBATA_LEDS
select COMMON_CLK_OXNAS
select GPIOLIB
select MFD_SYSCON

View File

@ -0,0 +1,73 @@
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -339,6 +339,13 @@ config USB_OCTEON_EHCI
USB 2.0 device support. All CN6XXX based chips with USB are
supported.
+config USB_EHCI_OXNAS
+ tristate "OXNAS EHCI Module"
+ depends on USB_EHCI_HCD && ARCH_OXNAS
+ select USB_EHCI_ROOT_HUB_TT
+ help
+ Enable support for the OX820 SOC's on-chip EHCI controller.
+
endif # USB_EHCI_HCD
config USB_OXU210HP_HCD
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_USB_EHCI_HCD_STI) += ehci-s
obj-$(CONFIG_USB_EHCI_EXYNOS) += ehci-exynos.o
obj-$(CONFIG_USB_EHCI_HCD_AT91) += ehci-atmel.o
obj-$(CONFIG_USB_EHCI_BRCMSTB) += ehci-brcm.o
+obj-$(CONFIG_USB_EHCI_OXNAS) += ehci-oxnas.o
obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
--- a/arch/arm/boot/dts/ox820.dtsi
+++ b/arch/arm/boot/dts/ox820.dtsi
@@ -106,6 +106,31 @@
status = "disabled";
};
+ ehci: ehci@40200100 {
+ compatible = "plxtech,nas782x-ehci";
+ reg = <0x40200100 0xf00>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&stdclk CLK_820_USBMPH>, <&pllb>, <&stdclk CLK_820_REF600>;
+ clock-names = "usb", "refsrc", "phyref";
+ resets = <&reset RESET_USBHS>, <&reset RESET_USBPHYA>, <&reset RESET_USBPHYB>;
+ reset-names = "host", "phya", "phyb";
+ oxsemi,sys-ctrl = <&sys>;
+ /* 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 ? */
+ oxsemi,ehci_use_pllb;
+ status = "disabled";
+
+ ehci_port1: port@1 {
+ reg = <1>;
+ #trigger-source-cells = <0>;
+ };
+ ehci_port2: port@2 {
+ reg = <2>;
+ #trigger-source-cells = <0>;
+ };
+ };
+
apb-bridge@44000000 {
#address-cells = <1>;
#size-cells = <1>;
--- a/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
+++ b/arch/arm/boot/dts/ox820-cloudengines-pogoplug-series-3.dts
@@ -105,6 +105,10 @@
};
};
+&ehci {
+ status = "okay";
+};
+
&etha {
status = "okay";

View File

@ -0,0 +1,260 @@
From 71270226b14733a4b1f2cde58ea9265caa50b38d Mon Sep 17 00:00:00 2001
From: Adrian Panella <ianchi74@outlook.com>
Date: Thu, 9 Mar 2017 09:37:17 +0100
Subject: [PATCH 67/69] generic: Mangle bootloader's kernel arguments
The command-line arguments provided by the boot loader will be
appended to a new device tree property: bootloader-args.
If there is a property "append-rootblock" in DT under /chosen
and a root= option in bootloaders command line it will be parsed
and added to DT bootargs with the form: <append-rootblock>XX.
Only command line ATAG will be processed, the rest of the ATAGs
sent by bootloader will be ignored.
This is usefull in dual boot systems, to get the current root partition
without afecting the rest of the system.
Signed-off-by: Adrian Panella <ianchi74@outlook.com>
---
arch/arm/Kconfig | 11 +++++
arch/arm/boot/compressed/atags_to_fdt.c | 72 ++++++++++++++++++++++++++++++++-
init/main.c | 16 ++++++++
3 files changed, 98 insertions(+), 1 deletion(-)
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1728,6 +1728,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN
The command-line arguments provided by the boot loader will be
appended to the the device tree bootargs property.
+config ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE
+ bool "Append rootblock parsing bootloader's kernel arguments"
+ help
+ The command-line arguments provided by the boot loader will be
+ appended to a new device tree property: bootloader-args.
+ If there is a property "append-rootblock" in DT under /chosen
+ and a root= option in bootloaders command line it will be parsed
+ and added to DT bootargs with the form: <append-rootblock>XX.
+ Only command line ATAG will be processed, the rest of the ATAGs
+ sent by bootloader will be ignored.
+
endchoice
config CMDLINE
--- a/arch/arm/boot/compressed/atags_to_fdt.c
+++ b/arch/arm/boot/compressed/atags_to_fdt.c
@@ -5,6 +5,8 @@
#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND)
#define do_extend_cmdline 1
+#elif defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+#define do_extend_cmdline 1
#else
#define do_extend_cmdline 0
#endif
@@ -20,6 +22,7 @@ static int node_offset(void *fdt, const
return offset;
}
+#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE
static int setprop(void *fdt, const char *node_path, const char *property,
void *val_array, int size)
{
@@ -28,6 +31,7 @@ static int setprop(void *fdt, const char
return offset;
return fdt_setprop(fdt, offset, property, val_array, size);
}
+#endif
static int setprop_string(void *fdt, const char *node_path,
const char *property, const char *string)
@@ -38,6 +42,7 @@ static int setprop_string(void *fdt, con
return fdt_setprop_string(fdt, offset, property, string);
}
+#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE
static int setprop_cell(void *fdt, const char *node_path,
const char *property, uint32_t val)
{
@@ -46,6 +51,7 @@ static int setprop_cell(void *fdt, const
return offset;
return fdt_setprop_cell(fdt, offset, property, val);
}
+#endif
static const void *getprop(const void *fdt, const char *node_path,
const char *property, int *len)
@@ -58,6 +64,7 @@ static const void *getprop(const void *f
return fdt_getprop(fdt, offset, property, len);
}
+#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE
static uint32_t get_cell_size(const void *fdt)
{
int len;
@@ -69,6 +76,61 @@ static uint32_t get_cell_size(const void
return cell_size;
}
+#endif
+
+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+
+static char *append_rootblock(char *dest, const char *str, int len, void *fdt)
+{
+ const char *ptr, *end;
+ const char *root="root=";
+ int i, l;
+ const char *rootblock;
+
+ //ARM doesn't have __HAVE_ARCH_STRSTR, so search manually
+ ptr = str - 1;
+
+ do {
+ //first find an 'r' at the begining or after a space
+ do {
+ ptr++;
+ ptr = strchr(ptr, 'r');
+ if(!ptr) return dest;
+
+ } while (ptr != str && *(ptr-1) != ' ');
+
+ //then check for the rest
+ for(i = 1; i <= 4; i++)
+ if(*(ptr+i) != *(root+i)) break;
+
+ } while (i != 5);
+
+ end = strchr(ptr, ' ');
+ end = end ? (end - 1) : (strchr(ptr, 0) - 1);
+
+ //find partition number (assumes format root=/dev/mtdXX | /dev/mtdblockXX | yy:XX )
+ for( i = 0; end >= ptr && *end >= '0' && *end <= '9'; end--, i++);
+ ptr = end + 1;
+
+ /* if append-rootblock property is set use it to append to command line */
+ rootblock = getprop(fdt, "/chosen", "append-rootblock", &l);
+ if(rootblock != NULL) {
+ if(*dest != ' ') {
+ *dest = ' ';
+ dest++;
+ len++;
+ }
+ if (len + l + i <= COMMAND_LINE_SIZE) {
+ memcpy(dest, rootblock, l);
+ dest += l - 1;
+ memcpy(dest, ptr, i);
+ dest += i;
+ }
+ }
+ return dest;
+}
+#endif
+
static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline)
{
char cmdline[COMMAND_LINE_SIZE];
@@ -88,18 +150,28 @@ static void merge_fdt_bootargs(void *fdt
/* and append the ATAG_CMDLINE */
if (fdt_cmdline) {
+
+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+ //save original bootloader args
+ //and append ubi.mtd with root partition number to current cmdline
+ setprop_string(fdt, "/chosen", "bootloader-args", fdt_cmdline);
+ ptr = append_rootblock(ptr, fdt_cmdline, len, fdt);
+
+#else
len = strlen(fdt_cmdline);
if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) {
*ptr++ = ' ';
memcpy(ptr, fdt_cmdline, len);
ptr += len;
}
+#endif
}
*ptr = '\0';
setprop_string(fdt, "/chosen", "bootargs", cmdline);
}
+#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE
static void hex_str(char *out, uint32_t value)
{
uint32_t digit;
@@ -117,6 +189,7 @@ static void hex_str(char *out, uint32_t
}
*out = '\0';
}
+#endif
/*
* Convert and fold provided ATAGs into the provided FDT.
@@ -131,9 +204,11 @@ int atags_to_fdt(void *atag_list, void *
struct tag *atag = atag_list;
/* In the case of 64 bits memory size, need to reserve 2 cells for
* address and size for each bank */
+#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE
__be32 mem_reg_property[2 * 2 * NR_BANKS];
- int memcount = 0;
- int ret, memsize;
+ int memsize, memcount = 0;
+#endif
+ int ret;
/* make sure we've got an aligned pointer */
if ((u32)atag_list & 0x3)
@@ -168,7 +243,9 @@ int atags_to_fdt(void *atag_list, void *
else
setprop_string(fdt, "/chosen", "bootargs",
atag->u.cmdline.cmdline);
- } else if (atag->hdr.tag == ATAG_MEM) {
+ }
+#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE
+ else if (atag->hdr.tag == ATAG_MEM) {
if (memcount >= sizeof(mem_reg_property)/4)
continue;
if (!atag->u.mem.size)
@@ -212,6 +289,10 @@ int atags_to_fdt(void *atag_list, void *
setprop(fdt, "/memory", "reg", mem_reg_property,
4 * memcount * memsize);
}
+#else
+
+ }
+#endif
return fdt_pack(fdt);
}
--- a/init/main.c
+++ b/init/main.c
@@ -113,6 +113,10 @@
#include <kunit/test.h>
+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+#include <linux/of.h>
+#endif
+
static int kernel_init(void *);
extern void init_IRQ(void);
@@ -993,6 +997,18 @@ asmlinkage __visible void __init __no_sa
page_alloc_init();
pr_notice("Kernel command line: %s\n", saved_command_line);
+
+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+ //Show bootloader's original command line for reference
+ if(of_chosen) {
+ const char *prop = of_get_property(of_chosen, "bootloader-args", NULL);
+ if(prop)
+ pr_notice("Bootloader command line (ignored): %s\n", prop);
+ else
+ pr_notice("Bootloader command line not present\n");
+ }
+#endif
+
/* parameters may set static keys */
jump_label_init();
parse_early_param();

View File

@ -0,0 +1,57 @@
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1531,6 +1531,14 @@ unsigned ata_exec_internal_sg(struct ata
return AC_ERR_SYSTEM;
}
+ if (ap->ops->acquire_hw && !ap->ops->acquire_hw(ap, 0, 0)) {
+ spin_unlock_irqrestore(ap->lock, flags);
+ if (!ap->ops->acquire_hw(ap, 1, (2*HZ))) {
+ return AC_ERR_TIMEOUT;
+ }
+ spin_lock_irqsave(ap->lock, flags);
+ }
+
/* initialize internal qc */
qc = __ata_qc_from_tag(ap, ATA_TAG_INTERNAL);
@@ -4587,6 +4595,9 @@ struct ata_queued_cmd *ata_qc_new_init(s
if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
return NULL;
+ if (ap->ops->qc_new && ap->ops->qc_new(ap))
+ return NULL;
+
/* libsas case */
if (ap->flags & ATA_FLAG_SAS_HOST) {
tag = ata_sas_allocate_tag(ap);
@@ -4632,6 +4643,8 @@ void ata_qc_free(struct ata_queued_cmd *
qc->tag = ATA_TAG_POISON;
if (ap->flags & ATA_FLAG_SAS_HOST)
ata_sas_free_tag(tag, ap);
+ if (ap->ops->qc_free)
+ ap->ops->qc_free(qc);
}
}
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -927,6 +927,8 @@ struct ata_port_operations {
enum ata_completion_errors (*qc_prep)(struct ata_queued_cmd *qc);
unsigned int (*qc_issue)(struct ata_queued_cmd *qc);
bool (*qc_fill_rtf)(struct ata_queued_cmd *qc);
+ int (*qc_new)(struct ata_port *ap);
+ void (*qc_free)(struct ata_queued_cmd *qc);
/*
* Configuration and exception handling
@@ -1017,6 +1019,9 @@ struct ata_port_operations {
void (*phy_reset)(struct ata_port *ap);
void (*eng_timeout)(struct ata_port *ap);
+ int (*acquire_hw)(struct ata_port *ap, int may_sleep,
+ int timeout_jiffies);
+
/*
* ->inherits must be the last field and all the preceding
* fields must be pointers.