diff options
Diffstat (limited to 'target/linux')
23 files changed, 27732 insertions, 54 deletions
diff --git a/target/linux/config/Config.in.flash b/target/linux/config/Config.in.flash index 91cfc9140..4d9bf6828 100644 --- a/target/linux/config/Config.in.flash +++ b/target/linux/config/Config.in.flash @@ -19,6 +19,13 @@ config ADK_KERNEL_MTD_BLOCK config ADK_KERNEL_MTD_PARTITIONS boolean +config ADK_KERNEL_MTD_REDBOOT_PARTS + boolean + +config ADK_KERNEL_MTD_REDBOOT_DIRECTORY_BLOCK + int + default "-3" + config ADK_KERNEL_MTD_ROOTFS_ROOT_DEV boolean @@ -31,6 +38,9 @@ config ADK_KERNEL_MTD_GEN_PROBE config ADK_KERNEL_MTD_PHYSMAP boolean +config ADK_KERNEL_MTD_CFI_ADV_OPTIONS + boolean + config ADK_KERNEL_MTD_NAND_RB4XX boolean default y if ADK_TARGET_SYSTEM_MIKROTIK_RB411 @@ -47,6 +57,13 @@ config ADK_KERNEL_MTD_CFI_INTELEXT default y if ADK_TARGET_SYSTEM_BROADCOM_BCM47XX default n +config ADK_KERNEL_MTD_AR2315 + boolean + select ADK_KERNEL_MTD_REDBOOT_PARTS + select ADK_KERNEL_MTD_CFI_ADV_OPTIONS + default y if ADK_TARGET_SYSTEM_FON_FON2100 + default n + config ADK_TARGET_NAND boolean select ADK_KERNEL_MISC_FILESYSTEMS diff --git a/target/linux/config/Config.in.fs b/target/linux/config/Config.in.fs index a895225f0..ede84a73a 100644 --- a/target/linux/config/Config.in.fs +++ b/target/linux/config/Config.in.fs @@ -1,5 +1,8 @@ menu "Filesystems support" +config ADK_KERNEL_EXPORTFS + boolean + config ADK_KERNEL_YAFFS_FS tristate @@ -36,12 +39,6 @@ config ADK_KERNEL_FAT_DEFAULT_IOCHARSET string default "iso8859-1" -config ADK_KPACKAGE_KMOD_EXPORTFS - tristate - depends on !ADK_KERNEL_EXPORTFS - default n - help - config ADK_KERNEL_SQUASHFS prompt ".................................. SquashFS filesystem" boolean @@ -177,9 +174,6 @@ config ADK_KPACKAGE_KMOD_VFAT_FS The VFAT support enlarges your kernel by about 10 KB Please read the file <file:Documentation/filesystems/vfat.txt> for details. -config ADK_KERNEL_EXPORTFS - boolean - default n config ADK_KERNEL_XFS_FS boolean @@ -189,7 +183,7 @@ config ADK_KERNEL_XFS_FS config ADK_KPACKAGE_KMOD_XFS_FS prompt "kmod-fs-xfs....................... XFS filesystem support" tristate - select ADK_KPACKAGE_KMOD_EXPORTFS + select ADK_KERNEL_EXPORTFS depends on !ADK_KERNEL_XFS_FS default n help diff --git a/target/linux/config/Config.in.fsnet b/target/linux/config/Config.in.fsnet index 756ffaa18..301a988f2 100644 --- a/target/linux/config/Config.in.fsnet +++ b/target/linux/config/Config.in.fsnet @@ -102,7 +102,7 @@ config ADK_KPACKAGE_KMOD_NFSD prompt "kmod-fs-nfsd...................... NFS server support (includes V3 support)" tristate default n - select ADK_KPACKAGE_KMOD_EXPORTFS if !ADK_KERNEL_EXPORTFS + select ADK_KERNEL_EXPORTFS select ADK_KERNEL_NFSD_V3 select ADK_KERNEL_NFSD_V4 select ADK_KERNEL_DNOTIFY diff --git a/target/linux/config/Config.in.graphics b/target/linux/config/Config.in.graphics index 1aafdf85f..00c06eb8b 100644 --- a/target/linux/config/Config.in.graphics +++ b/target/linux/config/Config.in.graphics @@ -42,6 +42,7 @@ config ADK_KERNEL_AGP_INTEL boolean menu "Graphic devices support" +depends on ADK_TARGET_WITH_VGA config ADK_KERNEL_FB_GEODE_LX prompt "................................ Framebuffer support for ALIX boards with VGA" diff --git a/target/linux/config/Config.in.mips b/target/linux/config/Config.in.mips index 0b0d1ea4f..2d9a2e661 100644 --- a/target/linux/config/Config.in.mips +++ b/target/linux/config/Config.in.mips @@ -1,4 +1,5 @@ menu "MIPS devices support" +depends on ADK_TARGET_SYSTEM_LEMOTE_YEELONG config ADK_KERNEL_MIPS_PLATFORM_DEVICES boolean diff --git a/target/linux/config/Config.in.netdevice b/target/linux/config/Config.in.netdevice index 590a466c4..b45e17ccd 100644 --- a/target/linux/config/Config.in.netdevice +++ b/target/linux/config/Config.in.netdevice @@ -308,7 +308,7 @@ config ADK_DEBUG_MAC80211 select ADK_KERNEL_DEBUG_FS menu "Wireless card support" -depends on ADK_TARGET_WITH_MINIPCI || ADK_TARGET_WITH_PCI || ADK_TARGET_WITH_USB || ADK_TARGET_WITH_SSB +depends on ADK_TARGET_WITH_MINIPCI || ADK_TARGET_WITH_PCI || ADK_TARGET_WITH_USB || ADK_TARGET_WITH_SSB || ADK_TARGET_WITH_AHB config ADK_KPACKAGE_KMOD_ATH5K prompt "kmod-ath5k................... Atheros 5xxx wireless cards" @@ -316,8 +316,9 @@ config ADK_KPACKAGE_KMOD_ATH5K select ADK_KERNEL_MAC80211_LEDS select ADK_KERNEL_ATH_COMMON select ADK_KPACKAGE_KMOD_MAC80211 - depends on ADK_TARGET_WITH_MINIPCI || ADK_TARGET_WITH_PCI + depends on ADK_TARGET_WITH_MINIPCI || ADK_TARGET_WITH_PCI || ADK_TARGET_WITH_AHB default y if ADK_TARGET_SYSTEM_IBM_X40 + default y if ADK_TARGET_SYSTEM_FON_FON2100 default n help Driver for Atheros 5xxx/24xx cards. diff --git a/target/linux/config/Config.in.pm b/target/linux/config/Config.in.pm index 45bf12f37..2f90df20c 100644 --- a/target/linux/config/Config.in.pm +++ b/target/linux/config/Config.in.pm @@ -23,6 +23,7 @@ config ADK_KERNEL_ACPI_DOCK boolean menu "Power Management support" +depends on ADK_TARGET_WITH_ACPI config ADK_HARDWARE_ACPI prompt "Enable ACPI support" diff --git a/target/linux/config/Config.in.systems b/target/linux/config/Config.in.systems index d744e45a1..8750ac281 100644 --- a/target/linux/config/Config.in.systems +++ b/target/linux/config/Config.in.systems @@ -34,8 +34,14 @@ config ADK_KERNEL_ARCH_AT91 config ADK_KERNEL_ARCH_AT91SAM9G20 boolean -config ADK_KERNEL_MACH_FOXG20 +config ADK_KERNEL_MACH_ACMENETUSFOXG20 boolean config ADK_KERNEL_AEABI boolean + +config ADK_KERNEL_CPU_BIG_ENDIAN + boolean + +config ADK_KERNEL_CPU_LITTLE_ENDIAN + boolean diff --git a/target/linux/config/Config.in.usb b/target/linux/config/Config.in.usb index b1375ac05..2be0c4f31 100644 --- a/target/linux/config/Config.in.usb +++ b/target/linux/config/Config.in.usb @@ -30,6 +30,7 @@ config ADK_KPACKAGE_KMOD_USB tristate select ADK_KERNEL_NLS depends on !ADK_KERNEL_USB + #depends on !ADK_TARGET_SYSTEM_ACMESYSTEMS_FOXG20 default y if ADK_TARGET_SYSTEM_PCENGINES_ALIX1C default y if ADK_TARGET_SYSTEM_PCENGINES_ALIX2D2 default y if ADK_TARGET_SYSTEM_PCENGINES_ALIX2D13 @@ -93,12 +94,13 @@ config ADK_KPACKAGE_KMOD_USB_OHCI_HCD tristate select ADK_PACKAGE_KMOD_USB_CONTROLLER depends on ADK_KPACKAGE_KMOD_USB - depends on !ADK_TARGET_SYSTEM_ACMESYSTEMS_FOXG20 + #depends on !ADK_TARGET_SYSTEM_ACMESYSTEMS_FOXG20 depends on !ADK_TARGET_SYSTEM_FOXBOARD_LX832 depends on !ADK_TARGET_SYSTEM_FOXBOARD_LX416 default y if ADK_TARGET_SYSTEM_PCENGINES_ALIX1C default y if ADK_TARGET_SYSTEM_PCENGINES_ALIX2D2 default y if ADK_TARGET_SYSTEM_PCENGINES_ALIX2D13 + default y if ADK_TARGET_SYSTEM_ACMESYSTEMS_FOXG20 default n help The Open Host Controller Interface (OHCI) is a standard for accessing diff --git a/target/linux/patches/2.6.37/atheros.patch b/target/linux/patches/2.6.37/atheros.patch index ee5184a00..d67bf0824 100644 --- a/target/linux/patches/2.6.37/atheros.patch +++ b/target/linux/patches/2.6.37/atheros.patch @@ -1,6 +1,6 @@ diff -Nur linux-2.6.37.orig/arch/mips/Kbuild.platforms linux-2.6.37/arch/mips/Kbuild.platforms --- linux-2.6.37.orig/arch/mips/Kbuild.platforms 2011-01-05 01:50:19.000000000 +0100 -+++ linux-2.6.37/arch/mips/Kbuild.platforms 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/Kbuild.platforms 2011-05-15 19:24:57.000000000 +0200 @@ -5,6 +5,7 @@ platforms += bcm47xx platforms += bcm63xx @@ -11,7 +11,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/Kbuild.platforms linux-2.6.37/arch/mips/Kb platforms += emma diff -Nur linux-2.6.37.orig/arch/mips/Kconfig linux-2.6.37/arch/mips/Kconfig --- linux-2.6.37.orig/arch/mips/Kconfig 2011-01-05 01:50:19.000000000 +0100 -+++ linux-2.6.37/arch/mips/Kconfig 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/Kconfig 2011-05-15 19:24:57.000000000 +0200 @@ -102,6 +102,20 @@ help Support for BCM63XX based boards @@ -43,7 +43,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/Kconfig linux-2.6.37/arch/mips/Kconfig source "arch/mips/jazz/Kconfig" diff -Nur linux-2.6.37.orig/arch/mips/ar231x/Kconfig linux-2.6.37/arch/mips/ar231x/Kconfig --- linux-2.6.37.orig/arch/mips/ar231x/Kconfig 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/ar231x/Kconfig 2011-04-12 08:12:33.000000000 +0200 ++++ linux-2.6.37/arch/mips/ar231x/Kconfig 2011-05-15 19:25:40.000000000 +0200 @@ -0,0 +1,27 @@ +config ATHEROS_AR5312 + bool "Atheros 5312/2312+ support" @@ -71,10 +71,10 @@ diff -Nur linux-2.6.37.orig/arch/mips/ar231x/Kconfig linux-2.6.37/arch/mips/ar23 + select USB_ARCH_HAS_HCD + select USB_ARCH_HAS_OHCI + select USB_ARCH_HAS_EHCI -+ default y ++ default n diff -Nur linux-2.6.37.orig/arch/mips/ar231x/Makefile linux-2.6.37/arch/mips/ar231x/Makefile --- linux-2.6.37.orig/arch/mips/ar231x/Makefile 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/ar231x/Makefile 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/ar231x/Makefile 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,17 @@ +# +# This file is subject to the terms and conditions of the GNU General Public @@ -95,7 +95,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/ar231x/Makefile linux-2.6.37/arch/mips/ar2 +obj-$(CONFIG_ATHEROS_AR2315_PCI) += pci.o diff -Nur linux-2.6.37.orig/arch/mips/ar231x/Platform linux-2.6.37/arch/mips/ar231x/Platform --- linux-2.6.37.orig/arch/mips/ar231x/Platform 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/ar231x/Platform 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/ar231x/Platform 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,6 @@ +# +# Atheros AR5312/AR2312 WiSoC @@ -105,7 +105,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/ar231x/Platform linux-2.6.37/arch/mips/ar2 +load-$(CONFIG_ATHEROS_AR231X) += 0xffffffff80041000 diff -Nur linux-2.6.37.orig/arch/mips/ar231x/ar2315.c linux-2.6.37/arch/mips/ar231x/ar2315.c --- linux-2.6.37.orig/arch/mips/ar231x/ar2315.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/ar231x/ar2315.c 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/ar231x/ar2315.c 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,683 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -792,7 +792,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/ar231x/ar2315.c linux-2.6.37/arch/mips/ar2 +} diff -Nur linux-2.6.37.orig/arch/mips/ar231x/ar2315.h linux-2.6.37/arch/mips/ar231x/ar2315.h --- linux-2.6.37.orig/arch/mips/ar231x/ar2315.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/ar231x/ar2315.h 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/ar231x/ar2315.h 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,37 @@ +#ifndef __AR2315_H +#define __AR2315_H @@ -833,7 +833,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/ar231x/ar2315.h linux-2.6.37/arch/mips/ar2 +#endif diff -Nur linux-2.6.37.orig/arch/mips/ar231x/ar5312.c linux-2.6.37/arch/mips/ar231x/ar5312.c --- linux-2.6.37.orig/arch/mips/ar231x/ar5312.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/ar231x/ar5312.c 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/ar231x/ar5312.c 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,549 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -1386,7 +1386,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/ar231x/ar5312.c linux-2.6.37/arch/mips/ar2 + diff -Nur linux-2.6.37.orig/arch/mips/ar231x/ar5312.h linux-2.6.37/arch/mips/ar231x/ar5312.h --- linux-2.6.37.orig/arch/mips/ar231x/ar5312.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/ar231x/ar5312.h 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/ar231x/ar5312.h 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,38 @@ +#ifndef __AR5312_H +#define __AR5312_H @@ -1428,7 +1428,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/ar231x/ar5312.h linux-2.6.37/arch/mips/ar2 +#endif diff -Nur linux-2.6.37.orig/arch/mips/ar231x/board.c linux-2.6.37/arch/mips/ar231x/board.c --- linux-2.6.37.orig/arch/mips/ar231x/board.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/ar231x/board.c 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/ar231x/board.c 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,251 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -1683,7 +1683,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/ar231x/board.c linux-2.6.37/arch/mips/ar23 + diff -Nur linux-2.6.37.orig/arch/mips/ar231x/devices.c linux-2.6.37/arch/mips/ar231x/devices.c --- linux-2.6.37.orig/arch/mips/ar231x/devices.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/ar231x/devices.c 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/ar231x/devices.c 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,175 @@ +#include <linux/kernel.h> +#include <linux/init.h> @@ -1862,7 +1862,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/ar231x/devices.c linux-2.6.37/arch/mips/ar +device_initcall(ar231x_register_devices); diff -Nur linux-2.6.37.orig/arch/mips/ar231x/devices.h linux-2.6.37/arch/mips/ar231x/devices.h --- linux-2.6.37.orig/arch/mips/ar231x/devices.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/ar231x/devices.h 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/ar231x/devices.h 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,37 @@ +#ifndef __AR231X_DEVICES_H +#define __AR231X_DEVICES_H @@ -1903,7 +1903,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/ar231x/devices.h linux-2.6.37/arch/mips/ar +#endif diff -Nur linux-2.6.37.orig/arch/mips/ar231x/early_printk.c linux-2.6.37/arch/mips/ar231x/early_printk.c --- linux-2.6.37.orig/arch/mips/ar231x/early_printk.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/ar231x/early_printk.c 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/ar231x/early_printk.c 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,44 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -1951,7 +1951,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/ar231x/early_printk.c linux-2.6.37/arch/mi + diff -Nur linux-2.6.37.orig/arch/mips/ar231x/pci.c linux-2.6.37/arch/mips/ar231x/pci.c --- linux-2.6.37.orig/arch/mips/ar231x/pci.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/ar231x/pci.c 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/ar231x/pci.c 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,230 @@ +/* + * This program is free software; you can redistribute it and/or @@ -2185,7 +2185,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/ar231x/pci.c linux-2.6.37/arch/mips/ar231x +arch_initcall(ar2315_pci_init); diff -Nur linux-2.6.37.orig/arch/mips/ar231x/prom.c linux-2.6.37/arch/mips/ar231x/prom.c --- linux-2.6.37.orig/arch/mips/ar231x/prom.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/ar231x/prom.c 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/ar231x/prom.c 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,37 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -2226,7 +2226,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/ar231x/prom.c linux-2.6.37/arch/mips/ar231 +} diff -Nur linux-2.6.37.orig/arch/mips/ar231x/reset.c linux-2.6.37/arch/mips/ar231x/reset.c --- linux-2.6.37.orig/arch/mips/ar231x/reset.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/ar231x/reset.c 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/ar231x/reset.c 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,161 @@ +#include <linux/init.h> +#include <linux/module.h> @@ -2391,7 +2391,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/ar231x/reset.c linux-2.6.37/arch/mips/ar23 +module_init(ar231x_init_reset); diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar2315_regs.h linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar2315_regs.h --- linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar2315_regs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar2315_regs.h 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar2315_regs.h 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,580 @@ +/* + * Register definitions for AR2315+ @@ -2975,7 +2975,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar2315_regs.h linu +#endif /* __AR2315_REG_H */ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar2315_spiflash.h linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar2315_spiflash.h --- linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar2315_spiflash.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar2315_spiflash.h 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar2315_spiflash.h 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,116 @@ +/* + * SPI Flash Memory support header file. @@ -3095,7 +3095,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar2315_spiflash.h +#endif diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar231x.h linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar231x.h --- linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar231x.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar231x.h 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar231x.h 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,54 @@ +#ifndef __AR531X_H +#define __AR531X_H @@ -3153,7 +3153,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar231x.h linux-2.6 +#endif diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar231x_platform.h linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar231x_platform.h --- linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar231x_platform.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar231x_platform.h 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar231x_platform.h 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,83 @@ +#ifndef __AR531X_PLATFORM_H +#define __AR531X_PLATFORM_H @@ -3240,7 +3240,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar231x_platform.h +#endif /* __AR531X_PLATFORM_H */ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar5312_regs.h linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar5312_regs.h --- linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar5312_regs.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar5312_regs.h 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/ar5312_regs.h 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,236 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -3480,7 +3480,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/ar5312_regs.h linu + diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/cpu-feature-overrides.h linux-2.6.37/arch/mips/include/asm/mach-ar231x/cpu-feature-overrides.h --- linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/cpu-feature-overrides.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/cpu-feature-overrides.h 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/cpu-feature-overrides.h 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,84 @@ +/* + * Atheros SoC specific CPU feature overrides @@ -3568,7 +3568,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/cpu-feature-overri +#endif /* __ASM_MACH_ATHEROS_CPU_FEATURE_OVERRIDES_H */ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/dma-coherence.h linux-2.6.37/arch/mips/include/asm/mach-ar231x/dma-coherence.h --- linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/dma-coherence.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/dma-coherence.h 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/dma-coherence.h 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,64 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -3636,7 +3636,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/dma-coherence.h li +#endif /* __ASM_MACH_GENERIC_DMA_COHERENCE_H */ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/gpio.h linux-2.6.37/arch/mips/include/asm/mach-ar231x/gpio.h --- linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/gpio.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/gpio.h 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/gpio.h 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,84 @@ +#ifndef _ATHEROS_GPIO_H_ +#define _ATHEROS_GPIO_H_ @@ -3724,7 +3724,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/gpio.h linux-2.6.3 +#endif diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/reset.h linux-2.6.37/arch/mips/include/asm/mach-ar231x/reset.h --- linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/reset.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/reset.h 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/reset.h 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,6 @@ +#ifndef __AR531X_RESET_H +#define __AR531X_RESET_H @@ -3734,7 +3734,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/reset.h linux-2.6. +#endif /* __AR531X_RESET_H */ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/war.h linux-2.6.37/arch/mips/include/asm/mach-ar231x/war.h --- linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/war.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/war.h 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/include/asm/mach-ar231x/war.h 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public @@ -3763,7 +3763,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/include/asm/mach-ar231x/war.h linux-2.6.37 +#endif /* __ASM_MIPS_MACH_ATHEROS_WAR_H */ diff -Nur linux-2.6.37.orig/arch/mips/kernel/cevt-r4k.c linux-2.6.37/arch/mips/kernel/cevt-r4k.c --- linux-2.6.37.orig/arch/mips/kernel/cevt-r4k.c 2011-01-05 01:50:19.000000000 +0100 -+++ linux-2.6.37/arch/mips/kernel/cevt-r4k.c 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/arch/mips/kernel/cevt-r4k.c 2011-05-15 19:24:57.000000000 +0200 @@ -168,20 +168,23 @@ struct clock_event_device *cd; unsigned int irq; @@ -3797,7 +3797,7 @@ diff -Nur linux-2.6.37.orig/arch/mips/kernel/cevt-r4k.c linux-2.6.37/arch/mips/k diff -Nur linux-2.6.37.orig/drivers/mtd/devices/Kconfig linux-2.6.37/drivers/mtd/devices/Kconfig --- linux-2.6.37.orig/drivers/mtd/devices/Kconfig 2011-01-05 01:50:19.000000000 +0100 -+++ linux-2.6.37/drivers/mtd/devices/Kconfig 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/drivers/mtd/devices/Kconfig 2011-05-15 19:24:57.000000000 +0200 @@ -112,6 +112,10 @@ Set up your spi devices with the right board-specific platform data, if you want to specify device partitioning. @@ -3811,7 +3811,7 @@ diff -Nur linux-2.6.37.orig/drivers/mtd/devices/Kconfig linux-2.6.37/drivers/mtd help diff -Nur linux-2.6.37.orig/drivers/mtd/devices/Makefile linux-2.6.37/drivers/mtd/devices/Makefile --- linux-2.6.37.orig/drivers/mtd/devices/Makefile 2011-01-05 01:50:19.000000000 +0100 -+++ linux-2.6.37/drivers/mtd/devices/Makefile 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/drivers/mtd/devices/Makefile 2011-05-15 19:24:57.000000000 +0200 @@ -17,3 +17,4 @@ obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o obj-$(CONFIG_MTD_M25P80) += m25p80.o @@ -3819,7 +3819,7 @@ diff -Nur linux-2.6.37.orig/drivers/mtd/devices/Makefile linux-2.6.37/drivers/mt +obj-$(CONFIG_MTD_AR2315) += ar2315.o diff -Nur linux-2.6.37.orig/drivers/mtd/devices/ar2315.c linux-2.6.37/drivers/mtd/devices/ar2315.c --- linux-2.6.37.orig/drivers/mtd/devices/ar2315.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/drivers/mtd/devices/ar2315.c 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/drivers/mtd/devices/ar2315.c 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,517 @@ + +/* @@ -4340,7 +4340,7 @@ diff -Nur linux-2.6.37.orig/drivers/mtd/devices/ar2315.c linux-2.6.37/drivers/mt + diff -Nur linux-2.6.37.orig/drivers/mtd/redboot.c linux-2.6.37/drivers/mtd/redboot.c --- linux-2.6.37.orig/drivers/mtd/redboot.c 2011-01-05 01:50:19.000000000 +0100 -+++ linux-2.6.37/drivers/mtd/redboot.c 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/drivers/mtd/redboot.c 2011-05-15 19:24:57.000000000 +0200 @@ -55,6 +55,22 @@ return 1; } @@ -4435,7 +4435,7 @@ diff -Nur linux-2.6.37.orig/drivers/mtd/redboot.c linux-2.6.37/drivers/mtd/redbo if (buf[i].name[0] == 0xff) { diff -Nur linux-2.6.37.orig/drivers/net/Kconfig linux-2.6.37/drivers/net/Kconfig --- linux-2.6.37.orig/drivers/net/Kconfig 2011-01-05 01:50:19.000000000 +0100 -+++ linux-2.6.37/drivers/net/Kconfig 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/drivers/net/Kconfig 2011-05-15 19:24:57.000000000 +0200 @@ -251,6 +251,12 @@ help Select this if your platform comes with an external 93CX6 eeprom. @@ -4451,7 +4451,7 @@ diff -Nur linux-2.6.37.orig/drivers/net/Kconfig linux-2.6.37/drivers/net/Kconfig depends on PPC_PMAC && PPC32 diff -Nur linux-2.6.37.orig/drivers/net/Makefile linux-2.6.37/drivers/net/Makefile --- linux-2.6.37.orig/drivers/net/Makefile 2011-01-05 01:50:19.000000000 +0100 -+++ linux-2.6.37/drivers/net/Makefile 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/drivers/net/Makefile 2011-05-15 19:24:57.000000000 +0200 @@ -224,6 +224,7 @@ obj-$(CONFIG_KORINA) += korina.o obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o @@ -4462,7 +4462,7 @@ diff -Nur linux-2.6.37.orig/drivers/net/Makefile linux-2.6.37/drivers/net/Makefi obj-$(CONFIG_DECLANCE) += declance.o diff -Nur linux-2.6.37.orig/drivers/net/ar231x.c linux-2.6.37/drivers/net/ar231x.c --- linux-2.6.37.orig/drivers/net/ar231x.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/drivers/net/ar231x.c 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/drivers/net/ar231x.c 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,1327 @@ +/* + * ar231x.c: Linux driver for the Atheros AR231x Ethernet device. @@ -5793,7 +5793,7 @@ diff -Nur linux-2.6.37.orig/drivers/net/ar231x.c linux-2.6.37/drivers/net/ar231x + diff -Nur linux-2.6.37.orig/drivers/net/ar231x.h linux-2.6.37/drivers/net/ar231x.h --- linux-2.6.37.orig/drivers/net/ar231x.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/drivers/net/ar231x.h 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/drivers/net/ar231x.h 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,304 @@ +/* + * ar231x.h: Linux driver for the Atheros AR231x Ethernet device. @@ -6101,7 +6101,7 @@ diff -Nur linux-2.6.37.orig/drivers/net/ar231x.h linux-2.6.37/drivers/net/ar231x +#endif /* _AR2313_H_ */ diff -Nur linux-2.6.37.orig/drivers/watchdog/Kconfig linux-2.6.37/drivers/watchdog/Kconfig --- linux-2.6.37.orig/drivers/watchdog/Kconfig 2011-01-05 01:50:19.000000000 +0100 -+++ linux-2.6.37/drivers/watchdog/Kconfig 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/drivers/watchdog/Kconfig 2011-05-15 19:24:57.000000000 +0200 @@ -930,6 +930,12 @@ To compile this driver as a loadable module, choose M here. The module will be called bcm63xx_wdt. @@ -6117,7 +6117,7 @@ diff -Nur linux-2.6.37.orig/drivers/watchdog/Kconfig linux-2.6.37/drivers/watchd # POWERPC Architecture diff -Nur linux-2.6.37.orig/drivers/watchdog/Makefile linux-2.6.37/drivers/watchdog/Makefile --- linux-2.6.37.orig/drivers/watchdog/Makefile 2011-01-05 01:50:19.000000000 +0100 -+++ linux-2.6.37/drivers/watchdog/Makefile 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/drivers/watchdog/Makefile 2011-05-15 19:24:57.000000000 +0200 @@ -116,6 +116,7 @@ obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o @@ -6128,7 +6128,7 @@ diff -Nur linux-2.6.37.orig/drivers/watchdog/Makefile linux-2.6.37/drivers/watch octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o diff -Nur linux-2.6.37.orig/drivers/watchdog/ar2315-wtd.c linux-2.6.37/drivers/watchdog/ar2315-wtd.c --- linux-2.6.37.orig/drivers/watchdog/ar2315-wtd.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.37/drivers/watchdog/ar2315-wtd.c 2011-04-12 08:12:01.000000000 +0200 ++++ linux-2.6.37/drivers/watchdog/ar2315-wtd.c 2011-05-15 19:24:57.000000000 +0200 @@ -0,0 +1,200 @@ +/* + * This program is free software; you can redistribute it and/or modify diff --git a/target/linux/patches/2.6.39/arm-statcmd.patch b/target/linux/patches/2.6.39/arm-statcmd.patch new file mode 100644 index 000000000..3aed60cbc --- /dev/null +++ b/target/linux/patches/2.6.39/arm-statcmd.patch @@ -0,0 +1,12 @@ +diff -Nur linux-2.6.39-rc6.orig/arch/arm/boot/compressed/Makefile linux-2.6.39-rc6/arch/arm/boot/compressed/Makefile +--- linux-2.6.39-rc6.orig/arch/arm/boot/compressed/Makefile 2011-05-04 04:59:13.000000000 +0200 ++++ linux-2.6.39-rc6/arch/arm/boot/compressed/Makefile 2011-05-10 10:35:34.000000000 +0200 +@@ -99,7 +99,7 @@ + asflags-y := -Wa,-march=all + + # Provide size of uncompressed kernel to the decompressor via a linker symbol. +-LDFLAGS_vmlinux = --defsym _image_size=$(shell stat -c "%s" $(obj)/../Image) ++LDFLAGS_vmlinux = --defsym _image_size=$(shell if stat -qs .>/dev/null 2>&1;then statcmd='stat -f %z';else statcmd='stat -c %s';fi; $$statcmd "%s" $(obj)/../Image) + # Supply ZRELADDR to the decompressor via a linker symbol. + ifneq ($(CONFIG_AUTO_ZRELADDR),y) + LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR) diff --git a/target/linux/patches/2.6.39/bsd-compatibility.patch b/target/linux/patches/2.6.39/bsd-compatibility.patch new file mode 100644 index 000000000..9e91a62de --- /dev/null +++ b/target/linux/patches/2.6.39/bsd-compatibility.patch @@ -0,0 +1,2512 @@ +diff -Nur linux-2.6.36.orig/scripts/Makefile.lib linux-2.6.36/scripts/Makefile.lib +--- linux-2.6.36.orig/scripts/Makefile.lib 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36/scripts/Makefile.lib 2010-11-28 18:34:22.000000000 +0100 +@@ -216,7 +216,12 @@ + size_append = printf $(shell \ + dec_size=0; \ + for F in $1; do \ +- fsize=$$(stat -c "%s" $$F); \ ++ if stat -qs .>/dev/null 2>&1; then \ ++ statcmd='stat -f %z'; \ ++ else \ ++ statcmd='stat -c %s'; \ ++ fi; \ ++ fsize=$$($$statcmd $$F); \ + dec_size=$$(expr $$dec_size + $$fsize); \ + done; \ + printf "%08x\n" $$dec_size | \ +diff -Nur linux-2.6.36.orig/scripts/mod/mk_elfconfig.c linux-2.6.36/scripts/mod/mk_elfconfig.c +--- linux-2.6.36.orig/scripts/mod/mk_elfconfig.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36/scripts/mod/mk_elfconfig.c 2010-11-28 18:33:24.000000000 +0100 +@@ -1,7 +1,18 @@ + #include <stdio.h> + #include <stdlib.h> + #include <string.h> +-#include <elf.h> ++ ++#define EI_NIDENT (16) ++#define ELFMAG "\177ELF" ++ ++#define SELFMAG 4 ++#define EI_CLASS 4 ++#define ELFCLASS32 1 /* 32-bit objects */ ++#define ELFCLASS64 2 /* 64-bit objects */ ++ ++#define EI_DATA 5 /* Data encoding byte index */ ++#define ELFDATA2LSB 1 /* 2's complement, little endian */ ++#define ELFDATA2MSB 2 /* 2's complement, big endian */ + + int + main(int argc, char **argv) +diff -Nur linux-2.6.36.orig/scripts/mod/modpost.h linux-2.6.36/scripts/mod/modpost.h +--- linux-2.6.36.orig/scripts/mod/modpost.h 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36/scripts/mod/modpost.h 2010-11-28 18:33:24.000000000 +0100 +@@ -7,7 +7,2453 @@ + #include <sys/mman.h> + #include <fcntl.h> + #include <unistd.h> +-#include <elf.h> ++ ++ ++/* This file defines standard ELF types, structures, and macros. ++ Copyright (C) 1995-1999,2000,2001,2002,2003 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library 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 ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, write to the Free ++ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ++ 02111-1307 USA. */ ++ ++#ifndef _ELF_H ++#define _ELF_H 1 ++ ++__BEGIN_DECLS ++ ++/* Standard ELF types. */ ++ ++#include <stdint.h> ++ ++/* Type for a 16-bit quantity. */ ++typedef uint16_t Elf32_Half; ++typedef uint16_t Elf64_Half; ++ ++/* Types for signed and unsigned 32-bit quantities. */ ++typedef uint32_t Elf32_Word; ++typedef int32_t Elf32_Sword; ++typedef uint32_t Elf64_Word; ++typedef int32_t Elf64_Sword; ++ ++/* Types for signed and unsigned 64-bit quantities. */ ++typedef uint64_t Elf32_Xword; ++typedef int64_t Elf32_Sxword; ++typedef uint64_t Elf64_Xword; ++typedef int64_t Elf64_Sxword; ++ ++/* Type of addresses. */ ++typedef uint32_t Elf32_Addr; ++typedef uint64_t Elf64_Addr; ++ ++/* Type of file offsets. */ ++typedef uint32_t Elf32_Off; ++typedef uint64_t Elf64_Off; ++ ++/* Type for section indices, which are 16-bit quantities. */ ++typedef uint16_t Elf32_Section; ++typedef uint16_t Elf64_Section; ++ ++/* Type for version symbol information. */ ++typedef Elf32_Half Elf32_Versym; ++typedef Elf64_Half Elf64_Versym; ++ ++ ++/* The ELF file header. This appears at the start of every ELF file. */ ++ ++#define EI_NIDENT (16) ++ ++typedef struct ++{ ++ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ ++ Elf32_Half e_type; /* Object file type */ ++ Elf32_Half e_machine; /* Architecture */ ++ Elf32_Word e_version; /* Object file version */ ++ Elf32_Addr e_entry; /* Entry point virtual address */ ++ Elf32_Off e_phoff; /* Program header table file offset */ ++ Elf32_Off e_shoff; /* Section header table file offset */ ++ Elf32_Word e_flags; /* Processor-specific flags */ ++ Elf32_Half e_ehsize; /* ELF header size in bytes */ ++ Elf32_Half e_phentsize; /* Program header table entry size */ ++ Elf32_Half e_phnum; /* Program header table entry count */ ++ Elf32_Half e_shentsize; /* Section header table entry size */ ++ Elf32_Half e_shnum; /* Section header table entry count */ ++ Elf32_Half e_shstrndx; /* Section header string table index */ ++} Elf32_Ehdr; ++ ++typedef struct ++{ ++ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ ++ Elf64_Half e_type; /* Object file type */ ++ Elf64_Half e_machine; /* Architecture */ ++ Elf64_Word e_version; /* Object file version */ ++ Elf64_Addr e_entry; /* Entry point virtual address */ ++ Elf64_Off e_phoff; /* Program header table file offset */ ++ Elf64_Off e_shoff; /* Section header table file offset */ ++ Elf64_Word e_flags; /* Processor-specific flags */ ++ Elf64_Half e_ehsize; /* ELF header size in bytes */ ++ Elf64_Half e_phentsize; /* Program header table entry size */ ++ Elf64_Half e_phnum; /* Program header table entry count */ ++ Elf64_Half e_shentsize; /* Section header table entry size */ ++ Elf64_Half e_shnum; /* Section header table entry count */ ++ Elf64_Half e_shstrndx; /* Section header string table index */ ++} Elf64_Ehdr; ++ ++/* Fields in the e_ident array. The EI_* macros are indices into the ++ array. The macros under each EI_* macro are the values the byte ++ may have. */ ++ ++#define EI_MAG0 0 /* File identification byte 0 index */ ++#define ELFMAG0 0x7f /* Magic number byte 0 */ ++ ++#define EI_MAG1 1 /* File identification byte 1 index */ ++#define ELFMAG1 'E' /* Magic number byte 1 */ ++ ++#define EI_MAG2 2 /* File identification byte 2 index */ ++#define ELFMAG2 'L' /* Magic number byte 2 */ ++ ++#define EI_MAG3 3 /* File identification byte 3 index */ ++#define ELFMAG3 'F' /* Magic number byte 3 */ ++ ++/* Conglomeration of the identification bytes, for easy testing as a word. */ ++#define ELFMAG "\177ELF" ++#define SELFMAG 4 ++ ++#define EI_CLASS 4 /* File class byte index */ ++#define ELFCLASSNONE 0 /* Invalid class */ ++#define ELFCLASS32 1 /* 32-bit objects */ ++#define ELFCLASS64 2 /* 64-bit objects */ ++#define ELFCLASSNUM 3 ++ ++#define EI_DATA 5 /* Data encoding byte index */ ++#define ELFDATANONE 0 /* Invalid data encoding */ ++#define ELFDATA2LSB 1 /* 2's complement, little endian */ ++#define ELFDATA2MSB 2 /* 2's complement, big endian */ ++#define ELFDATANUM 3 ++ ++#define EI_VERSION 6 /* File version byte index */ ++ /* Value must be EV_CURRENT */ ++ ++#define EI_OSABI 7 /* OS ABI identification */ ++#define ELFOSABI_NONE 0 /* UNIX System V ABI */ ++#define ELFOSABI_SYSV 0 /* Alias. */ ++#define ELFOSABI_HPUX 1 /* HP-UX */ ++#define ELFOSABI_NETBSD 2 /* NetBSD. */ ++#define ELFOSABI_LINUX 3 /* Linux. */ ++#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ ++#define ELFOSABI_AIX 7 /* IBM AIX. */ ++#define ELFOSABI_IRIX 8 /* SGI Irix. */ ++#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ ++#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ ++#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ ++#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ ++#define ELFOSABI_ARM 97 /* ARM */ ++#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ ++ ++#define EI_ABIVERSION 8 /* ABI version */ ++ ++#define EI_PAD 9 /* Byte index of padding bytes */ ++ ++/* Legal values for e_type (object file type). */ ++ ++#define ET_NONE 0 /* No file type */ ++#define ET_REL 1 /* Relocatable file */ ++#define ET_EXEC 2 /* Executable file */ ++#define ET_DYN 3 /* Shared object file */ ++#define ET_CORE 4 /* Core file */ ++#define ET_NUM 5 /* Number of defined types */ ++#define ET_LOOS 0xfe00 /* OS-specific range start */ ++#define ET_HIOS 0xfeff /* OS-specific range end */ ++#define ET_LOPROC 0xff00 /* Processor-specific range start */ ++#define ET_HIPROC 0xffff /* Processor-specific range end */ ++ ++/* Legal values for e_machine (architecture). */ ++ ++#define EM_NONE 0 /* No machine */ ++#define EM_M32 1 /* AT&T WE 32100 */ ++#define EM_SPARC 2 /* SUN SPARC */ ++#define EM_386 3 /* Intel 80386 */ ++#define EM_68K 4 /* Motorola m68k family */ ++#define EM_88K 5 /* Motorola m88k family */ ++#define EM_860 7 /* Intel 80860 */ ++#define EM_MIPS 8 /* MIPS R3000 big-endian */ ++#define EM_S370 9 /* IBM System/370 */ ++#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ ++ ++#define EM_PARISC 15 /* HPPA */ ++#define EM_VPP500 17 /* Fujitsu VPP500 */ ++#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ ++#define EM_960 19 /* Intel 80960 */ ++#define EM_PPC 20 /* PowerPC */ ++#define EM_PPC64 21 /* PowerPC 64-bit */ ++#define EM_S390 22 /* IBM S390 */ ++ ++#define EM_V800 36 /* NEC V800 series */ ++#define EM_FR20 37 /* Fujitsu FR20 */ ++#define EM_RH32 38 /* TRW RH-32 */ ++#define EM_RCE 39 /* Motorola RCE */ ++#define EM_ARM 40 /* ARM */ ++#define EM_FAKE_ALPHA 41 /* Digital Alpha */ ++#define EM_SH 42 /* Hitachi SH */ ++#define EM_SPARCV9 43 /* SPARC v9 64-bit */ ++#define EM_TRICORE 44 /* Siemens Tricore */ ++#define EM_ARC 45 /* Argonaut RISC Core */ ++#define EM_H8_300 46 /* Hitachi H8/300 */ ++#define EM_H8_300H 47 /* Hitachi H8/300H */ ++#define EM_H8S 48 /* Hitachi H8S */ ++#define EM_H8_500 49 /* Hitachi H8/500 */ ++#define EM_IA_64 50 /* Intel Merced */ ++#define EM_MIPS_X 51 /* Stanford MIPS-X */ ++#define EM_COLDFIRE 52 /* Motorola Coldfire */ ++#define EM_68HC12 53 /* Motorola M68HC12 */ ++#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ ++#define EM_PCP 55 /* Siemens PCP */ ++#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ ++#define EM_NDR1 57 /* Denso NDR1 microprocessor */ ++#define EM_STARCORE 58 /* Motorola Start*Core processor */ ++#define EM_ME16 59 /* Toyota ME16 processor */ ++#define EM_ST100 60 /* STMicroelectronic ST100 processor */ ++#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ ++#define EM_X86_64 62 /* AMD x86-64 architecture */ ++#define EM_PDSP 63 /* Sony DSP Processor */ ++ ++#define EM_FX66 66 /* Siemens FX66 microcontroller */ ++#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ ++#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ ++#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ ++#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ ++#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ ++#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ ++#define EM_SVX 73 /* Silicon Graphics SVx */ ++#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ ++#define EM_VAX 75 /* Digital VAX */ ++#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ ++#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ ++#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ ++#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ ++#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ ++#define EM_HUANY 81 /* Harvard University machine-independent object files */ ++#define EM_PRISM 82 /* SiTera Prism */ ++#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ ++#define EM_FR30 84 /* Fujitsu FR30 */ ++#define EM_D10V 85 /* Mitsubishi D10V */ ++#define EM_D30V 86 /* Mitsubishi D30V */ ++#define EM_V850 87 /* NEC v850 */ ++#define EM_M32R 88 /* Mitsubishi M32R */ ++#define EM_MN10300 89 /* Matsushita MN10300 */ ++#define EM_MN10200 90 /* Matsushita MN10200 */ ++#define EM_PJ 91 /* picoJava */ ++#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ ++#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ ++#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ ++#define EM_NUM 95 ++ ++/* If it is necessary to assign new unofficial EM_* values, please ++ pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the ++ chances of collision with official or non-GNU unofficial values. */ ++ ++#define EM_ALPHA 0x9026 ++ ++/* Legal values for e_version (version). */ ++ ++#define EV_NONE 0 /* Invalid ELF version */ ++#define EV_CURRENT 1 /* Current version */ ++#define EV_NUM 2 ++ ++/* Section header. */ ++ ++typedef struct ++{ ++ Elf32_Word sh_name; /* Section name (string tbl index) */ ++ Elf32_Word sh_type; /* Section type */ ++ Elf32_Word sh_flags; /* Section flags */ ++ Elf32_Addr sh_addr; /* Section virtual addr at execution */ ++ Elf32_Off sh_offset; /* Section file offset */ ++ Elf32_Word sh_size; /* Section size in bytes */ ++ Elf32_Word sh_link; /* Link to another section */ ++ Elf32_Word sh_info; /* Additional section information */ ++ Elf32_Word sh_addralign; /* Section alignment */ ++ Elf32_Word sh_entsize; /* Entry size if section holds table */ ++} Elf32_Shdr; ++ ++typedef struct ++{ ++ Elf64_Word sh_name; /* Section name (string tbl index) */ ++ Elf64_Word sh_type; /* Section type */ ++ Elf64_Xword sh_flags; /* Section flags */ ++ Elf64_Addr sh_addr; /* Section virtual addr at execution */ ++ Elf64_Off sh_offset; /* Section file offset */ ++ Elf64_Xword sh_size; /* Section size in bytes */ ++ Elf64_Word sh_link; /* Link to another section */ ++ Elf64_Word sh_info; /* Additional section information */ ++ Elf64_Xword sh_addralign; /* Section alignment */ ++ Elf64_Xword sh_entsize; /* Entry size if section holds table */ ++} Elf64_Shdr; ++ ++/* Special section indices. */ ++ ++#define SHN_UNDEF 0 /* Undefined section */ ++#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ ++#define SHN_LOPROC 0xff00 /* Start of processor-specific */ ++#define SHN_HIPROC 0xff1f /* End of processor-specific */ ++#define SHN_LOOS 0xff20 /* Start of OS-specific */ ++#define SHN_HIOS 0xff3f /* End of OS-specific */ ++#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ ++#define SHN_COMMON 0xfff2 /* Associated symbol is common */ ++#define SHN_XINDEX 0xffff /* Index is in extra table. */ ++#define SHN_HIRESERVE 0xffff /* End of reserved indices */ ++ ++/* Legal values for sh_type (section type). */ ++ ++#define SHT_NULL 0 /* Section header table entry unused */ ++#define SHT_PROGBITS 1 /* Program data */ ++#define SHT_SYMTAB 2 /* Symbol table */ ++#define SHT_STRTAB 3 /* String table */ ++#define SHT_RELA 4 /* Relocation entries with addends */ ++#define SHT_HASH 5 /* Symbol hash table */ ++#define SHT_DYNAMIC 6 /* Dynamic linking information */ ++#define SHT_NOTE 7 /* Notes */ ++#define SHT_NOBITS 8 /* Program space with no data (bss) */ ++#define SHT_REL 9 /* Relocation entries, no addends */ ++#define SHT_SHLIB 10 /* Reserved */ ++#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ ++#define SHT_INIT_ARRAY 14 /* Array of constructors */ ++#define SHT_FINI_ARRAY 15 /* Array of destructors */ ++#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ ++#define SHT_GROUP 17 /* Section group */ ++#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ ++#define SHT_NUM 19 /* Number of defined types. */ ++#define SHT_LOOS 0x60000000 /* Start OS-specific */ ++#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ ++#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ ++#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ ++#define SHT_SUNW_move 0x6ffffffa ++#define SHT_SUNW_COMDAT 0x6ffffffb ++#define SHT_SUNW_syminfo 0x6ffffffc ++#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ ++#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ ++#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ ++#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ ++#define SHT_HIOS 0x6fffffff /* End OS-specific type */ ++#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ ++#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ ++#define SHT_LOUSER 0x80000000 /* Start of application-specific */ ++#define SHT_HIUSER 0x8fffffff /* End of application-specific */ ++ ++/* Legal values for sh_flags (section flags). */ ++ ++#define SHF_WRITE (1 << 0) /* Writable */ ++#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ ++#define SHF_EXECINSTR (1 << 2) /* Executable */ ++#define SHF_MERGE (1 << 4) /* Might be merged */ ++#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ ++#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ ++#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ ++#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling ++ required */ ++#define SHF_GROUP (1 << 9) /* Section is member of a group. */ ++#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ ++#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ ++#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ ++ ++/* Section group handling. */ ++#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ ++ ++/* Symbol table entry. */ ++ ++typedef struct ++{ ++ Elf32_Word st_name; /* Symbol name (string tbl index) */ ++ Elf32_Addr st_value; /* Symbol value */ ++ Elf32_Word st_size; /* Symbol size */ ++ unsigned char st_info; /* Symbol type and binding */ ++ unsigned char st_other; /* Symbol visibility */ ++ Elf32_Section st_shndx; /* Section index */ ++} Elf32_Sym; ++ ++typedef struct ++{ ++ Elf64_Word st_name; /* Symbol name (string tbl index) */ ++ unsigned char st_info; /* Symbol type and binding */ ++ unsigned char st_other; /* Symbol visibility */ ++ Elf64_Section st_shndx; /* Section index */ ++ Elf64_Addr st_value; /* Symbol value */ ++ Elf64_Xword st_size; /* Symbol size */ ++} Elf64_Sym; ++ ++/* The syminfo section if available contains additional information about ++ every dynamic symbol. */ ++ ++typedef struct ++{ ++ Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ ++ Elf32_Half si_flags; /* Per symbol flags */ ++} Elf32_Syminfo; ++ ++typedef struct ++{ ++ Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ ++ Elf64_Half si_flags; /* Per symbol flags */ ++} Elf64_Syminfo; ++ ++/* Possible values for si_boundto. */ ++#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ ++#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ ++#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ ++ ++/* Possible bitmasks for si_flags. */ ++#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ ++#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ ++#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ ++#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy ++ loaded */ ++/* Syminfo version values. */ ++#define SYMINFO_NONE 0 ++#define SYMINFO_CURRENT 1 ++#define SYMINFO_NUM 2 ++ ++ ++/* How to extract and insert information held in the st_info field. */ ++ ++#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) ++#define ELF32_ST_TYPE(val) ((val) & 0xf) ++#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) ++ ++/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ ++#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) ++#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) ++#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) ++ ++/* Legal values for ST_BIND subfield of st_info (symbol binding). */ ++ ++#define STB_LOCAL 0 /* Local symbol */ ++#define STB_GLOBAL 1 /* Global symbol */ ++#define STB_WEAK 2 /* Weak symbol */ ++#define STB_NUM 3 /* Number of defined types. */ ++#define STB_LOOS 10 /* Start of OS-specific */ ++#define STB_HIOS 12 /* End of OS-specific */ ++#define STB_LOPROC 13 /* Start of processor-specific */ ++#define STB_HIPROC 15 /* End of processor-specific */ ++ ++/* Legal values for ST_TYPE subfield of st_info (symbol type). */ ++ ++#define STT_NOTYPE 0 /* Symbol type is unspecified */ ++#define STT_OBJECT 1 /* Symbol is a data object */ ++#define STT_FUNC 2 /* Symbol is a code object */ ++#define STT_SECTION 3 /* Symbol associated with a section */ ++#define STT_FILE 4 /* Symbol's name is file name */ ++#define STT_COMMON 5 /* Symbol is a common data object */ ++#define STT_TLS 6 /* Symbol is thread-local data object*/ ++#define STT_NUM 7 /* Number of defined types. */ ++#define STT_LOOS 10 /* Start of OS-specific */ ++#define STT_HIOS 12 /* End of OS-specific */ ++#define STT_LOPROC 13 /* Start of processor-specific */ ++#define STT_HIPROC 15 /* End of processor-specific */ ++ ++ ++/* Symbol table indices are found in the hash buckets and chain table ++ of a symbol hash table section. This special index value indicates ++ the end of a chain, meaning no further symbols are found in that bucket. */ ++ ++#define STN_UNDEF 0 /* End of a chain. */ ++ ++ ++/* How to extract and insert information held in the st_other field. */ ++ ++#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) ++ ++/* For ELF64 the definitions are the same. */ ++#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) ++ ++/* Symbol visibility specification encoded in the st_other field. */ ++#define STV_DEFAULT 0 /* Default symbol visibility rules */ ++#define STV_INTERNAL 1 /* Processor specific hidden class */ ++#define STV_HIDDEN 2 /* Sym unavailable in other modules */ ++#define STV_PROTECTED 3 /* Not preemptible, not exported */ ++ ++ ++/* Relocation table entry without addend (in section of type SHT_REL). */ ++ ++typedef struct ++{ ++ Elf32_Addr r_offset; /* Address */ ++ Elf32_Word r_info; /* Relocation type and symbol index */ ++} Elf32_Rel; ++ ++/* I have seen two different definitions of the Elf64_Rel and ++ Elf64_Rela structures, so we'll leave them out until Novell (or ++ whoever) gets their act together. */ ++/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ ++ ++typedef struct ++{ ++ Elf64_Addr r_offset; /* Address */ ++ Elf64_Xword r_info; /* Relocation type and symbol index */ ++} Elf64_Rel; ++ ++/* Relocation table entry with addend (in section of type SHT_RELA). */ ++ ++typedef struct ++{ ++ Elf32_Addr r_offset; /* Address */ ++ Elf32_Word r_info; /* Relocation type and symbol index */ ++ Elf32_Sword r_addend; /* Addend */ ++} Elf32_Rela; ++ ++typedef struct ++{ ++ Elf64_Addr r_offset; /* Address */ ++ Elf64_Xword r_info; /* Relocation type and symbol index */ ++ Elf64_Sxword r_addend; /* Addend */ ++} Elf64_Rela; ++ ++/* How to extract and insert information held in the r_info field. */ ++ ++#define ELF32_R_SYM(val) ((val) >> 8) ++#define ELF32_R_TYPE(val) ((val) & 0xff) ++#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) ++ ++#define ELF64_R_SYM(i) ((i) >> 32) ++#define ELF64_R_TYPE(i) ((i) & 0xffffffff) ++#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) ++ ++/* Program segment header. */ ++ ++typedef struct ++{ ++ Elf32_Word p_type; /* Segment type */ ++ Elf32_Off p_offset; /* Segment file offset */ ++ Elf32_Addr p_vaddr; /* Segment virtual address */ ++ Elf32_Addr p_paddr; /* Segment physical address */ ++ Elf32_Word p_filesz; /* Segment size in file */ ++ Elf32_Word p_memsz; /* Segment size in memory */ ++ Elf32_Word p_flags; /* Segment flags */ ++ Elf32_Word p_align; /* Segment alignment */ ++} Elf32_Phdr; ++ ++typedef struct ++{ ++ Elf64_Word p_type; /* Segment type */ ++ Elf64_Word p_flags; /* Segment flags */ ++ Elf64_Off p_offset; /* Segment file offset */ ++ Elf64_Addr p_vaddr; /* Segment virtual address */ ++ Elf64_Addr p_paddr; /* Segment physical address */ ++ Elf64_Xword p_filesz; /* Segment size in file */ ++ Elf64_Xword p_memsz; /* Segment size in memory */ ++ Elf64_Xword p_align; /* Segment alignment */ ++} Elf64_Phdr; ++ ++/* Legal values for p_type (segment type). */ ++ ++#define PT_NULL 0 /* Program header table entry unused */ ++#define PT_LOAD 1 /* Loadable program segment */ ++#define PT_DYNAMIC 2 /* Dynamic linking information */ ++#define PT_INTERP 3 /* Program interpreter */ ++#define PT_NOTE 4 /* Auxiliary information */ ++#define PT_SHLIB 5 /* Reserved */ ++#define PT_PHDR 6 /* Entry for header table itself */ ++#define PT_TLS 7 /* Thread-local storage segment */ ++#define PT_NUM 8 /* Number of defined types */ ++#define PT_LOOS 0x60000000 /* Start of OS-specific */ ++#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ ++#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ ++#define PT_LOSUNW 0x6ffffffa ++#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ ++#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ ++#define PT_HISUNW 0x6fffffff ++#define PT_HIOS 0x6fffffff /* End of OS-specific */ ++#define PT_LOPROC 0x70000000 /* Start of processor-specific */ ++#define PT_HIPROC 0x7fffffff /* End of processor-specific */ ++ ++/* Legal values for p_flags (segment flags). */ ++ ++#define PF_X (1 << 0) /* Segment is executable */ ++#define PF_W (1 << 1) /* Segment is writable */ ++#define PF_R (1 << 2) /* Segment is readable */ ++#define PF_MASKOS 0x0ff00000 /* OS-specific */ ++#define PF_MASKPROC 0xf0000000 /* Processor-specific */ ++ ++/* Legal values for note segment descriptor types for core files. */ ++ ++#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ ++#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ ++#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ ++#define NT_PRXREG 4 /* Contains copy of prxregset struct */ ++#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ ++#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ ++#define NT_AUXV 6 /* Contains copy of auxv array */ ++#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ ++#define NT_ASRS 8 /* Contains copy of asrset struct */ ++#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ ++#define NT_PSINFO 13 /* Contains copy of psinfo struct */ ++#define NT_PRCRED 14 /* Contains copy of prcred struct */ ++#define NT_UTSNAME 15 /* Contains copy of utsname struct */ ++#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ ++#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ ++#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct*/ ++ ++/* Legal values for the note segment descriptor types for object files. */ ++ ++#define NT_VERSION 1 /* Contains a version string. */ ++ ++ ++/* Dynamic section entry. */ ++ ++typedef struct ++{ ++ Elf32_Sword d_tag; /* Dynamic entry type */ ++ union ++ { ++ Elf32_Word d_val; /* Integer value */ ++ Elf32_Addr d_ptr; /* Address value */ ++ } d_un; ++} Elf32_Dyn; ++ ++typedef struct ++{ ++ Elf64_Sxword d_tag; /* Dynamic entry type */ ++ union ++ { ++ Elf64_Xword d_val; /* Integer value */ ++ Elf64_Addr d_ptr; /* Address value */ ++ } d_un; ++} Elf64_Dyn; ++ ++/* Legal values for d_tag (dynamic entry type). */ ++ ++#define DT_NULL 0 /* Marks end of dynamic section */ ++#define DT_NEEDED 1 /* Name of needed library */ ++#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ ++#define DT_PLTGOT 3 /* Processor defined value */ ++#define DT_HASH 4 /* Address of symbol hash table */ ++#define DT_STRTAB 5 /* Address of string table */ ++#define DT_SYMTAB 6 /* Address of symbol table */ ++#define DT_RELA 7 /* Address of Rela relocs */ ++#define DT_RELASZ 8 /* Total size of Rela relocs */ ++#define DT_RELAENT 9 /* Size of one Rela reloc */ ++#define DT_STRSZ 10 /* Size of string table */ ++#define DT_SYMENT 11 /* Size of one symbol table entry */ ++#define DT_INIT 12 /* Address of init function */ ++#define DT_FINI 13 /* Address of termination function */ ++#define DT_SONAME 14 /* Name of shared object */ ++#define DT_RPATH 15 /* Library search path (deprecated) */ ++#define DT_SYMBOLIC 16 /* Start symbol search here */ ++#define DT_REL 17 /* Address of Rel relocs */ ++#define DT_RELSZ 18 /* Total size of Rel relocs */ ++#define DT_RELENT 19 /* Size of one Rel reloc */ ++#define DT_PLTREL 20 /* Type of reloc in PLT */ ++#define DT_DEBUG 21 /* For debugging; unspecified */ ++#define DT_TEXTREL 22 /* Reloc might modify .text */ ++#define DT_JMPREL 23 /* Address of PLT relocs */ ++#define DT_BIND_NOW 24 /* Process relocations of object */ ++#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ ++#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ ++#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ ++#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ ++#define DT_RUNPATH 29 /* Library search path */ ++#define DT_FLAGS 30 /* Flags for the object being loaded */ ++#define DT_ENCODING 32 /* Start of encoded range */ ++#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ ++#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ ++#define DT_NUM 34 /* Number used */ ++#define DT_LOOS 0x6000000d /* Start of OS-specific */ ++#define DT_HIOS 0x6ffff000 /* End of OS-specific */ ++#define DT_LOPROC 0x70000000 /* Start of processor-specific */ ++#define DT_HIPROC 0x7fffffff /* End of processor-specific */ ++#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ ++ ++/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the ++ Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's ++ approach. */ ++#define DT_VALRNGLO 0x6ffffd00 ++#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ ++#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ ++#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ ++#define DT_CHECKSUM 0x6ffffdf8 ++#define DT_PLTPADSZ 0x6ffffdf9 ++#define DT_MOVEENT 0x6ffffdfa ++#define DT_MOVESZ 0x6ffffdfb ++#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ ++#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting ++ the following DT_* entry. */ ++#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ ++#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ ++#define DT_VALRNGHI 0x6ffffdff ++#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ ++#define DT_VALNUM 12 ++ ++/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the ++ Dyn.d_un.d_ptr field of the Elf*_Dyn structure. ++ ++ If any adjustment is made to the ELF object after it has been ++ built these entries will need to be adjusted. */ ++#define DT_ADDRRNGLO 0x6ffffe00 ++#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ ++#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ ++#define DT_CONFIG 0x6ffffefa /* Configuration information. */ ++#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ ++#define DT_AUDIT 0x6ffffefc /* Object auditing. */ ++#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ ++#define DT_MOVETAB 0x6ffffefe /* Move table. */ ++#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ ++#define DT_ADDRRNGHI 0x6ffffeff ++#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ ++#define DT_ADDRNUM 10 ++ ++/* The versioning entry types. The next are defined as part of the ++ GNU extension. */ ++#define DT_VERSYM 0x6ffffff0 ++ ++#define DT_RELACOUNT 0x6ffffff9 ++#define DT_RELCOUNT 0x6ffffffa ++ ++/* These were chosen by Sun. */ ++#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ ++#define DT_VERDEF 0x6ffffffc /* Address of version definition ++ table */ ++#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ ++#define DT_VERNEED 0x6ffffffe /* Address of table with needed ++ versions */ ++#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ ++#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ ++#define DT_VERSIONTAGNUM 16 ++ ++/* Sun added these machine-independent extensions in the "processor-specific" ++ range. Be compatible. */ ++#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ ++#define DT_FILTER 0x7fffffff /* Shared object to get values from */ ++#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) ++#define DT_EXTRANUM 3 ++ ++/* Values of `d_un.d_val' in the DT_FLAGS entry. */ ++#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ ++#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ ++#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ ++#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ ++#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ ++ ++/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 ++ entry in the dynamic section. */ ++#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ ++#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ ++#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ ++#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ ++#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ ++#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ ++#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ ++#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ ++#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ ++#define DF_1_TRANS 0x00000200 ++#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ ++#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ ++#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ ++#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ ++#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ ++#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ ++#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ ++ ++/* Flags for the feature selection in DT_FEATURE_1. */ ++#define DTF_1_PARINIT 0x00000001 ++#define DTF_1_CONFEXP 0x00000002 ++ ++/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ ++#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ ++#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not ++ generally available. */ ++ ++/* Version definition sections. */ ++ ++typedef struct ++{ ++ Elf32_Half vd_version; /* Version revision */ ++ Elf32_Half vd_flags; /* Version information */ ++ Elf32_Half vd_ndx; /* Version Index */ ++ Elf32_Half vd_cnt; /* Number of associated aux entries */ ++ Elf32_Word vd_hash; /* Version name hash value */ ++ Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ ++ Elf32_Word vd_next; /* Offset in bytes to next verdef ++ entry */ ++} Elf32_Verdef; ++ ++typedef struct ++{ ++ Elf64_Half vd_version; /* Version revision */ ++ Elf64_Half vd_flags; /* Version information */ ++ Elf64_Half vd_ndx; /* Version Index */ ++ Elf64_Half vd_cnt; /* Number of associated aux entries */ ++ Elf64_Word vd_hash; /* Version name hash value */ ++ Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ ++ Elf64_Word vd_next; /* Offset in bytes to next verdef ++ entry */ ++} Elf64_Verdef; ++ ++ ++/* Legal values for vd_version (version revision). */ ++#define VER_DEF_NONE 0 /* No version */ ++#define VER_DEF_CURRENT 1 /* Current version */ ++#define VER_DEF_NUM 2 /* Given version number */ ++ ++/* Legal values for vd_flags (version information flags). */ ++#define VER_FLG_BASE 0x1 /* Version definition of file itself */ ++#define VER_FLG_WEAK 0x2 /* Weak version identifier */ ++ ++/* Versym symbol index values. */ ++#define VER_NDX_LOCAL 0 /* Symbol is local. */ ++#define VER_NDX_GLOBAL 1 /* Symbol is global. */ ++#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ ++#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ ++ ++/* Auxialiary version information. */ ++ ++typedef struct ++{ ++ Elf32_Word vda_name; /* Version or dependency names */ ++ Elf32_Word vda_next; /* Offset in bytes to next verdaux ++ entry */ ++} Elf32_Verdaux; ++ ++typedef struct ++{ ++ Elf64_Word vda_name; /* Version or dependency names */ ++ Elf64_Word vda_next; /* Offset in bytes to next verdaux ++ entry */ ++} Elf64_Verdaux; ++ ++ ++/* Version dependency section. */ ++ ++typedef struct ++{ ++ Elf32_Half vn_version; /* Version of structure */ ++ Elf32_Half vn_cnt; /* Number of associated aux entries */ ++ Elf32_Word vn_file; /* Offset of filename for this ++ dependency */ ++ Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ ++ Elf32_Word vn_next; /* Offset in bytes to next verneed ++ entry */ ++} Elf32_Verneed; ++ ++typedef struct ++{ ++ Elf64_Half vn_version; /* Version of structure */ ++ Elf64_Half vn_cnt; /* Number of associated aux entries */ ++ Elf64_Word vn_file; /* Offset of filename for this ++ dependency */ ++ Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ ++ Elf64_Word vn_next; /* Offset in bytes to next verneed ++ entry */ ++} Elf64_Verneed; ++ ++ ++/* Legal values for vn_version (version revision). */ ++#define VER_NEED_NONE 0 /* No version */ ++#define VER_NEED_CURRENT 1 /* Current version */ ++#define VER_NEED_NUM 2 /* Given version number */ ++ ++/* Auxiliary needed version information. */ ++ ++typedef struct ++{ ++ Elf32_Word vna_hash; /* Hash value of dependency name */ ++ Elf32_Half vna_flags; /* Dependency specific information */ ++ Elf32_Half vna_other; /* Unused */ ++ Elf32_Word vna_name; /* Dependency name string offset */ ++ Elf32_Word vna_next; /* Offset in bytes to next vernaux ++ entry */ ++} Elf32_Vernaux; ++ ++typedef struct ++{ ++ Elf64_Word vna_hash; /* Hash value of dependency name */ ++ Elf64_Half vna_flags; /* Dependency specific information */ ++ Elf64_Half vna_other; /* Unused */ ++ Elf64_Word vna_name; /* Dependency name string offset */ ++ Elf64_Word vna_next; /* Offset in bytes to next vernaux ++ entry */ ++} Elf64_Vernaux; ++ ++ ++/* Legal values for vna_flags. */ ++#define VER_FLG_WEAK 0x2 /* Weak version identifier */ ++ ++ ++/* Auxiliary vector. */ ++ ++/* This vector is normally only used by the program interpreter. The ++ usual definition in an ABI supplement uses the name auxv_t. The ++ vector is not usually defined in a standard <elf.h> file, but it ++ can't hurt. We rename it to avoid conflicts. The sizes of these ++ types are an arrangement between the exec server and the program ++ interpreter, so we don't fully specify them here. */ ++ ++typedef struct ++{ ++ int a_type; /* Entry type */ ++ union ++ { ++ long int a_val; /* Integer value */ ++ void *a_ptr; /* Pointer value */ ++ void (*a_fcn) (void); /* Function pointer value */ ++ } a_un; ++} Elf32_auxv_t; ++ ++typedef struct ++{ ++ long int a_type; /* Entry type */ ++ union ++ { ++ long int a_val; /* Integer value */ ++ void *a_ptr; /* Pointer value */ ++ void (*a_fcn) (void); /* Function pointer value */ ++ } a_un; ++} Elf64_auxv_t; ++ ++/* Legal values for a_type (entry type). */ ++ ++#define AT_NULL 0 /* End of vector */ ++#define AT_IGNORE 1 /* Entry should be ignored */ ++#define AT_EXECFD 2 /* File descriptor of program */ ++#define AT_PHDR 3 /* Program headers for program */ ++#define AT_PHENT 4 /* Size of program header entry */ ++#define AT_PHNUM 5 /* Number of program headers */ ++#define AT_PAGESZ 6 /* System page size */ ++#define AT_BASE 7 /* Base address of interpreter */ ++#define AT_FLAGS 8 /* Flags */ ++#define AT_ENTRY 9 /* Entry point of program */ ++#define AT_NOTELF 10 /* Program is not ELF */ ++#define AT_UID 11 /* Real uid */ ++#define AT_EUID 12 /* Effective uid */ ++#define AT_GID 13 /* Real gid */ ++#define AT_EGID 14 /* Effective gid */ ++#define AT_CLKTCK 17 /* Frequency of times() */ ++ ++/* Some more special a_type values describing the hardware. */ ++#define AT_PLATFORM 15 /* String identifying platform. */ ++#define AT_HWCAP 16 /* Machine dependent hints about ++ processor capabilities. */ ++ ++/* This entry gives some information about the FPU initialization ++ performed by the kernel. */ ++#define AT_FPUCW 18 /* Used FPU control word. */ ++ ++/* Cache block sizes. */ ++#define AT_DCACHEBSIZE 19 /* Data cache block size. */ ++#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ ++#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ ++ ++/* A special ignored value for PPC, used by the kernel to control the ++ interpretation of the AUXV. Must be > 16. */ ++#define AT_IGNOREPPC 22 /* Entry should be ignored. */ ++ ++#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ ++ ++/* Pointer to the global system page used for system calls and other ++ nice things. */ ++#define AT_SYSINFO 32 ++#define AT_SYSINFO_EHDR 33 ++ ++ ++/* Note section contents. Each entry in the note section begins with ++ a header of a fixed form. */ ++ ++typedef struct ++{ ++ Elf32_Word n_namesz; /* Length of the note's name. */ ++ Elf32_Word n_descsz; /* Length of the note's descriptor. */ ++ Elf32_Word n_type; /* Type of the note. */ ++} Elf32_Nhdr; ++ ++typedef struct ++{ ++ Elf64_Word n_namesz; /* Length of the note's name. */ ++ Elf64_Word n_descsz; /* Length of the note's descriptor. */ ++ Elf64_Word n_type; /* Type of the note. */ ++} Elf64_Nhdr; ++ ++/* Known names of notes. */ ++ ++/* Solaris entries in the note section have this name. */ ++#define ELF_NOTE_SOLARIS "SUNW Solaris" ++ ++/* Note entries for GNU systems have this name. */ ++#define ELF_NOTE_GNU "GNU" ++ ++ ++/* Defined types of notes for Solaris. */ ++ ++/* Value of descriptor (one word) is desired pagesize for the binary. */ ++#define ELF_NOTE_PAGESIZE_HINT 1 ++ ++ ++/* Defined note types for GNU systems. */ ++ ++/* ABI information. The descriptor consists of words: ++ word 0: OS descriptor ++ word 1: major version of the ABI ++ word 2: minor version of the ABI ++ word 3: subminor version of the ABI ++*/ ++#define ELF_NOTE_ABI 1 ++ ++/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI ++ note section entry. */ ++#define ELF_NOTE_OS_LINUX 0 ++#define ELF_NOTE_OS_GNU 1 ++#define ELF_NOTE_OS_SOLARIS2 2 ++#define ELF_NOTE_OS_FREEBSD 3 ++ ++ ++/* Move records. */ ++typedef struct ++{ ++ Elf32_Xword m_value; /* Symbol value. */ ++ Elf32_Word m_info; /* Size and index. */ ++ Elf32_Word m_poffset; /* Symbol offset. */ ++ Elf32_Half m_repeat; /* Repeat count. */ ++ Elf32_Half m_stride; /* Stride info. */ ++} Elf32_Move; ++ ++typedef struct ++{ ++ Elf64_Xword m_value; /* Symbol value. */ ++ Elf64_Xword m_info; /* Size and index. */ ++ Elf64_Xword m_poffset; /* Symbol offset. */ ++ Elf64_Half m_repeat; /* Repeat count. */ ++ Elf64_Half m_stride; /* Stride info. */ ++} Elf64_Move; ++ ++/* Macro to construct move records. */ ++#define ELF32_M_SYM(info) ((info) >> 8) ++#define ELF32_M_SIZE(info) ((unsigned char) (info)) ++#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) ++ ++#define ELF64_M_SYM(info) ELF32_M_SYM (info) ++#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) ++#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) ++ ++ ++/* Motorola 68k specific definitions. */ ++ ++/* Values for Elf32_Ehdr.e_flags. */ ++#define EF_CPU32 0x00810000 ++ ++/* m68k relocs. */ ++ ++#define R_68K_NONE 0 /* No reloc */ ++#define R_68K_32 1 /* Direct 32 bit */ ++#define R_68K_16 2 /* Direct 16 bit */ ++#define R_68K_8 3 /* Direct 8 bit */ ++#define R_68K_PC32 4 /* PC relative 32 bit */ ++#define R_68K_PC16 5 /* PC relative 16 bit */ ++#define R_68K_PC8 6 /* PC relative 8 bit */ ++#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ ++#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ ++#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ ++#define R_68K_GOT32O 10 /* 32 bit GOT offset */ ++#define R_68K_GOT16O 11 /* 16 bit GOT offset */ ++#define R_68K_GOT8O 12 /* 8 bit GOT offset */ ++#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ ++#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ ++#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ ++#define R_68K_PLT32O 16 /* 32 bit PLT offset */ ++#define R_68K_PLT16O 17 /* 16 bit PLT offset */ ++#define R_68K_PLT8O 18 /* 8 bit PLT offset */ ++#define R_68K_COPY 19 /* Copy symbol at runtime */ ++#define R_68K_GLOB_DAT 20 /* Create GOT entry */ ++#define R_68K_JMP_SLOT 21 /* Create PLT entry */ ++#define R_68K_RELATIVE 22 /* Adjust by program base */ ++/* Keep this the last entry. */ ++#define R_68K_NUM 23 ++ ++/* Intel 80386 specific definitions. */ ++ ++/* i386 relocs. */ ++ ++#define R_386_NONE 0 /* No reloc */ ++#define R_386_32 1 /* Direct 32 bit */ ++#define R_386_PC32 2 /* PC relative 32 bit */ ++#define R_386_GOT32 3 /* 32 bit GOT entry */ ++#define R_386_PLT32 4 /* 32 bit PLT address */ ++#define R_386_COPY 5 /* Copy symbol at runtime */ ++#define R_386_GLOB_DAT 6 /* Create GOT entry */ ++#define R_386_JMP_SLOT 7 /* Create PLT entry */ ++#define R_386_RELATIVE 8 /* Adjust by program base */ ++#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ ++#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ ++#define R_386_32PLT 11 ++#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ ++#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS ++ block offset */ ++#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block ++ offset */ ++#define R_386_TLS_LE 17 /* Offset relative to static TLS ++ block */ ++#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of ++ general dynamic thread local data */ ++#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of ++ local dynamic thread local data ++ in LE code */ ++#define R_386_16 20 ++#define R_386_PC16 21 ++#define R_386_8 22 ++#define R_386_PC8 23 ++#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic ++ thread local data */ ++#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ ++#define R_386_TLS_GD_CALL 26 /* Relocation for call to ++ __tls_get_addr() */ ++#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ ++#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic ++ thread local data in LE code */ ++#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ ++#define R_386_TLS_LDM_CALL 30 /* Relocation for call to ++ __tls_get_addr() in LDM code */ ++#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ ++#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ ++#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS ++ block offset */ ++#define R_386_TLS_LE_32 34 /* Negated offset relative to static ++ TLS block */ ++#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ ++#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ ++#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ ++/* Keep this the last entry. */ ++#define R_386_NUM 38 ++ ++/* SUN SPARC specific definitions. */ ++ ++/* Legal values for ST_TYPE subfield of st_info (symbol type). */ ++ ++#define STT_REGISTER 13 /* Global register reserved to app. */ ++ ++/* Values for Elf64_Ehdr.e_flags. */ ++ ++#define EF_SPARCV9_MM 3 ++#define EF_SPARCV9_TSO 0 ++#define EF_SPARCV9_PSO 1 ++#define EF_SPARCV9_RMO 2 ++#define EF_SPARC_LEDATA 0x800000 /* little endian data */ ++#define EF_SPARC_EXT_MASK 0xFFFF00 ++#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ ++#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ ++#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ ++#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ ++ ++/* SPARC relocs. */ ++ ++#define R_SPARC_NONE 0 /* No reloc */ ++#define R_SPARC_8 1 /* Direct 8 bit */ ++#define R_SPARC_16 2 /* Direct 16 bit */ ++#define R_SPARC_32 3 /* Direct 32 bit */ ++#define R_SPARC_DISP8 4 /* PC relative 8 bit */ ++#define R_SPARC_DISP16 5 /* PC relative 16 bit */ ++#define R_SPARC_DISP32 6 /* PC relative 32 bit */ ++#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */ ++#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */ ++#define R_SPARC_HI22 9 /* High 22 bit */ ++#define R_SPARC_22 10 /* Direct 22 bit */ ++#define R_SPARC_13 11 /* Direct 13 bit */ ++#define R_SPARC_LO10 12 /* Truncated 10 bit */ ++#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */ ++#define R_SPARC_GOT13 14 /* 13 bit GOT entry */ ++#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */ ++#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */ ++#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */ ++#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */ ++#define R_SPARC_COPY 19 /* Copy symbol at runtime */ ++#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */ ++#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */ ++#define R_SPARC_RELATIVE 22 /* Adjust by program base */ ++#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */ ++ ++/* Additional Sparc64 relocs. */ ++ ++#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ ++#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ ++#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ ++#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ ++#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ ++#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ ++#define R_SPARC_10 30 /* Direct 10 bit */ ++#define R_SPARC_11 31 /* Direct 11 bit */ ++#define R_SPARC_64 32 /* Direct 64 bit */ ++#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ ++#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ ++#define R_SPARC_HM10 35 /* High middle 10 bits of ... */ ++#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ ++#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ ++#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ ++#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ ++#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ ++#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ ++#define R_SPARC_7 43 /* Direct 7 bit */ ++#define R_SPARC_5 44 /* Direct 5 bit */ ++#define R_SPARC_6 45 /* Direct 6 bit */ ++#define R_SPARC_DISP64 46 /* PC relative 64 bit */ ++#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ ++#define R_SPARC_HIX22 48 /* High 22 bit complemented */ ++#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ ++#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ ++#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ ++#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ ++#define R_SPARC_REGISTER 53 /* Global register usage */ ++#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ ++#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ ++#define R_SPARC_TLS_GD_HI22 56 ++#define R_SPARC_TLS_GD_LO10 57 ++#define R_SPARC_TLS_GD_ADD 58 ++#define R_SPARC_TLS_GD_CALL 59 ++#define R_SPARC_TLS_LDM_HI22 60 ++#define R_SPARC_TLS_LDM_LO10 61 ++#define R_SPARC_TLS_LDM_ADD 62 ++#define R_SPARC_TLS_LDM_CALL 63 ++#define R_SPARC_TLS_LDO_HIX22 64 ++#define R_SPARC_TLS_LDO_LOX10 65 ++#define R_SPARC_TLS_LDO_ADD 66 ++#define R_SPARC_TLS_IE_HI22 67 ++#define R_SPARC_TLS_IE_LO10 68 ++#define R_SPARC_TLS_IE_LD 69 ++#define R_SPARC_TLS_IE_LDX 70 ++#define R_SPARC_TLS_IE_ADD 71 ++#define R_SPARC_TLS_LE_HIX22 72 ++#define R_SPARC_TLS_LE_LOX10 73 ++#define R_SPARC_TLS_DTPMOD32 74 ++#define R_SPARC_TLS_DTPMOD64 75 ++#define R_SPARC_TLS_DTPOFF32 76 ++#define R_SPARC_TLS_DTPOFF64 77 ++#define R_SPARC_TLS_TPOFF32 78 ++#define R_SPARC_TLS_TPOFF64 79 ++/* Keep this the last entry. */ ++#define R_SPARC_NUM 80 ++ ++/* For Sparc64, legal values for d_tag of Elf64_Dyn. */ ++ ++#define DT_SPARC_REGISTER 0x70000001 ++#define DT_SPARC_NUM 2 ++ ++/* Bits present in AT_HWCAP, primarily for Sparc32. */ ++ ++#define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */ ++#define HWCAP_SPARC_STBAR 2 ++#define HWCAP_SPARC_SWAP 4 ++#define HWCAP_SPARC_MULDIV 8 ++#define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */ ++#define HWCAP_SPARC_ULTRA3 32 ++ ++/* MIPS R3000 specific definitions. */ ++ ++/* Legal values for e_flags field of Elf32_Ehdr. */ ++ ++#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */ ++#define EF_MIPS_PIC 2 /* Contains PIC code */ ++#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */ ++#define EF_MIPS_XGOT 8 ++#define EF_MIPS_64BIT_WHIRL 16 ++#define EF_MIPS_ABI2 32 ++#define EF_MIPS_ABI_ON32 64 ++#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ ++ ++/* Legal values for MIPS architecture level. */ ++ ++#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ ++#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ ++#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ ++#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ ++#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ ++#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ ++#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ ++ ++/* The following are non-official names and should not be used. */ ++ ++#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ ++#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ ++#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ ++#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ ++#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ ++#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ ++#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ ++ ++/* Special section indices. */ ++ ++#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ ++#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ ++#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ ++#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ ++#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ ++ ++/* Legal values for sh_type field of Elf32_Shdr. */ ++ ++#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ ++#define SHT_MIPS_MSYM 0x70000001 ++#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ ++#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ ++#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ ++#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/ ++#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ ++#define SHT_MIPS_PACKAGE 0x70000007 ++#define SHT_MIPS_PACKSYM 0x70000008 ++#define SHT_MIPS_RELD 0x70000009 ++#define SHT_MIPS_IFACE 0x7000000b ++#define SHT_MIPS_CONTENT 0x7000000c ++#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ ++#define SHT_MIPS_SHDR 0x70000010 ++#define SHT_MIPS_FDESC 0x70000011 ++#define SHT_MIPS_EXTSYM 0x70000012 ++#define SHT_MIPS_DENSE 0x70000013 ++#define SHT_MIPS_PDESC 0x70000014 ++#define SHT_MIPS_LOCSYM 0x70000015 ++#define SHT_MIPS_AUXSYM 0x70000016 ++#define SHT_MIPS_OPTSYM 0x70000017 ++#define SHT_MIPS_LOCSTR 0x70000018 ++#define SHT_MIPS_LINE 0x70000019 ++#define SHT_MIPS_RFDESC 0x7000001a ++#define SHT_MIPS_DELTASYM 0x7000001b ++#define SHT_MIPS_DELTAINST 0x7000001c ++#define SHT_MIPS_DELTACLASS 0x7000001d ++#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ ++#define SHT_MIPS_DELTADECL 0x7000001f ++#define SHT_MIPS_SYMBOL_LIB 0x70000020 ++#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ ++#define SHT_MIPS_TRANSLATE 0x70000022 ++#define SHT_MIPS_PIXIE 0x70000023 ++#define SHT_MIPS_XLATE 0x70000024 ++#define SHT_MIPS_XLATE_DEBUG 0x70000025 ++#define SHT_MIPS_WHIRL 0x70000026 ++#define SHT_MIPS_EH_REGION 0x70000027 ++#define SHT_MIPS_XLATE_OLD 0x70000028 ++#define SHT_MIPS_PDR_EXCEPTION 0x70000029 ++ ++/* Legal values for sh_flags field of Elf32_Shdr. */ ++ ++#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ ++#define SHF_MIPS_MERGE 0x20000000 ++#define SHF_MIPS_ADDR 0x40000000 ++#define SHF_MIPS_STRINGS 0x80000000 ++#define SHF_MIPS_NOSTRIP 0x08000000 ++#define SHF_MIPS_LOCAL 0x04000000 ++#define SHF_MIPS_NAMES 0x02000000 ++#define SHF_MIPS_NODUPE 0x01000000 ++ ++ ++/* Symbol tables. */ ++ ++/* MIPS specific values for `st_other'. */ ++#define STO_MIPS_DEFAULT 0x0 ++#define STO_MIPS_INTERNAL 0x1 ++#define STO_MIPS_HIDDEN 0x2 ++#define STO_MIPS_PROTECTED 0x3 ++#define STO_MIPS_SC_ALIGN_UNUSED 0xff ++ ++/* MIPS specific values for `st_info'. */ ++#define STB_MIPS_SPLIT_COMMON 13 ++ ++/* Entries found in sections of type SHT_MIPS_GPTAB. */ ++ ++typedef union ++{ ++ struct ++ { ++ Elf32_Word gt_current_g_value; /* -G value used for compilation */ ++ Elf32_Word gt_unused; /* Not used */ ++ } gt_header; /* First entry in section */ ++ struct ++ { ++ Elf32_Word gt_g_value; /* If this value were used for -G */ ++ Elf32_Word gt_bytes; /* This many bytes would be used */ ++ } gt_entry; /* Subsequent entries in section */ ++} Elf32_gptab; ++ ++/* Entry found in sections of type SHT_MIPS_REGINFO. */ ++ ++typedef struct ++{ ++ Elf32_Word ri_gprmask; /* General registers used */ ++ Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ ++ Elf32_Sword ri_gp_value; /* $gp register value */ ++} Elf32_RegInfo; ++ ++/* Entries found in sections of type SHT_MIPS_OPTIONS. */ ++ ++typedef struct ++{ ++ unsigned char kind; /* Determines interpretation of the ++ variable part of descriptor. */ ++ unsigned char size; /* Size of descriptor, including header. */ ++ Elf32_Section section; /* Section header index of section affected, ++ 0 for global options. */ ++ Elf32_Word info; /* Kind-specific information. */ ++} Elf_Options; ++ ++/* Values for `kind' field in Elf_Options. */ ++ ++#define ODK_NULL 0 /* Undefined. */ ++#define ODK_REGINFO 1 /* Register usage information. */ ++#define ODK_EXCEPTIONS 2 /* Exception processing options. */ ++#define ODK_PAD 3 /* Section padding options. */ ++#define ODK_HWPATCH 4 /* Hardware workarounds performed */ ++#define ODK_FILL 5 /* record the fill value used by the linker. */ ++#define ODK_TAGS 6 /* reserve space for desktop tools to write. */ ++#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ ++#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ ++ ++/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ ++ ++#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ ++#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ ++#define OEX_PAGE0 0x10000 /* page zero must be mapped. */ ++#define OEX_SMM 0x20000 /* Force sequential memory mode? */ ++#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ ++#define OEX_PRECISEFP OEX_FPDBUG ++#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ ++ ++#define OEX_FPU_INVAL 0x10 ++#define OEX_FPU_DIV0 0x08 ++#define OEX_FPU_OFLO 0x04 ++#define OEX_FPU_UFLO 0x02 ++#define OEX_FPU_INEX 0x01 ++ ++/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ ++ ++#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ ++#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ ++#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ ++#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ ++ ++#define OPAD_PREFIX 0x1 ++#define OPAD_POSTFIX 0x2 ++#define OPAD_SYMBOL 0x4 ++ ++/* Entry found in `.options' section. */ ++ ++typedef struct ++{ ++ Elf32_Word hwp_flags1; /* Extra flags. */ ++ Elf32_Word hwp_flags2; /* Extra flags. */ ++} Elf_Options_Hw; ++ ++/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ ++ ++#define OHWA0_R4KEOP_CHECKED 0x00000001 ++#define OHWA1_R4KEOP_CLEAN 0x00000002 ++ ++/* MIPS relocs. */ ++ ++#define R_MIPS_NONE 0 /* No reloc */ ++#define R_MIPS_16 1 /* Direct 16 bit */ ++#define R_MIPS_32 2 /* Direct 32 bit */ ++#define R_MIPS_REL32 3 /* PC relative 32 bit */ ++#define R_MIPS_26 4 /* Direct 26 bit shifted */ ++#define R_MIPS_HI16 5 /* High 16 bit */ ++#define R_MIPS_LO16 6 /* Low 16 bit */ ++#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ ++#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ ++#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ ++#define R_MIPS_PC16 10 /* PC relative 16 bit */ ++#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ ++#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ ++ ++#define R_MIPS_SHIFT5 16 ++#define R_MIPS_SHIFT6 17 ++#define R_MIPS_64 18 ++#define R_MIPS_GOT_DISP 19 ++#define R_MIPS_GOT_PAGE 20 ++#define R_MIPS_GOT_OFST 21 ++#define R_MIPS_GOT_HI16 22 ++#define R_MIPS_GOT_LO16 23 ++#define R_MIPS_SUB 24 ++#define R_MIPS_INSERT_A 25 ++#define R_MIPS_INSERT_B 26 ++#define R_MIPS_DELETE 27 ++#define R_MIPS_HIGHER 28 ++#define R_MIPS_HIGHEST 29 ++#define R_MIPS_CALL_HI16 30 ++#define R_MIPS_CALL_LO16 31 ++#define R_MIPS_SCN_DISP 32 ++#define R_MIPS_REL16 33 ++#define R_MIPS_ADD_IMMEDIATE 34 ++#define R_MIPS_PJUMP 35 ++#define R_MIPS_RELGOT 36 ++#define R_MIPS_JALR 37 ++/* Keep this the last entry. */ ++#define R_MIPS_NUM 38 ++ ++/* Legal values for p_type field of Elf32_Phdr. */ ++ ++#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ ++#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ ++#define PT_MIPS_OPTIONS 0x70000002 ++ ++/* Special program header types. */ ++ ++#define PF_MIPS_LOCAL 0x10000000 ++ ++/* Legal values for d_tag field of Elf32_Dyn. */ ++ ++#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ ++#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ ++#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ ++#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ ++#define DT_MIPS_FLAGS 0x70000005 /* Flags */ ++#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ ++#define DT_MIPS_MSYM 0x70000007 ++#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ ++#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ ++#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ ++#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ ++#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ ++#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ ++#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ ++#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ ++#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ ++#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ ++#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ ++#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in ++ DT_MIPS_DELTA_CLASS. */ ++#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ ++#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in ++ DT_MIPS_DELTA_INSTANCE. */ ++#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ ++#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in ++ DT_MIPS_DELTA_RELOC. */ ++#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta ++ relocations refer to. */ ++#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in ++ DT_MIPS_DELTA_SYM. */ ++#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the ++ class declaration. */ ++#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in ++ DT_MIPS_DELTA_CLASSSYM. */ ++#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ ++#define DT_MIPS_PIXIE_INIT 0x70000023 ++#define DT_MIPS_SYMBOL_LIB 0x70000024 ++#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 ++#define DT_MIPS_LOCAL_GOTIDX 0x70000026 ++#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 ++#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 ++#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */ ++#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ ++#define DT_MIPS_DYNSTR_ALIGN 0x7000002b ++#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */ ++#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve ++ function stored in GOT. */ ++#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added ++ by rld on dlopen() calls. */ ++#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ ++#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ ++#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ ++#define DT_MIPS_NUM 0x32 ++ ++/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ ++ ++#define RHF_NONE 0 /* No flags */ ++#define RHF_QUICKSTART (1 << 0) /* Use quickstart */ ++#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ ++#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ ++#define RHF_NO_MOVE (1 << 3) ++#define RHF_SGI_ONLY (1 << 4) ++#define RHF_GUARANTEE_INIT (1 << 5) ++#define RHF_DELTA_C_PLUS_PLUS (1 << 6) ++#define RHF_GUARANTEE_START_INIT (1 << 7) ++#define RHF_PIXIE (1 << 8) ++#define RHF_DEFAULT_DELAY_LOAD (1 << 9) ++#define RHF_REQUICKSTART (1 << 10) ++#define RHF_REQUICKSTARTED (1 << 11) ++#define RHF_CORD (1 << 12) ++#define RHF_NO_UNRES_UNDEF (1 << 13) ++#define RHF_RLD_ORDER_SAFE (1 << 14) ++ ++/* Entries found in sections of type SHT_MIPS_LIBLIST. */ ++ ++typedef struct ++{ ++ Elf32_Word l_name; /* Name (string table index) */ ++ Elf32_Word l_time_stamp; /* Timestamp */ ++ Elf32_Word l_checksum; /* Checksum */ ++ Elf32_Word l_version; /* Interface version */ ++ Elf32_Word l_flags; /* Flags */ ++} Elf32_Lib; ++ ++typedef struct ++{ ++ Elf64_Word l_name; /* Name (string table index) */ ++ Elf64_Word l_time_stamp; /* Timestamp */ ++ Elf64_Word l_checksum; /* Checksum */ ++ Elf64_Word l_version; /* Interface version */ ++ Elf64_Word l_flags; /* Flags */ ++} Elf64_Lib; ++ ++ ++/* Legal values for l_flags. */ ++ ++#define LL_NONE 0 ++#define LL_EXACT_MATCH (1 << 0) /* Require exact match */ ++#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ ++#define LL_REQUIRE_MINOR (1 << 2) ++#define LL_EXPORTS (1 << 3) ++#define LL_DELAY_LOAD (1 << 4) ++#define LL_DELTA (1 << 5) ++ ++/* Entries found in sections of type SHT_MIPS_CONFLICT. */ ++ ++typedef Elf32_Addr Elf32_Conflict; ++ ++ ++/* HPPA specific definitions. */ ++ ++/* Legal values for e_flags field of Elf32_Ehdr. */ ++ ++#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ ++#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ ++#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ ++#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ ++#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch ++ prediction. */ ++#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ ++#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ ++ ++/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ ++ ++#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ ++#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ ++#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ ++ ++/* Additional section indeces. */ ++ ++#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared ++ symbols in ANSI C. */ ++#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ ++ ++/* Legal values for sh_type field of Elf32_Shdr. */ ++ ++#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ ++#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ ++#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ ++ ++/* Legal values for sh_flags field of Elf32_Shdr. */ ++ ++#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ ++#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ ++#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ ++ ++/* Legal values for ST_TYPE subfield of st_info (symbol type). */ ++ ++#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ ++ ++#define STT_HP_OPAQUE (STT_LOOS + 0x1) ++#define STT_HP_STUB (STT_LOOS + 0x2) ++ ++/* HPPA relocs. */ ++ ++#define R_PARISC_NONE 0 /* No reloc. */ ++#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ ++#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ ++#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ ++#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ ++#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ ++#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ ++#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ ++#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ ++#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ ++#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ ++#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ ++#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ ++#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ ++#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ ++#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ ++#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ ++#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ ++#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ ++#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ ++#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ ++#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ ++#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ ++#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ ++#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ ++#define R_PARISC_FPTR64 64 /* 64 bits function address. */ ++#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ ++#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ ++#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ ++#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ ++#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ ++#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ ++#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ ++#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ ++#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ ++#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ ++#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ ++#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ ++#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ ++#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ ++#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ ++#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ ++#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ ++#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ ++#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ ++#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ ++#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ ++#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ ++#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ ++#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ ++#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ ++#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ ++#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ ++#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ ++#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ ++#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ ++#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ ++#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ ++#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ ++#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ ++#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ ++#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ ++#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ ++#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ ++#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ ++#define R_PARISC_LORESERVE 128 ++#define R_PARISC_COPY 128 /* Copy relocation. */ ++#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ ++#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ ++#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ ++#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ ++#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ ++#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ ++#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ ++#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ ++#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ ++#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ ++#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ ++#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ ++#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ ++#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ ++#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ ++#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ ++#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ ++#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ ++#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ ++#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ ++#define R_PARISC_HIRESERVE 255 ++ ++/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ ++ ++#define PT_HP_TLS (PT_LOOS + 0x0) ++#define PT_HP_CORE_NONE (PT_LOOS + 0x1) ++#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) ++#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) ++#define PT_HP_CORE_COMM (PT_LOOS + 0x4) ++#define PT_HP_CORE_PROC (PT_LOOS + 0x5) ++#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) ++#define PT_HP_CORE_STACK (PT_LOOS + 0x7) ++#define PT_HP_CORE_SHM (PT_LOOS + 0x8) ++#define PT_HP_CORE_MMF (PT_LOOS + 0x9) ++#define PT_HP_PARALLEL (PT_LOOS + 0x10) ++#define PT_HP_FASTBIND (PT_LOOS + 0x11) ++#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) ++#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) ++#define PT_HP_STACK (PT_LOOS + 0x14) ++ ++#define PT_PARISC_ARCHEXT 0x70000000 ++#define PT_PARISC_UNWIND 0x70000001 ++ ++/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ ++ ++#define PF_PARISC_SBP 0x08000000 ++ ++#define PF_HP_PAGE_SIZE 0x00100000 ++#define PF_HP_FAR_SHARED 0x00200000 ++#define PF_HP_NEAR_SHARED 0x00400000 ++#define PF_HP_CODE 0x01000000 ++#define PF_HP_MODIFY 0x02000000 ++#define PF_HP_LAZYSWAP 0x04000000 ++#define PF_HP_SBP 0x08000000 ++ ++ ++/* Alpha specific definitions. */ ++ ++/* Legal values for e_flags field of Elf64_Ehdr. */ ++ ++#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ ++#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ ++ ++/* Legal values for sh_type field of Elf64_Shdr. */ ++ ++/* These two are primerily concerned with ECOFF debugging info. */ ++#define SHT_ALPHA_DEBUG 0x70000001 ++#define SHT_ALPHA_REGINFO 0x70000002 ++ ++/* Legal values for sh_flags field of Elf64_Shdr. */ ++ ++#define SHF_ALPHA_GPREL 0x10000000 ++ ++/* Legal values for st_other field of Elf64_Sym. */ ++#define STO_ALPHA_NOPV 0x80 /* No PV required. */ ++#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ ++ ++/* Alpha relocs. */ ++ ++#define R_ALPHA_NONE 0 /* No reloc */ ++#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ ++#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ ++#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ ++#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ ++#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ ++#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ ++#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ ++#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ ++#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ ++#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ ++#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ ++#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ ++#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ ++#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ ++#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ ++#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ ++#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ ++#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ ++#define R_ALPHA_TLS_GD_HI 28 ++#define R_ALPHA_TLSGD 29 ++#define R_ALPHA_TLS_LDM 30 ++#define R_ALPHA_DTPMOD64 31 ++#define R_ALPHA_GOTDTPREL 32 ++#define R_ALPHA_DTPREL64 33 ++#define R_ALPHA_DTPRELHI 34 ++#define R_ALPHA_DTPRELLO 35 ++#define R_ALPHA_DTPREL16 36 ++#define R_ALPHA_GOTTPREL 37 ++#define R_ALPHA_TPREL64 38 ++#define R_ALPHA_TPRELHI 39 ++#define R_ALPHA_TPRELLO 40 ++#define R_ALPHA_TPREL16 41 ++/* Keep this the last entry. */ ++#define R_ALPHA_NUM 46 ++ ++/* Magic values of the LITUSE relocation addend. */ ++#define LITUSE_ALPHA_ADDR 0 ++#define LITUSE_ALPHA_BASE 1 ++#define LITUSE_ALPHA_BYTOFF 2 ++#define LITUSE_ALPHA_JSR 3 ++#define LITUSE_ALPHA_TLS_GD 4 ++#define LITUSE_ALPHA_TLS_LDM 5 ++ ++ ++/* PowerPC specific declarations */ ++ ++/* Values for Elf32/64_Ehdr.e_flags. */ ++#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ ++ ++/* Cygnus local bits below */ ++#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ ++#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib ++ flag */ ++ ++/* PowerPC relocations defined by the ABIs */ ++#define R_PPC_NONE 0 ++#define R_PPC_ADDR32 1 /* 32bit absolute address */ ++#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ ++#define R_PPC_ADDR16 3 /* 16bit absolute address */ ++#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ ++#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ ++#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ ++#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ ++#define R_PPC_ADDR14_BRTAKEN 8 ++#define R_PPC_ADDR14_BRNTAKEN 9 ++#define R_PPC_REL24 10 /* PC relative 26 bit */ ++#define R_PPC_REL14 11 /* PC relative 16 bit */ ++#define R_PPC_REL14_BRTAKEN 12 ++#define R_PPC_REL14_BRNTAKEN 13 ++#define R_PPC_GOT16 14 ++#define R_PPC_GOT16_LO 15 ++#define R_PPC_GOT16_HI 16 ++#define R_PPC_GOT16_HA 17 ++#define R_PPC_PLTREL24 18 ++#define R_PPC_COPY 19 ++#define R_PPC_GLOB_DAT 20 ++#define R_PPC_JMP_SLOT 21 ++#define R_PPC_RELATIVE 22 ++#define R_PPC_LOCAL24PC 23 ++#define R_PPC_UADDR32 24 ++#define R_PPC_UADDR16 25 ++#define R_PPC_REL32 26 ++#define R_PPC_PLT32 27 ++#define R_PPC_PLTREL32 28 ++#define R_PPC_PLT16_LO 29 ++#define R_PPC_PLT16_HI 30 ++#define R_PPC_PLT16_HA 31 ++#define R_PPC_SDAREL16 32 ++#define R_PPC_SECTOFF 33 ++#define R_PPC_SECTOFF_LO 34 ++#define R_PPC_SECTOFF_HI 35 ++#define R_PPC_SECTOFF_HA 36 ++ ++/* PowerPC relocations defined for the TLS access ABI. */ ++#define R_PPC_TLS 67 /* none (sym+add)@tls */ ++#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ ++#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ ++#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ ++#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ ++#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ ++#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ ++#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ ++#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ ++#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ ++#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ ++#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ ++#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ ++#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ ++#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ ++#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ ++#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ ++#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ ++#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ ++#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ ++#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */ ++#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */ ++#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ ++#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ ++#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */ ++#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */ ++#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */ ++#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */ ++ ++/* Keep this the last entry. */ ++#define R_PPC_NUM 95 ++ ++/* The remaining relocs are from the Embedded ELF ABI, and are not ++ in the SVR4 ELF ABI. */ ++#define R_PPC_EMB_NADDR32 101 ++#define R_PPC_EMB_NADDR16 102 ++#define R_PPC_EMB_NADDR16_LO 103 ++#define R_PPC_EMB_NADDR16_HI 104 ++#define R_PPC_EMB_NADDR16_HA 105 ++#define R_PPC_EMB_SDAI16 106 ++#define R_PPC_EMB_SDA2I16 107 ++#define R_PPC_EMB_SDA2REL 108 ++#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ ++#define R_PPC_EMB_MRKREF 110 ++#define R_PPC_EMB_RELSEC16 111 ++#define R_PPC_EMB_RELST_LO 112 ++#define R_PPC_EMB_RELST_HI 113 ++#define R_PPC_EMB_RELST_HA 114 ++#define R_PPC_EMB_BIT_FLD 115 ++#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ ++ ++/* Diab tool relocations. */ ++#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ ++#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ ++#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ ++#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ ++#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ ++#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ ++ ++/* This is a phony reloc to handle any old fashioned TOC16 references ++ that may still be in object files. */ ++#define R_PPC_TOC16 255 ++ ++ ++/* PowerPC64 relocations defined by the ABIs */ ++#define R_PPC64_NONE R_PPC_NONE ++#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */ ++#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */ ++#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */ ++#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */ ++#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */ ++#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ ++#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */ ++#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN ++#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN ++#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */ ++#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */ ++#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN ++#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN ++#define R_PPC64_GOT16 R_PPC_GOT16 ++#define R_PPC64_GOT16_LO R_PPC_GOT16_LO ++#define R_PPC64_GOT16_HI R_PPC_GOT16_HI ++#define R_PPC64_GOT16_HA R_PPC_GOT16_HA ++ ++#define R_PPC64_COPY R_PPC_COPY ++#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT ++#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT ++#define R_PPC64_RELATIVE R_PPC_RELATIVE ++ ++#define R_PPC64_UADDR32 R_PPC_UADDR32 ++#define R_PPC64_UADDR16 R_PPC_UADDR16 ++#define R_PPC64_REL32 R_PPC_REL32 ++#define R_PPC64_PLT32 R_PPC_PLT32 ++#define R_PPC64_PLTREL32 R_PPC_PLTREL32 ++#define R_PPC64_PLT16_LO R_PPC_PLT16_LO ++#define R_PPC64_PLT16_HI R_PPC_PLT16_HI ++#define R_PPC64_PLT16_HA R_PPC_PLT16_HA ++ ++#define R_PPC64_SECTOFF R_PPC_SECTOFF ++#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO ++#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI ++#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA ++#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */ ++#define R_PPC64_ADDR64 38 /* doubleword64 S + A */ ++#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */ ++#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */ ++#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */ ++#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */ ++#define R_PPC64_UADDR64 43 /* doubleword64 S + A */ ++#define R_PPC64_REL64 44 /* doubleword64 S + A - P */ ++#define R_PPC64_PLT64 45 /* doubleword64 L + A */ ++#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */ ++#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */ ++#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */ ++#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */ ++#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */ ++#define R_PPC64_TOC 51 /* doubleword64 .TOC */ ++#define R_PPC64_PLTGOT16 52 /* half16* M + A */ ++#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */ ++#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */ ++#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */ ++ ++#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */ ++#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */ ++#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */ ++#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */ ++#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */ ++#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */ ++#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */ ++#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */ ++#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */ ++#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */ ++#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */ ++ ++/* PowerPC64 relocations defined for the TLS access ABI. */ ++#define R_PPC64_TLS 67 /* none (sym+add)@tls */ ++#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ ++#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ ++#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ ++#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ ++#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ ++#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ ++#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ ++#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ ++#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ ++#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ ++#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ ++#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ ++#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ ++#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ ++#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ ++#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ ++#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ ++#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ ++#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ ++#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */ ++#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */ ++#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ ++#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ ++#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */ ++#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */ ++#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */ ++#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */ ++#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ ++#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */ ++#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */ ++#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */ ++#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */ ++#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */ ++#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ ++#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */ ++#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */ ++#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ ++#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ ++#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ ++ ++/* Keep this the last entry. */ ++#define R_PPC64_NUM 107 ++ ++/* PowerPC64 specific values for the Dyn d_tag field. */ ++#define DT_PPC64_GLINK (DT_LOPROC + 0) ++#define DT_PPC64_NUM 1 ++ ++ ++/* ARM specific declarations */ ++ ++/* Processor specific flags for the ELF header e_flags field. */ ++#define EF_ARM_RELEXEC 0x01 ++#define EF_ARM_HASENTRY 0x02 ++#define EF_ARM_INTERWORK 0x04 ++#define EF_ARM_APCS_26 0x08 ++#define EF_ARM_APCS_FLOAT 0x10 ++#define EF_ARM_PIC 0x20 ++#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ ++#define EF_ARM_NEW_ABI 0x80 ++#define EF_ARM_OLD_ABI 0x100 ++ ++/* Other constants defined in the ARM ELF spec. version B-01. */ ++/* NB. These conflict with values defined above. */ ++#define EF_ARM_SYMSARESORTED 0x04 ++#define EF_ARM_DYNSYMSUSESEGIDX 0x08 ++#define EF_ARM_MAPSYMSFIRST 0x10 ++#define EF_ARM_EABIMASK 0XFF000000 ++ ++#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) ++#define EF_ARM_EABI_UNKNOWN 0x00000000 ++#define EF_ARM_EABI_VER1 0x01000000 ++#define EF_ARM_EABI_VER2 0x02000000 ++ ++/* Additional symbol types for Thumb */ ++#define STT_ARM_TFUNC 0xd ++ ++/* ARM-specific values for sh_flags */ ++#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ ++#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined ++ in the input to a link step */ ++ ++/* ARM-specific program header flags */ ++#define PF_ARM_SB 0x10000000 /* Segment contains the location ++ addressed by the static base */ ++ ++/* ARM relocs. */ ++#define R_ARM_NONE 0 /* No reloc */ ++#define R_ARM_PC24 1 /* PC relative 26 bit branch */ ++#define R_ARM_ABS32 2 /* Direct 32 bit */ ++#define R_ARM_REL32 3 /* PC relative 32 bit */ ++#define R_ARM_PC13 4 ++#define R_ARM_ABS16 5 /* Direct 16 bit */ ++#define R_ARM_ABS12 6 /* Direct 12 bit */ ++#define R_ARM_THM_ABS5 7 ++#define R_ARM_ABS8 8 /* Direct 8 bit */ ++#define R_ARM_SBREL32 9 ++#define R_ARM_THM_PC22 10 ++#define R_ARM_THM_PC8 11 ++#define R_ARM_AMP_VCALL9 12 ++#define R_ARM_SWI24 13 ++#define R_ARM_THM_SWI8 14 ++#define R_ARM_XPC25 15 ++#define R_ARM_THM_XPC22 16 ++#define R_ARM_COPY 20 /* Copy symbol at runtime */ ++#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ ++#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ ++#define R_ARM_RELATIVE 23 /* Adjust by program base */ ++#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ ++#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ ++#define R_ARM_GOT32 26 /* 32 bit GOT entry */ ++#define R_ARM_PLT32 27 /* 32 bit PLT address */ ++#define R_ARM_ALU_PCREL_7_0 32 ++#define R_ARM_ALU_PCREL_15_8 33 ++#define R_ARM_ALU_PCREL_23_15 34 ++#define R_ARM_LDR_SBREL_11_0 35 ++#define R_ARM_ALU_SBREL_19_12 36 ++#define R_ARM_ALU_SBREL_27_20 37 ++#define R_ARM_GNU_VTENTRY 100 ++#define R_ARM_GNU_VTINHERIT 101 ++#define R_ARM_THM_PC11 102 /* thumb unconditional branch */ ++#define R_ARM_THM_PC9 103 /* thumb conditional branch */ ++#define R_ARM_RXPC25 249 ++#define R_ARM_RSBREL32 250 ++#define R_ARM_THM_RPC22 251 ++#define R_ARM_RREL32 252 ++#define R_ARM_RABS22 253 ++#define R_ARM_RPC24 254 ++#define R_ARM_RBASE 255 ++/* Keep this the last entry. */ ++#define R_ARM_NUM 256 ++ ++/* IA-64 specific declarations. */ ++ ++/* Processor specific flags for the Ehdr e_flags field. */ ++#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ ++#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ ++#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ ++ ++/* Processor specific values for the Phdr p_type field. */ ++#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ ++#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ ++ ++/* Processor specific flags for the Phdr p_flags field. */ ++#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ ++ ++/* Processor specific values for the Shdr sh_type field. */ ++#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ ++#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ ++ ++/* Processor specific flags for the Shdr sh_flags field. */ ++#define SHF_IA_64_SHORT 0x10000000 /* section near gp */ ++#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ ++ ++/* Processor specific values for the Dyn d_tag field. */ ++#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) ++#define DT_IA_64_NUM 1 ++ ++/* IA-64 relocations. */ ++#define R_IA64_NONE 0x00 /* none */ ++#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ ++#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ ++#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ ++#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ ++#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ ++#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ ++#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ ++#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ ++#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ ++#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ ++#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ ++#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ ++#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ ++#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ ++#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ ++#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ ++#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ ++#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ ++#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ ++#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ ++#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ ++#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ ++#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ ++#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ ++#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ ++#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ ++#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ ++#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ ++#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ ++#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ ++#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ ++#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ ++#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ ++#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ ++#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ ++#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ ++#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ ++#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ ++#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ ++#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ ++#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ ++#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ ++#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ ++#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ ++#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ ++#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ ++#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ ++#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ ++#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ ++#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ ++#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ ++#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ ++#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ ++#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ ++#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ ++#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ ++#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ ++#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ ++#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ ++#define R_IA64_COPY 0x84 /* copy relocation */ ++#define R_IA64_SUB 0x85 /* Addend and symbol difference */ ++#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ ++#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ ++#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ ++#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ ++#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ ++#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ ++#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ ++#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ ++#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ ++#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ ++#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ ++#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ ++#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ ++#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ ++#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ ++#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ ++#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ ++#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ ++#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ ++ ++/* SH specific declarations */ ++ ++/* SH relocs. */ ++#define R_SH_NONE 0 ++#define R_SH_DIR32 1 ++#define R_SH_REL32 2 ++#define R_SH_DIR8WPN 3 ++#define R_SH_IND12W 4 ++#define R_SH_DIR8WPL 5 ++#define R_SH_DIR8WPZ 6 ++#define R_SH_DIR8BP 7 ++#define R_SH_DIR8W 8 ++#define R_SH_DIR8L 9 ++#define R_SH_SWITCH16 25 ++#define R_SH_SWITCH32 26 ++#define R_SH_USES 27 ++#define R_SH_COUNT 28 ++#define R_SH_ALIGN 29 ++#define R_SH_CODE 30 ++#define R_SH_DATA 31 ++#define R_SH_LABEL 32 ++#define R_SH_SWITCH8 33 ++#define R_SH_GNU_VTINHERIT 34 ++#define R_SH_GNU_VTENTRY 35 ++#define R_SH_TLS_GD_32 144 ++#define R_SH_TLS_LD_32 145 ++#define R_SH_TLS_LDO_32 146 ++#define R_SH_TLS_IE_32 147 ++#define R_SH_TLS_LE_32 148 ++#define R_SH_TLS_DTPMOD32 149 ++#define R_SH_TLS_DTPOFF32 150 ++#define R_SH_TLS_TPOFF32 151 ++#define R_SH_GOT32 160 ++#define R_SH_PLT32 161 ++#define R_SH_COPY 162 ++#define R_SH_GLOB_DAT 163 ++#define R_SH_JMP_SLOT 164 ++#define R_SH_RELATIVE 165 ++#define R_SH_GOTOFF 166 ++#define R_SH_GOTPC 167 ++/* Keep this the last entry. */ ++#define R_SH_NUM 256 ++ ++/* Additional s390 relocs */ ++ ++#define R_390_NONE 0 /* No reloc. */ ++#define R_390_8 1 /* Direct 8 bit. */ ++#define R_390_12 2 /* Direct 12 bit. */ ++#define R_390_16 3 /* Direct 16 bit. */ ++#define R_390_32 4 /* Direct 32 bit. */ ++#define R_390_PC32 5 /* PC relative 32 bit. */ ++#define R_390_GOT12 6 /* 12 bit GOT offset. */ ++#define R_390_GOT32 7 /* 32 bit GOT offset. */ ++#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ ++#define R_390_COPY 9 /* Copy symbol at runtime. */ ++#define R_390_GLOB_DAT 10 /* Create GOT entry. */ ++#define R_390_JMP_SLOT 11 /* Create PLT entry. */ ++#define R_390_RELATIVE 12 /* Adjust by program base. */ ++#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ ++#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ ++#define R_390_GOT16 15 /* 16 bit GOT offset. */ ++#define R_390_PC16 16 /* PC relative 16 bit. */ ++#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ ++#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ ++#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ ++#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ ++#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ ++#define R_390_64 22 /* Direct 64 bit. */ ++#define R_390_PC64 23 /* PC relative 64 bit. */ ++#define R_390_GOT64 24 /* 64 bit GOT offset. */ ++#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ ++#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ ++#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ ++#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ ++#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ ++#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ ++#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ ++#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ ++#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ ++#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ ++#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ ++#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ ++#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ ++#define R_390_TLS_GDCALL 38 /* Tag for function call in general ++ dynamic TLS code. */ ++#define R_390_TLS_LDCALL 39 /* Tag for function call in local ++ dynamic TLS code. */ ++#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic ++ thread local data. */ ++#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic ++ thread local data. */ ++#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS ++ block offset. */ ++#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS ++ block offset. */ ++#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS ++ block offset. */ ++#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic ++ thread local data in LE code. */ ++#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic ++ thread local data in LE code. */ ++#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for ++ negated static TLS block offset. */ ++#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for ++ negated static TLS block offset. */ ++#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for ++ negated static TLS block offset. */ ++#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to ++ static TLS block. */ ++#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to ++ static TLS block. */ ++#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS ++ block. */ ++#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS ++ block. */ ++#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ ++#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ ++#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS ++ block. */ ++ ++/* Keep this the last entry. */ ++#define R_390_NUM 57 ++ ++/* CRIS relocations. */ ++#define R_CRIS_NONE 0 ++#define R_CRIS_8 1 ++#define R_CRIS_16 2 ++#define R_CRIS_32 3 ++#define R_CRIS_8_PCREL 4 ++#define R_CRIS_16_PCREL 5 ++#define R_CRIS_32_PCREL 6 ++#define R_CRIS_GNU_VTINHERIT 7 ++#define R_CRIS_GNU_VTENTRY 8 ++#define R_CRIS_COPY 9 ++#define R_CRIS_GLOB_DAT 10 ++#define R_CRIS_JUMP_SLOT 11 ++#define R_CRIS_RELATIVE 12 ++#define R_CRIS_16_GOT 13 ++#define R_CRIS_32_GOT 14 ++#define R_CRIS_16_GOTPLT 15 ++#define R_CRIS_32_GOTPLT 16 ++#define R_CRIS_32_GOTREL 17 ++#define R_CRIS_32_PLT_GOTREL 18 ++#define R_CRIS_32_PLT_PCREL 19 ++ ++#define R_CRIS_NUM 20 ++ ++/* AMD x86-64 relocations. */ ++#define R_X86_64_NONE 0 /* No reloc */ ++#define R_X86_64_64 1 /* Direct 64 bit */ ++#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ ++#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ ++#define R_X86_64_PLT32 4 /* 32 bit PLT address */ ++#define R_X86_64_COPY 5 /* Copy symbol at runtime */ ++#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ ++#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ ++#define R_X86_64_RELATIVE 8 /* Adjust by program base */ ++#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative ++ offset to GOT */ ++#define R_X86_64_32 10 /* Direct 32 bit zero extended */ ++#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ ++#define R_X86_64_16 12 /* Direct 16 bit zero extended */ ++#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ ++#define R_X86_64_8 14 /* Direct 8 bit sign extended */ ++#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ ++#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ ++#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ ++#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ ++#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset ++ to two GOT entries for GD symbol */ ++#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset ++ to two GOT entries for LD symbol */ ++#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ ++#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset ++ to GOT entry for IE symbol */ ++#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ ++ ++#define R_X86_64_NUM 24 ++ ++__END_DECLS ++ ++#endif /* elf.h */ + + #include "elfconfig.h" + +@@ -195,3 +2641,4 @@ + void fatal(const char *fmt, ...); + void warn(const char *fmt, ...); + void merror(const char *fmt, ...); ++ +diff -Nur linux-2.6.36.orig/scripts/mod/sumversion.c linux-2.6.36/scripts/mod/sumversion.c +--- linux-2.6.36.orig/scripts/mod/sumversion.c 2010-10-20 22:30:22.000000000 +0200 ++++ linux-2.6.36/scripts/mod/sumversion.c 2010-11-28 18:33:24.000000000 +0100 +@@ -1,4 +1,4 @@ +-#include <netinet/in.h> ++/* #include <netinet/in.h> */ + #ifdef __sun__ + #include <inttypes.h> + #else diff --git a/target/linux/patches/2.6.39/fon2100.patch b/target/linux/patches/2.6.39/fon2100.patch new file mode 100644 index 000000000..038ff7020 --- /dev/null +++ b/target/linux/patches/2.6.39/fon2100.patch @@ -0,0 +1,6279 @@ +diff -Nur linux-2.6.39-rc7.orig/arch/mips/Kbuild.platforms linux-2.6.39-rc7/arch/mips/Kbuild.platforms +--- linux-2.6.39-rc7.orig/arch/mips/Kbuild.platforms 2011-05-10 04:33:54.000000000 +0200 ++++ linux-2.6.39-rc7/arch/mips/Kbuild.platforms 2011-05-15 21:34:57.000000000 +0200 +@@ -6,6 +6,7 @@ + platforms += bcm47xx + platforms += bcm63xx + platforms += cavium-octeon ++platforms += ar231x + platforms += cobalt + platforms += dec + platforms += emma +diff -Nur linux-2.6.39-rc7.orig/arch/mips/Kconfig linux-2.6.39-rc7/arch/mips/Kconfig +--- linux-2.6.39-rc7.orig/arch/mips/Kconfig 2011-05-10 04:33:54.000000000 +0200 ++++ linux-2.6.39-rc7/arch/mips/Kconfig 2011-05-16 12:11:11.000000000 +0200 +@@ -121,6 +121,21 @@ + help + Support for BCM63XX based boards + ++config ATHEROS_AR231X ++ bool "Atheros 231x/531x SoC support" ++ select CEVT_R4K ++ select CSRC_R4K ++ select DMA_NONCOHERENT ++ select IRQ_CPU ++ select SYS_HAS_CPU_MIPS32_R1 ++ select SYS_SUPPORTS_BIG_ENDIAN ++ select SYS_SUPPORTS_32BIT_KERNEL ++ select GENERIC_GPIO ++ select SYS_HAS_EARLY_PRINTK ++ select SYS_SUPPORTS_ZBOOT ++ help ++ Support for AR231x and AR531x based boards ++ + config MIPS_COBALT + bool "Cobalt Server" + select CEVT_R4K +@@ -738,6 +753,7 @@ + + endchoice + ++source "arch/mips/ar231x/Kconfig" + source "arch/mips/alchemy/Kconfig" + source "arch/mips/ath79/Kconfig" + source "arch/mips/bcm63xx/Kconfig" +diff -Nur linux-2.6.39-rc7.orig/arch/mips/ar231x/Kconfig linux-2.6.39-rc7/arch/mips/ar231x/Kconfig +--- linux-2.6.39-rc7.orig/arch/mips/ar231x/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/ar231x/Kconfig 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,27 @@ ++config ATHEROS_AR5312 ++ bool "Atheros 5312/2312+ support" ++ depends on ATHEROS_AR231X ++ default y ++ ++config ATHEROS_AR2315 ++ bool "Atheros 2315+ support" ++ depends on ATHEROS_AR231X ++ select DMA_NONCOHERENT ++ select CEVT_R4K ++ select CSRC_R4K ++ select IRQ_CPU ++ select SYS_HAS_CPU_MIPS32_R1 ++ select SYS_SUPPORTS_32BIT_KERNEL ++ select SYS_SUPPORTS_BIG_ENDIAN ++ select GENERIC_GPIO ++ default y ++ ++config ATHEROS_AR2315_PCI ++ bool "PCI support" ++ depends on ATHEROS_AR2315 ++ select HW_HAS_PCI ++ select PCI ++ select USB_ARCH_HAS_HCD ++ select USB_ARCH_HAS_OHCI ++ select USB_ARCH_HAS_EHCI ++ default n +diff -Nur linux-2.6.39-rc7.orig/arch/mips/ar231x/Makefile linux-2.6.39-rc7/arch/mips/ar231x/Makefile +--- linux-2.6.39-rc7.orig/arch/mips/ar231x/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/ar231x/Makefile 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,17 @@ ++# ++# 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) 2006 FON Technology, SL. ++# Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> ++# Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> ++# ++ ++obj-y += board.o prom.o devices.o ++ ++obj-$(CONFIG_EARLY_PRINTK) += early_printk.o ++ ++obj-$(CONFIG_ATHEROS_AR5312) += ar5312.o ++obj-$(CONFIG_ATHEROS_AR2315) += ar2315.o ++obj-$(CONFIG_ATHEROS_AR2315_PCI) += pci.o +diff -Nur linux-2.6.39-rc7.orig/arch/mips/ar231x/Platform linux-2.6.39-rc7/arch/mips/ar231x/Platform +--- linux-2.6.39-rc7.orig/arch/mips/ar231x/Platform 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/ar231x/Platform 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,6 @@ ++# ++# Atheros AR5312/AR2312 WiSoC ++# ++platform-$(CONFIG_ATHEROS_AR231X) += ar231x/ ++cflags-$(CONFIG_ATHEROS_AR231X) += -I$(srctree)/arch/mips/include/asm/mach-ar231x ++load-$(CONFIG_ATHEROS_AR231X) += 0xffffffff80041000 +diff -Nur linux-2.6.39-rc7.orig/arch/mips/ar231x/ar2315.c linux-2.6.39-rc7/arch/mips/ar231x/ar2315.c +--- linux-2.6.39-rc7.orig/arch/mips/ar231x/ar2315.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/ar231x/ar2315.c 2011-05-15 21:47:07.000000000 +0200 +@@ -0,0 +1,654 @@ ++/* ++ * 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) 2003 Atheros Communications, Inc., All Rights Reserved. ++ * Copyright (C) 2006 FON Technology, SL. ++ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> ++ */ ++ ++/* ++ * Platform devices for Atheros SoCs ++ */ ++ ++#include <generated/autoconf.h> ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/string.h> ++#include <linux/platform_device.h> ++#include <linux/kernel.h> ++#include <linux/reboot.h> ++#include <linux/delay.h> ++#include <linux/leds.h> ++#include <asm/bootinfo.h> ++#include <asm/reboot.h> ++#include <asm/time.h> ++#include <asm/irq.h> ++#include <asm/io.h> ++#include <asm/gpio.h> ++ ++#include <ar231x_platform.h> ++#include <ar2315_regs.h> ++#include <ar231x.h> ++#include "devices.h" ++#include "ar2315.h" ++ ++static u32 gpiointmask = 0, gpiointval = 0; ++ ++static inline void ar2315_gpio_irq(void) ++{ ++ u32 pend; ++ int bit = -1; ++ ++ /* only do one gpio interrupt at a time */ ++ pend = (ar231x_read_reg(AR2315_GPIO_DI) ^ gpiointval) & gpiointmask; ++ ++ if (pend) { ++ bit = fls(pend) - 1; ++ pend &= ~(1 << bit); ++ gpiointval ^= (1 << bit); ++ } ++ ++ if (!pend) ++ ar231x_write_reg(AR2315_ISR, AR2315_ISR_GPIO); ++ ++ /* Enable interrupt with edge detection */ ++ if ((ar231x_read_reg(AR2315_GPIO_CR) & AR2315_GPIO_CR_M(bit)) != AR2315_GPIO_CR_I(bit)) ++ return; ++ ++ if (bit >= 0) ++ do_IRQ(AR531X_GPIO_IRQ_BASE + bit); ++} ++ ++#ifdef CONFIG_ATHEROS_AR2315_PCI ++static inline void pci_abort_irq(void) ++{ ++ ar231x_write_reg(AR2315_PCI_INT_STATUS, AR2315_PCI_ABORT_INT); ++} ++ ++static inline void pci_ack_irq(void) ++{ ++ ar231x_write_reg(AR2315_PCI_INT_STATUS, AR2315_PCI_EXT_INT); ++} ++ ++void ar2315_pci_irq(int irq) ++{ ++ if (ar231x_read_reg(AR2315_PCI_INT_STATUS) == AR2315_PCI_ABORT_INT) ++ pci_abort_irq(); ++ else { ++ do_IRQ(irq); ++ pci_ack_irq(); ++ } ++} ++#endif /* CONFIG_ATHEROS_AR2315_PCI */ ++ ++/* ++ * Called when an interrupt is received, this function ++ * determines exactly which interrupt it was, and it ++ * invokes the appropriate handler. ++ * ++ * Implicitly, we also define interrupt priority by ++ * choosing which to dispatch first. ++ */ ++static asmlinkage void ++ar2315_irq_dispatch(void) ++{ ++ int pending = read_c0_status() & read_c0_cause(); ++ ++ if (pending & CAUSEF_IP3) ++ do_IRQ(AR2315_IRQ_WLAN0_INTRS); ++ else if (pending & CAUSEF_IP4) ++ do_IRQ(AR2315_IRQ_ENET0_INTRS); ++#ifdef CONFIG_ATHEROS_AR2315_PCI ++ else if (pending & CAUSEF_IP5) ++ ar2315_pci_irq(AR2315_IRQ_LCBUS_PCI); ++#endif ++ else if (pending & CAUSEF_IP2) { ++ unsigned int misc_intr = ar231x_read_reg(AR2315_ISR) & ar231x_read_reg(AR2315_IMR); ++ ++ if (misc_intr & AR2315_ISR_SPI) ++ do_IRQ(AR531X_MISC_IRQ_SPI); ++ else if (misc_intr & AR2315_ISR_TIMER) ++ do_IRQ(AR531X_MISC_IRQ_TIMER); ++ else if (misc_intr & AR2315_ISR_AHB) ++ do_IRQ(AR531X_MISC_IRQ_AHB_PROC); ++ else if (misc_intr & AR2315_ISR_GPIO) ++ ar2315_gpio_irq(); ++ else if (misc_intr & AR2315_ISR_UART0) ++ do_IRQ(AR531X_MISC_IRQ_UART0); ++ else if (misc_intr & AR2315_ISR_WD) ++ do_IRQ(AR531X_MISC_IRQ_WATCHDOG); ++ else ++ do_IRQ(AR531X_MISC_IRQ_NONE); ++ } else if (pending & CAUSEF_IP7) ++ do_IRQ(AR531X_IRQ_CPU_CLOCK); ++} ++ ++static void ar2315_set_gpiointmask(int gpio, int level) ++{ ++ u32 reg; ++ ++ reg = ar231x_read_reg(AR2315_GPIO_INT); ++ reg &= ~(AR2315_GPIO_INT_M | AR2315_GPIO_INT_LVL_M); ++ reg |= gpio | AR2315_GPIO_INT_LVL(level); ++ ar231x_write_reg(AR2315_GPIO_INT, reg); ++} ++ ++static void ar2315_gpio_intr_enable(struct irq_data *d) ++{ ++ unsigned int gpio = d->irq - AR531X_GPIO_IRQ_BASE; ++ ++ /* Enable interrupt with edge detection */ ++ if ((ar231x_read_reg(AR2315_GPIO_CR) & AR2315_GPIO_CR_M(gpio)) != AR2315_GPIO_CR_I(gpio)) ++ return; ++ ++ gpiointmask |= (1 << gpio); ++ ar2315_set_gpiointmask(gpio, 3); ++} ++ ++static void ar2315_gpio_intr_disable(struct irq_data *d) ++{ ++ unsigned int gpio = d->irq - AR531X_GPIO_IRQ_BASE; ++ ++ /* Disable interrupt */ ++ gpiointmask &= ~(1 << gpio); ++ ar2315_set_gpiointmask(gpio, 0); ++} ++ ++static struct irq_chip ar2315_gpio_intr_controller = { ++ .name = "AR2315-GPIO", ++ .irq_ack = ar2315_gpio_intr_disable, ++ .irq_mask_ack = ar2315_gpio_intr_disable, ++ .irq_mask = ar2315_gpio_intr_disable, ++ .irq_unmask = ar2315_gpio_intr_enable, ++}; ++ ++static void ++ar2315_misc_intr_enable(struct irq_data *d) ++{ ++ unsigned int imr; ++ ++ imr = ar231x_read_reg(AR2315_IMR); ++ switch(d->irq) { ++ case AR531X_MISC_IRQ_SPI: ++ imr |= AR2315_ISR_SPI; ++ break; ++ case AR531X_MISC_IRQ_TIMER: ++ imr |= AR2315_ISR_TIMER; ++ break; ++ case AR531X_MISC_IRQ_AHB_PROC: ++ imr |= AR2315_ISR_AHB; ++ break; ++ case AR531X_MISC_IRQ_GPIO: ++ imr |= AR2315_ISR_GPIO; ++ break; ++ case AR531X_MISC_IRQ_UART0: ++ imr |= AR2315_ISR_UART0; ++ break; ++ case AR531X_MISC_IRQ_WATCHDOG: ++ imr |= AR2315_ISR_WD; ++ break; ++ default: ++ break; ++ } ++ ar231x_write_reg(AR2315_IMR, imr); ++} ++ ++static void ++ar2315_misc_intr_disable(struct irq_data *d) ++{ ++ unsigned int imr; ++ ++ imr = ar231x_read_reg(AR2315_IMR); ++ switch(d->irq) { ++ case AR531X_MISC_IRQ_SPI: ++ imr &= ~AR2315_ISR_SPI; ++ break; ++ case AR531X_MISC_IRQ_TIMER: ++ imr &= ~AR2315_ISR_TIMER; ++ break; ++ case AR531X_MISC_IRQ_AHB_PROC: ++ imr &= ~AR2315_ISR_AHB; ++ break; ++ case AR531X_MISC_IRQ_GPIO: ++ imr &= ~AR2315_ISR_GPIO; ++ break; ++ case AR531X_MISC_IRQ_UART0: ++ imr &= ~AR2315_ISR_UART0; ++ break; ++ case AR531X_MISC_IRQ_WATCHDOG: ++ imr &= ~AR2315_ISR_WD; ++ break; ++ default: ++ break; ++ } ++ ar231x_write_reg(AR2315_IMR, imr); ++} ++ ++ ++static struct irq_chip ar2315_misc_intr_controller = { ++ .name = "AR2315-MISC", ++ .irq_mask = ar2315_misc_intr_disable, ++ .irq_unmask = ar2315_misc_intr_enable, ++}; ++ ++static irqreturn_t ar2315_ahb_proc_handler(int cpl, void *dev_id) ++{ ++ ar231x_write_reg(AR2315_AHB_ERR0, AHB_ERROR_DET); ++ ar231x_read_reg(AR2315_AHB_ERR1); ++ ++ printk(KERN_ERR "AHB fatal error\n"); ++ machine_restart("AHB error"); /* Catastrophic failure */ ++ ++ return IRQ_HANDLED; ++} ++ ++static struct irqaction ar2315_ahb_proc_interrupt = { ++ .handler = ar2315_ahb_proc_handler, ++ .flags = IRQF_DISABLED, ++ .name = "ar2315_ahb_proc_interrupt", ++}; ++ ++static struct irqaction cascade = { ++ .handler = no_action, ++ .flags = IRQF_DISABLED, ++ .name = "cascade", ++}; ++ ++void ++ar2315_irq_init(void) ++{ ++ int i; ++ ++ if (!is_2315()) ++ return; ++ ++ ar231x_irq_dispatch = ar2315_irq_dispatch; ++ gpiointval = ar231x_read_reg(AR2315_GPIO_DI); ++ for (i = 0; i < AR531X_MISC_IRQ_COUNT; i++) { ++ int irq = AR531X_MISC_IRQ_BASE + i; ++ irq_set_chip_and_handler(irq, &ar2315_misc_intr_controller, ++ handle_level_irq); ++ } ++ for (i = 0; i < AR531X_GPIO_IRQ_COUNT; i++) { ++ int irq = AR531X_GPIO_IRQ_BASE + i; ++ irq_set_chip_and_handler(irq, &ar2315_gpio_intr_controller, ++ handle_level_irq); ++ } ++ setup_irq(AR531X_MISC_IRQ_GPIO, &cascade); ++ setup_irq(AR531X_MISC_IRQ_AHB_PROC, &ar2315_ahb_proc_interrupt); ++ setup_irq(AR2315_IRQ_MISC_INTRS, &cascade); ++} ++ ++const struct ar231x_gpiodev ar2315_gpiodev; ++ ++static u32 ++ar2315_gpio_get_output(void) ++{ ++ u32 reg; ++ reg = ar231x_read_reg(AR2315_GPIO_CR); ++ reg &= ar2315_gpiodev.valid_mask; ++ return reg; ++} ++ ++static u32 ++ar2315_gpio_set_output(u32 mask, u32 val) ++{ ++ u32 reg; ++ ++ reg = ar231x_read_reg(AR2315_GPIO_CR); ++ reg &= ~mask; ++ reg |= val; ++ ar231x_write_reg(AR2315_GPIO_CR, reg); ++ return reg; ++} ++ ++static u32 ++ar2315_gpio_get(void) ++{ ++ u32 reg; ++ reg = ar231x_read_reg(AR2315_GPIO_DI); ++ reg &= ar2315_gpiodev.valid_mask; ++ return reg; ++} ++ ++static u32 ++ar2315_gpio_set(u32 mask, u32 value) ++{ ++ u32 reg; ++ reg = ar231x_read_reg(AR2315_GPIO_DO); ++ reg &= ~mask; ++ reg |= value; ++ ar231x_write_reg(AR2315_GPIO_DO, reg); ++ return reg; ++} ++ ++const struct ar231x_gpiodev ar2315_gpiodev = { ++ .valid_mask = (1 << 22) - 1, ++ .get_output = ar2315_gpio_get_output, ++ .set_output = ar2315_gpio_set_output, ++ .get = ar2315_gpio_get, ++ .set = ar2315_gpio_set, ++}; ++ ++static struct ar231x_eth ar2315_eth_data = { ++ .reset_base = AR2315_RESET, ++ .reset_mac = AR2315_RESET_ENET0, ++ .reset_phy = AR2315_RESET_EPHY0, ++ .phy_base = KSEG1ADDR(AR2315_ENET0), ++ .config = &ar231x_board, ++}; ++ ++static struct resource ar2315_spiflash_res[] = { ++ { ++ .name = "flash_base", ++ .flags = IORESOURCE_MEM, ++ .start = KSEG1ADDR(AR2315_SPI_READ), ++ .end = KSEG1ADDR(AR2315_SPI_READ) + 0x1000000 - 1, ++ }, ++ { ++ .name = "flash_regs", ++ .flags = IORESOURCE_MEM, ++ .start = 0x11300000, ++ .end = 0x11300012, ++ }, ++}; ++ ++static struct platform_device ar2315_spiflash = { ++ .id = 0, ++ .name = "spiflash", ++ .resource = ar2315_spiflash_res, ++ .num_resources = ARRAY_SIZE(ar2315_spiflash_res) ++}; ++ ++static struct platform_device ar2315_wdt = { ++ .id = 0, ++ .name = "ar2315_wdt", ++}; ++ ++#define SPI_FLASH_CTL 0x00 ++#define SPI_FLASH_OPCODE 0x04 ++#define SPI_FLASH_DATA 0x08 ++ ++static inline u32 ++spiflash_read_reg(int reg) ++{ ++ return ar231x_read_reg(AR2315_SPI + reg); ++} ++ ++static inline void ++spiflash_write_reg(int reg, u32 data) ++{ ++ ar231x_write_reg(AR2315_SPI + reg, data); ++} ++ ++static u32 ++spiflash_wait_status(void) ++{ ++ u32 reg; ++ ++ do { ++ reg = spiflash_read_reg(SPI_FLASH_CTL); ++ } while (reg & SPI_CTL_BUSY); ++ ++ return reg; ++} ++ ++static u8 ++spiflash_probe(void) ++{ ++ u32 reg; ++ ++ reg = spiflash_wait_status(); ++ reg &= ~SPI_CTL_TX_RX_CNT_MASK; ++ reg |= (1 << 4) | 4 | SPI_CTL_START; ++ ++ spiflash_write_reg(SPI_FLASH_OPCODE, 0xab); ++ spiflash_write_reg(SPI_FLASH_CTL, reg); ++ ++ reg = spiflash_wait_status(); ++ reg = spiflash_read_reg(SPI_FLASH_DATA); ++ reg &= 0xff; ++ ++ return (u8) reg; ++} ++ ++ ++#define STM_8MBIT_SIGNATURE 0x13 ++#define STM_16MBIT_SIGNATURE 0x14 ++#define STM_32MBIT_SIGNATURE 0x15 ++#define STM_64MBIT_SIGNATURE 0x16 ++#define STM_128MBIT_SIGNATURE 0x17 ++ ++static u8 __init * ++ar2315_flash_limit(void) ++{ ++ u32 flash_size = 0; ++ ++ /* probe the flash chip size */ ++ switch(spiflash_probe()) { ++ case STM_8MBIT_SIGNATURE: ++ flash_size = 0x00100000; ++ break; ++ case STM_16MBIT_SIGNATURE: ++ flash_size = 0x00200000; ++ break; ++ case STM_32MBIT_SIGNATURE: ++ flash_size = 0x00400000; ++ break; ++ case STM_64MBIT_SIGNATURE: ++ flash_size = 0x00800000; ++ break; ++ case STM_128MBIT_SIGNATURE: ++ flash_size = 0x01000000; ++ break; ++ } ++ ++ ar2315_spiflash_res[0].end = ar2315_spiflash_res[0].start + ++ flash_size - 1; ++ return (u8 *) ar2315_spiflash_res[0].end + 1; ++} ++ ++#ifdef CONFIG_LEDS_GPIO ++static struct gpio_led ar2315_leds[6]; ++static struct gpio_led_platform_data ar2315_led_data = { ++ .leds = (void *) ar2315_leds, ++}; ++ ++static struct platform_device ar2315_gpio_leds = { ++ .name = "leds-gpio", ++ .id = -1, ++ .dev = { ++ .platform_data = (void *) &ar2315_led_data, ++ } ++}; ++ ++static void __init ++ar2315_init_gpio(void) ++{ ++ static char led_names[6][6]; ++ int i, led = 0; ++ ++ ar2315_led_data.num_leds = 0; ++ for(i = 1; i < 8; i++) ++ { ++ if((i == AR2315_RESET_GPIO) || ++ (i == ar231x_board.config->resetConfigGpio)) ++ continue; ++ ++ if(i == ar231x_board.config->sysLedGpio) ++ strcpy(led_names[led], "wlan"); ++ else ++ sprintf(led_names[led], "gpio%d", i); ++ ++ ar2315_leds[led].name = led_names[led]; ++ ar2315_leds[led].gpio = i; ++ ar2315_leds[led].active_low = 0; ++ led++; ++ } ++ ar2315_led_data.num_leds = led; ++ platform_device_register(&ar2315_gpio_leds); ++} ++#else ++static inline void ar2315_init_gpio(void) ++{ ++} ++#endif ++ ++int __init ++ar2315_init_devices(void) ++{ ++ if (!is_2315()) ++ return 0; ++ ++ /* Find board configuration */ ++ ar231x_find_config(ar2315_flash_limit()); ++ ar2315_eth_data.macaddr = ar231x_board.config->enet0_mac; ++ ++ ar2315_init_gpio(); ++ platform_device_register(&ar2315_wdt); ++ platform_device_register(&ar2315_spiflash); ++ ar231x_add_ethernet(0, KSEG1ADDR(AR2315_ENET0), AR2315_IRQ_ENET0_INTRS, ++ &ar2315_eth_data); ++ ar231x_add_wmac(0, AR2315_WLAN0, AR2315_IRQ_WLAN0_INTRS); ++ ++ return 0; ++} ++ ++static void ++ar2315_restart(char *command) ++{ ++ void (*mips_reset_vec)(void) = (void *) 0xbfc00000; ++ ++ local_irq_disable(); ++ ++ /* try reset the system via reset control */ ++ ar231x_write_reg(AR2315_COLD_RESET,AR2317_RESET_SYSTEM); ++ ++ /* Cold reset does not work on the AR2315/6, use the GPIO reset bits a workaround. ++ * give it some time to attempt a gpio based hardware reset ++ * (atheros reference design workaround) */ ++ gpio_direction_output(AR2315_RESET_GPIO, 0); ++ mdelay(100); ++ ++ /* Some boards (e.g. Senao EOC-2610) don't implement the reset logic ++ * workaround. Attempt to jump to the mips reset location - ++ * the boot loader itself might be able to recover the system */ ++ mips_reset_vec(); ++} ++ ++ ++/* ++ * This table is indexed by bits 5..4 of the CLOCKCTL1 register ++ * to determine the predevisor value. ++ */ ++static int __initdata CLOCKCTL1_PREDIVIDE_TABLE[4] = { 1, 2, 4, 5 }; ++static int __initdata PLLC_DIVIDE_TABLE[5] = { 2, 3, 4, 6, 3 }; ++ ++static unsigned int __init ++ar2315_sys_clk(unsigned int clockCtl) ++{ ++ unsigned int pllcCtrl,cpuDiv; ++ unsigned int pllcOut,refdiv,fdiv,divby2; ++ unsigned int clkDiv; ++ ++ pllcCtrl = ar231x_read_reg(AR2315_PLLC_CTL); ++ refdiv = (pllcCtrl & PLLC_REF_DIV_M) >> PLLC_REF_DIV_S; ++ refdiv = CLOCKCTL1_PREDIVIDE_TABLE[refdiv]; ++ fdiv = (pllcCtrl & PLLC_FDBACK_DIV_M) >> PLLC_FDBACK_DIV_S; ++ divby2 = (pllcCtrl & PLLC_ADD_FDBACK_DIV_M) >> PLLC_ADD_FDBACK_DIV_S; ++ divby2 += 1; ++ pllcOut = (40000000/refdiv)*(2*divby2)*fdiv; ++ ++ ++ /* clkm input selected */ ++ switch(clockCtl & CPUCLK_CLK_SEL_M) { ++ case 0: ++ case 1: ++ clkDiv = PLLC_DIVIDE_TABLE[(pllcCtrl & PLLC_CLKM_DIV_M) >> PLLC_CLKM_DIV_S]; ++ break; ++ case 2: ++ clkDiv = PLLC_DIVIDE_TABLE[(pllcCtrl & PLLC_CLKC_DIV_M) >> PLLC_CLKC_DIV_S]; ++ break; ++ default: ++ pllcOut = 40000000; ++ clkDiv = 1; ++ break; ++ } ++ cpuDiv = (clockCtl & CPUCLK_CLK_DIV_M) >> CPUCLK_CLK_DIV_S; ++ cpuDiv = cpuDiv * 2 ?: 1; ++ return (pllcOut/(clkDiv * cpuDiv)); ++} ++ ++static inline unsigned int ++ar2315_cpu_frequency(void) ++{ ++ return ar2315_sys_clk(ar231x_read_reg(AR2315_CPUCLK)); ++} ++ ++static inline unsigned int ++ar2315_apb_frequency(void) ++{ ++ return ar2315_sys_clk(ar231x_read_reg(AR2315_AMBACLK)); ++} ++ ++void __init ++ar2315_time_init(void) ++{ ++ if (!is_2315()) ++ return; ++ ++ mips_hpt_frequency = ar2315_cpu_frequency() / 2; ++} ++ ++void __init ++ar2315_prom_init(void) ++{ ++ u32 memsize, memcfg, devid; ++ ++ if (!is_2315()) ++ return; ++ ++ memcfg = ar231x_read_reg(AR2315_MEM_CFG); ++ memsize = 1 + ((memcfg & SDRAM_DATA_WIDTH_M) >> SDRAM_DATA_WIDTH_S); ++ memsize <<= 1 + ((memcfg & SDRAM_COL_WIDTH_M) >> SDRAM_COL_WIDTH_S); ++ memsize <<= 1 + ((memcfg & SDRAM_ROW_WIDTH_M) >> SDRAM_ROW_WIDTH_S); ++ memsize <<= 3; ++ add_memory_region(0, memsize, BOOT_MEM_RAM); ++ ++ /* Detect the hardware based on the device ID */ ++ devid = ar231x_read_reg(AR2315_SREV) & AR2315_REV_CHIP; ++ switch(devid) { ++ case 0x90: ++ case 0x91: ++ ar231x_devtype = DEV_TYPE_AR2317; ++ break; ++ default: ++ ar231x_devtype = DEV_TYPE_AR2315; ++ break; ++ } ++ ar231x_gpiodev = &ar2315_gpiodev; ++ ar231x_board.devid = devid; ++} ++ ++void __init ++ar2315_plat_setup(void) ++{ ++ u32 config; ++ ++ if (!is_2315()) ++ return; ++ ++ /* Clear any lingering AHB errors */ ++ config = read_c0_config(); ++ write_c0_config(config & ~0x3); ++ ar231x_write_reg(AR2315_AHB_ERR0,AHB_ERROR_DET); ++ ar231x_read_reg(AR2315_AHB_ERR1); ++ ar231x_write_reg(AR2315_WDC, AR2315_WDC_IGNORE_EXPIRATION); ++ ++ _machine_restart = ar2315_restart; ++ ar231x_serial_setup(KSEG1ADDR(AR2315_UART0), ar2315_apb_frequency()); ++} +diff -Nur linux-2.6.39-rc7.orig/arch/mips/ar231x/ar2315.h linux-2.6.39-rc7/arch/mips/ar231x/ar2315.h +--- linux-2.6.39-rc7.orig/arch/mips/ar231x/ar2315.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/ar231x/ar2315.h 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,37 @@ ++#ifndef __AR2315_H ++#define __AR2315_H ++ ++#ifdef CONFIG_ATHEROS_AR2315 ++ ++extern void ar2315_irq_init(void); ++extern int ar2315_init_devices(void); ++extern void ar2315_prom_init(void); ++extern void ar2315_plat_setup(void); ++extern void ar2315_time_init(void); ++ ++#else ++ ++static inline void ar2315_irq_init(void) ++{ ++} ++ ++static inline int ar2315_init_devices(void) ++{ ++ return 0; ++} ++ ++static inline void ar2315_prom_init(void) ++{ ++} ++ ++static inline void ar2315_plat_setup(void) ++{ ++} ++ ++static inline void ar2315_time_init(void) ++{ ++} ++ ++#endif ++ ++#endif +diff -Nur linux-2.6.39-rc7.orig/arch/mips/ar231x/ar5312.c linux-2.6.39-rc7/arch/mips/ar231x/ar5312.c +--- linux-2.6.39-rc7.orig/arch/mips/ar231x/ar5312.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/ar231x/ar5312.c 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,538 @@ ++/* ++ * 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) 2003 Atheros Communications, Inc., All Rights Reserved. ++ * Copyright (C) 2006 FON Technology, SL. ++ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> ++ */ ++ ++/* ++ * Platform devices for Atheros SoCs ++ */ ++ ++#include <generated/autoconf.h> ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/string.h> ++#include <linux/mtd/physmap.h> ++#include <linux/platform_device.h> ++#include <linux/kernel.h> ++#include <linux/reboot.h> ++#include <linux/leds.h> ++#include <asm/bootinfo.h> ++#include <asm/reboot.h> ++#include <asm/time.h> ++#include <asm/irq.h> ++#include <asm/io.h> ++#include <gpio.h> ++ ++#include <ar231x_platform.h> ++#include <ar5312_regs.h> ++#include <ar231x.h> ++#include "devices.h" ++#include "ar5312.h" ++ ++static void ++ar5312_misc_irq_dispatch(void) ++{ ++ unsigned int ar231x_misc_intrs = ar231x_read_reg(AR531X_ISR) & ar231x_read_reg(AR531X_IMR); ++ ++ if (ar231x_misc_intrs & AR531X_ISR_TIMER) { ++ do_IRQ(AR531X_MISC_IRQ_TIMER); ++ (void)ar231x_read_reg(AR531X_TIMER); ++ } else if (ar231x_misc_intrs & AR531X_ISR_AHBPROC) ++ do_IRQ(AR531X_MISC_IRQ_AHB_PROC); ++ else if ((ar231x_misc_intrs & AR531X_ISR_UART0)) ++ do_IRQ(AR531X_MISC_IRQ_UART0); ++ else if (ar231x_misc_intrs & AR531X_ISR_WD) ++ do_IRQ(AR531X_MISC_IRQ_WATCHDOG); ++ else ++ do_IRQ(AR531X_MISC_IRQ_NONE); ++} ++ ++static asmlinkage void ++ar5312_irq_dispatch(void) ++{ ++ int pending = read_c0_status() & read_c0_cause(); ++ ++ if (pending & CAUSEF_IP2) ++ do_IRQ(AR5312_IRQ_WLAN0_INTRS); ++ else if (pending & CAUSEF_IP3) ++ do_IRQ(AR5312_IRQ_ENET0_INTRS); ++ else if (pending & CAUSEF_IP4) ++ do_IRQ(AR5312_IRQ_ENET1_INTRS); ++ else if (pending & CAUSEF_IP5) ++ do_IRQ(AR5312_IRQ_WLAN1_INTRS); ++ else if (pending & CAUSEF_IP6) ++ ar5312_misc_irq_dispatch(); ++ else if (pending & CAUSEF_IP7) ++ do_IRQ(AR531X_IRQ_CPU_CLOCK); ++} ++ ++ ++/* Enable the specified AR531X_MISC_IRQ interrupt */ ++static void ++ar5312_misc_intr_enable(struct irq_data *d) ++{ ++ unsigned int imr; ++ ++ imr = ar231x_read_reg(AR531X_IMR); ++ imr |= (1 << (d->irq - AR531X_MISC_IRQ_BASE - 1)); ++ ar231x_write_reg(AR531X_IMR, imr); ++} ++ ++/* Disable the specified AR531X_MISC_IRQ interrupt */ ++static void ++ar5312_misc_intr_disable(struct irq_data *d) ++{ ++ unsigned int imr; ++ ++ imr = ar231x_read_reg(AR531X_IMR); ++ imr &= ~(1 << (d->irq - AR531X_MISC_IRQ_BASE - 1)); ++ ar231x_write_reg(AR531X_IMR, imr); ++ ar231x_read_reg(AR531X_IMR); /* flush write buffer */ ++} ++ ++static struct irq_chip ar5312_misc_intr_controller = { ++ .name = "AR5312-MISC", ++ .irq_mask = ar5312_misc_intr_disable, ++ .irq_unmask = ar5312_misc_intr_enable, ++}; ++ ++ ++static irqreturn_t ar5312_ahb_proc_handler(int cpl, void *dev_id) ++{ ++ u32 proc1 = ar231x_read_reg(AR531X_PROC1); ++ u32 procAddr = ar231x_read_reg(AR531X_PROCADDR); /* clears error state */ ++ u32 dma1 = ar231x_read_reg(AR531X_DMA1); ++ u32 dmaAddr = ar231x_read_reg(AR531X_DMAADDR); /* clears error state */ ++ ++ printk("AHB interrupt: PROCADDR=0x%8.8x PROC1=0x%8.8x DMAADDR=0x%8.8x DMA1=0x%8.8x\n", ++ procAddr, proc1, dmaAddr, dma1); ++ ++ machine_restart("AHB error"); /* Catastrophic failure */ ++ return IRQ_HANDLED; ++} ++ ++ ++static struct irqaction ar5312_ahb_proc_interrupt = { ++ .handler = ar5312_ahb_proc_handler, ++ .flags = IRQF_DISABLED, ++ .name = "ar5312_ahb_proc_interrupt", ++}; ++ ++ ++static struct irqaction cascade = { ++ .handler = no_action, ++ .flags = IRQF_DISABLED, ++ .name = "cascade", ++}; ++ ++void __init ar5312_irq_init(void) ++{ ++ int i; ++ ++ if (!is_5312()) ++ return; ++ ++ ar231x_irq_dispatch = ar5312_irq_dispatch; ++ for (i = 0; i < AR531X_MISC_IRQ_COUNT; i++) { ++ int irq = AR531X_MISC_IRQ_BASE + i; ++ irq_set_chip_and_handler(irq, &ar5312_misc_intr_controller, ++ handle_level_irq); ++ } ++ setup_irq(AR531X_MISC_IRQ_AHB_PROC, &ar5312_ahb_proc_interrupt); ++ setup_irq(AR5312_IRQ_MISC_INTRS, &cascade); ++} ++ ++const struct ar231x_gpiodev ar5312_gpiodev; ++ ++static u32 ++ar5312_gpio_get_output(void) ++{ ++ u32 reg; ++ reg = ~(ar231x_read_reg(AR531X_GPIO_CR)); ++ reg &= ar5312_gpiodev.valid_mask; ++ return reg; ++} ++ ++static u32 ++ar5312_gpio_set_output(u32 mask, u32 val) ++{ ++ u32 reg; ++ ++ reg = ar231x_read_reg(AR531X_GPIO_CR); ++ reg |= mask; ++ reg &= ~val; ++ ar231x_write_reg(AR531X_GPIO_CR, reg); ++ return reg; ++} ++ ++static u32 ++ar5312_gpio_get(void) ++{ ++ u32 reg; ++ reg = ar231x_read_reg(AR531X_GPIO_DI); ++ reg &= ar5312_gpiodev.valid_mask; ++ return reg; ++} ++ ++static u32 ++ar5312_gpio_set(u32 mask, u32 value) ++{ ++ u32 reg; ++ reg = ar231x_read_reg(AR531X_GPIO_DO); ++ reg &= ~mask; ++ reg |= value; ++ ar231x_write_reg(AR531X_GPIO_DO, reg); ++ return reg; ++} ++ ++const struct ar231x_gpiodev ar5312_gpiodev = { ++ .valid_mask = (1 << 8) - 1, ++ .get_output = ar5312_gpio_get_output, ++ .set_output = ar5312_gpio_set_output, ++ .get = ar5312_gpio_get, ++ .set = ar5312_gpio_set, ++}; ++ ++static struct physmap_flash_data ar5312_flash_data = { ++ .width = 2, ++}; ++ ++static struct resource ar5312_flash_resource = { ++ .start = AR531X_FLASH, ++ .end = AR531X_FLASH + 0x800000 - 1, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct ar231x_eth ar5312_eth0_data = { ++ .reset_base = AR531X_RESET, ++ .reset_mac = AR531X_RESET_ENET0, ++ .reset_phy = AR531X_RESET_EPHY0, ++ .phy_base = KSEG1ADDR(AR531X_ENET0), ++ .config = &ar231x_board, ++}; ++ ++static struct ar231x_eth ar5312_eth1_data = { ++ .reset_base = AR531X_RESET, ++ .reset_mac = AR531X_RESET_ENET1, ++ .reset_phy = AR531X_RESET_EPHY1, ++ .phy_base = KSEG1ADDR(AR531X_ENET1), ++ .config = &ar231x_board, ++}; ++ ++static struct platform_device ar5312_physmap_flash = { ++ .name = "physmap-flash", ++ .id = 0, ++ .dev.platform_data = &ar5312_flash_data, ++ .resource = &ar5312_flash_resource, ++ .num_resources = 1, ++}; ++ ++#ifdef CONFIG_LEDS_GPIO ++static struct gpio_led ar5312_leds[] = { ++ { .name = "wlan", .gpio = 0, .active_low = 1, }, ++}; ++ ++static const struct gpio_led_platform_data ar5312_led_data = { ++ .num_leds = ARRAY_SIZE(ar5312_leds), ++ .leds = (void *) ar5312_leds, ++}; ++ ++static struct platform_device ar5312_gpio_leds = { ++ .name = "leds-gpio", ++ .id = -1, ++ .dev.platform_data = (void *) &ar5312_led_data, ++}; ++#endif ++ ++/* ++ * NB: This mapping size is larger than the actual flash size, ++ * but this shouldn't be a problem here, because the flash ++ * will simply be mapped multiple times. ++ */ ++static char __init *ar5312_flash_limit(void) ++{ ++ u32 ctl; ++ /* ++ * Configure flash bank 0. ++ * Assume 8M window size. Flash will be aliased if it's smaller ++ */ ++ ctl = FLASHCTL_E | ++ FLASHCTL_AC_8M | ++ FLASHCTL_RBLE | ++ (0x01 << FLASHCTL_IDCY_S) | ++ (0x07 << FLASHCTL_WST1_S) | ++ (0x07 << FLASHCTL_WST2_S) | ++ (ar231x_read_reg(AR531X_FLASHCTL0) & FLASHCTL_MW); ++ ++ ar231x_write_reg(AR531X_FLASHCTL0, ctl); ++ ++ /* Disable other flash banks */ ++ ar231x_write_reg(AR531X_FLASHCTL1, ++ ar231x_read_reg(AR531X_FLASHCTL1) & ~(FLASHCTL_E | FLASHCTL_AC)); ++ ++ ar231x_write_reg(AR531X_FLASHCTL2, ++ ar231x_read_reg(AR531X_FLASHCTL2) & ~(FLASHCTL_E | FLASHCTL_AC)); ++ ++ return (char *) KSEG1ADDR(AR531X_FLASH + 0x800000); ++} ++ ++int __init ar5312_init_devices(void) ++{ ++ struct ar231x_boarddata *config; ++ u32 fctl = 0; ++ const u8 *radio; ++ u8 *c; ++ ++ if (!is_5312()) ++ return 0; ++ ++ /* Locate board/radio config data */ ++ ar231x_find_config(ar5312_flash_limit()); ++ config = ar231x_board.config; ++ ++ ++ /* ++ * Chip IDs and hardware detection for some Atheros ++ * models are really broken! ++ * ++ * Atheros uses a disabled WMAC0 and Silicon ID of AR5312 ++ * as indication for AR2312, which is otherwise ++ * indistinguishable from the real AR5312. ++ */ ++ if (ar231x_board.radio) { ++ radio = ar231x_board.radio + AR531X_RADIO_MASK_OFF; ++ if ((*((const u32 *) radio) & AR531X_RADIO0_MASK) == 0) ++ config->flags |= BD_ISCASPER; ++ } else ++ radio = NULL; ++ ++ /* AR2313 has CPU minor rev. 10 */ ++ if ((current_cpu_data.processor_id & 0xff) == 0x0a) ++ ar231x_devtype = DEV_TYPE_AR2313; ++ ++ /* AR2312 shares the same Silicon ID as AR5312 */ ++ else if (config->flags & BD_ISCASPER) ++ ar231x_devtype = DEV_TYPE_AR2312; ++ ++ /* Everything else is probably AR5312 or compatible */ ++ else ++ ar231x_devtype = DEV_TYPE_AR5312; ++ ++ /* fixup flash width */ ++ fctl = ar231x_read_reg(AR531X_FLASHCTL) & FLASHCTL_MW; ++ switch (fctl) { ++ case FLASHCTL_MWx16: ++ ar5312_flash_data.width = 2; ++ break; ++ case FLASHCTL_MWx8: ++ default: ++ ar5312_flash_data.width = 1; ++ break; ++ } ++ ++ platform_device_register(&ar5312_physmap_flash); ++ ++#ifdef CONFIG_LEDS_GPIO ++ ar5312_leds[0].gpio = config->sysLedGpio; ++ platform_device_register(&ar5312_gpio_leds); ++#endif ++ ++ /* Fix up MAC addresses if necessary */ ++ if (!memcmp(config->enet0_mac, "\xff\xff\xff\xff\xff\xff", 6)) ++ memcpy(config->enet0_mac, config->enet1_mac, 6); ++ ++ /* If ENET0 and ENET1 have the same mac address, ++ * increment the one from ENET1 */ ++ if (memcmp(config->enet0_mac, config->enet1_mac, 6) == 0) { ++ c = config->enet1_mac + 5; ++ while ((c >= config->enet1_mac) && !(++(*c))) ++ c--; ++ } ++ ++ switch(ar231x_devtype) { ++ case DEV_TYPE_AR5312: ++ ar5312_eth0_data.macaddr = config->enet0_mac; ++ ar231x_add_ethernet(0, KSEG1ADDR(AR531X_ENET0), ++ AR5312_IRQ_ENET0_INTRS, &ar5312_eth0_data); ++ ++ ar5312_eth1_data.macaddr = config->enet1_mac; ++ ar231x_add_ethernet(1, KSEG1ADDR(AR531X_ENET1), ++ AR5312_IRQ_ENET1_INTRS, &ar5312_eth1_data); ++ ++ if (!ar231x_board.radio) ++ return 0; ++ ++ if ((*((u32 *) radio) & AR531X_RADIO0_MASK) && ++ (config->flags & BD_WLAN0)) ++ ar231x_add_wmac(0, AR531X_WLAN0, ++ AR5312_IRQ_WLAN0_INTRS); ++ ++ break; ++ /* ++ * AR2312/3 ethernet uses the PHY of ENET0, but the MAC ++ * of ENET1. Atheros calls it 'twisted' for a reason :) ++ */ ++ case DEV_TYPE_AR2312: ++ case DEV_TYPE_AR2313: ++ ar5312_eth1_data.phy_base = ar5312_eth0_data.phy_base; ++ ar5312_eth1_data.reset_phy = ar5312_eth0_data.reset_phy; ++ ar5312_eth1_data.macaddr = config->enet0_mac; ++ ar231x_add_ethernet(0, KSEG1ADDR(AR531X_ENET1), ++ AR5312_IRQ_ENET1_INTRS, &ar5312_eth1_data); ++ ++ if (!ar231x_board.radio) ++ return 0; ++ break; ++ default: ++ break; ++ } ++ ++ if ((*((u32 *) radio) & AR531X_RADIO1_MASK) && ++ (config->flags & BD_WLAN1)) ++ ar231x_add_wmac(1, AR531X_WLAN1, ++ AR5312_IRQ_WLAN1_INTRS); ++ ++ return 0; ++} ++ ++ ++static void ar5312_restart(char *command) ++{ ++ /* reset the system */ ++ local_irq_disable(); ++ while(1) { ++ ar231x_write_reg(AR531X_RESET, AR531X_RESET_SYSTEM); ++ } ++} ++ ++ ++/* ++ * This table is indexed by bits 5..4 of the CLOCKCTL1 register ++ * to determine the predevisor value. ++ */ ++static int __initdata CLOCKCTL1_PREDIVIDE_TABLE[4] = { 1, 2, 4, 5 }; ++ ++ ++static int __init ++ar5312_cpu_frequency(void) ++{ ++ unsigned int result; ++ unsigned int predivide_mask, predivide_shift; ++ unsigned int multiplier_mask, multiplier_shift; ++ unsigned int clockCtl1, preDivideSelect, preDivisor, multiplier; ++ unsigned int doubler_mask; ++ u16 devid; ++ ++ /* Trust the bootrom's idea of cpu frequency. */ ++ if ((result = ar231x_read_reg(AR5312_SCRATCH))) ++ return result; ++ ++ devid = ar231x_read_reg(AR531X_REV); ++ devid &= AR531X_REV_MAJ; ++ devid >>= AR531X_REV_MAJ_S; ++ if (devid == AR531X_REV_MAJ_AR2313) { ++ predivide_mask = AR2313_CLOCKCTL1_PREDIVIDE_MASK; ++ predivide_shift = AR2313_CLOCKCTL1_PREDIVIDE_SHIFT; ++ multiplier_mask = AR2313_CLOCKCTL1_MULTIPLIER_MASK; ++ multiplier_shift = AR2313_CLOCKCTL1_MULTIPLIER_SHIFT; ++ doubler_mask = AR2313_CLOCKCTL1_DOUBLER_MASK; ++ } else { /* AR5312 and AR2312 */ ++ predivide_mask = AR5312_CLOCKCTL1_PREDIVIDE_MASK; ++ predivide_shift = AR5312_CLOCKCTL1_PREDIVIDE_SHIFT; ++ multiplier_mask = AR5312_CLOCKCTL1_MULTIPLIER_MASK; ++ multiplier_shift = AR5312_CLOCKCTL1_MULTIPLIER_SHIFT; ++ doubler_mask = AR5312_CLOCKCTL1_DOUBLER_MASK; ++ } ++ ++ /* ++ * Clocking is derived from a fixed 40MHz input clock. ++ * ++ * cpuFreq = InputClock * MULT (where MULT is PLL multiplier) ++ * sysFreq = cpuFreq / 4 (used for APB clock, serial, ++ * flash, Timer, Watchdog Timer) ++ * ++ * cntFreq = cpuFreq / 2 (use for CPU count/compare) ++ * ++ * So, for example, with a PLL multiplier of 5, we have ++ * ++ * cpuFreq = 200MHz ++ * sysFreq = 50MHz ++ * cntFreq = 100MHz ++ * ++ * We compute the CPU frequency, based on PLL settings. ++ */ ++ ++ clockCtl1 = ar231x_read_reg(AR5312_CLOCKCTL1); ++ preDivideSelect = (clockCtl1 & predivide_mask) >> predivide_shift; ++ preDivisor = CLOCKCTL1_PREDIVIDE_TABLE[preDivideSelect]; ++ multiplier = (clockCtl1 & multiplier_mask) >> multiplier_shift; ++ ++ if (clockCtl1 & doubler_mask) { ++ multiplier = multiplier << 1; ++ } ++ return (40000000 / preDivisor) * multiplier; ++} ++ ++static inline int ++ar5312_sys_frequency(void) ++{ ++ return ar5312_cpu_frequency() / 4; ++} ++ ++void __init ++ar5312_time_init(void) ++{ ++ if (!is_5312()) ++ return; ++ ++ mips_hpt_frequency = ar5312_cpu_frequency() / 2; ++} ++ ++ ++void __init ++ar5312_prom_init(void) ++{ ++ u32 memsize, memcfg, bank0AC, bank1AC; ++ u32 devid; ++ ++ if (!is_5312()) ++ return; ++ ++ /* Detect memory size */ ++ memcfg = ar231x_read_reg(AR531X_MEM_CFG1); ++ bank0AC = (memcfg & MEM_CFG1_AC0) >> MEM_CFG1_AC0_S; ++ bank1AC = (memcfg & MEM_CFG1_AC1) >> MEM_CFG1_AC1_S; ++ memsize = (bank0AC ? (1 << (bank0AC+1)) : 0) ++ + (bank1AC ? (1 << (bank1AC+1)) : 0); ++ memsize <<= 20; ++ add_memory_region(0, memsize, BOOT_MEM_RAM); ++ ++ devid = ar231x_read_reg(AR531X_REV); ++ devid >>= AR531X_REV_WMAC_MIN_S; ++ devid &= AR531X_REV_CHIP; ++ ar231x_board.devid = (u16) devid; ++ ar231x_gpiodev = &ar5312_gpiodev; ++} ++ ++void __init ++ar5312_plat_setup(void) ++{ ++ if (!is_5312()) ++ return; ++ ++ /* Clear any lingering AHB errors */ ++ ar231x_read_reg(AR531X_PROCADDR); ++ ar231x_read_reg(AR531X_DMAADDR); ++ ar231x_write_reg(AR531X_WD_CTRL, AR531X_WD_CTRL_IGNORE_EXPIRATION); ++ ++ _machine_restart = ar5312_restart; ++ ar231x_serial_setup(KSEG1ADDR(AR531X_UART0), ar5312_sys_frequency()); ++} ++ +diff -Nur linux-2.6.39-rc7.orig/arch/mips/ar231x/ar5312.h linux-2.6.39-rc7/arch/mips/ar231x/ar5312.h +--- linux-2.6.39-rc7.orig/arch/mips/ar231x/ar5312.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/ar231x/ar5312.h 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,38 @@ ++#ifndef __AR5312_H ++#define __AR5312_H ++ ++#ifdef CONFIG_ATHEROS_AR5312 ++ ++extern void ar5312_irq_init(void); ++extern int ar5312_init_devices(void); ++extern void ar5312_prom_init(void); ++extern void ar5312_plat_setup(void); ++extern void ar5312_time_init(void); ++extern void ar5312_time_init(void); ++ ++#else ++ ++static inline void ar5312_irq_init(void) ++{ ++} ++ ++static inline int ar5312_init_devices(void) ++{ ++ return 0; ++} ++ ++static inline void ar5312_prom_init(void) ++{ ++} ++ ++static inline void ar5312_plat_setup(void) ++{ ++} ++ ++static inline void ar5312_time_init(void) ++{ ++} ++ ++#endif ++ ++#endif +diff -Nur linux-2.6.39-rc7.orig/arch/mips/ar231x/board.c linux-2.6.39-rc7/arch/mips/ar231x/board.c +--- linux-2.6.39-rc7.orig/arch/mips/ar231x/board.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/ar231x/board.c 2011-05-15 22:16:11.000000000 +0200 +@@ -0,0 +1,261 @@ ++/* ++ * 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) 2003 Atheros Communications, Inc., All Rights Reserved. ++ * Copyright (C) 2006 FON Technology, SL. ++ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> ++ */ ++ ++#include <generated/autoconf.h> ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/string.h> ++#include <linux/platform_device.h> ++#include <linux/kernel.h> ++#include <linux/random.h> ++#include <linux/etherdevice.h> ++#include <asm/irq_cpu.h> ++#include <asm/reboot.h> ++#include <asm/io.h> ++ ++#include <ar231x_platform.h> ++#include "devices.h" ++#include "ar5312.h" ++#include "ar2315.h" ++ ++void (*ar231x_irq_dispatch)(void); ++ ++static inline bool ++check_radio_magic(u8 *addr) ++{ ++ addr += 0x7a; /* offset for flash magic */ ++ if ((addr[0] == 0x5a) && (addr[1] == 0xa5)) { ++ return 1; ++ } ++ return 0; ++} ++ ++static inline bool ++check_board_data(u8 *flash_limit, u8 *addr, bool broken) ++{ ++ /* config magic found */ ++ if (*((u32 *)addr) == AR531X_BD_MAGIC) ++ return 1; ++ ++ if (!broken) ++ return 0; ++ ++ if (check_radio_magic(addr + 0xf8)) ++ ar231x_board.radio = addr + 0xf8; ++ if ((addr < flash_limit + 0x10000) && ++ check_radio_magic(addr + 0x10000)) ++ ar231x_board.radio = addr + 0x10000; ++ ++ if (ar231x_board.radio) { ++ /* broken board data detected, use radio data to find the offset, ++ * user will fix this */ ++ return 1; ++ } ++ return 0; ++} ++ ++static u8 * ++find_board_config(u8 *flash_limit, bool broken) ++{ ++ u8 *addr; ++ int found = 0; ++ ++ for (addr = flash_limit - 0x1000; ++ addr >= flash_limit - 0x30000; ++ addr -= 0x1000) { ++ ++ if (check_board_data(flash_limit, addr, broken)) { ++ found = 1; ++ break; ++ } ++ } ++ ++ if (!found) ++ addr = NULL; ++ ++ return addr; ++} ++ ++static u8 * ++find_radio_config(u8 *flash_limit, u8 *board_config) ++{ ++ int found; ++ u8 *radio_config; ++ ++ /* ++ * Now find the start of Radio Configuration data, using heuristics: ++ * Search forward from Board Configuration data by 0x1000 bytes ++ * at a time until we find non-0xffffffff. ++ */ ++ found = 0; ++ for (radio_config = board_config + 0x1000; ++ (radio_config < flash_limit); ++ radio_config += 0x1000) { ++ if ((*(u32 *)radio_config != 0xffffffff) && ++ check_radio_magic(radio_config)) { ++ found = 1; ++ break; ++ } ++ } ++ ++ /* AR2316 relocates radio config to new location */ ++ if (!found) { ++ for (radio_config = board_config + 0xf8; ++ (radio_config < flash_limit - 0x1000 + 0xf8); ++ radio_config += 0x1000) { ++ if ((*(u32 *)radio_config != 0xffffffff) && ++ check_radio_magic(radio_config)) { ++ found = 1; ++ break; ++ } ++ } ++ } ++ ++ if (!found) { ++ printk("Could not find Radio Configuration data\n"); ++ radio_config = 0; ++ } ++ ++ return (u8 *) radio_config; ++} ++ ++int __init ++ar231x_find_config(u8 *flash_limit) ++{ ++ struct ar231x_boarddata *config; ++ unsigned int rcfg_size; ++ int broken_boarddata = 0, i, tmp; ++ u8 *bcfg, *rcfg; ++ u8 *board_data; ++ u8 *radio_data; ++ u32 offset; ++ ++ ar231x_board.config = NULL; ++ ar231x_board.radio = NULL; ++ /* Copy the board and radio data to RAM, because accessing the mapped ++ * memory of the flash directly after booting is not safe */ ++ ++ /* Try to find valid board and radio data */ ++ bcfg = find_board_config(flash_limit, false); ++ ++ /* If that fails, try to at least find valid radio data */ ++ if (!bcfg) { ++ bcfg = find_board_config(flash_limit, true); ++ broken_boarddata = 1; ++ } ++ ++ if (!bcfg) { ++ printk(KERN_WARNING "WARNING: No board configuration data found!\n"); ++ return -ENODEV; ++ } ++ ++ board_data = kzalloc(BOARD_CONFIG_BUFSZ, GFP_KERNEL); ++ ar231x_board.config = (struct ar231x_boarddata *) board_data; ++ memcpy(board_data, bcfg, 0x100); ++ if (broken_boarddata) { ++ printk(KERN_WARNING "WARNING: broken board data detected\n"); ++ config = ar231x_board.config; ++ if (!memcmp(config->enet0_mac, "\x00\x00\x00\x00\x00\x00", 6)) { ++ printk(KERN_INFO "Fixing up empty mac addresses\n"); ++ config->resetConfigGpio = 0xffff; ++ config->sysLedGpio = 0xffff; ++ random_ether_addr(config->wlan0_mac); ++ config->wlan0_mac[0] &= ~0x06; ++ random_ether_addr(config->enet0_mac); ++ random_ether_addr(config->enet1_mac); ++ } ++ } ++ ++ ++ /* Radio config starts 0x100 bytes after board config, regardless ++ * of what the physical layout on the flash chip looks like */ ++ ++ if (ar231x_board.radio) ++ rcfg = (u8 *) ar231x_board.radio; ++ else ++ rcfg = find_radio_config(flash_limit, bcfg); ++ ++ if (!rcfg) ++ return -ENODEV; ++ ++ radio_data = board_data + 0x100 + ((rcfg - bcfg) & 0xfff); ++ ar231x_board.radio = radio_data; ++ offset = radio_data - board_data; ++ printk(KERN_INFO "Radio config found at offset 0x%x(0x%x)\n", rcfg - bcfg, offset); ++ rcfg_size = BOARD_CONFIG_BUFSZ - offset; ++ memcpy(radio_data, rcfg, rcfg_size); ++ ++ for (tmp = 0xff, i = 0; i < ETH_ALEN; i++) ++ tmp &= radio_data[i + 0x1d * 2]; ++ if (tmp == 0xff) { ++ u16 *eep = (u16 *)radio_data, *bcfgs = (u16 *)bcfg; ++ printk(KERN_INFO "Radio MAC is blank; using board-data\n"); ++ eep[0x1f] = bcfgs[0x30]; ++ eep[0x1e] = bcfgs[0x34]; ++ eep[0x1d] = bcfgs[0x32]; ++ } ++ ++ return 0; ++} ++ ++static void ++ar231x_halt(void) ++{ ++ local_irq_disable(); ++ while (1); ++} ++ ++void __init ++plat_mem_setup(void) ++{ ++ _machine_halt = ar231x_halt; ++ pm_power_off = ar231x_halt; ++ ++ ar5312_plat_setup(); ++ ar2315_plat_setup(); ++ ++ /* Disable data watchpoints */ ++ write_c0_watchlo0(0); ++} ++ ++ ++asmlinkage void ++plat_irq_dispatch(void) ++{ ++ ar231x_irq_dispatch(); ++} ++ ++void __init ++plat_time_init(void) ++{ ++ ar5312_time_init(); ++ ar2315_time_init(); ++} ++ ++unsigned int __cpuinit ++get_c0_compare_int(void) ++{ ++ return CP0_LEGACY_COMPARE_IRQ; ++} ++ ++void __init ++arch_init_irq(void) ++{ ++ clear_c0_status(ST0_IM); ++ mips_cpu_irq_init(); ++ ++ /* Initialize interrupt controllers */ ++ ar5312_irq_init(); ++ ar2315_irq_init(); ++} ++ ++ +diff -Nur linux-2.6.39-rc7.orig/arch/mips/ar231x/devices.c linux-2.6.39-rc7/arch/mips/ar231x/devices.c +--- linux-2.6.39-rc7.orig/arch/mips/ar231x/devices.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/ar231x/devices.c 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,175 @@ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/serial.h> ++#include <linux/serial_core.h> ++#include <linux/serial_8250.h> ++#include <linux/platform_device.h> ++#include <ar231x_platform.h> ++#include <ar231x.h> ++#include "devices.h" ++#include "ar5312.h" ++#include "ar2315.h" ++ ++struct ar231x_board_config ar231x_board; ++int ar231x_devtype = DEV_TYPE_UNKNOWN; ++const struct ar231x_gpiodev *ar231x_gpiodev; ++EXPORT_SYMBOL(ar231x_gpiodev); ++ ++static struct resource ar231x_eth0_res[] = { ++ { ++ .name = "eth0_membase", ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = "eth0_irq", ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct resource ar231x_eth1_res[] = { ++ { ++ .name = "eth1_membase", ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = "eth1_irq", ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct platform_device ar231x_eth[] = { ++ { ++ .id = 0, ++ .name = "ar231x-eth", ++ .resource = ar231x_eth0_res, ++ .num_resources = ARRAY_SIZE(ar231x_eth0_res) ++ }, ++ { ++ .id = 1, ++ .name = "ar231x-eth", ++ .resource = ar231x_eth1_res, ++ .num_resources = ARRAY_SIZE(ar231x_eth1_res) ++ } ++}; ++ ++static struct resource ar231x_wmac0_res[] = { ++ { ++ .name = "wmac0_membase", ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = "wmac0_irq", ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++static struct resource ar231x_wmac1_res[] = { ++ { ++ .name = "wmac1_membase", ++ .flags = IORESOURCE_MEM, ++ }, ++ { ++ .name = "wmac1_irq", ++ .flags = IORESOURCE_IRQ, ++ } ++}; ++ ++ ++static struct platform_device ar231x_wmac[] = { ++ { ++ .id = 0, ++ .name = "ar231x-wmac", ++ .resource = ar231x_wmac0_res, ++ .num_resources = ARRAY_SIZE(ar231x_wmac0_res), ++ .dev.platform_data = &ar231x_board, ++ }, ++ { ++ .id = 1, ++ .name = "ar231x-wmac", ++ .resource = ar231x_wmac1_res, ++ .num_resources = ARRAY_SIZE(ar231x_wmac1_res), ++ .dev.platform_data = &ar231x_board, ++ }, ++}; ++ ++static const char *devtype_strings[] = { ++ [DEV_TYPE_AR5312] = "Atheros AR5312", ++ [DEV_TYPE_AR2312] = "Atheros AR2312", ++ [DEV_TYPE_AR2313] = "Atheros AR2313", ++ [DEV_TYPE_AR2315] = "Atheros AR2315", ++ [DEV_TYPE_AR2316] = "Atheros AR2316", ++ [DEV_TYPE_AR2317] = "Atheros AR2317", ++ [DEV_TYPE_UNKNOWN] = "Atheros (unknown)", ++}; ++ ++const char *get_system_type(void) ++{ ++ if ((ar231x_devtype >= ARRAY_SIZE(devtype_strings)) || ++ !devtype_strings[ar231x_devtype]) ++ return devtype_strings[DEV_TYPE_UNKNOWN]; ++ return devtype_strings[ar231x_devtype]; ++} ++ ++ ++int __init ++ar231x_add_ethernet(int nr, u32 base, int irq, void *pdata) ++{ ++ struct resource *res; ++ ++ ar231x_eth[nr].dev.platform_data = pdata; ++ res = &ar231x_eth[nr].resource[0]; ++ res->start = base; ++ res->end = base + 0x2000 - 1; ++ res++; ++ res->start = irq; ++ res->end = irq; ++ return platform_device_register(&ar231x_eth[nr]); ++} ++ ++void __init ++ar231x_serial_setup(u32 mapbase, unsigned int uartclk) ++{ ++ struct uart_port s; ++ ++ memset(&s, 0, sizeof(s)); ++ ++ s.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST; ++ s.iotype = UPIO_MEM; ++ s.irq = AR531X_MISC_IRQ_UART0; ++ s.regshift = 2; ++ s.mapbase = mapbase; ++ s.uartclk = uartclk; ++ s.membase = (void __iomem *)s.mapbase; ++ ++ early_serial_setup(&s); ++} ++ ++int __init ++ar231x_add_wmac(int nr, u32 base, int irq) ++{ ++ struct resource *res; ++ ++ ar231x_wmac[nr].dev.platform_data = &ar231x_board; ++ res = &ar231x_wmac[nr].resource[0]; ++ res->start = base; ++ res->end = base + 0x10000 - 1; ++ res++; ++ res->start = irq; ++ res->end = irq; ++ return platform_device_register(&ar231x_wmac[nr]); ++} ++ ++static int __init ar231x_register_devices(void) ++{ ++ static struct resource res = { ++ .start = 0xFFFFFFFF, ++ }; ++ ++ platform_device_register_simple("GPIODEV", 0, &res, 1); ++ ar5312_init_devices(); ++ ar2315_init_devices(); ++ ++ return 0; ++} ++ ++device_initcall(ar231x_register_devices); +diff -Nur linux-2.6.39-rc7.orig/arch/mips/ar231x/devices.h linux-2.6.39-rc7/arch/mips/ar231x/devices.h +--- linux-2.6.39-rc7.orig/arch/mips/ar231x/devices.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/ar231x/devices.h 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,37 @@ ++#ifndef __AR231X_DEVICES_H ++#define __AR231X_DEVICES_H ++ ++enum { ++ /* handled by ar5312.c */ ++ DEV_TYPE_AR2312, ++ DEV_TYPE_AR2313, ++ DEV_TYPE_AR5312, ++ ++ /* handled by ar2315.c */ ++ DEV_TYPE_AR2315, ++ DEV_TYPE_AR2316, ++ DEV_TYPE_AR2317, ++ ++ DEV_TYPE_UNKNOWN ++}; ++ ++extern int ar231x_devtype; ++extern struct ar231x_board_config ar231x_board; ++extern asmlinkage void (*ar231x_irq_dispatch)(void); ++ ++extern int ar231x_find_config(u8 *flash_limit); ++extern void ar231x_serial_setup(u32 mapbase, unsigned int uartclk); ++extern int ar231x_add_wmac(int nr, u32 base, int irq); ++extern int ar231x_add_ethernet(int nr, u32 base, int irq, void *pdata); ++ ++static inline bool is_2315(void) ++{ ++ return (current_cpu_data.cputype == CPU_4KEC); ++} ++ ++static inline bool is_5312(void) ++{ ++ return !is_2315(); ++} ++ ++#endif +diff -Nur linux-2.6.39-rc7.orig/arch/mips/ar231x/early_printk.c linux-2.6.39-rc7/arch/mips/ar231x/early_printk.c +--- linux-2.6.39-rc7.orig/arch/mips/ar231x/early_printk.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/ar231x/early_printk.c 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,44 @@ ++/* ++ * 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) 2010 Gabor Juhos <juhosg@openwrt.org> ++ */ ++ ++#include <linux/mm.h> ++#include <linux/io.h> ++#include <linux/serial_reg.h> ++#include <asm/addrspace.h> ++ ++#include <asm/mach-ar231x/ar2315_regs.h> ++#include <asm/mach-ar231x/ar5312_regs.h> ++#include "devices.h" ++ ++static inline void prom_uart_wr(void __iomem *base, unsigned reg, ++ unsigned char ch) ++{ ++ __raw_writeb(ch, base + 4 * reg); ++} ++ ++static inline unsigned char prom_uart_rr(void __iomem *base, unsigned reg) ++{ ++ return __raw_readb(base + 4 * reg); ++} ++ ++void prom_putchar(unsigned char ch) ++{ ++ static void __iomem *base; ++ ++ if (unlikely(base == NULL)) { ++ if (is_2315()) ++ base = (void __iomem *)(KSEG1ADDR(AR2315_UART0)); ++ else ++ base = (void __iomem *)(KSEG1ADDR(AR531X_UART0)); ++ } ++ ++ while ((prom_uart_rr(base, UART_LSR) & UART_LSR_THRE) == 0); ++ prom_uart_wr(base, UART_TX, ch); ++ while ((prom_uart_rr(base, UART_LSR) & UART_LSR_THRE) == 0); ++} ++ +diff -Nur linux-2.6.39-rc7.orig/arch/mips/ar231x/pci.c linux-2.6.39-rc7/arch/mips/ar231x/pci.c +--- linux-2.6.39-rc7.orig/arch/mips/ar231x/pci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/ar231x/pci.c 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,230 @@ ++/* ++ * 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. ++ */ ++ ++#include <linux/types.h> ++#include <linux/pci.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/mm.h> ++#include <linux/spinlock.h> ++#include <linux/delay.h> ++#include <linux/irq.h> ++#include <asm/bootinfo.h> ++#include <asm/paccess.h> ++#include <asm/irq_cpu.h> ++#include <asm/io.h> ++#include <ar231x_platform.h> ++#include <ar231x.h> ++#include <ar2315_regs.h> ++#include "devices.h" ++ ++#define AR531X_MEM_BASE 0x80800000UL ++#define AR531X_MEM_SIZE 0x00ffffffUL ++#define AR531X_IO_SIZE 0x00007fffUL ++ ++static unsigned long configspace; ++ ++static int config_access(int devfn, int where, int size, u32 *ptr, bool write) ++{ ++ unsigned long flags; ++ int func = PCI_FUNC(devfn); ++ int dev = PCI_SLOT(devfn); ++ u32 value = 0; ++ int err = 0; ++ u32 addr; ++ ++ if (((dev != 0) && (dev != 3)) || (func > 2)) ++ return PCIBIOS_DEVICE_NOT_FOUND; ++ ++ /* Select Configuration access */ ++ local_irq_save(flags); ++ ar231x_mask_reg(AR2315_PCI_MISC_CONFIG, 0, AR2315_PCIMISC_CFG_SEL); ++ mb(); ++ ++ addr = (u32) configspace + (1 << (13 + dev)) + (func << 8) + where; ++ if (size == 1) ++ addr ^= 0x3; ++ else if (size == 2) ++ addr ^= 0x2; ++ ++ if (write) { ++ value = *ptr; ++ if (size == 1) ++ err = put_dbe(value, (u8 *) addr); ++ else if (size == 2) ++ err = put_dbe(value, (u16 *) addr); ++ else if (size == 4) ++ err = put_dbe(value, (u32 *) addr); ++ } else { ++ if (size == 1) ++ err = get_dbe(value, (u8 *) addr); ++ else if (size == 2) ++ err = get_dbe(value, (u16 *) addr); ++ else if (size == 4) ++ err = get_dbe(value, (u32 *) addr); ++ if (err) ++ *ptr = 0xffffffff; ++ else ++ *ptr = value; ++ } ++ ++ /* Select Memory access */ ++ ar231x_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_CFG_SEL, 0); ++ local_irq_restore(flags); ++ ++ return (err ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL); ++} ++ ++static int ar231x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * value) ++{ ++ return config_access(devfn, where, size, value, 0); ++} ++ ++static int ar231x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) ++{ ++ return config_access(devfn, where, size, &value, 1); ++} ++ ++struct pci_ops ar231x_pci_ops = { ++ .read = ar231x_pci_read, ++ .write = ar231x_pci_write, ++}; ++ ++static struct resource ar231x_mem_resource = { ++ .name = "AR531x PCI MEM", ++ .start = AR531X_MEM_BASE, ++ .end = AR531X_MEM_BASE + AR531X_MEM_SIZE - AR531X_IO_SIZE - 1 + 0x4000000, ++ .flags = IORESOURCE_MEM, ++}; ++ ++static struct resource ar231x_io_resource = { ++ .name = "AR531x PCI I/O", ++ .start = AR531X_MEM_BASE + AR531X_MEM_SIZE - AR531X_IO_SIZE, ++ .end = AR531X_MEM_BASE + AR531X_MEM_SIZE - 1, ++ .flags = IORESOURCE_IO, ++}; ++ ++struct pci_controller ar231x_pci_controller = { ++ .pci_ops = &ar231x_pci_ops, ++ .mem_resource = &ar231x_mem_resource, ++ .io_resource = &ar231x_io_resource, ++ .mem_offset = 0x00000000UL, ++ .io_offset = 0x00000000UL, ++}; ++ ++int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) ++{ ++ return AR2315_IRQ_LCBUS_PCI; ++} ++ ++int pcibios_plat_dev_init(struct pci_dev *dev) ++{ ++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 5); ++ pci_write_config_word(dev, 0x40, 0); ++ ++ /* Clear any pending Abort or external Interrupts ++ * and enable interrupt processing */ ++ ar231x_mask_reg(AR2315_PCI_INTEN_REG, AR2315_PCI_INT_ENABLE, 0); ++ ar231x_write_reg(AR2315_PCI_INT_STATUS, (AR2315_PCI_ABORT_INT | AR2315_PCI_EXT_INT)); ++ ar231x_write_reg(AR2315_PCI_INT_MASK, (AR2315_PCI_ABORT_INT | AR2315_PCI_EXT_INT)); ++ ar231x_mask_reg(AR2315_PCI_INTEN_REG, 0, AR2315_PCI_INT_ENABLE); ++ ++ return 0; ++} ++ ++static void ++ar2315_pci_fixup(struct pci_dev *dev) ++{ ++ unsigned int devfn = dev->devfn; ++ ++ if (dev->bus->number != 0) ++ return; ++ ++ /* Only fix up the PCI host settings */ ++ if ((PCI_SLOT(devfn) != 3) || (PCI_FUNC(devfn) != 0)) ++ return; ++ ++ /* Fix up MBARs */ ++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, HOST_PCI_MBAR0); ++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, HOST_PCI_MBAR1); ++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, HOST_PCI_MBAR2); ++ pci_write_config_dword(dev, PCI_COMMAND, ++ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SPECIAL | ++ PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | ++ PCI_COMMAND_FAST_BACK); ++} ++DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, ar2315_pci_fixup); ++ ++static int __init ++ar2315_pci_init(void) ++{ ++ u32 reg; ++ ++ if (ar231x_devtype != DEV_TYPE_AR2315) ++ return -ENODEV; ++ ++ configspace = (unsigned long) ioremap_nocache(0x80000000, 1*1024*1024); /* Remap PCI config space */ ++ ar231x_pci_controller.io_map_base = ++ (unsigned long) ioremap_nocache(AR531X_MEM_BASE + AR531X_MEM_SIZE, AR531X_IO_SIZE); ++ set_io_port_base(ar231x_pci_controller.io_map_base); /* PCI I/O space */ ++ ++ reg = ar231x_mask_reg(AR2315_RESET, 0, AR2315_RESET_PCIDMA); ++ msleep(10); ++ ++ reg &= ~AR2315_RESET_PCIDMA; ++ ar231x_write_reg(AR2315_RESET, reg); ++ msleep(10); ++ ++ ar231x_mask_reg(AR2315_ENDIAN_CTL, 0, ++ AR2315_CONFIG_PCIAHB | AR2315_CONFIG_PCIAHB_BRIDGE); ++ ++ ar231x_write_reg(AR2315_PCICLK, AR2315_PCICLK_PLLC_CLKM | ++ (AR2315_PCICLK_IN_FREQ_DIV_6 << AR2315_PCICLK_DIV_S)); ++ ar231x_mask_reg(AR2315_AHB_ARB_CTL, 0, AR2315_ARB_PCI); ++ ar231x_mask_reg(AR2315_IF_CTL, AR2315_IF_PCI_CLK_MASK | AR2315_IF_MASK, ++ AR2315_IF_PCI | AR2315_IF_PCI_HOST | AR2315_IF_PCI_INTR | ++ (AR2315_IF_PCI_CLK_OUTPUT_CLK << AR2315_IF_PCI_CLK_SHIFT)); ++ ++ /* Reset the PCI bus by setting bits 5-4 in PCI_MCFG */ ++ ar231x_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_RST_MODE, ++ AR2315_PCIRST_LOW); ++ msleep(100); ++ ++ /* Bring the PCI out of reset */ ++ ar231x_mask_reg(AR2315_PCI_MISC_CONFIG, AR2315_PCIMISC_RST_MODE, ++ AR2315_PCIRST_HIGH | AR2315_PCICACHE_DIS | 0x8); ++ ++ ar231x_write_reg(AR2315_PCI_UNCACHE_CFG, ++ 0x1E | /* 1GB uncached */ ++ (1 << 5) | /* Enable uncached */ ++ (0x2 << 30) /* Base: 0x80000000 */ ++ ); ++ ar231x_read_reg(AR2315_PCI_UNCACHE_CFG); ++ ++ msleep(500); ++ ++ /* dirty hack - anyone with a datasheet that knows the memory map ? */ ++ ioport_resource.start = 0x10000000; ++ ioport_resource.end = 0xffffffff; ++ iomem_resource.start = 0x10000000; ++ iomem_resource.end = 0xffffffff; ++ ++ register_pci_controller(&ar231x_pci_controller); ++ ++ return 0; ++} ++ ++arch_initcall(ar2315_pci_init); +diff -Nur linux-2.6.39-rc7.orig/arch/mips/ar231x/prom.c linux-2.6.39-rc7/arch/mips/ar231x/prom.c +--- linux-2.6.39-rc7.orig/arch/mips/ar231x/prom.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/ar231x/prom.c 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,37 @@ ++/* ++ * 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 MontaVista Software Inc ++ * Copyright (C) 2003 Atheros Communications, Inc., All Rights Reserved. ++ * Copyright (C) 2006 FON Technology, SL. ++ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> ++ */ ++ ++/* ++ * Prom setup file for ar531x ++ */ ++ ++#include <linux/init.h> ++#include <generated/autoconf.h> ++#include <linux/kernel.h> ++#include <linux/string.h> ++#include <linux/mm.h> ++#include <linux/bootmem.h> ++ ++#include <asm/bootinfo.h> ++#include <asm/addrspace.h> ++#include "ar5312.h" ++#include "ar2315.h" ++ ++void __init prom_init(void) ++{ ++ ar5312_prom_init(); ++ ar2315_prom_init(); ++} ++ ++void __init prom_free_prom_memory(void) ++{ ++} +diff -Nur linux-2.6.39-rc7.orig/arch/mips/ar231x/reset.c linux-2.6.39-rc7/arch/mips/ar231x/reset.c +--- linux-2.6.39-rc7.orig/arch/mips/ar231x/reset.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/ar231x/reset.c 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,161 @@ ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/timer.h> ++#include <linux/interrupt.h> ++#include <linux/kobject.h> ++#include <linux/workqueue.h> ++#include <linux/skbuff.h> ++#include <linux/netlink.h> ++#include <net/sock.h> ++#include <asm/uaccess.h> ++#include <ar231x_platform.h> ++#include <ar231x.h> ++#include <gpio.h> ++#include "devices.h" ++ ++#define AR531X_RESET_GPIO_IRQ (AR531X_GPIO_IRQ(ar231x_board.config->resetConfigGpio)) ++ ++struct event_t { ++ struct work_struct wq; ++ int set; ++ unsigned long jiffies; ++}; ++ ++static struct timer_list rst_button_timer; ++static unsigned long seen; ++ ++struct sock *uevent_sock = NULL; ++EXPORT_SYMBOL_GPL(uevent_sock); ++extern u64 uevent_next_seqnum(void); ++ ++static int no_release_workaround = 1; ++module_param(no_release_workaround, int, 0); ++ ++static inline void ++add_msg(struct sk_buff *skb, char *msg) ++{ ++ char *scratch; ++ scratch = skb_put(skb, strlen(msg) + 1); ++ sprintf(scratch, msg); ++} ++ ++static void ++hotplug_button(struct work_struct *wq) ++{ ++ struct sk_buff *skb; ++ struct event_t *event; ++ size_t len; ++ char *scratch, *s; ++ char buf[128]; ++ ++ event = container_of(wq, struct event_t, wq); ++ if (!uevent_sock) ++ goto done; ++ ++ /* allocate message with the maximum possible size */ ++ s = event->set ? "pressed" : "released"; ++ len = strlen(s) + 2; ++ skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); ++ if (!skb) ++ goto done; ++ ++ /* add header */ ++ scratch = skb_put(skb, len); ++ sprintf(scratch, "%s@",s); ++ ++ /* copy keys to our continuous event payload buffer */ ++ add_msg(skb, "HOME=/"); ++ add_msg(skb, "PATH=/sbin:/bin:/usr/sbin:/usr/bin"); ++ add_msg(skb, "SUBSYSTEM=button"); ++ add_msg(skb, "BUTTON=reset"); ++ add_msg(skb, (event->set ? "ACTION=pressed" : "ACTION=released")); ++ sprintf(buf, "SEEN=%ld", (event->jiffies - seen)/HZ); ++ add_msg(skb, buf); ++ snprintf(buf, 128, "SEQNUM=%llu", uevent_next_seqnum()); ++ add_msg(skb, buf); ++ ++ NETLINK_CB(skb).dst_group = 1; ++ netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL); ++ ++done: ++ kfree(event); ++} ++ ++static void ++reset_button_poll(unsigned long unused) ++{ ++ struct event_t *event; ++ int gpio = ~0; ++ ++ if(!no_release_workaround) ++ return; ++ ++ gpio = ar231x_gpiodev->get(); ++ gpio &= (1 << (AR531X_RESET_GPIO_IRQ - AR531X_GPIO_IRQ_BASE)); ++ if(gpio) { ++ rst_button_timer.expires = jiffies + (HZ / 4); ++ add_timer(&rst_button_timer); ++ return; ++ } ++ ++ event = (struct event_t *) kzalloc(sizeof(struct event_t), GFP_ATOMIC); ++ if (!event) ++ return; ++ ++ event->set = 0; ++ event->jiffies = jiffies; ++ INIT_WORK(&event->wq, hotplug_button); ++ schedule_work(&event->wq); ++} ++ ++static irqreturn_t ++button_handler(int irq, void *dev_id) ++{ ++ static int pressed = 0; ++ struct event_t *event; ++ u32 gpio = ~0; ++ ++ event = (struct event_t *) kzalloc(sizeof(struct event_t), GFP_ATOMIC); ++ if (!event) ++ return IRQ_NONE; ++ ++ pressed = !pressed; ++ ++ gpio = ar231x_gpiodev->get() & (1 << (irq - AR531X_GPIO_IRQ_BASE)); ++ ++ event->set = gpio; ++ if(!event->set) ++ no_release_workaround = 0; ++ ++ event->jiffies = jiffies; ++ ++ INIT_WORK(&event->wq, hotplug_button); ++ schedule_work(&event->wq); ++ ++ seen = jiffies; ++ if(event->set && no_release_workaround) ++ mod_timer(&rst_button_timer, jiffies + (HZ / 4)); ++ ++ return IRQ_HANDLED; ++} ++ ++ ++static int __init ++ar231x_init_reset(void) ++{ ++ seen = jiffies; ++ ++ if (ar231x_board.config->resetConfigGpio == 0xffff) ++ return -ENODEV; ++ ++ init_timer(&rst_button_timer); ++ rst_button_timer.function = reset_button_poll; ++ rst_button_timer.expires = jiffies + HZ / 50; ++ add_timer(&rst_button_timer); ++ ++ request_irq(AR531X_RESET_GPIO_IRQ, &button_handler, IRQF_SAMPLE_RANDOM, "ar231x_reset", NULL); ++ ++ return 0; ++} ++ ++module_init(ar231x_init_reset); +diff -Nur linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/ar2315_regs.h linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/ar2315_regs.h +--- linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/ar2315_regs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/ar2315_regs.h 2011-05-15 21:44:12.000000000 +0200 +@@ -0,0 +1,580 @@ ++/* ++ * Register definitions for AR2315+ ++ * ++ * 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) 2003 Atheros Communications, Inc., All Rights Reserved. ++ * Copyright (C) 2006 FON Technology, SL. ++ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2006-2008 Felix Fietkau <nbd@openwrt.org> ++ */ ++ ++#ifndef __AR2315_REG_H ++#define __AR2315_REG_H ++ ++/* ++ * IRQs ++ */ ++#define AR2315_IRQ_MISC_INTRS MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */ ++#define AR2315_IRQ_WLAN0_INTRS MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */ ++#define AR2315_IRQ_ENET0_INTRS MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */ ++#define AR2315_IRQ_LCBUS_PCI MIPS_CPU_IRQ_BASE+5 /* C0_CAUSE: 0x2000 */ ++#define AR2315_IRQ_WLAN0_POLL MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */ ++ ++/* ++ * Address map ++ */ ++#define AR2315_SPI_READ 0x08000000 /* SPI FLASH */ ++#define AR2315_WLAN0 0x10000000 /* Wireless MMR */ ++#define AR2315_PCI 0x10100000 /* PCI MMR */ ++#define AR2315_SDRAMCTL 0x10300000 /* SDRAM MMR */ ++#define AR2315_LOCAL 0x10400000 /* LOCAL BUS MMR */ ++#define AR2315_ENET0 0x10500000 /* ETHERNET MMR */ ++#define AR2315_DSLBASE 0x11000000 /* RESET CONTROL MMR */ ++#define AR2315_UART0 0x11100003 /* UART MMR */ ++#define AR2315_SPI 0x11300000 /* SPI FLASH MMR */ ++#define AR2315_PCIEXT 0x80000000 /* pci external */ ++ ++/* ++ * Reset Register ++ */ ++#define AR2315_COLD_RESET (AR2315_DSLBASE + 0x0000) ++ ++#define AR2315_RESET_COLD_AHB 0x00000001 ++#define AR2315_RESET_COLD_APB 0x00000002 ++#define AR2315_RESET_COLD_CPU 0x00000004 ++#define AR2315_RESET_COLD_CPUWARM 0x00000008 ++#define AR2315_RESET_SYSTEM (RESET_COLD_CPU | RESET_COLD_APB | RESET_COLD_AHB) /* full system */ ++#define AR2317_RESET_SYSTEM 0x00000010 ++ ++ ++#define AR2315_RESET (AR2315_DSLBASE + 0x0004) ++ ++#define AR2315_RESET_WARM_WLAN0_MAC 0x00000001 /* warm reset WLAN0 MAC */ ++#define AR2315_RESET_WARM_WLAN0_BB 0x00000002 /* warm reset WLAN0 BaseBand */ ++#define AR2315_RESET_MPEGTS_RSVD 0x00000004 /* warm reset MPEG-TS */ ++#define AR2315_RESET_PCIDMA 0x00000008 /* warm reset PCI ahb/dma */ ++#define AR2315_RESET_MEMCTL 0x00000010 /* warm reset memory controller */ ++#define AR2315_RESET_LOCAL 0x00000020 /* warm reset local bus */ ++#define AR2315_RESET_I2C_RSVD 0x00000040 /* warm reset I2C bus */ ++#define AR2315_RESET_SPI 0x00000080 /* warm reset SPI interface */ ++#define AR2315_RESET_UART0 0x00000100 /* warm reset UART0 */ ++#define AR2315_RESET_IR_RSVD 0x00000200 /* warm reset IR interface */ ++#define AR2315_RESET_EPHY0 0x00000400 /* cold reset ENET0 phy */ ++#define AR2315_RESET_ENET0 0x00000800 /* cold reset ENET0 mac */ ++ ++/* ++ * AHB master arbitration control ++ */ ++#define AR2315_AHB_ARB_CTL (AR2315_DSLBASE + 0x0008) ++ ++#define AR2315_ARB_CPU 0x00000001 /* CPU, default */ ++#define AR2315_ARB_WLAN 0x00000002 /* WLAN */ ++#define AR2315_ARB_MPEGTS_RSVD 0x00000004 /* MPEG-TS */ ++#define AR2315_ARB_LOCAL 0x00000008 /* LOCAL */ ++#define AR2315_ARB_PCI 0x00000010 /* PCI */ ++#define AR2315_ARB_ETHERNET 0x00000020 /* Ethernet */ ++#define AR2315_ARB_RETRY 0x00000100 /* retry policy, debug only */ ++ ++/* ++ * Config Register ++ */ ++#define AR2315_ENDIAN_CTL (AR2315_DSLBASE + 0x000c) ++ ++#define AR2315_CONFIG_AHB 0x00000001 /* EC - AHB bridge endianess */ ++#define AR2315_CONFIG_WLAN 0x00000002 /* WLAN byteswap */ ++#define AR2315_CONFIG_MPEGTS_RSVD 0x00000004 /* MPEG-TS byteswap */ ++#define AR2315_CONFIG_PCI 0x00000008 /* PCI byteswap */ ++#define AR2315_CONFIG_MEMCTL 0x00000010 /* Memory controller endianess */ ++#define AR2315_CONFIG_LOCAL 0x00000020 /* Local bus byteswap */ ++#define AR2315_CONFIG_ETHERNET 0x00000040 /* Ethernet byteswap */ ++ ++#define AR2315_CONFIG_MERGE 0x00000200 /* CPU write buffer merge */ ++#define AR2315_CONFIG_CPU 0x00000400 /* CPU big endian */ ++#define AR2315_CONFIG_PCIAHB 0x00000800 ++#define AR2315_CONFIG_PCIAHB_BRIDGE 0x00001000 ++#define AR2315_CONFIG_SPI 0x00008000 /* SPI byteswap */ ++#define AR2315_CONFIG_CPU_DRAM 0x00010000 ++#define AR2315_CONFIG_CPU_PCI 0x00020000 ++#define AR2315_CONFIG_CPU_MMR 0x00040000 ++#define AR2315_CONFIG_BIG 0x00000400 ++ ++ ++/* ++ * NMI control ++ */ ++#define AR2315_NMI_CTL (AR2315_DSLBASE + 0x0010) ++ ++#define AR2315_NMI_EN 1 ++ ++/* ++ * Revision Register - Initial value is 0x3010 (WMAC 3.0, AR531X 1.0). ++ */ ++#define AR2315_SREV (AR2315_DSLBASE + 0x0014) ++ ++#define AR2315_REV_MAJ 0x00f0 ++#define AR2315_REV_MAJ_S 4 ++#define AR2315_REV_MIN 0x000f ++#define AR2315_REV_MIN_S 0 ++#define AR2315_REV_CHIP (AR2315_REV_MAJ|AR2315_REV_MIN) ++ ++/* ++ * Interface Enable ++ */ ++#define AR2315_IF_CTL (AR2315_DSLBASE + 0x0018) ++ ++#define AR2315_IF_MASK 0x00000007 ++#define AR2315_IF_DISABLED 0 ++#define AR2315_IF_PCI 1 ++#define AR2315_IF_TS_LOCAL 2 ++#define AR2315_IF_ALL 3 /* only for emulation with separate pins */ ++#define AR2315_IF_LOCAL_HOST 0x00000008 ++#define AR2315_IF_PCI_HOST 0x00000010 ++#define AR2315_IF_PCI_INTR 0x00000020 ++#define AR2315_IF_PCI_CLK_MASK 0x00030000 ++#define AR2315_IF_PCI_CLK_INPUT 0 ++#define AR2315_IF_PCI_CLK_OUTPUT_LOW 1 ++#define AR2315_IF_PCI_CLK_OUTPUT_CLK 2 ++#define AR2315_IF_PCI_CLK_OUTPUT_HIGH 3 ++#define AR2315_IF_PCI_CLK_SHIFT 16 ++ ++/* ++ * APB Interrupt control ++ */ ++ ++#define AR2315_ISR (AR2315_DSLBASE + 0x0020) ++#define AR2315_IMR (AR2315_DSLBASE + 0x0024) ++#define AR2315_GISR (AR2315_DSLBASE + 0x0028) ++ ++#define AR2315_ISR_UART0 0x0001 /* high speed UART */ ++#define AR2315_ISR_I2C_RSVD 0x0002 /* I2C bus */ ++#define AR2315_ISR_SPI 0x0004 /* SPI bus */ ++#define AR2315_ISR_AHB 0x0008 /* AHB error */ ++#define AR2315_ISR_APB 0x0010 /* APB error */ ++#define AR2315_ISR_TIMER 0x0020 /* timer */ ++#define AR2315_ISR_GPIO 0x0040 /* GPIO */ ++#define AR2315_ISR_WD 0x0080 /* watchdog */ ++#define AR2315_ISR_IR_RSVD 0x0100 /* IR */ ++ ++#define AR2315_GISR_MISC 0x0001 ++#define AR2315_GISR_WLAN0 0x0002 ++#define AR2315_GISR_MPEGTS_RSVD 0x0004 ++#define AR2315_GISR_LOCALPCI 0x0008 ++#define AR2315_GISR_WMACPOLL 0x0010 ++#define AR2315_GISR_TIMER 0x0020 ++#define AR2315_GISR_ETHERNET 0x0040 ++ ++/* ++ * Interrupt routing from IO to the processor IP bits ++ * Define our inter mask and level ++ */ ++#define AR2315_INTR_MISCIO SR_IBIT3 ++#define AR2315_INTR_WLAN0 SR_IBIT4 ++#define AR2315_INTR_ENET0 SR_IBIT5 ++#define AR2315_INTR_LOCALPCI SR_IBIT6 ++#define AR2315_INTR_WMACPOLL SR_IBIT7 ++#define AR2315_INTR_COMPARE SR_IBIT8 ++ ++/* ++ * Timers ++ */ ++#define AR2315_TIMER (AR2315_DSLBASE + 0x0030) ++#define AR2315_RELOAD (AR2315_DSLBASE + 0x0034) ++#define AR2315_WD (AR2315_DSLBASE + 0x0038) ++#define AR2315_WDC (AR2315_DSLBASE + 0x003c) ++ ++#define AR2315_WDC_IGNORE_EXPIRATION 0x00000000 ++#define AR2315_WDC_NMI 0x00000001 /* NMI on watchdog */ ++#define AR2315_WDC_RESET 0x00000002 /* reset on watchdog */ ++ ++/* ++ * CPU Performance Counters ++ */ ++#define AR2315_PERFCNT0 (AR2315_DSLBASE + 0x0048) ++#define AR2315_PERFCNT1 (AR2315_DSLBASE + 0x004c) ++ ++#define AR2315_PERF0_DATAHIT 0x0001 /* Count Data Cache Hits */ ++#define AR2315_PERF0_DATAMISS 0x0002 /* Count Data Cache Misses */ ++#define AR2315_PERF0_INSTHIT 0x0004 /* Count Instruction Cache Hits */ ++#define AR2315_PERF0_INSTMISS 0x0008 /* Count Instruction Cache Misses */ ++#define AR2315_PERF0_ACTIVE 0x0010 /* Count Active Processor Cycles */ ++#define AR2315_PERF0_WBHIT 0x0020 /* Count CPU Write Buffer Hits */ ++#define AR2315_PERF0_WBMISS 0x0040 /* Count CPU Write Buffer Misses */ ++ ++#define AR2315_PERF1_EB_ARDY 0x0001 /* Count EB_ARdy signal */ ++#define AR2315_PERF1_EB_AVALID 0x0002 /* Count EB_AValid signal */ ++#define AR2315_PERF1_EB_WDRDY 0x0004 /* Count EB_WDRdy signal */ ++#define AR2315_PERF1_EB_RDVAL 0x0008 /* Count EB_RdVal signal */ ++#define AR2315_PERF1_VRADDR 0x0010 /* Count valid read address cycles */ ++#define AR2315_PERF1_VWADDR 0x0020 /* Count valid write address cycles */ ++#define AR2315_PERF1_VWDATA 0x0040 /* Count valid write data cycles */ ++ ++/* ++ * AHB Error Reporting. ++ */ ++#define AR2315_AHB_ERR0 (AR2315_DSLBASE + 0x0050) /* error */ ++#define AR2315_AHB_ERR1 (AR2315_DSLBASE + 0x0054) /* haddr */ ++#define AR2315_AHB_ERR2 (AR2315_DSLBASE + 0x0058) /* hwdata */ ++#define AR2315_AHB_ERR3 (AR2315_DSLBASE + 0x005c) /* hrdata */ ++#define AR2315_AHB_ERR4 (AR2315_DSLBASE + 0x0060) /* status */ ++ ++#define AHB_ERROR_DET 1 /* AHB Error has been detected, */ ++ /* write 1 to clear all bits in ERR0 */ ++#define AHB_ERROR_OVR 2 /* AHB Error overflow has been detected */ ++#define AHB_ERROR_WDT 4 /* AHB Error due to wdt instead of hresp */ ++ ++#define AR2315_PROCERR_HMAST 0x0000000f ++#define AR2315_PROCERR_HMAST_DFLT 0 ++#define AR2315_PROCERR_HMAST_WMAC 1 ++#define AR2315_PROCERR_HMAST_ENET 2 ++#define AR2315_PROCERR_HMAST_PCIENDPT 3 ++#define AR2315_PROCERR_HMAST_LOCAL 4 ++#define AR2315_PROCERR_HMAST_CPU 5 ++#define AR2315_PROCERR_HMAST_PCITGT 6 ++ ++#define AR2315_PROCERR_HMAST_S 0 ++#define AR2315_PROCERR_HWRITE 0x00000010 ++#define AR2315_PROCERR_HSIZE 0x00000060 ++#define AR2315_PROCERR_HSIZE_S 5 ++#define AR2315_PROCERR_HTRANS 0x00000180 ++#define AR2315_PROCERR_HTRANS_S 7 ++#define AR2315_PROCERR_HBURST 0x00000e00 ++#define AR2315_PROCERR_HBURST_S 9 ++ ++/* ++ * Clock Control ++ */ ++#define AR2315_PLLC_CTL (AR2315_DSLBASE + 0x0064) ++#define AR2315_PLLV_CTL (AR2315_DSLBASE + 0x0068) ++#define AR2315_CPUCLK (AR2315_DSLBASE + 0x006c) ++#define AR2315_AMBACLK (AR2315_DSLBASE + 0x0070) ++#define AR2315_SYNCCLK (AR2315_DSLBASE + 0x0074) ++#define AR2315_DSL_SLEEP_CTL (AR2315_DSLBASE + 0x0080) ++#define AR2315_DSL_SLEEP_DUR (AR2315_DSLBASE + 0x0084) ++ ++/* PLLc Control fields */ ++#define PLLC_REF_DIV_M 0x00000003 ++#define PLLC_REF_DIV_S 0 ++#define PLLC_FDBACK_DIV_M 0x0000007C ++#define PLLC_FDBACK_DIV_S 2 ++#define PLLC_ADD_FDBACK_DIV_M 0x00000080 ++#define PLLC_ADD_FDBACK_DIV_S 7 ++#define PLLC_CLKC_DIV_M 0x0001c000 ++#define PLLC_CLKC_DIV_S 14 ++#define PLLC_CLKM_DIV_M 0x00700000 ++#define PLLC_CLKM_DIV_S 20 ++ ++/* CPU CLK Control fields */ ++#define CPUCLK_CLK_SEL_M 0x00000003 ++#define CPUCLK_CLK_SEL_S 0 ++#define CPUCLK_CLK_DIV_M 0x0000000c ++#define CPUCLK_CLK_DIV_S 2 ++ ++/* AMBA CLK Control fields */ ++#define AMBACLK_CLK_SEL_M 0x00000003 ++#define AMBACLK_CLK_SEL_S 0 ++#define AMBACLK_CLK_DIV_M 0x0000000c ++#define AMBACLK_CLK_DIV_S 2 ++ ++/* ++ * GPIO ++ */ ++#define AR2315_GPIO_DI (AR2315_DSLBASE + 0x0088) ++#define AR2315_GPIO_DO (AR2315_DSLBASE + 0x0090) ++#define AR2315_GPIO_CR (AR2315_DSLBASE + 0x0098) ++#define AR2315_GPIO_INT (AR2315_DSLBASE + 0x00a0) ++ ++#define AR2315_GPIO_CR_M(x) (1 << (x)) /* mask for i/o */ ++#define AR2315_GPIO_CR_O(x) (1 << (x)) /* output */ ++#define AR2315_GPIO_CR_I(x) (0) /* input */ ++ ++#define AR2315_GPIO_INT_S(x) (x) /* interrupt enable */ ++#define AR2315_GPIO_INT_M (0x3F) /* mask for int */ ++#define AR2315_GPIO_INT_LVL(x) ((x) << 6) /* interrupt level */ ++#define AR2315_GPIO_INT_LVL_M ((0x3) << 6) /* mask for int level */ ++ ++#define AR2315_GPIO_INT_MAX_Y 1 /* Maximum value of Y for AR5313_GPIO_INT_* macros */ ++#define AR2315_GPIO_INT_LVL_OFF 0 /* Triggerring off */ ++#define AR2315_GPIO_INT_LVL_LOW 1 /* Low Level Triggered */ ++#define AR2315_GPIO_INT_LVL_HIGH 2 /* High Level Triggered */ ++#define AR2315_GPIO_INT_LVL_EDGE 3 /* Edge Triggered */ ++ ++#define AR2315_RESET_GPIO 5 ++#define AR2315_NUM_GPIO 22 ++ ++/* ++ * PCI Clock Control ++ */ ++#define AR2315_PCICLK (AR2315_DSLBASE + 0x00a4) ++ ++#define AR2315_PCICLK_INPUT_M 0x3 ++#define AR2315_PCICLK_INPUT_S 0 ++ ++#define AR2315_PCICLK_PLLC_CLKM 0 ++#define AR2315_PCICLK_PLLC_CLKM1 1 ++#define AR2315_PCICLK_PLLC_CLKC 2 ++#define AR2315_PCICLK_REF_CLK 3 ++ ++#define AR2315_PCICLK_DIV_M 0xc ++#define AR2315_PCICLK_DIV_S 2 ++ ++#define AR2315_PCICLK_IN_FREQ 0 ++#define AR2315_PCICLK_IN_FREQ_DIV_6 1 ++#define AR2315_PCICLK_IN_FREQ_DIV_8 2 ++#define AR2315_PCICLK_IN_FREQ_DIV_10 3 ++ ++/* ++ * Observation Control Register ++ */ ++#define AR2315_OCR (AR2315_DSLBASE + 0x00b0) ++#define OCR_GPIO0_IRIN 0x0040 ++#define OCR_GPIO1_IROUT 0x0080 ++#define OCR_GPIO3_RXCLR 0x0200 ++ ++/* ++ * General Clock Control ++ */ ++ ++#define AR2315_MISCCLK (AR2315_DSLBASE + 0x00b4) ++#define MISCCLK_PLLBYPASS_EN 0x00000001 ++#define MISCCLK_PROCREFCLK 0x00000002 ++ ++/* ++ * SDRAM Controller ++ * - No read or write buffers are included. ++ */ ++#define AR2315_MEM_CFG (AR2315_SDRAMCTL + 0x00) ++#define AR2315_MEM_CTRL (AR2315_SDRAMCTL + 0x0c) ++#define AR2315_MEM_REF (AR2315_SDRAMCTL + 0x10) ++ ++#define SDRAM_DATA_WIDTH_M 0x00006000 ++#define SDRAM_DATA_WIDTH_S 13 ++ ++#define SDRAM_COL_WIDTH_M 0x00001E00 ++#define SDRAM_COL_WIDTH_S 9 ++ ++#define SDRAM_ROW_WIDTH_M 0x000001E0 ++#define SDRAM_ROW_WIDTH_S 5 ++ ++#define SDRAM_BANKADDR_BITS_M 0x00000018 ++#define SDRAM_BANKADDR_BITS_S 3 ++ ++/* ++ * SPI Flash Interface Registers ++ */ ++ ++#define AR2315_SPI_CTL (AR2315_SPI + 0x00) ++#define AR2315_SPI_OPCODE (AR2315_SPI + 0x04) ++#define AR2315_SPI_DATA (AR2315_SPI + 0x08) ++ ++#define SPI_CTL_START 0x00000100 ++#define SPI_CTL_BUSY 0x00010000 ++#define SPI_CTL_TXCNT_MASK 0x0000000f ++#define SPI_CTL_RXCNT_MASK 0x000000f0 ++#define SPI_CTL_TX_RX_CNT_MASK 0x000000ff ++#define SPI_CTL_SIZE_MASK 0x00060000 ++ ++#define SPI_CTL_CLK_SEL_MASK 0x03000000 ++#define SPI_OPCODE_MASK 0x000000ff ++ ++/* ++ * PCI Bus Interface Registers ++ */ ++#define AR2315_PCI_1MS_REG (AR2315_PCI + 0x0008) ++#define AR2315_PCI_1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */ ++ ++#define AR2315_PCI_MISC_CONFIG (AR2315_PCI + 0x000c) ++#define AR2315_PCIMISC_TXD_EN 0x00000001 /* Enable TXD for fragments */ ++#define AR2315_PCIMISC_CFG_SEL 0x00000002 /* mem or config cycles */ ++#define AR2315_PCIMISC_GIG_MASK 0x0000000C /* bits 31-30 for pci req */ ++#define AR2315_PCIMISC_RST_MODE 0x00000030 ++#define AR2315_PCIRST_INPUT 0x00000000 /* 4:5=0 rst is input */ ++#define AR2315_PCIRST_LOW 0x00000010 /* 4:5=1 rst to GND */ ++#define AR2315_PCIRST_HIGH 0x00000020 /* 4:5=2 rst to VDD */ ++#define AR2315_PCIGRANT_EN 0x00000000 /* 6:7=0 early grant en */ ++#define AR2315_PCIGRANT_FRAME 0x00000040 /* 6:7=1 grant waits 4 frame */ ++#define AR2315_PCIGRANT_IDLE 0x00000080 /* 6:7=2 grant waits 4 idle */ ++#define AR2315_PCIGRANT_GAP 0x00000000 /* 6:7=2 grant waits 4 idle */ ++#define AR2315_PCICACHE_DIS 0x00001000 /* PCI external access cache disable */ ++ ++#define AR2315_PCI_OUT_TSTAMP (AR2315_PCI + 0x0010) ++ ++#define AR2315_PCI_UNCACHE_CFG (AR2315_PCI + 0x0014) ++ ++#define AR2315_PCI_IN_EN (AR2315_PCI + 0x0100) ++#define AR2315_PCI_IN_EN0 0x01 /* Enable chain 0 */ ++#define AR2315_PCI_IN_EN1 0x02 /* Enable chain 1 */ ++#define AR2315_PCI_IN_EN2 0x04 /* Enable chain 2 */ ++#define AR2315_PCI_IN_EN3 0x08 /* Enable chain 3 */ ++ ++#define AR2315_PCI_IN_DIS (AR2315_PCI + 0x0104) ++#define AR2315_PCI_IN_DIS0 0x01 /* Disable chain 0 */ ++#define AR2315_PCI_IN_DIS1 0x02 /* Disable chain 1 */ ++#define AR2315_PCI_IN_DIS2 0x04 /* Disable chain 2 */ ++#define AR2315_PCI_IN_DIS3 0x08 /* Disable chain 3 */ ++ ++#define AR2315_PCI_IN_PTR (AR2315_PCI + 0x0200) ++ ++#define AR2315_PCI_OUT_EN (AR2315_PCI + 0x0400) ++#define AR2315_PCI_OUT_EN0 0x01 /* Enable chain 0 */ ++ ++#define AR2315_PCI_OUT_DIS (AR2315_PCI + 0x0404) ++#define AR2315_PCI_OUT_DIS0 0x01 /* Disable chain 0 */ ++ ++#define AR2315_PCI_OUT_PTR (AR2315_PCI + 0x0408) ++ ++#define AR2315_PCI_INT_STATUS (AR2315_PCI + 0x0500) /* write one to clr */ ++#define AR2315_PCI_TXINT 0x00000001 /* Desc In Completed */ ++#define AR2315_PCI_TXOK 0x00000002 /* Desc In OK */ ++#define AR2315_PCI_TXERR 0x00000004 /* Desc In ERR */ ++#define AR2315_PCI_TXEOL 0x00000008 /* Desc In End-of-List */ ++#define AR2315_PCI_RXINT 0x00000010 /* Desc Out Completed */ ++#define AR2315_PCI_RXOK 0x00000020 /* Desc Out OK */ ++#define AR2315_PCI_RXERR 0x00000040 /* Desc Out ERR */ ++#define AR2315_PCI_RXEOL 0x00000080 /* Desc Out EOL */ ++#define AR2315_PCI_TXOOD 0x00000200 /* Desc In Out-of-Desc */ ++#define AR2315_PCI_MASK 0x0000FFFF /* Desc Mask */ ++#define AR2315_PCI_EXT_INT 0x02000000 ++#define AR2315_PCI_ABORT_INT 0x04000000 ++ ++#define AR2315_PCI_INT_MASK (AR2315_PCI + 0x0504) /* same as INT_STATUS */ ++ ++#define AR2315_PCI_INTEN_REG (AR2315_PCI + 0x0508) ++#define AR2315_PCI_INT_DISABLE 0x00 /* disable pci interrupts */ ++#define AR2315_PCI_INT_ENABLE 0x01 /* enable pci interrupts */ ++ ++#define AR2315_PCI_HOST_IN_EN (AR2315_PCI + 0x0800) ++#define AR2315_PCI_HOST_IN_DIS (AR2315_PCI + 0x0804) ++#define AR2315_PCI_HOST_IN_PTR (AR2315_PCI + 0x0810) ++#define AR2315_PCI_HOST_OUT_EN (AR2315_PCI + 0x0900) ++#define AR2315_PCI_HOST_OUT_DIS (AR2315_PCI + 0x0904) ++#define AR2315_PCI_HOST_OUT_PTR (AR2315_PCI + 0x0908) ++ ++ ++/* ++ * Local Bus Interface Registers ++ */ ++#define AR2315_LB_CONFIG (AR2315_LOCAL + 0x0000) ++#define AR2315_LBCONF_OE 0x00000001 /* =1 OE is low-true */ ++#define AR2315_LBCONF_CS0 0x00000002 /* =1 first CS is low-true */ ++#define AR2315_LBCONF_CS1 0x00000004 /* =1 2nd CS is low-true */ ++#define AR2315_LBCONF_RDY 0x00000008 /* =1 RDY is low-true */ ++#define AR2315_LBCONF_WE 0x00000010 /* =1 Write En is low-true */ ++#define AR2315_LBCONF_WAIT 0x00000020 /* =1 WAIT is low-true */ ++#define AR2315_LBCONF_ADS 0x00000040 /* =1 Adr Strobe is low-true */ ++#define AR2315_LBCONF_MOT 0x00000080 /* =0 Intel, =1 Motorola */ ++#define AR2315_LBCONF_8CS 0x00000100 /* =1 8 bits CS, 0= 16bits */ ++#define AR2315_LBCONF_8DS 0x00000200 /* =1 8 bits Data S, 0=16bits */ ++#define AR2315_LBCONF_ADS_EN 0x00000400 /* =1 Enable ADS */ ++#define AR2315_LBCONF_ADR_OE 0x00000800 /* =1 Adr cap on OE, WE or DS */ ++#define AR2315_LBCONF_ADDT_MUX 0x00001000 /* =1 Adr and Data share bus */ ++#define AR2315_LBCONF_DATA_OE 0x00002000 /* =1 Data cap on OE, WE, DS */ ++#define AR2315_LBCONF_16DATA 0x00004000 /* =1 Data is 16 bits wide */ ++#define AR2315_LBCONF_SWAPDT 0x00008000 /* =1 Byte swap data */ ++#define AR2315_LBCONF_SYNC 0x00010000 /* =1 Bus synchronous to clk */ ++#define AR2315_LBCONF_INT 0x00020000 /* =1 Intr is low true */ ++#define AR2315_LBCONF_INT_CTR0 0x00000000 /* GND high-Z, Vdd is high-Z */ ++#define AR2315_LBCONF_INT_CTR1 0x00040000 /* GND drive, Vdd is high-Z */ ++#define AR2315_LBCONF_INT_CTR2 0x00080000 /* GND high-Z, Vdd drive */ ++#define AR2315_LBCONF_INT_CTR3 0x000C0000 /* GND drive, Vdd drive */ ++#define AR2315_LBCONF_RDY_WAIT 0x00100000 /* =1 RDY is negative of WAIT */ ++#define AR2315_LBCONF_INT_PULSE 0x00200000 /* =1 Interrupt is a pulse */ ++#define AR2315_LBCONF_ENABLE 0x00400000 /* =1 Falcon respond to LB */ ++ ++#define AR2315_LB_CLKSEL (AR2315_LOCAL + 0x0004) ++#define AR2315_LBCLK_EXT 0x0001 /* use external clk for lb */ ++ ++#define AR2315_LB_1MS (AR2315_LOCAL + 0x0008) ++#define AR2315_LB1MS_MASK 0x3FFFF /* # of AHB clk cycles in 1ms */ ++ ++#define AR2315_LB_MISCCFG (AR2315_LOCAL + 0x000C) ++#define AR2315_LBM_TXD_EN 0x00000001 /* Enable TXD for fragments */ ++#define AR2315_LBM_RX_INTEN 0x00000002 /* Enable LB ints on RX ready */ ++#define AR2315_LBM_MBOXWR_INTEN 0x00000004 /* Enable LB ints on mbox wr */ ++#define AR2315_LBM_MBOXRD_INTEN 0x00000008 /* Enable LB ints on mbox rd */ ++#define AR2315_LMB_DESCSWAP_EN 0x00000010 /* Byte swap desc enable */ ++#define AR2315_LBM_TIMEOUT_MASK 0x00FFFF80 ++#define AR2315_LBM_TIMEOUT_SHFT 7 ++#define AR2315_LBM_PORTMUX 0x07000000 ++ ++ ++#define AR2315_LB_RXTSOFF (AR2315_LOCAL + 0x0010) ++ ++#define AR2315_LB_TX_CHAIN_EN (AR2315_LOCAL + 0x0100) ++#define AR2315_LB_TXEN_0 0x01 ++#define AR2315_LB_TXEN_1 0x02 ++#define AR2315_LB_TXEN_2 0x04 ++#define AR2315_LB_TXEN_3 0x08 ++ ++#define AR2315_LB_TX_CHAIN_DIS (AR2315_LOCAL + 0x0104) ++#define AR2315_LB_TX_DESC_PTR (AR2315_LOCAL + 0x0200) ++ ++#define AR2315_LB_RX_CHAIN_EN (AR2315_LOCAL + 0x0400) ++#define AR2315_LB_RXEN 0x01 ++ ++#define AR2315_LB_RX_CHAIN_DIS (AR2315_LOCAL + 0x0404) ++#define AR2315_LB_RX_DESC_PTR (AR2315_LOCAL + 0x0408) ++ ++#define AR2315_LB_INT_STATUS (AR2315_LOCAL + 0x0500) ++#define AR2315_INT_TX_DESC 0x0001 ++#define AR2315_INT_TX_OK 0x0002 ++#define AR2315_INT_TX_ERR 0x0004 ++#define AR2315_INT_TX_EOF 0x0008 ++#define AR2315_INT_RX_DESC 0x0010 ++#define AR2315_INT_RX_OK 0x0020 ++#define AR2315_INT_RX_ERR 0x0040 ++#define AR2315_INT_RX_EOF 0x0080 ++#define AR2315_INT_TX_TRUNC 0x0100 ++#define AR2315_INT_TX_STARVE 0x0200 ++#define AR2315_INT_LB_TIMEOUT 0x0400 ++#define AR2315_INT_LB_ERR 0x0800 ++#define AR2315_INT_MBOX_WR 0x1000 ++#define AR2315_INT_MBOX_RD 0x2000 ++ ++/* Bit definitions for INT MASK are the same as INT_STATUS */ ++#define AR2315_LB_INT_MASK (AR2315_LOCAL + 0x0504) ++ ++#define AR2315_LB_INT_EN (AR2315_LOCAL + 0x0508) ++#define AR2315_LB_MBOX (AR2315_LOCAL + 0x0600) ++ ++/* ++ * IR Interface Registers ++ */ ++#define AR2315_IR_PKTDATA (AR2315_IR + 0x0000) ++ ++#define AR2315_IR_PKTLEN (AR2315_IR + 0x07fc) /* 0 - 63 */ ++ ++#define AR2315_IR_CONTROL (AR2315_IR + 0x0800) ++#define AR2315_IRCTL_TX 0x00000000 /* use as tranmitter */ ++#define AR2315_IRCTL_RX 0x00000001 /* use as receiver */ ++#define AR2315_IRCTL_SAMPLECLK_MASK 0x00003ffe /* Sample clk divisor mask */ ++#define AR2315_IRCTL_SAMPLECLK_SHFT 1 ++#define AR2315_IRCTL_OUTPUTCLK_MASK 0x03ffc000 /* Output clk divisor mask */ ++#define AR2315_IRCTL_OUTPUTCLK_SHFT 14 ++ ++#define AR2315_IR_STATUS (AR2315_IR + 0x0804) ++#define AR2315_IRSTS_RX 0x00000001 /* receive in progress */ ++#define AR2315_IRSTS_TX 0x00000002 /* transmit in progress */ ++ ++#define AR2315_IR_CONFIG (AR2315_IR + 0x0808) ++#define AR2315_IRCFG_INVIN 0x00000001 /* invert input polarity */ ++#define AR2315_IRCFG_INVOUT 0x00000002 /* invert output polarity */ ++#define AR2315_IRCFG_SEQ_START_WIN_SEL 0x00000004 /* 1 => 28, 0 => 7 */ ++#define AR2315_IRCFG_SEQ_START_THRESH 0x000000f0 /* */ ++#define AR2315_IRCFG_SEQ_END_UNIT_SEL 0x00000100 /* */ ++#define AR2315_IRCFG_SEQ_END_UNIT_THRESH 0x00007e00 /* */ ++#define AR2315_IRCFG_SEQ_END_WIN_SEL 0x00008000 /* */ ++#define AR2315_IRCFG_SEQ_END_WIN_THRESH 0x001f0000 /* */ ++#define AR2315_IRCFG_NUM_BACKOFF_WORDS 0x01e00000 /* */ ++ ++#define HOST_PCI_DEV_ID 3 ++#define HOST_PCI_MBAR0 0x10000000 ++#define HOST_PCI_MBAR1 0x20000000 ++#define HOST_PCI_MBAR2 0x30000000 ++ ++#define HOST_PCI_SDRAM_BASEADDR HOST_PCI_MBAR1 ++#define PCI_DEVICE_MEM_SPACE 0x800000 ++ ++#endif /* __AR2315_REG_H */ +diff -Nur linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/ar2315_spiflash.h linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/ar2315_spiflash.h +--- linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/ar2315_spiflash.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/ar2315_spiflash.h 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,116 @@ ++/* ++ * SPI Flash Memory support header file. ++ * ++ * Copyright (c) 2005, Atheros Communications Inc. ++ * Copyright (C) 2006 FON Technology, SL. ++ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> ++ * ++ * This code is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++#ifndef __AR2315_SPIFLASH_H ++#define __AR2315_SPIFLASH_H ++ ++#define STM_PAGE_SIZE 256 ++ ++#define SFI_WRITE_BUFFER_SIZE 4 ++#define SFI_FLASH_ADDR_MASK 0x00ffffff ++ ++#define STM_8MBIT_SIGNATURE 0x13 ++#define STM_M25P80_BYTE_COUNT 1048576 ++#define STM_M25P80_SECTOR_COUNT 16 ++#define STM_M25P80_SECTOR_SIZE 0x10000 ++ ++#define STM_16MBIT_SIGNATURE 0x14 ++#define STM_M25P16_BYTE_COUNT 2097152 ++#define STM_M25P16_SECTOR_COUNT 32 ++#define STM_M25P16_SECTOR_SIZE 0x10000 ++ ++#define STM_32MBIT_SIGNATURE 0x15 ++#define STM_M25P32_BYTE_COUNT 4194304 ++#define STM_M25P32_SECTOR_COUNT 64 ++#define STM_M25P32_SECTOR_SIZE 0x10000 ++ ++#define STM_64MBIT_SIGNATURE 0x16 ++#define STM_M25P64_BYTE_COUNT 8388608 ++#define STM_M25P64_SECTOR_COUNT 128 ++#define STM_M25P64_SECTOR_SIZE 0x10000 ++ ++#define STM_128MBIT_SIGNATURE 0x17 ++#define STM_M25P128_BYTE_COUNT 16777216 ++#define STM_M25P128_SECTOR_COUNT 256 ++#define STM_M25P128_SECTOR_SIZE 0x10000 ++ ++#define STM_1MB_BYTE_COUNT STM_M25P80_BYTE_COUNT ++#define STM_1MB_SECTOR_COUNT STM_M25P80_SECTOR_COUNT ++#define STM_1MB_SECTOR_SIZE STM_M25P80_SECTOR_SIZE ++#define STM_2MB_BYTE_COUNT STM_M25P16_BYTE_COUNT ++#define STM_2MB_SECTOR_COUNT STM_M25P16_SECTOR_COUNT ++#define STM_2MB_SECTOR_SIZE STM_M25P16_SECTOR_SIZE ++#define STM_4MB_BYTE_COUNT STM_M25P32_BYTE_COUNT ++#define STM_4MB_SECTOR_COUNT STM_M25P32_SECTOR_COUNT ++#define STM_4MB_SECTOR_SIZE STM_M25P32_SECTOR_SIZE ++#define STM_8MB_BYTE_COUNT STM_M25P64_BYTE_COUNT ++#define STM_8MB_SECTOR_COUNT STM_M25P64_SECTOR_COUNT ++#define STM_8MB_SECTOR_SIZE STM_M25P64_SECTOR_SIZE ++#define STM_16MB_BYTE_COUNT STM_M25P128_BYTE_COUNT ++#define STM_16MB_SECTOR_COUNT STM_M25P128_SECTOR_COUNT ++#define STM_16MB_SECTOR_SIZE STM_M25P128_SECTOR_SIZE ++ ++/* ++ * ST Microelectronics Opcodes for Serial Flash ++ */ ++ ++#define STM_OP_WR_ENABLE 0x06 /* Write Enable */ ++#define STM_OP_WR_DISABLE 0x04 /* Write Disable */ ++#define STM_OP_RD_STATUS 0x05 /* Read Status */ ++#define STM_OP_WR_STATUS 0x01 /* Write Status */ ++#define STM_OP_RD_DATA 0x03 /* Read Data */ ++#define STM_OP_FAST_RD_DATA 0x0b /* Fast Read Data */ ++#define STM_OP_PAGE_PGRM 0x02 /* Page Program */ ++#define STM_OP_SECTOR_ERASE 0xd8 /* Sector Erase */ ++#define STM_OP_BULK_ERASE 0xc7 /* Bulk Erase */ ++#define STM_OP_DEEP_PWRDOWN 0xb9 /* Deep Power-Down Mode */ ++#define STM_OP_RD_SIG 0xab /* Read Electronic Signature */ ++ ++#define STM_STATUS_WIP 0x01 /* Write-In-Progress */ ++#define STM_STATUS_WEL 0x02 /* Write Enable Latch */ ++#define STM_STATUS_BP0 0x04 /* Block Protect 0 */ ++#define STM_STATUS_BP1 0x08 /* Block Protect 1 */ ++#define STM_STATUS_BP2 0x10 /* Block Protect 2 */ ++#define STM_STATUS_SRWD 0x80 /* Status Register Write Disable */ ++ ++/* ++ * SPI Flash Interface Registers ++ */ ++#define AR531XPLUS_SPI_READ 0x08000000 ++#define AR531XPLUS_SPI_MMR 0x11300000 ++#define AR531XPLUS_SPI_MMR_SIZE 12 ++ ++#define AR531XPLUS_SPI_CTL 0x00 ++#define AR531XPLUS_SPI_OPCODE 0x04 ++#define AR531XPLUS_SPI_DATA 0x08 ++ ++#define SPI_FLASH_READ AR531XPLUS_SPI_READ ++#define SPI_FLASH_MMR AR531XPLUS_SPI_MMR ++#define SPI_FLASH_MMR_SIZE AR531XPLUS_SPI_MMR_SIZE ++#define SPI_FLASH_CTL AR531XPLUS_SPI_CTL ++#define SPI_FLASH_OPCODE AR531XPLUS_SPI_OPCODE ++#define SPI_FLASH_DATA AR531XPLUS_SPI_DATA ++ ++#define SPI_CTL_START 0x00000100 ++#define SPI_CTL_BUSY 0x00010000 ++#define SPI_CTL_TXCNT_MASK 0x0000000f ++#define SPI_CTL_RXCNT_MASK 0x000000f0 ++#define SPI_CTL_TX_RX_CNT_MASK 0x000000ff ++#define SPI_CTL_SIZE_MASK 0x00060000 ++ ++#define SPI_CTL_CLK_SEL_MASK 0x03000000 ++#define SPI_OPCODE_MASK 0x000000ff ++ ++#define SPI_STATUS_WIP STM_STATUS_WIP ++ ++#endif +diff -Nur linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/ar231x.h linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/ar231x.h +--- linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/ar231x.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/ar231x.h 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,54 @@ ++#ifndef __AR531X_H ++#define __AR531X_H ++ ++#define AR531X_MISC_IRQ_BASE 0x20 ++#define AR531X_GPIO_IRQ_BASE 0x30 ++ ++/* Software's idea of interrupts handled by "CPU Interrupt Controller" */ ++#define AR531X_IRQ_NONE MIPS_CPU_IRQ_BASE+0 ++#define AR531X_IRQ_CPU_CLOCK MIPS_CPU_IRQ_BASE+7 /* C0_CAUSE: 0x8000 */ ++ ++/* Miscellaneous interrupts, which share IP6 */ ++#define AR531X_MISC_IRQ_NONE AR531X_MISC_IRQ_BASE+0 ++#define AR531X_MISC_IRQ_TIMER AR531X_MISC_IRQ_BASE+1 ++#define AR531X_MISC_IRQ_AHB_PROC AR531X_MISC_IRQ_BASE+2 ++#define AR531X_MISC_IRQ_AHB_DMA AR531X_MISC_IRQ_BASE+3 ++#define AR531X_MISC_IRQ_GPIO AR531X_MISC_IRQ_BASE+4 ++#define AR531X_MISC_IRQ_UART0 AR531X_MISC_IRQ_BASE+5 ++#define AR531X_MISC_IRQ_UART0_DMA AR531X_MISC_IRQ_BASE+6 ++#define AR531X_MISC_IRQ_WATCHDOG AR531X_MISC_IRQ_BASE+7 ++#define AR531X_MISC_IRQ_LOCAL AR531X_MISC_IRQ_BASE+8 ++#define AR531X_MISC_IRQ_SPI AR531X_MISC_IRQ_BASE+9 ++#define AR531X_MISC_IRQ_COUNT 10 ++ ++/* GPIO Interrupts [0..7], share AR531X_MISC_IRQ_GPIO */ ++#define AR531X_GPIO_IRQ_NONE AR531X_GPIO_IRQ_BASE+0 ++#define AR531X_GPIO_IRQ(n) AR531X_GPIO_IRQ_BASE+n ++#define AR531X_GPIO_IRQ_COUNT 22 ++ ++static inline u32 ++ar231x_read_reg(u32 reg) ++{ ++ return __raw_readl((u32 *) KSEG1ADDR(reg)); ++} ++ ++static inline void ++ar231x_write_reg(u32 reg, u32 val) ++{ ++ __raw_writel(val, (u32 *) KSEG1ADDR(reg)); ++} ++ ++static inline u32 ++ar231x_mask_reg(u32 reg, u32 mask, u32 val) ++{ ++ u32 ret; ++ ++ ret = ar231x_read_reg(reg); ++ ret &= ~mask; ++ ret |= val; ++ ar231x_write_reg(reg, ret); ++ ++ return ret; ++} ++ ++#endif +diff -Nur linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/ar231x_platform.h linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/ar231x_platform.h +--- linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/ar231x_platform.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/ar231x_platform.h 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,83 @@ ++#ifndef __AR531X_PLATFORM_H ++#define __AR531X_PLATFORM_H ++ ++/* ++ * This is board-specific data that is stored in a "fixed" location in flash. ++ * It is shared across operating systems, so it should not be changed lightly. ++ * The main reason we need it is in order to extract the ethernet MAC ++ * address(es). ++ */ ++struct ar231x_boarddata { ++ u32 magic; /* board data is valid */ ++#define AR531X_BD_MAGIC 0x35333131 /* "5311", for all 531x platforms */ ++ u16 cksum; /* checksum (starting with BD_REV 2) */ ++ u16 rev; /* revision of this struct */ ++#define BD_REV 4 ++ char boardName[64]; /* Name of board */ ++ u16 major; /* Board major number */ ++ u16 minor; /* Board minor number */ ++ u32 flags; /* Board configuration */ ++#define BD_ENET0 0x00000001 /* ENET0 is stuffed */ ++#define BD_ENET1 0x00000002 /* ENET1 is stuffed */ ++#define BD_UART1 0x00000004 /* UART1 is stuffed */ ++#define BD_UART0 0x00000008 /* UART0 is stuffed (dma) */ ++#define BD_RSTFACTORY 0x00000010 /* Reset factory defaults stuffed */ ++#define BD_SYSLED 0x00000020 /* System LED stuffed */ ++#define BD_EXTUARTCLK 0x00000040 /* External UART clock */ ++#define BD_CPUFREQ 0x00000080 /* cpu freq is valid in nvram */ ++#define BD_SYSFREQ 0x00000100 /* sys freq is set in nvram */ ++#define BD_WLAN0 0x00000200 /* Enable WLAN0 */ ++#define BD_MEMCAP 0x00000400 /* CAP SDRAM @ memCap for testing */ ++#define BD_DISWATCHDOG 0x00000800 /* disable system watchdog */ ++#define BD_WLAN1 0x00001000 /* Enable WLAN1 (ar5212) */ ++#define BD_ISCASPER 0x00002000 /* FLAG for AR2312 */ ++#define BD_WLAN0_2G_EN 0x00004000 /* FLAG for radio0_2G */ ++#define BD_WLAN0_5G_EN 0x00008000 /* FLAG for radio0_2G */ ++#define BD_WLAN1_2G_EN 0x00020000 /* FLAG for radio0_2G */ ++#define BD_WLAN1_5G_EN 0x00040000 /* FLAG for radio0_2G */ ++ u16 resetConfigGpio; /* Reset factory GPIO pin */ ++ u16 sysLedGpio; /* System LED GPIO pin */ ++ ++ u32 cpuFreq; /* CPU core frequency in Hz */ ++ u32 sysFreq; /* System frequency in Hz */ ++ u32 cntFreq; /* Calculated C0_COUNT frequency */ ++ ++ u8 wlan0_mac[6]; ++ u8 enet0_mac[6]; ++ u8 enet1_mac[6]; ++ ++ u16 pciId; /* Pseudo PCIID for common code */ ++ u16 memCap; /* cap bank1 in MB */ ++ ++ /* version 3 */ ++ u8 wlan1_mac[6]; /* (ar5212) */ ++}; ++ ++#define BOARD_CONFIG_BUFSZ 0x1000 ++ ++/* ++ * Platform device information for the Wireless MAC ++ */ ++struct ar231x_board_config { ++ u16 devid; ++ ++ /* board config data */ ++ struct ar231x_boarddata *config; ++ ++ /* radio calibration data */ ++ const char *radio; ++}; ++ ++/* ++ * Platform device information for the Ethernet MAC ++ */ ++struct ar231x_eth { ++ u32 reset_base; ++ u32 reset_mac; ++ u32 reset_phy; ++ u32 phy_base; ++ struct ar231x_board_config *config; ++ char *macaddr; ++}; ++ ++#endif /* __AR531X_PLATFORM_H */ +diff -Nur linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/ar5312_regs.h linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/ar5312_regs.h +--- linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/ar5312_regs.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/ar5312_regs.h 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,236 @@ ++/* ++ * 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) 2003 Atheros Communications, Inc., All Rights Reserved. ++ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org> ++ */ ++ ++#ifndef AR5312_H ++#define AR5312_H ++ ++#include <asm/addrspace.h> ++ ++/* ++ * IRQs ++ */ ++ ++#define AR5312_IRQ_WLAN0_INTRS MIPS_CPU_IRQ_BASE+2 /* C0_CAUSE: 0x0400 */ ++#define AR5312_IRQ_ENET0_INTRS MIPS_CPU_IRQ_BASE+3 /* C0_CAUSE: 0x0800 */ ++#define AR5312_IRQ_ENET1_INTRS MIPS_CPU_IRQ_BASE+4 /* C0_CAUSE: 0x1000 */ ++#define AR5312_IRQ_WLAN1_INTRS MIPS_CPU_IRQ_BASE+5 /* C0_CAUSE: 0x2000 */ ++#define AR5312_IRQ_MISC_INTRS MIPS_CPU_IRQ_BASE+6 /* C0_CAUSE: 0x4000 */ ++ ++ ++/* Address Map */ ++#define AR531X_WLAN0 0x18000000 ++#define AR531X_WLAN1 0x18500000 ++#define AR531X_ENET0 0x18100000 ++#define AR531X_ENET1 0x18200000 ++#define AR531X_SDRAMCTL 0x18300000 ++#define AR531X_FLASHCTL 0x18400000 ++#define AR531X_APBBASE 0x1c000000 ++#define AR531X_FLASH 0x1e000000 ++#define AR531X_UART0 0xbc000003 /* UART MMR */ ++ ++/* ++ * AR531X_NUM_ENET_MAC defines the number of ethernet MACs that ++ * should be considered available. The AR5312 supports 2 enet MACS, ++ * even though many reference boards only actually use 1 of them ++ * (i.e. Only MAC 0 is actually connected to an enet PHY or PHY switch. ++ * The AR2312 supports 1 enet MAC. ++ */ ++#define AR531X_NUM_ENET_MAC 2 ++ ++/* ++ * Need these defines to determine true number of ethernet MACs ++ */ ++#define AR5212_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */ ++#define AR5212_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */ ++#define AR5212_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */ ++#define AR531X_RADIO_MASK_OFF 0xc8 ++#define AR531X_RADIO0_MASK 0x0003 ++#define AR531X_RADIO1_MASK 0x000c ++#define AR531X_RADIO1_S 2 ++ ++/* ++ * AR531X_NUM_WMAC defines the number of Wireless MACs that\ ++ * should be considered available. ++ */ ++#define AR531X_NUM_WMAC 2 ++ ++/* Reset/Timer Block Address Map */ ++#define AR531X_RESETTMR (AR531X_APBBASE + 0x3000) ++#define AR531X_TIMER (AR531X_RESETTMR + 0x0000) /* countdown timer */ ++#define AR531X_WD_CTRL (AR531X_RESETTMR + 0x0008) /* watchdog cntrl */ ++#define AR531X_WD_TIMER (AR531X_RESETTMR + 0x000c) /* watchdog timer */ ++#define AR531X_ISR (AR531X_RESETTMR + 0x0010) /* Intr Status Reg */ ++#define AR531X_IMR (AR531X_RESETTMR + 0x0014) /* Intr Mask Reg */ ++#define AR531X_RESET (AR531X_RESETTMR + 0x0020) ++#define AR5312_CLOCKCTL1 (AR531X_RESETTMR + 0x0064) ++#define AR5312_SCRATCH (AR531X_RESETTMR + 0x006c) ++#define AR531X_PROCADDR (AR531X_RESETTMR + 0x0070) ++#define AR531X_PROC1 (AR531X_RESETTMR + 0x0074) ++#define AR531X_DMAADDR (AR531X_RESETTMR + 0x0078) ++#define AR531X_DMA1 (AR531X_RESETTMR + 0x007c) ++#define AR531X_ENABLE (AR531X_RESETTMR + 0x0080) /* interface enb */ ++#define AR531X_REV (AR531X_RESETTMR + 0x0090) /* revision */ ++ ++/* AR531X_WD_CTRL register bit field definitions */ ++#define AR531X_WD_CTRL_IGNORE_EXPIRATION 0x0000 ++#define AR531X_WD_CTRL_NMI 0x0001 ++#define AR531X_WD_CTRL_RESET 0x0002 ++ ++/* AR531X_ISR register bit field definitions */ ++#define AR531X_ISR_NONE 0x0000 ++#define AR531X_ISR_TIMER 0x0001 ++#define AR531X_ISR_AHBPROC 0x0002 ++#define AR531X_ISR_AHBDMA 0x0004 ++#define AR531X_ISR_GPIO 0x0008 ++#define AR531X_ISR_UART0 0x0010 ++#define AR531X_ISR_UART0DMA 0x0020 ++#define AR531X_ISR_WD 0x0040 ++#define AR531X_ISR_LOCAL 0x0080 ++ ++/* AR531X_RESET register bit field definitions */ ++#define AR531X_RESET_SYSTEM 0x00000001 /* cold reset full system */ ++#define AR531X_RESET_PROC 0x00000002 /* cold reset MIPS core */ ++#define AR531X_RESET_WLAN0 0x00000004 /* cold reset WLAN MAC and BB */ ++#define AR531X_RESET_EPHY0 0x00000008 /* cold reset ENET0 phy */ ++#define AR531X_RESET_EPHY1 0x00000010 /* cold reset ENET1 phy */ ++#define AR531X_RESET_ENET0 0x00000020 /* cold reset ENET0 mac */ ++#define AR531X_RESET_ENET1 0x00000040 /* cold reset ENET1 mac */ ++#define AR531X_RESET_UART0 0x00000100 /* cold reset UART0 (high speed) */ ++#define AR531X_RESET_WLAN1 0x00000200 /* cold reset WLAN MAC/BB */ ++#define AR531X_RESET_APB 0x00000400 /* cold reset APB (ar5312) */ ++#define AR531X_RESET_WARM_PROC 0x00001000 /* warm reset MIPS core */ ++#define AR531X_RESET_WARM_WLAN0_MAC 0x00002000 /* warm reset WLAN0 MAC */ ++#define AR531X_RESET_WARM_WLAN0_BB 0x00004000 /* warm reset WLAN0 BaseBand */ ++#define AR531X_RESET_NMI 0x00010000 /* send an NMI to the processor */ ++#define AR531X_RESET_WARM_WLAN1_MAC 0x00020000 /* warm reset WLAN1 mac */ ++#define AR531X_RESET_WARM_WLAN1_BB 0x00040000 /* warm reset WLAN1 baseband */ ++#define AR531X_RESET_LOCAL_BUS 0x00080000 /* reset local bus */ ++#define AR531X_RESET_WDOG 0x00100000 /* last reset was a watchdog */ ++ ++#define AR531X_RESET_WMAC0_BITS \ ++ AR531X_RESET_WLAN0 |\ ++ AR531X_RESET_WARM_WLAN0_MAC |\ ++ AR531X_RESET_WARM_WLAN0_BB ++ ++#define AR531X_RESERT_WMAC1_BITS \ ++ AR531X_RESET_WLAN1 |\ ++ AR531X_RESET_WARM_WLAN1_MAC |\ ++ AR531X_RESET_WARM_WLAN1_BB ++ ++/* AR5312_CLOCKCTL1 register bit field definitions */ ++#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030 ++#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4 ++#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00 ++#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8 ++#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000 ++ ++/* Valid for AR5312 and AR2312 */ ++#define AR5312_CLOCKCTL1_PREDIVIDE_MASK 0x00000030 ++#define AR5312_CLOCKCTL1_PREDIVIDE_SHIFT 4 ++#define AR5312_CLOCKCTL1_MULTIPLIER_MASK 0x00001f00 ++#define AR5312_CLOCKCTL1_MULTIPLIER_SHIFT 8 ++#define AR5312_CLOCKCTL1_DOUBLER_MASK 0x00010000 ++ ++/* Valid for AR2313 */ ++#define AR2313_CLOCKCTL1_PREDIVIDE_MASK 0x00003000 ++#define AR2313_CLOCKCTL1_PREDIVIDE_SHIFT 12 ++#define AR2313_CLOCKCTL1_MULTIPLIER_MASK 0x001f0000 ++#define AR2313_CLOCKCTL1_MULTIPLIER_SHIFT 16 ++#define AR2313_CLOCKCTL1_DOUBLER_MASK 0x00000000 ++ ++ ++/* AR531X_ENABLE register bit field definitions */ ++#define AR531X_ENABLE_WLAN0 0x0001 ++#define AR531X_ENABLE_ENET0 0x0002 ++#define AR531X_ENABLE_ENET1 0x0004 ++#define AR531X_ENABLE_UART_AND_WLAN1_PIO 0x0008 /* UART, and WLAN1 PIOs */ ++#define AR531X_ENABLE_WLAN1_DMA 0x0010 /* WLAN1 DMAs */ ++#define AR531X_ENABLE_WLAN1 \ ++ (AR531X_ENABLE_UART_AND_WLAN1_PIO | AR531X_ENABLE_WLAN1_DMA) ++ ++/* AR531X_REV register bit field definitions */ ++#define AR531X_REV_WMAC_MAJ 0xf000 ++#define AR531X_REV_WMAC_MAJ_S 12 ++#define AR531X_REV_WMAC_MIN 0x0f00 ++#define AR531X_REV_WMAC_MIN_S 8 ++#define AR531X_REV_MAJ 0x00f0 ++#define AR531X_REV_MAJ_S 4 ++#define AR531X_REV_MIN 0x000f ++#define AR531X_REV_MIN_S 0 ++#define AR531X_REV_CHIP (AR531X_REV_MAJ|AR531X_REV_MIN) ++ ++/* Major revision numbers, bits 7..4 of Revision ID register */ ++#define AR531X_REV_MAJ_AR5312 0x4 ++#define AR531X_REV_MAJ_AR2313 0x5 ++ ++/* Minor revision numbers, bits 3..0 of Revision ID register */ ++#define AR5312_REV_MIN_DUAL 0x0 /* Dual WLAN version */ ++#define AR5312_REV_MIN_SINGLE 0x1 /* Single WLAN version */ ++ ++/* AR531X_FLASHCTL register bit field definitions */ ++#define FLASHCTL_IDCY 0x0000000f /* Idle cycle turn around time */ ++#define FLASHCTL_IDCY_S 0 ++#define FLASHCTL_WST1 0x000003e0 /* Wait state 1 */ ++#define FLASHCTL_WST1_S 5 ++#define FLASHCTL_RBLE 0x00000400 /* Read byte lane enable */ ++#define FLASHCTL_WST2 0x0000f800 /* Wait state 2 */ ++#define FLASHCTL_WST2_S 11 ++#define FLASHCTL_AC 0x00070000 /* Flash address check (added) */ ++#define FLASHCTL_AC_S 16 ++#define FLASHCTL_AC_128K 0x00000000 ++#define FLASHCTL_AC_256K 0x00010000 ++#define FLASHCTL_AC_512K 0x00020000 ++#define FLASHCTL_AC_1M 0x00030000 ++#define FLASHCTL_AC_2M 0x00040000 ++#define FLASHCTL_AC_4M 0x00050000 ++#define FLASHCTL_AC_8M 0x00060000 ++#define FLASHCTL_AC_RES 0x00070000 /* 16MB is not supported */ ++#define FLASHCTL_E 0x00080000 /* Flash bank enable (added) */ ++#define FLASHCTL_BUSERR 0x01000000 /* Bus transfer error status flag */ ++#define FLASHCTL_WPERR 0x02000000 /* Write protect error status flag */ ++#define FLASHCTL_WP 0x04000000 /* Write protect */ ++#define FLASHCTL_BM 0x08000000 /* Burst mode */ ++#define FLASHCTL_MW 0x30000000 /* Memory width */ ++#define FLASHCTL_MWx8 0x00000000 /* Memory width x8 */ ++#define FLASHCTL_MWx16 0x10000000 /* Memory width x16 */ ++#define FLASHCTL_MWx32 0x20000000 /* Memory width x32 (not supported) */ ++#define FLASHCTL_ATNR 0x00000000 /* Access type == no retry */ ++#define FLASHCTL_ATR 0x80000000 /* Access type == retry every */ ++#define FLASHCTL_ATR4 0xc0000000 /* Access type == retry every 4 */ ++ ++/* ARM Flash Controller -- 3 flash banks with either x8 or x16 devices. */ ++#define AR531X_FLASHCTL0 (AR531X_FLASHCTL + 0x00) ++#define AR531X_FLASHCTL1 (AR531X_FLASHCTL + 0x04) ++#define AR531X_FLASHCTL2 (AR531X_FLASHCTL + 0x08) ++ ++/* ARM SDRAM Controller -- just enough to determine memory size */ ++#define AR531X_MEM_CFG1 (AR531X_SDRAMCTL + 0x04) ++#define MEM_CFG1_AC0 0x00000700 /* bank 0: SDRAM addr check (added) */ ++#define MEM_CFG1_AC0_S 8 ++#define MEM_CFG1_AC1 0x00007000 /* bank 1: SDRAM addr check (added) */ ++#define MEM_CFG1_AC1_S 12 ++ ++/* GPIO Address Map */ ++#define AR531X_GPIO (AR531X_APBBASE + 0x2000) ++#define AR531X_GPIO_DO (AR531X_GPIO + 0x00) /* output register */ ++#define AR531X_GPIO_DI (AR531X_GPIO + 0x04) /* intput register */ ++#define AR531X_GPIO_CR (AR531X_GPIO + 0x08) /* control register */ ++ ++/* GPIO Control Register bit field definitions */ ++#define AR531X_GPIO_CR_M(x) (1 << (x)) /* mask for i/o */ ++#define AR531X_GPIO_CR_O(x) (0 << (x)) /* mask for output */ ++#define AR531X_GPIO_CR_I(x) (1 << (x)) /* mask for input */ ++#define AR531X_GPIO_CR_INT(x) (1 << ((x)+8)) /* mask for interrupt */ ++#define AR531X_GPIO_CR_UART(x) (1 << ((x)+16)) /* uart multiplex */ ++#define AR531X_NUM_GPIO 8 ++ ++ ++#endif ++ +diff -Nur linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/cpu-feature-overrides.h linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/cpu-feature-overrides.h +--- linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/cpu-feature-overrides.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/cpu-feature-overrides.h 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,84 @@ ++/* ++ * Atheros SoC specific CPU feature overrides ++ * ++ * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This file was derived from: include/asm-mips/cpu-features.h ++ * Copyright (C) 2003, 2004 Ralf Baechle ++ * Copyright (C) 2004 Maciej W. Rozycki ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++#ifndef __ASM_MACH_ATHEROS_CPU_FEATURE_OVERRIDES_H ++#define __ASM_MACH_ATHEROS_CPU_FEATURE_OVERRIDES_H ++ ++/* ++ * The ATHEROS SoCs have MIPS 4Kc/4KEc core. ++ */ ++#define cpu_has_tlb 1 ++#define cpu_has_4kex 1 ++#define cpu_has_3k_cache 0 ++#define cpu_has_4k_cache 1 ++#define cpu_has_tx39_cache 0 ++#define cpu_has_sb1_cache 0 ++#define cpu_has_fpu 0 ++#define cpu_has_32fpr 0 ++#define cpu_has_counter 1 ++/* #define cpu_has_watch ? */ ++/* #define cpu_has_divec ? */ ++/* #define cpu_has_vce ? */ ++/* #define cpu_has_cache_cdex_p ? */ ++/* #define cpu_has_cache_cdex_s ? */ ++/* #define cpu_has_prefetch ? */ ++/* #define cpu_has_mcheck ? */ ++#define cpu_has_ejtag 1 ++ ++#if !defined(CONFIG_ATHEROS_AR5312) ++# define cpu_has_llsc 1 ++#else ++/* ++ * The MIPS 4Kc V0.9 core in the AR5312/AR2312 have problems with the ++ * ll/sc instructions. ++ */ ++# define cpu_has_llsc 0 ++#endif ++ ++#define cpu_has_mips16 0 ++#define cpu_has_mdmx 0 ++#define cpu_has_mips3d 0 ++#define cpu_has_smartmips 0 ++ ++/* #define cpu_has_vtag_icache ? */ ++/* #define cpu_has_dc_aliases ? */ ++/* #define cpu_has_ic_fills_f_dc ? */ ++/* #define cpu_has_pindexed_dcache ? */ ++ ++/* #define cpu_icache_snoops_remote_store ? */ ++ ++#define cpu_has_mips32r1 1 ++ ++#if !defined(CONFIG_ATHEROS_AR5312) ++# define cpu_has_mips32r2 1 ++#endif ++ ++#define cpu_has_mips64r1 0 ++#define cpu_has_mips64r2 0 ++ ++#define cpu_has_dsp 0 ++#define cpu_has_mipsmt 0 ++ ++/* #define cpu_has_nofpuex ? */ ++#define cpu_has_64bits 0 ++#define cpu_has_64bit_zero_reg 0 ++#define cpu_has_64bit_gp_regs 0 ++#define cpu_has_64bit_addresses 0 ++ ++/* #define cpu_has_inclusive_pcaches ? */ ++ ++/* #define cpu_dcache_line_size() ? */ ++/* #define cpu_icache_line_size() ? */ ++ ++#endif /* __ASM_MACH_ATHEROS_CPU_FEATURE_OVERRIDES_H */ +diff -Nur linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/dma-coherence.h linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/dma-coherence.h +--- linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/dma-coherence.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/dma-coherence.h 2011-05-15 21:41:19.000000000 +0200 +@@ -0,0 +1,76 @@ ++/* ++ * 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) 2006 Ralf Baechle <ralf@linux-mips.org> ++ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org> ++ * ++ */ ++#ifndef __ASM_MACH_GENERIC_DMA_COHERENCE_H ++#define __ASM_MACH_GENERIC_DMA_COHERENCE_H ++ ++#define PCI_DMA_OFFSET 0x20000000 ++ ++#include <linux/device.h> ++ ++static inline dma_addr_t ar231x_dev_offset(struct device *dev) ++{ ++#ifdef CONFIG_PCI ++ extern struct bus_type pci_bus_type; ++ ++ if (dev && dev->bus == &pci_bus_type) ++ return PCI_DMA_OFFSET; ++ else ++#endif ++ return 0; ++} ++ ++static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr, size_t size) ++{ ++ return virt_to_phys(addr) + ar231x_dev_offset(dev); ++} ++ ++static inline dma_addr_t plat_map_dma_mem_page(struct device *dev, struct page *page) ++{ ++ return page_to_phys(page) + ar231x_dev_offset(dev); ++} ++ ++static inline unsigned long plat_dma_addr_to_phys(struct device *dev, ++ dma_addr_t dma_addr) ++{ ++ return dma_addr - ar231x_dev_offset(dev); ++} ++ ++static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr, ++ size_t size, enum dma_data_direction direction) ++{ ++} ++ ++static inline int plat_dma_supported(struct device *dev, u64 mask) ++{ ++ return 1; ++} ++ ++static inline void plat_extra_sync_for_device(struct device *dev) ++{ ++ return; ++} ++ ++static inline int plat_dma_mapping_error(struct device *dev, ++ dma_addr_t dma_addr) ++{ ++ return 0; ++} ++ ++static inline int plat_device_is_coherent(struct device *dev) ++{ ++#ifdef CONFIG_DMA_COHERENT ++ return 1; ++#endif ++#ifdef CONFIG_DMA_NONCOHERENT ++ return 0; ++#endif ++} ++ ++#endif /* __ASM_MACH_GENERIC_DMA_COHERENCE_H */ +diff -Nur linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/gpio.h linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/gpio.h +--- linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/gpio.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/gpio.h 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,84 @@ ++#ifndef _ATHEROS_GPIO_H_ ++#define _ATHEROS_GPIO_H_ ++ ++#include <ar231x.h> ++ ++struct ar231x_gpiodev { ++ u32 valid_mask; ++ u32 (*get_output)(void); ++ u32 (*set_output)(u32 mask, u32 val); ++ u32 (*get)(void); ++ u32 (*set)(u32 mask, u32 val); ++}; ++ ++extern const struct ar231x_gpiodev *ar231x_gpiodev; ++ ++/* ++ * Wrappers for the generic GPIO layer ++ */ ++ ++static inline int gpio_direction_input(unsigned gpio) { ++ u32 mask = 1 << gpio; ++ ++ if (!(ar231x_gpiodev->valid_mask & mask)) ++ return -ENXIO; ++ ++ ar231x_gpiodev->set_output(mask, 0); ++ return 0; ++} ++ ++static inline void gpio_set_value(unsigned gpio, int value) { ++ u32 mask = 1 << gpio; ++ ++ if (!(ar231x_gpiodev->valid_mask & mask)) ++ return; ++ ++ ar231x_gpiodev->set(mask, (!!value) * mask); ++} ++ ++static inline int gpio_direction_output(unsigned gpio, int value) { ++ u32 mask = 1 << gpio; ++ ++ if (!(ar231x_gpiodev->valid_mask & mask)) ++ return -ENXIO; ++ ++ ar231x_gpiodev->set_output(mask, mask); ++ ar231x_gpiodev->set(mask, (!!value) * mask); ++ return 0; ++} ++ ++/* Reads the gpio pin. Unchecked function */ ++static inline int gpio_get_value(unsigned gpio) { ++ u32 mask = 1 << gpio; ++ ++ if (!(ar231x_gpiodev->valid_mask & mask)) ++ return 0; ++ ++ return !!(ar231x_gpiodev->get() & mask); ++} ++ ++static inline int gpio_request(unsigned gpio, const char *label) { ++ return 0; ++} ++ ++static inline void gpio_free(unsigned gpio) { ++} ++ ++/* Returns IRQ to attach for gpio. Unchecked function */ ++static inline int gpio_to_irq(unsigned gpio) { ++ return AR531X_GPIO_IRQ(gpio); ++} ++ ++/* Returns gpio for IRQ attached. Unchecked function */ ++static inline int irq_to_gpio(unsigned irq) { ++ return (irq - (AR531X_GPIO_IRQ(0))); ++} ++ ++static inline int gpio_set_debounce(unsigned gpio, unsigned debounce) ++{ ++ return -ENOSYS; ++} ++ ++#include <asm-generic/gpio.h> /* cansleep wrappers */ ++ ++#endif +diff -Nur linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/reset.h linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/reset.h +--- linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/reset.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/reset.h 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,6 @@ ++#ifndef __AR531X_RESET_H ++#define __AR531X_RESET_H ++ ++void ar531x_disable_reset_button(void); ++ ++#endif /* __AR531X_RESET_H */ +diff -Nur linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/war.h linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/war.h +--- linux-2.6.39-rc7.orig/arch/mips/include/asm/mach-ar231x/war.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/arch/mips/include/asm/mach-ar231x/war.h 2011-05-15 21:34:57.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) 2008 Felix Fietkau <nbd@openwrt.org> ++ */ ++#ifndef __ASM_MIPS_MACH_ATHEROS_WAR_H ++#define __ASM_MIPS_MACH_ATHEROS_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_ATHEROS_WAR_H */ +diff -Nur linux-2.6.39-rc7.orig/arch/mips/kernel/cevt-r4k.c linux-2.6.39-rc7/arch/mips/kernel/cevt-r4k.c +--- linux-2.6.39-rc7.orig/arch/mips/kernel/cevt-r4k.c 2011-05-10 04:33:54.000000000 +0200 ++++ linux-2.6.39-rc7/arch/mips/kernel/cevt-r4k.c 2011-05-15 21:34:57.000000000 +0200 +@@ -168,20 +168,23 @@ + struct clock_event_device *cd; + unsigned int irq; + +- if (!cpu_has_counter || !mips_hpt_frequency) +- return -ENXIO; +- +- if (!c0_compare_int_usable()) +- return -ENXIO; +- + /* + * With vectored interrupts things are getting platform specific. + * get_c0_compare_int is a hook to allow a platform to return the + * interrupt number of it's liking. + */ + irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; +- if (get_c0_compare_int) ++ if (get_c0_compare_int) { + irq = get_c0_compare_int(); ++ if ((irq >= MIPS_CPU_IRQ_BASE) && (irq < MIPS_CPU_IRQ_BASE + 8)) ++ cp0_compare_irq = irq - MIPS_CPU_IRQ_BASE; ++ } ++ ++ if (!cpu_has_counter || !mips_hpt_frequency) ++ return -ENXIO; ++ ++ if (!c0_compare_int_usable()) ++ return -ENXIO; + + cd = &per_cpu(mips_clockevent_device, cpu); + +diff -Nur linux-2.6.39-rc7.orig/drivers/mtd/devices/Kconfig linux-2.6.39-rc7/drivers/mtd/devices/Kconfig +--- linux-2.6.39-rc7.orig/drivers/mtd/devices/Kconfig 2011-05-10 04:33:54.000000000 +0200 ++++ linux-2.6.39-rc7/drivers/mtd/devices/Kconfig 2011-05-15 21:34:57.000000000 +0200 +@@ -112,6 +112,10 @@ + Set up your spi devices with the right board-specific platform data, + if you want to specify device partitioning. + ++config MTD_AR2315 ++ tristate "Atheros AR2315+ SPI Flash support" ++ depends on ATHEROS_AR2315 ++ + config MTD_SLRAM + tristate "Uncached system RAM" + help +diff -Nur linux-2.6.39-rc7.orig/drivers/mtd/devices/Makefile linux-2.6.39-rc7/drivers/mtd/devices/Makefile +--- linux-2.6.39-rc7.orig/drivers/mtd/devices/Makefile 2011-05-10 04:33:54.000000000 +0200 ++++ linux-2.6.39-rc7/drivers/mtd/devices/Makefile 2011-05-15 21:34:57.000000000 +0200 +@@ -17,3 +17,4 @@ + obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o + obj-$(CONFIG_MTD_M25P80) += m25p80.o + obj-$(CONFIG_MTD_SST25L) += sst25l.o ++obj-$(CONFIG_MTD_AR2315) += ar2315.o +diff -Nur linux-2.6.39-rc7.orig/drivers/mtd/devices/ar2315.c linux-2.6.39-rc7/drivers/mtd/devices/ar2315.c +--- linux-2.6.39-rc7.orig/drivers/mtd/devices/ar2315.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/drivers/mtd/devices/ar2315.c 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,517 @@ ++ ++/* ++ * MTD driver for the SPI Flash Memory support on Atheros AR2315 ++ * ++ * Copyright (c) 2005-2006 Atheros Communications Inc. ++ * Copyright (C) 2006-2007 FON Technology, SL. ++ * Copyright (C) 2006-2007 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> ++ * ++ * This code is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/version.h> ++#include <linux/errno.h> ++#include <linux/slab.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <linux/platform_device.h> ++#include <linux/sched.h> ++#include <linux/root_dev.h> ++#include <linux/delay.h> ++#include <asm/delay.h> ++#include <asm/io.h> ++ ++#include <ar2315_spiflash.h> ++#include <ar231x_platform.h> ++#include <ar231x.h> ++ ++ ++#define SPIFLASH "spiflash: " ++#define busy_wait(_priv, _condition, _wait) do { \ ++ while (_condition) { \ ++ spin_unlock_bh(&_priv->lock); \ ++ if (_wait > 1) \ ++ msleep(_wait); \ ++ else if ((_wait == 1) && need_resched()) \ ++ schedule(); \ ++ else \ ++ udelay(1); \ ++ spin_lock_bh(&_priv->lock); \ ++ } \ ++} while (0) ++ ++enum { ++ FLASH_NONE, ++ FLASH_1MB, ++ FLASH_2MB, ++ FLASH_4MB, ++ FLASH_8MB, ++ FLASH_16MB, ++}; ++ ++/* Flash configuration table */ ++struct flashconfig { ++ u32 byte_cnt; ++ u32 sector_cnt; ++ u32 sector_size; ++}; ++ ++const struct flashconfig flashconfig_tbl[] = { ++ [FLASH_NONE] = { 0, 0, 0}, ++ [FLASH_1MB] = { STM_1MB_BYTE_COUNT, STM_1MB_SECTOR_COUNT, STM_1MB_SECTOR_SIZE}, ++ [FLASH_2MB] = { STM_2MB_BYTE_COUNT, STM_2MB_SECTOR_COUNT, STM_2MB_SECTOR_SIZE}, ++ [FLASH_4MB] = { STM_4MB_BYTE_COUNT, STM_4MB_SECTOR_COUNT, STM_4MB_SECTOR_SIZE}, ++ [FLASH_8MB] = { STM_8MB_BYTE_COUNT, STM_8MB_SECTOR_COUNT, STM_8MB_SECTOR_SIZE}, ++ [FLASH_16MB] = { STM_16MB_BYTE_COUNT, STM_16MB_SECTOR_COUNT, STM_16MB_SECTOR_SIZE} ++}; ++ ++/* Mapping of generic opcodes to STM serial flash opcodes */ ++enum { ++ SPI_WRITE_ENABLE, ++ SPI_WRITE_DISABLE, ++ SPI_RD_STATUS, ++ SPI_WR_STATUS, ++ SPI_RD_DATA, ++ SPI_FAST_RD_DATA, ++ SPI_PAGE_PROGRAM, ++ SPI_SECTOR_ERASE, ++ SPI_BULK_ERASE, ++ SPI_DEEP_PWRDOWN, ++ SPI_RD_SIG, ++}; ++ ++struct opcodes { ++ __u16 code; ++ __s8 tx_cnt; ++ __s8 rx_cnt; ++}; ++const struct opcodes stm_opcodes[] = { ++ [SPI_WRITE_ENABLE] = {STM_OP_WR_ENABLE, 1, 0}, ++ [SPI_WRITE_DISABLE] = {STM_OP_WR_DISABLE, 1, 0}, ++ [SPI_RD_STATUS] = {STM_OP_RD_STATUS, 1, 1}, ++ [SPI_WR_STATUS] = {STM_OP_WR_STATUS, 1, 0}, ++ [SPI_RD_DATA] = {STM_OP_RD_DATA, 4, 4}, ++ [SPI_FAST_RD_DATA] = {STM_OP_FAST_RD_DATA, 5, 0}, ++ [SPI_PAGE_PROGRAM] = {STM_OP_PAGE_PGRM, 8, 0}, ++ [SPI_SECTOR_ERASE] = {STM_OP_SECTOR_ERASE, 4, 0}, ++ [SPI_BULK_ERASE] = {STM_OP_BULK_ERASE, 1, 0}, ++ [SPI_DEEP_PWRDOWN] = {STM_OP_DEEP_PWRDOWN, 1, 0}, ++ [SPI_RD_SIG] = {STM_OP_RD_SIG, 4, 1}, ++}; ++ ++/* Driver private data structure */ ++struct spiflash_priv { ++ struct mtd_info mtd; ++ void *readaddr; /* memory mapped data for read */ ++ void *mmraddr; /* memory mapped register space */ ++ wait_queue_head_t wq; ++ spinlock_t lock; ++ int state; ++}; ++ ++#define to_spiflash(_mtd) container_of(_mtd, struct spiflash_priv, mtd) ++ ++enum { ++ FL_READY, ++ FL_READING, ++ FL_ERASING, ++ FL_WRITING ++}; ++ ++/***************************************************************************************************/ ++ ++static u32 ++spiflash_read_reg(struct spiflash_priv *priv, int reg) ++{ ++ return ar231x_read_reg((u32) priv->mmraddr + reg); ++} ++ ++static void ++spiflash_write_reg(struct spiflash_priv *priv, int reg, u32 data) ++{ ++ ar231x_write_reg((u32) priv->mmraddr + reg, data); ++} ++ ++static u32 ++spiflash_wait_busy(struct spiflash_priv *priv) ++{ ++ u32 reg; ++ ++ busy_wait(priv, (reg = spiflash_read_reg(priv, SPI_FLASH_CTL)) & ++ SPI_CTL_BUSY, 0); ++ return reg; ++} ++ ++static u32 ++spiflash_sendcmd (struct spiflash_priv *priv, int opcode, u32 addr) ++{ ++ const struct opcodes *op; ++ u32 reg, mask; ++ ++ op = &stm_opcodes[opcode]; ++ reg = spiflash_wait_busy(priv); ++ spiflash_write_reg(priv, SPI_FLASH_OPCODE, ++ ((u32) op->code) | (addr << 8)); ++ ++ reg &= ~SPI_CTL_TX_RX_CNT_MASK; ++ reg |= SPI_CTL_START | op->tx_cnt | (op->rx_cnt << 4); ++ ++ spiflash_write_reg(priv, SPI_FLASH_CTL, reg); ++ spiflash_wait_busy(priv); ++ ++ if (!op->rx_cnt) ++ return 0; ++ ++ reg = spiflash_read_reg(priv, SPI_FLASH_DATA); ++ ++ switch (op->rx_cnt) { ++ case 1: ++ mask = 0x000000ff; ++ break; ++ case 2: ++ mask = 0x0000ffff; ++ break; ++ case 3: ++ mask = 0x00ffffff; ++ break; ++ default: ++ mask = 0xffffffff; ++ break; ++ } ++ reg &= mask; ++ ++ return reg; ++} ++ ++ ++/* ++ * Probe SPI flash device ++ * Function returns 0 for failure. ++ * and flashconfig_tbl array index for success. ++ */ ++static int ++spiflash_probe_chip (struct spiflash_priv *priv) ++{ ++ u32 sig; ++ int flash_size; ++ ++ /* Read the signature on the flash device */ ++ spin_lock_bh(&priv->lock); ++ sig = spiflash_sendcmd(priv, SPI_RD_SIG, 0); ++ spin_unlock_bh(&priv->lock); ++ ++ switch (sig) { ++ case STM_8MBIT_SIGNATURE: ++ flash_size = FLASH_1MB; ++ break; ++ case STM_16MBIT_SIGNATURE: ++ flash_size = FLASH_2MB; ++ break; ++ case STM_32MBIT_SIGNATURE: ++ flash_size = FLASH_4MB; ++ break; ++ case STM_64MBIT_SIGNATURE: ++ flash_size = FLASH_8MB; ++ break; ++ case STM_128MBIT_SIGNATURE: ++ flash_size = FLASH_16MB; ++ break; ++ default: ++ printk (KERN_WARNING SPIFLASH "Read of flash device signature failed!\n"); ++ return 0; ++ } ++ ++ return flash_size; ++} ++ ++ ++/* wait until the flash chip is ready and grab a lock */ ++static int spiflash_wait_ready(struct spiflash_priv *priv, int state) ++{ ++ DECLARE_WAITQUEUE(wait, current); ++ ++retry: ++ spin_lock_bh(&priv->lock); ++ if (priv->state != FL_READY) { ++ set_current_state(TASK_UNINTERRUPTIBLE); ++ add_wait_queue(&priv->wq, &wait); ++ spin_unlock_bh(&priv->lock); ++ schedule(); ++ remove_wait_queue(&priv->wq, &wait); ++ ++ if(signal_pending(current)) ++ return 0; ++ ++ goto retry; ++ } ++ priv->state = state; ++ ++ return 1; ++} ++ ++static inline void spiflash_done(struct spiflash_priv *priv) ++{ ++ priv->state = FL_READY; ++ spin_unlock_bh(&priv->lock); ++ wake_up(&priv->wq); ++} ++ ++static void ++spiflash_wait_complete(struct spiflash_priv *priv, unsigned int timeout) ++{ ++ busy_wait(priv, spiflash_sendcmd(priv, SPI_RD_STATUS, 0) & ++ SPI_STATUS_WIP, timeout); ++ spiflash_done(priv); ++} ++ ++ ++ ++static int ++spiflash_erase (struct mtd_info *mtd, struct erase_info *instr) ++{ ++ struct spiflash_priv *priv = to_spiflash(mtd); ++ const struct opcodes *op; ++ u32 temp, reg; ++ ++ if (instr->addr + instr->len > mtd->size) ++ return -EINVAL; ++ ++ if (!spiflash_wait_ready(priv, FL_ERASING)) ++ return -EINTR; ++ ++ spiflash_sendcmd(priv, SPI_WRITE_ENABLE, 0); ++ reg = spiflash_wait_busy(priv); ++ ++ op = &stm_opcodes[SPI_SECTOR_ERASE]; ++ temp = ((u32)instr->addr << 8) | (u32)(op->code); ++ spiflash_write_reg(priv, SPI_FLASH_OPCODE, temp); ++ ++ reg &= ~SPI_CTL_TX_RX_CNT_MASK; ++ reg |= op->tx_cnt | SPI_CTL_START; ++ spiflash_write_reg(priv, SPI_FLASH_CTL, reg); ++ ++ spiflash_wait_complete(priv, 20); ++ ++ instr->state = MTD_ERASE_DONE; ++ mtd_erase_callback(instr); ++ ++ return 0; ++} ++ ++static int ++spiflash_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) ++{ ++ struct spiflash_priv *priv = to_spiflash(mtd); ++ u8 *read_addr; ++ ++ if (!len) ++ return 0; ++ ++ if (from + len > mtd->size) ++ return -EINVAL; ++ ++ *retlen = len; ++ ++ if (!spiflash_wait_ready(priv, FL_READING)) ++ return -EINTR; ++ ++ read_addr = (u8 *)(priv->readaddr + from); ++ memcpy_fromio(buf, read_addr, len); ++ spiflash_done(priv); ++ ++ return 0; ++} ++ ++static int ++spiflash_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u8 *buf) ++{ ++ struct spiflash_priv *priv = to_spiflash(mtd); ++ u32 opcode, bytes_left; ++ ++ *retlen = 0; ++ ++ if (!len) ++ return 0; ++ ++ if (to + len > mtd->size) ++ return -EINVAL; ++ ++ bytes_left = len; ++ ++ do { ++ u32 read_len, reg, page_offset, spi_data = 0; ++ ++ read_len = min(bytes_left, sizeof(u32)); ++ ++ /* 32-bit writes cannot span across a page boundary ++ * (256 bytes). This types of writes require two page ++ * program operations to handle it correctly. The STM part ++ * will write the overflow data to the beginning of the ++ * current page as opposed to the subsequent page. ++ */ ++ page_offset = (to & (STM_PAGE_SIZE - 1)) + read_len; ++ ++ if (page_offset > STM_PAGE_SIZE) ++ read_len -= (page_offset - STM_PAGE_SIZE); ++ ++ if (!spiflash_wait_ready(priv, FL_WRITING)) ++ return -EINTR; ++ ++ spiflash_sendcmd(priv, SPI_WRITE_ENABLE, 0); ++ spi_data = 0; ++ switch (read_len) { ++ case 4: ++ spi_data |= buf[3] << 24; ++ /* fall through */ ++ case 3: ++ spi_data |= buf[2] << 16; ++ /* fall through */ ++ case 2: ++ spi_data |= buf[1] << 8; ++ /* fall through */ ++ case 1: ++ spi_data |= buf[0] & 0xff; ++ break; ++ default: ++ break; ++ } ++ ++ spiflash_write_reg(priv, SPI_FLASH_DATA, spi_data); ++ opcode = stm_opcodes[SPI_PAGE_PROGRAM].code | ++ (to & 0x00ffffff) << 8; ++ spiflash_write_reg(priv, SPI_FLASH_OPCODE, opcode); ++ ++ reg = spiflash_read_reg(priv, SPI_FLASH_CTL); ++ reg &= ~SPI_CTL_TX_RX_CNT_MASK; ++ reg |= (read_len + 4) | SPI_CTL_START; ++ spiflash_write_reg(priv, SPI_FLASH_CTL, reg); ++ ++ spiflash_wait_complete(priv, 1); ++ ++ bytes_left -= read_len; ++ to += read_len; ++ buf += read_len; ++ ++ *retlen += read_len; ++ } while (bytes_left != 0); ++ ++ return 0; ++} ++ ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", "MyLoader", NULL }; ++#endif ++ ++ ++static int ++spiflash_probe(struct platform_device *pdev) ++{ ++ struct spiflash_priv *priv; ++ struct mtd_partition *parts; ++ struct mtd_info *mtd; ++ int index, num_parts; ++ int result = 0; ++ ++ priv = kzalloc(sizeof(struct spiflash_priv), GFP_KERNEL); ++ spin_lock_init(&priv->lock); ++ init_waitqueue_head(&priv->wq); ++ priv->state = FL_READY; ++ mtd = &priv->mtd; ++ ++ priv->mmraddr = ioremap_nocache(SPI_FLASH_MMR, SPI_FLASH_MMR_SIZE); ++ if (!priv->mmraddr) { ++ printk(KERN_WARNING SPIFLASH "Failed to map flash device\n"); ++ goto error; ++ } ++ ++ index = spiflash_probe_chip(priv); ++ if (!index) { ++ printk (KERN_WARNING SPIFLASH "Found no serial flash device\n"); ++ goto error; ++ } ++ ++ priv->readaddr = ioremap_nocache(SPI_FLASH_READ, flashconfig_tbl[index].byte_cnt); ++ if (!priv->readaddr) { ++ printk (KERN_WARNING SPIFLASH "Failed to map flash device\n"); ++ goto error; ++ } ++ ++ platform_set_drvdata(pdev, priv); ++ mtd->name = "spiflash"; ++ mtd->type = MTD_NORFLASH; ++ mtd->flags = (MTD_CAP_NORFLASH|MTD_WRITEABLE); ++ mtd->size = flashconfig_tbl[index].byte_cnt; ++ mtd->erasesize = flashconfig_tbl[index].sector_size; ++ mtd->writesize = 1; ++ mtd->numeraseregions = 0; ++ mtd->eraseregions = NULL; ++ mtd->erase = spiflash_erase; ++ mtd->read = spiflash_read; ++ mtd->write = spiflash_write; ++ mtd->owner = THIS_MODULE; ++ ++#ifdef CONFIG_MTD_PARTITIONS ++ /* parse redboot partitions */ ++ num_parts = parse_mtd_partitions(mtd, part_probe_types, &parts, 0); ++ if (!num_parts) ++ goto error; ++ ++ result = add_mtd_partitions(mtd, parts, num_parts); ++#endif ++ ++ return result; ++ ++error: ++ if (priv->mmraddr) ++ iounmap(priv->mmraddr); ++ kfree(priv); ++ return -ENXIO; ++} ++ ++static int ++spiflash_remove (struct platform_device *pdev) ++{ ++ struct spiflash_priv *priv = platform_get_drvdata(pdev); ++ struct mtd_info *mtd = &priv->mtd; ++ ++ del_mtd_partitions(mtd); ++ iounmap(priv->mmraddr); ++ iounmap(priv->readaddr); ++ kfree(priv); ++ ++ return 0; ++} ++ ++struct platform_driver spiflash_driver = { ++ .driver.name = "spiflash", ++ .probe = spiflash_probe, ++ .remove = spiflash_remove, ++}; ++ ++int __init ++spiflash_init (void) ++{ ++ return platform_driver_register(&spiflash_driver); ++} ++ ++void __exit ++spiflash_exit (void) ++{ ++ return platform_driver_unregister(&spiflash_driver); ++} ++ ++module_init (spiflash_init); ++module_exit (spiflash_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("OpenWrt.org, Atheros Communications Inc"); ++MODULE_DESCRIPTION("MTD driver for SPI Flash on Atheros SOC"); ++ +diff -Nur linux-2.6.39-rc7.orig/drivers/mtd/redboot.c linux-2.6.39-rc7/drivers/mtd/redboot.c +--- linux-2.6.39-rc7.orig/drivers/mtd/redboot.c 2011-05-10 04:33:54.000000000 +0200 ++++ linux-2.6.39-rc7/drivers/mtd/redboot.c 2011-05-15 21:34:57.000000000 +0200 +@@ -55,6 +55,22 @@ + return 1; + } + ++static uint32_t mtd_get_offset_erasesize(struct mtd_info *mtd, uint64_t offset) ++{ ++ struct mtd_erase_region_info *regions = mtd->eraseregions; ++ int i; ++ ++ for (i = 0; i < mtd->numeraseregions; i++) { ++ if (regions[i].offset + ++ regions[i].numblocks * regions[i].erasesize <= offset) ++ continue; ++ ++ return regions[i].erasesize; ++ } ++ ++ return mtd->erasesize; ++} ++ + static int parse_redboot_partitions(struct mtd_info *master, + struct mtd_partition **pparts, + unsigned long fis_origin) +@@ -70,36 +86,38 @@ + int namelen = 0; + int nulllen = 0; + int numslots; ++ int first_slot; + unsigned long offset; + #ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED + static char nullstring[] = "unallocated"; + #endif + ++ buf = vmalloc(master->erasesize); ++ if (!buf) ++ return -ENOMEM; ++ ++ restart: + if ( directory < 0 ) { + offset = master->size + directory * master->erasesize; +- while (master->block_isbad && ++ while (master->block_isbad && + master->block_isbad(master, offset)) { + if (!offset) { + nogood: + printk(KERN_NOTICE "Failed to find a non-bad block to check for RedBoot partition table\n"); ++ vfree(buf); + return -EIO; + } + offset -= master->erasesize; + } + } else { + offset = directory * master->erasesize; +- while (master->block_isbad && ++ while (master->block_isbad && + master->block_isbad(master, offset)) { + offset += master->erasesize; + if (offset == master->size) + goto nogood; + } + } +- buf = vmalloc(master->erasesize); +- +- if (!buf) +- return -ENOMEM; +- + printk(KERN_NOTICE "Searching for RedBoot partition table in %s at offset 0x%lx\n", + master->name, offset); + +@@ -171,13 +189,21 @@ + } + if (i == numslots) { + /* Didn't find it */ ++ if (offset + master->erasesize < master->size) { ++ /* not at the end of the flash yet, maybe next block :) */ ++ directory++; ++ goto restart; ++ } + printk(KERN_NOTICE "No RedBoot partition table detected in %s\n", + master->name); + ret = 0; + goto out; + } + +- for (i = 0; i < numslots; i++) { ++ first_slot = (buf[i].flash_base & (master->erasesize - 1)) / ++ sizeof(struct fis_image_desc); ++ ++ for (i = first_slot; i < first_slot + numslots; i++) { + struct fis_list *new_fl, **prev; + + if (buf[i].name[0] == 0xff) { +diff -Nur linux-2.6.39-rc7.orig/drivers/net/Kconfig linux-2.6.39-rc7/drivers/net/Kconfig +--- linux-2.6.39-rc7.orig/drivers/net/Kconfig 2011-05-10 04:33:54.000000000 +0200 ++++ linux-2.6.39-rc7/drivers/net/Kconfig 2011-05-15 21:34:57.000000000 +0200 +@@ -251,6 +251,12 @@ + help + Select this if your platform comes with an external 93CX6 eeprom. + ++config AR231X_ETHERNET ++ tristate "AR231x Ethernet support" ++ depends on ATHEROS_AR231X ++ help ++ Support for the AR231x/531x ethernet controller ++ + config MACE + tristate "MACE (Power Mac ethernet) support" + depends on PPC_PMAC && PPC32 +diff -Nur linux-2.6.39-rc7.orig/drivers/net/Makefile linux-2.6.39-rc7/drivers/net/Makefile +--- linux-2.6.39-rc7.orig/drivers/net/Makefile 2011-05-10 04:33:54.000000000 +0200 ++++ linux-2.6.39-rc7/drivers/net/Makefile 2011-05-15 21:34:57.000000000 +0200 +@@ -226,6 +226,7 @@ + obj-$(CONFIG_KORINA) += korina.o + obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o + obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o ++obj-$(CONFIG_AR231X_ETHERNET) += ar231x.o + obj-$(CONFIG_MIPS_SIM_NET) += mipsnet.o + obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o + obj-$(CONFIG_DECLANCE) += declance.o +diff -Nur linux-2.6.39-rc7.orig/drivers/net/ar231x.c linux-2.6.39-rc7/drivers/net/ar231x.c +--- linux-2.6.39-rc7.orig/drivers/net/ar231x.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/drivers/net/ar231x.c 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,1293 @@ ++/* ++ * ar231x.c: Linux driver for the Atheros AR231x Ethernet device. ++ * ++ * Copyright (C) 2004 by Sameer Dekate <sdekate@arubanetworks.com> ++ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> ++ * ++ * Thanks to Atheros for providing hardware and documentation ++ * enabling me to write this driver. ++ * ++ * 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. ++ * ++ * Additional credits: ++ * This code is taken from John Taylor's Sibyte driver and then ++ * modified for the AR2313. ++ */ ++ ++#include <linux/module.h> ++#include <linux/version.h> ++#include <linux/types.h> ++#include <linux/errno.h> ++#include <linux/ioport.h> ++#include <linux/pci.h> ++#include <linux/netdevice.h> ++#include <linux/etherdevice.h> ++#include <linux/skbuff.h> ++#include <linux/init.h> ++#include <linux/delay.h> ++#include <linux/mm.h> ++#include <linux/highmem.h> ++#include <linux/sockios.h> ++#include <linux/pkt_sched.h> ++#include <linux/mii.h> ++#include <linux/phy.h> ++#include <linux/ethtool.h> ++#include <linux/ctype.h> ++#include <linux/platform_device.h> ++ ++#include <net/sock.h> ++#include <net/ip.h> ++ ++#include <asm/system.h> ++#include <asm/io.h> ++#include <asm/irq.h> ++#include <asm/byteorder.h> ++#include <asm/uaccess.h> ++#include <asm/bootinfo.h> ++ ++#define AR2313_MTU 1692 ++#define AR2313_PRIOS 1 ++#define AR2313_QUEUES (2*AR2313_PRIOS) ++#define AR2313_DESCR_ENTRIES 64 ++ ++ ++#ifndef min ++#define min(a,b) (((a)<(b))?(a):(b)) ++#endif ++ ++#ifndef SMP_CACHE_BYTES ++#define SMP_CACHE_BYTES L1_CACHE_BYTES ++#endif ++ ++#define AR2313_MBOX_SET_BIT 0x8 ++ ++#include "ar231x.h" ++ ++/* ++ * New interrupt handler strategy: ++ * ++ * An old interrupt handler worked using the traditional method of ++ * replacing an skbuff with a new one when a packet arrives. However ++ * the rx rings do not need to contain a static number of buffer ++ * descriptors, thus it makes sense to move the memory allocation out ++ * of the main interrupt handler and do it in a bottom half handler ++ * and only allocate new buffers when the number of buffers in the ++ * ring is below a certain threshold. In order to avoid starving the ++ * NIC under heavy load it is however necessary to force allocation ++ * when hitting a minimum threshold. The strategy for alloction is as ++ * follows: ++ * ++ * RX_LOW_BUF_THRES - allocate buffers in the bottom half ++ * RX_PANIC_LOW_THRES - we are very low on buffers, allocate ++ * the buffers in the interrupt handler ++ * RX_RING_THRES - maximum number of buffers in the rx ring ++ * ++ * One advantagous side effect of this allocation approach is that the ++ * entire rx processing can be done without holding any spin lock ++ * since the rx rings and registers are totally independent of the tx ++ * ring and its registers. This of course includes the kmalloc's of ++ * new skb's. Thus start_xmit can run in parallel with rx processing ++ * and the memory allocation on SMP systems. ++ * ++ * Note that running the skb reallocation in a bottom half opens up ++ * another can of races which needs to be handled properly. In ++ * particular it can happen that the interrupt handler tries to run ++ * the reallocation while the bottom half is either running on another ++ * CPU or was interrupted on the same CPU. To get around this the ++ * driver uses bitops to prevent the reallocation routines from being ++ * reentered. ++ * ++ * TX handling can also be done without holding any spin lock, wheee ++ * this is fun! since tx_csm is only written to by the interrupt ++ * handler. ++ */ ++ ++/* ++ * Threshold values for RX buffer allocation - the low water marks for ++ * when to start refilling the rings are set to 75% of the ring ++ * sizes. It seems to make sense to refill the rings entirely from the ++ * intrrupt handler once it gets below the panic threshold, that way ++ * we don't risk that the refilling is moved to another CPU when the ++ * one running the interrupt handler just got the slab code hot in its ++ * cache. ++ */ ++#define RX_RING_SIZE AR2313_DESCR_ENTRIES ++#define RX_PANIC_THRES (RX_RING_SIZE/4) ++#define RX_LOW_THRES ((3*RX_RING_SIZE)/4) ++#define CRC_LEN 4 ++#define RX_OFFSET 2 ++ ++#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) ++#define VLAN_HDR 4 ++#else ++#define VLAN_HDR 0 ++#endif ++ ++#define AR2313_BUFSIZE (AR2313_MTU + VLAN_HDR + ETH_HLEN + CRC_LEN + RX_OFFSET) ++ ++#ifdef MODULE ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Sameer Dekate <sdekate@arubanetworks.com>, Imre Kaloz <kaloz@openwrt.org>, Felix Fietkau <nbd@openwrt.org>"); ++MODULE_DESCRIPTION("AR231x Ethernet driver"); ++#endif ++ ++#define virt_to_phys(x) ((u32)(x) & 0x1fffffff) ++ ++// prototypes ++static void ar231x_halt(struct net_device *dev); ++static void rx_tasklet_func(unsigned long data); ++static void rx_tasklet_cleanup(struct net_device *dev); ++static void ar231x_multicast_list(struct net_device *dev); ++static void ar231x_tx_timeout(struct net_device *dev); ++ ++static int ar231x_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum); ++static int ar231x_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, u16 value); ++static int ar231x_mdiobus_reset(struct mii_bus *bus); ++static int ar231x_mdiobus_probe (struct net_device *dev); ++static void ar231x_adjust_link(struct net_device *dev); ++ ++#ifndef ERR ++#define ERR(fmt, args...) printk("%s: " fmt, __func__, ##args) ++#endif ++ ++#ifdef CONFIG_NET_POLL_CONTROLLER ++static void ++ar231x_netpoll(struct net_device *dev) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ar231x_interrupt(dev->irq, dev); ++ local_irq_restore(flags); ++} ++#endif ++ ++static const struct net_device_ops ar231x_ops = { ++ .ndo_open = ar231x_open, ++ .ndo_stop = ar231x_close, ++ .ndo_start_xmit = ar231x_start_xmit, ++ .ndo_set_multicast_list = ar231x_multicast_list, ++ .ndo_do_ioctl = ar231x_ioctl, ++ .ndo_change_mtu = eth_change_mtu, ++ .ndo_validate_addr = eth_validate_addr, ++ .ndo_set_mac_address = eth_mac_addr, ++ .ndo_tx_timeout = ar231x_tx_timeout, ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = ar231x_netpoll, ++#endif ++}; ++ ++int __init ar231x_probe(struct platform_device *pdev) ++{ ++ struct net_device *dev; ++ struct ar231x_private *sp; ++ struct resource *res; ++ unsigned long ar_eth_base; ++ char buf[64]; ++ ++ dev = alloc_etherdev(sizeof(struct ar231x_private)); ++ ++ if (dev == NULL) { ++ printk(KERN_ERR ++ "ar231x: Unable to allocate net_device structure!\n"); ++ return -ENOMEM; ++ } ++ ++ platform_set_drvdata(pdev, dev); ++ ++ sp = netdev_priv(dev); ++ sp->dev = dev; ++ sp->cfg = pdev->dev.platform_data; ++ ++ sprintf(buf, "eth%d_membase", pdev->id); ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, buf); ++ if (!res) ++ return -ENODEV; ++ ++ sp->link = 0; ++ ar_eth_base = res->start; ++ ++ sprintf(buf, "eth%d_irq", pdev->id); ++ dev->irq = platform_get_irq_byname(pdev, buf); ++ ++ spin_lock_init(&sp->lock); ++ ++ dev->features |= NETIF_F_HIGHDMA; ++ dev->netdev_ops = &ar231x_ops; ++ ++ tasklet_init(&sp->rx_tasklet, rx_tasklet_func, (unsigned long) dev); ++ tasklet_disable(&sp->rx_tasklet); ++ ++ sp->eth_regs = ++ ioremap_nocache(virt_to_phys(ar_eth_base), sizeof(*sp->eth_regs)); ++ if (!sp->eth_regs) { ++ printk("Can't remap eth registers\n"); ++ return (-ENXIO); ++ } ++ ++ /* ++ * When there's only one MAC, PHY regs are typically on ENET0, ++ * even though the MAC might be on ENET1. ++ * Needto remap PHY regs separately in this case ++ */ ++ if (virt_to_phys(ar_eth_base) == virt_to_phys(sp->phy_regs)) ++ sp->phy_regs = sp->eth_regs; ++ else { ++ sp->phy_regs = ++ ioremap_nocache(virt_to_phys(sp->cfg->phy_base), ++ sizeof(*sp->phy_regs)); ++ if (!sp->phy_regs) { ++ printk("Can't remap phy registers\n"); ++ return (-ENXIO); ++ } ++ } ++ ++ sp->dma_regs = ++ ioremap_nocache(virt_to_phys(ar_eth_base + 0x1000), ++ sizeof(*sp->dma_regs)); ++ dev->base_addr = (unsigned int) sp->dma_regs; ++ if (!sp->dma_regs) { ++ printk("Can't remap DMA registers\n"); ++ return (-ENXIO); ++ } ++ ++ sp->int_regs = ioremap_nocache(virt_to_phys(sp->cfg->reset_base), 4); ++ if (!sp->int_regs) { ++ printk("Can't remap INTERRUPT registers\n"); ++ return (-ENXIO); ++ } ++ ++ strncpy(sp->name, "Atheros AR231x", sizeof(sp->name) - 1); ++ sp->name[sizeof(sp->name) - 1] = '\0'; ++ memcpy(dev->dev_addr, sp->cfg->macaddr, 6); ++ ++ if (ar231x_init(dev)) { ++ /* ++ * ar231x_init() calls ar231x_init_cleanup() on error. ++ */ ++ kfree(dev); ++ return -ENODEV; ++ } ++ ++ if (register_netdev(dev)) { ++ printk("%s: register_netdev failed\n", __func__); ++ return -1; ++ } ++ ++ printk("%s: %s: %02x:%02x:%02x:%02x:%02x:%02x, irq %d\n", ++ dev->name, sp->name, ++ dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], ++ dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5], dev->irq); ++ ++ sp->mii_bus = mdiobus_alloc(); ++ if (sp->mii_bus == NULL) ++ return -1; ++ ++ sp->mii_bus->priv = dev; ++ sp->mii_bus->read = ar231x_mdiobus_read; ++ sp->mii_bus->write = ar231x_mdiobus_write; ++ sp->mii_bus->reset = ar231x_mdiobus_reset; ++ sp->mii_bus->name = "ar231x_eth_mii"; ++ snprintf(sp->mii_bus->id, MII_BUS_ID_SIZE, "%d", pdev->id); ++ sp->mii_bus->irq = kmalloc(sizeof(int), GFP_KERNEL); ++ *sp->mii_bus->irq = PHY_POLL; ++ ++ mdiobus_register(sp->mii_bus); ++ ++ if (ar231x_mdiobus_probe(dev) != 0) { ++ printk(KERN_ERR "%s: mdiobus_probe failed\n", dev->name); ++ rx_tasklet_cleanup(dev); ++ ar231x_init_cleanup(dev); ++ unregister_netdev(dev); ++ kfree(dev); ++ return -ENODEV; ++ } ++ ++ /* start link poll timer */ ++ ar231x_setup_timer(dev); ++ ++ return 0; ++} ++ ++ ++static void ar231x_multicast_list(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ unsigned int filter; ++ ++ filter = sp->eth_regs->mac_control; ++ ++ if (dev->flags & IFF_PROMISC) ++ filter |= MAC_CONTROL_PR; ++ else ++ filter &= ~MAC_CONTROL_PR; ++ if ((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 0)) ++ filter |= MAC_CONTROL_PM; ++ else ++ filter &= ~MAC_CONTROL_PM; ++ ++ sp->eth_regs->mac_control = filter; ++} ++ ++static void rx_tasklet_cleanup(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ ++ /* ++ * Tasklet may be scheduled. Need to get it removed from the list ++ * since we're about to free the struct. ++ */ ++ ++ sp->unloading = 1; ++ tasklet_enable(&sp->rx_tasklet); ++ tasklet_kill(&sp->rx_tasklet); ++} ++ ++static int __devexit ar231x_remove(struct platform_device *pdev) ++{ ++ struct net_device *dev = platform_get_drvdata(pdev); ++ struct ar231x_private *sp = netdev_priv(dev); ++ rx_tasklet_cleanup(dev); ++ ar231x_init_cleanup(dev); ++ unregister_netdev(dev); ++ mdiobus_unregister(sp->mii_bus); ++ mdiobus_free(sp->mii_bus); ++ kfree(dev); ++ return 0; ++} ++ ++ ++/* ++ * Restart the AR2313 ethernet controller. ++ */ ++static int ar231x_restart(struct net_device *dev) ++{ ++ /* disable interrupts */ ++ disable_irq(dev->irq); ++ ++ /* stop mac */ ++ ar231x_halt(dev); ++ ++ /* initialize */ ++ ar231x_init(dev); ++ ++ /* enable interrupts */ ++ enable_irq(dev->irq); ++ ++ return 0; ++} ++ ++static struct platform_driver ar231x_driver = { ++ .driver.name = "ar231x-eth", ++ .probe = ar231x_probe, ++ .remove = __devexit_p(ar231x_remove), ++}; ++ ++int __init ar231x_module_init(void) ++{ ++ return platform_driver_register(&ar231x_driver); ++} ++ ++void __exit ar231x_module_cleanup(void) ++{ ++ platform_driver_unregister(&ar231x_driver); ++} ++ ++module_init(ar231x_module_init); ++module_exit(ar231x_module_cleanup); ++ ++ ++static void ar231x_free_descriptors(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ if (sp->rx_ring != NULL) { ++ kfree((void *) KSEG0ADDR(sp->rx_ring)); ++ sp->rx_ring = NULL; ++ sp->tx_ring = NULL; ++ } ++} ++ ++ ++static int ar231x_allocate_descriptors(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ int size; ++ int j; ++ ar231x_descr_t *space; ++ ++ if (sp->rx_ring != NULL) { ++ printk("%s: already done.\n", __FUNCTION__); ++ return 0; ++ } ++ ++ size = ++ (sizeof(ar231x_descr_t) * (AR2313_DESCR_ENTRIES * AR2313_QUEUES)); ++ space = kmalloc(size, GFP_KERNEL); ++ if (space == NULL) ++ return 1; ++ ++ /* invalidate caches */ ++ dma_cache_inv((unsigned int) space, size); ++ ++ /* now convert pointer to KSEG1 */ ++ space = (ar231x_descr_t *) KSEG1ADDR(space); ++ ++ memset((void *) space, 0, size); ++ ++ sp->rx_ring = space; ++ space += AR2313_DESCR_ENTRIES; ++ ++ sp->tx_ring = space; ++ space += AR2313_DESCR_ENTRIES; ++ ++ /* Initialize the transmit Descriptors */ ++ for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { ++ ar231x_descr_t *td = &sp->tx_ring[j]; ++ td->status = 0; ++ td->devcs = DMA_TX1_CHAINED; ++ td->addr = 0; ++ td->descr = ++ virt_to_phys(&sp-> ++ tx_ring[(j + 1) & (AR2313_DESCR_ENTRIES - 1)]); ++ } ++ ++ return 0; ++} ++ ++ ++/* ++ * Generic cleanup handling data allocated during init. Used when the ++ * module is unloaded or if an error occurs during initialization ++ */ ++static void ar231x_init_cleanup(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ struct sk_buff *skb; ++ int j; ++ ++ ar231x_free_descriptors(dev); ++ ++ if (sp->eth_regs) ++ iounmap((void *) sp->eth_regs); ++ if (sp->dma_regs) ++ iounmap((void *) sp->dma_regs); ++ ++ if (sp->rx_skb) { ++ for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { ++ skb = sp->rx_skb[j]; ++ if (skb) { ++ sp->rx_skb[j] = NULL; ++ dev_kfree_skb(skb); ++ } ++ } ++ kfree(sp->rx_skb); ++ sp->rx_skb = NULL; ++ } ++ ++ if (sp->tx_skb) { ++ for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { ++ skb = sp->tx_skb[j]; ++ if (skb) { ++ sp->tx_skb[j] = NULL; ++ dev_kfree_skb(skb); ++ } ++ } ++ kfree(sp->tx_skb); ++ sp->tx_skb = NULL; ++ } ++} ++ ++static int ar231x_setup_timer(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ ++ init_timer(&sp->link_timer); ++ ++ sp->link_timer.function = ar231x_link_timer_fn; ++ sp->link_timer.data = (int) dev; ++ sp->link_timer.expires = jiffies + HZ; ++ ++ add_timer(&sp->link_timer); ++ return 0; ++ ++} ++ ++static void ar231x_link_timer_fn(unsigned long data) ++{ ++ struct net_device *dev = (struct net_device *) data; ++ struct ar231x_private *sp = netdev_priv(dev); ++ ++ // see if the link status changed ++ // This was needed to make sure we set the PHY to the ++ // autonegotiated value of half or full duplex. ++ ar231x_check_link(dev); ++ ++ // Loop faster when we don't have link. ++ // This was needed to speed up the AP bootstrap time. ++ if (sp->link == 0) { ++ mod_timer(&sp->link_timer, jiffies + HZ / 2); ++ } else { ++ mod_timer(&sp->link_timer, jiffies + LINK_TIMER); ++ } ++} ++ ++static void ar231x_check_link(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ u16 phyData; ++ ++ phyData = ar231x_mdiobus_read(sp->mii_bus, sp->phy, MII_BMSR); ++ if (sp->phyData != phyData) { ++ if (phyData & BMSR_LSTATUS) { ++ /* link is present, ready link partner ability to deterine ++ duplexity */ ++ int duplex = 0; ++ u16 reg; ++ ++ sp->link = 1; ++ reg = ar231x_mdiobus_read(sp->mii_bus, sp->phy, MII_BMCR); ++ if (reg & BMCR_ANENABLE) { ++ /* auto neg enabled */ ++ reg = ar231x_mdiobus_read(sp->mii_bus, sp->phy, MII_LPA); ++ duplex = (reg & (LPA_100FULL | LPA_10FULL)) ? 1 : 0; ++ } else { ++ /* no auto neg, just read duplex config */ ++ duplex = (reg & BMCR_FULLDPLX) ? 1 : 0; ++ } ++ ++ printk(KERN_INFO "%s: Configuring MAC for %s duplex\n", ++ dev->name, (duplex) ? "full" : "half"); ++ ++ if (duplex) { ++ /* full duplex */ ++ sp->eth_regs->mac_control = ++ ((sp->eth_regs-> ++ mac_control | MAC_CONTROL_F) & ~MAC_CONTROL_DRO); ++ } else { ++ /* half duplex */ ++ sp->eth_regs->mac_control = ++ ((sp->eth_regs-> ++ mac_control | MAC_CONTROL_DRO) & ~MAC_CONTROL_F); ++ } ++ } else { ++ /* no link */ ++ sp->link = 0; ++ } ++ sp->phyData = phyData; ++ } ++} ++ ++static int ar231x_reset_reg(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ unsigned int ethsal, ethsah; ++ unsigned int flags; ++ ++ *sp->int_regs |= sp->cfg->reset_mac; ++ mdelay(10); ++ *sp->int_regs &= ~sp->cfg->reset_mac; ++ mdelay(10); ++ *sp->int_regs |= sp->cfg->reset_phy; ++ mdelay(10); ++ *sp->int_regs &= ~sp->cfg->reset_phy; ++ mdelay(10); ++ ++ sp->dma_regs->bus_mode = (DMA_BUS_MODE_SWR); ++ mdelay(10); ++ sp->dma_regs->bus_mode = ++ ((32 << DMA_BUS_MODE_PBL_SHIFT) | DMA_BUS_MODE_BLE); ++ ++ /* enable interrupts */ ++ sp->dma_regs->intr_ena = (DMA_STATUS_AIS | ++ DMA_STATUS_NIS | ++ DMA_STATUS_RI | ++ DMA_STATUS_TI | DMA_STATUS_FBE); ++ sp->dma_regs->xmt_base = virt_to_phys(sp->tx_ring); ++ sp->dma_regs->rcv_base = virt_to_phys(sp->rx_ring); ++ sp->dma_regs->control = ++ (DMA_CONTROL_SR | DMA_CONTROL_ST | DMA_CONTROL_SF); ++ ++ sp->eth_regs->flow_control = (FLOW_CONTROL_FCE); ++ sp->eth_regs->vlan_tag = (0x8100); ++ ++ /* Enable Ethernet Interface */ ++ flags = (MAC_CONTROL_TE | /* transmit enable */ ++ MAC_CONTROL_PM | /* pass mcast */ ++ MAC_CONTROL_F | /* full duplex */ ++ MAC_CONTROL_HBD); /* heart beat disabled */ ++ ++ if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ ++ flags |= MAC_CONTROL_PR; ++ } ++ sp->eth_regs->mac_control = flags; ++ ++ /* Set all Ethernet station address registers to their initial values */ ++ ethsah = ((((u_int) (dev->dev_addr[5]) << 8) & (u_int) 0x0000FF00) | ++ (((u_int) (dev->dev_addr[4]) << 0) & (u_int) 0x000000FF)); ++ ++ ethsal = ((((u_int) (dev->dev_addr[3]) << 24) & (u_int) 0xFF000000) | ++ (((u_int) (dev->dev_addr[2]) << 16) & (u_int) 0x00FF0000) | ++ (((u_int) (dev->dev_addr[1]) << 8) & (u_int) 0x0000FF00) | ++ (((u_int) (dev->dev_addr[0]) << 0) & (u_int) 0x000000FF)); ++ ++ sp->eth_regs->mac_addr[0] = ethsah; ++ sp->eth_regs->mac_addr[1] = ethsal; ++ ++ mdelay(10); ++ ++ return (0); ++} ++ ++ ++static int ar231x_init(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ int ecode = 0; ++ ++ /* ++ * Allocate descriptors ++ */ ++ if (ar231x_allocate_descriptors(dev)) { ++ printk("%s: %s: ar231x_allocate_descriptors failed\n", ++ dev->name, __FUNCTION__); ++ ecode = -EAGAIN; ++ goto init_error; ++ } ++ ++ /* ++ * Get the memory for the skb rings. ++ */ ++ if (sp->rx_skb == NULL) { ++ sp->rx_skb = ++ kmalloc(sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES, ++ GFP_KERNEL); ++ if (!(sp->rx_skb)) { ++ printk("%s: %s: rx_skb kmalloc failed\n", ++ dev->name, __FUNCTION__); ++ ecode = -EAGAIN; ++ goto init_error; ++ } ++ } ++ memset(sp->rx_skb, 0, sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES); ++ ++ if (sp->tx_skb == NULL) { ++ sp->tx_skb = ++ kmalloc(sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES, ++ GFP_KERNEL); ++ if (!(sp->tx_skb)) { ++ printk("%s: %s: tx_skb kmalloc failed\n", ++ dev->name, __FUNCTION__); ++ ecode = -EAGAIN; ++ goto init_error; ++ } ++ } ++ memset(sp->tx_skb, 0, sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES); ++ ++ /* ++ * Set tx_csm before we start receiving interrupts, otherwise ++ * the interrupt handler might think it is supposed to process ++ * tx ints before we are up and running, which may cause a null ++ * pointer access in the int handler. ++ */ ++ sp->rx_skbprd = 0; ++ sp->cur_rx = 0; ++ sp->tx_prd = 0; ++ sp->tx_csm = 0; ++ ++ /* ++ * Zero the stats before starting the interface ++ */ ++ memset(&dev->stats, 0, sizeof(dev->stats)); ++ ++ /* ++ * We load the ring here as there seem to be no way to tell the ++ * firmware to wipe the ring without re-initializing it. ++ */ ++ ar231x_load_rx_ring(dev, RX_RING_SIZE); ++ ++ /* ++ * Init hardware ++ */ ++ ar231x_reset_reg(dev); ++ ++ /* ++ * Get the IRQ ++ */ ++ ecode = ++ request_irq(dev->irq, &ar231x_interrupt, ++ IRQF_DISABLED | IRQF_SAMPLE_RANDOM, ++ dev->name, dev); ++ if (ecode) { ++ printk(KERN_WARNING "%s: %s: Requested IRQ %d is busy\n", ++ dev->name, __FUNCTION__, dev->irq); ++ goto init_error; ++ } ++ ++ ++ tasklet_enable(&sp->rx_tasklet); ++ ++ return 0; ++ ++ init_error: ++ ar231x_init_cleanup(dev); ++ return ecode; ++} ++ ++/* ++ * Load the rx ring. ++ * ++ * Loading rings is safe without holding the spin lock since this is ++ * done only before the device is enabled, thus no interrupts are ++ * generated and by the interrupt handler/tasklet handler. ++ */ ++static void ar231x_load_rx_ring(struct net_device *dev, int nr_bufs) ++{ ++ ++ struct ar231x_private *sp = netdev_priv(dev); ++ short i, idx; ++ ++ idx = sp->rx_skbprd; ++ ++ for (i = 0; i < nr_bufs; i++) { ++ struct sk_buff *skb; ++ ar231x_descr_t *rd; ++ ++ if (sp->rx_skb[idx]) ++ break; ++ ++ skb = netdev_alloc_skb(dev, AR2313_BUFSIZE); ++ if (!skb) { ++ printk("\n\n\n\n %s: No memory in system\n\n\n\n", ++ __FUNCTION__); ++ break; ++ } ++ ++ /* ++ * Make sure IP header starts on a fresh cache line. ++ */ ++ skb->dev = dev; ++ skb_reserve(skb, RX_OFFSET); ++ sp->rx_skb[idx] = skb; ++ ++ rd = (ar231x_descr_t *) & sp->rx_ring[idx]; ++ ++ /* initialize dma descriptor */ ++ rd->devcs = ((AR2313_BUFSIZE << DMA_RX1_BSIZE_SHIFT) | ++ DMA_RX1_CHAINED); ++ rd->addr = virt_to_phys(skb->data); ++ rd->descr = ++ virt_to_phys(&sp-> ++ rx_ring[(idx + 1) & (AR2313_DESCR_ENTRIES - 1)]); ++ rd->status = DMA_RX_OWN; ++ ++ idx = DSC_NEXT(idx); ++ } ++ ++ if (i) ++ sp->rx_skbprd = idx; ++ ++ return; ++} ++ ++#define AR2313_MAX_PKTS_PER_CALL 64 ++ ++static int ar231x_rx_int(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ struct sk_buff *skb, *skb_new; ++ ar231x_descr_t *rxdesc; ++ unsigned int status; ++ u32 idx; ++ int pkts = 0; ++ int rval; ++ ++ idx = sp->cur_rx; ++ ++ /* process at most the entire ring and then wait for another interrupt ++ */ ++ while (1) { ++ ++ rxdesc = &sp->rx_ring[idx]; ++ status = rxdesc->status; ++ if (status & DMA_RX_OWN) { ++ /* SiByte owns descriptor or descr not yet filled in */ ++ rval = 0; ++ break; ++ } ++ ++ if (++pkts > AR2313_MAX_PKTS_PER_CALL) { ++ rval = 1; ++ break; ++ } ++ ++ if ((status & DMA_RX_ERROR) && !(status & DMA_RX_LONG)) { ++ dev->stats.rx_errors++; ++ dev->stats.rx_dropped++; ++ ++ /* add statistics counters */ ++ if (status & DMA_RX_ERR_CRC) ++ dev->stats.rx_crc_errors++; ++ if (status & DMA_RX_ERR_COL) ++ dev->stats.rx_over_errors++; ++ if (status & DMA_RX_ERR_LENGTH) ++ dev->stats.rx_length_errors++; ++ if (status & DMA_RX_ERR_RUNT) ++ dev->stats.rx_over_errors++; ++ if (status & DMA_RX_ERR_DESC) ++ dev->stats.rx_over_errors++; ++ ++ } else { ++ /* alloc new buffer. */ ++ skb_new = netdev_alloc_skb(dev, AR2313_BUFSIZE + RX_OFFSET); ++ if (skb_new != NULL) { ++ ++ skb = sp->rx_skb[idx]; ++ /* set skb */ ++ skb_put(skb, ++ ((status >> DMA_RX_LEN_SHIFT) & 0x3fff) - CRC_LEN); ++ ++ dev->stats.rx_bytes += skb->len; ++ skb->protocol = eth_type_trans(skb, dev); ++ /* pass the packet to upper layers */ ++ netif_rx(skb); ++ ++ skb_new->dev = dev; ++ /* 16 bit align */ ++ skb_reserve(skb_new, RX_OFFSET); ++ /* reset descriptor's curr_addr */ ++ rxdesc->addr = virt_to_phys(skb_new->data); ++ ++ dev->stats.rx_packets++; ++ sp->rx_skb[idx] = skb_new; ++ } else { ++ dev->stats.rx_dropped++; ++ } ++ } ++ ++ rxdesc->devcs = ((AR2313_BUFSIZE << DMA_RX1_BSIZE_SHIFT) | ++ DMA_RX1_CHAINED); ++ rxdesc->status = DMA_RX_OWN; ++ ++ idx = DSC_NEXT(idx); ++ } ++ ++ sp->cur_rx = idx; ++ ++ return rval; ++} ++ ++ ++static void ar231x_tx_int(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ u32 idx; ++ struct sk_buff *skb; ++ ar231x_descr_t *txdesc; ++ unsigned int status = 0; ++ ++ idx = sp->tx_csm; ++ ++ while (idx != sp->tx_prd) { ++ txdesc = &sp->tx_ring[idx]; ++ ++ if ((status = txdesc->status) & DMA_TX_OWN) { ++ /* ar231x dma still owns descr */ ++ break; ++ } ++ /* done with this descriptor */ ++ dma_unmap_single(NULL, txdesc->addr, ++ txdesc->devcs & DMA_TX1_BSIZE_MASK, ++ DMA_TO_DEVICE); ++ txdesc->status = 0; ++ ++ if (status & DMA_TX_ERROR) { ++ dev->stats.tx_errors++; ++ dev->stats.tx_dropped++; ++ if (status & DMA_TX_ERR_UNDER) ++ dev->stats.tx_fifo_errors++; ++ if (status & DMA_TX_ERR_HB) ++ dev->stats.tx_heartbeat_errors++; ++ if (status & (DMA_TX_ERR_LOSS | DMA_TX_ERR_LINK)) ++ dev->stats.tx_carrier_errors++; ++ if (status & (DMA_TX_ERR_LATE | ++ DMA_TX_ERR_COL | ++ DMA_TX_ERR_JABBER | DMA_TX_ERR_DEFER)) ++ dev->stats.tx_aborted_errors++; ++ } else { ++ /* transmit OK */ ++ dev->stats.tx_packets++; ++ } ++ ++ skb = sp->tx_skb[idx]; ++ sp->tx_skb[idx] = NULL; ++ idx = DSC_NEXT(idx); ++ dev->stats.tx_bytes += skb->len; ++ dev_kfree_skb_irq(skb); ++ } ++ ++ sp->tx_csm = idx; ++ ++ return; ++} ++ ++ ++static void rx_tasklet_func(unsigned long data) ++{ ++ struct net_device *dev = (struct net_device *) data; ++ struct ar231x_private *sp = netdev_priv(dev); ++ ++ if (sp->unloading) { ++ return; ++ } ++ ++ if (ar231x_rx_int(dev)) { ++ tasklet_hi_schedule(&sp->rx_tasklet); ++ } else { ++ unsigned long flags; ++ spin_lock_irqsave(&sp->lock, flags); ++ sp->dma_regs->intr_ena |= DMA_STATUS_RI; ++ spin_unlock_irqrestore(&sp->lock, flags); ++ } ++} ++ ++static void rx_schedule(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ ++ sp->dma_regs->intr_ena &= ~DMA_STATUS_RI; ++ ++ tasklet_hi_schedule(&sp->rx_tasklet); ++} ++ ++static irqreturn_t ar231x_interrupt(int irq, void *dev_id) ++{ ++ struct net_device *dev = (struct net_device *) dev_id; ++ struct ar231x_private *sp = netdev_priv(dev); ++ unsigned int status, enabled; ++ ++ /* clear interrupt */ ++ /* ++ * Don't clear RI bit if currently disabled. ++ */ ++ status = sp->dma_regs->status; ++ enabled = sp->dma_regs->intr_ena; ++ sp->dma_regs->status = status & enabled; ++ ++ if (status & DMA_STATUS_NIS) { ++ /* normal status */ ++ /* ++ * Don't schedule rx processing if interrupt ++ * is already disabled. ++ */ ++ if (status & enabled & DMA_STATUS_RI) { ++ /* receive interrupt */ ++ rx_schedule(dev); ++ } ++ if (status & DMA_STATUS_TI) { ++ /* transmit interrupt */ ++ ar231x_tx_int(dev); ++ } ++ } ++ ++ /* abnormal status */ ++ if (status & (DMA_STATUS_FBE | DMA_STATUS_TPS)) { ++ ar231x_restart(dev); ++ } ++ return IRQ_HANDLED; ++} ++ ++ ++static int ar231x_open(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ unsigned int ethsal, ethsah; ++ ++ /* reset the hardware, in case the MAC address changed */ ++ ethsah = ((((u_int) (dev->dev_addr[5]) << 8) & (u_int) 0x0000FF00) | ++ (((u_int) (dev->dev_addr[4]) << 0) & (u_int) 0x000000FF)); ++ ++ ethsal = ((((u_int) (dev->dev_addr[3]) << 24) & (u_int) 0xFF000000) | ++ (((u_int) (dev->dev_addr[2]) << 16) & (u_int) 0x00FF0000) | ++ (((u_int) (dev->dev_addr[1]) << 8) & (u_int) 0x0000FF00) | ++ (((u_int) (dev->dev_addr[0]) << 0) & (u_int) 0x000000FF)); ++ ++ sp->eth_regs->mac_addr[0] = ethsah; ++ sp->eth_regs->mac_addr[1] = ethsal; ++ ++ mdelay(10); ++ ++ dev->mtu = 1500; ++ netif_start_queue(dev); ++ ++ sp->eth_regs->mac_control |= MAC_CONTROL_RE; ++ ++ return 0; ++} ++ ++static void ar231x_tx_timeout(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&sp->lock, flags); ++ ar231x_restart(dev); ++ spin_unlock_irqrestore(&sp->lock, flags); ++} ++ ++static void ar231x_halt(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ int j; ++ ++ tasklet_disable(&sp->rx_tasklet); ++ ++ /* kill the MAC */ ++ sp->eth_regs->mac_control &= ~(MAC_CONTROL_RE | /* disable Receives */ ++ MAC_CONTROL_TE); /* disable Transmits */ ++ /* stop dma */ ++ sp->dma_regs->control = 0; ++ sp->dma_regs->bus_mode = DMA_BUS_MODE_SWR; ++ ++ /* place phy and MAC in reset */ ++ *sp->int_regs |= (sp->cfg->reset_mac | sp->cfg->reset_phy); ++ ++ /* free buffers on tx ring */ ++ for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { ++ struct sk_buff *skb; ++ ar231x_descr_t *txdesc; ++ ++ txdesc = &sp->tx_ring[j]; ++ txdesc->descr = 0; ++ ++ skb = sp->tx_skb[j]; ++ if (skb) { ++ dev_kfree_skb(skb); ++ sp->tx_skb[j] = NULL; ++ } ++ } ++} ++ ++/* ++ * close should do nothing. Here's why. It's called when ++ * 'ifconfig bond0 down' is run. If it calls free_irq then ++ * the irq is gone forever ! When bond0 is made 'up' again, ++ * the ar231x_open () does not call request_irq (). Worse, ++ * the call to ar231x_halt() generates a WDOG reset due to ++ * the write to 'sp->int_regs' and the box reboots. ++ * Commenting this out is good since it allows the ++ * system to resume when bond0 is made up again. ++ */ ++static int ar231x_close(struct net_device *dev) ++{ ++#if 0 ++ /* ++ * Disable interrupts ++ */ ++ disable_irq(dev->irq); ++ ++ /* ++ * Without (or before) releasing irq and stopping hardware, this ++ * is an absolute non-sense, by the way. It will be reset instantly ++ * by the first irq. ++ */ ++ netif_stop_queue(dev); ++ ++ /* stop the MAC and DMA engines */ ++ ar231x_halt(dev); ++ ++ /* release the interrupt */ ++ free_irq(dev->irq, dev); ++ ++#endif ++ return 0; ++} ++ ++static int ar231x_start_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ ar231x_descr_t *td; ++ u32 idx; ++ ++ idx = sp->tx_prd; ++ td = &sp->tx_ring[idx]; ++ ++ if (td->status & DMA_TX_OWN) { ++ /* free skbuf and lie to the caller that we sent it out */ ++ dev->stats.tx_dropped++; ++ dev_kfree_skb(skb); ++ ++ /* restart transmitter in case locked */ ++ sp->dma_regs->xmt_poll = 0; ++ return 0; ++ } ++ ++ /* Setup the transmit descriptor. */ ++ td->devcs = ((skb->len << DMA_TX1_BSIZE_SHIFT) | ++ (DMA_TX1_LS | DMA_TX1_IC | DMA_TX1_CHAINED)); ++ td->addr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE); ++ td->status = DMA_TX_OWN; ++ ++ /* kick transmitter last */ ++ sp->dma_regs->xmt_poll = 0; ++ ++ sp->tx_skb[idx] = skb; ++ idx = DSC_NEXT(idx); ++ sp->tx_prd = idx; ++ ++ return 0; ++} ++ ++static int ar231x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ struct mii_ioctl_data *data = (struct mii_ioctl_data *) &ifr->ifr_data; ++ struct ar231x_private *sp = netdev_priv(dev); ++ int ret; ++ ++ switch (cmd) { ++ ++ case SIOCETHTOOL: ++ spin_lock_irq(&sp->lock); ++ ret = phy_ethtool_ioctl(sp->phy_dev, (void *) ifr->ifr_data); ++ spin_unlock_irq(&sp->lock); ++ return ret; ++ ++ case SIOCSIFHWADDR: ++ if (copy_from_user ++ (dev->dev_addr, ifr->ifr_data, sizeof(dev->dev_addr))) ++ return -EFAULT; ++ return 0; ++ ++ case SIOCGIFHWADDR: ++ if (copy_to_user ++ (ifr->ifr_data, dev->dev_addr, sizeof(dev->dev_addr))) ++ return -EFAULT; ++ return 0; ++ ++ case SIOCGMIIPHY: ++ case SIOCGMIIREG: ++ case SIOCSMIIREG: ++ return phy_mii_ioctl(sp->phy_dev, data, cmd); ++ ++ default: ++ break; ++ } ++ ++ return -EOPNOTSUPP; ++} ++ ++static void ar231x_adjust_link(struct net_device *dev) ++{ ++ struct ar231x_private *sp = netdev_priv(dev); ++ unsigned int mc; ++ ++ if (!sp->phy_dev->link) ++ return; ++ ++ if (sp->phy_dev->duplex != sp->oldduplex) { ++ mc = readl(&sp->eth_regs->mac_control); ++ mc &= ~(MAC_CONTROL_F | MAC_CONTROL_DRO); ++ if (sp->phy_dev->duplex) ++ mc |= MAC_CONTROL_F; ++ else ++ mc |= MAC_CONTROL_DRO; ++ writel(mc, &sp->eth_regs->mac_control); ++ sp->oldduplex = sp->phy_dev->duplex; ++ } ++} ++ ++#define MII_ADDR(phy, reg) \ ++ ((reg << MII_ADDR_REG_SHIFT) | (phy << MII_ADDR_PHY_SHIFT)) ++ ++static int ++ar231x_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum) ++{ ++ struct net_device *const dev = bus->priv; ++ struct ar231x_private *sp = netdev_priv(dev); ++ volatile ETHERNET_STRUCT *ethernet = sp->phy_regs; ++ ++ ethernet->mii_addr = MII_ADDR(phy_addr, regnum); ++ while (ethernet->mii_addr & MII_ADDR_BUSY); ++ return (ethernet->mii_data >> MII_DATA_SHIFT); ++} ++ ++static int ++ar231x_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, ++ u16 value) ++{ ++ struct net_device *const dev = bus->priv; ++ struct ar231x_private *sp = netdev_priv(dev); ++ volatile ETHERNET_STRUCT *ethernet = sp->phy_regs; ++ ++ while (ethernet->mii_addr & MII_ADDR_BUSY); ++ ethernet->mii_data = value << MII_DATA_SHIFT; ++ ethernet->mii_addr = MII_ADDR(phy_addr, regnum) | MII_ADDR_WRITE; ++ ++ return 0; ++} ++ ++static int ar231x_mdiobus_reset(struct mii_bus *bus) ++{ ++ struct net_device *const dev = bus->priv; ++ ++ ar231x_reset_reg(dev); ++ ++ return 0; ++} ++ ++static int ar231x_mdiobus_probe (struct net_device *dev) ++{ ++ struct ar231x_private *const sp = netdev_priv(dev); ++ struct phy_device *phydev = NULL; ++ int phy_addr; ++ ++ /* find the first (lowest address) PHY on the current MAC's MII bus */ ++ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) ++ if (sp->mii_bus->phy_map[phy_addr]) { ++ phydev = sp->mii_bus->phy_map[phy_addr]; ++ sp->phy = phy_addr; ++ break; /* break out with first one found */ ++ } ++ ++ if (!phydev) { ++ printk (KERN_ERR "ar231x: %s: no PHY found\n", dev->name); ++ return -1; ++ } ++ ++ /* now we are supposed to have a proper phydev, to attach to... */ ++ BUG_ON(!phydev); ++ BUG_ON(phydev->attached_dev); ++ ++ phydev = phy_connect(dev, dev_name(&phydev->dev), &ar231x_adjust_link, 0, ++ PHY_INTERFACE_MODE_MII); ++ ++ if (IS_ERR(phydev)) { ++ printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); ++ return PTR_ERR(phydev); ++ } ++ ++ /* mask with MAC supported features */ ++ phydev->supported &= (SUPPORTED_10baseT_Half ++ | SUPPORTED_10baseT_Full ++ | SUPPORTED_100baseT_Half ++ | SUPPORTED_100baseT_Full ++ | SUPPORTED_Autoneg ++ /* | SUPPORTED_Pause | SUPPORTED_Asym_Pause */ ++ | SUPPORTED_MII ++ | SUPPORTED_TP); ++ ++ phydev->advertising = phydev->supported; ++ ++ sp->oldduplex = -1; ++ sp->phy_dev = phydev; ++ ++ printk(KERN_INFO "%s: attached PHY driver [%s] " ++ "(mii_bus:phy_addr=%s)\n", ++ dev->name, phydev->drv->name, dev_name(&phydev->dev)); ++ ++ return 0; ++} ++ +diff -Nur linux-2.6.39-rc7.orig/drivers/net/ar231x.h linux-2.6.39-rc7/drivers/net/ar231x.h +--- linux-2.6.39-rc7.orig/drivers/net/ar231x.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/drivers/net/ar231x.h 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,302 @@ ++/* ++ * ar231x.h: Linux driver for the Atheros AR231x Ethernet device. ++ * ++ * Copyright (C) 2004 by Sameer Dekate <sdekate@arubanetworks.com> ++ * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2006-2009 Felix Fietkau <nbd@openwrt.org> ++ * ++ * Thanks to Atheros for providing hardware and documentation ++ * enabling me to write this driver. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#ifndef _AR2313_H_ ++#define _AR2313_H_ ++ ++#include <generated/autoconf.h> ++#include <linux/bitops.h> ++#include <asm/bootinfo.h> ++#include <ar231x_platform.h> ++ ++/* ++ * probe link timer - 5 secs ++ */ ++#define LINK_TIMER (5*HZ) ++ ++#define IS_DMA_TX_INT(X) (((X) & (DMA_STATUS_TI)) != 0) ++#define IS_DMA_RX_INT(X) (((X) & (DMA_STATUS_RI)) != 0) ++#define IS_DRIVER_OWNED(X) (((X) & (DMA_TX_OWN)) == 0) ++ ++#define AR2313_TX_TIMEOUT (HZ/4) ++ ++/* ++ * Rings ++ */ ++#define DSC_RING_ENTRIES_SIZE (AR2313_DESCR_ENTRIES * sizeof(struct desc)) ++#define DSC_NEXT(idx) ((idx + 1) & (AR2313_DESCR_ENTRIES - 1)) ++ ++#define AR2313_MBGET 2 ++#define AR2313_MBSET 3 ++#define AR2313_PCI_RECONFIG 4 ++#define AR2313_PCI_DUMP 5 ++#define AR2313_TEST_PANIC 6 ++#define AR2313_TEST_NULLPTR 7 ++#define AR2313_READ_DATA 8 ++#define AR2313_WRITE_DATA 9 ++#define AR2313_GET_VERSION 10 ++#define AR2313_TEST_HANG 11 ++#define AR2313_SYNC 12 ++ ++#define DMA_RX_ERR_CRC BIT(1) ++#define DMA_RX_ERR_DRIB BIT(2) ++#define DMA_RX_ERR_MII BIT(3) ++#define DMA_RX_EV2 BIT(5) ++#define DMA_RX_ERR_COL BIT(6) ++#define DMA_RX_LONG BIT(7) ++#define DMA_RX_LS BIT(8) /* last descriptor */ ++#define DMA_RX_FS BIT(9) /* first descriptor */ ++#define DMA_RX_MF BIT(10) /* multicast frame */ ++#define DMA_RX_ERR_RUNT BIT(11) /* runt frame */ ++#define DMA_RX_ERR_LENGTH BIT(12) /* length error */ ++#define DMA_RX_ERR_DESC BIT(14) /* descriptor error */ ++#define DMA_RX_ERROR BIT(15) /* error summary */ ++#define DMA_RX_LEN_MASK 0x3fff0000 ++#define DMA_RX_LEN_SHIFT 16 ++#define DMA_RX_FILT BIT(30) ++#define DMA_RX_OWN BIT(31) /* desc owned by DMA controller */ ++ ++#define DMA_RX1_BSIZE_MASK 0x000007ff ++#define DMA_RX1_BSIZE_SHIFT 0 ++#define DMA_RX1_CHAINED BIT(24) ++#define DMA_RX1_RER BIT(25) ++ ++#define DMA_TX_ERR_UNDER BIT(1) /* underflow error */ ++#define DMA_TX_ERR_DEFER BIT(2) /* excessive deferral */ ++#define DMA_TX_COL_MASK 0x78 ++#define DMA_TX_COL_SHIFT 3 ++#define DMA_TX_ERR_HB BIT(7) /* hearbeat failure */ ++#define DMA_TX_ERR_COL BIT(8) /* excessive collisions */ ++#define DMA_TX_ERR_LATE BIT(9) /* late collision */ ++#define DMA_TX_ERR_LINK BIT(10) /* no carrier */ ++#define DMA_TX_ERR_LOSS BIT(11) /* loss of carrier */ ++#define DMA_TX_ERR_JABBER BIT(14) /* transmit jabber timeout */ ++#define DMA_TX_ERROR BIT(15) /* frame aborted */ ++#define DMA_TX_OWN BIT(31) /* descr owned by DMA controller */ ++ ++#define DMA_TX1_BSIZE_MASK 0x000007ff ++#define DMA_TX1_BSIZE_SHIFT 0 ++#define DMA_TX1_CHAINED BIT(24) /* chained descriptors */ ++#define DMA_TX1_TER BIT(25) /* transmit end of ring */ ++#define DMA_TX1_FS BIT(29) /* first segment */ ++#define DMA_TX1_LS BIT(30) /* last segment */ ++#define DMA_TX1_IC BIT(31) /* interrupt on completion */ ++ ++#define RCVPKT_LENGTH(X) (X >> 16) /* Received pkt Length */ ++ ++#define MAC_CONTROL_RE BIT(2) /* receive enable */ ++#define MAC_CONTROL_TE BIT(3) /* transmit enable */ ++#define MAC_CONTROL_DC BIT(5) /* Deferral check */ ++#define MAC_CONTROL_ASTP BIT(8) /* Auto pad strip */ ++#define MAC_CONTROL_DRTY BIT(10) /* Disable retry */ ++#define MAC_CONTROL_DBF BIT(11) /* Disable bcast frames */ ++#define MAC_CONTROL_LCC BIT(12) /* late collision ctrl */ ++#define MAC_CONTROL_HP BIT(13) /* Hash Perfect filtering */ ++#define MAC_CONTROL_HASH BIT(14) /* Unicast hash filtering */ ++#define MAC_CONTROL_HO BIT(15) /* Hash only filtering */ ++#define MAC_CONTROL_PB BIT(16) /* Pass Bad frames */ ++#define MAC_CONTROL_IF BIT(17) /* Inverse filtering */ ++#define MAC_CONTROL_PR BIT(18) /* promiscuous mode (valid frames only) */ ++#define MAC_CONTROL_PM BIT(19) /* pass multicast */ ++#define MAC_CONTROL_F BIT(20) /* full-duplex */ ++#define MAC_CONTROL_DRO BIT(23) /* Disable Receive Own */ ++#define MAC_CONTROL_HBD BIT(28) /* heart-beat disabled (MUST BE SET) */ ++#define MAC_CONTROL_BLE BIT(30) /* big endian mode */ ++#define MAC_CONTROL_RA BIT(31) /* receive all (valid and invalid frames) */ ++ ++#define MII_ADDR_BUSY BIT(0) ++#define MII_ADDR_WRITE BIT(1) ++#define MII_ADDR_REG_SHIFT 6 ++#define MII_ADDR_PHY_SHIFT 11 ++#define MII_DATA_SHIFT 0 ++ ++#define FLOW_CONTROL_FCE BIT(1) ++ ++#define DMA_BUS_MODE_SWR BIT(0) /* software reset */ ++#define DMA_BUS_MODE_BLE BIT(7) /* big endian mode */ ++#define DMA_BUS_MODE_PBL_SHIFT 8 /* programmable burst length 32 */ ++#define DMA_BUS_MODE_DBO BIT(20) /* big-endian descriptors */ ++ ++#define DMA_STATUS_TI BIT(0) /* transmit interrupt */ ++#define DMA_STATUS_TPS BIT(1) /* transmit process stopped */ ++#define DMA_STATUS_TU BIT(2) /* transmit buffer unavailable */ ++#define DMA_STATUS_TJT BIT(3) /* transmit buffer timeout */ ++#define DMA_STATUS_UNF BIT(5) /* transmit underflow */ ++#define DMA_STATUS_RI BIT(6) /* receive interrupt */ ++#define DMA_STATUS_RU BIT(7) /* receive buffer unavailable */ ++#define DMA_STATUS_RPS BIT(8) /* receive process stopped */ ++#define DMA_STATUS_ETI BIT(10) /* early transmit interrupt */ ++#define DMA_STATUS_FBE BIT(13) /* fatal bus interrupt */ ++#define DMA_STATUS_ERI BIT(14) /* early receive interrupt */ ++#define DMA_STATUS_AIS BIT(15) /* abnormal interrupt summary */ ++#define DMA_STATUS_NIS BIT(16) /* normal interrupt summary */ ++#define DMA_STATUS_RS_SHIFT 17 /* receive process state */ ++#define DMA_STATUS_TS_SHIFT 20 /* transmit process state */ ++#define DMA_STATUS_EB_SHIFT 23 /* error bits */ ++ ++#define DMA_CONTROL_SR BIT(1) /* start receive */ ++#define DMA_CONTROL_ST BIT(13) /* start transmit */ ++#define DMA_CONTROL_SF BIT(21) /* store and forward */ ++ ++ ++typedef struct { ++ volatile unsigned int status; // OWN, Device control and status. ++ volatile unsigned int devcs; // pkt Control bits + Length ++ volatile unsigned int addr; // Current Address. ++ volatile unsigned int descr; // Next descriptor in chain. ++} ar231x_descr_t; ++ ++ ++ ++// ++// New Combo structure for Both Eth0 AND eth1 ++// ++typedef struct { ++ volatile unsigned int mac_control; /* 0x00 */ ++ volatile unsigned int mac_addr[2]; /* 0x04 - 0x08 */ ++ volatile unsigned int mcast_table[2]; /* 0x0c - 0x10 */ ++ volatile unsigned int mii_addr; /* 0x14 */ ++ volatile unsigned int mii_data; /* 0x18 */ ++ volatile unsigned int flow_control; /* 0x1c */ ++ volatile unsigned int vlan_tag; /* 0x20 */ ++ volatile unsigned int pad[7]; /* 0x24 - 0x3c */ ++ volatile unsigned int ucast_table[8]; /* 0x40-0x5c */ ++ ++} ETHERNET_STRUCT; ++ ++/******************************************************************** ++ * Interrupt controller ++ ********************************************************************/ ++ ++typedef struct { ++ volatile unsigned int wdog_control; /* 0x08 */ ++ volatile unsigned int wdog_timer; /* 0x0c */ ++ volatile unsigned int misc_status; /* 0x10 */ ++ volatile unsigned int misc_mask; /* 0x14 */ ++ volatile unsigned int global_status; /* 0x18 */ ++ volatile unsigned int reserved; /* 0x1c */ ++ volatile unsigned int reset_control; /* 0x20 */ ++} INTERRUPT; ++ ++/******************************************************************** ++ * DMA controller ++ ********************************************************************/ ++typedef struct { ++ volatile unsigned int bus_mode; /* 0x00 (CSR0) */ ++ volatile unsigned int xmt_poll; /* 0x04 (CSR1) */ ++ volatile unsigned int rcv_poll; /* 0x08 (CSR2) */ ++ volatile unsigned int rcv_base; /* 0x0c (CSR3) */ ++ volatile unsigned int xmt_base; /* 0x10 (CSR4) */ ++ volatile unsigned int status; /* 0x14 (CSR5) */ ++ volatile unsigned int control; /* 0x18 (CSR6) */ ++ volatile unsigned int intr_ena; /* 0x1c (CSR7) */ ++ volatile unsigned int rcv_missed; /* 0x20 (CSR8) */ ++ volatile unsigned int reserved[11]; /* 0x24-0x4c (CSR9-19) */ ++ volatile unsigned int cur_tx_buf_addr; /* 0x50 (CSR20) */ ++ volatile unsigned int cur_rx_buf_addr; /* 0x50 (CSR21) */ ++} DMA; ++ ++/* ++ * Struct private for the Sibyte. ++ * ++ * Elements are grouped so variables used by the tx handling goes ++ * together, and will go into the same cache lines etc. in order to ++ * avoid cache line contention between the rx and tx handling on SMP. ++ * ++ * Frequently accessed variables are put at the beginning of the ++ * struct to help the compiler generate better/shorter code. ++ */ ++struct ar231x_private { ++ struct net_device *dev; ++ int version; ++ u32 mb[2]; ++ ++ volatile ETHERNET_STRUCT *phy_regs; ++ volatile ETHERNET_STRUCT *eth_regs; ++ volatile DMA *dma_regs; ++ volatile u32 *int_regs; ++ struct ar231x_eth *cfg; ++ ++ spinlock_t lock; /* Serialise access to device */ ++ ++ /* ++ * RX and TX descriptors, must be adjacent ++ */ ++ ar231x_descr_t *rx_ring; ++ ar231x_descr_t *tx_ring; ++ ++ ++ struct sk_buff **rx_skb; ++ struct sk_buff **tx_skb; ++ ++ /* ++ * RX elements ++ */ ++ u32 rx_skbprd; ++ u32 cur_rx; ++ ++ /* ++ * TX elements ++ */ ++ u32 tx_prd; ++ u32 tx_csm; ++ ++ /* ++ * Misc elements ++ */ ++ char name[48]; ++ struct { ++ u32 address; ++ u32 length; ++ char *mapping; ++ } desc; ++ ++ ++ struct timer_list link_timer; ++ unsigned short phy; /* merlot phy = 1, samsung phy = 0x1f */ ++ unsigned short mac; ++ unsigned short link; /* 0 - link down, 1 - link up */ ++ u16 phyData; ++ ++ struct tasklet_struct rx_tasklet; ++ int unloading; ++ ++ struct phy_device *phy_dev; ++ struct mii_bus *mii_bus; ++ int oldduplex; ++}; ++ ++ ++/* ++ * Prototypes ++ */ ++static int ar231x_init(struct net_device *dev); ++#ifdef TX_TIMEOUT ++static void ar231x_tx_timeout(struct net_device *dev); ++#endif ++static int ar231x_restart(struct net_device *dev); ++static void ar231x_load_rx_ring(struct net_device *dev, int bufs); ++static irqreturn_t ar231x_interrupt(int irq, void *dev_id); ++static int ar231x_open(struct net_device *dev); ++static int ar231x_start_xmit(struct sk_buff *skb, struct net_device *dev); ++static int ar231x_close(struct net_device *dev); ++static int ar231x_ioctl(struct net_device *dev, struct ifreq *ifr, ++ int cmd); ++static void ar231x_init_cleanup(struct net_device *dev); ++static int ar231x_setup_timer(struct net_device *dev); ++static void ar231x_link_timer_fn(unsigned long data); ++static void ar231x_check_link(struct net_device *dev); ++#endif /* _AR2313_H_ */ +diff -Nur linux-2.6.39-rc7.orig/drivers/watchdog/Kconfig linux-2.6.39-rc7/drivers/watchdog/Kconfig +--- linux-2.6.39-rc7.orig/drivers/watchdog/Kconfig 2011-05-10 04:33:54.000000000 +0200 ++++ linux-2.6.39-rc7/drivers/watchdog/Kconfig 2011-05-15 21:34:57.000000000 +0200 +@@ -990,6 +990,12 @@ + To compile this driver as a loadable module, choose M here. + The module will be called bcm63xx_wdt. + ++config ATHEROS_WDT ++ tristate "Atheros wisoc Watchdog Timer" ++ depends on ATHEROS_AR231X ++ help ++ Hardware driver for the Atheros wisoc Watchdog Timer. ++ + # PARISC Architecture + + # POWERPC Architecture +diff -Nur linux-2.6.39-rc7.orig/drivers/watchdog/Makefile linux-2.6.39-rc7/drivers/watchdog/Makefile +--- linux-2.6.39-rc7.orig/drivers/watchdog/Makefile 2011-05-10 04:33:54.000000000 +0200 ++++ linux-2.6.39-rc7/drivers/watchdog/Makefile 2011-05-15 21:34:57.000000000 +0200 +@@ -120,6 +120,7 @@ + obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o + obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o + obj-$(CONFIG_AR7_WDT) += ar7_wdt.o ++obj-$(CONFIG_ATHEROS_WDT) += ar2315-wtd.o + obj-$(CONFIG_TXX9_WDT) += txx9wdt.o + obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o + octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o +diff -Nur linux-2.6.39-rc7.orig/drivers/watchdog/ar2315-wtd.c linux-2.6.39-rc7/drivers/watchdog/ar2315-wtd.c +--- linux-2.6.39-rc7.orig/drivers/watchdog/ar2315-wtd.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39-rc7/drivers/watchdog/ar2315-wtd.c 2011-05-15 21:34:57.000000000 +0200 +@@ -0,0 +1,200 @@ ++/* ++ * 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 ++ * ++ * Copyright (C) 2008 John Crispin <blogic@openwrt.org> ++ * Based on EP93xx and ifxmips wdt driver ++ */ ++ ++#include <linux/interrupt.h> ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/types.h> ++#include <linux/miscdevice.h> ++#include <linux/watchdog.h> ++#include <linux/fs.h> ++#include <linux/ioport.h> ++#include <linux/notifier.h> ++#include <linux/reboot.h> ++#include <linux/init.h> ++#include <linux/platform_device.h> ++ ++#include <asm/io.h> ++#include <asm/uaccess.h> ++#include <asm/system.h> ++#include <asm/addrspace.h> ++#include <ar231x_platform.h> ++#include <ar2315_regs.h> ++#include <ar231x.h> ++ ++#define CLOCK_RATE 40000000 ++#define HEARTBEAT(x) (x < 1 || x > 90)?(20):(x) ++ ++static int wdt_timeout = 20; ++static int started = 0; ++static int in_use = 0; ++ ++static void ++ar2315_wdt_enable(void) ++{ ++ ar231x_write_reg(AR2315_WD, wdt_timeout * CLOCK_RATE); ++ ar231x_write_reg(AR2315_ISR, 0x80); ++} ++ ++static ssize_t ++ar2315_wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) ++{ ++ if(len) ++ ar2315_wdt_enable(); ++ return len; ++} ++ ++static int ++ar2315_wdt_open(struct inode *inode, struct file *file) ++{ ++ if(in_use) ++ return -EBUSY; ++ ar2315_wdt_enable(); ++ in_use = started = 1; ++ return nonseekable_open(inode, file); ++} ++ ++static int ++ar2315_wdt_release(struct inode *inode, struct file *file) ++{ ++ in_use = 0; ++ return 0; ++} ++ ++static irqreturn_t ++ar2315_wdt_interrupt(int irq, void *dev_id) ++{ ++ if(started) ++ { ++ printk(KERN_CRIT "watchdog expired, rebooting system\n"); ++ emergency_restart(); ++ } else { ++ ar231x_write_reg(AR2315_WDC, 0); ++ ar231x_write_reg(AR2315_WD, 0); ++ ar231x_write_reg(AR2315_ISR, 0x80); ++ } ++ return IRQ_HANDLED; ++} ++ ++static struct watchdog_info ident = { ++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, ++ .identity = "ar2315 Watchdog", ++}; ++ ++static int ++ar2315_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) ++{ ++ int new_wdt_timeout; ++ int ret = -ENOIOCTLCMD; ++ ++ switch(cmd) ++ { ++ case WDIOC_GETSUPPORT: ++ ret = copy_to_user((struct watchdog_info __user *)arg, &ident, sizeof(ident)) ? -EFAULT : 0; ++ break; ++ ++ case WDIOC_KEEPALIVE: ++ ar2315_wdt_enable(); ++ ret = 0; ++ break; ++ ++ case WDIOC_SETTIMEOUT: ++ if((ret = get_user(new_wdt_timeout, (int __user *)arg))) ++ break; ++ wdt_timeout = HEARTBEAT(new_wdt_timeout); ++ ar2315_wdt_enable(); ++ break; ++ ++ case WDIOC_GETTIMEOUT: ++ ret = put_user(wdt_timeout, (int __user *)arg); ++ break; ++ } ++ return ret; ++} ++ ++static struct file_operations ar2315_wdt_fops = { ++ .owner = THIS_MODULE, ++ .llseek = no_llseek, ++ .write = ar2315_wdt_write, ++ .unlocked_ioctl = ar2315_wdt_ioctl, ++ .open = ar2315_wdt_open, ++ .release = ar2315_wdt_release, ++}; ++ ++static struct miscdevice ar2315_wdt_miscdev = { ++ .minor = WATCHDOG_MINOR, ++ .name = "watchdog", ++ .fops = &ar2315_wdt_fops, ++}; ++ ++static int ++ar2315_wdt_probe(struct platform_device *dev) ++{ ++ int ret = 0; ++ ++ ar2315_wdt_enable(); ++ ret = request_irq(AR531X_MISC_IRQ_WATCHDOG, ar2315_wdt_interrupt, IRQF_DISABLED, "ar2315_wdt", NULL); ++ if(ret) ++ { ++ printk(KERN_ERR "ar2315wdt: failed to register inetrrupt\n"); ++ goto out; ++ } ++ ++ ret = misc_register(&ar2315_wdt_miscdev); ++ if(ret) ++ printk(KERN_ERR "ar2315wdt: failed to register miscdev\n"); ++ ++out: ++ return ret; ++} ++ ++static int ++ar2315_wdt_remove(struct platform_device *dev) ++{ ++ misc_deregister(&ar2315_wdt_miscdev); ++ free_irq(AR531X_MISC_IRQ_WATCHDOG, NULL); ++ return 0; ++} ++ ++static struct platform_driver ar2315_wdt_driver = { ++ .probe = ar2315_wdt_probe, ++ .remove = ar2315_wdt_remove, ++ .driver = { ++ .name = "ar2315_wdt", ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init ++init_ar2315_wdt(void) ++{ ++ int ret = platform_driver_register(&ar2315_wdt_driver); ++ if(ret) ++ printk(KERN_INFO "ar2315_wdt: error registering platfom driver!"); ++ return ret; ++} ++ ++static void __exit ++exit_ar2315_wdt(void) ++{ ++ platform_driver_unregister(&ar2315_wdt_driver); ++} ++ ++module_init(init_ar2315_wdt); ++module_exit(exit_ar2315_wdt); diff --git a/target/linux/patches/2.6.39/mmc-host.patch b/target/linux/patches/2.6.39/mmc-host.patch new file mode 100644 index 000000000..3d0e37add --- /dev/null +++ b/target/linux/patches/2.6.39/mmc-host.patch @@ -0,0 +1,36 @@ +diff -Nur linux-2.6.39-rc6.orig/drivers/mmc/host/Kconfig linux-2.6.39-rc6/drivers/mmc/host/Kconfig +--- linux-2.6.39-rc6.orig/drivers/mmc/host/Kconfig 2011-05-04 04:59:13.000000000 +0200 ++++ linux-2.6.39-rc6/drivers/mmc/host/Kconfig 2011-05-10 23:39:01.000000000 +0200 +@@ -253,13 +253,6 @@ + + If unsure, say N. + +-choice +- prompt "Atmel SD/MMC Driver" +- depends on AVR32 || ARCH_AT91 +- default MMC_ATMELMCI if AVR32 +- help +- Choose which driver to use for the Atmel MCI Silicon +- + config MMC_AT91 + tristate "AT91 SD/MMC Card Interface support" + depends on ARCH_AT91 +@@ -268,18 +261,6 @@ + + If unsure, say N. + +-config MMC_ATMELMCI +- tristate "Atmel Multimedia Card Interface support" +- depends on AVR32 || ARCH_AT91 +- help +- This selects the Atmel Multimedia Card Interface driver. If +- you have an AT32 (AVR32) or AT91 platform with a Multimedia +- Card slot, say Y or M here. +- +- If unsure, say N. +- +-endchoice +- + config MMC_ATMELMCI_DMA + bool "Atmel MCI DMA support (EXPERIMENTAL)" + depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE && EXPERIMENTAL diff --git a/target/linux/patches/2.6.39/non-static.patch b/target/linux/patches/2.6.39/non-static.patch new file mode 100644 index 000000000..a967703d0 --- /dev/null +++ b/target/linux/patches/2.6.39/non-static.patch @@ -0,0 +1,33 @@ +diff -Nur linux-2.6.39-rc6.orig/fs/namei.c linux-2.6.39-rc6/fs/namei.c +--- linux-2.6.39-rc6.orig/fs/namei.c 2011-05-04 04:59:13.000000000 +0200 ++++ linux-2.6.39-rc6/fs/namei.c 2011-05-05 11:30:14.000000000 +0200 +@@ -1769,7 +1769,7 @@ + * needs parent already locked. Doesn't follow mounts. + * SMP-safe. + */ +-static struct dentry *lookup_hash(struct nameidata *nd) ++struct dentry *lookup_hash(struct nameidata *nd) + { + return __lookup_hash(&nd->last, nd->path.dentry, nd); + } +diff -Nur linux-2.6.39-rc6.orig/fs/splice.c linux-2.6.39-rc6/fs/splice.c +--- linux-2.6.39-rc6.orig/fs/splice.c 2011-05-04 04:59:13.000000000 +0200 ++++ linux-2.6.39-rc6/fs/splice.c 2011-05-05 11:31:04.000000000 +0200 +@@ -1081,7 +1081,7 @@ + /* + * Attempt to initiate a splice from pipe to file. + */ +-static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, ++long do_splice_from(struct pipe_inode_info *pipe, struct file *out, + loff_t *ppos, size_t len, unsigned int flags) + { + ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, +@@ -1109,7 +1109,7 @@ + /* + * Attempt to initiate a splice from a file to a pipe. + */ +-static long do_splice_to(struct file *in, loff_t *ppos, ++long do_splice_to(struct file *in, loff_t *ppos, + struct pipe_inode_info *pipe, size_t len, + unsigned int flags) + { diff --git a/target/linux/patches/2.6.39/rb4xx.patch b/target/linux/patches/2.6.39/rb4xx.patch new file mode 100644 index 000000000..1739221bf --- /dev/null +++ b/target/linux/patches/2.6.39/rb4xx.patch @@ -0,0 +1,18430 @@ +diff -Nur linux-2.6.39.orig/arch/mips/Kconfig linux-2.6.39/arch/mips/Kconfig +--- linux-2.6.39.orig/arch/mips/Kconfig 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/arch/mips/Kconfig 2011-05-27 14:36:50.000000000 +0200 +@@ -84,6 +84,23 @@ + help + Support for the Atheros AR71XX/AR724X/AR913X SoCs. + ++config ATHEROS_AR71XX ++ bool "Atheros AR71xx based boards" ++ select CEVT_R4K ++ select CSRC_R4K ++ select DMA_NONCOHERENT ++ select HW_HAS_PCI ++ select IRQ_CPU ++ select ARCH_REQUIRE_GPIOLIB ++ select SYS_HAS_CPU_MIPS32_R1 ++ select SYS_HAS_CPU_MIPS32_R2 ++ select SYS_SUPPORTS_32BIT_KERNEL ++ select SYS_SUPPORTS_BIG_ENDIAN ++ select SYS_HAS_EARLY_PRINTK ++ select MIPS_MACHINE ++ help ++ Support for Atheros AR71xx based boards. ++ + config BCM47XX + bool "Broadcom BCM47XX based boards" + select CEVT_R4K +@@ -740,6 +757,7 @@ + + source "arch/mips/alchemy/Kconfig" + source "arch/mips/ath79/Kconfig" ++source "arch/mips/ar71xx/Kconfig" + source "arch/mips/bcm63xx/Kconfig" + source "arch/mips/jazz/Kconfig" + source "arch/mips/jz4740/Kconfig" +diff -Nur linux-2.6.39.orig/arch/mips/Makefile linux-2.6.39/arch/mips/Makefile +--- linux-2.6.39.orig/arch/mips/Makefile 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/arch/mips/Makefile 2011-05-27 14:36:50.000000000 +0200 +@@ -158,6 +158,13 @@ + endif + cflags-$(CONFIG_CAVIUM_CN63XXP1) += -Wa,-mfix-cn63xxp1 + ++# ++# Atheros AR71xx ++# ++core-$(CONFIG_ATHEROS_AR71XX) += arch/mips/ar71xx/ ++cflags-$(CONFIG_ATHEROS_AR71XX) += -I$(srctree)/arch/mips/include/asm/mach-ar71xx ++load-$(CONFIG_ATHEROS_AR71XX) += 0xffffffff80060000 ++ + cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,) + cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,) + cflags-$(CONFIG_CPU_DADDI_WORKAROUNDS) += $(call cc-option,-mno-daddi,) +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/Kconfig linux-2.6.39/arch/mips/ar71xx/Kconfig +--- linux-2.6.39.orig/arch/mips/ar71xx/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/Kconfig 2011-05-27 14:36:50.000000000 +0200 +@@ -0,0 +1,264 @@ ++if ATHEROS_AR71XX ++ ++menu "Atheros AR71xx machine selection" ++ ++config AR71XX_MACH_AP81 ++ bool "Atheros AP81 board support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_AR913X_WMAC ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_DEV_USB ++ default n ++ ++config AR71XX_MACH_AP83 ++ bool "Atheros AP83 board support" ++ select AR71XX_DEV_AR913X_WMAC ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_DEV_USB ++ default n ++ ++config AR71XX_MACH_DIR_600_A1 ++ bool "D-Link DIR-600 rev. A1 support" ++ select AR71XX_DEV_AP91_ETH ++ select AR71XX_DEV_AP91_PCI if PCI ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_NVRAM ++ default n ++ ++config AR71XX_MACH_DIR_615_C1 ++ bool "D-Link DIR-615 rev. C1 support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_AR913X_WMAC ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_NVRAM ++ default n ++ ++config AR71XX_MACH_DIR_825_B1 ++ bool "D-Link DIR-825 rev. B1 board support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_AP94_PCI if PCI ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_DEV_USB ++ default n ++ ++config AR71XX_MACH_PB42 ++ bool "Atheros PB42 board support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_PB42_PCI if PCI ++ default n ++ ++config AR71XX_MACH_PB44 ++ bool "Atheros PB44 board support" ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_PB42_PCI if PCI ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_DEV_USB ++ default n ++ ++config AR71XX_MACH_PB92 ++ bool "Atheros PB92 board support" ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_PB9X_PCI if PCI ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_DEV_USB ++ default n ++ ++config AR71XX_MACH_AW_NR580 ++ bool "AzureWave AW-NR580 board support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_PB42_PCI if PCI ++ select AR71XX_DEV_LEDS_GPIO ++ default n ++ ++config AR71XX_MACH_WZR_HP_G300NH ++ bool "Buffalo WZR-HP-G300NH board support" ++ select AR71XX_DEV_AR913X_WMAC ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_DEV_USB ++ default y ++ ++config AR71XX_MACH_WP543 ++ bool "Compex WP543/WPJ543 board support" ++ select MYLOADER ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_PB42_PCI if PCI ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_DEV_USB ++ default n ++ ++config AR71XX_MACH_WRT160NL ++ bool "Linksys WRT160NL board support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_AR913X_WMAC ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_DEV_USB ++ select AR71XX_NVRAM ++ default n ++ ++config AR71XX_MACH_WRT400N ++ bool "Linksys WRT400N board support" ++ select AR71XX_DEV_AP94_PCI if PCI ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ default n ++ ++config AR71XX_MACH_RB4XX ++ bool "MikroTik RouterBOARD 4xx series support" ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_DEV_USB ++ default n ++ ++config AR71XX_MACH_RB750 ++ bool "MikroTik RouterBOARD 750 support" ++ select AR71XX_DEV_AP91_ETH ++ default n ++ ++config AR71XX_MACH_WNDR3700 ++ bool "NETGEAR WNDR3700 board support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_AP94_PCI if PCI ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_DEV_USB ++ default n ++ ++config AR71XX_MACH_WNR2000 ++ bool "NETGEAR WNR2000 board support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_AR913X_WMAC ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ default n ++ ++config AR71XX_MACH_MZK_W04NU ++ bool "Planex MZK-W04NU board support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_AR913X_WMAC ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_DEV_USB ++ default n ++ ++config AR71XX_MACH_MZK_W300NH ++ bool "Planex MZK-W300NH board support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_AR913X_WMAC ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ default n ++ ++config AR71XX_MACH_NBG460N ++ bool "Zyxel NBG460N/550N/550NH board support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_AR913X_WMAC ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ default n ++ ++config AR71XX_MACH_TL_WR741ND ++ bool "TP-LINK TL-WR741ND support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_AP91_ETH ++ select AR71XX_DEV_AP91_PCI if PCI ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ default n ++ ++config AR71XX_MACH_TL_WR841N_V1 ++ bool "TP-LINK TL-WR841N v1 support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_PB42_PCI if PCI ++ select AR71XX_DEV_DSA ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ default n ++ ++config AR71XX_MACH_TL_WR941ND ++ bool "TP-LINK TL-WR941ND support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_AR913X_WMAC ++ select AR71XX_DEV_DSA ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ default n ++ ++config AR71XX_MACH_TL_WR1043ND ++ bool "TP-LINK TL-WR1043ND support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_AR913X_WMAC ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_DEV_USB ++ default n ++ ++config AR71XX_MACH_TEW_632BRP ++ bool "TRENDnet TEW-632BRP support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_AR913X_WMAC ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_NVRAM ++ default n ++ ++config AR71XX_MACH_UBNT ++ bool "Ubiquiti AR71xx based boards support" ++ select AR71XX_DEV_M25P80 ++ select AR71XX_DEV_AP91_PCI if PCI ++ select AR71XX_DEV_GPIO_BUTTONS ++ select AR71XX_DEV_LEDS_GPIO ++ select AR71XX_DEV_PB42_PCI if PCI ++ select AR71XX_DEV_USB ++ default n ++ ++endmenu ++ ++config AR71XX_DEV_M25P80 ++ def_bool n ++ ++config AR71XX_DEV_AP91_PCI ++ def_bool n ++ ++config AR71XX_DEV_AP91_ETH ++ def_bool n ++ ++config AR71XX_DEV_AP94_PCI ++ def_bool n ++ ++config AR71XX_DEV_AR913X_WMAC ++ def_bool n ++ ++config AR71XX_DEV_DSA ++ def_bool n ++ ++config AR71XX_DEV_GPIO_BUTTONS ++ def_bool n ++ ++config AR71XX_DEV_LEDS_GPIO ++ def_bool n ++ ++config AR71XX_DEV_PB42_PCI ++ def_bool n ++ ++config AR71XX_DEV_PB9X_PCI ++ def_bool n ++ ++config AR71XX_DEV_USB ++ def_bool n ++ ++config AR71XX_NVRAM ++ def_bool n ++ ++endif +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/Makefile linux-2.6.39/arch/mips/ar71xx/Makefile +--- linux-2.6.39.orig/arch/mips/ar71xx/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/Makefile 2011-05-27 14:36:50.000000000 +0200 +@@ -0,0 +1,54 @@ ++# ++# Makefile for the Atheros AR71xx SoC specific parts of the kernel ++# ++# Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++# Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++# ++# This program is free software; you can redistribute it and/or modify it ++# under the terms of the GNU General Public License version 2 as published ++# by the Free Software Foundation. ++ ++obj-y := prom.o irq.o setup.o devices.o gpio.o ar71xx.o ++ ++obj-$(CONFIG_EARLY_PRINTK) += early_printk.o ++obj-$(CONFIG_PCI) += pci.o ++ ++obj-$(CONFIG_AR71XX_DEV_AP91_ETH) += dev-ap91-eth.o ++obj-$(CONFIG_AR71XX_DEV_AP91_PCI) += dev-ap91-pci.o ++obj-$(CONFIG_AR71XX_DEV_AP94_PCI) += dev-ap94-pci.o ++obj-$(CONFIG_AR71XX_DEV_AR913X_WMAC) += dev-ar913x-wmac.o ++obj-$(CONFIG_AR71XX_DEV_DSA) += dev-dsa.o ++obj-$(CONFIG_AR71XX_DEV_GPIO_BUTTONS) += dev-gpio-buttons.o ++obj-$(CONFIG_AR71XX_DEV_LEDS_GPIO) += dev-leds-gpio.o ++obj-$(CONFIG_AR71XX_DEV_M25P80) += dev-m25p80.o ++obj-$(CONFIG_AR71XX_DEV_PB42_PCI) += dev-pb42-pci.o ++obj-$(CONFIG_AR71XX_DEV_PB9X_PCI) += dev-pb9x-pci.o ++obj-$(CONFIG_AR71XX_DEV_USB) += dev-usb.o ++ ++obj-$(CONFIG_AR71XX_NVRAM) += nvram.o ++ ++obj-$(CONFIG_AR71XX_MACH_AP81) += mach-ap81.o ++obj-$(CONFIG_AR71XX_MACH_AP83) += mach-ap83.o ++obj-$(CONFIG_AR71XX_MACH_AW_NR580) += mach-aw-nr580.o ++obj-$(CONFIG_AR71XX_MACH_DIR_600_A1) += mach-dir-600-a1.o ++obj-$(CONFIG_AR71XX_MACH_DIR_615_C1) += mach-dir-615-c1.o ++obj-$(CONFIG_AR71XX_MACH_DIR_825_B1) += mach-dir-825-b1.o ++obj-$(CONFIG_AR71XX_MACH_MZK_W04NU) += mach-mzk-w04nu.o ++obj-$(CONFIG_AR71XX_MACH_MZK_W300NH) += mach-mzk-w300nh.o ++obj-$(CONFIG_AR71XX_MACH_NBG460N) += mach-nbg460n.o ++obj-$(CONFIG_AR71XX_MACH_PB42) += mach-pb42.o ++obj-$(CONFIG_AR71XX_MACH_PB44) += mach-pb44.o ++obj-$(CONFIG_AR71XX_MACH_PB92) += mach-pb92.o ++obj-$(CONFIG_AR71XX_MACH_RB4XX) += mach-rb4xx.o ++obj-$(CONFIG_AR71XX_MACH_RB750) += mach-rb750.o ++obj-$(CONFIG_AR71XX_MACH_TEW_632BRP) += mach-tew-632brp.o ++obj-$(CONFIG_AR71XX_MACH_TL_WR741ND) += mach-tl-wr741nd.o ++obj-$(CONFIG_AR71XX_MACH_TL_WR841N_V1) += mach-tl-wr841n.o ++obj-$(CONFIG_AR71XX_MACH_TL_WR941ND) += mach-tl-wr941nd.o ++obj-$(CONFIG_AR71XX_MACH_TL_WR1043ND) += mach-tl-wr1043nd.o ++obj-$(CONFIG_AR71XX_MACH_UBNT) += mach-ubnt.o ++obj-$(CONFIG_AR71XX_MACH_WNDR3700) += mach-wndr3700.o ++obj-$(CONFIG_AR71XX_MACH_WNR2000) += mach-wnr2000.o ++obj-$(CONFIG_AR71XX_MACH_WP543) += mach-wp543.o ++obj-$(CONFIG_AR71XX_MACH_WRT160NL) += mach-wrt160nl.o ++obj-$(CONFIG_AR71XX_MACH_WRT400N) += mach-wrt400n.o +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/ar71xx.c linux-2.6.39/arch/mips/ar71xx/ar71xx.c +--- linux-2.6.39.orig/arch/mips/ar71xx/ar71xx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/ar71xx.c 2011-05-27 14:36:50.000000000 +0200 +@@ -0,0 +1,177 @@ ++/* ++ * AR71xx SoC routines ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/mutex.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++static DEFINE_MUTEX(ar71xx_flash_mutex); ++ ++void __iomem *ar71xx_ddr_base; ++EXPORT_SYMBOL_GPL(ar71xx_ddr_base); ++ ++void __iomem *ar71xx_pll_base; ++EXPORT_SYMBOL_GPL(ar71xx_pll_base); ++ ++void __iomem *ar71xx_reset_base; ++EXPORT_SYMBOL_GPL(ar71xx_reset_base); ++ ++void __iomem *ar71xx_gpio_base; ++EXPORT_SYMBOL_GPL(ar71xx_gpio_base); ++ ++void __iomem *ar71xx_usb_ctrl_base; ++EXPORT_SYMBOL_GPL(ar71xx_usb_ctrl_base); ++ ++void ar71xx_device_stop(u32 mask) ++{ ++ unsigned long flags; ++ u32 mask_inv; ++ u32 t; ++ ++ switch (ar71xx_soc) { ++ case AR71XX_SOC_AR7130: ++ case AR71XX_SOC_AR7141: ++ case AR71XX_SOC_AR7161: ++ local_irq_save(flags); ++ t = ar71xx_reset_rr(AR71XX_RESET_REG_RESET_MODULE); ++ ar71xx_reset_wr(AR71XX_RESET_REG_RESET_MODULE, t | mask); ++ local_irq_restore(flags); ++ break; ++ ++ case AR71XX_SOC_AR7240: ++ case AR71XX_SOC_AR7241: ++ case AR71XX_SOC_AR7242: ++ mask_inv = mask & RESET_MODULE_USB_OHCI_DLL_7240; ++ local_irq_save(flags); ++ t = ar71xx_reset_rr(AR724X_RESET_REG_RESET_MODULE); ++ t |= mask; ++ t &= ~mask_inv; ++ ar71xx_reset_wr(AR724X_RESET_REG_RESET_MODULE, t); ++ local_irq_restore(flags); ++ break; ++ ++ case AR71XX_SOC_AR9130: ++ case AR71XX_SOC_AR9132: ++ local_irq_save(flags); ++ t = ar71xx_reset_rr(AR91XX_RESET_REG_RESET_MODULE); ++ ar71xx_reset_wr(AR91XX_RESET_REG_RESET_MODULE, t | mask); ++ local_irq_restore(flags); ++ break; ++ ++ default: ++ BUG(); ++ } ++} ++EXPORT_SYMBOL_GPL(ar71xx_device_stop); ++ ++void ar71xx_device_start(u32 mask) ++{ ++ unsigned long flags; ++ u32 mask_inv; ++ u32 t; ++ ++ switch (ar71xx_soc) { ++ case AR71XX_SOC_AR7130: ++ case AR71XX_SOC_AR7141: ++ case AR71XX_SOC_AR7161: ++ local_irq_save(flags); ++ t = ar71xx_reset_rr(AR71XX_RESET_REG_RESET_MODULE); ++ ar71xx_reset_wr(AR71XX_RESET_REG_RESET_MODULE, t & ~mask); ++ local_irq_restore(flags); ++ break; ++ ++ case AR71XX_SOC_AR7240: ++ case AR71XX_SOC_AR7241: ++ case AR71XX_SOC_AR7242: ++ mask_inv = mask & RESET_MODULE_USB_OHCI_DLL_7240; ++ local_irq_save(flags); ++ t = ar71xx_reset_rr(AR724X_RESET_REG_RESET_MODULE); ++ t &= ~mask; ++ t |= mask_inv; ++ ar71xx_reset_wr(AR724X_RESET_REG_RESET_MODULE, t); ++ local_irq_restore(flags); ++ break; ++ ++ case AR71XX_SOC_AR9130: ++ case AR71XX_SOC_AR9132: ++ local_irq_save(flags); ++ t = ar71xx_reset_rr(AR91XX_RESET_REG_RESET_MODULE); ++ ar71xx_reset_wr(AR91XX_RESET_REG_RESET_MODULE, t & ~mask); ++ local_irq_restore(flags); ++ break; ++ ++ default: ++ BUG(); ++ } ++} ++EXPORT_SYMBOL_GPL(ar71xx_device_start); ++ ++int ar71xx_device_stopped(u32 mask) ++{ ++ unsigned long flags; ++ u32 t; ++ ++ switch (ar71xx_soc) { ++ case AR71XX_SOC_AR7130: ++ case AR71XX_SOC_AR7141: ++ case AR71XX_SOC_AR7161: ++ local_irq_save(flags); ++ t = ar71xx_reset_rr(AR71XX_RESET_REG_RESET_MODULE); ++ local_irq_restore(flags); ++ break; ++ ++ case AR71XX_SOC_AR7240: ++ case AR71XX_SOC_AR7241: ++ case AR71XX_SOC_AR7242: ++ local_irq_save(flags); ++ t = ar71xx_reset_rr(AR724X_RESET_REG_RESET_MODULE); ++ local_irq_restore(flags); ++ break; ++ ++ case AR71XX_SOC_AR9130: ++ case AR71XX_SOC_AR9132: ++ local_irq_save(flags); ++ t = ar71xx_reset_rr(AR91XX_RESET_REG_RESET_MODULE); ++ local_irq_restore(flags); ++ break; ++ ++ default: ++ BUG(); ++ } ++ ++ return ((t & mask) == mask); ++} ++EXPORT_SYMBOL_GPL(ar71xx_device_stopped); ++ ++void ar71xx_ddr_flush(u32 reg) ++{ ++ ar71xx_ddr_wr(reg, 1); ++ while ((ar71xx_ddr_rr(reg) & 0x1)); ++ ++ ar71xx_ddr_wr(reg, 1); ++ while ((ar71xx_ddr_rr(reg) & 0x1)); ++} ++EXPORT_SYMBOL_GPL(ar71xx_ddr_flush); ++ ++void ar71xx_flash_acquire(void) ++{ ++ mutex_lock(&ar71xx_flash_mutex); ++} ++EXPORT_SYMBOL_GPL(ar71xx_flash_acquire); ++ ++void ar71xx_flash_release(void) ++{ ++ mutex_unlock(&ar71xx_flash_mutex); ++} ++EXPORT_SYMBOL_GPL(ar71xx_flash_release); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-ap91-eth.c linux-2.6.39/arch/mips/ar71xx/dev-ap91-eth.c +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-ap91-eth.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-ap91-eth.c 2011-05-27 14:36:50.000000000 +0200 +@@ -0,0 +1,70 @@ ++/* ++ * Atheros AP91 reference board ethernet initialization ++ * ++ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include "devices.h" ++#include "dev-dsa.h" ++#include "dev-ap91-eth.h" ++ ++static struct dsa_chip_data ap91_dsa_chip = { ++ .port_names[0] = "cpu", ++ .port_names[1] = "lan1", ++ .port_names[2] = "lan2", ++ .port_names[3] = "lan3", ++ .port_names[4] = "lan4", ++}; ++ ++static struct dsa_platform_data ap91_dsa_data = { ++ .nr_chips = 1, ++ .chip = &ap91_dsa_chip, ++}; ++ ++static void ap91_eth_set_port_name(unsigned port, const char *name) ++{ ++ if (port < 1 || port > 5) ++ return; ++ ++ if (name) ++ ap91_dsa_chip.port_names[port] = (char *) name; ++} ++ ++void __init ap91_eth_init(u8 *mac_addr, const char *port_names[]) ++{ ++ if (mac_addr) ++ ar71xx_set_mac_base(mac_addr); ++ ++ if (port_names) { ++ int i; ++ ++ for (i = 0; i < AP91_ETH_NUM_PORT_NAMES; i++) ++ ap91_eth_set_port_name(i + 1, port_names[i]); ++ } ++ ++ /* WAN port */ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth0_data.speed = SPEED_100; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ar71xx_eth0_data.fifo_cfg1 = 0x0fff0000; ++ ar71xx_eth0_data.fifo_cfg2 = 0x00001fff; ++ ar71xx_eth0_data.fifo_cfg3 = 0x008001ff; ++ ++ /* LAN ports */ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.speed = SPEED_1000; ++ ar71xx_eth1_data.duplex = DUPLEX_FULL; ++ ar71xx_eth1_data.fifo_cfg1 = 0x0fff0000; ++ ar71xx_eth1_data.fifo_cfg2 = 0x00001fff; ++ ar71xx_eth1_data.fifo_cfg3 = 0x008001ff; ++ ++ ar71xx_add_device_mdio(0x0); ++ ar71xx_add_device_eth(1); ++ ar71xx_add_device_eth(0); ++ ++ ar71xx_add_device_dsa(1, &ap91_dsa_data); ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-ap91-eth.h linux-2.6.39/arch/mips/ar71xx/dev-ap91-eth.h +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-ap91-eth.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-ap91-eth.h 2011-05-27 14:36:50.000000000 +0200 +@@ -0,0 +1,23 @@ ++/* ++ * Atheros AP91 reference board ethernet initialization ++ * ++ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _AR71XX_DEV_AP91_ETH_H ++#define _AR71XX_DEV_AP91_ETH_H ++ ++#define AP91_ETH_NUM_PORT_NAMES 4 ++ ++#if defined(CONFIG_AR71XX_DEV_AP91_ETH) ++void ap91_eth_init(u8 *mac_addr, const char *port_names[]) __init; ++#else ++static inline void ap91_eth_init(u8 *mac_addr) { } ++#endif ++ ++#endif /* _AR71XX_DEV_AP91_ETH_H */ ++ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-ap91-pci.c linux-2.6.39/arch/mips/ar71xx/dev-ap91-pci.c +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-ap91-pci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-ap91-pci.c 2011-05-27 14:36:50.000000000 +0200 +@@ -0,0 +1,114 @@ ++/* ++ * Atheros AP91 reference board PCI initialization ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/pci.h> ++#include <linux/ath9k_platform.h> ++#include <linux/delay.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/pci.h> ++ ++#include "dev-ap91-pci.h" ++ ++static struct ath9k_platform_data ap91_wmac_data; ++static char ap91_wmac_mac[6]; ++static int ap91_pci_fixup_enabled; ++ ++static struct ar71xx_pci_irq ap91_pci_irqs[] __initdata = { ++ { ++ .slot = 0, ++ .pin = 1, ++ .irq = AR71XX_PCI_IRQ_DEV0, ++ } ++}; ++ ++static int ap91_pci_plat_dev_init(struct pci_dev *dev) ++{ ++ switch(PCI_SLOT(dev->devfn)) { ++ case 0: ++ dev->dev.platform_data = &ap91_wmac_data; ++ break; ++ } ++ ++ return 0; ++} ++ ++static void ap91_pci_fixup(struct pci_dev *dev) ++{ ++ void __iomem *mem; ++ u16 *cal_data; ++ u16 cmd; ++ u32 val; ++ ++ if (!ap91_pci_fixup_enabled) ++ return; ++ ++ printk(KERN_INFO "PCI: fixup device %s\n", pci_name(dev)); ++ ++ cal_data = ap91_wmac_data.eeprom_data; ++ if (*cal_data != 0xa55a) { ++ printk(KERN_ERR "PCI: no calibration data found for %s\n", ++ pci_name(dev)); ++ return; ++ } ++ ++ mem = ioremap(AR71XX_PCI_MEM_BASE, 0x10000); ++ if (!mem) { ++ printk(KERN_ERR "PCI: ioremap error for device %s\n", ++ pci_name(dev)); ++ return; ++ } ++ ++ /* Setup the PCI device to allow access to the internal registers */ ++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0xffff); ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; ++ pci_write_config_word(dev, PCI_COMMAND, cmd); ++ ++ /* set pointer to first reg address */ ++ cal_data += 3; ++ while (*cal_data != 0xffff) { ++ u32 reg; ++ reg = *cal_data++; ++ val = *cal_data++; ++ val |= (*cal_data++) << 16; ++ ++ __raw_writel(val, mem + reg); ++ udelay(100); ++ } ++ ++ pci_read_config_dword(dev, PCI_VENDOR_ID, &val); ++ dev->vendor = val & 0xffff; ++ dev->device = (val >> 16) & 0xffff; ++ ++ pci_read_config_dword(dev, PCI_CLASS_REVISION, &val); ++ dev->revision = val & 0xff; ++ dev->class = val >> 8; /* upper 3 bytes */ ++ ++ iounmap(mem); ++} ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ap91_pci_fixup); ++ ++void __init ap91_pci_init(u8 *cal_data, u8 *mac_addr) ++{ ++ if (cal_data) ++ memcpy(ap91_wmac_data.eeprom_data, cal_data, ++ sizeof(ap91_wmac_data.eeprom_data)); ++ ++ if (mac_addr) { ++ memcpy(ap91_wmac_mac, mac_addr, sizeof(ap91_wmac_mac)); ++ ap91_wmac_data.macaddr = ap91_wmac_mac; ++ } ++ ++ ar71xx_pci_plat_dev_init = ap91_pci_plat_dev_init; ++ ar71xx_pci_init(ARRAY_SIZE(ap91_pci_irqs), ap91_pci_irqs); ++ ++ ap91_pci_fixup_enabled = 1; ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-ap91-pci.h linux-2.6.39/arch/mips/ar71xx/dev-ap91-pci.h +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-ap91-pci.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-ap91-pci.h 2011-05-27 14:36:50.000000000 +0200 +@@ -0,0 +1,21 @@ ++/* ++ * Atheros AP91 reference board PCI initialization ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _AR71XX_DEV_AP91_PCI_H ++#define _AR71XX_DEV_AP91_PCI_H ++ ++#if defined(CONFIG_AR71XX_DEV_AP91_PCI) ++void ap91_pci_init(u8 *cal_data, u8 *mac_addr) __init; ++#else ++static inline void ap91_pci_init(u8 *cal_data, u8 *mac_addr) { } ++#endif ++ ++#endif /* _AR71XX_DEV_AP91_PCI_H */ ++ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-ap94-pci.c linux-2.6.39/arch/mips/ar71xx/dev-ap94-pci.c +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-ap94-pci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-ap94-pci.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,159 @@ ++/* ++ * Atheros AP94 reference board PCI initialization ++ * ++ * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/pci.h> ++#include <linux/ath9k_platform.h> ++#include <linux/delay.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/pci.h> ++ ++#include "dev-ap94-pci.h" ++ ++static struct ath9k_platform_data ap94_wmac0_data; ++static struct ath9k_platform_data ap94_wmac1_data; ++static char ap94_wmac0_mac[6]; ++static char ap94_wmac1_mac[6]; ++static int ap94_pci_fixup_enabled; ++ ++static struct ar71xx_pci_irq ap94_pci_irqs[] __initdata = { ++ { ++ .slot = 0, ++ .pin = 1, ++ .irq = AR71XX_PCI_IRQ_DEV0, ++ }, { ++ .slot = 1, ++ .pin = 1, ++ .irq = AR71XX_PCI_IRQ_DEV1, ++ } ++}; ++ ++static int ap94_pci_plat_dev_init(struct pci_dev *dev) ++{ ++ switch(PCI_SLOT(dev->devfn)) { ++ case 17: ++ dev->dev.platform_data = &ap94_wmac0_data; ++ break; ++ ++ case 18: ++ dev->dev.platform_data = &ap94_wmac1_data; ++ break; ++ } ++ ++ return 0; ++} ++ ++static void ap94_pci_fixup(struct pci_dev *dev) ++{ ++ void __iomem *mem; ++ u16 *cal_data; ++ u16 cmd; ++ u32 bar0; ++ u32 val; ++ ++ if (!ap94_pci_fixup_enabled) ++ return; ++ ++ switch (PCI_SLOT(dev->devfn)) { ++ case 17: ++ cal_data = ap94_wmac0_data.eeprom_data; ++ break; ++ case 18: ++ cal_data = ap94_wmac1_data.eeprom_data; ++ break; ++ default: ++ return; ++ } ++ ++ if (*cal_data != 0xa55a) { ++ printk(KERN_ERR "PCI: no calibration data found for %s\n", ++ pci_name(dev)); ++ return; ++ } ++ ++ mem = ioremap(AR71XX_PCI_MEM_BASE, 0x10000); ++ if (!mem) { ++ printk(KERN_ERR "PCI: ioremap error for device %s\n", ++ pci_name(dev)); ++ return; ++ } ++ ++ printk(KERN_INFO "PCI: fixup device %s\n", pci_name(dev)); ++ ++ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &bar0); ++ ++ /* Setup the PCI device to allow access to the internal registers */ ++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, AR71XX_PCI_MEM_BASE); ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; ++ pci_write_config_word(dev, PCI_COMMAND, cmd); ++ ++ /* set pointer to first reg address */ ++ cal_data += 3; ++ while (*cal_data != 0xffff) { ++ u32 reg; ++ reg = *cal_data++; ++ val = *cal_data++; ++ val |= (*cal_data++) << 16; ++ ++ __raw_writel(val, mem + reg); ++ udelay(100); ++ } ++ ++ pci_read_config_dword(dev, PCI_VENDOR_ID, &val); ++ dev->vendor = val & 0xffff; ++ dev->device = (val >> 16) & 0xffff; ++ ++ pci_read_config_dword(dev, PCI_CLASS_REVISION, &val); ++ dev->revision = val & 0xff; ++ dev->class = val >> 8; /* upper 3 bytes */ ++ ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ cmd &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); ++ pci_write_config_word(dev, PCI_COMMAND, cmd); ++ ++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, bar0); ++ ++ iounmap(mem); ++} ++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATHEROS, PCI_ANY_ID, ap94_pci_fixup); ++ ++void __init ap94_pci_enable_quirk_wndr3700(void) ++{ ++ ap94_wmac0_data.quirk_wndr3700 = 1; ++ ap94_wmac1_data.quirk_wndr3700 = 1; ++} ++ ++void __init ap94_pci_init(u8 *cal_data0, u8 *mac_addr0, ++ u8 *cal_data1, u8 *mac_addr1) ++{ ++ if (cal_data0) ++ memcpy(ap94_wmac0_data.eeprom_data, cal_data0, ++ sizeof(ap94_wmac0_data.eeprom_data)); ++ ++ if (cal_data1) ++ memcpy(ap94_wmac1_data.eeprom_data, cal_data1, ++ sizeof(ap94_wmac1_data.eeprom_data)); ++ ++ if (mac_addr0) { ++ memcpy(ap94_wmac0_mac, mac_addr0, sizeof(ap94_wmac0_mac)); ++ ap94_wmac0_data.macaddr = ap94_wmac0_mac; ++ } ++ ++ if (mac_addr1) { ++ memcpy(ap94_wmac1_mac, mac_addr1, sizeof(ap94_wmac1_mac)); ++ ap94_wmac1_data.macaddr = ap94_wmac1_mac; ++ } ++ ++ ar71xx_pci_plat_dev_init = ap94_pci_plat_dev_init; ++ ar71xx_pci_init(ARRAY_SIZE(ap94_pci_irqs), ap94_pci_irqs); ++ ++ ap94_pci_fixup_enabled = 1; ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-ap94-pci.h linux-2.6.39/arch/mips/ar71xx/dev-ap94-pci.h +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-ap94-pci.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-ap94-pci.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,28 @@ ++/* ++ * Atheros AP94 reference board PCI initialization ++ * ++ * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _AR71XX_DEV_AP94_PCI_H ++#define _AR71XX_DEV_AP94_PCI_H ++ ++#if defined(CONFIG_AR71XX_DEV_AP94_PCI) ++void ap94_pci_init(u8 *cal_data0, u8 *mac_addr0, ++ u8 *cal_data1, u8 *mac_addr1) __init; ++ ++void ap94_pci_enable_quirk_wndr3700(void) __init; ++ ++#else ++static inline void ap94_pci_init(u8 *cal_data0, u8 *mac_addr0, ++ u8 *cal_data1, u8 *mac_addr1) {} ++ ++static inline void ap94_pci_enable_quirk_wndr3700(void) {} ++#endif ++ ++#endif /* _AR71XX_DEV_AP94_PCI_H */ ++ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-ar913x-wmac.c linux-2.6.39/arch/mips/ar71xx/dev-ar913x-wmac.c +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-ar913x-wmac.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-ar913x-wmac.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,68 @@ ++/* ++ * Atheros AR913x SoC built-in WMAC device support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/delay.h> ++#include <linux/etherdevice.h> ++#include <linux/platform_device.h> ++#include <linux/ath9k_platform.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "dev-ar913x-wmac.h" ++ ++static struct ath9k_platform_data ar913x_wmac_data; ++static char ar913x_wmac_mac[6]; ++ ++static struct resource ar913x_wmac_resources[] = { ++ { ++ .start = AR91XX_WMAC_BASE, ++ .end = AR91XX_WMAC_BASE + AR91XX_WMAC_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, { ++ .start = AR71XX_CPU_IRQ_IP2, ++ .end = AR71XX_CPU_IRQ_IP2, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct platform_device ar913x_wmac_device = { ++ .name = "ath9k", ++ .id = -1, ++ .resource = ar913x_wmac_resources, ++ .num_resources = ARRAY_SIZE(ar913x_wmac_resources), ++ .dev = { ++ .platform_data = &ar913x_wmac_data, ++ }, ++}; ++ ++void __init ar913x_add_device_wmac(u8 *cal_data, u8 *mac_addr) ++{ ++ if (cal_data) ++ memcpy(ar913x_wmac_data.eeprom_data, cal_data, ++ sizeof(ar913x_wmac_data.eeprom_data)); ++ ++ if (mac_addr) { ++ memcpy(ar913x_wmac_mac, mac_addr, sizeof(ar913x_wmac_mac)); ++ ar913x_wmac_data.macaddr = ar913x_wmac_mac; ++ } ++ ++ ar71xx_device_stop(RESET_MODULE_AMBA2WMAC); ++ mdelay(10); ++ ++ ar71xx_device_start(RESET_MODULE_AMBA2WMAC); ++ mdelay(10); ++ ++ platform_device_register(&ar913x_wmac_device); ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-ar913x-wmac.h linux-2.6.39/arch/mips/ar71xx/dev-ar913x-wmac.h +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-ar913x-wmac.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-ar913x-wmac.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,19 @@ ++/* ++ * Atheros AR913x SoC built-in WMAC device support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _AR71XX_DEV_AR913X_WMAC_H ++#define _AR71XX_DEV_AR913X_WMAC_H ++ ++void ar913x_add_device_wmac(u8 *cal_data, u8 *mac_addr) __init; ++ ++#endif /* _AR71XX_DEV_AR913X_WMAC_H */ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-dsa.c linux-2.6.39/arch/mips/ar71xx/dev-dsa.c +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-dsa.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-dsa.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,50 @@ ++/* ++ * Atheros AR71xx DSA switch device support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/init.h> ++#include <linux/platform_device.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "devices.h" ++#include "dev-dsa.h" ++ ++static struct platform_device ar71xx_dsa_switch_device = { ++ .name = "dsa", ++ .id = 0, ++}; ++ ++void __init ar71xx_add_device_dsa(unsigned int id, ++ struct dsa_platform_data *d) ++{ ++ int i; ++ ++ switch (id) { ++ case 0: ++ d->netdev = &ar71xx_eth0_device.dev; ++ break; ++ case 1: ++ d->netdev = &ar71xx_eth1_device.dev; ++ break; ++ default: ++ printk(KERN_ERR ++ "ar71xx: invalid ethernet id %d for DSA switch\n", ++ id); ++ return; ++ } ++ ++ for (i = 0; i < d->nr_chips; i++) ++ d->chip[i].mii_bus = &ar71xx_mdio_device.dev; ++ ++ ar71xx_dsa_switch_device.dev.platform_data = d; ++ ++ platform_device_register(&ar71xx_dsa_switch_device); ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-dsa.h linux-2.6.39/arch/mips/ar71xx/dev-dsa.h +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-dsa.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-dsa.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,20 @@ ++/* ++ * Atheros AR71xx DSA switch device support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _AR71XX_DEV_DSA_H ++#define _AR71XX_DEV_DSA_H ++ ++#include <net/dsa.h> ++ ++void ar71xx_add_device_dsa(unsigned int id, ++ struct dsa_platform_data *d) __init; ++ ++#endif /* _AR71XX_DEV_DSA_H */ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-gpio-buttons.c linux-2.6.39/arch/mips/ar71xx/dev-gpio-buttons.c +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-gpio-buttons.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-gpio-buttons.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,58 @@ ++/* ++ * Atheros AR71xx GPIO button support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include "linux/init.h" ++#include <linux/platform_device.h> ++ ++#include "dev-gpio-buttons.h" ++ ++void __init ar71xx_add_device_gpio_buttons(int id, ++ unsigned poll_interval, ++ unsigned nbuttons, ++ struct gpio_button *buttons) ++{ ++ struct platform_device *pdev; ++ struct gpio_buttons_platform_data pdata; ++ struct gpio_button *p; ++ int err; ++ ++ p = kmalloc(nbuttons * sizeof(*p), GFP_KERNEL); ++ if (!p) ++ return; ++ ++ memcpy(p, buttons, nbuttons * sizeof(*p)); ++ ++ pdev = platform_device_alloc("gpio-buttons", id); ++ if (!pdev) ++ goto err_free_buttons; ++ ++ memset(&pdata, 0, sizeof(pdata)); ++ pdata.poll_interval = poll_interval; ++ pdata.nbuttons = nbuttons; ++ pdata.buttons = p; ++ ++ err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); ++ if (err) ++ goto err_put_pdev; ++ ++ ++ err = platform_device_add(pdev); ++ if (err) ++ goto err_put_pdev; ++ ++ return; ++ ++err_put_pdev: ++ platform_device_put(pdev); ++ ++err_free_buttons: ++ kfree(p); ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-gpio-buttons.h linux-2.6.39/arch/mips/ar71xx/dev-gpio-buttons.h +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-gpio-buttons.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-gpio-buttons.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,25 @@ ++/* ++ * Atheros AR71xx GPIO button support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _AR71XX_DEV_GPIO_BUTTONS_H ++#define _AR71XX_DEV_GPIO_BUTTONS_H ++ ++#include <linux/input.h> ++#include <linux/gpio_buttons.h> ++ ++#include <asm/mach-ar71xx/platform.h> ++ ++void ar71xx_add_device_gpio_buttons(int id, ++ unsigned poll_interval, ++ unsigned nbuttons, ++ struct gpio_button *buttons) __init; ++ ++#endif /* _AR71XX_DEV_GPIO_BUTTONS_H */ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-leds-gpio.c linux-2.6.39/arch/mips/ar71xx/dev-leds-gpio.c +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-leds-gpio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-leds-gpio.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,57 @@ ++/* ++ * Atheros AR71xx GPIO LED device support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/init.h> ++#include <linux/platform_device.h> ++#include <linux/slab.h> ++ ++#include "dev-leds-gpio.h" ++ ++void __init ar71xx_add_device_leds_gpio(int id, unsigned num_leds, ++ struct gpio_led *leds) ++{ ++ struct platform_device *pdev; ++ struct gpio_led_platform_data pdata; ++ struct gpio_led *p; ++ int err; ++ ++ p = kmalloc(num_leds * sizeof(*p), GFP_KERNEL); ++ if (!p) ++ return; ++ ++ memcpy(p, leds, num_leds * sizeof(*p)); ++ ++ pdev = platform_device_alloc("leds-gpio", id); ++ if (!pdev) ++ goto err_free_leds; ++ ++ memset(&pdata, 0, sizeof(pdata)); ++ pdata.num_leds = num_leds; ++ pdata.leds = p; ++ ++ err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); ++ if (err) ++ goto err_put_pdev; ++ ++ err = platform_device_add(pdev); ++ if (err) ++ goto err_put_pdev; ++ ++ return; ++ ++err_put_pdev: ++ platform_device_put(pdev); ++ ++err_free_leds: ++ kfree(p); ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-leds-gpio.h linux-2.6.39/arch/mips/ar71xx/dev-leds-gpio.h +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-leds-gpio.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-leds-gpio.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,21 @@ ++/* ++ * Atheros AR71xx GPIO LED device support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _AR71XX_DEV_LEDS_GPIO_H ++#define _AR71XX_DEV_LEDS_GPIO_H ++ ++#include <linux/leds.h> ++ ++void ar71xx_add_device_leds_gpio(int id, ++ unsigned num_leds, ++ struct gpio_led *leds) __init; ++ ++#endif /* _AR71XX_DEV_LEDS_GPIO_H */ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-m25p80.c linux-2.6.39/arch/mips/ar71xx/dev-m25p80.c +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-m25p80.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-m25p80.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,30 @@ ++/* ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/init.h> ++#include <linux/spi/spi.h> ++#include <linux/spi/flash.h> ++ ++#include "devices.h" ++#include "dev-m25p80.h" ++ ++static struct spi_board_info ar71xx_spi_info[] = { ++ { ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 25000000, ++ .modalias = "m25p80", ++ } ++}; ++ ++void __init ar71xx_add_device_m25p80(struct flash_platform_data *pdata) ++{ ++ ar71xx_spi_info[0].platform_data = pdata; ++ ar71xx_add_device_spi(NULL, ar71xx_spi_info, ++ ARRAY_SIZE(ar71xx_spi_info)); ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-m25p80.h linux-2.6.39/arch/mips/ar71xx/dev-m25p80.h +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-m25p80.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-m25p80.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,16 @@ ++/* ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _AR71XX_DEV_M25P80_H ++#define _AR71XX_DEV_M25P80_H ++ ++#include <linux/spi/flash.h> ++ ++void ar71xx_add_device_m25p80(struct flash_platform_data *pdata) __init; ++ ++#endif /* _AR71XX_DEV_M25P80_H */ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-pb42-pci.c linux-2.6.39/arch/mips/ar71xx/dev-pb42-pci.c +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-pb42-pci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-pb42-pci.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,40 @@ ++/* ++ * Atheros PB42 reference board PCI initialization ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/pci.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/pci.h> ++ ++#include "dev-pb42-pci.h" ++ ++static struct ar71xx_pci_irq pb42_pci_irqs[] __initdata = { ++ { ++ .slot = 0, ++ .pin = 1, ++ .irq = AR71XX_PCI_IRQ_DEV0, ++ }, { ++ .slot = 1, ++ .pin = 1, ++ .irq = AR71XX_PCI_IRQ_DEV1, ++ }, { ++ .slot = 2, ++ .pin = 1, ++ .irq = AR71XX_PCI_IRQ_DEV2, ++ } ++}; ++ ++void __init pb42_pci_init(void) ++{ ++ ar71xx_pci_init(ARRAY_SIZE(pb42_pci_irqs), pb42_pci_irqs); ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-pb42-pci.h linux-2.6.39/arch/mips/ar71xx/dev-pb42-pci.h +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-pb42-pci.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-pb42-pci.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,21 @@ ++/* ++ * Atheros PB42 reference board PCI initialization ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _AR71XX_DEV_PB42_PCI_H ++#define _AR71XX_DEV_PB42_PCI_H ++ ++#if defined(CONFIG_AR71XX_DEV_PB42_PCI) ++void pb42_pci_init(void) __init; ++#else ++static inline void pb42_pci_init(void) { } ++#endif ++ ++#endif /* _AR71XX_DEV_PB42_PCI_H */ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-pb9x-pci.c linux-2.6.39/arch/mips/ar71xx/dev-pb9x-pci.c +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-pb9x-pci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-pb9x-pci.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,33 @@ ++/* ++ * Atheros PB9x reference board PCI initialization ++ * ++ * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org> ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/pci.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/pci.h> ++ ++#include "dev-pb9x-pci.h" ++ ++static struct ar71xx_pci_irq pb9x_pci_irqs[] __initdata = { ++ { ++ .slot = 0, ++ .pin = 1, ++ .irq = AR71XX_PCI_IRQ_DEV0, ++ } ++}; ++ ++void __init pb9x_pci_init(void) ++{ ++ ar71xx_pci_init(ARRAY_SIZE(pb9x_pci_irqs), pb9x_pci_irqs); ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-pb9x-pci.h linux-2.6.39/arch/mips/ar71xx/dev-pb9x-pci.h +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-pb9x-pci.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-pb9x-pci.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,22 @@ ++/* ++ * Atheros PB9x reference board PCI initialization ++ * ++ * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org> ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _AR71XX_DEV_PB9X_PCI_H ++#define _AR71XX_DEV_PB9X_PCI_H ++ ++#if defined(CONFIG_AR71XX_DEV_PB9X_PCI) ++void pb9x_pci_init(void) __init; ++#else ++static inline void pb9x_pci_init(void) { } ++#endif ++ ++#endif /* _AR71XX_DEV_PB9X_PCI_H */ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-usb.c linux-2.6.39/arch/mips/ar71xx/dev-usb.c +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-usb.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-usb.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,181 @@ ++/* ++ * Atheros AR71xx USB host device support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/delay.h> ++#include <linux/dma-mapping.h> ++#include <linux/platform_device.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/platform.h> ++ ++#include "dev-usb.h" ++ ++/* ++ * OHCI (USB full speed host controller) ++ */ ++static struct resource ar71xx_ohci_resources[] = { ++ [0] = { ++ .start = AR71XX_OHCI_BASE, ++ .end = AR71XX_OHCI_BASE + AR71XX_OHCI_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = AR71XX_MISC_IRQ_OHCI, ++ .end = AR71XX_MISC_IRQ_OHCI, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static struct resource ar7240_ohci_resources[] = { ++ [0] = { ++ .start = AR7240_OHCI_BASE, ++ .end = AR7240_OHCI_BASE + AR7240_OHCI_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = AR71XX_CPU_IRQ_USB, ++ .end = AR71XX_CPU_IRQ_USB, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static u64 ar71xx_ohci_dmamask = DMA_BIT_MASK(32); ++static struct platform_device ar71xx_ohci_device = { ++ .name = "ar71xx-ohci", ++ .id = -1, ++ .resource = ar71xx_ohci_resources, ++ .num_resources = ARRAY_SIZE(ar71xx_ohci_resources), ++ .dev = { ++ .dma_mask = &ar71xx_ohci_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ }, ++}; ++ ++/* ++ * EHCI (USB full speed host controller) ++ */ ++static struct resource ar71xx_ehci_resources[] = { ++ [0] = { ++ .start = AR71XX_EHCI_BASE, ++ .end = AR71XX_EHCI_BASE + AR71XX_EHCI_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++ [1] = { ++ .start = AR71XX_CPU_IRQ_USB, ++ .end = AR71XX_CPU_IRQ_USB, ++ .flags = IORESOURCE_IRQ, ++ }, ++}; ++ ++static u64 ar71xx_ehci_dmamask = DMA_BIT_MASK(32); ++static struct ar71xx_ehci_platform_data ar71xx_ehci_data; ++ ++static struct platform_device ar71xx_ehci_device = { ++ .name = "ar71xx-ehci", ++ .id = -1, ++ .resource = ar71xx_ehci_resources, ++ .num_resources = ARRAY_SIZE(ar71xx_ehci_resources), ++ .dev = { ++ .dma_mask = &ar71xx_ehci_dmamask, ++ .coherent_dma_mask = DMA_BIT_MASK(32), ++ .platform_data = &ar71xx_ehci_data, ++ }, ++}; ++ ++#define AR71XX_USB_RESET_MASK \ ++ (RESET_MODULE_USB_HOST | RESET_MODULE_USB_PHY \ ++ | RESET_MODULE_USB_OHCI_DLL) ++ ++#define AR7240_USB_RESET_MASK \ ++ (RESET_MODULE_USB_HOST | RESET_MODULE_USB_OHCI_DLL_7240) ++ ++static void __init ar71xx_usb_setup(void) ++{ ++ ar71xx_device_stop(AR71XX_USB_RESET_MASK); ++ mdelay(1000); ++ ar71xx_device_start(AR71XX_USB_RESET_MASK); ++ ++ /* Turning on the Buff and Desc swap bits */ ++ ar71xx_usb_ctrl_wr(USB_CTRL_REG_CONFIG, 0xf0000); ++ ++ /* WAR for HW bug. Here it adjusts the duration between two SOFS */ ++ ar71xx_usb_ctrl_wr(USB_CTRL_REG_FLADJ, 0x20c00); ++ ++ mdelay(900); ++ ++ platform_device_register(&ar71xx_ohci_device); ++ platform_device_register(&ar71xx_ehci_device); ++} ++ ++static void __init ar7240_usb_setup(void) ++{ ++ ar71xx_device_stop(AR7240_USB_RESET_MASK); ++ mdelay(1000); ++ ar71xx_device_start(AR7240_USB_RESET_MASK); ++ ++ /* WAR for HW bug. Here it adjusts the duration between two SOFS */ ++ ar71xx_usb_ctrl_wr(USB_CTRL_REG_FLADJ, 0x3); ++ ++ if (ar71xx_soc == AR71XX_SOC_AR7241 || ar71xx_soc == AR71XX_SOC_AR7242) { ++ ar71xx_ehci_data.is_ar91xx = 1; ++ ar71xx_ehci_device.resource = ar7240_ohci_resources; ++ ar71xx_ehci_device.num_resources = ARRAY_SIZE(ar7240_ohci_resources); ++ platform_device_register(&ar71xx_ehci_device); ++ } else { ++ ar71xx_ohci_device.resource = ar7240_ohci_resources; ++ ar71xx_ohci_device.num_resources = ARRAY_SIZE(ar7240_ohci_resources); ++ platform_device_register(&ar71xx_ohci_device); ++ } ++} ++ ++static void __init ar91xx_usb_setup(void) ++{ ++ ar71xx_device_stop(RESET_MODULE_USBSUS_OVERRIDE); ++ mdelay(10); ++ ++ ar71xx_device_start(RESET_MODULE_USB_HOST); ++ mdelay(10); ++ ++ ar71xx_device_start(RESET_MODULE_USB_PHY); ++ mdelay(10); ++ ++ ar71xx_ehci_data.is_ar91xx = 1; ++ platform_device_register(&ar71xx_ehci_device); ++} ++ ++void __init ar71xx_add_device_usb(void) ++{ ++ switch (ar71xx_soc) { ++ case AR71XX_SOC_AR7240: ++ case AR71XX_SOC_AR7241: ++ case AR71XX_SOC_AR7242: ++ ar7240_usb_setup(); ++ break; ++ ++ case AR71XX_SOC_AR7130: ++ case AR71XX_SOC_AR7141: ++ case AR71XX_SOC_AR7161: ++ ar71xx_usb_setup(); ++ break; ++ ++ case AR71XX_SOC_AR9130: ++ case AR71XX_SOC_AR9132: ++ ar91xx_usb_setup(); ++ break; ++ ++ default: ++ BUG(); ++ } ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/dev-usb.h linux-2.6.39/arch/mips/ar71xx/dev-usb.h +--- linux-2.6.39.orig/arch/mips/ar71xx/dev-usb.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/dev-usb.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,17 @@ ++/* ++ * Atheros AR71xx USB host device support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _AR71XX_DEV_USB_H ++#define _AR71XX_DEV_USB_H ++ ++void ar71xx_add_device_usb(void) __init; ++ ++#endif /* _AR71XX_DEV_USB_H */ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/devices.c linux-2.6.39/arch/mips/ar71xx/devices.c +--- linux-2.6.39.orig/arch/mips/ar71xx/devices.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/devices.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,575 @@ ++/* ++ * Atheros AR71xx SoC platform devices ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/delay.h> ++#include <linux/etherdevice.h> ++#include <linux/platform_device.h> ++#include <linux/serial_8250.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "devices.h" ++ ++static u8 ar71xx_mac_base[ETH_ALEN] __initdata; ++ ++static struct resource ar71xx_uart_resources[] = { ++ { ++ .start = AR71XX_UART_BASE, ++ .end = AR71XX_UART_BASE + AR71XX_UART_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++#define AR71XX_UART_FLAGS (UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP) ++static struct plat_serial8250_port ar71xx_uart_data[] = { ++ { ++ .mapbase = AR71XX_UART_BASE, ++ .irq = AR71XX_MISC_IRQ_UART, ++ .flags = AR71XX_UART_FLAGS, ++ .iotype = UPIO_MEM32, ++ .regshift = 2, ++ }, { ++ /* terminating entry */ ++ } ++}; ++ ++static struct platform_device ar71xx_uart_device = { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .resource = ar71xx_uart_resources, ++ .num_resources = ARRAY_SIZE(ar71xx_uart_resources), ++ .dev = { ++ .platform_data = ar71xx_uart_data ++ }, ++}; ++ ++void __init ar71xx_add_device_uart(void) ++{ ++ ar71xx_uart_data[0].uartclk = ar71xx_ahb_freq; ++ platform_device_register(&ar71xx_uart_device); ++} ++ ++static struct resource ar71xx_mdio_resources[] = { ++ { ++ .name = "mdio_base", ++ .flags = IORESOURCE_MEM, ++ .start = AR71XX_GE0_BASE, ++ .end = AR71XX_GE0_BASE + 0x200 - 1, ++ } ++}; ++ ++static struct ag71xx_mdio_platform_data ar71xx_mdio_data; ++ ++struct platform_device ar71xx_mdio_device = { ++ .name = "ag71xx-mdio", ++ .id = -1, ++ .resource = ar71xx_mdio_resources, ++ .num_resources = ARRAY_SIZE(ar71xx_mdio_resources), ++ .dev = { ++ .platform_data = &ar71xx_mdio_data, ++ }, ++}; ++ ++void __init ar71xx_add_device_mdio(u32 phy_mask) ++{ ++ switch (ar71xx_soc) { ++ case AR71XX_SOC_AR7240: ++ case AR71XX_SOC_AR7241: ++ case AR71XX_SOC_AR7242: ++ ar71xx_mdio_data.is_ar7240 = 1; ++ break; ++ default: ++ break; ++ } ++ ++ ar71xx_mdio_data.phy_mask = phy_mask; ++ ++ platform_device_register(&ar71xx_mdio_device); ++} ++ ++static void ar71xx_set_pll(u32 cfg_reg, u32 pll_reg, u32 pll_val, u32 shift) ++{ ++ void __iomem *base; ++ u32 t; ++ ++ base = ioremap_nocache(AR71XX_PLL_BASE, AR71XX_PLL_SIZE); ++ ++ t = __raw_readl(base + cfg_reg); ++ t &= ~(3 << shift); ++ t |= (2 << shift); ++ __raw_writel(t, base + cfg_reg); ++ udelay(100); ++ ++ __raw_writel(pll_val, base + pll_reg); ++ ++ t |= (3 << shift); ++ __raw_writel(t, base + cfg_reg); ++ udelay(100); ++ ++ t &= ~(3 << shift); ++ __raw_writel(t, base + cfg_reg); ++ udelay(100); ++ ++ printk(KERN_DEBUG "ar71xx: pll_reg %#x: %#x\n", ++ (unsigned int)(base + pll_reg), __raw_readl(base + pll_reg)); ++ ++ iounmap(base); ++} ++ ++struct ar71xx_eth_pll_data ar71xx_eth0_pll_data; ++struct ar71xx_eth_pll_data ar71xx_eth1_pll_data; ++ ++static u32 ar71xx_get_eth_pll(unsigned int mac, int speed) ++{ ++ struct ar71xx_eth_pll_data *pll_data; ++ u32 pll_val; ++ ++ switch (mac) { ++ case 0: ++ pll_data = &ar71xx_eth0_pll_data; ++ break; ++ case 1: ++ pll_data = &ar71xx_eth1_pll_data; ++ break; ++ default: ++ BUG(); ++ } ++ ++ switch (speed) { ++ case SPEED_10: ++ pll_val = pll_data->pll_10; ++ break; ++ case SPEED_100: ++ pll_val = pll_data->pll_100; ++ break; ++ case SPEED_1000: ++ pll_val = pll_data->pll_1000; ++ break; ++ default: ++ BUG(); ++ } ++ ++ return pll_val; ++} ++ ++static void ar71xx_set_pll_ge0(int speed) ++{ ++ u32 val = ar71xx_get_eth_pll(0, speed); ++ ++ ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR71XX_PLL_REG_ETH0_INT_CLOCK, ++ val, AR71XX_ETH0_PLL_SHIFT); ++} ++ ++static void ar71xx_set_pll_ge1(int speed) ++{ ++ u32 val = ar71xx_get_eth_pll(1, speed); ++ ++ ar71xx_set_pll(AR71XX_PLL_REG_SEC_CONFIG, AR71XX_PLL_REG_ETH1_INT_CLOCK, ++ val, AR71XX_ETH1_PLL_SHIFT); ++} ++ ++static void ar724x_set_pll_ge0(int speed) ++{ ++ /* TODO */ ++} ++ ++static void ar724x_set_pll_ge1(int speed) ++{ ++ /* TODO */ ++} ++ ++static void ar91xx_set_pll_ge0(int speed) ++{ ++ u32 val = ar71xx_get_eth_pll(0, speed); ++ ++ ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG, AR91XX_PLL_REG_ETH0_INT_CLOCK, ++ val, AR91XX_ETH0_PLL_SHIFT); ++} ++ ++static void ar91xx_set_pll_ge1(int speed) ++{ ++ u32 val = ar71xx_get_eth_pll(1, speed); ++ ++ ar71xx_set_pll(AR91XX_PLL_REG_ETH_CONFIG, AR91XX_PLL_REG_ETH1_INT_CLOCK, ++ val, AR91XX_ETH1_PLL_SHIFT); ++} ++ ++static void ar71xx_ddr_flush_ge0(void) ++{ ++ ar71xx_ddr_flush(AR71XX_DDR_REG_FLUSH_GE0); ++} ++ ++static void ar71xx_ddr_flush_ge1(void) ++{ ++ ar71xx_ddr_flush(AR71XX_DDR_REG_FLUSH_GE1); ++} ++ ++static void ar724x_ddr_flush_ge0(void) ++{ ++ ar71xx_ddr_flush(AR724X_DDR_REG_FLUSH_GE0); ++} ++ ++static void ar724x_ddr_flush_ge1(void) ++{ ++ ar71xx_ddr_flush(AR724X_DDR_REG_FLUSH_GE1); ++} ++ ++static void ar91xx_ddr_flush_ge0(void) ++{ ++ ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_GE0); ++} ++ ++static void ar91xx_ddr_flush_ge1(void) ++{ ++ ar71xx_ddr_flush(AR91XX_DDR_REG_FLUSH_GE1); ++} ++ ++static struct resource ar71xx_eth0_resources[] = { ++ { ++ .name = "mac_base", ++ .flags = IORESOURCE_MEM, ++ .start = AR71XX_GE0_BASE, ++ .end = AR71XX_GE0_BASE + 0x200 - 1, ++ }, { ++ .name = "mii_ctrl", ++ .flags = IORESOURCE_MEM, ++ .start = AR71XX_MII_BASE + MII_REG_MII0_CTRL, ++ .end = AR71XX_MII_BASE + MII_REG_MII0_CTRL + 3, ++ }, { ++ .name = "mac_irq", ++ .flags = IORESOURCE_IRQ, ++ .start = AR71XX_CPU_IRQ_GE0, ++ .end = AR71XX_CPU_IRQ_GE0, ++ }, ++}; ++ ++struct ag71xx_platform_data ar71xx_eth0_data = { ++ .reset_bit = RESET_MODULE_GE0_MAC, ++}; ++ ++struct platform_device ar71xx_eth0_device = { ++ .name = "ag71xx", ++ .id = 0, ++ .resource = ar71xx_eth0_resources, ++ .num_resources = ARRAY_SIZE(ar71xx_eth0_resources), ++ .dev = { ++ .platform_data = &ar71xx_eth0_data, ++ }, ++}; ++ ++static struct resource ar71xx_eth1_resources[] = { ++ { ++ .name = "mac_base", ++ .flags = IORESOURCE_MEM, ++ .start = AR71XX_GE1_BASE, ++ .end = AR71XX_GE1_BASE + 0x200 - 1, ++ }, { ++ .name = "mii_ctrl", ++ .flags = IORESOURCE_MEM, ++ .start = AR71XX_MII_BASE + MII_REG_MII1_CTRL, ++ .end = AR71XX_MII_BASE + MII_REG_MII1_CTRL + 3, ++ }, { ++ .name = "mac_irq", ++ .flags = IORESOURCE_IRQ, ++ .start = AR71XX_CPU_IRQ_GE1, ++ .end = AR71XX_CPU_IRQ_GE1, ++ }, ++}; ++ ++struct ag71xx_platform_data ar71xx_eth1_data = { ++ .reset_bit = RESET_MODULE_GE1_MAC, ++}; ++ ++struct platform_device ar71xx_eth1_device = { ++ .name = "ag71xx", ++ .id = 1, ++ .resource = ar71xx_eth1_resources, ++ .num_resources = ARRAY_SIZE(ar71xx_eth1_resources), ++ .dev = { ++ .platform_data = &ar71xx_eth1_data, ++ }, ++}; ++ ++#define AR71XX_PLL_VAL_1000 0x00110000 ++#define AR71XX_PLL_VAL_100 0x00001099 ++#define AR71XX_PLL_VAL_10 0x00991099 ++ ++#define AR724X_PLL_VAL_1000 0x00110000 ++#define AR724X_PLL_VAL_100 0x00001099 ++#define AR724X_PLL_VAL_10 0x00991099 ++ ++#define AR91XX_PLL_VAL_1000 0x1a000000 ++#define AR91XX_PLL_VAL_100 0x13000a44 ++#define AR91XX_PLL_VAL_10 0x00441099 ++ ++static void __init ar71xx_init_eth_pll_data(unsigned int id) ++{ ++ struct ar71xx_eth_pll_data *pll_data; ++ u32 pll_10, pll_100, pll_1000; ++ ++ switch (id) { ++ case 0: ++ pll_data = &ar71xx_eth0_pll_data; ++ break; ++ case 1: ++ pll_data = &ar71xx_eth1_pll_data; ++ break; ++ default: ++ BUG(); ++ } ++ ++ switch (ar71xx_soc) { ++ case AR71XX_SOC_AR7130: ++ case AR71XX_SOC_AR7141: ++ case AR71XX_SOC_AR7161: ++ pll_10 = AR71XX_PLL_VAL_10; ++ pll_100 = AR71XX_PLL_VAL_100; ++ pll_1000 = AR71XX_PLL_VAL_1000; ++ break; ++ ++ case AR71XX_SOC_AR7240: ++ case AR71XX_SOC_AR7241: ++ case AR71XX_SOC_AR7242: ++ pll_10 = AR724X_PLL_VAL_10; ++ pll_100 = AR724X_PLL_VAL_100; ++ pll_1000 = AR724X_PLL_VAL_1000; ++ break; ++ ++ case AR71XX_SOC_AR9130: ++ case AR71XX_SOC_AR9132: ++ pll_10 = AR91XX_PLL_VAL_10; ++ pll_100 = AR91XX_PLL_VAL_100; ++ pll_1000 = AR91XX_PLL_VAL_1000; ++ break; ++ default: ++ BUG(); ++ } ++ ++ if (!pll_data->pll_10) ++ pll_data->pll_10 = pll_10; ++ ++ if (!pll_data->pll_100) ++ pll_data->pll_100 = pll_100; ++ ++ if (!pll_data->pll_1000) ++ pll_data->pll_1000 = pll_1000; ++} ++ ++static int ar71xx_eth_instance __initdata; ++void __init ar71xx_add_device_eth(unsigned int id) ++{ ++ struct platform_device *pdev; ++ struct ag71xx_platform_data *pdata; ++ ++ ar71xx_init_eth_pll_data(id); ++ ++ switch (id) { ++ case 0: ++ switch (ar71xx_eth0_data.phy_if_mode) { ++ case PHY_INTERFACE_MODE_MII: ++ ar71xx_eth0_data.mii_if = MII0_CTRL_IF_MII; ++ break; ++ case PHY_INTERFACE_MODE_GMII: ++ ar71xx_eth0_data.mii_if = MII0_CTRL_IF_GMII; ++ break; ++ case PHY_INTERFACE_MODE_RGMII: ++ ar71xx_eth0_data.mii_if = MII0_CTRL_IF_RGMII; ++ break; ++ case PHY_INTERFACE_MODE_RMII: ++ ar71xx_eth0_data.mii_if = MII0_CTRL_IF_RMII; ++ break; ++ default: ++ printk(KERN_ERR "ar71xx: invalid PHY interface mode " ++ "for eth0\n"); ++ return; ++ } ++ pdev = &ar71xx_eth0_device; ++ break; ++ case 1: ++ switch (ar71xx_eth1_data.phy_if_mode) { ++ case PHY_INTERFACE_MODE_RMII: ++ ar71xx_eth1_data.mii_if = MII1_CTRL_IF_RMII; ++ break; ++ case PHY_INTERFACE_MODE_RGMII: ++ ar71xx_eth1_data.mii_if = MII1_CTRL_IF_RGMII; ++ break; ++ default: ++ printk(KERN_ERR "ar71xx: invalid PHY interface mode " ++ "for eth1\n"); ++ return; ++ } ++ pdev = &ar71xx_eth1_device; ++ break; ++ default: ++ printk(KERN_ERR "ar71xx: invalid ethernet id %d\n", id); ++ return; ++ } ++ ++ pdata = pdev->dev.platform_data; ++ ++ switch (ar71xx_soc) { ++ case AR71XX_SOC_AR7130: ++ pdata->ddr_flush = id ? ar71xx_ddr_flush_ge1 ++ : ar71xx_ddr_flush_ge0; ++ pdata->set_pll = id ? ar71xx_set_pll_ge1 ++ : ar71xx_set_pll_ge0; ++ break; ++ ++ case AR71XX_SOC_AR7141: ++ case AR71XX_SOC_AR7161: ++ pdata->ddr_flush = id ? ar71xx_ddr_flush_ge1 ++ : ar71xx_ddr_flush_ge0; ++ pdata->set_pll = id ? ar71xx_set_pll_ge1 ++ : ar71xx_set_pll_ge0; ++ pdata->has_gbit = 1; ++ break; ++ ++ case AR71XX_SOC_AR7241: ++ case AR71XX_SOC_AR7242: ++ ar71xx_eth0_data.reset_bit |= AR724X_RESET_GE0_MDIO; ++ ar71xx_eth1_data.reset_bit |= AR724X_RESET_GE1_MDIO; ++ /* fall through */ ++ case AR71XX_SOC_AR7240: ++ pdata->ddr_flush = id ? ar724x_ddr_flush_ge1 ++ : ar724x_ddr_flush_ge0; ++ pdata->set_pll = id ? ar724x_set_pll_ge1 ++ : ar724x_set_pll_ge0; ++ pdata->is_ar724x = 1; ++ break; ++ ++ case AR71XX_SOC_AR9130: ++ pdata->ddr_flush = id ? ar91xx_ddr_flush_ge1 ++ : ar91xx_ddr_flush_ge0; ++ pdata->set_pll = id ? ar91xx_set_pll_ge1 ++ : ar91xx_set_pll_ge0; ++ pdata->is_ar91xx = 1; ++ break; ++ ++ case AR71XX_SOC_AR9132: ++ pdata->ddr_flush = id ? ar91xx_ddr_flush_ge1 ++ : ar91xx_ddr_flush_ge0; ++ pdata->set_pll = id ? ar91xx_set_pll_ge1 ++ : ar91xx_set_pll_ge0; ++ pdata->is_ar91xx = 1; ++ pdata->has_gbit = 1; ++ break; ++ ++ default: ++ BUG(); ++ } ++ ++ switch (pdata->phy_if_mode) { ++ case PHY_INTERFACE_MODE_GMII: ++ case PHY_INTERFACE_MODE_RGMII: ++ if (!pdata->has_gbit) { ++ printk(KERN_ERR "ar71xx: no gbit available on eth%d\n", ++ id); ++ return; ++ } ++ /* fallthrough */ ++ default: ++ break; ++ } ++ ++ if (is_valid_ether_addr(ar71xx_mac_base)) { ++ memcpy(pdata->mac_addr, ar71xx_mac_base, ETH_ALEN); ++ pdata->mac_addr[5] += ar71xx_eth_instance; ++ } else { ++ random_ether_addr(pdata->mac_addr); ++ printk(KERN_DEBUG ++ "ar71xx: using random MAC address for eth%d\n", ++ ar71xx_eth_instance); ++ } ++ ++ if (pdata->mii_bus_dev == NULL) ++ pdata->mii_bus_dev = &ar71xx_mdio_device.dev; ++ ++ /* Reset the device */ ++ ar71xx_device_stop(pdata->reset_bit); ++ mdelay(100); ++ ++ ar71xx_device_start(pdata->reset_bit); ++ mdelay(100); ++ ++ platform_device_register(pdev); ++ ar71xx_eth_instance++; ++} ++ ++static struct resource ar71xx_spi_resources[] = { ++ [0] = { ++ .start = AR71XX_SPI_BASE, ++ .end = AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct platform_device ar71xx_spi_device = { ++ .name = "ar71xx-spi", ++ .id = -1, ++ .resource = ar71xx_spi_resources, ++ .num_resources = ARRAY_SIZE(ar71xx_spi_resources), ++}; ++ ++void __init ar71xx_add_device_spi(struct ar71xx_spi_platform_data *pdata, ++ struct spi_board_info const *info, ++ unsigned n) ++{ ++ spi_register_board_info(info, n); ++ ar71xx_spi_device.dev.platform_data = pdata; ++ platform_device_register(&ar71xx_spi_device); ++} ++ ++void __init ar71xx_add_device_wdt(void) ++{ ++ platform_device_register_simple("ar71xx-wdt", -1, NULL, 0); ++} ++ ++void __init ar71xx_set_mac_base(unsigned char *mac) ++{ ++ memcpy(ar71xx_mac_base, mac, ETH_ALEN); ++} ++ ++void __init ar71xx_parse_mac_addr(char *mac_str) ++{ ++ u8 tmp[ETH_ALEN]; ++ int t; ++ ++ t = sscanf(mac_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", ++ &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]); ++ ++ if (t != ETH_ALEN) ++ t = sscanf(mac_str, "%02hhx.%02hhx.%02hhx.%02hhx.%02hhx.%02hhx", ++ &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5]); ++ ++ if (t == ETH_ALEN) ++ ar71xx_set_mac_base(tmp); ++ else ++ printk(KERN_DEBUG "ar71xx: failed to parse mac address " ++ "\"%s\"\n", mac_str); ++} ++ ++static int __init ar71xx_ethaddr_setup(char *str) ++{ ++ ar71xx_parse_mac_addr(str); ++ return 1; ++} ++__setup("ethaddr=", ar71xx_ethaddr_setup); ++ ++static int __init ar71xx_kmac_setup(char *str) ++{ ++ ar71xx_parse_mac_addr(str); ++ return 1; ++} ++__setup("kmac=", ar71xx_kmac_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/devices.h linux-2.6.39/arch/mips/ar71xx/devices.h +--- linux-2.6.39.orig/arch/mips/ar71xx/devices.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/devices.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,48 @@ ++/* ++ * Atheros AR71xx SoC device definitions ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef __AR71XX_DEVICES_H ++#define __AR71XX_DEVICES_H ++ ++#include <asm/mach-ar71xx/platform.h> ++ ++struct platform_device; ++ ++void ar71xx_add_device_spi(struct ar71xx_spi_platform_data *pdata, ++ struct spi_board_info const *info, ++ unsigned n) __init; ++ ++void ar71xx_set_mac_base(unsigned char *mac) __init; ++void ar71xx_parse_mac_addr(char *mac_str) __init; ++ ++struct ar71xx_eth_pll_data { ++ u32 pll_10; ++ u32 pll_100; ++ u32 pll_1000; ++}; ++ ++extern struct ar71xx_eth_pll_data ar71xx_eth0_pll_data; ++extern struct ar71xx_eth_pll_data ar71xx_eth1_pll_data; ++ ++extern struct ag71xx_platform_data ar71xx_eth0_data; ++extern struct ag71xx_platform_data ar71xx_eth1_data; ++extern struct platform_device ar71xx_eth0_device; ++extern struct platform_device ar71xx_eth1_device; ++void ar71xx_add_device_eth(unsigned int id) __init; ++ ++extern struct platform_device ar71xx_mdio_device; ++void ar71xx_add_device_mdio(u32 phy_mask) __init; ++ ++void ar71xx_add_device_uart(void) __init; ++ ++void ar71xx_add_device_wdt(void) __init; ++ ++#endif /* __AR71XX_DEVICES_H */ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/early_printk.c linux-2.6.39/arch/mips/ar71xx/early_printk.c +--- linux-2.6.39.orig/arch/mips/ar71xx/early_printk.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/early_printk.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,30 @@ ++/* ++ * Atheros AR71xx SoC early printk support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/io.h> ++#include <linux/serial_reg.h> ++#include <asm/addrspace.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#define UART_READ(r) \ ++ __raw_readl((void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE) + 4 * (r))) ++ ++#define UART_WRITE(r, v) \ ++ __raw_writel((v), (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE) + 4*(r))) ++ ++void prom_putchar(unsigned char ch) ++{ ++ while (((UART_READ(UART_LSR)) & UART_LSR_THRE) == 0); ++ UART_WRITE(UART_TX, ch); ++ while (((UART_READ(UART_LSR)) & UART_LSR_THRE) == 0); ++} ++ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/gpio.c linux-2.6.39/arch/mips/ar71xx/gpio.c +--- linux-2.6.39.orig/arch/mips/ar71xx/gpio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/gpio.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,182 @@ ++/* ++ * Atheros AR71xx SoC GPIO API support ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/spinlock.h> ++#include <linux/io.h> ++#include <linux/ioport.h> ++#include <linux/gpio.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++static DEFINE_SPINLOCK(ar71xx_gpio_lock); ++ ++unsigned long ar71xx_gpio_count; ++EXPORT_SYMBOL(ar71xx_gpio_count); ++ ++void __ar71xx_gpio_set_value(unsigned gpio, int value) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ ++ if (value) ++ __raw_writel(1 << gpio, base + GPIO_REG_SET); ++ else ++ __raw_writel(1 << gpio, base + GPIO_REG_CLEAR); ++} ++EXPORT_SYMBOL(__ar71xx_gpio_set_value); ++ ++int __ar71xx_gpio_get_value(unsigned gpio) ++{ ++ return (__raw_readl(ar71xx_gpio_base + GPIO_REG_IN) >> gpio) & 1; ++} ++EXPORT_SYMBOL(__ar71xx_gpio_get_value); ++ ++static int ar71xx_gpio_get_value(struct gpio_chip *chip, unsigned offset) ++{ ++ return __ar71xx_gpio_get_value(offset); ++} ++ ++static void ar71xx_gpio_set_value(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ __ar71xx_gpio_set_value(offset, value); ++} ++ ++static int ar71xx_gpio_direction_input(struct gpio_chip *chip, ++ unsigned offset) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ar71xx_gpio_lock, flags); ++ ++ __raw_writel(__raw_readl(base + GPIO_REG_OE) & ~(1 << offset), ++ base + GPIO_REG_OE); ++ ++ spin_unlock_irqrestore(&ar71xx_gpio_lock, flags); ++ ++ return 0; ++} ++ ++static int ar71xx_gpio_direction_output(struct gpio_chip *chip, ++ unsigned offset, int value) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ar71xx_gpio_lock, flags); ++ ++ if (value) ++ __raw_writel(1 << offset, base + GPIO_REG_SET); ++ else ++ __raw_writel(1 << offset, base + GPIO_REG_CLEAR); ++ ++ __raw_writel(__raw_readl(base + GPIO_REG_OE) | (1 << offset), ++ base + GPIO_REG_OE); ++ ++ spin_unlock_irqrestore(&ar71xx_gpio_lock, flags); ++ ++ return 0; ++} ++ ++static struct gpio_chip ar71xx_gpio_chip = { ++ .label = "ar71xx", ++ .get = ar71xx_gpio_get_value, ++ .set = ar71xx_gpio_set_value, ++ .direction_input = ar71xx_gpio_direction_input, ++ .direction_output = ar71xx_gpio_direction_output, ++ .base = 0, ++ .ngpio = AR71XX_GPIO_COUNT, ++}; ++ ++void ar71xx_gpio_function_enable(u32 mask) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ar71xx_gpio_lock, flags); ++ ++ __raw_writel(__raw_readl(base + GPIO_REG_FUNC) | mask, ++ base + GPIO_REG_FUNC); ++ /* flush write */ ++ (void) __raw_readl(base + GPIO_REG_FUNC); ++ ++ spin_unlock_irqrestore(&ar71xx_gpio_lock, flags); ++} ++ ++void ar71xx_gpio_function_disable(u32 mask) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ar71xx_gpio_lock, flags); ++ ++ __raw_writel(__raw_readl(base + GPIO_REG_FUNC) & ~mask, ++ base + GPIO_REG_FUNC); ++ /* flush write */ ++ (void) __raw_readl(base + GPIO_REG_FUNC); ++ ++ spin_unlock_irqrestore(&ar71xx_gpio_lock, flags); ++} ++ ++void ar71xx_gpio_function_setup(u32 set, u32 clear) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&ar71xx_gpio_lock, flags); ++ ++ __raw_writel((__raw_readl(base + GPIO_REG_FUNC) & ~clear) | set, ++ base + GPIO_REG_FUNC); ++ /* flush write */ ++ (void) __raw_readl(base + GPIO_REG_FUNC); ++ ++ spin_unlock_irqrestore(&ar71xx_gpio_lock, flags); ++} ++EXPORT_SYMBOL(ar71xx_gpio_function_setup); ++ ++void __init ar71xx_gpio_init(void) ++{ ++ int err; ++ ++ if (!request_mem_region(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE, ++ "AR71xx GPIO controller")) ++ panic("cannot allocate AR71xx GPIO registers page"); ++ ++ switch (ar71xx_soc) { ++ case AR71XX_SOC_AR7130: ++ case AR71XX_SOC_AR7141: ++ case AR71XX_SOC_AR7161: ++ ar71xx_gpio_chip.ngpio = AR71XX_GPIO_COUNT; ++ break; ++ ++ case AR71XX_SOC_AR7240: ++ case AR71XX_SOC_AR7241: ++ case AR71XX_SOC_AR7242: ++ ar71xx_gpio_chip.ngpio = AR724X_GPIO_COUNT; ++ break; ++ ++ case AR71XX_SOC_AR9130: ++ case AR71XX_SOC_AR9132: ++ ar71xx_gpio_chip.ngpio = AR91XX_GPIO_COUNT; ++ break; ++ ++ default: ++ BUG(); ++ } ++ ++ err = gpiochip_add(&ar71xx_gpio_chip); ++ if (err) ++ panic("cannot add AR71xx GPIO chip, error=%d", err); ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/irq.c linux-2.6.39/arch/mips/ar71xx/irq.c +--- linux-2.6.39.orig/arch/mips/ar71xx/irq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/irq.c 2011-06-01 13:50:58.000000000 +0200 +@@ -0,0 +1,293 @@ ++/* ++ * Atheros AR71xx SoC specific interrupt handling ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/interrupt.h> ++#include <linux/irq.h> ++ ++#include <asm/irq_cpu.h> ++#include <asm/mipsregs.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++static int ip2_flush_reg; ++ ++static void ar71xx_gpio_irq_dispatch(void) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ u32 pending; ++ ++ pending = __raw_readl(base + GPIO_REG_INT_PENDING) & ++ __raw_readl(base + GPIO_REG_INT_ENABLE); ++ ++ if (pending) ++ do_IRQ(AR71XX_GPIO_IRQ_BASE + fls(pending) - 1); ++ else ++ spurious_interrupt(); ++} ++ ++static void ar71xx_gpio_irq_unmask(struct irq_data *d) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ u32 t; ++ ++ d->irq -= AR71XX_GPIO_IRQ_BASE; ++ ++ t = __raw_readl(base + GPIO_REG_INT_ENABLE); ++ __raw_writel(t | (1 << d->irq), base + GPIO_REG_INT_ENABLE); ++ ++ /* flush write */ ++ (void) __raw_readl(base + GPIO_REG_INT_ENABLE); ++} ++ ++static void ar71xx_gpio_irq_mask(struct irq_data *d) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ u32 t; ++ ++ d->irq -= AR71XX_GPIO_IRQ_BASE; ++ ++ t = __raw_readl(base + GPIO_REG_INT_ENABLE); ++ __raw_writel(t & ~(1 << d->irq), base + GPIO_REG_INT_ENABLE); ++ ++ /* flush write */ ++ (void) __raw_readl(base + GPIO_REG_INT_ENABLE); ++} ++ ++#if 0 ++static int ar71xx_gpio_irq_set_type(unsigned int irq, unsigned int flow_type) ++{ ++ /* TODO: implement */ ++ return 0; ++} ++#else ++#define ar71xx_gpio_irq_set_type NULL ++#endif ++ ++static struct irq_chip ar71xx_gpio_irq_chip = { ++ .name = "AR71XX GPIO", ++ .irq_unmask = ar71xx_gpio_irq_unmask, ++ .irq_mask = ar71xx_gpio_irq_mask, ++ .irq_mask_ack = ar71xx_gpio_irq_mask, ++ .irq_set_type = ar71xx_gpio_irq_set_type, ++}; ++ ++static struct irqaction ar71xx_gpio_irqaction = { ++ .handler = no_action, ++ .name = "cascade [AR71XX GPIO]", ++}; ++ ++#define GPIO_IRQ_INIT_STATUS (IRQ_LEVEL | IRQ_TYPE_LEVEL_HIGH) ++#define GPIO_INT_ALL 0xffff ++ ++static void __init ar71xx_gpio_irq_init(void) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ int i; ++ ++ __raw_writel(0, base + GPIO_REG_INT_ENABLE); ++ __raw_writel(0, base + GPIO_REG_INT_PENDING); ++ ++ /* setup type of all GPIO interrupts to level sensitive */ ++ __raw_writel(GPIO_INT_ALL, base + GPIO_REG_INT_TYPE); ++ ++ /* setup polarity of all GPIO interrupts to active high */ ++ __raw_writel(GPIO_INT_ALL, base + GPIO_REG_INT_POLARITY); ++ ++ for (i = AR71XX_GPIO_IRQ_BASE; ++ i < AR71XX_GPIO_IRQ_BASE + AR71XX_GPIO_IRQ_COUNT; i++) { ++ irq_set_chip_and_handler(i, &ar71xx_gpio_irq_chip, ++ handle_level_irq); ++ } ++ ++ setup_irq(AR71XX_MISC_IRQ_GPIO, &ar71xx_gpio_irqaction); ++} ++ ++static void ar71xx_misc_irq_dispatch(void) ++{ ++ u32 pending; ++ ++ pending = ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_STATUS) ++ & ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE); ++ ++ if (pending & MISC_INT_UART) ++ do_IRQ(AR71XX_MISC_IRQ_UART); ++ ++ else if (pending & MISC_INT_DMA) ++ do_IRQ(AR71XX_MISC_IRQ_DMA); ++ ++ else if (pending & MISC_INT_PERFC) ++ do_IRQ(AR71XX_MISC_IRQ_PERFC); ++ ++ else if (pending & MISC_INT_TIMER) ++ do_IRQ(AR71XX_MISC_IRQ_TIMER); ++ ++ else if (pending & MISC_INT_OHCI) ++ do_IRQ(AR71XX_MISC_IRQ_OHCI); ++ ++ else if (pending & MISC_INT_ERROR) ++ do_IRQ(AR71XX_MISC_IRQ_ERROR); ++ ++ else if (pending & MISC_INT_GPIO) ++ ar71xx_gpio_irq_dispatch(); ++ ++ else if (pending & MISC_INT_WDOG) ++ do_IRQ(AR71XX_MISC_IRQ_WDOG); ++ ++ else ++ spurious_interrupt(); ++} ++ ++static void ar71xx_misc_irq_unmask(struct irq_data *d) ++{ ++ void __iomem *base = ar71xx_reset_base; ++ u32 t; ++ ++ d->irq -= AR71XX_MISC_IRQ_BASE; ++ ++ t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); ++ __raw_writel(t | (1 << d->irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE); ++ ++ /* flush write */ ++ (void) __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); ++} ++ ++static void ar71xx_misc_irq_mask(struct irq_data *d) ++{ ++ void __iomem *base = ar71xx_reset_base; ++ u32 t; ++ ++ d->irq -= AR71XX_MISC_IRQ_BASE; ++ ++ t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); ++ __raw_writel(t & ~(1 << d->irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE); ++ ++ /* flush write */ ++ (void) __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); ++} ++ ++static void ar724x_misc_irq_ack(unsigned int irq) ++{ ++ void __iomem *base = ar71xx_reset_base; ++ u32 t; ++ ++ irq -= AR71XX_MISC_IRQ_BASE; ++ ++ t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS); ++ __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_STATUS); ++ ++ /* flush write */ ++ (void) __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS); ++} ++ ++static struct irq_chip ar71xx_misc_irq_chip = { ++ .name = "AR71XX MISC", ++ .irq_unmask = ar71xx_misc_irq_unmask, ++ .irq_mask = ar71xx_misc_irq_mask, ++}; ++ ++static struct irqaction ar71xx_misc_irqaction = { ++ .handler = no_action, ++ .name = "cascade [AR71XX MISC]", ++}; ++ ++static void __init ar71xx_misc_irq_init(void) ++{ ++ void __iomem *base = ar71xx_reset_base; ++ int i; ++ ++ __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE); ++ __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS); ++ ++ switch (ar71xx_soc) { ++ case AR71XX_SOC_AR7240: ++ case AR71XX_SOC_AR7241: ++ case AR71XX_SOC_AR7242: ++ ar71xx_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; ++ break; ++ default: ++ ar71xx_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; ++ break; ++ } ++ ++ for (i = AR71XX_MISC_IRQ_BASE; ++ i < AR71XX_MISC_IRQ_BASE + AR71XX_MISC_IRQ_COUNT; i++) { ++ irq_set_chip_and_handler(i, &ar71xx_misc_irq_chip, ++ handle_level_irq); ++ } ++ ++ setup_irq(AR71XX_CPU_IRQ_MISC, &ar71xx_misc_irqaction); ++} ++ ++asmlinkage void plat_irq_dispatch(void) ++{ ++ unsigned long pending; ++ ++ pending = read_c0_status() & read_c0_cause() & ST0_IM; ++ ++ if (pending & STATUSF_IP7) ++ do_IRQ(AR71XX_CPU_IRQ_TIMER); ++ ++ else if (pending & STATUSF_IP2) { ++ /* ++ * This IRQ is meant for a PCI device. Drivers for PCI devices ++ * typically allocate coherent DMA memory for the descriptor ++ * ring, however the DMA controller may still have some ++ * unsynchronized data in the FIFO. ++ * Issue a flush here to ensure that the driver sees the update. ++ */ ++ ar71xx_ddr_flush(ip2_flush_reg); ++ do_IRQ(AR71XX_CPU_IRQ_IP2); ++ } ++ ++ else if (pending & STATUSF_IP4) ++ do_IRQ(AR71XX_CPU_IRQ_GE0); ++ ++ else if (pending & STATUSF_IP5) ++ do_IRQ(AR71XX_CPU_IRQ_GE1); ++ ++ else if (pending & STATUSF_IP3) ++ do_IRQ(AR71XX_CPU_IRQ_USB); ++ ++ else if (pending & STATUSF_IP6) ++ ar71xx_misc_irq_dispatch(); ++ ++ else ++ spurious_interrupt(); ++} ++ ++void __init arch_init_irq(void) ++{ ++ switch(ar71xx_soc) { ++ case AR71XX_SOC_AR7240: ++ case AR71XX_SOC_AR7241: ++ case AR71XX_SOC_AR7242: ++ ip2_flush_reg = AR724X_DDR_REG_FLUSH_PCIE; ++ break; ++ case AR71XX_SOC_AR9130: ++ case AR71XX_SOC_AR9132: ++ ip2_flush_reg = AR91XX_DDR_REG_FLUSH_WMAC; ++ break; ++ default: ++ ip2_flush_reg = AR71XX_DDR_REG_FLUSH_PCI; ++ break; ++ } ++ mips_cpu_irq_init(); ++ ++ ar71xx_misc_irq_init(); ++ ++ cp0_perfcount_irq = AR71XX_MISC_IRQ_PERFC; ++ ++ ar71xx_gpio_irq_init(); ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-ap81.c linux-2.6.39/arch/mips/ar71xx/mach-ap81.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-ap81.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-ap81.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,140 @@ ++/* ++ * Atheros AP81 board support ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2009 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-ar913x-wmac.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++ ++#define AP81_GPIO_LED_STATUS 1 ++#define AP81_GPIO_LED_AOSS 3 ++#define AP81_GPIO_LED_WLAN 6 ++#define AP81_GPIO_LED_POWER 14 ++ ++#define AP81_GPIO_BTN_SW4 12 ++#define AP81_GPIO_BTN_SW1 21 ++ ++#define AP81_BUTTONS_POLL_INTERVAL 20 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition ap81_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x040000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "u-boot-env", ++ .offset = 0x040000, ++ .size = 0x010000, ++ } , { ++ .name = "rootfs", ++ .offset = 0x050000, ++ .size = 0x500000, ++ } , { ++ .name = "uImage", ++ .offset = 0x550000, ++ .size = 0x100000, ++ } , { ++ .name = "ART", ++ .offset = 0x650000, ++ .size = 0x1b0000, ++ .mask_flags = MTD_WRITEABLE, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data ap81_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = ap81_partitions, ++ .nr_parts = ARRAY_SIZE(ap81_partitions), ++#endif ++}; ++ ++static struct gpio_led ap81_leds_gpio[] __initdata = { ++ { ++ .name = "ap81:green:status", ++ .gpio = AP81_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "ap81:amber:aoss", ++ .gpio = AP81_GPIO_LED_AOSS, ++ .active_low = 1, ++ }, { ++ .name = "ap81:green:wlan", ++ .gpio = AP81_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "ap81:green:power", ++ .gpio = AP81_GPIO_LED_POWER, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button ap81_gpio_buttons[] __initdata = { ++ { ++ .desc = "sw1", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .threshold = 3, ++ .gpio = AP81_GPIO_BTN_SW1, ++ .active_low = 1, ++ } , { ++ .desc = "sw4", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .threshold = 3, ++ .gpio = AP81_GPIO_BTN_SW4, ++ .active_low = 1, ++ } ++}; ++ ++static void __init ap81_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ar71xx_set_mac_base(eeprom); ++ ar71xx_add_device_mdio(0x0); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth0_data.speed = SPEED_100; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ar71xx_eth0_data.has_ar8216 = 1; ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.phy_mask = 0x10; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_usb(); ++ ++ ar71xx_add_device_m25p80(&ap81_flash_data); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(ap81_leds_gpio), ++ ap81_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, AP81_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(ap81_gpio_buttons), ++ ap81_gpio_buttons); ++ ++ ar913x_add_device_wmac(eeprom, NULL); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_AP81, "AP81", "Atheros AP81", ap81_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-ap83.c linux-2.6.39/arch/mips/ar71xx/mach-ap83.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-ap83.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-ap83.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,266 @@ ++/* ++ * Atheros AP83 board support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/delay.h> ++#include <linux/platform_device.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <linux/spi/spi.h> ++#include <linux/spi/spi_gpio.h> ++#include <linux/spi/vsc7385.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/ar91xx_flash.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-ar913x-wmac.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++ ++#define AP83_GPIO_LED_WLAN 6 ++#define AP83_GPIO_LED_POWER 14 ++#define AP83_GPIO_LED_JUMPSTART 15 ++#define AP83_GPIO_BTN_JUMPSTART 12 ++#define AP83_GPIO_BTN_RESET 21 ++ ++#define AP83_050_GPIO_VSC7385_CS 1 ++#define AP83_050_GPIO_VSC7385_MISO 3 ++#define AP83_050_GPIO_VSC7385_MOSI 16 ++#define AP83_050_GPIO_VSC7385_SCK 17 ++ ++#define AP83_BUTTONS_POLL_INTERVAL 20 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition ap83_flash_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x040000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "u-boot-env", ++ .offset = 0x040000, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "kernel", ++ .offset = 0x060000, ++ .size = 0x140000, ++ } , { ++ .name = "rootfs", ++ .offset = 0x1a0000, ++ .size = 0x650000, ++ } , { ++ .name = "art", ++ .offset = 0x7f0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "firmware", ++ .offset = 0x060000, ++ .size = 0x790000, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct ar91xx_flash_platform_data ap83_flash_data = { ++ .width = 2, ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = ap83_flash_partitions, ++ .nr_parts = ARRAY_SIZE(ap83_flash_partitions), ++#endif ++}; ++ ++static struct resource ap83_flash_resources[] = { ++ [0] = { ++ .start = AR71XX_SPI_BASE, ++ .end = AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct platform_device ap83_flash_device = { ++ .name = "ar91xx-flash", ++ .id = -1, ++ .resource = ap83_flash_resources, ++ .num_resources = ARRAY_SIZE(ap83_flash_resources), ++ .dev = { ++ .platform_data = &ap83_flash_data, ++ } ++}; ++ ++static struct gpio_led ap83_leds_gpio[] __initdata = { ++ { ++ .name = "ap83:green:jumpstart", ++ .gpio = AP83_GPIO_LED_JUMPSTART, ++ .active_low = 0, ++ }, { ++ .name = "ap83:green:power", ++ .gpio = AP83_GPIO_LED_POWER, ++ .active_low = 0, ++ }, { ++ .name = "ap83:green:wlan", ++ .gpio = AP83_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_button ap83_gpio_buttons[] __initdata = { ++ { ++ .desc = "soft_reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = AP83_GPIO_BTN_RESET, ++ .active_low = 1, ++ } , { ++ .desc = "jumpstart", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = AP83_GPIO_BTN_JUMPSTART, ++ .active_low = 1, ++ } ++}; ++ ++static struct resource ap83_040_spi_resources[] = { ++ [0] = { ++ .start = AR71XX_SPI_BASE, ++ .end = AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct platform_device ap83_040_spi_device = { ++ .name = "ap83-spi", ++ .id = 0, ++ .resource = ap83_040_spi_resources, ++ .num_resources = ARRAY_SIZE(ap83_040_spi_resources), ++}; ++ ++static struct spi_gpio_platform_data ap83_050_spi_data = { ++ .miso = AP83_050_GPIO_VSC7385_MISO, ++ .mosi = AP83_050_GPIO_VSC7385_MOSI, ++ .sck = AP83_050_GPIO_VSC7385_SCK, ++ .num_chipselect = 1, ++}; ++ ++static struct platform_device ap83_050_spi_device = { ++ .name = "spi_gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &ap83_050_spi_data, ++ } ++}; ++ ++static void ap83_vsc7385_reset(void) ++{ ++ ar71xx_device_stop(RESET_MODULE_GE1_PHY); ++ udelay(10); ++ ar71xx_device_start(RESET_MODULE_GE1_PHY); ++ mdelay(50); ++} ++ ++static struct vsc7385_platform_data ap83_vsc7385_data = { ++ .reset = ap83_vsc7385_reset, ++ .ucode_name = "vsc7385_ucode_ap83.bin", ++ .mac_cfg = { ++ .tx_ipg = 6, ++ .bit2 = 0, ++ .clk_sel = 3, ++ }, ++}; ++ ++static struct spi_board_info ap83_spi_info[] = { ++ { ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 25000000, ++ .modalias = "spi-vsc7385", ++ .platform_data = &ap83_vsc7385_data, ++ .controller_data = (void *) AP83_050_GPIO_VSC7385_CS, ++ } ++}; ++ ++static void __init ap83_generic_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ar71xx_set_mac_base(eeprom); ++ ++ ar71xx_add_device_mdio(0xfffffffe); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth0_data.phy_mask = 0x1; ++ ++ ar71xx_add_device_eth(0); ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth1_data.speed = SPEED_1000; ++ ar71xx_eth1_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_eth1_pll_data.pll_1000 = 0x1f000000; ++ ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(ap83_leds_gpio), ++ ap83_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, AP83_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(ap83_gpio_buttons), ++ ap83_gpio_buttons); ++ ++ ar71xx_add_device_usb(); ++ ++ ar913x_add_device_wmac(eeprom, NULL); ++ ++ platform_device_register(&ap83_flash_device); ++ ++ spi_register_board_info(ap83_spi_info, ARRAY_SIZE(ap83_spi_info)); ++} ++ ++static void __init ap83_040_setup(void) ++{ ++ ap83_flash_data.is_shared=1; ++ ap83_generic_setup(); ++ platform_device_register(&ap83_040_spi_device); ++} ++ ++static void __init ap83_050_setup(void) ++{ ++ ap83_generic_setup(); ++ platform_device_register(&ap83_050_spi_device); ++} ++ ++static void __init ap83_setup(void) ++{ ++ u8 *board_id = (u8 *) KSEG1ADDR(0x1fff1244); ++ unsigned int board_version; ++ ++ board_version = (unsigned int)(board_id[0] - '0'); ++ board_version += ((unsigned int)(board_id[1] - '0')) * 10; ++ ++ switch (board_version) { ++ case 40: ++ ap83_040_setup(); ++ break; ++ case 50: ++ ap83_050_setup(); ++ break; ++ default: ++ printk(KERN_WARNING "AP83-%03u board is not yet supported\n", ++ board_version); ++ } ++} ++ ++MIPS_MACHINE(AR71XX_MACH_AP83, "AP83", "Atheros AP83", ap83_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-aw-nr580.c linux-2.6.39/arch/mips/ar71xx/mach-aw-nr580.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-aw-nr580.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-aw-nr580.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,101 @@ ++/* ++ * AzureWave AW-NR580 board support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/mips_machine.h> ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-gpio-buttons.h" ++#include "dev-pb42-pci.h" ++#include "dev-leds-gpio.h" ++ ++#define AW_NR580_GPIO_LED_READY_RED 0 ++#define AW_NR580_GPIO_LED_WLAN 1 ++#define AW_NR580_GPIO_LED_READY_GREEN 2 ++#define AW_NR580_GPIO_LED_WPS_GREEN 4 ++#define AW_NR580_GPIO_LED_WPS_AMBER 5 ++ ++#define AW_NR580_GPIO_BTN_WPS 3 ++#define AW_NR580_GPIO_BTN_RESET 11 ++ ++#define AW_NR580_BUTTONS_POLL_INTERVAL 20 ++ ++static struct gpio_led aw_nr580_leds_gpio[] __initdata = { ++ { ++ .name = "aw-nr580:red:ready", ++ .gpio = AW_NR580_GPIO_LED_READY_RED, ++ .active_low = 0, ++ }, { ++ .name = "aw-nr580:green:ready", ++ .gpio = AW_NR580_GPIO_LED_READY_GREEN, ++ .active_low = 0, ++ }, { ++ .name = "aw-nr580:green:wps", ++ .gpio = AW_NR580_GPIO_LED_WPS_GREEN, ++ .active_low = 0, ++ }, { ++ .name = "aw-nr580:amber:wps", ++ .gpio = AW_NR580_GPIO_LED_WPS_AMBER, ++ .active_low = 0, ++ }, { ++ .name = "aw-nr580:green:wlan", ++ .gpio = AW_NR580_GPIO_LED_WLAN, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_button aw_nr580_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = AW_NR580_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = AW_NR580_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init aw_nr580_setup(void) ++{ ++ ar71xx_add_device_mdio(0x0); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ar71xx_eth0_data.speed = SPEED_100; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_add_device_eth(0); ++ ++ pb42_pci_init(); ++ ++ ar71xx_add_device_m25p80(NULL); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(aw_nr580_leds_gpio), ++ aw_nr580_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, AW_NR580_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(aw_nr580_gpio_buttons), ++ aw_nr580_gpio_buttons); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_AW_NR580, "AW-NR580", "AzureWave AW-NR580", ++ aw_nr580_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-dir-600-a1.c linux-2.6.39/arch/mips/ar71xx/mach-dir-600-a1.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-dir-600-a1.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-dir-600-a1.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,138 @@ ++/* ++ * D-Link DIR-600 rev. A1 board support ++ * ++ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-ap91-eth.h" ++#include "dev-ap91-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "nvram.h" ++ ++#define DIR_600_A1_GPIO_LED_WPS 0 ++#define DIR_600_A1_GPIO_LED_POWER_AMBER 1 ++#define DIR_600_A1_GPIO_LED_POWER_GREEN 6 ++ ++#define DIR_600_A1_GPIO_BTN_RESET 8 ++#define DIR_600_A1_GPIO_BTN_WPS 12 ++ ++#define DIR_600_A1_BUTTONS_POLL_INTERVAL 20 ++ ++#define DIR_600_A1_NVRAM_ADDR 0x1f030000 ++#define DIR_600_A1_NVRAM_SIZE 0x10000 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition dir_600_a1_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x030000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "nvram", ++ .offset = 0x030000, ++ .size = 0x010000, ++ }, { ++ .name = "kernel", ++ .offset = 0x040000, ++ .size = 0x0e0000, ++ }, { ++ .name = "rootfs", ++ .offset = 0x120000, ++ .size = 0x2c0000, ++ }, { ++ .name = "mac", ++ .offset = 0x3e0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "art", ++ .offset = 0x3f0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "firmware", ++ .offset = 0x040000, ++ .size = 0x3a0000, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data dir_600_a1_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = dir_600_a1_partitions, ++ .nr_parts = ARRAY_SIZE(dir_600_a1_partitions), ++#endif ++}; ++ ++static struct gpio_led dir_600_a1_leds_gpio[] __initdata = { ++ { ++ .name = "dir-600-a1:green:power", ++ .gpio = DIR_600_A1_GPIO_LED_POWER_GREEN, ++ }, { ++ .name = "dir-600-a1:amber:power", ++ .gpio = DIR_600_A1_GPIO_LED_POWER_AMBER, ++ }, { ++ .name = "dir-600-a1:blue:wps", ++ .gpio = DIR_600_A1_GPIO_LED_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button dir_600_a1_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = DIR_600_A1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = DIR_600_A1_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init dir_600_a1_setup(void) ++{ ++ const char *nvram = (char *) KSEG1ADDR(DIR_600_A1_NVRAM_ADDR); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 mac_buff[6]; ++ u8 *mac = NULL; ++ ++ if (nvram_parse_mac_addr(nvram, DIR_600_A1_NVRAM_SIZE, ++ "lan_mac=", mac_buff) == 0) ++ mac = mac_buff; ++ ++ ar71xx_add_device_m25p80(&dir_600_a1_flash_data); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(dir_600_a1_leds_gpio), ++ dir_600_a1_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, DIR_600_A1_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(dir_600_a1_gpio_buttons), ++ dir_600_a1_gpio_buttons); ++ ++ ap91_eth_init(mac, NULL); ++ ap91_pci_init(ee, mac); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_DIR_600_A1, "DIR-600-A1", "D-Link DIR-600 rev. A1", ++ dir_600_a1_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-dir-615-c1.c linux-2.6.39/arch/mips/ar71xx/mach-dir-615-c1.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-dir-615-c1.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-dir-615-c1.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,173 @@ ++/* ++ * D-Link DIR-615 rev C1 board support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-ar913x-wmac.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "nvram.h" ++ ++#define DIR_615C1_GPIO_LED_ORANGE_STATUS 1 /* ORANGE:STATUS:TRICOLOR */ ++#define DIR_615C1_GPIO_LED_BLUE_WPS 3 /* BLUE:WPS */ ++#define DIR_615C1_GPIO_LED_GREEN_WAN 4 /* GREEN:WAN:TRICOLOR */ ++#define DIR_615C1_GPIO_LED_GREEN_WANCPU 5 /* GREEN:WAN:CPU:TRICOLOR */ ++#define DIR_615C1_GPIO_LED_GREEN_WLAN 6 /* GREEN:WLAN */ ++#define DIR_615C1_GPIO_LED_GREEN_STATUS 14 /* GREEN:STATUS:TRICOLOR */ ++#define DIR_615C1_GPIO_LED_ORANGE_WAN 15 /* ORANGE:WAN:TRICOLOR */ ++ ++/* buttons may need refinement */ ++ ++#define DIR_615C1_GPIO_BTN_WPS 12 ++#define DIR_615C1_GPIO_BTN_RESET 21 ++ ++#define DIR_615C1_BUTTONS_POLL_INTERVAL 20 ++ ++#define DIR_615C1_CONFIG_ADDR 0x1f020000 ++#define DIR_615C1_CONFIG_SIZE 0x10000 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition dir_615c1_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "config", ++ .offset = 0x020000, ++ .size = 0x010000, ++ } , { ++ .name = "kernel", ++ .offset = 0x030000, ++ .size = 0x0d0000, ++ } , { ++ .name = "rootfs", ++ .offset = 0x100000, ++ .size = 0x2f0000, ++ } , { ++ .name = "art", ++ .offset = 0x3f0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "firmware", ++ .offset = 0x030000, ++ .size = 0x3c0000, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data dir_615c1_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = dir_615c1_partitions, ++ .nr_parts = ARRAY_SIZE(dir_615c1_partitions), ++#endif ++}; ++ ++static struct gpio_led dir_615c1_leds_gpio[] __initdata = { ++ { ++ .name = "dir-615c1:orange:status", ++ .gpio = DIR_615C1_GPIO_LED_ORANGE_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "dir-615c1:blue:wps", ++ .gpio = DIR_615C1_GPIO_LED_BLUE_WPS, ++ .active_low = 1, ++ }, { ++ .name = "dir-615c1:green:wan", ++ .gpio = DIR_615C1_GPIO_LED_GREEN_WAN, ++ .active_low = 1, ++ }, { ++ .name = "dir-615c1:green:wancpu", ++ .gpio = DIR_615C1_GPIO_LED_GREEN_WANCPU, ++ .active_low = 1, ++ }, { ++ .name = "dir-615c1:green:wlan", ++ .gpio = DIR_615C1_GPIO_LED_GREEN_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "dir-615c1:green:status", ++ .gpio = DIR_615C1_GPIO_LED_GREEN_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "dir-615c1:orange:wan", ++ .gpio = DIR_615C1_GPIO_LED_ORANGE_WAN, ++ .active_low = 1, ++ } ++ ++}; ++ ++static struct gpio_button dir_615c1_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = DIR_615C1_GPIO_BTN_RESET, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = DIR_615C1_GPIO_BTN_WPS, ++ } ++}; ++ ++#define DIR_615C1_LAN_PHYMASK BIT(0) ++#define DIR_615C1_WAN_PHYMASK BIT(4) ++#define DIR_615C1_MDIO_MASK (~(DIR_615C1_LAN_PHYMASK | \ ++ DIR_615C1_WAN_PHYMASK)) ++ ++static void __init dir_615c1_setup(void) ++{ ++ const char *config = (char *) KSEG1ADDR(DIR_615C1_CONFIG_ADDR); ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 mac[6]; ++ u8 *wlan_mac = NULL; ++ ++ if (nvram_parse_mac_addr(config, DIR_615C1_CONFIG_SIZE, ++ "lan_mac=", mac) == 0) { ++ ar71xx_set_mac_base(mac); ++ wlan_mac = mac; ++ } ++ ++ ar71xx_add_device_mdio(DIR_615C1_MDIO_MASK); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth0_data.phy_mask = DIR_615C1_LAN_PHYMASK; ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.phy_mask = DIR_615C1_WAN_PHYMASK; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_m25p80(&dir_615c1_flash_data); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(dir_615c1_leds_gpio), ++ dir_615c1_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, DIR_615C1_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(dir_615c1_gpio_buttons), ++ dir_615c1_gpio_buttons); ++ ++ ar913x_add_device_wmac(eeprom, wlan_mac); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_DIR_615_C1, "DIR-615-C1", "D-Link DIR-615 rev. C1", ++ dir_615c1_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-dir-825-b1.c linux-2.6.39/arch/mips/ar71xx/mach-dir-825-b1.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-dir-825-b1.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-dir-825-b1.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,192 @@ ++/* ++ * D-Link DIR-825 rev. B1 board support ++ * ++ * Copyright (C) 2009 Lukas Kuna, Evkanet, s.r.o. ++ * ++ * based on mach-wndr3700.c ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/platform_device.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <linux/delay.h> ++#include <linux/rtl8366s.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-ap94-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++ ++#define DIR825B1_GPIO_LED_BLUE_USB 0 ++#define DIR825B1_GPIO_LED_ORANGE_POWER 1 ++#define DIR825B1_GPIO_LED_BLUE_POWER 2 ++#define DIR825B1_GPIO_LED_BLUE_POWERSAVE 4 ++#define DIR825B1_GPIO_LED_ORANGE_PLANET 6 ++#define DIR825B1_GPIO_LED_BLUE_PLANET 11 ++ ++#define DIR825B1_GPIO_BTN_RESET 3 ++#define DIR825B1_GPIO_BTN_POWERSAVE 8 ++ ++#define DIR825B1_GPIO_RTL8366_SDA 5 ++#define DIR825B1_GPIO_RTL8366_SCK 7 ++ ++#define DIR825B1_BUTTONS_POLL_INTERVAL 20 ++ ++#define DIR825B1_CAL_LOCATION_0 0x1f661000 ++#define DIR825B1_CAL_LOCATION_1 0x1f665000 ++ ++#define DIR825B1_MAC_LOCATION_0 0x2ffa81b8 ++#define DIR825B1_MAC_LOCATION_1 0x2ffa8370 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition dir825b1_partitions[] = { ++ { ++ .name = "uboot", ++ .offset = 0, ++ .size = 0x040000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "config", ++ .offset = 0x040000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "firmware", ++ .offset = 0x050000, ++ .size = 0x610000, ++ } , { ++ .name = "caldata", ++ .offset = 0x660000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "unknown", ++ .offset = 0x670000, ++ .size = 0x190000, ++ .mask_flags = MTD_WRITEABLE, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data dir825b1_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = dir825b1_partitions, ++ .nr_parts = ARRAY_SIZE(dir825b1_partitions), ++#endif ++}; ++ ++static struct gpio_led dir825b1_leds_gpio[] __initdata = { ++ { ++ .name = "dir825b1:blue:usb", ++ .gpio = DIR825B1_GPIO_LED_BLUE_USB, ++ .active_low = 1, ++ }, { ++ .name = "dir825b1:orange:power", ++ .gpio = DIR825B1_GPIO_LED_ORANGE_POWER, ++ .active_low = 1, ++ }, { ++ .name = "dir825b1:blue:power", ++ .gpio = DIR825B1_GPIO_LED_BLUE_POWER, ++ .active_low = 1, ++ }, { ++ .name = "dir825b1:blue:powersave", ++ .gpio = DIR825B1_GPIO_LED_BLUE_POWERSAVE, ++ .active_low = 1, ++ }, { ++ .name = "dir825b1:orange:planet", ++ .gpio = DIR825B1_GPIO_LED_ORANGE_PLANET, ++ .active_low = 1, ++ }, { ++ .name = "dir825b1:blue:planet", ++ .gpio = DIR825B1_GPIO_LED_BLUE_PLANET, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button dir825b1_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = DIR825B1_GPIO_BTN_RESET, ++ .active_low = 1, ++ } , { ++ .desc = "powersave", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .threshold = 3, ++ .gpio = DIR825B1_GPIO_BTN_POWERSAVE, ++ .active_low = 1, ++ } ++}; ++ ++static struct rtl8366s_platform_data dir825b1_rtl8366s_data = { ++ .gpio_sda = DIR825B1_GPIO_RTL8366_SDA, ++ .gpio_sck = DIR825B1_GPIO_RTL8366_SCK, ++}; ++ ++static struct platform_device dir825b1_rtl8366s_device = { ++ .name = RTL8366S_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &dir825b1_rtl8366s_data, ++ } ++}; ++ ++static void __init dir825b1_setup(void) ++{ ++ u8 mac[6], i; ++ ++ memcpy(mac, (u8*)KSEG1ADDR(DIR825B1_MAC_LOCATION_1), 6); ++ for(i = 5; i >= 3; i--) ++ if(++mac[i] != 0x00) break; ++ ++ ar71xx_set_mac_base(mac); ++ ++ ar71xx_add_device_mdio(0x0); ++ ++ ar71xx_eth0_data.mii_bus_dev = &dir825b1_rtl8366s_device.dev; ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth0_data.speed = SPEED_1000; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ar71xx_eth0_pll_data.pll_1000 = 0x11110000; ++ ++ ar71xx_eth1_data.mii_bus_dev = &dir825b1_rtl8366s_device.dev; ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth1_data.phy_mask = 0x10; ++ ar71xx_eth1_pll_data.pll_1000 = 0x11110000; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_m25p80(&dir825b1_flash_data); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(dir825b1_leds_gpio), ++ dir825b1_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, DIR825B1_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(dir825b1_gpio_buttons), ++ dir825b1_gpio_buttons); ++ ++ ar71xx_add_device_usb(); ++ ++ platform_device_register(&dir825b1_rtl8366s_device); ++ ++ ap94_pci_init((u8 *) KSEG1ADDR(DIR825B1_CAL_LOCATION_0), ++ (u8 *) KSEG1ADDR(DIR825B1_MAC_LOCATION_0), ++ (u8 *) KSEG1ADDR(DIR825B1_CAL_LOCATION_1), ++ (u8 *) KSEG1ADDR(DIR825B1_MAC_LOCATION_1)); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_DIR_825_B1, "DIR-825-B1", "D-Link DIR-825 rev. B1", ++ dir825b1_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-mzk-w04nu.c linux-2.6.39/arch/mips/ar71xx/mach-mzk-w04nu.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-mzk-w04nu.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-mzk-w04nu.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,165 @@ ++/* ++ * Planex MZK-W04NU board support ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-ar913x-wmac.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-m25p80.h" ++#include "dev-usb.h" ++ ++#define MZK_W04NU_GPIO_LED_USB 0 ++#define MZK_W04NU_GPIO_LED_STATUS 1 ++#define MZK_W04NU_GPIO_LED_WPS 3 ++#define MZK_W04NU_GPIO_LED_WLAN 6 ++#define MZK_W04NU_GPIO_LED_AP 15 ++#define MZK_W04NU_GPIO_LED_ROUTER 16 ++ ++#define MZK_W04NU_GPIO_BTN_APROUTER 5 ++#define MZK_W04NU_GPIO_BTN_WPS 12 ++#define MZK_W04NU_GPIO_BTN_RESET 21 ++ ++#define MZK_W04NU_BUTTONS_POLL_INTERVAL 20 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition mzk_w04nu_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x040000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "u-boot-env", ++ .offset = 0x040000, ++ .size = 0x010000, ++ } , { ++ .name = "kernel", ++ .offset = 0x050000, ++ .size = 0x160000, ++ } , { ++ .name = "rootfs", ++ .offset = 0x1b0000, ++ .size = 0x630000, ++ } , { ++ .name = "art", ++ .offset = 0x7e0000, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "firmware", ++ .offset = 0x050000, ++ .size = 0x790000, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data mzk_w04nu_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = mzk_w04nu_partitions, ++ .nr_parts = ARRAY_SIZE(mzk_w04nu_partitions), ++#endif ++}; ++ ++static struct gpio_led mzk_w04nu_leds_gpio[] __initdata = { ++ { ++ .name = "mzk-w04nu:green:status", ++ .gpio = MZK_W04NU_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "mzk-w04nu:blue:wps", ++ .gpio = MZK_W04NU_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "mzk-w04nu:green:wlan", ++ .gpio = MZK_W04NU_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "mzk-w04nu:green:usb", ++ .gpio = MZK_W04NU_GPIO_LED_USB, ++ .active_low = 1, ++ }, { ++ .name = "mzk-w04nu:green:ap", ++ .gpio = MZK_W04NU_GPIO_LED_AP, ++ .active_low = 1, ++ }, { ++ .name = "mzk-w04nu:green:router", ++ .gpio = MZK_W04NU_GPIO_LED_ROUTER, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button mzk_w04nu_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = MZK_W04NU_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = MZK_W04NU_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, { ++ .desc = "aprouter", ++ .type = EV_KEY, ++ .code = BTN_2, ++ .threshold = 3, ++ .gpio = MZK_W04NU_GPIO_BTN_APROUTER, ++ .active_low = 0, ++ } ++}; ++ ++#define MZK_W04NU_WAN_PHYMASK BIT(4) ++#define MZK_W04NU_MDIO_MASK (~MZK_W04NU_WAN_PHYMASK) ++ ++static void __init mzk_w04nu_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ar71xx_set_mac_base(eeprom); ++ ++ ar71xx_add_device_mdio(MZK_W04NU_MDIO_MASK); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth0_data.speed = SPEED_100; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ar71xx_eth0_data.has_ar8216 = 1; ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.phy_mask = MZK_W04NU_WAN_PHYMASK; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_m25p80(&mzk_w04nu_flash_data); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(mzk_w04nu_leds_gpio), ++ mzk_w04nu_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, MZK_W04NU_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(mzk_w04nu_gpio_buttons), ++ mzk_w04nu_gpio_buttons); ++ ar71xx_add_device_usb(); ++ ++ ar913x_add_device_wmac(eeprom, NULL); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_MZK_W04NU, "MZK-W04NU", "Planex MZK-W04NU", ++ mzk_w04nu_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-mzk-w300nh.c linux-2.6.39/arch/mips/ar71xx/mach-mzk-w300nh.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-mzk-w300nh.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-mzk-w300nh.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,158 @@ ++/* ++ * Planex MZK-W300NH board support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-ar913x-wmac.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++ ++#define MZK_W300NH_GPIO_LED_STATUS 1 ++#define MZK_W300NH_GPIO_LED_WPS 3 ++#define MZK_W300NH_GPIO_LED_WLAN 6 ++#define MZK_W300NH_GPIO_LED_AP 15 ++#define MZK_W300NH_GPIO_LED_ROUTER 16 ++ ++#define MZK_W300NH_GPIO_BTN_APROUTER 5 ++#define MZK_W300NH_GPIO_BTN_WPS 12 ++#define MZK_W300NH_GPIO_BTN_RESET 21 ++ ++#define MZK_W04NU_BUTTONS_POLL_INTERVAL 20 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition mzk_w300nh_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x040000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "u-boot-env", ++ .offset = 0x040000, ++ .size = 0x010000, ++ } , { ++ .name = "kernel", ++ .offset = 0x050000, ++ .size = 0x160000, ++ } , { ++ .name = "rootfs", ++ .offset = 0x1b0000, ++ .size = 0x630000, ++ } , { ++ .name = "art", ++ .offset = 0x7e0000, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "firmware", ++ .offset = 0x050000, ++ .size = 0x790000, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data mzk_w300nh_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = mzk_w300nh_partitions, ++ .nr_parts = ARRAY_SIZE(mzk_w300nh_partitions), ++#endif ++}; ++ ++static struct gpio_led mzk_w300nh_leds_gpio[] __initdata = { ++ { ++ .name = "mzk-w300nh:green:status", ++ .gpio = MZK_W300NH_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "mzk-w300nh:blue:wps", ++ .gpio = MZK_W300NH_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "mzk-w300nh:green:wlan", ++ .gpio = MZK_W300NH_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "mzk-w300nh:green:ap", ++ .gpio = MZK_W300NH_GPIO_LED_AP, ++ .active_low = 1, ++ }, { ++ .name = "mzk-w300nh:green:router", ++ .gpio = MZK_W300NH_GPIO_LED_ROUTER, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button mzk_w300nh_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = MZK_W300NH_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = MZK_W300NH_GPIO_BTN_WPS, ++ .active_low = 1, ++ }, { ++ .desc = "aprouter", ++ .type = EV_KEY, ++ .code = BTN_2, ++ .threshold = 3, ++ .gpio = MZK_W300NH_GPIO_BTN_APROUTER, ++ .active_low = 0, ++ } ++}; ++ ++#define MZK_W300NH_WAN_PHYMASK BIT(4) ++#define MZK_W300NH_MDIO_MASK (~MZK_W300NH_WAN_PHYMASK) ++ ++static void __init mzk_w300nh_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ar71xx_set_mac_base(eeprom); ++ ++ ar71xx_add_device_mdio(MZK_W300NH_MDIO_MASK); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth0_data.speed = SPEED_100; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ar71xx_eth0_data.has_ar8216 = 1; ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.phy_mask = MZK_W300NH_WAN_PHYMASK; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_m25p80(&mzk_w300nh_flash_data); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(mzk_w300nh_leds_gpio), ++ mzk_w300nh_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, MZK_W04NU_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(mzk_w300nh_gpio_buttons), ++ mzk_w300nh_gpio_buttons); ++ ar913x_add_device_wmac(eeprom, NULL); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_MZK_W300NH, "MZK-W300NH", "Planex MZK-W300NH", ++ mzk_w300nh_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-nbg460n.c linux-2.6.39/arch/mips/ar71xx/mach-nbg460n.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-nbg460n.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-nbg460n.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,222 @@ ++/* ++ * Zyxel NBG 460N/550N/550NH board support ++ * ++ * Copyright (C) 2010 Michael Kurz <michi.kurz@googlemail.com> ++ * ++ * based on mach-tl-wr1043nd.c ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/platform_device.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <linux/delay.h> ++#include <linux/rtl8366s.h> ++ ++#include <linux/i2c.h> ++#include <linux/i2c-algo-bit.h> ++#include <linux/i2c-gpio.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-ar913x-wmac.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++ ++/* LEDs */ ++#define NBG460N_GPIO_LED_WPS 3 ++#define NBG460N_GPIO_LED_WAN 6 ++#define NBG460N_GPIO_LED_POWER 14 ++#define NBG460N_GPIO_LED_WLAN 15 ++ ++/* Buttons */ ++#define NBG460N_GPIO_BTN_WPS 12 ++#define NBG460N_GPIO_BTN_RESET 21 ++#define NBG460N_BUTTONS_POLL_INTERVAL 20 ++ ++/* RTC chip PCF8563 I2C interface */ ++#define NBG460N_GPIO_PCF8563_SDA 8 ++#define NBG460N_GPIO_PCF8563_SCK 7 ++ ++/* Switch configuration I2C interface */ ++#define NBG460N_GPIO_RTL8366_SDA 16 ++#define NBG460N_GPIO_RTL8366_SCK 18 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition nbg460n_partitions[] = { ++ { ++ .name = "Bootbase", ++ .offset = 0, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "U-Boot Config", ++ .offset = 0x010000, ++ .size = 0x030000, ++ } , { ++ .name = "U-Boot", ++ .offset = 0x040000, ++ .size = 0x030000, ++ } , { ++ .name = "linux", ++ .offset = 0x070000, ++ .size = 0x0e0000, ++ } , { ++ .name = "rootfs", ++ .offset = 0x150000, ++ .size = 0x2a0000, ++ } , { ++ .name = "CalibData", ++ .offset = 0x3f0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "firmware", ++ .offset = 0x070000, ++ .size = 0x380000, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data nbg460n_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = nbg460n_partitions, ++ .nr_parts = ARRAY_SIZE(nbg460n_partitions), ++#endif ++}; ++ ++static struct gpio_led nbg460n_leds_gpio[] __initdata = { ++ { ++ .name = "nbg460n:green:power", ++ .gpio = NBG460N_GPIO_LED_POWER, ++ .active_low = 0, ++ .default_trigger = "default-on", ++ }, { ++ .name = "nbg460n:green:wps", ++ .gpio = NBG460N_GPIO_LED_WPS, ++ .active_low = 0, ++ }, { ++ .name = "nbg460n:green:wlan", ++ .gpio = NBG460N_GPIO_LED_WLAN, ++ .active_low = 0, ++ }, { ++ /* Not really for controlling the LED, ++ when set low the LED blinks uncontrollable */ ++ .name = "nbg460n:green:wan", ++ .gpio = NBG460N_GPIO_LED_WAN, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_button nbg460n_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = NBG460N_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = NBG460N_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static struct i2c_gpio_platform_data nbg460n_i2c_device_platdata = { ++ .sda_pin = NBG460N_GPIO_PCF8563_SDA, ++ .scl_pin = NBG460N_GPIO_PCF8563_SCK, ++ .udelay = 10, ++}; ++ ++static struct platform_device nbg460n_i2c_device = { ++ .name = "i2c-gpio", ++ .id = -1, ++ .num_resources = 0, ++ .resource = NULL, ++ .dev = { ++ .platform_data = &nbg460n_i2c_device_platdata, ++ }, ++}; ++ ++static struct i2c_board_info nbg460n_i2c_devs[] __initdata = { ++ { ++ I2C_BOARD_INFO("pcf8563", 0x51), ++ }, ++}; ++ ++static void __devinit nbg460n_i2c_init(void) ++{ ++ /* The gpio interface */ ++ platform_device_register(&nbg460n_i2c_device); ++ /* I2C devices */ ++ i2c_register_board_info(0, nbg460n_i2c_devs, ++ ARRAY_SIZE(nbg460n_i2c_devs)); ++} ++ ++ ++static struct rtl8366s_platform_data nbg460n_rtl8366s_data = { ++ .gpio_sda = NBG460N_GPIO_RTL8366_SDA, ++ .gpio_sck = NBG460N_GPIO_RTL8366_SCK, ++}; ++ ++static struct platform_device nbg460n_rtl8366s_device = { ++ .name = RTL8366S_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &nbg460n_rtl8366s_data, ++ } ++}; ++ ++static void __init nbg460n_setup(void) ++{ ++ /* end of bootloader sector contains mac address*/ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1fc0fff8); ++ /* last sector contains wlan calib data */ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ar71xx_set_mac_base(mac); ++ ++ /* LAN Port */ ++ ar71xx_eth0_data.mii_bus_dev = &nbg460n_rtl8366s_device.dev; ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth0_data.speed = SPEED_1000; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ++ /* WAN Port */ ++ ar71xx_eth1_data.mii_bus_dev = &nbg460n_rtl8366s_device.dev; ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth1_data.phy_mask = 0x10; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ /* register the switch phy */ ++ platform_device_register(&nbg460n_rtl8366s_device); ++ ++ /* register flash */ ++ ar71xx_add_device_m25p80(&nbg460n_flash_data); ++ ++ ar913x_add_device_wmac(eeprom, mac); ++ ++ /* register RTC chip */ ++ nbg460n_i2c_init(); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(nbg460n_leds_gpio), ++ nbg460n_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, NBG460N_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(nbg460n_gpio_buttons), ++ nbg460n_gpio_buttons); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_NBG460N, "NBG460N", "Zyxel NBG460N/550N/550NH", nbg460n_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-pb42.c linux-2.6.39/arch/mips/ar71xx/mach-pb42.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-pb42.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-pb42.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,71 @@ ++/* ++ * Atheros PB42 board support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-gpio-buttons.h" ++#include "dev-pb42-pci.h" ++#include "dev-usb.h" ++ ++#define PB42_BUTTONS_POLL_INTERVAL 20 ++ ++#define PB42_GPIO_BTN_SW4 8 ++#define PB42_GPIO_BTN_SW5 3 ++ ++static struct gpio_button pb42_gpio_buttons[] __initdata = { ++ { ++ .desc = "sw4", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .threshold = 3, ++ .gpio = PB42_GPIO_BTN_SW4, ++ .active_low = 1, ++ } , { ++ .desc = "sw5", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .threshold = 3, ++ .gpio = PB42_GPIO_BTN_SW5, ++ .active_low = 1, ++ } ++}; ++ ++#define PB42_WAN_PHYMASK BIT(20) ++#define PB42_LAN_PHYMASK (BIT(16) | BIT(17) | BIT(18) | BIT(19)) ++#define PB42_MDIO_PHYMASK (PB42_LAN_PHYMASK | PB42_WAN_PHYMASK) ++ ++static void __init pb42_init(void) ++{ ++ ar71xx_add_device_m25p80(NULL); ++ ++ ar71xx_add_device_mdio(~PB42_MDIO_PHYMASK); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ar71xx_eth0_data.phy_mask = PB42_WAN_PHYMASK; ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.speed = SPEED_100; ++ ar71xx_eth1_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_gpio_buttons(-1, PB42_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(pb42_gpio_buttons), ++ pb42_gpio_buttons); ++ ++ pb42_pci_init(); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_PB42, "PB42", "Atheros PB42", pb42_init); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-pb44.c linux-2.6.39/arch/mips/ar71xx/mach-pb44.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-pb44.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-pb44.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,207 @@ ++/* ++ * Atheros PB44 board support ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/init.h> ++#include <linux/bitops.h> ++#include <linux/delay.h> ++#include <linux/platform_device.h> ++#include <linux/spi/spi.h> ++#include <linux/spi/flash.h> ++#include <linux/spi/vsc7385.h> ++#include <linux/i2c.h> ++#include <linux/i2c-gpio.h> ++#include <linux/i2c/pcf857x.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-pb42-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++ ++#define PB44_PCF8757_VSC7395_CS 0 ++#define PB44_PCF8757_STEREO_CS 1 ++#define PB44_PCF8757_SLIC_CS0 2 ++#define PB44_PCF8757_SLIC_TEST 3 ++#define PB44_PCF8757_SLIC_INT0 4 ++#define PB44_PCF8757_SLIC_INT1 5 ++#define PB44_PCF8757_SW_RESET 6 ++#define PB44_PCF8757_SW_JUMP 8 ++#define PB44_PCF8757_LED_JUMP1 9 ++#define PB44_PCF8757_LED_JUMP2 10 ++#define PB44_PCF8757_TP24 11 ++#define PB44_PCF8757_TP25 12 ++#define PB44_PCF8757_TP26 13 ++#define PB44_PCF8757_TP27 14 ++#define PB44_PCF8757_TP28 15 ++ ++#define PB44_GPIO_I2C_SCL 0 ++#define PB44_GPIO_I2C_SDA 1 ++ ++#define PB44_GPIO_EXP_BASE 16 ++#define PB44_GPIO_VSC7395_CS (PB44_GPIO_EXP_BASE + PB44_PCF8757_VSC7395_CS) ++#define PB44_GPIO_SW_RESET (PB44_GPIO_EXP_BASE + PB44_PCF8757_SW_RESET) ++#define PB44_GPIO_SW_JUMP (PB44_GPIO_EXP_BASE + PB44_PCF8757_SW_JUMP) ++#define PB44_GPIO_LED_JUMP1 (PB44_GPIO_EXP_BASE + PB44_PCF8757_LED_JUMP1) ++#define PB44_GPIO_LED_JUMP2 (PB44_GPIO_EXP_BASE + PB44_PCF8757_LED_JUMP2) ++ ++static struct i2c_gpio_platform_data pb44_i2c_gpio_data = { ++ .sda_pin = PB44_GPIO_I2C_SDA, ++ .scl_pin = PB44_GPIO_I2C_SCL, ++}; ++ ++static struct platform_device pb44_i2c_gpio_device = { ++ .name = "i2c-gpio", ++ .id = 0, ++ .dev = { ++ .platform_data = &pb44_i2c_gpio_data, ++ } ++}; ++ ++static struct pcf857x_platform_data pb44_pcf857x_data = { ++ .gpio_base = PB44_GPIO_EXP_BASE, ++}; ++ ++static struct i2c_board_info pb44_i2c_board_info[] __initdata = { ++ { ++ I2C_BOARD_INFO("pcf8575", 0x20), ++ .platform_data = &pb44_pcf857x_data, ++ }, ++}; ++ ++static struct gpio_led pb44_leds_gpio[] __initdata = { ++ { ++ .name = "pb44:amber:jump1", ++ .gpio = PB44_GPIO_LED_JUMP1, ++ .active_low = 1, ++ }, { ++ .name = "pb44:green:jump2", ++ .gpio = PB44_GPIO_LED_JUMP2, ++ .active_low = 1, ++ }, ++}; ++ ++static struct gpio_button pb44_gpio_buttons[] __initdata = { ++ { ++ .desc = "soft_reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = PB44_GPIO_SW_RESET, ++ .active_low = 1, ++ } , { ++ .desc = "jumpstart", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = PB44_GPIO_SW_JUMP, ++ .active_low = 1, ++ } ++}; ++ ++static void pb44_vsc7395_reset(void) ++{ ++ ar71xx_device_stop(RESET_MODULE_GE1_PHY); ++ udelay(10); ++ ar71xx_device_start(RESET_MODULE_GE1_PHY); ++ mdelay(50); ++} ++ ++static struct vsc7385_platform_data pb44_vsc7395_data = { ++ .reset = pb44_vsc7395_reset, ++ .ucode_name = "vsc7395_ucode_pb44.bin", ++ .mac_cfg = { ++ .tx_ipg = 6, ++ .bit2 = 1, ++ .clk_sel = 0, ++ }, ++}; ++ ++static struct spi_board_info pb44_spi_info[] = { ++ { ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 25000000, ++ .modalias = "m25p80", ++ }, { ++ .bus_num = 0, ++ .chip_select = 1, ++ .max_speed_hz = 25000000, ++ .modalias = "spi-vsc7385", ++ .platform_data = &pb44_vsc7395_data, ++ .controller_data = (void *) PB44_GPIO_VSC7395_CS, ++ }, ++}; ++ ++static struct resource pb44_spi_resources[] = { ++ [0] = { ++ .start = AR71XX_SPI_BASE, ++ .end = AR71XX_SPI_BASE + AR71XX_SPI_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct ar71xx_spi_platform_data pb44_spi_data = { ++ .bus_num = 0, ++ .num_chipselect = 2, ++}; ++ ++static struct platform_device pb44_spi_device = { ++ .name = "pb44-spi", ++ .id = -1, ++ .resource = pb44_spi_resources, ++ .num_resources = ARRAY_SIZE(pb44_spi_resources), ++ .dev = { ++ .platform_data = &pb44_spi_data, ++ }, ++}; ++ ++#define PB44_WAN_PHYMASK BIT(0) ++#define PB44_LAN_PHYMASK 0 ++#define PB44_MDIO_PHYMASK (PB44_LAN_PHYMASK | PB44_WAN_PHYMASK) ++ ++static void __init pb44_init(void) ++{ ++ ar71xx_add_device_mdio(~PB44_MDIO_PHYMASK); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth0_data.phy_mask = PB44_WAN_PHYMASK; ++ ++ ar71xx_add_device_eth(0); ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth1_data.speed = SPEED_1000; ++ ar71xx_eth1_data.duplex = DUPLEX_FULL; ++ ar71xx_eth1_pll_data.pll_1000 = 0x110000; ++ ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_usb(); ++ ++ pb42_pci_init(); ++ ++ i2c_register_board_info(0, pb44_i2c_board_info, ++ ARRAY_SIZE(pb44_i2c_board_info)); ++ ++ platform_device_register(&pb44_i2c_gpio_device); ++ ++ spi_register_board_info(pb44_spi_info, ARRAY_SIZE(pb44_spi_info)); ++ platform_device_register(&pb44_spi_device); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(pb44_leds_gpio), ++ pb44_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, 20, ARRAY_SIZE(pb44_gpio_buttons), ++ pb44_gpio_buttons); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_PB44, "PB44", "Atheros PB44", pb44_init); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-pb92.c linux-2.6.39/arch/mips/ar71xx/mach-pb92.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-pb92.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-pb92.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,109 @@ ++/* ++ * Atheros PB92 board support ++ * ++ * Copyright (C) 2010 Felix Fietkau <nbd@openwrt.org> ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-gpio-buttons.h" ++#include "dev-pb9x-pci.h" ++#include "dev-usb.h" ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition pb92_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x040000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "u-boot-env", ++ .offset = 0x040000, ++ .size = 0x010000, ++ } , { ++ .name = "rootfs", ++ .offset = 0x050000, ++ .size = 0x2b0000, ++ } , { ++ .name = "uImage", ++ .offset = 0x300000, ++ .size = 0x0e0000, ++ } , { ++ .name = "ART", ++ .offset = 0x3e0000, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data pb92_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = pb92_partitions, ++ .nr_parts = ARRAY_SIZE(pb92_partitions), ++#endif ++}; ++ ++ ++#define PB92_BUTTONS_POLL_INTERVAL 20 ++ ++#define PB92_GPIO_BTN_SW4 8 ++#define PB92_GPIO_BTN_SW5 3 ++ ++static struct gpio_button pb92_gpio_buttons[] __initdata = { ++ { ++ .desc = "sw4", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .threshold = 3, ++ .gpio = PB92_GPIO_BTN_SW4, ++ .active_low = 1, ++ } , { ++ .desc = "sw5", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .threshold = 3, ++ .gpio = PB92_GPIO_BTN_SW5, ++ .active_low = 1, ++ } ++}; ++ ++static void __init pb92_init(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ar71xx_set_mac_base(mac); ++ ar71xx_add_device_m25p80(&pb92_flash_data); ++ ++ ar71xx_add_device_mdio(~0); ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth0_data.speed = SPEED_1000; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.speed = SPEED_1000; ++ ar71xx_eth1_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_gpio_buttons(-1, PB92_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(pb92_gpio_buttons), ++ pb92_gpio_buttons); ++ ++ pb9x_pci_init(); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_PB92, "PB92", "Atheros PB92", pb92_init); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-rb4xx.c linux-2.6.39/arch/mips/ar71xx/mach-rb4xx.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-rb4xx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-rb4xx.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,290 @@ ++/* ++ * MikroTik RouterBOARD 4xx series support ++ * ++ * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/platform_device.h> ++#include <linux/irq.h> ++#include <linux/mmc/host.h> ++#include <linux/spi/spi.h> ++#include <linux/spi/flash.h> ++#include <linux/spi/mmc_spi.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/pci.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++ ++#define RB4XX_GPIO_USER_LED 4 ++#define RB4XX_GPIO_RESET_SWITCH 7 ++ ++#define RB4XX_BUTTONS_POLL_INTERVAL 20 ++ ++static struct gpio_led rb4xx_leds_gpio[] __initdata = { ++ { ++ .name = "rb4xx:yellow:user", ++ .gpio = RB4XX_GPIO_USER_LED, ++ .active_low = 0, ++ }, ++}; ++ ++static struct gpio_button rb4xx_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset_switch", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = RB4XX_GPIO_RESET_SWITCH, ++ .active_low = 1, ++ } ++}; ++ ++static struct platform_device rb4xx_nand_device = { ++ .name = "rb4xx-nand", ++ .id = -1, ++}; ++ ++static struct ar71xx_pci_irq rb4xx_pci_irqs[] __initdata = { ++ { ++ .slot = 0, ++ .pin = 1, ++ .irq = AR71XX_PCI_IRQ_DEV2, ++ }, { ++ .slot = 1, ++ .pin = 1, ++ .irq = AR71XX_PCI_IRQ_DEV0, ++ }, { ++ .slot = 1, ++ .pin = 2, ++ .irq = AR71XX_PCI_IRQ_DEV1, ++ }, { ++ .slot = 2, ++ .pin = 1, ++ .irq = AR71XX_PCI_IRQ_DEV1, ++ }, { ++ .slot = 3, ++ .pin = 1, ++ .irq = AR71XX_PCI_IRQ_DEV2, ++ } ++}; ++ ++#if 0 ++/* ++ * SPI device support is experimental ++ */ ++static struct flash_platform_data rb4xx_flash_data = { ++ .type = "pm25lv512", ++}; ++ ++static struct spi_board_info rb4xx_spi_info[] = { ++ { ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 25000000, ++ .modalias = "m25p80", ++ .platform_data = &rb4xx_flash_data, ++ } ++}; ++ ++static struct mmc_spi_platform_data rb433_mmc_data = { ++ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, ++}; ++ ++static struct spi_board_info rb433_spi_info[] = { ++ { ++ .bus_num = 0, ++ .chip_select = 0, ++ .max_speed_hz = 25000000, ++ .modalias = "m25p80", ++ .platform_data = &rb433_flash_data, ++ }, { ++ .bus_num = 0, ++ .chip_select = 2, ++ .max_speed_hz = 25000000, ++ .modalias = "mmc_spi", ++ .platform_data = &rb433_mmc_data, ++ } ++}; ++ ++static u32 rb433_spi_get_ioc_base(u8 chip_select, int cs_high, int is_on) ++{ ++ u32 ret; ++ ++ if (is_on == AR71XX_SPI_CS_INACTIVE) { ++ ret = SPI_IOC_CS0 | SPI_IOC_CS1; ++ } else { ++ if (cs_high) { ++ ret = SPI_IOC_CS0 | SPI_IOC_CS1; ++ } else { ++ if ((chip_select ^ 2) == 0) ++ ret = SPI_IOC_CS1 ^ (SPI_IOC_CS0 | SPI_IOC_CS1); ++ else ++ ret = SPI_IOC_CS0 ^ (SPI_IOC_CS0 | SPI_IOC_CS1); ++ } ++ } ++ ++ return ret; ++} ++ ++struct ar71xx_spi_platform_data rb433_spi_data = { ++ .bus_num = 0, ++ .num_chipselect = 3, ++ .get_ioc_base = rb433_spi_get_ioc_base, ++}; ++ ++static void rb4xx_add_device_spi(void) ++{ ++ ar71xx_add_device_spi(NULL, rb4xx_spi_info, ARRAY_SIZE(rb4xx_spi_info)); ++} ++ ++static void rb433_add_device_spi(void) ++{ ++ ar71xx_add_device_spi(&rb433_spi_data, rb433_spi_info, ++ ARRAY_SIZE(rb433_spi_info)); ++} ++#else ++static inline void rb4xx_add_device_spi(void) {} ++static inline void rb433_add_device_spi(void) {} ++#endif ++ ++static void __init rb4xx_generic_setup(void) ++{ ++ ar71xx_gpio_function_enable(AR71XX_GPIO_FUNC_SPI_CS1_EN | ++ AR71XX_GPIO_FUNC_SPI_CS2_EN); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(rb4xx_leds_gpio), ++ rb4xx_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, RB4XX_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(rb4xx_gpio_buttons), ++ rb4xx_gpio_buttons); ++ ++ platform_device_register(&rb4xx_nand_device); ++} ++ ++static void __init rb411_setup(void) ++{ ++ rb4xx_generic_setup(); ++ rb4xx_add_device_spi(); ++ ++ ar71xx_add_device_mdio(0xfffffffc); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ar71xx_eth0_data.phy_mask = 0x00000003; ++ ++ ar71xx_add_device_eth(0); ++ ++ ar71xx_pci_init(ARRAY_SIZE(rb4xx_pci_irqs), rb4xx_pci_irqs); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_RB_411, "411", "MikroTik RouterBOARD 411/A/AH", ++ rb411_setup); ++ ++static void __init rb411u_setup(void) ++{ ++ rb411_setup(); ++ ar71xx_add_device_usb(); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_RB_411U, "411U", "MikroTik RouterBOARD 411U", ++ rb411u_setup); ++ ++static void __init rb433_setup(void) ++{ ++ rb4xx_generic_setup(); ++ rb433_add_device_spi(); ++ ++ ar71xx_add_device_mdio(0xffffffe9); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ar71xx_eth0_data.speed = SPEED_100; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.phy_mask = 0x00000010; ++ ++ ar71xx_add_device_eth(1); ++ ar71xx_add_device_eth(0); ++ ++ ar71xx_pci_init(ARRAY_SIZE(rb4xx_pci_irqs), rb4xx_pci_irqs); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_RB_433, "433", "MikroTik RouterBOARD 433/AH", ++ rb433_setup); ++ ++static void __init rb433u_setup(void) ++{ ++ rb433_setup(); ++ ar71xx_add_device_usb(); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_RB_433U, "433U", "MikroTik RouterBOARD 433UAH", ++ rb433u_setup); ++ ++static void __init rb450_generic_setup(int gige) ++{ ++ rb4xx_generic_setup(); ++ rb4xx_add_device_spi(); ++ ++ ar71xx_add_device_mdio(0xffffffe0); ++ ++ ar71xx_eth0_data.phy_if_mode = (gige) ? PHY_INTERFACE_MODE_RGMII : PHY_INTERFACE_MODE_MII; ++ ar71xx_eth0_data.phy_mask = (gige) ? (1 << 0) : 0; ++ ar71xx_eth0_data.speed = (gige) ? SPEED_1000 : SPEED_100; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_eth1_data.phy_if_mode = (gige) ? PHY_INTERFACE_MODE_RGMII : PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.phy_mask = 0x00000010; ++ ++ ar71xx_add_device_eth(1); ++ ar71xx_add_device_eth(0); ++} ++ ++static void __init rb450_setup(void) ++{ ++ rb450_generic_setup(0); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_RB_450, "450", "MikroTik RouterBOARD 450", ++ rb450_setup); ++ ++static void __init rb450g_setup(void) ++{ ++ rb450_generic_setup(1); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_RB_450G, "450G", "MikroTik RouterBOARD 450G", ++ rb450g_setup); ++ ++static void __init rb493_setup(void) ++{ ++ rb4xx_generic_setup(); ++ rb4xx_add_device_spi(); ++ ++ ar71xx_add_device_mdio(0x3fffff00); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ar71xx_eth0_data.speed = SPEED_100; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.phy_mask = 0x00000001; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_pci_init(ARRAY_SIZE(rb4xx_pci_irqs), rb4xx_pci_irqs); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_RB_493, "493", "MikroTik RouterBOARD 493/AH", ++ rb493_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-rb750.c linux-2.6.39/arch/mips/ar71xx/mach-rb750.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-rb750.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-rb750.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,133 @@ ++/* ++ * MikroTik RouterBOARD 750 support ++ * ++ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/platform_device.h> ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/mach-rb750.h> ++ ++#include "machtype.h" ++#include "dev-ap91-eth.h" ++ ++static struct rb750_led_data rb750_leds[] = { ++ { ++ .name = "rb750:green:act", ++ .mask = RB750_LED_ACT, ++ .active_low = 1, ++ }, { ++ .name = "rb750:green:port1", ++ .mask = RB750_LED_PORT5, ++ .active_low = 1, ++ }, { ++ .name = "rb750:green:port2", ++ .mask = RB750_LED_PORT4, ++ .active_low = 1, ++ }, { ++ .name = "rb750:green:port3", ++ .mask = RB750_LED_PORT3, ++ .active_low = 1, ++ }, { ++ .name = "rb750:green:port4", ++ .mask = RB750_LED_PORT2, ++ .active_low = 1, ++ }, { ++ .name = "rb750:green:port5", ++ .mask = RB750_LED_PORT1, ++ .active_low = 1, ++ } ++}; ++ ++static struct rb750_led_platform_data rb750_leds_data = { ++ .num_leds = ARRAY_SIZE(rb750_leds), ++ .leds = rb750_leds, ++}; ++ ++static struct platform_device rb750_leds_device = { ++ .name = "leds-rb750", ++ .dev = { ++ .platform_data = &rb750_leds_data, ++ } ++}; ++ ++static const char *rb750_port_names[AP91_ETH_NUM_PORT_NAMES] __initdata = { ++ "port5", ++ "port4", ++ "port3", ++ "port2", ++}; ++ ++static struct platform_device rb750_nand_device = { ++ .name = "rb750-nand", ++ .id = -1, ++}; ++ ++int rb750_latch_change(u32 mask_clr, u32 mask_set) ++{ ++ static DEFINE_SPINLOCK(lock); ++ static u32 latch_set = RB750_LED_BITS | RB750_LVC573_LE; ++ static u32 latch_oe; ++ static u32 latch_clr; ++ unsigned long flags; ++ u32 t; ++ int ret = 0; ++ ++ spin_lock_irqsave(&lock, flags); ++ ++ if ((mask_clr & BIT(31)) != 0 && ++ (latch_set & RB750_LVC573_LE) == 0) { ++ goto unlock; ++ } ++ ++ latch_set = (latch_set | mask_set) & ~mask_clr; ++ latch_clr = (latch_clr | mask_clr) & ~mask_set; ++ ++ if (latch_oe == 0) ++ latch_oe = __raw_readl(ar71xx_gpio_base + GPIO_REG_OE); ++ ++ if (likely(latch_set & RB750_LVC573_LE)) { ++ void __iomem *base = ar71xx_gpio_base; ++ ++ t = __raw_readl(base + GPIO_REG_OE); ++ t |= mask_clr | latch_oe | mask_set; ++ ++ __raw_writel(t, base + GPIO_REG_OE); ++ __raw_writel(latch_clr, base + GPIO_REG_CLEAR); ++ __raw_writel(latch_set, base + GPIO_REG_SET); ++ } else if (mask_clr & RB750_LVC573_LE) { ++ void __iomem *base = ar71xx_gpio_base; ++ ++ latch_oe = __raw_readl(base + GPIO_REG_OE); ++ __raw_writel(RB750_LVC573_LE, base + GPIO_REG_CLEAR); ++ /* flush write */ ++ __raw_readl(base + GPIO_REG_CLEAR); ++ } ++ ++ ret = 1; ++ ++ unlock: ++ spin_unlock_irqrestore(&lock, flags); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(rb750_latch_change); ++ ++static void __init rb750_setup(void) ++{ ++ ar71xx_gpio_function_disable(AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN | ++ AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN); ++ ++ ap91_eth_init(NULL, rb750_port_names); ++ platform_device_register(&rb750_leds_device); ++ platform_device_register(&rb750_nand_device); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_RB_750, "750i", "MikroTik RouterBOARD 750", ++ rb750_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-tew-632brp.c linux-2.6.39/arch/mips/ar71xx/mach-tew-632brp.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-tew-632brp.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-tew-632brp.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,149 @@ ++/* ++ * TrendNET TEW-632BRP board support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-ar913x-wmac.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "nvram.h" ++ ++#define TEW_632BRP_GPIO_LED_STATUS 1 ++#define TEW_632BRP_GPIO_LED_WPS 3 ++#define TEW_632BRP_GPIO_LED_WLAN 6 ++#define TEW_632BRP_GPIO_BTN_WPS 12 ++#define TEW_632BRP_GPIO_BTN_RESET 21 ++ ++#define TEW_632BRP_BUTTONS_POLL_INTERVAL 20 ++ ++#define TEW_632BRP_CONFIG_ADDR 0x1f020000 ++#define TEW_632BRP_CONFIG_SIZE 0x10000 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition tew_632brp_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "config", ++ .offset = 0x020000, ++ .size = 0x010000, ++ } , { ++ .name = "kernel", ++ .offset = 0x030000, ++ .size = 0x0d0000, ++ } , { ++ .name = "rootfs", ++ .offset = 0x100000, ++ .size = 0x2f0000, ++ } , { ++ .name = "art", ++ .offset = 0x3f0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "firmware", ++ .offset = 0x030000, ++ .size = 0x3c0000, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data tew_632brp_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = tew_632brp_partitions, ++ .nr_parts = ARRAY_SIZE(tew_632brp_partitions), ++#endif ++}; ++ ++static struct gpio_led tew_632brp_leds_gpio[] __initdata = { ++ { ++ .name = "tew-632brp:green:status", ++ .gpio = TEW_632BRP_GPIO_LED_STATUS, ++ .active_low = 1, ++ }, { ++ .name = "tew-632brp:blue:wps", ++ .gpio = TEW_632BRP_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "tew-632brp:green:wlan", ++ .gpio = TEW_632BRP_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button tew_632brp_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = TEW_632BRP_GPIO_BTN_RESET, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = TEW_632BRP_GPIO_BTN_WPS, ++ } ++}; ++ ++#define TEW_632BRP_LAN_PHYMASK BIT(0) ++#define TEW_632BRP_WAN_PHYMASK BIT(4) ++#define TEW_632BRP_MDIO_MASK (~(TEW_632BRP_LAN_PHYMASK | \ ++ TEW_632BRP_WAN_PHYMASK)) ++ ++static void __init tew_632brp_setup(void) ++{ ++ const char *config = (char *) KSEG1ADDR(TEW_632BRP_CONFIG_ADDR); ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 mac[6]; ++ u8 *wlan_mac = NULL; ++ ++ if (nvram_parse_mac_addr(config, TEW_632BRP_CONFIG_SIZE, ++ "lan_mac=", mac) == 0) { ++ ar71xx_set_mac_base(mac); ++ wlan_mac = mac; ++ } ++ ++ ar71xx_add_device_mdio(TEW_632BRP_MDIO_MASK); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth0_data.phy_mask = TEW_632BRP_LAN_PHYMASK; ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.phy_mask = TEW_632BRP_WAN_PHYMASK; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_m25p80(&tew_632brp_flash_data); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(tew_632brp_leds_gpio), ++ tew_632brp_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, TEW_632BRP_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(tew_632brp_gpio_buttons), ++ tew_632brp_gpio_buttons); ++ ++ ar913x_add_device_wmac(eeprom, wlan_mac); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_TEW_632BRP, "TEW-632BRP", "TRENDnet TEW-632BRP", ++ tew_632brp_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-tl-wr1043nd.c linux-2.6.39/arch/mips/ar71xx/mach-tl-wr1043nd.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-tl-wr1043nd.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-tl-wr1043nd.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,156 @@ ++/* ++ * TP-LINK TL-WR1043ND board support ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <linux/platform_device.h> ++#include <linux/rtl8366rb.h> ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-ar913x-wmac.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++ ++#define TL_WR1043ND_GPIO_LED_USB 1 ++#define TL_WR1043ND_GPIO_LED_SYSTEM 2 ++#define TL_WR1043ND_GPIO_LED_QSS 5 ++#define TL_WR1043ND_GPIO_LED_WLAN 9 ++ ++#define TL_WR1043ND_GPIO_BTN_RESET 3 ++#define TL_WR1043ND_GPIO_BTN_QSS 7 ++ ++#define TL_WR1043ND_GPIO_RTL8366_SDA 18 ++#define TL_WR1043ND_GPIO_RTL8366_SCK 19 ++ ++#define TL_WR1043ND_BUTTONS_POLL_INTERVAL 20 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition tl_wr1043nd_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "kernel", ++ .offset = 0x020000, ++ .size = 0x140000, ++ } , { ++ .name = "rootfs", ++ .offset = 0x160000, ++ .size = 0x690000, ++ } , { ++ .name = "art", ++ .offset = 0x7f0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "firmware", ++ .offset = 0x020000, ++ .size = 0x7d0000, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data tl_wr1043nd_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = tl_wr1043nd_partitions, ++ .nr_parts = ARRAY_SIZE(tl_wr1043nd_partitions), ++#endif ++}; ++ ++static struct gpio_led tl_wr1043nd_leds_gpio[] __initdata = { ++ { ++ .name = "tl-wr1043nd:green:usb", ++ .gpio = TL_WR1043ND_GPIO_LED_USB, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr1043nd:green:system", ++ .gpio = TL_WR1043ND_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr1043nd:green:qss", ++ .gpio = TL_WR1043ND_GPIO_LED_QSS, ++ .active_low = 0, ++ }, { ++ .name = "tl-wr1043nd:green:wlan", ++ .gpio = TL_WR1043ND_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button tl_wr1043nd_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = TL_WR1043ND_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "qss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = TL_WR1043ND_GPIO_BTN_QSS, ++ .active_low = 1, ++ } ++}; ++ ++static struct rtl8366rb_platform_data tl_wr1043nd_rtl8366rb_data = { ++ .gpio_sda = TL_WR1043ND_GPIO_RTL8366_SDA, ++ .gpio_sck = TL_WR1043ND_GPIO_RTL8366_SCK, ++}; ++ ++static struct platform_device tl_wr1043nd_rtl8366rb_device = { ++ .name = RTL8366RB_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &tl_wr1043nd_rtl8366rb_data, ++ } ++}; ++ ++static void __init tl_wr1043nd_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ar71xx_set_mac_base(mac); ++ ++ ar71xx_eth0_data.mii_bus_dev = &tl_wr1043nd_rtl8366rb_device.dev; ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth0_data.speed = SPEED_1000; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ar71xx_eth0_pll_data.pll_1000 = 0x1a000000; ++ ++ ar71xx_add_device_eth(0); ++ ++ ar71xx_add_device_usb(); ++ ++ ar71xx_add_device_m25p80(&tl_wr1043nd_flash_data); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(tl_wr1043nd_leds_gpio), ++ tl_wr1043nd_leds_gpio); ++ ++ platform_device_register(&tl_wr1043nd_rtl8366rb_device); ++ ++ ar71xx_add_device_gpio_buttons(-1, TL_WR1043ND_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr1043nd_gpio_buttons), ++ tl_wr1043nd_gpio_buttons); ++ ++ ar913x_add_device_wmac(eeprom, mac); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_TL_WR1043ND, "TL-WR1043ND", "TP-LINK TL-WR1043ND", ++ tl_wr1043nd_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-tl-wr741nd.c linux-2.6.39/arch/mips/ar71xx/mach-tl-wr741nd.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-tl-wr741nd.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-tl-wr741nd.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,115 @@ ++/* ++ * TP-LINK TL-WR741ND board support ++ * ++ * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-ap91-eth.h" ++#include "dev-ap91-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++ ++#define TL_WR741ND_GPIO_LED_QSS 0 ++#define TL_WR741ND_GPIO_LED_SYSTEM 1 ++ ++#define TL_WR741ND_GPIO_BTN_RESET 11 ++#define TL_WR741ND_GPIO_BTN_QSS 12 ++ ++#define TL_WR741ND_BUTTONS_POLL_INTERVAL 20 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition tl_wr741nd_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "kernel", ++ .offset = 0x020000, ++ .size = 0x140000, ++ } , { ++ .name = "rootfs", ++ .offset = 0x160000, ++ .size = 0x290000, ++ } , { ++ .name = "art", ++ .offset = 0x3f0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "firmware", ++ .offset = 0x020000, ++ .size = 0x3d0000, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data tl_wr741nd_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = tl_wr741nd_partitions, ++ .nr_parts = ARRAY_SIZE(tl_wr741nd_partitions), ++#endif ++}; ++ ++static struct gpio_led tl_wr741nd_leds_gpio[] __initdata = { ++ { ++ .name = "tl-wr741nd:green:system", ++ .gpio = TL_WR741ND_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr741nd:green:qss", ++ .gpio = TL_WR741ND_GPIO_LED_QSS, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button tl_wr741nd_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = TL_WR741ND_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "qss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = TL_WR741ND_GPIO_BTN_QSS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init tl_wr741nd_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ar71xx_add_device_m25p80(&tl_wr741nd_flash_data); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(tl_wr741nd_leds_gpio), ++ tl_wr741nd_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, TL_WR741ND_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr741nd_gpio_buttons), ++ tl_wr741nd_gpio_buttons); ++ ++ ap91_eth_init(mac, NULL); ++ ap91_pci_init(ee, mac); ++} ++MIPS_MACHINE(AR71XX_MACH_TL_WR741ND, "TL-WR741ND", "TP-LINK TL-WR741ND", ++ tl_wr741nd_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-tl-wr841n.c linux-2.6.39/arch/mips/ar71xx/mach-tl-wr841n.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-tl-wr841n.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-tl-wr841n.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,143 @@ ++/* ++ * TP-LINK TL-WR841N board support ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-dsa.h" ++#include "dev-m25p80.h" ++#include "dev-gpio-buttons.h" ++#include "dev-pb42-pci.h" ++#include "dev-leds-gpio.h" ++ ++#define TL_WR841ND_V1_GPIO_LED_SYSTEM 2 ++#define TL_WR841ND_V1_GPIO_LED_QSS_GREEN 4 ++#define TL_WR841ND_V1_GPIO_LED_QSS_RED 5 ++ ++#define TL_WR841ND_V1_GPIO_BTN_RESET 3 ++#define TL_WR841ND_V1_GPIO_BTN_QSS 7 ++ ++#define TL_WR841ND_V1_BUTTONS_POLL_INTERVAL 20 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition tl_wr841n_v1_partitions[] = { ++ { ++ .name = "redboot", ++ .offset = 0, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "kernel", ++ .offset = 0x020000, ++ .size = 0x140000, ++ } , { ++ .name = "rootfs", ++ .offset = 0x160000, ++ .size = 0x280000, ++ } , { ++ .name = "config", ++ .offset = 0x3e0000, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "firmware", ++ .offset = 0x020000, ++ .size = 0x3c0000, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data tl_wr841n_v1_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = tl_wr841n_v1_partitions, ++ .nr_parts = ARRAY_SIZE(tl_wr841n_v1_partitions), ++#endif ++}; ++ ++static struct gpio_led tl_wr841n_v1_leds_gpio[] __initdata = { ++ { ++ .name = "tl-wr841n:green:system", ++ .gpio = TL_WR841ND_V1_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr841n:red:qss", ++ .gpio = TL_WR841ND_V1_GPIO_LED_QSS_RED, ++ }, { ++ .name = "tl-wr841n:green:qss", ++ .gpio = TL_WR841ND_V1_GPIO_LED_QSS_GREEN, ++ } ++}; ++ ++static struct gpio_button tl_wr841n_v1_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = TL_WR841ND_V1_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "qss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = TL_WR841ND_V1_GPIO_BTN_QSS, ++ .active_low = 1, ++ } ++}; ++ ++static struct dsa_chip_data tl_wr841n_v1_dsa_chip = { ++ .port_names[0] = "wan", ++ .port_names[1] = "lan1", ++ .port_names[2] = "lan2", ++ .port_names[3] = "lan3", ++ .port_names[4] = "lan4", ++ .port_names[5] = "cpu", ++}; ++ ++static struct dsa_platform_data tl_wr841n_v1_dsa_data = { ++ .nr_chips = 1, ++ .chip = &tl_wr841n_v1_dsa_chip, ++}; ++ ++static void __init tl_wr841n_v1_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ ++ ar71xx_set_mac_base(mac); ++ ++ ar71xx_add_device_mdio(0x0); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth0_data.speed = SPEED_100; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_add_device_eth(0); ++ ++ ar71xx_add_device_dsa(0, &tl_wr841n_v1_dsa_data); ++ ++ ar71xx_add_device_m25p80(&tl_wr841n_v1_flash_data); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(tl_wr841n_v1_leds_gpio), ++ tl_wr841n_v1_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, TL_WR841ND_V1_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr841n_v1_gpio_buttons), ++ tl_wr841n_v1_gpio_buttons); ++ ++ pb42_pci_init(); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_TL_WR841N_V1, "TL-WR841N-v1.5", "TP-LINK TL-WR841N v1", ++ tl_wr841n_v1_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-tl-wr941nd.c linux-2.6.39/arch/mips/ar71xx/mach-tl-wr941nd.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-tl-wr941nd.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-tl-wr941nd.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,142 @@ ++/* ++ * TP-LINK TL-WR941ND board support ++ * ++ * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-dsa.h" ++#include "dev-m25p80.h" ++#include "dev-ar913x-wmac.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++ ++#define TL_WR941ND_GPIO_LED_SYSTEM 2 ++#define TL_WR941ND_GPIO_LED_QSS_RED 4 ++#define TL_WR941ND_GPIO_LED_QSS_GREEN 5 ++ ++#define TL_WR941ND_GPIO_BTN_RESET 3 ++#define TL_WR941ND_GPIO_BTN_QSS 7 ++ ++#define TL_WR941ND_BUTTONS_POLL_INTERVAL 20 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition tl_wr941nd_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "kernel", ++ .offset = 0x020000, ++ .size = 0x140000, ++ } , { ++ .name = "rootfs", ++ .offset = 0x160000, ++ .size = 0x290000, ++ } , { ++ .name = "art", ++ .offset = 0x3f0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "firmware", ++ .offset = 0x020000, ++ .size = 0x3d0000, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data tl_wr941nd_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = tl_wr941nd_partitions, ++ .nr_parts = ARRAY_SIZE(tl_wr941nd_partitions), ++#endif ++}; ++ ++static struct gpio_led tl_wr941nd_leds_gpio[] __initdata = { ++ { ++ .name = "tl-wr941nd:green:system", ++ .gpio = TL_WR941ND_GPIO_LED_SYSTEM, ++ .active_low = 1, ++ }, { ++ .name = "tl-wr941nd:red:qss", ++ .gpio = TL_WR941ND_GPIO_LED_QSS_RED, ++ }, { ++ .name = "tl-wr941nd:green:qss", ++ .gpio = TL_WR941ND_GPIO_LED_QSS_GREEN, ++ } ++}; ++ ++static struct gpio_button tl_wr941nd_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = TL_WR941ND_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "qss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = TL_WR941ND_GPIO_BTN_QSS, ++ .active_low = 1, ++ } ++}; ++ ++static struct dsa_chip_data tl_wr941nd_dsa_chip = { ++ .port_names[0] = "wan", ++ .port_names[1] = "lan1", ++ .port_names[2] = "lan2", ++ .port_names[3] = "lan3", ++ .port_names[4] = "lan4", ++ .port_names[5] = "cpu", ++}; ++ ++static struct dsa_platform_data tl_wr941nd_dsa_data = { ++ .nr_chips = 1, ++ .chip = &tl_wr941nd_dsa_chip, ++}; ++ ++static void __init tl_wr941nd_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1f01fc00); ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ar71xx_set_mac_base(mac); ++ ++ ar71xx_add_device_mdio(0x0); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth0_data.speed = SPEED_100; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_dsa(0, &tl_wr941nd_dsa_data); ++ ++ ar71xx_add_device_m25p80(&tl_wr941nd_flash_data); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(tl_wr941nd_leds_gpio), ++ tl_wr941nd_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, TL_WR941ND_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(tl_wr941nd_gpio_buttons), ++ tl_wr941nd_gpio_buttons); ++ ar913x_add_device_wmac(eeprom, mac); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_TL_WR941ND, "TL-WR941ND", "TP-LINK TL-WR941ND", ++ tl_wr941nd_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-ubnt.c linux-2.6.39/arch/mips/ar71xx/mach-ubnt.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-ubnt.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-ubnt.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,281 @@ ++/* ++ * Ubiquiti RouterStation support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2008 Ubiquiti <support@ubnt.com> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-ap91-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-pb42-pci.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++ ++#define UBNT_RS_GPIO_LED_RF 2 ++#define UBNT_RS_GPIO_SW4 8 ++ ++#define UBNT_LS_SR71_GPIO_LED_D25 0 ++#define UBNT_LS_SR71_GPIO_LED_D26 1 ++#define UBNT_LS_SR71_GPIO_LED_D24 2 ++#define UBNT_LS_SR71_GPIO_LED_D23 4 ++#define UBNT_LS_SR71_GPIO_LED_D22 5 ++#define UBNT_LS_SR71_GPIO_LED_D27 6 ++#define UBNT_LS_SR71_GPIO_LED_D28 7 ++ ++#define UBNT_M_GPIO_LED_L1 0 ++#define UBNT_M_GPIO_LED_L2 1 ++#define UBNT_M_GPIO_LED_L3 11 ++#define UBNT_M_GPIO_LED_L4 7 ++#define UBNT_M_GPIO_BTN_RESET 12 ++ ++#define UBNT_BUTTONS_POLL_INTERVAL 20 ++ ++static struct gpio_led ubnt_rs_leds_gpio[] __initdata = { ++ { ++ .name = "ubnt:green:rf", ++ .gpio = UBNT_RS_GPIO_LED_RF, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_led ubnt_ls_sr71_leds_gpio[] __initdata = { ++ { ++ .name = "ubnt:green:d22", ++ .gpio = UBNT_LS_SR71_GPIO_LED_D22, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:d23", ++ .gpio = UBNT_LS_SR71_GPIO_LED_D23, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:d24", ++ .gpio = UBNT_LS_SR71_GPIO_LED_D24, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:red:d25", ++ .gpio = UBNT_LS_SR71_GPIO_LED_D25, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:red:d26", ++ .gpio = UBNT_LS_SR71_GPIO_LED_D26, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:d27", ++ .gpio = UBNT_LS_SR71_GPIO_LED_D27, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:d28", ++ .gpio = UBNT_LS_SR71_GPIO_LED_D28, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_led ubnt_m_leds_gpio[] __initdata = { ++ { ++ .name = "ubnt:red:link1", ++ .gpio = UBNT_M_GPIO_LED_L1, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:orange:link2", ++ .gpio = UBNT_M_GPIO_LED_L2, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:link3", ++ .gpio = UBNT_M_GPIO_LED_L3, ++ .active_low = 0, ++ }, { ++ .name = "ubnt:green:link4", ++ .gpio = UBNT_M_GPIO_LED_L4, ++ .active_low = 0, ++ } ++}; ++ ++static struct gpio_button ubnt_gpio_buttons[] __initdata = { ++ { ++ .desc = "sw4", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = UBNT_RS_GPIO_SW4, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button ubnt_m_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = UBNT_M_GPIO_BTN_RESET, ++ .active_low = 1, ++ } ++}; ++ ++static void __init ubnt_generic_setup(void) ++{ ++ ar71xx_add_device_m25p80(NULL); ++ ++ ar71xx_add_device_gpio_buttons(-1, UBNT_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(ubnt_gpio_buttons), ++ ubnt_gpio_buttons); ++ ++ pb42_pci_init(); ++} ++ ++#define UBNT_RS_WAN_PHYMASK (1 << 20) ++#define UBNT_RS_LAN_PHYMASK ((1 << 16) | (1 << 17) | (1 << 18) | (1 << 19)) ++ ++static void __init ubnt_rs_setup(void) ++{ ++ ubnt_generic_setup(); ++ ++ ar71xx_add_device_mdio(~(UBNT_RS_WAN_PHYMASK | UBNT_RS_LAN_PHYMASK)); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ar71xx_eth0_data.phy_mask = UBNT_RS_WAN_PHYMASK; ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.speed = SPEED_100; ++ ar71xx_eth1_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_usb(); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(ubnt_rs_leds_gpio), ++ ubnt_rs_leds_gpio); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_UBNT_RS, "UBNT-RS", "Ubiquiti RouterStation", ++ ubnt_rs_setup); ++ ++MIPS_MACHINE(AR71XX_MACH_UBNT_AR71XX, "Ubiquiti AR71xx-based board", ++ "Ubiquiti RouterStation", ubnt_rs_setup); ++ ++#define UBNT_RSPRO_WAN_PHYMASK (1 << 4) ++#define UBNT_RSPRO_LAN_PHYMASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)) ++ ++static void __init ubnt_rspro_setup(void) ++{ ++ ubnt_generic_setup(); ++ ++ ar71xx_add_device_mdio(~(UBNT_RSPRO_WAN_PHYMASK | UBNT_RSPRO_LAN_PHYMASK)); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth0_data.phy_mask = UBNT_RSPRO_WAN_PHYMASK; ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth1_data.phy_mask = UBNT_RSPRO_LAN_PHYMASK; ++ ar71xx_eth1_data.speed = SPEED_1000; ++ ar71xx_eth1_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_usb(); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(ubnt_rs_leds_gpio), ++ ubnt_rs_leds_gpio); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_UBNT_RSPRO, "UBNT-RSPRO", "Ubiquiti RouterStation Pro", ++ ubnt_rspro_setup); ++ ++static void __init ubnt_lsx_setup(void) ++{ ++ ubnt_generic_setup(); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_UBNT_LSX, "UBNT-LSX", "Ubiquiti LSX", ubnt_lsx_setup); ++ ++#define UBNT_LSSR71_PHY_MASK (1 << 1) ++ ++static void __init ubnt_lssr71_setup(void) ++{ ++ ubnt_generic_setup(); ++ ++ ar71xx_add_device_mdio(~UBNT_LSSR71_PHY_MASK); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ar71xx_eth0_data.phy_mask = UBNT_LSSR71_PHY_MASK; ++ ++ ar71xx_add_device_eth(0); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(ubnt_ls_sr71_leds_gpio), ++ ubnt_ls_sr71_leds_gpio); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_UBNT_LSSR71, "UBNT-LS-SR71", "Ubiquiti LS-SR71", ++ ubnt_lssr71_setup); ++ ++static void __init ubnt_m_setup(void) ++{ ++ u8 *mac = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 *ee = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ar71xx_set_mac_base(mac); ++ ++ ar71xx_add_device_m25p80(NULL); ++ ++ ar71xx_add_device_mdio(~0); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ar71xx_eth0_data.speed = SPEED_100; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ar71xx_eth0_data.fifo_cfg1 = 0x0010ffff; ++ ar71xx_eth0_data.fifo_cfg2 = 0x015500aa; ++ ar71xx_eth0_data.fifo_cfg3 = 0x01f00140; ++ ++ ar71xx_add_device_eth(0); ++ ++ ap91_pci_init(ee, NULL); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(ubnt_m_leds_gpio), ++ ubnt_m_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, UBNT_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(ubnt_m_gpio_buttons), ++ ubnt_m_gpio_buttons); ++} ++ ++static void __init ubnt_rocket_m_setup(void) ++{ ++ ubnt_m_setup(); ++ ar71xx_add_device_usb(); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_UBNT_BULLET_M, "UBNT-BM", "Ubiquiti Bullet M", ++ ubnt_m_setup); ++MIPS_MACHINE(AR71XX_MACH_UBNT_ROCKET_M, "UBNT-RM", "Ubiquiti Rocket M", ++ ubnt_rocket_m_setup); ++ ++/* TODO detect the second ethernet port and use one ++ init function for all Ubiquiti MIMO series products */ ++static void __init ubnt_nano_m_setup(void) ++{ ++ ubnt_m_setup(); ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.speed = SPEED_1000; ++ ar71xx_eth1_data.duplex = DUPLEX_FULL; ++ ar71xx_eth1_data.fifo_cfg1 = 0x0010ffff; ++ ar71xx_eth1_data.fifo_cfg2 = 0x015500aa; ++ ar71xx_eth1_data.fifo_cfg3 = 0x01f00140; ++ ++ ar71xx_add_device_eth(1); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_UBNT_NANO_M, "UBNT-NM", "Ubiquiti Nanostation M", ++ ubnt_nano_m_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-wndr3700.c linux-2.6.39/arch/mips/ar71xx/mach-wndr3700.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-wndr3700.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-wndr3700.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,209 @@ ++/* ++ * Netgear WNDR3700 board support ++ * ++ * Copyright (C) 2009 Marco Porsch ++ * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/platform_device.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <linux/delay.h> ++#include <linux/rtl8366s.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-ap94-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++ ++#define WNDR3700_GPIO_LED_WPS_ORANGE 0 ++#define WNDR3700_GPIO_LED_POWER_ORANGE 1 ++#define WNDR3700_GPIO_LED_POWER_GREEN 2 ++#define WNDR3700_GPIO_LED_WPS_GREEN 4 ++#define WNDR3700_GPIO_LED_WAN_GREEN 6 ++ ++#define WNDR3700_GPIO_BTN_WPS 3 ++#define WNDR3700_GPIO_BTN_RESET 8 ++#define WNDR3700_GPIO_BTN_WIFI 11 ++ ++#define WNDR3700_GPIO_RTL8366_SDA 5 ++#define WNDR3700_GPIO_RTL8366_SCK 7 ++ ++#define WNDR3700_BUTTONS_POLL_INTERVAL 20 ++ ++#define WNDR3700_WMAC0_MAC_OFFSET 0 ++#define WNDR3700_WMAC1_MAC_OFFSET 0xc ++#define WNDR3700_CALDATA0_OFFSET 0x1000 ++#define WNDR3700_CALDATA1_OFFSET 0x5000 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition wndr3700_partitions[] = { ++ { ++ .name = "uboot", ++ .offset = 0, ++ .size = 0x050000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "env", ++ .offset = 0x050000, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "rootfs", ++ .offset = 0x070000, ++ .size = 0x720000, ++ } , { ++ .name = "config", ++ .offset = 0x790000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "config_bak", ++ .offset = 0x7a0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "pot", ++ .offset = 0x7b0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "traffic_meter", ++ .offset = 0x7c0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "language", ++ .offset = 0x7d0000, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "caldata", ++ .offset = 0x7f0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data wndr3700_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = wndr3700_partitions, ++ .nr_parts = ARRAY_SIZE(wndr3700_partitions), ++#endif ++}; ++ ++static struct gpio_led wndr3700_leds_gpio[] __initdata = { ++ { ++ .name = "wndr3700:green:power", ++ .gpio = WNDR3700_GPIO_LED_POWER_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "wndr3700:orange:power", ++ .gpio = WNDR3700_GPIO_LED_POWER_ORANGE, ++ .active_low = 1, ++ }, { ++ .name = "wndr3700:green:wps", ++ .gpio = WNDR3700_GPIO_LED_WPS_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "wndr3700:orange:wps", ++ .gpio = WNDR3700_GPIO_LED_WPS_ORANGE, ++ .active_low = 1, ++ }, { ++ .name = "wndr3700:green:wan", ++ .gpio = WNDR3700_GPIO_LED_WAN_GREEN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button wndr3700_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = WNDR3700_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = WNDR3700_GPIO_BTN_WPS, ++ .active_low = 1, ++ } , { ++ .desc = "wifi", ++ .type = EV_KEY, ++ .code = BTN_2, ++ .threshold = 3, ++ .gpio = WNDR3700_GPIO_BTN_WIFI, ++ .active_low = 1, ++ } ++}; ++ ++static struct rtl8366s_platform_data wndr3700_rtl8366s_data = { ++ .gpio_sda = WNDR3700_GPIO_RTL8366_SDA, ++ .gpio_sck = WNDR3700_GPIO_RTL8366_SCK, ++}; ++ ++static struct platform_device wndr3700_rtl8366s_device = { ++ .name = RTL8366S_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &wndr3700_rtl8366s_data, ++ } ++}; ++ ++static void __init wndr3700_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ ++ ar71xx_set_mac_base(art); ++ ++ ar71xx_eth0_pll_data.pll_1000 = 0x11110000; ++ ar71xx_eth0_data.mii_bus_dev = &wndr3700_rtl8366s_device.dev; ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth0_data.speed = SPEED_1000; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_eth1_pll_data.pll_1000 = 0x11110000; ++ ar71xx_eth1_data.mii_bus_dev = &wndr3700_rtl8366s_device.dev; ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth1_data.phy_mask = 0x10; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_usb(); ++ ++ ar71xx_add_device_m25p80(&wndr3700_flash_data); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(wndr3700_leds_gpio), ++ wndr3700_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, WNDR3700_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(wndr3700_gpio_buttons), ++ wndr3700_gpio_buttons); ++ ++ platform_device_register(&wndr3700_rtl8366s_device); ++ platform_device_register_simple("wndr3700-led-usb", -1, NULL, 0); ++ ++ ap94_pci_enable_quirk_wndr3700(); ++ ap94_pci_init(art + WNDR3700_CALDATA0_OFFSET, ++ art + WNDR3700_WMAC0_MAC_OFFSET, ++ art + WNDR3700_CALDATA1_OFFSET, ++ art + WNDR3700_WMAC1_MAC_OFFSET); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_WNDR3700, "WNDR3700", "NETGEAR WNDR3700", ++ wndr3700_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-wnr2000.c linux-2.6.39/arch/mips/ar71xx/mach-wnr2000.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-wnr2000.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-wnr2000.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,148 @@ ++/* ++ * NETGEAR WNR2000 board support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * Copyright (C) 2008-2009 Andy Boyett <agb@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-ar913x-wmac.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++ ++#define WNR2000_GPIO_LED_PWR_GREEN 14 ++#define WNR2000_GPIO_LED_PWR_AMBER 7 ++#define WNR2000_GPIO_LED_WPS 4 ++#define WNR2000_GPIO_LED_WLAN 6 ++#define WNR2000_GPIO_BTN_RESET 21 ++#define WNR2000_GPIO_BTN_WPS 8 ++ ++#define WNR2000_BUTTONS_POLL_INTERVAL 20 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition wnr2000_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x040000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "u-boot-env", ++ .offset = 0x040000, ++ .size = 0x010000, ++ } , { ++ .name = "rootfs", ++ .offset = 0x050000, ++ .size = 0x240000, ++ } , { ++ .name = "user-config", ++ .offset = 0x290000, ++ .size = 0x010000, ++ } , { ++ .name = "uImage", ++ .offset = 0x2a0000, ++ .size = 0x120000, ++ } , { ++ .name = "language_table", ++ .offset = 0x3c0000, ++ .size = 0x020000, ++ } , { ++ .name = "rootfs_checksum", ++ .offset = 0x3e0000, ++ .size = 0x010000, ++ } , { ++ .name = "art", ++ .offset = 0x3f0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data wnr2000_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = wnr2000_partitions, ++ .nr_parts = ARRAY_SIZE(wnr2000_partitions), ++#endif ++}; ++ ++static struct gpio_led wnr2000_leds_gpio[] __initdata = { ++ { ++ .name = "wnr2000:green:power", ++ .gpio = WNR2000_GPIO_LED_PWR_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "wnr2000:amber:power", ++ .gpio = WNR2000_GPIO_LED_PWR_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "wnr2000:green:wps", ++ .gpio = WNR2000_GPIO_LED_WPS, ++ .active_low = 1, ++ }, { ++ .name = "wnr2000:blue:wlan", ++ .gpio = WNR2000_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button wnr2000_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = WNR2000_GPIO_BTN_RESET, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = WNR2000_GPIO_BTN_WPS, ++ } ++}; ++ ++static void __init wnr2000_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ar71xx_set_mac_base(eeprom); ++ ar71xx_add_device_mdio(0x0); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth0_data.speed = SPEED_100; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ar71xx_eth0_data.has_ar8216 = 1; ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.phy_mask = 0x10; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_m25p80(&wnr2000_flash_data); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(wnr2000_leds_gpio), ++ wnr2000_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, WNR2000_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(wnr2000_gpio_buttons), ++ wnr2000_gpio_buttons); ++ ++ ++ ar913x_add_device_wmac(eeprom, NULL); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_WNR2000, "WNR2000", "NETGEAR WNR2000", wnr2000_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-wp543.c linux-2.6.39/arch/mips/ar71xx/mach-wp543.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-wp543.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-wp543.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,99 @@ ++/* ++ * Compex WP543/WPJ543 board support ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-pb42-pci.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++ ++#define WP543_GPIO_SW6 2 ++#define WP543_GPIO_LED_1 3 ++#define WP543_GPIO_LED_2 4 ++#define WP543_GPIO_LED_WLAN 5 ++#define WP543_GPIO_LED_CONN 6 ++#define WP543_GPIO_LED_DIAG 7 ++#define WP543_GPIO_SW4 8 ++ ++#define WP543_BUTTONS_POLL_INTERVAL 20 ++ ++static struct gpio_led wp543_leds_gpio[] __initdata = { ++ { ++ .name = "wp543:green:led1", ++ .gpio = WP543_GPIO_LED_1, ++ .active_low = 1, ++ }, { ++ .name = "wp543:green:led2", ++ .gpio = WP543_GPIO_LED_2, ++ .active_low = 1, ++ }, { ++ .name = "wp543:green:wlan", ++ .gpio = WP543_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "wp543:green:conn", ++ .gpio = WP543_GPIO_LED_CONN, ++ .active_low = 1, ++ }, { ++ .name = "wp543:green:diag", ++ .gpio = WP543_GPIO_LED_DIAG, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button wp543_gpio_buttons[] __initdata = { ++ { ++ .desc = "sw6", ++ .type = EV_KEY, ++ .code = BTN_0, ++ .threshold = 3, ++ .gpio = WP543_GPIO_SW6, ++ }, { ++ .desc = "sw4", ++ .type = EV_KEY, ++ .code = BTN_1, ++ .threshold = 3, ++ .gpio = WP543_GPIO_SW4, ++ } ++}; ++ ++static void __init wp543_setup(void) ++{ ++ ar71xx_add_device_m25p80(NULL); ++ ++ ar71xx_add_device_mdio(0xfffffff7); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_MII; ++ ar71xx_eth0_data.phy_mask = 0x08; ++ ar71xx_eth0_data.reset_bit = RESET_MODULE_GE0_MAC | ++ RESET_MODULE_GE0_PHY; ++ ar71xx_add_device_eth(0); ++ ++ ar71xx_add_device_usb(); ++ ++ pb42_pci_init(); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(wp543_leds_gpio), ++ wp543_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, WP543_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(wp543_gpio_buttons), ++ wp543_gpio_buttons); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_WP543, "WP543", "Compex WP543", wp543_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-wrt160nl.c linux-2.6.39/arch/mips/ar71xx/mach-wrt160nl.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-wrt160nl.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-wrt160nl.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,158 @@ ++/* ++ * Linksys WRT160NL board support ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-m25p80.h" ++#include "dev-ar913x-wmac.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++#include "nvram.h" ++ ++#define WRT160NL_GPIO_LED_POWER 14 ++#define WRT160NL_GPIO_LED_WPS_AMBER 9 ++#define WRT160NL_GPIO_LED_WPS_BLUE 8 ++#define WRT160NL_GPIO_LED_WLAN 6 ++ ++#define WRT160NL_GPIO_BTN_WPS 7 ++#define WRT160NL_GPIO_BTN_RESET 21 ++ ++#define WRT160NL_BUTTONS_POLL_INTERVAL 20 ++ ++#define WRT160NL_NVRAM_ADDR 0x1f7e0000 ++#define WRT160NL_NVRAM_SIZE 0x10000 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition wrt160nl_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x040000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "kernel", ++ .offset = 0x040000, ++ .size = 0x0e0000, ++ } , { ++ .name = "filesytem", ++ .offset = 0x120000, ++ .size = 0x6c0000, ++ } , { ++ .name = "nvram", ++ .offset = 0x7e0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "ART", ++ .offset = 0x7f0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "firmware", ++ .offset = 0x040000, ++ .size = 0x7a0000, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data wrt160nl_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = wrt160nl_partitions, ++ .nr_parts = ARRAY_SIZE(wrt160nl_partitions), ++#endif ++}; ++ ++static struct gpio_led wrt160nl_leds_gpio[] __initdata = { ++ { ++ .name = "wrt160nl:blue:power", ++ .gpio = WRT160NL_GPIO_LED_POWER, ++ .active_low = 1, ++ .default_trigger = "default-on", ++ }, { ++ .name = "wrt160nl:amber:wps", ++ .gpio = WRT160NL_GPIO_LED_WPS_AMBER, ++ .active_low = 1, ++ }, { ++ .name = "wrt160nl:blue:wps", ++ .gpio = WRT160NL_GPIO_LED_WPS_BLUE, ++ .active_low = 1, ++ }, { ++ .name = "wrt160nl:blue:wlan", ++ .gpio = WRT160NL_GPIO_LED_WLAN, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button wrt160nl_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = WRT160NL_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "wps", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = WRT160NL_GPIO_BTN_WPS, ++ .active_low = 1, ++ } ++}; ++ ++static void __init wrt160nl_setup(void) ++{ ++ const char *nvram = (char *) KSEG1ADDR(WRT160NL_NVRAM_ADDR); ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ u8 mac[6]; ++ ++ if (nvram_parse_mac_addr(nvram, WRT160NL_NVRAM_SIZE, ++ "lan_hwaddr=", mac) == 0) ++ ar71xx_set_mac_base(mac); ++ ++ ar71xx_add_device_mdio(0x0); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth0_data.phy_mask = 0x01; ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.phy_mask = 0x10; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_m25p80(&wrt160nl_flash_data); ++ ++ ar71xx_add_device_usb(); ++ ++ if (nvram_parse_mac_addr(nvram, WRT160NL_NVRAM_SIZE, ++ "wl0_hwaddr=", mac) == 0) ++ ar913x_add_device_wmac(eeprom, mac); ++ else ++ ar913x_add_device_wmac(eeprom, NULL); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(wrt160nl_leds_gpio), ++ wrt160nl_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, WRT160NL_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(wrt160nl_gpio_buttons), ++ wrt160nl_gpio_buttons); ++ ++} ++ ++MIPS_MACHINE(AR71XX_MACH_WRT160NL, "WRT160NL", "Linksys WRT160NL", ++ wrt160nl_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-wrt400n.c linux-2.6.39/arch/mips/ar71xx/mach-wrt400n.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-wrt400n.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-wrt400n.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,168 @@ ++/* ++ * Linksys WRT400N board support ++ * ++ * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2009 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-ap94-pci.h" ++#include "dev-m25p80.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++ ++#define WRT400N_GPIO_LED_ORANGE 5 ++#define WRT400N_GPIO_LED_GREEN 4 ++#define WRT400N_GPIO_LED_POWER 1 ++#define WRT400N_GPIO_LED_WLAN 0 ++ ++#define WRT400N_GPIO_BTN_RESET 8 ++#define WRT400N_GPIO_BTN_WLSEC 3 ++ ++#define WRT400N_BUTTONS_POLL_INTERVAL 20 ++ ++#define WRT400N_MAC_ADDR_OFFSET 0x120c ++#define WRT400N_CALDATA0_OFFSET 0x1000 ++#define WRT400N_CALDATA1_OFFSET 0x5000 ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition wrt400n_partitions[] = { ++ { ++ .name = "uboot", ++ .offset = 0, ++ .size = 0x030000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "env", ++ .offset = 0x030000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "linux", ++ .offset = 0x040000, ++ .size = 0x140000, ++ } , { ++ .name = "rootfs", ++ .offset = 0x180000, ++ .size = 0x630000, ++ } , { ++ .name = "nvram", ++ .offset = 0x7b0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "factory", ++ .offset = 0x7c0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "language", ++ .offset = 0x7d0000, ++ .size = 0x020000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "caldata", ++ .offset = 0x7f0000, ++ .size = 0x010000, ++ .mask_flags = MTD_WRITEABLE, ++ } , { ++ .name = "firmware", ++ .offset = 0x040000, ++ .size = 0x770000, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct flash_platform_data wrt400n_flash_data = { ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = wrt400n_partitions, ++ .nr_parts = ARRAY_SIZE(wrt400n_partitions), ++#endif ++}; ++ ++static struct gpio_led wrt400n_leds_gpio[] __initdata = { ++ { ++ .name = "wrt400n:green:status", ++ .gpio = WRT400N_GPIO_LED_GREEN, ++ .active_low = 1, ++ }, { ++ .name = "wrt400n:amber:aoss", ++ .gpio = WRT400N_GPIO_LED_ORANGE, ++ .active_low = 1, ++ }, { ++ .name = "wrt400n:green:wlan", ++ .gpio = WRT400N_GPIO_LED_WLAN, ++ .active_low = 1, ++ }, { ++ .name = "wrt400n:green:power", ++ .gpio = WRT400N_GPIO_LED_POWER, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button wrt400n_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = WRT400N_GPIO_BTN_RESET, ++ .active_low = 1, ++ } , { ++ .desc = "wlsec", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = WRT400N_GPIO_BTN_WLSEC, ++ .active_low = 1, ++ } ++}; ++ ++static void __init wrt400n_setup(void) ++{ ++ u8 *art = (u8 *) KSEG1ADDR(0x1fff0000); ++ u8 mac[6]; ++ int i; ++ ++ memcpy(mac, art + WRT400N_MAC_ADDR_OFFSET, 6); ++ for (i = 5; i >= 3; i--) ++ if (++mac[i] != 0x00) break; ++ ++ ar71xx_set_mac_base(mac); ++ ++ ar71xx_add_device_mdio(0x0); ++ ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth0_data.speed = SPEED_100; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RMII; ++ ar71xx_eth1_data.phy_mask = 0x10; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_m25p80(&wrt400n_flash_data); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(wrt400n_leds_gpio), ++ wrt400n_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, WRT400N_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(wrt400n_gpio_buttons), ++ wrt400n_gpio_buttons); ++ ++ ap94_pci_init(art + WRT400N_CALDATA0_OFFSET, NULL, ++ art + WRT400N_CALDATA1_OFFSET, NULL); ++} ++ ++MIPS_MACHINE(AR71XX_MACH_WRT400N, "WRT400N", "Linksys WRT400N", wrt400n_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/mach-wzr-hp-g300nh.c linux-2.6.39/arch/mips/ar71xx/mach-wzr-hp-g300nh.c +--- linux-2.6.39.orig/arch/mips/ar71xx/mach-wzr-hp-g300nh.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/mach-wzr-hp-g300nh.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,265 @@ ++/* ++ * Buffalo WZR-HP-G300NH board support ++ * ++ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/platform_device.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <linux/nxp_74hc153.h> ++#include <linux/rtl8366s.h> ++ ++#include <asm/mips_machine.h> ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/ar91xx_flash.h> ++ ++#include "machtype.h" ++#include "devices.h" ++#include "dev-ar913x-wmac.h" ++#include "dev-gpio-buttons.h" ++#include "dev-leds-gpio.h" ++#include "dev-usb.h" ++ ++#define WZRHPG300NH_GPIO_LED_USB 0 ++#define WZRHPG300NH_GPIO_LED_DIAG 1 ++#define WZRHPG300NH_GPIO_LED_WIRELESS 6 ++#define WZRHPG300NH_GPIO_LED_SECURITY 17 ++#define WZRHPG300NH_GPIO_LED_ROUTER 18 ++ ++#define WZRHPG300NH_GPIO_RTL8366_SDA 19 ++#define WZRHPG300NH_GPIO_RTL8366_SCK 20 ++ ++#define WZRHPG300NH_GPIO_74HC153_S0 9 ++#define WZRHPG300NH_GPIO_74HC153_S1 11 ++#define WZRHPG300NH_GPIO_74HC153_1Y 12 ++#define WZRHPG300NH_GPIO_74HC153_2Y 14 ++ ++#define WZRHPG300NH_GPIO_EXP_BASE 32 ++#define WZRHPG300NH_GPIO_BTN_AOSS (WZRHPG300NH_GPIO_EXP_BASE + 0) ++#define WZRHPG300NH_GPIO_BTN_RESET (WZRHPG300NH_GPIO_EXP_BASE + 1) ++#define WZRHPG300NH_GPIO_BTN_ROUTER_ON (WZRHPG300NH_GPIO_EXP_BASE + 2) ++#define WZRHPG300NH_GPIO_BTN_QOS_ON (WZRHPG300NH_GPIO_EXP_BASE + 3) ++#define WZRHPG300NH_GPIO_BTN_USB (WZRHPG300NH_GPIO_EXP_BASE + 5) ++#define WZRHPG300NH_GPIO_BTN_ROUTER_AUTO (WZRHPG300NH_GPIO_EXP_BASE + 6) ++#define WZRHPG300NH_GPIO_BTN_QOS_OFF (WZRHPG300NH_GPIO_EXP_BASE + 7) ++ ++#define WZRHPG300NH_BUTTONS_POLL_INTERVAL 20 ++ ++#define WZRHPG300NH_MAC_OFFSET 0x20c ++ ++#ifdef CONFIG_MTD_PARTITIONS ++static struct mtd_partition wzrhpg300nh_flash_partitions[] = { ++ { ++ .name = "u-boot", ++ .offset = 0, ++ .size = 0x0040000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "u-boot-env", ++ .offset = 0x0040000, ++ .size = 0x0020000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "kernel", ++ .offset = 0x0060000, ++ .size = 0x0100000, ++ }, { ++ .name = "rootfs", ++ .offset = 0x0160000, ++ .size = 0x1e60000, ++ }, { ++ .name = "user_property", ++ .offset = 0x1fc0000, ++ .size = 0x0020000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "art", ++ .offset = 0x1fe0000, ++ .size = 0x0020000, ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "firmware", ++ .offset = 0x0060000, ++ .size = 0x1f60000, ++ } ++}; ++#endif /* CONFIG_MTD_PARTITIONS */ ++ ++static struct ar91xx_flash_platform_data wzrhpg300nh_flash_data = { ++ .width = 2, ++#ifdef CONFIG_MTD_PARTITIONS ++ .parts = wzrhpg300nh_flash_partitions, ++ .nr_parts = ARRAY_SIZE(wzrhpg300nh_flash_partitions), ++#endif ++}; ++ ++#define WZRHPG300NH_FLASH_BASE 0x1e000000 ++#define WZRHPG300NH_FLASH_SIZE (32 * 1024 * 1024) ++ ++static struct resource wzrhpg300nh_flash_resources[] = { ++ [0] = { ++ .start = WZRHPG300NH_FLASH_BASE, ++ .end = WZRHPG300NH_FLASH_BASE + WZRHPG300NH_FLASH_SIZE - 1, ++ .flags = IORESOURCE_MEM, ++ }, ++}; ++ ++static struct platform_device wzrhpg300nh_flash_device = { ++ .name = "ar91xx-flash", ++ .id = -1, ++ .resource = wzrhpg300nh_flash_resources, ++ .num_resources = ARRAY_SIZE(wzrhpg300nh_flash_resources), ++ .dev = { ++ .platform_data = &wzrhpg300nh_flash_data, ++ } ++}; ++ ++static struct gpio_led wzrhpg300nh_leds_gpio[] __initdata = { ++ { ++ .name = "wzr-hp-g300nh:orange:security", ++ .gpio = WZRHPG300NH_GPIO_LED_SECURITY, ++ .active_low = 1, ++ }, { ++ .name = "wzr-hp-g300nh:green:wireless", ++ .gpio = WZRHPG300NH_GPIO_LED_WIRELESS, ++ .active_low = 1, ++ }, { ++ .name = "wzr-hp-g300nh:green:router", ++ .gpio = WZRHPG300NH_GPIO_LED_ROUTER, ++ .active_low = 1, ++ }, { ++ .name = "wzr-hp-g300nh:red:diag", ++ .gpio = WZRHPG300NH_GPIO_LED_DIAG, ++ .active_low = 1, ++ }, { ++ .name = "wzr-hp-g300nh:blue:usb", ++ .gpio = WZRHPG300NH_GPIO_LED_USB, ++ .active_low = 1, ++ } ++}; ++ ++static struct gpio_button wzrhpg300nh_gpio_buttons[] __initdata = { ++ { ++ .desc = "reset", ++ .type = EV_KEY, ++ .code = KEY_RESTART, ++ .threshold = 3, ++ .gpio = WZRHPG300NH_GPIO_BTN_RESET, ++ .active_low = 1, ++ }, { ++ .desc = "aoss", ++ .type = EV_KEY, ++ .code = KEY_WPS_BUTTON, ++ .threshold = 3, ++ .gpio = WZRHPG300NH_GPIO_BTN_AOSS, ++ .active_low = 1, ++ }, { ++ .desc = "usb", ++ .type = EV_KEY, ++ .code = BTN_2, ++ .threshold = 3, ++ .gpio = WZRHPG300NH_GPIO_BTN_USB, ++ .active_low = 1, ++ }, { ++ .desc = "qos_on", ++ .type = EV_KEY, ++ .code = BTN_3, ++ .threshold = 3, ++ .gpio = WZRHPG300NH_GPIO_BTN_QOS_ON, ++ .active_low = 0, ++ }, { ++ .desc = "qos_off", ++ .type = EV_KEY, ++ .code = BTN_4, ++ .threshold = 3, ++ .gpio = WZRHPG300NH_GPIO_BTN_QOS_OFF, ++ .active_low = 0, ++ }, { ++ .desc = "router_on", ++ .type = EV_KEY, ++ .code = BTN_5, ++ .threshold = 3, ++ .gpio = WZRHPG300NH_GPIO_BTN_ROUTER_ON, ++ .active_low = 0, ++ }, { ++ .desc = "router_auto", ++ .type = EV_KEY, ++ .code = BTN_6, ++ .threshold = 3, ++ .gpio = WZRHPG300NH_GPIO_BTN_ROUTER_AUTO, ++ .active_low = 0, ++ } ++}; ++ ++static struct nxp_74hc153_platform_data wzrhpg300nh_74hc153_data = { ++ .gpio_base = WZRHPG300NH_GPIO_EXP_BASE, ++ .gpio_pin_s0 = WZRHPG300NH_GPIO_74HC153_S0, ++ .gpio_pin_s1 = WZRHPG300NH_GPIO_74HC153_S1, ++ .gpio_pin_1y = WZRHPG300NH_GPIO_74HC153_1Y, ++ .gpio_pin_2y = WZRHPG300NH_GPIO_74HC153_2Y, ++}; ++ ++static struct platform_device wzrhpg300nh_74hc153_device = { ++ .name = NXP_74HC153_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &wzrhpg300nh_74hc153_data, ++ } ++}; ++ ++static struct rtl8366s_platform_data wzrhpg300nh_rtl8366s_data = { ++ .gpio_sda = WZRHPG300NH_GPIO_RTL8366_SDA, ++ .gpio_sck = WZRHPG300NH_GPIO_RTL8366_SCK, ++}; ++ ++static struct platform_device wzrhpg300nh_rtl8366s_device = { ++ .name = RTL8366S_DRIVER_NAME, ++ .id = -1, ++ .dev = { ++ .platform_data = &wzrhpg300nh_rtl8366s_data, ++ } ++}; ++ ++static void __init wzrhpg300nh_setup(void) ++{ ++ u8 *eeprom = (u8 *) KSEG1ADDR(0x1fff1000); ++ ++ ar71xx_set_mac_base(eeprom + WZRHPG300NH_MAC_OFFSET); ++ ++ ar71xx_eth0_pll_data.pll_1000 = 0x1e000100; ++ ar71xx_eth0_data.mii_bus_dev = &wzrhpg300nh_rtl8366s_device.dev; ++ ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth0_data.speed = SPEED_1000; ++ ar71xx_eth0_data.duplex = DUPLEX_FULL; ++ ++ ar71xx_eth1_pll_data.pll_1000 = 0x1e000100; ++ ar71xx_eth1_data.mii_bus_dev = &wzrhpg300nh_rtl8366s_device.dev; ++ ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII; ++ ar71xx_eth1_data.phy_mask = 0x10; ++ ++ ar71xx_add_device_eth(0); ++ ar71xx_add_device_eth(1); ++ ++ ar71xx_add_device_usb(); ++ ar913x_add_device_wmac(eeprom, NULL); ++ ++ platform_device_register(&wzrhpg300nh_74hc153_device); ++ platform_device_register(&wzrhpg300nh_flash_device); ++ platform_device_register(&wzrhpg300nh_rtl8366s_device); ++ ++ ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(wzrhpg300nh_leds_gpio), ++ wzrhpg300nh_leds_gpio); ++ ++ ar71xx_add_device_gpio_buttons(-1, WZRHPG300NH_BUTTONS_POLL_INTERVAL, ++ ARRAY_SIZE(wzrhpg300nh_gpio_buttons), ++ wzrhpg300nh_gpio_buttons); ++ ++} ++ ++MIPS_MACHINE(AR71XX_MACH_WZR_HP_G300NH, "WZR-HP-G300NH", ++ "Buffalo WZR-HP-G300NH", wzrhpg300nh_setup); +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/machtype.h linux-2.6.39/arch/mips/ar71xx/machtype.h +--- linux-2.6.39.orig/arch/mips/ar71xx/machtype.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/machtype.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,60 @@ ++/* ++ * Atheros AR71xx machine type definitions ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _AR71XX_MACHTYPE_H ++#define _AR71XX_MACHTYPE_H ++ ++#include <asm/mips_machine.h> ++ ++enum ar71xx_mach_type { ++ AR71XX_MACH_GENERIC = 0, ++ AR71XX_MACH_AP81, /* Atheros AP81 */ ++ AR71XX_MACH_AP83, /* Atheros AP83 */ ++ AR71XX_MACH_AW_NR580, /* AzureWave AW-NR580 */ ++ AR71XX_MACH_DIR_600_A1, /* D-Link DIR-600 rev. A1 */ ++ AR71XX_MACH_DIR_615_C1, /* D-Link DIR-615 rev. C1 */ ++ AR71XX_MACH_DIR_825_B1, /* D-Link DIR-825 rev. B1 */ ++ AR71XX_MACH_RB_411, /* MikroTik RouterBOARD 411/411A/411AH */ ++ AR71XX_MACH_RB_411U, /* MikroTik RouterBOARD 411U */ ++ AR71XX_MACH_RB_433, /* MikroTik RouterBOARD 433/433AH */ ++ AR71XX_MACH_RB_433U, /* MikroTik RouterBOARD 433UAH */ ++ AR71XX_MACH_RB_450, /* MikroTik RouterBOARD 450 */ ++ AR71XX_MACH_RB_450G, /* MikroTik RouterBOARD 450G */ ++ AR71XX_MACH_RB_493, /* Mikrotik RouterBOARD 493/493AH */ ++ AR71XX_MACH_RB_750, /* MikroTik RouterBOARD 750 */ ++ AR71XX_MACH_PB42, /* Atheros PB42 */ ++ AR71XX_MACH_PB44, /* Atheros PB44 */ ++ AR71XX_MACH_PB92, /* Atheros PB92 */ ++ AR71XX_MACH_MZK_W04NU, /* Planex MZK-W04NU */ ++ AR71XX_MACH_MZK_W300NH, /* Planex MZK-W300NH */ ++ AR71XX_MACH_NBG460N, /* Zyxel NBG460N/550N/550NH */ ++ AR71XX_MACH_TEW_632BRP, /* TRENDnet TEW-632BRP */ ++ AR71XX_MACH_TL_WR741ND, /* TP-LINK TL-WR741ND */ ++ AR71XX_MACH_TL_WR841N_V1, /* TP-LINK TL-WR841N v1 */ ++ AR71XX_MACH_TL_WR941ND, /* TP-LINK TL-WR941ND */ ++ AR71XX_MACH_TL_WR1043ND, /* TP-LINK TL-WR1041ND */ ++ AR71XX_MACH_UBNT_LSSR71, /* Ubiquiti LS-SR71 */ ++ AR71XX_MACH_UBNT_LSX, /* Ubiquiti LSX */ ++ AR71XX_MACH_UBNT_RS, /* Ubiquiti RouterStation */ ++ AR71XX_MACH_UBNT_AR71XX, /* Ubiquiti AR71xx-based board */ ++ AR71XX_MACH_UBNT_RSPRO, /* Ubiquiti RouterStation Pro */ ++ AR71XX_MACH_UBNT_BULLET_M, /* Ubiquiti Bullet M */ ++ AR71XX_MACH_UBNT_ROCKET_M, /* Ubiquiti Rocket M */ ++ AR71XX_MACH_UBNT_NANO_M, /* Ubiquiti NanoStation M */ ++ AR71XX_MACH_WNDR3700, /* NETGEAR WNDR3700 */ ++ AR71XX_MACH_WNR2000, /* NETGEAR WNR2000 */ ++ AR71XX_MACH_WP543, /* Compex WP543 */ ++ AR71XX_MACH_WRT160NL, /* Linksys WRT160NL */ ++ AR71XX_MACH_WRT400N, /* Linksys WRT400N */ ++ AR71XX_MACH_WZR_HP_G300NH, /* Buffalo WZR-HP-G300NH */ ++}; ++ ++#endif /* _AR71XX_MACHTYPE_H */ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/nvram.c linux-2.6.39/arch/mips/ar71xx/nvram.c +--- linux-2.6.39.orig/arch/mips/ar71xx/nvram.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/nvram.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,75 @@ ++/* ++ * Atheros AR71xx minimal nvram support ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/vmalloc.h> ++#include <linux/errno.h> ++#include <linux/init.h> ++#include <linux/string.h> ++ ++#include "nvram.h" ++ ++char *nvram_find_var(const char *name, const char *buf, unsigned buf_len) ++{ ++ unsigned len = strlen(name); ++ char *cur, *last; ++ ++ if (buf_len == 0 || len == 0) ++ return NULL; ++ ++ if (buf_len < len) ++ return NULL; ++ ++ if (len == 1) ++ return memchr(buf, (int) *name, buf_len); ++ ++ last = (char *) buf + buf_len - len; ++ for (cur = (char *) buf; cur <= last; cur++) ++ if (cur[0] == name[0] && memcmp(cur, name, len) == 0) ++ return cur + len; ++ ++ return NULL; ++} ++ ++int nvram_parse_mac_addr(const char *nvram, unsigned nvram_len, ++ const char *name, char *mac) ++{ ++ char *buf; ++ char *mac_str; ++ int ret; ++ int t; ++ ++ buf = vmalloc(nvram_len); ++ if (!buf) ++ return -ENOMEM; ++ ++ memcpy(buf, nvram, nvram_len); ++ buf[nvram_len - 1] = '\0'; ++ ++ mac_str = nvram_find_var(name, buf, nvram_len); ++ if (!mac_str) { ++ ret = -EINVAL; ++ goto free; ++ } ++ ++ t = sscanf(mac_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", ++ &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]); ++ ++ if (t != 6) { ++ ret = -EINVAL; ++ goto free; ++ } ++ ++ ret = 0; ++ ++ free: ++ vfree(buf); ++ return ret; ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/nvram.h linux-2.6.39/arch/mips/ar71xx/nvram.h +--- linux-2.6.39.orig/arch/mips/ar71xx/nvram.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/nvram.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,19 @@ ++/* ++ * Atheros AR71xx minimal nvram support ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef _AR71XX_NVRAM_H ++#define _AR71XX_NVRAM_H ++ ++char *nvram_find_var(const char *name, const char *buf, ++ unsigned buf_len) __init; ++int nvram_parse_mac_addr(const char *nvram, unsigned nvram_len, ++ const char *name, char *mac) __init; ++ ++#endif /* _AR71XX_NVRAM_H */ +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/pci.c linux-2.6.39/arch/mips/ar71xx/pci.c +--- linux-2.6.39.orig/arch/mips/ar71xx/pci.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/pci.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,93 @@ ++/* ++ * Atheros AR71xx PCI setup code ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/kernel.h> ++ ++#include <asm/traps.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/pci.h> ++ ++unsigned ar71xx_pci_nr_irqs __initdata; ++struct ar71xx_pci_irq *ar71xx_pci_irq_map __initdata; ++ ++int (*ar71xx_pci_plat_dev_init)(struct pci_dev *dev); ++ ++static int ar71xx_be_handler(struct pt_regs *regs, int is_fixup) ++{ ++ int err = 0; ++ ++ err = ar71xx_pci_be_handler(is_fixup); ++ ++ return (is_fixup && !err) ? MIPS_BE_FIXUP : MIPS_BE_FATAL; ++} ++ ++int pcibios_plat_dev_init(struct pci_dev *dev) ++{ ++ if (ar71xx_pci_plat_dev_init) ++ return ar71xx_pci_plat_dev_init(dev); ++ ++ return 0; ++} ++ ++int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) ++{ ++ int ret = 0; ++ ++ switch (ar71xx_soc) { ++ case AR71XX_SOC_AR7130: ++ case AR71XX_SOC_AR7141: ++ case AR71XX_SOC_AR7161: ++ ret = ar71xx_pcibios_map_irq(dev, slot, pin); ++ break; ++ ++ case AR71XX_SOC_AR7240: ++ case AR71XX_SOC_AR7241: ++ case AR71XX_SOC_AR7242: ++ ret = ar724x_pcibios_map_irq(dev, slot, pin); ++ break; ++ ++ default: ++ break; ++ } ++ ++ return ret; ++} ++ ++int __init ar71xx_pci_init(unsigned nr_irqs, struct ar71xx_pci_irq *map) ++{ ++ int ret = 0; ++ ++ switch (ar71xx_soc) { ++ case AR71XX_SOC_AR7130: ++ case AR71XX_SOC_AR7141: ++ case AR71XX_SOC_AR7161: ++ board_be_handler = ar71xx_be_handler; ++ ret = ar71xx_pcibios_init(); ++ break; ++ ++ case AR71XX_SOC_AR7240: ++ case AR71XX_SOC_AR7241: ++ case AR71XX_SOC_AR7242: ++ ret = ar724x_pcibios_init(); ++ break; ++ ++ default: ++ return 0; ++ } ++ ++ ar71xx_pci_nr_irqs = nr_irqs; ++ ar71xx_pci_irq_map = map; ++ ++ return ret; ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/prom.c linux-2.6.39/arch/mips/ar71xx/prom.c +--- linux-2.6.39.orig/arch/mips/ar71xx/prom.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/prom.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,105 @@ ++/* ++ * Atheros AR71xx SoC specific prom routines ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/io.h> ++#include <linux/string.h> ++ ++#include <asm/bootinfo.h> ++#include <asm/addrspace.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++static inline int is_valid_ram_addr(void *addr) ++{ ++ if (((u32) addr > KSEG0) && ++ ((u32) addr < (KSEG0 + AR71XX_MEM_SIZE_MAX))) ++ return 1; ++ ++ if (((u32) addr > KSEG1) && ++ ((u32) addr < (KSEG1 + AR71XX_MEM_SIZE_MAX))) ++ return 1; ++ ++ return 0; ++} ++ ++static void __init ar71xx_prom_append_cmdline(const char *name, ++ const char *value) ++{ ++ char buf[COMMAND_LINE_SIZE]; ++ ++ snprintf(buf, sizeof(buf), " %s=%s", name, value); ++ strlcat(arcs_cmdline, buf, sizeof(arcs_cmdline)); ++} ++ ++static void __init ar71xx_prom_find_env(char **envp, const char *name) ++{ ++ int len = strlen(name); ++ char **p; ++ ++ if (!is_valid_ram_addr(envp)) ++ return; ++ ++ for (p = envp; is_valid_ram_addr(*p); p++) { ++ if (strncmp(name, *p, len) == 0 && (*p)[len] == '=') { ++ ar71xx_prom_append_cmdline(name, *p + len + 1); ++ break; ++ } ++ ++ /* RedBoot env comes in pointer pairs - key, value */ ++ if (strncmp(name, *p, len) == 0 && (*p)[len] == 0) ++ if (is_valid_ram_addr(*(++p))) { ++ ar71xx_prom_append_cmdline(name, *p); ++ break; ++ } ++ } ++} ++ ++static int inline ar71xx_use__image_cmdline(void) { return 0; } ++ ++static __init void ar71xx_prom_init_cmdline(int argc, char **argv) ++{ ++ int i; ++ ++ if (ar71xx_use__image_cmdline()) ++ return; ++ ++ if (!is_valid_ram_addr(argv)) ++ return; ++ ++ for (i = 0; i < argc; i++) ++ if (is_valid_ram_addr(argv[i])) { ++ strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline)); ++ strlcat(arcs_cmdline, argv[i], sizeof(arcs_cmdline)); ++ } ++} ++ ++void __init prom_init(void) ++{ ++ char **envp; ++ ++ printk(KERN_DEBUG "prom: fw_arg0=%08x, fw_arg1=%08x, " ++ "fw_arg2=%08x, fw_arg3=%08x\n", ++ (unsigned int)fw_arg0, (unsigned int)fw_arg1, ++ (unsigned int)fw_arg2, (unsigned int)fw_arg3); ++ ++ ++ ar71xx_prom_init_cmdline(fw_arg0, (char **)fw_arg1); ++ ++ envp = (char **)fw_arg2; ++ ar71xx_prom_find_env(envp, "board"); ++} ++ ++void __init prom_free_prom_memory(void) ++{ ++ /* We do not have to prom memory to free */ ++} +diff -Nur linux-2.6.39.orig/arch/mips/ar71xx/setup.c linux-2.6.39/arch/mips/ar71xx/setup.c +--- linux-2.6.39.orig/arch/mips/ar71xx/setup.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/ar71xx/setup.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,310 @@ ++/* ++ * Atheros AR71xx SoC specific setup ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/bootmem.h> ++ ++#include <asm/bootinfo.h> ++#include <asm/time.h> /* for mips_hpt_frequency */ ++#include <asm/reboot.h> /* for _machine_{restart,halt} */ ++#include <asm/mips_machine.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#include "machtype.h" ++#include "devices.h" ++ ++#define AR71XX_SYS_TYPE_LEN 64 ++#define AR71XX_BASE_FREQ 40000000 ++#define AR91XX_BASE_FREQ 5000000 ++#define AR724X_BASE_FREQ 5000000 ++ ++u32 ar71xx_cpu_freq; ++EXPORT_SYMBOL_GPL(ar71xx_cpu_freq); ++ ++u32 ar71xx_ahb_freq; ++EXPORT_SYMBOL_GPL(ar71xx_ahb_freq); ++ ++u32 ar71xx_ddr_freq; ++EXPORT_SYMBOL_GPL(ar71xx_ddr_freq); ++ ++enum ar71xx_soc_type ar71xx_soc; ++EXPORT_SYMBOL_GPL(ar71xx_soc); ++ ++static char ar71xx_sys_type[AR71XX_SYS_TYPE_LEN]; ++ ++static void ar71xx_restart(char *command) ++{ ++ ar71xx_device_stop(RESET_MODULE_FULL_CHIP); ++ for (;;) ++ if (cpu_wait) ++ cpu_wait(); ++} ++ ++static void ar71xx_halt(void) ++{ ++ while (1) ++ cpu_wait(); ++} ++ ++static void __init ar71xx_detect_mem_size(void) ++{ ++ unsigned long size; ++ ++ for (size = AR71XX_MEM_SIZE_MIN; size < AR71XX_MEM_SIZE_MAX; ++ size <<= 1 ) { ++ if (!memcmp(ar71xx_detect_mem_size, ++ ar71xx_detect_mem_size + size, 1024)) ++ break; ++ } ++ ++ add_memory_region(0, size, BOOT_MEM_RAM); ++} ++ ++static void __init ar71xx_detect_sys_type(void) ++{ ++ char *chip = "????"; ++ u32 id; ++ u32 major; ++ u32 minor; ++ u32 rev = 0; ++ ++ id = ar71xx_reset_rr(AR71XX_RESET_REG_REV_ID); ++ major = id & REV_ID_MAJOR_MASK; ++ ++ switch (major) { ++ case REV_ID_MAJOR_AR71XX: ++ minor = id & AR71XX_REV_ID_MINOR_MASK; ++ rev = id >> AR71XX_REV_ID_REVISION_SHIFT; ++ rev &= AR71XX_REV_ID_REVISION_MASK; ++ switch (minor) { ++ case AR71XX_REV_ID_MINOR_AR7130: ++ ar71xx_soc = AR71XX_SOC_AR7130; ++ chip = "7130"; ++ break; ++ ++ case AR71XX_REV_ID_MINOR_AR7141: ++ ar71xx_soc = AR71XX_SOC_AR7141; ++ chip = "7141"; ++ break; ++ ++ case AR71XX_REV_ID_MINOR_AR7161: ++ ar71xx_soc = AR71XX_SOC_AR7161; ++ chip = "7161"; ++ break; ++ } ++ break; ++ ++ case REV_ID_MAJOR_AR7240: ++ ar71xx_soc = AR71XX_SOC_AR7240; ++ chip = "7240"; ++ rev = (id & AR724X_REV_ID_REVISION_MASK); ++ break; ++ ++ case REV_ID_MAJOR_AR7241: ++ ar71xx_soc = AR71XX_SOC_AR7241; ++ chip = "7241"; ++ rev = (id & AR724X_REV_ID_REVISION_MASK); ++ break; ++ ++ case REV_ID_MAJOR_AR7242: ++ ar71xx_soc = AR71XX_SOC_AR7242; ++ chip = "7242"; ++ rev = (id & AR724X_REV_ID_REVISION_MASK); ++ break; ++ ++ case REV_ID_MAJOR_AR913X: ++ minor = id & AR91XX_REV_ID_MINOR_MASK; ++ rev = id >> AR91XX_REV_ID_REVISION_SHIFT; ++ rev &= AR91XX_REV_ID_REVISION_MASK; ++ switch (minor) { ++ case AR91XX_REV_ID_MINOR_AR9130: ++ ar71xx_soc = AR71XX_SOC_AR9130; ++ chip = "9130"; ++ break; ++ ++ case AR91XX_REV_ID_MINOR_AR9132: ++ ar71xx_soc = AR71XX_SOC_AR9132; ++ chip = "9132"; ++ break; ++ } ++ break; ++ ++ default: ++ panic("ar71xx: unknown chip id:0x%08x\n", id); ++ } ++ ++ sprintf(ar71xx_sys_type, "Atheros AR%s rev %u", chip, rev); ++} ++ ++static void __init ar91xx_detect_sys_frequency(void) ++{ ++ u32 pll; ++ u32 freq; ++ u32 div; ++ ++ pll = ar71xx_pll_rr(AR91XX_PLL_REG_CPU_CONFIG); ++ ++ div = ((pll >> AR91XX_PLL_DIV_SHIFT) & AR91XX_PLL_DIV_MASK); ++ freq = div * AR91XX_BASE_FREQ; ++ ++ ar71xx_cpu_freq = freq; ++ ++ div = ((pll >> AR91XX_DDR_DIV_SHIFT) & AR91XX_DDR_DIV_MASK) + 1; ++ ar71xx_ddr_freq = freq / div; ++ ++ div = (((pll >> AR91XX_AHB_DIV_SHIFT) & AR91XX_AHB_DIV_MASK) + 1) * 2; ++ ar71xx_ahb_freq = ar71xx_cpu_freq / div; ++} ++ ++static void __init ar71xx_detect_sys_frequency(void) ++{ ++ u32 pll; ++ u32 freq; ++ u32 div; ++ ++ pll = ar71xx_pll_rr(AR71XX_PLL_REG_CPU_CONFIG); ++ ++ div = ((pll >> AR71XX_PLL_DIV_SHIFT) & AR71XX_PLL_DIV_MASK) + 1; ++ freq = div * AR71XX_BASE_FREQ; ++ ++ div = ((pll >> AR71XX_CPU_DIV_SHIFT) & AR71XX_CPU_DIV_MASK) + 1; ++ ar71xx_cpu_freq = freq / div; ++ ++ div = ((pll >> AR71XX_DDR_DIV_SHIFT) & AR71XX_DDR_DIV_MASK) + 1; ++ ar71xx_ddr_freq = freq / div; ++ ++ div = (((pll >> AR71XX_AHB_DIV_SHIFT) & AR71XX_AHB_DIV_MASK) + 1) * 2; ++ ar71xx_ahb_freq = ar71xx_cpu_freq / div; ++} ++ ++static void __init ar724x_detect_sys_frequency(void) ++{ ++ u32 pll; ++ u32 freq; ++ u32 div; ++ ++ pll = ar71xx_pll_rr(AR724X_PLL_REG_CPU_CONFIG); ++ ++ div = ((pll >> AR724X_PLL_DIV_SHIFT) & AR724X_PLL_DIV_MASK); ++ freq = div * AR724X_BASE_FREQ; ++ ++ div = ((pll >> AR724X_PLL_REF_DIV_SHIFT) & AR724X_PLL_REF_DIV_MASK); ++ freq *= div; ++ ++ ar71xx_cpu_freq = freq; ++ ++ div = ((pll >> AR724X_DDR_DIV_SHIFT) & AR724X_DDR_DIV_MASK) + 1; ++ ar71xx_ddr_freq = freq / div; ++ ++ div = (((pll >> AR724X_AHB_DIV_SHIFT) & AR724X_AHB_DIV_MASK) + 1) * 2; ++ ar71xx_ahb_freq = ar71xx_cpu_freq / div; ++} ++ ++static void __init detect_sys_frequency(void) ++{ ++ switch (ar71xx_soc) { ++ case AR71XX_SOC_AR7130: ++ case AR71XX_SOC_AR7141: ++ case AR71XX_SOC_AR7161: ++ ar71xx_detect_sys_frequency(); ++ break; ++ ++ case AR71XX_SOC_AR7240: ++ case AR71XX_SOC_AR7241: ++ case AR71XX_SOC_AR7242: ++ ar724x_detect_sys_frequency(); ++ break; ++ ++ case AR71XX_SOC_AR9130: ++ case AR71XX_SOC_AR9132: ++ ar91xx_detect_sys_frequency(); ++ break; ++ ++ default: ++ BUG(); ++ } ++} ++ ++const char *get_system_type(void) ++{ ++ return ar71xx_sys_type; ++} ++ ++unsigned int __cpuinit get_c0_compare_irq(void) ++{ ++ return CP0_LEGACY_COMPARE_IRQ; ++} ++ ++void __init plat_mem_setup(void) ++{ ++ set_io_port_base(KSEG1); ++ ++ ar71xx_ddr_base = ioremap_nocache(AR71XX_DDR_CTRL_BASE, ++ AR71XX_DDR_CTRL_SIZE); ++ ++ ar71xx_pll_base = ioremap_nocache(AR71XX_PLL_BASE, ++ AR71XX_PLL_SIZE); ++ ++ ar71xx_reset_base = ioremap_nocache(AR71XX_RESET_BASE, ++ AR71XX_RESET_SIZE); ++ ++ ar71xx_gpio_base = ioremap_nocache(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE); ++ ++ ar71xx_usb_ctrl_base = ioremap_nocache(AR71XX_USB_CTRL_BASE, ++ AR71XX_USB_CTRL_SIZE); ++ ++ ar71xx_detect_mem_size(); ++ ar71xx_detect_sys_type(); ++ detect_sys_frequency(); ++ ++ printk(KERN_INFO ++ "%s, CPU:%u.%03u MHz, AHB:%u.%03u MHz, DDR:%u.%03u MHz\n", ++ ar71xx_sys_type, ++ ar71xx_cpu_freq / 1000000, (ar71xx_cpu_freq / 1000) % 1000, ++ ar71xx_ahb_freq / 1000000, (ar71xx_ahb_freq / 1000) % 1000, ++ ar71xx_ddr_freq / 1000000, (ar71xx_ddr_freq / 1000) % 1000); ++ ++ _machine_restart = ar71xx_restart; ++ _machine_halt = ar71xx_halt; ++ pm_power_off = ar71xx_halt; ++} ++ ++void __init plat_time_init(void) ++{ ++ mips_hpt_frequency = ar71xx_cpu_freq / 2; ++} ++ ++__setup("board=", mips_machtype_setup); ++ ++static int __init ar71xx_machine_setup(void) ++{ ++ ar71xx_gpio_init(); ++ ++ ar71xx_add_device_uart(); ++ ar71xx_add_device_wdt(); ++ ++ mips_machine_setup(); ++ return 0; ++} ++ ++arch_initcall(ar71xx_machine_setup); ++ ++static void __init ar71xx_generic_init(void) ++{ ++ /* Nothing to do */ ++} ++ ++MIPS_MACHINE(AR71XX_MACH_GENERIC, "Generic", "Generic AR71xx board", ++ ar71xx_generic_init); +diff -Nur linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/ar71xx.h linux-2.6.39/arch/mips/include/asm/mach-ar71xx/ar71xx.h +--- linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/ar71xx.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/include/asm/mach-ar71xx/ar71xx.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,514 @@ ++/* ++ * Atheros AR71xx SoC specific definitions ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef __ASM_MACH_AR71XX_H ++#define __ASM_MACH_AR71XX_H ++ ++#include <linux/types.h> ++#include <linux/init.h> ++#include <linux/io.h> ++#include <linux/bitops.h> ++ ++#ifndef __ASSEMBLER__ ++ ++#define AR71XX_PCI_MEM_BASE 0x10000000 ++#define AR71XX_PCI_MEM_SIZE 0x08000000 ++#define AR71XX_APB_BASE 0x18000000 ++#define AR71XX_GE0_BASE 0x19000000 ++#define AR71XX_GE0_SIZE 0x01000000 ++#define AR71XX_GE1_BASE 0x1a000000 ++#define AR71XX_GE1_SIZE 0x01000000 ++#define AR71XX_EHCI_BASE 0x1b000000 ++#define AR71XX_EHCI_SIZE 0x01000000 ++#define AR71XX_OHCI_BASE 0x1c000000 ++#define AR71XX_OHCI_SIZE 0x01000000 ++#define AR7240_OHCI_BASE 0x1b000000 ++#define AR7240_OHCI_SIZE 0x01000000 ++#define AR71XX_SPI_BASE 0x1f000000 ++#define AR71XX_SPI_SIZE 0x01000000 ++ ++#define AR71XX_DDR_CTRL_BASE (AR71XX_APB_BASE + 0x00000000) ++#define AR71XX_DDR_CTRL_SIZE 0x10000 ++#define AR71XX_CPU_BASE (AR71XX_APB_BASE + 0x00010000) ++#define AR71XX_UART_BASE (AR71XX_APB_BASE + 0x00020000) ++#define AR71XX_UART_SIZE 0x10000 ++#define AR71XX_USB_CTRL_BASE (AR71XX_APB_BASE + 0x00030000) ++#define AR71XX_USB_CTRL_SIZE 0x10000 ++#define AR71XX_GPIO_BASE (AR71XX_APB_BASE + 0x00040000) ++#define AR71XX_GPIO_SIZE 0x10000 ++#define AR71XX_PLL_BASE (AR71XX_APB_BASE + 0x00050000) ++#define AR71XX_PLL_SIZE 0x10000 ++#define AR71XX_RESET_BASE (AR71XX_APB_BASE + 0x00060000) ++#define AR71XX_RESET_SIZE 0x10000 ++#define AR71XX_MII_BASE (AR71XX_APB_BASE + 0x00070000) ++#define AR71XX_MII_SIZE 0x10000 ++#define AR71XX_SLIC_BASE (AR71XX_APB_BASE + 0x00090000) ++#define AR71XX_SLIC_SIZE 0x10000 ++#define AR71XX_DMA_BASE (AR71XX_APB_BASE + 0x000A0000) ++#define AR71XX_DMA_SIZE 0x10000 ++#define AR71XX_STEREO_BASE (AR71XX_APB_BASE + 0x000B0000) ++#define AR71XX_STEREO_SIZE 0x10000 ++ ++#define AR724X_PCI_CRP_BASE (AR71XX_APB_BASE + 0x000C0000) ++#define AR724X_PCI_CRP_SIZE 0x100 ++ ++#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000F0000) ++#define AR724X_PCI_CTRL_SIZE 0x100 ++ ++#define AR91XX_WMAC_BASE (AR71XX_APB_BASE + 0x000C0000) ++#define AR91XX_WMAC_SIZE 0x30000 ++ ++#define AR71XX_MEM_SIZE_MIN 0x0200000 ++#define AR71XX_MEM_SIZE_MAX 0x10000000 ++ ++#define AR71XX_CPU_IRQ_BASE 0 ++#define AR71XX_MISC_IRQ_BASE 8 ++#define AR71XX_MISC_IRQ_COUNT 8 ++#define AR71XX_GPIO_IRQ_BASE 16 ++#define AR71XX_GPIO_IRQ_COUNT 32 ++#define AR71XX_PCI_IRQ_BASE 48 ++#define AR71XX_PCI_IRQ_COUNT 8 ++ ++#define AR71XX_CPU_IRQ_IP2 (AR71XX_CPU_IRQ_BASE + 2) ++#define AR71XX_CPU_IRQ_USB (AR71XX_CPU_IRQ_BASE + 3) ++#define AR71XX_CPU_IRQ_GE0 (AR71XX_CPU_IRQ_BASE + 4) ++#define AR71XX_CPU_IRQ_GE1 (AR71XX_CPU_IRQ_BASE + 5) ++#define AR71XX_CPU_IRQ_MISC (AR71XX_CPU_IRQ_BASE + 6) ++#define AR71XX_CPU_IRQ_TIMER (AR71XX_CPU_IRQ_BASE + 7) ++ ++#define AR71XX_MISC_IRQ_TIMER (AR71XX_MISC_IRQ_BASE + 0) ++#define AR71XX_MISC_IRQ_ERROR (AR71XX_MISC_IRQ_BASE + 1) ++#define AR71XX_MISC_IRQ_GPIO (AR71XX_MISC_IRQ_BASE + 2) ++#define AR71XX_MISC_IRQ_UART (AR71XX_MISC_IRQ_BASE + 3) ++#define AR71XX_MISC_IRQ_WDOG (AR71XX_MISC_IRQ_BASE + 4) ++#define AR71XX_MISC_IRQ_PERFC (AR71XX_MISC_IRQ_BASE + 5) ++#define AR71XX_MISC_IRQ_OHCI (AR71XX_MISC_IRQ_BASE + 6) ++#define AR71XX_MISC_IRQ_DMA (AR71XX_MISC_IRQ_BASE + 7) ++ ++#define AR71XX_GPIO_IRQ(_x) (AR71XX_GPIO_IRQ_BASE + (_x)) ++ ++#define AR71XX_PCI_IRQ_DEV0 (AR71XX_PCI_IRQ_BASE + 0) ++#define AR71XX_PCI_IRQ_DEV1 (AR71XX_PCI_IRQ_BASE + 1) ++#define AR71XX_PCI_IRQ_DEV2 (AR71XX_PCI_IRQ_BASE + 2) ++#define AR71XX_PCI_IRQ_CORE (AR71XX_PCI_IRQ_BASE + 4) ++ ++extern u32 ar71xx_ahb_freq; ++extern u32 ar71xx_cpu_freq; ++extern u32 ar71xx_ddr_freq; ++ ++enum ar71xx_soc_type { ++ AR71XX_SOC_UNKNOWN, ++ AR71XX_SOC_AR7130, ++ AR71XX_SOC_AR7141, ++ AR71XX_SOC_AR7161, ++ AR71XX_SOC_AR7240, ++ AR71XX_SOC_AR7241, ++ AR71XX_SOC_AR7242, ++ AR71XX_SOC_AR9130, ++ AR71XX_SOC_AR9132 ++}; ++ ++extern enum ar71xx_soc_type ar71xx_soc; ++ ++/* ++ * PLL block ++ */ ++#define AR71XX_PLL_REG_CPU_CONFIG 0x00 ++#define AR71XX_PLL_REG_SEC_CONFIG 0x04 ++#define AR71XX_PLL_REG_ETH0_INT_CLOCK 0x10 ++#define AR71XX_PLL_REG_ETH1_INT_CLOCK 0x14 ++ ++#define AR71XX_PLL_DIV_SHIFT 3 ++#define AR71XX_PLL_DIV_MASK 0x1f ++#define AR71XX_CPU_DIV_SHIFT 16 ++#define AR71XX_CPU_DIV_MASK 0x3 ++#define AR71XX_DDR_DIV_SHIFT 18 ++#define AR71XX_DDR_DIV_MASK 0x3 ++#define AR71XX_AHB_DIV_SHIFT 20 ++#define AR71XX_AHB_DIV_MASK 0x7 ++ ++#define AR71XX_ETH0_PLL_SHIFT 17 ++#define AR71XX_ETH1_PLL_SHIFT 19 ++ ++#define AR724X_PLL_REG_CPU_CONFIG 0x00 ++#define AR724X_PLL_REG_PCIE_CONFIG 0x18 ++ ++#define AR724X_PLL_DIV_SHIFT 0 ++#define AR724X_PLL_DIV_MASK 0x3ff ++#define AR724X_PLL_REF_DIV_SHIFT 10 ++#define AR724X_PLL_REF_DIV_MASK 0xf ++#define AR724X_AHB_DIV_SHIFT 19 ++#define AR724X_AHB_DIV_MASK 0x1 ++#define AR724X_DDR_DIV_SHIFT 22 ++#define AR724X_DDR_DIV_MASK 0x3 ++ ++#define AR91XX_PLL_REG_CPU_CONFIG 0x00 ++#define AR91XX_PLL_REG_ETH_CONFIG 0x04 ++#define AR91XX_PLL_REG_ETH0_INT_CLOCK 0x14 ++#define AR91XX_PLL_REG_ETH1_INT_CLOCK 0x18 ++ ++#define AR91XX_PLL_DIV_SHIFT 0 ++#define AR91XX_PLL_DIV_MASK 0x3ff ++#define AR91XX_DDR_DIV_SHIFT 22 ++#define AR91XX_DDR_DIV_MASK 0x3 ++#define AR91XX_AHB_DIV_SHIFT 19 ++#define AR91XX_AHB_DIV_MASK 0x1 ++ ++#define AR91XX_ETH0_PLL_SHIFT 20 ++#define AR91XX_ETH1_PLL_SHIFT 22 ++ ++extern void __iomem *ar71xx_pll_base; ++ ++static inline void ar71xx_pll_wr(unsigned reg, u32 val) ++{ ++ __raw_writel(val, ar71xx_pll_base + reg); ++} ++ ++static inline u32 ar71xx_pll_rr(unsigned reg) ++{ ++ return __raw_readl(ar71xx_pll_base + reg); ++} ++ ++/* ++ * USB_CONFIG block ++ */ ++#define USB_CTRL_REG_FLADJ 0x00 ++#define USB_CTRL_REG_CONFIG 0x04 ++ ++extern void __iomem *ar71xx_usb_ctrl_base; ++ ++static inline void ar71xx_usb_ctrl_wr(unsigned reg, u32 val) ++{ ++ __raw_writel(val, ar71xx_usb_ctrl_base + reg); ++} ++ ++static inline u32 ar71xx_usb_ctrl_rr(unsigned reg) ++{ ++ return __raw_readl(ar71xx_usb_ctrl_base + reg); ++} ++ ++/* ++ * GPIO block ++ */ ++#define GPIO_REG_OE 0x00 ++#define GPIO_REG_IN 0x04 ++#define GPIO_REG_OUT 0x08 ++#define GPIO_REG_SET 0x0c ++#define GPIO_REG_CLEAR 0x10 ++#define GPIO_REG_INT_MODE 0x14 ++#define GPIO_REG_INT_TYPE 0x18 ++#define GPIO_REG_INT_POLARITY 0x1c ++#define GPIO_REG_INT_PENDING 0x20 ++#define GPIO_REG_INT_ENABLE 0x24 ++#define GPIO_REG_FUNC 0x28 ++ ++#define AR71XX_GPIO_FUNC_STEREO_EN BIT(17) ++#define AR71XX_GPIO_FUNC_SLIC_EN BIT(16) ++#define AR71XX_GPIO_FUNC_SPI_CS2_EN BIT(13) ++#define AR71XX_GPIO_FUNC_SPI_CS1_EN BIT(12) ++#define AR71XX_GPIO_FUNC_UART_EN BIT(8) ++#define AR71XX_GPIO_FUNC_USB_OC_EN BIT(4) ++#define AR71XX_GPIO_FUNC_USB_CLK_EN BIT(0) ++ ++#define AR71XX_GPIO_COUNT 16 ++ ++#define AR724X_GPIO_FUNC_GE0_MII_CLK_EN BIT(19) ++#define AR724X_GPIO_FUNC_SPI_EN BIT(18) ++#define AR724X_GPIO_FUNC_SPI_CS_EN2 BIT(14) ++#define AR724X_GPIO_FUNC_SPI_CS_EN1 BIT(13) ++#define AR724X_GPIO_FUNC_CLK_OBS5_EN BIT(12) ++#define AR724X_GPIO_FUNC_CLK_OBS4_EN BIT(11) ++#define AR724X_GPIO_FUNC_CLK_OBS3_EN BIT(10) ++#define AR724X_GPIO_FUNC_CLK_OBS2_EN BIT(9) ++#define AR724X_GPIO_FUNC_CLK_OBS1_EN BIT(8) ++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED4_EN BIT(7) ++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED3_EN BIT(6) ++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED2_EN BIT(5) ++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED1_EN BIT(4) ++#define AR724X_GPIO_FUNC_ETH_SWITCH_LED0_EN BIT(3) ++#define AR724X_GPIO_FUNC_UART_RTS_CTS_EN BIT(2) ++#define AR724X_GPIO_FUNC_UART_EN BIT(1) ++#define AR724X_GPIO_FUNC_JTAG_DISABLE BIT(0) ++ ++#define AR724X_GPIO_COUNT 18 ++ ++#define AR91XX_GPIO_FUNC_WMAC_LED_EN BIT(22) ++#define AR91XX_GPIO_FUNC_EXP_PORT_CS_EN BIT(21) ++#define AR91XX_GPIO_FUNC_I2S_REFCLKEN BIT(20) ++#define AR91XX_GPIO_FUNC_I2S_MCKEN BIT(19) ++#define AR91XX_GPIO_FUNC_I2S1_EN BIT(18) ++#define AR91XX_GPIO_FUNC_I2S0_EN BIT(17) ++#define AR91XX_GPIO_FUNC_SLIC_EN BIT(16) ++#define AR91XX_GPIO_FUNC_UART_RTSCTS_EN BIT(9) ++#define AR91XX_GPIO_FUNC_UART_EN BIT(8) ++#define AR91XX_GPIO_FUNC_USB_CLK_EN BIT(4) ++ ++#define AR91XX_GPIO_COUNT 22 ++ ++extern void __iomem *ar71xx_gpio_base; ++ ++static inline void ar71xx_gpio_wr(unsigned reg, u32 value) ++{ ++ __raw_writel(value, ar71xx_gpio_base + reg); ++} ++ ++static inline u32 ar71xx_gpio_rr(unsigned reg) ++{ ++ return __raw_readl(ar71xx_gpio_base + reg); ++} ++ ++void ar71xx_gpio_init(void) __init; ++void ar71xx_gpio_function_enable(u32 mask); ++void ar71xx_gpio_function_disable(u32 mask); ++void ar71xx_gpio_function_setup(u32 set, u32 clear); ++ ++/* ++ * DDR_CTRL block ++ */ ++#define AR71XX_DDR_REG_PCI_WIN0 0x7c ++#define AR71XX_DDR_REG_PCI_WIN1 0x80 ++#define AR71XX_DDR_REG_PCI_WIN2 0x84 ++#define AR71XX_DDR_REG_PCI_WIN3 0x88 ++#define AR71XX_DDR_REG_PCI_WIN4 0x8c ++#define AR71XX_DDR_REG_PCI_WIN5 0x90 ++#define AR71XX_DDR_REG_PCI_WIN6 0x94 ++#define AR71XX_DDR_REG_PCI_WIN7 0x98 ++#define AR71XX_DDR_REG_FLUSH_GE0 0x9c ++#define AR71XX_DDR_REG_FLUSH_GE1 0xa0 ++#define AR71XX_DDR_REG_FLUSH_USB 0xa4 ++#define AR71XX_DDR_REG_FLUSH_PCI 0xa8 ++ ++#define AR724X_DDR_REG_FLUSH_GE0 0x7c ++#define AR724X_DDR_REG_FLUSH_GE1 0x80 ++#define AR724X_DDR_REG_FLUSH_USB 0x84 ++#define AR724X_DDR_REG_FLUSH_PCIE 0x88 ++ ++#define AR91XX_DDR_REG_FLUSH_GE0 0x7c ++#define AR91XX_DDR_REG_FLUSH_GE1 0x80 ++#define AR91XX_DDR_REG_FLUSH_USB 0x84 ++#define AR91XX_DDR_REG_FLUSH_WMAC 0x88 ++ ++#define PCI_WIN0_OFFS 0x10000000 ++#define PCI_WIN1_OFFS 0x11000000 ++#define PCI_WIN2_OFFS 0x12000000 ++#define PCI_WIN3_OFFS 0x13000000 ++#define PCI_WIN4_OFFS 0x14000000 ++#define PCI_WIN5_OFFS 0x15000000 ++#define PCI_WIN6_OFFS 0x16000000 ++#define PCI_WIN7_OFFS 0x07000000 ++ ++extern void __iomem *ar71xx_ddr_base; ++ ++static inline void ar71xx_ddr_wr(unsigned reg, u32 val) ++{ ++ __raw_writel(val, ar71xx_ddr_base + reg); ++} ++ ++static inline u32 ar71xx_ddr_rr(unsigned reg) ++{ ++ return __raw_readl(ar71xx_ddr_base + reg); ++} ++ ++void ar71xx_ddr_flush(u32 reg); ++ ++/* ++ * PCI block ++ */ ++#define AR71XX_PCI_CFG_BASE (AR71XX_PCI_MEM_BASE + PCI_WIN7_OFFS + 0x10000) ++#define AR71XX_PCI_CFG_SIZE 0x100 ++ ++#define PCI_REG_CRP_AD_CBE 0x00 ++#define PCI_REG_CRP_WRDATA 0x04 ++#define PCI_REG_CRP_RDDATA 0x08 ++#define PCI_REG_CFG_AD 0x0c ++#define PCI_REG_CFG_CBE 0x10 ++#define PCI_REG_CFG_WRDATA 0x14 ++#define PCI_REG_CFG_RDDATA 0x18 ++#define PCI_REG_PCI_ERR 0x1c ++#define PCI_REG_PCI_ERR_ADDR 0x20 ++#define PCI_REG_AHB_ERR 0x24 ++#define PCI_REG_AHB_ERR_ADDR 0x28 ++ ++#define PCI_CRP_CMD_WRITE 0x00010000 ++#define PCI_CRP_CMD_READ 0x00000000 ++#define PCI_CFG_CMD_READ 0x0000000a ++#define PCI_CFG_CMD_WRITE 0x0000000b ++ ++#define PCI_IDSEL_ADL_START 17 ++ ++#define AR724X_PCI_CFG_BASE (AR71XX_PCI_MEM_BASE + 0x4000000) ++#define AR724X_PCI_CFG_SIZE 0x1000 ++ ++#define AR724X_PCI_REG_APP 0x00 ++#define AR724X_PCI_REG_RESET 0x18 ++#define AR724X_PCI_REG_INT_STATUS 0x4c ++#define AR724X_PCI_REG_INT_MASK 0x50 ++ ++#define AR724X_PCI_APP_LTSSM_ENABLE BIT(0) ++#define AR724X_PCI_RESET_LINK_UP BIT(0) ++ ++#define AR724X_PCI_INT_DEV0 BIT(14) ++ ++/* ++ * RESET block ++ */ ++#define AR71XX_RESET_REG_TIMER 0x00 ++#define AR71XX_RESET_REG_TIMER_RELOAD 0x04 ++#define AR71XX_RESET_REG_WDOG_CTRL 0x08 ++#define AR71XX_RESET_REG_WDOG 0x0c ++#define AR71XX_RESET_REG_MISC_INT_STATUS 0x10 ++#define AR71XX_RESET_REG_MISC_INT_ENABLE 0x14 ++#define AR71XX_RESET_REG_PCI_INT_STATUS 0x18 ++#define AR71XX_RESET_REG_PCI_INT_ENABLE 0x1c ++#define AR71XX_RESET_REG_GLOBAL_INT_STATUS 0x20 ++#define AR71XX_RESET_REG_RESET_MODULE 0x24 ++#define AR71XX_RESET_REG_PERFC_CTRL 0x2c ++#define AR71XX_RESET_REG_PERFC0 0x30 ++#define AR71XX_RESET_REG_PERFC1 0x34 ++#define AR71XX_RESET_REG_REV_ID 0x90 ++ ++#define AR91XX_RESET_REG_GLOBAL_INT_STATUS 0x18 ++#define AR91XX_RESET_REG_RESET_MODULE 0x1c ++#define AR91XX_RESET_REG_PERF_CTRL 0x20 ++#define AR91XX_RESET_REG_PERFC0 0x24 ++#define AR91XX_RESET_REG_PERFC1 0x28 ++ ++#define AR724X_RESET_REG_RESET_MODULE 0x1c ++ ++#define WDOG_CTRL_LAST_RESET BIT(31) ++#define WDOG_CTRL_ACTION_MASK 3 ++#define WDOG_CTRL_ACTION_NONE 0 /* no action */ ++#define WDOG_CTRL_ACTION_GPI 1 /* general purpose interrupt */ ++#define WDOG_CTRL_ACTION_NMI 2 /* NMI */ ++#define WDOG_CTRL_ACTION_FCR 3 /* full chip reset */ ++ ++#define MISC_INT_DMA BIT(7) ++#define MISC_INT_OHCI BIT(6) ++#define MISC_INT_PERFC BIT(5) ++#define MISC_INT_WDOG BIT(4) ++#define MISC_INT_UART BIT(3) ++#define MISC_INT_GPIO BIT(2) ++#define MISC_INT_ERROR BIT(1) ++#define MISC_INT_TIMER BIT(0) ++ ++#define PCI_INT_CORE BIT(4) ++#define PCI_INT_DEV2 BIT(2) ++#define PCI_INT_DEV1 BIT(1) ++#define PCI_INT_DEV0 BIT(0) ++ ++#define RESET_MODULE_EXTERNAL BIT(28) ++#define RESET_MODULE_FULL_CHIP BIT(24) ++#define RESET_MODULE_AMBA2WMAC BIT(22) ++#define RESET_MODULE_CPU_NMI BIT(21) ++#define RESET_MODULE_CPU_COLD BIT(20) ++#define RESET_MODULE_DMA BIT(19) ++#define RESET_MODULE_SLIC BIT(18) ++#define RESET_MODULE_STEREO BIT(17) ++#define RESET_MODULE_DDR BIT(16) ++#define RESET_MODULE_GE1_MAC BIT(13) ++#define RESET_MODULE_GE1_PHY BIT(12) ++#define RESET_MODULE_USBSUS_OVERRIDE BIT(10) ++#define RESET_MODULE_GE0_MAC BIT(9) ++#define RESET_MODULE_GE0_PHY BIT(8) ++#define RESET_MODULE_USB_OHCI_DLL BIT(6) ++#define RESET_MODULE_USB_HOST BIT(5) ++#define RESET_MODULE_USB_PHY BIT(4) ++#define RESET_MODULE_USB_OHCI_DLL_7240 BIT(3) ++#define RESET_MODULE_PCI_BUS BIT(1) ++#define RESET_MODULE_PCI_CORE BIT(0) ++ ++#define AR724X_RESET_GE1_MDIO BIT(23) ++#define AR724X_RESET_GE0_MDIO BIT(22) ++#define AR724X_RESET_PCIE_PHY_SERIAL BIT(10) ++#define AR724X_RESET_PCIE_PHY BIT(7) ++#define AR724X_RESET_PCIE BIT(6) ++ ++#define REV_ID_MAJOR_MASK 0xfff0 ++#define REV_ID_MAJOR_AR71XX 0x00a0 ++#define REV_ID_MAJOR_AR913X 0x00b0 ++#define REV_ID_MAJOR_AR7240 0x00c0 ++#define REV_ID_MAJOR_AR7241 0x0100 ++#define REV_ID_MAJOR_AR7242 0x1100 ++ ++#define AR71XX_REV_ID_MINOR_MASK 0x3 ++#define AR71XX_REV_ID_MINOR_AR7130 0x0 ++#define AR71XX_REV_ID_MINOR_AR7141 0x1 ++#define AR71XX_REV_ID_MINOR_AR7161 0x2 ++#define AR71XX_REV_ID_REVISION_MASK 0x3 ++#define AR71XX_REV_ID_REVISION_SHIFT 2 ++ ++#define AR91XX_REV_ID_MINOR_MASK 0x3 ++#define AR91XX_REV_ID_MINOR_AR9130 0x0 ++#define AR91XX_REV_ID_MINOR_AR9132 0x1 ++#define AR91XX_REV_ID_REVISION_MASK 0x3 ++#define AR91XX_REV_ID_REVISION_SHIFT 2 ++ ++#define AR724X_REV_ID_REVISION_MASK 0x3 ++ ++extern void __iomem *ar71xx_reset_base; ++ ++static inline void ar71xx_reset_wr(unsigned reg, u32 val) ++{ ++ __raw_writel(val, ar71xx_reset_base + reg); ++} ++ ++static inline u32 ar71xx_reset_rr(unsigned reg) ++{ ++ return __raw_readl(ar71xx_reset_base + reg); ++} ++ ++void ar71xx_device_stop(u32 mask); ++void ar71xx_device_start(u32 mask); ++int ar71xx_device_stopped(u32 mask); ++ ++/* ++ * SPI block ++ */ ++#define SPI_REG_FS 0x00 /* Function Select */ ++#define SPI_REG_CTRL 0x04 /* SPI Control */ ++#define SPI_REG_IOC 0x08 /* SPI I/O Control */ ++#define SPI_REG_RDS 0x0c /* Read Data Shift */ ++ ++#define SPI_FS_GPIO BIT(0) /* Enable GPIO mode */ ++ ++#define SPI_CTRL_RD BIT(6) /* Remap Disable */ ++#define SPI_CTRL_DIV_MASK 0x3f ++ ++#define SPI_IOC_DO BIT(0) /* Data Out pin */ ++#define SPI_IOC_CLK BIT(8) /* CLK pin */ ++#define SPI_IOC_CS(n) BIT(16 + (n)) ++#define SPI_IOC_CS0 SPI_IOC_CS(0) ++#define SPI_IOC_CS1 SPI_IOC_CS(1) ++#define SPI_IOC_CS2 SPI_IOC_CS(2) ++#define SPI_IOC_CS_ALL (SPI_IOC_CS0 | SPI_IOC_CS1 | SPI_IOC_CS2) ++ ++void ar71xx_flash_acquire(void); ++void ar71xx_flash_release(void); ++ ++/* ++ * MII_CTRL block ++ */ ++#define MII_REG_MII0_CTRL 0x00 ++#define MII_REG_MII1_CTRL 0x04 ++ ++#define MII0_CTRL_IF_GMII 0 ++#define MII0_CTRL_IF_MII 1 ++#define MII0_CTRL_IF_RGMII 2 ++#define MII0_CTRL_IF_RMII 3 ++ ++#define MII1_CTRL_IF_RGMII 0 ++#define MII1_CTRL_IF_RMII 1 ++ ++#endif /* __ASSEMBLER__ */ ++ ++#endif /* __ASM_MACH_AR71XX_H */ +diff -Nur linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/ar91xx_flash.h linux-2.6.39/arch/mips/include/asm/mach-ar71xx/ar91xx_flash.h +--- linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/ar91xx_flash.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/include/asm/mach-ar71xx/ar91xx_flash.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,26 @@ ++/* ++ * AR91xx parallel flash driver platform data definitions ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef __AR91XX_FLASH_H ++#define __AR91XX_FLASH_H ++ ++struct mtd_partition; ++ ++struct ar91xx_flash_platform_data { ++ unsigned int width; ++ u8 is_shared:1; ++#ifdef CONFIG_MTD_PARTITIONS ++ unsigned int nr_parts; ++ struct mtd_partition *parts; ++#endif ++}; ++ ++#endif /* __AR91XX_FLASH_H */ +diff -Nur linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/cpu-feature-overrides.h linux-2.6.39/arch/mips/include/asm/mach-ar71xx/cpu-feature-overrides.h +--- linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/cpu-feature-overrides.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/include/asm/mach-ar71xx/cpu-feature-overrides.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,56 @@ ++/* ++ * Atheros AR71xx specific CPU feature overrides ++ * ++ * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This file was derived from: include/asm-mips/cpu-features.h ++ * Copyright (C) 2003, 2004 Ralf Baechle ++ * Copyright (C) 2004 Maciej W. Rozycki ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++#ifndef __ASM_MACH_AR71XX_CPU_FEATURE_OVERRIDES_H ++#define __ASM_MACH_AR71XX_CPU_FEATURE_OVERRIDES_H ++ ++#define cpu_has_tlb 1 ++#define cpu_has_4kex 1 ++#define cpu_has_3k_cache 0 ++#define cpu_has_4k_cache 1 ++#define cpu_has_tx39_cache 0 ++#define cpu_has_sb1_cache 0 ++#define cpu_has_fpu 0 ++#define cpu_has_32fpr 0 ++#define cpu_has_counter 1 ++#define cpu_has_watch 1 ++#define cpu_has_divec 1 ++ ++#define cpu_has_prefetch 1 ++#define cpu_has_ejtag 1 ++#define cpu_has_llsc 1 ++ ++#define cpu_has_mips16 1 ++#define cpu_has_mdmx 0 ++#define cpu_has_mips3d 0 ++#define cpu_has_smartmips 0 ++ ++#define cpu_has_mips32r1 1 ++#define cpu_has_mips32r2 1 ++#define cpu_has_mips64r1 0 ++#define cpu_has_mips64r2 0 ++ ++#define cpu_has_dsp 0 ++#define cpu_has_mipsmt 0 ++ ++#define cpu_has_64bits 0 ++#define cpu_has_64bit_zero_reg 0 ++#define cpu_has_64bit_gp_regs 0 ++#define cpu_has_64bit_addresses 0 ++ ++#define cpu_dcache_line_size() 32 ++#define cpu_icache_line_size() 32 ++ ++#endif /* __ASM_MACH_AR71XX_CPU_FEATURE_OVERRIDES_H */ +diff -Nur linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/gpio.h linux-2.6.39/arch/mips/include/asm/mach-ar71xx/gpio.h +--- linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/gpio.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/include/asm/mach-ar71xx/gpio.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,53 @@ ++/* ++ * Atheros AR71xx GPIO API definitions ++ * ++ * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++ ++#ifndef __ASM_MACH_AR71XX_GPIO_H ++#define __ASM_MACH_AR71XX_GPIO_H ++ ++#define ARCH_NR_GPIOS 64 ++#include <asm-generic/gpio.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++extern unsigned long ar71xx_gpio_count; ++extern void __ar71xx_gpio_set_value(unsigned gpio, int value); ++extern int __ar71xx_gpio_get_value(unsigned gpio); ++ ++static inline int gpio_to_irq(unsigned gpio) ++{ ++ return AR71XX_GPIO_IRQ(gpio); ++} ++ ++static inline int irq_to_gpio(unsigned irq) ++{ ++ return irq - AR71XX_GPIO_IRQ_BASE; ++} ++ ++static inline int gpio_get_value(unsigned gpio) ++{ ++ if (gpio < ar71xx_gpio_count) ++ return __ar71xx_gpio_get_value(gpio); ++ ++ return __gpio_get_value(gpio); ++} ++ ++static inline void gpio_set_value(unsigned gpio, int value) ++{ ++ if (gpio < ar71xx_gpio_count) ++ __ar71xx_gpio_set_value(gpio, value); ++ else ++ __gpio_set_value(gpio, value); ++} ++ ++#define gpio_cansleep __gpio_cansleep ++ ++#endif /* __ASM_MACH_AR71XX_GPIO_H */ +diff -Nur linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/irq.h linux-2.6.39/arch/mips/include/asm/mach-ar71xx/irq.h +--- linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/irq.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/include/asm/mach-ar71xx/irq.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,17 @@ ++/* ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++#ifndef __ASM_MACH_AR71XX_IRQ_H ++#define __ASM_MACH_AR71XX_IRQ_H ++ ++#define MIPS_CPU_IRQ_BASE 0 ++#define NR_IRQS 56 ++ ++#include_next <irq.h> ++ ++#endif /* __ASM_MACH_AR71XX_IRQ_H */ +diff -Nur linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/kernel-entry-init.h linux-2.6.39/arch/mips/include/asm/mach-ar71xx/kernel-entry-init.h +--- linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/kernel-entry-init.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/include/asm/mach-ar71xx/kernel-entry-init.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,32 @@ ++/* ++ * Atheros AR71xx specific kernel entry setup ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++#ifndef __ASM_MACH_AR71XX_KERNEL_ENTRY_H ++#define __ASM_MACH_AR71XX_KERNEL_ENTRY_H ++ ++ /* ++ * Some bootloaders set the 'Kseg0 coherency algorithm' to ++ * 'Cacheable, noncoherent, write-through, no write allocate' ++ * and this cause performance issues. Let's go and change it to ++ * 'Cacheable, noncoherent, write-back, write allocate' ++ */ ++ .macro kernel_entry_setup ++ mfc0 t0, CP0_CONFIG ++ li t1, ~CONF_CM_CMASK ++ and t0, t1 ++ ori t0, CONF_CM_CACHABLE_NONCOHERENT ++ mtc0 t0, CP0_CONFIG ++ nop ++ .endm ++ ++ .macro smp_slave_setup ++ .endm ++ ++#endif /* __ASM_MACH_AR71XX_KERNEL_ENTRY_H */ +diff -Nur linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/mach-rb750.h linux-2.6.39/arch/mips/include/asm/mach-ar71xx/mach-rb750.h +--- linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/mach-rb750.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/include/asm/mach-ar71xx/mach-rb750.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,66 @@ ++/* ++ * MikroTik RouterBOARD 750 definitions ++ * ++ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++#ifndef _MACH_RB750_H ++#define _MACH_RB750_H ++ ++#include <linux/bitops.h> ++ ++#define RB750_GPIO_LVC573_LE 0 /* Latch enable on LVC573 */ ++#define RB750_GPIO_NAND_IO0 1 /* NAND I/O 0 */ ++#define RB750_GPIO_NAND_IO1 2 /* NAND I/O 1 */ ++#define RB750_GPIO_NAND_IO2 3 /* NAND I/O 2 */ ++#define RB750_GPIO_NAND_IO3 4 /* NAND I/O 3 */ ++#define RB750_GPIO_NAND_IO4 5 /* NAND I/O 4 */ ++#define RB750_GPIO_NAND_IO5 6 /* NAND I/O 5 */ ++#define RB750_GPIO_NAND_IO6 7 /* NAND I/O 6 */ ++#define RB750_GPIO_NAND_IO7 8 /* NAND I/O 7 */ ++#define RB750_GPIO_NAND_NCE 11 /* NAND Chip Enable (active low) */ ++#define RB750_GPIO_NAND_RDY 12 /* NAND Ready */ ++#define RB750_GPIO_NAND_CLE 14 /* NAND Command Latch Enable */ ++#define RB750_GPIO_NAND_ALE 15 /* NAND Address Latch Enable */ ++#define RB750_GPIO_NAND_NRE 16 /* NAND Read Enable (active low) */ ++#define RB750_GPIO_NAND_NWE 17 /* NAND Write Enable (active low) */ ++ ++#define RB750_GPIO_BTN_RESET 1 ++#define RB750_GPIO_SPI_CS0 2 ++#define RB750_GPIO_LED_ACT 12 ++#define RB750_GPIO_LED_PORT1 13 ++#define RB750_GPIO_LED_PORT2 14 ++#define RB750_GPIO_LED_PORT3 15 ++#define RB750_GPIO_LED_PORT4 16 ++#define RB750_GPIO_LED_PORT5 17 ++ ++#define RB750_LED_ACT BIT(RB750_GPIO_LED_ACT) ++#define RB750_LED_PORT1 BIT(RB750_GPIO_LED_PORT1) ++#define RB750_LED_PORT2 BIT(RB750_GPIO_LED_PORT2) ++#define RB750_LED_PORT3 BIT(RB750_GPIO_LED_PORT3) ++#define RB750_LED_PORT4 BIT(RB750_GPIO_LED_PORT4) ++#define RB750_LED_PORT5 BIT(RB750_GPIO_LED_PORT5) ++ ++#define RB750_LVC573_LE BIT(RB750_GPIO_LVC573_LE) ++ ++#define RB750_LED_BITS (RB750_LED_PORT1 | RB750_LED_PORT2 | RB750_LED_PORT3 | \ ++ RB750_LED_PORT4 | RB750_LED_PORT5 | RB750_LED_ACT) ++ ++struct rb750_led_data { ++ char *name; ++ char *default_trigger; ++ u32 mask; ++ int active_low; ++}; ++ ++struct rb750_led_platform_data { ++ int num_leds; ++ struct rb750_led_data *leds; ++}; ++ ++int rb750_latch_change(u32 mask_clr, u32 mask_set); ++ ++#endif /* _MACH_RB750_H */ +\ No newline at end of file +diff -Nur linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/mangle-port.h linux-2.6.39/arch/mips/include/asm/mach-ar71xx/mangle-port.h +--- linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/mangle-port.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/include/asm/mach-ar71xx/mangle-port.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This file was derived from: inlude/asm-mips/mach-generic/mangle-port.h ++ * Copyright (C) 2003, 2004 Ralf Baechle ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef __ASM_MACH_AR71XX_MANGLE_PORT_H ++#define __ASM_MACH_AR71XX_MANGLE_PORT_H ++ ++#define __swizzle_addr_b(port) ((port) ^ 3) ++#define __swizzle_addr_w(port) ((port) ^ 2) ++#define __swizzle_addr_l(port) (port) ++#define __swizzle_addr_q(port) (port) ++ ++#if defined(CONFIG_SWAP_IO_SPACE) ++ ++# define ioswabb(a, x) (x) ++# define __mem_ioswabb(a, x) (x) ++# define ioswabw(a, x) le16_to_cpu(x) ++# define __mem_ioswabw(a, x) (x) ++# define ioswabl(a, x) le32_to_cpu(x) ++# define __mem_ioswabl(a, x) (x) ++# define ioswabq(a, x) le64_to_cpu(x) ++# define __mem_ioswabq(a, x) (x) ++ ++#else ++ ++# define ioswabb(a, x) (x) ++# define __mem_ioswabb(a, x) (x) ++# define ioswabw(a, x) (x) ++# define __mem_ioswabw(a, x) cpu_to_le16(x) ++# define ioswabl(a, x) (x) ++# define __mem_ioswabl(a, x) cpu_to_le32(x) ++# define ioswabq(a, x) (x) ++# define __mem_ioswabq(a, x) cpu_to_le64(x) ++ ++#endif ++ ++#endif /* __ASM_MACH_AR71XX_MANGLE_PORT_H */ +diff -Nur linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/pci.h linux-2.6.39/arch/mips/include/asm/mach-ar71xx/pci.h +--- linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/pci.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/include/asm/mach-ar71xx/pci.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,39 @@ ++/* ++ * Atheros AR71xx SoC specific PCI definitions ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef __ASM_MACH_AR71XX_PCI_H ++#define __ASM_MACH_AR71XX_PCI_H ++ ++struct pci_dev; ++ ++struct ar71xx_pci_irq { ++ int irq; ++ u8 slot; ++ u8 pin; ++}; ++ ++extern int (*ar71xx_pci_plat_dev_init)(struct pci_dev *dev); ++extern unsigned ar71xx_pci_nr_irqs __initdata; ++extern struct ar71xx_pci_irq *ar71xx_pci_irq_map __initdata; ++ ++int ar71xx_pcibios_map_irq(const struct pci_dev *dev, ++ uint8_t slot, uint8_t pin) __init; ++int ar71xx_pcibios_init(void) __init; ++ ++int ar71xx_pci_be_handler(int is_fixup); ++ ++int ar724x_pcibios_map_irq(const struct pci_dev *dev, ++ uint8_t slot, uint8_t pin) __init; ++int ar724x_pcibios_init(void) __init; ++ ++int ar71xx_pci_init(unsigned nr_irqs, struct ar71xx_pci_irq *map) __init; ++ ++#endif /* __ASM_MACH_AR71XX_PCI_H */ +diff -Nur linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/platform.h linux-2.6.39/arch/mips/include/asm/mach-ar71xx/platform.h +--- linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/platform.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/include/asm/mach-ar71xx/platform.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,61 @@ ++/* ++ * Atheros AR71xx SoC specific platform data definitions ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef __ASM_MACH_AR71XX_PLATFORM_H ++#define __ASM_MACH_AR71XX_PLATFORM_H ++ ++#include <linux/if_ether.h> ++#include <linux/skbuff.h> ++#include <linux/phy.h> ++#include <linux/spi/spi.h> ++ ++struct ag71xx_platform_data { ++ phy_interface_t phy_if_mode; ++ u32 phy_mask; ++ int speed; ++ int duplex; ++ u32 reset_bit; ++ u32 mii_if; ++ u8 mac_addr[ETH_ALEN]; ++ struct device *mii_bus_dev; ++ ++ u8 has_gbit:1; ++ u8 is_ar91xx:1; ++ u8 is_ar724x:1; ++ u8 has_ar8216:1; ++ ++ void (* ddr_flush)(void); ++ void (* set_pll)(int speed); ++ ++ u32 fifo_cfg1; ++ u32 fifo_cfg2; ++ u32 fifo_cfg3; ++}; ++ ++struct ag71xx_mdio_platform_data { ++ u32 phy_mask; ++ int is_ar7240; ++}; ++ ++struct ar71xx_ehci_platform_data { ++ u8 is_ar91xx; ++}; ++ ++struct ar71xx_spi_platform_data { ++ unsigned bus_num; ++ unsigned num_chipselect; ++ u32 (*get_ioc_base)(u8 chip_select, int cs_high, int is_on); ++}; ++ ++#define AR71XX_SPI_CS_INACTIVE 0 ++#define AR71XX_SPI_CS_ACTIVE 1 ++ ++#endif /* __ASM_MACH_AR71XX_PLATFORM_H */ +diff -Nur linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/war.h linux-2.6.39/arch/mips/include/asm/mach-ar71xx/war.h +--- linux-2.6.39.orig/arch/mips/include/asm/mach-ar71xx/war.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/include/asm/mach-ar71xx/war.h 2011-05-27 14:36:51.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_MACH_AR71XX_WAR_H ++#define __ASM_MACH_AR71XX_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_MACH_AR71XX_WAR_H */ +diff -Nur linux-2.6.39.orig/arch/mips/include/asm/time.h linux-2.6.39/arch/mips/include/asm/time.h +--- linux-2.6.39.orig/arch/mips/include/asm/time.h 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/arch/mips/include/asm/time.h 2011-05-27 14:36:51.000000000 +0200 +@@ -52,6 +52,7 @@ + */ + #ifdef CONFIG_CEVT_R4K_LIB + extern unsigned int __weak get_c0_compare_int(void); ++extern unsigned int __weak get_c0_compare_irq(void); + extern int r4k_clockevent_init(void); + #endif + +diff -Nur linux-2.6.39.orig/arch/mips/kernel/Makefile linux-2.6.39/arch/mips/kernel/Makefile +--- linux-2.6.39.orig/arch/mips/kernel/Makefile 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/arch/mips/kernel/Makefile 2011-05-27 14:36:51.000000000 +0200 +@@ -94,6 +94,7 @@ + + obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o + obj-$(CONFIG_EARLY_PRINTK) += early_printk.o ++obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o + obj-$(CONFIG_SPINLOCK_TEST) += spinlock_test.o + obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o + +diff -Nur linux-2.6.39.orig/arch/mips/kernel/traps.c linux-2.6.39/arch/mips/kernel/traps.c +--- linux-2.6.39.orig/arch/mips/kernel/traps.c 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/arch/mips/kernel/traps.c 2011-05-27 14:36:51.000000000 +0200 +@@ -46,6 +46,7 @@ + #include <asm/ptrace.h> + #include <asm/sections.h> + #include <asm/system.h> ++#include <asm/time.h> + #include <asm/tlbdebug.h> + #include <asm/traps.h> + #include <asm/uaccess.h> +@@ -1576,6 +1577,8 @@ + if (cpu_has_mips_r2) { + cp0_compare_irq_shift = CAUSEB_TI - CAUSEB_IP; + cp0_compare_irq = (read_c0_intctl() >> INTCTLB_IPTI) & 7; ++ if (get_c0_compare_irq) ++ cp0_compare_irq = get_c0_compare_irq(); + cp0_perfcount_irq = (read_c0_intctl() >> INTCTLB_IPPCI) & 7; + if (cp0_perfcount_irq == cp0_compare_irq) + cp0_perfcount_irq = -1; +diff -Nur linux-2.6.39.orig/arch/mips/pci/Makefile linux-2.6.39/arch/mips/pci/Makefile +--- linux-2.6.39.orig/arch/mips/pci/Makefile 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/arch/mips/pci/Makefile 2011-05-27 14:36:51.000000000 +0200 +@@ -18,6 +18,7 @@ + obj-$(CONFIG_BCM47XX) += pci-bcm47xx.o + obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \ + ops-bcm63xx.o ++obj-$(CONFIG_ATHEROS_AR71XX) += pci-ar71xx.o pci-ar724x.o + + # + # These are still pretty much in the old state, watch, go blind. +diff -Nur linux-2.6.39.orig/arch/mips/pci/pci-ar71xx.c linux-2.6.39/arch/mips/pci/pci-ar71xx.c +--- linux-2.6.39.orig/arch/mips/pci/pci-ar71xx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/pci/pci-ar71xx.c 2011-06-01 14:02:22.000000000 +0200 +@@ -0,0 +1,408 @@ ++/* ++ * Atheros AR71xx PCI host controller driver ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/resource.h> ++#include <linux/types.h> ++#include <linux/delay.h> ++#include <linux/bitops.h> ++#include <linux/pci.h> ++#include <linux/pci_regs.h> ++#include <linux/interrupt.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/pci.h> ++ ++#undef DEBUG ++#ifdef DEBUG ++#define DBG(fmt, args...) printk(KERN_DEBUG fmt, ## args) ++#else ++#define DBG(fmt, args...) ++#endif ++ ++#define AR71XX_PCI_DELAY 100 /* msecs */ ++ ++#if 0 ++#define PCI_IDSEL_BASE PCI_IDSEL_ADL_START ++#else ++#define PCI_IDSEL_BASE 0 ++#endif ++ ++static void __iomem *ar71xx_pcicfg_base; ++static DEFINE_SPINLOCK(ar71xx_pci_lock); ++static int ar71xx_pci_fixup_enable; ++ ++static inline void ar71xx_pci_delay(void) ++{ ++ mdelay(AR71XX_PCI_DELAY); ++} ++ ++/* Byte lane enable bits */ ++static u8 ble_table[4][4] = { ++ {0x0, 0xf, 0xf, 0xf}, ++ {0xe, 0xd, 0xb, 0x7}, ++ {0xc, 0xf, 0x3, 0xf}, ++ {0xf, 0xf, 0xf, 0xf}, ++}; ++ ++static inline u32 ar71xx_pci_get_ble(int where, int size, int local) ++{ ++ u32 t; ++ ++ t = ble_table[size & 3][where & 3]; ++ BUG_ON(t == 0xf); ++ t <<= (local) ? 20 : 4; ++ return t; ++} ++ ++static inline u32 ar71xx_pci_bus_addr(struct pci_bus *bus, unsigned int devfn, ++ int where) ++{ ++ u32 ret; ++ ++ if (!bus->number) { ++ /* type 0 */ ++ ret = (1 << (PCI_IDSEL_BASE + PCI_SLOT(devfn))) ++ | (PCI_FUNC(devfn) << 8) | (where & ~3); ++ } else { ++ /* type 1 */ ++ ret = (bus->number << 16) | (PCI_SLOT(devfn) << 11) ++ | (PCI_FUNC(devfn) << 8) | (where & ~3) | 1; ++ } ++ ++ return ret; ++} ++ ++int ar71xx_pci_be_handler(int is_fixup) ++{ ++ void __iomem *base = ar71xx_pcicfg_base; ++ u32 pci_err; ++ u32 ahb_err; ++ ++ pci_err = __raw_readl(base + PCI_REG_PCI_ERR) & 3; ++ if (pci_err) { ++ if (!is_fixup) ++ printk(KERN_ALERT "PCI error %d at PCI addr 0x%x\n", ++ pci_err, ++ __raw_readl(base + PCI_REG_PCI_ERR_ADDR)); ++ ++ __raw_writel(pci_err, base + PCI_REG_PCI_ERR); ++ } ++ ++ ahb_err = __raw_readl(base + PCI_REG_AHB_ERR) & 1; ++ if (ahb_err) { ++ if (!is_fixup) ++ printk(KERN_ALERT "AHB error at AHB address 0x%x\n", ++ __raw_readl(base + PCI_REG_AHB_ERR_ADDR)); ++ ++ __raw_writel(ahb_err, base + PCI_REG_AHB_ERR); ++ } ++ ++ return ((ahb_err | pci_err) ? 1 : 0); ++} ++ ++static inline int ar71xx_pci_set_cfgaddr(struct pci_bus *bus, ++ unsigned int devfn, int where, int size, u32 cmd) ++{ ++ void __iomem *base = ar71xx_pcicfg_base; ++ u32 addr; ++ ++ addr = ar71xx_pci_bus_addr(bus, devfn, where); ++ ++ DBG("PCI: set cfgaddr: %02x:%02x.%01x/%02x:%01d, addr=%08x\n", ++ bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), ++ where, size, addr); ++ ++ __raw_writel(addr, base + PCI_REG_CFG_AD); ++ __raw_writel(cmd | ar71xx_pci_get_ble(where, size, 0), ++ base + PCI_REG_CFG_CBE); ++ ++ return ar71xx_pci_be_handler(1); ++} ++ ++static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 *value) ++{ ++ void __iomem *base = ar71xx_pcicfg_base; ++ static u32 mask[8] = {0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0}; ++ unsigned long flags; ++ u32 data; ++ int ret; ++ ++ ret = PCIBIOS_SUCCESSFUL; ++ ++ DBG("PCI: read config: %02x:%02x.%01x/%02x:%01d\n", bus->number, ++ PCI_SLOT(devfn), PCI_FUNC(devfn), where, size); ++ ++ spin_lock_irqsave(&ar71xx_pci_lock, flags); ++ ++ if (bus->number == 0 && devfn == 0) { ++ u32 t; ++ ++ t = PCI_CRP_CMD_READ | (where & ~3); ++ ++ __raw_writel(t, base + PCI_REG_CRP_AD_CBE); ++ data = __raw_readl(base + PCI_REG_CRP_RDDATA); ++ ++ DBG("PCI: rd local cfg, ad_cbe:%08x, data:%08x\n", t, data); ++ ++ } else { ++ int err; ++ ++ err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size, ++ PCI_CFG_CMD_READ); ++ ++ if (err == 0) { ++ data = __raw_readl(base + PCI_REG_CFG_RDDATA); ++ } else { ++ ret = PCIBIOS_DEVICE_NOT_FOUND; ++ data = ~0; ++ } ++ } ++ ++ spin_unlock_irqrestore(&ar71xx_pci_lock, flags); ++ ++ DBG("PCI: read config: data=%08x raw=%08x\n", ++ (data >> (8 * (where & 3))) & mask[size & 7], data); ++ ++ *value = (data >> (8 * (where & 3))) & mask[size & 7]; ++ ++ return ret; ++} ++ ++static int ar71xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 value) ++{ ++ void __iomem *base = ar71xx_pcicfg_base; ++ unsigned long flags; ++ int ret; ++ ++ DBG("PCI: write config: %02x:%02x.%01x/%02x:%01d value=%08x\n", ++ bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), ++ where, size, value); ++ ++ value = value << (8 * (where & 3)); ++ ret = PCIBIOS_SUCCESSFUL; ++ ++ spin_lock_irqsave(&ar71xx_pci_lock, flags); ++ if (bus->number == 0 && devfn == 0) { ++ u32 t; ++ ++ t = PCI_CRP_CMD_WRITE | (where & ~3); ++ t |= ar71xx_pci_get_ble(where, size, 1); ++ ++ DBG("PCI: wr local cfg, ad_cbe:%08x, value:%08x\n", t, value); ++ ++ __raw_writel(t, base + PCI_REG_CRP_AD_CBE); ++ __raw_writel(value, base + PCI_REG_CRP_WRDATA); ++ } else { ++ int err; ++ ++ err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size, ++ PCI_CFG_CMD_WRITE); ++ ++ if (err == 0) ++ __raw_writel(value, base + PCI_REG_CFG_WRDATA); ++ else ++ ret = PCIBIOS_DEVICE_NOT_FOUND; ++ } ++ spin_unlock_irqrestore(&ar71xx_pci_lock, flags); ++ ++ return ret; ++} ++ ++static void ar71xx_pci_fixup(struct pci_dev *dev) ++{ ++ u32 t; ++ ++ if (!ar71xx_pci_fixup_enable) ++ return; ++ ++ if (dev->bus->number != 0 || dev->devfn != 0) ++ return; ++ ++ DBG("PCI: fixup host controller %s (%04x:%04x)\n", pci_name(dev), ++ dev->vendor, dev->device); ++ ++ /* setup COMMAND register */ ++ t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE ++ | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK; ++ ++ pci_write_config_word(dev, PCI_COMMAND, t); ++} ++DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ar71xx_pci_fixup); ++ ++int __init ar71xx_pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, ++ uint8_t pin) ++{ ++ int irq = -1; ++ int i; ++ ++ slot -= PCI_IDSEL_ADL_START - PCI_IDSEL_BASE; ++ ++ for (i = 0; i < ar71xx_pci_nr_irqs; i++) { ++ struct ar71xx_pci_irq *entry; ++ ++ entry = &ar71xx_pci_irq_map[i]; ++ if (entry->slot == slot && entry->pin == pin) { ++ irq = entry->irq; ++ break; ++ } ++ } ++ ++ if (irq < 0) { ++ printk(KERN_ALERT "PCI: no irq found for pin%u@%s\n", ++ pin, pci_name((struct pci_dev *)dev)); ++ } else { ++ printk(KERN_INFO "PCI: mapping irq %d to pin%u@%s\n", ++ irq, pin, pci_name((struct pci_dev *)dev)); ++ } ++ ++ return irq; ++} ++ ++static struct pci_ops ar71xx_pci_ops = { ++ .read = ar71xx_pci_read_config, ++ .write = ar71xx_pci_write_config, ++}; ++ ++static struct resource ar71xx_pci_io_resource = { ++ .name = "PCI IO space", ++ .start = 0, ++ .end = 0, ++ .flags = IORESOURCE_IO, ++}; ++ ++static struct resource ar71xx_pci_mem_resource = { ++ .name = "PCI memory space", ++ .start = AR71XX_PCI_MEM_BASE, ++ .end = AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1, ++ .flags = IORESOURCE_MEM ++}; ++ ++static struct pci_controller ar71xx_pci_controller = { ++ .pci_ops = &ar71xx_pci_ops, ++ .mem_resource = &ar71xx_pci_mem_resource, ++ .io_resource = &ar71xx_pci_io_resource, ++}; ++ ++static void ar71xx_pci_irq_handler(unsigned int irq, struct irq_desc *desc) ++{ ++ void __iomem *base = ar71xx_reset_base; ++ u32 pending; ++ ++ pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) & ++ __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); ++ ++ if (pending & PCI_INT_DEV0) ++ generic_handle_irq(AR71XX_PCI_IRQ_DEV0); ++ ++ else if (pending & PCI_INT_DEV1) ++ generic_handle_irq(AR71XX_PCI_IRQ_DEV1); ++ ++ else if (pending & PCI_INT_DEV2) ++ generic_handle_irq(AR71XX_PCI_IRQ_DEV2); ++ ++ else if (pending & PCI_INT_CORE) ++ generic_handle_irq(AR71XX_PCI_IRQ_CORE); ++ ++ else ++ spurious_interrupt(); ++} ++ ++static void ar71xx_pci_irq_unmask(struct irq_data *d) ++{ ++ void __iomem *base = ar71xx_reset_base; ++ u32 t; ++ ++ d->irq -= AR71XX_PCI_IRQ_BASE; ++ ++ t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); ++ __raw_writel(t | (1 << d->irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); ++ ++ /* flush write */ ++ (void) __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); ++} ++ ++static void ar71xx_pci_irq_mask(struct irq_data *d) ++{ ++ void __iomem *base = ar71xx_reset_base; ++ u32 t; ++ ++ d->irq -= AR71XX_PCI_IRQ_BASE; ++ ++ t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); ++ __raw_writel(t & ~(1 << d->irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); ++ ++ /* flush write */ ++ (void) __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); ++} ++ ++static struct irq_chip ar71xx_pci_irq_chip = { ++ .name = "AR71XX PCI ", ++ .irq_mask = ar71xx_pci_irq_mask, ++ .irq_unmask = ar71xx_pci_irq_unmask, ++ .irq_mask_ack = ar71xx_pci_irq_mask, ++}; ++ ++static void __init ar71xx_pci_irq_init(void) ++{ ++ void __iomem *base = ar71xx_reset_base; ++ int i; ++ ++ __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE); ++ __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS); ++ ++ for (i = AR71XX_PCI_IRQ_BASE; ++ i < AR71XX_PCI_IRQ_BASE + AR71XX_PCI_IRQ_COUNT; i++) { ++ irq_set_chip_and_handler(i, &ar71xx_pci_irq_chip, ++ handle_level_irq); ++ } ++ ++ irq_set_chained_handler(AR71XX_CPU_IRQ_IP2, ar71xx_pci_irq_handler); ++} ++ ++int __init ar71xx_pcibios_init(void) ++{ ++ void __iomem *ddr_base = ar71xx_ddr_base; ++ ++ ar71xx_device_stop(RESET_MODULE_PCI_BUS | RESET_MODULE_PCI_CORE); ++ ar71xx_pci_delay(); ++ ++ ar71xx_device_start(RESET_MODULE_PCI_BUS | RESET_MODULE_PCI_CORE); ++ ar71xx_pci_delay(); ++ ++ ar71xx_pcicfg_base = ioremap_nocache(AR71XX_PCI_CFG_BASE, ++ AR71XX_PCI_CFG_SIZE); ++ if (ar71xx_pcicfg_base == NULL) ++ return -ENOMEM; ++ ++ __raw_writel(PCI_WIN0_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN0); ++ __raw_writel(PCI_WIN1_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN1); ++ __raw_writel(PCI_WIN2_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN2); ++ __raw_writel(PCI_WIN3_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN3); ++ __raw_writel(PCI_WIN4_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN4); ++ __raw_writel(PCI_WIN5_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN5); ++ __raw_writel(PCI_WIN6_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN6); ++ __raw_writel(PCI_WIN7_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN7); ++ ++ ar71xx_pci_delay(); ++ ++ /* clear bus errors */ ++ (void)ar71xx_pci_be_handler(1); ++ ++ ar71xx_pci_fixup_enable = 1; ++ ar71xx_pci_irq_init(); ++ register_pci_controller(&ar71xx_pci_controller); ++ ++ return 0; ++} +diff -Nur linux-2.6.39.orig/arch/mips/pci/pci-ar724x.c linux-2.6.39/arch/mips/pci/pci-ar724x.c +--- linux-2.6.39.orig/arch/mips/pci/pci-ar724x.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/arch/mips/pci/pci-ar724x.c 2011-06-01 14:02:22.000000000 +0200 +@@ -0,0 +1,394 @@ ++/* ++ * Atheros AR724x PCI host controller driver ++ * ++ * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/resource.h> ++#include <linux/types.h> ++#include <linux/delay.h> ++#include <linux/bitops.h> ++#include <linux/pci.h> ++#include <linux/pci_regs.h> ++#include <linux/interrupt.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/pci.h> ++ ++#undef DEBUG ++#ifdef DEBUG ++#define DBG(fmt, args...) printk(KERN_INFO fmt, ## args) ++#else ++#define DBG(fmt, args...) ++#endif ++ ++static void __iomem *ar724x_pci_localcfg_base; ++static void __iomem *ar724x_pci_devcfg_base; ++static void __iomem *ar724x_pci_ctrl_base; ++static int ar724x_pci_fixup_enable; ++ ++static DEFINE_SPINLOCK(ar724x_pci_lock); ++ ++static void ar724x_pci_read(void __iomem *base, int where, int size, u32 *value) ++{ ++ unsigned long flags; ++ u32 data; ++ ++ spin_lock_irqsave(&ar724x_pci_lock, flags); ++ data = __raw_readl(base + (where & ~3)); ++ ++ switch (size) { ++ case 1: ++ if (where & 1) ++ data >>= 8; ++ if (where & 2) ++ data >>= 16; ++ data &= 0xFF; ++ break; ++ case 2: ++ if (where & 2) ++ data >>= 16; ++ data &= 0xFFFF; ++ break; ++ } ++ ++ *value = data; ++ spin_unlock_irqrestore(&ar724x_pci_lock, flags); ++} ++ ++static void ar724x_pci_write(void __iomem *base, int where, int size, u32 value) ++{ ++ unsigned long flags; ++ u32 data; ++ int s; ++ ++ spin_lock_irqsave(&ar724x_pci_lock, flags); ++ data = __raw_readl(base + (where & ~3)); ++ ++ switch (size) { ++ case 1: ++ s = ((where & 3) << 3); ++ data &= ~(0xFF << s); ++ data |= ((value & 0xFF) << s); ++ break; ++ case 2: ++ s = ((where & 2) << 3); ++ data &= ~(0xFFFF << s); ++ data |= ((value & 0xFFFF) << s); ++ break; ++ case 4: ++ data = value; ++ break; ++ } ++ ++ __raw_writel(data, base + (where & ~3)); ++ /* flush write */ ++ (void)__raw_readl(base + (where & ~3)); ++ spin_unlock_irqrestore(&ar724x_pci_lock, flags); ++} ++ ++static int ar724x_pci_read_config(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 *value) ++{ ++ ++ if (bus->number != 0 || devfn != 0) ++ return PCIBIOS_DEVICE_NOT_FOUND; ++ ++ ar724x_pci_read(ar724x_pci_devcfg_base, where, size, value); ++ ++ DBG("PCI: read config: %02x:%02x.%01x/%02x:%01d, value=%08x\n", ++ bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), ++ where, size, *value); ++ ++ /* ++ * WAR for BAR issue - We are unable to access the PCI device space ++ * if we set the BAR with proper base address ++ */ ++ if ((where == 0x10) && (size == 4)) { ++ if (ar71xx_soc == AR71XX_SOC_AR7240) ++ ar724x_pci_write(ar724x_pci_devcfg_base, where, size, 0xffff); ++ else ++ ar724x_pci_write(ar724x_pci_devcfg_base, where, size, 0x1000ffff); ++ } ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static int ar724x_pci_write_config(struct pci_bus *bus, unsigned int devfn, ++ int where, int size, u32 value) ++{ ++ if (bus->number != 0 || devfn != 0) ++ return PCIBIOS_DEVICE_NOT_FOUND; ++ ++ DBG("PCI: write config: %02x:%02x.%01x/%02x:%01d, value=%08x\n", ++ bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), ++ where, size, value); ++ ++ ar724x_pci_write(ar724x_pci_devcfg_base, where, size, value); ++ ++ return PCIBIOS_SUCCESSFUL; ++} ++ ++static void ar724x_pci_fixup(struct pci_dev *dev) ++{ ++ u16 cmd; ++ ++ if (!ar724x_pci_fixup_enable) ++ return; ++ ++ if (dev->bus->number != 0 || dev->devfn != 0) ++ return; ++ ++ /* setup COMMAND register */ ++ pci_read_config_word(dev, PCI_COMMAND, &cmd); ++ cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | ++ PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | ++ PCI_COMMAND_FAST_BACK; ++ ++ pci_write_config_word(dev, PCI_COMMAND, cmd); ++} ++DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ar724x_pci_fixup); ++ ++int __init ar724x_pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, ++ uint8_t pin) ++{ ++ int irq = -1; ++ int i; ++ ++ for (i = 0; i < ar71xx_pci_nr_irqs; i++) { ++ struct ar71xx_pci_irq *entry; ++ entry = &ar71xx_pci_irq_map[i]; ++ ++ if (entry->slot == slot && entry->pin == pin) { ++ irq = entry->irq; ++ break; ++ } ++ } ++ ++ if (irq < 0) ++ printk(KERN_ALERT "PCI: no irq found for pin%u@%s\n", ++ pin, pci_name((struct pci_dev *)dev)); ++ else ++ printk(KERN_INFO "PCI: mapping irq %d to pin%u@%s\n", ++ irq, pin, pci_name((struct pci_dev *)dev)); ++ ++ return irq; ++} ++ ++static struct pci_ops ar724x_pci_ops = { ++ .read = ar724x_pci_read_config, ++ .write = ar724x_pci_write_config, ++}; ++ ++static struct resource ar724x_pci_io_resource = { ++ .name = "PCI IO space", ++ .start = 0, ++ .end = 0, ++ .flags = IORESOURCE_IO, ++}; ++ ++static struct resource ar724x_pci_mem_resource = { ++ .name = "PCI memory space", ++ .start = AR71XX_PCI_MEM_BASE, ++ .end = AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1, ++ .flags = IORESOURCE_MEM ++}; ++ ++static struct pci_controller ar724x_pci_controller = { ++ .pci_ops = &ar724x_pci_ops, ++ .mem_resource = &ar724x_pci_mem_resource, ++ .io_resource = &ar724x_pci_io_resource, ++}; ++ ++static void __init ar724x_pci_reset(void) ++{ ++ ar71xx_device_stop(AR724X_RESET_PCIE); ++ ar71xx_device_stop(AR724X_RESET_PCIE_PHY); ++ ar71xx_device_stop(AR724X_RESET_PCIE_PHY_SERIAL); ++ udelay(100); ++ ++ ar71xx_device_start(AR724X_RESET_PCIE_PHY_SERIAL); ++ udelay(100); ++ ar71xx_device_start(AR724X_RESET_PCIE_PHY); ++ ar71xx_device_start(AR724X_RESET_PCIE); ++} ++ ++static int __init ar724x_pci_setup(void) ++{ ++ void __iomem *base = ar724x_pci_ctrl_base; ++ u32 t; ++ ++ /* setup COMMAND register */ ++ t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | ++ PCI_COMMAND_PARITY|PCI_COMMAND_SERR|PCI_COMMAND_FAST_BACK; ++ ++ ar724x_pci_write(ar724x_pci_localcfg_base, PCI_COMMAND, 4, t); ++ ar724x_pci_write(ar724x_pci_localcfg_base, 0x20, 4, 0x1ff01000); ++ ar724x_pci_write(ar724x_pci_localcfg_base, 0x24, 4, 0x1ff01000); ++ ++ t = __raw_readl(base + AR724X_PCI_REG_RESET); ++ if (t != 0x7) { ++ udelay(100000); ++ __raw_writel(0, base + AR724X_PCI_REG_RESET); ++ udelay(100); ++ __raw_writel(4, base + AR724X_PCI_REG_RESET); ++ udelay(100000); ++ } ++ ++ if (ar71xx_soc == AR71XX_SOC_AR7240) ++ t = AR724X_PCI_APP_LTSSM_ENABLE; ++ else ++ t = 0x1ffc1; ++ __raw_writel(t, base + AR724X_PCI_REG_APP); ++ /* flush write */ ++ (void) __raw_readl(base + AR724X_PCI_REG_APP); ++ udelay(1000); ++ ++ t = __raw_readl(base + AR724X_PCI_REG_RESET); ++ if ((t & AR724X_PCI_RESET_LINK_UP) == 0x0) { ++ printk(KERN_WARNING "PCI: no PCIe module found\n"); ++ return -ENODEV; ++ } ++ ++ if (ar71xx_soc == AR71XX_SOC_AR7241 || ar71xx_soc == AR71XX_SOC_AR7242) { ++ t = __raw_readl(base + AR724X_PCI_REG_APP); ++ t |= BIT(16); ++ __raw_writel(t, base + AR724X_PCI_REG_APP); ++ } ++ ++ return 0; ++} ++ ++static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc) ++{ ++ void __iomem *base = ar724x_pci_ctrl_base; ++ u32 pending; ++ ++ pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) & ++ __raw_readl(base + AR724X_PCI_REG_INT_MASK); ++ ++ if (pending & AR724X_PCI_INT_DEV0) ++ generic_handle_irq(AR71XX_PCI_IRQ_DEV0); ++ ++ else ++ spurious_interrupt(); ++} ++ ++static void ar724x_pci_irq_unmask(struct irq_data *d) ++{ ++ void __iomem *base = ar724x_pci_ctrl_base; ++ u32 t; ++ ++ switch (d->irq) { ++ case AR71XX_PCI_IRQ_DEV0: ++ d->irq -= AR71XX_PCI_IRQ_BASE; ++ ++ t = __raw_readl(base + AR724X_PCI_REG_INT_MASK); ++ __raw_writel(t | AR724X_PCI_INT_DEV0, ++ base + AR724X_PCI_REG_INT_MASK); ++ /* flush write */ ++ (void) __raw_readl(base + AR724X_PCI_REG_INT_MASK); ++ } ++} ++ ++static void ar724x_pci_irq_mask(struct irq_data *d) ++{ ++ void __iomem *base = ar724x_pci_ctrl_base; ++ u32 t; ++ ++ switch (d->irq) { ++ case AR71XX_PCI_IRQ_DEV0: ++ d->irq -= AR71XX_PCI_IRQ_BASE; ++ ++ t = __raw_readl(base + AR724X_PCI_REG_INT_MASK); ++ __raw_writel(t & ~AR724X_PCI_INT_DEV0, ++ base + AR724X_PCI_REG_INT_MASK); ++ ++ /* flush write */ ++ (void) __raw_readl(base + AR724X_PCI_REG_INT_MASK); ++ ++ t = __raw_readl(base + AR724X_PCI_REG_INT_STATUS); ++ __raw_writel(t | AR724X_PCI_INT_DEV0, ++ base + AR724X_PCI_REG_INT_STATUS); ++ ++ /* flush write */ ++ (void) __raw_readl(base + AR724X_PCI_REG_INT_STATUS); ++ } ++} ++ ++static struct irq_chip ar724x_pci_irq_chip = { ++ .name = "AR724X PCI ", ++ .irq_mask = ar724x_pci_irq_mask, ++ .irq_unmask = ar724x_pci_irq_unmask, ++ .irq_mask_ack = ar724x_pci_irq_mask, ++}; ++ ++static void __init ar724x_pci_irq_init(void) ++{ ++ void __iomem *base = ar724x_pci_ctrl_base; ++ u32 t; ++ int i; ++ ++ t = ar71xx_reset_rr(AR724X_RESET_REG_RESET_MODULE); ++ if (t & (AR724X_RESET_PCIE | AR724X_RESET_PCIE_PHY | ++ AR724X_RESET_PCIE_PHY_SERIAL)) { ++ return; ++ } ++ ++ __raw_writel(0, base + AR724X_PCI_REG_INT_MASK); ++ __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS); ++ ++ for (i = AR71XX_PCI_IRQ_BASE; ++ i < AR71XX_PCI_IRQ_BASE + AR71XX_PCI_IRQ_COUNT; i++) { ++ irq_set_chip_and_handler(i, &ar724x_pci_irq_chip, ++ handle_level_irq); ++ } ++ ++ irq_set_chained_handler(AR71XX_CPU_IRQ_IP2, ar724x_pci_irq_handler); ++} ++ ++int __init ar724x_pcibios_init(void) ++{ ++ int ret = -ENOMEM; ++ ++ ar724x_pci_localcfg_base = ioremap_nocache(AR724X_PCI_CRP_BASE, ++ AR724X_PCI_CRP_SIZE); ++ if (ar724x_pci_localcfg_base == NULL) ++ goto err; ++ ++ ar724x_pci_devcfg_base = ioremap_nocache(AR724X_PCI_CFG_BASE, ++ AR724X_PCI_CFG_SIZE); ++ if (ar724x_pci_devcfg_base == NULL) ++ goto err_unmap_localcfg; ++ ++ ar724x_pci_ctrl_base = ioremap_nocache(AR724X_PCI_CTRL_BASE, ++ AR724X_PCI_CTRL_SIZE); ++ if (ar724x_pci_ctrl_base == NULL) ++ goto err_unmap_devcfg; ++ ++ ar724x_pci_reset(); ++ ret = ar724x_pci_setup(); ++ if (ret) ++ goto err_unmap_ctrl; ++ ++ ar724x_pci_fixup_enable = 1; ++ ar724x_pci_irq_init(); ++ register_pci_controller(&ar724x_pci_controller); ++ ++ return 0; ++ ++ err_unmap_ctrl: ++ iounmap(ar724x_pci_ctrl_base); ++ err_unmap_devcfg: ++ iounmap(ar724x_pci_devcfg_base); ++ err_unmap_localcfg: ++ iounmap(ar724x_pci_localcfg_base); ++ err: ++ return ret; ++} +diff -Nur linux-2.6.39.orig/drivers/char/Kconfig linux-2.6.39/drivers/char/Kconfig +--- linux-2.6.39.orig/drivers/char/Kconfig 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/char/Kconfig 2011-05-27 14:36:51.000000000 +0200 +@@ -511,6 +511,14 @@ + pc8736x_gpio drivers. If those drivers are built as + modules, this one will be too, named nsc_gpio + ++config GPIO_DEVICE ++ tristate "GPIO device support" ++ depends on GENERIC_GPIO ++ help ++ Say Y to enable Linux GPIO device support. This allows control of ++ GPIO pins using a character device ++ ++ + config RAW_DRIVER + tristate "RAW driver (/dev/raw/rawN)" + depends on BLOCK +diff -Nur linux-2.6.39.orig/drivers/char/Makefile linux-2.6.39/drivers/char/Makefile +--- linux-2.6.39.orig/drivers/char/Makefile 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/char/Makefile 2011-05-27 14:36:51.000000000 +0200 +@@ -47,6 +47,7 @@ + obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o + obj-$(CONFIG_PC8736x_GPIO) += pc8736x_gpio.o + obj-$(CONFIG_NSC_GPIO) += nsc_gpio.o ++obj-$(CONFIG_GPIO_DEVICE) += gpio_dev.o + obj-$(CONFIG_GPIO_TB0219) += tb0219.o + obj-$(CONFIG_TELCLOCK) += tlclk.o + +diff -Nur linux-2.6.39.orig/drivers/gpio/nxp_74hc153.c linux-2.6.39/drivers/gpio/nxp_74hc153.c +--- linux-2.6.39.orig/drivers/gpio/nxp_74hc153.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/gpio/nxp_74hc153.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,246 @@ ++/* ++ * NXP 74HC153 - Dual 4-input multiplexer GPIO driver ++ * ++ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/gpio.h> ++#include <linux/platform_device.h> ++#include <linux/nxp_74hc153.h> ++ ++#define NXP_74HC153_NUM_GPIOS 8 ++#define NXP_74HC153_S0_MASK 0x1 ++#define NXP_74HC153_S1_MASK 0x2 ++#define NXP_74HC153_BANK_MASK 0x4 ++ ++struct nxp_74hc153_chip { ++ struct device *parent; ++ struct gpio_chip gpio_chip; ++ struct mutex lock; ++}; ++ ++static struct nxp_74hc153_chip *gpio_to_nxp(struct gpio_chip *gc) ++{ ++ return container_of(gc, struct nxp_74hc153_chip, gpio_chip); ++} ++ ++static int nxp_74hc153_direction_input(struct gpio_chip *gc, unsigned offset) ++{ ++ return 0; ++} ++ ++static int nxp_74hc153_direction_output(struct gpio_chip *gc, ++ unsigned offset, int val) ++{ ++ return -EINVAL; ++} ++ ++static int nxp_74hc153_get_value(struct gpio_chip *gc, unsigned offset) ++{ ++ struct nxp_74hc153_chip *nxp; ++ struct nxp_74hc153_platform_data *pdata; ++ unsigned s0; ++ unsigned s1; ++ unsigned pin; ++ int ret; ++ ++ nxp = gpio_to_nxp(gc); ++ pdata = nxp->parent->platform_data; ++ ++ s0 = !!(offset & NXP_74HC153_S0_MASK); ++ s1 = !!(offset & NXP_74HC153_S1_MASK); ++ pin = (offset & NXP_74HC153_BANK_MASK) ? pdata->gpio_pin_2y ++ : pdata->gpio_pin_1y; ++ ++ mutex_lock(&nxp->lock); ++ gpio_set_value(pdata->gpio_pin_s0, s0); ++ gpio_set_value(pdata->gpio_pin_s1, s1); ++ ret = gpio_get_value(pin); ++ mutex_unlock(&nxp->lock); ++ ++ return ret; ++} ++ ++static void nxp_74hc153_set_value(struct gpio_chip *gc, ++ unsigned offset, int val) ++{ ++ /* not supported */ ++} ++ ++static int __devinit nxp_74hc153_probe(struct platform_device *pdev) ++{ ++ struct nxp_74hc153_platform_data *pdata; ++ struct nxp_74hc153_chip *nxp; ++ struct gpio_chip *gc; ++ int err; ++ ++ pdata = pdev->dev.platform_data; ++ if (pdata == NULL) { ++ dev_dbg(&pdev->dev, "no platform data specified\n"); ++ return -EINVAL; ++ } ++ ++ nxp = kzalloc(sizeof(struct nxp_74hc153_chip), GFP_KERNEL); ++ if (nxp == NULL) { ++ dev_err(&pdev->dev, "no memory for private data\n"); ++ return -ENOMEM; ++ } ++ ++ err = gpio_request(pdata->gpio_pin_s0, dev_name(&pdev->dev)); ++ if (err) { ++ dev_err(&pdev->dev, "unable to claim gpio %u, err=%d\n", ++ pdata->gpio_pin_s0, err); ++ goto err_free_nxp; ++ } ++ ++ err = gpio_request(pdata->gpio_pin_s1, dev_name(&pdev->dev)); ++ if (err) { ++ dev_err(&pdev->dev, "unable to claim gpio %u, err=%d\n", ++ pdata->gpio_pin_s1, err); ++ goto err_free_s0; ++ } ++ ++ err = gpio_request(pdata->gpio_pin_1y, dev_name(&pdev->dev)); ++ if (err) { ++ dev_err(&pdev->dev, "unable to claim gpio %u, err=%d\n", ++ pdata->gpio_pin_1y, err); ++ goto err_free_s1; ++ } ++ ++ err = gpio_request(pdata->gpio_pin_2y, dev_name(&pdev->dev)); ++ if (err) { ++ dev_err(&pdev->dev, "unable to claim gpio %u, err=%d\n", ++ pdata->gpio_pin_2y, err); ++ goto err_free_1y; ++ } ++ ++ err = gpio_direction_output(pdata->gpio_pin_s0, 0); ++ if (err) { ++ dev_err(&pdev->dev, ++ "unable to set direction of gpio %u, err=%d\n", ++ pdata->gpio_pin_s0, err); ++ goto err_free_2y; ++ } ++ ++ err = gpio_direction_output(pdata->gpio_pin_s1, 0); ++ if (err) { ++ dev_err(&pdev->dev, ++ "unable to set direction of gpio %u, err=%d\n", ++ pdata->gpio_pin_s1, err); ++ goto err_free_2y; ++ } ++ ++ err = gpio_direction_input(pdata->gpio_pin_1y); ++ if (err) { ++ dev_err(&pdev->dev, ++ "unable to set direction of gpio %u, err=%d\n", ++ pdata->gpio_pin_1y, err); ++ goto err_free_2y; ++ } ++ ++ err = gpio_direction_input(pdata->gpio_pin_2y); ++ if (err) { ++ dev_err(&pdev->dev, ++ "unable to set direction of gpio %u, err=%d\n", ++ pdata->gpio_pin_2y, err); ++ goto err_free_2y; ++ } ++ ++ nxp->parent = &pdev->dev; ++ mutex_init(&nxp->lock); ++ ++ gc = &nxp->gpio_chip; ++ ++ gc->direction_input = nxp_74hc153_direction_input; ++ gc->direction_output = nxp_74hc153_direction_output; ++ gc->get = nxp_74hc153_get_value; ++ gc->set = nxp_74hc153_set_value; ++ gc->can_sleep = 1; ++ ++ gc->base = pdata->gpio_base; ++ gc->ngpio = NXP_74HC153_NUM_GPIOS; ++ gc->label = dev_name(nxp->parent); ++ gc->dev = nxp->parent; ++ gc->owner = THIS_MODULE; ++ ++ err = gpiochip_add(&nxp->gpio_chip); ++ if (err) { ++ dev_err(&pdev->dev, "unable to add gpio chip, err=%d\n", err); ++ goto err_free_2y; ++ } ++ ++ platform_set_drvdata(pdev, nxp); ++ return 0; ++ ++ err_free_2y: ++ gpio_free(pdata->gpio_pin_2y); ++ err_free_1y: ++ gpio_free(pdata->gpio_pin_1y); ++ err_free_s1: ++ gpio_free(pdata->gpio_pin_s1); ++ err_free_s0: ++ gpio_free(pdata->gpio_pin_s0); ++ err_free_nxp: ++ kfree(nxp); ++ return err; ++} ++ ++static int nxp_74hc153_remove(struct platform_device *pdev) ++{ ++ struct nxp_74hc153_chip *nxp = platform_get_drvdata(pdev); ++ struct nxp_74hc153_platform_data *pdata = pdev->dev.platform_data; ++ ++ if (nxp) { ++ int err; ++ ++ err = gpiochip_remove(&nxp->gpio_chip); ++ if (err) { ++ dev_err(&pdev->dev, ++ "unable to remove gpio chip, err=%d\n", ++ err); ++ return err; ++ } ++ ++ gpio_free(pdata->gpio_pin_2y); ++ gpio_free(pdata->gpio_pin_1y); ++ gpio_free(pdata->gpio_pin_s1); ++ gpio_free(pdata->gpio_pin_s0); ++ ++ kfree(nxp); ++ platform_set_drvdata(pdev, NULL); ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver nxp_74hc153_driver = { ++ .probe = nxp_74hc153_probe, ++ .remove = __devexit_p(nxp_74hc153_remove), ++ .driver = { ++ .name = NXP_74HC153_DRIVER_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init nxp_74hc153_init(void) ++{ ++ return platform_driver_register(&nxp_74hc153_driver); ++} ++subsys_initcall(nxp_74hc153_init); ++ ++static void __exit nxp_74hc153_exit(void) ++{ ++ platform_driver_unregister(&nxp_74hc153_driver); ++} ++module_exit(nxp_74hc153_exit); ++ ++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); ++MODULE_DESCRIPTION("GPIO expander driver for NXP 74HC153"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" NXP_74HC153_DRIVER_NAME); +diff -Nur linux-2.6.39.orig/drivers/input/misc/Kconfig linux-2.6.39/drivers/input/misc/Kconfig +--- linux-2.6.39.orig/drivers/input/misc/Kconfig 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/input/misc/Kconfig 2011-05-27 14:36:51.000000000 +0200 +@@ -467,4 +467,20 @@ + To compile this driver as a module, choose M here: the + module will be called xen-kbdfront. + ++config INPUT_GPIO_BUTTONS ++ tristate "Polled GPIO buttons interface" ++ depends on GENERIC_GPIO ++ select INPUT_POLLDEV ++ help ++ This driver implements support for buttons connected ++ to GPIO pins of various CPUs (and some other chips). ++ ++ Say Y here if your device has buttons connected ++ directly to such GPIO pins. Your board-specific ++ setup logic must also provide a platform device, ++ with configuration data saying which GPIOs are used. ++ ++ To compile this driver as a module, choose M here: the ++ module will be called gpio-buttons. ++ + endif +diff -Nur linux-2.6.39.orig/drivers/input/misc/Makefile linux-2.6.39/drivers/input/misc/Makefile +--- linux-2.6.39.orig/drivers/input/misc/Makefile 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/input/misc/Makefile 2011-05-27 14:36:51.000000000 +0200 +@@ -44,4 +44,5 @@ + obj-$(CONFIG_INPUT_WM831X_ON) += wm831x-on.o + obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND) += xen-kbdfront.o + obj-$(CONFIG_INPUT_YEALINK) += yealink.o ++obj-$(CONFIG_INPUT_GPIO_BUTTONS) += gpio_buttons.o + +diff -Nur linux-2.6.39.orig/drivers/input/misc/gpio_buttons.c linux-2.6.39/drivers/input/misc/gpio_buttons.c +--- linux-2.6.39.orig/drivers/input/misc/gpio_buttons.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/input/misc/gpio_buttons.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,216 @@ ++/* ++ * Driver for buttons on GPIO lines not capable of generating interrupts ++ * ++ * Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2010 Nuno Goncalves <nunojpg@gmail.com> ++ * ++ * This file was based on: /drivers/input/misc/cobalt_btns.c ++ * Copyright (C) 2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> ++ * ++ * also was based on: /drivers/input/keyboard/gpio_keys.c ++ * Copyright 2005 Phil Blundell ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/slab.h> ++ ++#include <linux/input.h> ++#include <linux/input-polldev.h> ++#include <linux/ioport.h> ++#include <linux/platform_device.h> ++ ++#include <linux/gpio_buttons.h> ++ ++#include <asm/gpio.h> ++ ++#define DRV_NAME "gpio-buttons" ++#define DRV_VERSION "0.1.2" ++#define PFX DRV_NAME ": " ++ ++struct gpio_button_data { ++ int last_state; ++ int count; ++}; ++ ++struct gpio_buttons_dev { ++ struct input_polled_dev *poll_dev; ++ struct gpio_buttons_platform_data *pdata; ++ struct gpio_button_data *data; ++}; ++ ++static void gpio_buttons_poll(struct input_polled_dev *dev) ++{ ++ struct gpio_buttons_dev *bdev = dev->private; ++ struct gpio_buttons_platform_data *pdata = bdev->pdata; ++ struct input_dev *input = dev->input; ++ int i; ++ ++ for (i = 0; i < bdev->pdata->nbuttons; i++) { ++ struct gpio_button *button = &pdata->buttons[i]; ++ unsigned int type = button->type ?: EV_KEY; ++ int state; ++ ++ if (bdev->data[i].count < button->threshold) { ++ bdev->data[i].count++; ++ continue; ++ } ++ ++ state = gpio_get_value(button->gpio) ? 1 : 0; ++ if (state != bdev->data[i].last_state) { ++ input_event(input, type, button->code, ++ !!(state ^ button->active_low)); ++ input_sync(input); ++ bdev->data[i].count = 0; ++ bdev->data[i].last_state = state; ++ } ++ } ++} ++ ++static int __devinit gpio_buttons_probe(struct platform_device *pdev) ++{ ++ struct gpio_buttons_platform_data *pdata = pdev->dev.platform_data; ++ struct gpio_buttons_dev *bdev; ++ struct input_polled_dev *poll_dev; ++ struct input_dev *input; ++ int error, i; ++ ++ if (!pdata) ++ return -ENXIO; ++ ++ bdev = kzalloc(sizeof(struct gpio_buttons_dev) + ++ sizeof(struct gpio_button_data) * pdata->nbuttons, ++ GFP_KERNEL); ++ if (!bdev) { ++ printk(KERN_ERR DRV_NAME "no memory for device\n"); ++ return -ENOMEM; ++ } ++ ++ bdev->data = (struct gpio_button_data *) &bdev[1]; ++ ++ poll_dev = input_allocate_polled_device(); ++ if (!poll_dev) { ++ printk(KERN_ERR DRV_NAME "no memory for polled device\n"); ++ error = -ENOMEM; ++ goto err_free_bdev; ++ } ++ ++ poll_dev->private = bdev; ++ poll_dev->poll = gpio_buttons_poll; ++ poll_dev->poll_interval = pdata->poll_interval; ++ ++ input = poll_dev->input; ++ ++ input->evbit[0] = BIT(EV_KEY); ++ input->name = pdev->name; ++ input->phys = "gpio-buttons/input0"; ++ input->dev.parent = &pdev->dev; ++ ++ input->id.bustype = BUS_HOST; ++ input->id.vendor = 0x0001; ++ input->id.product = 0x0001; ++ input->id.version = 0x0100; ++ ++ for (i = 0; i < pdata->nbuttons; i++) { ++ struct gpio_button *button = &pdata->buttons[i]; ++ unsigned int gpio = button->gpio; ++ unsigned int type = button->type ?: EV_KEY; ++ ++ error = gpio_request(gpio, button->desc ? ++ button->desc : DRV_NAME); ++ if (error) { ++ printk(KERN_ERR PFX "unable to claim gpio %u, " ++ "error %d\n", gpio, error); ++ goto err_free_gpio; ++ } ++ ++ error = gpio_direction_input(gpio); ++ if (error) { ++ printk(KERN_ERR PFX "unable to set direction on " ++ "gpio %u, error %d\n", gpio, error); ++ goto err_free_gpio; ++ } ++ ++ input_set_capability(input, type, button->code); ++ bdev->data[i].last_state = gpio_get_value(button->gpio) ? 1 : 0; ++ } ++ ++ bdev->poll_dev = poll_dev; ++ bdev->pdata = pdata; ++ platform_set_drvdata(pdev, bdev); ++ ++ error = input_register_polled_device(poll_dev); ++ if (error) { ++ printk(KERN_ERR PFX "unable to register polled device, " ++ "error %d\n", error); ++ goto err_free_gpio; ++ } ++ ++ return 0; ++ ++err_free_gpio: ++ for (i = i - 1; i >= 0; i--) ++ gpio_free(pdata->buttons[i].gpio); ++ ++ input_free_polled_device(poll_dev); ++ ++err_free_bdev: ++ kfree(bdev); ++ ++ platform_set_drvdata(pdev, NULL); ++ return error; ++} ++ ++static int __devexit gpio_buttons_remove(struct platform_device *pdev) ++{ ++ struct gpio_buttons_dev *bdev = platform_get_drvdata(pdev); ++ struct gpio_buttons_platform_data *pdata = bdev->pdata; ++ int i; ++ ++ input_unregister_polled_device(bdev->poll_dev); ++ ++ for (i = 0; i < pdata->nbuttons; i++) ++ gpio_free(pdata->buttons[i].gpio); ++ ++ input_free_polled_device(bdev->poll_dev); ++ ++ kfree(bdev); ++ platform_set_drvdata(pdev, NULL); ++ ++ return 0; ++} ++ ++static struct platform_driver gpio_buttons_driver = { ++ .probe = gpio_buttons_probe, ++ .remove = __devexit_p(gpio_buttons_remove), ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init gpio_buttons_init(void) ++{ ++ printk(KERN_INFO DRV_NAME " driver version " DRV_VERSION "\n"); ++ return platform_driver_register(&gpio_buttons_driver); ++} ++ ++static void __exit gpio_buttons_exit(void) ++{ ++ platform_driver_unregister(&gpio_buttons_driver); ++} ++ ++module_init(gpio_buttons_init); ++module_exit(gpio_buttons_exit); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>"); ++MODULE_VERSION(DRV_VERSION); ++MODULE_DESCRIPTION("Polled buttons driver for CPU GPIOs"); ++ +diff -Nur linux-2.6.39.orig/drivers/leds/leds-rb750.c linux-2.6.39/drivers/leds/leds-rb750.c +--- linux-2.6.39.orig/drivers/leds/leds-rb750.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/leds/leds-rb750.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,140 @@ ++/* ++ * LED driver for the RouterBOARD 750 ++ * ++ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/platform_device.h> ++#include <linux/leds.h> ++ ++#include <asm/mach-ar71xx/mach-rb750.h> ++ ++#define DRV_NAME "leds-rb750" ++ ++struct rb750_led_dev { ++ struct led_classdev cdev; ++ u32 mask; ++ int active_low; ++}; ++ ++struct rb750_led_drvdata { ++ struct rb750_led_dev *led_devs; ++ int num_leds; ++}; ++ ++static inline struct rb750_led_dev *to_rbled(struct led_classdev *led_cdev) ++{ ++ return (struct rb750_led_dev *)container_of(led_cdev, ++ struct rb750_led_dev, cdev); ++} ++ ++static void rb750_led_brightness_set(struct led_classdev *led_cdev, ++ enum led_brightness value) ++{ ++ struct rb750_led_dev *rbled = to_rbled(led_cdev); ++ int level; ++ ++ level = (value == LED_OFF) ? 0 : 1; ++ level ^= rbled->active_low; ++ ++ if (level) ++ rb750_latch_change(0, rbled->mask); ++ else ++ rb750_latch_change(rbled->mask, 0); ++} ++ ++static int __devinit rb750_led_probe(struct platform_device *pdev) ++{ ++ struct rb750_led_platform_data *pdata; ++ struct rb750_led_drvdata *drvdata; ++ int ret = 0; ++ int i; ++ ++ pdata = pdev->dev.platform_data; ++ if (!pdata) ++ return -EINVAL; ++ ++ drvdata = kzalloc(sizeof(struct rb750_led_drvdata) + ++ sizeof(struct rb750_led_dev) * pdata->num_leds, ++ GFP_KERNEL); ++ if (!drvdata) ++ return -ENOMEM; ++ ++ drvdata->num_leds = pdata->num_leds; ++ drvdata->led_devs = (struct rb750_led_dev *) &drvdata[1]; ++ ++ for (i = 0; i < drvdata->num_leds; i++) { ++ struct rb750_led_dev *rbled = &drvdata->led_devs[i]; ++ struct rb750_led_data *led_data = &pdata->leds[i]; ++ ++ rbled->cdev.name = led_data->name; ++ rbled->cdev.default_trigger = led_data->default_trigger; ++ rbled->cdev.brightness_set = rb750_led_brightness_set; ++ rbled->cdev.brightness = LED_OFF; ++ ++ rbled->mask = led_data->mask; ++ rbled->active_low = !!led_data->active_low; ++ ++ ret = led_classdev_register(&pdev->dev, &rbled->cdev); ++ if (ret) ++ goto err; ++ } ++ ++ platform_set_drvdata(pdev, drvdata); ++ return 0; ++ ++ err: ++ for (i = i - 1; i >= 0; i--) ++ led_classdev_unregister(&drvdata->led_devs[i].cdev); ++ ++ kfree(drvdata); ++ return ret; ++} ++ ++static int __devexit rb750_led_remove(struct platform_device *pdev) ++{ ++ struct rb750_led_drvdata *drvdata; ++ int i; ++ ++ drvdata = platform_get_drvdata(pdev); ++ for (i = 0; i < drvdata->num_leds; i++) ++ led_classdev_unregister(&drvdata->led_devs[i].cdev); ++ ++ kfree(drvdata); ++ return 0; ++} ++ ++static struct platform_driver rb750_led_driver = { ++ .probe = rb750_led_probe, ++ .remove = __devexit_p(rb750_led_remove), ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++MODULE_ALIAS("platform:leds-rb750"); ++ ++static int __init rb750_led_init(void) ++{ ++ return platform_driver_register(&rb750_led_driver); ++} ++ ++static void __exit rb750_led_exit(void) ++{ ++ platform_driver_unregister(&rb750_led_driver); ++} ++ ++module_init(rb750_led_init); ++module_exit(rb750_led_exit); ++ ++MODULE_DESCRIPTION(DRV_NAME); ++MODULE_DESCRIPTION("LED driver for the RouterBOARD 750"); ++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); ++MODULE_LICENSE("GPL v2"); +diff -Nur linux-2.6.39.orig/drivers/leds/leds-wndr3700-usb.c linux-2.6.39/drivers/leds/leds-wndr3700-usb.c +--- linux-2.6.39.orig/drivers/leds/leds-wndr3700-usb.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/leds/leds-wndr3700-usb.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,75 @@ ++/* ++ * USB LED driver for the NETGEAR WNDR3700 ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/leds.h> ++#include <linux/module.h> ++#include <linux/platform_device.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#define DRIVER_NAME "wndr3700-led-usb" ++ ++static void wndr3700_usb_led_set(struct led_classdev *cdev, ++ enum led_brightness brightness) ++{ ++ if (brightness) ++ ar71xx_device_start(RESET_MODULE_GE1_PHY); ++ else ++ ar71xx_device_stop(RESET_MODULE_GE1_PHY); ++} ++ ++static enum led_brightness wndr3700_usb_led_get(struct led_classdev *cdev) ++{ ++ return ar71xx_device_stopped(RESET_MODULE_GE1_PHY) ? LED_OFF : LED_FULL; ++} ++ ++static struct led_classdev wndr3700_usb_led = { ++ .name = "wndr3700:green:usb", ++ .brightness_set = wndr3700_usb_led_set, ++ .brightness_get = wndr3700_usb_led_get, ++}; ++ ++static int __devinit wndr3700_usb_led_probe(struct platform_device *pdev) ++{ ++ return led_classdev_register(&pdev->dev, &wndr3700_usb_led); ++} ++ ++static int __devexit wndr3700_usb_led_remove(struct platform_device *pdev) ++{ ++ led_classdev_unregister(&wndr3700_usb_led); ++ return 0; ++} ++ ++static struct platform_driver wndr3700_usb_led_driver = { ++ .probe = wndr3700_usb_led_probe, ++ .remove = __devexit_p(wndr3700_usb_led_remove), ++ .driver = { ++ .name = DRIVER_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init wndr3700_usb_led_init(void) ++{ ++ return platform_driver_register(&wndr3700_usb_led_driver); ++} ++ ++static void __exit wndr3700_usb_led_exit(void) ++{ ++ platform_driver_unregister(&wndr3700_usb_led_driver); ++} ++ ++module_init(wndr3700_usb_led_init); ++module_exit(wndr3700_usb_led_exit); ++ ++MODULE_DESCRIPTION("USB LED driver for the NETGEAR WNDR3700"); ++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" DRIVER_NAME); +diff -Nur linux-2.6.39.orig/drivers/mtd/maps/Kconfig linux-2.6.39/drivers/mtd/maps/Kconfig +--- linux-2.6.39.orig/drivers/mtd/maps/Kconfig 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/mtd/maps/Kconfig 2011-05-27 14:36:51.000000000 +0200 +@@ -260,6 +260,13 @@ + Support for parsing CFE image tag and creating MTD partitions on + Broadcom BCM63xx boards. + ++config MTD_AR91XX_FLASH ++ tristate "Atheros AR91xx parallel flash support" ++ depends on ATHEROS_AR71XX ++ select MTD_COMPLEX_MAPPINGS ++ help ++ Parallel flash driver for the Atheros AR91xx based boards. ++ + config MTD_DILNETPC + tristate "CFI Flash device mapped on DIL/Net PC" + depends on X86 && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN +diff -Nur linux-2.6.39.orig/drivers/mtd/maps/Makefile linux-2.6.39/drivers/mtd/maps/Makefile +--- linux-2.6.39.orig/drivers/mtd/maps/Makefile 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/mtd/maps/Makefile 2011-05-27 14:36:51.000000000 +0200 +@@ -7,6 +7,7 @@ + endif + + # Chip mappings ++obj-$(CONFIG_MTD_AR91XX_FLASH) += ar91xx_flash.o + obj-$(CONFIG_MTD_CDB89712) += cdb89712.o + obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o + obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o +diff -Nur linux-2.6.39.orig/drivers/mtd/maps/ar91xx_flash.c linux-2.6.39/drivers/mtd/maps/ar91xx_flash.c +--- linux-2.6.39.orig/drivers/mtd/maps/ar91xx_flash.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/mtd/maps/ar91xx_flash.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,310 @@ ++/* ++ * Parallel flash driver for the Atheros AR91xx SoC ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#include <linux/module.h> ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/slab.h> ++#include <linux/device.h> ++#include <linux/platform_device.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/map.h> ++#include <linux/mtd/partitions.h> ++#include <linux/io.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/ar91xx_flash.h> ++ ++#define DRV_NAME "ar91xx-flash" ++ ++struct ar91xx_flash_info { ++ struct mtd_info *mtd; ++ struct map_info map; ++#ifdef CONFIG_MTD_PARTITIONS ++ int nr_parts; ++ struct mtd_partition *parts; ++#endif ++}; ++ ++static map_word ar91xx_flash_read(struct map_info *map, unsigned long ofs) ++{ ++ map_word val; ++ ++ if (map_bankwidth_is_1(map)) ++ val.x[0] = __raw_readb(map->virt + (ofs ^ 3)); ++ else if (map_bankwidth_is_2(map)) ++ val.x[0] = __raw_readw(map->virt + (ofs ^ 2)); ++ else ++ val = map_word_ff(map); ++ ++ return val; ++} ++ ++static void ar91xx_flash_write(struct map_info *map, map_word d, ++ unsigned long ofs) ++{ ++ if (map_bankwidth_is_1(map)) ++ __raw_writeb(d.x[0], map->virt + (ofs ^ 3)); ++ else if (map_bankwidth_is_2(map)) ++ __raw_writew(d.x[0], map->virt + (ofs ^ 2)); ++ ++ mb(); ++} ++ ++static map_word ar91xx_flash_read_lock(struct map_info *map, unsigned long ofs) ++{ ++ map_word ret; ++ ++ ar71xx_flash_acquire(); ++ ret = ar91xx_flash_read(map, ofs); ++ ar71xx_flash_release(); ++ ++ return ret; ++} ++ ++static void ar91xx_flash_write_lock(struct map_info *map, map_word d, ++ unsigned long ofs) ++{ ++ ar71xx_flash_acquire(); ++ ar91xx_flash_write(map, d, ofs); ++ ar71xx_flash_release(); ++} ++ ++static void ar91xx_flash_copy_from_lock(struct map_info *map, void *to, ++ unsigned long from, ssize_t len) ++{ ++ ar71xx_flash_acquire(); ++ inline_map_copy_from(map, to, from, len); ++ ar71xx_flash_release(); ++} ++ ++static void ar91xx_flash_copy_to_lock(struct map_info *map, unsigned long to, ++ const void *from, ssize_t len) ++{ ++ ar71xx_flash_acquire(); ++ inline_map_copy_to(map, to, from, len); ++ ar71xx_flash_release(); ++} ++ ++static int ar91xx_flash_remove(struct platform_device *pdev) ++{ ++ struct ar91xx_flash_platform_data *pdata; ++ struct ar91xx_flash_info *info; ++ ++ info = platform_get_drvdata(pdev); ++ if (info == NULL) ++ return 0; ++ ++ platform_set_drvdata(pdev, NULL); ++ ++ if (info->mtd == NULL) ++ return 0; ++ ++ pdata = pdev->dev.platform_data; ++#ifdef CONFIG_MTD_PARTITIONS ++ if (info->nr_parts) { ++ del_mtd_partitions(info->mtd); ++ kfree(info->parts); ++ } else if (pdata->nr_parts) { ++ del_mtd_partitions(info->mtd); ++ } else { ++ del_mtd_device(info->mtd); ++ } ++#else ++ del_mtd_device(info->mtd); ++#endif ++ map_destroy(info->mtd); ++ ++ return 0; ++} ++ ++static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; ++#ifdef CONFIG_MTD_PARTITIONS ++static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL }; ++#endif ++ ++static int ar91xx_flash_probe(struct platform_device *pdev) ++{ ++ struct ar91xx_flash_platform_data *pdata; ++ struct ar91xx_flash_info *info; ++ struct resource *res; ++ struct resource *region; ++ const char **probe_type; ++ int err = 0; ++ ++ pdata = pdev->dev.platform_data; ++ if (pdata == NULL) ++ return -EINVAL; ++ ++ info = devm_kzalloc(&pdev->dev, sizeof(struct ar91xx_flash_info), ++ GFP_KERNEL); ++ if (info == NULL) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ platform_set_drvdata(pdev, info); ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (res == NULL) { ++ err = -ENOENT; ++ goto err_out; ++ } ++ ++ dev_info(&pdev->dev, "%.8llx at %.8llx\n", ++ (unsigned long long)(res->end - res->start + 1), ++ (unsigned long long)res->start); ++ ++ region = devm_request_mem_region(&pdev->dev, ++ res->start, res->end - res->start + 1, ++ dev_name(&pdev->dev)); ++ if (region == NULL) { ++ dev_err(&pdev->dev, "could not reserve memory region\n"); ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ info->map.name = dev_name(&pdev->dev); ++ info->map.phys = res->start; ++ info->map.size = res->end - res->start + 1; ++ info->map.bankwidth = pdata->width; ++ ++ info->map.virt = devm_ioremap(&pdev->dev, info->map.phys, ++ info->map.size); ++ if (info->map.virt == NULL) { ++ dev_err(&pdev->dev, "failed to ioremap flash region\n"); ++ err = -EIO; ++ goto err_out; ++ } ++ ++ simple_map_init(&info->map); ++ if (pdata->is_shared) { ++ info->map.read = ar91xx_flash_read_lock; ++ info->map.write = ar91xx_flash_write_lock; ++ info->map.copy_from = ar91xx_flash_copy_from_lock; ++ info->map.copy_to = ar91xx_flash_copy_to_lock; ++ } else { ++ info->map.read = ar91xx_flash_read; ++ info->map.write = ar91xx_flash_write; ++ } ++ ++ probe_type = rom_probe_types; ++ for (; info->mtd == NULL && *probe_type != NULL; probe_type++) ++ info->mtd = do_map_probe(*probe_type, &info->map); ++ ++ if (info->mtd == NULL) { ++ dev_err(&pdev->dev, "map_probe failed\n"); ++ err = -ENXIO; ++ goto err_out; ++ } ++ ++ info->mtd->owner = THIS_MODULE; ++ ++#ifdef CONFIG_MTD_PARTITIONS ++ if (pdata->nr_parts) { ++ dev_info(&pdev->dev, "using static partition mapping\n"); ++ add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts); ++ return 0; ++ } ++ ++ err = parse_mtd_partitions(info->mtd, part_probe_types, ++ &info->parts, 0); ++ if (err > 0) { ++ add_mtd_partitions(info->mtd, info->parts, err); ++ return 0; ++ } ++#endif ++ ++ add_mtd_device(info->mtd); ++ return 0; ++ ++ err_out: ++ ar91xx_flash_remove(pdev); ++ return err; ++} ++ ++#ifdef CONFIG_PM ++static int ar91xx_flash_suspend(struct platform_device *dev, pm_message_t state) ++{ ++ struct ar91xx_flash_info *info = platform_get_drvdata(dev); ++ int ret = 0; ++ ++ if (info->mtd->suspend) ++ ret = info->mtd->suspend(info->mtd); ++ ++ if (ret) ++ goto fail; ++ ++ return 0; ++ ++ fail: ++ if (info->mtd->suspend) { ++ BUG_ON(!info->mtd->resume); ++ info->mtd->resume(info->mtd); ++ } ++ ++ return ret; ++} ++ ++static int ar91xx_flash_resume(struct platform_device *pdev) ++{ ++ struct ar91xx_flash_info *info = platform_get_drvdata(pdev); ++ ++ if (info->mtd->resume) ++ info->mtd->resume(info->mtd); ++ ++ return 0; ++} ++ ++static void ar91xx_flash_shutdown(struct platform_device *pdev) ++{ ++ struct ar91xx_flash_info *info = platform_get_drvdata(pdev); ++ ++ if (info->mtd->suspend && info->mtd->resume) ++ if (info->mtd->suspend(info->mtd) == 0) ++ info->mtd->resume(info->mtd); ++} ++#else ++#define ar91xx_flash_suspend NULL ++#define ar91xx_flash_resume NULL ++#define ar91xx_flash_shutdown NULL ++#endif ++ ++static struct platform_driver ar91xx_flash_driver = { ++ .probe = ar91xx_flash_probe, ++ .remove = ar91xx_flash_remove, ++ .suspend = ar91xx_flash_suspend, ++ .resume = ar91xx_flash_resume, ++ .shutdown = ar91xx_flash_shutdown, ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init ar91xx_flash_init(void) ++{ ++ return platform_driver_register(&ar91xx_flash_driver); ++} ++ ++static void __exit ar91xx_flash_exit(void) ++{ ++ platform_driver_unregister(&ar91xx_flash_driver); ++} ++ ++module_init(ar91xx_flash_init); ++module_exit(ar91xx_flash_exit); ++ ++MODULE_LICENSE("GPL v2"); ++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); ++MODULE_DESCRIPTION("Parallel flash driver for the Atheros AR91xx SoC"); ++MODULE_ALIAS("platform:" DRV_NAME); +diff -Nur linux-2.6.39.orig/drivers/mtd/nand/Kconfig linux-2.6.39/drivers/mtd/nand/Kconfig +--- linux-2.6.39.orig/drivers/mtd/nand/Kconfig 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/mtd/nand/Kconfig 2011-05-27 14:36:51.000000000 +0200 +@@ -531,4 +531,8 @@ + Enables support for NAND Flash chips on the ST Microelectronics + Flexible Static Memory Controller (FSMC) + ++config MTD_NAND_RB4XX ++ tristate "NAND flash driver for RouterBoard 4xx series" ++ depends on MTD_NAND && AR71XX_MACH_RB4XX ++ + endif # MTD_NAND +diff -Nur linux-2.6.39.orig/drivers/mtd/nand/Makefile linux-2.6.39/drivers/mtd/nand/Makefile +--- linux-2.6.39.orig/drivers/mtd/nand/Makefile 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/mtd/nand/Makefile 2011-05-27 14:36:51.000000000 +0200 +@@ -34,6 +34,7 @@ + obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o + obj-$(CONFIG_MTD_NAND_TMIO) += tmio_nand.o + obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o ++obj-$(CONFIG_MTD_NAND_RB4XX) += rb4xx_nand.o + obj-$(CONFIG_MTD_ALAUDA) += alauda.o + obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o + obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o +diff -Nur linux-2.6.39.orig/drivers/mtd/nand/rb4xx_nand.c linux-2.6.39/drivers/mtd/nand/rb4xx_nand.c +--- linux-2.6.39.orig/drivers/mtd/nand/rb4xx_nand.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/mtd/nand/rb4xx_nand.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,513 @@ ++/* ++ * NAND flash driver for the MikroTik RouterBoard 4xx series ++ * ++ * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This file was based on the driver for Linux 2.6.22 published by ++ * MikroTik for their RouterBoard 4xx series devices. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/init.h> ++#include <linux/mtd/nand.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <linux/platform_device.h> ++#include <linux/delay.h> ++#include <linux/io.h> ++#include <linux/gpio.h> ++#include <linux/slab.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#define DRV_NAME "rb4xx-nand" ++#define DRV_VERSION "0.1.10" ++#define DRV_DESC "NAND flash driver for RouterBoard 4xx series" ++ ++#define USE_FAST_READ 1 ++#define USE_FAST_WRITE 1 ++#undef RB4XX_NAND_DEBUG ++ ++#ifdef RB4XX_NAND_DEBUG ++#define DBG(fmt, arg...) printk(KERN_DEBUG DRV_NAME ": " fmt, ## arg) ++#else ++#define DBG(fmt, arg...) do {} while (0) ++#endif ++ ++#define RB4XX_NAND_GPIO_RDY 5 ++#define RB4XX_FLASH_HZ 33333334 ++#define RB4XX_NAND_HZ 33333334 ++ ++#define SPI_CTRL_FASTEST 0x40 ++#define SPI_CTRL_SAFE 0x43 /* 25 MHz for AHB 200 MHz */ ++#define SBIT_IOC_BASE SPI_IOC_CS1 ++#define SBIT_IOC_DO_SHIFT 0 ++#define SBIT_IOC_DO (1u << SBIT_IOC_DO_SHIFT) ++#define SBIT_IOC_DO2_SHIFT 18 ++#define SBIT_IOC_DO2 (1u << SBIT_IOC_DO2_SHIFT) ++ ++#define CPLD_CMD_WRITE_MULT 0x08 /* send cmd, n x send data, read data */ ++#define CPLD_CMD_WRITE_CFG 0x09 /* send cmd, n x send cfg */ ++#define CPLD_CMD_READ_MULT 0x0a /* send cmd, send idle, n x read data */ ++#define CPLD_CMD_READ_FAST 0x0b /* send cmd, 4 x idle, n x read data */ ++ ++#define CFG_BIT_nCE 0x80 ++#define CFG_BIT_CLE 0x40 ++#define CFG_BIT_ALE 0x20 ++#define CFG_BIT_FAN 0x10 ++#define CFG_BIT_nLED4 0x08 ++#define CFG_BIT_nLED3 0x04 ++#define CFG_BIT_nLED2 0x02 ++#define CFG_BIT_nLED1 0x01 ++ ++#define CFG_BIT_nLEDS \ ++ (CFG_BIT_nLED1 | CFG_BIT_nLED2 | CFG_BIT_nLED3 | CFG_BIT_nLED4) ++ ++struct rb4xx_nand_info { ++ struct nand_chip chip; ++ struct mtd_info mtd; ++}; ++ ++/* ++ * We need to use the OLD Yaffs-1 OOB layout, otherwise the RB bootloader ++ * will not be able to find the kernel that we load. ++ */ ++static struct nand_ecclayout rb4xx_nand_ecclayout = { ++ .eccbytes = 6, ++ .eccpos = { 8, 9, 10, 13, 14, 15 }, ++ .oobavail = 9, ++ .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } ++}; ++ ++static struct mtd_partition rb4xx_nand_partitions[] = { ++ { ++ .name = "booter", ++ .offset = 0, ++ .size = (256 * 1024), ++ .mask_flags = MTD_WRITEABLE, ++ }, ++ { ++ .name = "kernel", ++ .offset = (256 * 1024), ++ .size = (4 * 1024 * 1024) - (256 * 1024), ++ }, ++ { ++ .name = "rootfs", ++ .offset = MTDPART_OFS_NXTBLK, ++ .size = (1024*1024*64) - (1024*256) - (4 * 1024 * 1024) ++ }, ++ { ++ .name = "cfgfs", ++ .offset = (1024*1024*64) - (1024*256), ++ .size = (1024*256), ++ }, ++}; ++ ++#if USE_FAST_READ ++#define SPI_NDATA_BASE 0x00800000 ++static unsigned spi_ctrl_fread = SPI_CTRL_SAFE; ++static unsigned spi_ctrl_flash = SPI_CTRL_SAFE; ++extern unsigned mips_hpt_frequency; ++#endif ++ ++static inline unsigned rb4xx_spi_rreg(unsigned r) ++{ ++ return __raw_readl((void * __iomem)(KSEG1ADDR(AR71XX_SPI_BASE) + r)); ++} ++ ++static inline void rb4xx_spi_wreg(unsigned r, unsigned v) ++{ ++ __raw_writel(v, (void * __iomem)(KSEG1ADDR(AR71XX_SPI_BASE) + r)); ++} ++ ++static inline void do_spi_clk(int bit) ++{ ++ unsigned bval = SBIT_IOC_BASE | (bit & 1); ++ ++ rb4xx_spi_wreg(SPI_REG_IOC, bval); ++ rb4xx_spi_wreg(SPI_REG_IOC, bval | SPI_IOC_CLK); ++} ++ ++static void do_spi_byte(uint8_t byte) ++{ ++ do_spi_clk(byte >> 7); ++ do_spi_clk(byte >> 6); ++ do_spi_clk(byte >> 5); ++ do_spi_clk(byte >> 4); ++ do_spi_clk(byte >> 3); ++ do_spi_clk(byte >> 2); ++ do_spi_clk(byte >> 1); ++ do_spi_clk(byte); ++ ++ DBG("spi_byte sent 0x%02x got 0x%x\n", ++ byte, rb4xx_spi_rreg(SPI_REG_RDS)); ++} ++ ++#if USE_FAST_WRITE ++static inline void do_spi_clk_fast(int bit1, int bit2) ++{ ++ unsigned bval = (SBIT_IOC_BASE | ++ ((bit1 << SBIT_IOC_DO_SHIFT) & SBIT_IOC_DO) | ++ ((bit2 << SBIT_IOC_DO2_SHIFT) & SBIT_IOC_DO2)); ++ ++ rb4xx_spi_wreg(SPI_REG_IOC, bval); ++ rb4xx_spi_wreg(SPI_REG_IOC, bval | SPI_IOC_CLK); ++} ++ ++static inline void do_spi_byte_fast(uint8_t byte) ++{ ++ do_spi_clk_fast(byte >> 7, byte >> 6); ++ do_spi_clk_fast(byte >> 5, byte >> 4); ++ do_spi_clk_fast(byte >> 3, byte >> 2); ++ do_spi_clk_fast(byte >> 1, byte >> 0); ++ ++ DBG("spi_byte_fast sent 0x%02x got 0x%x\n", ++ byte, rb4xx_spi_rreg(SPI_REG_RDS)); ++} ++#else ++static inline void do_spi_byte_fast(uint8_t byte) ++{ ++ do_spi_byte(byte); ++} ++#endif /* USE_FAST_WRITE */ ++ ++static int do_spi_cmd(unsigned cmd, unsigned sendCnt, const uint8_t *sendData, ++ unsigned recvCnt, uint8_t *recvData, ++ const uint8_t *verifyData, int fastWrite) ++{ ++ unsigned i; ++ ++ DBG("SPI cmd 0x%x send %u recv %u\n", cmd, sendCnt, recvCnt); ++ ++ rb4xx_spi_wreg(SPI_REG_FS, SPI_FS_GPIO); ++ rb4xx_spi_wreg(SPI_REG_CTRL, SPI_CTRL_FASTEST); ++ ++ do_spi_byte(cmd); ++#if 0 ++ if (cmd == CPLD_CMD_READ_FAST) { ++ do_spi_byte(0x80); ++ do_spi_byte(0); ++ do_spi_byte(0); ++ } ++#endif ++ for (i = 0; i < sendCnt; ++i) { ++ if (fastWrite) ++ do_spi_byte_fast(sendData[i]); ++ else ++ do_spi_byte(sendData[i]); ++ } ++ ++ for (i = 0; i < recvCnt; ++i) { ++ if (fastWrite) ++ do_spi_byte_fast(0); ++ else ++ do_spi_byte(0); ++ ++ if (recvData) { ++ recvData[i] = rb4xx_spi_rreg(SPI_REG_RDS) & 0xff; ++ } else if (verifyData) { ++ if (verifyData[i] != (rb4xx_spi_rreg(SPI_REG_RDS) ++ & 0xff)) ++ break; ++ } ++ } ++ ++ rb4xx_spi_wreg(SPI_REG_IOC, SBIT_IOC_BASE | SPI_IOC_CS0); ++ rb4xx_spi_wreg(SPI_REG_CTRL, spi_ctrl_flash); ++ rb4xx_spi_wreg(SPI_REG_FS, 0); ++ ++ return i == recvCnt; ++} ++ ++static int got_write = 1; ++ ++static void rb4xx_nand_write_data(const uint8_t *byte, unsigned cnt) ++{ ++ do_spi_cmd(CPLD_CMD_WRITE_MULT, cnt, byte, 1, NULL, NULL, 1); ++ got_write = 1; ++} ++ ++static void rb4xx_nand_write_byte(uint8_t byte) ++{ ++ rb4xx_nand_write_data(&byte, 1); ++} ++ ++#if USE_FAST_READ ++static uint8_t *rb4xx_nand_read_getaddr(unsigned cnt) ++{ ++ static unsigned nboffset = 0x100000; ++ unsigned addr; ++ ++ if (got_write) { ++ nboffset = (nboffset + 31) & ~31; ++ if (nboffset >= 0x100000) /* 1MB */ ++ nboffset = 0; ++ ++ got_write = 0; ++ rb4xx_spi_wreg(SPI_REG_FS, SPI_FS_GPIO); ++ rb4xx_spi_wreg(SPI_REG_CTRL, spi_ctrl_fread); ++ rb4xx_spi_wreg(SPI_REG_FS, 0); ++ } ++ ++ addr = KSEG1ADDR(AR71XX_SPI_BASE + SPI_NDATA_BASE) + nboffset; ++ DBG("rb4xx_nand_read_getaddr 0x%x cnt 0x%x\n", addr, cnt); ++ ++ nboffset += cnt; ++ return (uint8_t *)addr; ++} ++ ++static void rb4xx_nand_read_data(uint8_t *buf, unsigned cnt) ++{ ++ unsigned size32 = cnt & ~31; ++ unsigned remain = cnt & 31; ++ ++ if (size32) { ++ uint8_t *addr = rb4xx_nand_read_getaddr(size32); ++ memcpy(buf, (void *)addr, size32); ++ } ++ ++ if (remain) { ++ do_spi_cmd(CPLD_CMD_READ_MULT, 1, buf, remain, ++ buf + size32, NULL, 0); ++ } ++} ++ ++static int rb4xx_nand_verify_data(const uint8_t *buf, unsigned cnt) ++{ ++ unsigned size32 = cnt & ~31; ++ unsigned remain = cnt & 31; ++ ++ if (size32) { ++ uint8_t *addr = rb4xx_nand_read_getaddr(size32); ++ if (memcmp(buf, (void *)addr, size32) != 0) ++ return 0; ++ } ++ ++ if (remain) { ++ return do_spi_cmd(CPLD_CMD_READ_MULT, 1, buf, remain, ++ NULL, buf + size32, 0); ++ } ++ return 1; ++} ++#else /* USE_FAST_READ */ ++static void rb4xx_nand_read_data(uint8_t *buf, unsigned cnt) ++{ ++ do_spi_cmd(CPLD_CMD_READ_MULT, 1, buf, cnt, buf, NULL, 0); ++} ++ ++static int rb4xx_nand_verify_data(const uint8_t *buf, unsigned cnt) ++{ ++ return do_spi_cmd(CPLD_CMD_READ_MULT, 1, buf, cnt, NULL, buf, 0); ++} ++#endif /* USE_FAST_READ */ ++ ++static void rb4xx_nand_write_cfg(uint8_t byte) ++{ ++ do_spi_cmd(CPLD_CMD_WRITE_CFG, 1, &byte, 0, NULL, NULL, 0); ++ got_write = 1; ++} ++ ++static int rb4xx_nand_dev_ready(struct mtd_info *mtd) ++{ ++ return gpio_get_value(RB4XX_NAND_GPIO_RDY); ++} ++ ++static void rb4xx_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, ++ unsigned int ctrl) ++{ ++ if (ctrl & NAND_CTRL_CHANGE) { ++ uint8_t cfg = CFG_BIT_nLEDS; ++ ++ cfg |= (ctrl & NAND_CLE) ? CFG_BIT_CLE : 0; ++ cfg |= (ctrl & NAND_ALE) ? CFG_BIT_ALE : 0; ++ cfg |= (ctrl & NAND_NCE) ? 0 : CFG_BIT_nCE; ++ ++ rb4xx_nand_write_cfg(cfg); ++ } ++ ++ if (cmd != NAND_CMD_NONE) ++ rb4xx_nand_write_byte(cmd); ++} ++ ++static uint8_t rb4xx_nand_read_byte(struct mtd_info *mtd) ++{ ++ uint8_t byte = 0; ++ ++ rb4xx_nand_read_data(&byte, 1); ++ return byte; ++} ++ ++static void rb4xx_nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, ++ int len) ++{ ++ rb4xx_nand_write_data(buf, len); ++} ++ ++static void rb4xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, ++ int len) ++{ ++ rb4xx_nand_read_data(buf, len); ++} ++ ++static int rb4xx_nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, ++ int len) ++{ ++ if (!rb4xx_nand_verify_data(buf, len)) ++ return -EFAULT; ++ ++ return 0; ++} ++ ++static unsigned get_spi_ctrl(unsigned hz_max, const char *name) ++{ ++ unsigned div; ++ ++ div = (ar71xx_ahb_freq - 1) / (2 * hz_max); ++ /* ++ * CPU has a bug at (div == 0) - first bit read is random ++ */ ++ if (div == 0) ++ ++div; ++ ++ if (name) { ++ unsigned ahb_khz = (ar71xx_ahb_freq + 500) / 1000; ++ unsigned div_real = 2 * (div + 1); ++ printk(KERN_INFO "%s SPI clock %u kHz (AHB %u kHz / %u)\n", ++ name, ++ ahb_khz / div_real, ++ ahb_khz, div_real); ++ } ++ ++ return SPI_CTRL_FASTEST + div; ++} ++ ++static int __init rb4xx_nand_probe(struct platform_device *pdev) ++{ ++ struct rb4xx_nand_info *info; ++ int ret; ++ ++ printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n"); ++ ++ ret = gpio_request(RB4XX_NAND_GPIO_RDY, "NAND RDY"); ++ if (ret) { ++ printk(KERN_ERR "rb4xx-nand: gpio request failed\n"); ++ return ret; ++ } ++ ++ ret = gpio_direction_input(RB4XX_NAND_GPIO_RDY); ++ if (ret) { ++ printk(KERN_ERR "rb4xx-nand: unable to set input mode " ++ "on gpio%d\n", RB4XX_NAND_GPIO_RDY); ++ goto err_free_gpio; ++ } ++ ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) { ++ printk(KERN_ERR "rb4xx-nand: no memory for private data\n"); ++ ret = -ENOMEM; ++ goto err_free_gpio; ++ } ++ ++#if USE_FAST_READ ++ spi_ctrl_fread = get_spi_ctrl(RB4XX_NAND_HZ, "NAND"); ++#endif ++ spi_ctrl_flash = get_spi_ctrl(RB4XX_FLASH_HZ, "FLASH"); ++ ++ rb4xx_nand_write_cfg(CFG_BIT_nLEDS | CFG_BIT_nCE); ++ ++ info->chip.priv = &info; ++ info->mtd.priv = &info->chip; ++ info->mtd.owner = THIS_MODULE; ++ ++ info->chip.cmd_ctrl = rb4xx_nand_cmd_ctrl; ++ info->chip.dev_ready = rb4xx_nand_dev_ready; ++ info->chip.read_byte = rb4xx_nand_read_byte; ++ info->chip.write_buf = rb4xx_nand_write_buf; ++ info->chip.read_buf = rb4xx_nand_read_buf; ++ info->chip.verify_buf = rb4xx_nand_verify_buf; ++ ++ info->chip.chip_delay = 25; ++ info->chip.ecc.mode = NAND_ECC_SOFT; ++ info->chip.options |= NAND_NO_AUTOINCR; ++ ++ platform_set_drvdata(pdev, info); ++ ++ ret = nand_scan_ident(&info->mtd, 1, NULL); ++ if (ret) { ++ ret = -ENXIO; ++ goto err_free_info; ++ } ++ ++ if (info->mtd.writesize == 512) ++ info->chip.ecc.layout = &rb4xx_nand_ecclayout; ++ ++ ret = nand_scan_tail(&info->mtd); ++ if (ret) { ++ return -ENXIO; ++ goto err_set_drvdata; ++ } ++ ++#ifdef CONFIG_MTD_PARTITIONS ++ ret = add_mtd_partitions(&info->mtd, rb4xx_nand_partitions, ++ ARRAY_SIZE(rb4xx_nand_partitions)); ++#else ++ ret = add_mtd_device(&info->mtd); ++#endif ++ if (ret) ++ goto err_release_nand; ++ ++ return 0; ++ ++err_release_nand: ++ nand_release(&info->mtd); ++err_set_drvdata: ++ platform_set_drvdata(pdev, NULL); ++err_free_info: ++ kfree(info); ++err_free_gpio: ++ gpio_free(RB4XX_NAND_GPIO_RDY); ++ return ret; ++} ++ ++static int __devexit rb4xx_nand_remove(struct platform_device *pdev) ++{ ++ struct rb4xx_nand_info *info = platform_get_drvdata(pdev); ++ ++ nand_release(&info->mtd); ++ platform_set_drvdata(pdev, NULL); ++ kfree(info); ++ ++ return 0; ++} ++ ++static struct platform_driver rb4xx_nand_driver = { ++ .probe = rb4xx_nand_probe, ++ .remove = __devexit_p(rb4xx_nand_remove), ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init rb4xx_nand_init(void) ++{ ++ return platform_driver_register(&rb4xx_nand_driver); ++} ++ ++static void __exit rb4xx_nand_exit(void) ++{ ++ platform_driver_unregister(&rb4xx_nand_driver); ++} ++ ++module_init(rb4xx_nand_init); ++module_exit(rb4xx_nand_exit); ++ ++MODULE_DESCRIPTION(DRV_DESC); ++MODULE_VERSION(DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); ++MODULE_AUTHOR("Imre Kaloz <kaloz@openwrt.org>"); ++MODULE_LICENSE("GPL v2"); +diff -Nur linux-2.6.39.orig/drivers/mtd/nand/rb750_nand.c linux-2.6.39/drivers/mtd/nand/rb750_nand.c +--- linux-2.6.39.orig/drivers/mtd/nand/rb750_nand.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/mtd/nand/rb750_nand.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,360 @@ ++/* ++ * NAND flash driver for the MikroTik RouterBOARD 750 ++ * ++ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/init.h> ++#include <linux/mtd/nand.h> ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++#include <linux/platform_device.h> ++#include <linux/io.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/mach-rb750.h> ++ ++#define DRV_NAME "rb750-nand" ++#define DRV_VERSION "0.1.0" ++#define DRV_DESC "NAND flash driver for the RouterBOARD 750" ++ ++#define RB750_NAND_IO0 BIT(RB750_GPIO_NAND_IO0) ++#define RB750_NAND_ALE BIT(RB750_GPIO_NAND_ALE) ++#define RB750_NAND_CLE BIT(RB750_GPIO_NAND_CLE) ++#define RB750_NAND_NRE BIT(RB750_GPIO_NAND_NRE) ++#define RB750_NAND_NWE BIT(RB750_GPIO_NAND_NWE) ++#define RB750_NAND_RDY BIT(RB750_GPIO_NAND_RDY) ++#define RB750_NAND_NCE BIT(RB750_GPIO_NAND_NCE) ++ ++#define RB750_NAND_DATA_SHIFT 1 ++#define RB750_NAND_DATA_BITS (0xff << RB750_NAND_DATA_SHIFT) ++#define RB750_NAND_INPUT_BITS (RB750_NAND_DATA_BITS | RB750_NAND_RDY) ++#define RB750_NAND_OUTPUT_BITS (RB750_NAND_ALE | RB750_NAND_CLE | \ ++ RB750_NAND_NRE | RB750_NAND_NWE | \ ++ RB750_NAND_NCE) ++ ++struct rb750_nand_info { ++ struct nand_chip chip; ++ struct mtd_info mtd; ++}; ++ ++/* ++ * We need to use the OLD Yaffs-1 OOB layout, otherwise the RB bootloader ++ * will not be able to find the kernel that we load. ++ */ ++static struct nand_ecclayout rb750_nand_ecclayout = { ++ .eccbytes = 6, ++ .eccpos = { 8, 9, 10, 13, 14, 15 }, ++ .oobavail = 9, ++ .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } ++}; ++ ++static struct mtd_partition rb750_nand_partitions[] = { ++ { ++ .name = "booter", ++ .offset = 0, ++ .size = (256 * 1024), ++ .mask_flags = MTD_WRITEABLE, ++ }, { ++ .name = "kernel", ++ .offset = (256 * 1024), ++ .size = (4 * 1024 * 1024) - (256 * 1024), ++ }, { ++ .name = "rootfs", ++ .offset = MTDPART_OFS_NXTBLK, ++ .size = MTDPART_SIZ_FULL, ++ }, ++}; ++ ++static void rb750_nand_write(const u8 *buf, unsigned len) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ u32 out; ++ unsigned i; ++ ++ /* set data lines to output mode */ ++ __raw_writel(__raw_readl(base + GPIO_REG_OE) | RB750_NAND_DATA_BITS, ++ base + GPIO_REG_OE); ++ ++ out = __raw_readl(base + GPIO_REG_OUT); ++ out &= ~(RB750_NAND_DATA_BITS | RB750_NAND_NWE); ++ for (i = 0; i != len; i++) { ++ u32 data; ++ ++ data = buf[i]; ++ data <<= RB750_NAND_DATA_SHIFT; ++ data |= out; ++ __raw_writel(data, base + GPIO_REG_OUT); ++ ++ __raw_writel(data | RB750_NAND_NWE, base + GPIO_REG_OUT); ++ /* flush write */ ++ __raw_readl(base + GPIO_REG_OUT); ++ } ++ ++ /* set data lines to input mode */ ++ __raw_writel(__raw_readl(base + GPIO_REG_OE) & ~RB750_NAND_DATA_BITS, ++ base + GPIO_REG_OE); ++ /* flush write */ ++ __raw_readl(base + GPIO_REG_OE); ++} ++ ++static int rb750_nand_read_verify(u8 *read_buf, unsigned len, ++ const u8 *verify_buf) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ unsigned i; ++ ++ for (i = 0; i < len; i++) { ++ u8 data; ++ ++ /* activate RE line */ ++ __raw_writel(RB750_NAND_NRE, base + GPIO_REG_CLEAR); ++ /* flush write */ ++ __raw_readl(base + GPIO_REG_CLEAR); ++ ++ /* read input lines */ ++ data = __raw_readl(base + GPIO_REG_IN) >> RB750_NAND_DATA_SHIFT; ++ ++ /* deactivate RE line */ ++ __raw_writel(RB750_NAND_NRE, base + GPIO_REG_SET); ++ ++ if (read_buf) ++ read_buf[i] = data; ++ else if (verify_buf && verify_buf[i] != data) ++ return -EFAULT; ++ } ++ ++ return 0; ++} ++ ++static void rb750_nand_select_chip(struct mtd_info *mtd, int chip) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ u32 func; ++ ++ func = __raw_readl(base + GPIO_REG_FUNC); ++ if (chip >= 0) { ++ /* disable latch */ ++ rb750_latch_change(RB750_LVC573_LE, 0); ++ ++ /* disable alternate functions */ ++ ar71xx_gpio_function_setup(AR724X_GPIO_FUNC_JTAG_DISABLE, ++ AR724X_GPIO_FUNC_SPI_EN); ++ ++ /* set input mode for data lines */ ++ __raw_writel(__raw_readl(base + GPIO_REG_OE) & ++ ~RB750_NAND_INPUT_BITS, ++ base + GPIO_REG_OE); ++ ++ /* deactivate RE and WE lines */ ++ __raw_writel(RB750_NAND_NRE | RB750_NAND_NWE, ++ base + GPIO_REG_SET); ++ /* flush write */ ++ (void) __raw_readl(base + GPIO_REG_SET); ++ ++ /* activate CE line */ ++ __raw_writel(RB750_NAND_NCE, base + GPIO_REG_CLEAR); ++ } else { ++ /* deactivate CE line */ ++ __raw_writel(RB750_NAND_NCE, base + GPIO_REG_SET); ++ /* flush write */ ++ (void) __raw_readl(base + GPIO_REG_SET); ++ ++ __raw_writel(__raw_readl(base + GPIO_REG_OE) | ++ RB750_NAND_IO0 | RB750_NAND_RDY, ++ base + GPIO_REG_OE); ++ ++ /* restore alternate functions */ ++ ar71xx_gpio_function_setup(AR724X_GPIO_FUNC_SPI_EN, ++ AR724X_GPIO_FUNC_JTAG_DISABLE); ++ ++ /* enable latch */ ++ rb750_latch_change(0, RB750_LVC573_LE); ++ } ++} ++ ++static int rb750_nand_dev_ready(struct mtd_info *mtd) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ ++ return !!(__raw_readl(base + GPIO_REG_IN) & RB750_NAND_RDY); ++} ++ ++static void rb750_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, ++ unsigned int ctrl) ++{ ++ if (ctrl & NAND_CTRL_CHANGE) { ++ void __iomem *base = ar71xx_gpio_base; ++ u32 t; ++ ++ t = __raw_readl(base + GPIO_REG_OUT); ++ ++ t &= ~(RB750_NAND_CLE | RB750_NAND_ALE); ++ t |= (ctrl & NAND_CLE) ? RB750_NAND_CLE : 0; ++ t |= (ctrl & NAND_ALE) ? RB750_NAND_ALE : 0; ++ ++ __raw_writel(t, base + GPIO_REG_OUT); ++ /* flush write */ ++ __raw_readl(base + GPIO_REG_OUT); ++ } ++ ++ if (cmd != NAND_CMD_NONE) { ++ u8 t = cmd; ++ rb750_nand_write(&t, 1); ++ } ++} ++ ++static u8 rb750_nand_read_byte(struct mtd_info *mtd) ++{ ++ u8 data = 0; ++ rb750_nand_read_verify(&data, 1, NULL); ++ return data; ++} ++ ++static void rb750_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len) ++{ ++ rb750_nand_read_verify(buf, len, NULL); ++} ++ ++static void rb750_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) ++{ ++ rb750_nand_write(buf, len); ++} ++ ++static int rb750_nand_verify_buf(struct mtd_info *mtd, const u8 *buf, int len) ++{ ++ return rb750_nand_read_verify(NULL, len, buf); ++} ++ ++static void __init rb750_nand_gpio_init(void) ++{ ++ void __iomem *base = ar71xx_gpio_base; ++ u32 out; ++ ++ out = __raw_readl(base + GPIO_REG_OUT); ++ ++ /* setup output levels */ ++ __raw_writel(RB750_NAND_NCE | RB750_NAND_NRE | RB750_NAND_NWE, ++ base + GPIO_REG_SET); ++ ++ __raw_writel(RB750_NAND_ALE | RB750_NAND_CLE, ++ base + GPIO_REG_CLEAR); ++ ++ /* setup input lines */ ++ __raw_writel(__raw_readl(base + GPIO_REG_OE) & ~(RB750_NAND_INPUT_BITS), ++ base + GPIO_REG_OE); ++ ++ /* setup output lines */ ++ __raw_writel(__raw_readl(base + GPIO_REG_OE) | RB750_NAND_OUTPUT_BITS, ++ base + GPIO_REG_OE); ++ ++ rb750_latch_change(~out & RB750_NAND_IO0, out & RB750_NAND_IO0); ++} ++ ++static int __init rb750_nand_probe(struct platform_device *pdev) ++{ ++ struct rb750_nand_info *info; ++ int ret; ++ ++ printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n"); ++ ++ rb750_nand_gpio_init(); ++ ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) ++ return -ENOMEM; ++ ++ info->chip.priv = &info; ++ info->mtd.priv = &info->chip; ++ info->mtd.owner = THIS_MODULE; ++ ++ info->chip.select_chip = rb750_nand_select_chip; ++ info->chip.cmd_ctrl = rb750_nand_cmd_ctrl; ++ info->chip.dev_ready = rb750_nand_dev_ready; ++ info->chip.read_byte = rb750_nand_read_byte; ++ info->chip.write_buf = rb750_nand_write_buf; ++ info->chip.read_buf = rb750_nand_read_buf; ++ info->chip.verify_buf = rb750_nand_verify_buf; ++ ++ info->chip.chip_delay = 25; ++ info->chip.ecc.mode = NAND_ECC_SOFT; ++ info->chip.options |= NAND_NO_AUTOINCR; ++ ++ platform_set_drvdata(pdev, info); ++ ++ ret = nand_scan_ident(&info->mtd, 1); ++ if (ret) { ++ ret = -ENXIO; ++ goto err_free_info; ++ } ++ ++ if (info->mtd.writesize == 512) ++ info->chip.ecc.layout = &rb750_nand_ecclayout; ++ ++ ret = nand_scan_tail(&info->mtd); ++ if (ret) { ++ return -ENXIO; ++ goto err_set_drvdata; ++ } ++ ++#ifdef CONFIG_MTD_PARTITIONS ++ ret = add_mtd_partitions(&info->mtd, rb750_nand_partitions, ++ ARRAY_SIZE(rb750_nand_partitions)); ++#else ++ ret = add_mtd_device(&info->mtd); ++#endif ++ if (ret) ++ goto err_release_nand; ++ ++ return 0; ++ ++ err_release_nand: ++ nand_release(&info->mtd); ++ err_set_drvdata: ++ platform_set_drvdata(pdev, NULL); ++ err_free_info: ++ kfree(info); ++ return ret; ++} ++ ++static int __devexit rb750_nand_remove(struct platform_device *pdev) ++{ ++ struct rb750_nand_info *info = platform_get_drvdata(pdev); ++ ++ nand_release(&info->mtd); ++ platform_set_drvdata(pdev, NULL); ++ kfree(info); ++ ++ return 0; ++} ++ ++static struct platform_driver rb750_nand_driver = { ++ .probe = rb750_nand_probe, ++ .remove = __devexit_p(rb750_nand_remove), ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init rb750_nand_init(void) ++{ ++ return platform_driver_register(&rb750_nand_driver); ++} ++ ++static void __exit rb750_nand_exit(void) ++{ ++ platform_driver_unregister(&rb750_nand_driver); ++} ++ ++module_init(rb750_nand_init); ++module_exit(rb750_nand_exit); ++ ++MODULE_DESCRIPTION(DRV_DESC); ++MODULE_VERSION(DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); ++MODULE_LICENSE("GPL v2"); +diff -Nur linux-2.6.39.orig/drivers/mtd/wrt160nl_part.c linux-2.6.39/drivers/mtd/wrt160nl_part.c +--- linux-2.6.39.orig/drivers/mtd/wrt160nl_part.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/mtd/wrt160nl_part.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,181 @@ ++/* ++ * Copyright (C) 2009 Christian Daniel <cd@maintech.de> ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * 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 ++ * ++ * TRX flash partition table. ++ * Based on ar7 map by Felix Fietkau <nbd@openwrt.org> ++ * ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/slab.h> ++#include <linux/vmalloc.h> ++ ++#include <linux/mtd/mtd.h> ++#include <linux/mtd/partitions.h> ++ ++struct cybertan_header { ++ char magic[4]; ++ u8 res1[4]; ++ char fw_date[3]; ++ char fw_ver[3]; ++ char id[4]; ++ char hw_ver; ++ char unused; ++ u8 flags[2]; ++ u8 res2[10]; ++}; ++ ++#define TRX_PARTS 6 ++#define TRX_MAGIC 0x30524448 ++#define TRX_MAX_OFFSET 3 ++ ++struct trx_header { ++ uint32_t magic; /* "HDR0" */ ++ uint32_t len; /* Length of file including header */ ++ uint32_t crc32; /* 32-bit CRC from flag_version to end of file */ ++ uint32_t flag_version; /* 0:15 flags, 16:31 version */ ++ uint32_t offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ ++}; ++ ++#define IH_MAGIC 0x27051956 /* Image Magic Number */ ++#define IH_NMLEN 32 /* Image Name Length */ ++ ++struct uimage_header { ++ uint32_t ih_magic; /* Image Header Magic Number */ ++ uint32_t ih_hcrc; /* Image Header CRC Checksum */ ++ uint32_t ih_time; /* Image Creation Timestamp */ ++ uint32_t ih_size; /* Image Data Size */ ++ uint32_t ih_load; /* Data» Load Address */ ++ uint32_t ih_ep; /* Entry Point Address */ ++ uint32_t ih_dcrc; /* Image Data CRC Checksum */ ++ uint8_t ih_os; /* Operating System */ ++ uint8_t ih_arch; /* CPU architecture */ ++ uint8_t ih_type; /* Image Type */ ++ uint8_t ih_comp; /* Compression Type */ ++ uint8_t ih_name[IH_NMLEN]; /* Image Name */ ++}; ++ ++struct wrt160nl_header { ++ struct cybertan_header cybertan; ++ struct trx_header trx; ++ struct uimage_header uimage; ++} __attribute__ ((packed)); ++ ++static struct mtd_partition trx_parts[TRX_PARTS]; ++ ++static int wrt160nl_parse_partitions(struct mtd_info *master, ++ struct mtd_partition **pparts, ++ unsigned long origin) ++{ ++ struct wrt160nl_header *header; ++ struct trx_header *theader; ++ struct uimage_header *uheader; ++ size_t retlen; ++ unsigned int kernel_len; ++ int ret; ++ ++ header = vmalloc(sizeof(*header)); ++ if (!header) { ++ return -ENOMEM; ++ goto out; ++ } ++ ++ ret = master->read(master, 4 * master->erasesize, sizeof(*header), ++ &retlen, (void *) header); ++ if (ret) ++ goto free_hdr; ++ ++ if (retlen != sizeof(*header)) { ++ ret = -EIO; ++ goto free_hdr; ++ } ++ ++ if (strncmp(header->cybertan.magic, "NL16", 4) != 0) { ++ printk(KERN_NOTICE "%s: no WRT160NL signature found\n", ++ master->name); ++ goto free_hdr; ++ } ++ ++ theader = &header->trx; ++ if (le32_to_cpu(theader->magic) != TRX_MAGIC) { ++ printk(KERN_NOTICE "%s: no TRX header found\n", master->name); ++ goto free_hdr; ++ } ++ ++ uheader = &header->uimage; ++ if (uheader->ih_magic != IH_MAGIC) { ++ printk(KERN_NOTICE "%s: no uImage found\n", master->name); ++ goto free_hdr; ++ } ++ ++ kernel_len = le32_to_cpu(theader->offsets[1]) + sizeof(struct cybertan_header); ++ ++ trx_parts[0].name = "u-boot"; ++ trx_parts[0].offset = 0; ++ trx_parts[0].size = 4 * master->erasesize; ++ trx_parts[0].mask_flags = MTD_WRITEABLE; ++ ++ trx_parts[1].name = "kernel"; ++ trx_parts[1].offset = trx_parts[0].offset + trx_parts[0].size; ++ trx_parts[1].size = kernel_len; ++ trx_parts[1].mask_flags = 0; ++ ++ trx_parts[2].name = "rootfs"; ++ trx_parts[2].offset = trx_parts[1].offset + trx_parts[1].size; ++ trx_parts[2].size = master->size - 6 * master->erasesize - trx_parts[1].size; ++ trx_parts[2].mask_flags = 0; ++ ++ trx_parts[3].name = "nvram"; ++ trx_parts[3].offset = master->size - 2 * master->erasesize; ++ trx_parts[3].size = master->erasesize; ++ trx_parts[3].mask_flags = MTD_WRITEABLE; ++ ++ trx_parts[4].name = "art"; ++ trx_parts[4].offset = master->size - master->erasesize; ++ trx_parts[4].size = master->erasesize; ++ trx_parts[4].mask_flags = MTD_WRITEABLE; ++ ++ trx_parts[5].name = "firmware"; ++ trx_parts[5].offset = 4 * master->erasesize; ++ trx_parts[5].size = master->size - 6 * master->erasesize; ++ trx_parts[5].mask_flags = 0; ++ ++ *pparts = trx_parts; ++ ret = TRX_PARTS; ++ ++ free_hdr: ++ vfree(header); ++ out: ++ return ret; ++} ++ ++static struct mtd_part_parser wrt160nl_parser = { ++ .owner = THIS_MODULE, ++ .parse_fn = wrt160nl_parse_partitions, ++ .name = "wrt160nl", ++}; ++ ++static int __init wrt160nl_parser_init(void) ++{ ++ return register_mtd_parser(&wrt160nl_parser); ++} ++ ++module_init(wrt160nl_parser_init); ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Christian Daniel <cd@maintech.de>"); +diff -Nur linux-2.6.39.orig/drivers/net/Kconfig linux-2.6.39/drivers/net/Kconfig +--- linux-2.6.39.orig/drivers/net/Kconfig 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/net/Kconfig 2011-05-27 14:36:51.000000000 +0200 +@@ -2071,6 +2071,8 @@ + + The safe and default value for this is N. + ++source drivers/net/ag71xx/Kconfig ++ + config DL2K + tristate "DL2000/TC902x-based Gigabit Ethernet support" + depends on PCI +diff -Nur linux-2.6.39.orig/drivers/net/Makefile linux-2.6.39/drivers/net/Makefile +--- linux-2.6.39.orig/drivers/net/Makefile 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/net/Makefile 2011-05-27 14:36:51.000000000 +0200 +@@ -112,6 +112,7 @@ + # end link order section + # + ++obj-$(CONFIG_AG71XX) += ag71xx/ + obj-$(CONFIG_SUNDANCE) += sundance.o + obj-$(CONFIG_HAMACHI) += hamachi.o + obj-$(CONFIG_NET) += Space.o loopback.o +diff -Nur linux-2.6.39.orig/drivers/net/ag71xx/Kconfig linux-2.6.39/drivers/net/ag71xx/Kconfig +--- linux-2.6.39.orig/drivers/net/ag71xx/Kconfig 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/net/ag71xx/Kconfig 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,33 @@ ++config AG71XX ++ tristate "Atheros AR71xx built-in ethernet mac support" ++ depends on ATHEROS_AR71XX ++ select PHYLIB ++ help ++ If you wish to compile a kernel for AR71xx/91xx and enable ++ ethernet support, then you should always answer Y to this. ++ ++if AG71XX ++ ++config AG71XX_DEBUG ++ bool "Atheros AR71xx built-in ethernet driver debugging" ++ default n ++ help ++ Atheros AR71xx built-in ethernet driver debugging messages. ++ ++config AG71XX_DEBUG_FS ++ bool "Atheros AR71xx built-in ethernet driver debugfs support" ++ depends on DEBUG_FS ++ default n ++ help ++ Say Y, if you need access to various statistics provided by ++ the ag71xx driver. ++ ++config AG71XX_AR8216_SUPPORT ++ bool "special support for the Atheros AR8216 switch" ++ default n ++ default y if AR71XX_MACH_WNR2000 || AR71XX_MACH_MZK_W04NU ++ help ++ Say 'y' here if you want to enable special support for the ++ Atheros AR8216 switch found on some boards. ++ ++endif +diff -Nur linux-2.6.39.orig/drivers/net/ag71xx/Makefile linux-2.6.39/drivers/net/ag71xx/Makefile +--- linux-2.6.39.orig/drivers/net/ag71xx/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/net/ag71xx/Makefile 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,14 @@ ++# ++# Makefile for the Atheros AR71xx built-in ethernet macs ++# ++ ++ag71xx-y += ag71xx_main.o ++ag71xx-y += ag71xx_ethtool.o ++ag71xx-y += ag71xx_phy.o ++ag71xx-y += ag71xx_mdio.o ++ ++ag71xx-$(CONFIG_AG71XX_DEBUG_FS) += ag71xx_debugfs.o ++ag71xx-$(CONFIG_AG71XX_AR8216_SUPPORT) += ag71xx_ar8216.o ++ ++obj-$(CONFIG_AG71XX) += ag71xx.o ++ +diff -Nur linux-2.6.39.orig/drivers/net/ag71xx/ag71xx.h linux-2.6.39/drivers/net/ag71xx/ag71xx.h +--- linux-2.6.39.orig/drivers/net/ag71xx/ag71xx.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/net/ag71xx/ag71xx.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,500 @@ ++/* ++ * Atheros AR71xx built-in ethernet mac driver ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Based on Atheros' AG7100 driver ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#ifndef __AG71XX_H ++#define __AG71XX_H ++ ++#include <linux/kernel.h> ++#include <linux/version.h> ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/types.h> ++#include <linux/random.h> ++#include <linux/spinlock.h> ++#include <linux/interrupt.h> ++#include <linux/platform_device.h> ++#include <linux/ethtool.h> ++#include <linux/etherdevice.h> ++#include <linux/phy.h> ++#include <linux/skbuff.h> ++#include <linux/dma-mapping.h> ++#include <linux/workqueue.h> ++ ++#include <linux/bitops.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/platform.h> ++ ++#define ETH_FCS_LEN 4 ++ ++#define AG71XX_DRV_NAME "ag71xx" ++#define AG71XX_DRV_VERSION "0.5.35" ++ ++#define AG71XX_NAPI_WEIGHT 64 ++#define AG71XX_OOM_REFILL (1 + HZ/10) ++ ++#define AG71XX_INT_ERR (AG71XX_INT_RX_BE | AG71XX_INT_TX_BE) ++#define AG71XX_INT_TX (AG71XX_INT_TX_PS) ++#define AG71XX_INT_RX (AG71XX_INT_RX_PR | AG71XX_INT_RX_OF) ++ ++#define AG71XX_INT_POLL (AG71XX_INT_RX | AG71XX_INT_TX) ++#define AG71XX_INT_INIT (AG71XX_INT_ERR | AG71XX_INT_POLL) ++ ++#define AG71XX_TX_FIFO_LEN 2048 ++#define AG71XX_TX_MTU_LEN 1536 ++#define AG71XX_RX_PKT_RESERVE 64 ++#define AG71XX_RX_PKT_SIZE \ ++ (AG71XX_RX_PKT_RESERVE + ETH_HLEN + ETH_FRAME_LEN + ETH_FCS_LEN) ++ ++#define AG71XX_TX_RING_SIZE 64 ++#define AG71XX_TX_THRES_STOP (AG71XX_TX_RING_SIZE - 4) ++#define AG71XX_TX_THRES_WAKEUP \ ++ (AG71XX_TX_RING_SIZE - (AG71XX_TX_RING_SIZE / 4)) ++ ++#define AG71XX_RX_RING_SIZE 128 ++ ++#ifdef CONFIG_AG71XX_DEBUG ++#define DBG(fmt, args...) printk(KERN_DEBUG fmt, ## args) ++#else ++#define DBG(fmt, args...) do {} while (0) ++#endif ++ ++#define ag71xx_assert(_cond) \ ++do { \ ++ if (_cond) \ ++ break; \ ++ printk("%s,%d: assertion failed\n", __FILE__, __LINE__); \ ++ BUG(); \ ++} while (0) ++ ++struct ag71xx_desc { ++ u32 data; ++ u32 ctrl; ++#define DESC_EMPTY BIT(31) ++#define DESC_MORE BIT(24) ++#define DESC_PKTLEN_M 0xfff ++ u32 next; ++ u32 pad; ++} __attribute__((aligned(4))); ++ ++struct ag71xx_buf { ++ struct sk_buff *skb; ++ struct ag71xx_desc *desc; ++ dma_addr_t dma_addr; ++ u32 pad; ++}; ++ ++struct ag71xx_ring { ++ struct ag71xx_buf *buf; ++ u8 *descs_cpu; ++ dma_addr_t descs_dma; ++ unsigned int desc_size; ++ unsigned int curr; ++ unsigned int dirty; ++ unsigned int size; ++}; ++ ++struct ag71xx_mdio { ++ struct mii_bus *mii_bus; ++ int mii_irq[PHY_MAX_ADDR]; ++ void __iomem *mdio_base; ++ struct ag71xx_mdio_platform_data *pdata; ++}; ++ ++struct ag71xx_int_stats { ++ unsigned long rx_pr; ++ unsigned long rx_be; ++ unsigned long rx_of; ++ unsigned long tx_ps; ++ unsigned long tx_be; ++ unsigned long tx_ur; ++ unsigned long total; ++}; ++ ++struct ag71xx_napi_stats { ++ unsigned long napi_calls; ++ unsigned long rx_count; ++ unsigned long rx_packets; ++ unsigned long rx_packets_max; ++ unsigned long tx_count; ++ unsigned long tx_packets; ++ unsigned long tx_packets_max; ++ ++ unsigned long rx[AG71XX_NAPI_WEIGHT + 1]; ++ unsigned long tx[AG71XX_NAPI_WEIGHT + 1]; ++}; ++ ++struct ag71xx_debug { ++ struct dentry *debugfs_dir; ++ struct dentry *debugfs_int_stats; ++ struct dentry *debugfs_napi_stats; ++ ++ struct ag71xx_int_stats int_stats; ++ struct ag71xx_napi_stats napi_stats; ++}; ++ ++struct ag71xx { ++ void __iomem *mac_base; ++ void __iomem *mii_ctrl; ++ ++ spinlock_t lock; ++ struct platform_device *pdev; ++ struct net_device *dev; ++ struct napi_struct napi; ++ u32 msg_enable; ++ ++ struct ag71xx_ring rx_ring; ++ struct ag71xx_ring tx_ring; ++ ++ struct mii_bus *mii_bus; ++ struct phy_device *phy_dev; ++ ++ unsigned int link; ++ unsigned int speed; ++ int duplex; ++ ++ struct work_struct restart_work; ++ struct timer_list oom_timer; ++ ++#ifdef CONFIG_AG71XX_DEBUG_FS ++ struct ag71xx_debug debug; ++#endif ++}; ++ ++extern struct ethtool_ops ag71xx_ethtool_ops; ++void ag71xx_link_adjust(struct ag71xx *ag); ++ ++int ag71xx_mdio_driver_init(void) __init; ++void ag71xx_mdio_driver_exit(void); ++ ++int ag71xx_phy_connect(struct ag71xx *ag); ++void ag71xx_phy_disconnect(struct ag71xx *ag); ++void ag71xx_phy_start(struct ag71xx *ag); ++void ag71xx_phy_stop(struct ag71xx *ag); ++ ++static inline struct ag71xx_platform_data *ag71xx_get_pdata(struct ag71xx *ag) ++{ ++ return ag->pdev->dev.platform_data; ++} ++ ++static inline int ag71xx_desc_empty(struct ag71xx_desc *desc) ++{ ++ return ((desc->ctrl & DESC_EMPTY) != 0); ++} ++ ++static inline int ag71xx_desc_pktlen(struct ag71xx_desc *desc) ++{ ++ return (desc->ctrl & DESC_PKTLEN_M); ++} ++ ++/* Register offsets */ ++#define AG71XX_REG_MAC_CFG1 0x0000 ++#define AG71XX_REG_MAC_CFG2 0x0004 ++#define AG71XX_REG_MAC_IPG 0x0008 ++#define AG71XX_REG_MAC_HDX 0x000c ++#define AG71XX_REG_MAC_MFL 0x0010 ++#define AG71XX_REG_MII_CFG 0x0020 ++#define AG71XX_REG_MII_CMD 0x0024 ++#define AG71XX_REG_MII_ADDR 0x0028 ++#define AG71XX_REG_MII_CTRL 0x002c ++#define AG71XX_REG_MII_STATUS 0x0030 ++#define AG71XX_REG_MII_IND 0x0034 ++#define AG71XX_REG_MAC_IFCTL 0x0038 ++#define AG71XX_REG_MAC_ADDR1 0x0040 ++#define AG71XX_REG_MAC_ADDR2 0x0044 ++#define AG71XX_REG_FIFO_CFG0 0x0048 ++#define AG71XX_REG_FIFO_CFG1 0x004c ++#define AG71XX_REG_FIFO_CFG2 0x0050 ++#define AG71XX_REG_FIFO_CFG3 0x0054 ++#define AG71XX_REG_FIFO_CFG4 0x0058 ++#define AG71XX_REG_FIFO_CFG5 0x005c ++#define AG71XX_REG_FIFO_RAM0 0x0060 ++#define AG71XX_REG_FIFO_RAM1 0x0064 ++#define AG71XX_REG_FIFO_RAM2 0x0068 ++#define AG71XX_REG_FIFO_RAM3 0x006c ++#define AG71XX_REG_FIFO_RAM4 0x0070 ++#define AG71XX_REG_FIFO_RAM5 0x0074 ++#define AG71XX_REG_FIFO_RAM6 0x0078 ++#define AG71XX_REG_FIFO_RAM7 0x007c ++ ++#define AG71XX_REG_TX_CTRL 0x0180 ++#define AG71XX_REG_TX_DESC 0x0184 ++#define AG71XX_REG_TX_STATUS 0x0188 ++#define AG71XX_REG_RX_CTRL 0x018c ++#define AG71XX_REG_RX_DESC 0x0190 ++#define AG71XX_REG_RX_STATUS 0x0194 ++#define AG71XX_REG_INT_ENABLE 0x0198 ++#define AG71XX_REG_INT_STATUS 0x019c ++ ++#define MAC_CFG1_TXE BIT(0) /* Tx Enable */ ++#define MAC_CFG1_STX BIT(1) /* Synchronize Tx Enable */ ++#define MAC_CFG1_RXE BIT(2) /* Rx Enable */ ++#define MAC_CFG1_SRX BIT(3) /* Synchronize Rx Enable */ ++#define MAC_CFG1_TFC BIT(4) /* Tx Flow Control Enable */ ++#define MAC_CFG1_RFC BIT(5) /* Rx Flow Control Enable */ ++#define MAC_CFG1_LB BIT(8) /* Loopback mode */ ++#define MAC_CFG1_SR BIT(31) /* Soft Reset */ ++ ++#define MAC_CFG2_FDX BIT(0) ++#define MAC_CFG2_CRC_EN BIT(1) ++#define MAC_CFG2_PAD_CRC_EN BIT(2) ++#define MAC_CFG2_LEN_CHECK BIT(4) ++#define MAC_CFG2_HUGE_FRAME_EN BIT(5) ++#define MAC_CFG2_IF_1000 BIT(9) ++#define MAC_CFG2_IF_10_100 BIT(8) ++ ++#define FIFO_CFG0_WTM BIT(0) /* Watermark Module */ ++#define FIFO_CFG0_RXS BIT(1) /* Rx System Module */ ++#define FIFO_CFG0_RXF BIT(2) /* Rx Fabric Module */ ++#define FIFO_CFG0_TXS BIT(3) /* Tx System Module */ ++#define FIFO_CFG0_TXF BIT(4) /* Tx Fabric Module */ ++#define FIFO_CFG0_ALL (FIFO_CFG0_WTM | FIFO_CFG0_RXS | FIFO_CFG0_RXF \ ++ | FIFO_CFG0_TXS | FIFO_CFG0_TXF) ++ ++#define FIFO_CFG0_ENABLE_SHIFT 8 ++ ++#define FIFO_CFG4_DE BIT(0) /* Drop Event */ ++#define FIFO_CFG4_DV BIT(1) /* RX_DV Event */ ++#define FIFO_CFG4_FC BIT(2) /* False Carrier */ ++#define FIFO_CFG4_CE BIT(3) /* Code Error */ ++#define FIFO_CFG4_CR BIT(4) /* CRC error */ ++#define FIFO_CFG4_LM BIT(5) /* Length Mismatch */ ++#define FIFO_CFG4_LO BIT(6) /* Length out of range */ ++#define FIFO_CFG4_OK BIT(7) /* Packet is OK */ ++#define FIFO_CFG4_MC BIT(8) /* Multicast Packet */ ++#define FIFO_CFG4_BC BIT(9) /* Broadcast Packet */ ++#define FIFO_CFG4_DR BIT(10) /* Dribble */ ++#define FIFO_CFG4_LE BIT(11) /* Long Event */ ++#define FIFO_CFG4_CF BIT(12) /* Control Frame */ ++#define FIFO_CFG4_PF BIT(13) /* Pause Frame */ ++#define FIFO_CFG4_UO BIT(14) /* Unsupported Opcode */ ++#define FIFO_CFG4_VT BIT(15) /* VLAN tag detected */ ++#define FIFO_CFG4_FT BIT(16) /* Frame Truncated */ ++#define FIFO_CFG4_UC BIT(17) /* Unicast Packet */ ++ ++#define FIFO_CFG5_DE BIT(0) /* Drop Event */ ++#define FIFO_CFG5_DV BIT(1) /* RX_DV Event */ ++#define FIFO_CFG5_FC BIT(2) /* False Carrier */ ++#define FIFO_CFG5_CE BIT(3) /* Code Error */ ++#define FIFO_CFG5_LM BIT(4) /* Length Mismatch */ ++#define FIFO_CFG5_LO BIT(5) /* Length Out of Range */ ++#define FIFO_CFG5_OK BIT(6) /* Packet is OK */ ++#define FIFO_CFG5_MC BIT(7) /* Multicast Packet */ ++#define FIFO_CFG5_BC BIT(8) /* Broadcast Packet */ ++#define FIFO_CFG5_DR BIT(9) /* Dribble */ ++#define FIFO_CFG5_CF BIT(10) /* Control Frame */ ++#define FIFO_CFG5_PF BIT(11) /* Pause Frame */ ++#define FIFO_CFG5_UO BIT(12) /* Unsupported Opcode */ ++#define FIFO_CFG5_VT BIT(13) /* VLAN tag detected */ ++#define FIFO_CFG5_LE BIT(14) /* Long Event */ ++#define FIFO_CFG5_FT BIT(15) /* Frame Truncated */ ++#define FIFO_CFG5_16 BIT(16) /* unknown */ ++#define FIFO_CFG5_17 BIT(17) /* unknown */ ++#define FIFO_CFG5_SF BIT(18) /* Short Frame */ ++#define FIFO_CFG5_BM BIT(19) /* Byte Mode */ ++ ++#define AG71XX_INT_TX_PS BIT(0) ++#define AG71XX_INT_TX_UR BIT(1) ++#define AG71XX_INT_TX_BE BIT(3) ++#define AG71XX_INT_RX_PR BIT(4) ++#define AG71XX_INT_RX_OF BIT(6) ++#define AG71XX_INT_RX_BE BIT(7) ++ ++#define MAC_IFCTL_SPEED BIT(16) ++ ++#define MII_CFG_CLK_DIV_4 0 ++#define MII_CFG_CLK_DIV_6 2 ++#define MII_CFG_CLK_DIV_8 3 ++#define MII_CFG_CLK_DIV_10 4 ++#define MII_CFG_CLK_DIV_14 5 ++#define MII_CFG_CLK_DIV_20 6 ++#define MII_CFG_CLK_DIV_28 7 ++#define MII_CFG_RESET BIT(31) ++ ++#define MII_CMD_WRITE 0x0 ++#define MII_CMD_READ 0x1 ++#define MII_ADDR_SHIFT 8 ++#define MII_IND_BUSY BIT(0) ++#define MII_IND_INVALID BIT(2) ++ ++#define TX_CTRL_TXE BIT(0) /* Tx Enable */ ++ ++#define TX_STATUS_PS BIT(0) /* Packet Sent */ ++#define TX_STATUS_UR BIT(1) /* Tx Underrun */ ++#define TX_STATUS_BE BIT(3) /* Bus Error */ ++ ++#define RX_CTRL_RXE BIT(0) /* Rx Enable */ ++ ++#define RX_STATUS_PR BIT(0) /* Packet Received */ ++#define RX_STATUS_OF BIT(2) /* Rx Overflow */ ++#define RX_STATUS_BE BIT(3) /* Bus Error */ ++ ++#define MII_CTRL_IF_MASK 3 ++#define MII_CTRL_SPEED_SHIFT 4 ++#define MII_CTRL_SPEED_MASK 3 ++#define MII_CTRL_SPEED_10 0 ++#define MII_CTRL_SPEED_100 1 ++#define MII_CTRL_SPEED_1000 2 ++ ++static inline void ag71xx_check_reg_offset(struct ag71xx *ag, unsigned reg) ++{ ++ switch (reg) { ++ case AG71XX_REG_MAC_CFG1 ... AG71XX_REG_MAC_MFL: ++ case AG71XX_REG_MAC_IFCTL ... AG71XX_REG_INT_STATUS: ++ break; ++ ++ default: ++ BUG(); ++ } ++} ++ ++static inline void ag71xx_wr(struct ag71xx *ag, unsigned reg, u32 value) ++{ ++ ag71xx_check_reg_offset(ag, reg); ++ ++ __raw_writel(value, ag->mac_base + reg); ++ /* flush write */ ++ (void) __raw_readl(ag->mac_base + reg); ++} ++ ++static inline u32 ag71xx_rr(struct ag71xx *ag, unsigned reg) ++{ ++ ag71xx_check_reg_offset(ag, reg); ++ ++ return __raw_readl(ag->mac_base + reg); ++} ++ ++static inline void ag71xx_sb(struct ag71xx *ag, unsigned reg, u32 mask) ++{ ++ void __iomem *r; ++ ++ ag71xx_check_reg_offset(ag, reg); ++ ++ r = ag->mac_base + reg; ++ __raw_writel(__raw_readl(r) | mask, r); ++ /* flush write */ ++ (void)__raw_readl(r); ++} ++ ++static inline void ag71xx_cb(struct ag71xx *ag, unsigned reg, u32 mask) ++{ ++ void __iomem *r; ++ ++ ag71xx_check_reg_offset(ag, reg); ++ ++ r = ag->mac_base + reg; ++ __raw_writel(__raw_readl(r) & ~mask, r); ++ /* flush write */ ++ (void) __raw_readl(r); ++} ++ ++static inline void ag71xx_int_enable(struct ag71xx *ag, u32 ints) ++{ ++ ag71xx_sb(ag, AG71XX_REG_INT_ENABLE, ints); ++} ++ ++static inline void ag71xx_int_disable(struct ag71xx *ag, u32 ints) ++{ ++ ag71xx_cb(ag, AG71XX_REG_INT_ENABLE, ints); ++} ++ ++static inline void ag71xx_mii_ctrl_wr(struct ag71xx *ag, u32 value) ++{ ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ ++ if (pdata->is_ar724x) ++ return; ++ ++ __raw_writel(value, ag->mii_ctrl); ++ ++ /* flush write */ ++ __raw_readl(ag->mii_ctrl); ++} ++ ++static inline u32 ag71xx_mii_ctrl_rr(struct ag71xx *ag) ++{ ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ ++ if (pdata->is_ar724x) ++ return 0xffffffff; ++ ++ return __raw_readl(ag->mii_ctrl); ++} ++ ++static void inline ag71xx_mii_ctrl_set_if(struct ag71xx *ag, ++ unsigned int mii_if) ++{ ++ u32 t; ++ ++ t = ag71xx_mii_ctrl_rr(ag); ++ t &= ~(MII_CTRL_IF_MASK); ++ t |= (mii_if & MII_CTRL_IF_MASK); ++ ag71xx_mii_ctrl_wr(ag, t); ++} ++ ++static void inline ag71xx_mii_ctrl_set_speed(struct ag71xx *ag, ++ unsigned int speed) ++{ ++ u32 t; ++ ++ t = ag71xx_mii_ctrl_rr(ag); ++ t &= ~(MII_CTRL_SPEED_MASK << MII_CTRL_SPEED_SHIFT); ++ t |= (speed & MII_CTRL_SPEED_MASK) << MII_CTRL_SPEED_SHIFT; ++ ag71xx_mii_ctrl_wr(ag, t); ++} ++ ++#ifdef CONFIG_AG71XX_AR8216_SUPPORT ++void ag71xx_add_ar8216_header(struct ag71xx *ag, struct sk_buff *skb); ++int ag71xx_remove_ar8216_header(struct ag71xx *ag, struct sk_buff *skb, ++ int pktlen); ++static inline int ag71xx_has_ar8216(struct ag71xx *ag) ++{ ++ return ag71xx_get_pdata(ag)->has_ar8216; ++} ++#else ++static inline void ag71xx_add_ar8216_header(struct ag71xx *ag, ++ struct sk_buff *skb) ++{ ++} ++ ++static inline int ag71xx_remove_ar8216_header(struct ag71xx *ag, ++ struct sk_buff *skb, ++ int pktlen) ++{ ++ return 0; ++} ++static inline int ag71xx_has_ar8216(struct ag71xx *ag) ++{ ++ return 0; ++} ++#endif ++ ++#ifdef CONFIG_AG71XX_DEBUG_FS ++int ag71xx_debugfs_root_init(void); ++void ag71xx_debugfs_root_exit(void); ++int ag71xx_debugfs_init(struct ag71xx *ag); ++void ag71xx_debugfs_exit(struct ag71xx *ag); ++void ag71xx_debugfs_update_int_stats(struct ag71xx *ag, u32 status); ++void ag71xx_debugfs_update_napi_stats(struct ag71xx *ag, int rx, int tx); ++#else ++static inline int ag71xx_debugfs_root_init(void) { return 0; } ++static inline void ag71xx_debugfs_root_exit(void) {} ++static inline int ag71xx_debugfs_init(struct ag71xx *ag) { return 0; } ++static inline void ag71xx_debugfs_exit(struct ag71xx *ag) {} ++static inline void ag71xx_debugfs_update_int_stats(struct ag71xx *ag, ++ u32 status) {} ++static inline void ag71xx_debugfs_update_napi_stats(struct ag71xx *ag, ++ int rx, int tx) {} ++#endif /* CONFIG_AG71XX_DEBUG_FS */ ++ ++#endif /* _AG71XX_H */ +diff -Nur linux-2.6.39.orig/drivers/net/ag71xx/ag71xx_ar8216.c linux-2.6.39/drivers/net/ag71xx/ag71xx_ar8216.c +--- linux-2.6.39.orig/drivers/net/ag71xx/ag71xx_ar8216.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/net/ag71xx/ag71xx_ar8216.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,44 @@ ++/* ++ * Atheros AR71xx built-in ethernet mac driver ++ * Special support for the Atheros ar8216 switch chip ++ * ++ * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * Based on Atheros' AG7100 driver ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include "ag71xx.h" ++ ++#define AR8216_PACKET_TYPE_MASK 0xf ++#define AR8216_PACKET_TYPE_NORMAL 0 ++ ++#define AR8216_HEADER_LEN 2 ++ ++void ag71xx_add_ar8216_header(struct ag71xx *ag, struct sk_buff *skb) ++{ ++ skb_push(skb, AR8216_HEADER_LEN); ++ skb->data[0] = 0x10; ++ skb->data[1] = 0x80; ++} ++ ++int ag71xx_remove_ar8216_header(struct ag71xx *ag, struct sk_buff *skb, ++ int pktlen) ++{ ++ u8 type; ++ ++ type = skb->data[1] & AR8216_PACKET_TYPE_MASK; ++ switch (type) { ++ case AR8216_PACKET_TYPE_NORMAL: ++ break; ++ ++ default: ++ return -EINVAL; ++ } ++ ++ skb_pull(skb, AR8216_HEADER_LEN); ++ return 0; ++} +diff -Nur linux-2.6.39.orig/drivers/net/ag71xx/ag71xx_debugfs.c linux-2.6.39/drivers/net/ag71xx/ag71xx_debugfs.c +--- linux-2.6.39.orig/drivers/net/ag71xx/ag71xx_debugfs.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/net/ag71xx/ag71xx_debugfs.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,197 @@ ++/* ++ * Atheros AR71xx built-in ethernet mac driver ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Based on Atheros' AG7100 driver ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/debugfs.h> ++ ++#include "ag71xx.h" ++ ++static struct dentry *ag71xx_debugfs_root; ++ ++static int ag71xx_debugfs_generic_open(struct inode *inode, struct file *file) ++{ ++ file->private_data = inode->i_private; ++ return 0; ++} ++ ++void ag71xx_debugfs_update_int_stats(struct ag71xx *ag, u32 status) ++{ ++ if (status) ++ ag->debug.int_stats.total++; ++ if (status & AG71XX_INT_TX_PS) ++ ag->debug.int_stats.tx_ps++; ++ if (status & AG71XX_INT_TX_UR) ++ ag->debug.int_stats.tx_ur++; ++ if (status & AG71XX_INT_TX_BE) ++ ag->debug.int_stats.tx_be++; ++ if (status & AG71XX_INT_RX_PR) ++ ag->debug.int_stats.rx_pr++; ++ if (status & AG71XX_INT_RX_OF) ++ ag->debug.int_stats.rx_of++; ++ if (status & AG71XX_INT_RX_BE) ++ ag->debug.int_stats.rx_be++; ++} ++ ++static ssize_t read_file_int_stats(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++#define PR_INT_STAT(_label, _field) \ ++ len += snprintf(buf + len, sizeof(buf) - len, \ ++ "%20s: %10lu\n", _label, ag->debug.int_stats._field); ++ ++ struct ag71xx *ag = file->private_data; ++ char buf[256]; ++ unsigned int len = 0; ++ ++ PR_INT_STAT("TX Packet Sent", tx_ps); ++ PR_INT_STAT("TX Underrun", tx_ur); ++ PR_INT_STAT("TX Bus Error", tx_be); ++ PR_INT_STAT("RX Packet Received", rx_pr); ++ PR_INT_STAT("RX Overflow", rx_of); ++ PR_INT_STAT("RX Bus Error", rx_be); ++ len += snprintf(buf + len, sizeof(buf) - len, "\n"); ++ PR_INT_STAT("Total", total); ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++#undef PR_INT_STAT ++} ++ ++static const struct file_operations ag71xx_fops_int_stats = { ++ .open = ag71xx_debugfs_generic_open, ++ .read = read_file_int_stats, ++ .owner = THIS_MODULE ++}; ++ ++void ag71xx_debugfs_update_napi_stats(struct ag71xx *ag, int rx, int tx) ++{ ++ struct ag71xx_napi_stats *stats = &ag->debug.napi_stats; ++ ++ if (rx) { ++ stats->rx_count++; ++ stats->rx_packets += rx; ++ if (rx <= AG71XX_NAPI_WEIGHT) ++ stats->rx[rx]++; ++ if (rx > stats->rx_packets_max) ++ stats->rx_packets_max = rx; ++ } ++ ++ if (tx) { ++ stats->tx_count++; ++ stats->tx_packets += tx; ++ if (tx <= AG71XX_NAPI_WEIGHT) ++ stats->tx[tx]++; ++ if (tx > stats->tx_packets_max) ++ stats->tx_packets_max = tx; ++ } ++} ++ ++static ssize_t read_file_napi_stats(struct file *file, char __user *user_buf, ++ size_t count, loff_t *ppos) ++{ ++ struct ag71xx *ag = file->private_data; ++ struct ag71xx_napi_stats *stats = &ag->debug.napi_stats; ++ char buf[2048]; ++ unsigned int len = 0; ++ unsigned long rx_avg = 0; ++ unsigned long tx_avg = 0; ++ int i; ++ ++ if (stats->rx_count) ++ rx_avg = stats->rx_packets / stats->rx_count; ++ ++ if (stats->tx_count) ++ tx_avg = stats->tx_packets / stats->tx_count; ++ ++ len += snprintf(buf + len, sizeof(buf) - len, "%3s %10s %10s\n", ++ "len", "rx", "tx"); ++ ++ for (i = 1; i <= AG71XX_NAPI_WEIGHT; i++) ++ len += snprintf(buf + len, sizeof(buf) - len, ++ "%3d: %10lu %10lu\n", ++ i, stats->rx[i], stats->tx[i]); ++ ++ len += snprintf(buf + len, sizeof(buf) - len, "\n"); ++ ++ len += snprintf(buf + len, sizeof(buf) - len, "%3s: %10lu %10lu\n", ++ "sum", stats->rx_count, stats->tx_count); ++ len += snprintf(buf + len, sizeof(buf) - len, "%3s: %10lu %10lu\n", ++ "avg", rx_avg, tx_avg); ++ len += snprintf(buf + len, sizeof(buf) - len, "%3s: %10lu %10lu\n", ++ "max", stats->rx_packets_max, stats->tx_packets_max); ++ len += snprintf(buf + len, sizeof(buf) - len, "%3s: %10lu %10lu\n", ++ "pkt", stats->rx_packets, stats->tx_packets); ++ ++ return simple_read_from_buffer(user_buf, count, ppos, buf, len); ++} ++ ++static const struct file_operations ag71xx_fops_napi_stats = { ++ .open = ag71xx_debugfs_generic_open, ++ .read = read_file_napi_stats, ++ .owner = THIS_MODULE ++}; ++ ++void ag71xx_debugfs_exit(struct ag71xx *ag) ++{ ++ debugfs_remove(ag->debug.debugfs_napi_stats); ++ debugfs_remove(ag->debug.debugfs_int_stats); ++ debugfs_remove(ag->debug.debugfs_dir); ++} ++ ++int ag71xx_debugfs_init(struct ag71xx *ag) ++{ ++ ag->debug.debugfs_dir = debugfs_create_dir(ag->dev->name, ++ ag71xx_debugfs_root); ++ if (!ag->debug.debugfs_dir) ++ goto err; ++ ++ ag->debug.debugfs_int_stats = ++ debugfs_create_file("int_stats", ++ S_IRUGO, ++ ag->debug.debugfs_dir, ++ ag, ++ &ag71xx_fops_int_stats); ++ if (!ag->debug.debugfs_int_stats) ++ goto err; ++ ++ ag->debug.debugfs_napi_stats = ++ debugfs_create_file("napi_stats", ++ S_IRUGO, ++ ag->debug.debugfs_dir, ++ ag, ++ &ag71xx_fops_napi_stats); ++ if (!ag->debug.debugfs_napi_stats) ++ goto err; ++ ++ return 0; ++ ++ err: ++ ag71xx_debugfs_exit(ag); ++ return -ENOMEM; ++} ++ ++int ag71xx_debugfs_root_init(void) ++{ ++ if (ag71xx_debugfs_root) ++ return -EBUSY; ++ ++ ag71xx_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); ++ if (!ag71xx_debugfs_root) ++ return -ENOENT; ++ ++ return 0; ++} ++ ++void ag71xx_debugfs_root_exit(void) ++{ ++ debugfs_remove(ag71xx_debugfs_root); ++ ag71xx_debugfs_root = NULL; ++} +diff -Nur linux-2.6.39.orig/drivers/net/ag71xx/ag71xx_ethtool.c linux-2.6.39/drivers/net/ag71xx/ag71xx_ethtool.c +--- linux-2.6.39.orig/drivers/net/ag71xx/ag71xx_ethtool.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/net/ag71xx/ag71xx_ethtool.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,71 @@ ++/* ++ * Atheros AR71xx built-in ethernet mac driver ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Based on Atheros' AG7100 driver ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include "ag71xx.h" ++ ++static int ag71xx_ethtool_get_settings(struct net_device *dev, ++ struct ethtool_cmd *cmd) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ struct phy_device *phydev = ag->phy_dev; ++ ++ if (!phydev) ++ return -ENODEV; ++ ++ return phy_ethtool_gset(phydev, cmd); ++} ++ ++static int ag71xx_ethtool_set_settings(struct net_device *dev, ++ struct ethtool_cmd *cmd) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ struct phy_device *phydev = ag->phy_dev; ++ ++ if (!phydev) ++ return -ENODEV; ++ ++ return phy_ethtool_sset(phydev, cmd); ++} ++ ++static void ag71xx_ethtool_get_drvinfo(struct net_device *dev, ++ struct ethtool_drvinfo *info) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ ++ strcpy(info->driver, ag->pdev->dev.driver->name); ++ strcpy(info->version, AG71XX_DRV_VERSION); ++ strcpy(info->bus_info, dev_name(&ag->pdev->dev)); ++} ++ ++static u32 ag71xx_ethtool_get_msglevel(struct net_device *dev) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ ++ return ag->msg_enable; ++} ++ ++static void ag71xx_ethtool_set_msglevel(struct net_device *dev, u32 msg_level) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ ++ ag->msg_enable = msg_level; ++} ++ ++struct ethtool_ops ag71xx_ethtool_ops = { ++ .set_settings = ag71xx_ethtool_set_settings, ++ .get_settings = ag71xx_ethtool_get_settings, ++ .get_drvinfo = ag71xx_ethtool_get_drvinfo, ++ .get_msglevel = ag71xx_ethtool_get_msglevel, ++ .set_msglevel = ag71xx_ethtool_set_msglevel, ++ .get_link = ethtool_op_get_link, ++}; +diff -Nur linux-2.6.39.orig/drivers/net/ag71xx/ag71xx_main.c linux-2.6.39/drivers/net/ag71xx/ag71xx_main.c +--- linux-2.6.39.orig/drivers/net/ag71xx/ag71xx_main.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/net/ag71xx/ag71xx_main.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,1184 @@ ++/* ++ * Atheros AR71xx built-in ethernet mac driver ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Based on Atheros' AG7100 driver ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include "ag71xx.h" ++ ++#define AG71XX_DEFAULT_MSG_ENABLE \ ++ ( NETIF_MSG_DRV \ ++ | NETIF_MSG_PROBE \ ++ | NETIF_MSG_LINK \ ++ | NETIF_MSG_TIMER \ ++ | NETIF_MSG_IFDOWN \ ++ | NETIF_MSG_IFUP \ ++ | NETIF_MSG_RX_ERR \ ++ | NETIF_MSG_TX_ERR ) ++ ++static int ag71xx_msg_level = -1; ++ ++module_param_named(msg_level, ag71xx_msg_level, int, 0); ++MODULE_PARM_DESC(msg_level, "Message level (-1=defaults,0=none,...,16=all)"); ++ ++static void ag71xx_dump_dma_regs(struct ag71xx *ag) ++{ ++ DBG("%s: dma_tx_ctrl=%08x, dma_tx_desc=%08x, dma_tx_status=%08x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_TX_CTRL), ++ ag71xx_rr(ag, AG71XX_REG_TX_DESC), ++ ag71xx_rr(ag, AG71XX_REG_TX_STATUS)); ++ ++ DBG("%s: dma_rx_ctrl=%08x, dma_rx_desc=%08x, dma_rx_status=%08x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_RX_CTRL), ++ ag71xx_rr(ag, AG71XX_REG_RX_DESC), ++ ag71xx_rr(ag, AG71XX_REG_RX_STATUS)); ++} ++ ++static void ag71xx_dump_regs(struct ag71xx *ag) ++{ ++ DBG("%s: mac_cfg1=%08x, mac_cfg2=%08x, ipg=%08x, hdx=%08x, mfl=%08x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_MAC_CFG1), ++ ag71xx_rr(ag, AG71XX_REG_MAC_CFG2), ++ ag71xx_rr(ag, AG71XX_REG_MAC_IPG), ++ ag71xx_rr(ag, AG71XX_REG_MAC_HDX), ++ ag71xx_rr(ag, AG71XX_REG_MAC_MFL)); ++ DBG("%s: mac_ifctl=%08x, mac_addr1=%08x, mac_addr2=%08x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL), ++ ag71xx_rr(ag, AG71XX_REG_MAC_ADDR1), ++ ag71xx_rr(ag, AG71XX_REG_MAC_ADDR2)); ++ DBG("%s: fifo_cfg0=%08x, fifo_cfg1=%08x, fifo_cfg2=%08x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG0), ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG1), ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG2)); ++ DBG("%s: fifo_cfg3=%08x, fifo_cfg4=%08x, fifo_cfg5=%08x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG3), ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG4), ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5)); ++} ++ ++static inline void ag71xx_dump_intr(struct ag71xx *ag, char *label, u32 intr) ++{ ++ DBG("%s: %s intr=%08x %s%s%s%s%s%s\n", ++ ag->dev->name, label, intr, ++ (intr & AG71XX_INT_TX_PS) ? "TXPS " : "", ++ (intr & AG71XX_INT_TX_UR) ? "TXUR " : "", ++ (intr & AG71XX_INT_TX_BE) ? "TXBE " : "", ++ (intr & AG71XX_INT_RX_PR) ? "RXPR " : "", ++ (intr & AG71XX_INT_RX_OF) ? "RXOF " : "", ++ (intr & AG71XX_INT_RX_BE) ? "RXBE " : ""); ++} ++ ++static void ag71xx_ring_free(struct ag71xx_ring *ring) ++{ ++ kfree(ring->buf); ++ ++ if (ring->descs_cpu) ++ dma_free_coherent(NULL, ring->size * ring->desc_size, ++ ring->descs_cpu, ring->descs_dma); ++} ++ ++static int ag71xx_ring_alloc(struct ag71xx_ring *ring, unsigned int size) ++{ ++ int err; ++ int i; ++ ++ ring->desc_size = sizeof(struct ag71xx_desc); ++ if (ring->desc_size % cache_line_size()) { ++ DBG("ag71xx: ring %p, desc size %u rounded to %u\n", ++ ring, ring->desc_size, ++ roundup(ring->desc_size, cache_line_size())); ++ ring->desc_size = roundup(ring->desc_size, cache_line_size()); ++ } ++ ++ ring->descs_cpu = dma_alloc_coherent(NULL, size * ring->desc_size, ++ &ring->descs_dma, GFP_ATOMIC); ++ if (!ring->descs_cpu) { ++ err = -ENOMEM; ++ goto err; ++ } ++ ++ ring->size = size; ++ ++ ring->buf = kzalloc(size * sizeof(*ring->buf), GFP_KERNEL); ++ if (!ring->buf) { ++ err = -ENOMEM; ++ goto err; ++ } ++ ++ for (i = 0; i < size; i++) { ++ ring->buf[i].desc = (struct ag71xx_desc *)&ring->descs_cpu[i * ring->desc_size]; ++ DBG("ag71xx: ring %p, desc %d at %p\n", ++ ring, i, ring->buf[i].desc); ++ } ++ ++ return 0; ++ ++ err: ++ return err; ++} ++ ++static void ag71xx_ring_tx_clean(struct ag71xx *ag) ++{ ++ struct ag71xx_ring *ring = &ag->tx_ring; ++ struct net_device *dev = ag->dev; ++ ++ while (ring->curr != ring->dirty) { ++ u32 i = ring->dirty % AG71XX_TX_RING_SIZE; ++ ++ if (!ag71xx_desc_empty(ring->buf[i].desc)) { ++ ring->buf[i].desc->ctrl = 0; ++ dev->stats.tx_errors++; ++ } ++ ++ if (ring->buf[i].skb) ++ dev_kfree_skb_any(ring->buf[i].skb); ++ ++ ring->buf[i].skb = NULL; ++ ++ ring->dirty++; ++ } ++ ++ /* flush descriptors */ ++ wmb(); ++ ++} ++ ++static void ag71xx_ring_tx_init(struct ag71xx *ag) ++{ ++ struct ag71xx_ring *ring = &ag->tx_ring; ++ int i; ++ ++ for (i = 0; i < AG71XX_TX_RING_SIZE; i++) { ++ ring->buf[i].desc->next = (u32) (ring->descs_dma + ++ ring->desc_size * ((i + 1) % AG71XX_TX_RING_SIZE)); ++ ++ ring->buf[i].desc->ctrl = DESC_EMPTY; ++ ring->buf[i].skb = NULL; ++ } ++ ++ /* flush descriptors */ ++ wmb(); ++ ++ ring->curr = 0; ++ ring->dirty = 0; ++} ++ ++static void ag71xx_ring_rx_clean(struct ag71xx *ag) ++{ ++ struct ag71xx_ring *ring = &ag->rx_ring; ++ int i; ++ ++ if (!ring->buf) ++ return; ++ ++ for (i = 0; i < AG71XX_RX_RING_SIZE; i++) ++ if (ring->buf[i].skb) { ++ dma_unmap_single(&ag->dev->dev, ring->buf[i].dma_addr, ++ AG71XX_RX_PKT_SIZE, DMA_FROM_DEVICE); ++ kfree_skb(ring->buf[i].skb); ++ } ++} ++ ++static int ag71xx_rx_reserve(struct ag71xx *ag) ++{ ++ int reserve = 0; ++ ++ if (ag71xx_get_pdata(ag)->is_ar724x) { ++ if (!ag71xx_has_ar8216(ag)) ++ reserve = 2; ++ ++ if (ag->phy_dev) ++ reserve += 4 - (ag->phy_dev->pkt_align % 4); ++ ++ reserve %= 4; ++ } ++ ++ return reserve + AG71XX_RX_PKT_RESERVE; ++} ++ ++ ++static int ag71xx_ring_rx_init(struct ag71xx *ag) ++{ ++ struct ag71xx_ring *ring = &ag->rx_ring; ++ unsigned int reserve = ag71xx_rx_reserve(ag); ++ unsigned int i; ++ int ret; ++ ++ ret = 0; ++ for (i = 0; i < AG71XX_RX_RING_SIZE; i++) { ++ ring->buf[i].desc->next = (u32) (ring->descs_dma + ++ ring->desc_size * ((i + 1) % AG71XX_RX_RING_SIZE)); ++ ++ DBG("ag71xx: RX desc at %p, next is %08x\n", ++ ring->buf[i].desc, ++ ring->buf[i].desc->next); ++ } ++ ++ for (i = 0; i < AG71XX_RX_RING_SIZE; i++) { ++ struct sk_buff *skb; ++ dma_addr_t dma_addr; ++ ++ skb = dev_alloc_skb(AG71XX_RX_PKT_SIZE + reserve); ++ if (!skb) { ++ ret = -ENOMEM; ++ break; ++ } ++ ++ skb->dev = ag->dev; ++ skb_reserve(skb, reserve); ++ ++ dma_addr = dma_map_single(&ag->dev->dev, skb->data, ++ AG71XX_RX_PKT_SIZE, ++ DMA_FROM_DEVICE); ++ ring->buf[i].skb = skb; ++ ring->buf[i].dma_addr = dma_addr; ++ ring->buf[i].desc->data = (u32) dma_addr; ++ ring->buf[i].desc->ctrl = DESC_EMPTY; ++ } ++ ++ /* flush descriptors */ ++ wmb(); ++ ++ ring->curr = 0; ++ ring->dirty = 0; ++ ++ return ret; ++} ++ ++static int ag71xx_ring_rx_refill(struct ag71xx *ag) ++{ ++ struct ag71xx_ring *ring = &ag->rx_ring; ++ unsigned int reserve = ag71xx_rx_reserve(ag); ++ unsigned int count; ++ ++ count = 0; ++ for (; ring->curr - ring->dirty > 0; ring->dirty++) { ++ unsigned int i; ++ ++ i = ring->dirty % AG71XX_RX_RING_SIZE; ++ ++ if (ring->buf[i].skb == NULL) { ++ dma_addr_t dma_addr; ++ struct sk_buff *skb; ++ ++ skb = dev_alloc_skb(AG71XX_RX_PKT_SIZE + reserve); ++ if (skb == NULL) ++ break; ++ ++ skb_reserve(skb, reserve); ++ skb->dev = ag->dev; ++ ++ dma_addr = dma_map_single(&ag->dev->dev, skb->data, ++ AG71XX_RX_PKT_SIZE, ++ DMA_FROM_DEVICE); ++ ++ ring->buf[i].skb = skb; ++ ring->buf[i].dma_addr = dma_addr; ++ ring->buf[i].desc->data = (u32) dma_addr; ++ } ++ ++ ring->buf[i].desc->ctrl = DESC_EMPTY; ++ count++; ++ } ++ ++ /* flush descriptors */ ++ wmb(); ++ ++ DBG("%s: %u rx descriptors refilled\n", ag->dev->name, count); ++ ++ return count; ++} ++ ++static int ag71xx_rings_init(struct ag71xx *ag) ++{ ++ int ret; ++ ++ ret = ag71xx_ring_alloc(&ag->tx_ring, AG71XX_TX_RING_SIZE); ++ if (ret) ++ return ret; ++ ++ ag71xx_ring_tx_init(ag); ++ ++ ret = ag71xx_ring_alloc(&ag->rx_ring, AG71XX_RX_RING_SIZE); ++ if (ret) ++ return ret; ++ ++ ret = ag71xx_ring_rx_init(ag); ++ return ret; ++} ++ ++static void ag71xx_rings_cleanup(struct ag71xx *ag) ++{ ++ ag71xx_ring_rx_clean(ag); ++ ag71xx_ring_free(&ag->rx_ring); ++ ++ ag71xx_ring_tx_clean(ag); ++ ag71xx_ring_free(&ag->tx_ring); ++} ++ ++static unsigned char *ag71xx_speed_str(struct ag71xx *ag) ++{ ++ switch (ag->speed) { ++ case SPEED_1000: ++ return "1000"; ++ case SPEED_100: ++ return "100"; ++ case SPEED_10: ++ return "10"; ++ } ++ ++ return "?"; ++} ++ ++void ag71xx_link_adjust(struct ag71xx *ag) ++{ ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ u32 cfg2; ++ u32 ifctl; ++ u32 fifo5; ++ u32 mii_speed; ++ ++ if (!ag->link) { ++ netif_carrier_off(ag->dev); ++ if (netif_msg_link(ag)) ++ printk(KERN_INFO "%s: link down\n", ag->dev->name); ++ return; ++ } ++ ++ cfg2 = ag71xx_rr(ag, AG71XX_REG_MAC_CFG2); ++ cfg2 &= ~(MAC_CFG2_IF_1000 | MAC_CFG2_IF_10_100 | MAC_CFG2_FDX); ++ cfg2 |= (ag->duplex) ? MAC_CFG2_FDX : 0; ++ ++ ifctl = ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL); ++ ifctl &= ~(MAC_IFCTL_SPEED); ++ ++ fifo5 = ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5); ++ fifo5 &= ~FIFO_CFG5_BM; ++ ++ switch (ag->speed) { ++ case SPEED_1000: ++ mii_speed = MII_CTRL_SPEED_1000; ++ cfg2 |= MAC_CFG2_IF_1000; ++ fifo5 |= FIFO_CFG5_BM; ++ break; ++ case SPEED_100: ++ mii_speed = MII_CTRL_SPEED_100; ++ cfg2 |= MAC_CFG2_IF_10_100; ++ ifctl |= MAC_IFCTL_SPEED; ++ break; ++ case SPEED_10: ++ mii_speed = MII_CTRL_SPEED_10; ++ cfg2 |= MAC_CFG2_IF_10_100; ++ break; ++ default: ++ BUG(); ++ return; ++ } ++ ++ if (pdata->is_ar91xx) ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x00780fff); ++ else if (pdata->is_ar724x) ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, pdata->fifo_cfg3); ++ else ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG3, 0x008001ff); ++ ++ if (pdata->set_pll) ++ pdata->set_pll(ag->speed); ++ ++ ag71xx_mii_ctrl_set_speed(ag, mii_speed); ++ ++ ag71xx_wr(ag, AG71XX_REG_MAC_CFG2, cfg2); ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, fifo5); ++ ag71xx_wr(ag, AG71XX_REG_MAC_IFCTL, ifctl); ++ ++ netif_carrier_on(ag->dev); ++ if (netif_msg_link(ag)) ++ printk(KERN_INFO "%s: link up (%sMbps/%s duplex)\n", ++ ag->dev->name, ++ ag71xx_speed_str(ag), ++ (DUPLEX_FULL == ag->duplex) ? "Full" : "Half"); ++ ++ DBG("%s: fifo_cfg0=%#x, fifo_cfg1=%#x, fifo_cfg2=%#x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG0), ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG1), ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG2)); ++ ++ DBG("%s: fifo_cfg3=%#x, fifo_cfg4=%#x, fifo_cfg5=%#x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG3), ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG4), ++ ag71xx_rr(ag, AG71XX_REG_FIFO_CFG5)); ++ ++ DBG("%s: mac_cfg2=%#x, mac_ifctl=%#x, mii_ctrl=%#x\n", ++ ag->dev->name, ++ ag71xx_rr(ag, AG71XX_REG_MAC_CFG2), ++ ag71xx_rr(ag, AG71XX_REG_MAC_IFCTL), ++ ag71xx_mii_ctrl_rr(ag)); ++} ++ ++static void ag71xx_hw_set_macaddr(struct ag71xx *ag, unsigned char *mac) ++{ ++ u32 t; ++ ++ t = (((u32) mac[5]) << 24) | (((u32) mac[4]) << 16) ++ | (((u32) mac[3]) << 8) | ((u32) mac[2]); ++ ++ ag71xx_wr(ag, AG71XX_REG_MAC_ADDR1, t); ++ ++ t = (((u32) mac[1]) << 24) | (((u32) mac[0]) << 16); ++ ag71xx_wr(ag, AG71XX_REG_MAC_ADDR2, t); ++} ++ ++static void ag71xx_dma_reset(struct ag71xx *ag) ++{ ++ u32 val; ++ int i; ++ ++ ag71xx_dump_dma_regs(ag); ++ ++ /* stop RX and TX */ ++ ag71xx_wr(ag, AG71XX_REG_RX_CTRL, 0); ++ ag71xx_wr(ag, AG71XX_REG_TX_CTRL, 0); ++ ++ /* clear descriptor addresses */ ++ ag71xx_wr(ag, AG71XX_REG_TX_DESC, 0); ++ ag71xx_wr(ag, AG71XX_REG_RX_DESC, 0); ++ ++ /* clear pending RX/TX interrupts */ ++ for (i = 0; i < 256; i++) { ++ ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_PR); ++ ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_PS); ++ } ++ ++ /* clear pending errors */ ++ ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_BE | RX_STATUS_OF); ++ ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_BE | TX_STATUS_UR); ++ ++ val = ag71xx_rr(ag, AG71XX_REG_RX_STATUS); ++ if (val) ++ printk(KERN_ALERT "%s: unable to clear DMA Rx status: %08x\n", ++ ag->dev->name, val); ++ ++ val = ag71xx_rr(ag, AG71XX_REG_TX_STATUS); ++ ++ /* mask out reserved bits */ ++ val &= ~0xff000000; ++ ++ if (val) ++ printk(KERN_ALERT "%s: unable to clear DMA Tx status: %08x\n", ++ ag->dev->name, val); ++ ++ ag71xx_dump_dma_regs(ag); ++} ++ ++#define MAC_CFG1_INIT (MAC_CFG1_RXE | MAC_CFG1_TXE | \ ++ MAC_CFG1_SRX | MAC_CFG1_STX) ++ ++#define FIFO_CFG0_INIT (FIFO_CFG0_ALL << FIFO_CFG0_ENABLE_SHIFT) ++ ++#define FIFO_CFG4_INIT (FIFO_CFG4_DE | FIFO_CFG4_DV | FIFO_CFG4_FC | \ ++ FIFO_CFG4_CE | FIFO_CFG4_CR | FIFO_CFG4_LM | \ ++ FIFO_CFG4_LO | FIFO_CFG4_OK | FIFO_CFG4_MC | \ ++ FIFO_CFG4_BC | FIFO_CFG4_DR | FIFO_CFG4_LE | \ ++ FIFO_CFG4_CF | FIFO_CFG4_PF | FIFO_CFG4_UO | \ ++ FIFO_CFG4_VT) ++ ++#define FIFO_CFG5_INIT (FIFO_CFG5_DE | FIFO_CFG5_DV | FIFO_CFG5_FC | \ ++ FIFO_CFG5_CE | FIFO_CFG5_LO | FIFO_CFG5_OK | \ ++ FIFO_CFG5_MC | FIFO_CFG5_BC | FIFO_CFG5_DR | \ ++ FIFO_CFG5_CF | FIFO_CFG5_PF | FIFO_CFG5_VT | \ ++ FIFO_CFG5_LE | FIFO_CFG5_FT | FIFO_CFG5_16 | \ ++ FIFO_CFG5_17 | FIFO_CFG5_SF) ++ ++static void ag71xx_hw_init(struct ag71xx *ag) ++{ ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ ++ ag71xx_sb(ag, AG71XX_REG_MAC_CFG1, MAC_CFG1_SR); ++ udelay(20); ++ ++ ar71xx_device_stop(pdata->reset_bit); ++ mdelay(100); ++ ar71xx_device_start(pdata->reset_bit); ++ mdelay(100); ++ ++ /* setup MAC configuration registers */ ++ if (pdata->is_ar724x) ++ ag71xx_wr(ag, AG71XX_REG_MAC_CFG1, ++ MAC_CFG1_INIT | MAC_CFG1_TFC | MAC_CFG1_RFC); ++ else ++ ag71xx_wr(ag, AG71XX_REG_MAC_CFG1, MAC_CFG1_INIT); ++ ++ ag71xx_sb(ag, AG71XX_REG_MAC_CFG2, ++ MAC_CFG2_PAD_CRC_EN | MAC_CFG2_LEN_CHECK); ++ ++ /* setup max frame length */ ++ ag71xx_wr(ag, AG71XX_REG_MAC_MFL, AG71XX_TX_MTU_LEN); ++ ++ /* setup MII interface type */ ++ ag71xx_mii_ctrl_set_if(ag, pdata->mii_if); ++ ++ /* setup FIFO configuration registers */ ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG0, FIFO_CFG0_INIT); ++ if (pdata->is_ar724x) { ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, pdata->fifo_cfg1); ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, pdata->fifo_cfg2); ++ } else { ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG1, 0x0fff0000); ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG2, 0x00001fff); ++ } ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG4, FIFO_CFG4_INIT); ++ ag71xx_wr(ag, AG71XX_REG_FIFO_CFG5, FIFO_CFG5_INIT); ++ ++ ag71xx_dma_reset(ag); ++} ++ ++static void ag71xx_hw_start(struct ag71xx *ag) ++{ ++ /* start RX engine */ ++ ag71xx_wr(ag, AG71XX_REG_RX_CTRL, RX_CTRL_RXE); ++ ++ /* enable interrupts */ ++ ag71xx_wr(ag, AG71XX_REG_INT_ENABLE, AG71XX_INT_INIT); ++} ++ ++static void ag71xx_hw_stop(struct ag71xx *ag) ++{ ++ /* disable all interrupts */ ++ ag71xx_wr(ag, AG71XX_REG_INT_ENABLE, 0); ++ ++ ag71xx_dma_reset(ag); ++} ++ ++static int ag71xx_open(struct net_device *dev) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ int ret; ++ ++ ret = ag71xx_rings_init(ag); ++ if (ret) ++ goto err; ++ ++ napi_enable(&ag->napi); ++ ++ netif_carrier_off(dev); ++ ag71xx_phy_start(ag); ++ ++ ag71xx_wr(ag, AG71XX_REG_TX_DESC, ag->tx_ring.descs_dma); ++ ag71xx_wr(ag, AG71XX_REG_RX_DESC, ag->rx_ring.descs_dma); ++ ++ ag71xx_hw_set_macaddr(ag, dev->dev_addr); ++ ++ ag71xx_hw_start(ag); ++ ++ netif_start_queue(dev); ++ ++ return 0; ++ ++ err: ++ ag71xx_rings_cleanup(ag); ++ return ret; ++} ++ ++static int ag71xx_stop(struct net_device *dev) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ unsigned long flags; ++ ++ netif_carrier_off(dev); ++ ag71xx_phy_stop(ag); ++ ++ spin_lock_irqsave(&ag->lock, flags); ++ ++ netif_stop_queue(dev); ++ ++ ag71xx_hw_stop(ag); ++ ++ napi_disable(&ag->napi); ++ del_timer_sync(&ag->oom_timer); ++ ++ spin_unlock_irqrestore(&ag->lock, flags); ++ ++ ag71xx_rings_cleanup(ag); ++ ++ return 0; ++} ++ ++static netdev_tx_t ag71xx_hard_start_xmit(struct sk_buff *skb, ++ struct net_device *dev) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ struct ag71xx_ring *ring = &ag->tx_ring; ++ struct ag71xx_desc *desc; ++ dma_addr_t dma_addr; ++ int i; ++ ++ i = ring->curr % AG71XX_TX_RING_SIZE; ++ desc = ring->buf[i].desc; ++ ++ if (!ag71xx_desc_empty(desc)) ++ goto err_drop; ++ ++ if (ag71xx_has_ar8216(ag)) ++ ag71xx_add_ar8216_header(ag, skb); ++ ++ if (skb->len <= 0) { ++ DBG("%s: packet len is too small\n", ag->dev->name); ++ goto err_drop; ++ } ++ ++ dma_addr = dma_map_single(&dev->dev, skb->data, skb->len, ++ DMA_TO_DEVICE); ++ ++ ring->buf[i].skb = skb; ++ ++ /* setup descriptor fields */ ++ desc->data = (u32) dma_addr; ++ desc->ctrl = (skb->len & DESC_PKTLEN_M); ++ ++ /* flush descriptor */ ++ wmb(); ++ ++ ring->curr++; ++ if (ring->curr == (ring->dirty + AG71XX_TX_THRES_STOP)) { ++ DBG("%s: tx queue full\n", ag->dev->name); ++ netif_stop_queue(dev); ++ } ++ ++ DBG("%s: packet injected into TX queue\n", ag->dev->name); ++ ++ /* enable TX engine */ ++ ag71xx_wr(ag, AG71XX_REG_TX_CTRL, TX_CTRL_TXE); ++ ++ return NETDEV_TX_OK; ++ ++ err_drop: ++ dev->stats.tx_dropped++; ++ ++ dev_kfree_skb(skb); ++ return NETDEV_TX_OK; ++} ++ ++static int ag71xx_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ++{ ++ struct mii_ioctl_data *data = (struct mii_ioctl_data *) &ifr->ifr_data; ++ struct ag71xx *ag = netdev_priv(dev); ++ int ret; ++ ++ switch (cmd) { ++ case SIOCETHTOOL: ++ if (ag->phy_dev == NULL) ++ break; ++ ++ spin_lock_irq(&ag->lock); ++ ret = phy_ethtool_ioctl(ag->phy_dev, (void *) ifr->ifr_data); ++ spin_unlock_irq(&ag->lock); ++ return ret; ++ ++ case SIOCSIFHWADDR: ++ if (copy_from_user ++ (dev->dev_addr, ifr->ifr_data, sizeof(dev->dev_addr))) ++ return -EFAULT; ++ return 0; ++ ++ case SIOCGIFHWADDR: ++ if (copy_to_user ++ (ifr->ifr_data, dev->dev_addr, sizeof(dev->dev_addr))) ++ return -EFAULT; ++ return 0; ++ ++ case SIOCGMIIPHY: ++ case SIOCGMIIREG: ++ case SIOCSMIIREG: ++ if (ag->phy_dev == NULL) ++ break; ++ ++ return phy_mii_ioctl(ag->phy_dev, data, cmd); ++ ++ default: ++ break; ++ } ++ ++ return -EOPNOTSUPP; ++} ++ ++static void ag71xx_oom_timer_handler(unsigned long data) ++{ ++ struct net_device *dev = (struct net_device *) data; ++ struct ag71xx *ag = netdev_priv(dev); ++ ++ napi_schedule(&ag->napi); ++} ++ ++static void ag71xx_tx_timeout(struct net_device *dev) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ ++ if (netif_msg_tx_err(ag)) ++ printk(KERN_DEBUG "%s: tx timeout\n", ag->dev->name); ++ ++ schedule_work(&ag->restart_work); ++} ++ ++static void ag71xx_restart_work_func(struct work_struct *work) ++{ ++ struct ag71xx *ag = container_of(work, struct ag71xx, restart_work); ++ ++ ag71xx_stop(ag->dev); ++ ag71xx_open(ag->dev); ++} ++ ++static int ag71xx_tx_packets(struct ag71xx *ag) ++{ ++ struct ag71xx_ring *ring = &ag->tx_ring; ++ int sent; ++ ++ DBG("%s: processing TX ring\n", ag->dev->name); ++ ++ sent = 0; ++ while (ring->dirty != ring->curr) { ++ unsigned int i = ring->dirty % AG71XX_TX_RING_SIZE; ++ struct ag71xx_desc *desc = ring->buf[i].desc; ++ struct sk_buff *skb = ring->buf[i].skb; ++ ++ if (!ag71xx_desc_empty(desc)) ++ break; ++ ++ ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_PS); ++ ++ ag->dev->stats.tx_bytes += skb->len; ++ ag->dev->stats.tx_packets++; ++ ++ dev_kfree_skb_any(skb); ++ ring->buf[i].skb = NULL; ++ ++ ring->dirty++; ++ sent++; ++ } ++ ++ DBG("%s: %d packets sent out\n", ag->dev->name, sent); ++ ++ if ((ring->curr - ring->dirty) < AG71XX_TX_THRES_WAKEUP) ++ netif_wake_queue(ag->dev); ++ ++ return sent; ++} ++ ++static int ag71xx_rx_packets(struct ag71xx *ag, int limit) ++{ ++ struct net_device *dev = ag->dev; ++ struct ag71xx_ring *ring = &ag->rx_ring; ++ int done = 0; ++ ++ DBG("%s: rx packets, limit=%d, curr=%u, dirty=%u\n", ++ dev->name, limit, ring->curr, ring->dirty); ++ ++ while (done < limit) { ++ unsigned int i = ring->curr % AG71XX_RX_RING_SIZE; ++ struct ag71xx_desc *desc = ring->buf[i].desc; ++ struct sk_buff *skb; ++ int pktlen; ++ int err = 0; ++ ++ if (ag71xx_desc_empty(desc)) ++ break; ++ ++ if ((ring->dirty + AG71XX_RX_RING_SIZE) == ring->curr) { ++ ag71xx_assert(0); ++ break; ++ } ++ ++ ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_PR); ++ ++ skb = ring->buf[i].skb; ++ pktlen = ag71xx_desc_pktlen(desc); ++ pktlen -= ETH_FCS_LEN; ++ ++ dma_unmap_single(&dev->dev, ring->buf[i].dma_addr, ++ AG71XX_RX_PKT_SIZE, DMA_FROM_DEVICE); ++ ++ dev->last_rx = jiffies; ++ dev->stats.rx_packets++; ++ dev->stats.rx_bytes += pktlen; ++ ++ skb_put(skb, pktlen); ++ if (ag71xx_has_ar8216(ag)) ++ err = ag71xx_remove_ar8216_header(ag, skb, pktlen); ++ ++ if (err) { ++ dev->stats.rx_dropped++; ++ kfree_skb(skb); ++ } else { ++ skb->dev = dev; ++ skb->ip_summed = CHECKSUM_NONE; ++ if (ag->phy_dev) { ++ ag->phy_dev->netif_receive_skb(skb); ++ } else { ++ skb->protocol = eth_type_trans(skb, dev); ++ netif_receive_skb(skb); ++ } ++ } ++ ++ ring->buf[i].skb = NULL; ++ done++; ++ ++ ring->curr++; ++ } ++ ++ ag71xx_ring_rx_refill(ag); ++ ++ DBG("%s: rx finish, curr=%u, dirty=%u, done=%d\n", ++ dev->name, ring->curr, ring->dirty, done); ++ ++ return done; ++} ++ ++static int ag71xx_poll(struct napi_struct *napi, int limit) ++{ ++ struct ag71xx *ag = container_of(napi, struct ag71xx, napi); ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ struct net_device *dev = ag->dev; ++ struct ag71xx_ring *rx_ring; ++ unsigned long flags; ++ u32 status; ++ int tx_done; ++ int rx_done; ++ ++ pdata->ddr_flush(); ++ tx_done = ag71xx_tx_packets(ag); ++ ++ DBG("%s: processing RX ring\n", dev->name); ++ rx_done = ag71xx_rx_packets(ag, limit); ++ ++ ag71xx_debugfs_update_napi_stats(ag, rx_done, tx_done); ++ ++ rx_ring = &ag->rx_ring; ++ if (rx_ring->buf[rx_ring->dirty % AG71XX_RX_RING_SIZE].skb == NULL) ++ goto oom; ++ ++ status = ag71xx_rr(ag, AG71XX_REG_RX_STATUS); ++ if (unlikely(status & RX_STATUS_OF)) { ++ ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_OF); ++ dev->stats.rx_fifo_errors++; ++ ++ /* restart RX */ ++ ag71xx_wr(ag, AG71XX_REG_RX_CTRL, RX_CTRL_RXE); ++ } ++ ++ if (rx_done < limit) { ++ if (status & RX_STATUS_PR) ++ goto more; ++ ++ status = ag71xx_rr(ag, AG71XX_REG_TX_STATUS); ++ if (status & TX_STATUS_PS) ++ goto more; ++ ++ DBG("%s: disable polling mode, rx=%d, tx=%d,limit=%d\n", ++ dev->name, rx_done, tx_done, limit); ++ ++ napi_complete(napi); ++ ++ /* enable interrupts */ ++ spin_lock_irqsave(&ag->lock, flags); ++ ag71xx_int_enable(ag, AG71XX_INT_POLL); ++ spin_unlock_irqrestore(&ag->lock, flags); ++ return rx_done; ++ } ++ ++ more: ++ DBG("%s: stay in polling mode, rx=%d, tx=%d, limit=%d\n", ++ dev->name, rx_done, tx_done, limit); ++ return rx_done; ++ ++ oom: ++ if (netif_msg_rx_err(ag)) ++ printk(KERN_DEBUG "%s: out of memory\n", dev->name); ++ ++ mod_timer(&ag->oom_timer, jiffies + AG71XX_OOM_REFILL); ++ napi_complete(napi); ++ return 0; ++} ++ ++static irqreturn_t ag71xx_interrupt(int irq, void *dev_id) ++{ ++ struct net_device *dev = dev_id; ++ struct ag71xx *ag = netdev_priv(dev); ++ u32 status; ++ ++ status = ag71xx_rr(ag, AG71XX_REG_INT_STATUS); ++ ag71xx_dump_intr(ag, "raw", status); ++ ++ if (unlikely(!status)) ++ return IRQ_NONE; ++ ++ if (unlikely(status & AG71XX_INT_ERR)) { ++ if (status & AG71XX_INT_TX_BE) { ++ ag71xx_wr(ag, AG71XX_REG_TX_STATUS, TX_STATUS_BE); ++ dev_err(&dev->dev, "TX BUS error\n"); ++ } ++ if (status & AG71XX_INT_RX_BE) { ++ ag71xx_wr(ag, AG71XX_REG_RX_STATUS, RX_STATUS_BE); ++ dev_err(&dev->dev, "RX BUS error\n"); ++ } ++ } ++ ++ if (likely(status & AG71XX_INT_POLL)) { ++ ag71xx_int_disable(ag, AG71XX_INT_POLL); ++ DBG("%s: enable polling mode\n", dev->name); ++ napi_schedule(&ag->napi); ++ } ++ ++ ag71xx_debugfs_update_int_stats(ag, status); ++ ++ return IRQ_HANDLED; ++} ++ ++static void ag71xx_set_multicast_list(struct net_device *dev) ++{ ++ /* TODO */ ++} ++ ++#ifdef CONFIG_NET_POLL_CONTROLLER ++/* ++ * Polling 'interrupt' - used by things like netconsole to send skbs ++ * without having to re-enable interrupts. It's not called while ++ * the interrupt routine is executing. ++ */ ++static void ag71xx_netpoll(struct net_device *dev) ++{ ++ disable_irq(dev->irq); ++ ag71xx_interrupt(dev->irq, dev); ++ enable_irq(dev->irq); ++} ++#endif ++ ++static const struct net_device_ops ag71xx_netdev_ops = { ++ .ndo_open = ag71xx_open, ++ .ndo_stop = ag71xx_stop, ++ .ndo_start_xmit = ag71xx_hard_start_xmit, ++ .ndo_set_multicast_list = ag71xx_set_multicast_list, ++ .ndo_do_ioctl = ag71xx_do_ioctl, ++ .ndo_tx_timeout = ag71xx_tx_timeout, ++ .ndo_change_mtu = eth_change_mtu, ++ .ndo_set_mac_address = eth_mac_addr, ++ .ndo_validate_addr = eth_validate_addr, ++#ifdef CONFIG_NET_POLL_CONTROLLER ++ .ndo_poll_controller = ag71xx_netpoll, ++#endif ++}; ++ ++static int __init ag71xx_probe(struct platform_device *pdev) ++{ ++ struct net_device *dev; ++ struct resource *res; ++ struct ag71xx *ag; ++ struct ag71xx_platform_data *pdata; ++ int err; ++ ++ pdata = pdev->dev.platform_data; ++ if (!pdata) { ++ dev_err(&pdev->dev, "no platform data specified\n"); ++ err = -ENXIO; ++ goto err_out; ++ } ++ ++ if (pdata->mii_bus_dev == NULL) { ++ dev_err(&pdev->dev, "no MII bus device specified\n"); ++ err = -EINVAL; ++ goto err_out; ++ } ++ ++ dev = alloc_etherdev(sizeof(*ag)); ++ if (!dev) { ++ dev_err(&pdev->dev, "alloc_etherdev failed\n"); ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ SET_NETDEV_DEV(dev, &pdev->dev); ++ ++ ag = netdev_priv(dev); ++ ag->pdev = pdev; ++ ag->dev = dev; ++ ag->msg_enable = netif_msg_init(ag71xx_msg_level, ++ AG71XX_DEFAULT_MSG_ENABLE); ++ spin_lock_init(&ag->lock); ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac_base"); ++ if (!res) { ++ dev_err(&pdev->dev, "no mac_base resource found\n"); ++ err = -ENXIO; ++ goto err_out; ++ } ++ ++ ag->mac_base = ioremap_nocache(res->start, res->end - res->start + 1); ++ if (!ag->mac_base) { ++ dev_err(&pdev->dev, "unable to ioremap mac_base\n"); ++ err = -ENOMEM; ++ goto err_free_dev; ++ } ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mii_ctrl"); ++ if (!res) { ++ dev_err(&pdev->dev, "no mii_ctrl resource found\n"); ++ err = -ENXIO; ++ goto err_unmap_base; ++ } ++ ++ ag->mii_ctrl = ioremap_nocache(res->start, res->end - res->start + 1); ++ if (!ag->mii_ctrl) { ++ dev_err(&pdev->dev, "unable to ioremap mii_ctrl\n"); ++ err = -ENOMEM; ++ goto err_unmap_base; ++ } ++ ++ dev->irq = platform_get_irq(pdev, 0); ++ err = request_irq(dev->irq, ag71xx_interrupt, ++ IRQF_DISABLED | IRQF_SAMPLE_RANDOM, ++ dev->name, dev); ++ if (err) { ++ dev_err(&pdev->dev, "unable to request IRQ %d\n", dev->irq); ++ goto err_unmap_mii_ctrl; ++ } ++ ++ dev->base_addr = (unsigned long)ag->mac_base; ++ dev->netdev_ops = &ag71xx_netdev_ops; ++ dev->ethtool_ops = &ag71xx_ethtool_ops; ++ ++ INIT_WORK(&ag->restart_work, ag71xx_restart_work_func); ++ ++ init_timer(&ag->oom_timer); ++ ag->oom_timer.data = (unsigned long) dev; ++ ag->oom_timer.function = ag71xx_oom_timer_handler; ++ ++ memcpy(dev->dev_addr, pdata->mac_addr, ETH_ALEN); ++ ++ netif_napi_add(dev, &ag->napi, ag71xx_poll, AG71XX_NAPI_WEIGHT); ++ ++ err = register_netdev(dev); ++ if (err) { ++ dev_err(&pdev->dev, "unable to register net device\n"); ++ goto err_free_irq; ++ } ++ ++ printk(KERN_INFO "%s: Atheros AG71xx at 0x%08lx, irq %d\n", ++ dev->name, dev->base_addr, dev->irq); ++ ++ ag71xx_dump_regs(ag); ++ ++ ag71xx_hw_init(ag); ++ ++ ag71xx_dump_regs(ag); ++ ++ err = ag71xx_phy_connect(ag); ++ if (err) ++ goto err_unregister_netdev; ++ ++ err = ag71xx_debugfs_init(ag); ++ if (err) ++ goto err_phy_disconnect; ++ ++ platform_set_drvdata(pdev, dev); ++ ++ return 0; ++ ++ err_phy_disconnect: ++ ag71xx_phy_disconnect(ag); ++ err_unregister_netdev: ++ unregister_netdev(dev); ++ err_free_irq: ++ free_irq(dev->irq, dev); ++ err_unmap_mii_ctrl: ++ iounmap(ag->mii_ctrl); ++ err_unmap_base: ++ iounmap(ag->mac_base); ++ err_free_dev: ++ kfree(dev); ++ err_out: ++ platform_set_drvdata(pdev, NULL); ++ return err; ++} ++ ++static int __exit ag71xx_remove(struct platform_device *pdev) ++{ ++ struct net_device *dev = platform_get_drvdata(pdev); ++ ++ if (dev) { ++ struct ag71xx *ag = netdev_priv(dev); ++ ++ ag71xx_debugfs_exit(ag); ++ ag71xx_phy_disconnect(ag); ++ unregister_netdev(dev); ++ free_irq(dev->irq, dev); ++ iounmap(ag->mii_ctrl); ++ iounmap(ag->mac_base); ++ kfree(dev); ++ platform_set_drvdata(pdev, NULL); ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver ag71xx_driver = { ++ .probe = ag71xx_probe, ++ .remove = __exit_p(ag71xx_remove), ++ .driver = { ++ .name = AG71XX_DRV_NAME, ++ } ++}; ++ ++static int __init ag71xx_module_init(void) ++{ ++ int ret; ++ ++ ret = ag71xx_debugfs_root_init(); ++ if (ret) ++ goto err_out; ++ ++ ret = ag71xx_mdio_driver_init(); ++ if (ret) ++ goto err_debugfs_exit; ++ ++ ret = platform_driver_register(&ag71xx_driver); ++ if (ret) ++ goto err_mdio_exit; ++ ++ return 0; ++ ++ err_mdio_exit: ++ ag71xx_mdio_driver_exit(); ++ err_debugfs_exit: ++ ag71xx_debugfs_root_exit(); ++ err_out: ++ return ret; ++} ++ ++static void __exit ag71xx_module_exit(void) ++{ ++ platform_driver_unregister(&ag71xx_driver); ++ ag71xx_mdio_driver_exit(); ++ ag71xx_debugfs_root_exit(); ++} ++ ++module_init(ag71xx_module_init); ++module_exit(ag71xx_module_exit); ++ ++MODULE_VERSION(AG71XX_DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); ++MODULE_AUTHOR("Imre Kaloz <kaloz@openwrt.org>"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" AG71XX_DRV_NAME); +diff -Nur linux-2.6.39.orig/drivers/net/ag71xx/ag71xx_mdio.c linux-2.6.39/drivers/net/ag71xx/ag71xx_mdio.c +--- linux-2.6.39.orig/drivers/net/ag71xx/ag71xx_mdio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/net/ag71xx/ag71xx_mdio.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,243 @@ ++/* ++ * Atheros AR71xx built-in ethernet mac driver ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Based on Atheros' AG7100 driver ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include "ag71xx.h" ++ ++#define AG71XX_MDIO_RETRY 1000 ++#define AG71XX_MDIO_DELAY 5 ++ ++static inline void ag71xx_mdio_wr(struct ag71xx_mdio *am, unsigned reg, ++ u32 value) ++{ ++ void __iomem *r; ++ ++ r = am->mdio_base + reg; ++ __raw_writel(value, r); ++ ++ /* flush write */ ++ (void) __raw_readl(r); ++} ++ ++static inline u32 ag71xx_mdio_rr(struct ag71xx_mdio *am, unsigned reg) ++{ ++ return __raw_readl(am->mdio_base + reg); ++} ++ ++static void ag71xx_mdio_dump_regs(struct ag71xx_mdio *am) ++{ ++ DBG("%s: mii_cfg=%08x, mii_cmd=%08x, mii_addr=%08x\n", ++ am->mii_bus->name, ++ ag71xx_mdio_rr(am, AG71XX_REG_MII_CFG), ++ ag71xx_mdio_rr(am, AG71XX_REG_MII_CMD), ++ ag71xx_mdio_rr(am, AG71XX_REG_MII_ADDR)); ++ DBG("%s: mii_ctrl=%08x, mii_status=%08x, mii_ind=%08x\n", ++ am->mii_bus->name, ++ ag71xx_mdio_rr(am, AG71XX_REG_MII_CTRL), ++ ag71xx_mdio_rr(am, AG71XX_REG_MII_STATUS), ++ ag71xx_mdio_rr(am, AG71XX_REG_MII_IND)); ++} ++ ++static int ag71xx_mdio_mii_read(struct ag71xx_mdio *am, int addr, int reg) ++{ ++ int ret; ++ int i; ++ ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_WRITE); ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_ADDR, ++ ((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff)); ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_READ); ++ ++ i = AG71XX_MDIO_RETRY; ++ while (ag71xx_mdio_rr(am, AG71XX_REG_MII_IND) & MII_IND_BUSY) { ++ if (i-- == 0) { ++ printk(KERN_ERR "%s: mii_read timed out\n", ++ am->mii_bus->name); ++ ret = 0xffff; ++ goto out; ++ } ++ udelay(AG71XX_MDIO_DELAY); ++ } ++ ++ ret = ag71xx_mdio_rr(am, AG71XX_REG_MII_STATUS) & 0xffff; ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_CMD, MII_CMD_WRITE); ++ ++ DBG("mii_read: addr=%04x, reg=%04x, value=%04x\n", addr, reg, ret); ++ ++ out: ++ return ret; ++} ++ ++static void ag71xx_mdio_mii_write(struct ag71xx_mdio *am, ++ int addr, int reg, u16 val) ++{ ++ int i; ++ ++ DBG("mii_write: addr=%04x, reg=%04x, value=%04x\n", addr, reg, val); ++ ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_ADDR, ++ ((addr & 0xff) << MII_ADDR_SHIFT) | (reg & 0xff)); ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_CTRL, val); ++ ++ i = AG71XX_MDIO_RETRY; ++ while (ag71xx_mdio_rr(am, AG71XX_REG_MII_IND) & MII_IND_BUSY) { ++ if (i-- == 0) { ++ printk(KERN_ERR "%s: mii_write timed out\n", ++ am->mii_bus->name); ++ break; ++ } ++ udelay(AG71XX_MDIO_DELAY); ++ } ++} ++ ++static int ag71xx_mdio_reset(struct mii_bus *bus) ++{ ++ struct ag71xx_mdio *am = bus->priv; ++ u32 t; ++ ++ if (am->pdata->is_ar7240) ++ t = MII_CFG_CLK_DIV_6; ++ else ++ t = MII_CFG_CLK_DIV_28; ++ ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, t | MII_CFG_RESET); ++ udelay(100); ++ ++ ag71xx_mdio_wr(am, AG71XX_REG_MII_CFG, t); ++ udelay(100); ++ ++ return 0; ++} ++ ++static int ag71xx_mdio_read(struct mii_bus *bus, int addr, int reg) ++{ ++ struct ag71xx_mdio *am = bus->priv; ++ ++ return ag71xx_mdio_mii_read(am, addr, reg); ++} ++ ++static int ag71xx_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val) ++{ ++ struct ag71xx_mdio *am = bus->priv; ++ ++ ag71xx_mdio_mii_write(am, addr, reg, val); ++ return 0; ++} ++ ++static int __init ag71xx_mdio_probe(struct platform_device *pdev) ++{ ++ struct ag71xx_mdio_platform_data *pdata; ++ struct ag71xx_mdio *am; ++ struct resource *res; ++ int i; ++ int err; ++ ++ pdata = pdev->dev.platform_data; ++ if (!pdata) { ++ dev_err(&pdev->dev, "no platform data specified\n"); ++ return -EINVAL; ++ } ++ ++ am = kzalloc(sizeof(*am), GFP_KERNEL); ++ if (!am) { ++ err = -ENOMEM; ++ goto err_out; ++ } ++ ++ am->pdata = pdata; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_err(&pdev->dev, "no iomem resource found\n"); ++ err = -ENXIO; ++ goto err_out; ++ } ++ ++ am->mdio_base = ioremap_nocache(res->start, res->end - res->start + 1); ++ if (!am->mdio_base) { ++ dev_err(&pdev->dev, "unable to ioremap registers\n"); ++ err = -ENOMEM; ++ goto err_free_mdio; ++ } ++ ++ am->mii_bus = mdiobus_alloc(); ++ if (am->mii_bus == NULL) { ++ err = -ENOMEM; ++ goto err_iounmap; ++ } ++ ++ am->mii_bus->name = "ag71xx_mdio"; ++ am->mii_bus->read = ag71xx_mdio_read; ++ am->mii_bus->write = ag71xx_mdio_write; ++ am->mii_bus->reset = ag71xx_mdio_reset; ++ am->mii_bus->irq = am->mii_irq; ++ am->mii_bus->priv = am; ++ am->mii_bus->parent = &pdev->dev; ++ snprintf(am->mii_bus->id, MII_BUS_ID_SIZE, "%s", dev_name(&pdev->dev)); ++ am->mii_bus->phy_mask = pdata->phy_mask; ++ ++ for (i = 0; i < PHY_MAX_ADDR; i++) ++ am->mii_irq[i] = PHY_POLL; ++ ++ ag71xx_mdio_wr(am, AG71XX_REG_MAC_CFG1, 0); ++ ++ err = mdiobus_register(am->mii_bus); ++ if (err) ++ goto err_free_bus; ++ ++ ag71xx_mdio_dump_regs(am); ++ ++ platform_set_drvdata(pdev, am); ++ return 0; ++ ++ err_free_bus: ++ mdiobus_free(am->mii_bus); ++ err_iounmap: ++ iounmap(am->mdio_base); ++ err_free_mdio: ++ kfree(am); ++ err_out: ++ return err; ++} ++ ++static int __exit ag71xx_mdio_remove(struct platform_device *pdev) ++{ ++ struct ag71xx_mdio *am = platform_get_drvdata(pdev); ++ ++ if (am) { ++ mdiobus_unregister(am->mii_bus); ++ mdiobus_free(am->mii_bus); ++ iounmap(am->mdio_base); ++ kfree(am); ++ platform_set_drvdata(pdev, NULL); ++ } ++ ++ return 0; ++} ++ ++static struct platform_driver ag71xx_mdio_driver = { ++ .probe = ag71xx_mdio_probe, ++ .remove = __exit_p(ag71xx_mdio_remove), ++ .driver = { ++ .name = "ag71xx-mdio", ++ } ++}; ++ ++int ag71xx_mdio_driver_init(void) ++{ ++ return platform_driver_register(&ag71xx_mdio_driver); ++} ++ ++void ag71xx_mdio_driver_exit(void) ++{ ++ platform_driver_unregister(&ag71xx_mdio_driver); ++} +diff -Nur linux-2.6.39.orig/drivers/net/ag71xx/ag71xx_phy.c linux-2.6.39/drivers/net/ag71xx/ag71xx_phy.c +--- linux-2.6.39.orig/drivers/net/ag71xx/ag71xx_phy.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/net/ag71xx/ag71xx_phy.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,213 @@ ++/* ++ * Atheros AR71xx built-in ethernet mac driver ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Based on Atheros' AG7100 driver ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include "ag71xx.h" ++ ++static void ag71xx_phy_link_adjust(struct net_device *dev) ++{ ++ struct ag71xx *ag = netdev_priv(dev); ++ struct phy_device *phydev = ag->phy_dev; ++ unsigned long flags; ++ int status_change = 0; ++ ++ spin_lock_irqsave(&ag->lock, flags); ++ ++ if (phydev->link) { ++ if (ag->duplex != phydev->duplex ++ || ag->speed != phydev->speed) { ++ status_change = 1; ++ } ++ } ++ ++ if (phydev->link != ag->link) ++ status_change = 1; ++ ++ ag->link = phydev->link; ++ ag->duplex = phydev->duplex; ++ ag->speed = phydev->speed; ++ ++ if (status_change) ++ ag71xx_link_adjust(ag); ++ ++ spin_unlock_irqrestore(&ag->lock, flags); ++} ++ ++void ag71xx_phy_start(struct ag71xx *ag) ++{ ++ if (ag->phy_dev) { ++ phy_start(ag->phy_dev); ++ } else { ++ ag->link = 1; ++ ag71xx_link_adjust(ag); ++ } ++} ++ ++void ag71xx_phy_stop(struct ag71xx *ag) ++{ ++ if (ag->phy_dev) { ++ phy_stop(ag->phy_dev); ++ } else { ++ ag->link = 0; ++ ag71xx_link_adjust(ag); ++ } ++} ++ ++static int ag71xx_phy_connect_fixed(struct ag71xx *ag) ++{ ++ struct net_device *dev = ag->dev; ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ int ret = 0; ++ ++ /* use fixed settings */ ++ switch (pdata->speed) { ++ case SPEED_10: ++ case SPEED_100: ++ case SPEED_1000: ++ break; ++ default: ++ printk(KERN_ERR "%s: invalid speed specified\n", dev->name); ++ ret = -EINVAL; ++ break; ++ } ++ ++ printk(KERN_DEBUG "%s: using fixed link parameters\n", dev->name); ++ ++ ag->duplex = pdata->duplex; ++ ag->speed = pdata->speed; ++ ++ return ret; ++} ++ ++static int ag71xx_phy_connect_multi(struct ag71xx *ag) ++{ ++ struct net_device *dev = ag->dev; ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ struct phy_device *phydev = NULL; ++ int phy_addr; ++ int ret = 0; ++ ++ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { ++ if (!(pdata->phy_mask & (1 << phy_addr))) ++ continue; ++ ++ if (ag->mii_bus->phy_map[phy_addr] == NULL) ++ continue; ++ ++ DBG("%s: PHY found at %s, uid=%08x\n", ++ dev->name, ++ dev_name(&ag->mii_bus->phy_map[phy_addr]->dev), ++ ag->mii_bus->phy_map[phy_addr]->phy_id); ++ ++ if (phydev == NULL) ++ phydev = ag->mii_bus->phy_map[phy_addr]; ++ } ++ ++ if (!phydev) { ++ printk(KERN_ERR "%s: no PHY found with phy_mask=%08x\n", ++ dev->name, pdata->phy_mask); ++ return -ENODEV; ++ } ++ ++ ag->phy_dev = phy_connect(dev, dev_name(&phydev->dev), ++ &ag71xx_phy_link_adjust, 0, ++ pdata->phy_if_mode); ++ ++ if (IS_ERR(ag->phy_dev)) { ++ printk(KERN_ERR "%s: could not connect to PHY at %s\n", ++ dev->name, dev_name(&phydev->dev)); ++ return PTR_ERR(ag->phy_dev); ++ } ++ ++ /* mask with MAC supported features */ ++ if (pdata->has_gbit) ++ phydev->supported &= PHY_GBIT_FEATURES; ++ else ++ phydev->supported &= PHY_BASIC_FEATURES; ++ ++ phydev->advertising = phydev->supported; ++ ++ printk(KERN_DEBUG "%s: connected to PHY at %s [uid=%08x, driver=%s]\n", ++ dev->name, dev_name(&phydev->dev), ++ phydev->phy_id, phydev->drv->name); ++ ++ ag->link = 0; ++ ag->speed = 0; ++ ag->duplex = -1; ++ ++ return ret; ++} ++ ++static int dev_is_class(struct device *dev, void *class) ++{ ++ if (dev->class != NULL && !strcmp(dev->class->name, class)) ++ return 1; ++ ++ return 0; ++} ++ ++static struct device *dev_find_class(struct device *parent, char *class) ++{ ++ if (dev_is_class(parent, class)) { ++ get_device(parent); ++ return parent; ++ } ++ ++ return device_find_child(parent, class, dev_is_class); ++} ++ ++static struct mii_bus *dev_to_mii_bus(struct device *dev) ++{ ++ struct device *d; ++ ++ d = dev_find_class(dev, "mdio_bus"); ++ if (d != NULL) { ++ struct mii_bus *bus; ++ ++ bus = to_mii_bus(d); ++ put_device(d); ++ ++ return bus; ++ } ++ ++ return NULL; ++} ++ ++int ag71xx_phy_connect(struct ag71xx *ag) ++{ ++ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); ++ ++ ag->mii_bus = dev_to_mii_bus(pdata->mii_bus_dev); ++ if (ag->mii_bus == NULL) { ++ printk(KERN_ERR "%s: unable to find MII bus on device '%s'\n", ++ ag->dev->name, dev_name(pdata->mii_bus_dev)); ++ return -ENODEV; ++ } ++ ++ /* Reset the mdio bus explicitly */ ++ if (ag->mii_bus->reset) { ++ mutex_lock(&ag->mii_bus->mdio_lock); ++ ag->mii_bus->reset(ag->mii_bus); ++ mutex_unlock(&ag->mii_bus->mdio_lock); ++ } ++ ++ if (pdata->phy_mask) ++ return ag71xx_phy_connect_multi(ag); ++ ++ return ag71xx_phy_connect_fixed(ag); ++} ++ ++void ag71xx_phy_disconnect(struct ag71xx *ag) ++{ ++ if (ag->phy_dev) ++ phy_disconnect(ag->phy_dev); ++} +diff -Nur linux-2.6.39.orig/drivers/net/phy/Kconfig linux-2.6.39/drivers/net/phy/Kconfig +--- linux-2.6.39.orig/drivers/net/phy/Kconfig 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/net/phy/Kconfig 2011-05-27 14:36:51.000000000 +0200 +@@ -91,6 +91,10 @@ + ---help--- + Supports the KSZ9021, VSC8201, KS8001 PHYs. + ++config IP175C_PHY ++ tristate "Driver for IC+ IP175C/IP178C switches" ++ select SWCONFIG ++ + config FIXED_PHY + bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" + depends on PHYLIB=y +diff -Nur linux-2.6.39.orig/drivers/net/phy/phy.c linux-2.6.39/drivers/net/phy/phy.c +--- linux-2.6.39.orig/drivers/net/phy/phy.c 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/net/phy/phy.c 2011-05-27 14:36:51.000000000 +0200 +@@ -297,6 +297,50 @@ + } + EXPORT_SYMBOL(phy_ethtool_gset); + ++int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr) ++{ ++ u32 cmd; ++ int tmp; ++ struct ethtool_cmd ecmd = { ETHTOOL_GSET }; ++ struct ethtool_value edata = { ETHTOOL_GLINK }; ++ ++ if (get_user(cmd, (u32 *) useraddr)) ++ return -EFAULT; ++ ++ switch (cmd) { ++ case ETHTOOL_GSET: ++ phy_ethtool_gset(phydev, &ecmd); ++ if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) ++ return -EFAULT; ++ return 0; ++ ++ case ETHTOOL_SSET: ++ if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) ++ return -EFAULT; ++ return phy_ethtool_sset(phydev, &ecmd); ++ ++ case ETHTOOL_NWAY_RST: ++ /* if autoneg is off, it's an error */ ++ tmp = phy_read(phydev, MII_BMCR); ++ if (tmp & BMCR_ANENABLE) { ++ tmp |= (BMCR_ANRESTART); ++ phy_write(phydev, MII_BMCR, tmp); ++ return 0; ++ } ++ return -EINVAL; ++ ++ case ETHTOOL_GLINK: ++ edata.data = (phy_read(phydev, ++ MII_BMSR) & BMSR_LSTATUS) ? 1 : 0; ++ if (copy_to_user(useraddr, &edata, sizeof(edata))) ++ return -EFAULT; ++ return 0; ++ } ++ ++ return -EOPNOTSUPP; ++} ++EXPORT_SYMBOL(phy_ethtool_ioctl); ++ + /** + * phy_mii_ioctl - generic PHY MII ioctl interface + * @phydev: the phy_device struct +@@ -472,7 +516,7 @@ + int idx; + + idx = phy_find_setting(phydev->speed, phydev->duplex); +- ++ + idx++; + + idx = phy_find_valid(idx, phydev->supported); +diff -Nur linux-2.6.39.orig/drivers/net/phy/phy_device.c linux-2.6.39/drivers/net/phy/phy_device.c +--- linux-2.6.39.orig/drivers/net/phy/phy_device.c 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/net/phy/phy_device.c 2011-05-27 14:36:51.000000000 +0200 +@@ -149,6 +149,19 @@ + } + EXPORT_SYMBOL(phy_scan_fixups); + ++static int generic_receive_skb(struct sk_buff *skb) ++{ ++ skb->protocol = eth_type_trans(skb, skb->dev); ++ return netif_receive_skb(skb); ++} ++ ++static int generic_rx(struct sk_buff *skb) ++{ ++ skb->protocol = eth_type_trans(skb, skb->dev); ++ return netif_rx(skb); ++} ++ ++ + static struct phy_device* phy_device_create(struct mii_bus *bus, + int addr, int phy_id) + { +@@ -180,6 +193,8 @@ + dev_set_name(&dev->dev, PHY_ID_FMT, bus->id, addr); + + dev->state = PHY_DOWN; ++ dev->netif_receive_skb = &generic_receive_skb; ++ dev->netif_rx = &generic_rx; + + mutex_init(&dev->lock); + INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); +diff -Nur linux-2.6.39.orig/drivers/spi/Kconfig linux-2.6.39/drivers/spi/Kconfig +--- linux-2.6.39.orig/drivers/spi/Kconfig 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/spi/Kconfig 2011-05-27 14:36:51.000000000 +0200 +@@ -67,6 +67,13 @@ + This enables support for the SPI controller present on the + Atheros AR71XX/AR724X/AR913X SoCs. + ++config SPI_AR71XX ++ tristate "Atheros AR71xx SPI Controller" ++ depends on SPI_MASTER && ATHEROS_AR71XX ++ select SPI_BITBANG ++ help ++ This is the SPI contoller driver for Atheros AR71xx. ++ + config SPI_ATMEL + tristate "Atmel SPI Controller" + depends on (ARCH_AT91 || AVR32) +diff -Nur linux-2.6.39.orig/drivers/spi/Makefile linux-2.6.39/drivers/spi/Makefile +--- linux-2.6.39.orig/drivers/spi/Makefile 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/spi/Makefile 2011-05-27 14:36:51.000000000 +0200 +@@ -11,6 +11,7 @@ + # SPI master controller drivers (bus) + obj-$(CONFIG_SPI_ALTERA) += spi_altera.o + obj-$(CONFIG_SPI_ATMEL) += atmel_spi.o ++obj-$(CONFIG_SPI_AR71XX) += ar71xx_spi.o + obj-$(CONFIG_SPI_ATH79) += ath79_spi.o + obj-$(CONFIG_SPI_BFIN) += spi_bfin5xx.o + obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o +diff -Nur linux-2.6.39.orig/drivers/spi/ap83_spi.c linux-2.6.39/drivers/spi/ap83_spi.c +--- linux-2.6.39.orig/drivers/spi/ap83_spi.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/spi/ap83_spi.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,282 @@ ++/* ++ * Atheros AP83 board specific SPI Controller driver ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/delay.h> ++#include <linux/spinlock.h> ++#include <linux/workqueue.h> ++#include <linux/platform_device.h> ++#include <linux/io.h> ++#include <linux/spi/spi.h> ++#include <linux/spi/spi_bitbang.h> ++#include <linux/bitops.h> ++#include <linux/gpio.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/platform.h> ++ ++#define DRV_DESC "Atheros AP83 board SPI Controller driver" ++#define DRV_VERSION "0.1.0" ++#define DRV_NAME "ap83-spi" ++ ++#define AP83_SPI_CLK_HIGH (1 << 23) ++#define AP83_SPI_CLK_LOW 0 ++#define AP83_SPI_MOSI_HIGH (1 << 22) ++#define AP83_SPI_MOSI_LOW 0 ++ ++#define AP83_SPI_GPIO_CS 1 ++#define AP83_SPI_GPIO_MISO 3 ++ ++struct ap83_spi { ++ struct spi_bitbang bitbang; ++ void __iomem *base; ++ u32 addr; ++ ++ struct platform_device *pdev; ++}; ++ ++static inline u32 ap83_spi_rr(struct ap83_spi *sp, u32 reg) ++{ ++ return __raw_readl(sp->base + reg); ++} ++ ++static inline struct ap83_spi *spidev_to_sp(struct spi_device *spi) ++{ ++ return spi_master_get_devdata(spi->master); ++} ++ ++static inline void setsck(struct spi_device *spi, int val) ++{ ++ struct ap83_spi *sp = spidev_to_sp(spi); ++ ++ if (val) ++ sp->addr |= AP83_SPI_CLK_HIGH; ++ else ++ sp->addr &= ~AP83_SPI_CLK_HIGH; ++ ++ dev_dbg(&spi->dev, "addr=%08x, SCK set to %s\n", ++ sp->addr, (val) ? "HIGH" : "LOW"); ++ ++ ap83_spi_rr(sp, sp->addr); ++} ++ ++static inline void setmosi(struct spi_device *spi, int val) ++{ ++ struct ap83_spi *sp = spidev_to_sp(spi); ++ ++ if (val) ++ sp->addr |= AP83_SPI_MOSI_HIGH; ++ else ++ sp->addr &= ~AP83_SPI_MOSI_HIGH; ++ ++ dev_dbg(&spi->dev, "addr=%08x, MOSI set to %s\n", ++ sp->addr, (val) ? "HIGH" : "LOW"); ++ ++ ap83_spi_rr(sp, sp->addr); ++} ++ ++static inline u32 getmiso(struct spi_device *spi) ++{ ++ u32 ret; ++ ++ ret = gpio_get_value(AP83_SPI_GPIO_MISO) ? 1 : 0; ++ dev_dbg(&spi->dev, "get MISO: %d\n", ret); ++ ++ return ret; ++} ++ ++static inline void do_spidelay(struct spi_device *spi, unsigned nsecs) ++{ ++ ndelay(nsecs); ++} ++ ++static void ap83_spi_chipselect(struct spi_device *spi, int on) ++{ ++ struct ap83_spi *sp = spidev_to_sp(spi); ++ ++ dev_dbg(&spi->dev, "set CS to %d\n", (on) ? 0 : 1); ++ ++ if (on) { ++ ar71xx_flash_acquire(); ++ ++ sp->addr = 0; ++ ap83_spi_rr(sp, sp->addr); ++ ++ gpio_set_value(AP83_SPI_GPIO_CS, 0); ++ } else { ++ gpio_set_value(AP83_SPI_GPIO_CS, 1); ++ ar71xx_flash_release(); ++ } ++} ++ ++#define spidelay(nsecs) \ ++ do { \ ++ /* Steal the spi_device pointer from our caller. \ ++ * The bitbang-API should probably get fixed here... */ \ ++ do_spidelay(spi, nsecs); \ ++ } while (0) ++ ++#define EXPAND_BITBANG_TXRX ++#include <linux/spi/spi_bitbang.h> ++ ++static u32 ap83_spi_txrx_mode0(struct spi_device *spi, ++ unsigned nsecs, u32 word, u8 bits) ++{ ++ dev_dbg(&spi->dev, "TXRX0 word=%08x, bits=%u\n", word, bits); ++ return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); ++} ++ ++static u32 ap83_spi_txrx_mode1(struct spi_device *spi, ++ unsigned nsecs, u32 word, u8 bits) ++{ ++ dev_dbg(&spi->dev, "TXRX1 word=%08x, bits=%u\n", word, bits); ++ return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); ++} ++ ++static u32 ap83_spi_txrx_mode2(struct spi_device *spi, ++ unsigned nsecs, u32 word, u8 bits) ++{ ++ dev_dbg(&spi->dev, "TXRX2 word=%08x, bits=%u\n", word, bits); ++ return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits); ++} ++ ++static u32 ap83_spi_txrx_mode3(struct spi_device *spi, ++ unsigned nsecs, u32 word, u8 bits) ++{ ++ dev_dbg(&spi->dev, "TXRX3 word=%08x, bits=%u\n", word, bits); ++ return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits); ++} ++ ++static int ap83_spi_probe(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct ap83_spi *sp; ++ struct ap83_spi_platform_data *pdata; ++ struct resource *r; ++ int ret; ++ ++ ret = gpio_request(AP83_SPI_GPIO_MISO, "spi-miso"); ++ if (ret) { ++ dev_err(&pdev->dev, "gpio request failed for MISO\n"); ++ return ret; ++ } ++ ++ ret = gpio_request(AP83_SPI_GPIO_CS, "spi-cs"); ++ if (ret) { ++ dev_err(&pdev->dev, "gpio request failed for CS\n"); ++ goto err_free_miso; ++ } ++ ++ ret = gpio_direction_input(AP83_SPI_GPIO_MISO); ++ if (ret) { ++ dev_err(&pdev->dev, "unable to set direction of MISO\n"); ++ goto err_free_cs; ++ } ++ ++ ret = gpio_direction_output(AP83_SPI_GPIO_CS, 0); ++ if (ret) { ++ dev_err(&pdev->dev, "unable to set direction of CS\n"); ++ goto err_free_cs; ++ } ++ ++ master = spi_alloc_master(&pdev->dev, sizeof(*sp)); ++ if (master == NULL) { ++ dev_err(&pdev->dev, "failed to allocate spi master\n"); ++ return -ENOMEM; ++ } ++ ++ sp = spi_master_get_devdata(master); ++ platform_set_drvdata(pdev, sp); ++ ++ pdata = pdev->dev.platform_data; ++ ++ sp->bitbang.master = spi_master_get(master); ++ sp->bitbang.chipselect = ap83_spi_chipselect; ++ sp->bitbang.txrx_word[SPI_MODE_0] = ap83_spi_txrx_mode0; ++ sp->bitbang.txrx_word[SPI_MODE_1] = ap83_spi_txrx_mode1; ++ sp->bitbang.txrx_word[SPI_MODE_2] = ap83_spi_txrx_mode2; ++ sp->bitbang.txrx_word[SPI_MODE_3] = ap83_spi_txrx_mode3; ++ ++ sp->bitbang.master->bus_num = pdev->id; ++ sp->bitbang.master->num_chipselect = 1; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (r == NULL) { ++ ret = -ENOENT; ++ goto err_spi_put; ++ } ++ ++ sp->base = ioremap_nocache(r->start, r->end - r->start + 1); ++ if (!sp->base) { ++ ret = -ENXIO; ++ goto err_spi_put; ++ } ++ ++ ret = spi_bitbang_start(&sp->bitbang); ++ if (!ret) ++ goto err_unmap; ++ ++ dev_info(&pdev->dev, "AP83 SPI adapter at %08x\n", r->start); ++ ++ return 0; ++ ++ err_unmap: ++ iounmap(sp->base); ++ err_spi_put: ++ platform_set_drvdata(pdev, NULL); ++ spi_master_put(sp->bitbang.master); ++ ++ err_free_cs: ++ gpio_free(AP83_SPI_GPIO_CS); ++ err_free_miso: ++ gpio_free(AP83_SPI_GPIO_MISO); ++ return ret; ++} ++ ++static int ap83_spi_remove(struct platform_device *pdev) ++{ ++ struct ap83_spi *sp = platform_get_drvdata(pdev); ++ ++ spi_bitbang_stop(&sp->bitbang); ++ iounmap(sp->base); ++ platform_set_drvdata(pdev, NULL); ++ spi_master_put(sp->bitbang.master); ++ ++ return 0; ++} ++ ++static struct platform_driver ap83_spi_drv = { ++ .probe = ap83_spi_probe, ++ .remove = ap83_spi_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init ap83_spi_init(void) ++{ ++ return platform_driver_register(&ap83_spi_drv); ++} ++module_init(ap83_spi_init); ++ ++static void __exit ap83_spi_exit(void) ++{ ++ platform_driver_unregister(&ap83_spi_drv); ++} ++module_exit(ap83_spi_exit); ++ ++MODULE_ALIAS("platform:" DRV_NAME); ++MODULE_DESCRIPTION(DRV_DESC); ++MODULE_VERSION(DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); ++MODULE_LICENSE("GPL v2"); +diff -Nur linux-2.6.39.orig/drivers/spi/ar71xx_spi.c linux-2.6.39/drivers/spi/ar71xx_spi.c +--- linux-2.6.39.orig/drivers/spi/ar71xx_spi.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/spi/ar71xx_spi.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,283 @@ ++/* ++ * Atheros AR71xx SPI Controller driver ++ * ++ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/delay.h> ++#include <linux/spinlock.h> ++#include <linux/workqueue.h> ++#include <linux/platform_device.h> ++#include <linux/io.h> ++#include <linux/spi/spi.h> ++#include <linux/spi/spi_bitbang.h> ++#include <linux/bitops.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/platform.h> ++ ++#define DRV_DESC "Atheros AR71xx SPI Controller driver" ++#define DRV_VERSION "0.2.4" ++#define DRV_NAME "ar71xx-spi" ++ ++#undef PER_BIT_READ ++ ++struct ar71xx_spi { ++ struct spi_bitbang bitbang; ++ u32 ioc_base; ++ u32 reg_ctrl; ++ ++ void __iomem *base; ++ ++ struct platform_device *pdev; ++ u32 (*get_ioc_base)(u8 chip_select, int cs_high, ++ int is_on); ++}; ++ ++static inline u32 ar71xx_spi_rr(struct ar71xx_spi *sp, unsigned reg) ++{ ++ return __raw_readl(sp->base + reg); ++} ++ ++static inline void ar71xx_spi_wr(struct ar71xx_spi *sp, unsigned reg, u32 val) ++{ ++ __raw_writel(val, sp->base + reg); ++} ++ ++static inline struct ar71xx_spi *spidev_to_sp(struct spi_device *spi) ++{ ++ return spi_master_get_devdata(spi->master); ++} ++ ++static u32 ar71xx_spi_get_ioc_base(u8 chip_select, int cs_high, int is_on) ++{ ++ u32 ret; ++ ++ if (is_on == AR71XX_SPI_CS_INACTIVE) ++ ret = SPI_IOC_CS_ALL; ++ else ++ ret = SPI_IOC_CS_ALL & ~SPI_IOC_CS(chip_select); ++ ++ return ret; ++} ++ ++static void ar71xx_spi_chipselect(struct spi_device *spi, int value) ++{ ++ struct ar71xx_spi *sp = spidev_to_sp(spi); ++ void __iomem *base = sp->base; ++ u32 ioc_base; ++ ++ switch (value) { ++ case BITBANG_CS_INACTIVE: ++ ioc_base = sp->get_ioc_base(spi->chip_select, ++ (spi->mode & SPI_CS_HIGH) != 0, ++ AR71XX_SPI_CS_INACTIVE); ++ __raw_writel(ioc_base, base + SPI_REG_IOC); ++ break; ++ ++ case BITBANG_CS_ACTIVE: ++ ioc_base = sp->get_ioc_base(spi->chip_select, ++ (spi->mode & SPI_CS_HIGH) != 0, ++ AR71XX_SPI_CS_ACTIVE); ++ ++ __raw_writel(ioc_base, base + SPI_REG_IOC); ++ sp->ioc_base = ioc_base; ++ break; ++ } ++} ++ ++static void ar71xx_spi_setup_regs(struct spi_device *spi) ++{ ++ struct ar71xx_spi *sp = spidev_to_sp(spi); ++ ++ /* enable GPIO mode */ ++ ar71xx_spi_wr(sp, SPI_REG_FS, SPI_FS_GPIO); ++ ++ /* save CTRL register */ ++ sp->reg_ctrl = ar71xx_spi_rr(sp, SPI_REG_CTRL); ++ ++ /* TODO: setup speed? */ ++ ar71xx_spi_wr(sp, SPI_REG_CTRL, 0x43); ++} ++ ++static void ar71xx_spi_restore_regs(struct spi_device *spi) ++{ ++ struct ar71xx_spi *sp = spidev_to_sp(spi); ++ ++ /* restore CTRL register */ ++ ar71xx_spi_wr(sp, SPI_REG_CTRL, sp->reg_ctrl); ++ /* disable GPIO mode */ ++ ar71xx_spi_wr(sp, SPI_REG_FS, 0); ++} ++ ++static int ar71xx_spi_setup(struct spi_device *spi) ++{ ++ int status; ++ ++ if (spi->bits_per_word > 32) ++ return -EINVAL; ++ ++ if (!spi->controller_state) ++ ar71xx_spi_setup_regs(spi); ++ ++ status = spi_bitbang_setup(spi); ++ if (status && !spi->controller_state) ++ ar71xx_spi_restore_regs(spi); ++ ++ return status; ++} ++ ++static void ar71xx_spi_cleanup(struct spi_device *spi) ++{ ++ ar71xx_spi_restore_regs(spi); ++ spi_bitbang_cleanup(spi); ++} ++ ++static u32 ar71xx_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs, ++ u32 word, u8 bits) ++{ ++ struct ar71xx_spi *sp = spidev_to_sp(spi); ++ void __iomem *base = sp->base; ++ u32 ioc = sp->ioc_base; ++ u32 ret; ++ ++ /* clock starts at inactive polarity */ ++ for (word <<= (32 - bits); likely(bits); bits--) { ++ u32 out; ++ ++ if (word & (1 << 31)) ++ out = ioc | SPI_IOC_DO; ++ else ++ out = ioc & ~SPI_IOC_DO; ++ ++ /* setup MSB (to slave) on trailing edge */ ++ __raw_writel(out, base + SPI_REG_IOC); ++ ++ __raw_writel(out | SPI_IOC_CLK, base + SPI_REG_IOC); ++ ++ word <<= 1; ++ ++#ifdef PER_BIT_READ ++ /* sample MSB (from slave) on leading edge */ ++ ret = __raw_readl(base + SPI_REG_RDS); ++ __raw_writel(out, base + SPI_REG_IOC); ++#endif ++ ++ } ++ ++#ifndef PER_BIT_READ ++ ret = __raw_readl(base + SPI_REG_RDS); ++#endif ++ return ret; ++} ++ ++static int ar71xx_spi_probe(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct ar71xx_spi *sp; ++ struct ar71xx_spi_platform_data *pdata; ++ struct resource *r; ++ int ret; ++ ++ master = spi_alloc_master(&pdev->dev, sizeof(*sp)); ++ if (master == NULL) { ++ dev_err(&pdev->dev, "failed to allocate spi master\n"); ++ return -ENOMEM; ++ } ++ ++ sp = spi_master_get_devdata(master); ++ platform_set_drvdata(pdev, sp); ++ ++ pdata = pdev->dev.platform_data; ++ ++ master->setup = ar71xx_spi_setup; ++ master->cleanup = ar71xx_spi_cleanup; ++ ++ sp->bitbang.master = spi_master_get(master); ++ sp->bitbang.chipselect = ar71xx_spi_chipselect; ++ sp->bitbang.txrx_word[SPI_MODE_0] = ar71xx_spi_txrx_mode0; ++ sp->bitbang.setup_transfer = spi_bitbang_setup_transfer; ++ ++ sp->get_ioc_base = ar71xx_spi_get_ioc_base; ++ if (pdata) { ++ sp->bitbang.master->bus_num = pdata->bus_num; ++ sp->bitbang.master->num_chipselect = pdata->num_chipselect; ++ if (pdata->get_ioc_base) ++ sp->get_ioc_base = pdata->get_ioc_base; ++ } else { ++ sp->bitbang.master->bus_num = 0; ++ sp->bitbang.master->num_chipselect = 3; ++ } ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (r == NULL) { ++ ret = -ENOENT; ++ goto err1; ++ } ++ ++ sp->base = ioremap_nocache(r->start, r->end - r->start + 1); ++ if (!sp->base) { ++ ret = -ENXIO; ++ goto err1; ++ } ++ ++ ret = spi_bitbang_start(&sp->bitbang); ++ if (!ret) ++ return 0; ++ ++ iounmap(sp->base); ++ err1: ++ platform_set_drvdata(pdev, NULL); ++ spi_master_put(sp->bitbang.master); ++ ++ return ret; ++} ++ ++static int ar71xx_spi_remove(struct platform_device *pdev) ++{ ++ struct ar71xx_spi *sp = platform_get_drvdata(pdev); ++ ++ spi_bitbang_stop(&sp->bitbang); ++ iounmap(sp->base); ++ platform_set_drvdata(pdev, NULL); ++ spi_master_put(sp->bitbang.master); ++ ++ return 0; ++} ++ ++static struct platform_driver ar71xx_spi_drv = { ++ .probe = ar71xx_spi_probe, ++ .remove = ar71xx_spi_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init ar71xx_spi_init(void) ++{ ++ printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n"); ++ return platform_driver_register(&ar71xx_spi_drv); ++} ++module_init(ar71xx_spi_init); ++ ++static void __exit ar71xx_spi_exit(void) ++{ ++ platform_driver_unregister(&ar71xx_spi_drv); ++} ++module_exit(ar71xx_spi_exit); ++ ++MODULE_ALIAS("platform:" DRV_NAME); ++MODULE_DESCRIPTION(DRV_DESC); ++MODULE_VERSION(DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); ++MODULE_AUTHOR("Imre Kaloz <kaloz@openwrt.org>"); ++MODULE_LICENSE("GPL v2"); +diff -Nur linux-2.6.39.orig/drivers/spi/pb44_spi.c linux-2.6.39/drivers/spi/pb44_spi.c +--- linux-2.6.39.orig/drivers/spi/pb44_spi.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/spi/pb44_spi.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,299 @@ ++/* ++ * Atheros PB44 board SPI controller driver ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/delay.h> ++#include <linux/spinlock.h> ++#include <linux/workqueue.h> ++#include <linux/platform_device.h> ++#include <linux/io.h> ++#include <linux/spi/spi.h> ++#include <linux/spi/spi_bitbang.h> ++#include <linux/bitops.h> ++#include <linux/gpio.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++#include <asm/mach-ar71xx/platform.h> ++ ++#define DRV_DESC "Atheros PB44 SPI Controller driver" ++#define DRV_VERSION "0.1.0" ++#define DRV_NAME "pb44-spi" ++ ++#undef PER_BIT_READ ++ ++struct ar71xx_spi { ++ struct spi_bitbang bitbang; ++ u32 ioc_base; ++ u32 reg_ctrl; ++ ++ void __iomem *base; ++ ++ struct platform_device *pdev; ++}; ++ ++static inline u32 pb44_spi_rr(struct ar71xx_spi *sp, unsigned reg) ++{ ++ return __raw_readl(sp->base + reg); ++} ++ ++static inline void pb44_spi_wr(struct ar71xx_spi *sp, unsigned reg, u32 val) ++{ ++ __raw_writel(val, sp->base + reg); ++} ++ ++static inline struct ar71xx_spi *spidev_to_sp(struct spi_device *spi) ++{ ++ return spi_master_get_devdata(spi->master); ++} ++ ++static void pb44_spi_chipselect(struct spi_device *spi, int is_active) ++{ ++ struct ar71xx_spi *sp = spidev_to_sp(spi); ++ int cs_high = (spi->mode & SPI_CS_HIGH) ? is_active : !is_active; ++ ++ if (is_active) { ++ /* set initial clock polarity */ ++ if (spi->mode & SPI_CPOL) ++ sp->ioc_base |= SPI_IOC_CLK; ++ else ++ sp->ioc_base &= ~SPI_IOC_CLK; ++ ++ pb44_spi_wr(sp, SPI_REG_IOC, sp->ioc_base); ++ } ++ ++ if (spi->chip_select) { ++ unsigned long gpio = (unsigned long) spi->controller_data; ++ ++ /* SPI is normally active-low */ ++ gpio_set_value(gpio, cs_high); ++ } else { ++ if (cs_high) ++ sp->ioc_base |= SPI_IOC_CS0; ++ else ++ sp->ioc_base &= ~SPI_IOC_CS0; ++ ++ pb44_spi_wr(sp, SPI_REG_IOC, sp->ioc_base); ++ } ++ ++} ++ ++static int pb44_spi_setup_cs(struct spi_device *spi) ++{ ++ struct ar71xx_spi *sp = spidev_to_sp(spi); ++ ++ /* enable GPIO mode */ ++ pb44_spi_wr(sp, SPI_REG_FS, SPI_FS_GPIO); ++ ++ /* save CTRL register */ ++ sp->reg_ctrl = pb44_spi_rr(sp, SPI_REG_CTRL); ++ sp->ioc_base = pb44_spi_rr(sp, SPI_REG_IOC); ++ ++ /* TODO: setup speed? */ ++ pb44_spi_wr(sp, SPI_REG_CTRL, 0x43); ++ ++ if (spi->chip_select) { ++ unsigned long gpio = (unsigned long) spi->controller_data; ++ int status = 0; ++ ++ status = gpio_request(gpio, dev_name(&spi->dev)); ++ if (status) ++ return status; ++ ++ status = gpio_direction_output(gpio, spi->mode & SPI_CS_HIGH); ++ if (status) { ++ gpio_free(gpio); ++ return status; ++ } ++ } else { ++ if (spi->mode & SPI_CS_HIGH) ++ sp->ioc_base |= SPI_IOC_CS0; ++ else ++ sp->ioc_base &= ~SPI_IOC_CS0; ++ pb44_spi_wr(sp, SPI_REG_IOC, sp->ioc_base); ++ } ++ ++ return 0; ++} ++ ++static void pb44_spi_cleanup_cs(struct spi_device *spi) ++{ ++ struct ar71xx_spi *sp = spidev_to_sp(spi); ++ ++ if (spi->chip_select) { ++ unsigned long gpio = (unsigned long) spi->controller_data; ++ gpio_free(gpio); ++ } ++ ++ /* restore CTRL register */ ++ pb44_spi_wr(sp, SPI_REG_CTRL, sp->reg_ctrl); ++ /* disable GPIO mode */ ++ pb44_spi_wr(sp, SPI_REG_FS, 0); ++} ++ ++static int pb44_spi_setup(struct spi_device *spi) ++{ ++ int status = 0; ++ ++ if (spi->bits_per_word > 32) ++ return -EINVAL; ++ ++ if (!spi->controller_state) { ++ status = pb44_spi_setup_cs(spi); ++ if (status) ++ return status; ++ } ++ ++ status = spi_bitbang_setup(spi); ++ if (status && !spi->controller_state) ++ pb44_spi_cleanup_cs(spi); ++ ++ return status; ++} ++ ++static void pb44_spi_cleanup(struct spi_device *spi) ++{ ++ pb44_spi_cleanup_cs(spi); ++ spi_bitbang_cleanup(spi); ++} ++ ++static u32 pb44_spi_txrx_mode0(struct spi_device *spi, unsigned nsecs, ++ u32 word, u8 bits) ++{ ++ struct ar71xx_spi *sp = spidev_to_sp(spi); ++ u32 ioc = sp->ioc_base; ++ u32 ret; ++ ++ /* clock starts at inactive polarity */ ++ for (word <<= (32 - bits); likely(bits); bits--) { ++ u32 out; ++ ++ if (word & (1 << 31)) ++ out = ioc | SPI_IOC_DO; ++ else ++ out = ioc & ~SPI_IOC_DO; ++ ++ /* setup MSB (to slave) on trailing edge */ ++ pb44_spi_wr(sp, SPI_REG_IOC, out); ++ pb44_spi_wr(sp, SPI_REG_IOC, out | SPI_IOC_CLK); ++ ++ word <<= 1; ++ ++#ifdef PER_BIT_READ ++ /* sample MSB (from slave) on leading edge */ ++ ret = pb44_spi_rr(sp, SPI_REG_RDS); ++ pb44_spi_wr(sp, SPI_REG_IOC, out); ++#endif ++ } ++ ++#ifndef PER_BIT_READ ++ ret = pb44_spi_rr(sp, SPI_REG_RDS); ++#endif ++ return ret; ++} ++ ++static int pb44_spi_probe(struct platform_device *pdev) ++{ ++ struct spi_master *master; ++ struct ar71xx_spi *sp; ++ struct ar71xx_spi_platform_data *pdata; ++ struct resource *r; ++ int ret; ++ ++ master = spi_alloc_master(&pdev->dev, sizeof(*sp)); ++ if (master == NULL) { ++ dev_err(&pdev->dev, "failed to allocate spi master\n"); ++ return -ENOMEM; ++ } ++ ++ sp = spi_master_get_devdata(master); ++ platform_set_drvdata(pdev, sp); ++ ++ pdata = pdev->dev.platform_data; ++ ++ master->setup = pb44_spi_setup; ++ master->cleanup = pb44_spi_cleanup; ++ if (pdata) { ++ master->bus_num = pdata->bus_num; ++ master->num_chipselect = pdata->num_chipselect; ++ } else { ++ master->bus_num = 0; ++ master->num_chipselect = 1; ++ } ++ ++ sp->bitbang.master = spi_master_get(master); ++ sp->bitbang.chipselect = pb44_spi_chipselect; ++ sp->bitbang.txrx_word[SPI_MODE_0] = pb44_spi_txrx_mode0; ++ sp->bitbang.setup_transfer = spi_bitbang_setup_transfer; ++ sp->bitbang.flags = SPI_CS_HIGH; ++ ++ r = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (r == NULL) { ++ ret = -ENOENT; ++ goto err1; ++ } ++ ++ sp->base = ioremap_nocache(r->start, r->end - r->start + 1); ++ if (!sp->base) { ++ ret = -ENXIO; ++ goto err1; ++ } ++ ++ ret = spi_bitbang_start(&sp->bitbang); ++ if (!ret) ++ return 0; ++ ++ iounmap(sp->base); ++ err1: ++ platform_set_drvdata(pdev, NULL); ++ spi_master_put(sp->bitbang.master); ++ ++ return ret; ++} ++ ++static int pb44_spi_remove(struct platform_device *pdev) ++{ ++ struct ar71xx_spi *sp = platform_get_drvdata(pdev); ++ ++ spi_bitbang_stop(&sp->bitbang); ++ iounmap(sp->base); ++ platform_set_drvdata(pdev, NULL); ++ spi_master_put(sp->bitbang.master); ++ ++ return 0; ++} ++ ++static struct platform_driver pb44_spi_drv = { ++ .probe = pb44_spi_probe, ++ .remove = pb44_spi_remove, ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init pb44_spi_init(void) ++{ ++ return platform_driver_register(&pb44_spi_drv); ++} ++module_init(pb44_spi_init); ++ ++static void __exit pb44_spi_exit(void) ++{ ++ platform_driver_unregister(&pb44_spi_drv); ++} ++module_exit(pb44_spi_exit); ++ ++MODULE_ALIAS("platform:" DRV_NAME); ++MODULE_DESCRIPTION(DRV_DESC); ++MODULE_VERSION(DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); ++MODULE_LICENSE("GPL v2"); +diff -Nur linux-2.6.39.orig/drivers/spi/spi_vsc7385.c linux-2.6.39/drivers/spi/spi_vsc7385.c +--- linux-2.6.39.orig/drivers/spi/spi_vsc7385.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/spi/spi_vsc7385.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,620 @@ ++/* ++ * SPI driver for the Vitesse VSC7385 ethernet switch ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/types.h> ++#include <linux/kernel.h> ++#include <linux/init.h> ++#include <linux/module.h> ++#include <linux/delay.h> ++#include <linux/device.h> ++#include <linux/bitops.h> ++#include <linux/firmware.h> ++#include <linux/spi/spi.h> ++#include <linux/spi/vsc7385.h> ++ ++#define DRV_NAME "spi-vsc7385" ++#define DRV_DESC "Vitesse VSC7385 Gbit ethernet switch driver" ++#define DRV_VERSION "0.1.0" ++ ++#define VSC73XX_BLOCK_MAC 0x1 ++#define VSC73XX_BLOCK_2 0x2 ++#define VSC73XX_BLOCK_MII 0x3 ++#define VSC73XX_BLOCK_4 0x4 ++#define VSC73XX_BLOCK_5 0x5 ++#define VSC73XX_BLOCK_SYSTEM 0x7 ++ ++#define VSC73XX_SUBBLOCK_PORT_0 0 ++#define VSC73XX_SUBBLOCK_PORT_1 1 ++#define VSC73XX_SUBBLOCK_PORT_2 2 ++#define VSC73XX_SUBBLOCK_PORT_3 3 ++#define VSC73XX_SUBBLOCK_PORT_4 4 ++#define VSC73XX_SUBBLOCK_PORT_MAC 6 ++ ++/* MAC Block registers */ ++#define VSC73XX_MAC_CFG 0x0 ++#define VSC73XX_ADVPORTM 0x19 ++#define VSC73XX_RXOCT 0x50 ++#define VSC73XX_TXOCT 0x51 ++#define VSC73XX_C_RX0 0x52 ++#define VSC73XX_C_RX1 0x53 ++#define VSC73XX_C_RX2 0x54 ++#define VSC73XX_C_TX0 0x55 ++#define VSC73XX_C_TX1 0x56 ++#define VSC73XX_C_TX2 0x57 ++#define VSC73XX_C_CFG 0x58 ++ ++/* MAC_CFG register bits */ ++#define VSC73XX_MAC_CFG_WEXC_DIS (1 << 31) ++#define VSC73XX_MAC_CFG_PORT_RST (1 << 29) ++#define VSC73XX_MAC_CFG_TX_EN (1 << 28) ++#define VSC73XX_MAC_CFG_SEED_LOAD (1 << 27) ++#define VSC73XX_MAC_CFG_FDX (1 << 18) ++#define VSC73XX_MAC_CFG_GIGE (1 << 17) ++#define VSC73XX_MAC_CFG_RX_EN (1 << 16) ++#define VSC73XX_MAC_CFG_VLAN_DBLAWR (1 << 15) ++#define VSC73XX_MAC_CFG_VLAN_AWR (1 << 14) ++#define VSC73XX_MAC_CFG_100_BASE_T (1 << 13) ++#define VSC73XX_MAC_CFG_TX_IPG(x) (((x) & 0x1f) << 6) ++#define VSC73XX_MAC_CFG_MAC_RX_RST (1 << 5) ++#define VSC73XX_MAC_CFG_MAC_TX_RST (1 << 4) ++#define VSC73XX_MAC_CFG_BIT2 (1 << 2) ++#define VSC73XX_MAC_CFG_CLK_SEL(x) ((x) & 0x3) ++ ++/* ADVPORTM register bits */ ++#define VSC73XX_ADVPORTM_IFG_PPM (1 << 7) ++#define VSC73XX_ADVPORTM_EXC_COL_CONT (1 << 6) ++#define VSC73XX_ADVPORTM_EXT_PORT (1 << 5) ++#define VSC73XX_ADVPORTM_INV_GTX (1 << 4) ++#define VSC73XX_ADVPORTM_ENA_GTX (1 << 3) ++#define VSC73XX_ADVPORTM_DDR_MODE (1 << 2) ++#define VSC73XX_ADVPORTM_IO_LOOPBACK (1 << 1) ++#define VSC73XX_ADVPORTM_HOST_LOOPBACK (1 << 0) ++ ++/* MII Block registers */ ++#define VSC73XX_MII_STAT 0x0 ++#define VSC73XX_MII_CMD 0x1 ++#define VSC73XX_MII_DATA 0x2 ++ ++/* System Block registers */ ++#define VSC73XX_ICPU_SIPAD 0x01 ++#define VSC73XX_ICPU_CLOCK_DELAY 0x05 ++#define VSC73XX_ICPU_CTRL 0x10 ++#define VSC73XX_ICPU_ADDR 0x11 ++#define VSC73XX_ICPU_SRAM 0x12 ++#define VSC73XX_ICPU_MBOX_VAL 0x15 ++#define VSC73XX_ICPU_MBOX_SET 0x16 ++#define VSC73XX_ICPU_MBOX_CLR 0x17 ++#define VSC73XX_ICPU_CHIPID 0x18 ++#define VSC73XX_ICPU_GPIO 0x34 ++ ++#define VSC73XX_ICPU_CTRL_CLK_DIV (1 << 8) ++#define VSC73XX_ICPU_CTRL_SRST_HOLD (1 << 7) ++#define VSC73XX_ICPU_CTRL_BOOT_EN (1 << 3) ++#define VSC73XX_ICPU_CTRL_EXT_ACC_EN (1 << 2) ++#define VSC73XX_ICPU_CTRL_CLK_EN (1 << 1) ++#define VSC73XX_ICPU_CTRL_SRST (1 << 0) ++ ++#define VSC73XX_ICPU_CHIPID_ID_SHIFT 12 ++#define VSC73XX_ICPU_CHIPID_ID_MASK 0xffff ++#define VSC73XX_ICPU_CHIPID_REV_SHIFT 28 ++#define VSC73XX_ICPU_CHIPID_REV_MASK 0xf ++#define VSC73XX_ICPU_CHIPID_ID_7385 0x7385 ++#define VSC73XX_ICPU_CHIPID_ID_7395 0x7395 ++ ++#define VSC73XX_CMD_MODE_READ 0 ++#define VSC73XX_CMD_MODE_WRITE 1 ++#define VSC73XX_CMD_MODE_SHIFT 4 ++#define VSC73XX_CMD_BLOCK_SHIFT 5 ++#define VSC73XX_CMD_BLOCK_MASK 0x7 ++#define VSC73XX_CMD_SUBBLOCK_MASK 0xf ++ ++#define VSC7385_CLOCK_DELAY ((3 << 4) | 3) ++#define VSC7385_CLOCK_DELAY_MASK ((3 << 4) | 3) ++ ++#define VSC73XX_ICPU_CTRL_STOP (VSC73XX_ICPU_CTRL_SRST_HOLD | \ ++ VSC73XX_ICPU_CTRL_BOOT_EN | \ ++ VSC73XX_ICPU_CTRL_EXT_ACC_EN) ++ ++#define VSC73XX_ICPU_CTRL_START (VSC73XX_ICPU_CTRL_CLK_DIV | \ ++ VSC73XX_ICPU_CTRL_BOOT_EN | \ ++ VSC73XX_ICPU_CTRL_CLK_EN | \ ++ VSC73XX_ICPU_CTRL_SRST) ++ ++#define VSC7385_ADVPORTM_MASK (VSC73XX_ADVPORTM_IFG_PPM | \ ++ VSC73XX_ADVPORTM_EXC_COL_CONT | \ ++ VSC73XX_ADVPORTM_EXT_PORT | \ ++ VSC73XX_ADVPORTM_INV_GTX | \ ++ VSC73XX_ADVPORTM_ENA_GTX | \ ++ VSC73XX_ADVPORTM_DDR_MODE | \ ++ VSC73XX_ADVPORTM_IO_LOOPBACK | \ ++ VSC73XX_ADVPORTM_HOST_LOOPBACK) ++ ++#define VSC7385_ADVPORTM_INIT (VSC73XX_ADVPORTM_EXT_PORT | \ ++ VSC73XX_ADVPORTM_ENA_GTX | \ ++ VSC73XX_ADVPORTM_DDR_MODE) ++ ++#define VSC7385_MAC_CFG_RESET (VSC73XX_MAC_CFG_PORT_RST | \ ++ VSC73XX_MAC_CFG_MAC_RX_RST | \ ++ VSC73XX_MAC_CFG_MAC_TX_RST) ++ ++#define VSC73XX_MAC_CFG_INIT (VSC73XX_MAC_CFG_TX_EN | \ ++ VSC73XX_MAC_CFG_FDX | \ ++ VSC73XX_MAC_CFG_GIGE | \ ++ VSC73XX_MAC_CFG_RX_EN) ++ ++#define VSC73XX_RESET_DELAY 100 ++ ++struct vsc7385 { ++ struct spi_device *spi; ++ struct mutex lock; ++ struct vsc7385_platform_data *pdata; ++}; ++ ++static int vsc7385_is_addr_valid(u8 block, u8 subblock) ++{ ++ switch (block) { ++ case VSC73XX_BLOCK_MAC: ++ switch (subblock) { ++ case 0 ... 4: ++ case 6: ++ return 1; ++ } ++ break; ++ ++ case VSC73XX_BLOCK_2: ++ case VSC73XX_BLOCK_SYSTEM: ++ switch (subblock) { ++ case 0: ++ return 1; ++ } ++ break; ++ ++ case VSC73XX_BLOCK_MII: ++ case VSC73XX_BLOCK_4: ++ case VSC73XX_BLOCK_5: ++ switch (subblock) { ++ case 0 ... 1: ++ return 1; ++ } ++ break; ++ } ++ ++ return 0; ++} ++ ++static inline u8 vsc7385_make_addr(u8 mode, u8 block, u8 subblock) ++{ ++ u8 ret; ++ ++ ret = (block & VSC73XX_CMD_BLOCK_MASK) << VSC73XX_CMD_BLOCK_SHIFT; ++ ret |= (mode & 1) << VSC73XX_CMD_MODE_SHIFT; ++ ret |= subblock & VSC73XX_CMD_SUBBLOCK_MASK; ++ ++ return ret; ++} ++ ++static int vsc7385_read(struct vsc7385 *vsc, u8 block, u8 subblock, u8 reg, ++ u32 *value) ++{ ++ u8 cmd[4]; ++ u8 buf[4]; ++ struct spi_transfer t[2]; ++ struct spi_message m; ++ int err; ++ ++ if (!vsc7385_is_addr_valid(block, subblock)) ++ return -EINVAL; ++ ++ spi_message_init(&m); ++ ++ memset(&t, 0, sizeof(t)); ++ ++ t[0].tx_buf = cmd; ++ t[0].len = sizeof(cmd); ++ spi_message_add_tail(&t[0], &m); ++ ++ t[1].rx_buf = buf; ++ t[1].len = sizeof(buf); ++ spi_message_add_tail(&t[1], &m); ++ ++ cmd[0] = vsc7385_make_addr(VSC73XX_CMD_MODE_READ, block, subblock); ++ cmd[1] = reg; ++ cmd[2] = 0; ++ cmd[3] = 0; ++ ++ mutex_lock(&vsc->lock); ++ err = spi_sync(vsc->spi, &m); ++ mutex_unlock(&vsc->lock); ++ ++ if (err) ++ return err; ++ ++ *value = (((u32) buf[0]) << 24) | (((u32) buf[1]) << 16) | ++ (((u32) buf[2]) << 8) | ((u32) buf[3]); ++ ++ return 0; ++} ++ ++ ++static int vsc7385_write(struct vsc7385 *vsc, u8 block, u8 subblock, u8 reg, ++ u32 value) ++{ ++ u8 cmd[2]; ++ u8 buf[4]; ++ struct spi_transfer t[2]; ++ struct spi_message m; ++ int err; ++ ++ if (!vsc7385_is_addr_valid(block, subblock)) ++ return -EINVAL; ++ ++ spi_message_init(&m); ++ ++ memset(&t, 0, sizeof(t)); ++ ++ t[0].tx_buf = cmd; ++ t[0].len = sizeof(cmd); ++ spi_message_add_tail(&t[0], &m); ++ ++ t[1].tx_buf = buf; ++ t[1].len = sizeof(buf); ++ spi_message_add_tail(&t[1], &m); ++ ++ cmd[0] = vsc7385_make_addr(VSC73XX_CMD_MODE_WRITE, block, subblock); ++ cmd[1] = reg; ++ ++ buf[0] = (value >> 24) & 0xff; ++ buf[1] = (value >> 16) & 0xff; ++ buf[2] = (value >> 8) & 0xff; ++ buf[3] = value & 0xff; ++ ++ mutex_lock(&vsc->lock); ++ err = spi_sync(vsc->spi, &m); ++ mutex_unlock(&vsc->lock); ++ ++ return err; ++} ++ ++static inline int vsc7385_write_verify(struct vsc7385 *vsc, u8 block, ++ u8 subblock, u8 reg, u32 value, ++ u32 read_mask, u32 read_val) ++{ ++ struct spi_device *spi = vsc->spi; ++ u32 t; ++ int err; ++ ++ err = vsc7385_write(vsc, block, subblock, reg, value); ++ if (err) ++ return err; ++ ++ err = vsc7385_read(vsc, block, subblock, reg, &t); ++ if (err) ++ return err; ++ ++ if ((t & read_mask) != read_val) { ++ dev_err(&spi->dev, "register write error\n"); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static inline int vsc7385_set_clock_delay(struct vsc7385 *vsc, u32 val) ++{ ++ return vsc7385_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, ++ VSC73XX_ICPU_CLOCK_DELAY, val); ++} ++ ++static inline int vsc7385_get_clock_delay(struct vsc7385 *vsc, u32 *val) ++{ ++ return vsc7385_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, ++ VSC73XX_ICPU_CLOCK_DELAY, val); ++} ++ ++static inline int vsc7385_icpu_stop(struct vsc7385 *vsc) ++{ ++ return vsc7385_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_ICPU_CTRL, ++ VSC73XX_ICPU_CTRL_STOP); ++} ++ ++static inline int vsc7385_icpu_start(struct vsc7385 *vsc) ++{ ++ return vsc7385_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_ICPU_CTRL, ++ VSC73XX_ICPU_CTRL_START); ++} ++ ++static inline int vsc7385_icpu_reset(struct vsc7385 *vsc) ++{ ++ int rc; ++ ++ rc = vsc7385_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, VSC73XX_ICPU_ADDR, ++ 0x0000); ++ if (rc) ++ dev_err(&vsc->spi->dev, ++ "could not reset microcode, err=%d\n", rc); ++ ++ return rc; ++} ++ ++static int vsc7385_upload_ucode(struct vsc7385 *vsc) ++{ ++ struct spi_device *spi = vsc->spi; ++ const struct firmware *firmware; ++ char *ucode_name; ++ unsigned char *dp; ++ unsigned int curVal; ++ int i; ++ int diffs; ++ int rc; ++ ++ ucode_name = (vsc->pdata->ucode_name) ? vsc->pdata->ucode_name ++ : "vsc7385_ucode.bin"; ++ rc = request_firmware(&firmware, ucode_name, &spi->dev); ++ if (rc) { ++ dev_err(&spi->dev, "request_firmware failed, err=%d\n", ++ rc); ++ return rc; ++ } ++ ++ rc = vsc7385_icpu_stop(vsc); ++ if (rc) ++ goto out; ++ ++ rc = vsc7385_icpu_reset(vsc); ++ if (rc) ++ goto out; ++ ++ dev_info(&spi->dev, "uploading microcode...\n"); ++ ++ dp = (unsigned char *) firmware->data; ++ for (i = 0; i < firmware->size; i++) { ++ rc = vsc7385_write(vsc, VSC73XX_BLOCK_SYSTEM, 0, ++ VSC73XX_ICPU_SRAM, *dp++); ++ if (rc) { ++ dev_err(&spi->dev, "could not load microcode, err=%d\n", ++ rc); ++ goto out; ++ } ++ } ++ ++ rc = vsc7385_icpu_reset(vsc); ++ if (rc) ++ goto out; ++ ++ dev_info(&spi->dev, "verifying microcode...\n"); ++ ++ dp = (unsigned char *) firmware->data; ++ diffs = 0; ++ for (i = 0; i < firmware->size; i++) { ++ rc = vsc7385_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, ++ VSC73XX_ICPU_SRAM, &curVal); ++ if (rc) { ++ dev_err(&spi->dev, "could not read microcode %d\n",rc); ++ goto out; ++ } ++ ++ if (curVal > 0xff) { ++ dev_err(&spi->dev, "bad val read: %04x : %02x %02x\n", ++ i, *dp, curVal); ++ rc = -EIO; ++ goto out; ++ } ++ ++ if ((curVal & 0xff) != *dp) { ++ diffs++; ++ dev_err(&spi->dev, "verify error: %04x : %02x %02x\n", ++ i, *dp, curVal); ++ ++ if (diffs > 4) ++ break; ++ } ++ dp++; ++ } ++ ++ if (diffs) { ++ dev_err(&spi->dev, "microcode verification failed\n"); ++ rc = -EIO; ++ goto out; ++ } ++ ++ dev_info(&spi->dev, "microcode uploaded\n"); ++ ++ rc = vsc7385_icpu_start(vsc); ++ ++ out: ++ release_firmware(firmware); ++ return rc; ++} ++ ++static int vsc7385_setup(struct vsc7385 *vsc) ++{ ++ struct vsc7385_platform_data *pdata = vsc->pdata; ++ u32 t; ++ int err; ++ ++ err = vsc7385_write_verify(vsc, VSC73XX_BLOCK_SYSTEM, 0, ++ VSC73XX_ICPU_CLOCK_DELAY, ++ VSC7385_CLOCK_DELAY, ++ VSC7385_CLOCK_DELAY_MASK, ++ VSC7385_CLOCK_DELAY); ++ if (err) ++ goto err; ++ ++ err = vsc7385_write_verify(vsc, VSC73XX_BLOCK_MAC, ++ VSC73XX_SUBBLOCK_PORT_MAC, VSC73XX_ADVPORTM, ++ VSC7385_ADVPORTM_INIT, ++ VSC7385_ADVPORTM_MASK, ++ VSC7385_ADVPORTM_INIT); ++ if (err) ++ goto err; ++ ++ err = vsc7385_write(vsc, VSC73XX_BLOCK_MAC, VSC73XX_SUBBLOCK_PORT_MAC, ++ VSC73XX_MAC_CFG, VSC7385_MAC_CFG_RESET); ++ if (err) ++ goto err; ++ ++ t = VSC73XX_MAC_CFG_INIT; ++ t |= VSC73XX_MAC_CFG_TX_IPG(pdata->mac_cfg.tx_ipg); ++ t |= VSC73XX_MAC_CFG_CLK_SEL(pdata->mac_cfg.clk_sel); ++ if (pdata->mac_cfg.bit2) ++ t |= VSC73XX_MAC_CFG_BIT2; ++ ++ err = vsc7385_write(vsc, VSC73XX_BLOCK_MAC, VSC73XX_SUBBLOCK_PORT_MAC, ++ VSC73XX_MAC_CFG, t); ++ if (err) ++ goto err; ++ ++ return 0; ++ ++ err: ++ return err; ++} ++ ++static int vsc7385_detect(struct vsc7385 *vsc) ++{ ++ struct spi_device *spi = vsc->spi; ++ u32 t; ++ u32 id; ++ u32 rev; ++ int err; ++ ++ err = vsc7385_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, ++ VSC73XX_ICPU_MBOX_VAL, &t); ++ if (err) { ++ dev_err(&spi->dev, "unable to read mailbox, err=%d\n", err); ++ return err; ++ } ++ ++ if (t == 0xffffffff) { ++ dev_dbg(&spi->dev, "assert chip reset\n"); ++ if (vsc->pdata->reset) ++ vsc->pdata->reset(); ++ ++ } ++ ++ err = vsc7385_read(vsc, VSC73XX_BLOCK_SYSTEM, 0, ++ VSC73XX_ICPU_CHIPID, &t); ++ if (err) { ++ dev_err(&spi->dev, "unable to read chip id, err=%d\n", err); ++ return err; ++ } ++ ++ id = (t >> VSC73XX_ICPU_CHIPID_ID_SHIFT) & VSC73XX_ICPU_CHIPID_ID_MASK; ++ switch (id) { ++ case VSC73XX_ICPU_CHIPID_ID_7385: ++ case VSC73XX_ICPU_CHIPID_ID_7395: ++ break; ++ default: ++ dev_err(&spi->dev, "unsupported chip, id=%04x\n", id); ++ return -ENODEV; ++ } ++ ++ rev = (t >> VSC73XX_ICPU_CHIPID_REV_SHIFT) & ++ VSC73XX_ICPU_CHIPID_REV_MASK; ++ dev_info(&spi->dev, "VSC%04X (rev. %d) switch found \n", id, rev); ++ ++ return 0; ++} ++ ++static int __devinit vsc7385_probe(struct spi_device *spi) ++{ ++ struct vsc7385 *vsc; ++ struct vsc7385_platform_data *pdata; ++ int err; ++ ++ printk(KERN_INFO DRV_DESC " version " DRV_VERSION"\n"); ++ ++ pdata = spi->dev.platform_data; ++ if (!pdata) { ++ dev_err(&spi->dev, "no platform data specified\n"); ++ return-ENODEV; ++ } ++ ++ vsc = kzalloc(sizeof(*vsc), GFP_KERNEL); ++ if (!vsc) { ++ dev_err(&spi->dev, "no memory for private data\n"); ++ return-ENOMEM; ++ } ++ ++ mutex_init(&vsc->lock); ++ vsc->pdata = pdata; ++ vsc->spi = spi_dev_get(spi); ++ dev_set_drvdata(&spi->dev, vsc); ++ ++ spi->mode = SPI_MODE_0; ++ spi->bits_per_word = 8; ++ err = spi_setup(spi); ++ if (err) { ++ dev_err(&spi->dev, "spi_setup failed, err=%d \n", err); ++ goto err_drvdata; ++ } ++ ++ err = vsc7385_detect(vsc); ++ if (err) { ++ dev_err(&spi->dev, "no chip found, err=%d \n", err); ++ goto err_drvdata; ++ } ++ ++ err = vsc7385_upload_ucode(vsc); ++ if (err) ++ goto err_drvdata; ++ ++ err = vsc7385_setup(vsc); ++ if (err) ++ goto err_drvdata; ++ ++ return 0; ++ ++ err_drvdata: ++ dev_set_drvdata(&spi->dev, NULL); ++ kfree(vsc); ++ return err; ++} ++ ++static int __devexit vsc7385_remove(struct spi_device *spi) ++{ ++ struct vsc7385_data *vsc; ++ ++ vsc = dev_get_drvdata(&spi->dev); ++ dev_set_drvdata(&spi->dev, NULL); ++ kfree(vsc); ++ ++ return 0; ++} ++ ++static struct spi_driver vsc7385_driver = { ++ .driver = { ++ .name = DRV_NAME, ++ .bus = &spi_bus_type, ++ .owner = THIS_MODULE, ++ }, ++ .probe = vsc7385_probe, ++ .remove = __devexit_p(vsc7385_remove), ++}; ++ ++static int __init vsc7385_init(void) ++{ ++ return spi_register_driver(&vsc7385_driver); ++} ++module_init(vsc7385_init); ++ ++static void __exit vsc7385_exit(void) ++{ ++ spi_unregister_driver(&vsc7385_driver); ++} ++module_exit(vsc7385_exit); ++ ++MODULE_DESCRIPTION(DRV_DESC); ++MODULE_VERSION(DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); ++MODULE_LICENSE("GPL v2"); ++ +diff -Nur linux-2.6.39.orig/drivers/usb/host/Kconfig linux-2.6.39/drivers/usb/host/Kconfig +--- linux-2.6.39.orig/drivers/usb/host/Kconfig 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/usb/host/Kconfig 2011-05-27 14:36:51.000000000 +0200 +@@ -129,6 +129,13 @@ + config USB_FSL_MPH_DR_OF + tristate + ++config USB_EHCI_AR71XX ++ bool "USB EHCI support for AR71xx" ++ depends on USB_EHCI_HCD && ATHEROS_AR71XX ++ default y ++ help ++ Support for Atheros AR71xx built-in EHCI controller ++ + config USB_EHCI_FSL + bool "Support for Freescale on-chip EHCI USB controller" + depends on USB_EHCI_HCD && FSL_SOC +@@ -287,6 +294,13 @@ + Enables support for the on-chip OHCI controller on + OMAP3 and later chips. + ++config USB_OHCI_AR71XX ++ bool "USB OHCI support for Atheros AR71xx" ++ depends on USB_OHCI_HCD && ATHEROS_AR71XX ++ default y ++ help ++ Support for Atheros AR71xx built-in OHCI controller ++ + config USB_OHCI_HCD_PPC_SOC + bool "OHCI support for on-chip PPC USB controller" + depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx) +diff -Nur linux-2.6.39.orig/drivers/usb/host/ehci-ar71xx.c linux-2.6.39/drivers/usb/host/ehci-ar71xx.c +--- linux-2.6.39.orig/drivers/usb/host/ehci-ar71xx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/usb/host/ehci-ar71xx.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,242 @@ ++/* ++ * Bus Glue for Atheros AR71xx built-in EHCI controller. ++ * ++ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * Copyright (C) 2007 Atheros Communications, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/platform_device.h> ++#include <linux/delay.h> ++ ++#include <asm/mach-ar71xx/platform.h> ++ ++extern int usb_disabled(void); ++ ++static int ehci_ar71xx_init(struct usb_hcd *hcd) ++{ ++ struct ehci_hcd *ehci = hcd_to_ehci(hcd); ++ int ret; ++ ++ ehci->caps = hcd->regs; ++ ehci->regs = hcd->regs + ++ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); ++ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); ++ ++ ehci->sbrn = 0x20; ++ ehci->has_synopsys_hc_bug = 1; ++ ++ ehci_reset(ehci); ++ ++ ret = ehci_init(hcd); ++ if (ret) ++ return ret; ++ ++ ehci_port_power(ehci, 0); ++ ++ return 0; ++} ++ ++static int ehci_ar91xx_init(struct usb_hcd *hcd) ++{ ++ struct ehci_hcd *ehci = hcd_to_ehci(hcd); ++ int ret; ++ ++ ehci->caps = hcd->regs + 0x100; ++ ehci->regs = hcd->regs + 0x100 + ++ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); ++ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); ++ ++ hcd->has_tt = 1; ++ ehci->sbrn = 0x20; ++ ++ ehci_reset(ehci); ++ ++ ret = ehci_init(hcd); ++ if (ret) ++ return ret; ++ ++ ehci_port_power(ehci, 0); ++ ++ return 0; ++} ++ ++static int ehci_ar71xx_probe(const struct hc_driver *driver, ++ struct usb_hcd **hcd_out, ++ struct platform_device *pdev) ++{ ++ struct usb_hcd *hcd; ++ struct resource *res; ++ int irq; ++ int ret; ++ ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!res) { ++ dev_dbg(&pdev->dev, "no IRQ specified for %s\n", ++ dev_name(&pdev->dev)); ++ return -ENODEV; ++ } ++ irq = res->start; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_dbg(&pdev->dev, "no base address specified for %s\n", ++ dev_name(&pdev->dev)); ++ return -ENODEV; ++ } ++ ++ hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); ++ if (!hcd) ++ return -ENOMEM; ++ ++ hcd->rsrc_start = res->start; ++ hcd->rsrc_len = res->end - res->start + 1; ++ ++ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { ++ dev_dbg(&pdev->dev, "controller already in use\n"); ++ ret = -EBUSY; ++ goto err_put_hcd; ++ } ++ ++ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); ++ if (!hcd->regs) { ++ dev_dbg(&pdev->dev, "error mapping memory\n"); ++ ret = -EFAULT; ++ goto err_release_region; ++ } ++ ++ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); ++ if (ret) ++ goto err_iounmap; ++ ++ return 0; ++ ++ err_iounmap: ++ iounmap(hcd->regs); ++ ++ err_release_region: ++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); ++ err_put_hcd: ++ usb_put_hcd(hcd); ++ return ret; ++} ++ ++static void ehci_ar71xx_remove(struct usb_hcd *hcd, ++ struct platform_device *pdev) ++{ ++ usb_remove_hcd(hcd); ++ iounmap(hcd->regs); ++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); ++ usb_put_hcd(hcd); ++} ++ ++static const struct hc_driver ehci_ar71xx_hc_driver = { ++ .description = hcd_name, ++ .product_desc = "Atheros AR71xx built-in EHCI controller", ++ .hcd_priv_size = sizeof(struct ehci_hcd), ++ ++ .irq = ehci_irq, ++ .flags = HCD_MEMORY | HCD_USB2, ++ ++ .reset = ehci_ar71xx_init, ++ .start = ehci_run, ++ .stop = ehci_stop, ++ .shutdown = ehci_shutdown, ++ ++ .urb_enqueue = ehci_urb_enqueue, ++ .urb_dequeue = ehci_urb_dequeue, ++ .endpoint_disable = ehci_endpoint_disable, ++ .endpoint_reset = ehci_endpoint_reset, ++ ++ .get_frame_number = ehci_get_frame, ++ ++ .hub_status_data = ehci_hub_status_data, ++ .hub_control = ehci_hub_control, ++#ifdef CONFIG_PM ++ .hub_suspend = ehci_hub_suspend, ++ .hub_resume = ehci_hub_resume, ++#endif ++ .relinquish_port = ehci_relinquish_port, ++ .port_handed_over = ehci_port_handed_over, ++ ++ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, ++}; ++ ++static const struct hc_driver ehci_ar91xx_hc_driver = { ++ .description = hcd_name, ++ .product_desc = "Atheros AR91xx built-in EHCI controller", ++ .hcd_priv_size = sizeof(struct ehci_hcd), ++ .irq = ehci_irq, ++ .flags = HCD_MEMORY | HCD_USB2, ++ ++ .reset = ehci_ar91xx_init, ++ .start = ehci_run, ++ .stop = ehci_stop, ++ .shutdown = ehci_shutdown, ++ ++ .urb_enqueue = ehci_urb_enqueue, ++ .urb_dequeue = ehci_urb_dequeue, ++ .endpoint_disable = ehci_endpoint_disable, ++ .endpoint_reset = ehci_endpoint_reset, ++ ++ .get_frame_number = ehci_get_frame, ++ ++ .hub_status_data = ehci_hub_status_data, ++ .hub_control = ehci_hub_control, ++#ifdef CONFIG_PM ++ .hub_suspend = ehci_hub_suspend, ++ .hub_resume = ehci_hub_resume, ++#endif ++ .relinquish_port = ehci_relinquish_port, ++ .port_handed_over = ehci_port_handed_over, ++ ++ .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, ++}; ++ ++static int ehci_ar71xx_driver_probe(struct platform_device *pdev) ++{ ++ struct ar71xx_ehci_platform_data *pdata; ++ struct usb_hcd *hcd = NULL; ++ int ret; ++ ++ if (usb_disabled()) ++ return -ENODEV; ++ ++ pdata = pdev->dev.platform_data; ++ if (!pdata) { ++ dev_err(&pdev->dev, "no platform data specified for %s\n", ++ dev_name(&pdev->dev)); ++ return -ENODEV; ++ } ++ ++ if (pdata->is_ar91xx) ++ ret = ehci_ar71xx_probe(&ehci_ar91xx_hc_driver, &hcd, pdev); ++ else ++ ret = ehci_ar71xx_probe(&ehci_ar71xx_hc_driver, &hcd, pdev); ++ ++ return ret; ++} ++ ++static int ehci_ar71xx_driver_remove(struct platform_device *pdev) ++{ ++ struct usb_hcd *hcd = platform_get_drvdata(pdev); ++ ++ ehci_ar71xx_remove(hcd, pdev); ++ return 0; ++} ++ ++MODULE_ALIAS("platform:ar71xx-ehci"); ++ ++static struct platform_driver ehci_ar71xx_driver = { ++ .probe = ehci_ar71xx_driver_probe, ++ .remove = ehci_ar71xx_driver_remove, ++ .driver = { ++ .name = "ar71xx-ehci", ++ } ++}; +diff -Nur linux-2.6.39.orig/drivers/usb/host/ehci-hcd.c linux-2.6.39/drivers/usb/host/ehci-hcd.c +--- linux-2.6.39.orig/drivers/usb/host/ehci-hcd.c 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/usb/host/ehci-hcd.c 2011-05-27 14:36:51.000000000 +0200 +@@ -1265,6 +1265,11 @@ + #define PLATFORM_DRIVER tegra_ehci_driver + #endif + ++#ifdef CONFIG_USB_EHCI_AR71XX ++#include "ehci-ar71xx.c" ++#define PLATFORM_DRIVER ehci_ar71xx_driver ++#endif ++ + #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ + !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ + !defined(XILINX_OF_PLATFORM_DRIVER) +diff -Nur linux-2.6.39.orig/drivers/usb/host/ohci-ar71xx.c linux-2.6.39/drivers/usb/host/ohci-ar71xx.c +--- linux-2.6.39.orig/drivers/usb/host/ohci-ar71xx.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/usb/host/ohci-ar71xx.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,165 @@ ++/* ++ * OHCI HCD (Host Controller Driver) for USB. ++ * ++ * Bus Glue for Atheros AR71xx built-in OHCI controller. ++ * ++ * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * Parts of this file are based on Atheros' 2.6.15 BSP ++ * Copyright (C) 2007 Atheros Communications, Inc. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++#include <linux/platform_device.h> ++#include <linux/delay.h> ++ ++extern int usb_disabled(void); ++ ++static int usb_hcd_ar71xx_probe(const struct hc_driver *driver, ++ struct platform_device *pdev) ++{ ++ struct usb_hcd *hcd; ++ struct resource *res; ++ int irq; ++ int ret; ++ ++ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); ++ if (!res) { ++ dev_dbg(&pdev->dev, "no IRQ specified for %s\n", ++ dev_name(&pdev->dev)); ++ return -ENODEV; ++ } ++ irq = res->start; ++ ++ hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); ++ if (!hcd) ++ return -ENOMEM; ++ ++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); ++ if (!res) { ++ dev_dbg(&pdev->dev, "no base address specified for %s\n", ++ dev_name(&pdev->dev)); ++ ret = -ENODEV; ++ goto err_put_hcd; ++ } ++ hcd->rsrc_start = res->start; ++ hcd->rsrc_len = res->end - res->start + 1; ++ ++ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { ++ dev_dbg(&pdev->dev, "controller already in use\n"); ++ ret = -EBUSY; ++ goto err_put_hcd; ++ } ++ ++ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); ++ if (!hcd->regs) { ++ dev_dbg(&pdev->dev, "error mapping memory\n"); ++ ret = -EFAULT; ++ goto err_release_region; ++ } ++ ++ ohci_hcd_init(hcd_to_ohci(hcd)); ++ ++ ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); ++ if (ret) ++ goto err_stop_hcd; ++ ++ return 0; ++ ++ err_stop_hcd: ++ iounmap(hcd->regs); ++ err_release_region: ++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); ++ err_put_hcd: ++ usb_put_hcd(hcd); ++ return ret; ++} ++ ++void usb_hcd_ar71xx_remove(struct usb_hcd *hcd, struct platform_device *pdev) ++{ ++ usb_remove_hcd(hcd); ++ iounmap(hcd->regs); ++ release_mem_region(hcd->rsrc_start, hcd->rsrc_len); ++ usb_put_hcd(hcd); ++} ++ ++static int __devinit ohci_ar71xx_start(struct usb_hcd *hcd) ++{ ++ struct ohci_hcd *ohci = hcd_to_ohci(hcd); ++ int ret; ++ ++ ret = ohci_init(ohci); ++ if (ret < 0) ++ return ret; ++ ++ ret = ohci_run(ohci); ++ if (ret < 0) ++ goto err; ++ ++ return 0; ++ ++ err: ++ ohci_stop(hcd); ++ return ret; ++} ++ ++static const struct hc_driver ohci_ar71xx_hc_driver = { ++ .description = hcd_name, ++ .product_desc = "Atheros AR71xx built-in OHCI controller", ++ .hcd_priv_size = sizeof(struct ohci_hcd), ++ ++ .irq = ohci_irq, ++ .flags = HCD_USB11 | HCD_MEMORY, ++ ++ .start = ohci_ar71xx_start, ++ .stop = ohci_stop, ++ .shutdown = ohci_shutdown, ++ ++ .urb_enqueue = ohci_urb_enqueue, ++ .urb_dequeue = ohci_urb_dequeue, ++ .endpoint_disable = ohci_endpoint_disable, ++ ++ /* ++ * scheduling support ++ */ ++ .get_frame_number = ohci_get_frame, ++ ++ /* ++ * root hub support ++ */ ++ .hub_status_data = ohci_hub_status_data, ++ .hub_control = ohci_hub_control, ++ .start_port_reset = ohci_start_port_reset, ++}; ++ ++static int ohci_hcd_ar71xx_drv_probe(struct platform_device *pdev) ++{ ++ if (usb_disabled()) ++ return -ENODEV; ++ ++ return usb_hcd_ar71xx_probe(&ohci_ar71xx_hc_driver, pdev); ++} ++ ++static int ohci_hcd_ar71xx_drv_remove(struct platform_device *pdev) ++{ ++ struct usb_hcd *hcd = platform_get_drvdata(pdev); ++ ++ usb_hcd_ar71xx_remove(hcd, pdev); ++ return 0; ++} ++ ++MODULE_ALIAS("platform:ar71xx-ohci"); ++ ++static struct platform_driver ohci_hcd_ar71xx_driver = { ++ .probe = ohci_hcd_ar71xx_drv_probe, ++ .remove = ohci_hcd_ar71xx_drv_remove, ++ .shutdown = usb_hcd_platform_shutdown, ++ .driver = { ++ .name = "ar71xx-ohci", ++ .owner = THIS_MODULE, ++ }, ++}; +diff -Nur linux-2.6.39.orig/drivers/usb/host/ohci-hcd.c linux-2.6.39/drivers/usb/host/ohci-hcd.c +--- linux-2.6.39.orig/drivers/usb/host/ohci-hcd.c 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/usb/host/ohci-hcd.c 2011-05-27 14:36:51.000000000 +0200 +@@ -1105,6 +1105,11 @@ + #define PLATFORM_DRIVER ohci_hcd_cns3xxx_driver + #endif + ++#ifdef CONFIG_USB_OHCI_AR71XX ++#include "ohci-ar71xx.c" ++#define PLATFORM_DRIVER ohci_hcd_ar71xx_driver ++#endif ++ + #if !defined(PCI_DRIVER) && \ + !defined(PLATFORM_DRIVER) && \ + !defined(OMAP1_PLATFORM_DRIVER) && \ +diff -Nur linux-2.6.39.orig/drivers/watchdog/Kconfig linux-2.6.39/drivers/watchdog/Kconfig +--- linux-2.6.39.orig/drivers/watchdog/Kconfig 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/watchdog/Kconfig 2011-05-27 14:36:51.000000000 +0200 +@@ -990,6 +990,13 @@ + To compile this driver as a loadable module, choose M here. + The module will be called bcm63xx_wdt. + ++config AR71XX_WDT ++ tristate "Atheros AR71xx Watchdog Timer" ++ depends on ATHEROS_AR71XX ++ help ++ Hardware driver for the built-in watchdog timer on the Atheros ++ AR71xx SoCs. ++ + # PARISC Architecture + + # POWERPC Architecture +diff -Nur linux-2.6.39.orig/drivers/watchdog/Makefile linux-2.6.39/drivers/watchdog/Makefile +--- linux-2.6.39.orig/drivers/watchdog/Makefile 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/drivers/watchdog/Makefile 2011-05-27 14:36:51.000000000 +0200 +@@ -121,6 +121,7 @@ + obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o + obj-$(CONFIG_AR7_WDT) += ar7_wdt.o + obj-$(CONFIG_TXX9_WDT) += txx9wdt.o ++obj-$(CONFIG_AR71XX_WDT) += ar71xx_wdt.o + obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o + octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o + +diff -Nur linux-2.6.39.orig/drivers/watchdog/ar71xx_wdt.c linux-2.6.39/drivers/watchdog/ar71xx_wdt.c +--- linux-2.6.39.orig/drivers/watchdog/ar71xx_wdt.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/drivers/watchdog/ar71xx_wdt.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,270 @@ ++/* ++ * Driver for the Atheros AR71xx SoC's built-in hardware watchdog timer. ++ * ++ * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org> ++ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> ++ * ++ * This driver was based on: drivers/watchdog/ixp4xx_wdt.c ++ * Author: Deepak Saxena <dsaxena@plexity.net> ++ * Copyright 2004 (c) MontaVista, Software, Inc. ++ * ++ * which again was based on sa1100 driver, ++ * Copyright (C) 2000 Oleg Drokin <green@crimea.edu> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++ ++#include <linux/bitops.h> ++#include <linux/errno.h> ++#include <linux/fs.h> ++#include <linux/init.h> ++#include <linux/kernel.h> ++#include <linux/miscdevice.h> ++#include <linux/module.h> ++#include <linux/moduleparam.h> ++#include <linux/platform_device.h> ++#include <linux/types.h> ++#include <linux/watchdog.h> ++ ++#include <asm/mach-ar71xx/ar71xx.h> ++ ++#define DRV_NAME "ar71xx-wdt" ++#define DRV_DESC "Atheros AR71xx hardware watchdog driver" ++#define DRV_VERSION "0.1.0" ++ ++#define WDT_TIMEOUT 15 /* seconds */ ++ ++static int nowayout = WATCHDOG_NOWAYOUT; ++ ++#ifdef CONFIG_WATCHDOG_NOWAYOUT ++module_param(nowayout, int, 0); ++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " ++ "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); ++#endif ++ ++static unsigned long wdt_flags; ++ ++#define WDT_FLAGS_BUSY 0 ++#define WDT_FLAGS_EXPECT_CLOSE 1 ++ ++static int wdt_timeout = WDT_TIMEOUT; ++static int boot_status; ++static int max_timeout; ++ ++static void inline ar71xx_wdt_keepalive(void) ++{ ++ ar71xx_reset_wr(AR71XX_RESET_REG_WDOG, ar71xx_ahb_freq * wdt_timeout); ++} ++ ++static void inline ar71xx_wdt_enable(void) ++{ ++ printk(KERN_DEBUG DRV_NAME ": enabling watchdog timer\n"); ++ ar71xx_wdt_keepalive(); ++ ar71xx_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_FCR); ++} ++ ++static void inline ar71xx_wdt_disable(void) ++{ ++ printk(KERN_DEBUG DRV_NAME ": disabling watchdog timer\n"); ++ ar71xx_reset_wr(AR71XX_RESET_REG_WDOG_CTRL, WDOG_CTRL_ACTION_NONE); ++} ++ ++static int ar71xx_wdt_set_timeout(int val) ++{ ++ if (val < 1 || val > max_timeout) ++ return -EINVAL; ++ ++ wdt_timeout = val; ++ ar71xx_wdt_keepalive(); ++ ++ printk(KERN_DEBUG DRV_NAME ": timeout=%d secs\n", wdt_timeout); ++ ++ return 0; ++} ++ ++static int ar71xx_wdt_open(struct inode *inode, struct file *file) ++{ ++ if (test_and_set_bit(WDT_FLAGS_BUSY, &wdt_flags)) ++ return -EBUSY; ++ ++ clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags); ++ ++ ar71xx_wdt_enable(); ++ ++ return nonseekable_open(inode, file); ++} ++ ++static int ar71xx_wdt_release(struct inode *inode, struct file *file) ++{ ++ if (test_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags)) { ++ ar71xx_wdt_disable(); ++ } else { ++ printk(KERN_CRIT DRV_NAME ": device closed unexpectedly, " ++ "watchdog timer will not stop!\n"); ++ } ++ ++ clear_bit(WDT_FLAGS_BUSY, &wdt_flags); ++ clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags); ++ ++ return 0; ++} ++ ++static ssize_t ar71xx_wdt_write(struct file *file, const char *data, ++ size_t len, loff_t *ppos) ++{ ++ if (len) { ++ if (!nowayout) { ++ size_t i; ++ ++ clear_bit(WDT_FLAGS_EXPECT_CLOSE, &wdt_flags); ++ ++ for (i = 0; i != len; i++) { ++ char c; ++ ++ if (get_user(c, data + i)) ++ return -EFAULT; ++ ++ if (c == 'V') ++ set_bit(WDT_FLAGS_EXPECT_CLOSE, ++ &wdt_flags); ++ } ++ } ++ ++ ar71xx_wdt_keepalive(); ++ } ++ ++ return len; ++} ++ ++static struct watchdog_info ar71xx_wdt_info = { ++ .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | ++ WDIOF_MAGICCLOSE | WDIOF_CARDRESET, ++ .firmware_version = 0, ++ .identity = "AR71XX watchdog", ++}; ++ ++static int ar71xx_wdt_ioctl(struct inode *inode, struct file *file, ++ unsigned int cmd, unsigned long arg) ++{ ++ int t; ++ int ret; ++ ++ switch (cmd) { ++ case WDIOC_GETSUPPORT: ++ ret = copy_to_user((struct watchdog_info *)arg, ++ &ar71xx_wdt_info, ++ sizeof(&ar71xx_wdt_info)) ? -EFAULT : 0; ++ break; ++ ++ case WDIOC_GETSTATUS: ++ ret = put_user(0, (int *)arg) ? -EFAULT : 0; ++ break; ++ ++ case WDIOC_GETBOOTSTATUS: ++ ret = put_user(boot_status, (int *)arg) ? -EFAULT : 0; ++ break; ++ ++ case WDIOC_KEEPALIVE: ++ ar71xx_wdt_keepalive(); ++ ret = 0; ++ break; ++ ++ case WDIOC_SETTIMEOUT: ++ ret = get_user(t, (int *)arg) ? -EFAULT : 0; ++ if (ret) ++ break; ++ ++ ret = ar71xx_wdt_set_timeout(t); ++ if (ret) ++ break; ++ ++ /* fallthrough */ ++ case WDIOC_GETTIMEOUT: ++ ret = put_user(wdt_timeout, (int *)arg) ? -EFAULT : 0; ++ break; ++ ++ default: ++ ret = -ENOTTY; ++ break; ++ } ++ ++ return ret; ++} ++ ++static const struct file_operations ar71xx_wdt_fops = { ++ .owner = THIS_MODULE, ++ .write = ar71xx_wdt_write, ++ .ioctl = ar71xx_wdt_ioctl, ++ .open = ar71xx_wdt_open, ++ .release = ar71xx_wdt_release, ++}; ++ ++static struct miscdevice ar71xx_wdt_miscdev = { ++ .minor = WATCHDOG_MINOR, ++ .name = "watchdog", ++ .fops = &ar71xx_wdt_fops, ++}; ++ ++static int __devinit ar71xx_wdt_probe(struct platform_device *pdev) ++{ ++ int ret; ++ ++ max_timeout = (0xfffffffful / ar71xx_ahb_freq); ++ wdt_timeout = (max_timeout < WDT_TIMEOUT) ? max_timeout : WDT_TIMEOUT; ++ ++ boot_status = ++ (ar71xx_reset_rr(AR71XX_RESET_REG_WDOG_CTRL) & WDOG_CTRL_LAST_RESET) ? ++ WDIOF_CARDRESET : 0; ++ ++ ret = misc_register(&ar71xx_wdt_miscdev); ++ if (ret) ++ goto err_out; ++ ++ printk(KERN_INFO DRV_DESC " version " DRV_VERSION "\n"); ++ ++ printk(KERN_DEBUG DRV_NAME ": timeout=%d secs (max=%d)\n", ++ wdt_timeout, max_timeout); ++ ++ return 0; ++ ++err_out: ++ return ret; ++} ++ ++static int __devexit ar71xx_wdt_remove(struct platform_device *pdev) ++{ ++ misc_deregister(&ar71xx_wdt_miscdev); ++ return 0; ++} ++ ++static struct platform_driver ar71xx_wdt_driver = { ++ .probe = ar71xx_wdt_probe, ++ .remove = __devexit_p(ar71xx_wdt_remove), ++ .driver = { ++ .name = DRV_NAME, ++ .owner = THIS_MODULE, ++ }, ++}; ++ ++static int __init ar71xx_wdt_init(void) ++{ ++ return platform_driver_register(&ar71xx_wdt_driver); ++} ++module_init(ar71xx_wdt_init); ++ ++static void __exit ar71xx_wdt_exit(void) ++{ ++ platform_driver_unregister(&ar71xx_wdt_driver); ++} ++module_exit(ar71xx_wdt_exit); ++ ++MODULE_DESCRIPTION(DRV_DESC); ++MODULE_VERSION(DRV_VERSION); ++MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org"); ++MODULE_AUTHOR("Imre Kaloz <kaloz@openwrt.org"); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("platform:" DRV_NAME); ++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +diff -Nur linux-2.6.39.orig/include/linux/ath9k_platform.h linux-2.6.39/include/linux/ath9k_platform.h +--- linux-2.6.39.orig/include/linux/ath9k_platform.h 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/include/linux/ath9k_platform.h 2011-05-27 14:36:51.000000000 +0200 +@@ -1,19 +1,11 @@ + /* +- * Copyright (c) 2008 Atheros Communications Inc. +- * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org> +- * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org> ++ * ath9k platform data defines + * +- * Permission to use, copy, modify, and/or distribute this software for any +- * purpose with or without fee is hereby granted, provided that the above +- * copyright notice and this permission notice appear in all copies. ++ * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org> + * +- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. + */ + + #ifndef _LINUX_ATH9K_PLATFORM_H +@@ -23,6 +15,9 @@ + + struct ath9k_platform_data { + u16 eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS]; ++ u8 *macaddr; ++ ++ unsigned long quirk_wndr3700:1; + }; + + #endif /* _LINUX_ATH9K_PLATFORM_H */ +diff -Nur linux-2.6.39.orig/include/linux/gpio_buttons.h linux-2.6.39/include/linux/gpio_buttons.h +--- linux-2.6.39.orig/include/linux/gpio_buttons.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/include/linux/gpio_buttons.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,33 @@ ++/* ++ * Definitions for the GPIO buttons interface driver ++ * ++ * Copyright (C) 2007-2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This file was based on: /include/linux/gpio_keys.h ++ * The original gpio_keys.h seems not to have a license. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#ifndef _GPIO_BUTTONS_H_ ++#define _GPIO_BUTTONS_H_ ++ ++struct gpio_button { ++ int gpio; /* GPIO line number */ ++ int active_low; ++ char *desc; /* button description */ ++ int type; /* input event type (EV_KEY, EV_SW) */ ++ int code; /* input event code (KEY_*, SW_*) */ ++ int threshold; /* count threshold */ ++}; ++ ++struct gpio_buttons_platform_data { ++ struct gpio_button *buttons; ++ int nbuttons; /* number of buttons */ ++ int poll_interval; /* polling interval */ ++}; ++ ++#endif /* _GPIO_BUTTONS_H_ */ +diff -Nur linux-2.6.39.orig/include/linux/gpio_dev.h linux-2.6.39/include/linux/gpio_dev.h +--- linux-2.6.39.orig/include/linux/gpio_dev.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/include/linux/gpio_dev.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,11 @@ ++#ifndef _GPIODEV_H__ ++#define _GPIODEV_H__ ++ ++#define IOC_GPIODEV_MAGIC 'B' ++#define GPIO_GET _IO(IOC_GPIODEV_MAGIC, 10) ++#define GPIO_SET _IO(IOC_GPIODEV_MAGIC, 11) ++#define GPIO_CLEAR _IO(IOC_GPIODEV_MAGIC, 12) ++#define GPIO_DIR_IN _IO(IOC_GPIODEV_MAGIC, 13) ++#define GPIO_DIR_OUT _IO(IOC_GPIODEV_MAGIC, 14) ++ ++#endif +diff -Nur linux-2.6.39.orig/include/linux/netdevice.h linux-2.6.39/include/linux/netdevice.h +--- linux-2.6.39.orig/include/linux/netdevice.h 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/include/linux/netdevice.h 2011-05-27 14:36:51.000000000 +0200 +@@ -1182,6 +1182,7 @@ + void *ax25_ptr; /* AX.25 specific data */ + struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data, + assign before registering */ ++ void *phy_ptr; /* PHY device specific data */ + + /* + * Cache lines mostly used on receive path (including eth_type_trans()) +diff -Nur linux-2.6.39.orig/include/linux/nxp_74hc153.h linux-2.6.39/include/linux/nxp_74hc153.h +--- linux-2.6.39.orig/include/linux/nxp_74hc153.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/include/linux/nxp_74hc153.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,24 @@ ++/* ++ * NXP 74HC153 - Dual 4-input multiplexer defines ++ * ++ * Copyright (C) 2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++ ++#ifndef _NXP_74HC153_H ++#define _NXP_74HC153_H ++ ++#define NXP_74HC153_DRIVER_NAME "nxp-74hc153" ++ ++struct nxp_74hc153_platform_data { ++ unsigned gpio_base; ++ unsigned gpio_pin_s0; ++ unsigned gpio_pin_s1; ++ unsigned gpio_pin_1y; ++ unsigned gpio_pin_2y; ++}; ++ ++#endif /* _NXP_74HC153_H */ +diff -Nur linux-2.6.39.orig/include/linux/phy.h linux-2.6.39/include/linux/phy.h +--- linux-2.6.39.orig/include/linux/phy.h 2011-05-19 06:06:34.000000000 +0200 ++++ linux-2.6.39/include/linux/phy.h 2011-05-27 14:36:51.000000000 +0200 +@@ -332,6 +332,20 @@ + void (*adjust_link)(struct net_device *dev); + + void (*adjust_state)(struct net_device *dev); ++ ++ /* ++ * By default these point to the original functions ++ * with the same name. adding them to the phy_device ++ * allows the phy driver to override them for packet ++ * mangling if the ethernet driver supports it ++ * This is required to support some really horrible ++ * switches such as the Marvell 88E6060 ++ */ ++ int (*netif_receive_skb)(struct sk_buff *skb); ++ int (*netif_rx)(struct sk_buff *skb); ++ ++ /* alignment offset for packets */ ++ int pkt_align; + }; + #define to_phy_device(d) container_of(d, struct phy_device, dev) + +@@ -508,6 +522,7 @@ + void phy_stop_machine(struct phy_device *phydev); + int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd); + int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd); ++int phy_ethtool_ioctl(struct phy_device *phydev, void *useraddr); + int phy_mii_ioctl(struct phy_device *phydev, + struct ifreq *ifr, int cmd); + int phy_start_interrupts(struct phy_device *phydev); +diff -Nur linux-2.6.39.orig/include/linux/spi/vsc7385.h linux-2.6.39/include/linux/spi/vsc7385.h +--- linux-2.6.39.orig/include/linux/spi/vsc7385.h 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/include/linux/spi/vsc7385.h 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,19 @@ ++/* ++ * Platform data definition for the Vitesse VSC7385 ethernet switch driver ++ * ++ * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ */ ++ ++struct vsc7385_platform_data { ++ void (* reset)(void); ++ char *ucode_name; ++ struct { ++ u32 tx_ipg:5; ++ u32 bit2:1; ++ u32 clk_sel:3; ++ } mac_cfg; ++}; +diff -Nur linux-2.6.39.orig/net/dsa/ar7240.c linux-2.6.39/net/dsa/ar7240.c +--- linux-2.6.39.orig/net/dsa/ar7240.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/net/dsa/ar7240.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,736 @@ ++/* ++ * DSA driver for the built-in ethernet switch of the Atheros AR7240 SoC ++ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This file was based on: ++ * net/dsa/mv88e6060.c - Driver for Marvell 88e6060 switch chips ++ * Copyright (c) 2008 Marvell Semiconductor ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published ++ * by the Free Software Foundation. ++ * ++ */ ++ ++#include <linux/etherdevice.h> ++#include <linux/list.h> ++#include <linux/netdevice.h> ++#include <linux/phy.h> ++#include <linux/mii.h> ++#include <linux/bitops.h> ++ ++#include "dsa_priv.h" ++ ++#define BITM(_count) (BIT(_count) - 1) ++ ++#define AR7240_REG_MASK_CTRL 0x00 ++#define AR7240_MASK_CTRL_REVISION_M BITM(8) ++#define AR7240_MASK_CTRL_VERSION_M BITM(8) ++#define AR7240_MASK_CTRL_VERSION_S 8 ++#define AR7240_MASK_CTRL_SOFT_RESET BIT(31) ++ ++#define AR7240_REG_MAC_ADDR0 0x20 ++#define AR7240_REG_MAC_ADDR1 0x24 ++ ++#define AR7240_REG_FLOOD_MASK 0x2c ++#define AR7240_FLOOD_MASK_BROAD_TO_CPU BIT(26) ++ ++#define AR7240_REG_GLOBAL_CTRL 0x30 ++#define AR7240_GLOBAL_CTRL_MTU_M BITM(12) ++ ++#define AR7240_REG_AT_CTRL 0x5c ++#define AR7240_AT_CTRL_ARP_EN BIT(20) ++ ++#define AR7240_REG_TAG_PRIORITY 0x70 ++ ++#define AR7240_REG_SERVICE_TAG 0x74 ++#define AR7240_SERVICE_TAG_M BITM(16) ++ ++#define AR7240_REG_CPU_PORT 0x78 ++#define AR7240_MIRROR_PORT_S 4 ++#define AR7240_CPU_PORT_EN BIT(8) ++ ++#define AR7240_REG_MIB_FUNCTION0 0x80 ++#define AR7240_MIB_TIMER_M BITM(16) ++#define AR7240_MIB_AT_HALF_EN BIT(16) ++#define AR7240_MIB_BUSY BIT(17) ++#define AR7240_MIB_FUNC_S 24 ++#define AR7240_MIB_FUNC_NO_OP 0x0 ++#define AR7240_MIB_FUNC_FLUSH 0x1 ++#define AR7240_MIB_FUNC_CAPTURE 0x3 ++ ++#define AR7240_REG_MDIO_CTRL 0x98 ++#define AR7240_MDIO_CTRL_DATA_M BITM(16) ++#define AR7240_MDIO_CTRL_REG_ADDR_S 16 ++#define AR7240_MDIO_CTRL_PHY_ADDR_S 21 ++#define AR7240_MDIO_CTRL_CMD_WRITE 0 ++#define AR7240_MDIO_CTRL_CMD_READ BIT(27) ++#define AR7240_MDIO_CTRL_MASTER_EN BIT(30) ++#define AR7240_MDIO_CTRL_BUSY BIT(31) ++ ++#define AR7240_REG_PORT_BASE(_port) (0x100 + (_port) * 0x100) ++ ++#define AR7240_REG_PORT_STATUS(_port) (AR7240_REG_PORT_BASE((_port)) + 0x00) ++#define AR7240_PORT_STATUS_SPEED_M BITM(2) ++#define AR7240_PORT_STATUS_SPEED_10 0 ++#define AR7240_PORT_STATUS_SPEED_100 1 ++#define AR7240_PORT_STATUS_SPEED_1000 2 ++#define AR7240_PORT_STATUS_TXMAC BIT(2) ++#define AR7240_PORT_STATUS_RXMAC BIT(3) ++#define AR7240_PORT_STATUS_TXFLOW BIT(4) ++#define AR7240_PORT_STATUS_RXFLOW BIT(5) ++#define AR7240_PORT_STATUS_DUPLEX BIT(6) ++#define AR7240_PORT_STATUS_LINK_UP BIT(8) ++#define AR7240_PORT_STATUS_LINK_AUTO BIT(9) ++#define AR7240_PORT_STATUS_LINK_PAUSE BIT(10) ++ ++#define AR7240_REG_PORT_CTRL(_port) (AR7240_REG_PORT_BASE((_port)) + 0x04) ++#define AR7240_PORT_CTRL_STATE_M BITM(3) ++#define AR7240_PORT_CTRL_STATE_DISABLED 0 ++#define AR7240_PORT_CTRL_STATE_BLOCK 1 ++#define AR7240_PORT_CTRL_STATE_LISTEN 2 ++#define AR7240_PORT_CTRL_STATE_LEARN 3 ++#define AR7240_PORT_CTRL_STATE_FORWARD 4 ++#define AR7240_PORT_CTRL_LEARN_LOCK BIT(7) ++#define AR7240_PORT_CTRL_VLAN_MODE_S 8 ++#define AR7240_PORT_CTRL_VLAN_MODE_KEEP 0 ++#define AR7240_PORT_CTRL_VLAN_MODE_STRIP 1 ++#define AR7240_PORT_CTRL_VLAN_MODE_ADD 2 ++#define AR7240_PORT_CTRL_VLAN_MODE_DOUBLE_TAG 3 ++#define AR7240_PORT_CTRL_IGMP_SNOOP BIT(10) ++#define AR7240_PORT_CTRL_HEADER BIT(11) ++#define AR7240_PORT_CTRL_MAC_LOOP BIT(12) ++#define AR7240_PORT_CTRL_SINGLE_VLAN BIT(13) ++#define AR7240_PORT_CTRL_LEARN BIT(14) ++#define AR7240_PORT_CTRL_DOUBLE_TAG BIT(15) ++#define AR7240_PORT_CTRL_MIRROR_TX BIT(16) ++#define AR7240_PORT_CTRL_MIRROR_RX BIT(17) ++ ++#define AR7240_REG_PORT_VLAN(_port) (AR7240_REG_PORT_BASE((_port)) + 0x08) ++ ++#define AR7240_PORT_VLAN_DEFAULT_ID_S 0 ++#define AR7240_PORT_VLAN_DEST_PORTS_S 16 ++ ++#define AR7240_REG_STATS_BASE(_port) (0x20000 + (_port) * 0x100) ++ ++#define AR7240_STATS_RXBROAD 0x00 ++#define AR7240_STATS_RXPAUSE 0x04 ++#define AR7240_STATS_RXMULTI 0x08 ++#define AR7240_STATS_RXFCSERR 0x0c ++#define AR7240_STATS_RXALIGNERR 0x10 ++#define AR7240_STATS_RXRUNT 0x14 ++#define AR7240_STATS_RXFRAGMENT 0x18 ++#define AR7240_STATS_RX64BYTE 0x1c ++#define AR7240_STATS_RX128BYTE 0x20 ++#define AR7240_STATS_RX256BYTE 0x24 ++#define AR7240_STATS_RX512BYTE 0x28 ++#define AR7240_STATS_RX1024BYTE 0x2c ++#define AR7240_STATS_RX1518BYTE 0x30 ++#define AR7240_STATS_RXMAXBYTE 0x34 ++#define AR7240_STATS_RXTOOLONG 0x38 ++#define AR7240_STATS_RXGOODBYTE 0x3c ++#define AR7240_STATS_RXBADBYTE 0x44 ++#define AR7240_STATS_RXOVERFLOW 0x4c ++#define AR7240_STATS_FILTERED 0x50 ++#define AR7240_STATS_TXBROAD 0x54 ++#define AR7240_STATS_TXPAUSE 0x58 ++#define AR7240_STATS_TXMULTI 0x5c ++#define AR7240_STATS_TXUNDERRUN 0x60 ++#define AR7240_STATS_TX64BYTE 0x64 ++#define AR7240_STATS_TX128BYTE 0x68 ++#define AR7240_STATS_TX256BYTE 0x6c ++#define AR7240_STATS_TX512BYTE 0x70 ++#define AR7240_STATS_TX1024BYTE 0x74 ++#define AR7240_STATS_TX1518BYTE 0x78 ++#define AR7240_STATS_TXMAXBYTE 0x7c ++#define AR7240_STATS_TXOVERSIZE 0x80 ++#define AR7240_STATS_TXBYTE 0x84 ++#define AR7240_STATS_TXCOLLISION 0x8c ++#define AR7240_STATS_TXABORTCOL 0x90 ++#define AR7240_STATS_TXMULTICOL 0x94 ++#define AR7240_STATS_TXSINGLECOL 0x98 ++#define AR7240_STATS_TXEXCDEFER 0x9c ++#define AR7240_STATS_TXDEFER 0xa0 ++#define AR7240_STATS_TXLATECOL 0xa4 ++ ++#define AR7240_PORT_CPU 0 ++#define AR7240_NUM_PORTS 6 ++#define AR7240_NUM_PHYS 5 ++ ++#define AR7240_PHY_ID1 0x004d ++#define AR7240_PHY_ID2 0xd041 ++ ++#define AR7240_PORT_MASK(_port) BIT((_port)) ++#define AR7240_PORT_MASK_ALL BITM(AR7240_NUM_PORTS) ++#define AR7240_PORT_MASK_BUT(_port) (AR7240_PORT_MASK_ALL & ~BIT((_port))) ++ ++struct ar7240sw { ++ struct mii_bus *mii_bus; ++ struct mutex reg_mutex; ++ struct mutex stats_mutex; ++}; ++ ++struct ar7240sw_hw_stat { ++ char string[ETH_GSTRING_LEN]; ++ int sizeof_stat; ++ int reg; ++}; ++ ++static inline struct ar7240sw *dsa_to_ar7240sw(struct dsa_switch *ds) ++{ ++ return (struct ar7240sw *)(ds + 1); ++} ++ ++static inline void ar7240sw_init(struct ar7240sw *as, struct mii_bus *mii) ++{ ++ as->mii_bus = mii; ++ mutex_init(&as->reg_mutex); ++ mutex_init(&as->stats_mutex); ++} ++ ++static inline u16 mk_phy_addr(u32 reg) ++{ ++ return (0x17 & ((reg >> 4) | 0x10)); ++} ++ ++static inline u16 mk_phy_reg(u32 reg) ++{ ++ return ((reg << 1) & 0x1e); ++} ++ ++static inline u16 mk_high_addr(u32 reg) ++{ ++ return ((reg >> 7) & 0x1ff); ++} ++ ++static u32 __ar7240sw_reg_read(struct ar7240sw *as, u32 reg) ++{ ++ struct mii_bus *mii = as->mii_bus; ++ u16 phy_addr; ++ u16 phy_reg; ++ u32 hi, lo; ++ ++ reg = (reg & 0xfffffffc) >> 2; ++ ++ mdiobus_write(mii, 0x1f, 0x10, mk_high_addr(reg)); ++ ++ phy_addr = mk_phy_addr(reg); ++ phy_reg = mk_phy_reg(reg); ++ ++ lo = (u32) mdiobus_read(mii, phy_addr, phy_reg); ++ hi = (u32) mdiobus_read(mii, phy_addr, phy_reg + 1); ++ ++ return ((hi << 16) | lo); ++} ++ ++static void __ar7240sw_reg_write(struct ar7240sw *as, u32 reg, u32 val) ++{ ++ struct mii_bus *mii = as->mii_bus; ++ u16 phy_addr; ++ u16 phy_reg; ++ ++ reg = (reg & 0xfffffffc) >> 2; ++ ++ mdiobus_write(mii, 0x1f, 0x10, mk_high_addr(reg)); ++ ++ phy_addr = mk_phy_addr(reg); ++ phy_reg = mk_phy_reg(reg); ++ ++ mdiobus_write(mii, phy_addr, phy_reg + 1, (val >> 16)); ++ mdiobus_write(mii, phy_addr, phy_reg, (val & 0xffff)); ++} ++ ++static u32 ar7240sw_reg_read(struct ar7240sw *as, u32 reg_addr) ++{ ++ u32 ret; ++ ++ mutex_lock(&as->reg_mutex); ++ ret = __ar7240sw_reg_read(as, reg_addr); ++ mutex_unlock(&as->reg_mutex); ++ ++ return ret; ++} ++ ++static void ar7240sw_reg_write(struct ar7240sw *as, u32 reg_addr, u32 reg_val) ++{ ++ mutex_lock(&as->reg_mutex); ++ __ar7240sw_reg_write(as, reg_addr, reg_val); ++ mutex_unlock(&as->reg_mutex); ++} ++ ++static u32 ar7240sw_reg_rmw(struct ar7240sw *as, u32 reg, u32 mask, u32 val) ++{ ++ u32 t; ++ ++ mutex_lock(&as->reg_mutex); ++ t = __ar7240sw_reg_read(as, reg); ++ t &= ~mask; ++ t |= val; ++ __ar7240sw_reg_write(as, reg, t); ++ mutex_unlock(&as->reg_mutex); ++ ++ return t; ++} ++ ++static void ar7240sw_reg_set(struct ar7240sw *as, u32 reg, u32 val) ++{ ++ u32 t; ++ ++ mutex_lock(&as->reg_mutex); ++ t = __ar7240sw_reg_read(as, reg); ++ t |= val; ++ __ar7240sw_reg_write(as, reg, t); ++ mutex_unlock(&as->reg_mutex); ++} ++ ++static int ar7240sw_reg_wait(struct ar7240sw *as, u32 reg, u32 mask, u32 val, ++ unsigned timeout) ++{ ++ int i; ++ ++ for (i = 0; i < timeout; i++) { ++ u32 t; ++ ++ t = ar7240sw_reg_read(as, reg); ++ if ((t & mask) == val) ++ return 0; ++ ++ msleep(1); ++ } ++ ++ return -ETIMEDOUT; ++} ++ ++static u16 ar7240sw_phy_read(struct ar7240sw *as, unsigned phy_addr, ++ unsigned reg_addr) ++{ ++ u32 t; ++ int err; ++ ++ if (phy_addr >= AR7240_NUM_PHYS) ++ return 0xffff; ++ ++ t = (reg_addr << AR7240_MDIO_CTRL_REG_ADDR_S) | ++ (phy_addr << AR7240_MDIO_CTRL_PHY_ADDR_S) | ++ AR7240_MDIO_CTRL_MASTER_EN | ++ AR7240_MDIO_CTRL_BUSY | ++ AR7240_MDIO_CTRL_CMD_READ; ++ ++ ar7240sw_reg_write(as, AR7240_REG_MDIO_CTRL, t); ++ err = ar7240sw_reg_wait(as, AR7240_REG_MDIO_CTRL, ++ AR7240_MDIO_CTRL_BUSY, 0, 5); ++ if (err) ++ return 0xffff; ++ ++ t = ar7240sw_reg_read(as, AR7240_REG_MDIO_CTRL); ++ return (t & AR7240_MDIO_CTRL_DATA_M); ++} ++ ++static int ar7240sw_phy_write(struct ar7240sw *as, unsigned phy_addr, ++ unsigned reg_addr, u16 reg_val) ++{ ++ u32 t; ++ int ret; ++ ++ if (phy_addr >= AR7240_NUM_PHYS) ++ return -EINVAL; ++ ++ t = (phy_addr << AR7240_MDIO_CTRL_PHY_ADDR_S) | ++ (reg_addr << AR7240_MDIO_CTRL_REG_ADDR_S) | ++ AR7240_MDIO_CTRL_MASTER_EN | ++ AR7240_MDIO_CTRL_BUSY | ++ AR7240_MDIO_CTRL_CMD_WRITE | ++ reg_val; ++ ++ ar7240sw_reg_write(as, AR7240_REG_MDIO_CTRL, t); ++ ret = ar7240sw_reg_wait(as, AR7240_REG_MDIO_CTRL, ++ AR7240_MDIO_CTRL_BUSY, 0, 5); ++ return ret; ++} ++ ++static int ar7240sw_capture_stats(struct ar7240sw *as) ++{ ++ int ret; ++ ++ /* Capture the hardware statistics for all ports */ ++ ar7240sw_reg_write(as, AR7240_REG_MIB_FUNCTION0, ++ (AR7240_MIB_FUNC_CAPTURE << AR7240_MIB_FUNC_S)); ++ ++ /* Wait for the capturing to complete. */ ++ ret = ar7240sw_reg_wait(as, AR7240_REG_MIB_FUNCTION0, ++ AR7240_MIB_BUSY, 0, 10); ++ return ret; ++} ++ ++static void ar7240sw_disable_port(struct ar7240sw *as, unsigned port) ++{ ++ ar7240sw_reg_write(as, AR7240_REG_PORT_CTRL(port), ++ AR7240_PORT_CTRL_STATE_DISABLED); ++} ++ ++static int ar7240sw_reset(struct ar7240sw *as) ++{ ++ int ret; ++ int i; ++ ++ /* Set all ports to disabled state. */ ++ for (i = 0; i < AR7240_NUM_PORTS; i++) ++ ar7240sw_disable_port(as, i); ++ ++ /* Wait for transmit queues to drain. */ ++ msleep(2); ++ ++ /* Reset the switch. */ ++ ar7240sw_reg_write(as, AR7240_REG_MASK_CTRL, ++ AR7240_MASK_CTRL_SOFT_RESET); ++ ++ ret = ar7240sw_reg_wait(as, AR7240_REG_MASK_CTRL, ++ AR7240_MASK_CTRL_SOFT_RESET, 0, 1000); ++ return ret; ++} ++ ++static void ar7240sw_setup(struct ar7240sw *as) ++{ ++ /* Enable CPU port, and disable mirror port */ ++ ar7240sw_reg_write(as, AR7240_REG_CPU_PORT, ++ AR7240_CPU_PORT_EN | ++ (15 << AR7240_MIRROR_PORT_S)); ++ ++ /* Setup TAG priority mapping */ ++ ar7240sw_reg_write(as, AR7240_REG_TAG_PRIORITY, 0xfa50); ++ ++ /* Enable ARP frame acknowledge */ ++ ar7240sw_reg_set(as, AR7240_REG_AT_CTRL, AR7240_AT_CTRL_ARP_EN); ++ ++ /* Enable Broadcast frames transmitted to the CPU */ ++ ar7240sw_reg_set(as, AR7240_REG_FLOOD_MASK, ++ AR7240_FLOOD_MASK_BROAD_TO_CPU); ++ ++ /* setup MTU */ ++ ar7240sw_reg_rmw(as, AR7240_REG_GLOBAL_CTRL, AR7240_GLOBAL_CTRL_MTU_M, ++ 1536); ++ ++ /* setup Service TAG */ ++ ar7240sw_reg_rmw(as, AR7240_REG_SERVICE_TAG, AR7240_SERVICE_TAG_M, ++ ETH_P_QINQ); ++} ++ ++static void ar7240sw_setup_port(struct ar7240sw *as, unsigned port) ++{ ++ u32 ctrl; ++ u32 dest_ports; ++ u32 vlan; ++ ++ ctrl = AR7240_PORT_CTRL_STATE_FORWARD; ++ ++ if (port == AR7240_PORT_CPU) { ++ ar7240sw_reg_write(as, AR7240_REG_PORT_STATUS(port), ++ AR7240_PORT_STATUS_SPEED_1000 | ++ AR7240_PORT_STATUS_TXFLOW | ++ AR7240_PORT_STATUS_RXFLOW | ++ AR7240_PORT_STATUS_TXMAC | ++ AR7240_PORT_STATUS_RXMAC | ++ AR7240_PORT_STATUS_DUPLEX); ++ ++ /* allow the CPU port to talk to each of the 'real' ports */ ++ dest_ports = AR7240_PORT_MASK_BUT(port); ++ ++ /* remove service tag from ingress frames */ ++ ctrl |= AR7240_PORT_CTRL_DOUBLE_TAG; ++ } else { ++ ar7240sw_reg_write(as, AR7240_REG_PORT_STATUS(port), ++ AR7240_PORT_STATUS_LINK_AUTO); ++ ++ /* ++ * allow each of the 'real' ports to only talk to the CPU ++ * port. ++ */ ++ dest_ports = AR7240_PORT_MASK(port) | ++ AR7240_PORT_MASK(AR7240_PORT_CPU); ++ ++ /* add service tag to egress frames */ ++ ctrl |= (AR7240_PORT_CTRL_VLAN_MODE_DOUBLE_TAG << ++ AR7240_PORT_CTRL_VLAN_MODE_S); ++ } ++ ++ /* set default VID and and destination ports for this VLAN */ ++ vlan = port; ++ vlan |= (dest_ports << AR7240_PORT_VLAN_DEST_PORTS_S); ++ ++ ar7240sw_reg_write(as, AR7240_REG_PORT_CTRL(port), ctrl); ++ ar7240sw_reg_write(as, AR7240_REG_PORT_VLAN(port), vlan); ++} ++ ++static char *ar7240_dsa_probe(struct mii_bus *mii, int sw_addr) ++{ ++ struct ar7240sw as; ++ u32 ctrl; ++ u16 phy_id1; ++ u16 phy_id2; ++ u8 ver; ++ ++ ar7240sw_init(&as, mii); ++ ++ ctrl = ar7240sw_reg_read(&as, AR7240_REG_MASK_CTRL); ++ ++ ver = (ctrl >> AR7240_MASK_CTRL_VERSION_S) & AR7240_MASK_CTRL_VERSION_M; ++ if (ver != 1) { ++ pr_err("ar7240_dsa: unsupported chip, ctrl=%08x\n", ctrl); ++ return NULL; ++ } ++ ++ phy_id1 = ar7240sw_phy_read(&as, 0, MII_PHYSID1); ++ phy_id2 = ar7240sw_phy_read(&as, 0, MII_PHYSID2); ++ if (phy_id1 != AR7240_PHY_ID1 || phy_id2 != AR7240_PHY_ID2) { ++ pr_err("ar7240_dsa: unknown phy id '%04x:%04x'\n", ++ phy_id1, phy_id2); ++ return NULL; ++ } ++ ++ return "Atheros AR7240 built-in"; ++} ++ ++static int ar7240_dsa_setup(struct dsa_switch *ds) ++{ ++ struct ar7240sw *as = dsa_to_ar7240sw(ds); ++ int i; ++ int ret; ++ ++ ar7240sw_init(as, ds->master_mii_bus); ++ ++ ret = ar7240sw_reset(as); ++ if (ret) ++ return ret; ++ ++ ar7240sw_setup(as); ++ ++ for (i = 0; i < AR7240_NUM_PORTS; i++) { ++ if (dsa_is_cpu_port(ds, i) || (ds->phys_port_mask & (1 << i))) ++ ar7240sw_setup_port(as, i); ++ else ++ ar7240sw_disable_port(as, i); ++ } ++ ++ return 0; ++} ++ ++static int ar7240_dsa_set_addr(struct dsa_switch *ds, u8 *addr) ++{ ++ struct ar7240sw *as = dsa_to_ar7240sw(ds); ++ u32 t; ++ ++ t = (addr[4] << 8) | addr[5]; ++ ar7240sw_reg_write(as, AR7240_REG_MAC_ADDR0, t); ++ ++ t = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3]; ++ ar7240sw_reg_write(as, AR7240_REG_MAC_ADDR1, t); ++ ++ return 0; ++} ++ ++static int ar7240_iort_to_phy_addr(int port) ++{ ++ if (port > 0 && port < AR7240_NUM_PORTS) ++ return port - 1; ++ ++ return -EINVAL; ++} ++ ++static int ar7240_dsa_phy_read(struct dsa_switch *ds, int port, int regnum) ++{ ++ struct ar7240sw *as = dsa_to_ar7240sw(ds); ++ int phy_addr; ++ ++ phy_addr = ar7240_iort_to_phy_addr(port); ++ if (phy_addr < 0) ++ return 0xffff; ++ ++ return ar7240sw_phy_read(as, phy_addr, regnum); ++} ++ ++static int ar7240_dsa_phy_write(struct dsa_switch *ds, int port, int regnum, ++ u16 val) ++{ ++ struct ar7240sw *as = dsa_to_ar7240sw(ds); ++ int phy_addr; ++ ++ phy_addr = ar7240_iort_to_phy_addr(port); ++ if (phy_addr < 0) ++ return 0xffff; ++ ++ return ar7240sw_phy_write(as, phy_addr, regnum, val); ++} ++ ++static const char *ar7240sw_speed_str(unsigned speed) ++{ ++ switch (speed) { ++ case AR7240_PORT_STATUS_SPEED_10: ++ return "10"; ++ case AR7240_PORT_STATUS_SPEED_100: ++ return "100"; ++ case AR7240_PORT_STATUS_SPEED_1000: ++ return "1000"; ++ } ++ ++ return "????"; ++} ++ ++static void ar7240_dsa_poll_link(struct dsa_switch *ds) ++{ ++ struct ar7240sw *as = dsa_to_ar7240sw(ds); ++ int i; ++ ++ for (i = 0; i < DSA_MAX_PORTS; i++) { ++ struct net_device *dev; ++ u32 status; ++ int link; ++ unsigned speed; ++ int duplex; ++ ++ dev = ds->ports[i]; ++ if (dev == NULL) ++ continue; ++ ++ link = 0; ++ if (dev->flags & IFF_UP) { ++ status = ar7240sw_reg_read(as, ++ AR7240_REG_PORT_STATUS(i)); ++ link = !!(status & AR7240_PORT_STATUS_LINK_UP); ++ } ++ ++ if (!link) { ++ if (netif_carrier_ok(dev)) { ++ pr_info("%s: link down\n", dev->name); ++ netif_carrier_off(dev); ++ } ++ continue; ++ } ++ ++ speed = (status & AR7240_PORT_STATUS_SPEED_M); ++ duplex = (status & AR7240_PORT_STATUS_DUPLEX) ? 1 : 0; ++ if (!netif_carrier_ok(dev)) { ++ pr_info("%s: link up, %sMb/s, %s duplex", ++ dev->name, ++ ar7240sw_speed_str(speed), ++ duplex ? "full" : "half"); ++ netif_carrier_on(dev); ++ } ++ } ++} ++ ++static const struct ar7240sw_hw_stat ar7240_hw_stats[] = { ++ { "rx_broadcast" , 4, AR7240_STATS_RXBROAD, }, ++ { "rx_pause" , 4, AR7240_STATS_RXPAUSE, }, ++ { "rx_multicast" , 4, AR7240_STATS_RXMULTI, }, ++ { "rx_fcs_error" , 4, AR7240_STATS_RXFCSERR, }, ++ { "rx_align_error" , 4, AR7240_STATS_RXALIGNERR, }, ++ { "rx_undersize" , 4, AR7240_STATS_RXRUNT, }, ++ { "rx_fragments" , 4, AR7240_STATS_RXFRAGMENT, }, ++ { "rx_64bytes" , 4, AR7240_STATS_RX64BYTE, }, ++ { "rx_65_127bytes" , 4, AR7240_STATS_RX128BYTE, }, ++ { "rx_128_255bytes" , 4, AR7240_STATS_RX256BYTE, }, ++ { "rx_256_511bytes" , 4, AR7240_STATS_RX512BYTE, }, ++ { "rx_512_1023bytes" , 4, AR7240_STATS_RX1024BYTE, }, ++ { "rx_1024_1518bytes" , 4, AR7240_STATS_RX1518BYTE, }, ++ { "rx_1519_max_bytes" , 4, AR7240_STATS_RXMAXBYTE, }, ++ { "rx_oversize" , 4, AR7240_STATS_RXTOOLONG, }, ++ { "rx_good_bytes" , 8, AR7240_STATS_RXGOODBYTE, }, ++ { "rx_bad_bytes" , 8, AR7240_STATS_RXBADBYTE, }, ++ { "rx_overflow" , 4, AR7240_STATS_RXOVERFLOW, }, ++ { "filtered" , 4, AR7240_STATS_FILTERED, }, ++ { "tx_broadcast" , 4, AR7240_STATS_TXBROAD, }, ++ { "tx_pause" , 4, AR7240_STATS_TXPAUSE, }, ++ { "tx_multicast" , 4, AR7240_STATS_TXMULTI, }, ++ { "tx_underrun" , 4, AR7240_STATS_TXUNDERRUN, }, ++ { "tx_64bytes" , 4, AR7240_STATS_TX64BYTE, }, ++ { "tx_65_127bytes" , 4, AR7240_STATS_TX128BYTE, }, ++ { "tx_128_255bytes" , 4, AR7240_STATS_TX256BYTE, }, ++ { "tx_256_511bytes" , 4, AR7240_STATS_TX512BYTE, }, ++ { "tx_512_1023bytes" , 4, AR7240_STATS_TX1024BYTE, }, ++ { "tx_1024_1518bytes" , 4, AR7240_STATS_TX1518BYTE, }, ++ { "tx_1519_max_bytes" , 4, AR7240_STATS_TXMAXBYTE, }, ++ { "tx_oversize" , 4, AR7240_STATS_TXOVERSIZE, }, ++ { "tx_bytes" , 8, AR7240_STATS_TXBYTE, }, ++ { "tx_collisions" , 4, AR7240_STATS_TXCOLLISION, }, ++ { "tx_abort_collisions" , 4, AR7240_STATS_TXABORTCOL, }, ++ { "tx_multi_collisions" , 4, AR7240_STATS_TXMULTICOL, }, ++ { "tx_single_collisions", 4, AR7240_STATS_TXSINGLECOL, }, ++ { "tx_excessive_deferred", 4, AR7240_STATS_TXEXCDEFER, }, ++ { "tx_deferred" , 4, AR7240_STATS_TXDEFER, }, ++ { "tx_late_collisions" , 4, AR7240_STATS_TXLATECOL, }, ++}; ++ ++static void ar7240_dsa_get_strings(struct dsa_switch *ds, int port, ++ uint8_t *data) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(ar7240_hw_stats); i++) { ++ memcpy(data + i * ETH_GSTRING_LEN, ++ ar7240_hw_stats[i].string, ETH_GSTRING_LEN); ++ } ++} ++ ++static void ar7240_dsa_get_ethtool_stats(struct dsa_switch *ds, int port, ++ uint64_t *data) ++{ ++ struct ar7240sw *as = dsa_to_ar7240sw(ds); ++ int err; ++ int i; ++ ++ mutex_lock(&as->stats_mutex); ++ ++ err = ar7240sw_capture_stats(as); ++ if (err) ++ goto unlock; ++ ++ for (i = 0; i < ARRAY_SIZE(ar7240_hw_stats); i++) { ++ const struct ar7240sw_hw_stat *s = &ar7240_hw_stats[i]; ++ u32 reg = AR7240_REG_STATS_BASE(port); ++ u32 low; ++ u32 high; ++ ++ low = ar7240sw_reg_read(as, reg + s->reg); ++ if (s->sizeof_stat == 8) ++ high = ar7240sw_reg_read(as, reg + s->reg); ++ else ++ high = 0; ++ ++ data[i] = (((u64) high) << 32) | low; ++ } ++ ++ unlock: ++ mutex_unlock(&as->stats_mutex); ++} ++ ++static int ar7240_dsa_get_sset_count(struct dsa_switch *ds) ++{ ++ return ARRAY_SIZE(ar7240_hw_stats); ++} ++ ++static struct dsa_switch_driver ar7240_dsa_driver = { ++ .tag_protocol = htons(ETH_P_QINQ), ++ .priv_size = sizeof(struct ar7240sw), ++ .probe = ar7240_dsa_probe, ++ .setup = ar7240_dsa_setup, ++ .set_addr = ar7240_dsa_set_addr, ++ .phy_read = ar7240_dsa_phy_read, ++ .phy_write = ar7240_dsa_phy_write, ++ .poll_link = ar7240_dsa_poll_link, ++ .get_strings = ar7240_dsa_get_strings, ++ .get_ethtool_stats = ar7240_dsa_get_ethtool_stats, ++ .get_sset_count = ar7240_dsa_get_sset_count, ++}; ++ ++int __init dsa_ar7240_init(void) ++{ ++ register_switch_driver(&ar7240_dsa_driver); ++ return 0; ++} ++module_init(dsa_ar7240_init); ++ ++void __exit dsa_ar7240_cleanup(void) ++{ ++ unregister_switch_driver(&ar7240_dsa_driver); ++} ++module_exit(dsa_ar7240_cleanup); +diff -Nur linux-2.6.39.orig/net/dsa/mv88e6063.c linux-2.6.39/net/dsa/mv88e6063.c +--- linux-2.6.39.orig/net/dsa/mv88e6063.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/net/dsa/mv88e6063.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,294 @@ ++/* ++ * net/dsa/mv88e6063.c - Driver for Marvell 88e6063 switch chips ++ * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This driver was base on: net/dsa/mv88e6060.c ++ * net/dsa/mv88e6063.c - Driver for Marvell 88e6060 switch chips ++ * Copyright (c) 2008-2009 Marvell Semiconductor ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include <linux/list.h> ++#include <linux/netdevice.h> ++#include <linux/phy.h> ++#include "dsa_priv.h" ++ ++#define REG_BASE 0x10 ++#define REG_PHY(p) (REG_BASE + (p)) ++#define REG_PORT(p) (REG_BASE + 8 + (p)) ++#define REG_GLOBAL (REG_BASE + 0x0f) ++#define NUM_PORTS 7 ++ ++static int reg_read(struct dsa_switch *ds, int addr, int reg) ++{ ++ return mdiobus_read(ds->master_mii_bus, addr, reg); ++} ++ ++#define REG_READ(addr, reg) \ ++ ({ \ ++ int __ret; \ ++ \ ++ __ret = reg_read(ds, addr, reg); \ ++ if (__ret < 0) \ ++ return __ret; \ ++ __ret; \ ++ }) ++ ++ ++static int reg_write(struct dsa_switch *ds, int addr, int reg, u16 val) ++{ ++ return mdiobus_write(ds->master_mii_bus, addr, reg, val); ++} ++ ++#define REG_WRITE(addr, reg, val) \ ++ ({ \ ++ int __ret; \ ++ \ ++ __ret = reg_write(ds, addr, reg, val); \ ++ if (__ret < 0) \ ++ return __ret; \ ++ }) ++ ++static char *mv88e6063_probe(struct mii_bus *bus, int sw_addr) ++{ ++ int ret; ++ ++ ret = mdiobus_read(bus, REG_PORT(0), 0x03); ++ if (ret >= 0) { ++ ret &= 0xfff0; ++ if (ret == 0x1530) ++ return "Marvell 88E6063"; ++ } ++ ++ return NULL; ++} ++ ++static int mv88e6063_switch_reset(struct dsa_switch *ds) ++{ ++ int i; ++ int ret; ++ ++ /* ++ * Set all ports to the disabled state. ++ */ ++ for (i = 0; i < NUM_PORTS; i++) { ++ ret = REG_READ(REG_PORT(i), 0x04); ++ REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc); ++ } ++ ++ /* ++ * Wait for transmit queues to drain. ++ */ ++ msleep(2); ++ ++ /* ++ * Reset the switch. ++ */ ++ REG_WRITE(REG_GLOBAL, 0x0a, 0xa130); ++ ++ /* ++ * Wait up to one second for reset to complete. ++ */ ++ for (i = 0; i < 1000; i++) { ++ ret = REG_READ(REG_GLOBAL, 0x00); ++ if ((ret & 0x8000) == 0x0000) ++ break; ++ ++ msleep(1); ++ } ++ if (i == 1000) ++ return -ETIMEDOUT; ++ ++ return 0; ++} ++ ++static int mv88e6063_setup_global(struct dsa_switch *ds) ++{ ++ /* ++ * Disable discarding of frames with excessive collisions, ++ * set the maximum frame size to 1536 bytes, and mask all ++ * interrupt sources. ++ */ ++ REG_WRITE(REG_GLOBAL, 0x04, 0x0800); ++ ++ /* ++ * Enable automatic address learning, set the address ++ * database size to 1024 entries, and set the default aging ++ * time to 5 minutes. ++ */ ++ REG_WRITE(REG_GLOBAL, 0x0a, 0x2130); ++ ++ return 0; ++} ++ ++static int mv88e6063_setup_port(struct dsa_switch *ds, int p) ++{ ++ int addr = REG_PORT(p); ++ ++ /* ++ * Do not force flow control, disable Ingress and Egress ++ * Header tagging, disable VLAN tunneling, and set the port ++ * state to Forwarding. Additionally, if this is the CPU ++ * port, enable Ingress and Egress Trailer tagging mode. ++ */ ++ REG_WRITE(addr, 0x04, dsa_is_cpu_port(ds, p) ? 0x4103 : 0x0003); ++ ++ /* ++ * Port based VLAN map: give each port its own address ++ * database, allow the CPU port to talk to each of the 'real' ++ * ports, and allow each of the 'real' ports to only talk to ++ * the CPU port. ++ */ ++ REG_WRITE(addr, 0x06, ++ ((p & 0xf) << 12) | ++ (dsa_is_cpu_port(ds, p) ? ++ ds->phys_port_mask : ++ (1 << ds->dst->cpu_port))); ++ ++ /* ++ * Port Association Vector: when learning source addresses ++ * of packets, add the address to the address database using ++ * a port bitmap that has only the bit for this port set and ++ * the other bits clear. ++ */ ++ REG_WRITE(addr, 0x0b, 1 << p); ++ ++ return 0; ++} ++ ++static int mv88e6063_setup(struct dsa_switch *ds) ++{ ++ int i; ++ int ret; ++ ++ ret = mv88e6063_switch_reset(ds); ++ if (ret < 0) ++ return ret; ++ ++ /* @@@ initialise atu */ ++ ++ ret = mv88e6063_setup_global(ds); ++ if (ret < 0) ++ return ret; ++ ++ for (i = 0; i < NUM_PORTS; i++) { ++ ret = mv88e6063_setup_port(ds, i); ++ if (ret < 0) ++ return ret; ++ } ++ ++ return 0; ++} ++ ++static int mv88e6063_set_addr(struct dsa_switch *ds, u8 *addr) ++{ ++ REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]); ++ REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]); ++ REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]); ++ ++ return 0; ++} ++ ++static int mv88e6063_port_to_phy_addr(int port) ++{ ++ if (port >= 0 && port <= NUM_PORTS) ++ return REG_PHY(port); ++ return -1; ++} ++ ++static int mv88e6063_phy_read(struct dsa_switch *ds, int port, int regnum) ++{ ++ int addr; ++ ++ addr = mv88e6063_port_to_phy_addr(port); ++ if (addr == -1) ++ return 0xffff; ++ ++ return reg_read(ds, addr, regnum); ++} ++ ++static int ++mv88e6063_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val) ++{ ++ int addr; ++ ++ addr = mv88e6063_port_to_phy_addr(port); ++ if (addr == -1) ++ return 0xffff; ++ ++ return reg_write(ds, addr, regnum, val); ++} ++ ++static void mv88e6063_poll_link(struct dsa_switch *ds) ++{ ++ int i; ++ ++ for (i = 0; i < DSA_MAX_PORTS; i++) { ++ struct net_device *dev; ++ int uninitialized_var(port_status); ++ int link; ++ int speed; ++ int duplex; ++ int fc; ++ ++ dev = ds->ports[i]; ++ if (dev == NULL) ++ continue; ++ ++ link = 0; ++ if (dev->flags & IFF_UP) { ++ port_status = reg_read(ds, REG_PORT(i), 0x00); ++ if (port_status < 0) ++ continue; ++ ++ link = !!(port_status & 0x1000); ++ } ++ ++ if (!link) { ++ if (netif_carrier_ok(dev)) { ++ printk(KERN_INFO "%s: link down\n", dev->name); ++ netif_carrier_off(dev); ++ } ++ continue; ++ } ++ ++ speed = (port_status & 0x0100) ? 100 : 10; ++ duplex = (port_status & 0x0200) ? 1 : 0; ++ fc = ((port_status & 0xc000) == 0xc000) ? 1 : 0; ++ ++ if (!netif_carrier_ok(dev)) { ++ printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, " ++ "flow control %sabled\n", dev->name, ++ speed, duplex ? "full" : "half", ++ fc ? "en" : "dis"); ++ netif_carrier_on(dev); ++ } ++ } ++} ++ ++static struct dsa_switch_driver mv88e6063_switch_driver = { ++ .tag_protocol = htons(ETH_P_TRAILER), ++ .probe = mv88e6063_probe, ++ .setup = mv88e6063_setup, ++ .set_addr = mv88e6063_set_addr, ++ .phy_read = mv88e6063_phy_read, ++ .phy_write = mv88e6063_phy_write, ++ .poll_link = mv88e6063_poll_link, ++}; ++ ++static int __init mv88e6063_init(void) ++{ ++ register_switch_driver(&mv88e6063_switch_driver); ++ return 0; ++} ++module_init(mv88e6063_init); ++ ++static void __exit mv88e6063_cleanup(void) ++{ ++ unregister_switch_driver(&mv88e6063_switch_driver); ++} ++module_exit(mv88e6063_cleanup); +diff -Nur linux-2.6.39.orig/net/dsa/tag_qinq.c linux-2.6.39/net/dsa/tag_qinq.c +--- linux-2.6.39.orig/net/dsa/tag_qinq.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.39/net/dsa/tag_qinq.c 2011-05-27 14:36:51.000000000 +0200 +@@ -0,0 +1,127 @@ ++/* ++ * net/dsa/tag_qinq.c - QinQ tag format handling ++ * Copyright (c) 2010 Gabor Juhos <juhosg@openwrt.org> ++ * ++ * This file was based on: ++ * net/dsa/tag_edsa.c - Ethertype DSA tagging ++ * Copyright (c) 2008-2009 Marvell Semiconductor ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include <linux/etherdevice.h> ++#include <linux/list.h> ++#include <linux/netdevice.h> ++#include <linux/if_vlan.h> ++ ++#include "dsa_priv.h" ++ ++netdev_tx_t qinq_xmit(struct sk_buff *skb, struct net_device *dev) ++{ ++ struct dsa_slave_priv *p = netdev_priv(dev); ++ struct vlan_ethhdr *veth; ++ unsigned int len; ++ int ret; ++ ++ if (skb_cow_head(skb, VLAN_HLEN) < 0) ++ goto out_free_skb; ++ ++ veth = (struct vlan_ethhdr *)skb_push(skb, VLAN_HLEN); ++ ++ /* Move the mac addresses to the beginning of the new header. */ ++ memmove(skb->data, skb->data + VLAN_HLEN, 2 * VLAN_ETH_ALEN); ++ skb->mac_header -= VLAN_HLEN; ++ ++ /* setup VLAN header fields */ ++ veth->h_vlan_proto = htons(ETH_P_QINQ); ++ veth->h_vlan_TCI = htons(p->port); ++ ++ len = skb->len; ++ skb->protocol = htons(ETH_P_QINQ); ++ skb->dev = p->parent->dst->master_netdev; ++ ++ ret = dev_queue_xmit(skb); ++ if (unlikely(ret != NET_XMIT_SUCCESS)) ++ goto out_dropped; ++ ++ dev->stats.tx_packets++; ++ dev->stats.tx_bytes += len; ++ ++ return NETDEV_TX_OK; ++ ++ out_free_skb: ++ kfree_skb(skb); ++ out_dropped: ++ dev->stats.tx_dropped++; ++ return NETDEV_TX_OK; ++} ++ ++static int qinq_rcv(struct sk_buff *skb, struct net_device *dev, ++ struct packet_type *pt, struct net_device *orig_dev) ++{ ++ struct dsa_switch_tree *dst; ++ struct dsa_switch *ds; ++ struct vlan_hdr *vhdr; ++ int source_port; ++ ++ dst = dev->dsa_ptr; ++ if (unlikely(dst == NULL)) ++ goto out_drop; ++ ds = dst->ds[0]; ++ ++ skb = skb_unshare(skb, GFP_ATOMIC); ++ if (skb == NULL) ++ goto out; ++ ++ if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) ++ goto out_drop; ++ ++ vhdr = (struct vlan_hdr *)skb->data; ++ source_port = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK; ++ if (source_port >= DSA_MAX_PORTS || ds->ports[source_port] == NULL) ++ goto out_drop; ++ ++ /* Remove the outermost VLAN tag and update checksum. */ ++ skb_pull_rcsum(skb, VLAN_HLEN); ++ memmove(skb->data - ETH_HLEN, ++ skb->data - ETH_HLEN - VLAN_HLEN, ++ 2 * ETH_ALEN); ++ ++ skb->dev = ds->ports[source_port]; ++ skb_push(skb, ETH_HLEN); ++ skb->pkt_type = PACKET_HOST; ++ skb->protocol = eth_type_trans(skb, skb->dev); ++ ++ skb->dev->stats.rx_packets++; ++ skb->dev->stats.rx_bytes += skb->len; ++ ++ netif_receive_skb(skb); ++ ++ return 0; ++ ++ out_drop: ++ kfree_skb(skb); ++ out: ++ return 0; ++} ++ ++static struct packet_type qinq_packet_type __read_mostly = { ++ .type = cpu_to_be16(ETH_P_QINQ), ++ .func = qinq_rcv, ++}; ++ ++static int __init qinq_init_module(void) ++{ ++ dev_add_pack(&qinq_packet_type); ++ return 0; ++} ++module_init(qinq_init_module); ++ ++static void __exit qinq_cleanup_module(void) ++{ ++ dev_remove_pack(&qinq_packet_type); ++} ++module_exit(qinq_cleanup_module); diff --git a/target/linux/patches/2.6.39/sparc-include.patch b/target/linux/patches/2.6.39/sparc-include.patch new file mode 100644 index 000000000..2f8ffd061 --- /dev/null +++ b/target/linux/patches/2.6.39/sparc-include.patch @@ -0,0 +1,11 @@ +diff -Nur linux-2.6.39-rc7.orig/arch/sparc/boot/btfixupprep.c linux-2.6.39-rc7/arch/sparc/boot/btfixupprep.c +--- linux-2.6.39-rc7.orig/arch/sparc/boot/btfixupprep.c 2011-05-10 04:33:54.000000000 +0200 ++++ linux-2.6.39-rc7/arch/sparc/boot/btfixupprep.c 2011-05-21 13:34:40.000000000 +0200 +@@ -25,7 +25,6 @@ + #include <errno.h> + #include <unistd.h> + #include <stdlib.h> +-#include <malloc.h> + + #define MAXSYMS 1024 + diff --git a/target/linux/patches/2.6.39/startup.patch b/target/linux/patches/2.6.39/startup.patch new file mode 100644 index 000000000..68e8987b0 --- /dev/null +++ b/target/linux/patches/2.6.39/startup.patch @@ -0,0 +1,20 @@ +diff -Nur linux-2.6.34.orig/init/main.c linux-2.6.34/init/main.c +--- linux-2.6.34.orig/init/main.c 2010-05-16 23:17:36.000000000 +0200 ++++ linux-2.6.34/init/main.c 2010-05-20 20:13:26.321613615 +0200 +@@ -842,6 +842,7 @@ + printk(KERN_WARNING "Failed to execute %s. Attempting " + "defaults...\n", execute_command); + } ++ run_init_process("/init"); + run_init_process("/sbin/init"); + run_init_process("/etc/init"); + run_init_process("/bin/init"); +@@ -889,6 +890,8 @@ + if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) + printk(KERN_WARNING "Warning: unable to open an initial console.\n"); + ++ printk(KERN_WARNING "Starting Linux (built with OpenADK).\n"); ++ + (void) sys_dup(0); + (void) sys_dup(0); + /* diff --git a/target/linux/patches/2.6.39/usb-defaults-off.patch b/target/linux/patches/2.6.39/usb-defaults-off.patch new file mode 100644 index 000000000..31367108a --- /dev/null +++ b/target/linux/patches/2.6.39/usb-defaults-off.patch @@ -0,0 +1,32 @@ +diff -Nur linux-2.6.37.orig//drivers/usb/core/Kconfig linux-2.6.37/drivers/usb/core/Kconfig +--- linux-2.6.37.orig//drivers/usb/core/Kconfig 2011-01-05 01:50:19.000000000 +0100 ++++ linux-2.6.37/drivers/usb/core/Kconfig 2011-04-12 19:04:23.000000000 +0200 +@@ -59,7 +59,7 @@ + config USB_DEVICE_CLASS + bool "USB device class-devices (DEPRECATED)" + depends on USB +- default y ++ default n + ---help--- + Userspace access to USB devices is granted by device-nodes exported + directly from the usbdev in sysfs. Old versions of the driver +diff -Nur linux-2.6.37.orig//drivers/usb/host/Kconfig linux-2.6.37/drivers/usb/host/Kconfig +--- linux-2.6.37.orig//drivers/usb/host/Kconfig 2011-01-05 01:50:19.000000000 +0100 ++++ linux-2.6.37/drivers/usb/host/Kconfig 2011-04-12 19:04:48.000000000 +0200 +@@ -62,6 +62,7 @@ + config USB_EHCI_ROOT_HUB_TT + bool "Root Hub Transaction Translators" + depends on USB_EHCI_HCD ++ default n + ---help--- + Some EHCI chips have vendor-specific extensions to integrate + transaction translators, so that no OHCI or UHCI companion +@@ -74,7 +75,7 @@ + config USB_EHCI_TT_NEWSCHED + bool "Improved Transaction Translator scheduling" + depends on USB_EHCI_HCD +- default y ++ default n + ---help--- + This changes the periodic scheduling code to fill more of the low + and full speed bandwidth available from the Transaction Translator diff --git a/target/linux/patches/2.6.39/uuid.patch b/target/linux/patches/2.6.39/uuid.patch new file mode 100644 index 000000000..2529fdab5 --- /dev/null +++ b/target/linux/patches/2.6.39/uuid.patch @@ -0,0 +1,255 @@ +diff -Nur linux-2.6.38.4.orig/block/genhd.c linux-2.6.38.4/block/genhd.c +--- linux-2.6.38.4.orig/block/genhd.c 2011-04-21 23:34:46.000000000 +0200 ++++ linux-2.6.38.4/block/genhd.c 2011-04-27 19:21:18.668912036 +0200 +@@ -34,7 +34,7 @@ + static DEFINE_MUTEX(ext_devt_mutex); + static DEFINE_IDR(ext_devt_idr); + +-static struct device_type disk_type; ++struct device_type disk_type; + + static void disk_add_events(struct gendisk *disk); + static void disk_del_events(struct gendisk *disk); +@@ -1118,7 +1118,7 @@ + return NULL; + } + +-static struct device_type disk_type = { ++struct device_type disk_type = { + .name = "disk", + .groups = disk_attr_groups, + .release = disk_release, +diff -Nur linux-2.6.38.4.orig/init/do_mounts.c linux-2.6.38.4/init/do_mounts.c +--- linux-2.6.38.4.orig/init/do_mounts.c 2011-04-21 23:34:46.000000000 +0200 ++++ linux-2.6.38.4/init/do_mounts.c 2011-04-27 19:26:52.721413000 +0200 +@@ -32,6 +32,132 @@ + + dev_t ROOT_DEV; + ++#ifdef CONFIG_EXT2_FS ++/* support for root=UUID=ce40d6b2-18eb-4a75-aefe-7ddb0995ce63 bootargs */ ++ ++#include <linux/ext2_fs.h> ++ ++__u8 root_dev_uuid[16]; ++int root_dev_type; /* 0 = normal (/dev/hda1, 0301); 1 = UUID; 3 = bad */ ++ ++/* imported from block/genhd.c after removing its static qualifier */ ++extern struct device_type disk_type; ++ ++/* helper function */ ++static __u8 __init fromhex(char c) ++{ ++ if (c >= '0' && c <= '9') ++ return (c - '0'); ++ c &= ~32; ++ if (c >= 'A' && c <= 'F') ++ return (c - 'A' + 10); ++ return (0xFF); ++} ++ ++static void __init parse_uuid(const char *s) ++{ ++ int i; ++ __u8 j, k; ++ ++ if (strlen(s) != 36 || s[8] != '-' || s[13] != '-' || ++ s[18] != '-' || s[23] != '-') ++ goto bad_uuid; ++ for (i = 0; i < 16; i++) { ++ if (*s == '-') ++ ++s; ++ j = fromhex(*s++); ++ k = fromhex(*s++); ++ if (j == 0xFF || k == 0xFF) ++ goto bad_uuid; ++ root_dev_uuid[i] = (j << 4) | k; ++ } ++ return; ++ bad_uuid: ++ /* we cannot panic here, defer */ ++ root_dev_type = 3; ++} ++ ++/* from drivers/md/md.c */ ++static void __init initcode_bi_complete(struct bio *bio, int error) ++{ ++ complete((struct completion*)bio->bi_private); ++} ++ ++static int __init initcode_sync_page_read(struct block_device *bdev, ++ sector_t sector, int size, struct page *page) ++{ ++ struct bio *bio = bio_alloc(GFP_NOIO, 1); ++ struct completion event; ++ int ret, rw = READ; ++ ++ rw |= REQ_SYNC; ++ ++ bio->bi_bdev = bdev; ++ bio->bi_sector = sector; ++ bio_add_page(bio, page, size, 0); ++ init_completion(&event); ++ bio->bi_private = &event; ++ bio->bi_end_io = initcode_bi_complete; ++ submit_bio(rw, bio); ++ wait_for_completion(&event); ++ ++ ret = test_bit(BIO_UPTODATE, &bio->bi_flags); ++ bio_put(bio); ++ /* 0 = failure */ ++ return ret; ++} ++ ++/* most of this taken from fs/ext2/super.c */ ++static int __init check_dev(struct gendisk *thedisk, dev_t devt, ++ int blocksize, struct page *page) ++{ ++ struct ext2_super_block * es; ++ struct block_device *bdev; ++ unsigned long sb_block = 1; ++ unsigned long logic_sb_block; ++ unsigned long offset = 0; ++ int rv = /* not found */ 0; ++ char bff[22]; ++ ++ bdev = bdget(devt); ++ if (blkdev_get(bdev, FMODE_READ, NULL)) { ++ printk(KERN_ERR "VFS: opening block device %s failed!\n", ++ format_dev_t(bff, devt)); ++ return (0); ++ } ++ ++ if (blocksize != BLOCK_SIZE) { ++ logic_sb_block = (sb_block*BLOCK_SIZE) / blocksize; ++ offset = (sb_block*BLOCK_SIZE) % blocksize; ++ } else { ++ logic_sb_block = sb_block; ++ } ++ ++// printk(KERN_ERR "D: attempting to read %d @%lu from " ++// "bdev %p devt %08X %s\n", blocksize, logic_sb_block, ++// bdev, devt, format_dev_t(bff, devt)); ++ if (!initcode_sync_page_read(bdev, logic_sb_block, blocksize, page)) { ++// printk(KERN_ERR "D: failed!\n"); ++ goto out; ++ } ++ es = (struct ext2_super_block *)(((char *)page_address(page)) + offset); ++ if (le16_to_cpu(es->s_magic) == EXT2_SUPER_MAGIC) { ++// printk(KERN_ERR "D: has uuid " ++// "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", ++// es->s_uuid[0], es->s_uuid[1], es->s_uuid[2], es->s_uuid[3], ++// es->s_uuid[4], es->s_uuid[5], es->s_uuid[6], es->s_uuid[7], ++// es->s_uuid[8], es->s_uuid[9], es->s_uuid[10], es->s_uuid[11], ++// es->s_uuid[12], es->s_uuid[13], es->s_uuid[14], es->s_uuid[15]); ++ if (!memcmp(es->s_uuid, root_dev_uuid, 16)) ++ rv = /* found */ 1; ++ } ++// else printk(KERN_ERR "D: bad ext2fs magic\n"); ++ out: ++ blkdev_put(bdev, FMODE_READ); ++ return (rv); ++} ++#endif /* CONFIG_EXT2_FS for UUID support */ ++ + static int __init load_ramdisk(char *str) + { + rd_doload = simple_strtol(str,NULL,0) & 3; +@@ -218,6 +344,13 @@ + static int __init root_dev_setup(char *line) + { + strlcpy(saved_root_name, line, sizeof(saved_root_name)); ++#ifdef CONFIG_EXT2_FS ++ root_dev_type = 0; ++ if (!strncmp(line, "UUID=", 5)) { ++ root_dev_type = 1; ++ parse_uuid(line + 5); ++ } ++#endif /* CONFIG_EXT2_FS for UUID support */ + return 1; + } + +@@ -403,6 +536,83 @@ + + void __init mount_root(void) + { ++#ifdef CONFIG_EXT2_FS ++ /* UUID support */ ++// printk_all_partitions(); ++ if (root_dev_type == 1) { ++ int blocksize; ++ ++ /* from block/genhd.c printk_all_partitions */ ++ struct class_dev_iter iter; ++ struct device *dev; ++ ++ /* from drivers/md/md.c */ ++ struct page *sb_page; ++ ++ if (!(sb_page = alloc_page(GFP_KERNEL))) { ++ printk(KERN_ERR "VFS: no memory for bio page\n"); ++ goto nomemforbio; ++ } ++ ++// printk(KERN_ERR "D: root is: " ++// "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", ++// root_dev_uuid[0], root_dev_uuid[1], root_dev_uuid[2], root_dev_uuid[3], ++// root_dev_uuid[4], root_dev_uuid[5], root_dev_uuid[6], root_dev_uuid[7], ++// root_dev_uuid[8], root_dev_uuid[9], root_dev_uuid[10], root_dev_uuid[11], ++// root_dev_uuid[12], root_dev_uuid[13], root_dev_uuid[14], root_dev_uuid[15]); ++ /* from block/genhd.c printk_all_partitions */ ++// printk(KERN_ERR "D: begin iter\n"); ++ class_dev_iter_init(&iter, &block_class, NULL, &disk_type); ++ while (root_dev_type && (dev = class_dev_iter_next(&iter))) { ++// char bff[22]; ++ struct gendisk *disk = dev_to_disk(dev); ++ struct disk_part_iter piter; ++ struct hd_struct *part; ++ if (get_capacity(disk) == 0 || ++ (disk->flags & GENHD_FL_SUPPRESS_PARTITION_INFO)) { ++// printk(KERN_ERR "D: ignoring\n"); ++ continue; ++ } ++ blocksize = queue_logical_block_size(disk->queue); ++// printk(KERN_ERR "D: gendisk, blocksize %d " ++// "name '%s' devt %08X %s #part %d\n", blocksize, ++// disk->disk_name, dev->devt, ++// format_dev_t(bff, dev->devt), ++// disk_max_parts(disk)); ++ disk_part_iter_init(&piter, disk, DISK_PITER_INCL_PART0); ++ while (root_dev_type && (part = disk_part_iter_next(&piter))) { ++ /* avoid empty or too small partitions */ ++// printk(KERN_ERR "D: part #%d start %llu " ++// "nr %llu\n", part->partno, ++// (__u64)part->start_sect, ++// (__u64)part->nr_sects); ++ if (part->nr_sects < 8) ++ continue; ++ if (check_dev(disk, MKDEV(MAJOR(dev->devt), ++ MINOR(dev->devt) + part->partno), ++ blocksize, sb_page)) { ++ ROOT_DEV = part_devt(part); ++// printk(KERN_ERR "D: got match!\n"); ++ // comment out below for debugging ++ root_dev_type = 0; ++ } ++ } ++ disk_part_iter_exit(&piter); ++ } ++// printk(KERN_ERR "D: end iter\n"); ++ class_dev_iter_exit(&iter); ++ put_page(sb_page); ++ } ++ nomemforbio: ++ if (root_dev_type == 1) ++ printk(KERN_ERR "VFS: Unable to find root by UUID %s.\n", ++ saved_root_name + 5); ++ else if (root_dev_type == 3) ++ /* execute deferred panic from parse_uuid */ ++ panic("Badly formatted UUID %s was supplied as kernel " ++ "parameter root", saved_root_name + 5); ++#endif /* CONFIG_EXT2_FS for UUID support */ ++ + #ifdef CONFIG_ROOT_NFS + if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) { + if (mount_nfs_root()) diff --git a/target/linux/patches/2.6.39/vga-cons-default-off.patch b/target/linux/patches/2.6.39/vga-cons-default-off.patch new file mode 100644 index 000000000..178aeeeb9 --- /dev/null +++ b/target/linux/patches/2.6.39/vga-cons-default-off.patch @@ -0,0 +1,12 @@ +diff -Nur linux-2.6.37.orig//drivers/video/console/Kconfig linux-2.6.37/drivers/video/console/Kconfig +--- linux-2.6.37.orig//drivers/video/console/Kconfig 2011-01-05 01:50:19.000000000 +0100 ++++ linux-2.6.37/drivers/video/console/Kconfig 2011-04-12 16:29:34.000000000 +0200 +@@ -7,7 +7,7 @@ + config VGA_CONSOLE + bool "VGA text console" if EMBEDDED || !X86 + depends on !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && !SUPERH && !BLACKFIN && !AVR32 && !MN10300 && (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER) +- default y ++ default n + help + Saying Y here will allow you to use Linux in text mode through a + display that complies with the generic VGA standard. Virtually diff --git a/target/linux/patches/2.6.39/x86-build.patch b/target/linux/patches/2.6.39/x86-build.patch new file mode 100644 index 000000000..339140f41 --- /dev/null +++ b/target/linux/patches/2.6.39/x86-build.patch @@ -0,0 +1,11 @@ +diff -Nur linux-2.6.39-rc6.orig/arch/x86/boot/tools/build.c linux-2.6.39-rc6/arch/x86/boot/tools/build.c +--- linux-2.6.39-rc6.orig/arch/x86/boot/tools/build.c 2011-05-04 04:59:13.000000000 +0200 ++++ linux-2.6.39-rc6/arch/x86/boot/tools/build.c 2011-05-05 20:10:07.000000000 +0200 +@@ -29,7 +29,6 @@ + #include <stdarg.h> + #include <sys/types.h> + #include <sys/stat.h> +-#include <sys/sysmacros.h> + #include <unistd.h> + #include <fcntl.h> + #include <sys/mman.h> diff --git a/target/linux/patches/2.6.39/zlib-inflate.patch b/target/linux/patches/2.6.39/zlib-inflate.patch new file mode 100644 index 000000000..58e1f6d21 --- /dev/null +++ b/target/linux/patches/2.6.39/zlib-inflate.patch @@ -0,0 +1,12 @@ +diff -Nur linux-2.6.37.orig/lib/Kconfig linux-2.6.37/lib/Kconfig +--- linux-2.6.37.orig/lib/Kconfig 2011-01-05 01:50:19.000000000 +0100 ++++ linux-2.6.37/lib/Kconfig 2011-03-01 20:10:29.833370667 +0100 +@@ -95,7 +95,7 @@ + # compression support is select'ed if needed + # + config ZLIB_INFLATE +- tristate ++ boolean + + config ZLIB_DEFLATE + tristate |