diff options
author | Waldemar Brodkorb <wbx@openadk.org> | 2009-06-04 19:48:44 +0200 |
---|---|---|
committer | Waldemar Brodkorb <wbx@openadk.org> | 2009-06-04 19:48:44 +0200 |
commit | 9bd4456c5a83c3474fdf9fe5cf14004a0874e2c8 (patch) | |
tree | 2c8ac1a18a6f40388a5e2a64e86c32ec63a42f3f | |
parent | a1373c5ba4bbc90e4b20191e56f728df797bf7bc (diff) |
add experimental linksys wag54h ar7 support
- network interface does not work, but system can boot
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | scripts/scan-pkgs.sh | 11 | ||||
-rw-r--r-- | target/Config.in | 23 | ||||
-rw-r--r-- | target/foxboard/tools/e100boot/Makefile | 2 | ||||
-rw-r--r-- | target/foxboard/tools/squashfs/Makefile | 2 | ||||
-rw-r--r-- | target/linux/config/Config.in.network | 2 | ||||
-rw-r--r-- | target/wag54g/Makefile | 54 | ||||
-rw-r--r-- | target/wag54g/device.mk | 7 | ||||
-rw-r--r-- | target/wag54g/files/etc/mdev.conf | 11 | ||||
-rw-r--r-- | target/wag54g/kernel.config | 904 | ||||
-rw-r--r-- | target/wag54g/patches/ar7.patch | 5087 | ||||
-rw-r--r-- | target/wag54g/tools/addpattern/Makefile | 4 | ||||
-rw-r--r-- | target/wag54g/tools/addpattern/addpattern.c | 255 | ||||
-rw-r--r-- | target/wag54g/tools/rules.mk | 9 | ||||
-rw-r--r-- | target/wag54g/tools/squashfs/Makefile | 27 | ||||
-rw-r--r-- | target/wag54g/tools/srec2bin/Makefile | 4 | ||||
-rw-r--r-- | target/wag54g/tools/srec2bin/srec2bin.c | 524 | ||||
-rw-r--r-- | target/wag54g/uclibc.config | 250 |
18 files changed, 7173 insertions, 4 deletions
diff --git a/.gitignore b/.gitignore index 3bfb728a2..931ccdf1e 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ config/*.o make.log dl/ package/*/info.mk +tools_build/ diff --git a/scripts/scan-pkgs.sh b/scripts/scan-pkgs.sh index ee62ed33f..c40f7c43d 100644 --- a/scripts/scan-pkgs.sh +++ b/scripts/scan-pkgs.sh @@ -30,6 +30,10 @@ if [[ -n $ADK_PACKAGE_ALSA_UTILS ]]; then NEED_XMLTO="$NEED_XMLTO alsa-utils" fi +if [[ -n $ADK_PACKAGE_XKEYBOARD_CONFIG ]]; then + NEED_XKBCOMP="$NEED_XKBCOMP xkeyboard-config" +fi + if [[ -n $ADK_COMPILE_AVAHI ]]; then NEED_PKGCONFIG="$NEED_PKGCONFIG avahi" fi @@ -63,6 +67,13 @@ if [[ -n $NEED_RUBY ]]; then fi fi +if [[ -n $NEED_XKBCOMP ]]; then + if ! which xkbcomp >/dev/null 2>&1; then + echo >&2 You need xkbcomp to build $NEED_XKBCOMP + out=1 + fi +fi + if [[ -n $NEED_XMLTO ]]; then if ! which xmlto >/dev/null 2>&1; then echo >&2 You need xmlto to build $NEED_XMLTO diff --git a/target/Config.in b/target/Config.in index 096aec6a9..7cffc9fd5 100644 --- a/target/Config.in +++ b/target/Config.in @@ -60,6 +60,9 @@ config ADK_rescue_mips config ADK_rescue_mipsel tristate +config ADK_wag54g + tristate + config ADK_DEVICE string default "alix1c" if ADK_alix1c @@ -76,6 +79,7 @@ config ADK_DEVICE default "rb433" if ADK_rb433 default "zaurus" if ADK_arm default "lemote" if ADK_lemote + default "wag54g" if ADK_wag54g default "rescue-x86" if ADK_rescue_x86 default "rescue-x86_64" if ADK_rescue_x86_64 default "rescue-mips" if ADK_rescue_mips @@ -103,6 +107,7 @@ config ADK_LINUX_X86_ALIX1C select ADK_alix1c select ADK_KERNEL_SCSI select ADK_KERNEL_EXT2_FS + select ADK_KERNEL_NETDEVICES select ADK_KERNEL_NET_PCI select ADK_KERNEL_NET_ETHERNET select ADK_KERNEL_MII @@ -124,9 +129,21 @@ config ADK_LINUX_MIPS64_LEMOTE help Lemote Subnotebook +config ADK_LINUX_MIPS_WAG54G + bool "Linksys WAG54G" + select ADK_KERNEL_NETDEVICES + select ADK_KERNEL_NET_PCI + select ADK_KERNEL_NET_ETHERNET + select ADK_KERNEL_MII + select ADK_wag54g + help + Linksys WAG54G DSL router with Wireless + TI AR7 platform + config ADK_LINUX_MIPS_RB411 bool "Mikrotik Routerboard 411" select ADK_rb411 + select ADK_KERNEL_NETDEVICES select ADK_KERNEL_NET_PCI select ADK_KERNEL_NETDEV_1000 select ADK_KERNEL_NET_ETHERNET @@ -136,6 +153,7 @@ config ADK_LINUX_MIPS_RB411 config ADK_LINUX_MIPS_RB433 bool "Mikrotik Routerboard 433" select ADK_rb433 + select ADK_KERNEL_NETDEVICES select ADK_KERNEL_NET_PCI select ADK_KERNEL_NETDEV_1000 select ADK_KERNEL_NET_ETHERNET @@ -145,6 +163,7 @@ config ADK_LINUX_MIPS_RB433 config ADK_LINUX_MIPS_RB532 bool "Mikrotik Routerboard 532" select ADK_rb532 + select ADK_KERNEL_NETDEVICES select ADK_KERNEL_NET_PCI select ADK_KERNEL_NET_ETHERNET select ADK_KERNEL_MII @@ -309,7 +328,8 @@ config ADK_TARGET_ROOTFS_INITRAMFS config ADK_TARGET_ROOTFS_SQUASHFS bool "squashfs read-only root filesystem" - depends on ADK_LINUX_CRIS_FOXBOARD + depends on ADK_LINUX_CRIS_FOXBOARD || \ + ADK_LINUX_MIPS_WAG54G help highly compressed read-only filesystem for flash. @@ -328,6 +348,7 @@ config ADK_TARGET_ROOTFS_NFSROOT ADK_LINUX_MIPS_RB532 || \ ADK_LINUX_MIPS_RB433 || \ ADK_LINUX_MIPS_RB411 || \ + ADK_LINUX_MIPS_WAG54G || \ ADK_LINUX_MIPS64_LEMOTE select ADK_KERNEL_NFS_FS select ADK_KERNEL_NFS_V3 diff --git a/target/foxboard/tools/e100boot/Makefile b/target/foxboard/tools/e100boot/Makefile index 9e9f78861..a6eba9dad 100644 --- a/target/foxboard/tools/e100boot/Makefile +++ b/target/foxboard/tools/e100boot/Makefile @@ -9,7 +9,7 @@ PKG_NAME:= e100boot PKG_VERSION:= 0.1 PKG_RELEASE:= 1 PKG_MD5SUM:= 11fd53e7824dc550e4cffbc4cd114c3e -MASTER_SITES:= http://download.tuxfamily.org/crisos/repository/source/ +PKG_SITES:= http://download.tuxfamily.org/crisos/repository/source/ DISTFILES:= ${PKG_NAME}.tar.bz2 WRKDIST= ${WRKDIR}/${PKG_NAME} diff --git a/target/foxboard/tools/squashfs/Makefile b/target/foxboard/tools/squashfs/Makefile index 866beabf5..0887afc22 100644 --- a/target/foxboard/tools/squashfs/Makefile +++ b/target/foxboard/tools/squashfs/Makefile @@ -9,7 +9,7 @@ PKG_NAME:= squashfs PKG_VERSION:= 4.0 PKG_RELEASE:= 1 PKG_MD5SUM:= a3c23391da4ebab0ac4a75021ddabf96 -MASTER_SITES:= ${MASTER_SITE_SOURCEFORGE:=squashfs/} +PKG_SITES:= ${MASTER_SITE_SOURCEFORGE:=squashfs/} DISTFILES:= ${PKG_NAME}${PKG_VERSION}.tar.gz WRKDIST= ${WRKDIR}/$(PKG_NAME)${PKG_VERSION} diff --git a/target/linux/config/Config.in.network b/target/linux/config/Config.in.network index 724233ab3..7390b061d 100644 --- a/target/linux/config/Config.in.network +++ b/target/linux/config/Config.in.network @@ -10,7 +10,7 @@ config ADK_KERNEL_IP_FIB_HASH config ADK_KERNEL_SYN_COOKIES boolean - default y + default n config ADK_KERNEL_IP_PNP_BOOTP boolean diff --git a/target/wag54g/Makefile b/target/wag54g/Makefile new file mode 100644 index 000000000..2c7f1581b --- /dev/null +++ b/target/wag54g/Makefile @@ -0,0 +1,54 @@ +# $Id: Makefile 30 2008-09-04 13:31:09Z wbx $ +#- +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +include $(TOPDIR)/rules.mk +include $(TOPDIR)/mk/kernel.mk +include $(TOPDIR)/mk/modules.mk +include $(TOPDIR)/mk/kernel-build.mk +include $(TOPDIR)/mk/image.mk + +$(TOOLS_BUILD_DIR): + mkdir -p $(TOOLS_BUILD_DIR) + +tools-compile: $(TOOLS_BUILD_DIR) + $(MAKE) -C tools/addpattern + $(MAKE) -C tools/srec2bin + $(MAKE) -C tools/squashfs prepare compile install + +kernel-install: tools-compile + PATH='${TARGET_PATH}' \ + mipsel-linux-objcopy -S -O srec $(LINUX_DIR)/vmlinux \ + $(LINUX_DIR)/vmlinux.srec + PATH='${TARGET_PATH}' \ + srec2bin $(LINUX_DIR)/vmlinux.srec $(LINUX_DIR)/vmlinux.bin + (dd if=/dev/zero bs=16 count=1; cat $(LINUX_DIR)/vmlinux.bin) > \ + $(LINUX_DIR)/vmlinux.tmp + PATH='${TARGET_PATH}' \ + addpattern -p WA21 -i $(LINUX_DIR)/vmlinux.tmp \ + -o $(BIN_DIR)/${DEVICE}-${ARCH}-kernel + +ifeq ($(FS),squashfs) +imageinstall: $(BIN_DIR)/$(ROOTFSTARBALL) + @echo + @echo 'The kernel file is: ${BIN_DIR}/${DEVICE}-${ARCH}-kernel' + @echo 'The nfs root tarball is: ${BIN_DIR}/${ROOTFSTARBALL}' + @echo 'You can flash the kernel via tftp:' + @echo 'tftp 192.168.1.1' + @echo 'tftp> binary' + @echo 'tftp> put wag54g-mips-kernel upgrade_code.bin' + +endif + +ifeq ($(FS),nfsroot) +imageinstall: $(BIN_DIR)/$(ROOTFSTARBALL) + @echo + @echo 'The kernel file is: ${BIN_DIR}/${DEVICE}-${ARCH}-kernel' + @echo 'The nfs root tarball is: ${BIN_DIR}/${ROOTFSTARBALL}' + @echo 'You can flash the kernel via tftp:' + @echo 'tftp 192.168.1.1' + @echo 'tftp> binary' + @echo 'tftp> put wag54g-mips-kernel upgrade_code.bin' + +endif diff --git a/target/wag54g/device.mk b/target/wag54g/device.mk new file mode 100644 index 000000000..df956ae5e --- /dev/null +++ b/target/wag54g/device.mk @@ -0,0 +1,7 @@ +ARCH:= mips +CPU_ARCH:= mipsel +KERNEL_VERSION:= 2.6.29.1 +KERNEL_RELEASE:= 1 +KERNEL_MD5SUM:= 4ada43caecb08fe2af71b416b6f586d8 +TARGET_OPTIMIZATION:= -Os -pipe +TARGET_CFLAGS_ARCH:= -march=mips32 diff --git a/target/wag54g/files/etc/mdev.conf b/target/wag54g/files/etc/mdev.conf new file mode 100644 index 000000000..a8b87c84c --- /dev/null +++ b/target/wag54g/files/etc/mdev.conf @@ -0,0 +1,11 @@ +rtc0 root:root 660 @ln -sf /dev/rtc0 /dev/rtc +tun 0:0 660 >net/tun +device-mapper 0:0 660 @mkdir /dev/mapper +null 0:0 777 +zero 0:0 666 +u?random 0:0 644 +console 0:0 0600 +ptmx 0:0 666 +tty 0:0 666 +ttyS* 0:0 640 +.* 0:0 644 @/lib/mdev/init diff --git a/target/wag54g/kernel.config b/target/wag54g/kernel.config new file mode 100644 index 000000000..684c2065b --- /dev/null +++ b/target/wag54g/kernel.config @@ -0,0 +1,904 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.29.1 +# Mon Jun 1 20:30:47 2009 +# +CONFIG_MIPS=y + +# +# Machine selection +# +CONFIG_AR7=y +# CONFIG_MACH_ALCHEMY is not set +# CONFIG_BASLER_EXCITE is not set +# CONFIG_BCM47XX is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_LASAT is not set +# CONFIG_LEMOTE_FULONG is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SIM is not set +# CONFIG_NEC_MARKEINS is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_NXP_STB220 is not set +# CONFIG_NXP_STB225 is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP28 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SNI_RM is not set +# CONFIG_MACH_TX39XX is not set +# CONFIG_MACH_TX49XX is not set +# CONFIG_MIKROTIK_RB532 is not set +# CONFIG_WR_PPMC is not set +# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set +# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_SUPPORTS_OPROFILE=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_CMOS_UPDATE=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y +CONFIG_CEVT_R4K_LIB=y +CONFIG_CEVT_R4K=y +CONFIG_CSRC_R4K_LIB=y +CONFIG_CSRC_R4K=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_EARLY_PRINTK=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +# CONFIG_HOTPLUG_CPU is not set +# CONFIG_NO_IOPORT is not set +CONFIG_GENERIC_GPIO=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_NO_EXCEPT_FILL=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_MIPS_L1_CACHE_SHIFT=5 + +# +# CPU selection +# +# CONFIG_CPU_LOONGSON2 is not set +CONFIG_CPU_MIPS32_R1=y +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R5500 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_CAVIUM_OCTEON is not set +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPSR1=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_HARDWARE_WATCHPOINTS=y + +# +# Kernel type +# +CONFIG_32BIT=y +# CONFIG_64BIT is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_16KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_VIRT_TO_BUS=y +CONFIG_UNEVICTABLE_LRU=y +# CONFIG_NO_HZ is not set +# CONFIG_HIGH_RES_TIMERS is not set +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +# CONFIG_HZ_48 is not set +CONFIG_HZ_100=y +# CONFIG_HZ_128 is not set +# CONFIG_HZ_250 is not set +# CONFIG_HZ_256 is not set +# CONFIG_HZ_1000 is not set +# CONFIG_HZ_1024 is not set +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_HZ=100 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +# CONFIG_KEXEC is not set +# CONFIG_SECCOMP is not set +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_AUDIT is not set + +# +# RCU Subsystem +# +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_GROUP_SCHED is not set +# CONFIG_CGROUPS is not set +# CONFIG_SYSFS_DEPRECATED_V2 is not set +# CONFIG_RELAY is not set +# CONFIG_NAMESPACES is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_EMBEDDED=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +# CONFIG_ELF_CORE is not set +# CONFIG_PCSPKR_PLATFORM is not set +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +CONFIG_VM_EVENT_COUNTERS=y +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +# CONFIG_MODULE_FORCE_LOAD is not set +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_FREEZER is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_MMU=y +# CONFIG_PCCARD is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_TRAD_SIGNALS=y + +# +# Power management options +# +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_PM is not set +CONFIG_NET=y + +# +# Networking options +# +CONFIG_COMPAT_NET_DEV_OPS=y +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_ASK_IP_FIB_HASH=y +# CONFIG_IP_FIB_TRIE is not set +CONFIG_IP_FIB_HASH=y +# CONFIG_IP_MULTIPLE_TABLES is not set +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_TRANSPORT is not set +# CONFIG_INET_XFRM_MODE_TUNNEL is not set +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +# CONFIG_PHONET is not set +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +CONFIG_WIRELESS_OLD_REGULATORY=y +# CONFIG_WIRELESS_EXT is not set +# CONFIG_LIB80211 is not set +# CONFIG_MAC80211 is not set +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +# CONFIG_PREVENT_FIRMWARE_BUILD is not set +# CONFIG_FW_LOADER is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set +CONFIG_MTD_AR7_PARTS=y + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +# CONFIG_MTD_NAND is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_COW_COMMON is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_BLK_DEV_HD is not set +# CONFIG_MISC_DEVICES is not set +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +CONFIG_PHYLIB=y +# CONFIG_SWCONFIG is not set + +# +# MII PHY device drivers +# +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_AX88796 is not set +# CONFIG_SMC91X is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set +# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set +# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_B44 is not set +CONFIG_CPMAC=y +# CONFIG_NETDEV_1000 is not set +# CONFIG_NETDEV_10000 is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +# CONFIG_SERIO_SERPORT is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_DEVKMEM is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +CONFIG_SERIAL_8250_RUNTIME_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_R3964 is not set +CONFIG_AR7_GPIO=y +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_I2C is not set +# CONFIG_SPI is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +# CONFIG_HWMON is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set +CONFIG_AR7_WDT=y +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_REGULATOR is not set + +# +# Multimedia devices +# + +# +# Multimedia core support +# +# CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_VIDEO_MEDIA is not set + +# +# Multimedia drivers +# +# CONFIG_DAB is not set + +# +# Graphics support +# +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +# CONFIG_HID is not set +# CONFIG_HID_PID is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +CONFIG_RTC_LIB=y +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_UIO is not set + +# +# TI VLYNQ +# +CONFIG_VLYNQ=y +# CONFIG_STAGING is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_EXT4_FS is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +CONFIG_FILE_LOCKING=y +# CONFIG_XFS_FS is not set +# CONFIG_OCFS2_FS is not set +# CONFIG_BTRFS_FS is not set +CONFIG_DNOTIFY=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_FUSE_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_PROC_KCORE is not set +CONFIG_PROC_SYSCTL=y +# CONFIG_PROC_PAGE_MONITOR is not set +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_YAFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set +# CONFIG_DLM is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_PRINTK_TIME=y +# CONFIG_ENABLE_WARN_DEPRECATED is not set +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_KERNEL is not set +# CONFIG_DEBUG_MEMORY_INIT is not set +# CONFIG_RCU_CPU_STALL_DETECTOR is not set +# CONFIG_SYSCTL_SYSCALL_CHECK is not set + +# +# Tracers +# +# CONFIG_DYNAMIC_PRINTK_DEBUG is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +CONFIG_CMDLINE="init=/init console=ttyS0" + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +# CONFIG_CRYPTO_FIPS is not set +# CONFIG_CRYPTO_MANAGER is not set +# CONFIG_CRYPTO_MANAGER2 is not set +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_CRYPTD is not set +# CONFIG_CRYPTO_AUTHENC is not set +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +# CONFIG_CRYPTO_CBC is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +# CONFIG_CRYPTO_ECB is not set +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_XCBC is not set + +# +# Digest +# +# CONFIG_CRYPTO_CRC32C is not set +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_ARC4 is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set +# CONFIG_CRYPTO_TWOFISH is not set + +# +# Compression +# +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +# CONFIG_CRYPTO_HW is not set + +# +# OCF Configuration +# +# CONFIG_OCF_OCF is not set + +# +# Library routines +# +CONFIG_GENERIC_FIND_LAST_BIT=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +# CONFIG_CRC32 is not set +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff --git a/target/wag54g/patches/ar7.patch b/target/wag54g/patches/ar7.patch new file mode 100644 index 000000000..1398c5e71 --- /dev/null +++ b/target/wag54g/patches/ar7.patch @@ -0,0 +1,5087 @@ +diff -Nur linux-2.6.29.1.orig/arch/mips/ar7/clock.c linux-2.6.29.1/arch/mips/ar7/clock.c +--- linux-2.6.29.1.orig/arch/mips/ar7/clock.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/ar7/clock.c 2009-05-31 20:19:17.000000000 +0200 +@@ -0,0 +1,483 @@ ++/* ++ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> ++ * Copyright (C) 2007 Eugene Konev <ejka@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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include <linux/init.h> ++#include <linux/types.h> ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <asm/addrspace.h> ++#include <asm/io.h> ++#include <asm/mach-ar7/ar7.h> ++ ++#define BOOT_PLL_SOURCE_MASK 0x3 ++#define CPU_PLL_SOURCE_SHIFT 16 ++#define BUS_PLL_SOURCE_SHIFT 14 ++#define USB_PLL_SOURCE_SHIFT 18 ++#define DSP_PLL_SOURCE_SHIFT 22 ++#define BOOT_PLL_SOURCE_AFE 0 ++#define BOOT_PLL_SOURCE_BUS 0 ++#define BOOT_PLL_SOURCE_REF 1 ++#define BOOT_PLL_SOURCE_XTAL 2 ++#define BOOT_PLL_SOURCE_CPU 3 ++#define BOOT_PLL_BYPASS 0x00000020 ++#define BOOT_PLL_ASYNC_MODE 0x02000000 ++#define BOOT_PLL_2TO1_MODE 0x00008000 ++ ++#define TNETD7200_CLOCK_ID_CPU 0 ++#define TNETD7200_CLOCK_ID_DSP 1 ++#define TNETD7200_CLOCK_ID_USB 2 ++ ++#define TNETD7200_DEF_CPU_CLK 211000000 ++#define TNETD7200_DEF_DSP_CLK 125000000 ++#define TNETD7200_DEF_USB_CLK 48000000 ++ ++struct tnetd7300_clock { ++ u32 ctrl; ++#define PREDIV_MASK 0x001f0000 ++#define PREDIV_SHIFT 16 ++#define POSTDIV_MASK 0x0000001f ++ u32 unused1[3]; ++ u32 pll; ++#define MUL_MASK 0x0000f000 ++#define MUL_SHIFT 12 ++#define PLL_MODE_MASK 0x00000001 ++#define PLL_NDIV 0x00000800 ++#define PLL_DIV 0x00000002 ++#define PLL_STATUS 0x00000001 ++ u32 unused2[3]; ++}; ++ ++struct tnetd7300_clocks { ++ struct tnetd7300_clock bus; ++ struct tnetd7300_clock cpu; ++ struct tnetd7300_clock usb; ++ struct tnetd7300_clock dsp; ++}; ++ ++struct tnetd7200_clock { ++ u32 ctrl; ++ u32 unused1[3]; ++#define DIVISOR_ENABLE_MASK 0x00008000 ++ u32 mul; ++ u32 prediv; ++ u32 postdiv; ++ u32 postdiv2; ++ u32 unused2[6]; ++ u32 cmd; ++ u32 status; ++ u32 cmden; ++ u32 padding[15]; ++}; ++ ++struct tnetd7200_clocks { ++ struct tnetd7200_clock cpu; ++ struct tnetd7200_clock dsp; ++ struct tnetd7200_clock usb; ++}; ++ ++int ar7_cpu_clock = 150000000; ++EXPORT_SYMBOL(ar7_cpu_clock); ++int ar7_bus_clock = 125000000; ++EXPORT_SYMBOL(ar7_bus_clock); ++int ar7_dsp_clock; ++EXPORT_SYMBOL(ar7_dsp_clock); ++ ++static int gcd(int a, int b) ++{ ++ int c; ++ ++ if (a < b) { ++ c = a; ++ a = b; ++ b = c; ++ } ++ while ((c = (a % b))) { ++ a = b; ++ b = c; ++ } ++ return b; ++} ++ ++static void approximate(int base, int target, int *prediv, ++ int *postdiv, int *mul) ++{ ++ int i, j, k, freq, res = target; ++ for (i = 1; i <= 16; i++) ++ for (j = 1; j <= 32; j++) ++ for (k = 1; k <= 32; k++) { ++ freq = abs(base / j * i / k - target); ++ if (freq < res) { ++ res = freq; ++ *mul = i; ++ *prediv = j; ++ *postdiv = k; ++ } ++ } ++} ++ ++static void calculate(int base, int target, int *prediv, int *postdiv, ++ int *mul) ++{ ++ int tmp_gcd, tmp_base, tmp_freq; ++ ++ for (*prediv = 1; *prediv <= 32; (*prediv)++) { ++ tmp_base = base / *prediv; ++ tmp_gcd = gcd(target, tmp_base); ++ *mul = target / tmp_gcd; ++ *postdiv = tmp_base / tmp_gcd; ++ if ((*mul < 1) || (*mul >= 16)) ++ continue; ++ if ((*postdiv > 0) & (*postdiv <= 32)) ++ break; ++ } ++ ++ if (base / (*prediv) * (*mul) / (*postdiv) != target) { ++ approximate(base, target, prediv, postdiv, mul); ++ tmp_freq = base / (*prediv) * (*mul) / (*postdiv); ++ printk(KERN_WARNING ++ "Adjusted requested frequency %d to %d\n", ++ target, tmp_freq); ++ } ++ ++ printk(KERN_DEBUG "Clocks: prediv: %d, postdiv: %d, mul: %d\n", ++ *prediv, *postdiv, *mul); ++} ++ ++static int tnetd7300_dsp_clock(void) ++{ ++ u32 didr1, didr2; ++ u8 rev = ar7_chip_rev(); ++ didr1 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x18)); ++ didr2 = readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x1c)); ++ if (didr2 & (1 << 23)) ++ return 0; ++ if ((rev >= 0x23) && (rev != 0x57)) ++ return 250000000; ++ if ((((didr2 & 0x1fff) << 10) | ((didr1 & 0xffc00000) >> 22)) ++ > 4208000) ++ return 250000000; ++ return 0; ++} ++ ++static int tnetd7300_get_clock(u32 shift, struct tnetd7300_clock *clock, ++ u32 *bootcr, u32 bus_clock) ++{ ++ int product; ++ int base_clock = AR7_REF_CLOCK; ++ u32 ctrl = readl(&clock->ctrl); ++ u32 pll = readl(&clock->pll); ++ int prediv = ((ctrl & PREDIV_MASK) >> PREDIV_SHIFT) + 1; ++ int postdiv = (ctrl & POSTDIV_MASK) + 1; ++ int divisor = prediv * postdiv; ++ int mul = ((pll & MUL_MASK) >> MUL_SHIFT) + 1; ++ ++ switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) { ++ case BOOT_PLL_SOURCE_BUS: ++ base_clock = bus_clock; ++ break; ++ case BOOT_PLL_SOURCE_REF: ++ base_clock = AR7_REF_CLOCK; ++ break; ++ case BOOT_PLL_SOURCE_XTAL: ++ base_clock = AR7_XTAL_CLOCK; ++ break; ++ case BOOT_PLL_SOURCE_CPU: ++ base_clock = ar7_cpu_clock; ++ break; ++ } ++ ++ if (*bootcr & BOOT_PLL_BYPASS) ++ return base_clock / divisor; ++ ++ if ((pll & PLL_MODE_MASK) == 0) ++ return (base_clock >> (mul / 16 + 1)) / divisor; ++ ++ if ((pll & (PLL_NDIV | PLL_DIV)) == (PLL_NDIV | PLL_DIV)) { ++ product = (mul & 1) ? ++ (base_clock * mul) >> 1 : ++ (base_clock * (mul - 1)) >> 2; ++ return product / divisor; ++ } ++ ++ if (mul == 16) ++ return base_clock / divisor; ++ ++ return base_clock * mul / divisor; ++} ++ ++static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock, ++ u32 *bootcr, u32 frequency) ++{ ++ int prediv, postdiv, mul; ++ int base_clock = ar7_bus_clock; ++ ++ switch ((*bootcr & (BOOT_PLL_SOURCE_MASK << shift)) >> shift) { ++ case BOOT_PLL_SOURCE_BUS: ++ base_clock = ar7_bus_clock; ++ break; ++ case BOOT_PLL_SOURCE_REF: ++ base_clock = AR7_REF_CLOCK; ++ break; ++ case BOOT_PLL_SOURCE_XTAL: ++ base_clock = AR7_XTAL_CLOCK; ++ break; ++ case BOOT_PLL_SOURCE_CPU: ++ base_clock = ar7_cpu_clock; ++ break; ++ } ++ ++ calculate(base_clock, frequency, &prediv, &postdiv, &mul); ++ ++ writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl); ++ mdelay(1); ++ writel(4, &clock->pll); ++ while (readl(&clock->pll) & PLL_STATUS); ++ writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll); ++ mdelay(75); ++} ++ ++static void __init tnetd7300_init_clocks(void) ++{ ++ u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4); ++ struct tnetd7300_clocks *clocks = ++ (struct tnetd7300_clocks *) ++ ioremap_nocache(AR7_REGS_POWER + 0x20, ++ sizeof(struct tnetd7300_clocks)); ++ ++ ar7_bus_clock = tnetd7300_get_clock(BUS_PLL_SOURCE_SHIFT, ++ &clocks->bus, bootcr, AR7_AFE_CLOCK); ++ ++ if (*bootcr & BOOT_PLL_ASYNC_MODE) ++ ar7_cpu_clock = tnetd7300_get_clock(CPU_PLL_SOURCE_SHIFT, ++ &clocks->cpu, bootcr, AR7_AFE_CLOCK); ++ else ++ ar7_cpu_clock = ar7_bus_clock; ++/* ++ tnetd7300_set_clock(USB_PLL_SOURCE_SHIFT, &clocks->usb, ++ bootcr, 48000000); ++*/ ++ if (ar7_dsp_clock == 250000000) ++ tnetd7300_set_clock(DSP_PLL_SOURCE_SHIFT, &clocks->dsp, ++ bootcr, ar7_dsp_clock); ++ ++ iounmap(clocks); ++ iounmap(bootcr); ++} ++ ++static int tnetd7200_get_clock(int base, struct tnetd7200_clock *clock, ++ u32 *bootcr, u32 bus_clock) ++{ ++ int divisor = ((readl(&clock->prediv) & 0x1f) + 1) * ++ ((readl(&clock->postdiv) & 0x1f) + 1); ++ ++ if (*bootcr & BOOT_PLL_BYPASS) ++ return base / divisor; ++ ++ return base * ((readl(&clock->mul) & 0xf) + 1) / divisor; ++} ++ ++ ++static void tnetd7200_set_clock(int base, struct tnetd7200_clock *clock, ++ int prediv, int postdiv, int postdiv2, int mul, u32 frequency) ++{ ++ printk(KERN_INFO ++ "Clocks: base = %d, frequency = %u, prediv = %d, " ++ "postdiv = %d, postdiv2 = %d, mul = %d\n", ++ base, frequency, prediv, postdiv, postdiv2, mul); ++ ++ writel(0, &clock->ctrl); ++ writel(DIVISOR_ENABLE_MASK | ((prediv - 1) & 0x1F), &clock->prediv); ++ writel((mul - 1) & 0xF, &clock->mul); ++ ++ for (mul = 0; mul < 2000; mul++) /* nop */; ++ ++ while (readl(&clock->status) & 0x1) /* nop */; ++ ++ writel(DIVISOR_ENABLE_MASK | ((postdiv - 1) & 0x1F), &clock->postdiv); ++ ++ writel(readl(&clock->cmden) | 1, &clock->cmden); ++ writel(readl(&clock->cmd) | 1, &clock->cmd); ++ ++ while (readl(&clock->status) & 0x1) /* nop */; ++ ++ writel(DIVISOR_ENABLE_MASK | ((postdiv2 - 1) & 0x1F), &clock->postdiv2); ++ ++ writel(readl(&clock->cmden) | 1, &clock->cmden); ++ writel(readl(&clock->cmd) | 1, &clock->cmd); ++ ++ while (readl(&clock->status) & 0x1) /* nop */; ++ ++ writel(readl(&clock->ctrl) | 1, &clock->ctrl); ++} ++ ++static int tnetd7200_get_clock_base(int clock_id, u32 *bootcr) ++{ ++ if (*bootcr & BOOT_PLL_ASYNC_MODE) ++ /* Async */ ++ switch (clock_id) { ++ case TNETD7200_CLOCK_ID_DSP: ++ return AR7_REF_CLOCK; ++ default: ++ return AR7_AFE_CLOCK; ++ } ++ else ++ /* Sync */ ++ if (*bootcr & BOOT_PLL_2TO1_MODE) ++ /* 2:1 */ ++ switch (clock_id) { ++ case TNETD7200_CLOCK_ID_DSP: ++ return AR7_REF_CLOCK; ++ default: ++ return AR7_AFE_CLOCK; ++ } ++ else ++ /* 1:1 */ ++ return AR7_REF_CLOCK; ++} ++ ++ ++static void __init tnetd7200_init_clocks(void) ++{ ++ u32 *bootcr = (u32 *)ioremap_nocache(AR7_REGS_DCL, 4); ++ struct tnetd7200_clocks *clocks = ++ (struct tnetd7200_clocks *) ++ ioremap_nocache(AR7_REGS_POWER + 0x80, ++ sizeof(struct tnetd7200_clocks)); ++ int cpu_base, cpu_mul, cpu_prediv, cpu_postdiv; ++ int dsp_base, dsp_mul, dsp_prediv, dsp_postdiv; ++ int usb_base, usb_mul, usb_prediv, usb_postdiv; ++ ++/* ++ Log from Fritz!Box 7170 Annex B: ++ ++ CPU revision is: 00018448 ++ Clocks: Async mode ++ Clocks: Setting DSP clock ++ Clocks: prediv: 1, postdiv: 1, mul: 5 ++ Clocks: base = 25000000, frequency = 125000000, prediv = 1, ++ postdiv = 2, postdiv2 = 1, mul = 10 ++ Clocks: Setting CPU clock ++ Adjusted requested frequency 211000000 to 211968000 ++ Clocks: prediv: 1, postdiv: 1, mul: 6 ++ Clocks: base = 35328000, frequency = 211968000, prediv = 1, ++ postdiv = 1, postdiv2 = -1, mul = 6 ++ Clocks: Setting USB clock ++ Adjusted requested frequency 48000000 to 48076920 ++ Clocks: prediv: 13, postdiv: 1, mul: 5 ++ Clocks: base = 125000000, frequency = 48000000, prediv = 13, ++ postdiv = 1, postdiv2 = -1, mul = 5 ++ ++ DSL didn't work if you didn't set the postdiv 2:1 postdiv2 combination, ++ driver hung on startup. ++ Haven't tested this on a synchronous board, ++ neither do i know what to do with ar7_dsp_clock ++*/ ++ ++ cpu_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_CPU, bootcr); ++ dsp_base = tnetd7200_get_clock_base(TNETD7200_CLOCK_ID_DSP, bootcr); ++ ++ if (*bootcr & BOOT_PLL_ASYNC_MODE) { ++ printk(KERN_INFO "Clocks: Async mode\n"); ++ ++ printk(KERN_INFO "Clocks: Setting DSP clock\n"); ++ calculate(dsp_base, TNETD7200_DEF_DSP_CLK, ++ &dsp_prediv, &dsp_postdiv, &dsp_mul); ++ ar7_bus_clock = ++ ((dsp_base / dsp_prediv) * dsp_mul) / dsp_postdiv; ++ tnetd7200_set_clock(dsp_base, &clocks->dsp, ++ dsp_prediv, dsp_postdiv * 2, dsp_postdiv, dsp_mul * 2, ++ ar7_bus_clock); ++ ++ printk(KERN_INFO "Clocks: Setting CPU clock\n"); ++ calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv, ++ &cpu_postdiv, &cpu_mul); ++ ar7_cpu_clock = ++ ((cpu_base / cpu_prediv) * cpu_mul) / cpu_postdiv; ++ tnetd7200_set_clock(cpu_base, &clocks->cpu, ++ cpu_prediv, cpu_postdiv, -1, cpu_mul, ++ ar7_cpu_clock); ++ ++ } else ++ if (*bootcr & BOOT_PLL_2TO1_MODE) { ++ printk(KERN_INFO "Clocks: Sync 2:1 mode\n"); ++ ++ printk(KERN_INFO "Clocks: Setting CPU clock\n"); ++ calculate(cpu_base, TNETD7200_DEF_CPU_CLK, &cpu_prediv, ++ &cpu_postdiv, &cpu_mul); ++ ar7_cpu_clock = ((cpu_base / cpu_prediv) * cpu_mul) ++ / cpu_postdiv; ++ tnetd7200_set_clock(cpu_base, &clocks->cpu, ++ cpu_prediv, cpu_postdiv, -1, cpu_mul, ++ ar7_cpu_clock); ++ ++ printk(KERN_INFO "Clocks: Setting DSP clock\n"); ++ calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv, ++ &dsp_postdiv, &dsp_mul); ++ ar7_bus_clock = ar7_cpu_clock / 2; ++ tnetd7200_set_clock(dsp_base, &clocks->dsp, ++ dsp_prediv, dsp_postdiv * 2, dsp_postdiv, ++ dsp_mul * 2, ar7_bus_clock); ++ } else { ++ printk(KERN_INFO "Clocks: Sync 1:1 mode\n"); ++ ++ printk(KERN_INFO "Clocks: Setting DSP clock\n"); ++ calculate(dsp_base, TNETD7200_DEF_DSP_CLK, &dsp_prediv, ++ &dsp_postdiv, &dsp_mul); ++ ar7_bus_clock = ((dsp_base / dsp_prediv) * dsp_mul) ++ / dsp_postdiv; ++ tnetd7200_set_clock(dsp_base, &clocks->dsp, ++ dsp_prediv, dsp_postdiv * 2, dsp_postdiv, ++ dsp_mul * 2, ar7_bus_clock); ++ ++ ar7_cpu_clock = ar7_bus_clock; ++ } ++ ++ printk(KERN_INFO "Clocks: Setting USB clock\n"); ++ usb_base = ar7_bus_clock; ++ calculate(usb_base, TNETD7200_DEF_USB_CLK, &usb_prediv, ++ &usb_postdiv, &usb_mul); ++ tnetd7200_set_clock(usb_base, &clocks->usb, ++ usb_prediv, usb_postdiv, -1, usb_mul, ++ TNETD7200_DEF_USB_CLK); ++ ++ #warning FIXME ++ ar7_dsp_clock = ar7_cpu_clock; ++ ++ iounmap(clocks); ++ iounmap(bootcr); ++} ++ ++void __init ar7_init_clocks(void) ++{ ++ switch (ar7_chip_id()) { ++ case AR7_CHIP_7100: ++#warning FIXME: Check if the new 7200 clock init works for 7100 ++ tnetd7200_init_clocks(); ++ break; ++ case AR7_CHIP_7200: ++ tnetd7200_init_clocks(); ++ break; ++ case AR7_CHIP_7300: ++ ar7_dsp_clock = tnetd7300_dsp_clock(); ++ tnetd7300_init_clocks(); ++ break; ++ default: ++ break; ++ } ++} +diff -Nur linux-2.6.29.1.orig/arch/mips/ar7/gpio.c linux-2.6.29.1/arch/mips/ar7/gpio.c +--- linux-2.6.29.1.orig/arch/mips/ar7/gpio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/ar7/gpio.c 2009-05-31 20:19:27.000000000 +0200 +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> ++ * Copyright (C) 2007 Eugene Konev <ejka@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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include <linux/module.h> ++ ++#include <asm/mach-ar7/gpio.h> ++ ++static const char *ar7_gpio_list[AR7_GPIO_MAX]; ++ ++int gpio_request(unsigned gpio, const char *label) ++{ ++ if (gpio >= AR7_GPIO_MAX) ++ return -EINVAL; ++ ++ if (ar7_gpio_list[gpio]) ++ return -EBUSY; ++ ++ if (label) { ++ ar7_gpio_list[gpio] = label; ++ } else { ++ ar7_gpio_list[gpio] = "busy"; ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL(gpio_request); ++ ++void gpio_free(unsigned gpio) ++{ ++ BUG_ON(!ar7_gpio_list[gpio]); ++ ar7_gpio_list[gpio] = NULL; ++} ++EXPORT_SYMBOL(gpio_free); +diff -Nur linux-2.6.29.1.orig/arch/mips/ar7/irq.c linux-2.6.29.1/arch/mips/ar7/irq.c +--- linux-2.6.29.1.orig/arch/mips/ar7/irq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/ar7/irq.c 2009-05-31 20:19:35.000000000 +0200 +@@ -0,0 +1,183 @@ ++/* ++ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org> ++ * Copyright (C) 2006,2007 Eugene Konev <ejka@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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include <linux/interrupt.h> ++#include <linux/io.h> ++ ++#include <asm/irq_cpu.h> ++#include <asm/mipsregs.h> ++#include <asm/mach-ar7/ar7.h> ++ ++#define EXCEPT_OFFSET 0x80 ++#define PACE_OFFSET 0xA0 ++#define CHNLS_OFFSET 0x200 ++ ++#define REG_OFFSET(irq, reg) ((irq) / 32 * 0x4 + reg * 0x10) ++#define SEC_REG_OFFSET(reg) (EXCEPT_OFFSET + reg * 0x8) ++#define SEC_SR_OFFSET (SEC_REG_OFFSET(0)) /* 0x80 */ ++#define CR_OFFSET(irq) (REG_OFFSET(irq, 1)) /* 0x10 */ ++#define SEC_CR_OFFSET (SEC_REG_OFFSET(1)) /* 0x88 */ ++#define ESR_OFFSET(irq) (REG_OFFSET(irq, 2)) /* 0x20 */ ++#define SEC_ESR_OFFSET (SEC_REG_OFFSET(2)) /* 0x90 */ ++#define ECR_OFFSET(irq) (REG_OFFSET(irq, 3)) /* 0x30 */ ++#define SEC_ECR_OFFSET (SEC_REG_OFFSET(3)) /* 0x98 */ ++#define PIR_OFFSET (0x40) ++#define MSR_OFFSET (0x44) ++#define PM_OFFSET(irq) (REG_OFFSET(irq, 5)) /* 0x50 */ ++#define TM_OFFSET(irq) (REG_OFFSET(irq, 6)) /* 0x60 */ ++ ++#define REG(addr) ((u32 *)(KSEG1ADDR(AR7_REGS_IRQ) + addr)) ++ ++#define CHNL_OFFSET(chnl) (CHNLS_OFFSET + (chnl * 4)) ++ ++static void ar7_unmask_irq(unsigned int irq_nr); ++static void ar7_mask_irq(unsigned int irq_nr); ++static void ar7_ack_irq(unsigned int irq_nr); ++static void ar7_unmask_sec_irq(unsigned int irq_nr); ++static void ar7_mask_sec_irq(unsigned int irq_nr); ++static void ar7_ack_sec_irq(unsigned int irq_nr); ++static void ar7_cascade(void); ++static void ar7_irq_init(int base); ++static int ar7_irq_base; ++ ++static struct irq_chip ar7_irq_type = { ++ .name = "AR7", ++ .unmask = ar7_unmask_irq, ++ .mask = ar7_mask_irq, ++ .ack = ar7_ack_irq ++}; ++ ++static struct irq_chip ar7_sec_irq_type = { ++ .name = "AR7", ++ .unmask = ar7_unmask_sec_irq, ++ .mask = ar7_mask_sec_irq, ++ .ack = ar7_ack_sec_irq, ++}; ++ ++static struct irqaction ar7_cascade_action = { ++ .handler = no_action, ++ .name = "AR7 cascade interrupt" ++}; ++ ++static void ar7_unmask_irq(unsigned int irq) ++{ ++ writel(1 << ((irq - ar7_irq_base) % 32), ++ REG(ESR_OFFSET(irq - ar7_irq_base))); ++} ++ ++static void ar7_mask_irq(unsigned int irq) ++{ ++ writel(1 << ((irq - ar7_irq_base) % 32), ++ REG(ECR_OFFSET(irq - ar7_irq_base))); ++} ++ ++static void ar7_ack_irq(unsigned int irq) ++{ ++ writel(1 << ((irq - ar7_irq_base) % 32), ++ REG(CR_OFFSET(irq - ar7_irq_base))); ++} ++ ++static void ar7_unmask_sec_irq(unsigned int irq) ++{ ++ writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET)); ++} ++ ++static void ar7_mask_sec_irq(unsigned int irq) ++{ ++ writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET)); ++} ++ ++static void ar7_ack_sec_irq(unsigned int irq) ++{ ++ writel(1 << (irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET)); ++} ++ ++void __init arch_init_irq(void) { ++ mips_cpu_irq_init(); ++ ar7_irq_init(8); ++} ++ ++static void __init ar7_irq_init(int base) ++{ ++ int i; ++ /* ++ * Disable interrupts and clear pending ++ */ ++ writel(0xffffffff, REG(ECR_OFFSET(0))); ++ writel(0xff, REG(ECR_OFFSET(32))); ++ writel(0xffffffff, REG(SEC_ECR_OFFSET)); ++ writel(0xffffffff, REG(CR_OFFSET(0))); ++ writel(0xff, REG(CR_OFFSET(32))); ++ writel(0xffffffff, REG(SEC_CR_OFFSET)); ++ ++ ar7_irq_base = base; ++ ++ for (i = 0; i < 40; i++) { ++ writel(i, REG(CHNL_OFFSET(i))); ++ /* Primary IRQ's */ ++ set_irq_chip_and_handler(base + i, &ar7_irq_type, ++ handle_level_irq); ++ /* Secondary IRQ's */ ++ if (i < 32) ++ set_irq_chip_and_handler(base + i + 40, ++ &ar7_sec_irq_type, ++ handle_level_irq); ++ } ++ ++ setup_irq(2, &ar7_cascade_action); ++ setup_irq(ar7_irq_base, &ar7_cascade_action); ++ set_c0_status(IE_IRQ0); ++} ++ ++static void ar7_cascade(void) ++{ ++ u32 status; ++ int i, irq; ++ ++ /* Primary IRQ's */ ++ irq = readl(REG(PIR_OFFSET)) & 0x3f; ++ if (irq) { ++ do_IRQ(ar7_irq_base + irq); ++ return; ++ } ++ ++ /* Secondary IRQ's are cascaded through primary '0' */ ++ writel(1, REG(CR_OFFSET(irq))); ++ status = readl(REG(SEC_SR_OFFSET)); ++ for (i = 0; i < 32; i++) { ++ if (status & 1) { ++ do_IRQ(ar7_irq_base + i + 40); ++ return; ++ } ++ status >>= 1; ++ } ++ ++ spurious_interrupt(); ++} ++ ++asmlinkage void plat_irq_dispatch(void) ++{ ++ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; ++ if (pending & STATUSF_IP7) /* cpu timer */ ++ do_IRQ(7); ++ else if (pending & STATUSF_IP2) /* int0 hardware line */ ++ ar7_cascade(); ++ else ++ spurious_interrupt(); ++} +diff -Nur linux-2.6.29.1.orig/arch/mips/ar7/Makefile linux-2.6.29.1/arch/mips/ar7/Makefile +--- linux-2.6.29.1.orig/arch/mips/ar7/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/ar7/Makefile 2009-05-31 19:50:05.000000000 +0200 +@@ -0,0 +1,10 @@ ++ ++obj-y := \ ++ prom.o \ ++ setup.o \ ++ memory.o \ ++ irq.o \ ++ time.o \ ++ platform.o \ ++ gpio.o \ ++ clock.o +diff -Nur linux-2.6.29.1.orig/arch/mips/ar7/memory.c linux-2.6.29.1/arch/mips/ar7/memory.c +--- linux-2.6.29.1.orig/arch/mips/ar7/memory.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/ar7/memory.c 2009-05-31 19:50:05.000000000 +0200 +@@ -0,0 +1,74 @@ ++/* ++ * Based on arch/mips/mm/init.c ++ * Copyright (C) 1994 - 2000 Ralf Baechle ++ * Copyright (C) 1999, 2000 Silicon Graphics, Inc. ++ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com ++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++#include <linux/bootmem.h> ++#include <linux/init.h> ++#include <linux/mm.h> ++#include <linux/module.h> ++#include <linux/pfn.h> ++#include <linux/proc_fs.h> ++#include <linux/string.h> ++#include <linux/swap.h> ++ ++#include <asm/bootinfo.h> ++#include <asm/page.h> ++#include <asm/sections.h> ++ ++#include <asm/mips-boards/prom.h> ++ ++static int __init memsize(void) ++{ ++ u32 size = (64 << 20); ++ u32 *addr = (u32 *)KSEG1ADDR(0x14000000 + size - 4); ++ u32 *kernel_end = (u32 *)KSEG1ADDR(CPHYSADDR((u32)&_end)); ++ u32 *tmpaddr = addr; ++ ++ while (tmpaddr > kernel_end) { ++ *tmpaddr = (u32)tmpaddr; ++ size >>= 1; ++ tmpaddr -= size >> 2; ++ } ++ ++ do { ++ tmpaddr += size >> 2; ++ if (*tmpaddr != (u32)tmpaddr) ++ break; ++ size <<= 1; ++ } while (size < (64 << 20)); ++ ++ writel(tmpaddr, &addr); ++ ++ return size; ++} ++ ++void __init prom_meminit(void) ++{ ++ unsigned long pages; ++ ++ pages = memsize() >> PAGE_SHIFT; ++ add_memory_region(PHYS_OFFSET, pages << PAGE_SHIFT, ++ BOOT_MEM_RAM); ++} ++ ++void __init prom_free_prom_memory(void) ++{ ++ return; ++} +diff -Nur linux-2.6.29.1.orig/arch/mips/ar7/platform.c linux-2.6.29.1/arch/mips/ar7/platform.c +--- linux-2.6.29.1.orig/arch/mips/ar7/platform.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/ar7/platform.c 2009-06-01 13:34:18.000000000 +0200 +@@ -0,0 +1,535 @@ ++/* ++ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org> ++ * Copyright (C) 2006,2007 Eugene Konev <ejka@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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include <linux/autoconf.h> ++#include <linux/init.h> ++#include <linux/types.h> ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/dma-mapping.h> ++#include <linux/platform_device.h> ++#include <linux/mtd/physmap.h> ++#include <linux/serial.h> ++#include <linux/serial_8250.h> ++#include <linux/ioport.h> ++#include <linux/io.h> ++#include <linux/version.h> ++#include <linux/vlynq.h> ++#include <linux/leds.h> ++#include <linux/string.h> ++ ++#include <asm/addrspace.h> ++#include <asm/mach-ar7/ar7.h> ++#include <asm/mach-ar7/gpio.h> ++#include <asm/mach-ar7/prom.h> ++ ++struct plat_vlynq_data { ++ struct plat_vlynq_ops ops; ++ int gpio_bit; ++ int reset_bit; ++}; ++ ++ ++static int vlynq_on(struct vlynq_device *dev) ++{ ++ int result; ++ struct plat_vlynq_data *pdata = dev->dev.platform_data; ++ ++ if ((result = gpio_request(pdata->gpio_bit, "vlynq"))) ++ goto out; ++ ++ ar7_device_reset(pdata->reset_bit); ++ ++ if ((result = ar7_gpio_disable(pdata->gpio_bit))) ++ goto out_enabled; ++ ++ if ((result = ar7_gpio_enable(pdata->gpio_bit))) ++ goto out_enabled; ++ ++ if ((result = gpio_direction_output(pdata->gpio_bit, 0))) ++ goto out_gpio_enabled; ++ ++ mdelay(50); ++ ++ gpio_set_value(pdata->gpio_bit, 1); ++ mdelay(50); ++ ++ return 0; ++ ++out_gpio_enabled: ++ ar7_gpio_disable(pdata->gpio_bit); ++out_enabled: ++ ar7_device_disable(pdata->reset_bit); ++ gpio_free(pdata->gpio_bit); ++out: ++ return result; ++} ++ ++static void vlynq_off(struct vlynq_device *dev) ++{ ++ struct plat_vlynq_data *pdata = dev->dev.platform_data; ++ ar7_gpio_disable(pdata->gpio_bit); ++ gpio_free(pdata->gpio_bit); ++ ar7_device_disable(pdata->reset_bit); ++} ++ ++static struct resource physmap_flash_resource = { ++ .name = "mem", ++ .flags = IORESOURCE_MEM, ++ .start = 0x10000000, ++ .end = 0x107fffff, ++}; ++ ++static struct resource cpmac_low_res[] = { ++ { ++ .name = "regs", ++ .flags = IORESOURCE_MEM, ++ .start = AR7_REGS_MAC0, ++ .end = AR7_REGS_MAC0 + 0x7ff, ++ }, ++ { ++ .name = "irq", ++ .flags = IORESOURCE_IRQ, ++ .start = 27, ++ .end = 27, ++ }, ++}; ++ ++static struct resource cpmac_high_res[] = { ++ { ++ .name = "regs", ++ .flags = IORESOURCE_MEM, ++ .start = AR7_REGS_MAC1, ++ .end = AR7_REGS_MAC1 + 0x7ff, ++ }, ++ { ++ .name = "irq", ++ .flags = IORESOURCE_IRQ, ++ .start = 41, ++ .end = 41, ++ }, ++}; ++ ++static struct resource vlynq_low_res[] = { ++ { ++ .name = "regs", ++ .flags = IORESOURCE_MEM, ++ .start = AR7_REGS_VLYNQ0, ++ .end = AR7_REGS_VLYNQ0 + 0xff, ++ }, ++ { ++ .name = "irq", ++ .flags = IORESOURCE_IRQ, ++ .start = 29, ++ .end = 29, ++ }, ++ { ++ .name = "mem", ++ .flags = IORESOURCE_MEM, ++ .start = 0x04000000, ++ .end = 0x04ffffff, ++ }, ++ { ++ .name = "devirq", ++ .flags = IORESOURCE_IRQ, ++ .start = 80, ++ .end = 111, ++ }, ++}; ++ ++static struct resource vlynq_high_res[] = { ++ { ++ .name = "regs", ++ .flags = IORESOURCE_MEM, ++ .start = AR7_REGS_VLYNQ1, ++ .end = AR7_REGS_VLYNQ1 + 0xff, ++ }, ++ { ++ .name = "irq", ++ .flags = IORESOURCE_IRQ, ++ .start = 33, ++ .end = 33, ++ }, ++ { ++ .name = "mem", ++ .flags = IORESOURCE_MEM, ++ .start = 0x0c000000, ++ .end = 0x0cffffff, ++ }, ++ { ++ .name = "devirq", ++ .flags = IORESOURCE_IRQ, ++ .start = 112, ++ .end = 143, ++ }, ++}; ++ ++static struct resource usb_res[] = { ++ { ++ .name = "regs", ++ .flags = IORESOURCE_MEM, ++ .start = AR7_REGS_USB, ++ .end = AR7_REGS_USB + 0xff, ++ }, ++ { ++ .name = "irq", ++ .flags = IORESOURCE_IRQ, ++ .start = 32, ++ .end = 32, ++ }, ++ { ++ .name = "mem", ++ .flags = IORESOURCE_MEM, ++ .start = 0x03400000, ++ .end = 0x034001fff, ++ }, ++}; ++ ++static struct physmap_flash_data physmap_flash_data = { ++ .width = 2, ++}; ++ ++static struct plat_cpmac_data cpmac_low_data = { ++ .reset_bit = 17, ++ .power_bit = 20, ++ .phy_mask = 0x80000000, ++}; ++ ++static struct plat_cpmac_data cpmac_high_data = { ++ .reset_bit = 21, ++ .power_bit = 22, ++ .phy_mask = 0x7fffffff, ++}; ++ ++static struct plat_vlynq_data vlynq_low_data = { ++ .ops.on = vlynq_on, ++ .ops.off = vlynq_off, ++ .reset_bit = 20, ++ .gpio_bit = 18, ++}; ++ ++static struct plat_vlynq_data vlynq_high_data = { ++ .ops.on = vlynq_on, ++ .ops.off = vlynq_off, ++ .reset_bit = 16, ++ .gpio_bit = 19, ++}; ++ ++static struct platform_device physmap_flash = { ++ .id = 0, ++ .name = "physmap-flash", ++ .dev.platform_data = &physmap_flash_data, ++ .resource = &physmap_flash_resource, ++ .num_resources = 1, ++}; ++ ++static u64 cpmac_dma_mask = DMA_32BIT_MASK; ++static struct platform_device cpmac_low = { ++ .id = 0, ++ .name = "cpmac", ++ .dev = { ++ .dma_mask = &cpmac_dma_mask, ++ .coherent_dma_mask = DMA_32BIT_MASK, ++ .platform_data = &cpmac_low_data, ++ }, ++ .resource = cpmac_low_res, ++ .num_resources = ARRAY_SIZE(cpmac_low_res), ++}; ++ ++static struct platform_device cpmac_high = { ++ .id = 1, ++ .name = "cpmac", ++ .dev = { ++ .dma_mask = &cpmac_dma_mask, ++ .coherent_dma_mask = DMA_32BIT_MASK, ++ .platform_data = &cpmac_high_data, ++ }, ++ .resource = cpmac_high_res, ++ .num_resources = ARRAY_SIZE(cpmac_high_res), ++}; ++ ++static struct platform_device vlynq_low = { ++ .id = 0, ++ .name = "vlynq", ++ .dev.platform_data = &vlynq_low_data, ++ .resource = vlynq_low_res, ++ .num_resources = ARRAY_SIZE(vlynq_low_res), ++}; ++ ++static struct platform_device vlynq_high = { ++ .id = 1, ++ .name = "vlynq", ++ .dev.platform_data = &vlynq_high_data, ++ .resource = vlynq_high_res, ++ .num_resources = ARRAY_SIZE(vlynq_high_res), ++}; ++ ++ ++/* This is proper way to define uart ports, but they are then detected ++ * as xscale and, obviously, don't work... ++ */ ++#if !defined(CONFIG_SERIAL_8250) ++ ++static struct plat_serial8250_port uart0_data = { ++ .mapbase = AR7_REGS_UART0, ++ .irq = AR7_IRQ_UART0, ++ .regshift = 2, ++ .iotype = UPIO_MEM, ++ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, ++}; ++ ++static struct plat_serial8250_port uart1_data = { ++ .mapbase = UR8_REGS_UART1, ++ .irq = AR7_IRQ_UART1, ++ .regshift = 2, ++ .iotype = UPIO_MEM, ++ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP, ++}; ++ ++static struct plat_serial8250_port uart_data[] = { ++ uart0_data, ++ uart1_data, ++ { .flags = 0 } ++}; ++ ++static struct plat_serial8250_port uart_data_single[] = { ++ uart0_data, ++ { .flags = 0 } ++}; ++ ++static struct platform_device uart = { ++ .id = 0, ++ .name = "serial8250", ++ .dev.platform_data = uart_data_single ++}; ++#endif ++ ++static struct gpio_led default_leds[] = { ++ { .name = "status", .gpio = 8, .active_low = 1, }, ++}; ++ ++static struct gpio_led dsl502t_leds[] = { ++ { .name = "status", .gpio = 9, .active_low = 1, }, ++ { .name = "ethernet", .gpio = 7, .active_low = 1, }, ++ { .name = "usb", .gpio = 12, .active_low = 1, }, ++}; ++ ++static struct gpio_led dg834g_leds[] = { ++ { .name = "ppp", .gpio = 6, .active_low = 1, }, ++ { .name = "status", .gpio = 7, .active_low = 1, }, ++ { .name = "adsl", .gpio = 8, .active_low = 1, }, ++ { .name = "wifi", .gpio = 12, .active_low = 1, }, ++ { .name = "power", .gpio = 14, .active_low = 1, .default_trigger = "default-on", }, ++}; ++ ++static struct gpio_led fb_sl_leds[] = { ++ { .name = "1", .gpio = 7, }, ++ { .name = "2", .gpio = 13, .active_low = 1, }, ++ { .name = "3", .gpio = 10, .active_low = 1, }, ++ { .name = "4", .gpio = 12, .active_low = 1, }, ++ { .name = "5", .gpio = 9, .active_low = 1, }, ++}; ++ ++static struct gpio_led fb_fon_leds[] = { ++ { .name = "1", .gpio = 8, }, ++ { .name = "2", .gpio = 3, .active_low = 1, }, ++ { .name = "3", .gpio = 5, }, ++ { .name = "4", .gpio = 4, .active_low = 1, }, ++ { .name = "5", .gpio = 11, .active_low = 1, }, ++}; ++ ++static struct gpio_led_platform_data ar7_led_data; ++ ++static struct platform_device ar7_gpio_leds = { ++ .name = "leds-gpio", ++ .id = -1, ++ .dev = { ++ .platform_data = &ar7_led_data, ++ } ++}; ++ ++static struct platform_device ar7_udc = { ++ .id = -1, ++ .name = "ar7_udc", ++ .resource = usb_res, ++ .num_resources = ARRAY_SIZE(usb_res), ++}; ++ ++static inline unsigned char char2hex(char h) ++{ ++ switch (h) { ++ case '0': case '1': case '2': case '3': case '4': ++ case '5': case '6': case '7': case '8': case '9': ++ return h - '0'; ++ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': ++ return h - 'A' + 10; ++ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': ++ return h - 'a' + 10; ++ default: ++ return 0; ++ } ++} ++ ++static void cpmac_get_mac(int instance, unsigned char *dev_addr) ++{ ++ int i; ++ char name[5], default_mac[] = "00:00:00:12:34:56", *mac; ++ ++ mac = NULL; ++ sprintf(name, "mac%c", 'a' + instance); ++ mac = prom_getenv(name); ++ if (!mac) { ++ sprintf(name, "mac%c", 'a'); ++ mac = prom_getenv(name); ++ } ++ if (!mac) ++ mac = default_mac; ++ for (i = 0; i < 6; i++) ++ dev_addr[i] = (char2hex(mac[i * 3]) << 4) + ++ char2hex(mac[i * 3 + 1]); ++} ++ ++static void __init detect_leds(void) ++{ ++ char *prId, *usb_prod; ++ ++ /* Default LEDs */ ++ ar7_led_data.num_leds = ARRAY_SIZE(default_leds); ++ ar7_led_data.leds = default_leds; ++ ++ /* FIXME: the whole thing is unreliable */ ++ prId = prom_getenv("ProductID"); ++ usb_prod = prom_getenv("usb_prod"); ++ ++ /* If we can't get the product id from PROM, use the default LEDs */ ++ if (!prId) ++ return; ++ ++ if (strstr(prId, "Fritz_Box_FON")) { ++ ar7_led_data.num_leds = ARRAY_SIZE(fb_fon_leds); ++ ar7_led_data.leds = fb_fon_leds; ++ } else if (strstr(prId, "Fritz_Box_")) { ++ ar7_led_data.num_leds = ARRAY_SIZE(fb_sl_leds); ++ ar7_led_data.leds = fb_sl_leds; ++ } else if ((!strcmp(prId, "AR7RD") || !strcmp(prId, "AR7DB")) && usb_prod != NULL && strstr(usb_prod, "DSL-502T")) { ++ ar7_led_data.num_leds = ARRAY_SIZE(dsl502t_leds); ++ ar7_led_data.leds = dsl502t_leds; ++ } else if (strstr(prId, "DG834")) { ++ ar7_led_data.num_leds = ARRAY_SIZE(dg834g_leds); ++ ar7_led_data.leds = dg834g_leds; ++ } ++} ++ ++static int __init ar7_register_devices(void) ++{ ++ int res; ++ ++#ifdef CONFIG_SERIAL_8250 ++ ++ static struct uart_port uart_port[2]; ++ ++ memset(uart_port, 0, sizeof(struct uart_port) * 2); ++ ++ // use default type ++ //uart_port[0].type = PORT_AR7; ++ uart_port[0].line = 0; ++ uart_port[0].irq = AR7_IRQ_UART0; ++ uart_port[0].uartclk = ar7_bus_freq() / 2; ++ uart_port[0].iotype = UPIO_MEM; ++ uart_port[0].mapbase = AR7_REGS_UART0; ++ uart_port[0].membase = ioremap(uart_port[0].mapbase, 256); ++ uart_port[0].regshift = 2; ++ res = early_serial_setup(&uart_port[0]); ++ if (res) ++ return res; ++ ++ ++ /* Only TNETD73xx have a second serial port */ ++ if (ar7_has_second_uart()) { ++ // use default type ++ //uart_port[1].type = PORT_AR7; ++ uart_port[1].line = 1; ++ uart_port[1].irq = AR7_IRQ_UART1; ++ uart_port[1].uartclk = ar7_bus_freq() / 2; ++ uart_port[1].iotype = UPIO_MEM; ++ uart_port[1].mapbase = UR8_REGS_UART1; ++ uart_port[1].membase = ioremap(uart_port[1].mapbase, 256); ++ uart_port[1].regshift = 2; ++ res = early_serial_setup(&uart_port[1]); ++ if (res) ++ return res; ++ } ++ ++#else /* !CONFIG_SERIAL_8250 */ ++ ++ uart_data[0].uartclk = ar7_bus_freq() / 2; ++ uart_data[1].uartclk = uart_data[0].uartclk; ++ ++ /* Only TNETD73xx have a second serial port */ ++ if (ar7_has_second_uart()) ++ uart.dev.platform_data = uart_data; ++ ++ res = platform_device_register(&uart); ++ if (res) ++ return res; ++ ++#endif /* CONFIG_SERIAL_8250 */ ++ ++ res = platform_device_register(&physmap_flash); ++ if (res) ++ return res; ++ ++ ar7_device_disable(vlynq_low_data.reset_bit); ++ res = platform_device_register(&vlynq_low); ++ if (res) ++ return res; ++ ++ if (ar7_has_high_vlynq()) { ++ ar7_device_disable(vlynq_high_data.reset_bit); ++ res = platform_device_register(&vlynq_high); ++ if (res) ++ return res; ++ } ++ ++ if (ar7_has_high_cpmac()) { ++ cpmac_get_mac(1, cpmac_high_data.dev_addr); ++ res = platform_device_register(&cpmac_high); ++ if (res) ++ return res; ++ } else { ++ cpmac_low_data.phy_mask = 0xffffffff; ++ } ++ ++ cpmac_get_mac(0, cpmac_low_data.dev_addr); ++ res = platform_device_register(&cpmac_low); ++ if (res) ++ return res; ++ ++ detect_leds(); ++ res = platform_device_register(&ar7_gpio_leds); ++ if (res) ++ return res; ++ ++ res = platform_device_register(&ar7_udc); ++ ++ return res; ++} ++ ++ ++arch_initcall(ar7_register_devices); +diff -Nur linux-2.6.29.1.orig/arch/mips/ar7/prom.c linux-2.6.29.1/arch/mips/ar7/prom.c +--- linux-2.6.29.1.orig/arch/mips/ar7/prom.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/ar7/prom.c 2009-05-31 20:18:44.000000000 +0200 +@@ -0,0 +1,321 @@ ++/* ++ * Carsten Langgaard, carstenl@mips.com ++ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. ++ * ++ * This program is free software; you can distribute it and/or modify it ++ * under the terms of the GNU General Public License (Version 2) as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. ++ * ++ * Putting things on the screen/serial line using YAMONs facilities. ++ */ ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/serial_reg.h> ++#include <linux/spinlock.h> ++#include <linux/module.h> ++#include <linux/string.h> ++#include <linux/io.h> ++#include <asm/bootinfo.h> ++ ++#include <asm/mach-ar7/ar7.h> ++#include <asm/mach-ar7/prom.h> ++ ++#define MAX_ENTRY 80 ++ ++struct env_var { ++ char *name; ++ char *value; ++}; ++ ++static struct env_var adam2_env[MAX_ENTRY] = { { 0, }, }; ++ ++char *prom_getenv(const char *name) ++{ ++ int i; ++ for (i = 0; (i < MAX_ENTRY) && adam2_env[i].name; i++) ++ if (!strcmp(name, adam2_env[i].name)) ++ return adam2_env[i].value; ++ ++ return NULL; ++} ++EXPORT_SYMBOL(prom_getenv); ++ ++char * __init prom_getcmdline(void) ++{ ++ return &(arcs_cmdline[0]); ++} ++ ++static void __init ar7_init_cmdline(int argc, char *argv[]) ++{ ++ char *cp; ++ int actr; ++ ++ actr = 1; /* Always ignore argv[0] */ ++ ++ cp = &(arcs_cmdline[0]); ++ while (actr < argc) { ++ strcpy(cp, argv[actr]); ++ cp += strlen(argv[actr]); ++ *cp++ = ' '; ++ actr++; ++ } ++ if (cp != &(arcs_cmdline[0])) { ++ /* get rid of trailing space */ ++ --cp; ++ *cp = '\0'; ++ } ++} ++ ++struct psbl_rec { ++ u32 psbl_size; ++ u32 env_base; ++ u32 env_size; ++ u32 ffs_base; ++ u32 ffs_size; ++}; ++ ++static __initdata char psp_env_version[] = "TIENV0.8"; ++ ++struct psp_env_chunk { ++ u8 num; ++ u8 ctrl; ++ u16 csum; ++ u8 len; ++ char data[11]; ++} __attribute__ ((packed)); ++ ++struct psp_var_map_entry { ++ u8 num; ++ char *value; ++}; ++ ++static struct psp_var_map_entry psp_var_map[] = { ++ { 1, "cpufrequency" }, ++ { 2, "memsize" }, ++ { 3, "flashsize" }, ++ { 4, "modetty0" }, ++ { 5, "modetty1" }, ++ { 8, "maca" }, ++ { 9, "macb" }, ++ { 28, "sysfrequency" }, ++ { 38, "mipsfrequency" }, ++}; ++ ++/* ++ ++Well-known variable (num is looked up in table above for matching variable name) ++Example: cpufrequency=211968000 +++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- ++| 01 |CTRL|CHECKSUM | 01 | _2 | _1 | _1 | _9 | _6 | _8 | _0 | _0 | _0 | \0 | FF +++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- ++ ++Name=Value pair in a single chunk ++Example: NAME=VALUE +++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- ++| 00 |CTRL|CHECKSUM | 01 | _N | _A | _M | _E | _0 | _V | _A | _L | _U | _E | \0 +++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- ++ ++Name=Value pair in 2 chunks (len is the number of chunks) ++Example: bootloaderVersion=1.3.7.15 +++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- ++| 00 |CTRL|CHECKSUM | 02 | _b | _o | _o | _t | _l | _o | _a | _d | _e | _r | _V +++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- ++| _e | _r | _s | _i | _o | _n | \0 | _1 | _. | _3 | _. | _7 | _. | _1 | _5 | \0 +++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--- ++ ++Data is padded with 0xFF ++ ++*/ ++ ++#define PSP_ENV_SIZE 4096 ++ ++static char psp_env_data[PSP_ENV_SIZE] = { 0, }; ++ ++static char * __init lookup_psp_var_map(u8 num) ++{ ++ int i; ++ ++ for (i = 0; i < sizeof(psp_var_map); i++) ++ if (psp_var_map[i].num == num) ++ return psp_var_map[i].value; ++ ++ return NULL; ++} ++ ++static void __init add_adam2_var(char *name, char *value) ++{ ++ int i; ++ for (i = 0; i < MAX_ENTRY; i++) { ++ if (!adam2_env[i].name) { ++ adam2_env[i].name = name; ++ adam2_env[i].value = value; ++ return; ++ } else if (!strcmp(adam2_env[i].name, name)) { ++ adam2_env[i].value = value; ++ return; ++ } ++ } ++} ++ ++static int __init parse_psp_env(void *psp_env_base) ++{ ++ int i, n; ++ char *name, *value; ++ struct psp_env_chunk *chunks = (struct psp_env_chunk *)psp_env_data; ++ ++ memcpy_fromio(chunks, psp_env_base, PSP_ENV_SIZE); ++ ++ i = 1; ++ n = PSP_ENV_SIZE / sizeof(struct psp_env_chunk); ++ while (i < n) { ++ if ((chunks[i].num == 0xff) || ((i + chunks[i].len) > n)) ++ break; ++ value = chunks[i].data; ++ if (chunks[i].num) { ++ name = lookup_psp_var_map(chunks[i].num); ++ } else { ++ name = value; ++ value += strlen(name) + 1; ++ } ++ if (name) ++ add_adam2_var(name, value); ++ i += chunks[i].len; ++ } ++ return 0; ++} ++ ++static void __init ar7_init_env(struct env_var *env) ++{ ++ int i; ++ struct psbl_rec *psbl = (struct psbl_rec *)(KSEG1ADDR(0x14000300)); ++ void *psp_env = (void *)KSEG1ADDR(psbl->env_base); ++ ++ if (strcmp(psp_env, psp_env_version) == 0) { ++ parse_psp_env(psp_env); ++ } else { ++ for (i = 0; i < MAX_ENTRY; i++, env++) ++ if (env->name) ++ add_adam2_var(env->name, env->value); ++ } ++} ++ ++static void __init console_config(void) ++{ ++#ifdef CONFIG_SERIAL_8250_CONSOLE ++ char console_string[40]; ++ int baud = 0; ++ char parity = '\0', bits = '\0', flow = '\0'; ++ char *s, *p; ++ ++ if (strstr(prom_getcmdline(), "console=")) ++ return; ++ ++#ifdef CONFIG_KGDB ++ if (!strstr(prom_getcmdline(), "nokgdb")) { ++ strcat(prom_getcmdline(), " console=kgdb"); ++ kgdb_enabled = 1; ++ return; ++ } ++#endif ++ ++ if ((s = prom_getenv("modetty0"))) { ++ baud = simple_strtoul(s, &p, 10); ++ s = p; ++ if (*s == ',') s++; ++ if (*s) parity = *s++; ++ if (*s == ',') s++; ++ if (*s) bits = *s++; ++ if (*s == ',') s++; ++ if (*s == 'h') flow = 'r'; ++ } ++ ++ if (baud == 0) ++ baud = 38400; ++ if (parity != 'n' && parity != 'o' && parity != 'e') ++ parity = 'n'; ++ if (bits != '7' && bits != '8') ++ bits = '8'; ++ ++ if (flow == 'r') ++ sprintf(console_string, " console=ttyS0,%d%c%c%c", baud, ++ parity, bits, flow); ++ else ++ sprintf(console_string, " console=ttyS0,%d%c%c", baud, parity, ++ bits); ++ strcat(prom_getcmdline(), console_string); ++#endif ++} ++ ++void __init prom_init(void) ++{ ++ ar7_init_cmdline(fw_arg0, (char **)fw_arg1); ++ ar7_init_env((struct env_var *)fw_arg2); ++ console_config(); ++} ++ ++#define PORT(offset) (KSEG1ADDR(AR7_REGS_UART0 + (offset * 4))) ++static inline unsigned int serial_in(int offset) ++{ ++ return readb((void *)PORT(offset)); ++} ++ ++static inline void serial_out(int offset, int value) ++{ ++ writeb(value, (void *)PORT(offset)); ++} ++ ++char prom_getchar(void) ++{ ++ while (!(serial_in(UART_LSR) & UART_LSR_DR)); ++ return serial_in(UART_RX); ++} ++ ++int prom_putchar(char c) ++{ ++ while ((serial_in(UART_LSR) & UART_LSR_TEMT) == 0); ++ serial_out(UART_TX, c); ++ return 1; ++} ++ ++/* from adm5120/prom.c */ ++void prom_printf(const char *fmt, ...) ++{ ++ va_list args; ++ int l; ++ char *p, *buf_end; ++ char buf[1024]; ++ ++ va_start(args, fmt); ++ l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */ ++ va_end(args); ++ ++ buf_end = buf + l; ++ ++ for (p = buf; p < buf_end; p++) { ++ /* Crude cr/nl handling is better than none */ ++ if (*p == '\n') ++ prom_putchar('\r'); ++ prom_putchar(*p); ++ } ++} ++ ++#ifdef CONFIG_KGDB ++int putDebugChar(char c) ++{ ++ return prom_putchar(c); ++} ++ ++char getDebugChar(void) ++{ ++ return prom_getchar(); ++} ++#endif +diff -Nur linux-2.6.29.1.orig/arch/mips/ar7/setup.c linux-2.6.29.1/arch/mips/ar7/setup.c +--- linux-2.6.29.1.orig/arch/mips/ar7/setup.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/ar7/setup.c 2009-06-01 12:36:33.000000000 +0200 +@@ -0,0 +1,105 @@ ++/* ++ * Carsten Langgaard, carstenl@mips.com ++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. ++ * ++ * This program is free software; you can distribute it and/or modify it ++ * under the terms of the GNU General Public License (Version 2) as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. ++ */ ++#include <linux/version.h> ++#include <linux/init.h> ++#include <linux/ioport.h> ++#include <linux/pm.h> ++ ++#include <asm/reboot.h> ++#include <asm/time.h> ++#include <asm/mach-ar7/ar7.h> ++#include <asm/mach-ar7/prom.h> ++ ++static void ar7_machine_restart(char *command); ++static void ar7_machine_halt(void); ++static void ar7_machine_power_off(void); ++ ++static void ar7_machine_restart(char *command) ++{ ++ u32 *softres_reg = (u32 *)ioremap(AR7_REGS_RESET + ++ AR7_RESET_SOFTWARE, 1); ++ writel(1, softres_reg); ++} ++ ++static void ar7_machine_halt(void) ++{ ++ while (1); ++} ++ ++static void ar7_machine_power_off(void) ++{ ++ u32 *power_reg = (u32 *)ioremap(AR7_REGS_POWER, 1); ++ u32 power_state = readl(power_reg) | (3 << 30); ++ writel(power_state, power_reg); ++ ar7_machine_halt(); ++} ++ ++const char *get_system_type(void) ++{ ++ u16 chip_id = ar7_chip_id(); ++ switch (chip_id) { ++ case AR7_CHIP_7300: ++ return "TI AR7 (TNETD7300)"; ++ case AR7_CHIP_7100: ++ return "TI AR7 (TNETD7100)"; ++ case AR7_CHIP_7200: ++ return "TI AR7 (TNETD7200)"; ++ default: ++ return "TI AR7 (Unknown)"; ++ } ++} ++ ++static int __init ar7_init_console(void) ++{ ++ return 0; ++} ++ ++/* ++ * Initializes basic routines and structures pointers, memory size (as ++ * given by the bios and saves the command line. ++ */ ++ ++extern void ar7_init_clocks(void); ++ ++void __init plat_mem_setup(void) ++{ ++ unsigned long io_base; ++ ++ _machine_restart = ar7_machine_restart; ++ _machine_halt = ar7_machine_halt; ++ pm_power_off = ar7_machine_power_off; ++ panic_timeout = 3; ++ ++ io_base = (unsigned long)ioremap(AR7_REGS_BASE, 0x10000); ++ if (!io_base) panic("Can't remap IO base!\n"); ++ set_io_port_base(io_base); ++ ++ prom_meminit(); ++ ar7_init_clocks(); ++ ++ ioport_resource.start = 0; ++ ioport_resource.end = ~0; ++ iomem_resource.start = 0; ++ iomem_resource.end = ~0; ++ ++ printk(KERN_INFO "%s, ID: 0x%04x, Revision: 0x%02x\n", ++ get_system_type(), ++ ar7_chip_id(), ar7_chip_rev()); ++} ++ ++console_initcall(ar7_init_console); +diff -Nur linux-2.6.29.1.orig/arch/mips/ar7/time.c linux-2.6.29.1/arch/mips/ar7/time.c +--- linux-2.6.29.1.orig/arch/mips/ar7/time.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/ar7/time.c 2009-06-01 12:37:00.000000000 +0200 +@@ -0,0 +1,28 @@ ++/* ++ * Carsten Langgaard, carstenl@mips.com ++ * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. ++ * ++ * This program is free software; you can distribute it and/or modify it ++ * under the terms of the GNU General Public License (Version 2) as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope it will be useful, but WITHOUT ++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ++ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ++ * for more details. ++ * ++ * You should have received a copy of the GNU General Public License along ++ * with this program; if not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. ++ * ++ * Setting up the clock on the MIPS boards. ++ */ ++ ++#include <linux/version.h> ++#include <asm/time.h> ++#include <asm/mach-ar7/ar7.h> ++ ++void __init plat_time_init(void) ++{ ++ mips_hpt_frequency = ar7_cpu_freq() / 2; ++} +diff -Nur linux-2.6.29.1.orig/arch/mips/include/asm/mach-ar7/ar7.h linux-2.6.29.1/arch/mips/include/asm/mach-ar7/ar7.h +--- linux-2.6.29.1.orig/arch/mips/include/asm/mach-ar7/ar7.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/include/asm/mach-ar7/ar7.h 2009-05-31 19:50:04.000000000 +0200 +@@ -0,0 +1,170 @@ ++/* ++ * Copyright (C) 2006,2007 Felix Fietkau <nbd@openwrt.org> ++ * Copyright (C) 2006,2007 Eugene Konev <ejka@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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef __AR7_H__ ++#define __AR7_H__ ++ ++#include <linux/delay.h> ++#include <asm/addrspace.h> ++#include <linux/io.h> ++ ++#define AR7_REGS_BASE 0x08610000 ++ ++#define AR7_REGS_MAC0 (AR7_REGS_BASE + 0x0000) ++#define AR7_REGS_GPIO (AR7_REGS_BASE + 0x0900) ++/* 0x08610A00 - 0x08610BFF (512 bytes, 128 bytes / clock) */ ++#define AR7_REGS_POWER (AR7_REGS_BASE + 0x0a00) ++#define AR7_REGS_UART0 (AR7_REGS_BASE + 0x0e00) ++#define AR7_REGS_USB (AR7_REGS_BASE + 0x1200) ++#define AR7_REGS_RESET (AR7_REGS_BASE + 0x1600) ++#define AR7_REGS_VLYNQ0 (AR7_REGS_BASE + 0x1800) ++#define AR7_REGS_DCL (AR7_REGS_BASE + 0x1a00) ++#define AR7_REGS_VLYNQ1 (AR7_REGS_BASE + 0x1c00) ++#define AR7_REGS_MDIO (AR7_REGS_BASE + 0x1e00) ++#define AR7_REGS_IRQ (AR7_REGS_BASE + 0x2400) ++#define AR7_REGS_MAC1 (AR7_REGS_BASE + 0x2800) ++ ++#define AR7_REGS_WDT (AR7_REGS_BASE + 0x1f00) ++#define UR8_REGS_WDT (AR7_REGS_BASE + 0x0b00) ++#define UR8_REGS_UART1 (AR7_REGS_BASE + 0x0f00) ++ ++#define AR7_RESET_PEREPHERIAL 0x0 ++#define AR7_RESET_SOFTWARE 0x4 ++#define AR7_RESET_STATUS 0x8 ++ ++#define AR7_RESET_BIT_CPMAC_LO 17 ++#define AR7_RESET_BIT_CPMAC_HI 21 ++#define AR7_RESET_BIT_MDIO 22 ++#define AR7_RESET_BIT_EPHY 26 ++ ++/* GPIO control registers */ ++#define AR7_GPIO_INPUT 0x0 ++#define AR7_GPIO_OUTPUT 0x4 ++#define AR7_GPIO_DIR 0x8 ++#define AR7_GPIO_ENABLE 0xc ++ ++#define AR7_CHIP_7100 0x18 ++#define AR7_CHIP_7200 0x2b ++#define AR7_CHIP_7300 0x05 ++ ++/* Interrupts */ ++#define AR7_IRQ_UART0 15 ++#define AR7_IRQ_UART1 16 ++ ++/* Clocks */ ++#define AR7_AFE_CLOCK 35328000 ++#define AR7_REF_CLOCK 25000000 ++#define AR7_XTAL_CLOCK 24000000 ++ ++struct plat_cpmac_data { ++ int reset_bit; ++ int power_bit; ++ u32 phy_mask; ++ char dev_addr[6]; ++}; ++ ++struct plat_dsl_data { ++ int reset_bit_dsl; ++ int reset_bit_sar; ++}; ++ ++extern int ar7_cpu_clock, ar7_bus_clock, ar7_dsp_clock; ++ ++static inline u16 ar7_chip_id(void) ++{ ++ return readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) & 0xffff; ++} ++ ++static inline u8 ar7_chip_rev(void) ++{ ++ return (readl((void *)KSEG1ADDR(AR7_REGS_GPIO + 0x14)) >> 16) & 0xff; ++} ++ ++static inline int ar7_cpu_freq(void) ++{ ++ return ar7_cpu_clock; ++} ++ ++static inline int ar7_bus_freq(void) ++{ ++ return ar7_bus_clock; ++} ++ ++static inline int ar7_vbus_freq(void) ++{ ++ return ar7_bus_clock / 2; ++} ++#define ar7_cpmac_freq ar7_vbus_freq ++ ++static inline int ar7_dsp_freq(void) ++{ ++ return ar7_dsp_clock; ++} ++ ++static inline int ar7_has_high_cpmac(void) ++{ ++ u16 chip_id = ar7_chip_id(); ++ switch (chip_id) { ++ case AR7_CHIP_7100: ++ case AR7_CHIP_7200: ++ return 0; ++ default: ++ return 1; ++ } ++} ++#define ar7_has_high_vlynq ar7_has_high_cpmac ++#define ar7_has_second_uart ar7_has_high_cpmac ++ ++static inline void ar7_device_enable(u32 bit) ++{ ++ void *reset_reg = ++ (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL); ++ writel(readl(reset_reg) | (1 << bit), reset_reg); ++ mdelay(20); ++} ++ ++static inline void ar7_device_disable(u32 bit) ++{ ++ void *reset_reg = ++ (void *)KSEG1ADDR(AR7_REGS_RESET + AR7_RESET_PEREPHERIAL); ++ writel(readl(reset_reg) & ~(1 << bit), reset_reg); ++ mdelay(20); ++} ++ ++static inline void ar7_device_reset(u32 bit) ++{ ++ ar7_device_disable(bit); ++ ar7_device_enable(bit); ++} ++ ++static inline void ar7_device_on(u32 bit) ++{ ++ void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER); ++ writel(readl(power_reg) | (1 << bit), power_reg); ++ mdelay(20); ++} ++ ++static inline void ar7_device_off(u32 bit) ++{ ++ void *power_reg = (void *)KSEG1ADDR(AR7_REGS_POWER); ++ writel(readl(power_reg) & ~(1 << bit), power_reg); ++ mdelay(20); ++} ++ ++#endif /* __AR7_H__ */ +diff -Nur linux-2.6.29.1.orig/arch/mips/include/asm/mach-ar7/gpio.h linux-2.6.29.1/arch/mips/include/asm/mach-ar7/gpio.h +--- linux-2.6.29.1.orig/arch/mips/include/asm/mach-ar7/gpio.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/include/asm/mach-ar7/gpio.h 2009-05-31 20:26:23.000000000 +0200 +@@ -0,0 +1,109 @@ ++/* ++ * Copyright (C) 2007 Florian Fainelli <florian@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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef __AR7_GPIO_H__ ++#define __AR7_GPIO_H__ ++#include <asm/mach-ar7/ar7.h> ++ ++#define AR7_GPIO_MAX 32 ++ ++extern int gpio_request(unsigned gpio, const char *label); ++extern void gpio_free(unsigned gpio); ++ ++/* Common GPIO layer */ ++static inline int gpio_get_value(unsigned gpio) ++{ ++ void __iomem *gpio_in = ++ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_INPUT); ++ ++ return readl(gpio_in) & (1 << gpio); ++} ++ ++static inline void gpio_set_value(unsigned gpio, int value) ++{ ++ void __iomem *gpio_out = ++ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_OUTPUT); ++ unsigned tmp; ++ ++ tmp = readl(gpio_out) & ~(1 << gpio); ++ if (value) ++ tmp |= 1 << gpio; ++ writel(tmp, gpio_out); ++} ++ ++static inline int gpio_direction_input(unsigned gpio) ++{ ++ void __iomem *gpio_dir = ++ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR); ++ ++ if (gpio >= AR7_GPIO_MAX) ++ return -EINVAL; ++ ++ writel(readl(gpio_dir) | (1 << gpio), gpio_dir); ++ ++ return 0; ++} ++ ++static inline int gpio_direction_output(unsigned gpio, int value) ++{ ++ void __iomem *gpio_dir = ++ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_DIR); ++ ++ if (gpio >= AR7_GPIO_MAX) ++ return -EINVAL; ++ ++ gpio_set_value(gpio, value); ++ writel(readl(gpio_dir) & ~(1 << gpio), gpio_dir); ++ ++ return 0; ++} ++ ++static inline int gpio_to_irq(unsigned gpio) ++{ ++ return -EINVAL; ++} ++ ++static inline int irq_to_gpio(unsigned irq) ++{ ++ return -EINVAL; ++} ++ ++/* Board specific GPIO functions */ ++static inline int ar7_gpio_enable(unsigned gpio) ++{ ++ void __iomem *gpio_en = ++ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE); ++ ++ writel(readl(gpio_en) | (1 << gpio), gpio_en); ++ ++ return 0; ++} ++ ++static inline int ar7_gpio_disable(unsigned gpio) ++{ ++ void __iomem *gpio_en = ++ (void __iomem *)KSEG1ADDR(AR7_REGS_GPIO + AR7_GPIO_ENABLE); ++ ++ writel(readl(gpio_en) & ~(1 << gpio), gpio_en); ++ ++ return 0; ++} ++ ++#include <asm-generic/gpio.h> ++ ++#endif +diff -Nur linux-2.6.29.1.orig/arch/mips/include/asm/mach-ar7/irq.h linux-2.6.29.1/arch/mips/include/asm/mach-ar7/irq.h +--- linux-2.6.29.1.orig/arch/mips/include/asm/mach-ar7/irq.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/include/asm/mach-ar7/irq.h 2009-05-31 19:50:04.000000000 +0200 +@@ -0,0 +1,16 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * Shamelessly copied from asm-mips/mach-emma2rh/ ++ * Copyright (C) 2003 by Ralf Baechle ++ */ ++#ifndef __ASM_AR7_IRQ_H ++#define __ASM_AR7_IRQ_H ++ ++#define NR_IRQS 256 ++ ++#include_next <irq.h> ++ ++#endif /* __ASM_AR7_IRQ_H */ +diff -Nur linux-2.6.29.1.orig/arch/mips/include/asm/mach-ar7/prom.h linux-2.6.29.1/arch/mips/include/asm/mach-ar7/prom.h +--- linux-2.6.29.1.orig/arch/mips/include/asm/mach-ar7/prom.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/include/asm/mach-ar7/prom.h 2009-05-31 19:50:04.000000000 +0200 +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2006, 2007 Florian Fainelli <florian@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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef __PROM_H__ ++#define __PROM_H__ ++ ++extern char *prom_getenv(const char *name); ++extern void prom_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); ++extern void prom_meminit(void); ++ ++#endif /* __PROM_H__ */ +diff -Nur linux-2.6.29.1.orig/arch/mips/include/asm/mach-ar7/spaces.h linux-2.6.29.1/arch/mips/include/asm/mach-ar7/spaces.h +--- linux-2.6.29.1.orig/arch/mips/include/asm/mach-ar7/spaces.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/include/asm/mach-ar7/spaces.h 2009-05-31 19:50:04.000000000 +0200 +@@ -0,0 +1,32 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * Copyright (C) 1994 - 1999, 2000, 03, 04 Ralf Baechle ++ * Copyright (C) 2000, 2002 Maciej W. Rozycki ++ * Copyright (C) 1990, 1999, 2000 Silicon Graphics, Inc. ++ */ ++#ifndef _ASM_AR7_SPACES_H ++#define _ASM_AR7_SPACES_H ++ ++#define CAC_BASE 0x80000000 ++#define IO_BASE 0xa0000000 ++#define UNCAC_BASE 0xa0000000 ++#define MAP_BASE 0xc0000000 ++ ++/* ++ * This handles the memory map. ++ * We handle pages at KSEG0 for kernels with 32 bit address space. ++ */ ++#define PAGE_OFFSET 0x94000000UL ++#define PHYS_OFFSET 0x14000000UL ++ ++/* ++ * Memory above this physical address will be considered highmem. ++ */ ++#ifndef HIGHMEM_START ++#define HIGHMEM_START 0x40000000UL ++#endif ++ ++#endif /* __ASM_AR7_SPACES_H */ +diff -Nur linux-2.6.29.1.orig/arch/mips/include/asm/mach-ar7/war.h linux-2.6.29.1/arch/mips/include/asm/mach-ar7/war.h +--- linux-2.6.29.1.orig/arch/mips/include/asm/mach-ar7/war.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/arch/mips/include/asm/mach-ar7/war.h 2009-05-31 19:50:04.000000000 +0200 +@@ -0,0 +1,25 @@ ++/* ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file "COPYING" in the main directory of this archive ++ * for more details. ++ * ++ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org> ++ */ ++#ifndef __ASM_MIPS_MACH_BCM947XX_WAR_H ++#define __ASM_MIPS_MACH_BCM947XX_WAR_H ++ ++#define R4600_V1_INDEX_ICACHEOP_WAR 0 ++#define R4600_V1_HIT_CACHEOP_WAR 0 ++#define R4600_V2_HIT_CACHEOP_WAR 0 ++#define R5432_CP0_INTERRUPT_WAR 0 ++#define BCM1250_M3_WAR 0 ++#define SIBYTE_1956_WAR 0 ++#define MIPS4K_ICACHE_REFILL_WAR 0 ++#define MIPS_CACHE_SYNC_WAR 0 ++#define TX49XX_ICACHE_INDEX_INV_WAR 0 ++#define RM9000_CDEX_SMP_WAR 0 ++#define ICACHE_REFILLS_WORKAROUND_WAR 0 ++#define R10000_LLSC_WAR 0 ++#define MIPS34K_MISSED_ITLB_WAR 0 ++ ++#endif /* __ASM_MIPS_MACH_BCM947XX_WAR_H */ +diff -Nur linux-2.6.29.1.orig/arch/mips/include/asm/page.h linux-2.6.29.1/arch/mips/include/asm/page.h +--- linux-2.6.29.1.orig/arch/mips/include/asm/page.h 2009-04-02 22:55:27.000000000 +0200 ++++ linux-2.6.29.1/arch/mips/include/asm/page.h 2009-05-31 19:57:06.000000000 +0200 +@@ -182,8 +182,11 @@ + #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ + VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) + +-#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE) +-#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET) ++#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE + \ ++ PHYS_OFFSET) ++#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET - \ ++ PHYS_OFFSET) ++ + + #include <asm-generic/memory_model.h> + #include <asm-generic/page.h> +diff -Nur linux-2.6.29.1.orig/arch/mips/Kconfig linux-2.6.29.1/arch/mips/Kconfig +--- linux-2.6.29.1.orig/arch/mips/Kconfig 2009-04-02 22:55:27.000000000 +0200 ++++ linux-2.6.29.1/arch/mips/Kconfig 2009-05-31 19:55:40.000000000 +0200 +@@ -19,6 +19,24 @@ + prompt "System type" + default SGI_IP22 + ++config AR7 ++ bool "Texas Instruments AR7" ++ select BOOT_ELF32 ++ select DMA_NONCOHERENT ++ select CEVT_R4K ++ select CSRC_R4K ++ select IRQ_CPU ++ select NO_EXCEPT_FILL ++ select SWAP_IO_SPACE ++ select SYS_HAS_CPU_MIPS32_R1 ++ select SYS_HAS_EARLY_PRINTK ++ select SYS_SUPPORTS_32BIT_KERNEL ++ select SYS_SUPPORTS_KGDB ++ select SYS_SUPPORTS_LITTLE_ENDIAN ++ select SYS_SUPPORTS_BIG_ENDIAN ++ select GENERIC_GPIO ++ select GENERIC_HARDIRQS_NO__DO_IRQ ++ + config MACH_ALCHEMY + bool "Alchemy processor based machines" + +diff -Nur linux-2.6.29.1.orig/arch/mips/kernel/traps.c linux-2.6.29.1/arch/mips/kernel/traps.c +--- linux-2.6.29.1.orig/arch/mips/kernel/traps.c 2009-04-02 22:55:27.000000000 +0200 ++++ linux-2.6.29.1/arch/mips/kernel/traps.c 2009-05-31 23:46:49.000000000 +0200 +@@ -1256,9 +1256,22 @@ + + exception_handlers[n] = handler; + if (n == 0 && cpu_has_divec) { +- *(u32 *)(ebase + 0x200) = 0x08000000 | +- (0x03ffffff & (handler >> 2)); +- local_flush_icache_range(ebase + 0x200, ebase + 0x204); ++ if ((handler ^ (ebase + 4)) & 0xfc000000) { ++ /* lui k0, 0x0000 */ ++ *(u32 *)(ebase + 0x200) = 0x3c1a0000 | (handler >> 16); ++ /* ori k0, 0x0000 */ ++ *(u32 *)(ebase + 0x204) = ++ 0x375a0000 | (handler & 0xffff); ++ /* jr k0 */ ++ *(u32 *)(ebase + 0x208) = 0x03400008; ++ /* nop */ ++ *(u32 *)(ebase + 0x20C) = 0x00000000; ++ flush_icache_range(ebase + 0x200, ebase + 0x210); ++ } else { ++ *(u32 *)(ebase + 0x200) = ++ 0x08000000 | (0x03ffffff & (handler >> 2)); ++ flush_icache_range(ebase + 0x200, ebase + 0x204); ++ } + } + return (void *)old_handler; + } +diff -Nur linux-2.6.29.1.orig/arch/mips/Makefile linux-2.6.29.1/arch/mips/Makefile +--- linux-2.6.29.1.orig/arch/mips/Makefile 2009-04-02 22:55:27.000000000 +0200 ++++ linux-2.6.29.1/arch/mips/Makefile 2009-05-31 20:01:45.000000000 +0200 +@@ -173,6 +173,13 @@ + # + + # ++# Texas Instruments AR7 ++# ++core-$(CONFIG_AR7) += arch/mips/ar7/ ++cflags-$(CONFIG_AR7) += -I$(srctree)/arch/mips/include/asm/mach-ar7 ++load-$(CONFIG_AR7) += 0xffffffff94100000 ++ ++# + # Acer PICA 61, Mips Magnum 4000 and Olivetti M700. + # + core-$(CONFIG_MACH_JAZZ) += arch/mips/jazz/ +diff -Nur linux-2.6.29.1.orig/drivers/char/ar7_gpio.c linux-2.6.29.1/drivers/char/ar7_gpio.c +--- linux-2.6.29.1.orig/drivers/char/ar7_gpio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/drivers/char/ar7_gpio.c 2009-05-31 19:53:09.000000000 +0200 +@@ -0,0 +1,158 @@ ++/* ++ * Copyright (C) 2007 Nicolas Thill <nico@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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include <linux/device.h> ++#include <linux/fs.h> ++#include <linux/module.h> ++#include <linux/errno.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/platform_device.h> ++#include <linux/uaccess.h> ++#include <linux/io.h> ++#include <linux/types.h> ++#include <linux/cdev.h> ++#include <gpio.h> ++ ++#define DRVNAME "ar7_gpio" ++#define LONGNAME "TI AR7 GPIOs Driver" ++ ++MODULE_AUTHOR("Nicolas Thill <nico@openwrt.org>"); ++MODULE_DESCRIPTION(LONGNAME); ++MODULE_LICENSE("GPL"); ++ ++static int ar7_gpio_major; ++ ++static ssize_t ar7_gpio_write(struct file *file, const char __user *buf, ++ size_t len, loff_t *ppos) ++{ ++ int pin = iminor(file->f_dentry->d_inode); ++ size_t i; ++ ++ for (i = 0; i < len; ++i) { ++ char c; ++ if (get_user(c, buf + i)) ++ return -EFAULT; ++ switch (c) { ++ case '0': ++ gpio_set_value(pin, 0); ++ break; ++ case '1': ++ gpio_set_value(pin, 1); ++ break; ++ case 'd': ++ case 'D': ++ ar7_gpio_disable(pin); ++ break; ++ case 'e': ++ case 'E': ++ ar7_gpio_enable(pin); ++ break; ++ case 'i': ++ case 'I': ++ case '<': ++ gpio_direction_input(pin); ++ break; ++ case 'o': ++ case 'O': ++ case '>': ++ gpio_direction_output(pin, 0); ++ break; ++ default: ++ return -EINVAL; ++ } ++ } ++ ++ return len; ++} ++ ++static ssize_t ar7_gpio_read(struct file *file, char __user *buf, ++ size_t len, loff_t *ppos) ++{ ++ int pin = iminor(file->f_dentry->d_inode); ++ int value; ++ ++ value = gpio_get_value(pin); ++ if (put_user(value ? '1' : '0', buf)) ++ return -EFAULT; ++ ++ return 1; ++} ++ ++static int ar7_gpio_open(struct inode *inode, struct file *file) ++{ ++ int m = iminor(inode); ++ ++ if (m >= AR7_GPIO_MAX) ++ return -EINVAL; ++ ++ return nonseekable_open(inode, file); ++} ++ ++static int ar7_gpio_release(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static const struct file_operations ar7_gpio_fops = { ++ .owner = THIS_MODULE, ++ .write = ar7_gpio_write, ++ .read = ar7_gpio_read, ++ .open = ar7_gpio_open, ++ .release = ar7_gpio_release, ++ .llseek = no_llseek, ++}; ++ ++static struct platform_device *ar7_gpio_device; ++ ++static int __init ar7_gpio_init(void) ++{ ++ int rc; ++ ++ ar7_gpio_device = platform_device_alloc(DRVNAME, -1); ++ if (!ar7_gpio_device) ++ return -ENOMEM; ++ ++ rc = platform_device_add(ar7_gpio_device); ++ if (rc < 0) ++ goto out_put; ++ ++ rc = register_chrdev(ar7_gpio_major, DRVNAME, &ar7_gpio_fops); ++ if (rc < 0) ++ goto out_put; ++ ++ ar7_gpio_major = rc; ++ ++ rc = 0; ++ ++ goto out; ++ ++out_put: ++ platform_device_put(ar7_gpio_device); ++out: ++ return rc; ++} ++ ++static void __exit ar7_gpio_exit(void) ++{ ++ unregister_chrdev(ar7_gpio_major, DRVNAME); ++ platform_device_unregister(ar7_gpio_device); ++} ++ ++module_init(ar7_gpio_init); ++module_exit(ar7_gpio_exit); +diff -Nur linux-2.6.29.1.orig/drivers/char/Kconfig linux-2.6.29.1/drivers/char/Kconfig +--- linux-2.6.29.1.orig/drivers/char/Kconfig 2009-04-02 22:55:27.000000000 +0200 ++++ linux-2.6.29.1/drivers/char/Kconfig 2009-05-31 20:03:22.000000000 +0200 +@@ -974,6 +974,15 @@ + To compile this driver as a module, choose M here: the + module will be called mwave. + ++config AR7_GPIO ++ tristate "TI AR7 GPIO Support" ++ depends on AR7 ++ help ++ Give userspace access to the GPIO pins on the Texas Instruments AR7 ++ processors. ++ ++ If compiled as a module, it will be called ar7_gpio. ++ + config SCx200_GPIO + tristate "NatSemi SCx200 GPIO Support" + depends on SCx200 +diff -Nur linux-2.6.29.1.orig/drivers/char/Makefile linux-2.6.29.1/drivers/char/Makefile +--- linux-2.6.29.1.orig/drivers/char/Makefile 2009-04-02 22:55:27.000000000 +0200 ++++ linux-2.6.29.1/drivers/char/Makefile 2009-05-31 20:03:22.000000000 +0200 +@@ -90,6 +90,7 @@ + obj-$(CONFIG_PPDEV) += ppdev.o + obj-$(CONFIG_NWBUTTON) += nwbutton.o + obj-$(CONFIG_NWFLASH) += nwflash.o ++obj-$(CONFIG_AR7_GPIO) += ar7_gpio.o + obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o + obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o + obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o +diff -Nur linux-2.6.29.1.orig/drivers/Kconfig linux-2.6.29.1/drivers/Kconfig +--- linux-2.6.29.1.orig/drivers/Kconfig 2009-04-02 22:55:27.000000000 +0200 ++++ linux-2.6.29.1/drivers/Kconfig 2009-05-31 20:03:35.000000000 +0200 +@@ -104,6 +104,8 @@ + + source "drivers/uio/Kconfig" + ++source "drivers/vlynq/Kconfig" ++ + source "drivers/xen/Kconfig" + + source "drivers/staging/Kconfig" +diff -Nur linux-2.6.29.1.orig/drivers/Makefile linux-2.6.29.1/drivers/Makefile +--- linux-2.6.29.1.orig/drivers/Makefile 2009-04-02 22:55:27.000000000 +0200 ++++ linux-2.6.29.1/drivers/Makefile 2009-05-31 20:03:35.000000000 +0200 +@@ -102,6 +102,7 @@ + obj-$(CONFIG_HID) += hid/ + obj-$(CONFIG_PPC_PS3) += ps3/ + obj-$(CONFIG_OF) += of/ ++obj-$(CONFIG_VLYNQ) += vlynq/ + obj-$(CONFIG_SSB) += ssb/ + obj-$(CONFIG_VIRTIO) += virtio/ + obj-$(CONFIG_STAGING) += staging/ +diff -Nur linux-2.6.29.1.orig/drivers/mtd/maps/physmap.c linux-2.6.29.1/drivers/mtd/maps/physmap.c +--- linux-2.6.29.1.orig/drivers/mtd/maps/physmap.c 2009-04-02 22:55:27.000000000 +0200 ++++ linux-2.6.29.1/drivers/mtd/maps/physmap.c 2009-05-31 20:02:55.000000000 +0200 +@@ -80,7 +80,7 @@ + "map_rom", + NULL }; + #ifdef CONFIG_MTD_PARTITIONS +-static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; ++static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", "ar7part", NULL }; + #endif + + static int physmap_flash_probe(struct platform_device *dev) +diff -Nur linux-2.6.29.1.orig/drivers/net/cpmac.c linux-2.6.29.1/drivers/net/cpmac.c +--- linux-2.6.29.1.orig/drivers/net/cpmac.c 2009-04-02 22:55:27.000000000 +0200 ++++ linux-2.6.29.1/drivers/net/cpmac.c 2009-06-01 15:23:14.000000000 +0200 +@@ -615,13 +615,13 @@ + + dev_kfree_skb_irq(desc->skb); + desc->skb = NULL; +- if (netif_subqueue_stopped(dev, queue)) ++ if (__netif_subqueue_stopped(dev, queue)) + netif_wake_subqueue(dev, queue); + } else { + if (netif_msg_tx_err(priv) && net_ratelimit()) + printk(KERN_WARNING + "%s: end_xmit: spurious interrupt\n", dev->name); +- if (netif_subqueue_stopped(dev, queue)) ++ if (__netif_subqueue_stopped(dev, queue)) + netif_wake_subqueue(dev, queue); + } + } +@@ -731,7 +731,6 @@ + + static void cpmac_hw_error(struct work_struct *work) + { +- int i; + struct cpmac_priv *priv = + container_of(work, struct cpmac_priv, reset_work); + +@@ -818,7 +817,6 @@ + + static void cpmac_tx_timeout(struct net_device *dev) + { +- int i; + struct cpmac_priv *priv = netdev_priv(dev); + + spin_lock(&priv->lock); +@@ -1093,12 +1091,10 @@ + return 0; + } + +-static int external_switch; +- + static int __devinit cpmac_probe(struct platform_device *pdev) + { +- int rc, phy_id, i; +- char *mdio_bus_id = "0"; ++ int rc, phy_id; ++ char mdio_bus_id[BUS_ID_SIZE]; + struct resource *mem; + struct cpmac_priv *priv; + struct net_device *dev; +@@ -1115,16 +1111,13 @@ + } + + if (phy_id == PHY_MAX_ADDR) { +- if (external_switch || dumb_switch) { +- mdio_bus_id = 0; /* fixed phys bus */ +- phy_id = pdev->id; +- } else { + dev_err(&pdev->dev, "no PHY present\n"); + return -ENODEV; + } + } + + dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES); ++ //~ dev = alloc_etherdev(sizeof(*priv)); + + if (!dev) { + printk(KERN_ERR "cpmac: Unable to allocate net_device\n"); +@@ -1236,17 +1229,11 @@ + + cpmac_mii->reset(cpmac_mii); + +- for (i = 0; i < 300000; i++) ++ for (i = 0; i < 300; i++) + if ((mask = cpmac_read(cpmac_mii->priv, CPMAC_MDIO_ALIVE))) + break; + else +- cpu_relax(); +- +- mask &= 0x7fffffff; +- if (mask & (mask - 1)) { +- external_switch = 1; +- mask = 0; +- } ++ msleep(10); + + cpmac_mii->phy_mask = ~(mask | 0x80000000); + snprintf(cpmac_mii->id, MII_BUS_ID_SIZE, "0"); +diff -Nur linux-2.6.29.1.orig/drivers/net/cpmac.c.orig linux-2.6.29.1/drivers/net/cpmac.c.orig +--- linux-2.6.29.1.orig/drivers/net/cpmac.c.orig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/drivers/net/cpmac.c.orig 2009-06-01 14:37:40.000000000 +0200 +@@ -0,0 +1,1285 @@ ++/* ++ * Copyright (C) 2006, 2007 Eugene Konev ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/moduleparam.h> ++ ++#include <linux/sched.h> ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/errno.h> ++#include <linux/types.h> ++#include <linux/delay.h> ++ ++#include <linux/netdevice.h> ++#include <linux/etherdevice.h> ++#include <linux/ethtool.h> ++#include <linux/skbuff.h> ++#include <linux/mii.h> ++#include <linux/phy.h> ++#include <linux/phy_fixed.h> ++#include <linux/platform_device.h> ++#include <linux/dma-mapping.h> ++#include <asm/gpio.h> ++#include <asm/atomic.h> ++ ++MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>"); ++MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:cpmac"); ++ ++static int debug_level = 8; ++static int dumb_switch; ++ ++/* Next 2 are only used in cpmac_probe, so it's pointless to change them */ ++module_param(debug_level, int, 0444); ++module_param(dumb_switch, int, 0444); ++ ++MODULE_PARM_DESC(debug_level, "Number of NETIF_MSG bits to enable"); ++MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus"); ++ ++#define CPMAC_VERSION "0.5.0" ++/* frame size + 802.1q tag */ ++#define CPMAC_SKB_SIZE (ETH_FRAME_LEN + 4) ++#define CPMAC_QUEUES 8 ++ ++/* Ethernet registers */ ++#define CPMAC_TX_CONTROL 0x0004 ++#define CPMAC_TX_TEARDOWN 0x0008 ++#define CPMAC_RX_CONTROL 0x0014 ++#define CPMAC_RX_TEARDOWN 0x0018 ++#define CPMAC_MBP 0x0100 ++# define MBP_RXPASSCRC 0x40000000 ++# define MBP_RXQOS 0x20000000 ++# define MBP_RXNOCHAIN 0x10000000 ++# define MBP_RXCMF 0x01000000 ++# define MBP_RXSHORT 0x00800000 ++# define MBP_RXCEF 0x00400000 ++# define MBP_RXPROMISC 0x00200000 ++# define MBP_PROMISCCHAN(channel) (((channel) & 0x7) << 16) ++# define MBP_RXBCAST 0x00002000 ++# define MBP_BCASTCHAN(channel) (((channel) & 0x7) << 8) ++# define MBP_RXMCAST 0x00000020 ++# define MBP_MCASTCHAN(channel) ((channel) & 0x7) ++#define CPMAC_UNICAST_ENABLE 0x0104 ++#define CPMAC_UNICAST_CLEAR 0x0108 ++#define CPMAC_MAX_LENGTH 0x010c ++#define CPMAC_BUFFER_OFFSET 0x0110 ++#define CPMAC_MAC_CONTROL 0x0160 ++# define MAC_TXPTYPE 0x00000200 ++# define MAC_TXPACE 0x00000040 ++# define MAC_MII 0x00000020 ++# define MAC_TXFLOW 0x00000010 ++# define MAC_RXFLOW 0x00000008 ++# define MAC_MTEST 0x00000004 ++# define MAC_LOOPBACK 0x00000002 ++# define MAC_FDX 0x00000001 ++#define CPMAC_MAC_STATUS 0x0164 ++# define MAC_STATUS_QOS 0x00000004 ++# define MAC_STATUS_RXFLOW 0x00000002 ++# define MAC_STATUS_TXFLOW 0x00000001 ++#define CPMAC_TX_INT_ENABLE 0x0178 ++#define CPMAC_TX_INT_CLEAR 0x017c ++#define CPMAC_MAC_INT_VECTOR 0x0180 ++# define MAC_INT_STATUS 0x00080000 ++# define MAC_INT_HOST 0x00040000 ++# define MAC_INT_RX 0x00020000 ++# define MAC_INT_TX 0x00010000 ++#define CPMAC_MAC_EOI_VECTOR 0x0184 ++#define CPMAC_RX_INT_ENABLE 0x0198 ++#define CPMAC_RX_INT_CLEAR 0x019c ++#define CPMAC_MAC_INT_ENABLE 0x01a8 ++#define CPMAC_MAC_INT_CLEAR 0x01ac ++#define CPMAC_MAC_ADDR_LO(channel) (0x01b0 + (channel) * 4) ++#define CPMAC_MAC_ADDR_MID 0x01d0 ++#define CPMAC_MAC_ADDR_HI 0x01d4 ++#define CPMAC_MAC_HASH_LO 0x01d8 ++#define CPMAC_MAC_HASH_HI 0x01dc ++#define CPMAC_TX_PTR(channel) (0x0600 + (channel) * 4) ++#define CPMAC_RX_PTR(channel) (0x0620 + (channel) * 4) ++#define CPMAC_TX_ACK(channel) (0x0640 + (channel) * 4) ++#define CPMAC_RX_ACK(channel) (0x0660 + (channel) * 4) ++#define CPMAC_REG_END 0x0680 ++/* ++ * Rx/Tx statistics ++ * TODO: use some of them to fill stats in cpmac_stats() ++ */ ++#define CPMAC_STATS_RX_GOOD 0x0200 ++#define CPMAC_STATS_RX_BCAST 0x0204 ++#define CPMAC_STATS_RX_MCAST 0x0208 ++#define CPMAC_STATS_RX_PAUSE 0x020c ++#define CPMAC_STATS_RX_CRC 0x0210 ++#define CPMAC_STATS_RX_ALIGN 0x0214 ++#define CPMAC_STATS_RX_OVER 0x0218 ++#define CPMAC_STATS_RX_JABBER 0x021c ++#define CPMAC_STATS_RX_UNDER 0x0220 ++#define CPMAC_STATS_RX_FRAG 0x0224 ++#define CPMAC_STATS_RX_FILTER 0x0228 ++#define CPMAC_STATS_RX_QOSFILTER 0x022c ++#define CPMAC_STATS_RX_OCTETS 0x0230 ++ ++#define CPMAC_STATS_TX_GOOD 0x0234 ++#define CPMAC_STATS_TX_BCAST 0x0238 ++#define CPMAC_STATS_TX_MCAST 0x023c ++#define CPMAC_STATS_TX_PAUSE 0x0240 ++#define CPMAC_STATS_TX_DEFER 0x0244 ++#define CPMAC_STATS_TX_COLLISION 0x0248 ++#define CPMAC_STATS_TX_SINGLECOLL 0x024c ++#define CPMAC_STATS_TX_MULTICOLL 0x0250 ++#define CPMAC_STATS_TX_EXCESSCOLL 0x0254 ++#define CPMAC_STATS_TX_LATECOLL 0x0258 ++#define CPMAC_STATS_TX_UNDERRUN 0x025c ++#define CPMAC_STATS_TX_CARRIERSENSE 0x0260 ++#define CPMAC_STATS_TX_OCTETS 0x0264 ++ ++#define cpmac_read(base, reg) (readl((void __iomem *)(base) + (reg))) ++#define cpmac_write(base, reg, val) (writel(val, (void __iomem *)(base) + \ ++ (reg))) ++ ++/* MDIO bus */ ++#define CPMAC_MDIO_VERSION 0x0000 ++#define CPMAC_MDIO_CONTROL 0x0004 ++# define MDIOC_IDLE 0x80000000 ++# define MDIOC_ENABLE 0x40000000 ++# define MDIOC_PREAMBLE 0x00100000 ++# define MDIOC_FAULT 0x00080000 ++# define MDIOC_FAULTDETECT 0x00040000 ++# define MDIOC_INTTEST 0x00020000 ++# define MDIOC_CLKDIV(div) ((div) & 0xff) ++#define CPMAC_MDIO_ALIVE 0x0008 ++#define CPMAC_MDIO_LINK 0x000c ++#define CPMAC_MDIO_ACCESS(channel) (0x0080 + (channel) * 8) ++# define MDIO_BUSY 0x80000000 ++# define MDIO_WRITE 0x40000000 ++# define MDIO_REG(reg) (((reg) & 0x1f) << 21) ++# define MDIO_PHY(phy) (((phy) & 0x1f) << 16) ++# define MDIO_DATA(data) ((data) & 0xffff) ++#define CPMAC_MDIO_PHYSEL(channel) (0x0084 + (channel) * 8) ++# define PHYSEL_LINKSEL 0x00000040 ++# define PHYSEL_LINKINT 0x00000020 ++ ++struct cpmac_desc { ++ u32 hw_next; ++ u32 hw_data; ++ u16 buflen; ++ u16 bufflags; ++ u16 datalen; ++ u16 dataflags; ++#define CPMAC_SOP 0x8000 ++#define CPMAC_EOP 0x4000 ++#define CPMAC_OWN 0x2000 ++#define CPMAC_EOQ 0x1000 ++ struct sk_buff *skb; ++ struct cpmac_desc *next; ++ struct cpmac_desc *prev; ++ dma_addr_t mapping; ++ dma_addr_t data_mapping; ++}; ++ ++struct cpmac_priv { ++ spinlock_t lock; ++ spinlock_t rx_lock; ++ struct cpmac_desc *rx_head; ++ int ring_size; ++ struct cpmac_desc *desc_ring; ++ dma_addr_t dma_ring; ++ void __iomem *regs; ++ struct mii_bus *mii_bus; ++ struct phy_device *phy; ++ char phy_name[BUS_ID_SIZE]; ++ int oldlink, oldspeed, oldduplex; ++ u32 msg_enable; ++ struct net_device *dev; ++ struct work_struct reset_work; ++ struct platform_device *pdev; ++ struct napi_struct napi; ++ atomic_t reset_pending; ++}; ++ ++static irqreturn_t cpmac_irq(int, void *); ++static void cpmac_hw_start(struct net_device *dev); ++static void cpmac_hw_stop(struct net_device *dev); ++static int cpmac_stop(struct net_device *dev); ++static int cpmac_open(struct net_device *dev); ++ ++static void cpmac_dump_regs(struct net_device *dev) ++{ ++ int i; ++ struct cpmac_priv *priv = netdev_priv(dev); ++ for (i = 0; i < CPMAC_REG_END; i += 4) { ++ if (i % 16 == 0) { ++ if (i) ++ printk("\n"); ++ printk(KERN_DEBUG "%s: reg[%p]:", dev->name, ++ priv->regs + i); ++ } ++ printk(" %08x", cpmac_read(priv->regs, i)); ++ } ++ printk("\n"); ++} ++ ++static void cpmac_dump_desc(struct net_device *dev, struct cpmac_desc *desc) ++{ ++ int i; ++ printk(KERN_DEBUG "%s: desc[%p]:", dev->name, desc); ++ for (i = 0; i < sizeof(*desc) / 4; i++) ++ printk(" %08x", ((u32 *)desc)[i]); ++ printk("\n"); ++} ++ ++static void cpmac_dump_all_desc(struct net_device *dev) ++{ ++ struct cpmac_priv *priv = netdev_priv(dev); ++ struct cpmac_desc *dump = priv->rx_head; ++ do { ++ cpmac_dump_desc(dev, dump); ++ dump = dump->next; ++ } while (dump != priv->rx_head); ++} ++ ++static void cpmac_dump_skb(struct net_device *dev, struct sk_buff *skb) ++{ ++ int i; ++ printk(KERN_DEBUG "%s: skb 0x%p, len=%d\n", dev->name, skb, skb->len); ++ for (i = 0; i < skb->len; i++) { ++ if (i % 16 == 0) { ++ if (i) ++ printk("\n"); ++ printk(KERN_DEBUG "%s: data[%p]:", dev->name, ++ skb->data + i); ++ } ++ printk(" %02x", ((u8 *)skb->data)[i]); ++ } ++ printk("\n"); ++} ++ ++static int cpmac_mdio_read(struct mii_bus *bus, int phy_id, int reg) ++{ ++ u32 val; ++ ++ while (cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0)) & MDIO_BUSY) ++ cpu_relax(); ++ cpmac_write(bus->priv, CPMAC_MDIO_ACCESS(0), MDIO_BUSY | MDIO_REG(reg) | ++ MDIO_PHY(phy_id)); ++ while ((val = cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0))) & MDIO_BUSY) ++ cpu_relax(); ++ return MDIO_DATA(val); ++} ++ ++static int cpmac_mdio_write(struct mii_bus *bus, int phy_id, ++ int reg, u16 val) ++{ ++ while (cpmac_read(bus->priv, CPMAC_MDIO_ACCESS(0)) & MDIO_BUSY) ++ cpu_relax(); ++ cpmac_write(bus->priv, CPMAC_MDIO_ACCESS(0), MDIO_BUSY | MDIO_WRITE | ++ MDIO_REG(reg) | MDIO_PHY(phy_id) | MDIO_DATA(val)); ++ return 0; ++} ++ ++static int cpmac_mdio_reset(struct mii_bus *bus) ++{ ++ ar7_device_reset(AR7_RESET_BIT_MDIO); ++ cpmac_write(bus->priv, CPMAC_MDIO_CONTROL, MDIOC_ENABLE | ++ MDIOC_CLKDIV(ar7_cpmac_freq() / 2200000 - 1)); ++ return 0; ++} ++ ++static int mii_irqs[PHY_MAX_ADDR] = { PHY_POLL, }; ++ ++static struct mii_bus *cpmac_mii; ++ ++static int cpmac_config(struct net_device *dev, struct ifmap *map) ++{ ++ if (dev->flags & IFF_UP) ++ return -EBUSY; ++ ++ /* Don't allow changing the I/O address */ ++ if (map->base_addr != dev->base_addr) ++ return -EOPNOTSUPP; ++ ++ /* ignore other fields */ ++ return 0; ++} ++ ++static void cpmac_set_multicast_list(struct net_device *dev) ++{ ++ struct dev_mc_list *iter; ++ int i; ++ u8 tmp; ++ u32 mbp, bit, hash[2] = { 0, }; ++ struct cpmac_priv *priv = netdev_priv(dev); ++ ++ mbp = cpmac_read(priv->regs, CPMAC_MBP); ++ if (dev->flags & IFF_PROMISC) { ++ cpmac_write(priv->regs, CPMAC_MBP, (mbp & ~MBP_PROMISCCHAN(0)) | ++ MBP_RXPROMISC); ++ } else { ++ cpmac_write(priv->regs, CPMAC_MBP, mbp & ~MBP_RXPROMISC); ++ if (dev->flags & IFF_ALLMULTI) { ++ /* enable all multicast mode */ ++ cpmac_write(priv->regs, CPMAC_MAC_HASH_LO, 0xffffffff); ++ cpmac_write(priv->regs, CPMAC_MAC_HASH_HI, 0xffffffff); ++ } else { ++ /* ++ * cpmac uses some strange mac address hashing ++ * (not crc32) ++ */ ++ for (i = 0, iter = dev->mc_list; i < dev->mc_count; ++ i++, iter = iter->next) { ++ bit = 0; ++ tmp = iter->dmi_addr[0]; ++ bit ^= (tmp >> 2) ^ (tmp << 4); ++ tmp = iter->dmi_addr[1]; ++ bit ^= (tmp >> 4) ^ (tmp << 2); ++ tmp = iter->dmi_addr[2]; ++ bit ^= (tmp >> 6) ^ tmp; ++ tmp = iter->dmi_addr[3]; ++ bit ^= (tmp >> 2) ^ (tmp << 4); ++ tmp = iter->dmi_addr[4]; ++ bit ^= (tmp >> 4) ^ (tmp << 2); ++ tmp = iter->dmi_addr[5]; ++ bit ^= (tmp >> 6) ^ tmp; ++ bit &= 0x3f; ++ hash[bit / 32] |= 1 << (bit % 32); ++ } ++ ++ cpmac_write(priv->regs, CPMAC_MAC_HASH_LO, hash[0]); ++ cpmac_write(priv->regs, CPMAC_MAC_HASH_HI, hash[1]); ++ } ++ } ++} ++ ++static struct sk_buff *cpmac_rx_one(struct cpmac_priv *priv, ++ struct cpmac_desc *desc) ++{ ++ struct sk_buff *skb, *result = NULL; ++ ++ if (unlikely(netif_msg_hw(priv))) ++ cpmac_dump_desc(priv->dev, desc); ++ cpmac_write(priv->regs, CPMAC_RX_ACK(0), (u32)desc->mapping); ++ if (unlikely(!desc->datalen)) { ++ if (netif_msg_rx_err(priv) && net_ratelimit()) ++ printk(KERN_WARNING "%s: rx: spurious interrupt\n", ++ priv->dev->name); ++ return NULL; ++ } ++ ++ skb = netdev_alloc_skb(priv->dev, CPMAC_SKB_SIZE); ++ if (likely(skb)) { ++ skb_reserve(skb, 2); ++ skb_put(desc->skb, desc->datalen); ++ desc->skb->protocol = eth_type_trans(desc->skb, priv->dev); ++ desc->skb->ip_summed = CHECKSUM_NONE; ++ priv->dev->stats.rx_packets++; ++ priv->dev->stats.rx_bytes += desc->datalen; ++ result = desc->skb; ++ dma_unmap_single(&priv->dev->dev, desc->data_mapping, ++ CPMAC_SKB_SIZE, DMA_FROM_DEVICE); ++ desc->skb = skb; ++ desc->data_mapping = dma_map_single(&priv->dev->dev, skb->data, ++ CPMAC_SKB_SIZE, ++ DMA_FROM_DEVICE); ++ desc->hw_data = (u32)desc->data_mapping; ++ if (unlikely(netif_msg_pktdata(priv))) { ++ printk(KERN_DEBUG "%s: received packet:\n", ++ priv->dev->name); ++ cpmac_dump_skb(priv->dev, result); ++ } ++ } else { ++ if (netif_msg_rx_err(priv) && net_ratelimit()) ++ printk(KERN_WARNING ++ "%s: low on skbs, dropping packet\n", ++ priv->dev->name); ++ priv->dev->stats.rx_dropped++; ++ } ++ ++ desc->buflen = CPMAC_SKB_SIZE; ++ desc->dataflags = CPMAC_OWN; ++ ++ return result; ++} ++ ++static int cpmac_poll(struct napi_struct *napi, int budget) ++{ ++ struct sk_buff *skb; ++ struct cpmac_desc *desc, *restart; ++ struct cpmac_priv *priv = container_of(napi, struct cpmac_priv, napi); ++ int received = 0, processed = 0; ++ ++ spin_lock(&priv->rx_lock); ++ if (unlikely(!priv->rx_head)) { ++ if (netif_msg_rx_err(priv) && net_ratelimit()) ++ printk(KERN_WARNING "%s: rx: polling, but no queue\n", ++ priv->dev->name); ++ spin_unlock(&priv->rx_lock); ++ netif_rx_complete(napi); ++ return 0; ++ } ++ ++ desc = priv->rx_head; ++ restart = NULL; ++ while (((desc->dataflags & CPMAC_OWN) == 0) && (received < budget)) { ++ processed++; ++ ++ if ((desc->dataflags & CPMAC_EOQ) != 0) { ++ /* The last update to eoq->hw_next didn't happen ++ * soon enough, and the receiver stopped here. ++ *Remember this descriptor so we can restart ++ * the receiver after freeing some space. ++ */ ++ if (unlikely(restart)) { ++ if (netif_msg_rx_err(priv)) ++ printk(KERN_ERR "%s: poll found a" ++ " duplicate EOQ: %p and %p\n", ++ priv->dev->name, restart, desc); ++ goto fatal_error; ++ } ++ ++ restart = desc->next; ++ } ++ ++ skb = cpmac_rx_one(priv, desc); ++ if (likely(skb)) { ++ netif_receive_skb(skb); ++ received++; ++ } ++ desc = desc->next; ++ } ++ ++ if (desc != priv->rx_head) { ++ /* We freed some buffers, but not the whole ring, ++ * add what we did free to the rx list */ ++ desc->prev->hw_next = (u32)0; ++ priv->rx_head->prev->hw_next = priv->rx_head->mapping; ++ } ++ ++ /* Optimization: If we did not actually process an EOQ (perhaps because ++ * of quota limits), check to see if the tail of the queue has EOQ set. ++ * We should immediately restart in that case so that the receiver can ++ * restart and run in parallel with more packet processing. ++ * This lets us handle slightly larger bursts before running ++ * out of ring space (assuming dev->weight < ring_size) */ ++ ++ if (!restart && ++ (priv->rx_head->prev->dataflags & (CPMAC_OWN|CPMAC_EOQ)) ++ == CPMAC_EOQ && ++ (priv->rx_head->dataflags & CPMAC_OWN) != 0) { ++ /* reset EOQ so the poll loop (above) doesn't try to ++ * restart this when it eventually gets to this descriptor. ++ */ ++ priv->rx_head->prev->dataflags &= ~CPMAC_EOQ; ++ restart = priv->rx_head; ++ } ++ ++ if (restart) { ++ priv->dev->stats.rx_errors++; ++ priv->dev->stats.rx_fifo_errors++; ++ if (netif_msg_rx_err(priv) && net_ratelimit()) ++ printk(KERN_WARNING "%s: rx dma ring overrun\n", ++ priv->dev->name); ++ ++ if (unlikely((restart->dataflags & CPMAC_OWN) == 0)) { ++ if (netif_msg_drv(priv)) ++ printk(KERN_ERR "%s: cpmac_poll is trying to " ++ "restart rx from a descriptor that's " ++ "not free: %p\n", ++ priv->dev->name, restart); ++ goto fatal_error; ++ } ++ ++ cpmac_write(priv->regs, CPMAC_RX_PTR(0), restart->mapping); ++ } ++ ++ priv->rx_head = desc; ++ spin_unlock(&priv->rx_lock); ++ if (unlikely(netif_msg_rx_status(priv))) ++ printk(KERN_DEBUG "%s: poll processed %d packets\n", ++ priv->dev->name, received); ++ if (processed == 0) { ++ /* we ran out of packets to read, ++ * revert to interrupt-driven mode */ ++ netif_rx_complete(napi); ++ cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1); ++ return 0; ++ } ++ ++ return 1; ++ ++fatal_error: ++ /* Something went horribly wrong. ++ * Reset hardware to try to recover rather than wedging. */ ++ ++ if (netif_msg_drv(priv)) { ++ printk(KERN_ERR "%s: cpmac_poll is confused. " ++ "Resetting hardware\n", priv->dev->name); ++ cpmac_dump_all_desc(priv->dev); ++ printk(KERN_DEBUG "%s: RX_PTR(0)=0x%08x RX_ACK(0)=0x%08x\n", ++ priv->dev->name, ++ cpmac_read(priv->regs, CPMAC_RX_PTR(0)), ++ cpmac_read(priv->regs, CPMAC_RX_ACK(0))); ++ } ++ ++ spin_unlock(&priv->rx_lock); ++ netif_rx_complete(napi); ++ netif_tx_stop_all_queues(priv->dev); ++ napi_disable(&priv->napi); ++ ++ atomic_inc(&priv->reset_pending); ++ cpmac_hw_stop(priv->dev); ++ if (!schedule_work(&priv->reset_work)) ++ atomic_dec(&priv->reset_pending); ++ return 0; ++ ++} ++ ++static int cpmac_start_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ int queue, len; ++ struct cpmac_desc *desc; ++ struct cpmac_priv *priv = netdev_priv(dev); ++ ++ if (unlikely(atomic_read(&priv->reset_pending))) ++ return NETDEV_TX_BUSY; ++ ++ if (unlikely(skb_padto(skb, ETH_ZLEN))) ++ return NETDEV_TX_OK; ++ ++ len = max(skb->len, ETH_ZLEN); ++ queue = skb_get_queue_mapping(skb); ++ netif_stop_subqueue(dev, queue); ++ ++ desc = &priv->desc_ring[queue]; ++ if (unlikely(desc->dataflags & CPMAC_OWN)) { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ printk(KERN_WARNING "%s: tx dma ring full\n", ++ dev->name); ++ return NETDEV_TX_BUSY; ++ } ++ ++ spin_lock(&priv->lock); ++ dev->trans_start = jiffies; ++ spin_unlock(&priv->lock); ++ desc->dataflags = CPMAC_SOP | CPMAC_EOP | CPMAC_OWN; ++ desc->skb = skb; ++ desc->data_mapping = dma_map_single(&dev->dev, skb->data, len, ++ DMA_TO_DEVICE); ++ desc->hw_data = (u32)desc->data_mapping; ++ desc->datalen = len; ++ desc->buflen = len; ++ if (unlikely(netif_msg_tx_queued(priv))) ++ printk(KERN_DEBUG "%s: sending 0x%p, len=%d\n", dev->name, skb, ++ skb->len); ++ if (unlikely(netif_msg_hw(priv))) ++ cpmac_dump_desc(dev, desc); ++ if (unlikely(netif_msg_pktdata(priv))) ++ cpmac_dump_skb(dev, skb); ++ cpmac_write(priv->regs, CPMAC_TX_PTR(queue), (u32)desc->mapping); ++ ++ return NETDEV_TX_OK; ++} ++ ++static void cpmac_end_xmit(struct net_device *dev, int queue) ++{ ++ struct cpmac_desc *desc; ++ struct cpmac_priv *priv = netdev_priv(dev); ++ ++ desc = &priv->desc_ring[queue]; ++ cpmac_write(priv->regs, CPMAC_TX_ACK(queue), (u32)desc->mapping); ++ if (likely(desc->skb)) { ++ spin_lock(&priv->lock); ++ dev->stats.tx_packets++; ++ dev->stats.tx_bytes += desc->skb->len; ++ spin_unlock(&priv->lock); ++ dma_unmap_single(&dev->dev, desc->data_mapping, desc->skb->len, ++ DMA_TO_DEVICE); ++ ++ if (unlikely(netif_msg_tx_done(priv))) ++ printk(KERN_DEBUG "%s: sent 0x%p, len=%d\n", dev->name, ++ desc->skb, desc->skb->len); ++ ++ dev_kfree_skb_irq(desc->skb); ++ desc->skb = NULL; ++ if (netif_subqueue_stopped(dev, queue)) ++ netif_wake_subqueue(dev, queue); ++ } else { ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ printk(KERN_WARNING ++ "%s: end_xmit: spurious interrupt\n", dev->name); ++ if (netif_subqueue_stopped(dev, queue)) ++ netif_wake_subqueue(dev, queue); ++ } ++} ++ ++static void cpmac_hw_stop(struct net_device *dev) ++{ ++ int i; ++ struct cpmac_priv *priv = netdev_priv(dev); ++ struct plat_cpmac_data *pdata = priv->pdev->dev.platform_data; ++ ++ ar7_device_reset(pdata->reset_bit); ++ cpmac_write(priv->regs, CPMAC_RX_CONTROL, ++ cpmac_read(priv->regs, CPMAC_RX_CONTROL) & ~1); ++ cpmac_write(priv->regs, CPMAC_TX_CONTROL, ++ cpmac_read(priv->regs, CPMAC_TX_CONTROL) & ~1); ++ for (i = 0; i < 8; i++) { ++ cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0); ++ cpmac_write(priv->regs, CPMAC_RX_PTR(i), 0); ++ } ++ cpmac_write(priv->regs, CPMAC_UNICAST_CLEAR, 0xff); ++ cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 0xff); ++ cpmac_write(priv->regs, CPMAC_TX_INT_CLEAR, 0xff); ++ cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff); ++ cpmac_write(priv->regs, CPMAC_MAC_CONTROL, ++ cpmac_read(priv->regs, CPMAC_MAC_CONTROL) & ~MAC_MII); ++} ++ ++static void cpmac_hw_start(struct net_device *dev) ++{ ++ int i; ++ struct cpmac_priv *priv = netdev_priv(dev); ++ struct plat_cpmac_data *pdata = priv->pdev->dev.platform_data; ++ ++ ar7_device_reset(pdata->reset_bit); ++ for (i = 0; i < 8; i++) { ++ cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0); ++ cpmac_write(priv->regs, CPMAC_RX_PTR(i), 0); ++ } ++ cpmac_write(priv->regs, CPMAC_RX_PTR(0), priv->rx_head->mapping); ++ ++ cpmac_write(priv->regs, CPMAC_MBP, MBP_RXSHORT | MBP_RXBCAST | ++ MBP_RXMCAST); ++ cpmac_write(priv->regs, CPMAC_BUFFER_OFFSET, 0); ++ for (i = 0; i < 8; i++) ++ cpmac_write(priv->regs, CPMAC_MAC_ADDR_LO(i), dev->dev_addr[5]); ++ cpmac_write(priv->regs, CPMAC_MAC_ADDR_MID, dev->dev_addr[4]); ++ cpmac_write(priv->regs, CPMAC_MAC_ADDR_HI, dev->dev_addr[0] | ++ (dev->dev_addr[1] << 8) | (dev->dev_addr[2] << 16) | ++ (dev->dev_addr[3] << 24)); ++ cpmac_write(priv->regs, CPMAC_MAX_LENGTH, CPMAC_SKB_SIZE); ++ cpmac_write(priv->regs, CPMAC_UNICAST_CLEAR, 0xff); ++ cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 0xff); ++ cpmac_write(priv->regs, CPMAC_TX_INT_CLEAR, 0xff); ++ cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff); ++ cpmac_write(priv->regs, CPMAC_UNICAST_ENABLE, 1); ++ cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1); ++ cpmac_write(priv->regs, CPMAC_TX_INT_ENABLE, 0xff); ++ cpmac_write(priv->regs, CPMAC_MAC_INT_ENABLE, 3); ++ ++ cpmac_write(priv->regs, CPMAC_RX_CONTROL, ++ cpmac_read(priv->regs, CPMAC_RX_CONTROL) | 1); ++ cpmac_write(priv->regs, CPMAC_TX_CONTROL, ++ cpmac_read(priv->regs, CPMAC_TX_CONTROL) | 1); ++ cpmac_write(priv->regs, CPMAC_MAC_CONTROL, ++ cpmac_read(priv->regs, CPMAC_MAC_CONTROL) | MAC_MII | ++ MAC_FDX); ++} ++ ++static void cpmac_clear_rx(struct net_device *dev) ++{ ++ struct cpmac_priv *priv = netdev_priv(dev); ++ struct cpmac_desc *desc; ++ int i; ++ if (unlikely(!priv->rx_head)) ++ return; ++ desc = priv->rx_head; ++ for (i = 0; i < priv->ring_size; i++) { ++ if ((desc->dataflags & CPMAC_OWN) == 0) { ++ if (netif_msg_rx_err(priv) && net_ratelimit()) ++ printk(KERN_WARNING "%s: packet dropped\n", ++ dev->name); ++ if (unlikely(netif_msg_hw(priv))) ++ cpmac_dump_desc(dev, desc); ++ desc->dataflags = CPMAC_OWN; ++ dev->stats.rx_dropped++; ++ } ++ desc->hw_next = desc->next->mapping; ++ desc = desc->next; ++ } ++ priv->rx_head->prev->hw_next = 0; ++} ++ ++static void cpmac_clear_tx(struct net_device *dev) ++{ ++ struct cpmac_priv *priv = netdev_priv(dev); ++ int i; ++ if (unlikely(!priv->desc_ring)) ++ return; ++ for (i = 0; i < CPMAC_QUEUES; i++) { ++ priv->desc_ring[i].dataflags = 0; ++ if (priv->desc_ring[i].skb) { ++ dev_kfree_skb_any(priv->desc_ring[i].skb); ++ priv->desc_ring[i].skb = NULL; ++ } ++ } ++} ++ ++static void cpmac_hw_error(struct work_struct *work) ++{ ++ int i; ++ struct cpmac_priv *priv = ++ container_of(work, struct cpmac_priv, reset_work); ++ ++ spin_lock(&priv->rx_lock); ++ cpmac_clear_rx(priv->dev); ++ spin_unlock(&priv->rx_lock); ++ cpmac_clear_tx(priv->dev); ++ cpmac_hw_start(priv->dev); ++ barrier(); ++ atomic_dec(&priv->reset_pending); ++ ++ netif_tx_wake_all_queues(priv->dev); ++ cpmac_write(priv->regs, CPMAC_MAC_INT_ENABLE, 3); ++} ++ ++static void cpmac_check_status(struct net_device *dev) ++{ ++ struct cpmac_priv *priv = netdev_priv(dev); ++ ++ u32 macstatus = cpmac_read(priv->regs, CPMAC_MAC_STATUS); ++ int rx_channel = (macstatus >> 8) & 7; ++ int rx_code = (macstatus >> 12) & 15; ++ int tx_channel = (macstatus >> 16) & 7; ++ int tx_code = (macstatus >> 20) & 15; ++ ++ if (rx_code || tx_code) { ++ if (netif_msg_drv(priv) && net_ratelimit()) { ++ /* Can't find any documentation on what these ++ *error codes actually are. So just log them and hope.. ++ */ ++ if (rx_code) ++ printk(KERN_WARNING "%s: host error %d on rx " ++ "channel %d (macstatus %08x), resetting\n", ++ dev->name, rx_code, rx_channel, macstatus); ++ if (tx_code) ++ printk(KERN_WARNING "%s: host error %d on tx " ++ "channel %d (macstatus %08x), resetting\n", ++ dev->name, tx_code, tx_channel, macstatus); ++ } ++ ++ netif_tx_stop_all_queues(dev); ++ cpmac_hw_stop(dev); ++ if (schedule_work(&priv->reset_work)) ++ atomic_inc(&priv->reset_pending); ++ if (unlikely(netif_msg_hw(priv))) ++ cpmac_dump_regs(dev); ++ } ++ cpmac_write(priv->regs, CPMAC_MAC_INT_CLEAR, 0xff); ++} ++ ++static irqreturn_t cpmac_irq(int irq, void *dev_id) ++{ ++ struct net_device *dev = dev_id; ++ struct cpmac_priv *priv; ++ int queue; ++ u32 status; ++ ++ priv = netdev_priv(dev); ++ ++ status = cpmac_read(priv->regs, CPMAC_MAC_INT_VECTOR); ++ ++ if (unlikely(netif_msg_intr(priv))) ++ printk(KERN_DEBUG "%s: interrupt status: 0x%08x\n", dev->name, ++ status); ++ ++ if (status & MAC_INT_TX) ++ cpmac_end_xmit(dev, (status & 7)); ++ ++ if (status & MAC_INT_RX) { ++ queue = (status >> 8) & 7; ++ if (netif_rx_schedule_prep(&priv->napi)) { ++ cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 1 << queue); ++ __netif_rx_schedule(&priv->napi); ++ } ++ } ++ ++ cpmac_write(priv->regs, CPMAC_MAC_EOI_VECTOR, 0); ++ ++ if (unlikely(status & (MAC_INT_HOST | MAC_INT_STATUS))) ++ cpmac_check_status(dev); ++ ++ return IRQ_HANDLED; ++} ++ ++static void cpmac_tx_timeout(struct net_device *dev) ++{ ++ int i; ++ struct cpmac_priv *priv = netdev_priv(dev); ++ ++ spin_lock(&priv->lock); ++ dev->stats.tx_errors++; ++ spin_unlock(&priv->lock); ++ if (netif_msg_tx_err(priv) && net_ratelimit()) ++ printk(KERN_WARNING "%s: transmit timeout\n", dev->name); ++ ++ atomic_inc(&priv->reset_pending); ++ barrier(); ++ cpmac_clear_tx(dev); ++ barrier(); ++ atomic_dec(&priv->reset_pending); ++ ++ netif_tx_wake_all_queues(priv->dev); ++} ++ ++static int cpmac_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ struct cpmac_priv *priv = netdev_priv(dev); ++ if (!(netif_running(dev))) ++ return -EINVAL; ++ if (!priv->phy) ++ return -EINVAL; ++ if ((cmd == SIOCGMIIPHY) || (cmd == SIOCGMIIREG) || ++ (cmd == SIOCSMIIREG)) ++ return phy_mii_ioctl(priv->phy, if_mii(ifr), cmd); ++ ++ return -EOPNOTSUPP; ++} ++ ++static int cpmac_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) ++{ ++ struct cpmac_priv *priv = netdev_priv(dev); ++ ++ if (priv->phy) ++ return phy_ethtool_gset(priv->phy, cmd); ++ ++ return -EINVAL; ++} ++ ++static int cpmac_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) ++{ ++ struct cpmac_priv *priv = netdev_priv(dev); ++ ++ if (!capable(CAP_NET_ADMIN)) ++ return -EPERM; ++ ++ if (priv->phy) ++ return phy_ethtool_sset(priv->phy, cmd); ++ ++ return -EINVAL; ++} ++ ++static void cpmac_get_ringparam(struct net_device *dev, struct ethtool_ringparam* ring) ++{ ++ struct cpmac_priv *priv = netdev_priv(dev); ++ ++ ring->rx_max_pending = 1024; ++ ring->rx_mini_max_pending = 1; ++ ring->rx_jumbo_max_pending = 1; ++ ring->tx_max_pending = 1; ++ ++ ring->rx_pending = priv->ring_size; ++ ring->rx_mini_pending = 1; ++ ring->rx_jumbo_pending = 1; ++ ring->tx_pending = 1; ++} ++ ++static int cpmac_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ring) ++{ ++ struct cpmac_priv *priv = netdev_priv(dev); ++ ++ if (netif_running(dev)) ++ return -EBUSY; ++ priv->ring_size = ring->rx_pending; ++ return 0; ++} ++ ++static void cpmac_get_drvinfo(struct net_device *dev, ++ struct ethtool_drvinfo *info) ++{ ++ strcpy(info->driver, "cpmac"); ++ strcpy(info->version, CPMAC_VERSION); ++ info->fw_version[0] = '\0'; ++ sprintf(info->bus_info, "%s", "cpmac"); ++ info->regdump_len = 0; ++} ++ ++static const struct ethtool_ops cpmac_ethtool_ops = { ++ .get_settings = cpmac_get_settings, ++ .set_settings = cpmac_set_settings, ++ .get_drvinfo = cpmac_get_drvinfo, ++ .get_link = ethtool_op_get_link, ++ .get_ringparam = cpmac_get_ringparam, ++ .set_ringparam = cpmac_set_ringparam, ++}; ++ ++static void cpmac_adjust_link(struct net_device *dev) ++{ ++ struct cpmac_priv *priv = netdev_priv(dev); ++ int new_state = 0; ++ ++ spin_lock(&priv->lock); ++ if (priv->phy->link) { ++ netif_tx_start_all_queues(dev); ++ if (priv->phy->duplex != priv->oldduplex) { ++ new_state = 1; ++ priv->oldduplex = priv->phy->duplex; ++ } ++ ++ if (priv->phy->speed != priv->oldspeed) { ++ new_state = 1; ++ priv->oldspeed = priv->phy->speed; ++ } ++ ++ if (!priv->oldlink) { ++ new_state = 1; ++ priv->oldlink = 1; ++ } ++ } else if (priv->oldlink) { ++ new_state = 1; ++ priv->oldlink = 0; ++ priv->oldspeed = 0; ++ priv->oldduplex = -1; ++ } ++ ++ if (new_state && netif_msg_link(priv) && net_ratelimit()) ++ phy_print_status(priv->phy); ++ ++ spin_unlock(&priv->lock); ++} ++ ++static int cpmac_open(struct net_device *dev) ++{ ++ int i, size, res; ++ struct cpmac_priv *priv = netdev_priv(dev); ++ struct resource *mem; ++ struct cpmac_desc *desc; ++ struct sk_buff *skb; ++ ++ mem = platform_get_resource_byname(priv->pdev, IORESOURCE_MEM, "regs"); ++ if (!request_mem_region(mem->start, mem->end - mem->start, dev->name)) { ++ if (netif_msg_drv(priv)) ++ printk(KERN_ERR "%s: failed to request registers\n", ++ dev->name); ++ res = -ENXIO; ++ goto fail_reserve; ++ } ++ ++ priv->regs = ioremap(mem->start, mem->end - mem->start); ++ if (!priv->regs) { ++ if (netif_msg_drv(priv)) ++ printk(KERN_ERR "%s: failed to remap registers\n", ++ dev->name); ++ res = -ENXIO; ++ goto fail_remap; ++ } ++ ++ size = priv->ring_size + CPMAC_QUEUES; ++ priv->desc_ring = dma_alloc_coherent(&dev->dev, ++ sizeof(struct cpmac_desc) * size, ++ &priv->dma_ring, ++ GFP_KERNEL); ++ if (!priv->desc_ring) { ++ res = -ENOMEM; ++ goto fail_alloc; ++ } ++ ++ for (i = 0; i < size; i++) ++ priv->desc_ring[i].mapping = priv->dma_ring + sizeof(*desc) * i; ++ ++ priv->rx_head = &priv->desc_ring[CPMAC_QUEUES]; ++ for (i = 0, desc = priv->rx_head; i < priv->ring_size; i++, desc++) { ++ skb = netdev_alloc_skb(dev, CPMAC_SKB_SIZE); ++ if (unlikely(!skb)) { ++ res = -ENOMEM; ++ goto fail_desc; ++ } ++ skb_reserve(skb, 2); ++ desc->skb = skb; ++ desc->data_mapping = dma_map_single(&dev->dev, skb->data, ++ CPMAC_SKB_SIZE, ++ DMA_FROM_DEVICE); ++ desc->hw_data = (u32)desc->data_mapping; ++ desc->buflen = CPMAC_SKB_SIZE; ++ desc->dataflags = CPMAC_OWN; ++ desc->next = &priv->rx_head[(i + 1) % priv->ring_size]; ++ desc->next->prev = desc; ++ desc->hw_next = (u32)desc->next->mapping; ++ } ++ ++ priv->rx_head->prev->hw_next = (u32)0; ++ ++ if ((res = request_irq(dev->irq, cpmac_irq, IRQF_SHARED, ++ dev->name, dev))) { ++ if (netif_msg_drv(priv)) ++ printk(KERN_ERR "%s: failed to obtain irq\n", ++ dev->name); ++ goto fail_irq; ++ } ++ ++ atomic_set(&priv->reset_pending, 0); ++ INIT_WORK(&priv->reset_work, cpmac_hw_error); ++ cpmac_hw_start(dev); ++ ++ napi_enable(&priv->napi); ++ priv->phy->state = PHY_CHANGELINK; ++ phy_start(priv->phy); ++ ++ return 0; ++ ++fail_irq: ++fail_desc: ++ for (i = 0; i < priv->ring_size; i++) { ++ if (priv->rx_head[i].skb) { ++ dma_unmap_single(&dev->dev, ++ priv->rx_head[i].data_mapping, ++ CPMAC_SKB_SIZE, ++ DMA_FROM_DEVICE); ++ kfree_skb(priv->rx_head[i].skb); ++ } ++ } ++fail_alloc: ++ kfree(priv->desc_ring); ++ iounmap(priv->regs); ++ ++fail_remap: ++ release_mem_region(mem->start, mem->end - mem->start); ++ ++fail_reserve: ++ return res; ++} ++ ++static int cpmac_stop(struct net_device *dev) ++{ ++ int i; ++ struct cpmac_priv *priv = netdev_priv(dev); ++ struct resource *mem; ++ ++ netif_tx_stop_all_queues(dev); ++ ++ cancel_work_sync(&priv->reset_work); ++ napi_disable(&priv->napi); ++ phy_stop(priv->phy); ++ ++ cpmac_hw_stop(dev); ++ ++ for (i = 0; i < 8; i++) ++ cpmac_write(priv->regs, CPMAC_TX_PTR(i), 0); ++ cpmac_write(priv->regs, CPMAC_RX_PTR(0), 0); ++ cpmac_write(priv->regs, CPMAC_MBP, 0); ++ ++ free_irq(dev->irq, dev); ++ iounmap(priv->regs); ++ mem = platform_get_resource_byname(priv->pdev, IORESOURCE_MEM, "regs"); ++ release_mem_region(mem->start, mem->end - mem->start); ++ priv->rx_head = &priv->desc_ring[CPMAC_QUEUES]; ++ for (i = 0; i < priv->ring_size; i++) { ++ if (priv->rx_head[i].skb) { ++ dma_unmap_single(&dev->dev, ++ priv->rx_head[i].data_mapping, ++ CPMAC_SKB_SIZE, ++ DMA_FROM_DEVICE); ++ kfree_skb(priv->rx_head[i].skb); ++ } ++ } ++ ++ dma_free_coherent(&dev->dev, sizeof(struct cpmac_desc) * ++ (CPMAC_QUEUES + priv->ring_size), ++ priv->desc_ring, priv->dma_ring); ++ return 0; ++} ++ ++static int external_switch; ++ ++static int __devinit cpmac_probe(struct platform_device *pdev) ++{ ++ int rc, phy_id, i; ++ char *mdio_bus_id = "0"; ++ struct resource *mem; ++ struct cpmac_priv *priv; ++ struct net_device *dev; ++ struct plat_cpmac_data *pdata; ++ ++ pdata = pdev->dev.platform_data; ++ ++ for (phy_id = 0; phy_id < PHY_MAX_ADDR; phy_id++) { ++ if (!(pdata->phy_mask & (1 << phy_id))) ++ continue; ++ if (!cpmac_mii->phy_map[phy_id]) ++ continue; ++ break; ++ } ++ ++ if (phy_id == PHY_MAX_ADDR) { ++ if (external_switch || dumb_switch) { ++ mdio_bus_id = 0; /* fixed phys bus */ ++ phy_id = pdev->id; ++ } else { ++ dev_err(&pdev->dev, "no PHY present\n"); ++ return -ENODEV; ++ } ++ } ++ ++ dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES); ++ ++ if (!dev) { ++ printk(KERN_ERR "cpmac: Unable to allocate net_device\n"); ++ return -ENOMEM; ++ } ++ ++ platform_set_drvdata(pdev, dev); ++ priv = netdev_priv(dev); ++ ++ priv->pdev = pdev; ++ mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); ++ if (!mem) { ++ rc = -ENODEV; ++ goto fail; ++ } ++ ++ dev->irq = platform_get_irq_byname(pdev, "irq"); ++ ++ dev->open = cpmac_open; ++ dev->stop = cpmac_stop; ++ dev->set_config = cpmac_config; ++ dev->hard_start_xmit = cpmac_start_xmit; ++ dev->do_ioctl = cpmac_ioctl; ++ dev->set_multicast_list = cpmac_set_multicast_list; ++ dev->tx_timeout = cpmac_tx_timeout; ++ dev->ethtool_ops = &cpmac_ethtool_ops; ++ ++ netif_napi_add(dev, &priv->napi, cpmac_poll, 64); ++ ++ spin_lock_init(&priv->lock); ++ spin_lock_init(&priv->rx_lock); ++ priv->dev = dev; ++ priv->ring_size = 64; ++ priv->msg_enable = netif_msg_init(debug_level, 0xff); ++ memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); ++ ++ priv->phy = phy_connect(dev, cpmac_mii->phy_map[phy_id]->dev.bus_id, ++ &cpmac_adjust_link, 0, PHY_INTERFACE_MODE_MII); ++ if (IS_ERR(priv->phy)) { ++ if (netif_msg_drv(priv)) ++ printk(KERN_ERR "%s: Could not attach to PHY\n", ++ dev->name); ++ return PTR_ERR(priv->phy); ++ } ++ ++ if ((rc = register_netdev(dev))) { ++ printk(KERN_ERR "cpmac: error %i registering device %s\n", rc, ++ dev->name); ++ goto fail; ++ } ++ ++ if (netif_msg_probe(priv)) { ++ printk(KERN_INFO ++ "cpmac: device %s (regs: %p, irq: %d, phy: %s, " ++ "mac: %pM)\n", dev->name, (void *)mem->start, dev->irq, ++ priv->phy_name, dev->dev_addr); ++ } ++ return 0; ++ ++fail: ++ free_netdev(dev); ++ return rc; ++} ++ ++static int __devexit cpmac_remove(struct platform_device *pdev) ++{ ++ struct net_device *dev = platform_get_drvdata(pdev); ++ unregister_netdev(dev); ++ free_netdev(dev); ++ return 0; ++} ++ ++static struct platform_driver cpmac_driver = { ++ .driver.name = "cpmac", ++ .driver.owner = THIS_MODULE, ++ .probe = cpmac_probe, ++ .remove = __devexit_p(cpmac_remove), ++}; ++ ++int __devinit cpmac_init(void) ++{ ++ u32 mask; ++ int i, res; ++ ++ cpmac_mii = mdiobus_alloc(); ++ if (cpmac_mii == NULL) ++ return -ENOMEM; ++ ++ cpmac_mii->name = "cpmac-mii"; ++ cpmac_mii->read = cpmac_mdio_read; ++ cpmac_mii->write = cpmac_mdio_write; ++ cpmac_mii->reset = cpmac_mdio_reset; ++ cpmac_mii->irq = mii_irqs; ++ ++ cpmac_mii->priv = ioremap(AR7_REGS_MDIO, 256); ++ ++ if (!cpmac_mii->priv) { ++ printk(KERN_ERR "Can't ioremap mdio registers\n"); ++ res = -ENXIO; ++ goto fail_alloc; ++ } ++ ++#warning FIXME: unhardcode gpio&reset bits ++ ar7_gpio_disable(26); ++ ar7_gpio_disable(27); ++ ar7_device_reset(AR7_RESET_BIT_CPMAC_LO); ++ ar7_device_reset(AR7_RESET_BIT_CPMAC_HI); ++ ar7_device_reset(AR7_RESET_BIT_EPHY); ++ ++ cpmac_mii->reset(cpmac_mii); ++ ++ for (i = 0; i < 300000; i++) ++ if ((mask = cpmac_read(cpmac_mii->priv, CPMAC_MDIO_ALIVE))) ++ break; ++ else ++ cpu_relax(); ++ ++ mask &= 0x7fffffff; ++ if (mask & (mask - 1)) { ++ external_switch = 1; ++ mask = 0; ++ } ++ ++ cpmac_mii->phy_mask = ~(mask | 0x80000000); ++ snprintf(cpmac_mii->id, MII_BUS_ID_SIZE, "0"); ++ ++ res = mdiobus_register(cpmac_mii); ++ if (res) ++ goto fail_mii; ++ ++ res = platform_driver_register(&cpmac_driver); ++ if (res) ++ goto fail_cpmac; ++ ++ return 0; ++ ++fail_cpmac: ++ mdiobus_unregister(cpmac_mii); ++ ++fail_mii: ++ iounmap(cpmac_mii->priv); ++ ++fail_alloc: ++ mdiobus_free(cpmac_mii); ++ ++ return res; ++} ++ ++void __devexit cpmac_exit(void) ++{ ++ platform_driver_unregister(&cpmac_driver); ++ mdiobus_unregister(cpmac_mii); ++ mdiobus_free(cpmac_mii); ++ iounmap(cpmac_mii->priv); ++} ++ ++module_init(cpmac_init); ++module_exit(cpmac_exit); +diff -Nur linux-2.6.29.1.orig/drivers/net/Kconfig linux-2.6.29.1/drivers/net/Kconfig +--- linux-2.6.29.1.orig/drivers/net/Kconfig 2009-04-02 22:55:27.000000000 +0200 ++++ linux-2.6.29.1/drivers/net/Kconfig 2009-05-31 20:04:03.000000000 +0200 +@@ -1741,7 +1741,7 @@ + + config CPMAC + tristate "TI AR7 CPMAC Ethernet support (EXPERIMENTAL)" +- depends on NET_ETHERNET && EXPERIMENTAL && AR7 && BROKEN ++ depends on NET_ETHERNET && EXPERIMENTAL && AR7 + select PHYLIB + help + TI AR7 CPMAC Ethernet support +diff -Nur linux-2.6.29.1.orig/drivers/vlynq/Kconfig linux-2.6.29.1/drivers/vlynq/Kconfig +--- linux-2.6.29.1.orig/drivers/vlynq/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/drivers/vlynq/Kconfig 2009-05-31 19:50:05.000000000 +0200 +@@ -0,0 +1,13 @@ ++menu "TI VLYNQ" ++ ++config VLYNQ ++ bool "TI VLYNQ bus support" ++ depends on AR7 && EXPERIMENTAL ++ help ++ Support for the TI VLYNQ bus ++ ++ The module will be called vlynq ++ ++ If unsure, say N ++ ++endmenu +diff -Nur linux-2.6.29.1.orig/drivers/vlynq/Makefile linux-2.6.29.1/drivers/vlynq/Makefile +--- linux-2.6.29.1.orig/drivers/vlynq/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/drivers/vlynq/Makefile 2009-05-31 19:50:06.000000000 +0200 +@@ -0,0 +1,5 @@ ++# ++# Makefile for kernel vlynq drivers ++# ++ ++obj-$(CONFIG_VLYNQ) += vlynq.o +diff -Nur linux-2.6.29.1.orig/drivers/vlynq/vlynq.c linux-2.6.29.1/drivers/vlynq/vlynq.c +--- linux-2.6.29.1.orig/drivers/vlynq/vlynq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/drivers/vlynq/vlynq.c 2009-05-31 19:50:06.000000000 +0200 +@@ -0,0 +1,783 @@ ++/* ++ * Copyright (C) 2006, 2007 Eugene Konev <ejka@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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#include <linux/init.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/string.h> ++#include <linux/device.h> ++#include <linux/module.h> ++#include <linux/errno.h> ++#include <linux/platform_device.h> ++#include <linux/interrupt.h> ++#include <linux/device.h> ++#include <linux/delay.h> ++#include <linux/io.h> ++ ++#include <linux/vlynq.h> ++ ++#define VLYNQ_CTRL_PM_ENABLE 0x80000000 ++#define VLYNQ_CTRL_CLOCK_INT 0x00008000 ++#define VLYNQ_CTRL_CLOCK_DIV(x) (((x) & 7) << 16) ++#define VLYNQ_CTRL_INT_LOCAL 0x00004000 ++#define VLYNQ_CTRL_INT_ENABLE 0x00002000 ++#define VLYNQ_CTRL_INT_VECTOR(x) (((x) & 0x1f) << 8) ++#define VLYNQ_CTRL_INT2CFG 0x00000080 ++#define VLYNQ_CTRL_RESET 0x00000001 ++ ++#define VLYNQ_CTRL_CLOCK_MASK (0x7 << 16) ++ ++#define VLYNQ_INT_OFFSET 0x00000014 ++#define VLYNQ_REMOTE_OFFSET 0x00000080 ++ ++#define VLYNQ_STATUS_LINK 0x00000001 ++#define VLYNQ_STATUS_LERROR 0x00000080 ++#define VLYNQ_STATUS_RERROR 0x00000100 ++ ++#define VINT_ENABLE 0x00000100 ++#define VINT_TYPE_EDGE 0x00000080 ++#define VINT_LEVEL_LOW 0x00000040 ++#define VINT_VECTOR(x) ((x) & 0x1f) ++#define VINT_OFFSET(irq) (8 * ((irq) % 4)) ++ ++#define VLYNQ_AUTONEGO_V2 0x00010000 ++ ++struct vlynq_regs { ++ u32 revision; ++ u32 control; ++ u32 status; ++ u32 int_prio; ++ u32 int_status; ++ u32 int_pending; ++ u32 int_ptr; ++ u32 tx_offset; ++ struct vlynq_mapping rx_mapping[4]; ++ u32 chip; ++ u32 autonego; ++ u32 unused[6]; ++ u32 int_device[8]; ++}; ++ ++#define vlynq_reg_read(reg) readl(&(reg)) ++#define vlynq_reg_write(reg, val) writel(val, &(reg)) ++ ++static int __vlynq_enable_device(struct vlynq_device *dev); ++ ++#ifdef VLYNQ_DEBUG ++static void vlynq_dump_regs(struct vlynq_device *dev) ++{ ++ int i; ++ printk(KERN_DEBUG "VLYNQ local=%p remote=%p\n", ++ dev->local, dev->remote); ++ for (i = 0; i < 32; i++) { ++ printk(KERN_DEBUG "VLYNQ: local %d: %08x\n", ++ i + 1, ((u32 *)dev->local)[i]); ++ printk(KERN_DEBUG "VLYNQ: remote %d: %08x\n", ++ i + 1, ((u32 *)dev->remote)[i]); ++ } ++} ++ ++static void vlynq_dump_mem(u32 *base, int count) ++{ ++ int i; ++ for (i = 0; i < (count + 3) / 4; i++) { ++ if (i % 4 == 0) printk(KERN_DEBUG "\nMEM[0x%04x]:", i * 4); ++ printk(KERN_DEBUG " 0x%08x", *(base + i)); ++ } ++ printk(KERN_DEBUG "\n"); ++} ++#endif ++ ++int vlynq_linked(struct vlynq_device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < 100; i++) ++ if (vlynq_reg_read(dev->local->status) & VLYNQ_STATUS_LINK) ++ return 1; ++ else ++ cpu_relax(); ++ ++ return 0; ++} ++ ++static void vlynq_reset(struct vlynq_device *dev) ++{ ++ vlynq_reg_write(dev->local->control, ++ vlynq_reg_read(dev->local->control) | ++ VLYNQ_CTRL_RESET); ++ ++ /* Wait for the devices to finish resetting */ ++ msleep(5); ++ ++ /* Remove reset bit */ ++ vlynq_reg_write(dev->local->control, ++ vlynq_reg_read(dev->local->control) & ++ ~VLYNQ_CTRL_RESET); ++ ++ /* Give some time for the devices to settle */ ++ msleep(5); ++} ++ ++static void vlynq_irq_unmask(unsigned int irq) ++{ ++ u32 val; ++ struct vlynq_device *dev = get_irq_chip_data(irq); ++ int virq; ++ ++ BUG_ON(!dev); ++ virq = irq - dev->irq_start; ++ val = vlynq_reg_read(dev->remote->int_device[virq >> 2]); ++ val |= (VINT_ENABLE | virq) << VINT_OFFSET(virq); ++ vlynq_reg_write(dev->remote->int_device[virq >> 2], val); ++} ++ ++static void vlynq_irq_mask(unsigned int irq) ++{ ++ u32 val; ++ struct vlynq_device *dev = get_irq_chip_data(irq); ++ int virq; ++ ++ BUG_ON(!dev); ++ virq = irq - dev->irq_start; ++ val = vlynq_reg_read(dev->remote->int_device[virq >> 2]); ++ val &= ~(VINT_ENABLE << VINT_OFFSET(virq)); ++ vlynq_reg_write(dev->remote->int_device[virq >> 2], val); ++} ++ ++static int vlynq_irq_type(unsigned int irq, unsigned int flow_type) ++{ ++ u32 val; ++ struct vlynq_device *dev = get_irq_chip_data(irq); ++ int virq; ++ ++ BUG_ON(!dev); ++ virq = irq - dev->irq_start; ++ val = vlynq_reg_read(dev->remote->int_device[virq >> 2]); ++ switch (flow_type & IRQ_TYPE_SENSE_MASK) { ++ case IRQ_TYPE_EDGE_RISING: ++ case IRQ_TYPE_EDGE_FALLING: ++ case IRQ_TYPE_EDGE_BOTH: ++ val |= VINT_TYPE_EDGE << VINT_OFFSET(virq); ++ val &= ~(VINT_LEVEL_LOW << VINT_OFFSET(virq)); ++ break; ++ case IRQ_TYPE_LEVEL_HIGH: ++ val &= ~(VINT_TYPE_EDGE << VINT_OFFSET(virq)); ++ val &= ~(VINT_LEVEL_LOW << VINT_OFFSET(virq)); ++ break; ++ case IRQ_TYPE_LEVEL_LOW: ++ val &= ~(VINT_TYPE_EDGE << VINT_OFFSET(virq)); ++ val |= VINT_LEVEL_LOW << VINT_OFFSET(virq); ++ break; ++ default: ++ return -EINVAL; ++ } ++ vlynq_reg_write(dev->remote->int_device[virq >> 2], val); ++ return 0; ++} ++ ++static void vlynq_local_ack(unsigned int irq) ++{ ++ struct vlynq_device *dev = get_irq_chip_data(irq); ++ u32 status = vlynq_reg_read(dev->local->status); ++ if (printk_ratelimit()) ++ printk(KERN_DEBUG "%s: local status: 0x%08x\n", ++ dev->dev.bus_id, status); ++ vlynq_reg_write(dev->local->status, status); ++} ++ ++static void vlynq_remote_ack(unsigned int irq) ++{ ++ struct vlynq_device *dev = get_irq_chip_data(irq); ++ u32 status = vlynq_reg_read(dev->remote->status); ++ if (printk_ratelimit()) ++ printk(KERN_DEBUG "%s: remote status: 0x%08x\n", ++ dev->dev.bus_id, status); ++ vlynq_reg_write(dev->remote->status, status); ++} ++ ++static irqreturn_t vlynq_irq(int irq, void *dev_id) ++{ ++ struct vlynq_device *dev = dev_id; ++ u32 status; ++ int virq = 0; ++ ++ status = vlynq_reg_read(dev->local->int_status); ++ vlynq_reg_write(dev->local->int_status, status); ++ ++ if (unlikely(!status)) ++ spurious_interrupt(); ++ ++ while (status) { ++ if (status & 1) ++ do_IRQ(dev->irq_start + virq); ++ status >>= 1; ++ virq++; ++ } ++ ++ return IRQ_HANDLED; ++} ++ ++static struct irq_chip vlynq_irq_chip = { ++ .name = "vlynq", ++ .unmask = vlynq_irq_unmask, ++ .mask = vlynq_irq_mask, ++ .set_type = vlynq_irq_type, ++}; ++ ++static struct irq_chip vlynq_local_chip = { ++ .name = "vlynq local error", ++ .unmask = vlynq_irq_unmask, ++ .mask = vlynq_irq_mask, ++ .ack = vlynq_local_ack, ++}; ++ ++static struct irq_chip vlynq_remote_chip = { ++ .name = "vlynq local error", ++ .unmask = vlynq_irq_unmask, ++ .mask = vlynq_irq_mask, ++ .ack = vlynq_remote_ack, ++}; ++ ++static int vlynq_setup_irq(struct vlynq_device *dev) ++{ ++ u32 val; ++ int i, virq; ++ ++ if (dev->local_irq == dev->remote_irq) { ++ printk(KERN_ERR ++ "%s: local vlynq irq should be different from remote\n", ++ dev->dev.bus_id); ++ return -EINVAL; ++ } ++ ++ /* Clear local and remote error bits */ ++ vlynq_reg_write(dev->local->status, vlynq_reg_read(dev->local->status)); ++ vlynq_reg_write(dev->remote->status, ++ vlynq_reg_read(dev->remote->status)); ++ ++ /* Now setup interrupts */ ++ val = VLYNQ_CTRL_INT_VECTOR(dev->local_irq); ++ val |= VLYNQ_CTRL_INT_ENABLE | VLYNQ_CTRL_INT_LOCAL | ++ VLYNQ_CTRL_INT2CFG; ++ val |= vlynq_reg_read(dev->local->control); ++ vlynq_reg_write(dev->local->int_ptr, VLYNQ_INT_OFFSET); ++ vlynq_reg_write(dev->local->control, val); ++ ++ val = VLYNQ_CTRL_INT_VECTOR(dev->remote_irq); ++ val |= VLYNQ_CTRL_INT_ENABLE; ++ val |= vlynq_reg_read(dev->remote->control); ++ vlynq_reg_write(dev->remote->int_ptr, VLYNQ_INT_OFFSET); ++ vlynq_reg_write(dev->remote->control, val); ++ ++ for (i = dev->irq_start; i <= dev->irq_end; i++) { ++ virq = i - dev->irq_start; ++ if (virq == dev->local_irq) { ++ set_irq_chip_and_handler(i, &vlynq_local_chip, ++ handle_level_irq); ++ set_irq_chip_data(i, dev); ++ } else if (virq == dev->remote_irq) { ++ set_irq_chip_and_handler(i, &vlynq_remote_chip, ++ handle_level_irq); ++ set_irq_chip_data(i, dev); ++ } else { ++ set_irq_chip_and_handler(i, &vlynq_irq_chip, ++ handle_simple_irq); ++ set_irq_chip_data(i, dev); ++ vlynq_reg_write(dev->remote->int_device[virq >> 2], 0); ++ } ++ } ++ ++ if (request_irq(dev->irq, vlynq_irq, IRQF_SHARED, "vlynq", dev)) { ++ printk(KERN_ERR "%s: request_irq failed\n", dev->dev.bus_id); ++ return -EAGAIN; ++ } ++ ++ return 0; ++} ++ ++static void vlynq_device_release(struct device *dev) ++{ ++ struct vlynq_device *vdev = to_vlynq_device(dev); ++ kfree(vdev); ++} ++ ++static int vlynq_device_match(struct device *dev, ++ struct device_driver *drv) ++{ ++ struct vlynq_device *vdev = to_vlynq_device(dev); ++ struct vlynq_driver *vdrv = to_vlynq_driver(drv); ++ struct vlynq_device_id *ids = vdrv->id_table; ++ ++ while (ids->id) { ++ if (ids->id == vdev->dev_id) { ++ vdev->divisor = ids->divisor; ++ vlynq_set_drvdata(vdev, ids); ++ printk(KERN_INFO "Driver found for VLYNQ " \ ++ "device: %08x\n", vdev->dev_id); ++ return 1; ++ } ++ printk(KERN_DEBUG "Not using the %08x VLYNQ device's driver" \ ++ " for VLYNQ device: %08x\n", ids->id, vdev->dev_id); ++ ids++; ++ } ++ return 0; ++} ++ ++static int vlynq_device_probe(struct device *dev) ++{ ++ struct vlynq_device *vdev = to_vlynq_device(dev); ++ struct vlynq_driver *drv = to_vlynq_driver(dev->driver); ++ struct vlynq_device_id *id = vlynq_get_drvdata(vdev); ++ int result = -ENODEV; ++ ++ get_device(dev); ++ if (drv && drv->probe) ++ result = drv->probe(vdev, id); ++ if (result) ++ put_device(dev); ++ return result; ++} ++ ++static int vlynq_device_remove(struct device *dev) ++{ ++ struct vlynq_driver *drv = to_vlynq_driver(dev->driver); ++ if (drv && drv->remove) ++ drv->remove(to_vlynq_device(dev)); ++ put_device(dev); ++ return 0; ++} ++ ++int __vlynq_register_driver(struct vlynq_driver *driver, struct module *owner) ++{ ++ driver->driver.name = driver->name; ++ driver->driver.bus = &vlynq_bus_type; ++ return driver_register(&driver->driver); ++} ++EXPORT_SYMBOL(__vlynq_register_driver); ++ ++void vlynq_unregister_driver(struct vlynq_driver *driver) ++{ ++ driver_unregister(&driver->driver); ++} ++EXPORT_SYMBOL(vlynq_unregister_driver); ++ ++static int __vlynq_try_remote(struct vlynq_device *dev) ++{ ++ int i; ++ ++ vlynq_reset(dev); ++ for (i = dev->dev_id ? vlynq_rdiv2 : vlynq_rdiv8; dev->dev_id ? ++ i <= vlynq_rdiv8 : i >= vlynq_rdiv2; ++ dev->dev_id ? i++ : i--) { ++ ++ if (!vlynq_linked(dev)) ++ break; ++ ++ vlynq_reg_write(dev->remote->control, ++ (vlynq_reg_read(dev->remote->control) & ++ ~VLYNQ_CTRL_CLOCK_MASK) | ++ VLYNQ_CTRL_CLOCK_INT | ++ VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1)); ++ vlynq_reg_write(dev->local->control, ++ ((vlynq_reg_read(dev->local->control) ++ & ~(VLYNQ_CTRL_CLOCK_INT | ++ VLYNQ_CTRL_CLOCK_MASK)) | ++ VLYNQ_CTRL_CLOCK_DIV(i - vlynq_rdiv1))); ++ ++ if (vlynq_linked(dev)) { ++ printk(KERN_DEBUG ++ "%s: using remote clock divisor %d\n", ++ dev->dev.bus_id, i - vlynq_rdiv1 + 1); ++ dev->divisor = i; ++ return 0; ++ } else { ++ vlynq_reset(dev); ++ } ++ } ++ ++ return -ENODEV; ++} ++ ++static int __vlynq_try_local(struct vlynq_device *dev) ++{ ++ int i; ++ ++ vlynq_reset(dev); ++ ++ for (i = dev->dev_id ? vlynq_ldiv2 : vlynq_ldiv8; dev->dev_id ? ++ i <= vlynq_ldiv8 : i >= vlynq_ldiv2; ++ dev->dev_id ? i++ : i--) { ++ ++ vlynq_reg_write(dev->local->control, ++ (vlynq_reg_read(dev->local->control) & ++ ~VLYNQ_CTRL_CLOCK_MASK) | ++ VLYNQ_CTRL_CLOCK_INT | ++ VLYNQ_CTRL_CLOCK_DIV(i - vlynq_ldiv1)); ++ ++ if (vlynq_linked(dev)) { ++ printk(KERN_DEBUG ++ "%s: using local clock divisor %d\n", ++ dev->dev.bus_id, i - vlynq_ldiv1 + 1); ++ dev->divisor = i; ++ return 0; ++ } else { ++ vlynq_reset(dev); ++ } ++ } ++ ++ return -ENODEV; ++} ++ ++static int __vlynq_try_external(struct vlynq_device *dev) ++{ ++ vlynq_reset(dev); ++ if (!vlynq_linked(dev)) ++ return -ENODEV; ++ ++ vlynq_reg_write(dev->remote->control, ++ (vlynq_reg_read(dev->remote->control) & ++ ~VLYNQ_CTRL_CLOCK_INT)); ++ ++ vlynq_reg_write(dev->local->control, ++ (vlynq_reg_read(dev->local->control) & ++ ~VLYNQ_CTRL_CLOCK_INT)); ++ ++ if (vlynq_linked(dev)) { ++ printk(KERN_DEBUG "%s: using external clock\n", ++ dev->dev.bus_id); ++ dev->divisor = vlynq_div_external; ++ return 0; ++ } ++ ++ return -ENODEV; ++} ++ ++static int __vlynq_enable_device(struct vlynq_device *dev) ++{ ++ int result; ++ struct plat_vlynq_ops *ops = dev->dev.platform_data; ++ ++ result = ops->on(dev); ++ if (result) ++ return result; ++ ++ switch (dev->divisor) { ++ case vlynq_div_external: ++ case vlynq_div_auto: ++ /* When the device is brought from reset it should have clock ++ generation negotiated by hardware. ++ Check which device is generating clocks and perform setup ++ accordingly */ ++ if (vlynq_linked(dev) && vlynq_reg_read(dev->remote->control) & ++ VLYNQ_CTRL_CLOCK_INT) { ++ if (!__vlynq_try_remote(dev) || ++ !__vlynq_try_local(dev) || ++ !__vlynq_try_external(dev)) ++ return 0; ++ } else { ++ if (!__vlynq_try_external(dev) || ++ !__vlynq_try_local(dev) || ++ !__vlynq_try_remote(dev)) ++ return 0; ++ } ++ break; ++ case vlynq_ldiv1: case vlynq_ldiv2: case vlynq_ldiv3: case vlynq_ldiv4: ++ case vlynq_ldiv5: case vlynq_ldiv6: case vlynq_ldiv7: case vlynq_ldiv8: ++ vlynq_reg_write(dev->local->control, ++ VLYNQ_CTRL_CLOCK_INT | ++ VLYNQ_CTRL_CLOCK_DIV(dev->divisor - ++ vlynq_ldiv1)); ++ vlynq_reg_write(dev->remote->control, 0); ++ if (vlynq_linked(dev)) { ++ printk(KERN_DEBUG ++ "%s: using local clock divisor %d\n", ++ dev->dev.bus_id, dev->divisor - vlynq_ldiv1 + 1); ++ return 0; ++ } ++ break; ++ case vlynq_rdiv1: case vlynq_rdiv2: case vlynq_rdiv3: case vlynq_rdiv4: ++ case vlynq_rdiv5: case vlynq_rdiv6: case vlynq_rdiv7: case vlynq_rdiv8: ++ vlynq_reg_write(dev->local->control, 0); ++ vlynq_reg_write(dev->remote->control, ++ VLYNQ_CTRL_CLOCK_INT | ++ VLYNQ_CTRL_CLOCK_DIV(dev->divisor - ++ vlynq_rdiv1)); ++ if (vlynq_linked(dev)) { ++ printk(KERN_DEBUG ++ "%s: using remote clock divisor %d\n", ++ dev->dev.bus_id, dev->divisor - vlynq_rdiv1 + 1); ++ return 0; ++ } ++ break; ++ } ++ ++ ops->off(dev); ++ return -ENODEV; ++} ++ ++int vlynq_enable_device(struct vlynq_device *dev) ++{ ++ struct plat_vlynq_ops *ops = dev->dev.platform_data; ++ int result = -ENODEV; ++ ++ result = __vlynq_enable_device(dev); ++ if (result) ++ return result; ++ ++ result = vlynq_setup_irq(dev); ++ if (result) ++ ops->off(dev); ++ ++ dev->enabled = !result; ++ return result; ++} ++EXPORT_SYMBOL(vlynq_enable_device); ++ ++ ++void vlynq_disable_device(struct vlynq_device *dev) ++{ ++ struct plat_vlynq_ops *ops = dev->dev.platform_data; ++ ++ dev->enabled = 0; ++ free_irq(dev->irq, dev); ++ ops->off(dev); ++} ++EXPORT_SYMBOL(vlynq_disable_device); ++ ++int vlynq_set_local_mapping(struct vlynq_device *dev, u32 tx_offset, ++ struct vlynq_mapping *mapping) ++{ ++ int i; ++ ++ if (!dev->enabled) ++ return -ENXIO; ++ ++ vlynq_reg_write(dev->local->tx_offset, tx_offset); ++ for (i = 0; i < 4; i++) { ++ vlynq_reg_write(dev->local->rx_mapping[i].offset, ++ mapping[i].offset); ++ vlynq_reg_write(dev->local->rx_mapping[i].size, ++ mapping[i].size); ++ } ++ return 0; ++} ++EXPORT_SYMBOL(vlynq_set_local_mapping); ++ ++int vlynq_set_remote_mapping(struct vlynq_device *dev, u32 tx_offset, ++ struct vlynq_mapping *mapping) ++{ ++ int i; ++ ++ if (!dev->enabled) ++ return -ENXIO; ++ ++ vlynq_reg_write(dev->remote->tx_offset, tx_offset); ++ for (i = 0; i < 4; i++) { ++ vlynq_reg_write(dev->remote->rx_mapping[i].offset, ++ mapping[i].offset); ++ vlynq_reg_write(dev->remote->rx_mapping[i].size, ++ mapping[i].size); ++ } ++ return 0; ++} ++EXPORT_SYMBOL(vlynq_set_remote_mapping); ++ ++int vlynq_set_local_irq(struct vlynq_device *dev, int virq) ++{ ++ int irq = dev->irq_start + virq; ++ if (dev->enabled) ++ return -EBUSY; ++ ++ if ((irq < dev->irq_start) || (irq > dev->irq_end)) ++ return -EINVAL; ++ ++ if (virq == dev->remote_irq) ++ return -EINVAL; ++ ++ dev->local_irq = virq; ++ ++ return 0; ++} ++EXPORT_SYMBOL(vlynq_set_local_irq); ++ ++int vlynq_set_remote_irq(struct vlynq_device *dev, int virq) ++{ ++ int irq = dev->irq_start + virq; ++ if (dev->enabled) ++ return -EBUSY; ++ ++ if ((irq < dev->irq_start) || (irq > dev->irq_end)) ++ return -EINVAL; ++ ++ if (virq == dev->local_irq) ++ return -EINVAL; ++ ++ dev->remote_irq = virq; ++ ++ return 0; ++} ++EXPORT_SYMBOL(vlynq_set_remote_irq); ++ ++static int vlynq_probe(struct platform_device *pdev) ++{ ++ struct vlynq_device *dev; ++ struct resource *regs_res, *mem_res, *irq_res; ++ int len, result; ++ ++ regs_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); ++ if (!regs_res) ++ return -ENODEV; ++ ++ mem_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem"); ++ if (!mem_res) ++ return -ENODEV; ++ ++ irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "devirq"); ++ if (!irq_res) ++ return -ENODEV; ++ ++ dev = kzalloc(sizeof(*dev), GFP_KERNEL); ++ if (!dev) { ++ printk(KERN_ERR ++ "vlynq: failed to allocate device structure\n"); ++ return -ENOMEM; ++ } ++ ++ dev->id = pdev->id; ++ dev->dev.bus = &vlynq_bus_type; ++ dev->dev.parent = &pdev->dev; ++ snprintf(dev->dev.bus_id, BUS_ID_SIZE, "vlynq%d", dev->id); ++ dev->dev.bus_id[BUS_ID_SIZE - 1] = 0; ++ dev->dev.platform_data = pdev->dev.platform_data; ++ dev->dev.release = vlynq_device_release; ++ ++ dev->regs_start = regs_res->start; ++ dev->regs_end = regs_res->end; ++ dev->mem_start = mem_res->start; ++ dev->mem_end = mem_res->end; ++ ++ len = regs_res->end - regs_res->start; ++ if (!request_mem_region(regs_res->start, len, dev->dev.bus_id)) { ++ printk(KERN_ERR "%s: Can't request vlynq registers\n", ++ dev->dev.bus_id); ++ result = -ENXIO; ++ goto fail_request; ++ } ++ ++ dev->local = ioremap(regs_res->start, len); ++ if (!dev->local) { ++ printk(KERN_ERR "%s: Can't remap vlynq registers\n", ++ dev->dev.bus_id); ++ result = -ENXIO; ++ goto fail_remap; ++ } ++ ++ dev->remote = (struct vlynq_regs *)((void *)dev->local + ++ VLYNQ_REMOTE_OFFSET); ++ ++ dev->irq = platform_get_irq_byname(pdev, "irq"); ++ dev->irq_start = irq_res->start; ++ dev->irq_end = irq_res->end; ++ dev->local_irq = dev->irq_end - dev->irq_start; ++ dev->remote_irq = dev->local_irq - 1; ++ ++ if (device_register(&dev->dev)) ++ goto fail_register; ++ platform_set_drvdata(pdev, dev); ++ ++ printk(KERN_INFO "%s: regs 0x%p, irq %d, mem 0x%p\n", ++ dev->dev.bus_id, (void *)dev->regs_start, dev->irq, ++ (void *)dev->mem_start); ++ ++ dev->dev_id = 0; ++ dev->divisor = vlynq_div_auto; ++ result = __vlynq_enable_device(dev); ++ if (result == 0) { ++ dev->dev_id = vlynq_reg_read(dev->remote->chip); ++ ((struct plat_vlynq_ops *)(dev->dev.platform_data))->off(dev); ++ } ++ if (dev->dev_id) ++ printk(KERN_INFO "Found a VLYNQ device: %08x\n", dev->dev_id); ++ ++ return 0; ++ ++fail_register: ++ iounmap(dev->local); ++fail_remap: ++fail_request: ++ release_mem_region(regs_res->start, len); ++ kfree(dev); ++ return result; ++} ++ ++static int vlynq_remove(struct platform_device *pdev) ++{ ++ struct vlynq_device *dev = platform_get_drvdata(pdev); ++ ++ device_unregister(&dev->dev); ++ iounmap(dev->local); ++ release_mem_region(dev->regs_start, dev->regs_end - dev->regs_start); ++ ++ kfree(dev); ++ ++ return 0; ++} ++ ++static struct platform_driver vlynq_platform_driver = { ++ .driver.name = "vlynq", ++ .probe = vlynq_probe, ++ .remove = __devexit_p(vlynq_remove), ++}; ++ ++struct bus_type vlynq_bus_type = { ++ .name = "vlynq", ++ .match = vlynq_device_match, ++ .probe = vlynq_device_probe, ++ .remove = vlynq_device_remove, ++}; ++EXPORT_SYMBOL(vlynq_bus_type); ++ ++static int __devinit vlynq_init(void) ++{ ++ int res = 0; ++ ++ res = bus_register(&vlynq_bus_type); ++ if (res) ++ goto fail_bus; ++ ++ res = platform_driver_register(&vlynq_platform_driver); ++ if (res) ++ goto fail_platform; ++ ++ return 0; ++ ++fail_platform: ++ bus_unregister(&vlynq_bus_type); ++fail_bus: ++ return res; ++} ++ ++static void __devexit vlynq_exit(void) ++{ ++ platform_driver_unregister(&vlynq_platform_driver); ++ bus_unregister(&vlynq_bus_type); ++} ++ ++module_init(vlynq_init); ++module_exit(vlynq_exit); +diff -Nur linux-2.6.29.1.orig/drivers/watchdog/ar7_wdt.c linux-2.6.29.1/drivers/watchdog/ar7_wdt.c +--- linux-2.6.29.1.orig/drivers/watchdog/ar7_wdt.c 2009-04-02 22:55:27.000000000 +0200 ++++ linux-2.6.29.1/drivers/watchdog/ar7_wdt.c 2009-05-31 19:54:01.000000000 +0200 +@@ -69,8 +69,7 @@ + u32 prescale; + }; + +-static unsigned long wdt_is_open; +-static spinlock_t wdt_lock; ++static struct semaphore open_semaphore; + static unsigned expect_close; + + /* XXX currently fixed, allows max margin ~68.72 secs */ +@@ -155,10 +154,8 @@ + u32 change; + + change = new_margin * (ar7_vbus_freq() / prescale_value); +- if (change < 1) +- change = 1; +- if (change > 0xffff) +- change = 0xffff; ++ if (change < 1) change = 1; ++ if (change > 0xffff) change = 0xffff; + ar7_wdt_change(change); + margin = change * prescale_value / ar7_vbus_freq(); + printk(KERN_INFO DRVNAME +@@ -182,7 +179,7 @@ + static int ar7_wdt_open(struct inode *inode, struct file *file) + { + /* only allow one at a time */ +- if (test_and_set_bit(0, &wdt_is_open)) ++ if (down_trylock(&open_semaphore)) + return -EBUSY; + ar7_wdt_enable_wdt(); + expect_close = 0; +@@ -198,7 +195,9 @@ + "will not disable the watchdog timer\n"); + else if (!nowayout) + ar7_wdt_disable_wdt(); +- clear_bit(0, &wdt_is_open); ++ ++ up(&open_semaphore); ++ + return 0; + } + +@@ -213,7 +212,7 @@ + } + + static struct notifier_block ar7_wdt_notifier = { +- .notifier_call = ar7_wdt_notify_sys, ++ .notifier_call = ar7_wdt_notify_sys + }; + + static ssize_t ar7_wdt_write(struct file *file, const char *data, +@@ -223,14 +222,12 @@ + if (len) { + size_t i; + +- spin_lock(&wdt_lock); + ar7_wdt_kick(1); +- spin_unlock(&wdt_lock); + + expect_close = 0; + for (i = 0; i < len; ++i) { + char c; +- if (get_user(c, data + i)) ++ if (get_user(c, data+i)) + return -EFAULT; + if (c == 'V') + expect_close = 1; +@@ -240,17 +237,19 @@ + return len; + } + +-static long ar7_wdt_ioctl(struct file *file, +- unsigned int cmd, unsigned long arg) ++static int ar7_wdt_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) + { + static struct watchdog_info ident = { + .identity = LONGNAME, + .firmware_version = 1, +- .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING), ++ .options = (WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING), + }; + int new_margin; + + switch (cmd) { ++ default: ++ return -ENOTTY; + case WDIOC_GETSUPPORT: + if (copy_to_user((struct watchdog_info *)arg, &ident, + sizeof(ident))) +@@ -270,24 +269,20 @@ + if (new_margin < 1) + return -EINVAL; + +- spin_lock(&wdt_lock); + ar7_wdt_update_margin(new_margin); + ar7_wdt_kick(1); +- spin_unlock(&wdt_lock); + + case WDIOC_GETTIMEOUT: + if (put_user(margin, (int *)arg)) + return -EFAULT; + return 0; +- default: +- return -ENOTTY; + } + } + +-static const struct file_operations ar7_wdt_fops = { ++static struct file_operations ar7_wdt_fops = { + .owner = THIS_MODULE, + .write = ar7_wdt_write, +- .unlocked_ioctl = ar7_wdt_ioctl, ++ .ioctl = ar7_wdt_ioctl, + .open = ar7_wdt_open, + .release = ar7_wdt_release, + }; +@@ -302,8 +297,6 @@ + { + int rc; + +- spin_lock_init(&wdt_lock); +- + ar7_wdt_get_regs(); + + if (!request_mem_region(ar7_regs_wdt, sizeof(struct ar7_wdt), +@@ -319,6 +312,8 @@ + ar7_wdt_prescale(prescale_value); + ar7_wdt_update_margin(margin); + ++ sema_init(&open_semaphore, 1); ++ + rc = register_reboot_notifier(&ar7_wdt_notifier); + if (rc) { + printk(KERN_ERR DRVNAME +diff -Nur linux-2.6.29.1.orig/include/linux/vlynq.h linux-2.6.29.1/include/linux/vlynq.h +--- linux-2.6.29.1.orig/include/linux/vlynq.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.29.1/include/linux/vlynq.h 2009-05-31 20:25:54.000000000 +0200 +@@ -0,0 +1,161 @@ ++/* ++ * Copyright (C) 2006, 2007 Eugene Konev <ejka@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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ */ ++ ++#ifndef __VLYNQ_H__ ++#define __VLYNQ_H__ ++ ++#include <linux/device.h> ++#include <linux/module.h> ++#include <linux/types.h> ++ ++#define VLYNQ_NUM_IRQS 32 ++ ++struct vlynq_mapping { ++ u32 size; ++ u32 offset; ++}; ++ ++enum vlynq_divisor { ++ vlynq_div_auto = 0, ++ vlynq_ldiv1, ++ vlynq_ldiv2, ++ vlynq_ldiv3, ++ vlynq_ldiv4, ++ vlynq_ldiv5, ++ vlynq_ldiv6, ++ vlynq_ldiv7, ++ vlynq_ldiv8, ++ vlynq_rdiv1, ++ vlynq_rdiv2, ++ vlynq_rdiv3, ++ vlynq_rdiv4, ++ vlynq_rdiv5, ++ vlynq_rdiv6, ++ vlynq_rdiv7, ++ vlynq_rdiv8, ++ vlynq_div_external ++}; ++ ++struct vlynq_device_id { ++ u32 id; ++ enum vlynq_divisor divisor; ++ unsigned long driver_data; ++}; ++ ++struct vlynq_regs; ++struct vlynq_device { ++ u32 id, dev_id; ++ int local_irq; ++ int remote_irq; ++ enum vlynq_divisor divisor; ++ u32 regs_start, regs_end; ++ u32 mem_start, mem_end; ++ u32 irq_start, irq_end; ++ int irq; ++ int enabled; ++ struct vlynq_regs *local; ++ struct vlynq_regs *remote; ++ struct device dev; ++}; ++ ++struct vlynq_driver { ++ char *name; ++ struct vlynq_device_id *id_table; ++ int (*probe)(struct vlynq_device *dev, struct vlynq_device_id *id); ++ void (*remove)(struct vlynq_device *dev); ++ struct device_driver driver; ++}; ++ ++struct plat_vlynq_ops { ++ int (*on)(struct vlynq_device *dev); ++ void (*off)(struct vlynq_device *dev); ++}; ++ ++static inline struct vlynq_driver *to_vlynq_driver(struct device_driver *drv) ++{ ++ return container_of(drv, struct vlynq_driver, driver); ++} ++ ++static inline struct vlynq_device *to_vlynq_device(struct device *device) ++{ ++ return container_of(device, struct vlynq_device, dev); ++} ++ ++extern struct bus_type vlynq_bus_type; ++ ++extern int __vlynq_register_driver(struct vlynq_driver *driver, ++ struct module *owner); ++ ++static inline int vlynq_register_driver(struct vlynq_driver *driver) ++{ ++ return __vlynq_register_driver(driver, THIS_MODULE); ++} ++ ++static inline void *vlynq_get_drvdata(struct vlynq_device *dev) ++{ ++ return dev_get_drvdata(&dev->dev); ++} ++ ++static inline void vlynq_set_drvdata(struct vlynq_device *dev, void *data) ++{ ++ dev_set_drvdata(&dev->dev, data); ++} ++ ++static inline u32 vlynq_mem_start(struct vlynq_device *dev) ++{ ++ return dev->mem_start; ++} ++ ++static inline u32 vlynq_mem_end(struct vlynq_device *dev) ++{ ++ return dev->mem_end; ++} ++ ++static inline u32 vlynq_mem_len(struct vlynq_device *dev) ++{ ++ return dev->mem_end - dev->mem_start + 1; ++} ++ ++static inline int vlynq_virq_to_irq(struct vlynq_device *dev, int virq) ++{ ++ int irq = dev->irq_start + virq; ++ if ((irq < dev->irq_start) || (irq > dev->irq_end)) ++ return -EINVAL; ++ ++ return irq; ++} ++ ++static inline int vlynq_irq_to_virq(struct vlynq_device *dev, int irq) ++{ ++ if ((irq < dev->irq_start) || (irq > dev->irq_end)) ++ return -EINVAL; ++ ++ return irq - dev->irq_start; ++} ++ ++extern void vlynq_unregister_driver(struct vlynq_driver *driver); ++extern int vlynq_enable_device(struct vlynq_device *dev); ++extern void vlynq_disable_device(struct vlynq_device *dev); ++extern int vlynq_set_local_mapping(struct vlynq_device *dev, u32 tx_offset, ++ struct vlynq_mapping *mapping); ++extern int vlynq_set_remote_mapping(struct vlynq_device *dev, u32 tx_offset, ++ struct vlynq_mapping *mapping); ++extern int vlynq_set_local_irq(struct vlynq_device *dev, int virq); ++extern int vlynq_set_remote_irq(struct vlynq_device *dev, int virq); ++ ++#endif /* __VLYNQ_H__ */ +diff -Nur linux-2.6.29.1.orig/kernel/futex.c linux-2.6.29.1/kernel/futex.c +--- linux-2.6.29.1.orig/kernel/futex.c 2009-04-02 22:55:27.000000000 +0200 ++++ linux-2.6.29.1/kernel/futex.c 2009-06-01 12:42:57.000000000 +0200 +@@ -2027,9 +2027,11 @@ + * implementation, the non functional ones will return + * -ENOSYS. + */ +- curval = cmpxchg_futex_value_locked(NULL, 0, 0); +- if (curval == -EFAULT) +- futex_cmpxchg_enabled = 1; ++ // exeption handler on ar7 is broken ++ //curval = cmpxchg_futex_value_locked(NULL, 0, 0); ++ //if (curval == -EFAULT) ++ // futex_cmpxchg_enabled = 1; ++ futex_cmpxchg_enabled = 0; + + for (i = 0; i < ARRAY_SIZE(futex_queues); i++) { + plist_head_init(&futex_queues[i].chain, &futex_queues[i].lock); +diff -Nur linux-2.6.29.1.orig/kernel/printk.c linux-2.6.29.1/kernel/printk.c +--- linux-2.6.29.1.orig/kernel/printk.c 2009-04-02 22:55:27.000000000 +0200 ++++ linux-2.6.29.1/kernel/printk.c 2009-06-01 13:40:39.000000000 +0200 +@@ -1253,6 +1253,7 @@ + + static int __init disable_boot_consoles(void) + { ++ /* triggers reboot on ar7 + if (console_drivers != NULL) { + if (console_drivers->flags & CON_BOOT) { + printk(KERN_INFO "turn off boot console %s%d\n", +@@ -1260,6 +1261,7 @@ + return unregister_console(console_drivers); + } + } ++ */ + return 0; + } + late_initcall(disable_boot_consoles); diff --git a/target/wag54g/tools/addpattern/Makefile b/target/wag54g/tools/addpattern/Makefile new file mode 100644 index 000000000..3ac1884fa --- /dev/null +++ b/target/wag54g/tools/addpattern/Makefile @@ -0,0 +1,4 @@ +include $(TOPDIR)/rules.mk + +all: + $(HOSTCC) ${HOSTCFLAGS} -o ${STAGING_TOOLS}/bin/addpattern addpattern.c diff --git a/target/wag54g/tools/addpattern/addpattern.c b/target/wag54g/tools/addpattern/addpattern.c new file mode 100644 index 000000000..6f2a036c0 --- /dev/null +++ b/target/wag54g/tools/addpattern/addpattern.c @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* July 29, 2004 + * + * This is a hacked replacement for the 'addpattern' utility used to + * create wrt54g .bin firmware files. It isn't pretty, but it does + * the job for me. + * + * Extensions: + * -v allows setting the version string on the command line. + * -{0|1} sets the (currently ignored) hw_ver flag in the header + * to 0 or 1 respectively. + */ + +/* January 12, 2005 + * + * Modified by rodent at rodent dot za dot net + * Support added for the new WRT54G v2.2 and WRT54GS v1.1 "flags" + * Without the flags set to 0x7, the above units will refuse to flash. + * + * Extensions: + * -{0|1|2} sets {0|1} sets hw_ver flag to 0/1. {2} sets hw_ver to 1 + * and adds the new hardware "flags" for the v2.2/v1.1 units +*/ + +/* January 1, 2007 + * + * Modified by juan.i.gonzalez at subdown dot net + * Support added for the AG241v2 and similar + * + * Extensions: + * -r #.# adds revision hardware flags. AG241v2 and similar. + * + * AG241V2 firmware sets the hw_ver to 0x44. + * + * Example: -r 2.0 + * + * Convert 2.0 to 20 to be an integer, and add 0x30 to skip special ASCII + * #define HW_Version ((HW_REV * 10) + 0x30) -> from cyutils.h +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/stat.h> + +/**********************************************************************/ + +#define CODE_ID "U2ND" /* from code_pattern.h */ +#define CODE_PATTERN "W54S" /* from code_pattern.h */ +#define PBOT_PATTERN "PBOT" + +#define CYBERTAN_VERSION "v3.37.2" /* from cyutils.h */ + +/* WRT54G v2.2 and WRT54GS v1.1 "flags" (from 3.37.32 firmware cyutils.h) */ +#define SUPPORT_4712_CHIP 0x0001 +#define SUPPORT_INTEL_FLASH 0x0002 +#define SUPPORT_5325E_SWITCH 0x0004 + +struct code_header { /* from cyutils.h */ + char magic[4]; + char res1[4]; /* for extra magic */ + char fwdate[3]; + char fwvern[3]; + char id[4]; /* U2ND */ + char hw_ver; /* 0: for 4702, 1: for 4712 -- new in 2.04.3 */ + char unused; + unsigned char flags[2]; /* SUPPORT_ flags new for 3.37.2 (WRT54G v2.2 and WRT54GS v1.1) */ + unsigned char res2[10]; +} ; + +/**********************************************************************/ + +void usage(void) __attribute__ (( __noreturn__ )); + +void usage(void) +{ + fprintf(stderr, "Usage: addpattern [-i trxfile] [-o binfile] [-p pattern] [-g] [-b] [-v v#.#.#] [-r #.#] [-{0|1|2|4}] -h\n"); + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) +{ + char buf[1024]; /* keep this at 1k or adjust garbage calc below */ + struct code_header *hdr; + FILE *in = stdin; + FILE *out = stdout; + char *ifn = NULL; + char *ofn = NULL; + char *pattern = CODE_PATTERN; + char *pbotpat = PBOT_PATTERN; + char *version = CYBERTAN_VERSION; + int gflag = 0; + int pbotflag = 0; + int c; + int v0, v1, v2; + size_t off, n; + time_t t; + struct tm *ptm; + + fprintf(stderr, "mjn3's addpattern replacement - v0.81\n"); + + hdr = (struct code_header *) buf; + memset(hdr, 0, sizeof(struct code_header)); + + while ((c = getopt(argc, argv, "i:o:p:gbv:0124hr:")) != -1) { + switch (c) { + case 'i': + ifn = optarg; + break; + case 'o': + ofn = optarg; + break; + case 'p': + pattern = optarg; + break; + case 'g': + gflag = 1; + break; + case 'b': + pbotflag = 1; + break; + case 'v': /* extension to allow setting version */ + version = optarg; + break; + case '0': + hdr->hw_ver = 0; + break; + case '1': + hdr->hw_ver = 1; + break; + case '2': /* new 54G v2.2 and 54GS v1.1 flags */ + hdr->hw_ver = 1; + hdr->flags[0] |= SUPPORT_4712_CHIP; + hdr->flags[0] |= SUPPORT_INTEL_FLASH; + hdr->flags[0] |= SUPPORT_5325E_SWITCH; + break; + case '4': + /* V4 firmware sets the flags to 0x1f */ + hdr->hw_ver = 0; + hdr->flags[0] = 0x1f; + break; + case 'r': + hdr->hw_ver = (char)(atof(optarg)*10)+0x30; + break; + + case 'h': + default: + usage(); + } + } + + if (optind != argc || optind == 1) { + fprintf(stderr, "illegal arg \"%s\"\n", argv[optind]); + usage(); + } + + if (strlen(pattern) != 4) { + fprintf(stderr, "illegal pattern \"%s\": length != 4\n", pattern); + usage(); + } + + if (ifn && !(in = fopen(ifn, "r"))) { + fprintf(stderr, "can not open \"%s\" for reading\n", ifn); + usage(); + } + + if (ofn && !(out = fopen(ofn, "w"))) { + fprintf(stderr, "can not open \"%s\" for writing\n", ofn); + usage(); + } + + if (time(&t) == (time_t)(-1)) { + fprintf(stderr, "time call failed\n"); + return EXIT_FAILURE; + } + + ptm = localtime(&t); + + if (3 != sscanf(version, "v%d.%d.%d", &v0, &v1, &v2)) { + fprintf(stderr, "bad version string \"%s\"\n", version); + return EXIT_FAILURE; + } + + memcpy(&hdr->magic, pattern, 4); + if (pbotflag) + memcpy(&hdr->res1, pbotpat, 4); + hdr->fwdate[0] = ptm->tm_year % 100; + hdr->fwdate[1] = ptm->tm_mon + 1; + hdr->fwdate[2] = ptm->tm_mday; + hdr->fwvern[0] = v0; + hdr->fwvern[1] = v1; + hdr->fwvern[2] = v2; + memcpy(&hdr->id, CODE_ID, strlen(CODE_ID)); + + off = sizeof(struct code_header); + + fprintf(stderr, "writing firmware v%d.%d.%d on %d/%d/%d (y/m/d)\n", + v0, v1, v2, + hdr->fwdate[0], hdr->fwdate[1], hdr->fwdate[2]); + + + while ((n = fread(buf + off, 1, sizeof(buf)-off, in) + off) > 0) { + off = 0; + if (n < sizeof(buf)) { + if (ferror(in)) { + FREAD_ERROR: + fprintf(stderr, "fread error\n"); + return EXIT_FAILURE; + } + if (gflag) { + gflag = sizeof(buf) - n; + memset(buf + n, 0xff, gflag); + fprintf(stderr, "adding %d bytes of garbage\n", gflag); + n = sizeof(buf); + } + } + if (!fwrite(buf, n, 1, out)) { + FWRITE_ERROR: + fprintf(stderr, "fwrite error\n"); + return EXIT_FAILURE; + } + } + + if (ferror(in)) { + goto FREAD_ERROR; + } + + if (fflush(out)) { + goto FWRITE_ERROR; + } + + fclose(in); + fclose(out); + + return EXIT_SUCCESS; +} diff --git a/target/wag54g/tools/rules.mk b/target/wag54g/tools/rules.mk new file mode 100644 index 000000000..8d03c031a --- /dev/null +++ b/target/wag54g/tools/rules.mk @@ -0,0 +1,9 @@ +# $Id$ +#- +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +WRKDIR_BASE= ${TOOLS_BUILD_DIR} +WRKDIR= ${WRKDIR_BASE} + +include ${TOPDIR}/mk/buildhlp.mk diff --git a/target/wag54g/tools/squashfs/Makefile b/target/wag54g/tools/squashfs/Makefile new file mode 100644 index 000000000..0887afc22 --- /dev/null +++ b/target/wag54g/tools/squashfs/Makefile @@ -0,0 +1,27 @@ +# $Id$ +#- +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +include $(TOPDIR)/rules.mk + +PKG_NAME:= squashfs +PKG_VERSION:= 4.0 +PKG_RELEASE:= 1 +PKG_MD5SUM:= a3c23391da4ebab0ac4a75021ddabf96 +PKG_SITES:= ${MASTER_SITE_SOURCEFORGE:=squashfs/} +DISTFILES:= ${PKG_NAME}${PKG_VERSION}.tar.gz +WRKDIST= ${WRKDIR}/$(PKG_NAME)${PKG_VERSION} + +include ../rules.mk + +$(WRKBUILD)/.compiled: ${WRKDIST}/.prepared + $(MAKE) -C $(WRKBUILD)/squashfs-tools + touch $@ + +$(WRKBUILD)/.installed: + $(INSTALL_BIN) $(WRKBUILD)/squashfs-tools/mksquashfs \ + ${STAGING_TOOLS}/bin + touch $@ + +include $(TOPDIR)/mk/tools.mk diff --git a/target/wag54g/tools/srec2bin/Makefile b/target/wag54g/tools/srec2bin/Makefile new file mode 100644 index 000000000..dd6a285fd --- /dev/null +++ b/target/wag54g/tools/srec2bin/Makefile @@ -0,0 +1,4 @@ +include $(TOPDIR)/rules.mk + +all: + $(HOSTCC) ${HOSTCFLAGS} -o ${STAGING_TOOLS}/bin/srec2bin srec2bin.c diff --git a/target/wag54g/tools/srec2bin/srec2bin.c b/target/wag54g/tools/srec2bin/srec2bin.c new file mode 100644 index 000000000..1cffbaed9 --- /dev/null +++ b/target/wag54g/tools/srec2bin/srec2bin.c @@ -0,0 +1,524 @@ +#include <stdio.h> +#include <ctype.h> +#include <string.h> + +//Rev 0.1 Original +// 8 Jan 2001 MJH Added code to write data to Binary file +// note: outputfile is name.bin, where name is first part +// of input file. ie tmp.rec -> tmp.bin +// +// srec2bin <input SREC file> <Output Binary File> <If Present, Big Endian> +// +// TAG +// bit32u TAG_BIG = 0xDEADBE42; +// bit32u TAG_LITTLE = 0xFEEDFA42; +// +// File Structure +// +// TAG : 32 Bits +// [DATA RECORDS] +// +// Data Records Structure +// +// LENGTH : 32 Bits <- Length of DATA, excludes ADDRESS and CHECKSUM +// ADDRESS : 32 Bits +// DATA : 8 Bits * LENGTH +// CHECKSUM: 32 Bits <- 0 - (Sum of Length --> End of Data) +// +// Note : If Length == 0, Address will be Program Start +// +// +// +// +// + +#define MajRevNum 0 +#define MinRevNum 2 + + +#define EndianSwitch(x) ((x >> 24) | (x << 24) | ((x << 8) & (0x00FF0000)) | ((x >> 8) & (0x0000FF00)) ) + +typedef unsigned char bit8u; +typedef unsigned int bit32u; +typedef int bit32; + +#define FALSE 0 +#define TRUE (!FALSE) + + +bit32u CheckSum; +int RecStart; +int debug; +int verbose; + +FILE *OpenOutputFile( char *Name ); +FILE *fOut; +bit32u RecLength=0; + +bit32u AddressCurrent; + +bit32u gh(char *cp,int nibs); + +int BigEndian; + +int inputline; + +// char buf[16*1024]; + +char buffer[2048]; +char *cur_ptr; +int cur_line=0; +int cur_len=0; + +int s1s2s3_total=0; + +bit32u PBVal; +int PBValid; +bit32u PBAdr; + + +void dumpfTell(char *s, bit32u Value) +{ + int Length; + Length = (int) RecLength; + if (debug) + printf("[%s ] ftell()[0x%08lX] Length[0x%4X] Length[%4d] Value[0x%08x]\n", + s, ftell(fOut), Length, Length, Value); +} + +void DispHex(bit32u Hex) +{ +// printf("%X", Hex); +} + +void WaitDisplay(void) +{ + static int Count=0; + static int Index=0; + char iline[]={"-\\|/"}; + + Count++; + if ((Count % 32)==0) + { + if (verbose) + printf("%c%c",iline[Index++],8); + Index &= 3; + } +} + + +void binOut32 ( bit32u Data ) +{ +// On UNIX machine all 32bit writes need ENDIAN switched +// Data = EndianSwitch(Data); +// fwrite( &Data, sizeof(bit32u), 1, fOut); + + char sdat[4]; + int i; + + for(i=0;i<4;i++) + sdat[i]=(char)(Data>>(i*8)); + fwrite( sdat, 1, 4, fOut); + dumpfTell("Out32" , Data); +} + +// Only update RecLength on Byte Writes +// All 32 bit writes will be for Length etc + +void binOut8 ( bit8u Data ) +{ + int n; + dumpfTell("B4Data" , (bit32u) (Data & 0xFF) ); + n = fwrite( &Data, sizeof(bit8u), 1, fOut); + if (n != 1) + printf("Error in writing %X for Address 0x%8X\n", Data, AddressCurrent); + RecLength += 1; +} + +// Currently ONLY used for outputting Program Start + +void binRecStart(bit32u Address) +{ + RecLength = 0; + CheckSum = Address; + RecStart = TRUE; + + if (debug) + printf("[RecStart] CheckSum[0x%08X] Length[%4d] Address[0x%08X]\n", + CheckSum, RecLength, Address); + + + dumpfTell("RecLength", RecLength); + binOut32( RecLength ); + dumpfTell("Address", Address); + binOut32( Address ); +} + +void binRecEnd(void) +{ + long RecEnd; + + if (!RecStart) // if no record started, do not end it + { + return; + } + + RecStart = FALSE; + + + RecEnd = ftell(fOut); // Save Current position + + if (debug) + printf("[RecEnd ] CheckSum[0x%08X] Length[%4d] Length[0x%X] RecEnd[0x%08lX]\n", + CheckSum, RecLength, RecLength, RecEnd); + + fseek( fOut, -((long) RecLength), SEEK_CUR); // move back Start Of Data + + dumpfTell("Data ", -1); + + fseek( fOut, -4, SEEK_CUR); // move back Start Of Address + + dumpfTell("Address ", -1); + + fseek( fOut, -4, SEEK_CUR); // move back Start Of Length + + dumpfTell("Length ", -1); + + binOut32( RecLength ); + + fseek( fOut, RecEnd, SEEK_SET); // move to end of Record + + CheckSum += RecLength; + + CheckSum = ~CheckSum + 1; // Two's complement + + binOut32( CheckSum ); + + if (verbose) + printf("[Created Record of %d Bytes with CheckSum [0x%8X]\n", RecLength, CheckSum); +} + +void binRecOutProgramStart(bit32u Address) +{ + if (Address != (AddressCurrent+1)) + { + binRecEnd(); + binRecStart(Address); + } + AddressCurrent = Address; +} +void binRecOutByte(bit32u Address, bit8u Data) +{ + // If Address is one after Current Address, output Byte + // If not, close out last record, update Length, write checksum + // Then Start New Record, updating Current Address + + if (Address != (AddressCurrent+1)) + { + binRecEnd(); + binRecStart(Address); + } + AddressCurrent = Address; + CheckSum += Data; + binOut8( Data ); +} + +//============================================================================= +// SUPPORT FUNCTIONS +//============================================================================= +int readline(FILE *fil,char *buf,int len) +{ + int rlen; + + rlen=0; + if (len==0) return(0); + while(1) + { + if (cur_len==0) + { + cur_len=fread(buffer, 1, sizeof(buffer), fil); + if (cur_len==0) + { + if (rlen) + { + *buf=0; + return(rlen); + } + return(-1); + } + cur_ptr=buffer; + } + if (cur_len) + { + if (*cur_ptr=='\n') + { + *buf=0; + cur_ptr++; + cur_len--; + return(rlen); + } + else + { + if ((len>1)&&(*cur_ptr!='\r')) + { + *buf++=*cur_ptr++; + len--; + } + else + cur_ptr++; + + rlen++; + cur_len--; + } + } + else + { + *buf=0; + cur_ptr++; + cur_len--; + return(rlen); + } + } +} + + +int SRLerrorout(char *c1,char *c2) +{ + printf("\nERROR: %s - '%s'.",c1,c2); + return(FALSE); +} + + +int checksum(char *cp,int count) +{ + char *scp; + int cksum; + int dum; + + scp=cp; + while(*scp) + { + if (!isxdigit(*scp++)) + return(SRLerrorout("Invalid hex digits",cp)); + } + scp=cp; + + cksum=count; + + while(count) + { + cksum += gh(scp,2); + if (count == 2) + dum = ~cksum; + scp += 2; + count--; + } + cksum&=0x0ff; + // printf("\nCk:%02x",cksum); + return(cksum==0x0ff); +} + +bit32u gh(char *cp,int nibs) +{ + int i; + bit32u j; + + j=0; + + for(i=0;i<nibs;i++) + { + j<<=4; + if ((*cp>='a')&&(*cp<='z')) *cp &= 0x5f; + if ((*cp>='0')&&(*cp<='9')) + j += (*cp-0x30); + else + if ((*cp>='A')&&(*cp<='F')) + j += (*cp-0x37); + else + SRLerrorout("Bad Hex char", cp); + cp++; + } + return(j); +} + + +//============================================================================= +// PROCESS SREC LINE +//============================================================================= + +int srecLine(char *pSrecLine) +{ + char *scp,ch; + int itmp,count,dat; + bit32u adr; + static bit32u RecordCounter=0; + + cur_line++; + scp=pSrecLine; + + if (*pSrecLine!='S') + return(SRLerrorout("Not an Srecord file",scp)); + pSrecLine++; + if (strlen(pSrecLine)<4) + return(SRLerrorout("Srecord too short",scp)); + + ch=*pSrecLine++; + + count=gh(pSrecLine,2); + + pSrecLine += 2; + + // if(debug) + // printf("count %d, strlen(pSrecLine) = %d, pSrecLine =[%s]\n", count, strlen(pSrecLine), pSrecLine); + RecordCounter++; + DispHex(RecordCounter); + + if ((count*2) != strlen(pSrecLine)) return(SRLerrorout("Count field larger than record",scp)); + + if (!checksum(pSrecLine, count)) return(SRLerrorout("Bad Checksum",scp)); + + switch(ch) + { + case '0': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp)); + itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2; + if (itmp) return(SRLerrorout("Srecord 1 address not zero",scp)); + break; + case '1': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp)); + return(SRLerrorout("Srecord Not valid for MIPS",scp)); + break; + case '2': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp)); + return(SRLerrorout("Srecord Not valid for MIPS",scp)); + break; + case '3': if (count<5) return(SRLerrorout("Invalid Srecord count field",scp)); + adr=gh(pSrecLine,8); pSrecLine+=8; count-=4; + count--; + while(count) + { + dat=gh(pSrecLine,2); pSrecLine+=2; count--; + binRecOutByte(adr, (char) (dat & 0xFF)); + adr++; + } + s1s2s3_total++; + break; + case '4': return(SRLerrorout("Invalid Srecord type",scp)); + break; + case '5': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp)); + itmp=gh(pSrecLine,4); pSrecLine+=4; count-=2; + if (itmp|=s1s2s3_total) return(SRLerrorout("Incorrect number of S3 Record processed",scp)); + break; + case '6': return(SRLerrorout("Invalid Srecord type",scp)); + break; + case '7': // PROGRAM START + if (count<5) return(SRLerrorout("Invalid Srecord count field",scp)); + adr=gh(pSrecLine,8); pSrecLine+=8; count-=4; + if (count!=1) return(SRLerrorout("Invalid Srecord count field",scp)); + binRecOutProgramStart(adr); + break; + case '8': if (count<4) return(SRLerrorout("Invalid Srecord count field",scp)); + return(SRLerrorout("Srecord Not valid for MIPS",scp)); + break; + case '9': if (count<3) return(SRLerrorout("Invalid Srecord count field",scp)); + return(SRLerrorout("Srecord Not valid for MIPS",scp)); + break; + default: + break; + } + return(TRUE); +} + + +//============================================================================= +// MAIN LOGIC, READS IN LINE AND OUTPUTS BINARY +//============================================================================= + +int srec2bin(int argc,char *argv[],int verbose) +{ + int i,rlen,sts; + FILE *fp; + char ac; + char buff[256]; + bit32u TAG_BIG = 0xDEADBE42; + bit32u TAG_LITTLE = 0xFEEDFA42; + + bit32u Tag; + + + if(argc < 3) + { + printf("\nError: <srec2bin <srec input file> <bin output file>\n\n"); + return(0); + } + + if (argc > 3) BigEndian=TRUE; else BigEndian=FALSE; + + if (BigEndian) + Tag = TAG_BIG; + else + Tag = TAG_LITTLE; + + if (verbose) + printf("\nEndian: %s, Tag is 0x%8X\n",(BigEndian)?"BIG":"LITTLE", Tag); + + fp = fopen(argv[1],"rt"); + + if (fp==NULL) + { + printf("\nError: Opening input file, %s.", argv[1]); + return(0); + } + + fOut = fopen( argv[2], "wb"); + + if (fOut==NULL) + { + printf("\nError: Opening Output file, %s.", argv[2]); + if(fp) fclose(fp); + return(0); + } + + RecStart = FALSE; + + AddressCurrent = 0xFFFFFFFFL; + + // Setup Tag + + dumpfTell("Tag", Tag); + + binOut32(Tag); + + + inputline=0; + sts=TRUE; + + rlen = readline(fp,buff,sizeof buff); + + while( (sts) && (rlen != -1)) + { + if (strlen(buff)) + { + sts &= srecLine(buff); + WaitDisplay(); + } + rlen = readline(fp,buff,sizeof buff); + } + + + // printf("PC: 0x%08X, Length 0x%08X, Tag 0x%08X\n", ProgramStart, RecLength, TAG_LITTLE); + + binRecEnd(); + + if(fp) fclose(fp); + if(fOut) fclose(fOut); + + return(1); +} + +main(int argc, char *argv[]) +{ + debug = TRUE; + debug = FALSE; + verbose = FALSE; + srec2bin(argc,argv,verbose); + return 0; +} + diff --git a/target/wag54g/uclibc.config b/target/wag54g/uclibc.config new file mode 100644 index 000000000..223c3ddd9 --- /dev/null +++ b/target/wag54g/uclibc.config @@ -0,0 +1,250 @@ +# +# Automatically generated make config: don't edit +# Version: 0.9.30 +# Fri Jan 9 14:41:23 2009 +# +# TARGET_alpha is not set +# TARGET_arm is not set +# TARGET_avr32 is not set +# TARGET_bfin is not set +# TARGET_cris is not set +# TARGET_e1 is not set +# TARGET_frv is not set +# TARGET_h8300 is not set +# TARGET_hppa is not set +# TARGET_i386 is not set +# TARGET_i960 is not set +# TARGET_ia64 is not set +# TARGET_m68k is not set +# TARGET_microblaze is not set +TARGET_mips=y +# TARGET_nios is not set +# TARGET_nios2 is not set +# TARGET_powerpc is not set +# TARGET_sh is not set +# TARGET_sh64 is not set +# TARGET_sparc is not set +# TARGET_v850 is not set +# TARGET_vax is not set +# TARGET_x86_64 is not set +# TARGET_xtensa is not set + +# +# Target Architecture Features and Options +# +TARGET_ARCH="mips" +FORCE_OPTIONS_FOR_ARCH=y +ARCH_CFLAGS="-mno-split-addresses" +# CONFIG_GENERIC_386 is not set +# CONFIG_386 is not set +# CONFIG_486 is not set +# CONFIG_586 is not set +# CONFIG_586MMX is not set +# CONFIG_686 is not set +# CONFIG_PENTIUMII is not set +# CONFIG_PENTIUMIII is not set +# CONFIG_PENTIUM4 is not set +# CONFIG_K6 is not set +# CONFIG_K7 is not set +# CONFIG_ELAN is not set +# CONFIG_CRUSOE is not set +# CONFIG_WINCHIPC6 is not set +# CONFIG_WINCHIP2 is not set +# CONFIG_CYRIXIII is not set +# CONFIG_NEHEMIAH is not set +CONFIG_MIPS_O32_ABI=y +# CONFIG_MIPS_N32_ABI is not set +# CONFIG_MIPS_N64_ABI is not set +# CONFIG_MIPS_ISA_1 is not set +# CONFIG_MIPS_ISA_2 is not set +# CONFIG_MIPS_ISA_3 is not set +# CONFIG_MIPS_ISA_4 is not set +CONFIG_MIPS_ISA_MIPS32=y +# CONFIG_MIPS_ISA_MIPS32R2 is not set +# CONFIG_MIPS_ISA_MIPS64 is not set +TARGET_SUBARCH="" + +# +# Using ELF file format +# +ARCH_ANY_ENDIAN=y +ARCH_LITTLE_ENDIAN=y +# ARCH_WANTS_BIG_ENDIAN is not set +ARCH_WANTS_LITTLE_ENDIAN=y +ARCH_HAS_MMU=y +ARCH_USE_MMU=y +UCLIBC_HAS_FLOATS=y +UCLIBC_HAS_FPU=y +DO_C99_MATH=y +UCLIBC_HAS_FENV=y +KERNEL_HEADERS="" +HAVE_DOT_CONFIG=y + +# +# General Library Settings +# +# HAVE_NO_PIC is not set +DOPIC=y +# ARCH_HAS_NO_SHARED is not set +# ARCH_HAS_NO_LDSO is not set +HAVE_SHARED=y +# FORCE_SHAREABLE_TEXT_SEGMENTS is not set +LDSO_LDD_SUPPORT=y +LDSO_CACHE_SUPPORT=y +# LDSO_PRELOAD_FILE_SUPPORT is not set +LDSO_BASE_FILENAME="ld.so" +# UCLIBC_STATIC_LDCONFIG is not set +LDSO_RUNPATH=y +UCLIBC_CTOR_DTOR=y +# LDSO_GNU_HASH_SUPPORT is not set +# HAS_NO_THREADS is not set +UCLIBC_HAS_THREADS=y +PTHREADS_DEBUG_SUPPORT=y +LINUXTHREADS_OLD=y +UCLIBC_HAS_SYSLOG=y +UCLIBC_HAS_LFS=y +# MALLOC is not set +# MALLOC_SIMPLE is not set +MALLOC_STANDARD=y +MALLOC_GLIBC_COMPAT=y +UCLIBC_DYNAMIC_ATEXIT=y +COMPAT_ATEXIT=y +# UCLIBC_SUSV3_LEGACY is not set +# UCLIBC_SUSV3_LEGACY_MACROS is not set +# UCLIBC_HAS_STUBS is not set +UCLIBC_HAS_SHADOW=y +UCLIBC_HAS_PROGRAM_INVOCATION_NAME=y +UCLIBC_HAS___PROGNAME=y +UCLIBC_HAS_PTY=y +ASSUME_DEVPTS=y +UNIX98PTY_ONLY=y +# UCLIBC_HAS_GETPT is not set +UCLIBC_HAS_TM_EXTENSIONS=y +UCLIBC_HAS_TZ_CACHING=y +UCLIBC_HAS_TZ_FILE=y +UCLIBC_HAS_TZ_FILE_READ_MANY=y +UCLIBC_TZ_FILE_PATH="/etc/TZ" + +# +# Advanced Library Settings +# +UCLIBC_PWD_BUFFER_SIZE=256 +UCLIBC_GRP_BUFFER_SIZE=256 + +# +# Support various families of functions +# +# UCLIBC_LINUX_MODULE_24 is not set +UCLIBC_LINUX_SPECIFIC=y +UCLIBC_HAS_GNU_ERROR=y +UCLIBC_BSD_SPECIFIC=y +UCLIBC_HAS_BSD_ERR=y +# UCLIBC_HAS_OBSOLETE_BSD_SIGNAL is not set +# UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL is not set +# UCLIBC_NTP_LEGACY is not set +# UCLIBC_SV4_DEPRECATED is not set +UCLIBC_HAS_REALTIME=y +# UCLIBC_HAS_ADVANCED_REALTIME is not set +UCLIBC_HAS_EPOLL=y +UCLIBC_HAS_XATTR=y +# UCLIBC_HAS_PROFILING is not set +UCLIBC_HAS_CRYPT_IMPL=y +UCLIBC_HAS_CRYPT=y +UCLIBC_HAS_NETWORK_SUPPORT=y +UCLIBC_HAS_SOCKET=y +UCLIBC_HAS_IPV4=y +# UCLIBC_HAS_IPV6 is not set +UCLIBC_HAS_RPC=y +UCLIBC_HAS_FULL_RPC=y +UCLIBC_HAS_REENTRANT_RPC=y +UCLIBC_USE_NETLINK=y +UCLIBC_SUPPORT_AI_ADDRCONFIG=y +UCLIBC_HAS_BSD_RES_CLOSE=y + +# +# String and Stdio Support +# +UCLIBC_HAS_STRING_GENERIC_OPT=y +UCLIBC_HAS_STRING_ARCH_OPT=y +UCLIBC_HAS_CTYPE_TABLES=y +UCLIBC_HAS_CTYPE_SIGNED=y +# UCLIBC_HAS_CTYPE_UNSAFE is not set +UCLIBC_HAS_CTYPE_CHECKED=y +# UCLIBC_HAS_CTYPE_ENFORCED is not set +UCLIBC_HAS_WCHAR=y +# UCLIBC_HAS_LOCALE is not set +UCLIBC_HAS_HEXADECIMAL_FLOATS=y +UCLIBC_HAS_GLIBC_CUSTOM_PRINTF=y +UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS=9 +UCLIBC_HAS_SCANF_GLIBC_A_FLAG=y +# UCLIBC_HAS_STDIO_BUFSIZ_NONE is not set +# UCLIBC_HAS_STDIO_BUFSIZ_256 is not set +# UCLIBC_HAS_STDIO_BUFSIZ_512 is not set +# UCLIBC_HAS_STDIO_BUFSIZ_1024 is not set +# UCLIBC_HAS_STDIO_BUFSIZ_2048 is not set +UCLIBC_HAS_STDIO_BUFSIZ_4096=y +# UCLIBC_HAS_STDIO_BUFSIZ_8192 is not set +UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE=y +# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4 is not set +# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8 is not set +# UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT is not set +UCLIBC_HAS_STDIO_GETC_MACRO=y +UCLIBC_HAS_STDIO_PUTC_MACRO=y +UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION=y +# UCLIBC_HAS_FOPEN_LARGEFILE_MODE is not set +UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE=y +UCLIBC_HAS_GLIBC_CUSTOM_STREAMS=y +UCLIBC_HAS_PRINTF_M_SPEC=y +UCLIBC_HAS_ERRNO_MESSAGES=y +# UCLIBC_HAS_SYS_ERRLIST is not set +UCLIBC_HAS_SIGNUM_MESSAGES=y +# UCLIBC_HAS_SYS_SIGLIST is not set +UCLIBC_HAS_GNU_GETOPT=y +UCLIBC_HAS_GNU_GETSUBOPT=y + +# +# Big and Tall +# +UCLIBC_HAS_REGEX=y +UCLIBC_HAS_REGEX_OLD=y +UCLIBC_HAS_FNMATCH=y +UCLIBC_HAS_FNMATCH_OLD=y +UCLIBC_HAS_WORDEXP=y +UCLIBC_HAS_FTW=y +UCLIBC_HAS_GLOB=y +UCLIBC_HAS_GNU_GLOB=y + +# +# Library Installation Options +# +SHARED_LIB_LOADER_PREFIX="/lib" +RUNTIME_PREFIX="/" +DEVEL_PREFIX="/usr/" + +# +# Security options +# +# UCLIBC_BUILD_PIE is not set +UCLIBC_HAS_ARC4RANDOM=y +# HAVE_NO_SSP is not set +# UCLIBC_HAS_SSP is not set +UCLIBC_BUILD_RELRO=y +# UCLIBC_BUILD_NOW is not set +UCLIBC_BUILD_NOEXECSTACK=y + +# +# uClibc development/debugging options +# +CROSS_COMPILER_PREFIX="" +UCLIBC_EXTRA_CFLAGS="" +# DODEBUG is not set +# DODEBUG_PT is not set +DOSTRIP=y +# DOASSERTS is not set +# SUPPORT_LD_DEBUG is not set +# SUPPORT_LD_DEBUG_EARLY is not set +# UCLIBC_MALLOC_DEBUGGING is not set +WARNINGS="-Wall" +EXTRA_WARNINGS=y +# DOMULTI is not set +# UCLIBC_MJN3_ONLY is not set |