mirror of https://github.com/hak5/openwrt-owl.git
parent
a718ebf1ed
commit
72ba27ae72
|
@ -0,0 +1,27 @@
|
|||
#
|
||||
# Copyright (C) 2010 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
ARCH:=arm
|
||||
BOARD:=cns21xx
|
||||
BOARDNAME:=Cavium Networks CNS21xx
|
||||
FEATURES:=squashfs broken
|
||||
CFLAGS:=-Os -pipe -march=armv4 -mtune=arm9tdmi -funit-at-a-time
|
||||
|
||||
LINUX_VERSION:=2.6.36.2
|
||||
|
||||
include $(INCLUDE_DIR)/target.mk
|
||||
|
||||
DEFAULT_PACKAGES += \
|
||||
kmod-leds-gpio kmod-input-core kmod-input-gpio-keys \
|
||||
kmod-button-hotplug
|
||||
|
||||
define Target/Description
|
||||
Build firmware images for Cavium Networks CNS21XX based boards.
|
||||
endef
|
||||
|
||||
$(eval $(call BuildTarget))
|
|
@ -0,0 +1,54 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2010 OpenWrt.org
|
||||
#
|
||||
#
|
||||
|
||||
. /lib/cns21xx.sh
|
||||
|
||||
status_led=""
|
||||
|
||||
led_set_attr() {
|
||||
[ -f "/sys/class/leds/$1/$2" ] && echo "$3" > "/sys/class/leds/$1/$2"
|
||||
}
|
||||
|
||||
status_led_set_timer() {
|
||||
led_set_attr $status_led "trigger" "timer"
|
||||
led_set_attr $status_led "delay_on" "$1"
|
||||
led_set_attr $status_led "delay_off" "$2"
|
||||
}
|
||||
|
||||
status_led_on() {
|
||||
led_set_attr $status_led "trigger" "none"
|
||||
led_set_attr $status_led "brightness" 255
|
||||
}
|
||||
|
||||
status_led_off() {
|
||||
led_set_attr $status_led "trigger" "none"
|
||||
led_set_attr $status_led "brightness" 0
|
||||
}
|
||||
|
||||
get_status_led() {
|
||||
case $(get_board_name) in
|
||||
ns-k330)
|
||||
status_led="ns-k330:red:link"
|
||||
;;
|
||||
esac;
|
||||
}
|
||||
|
||||
set_state() {
|
||||
get_status_led
|
||||
|
||||
case "$1" in
|
||||
preinit)
|
||||
insmod leds-gpio
|
||||
status_led_set_timer 200 200
|
||||
;;
|
||||
failsafe)
|
||||
status_led_set_timer 50 50
|
||||
;;
|
||||
done)
|
||||
status_led_on
|
||||
;;
|
||||
esac
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2010 OpenWrt.org
|
||||
#
|
||||
|
||||
. /lib/cns21xx.sh
|
||||
|
||||
board=$(get_board_name)
|
||||
|
||||
ns_k330_set_leds() {
|
||||
uci batch <<EOF
|
||||
set system.led_eth_orange='led'
|
||||
set system.led_eth_orange.name='eth_orange'
|
||||
set system.led_eth_orange.sysfs='ns-k330:orange:eth'
|
||||
set system.led_eth_orange.trigger='netdev'
|
||||
set system.led_eth_orange.dev='eth0'
|
||||
set system.led_eth_orange.mode='link'
|
||||
set system.led_eth_green='led'
|
||||
set system.led_eth_green.name='eth_green'
|
||||
set system.led_eth_green.sysfs='ns-k330:green:eth'
|
||||
set system.led_eth_green.trigger='netdev'
|
||||
set system.led_eth_green.dev='eth0'
|
||||
set system.led_eth_green.mode='tx rx'
|
||||
set system.usb_led1=led
|
||||
set system.usb_led1.name='USB'
|
||||
set system.usb_led1.sysfs='ns-k330:green:usb1'
|
||||
set system.usb_led1.trigger='usbdev'
|
||||
set system.usb_led1.dev='1-1'
|
||||
set system.usb_led1.interval='50'
|
||||
set system.usb_led2=led
|
||||
set system.usb_led2.name='USB'
|
||||
set system.usb_led2.sysfs='ns-k330:green:usb2'
|
||||
set system.usb_led2.trigger='usbdev'
|
||||
set system.usb_led2.dev='1-2'
|
||||
set system.usb_led2.interval='50'
|
||||
commit system
|
||||
EOF
|
||||
}
|
||||
|
||||
if [ "${board}" == "ns-k330" ]; then
|
||||
ns_k330_set_leds
|
||||
fi
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2010 OpenWrt.org
|
||||
#
|
||||
|
||||
get_board_name() {
|
||||
local hardware
|
||||
local name
|
||||
|
||||
hardware=$(awk 'BEGIN{FS="[ \t]+:[ \t]"} /Hardware/ {print $2}' /proc/cpuinfo)
|
||||
|
||||
case "$hardware" in
|
||||
*NSB3AST)
|
||||
name="nsb3ast"
|
||||
;;
|
||||
"NS-K330 NAS")
|
||||
name="ns-k330"
|
||||
;;
|
||||
*)
|
||||
name="generic"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo $name
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# Copyright (C) 2010 OpenWrt.org
|
||||
#
|
||||
|
||||
preinit_load_button_drivers() {
|
||||
insmod input-core
|
||||
insmod gpio_keys
|
||||
insmod button-hotplug
|
||||
}
|
||||
|
||||
boot_hook_add preinit_main preinit_load_button_drivers
|
|
@ -0,0 +1,45 @@
|
|||
#
|
||||
# Copyright (C) 2010 OpenWrt.org
|
||||
#
|
||||
|
||||
. /lib/cns21xx.sh
|
||||
|
||||
PART_NAME=firmware
|
||||
RAMFS_COPY_DATA=/lib/cns21xx.sh
|
||||
|
||||
platform_check_image() {
|
||||
local board=$(get_board_name)
|
||||
local magic="$(get_magic_word "$1")"
|
||||
|
||||
[ "$ARGC" -gt 1 ] && return 1
|
||||
|
||||
case "$board" in
|
||||
nsb3ast)
|
||||
[ "$magic" != "0b1c" ] && {
|
||||
echo "Invalid image type."
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
;;
|
||||
ns-k330)
|
||||
[ "$magic" != "0c1c" ] && {
|
||||
echo "Invalid image type."
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Sysupgrade is not yet supported on $board."
|
||||
return 1
|
||||
}
|
||||
|
||||
disable_watchdog() {
|
||||
killall watchdog
|
||||
( ps | grep -v 'grep' | grep '/dev/watchdog' ) && {
|
||||
echo 'Could not disable watchdog'
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
append sysupgrade_pre_upgrade disable_watchdog
|
|
@ -0,0 +1,130 @@
|
|||
# CONFIG_AEABI is not set
|
||||
CONFIG_ALIGNMENT_TRAP=y
|
||||
CONFIG_ARCH_CNS21XX=y
|
||||
CONFIG_ARCH_REQUIRE_GPIOLIB=y
|
||||
# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
|
||||
# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
|
||||
# CONFIG_ARCH_SUPPORTS_MSI is not set
|
||||
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
||||
# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
|
||||
CONFIG_ARM=y
|
||||
CONFIG_ARM_L1_CACHE_SHIFT=4
|
||||
CONFIG_ARM_L1_CACHE_SHIFT_4=y
|
||||
# CONFIG_ARPD is not set
|
||||
CONFIG_ATA=m
|
||||
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
|
||||
CONFIG_CMDLINE="console=ttyS0,38400 rootfstype=squashfs,jffs2 noinitrd"
|
||||
CONFIG_CNS21XX_DEV_GEC=y
|
||||
CONFIG_CNS21XX_DEV_SPI_MASTER=y
|
||||
CONFIG_CNS21XX_DEV_USB=y
|
||||
CONFIG_CNS21XX_GEC=y
|
||||
CONFIG_CPU_32v4=y
|
||||
CONFIG_CPU_ABRT_EV4=y
|
||||
# CONFIG_CPU_BPREDICT_DISABLE is not set
|
||||
CONFIG_CPU_CACHE_FA=y
|
||||
CONFIG_CPU_CACHE_VIVT=y
|
||||
CONFIG_CPU_COPY_FA=y
|
||||
CONFIG_CPU_CP15=y
|
||||
CONFIG_CPU_CP15_MMU=y
|
||||
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
|
||||
CONFIG_CPU_FA526=y
|
||||
# CONFIG_CPU_ICACHE_DISABLE is not set
|
||||
CONFIG_CPU_PABRT_LEGACY=y
|
||||
CONFIG_CPU_TLB_FA=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
# CONFIG_DEBUG_USER is not set
|
||||
CONFIG_DECOMPRESS_LZMA=y
|
||||
CONFIG_DLCI=m
|
||||
CONFIG_DLCI_MAX=8
|
||||
CONFIG_DMADEVICES=y
|
||||
CONFIG_DNOTIFY=y
|
||||
CONFIG_EEPROM_AT25=y
|
||||
CONFIG_ELF_CORE=y
|
||||
CONFIG_FA_WATCHDOG=y
|
||||
CONFIG_FORCE_MAX_ZONEORDER=11
|
||||
# CONFIG_FPE_FASTFPE is not set
|
||||
# CONFIG_FPE_NWFPE is not set
|
||||
CONFIG_FRAME_POINTER=y
|
||||
CONFIG_GENERIC_ATOMIC64=y
|
||||
CONFIG_GENERIC_FIND_LAST_BIT=y
|
||||
CONFIG_GENERIC_GPIO=y
|
||||
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
|
||||
CONFIG_GPIOLIB=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
# CONFIG_HAMRADIO is not set
|
||||
CONFIG_HARDIRQS_SW_RESEND=y
|
||||
CONFIG_HAS_DMA=y
|
||||
CONFIG_HAS_IOMEM=y
|
||||
CONFIG_HAS_IOPORT=y
|
||||
CONFIG_HAVE_AOUT=y
|
||||
CONFIG_HAVE_ARCH_KGDB=y
|
||||
CONFIG_HAVE_FUNCTION_TRACER=y
|
||||
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
|
||||
CONFIG_HAVE_IDE=y
|
||||
CONFIG_HAVE_KERNEL_GZIP=y
|
||||
CONFIG_HAVE_KERNEL_LZMA=y
|
||||
CONFIG_HAVE_KERNEL_LZO=y
|
||||
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
|
||||
CONFIG_HAVE_MEMBLOCK=y
|
||||
CONFIG_HAVE_OPROFILE=y
|
||||
CONFIG_HAVE_PERF_EVENTS=y
|
||||
CONFIG_HAVE_PROC_CPU=y
|
||||
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
|
||||
CONFIG_HDLC=m
|
||||
CONFIG_HDLC_CISCO=m
|
||||
CONFIG_HDLC_FR=m
|
||||
CONFIG_HDLC_PPP=m
|
||||
CONFIG_HDLC_RAW=m
|
||||
CONFIG_HWMON=y
|
||||
# CONFIG_HWMON_DEBUG_CHIP is not set
|
||||
CONFIG_HW_RANDOM=y
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
CONFIG_INOTIFY_USER=y
|
||||
# CONFIG_IP_ADVANCED_ROUTER is not set
|
||||
CONFIG_IP_PIMSM_V1=y
|
||||
CONFIG_IP_PIMSM_V2=y
|
||||
# CONFIG_LEDS_GPIO is not set
|
||||
CONFIG_LEGACY_PTYS=y
|
||||
CONFIG_LEGACY_PTY_COUNT=256
|
||||
CONFIG_M25PXX_USE_FAST_READ=y
|
||||
CONFIG_MACH_NSB3AST=y
|
||||
CONFIG_MACH_NS_K330=y
|
||||
# CONFIG_MTD_CFI is not set
|
||||
CONFIG_MTD_M25P80=y
|
||||
CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NLS=m
|
||||
CONFIG_PAGEFLAGS_EXTENDED=y
|
||||
CONFIG_PAGE_OFFSET=0xC0000000
|
||||
# CONFIG_PCI_SYSCALL is not set
|
||||
CONFIG_PERF_USE_VMALLOC=y
|
||||
CONFIG_PHYLIB=y
|
||||
CONFIG_PLAT_FA=y
|
||||
CONFIG_PLAT_FA_GPIO=y
|
||||
CONFIG_PLAT_FA_TIME=y
|
||||
CONFIG_SCSI=m
|
||||
CONFIG_SCSI_MOD=m
|
||||
# CONFIG_SCSI_MULTI_LUN is not set
|
||||
CONFIG_SERIO=y
|
||||
CONFIG_SERIO_LIBPS2=y
|
||||
# CONFIG_SERIO_RAW is not set
|
||||
CONFIG_SERIO_SERPORT=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_BITBANG=y
|
||||
CONFIG_SPI_CNS21XX=y
|
||||
CONFIG_SPI_DEBUG=y
|
||||
# CONFIG_SPI_GPIO is not set
|
||||
CONFIG_SPI_MASTER=y
|
||||
CONFIG_SPLIT_PTLOCK_CPUS=999999
|
||||
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
|
||||
# CONFIG_TINY_RCU is not set
|
||||
CONFIG_TREE_RCU=y
|
||||
CONFIG_UID16=y
|
||||
# CONFIG_USB_ARCH_HAS_EHCI is not set
|
||||
# CONFIG_USB_ARCH_HAS_OHCI is not set
|
||||
CONFIG_USB_SUPPORT=y
|
||||
CONFIG_VECTORS_BASE=0xffff0000
|
||||
CONFIG_VM_EVENT_COUNTERS=y
|
||||
CONFIG_WAN=y
|
||||
CONFIG_ZBOOT_ROM_BSS=0x0
|
||||
CONFIG_ZBOOT_ROM_TEXT=0x0
|
||||
CONFIG_ZONE_DMA_FLAG=0
|
|
@ -0,0 +1,147 @@
|
|||
# CONFIG_AEABI is not set
|
||||
CONFIG_ALIGNMENT_TRAP=y
|
||||
CONFIG_ARCH_CNS21XX=y
|
||||
# CONFIG_ARCH_CNS3XXX is not set
|
||||
CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
|
||||
# CONFIG_ARCH_NUC93X is not set
|
||||
CONFIG_ARCH_REQUIRE_GPIOLIB=y
|
||||
# CONFIG_ARCH_S5P6442 is not set
|
||||
# CONFIG_ARCH_S5PC100 is not set
|
||||
# CONFIG_ARCH_S5PV210 is not set
|
||||
# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
|
||||
# CONFIG_ARCH_SHMOBILE is not set
|
||||
# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
|
||||
# CONFIG_ARCH_SUPPORTS_MSI is not set
|
||||
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
||||
# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
|
||||
# CONFIG_ARCH_VEXPRESS is not set
|
||||
CONFIG_ARM=y
|
||||
CONFIG_ARM_L1_CACHE_SHIFT=4
|
||||
CONFIG_ARM_L1_CACHE_SHIFT_4=y
|
||||
# CONFIG_ARPD is not set
|
||||
CONFIG_ATA=m
|
||||
CONFIG_BKL=y
|
||||
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
|
||||
CONFIG_CMDLINE="console=ttyS0,38400 rootfstype=squashfs,jffs2 noinitrd"
|
||||
CONFIG_CNS21XX_DEV_GEC=y
|
||||
CONFIG_CNS21XX_DEV_SPI_MASTER=y
|
||||
CONFIG_CNS21XX_DEV_USB=y
|
||||
CONFIG_CNS21XX_GEC=y
|
||||
CONFIG_CPU_32v4=y
|
||||
CONFIG_CPU_ABRT_EV4=y
|
||||
# CONFIG_CPU_BPREDICT_DISABLE is not set
|
||||
CONFIG_CPU_CACHE_FA=y
|
||||
CONFIG_CPU_CACHE_VIVT=y
|
||||
CONFIG_CPU_COPY_FA=y
|
||||
CONFIG_CPU_CP15=y
|
||||
CONFIG_CPU_CP15_MMU=y
|
||||
# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
|
||||
CONFIG_CPU_FA526=y
|
||||
# CONFIG_CPU_ICACHE_DISABLE is not set
|
||||
CONFIG_CPU_PABRT_LEGACY=y
|
||||
CONFIG_CPU_TLB_FA=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
# CONFIG_DEBUG_USER is not set
|
||||
CONFIG_DECOMPRESS_LZMA=y
|
||||
CONFIG_DLCI=m
|
||||
CONFIG_DLCI_MAX=8
|
||||
CONFIG_DMADEVICES=y
|
||||
# CONFIG_DMADEVICES_DEBUG is not set
|
||||
CONFIG_DNOTIFY=y
|
||||
CONFIG_EEPROM_AT25=y
|
||||
CONFIG_ELF_CORE=y
|
||||
CONFIG_FA_WATCHDOG=y
|
||||
# CONFIG_FPE_FASTFPE is not set
|
||||
# CONFIG_FPE_NWFPE is not set
|
||||
CONFIG_FRAME_POINTER=y
|
||||
CONFIG_GENERIC_ATOMIC64=y
|
||||
CONFIG_GENERIC_FIND_LAST_BIT=y
|
||||
CONFIG_GENERIC_GPIO=y
|
||||
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
|
||||
CONFIG_GPIOLIB=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
# CONFIG_HAMRADIO is not set
|
||||
CONFIG_HARDIRQS_SW_RESEND=y
|
||||
CONFIG_HAS_DMA=y
|
||||
CONFIG_HAS_IOMEM=y
|
||||
CONFIG_HAS_IOPORT=y
|
||||
CONFIG_HAVE_AOUT=y
|
||||
CONFIG_HAVE_ARCH_KGDB=y
|
||||
CONFIG_HAVE_DYNAMIC_FTRACE=y
|
||||
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
|
||||
CONFIG_HAVE_FUNCTION_TRACER=y
|
||||
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
|
||||
# CONFIG_HAVE_GENERIC_HARDIRQS is not set
|
||||
CONFIG_HAVE_IDE=y
|
||||
CONFIG_HAVE_IRQ_WORK=y
|
||||
CONFIG_HAVE_KERNEL_GZIP=y
|
||||
CONFIG_HAVE_KERNEL_LZMA=y
|
||||
CONFIG_HAVE_KERNEL_LZO=y
|
||||
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
|
||||
CONFIG_HAVE_MEMBLOCK=y
|
||||
CONFIG_HAVE_OPROFILE=y
|
||||
CONFIG_HAVE_PERF_EVENTS=y
|
||||
CONFIG_HAVE_PROC_CPU=y
|
||||
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
|
||||
CONFIG_HDLC=m
|
||||
CONFIG_HDLC_CISCO=m
|
||||
CONFIG_HDLC_FR=m
|
||||
CONFIG_HDLC_PPP=m
|
||||
CONFIG_HDLC_RAW=m
|
||||
CONFIG_HWMON=y
|
||||
# CONFIG_HWMON_DEBUG_CHIP is not set
|
||||
CONFIG_HW_RANDOM=y
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
CONFIG_INOTIFY_USER=y
|
||||
# CONFIG_IP_ADVANCED_ROUTER is not set
|
||||
CONFIG_IP_PIMSM_V1=y
|
||||
CONFIG_IP_PIMSM_V2=y
|
||||
# CONFIG_LEDS_GPIO is not set
|
||||
CONFIG_LEGACY_PTYS=y
|
||||
CONFIG_LEGACY_PTY_COUNT=256
|
||||
CONFIG_M25PXX_USE_FAST_READ=y
|
||||
CONFIG_MACH_NO_WESTBRIDGE=y
|
||||
CONFIG_MACH_NSB3AST=y
|
||||
CONFIG_MACH_NS_K330=y
|
||||
# CONFIG_MTD_CFI is not set
|
||||
CONFIG_MTD_M25P80=y
|
||||
CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NEED_PER_CPU_KM=y
|
||||
CONFIG_NLS=m
|
||||
CONFIG_PAGEFLAGS_EXTENDED=y
|
||||
CONFIG_PAGE_OFFSET=0xC0000000
|
||||
# CONFIG_PCI_SYSCALL is not set
|
||||
CONFIG_PERF_USE_VMALLOC=y
|
||||
CONFIG_PHYLIB=y
|
||||
CONFIG_PLAT_FA=y
|
||||
CONFIG_PLAT_FA_GPIO=y
|
||||
CONFIG_PLAT_FA_TIME=y
|
||||
# CONFIG_PLAT_SPEAR is not set
|
||||
# CONFIG_PREEMPT_RCU is not set
|
||||
# CONFIG_QUOTACTL is not set
|
||||
CONFIG_SCSI=m
|
||||
CONFIG_SCSI_MOD=m
|
||||
# CONFIG_SCSI_MULTI_LUN is not set
|
||||
CONFIG_SERIO=y
|
||||
CONFIG_SERIO_LIBPS2=y
|
||||
# CONFIG_SERIO_PS2MULT is not set
|
||||
# CONFIG_SERIO_RAW is not set
|
||||
CONFIG_SERIO_SERPORT=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_BITBANG=y
|
||||
CONFIG_SPI_CNS21XX=y
|
||||
CONFIG_SPI_DEBUG=y
|
||||
# CONFIG_SPI_GPIO is not set
|
||||
CONFIG_SPI_MASTER=y
|
||||
CONFIG_SPLIT_PTLOCK_CPUS=999999
|
||||
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
|
||||
# CONFIG_TEST_LIST_SORT is not set
|
||||
# CONFIG_TIMB_DMA is not set
|
||||
CONFIG_UID16=y
|
||||
CONFIG_USB_SUPPORT=y
|
||||
CONFIG_VECTORS_BASE=0xffff0000
|
||||
CONFIG_VM_EVENT_COUNTERS=y
|
||||
CONFIG_WAN=y
|
||||
CONFIG_ZBOOT_ROM_BSS=0x0
|
||||
CONFIG_ZBOOT_ROM_TEXT=0x0
|
||||
CONFIG_ZONE_DMA_FLAG=0
|
|
@ -0,0 +1,118 @@
|
|||
#
|
||||
# Copyright (C) 2010 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
JFFS2_BLOCKSIZE:=64k
|
||||
|
||||
include $(INCLUDE_DIR)/image.mk
|
||||
|
||||
INITRAMFS_SUFFIX:=
|
||||
|
||||
ifeq ($(CONFIG_TARGET_ROOTFS_INITRAMFS),y)
|
||||
INITRAMFS_SUFFIX:=-initramfs
|
||||
endif
|
||||
|
||||
define zimage_name
|
||||
$(IMG_PREFIX)-$(1)-zImage$(INITRAMFS_SUFFIX)
|
||||
endef
|
||||
|
||||
define uimage_name
|
||||
$(IMG_PREFIX)-$(1)-uImage$(INITRAMFS_SUFFIX)
|
||||
endef
|
||||
|
||||
define imgname
|
||||
$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(patsubst jffs2-%,jffs2,$(patsubst squashfs-%,squashfs,$(1)))
|
||||
endef
|
||||
|
||||
define rootfsname
|
||||
$(BIN_DIR)/$(IMG_PREFIX)-$(2)-root.$(patsubst jffs2-%,jffs2,$(patsubst squashfs-%,squashfs,$(1)))
|
||||
endef
|
||||
|
||||
define build_squashfs
|
||||
dd if=$(KDIR)/root.squashfs of=$(KDIR)/root.squashfs-$(1) bs=$(1) conv=sync
|
||||
$(call add_jffs2_mark,$(KDIR)/root.squashfs-$(1))
|
||||
dd if=$(KDIR)/root.squashfs-$(1) of=$(BIN_DIR)/$(IMG_PREFIX)-root.squashfs-$(1) bs=$(1) conv=sync
|
||||
endef
|
||||
|
||||
define prepare_zimage
|
||||
echo -en "\x$(2)\x1c\xa0\xe3\x$(3)\x10\x81\xe3" > $(KDIR)/$(call zimage_name,$(1))
|
||||
cat $(LINUX_DIR)/arch/arm/boot/zImage >> $(KDIR)/$(call zimage_name,$(1))
|
||||
endef
|
||||
|
||||
define prepare_uimage
|
||||
$(call prepare_zimage,$(1),$(2),$(3))
|
||||
mkimage -A arm -O linux -T kernel -a 0x100000 -e 0x100000 -C none \
|
||||
-n 'OpenWrt Linux-$(LINUX_VERSION)' \
|
||||
-d $(KDIR)/$(call zimage_name,$(1)) \
|
||||
$(KDIR)/$(call uimage_name,$(1))
|
||||
endef
|
||||
|
||||
define Image/Prepare
|
||||
# NSB3AST : mach id 2917 (0xb65)
|
||||
$(call prepare_zimage,nsb3ast,0b,65)
|
||||
# NS-K330 : mach id 3108 (0xc24)
|
||||
$(call prepare_zimage,ns-k330,0c,24)
|
||||
endef
|
||||
|
||||
define Image/BuildKernel
|
||||
cat $(KDIR)/$(call zimage_name,nsb3ast) > $(BIN_DIR)/$(call zimage_name,nsb3ast)
|
||||
cat $(KDIR)/$(call zimage_name,ns-k330) > $(BIN_DIR)/$(call zimage_name,ns-k330)
|
||||
endef
|
||||
|
||||
define Image/Build/Generic
|
||||
if [ `stat -c%s "$(KDIR)/$(call zimage_name,$(2))"` -gt 1048576 ]; then \
|
||||
echo "Warning: $(KDIR)/$(call zimage_name,$(2)) is too big"; \
|
||||
else if [ `stat -c%s $(KDIR)/root.$(1)` -gt $(3) ]; then \
|
||||
echo "Warning: of=$(BIN_DIR)/$(IMG_PREFIX)-root.$(1) is too big"; \
|
||||
else \
|
||||
cat $(KDIR)/root.$(1) > $(call rootfsname,$(1),$(2)); \
|
||||
( \
|
||||
dd if=$(KDIR)/$(call zimage_name,$(2)) bs=1024k conv=sync; \
|
||||
dd if=$(BIN_DIR)/$(IMG_PREFIX)-root.$(1) \
|
||||
) > $(call imgname,$(1),$(2)).img; \
|
||||
fi; fi
|
||||
endef
|
||||
|
||||
define Image/Build/uImage
|
||||
if [ `stat -c%s "$(KDIR)/$(call uimage_name,$(2))"` -gt 1048576 ]; then \
|
||||
echo "Warning: $(KDIR)/$(call uimage_name,$(2)) is too big"; \
|
||||
else if [ `stat -c%s $(KDIR)/root.$(1)` -gt $(3) ]; then \
|
||||
echo "Warning: of=$(BIN_DIR)/$(IMG_PREFIX)-root.$(1) is too big"; \
|
||||
else \
|
||||
cat $(KDIR)/root.$(1) > $(call rootfsname,$(1),$(2)); \
|
||||
( \
|
||||
dd if=$(KDIR)/$(call uimage_name,$(2)) bs=1024k conv=sync; \
|
||||
dd if=$(BIN_DIR)/$(IMG_PREFIX)-root.$(1) \
|
||||
) > $(call imgname,$(1),$(2))-uImage.img; \
|
||||
fi; fi
|
||||
endef
|
||||
|
||||
define Image/Build/NSB3AST
|
||||
$(call Image/Build/Generic,$(1),nsb3ast,7077888)
|
||||
endef
|
||||
|
||||
define Image/Build/NSK330
|
||||
$(call Image/Build/Generic,$(1),ns-k330,2686976)
|
||||
endef
|
||||
|
||||
define Image/Build/squashfs
|
||||
$(call prepare_generic_squashfs,$(KDIR)/root.squashfs)
|
||||
|
||||
$(call build_squashfs,64k)
|
||||
$(call Image/Build/NSB3AST,squashfs-64k)
|
||||
$(call Image/Build/NSK330,squashfs-64k)
|
||||
endef
|
||||
|
||||
define Image/Build/jffs2-64k
|
||||
dd if=$(KDIR)/root.$(1) of=$(BIN_DIR)/$(IMG_PREFIX)-root.$(1) bs=64k conv=sync
|
||||
endef
|
||||
|
||||
define Image/Build
|
||||
$(call Image/Build/$(1),$(1))
|
||||
endef
|
||||
|
||||
$(eval $(call BuildImage))
|
|
@ -0,0 +1,438 @@
|
|||
From 248d9a5b63bba72bfc316b8a48c6163fce5acc22 Mon Sep 17 00:00:00 2001
|
||||
From: Paulius Zaleckas <paulius.zaleckas@gmail.com>
|
||||
Date: Thu, 18 Feb 2010 21:53:01 +0200
|
||||
Subject: [PATCH] ARM: Use cache alignment from asm/cache.h
|
||||
|
||||
Make code more optimal for ARM variants with
|
||||
different cache line size.
|
||||
|
||||
Signed-off-by: Paulius Zaleckas <paulius.zaleckas@gmail.com>
|
||||
---
|
||||
arch/arm/boot/compressed/head.S | 11 ++++++-----
|
||||
arch/arm/include/asm/dma-mapping.h | 2 +-
|
||||
arch/arm/kernel/entry-armv.S | 31 ++++++++++++++++---------------
|
||||
arch/arm/kernel/entry-common.S | 7 ++++---
|
||||
arch/arm/kernel/head.S | 3 ++-
|
||||
arch/arm/kernel/vmlinux.lds.S | 5 +++--
|
||||
arch/arm/lib/copy_page.S | 2 +-
|
||||
arch/arm/lib/memchr.S | 3 ++-
|
||||
arch/arm/lib/memset.S | 3 ++-
|
||||
arch/arm/lib/memzero.S | 3 ++-
|
||||
arch/arm/lib/strchr.S | 3 ++-
|
||||
arch/arm/lib/strncpy_from_user.S | 3 ++-
|
||||
arch/arm/lib/strnlen_user.S | 3 ++-
|
||||
arch/arm/lib/strrchr.S | 3 ++-
|
||||
arch/arm/mm/abort-ev4.S | 3 ++-
|
||||
arch/arm/mm/abort-nommu.S | 3 ++-
|
||||
16 files changed, 51 insertions(+), 37 deletions(-)
|
||||
|
||||
--- a/arch/arm/boot/compressed/head.S
|
||||
+++ b/arch/arm/boot/compressed/head.S
|
||||
@@ -9,6 +9,7 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
/*
|
||||
* Debugging stuff
|
||||
@@ -349,7 +350,7 @@ params: ldr r0, =0x10000100 @ params_p
|
||||
* This routine must preserve:
|
||||
* r4, r5, r6, r7, r8
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
cache_on: mov r3, #8 @ cache_on function
|
||||
b call_cache_fn
|
||||
|
||||
@@ -537,7 +538,7 @@ __common_mmu_cache_on:
|
||||
mcr p15, 0, r3, c2, c0, 0 @ load page table pointer
|
||||
mcr p15, 0, r1, c3, c0, 0 @ load domain access control
|
||||
b 1f
|
||||
- .align 5 @ cache line aligned
|
||||
+ .align L1_CACHE_SHIFT @ cache line aligned
|
||||
1: mcr p15, 0, r0, c1, c0, 0 @ load control register
|
||||
mrc p15, 0, r0, c1, c0, 0 @ and read it back to
|
||||
sub pc, lr, r0, lsr #32 @ properly flush pipeline
|
||||
@@ -556,7 +557,7 @@ __common_mmu_cache_on:
|
||||
* r8 = atags pointer
|
||||
* r9-r12,r14 = corrupted
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
reloc_start: add r9, r5, r0
|
||||
sub r9, r9, #128 @ do not copy the stack
|
||||
debug_reloc_start
|
||||
@@ -786,7 +787,7 @@ proc_types:
|
||||
* This routine must preserve:
|
||||
* r4, r6, r7
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
cache_off: mov r3, #12 @ cache_off function
|
||||
b call_cache_fn
|
||||
|
||||
@@ -861,7 +862,7 @@ __armv3_mmu_cache_off:
|
||||
* This routine must preserve:
|
||||
* r0, r4, r5, r6, r7
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
cache_clean_flush:
|
||||
mov r3, #16
|
||||
b call_cache_fn
|
||||
--- a/arch/arm/kernel/entry-armv.S
|
||||
+++ b/arch/arm/kernel/entry-armv.S
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <asm/unwind.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/tls.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
#include "entry-header.S"
|
||||
|
||||
@@ -165,7 +166,7 @@ ENDPROC(__und_invalid)
|
||||
stmia r5, {r0 - r4}
|
||||
.endm
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__dabt_svc:
|
||||
svc_entry
|
||||
|
||||
@@ -213,7 +214,7 @@ __dabt_svc:
|
||||
UNWIND(.fnend )
|
||||
ENDPROC(__dabt_svc)
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__irq_svc:
|
||||
svc_entry
|
||||
|
||||
@@ -257,7 +258,7 @@ svc_preempt:
|
||||
b 1b
|
||||
#endif
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__und_svc:
|
||||
#ifdef CONFIG_KPROBES
|
||||
@ If a kprobe is about to simulate a "stmdb sp..." instruction,
|
||||
@@ -303,7 +304,7 @@ __und_svc:
|
||||
UNWIND(.fnend )
|
||||
ENDPROC(__und_svc)
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__pabt_svc:
|
||||
svc_entry
|
||||
|
||||
@@ -339,7 +340,7 @@ __pabt_svc:
|
||||
UNWIND(.fnend )
|
||||
ENDPROC(__pabt_svc)
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
.LCcralign:
|
||||
.word cr_alignment
|
||||
#ifdef MULTI_DABORT
|
||||
@@ -412,7 +413,7 @@ ENDPROC(__pabt_svc)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__dabt_usr:
|
||||
usr_entry
|
||||
kuser_cmpxchg_check
|
||||
@@ -444,7 +445,7 @@ __dabt_usr:
|
||||
UNWIND(.fnend )
|
||||
ENDPROC(__dabt_usr)
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__irq_usr:
|
||||
usr_entry
|
||||
kuser_cmpxchg_check
|
||||
@@ -473,7 +474,7 @@ ENDPROC(__irq_usr)
|
||||
|
||||
.ltorg
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__und_usr:
|
||||
usr_entry
|
||||
|
||||
@@ -689,7 +690,7 @@ __und_usr_unknown:
|
||||
b do_undefinstr
|
||||
ENDPROC(__und_usr_unknown)
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__pabt_usr:
|
||||
usr_entry
|
||||
|
||||
@@ -803,7 +804,7 @@ ENDPROC(__switch_to)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
.globl __kuser_helper_start
|
||||
__kuser_helper_start:
|
||||
|
||||
@@ -843,7 +844,7 @@ __kuser_memory_barrier: @ 0xffff0fa0
|
||||
smp_dmb
|
||||
usr_ret lr
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
|
||||
/*
|
||||
* Reference prototype:
|
||||
@@ -973,7 +974,7 @@ kuser_cmpxchg_fixup:
|
||||
|
||||
#endif
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
|
||||
/*
|
||||
* Reference prototype:
|
||||
@@ -1051,7 +1052,7 @@ __kuser_helper_end:
|
||||
* of which is copied into r0 for the mode specific abort handler.
|
||||
*/
|
||||
.macro vector_stub, name, mode, correction=0
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
|
||||
vector_\name:
|
||||
.if \correction
|
||||
@@ -1182,7 +1183,7 @@ __stubs_start:
|
||||
.long __und_invalid @ e
|
||||
.long __und_invalid @ f
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
|
||||
/*=============================================================================
|
||||
* Undefined FIQs
|
||||
@@ -1212,7 +1213,7 @@ vector_addrexcptn:
|
||||
* We group all the following data together to optimise
|
||||
* for CPUs with separate I & D caches.
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
|
||||
.LCvswi:
|
||||
.word vector_swi
|
||||
--- a/arch/arm/kernel/entry-common.S
|
||||
+++ b/arch/arm/kernel/entry-common.S
|
||||
@@ -10,13 +10,14 @@
|
||||
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/ftrace.h>
|
||||
+#include <asm/cache.h>
|
||||
#include <mach/entry-macro.S>
|
||||
#include <asm/unwind.h>
|
||||
|
||||
#include "entry-header.S"
|
||||
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
/*
|
||||
* This is the fast syscall return path. We do as little as
|
||||
* possible here, and this includes saving r0 back into the SVC
|
||||
@@ -221,7 +222,7 @@ ftrace_stub:
|
||||
#define A710(code...)
|
||||
#endif
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
ENTRY(vector_swi)
|
||||
sub sp, sp, #S_FRAME_SIZE
|
||||
stmia sp, {r0 - r12} @ Calling r0 - r12
|
||||
@@ -354,7 +355,7 @@ __sys_trace_return:
|
||||
bl syscall_trace
|
||||
b ret_slow_syscall
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
#ifdef CONFIG_ALIGNMENT_TRAP
|
||||
.type __cr_alignment, #object
|
||||
__cr_alignment:
|
||||
--- a/arch/arm/kernel/head.S
|
||||
+++ b/arch/arm/kernel/head.S
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <asm/memory.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/system.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
#if (PHYS_OFFSET & 0x001fffff)
|
||||
#error "PHYS_OFFSET must be at an even 2MiB boundary!"
|
||||
@@ -192,7 +193,7 @@ ENDPROC(__enable_mmu)
|
||||
*
|
||||
* other registers depend on the function called upon completion
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__turn_mmu_on:
|
||||
mov r0, r0
|
||||
mcr p15, 0, r0, c1, c0, 0 @ write control reg
|
||||
--- a/arch/arm/kernel/vmlinux.lds.S
|
||||
+++ b/arch/arm/kernel/vmlinux.lds.S
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/page.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(stext)
|
||||
--- a/arch/arm/lib/copy_page.S
|
||||
+++ b/arch/arm/lib/copy_page.S
|
||||
@@ -17,7 +17,7 @@
|
||||
#define COPY_COUNT (PAGE_SZ / (2 * L1_CACHE_BYTES) PLD( -1 ))
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
/*
|
||||
* StrongARM optimised copy_page routine
|
||||
* now 1.78bytes/cycle, was 1.60 bytes/cycle (50MHz bus -> 89MB/s)
|
||||
--- a/arch/arm/lib/memchr.S
|
||||
+++ b/arch/arm/lib/memchr.S
|
||||
@@ -11,9 +11,10 @@
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
ENTRY(memchr)
|
||||
1: subs r2, r2, #1
|
||||
bmi 2f
|
||||
--- a/arch/arm/lib/memset.S
|
||||
+++ b/arch/arm/lib/memset.S
|
||||
@@ -11,9 +11,10 @@
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
.word 0
|
||||
|
||||
1: subs r2, r2, #4 @ 1 do we have enough
|
||||
--- a/arch/arm/lib/memzero.S
|
||||
+++ b/arch/arm/lib/memzero.S
|
||||
@@ -9,9 +9,10 @@
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
.word 0
|
||||
/*
|
||||
* Align the pointer in r0. r3 contains the number of bytes that we are
|
||||
--- a/arch/arm/lib/strchr.S
|
||||
+++ b/arch/arm/lib/strchr.S
|
||||
@@ -11,9 +11,10 @@
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
ENTRY(strchr)
|
||||
and r1, r1, #0xff
|
||||
1: ldrb r2, [r0], #1
|
||||
--- a/arch/arm/lib/strncpy_from_user.S
|
||||
+++ b/arch/arm/lib/strncpy_from_user.S
|
||||
@@ -10,9 +10,10 @@
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/errno.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
|
||||
/*
|
||||
* Copy a string from user space to kernel space.
|
||||
--- a/arch/arm/lib/strnlen_user.S
|
||||
+++ b/arch/arm/lib/strnlen_user.S
|
||||
@@ -10,9 +10,10 @@
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/errno.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
|
||||
/* Prototype: unsigned long __strnlen_user(const char *str, long n)
|
||||
* Purpose : get length of a string in user memory
|
||||
--- a/arch/arm/lib/strrchr.S
|
||||
+++ b/arch/arm/lib/strrchr.S
|
||||
@@ -11,9 +11,10 @@
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
ENTRY(strrchr)
|
||||
mov r3, #0
|
||||
1: ldrb r2, [r0], #1
|
||||
--- a/arch/arm/mm/abort-ev4.S
|
||||
+++ b/arch/arm/mm/abort-ev4.S
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
+#include <asm/cache.h>
|
||||
/*
|
||||
* Function: v4_early_abort
|
||||
*
|
||||
@@ -17,7 +18,7 @@
|
||||
* abort here if the I-TLB and D-TLB aren't seeing the same
|
||||
* picture. Unfortunately, this does happen. We live with it.
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
ENTRY(v4_early_abort)
|
||||
mrc p15, 0, r1, c5, c0, 0 @ get FSR
|
||||
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
||||
--- a/arch/arm/mm/abort-nommu.S
|
||||
+++ b/arch/arm/mm/abort-nommu.S
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
+#include <asm/cache.h>
|
||||
/*
|
||||
* Function: nommu_early_abort
|
||||
*
|
||||
@@ -12,7 +13,7 @@
|
||||
* Note: There is no FSR/FAR on !CPU_CP15_MMU cores.
|
||||
* Just fill zero into the registers.
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
ENTRY(nommu_early_abort)
|
||||
mov r0, #0 @ clear r0, r1 (no FSR/FAR)
|
||||
mov r1, #0
|
|
@ -0,0 +1,24 @@
|
|||
--- a/kernel/printk.c
|
||||
+++ b/kernel/printk.c
|
||||
@@ -48,6 +48,10 @@
|
||||
#define for_each_console(con) \
|
||||
for (con = console_drivers; con != NULL; con = con->next)
|
||||
|
||||
+#ifdef CONFIG_DEBUG_LL
|
||||
+extern void printascii(char *);
|
||||
+#endif /* CONFIG_DEBUG_LL */
|
||||
+
|
||||
/*
|
||||
* Architectures can override it:
|
||||
*/
|
||||
@@ -760,6 +764,10 @@ asmlinkage int vprintk(const char *fmt,
|
||||
}
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_DEBUG_LL
|
||||
+ printascii(printk_buf);
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Copy the output into log_buf. If the caller didn't provide
|
||||
* appropriate log level tags, we insert them here
|
|
@ -0,0 +1,47 @@
|
|||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -954,10 +954,15 @@ source "arch/arm/mach-vexpress/Kconfig"
|
||||
|
||||
source "arch/arm/mach-w90x900/Kconfig"
|
||||
|
||||
+source "arch/arm/plat-fa/Kconfig"
|
||||
+
|
||||
# Definitions to make life easier
|
||||
config ARCH_ACORN
|
||||
bool
|
||||
|
||||
+config PLAT_FA
|
||||
+ bool
|
||||
+
|
||||
config PLAT_IOP
|
||||
bool
|
||||
select GENERIC_CLOCKEVENTS
|
||||
--- a/arch/arm/Makefile
|
||||
+++ b/arch/arm/Makefile
|
||||
@@ -202,6 +202,7 @@ plat-$(CONFIG_ARCH_MXC) := mxc
|
||||
plat-$(CONFIG_ARCH_OMAP) := omap
|
||||
plat-$(CONFIG_ARCH_S3C64XX) := samsung
|
||||
plat-$(CONFIG_ARCH_STMP3XXX) := stmp3xxx
|
||||
+plat-$(CONFIG_PLAT_FA) := fa
|
||||
plat-$(CONFIG_PLAT_IOP) := iop
|
||||
plat-$(CONFIG_PLAT_NOMADIK) := nomadik
|
||||
plat-$(CONFIG_PLAT_ORION) := orion
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/plat-fa/Makefile
|
||||
@@ -0,0 +1,10 @@
|
||||
+#
|
||||
+# Makefile for the linux kernel.
|
||||
+#
|
||||
+
|
||||
+obj-y :=
|
||||
+
|
||||
+obj-m :=
|
||||
+obj-n :=
|
||||
+obj- :=
|
||||
+
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/plat-fa/Kconfig
|
||||
@@ -0,0 +1,3 @@
|
||||
+if PLAT_FA
|
||||
+
|
||||
+endif
|
|
@ -0,0 +1,143 @@
|
|||
--- /dev/null
|
||||
+++ b/arch/arm/plat-fa/include/plat/time.h
|
||||
@@ -0,0 +1,20 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#ifndef _FA_TIME_H
|
||||
+#define _FA_TIME_H
|
||||
+
|
||||
+#define FA_TIMER1 0
|
||||
+#define FA_TIMER2 1
|
||||
+#define FA_TIMER3 2
|
||||
+
|
||||
+int __init fa_timer_init(unsigned int mapbase, unsigned int irq,
|
||||
+ unsigned int timer, unsigned int freq);
|
||||
+
|
||||
+#endif /* _FA_TIME_H */
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/plat-fa/time.c
|
||||
@@ -0,0 +1,97 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2001-2006 Storlink, Corp.
|
||||
+ * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <linux/io.h>
|
||||
+
|
||||
+#include <asm/mach/time.h>
|
||||
+#include <plat/time.h>
|
||||
+
|
||||
+/*
|
||||
+ * Register definitions for the timers
|
||||
+ */
|
||||
+#define TIMER_COUNT(_base, _tmr) ((_base) + 0x00 + (_tmr) * 0x10)
|
||||
+#define TIMER_LOAD(_base, _tmr) ((_base) + 0x04 + (_tmr) * 0x10)
|
||||
+#define TIMER_MATCH1(_base, _tmr) ((_base) + 0x08 + (_tmr) * 0x10)
|
||||
+#define TIMER_MATCH2(_base, _tmr) ((_base) + 0x0c + (_tmr) * 0x10)
|
||||
+
|
||||
+#define TIMER_CR(_base) ((_base) + 0x30)
|
||||
+#define TIMER_STATUS(_base) ((_base) + 0x34)
|
||||
+#define TIMER_MASK(_base) ((_base) + 0x38)
|
||||
+
|
||||
+#define TIMER_SIZE 0x3c
|
||||
+
|
||||
+#define TIMER_CR_ENABLE(x) (1 << ((x) * 3))
|
||||
+#define TIMER_CR_CLOCK(x) (1 << ((x) * 3 + 1))
|
||||
+#define TIMER_CR_INT(x) (1 << ((x) * 3 + 2))
|
||||
+#define TIMER_CR_DOWN(x) (1 << ((x) * 3 + 9))
|
||||
+
|
||||
+#define TIMER_MASK_MATCH1(x) (1 << ((x) * 3))
|
||||
+#define TIMER_MASK_MATCH2(x) (1 << ((x) * 3 + 1))
|
||||
+#define TIMER_MASK_OF(x) (1 << ((x) * 3 + 2))
|
||||
+
|
||||
+#define TIMER_MASK_ALL 0x7ff
|
||||
+
|
||||
+/*
|
||||
+ * IRQ handler for the timer
|
||||
+ */
|
||||
+static irqreturn_t fa_timer_interrupt(int irq, void *dev_id)
|
||||
+{
|
||||
+ timer_tick();
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static struct irqaction fa_timer_irq = {
|
||||
+ .name = "Timer Tick",
|
||||
+ .flags = IRQF_DISABLED | IRQF_TIMER,
|
||||
+ .handler = fa_timer_interrupt,
|
||||
+};
|
||||
+
|
||||
+int __init fa_timer_init(unsigned int mapbase, unsigned int irq,
|
||||
+ unsigned int timer, unsigned int freq)
|
||||
+{
|
||||
+ void __iomem *base;
|
||||
+
|
||||
+ base = ioremap(mapbase, TIMER_SIZE);
|
||||
+ if (!base)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ /* disable timers, clear status and mask all interrupts */
|
||||
+ __raw_writel(0, TIMER_CR(base));
|
||||
+ __raw_writel(0, TIMER_STATUS(base));
|
||||
+ __raw_writel(TIMER_MASK_ALL, TIMER_MASK(base));
|
||||
+
|
||||
+ /*
|
||||
+ * Make irqs happen for the system timer
|
||||
+ */
|
||||
+ setup_irq(irq, &fa_timer_irq);
|
||||
+
|
||||
+ /* Setup the timer */
|
||||
+ __raw_writel(freq / HZ, TIMER_COUNT(base, timer));
|
||||
+ __raw_writel(freq / HZ, TIMER_LOAD(base, timer));
|
||||
+ __raw_writel(0, TIMER_MATCH1(base, timer));
|
||||
+ __raw_writel(0, TIMER_MATCH2(base, timer));
|
||||
+
|
||||
+ /* Enable interrupt and start the timer */
|
||||
+ __raw_writel(TIMER_MASK_ALL & ~TIMER_MASK_OF(timer),
|
||||
+ TIMER_MASK(base));
|
||||
+
|
||||
+ __raw_writel(TIMER_CR_ENABLE(timer) |
|
||||
+ TIMER_CR_INT(timer) |
|
||||
+ TIMER_CR_DOWN(timer),
|
||||
+ TIMER_CR(base));
|
||||
+
|
||||
+ iounmap(base);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
--- a/arch/arm/plat-fa/Kconfig
|
||||
+++ b/arch/arm/plat-fa/Kconfig
|
||||
@@ -1,3 +1,6 @@
|
||||
if PLAT_FA
|
||||
|
||||
+config PLAT_FA_TIME
|
||||
+ def_bool n
|
||||
+
|
||||
endif
|
||||
--- a/arch/arm/plat-fa/Makefile
|
||||
+++ b/arch/arm/plat-fa/Makefile
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
obj-y :=
|
||||
|
||||
+obj-$(CONFIG_PLAT_FA_TIME) += time.o
|
||||
+
|
||||
obj-m :=
|
||||
obj-n :=
|
||||
obj- :=
|
|
@ -0,0 +1,335 @@
|
|||
--- /dev/null
|
||||
+++ b/arch/arm/plat-fa/gpio.c
|
||||
@@ -0,0 +1,275 @@
|
||||
+/*
|
||||
+ * Gpiochip and interrupt routines for Faraday FA526 based SoCs
|
||||
+ *
|
||||
+ * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
|
||||
+ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * Based on plat-mxc/gpio.c:
|
||||
+ * MXC GPIO supchip. (c) 2008 Daniel Mack <daniel@caiaq.de>
|
||||
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/spinlock.h>
|
||||
+
|
||||
+#include <plat/gpio.h>
|
||||
+
|
||||
+#define GPIO_DATA_OUT 0x0
|
||||
+#define GPIO_DATA_IN 0x4
|
||||
+#define GPIO_DIR 0x8
|
||||
+#define GPIO_DATA_SET 0x10
|
||||
+#define GPIO_DATA_CLR 0x14
|
||||
+#define GPIO_PULL_EN 0x18
|
||||
+#define GPIO_PULL_TYPE 0x1C
|
||||
+#define GPIO_INT_EN 0x20
|
||||
+#define GPIO_INT_STAT 0x24
|
||||
+#define GPIO_INT_MASK 0x2C
|
||||
+#define GPIO_INT_CLR 0x30
|
||||
+#define GPIO_INT_TYPE 0x34
|
||||
+#define GPIO_INT_BOTH_EDGE 0x38
|
||||
+#define GPIO_INT_LEVEL 0x3C
|
||||
+#define GPIO_DEBOUNCE_EN 0x40
|
||||
+#define GPIO_DEBOUNCE_PRESCALE 0x44
|
||||
+
|
||||
+#define GPIO_REGS_SIZE 0x48
|
||||
+
|
||||
+static DEFINE_SPINLOCK(fa_gpio_lock);
|
||||
+
|
||||
+static inline struct fa_gpio_chip *to_fgc(struct gpio_chip *chip)
|
||||
+{
|
||||
+ return container_of(chip, struct fa_gpio_chip, gpio_chip);
|
||||
+}
|
||||
+
|
||||
+static void _fa_gpio_irq_setenable(unsigned int irq, int enable)
|
||||
+{
|
||||
+ struct fa_gpio_chip *fgc = get_irq_chip_data(irq);
|
||||
+ void __iomem *base = fgc->mem_base;
|
||||
+ unsigned int gpio = irq - fgc->irq_base;
|
||||
+ unsigned int reg;
|
||||
+
|
||||
+ reg = __raw_readl(base + GPIO_INT_EN);
|
||||
+ reg = (reg & (~(1 << gpio))) | (!!enable << gpio);
|
||||
+ __raw_writel(reg, base + GPIO_INT_EN);
|
||||
+}
|
||||
+
|
||||
+static void fa_gpio_irq_ack(unsigned int irq)
|
||||
+{
|
||||
+ struct fa_gpio_chip *fgc = get_irq_chip_data(irq);
|
||||
+ unsigned int gpio = irq - fgc->irq_base;
|
||||
+
|
||||
+ __raw_writel(1 << gpio, fgc->mem_base + GPIO_INT_CLR);
|
||||
+}
|
||||
+
|
||||
+static void fa_gpio_irq_mask(unsigned int irq)
|
||||
+{
|
||||
+ _fa_gpio_irq_setenable(irq, 0);
|
||||
+}
|
||||
+
|
||||
+static void fa_gpio_irq_unmask(unsigned int irq)
|
||||
+{
|
||||
+ _fa_gpio_irq_setenable(irq, 1);
|
||||
+}
|
||||
+
|
||||
+static int fa_gpio_irq_set_type(unsigned int irq, unsigned int type)
|
||||
+{
|
||||
+ struct fa_gpio_chip *fgc = get_irq_chip_data(irq);
|
||||
+ void __iomem *base = fgc->mem_base;
|
||||
+ unsigned int gpio = irq - fgc->irq_base;
|
||||
+ unsigned int gpio_mask = 1 << gpio;
|
||||
+ unsigned int reg_both, reg_level, reg_type;
|
||||
+
|
||||
+ reg_type = __raw_readl(base + GPIO_INT_TYPE);
|
||||
+ reg_level = __raw_readl(base + GPIO_INT_LEVEL);
|
||||
+ reg_both = __raw_readl(base + GPIO_INT_BOTH_EDGE);
|
||||
+
|
||||
+ switch (type) {
|
||||
+ case IRQ_TYPE_EDGE_BOTH:
|
||||
+ reg_type &= ~gpio_mask;
|
||||
+ reg_both |= gpio_mask;
|
||||
+ break;
|
||||
+ case IRQ_TYPE_EDGE_RISING:
|
||||
+ reg_type &= ~gpio_mask;
|
||||
+ reg_both &= ~gpio_mask;
|
||||
+ reg_level &= ~gpio_mask;
|
||||
+ break;
|
||||
+ case IRQ_TYPE_EDGE_FALLING:
|
||||
+ reg_type &= ~gpio_mask;
|
||||
+ reg_both &= ~gpio_mask;
|
||||
+ reg_level |= gpio_mask;
|
||||
+ break;
|
||||
+ case IRQ_TYPE_LEVEL_HIGH:
|
||||
+ reg_type |= gpio_mask;
|
||||
+ reg_level &= ~gpio_mask;
|
||||
+ break;
|
||||
+ case IRQ_TYPE_LEVEL_LOW:
|
||||
+ reg_type |= gpio_mask;
|
||||
+ reg_level |= gpio_mask;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ __raw_writel(reg_type, base + GPIO_INT_TYPE);
|
||||
+ __raw_writel(reg_level, base + GPIO_INT_LEVEL);
|
||||
+ __raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE);
|
||||
+
|
||||
+ fa_gpio_irq_ack(irq);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void fa_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
+{
|
||||
+ struct fa_gpio_data *data = get_irq_data(irq);
|
||||
+ unsigned int chip;
|
||||
+
|
||||
+ for (chip = 0; chip < data->nchips; chip++) {
|
||||
+ struct fa_gpio_chip *fgc = &data->chips[chip];
|
||||
+ unsigned int status;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ status = __raw_readl(fgc->mem_base + GPIO_INT_STAT);
|
||||
+ for (i = fgc->irq_base; status != 0; status >>= 1, i++) {
|
||||
+ if ((status & 1) == 0)
|
||||
+ continue;
|
||||
+
|
||||
+ BUG_ON(!(irq_desc[i].handle_irq));
|
||||
+ irq_desc[i].handle_irq(i, &irq_desc[i]);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static struct irq_chip fa_gpio_irq_chip = {
|
||||
+ .name = "GPIO",
|
||||
+ .ack = fa_gpio_irq_ack,
|
||||
+ .mask = fa_gpio_irq_mask,
|
||||
+ .unmask = fa_gpio_irq_unmask,
|
||||
+ .set_type = fa_gpio_irq_set_type,
|
||||
+};
|
||||
+
|
||||
+static void _fa_gpio_set_direction(struct fa_gpio_chip *fgc, unsigned offset,
|
||||
+ int is_output)
|
||||
+{
|
||||
+ unsigned int reg;
|
||||
+
|
||||
+ reg = __raw_readl(fgc->mem_base + GPIO_DIR);
|
||||
+ if (is_output)
|
||||
+ reg |= 1 << offset;
|
||||
+ else
|
||||
+ reg &= ~(1 << offset);
|
||||
+ __raw_writel(reg, fgc->mem_base + GPIO_DIR);
|
||||
+}
|
||||
+
|
||||
+static void _fa_gpio_set(struct fa_gpio_chip *fgc, unsigned offset, int value)
|
||||
+{
|
||||
+ if (value)
|
||||
+ __raw_writel(1 << offset, fgc->mem_base + GPIO_DATA_SET);
|
||||
+ else
|
||||
+ __raw_writel(1 << offset, fgc->mem_base + GPIO_DATA_CLR);
|
||||
+}
|
||||
+
|
||||
+static void fa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
+{
|
||||
+ struct fa_gpio_chip *fgc = to_fgc(chip);
|
||||
+
|
||||
+ _fa_gpio_set(fgc, offset, value);
|
||||
+}
|
||||
+
|
||||
+static int fa_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
+{
|
||||
+ struct fa_gpio_chip *fgc = to_fgc(chip);
|
||||
+
|
||||
+ return (__raw_readl(fgc->mem_base + GPIO_DATA_IN) >> offset) & 1;
|
||||
+}
|
||||
+
|
||||
+static int fa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
+{
|
||||
+ struct fa_gpio_chip *fgc = to_fgc(chip);
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&fa_gpio_lock, flags);
|
||||
+
|
||||
+ _fa_gpio_set_direction(fgc, offset, 0);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&fa_gpio_lock, flags);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int fa_gpio_direction_output(struct gpio_chip *chip,
|
||||
+ unsigned offset,
|
||||
+ int value)
|
||||
+{
|
||||
+ struct fa_gpio_chip *fgc = to_fgc(chip);
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&fa_gpio_lock, flags);
|
||||
+
|
||||
+ _fa_gpio_set(fgc, offset, value);
|
||||
+ _fa_gpio_set_direction(fgc, offset, 1);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&fa_gpio_lock, flags);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int fa_gpio_init_chip(struct fa_gpio_chip *fgc)
|
||||
+{
|
||||
+ void __iomem *mem_base;
|
||||
+ unsigned int i;
|
||||
+ int err;
|
||||
+
|
||||
+ mem_base = ioremap(fgc->map_base, GPIO_REGS_SIZE);
|
||||
+ if (!mem_base)
|
||||
+ return -ENXIO;
|
||||
+
|
||||
+ fgc->mem_base = mem_base;
|
||||
+
|
||||
+ fgc->gpio_chip.direction_input = fa_gpio_direction_input;
|
||||
+ fgc->gpio_chip.direction_output = fa_gpio_direction_output;
|
||||
+ fgc->gpio_chip.get = fa_gpio_get;
|
||||
+ fgc->gpio_chip.set = fa_gpio_set;
|
||||
+
|
||||
+ /* disable, unmask and clear all interrupts */
|
||||
+ __raw_writel(0x0, mem_base + GPIO_INT_EN);
|
||||
+ __raw_writel(0x0, mem_base + GPIO_INT_MASK);
|
||||
+ __raw_writel(~0x0, mem_base + GPIO_INT_CLR);
|
||||
+
|
||||
+ for (i = fgc->irq_base;
|
||||
+ i < fgc->irq_base + fgc->gpio_chip.ngpio; i++) {
|
||||
+ set_irq_chip(i, &fa_gpio_irq_chip);
|
||||
+ set_irq_chip_data(i, fgc);
|
||||
+ set_irq_handler(i, handle_edge_irq);
|
||||
+ set_irq_flags(i, IRQF_VALID);
|
||||
+ }
|
||||
+
|
||||
+ err = gpiochip_add(&fgc->gpio_chip);
|
||||
+ if (err)
|
||||
+ goto unmap;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+ unmap:
|
||||
+ iounmap(fgc->mem_base);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+void __init fa_gpio_init(struct fa_gpio_data *data)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < data->nchips; i++) {
|
||||
+ int err;
|
||||
+
|
||||
+ err = fa_gpio_init_chip(&data->chips[i]);
|
||||
+ if (WARN(err, "GPIO init failed\n"))
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ set_irq_chained_handler(data->irq, fa_gpio_irq_handler);
|
||||
+ set_irq_data(data->irq, data);
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/plat-fa/include/plat/gpio.h
|
||||
@@ -0,0 +1,33 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file 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 _FA_GPIO_H
|
||||
+#define _FA_GPIO_H
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <linux/io.h>
|
||||
+
|
||||
+struct fa_gpio_chip {
|
||||
+ struct gpio_chip gpio_chip;
|
||||
+ unsigned int map_base;
|
||||
+ unsigned int irq_base;
|
||||
+
|
||||
+ void __iomem *mem_base;
|
||||
+};
|
||||
+
|
||||
+struct fa_gpio_data {
|
||||
+ struct fa_gpio_chip *chips;
|
||||
+ unsigned int nchips;
|
||||
+ unsigned int irq;
|
||||
+};
|
||||
+
|
||||
+void __init fa_gpio_init(struct fa_gpio_data *data);
|
||||
+
|
||||
+#endif /* _FA_GPIO_H */
|
||||
--- a/arch/arm/plat-fa/Kconfig
|
||||
+++ b/arch/arm/plat-fa/Kconfig
|
||||
@@ -1,5 +1,8 @@
|
||||
if PLAT_FA
|
||||
|
||||
+config PLAT_FA_GPIO
|
||||
+ def_bool n
|
||||
+
|
||||
config PLAT_FA_TIME
|
||||
def_bool n
|
||||
|
||||
--- a/arch/arm/plat-fa/Makefile
|
||||
+++ b/arch/arm/plat-fa/Makefile
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
obj-y :=
|
||||
|
||||
+obj-$(CONFIG_PLAT_FA_GPIO) += gpio.o
|
||||
obj-$(CONFIG_PLAT_FA_TIME) += time.o
|
||||
|
||||
obj-m :=
|
|
@ -0,0 +1,456 @@
|
|||
--- a/drivers/watchdog/Kconfig
|
||||
+++ b/drivers/watchdog/Kconfig
|
||||
@@ -331,6 +331,13 @@ config IMX2_WDT
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imx2_wdt.
|
||||
|
||||
+config FA_WATCHDOG
|
||||
+ tristate "Faraday watchdog"
|
||||
+ depends on ARCH_GEMINI
|
||||
+ help
|
||||
+ Say Y here if you want support for the built-in watchdog timer
|
||||
+ found in some Faraday FA526 based SoCs.
|
||||
+
|
||||
# AVR32 Architecture
|
||||
|
||||
config AT32AP700X_WDT
|
||||
--- a/drivers/watchdog/Makefile
|
||||
+++ b/drivers/watchdog/Makefile
|
||||
@@ -49,6 +49,7 @@ obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_
|
||||
obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o
|
||||
obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
|
||||
obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
|
||||
+obj-$(CONFIG_FA_WATCHDOG) += fa_wdt.o
|
||||
|
||||
# AVR32 Architecture
|
||||
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/watchdog/fa_wdt.c
|
||||
@@ -0,0 +1,411 @@
|
||||
+/*
|
||||
+ * Watchdog driver for SoCs based on the Faraday FA526 core
|
||||
+ *
|
||||
+ * Copyright (C) 2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
|
||||
+ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/fs.h>
|
||||
+#include <linux/notifier.h>
|
||||
+#include <linux/reboot.h>
|
||||
+#include <linux/uaccess.h>
|
||||
+#include <linux/miscdevice.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/watchdog.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/fa_wdt.h>
|
||||
+
|
||||
+#define FA_WDCOUNTER 0x0
|
||||
+#define FA_WDLOAD 0x4
|
||||
+#define FA_WDRESTART 0x8
|
||||
+
|
||||
+#define WDRESTART_MAGIC 0x5AB9
|
||||
+
|
||||
+#define FA_WDCR 0xC
|
||||
+
|
||||
+#define WDCR_CLOCK_5MHZ (1 << 4)
|
||||
+#define WDCR_SYS_RST (1 << 1)
|
||||
+#define WDCR_ENABLE (1 << 0)
|
||||
+
|
||||
+#define WDT_DEFAULT_TIMEOUT 13
|
||||
+
|
||||
+/* status bits */
|
||||
+#define WDT_ACTIVE 0
|
||||
+#define WDT_OK_TO_CLOSE 1
|
||||
+
|
||||
+static unsigned int timeout = WDT_DEFAULT_TIMEOUT;
|
||||
+static int nowayout = WATCHDOG_NOWAYOUT;
|
||||
+
|
||||
+static DEFINE_SPINLOCK(fa_wdt_lock);
|
||||
+
|
||||
+static struct platform_device *fa_wdt_dev;
|
||||
+
|
||||
+struct fa_wdt_struct {
|
||||
+ struct resource *res;
|
||||
+ struct device *dev;
|
||||
+ void __iomem *base;
|
||||
+ unsigned long status;
|
||||
+ unsigned int clock;
|
||||
+ unsigned int max_timeout;
|
||||
+};
|
||||
+
|
||||
+static const struct watchdog_info fa_wdt_info = {
|
||||
+ .identity = "Faraday watchdog",
|
||||
+ .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING |
|
||||
+ WDIOF_SETTIMEOUT,
|
||||
+};
|
||||
+
|
||||
+/* Disable the watchdog. */
|
||||
+static void fa_wdt_stop(struct fa_wdt_struct *fa_wdt)
|
||||
+{
|
||||
+ spin_lock(&fa_wdt_lock);
|
||||
+
|
||||
+ __raw_writel(0, fa_wdt->base + FA_WDCR);
|
||||
+
|
||||
+ clear_bit(WDT_ACTIVE, &fa_wdt->status);
|
||||
+
|
||||
+ spin_unlock(&fa_wdt_lock);
|
||||
+}
|
||||
+
|
||||
+/* Service the watchdog */
|
||||
+static void fa_wdt_service(struct fa_wdt_struct *fa_wdt)
|
||||
+{
|
||||
+ __raw_writel(WDRESTART_MAGIC, fa_wdt->base + FA_WDRESTART);
|
||||
+}
|
||||
+
|
||||
+/* Enable and reset the watchdog. */
|
||||
+static void fa_wdt_start(struct fa_wdt_struct *fa_wdt)
|
||||
+{
|
||||
+ spin_lock(&fa_wdt_lock);
|
||||
+
|
||||
+ __raw_writel(timeout * fa_wdt->clock,
|
||||
+ fa_wdt->base + FA_WDLOAD);
|
||||
+
|
||||
+ fa_wdt_service(fa_wdt);
|
||||
+
|
||||
+ /* set clock before enabling */
|
||||
+ __raw_writel(WDCR_CLOCK_5MHZ | WDCR_SYS_RST,
|
||||
+ fa_wdt->base + FA_WDCR);
|
||||
+
|
||||
+ __raw_writel(WDCR_CLOCK_5MHZ | WDCR_SYS_RST | WDCR_ENABLE,
|
||||
+ fa_wdt->base + FA_WDCR);
|
||||
+
|
||||
+ set_bit(WDT_ACTIVE, &fa_wdt->status);
|
||||
+
|
||||
+ spin_unlock(&fa_wdt_lock);
|
||||
+}
|
||||
+
|
||||
+/* Watchdog device is opened, and watchdog starts running. */
|
||||
+static int fa_wdt_open(struct inode *inode, struct file *file)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = platform_get_drvdata(fa_wdt_dev);
|
||||
+
|
||||
+ if (test_bit(WDT_ACTIVE, &fa_wdt->status))
|
||||
+ return -EBUSY;
|
||||
+
|
||||
+ file->private_data = fa_wdt;
|
||||
+
|
||||
+ fa_wdt_start(fa_wdt);
|
||||
+
|
||||
+ return nonseekable_open(inode, file);
|
||||
+}
|
||||
+
|
||||
+/* Close the watchdog device. */
|
||||
+static int fa_wdt_close(struct inode *inode, struct file *file)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = file->private_data;
|
||||
+
|
||||
+ /* Disable the watchdog if possible */
|
||||
+ if (test_bit(WDT_OK_TO_CLOSE, &fa_wdt->status))
|
||||
+ fa_wdt_stop(fa_wdt);
|
||||
+ else
|
||||
+ dev_warn(fa_wdt->dev, "Device closed unexpectedly - timer will not stop\n");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Handle commands from user-space. */
|
||||
+static long fa_wdt_ioctl(struct file *file, unsigned int cmd,
|
||||
+ unsigned long arg)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = file->private_data;
|
||||
+
|
||||
+ int value;
|
||||
+
|
||||
+ switch (cmd) {
|
||||
+ case WDIOC_KEEPALIVE:
|
||||
+ fa_wdt_service(fa_wdt);
|
||||
+ return 0;
|
||||
+
|
||||
+ case WDIOC_GETSUPPORT:
|
||||
+ return copy_to_user((struct watchdog_info *)arg, &fa_wdt_info,
|
||||
+ sizeof(fa_wdt_info)) ? -EFAULT : 0;
|
||||
+
|
||||
+ case WDIOC_SETTIMEOUT:
|
||||
+ if (get_user(value, (int *)arg))
|
||||
+ return -EFAULT;
|
||||
+
|
||||
+ if ((value < 1) || (value > fa_wdt->max_timeout))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ timeout = value;
|
||||
+
|
||||
+ /* restart wdt to use new timeout */
|
||||
+ fa_wdt_stop(fa_wdt);
|
||||
+ fa_wdt_start(fa_wdt);
|
||||
+
|
||||
+ /* Fall through */
|
||||
+ case WDIOC_GETTIMEOUT:
|
||||
+ return put_user(timeout, (int *)arg);
|
||||
+
|
||||
+ case WDIOC_GETTIMELEFT:
|
||||
+ value = __raw_readl(fa_wdt->base + FA_WDCOUNTER);
|
||||
+ return put_user(value / fa_wdt->clock, (int *)arg);
|
||||
+
|
||||
+ default:
|
||||
+ return -ENOTTY;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Refresh the watchdog whenever device is written to. */
|
||||
+static ssize_t fa_wdt_write(struct file *file, const char *data,
|
||||
+ size_t len, loff_t *ppos)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = file->private_data;
|
||||
+
|
||||
+ if (len) {
|
||||
+ if (!nowayout) {
|
||||
+ size_t i;
|
||||
+
|
||||
+ clear_bit(WDT_OK_TO_CLOSE, &fa_wdt->status);
|
||||
+ for (i = 0; i != len; i++) {
|
||||
+ char c;
|
||||
+
|
||||
+ if (get_user(c, data + i))
|
||||
+ return -EFAULT;
|
||||
+ if (c == 'V')
|
||||
+ set_bit(WDT_OK_TO_CLOSE,
|
||||
+ &fa_wdt->status);
|
||||
+ }
|
||||
+ }
|
||||
+ fa_wdt_service(fa_wdt);
|
||||
+ }
|
||||
+
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+static int fa_wdt_notify_sys(struct notifier_block *this,
|
||||
+ unsigned long code, void *unused)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = platform_get_drvdata(fa_wdt_dev);
|
||||
+
|
||||
+ if (code == SYS_DOWN || code == SYS_HALT)
|
||||
+ fa_wdt_stop(fa_wdt);
|
||||
+
|
||||
+ return NOTIFY_DONE;
|
||||
+}
|
||||
+
|
||||
+static struct notifier_block fa_wdt_notifier = {
|
||||
+ .notifier_call = fa_wdt_notify_sys,
|
||||
+};
|
||||
+
|
||||
+static const struct file_operations fa_wdt_fops = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .llseek = no_llseek,
|
||||
+ .unlocked_ioctl = fa_wdt_ioctl,
|
||||
+ .open = fa_wdt_open,
|
||||
+ .release = fa_wdt_close,
|
||||
+ .write = fa_wdt_write,
|
||||
+};
|
||||
+
|
||||
+static struct miscdevice fa_wdt_miscdev = {
|
||||
+ .minor = WATCHDOG_MINOR,
|
||||
+ .name = "watchdog",
|
||||
+ .fops = &fa_wdt_fops,
|
||||
+};
|
||||
+
|
||||
+static void fa_wdt_shutdown(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ fa_wdt_stop(fa_wdt);
|
||||
+}
|
||||
+
|
||||
+static int __devinit fa_wdt_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ int ret;
|
||||
+ int res_size;
|
||||
+ struct resource *res;
|
||||
+ void __iomem *base;
|
||||
+ struct fa_wdt_struct *fa_wdt;
|
||||
+ struct fa_wdt_platform_data *pdata;
|
||||
+
|
||||
+ pdata = pdev->dev.platform_data;
|
||||
+ if (!pdata) {
|
||||
+ dev_err(&pdev->dev, "no platform data specified\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (!pdata->clock) {
|
||||
+ dev_err(&pdev->dev, "invalid clock value\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ if (!res) {
|
||||
+ dev_err(&pdev->dev, "can't get device resources\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ res_size = resource_size(res);
|
||||
+ if (!request_mem_region(res->start, res_size, res->name)) {
|
||||
+ dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n",
|
||||
+ res_size, res->start);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ base = ioremap(res->start, res_size);
|
||||
+ if (!base) {
|
||||
+ dev_err(&pdev->dev, "ioremap failed\n");
|
||||
+ ret = -EIO;
|
||||
+ goto fail0;
|
||||
+ }
|
||||
+
|
||||
+ fa_wdt = kzalloc(sizeof(struct fa_wdt_struct), GFP_KERNEL);
|
||||
+ if (!fa_wdt) {
|
||||
+ dev_err(&pdev->dev, "can't allocate interface\n");
|
||||
+ ret = -ENOMEM;
|
||||
+ goto fail1;
|
||||
+ }
|
||||
+
|
||||
+ /* Setup fa_wdt driver structure */
|
||||
+ fa_wdt->base = base;
|
||||
+ fa_wdt->res = res;
|
||||
+ fa_wdt->dev = &pdev->dev;
|
||||
+ fa_wdt->clock = pdata->clock;
|
||||
+ fa_wdt->max_timeout = 0xffffffffU / pdata->clock;
|
||||
+
|
||||
+ /* Set up platform driver data */
|
||||
+ platform_set_drvdata(pdev, fa_wdt);
|
||||
+ fa_wdt_dev = pdev;
|
||||
+
|
||||
+ if (fa_wdt_miscdev.parent) {
|
||||
+ ret = -EBUSY;
|
||||
+ goto fail2;
|
||||
+ }
|
||||
+
|
||||
+ ret = register_reboot_notifier(&fa_wdt_notifier);
|
||||
+ if (ret)
|
||||
+ goto fail2;
|
||||
+
|
||||
+ fa_wdt_miscdev.parent = &pdev->dev;
|
||||
+
|
||||
+ ret = misc_register(&fa_wdt_miscdev);
|
||||
+ if (ret)
|
||||
+ goto fail3;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+fail3:
|
||||
+ unregister_reboot_notifier(&fa_wdt_notifier);
|
||||
+fail2:
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
+ kfree(fa_wdt);
|
||||
+fail1:
|
||||
+ iounmap(base);
|
||||
+fail0:
|
||||
+ release_mem_region(res->start, res_size);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int __devexit fa_wdt_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
+ misc_deregister(&fa_wdt_miscdev);
|
||||
+ unregister_reboot_notifier(&fa_wdt_notifier);
|
||||
+ fa_wdt_dev = NULL;
|
||||
+ iounmap(fa_wdt->base);
|
||||
+ release_mem_region(fa_wdt->res->start, resource_size(fa_wdt->res));
|
||||
+
|
||||
+ kfree(fa_wdt);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_PM
|
||||
+static int fa_wdt_suspend(struct platform_device *pdev, pm_message_t message)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = platform_get_drvdata(pdev);
|
||||
+ unsigned int reg;
|
||||
+
|
||||
+ reg = __raw_readw(fa_wdt->base + FA_WDCR);
|
||||
+ reg &= ~(WDCR_WDENABLE);
|
||||
+ __raw_writel(reg, fa_wdt->base + FA_WDCR);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int fa_wdt_resume(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = platform_get_drvdata(pdev);
|
||||
+ unsigned int reg;
|
||||
+
|
||||
+ if (fa_wdt->status) {
|
||||
+ reg = __raw_readw(fa_wdt->base + FA_WDCR);
|
||||
+ reg |= WDCR_WDENABLE;
|
||||
+ __raw_writel(reg, fa_wdt->base + FA_WDCR);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+#else
|
||||
+#define fa_wdt_suspend NULL
|
||||
+#define fa_wdt_resume NULL
|
||||
+#endif
|
||||
+
|
||||
+static struct platform_driver fa_wdt_driver = {
|
||||
+ .probe = fa_wdt_probe,
|
||||
+ .remove = __devexit_p(fa_wdt_remove),
|
||||
+ .shutdown = fa_wdt_shutdown,
|
||||
+ .suspend = fa_wdt_suspend,
|
||||
+ .resume = fa_wdt_resume,
|
||||
+ .driver = {
|
||||
+ .name = "fa-wdt",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init fa_wdt_init(void)
|
||||
+{
|
||||
+ return platform_driver_probe(&fa_wdt_driver, fa_wdt_probe);
|
||||
+}
|
||||
+
|
||||
+static void __exit fa_wdt_exit(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&fa_wdt_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(fa_wdt_init);
|
||||
+module_exit(fa_wdt_exit);
|
||||
+
|
||||
+module_param(timeout, uint, 0);
|
||||
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
|
||||
+
|
||||
+module_param(nowayout, int, 0);
|
||||
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
|
||||
+
|
||||
+MODULE_AUTHOR("Paulius Zaleckas");
|
||||
+MODULE_DESCRIPTION("Watchdog driver for Faraday FA526 based SoCs");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
|
||||
+MODULE_ALIAS("platform:fa-wdt");
|
||||
--- /dev/null
|
||||
+++ b/include/linux/fa_wdt.h
|
||||
@@ -0,0 +1,13 @@
|
||||
+/*
|
||||
+ * Platform data definition for the Faraday watchdog driver
|
||||
+ */
|
||||
+
|
||||
+#ifndef _FA_WDT_H
|
||||
+#define _FA_WDT_H
|
||||
+
|
||||
+struct fa_wdt_platform_data {
|
||||
+ unsigned int clock;
|
||||
+};
|
||||
+
|
||||
+#endif /* _FA_WDT_H */
|
||||
+
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,103 @@
|
|||
--- a/arch/arm/mach-cns21xx/common.h
|
||||
+++ b/arch/arm/mach-cns21xx/common.h
|
||||
@@ -15,4 +15,7 @@ void __init cns21xx_init_irq(void);
|
||||
|
||||
extern struct sys_timer cns21xx_timer;
|
||||
|
||||
+int __init cns21xx_register_uart0(void);
|
||||
+int __init cns21xx_register_uart1(void);
|
||||
+
|
||||
#endif /* _MACH_CNS21XX_COMMON_H */
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/devices.c
|
||||
@@ -0,0 +1,79 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2008 Cavium Networks
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/serial_8250.h>
|
||||
+
|
||||
+#include <mach/irqs.h>
|
||||
+#include <mach/hardware.h>
|
||||
+#include <mach/cns21xx.h>
|
||||
+#include <mach/cns21xx_misc.h>
|
||||
+
|
||||
+#define CNS21XX_UART_CLOCK 24000000
|
||||
+
|
||||
+#define CNS21XX_UART_FLAGS (UPF_SKIP_TEST | UPF_FIXED_TYPE | UPF_NO_TXEN_TEST)
|
||||
+
|
||||
+static struct plat_serial8250_port cns21xx_uart0_data[] = {
|
||||
+ {
|
||||
+ .mapbase = CNS21XX_UART0_BASE,
|
||||
+ .membase = (void *) CNS21XX_UART0_BASE_VIRT,
|
||||
+ .irq = CNS21XX_IRQ_UART0,
|
||||
+ .uartclk = CNS21XX_UART_CLOCK,
|
||||
+ .regshift = 2,
|
||||
+ .iotype = UPIO_MEM,
|
||||
+ .type = PORT_16550A,
|
||||
+ .flags = CNS21XX_UART_FLAGS,
|
||||
+ }, {
|
||||
+ /* terminating entry */
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device cns21xx_uart0_device = {
|
||||
+ .name = "serial8250",
|
||||
+ .id = PLAT8250_DEV_PLATFORM,
|
||||
+ .dev = {
|
||||
+ .platform_data = cns21xx_uart0_data,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+int __init cns21xx_register_uart0(void)
|
||||
+{
|
||||
+ return platform_device_register(&cns21xx_uart0_device);
|
||||
+}
|
||||
+
|
||||
+static struct plat_serial8250_port cns21xx_uart1_data[] = {
|
||||
+ {
|
||||
+ .mapbase = CNS21XX_UART1_BASE,
|
||||
+ .membase = (void *) CNS21XX_UART1_BASE_VIRT,
|
||||
+ .irq = CNS21XX_IRQ_UART1,
|
||||
+ .uartclk = CNS21XX_UART_CLOCK,
|
||||
+ .regshift = 2,
|
||||
+ .iotype = UPIO_MEM,
|
||||
+ .type = PORT_16550A,
|
||||
+ .flags = CNS21XX_UART_FLAGS,
|
||||
+ }, {
|
||||
+ /* terminating entry */
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device cns21xx_uart1_device = {
|
||||
+ .name = "serial8250",
|
||||
+ .id = PLAT8250_DEV_PLATFORM1,
|
||||
+ .dev = {
|
||||
+ .platform_data = cns21xx_uart1_data,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+int __init cns21xx_register_uart1(void)
|
||||
+{
|
||||
+ HAL_MISC_ENABLE_UART1_PINS();
|
||||
+ return platform_device_register(&cns21xx_uart1_device);
|
||||
+}
|
||||
--- a/arch/arm/mach-cns21xx/Makefile
|
||||
+++ b/arch/arm/mach-cns21xx/Makefile
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
# Object file lists.
|
||||
|
||||
-obj-y := core.o irq.o mm.o time.o
|
||||
+obj-y := core.o devices.o irq.o mm.o time.o
|
||||
|
||||
# machine specific files
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -296,6 +296,8 @@ config ARCH_CNS21XX
|
||||
select CPU_FA526
|
||||
select PLAT_FA
|
||||
select PLAT_FA_TIME
|
||||
+ select PLAT_FA_GPIO
|
||||
+ select ARCH_REQUIRE_GPIOLIB
|
||||
select ARM_L1_CACHE_SHIFT_4
|
||||
help
|
||||
Support for Cavium Networks CNS21xx family.
|
||||
--- a/arch/arm/mach-cns21xx/common.h
|
||||
+++ b/arch/arm/mach-cns21xx/common.h
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
void __init cns21xx_map_io(void);
|
||||
void __init cns21xx_init_irq(void);
|
||||
+void __init cns21xx_gpio_init(void);
|
||||
|
||||
extern struct sys_timer cns21xx_timer;
|
||||
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/gpio.c
|
||||
@@ -0,0 +1,45 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <plat/gpio.h>
|
||||
+
|
||||
+#include <mach/cns21xx.h>
|
||||
+#include <mach/irqs.h>
|
||||
+
|
||||
+static struct fa_gpio_chip cns21xx_gpio_chips[] = {
|
||||
+ {
|
||||
+ .gpio_chip = {
|
||||
+ .label = "GPIOA",
|
||||
+ .base = 0,
|
||||
+ .ngpio = 32,
|
||||
+ },
|
||||
+
|
||||
+ .map_base = CNS21XX_GPIOA_BASE,
|
||||
+ .irq_base = CNS21XX_GPIO_IRQ_BASE,
|
||||
+ }, {
|
||||
+ .gpio_chip = {
|
||||
+ .label = "GPIOB",
|
||||
+ .base = 32,
|
||||
+ .ngpio = 32,
|
||||
+ },
|
||||
+
|
||||
+ .map_base = CNS21XX_GPIOB_BASE,
|
||||
+ .irq_base = CNS21XX_GPIO_IRQ_BASE + 32,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct fa_gpio_data cns21xx_gpio_data = {
|
||||
+ .chips = cns21xx_gpio_chips,
|
||||
+ .nchips = ARRAY_SIZE(cns21xx_gpio_chips),
|
||||
+ .irq = CNS21XX_IRQ_GPIO,
|
||||
+};
|
||||
+
|
||||
+void __init cns21xx_gpio_init(void)
|
||||
+{
|
||||
+ fa_gpio_init(&cns21xx_gpio_data);
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/include/mach/gpio.h
|
||||
@@ -0,0 +1,30 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2008 Cavium Networks
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file 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 _CNS21XX_GPIO_H
|
||||
+#define _CNS21XX_GPIO_H
|
||||
+
|
||||
+#include <asm-generic/gpio.h>
|
||||
+#include <mach/irqs.h>
|
||||
+
|
||||
+#define gpio_get_value __gpio_get_value
|
||||
+#define gpio_set_value __gpio_set_value
|
||||
+#define gpio_cansleep __gpio_cansleep
|
||||
+
|
||||
+static inline int gpio_to_irq(unsigned gpio)
|
||||
+{
|
||||
+ return (CNS21XX_GPIO_IRQ_BASE + gpio);
|
||||
+}
|
||||
+
|
||||
+static inline int irq_to_gpio(int irq)
|
||||
+{
|
||||
+ return (irq - CNS21XX_GPIO_IRQ_BASE);
|
||||
+}
|
||||
+
|
||||
+#endif /* _CNS21XX_GPIO_H */
|
||||
--- a/arch/arm/mach-cns21xx/Makefile
|
||||
+++ b/arch/arm/mach-cns21xx/Makefile
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
# Object file lists.
|
||||
|
||||
-obj-y := core.o devices.o irq.o mm.o time.o
|
||||
+obj-y := core.o devices.o gpio.o irq.o mm.o time.o
|
||||
|
||||
# machine specific files
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
--- a/drivers/usb/host/ohci-hcd.c
|
||||
+++ b/drivers/usb/host/ohci-hcd.c
|
||||
@@ -583,7 +583,6 @@ static int ohci_run (struct ohci_hcd *oh
|
||||
|
||||
/* boot firmware should have set this up (5.1.1.3.1) */
|
||||
if (first) {
|
||||
-
|
||||
val = ohci_readl (ohci, &ohci->regs->fminterval);
|
||||
ohci->fminterval = val & 0x3fff;
|
||||
if (ohci->fminterval != FI)
|
||||
@@ -667,6 +666,9 @@ retry:
|
||||
|
||||
periodic_reinit (ohci);
|
||||
|
||||
+ if (ohci->flags & OHCI_QUIRK_INIT_FMINTERVAL)
|
||||
+ ohci_writel (ohci, ohci->fminterval, &ohci->regs->fminterval);
|
||||
+
|
||||
/* some OHCI implementations are finicky about how they init.
|
||||
* bogus values here mean not even enumeration could work.
|
||||
*/
|
||||
@@ -1061,6 +1063,11 @@ MODULE_LICENSE ("GPL");
|
||||
#define PLATFORM_DRIVER ohci_hcd_da8xx_driver
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_ARCH_CNS21XX
|
||||
+#include "ohci-cns21xx.c"
|
||||
+#define PLATFORM_DRIVER ohci_cns21xx_driver
|
||||
+#endif
|
||||
+
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7721) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7763) || \
|
||||
--- /dev/null
|
||||
+++ b/drivers/usb/host/ohci-cns21xx.c
|
||||
@@ -0,0 +1,175 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2008 Cavium Networks
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include <mach/cns21xx.h>
|
||||
+
|
||||
+#define DRIVER_NAME "cns21xx-ohci"
|
||||
+
|
||||
+static int __devinit cns21xx_ohci_start(struct usb_hcd *hcd)
|
||||
+{
|
||||
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ohci_init(ohci);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = ohci_run(ohci);
|
||||
+ if (ret) {
|
||||
+ err("can't start %s", ohci_to_hcd(ohci)->self.bus_name);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err:
|
||||
+ ohci_stop(hcd);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static const struct hc_driver ohci_cns21xx_hc_driver = {
|
||||
+ .description = hcd_name,
|
||||
+ .product_desc = "cns21xx-ohci",
|
||||
+ .hcd_priv_size = sizeof(struct ohci_hcd),
|
||||
+
|
||||
+ /*
|
||||
+ * generic hardware linkage
|
||||
+ */
|
||||
+ .irq = ohci_irq,
|
||||
+ .flags = HCD_USB11 | HCD_MEMORY,
|
||||
+
|
||||
+ /*
|
||||
+ * basic lifecycle operations
|
||||
+ */
|
||||
+ .start = cns21xx_ohci_start,
|
||||
+ .stop = ohci_stop,
|
||||
+ .shutdown = ohci_shutdown,
|
||||
+
|
||||
+ /*
|
||||
+ * managing i/o requests and associated device resources
|
||||
+ */
|
||||
+ .urb_enqueue = ohci_urb_enqueue,
|
||||
+ .urb_dequeue = ohci_urb_dequeue,
|
||||
+ .endpoint_disable = ohci_endpoint_disable,
|
||||
+
|
||||
+ /*
|
||||
+ * scheduling support
|
||||
+ */
|
||||
+ .get_frame_number = ohci_get_frame,
|
||||
+
|
||||
+ /*
|
||||
+ * root hub support
|
||||
+ */
|
||||
+ .hub_status_data = ohci_hub_status_data,
|
||||
+ .hub_control = ohci_hub_control,
|
||||
+ .start_port_reset = ohci_start_port_reset,
|
||||
+};
|
||||
+
|
||||
+static void cns21xx_ohci_init_hc(void)
|
||||
+{
|
||||
+ __raw_writel(0x146, CNS21XX_OHCI_CONFIG_BASE_VIRT + 0x04);
|
||||
+ __raw_writel(0x200, CNS21XX_OHCI_CONFIG_BASE_VIRT + 0x44);
|
||||
+ msleep(100);
|
||||
+}
|
||||
+
|
||||
+static int ohci_cns21xx_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct usb_hcd *hcd;
|
||||
+ struct resource *res;
|
||||
+ struct ohci_hcd *ohci;
|
||||
+ int irq;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (usb_disabled())
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
+ if (!res) {
|
||||
+ dev_dbg(&pdev->dev, "no IRQ specified for %s\n",
|
||||
+ dev_name(&pdev->dev));
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ irq = res->start;
|
||||
+
|
||||
+ hcd = usb_create_hcd(&ohci_cns21xx_hc_driver, &pdev->dev,
|
||||
+ dev_name(&pdev->dev));
|
||||
+ if (!hcd)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ if (!res) {
|
||||
+ dev_dbg(&pdev->dev, "no base address specified for %s\n",
|
||||
+ dev_name(&pdev->dev));
|
||||
+ ret = -ENODEV;
|
||||
+ goto err_put_hcd;
|
||||
+ }
|
||||
+ hcd->rsrc_start = res->start;
|
||||
+ hcd->rsrc_len = res->end - res->start + 1;
|
||||
+
|
||||
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
|
||||
+ dev_dbg(&pdev->dev, "controller already in use\n");
|
||||
+ ret = -EBUSY;
|
||||
+ goto err_put_hcd;
|
||||
+ }
|
||||
+
|
||||
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
|
||||
+ if (!hcd->regs) {
|
||||
+ dev_dbg(&pdev->dev, "error mapping memory\n");
|
||||
+ ret = -EFAULT;
|
||||
+ goto err_release_region;
|
||||
+ }
|
||||
+
|
||||
+ cns21xx_ohci_init_hc();
|
||||
+
|
||||
+ ohci = hcd_to_ohci(hcd);
|
||||
+ ohci->flags |= OHCI_QUIRK_INIT_FMINTERVAL;
|
||||
+ ohci_hcd_init(ohci);
|
||||
+
|
||||
+ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
|
||||
+ if (ret)
|
||||
+ goto err_unmap;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, hcd);
|
||||
+ return 0;
|
||||
+
|
||||
+err_unmap:
|
||||
+ iounmap(hcd->regs);
|
||||
+err_release_region:
|
||||
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
+err_put_hcd:
|
||||
+ usb_put_hcd(hcd);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int ohci_cns21xx_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ usb_remove_hcd(hcd);
|
||||
+ iounmap(hcd->regs);
|
||||
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
+ usb_put_hcd(hcd);
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver ohci_cns21xx_driver = {
|
||||
+ .probe = ohci_cns21xx_probe,
|
||||
+ .remove = ohci_cns21xx_remove,
|
||||
+ .shutdown = usb_hcd_platform_shutdown,
|
||||
+ .driver = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .name = DRIVER_NAME,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
--- a/drivers/usb/host/ohci.h
|
||||
+++ b/drivers/usb/host/ohci.h
|
||||
@@ -403,6 +403,7 @@ struct ohci_hcd {
|
||||
#define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */
|
||||
#define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/
|
||||
#define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */
|
||||
+#define OHCI_QUIRK_INIT_FMINTERVAL 0x800 /* fminterval must be initialized */
|
||||
// there are also chip quirks/bugs in init logic
|
||||
|
||||
struct work_struct nec_work; /* Worker for NEC quirk */
|
||||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -299,6 +299,7 @@ config ARCH_CNS21XX
|
||||
select PLAT_FA_GPIO
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARM_L1_CACHE_SHIFT_4
|
||||
+ select USB_ARCH_HAS_OHCI
|
||||
help
|
||||
Support for Cavium Networks CNS21xx family.
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
--- /dev/null
|
||||
+++ b/drivers/usb/host/ehci-cns21xx.c
|
||||
@@ -0,0 +1,184 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2008 Cavium Networks
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/irq.h>
|
||||
+
|
||||
+#include <mach/cns21xx.h>
|
||||
+
|
||||
+#define DRIVER_NAME "cns21xx-ehci"
|
||||
+
|
||||
+static int cns21xx_ehci_reset(struct usb_hcd *hcd)
|
||||
+{
|
||||
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ehci_halt(ehci);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = ehci_init(hcd);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ehci_reset(ehci);
|
||||
+ ehci_port_power(ehci, 0);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct hc_driver ehci_cns21xx_hc_driver = {
|
||||
+ .description = hcd_name,
|
||||
+ .product_desc = DRIVER_NAME,
|
||||
+ .hcd_priv_size = sizeof(struct ehci_hcd),
|
||||
+
|
||||
+ /*
|
||||
+ * generic hardware linkage
|
||||
+ */
|
||||
+ .irq = ehci_irq,
|
||||
+ .flags = HCD_MEMORY | HCD_USB2,
|
||||
+
|
||||
+ /*
|
||||
+ * basic lifecycle operations
|
||||
+ */
|
||||
+ .reset = cns21xx_ehci_reset,
|
||||
+ .start = ehci_run,
|
||||
+ .stop = ehci_stop,
|
||||
+ .shutdown = ehci_shutdown,
|
||||
+
|
||||
+ /*
|
||||
+ * managing i/o requests and associated device resources
|
||||
+ */
|
||||
+ .urb_enqueue = ehci_urb_enqueue,
|
||||
+ .urb_dequeue = ehci_urb_dequeue,
|
||||
+ .endpoint_disable = ehci_endpoint_disable,
|
||||
+ .endpoint_reset = ehci_endpoint_reset,
|
||||
+
|
||||
+ /*
|
||||
+ * scheduling support
|
||||
+ */
|
||||
+ .get_frame_number = ehci_get_frame,
|
||||
+
|
||||
+ /*
|
||||
+ * root hub support
|
||||
+ */
|
||||
+ .hub_status_data = ehci_hub_status_data,
|
||||
+ .hub_control = ehci_hub_control,
|
||||
+ .relinquish_port = ehci_relinquish_port,
|
||||
+ .port_handed_over = ehci_port_handed_over,
|
||||
+
|
||||
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
|
||||
+};
|
||||
+
|
||||
+static void cns21xx_ehci_init_hc(void)
|
||||
+{
|
||||
+ __raw_writel(0x106, CNS21XX_EHCI_CONFIG_BASE_VIRT + 0x04);
|
||||
+ __raw_writel((3 << 5) | 0x2000, CNS21XX_EHCI_CONFIG_BASE_VIRT + 0x40);
|
||||
+ msleep(100);
|
||||
+}
|
||||
+
|
||||
+static int ehci_cns21xx_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct usb_hcd *hcd;
|
||||
+ struct ehci_hcd *ehci;
|
||||
+ struct resource *res;
|
||||
+ int irq;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (usb_disabled())
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
+ if (!res) {
|
||||
+ dev_dbg(&pdev->dev, "no IRQ specified for %s\n",
|
||||
+ dev_name(&pdev->dev));
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ irq = res->start;
|
||||
+
|
||||
+ hcd = usb_create_hcd(&ehci_cns21xx_hc_driver, &pdev->dev,
|
||||
+ dev_name(&pdev->dev));
|
||||
+ if (!hcd)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ if (!res) {
|
||||
+ dev_dbg(&pdev->dev, "no base address specified for %s\n",
|
||||
+ dev_name(&pdev->dev));
|
||||
+ ret = -ENODEV;
|
||||
+ goto err_put_hcd;
|
||||
+ }
|
||||
+ hcd->rsrc_start = res->start;
|
||||
+ hcd->rsrc_len = res->end - res->start + 1;
|
||||
+
|
||||
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
|
||||
+ dev_dbg(&pdev->dev, "controller already in use\n");
|
||||
+ ret = -EBUSY;
|
||||
+ goto err_put_hcd;
|
||||
+ }
|
||||
+
|
||||
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
|
||||
+ if (!hcd->regs) {
|
||||
+ dev_dbg(&pdev->dev, "error mapping memory\n");
|
||||
+ ret = -EFAULT;
|
||||
+ goto err_release_region;
|
||||
+ }
|
||||
+
|
||||
+ cns21xx_ehci_init_hc();
|
||||
+
|
||||
+ ehci = hcd_to_ehci(hcd);
|
||||
+
|
||||
+ ehci->caps = hcd->regs;
|
||||
+ ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
|
||||
+ dbg_hcs_params(ehci, "reset");
|
||||
+ dbg_hcc_params(ehci, "reset");
|
||||
+
|
||||
+ /* cache this readonly data; minimize chip reads */
|
||||
+ ehci->hcs_params = readl(&ehci->caps->hcs_params);
|
||||
+ ehci->sbrn = 0x20;
|
||||
+
|
||||
+ ret = usb_add_hcd(hcd, CNS21XX_IRQ_EHCI, IRQF_DISABLED);
|
||||
+ if (ret)
|
||||
+ goto err_unmap;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, hcd);
|
||||
+ return 0;
|
||||
+
|
||||
+err_unmap:
|
||||
+ iounmap(hcd->regs);
|
||||
+err_release_region:
|
||||
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
+err_put_hcd:
|
||||
+ usb_put_hcd(hcd);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int ehci_cns21xx_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ usb_remove_hcd(hcd);
|
||||
+ iounmap(hcd->regs);
|
||||
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
+ usb_put_hcd(hcd);
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver ehci_cns21xx_driver = {
|
||||
+ .probe = ehci_cns21xx_probe,
|
||||
+ .remove = ehci_cns21xx_remove,
|
||||
+ .driver = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .name = DRIVER_NAME,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
--- a/drivers/usb/host/ehci-hcd.c
|
||||
+++ b/drivers/usb/host/ehci-hcd.c
|
||||
@@ -1197,6 +1197,11 @@ MODULE_LICENSE ("GPL");
|
||||
#define PLATFORM_DRIVER ehci_atmel_driver
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_ARCH_CNS21XX
|
||||
+#include "ehci-cns21xx.c"
|
||||
+#define PLATFORM_DRIVER ehci_cns21xx_driver
|
||||
+#endif
|
||||
+
|
||||
#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
|
||||
!defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
|
||||
!defined(XILINX_OF_PLATFORM_DRIVER)
|
||||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -300,6 +300,7 @@ config ARCH_CNS21XX
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARM_L1_CACHE_SHIFT_4
|
||||
select USB_ARCH_HAS_OHCI
|
||||
+ select USB_ARCH_HAS_EHCI
|
||||
help
|
||||
Support for Cavium Networks CNS21xx family.
|
||||
|
|
@ -0,0 +1,577 @@
|
|||
--- a/include/linux/spi/spi.h
|
||||
+++ b/include/linux/spi/spi.h
|
||||
@@ -442,6 +442,8 @@ struct spi_transfer {
|
||||
u16 delay_usecs;
|
||||
u32 speed_hz;
|
||||
|
||||
+ unsigned last_in_message_list;
|
||||
+
|
||||
struct list_head transfer_list;
|
||||
};
|
||||
|
||||
--- a/drivers/spi/Kconfig
|
||||
+++ b/drivers/spi/Kconfig
|
||||
@@ -152,6 +152,14 @@ config SPI_GPIO_OLD
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
+config SPI_CNS21XX
|
||||
+ tristate "Cavium Netowrks CNS21xx SPI master"
|
||||
+ depends on ARCH_CNS21XX && EXPERIMENTAL
|
||||
+ select SPI_BITBANG
|
||||
+ help
|
||||
+ This driver supports the buil-in SPI controller of the Cavium Networks
|
||||
+ CNS21xx SoCs.
|
||||
+
|
||||
config SPI_IMX
|
||||
tristate "Freescale i.MX SPI controllers"
|
||||
depends on ARCH_MXC
|
||||
--- a/drivers/spi/Makefile
|
||||
+++ b/drivers/spi/Makefile
|
||||
@@ -48,6 +48,7 @@ obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.
|
||||
obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o
|
||||
obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
|
||||
obj-$(CONFIG_SPI_NUC900) += spi_nuc900.o
|
||||
+obj-$(CONFIG_SPI_CNS21XX) += spi_cns21xx.o
|
||||
|
||||
# special build for s3c24xx spi driver with fiq support
|
||||
spi_s3c24xx_hw-y := spi_s3c24xx.o
|
||||
--- a/drivers/spi/spi_bitbang.c
|
||||
+++ b/drivers/spi/spi_bitbang.c
|
||||
@@ -337,6 +337,13 @@ static void bitbang_work(struct work_str
|
||||
*/
|
||||
if (!m->is_dma_mapped)
|
||||
t->rx_dma = t->tx_dma = 0;
|
||||
+
|
||||
+ if (t->transfer_list.next == &m->transfers) {
|
||||
+ t->last_in_message_list = 1;
|
||||
+ } else {
|
||||
+ t->last_in_message_list = 0;
|
||||
+ }
|
||||
+
|
||||
status = bitbang->txrx_bufs(spi, t);
|
||||
}
|
||||
if (status > 0)
|
||||
--- /dev/null
|
||||
+++ b/drivers/spi/spi_cns21xx.c
|
||||
@@ -0,0 +1,520 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2008 Cavium Networks
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/workqueue.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+#include <linux/spi/spi_bitbang.h>
|
||||
+
|
||||
+#include <mach/hardware.h>
|
||||
+#include <mach/cns21xx.h>
|
||||
+
|
||||
+#define DRIVER_NAME "cns21xx-spi"
|
||||
+
|
||||
+#ifdef CONFIG_CNS21XX_SPI_DEBUG
|
||||
+#define DBG(fmt, args...) pr_info("[CNS21XX_SPI_DEBUG]" fmt, ## args)
|
||||
+#else
|
||||
+#define DBG(fmt, args...) do {} while (0)
|
||||
+#endif /* CNS21XX_SPI_DEBUG */
|
||||
+
|
||||
+#define SPI_REG_CFG 0x40
|
||||
+#define SPI_REG_STAT 0x44
|
||||
+#define SPI_REG_BIT_RATE 0x48
|
||||
+#define SPI_REG_TX_CTRL 0x4c
|
||||
+#define SPI_REG_TX_DATA 0x50
|
||||
+#define SPI_REG_RX_CTRL 0x54
|
||||
+#define SPI_REG_RX_DATA 0x58
|
||||
+#define SPI_REG_FIFO_TX_CFG 0x5c
|
||||
+#define SPI_REG_FIFO_TX_CTRL 0x60
|
||||
+#define SPI_REG_FIFO_RX_CFG 0x64
|
||||
+#define SPI_REG_INTR_STAT 0x68
|
||||
+#define SPI_REG_INTR_ENA 0x6c
|
||||
+
|
||||
+#define CFG_SPI_EN BIT(31)
|
||||
+#define CFG_SPI_CLKPOL BIT(14)
|
||||
+#define CFG_SPI_CLKPHA BIT(13)
|
||||
+#define CFG_SPI_MASTER_EN BIT(11)
|
||||
+#define CFG_SPI_CHAR_LEN_M 0x3
|
||||
+#define CFG_SPI_CHAR_LEN_8BITS 0
|
||||
+#define CFG_SPI_CHAR_LEN_16BITS 1
|
||||
+#define CFG_SPI_CHAR_LEN_24BITS 2
|
||||
+#define CFG_SPI_CHAR_LEN_32BITS 3
|
||||
+
|
||||
+#define STAT_SPI_BUSY_STA BIT(1)
|
||||
+
|
||||
+#define BIT_RATE_DIV_1 0
|
||||
+#define BIT_RATE_DIV_2 1
|
||||
+#define BIT_RATE_DIV_4 2
|
||||
+#define BIT_RATE_DIV_8 3
|
||||
+#define BIT_RATE_DIV_16 4
|
||||
+#define BIT_RATE_DIV_32 5
|
||||
+#define BIT_RATE_DIV_64 6
|
||||
+#define BIT_RATE_DIV_128 7
|
||||
+
|
||||
+#define TX_CTRL_SPI_TXDAT_EOF BIT(2)
|
||||
+#define TX_CTRL_SPI_TXCH_NUM_M 0x3
|
||||
+#define TX_CTRL_CLEAR_MASK (TX_CTRL_SPI_TXDAT_EOF | \
|
||||
+ TX_CTRL_SPI_TXCH_NUM_M)
|
||||
+
|
||||
+#define RX_CTRL_SPI_RXDAT_EOF BIT(2)
|
||||
+#define RX_CTRL_SPI_RXCH_NUM_M 0x3
|
||||
+
|
||||
+#define INTR_STAT_SPI_TXBF_UNRN_FG BIT(7)
|
||||
+#define INTR_STAT_SPI_RXBF_OVRN_FG BIT(6)
|
||||
+#define INTR_STAT_SPI_TXFF_UNRN_FG BIT(5)
|
||||
+#define INTR_STAT_SPI_RXFF_OVRN_FG BIT(4)
|
||||
+#define INTR_STAT_SPI_TXBUF_FG BIT(3)
|
||||
+#define INTR_STAT_SPI_RXBUF_FG BIT(2)
|
||||
+#define INTR_STAT_SPI_TXFF_FG BIT(1)
|
||||
+#define INTR_STAT_SPI_RXFF_FG BIT(0)
|
||||
+
|
||||
+#define INTR_STAT_CLEAR_MASK (INTR_STAT_SPI_TXBF_UNRN_FG | \
|
||||
+ INTR_STAT_SPI_RXBF_OVRN_FG | \
|
||||
+ INTR_STAT_SPI_TXFF_UNRN_FG | \
|
||||
+ INTR_STAT_SPI_RXFF_OVRN_FG)
|
||||
+
|
||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_M 0x3
|
||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_S 4
|
||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_2 0
|
||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_4 1
|
||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_6 0
|
||||
+#define FIFO_TX_CFG_SPI_TXFF_STATUS_M 0xf
|
||||
+
|
||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_M 0x3
|
||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_S 4
|
||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_2 0
|
||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_4 1
|
||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_6 0
|
||||
+#define FIFO_RX_CFG_SPI_RXFF_STATUS_M 0xf
|
||||
+
|
||||
+#define CNS21XX_SPI_NUM_BIT_RATES 8
|
||||
+
|
||||
+struct cns21xx_spi {
|
||||
+ struct spi_bitbang bitbang;
|
||||
+
|
||||
+ struct spi_master *master;
|
||||
+ struct device *dev;
|
||||
+ void __iomem *base;
|
||||
+ struct resource *region;
|
||||
+
|
||||
+ unsigned freq_max;
|
||||
+ unsigned freq_min;
|
||||
+
|
||||
+};
|
||||
+
|
||||
+static inline struct cns21xx_spi *to_hw(struct spi_device *spi)
|
||||
+{
|
||||
+ return spi_master_get_devdata(spi->master);
|
||||
+}
|
||||
+
|
||||
+static inline u32 cns21xx_spi_rr(struct cns21xx_spi *hw, unsigned int reg)
|
||||
+{
|
||||
+ return __raw_readl(hw->base + reg);
|
||||
+}
|
||||
+
|
||||
+static inline void cns21xx_spi_wr(struct cns21xx_spi *hw, u32 val,
|
||||
+ unsigned int reg)
|
||||
+{
|
||||
+ __raw_writel(val, hw->base + reg);
|
||||
+}
|
||||
+
|
||||
+#define CNS21XX_SPI_RETRY_COUNT 100
|
||||
+static inline int cns21xx_spi_wait(struct cns21xx_spi *hw, unsigned int reg,
|
||||
+ u32 mask, u32 val)
|
||||
+{
|
||||
+ int retry_cnt = 0;
|
||||
+
|
||||
+ do {
|
||||
+ if ((cns21xx_spi_rr(hw, reg) & mask) == val)
|
||||
+ break;
|
||||
+
|
||||
+ if (++retry_cnt > CNS21XX_SPI_RETRY_COUNT) {
|
||||
+ dev_err(hw->dev, "timeout waiting on register %02x\n",
|
||||
+ reg);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ } while (1);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cns21xx_spi_txrx_word(struct cns21xx_spi *hw, u8 tx_channel,
|
||||
+ u8 tx_eof_flag, u32 tx_data, u32 *rx_data)
|
||||
+{
|
||||
+ unsigned int tx_ctrl;
|
||||
+ u8 rx_channel;
|
||||
+ u8 rx_eof_flag;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ err = cns21xx_spi_wait(hw, SPI_REG_STAT, STAT_SPI_BUSY_STA, 0);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = cns21xx_spi_wait(hw, SPI_REG_INTR_STAT, INTR_STAT_SPI_TXBUF_FG,
|
||||
+ INTR_STAT_SPI_TXBUF_FG);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ tx_ctrl = cns21xx_spi_rr(hw, SPI_REG_TX_CTRL);
|
||||
+ tx_ctrl &= ~(TX_CTRL_CLEAR_MASK);
|
||||
+ tx_ctrl |= (tx_channel & TX_CTRL_SPI_TXCH_NUM_M);
|
||||
+ tx_ctrl |= (tx_eof_flag) ? TX_CTRL_SPI_TXDAT_EOF : 0;
|
||||
+ cns21xx_spi_wr(hw, tx_ctrl, SPI_REG_TX_CTRL);
|
||||
+
|
||||
+ cns21xx_spi_wr(hw, tx_data, SPI_REG_TX_DATA);
|
||||
+
|
||||
+ err = cns21xx_spi_wait(hw, SPI_REG_INTR_STAT, INTR_STAT_SPI_RXBUF_FG,
|
||||
+ INTR_STAT_SPI_RXBUF_FG);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ rx_channel = cns21xx_spi_rr(hw, SPI_REG_RX_CTRL) &
|
||||
+ RX_CTRL_SPI_RXCH_NUM_M;
|
||||
+
|
||||
+ rx_eof_flag = (cns21xx_spi_rr(hw, SPI_REG_RX_CTRL) &
|
||||
+ RX_CTRL_SPI_RXDAT_EOF) ? 1 : 0;
|
||||
+
|
||||
+ *rx_data = cns21xx_spi_rr(hw, SPI_REG_RX_DATA);
|
||||
+
|
||||
+ if ((tx_channel != rx_channel) || (tx_eof_flag != rx_eof_flag))
|
||||
+ return -EPROTO;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void cns21xx_spi_chipselect(struct spi_device *spi, int value)
|
||||
+{
|
||||
+ struct cns21xx_spi *hw = to_hw(spi);
|
||||
+ unsigned int spi_config;
|
||||
+ unsigned int tx_ctrl;
|
||||
+
|
||||
+ switch (value) {
|
||||
+ case BITBANG_CS_INACTIVE:
|
||||
+ break;
|
||||
+
|
||||
+ case BITBANG_CS_ACTIVE:
|
||||
+ spi_config = cns21xx_spi_rr(hw, SPI_REG_CFG);
|
||||
+
|
||||
+ if (spi->mode & SPI_CPHA)
|
||||
+ spi_config |= CFG_SPI_CLKPHA;
|
||||
+ else
|
||||
+ spi_config &= ~CFG_SPI_CLKPHA;
|
||||
+
|
||||
+ if (spi->mode & SPI_CPOL)
|
||||
+ spi_config |= CFG_SPI_CLKPOL;
|
||||
+ else
|
||||
+ spi_config &= ~CFG_SPI_CLKPOL;
|
||||
+
|
||||
+ cns21xx_spi_wr(hw, spi_config, SPI_REG_CFG);
|
||||
+
|
||||
+ tx_ctrl = cns21xx_spi_rr(hw, SPI_REG_TX_CTRL);
|
||||
+ tx_ctrl &= ~(TX_CTRL_CLEAR_MASK);
|
||||
+ tx_ctrl |= (spi->chip_select & TX_CTRL_SPI_TXCH_NUM_M);
|
||||
+ cns21xx_spi_wr(hw, tx_ctrl, SPI_REG_TX_CTRL);
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int cns21xx_spi_setup(struct spi_device *spi)
|
||||
+{
|
||||
+ struct cns21xx_spi *hw = to_hw(spi);
|
||||
+
|
||||
+ if (spi->bits_per_word != 8) {
|
||||
+ dev_err(&spi->dev, "%s: invalid bits_per_word=%u\n",
|
||||
+ __func__, spi->bits_per_word);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (spi->max_speed_hz == 0)
|
||||
+ spi->max_speed_hz = hw->freq_max;
|
||||
+
|
||||
+ if (spi->max_speed_hz > hw->freq_max ||
|
||||
+ spi->max_speed_hz < hw->freq_min) {
|
||||
+ dev_err(&spi->dev, "%s: max_speed_hz=%u out of range\n",
|
||||
+ __func__, spi->max_speed_hz);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cns21xx_spi_setup_transfer(struct spi_device *spi,
|
||||
+ struct spi_transfer *t)
|
||||
+{
|
||||
+ struct cns21xx_spi *hw = to_hw(spi);
|
||||
+ u8 bits_per_word;
|
||||
+ u32 hz;
|
||||
+ int i;
|
||||
+
|
||||
+ bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
|
||||
+ hz = t ? t->speed_hz : spi->max_speed_hz;
|
||||
+
|
||||
+ if (!bits_per_word)
|
||||
+ bits_per_word = spi->bits_per_word;
|
||||
+
|
||||
+ if (!hz)
|
||||
+ hz = spi->max_speed_hz;
|
||||
+
|
||||
+ if (bits_per_word != 8) {
|
||||
+ dev_err(&spi->dev, "%s: invalid bits_per_word=%u\n",
|
||||
+ __func__, bits_per_word);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (hz > spi->max_speed_hz || hz > hw->freq_max || hz < hw->freq_min) {
|
||||
+ dev_err(&spi->dev, "%s: max_speed_hz=%u out of range\n",
|
||||
+ __func__, hz);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < CNS21XX_SPI_NUM_BIT_RATES; i++)
|
||||
+ if (spi->max_speed_hz > (cns21xx_get_apb_freq() >> i))
|
||||
+ break;
|
||||
+
|
||||
+ DBG("max_speed:%uHz, curr_speed:%luHz, rate_index=%d\n",
|
||||
+ spi->max_speed_hz, cns21xx_get_apb_freq() / (1 << i), i);
|
||||
+
|
||||
+ cns21xx_spi_wr(hw, i, SPI_REG_BIT_RATE);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cns21xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
|
||||
+{
|
||||
+ struct cns21xx_spi *hw = to_hw(spi);
|
||||
+ const unsigned char *tx_buf;
|
||||
+ unsigned char *rx_buf;
|
||||
+ u32 rx_data;
|
||||
+ int tx_eof;
|
||||
+ int err = 0;
|
||||
+ int i;
|
||||
+
|
||||
+ tx_buf = t->tx_buf;
|
||||
+ rx_buf = t->rx_buf;
|
||||
+ tx_eof = t->last_in_message_list;
|
||||
+
|
||||
+ DBG("txrx: tx %p, rx %p, len %d\n", tx_buf, rx_buf, t->len);
|
||||
+
|
||||
+ if (tx_buf) {
|
||||
+ for (i = 0; i < t->len; i++)
|
||||
+ DBG("tx_buf[%02d]: 0x%02x\n", i, tx_buf[i]);
|
||||
+
|
||||
+ for (i = 0; i < (t->len - 1); i++) {
|
||||
+ err = cns21xx_spi_txrx_word(hw, spi->chip_select, 0,
|
||||
+ tx_buf[i], &rx_data);
|
||||
+ if (err)
|
||||
+ goto done;
|
||||
+
|
||||
+ if (rx_buf) {
|
||||
+ rx_buf[i] = rx_data;
|
||||
+ DBG("rx_buf[%02d]:0x%02x\n", i, rx_buf[i]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ err = cns21xx_spi_txrx_word(hw, spi->chip_select, tx_eof,
|
||||
+ tx_buf[i], &rx_data);
|
||||
+ if (err)
|
||||
+ goto done;
|
||||
+
|
||||
+ if ((tx_eof) && rx_buf) {
|
||||
+ rx_buf[i] = rx_data;
|
||||
+ DBG("rx_buf[%02d]:0x%02x\n", i, rx_buf[i]);
|
||||
+ }
|
||||
+ } else if (rx_buf) {
|
||||
+ for (i = 0; i < (t->len - 1); i++) {
|
||||
+ err = cns21xx_spi_txrx_word(hw, spi->chip_select, 0,
|
||||
+ 0xff, &rx_data);
|
||||
+ if (err)
|
||||
+ goto done;
|
||||
+
|
||||
+ rx_buf[i] = rx_data;
|
||||
+ DBG("rx_buf[%02d]:0x%02x\n", i, rx_buf[i]);
|
||||
+ }
|
||||
+
|
||||
+ err = cns21xx_spi_txrx_word(hw, spi->chip_select, tx_eof,
|
||||
+ 0xff, &rx_data);
|
||||
+ if (err)
|
||||
+ goto done;
|
||||
+
|
||||
+ rx_buf[i] = rx_data;
|
||||
+ DBG("rx_buf[%02d]:0x%02x\n", i, rx_buf[i]);
|
||||
+ }
|
||||
+
|
||||
+ done:
|
||||
+ return (err) ? err : t->len;
|
||||
+}
|
||||
+
|
||||
+static void __init cns21xx_spi_hw_init(struct cns21xx_spi *hw)
|
||||
+{
|
||||
+ u32 t;
|
||||
+ u32 pclk;
|
||||
+
|
||||
+ /* Setup configuration register */
|
||||
+ cns21xx_spi_wr(hw, CFG_SPI_MASTER_EN, SPI_REG_CFG);
|
||||
+
|
||||
+ /* Set default clock to PCLK/2 */
|
||||
+ cns21xx_spi_wr(hw, BIT_RATE_DIV_2, SPI_REG_BIT_RATE);
|
||||
+
|
||||
+ /* Configure SPI's Tx channel */
|
||||
+ cns21xx_spi_wr(hw, 0, SPI_REG_TX_CTRL);
|
||||
+
|
||||
+ /* Configure Tx FIFO Threshold */
|
||||
+ t = cns21xx_spi_rr(hw, SPI_REG_FIFO_TX_CFG);
|
||||
+ t &= ~(FIFO_TX_CFG_SPI_TXFF_THRED_M << FIFO_TX_CFG_SPI_TXFF_THRED_S);
|
||||
+ t |= (FIFO_TX_CFG_SPI_TXFF_THRED_2 << FIFO_TX_CFG_SPI_TXFF_THRED_S);
|
||||
+ cns21xx_spi_wr(hw, t, SPI_REG_FIFO_TX_CFG);
|
||||
+
|
||||
+ /* Configure Rx FIFO Threshold */
|
||||
+ t = cns21xx_spi_rr(hw, SPI_REG_FIFO_RX_CFG);
|
||||
+ t &= ~(FIFO_RX_CFG_SPI_RXFF_THRED_M << FIFO_RX_CFG_SPI_RXFF_THRED_S);
|
||||
+ t |= (FIFO_RX_CFG_SPI_RXFF_THRED_2 << FIFO_RX_CFG_SPI_RXFF_THRED_S);
|
||||
+ cns21xx_spi_wr(hw, t, SPI_REG_FIFO_RX_CFG);
|
||||
+
|
||||
+ /* Disable interrupts, and clear interrupt status */
|
||||
+ cns21xx_spi_wr(hw, 0, SPI_REG_INTR_ENA);
|
||||
+ cns21xx_spi_wr(hw, INTR_STAT_CLEAR_MASK, SPI_REG_INTR_STAT);
|
||||
+
|
||||
+ (void) cns21xx_spi_rr(hw, SPI_REG_RX_DATA);
|
||||
+
|
||||
+ /* Enable SPI */
|
||||
+ t = cns21xx_spi_rr(hw, SPI_REG_CFG);
|
||||
+ t |= CFG_SPI_EN;
|
||||
+ cns21xx_spi_wr(hw, t, SPI_REG_CFG);
|
||||
+
|
||||
+ pclk = cns21xx_get_apb_freq();
|
||||
+ hw->freq_max = pclk;
|
||||
+ hw->freq_min = pclk / (1 << BIT_RATE_DIV_128);
|
||||
+}
|
||||
+
|
||||
+static int __init cns21xx_spi_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct cns21xx_spi *hw;
|
||||
+ struct spi_master *master;
|
||||
+ struct resource *res;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ master = spi_alloc_master(&pdev->dev, sizeof(struct cns21xx_spi));
|
||||
+ if (!master) {
|
||||
+ dev_err(&pdev->dev, "No memory for spi_master\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ hw = spi_master_get_devdata(master);
|
||||
+
|
||||
+ platform_set_drvdata(pdev, hw);
|
||||
+ hw->master = spi_master_get(master);
|
||||
+ hw->dev = &pdev->dev;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ if (!res) {
|
||||
+ dev_dbg(&pdev->dev, "no MEM resource found\n");
|
||||
+ err = -ENOENT;
|
||||
+ goto err_put_master;
|
||||
+ }
|
||||
+
|
||||
+ hw->region = request_mem_region(res->start, resource_size(res),
|
||||
+ dev_name(&pdev->dev));
|
||||
+ if (!hw->region) {
|
||||
+ dev_err(&pdev->dev, "unable to reserve iomem region\n");
|
||||
+ err = -ENXIO;
|
||||
+ goto err_put_master;
|
||||
+ }
|
||||
+
|
||||
+ hw->base = ioremap(res->start, resource_size(res));
|
||||
+ if (!hw->base) {
|
||||
+ dev_err(&pdev->dev, "ioremap failed\n");
|
||||
+ err = -ENOENT;
|
||||
+ goto err_release_region;
|
||||
+ }
|
||||
+
|
||||
+ cns21xx_spi_hw_init(hw);
|
||||
+
|
||||
+ master->bus_num = pdev->id;
|
||||
+ if (master->bus_num == -1)
|
||||
+ master->bus_num = 0;
|
||||
+
|
||||
+ master->num_chipselect = 4;
|
||||
+ master->setup = cns21xx_spi_setup;
|
||||
+
|
||||
+ hw->bitbang.master = hw->master;
|
||||
+ hw->bitbang.chipselect = cns21xx_spi_chipselect;
|
||||
+ hw->bitbang.txrx_bufs = cns21xx_spi_txrx;
|
||||
+ hw->bitbang.setup_transfer = cns21xx_spi_setup_transfer;
|
||||
+
|
||||
+ err = spi_bitbang_start(&hw->bitbang);
|
||||
+ if (err) {
|
||||
+ dev_err(hw->dev, "unable to register SPI master\n");
|
||||
+ goto err_unmap;
|
||||
+ }
|
||||
+
|
||||
+ dev_info(hw->dev, "iomem at %08x\n", res->start);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+ err_unmap:
|
||||
+ iounmap(hw->base);
|
||||
+
|
||||
+ err_release_region:
|
||||
+ release_resource(hw->region);
|
||||
+ kfree(hw->region);
|
||||
+
|
||||
+ err_put_master:
|
||||
+ spi_master_put(hw->bitbang.master);
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int __devexit cns21xx_spi_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct cns21xx_spi *hw = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ spi_bitbang_stop(&hw->bitbang);
|
||||
+ iounmap(hw->base);
|
||||
+ release_resource(hw->region);
|
||||
+ kfree(hw->region);
|
||||
+ spi_master_put(hw->bitbang.master);
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver cns21xx_spi_driver = {
|
||||
+ .remove = __devexit_p(cns21xx_spi_remove),
|
||||
+ .driver = {
|
||||
+ .name = DRIVER_NAME,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init cns21xx_spi_init(void)
|
||||
+{
|
||||
+ return platform_driver_probe(&cns21xx_spi_driver, cns21xx_spi_probe);
|
||||
+}
|
||||
+
|
||||
+static void __exit cns21xx_spi_exit(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&cns21xx_spi_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(cns21xx_spi_init);
|
||||
+module_exit(cns21xx_spi_exit);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Cavium Networks CNS21xx SPI Controller driver");
|
||||
+MODULE_AUTHOR("STAR Semi Corp.");
|
||||
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
+MODULE_ALIAS("platform:" DRIVER_NAME);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,104 @@
|
|||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/dev-usb.c
|
||||
@@ -0,0 +1,71 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2008 Cavium Networks
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include <mach/cns21xx.h>
|
||||
+
|
||||
+static u64 cns21xx_usb_dmamask = DMA_BIT_MASK(32);
|
||||
+
|
||||
+static struct resource cns21xx_ohci_resources[] = {
|
||||
+ [0] = {
|
||||
+ .start = CNS21XX_OHCI_CTRL_BASE,
|
||||
+ .end = CNS21XX_OHCI_CTRL_BASE + SZ_1M - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ [1] = {
|
||||
+ .start = CNS21XX_IRQ_OHCI,
|
||||
+ .end = CNS21XX_IRQ_OHCI,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device cns21xx_ohci_device = {
|
||||
+ .name = "cns21xx-ohci",
|
||||
+ .id = -1,
|
||||
+ .dev = {
|
||||
+ .dma_mask = &cns21xx_usb_dmamask,
|
||||
+ .coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
+ },
|
||||
+ .resource = cns21xx_ohci_resources,
|
||||
+ .num_resources = ARRAY_SIZE(cns21xx_ohci_resources),
|
||||
+};
|
||||
+
|
||||
+static struct resource cns21xx_ehci_resources[] = {
|
||||
+ [0] = {
|
||||
+ .start = CNS21XX_EHCI_CTRL_BASE,
|
||||
+ .end = CNS21XX_EHCI_CTRL_BASE + SZ_1M - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ [1] = {
|
||||
+ .start = CNS21XX_IRQ_EHCI,
|
||||
+ .end = CNS21XX_IRQ_EHCI,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device cns21xx_ehci_device = {
|
||||
+ .name = "cns21xx-ehci",
|
||||
+ .id = -1,
|
||||
+ .dev = {
|
||||
+ .dma_mask = &cns21xx_usb_dmamask,
|
||||
+ .coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
+ },
|
||||
+ .resource = cns21xx_ehci_resources,
|
||||
+ .num_resources = ARRAY_SIZE(cns21xx_ehci_resources),
|
||||
+};
|
||||
+
|
||||
+void __init cns21xx_register_usb(void)
|
||||
+{
|
||||
+ platform_device_register(&cns21xx_ehci_device);
|
||||
+ platform_device_register(&cns21xx_ohci_device);
|
||||
+}
|
||||
--- a/arch/arm/mach-cns21xx/Kconfig
|
||||
+++ b/arch/arm/mach-cns21xx/Kconfig
|
||||
@@ -3,4 +3,7 @@ if ARCH_CNS21XX
|
||||
menu "Cavium Networks CNS21xx based machines"
|
||||
endmenu
|
||||
|
||||
+config CNS21XX_DEV_USB
|
||||
+ def_bool n
|
||||
+
|
||||
endif
|
||||
--- a/arch/arm/mach-cns21xx/Makefile
|
||||
+++ b/arch/arm/mach-cns21xx/Makefile
|
||||
@@ -6,5 +6,8 @@
|
||||
|
||||
obj-y := core.o devices.o gpio.o irq.o mm.o time.o
|
||||
|
||||
+# devices
|
||||
+obj-$(CONFIG_CNS21XX_DEV_USB) += dev-usb.o
|
||||
+
|
||||
# machine specific files
|
||||
|
||||
--- a/arch/arm/mach-cns21xx/common.h
|
||||
+++ b/arch/arm/mach-cns21xx/common.h
|
||||
@@ -18,5 +18,6 @@ extern struct sys_timer cns21xx_timer;
|
||||
|
||||
int __init cns21xx_register_uart0(void);
|
||||
int __init cns21xx_register_uart1(void);
|
||||
+int __init cns21xx_register_usb(void);
|
||||
|
||||
#endif /* _MACH_CNS21XX_COMMON_H */
|
|
@ -0,0 +1,63 @@
|
|||
--- a/arch/arm/mach-cns21xx/common.h
|
||||
+++ b/arch/arm/mach-cns21xx/common.h
|
||||
@@ -19,5 +19,6 @@ extern struct sys_timer cns21xx_timer;
|
||||
int __init cns21xx_register_uart0(void);
|
||||
int __init cns21xx_register_uart1(void);
|
||||
int __init cns21xx_register_usb(void);
|
||||
+int __init cns21xx_register_wdt(void);
|
||||
|
||||
#endif /* _MACH_CNS21XX_COMMON_H */
|
||||
--- a/arch/arm/mach-cns21xx/devices.c
|
||||
+++ b/arch/arm/mach-cns21xx/devices.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial_8250.h>
|
||||
+#include <linux/fa_wdt.h>
|
||||
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/hardware.h>
|
||||
@@ -77,3 +78,32 @@ int __init cns21xx_register_uart1(void)
|
||||
HAL_MISC_ENABLE_UART1_PINS();
|
||||
return platform_device_register(&cns21xx_uart1_device);
|
||||
}
|
||||
+
|
||||
+static struct resource cns21xx_wdt_resources[] = {
|
||||
+ {
|
||||
+ .start = CNS21XX_WDT_BASE,
|
||||
+ .end = CNS21XX_WDT_BASE + SZ_4K - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+#define CNS21XX_WDT_CLOCK 10 /* 10 Hz */
|
||||
+
|
||||
+static struct fa_wdt_platform_data cns21xx_wdt_data = {
|
||||
+ .clock = CNS21XX_WDT_CLOCK,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device cns21xx_wdt_device = {
|
||||
+ .name = "fa-wdt",
|
||||
+ .id = -1,
|
||||
+ .resource = cns21xx_wdt_resources,
|
||||
+ .num_resources = ARRAY_SIZE(cns21xx_wdt_resources),
|
||||
+ .dev = {
|
||||
+ .platform_data = &cns21xx_wdt_data,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+int __init cns21xx_register_wdt(void)
|
||||
+{
|
||||
+ return platform_device_register(&cns21xx_wdt_device);
|
||||
+}
|
||||
--- a/drivers/watchdog/Kconfig
|
||||
+++ b/drivers/watchdog/Kconfig
|
||||
@@ -333,7 +333,7 @@ config IMX2_WDT
|
||||
|
||||
config FA_WATCHDOG
|
||||
tristate "Faraday watchdog"
|
||||
- depends on ARCH_GEMINI
|
||||
+ depends on ARCH_GEMINI || ARCH_CNS21XX
|
||||
help
|
||||
Say Y here if you want support for the built-in watchdog timer
|
||||
found in some Faraday FA526 based SoCs.
|
|
@ -0,0 +1,117 @@
|
|||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/dev-spi-master.c
|
||||
@@ -0,0 +1,83 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include <mach/hardware.h>
|
||||
+#include <mach/cns21xx.h>
|
||||
+#include <mach/cns21xx_misc.h>
|
||||
+#include <mach/cns21xx_powermgmt.h>
|
||||
+#include <mach/irqs.h>
|
||||
+
|
||||
+#include "common.h"
|
||||
+
|
||||
+static u64 spi_dmamask = DMA_BIT_MASK(32);
|
||||
+static struct resource cns21xx_spi_resources[] = {
|
||||
+ [0] = {
|
||||
+ .start = CNS21XX_SPI_BASE,
|
||||
+ .end = CNS21XX_SPI_BASE + SZ_4K - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ [1] = {
|
||||
+ .start = CNS21XX_IRQ_SPI,
|
||||
+ .end = CNS21XX_IRQ_SPI,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device cns21xx_spi_master_device = {
|
||||
+ .name = "cns21xx-spi",
|
||||
+ .id = -1,
|
||||
+ .dev = {
|
||||
+ .dma_mask = &spi_dmamask,
|
||||
+ .coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
+ },
|
||||
+ .resource = cns21xx_spi_resources,
|
||||
+ .num_resources = ARRAY_SIZE(cns21xx_spi_resources),
|
||||
+};
|
||||
+
|
||||
+void __init cns21xx_register_spi_master(int id, struct spi_board_info *info,
|
||||
+ unsigned int n)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ /* Enable SPI pins */
|
||||
+ HAL_MISC_ENABLE_SPIDR_PINS();
|
||||
+ HAL_MISC_ENABLE_SPICLK_PINS();
|
||||
+ for (i = 0; i < n; i++) {
|
||||
+ switch (info[i].chip_select) {
|
||||
+ case 0:
|
||||
+ HAL_MISC_ENABLE_SPICSN0_PINS();
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ HAL_MISC_ENABLE_SPICSN1_PINS();
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ HAL_MISC_ENABLE_SPICSN2_PINS();
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ HAL_MISC_ENABLE_SPICSN3_PINS();
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Disable SPI serial flash access through 0x30000000 region */
|
||||
+ HAL_MISC_DISABLE_SPI_SERIAL_FLASH_BANK_ACCESS();
|
||||
+
|
||||
+ /* Enable SPI clock */
|
||||
+ HAL_PWRMGT_ENABLE_SPI_CLOCK();
|
||||
+
|
||||
+ cns21xx_spi_master_device.id = id;
|
||||
+
|
||||
+ spi_register_board_info(info, n);
|
||||
+ platform_device_register(&cns21xx_spi_master_device);
|
||||
+}
|
||||
--- a/arch/arm/mach-cns21xx/Kconfig
|
||||
+++ b/arch/arm/mach-cns21xx/Kconfig
|
||||
@@ -6,4 +6,7 @@ endmenu
|
||||
config CNS21XX_DEV_USB
|
||||
def_bool n
|
||||
|
||||
+config CNS21XX_DEV_SPI_MASTER
|
||||
+ def_bool n
|
||||
+
|
||||
endif
|
||||
--- a/arch/arm/mach-cns21xx/Makefile
|
||||
+++ b/arch/arm/mach-cns21xx/Makefile
|
||||
@@ -8,6 +8,7 @@ obj-y := core.o devices.o gpio.o irq.o
|
||||
|
||||
# devices
|
||||
obj-$(CONFIG_CNS21XX_DEV_USB) += dev-usb.o
|
||||
+obj-$(CONFIG_CNS21XX_DEV_SPI_MASTER) += dev-spi-master.o
|
||||
|
||||
# machine specific files
|
||||
|
||||
--- a/arch/arm/mach-cns21xx/common.h
|
||||
+++ b/arch/arm/mach-cns21xx/common.h
|
||||
@@ -21,4 +21,8 @@ int __init cns21xx_register_uart1(void);
|
||||
int __init cns21xx_register_usb(void);
|
||||
int __init cns21xx_register_wdt(void);
|
||||
|
||||
+struct spi_board_info;
|
||||
+void __init cns21xx_register_spi_master(int id, struct spi_board_info *info,
|
||||
+ unsigned int n);
|
||||
+
|
||||
#endif /* _MACH_CNS21XX_COMMON_H */
|
|
@ -0,0 +1,178 @@
|
|||
--- a/arch/arm/mach-cns21xx/Kconfig
|
||||
+++ b/arch/arm/mach-cns21xx/Kconfig
|
||||
@@ -3,6 +3,9 @@ if ARCH_CNS21XX
|
||||
menu "Cavium Networks CNS21xx based machines"
|
||||
endmenu
|
||||
|
||||
+config CNS21XX_DEV_GEC
|
||||
+ def_bool n
|
||||
+
|
||||
config CNS21XX_DEV_USB
|
||||
def_bool n
|
||||
|
||||
--- a/arch/arm/mach-cns21xx/Makefile
|
||||
+++ b/arch/arm/mach-cns21xx/Makefile
|
||||
@@ -7,6 +7,7 @@
|
||||
obj-y := core.o devices.o gpio.o irq.o mm.o time.o
|
||||
|
||||
# devices
|
||||
+obj-$(CONFIG_CNS21XX_DEV_GEC) += dev-gec.o
|
||||
obj-$(CONFIG_CNS21XX_DEV_USB) += dev-usb.o
|
||||
obj-$(CONFIG_CNS21XX_DEV_SPI_MASTER) += dev-spi-master.o
|
||||
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/dev-gec.c
|
||||
@@ -0,0 +1,98 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
+
|
||||
+#include <asm/sizes.h>
|
||||
+#include <mach/cns21xx.h>
|
||||
+#include <mach/irqs.h>
|
||||
+
|
||||
+#include "dev-gec.h"
|
||||
+
|
||||
+static u8 cns21xx_ethaddr[ETH_ALEN];
|
||||
+struct cns21xx_gec_plat_data cns21xx_gec_data;
|
||||
+
|
||||
+static struct resource cns21xx_gec_resources[] = {
|
||||
+ {
|
||||
+ .start = CNS21XX_NIC_BASE,
|
||||
+ .end = CNS21XX_NIC_BASE + SZ_4K - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ }, {
|
||||
+ .name = CNS21XX_GEC_STATUS_IRQ_NAME,
|
||||
+ .start = CNS21XX_IRQ_NIC_STATUS,
|
||||
+ .end = CNS21XX_IRQ_NIC_STATUS,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ }, {
|
||||
+ .name = CNS21XX_GEC_RXRC_IRQ_NAME,
|
||||
+ .start = CNS21XX_IRQ_NIC_RXRC,
|
||||
+ .end = CNS21XX_IRQ_NIC_RXRC,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ }, {
|
||||
+ .name = CNS21XX_GEC_RXQF_IRQ_NAME,
|
||||
+ .start = CNS21XX_IRQ_NIC_RXQF,
|
||||
+ .end = CNS21XX_IRQ_NIC_RXQF,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ }, {
|
||||
+ .name = CNS21XX_GEC_TXTC_IRQ_NAME,
|
||||
+ .start = CNS21XX_IRQ_NIC_TXTC,
|
||||
+ .end = CNS21XX_IRQ_NIC_TXTC,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ }, {
|
||||
+ .name = CNS21XX_GEC_TXQE_IRQ_NAME,
|
||||
+ .start = CNS21XX_IRQ_NIC_TXQE,
|
||||
+ .end = CNS21XX_IRQ_NIC_TXQE,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static u64 cns21xx_gec_dmamask = DMA_BIT_MASK(32);
|
||||
+static struct platform_device cns21xx_gec_device = {
|
||||
+ .name = "cns21xx-gec",
|
||||
+ .id = -1,
|
||||
+ .resource = cns21xx_gec_resources,
|
||||
+ .num_resources = ARRAY_SIZE(cns21xx_gec_resources),
|
||||
+ .dev = {
|
||||
+ .dma_mask = &cns21xx_gec_dmamask,
|
||||
+ .coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
+ .platform_data = &cns21xx_gec_data,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init cns21xx_ethaddr_setup(char *str)
|
||||
+{
|
||||
+ int t;
|
||||
+
|
||||
+ t = sscanf(str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
|
||||
+ &cns21xx_ethaddr[0], &cns21xx_ethaddr[1],
|
||||
+ &cns21xx_ethaddr[2], &cns21xx_ethaddr[3],
|
||||
+ &cns21xx_ethaddr[4], &cns21xx_ethaddr[5]);
|
||||
+
|
||||
+ if (t != ETH_ALEN)
|
||||
+ pr_err("cns21xx: failed to parse mac address \"%s\"\n", str);
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+__setup("ethaddr=", cns21xx_ethaddr_setup);
|
||||
+
|
||||
+__init int cns21xx_register_gec(void)
|
||||
+{
|
||||
+ if (cns21xx_gec_data.mac_addr == NULL)
|
||||
+ cns21xx_gec_data.mac_addr = cns21xx_ethaddr;
|
||||
+
|
||||
+ if (!is_valid_ether_addr(cns21xx_gec_data.mac_addr)) {
|
||||
+ random_ether_addr(cns21xx_gec_data.mac_addr);
|
||||
+ pr_debug("cns21xx: using random MAC address \"%s\"\n",
|
||||
+ cns21xx_gec_data.mac_addr);
|
||||
+ }
|
||||
+
|
||||
+ return platform_device_register(&cns21xx_gec_device);
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/dev-gec.h
|
||||
@@ -0,0 +1,18 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file 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 _CNS21XX_DEV_GEC_H
|
||||
+#define _CNS21XX_DEV_GEC_H
|
||||
+
|
||||
+#include <mach/cns21xx_gec_platform.h>
|
||||
+
|
||||
+extern struct cns21xx_gec_plat_data cns21xx_gec_data;
|
||||
+
|
||||
+__init int cns21xx_register_gec(void);
|
||||
+
|
||||
+#endif /* _CNS21XX_DEV_GEC_H */
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/include/mach/cns21xx_gec_platform.h
|
||||
@@ -0,0 +1,31 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file 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 _CNS21XX_GEC_PLATFORM_H
|
||||
+#define _CNS21XX_GEC_PLATFORM_H
|
||||
+
|
||||
+#define CNS21XX_GEC_STATUS_IRQ_NAME "status"
|
||||
+#define CNS21XX_GEC_RXRC_IRQ_NAME "rxrc"
|
||||
+#define CNS21XX_GEC_RXQF_IRQ_NAME "rxqf"
|
||||
+#define CNS21XX_GEC_TXTC_IRQ_NAME "txtc"
|
||||
+#define CNS21XX_GEC_TXQE_IRQ_NAME "txqe"
|
||||
+
|
||||
+enum cns21xx_gec_phy_type {
|
||||
+ CNS21XX_GEC_PHY_TYPE_INTERNAL = 0,
|
||||
+ CNS21XX_GEC_PHY_TYPE_VSC8601,
|
||||
+ CNS21XX_GEC_PHY_TYPE_IP101A,
|
||||
+ CNS21XX_GEC_PHY_TYPE_IP1001,
|
||||
+};
|
||||
+
|
||||
+struct cns21xx_gec_plat_data {
|
||||
+ u8 *mac_addr;
|
||||
+ enum cns21xx_gec_phy_type phy_type;
|
||||
+ u8 phy_addr;
|
||||
+};
|
||||
+
|
||||
+#endif /* _CNS21XX_GEC_PLATFORM_H */
|
|
@ -0,0 +1,242 @@
|
|||
--- a/arch/arm/mach-cns21xx/Kconfig
|
||||
+++ b/arch/arm/mach-cns21xx/Kconfig
|
||||
@@ -1,6 +1,16 @@
|
||||
if ARCH_CNS21XX
|
||||
|
||||
menu "Cavium Networks CNS21xx based machines"
|
||||
+
|
||||
+config MACH_NS_K330
|
||||
+ bool "NS-K330 NAS"
|
||||
+ select CNS21XX_DEV_GEC
|
||||
+ select CNS21XX_DEV_SPI_MASTER
|
||||
+ select CNS21XX_DEV_USB
|
||||
+ help
|
||||
+ Say Y here if you intend to run this kernel on the
|
||||
+ NS-K330 NAS board.
|
||||
+
|
||||
endmenu
|
||||
|
||||
config CNS21XX_DEV_GEC
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/mach-ns-k330.c
|
||||
@@ -0,0 +1,212 @@
|
||||
+/*
|
||||
+ * NS-K330 NAS board support
|
||||
+ *
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/map.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+#include <linux/spi/flash.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/leds.h>
|
||||
+#include <linux/gpio_keys.h>
|
||||
+#include <linux/input.h>
|
||||
+
|
||||
+#include <asm/setup.h>
|
||||
+#include <asm/mach-types.h>
|
||||
+#include <asm/mach/arch.h>
|
||||
+#include <asm/mach/time.h>
|
||||
+#include <mach/hardware.h>
|
||||
+#include <mach/cns21xx.h>
|
||||
+#include <mach/cns21xx_misc.h>
|
||||
+
|
||||
+#include "common.h"
|
||||
+#include "dev-gec.h"
|
||||
+
|
||||
+#define NS_K330_GPIO_LED_LINK 1
|
||||
+#define NS_K330_GPIO_LED_USB1 16
|
||||
+#define NS_K330_GPIO_LED_USB2 17
|
||||
+#define NS_K330_GPIO_LED_ETH_GREEN 22
|
||||
+#define NS_K330_GPIO_LED_ETH_ORANGE 23
|
||||
+
|
||||
+#define NS_K330_GPIO_BTN_RESET 13
|
||||
+#define NS_K330_GPIO_BTN_USB1 14
|
||||
+#define NS_K330_GPIO_BTN_USB2 15
|
||||
+
|
||||
+#ifdef CONFIG_MTD_PARTITIONS
|
||||
+static struct mtd_partition ns_k330_partitions[] = {
|
||||
+ {
|
||||
+ .name = "boot",
|
||||
+ .offset = 0x0,
|
||||
+ .size = 0x040000,
|
||||
+ .mask_flags = MTD_WRITEABLE,
|
||||
+ }, {
|
||||
+ .name = "config",
|
||||
+ .offset = 0x040000,
|
||||
+ .size = 0x020000,
|
||||
+ .mask_flags = MTD_WRITEABLE,
|
||||
+ }, {
|
||||
+ .name = "kernel",
|
||||
+ .offset = 0x060000,
|
||||
+ .size = 0x100000,
|
||||
+ }, {
|
||||
+ .name = "rootfs",
|
||||
+ .offset = 0x160000,
|
||||
+ .size = 0x290000,
|
||||
+ }, {
|
||||
+ .name = "firmware",
|
||||
+ .offset = 0x060000,
|
||||
+ .size = 0x390000,
|
||||
+ },
|
||||
+};
|
||||
+#else
|
||||
+#define ns_k330_partitions NULL
|
||||
+#define ns_k330_num_partitions 0
|
||||
+#endif /* CONFIG_MTD_PARTITIONS */
|
||||
+
|
||||
+static struct flash_platform_data ns_k330_flash_data = {
|
||||
+ .parts = ns_k330_partitions,
|
||||
+ .nr_parts = ARRAY_SIZE(ns_k330_partitions),
|
||||
+};
|
||||
+
|
||||
+static struct spi_board_info ns_k330_spi_board_info[] = {
|
||||
+ {
|
||||
+ .bus_num = 0,
|
||||
+ .chip_select = 0,
|
||||
+ .max_speed_hz = 25000000,
|
||||
+ .modalias = "m25p80",
|
||||
+ .platform_data = &ns_k330_flash_data,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct gpio_led ns_k330_gpio_leds[] = {
|
||||
+ {
|
||||
+ .name = "ns-k330:red:link",
|
||||
+ .gpio = NS_K330_GPIO_LED_LINK,
|
||||
+ .active_low = 1,
|
||||
+ }, {
|
||||
+ .name = "ns-k330:green:usb1",
|
||||
+ .gpio = NS_K330_GPIO_LED_USB1,
|
||||
+ .active_low = 1,
|
||||
+ }, {
|
||||
+ .name = "ns-k330:green:usb2",
|
||||
+ .gpio = NS_K330_GPIO_LED_USB2,
|
||||
+ .active_low = 1,
|
||||
+ }, {
|
||||
+ .name = "ns-k330:green:eth",
|
||||
+ .gpio = NS_K330_GPIO_LED_ETH_GREEN,
|
||||
+ .active_low = 1,
|
||||
+ }, {
|
||||
+ .name = "ns-k330:orange:eth",
|
||||
+ .gpio = NS_K330_GPIO_LED_ETH_ORANGE,
|
||||
+ .active_low = 1,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct gpio_led_platform_data ns_k330_gpio_leds_data = {
|
||||
+ .num_leds = ARRAY_SIZE(ns_k330_gpio_leds),
|
||||
+ .leds = ns_k330_gpio_leds,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device ns_k330_gpio_leds_device = {
|
||||
+ .name = "leds-gpio",
|
||||
+ .id = -1,
|
||||
+ .dev.platform_data = &ns_k330_gpio_leds_data,
|
||||
+};
|
||||
+
|
||||
+static struct gpio_keys_button ns_k330_gpio_keys[] = {
|
||||
+ {
|
||||
+ .code = KEY_RESTART,
|
||||
+ .gpio = NS_K330_GPIO_BTN_RESET,
|
||||
+ .desc = "Reset Button",
|
||||
+ .active_low = 1,
|
||||
+ },
|
||||
+ {
|
||||
+ .code = BTN_0,
|
||||
+ .gpio = NS_K330_GPIO_BTN_USB1,
|
||||
+ .desc = "USB1 Button",
|
||||
+ .active_low = 1,
|
||||
+ },
|
||||
+ {
|
||||
+ .code = BTN_1,
|
||||
+ .gpio = NS_K330_GPIO_BTN_USB2,
|
||||
+ .desc = "USB2 Button",
|
||||
+ .active_low = 0,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct gpio_keys_platform_data ns_k330_gpio_keys_data = {
|
||||
+ .buttons = ns_k330_gpio_keys,
|
||||
+ .nbuttons = ARRAY_SIZE(ns_k330_gpio_keys),
|
||||
+};
|
||||
+
|
||||
+static struct platform_device ns_k330_gpio_keys_device = {
|
||||
+ .name = "gpio-keys",
|
||||
+ .id = -1,
|
||||
+ .num_resources = 0,
|
||||
+ .dev = {
|
||||
+ .platform_data = &ns_k330_gpio_keys_data,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void __init ns_k330_fixup(struct machine_desc *desc,
|
||||
+ struct tag *tags, char **cmdline,
|
||||
+ struct meminfo *mi)
|
||||
+{
|
||||
+ struct tag *t;
|
||||
+
|
||||
+ /* The board has 32MB of RAM mapped at 0. */
|
||||
+ mi->nr_banks = 1;
|
||||
+ mi->bank[0].start = 0;
|
||||
+ mi->bank[0].size = SZ_32M;
|
||||
+
|
||||
+ for (t = tags; t->hdr.size; t = tag_next(t)) {
|
||||
+ switch (t->hdr.tag) {
|
||||
+ case ATAG_CORE:
|
||||
+ if (t->u.core.rootdev == 255)
|
||||
+ t->u.core.rootdev = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void __init ns_k330_init(void)
|
||||
+{
|
||||
+ cns21xx_gpio_init();
|
||||
+
|
||||
+ HAL_MISC_DISABLE_LED012_PINS();
|
||||
+ HAL_MISC_DISABLE_I2C_PINS();
|
||||
+ HAL_MISC_DISABLE_I2S_PINS();
|
||||
+
|
||||
+ cns21xx_register_uart0();
|
||||
+ cns21xx_register_wdt();
|
||||
+ cns21xx_register_usb();
|
||||
+ cns21xx_register_spi_master(-1, ns_k330_spi_board_info,
|
||||
+ ARRAY_SIZE(ns_k330_spi_board_info));
|
||||
+
|
||||
+ cns21xx_gec_data.phy_type = CNS21XX_GEC_PHY_TYPE_INTERNAL;
|
||||
+ cns21xx_register_gec();
|
||||
+
|
||||
+ platform_device_register(&ns_k330_gpio_leds_device);
|
||||
+ platform_device_register(&ns_k330_gpio_keys_device);
|
||||
+}
|
||||
+
|
||||
+MACHINE_START(NS_K330, "NS-K330 NAS")
|
||||
+ .phys_io = CNS21XX_PHYS_IO,
|
||||
+ .io_pg_offst = CNS21XX_IO_PAGE_OFFSET,
|
||||
+ .boot_params = 0x100,
|
||||
+ .fixup = ns_k330_fixup,
|
||||
+ .map_io = cns21xx_map_io,
|
||||
+ .init_irq = cns21xx_init_irq,
|
||||
+ .timer = &cns21xx_timer,
|
||||
+ .init_machine = ns_k330_init,
|
||||
+MACHINE_END
|
||||
--- a/arch/arm/mach-cns21xx/Makefile
|
||||
+++ b/arch/arm/mach-cns21xx/Makefile
|
||||
@@ -12,4 +12,4 @@ obj-$(CONFIG_CNS21XX_DEV_USB) += dev-us
|
||||
obj-$(CONFIG_CNS21XX_DEV_SPI_MASTER) += dev-spi-master.o
|
||||
|
||||
# machine specific files
|
||||
-
|
||||
+obj-$(CONFIG_MACH_NS_K330) += mach-ns-k330.o
|
|
@ -0,0 +1,209 @@
|
|||
--- a/arch/arm/mach-cns21xx/Kconfig
|
||||
+++ b/arch/arm/mach-cns21xx/Kconfig
|
||||
@@ -2,6 +2,15 @@ if ARCH_CNS21XX
|
||||
|
||||
menu "Cavium Networks CNS21xx based machines"
|
||||
|
||||
+config MACH_NSB3AST
|
||||
+ bool "AGESTAR NSB3AST support"
|
||||
+ select CNS21XX_DEV_GEC
|
||||
+ select CNS21XX_DEV_SPI_MASTER
|
||||
+ select CNS21XX_DEV_USB
|
||||
+ help
|
||||
+ Say Y here if you intend to run this kernel on the
|
||||
+ AGESTAR NSB3AST board.
|
||||
+
|
||||
config MACH_NS_K330
|
||||
bool "NS-K330 NAS"
|
||||
select CNS21XX_DEV_GEC
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/mach-nsb3ast.c
|
||||
@@ -0,0 +1,181 @@
|
||||
+/*
|
||||
+ * AGESTAR NSB3AST board support
|
||||
+ *
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/map.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+#include <linux/spi/flash.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/leds.h>
|
||||
+#include <linux/gpio_keys.h>
|
||||
+#include <linux/input.h>
|
||||
+
|
||||
+#include <asm/setup.h>
|
||||
+#include <asm/mach-types.h>
|
||||
+#include <asm/mach/arch.h>
|
||||
+#include <asm/mach/time.h>
|
||||
+#include <mach/hardware.h>
|
||||
+#include <mach/cns21xx.h>
|
||||
+#include <mach/cns21xx_misc.h>
|
||||
+
|
||||
+#include "common.h"
|
||||
+#include "dev-gec.h"
|
||||
+
|
||||
+#ifdef CONFIG_MTD_PARTITIONS
|
||||
+static struct mtd_partition nsb3ast_partitions[] = {
|
||||
+ {
|
||||
+ .name = "armboot",
|
||||
+ .offset = 0x0,
|
||||
+ .size = 0x040000,
|
||||
+ .mask_flags = MTD_WRITEABLE,
|
||||
+ }, {
|
||||
+ .name = "kernel",
|
||||
+ .offset = 0x040000,
|
||||
+ .size = 0x100000,
|
||||
+ }, {
|
||||
+ .name = "rootfs",
|
||||
+ .offset = 0x140000,
|
||||
+ .size = 0x6c0000,
|
||||
+ }, {
|
||||
+ .name = "firmware",
|
||||
+ .offset = 0x040000,
|
||||
+ .size = 0x7c0000,
|
||||
+ }, {
|
||||
+ .name = "wholeflash",
|
||||
+ .offset = 0x0,
|
||||
+ .size = 0x800000,
|
||||
+ .mask_flags = MTD_WRITEABLE,
|
||||
+ },
|
||||
+};
|
||||
+#else
|
||||
+#define nsb3ast_partitions NULL
|
||||
+#define nsb3ast_num_partitions 0
|
||||
+#endif /* CONFIG_MTD_PARTITIONS */
|
||||
+
|
||||
+static struct flash_platform_data nsb3ast_flash_data = {
|
||||
+ .parts = nsb3ast_partitions,
|
||||
+ .nr_parts = ARRAY_SIZE(nsb3ast_partitions),
|
||||
+};
|
||||
+
|
||||
+static struct spi_board_info nsb3ast_spi_board_info[] = {
|
||||
+ {
|
||||
+ .bus_num = 0,
|
||||
+ .chip_select = 0,
|
||||
+ .max_speed_hz = 25000000,
|
||||
+ .modalias = "m25p80",
|
||||
+ .platform_data = &nsb3ast_flash_data,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct gpio_led nsb3ast_gpio_leds[] = {
|
||||
+ {
|
||||
+ .name = "nsb3ast:red:d1",
|
||||
+ .gpio = 15,
|
||||
+ .active_low = 1,
|
||||
+ }, {
|
||||
+ .name = "nsb3ast:amber:eth",
|
||||
+ .gpio = 22,
|
||||
+ .active_low = 1,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct gpio_led_platform_data nsb3ast_gpio_leds_data = {
|
||||
+ .num_leds = ARRAY_SIZE(nsb3ast_gpio_leds),
|
||||
+ .leds = nsb3ast_gpio_leds,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device nsb3ast_gpio_leds_device = {
|
||||
+ .name = "leds-gpio",
|
||||
+ .id = -1,
|
||||
+ .dev.platform_data = &nsb3ast_gpio_leds_data,
|
||||
+};
|
||||
+
|
||||
+static struct gpio_keys_button nsb3ast_gpio_keys[] = {
|
||||
+ {
|
||||
+ .code = KEY_RESTART,
|
||||
+ .gpio = 0,
|
||||
+ .desc = "Reset Button",
|
||||
+ .active_low = 1,
|
||||
+ },
|
||||
+ {
|
||||
+ .code = BTN_0,
|
||||
+ .gpio = 2,
|
||||
+ .desc = "USB Button",
|
||||
+ .active_low = 0,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct gpio_keys_platform_data nsb3ast_gpio_keys_data = {
|
||||
+ .buttons = nsb3ast_gpio_keys,
|
||||
+ .nbuttons = ARRAY_SIZE(nsb3ast_gpio_keys),
|
||||
+};
|
||||
+
|
||||
+static struct platform_device nsb3ast_gpio_keys_device = {
|
||||
+ .name = "gpio-keys",
|
||||
+ .id = -1,
|
||||
+ .num_resources = 0,
|
||||
+ .dev = {
|
||||
+ .platform_data = &nsb3ast_gpio_keys_data,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void __init nsb3ast_fixup(struct machine_desc *desc,
|
||||
+ struct tag *tags, char **cmdline,
|
||||
+ struct meminfo *mi)
|
||||
+{
|
||||
+ struct tag *t;
|
||||
+
|
||||
+ /* The board has 32MB of RAM mapped at 0. */
|
||||
+ mi->nr_banks = 1;
|
||||
+ mi->bank[0].start = 0;
|
||||
+ mi->bank[0].size = SZ_32M;
|
||||
+
|
||||
+ for (t = tags; t->hdr.size; t = tag_next(t)) {
|
||||
+ switch (t->hdr.tag) {
|
||||
+ case ATAG_CORE:
|
||||
+ if (t->u.core.rootdev == 255)
|
||||
+ t->u.core.rootdev = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void __init nsb3ast_init(void)
|
||||
+{
|
||||
+ cns21xx_gpio_init();
|
||||
+ cns21xx_register_uart0();
|
||||
+ cns21xx_register_uart1();
|
||||
+ cns21xx_register_wdt();
|
||||
+ cns21xx_register_usb();
|
||||
+ cns21xx_register_spi_master(-1, nsb3ast_spi_board_info,
|
||||
+ ARRAY_SIZE(nsb3ast_spi_board_info));
|
||||
+
|
||||
+ cns21xx_gec_data.phy_type = CNS21XX_GEC_PHY_TYPE_INTERNAL;
|
||||
+ cns21xx_register_gec();
|
||||
+
|
||||
+ HAL_MISC_DISABLE_LED012_PINS();
|
||||
+ platform_device_register(&nsb3ast_gpio_leds_device);
|
||||
+ platform_device_register(&nsb3ast_gpio_keys_device);
|
||||
+}
|
||||
+
|
||||
+MACHINE_START(NSB3AST, "AGESTAR NSB3AST")
|
||||
+ .phys_io = CNS21XX_PHYS_IO,
|
||||
+ .io_pg_offst = CNS21XX_IO_PAGE_OFFSET,
|
||||
+ .boot_params = 0x100,
|
||||
+ .fixup = nsb3ast_fixup,
|
||||
+ .map_io = cns21xx_map_io,
|
||||
+ .init_irq = cns21xx_init_irq,
|
||||
+ .timer = &cns21xx_timer,
|
||||
+ .init_machine = nsb3ast_init,
|
||||
+MACHINE_END
|
||||
--- a/arch/arm/mach-cns21xx/Makefile
|
||||
+++ b/arch/arm/mach-cns21xx/Makefile
|
||||
@@ -13,3 +13,4 @@ obj-$(CONFIG_CNS21XX_DEV_SPI_MASTER) +=
|
||||
|
||||
# machine specific files
|
||||
obj-$(CONFIG_MACH_NS_K330) += mach-ns-k330.o
|
||||
+obj-$(CONFIG_MACH_NSB3AST) += mach-nsb3ast.o
|
|
@ -0,0 +1,438 @@
|
|||
From 248d9a5b63bba72bfc316b8a48c6163fce5acc22 Mon Sep 17 00:00:00 2001
|
||||
From: Paulius Zaleckas <paulius.zaleckas@gmail.com>
|
||||
Date: Thu, 18 Feb 2010 21:53:01 +0200
|
||||
Subject: [PATCH] ARM: Use cache alignment from asm/cache.h
|
||||
|
||||
Make code more optimal for ARM variants with
|
||||
different cache line size.
|
||||
|
||||
Signed-off-by: Paulius Zaleckas <paulius.zaleckas@gmail.com>
|
||||
---
|
||||
arch/arm/boot/compressed/head.S | 11 ++++++-----
|
||||
arch/arm/include/asm/dma-mapping.h | 2 +-
|
||||
arch/arm/kernel/entry-armv.S | 31 ++++++++++++++++---------------
|
||||
arch/arm/kernel/entry-common.S | 7 ++++---
|
||||
arch/arm/kernel/head.S | 3 ++-
|
||||
arch/arm/kernel/vmlinux.lds.S | 5 +++--
|
||||
arch/arm/lib/copy_page.S | 2 +-
|
||||
arch/arm/lib/memchr.S | 3 ++-
|
||||
arch/arm/lib/memset.S | 3 ++-
|
||||
arch/arm/lib/memzero.S | 3 ++-
|
||||
arch/arm/lib/strchr.S | 3 ++-
|
||||
arch/arm/lib/strncpy_from_user.S | 3 ++-
|
||||
arch/arm/lib/strnlen_user.S | 3 ++-
|
||||
arch/arm/lib/strrchr.S | 3 ++-
|
||||
arch/arm/mm/abort-ev4.S | 3 ++-
|
||||
arch/arm/mm/abort-nommu.S | 3 ++-
|
||||
16 files changed, 51 insertions(+), 37 deletions(-)
|
||||
|
||||
--- a/arch/arm/boot/compressed/head.S
|
||||
+++ b/arch/arm/boot/compressed/head.S
|
||||
@@ -9,6 +9,7 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
/*
|
||||
* Debugging stuff
|
||||
@@ -355,7 +356,7 @@ params: ldr r0, =0x10000100 @ params_p
|
||||
* This routine must preserve:
|
||||
* r4, r5, r6, r7, r8
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
cache_on: mov r3, #8 @ cache_on function
|
||||
b call_cache_fn
|
||||
|
||||
@@ -544,7 +545,7 @@ __common_mmu_cache_on:
|
||||
mcr p15, 0, r3, c2, c0, 0 @ load page table pointer
|
||||
mcr p15, 0, r1, c3, c0, 0 @ load domain access control
|
||||
b 1f
|
||||
- .align 5 @ cache line aligned
|
||||
+ .align L1_CACHE_SHIFT @ cache line aligned
|
||||
1: mcr p15, 0, r0, c1, c0, 0 @ load control register
|
||||
mrc p15, 0, r0, c1, c0, 0 @ and read it back to
|
||||
sub pc, lr, r0, lsr #32 @ properly flush pipeline
|
||||
@@ -563,7 +564,7 @@ __common_mmu_cache_on:
|
||||
* r8 = atags pointer
|
||||
* r9-r12,r14 = corrupted
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
reloc_start: add r9, r5, r0
|
||||
sub r9, r9, #128 @ do not copy the stack
|
||||
debug_reloc_start
|
||||
@@ -793,7 +794,7 @@ proc_types:
|
||||
* This routine must preserve:
|
||||
* r4, r6, r7
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
cache_off: mov r3, #12 @ cache_off function
|
||||
b call_cache_fn
|
||||
|
||||
@@ -868,7 +869,7 @@ __armv3_mmu_cache_off:
|
||||
* This routine must preserve:
|
||||
* r0, r4, r5, r6, r7
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
cache_clean_flush:
|
||||
mov r3, #16
|
||||
b call_cache_fn
|
||||
--- a/arch/arm/kernel/entry-armv.S
|
||||
+++ b/arch/arm/kernel/entry-armv.S
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <asm/unwind.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/tls.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
#include "entry-header.S"
|
||||
|
||||
@@ -167,7 +168,7 @@ ENDPROC(__und_invalid)
|
||||
stmia r5, {r0 - r4}
|
||||
.endm
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__dabt_svc:
|
||||
svc_entry
|
||||
|
||||
@@ -215,7 +216,7 @@ __dabt_svc:
|
||||
UNWIND(.fnend )
|
||||
ENDPROC(__dabt_svc)
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__irq_svc:
|
||||
svc_entry
|
||||
|
||||
@@ -259,7 +260,7 @@ svc_preempt:
|
||||
b 1b
|
||||
#endif
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__und_svc:
|
||||
#ifdef CONFIG_KPROBES
|
||||
@ If a kprobe is about to simulate a "stmdb sp..." instruction,
|
||||
@@ -305,7 +306,7 @@ __und_svc:
|
||||
UNWIND(.fnend )
|
||||
ENDPROC(__und_svc)
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__pabt_svc:
|
||||
svc_entry
|
||||
|
||||
@@ -341,7 +342,7 @@ __pabt_svc:
|
||||
UNWIND(.fnend )
|
||||
ENDPROC(__pabt_svc)
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
.LCcralign:
|
||||
.word cr_alignment
|
||||
#ifdef MULTI_DABORT
|
||||
@@ -414,7 +415,7 @@ ENDPROC(__pabt_svc)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__dabt_usr:
|
||||
usr_entry
|
||||
kuser_cmpxchg_check
|
||||
@@ -446,7 +447,7 @@ __dabt_usr:
|
||||
UNWIND(.fnend )
|
||||
ENDPROC(__dabt_usr)
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__irq_usr:
|
||||
usr_entry
|
||||
kuser_cmpxchg_check
|
||||
@@ -475,7 +476,7 @@ ENDPROC(__irq_usr)
|
||||
|
||||
.ltorg
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__und_usr:
|
||||
usr_entry
|
||||
|
||||
@@ -691,7 +692,7 @@ __und_usr_unknown:
|
||||
b do_undefinstr
|
||||
ENDPROC(__und_usr_unknown)
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__pabt_usr:
|
||||
usr_entry
|
||||
|
||||
@@ -805,7 +806,7 @@ ENDPROC(__switch_to)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
.globl __kuser_helper_start
|
||||
__kuser_helper_start:
|
||||
|
||||
@@ -845,7 +846,7 @@ __kuser_memory_barrier: @ 0xffff0fa0
|
||||
smp_dmb
|
||||
usr_ret lr
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
|
||||
/*
|
||||
* Reference prototype:
|
||||
@@ -972,7 +973,7 @@ kuser_cmpxchg_fixup:
|
||||
|
||||
#endif
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
|
||||
/*
|
||||
* Reference prototype:
|
||||
@@ -1050,7 +1051,7 @@ __kuser_helper_end:
|
||||
* of which is copied into r0 for the mode specific abort handler.
|
||||
*/
|
||||
.macro vector_stub, name, mode, correction=0
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
|
||||
vector_\name:
|
||||
.if \correction
|
||||
@@ -1181,7 +1182,7 @@ __stubs_start:
|
||||
.long __und_invalid @ e
|
||||
.long __und_invalid @ f
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
|
||||
/*=============================================================================
|
||||
* Undefined FIQs
|
||||
@@ -1211,7 +1212,7 @@ vector_addrexcptn:
|
||||
* We group all the following data together to optimise
|
||||
* for CPUs with separate I & D caches.
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
|
||||
.LCvswi:
|
||||
.word vector_swi
|
||||
--- a/arch/arm/kernel/entry-common.S
|
||||
+++ b/arch/arm/kernel/entry-common.S
|
||||
@@ -10,13 +10,14 @@
|
||||
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/ftrace.h>
|
||||
+#include <asm/cache.h>
|
||||
#include <mach/entry-macro.S>
|
||||
#include <asm/unwind.h>
|
||||
|
||||
#include "entry-header.S"
|
||||
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
/*
|
||||
* This is the fast syscall return path. We do as little as
|
||||
* possible here, and this includes saving r0 back into the SVC
|
||||
@@ -260,7 +261,7 @@ ENDPROC(ftrace_stub)
|
||||
#define A710(code...)
|
||||
#endif
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
ENTRY(vector_swi)
|
||||
sub sp, sp, #S_FRAME_SIZE
|
||||
stmia sp, {r0 - r12} @ Calling r0 - r12
|
||||
@@ -404,7 +405,7 @@ __sys_trace_return:
|
||||
bl syscall_trace
|
||||
b ret_slow_syscall
|
||||
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
#ifdef CONFIG_ALIGNMENT_TRAP
|
||||
.type __cr_alignment, #object
|
||||
__cr_alignment:
|
||||
--- a/arch/arm/kernel/head.S
|
||||
+++ b/arch/arm/kernel/head.S
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <asm/memory.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/system.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
#ifdef CONFIG_DEBUG_LL
|
||||
#include <mach/debug-macro.S>
|
||||
@@ -373,7 +374,7 @@ ENDPROC(__enable_mmu)
|
||||
*
|
||||
* other registers depend on the function called upon completion
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
__turn_mmu_on:
|
||||
mov r0, r0
|
||||
mcr p15, 0, r0, c1, c0, 0 @ write control reg
|
||||
--- a/arch/arm/kernel/vmlinux.lds.S
|
||||
+++ b/arch/arm/kernel/vmlinux.lds.S
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/page.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
#define PROC_INFO \
|
||||
VMLINUX_SYMBOL(__proc_info_begin) = .; \
|
||||
--- a/arch/arm/lib/copy_page.S
|
||||
+++ b/arch/arm/lib/copy_page.S
|
||||
@@ -17,7 +17,7 @@
|
||||
#define COPY_COUNT (PAGE_SZ / (2 * L1_CACHE_BYTES) PLD( -1 ))
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
/*
|
||||
* StrongARM optimised copy_page routine
|
||||
* now 1.78bytes/cycle, was 1.60 bytes/cycle (50MHz bus -> 89MB/s)
|
||||
--- a/arch/arm/lib/memchr.S
|
||||
+++ b/arch/arm/lib/memchr.S
|
||||
@@ -11,9 +11,10 @@
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
ENTRY(memchr)
|
||||
1: subs r2, r2, #1
|
||||
bmi 2f
|
||||
--- a/arch/arm/lib/memset.S
|
||||
+++ b/arch/arm/lib/memset.S
|
||||
@@ -11,9 +11,10 @@
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
.word 0
|
||||
|
||||
1: subs r2, r2, #4 @ 1 do we have enough
|
||||
--- a/arch/arm/lib/memzero.S
|
||||
+++ b/arch/arm/lib/memzero.S
|
||||
@@ -9,9 +9,10 @@
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
.word 0
|
||||
/*
|
||||
* Align the pointer in r0. r3 contains the number of bytes that we are
|
||||
--- a/arch/arm/lib/strchr.S
|
||||
+++ b/arch/arm/lib/strchr.S
|
||||
@@ -11,9 +11,10 @@
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
ENTRY(strchr)
|
||||
and r1, r1, #0xff
|
||||
1: ldrb r2, [r0], #1
|
||||
--- a/arch/arm/lib/strncpy_from_user.S
|
||||
+++ b/arch/arm/lib/strncpy_from_user.S
|
||||
@@ -10,9 +10,10 @@
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/errno.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
|
||||
/*
|
||||
* Copy a string from user space to kernel space.
|
||||
--- a/arch/arm/lib/strnlen_user.S
|
||||
+++ b/arch/arm/lib/strnlen_user.S
|
||||
@@ -10,9 +10,10 @@
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
#include <asm/errno.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
|
||||
/* Prototype: unsigned long __strnlen_user(const char *str, long n)
|
||||
* Purpose : get length of a string in user memory
|
||||
--- a/arch/arm/lib/strrchr.S
|
||||
+++ b/arch/arm/lib/strrchr.S
|
||||
@@ -11,9 +11,10 @@
|
||||
*/
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
+#include <asm/cache.h>
|
||||
|
||||
.text
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
ENTRY(strrchr)
|
||||
mov r3, #0
|
||||
1: ldrb r2, [r0], #1
|
||||
--- a/arch/arm/mm/abort-ev4.S
|
||||
+++ b/arch/arm/mm/abort-ev4.S
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
+#include <asm/cache.h>
|
||||
/*
|
||||
* Function: v4_early_abort
|
||||
*
|
||||
@@ -17,7 +18,7 @@
|
||||
* abort here if the I-TLB and D-TLB aren't seeing the same
|
||||
* picture. Unfortunately, this does happen. We live with it.
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
ENTRY(v4_early_abort)
|
||||
mrc p15, 0, r1, c5, c0, 0 @ get FSR
|
||||
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
||||
--- a/arch/arm/mm/abort-nommu.S
|
||||
+++ b/arch/arm/mm/abort-nommu.S
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/assembler.h>
|
||||
+#include <asm/cache.h>
|
||||
/*
|
||||
* Function: nommu_early_abort
|
||||
*
|
||||
@@ -12,7 +13,7 @@
|
||||
* Note: There is no FSR/FAR on !CPU_CP15_MMU cores.
|
||||
* Just fill zero into the registers.
|
||||
*/
|
||||
- .align 5
|
||||
+ .align L1_CACHE_SHIFT
|
||||
ENTRY(nommu_early_abort)
|
||||
mov r0, #0 @ clear r0, r1 (no FSR/FAR)
|
||||
mov r1, #0
|
|
@ -0,0 +1,24 @@
|
|||
--- a/kernel/printk.c
|
||||
+++ b/kernel/printk.c
|
||||
@@ -48,6 +48,10 @@
|
||||
#define for_each_console(con) \
|
||||
for (con = console_drivers; con != NULL; con = con->next)
|
||||
|
||||
+#ifdef CONFIG_DEBUG_LL
|
||||
+extern void printascii(char *);
|
||||
+#endif /* CONFIG_DEBUG_LL */
|
||||
+
|
||||
/*
|
||||
* Architectures can override it:
|
||||
*/
|
||||
@@ -780,6 +784,10 @@ asmlinkage int vprintk(const char *fmt,
|
||||
}
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_DEBUG_LL
|
||||
+ printascii(printk_buf);
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Copy the output into log_buf. If the caller didn't provide
|
||||
* appropriate log level tags, we insert them here
|
|
@ -0,0 +1,47 @@
|
|||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -975,10 +975,15 @@ source "arch/arm/mach-vexpress/Kconfig"
|
||||
|
||||
source "arch/arm/mach-w90x900/Kconfig"
|
||||
|
||||
+source "arch/arm/plat-fa/Kconfig"
|
||||
+
|
||||
# Definitions to make life easier
|
||||
config ARCH_ACORN
|
||||
bool
|
||||
|
||||
+config PLAT_FA
|
||||
+ bool
|
||||
+
|
||||
config PLAT_IOP
|
||||
bool
|
||||
select GENERIC_CLOCKEVENTS
|
||||
--- a/arch/arm/Makefile
|
||||
+++ b/arch/arm/Makefile
|
||||
@@ -204,6 +204,7 @@ plat-$(CONFIG_ARCH_OMAP) := omap
|
||||
plat-$(CONFIG_ARCH_S3C64XX) := samsung
|
||||
plat-$(CONFIG_ARCH_STMP3XXX) := stmp3xxx
|
||||
plat-$(CONFIG_ARCH_TCC_926) := tcc
|
||||
+plat-$(CONFIG_PLAT_FA) := fa
|
||||
plat-$(CONFIG_PLAT_IOP) := iop
|
||||
plat-$(CONFIG_PLAT_NOMADIK) := nomadik
|
||||
plat-$(CONFIG_PLAT_ORION) := orion
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/plat-fa/Makefile
|
||||
@@ -0,0 +1,10 @@
|
||||
+#
|
||||
+# Makefile for the linux kernel.
|
||||
+#
|
||||
+
|
||||
+obj-y :=
|
||||
+
|
||||
+obj-m :=
|
||||
+obj-n :=
|
||||
+obj- :=
|
||||
+
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/plat-fa/Kconfig
|
||||
@@ -0,0 +1,3 @@
|
||||
+if PLAT_FA
|
||||
+
|
||||
+endif
|
|
@ -0,0 +1,143 @@
|
|||
--- /dev/null
|
||||
+++ b/arch/arm/plat-fa/include/plat/time.h
|
||||
@@ -0,0 +1,20 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#ifndef _FA_TIME_H
|
||||
+#define _FA_TIME_H
|
||||
+
|
||||
+#define FA_TIMER1 0
|
||||
+#define FA_TIMER2 1
|
||||
+#define FA_TIMER3 2
|
||||
+
|
||||
+int __init fa_timer_init(unsigned int mapbase, unsigned int irq,
|
||||
+ unsigned int timer, unsigned int freq);
|
||||
+
|
||||
+#endif /* _FA_TIME_H */
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/plat-fa/time.c
|
||||
@@ -0,0 +1,97 @@
|
||||
+/*
|
||||
+ * Copyright (C) 2001-2006 Storlink, Corp.
|
||||
+ * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <linux/io.h>
|
||||
+
|
||||
+#include <asm/mach/time.h>
|
||||
+#include <plat/time.h>
|
||||
+
|
||||
+/*
|
||||
+ * Register definitions for the timers
|
||||
+ */
|
||||
+#define TIMER_COUNT(_base, _tmr) ((_base) + 0x00 + (_tmr) * 0x10)
|
||||
+#define TIMER_LOAD(_base, _tmr) ((_base) + 0x04 + (_tmr) * 0x10)
|
||||
+#define TIMER_MATCH1(_base, _tmr) ((_base) + 0x08 + (_tmr) * 0x10)
|
||||
+#define TIMER_MATCH2(_base, _tmr) ((_base) + 0x0c + (_tmr) * 0x10)
|
||||
+
|
||||
+#define TIMER_CR(_base) ((_base) + 0x30)
|
||||
+#define TIMER_STATUS(_base) ((_base) + 0x34)
|
||||
+#define TIMER_MASK(_base) ((_base) + 0x38)
|
||||
+
|
||||
+#define TIMER_SIZE 0x3c
|
||||
+
|
||||
+#define TIMER_CR_ENABLE(x) (1 << ((x) * 3))
|
||||
+#define TIMER_CR_CLOCK(x) (1 << ((x) * 3 + 1))
|
||||
+#define TIMER_CR_INT(x) (1 << ((x) * 3 + 2))
|
||||
+#define TIMER_CR_DOWN(x) (1 << ((x) * 3 + 9))
|
||||
+
|
||||
+#define TIMER_MASK_MATCH1(x) (1 << ((x) * 3))
|
||||
+#define TIMER_MASK_MATCH2(x) (1 << ((x) * 3 + 1))
|
||||
+#define TIMER_MASK_OF(x) (1 << ((x) * 3 + 2))
|
||||
+
|
||||
+#define TIMER_MASK_ALL 0x7ff
|
||||
+
|
||||
+/*
|
||||
+ * IRQ handler for the timer
|
||||
+ */
|
||||
+static irqreturn_t fa_timer_interrupt(int irq, void *dev_id)
|
||||
+{
|
||||
+ timer_tick();
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static struct irqaction fa_timer_irq = {
|
||||
+ .name = "Timer Tick",
|
||||
+ .flags = IRQF_DISABLED | IRQF_TIMER,
|
||||
+ .handler = fa_timer_interrupt,
|
||||
+};
|
||||
+
|
||||
+int __init fa_timer_init(unsigned int mapbase, unsigned int irq,
|
||||
+ unsigned int timer, unsigned int freq)
|
||||
+{
|
||||
+ void __iomem *base;
|
||||
+
|
||||
+ base = ioremap(mapbase, TIMER_SIZE);
|
||||
+ if (!base)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ /* disable timers, clear status and mask all interrupts */
|
||||
+ __raw_writel(0, TIMER_CR(base));
|
||||
+ __raw_writel(0, TIMER_STATUS(base));
|
||||
+ __raw_writel(TIMER_MASK_ALL, TIMER_MASK(base));
|
||||
+
|
||||
+ /*
|
||||
+ * Make irqs happen for the system timer
|
||||
+ */
|
||||
+ setup_irq(irq, &fa_timer_irq);
|
||||
+
|
||||
+ /* Setup the timer */
|
||||
+ __raw_writel(freq / HZ, TIMER_COUNT(base, timer));
|
||||
+ __raw_writel(freq / HZ, TIMER_LOAD(base, timer));
|
||||
+ __raw_writel(0, TIMER_MATCH1(base, timer));
|
||||
+ __raw_writel(0, TIMER_MATCH2(base, timer));
|
||||
+
|
||||
+ /* Enable interrupt and start the timer */
|
||||
+ __raw_writel(TIMER_MASK_ALL & ~TIMER_MASK_OF(timer),
|
||||
+ TIMER_MASK(base));
|
||||
+
|
||||
+ __raw_writel(TIMER_CR_ENABLE(timer) |
|
||||
+ TIMER_CR_INT(timer) |
|
||||
+ TIMER_CR_DOWN(timer),
|
||||
+ TIMER_CR(base));
|
||||
+
|
||||
+ iounmap(base);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
--- a/arch/arm/plat-fa/Kconfig
|
||||
+++ b/arch/arm/plat-fa/Kconfig
|
||||
@@ -1,3 +1,6 @@
|
||||
if PLAT_FA
|
||||
|
||||
+config PLAT_FA_TIME
|
||||
+ def_bool n
|
||||
+
|
||||
endif
|
||||
--- a/arch/arm/plat-fa/Makefile
|
||||
+++ b/arch/arm/plat-fa/Makefile
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
obj-y :=
|
||||
|
||||
+obj-$(CONFIG_PLAT_FA_TIME) += time.o
|
||||
+
|
||||
obj-m :=
|
||||
obj-n :=
|
||||
obj- :=
|
|
@ -0,0 +1,335 @@
|
|||
--- /dev/null
|
||||
+++ b/arch/arm/plat-fa/gpio.c
|
||||
@@ -0,0 +1,275 @@
|
||||
+/*
|
||||
+ * Gpiochip and interrupt routines for Faraday FA526 based SoCs
|
||||
+ *
|
||||
+ * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
|
||||
+ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * Based on plat-mxc/gpio.c:
|
||||
+ * MXC GPIO supchip. (c) 2008 Daniel Mack <daniel@caiaq.de>
|
||||
+ * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License as published by
|
||||
+ * the Free Software Foundation; either version 2 of the License, or
|
||||
+ * (at your option) any later version.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/spinlock.h>
|
||||
+
|
||||
+#include <plat/gpio.h>
|
||||
+
|
||||
+#define GPIO_DATA_OUT 0x0
|
||||
+#define GPIO_DATA_IN 0x4
|
||||
+#define GPIO_DIR 0x8
|
||||
+#define GPIO_DATA_SET 0x10
|
||||
+#define GPIO_DATA_CLR 0x14
|
||||
+#define GPIO_PULL_EN 0x18
|
||||
+#define GPIO_PULL_TYPE 0x1C
|
||||
+#define GPIO_INT_EN 0x20
|
||||
+#define GPIO_INT_STAT 0x24
|
||||
+#define GPIO_INT_MASK 0x2C
|
||||
+#define GPIO_INT_CLR 0x30
|
||||
+#define GPIO_INT_TYPE 0x34
|
||||
+#define GPIO_INT_BOTH_EDGE 0x38
|
||||
+#define GPIO_INT_LEVEL 0x3C
|
||||
+#define GPIO_DEBOUNCE_EN 0x40
|
||||
+#define GPIO_DEBOUNCE_PRESCALE 0x44
|
||||
+
|
||||
+#define GPIO_REGS_SIZE 0x48
|
||||
+
|
||||
+static DEFINE_SPINLOCK(fa_gpio_lock);
|
||||
+
|
||||
+static inline struct fa_gpio_chip *to_fgc(struct gpio_chip *chip)
|
||||
+{
|
||||
+ return container_of(chip, struct fa_gpio_chip, gpio_chip);
|
||||
+}
|
||||
+
|
||||
+static void _fa_gpio_irq_setenable(unsigned int irq, int enable)
|
||||
+{
|
||||
+ struct fa_gpio_chip *fgc = get_irq_chip_data(irq);
|
||||
+ void __iomem *base = fgc->mem_base;
|
||||
+ unsigned int gpio = irq - fgc->irq_base;
|
||||
+ unsigned int reg;
|
||||
+
|
||||
+ reg = __raw_readl(base + GPIO_INT_EN);
|
||||
+ reg = (reg & (~(1 << gpio))) | (!!enable << gpio);
|
||||
+ __raw_writel(reg, base + GPIO_INT_EN);
|
||||
+}
|
||||
+
|
||||
+static void fa_gpio_irq_ack(unsigned int irq)
|
||||
+{
|
||||
+ struct fa_gpio_chip *fgc = get_irq_chip_data(irq);
|
||||
+ unsigned int gpio = irq - fgc->irq_base;
|
||||
+
|
||||
+ __raw_writel(1 << gpio, fgc->mem_base + GPIO_INT_CLR);
|
||||
+}
|
||||
+
|
||||
+static void fa_gpio_irq_mask(unsigned int irq)
|
||||
+{
|
||||
+ _fa_gpio_irq_setenable(irq, 0);
|
||||
+}
|
||||
+
|
||||
+static void fa_gpio_irq_unmask(unsigned int irq)
|
||||
+{
|
||||
+ _fa_gpio_irq_setenable(irq, 1);
|
||||
+}
|
||||
+
|
||||
+static int fa_gpio_irq_set_type(unsigned int irq, unsigned int type)
|
||||
+{
|
||||
+ struct fa_gpio_chip *fgc = get_irq_chip_data(irq);
|
||||
+ void __iomem *base = fgc->mem_base;
|
||||
+ unsigned int gpio = irq - fgc->irq_base;
|
||||
+ unsigned int gpio_mask = 1 << gpio;
|
||||
+ unsigned int reg_both, reg_level, reg_type;
|
||||
+
|
||||
+ reg_type = __raw_readl(base + GPIO_INT_TYPE);
|
||||
+ reg_level = __raw_readl(base + GPIO_INT_LEVEL);
|
||||
+ reg_both = __raw_readl(base + GPIO_INT_BOTH_EDGE);
|
||||
+
|
||||
+ switch (type) {
|
||||
+ case IRQ_TYPE_EDGE_BOTH:
|
||||
+ reg_type &= ~gpio_mask;
|
||||
+ reg_both |= gpio_mask;
|
||||
+ break;
|
||||
+ case IRQ_TYPE_EDGE_RISING:
|
||||
+ reg_type &= ~gpio_mask;
|
||||
+ reg_both &= ~gpio_mask;
|
||||
+ reg_level &= ~gpio_mask;
|
||||
+ break;
|
||||
+ case IRQ_TYPE_EDGE_FALLING:
|
||||
+ reg_type &= ~gpio_mask;
|
||||
+ reg_both &= ~gpio_mask;
|
||||
+ reg_level |= gpio_mask;
|
||||
+ break;
|
||||
+ case IRQ_TYPE_LEVEL_HIGH:
|
||||
+ reg_type |= gpio_mask;
|
||||
+ reg_level &= ~gpio_mask;
|
||||
+ break;
|
||||
+ case IRQ_TYPE_LEVEL_LOW:
|
||||
+ reg_type |= gpio_mask;
|
||||
+ reg_level |= gpio_mask;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ __raw_writel(reg_type, base + GPIO_INT_TYPE);
|
||||
+ __raw_writel(reg_level, base + GPIO_INT_LEVEL);
|
||||
+ __raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE);
|
||||
+
|
||||
+ fa_gpio_irq_ack(irq);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void fa_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
||||
+{
|
||||
+ struct fa_gpio_data *data = get_irq_data(irq);
|
||||
+ unsigned int chip;
|
||||
+
|
||||
+ for (chip = 0; chip < data->nchips; chip++) {
|
||||
+ struct fa_gpio_chip *fgc = &data->chips[chip];
|
||||
+ unsigned int status;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ status = __raw_readl(fgc->mem_base + GPIO_INT_STAT);
|
||||
+ for (i = fgc->irq_base; status != 0; status >>= 1, i++) {
|
||||
+ if ((status & 1) == 0)
|
||||
+ continue;
|
||||
+
|
||||
+ BUG_ON(!(irq_desc[i].handle_irq));
|
||||
+ irq_desc[i].handle_irq(i, &irq_desc[i]);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static struct irq_chip fa_gpio_irq_chip = {
|
||||
+ .name = "GPIO",
|
||||
+ .ack = fa_gpio_irq_ack,
|
||||
+ .mask = fa_gpio_irq_mask,
|
||||
+ .unmask = fa_gpio_irq_unmask,
|
||||
+ .set_type = fa_gpio_irq_set_type,
|
||||
+};
|
||||
+
|
||||
+static void _fa_gpio_set_direction(struct fa_gpio_chip *fgc, unsigned offset,
|
||||
+ int is_output)
|
||||
+{
|
||||
+ unsigned int reg;
|
||||
+
|
||||
+ reg = __raw_readl(fgc->mem_base + GPIO_DIR);
|
||||
+ if (is_output)
|
||||
+ reg |= 1 << offset;
|
||||
+ else
|
||||
+ reg &= ~(1 << offset);
|
||||
+ __raw_writel(reg, fgc->mem_base + GPIO_DIR);
|
||||
+}
|
||||
+
|
||||
+static void _fa_gpio_set(struct fa_gpio_chip *fgc, unsigned offset, int value)
|
||||
+{
|
||||
+ if (value)
|
||||
+ __raw_writel(1 << offset, fgc->mem_base + GPIO_DATA_SET);
|
||||
+ else
|
||||
+ __raw_writel(1 << offset, fgc->mem_base + GPIO_DATA_CLR);
|
||||
+}
|
||||
+
|
||||
+static void fa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
||||
+{
|
||||
+ struct fa_gpio_chip *fgc = to_fgc(chip);
|
||||
+
|
||||
+ _fa_gpio_set(fgc, offset, value);
|
||||
+}
|
||||
+
|
||||
+static int fa_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
+{
|
||||
+ struct fa_gpio_chip *fgc = to_fgc(chip);
|
||||
+
|
||||
+ return (__raw_readl(fgc->mem_base + GPIO_DATA_IN) >> offset) & 1;
|
||||
+}
|
||||
+
|
||||
+static int fa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
+{
|
||||
+ struct fa_gpio_chip *fgc = to_fgc(chip);
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&fa_gpio_lock, flags);
|
||||
+
|
||||
+ _fa_gpio_set_direction(fgc, offset, 0);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&fa_gpio_lock, flags);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int fa_gpio_direction_output(struct gpio_chip *chip,
|
||||
+ unsigned offset,
|
||||
+ int value)
|
||||
+{
|
||||
+ struct fa_gpio_chip *fgc = to_fgc(chip);
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&fa_gpio_lock, flags);
|
||||
+
|
||||
+ _fa_gpio_set(fgc, offset, value);
|
||||
+ _fa_gpio_set_direction(fgc, offset, 1);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&fa_gpio_lock, flags);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int fa_gpio_init_chip(struct fa_gpio_chip *fgc)
|
||||
+{
|
||||
+ void __iomem *mem_base;
|
||||
+ unsigned int i;
|
||||
+ int err;
|
||||
+
|
||||
+ mem_base = ioremap(fgc->map_base, GPIO_REGS_SIZE);
|
||||
+ if (!mem_base)
|
||||
+ return -ENXIO;
|
||||
+
|
||||
+ fgc->mem_base = mem_base;
|
||||
+
|
||||
+ fgc->gpio_chip.direction_input = fa_gpio_direction_input;
|
||||
+ fgc->gpio_chip.direction_output = fa_gpio_direction_output;
|
||||
+ fgc->gpio_chip.get = fa_gpio_get;
|
||||
+ fgc->gpio_chip.set = fa_gpio_set;
|
||||
+
|
||||
+ /* disable, unmask and clear all interrupts */
|
||||
+ __raw_writel(0x0, mem_base + GPIO_INT_EN);
|
||||
+ __raw_writel(0x0, mem_base + GPIO_INT_MASK);
|
||||
+ __raw_writel(~0x0, mem_base + GPIO_INT_CLR);
|
||||
+
|
||||
+ for (i = fgc->irq_base;
|
||||
+ i < fgc->irq_base + fgc->gpio_chip.ngpio; i++) {
|
||||
+ set_irq_chip(i, &fa_gpio_irq_chip);
|
||||
+ set_irq_chip_data(i, fgc);
|
||||
+ set_irq_handler(i, handle_edge_irq);
|
||||
+ set_irq_flags(i, IRQF_VALID);
|
||||
+ }
|
||||
+
|
||||
+ err = gpiochip_add(&fgc->gpio_chip);
|
||||
+ if (err)
|
||||
+ goto unmap;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+ unmap:
|
||||
+ iounmap(fgc->mem_base);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+void __init fa_gpio_init(struct fa_gpio_data *data)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ for (i = 0; i < data->nchips; i++) {
|
||||
+ int err;
|
||||
+
|
||||
+ err = fa_gpio_init_chip(&data->chips[i]);
|
||||
+ if (WARN(err, "GPIO init failed\n"))
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ set_irq_chained_handler(data->irq, fa_gpio_irq_handler);
|
||||
+ set_irq_data(data->irq, data);
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/plat-fa/include/plat/gpio.h
|
||||
@@ -0,0 +1,33 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file 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 _FA_GPIO_H
|
||||
+#define _FA_GPIO_H
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <linux/io.h>
|
||||
+
|
||||
+struct fa_gpio_chip {
|
||||
+ struct gpio_chip gpio_chip;
|
||||
+ unsigned int map_base;
|
||||
+ unsigned int irq_base;
|
||||
+
|
||||
+ void __iomem *mem_base;
|
||||
+};
|
||||
+
|
||||
+struct fa_gpio_data {
|
||||
+ struct fa_gpio_chip *chips;
|
||||
+ unsigned int nchips;
|
||||
+ unsigned int irq;
|
||||
+};
|
||||
+
|
||||
+void __init fa_gpio_init(struct fa_gpio_data *data);
|
||||
+
|
||||
+#endif /* _FA_GPIO_H */
|
||||
--- a/arch/arm/plat-fa/Kconfig
|
||||
+++ b/arch/arm/plat-fa/Kconfig
|
||||
@@ -1,5 +1,8 @@
|
||||
if PLAT_FA
|
||||
|
||||
+config PLAT_FA_GPIO
|
||||
+ def_bool n
|
||||
+
|
||||
config PLAT_FA_TIME
|
||||
def_bool n
|
||||
|
||||
--- a/arch/arm/plat-fa/Makefile
|
||||
+++ b/arch/arm/plat-fa/Makefile
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
obj-y :=
|
||||
|
||||
+obj-$(CONFIG_PLAT_FA_GPIO) += gpio.o
|
||||
obj-$(CONFIG_PLAT_FA_TIME) += time.o
|
||||
|
||||
obj-m :=
|
|
@ -0,0 +1,456 @@
|
|||
--- a/drivers/watchdog/Kconfig
|
||||
+++ b/drivers/watchdog/Kconfig
|
||||
@@ -331,6 +331,13 @@ config IMX2_WDT
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imx2_wdt.
|
||||
|
||||
+config FA_WATCHDOG
|
||||
+ tristate "Faraday watchdog"
|
||||
+ depends on ARCH_GEMINI
|
||||
+ help
|
||||
+ Say Y here if you want support for the built-in watchdog timer
|
||||
+ found in some Faraday FA526 based SoCs.
|
||||
+
|
||||
# AVR32 Architecture
|
||||
|
||||
config AT32AP700X_WDT
|
||||
--- a/drivers/watchdog/Makefile
|
||||
+++ b/drivers/watchdog/Makefile
|
||||
@@ -49,6 +49,7 @@ obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_
|
||||
obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o
|
||||
obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
|
||||
obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
|
||||
+obj-$(CONFIG_FA_WATCHDOG) += fa_wdt.o
|
||||
|
||||
# AVR32 Architecture
|
||||
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/watchdog/fa_wdt.c
|
||||
@@ -0,0 +1,411 @@
|
||||
+/*
|
||||
+ * Watchdog driver for SoCs based on the Faraday FA526 core
|
||||
+ *
|
||||
+ * Copyright (C) 2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
|
||||
+ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License version 2 as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/fs.h>
|
||||
+#include <linux/notifier.h>
|
||||
+#include <linux/reboot.h>
|
||||
+#include <linux/uaccess.h>
|
||||
+#include <linux/miscdevice.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/watchdog.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/fa_wdt.h>
|
||||
+
|
||||
+#define FA_WDCOUNTER 0x0
|
||||
+#define FA_WDLOAD 0x4
|
||||
+#define FA_WDRESTART 0x8
|
||||
+
|
||||
+#define WDRESTART_MAGIC 0x5AB9
|
||||
+
|
||||
+#define FA_WDCR 0xC
|
||||
+
|
||||
+#define WDCR_CLOCK_5MHZ (1 << 4)
|
||||
+#define WDCR_SYS_RST (1 << 1)
|
||||
+#define WDCR_ENABLE (1 << 0)
|
||||
+
|
||||
+#define WDT_DEFAULT_TIMEOUT 13
|
||||
+
|
||||
+/* status bits */
|
||||
+#define WDT_ACTIVE 0
|
||||
+#define WDT_OK_TO_CLOSE 1
|
||||
+
|
||||
+static unsigned int timeout = WDT_DEFAULT_TIMEOUT;
|
||||
+static int nowayout = WATCHDOG_NOWAYOUT;
|
||||
+
|
||||
+static DEFINE_SPINLOCK(fa_wdt_lock);
|
||||
+
|
||||
+static struct platform_device *fa_wdt_dev;
|
||||
+
|
||||
+struct fa_wdt_struct {
|
||||
+ struct resource *res;
|
||||
+ struct device *dev;
|
||||
+ void __iomem *base;
|
||||
+ unsigned long status;
|
||||
+ unsigned int clock;
|
||||
+ unsigned int max_timeout;
|
||||
+};
|
||||
+
|
||||
+static const struct watchdog_info fa_wdt_info = {
|
||||
+ .identity = "Faraday watchdog",
|
||||
+ .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING |
|
||||
+ WDIOF_SETTIMEOUT,
|
||||
+};
|
||||
+
|
||||
+/* Disable the watchdog. */
|
||||
+static void fa_wdt_stop(struct fa_wdt_struct *fa_wdt)
|
||||
+{
|
||||
+ spin_lock(&fa_wdt_lock);
|
||||
+
|
||||
+ __raw_writel(0, fa_wdt->base + FA_WDCR);
|
||||
+
|
||||
+ clear_bit(WDT_ACTIVE, &fa_wdt->status);
|
||||
+
|
||||
+ spin_unlock(&fa_wdt_lock);
|
||||
+}
|
||||
+
|
||||
+/* Service the watchdog */
|
||||
+static void fa_wdt_service(struct fa_wdt_struct *fa_wdt)
|
||||
+{
|
||||
+ __raw_writel(WDRESTART_MAGIC, fa_wdt->base + FA_WDRESTART);
|
||||
+}
|
||||
+
|
||||
+/* Enable and reset the watchdog. */
|
||||
+static void fa_wdt_start(struct fa_wdt_struct *fa_wdt)
|
||||
+{
|
||||
+ spin_lock(&fa_wdt_lock);
|
||||
+
|
||||
+ __raw_writel(timeout * fa_wdt->clock,
|
||||
+ fa_wdt->base + FA_WDLOAD);
|
||||
+
|
||||
+ fa_wdt_service(fa_wdt);
|
||||
+
|
||||
+ /* set clock before enabling */
|
||||
+ __raw_writel(WDCR_CLOCK_5MHZ | WDCR_SYS_RST,
|
||||
+ fa_wdt->base + FA_WDCR);
|
||||
+
|
||||
+ __raw_writel(WDCR_CLOCK_5MHZ | WDCR_SYS_RST | WDCR_ENABLE,
|
||||
+ fa_wdt->base + FA_WDCR);
|
||||
+
|
||||
+ set_bit(WDT_ACTIVE, &fa_wdt->status);
|
||||
+
|
||||
+ spin_unlock(&fa_wdt_lock);
|
||||
+}
|
||||
+
|
||||
+/* Watchdog device is opened, and watchdog starts running. */
|
||||
+static int fa_wdt_open(struct inode *inode, struct file *file)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = platform_get_drvdata(fa_wdt_dev);
|
||||
+
|
||||
+ if (test_bit(WDT_ACTIVE, &fa_wdt->status))
|
||||
+ return -EBUSY;
|
||||
+
|
||||
+ file->private_data = fa_wdt;
|
||||
+
|
||||
+ fa_wdt_start(fa_wdt);
|
||||
+
|
||||
+ return nonseekable_open(inode, file);
|
||||
+}
|
||||
+
|
||||
+/* Close the watchdog device. */
|
||||
+static int fa_wdt_close(struct inode *inode, struct file *file)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = file->private_data;
|
||||
+
|
||||
+ /* Disable the watchdog if possible */
|
||||
+ if (test_bit(WDT_OK_TO_CLOSE, &fa_wdt->status))
|
||||
+ fa_wdt_stop(fa_wdt);
|
||||
+ else
|
||||
+ dev_warn(fa_wdt->dev, "Device closed unexpectedly - timer will not stop\n");
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* Handle commands from user-space. */
|
||||
+static long fa_wdt_ioctl(struct file *file, unsigned int cmd,
|
||||
+ unsigned long arg)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = file->private_data;
|
||||
+
|
||||
+ int value;
|
||||
+
|
||||
+ switch (cmd) {
|
||||
+ case WDIOC_KEEPALIVE:
|
||||
+ fa_wdt_service(fa_wdt);
|
||||
+ return 0;
|
||||
+
|
||||
+ case WDIOC_GETSUPPORT:
|
||||
+ return copy_to_user((struct watchdog_info *)arg, &fa_wdt_info,
|
||||
+ sizeof(fa_wdt_info)) ? -EFAULT : 0;
|
||||
+
|
||||
+ case WDIOC_SETTIMEOUT:
|
||||
+ if (get_user(value, (int *)arg))
|
||||
+ return -EFAULT;
|
||||
+
|
||||
+ if ((value < 1) || (value > fa_wdt->max_timeout))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ timeout = value;
|
||||
+
|
||||
+ /* restart wdt to use new timeout */
|
||||
+ fa_wdt_stop(fa_wdt);
|
||||
+ fa_wdt_start(fa_wdt);
|
||||
+
|
||||
+ /* Fall through */
|
||||
+ case WDIOC_GETTIMEOUT:
|
||||
+ return put_user(timeout, (int *)arg);
|
||||
+
|
||||
+ case WDIOC_GETTIMELEFT:
|
||||
+ value = __raw_readl(fa_wdt->base + FA_WDCOUNTER);
|
||||
+ return put_user(value / fa_wdt->clock, (int *)arg);
|
||||
+
|
||||
+ default:
|
||||
+ return -ENOTTY;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/* Refresh the watchdog whenever device is written to. */
|
||||
+static ssize_t fa_wdt_write(struct file *file, const char *data,
|
||||
+ size_t len, loff_t *ppos)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = file->private_data;
|
||||
+
|
||||
+ if (len) {
|
||||
+ if (!nowayout) {
|
||||
+ size_t i;
|
||||
+
|
||||
+ clear_bit(WDT_OK_TO_CLOSE, &fa_wdt->status);
|
||||
+ for (i = 0; i != len; i++) {
|
||||
+ char c;
|
||||
+
|
||||
+ if (get_user(c, data + i))
|
||||
+ return -EFAULT;
|
||||
+ if (c == 'V')
|
||||
+ set_bit(WDT_OK_TO_CLOSE,
|
||||
+ &fa_wdt->status);
|
||||
+ }
|
||||
+ }
|
||||
+ fa_wdt_service(fa_wdt);
|
||||
+ }
|
||||
+
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+static int fa_wdt_notify_sys(struct notifier_block *this,
|
||||
+ unsigned long code, void *unused)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = platform_get_drvdata(fa_wdt_dev);
|
||||
+
|
||||
+ if (code == SYS_DOWN || code == SYS_HALT)
|
||||
+ fa_wdt_stop(fa_wdt);
|
||||
+
|
||||
+ return NOTIFY_DONE;
|
||||
+}
|
||||
+
|
||||
+static struct notifier_block fa_wdt_notifier = {
|
||||
+ .notifier_call = fa_wdt_notify_sys,
|
||||
+};
|
||||
+
|
||||
+static const struct file_operations fa_wdt_fops = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .llseek = no_llseek,
|
||||
+ .unlocked_ioctl = fa_wdt_ioctl,
|
||||
+ .open = fa_wdt_open,
|
||||
+ .release = fa_wdt_close,
|
||||
+ .write = fa_wdt_write,
|
||||
+};
|
||||
+
|
||||
+static struct miscdevice fa_wdt_miscdev = {
|
||||
+ .minor = WATCHDOG_MINOR,
|
||||
+ .name = "watchdog",
|
||||
+ .fops = &fa_wdt_fops,
|
||||
+};
|
||||
+
|
||||
+static void fa_wdt_shutdown(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ fa_wdt_stop(fa_wdt);
|
||||
+}
|
||||
+
|
||||
+static int __devinit fa_wdt_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ int ret;
|
||||
+ int res_size;
|
||||
+ struct resource *res;
|
||||
+ void __iomem *base;
|
||||
+ struct fa_wdt_struct *fa_wdt;
|
||||
+ struct fa_wdt_platform_data *pdata;
|
||||
+
|
||||
+ pdata = pdev->dev.platform_data;
|
||||
+ if (!pdata) {
|
||||
+ dev_err(&pdev->dev, "no platform data specified\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (!pdata->clock) {
|
||||
+ dev_err(&pdev->dev, "invalid clock value\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ if (!res) {
|
||||
+ dev_err(&pdev->dev, "can't get device resources\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ res_size = resource_size(res);
|
||||
+ if (!request_mem_region(res->start, res_size, res->name)) {
|
||||
+ dev_err(&pdev->dev, "can't allocate %d bytes at %d address\n",
|
||||
+ res_size, res->start);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ base = ioremap(res->start, res_size);
|
||||
+ if (!base) {
|
||||
+ dev_err(&pdev->dev, "ioremap failed\n");
|
||||
+ ret = -EIO;
|
||||
+ goto fail0;
|
||||
+ }
|
||||
+
|
||||
+ fa_wdt = kzalloc(sizeof(struct fa_wdt_struct), GFP_KERNEL);
|
||||
+ if (!fa_wdt) {
|
||||
+ dev_err(&pdev->dev, "can't allocate interface\n");
|
||||
+ ret = -ENOMEM;
|
||||
+ goto fail1;
|
||||
+ }
|
||||
+
|
||||
+ /* Setup fa_wdt driver structure */
|
||||
+ fa_wdt->base = base;
|
||||
+ fa_wdt->res = res;
|
||||
+ fa_wdt->dev = &pdev->dev;
|
||||
+ fa_wdt->clock = pdata->clock;
|
||||
+ fa_wdt->max_timeout = 0xffffffffU / pdata->clock;
|
||||
+
|
||||
+ /* Set up platform driver data */
|
||||
+ platform_set_drvdata(pdev, fa_wdt);
|
||||
+ fa_wdt_dev = pdev;
|
||||
+
|
||||
+ if (fa_wdt_miscdev.parent) {
|
||||
+ ret = -EBUSY;
|
||||
+ goto fail2;
|
||||
+ }
|
||||
+
|
||||
+ ret = register_reboot_notifier(&fa_wdt_notifier);
|
||||
+ if (ret)
|
||||
+ goto fail2;
|
||||
+
|
||||
+ fa_wdt_miscdev.parent = &pdev->dev;
|
||||
+
|
||||
+ ret = misc_register(&fa_wdt_miscdev);
|
||||
+ if (ret)
|
||||
+ goto fail3;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+fail3:
|
||||
+ unregister_reboot_notifier(&fa_wdt_notifier);
|
||||
+fail2:
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
+ kfree(fa_wdt);
|
||||
+fail1:
|
||||
+ iounmap(base);
|
||||
+fail0:
|
||||
+ release_mem_region(res->start, res_size);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int __devexit fa_wdt_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
+ misc_deregister(&fa_wdt_miscdev);
|
||||
+ unregister_reboot_notifier(&fa_wdt_notifier);
|
||||
+ fa_wdt_dev = NULL;
|
||||
+ iounmap(fa_wdt->base);
|
||||
+ release_mem_region(fa_wdt->res->start, resource_size(fa_wdt->res));
|
||||
+
|
||||
+ kfree(fa_wdt);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#ifdef CONFIG_PM
|
||||
+static int fa_wdt_suspend(struct platform_device *pdev, pm_message_t message)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = platform_get_drvdata(pdev);
|
||||
+ unsigned int reg;
|
||||
+
|
||||
+ reg = __raw_readw(fa_wdt->base + FA_WDCR);
|
||||
+ reg &= ~(WDCR_WDENABLE);
|
||||
+ __raw_writel(reg, fa_wdt->base + FA_WDCR);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int fa_wdt_resume(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct fa_wdt_struct *fa_wdt = platform_get_drvdata(pdev);
|
||||
+ unsigned int reg;
|
||||
+
|
||||
+ if (fa_wdt->status) {
|
||||
+ reg = __raw_readw(fa_wdt->base + FA_WDCR);
|
||||
+ reg |= WDCR_WDENABLE;
|
||||
+ __raw_writel(reg, fa_wdt->base + FA_WDCR);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+#else
|
||||
+#define fa_wdt_suspend NULL
|
||||
+#define fa_wdt_resume NULL
|
||||
+#endif
|
||||
+
|
||||
+static struct platform_driver fa_wdt_driver = {
|
||||
+ .probe = fa_wdt_probe,
|
||||
+ .remove = __devexit_p(fa_wdt_remove),
|
||||
+ .shutdown = fa_wdt_shutdown,
|
||||
+ .suspend = fa_wdt_suspend,
|
||||
+ .resume = fa_wdt_resume,
|
||||
+ .driver = {
|
||||
+ .name = "fa-wdt",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init fa_wdt_init(void)
|
||||
+{
|
||||
+ return platform_driver_probe(&fa_wdt_driver, fa_wdt_probe);
|
||||
+}
|
||||
+
|
||||
+static void __exit fa_wdt_exit(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&fa_wdt_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(fa_wdt_init);
|
||||
+module_exit(fa_wdt_exit);
|
||||
+
|
||||
+module_param(timeout, uint, 0);
|
||||
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds");
|
||||
+
|
||||
+module_param(nowayout, int, 0);
|
||||
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
|
||||
+
|
||||
+MODULE_AUTHOR("Paulius Zaleckas");
|
||||
+MODULE_DESCRIPTION("Watchdog driver for Faraday FA526 based SoCs");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
|
||||
+MODULE_ALIAS("platform:fa-wdt");
|
||||
--- /dev/null
|
||||
+++ b/include/linux/fa_wdt.h
|
||||
@@ -0,0 +1,13 @@
|
||||
+/*
|
||||
+ * Platform data definition for the Faraday watchdog driver
|
||||
+ */
|
||||
+
|
||||
+#ifndef _FA_WDT_H
|
||||
+#define _FA_WDT_H
|
||||
+
|
||||
+struct fa_wdt_platform_data {
|
||||
+ unsigned int clock;
|
||||
+};
|
||||
+
|
||||
+#endif /* _FA_WDT_H */
|
||||
+
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,103 @@
|
|||
--- a/arch/arm/mach-cns21xx/common.h
|
||||
+++ b/arch/arm/mach-cns21xx/common.h
|
||||
@@ -15,4 +15,7 @@ void __init cns21xx_init_irq(void);
|
||||
|
||||
extern struct sys_timer cns21xx_timer;
|
||||
|
||||
+int __init cns21xx_register_uart0(void);
|
||||
+int __init cns21xx_register_uart1(void);
|
||||
+
|
||||
#endif /* _MACH_CNS21XX_COMMON_H */
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/devices.c
|
||||
@@ -0,0 +1,79 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2008 Cavium Networks
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/serial_8250.h>
|
||||
+
|
||||
+#include <mach/irqs.h>
|
||||
+#include <mach/hardware.h>
|
||||
+#include <mach/cns21xx.h>
|
||||
+#include <mach/cns21xx_misc.h>
|
||||
+
|
||||
+#define CNS21XX_UART_CLOCK 24000000
|
||||
+
|
||||
+#define CNS21XX_UART_FLAGS (UPF_SKIP_TEST | UPF_FIXED_TYPE | UPF_NO_TXEN_TEST)
|
||||
+
|
||||
+static struct plat_serial8250_port cns21xx_uart0_data[] = {
|
||||
+ {
|
||||
+ .mapbase = CNS21XX_UART0_BASE,
|
||||
+ .membase = (void *) CNS21XX_UART0_BASE_VIRT,
|
||||
+ .irq = CNS21XX_IRQ_UART0,
|
||||
+ .uartclk = CNS21XX_UART_CLOCK,
|
||||
+ .regshift = 2,
|
||||
+ .iotype = UPIO_MEM,
|
||||
+ .type = PORT_16550A,
|
||||
+ .flags = CNS21XX_UART_FLAGS,
|
||||
+ }, {
|
||||
+ /* terminating entry */
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device cns21xx_uart0_device = {
|
||||
+ .name = "serial8250",
|
||||
+ .id = PLAT8250_DEV_PLATFORM,
|
||||
+ .dev = {
|
||||
+ .platform_data = cns21xx_uart0_data,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+int __init cns21xx_register_uart0(void)
|
||||
+{
|
||||
+ return platform_device_register(&cns21xx_uart0_device);
|
||||
+}
|
||||
+
|
||||
+static struct plat_serial8250_port cns21xx_uart1_data[] = {
|
||||
+ {
|
||||
+ .mapbase = CNS21XX_UART1_BASE,
|
||||
+ .membase = (void *) CNS21XX_UART1_BASE_VIRT,
|
||||
+ .irq = CNS21XX_IRQ_UART1,
|
||||
+ .uartclk = CNS21XX_UART_CLOCK,
|
||||
+ .regshift = 2,
|
||||
+ .iotype = UPIO_MEM,
|
||||
+ .type = PORT_16550A,
|
||||
+ .flags = CNS21XX_UART_FLAGS,
|
||||
+ }, {
|
||||
+ /* terminating entry */
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device cns21xx_uart1_device = {
|
||||
+ .name = "serial8250",
|
||||
+ .id = PLAT8250_DEV_PLATFORM1,
|
||||
+ .dev = {
|
||||
+ .platform_data = cns21xx_uart1_data,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+int __init cns21xx_register_uart1(void)
|
||||
+{
|
||||
+ HAL_MISC_ENABLE_UART1_PINS();
|
||||
+ return platform_device_register(&cns21xx_uart1_device);
|
||||
+}
|
||||
--- a/arch/arm/mach-cns21xx/Makefile
|
||||
+++ b/arch/arm/mach-cns21xx/Makefile
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
# Object file lists.
|
||||
|
||||
-obj-y := core.o irq.o mm.o time.o
|
||||
+obj-y := core.o devices.o irq.o mm.o time.o
|
||||
|
||||
# machine specific files
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -296,6 +296,8 @@ config ARCH_CNS21XX
|
||||
select CPU_FA526
|
||||
select PLAT_FA
|
||||
select PLAT_FA_TIME
|
||||
+ select PLAT_FA_GPIO
|
||||
+ select ARCH_REQUIRE_GPIOLIB
|
||||
select ARM_L1_CACHE_SHIFT_4
|
||||
help
|
||||
Support for Cavium Networks CNS21xx family.
|
||||
--- a/arch/arm/mach-cns21xx/common.h
|
||||
+++ b/arch/arm/mach-cns21xx/common.h
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
void __init cns21xx_map_io(void);
|
||||
void __init cns21xx_init_irq(void);
|
||||
+void __init cns21xx_gpio_init(void);
|
||||
|
||||
extern struct sys_timer cns21xx_timer;
|
||||
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/gpio.c
|
||||
@@ -0,0 +1,45 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <plat/gpio.h>
|
||||
+
|
||||
+#include <mach/cns21xx.h>
|
||||
+#include <mach/irqs.h>
|
||||
+
|
||||
+static struct fa_gpio_chip cns21xx_gpio_chips[] = {
|
||||
+ {
|
||||
+ .gpio_chip = {
|
||||
+ .label = "GPIOA",
|
||||
+ .base = 0,
|
||||
+ .ngpio = 32,
|
||||
+ },
|
||||
+
|
||||
+ .map_base = CNS21XX_GPIOA_BASE,
|
||||
+ .irq_base = CNS21XX_GPIO_IRQ_BASE,
|
||||
+ }, {
|
||||
+ .gpio_chip = {
|
||||
+ .label = "GPIOB",
|
||||
+ .base = 32,
|
||||
+ .ngpio = 32,
|
||||
+ },
|
||||
+
|
||||
+ .map_base = CNS21XX_GPIOB_BASE,
|
||||
+ .irq_base = CNS21XX_GPIO_IRQ_BASE + 32,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct fa_gpio_data cns21xx_gpio_data = {
|
||||
+ .chips = cns21xx_gpio_chips,
|
||||
+ .nchips = ARRAY_SIZE(cns21xx_gpio_chips),
|
||||
+ .irq = CNS21XX_IRQ_GPIO,
|
||||
+};
|
||||
+
|
||||
+void __init cns21xx_gpio_init(void)
|
||||
+{
|
||||
+ fa_gpio_init(&cns21xx_gpio_data);
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/include/mach/gpio.h
|
||||
@@ -0,0 +1,30 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2008 Cavium Networks
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file 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 _CNS21XX_GPIO_H
|
||||
+#define _CNS21XX_GPIO_H
|
||||
+
|
||||
+#include <asm-generic/gpio.h>
|
||||
+#include <mach/irqs.h>
|
||||
+
|
||||
+#define gpio_get_value __gpio_get_value
|
||||
+#define gpio_set_value __gpio_set_value
|
||||
+#define gpio_cansleep __gpio_cansleep
|
||||
+
|
||||
+static inline int gpio_to_irq(unsigned gpio)
|
||||
+{
|
||||
+ return (CNS21XX_GPIO_IRQ_BASE + gpio);
|
||||
+}
|
||||
+
|
||||
+static inline int irq_to_gpio(int irq)
|
||||
+{
|
||||
+ return (irq - CNS21XX_GPIO_IRQ_BASE);
|
||||
+}
|
||||
+
|
||||
+#endif /* _CNS21XX_GPIO_H */
|
||||
--- a/arch/arm/mach-cns21xx/Makefile
|
||||
+++ b/arch/arm/mach-cns21xx/Makefile
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
# Object file lists.
|
||||
|
||||
-obj-y := core.o devices.o irq.o mm.o time.o
|
||||
+obj-y := core.o devices.o gpio.o irq.o mm.o time.o
|
||||
|
||||
# machine specific files
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
--- a/drivers/usb/host/ohci-hcd.c
|
||||
+++ b/drivers/usb/host/ohci-hcd.c
|
||||
@@ -589,7 +589,6 @@ static int ohci_run (struct ohci_hcd *oh
|
||||
|
||||
/* boot firmware should have set this up (5.1.1.3.1) */
|
||||
if (first) {
|
||||
-
|
||||
val = ohci_readl (ohci, &ohci->regs->fminterval);
|
||||
ohci->fminterval = val & 0x3fff;
|
||||
if (ohci->fminterval != FI)
|
||||
@@ -673,6 +672,9 @@ retry:
|
||||
|
||||
periodic_reinit (ohci);
|
||||
|
||||
+ if (ohci->flags & OHCI_QUIRK_INIT_FMINTERVAL)
|
||||
+ ohci_writel (ohci, ohci->fminterval, &ohci->regs->fminterval);
|
||||
+
|
||||
/* some OHCI implementations are finicky about how they init.
|
||||
* bogus values here mean not even enumeration could work.
|
||||
*/
|
||||
@@ -1067,6 +1069,11 @@ MODULE_LICENSE ("GPL");
|
||||
#define PLATFORM_DRIVER ohci_hcd_da8xx_driver
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_ARCH_CNS21XX
|
||||
+#include "ohci-cns21xx.c"
|
||||
+#define PLATFORM_DRIVER ohci_cns21xx_driver
|
||||
+#endif
|
||||
+
|
||||
#if defined(CONFIG_CPU_SUBTYPE_SH7720) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7721) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7763) || \
|
||||
--- /dev/null
|
||||
+++ b/drivers/usb/host/ohci-cns21xx.c
|
||||
@@ -0,0 +1,175 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2008 Cavium Networks
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include <mach/cns21xx.h>
|
||||
+
|
||||
+#define DRIVER_NAME "cns21xx-ohci"
|
||||
+
|
||||
+static int __devinit cns21xx_ohci_start(struct usb_hcd *hcd)
|
||||
+{
|
||||
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ohci_init(ohci);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = ohci_run(ohci);
|
||||
+ if (ret) {
|
||||
+ err("can't start %s", ohci_to_hcd(ohci)->self.bus_name);
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err:
|
||||
+ ohci_stop(hcd);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static const struct hc_driver ohci_cns21xx_hc_driver = {
|
||||
+ .description = hcd_name,
|
||||
+ .product_desc = "cns21xx-ohci",
|
||||
+ .hcd_priv_size = sizeof(struct ohci_hcd),
|
||||
+
|
||||
+ /*
|
||||
+ * generic hardware linkage
|
||||
+ */
|
||||
+ .irq = ohci_irq,
|
||||
+ .flags = HCD_USB11 | HCD_MEMORY,
|
||||
+
|
||||
+ /*
|
||||
+ * basic lifecycle operations
|
||||
+ */
|
||||
+ .start = cns21xx_ohci_start,
|
||||
+ .stop = ohci_stop,
|
||||
+ .shutdown = ohci_shutdown,
|
||||
+
|
||||
+ /*
|
||||
+ * managing i/o requests and associated device resources
|
||||
+ */
|
||||
+ .urb_enqueue = ohci_urb_enqueue,
|
||||
+ .urb_dequeue = ohci_urb_dequeue,
|
||||
+ .endpoint_disable = ohci_endpoint_disable,
|
||||
+
|
||||
+ /*
|
||||
+ * scheduling support
|
||||
+ */
|
||||
+ .get_frame_number = ohci_get_frame,
|
||||
+
|
||||
+ /*
|
||||
+ * root hub support
|
||||
+ */
|
||||
+ .hub_status_data = ohci_hub_status_data,
|
||||
+ .hub_control = ohci_hub_control,
|
||||
+ .start_port_reset = ohci_start_port_reset,
|
||||
+};
|
||||
+
|
||||
+static void cns21xx_ohci_init_hc(void)
|
||||
+{
|
||||
+ __raw_writel(0x146, CNS21XX_OHCI_CONFIG_BASE_VIRT + 0x04);
|
||||
+ __raw_writel(0x200, CNS21XX_OHCI_CONFIG_BASE_VIRT + 0x44);
|
||||
+ msleep(100);
|
||||
+}
|
||||
+
|
||||
+static int ohci_cns21xx_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct usb_hcd *hcd;
|
||||
+ struct resource *res;
|
||||
+ struct ohci_hcd *ohci;
|
||||
+ int irq;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (usb_disabled())
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
+ if (!res) {
|
||||
+ dev_dbg(&pdev->dev, "no IRQ specified for %s\n",
|
||||
+ dev_name(&pdev->dev));
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ irq = res->start;
|
||||
+
|
||||
+ hcd = usb_create_hcd(&ohci_cns21xx_hc_driver, &pdev->dev,
|
||||
+ dev_name(&pdev->dev));
|
||||
+ if (!hcd)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ if (!res) {
|
||||
+ dev_dbg(&pdev->dev, "no base address specified for %s\n",
|
||||
+ dev_name(&pdev->dev));
|
||||
+ ret = -ENODEV;
|
||||
+ goto err_put_hcd;
|
||||
+ }
|
||||
+ hcd->rsrc_start = res->start;
|
||||
+ hcd->rsrc_len = res->end - res->start + 1;
|
||||
+
|
||||
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
|
||||
+ dev_dbg(&pdev->dev, "controller already in use\n");
|
||||
+ ret = -EBUSY;
|
||||
+ goto err_put_hcd;
|
||||
+ }
|
||||
+
|
||||
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
|
||||
+ if (!hcd->regs) {
|
||||
+ dev_dbg(&pdev->dev, "error mapping memory\n");
|
||||
+ ret = -EFAULT;
|
||||
+ goto err_release_region;
|
||||
+ }
|
||||
+
|
||||
+ cns21xx_ohci_init_hc();
|
||||
+
|
||||
+ ohci = hcd_to_ohci(hcd);
|
||||
+ ohci->flags |= OHCI_QUIRK_INIT_FMINTERVAL;
|
||||
+ ohci_hcd_init(ohci);
|
||||
+
|
||||
+ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
|
||||
+ if (ret)
|
||||
+ goto err_unmap;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, hcd);
|
||||
+ return 0;
|
||||
+
|
||||
+err_unmap:
|
||||
+ iounmap(hcd->regs);
|
||||
+err_release_region:
|
||||
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
+err_put_hcd:
|
||||
+ usb_put_hcd(hcd);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int ohci_cns21xx_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ usb_remove_hcd(hcd);
|
||||
+ iounmap(hcd->regs);
|
||||
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
+ usb_put_hcd(hcd);
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver ohci_cns21xx_driver = {
|
||||
+ .probe = ohci_cns21xx_probe,
|
||||
+ .remove = ohci_cns21xx_remove,
|
||||
+ .shutdown = usb_hcd_platform_shutdown,
|
||||
+ .driver = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .name = DRIVER_NAME,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
--- a/drivers/usb/host/ohci.h
|
||||
+++ b/drivers/usb/host/ohci.h
|
||||
@@ -404,6 +404,7 @@ struct ohci_hcd {
|
||||
#define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/
|
||||
#define OHCI_QUIRK_AMD_PREFETCH 0x400 /* pre-fetch for ISO transfer */
|
||||
#define OHCI_QUIRK_SHUTDOWN 0x800 /* nVidia power bug */
|
||||
+#define OHCI_QUIRK_INIT_FMINTERVAL 0x1000 /* fminterval must be initialized */
|
||||
// there are also chip quirks/bugs in init logic
|
||||
|
||||
struct work_struct nec_work; /* Worker for NEC quirk */
|
||||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -299,6 +299,7 @@ config ARCH_CNS21XX
|
||||
select PLAT_FA_GPIO
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARM_L1_CACHE_SHIFT_4
|
||||
+ select USB_ARCH_HAS_OHCI
|
||||
help
|
||||
Support for Cavium Networks CNS21xx family.
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
--- /dev/null
|
||||
+++ b/drivers/usb/host/ehci-cns21xx.c
|
||||
@@ -0,0 +1,185 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2008 Cavium Networks
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/irq.h>
|
||||
+
|
||||
+#include <mach/cns21xx.h>
|
||||
+
|
||||
+#define DRIVER_NAME "cns21xx-ehci"
|
||||
+
|
||||
+static int cns21xx_ehci_reset(struct usb_hcd *hcd)
|
||||
+{
|
||||
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = ehci_halt(ehci);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = ehci_init(hcd);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ehci_reset(ehci);
|
||||
+ ehci_port_power(ehci, 0);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct hc_driver ehci_cns21xx_hc_driver = {
|
||||
+ .description = hcd_name,
|
||||
+ .product_desc = DRIVER_NAME,
|
||||
+ .hcd_priv_size = sizeof(struct ehci_hcd),
|
||||
+
|
||||
+ /*
|
||||
+ * generic hardware linkage
|
||||
+ */
|
||||
+ .irq = ehci_irq,
|
||||
+ .flags = HCD_MEMORY | HCD_USB2,
|
||||
+
|
||||
+ /*
|
||||
+ * basic lifecycle operations
|
||||
+ */
|
||||
+ .reset = cns21xx_ehci_reset,
|
||||
+ .start = ehci_run,
|
||||
+ .stop = ehci_stop,
|
||||
+ .shutdown = ehci_shutdown,
|
||||
+
|
||||
+ /*
|
||||
+ * managing i/o requests and associated device resources
|
||||
+ */
|
||||
+ .urb_enqueue = ehci_urb_enqueue,
|
||||
+ .urb_dequeue = ehci_urb_dequeue,
|
||||
+ .endpoint_disable = ehci_endpoint_disable,
|
||||
+ .endpoint_reset = ehci_endpoint_reset,
|
||||
+
|
||||
+ /*
|
||||
+ * scheduling support
|
||||
+ */
|
||||
+ .get_frame_number = ehci_get_frame,
|
||||
+
|
||||
+ /*
|
||||
+ * root hub support
|
||||
+ */
|
||||
+ .hub_status_data = ehci_hub_status_data,
|
||||
+ .hub_control = ehci_hub_control,
|
||||
+ .relinquish_port = ehci_relinquish_port,
|
||||
+ .port_handed_over = ehci_port_handed_over,
|
||||
+
|
||||
+ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
|
||||
+};
|
||||
+
|
||||
+static void cns21xx_ehci_init_hc(void)
|
||||
+{
|
||||
+ __raw_writel(0x106, CNS21XX_EHCI_CONFIG_BASE_VIRT + 0x04);
|
||||
+ __raw_writel((3 << 5) | 0x2000, CNS21XX_EHCI_CONFIG_BASE_VIRT + 0x40);
|
||||
+ msleep(100);
|
||||
+}
|
||||
+
|
||||
+static int ehci_cns21xx_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct usb_hcd *hcd;
|
||||
+ struct ehci_hcd *ehci;
|
||||
+ struct resource *res;
|
||||
+ int irq;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (usb_disabled())
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
+ if (!res) {
|
||||
+ dev_dbg(&pdev->dev, "no IRQ specified for %s\n",
|
||||
+ dev_name(&pdev->dev));
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ irq = res->start;
|
||||
+
|
||||
+ hcd = usb_create_hcd(&ehci_cns21xx_hc_driver, &pdev->dev,
|
||||
+ dev_name(&pdev->dev));
|
||||
+ if (!hcd)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ if (!res) {
|
||||
+ dev_dbg(&pdev->dev, "no base address specified for %s\n",
|
||||
+ dev_name(&pdev->dev));
|
||||
+ ret = -ENODEV;
|
||||
+ goto err_put_hcd;
|
||||
+ }
|
||||
+ hcd->rsrc_start = res->start;
|
||||
+ hcd->rsrc_len = res->end - res->start + 1;
|
||||
+
|
||||
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
|
||||
+ dev_dbg(&pdev->dev, "controller already in use\n");
|
||||
+ ret = -EBUSY;
|
||||
+ goto err_put_hcd;
|
||||
+ }
|
||||
+
|
||||
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
|
||||
+ if (!hcd->regs) {
|
||||
+ dev_dbg(&pdev->dev, "error mapping memory\n");
|
||||
+ ret = -EFAULT;
|
||||
+ goto err_release_region;
|
||||
+ }
|
||||
+
|
||||
+ cns21xx_ehci_init_hc();
|
||||
+
|
||||
+ ehci = hcd_to_ehci(hcd);
|
||||
+
|
||||
+ ehci->caps = hcd->regs;
|
||||
+ ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
|
||||
+ dbg_hcs_params(ehci, "reset");
|
||||
+ dbg_hcc_params(ehci, "reset");
|
||||
+
|
||||
+ /* cache this readonly data; minimize chip reads */
|
||||
+ ehci->hcs_params = readl(&ehci->caps->hcs_params);
|
||||
+ ehci->sbrn = 0x20;
|
||||
+
|
||||
+ ret = usb_add_hcd(hcd, CNS21XX_IRQ_EHCI, IRQF_DISABLED);
|
||||
+ if (ret)
|
||||
+ goto err_unmap;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, hcd);
|
||||
+ return 0;
|
||||
+
|
||||
+err_unmap:
|
||||
+ iounmap(hcd->regs);
|
||||
+err_release_region:
|
||||
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
+err_put_hcd:
|
||||
+ usb_put_hcd(hcd);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int ehci_cns21xx_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct usb_hcd *hcd = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ usb_remove_hcd(hcd);
|
||||
+ iounmap(hcd->regs);
|
||||
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
|
||||
+ usb_put_hcd(hcd);
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver ehci_cns21xx_driver = {
|
||||
+ .probe = ehci_cns21xx_probe,
|
||||
+ .remove = ehci_cns21xx_remove,
|
||||
+ .shutdown = usb_hcd_platform_shutdown,
|
||||
+ .driver = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .name = DRIVER_NAME,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+MODULE_ALIAS("platform:" DRIVER_NAME);
|
||||
--- a/drivers/usb/host/ehci-hcd.c
|
||||
+++ b/drivers/usb/host/ehci-hcd.c
|
||||
@@ -1216,6 +1216,11 @@ MODULE_LICENSE ("GPL");
|
||||
#define PLATFORM_DRIVER ehci_octeon_driver
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_ARCH_CNS21XX
|
||||
+#include "ehci-cns21xx.c"
|
||||
+#define PLATFORM_DRIVER ehci_cns21xx_driver
|
||||
+#endif
|
||||
+
|
||||
#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
|
||||
!defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
|
||||
!defined(XILINX_OF_PLATFORM_DRIVER)
|
||||
--- a/arch/arm/Kconfig
|
||||
+++ b/arch/arm/Kconfig
|
||||
@@ -300,6 +300,7 @@ config ARCH_CNS21XX
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARM_L1_CACHE_SHIFT_4
|
||||
select USB_ARCH_HAS_OHCI
|
||||
+ select USB_ARCH_HAS_EHCI
|
||||
help
|
||||
Support for Cavium Networks CNS21xx family.
|
||||
|
|
@ -0,0 +1,577 @@
|
|||
--- a/include/linux/spi/spi.h
|
||||
+++ b/include/linux/spi/spi.h
|
||||
@@ -445,6 +445,8 @@ struct spi_transfer {
|
||||
u16 delay_usecs;
|
||||
u32 speed_hz;
|
||||
|
||||
+ unsigned last_in_message_list;
|
||||
+
|
||||
struct list_head transfer_list;
|
||||
};
|
||||
|
||||
--- a/drivers/spi/Kconfig
|
||||
+++ b/drivers/spi/Kconfig
|
||||
@@ -167,6 +167,14 @@ config SPI_GPIO_OLD
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
+config SPI_CNS21XX
|
||||
+ tristate "Cavium Netowrks CNS21xx SPI master"
|
||||
+ depends on ARCH_CNS21XX && EXPERIMENTAL
|
||||
+ select SPI_BITBANG
|
||||
+ help
|
||||
+ This driver supports the buil-in SPI controller of the Cavium Networks
|
||||
+ CNS21xx SoCs.
|
||||
+
|
||||
config SPI_IMX
|
||||
tristate "Freescale i.MX SPI controllers"
|
||||
depends on ARCH_MXC
|
||||
--- a/drivers/spi/Makefile
|
||||
+++ b/drivers/spi/Makefile
|
||||
@@ -50,6 +50,7 @@ obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.
|
||||
obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o
|
||||
obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
|
||||
obj-$(CONFIG_SPI_NUC900) += spi_nuc900.o
|
||||
+obj-$(CONFIG_SPI_CNS21XX) += spi_cns21xx.o
|
||||
|
||||
# special build for s3c24xx spi driver with fiq support
|
||||
spi_s3c24xx_hw-y := spi_s3c24xx.o
|
||||
--- a/drivers/spi/spi_bitbang.c
|
||||
+++ b/drivers/spi/spi_bitbang.c
|
||||
@@ -337,6 +337,13 @@ static void bitbang_work(struct work_str
|
||||
*/
|
||||
if (!m->is_dma_mapped)
|
||||
t->rx_dma = t->tx_dma = 0;
|
||||
+
|
||||
+ if (t->transfer_list.next == &m->transfers) {
|
||||
+ t->last_in_message_list = 1;
|
||||
+ } else {
|
||||
+ t->last_in_message_list = 0;
|
||||
+ }
|
||||
+
|
||||
status = bitbang->txrx_bufs(spi, t);
|
||||
}
|
||||
if (status > 0)
|
||||
--- /dev/null
|
||||
+++ b/drivers/spi/spi_cns21xx.c
|
||||
@@ -0,0 +1,520 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2008 Cavium Networks
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/spinlock.h>
|
||||
+#include <linux/workqueue.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/errno.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+#include <linux/spi/spi_bitbang.h>
|
||||
+
|
||||
+#include <mach/hardware.h>
|
||||
+#include <mach/cns21xx.h>
|
||||
+
|
||||
+#define DRIVER_NAME "cns21xx-spi"
|
||||
+
|
||||
+#ifdef CONFIG_CNS21XX_SPI_DEBUG
|
||||
+#define DBG(fmt, args...) pr_info("[CNS21XX_SPI_DEBUG]" fmt, ## args)
|
||||
+#else
|
||||
+#define DBG(fmt, args...) do {} while (0)
|
||||
+#endif /* CNS21XX_SPI_DEBUG */
|
||||
+
|
||||
+#define SPI_REG_CFG 0x40
|
||||
+#define SPI_REG_STAT 0x44
|
||||
+#define SPI_REG_BIT_RATE 0x48
|
||||
+#define SPI_REG_TX_CTRL 0x4c
|
||||
+#define SPI_REG_TX_DATA 0x50
|
||||
+#define SPI_REG_RX_CTRL 0x54
|
||||
+#define SPI_REG_RX_DATA 0x58
|
||||
+#define SPI_REG_FIFO_TX_CFG 0x5c
|
||||
+#define SPI_REG_FIFO_TX_CTRL 0x60
|
||||
+#define SPI_REG_FIFO_RX_CFG 0x64
|
||||
+#define SPI_REG_INTR_STAT 0x68
|
||||
+#define SPI_REG_INTR_ENA 0x6c
|
||||
+
|
||||
+#define CFG_SPI_EN BIT(31)
|
||||
+#define CFG_SPI_CLKPOL BIT(14)
|
||||
+#define CFG_SPI_CLKPHA BIT(13)
|
||||
+#define CFG_SPI_MASTER_EN BIT(11)
|
||||
+#define CFG_SPI_CHAR_LEN_M 0x3
|
||||
+#define CFG_SPI_CHAR_LEN_8BITS 0
|
||||
+#define CFG_SPI_CHAR_LEN_16BITS 1
|
||||
+#define CFG_SPI_CHAR_LEN_24BITS 2
|
||||
+#define CFG_SPI_CHAR_LEN_32BITS 3
|
||||
+
|
||||
+#define STAT_SPI_BUSY_STA BIT(1)
|
||||
+
|
||||
+#define BIT_RATE_DIV_1 0
|
||||
+#define BIT_RATE_DIV_2 1
|
||||
+#define BIT_RATE_DIV_4 2
|
||||
+#define BIT_RATE_DIV_8 3
|
||||
+#define BIT_RATE_DIV_16 4
|
||||
+#define BIT_RATE_DIV_32 5
|
||||
+#define BIT_RATE_DIV_64 6
|
||||
+#define BIT_RATE_DIV_128 7
|
||||
+
|
||||
+#define TX_CTRL_SPI_TXDAT_EOF BIT(2)
|
||||
+#define TX_CTRL_SPI_TXCH_NUM_M 0x3
|
||||
+#define TX_CTRL_CLEAR_MASK (TX_CTRL_SPI_TXDAT_EOF | \
|
||||
+ TX_CTRL_SPI_TXCH_NUM_M)
|
||||
+
|
||||
+#define RX_CTRL_SPI_RXDAT_EOF BIT(2)
|
||||
+#define RX_CTRL_SPI_RXCH_NUM_M 0x3
|
||||
+
|
||||
+#define INTR_STAT_SPI_TXBF_UNRN_FG BIT(7)
|
||||
+#define INTR_STAT_SPI_RXBF_OVRN_FG BIT(6)
|
||||
+#define INTR_STAT_SPI_TXFF_UNRN_FG BIT(5)
|
||||
+#define INTR_STAT_SPI_RXFF_OVRN_FG BIT(4)
|
||||
+#define INTR_STAT_SPI_TXBUF_FG BIT(3)
|
||||
+#define INTR_STAT_SPI_RXBUF_FG BIT(2)
|
||||
+#define INTR_STAT_SPI_TXFF_FG BIT(1)
|
||||
+#define INTR_STAT_SPI_RXFF_FG BIT(0)
|
||||
+
|
||||
+#define INTR_STAT_CLEAR_MASK (INTR_STAT_SPI_TXBF_UNRN_FG | \
|
||||
+ INTR_STAT_SPI_RXBF_OVRN_FG | \
|
||||
+ INTR_STAT_SPI_TXFF_UNRN_FG | \
|
||||
+ INTR_STAT_SPI_RXFF_OVRN_FG)
|
||||
+
|
||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_M 0x3
|
||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_S 4
|
||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_2 0
|
||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_4 1
|
||||
+#define FIFO_TX_CFG_SPI_TXFF_THRED_6 0
|
||||
+#define FIFO_TX_CFG_SPI_TXFF_STATUS_M 0xf
|
||||
+
|
||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_M 0x3
|
||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_S 4
|
||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_2 0
|
||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_4 1
|
||||
+#define FIFO_RX_CFG_SPI_RXFF_THRED_6 0
|
||||
+#define FIFO_RX_CFG_SPI_RXFF_STATUS_M 0xf
|
||||
+
|
||||
+#define CNS21XX_SPI_NUM_BIT_RATES 8
|
||||
+
|
||||
+struct cns21xx_spi {
|
||||
+ struct spi_bitbang bitbang;
|
||||
+
|
||||
+ struct spi_master *master;
|
||||
+ struct device *dev;
|
||||
+ void __iomem *base;
|
||||
+ struct resource *region;
|
||||
+
|
||||
+ unsigned freq_max;
|
||||
+ unsigned freq_min;
|
||||
+
|
||||
+};
|
||||
+
|
||||
+static inline struct cns21xx_spi *to_hw(struct spi_device *spi)
|
||||
+{
|
||||
+ return spi_master_get_devdata(spi->master);
|
||||
+}
|
||||
+
|
||||
+static inline u32 cns21xx_spi_rr(struct cns21xx_spi *hw, unsigned int reg)
|
||||
+{
|
||||
+ return __raw_readl(hw->base + reg);
|
||||
+}
|
||||
+
|
||||
+static inline void cns21xx_spi_wr(struct cns21xx_spi *hw, u32 val,
|
||||
+ unsigned int reg)
|
||||
+{
|
||||
+ __raw_writel(val, hw->base + reg);
|
||||
+}
|
||||
+
|
||||
+#define CNS21XX_SPI_RETRY_COUNT 100
|
||||
+static inline int cns21xx_spi_wait(struct cns21xx_spi *hw, unsigned int reg,
|
||||
+ u32 mask, u32 val)
|
||||
+{
|
||||
+ int retry_cnt = 0;
|
||||
+
|
||||
+ do {
|
||||
+ if ((cns21xx_spi_rr(hw, reg) & mask) == val)
|
||||
+ break;
|
||||
+
|
||||
+ if (++retry_cnt > CNS21XX_SPI_RETRY_COUNT) {
|
||||
+ dev_err(hw->dev, "timeout waiting on register %02x\n",
|
||||
+ reg);
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+ } while (1);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cns21xx_spi_txrx_word(struct cns21xx_spi *hw, u8 tx_channel,
|
||||
+ u8 tx_eof_flag, u32 tx_data, u32 *rx_data)
|
||||
+{
|
||||
+ unsigned int tx_ctrl;
|
||||
+ u8 rx_channel;
|
||||
+ u8 rx_eof_flag;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ err = cns21xx_spi_wait(hw, SPI_REG_STAT, STAT_SPI_BUSY_STA, 0);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = cns21xx_spi_wait(hw, SPI_REG_INTR_STAT, INTR_STAT_SPI_TXBUF_FG,
|
||||
+ INTR_STAT_SPI_TXBUF_FG);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ tx_ctrl = cns21xx_spi_rr(hw, SPI_REG_TX_CTRL);
|
||||
+ tx_ctrl &= ~(TX_CTRL_CLEAR_MASK);
|
||||
+ tx_ctrl |= (tx_channel & TX_CTRL_SPI_TXCH_NUM_M);
|
||||
+ tx_ctrl |= (tx_eof_flag) ? TX_CTRL_SPI_TXDAT_EOF : 0;
|
||||
+ cns21xx_spi_wr(hw, tx_ctrl, SPI_REG_TX_CTRL);
|
||||
+
|
||||
+ cns21xx_spi_wr(hw, tx_data, SPI_REG_TX_DATA);
|
||||
+
|
||||
+ err = cns21xx_spi_wait(hw, SPI_REG_INTR_STAT, INTR_STAT_SPI_RXBUF_FG,
|
||||
+ INTR_STAT_SPI_RXBUF_FG);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ rx_channel = cns21xx_spi_rr(hw, SPI_REG_RX_CTRL) &
|
||||
+ RX_CTRL_SPI_RXCH_NUM_M;
|
||||
+
|
||||
+ rx_eof_flag = (cns21xx_spi_rr(hw, SPI_REG_RX_CTRL) &
|
||||
+ RX_CTRL_SPI_RXDAT_EOF) ? 1 : 0;
|
||||
+
|
||||
+ *rx_data = cns21xx_spi_rr(hw, SPI_REG_RX_DATA);
|
||||
+
|
||||
+ if ((tx_channel != rx_channel) || (tx_eof_flag != rx_eof_flag))
|
||||
+ return -EPROTO;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void cns21xx_spi_chipselect(struct spi_device *spi, int value)
|
||||
+{
|
||||
+ struct cns21xx_spi *hw = to_hw(spi);
|
||||
+ unsigned int spi_config;
|
||||
+ unsigned int tx_ctrl;
|
||||
+
|
||||
+ switch (value) {
|
||||
+ case BITBANG_CS_INACTIVE:
|
||||
+ break;
|
||||
+
|
||||
+ case BITBANG_CS_ACTIVE:
|
||||
+ spi_config = cns21xx_spi_rr(hw, SPI_REG_CFG);
|
||||
+
|
||||
+ if (spi->mode & SPI_CPHA)
|
||||
+ spi_config |= CFG_SPI_CLKPHA;
|
||||
+ else
|
||||
+ spi_config &= ~CFG_SPI_CLKPHA;
|
||||
+
|
||||
+ if (spi->mode & SPI_CPOL)
|
||||
+ spi_config |= CFG_SPI_CLKPOL;
|
||||
+ else
|
||||
+ spi_config &= ~CFG_SPI_CLKPOL;
|
||||
+
|
||||
+ cns21xx_spi_wr(hw, spi_config, SPI_REG_CFG);
|
||||
+
|
||||
+ tx_ctrl = cns21xx_spi_rr(hw, SPI_REG_TX_CTRL);
|
||||
+ tx_ctrl &= ~(TX_CTRL_CLEAR_MASK);
|
||||
+ tx_ctrl |= (spi->chip_select & TX_CTRL_SPI_TXCH_NUM_M);
|
||||
+ cns21xx_spi_wr(hw, tx_ctrl, SPI_REG_TX_CTRL);
|
||||
+
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int cns21xx_spi_setup(struct spi_device *spi)
|
||||
+{
|
||||
+ struct cns21xx_spi *hw = to_hw(spi);
|
||||
+
|
||||
+ if (spi->bits_per_word != 8) {
|
||||
+ dev_err(&spi->dev, "%s: invalid bits_per_word=%u\n",
|
||||
+ __func__, spi->bits_per_word);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (spi->max_speed_hz == 0)
|
||||
+ spi->max_speed_hz = hw->freq_max;
|
||||
+
|
||||
+ if (spi->max_speed_hz > hw->freq_max ||
|
||||
+ spi->max_speed_hz < hw->freq_min) {
|
||||
+ dev_err(&spi->dev, "%s: max_speed_hz=%u out of range\n",
|
||||
+ __func__, spi->max_speed_hz);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cns21xx_spi_setup_transfer(struct spi_device *spi,
|
||||
+ struct spi_transfer *t)
|
||||
+{
|
||||
+ struct cns21xx_spi *hw = to_hw(spi);
|
||||
+ u8 bits_per_word;
|
||||
+ u32 hz;
|
||||
+ int i;
|
||||
+
|
||||
+ bits_per_word = (t) ? t->bits_per_word : spi->bits_per_word;
|
||||
+ hz = t ? t->speed_hz : spi->max_speed_hz;
|
||||
+
|
||||
+ if (!bits_per_word)
|
||||
+ bits_per_word = spi->bits_per_word;
|
||||
+
|
||||
+ if (!hz)
|
||||
+ hz = spi->max_speed_hz;
|
||||
+
|
||||
+ if (bits_per_word != 8) {
|
||||
+ dev_err(&spi->dev, "%s: invalid bits_per_word=%u\n",
|
||||
+ __func__, bits_per_word);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (hz > spi->max_speed_hz || hz > hw->freq_max || hz < hw->freq_min) {
|
||||
+ dev_err(&spi->dev, "%s: max_speed_hz=%u out of range\n",
|
||||
+ __func__, hz);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < CNS21XX_SPI_NUM_BIT_RATES; i++)
|
||||
+ if (spi->max_speed_hz > (cns21xx_get_apb_freq() >> i))
|
||||
+ break;
|
||||
+
|
||||
+ DBG("max_speed:%uHz, curr_speed:%luHz, rate_index=%d\n",
|
||||
+ spi->max_speed_hz, cns21xx_get_apb_freq() / (1 << i), i);
|
||||
+
|
||||
+ cns21xx_spi_wr(hw, i, SPI_REG_BIT_RATE);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int cns21xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
|
||||
+{
|
||||
+ struct cns21xx_spi *hw = to_hw(spi);
|
||||
+ const unsigned char *tx_buf;
|
||||
+ unsigned char *rx_buf;
|
||||
+ u32 rx_data;
|
||||
+ int tx_eof;
|
||||
+ int err = 0;
|
||||
+ int i;
|
||||
+
|
||||
+ tx_buf = t->tx_buf;
|
||||
+ rx_buf = t->rx_buf;
|
||||
+ tx_eof = t->last_in_message_list;
|
||||
+
|
||||
+ DBG("txrx: tx %p, rx %p, len %d\n", tx_buf, rx_buf, t->len);
|
||||
+
|
||||
+ if (tx_buf) {
|
||||
+ for (i = 0; i < t->len; i++)
|
||||
+ DBG("tx_buf[%02d]: 0x%02x\n", i, tx_buf[i]);
|
||||
+
|
||||
+ for (i = 0; i < (t->len - 1); i++) {
|
||||
+ err = cns21xx_spi_txrx_word(hw, spi->chip_select, 0,
|
||||
+ tx_buf[i], &rx_data);
|
||||
+ if (err)
|
||||
+ goto done;
|
||||
+
|
||||
+ if (rx_buf) {
|
||||
+ rx_buf[i] = rx_data;
|
||||
+ DBG("rx_buf[%02d]:0x%02x\n", i, rx_buf[i]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ err = cns21xx_spi_txrx_word(hw, spi->chip_select, tx_eof,
|
||||
+ tx_buf[i], &rx_data);
|
||||
+ if (err)
|
||||
+ goto done;
|
||||
+
|
||||
+ if ((tx_eof) && rx_buf) {
|
||||
+ rx_buf[i] = rx_data;
|
||||
+ DBG("rx_buf[%02d]:0x%02x\n", i, rx_buf[i]);
|
||||
+ }
|
||||
+ } else if (rx_buf) {
|
||||
+ for (i = 0; i < (t->len - 1); i++) {
|
||||
+ err = cns21xx_spi_txrx_word(hw, spi->chip_select, 0,
|
||||
+ 0xff, &rx_data);
|
||||
+ if (err)
|
||||
+ goto done;
|
||||
+
|
||||
+ rx_buf[i] = rx_data;
|
||||
+ DBG("rx_buf[%02d]:0x%02x\n", i, rx_buf[i]);
|
||||
+ }
|
||||
+
|
||||
+ err = cns21xx_spi_txrx_word(hw, spi->chip_select, tx_eof,
|
||||
+ 0xff, &rx_data);
|
||||
+ if (err)
|
||||
+ goto done;
|
||||
+
|
||||
+ rx_buf[i] = rx_data;
|
||||
+ DBG("rx_buf[%02d]:0x%02x\n", i, rx_buf[i]);
|
||||
+ }
|
||||
+
|
||||
+ done:
|
||||
+ return (err) ? err : t->len;
|
||||
+}
|
||||
+
|
||||
+static void __init cns21xx_spi_hw_init(struct cns21xx_spi *hw)
|
||||
+{
|
||||
+ u32 t;
|
||||
+ u32 pclk;
|
||||
+
|
||||
+ /* Setup configuration register */
|
||||
+ cns21xx_spi_wr(hw, CFG_SPI_MASTER_EN, SPI_REG_CFG);
|
||||
+
|
||||
+ /* Set default clock to PCLK/2 */
|
||||
+ cns21xx_spi_wr(hw, BIT_RATE_DIV_2, SPI_REG_BIT_RATE);
|
||||
+
|
||||
+ /* Configure SPI's Tx channel */
|
||||
+ cns21xx_spi_wr(hw, 0, SPI_REG_TX_CTRL);
|
||||
+
|
||||
+ /* Configure Tx FIFO Threshold */
|
||||
+ t = cns21xx_spi_rr(hw, SPI_REG_FIFO_TX_CFG);
|
||||
+ t &= ~(FIFO_TX_CFG_SPI_TXFF_THRED_M << FIFO_TX_CFG_SPI_TXFF_THRED_S);
|
||||
+ t |= (FIFO_TX_CFG_SPI_TXFF_THRED_2 << FIFO_TX_CFG_SPI_TXFF_THRED_S);
|
||||
+ cns21xx_spi_wr(hw, t, SPI_REG_FIFO_TX_CFG);
|
||||
+
|
||||
+ /* Configure Rx FIFO Threshold */
|
||||
+ t = cns21xx_spi_rr(hw, SPI_REG_FIFO_RX_CFG);
|
||||
+ t &= ~(FIFO_RX_CFG_SPI_RXFF_THRED_M << FIFO_RX_CFG_SPI_RXFF_THRED_S);
|
||||
+ t |= (FIFO_RX_CFG_SPI_RXFF_THRED_2 << FIFO_RX_CFG_SPI_RXFF_THRED_S);
|
||||
+ cns21xx_spi_wr(hw, t, SPI_REG_FIFO_RX_CFG);
|
||||
+
|
||||
+ /* Disable interrupts, and clear interrupt status */
|
||||
+ cns21xx_spi_wr(hw, 0, SPI_REG_INTR_ENA);
|
||||
+ cns21xx_spi_wr(hw, INTR_STAT_CLEAR_MASK, SPI_REG_INTR_STAT);
|
||||
+
|
||||
+ (void) cns21xx_spi_rr(hw, SPI_REG_RX_DATA);
|
||||
+
|
||||
+ /* Enable SPI */
|
||||
+ t = cns21xx_spi_rr(hw, SPI_REG_CFG);
|
||||
+ t |= CFG_SPI_EN;
|
||||
+ cns21xx_spi_wr(hw, t, SPI_REG_CFG);
|
||||
+
|
||||
+ pclk = cns21xx_get_apb_freq();
|
||||
+ hw->freq_max = pclk;
|
||||
+ hw->freq_min = pclk / (1 << BIT_RATE_DIV_128);
|
||||
+}
|
||||
+
|
||||
+static int __init cns21xx_spi_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct cns21xx_spi *hw;
|
||||
+ struct spi_master *master;
|
||||
+ struct resource *res;
|
||||
+ int err = 0;
|
||||
+
|
||||
+ master = spi_alloc_master(&pdev->dev, sizeof(struct cns21xx_spi));
|
||||
+ if (!master) {
|
||||
+ dev_err(&pdev->dev, "No memory for spi_master\n");
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+
|
||||
+ hw = spi_master_get_devdata(master);
|
||||
+
|
||||
+ platform_set_drvdata(pdev, hw);
|
||||
+ hw->master = spi_master_get(master);
|
||||
+ hw->dev = &pdev->dev;
|
||||
+
|
||||
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ if (!res) {
|
||||
+ dev_dbg(&pdev->dev, "no MEM resource found\n");
|
||||
+ err = -ENOENT;
|
||||
+ goto err_put_master;
|
||||
+ }
|
||||
+
|
||||
+ hw->region = request_mem_region(res->start, resource_size(res),
|
||||
+ dev_name(&pdev->dev));
|
||||
+ if (!hw->region) {
|
||||
+ dev_err(&pdev->dev, "unable to reserve iomem region\n");
|
||||
+ err = -ENXIO;
|
||||
+ goto err_put_master;
|
||||
+ }
|
||||
+
|
||||
+ hw->base = ioremap(res->start, resource_size(res));
|
||||
+ if (!hw->base) {
|
||||
+ dev_err(&pdev->dev, "ioremap failed\n");
|
||||
+ err = -ENOENT;
|
||||
+ goto err_release_region;
|
||||
+ }
|
||||
+
|
||||
+ cns21xx_spi_hw_init(hw);
|
||||
+
|
||||
+ master->bus_num = pdev->id;
|
||||
+ if (master->bus_num == -1)
|
||||
+ master->bus_num = 0;
|
||||
+
|
||||
+ master->num_chipselect = 4;
|
||||
+ master->setup = cns21xx_spi_setup;
|
||||
+
|
||||
+ hw->bitbang.master = hw->master;
|
||||
+ hw->bitbang.chipselect = cns21xx_spi_chipselect;
|
||||
+ hw->bitbang.txrx_bufs = cns21xx_spi_txrx;
|
||||
+ hw->bitbang.setup_transfer = cns21xx_spi_setup_transfer;
|
||||
+
|
||||
+ err = spi_bitbang_start(&hw->bitbang);
|
||||
+ if (err) {
|
||||
+ dev_err(hw->dev, "unable to register SPI master\n");
|
||||
+ goto err_unmap;
|
||||
+ }
|
||||
+
|
||||
+ dev_info(hw->dev, "iomem at %08x\n", res->start);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+ err_unmap:
|
||||
+ iounmap(hw->base);
|
||||
+
|
||||
+ err_release_region:
|
||||
+ release_resource(hw->region);
|
||||
+ kfree(hw->region);
|
||||
+
|
||||
+ err_put_master:
|
||||
+ spi_master_put(hw->bitbang.master);
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static int __devexit cns21xx_spi_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct cns21xx_spi *hw = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ spi_bitbang_stop(&hw->bitbang);
|
||||
+ iounmap(hw->base);
|
||||
+ release_resource(hw->region);
|
||||
+ kfree(hw->region);
|
||||
+ spi_master_put(hw->bitbang.master);
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver cns21xx_spi_driver = {
|
||||
+ .remove = __devexit_p(cns21xx_spi_remove),
|
||||
+ .driver = {
|
||||
+ .name = DRIVER_NAME,
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init cns21xx_spi_init(void)
|
||||
+{
|
||||
+ return platform_driver_probe(&cns21xx_spi_driver, cns21xx_spi_probe);
|
||||
+}
|
||||
+
|
||||
+static void __exit cns21xx_spi_exit(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&cns21xx_spi_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(cns21xx_spi_init);
|
||||
+module_exit(cns21xx_spi_exit);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Cavium Networks CNS21xx SPI Controller driver");
|
||||
+MODULE_AUTHOR("STAR Semi Corp.");
|
||||
+MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
+MODULE_ALIAS("platform:" DRIVER_NAME);
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,104 @@
|
|||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/dev-usb.c
|
||||
@@ -0,0 +1,71 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2008 Cavium Networks
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/irq.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include <mach/cns21xx.h>
|
||||
+
|
||||
+static u64 cns21xx_usb_dmamask = DMA_BIT_MASK(32);
|
||||
+
|
||||
+static struct resource cns21xx_ohci_resources[] = {
|
||||
+ [0] = {
|
||||
+ .start = CNS21XX_OHCI_CTRL_BASE,
|
||||
+ .end = CNS21XX_OHCI_CTRL_BASE + SZ_1M - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ [1] = {
|
||||
+ .start = CNS21XX_IRQ_OHCI,
|
||||
+ .end = CNS21XX_IRQ_OHCI,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device cns21xx_ohci_device = {
|
||||
+ .name = "cns21xx-ohci",
|
||||
+ .id = -1,
|
||||
+ .dev = {
|
||||
+ .dma_mask = &cns21xx_usb_dmamask,
|
||||
+ .coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
+ },
|
||||
+ .resource = cns21xx_ohci_resources,
|
||||
+ .num_resources = ARRAY_SIZE(cns21xx_ohci_resources),
|
||||
+};
|
||||
+
|
||||
+static struct resource cns21xx_ehci_resources[] = {
|
||||
+ [0] = {
|
||||
+ .start = CNS21XX_EHCI_CTRL_BASE,
|
||||
+ .end = CNS21XX_EHCI_CTRL_BASE + SZ_1M - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ [1] = {
|
||||
+ .start = CNS21XX_IRQ_EHCI,
|
||||
+ .end = CNS21XX_IRQ_EHCI,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device cns21xx_ehci_device = {
|
||||
+ .name = "cns21xx-ehci",
|
||||
+ .id = -1,
|
||||
+ .dev = {
|
||||
+ .dma_mask = &cns21xx_usb_dmamask,
|
||||
+ .coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
+ },
|
||||
+ .resource = cns21xx_ehci_resources,
|
||||
+ .num_resources = ARRAY_SIZE(cns21xx_ehci_resources),
|
||||
+};
|
||||
+
|
||||
+void __init cns21xx_register_usb(void)
|
||||
+{
|
||||
+ platform_device_register(&cns21xx_ehci_device);
|
||||
+ platform_device_register(&cns21xx_ohci_device);
|
||||
+}
|
||||
--- a/arch/arm/mach-cns21xx/Kconfig
|
||||
+++ b/arch/arm/mach-cns21xx/Kconfig
|
||||
@@ -3,4 +3,7 @@ if ARCH_CNS21XX
|
||||
menu "Cavium Networks CNS21xx based machines"
|
||||
endmenu
|
||||
|
||||
+config CNS21XX_DEV_USB
|
||||
+ def_bool n
|
||||
+
|
||||
endif
|
||||
--- a/arch/arm/mach-cns21xx/Makefile
|
||||
+++ b/arch/arm/mach-cns21xx/Makefile
|
||||
@@ -6,5 +6,8 @@
|
||||
|
||||
obj-y := core.o devices.o gpio.o irq.o mm.o time.o
|
||||
|
||||
+# devices
|
||||
+obj-$(CONFIG_CNS21XX_DEV_USB) += dev-usb.o
|
||||
+
|
||||
# machine specific files
|
||||
|
||||
--- a/arch/arm/mach-cns21xx/common.h
|
||||
+++ b/arch/arm/mach-cns21xx/common.h
|
||||
@@ -18,5 +18,6 @@ extern struct sys_timer cns21xx_timer;
|
||||
|
||||
int __init cns21xx_register_uart0(void);
|
||||
int __init cns21xx_register_uart1(void);
|
||||
+int __init cns21xx_register_usb(void);
|
||||
|
||||
#endif /* _MACH_CNS21XX_COMMON_H */
|
|
@ -0,0 +1,63 @@
|
|||
--- a/arch/arm/mach-cns21xx/common.h
|
||||
+++ b/arch/arm/mach-cns21xx/common.h
|
||||
@@ -19,5 +19,6 @@ extern struct sys_timer cns21xx_timer;
|
||||
int __init cns21xx_register_uart0(void);
|
||||
int __init cns21xx_register_uart1(void);
|
||||
int __init cns21xx_register_usb(void);
|
||||
+int __init cns21xx_register_wdt(void);
|
||||
|
||||
#endif /* _MACH_CNS21XX_COMMON_H */
|
||||
--- a/arch/arm/mach-cns21xx/devices.c
|
||||
+++ b/arch/arm/mach-cns21xx/devices.c
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial_8250.h>
|
||||
+#include <linux/fa_wdt.h>
|
||||
|
||||
#include <mach/irqs.h>
|
||||
#include <mach/hardware.h>
|
||||
@@ -77,3 +78,32 @@ int __init cns21xx_register_uart1(void)
|
||||
HAL_MISC_ENABLE_UART1_PINS();
|
||||
return platform_device_register(&cns21xx_uart1_device);
|
||||
}
|
||||
+
|
||||
+static struct resource cns21xx_wdt_resources[] = {
|
||||
+ {
|
||||
+ .start = CNS21XX_WDT_BASE,
|
||||
+ .end = CNS21XX_WDT_BASE + SZ_4K - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+#define CNS21XX_WDT_CLOCK 10 /* 10 Hz */
|
||||
+
|
||||
+static struct fa_wdt_platform_data cns21xx_wdt_data = {
|
||||
+ .clock = CNS21XX_WDT_CLOCK,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device cns21xx_wdt_device = {
|
||||
+ .name = "fa-wdt",
|
||||
+ .id = -1,
|
||||
+ .resource = cns21xx_wdt_resources,
|
||||
+ .num_resources = ARRAY_SIZE(cns21xx_wdt_resources),
|
||||
+ .dev = {
|
||||
+ .platform_data = &cns21xx_wdt_data,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+int __init cns21xx_register_wdt(void)
|
||||
+{
|
||||
+ return platform_device_register(&cns21xx_wdt_device);
|
||||
+}
|
||||
--- a/drivers/watchdog/Kconfig
|
||||
+++ b/drivers/watchdog/Kconfig
|
||||
@@ -333,7 +333,7 @@ config IMX2_WDT
|
||||
|
||||
config FA_WATCHDOG
|
||||
tristate "Faraday watchdog"
|
||||
- depends on ARCH_GEMINI
|
||||
+ depends on ARCH_GEMINI || ARCH_CNS21XX
|
||||
help
|
||||
Say Y here if you want support for the built-in watchdog timer
|
||||
found in some Faraday FA526 based SoCs.
|
|
@ -0,0 +1,117 @@
|
|||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/dev-spi-master.c
|
||||
@@ -0,0 +1,83 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include <mach/hardware.h>
|
||||
+#include <mach/cns21xx.h>
|
||||
+#include <mach/cns21xx_misc.h>
|
||||
+#include <mach/cns21xx_powermgmt.h>
|
||||
+#include <mach/irqs.h>
|
||||
+
|
||||
+#include "common.h"
|
||||
+
|
||||
+static u64 spi_dmamask = DMA_BIT_MASK(32);
|
||||
+static struct resource cns21xx_spi_resources[] = {
|
||||
+ [0] = {
|
||||
+ .start = CNS21XX_SPI_BASE,
|
||||
+ .end = CNS21XX_SPI_BASE + SZ_4K - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ },
|
||||
+ [1] = {
|
||||
+ .start = CNS21XX_IRQ_SPI,
|
||||
+ .end = CNS21XX_IRQ_SPI,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct platform_device cns21xx_spi_master_device = {
|
||||
+ .name = "cns21xx-spi",
|
||||
+ .id = -1,
|
||||
+ .dev = {
|
||||
+ .dma_mask = &spi_dmamask,
|
||||
+ .coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
+ },
|
||||
+ .resource = cns21xx_spi_resources,
|
||||
+ .num_resources = ARRAY_SIZE(cns21xx_spi_resources),
|
||||
+};
|
||||
+
|
||||
+void __init cns21xx_register_spi_master(int id, struct spi_board_info *info,
|
||||
+ unsigned int n)
|
||||
+{
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ /* Enable SPI pins */
|
||||
+ HAL_MISC_ENABLE_SPIDR_PINS();
|
||||
+ HAL_MISC_ENABLE_SPICLK_PINS();
|
||||
+ for (i = 0; i < n; i++) {
|
||||
+ switch (info[i].chip_select) {
|
||||
+ case 0:
|
||||
+ HAL_MISC_ENABLE_SPICSN0_PINS();
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ HAL_MISC_ENABLE_SPICSN1_PINS();
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ HAL_MISC_ENABLE_SPICSN2_PINS();
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ HAL_MISC_ENABLE_SPICSN3_PINS();
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Disable SPI serial flash access through 0x30000000 region */
|
||||
+ HAL_MISC_DISABLE_SPI_SERIAL_FLASH_BANK_ACCESS();
|
||||
+
|
||||
+ /* Enable SPI clock */
|
||||
+ HAL_PWRMGT_ENABLE_SPI_CLOCK();
|
||||
+
|
||||
+ cns21xx_spi_master_device.id = id;
|
||||
+
|
||||
+ spi_register_board_info(info, n);
|
||||
+ platform_device_register(&cns21xx_spi_master_device);
|
||||
+}
|
||||
--- a/arch/arm/mach-cns21xx/Kconfig
|
||||
+++ b/arch/arm/mach-cns21xx/Kconfig
|
||||
@@ -6,4 +6,7 @@ endmenu
|
||||
config CNS21XX_DEV_USB
|
||||
def_bool n
|
||||
|
||||
+config CNS21XX_DEV_SPI_MASTER
|
||||
+ def_bool n
|
||||
+
|
||||
endif
|
||||
--- a/arch/arm/mach-cns21xx/Makefile
|
||||
+++ b/arch/arm/mach-cns21xx/Makefile
|
||||
@@ -8,6 +8,7 @@ obj-y := core.o devices.o gpio.o irq.o
|
||||
|
||||
# devices
|
||||
obj-$(CONFIG_CNS21XX_DEV_USB) += dev-usb.o
|
||||
+obj-$(CONFIG_CNS21XX_DEV_SPI_MASTER) += dev-spi-master.o
|
||||
|
||||
# machine specific files
|
||||
|
||||
--- a/arch/arm/mach-cns21xx/common.h
|
||||
+++ b/arch/arm/mach-cns21xx/common.h
|
||||
@@ -21,4 +21,8 @@ int __init cns21xx_register_uart1(void);
|
||||
int __init cns21xx_register_usb(void);
|
||||
int __init cns21xx_register_wdt(void);
|
||||
|
||||
+struct spi_board_info;
|
||||
+void __init cns21xx_register_spi_master(int id, struct spi_board_info *info,
|
||||
+ unsigned int n);
|
||||
+
|
||||
#endif /* _MACH_CNS21XX_COMMON_H */
|
|
@ -0,0 +1,178 @@
|
|||
--- a/arch/arm/mach-cns21xx/Kconfig
|
||||
+++ b/arch/arm/mach-cns21xx/Kconfig
|
||||
@@ -3,6 +3,9 @@ if ARCH_CNS21XX
|
||||
menu "Cavium Networks CNS21xx based machines"
|
||||
endmenu
|
||||
|
||||
+config CNS21XX_DEV_GEC
|
||||
+ def_bool n
|
||||
+
|
||||
config CNS21XX_DEV_USB
|
||||
def_bool n
|
||||
|
||||
--- a/arch/arm/mach-cns21xx/Makefile
|
||||
+++ b/arch/arm/mach-cns21xx/Makefile
|
||||
@@ -7,6 +7,7 @@
|
||||
obj-y := core.o devices.o gpio.o irq.o mm.o time.o
|
||||
|
||||
# devices
|
||||
+obj-$(CONFIG_CNS21XX_DEV_GEC) += dev-gec.o
|
||||
obj-$(CONFIG_CNS21XX_DEV_USB) += dev-usb.o
|
||||
obj-$(CONFIG_CNS21XX_DEV_SPI_MASTER) += dev-spi-master.o
|
||||
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/dev-gec.c
|
||||
@@ -0,0 +1,98 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/dma-mapping.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/etherdevice.h>
|
||||
+
|
||||
+#include <asm/sizes.h>
|
||||
+#include <mach/cns21xx.h>
|
||||
+#include <mach/irqs.h>
|
||||
+
|
||||
+#include "dev-gec.h"
|
||||
+
|
||||
+static u8 cns21xx_ethaddr[ETH_ALEN];
|
||||
+struct cns21xx_gec_plat_data cns21xx_gec_data;
|
||||
+
|
||||
+static struct resource cns21xx_gec_resources[] = {
|
||||
+ {
|
||||
+ .start = CNS21XX_NIC_BASE,
|
||||
+ .end = CNS21XX_NIC_BASE + SZ_4K - 1,
|
||||
+ .flags = IORESOURCE_MEM,
|
||||
+ }, {
|
||||
+ .name = CNS21XX_GEC_STATUS_IRQ_NAME,
|
||||
+ .start = CNS21XX_IRQ_NIC_STATUS,
|
||||
+ .end = CNS21XX_IRQ_NIC_STATUS,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ }, {
|
||||
+ .name = CNS21XX_GEC_RXRC_IRQ_NAME,
|
||||
+ .start = CNS21XX_IRQ_NIC_RXRC,
|
||||
+ .end = CNS21XX_IRQ_NIC_RXRC,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ }, {
|
||||
+ .name = CNS21XX_GEC_RXQF_IRQ_NAME,
|
||||
+ .start = CNS21XX_IRQ_NIC_RXQF,
|
||||
+ .end = CNS21XX_IRQ_NIC_RXQF,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ }, {
|
||||
+ .name = CNS21XX_GEC_TXTC_IRQ_NAME,
|
||||
+ .start = CNS21XX_IRQ_NIC_TXTC,
|
||||
+ .end = CNS21XX_IRQ_NIC_TXTC,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ }, {
|
||||
+ .name = CNS21XX_GEC_TXQE_IRQ_NAME,
|
||||
+ .start = CNS21XX_IRQ_NIC_TXQE,
|
||||
+ .end = CNS21XX_IRQ_NIC_TXQE,
|
||||
+ .flags = IORESOURCE_IRQ,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static u64 cns21xx_gec_dmamask = DMA_BIT_MASK(32);
|
||||
+static struct platform_device cns21xx_gec_device = {
|
||||
+ .name = "cns21xx-gec",
|
||||
+ .id = -1,
|
||||
+ .resource = cns21xx_gec_resources,
|
||||
+ .num_resources = ARRAY_SIZE(cns21xx_gec_resources),
|
||||
+ .dev = {
|
||||
+ .dma_mask = &cns21xx_gec_dmamask,
|
||||
+ .coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
+ .platform_data = &cns21xx_gec_data,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init cns21xx_ethaddr_setup(char *str)
|
||||
+{
|
||||
+ int t;
|
||||
+
|
||||
+ t = sscanf(str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
|
||||
+ &cns21xx_ethaddr[0], &cns21xx_ethaddr[1],
|
||||
+ &cns21xx_ethaddr[2], &cns21xx_ethaddr[3],
|
||||
+ &cns21xx_ethaddr[4], &cns21xx_ethaddr[5]);
|
||||
+
|
||||
+ if (t != ETH_ALEN)
|
||||
+ pr_err("cns21xx: failed to parse mac address \"%s\"\n", str);
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+__setup("ethaddr=", cns21xx_ethaddr_setup);
|
||||
+
|
||||
+__init int cns21xx_register_gec(void)
|
||||
+{
|
||||
+ if (cns21xx_gec_data.mac_addr == NULL)
|
||||
+ cns21xx_gec_data.mac_addr = cns21xx_ethaddr;
|
||||
+
|
||||
+ if (!is_valid_ether_addr(cns21xx_gec_data.mac_addr)) {
|
||||
+ random_ether_addr(cns21xx_gec_data.mac_addr);
|
||||
+ pr_debug("cns21xx: using random MAC address \"%s\"\n",
|
||||
+ cns21xx_gec_data.mac_addr);
|
||||
+ }
|
||||
+
|
||||
+ return platform_device_register(&cns21xx_gec_device);
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/dev-gec.h
|
||||
@@ -0,0 +1,18 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file 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 _CNS21XX_DEV_GEC_H
|
||||
+#define _CNS21XX_DEV_GEC_H
|
||||
+
|
||||
+#include <mach/cns21xx_gec_platform.h>
|
||||
+
|
||||
+extern struct cns21xx_gec_plat_data cns21xx_gec_data;
|
||||
+
|
||||
+__init int cns21xx_register_gec(void);
|
||||
+
|
||||
+#endif /* _CNS21XX_DEV_GEC_H */
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/include/mach/cns21xx_gec_platform.h
|
||||
@@ -0,0 +1,31 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file 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 _CNS21XX_GEC_PLATFORM_H
|
||||
+#define _CNS21XX_GEC_PLATFORM_H
|
||||
+
|
||||
+#define CNS21XX_GEC_STATUS_IRQ_NAME "status"
|
||||
+#define CNS21XX_GEC_RXRC_IRQ_NAME "rxrc"
|
||||
+#define CNS21XX_GEC_RXQF_IRQ_NAME "rxqf"
|
||||
+#define CNS21XX_GEC_TXTC_IRQ_NAME "txtc"
|
||||
+#define CNS21XX_GEC_TXQE_IRQ_NAME "txqe"
|
||||
+
|
||||
+enum cns21xx_gec_phy_type {
|
||||
+ CNS21XX_GEC_PHY_TYPE_INTERNAL = 0,
|
||||
+ CNS21XX_GEC_PHY_TYPE_VSC8601,
|
||||
+ CNS21XX_GEC_PHY_TYPE_IP101A,
|
||||
+ CNS21XX_GEC_PHY_TYPE_IP1001,
|
||||
+};
|
||||
+
|
||||
+struct cns21xx_gec_plat_data {
|
||||
+ u8 *mac_addr;
|
||||
+ enum cns21xx_gec_phy_type phy_type;
|
||||
+ u8 phy_addr;
|
||||
+};
|
||||
+
|
||||
+#endif /* _CNS21XX_GEC_PLATFORM_H */
|
|
@ -0,0 +1,240 @@
|
|||
--- a/arch/arm/mach-cns21xx/Kconfig
|
||||
+++ b/arch/arm/mach-cns21xx/Kconfig
|
||||
@@ -1,6 +1,16 @@
|
||||
if ARCH_CNS21XX
|
||||
|
||||
menu "Cavium Networks CNS21xx based machines"
|
||||
+
|
||||
+config MACH_NS_K330
|
||||
+ bool "NS-K330 NAS"
|
||||
+ select CNS21XX_DEV_GEC
|
||||
+ select CNS21XX_DEV_SPI_MASTER
|
||||
+ select CNS21XX_DEV_USB
|
||||
+ help
|
||||
+ Say Y here if you intend to run this kernel on the
|
||||
+ NS-K330 NAS board.
|
||||
+
|
||||
endmenu
|
||||
|
||||
config CNS21XX_DEV_GEC
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/mach-ns-k330.c
|
||||
@@ -0,0 +1,210 @@
|
||||
+/*
|
||||
+ * NS-K330 NAS board support
|
||||
+ *
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/map.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+#include <linux/spi/flash.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/leds.h>
|
||||
+#include <linux/gpio_keys.h>
|
||||
+#include <linux/input.h>
|
||||
+
|
||||
+#include <asm/setup.h>
|
||||
+#include <asm/mach-types.h>
|
||||
+#include <asm/mach/arch.h>
|
||||
+#include <asm/mach/time.h>
|
||||
+#include <mach/hardware.h>
|
||||
+#include <mach/cns21xx.h>
|
||||
+#include <mach/cns21xx_misc.h>
|
||||
+
|
||||
+#include "common.h"
|
||||
+#include "dev-gec.h"
|
||||
+
|
||||
+#define NS_K330_GPIO_LED_LINK 1
|
||||
+#define NS_K330_GPIO_LED_USB1 16
|
||||
+#define NS_K330_GPIO_LED_USB2 17
|
||||
+#define NS_K330_GPIO_LED_ETH_GREEN 22
|
||||
+#define NS_K330_GPIO_LED_ETH_ORANGE 23
|
||||
+
|
||||
+#define NS_K330_GPIO_BTN_RESET 13
|
||||
+#define NS_K330_GPIO_BTN_USB1 14
|
||||
+#define NS_K330_GPIO_BTN_USB2 15
|
||||
+
|
||||
+#ifdef CONFIG_MTD_PARTITIONS
|
||||
+static struct mtd_partition ns_k330_partitions[] = {
|
||||
+ {
|
||||
+ .name = "boot",
|
||||
+ .offset = 0x0,
|
||||
+ .size = 0x040000,
|
||||
+ .mask_flags = MTD_WRITEABLE,
|
||||
+ }, {
|
||||
+ .name = "config",
|
||||
+ .offset = 0x040000,
|
||||
+ .size = 0x020000,
|
||||
+ .mask_flags = MTD_WRITEABLE,
|
||||
+ }, {
|
||||
+ .name = "kernel",
|
||||
+ .offset = 0x060000,
|
||||
+ .size = 0x100000,
|
||||
+ }, {
|
||||
+ .name = "rootfs",
|
||||
+ .offset = 0x160000,
|
||||
+ .size = 0x290000,
|
||||
+ }, {
|
||||
+ .name = "firmware",
|
||||
+ .offset = 0x060000,
|
||||
+ .size = 0x390000,
|
||||
+ },
|
||||
+};
|
||||
+#else
|
||||
+#define ns_k330_partitions NULL
|
||||
+#define ns_k330_num_partitions 0
|
||||
+#endif /* CONFIG_MTD_PARTITIONS */
|
||||
+
|
||||
+static struct flash_platform_data ns_k330_flash_data = {
|
||||
+ .parts = ns_k330_partitions,
|
||||
+ .nr_parts = ARRAY_SIZE(ns_k330_partitions),
|
||||
+};
|
||||
+
|
||||
+static struct spi_board_info ns_k330_spi_board_info[] = {
|
||||
+ {
|
||||
+ .bus_num = 0,
|
||||
+ .chip_select = 0,
|
||||
+ .max_speed_hz = 25000000,
|
||||
+ .modalias = "m25p80",
|
||||
+ .platform_data = &ns_k330_flash_data,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct gpio_led ns_k330_gpio_leds[] = {
|
||||
+ {
|
||||
+ .name = "ns-k330:red:link",
|
||||
+ .gpio = NS_K330_GPIO_LED_LINK,
|
||||
+ .active_low = 1,
|
||||
+ }, {
|
||||
+ .name = "ns-k330:green:usb1",
|
||||
+ .gpio = NS_K330_GPIO_LED_USB1,
|
||||
+ .active_low = 1,
|
||||
+ }, {
|
||||
+ .name = "ns-k330:green:usb2",
|
||||
+ .gpio = NS_K330_GPIO_LED_USB2,
|
||||
+ .active_low = 1,
|
||||
+ }, {
|
||||
+ .name = "ns-k330:green:eth",
|
||||
+ .gpio = NS_K330_GPIO_LED_ETH_GREEN,
|
||||
+ .active_low = 1,
|
||||
+ }, {
|
||||
+ .name = "ns-k330:orange:eth",
|
||||
+ .gpio = NS_K330_GPIO_LED_ETH_ORANGE,
|
||||
+ .active_low = 1,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct gpio_led_platform_data ns_k330_gpio_leds_data = {
|
||||
+ .num_leds = ARRAY_SIZE(ns_k330_gpio_leds),
|
||||
+ .leds = ns_k330_gpio_leds,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device ns_k330_gpio_leds_device = {
|
||||
+ .name = "leds-gpio",
|
||||
+ .id = -1,
|
||||
+ .dev.platform_data = &ns_k330_gpio_leds_data,
|
||||
+};
|
||||
+
|
||||
+static struct gpio_keys_button ns_k330_gpio_keys[] = {
|
||||
+ {
|
||||
+ .code = KEY_RESTART,
|
||||
+ .gpio = NS_K330_GPIO_BTN_RESET,
|
||||
+ .desc = "Reset Button",
|
||||
+ .active_low = 1,
|
||||
+ },
|
||||
+ {
|
||||
+ .code = BTN_0,
|
||||
+ .gpio = NS_K330_GPIO_BTN_USB1,
|
||||
+ .desc = "USB1 Button",
|
||||
+ .active_low = 1,
|
||||
+ },
|
||||
+ {
|
||||
+ .code = BTN_1,
|
||||
+ .gpio = NS_K330_GPIO_BTN_USB2,
|
||||
+ .desc = "USB2 Button",
|
||||
+ .active_low = 0,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct gpio_keys_platform_data ns_k330_gpio_keys_data = {
|
||||
+ .buttons = ns_k330_gpio_keys,
|
||||
+ .nbuttons = ARRAY_SIZE(ns_k330_gpio_keys),
|
||||
+};
|
||||
+
|
||||
+static struct platform_device ns_k330_gpio_keys_device = {
|
||||
+ .name = "gpio-keys",
|
||||
+ .id = -1,
|
||||
+ .num_resources = 0,
|
||||
+ .dev = {
|
||||
+ .platform_data = &ns_k330_gpio_keys_data,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void __init ns_k330_fixup(struct machine_desc *desc,
|
||||
+ struct tag *tags, char **cmdline,
|
||||
+ struct meminfo *mi)
|
||||
+{
|
||||
+ struct tag *t;
|
||||
+
|
||||
+ /* The board has 32MB of RAM mapped at 0. */
|
||||
+ mi->nr_banks = 1;
|
||||
+ mi->bank[0].start = 0;
|
||||
+ mi->bank[0].size = SZ_32M;
|
||||
+
|
||||
+ for (t = tags; t->hdr.size; t = tag_next(t)) {
|
||||
+ switch (t->hdr.tag) {
|
||||
+ case ATAG_CORE:
|
||||
+ if (t->u.core.rootdev == 255)
|
||||
+ t->u.core.rootdev = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void __init ns_k330_init(void)
|
||||
+{
|
||||
+ cns21xx_gpio_init();
|
||||
+
|
||||
+ HAL_MISC_DISABLE_LED012_PINS();
|
||||
+ HAL_MISC_DISABLE_I2C_PINS();
|
||||
+ HAL_MISC_DISABLE_I2S_PINS();
|
||||
+
|
||||
+ cns21xx_register_uart0();
|
||||
+ cns21xx_register_wdt();
|
||||
+ cns21xx_register_usb();
|
||||
+ cns21xx_register_spi_master(-1, ns_k330_spi_board_info,
|
||||
+ ARRAY_SIZE(ns_k330_spi_board_info));
|
||||
+
|
||||
+ cns21xx_gec_data.phy_type = CNS21XX_GEC_PHY_TYPE_INTERNAL;
|
||||
+ cns21xx_register_gec();
|
||||
+
|
||||
+ platform_device_register(&ns_k330_gpio_leds_device);
|
||||
+ platform_device_register(&ns_k330_gpio_keys_device);
|
||||
+}
|
||||
+
|
||||
+MACHINE_START(NS_K330, "NS-K330 NAS")
|
||||
+ .boot_params = 0x100,
|
||||
+ .fixup = ns_k330_fixup,
|
||||
+ .map_io = cns21xx_map_io,
|
||||
+ .init_irq = cns21xx_init_irq,
|
||||
+ .timer = &cns21xx_timer,
|
||||
+ .init_machine = ns_k330_init,
|
||||
+MACHINE_END
|
||||
--- a/arch/arm/mach-cns21xx/Makefile
|
||||
+++ b/arch/arm/mach-cns21xx/Makefile
|
||||
@@ -12,4 +12,4 @@ obj-$(CONFIG_CNS21XX_DEV_USB) += dev-us
|
||||
obj-$(CONFIG_CNS21XX_DEV_SPI_MASTER) += dev-spi-master.o
|
||||
|
||||
# machine specific files
|
||||
-
|
||||
+obj-$(CONFIG_MACH_NS_K330) += mach-ns-k330.o
|
|
@ -0,0 +1,207 @@
|
|||
--- a/arch/arm/mach-cns21xx/Kconfig
|
||||
+++ b/arch/arm/mach-cns21xx/Kconfig
|
||||
@@ -2,6 +2,15 @@ if ARCH_CNS21XX
|
||||
|
||||
menu "Cavium Networks CNS21xx based machines"
|
||||
|
||||
+config MACH_NSB3AST
|
||||
+ bool "AGESTAR NSB3AST support"
|
||||
+ select CNS21XX_DEV_GEC
|
||||
+ select CNS21XX_DEV_SPI_MASTER
|
||||
+ select CNS21XX_DEV_USB
|
||||
+ help
|
||||
+ Say Y here if you intend to run this kernel on the
|
||||
+ AGESTAR NSB3AST board.
|
||||
+
|
||||
config MACH_NS_K330
|
||||
bool "NS-K330 NAS"
|
||||
select CNS21XX_DEV_GEC
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-cns21xx/mach-nsb3ast.c
|
||||
@@ -0,0 +1,179 @@
|
||||
+/*
|
||||
+ * AGESTAR NSB3AST board support
|
||||
+ *
|
||||
+ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org>
|
||||
+ *
|
||||
+ * This file is free software; you can redistribute it and/or modify
|
||||
+ * it under the terms of the GNU General Public License, Version 2, as
|
||||
+ * published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/mtd/mtd.h>
|
||||
+#include <linux/mtd/map.h>
|
||||
+#include <linux/mtd/partitions.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+#include <linux/spi/flash.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/leds.h>
|
||||
+#include <linux/gpio_keys.h>
|
||||
+#include <linux/input.h>
|
||||
+
|
||||
+#include <asm/setup.h>
|
||||
+#include <asm/mach-types.h>
|
||||
+#include <asm/mach/arch.h>
|
||||
+#include <asm/mach/time.h>
|
||||
+#include <mach/hardware.h>
|
||||
+#include <mach/cns21xx.h>
|
||||
+#include <mach/cns21xx_misc.h>
|
||||
+
|
||||
+#include "common.h"
|
||||
+#include "dev-gec.h"
|
||||
+
|
||||
+#ifdef CONFIG_MTD_PARTITIONS
|
||||
+static struct mtd_partition nsb3ast_partitions[] = {
|
||||
+ {
|
||||
+ .name = "armboot",
|
||||
+ .offset = 0x0,
|
||||
+ .size = 0x040000,
|
||||
+ .mask_flags = MTD_WRITEABLE,
|
||||
+ }, {
|
||||
+ .name = "kernel",
|
||||
+ .offset = 0x040000,
|
||||
+ .size = 0x100000,
|
||||
+ }, {
|
||||
+ .name = "rootfs",
|
||||
+ .offset = 0x140000,
|
||||
+ .size = 0x6c0000,
|
||||
+ }, {
|
||||
+ .name = "firmware",
|
||||
+ .offset = 0x040000,
|
||||
+ .size = 0x7c0000,
|
||||
+ }, {
|
||||
+ .name = "wholeflash",
|
||||
+ .offset = 0x0,
|
||||
+ .size = 0x800000,
|
||||
+ .mask_flags = MTD_WRITEABLE,
|
||||
+ },
|
||||
+};
|
||||
+#else
|
||||
+#define nsb3ast_partitions NULL
|
||||
+#define nsb3ast_num_partitions 0
|
||||
+#endif /* CONFIG_MTD_PARTITIONS */
|
||||
+
|
||||
+static struct flash_platform_data nsb3ast_flash_data = {
|
||||
+ .parts = nsb3ast_partitions,
|
||||
+ .nr_parts = ARRAY_SIZE(nsb3ast_partitions),
|
||||
+};
|
||||
+
|
||||
+static struct spi_board_info nsb3ast_spi_board_info[] = {
|
||||
+ {
|
||||
+ .bus_num = 0,
|
||||
+ .chip_select = 0,
|
||||
+ .max_speed_hz = 25000000,
|
||||
+ .modalias = "m25p80",
|
||||
+ .platform_data = &nsb3ast_flash_data,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct gpio_led nsb3ast_gpio_leds[] = {
|
||||
+ {
|
||||
+ .name = "nsb3ast:red:d1",
|
||||
+ .gpio = 15,
|
||||
+ .active_low = 1,
|
||||
+ }, {
|
||||
+ .name = "nsb3ast:amber:eth",
|
||||
+ .gpio = 22,
|
||||
+ .active_low = 1,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct gpio_led_platform_data nsb3ast_gpio_leds_data = {
|
||||
+ .num_leds = ARRAY_SIZE(nsb3ast_gpio_leds),
|
||||
+ .leds = nsb3ast_gpio_leds,
|
||||
+};
|
||||
+
|
||||
+static struct platform_device nsb3ast_gpio_leds_device = {
|
||||
+ .name = "leds-gpio",
|
||||
+ .id = -1,
|
||||
+ .dev.platform_data = &nsb3ast_gpio_leds_data,
|
||||
+};
|
||||
+
|
||||
+static struct gpio_keys_button nsb3ast_gpio_keys[] = {
|
||||
+ {
|
||||
+ .code = KEY_RESTART,
|
||||
+ .gpio = 0,
|
||||
+ .desc = "Reset Button",
|
||||
+ .active_low = 1,
|
||||
+ },
|
||||
+ {
|
||||
+ .code = BTN_0,
|
||||
+ .gpio = 2,
|
||||
+ .desc = "USB Button",
|
||||
+ .active_low = 0,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct gpio_keys_platform_data nsb3ast_gpio_keys_data = {
|
||||
+ .buttons = nsb3ast_gpio_keys,
|
||||
+ .nbuttons = ARRAY_SIZE(nsb3ast_gpio_keys),
|
||||
+};
|
||||
+
|
||||
+static struct platform_device nsb3ast_gpio_keys_device = {
|
||||
+ .name = "gpio-keys",
|
||||
+ .id = -1,
|
||||
+ .num_resources = 0,
|
||||
+ .dev = {
|
||||
+ .platform_data = &nsb3ast_gpio_keys_data,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void __init nsb3ast_fixup(struct machine_desc *desc,
|
||||
+ struct tag *tags, char **cmdline,
|
||||
+ struct meminfo *mi)
|
||||
+{
|
||||
+ struct tag *t;
|
||||
+
|
||||
+ /* The board has 32MB of RAM mapped at 0. */
|
||||
+ mi->nr_banks = 1;
|
||||
+ mi->bank[0].start = 0;
|
||||
+ mi->bank[0].size = SZ_32M;
|
||||
+
|
||||
+ for (t = tags; t->hdr.size; t = tag_next(t)) {
|
||||
+ switch (t->hdr.tag) {
|
||||
+ case ATAG_CORE:
|
||||
+ if (t->u.core.rootdev == 255)
|
||||
+ t->u.core.rootdev = 0;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void __init nsb3ast_init(void)
|
||||
+{
|
||||
+ cns21xx_gpio_init();
|
||||
+ cns21xx_register_uart0();
|
||||
+ cns21xx_register_uart1();
|
||||
+ cns21xx_register_wdt();
|
||||
+ cns21xx_register_usb();
|
||||
+ cns21xx_register_spi_master(-1, nsb3ast_spi_board_info,
|
||||
+ ARRAY_SIZE(nsb3ast_spi_board_info));
|
||||
+
|
||||
+ cns21xx_gec_data.phy_type = CNS21XX_GEC_PHY_TYPE_INTERNAL;
|
||||
+ cns21xx_register_gec();
|
||||
+
|
||||
+ HAL_MISC_DISABLE_LED012_PINS();
|
||||
+ platform_device_register(&nsb3ast_gpio_leds_device);
|
||||
+ platform_device_register(&nsb3ast_gpio_keys_device);
|
||||
+}
|
||||
+
|
||||
+MACHINE_START(NSB3AST, "AGESTAR NSB3AST")
|
||||
+ .boot_params = 0x100,
|
||||
+ .fixup = nsb3ast_fixup,
|
||||
+ .map_io = cns21xx_map_io,
|
||||
+ .init_irq = cns21xx_init_irq,
|
||||
+ .timer = &cns21xx_timer,
|
||||
+ .init_machine = nsb3ast_init,
|
||||
+MACHINE_END
|
||||
--- a/arch/arm/mach-cns21xx/Makefile
|
||||
+++ b/arch/arm/mach-cns21xx/Makefile
|
||||
@@ -13,3 +13,4 @@ obj-$(CONFIG_CNS21XX_DEV_SPI_MASTER) +=
|
||||
|
||||
# machine specific files
|
||||
obj-$(CONFIG_MACH_NS_K330) += mach-ns-k330.o
|
||||
+obj-$(CONFIG_MACH_NSB3AST) += mach-nsb3ast.o
|
|
@ -0,0 +1,17 @@
|
|||
#
|
||||
# Copyright (C) 2010 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
define Profile/Default
|
||||
NAME:=Default Profile (all drivers)
|
||||
PACKAGES:= \
|
||||
kmod-usb-core kmod-usb-ohci kmod-usb2 kmod-ledtrig-usbdev
|
||||
endef
|
||||
|
||||
define Profile/Default/Description
|
||||
Default package set compatible with most boards.
|
||||
endef
|
||||
$(eval $(call Profile,Default))
|
|
@ -91,6 +91,7 @@ config EABI_SUPPORT
|
|||
depends arm||armeb
|
||||
prompt "Enable EABI support" if TOOLCHAINOPTS
|
||||
default n if TARGET_gemini
|
||||
default n if TARGET_cns21xx
|
||||
default y
|
||||
help
|
||||
Enable ARM EABI support
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
choice
|
||||
prompt "GCC compiler Version" if TOOLCHAINOPTS
|
||||
default GCC_VERSION_4_3_5 if (avr32 || powerpc64)
|
||||
default GCC_VERSION_4_3_5 if (TARGET_coldfire || TARGET_etrax || TARGET_gemini)
|
||||
default GCC_VERSION_4_3_3_CS if (arm || armeb) && !(TARGET_gemini || TARGET_omap35xx)
|
||||
default GCC_VERSION_4_3_5 if (TARGET_coldfire || TARGET_etrax || TARGET_gemini || TARGET_cns21xx)
|
||||
default GCC_VERSION_4_3_3_CS if (arm || armeb) && !(TARGET_gemini || TARGET_cns21xx || TARGET_omap35xx)
|
||||
default GCC_VERSION_4_3_3_CS if (mips || mipsel) && !(TARGET_octeon || TARGET_sibyte)
|
||||
default GCC_VERSION_4_4_5 if (powerpc || ubicom32)
|
||||
default GCC_VERSION_4_4_5 if (TARGET_omap35xx || TARGET_octeon || TARGET_sibyte)
|
||||
|
|
|
@ -47,7 +47,7 @@ if !TOOLCHAINOPTS
|
|||
|
||||
config GCC_VERSION_4_3_3_CS
|
||||
default y if (mips || mipsel) && !(TARGET_octeon || TARGET_sibyte)
|
||||
default y if (arm || armeb) && !(TARGET_gemini || TARGET_omap35xx)
|
||||
default y if (arm || armeb) && !(TARGET_gemini || TARGET_cns21xx || TARGET_omap35xx)
|
||||
|
||||
config GCC_VERSION_4_3_5
|
||||
default y if avr32
|
||||
|
@ -55,6 +55,7 @@ if !TOOLCHAINOPTS
|
|||
default y if TARGET_etrax
|
||||
default y if TARGET_coldfire
|
||||
default y if TARGET_gemini
|
||||
default y if TARGET_cns21xx
|
||||
|
||||
config GCC_VERSION_4_4_5
|
||||
default y if (TARGET_octeon || TARGET_sibyte || TARGET_omap35xx)
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
ARCH_ANY_ENDIAN=y
|
||||
ARCH_LITTLE_ENDIAN=y
|
||||
ARCH_WANTS_LITTLE_ENDIAN=y
|
||||
# CONFIG_ARM10T is not set
|
||||
# CONFIG_ARM1136JF_S is not set
|
||||
# CONFIG_ARM1176JZF_S is not set
|
||||
# CONFIG_ARM1176JZ_S is not set
|
||||
# CONFIG_ARM610 is not set
|
||||
# CONFIG_ARM710 is not set
|
||||
# CONFIG_ARM720T is not set
|
||||
# CONFIG_ARM7TDMI is not set
|
||||
CONFIG_ARM920T=y
|
||||
# CONFIG_ARM922T is not set
|
||||
# CONFIG_ARM926T is not set
|
||||
# CONFIG_ARM_CORTEX_M1 is not set
|
||||
# CONFIG_ARM_CORTEX_M3 is not set
|
||||
# CONFIG_ARM_EABI is not set
|
||||
# CONFIG_ARM_IWMMXT is not set
|
||||
CONFIG_ARM_OABI=y
|
||||
# CONFIG_ARM_SA110 is not set
|
||||
# CONFIG_ARM_SA1100 is not set
|
||||
# CONFIG_ARM_XSCALE is not set
|
||||
# CONFIG_GENERIC_ARM is not set
|
||||
TARGET_ARCH="arm"
|
||||
TARGET_arm=y
|
||||
# USE_BX is not set
|
|
@ -0,0 +1,26 @@
|
|||
ARCH_ANY_ENDIAN=y
|
||||
ARCH_LITTLE_ENDIAN=y
|
||||
ARCH_WANTS_LITTLE_ENDIAN=y
|
||||
# CONFIG_ARM10T is not set
|
||||
# CONFIG_ARM1136JF_S is not set
|
||||
# CONFIG_ARM1176JZF_S is not set
|
||||
# CONFIG_ARM1176JZ_S is not set
|
||||
# CONFIG_ARM610 is not set
|
||||
# CONFIG_ARM710 is not set
|
||||
# CONFIG_ARM720T is not set
|
||||
# CONFIG_ARM7TDMI is not set
|
||||
CONFIG_ARM920T=y
|
||||
# CONFIG_ARM922T is not set
|
||||
# CONFIG_ARM926T is not set
|
||||
# CONFIG_ARM_CORTEX_M1 is not set
|
||||
# CONFIG_ARM_CORTEX_M3 is not set
|
||||
# CONFIG_ARM_EABI is not set
|
||||
# CONFIG_ARM_IWMMXT is not set
|
||||
CONFIG_ARM_OABI=y
|
||||
# CONFIG_ARM_SA110 is not set
|
||||
# CONFIG_ARM_SA1100 is not set
|
||||
# CONFIG_ARM_XSCALE is not set
|
||||
# CONFIG_GENERIC_ARM is not set
|
||||
TARGET_ARCH="arm"
|
||||
TARGET_arm=y
|
||||
# USE_BX is not set
|
|
@ -0,0 +1,26 @@
|
|||
ARCH_ANY_ENDIAN=y
|
||||
ARCH_LITTLE_ENDIAN=y
|
||||
ARCH_WANTS_LITTLE_ENDIAN=y
|
||||
# CONFIG_ARM10T is not set
|
||||
# CONFIG_ARM1136JF_S is not set
|
||||
# CONFIG_ARM1176JZF_S is not set
|
||||
# CONFIG_ARM1176JZ_S is not set
|
||||
# CONFIG_ARM610 is not set
|
||||
# CONFIG_ARM710 is not set
|
||||
# CONFIG_ARM720T is not set
|
||||
# CONFIG_ARM7TDMI is not set
|
||||
CONFIG_ARM920T=y
|
||||
# CONFIG_ARM922T is not set
|
||||
# CONFIG_ARM926T is not set
|
||||
# CONFIG_ARM_CORTEX_M1 is not set
|
||||
# CONFIG_ARM_CORTEX_M3 is not set
|
||||
# CONFIG_ARM_EABI is not set
|
||||
# CONFIG_ARM_IWMMXT is not set
|
||||
CONFIG_ARM_OABI=y
|
||||
# CONFIG_ARM_SA110 is not set
|
||||
# CONFIG_ARM_SA1100 is not set
|
||||
# CONFIG_ARM_XSCALE is not set
|
||||
# CONFIG_GENERIC_ARM is not set
|
||||
TARGET_ARCH="arm"
|
||||
TARGET_arm=y
|
||||
# USE_BX is not set
|
Loading…
Reference in New Issue