summaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/linux/lantiq/Makefile2
-rw-r--r--target/linux/lantiq/ar9/config-default52
-rw-r--r--target/linux/lantiq/ar9/profiles/001-lantiq.mk2
-rw-r--r--target/linux/lantiq/ar9/profiles/002-netgear.mk2
-rw-r--r--target/linux/lantiq/ar9/profiles/004-avm.mk7
-rw-r--r--target/linux/lantiq/ase/config-default39
-rw-r--r--target/linux/lantiq/config-3.2 (renamed from target/linux/lantiq/config-default)0
-rw-r--r--target/linux/lantiq/danube/config-default51
-rw-r--r--target/linux/lantiq/danube/profiles/004-bt.mk23
-rw-r--r--target/linux/lantiq/falcon/config-default18
-rw-r--r--target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-fritz.c77
-rw-r--r--target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-gigasx76x.c233
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/include/asm/mach-lantiq/dev-gpio-buttons.h (renamed from target/linux/lantiq/files-3.1/arch/mips/include/asm/mach-lantiq/dev-gpio-buttons.h)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/include/asm/mach-lantiq/dev-gpio-leds.h (renamed from target/linux/lantiq/files-3.1/arch/mips/include/asm/mach-lantiq/dev-gpio-leds.h)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/dev-gpio-buttons.c (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/dev-gpio-buttons.c)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/dev-gpio-leds.c (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/dev-gpio-leds.c)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/addon-easy98000.c (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/addon-easy98000.c)1
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/dev-leds-easy98000-cpld.c (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/dev-leds-easy98000-cpld.c)1
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/dev-leds-easy98000-cpld.h (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/dev-leds-easy98000-cpld.h)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/mach-95C3AM1.c (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/mach-95C3AM1.c)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/mach-easy98020.c (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/mach-easy98020.c)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-dwc_otg.c (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-dwc_otg.c)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-dwc_otg.h (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-dwc_otg.h)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-wifi-ath5k.c (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-wifi-ath5k.c)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-wifi-ath5k.h (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-wifi-ath5k.h)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-wifi-rt2x00.c (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-wifi-rt2x00.c)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-wifi-rt2x00.h (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-wifi-rt2x00.h)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-arv.c (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-arv45xx.c)425
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-bthomehubv2b.c542
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-easy50601.c (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-easy50601.c)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-easy50712.c (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-easy50712.c)0
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-fritz_ar9.c114
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-fritz_vr9.c163
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-gigasx76x.c166
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-gigasx76x.h (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-gigasx76x.h)9
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-netgear.c (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-netgear.c)38
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-p2601hnf1.c106
-rw-r--r--target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-wbmr.c (renamed from target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-wbmr.c)0
-rw-r--r--target/linux/lantiq/image/Makefile90
-rw-r--r--target/linux/lantiq/image/eva.dummy.squashfsbin0 -> 256 bytes
-rw-r--r--target/linux/lantiq/modules.mk35
-rw-r--r--target/linux/lantiq/patches-3.2/0001-GPIO-add-bindings-for-managed-devices.patch144
-rw-r--r--target/linux/lantiq/patches-3.2/0002-MIPS-remove-unused-prototype-kgdb_config.patch25
-rw-r--r--target/linux/lantiq/patches-3.2/0003-MTD-MIPS-lantiq-reintroduce-support-for-cmdline-part.patch39
-rw-r--r--target/linux/lantiq/patches-3.2/0004-MTD-add-m25p80-id-for-mx25l2005a.patch24
-rw-r--r--target/linux/lantiq/patches-3.2/0005-MIPS-lantiq-reorganize-xway-code.patch (renamed from target/linux/lantiq/patches/0004-MIPS-lantiq-reorganize-xway-code.patch)114
-rw-r--r--target/linux/lantiq/patches-3.2/0006-MIPS-lantiq-change-ltq_request_gpio-call-signature.patch149
-rw-r--r--target/linux/lantiq/patches-3.2/0007-MIPS-lantiq-make-irq.c-support-the-FALC-ON.patch (renamed from target/linux/lantiq/patches/0005-MIPS-lantiq-make-irq.c-support-the-FALC-ON.patch)23
-rw-r--r--target/linux/lantiq/patches-3.2/0008-MIPS-lantiq-add-basic-support-for-FALC-ON.patch (renamed from target/linux/lantiq/patches/0006-MIPS-lantiq-add-basic-support-for-FALC-ON.patch)125
-rw-r--r--target/linux/lantiq/patches-3.2/0009-MIPS-lantiq-add-support-for-FALC-ON-GPIOs.patch (renamed from target/linux/lantiq/patches/0007-MIPS-lantiq-add-support-for-FALC-ON-GPIOs.patch)30
-rw-r--r--target/linux/lantiq/patches-3.2/0010-MIPS-lantiq-add-support-for-the-EASY98000-evaluation.patch (renamed from target/linux/lantiq/patches/0008-MIPS-lantiq-add-support-for-the-EASY98000-evaluation.patch)18
-rw-r--r--target/linux/lantiq/patches-3.2/0011-MIPS-lantiq-fix-early-printk.patch (renamed from target/linux/lantiq/patches/0001-MIPS-lantiq-fix-early-printk.patch)30
-rw-r--r--target/linux/lantiq/patches-3.2/0012-MIPS-lantiq-fix-cmdline-parsing.patch (renamed from target/linux/lantiq/patches/0002-MIPS-lantiq-fix-cmdline-parsing.patch)12
-rw-r--r--target/linux/lantiq/patches-3.2/0013-MIPS-lantiq-fix-STP-gpio-groups.patch (renamed from target/linux/lantiq/patches/0024-MIPS-lantiq-fixes-STP-based-gpios.patch)10
-rw-r--r--target/linux/lantiq/patches-3.2/0014-MIPS-lantiq-fix-pull-gpio-up-resistors-usage.patch (renamed from target/linux/lantiq/patches/0025-MIPS-lantiq-activate-pull-up-resistors-when-gpio-is-.patch)17
-rw-r--r--target/linux/lantiq/patches-3.2/0015-MIPS-lantiq-add-default-configs.patch247
-rw-r--r--target/linux/lantiq/patches-3.2/0016-MAINTAINERS-add-entry-for-Lantiq-related-files.patch38
-rw-r--r--target/linux/lantiq/patches-3.2/0017-MIPS-make-oprofile-use-cp0_perfcount_irq-if-it-is-se.patch55
-rw-r--r--target/linux/lantiq/patches-3.2/0018-MIPS-lantiq-enable-oprofile-support-on-lantiq-target.patch (renamed from target/linux/lantiq/patches/0010-MIPS-enable-oprofile-support-on-lantiq-targets.patch)18
-rw-r--r--target/linux/lantiq/patches-3.2/0019-NET-MIPS-lantiq-make-etop-ethernet-work-on-ase-ar9.patch (renamed from target/linux/lantiq/patches/0015-MIPS-lantiq-adds-etop-support-for-ase-ar9.patch)93
-rw-r--r--target/linux/lantiq/patches-3.2/0020-NET-MIPS-lantiq-non-existing-phy-was-not-handled-gra.patch67
-rw-r--r--target/linux/lantiq/patches-3.2/0021-NET-MIPS-lantiq-return-value-of-request_irq-was-not-.patch71
-rw-r--r--target/linux/lantiq/patches-3.2/0022-MIPS-lantiq-use-devres-managed-gpios.patch282
-rw-r--r--target/linux/lantiq/patches-3.2/0023-MIPS-add-clkdev.h.patch49
-rw-r--r--target/linux/lantiq/patches-3.2/0024-MIPS-lantiq-helper-functions-for-SoC-detection.patch59
-rw-r--r--target/linux/lantiq/patches-3.2/0025-MIPS-lantiq-convert-to-clkdev-api.patch299
-rw-r--r--target/linux/lantiq/patches-3.2/0026-MIPS-lantiq-convert-xway-to-clkdev-api.patch736
-rw-r--r--target/linux/lantiq/patches-3.2/0027-MIPS-lantiq-convert-falcon-to-clkdev-api.patch244
-rw-r--r--target/linux/lantiq/patches-3.2/0028-MIPS-lantiq-convert-dma-driver-to-clkdev-api.patch65
-rw-r--r--target/linux/lantiq/patches-3.2/0029-MIPS-lantiq-convert-gpio_stp-driver-to-clkdev-api.patch60
-rw-r--r--target/linux/lantiq/patches-3.2/0030-MIPS-lantiq-convert-falcon-gpio-to-clkdev-api.patch73
-rw-r--r--target/linux/lantiq/patches-3.2/0031-SERIAL-MIPS-lantiq-convert-serial-driver-to-clkdev-a.patch41
-rw-r--r--target/linux/lantiq/patches-3.2/0032-MIPS-lantiq-convert-falcon-debug-uart-to-clkdev-api.patch73
-rw-r--r--target/linux/lantiq/patches-3.2/0033-NET-MIPS-lantiq-convert-etop-driver-to-clkdev-api.patch123
-rw-r--r--target/linux/lantiq/patches-3.2/0034-WDT-MIPS-lantiq-convert-watchdog-driver-to-clkdev-ap.patch30
-rw-r--r--target/linux/lantiq/patches-3.2/0035-MIPS-lantiq-unify-xway-prom-code.patch262
-rw-r--r--target/linux/lantiq/patches-3.2/0036-MIPS-lantiq-add-vr9-support.patch172
-rw-r--r--target/linux/lantiq/patches-3.2/0037-MIPS-lantiq-add-ipi-handlers-to-make-vsmp-work.patch124
-rw-r--r--target/linux/lantiq/patches-3.2/0038-MIPS-lantiq-add-additional-soc-ids.patch156
-rw-r--r--target/linux/lantiq/patches-3.2/0039-SPI-MIPS-lantiq-add-FALC-ON-spi-driver.patch (renamed from target/linux/lantiq/patches/0013-MIPS-lantiq-adds-FALC-ON-spi-driver.patch)112
-rw-r--r--target/linux/lantiq/patches-3.2/0040-I2C-MIPS-lantiq-add-FALC-ON-i2c-bus-master.patch (renamed from target/linux/lantiq/patches/0011-MIPS-lantiq-adds-falcon-I2C.patch)505
-rw-r--r--target/linux/lantiq/patches-3.2/0041-MIPS-lantiq-add-xway-nand-driver.patch310
-rw-r--r--target/linux/lantiq/patches-3.2/0042-SPI-MIPS-lantiq-adds-spi-xway.patch (renamed from target/linux/lantiq/patches/0014-MIPS-lantiq-adds-xway-spi.patch)97
-rw-r--r--target/linux/lantiq/patches-3.2/0043-NET-adds-driver-for-lantiq-vr9-ethernet.patch1470
-rw-r--r--target/linux/lantiq/patches-3.2/0044-MIPS-NET-several-fixes-to-etop-driver.patch445
-rw-r--r--target/linux/lantiq/patches-3.2/0045-MTD-MIPS-lantiq-use-module_platform_driver-inside-la.patch64
-rw-r--r--target/linux/lantiq/patches-3.2/0046-WDT-MIPS-lantiq-use-module_platform_driver-inside-la.patch61
-rw-r--r--target/linux/lantiq/patches-3.2/0047-MIPS-lantiq-adds-GPTU-driver.patch (renamed from target/linux/lantiq/patches/0017-MIPS-lantiq-adds-GPTU-driver.patch)64
-rw-r--r--target/linux/lantiq/patches-3.2/0048-MIPS-lantiq-adds-dwc_otg.patch (renamed from target/linux/lantiq/patches/0018-MIPS-lantiq-adds-dwc_otg.patch)73
-rw-r--r--target/linux/lantiq/patches-3.2/0049-dwc_otg-remove-bogus-halt_channel.patch26
-rw-r--r--target/linux/lantiq/patches-3.2/0050-MIPS-adds-ifxhcd.patch16672
-rw-r--r--target/linux/lantiq/patches-3.2/0051-MIPS-adds-gptu-driver.patch195
-rw-r--r--target/linux/lantiq/patches-3.2/0052-MIPS-lantiq-pci-rename-variable-inside.patch79
-rw-r--r--target/linux/lantiq/patches-3.2/0053-MIPS-lantiq-pci-give-xway-pci-support-its-own-kbuild.patch45
-rw-r--r--target/linux/lantiq/patches-3.2/0054-MIPS-lantiq-pci-move-pcibios-code-into-fixup-lantiq..patch131
-rw-r--r--target/linux/lantiq/patches-3.2/0055-MIPS-lantiq-pcie-add-pcie-driver.patch3503
-rw-r--r--target/linux/lantiq/patches-3.2/0056-MIPS-lantiq-make-GPIO3-work-on-AR9.patch (renamed from target/linux/lantiq/patches/0026-MIPS-lantiq-adds-GPIO3-support-on-AR9.patch)95
-rw-r--r--target/linux/lantiq/patches-3.2/0057-MIPS-lantiq-VPE-extensions.patch (renamed from target/linux/lantiq/patches/0019-MIPS-lantiq-adds-VPE-extensions.patch)67
-rw-r--r--target/linux/lantiq/patches-3.2/0058-MIPS-lantiq-falcon-VPE-softdog.patch (renamed from target/linux/lantiq/patches/0020-MIPS-lantiq-adds-falcon-VPE-softdog.patch)19
-rw-r--r--target/linux/lantiq/patches-3.2/0059-MIPS-lantiq-udp-in-kernel-redirect.patch (renamed from target/linux/lantiq/patches/0022-MIPS-lantiq-adds-udp-in-kernel-redirect.patch)31
-rw-r--r--target/linux/lantiq/patches-3.2/0060-MIPS-lantiq-cache-split.patch (renamed from target/linux/lantiq/patches/0021-MIPS-lantiq-adds-cache-split.patch)56
-rw-r--r--target/linux/lantiq/patches-3.2/0061-MIPS-clean-up-clock-code.patch319
-rw-r--r--target/linux/lantiq/patches-3.2/0062-MIPS-cleanup-reset-code.patch103
-rw-r--r--target/linux/lantiq/patches-3.2/0063-MIPS-lantiq-fixes-ar9-vr9-clock.patch116
-rw-r--r--target/linux/lantiq/patches-3.2/0064-MIPS-lantiq-fixes-danube-clock.patch57
-rw-r--r--target/linux/lantiq/patches-3.2/0065-MIPS-adds-dsl-clocks.patch66
-rw-r--r--target/linux/lantiq/patches-3.2/0066-MIPS-lantiq-dont-always-register-asc0.patch31
-rw-r--r--target/linux/lantiq/patches-3.2/0067-MIPS-lantiq-irqs-were-not-cleared-properly-on-boot.patch34
-rw-r--r--target/linux/lantiq/patches-3.2/0068-MIPS-lantiq-adds-bootsel-helper.patch66
-rw-r--r--target/linux/lantiq/patches-3.2/0069-MIPS-lantiq-adds-USB_ARCH_HAS_HCD-to-CONFIG_LANTIQ.patch24
-rw-r--r--target/linux/lantiq/patches-3.2/100-falcon_bsp_header.patch (renamed from target/linux/lantiq/patches/100-falcon_bsp_header.patch)0
-rw-r--r--target/linux/lantiq/patches-3.2/101-sdk-compat.patch (renamed from target/linux/lantiq/patches/110-sdk-compat.patch)0
-rw-r--r--target/linux/lantiq/patches-3.2/200-owrt-netif_receive_skb.patch (renamed from target/linux/lantiq/patches/200-owrt-netif_receive_skb.patch)4
-rw-r--r--target/linux/lantiq/patches-3.2/201-owrt-mtd_split.patch244
-rw-r--r--target/linux/lantiq/patches-3.2/202-owrt-atm.patch (renamed from target/linux/lantiq/patches/202-owrt-atm.patch)36
-rw-r--r--target/linux/lantiq/patches-3.2/203-owrt-cmdline.patch (renamed from target/linux/lantiq/patches/203-owrt-cmdline.patch)0
-rw-r--r--target/linux/lantiq/patches-3.2/204-owrt-dm9000-polling.patch (renamed from target/linux/lantiq/patches/204-owrt-dm9000-polling.patch)4
-rw-r--r--target/linux/lantiq/patches-3.2/205-owrt-gpio-export.patch (renamed from target/linux/lantiq/patches/205-owrt-gpio-export.patch)0
-rw-r--r--target/linux/lantiq/patches-3.2/206-machtypes.patch (renamed from target/linux/lantiq/patches/210-machtypes.patch)83
-rw-r--r--target/linux/lantiq/patches-3.2/207-devices.patch (renamed from target/linux/lantiq/patches/211-devices.patch)40
-rw-r--r--target/linux/lantiq/patches-3.2/208-fix-mach-easy98000.patch (renamed from target/linux/lantiq/patches/810-fix-mach-easy98000.patch)16
-rw-r--r--target/linux/lantiq/patches-3.2/209-fritz_ram.patch17
-rw-r--r--target/linux/lantiq/patches/0016-MIPS-lantiq-adds-xway-nand-driver.patch253
-rw-r--r--target/linux/lantiq/patches/0023-MIPS-lantiq-adds-basic-vr9-support.patch262
-rw-r--r--target/linux/lantiq/patches/201-owrt-mtd_uimage_split.patch116
-rw-r--r--target/linux/lantiq/patches/206-owrt-brnboot.patch93
-rw-r--r--target/linux/lantiq/patches/800-fix-etop.patch67
-rw-r--r--target/linux/lantiq/patches/820-fix-falcon-ltq_gpio_request.patch53
-rw-r--r--target/linux/lantiq/patches/830-fix-falcon-i2c-resources.patch17
-rw-r--r--target/linux/lantiq/patches/840-fix-falcon-sysctrl.patch61
-rw-r--r--target/linux/lantiq/patches/850-etop_irq.patch70
-rw-r--r--target/linux/lantiq/patches/860-falcon-fix-version.patch65
-rw-r--r--target/linux/lantiq/patches/999-mtd.patch11
-rw-r--r--target/linux/lantiq/vr9/config-default68
-rw-r--r--target/linux/lantiq/vr9/profiles/001-avm.mk6
135 files changed, 30640 insertions, 2275 deletions
diff --git a/target/linux/lantiq/Makefile b/target/linux/lantiq/Makefile
index b0bed09..10d6665 100644
--- a/target/linux/lantiq/Makefile
+++ b/target/linux/lantiq/Makefile
@@ -12,7 +12,7 @@ BOARDNAME:=Lantiq GPON/XWAY
FEATURES:=squashfs jffs2
DEFAULT_SUBTARGET:=danube
-LINUX_VERSION:=3.1.10
+LINUX_VERSION:=3.2.12
CFLAGS=-Os -pipe -mips32r2 -mtune=mips32r2 -fno-caller-saves
diff --git a/target/linux/lantiq/ar9/config-default b/target/linux/lantiq/ar9/config-default
index 34192d0..ce21adf 100644
--- a/target/linux/lantiq/ar9/config-default
+++ b/target/linux/lantiq/ar9/config-default
@@ -1,54 +1,38 @@
CONFIG_ADM6996_PHY=y
CONFIG_AR8216_PHY=y
-# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
-# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
-# CONFIG_ATH79 is not set
-CONFIG_GENERIC_ATOMIC64=y
-CONFIG_GENERIC_IRQ_SHOW=y
-CONFIG_HAVE_ARCH_JUMP_LABEL=y
-CONFIG_HAVE_C_RECORDMCOUNT=y
-CONFIG_HAVE_DMA_API_DEBUG=y
-CONFIG_HAVE_DMA_ATTRS=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
-CONFIG_HAVE_GENERIC_HARDIRQS=y
-CONFIG_HAVE_IRQ_WORK=y
-CONFIG_HAVE_PERF_EVENTS=y
+# CONFIG_ATMEL_PWM is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_FSNOTIFY=y
+CONFIG_HAVE_MACH_CLKDEV=y
CONFIG_HW_HAS_PCI=y
CONFIG_INPUT=y
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_GPIO_BUTTONS is not set
CONFIG_INPUT_POLLDEV=y
+CONFIG_IRQ_FORCED_THREADING=y
# CONFIG_ISDN is not set
CONFIG_LANTIQ_ETOP=y
-# CONFIG_LANTIQ_MACH_ARV45XX is not set
+# CONFIG_LANTIQ_MACH_ARV is not set
# CONFIG_LANTIQ_MACH_EASY50712 is not set
+CONFIG_LANTIQ_MACH_FRITZ_AR9=y
+# CONFIG_LANTIQ_MACH_FRITZ_VR9 is not set
+# CONFIG_LANTIQ_MACH_GIGASX76X is not set
CONFIG_LANTIQ_MACH_NETGEAR=y
CONFIG_LANTIQ_MACH_WBMR=y
-# CONFIG_LANTIQ_MACH_GIGASX76X is not set
-CONFIG_MACH_NO_WESTBRIDGE=y
-# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set
-CONFIG_NEED_DMA_MAP_STATE=y
-CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_LANTIQ_VRX200 is not set
+CONFIG_MDIO_BOARDINFO=y
+# CONFIG_MLX4_CORE is not set
+CONFIG_MTD_BLOCK2MTD=y
CONFIG_PCI=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCIE_LANTIQ is not set
CONFIG_PCI_DOMAINS=y
-CONFIG_PERF_USE_VMALLOC=y
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_QUOTACTL is not set
+CONFIG_PCI_LANTIQ=y
+# CONFIG_PCI_LANTIQ_NONE is not set
CONFIG_RTL8306_PHY=y
# CONFIG_SOC_AMAZON_SE is not set
-# CONFIG_SOC_VR9 is not set
# CONFIG_SOC_FALCON is not set
CONFIG_SOC_TYPE_XWAY=y
CONFIG_SOC_XWAY=y
-CONFIG_SPI=y
-CONFIG_SPI_BITBANG=y
-# CONFIG_SPI_GPIO is not set
-CONFIG_SPI_LANTIQ=y
-CONFIG_SPI_MASTER=y
+CONFIG_USB_ARCH_HAS_XHCI=y
CONFIG_USB_SUPPORT=y
-CONFIG_XZ_DEC=y
-CONFIG_SPI_XWAY=y
diff --git a/target/linux/lantiq/ar9/profiles/001-lantiq.mk b/target/linux/lantiq/ar9/profiles/001-lantiq.mk
index 2039738..a1fc2d2 100644
--- a/target/linux/lantiq/ar9/profiles/001-lantiq.mk
+++ b/target/linux/lantiq/ar9/profiles/001-lantiq.mk
@@ -1,5 +1,5 @@
define Profile/EASY50812
- NAME:=EASY50812
+ NAME:=EASY50812 - Eval Board
PACKAGES:= kmod-usb-core kmod-usb-dwc-otg
endef
diff --git a/target/linux/lantiq/ar9/profiles/002-netgear.mk b/target/linux/lantiq/ar9/profiles/002-netgear.mk
index 1a77786..a3c83bb 100644
--- a/target/linux/lantiq/ar9/profiles/002-netgear.mk
+++ b/target/linux/lantiq/ar9/profiles/002-netgear.mk
@@ -1,5 +1,5 @@
define Profile/DGN3500B
- NAME:=DGN3500B
+ NAME:=DGN3500B Netgear
PACKAGES:= kmod-usb-core kmod-usb-dwc-otg
endef
diff --git a/target/linux/lantiq/ar9/profiles/004-avm.mk b/target/linux/lantiq/ar9/profiles/004-avm.mk
new file mode 100644
index 0000000..e424d6a
--- /dev/null
+++ b/target/linux/lantiq/ar9/profiles/004-avm.mk
@@ -0,0 +1,7 @@
+define Profile/FRITZ7320
+ NAME:=FRITZ7320 Fritzbox
+ PACKAGES:= kmod-usb-core kmod-usb-ifxhcd kmod-ledtrig-usbdev \
+ kmod-ltq-dsl-firmware-b-ar9 kmod-ath9k wpad-mini
+endef
+
+$(eval $(call Profile,FRITZ7320))
diff --git a/target/linux/lantiq/ase/config-default b/target/linux/lantiq/ase/config-default
index a6c8a3d..8d2597d 100644
--- a/target/linux/lantiq/ase/config-default
+++ b/target/linux/lantiq/ase/config-default
@@ -1,39 +1,22 @@
-# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
-# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
-# CONFIG_ATH79 is not set
-CONFIG_GENERIC_ATOMIC64=y
-CONFIG_GENERIC_IRQ_SHOW=y
-CONFIG_HAVE_ARCH_JUMP_LABEL=y
-CONFIG_HAVE_C_RECORDMCOUNT=y
-CONFIG_HAVE_DMA_API_DEBUG=y
-CONFIG_HAVE_DMA_ATTRS=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
-CONFIG_HAVE_GENERIC_HARDIRQS=y
-CONFIG_HAVE_IRQ_WORK=y
-CONFIG_HAVE_PERF_EVENTS=y
+# CONFIG_ATMEL_PWM is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_FSNOTIFY=y
+CONFIG_HAVE_MACH_CLKDEV=y
CONFIG_INPUT=y
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_GPIO_BUTTONS is not set
CONFIG_INPUT_POLLDEV=y
+CONFIG_IRQ_FORCED_THREADING=y
# CONFIG_ISDN is not set
CONFIG_LANTIQ_ETOP=y
CONFIG_LANTIQ_MACH_EASY50601=y
-CONFIG_MACH_NO_WESTBRIDGE=y
-# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set
-# CONFIG_MTD_LATCH_ADDR is not set
-CONFIG_NEED_DMA_MAP_STATE=y
-CONFIG_NEED_PER_CPU_KM=y
-CONFIG_PERF_USE_VMALLOC=y
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_QUOTACTL is not set
+# CONFIG_LANTIQ_VRX200 is not set
+CONFIG_MDIO_BOARDINFO=y
CONFIG_SOC_AMAZON_SE=y
-# CONFIG_SOC_VR9 is not set
# CONFIG_SOC_FALCON is not set
CONFIG_SOC_TYPE_XWAY=y
# CONFIG_SOC_XWAY is not set
-CONFIG_XZ_DEC=y
-CONFIG_SPI_XWAY=y
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_XHCI is not set
+CONFIG_USB_SUPPORT=y
diff --git a/target/linux/lantiq/config-default b/target/linux/lantiq/config-3.2
index d4e90c9..d4e90c9 100644
--- a/target/linux/lantiq/config-default
+++ b/target/linux/lantiq/config-3.2
diff --git a/target/linux/lantiq/danube/config-default b/target/linux/lantiq/danube/config-default
index 508706d..ff04f3c 100644
--- a/target/linux/lantiq/danube/config-default
+++ b/target/linux/lantiq/danube/config-default
@@ -1,54 +1,37 @@
CONFIG_ADM6996_PHY=y
CONFIG_AR8216_PHY=y
-# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
-# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
-# CONFIG_ATH79 is not set
-CONFIG_GENERIC_ATOMIC64=y
-CONFIG_GENERIC_IRQ_SHOW=y
-CONFIG_HAVE_ARCH_JUMP_LABEL=y
-CONFIG_HAVE_C_RECORDMCOUNT=y
-CONFIG_HAVE_DMA_API_DEBUG=y
-CONFIG_HAVE_DMA_ATTRS=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
-CONFIG_HAVE_GENERIC_HARDIRQS=y
-CONFIG_HAVE_IRQ_WORK=y
-CONFIG_HAVE_PERF_EVENTS=y
+# CONFIG_ATMEL_PWM is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_FSNOTIFY=y
+CONFIG_HAVE_MACH_CLKDEV=y
CONFIG_HW_HAS_PCI=y
CONFIG_INPUT=y
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_GPIO_BUTTONS is not set
CONFIG_INPUT_POLLDEV=y
+CONFIG_IRQ_FORCED_THREADING=y
# CONFIG_ISDN is not set
CONFIG_LANTIQ_ETOP=y
-CONFIG_LANTIQ_MACH_ARV45XX=y
+CONFIG_LANTIQ_MACH_ARV=y
CONFIG_LANTIQ_MACH_EASY50712=y
+# CONFIG_LANTIQ_MACH_FRITZ_AR9 is not set
+# CONFIG_LANTIQ_MACH_FRITZ_VR9 is not set
+CONFIG_LANTIQ_MACH_GIGASX76X=y
# CONFIG_LANTIQ_MACH_NETGEAR is not set
# CONFIG_LANTIQ_MACH_WBMR is not set
-CONFIG_LANTIQ_MACH_GIGASX76X=y
-CONFIG_MACH_NO_WESTBRIDGE=y
-# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set
-CONFIG_NEED_DMA_MAP_STATE=y
-CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_LANTIQ_VRX200 is not set
+CONFIG_MDIO_BOARDINFO=y
+# CONFIG_MLX4_CORE is not set
CONFIG_PCI=y
+# CONFIG_PCIEPORTBUS is not set
+# CONFIG_PCIE_LANTIQ is not set
CONFIG_PCI_DOMAINS=y
-CONFIG_PERF_USE_VMALLOC=y
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_QUOTACTL is not set
+CONFIG_PCI_LANTIQ=y
+# CONFIG_PCI_LANTIQ_NONE is not set
CONFIG_RTL8306_PHY=y
# CONFIG_SOC_AMAZON_SE is not set
# CONFIG_SOC_FALCON is not set
-# CONFIG_SOC_VR9 is not set
CONFIG_SOC_TYPE_XWAY=y
CONFIG_SOC_XWAY=y
-CONFIG_SPI=y
-CONFIG_SPI_BITBANG=y
-# CONFIG_SPI_GPIO is not set
-CONFIG_SPI_LANTIQ=y
-CONFIG_SPI_MASTER=y
+CONFIG_USB_ARCH_HAS_XHCI=y
CONFIG_USB_SUPPORT=y
-CONFIG_XZ_DEC=y
-CONFIG_SPI_XWAY=y
diff --git a/target/linux/lantiq/danube/profiles/004-bt.mk b/target/linux/lantiq/danube/profiles/004-bt.mk
new file mode 100644
index 0000000..26dd93c
--- /dev/null
+++ b/target/linux/lantiq/danube/profiles/004-bt.mk
@@ -0,0 +1,23 @@
+define Profile/BTHOMEHUBV2B
+ NAME:=BTHOMEHUBV2B - BT Homehub V2.0 Type B
+ PACKAGES:= kmod-usb-core kmod-usb-dwc-otg kmod-ledtrig-usbdev \
+ kmod-ath9k wpad-mini kmod-ltq-dsl-firmware-a-danube
+endef
+
+define Profile/BTHOMEHUBV2B/Description
+ Package set optimized for the BT Homehub V2.0 Type B using whole nand for OpenWRT
+endef
+
+$(eval $(call Profile,BTHOMEHUBV2B))
+
+define Profile/BTHOMEHUBV2BOPENRG
+ NAME:=BTHOMEHUBV2B - BT Homehub V2.0 Type B (OpenRG)
+ PACKAGES:= kmod-usb-core kmod-usb-dwc-otg kmod-ledtrig-usbdev \
+ kmod-ath9k wpad-mini kmod-ltq-dsl-firmware-a-danube
+endef
+
+define Profile/BTHOMEHUBV2BOPENRG/Description
+ Package set optimized for the BT Homehub V2.0 Type B but retaining OpenRG image
+endef
+
+$(eval $(call Profile,BTHOMEHUBV2BOPENRG))
diff --git a/target/linux/lantiq/falcon/config-default b/target/linux/lantiq/falcon/config-default
index f1d6e48..e1210e1 100644
--- a/target/linux/lantiq/falcon/config-default
+++ b/target/linux/lantiq/falcon/config-default
@@ -1,28 +1,20 @@
-CONFIG_CPU_MIPSR2_IRQ_EI=y
-CONFIG_CPU_MIPSR2_IRQ_VI=y
-CONFIG_IFX_VPE_CACHE_SPLIT=y
-CONFIG_IFX_VPE_EXT=y
+# CONFIG_ATMEL_PWM is not set
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_FSNOTIFY=y
+CONFIG_HAVE_MACH_CLKDEV=y
+CONFIG_IRQ_FORCED_THREADING=y
CONFIG_M25PXX_USE_FAST_READ=y
-CONFIG_MIPS_MT=y
-# CONFIG_MIPS_VPE_APSP_API is not set
-CONFIG_MIPS_VPE_LOADER=y
-CONFIG_MIPS_VPE_LOADER_TOM=y
CONFIG_MTD_M25P80=y
CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_NAND_PLATFORM=y
# CONFIG_MTD_SM_COMMON is not set
-CONFIG_MTSCHED=y
-# CONFIG_PERFCTRS is not set
# CONFIG_SOC_AMAZON_SE is not set
CONFIG_SOC_FALCON=y
# CONFIG_SOC_TYPE_XWAY is not set
# CONFIG_SOC_XWAY is not set
-# CONFIG_SOC_VR9 is not set
CONFIG_SPI=y
# CONFIG_SPI_BITBANG is not set
CONFIG_SPI_FALCON=y
# CONFIG_SPI_GPIO is not set
CONFIG_SPI_MASTER=y
-# CONFIG_I2C_DESIGNWARE is not set
-
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-fritz.c b/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-fritz.c
deleted file mode 100644
index 9b54242..0000000
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-fritz.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/input.h>
-#include <linux/phy.h>
-
-#include <lantiq_soc.h>
-#include <irq.h>
-
-#include "../machtypes.h"
-#include "devices.h"
-
-/*static struct mtd_partition fritz3370_partitions[] = {
- {
- .name = "uboot",
- .offset = 0x0,
- .size = 0x10000,
- },
- {
- .name = "uboot_env",
- .offset = 0x10000,
- .size = 0x10000,
- },
- {
- .name = "linux",
- .offset = 0x20000,
- .size = 0xe0000,
- },
- {
- .name = "rootfs",
- .offset = 0x100000,
- .size = 0x300000,
- },
-};
-
-static struct physmap_flash_data fritz3370_flash_data = {
- .nr_parts = ARRAY_SIZE(fritz3370_partitions),
- .parts = fritz3370_partitions,
-};
-
-static struct ltq_pci_data ltq_pci_data = {
- .clock = PCI_CLOCK_INT,
- .gpio = PCI_GNT1 | PCI_REQ1,
- .irq = {
- [14] = INT_NUM_IM0_IRL0 + 22,
- },
-};
-*/
-static struct ltq_eth_data ltq_eth_data = {
- .mii_mode = PHY_INTERFACE_MODE_MII,
-};
-
-extern void xway_register_nand(void);
-
-static void __init fritz3370_init(void)
-{
-// ltq_register_gpio_stp();
-// ltq_register_nor(&fritz3370_flash_data);
-// ltq_register_pci(&ltq_pci_data);
- ltq_register_etop(&ltq_eth_data);
- xway_register_nand();
-}
-
-MIPS_MACHINE(LANTIQ_MACH_FRITZ3370,
- "FRITZ3370",
- "FRITZ!BOX 3370",
- fritz3370_init);
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-gigasx76x.c b/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-gigasx76x.c
deleted file mode 100644
index 3dbfcb9..0000000
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-gigasx76x.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) 2011 Andrej Vlašić
- * Copyright (C) 2011 Luka Perkov
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/gpio.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/input.h>
-#include <linux/ath5k_platform.h>
-#include <linux/pci.h>
-#include <linux/phy.h>
-#include <linux/io.h>
-#include <linux/string.h>
-
-#include <irq.h>
-#include <lantiq_soc.h>
-#include <lantiq_platform.h>
-#include <dev-gpio-leds.h>
-#include <dev-gpio-buttons.h>
-
-#include "../machtypes.h"
-#include "dev-wifi-ath5k.h"
-#include "devices.h"
-#include "dev-dwc_otg.h"
-
-#include "mach-gigasx76x.h"
-
-#define UBOOT_ENV_OFFSET 0x010000
-#define UBOOT_ENV_SIZE 0x010000
-
-static struct mtd_partition gigasx76x_partitions[] =
-{
- {
- .name = "uboot",
- .offset = 0x000000,
- .size = 0x010000,
- },
- {
- .name = "uboot_env",
- .offset = UBOOT_ENV_OFFSET,
- .size = UBOOT_ENV_SIZE,
- },
- {
- .name = "linux",
- .offset = 0x020000,
- .size = 0x7e0000,
- },
-};
-
-static struct gpio_led
-gigasx76x_gpio_leds[] __initdata = {
- { .name = "soc:green:voip", .gpio = 216, },
- { .name = "soc:green:adsl", .gpio = 217, },
- { .name = "soc:green:usb", .gpio = 218, },
- { .name = "soc:green:wifi", .gpio = 219, },
- { .name = "soc:green:phone2", .gpio = 220, },
- { .name = "soc:green:phone1", .gpio = 221, },
- { .name = "soc:green:line", .gpio = 222, },
- { .name = "soc:green:online", .gpio = 223, },
-};
-
-static struct gpio_keys_button
-gigasx76x_gpio_keys[] __initdata = {
- {
- .desc = "wps",
- .type = EV_KEY,
- .code = KEY_WPS_BUTTON,
- .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
- .gpio = 22,
- .active_low = 1,
- },
- {
- .desc = "reset",
- .type = EV_KEY,
- .code = BTN_0,
- .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
- .gpio = 14,
- .active_low = 0,
- },
-};
-
-static struct physmap_flash_data gigasx76x_flash_data = {
- .nr_parts = ARRAY_SIZE(gigasx76x_partitions),
- .parts = gigasx76x_partitions,
-};
-
-static struct ltq_pci_data ltq_pci_data = {
- .clock = PCI_CLOCK_INT,
- .gpio = PCI_GNT1 | PCI_REQ1,
- .irq = { [14] = INT_NUM_IM0_IRL0 + 22, },
-};
-
-static struct ltq_eth_data ltq_eth_data = {
- .mii_mode = PHY_INTERFACE_MODE_MII,
-};
-
-static char __init *get_uboot_env_var(char *haystack, int haystack_len, char *needle, int needle_len) {
- int i;
- for (i = 0; i <= haystack_len - needle_len; i++) {
- if (memcmp(haystack + i, needle, needle_len) == 0) {
- return haystack + i + needle_len;
- }
- }
- return NULL;
-}
-
-/*
- * gigasx76x_parse_hex_* are not uniq. in arm/orion there are also duplicates:
- * dns323_parse_hex_*
- * TODO: one day write a patch for this :)
- */
-static int __init gigasx76x_parse_hex_nibble(char n) {
- if (n >= '0' && n <= '9')
- return n - '0';
-
- if (n >= 'A' && n <= 'F')
- return n - 'A' + 10;
-
- if (n >= 'a' && n <= 'f')
- return n - 'a' + 10;
-
- return -1;
-}
-
-static int __init gigasx76x_parse_hex_byte(const char *b) {
- int hi;
- int lo;
-
- hi = gigasx76x_parse_hex_nibble(b[0]);
- lo = gigasx76x_parse_hex_nibble(b[1]);
-
- if (hi < 0 || lo < 0)
- return -1;
-
- return (hi << 4) | lo;
-}
-
-static u16 gigasx76x_ath5k_eeprom_data[ATH5K_PLAT_EEP_MAX_WORDS];
-static u8 gigasx76x_ath5k_eeprom_mac[6];
-
-static int __init gigasx76x_register_ethernet(void) {
- u_int8_t addr[6];
- int i;
- char *uboot_env_page;
- char *mac;
- char *boardid;
-
- uboot_env_page = ioremap(LTQ_FLASH_START + UBOOT_ENV_OFFSET, UBOOT_ENV_SIZE);
- if (!uboot_env_page)
- return -ENOMEM;
-
- mac = get_uboot_env_var(uboot_env_page, UBOOT_ENV_SIZE, "\0ethaddr=", 9);
- boardid = get_uboot_env_var(uboot_env_page, UBOOT_ENV_SIZE, "\0boardid=", 9);
-
- if (!mac) {
- goto error_fail;
- }
-
- if (!boardid) {
- goto error_fail;
- }
-
- /* Sanity check the string we're looking at */
- for (i = 0; i < 5; i++) {
- if (*(mac + (i * 3) + 2) != ':') {
- goto error_fail;
- }
- }
-
- for (i = 0; i < 6; i++) {
- int byte;
- byte = gigasx76x_parse_hex_byte(mac + (i * 3));
- if (byte < 0) {
- goto error_fail;
- }
- addr[i] = byte;
- }
-
- iounmap(uboot_env_page);
- printk("GIGASX76X: Found ethernet MAC address: ");
- for (i = 0; i < 6; i++)
- printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n");
-
- memcpy(&ltq_eth_data.mac.sa_data, addr, 6);
- ltq_register_etop(&ltq_eth_data);
-
- memcpy(&gigasx76x_ath5k_eeprom_mac, addr, 6);
- gigasx76x_ath5k_eeprom_mac[5]++;
-
- if (strncmp(boardid, "sx763", 5) == 0) {
- printk("GIGASX76X: Board id is sx763.");
- memcpy(&gigasx76x_ath5k_eeprom_data, sx763_eeprom_data, ATH5K_PLAT_EEP_MAX_WORDS);
- } else if (strncmp(boardid, "sx762", 5) == 0) {
- printk("GIGASX76X: Board id is sx762.");
- memcpy(&gigasx76x_ath5k_eeprom_data, sx762_eeprom_data, ATH5K_PLAT_EEP_MAX_WORDS);
- } else {
- printk("GIGASX76X: Board id is unknown, fix uboot_env data.");
- }
-
- return 0;
-
- error_fail:
- iounmap(uboot_env_page);
- return -EINVAL;
-}
-
-static void __init gigasx76x_init(void) {
-#define GIGASX76X_USB 29
-#define GIGASX76X_MADWIFI_ADDR 0xb07f0000
-
- ltq_register_gpio_stp();
- ltq_register_nor(&gigasx76x_flash_data);
- ltq_register_pci(&ltq_pci_data);
- ltq_register_tapi();
- ltq_add_device_gpio_leds(-1, ARRAY_SIZE(gigasx76x_gpio_leds), gigasx76x_gpio_leds);
- ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, ARRAY_SIZE(gigasx76x_gpio_keys), gigasx76x_gpio_keys);
- ltq_register_ath5k(gigasx76x_ath5k_eeprom_data, gigasx76x_ath5k_eeprom_mac);
- xway_register_dwc(GIGASX76X_USB);
- gigasx76x_register_ethernet();
-}
-
-MIPS_MACHINE(LANTIQ_MACH_GIGASX76X, "GIGASX76X", "GIGASX76X - Gigaset SX761,SX762,SX763", gigasx76x_init);
diff --git a/target/linux/lantiq/files-3.1/arch/mips/include/asm/mach-lantiq/dev-gpio-buttons.h b/target/linux/lantiq/files-3.2/arch/mips/include/asm/mach-lantiq/dev-gpio-buttons.h
index adb531c..adb531c 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/include/asm/mach-lantiq/dev-gpio-buttons.h
+++ b/target/linux/lantiq/files-3.2/arch/mips/include/asm/mach-lantiq/dev-gpio-buttons.h
diff --git a/target/linux/lantiq/files-3.1/arch/mips/include/asm/mach-lantiq/dev-gpio-leds.h b/target/linux/lantiq/files-3.2/arch/mips/include/asm/mach-lantiq/dev-gpio-leds.h
index d51e496..d51e496 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/include/asm/mach-lantiq/dev-gpio-leds.h
+++ b/target/linux/lantiq/files-3.2/arch/mips/include/asm/mach-lantiq/dev-gpio-leds.h
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/dev-gpio-buttons.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/dev-gpio-buttons.c
index ad25cac..ad25cac 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/dev-gpio-buttons.c
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/dev-gpio-buttons.c
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/dev-gpio-leds.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/dev-gpio-leds.c
index 89dc79d..89dc79d 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/dev-gpio-leds.c
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/dev-gpio-leds.c
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/addon-easy98000.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/addon-easy98000.c
index 2085a1c..317ee40 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/addon-easy98000.c
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/addon-easy98000.c
@@ -10,6 +10,7 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/init.h>
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/dev-leds-easy98000-cpld.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/dev-leds-easy98000-cpld.c
index d02d261..94622cf 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/dev-leds-easy98000-cpld.c
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/dev-leds-easy98000-cpld.c
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/module.h>
#include <linux/errno.h>
#include <linux/leds.h>
#include <linux/slab.h>
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/dev-leds-easy98000-cpld.h b/target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/dev-leds-easy98000-cpld.h
index 3160189..3160189 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/dev-leds-easy98000-cpld.h
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/dev-leds-easy98000-cpld.h
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/mach-95C3AM1.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/mach-95C3AM1.c
index 42a3344..42a3344 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/mach-95C3AM1.c
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/mach-95C3AM1.c
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/mach-easy98020.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/mach-easy98020.c
index 4cdfc19..4cdfc19 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/falcon/mach-easy98020.c
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/falcon/mach-easy98020.c
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-dwc_otg.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-dwc_otg.c
index 90b63fc..90b63fc 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-dwc_otg.c
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-dwc_otg.c
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-dwc_otg.h b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-dwc_otg.h
index 521fad0..521fad0 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-dwc_otg.h
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-dwc_otg.h
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-wifi-ath5k.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-wifi-ath5k.c
index 14fd511..14fd511 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-wifi-ath5k.c
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-wifi-ath5k.c
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-wifi-ath5k.h b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-wifi-ath5k.h
index 37f6e41..37f6e41 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-wifi-ath5k.h
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-wifi-ath5k.h
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-wifi-rt2x00.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-wifi-rt2x00.c
index 94932df..94932df 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-wifi-rt2x00.c
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-wifi-rt2x00.c
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-wifi-rt2x00.h b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-wifi-rt2x00.h
index 060ca50..060ca50 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/dev-wifi-rt2x00.h
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/dev-wifi-rt2x00.h
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-arv45xx.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-arv.c
index 9be1a5f..9cc90fe 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-arv45xx.c
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-arv.c
@@ -17,6 +17,7 @@
#include <linux/input.h>
#include <linux/etherdevice.h>
#include <linux/ath5k_platform.h>
+#include <linux/ath9k_platform.h>
#include <linux/pci.h>
#include <lantiq_soc.h>
@@ -26,57 +27,10 @@
#include "../machtypes.h"
#include "dev-wifi-rt2x00.h"
-#include "dev-wifi-ath5k.h"
+#include "dev-wifi-athxk.h"
#include "devices.h"
#include "dev-dwc_otg.h"
-
-static struct mtd_partition arv4510_partitions[] =
-{
- {
- .name = "uboot",
- .offset = 0x0,
- .size = 0x20000,
- },
- {
- .name = "uboot_env",
- .offset = 0x20000,
- .size = 0x120000,
- },
- {
- .name = "linux",
- .offset = 0x40000,
- .size = 0xfa0000,
- },
- {
- .name = "board_config",
- .offset = 0xfe0000,
- .size = 0x20000,
- },
-};
-
-static struct mtd_partition arv45xx_partitions[] =
-{
- {
- .name = "uboot",
- .offset = 0x0,
- .size = 0x20000,
- },
- {
- .name = "uboot_env",
- .offset = 0x20000,
- .size = 0x10000,
- },
- {
- .name = "linux",
- .offset = 0x30000,
- .size = 0x3c0000,
- },
- {
- .name = "board_config",
- .offset = 0x3f0000,
- .size = 0x10000,
- },
-};
+#include "pci-ath-fixup.h"
static struct mtd_partition arv45xx_brnboot_partitions[] =
{
@@ -107,79 +61,110 @@ static struct mtd_partition arv45xx_brnboot_partitions[] =
},
};
-static struct mtd_partition arv7525_partitions[] =
+static struct mtd_partition arv75xx_brnboot_partitions[] =
{
{
- .name = "uboot",
+ .name = "brn-boot",
.offset = 0x0,
- .size = 0x10000,
+ .size = 0x20000,
},
{
- .name = "uboot_env",
- .offset = 0x10000,
- .size = 0x10000,
+ .name = "config",
+ .offset = 0x20000,
+ .size = 0x40000,
},
{
.name = "linux",
- .offset = 0x20000,
- .size = 0x3d0000,
+ .offset = 0x440000,
+ .size = 0x3a0000,
+ },
+ {
+ .name = "reserved", /* 12-byte signature at 0x7efff4 :/ */
+ .offset = 0x7e0000,
+ .size = 0x010000,
},
{
.name = "board_config",
- .offset = 0x3f0000,
+ .offset = 0x7f0000,
.size = 0x10000,
},
};
-static struct mtd_partition arv75xx_partitions[] =
+/*
+ * this is generic configuration for all arv based boards, note that it can be
+ * rewriten in arv_load_nor()
+ */
+static struct mtd_partition arv_partitions[] =
{
{
.name = "uboot",
.offset = 0x0,
- .size = 0x10000,
+ .size = 0x20000,
},
{
.name = "uboot_env",
- .offset = 0x10000,
+ .offset = 0x20000,
.size = 0x10000,
},
{
.name = "linux",
- .offset = 0x20000,
- .size = 0x7d0000,
+ .offset = 0x30000,
+ .size = 0x3c0000,
},
{
.name = "board_config",
- .offset = 0x7f0000,
+ .offset = 0x3f0000,
.size = 0x10000,
},
};
-static struct physmap_flash_data arv4510_flash_data = {
- .nr_parts = ARRAY_SIZE(arv4510_partitions),
- .parts = arv4510_partitions,
-};
-
-static struct physmap_flash_data arv45xx_flash_data = {
- .nr_parts = ARRAY_SIZE(arv45xx_partitions),
- .parts = arv45xx_partitions,
-};
-
static struct physmap_flash_data arv45xx_brnboot_flash_data = {
.nr_parts = ARRAY_SIZE(arv45xx_brnboot_partitions),
.parts = arv45xx_brnboot_partitions,
};
-static struct physmap_flash_data arv7525_flash_data = {
- .nr_parts = ARRAY_SIZE(arv7525_partitions),
- .parts = arv7525_partitions,
+static struct physmap_flash_data arv75xx_brnboot_flash_data = {
+ .nr_parts = ARRAY_SIZE(arv75xx_brnboot_partitions),
+ .parts = arv75xx_brnboot_partitions,
};
-static struct physmap_flash_data arv75xx_flash_data = {
- .nr_parts = ARRAY_SIZE(arv75xx_partitions),
- .parts = arv75xx_partitions,
+static struct physmap_flash_data arv_flash_data = {
+ .nr_parts = ARRAY_SIZE(arv_partitions),
+ .parts = arv_partitions,
};
+static void arv_load_nor(unsigned int max)
+{
+#define UBOOT_MAGIC 0x27051956
+
+ int i;
+ int sector = -1;
+
+ if (ltq_brn_boot) {
+ if (max == 0x800000)
+ ltq_register_nor(&arv75xx_brnboot_flash_data);
+ else
+ ltq_register_nor(&arv45xx_brnboot_flash_data);
+ return;
+ }
+
+ for (i = 1; i < 4 && sector < 0; i++) {
+ unsigned int uboot_magic;
+ memcpy_fromio(&uboot_magic, (void *)KSEG1ADDR(LTQ_FLASH_START) + (i * 0x10000), 4);
+ if (uboot_magic == UBOOT_MAGIC)
+ sector = i;
+ }
+
+ if (sector < 0)
+ return;
+
+ arv_partitions[0].size = arv_partitions[1].offset = (sector - 1) * 0x10000;
+ arv_partitions[2].offset = arv_partitions[0].size + 0x10000;
+ arv_partitions[2].size = max - arv_partitions[2].offset - 0x10000;
+ arv_partitions[3].offset = max - 0x10000;
+ ltq_register_nor(&arv_flash_data);
+}
+
static struct ltq_pci_data ltq_pci_data = {
.clock = PCI_CLOCK_EXT,
.gpio = PCI_GNT1 | PCI_REQ1,
@@ -241,6 +226,45 @@ arv4518pw_gpio_keys[] __initdata = {
};
static struct gpio_led
+arv4519pw_gpio_leds[] __initdata = {
+ { .name = "soc:red:power", .gpio = 7, .active_low = 1, },
+ { .name = "soc:green:power", .gpio = 2, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:wifi", .gpio = 6, .active_low = 1, },
+ { .name = "soc:green:adsl", .gpio = 4, .active_low = 1, },
+ { .name = "soc:green:internet", .gpio = 5, .active_low = 1, },
+ { .name = "soc:red:internet", .gpio = 8, .active_low = 1, },
+ { .name = "soc:green:voip", .gpio = 100, .active_low = 1, },
+ { .name = "soc:green:phone1", .gpio = 101, .active_low = 1, },
+ { .name = "soc:green:phone2", .gpio = 102, .active_low = 1, },
+ { .name = "soc:green:fxo", .gpio = 103, .active_low = 1, },
+ { .name = "soc:green:usb", .gpio = 19, .active_low = 1, },
+ { .name = "soc:orange:wps", .gpio = 104, .active_low = 1, },
+ { .name = "soc:green:wps", .gpio = 105, .active_low = 1, },
+ { .name = "soc:red:wps", .gpio = 106, .active_low = 1, },
+
+};
+
+static struct gpio_keys_button
+arv4519pw_gpio_keys[] __initdata = {
+ {
+ .desc = "reset",
+ .type = EV_KEY,
+ .code = BTN_1,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 30,
+ .active_low = 1,
+ },
+ {
+ .desc = "wlan",
+ .type = EV_KEY,
+ .code = BTN_2,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 28,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led
arv4520pw_gpio_leds[] __initdata = {
{ .name = "soc:blue:power", .gpio = 3, .active_low = 1, },
{ .name = "soc:blue:adsl", .gpio = 4, .active_low = 1, },
@@ -285,8 +309,8 @@ arv4525pw_gpio_leds[] __initdata = {
{ .name = "soc:green:fxs-festnetz", .gpio = 4, .active_low = 1, .default_trigger = "default-on" },
};
-#define ARV4525PW_PHYRESET 13
-#define ARV4525PW_RELAY 31
+#define ARV4525PW_PHYRESET 13
+#define ARV4525PW_RELAY 31
static struct gpio arv4525pw_gpios[] __initdata = {
{ ARV4525PW_PHYRESET, GPIOF_OUT_INIT_HIGH, "phyreset" },
@@ -332,39 +356,48 @@ arv752dpw22_gpio_keys[] __initdata = {
.active_low = 1,
},
{
- .desc = "btn2",
- .type = EV_KEY,
- .code = BTN_2,
+ .desc = "btn2",
+ .type = EV_KEY,
+ .code = BTN_2,
.debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
- .gpio = 28,
- .active_low = 1,
+ .gpio = 28,
+ .active_low = 1,
},
};
static struct gpio_led
arv7518pw_gpio_leds[] __initdata = {
- { .name = "soc:green:power", .gpio = 2, .active_low = 1, },
+ { .name = "soc:red:power", .gpio = 7, .active_low = 1, },
+ { .name = "soc:green:power", .gpio = 2, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:wifi", .gpio = 6, .active_low = 1, },
{ .name = "soc:green:adsl", .gpio = 4, .active_low = 1, },
{ .name = "soc:green:internet", .gpio = 5, .active_low = 1, },
- { .name = "soc:green:wifi", .gpio = 6, .active_low = 1, },
{ .name = "soc:red:internet", .gpio = 8, .active_low = 1, },
+ { .name = "soc:green:voip", .gpio = 100, .active_low = 1, },
+ { .name = "soc:green:phone1", .gpio = 101, .active_low = 1, },
+ { .name = "soc:green:phone2", .gpio = 102, .active_low = 1, },
+ { .name = "soc:orange:fail", .gpio = 103, .active_low = 1, },
{ .name = "soc:green:usb", .gpio = 19, .active_low = 1, },
+ { .name = "soc:orange:wps", .gpio = 104, .active_low = 1, },
+ { .name = "soc:green:wps", .gpio = 105, .active_low = 1, },
+ { .name = "soc:red:wps", .gpio = 106, .active_low = 1, },
+
};
static struct gpio_keys_button
arv7518pw_gpio_keys[] __initdata = {
- {
+ /*{
.desc = "reset",
.type = EV_KEY,
- .code = BTN_0,
+ .code = BTN_1,
.debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
.gpio = 23,
.active_low = 1,
- },
+ },*/
{
.desc = "wifi",
.type = EV_KEY,
- .code = BTN_1,
+ .code = BTN_2,
.debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
.gpio = 25,
.active_low = 1,
@@ -384,70 +417,75 @@ arv7525pw_gpio_keys[] __initdata = {
};
static void
-arv45xx_register_ethernet(void)
+arv_register_ethernet(unsigned int mac_addr)
{
-#define ARV45XX_BRN_MAC 0x3f0016
memcpy_fromio(&ltq_eth_data.mac.sa_data,
- (void *)KSEG1ADDR(LTQ_FLASH_START + ARV45XX_BRN_MAC), 6);
+ (void *)KSEG1ADDR(LTQ_FLASH_START + mac_addr), 6);
ltq_register_etop(&ltq_eth_data);
}
-static void
-arv75xx_register_ethernet(void)
-{
-#define ARV75XX_BRN_MAC 0x7f0016
- memcpy_fromio(&ltq_eth_data.mac.sa_data,
- (void *)KSEG1ADDR(LTQ_FLASH_START + ARV75XX_BRN_MAC), 6);
- ltq_register_etop(&ltq_eth_data);
-}
-
-static void
-bewan_register_ethernet(void)
-{
-#define BEWAN_BRN_MAC 0x3f0014
- memcpy_fromio(&ltq_eth_data.mac.sa_data,
- (void *)KSEG1ADDR(LTQ_FLASH_START + BEWAN_BRN_MAC), 6);
- ltq_register_etop(&ltq_eth_data);
-}
-
-static u16 arv45xx_ath5k_eeprom_data[ATH5K_PLAT_EEP_MAX_WORDS];
-static u8 arv45xx_ath5k_eeprom_mac[6];
+static u16 arv_ath5k_eeprom_data[ATH5K_PLAT_EEP_MAX_WORDS];
+static u16 arv_ath9k_eeprom_data[ATH9K_PLAT_EEP_MAX_WORDS];
+static u8 arv_athxk_eeprom_mac[6];
void __init
-arv45xx_register_ath5k(void)
+arv_register_ath5k(unsigned int ath_addr, unsigned int mac_addr)
{
-#define ARV45XX_BRN_ATH 0x3f0478
int i;
- static u16 eeprom_data[ATH5K_PLAT_EEP_MAX_WORDS];
- u32 *p = (u32*)arv45xx_ath5k_eeprom_data;
-
- memcpy_fromio(arv45xx_ath5k_eeprom_mac,
- (void *)KSEG1ADDR(LTQ_FLASH_START + ARV45XX_BRN_MAC), 6);
- arv45xx_ath5k_eeprom_mac[5]++;
- memcpy_fromio(arv45xx_ath5k_eeprom_data,
- (void *)KSEG1ADDR(LTQ_FLASH_START + ARV45XX_BRN_ATH), ATH5K_PLAT_EEP_MAX_WORDS);
+
+ memcpy_fromio(arv_athxk_eeprom_mac,
+ (void *)KSEG1ADDR(LTQ_FLASH_START + mac_addr), 6);
+ arv_athxk_eeprom_mac[5]++;
+ memcpy_fromio(arv_ath5k_eeprom_data,
+ (void *)KSEG1ADDR(LTQ_FLASH_START + ath_addr), ATH5K_PLAT_EEP_MAX_WORDS);
// swap eeprom bytes
- for (i = 0; i < ATH5K_PLAT_EEP_MAX_WORDS>>1; i++){
- //arv4518_ath5k_eeprom_data[i] = ((eeprom_data[i]&0xff)<<8)|((eeprom_data[i]&0xff00)>>8);
- p[i] = ((eeprom_data[(i<<1)+1]&0xff)<<24)|((eeprom_data[(i<<1)+1]&0xff00)<<8)|((eeprom_data[i<<1]&0xff)<<8)|((eeprom_data[i<<1]&0xff00)>>8);
- if (i == 0xbf>>1){
- // printk ("regdomain: 0x%x --> 0x%x\n", p[i], (p[i] & 0xffff0000)|0x67);
- /* regdomain is invalid?? how did original fw convert
- * value to 0x82d4 ??
- * for now, force to 0x67 */
- p[i] &= 0xffff0000;
- p[i] |= 0x67;
+ for (i = 0; i < ATH5K_PLAT_EEP_MAX_WORDS>>1; i++) {
+ arv_ath5k_eeprom_data[i] = swab16(arv_ath5k_eeprom_data[i]);
+ if (i == 0x17e>>1) {
+ /*
+ * regdomain is invalid. it's unknown how did original
+ * fw convered value to 0x82d4 so for now force to 0x67
+ */
+ arv_ath5k_eeprom_data[i] &= 0x0000;
+ arv_ath5k_eeprom_data[i] |= 0x67;
}
}
}
+void __init
+arv_register_ath9k(unsigned int ath_addr, unsigned int mac_addr)
+{
+ int i;
+ u16 *eepdata, sum, el;
+
+ memcpy_fromio(arv_athxk_eeprom_mac,
+ (void *)KSEG1ADDR(LTQ_FLASH_START + mac_addr), 6);
+ arv_athxk_eeprom_mac[5]++;
+ memcpy_fromio(arv_ath9k_eeprom_data,
+ (void *)KSEG1ADDR(LTQ_FLASH_START + ath_addr), ATH9K_PLAT_EEP_MAX_WORDS);
+
+ // force regdomain to 0x67
+ arv_ath9k_eeprom_data[0x208>>1] = 0x67;
+
+ // calculate new checksum
+ sum = arv_ath9k_eeprom_data[0x200>>1];
+ el = sum / sizeof(u16) - 2; /* skip length and (old) checksum */
+ eepdata = (u16 *) (&arv_ath9k_eeprom_data[0x204>>1]); /* after checksum */
+ for (i = 0; i < el; i++)
+ sum ^= *eepdata++;
+ sum ^= 0xffff;
+ arv_ath9k_eeprom_data[0x202>>1] = sum;
+}
+
static void __init
arv3527p_init(void)
{
+#define ARV3527P_MAC_ADDR 0x3f0016
+
ltq_register_gpio_stp();
//ltq_add_device_gpio_leds(arv3527p_gpio_leds, ARRAY_SIZE(arv3527p_gpio_leds));
- ltq_register_nor(&arv45xx_flash_data);
- arv45xx_register_ethernet();
+ arv_load_nor(0x400000);
+ arv_register_ethernet(ARV3527P_MAC_ADDR);
}
MIPS_MACHINE(LANTIQ_MACH_ARV3527P,
@@ -458,14 +496,16 @@ MIPS_MACHINE(LANTIQ_MACH_ARV3527P,
static void __init
arv4510pw_init(void)
{
+#define ARV4510PW_MAC_ADDR 0x3f0014
+
ltq_register_gpio_stp();
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv4510pw_gpio_leds), arv4510pw_gpio_leds);
- ltq_register_nor(&arv4510_flash_data);
+ arv_load_nor(0x400000);
ltq_pci_data.irq[12] = (INT_NUM_IM2_IRL0 + 31);
ltq_pci_data.irq[15] = (INT_NUM_IM0_IRL0 + 26);
ltq_pci_data.gpio |= PCI_EXIN2 | PCI_REQ2;
ltq_register_pci(&ltq_pci_data);
- bewan_register_ethernet();
+ arv_register_ethernet(ARV4510PW_MAC_ADDR);
}
MIPS_MACHINE(LANTIQ_MACH_ARV4510PW,
@@ -479,19 +519,21 @@ arv4518pw_init(void)
#define ARV4518PW_EBU 0
#define ARV4518PW_USB 14
#define ARV4518PW_SWITCH_RESET 13
-#define ARV4518PW_MADWIFI_ADDR 0xb07f0400
+#define ARV4518PW_ATH_ADDR 0x3f0400
+#define ARV4518PW_MADWIFI_ADDR 0xb03f0400
+#define ARV4518PW_MAC_ADDR 0x3f0016
ltq_register_gpio_ebu(ARV4518PW_EBU);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv4518pw_gpio_leds), arv4518pw_gpio_leds);
ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL,
ARRAY_SIZE(arv4518pw_gpio_keys), arv4518pw_gpio_keys);
- ltq_register_nor(&arv45xx_flash_data);
+ arv_load_nor(0x400000);
ltq_pci_data.gpio = PCI_GNT2 | PCI_REQ2;
ltq_register_pci(&ltq_pci_data);
- ltq_register_madwifi_eep(ARV4518PW_MADWIFI_ADDR);
- ltq_register_ath5k(arv45xx_ath5k_eeprom_data, arv45xx_ath5k_eeprom_mac);
xway_register_dwc(ARV4518PW_USB);
- arv45xx_register_ethernet();
+ arv_register_ethernet(ARV4518PW_MAC_ADDR);
+ arv_register_ath5k(ARV4518PW_ATH_ADDR, ARV4518PW_MAC_ADDR);
+ ltq_register_ath5k(arv_ath5k_eeprom_data, arv_athxk_eeprom_mac);
gpio_request(ARV4518PW_SWITCH_RESET, "switch");
gpio_direction_output(ARV4518PW_SWITCH_RESET, 1);
@@ -504,18 +546,55 @@ MIPS_MACHINE(LANTIQ_MACH_ARV4518PW,
arv4518pw_init);
static void __init
+arv4519pw_init(void)
+{
+#define ARV4519PW_EBU 0
+#define ARV4519PW_USB 14
+#define ARV4519PW_RELAY 31
+#define ARV4519PW_SWITCH_RESET 13
+#define ARV4519PW_ATH_ADDR 0x3f0400
+#define ARV4519PW_MAC_ADDR 0x3f0016
+
+ arv_load_nor(0x400000);
+ ltq_register_gpio_ebu(ARV4519PW_EBU);
+ ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv4519pw_gpio_leds), arv4519pw_gpio_leds);
+ ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL,
+ ARRAY_SIZE(arv4519pw_gpio_keys), arv4519pw_gpio_keys);
+ ltq_pci_data.gpio = PCI_GNT2 | PCI_REQ1;
+ ltq_register_pci(&ltq_pci_data);
+ xway_register_dwc(ARV4519PW_USB);
+ arv_register_ethernet(ARV4519PW_MAC_ADDR);
+ arv_register_ath5k(ARV4519PW_ATH_ADDR, ARV4519PW_MAC_ADDR);
+ ltq_register_ath5k(arv_ath5k_eeprom_data, arv_athxk_eeprom_mac);
+
+ gpio_request(ARV4519PW_RELAY, "relay");
+ gpio_direction_output(ARV4519PW_RELAY, 1);
+ gpio_export(ARV4519PW_RELAY, 0);
+
+ gpio_request(ARV4519PW_SWITCH_RESET, "switch");
+ gpio_set_value(ARV4519PW_SWITCH_RESET, 1);
+ gpio_export(ARV4519PW_SWITCH_RESET, 0);
+}
+
+MIPS_MACHINE(LANTIQ_MACH_ARV4519PW,
+ "ARV4519PW",
+ "ARV4519PW - Vodafone, Pirelli",
+ arv4519pw_init);
+
+static void __init
arv4520pw_init(void)
{
#define ARV4520PW_EBU 0x400
#define ARV4520PW_USB 28
#define ARV4520PW_SWITCH_RESET 110
+#define ARV4520PW_MAC_ADDR 0x3f0016
ltq_register_gpio_ebu(ARV4520PW_EBU);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv4520pw_gpio_leds), arv4520pw_gpio_leds);
- ltq_register_nor(&arv45xx_flash_data);
+ arv_load_nor(0x400000);
ltq_register_pci(&ltq_pci_data);
ltq_register_tapi();
- arv45xx_register_ethernet();
+ arv_register_ethernet(ARV4520PW_MAC_ADDR);
xway_register_dwc(ARV4520PW_USB);
gpio_request(ARV4520PW_SWITCH_RESET, "switch");
@@ -535,16 +614,18 @@ arv452Cpw_init(void)
#define ARV452CPW_RELAY1 31
#define ARV452CPW_RELAY2 107
#define ARV452CPW_SWITCH_RESET 110
-#define ARV452CPW_MADWIFI_ADDR 0xb07f0400
+#define ARV452CPW_ATH_ADDR 0x3f0400
+#define ARV452CPW_MADWIFI_ADDR 0xb03f0400
+#define ARV452CPW_MAC_ADDR 0x3f0016
ltq_register_gpio_ebu(ARV452CPW_EBU);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv452cpw_gpio_leds), arv452cpw_gpio_leds);
- ltq_register_nor(&arv45xx_flash_data);
+ arv_load_nor(0x400000);
ltq_register_pci(&ltq_pci_data);
- ltq_register_madwifi_eep(ARV452CPW_MADWIFI_ADDR);
xway_register_dwc(ARV452CPW_USB);
- arv45xx_register_ethernet();
- arv45xx_register_ath5k();
+ arv_register_ethernet(ARV452CPW_MAC_ADDR);
+ arv_register_ath5k(ARV452CPW_ATH_ADDR, ARV452CPW_MAC_ADDR);
+ ltq_register_ath5k(arv_ath5k_eeprom_data, arv_athxk_eeprom_mac);
gpio_request(ARV452CPW_SWITCH_RESET, "switch");
gpio_set_value(ARV452CPW_SWITCH_RESET, 1);
@@ -567,23 +648,21 @@ MIPS_MACHINE(LANTIQ_MACH_ARV452CPW,
static void __init
arv4525pw_init(void)
{
+#define ARV4525PW_ATH_ADDR 0x3f0400
#define ARV4525PW_MADWIFI_ADDR 0xb03f0400
- if (ltq_brn_boot)
- ltq_register_nor(&arv45xx_brnboot_flash_data);
- else
- ltq_register_nor(&arv45xx_flash_data);
+#define ARV4525PW_MAC_ADDR 0x3f0016
+ arv_load_nor(0x400000);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv4525pw_gpio_leds), arv4525pw_gpio_leds);
gpio_request_array(arv4525pw_gpios, ARRAY_SIZE(arv4525pw_gpios));
gpio_export(ARV4525PW_RELAY, false);
gpio_export(ARV4525PW_PHYRESET, false);
ltq_pci_data.clock = PCI_CLOCK_INT;
ltq_register_pci(&ltq_pci_data);
- ltq_register_madwifi_eep(ARV4525PW_MADWIFI_ADDR);
- arv45xx_register_ath5k();
- ltq_register_ath5k(arv45xx_ath5k_eeprom_data, arv45xx_ath5k_eeprom_mac);
+ arv_register_ath5k(ARV4525PW_ATH_ADDR, ARV4525PW_MADWIFI_ADDR);
+ ltq_register_ath5k(arv_ath5k_eeprom_data, arv_athxk_eeprom_mac);
ltq_eth_data.mii_mode = PHY_INTERFACE_MODE_MII;
- arv45xx_register_ethernet();
+ arv_register_ethernet(ARV4525PW_MAC_ADDR);
}
MIPS_MACHINE(LANTIQ_MACH_ARV4525PW,
@@ -594,8 +673,10 @@ MIPS_MACHINE(LANTIQ_MACH_ARV4525PW,
static void __init
arv7525pw_init(void)
{
+#define ARV7525P_MAC_ADDR 0x3f0016
+
+ arv_load_nor(0x400000);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv4525pw_gpio_leds), arv4525pw_gpio_leds);
- ltq_register_nor(&arv7525_flash_data);
ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL,
ARRAY_SIZE(arv7525pw_gpio_keys), arv7525pw_gpio_keys);
ltq_pci_data.clock = PCI_CLOCK_INT;
@@ -605,7 +686,7 @@ arv7525pw_init(void)
ltq_eth_data.mii_mode = PHY_INTERFACE_MODE_MII;
ltq_register_rt2x00("RT2860.eeprom");
ltq_register_tapi();
- arv45xx_register_ethernet();
+ arv_register_ethernet(ARV7525P_MAC_ADDR);
}
MIPS_MACHINE(LANTIQ_MACH_ARV7525PW,
@@ -618,17 +699,26 @@ arv7518pw_init(void)
{
#define ARV7518PW_EBU 0x2
#define ARV7518PW_USB 14
+#define ARV7518PW_SWITCH_RESET 13
+#define ARV7518PW_ATH_ADDR 0x7f0400
+#define ARV7518PW_MAC_ADDR 0x7f0016
+ arv_load_nor(0x800000);
ltq_register_gpio_ebu(ARV7518PW_EBU);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv7518pw_gpio_leds), arv7518pw_gpio_leds);
ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL,
ARRAY_SIZE(arv7518pw_gpio_keys), arv7518pw_gpio_keys);
- ltq_register_nor(&arv75xx_flash_data);
ltq_register_pci(&ltq_pci_data);
ltq_register_tapi();
xway_register_dwc(ARV7518PW_USB);
- arv75xx_register_ethernet();
- //arv7518_register_ath9k(mac);
+ arv_register_ethernet(ARV7518PW_MAC_ADDR);
+ arv_register_ath9k(ARV7518PW_ATH_ADDR, ARV7518PW_MAC_ADDR);
+ ltq_register_ath9k(arv_ath9k_eeprom_data, arv_athxk_eeprom_mac);
+ ltq_pci_ath_fixup(14, arv_ath9k_eeprom_data);
+
+ gpio_request(ARV7518PW_SWITCH_RESET, "switch");
+ gpio_direction_output(ARV7518PW_SWITCH_RESET, 1);
+ gpio_export(ARV7518PW_SWITCH_RESET, 0);
}
MIPS_MACHINE(LANTIQ_MACH_ARV7518PW,
@@ -642,17 +732,18 @@ arv752dpw22_init(void)
#define ARV752DPW22_EBU 0x2
#define ARV752DPW22_USB 100
#define ARV752DPW22_RELAY 101
+#define ARV752DPW22_MAC_ADDR 0x7f0016
+ arv_load_nor(0x800000);
ltq_register_gpio_ebu(ARV752DPW22_EBU);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv752dpw22_gpio_leds), arv752dpw22_gpio_leds);
ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL,
ARRAY_SIZE(arv752dpw22_gpio_keys), arv752dpw22_gpio_keys);
- ltq_register_nor(&arv75xx_flash_data);
ltq_pci_data.irq[15] = (INT_NUM_IM3_IRL0 + 31);
ltq_pci_data.gpio |= PCI_EXIN1 | PCI_REQ2;
ltq_register_pci(&ltq_pci_data);
xway_register_dwc(ARV752DPW22_USB);
- arv75xx_register_ethernet();
+ arv_register_ethernet(ARV752DPW22_MAC_ADDR);
gpio_request(ARV752DPW22_RELAY, "relay");
gpio_set_value(ARV752DPW22_RELAY, 1);
diff --git a/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-bthomehubv2b.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-bthomehubv2b.c
new file mode 100644
index 0000000..44fe2f4
--- /dev/null
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-bthomehubv2b.c
@@ -0,0 +1,542 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2011 Andrej Vlašić
+ * Copyright (C) 2011 Luka Perkov
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+#include <linux/ath5k_platform.h>
+#include <linux/ath9k_platform.h>
+#include <linux/pci.h>
+#include <linux/phy.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+
+#include <irq.h>
+#include <lantiq_soc.h>
+#include <lantiq_platform.h>
+#include <dev-gpio-leds.h>
+#include <dev-gpio-buttons.h>
+
+#include "../machtypes.h"
+//#include "dev-wifi-ath9k.h"
+#include "devices.h"
+#include "dev-dwc_otg.h"
+
+#undef USE_BTHH_GPIO_INIT
+
+// this reads certain data from u-boot if it's there
+#define USE_UBOOT_ENV_DATA
+
+#define UBOOT_ENV_OFFSET 0x040000
+#define UBOOT_ENV_SIZE 0x010000
+
+#ifdef NAND_ORGLAYOUT
+// this is only here for reference
+// definition of NAND flash area
+static struct mtd_partition bthomehubv2b_nand_partitions[] =
+{
+ {
+ .name = "ART",
+ .offset = 0x0000000,
+ .size = 0x0004000,
+ },
+ {
+ .name = "image1",
+ .offset = 0x0004000,
+ .size = 0x0E00000,
+ },
+ {
+ .name = "unknown1",
+ .offset = 0x0E04000,
+ .size = 0x00FC000,
+ },
+ {
+ .name = "image2",
+ .offset = 0x0F00000,
+ .size = 0x0E00000,
+ },
+ {
+ .name = "unknown2",
+ .offset = 0x1D00000,
+ .size = 0x0300000,
+ },
+
+};
+#endif
+
+#ifdef NAND_KEEPOPENRG
+// this allows both firmwares to co-exist
+
+static struct mtd_partition bthomehubv2b_nand_partitions[] =
+{
+ {
+ .name = "art",
+ .offset = 0x0000000,
+ .size = 0x0004000,
+ },
+ {
+ .name = "Image1",
+ .offset = 0x0004000,
+ .size = 0x0E00000,
+ },
+ {
+ .name = "linux",
+ .offset = 0x0E04000,
+ .size = 0x11fC000,
+ },
+ {
+ .name = "wholeflash",
+ .offset = 0x0000000,
+ .size = 0x2000000,
+ },
+
+};
+#endif
+
+// this gives more jffs2 by overwriting openrg
+
+static struct mtd_partition bthomehubv2b_nand_partitions[] =
+{
+ {
+ .name = "art",
+ .offset = 0x0000000,
+ .size = 0x0004000,
+ },
+ {
+ .name = "linux",
+ .offset = 0x0004000,
+ .size = 0x1ffC000,
+ },
+ {
+ .name = "wholeflash",
+ .offset = 0x0000000,
+ .size = 0x2000000,
+ },
+
+};
+
+extern void __init xway_register_nand(struct mtd_partition *parts, int count);
+
+// end BTHH_USE_NAND
+
+static struct gpio_led
+bthomehubv2b_gpio_leds[] __initdata = {
+
+ { .name = "soc:orange:upgrading", .gpio = 213, },
+ { .name = "soc:orange:phone", .gpio = 214, },
+ { .name = "soc:blue:phone", .gpio = 215, },
+ { .name = "soc:orange:wireless", .gpio = 216, },
+ { .name = "soc:blue:wireless", .gpio = 217, },
+ { .name = "soc:red:broadband", .gpio = 218, },
+ { .name = "soc:orange:broadband", .gpio = 219, },
+ { .name = "soc:blue:broadband", .gpio = 220, },
+ { .name = "soc:red:power", .gpio = 221, },
+ { .name = "soc:orange:power", .gpio = 222, },
+ { .name = "soc:blue:power", .gpio = 223, },
+};
+
+static struct gpio_keys_button
+bthomehubv2b_gpio_keys[] __initdata = {
+ {
+ .desc = "restart",
+ .type = EV_KEY,
+ .code = BTN_0,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 2,
+ .active_low = 1,
+ },
+ {
+ .desc = "findhandset",
+ .type = EV_KEY,
+ .code = BTN_1,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 15,
+ .active_low = 1,
+ },
+ {
+ .desc = "wps",
+ .type = EV_KEY,
+ .code = BTN_2,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 22,
+ .active_low = 1,
+ },
+};
+
+// definition of NOR flash area - as per original.
+static struct mtd_partition bthomehubv2b_partitions[] =
+{
+ {
+ .name = "uboot",
+ .offset = 0x000000,
+ .size = 0x040000,
+ },
+ {
+ .name = "uboot_env",
+ .offset = UBOOT_ENV_OFFSET,
+ .size = UBOOT_ENV_SIZE,
+ },
+ {
+ .name = "rg_conf_1",
+ .offset = 0x050000,
+ .size = 0x010000,
+ },
+ {
+ .name = "rg_conf_2",
+ .offset = 0x060000,
+ .size = 0x010000,
+ },
+ {
+ .name = "rg_conf_factory",
+ .offset = 0x070000,
+ .size = 0x010000,
+ },
+};
+
+
+/* nor flash */
+/* bt homehubv2b has a very small nor flash */
+/* so make it look for a small one, else we get a lot of alias chips identified - */
+/* not a bug problem, but fills the logs. */
+static struct resource bthhv2b_nor_resource =
+ MEM_RES("nor", LTQ_FLASH_START, 0x80000);
+
+static struct platform_device ltq_nor = {
+ .name = "ltq_nor",
+ .resource = &bthhv2b_nor_resource,
+ .num_resources = 1,
+};
+
+static void __init bthhv2b_register_nor(struct physmap_flash_data *data)
+{
+ ltq_nor.dev.platform_data = data;
+ platform_device_register(&ltq_nor);
+}
+
+static struct physmap_flash_data bthomehubv2b_flash_data = {
+ .nr_parts = ARRAY_SIZE(bthomehubv2b_partitions),
+ .parts = bthomehubv2b_partitions,
+};
+
+
+
+
+static struct ltq_pci_data ltq_pci_data = {
+ .clock = PCI_CLOCK_INT,
+ .gpio = PCI_GNT1 | PCI_REQ1,
+ .irq = { [14] = INT_NUM_IM0_IRL0 + 22, },
+};
+
+
+
+
+static struct ltq_eth_data ltq_eth_data = {
+ .mii_mode = PHY_INTERFACE_MODE_MII,
+};
+
+
+
+
+static char __init *get_uboot_env_var(char *haystack, int haystack_len, char *needle, int needle_len) {
+ int i;
+ for (i = 0; i <= haystack_len - needle_len; i++) {
+ if (memcmp(haystack + i, needle, needle_len) == 0) {
+ return haystack + i + needle_len;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * bthomehubv2b_parse_hex_* are not uniq. in arm/orion there are also duplicates:
+ * dns323_parse_hex_*
+ * TODO: one day write a patch for this :)
+ */
+static int __init bthomehubv2b_parse_hex_nibble(char n) {
+ if (n >= '0' && n <= '9')
+ return n - '0';
+
+ if (n >= 'A' && n <= 'F')
+ return n - 'A' + 10;
+
+ if (n >= 'a' && n <= 'f')
+ return n - 'a' + 10;
+
+ return -1;
+}
+
+static int __init bthomehubv2b_parse_hex_byte(const char *b) {
+ int hi;
+ int lo;
+
+ hi = bthomehubv2b_parse_hex_nibble(b[0]);
+ lo = bthomehubv2b_parse_hex_nibble(b[1]);
+
+ if (hi < 0 || lo < 0)
+ return -1;
+
+ return (hi << 4) | lo;
+}
+
+static int __init bthomehubv2b_register_ethernet(void) {
+ u_int8_t addr[6];
+ int i;
+ char *mac = "01:02:03:04:05:06";
+ int gotmac = 0;
+ char *boardid = "BTHHV2B";
+ int gotboardid = 0;
+
+ char *uboot_env_page;
+ uboot_env_page = ioremap(LTQ_FLASH_START + UBOOT_ENV_OFFSET, UBOOT_ENV_SIZE);
+ if (uboot_env_page)
+ {
+ char *Data = NULL;
+ Data = get_uboot_env_var(uboot_env_page, UBOOT_ENV_SIZE, "\0ethaddr=", 9);
+ if (Data)
+ {
+ mac = Data;
+ }
+
+ Data = get_uboot_env_var(uboot_env_page, UBOOT_ENV_SIZE, "\0boardid=", 9);
+
+ if (Data)
+ boardid = Data;
+ }
+ else
+ {
+ printk("bthomehubv2b: Failed to get uboot_env_page");
+ }
+
+ if (!mac) {
+ goto error_fail;
+ }
+
+ if (!boardid) {
+ goto error_fail;
+ }
+
+ /* Sanity check the string we're looking at */
+ for (i = 0; i < 5; i++) {
+ if (*(mac + (i * 3) + 2) != ':') {
+ goto error_fail;
+ }
+ }
+
+ for (i = 0; i < 6; i++) {
+ int byte;
+ byte = bthomehubv2b_parse_hex_byte(mac + (i * 3));
+ if (byte < 0) {
+ goto error_fail;
+ }
+ addr[i] = byte;
+ }
+
+ if (gotmac)
+ printk("bthomehubv2b: Found ethernet MAC address: ");
+ else
+ printk("bthomehubv2b: using default MAC (pls set ethaddr in u-boot): ");
+
+ for (i = 0; i < 6; i++)
+ printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n");
+
+ memcpy(&ltq_eth_data.mac.sa_data, addr, 6);
+ ltq_register_etop(&ltq_eth_data);
+
+ //memcpy(&bthomehubv2b_ath5k_eeprom_mac, addr, 6);
+ //bthomehubv2b_ath5k_eeprom_mac[5]++;
+
+ if (gotboardid)
+ printk("bthomehubv2b: Board id is %s.", boardid);
+ else
+ printk("bthomehubv2b: Default Board id is %s.", boardid);
+
+ if (strncmp(boardid, "BTHHV2B", 7) == 0) {
+ // read in dev-wifi-ath9k
+ //memcpy(&bthomehubv2b_ath5k_eeprom_data, sx763_eeprom_data, ATH5K_PLAT_EEP_MAX_WORDS);
+ }
+ else {
+ printk("bthomehubv2b: Board id is unknown, fix uboot_env data.");
+ }
+
+
+ // should not unmap while we are using the ram?
+ if (uboot_env_page)
+ iounmap(uboot_env_page);
+
+ return 0;
+
+error_fail:
+ if (uboot_env_page)
+ iounmap(uboot_env_page);
+ return -EINVAL;
+}
+
+
+#define PORTA2_HW_PASS1 0
+#define PORTA2_HW_PASS1_SC14480 1
+#define PORTA2_HW_PASS2 2
+
+int porta2_hw_revision = -1;
+EXPORT_SYMBOL(porta2_hw_revision);
+
+#define LTQ_GPIO_OUT 0x00
+#define LTQ_GPIO_IN 0x04
+#define LTQ_GPIO_DIR 0x08
+#define LTQ_GPIO_ALTSEL0 0x0C
+#define LTQ_GPIO_ALTSEL1 0x10
+#define LTQ_GPIO_OD 0x14
+#define LTQ_GPIO_PUDSEL 0x1C
+#define LTQ_GPIO_PUDEN 0x20
+
+#ifdef USE_BTHH_GPIO_INIT
+static void bthomehubv2b_board_prom_init(void)
+{
+ int revision = 0;
+ unsigned int gpio = 0;
+ void __iomem *mem = ioremap(LTQ_GPIO0_BASE_ADDR, LTQ_GPIO_SIZE*2);
+
+#define DANUBE_GPIO_P0_OUT (unsigned short *)(mem + LTQ_GPIO_OUT)
+#define DANUBE_GPIO_P0_IN (unsigned short *)(mem + LTQ_GPIO_IN)
+#define DANUBE_GPIO_P0_DIR (unsigned short *)(mem + LTQ_GPIO_DIR)
+#define DANUBE_GPIO_P0_ALTSEL0 (unsigned short *)(mem + LTQ_GPIO_ALTSEL0)
+#define DANUBE_GPIO_P0_ALTSEL1 (unsigned short *)(mem + LTQ_GPIO_ALTSEL1)
+
+#define DANUBE_GPIO_P1_OUT (unsigned short *)(mem + LTQ_GPIO_SIZE + LTQ_GPIO_OUT)
+#define DANUBE_GPIO_P1_IN (unsigned short *)(mem + LTQ_GPIO_SIZE + LTQ_GPIO_IN)
+#define DANUBE_GPIO_P1_DIR (unsigned short *)(mem + LTQ_GPIO_SIZE + LTQ_GPIO_DIR)
+#define DANUBE_GPIO_P1_ALTSEL0 (unsigned short *)(mem + LTQ_GPIO_SIZE + LTQ_GPIO_ALTSEL0)
+#define DANUBE_GPIO_P1_ALTSEL1 (unsigned short *)(mem + LTQ_GPIO_SIZE + LTQ_GPIO_ALTSEL1)
+#define DANUBE_GPIO_P1_OD (unsigned short *)(mem + LTQ_GPIO_SIZE + LTQ_GPIO_OD)
+
+ printk("About to sense board using GPIOs at %8.8X\n", (unsigned int)mem);
+
+
+ /* First detect HW revision of the board. For that we need to set the GPIO
+ * lines according to table 7.2.1/7.2.2 in HSI */
+ *DANUBE_GPIO_P0_OUT = 0x0200;
+ *DANUBE_GPIO_P0_DIR = 0x2610;
+ *DANUBE_GPIO_P0_ALTSEL0 = 0x7812;
+ *DANUBE_GPIO_P0_ALTSEL1 = 0x0000;
+
+ *DANUBE_GPIO_P1_OUT = 0x7008;
+ *DANUBE_GPIO_P1_DIR = 0xF3AE;
+ *DANUBE_GPIO_P1_ALTSEL0 = 0x83A7;
+ *DANUBE_GPIO_P1_ALTSEL1 = 0x0400;
+
+ gpio = (*DANUBE_GPIO_P0_IN & 0xFFFF) |
+ ((*DANUBE_GPIO_P1_IN & 0xFFFF) << 16);
+
+ revision |= (gpio & (1 << 27)) ? (1 << 0) : 0;
+ revision |= (gpio & (1 << 20)) ? (1 << 1) : 0;
+ revision |= (gpio & (1 << 8)) ? (1 << 2) : 0;
+ revision |= (gpio & (1 << 6)) ? (1 << 3) : 0;
+ revision |= (gpio & (1 << 5)) ? (1 << 4) : 0;
+ revision |= (gpio & (1 << 0)) ? (1 << 5) : 0;
+
+ porta2_hw_revision = revision;
+ printk("PORTA2: detected HW revision %d\n", revision);
+
+ /* Set GPIO lines according to HW revision. */
+ /* !!! Note that we are setting SPI_CS5 (GPIO 9) to be GPIO out with value
+ * of HIGH since the FXO does not use the SPI CS mechanism, it does it
+ * manually by controlling the GPIO line. We need the CS line to be disabled
+ * (HIGH) until needed since it will intefere with other devices on the SPI
+ * bus. */
+ *DANUBE_GPIO_P0_OUT = 0x0200;
+ /*
+ * During the manufacturing process a different machine takes over uart0
+ * so set it as input (so it wouldn't drive the line)
+ */
+#define cCONFIG_SHC_BT_MFG_TEST 0
+ *DANUBE_GPIO_P0_DIR = 0x2671 | (cCONFIG_SHC_BT_MFG_TEST ? 0 : (1 << 12));
+
+ if (revision == PORTA2_HW_PASS1_SC14480 || revision == PORTA2_HW_PASS2)
+ *DANUBE_GPIO_P0_ALTSEL0 = 0x7873;
+ else
+ *DANUBE_GPIO_P0_ALTSEL0 = 0x3873;
+
+ *DANUBE_GPIO_P0_ALTSEL1 = 0x0001;
+
+
+ //###################################################################################
+ // Register values before patch
+ // P1_ALTSEL0 = 0x83A7
+ // P1_ALTSEL1 = 0x0400
+ // P1_OU T = 0x7008
+ // P1_DIR = 0xF3AE
+ // P1_OD = 0xE3Fc
+ printk("\nApplying Patch for CPU1 IRQ Issue\n");
+ *DANUBE_GPIO_P1_ALTSEL0 &= ~(1<<12); // switch P1.12 (GPIO28) to GPIO functionality
+ *DANUBE_GPIO_P1_ALTSEL1 &= ~(1<<12); // switch P1.12 (GPIO28) to GPIO functionality
+ *DANUBE_GPIO_P1_OUT &= ~(1<<12); // set P1.12 (GPIO28) to 0
+ *DANUBE_GPIO_P1_DIR |= (1<<12); // configure P1.12 (GPIO28) as output
+ *DANUBE_GPIO_P1_OD |= (1<<12); // activate Push/Pull mode
+ udelay(100); // wait a little bit (100us)
+ *DANUBE_GPIO_P1_OD &= ~(1<<12); // switch back from Push/Pull to Open Drain
+ // important: before! setting output to 1 (3,3V) the mode must be switched
+ // back to Open Drain because the reset pin of the SC14488 is internally
+ // pulled to 1,8V
+ *DANUBE_GPIO_P1_OUT |= (1<<12); // set output P1.12 (GPIO28) to 1
+ // Register values after patch, should be the same as before
+ // P1_ALTSEL0 = 0x83A7
+ // P1_ALTSEL1 = 0x0400
+ // P1_OUT = 0x7008
+ // P1_DIR = 0xF3AE
+ // P1_OD = 0xE3Fc
+ //###################################################################################
+
+
+ *DANUBE_GPIO_P1_OUT = 0x7008;
+ *DANUBE_GPIO_P1_DIR = 0xEBAE | (revision == PORTA2_HW_PASS2 ? 0x1000 : 0);
+ *DANUBE_GPIO_P1_ALTSEL0 = 0x8BA7;
+ *DANUBE_GPIO_P1_ALTSEL1 = 0x0400;
+
+ iounmap(mem);
+}
+#endif
+static void __init bthomehubv2b_init(void) {
+#define bthomehubv2b_USB 13
+
+ // read the board version
+#ifdef USE_BTHH_GPIO_INIT
+ bthomehubv2b_board_prom_init();
+#endif
+
+ // register extra GPPOs used by LEDs as GPO 0x200+
+ ltq_register_gpio_stp();
+ ltq_add_device_gpio_leds(-1, ARRAY_SIZE(bthomehubv2b_gpio_leds), bthomehubv2b_gpio_leds);
+ bthhv2b_register_nor(&bthomehubv2b_flash_data);
+ xway_register_nand(bthomehubv2b_nand_partitions, ARRAY_SIZE(bthomehubv2b_nand_partitions));
+ ltq_register_pci(&ltq_pci_data);
+ ltq_register_tapi();
+ ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, ARRAY_SIZE(bthomehubv2b_gpio_keys), bthomehubv2b_gpio_keys);
+// ltq_register_ath9k();
+ xway_register_dwc(bthomehubv2b_USB);
+ bthomehubv2b_register_ethernet();
+
+}
+
+MIPS_MACHINE(LANTIQ_MACH_BTHOMEHUBV2BOPENRG,
+ "BTHOMEHUBV2BOPENRG",
+ "BTHOMEHUBV2B - BT Homehub V2.0 Type B with OpenRG image retained",
+ bthomehubv2b_init);
+
+MIPS_MACHINE(LANTIQ_MACH_BTHOMEHUBV2B,
+ "BTHOMEHUBV2B",
+ "BTHOMEHUBV2B - BT Homehub V2.0 Type B",
+ bthomehubv2b_init);
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-easy50601.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-easy50601.c
index a5a0105..a5a0105 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-easy50601.c
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-easy50601.c
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-easy50712.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-easy50712.c
index 2fddfca..2fddfca 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-easy50712.c
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-easy50712.c
diff --git a/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-fritz_ar9.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-fritz_ar9.c
new file mode 100644
index 0000000..503e4be
--- /dev/null
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-fritz_ar9.c
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+#include <linux/phy.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/spi/flash.h>
+
+#include <lantiq_soc.h>
+#include <irq.h>
+
+#include "../machtypes.h"
+#include "devices.h"
+#include "dev-ifxhcd.h"
+#include "dev-gpio-leds.h"
+#include "dev-gpio-buttons.h"
+
+static struct mtd_partition fritz7320_partitions[] = {
+ {
+ .name = "urlader",
+ .offset = 0x0,
+ .size = 0x20000,
+ },
+ {
+ .name = "linux",
+ .offset = 0x20000,
+ .size = 0xf60000,
+ },
+ {
+ .name = "tffs (1)",
+ .offset = 0xf80000,
+ .size = 0x40000,
+ },
+ {
+ .name = "tffs (2)",
+ .offset = 0xfc0000,
+ .size = 0x40000,
+ },
+};
+
+static struct physmap_flash_data fritz7320_flash_data = {
+ .nr_parts = ARRAY_SIZE(fritz7320_partitions),
+ .parts = fritz7320_partitions,
+};
+
+static struct gpio_led
+fritz7320_gpio_leds[] __initdata = {
+ { .name = "soc:green:power", .gpio = 44, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:internet", .gpio = 47, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:dect", .gpio = 38, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:wlan", .gpio = 37, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:dual1", .gpio = 35, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:red:dual2", .gpio = 45, .active_low = 1, .default_trigger = "default-on" },
+};
+
+static struct gpio_keys_button
+fritz7320_gpio_keys[] __initdata = {
+ {
+ .desc = "wifi",
+ .type = EV_KEY,
+ .code = BTN_0,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 1,
+ .active_low = 1,
+ },
+ {
+ .desc = "dect",
+ .type = EV_KEY,
+ .code = BTN_1,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 2,
+ .active_low = 1,
+ },
+};
+
+static struct ltq_pci_data ltq_pci_data = {
+ .clock = PCI_CLOCK_INT,
+ .gpio = PCI_GNT1 | PCI_REQ1,
+ .irq = {
+ [14] = INT_NUM_IM0_IRL0 + 22,
+ },
+};
+
+static struct ltq_eth_data ltq_eth_data = {
+ .mii_mode = PHY_INTERFACE_MODE_RMII,
+};
+
+static int usb_pins[2] = { 50, 51 };
+
+static void __init fritz7320_init(void)
+{
+ ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL,
+ ARRAY_SIZE(fritz7320_gpio_keys), fritz7320_gpio_keys);
+ ltq_add_device_gpio_leds(-1, ARRAY_SIZE(fritz7320_gpio_leds), fritz7320_gpio_leds);
+ ltq_register_pci(&ltq_pci_data);
+ ltq_register_etop(&ltq_eth_data);
+ ltq_register_nor(&fritz7320_flash_data);
+ xway_register_hcd(usb_pins);
+}
+
+MIPS_MACHINE(LANTIQ_MACH_FRITZ7320,
+ "FRITZ7320",
+ "FRITZ!BOX 7320",
+ fritz7320_init);
diff --git a/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-fritz_vr9.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-fritz_vr9.c
new file mode 100644
index 0000000..4a38988
--- /dev/null
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-fritz_vr9.c
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+#include <linux/phy.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/spi/flash.h>
+
+#include <lantiq_soc.h>
+#include <irq.h>
+
+#include "../machtypes.h"
+#include "devices.h"
+#include "dev-ifxhcd.h"
+#include "dev-gpio-leds.h"
+#include "dev-gpio-buttons.h"
+
+static struct mtd_partition fritz3370_partitions[] = {
+ {
+ .name = "linux",
+ .offset = 0x0,
+ .size = 0x400000,
+ },
+ {
+ .name = "filesystem",
+ .offset = 0x400000,
+ .size = 0x3000000,
+ },
+ {
+ .name = "reserved-kernel",
+ .offset = 0x3400000,
+ .size = 0x400000,
+ },
+ {
+ .name = "reserved",
+ .offset = 0x3800000,
+ .size = 0x3000000,
+ },
+ {
+ .name = "config",
+ .offset = 0x6800000,
+ .size = 0x200000,
+ },
+ {
+ .name = "nand-filesystem",
+ .offset = 0x6a00000,
+ .size = 0x1600000,
+ },
+};
+
+static struct mtd_partition spi_flash_partitions[] = {
+ {
+ .name = "urlader",
+ .offset = 0x0,
+ .size = 0x20000,
+ },
+ {
+ .name = "tffs",
+ .offset = 0x20000,
+ .size = 0x10000,
+ },
+ {
+ .name = "tffs",
+ .offset = 0x30000,
+ .size = 0x10000,
+ },
+};
+
+static struct gpio_led
+fritz3370_gpio_leds[] __initdata = {
+ { .name = "soc:green:1", .gpio = 32, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:red:2", .gpio = 33, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:red:3", .gpio = 34, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:4", .gpio = 35, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:5", .gpio = 36, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:6", .gpio = 47, .active_low = 1, .default_trigger = "default-on" },
+};
+
+static struct gpio_keys_button
+fritz3370_gpio_keys[] __initdata = {
+ {
+ .desc = "wifi",
+ .type = EV_KEY,
+ .code = BTN_0,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 29,
+ .active_low = 1,
+ },
+};
+
+static struct ltq_eth_data ltq_eth_data = {
+ .mii_mode = PHY_INTERFACE_MODE_RMII,
+};
+
+static int usb_pins[2] = { 5, 14 };
+
+#define SPI_GPIO_MRST 16
+#define SPI_GPIO_MTSR 17
+#define SPI_GPIO_CLK 18
+#define SPI_GPIO_CS0 10
+
+static struct spi_gpio_platform_data spi_gpio_data = {
+ .sck = SPI_GPIO_CLK,
+ .mosi = SPI_GPIO_MTSR,
+ .miso = SPI_GPIO_MRST,
+ .num_chipselect = 2,
+};
+
+static struct platform_device spi_gpio_device = {
+ .name = "spi_gpio",
+ .dev.platform_data = &spi_gpio_data,
+};
+
+static struct flash_platform_data spi_flash_data = {
+ .name = "SPL",
+ .parts = spi_flash_partitions,
+ .nr_parts = ARRAY_SIZE(spi_flash_partitions),
+};
+
+static struct spi_board_info spi_flash __initdata = {
+ .modalias = "m25p80",
+ .bus_num = 0,
+ .chip_select = 0,
+ .max_speed_hz = 10 * 1000 * 1000,
+ .mode = SPI_MODE_3,
+ .chip_select = 0,
+ .controller_data = (void *) SPI_GPIO_CS0,
+ .platform_data = &spi_flash_data
+};
+
+static void __init
+spi_gpio_init(void)
+{
+ spi_register_board_info(&spi_flash, 1);
+ platform_device_register(&spi_gpio_device);
+}
+
+static void __init fritz3370_init(void)
+{
+ spi_gpio_init();
+ platform_device_register_simple("pcie-xway", 0, NULL, 0);
+ xway_register_nand(fritz3370_partitions, ARRAY_SIZE(fritz3370_partitions));
+ xway_register_hcd(usb_pins);
+ ltq_add_device_gpio_leds(-1, ARRAY_SIZE(fritz3370_gpio_leds), fritz3370_gpio_leds);
+ ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL,
+ ARRAY_SIZE(fritz3370_gpio_keys), fritz3370_gpio_keys);
+ ltq_register_vrx200(&ltq_eth_data);
+}
+
+MIPS_MACHINE(LANTIQ_MACH_FRITZ3370,
+ "FRITZ3370",
+ "FRITZ!BOX 3370",
+ fritz3370_init);
diff --git a/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-gigasx76x.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-gigasx76x.c
new file mode 100644
index 0000000..c7a2de5
--- /dev/null
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-gigasx76x.c
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2011 Andrej Vlašić
+ * Copyright (C) 2011 Luka Perkov
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+#include <linux/ath5k_platform.h>
+#include <linux/pci.h>
+#include <linux/phy.h>
+#include <linux/io.h>
+#include <linux/if_ether.h>
+#include <linux/etherdevice.h>
+#include <linux/string.h>
+
+#include <irq.h>
+#include <lantiq_soc.h>
+#include <lantiq_platform.h>
+#include <dev-gpio-leds.h>
+#include <dev-gpio-buttons.h>
+
+#include "../machtypes.h"
+#include "dev-wifi-athxk.h"
+#include "devices.h"
+#include "dev-dwc_otg.h"
+
+#include "mach-gigasx76x.h"
+
+static u8 ltq_ethaddr[6] = { 0 };
+
+static int __init setup_ethaddr(char *str)
+{
+ if (!mac_pton(str, ltq_ethaddr))
+ memset(ltq_ethaddr, 0, 6);
+ return 0;
+}
+__setup("ethaddr=", setup_ethaddr);
+
+
+enum {
+ UNKNOWN = 0,
+ SX761,
+ SX762,
+ SX763,
+};
+static u8 board = SX763;
+
+static int __init setup_board(char *str)
+{
+ if (!strcmp(str, "sx761"))
+ board = SX761;
+ else if (!strcmp(str, "sx762"))
+ board = SX762;
+ else if (!strcmp(str, "sx763"))
+ board = SX763;
+ else
+ board = UNKNOWN;
+ return 0;
+}
+__setup("board=", setup_board);
+
+static struct mtd_partition gigasx76x_partitions[] =
+{
+ {
+ .name = "uboot",
+ .offset = 0x0,
+ .size = 0x10000,
+ },
+ {
+ .name = "uboot_env",
+ .offset = 0x10000,
+ .size = 0x10000,
+ },
+ {
+ .name = "linux",
+ .offset = 0x20000,
+ .size = 0x7e0000,
+ },
+};
+
+static struct gpio_led
+gigasx76x_gpio_leds[] __initdata = {
+ { .name = "soc:green:voip", .gpio = 216, },
+ { .name = "soc:green:adsl", .gpio = 217, },
+ { .name = "soc:green:usb", .gpio = 218, },
+ { .name = "soc:green:wifi", .gpio = 219, },
+ { .name = "soc:green:phone2", .gpio = 220, },
+ { .name = "soc:green:phone1", .gpio = 221, },
+ { .name = "soc:green:line", .gpio = 222, },
+ { .name = "soc:green:online", .gpio = 223, },
+};
+
+static struct gpio_keys_button
+gigasx76x_gpio_keys[] __initdata = {
+ {
+ .desc = "wps",
+ .type = EV_KEY,
+ .code = KEY_WPS_BUTTON,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 22,
+ .active_low = 1,
+ },
+ {
+ .desc = "reset",
+ .type = EV_KEY,
+ .code = BTN_0,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 14,
+ .active_low = 0,
+ },
+};
+
+static struct physmap_flash_data gigasx76x_flash_data = {
+ .nr_parts = ARRAY_SIZE(gigasx76x_partitions),
+ .parts = gigasx76x_partitions,
+};
+
+static struct ltq_pci_data ltq_pci_data = {
+ .clock = PCI_CLOCK_INT,
+ .gpio = PCI_GNT1 | PCI_REQ1,
+ .irq = { [14] = INT_NUM_IM0_IRL0 + 22, },
+};
+
+static struct ltq_eth_data ltq_eth_data = {
+ .mii_mode = PHY_INTERFACE_MODE_MII,
+};
+
+static void __init gigasx76x_init(void)
+{
+#define GIGASX76X_USB 29
+
+ ltq_register_gpio_stp();
+ ltq_register_nor(&gigasx76x_flash_data);
+ ltq_register_pci(&ltq_pci_data);
+ ltq_register_tapi();
+ ltq_add_device_gpio_leds(-1, ARRAY_SIZE(gigasx76x_gpio_leds), gigasx76x_gpio_leds);
+ ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, ARRAY_SIZE(gigasx76x_gpio_keys), gigasx76x_gpio_keys);
+ xway_register_dwc(GIGASX76X_USB);
+
+ if (!is_valid_ether_addr(ltq_ethaddr))
+ random_ether_addr(ltq_ethaddr);
+
+ memcpy(&ltq_eth_data.mac.sa_data, ltq_ethaddr, 6);
+ ltq_register_etop(&ltq_eth_data);
+ if (board == SX762)
+ ltq_register_ath5k(sx762_eeprom_data, ltq_ethaddr);
+ else
+ ltq_register_ath5k(sx763_eeprom_data, ltq_ethaddr);
+}
+
+MIPS_MACHINE(LANTIQ_MACH_GIGASX76X,
+ "GIGASX76X",
+ "GIGASX76X - Gigaset SX761,SX762,SX763",
+ gigasx76x_init);
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-gigasx76x.h b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-gigasx76x.h
index 186a146..c25a679 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-gigasx76x.h
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-gigasx76x.h
@@ -8,9 +8,12 @@
*
*/
+#ifndef _MACH_GIGASX76X_H__
+#define _MACH_GIGASX76X_H__
+
static u16 sx763_eeprom_data[ATH5K_PLAT_EEP_MAX_WORDS]=
{
-0x5aa5,0x168c,0x0200,0x0001,0x0000,0x5001,0x0000,0x2051,0x2051,0x1c0a,0x0100,
+0x0013,0x168c,0x0200,0x0001,0x0000,0x5001,0x0000,0x2051,0x2051,0x1c0a,0x0100,
0x0000,0x01c2,0x0002,0xc606,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xf165,0x7fbe,0x0003,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -108,7 +111,7 @@ static u16 sx763_eeprom_data[ATH5K_PLAT_EEP_MAX_WORDS]=
static u16 sx762_eeprom_data[ATH5K_PLAT_EEP_MAX_WORDS]=
{
-0x5aa5,0x168c,0x0200,0x0001,0x0000,0x5001,0x0000,0x2051,0x2051,0x1c0a,0x0100,
+0x001a,0x168c,0x0200,0x0001,0x0000,0x5001,0x0000,0x2051,0x2051,0x1c0a,0x0100,
0x0000,0x01c2,0x0002,0xc606,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xf165,0x7fbe,0x0003,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
@@ -201,3 +204,5 @@ static u16 sx762_eeprom_data[ATH5K_PLAT_EEP_MAX_WORDS]=
0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,
0xffff,0xffff};
+
+#endif
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-netgear.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-netgear.c
index 826bfe2..ed9098e 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-netgear.c
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-netgear.c
@@ -14,6 +14,7 @@
#include <linux/input.h>
#include <linux/phy.h>
#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
#include <lantiq_soc.h>
#include <irq.h>
@@ -33,11 +34,38 @@ static struct ltq_eth_data ltq_eth_data = {
.mii_mode = PHY_INTERFACE_MODE_MII,
};
-struct spi_board_info spi_info = {
- .bus_num = 0,
- .chip_select = 3,
- .max_speed_hz = 25000000,
- .modalias = "mx25l12805d",
+static struct mtd_partition easy98000_nor_partitions[] =
+{
+ {
+ .name = "uboot",
+ .offset = 0x0,
+ .size = 0x40000,
+ },
+ {
+ .name = "uboot_env",
+ .offset = 0x40000,
+ .size = 0x40000, /* 2 sectors for redundant env. */
+ },
+ {
+ .name = "linux",
+ .offset = 0x80000,
+ .size = 0xF80000, /* map only 16 MiB */
+ },
+};
+
+static struct flash_platform_data easy98000_spi_flash_platform_data = {
+ .name = "sflash",
+ .parts = easy98000_nor_partitions,
+ .nr_parts = ARRAY_SIZE(easy98000_nor_partitions)
+};
+
+static struct spi_board_info spi_info __initdata = {
+ .modalias = "m25p80",
+ .bus_num = 0,
+ .chip_select = 3,
+ .max_speed_hz = 10 * 1000 * 1000,
+ .mode = SPI_MODE_3,
+ .platform_data = &easy98000_spi_flash_platform_data
};
struct ltq_spi_platform_data ltq_spi_data = {
diff --git a/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-p2601hnf1.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-p2601hnf1.c
new file mode 100644
index 0000000..98c1181
--- /dev/null
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-p2601hnf1.c
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/gpio_buttons.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+#include <linux/etherdevice.h>
+#include <linux/mdio-gpio.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+
+#include <lantiq_soc.h>
+#include <lantiq_platform.h>
+
+#include "../machtypes.h"
+#include "devices.h"
+#include "../dev-gpio-leds.h"
+#include "dev-dwc_otg.h"
+
+
+static struct mtd_partition p2601hnf1_partitions[] __initdata =
+{
+ {
+ .name = "uboot",
+ .offset = 0x0,
+ .size = 0x20000,
+ },
+/* {
+ .name = "uboot_env",
+ .offset = 0x20000,
+ .size = 0x20000,
+ },
+*/ {
+ .name = "linux",
+ .offset = 0x020000,
+ .size = 0xfc0000,
+ },
+ {
+ .name = "board_config",
+ .offset = 0xfe0000,
+ .size = 0x20000,
+ },
+};
+
+static struct physmap_flash_data p2601hnf1_flash_data __initdata = {
+ .nr_parts = ARRAY_SIZE(p2601hnf1_partitions),
+ .parts = p2601hnf1_partitions,
+};
+
+static struct gpio_led p2601hnf1_leds_gpio[] __initdata = {
+ { .name = "soc:red:power", .gpio = 29, .active_low = 1, .default_trigger = "default-off" },
+ { .name = "soc:yellow:phone", .gpio = 64, .active_low = 1, .default_trigger = "default-off" },
+ { .name = "soc:green:phone", .gpio = 65, .active_low = 1, .default_trigger = "default-off" },
+ { .name = "soc:yellow:wlan", .gpio = 66, .active_low = 1, .default_trigger = "default-off" },
+ { .name = "soc:green:power", .gpio = 67, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:red:internet", .gpio = 68, .active_low = 1, .default_trigger = "default-off" },
+ { .name = "soc:green:internet", .gpio = 69, .active_low = 1, .default_trigger = "default-off" },
+ { .name = "soc:green:dsl", .gpio = 70, .active_low = 1, .default_trigger = "default-off" },
+ { .name = "soc:green:wlan", .gpio = 71, .active_low = 1, .default_trigger = "default-off" },
+};
+
+static struct gpio_button
+p2601hnf1_gpio_buttons[] /*__initdata*/ = {
+ { .desc = "reset", .type = EV_KEY, .code = BTN_0, .threshold = 3, .gpio = 53, .active_low = 1, },
+ { .desc = "wlan", .type = EV_KEY, .code = BTN_1, .threshold = 1, .gpio = 54, .active_low = 1, },
+};
+
+static struct ltq_eth_data ltq_eth_data = {
+ .mii_mode = PHY_INTERFACE_MODE_RMII,
+};
+
+static void __init
+p2601hnf1_init(void)
+{
+
+#define P2601HNF1_USB 9
+
+ ltq_register_gpio_stp();
+ ltq_add_device_gpio_leds(-1, ARRAY_SIZE(p2601hnf1_leds_gpio), p2601hnf1_leds_gpio);
+ ltq_register_gpio_buttons(p2601hnf1_gpio_buttons, ARRAY_SIZE(p2601hnf1_gpio_buttons));
+ ltq_register_nor(&p2601hnf1_flash_data);
+ ltq_register_etop(&ltq_eth_data);
+ xway_register_dwc(P2601HNF1_USB);
+
+ // enable the ethernet ports on the SoC
+// ltq_w32((ltq_r32(LTQ_GPORT_P0_CTL) & ~(1 << 17)) | (1 << 18), LTQ_GPORT_P0_CTL);
+// ltq_w32((ltq_r32(LTQ_GPORT_P1_CTL) & ~(1 << 17)) | (1 << 18), LTQ_GPORT_P1_CTL);
+// ltq_w32((ltq_r32(LTQ_GPORT_P2_CTL) & ~(1 << 17)) | (1 << 18), LTQ_GPORT_P2_CTL);
+}
+
+MIPS_MACHINE(LANTIQ_MACH_P2601HNF1,
+ "P2601HNF1",
+ "ZyXEL P-2601HN-F1",
+ p2601hnf1_init);
+
diff --git a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-wbmr.c b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-wbmr.c
index b11c263..b11c263 100644
--- a/target/linux/lantiq/files-3.1/arch/mips/lantiq/xway/mach-wbmr.c
+++ b/target/linux/lantiq/files-3.2/arch/mips/lantiq/xway/mach-wbmr.c
diff --git a/target/linux/lantiq/image/Makefile b/target/linux/lantiq/image/Makefile
index 9ccf45d..5f19d2b 100644
--- a/target/linux/lantiq/image/Makefile
+++ b/target/linux/lantiq/image/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2010 OpenWrt.org
+# Copyright (C) 2010-2012 OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
@@ -12,6 +12,7 @@ JFFS2_BLOCKSIZE = 64k 128k 256k
ase_cmdline=-console=ttyLTQ0,115200 rootfstype=squashfs,jffs2
xway_cmdline=-console=ttyLTQ1,115200 rootfstype=squashfs,jffs2
falcon_cmdline=-console=ttyLTQ0,115200 rootfstype=squashfs,jffs2
+sx76x_cmdline=console=ttyLTQ1,115200 rootfstype=squashfs,jffs2
define CompressLzma
$(STAGING_DIR_HOST)/bin/lzma e $(1) $(2)
@@ -35,12 +36,23 @@ define MkImageLzma
-d $(KDIR)/vmlinux-$(1).lzma $(KDIR)/uImage-$(1)
endef
+define MkImageEVA
+ lzma2eva 0x80002000 0x80002000 $(KDIR)/vmlinux-$(1).lzma $(KDIR)/$(1).eva.prealign
+ dd if=$(KDIR)/$(1).eva.prealign of=$(KDIR)/$(1).eva bs=64k conv=sync
+ cat ./eva.dummy.squashfs >> $(KDIR)/$(1).eva
+endef
+
define Image/Build/squashfs
cat $(KDIR)/uImage-$(2) $(KDIR)/root.$(1) > $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1).image
$(call prepare_generic_squashfs,$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1).image)
$(if $(3),$(call MkBrnImage,$(3),$(4),$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(3)-brnImage,$(2),$(1),$(5)))
endef
+define Image/BuildEVA/squashfs
+ cat $(KDIR)/$(2).eva $(KDIR)/root.$(1) > $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1).image.eva
+ $(call prepare_generic_squashfs,$(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1).image.eva)
+endef
+
define Image/Build/jffs2-64k
dd if=$(KDIR)/uImage-$(2) of=$(KDIR)/uImage-$(2)-$(1) bs=64k conv=sync
cat $(KDIR)/uImage-$(2)-$(1) $(KDIR)/root.$(1) > $(BIN_DIR)/$(IMG_PREFIX)-$(2)-$(1).image
@@ -62,6 +74,12 @@ define Image/BuildKernel/Template
$(CP) $(KDIR)/uImage-$(1) $(BIN_DIR)/$(IMG_PREFIX)-$(1)-uImage
endef
+define Image/BuildKernelEVA/Template
+ $(call PatchKernelLzma,$(1),$(if $(2),$(2) machtype=$(1),))
+ $(call MkImageEVA,$(1))
+ $(CP) $(KDIR)/$(1).eva $(BIN_DIR)/$(IMG_PREFIX)-$(1).eva
+endef
+
ifeq ($(CONFIG_TARGET_lantiq_danube),y)
define Image/BuildKernel/Profile/EASY50712
$(call Image/BuildKernel/Template,EASY50712,$(xway_cmdline))
@@ -103,6 +121,14 @@ define Image/Build/Profile/ARV4518PW
$(call Image/Build/$(1),$(1),ARV4518PW)
endef
+define Image/BuildKernel/Profile/ARV4519PW
+ $(call Image/BuildKernel/Template,ARV4519PW,$(xway_cmdline))
+endef
+
+define Image/Build/Profile/ARV4519PW
+ $(call Image/Build/$(1),$(1),ARV4519PW,BRNDA4519,0x12345678,memsize=32)
+endef
+
define Image/BuildKernel/Profile/ARV4520PW
$(call Image/BuildKernel/Template,ARV4520PW,$(xway_cmdline))
endef
@@ -140,7 +166,7 @@ define Image/BuildKernel/Profile/ARV7518PW
endef
define Image/Build/Profile/ARV7518PW
- $(call Image/Build/$(1),$(1),ARV7518PW)
+ $(call Image/Build/$(1),$(1),ARV7518PW,BRNDA7519,0x12345678,memsize=64)
endef
define Image/BuildKernel/Profile/ARV752DPW
@@ -160,13 +186,29 @@ define Image/Build/Profile/ARV752DPW22
endef
define Image/BuildKernel/Profile/GIGASX76X
- $(call Image/BuildKernel/Template,GIGASX76X,$(xway_cmdline))
+ $(call Image/BuildKernel/Template,GIGASX76X,$(sx76x_cmdline))
endef
define Image/Build/Profile/GIGASX76X
$(call Image/Build/$(1),$(1),GIGASX76X)
endef
+define Image/BuildKernel/Profile/BTHOMEHUBV2B
+ $(call Image/BuildKernel/Template,BTHOMEHUBV2B,$(xway_cmdline))
+endef
+
+define Image/Build/Profile/BTHOMEHUBV2B
+ $(call Image/Build/$(1),$(1),BTHOMEHUBV2B)
+endef
+
+define Image/BuildKernel/Profile/BTHOMEHUBV2BOPENRG
+ $(call Image/BuildKernel/Template,BTHOMEHUBV2BOPENRG,$(xway_cmdline))
+endef
+
+define Image/Build/Profile/BTHOMEHUBV2BOPENRG
+ $(call Image/Build/$(1),$(1),BTHOMEHUBV2BOPENRG)
+endef
+
define Image/BuildKernel/Profile/Generic
$(call Image/BuildKernel/Template,EASY4010,$(xway_cmdline))
$(call Image/BuildKernel/Template,EASY50712,$(xway_cmdline))
@@ -174,6 +216,7 @@ define Image/BuildKernel/Profile/Generic
$(call Image/BuildKernel/Template,ARV3527P,$(xway_cmdline))
$(call Image/BuildKernel/Template,ARV4510PW,$(xway_cmdline))
$(call Image/BuildKernel/Template,ARV4518PW,$(xway_cmdline))
+ $(call Image/BuildKernel/Template,ARV4519PW,$(xway_cmdline))
$(call Image/BuildKernel/Template,ARV4520PW,$(xway_cmdline))
$(call Image/BuildKernel/Template,ARV452CPW,$(xway_cmdline))
$(call Image/BuildKernel/Template,ARV4525PW,$(xway_cmdline))
@@ -182,6 +225,8 @@ define Image/BuildKernel/Profile/Generic
$(call Image/BuildKernel/Template,ARV752DPW,$(xway_cmdline))
$(call Image/BuildKernel/Template,ARV752DPW22,$(xway_cmdline))
$(call Image/BuildKernel/Template,GIGASX76X,$(xway_cmdline))
+ $(call Image/BuildKernel/Template,BTHOMEHUBV2B,$(xway_cmdline))
+ $(call Image/BuildKernel/Template,BTHOMEHUBV2BOPENRG,$(xway_cmdline))
$(call Image/BuildKernel/Template,NONE)
endef
@@ -192,14 +237,17 @@ define Image/Build/Profile/Generic
$(call Image/Build/$(1),$(1),ARV3527P)
$(call Image/Build/$(1),$(1),ARV4510PW)
$(call Image/Build/$(1),$(1),ARV4518PW)
+ $(call Image/Build/$(1),$(1),ARV4519PW,BRNDA4519,0x12345678,memsize=32)
$(call Image/Build/$(1),$(1),ARV4520PW)
$(call Image/Build/$(1),$(1),ARV452CPW)
- $(call Image/Build/$(1),$(1),ARV4525PW)
+ $(call Image/Build/$(1),$(1),ARV4525PW,BRNDTW502,0x12345678,memsize=32)
$(call Image/Build/$(1),$(1),ARV7525PW)
- $(call Image/Build/$(1),$(1),ARV7518PW)
+ $(call Image/Build/$(1),$(1),ARV7518PW,BRNDA7519,0x12345678,memsize=32)
$(call Image/Build/$(1),$(1),ARV752DPW)
$(call Image/Build/$(1),$(1),ARV752DPW22)
$(call Image/Build/$(1),$(1),GIGASX76X)
+ $(call Image/Build/$(1),$(1),BTHOMEHUBV2B)
+ $(call Image/Build/$(1),$(1),BTHOMEHUBV2BOPENRG)
$(call Image/Build/$(1),$(1),NONE)
$(CP) $(KDIR)/root.$(1) $(BIN_DIR)/$(IMG_PREFIX)-$(1).rootfs
endef
@@ -222,15 +270,25 @@ define Image/Build/Profile/DGN3500B
$(call Image/Build/$(1),$(1),DGN3500B)
endef
+define Image/BuildKernel/Profile/FRITZ7320
+ $(call Image/BuildKernelEVA/Template,FRITZ7320,$(xway_cmdline))
+endef
+
+define Image/Build/Profile/FRITZ7320
+ $(call Image/BuildEVA/$(1),$(1),FRITZ7320)
+endef
+
define Image/BuildKernel/Profile/Generic
$(call Image/BuildKernel/Template,WBMR,$(xway_cmdline))
$(call Image/BuildKernel/Template,DGN3500B,$(xway_cmdline))
+ $(call Image/BuildKernelEVA/Template,FRITZ7320,$(xway_cmdline))
$(call Image/BuildKernel/Template,NONE)
endef
define Image/Build/Profile/Generic
$(call Image/Build/$(1),$(1),WBMR)
$(call Image/Build/$(1),$(1),DGN3500B)
+ $(call Image/BuildEVA/$(1),$(1),FRITZ7320)
$(call Image/Build/$(1),$(1),NONE)
$(CP) $(KDIR)/root.$(1) $(BIN_DIR)/$(IMG_PREFIX)-$(1).rootfs
endef
@@ -288,6 +346,28 @@ define Image/Build/Profile/Generic
endef
endif
+ifeq ($(CONFIG_TARGET_lantiq_vr9),y)
+define Image/BuildKernel/Profile/FRITZ3370
+ $(call Image/BuildKernel/Template,FRITZ3370,$(xway_cmdline))
+ $(call Image/BuildKernelEVA/Template,FRITZ3370,$(xway_cmdline))
+endef
+
+define Image/Build/Profile/FRITZ3370
+ $(call Image/Build/$(1),$(1),FRITZ3370)
+endef
+
+define Image/BuildKernel/Profile/Generic
+ $(call Image/BuildKernel/Template,FRITZ3370,$(xway_cmdline))
+ $(call Image/BuildKernel/Template,NONE)
+endef
+
+define Image/Build/Profile/Generic
+ $(call Image/Build/$(1),$(1),FRITZ3370)
+ $(call Image/Build/$(1),$(1),NONE)
+ $(CP) $(KDIR)/root.$(1) $(BIN_DIR)/$(IMG_PREFIX)-$(1).rootfs
+endef
+endif
+
define Image/BuildKernel
$(call Image/BuildKernel/Profile/$(PROFILE))
endef
diff --git a/target/linux/lantiq/image/eva.dummy.squashfs b/target/linux/lantiq/image/eva.dummy.squashfs
new file mode 100644
index 0000000..71c688c
--- /dev/null
+++ b/target/linux/lantiq/image/eva.dummy.squashfs
Binary files differ
diff --git a/target/linux/lantiq/modules.mk b/target/linux/lantiq/modules.mk
index 0eccec5..0868e6a 100644
--- a/target/linux/lantiq/modules.mk
+++ b/target/linux/lantiq/modules.mk
@@ -29,7 +29,7 @@ USB_MENU:=USB Support
define KernelPackage/usb-dwc-otg
TITLE:=Synopsis DWC_OTG support
SUBMENU:=$(USB_MENU)
- DEPENDS+=@(TARGET_lantiq_danube||TARGET_lantiq_ar9||TARGET_lantiq_vr9) +kmod-usb-core
+ DEPENDS+=@(TARGET_lantiq_danube||TARGET_lantiq_ar9) +kmod-usb-core
KCONFIG:=CONFIG_DWC_OTG \
CONFIG_DWC_OTG_DEBUG=n \
CONFIG_DWC_OTG_LANTIQ=y \
@@ -45,6 +45,39 @@ endef
$(eval $(call KernelPackage,usb-dwc-otg))
+define KernelPackage/usb-ifxhcd
+ TITLE:=IFXHCD usb driver
+ SUBMENU:=$(USB_MENU)
+ DEPENDS+=@(TARGET_lantiq_vr9||TARGET_lantiq_ar9) +kmod-usb-core
+ifeq ($(CONFIG_TARGET_lantiq_ar9),)
+ KCONFIG:=CONFIG_USB_HOST_IFX \
+ CONFIG_USB_HOST_IFX_B=y \
+ CONFIG_IFX_VR9=y \
+ CONFIG_IFX_AR9=n \
+ CONFIG_USB_HOST_IFX_FORCE_USB11=n \
+ CONFIG_USB_HOST_IFX_WITH_HS_ELECT_TST=n \
+ CONFIG_USB_HOST_IFX_WITH_ISO=n \
+ CONFIG_USB_HOST_IFX_UNALIGNED_ADJ=y
+else
+ KCONFIG:=CONFIG_USB_HOST_IFX \
+ CONFIG_USB_HOST_IFX_B=y \
+ CONFIG_IFX_AR9=y \
+ CONFIG_IFX_VR9=n \
+ CONFIG_USB_HOST_IFX_FORCE_USB11=n \
+ CONFIG_USB_HOST_IFX_WITH_HS_ELECT_TST=n \
+ CONFIG_USB_HOST_IFX_WITH_ISO=n \
+ CONFIG_USB_HOST_IFX_UNALIGNED_ADJ=y
+endif
+ FILES:=$(LINUX_DIR)/drivers/usb/ifxhcd/ifxusb_host.ko
+ AUTOLOAD:=$(call AutoLoad,50,ifxusb_host)
+endef
+
+define KernelPackage/usb-ifxhcd/description
+ Kernel support for Synopsis USB on XWAY
+endef
+
+$(eval $(call KernelPackage,usb-ifxhcd))
+
I2C_FALCON_MODULES:= \
CONFIG_I2C_FALCON:drivers/i2c/busses/i2c-falcon
diff --git a/target/linux/lantiq/patches-3.2/0001-GPIO-add-bindings-for-managed-devices.patch b/target/linux/lantiq/patches-3.2/0001-GPIO-add-bindings-for-managed-devices.patch
new file mode 100644
index 0000000..316d040
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0001-GPIO-add-bindings-for-managed-devices.patch
@@ -0,0 +1,144 @@
+From 282f1ca84b35f3be68abc4fd8b52e229f3cb6bb7 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Mar 2012 13:23:53 +0100
+Subject: [PATCH 01/70] GPIO: add bindings for managed devices
+
+This patch adds 2 functions that allow managed devices to request GPIOs.
+These GPIOs will then be managed by drivers/base/devres.c.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
+---
+ drivers/gpio/Makefile | 2 +-
+ drivers/gpio/devres.c | 90 ++++++++++++++++++++++++++++++++++++++++++++
+ include/asm-generic/gpio.h | 4 ++
+ 3 files changed, 95 insertions(+), 1 deletions(-)
+ create mode 100644 drivers/gpio/devres.c
+
+diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
+index 4e018d6..76dbd3f 100644
+--- a/drivers/gpio/Makefile
++++ b/drivers/gpio/Makefile
+@@ -2,7 +2,7 @@
+
+ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
+
+-obj-$(CONFIG_GPIOLIB) += gpiolib.o
++obj-$(CONFIG_GPIOLIB) += gpiolib.o devres.o
+
+ # Device drivers. Generally keep list sorted alphabetically
+ obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
+diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c
+new file mode 100644
+index 0000000..3dd2939
+--- /dev/null
++++ b/drivers/gpio/devres.c
+@@ -0,0 +1,90 @@
++/*
++ * drivers/gpio/devres.c - managed gpio resources
++ *
++ * 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.
++ *
++ * 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
++ *
++ * This file is based on kernel/irq/devres.c
++ *
++ * Copyright (c) 2011 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/module.h>
++#include <linux/gpio.h>
++#include <linux/device.h>
++#include <linux/gfp.h>
++
++static void devm_gpio_release(struct device *dev, void *res)
++{
++ unsigned *gpio = res;
++
++ gpio_free(*gpio);
++}
++
++static int devm_gpio_match(struct device *dev, void *res, void *data)
++{
++ unsigned *this = res, *gpio = data;
++
++ return *this == *gpio;
++}
++
++/**
++ * devm_gpio_request - request a gpio for a managed device
++ * @dev: device to request the gpio for
++ * @gpio: gpio to allocate
++ * @label: the name of the requested gpio
++ *
++ * Except for the extra @dev argument, this function takes the
++ * same arguments and performs the same function as
++ * gpio_request(). GPIOs requested with this function will be
++ * automatically freed on driver detach.
++ *
++ * If an GPIO allocated with this function needs to be freed
++ * separately, devm_gpio_free() must be used.
++ */
++
++int devm_gpio_request(struct device *dev, unsigned gpio, const char *label)
++{
++ unsigned *dr;
++ int rc;
++
++ dr = devres_alloc(devm_gpio_release, sizeof(unsigned), GFP_KERNEL);
++ if (!dr)
++ return -ENOMEM;
++
++ rc = gpio_request(gpio, label);
++ if (rc) {
++ devres_free(dr);
++ return rc;
++ }
++
++ *dr = gpio;
++ devres_add(dev, dr);
++
++ return 0;
++}
++EXPORT_SYMBOL(devm_gpio_request);
++
++/**
++ * devm_gpio_free - free an interrupt
++ * @dev: device to free gpio for
++ * @gpio: gpio to free
++ *
++ * Except for the extra @dev argument, this function takes the
++ * same arguments and performs the same function as gpio_free().
++ * This function instead of gpio_free() should be used to manually
++ * free GPIOs allocated with devm_gpio_request().
++ */
++void devm_gpio_free(struct device *dev, unsigned int gpio)
++{
++
++ WARN_ON(devres_destroy(dev, devm_gpio_release, devm_gpio_match,
++ &gpio));
++ gpio_free(gpio);
++}
++EXPORT_SYMBOL(devm_gpio_free);
+diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
+index 8c86210..8601a02 100644
+--- a/include/asm-generic/gpio.h
++++ b/include/asm-generic/gpio.h
+@@ -175,6 +175,10 @@ extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *labe
+ extern int gpio_request_array(const struct gpio *array, size_t num);
+ extern void gpio_free_array(const struct gpio *array, size_t num);
+
++/* bindings for managed devices that want to request gpios */
++int devm_gpio_request(struct device *dev, unsigned gpio, const char *label);
++void devm_gpio_free(struct device *dev, unsigned int gpio);
++
+ #ifdef CONFIG_GPIO_SYSFS
+
+ /*
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0002-MIPS-remove-unused-prototype-kgdb_config.patch b/target/linux/lantiq/patches-3.2/0002-MIPS-remove-unused-prototype-kgdb_config.patch
new file mode 100644
index 0000000..d3b3c0d
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0002-MIPS-remove-unused-prototype-kgdb_config.patch
@@ -0,0 +1,25 @@
+From b859096bdc4b029357217af98874d6feec3ff4bd Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 16 Mar 2012 16:27:35 +0100
+Subject: [PATCH 02/70] MIPS: remove unused prototype kgdb_config
+
+---
+ arch/mips/include/asm/mips-boards/generic.h | 4 ----
+ 1 files changed, 0 insertions(+), 4 deletions(-)
+
+diff --git a/arch/mips/include/asm/mips-boards/generic.h b/arch/mips/include/asm/mips-boards/generic.h
+index 46c0856..6e23ceb 100644
+--- a/arch/mips/include/asm/mips-boards/generic.h
++++ b/arch/mips/include/asm/mips-boards/generic.h
+@@ -93,8 +93,4 @@ extern void mips_pcibios_init(void);
+ #define mips_pcibios_init() do { } while (0)
+ #endif
+
+-#ifdef CONFIG_KGDB
+-extern void kgdb_config(void);
+-#endif
+-
+ #endif /* __ASM_MIPS_BOARDS_GENERIC_H */
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0003-MTD-MIPS-lantiq-reintroduce-support-for-cmdline-part.patch b/target/linux/lantiq/patches-3.2/0003-MTD-MIPS-lantiq-reintroduce-support-for-cmdline-part.patch
new file mode 100644
index 0000000..64b2101
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0003-MTD-MIPS-lantiq-reintroduce-support-for-cmdline-part.patch
@@ -0,0 +1,39 @@
+From 63e9d017ce90dc1cd0822bace72e4e391feafdab Mon Sep 17 00:00:00 2001
+From: Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
+Date: Fri, 17 Feb 2012 22:32:18 +0100
+Subject: [PATCH 03/70] MTD: MIPS: lantiq: reintroduce support for cmdline
+ partitions
+
+Since commit ca97dec2ab5c87e9fbdf7e882e1820004a3966fa the
+command line parsing of MTD partitions does not work anymore.
+
+Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ drivers/mtd/maps/lantiq-flash.c | 3 ++-
+ 1 files changed, 2 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
+index 4f10e27..764d468 100644
+--- a/drivers/mtd/maps/lantiq-flash.c
++++ b/drivers/mtd/maps/lantiq-flash.c
+@@ -45,6 +45,7 @@ struct ltq_mtd {
+ };
+
+ static char ltq_map_name[] = "ltq_nor";
++static const char *ltq_probe_types[] __devinitconst = { "cmdlinepart", NULL };
+
+ static map_word
+ ltq_read16(struct map_info *map, unsigned long adr)
+@@ -168,7 +169,7 @@ ltq_mtd_probe(struct platform_device *pdev)
+ cfi->addr_unlock1 ^= 1;
+ cfi->addr_unlock2 ^= 1;
+
+- err = mtd_device_parse_register(ltq_mtd->mtd, NULL, 0,
++ err = mtd_device_parse_register(ltq_mtd->mtd, ltq_probe_types, 0,
+ ltq_mtd_data->parts, ltq_mtd_data->nr_parts);
+ if (err) {
+ dev_err(&pdev->dev, "failed to add partitions\n");
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0004-MTD-add-m25p80-id-for-mx25l2005a.patch b/target/linux/lantiq/patches-3.2/0004-MTD-add-m25p80-id-for-mx25l2005a.patch
new file mode 100644
index 0000000..75adef3
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0004-MTD-add-m25p80-id-for-mx25l2005a.patch
@@ -0,0 +1,24 @@
+From e4e27fbcaf2caa2a3e3ef45c736b4bb14f91ecfe Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 13 Mar 2012 18:03:33 +0100
+Subject: [PATCH 04/70] MTD: add m25p80 id for mx25l2005a
+
+---
+ drivers/mtd/devices/m25p80.c | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
+index 884904d..3f37f5f 100644
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -676,6 +676,7 @@ static const struct spi_device_id m25p_ids[] = {
+ { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) },
+
+ /* Macronix */
++ { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 8, SECT_4K) },
+ { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) },
+ { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) },
+ { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) },
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0004-MIPS-lantiq-reorganize-xway-code.patch b/target/linux/lantiq/patches-3.2/0005-MIPS-lantiq-reorganize-xway-code.patch
index 982b69d..2ab9522 100644
--- a/target/linux/lantiq/patches/0004-MIPS-lantiq-reorganize-xway-code.patch
+++ b/target/linux/lantiq/patches-3.2/0005-MIPS-lantiq-reorganize-xway-code.patch
@@ -1,7 +1,7 @@
-From d90739a8962b541969b4c5f7ef1df8fec9c7f153 Mon Sep 17 00:00:00 2001
+From cf7086d4c2f7caeccd019c0a57bf1566c72c13ee Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 10 Aug 2011 14:57:04 +0200
-Subject: [PATCH 04/24] MIPS: lantiq: reorganize xway code
+Subject: [PATCH 05/70] MIPS: lantiq: reorganize xway code
Inside the folder arch/mips/lantiq/xway, there were alot of small files with
lots of duplicated code. This patch adds a wrapper function for inserting and
@@ -11,35 +11,35 @@ This patch makes the xway code consistent with the falcon support added later
in this series.
Signed-off-by: John Crispin <blogic@openwrt.org>
-Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
-Cc: linux-mips@linux-mips.org
---
arch/mips/include/asm/mach-lantiq/lantiq.h | 14 +---
.../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 14 ++++
arch/mips/lantiq/clk.c | 25 +------
arch/mips/lantiq/devices.c | 30 ++------
arch/mips/lantiq/devices.h | 4 +
- arch/mips/lantiq/prom.c | 50 +++++++++++--
+ arch/mips/lantiq/prom.c | 51 +++++++++++--
arch/mips/lantiq/prom.h | 4 +
arch/mips/lantiq/xway/Makefile | 6 +-
arch/mips/lantiq/xway/devices.c | 42 ++---------
- arch/mips/lantiq/xway/dma.c | 21 ++----
- arch/mips/lantiq/xway/ebu.c | 53 --------------
- arch/mips/lantiq/xway/pmu.c | 70 ------------------
- arch/mips/lantiq/xway/prom-ase.c | 9 +++
+ arch/mips/lantiq/xway/dma.c | 21 +----
+ arch/mips/lantiq/xway/ebu.c | 52 -------------
+ arch/mips/lantiq/xway/pmu.c | 69 -----------------
+ arch/mips/lantiq/xway/prom-ase.c | 9 ++
arch/mips/lantiq/xway/prom-xway.c | 10 +++
- arch/mips/lantiq/xway/reset.c | 21 ++----
+ arch/mips/lantiq/xway/reset.c | 21 +----
arch/mips/lantiq/xway/setup-ase.c | 19 -----
arch/mips/lantiq/xway/setup-xway.c | 20 -----
- arch/mips/lantiq/xway/sysctrl.c | 77 ++++++++++++++++++++
+ arch/mips/lantiq/xway/sysctrl.c | 78 ++++++++++++++++++++
drivers/watchdog/lantiq_wdt.c | 2 +-
- 19 files changed, 197 insertions(+), 294 deletions(-)
+ 19 files changed, 199 insertions(+), 292 deletions(-)
delete mode 100644 arch/mips/lantiq/xway/ebu.c
delete mode 100644 arch/mips/lantiq/xway/pmu.c
delete mode 100644 arch/mips/lantiq/xway/setup-ase.c
delete mode 100644 arch/mips/lantiq/xway/setup-xway.c
create mode 100644 arch/mips/lantiq/xway/sysctrl.c
+diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h
+index ce2f029..66d7300 100644
--- a/arch/mips/include/asm/mach-lantiq/lantiq.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
@@ -9,6 +9,7 @@
@@ -66,7 +66,7 @@ Cc: linux-mips@linux-mips.org
extern unsigned int ltq_get_cpu_ver(void);
extern unsigned int ltq_get_soc_type(void);
-@@ -51,7 +43,9 @@ extern void ltq_enable_irq(struct irq_da
+@@ -51,7 +43,9 @@ extern void ltq_enable_irq(struct irq_data *data);
/* find out what caused the last cpu reset */
extern int ltq_reset_cause(void);
@@ -77,9 +77,11 @@ Cc: linux-mips@linux-mips.org
#define IOPORT_RESOURCE_START 0x10000000
#define IOPORT_RESOURCE_END 0xffffffff
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index 8a3c6be..9b7ee366 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
-@@ -65,6 +65,8 @@
+@@ -61,6 +61,8 @@
#define LTQ_CGU_BASE_ADDR 0x1F103000
#define LTQ_CGU_SIZE 0x1000
@@ -88,7 +90,7 @@ Cc: linux-mips@linux-mips.org
/* ICU - interrupt control unit */
#define LTQ_ICU_BASE_ADDR 0x1F880200
#define LTQ_ICU_SIZE 0x100
-@@ -101,6 +103,8 @@
+@@ -97,6 +99,8 @@
#define LTQ_WDT_BASE_ADDR 0x1F8803F0
#define LTQ_WDT_SIZE 0x10
@@ -97,7 +99,7 @@ Cc: linux-mips@linux-mips.org
/* STP - serial to parallel conversion unit */
#define LTQ_STP_BASE_ADDR 0x1E100BB0
#define LTQ_STP_SIZE 0x40
-@@ -125,11 +129,21 @@
+@@ -121,11 +125,21 @@
#define LTQ_MPS_BASE_ADDR (KSEG1 + 0x1F107000)
#define LTQ_MPS_CHIPID ((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
@@ -119,6 +121,8 @@ Cc: linux-mips@linux-mips.org
static inline int ltq_is_ar9(void)
{
+diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
+index 77ed70f..39eef7f 100644
--- a/arch/mips/lantiq/clk.c
+++ b/arch/mips/lantiq/clk.c
@@ -22,6 +22,7 @@
@@ -152,12 +156,12 @@ Cc: linux-mips@linux-mips.org
- if (insert_resource(&iomem_resource, &ltq_cgu_resource) < 0)
- panic("Failed to insert cgu memory\n");
-+ ltq_soc_init();
-
+-
- if (request_mem_region(ltq_cgu_resource.start,
- resource_size(&ltq_cgu_resource), "cgu") < 0)
- panic("Failed to request cgu memory\n");
--
++ ltq_soc_init();
+
- ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start,
- resource_size(&ltq_cgu_resource));
- if (!ltq_cgu_membase) {
@@ -170,6 +174,8 @@ Cc: linux-mips@linux-mips.org
+ pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
clk_put(clk);
}
+diff --git a/arch/mips/lantiq/devices.c b/arch/mips/lantiq/devices.c
+index de1cb2b..7193d78 100644
--- a/arch/mips/lantiq/devices.c
+++ b/arch/mips/lantiq/devices.c
@@ -27,12 +27,8 @@
@@ -187,7 +193,7 @@ Cc: linux-mips@linux-mips.org
static struct platform_device ltq_nor = {
.name = "ltq_nor",
-@@ -47,12 +43,8 @@ void __init ltq_register_nor(struct phys
+@@ -47,12 +43,8 @@ void __init ltq_register_nor(struct physmap_flash_data *data)
}
/* watchdog */
@@ -229,6 +235,8 @@ Cc: linux-mips@linux-mips.org
IRQ_RES(tx, LTQ_ASC_TIR(1)),
IRQ_RES(rx, LTQ_ASC_RIR(1)),
IRQ_RES(err, LTQ_ASC_EIR(1)),
+diff --git a/arch/mips/lantiq/devices.h b/arch/mips/lantiq/devices.h
+index 2947bb1..a03c23f 100644
--- a/arch/mips/lantiq/devices.h
+++ b/arch/mips/lantiq/devices.h
@@ -14,6 +14,10 @@
@@ -242,6 +250,8 @@ Cc: linux-mips@linux-mips.org
extern void ltq_register_nor(struct physmap_flash_data *data);
extern void ltq_register_wdt(void);
+diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
+index e34fcfd..e3b1e25 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -16,6 +16,10 @@
@@ -255,7 +265,7 @@ Cc: linux-mips@linux-mips.org
static struct ltq_soc_info soc_info;
unsigned int ltq_get_cpu_ver(void)
-@@ -57,16 +61,50 @@ static void __init prom_init_cmdline(voi
+@@ -55,16 +59,51 @@ static void __init prom_init_cmdline(void)
}
}
@@ -265,23 +275,23 @@ Cc: linux-mips@linux-mips.org
- struct clk *clk;
+ __iomem void *ret = NULL;
+ struct resource *lookup = lookup_resource(&iomem_resource, res->start);
-
++
+ if (lookup && strcmp(lookup->name, res->name)) {
-+ panic("conflicting memory range %s\n", res->name);
++ pr_err("conflicting memory range %s\n", res->name);
+ return NULL;
+ }
+ if (!lookup) {
+ if (insert_resource(&iomem_resource, res) < 0) {
-+ panic("Failed to insert %s memory\n", res->name);
++ pr_err("Failed to insert %s memory\n", res->name);
+ return NULL;
+ }
+ }
+ if (request_mem_region(res->start,
+ resource_size(res), res->name) < 0) {
-+ panic("Failed to request %s memory\n", res->name);
++ pr_err("Failed to request %s memory\n", res->name);
+ goto err_res;
+ }
-+
+
+ ret = ioremap_nocache(res->start, resource_size(res));
+ if (!ret)
+ goto err_mem;
@@ -298,6 +308,7 @@ Cc: linux-mips@linux-mips.org
+ release_resource(res);
+ return NULL;
+}
++EXPORT_SYMBOL(ltq_remap_resource);
+
+void __init prom_init(void)
+{
@@ -312,6 +323,8 @@ Cc: linux-mips@linux-mips.org
soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
pr_info("SoC: %s\n", soc_info.sys_type);
prom_init_cmdline();
+diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h
+index b4229d9..51dba1b 100644
--- a/arch/mips/lantiq/prom.h
+++ b/arch/mips/lantiq/prom.h
@@ -9,17 +9,21 @@
@@ -336,6 +349,8 @@ Cc: linux-mips@linux-mips.org
extern void ltq_soc_setup(void);
#endif
+diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
+index c517f2e..6678402 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,7 +1,7 @@
@@ -349,6 +364,8 @@ Cc: linux-mips@linux-mips.org
obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
+diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
+index d614aa7..f97e565 100644
--- a/arch/mips/lantiq/xway/devices.c
+++ b/arch/mips/lantiq/xway/devices.c
@@ -31,22 +31,9 @@
@@ -421,9 +438,11 @@ Cc: linux-mips@linux-mips.org
static struct platform_device ltq_etop = {
.name = "ltq_etop",
+diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
+index cbb6ae5..60cd11f 100644
--- a/arch/mips/lantiq/xway/dma.c
+++ b/arch/mips/lantiq/xway/dma.c
-@@ -23,6 +23,8 @@
+@@ -24,6 +24,8 @@
#include <lantiq_soc.h>
#include <xway_dma.h>
@@ -432,7 +451,7 @@ Cc: linux-mips@linux-mips.org
#define LTQ_DMA_CTRL 0x10
#define LTQ_DMA_CPOLL 0x14
#define LTQ_DMA_CS 0x18
-@@ -54,12 +56,8 @@
+@@ -55,12 +57,8 @@
#define ltq_dma_w32_mask(x, y, z) ltq_w32_mask(x, y, \
ltq_dma_membase + (z))
@@ -447,7 +466,7 @@ Cc: linux-mips@linux-mips.org
static void __iomem *ltq_dma_membase;
-@@ -219,17 +217,8 @@ ltq_dma_init(void)
+@@ -220,17 +218,8 @@ ltq_dma_init(void)
{
int i;
@@ -466,6 +485,9 @@ Cc: linux-mips@linux-mips.org
if (!ltq_dma_membase)
panic("Failed to remap dma memory\n");
+diff --git a/arch/mips/lantiq/xway/ebu.c b/arch/mips/lantiq/xway/ebu.c
+deleted file mode 100644
+index 033b318..0000000
--- a/arch/mips/lantiq/xway/ebu.c
+++ /dev/null
@@ -1,52 +0,0 @@
@@ -521,6 +543,9 @@ Cc: linux-mips@linux-mips.org
-}
-
-postcore_initcall(lantiq_ebu_init);
+diff --git a/arch/mips/lantiq/xway/pmu.c b/arch/mips/lantiq/xway/pmu.c
+deleted file mode 100644
+index 39f0d26..0000000
--- a/arch/mips/lantiq/xway/pmu.c
+++ /dev/null
@@ -1,69 +0,0 @@
@@ -593,6 +618,8 @@ Cc: linux-mips@linux-mips.org
-}
-
-core_initcall(ltq_pmu_init);
+diff --git a/arch/mips/lantiq/xway/prom-ase.c b/arch/mips/lantiq/xway/prom-ase.c
+index ae4959a..3f86a3b 100644
--- a/arch/mips/lantiq/xway/prom-ase.c
+++ b/arch/mips/lantiq/xway/prom-ase.c
@@ -13,6 +13,7 @@
@@ -603,7 +630,7 @@ Cc: linux-mips@linux-mips.org
#include "../prom.h"
#define SOC_AMAZON_SE "Amazon_SE"
-@@ -26,6 +27,7 @@ void __init ltq_soc_detect(struct ltq_so
+@@ -26,6 +27,7 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
{
i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
@@ -611,7 +638,7 @@ Cc: linux-mips@linux-mips.org
switch (i->partnum) {
case SOC_ID_AMAZON_SE:
i->name = SOC_AMAZON_SE;
-@@ -37,3 +39,10 @@ void __init ltq_soc_detect(struct ltq_so
+@@ -37,3 +39,10 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
break;
}
}
@@ -622,6 +649,8 @@ Cc: linux-mips@linux-mips.org
+ ltq_register_gpio();
+ ltq_register_wdt();
+}
+diff --git a/arch/mips/lantiq/xway/prom-xway.c b/arch/mips/lantiq/xway/prom-xway.c
+index 2228133..d823a92 100644
--- a/arch/mips/lantiq/xway/prom-xway.c
+++ b/arch/mips/lantiq/xway/prom-xway.c
@@ -13,6 +13,7 @@
@@ -632,7 +661,7 @@ Cc: linux-mips@linux-mips.org
#include "../prom.h"
#define SOC_DANUBE "Danube"
-@@ -28,6 +29,7 @@ void __init ltq_soc_detect(struct ltq_so
+@@ -28,6 +29,7 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
{
i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
@@ -640,7 +669,7 @@ Cc: linux-mips@linux-mips.org
switch (i->partnum) {
case SOC_ID_DANUBE1:
case SOC_ID_DANUBE2:
-@@ -52,3 +54,11 @@ void __init ltq_soc_detect(struct ltq_so
+@@ -52,3 +54,11 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
break;
}
}
@@ -652,6 +681,8 @@ Cc: linux-mips@linux-mips.org
+ ltq_register_gpio();
+ ltq_register_wdt();
+}
+diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
+index 3d41f0b..ca2212a 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -15,6 +15,8 @@
@@ -697,6 +728,9 @@ Cc: linux-mips@linux-mips.org
if (!ltq_rcu_membase)
panic("Failed to remap rcu memory\n");
+diff --git a/arch/mips/lantiq/xway/setup-ase.c b/arch/mips/lantiq/xway/setup-ase.c
+deleted file mode 100644
+index f6f3267..0000000
--- a/arch/mips/lantiq/xway/setup-ase.c
+++ /dev/null
@@ -1,19 +0,0 @@
@@ -719,6 +753,9 @@ Cc: linux-mips@linux-mips.org
- ltq_register_gpio();
- ltq_register_wdt();
-}
+diff --git a/arch/mips/lantiq/xway/setup-xway.c b/arch/mips/lantiq/xway/setup-xway.c
+deleted file mode 100644
+index c292f64..0000000
--- a/arch/mips/lantiq/xway/setup-xway.c
+++ /dev/null
@@ -1,20 +0,0 @@
@@ -742,9 +779,12 @@ Cc: linux-mips@linux-mips.org
- ltq_register_gpio();
- ltq_register_wdt();
-}
+diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
+new file mode 100644
+index 0000000..8fd13a1
--- /dev/null
+++ b/arch/mips/lantiq/xway/sysctrl.c
-@@ -0,0 +1,77 @@
+@@ -0,0 +1,78 @@
+/*
+ * 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
@@ -754,6 +794,7 @@ Cc: linux-mips@linux-mips.org
+ */
+
+#include <linux/ioport.h>
++#include <linux/export.h>
+
+#include <lantiq_soc.h>
+
@@ -822,6 +863,8 @@ Cc: linux-mips@linux-mips.org
+ /* make sure to unprotect the memory region where flash is located */
+ ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
+}
+diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c
+index 102aed0..179bf98 100644
--- a/drivers/watchdog/lantiq_wdt.c
+++ b/drivers/watchdog/lantiq_wdt.c
@@ -16,7 +16,7 @@
@@ -833,3 +876,6 @@ Cc: linux-mips@linux-mips.org
/* Section 3.4 of the datasheet
* The password sequence protects the WDT control register from unintended
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0006-MIPS-lantiq-change-ltq_request_gpio-call-signature.patch b/target/linux/lantiq/patches-3.2/0006-MIPS-lantiq-change-ltq_request_gpio-call-signature.patch
new file mode 100644
index 0000000..4700bc9
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0006-MIPS-lantiq-change-ltq_request_gpio-call-signature.patch
@@ -0,0 +1,149 @@
+From 35f0a707698fc8f20e4164a704d7ac6af3342fb8 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 11 Nov 2011 12:45:24 +0100
+Subject: [PATCH 06/70] MIPS: lantiq: change ltq_request_gpio() call signature
+
+ltq_request_gpio() was using alt0/1 to multiplex the function of GPIO pins.
+This was XWAY specific. In order to also accomodate SoCs that require more bits
+we use a 32bit mask instead. This way the call signature is consistent between
+XWAY and FALC-ON.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
+---
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 4 +-
+ arch/mips/lantiq/xway/gpio.c | 8 ++--
+ arch/mips/lantiq/xway/gpio_stp.c | 6 ++--
+ arch/mips/pci/pci-lantiq.c | 36 +++++++++----------
+ 4 files changed, 26 insertions(+), 28 deletions(-)
+
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index 9b7ee366..87f6d24 100644
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -135,8 +135,8 @@ extern __iomem void *ltq_ebu_membase;
+ extern __iomem void *ltq_cgu_membase;
+
+ /* request a non-gpio and set the PIO config */
+-extern int ltq_gpio_request(unsigned int pin, unsigned int alt0,
+- unsigned int alt1, unsigned int dir, const char *name);
++extern int ltq_gpio_request(unsigned int pin, unsigned int mux,
++ unsigned int dir, const char *name);
+ extern void ltq_pmu_enable(unsigned int module);
+ extern void ltq_pmu_disable(unsigned int module);
+ extern void ltq_cgu_enable(unsigned int clk);
+diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c
+index d2fa98f..f204f6c 100644
+--- a/arch/mips/lantiq/xway/gpio.c
++++ b/arch/mips/lantiq/xway/gpio.c
+@@ -48,8 +48,8 @@ int irq_to_gpio(unsigned int gpio)
+ }
+ EXPORT_SYMBOL(irq_to_gpio);
+
+-int ltq_gpio_request(unsigned int pin, unsigned int alt0,
+- unsigned int alt1, unsigned int dir, const char *name)
++int ltq_gpio_request(unsigned int pin, unsigned int mux,
++ unsigned int dir, const char *name)
+ {
+ int id = 0;
+
+@@ -67,13 +67,13 @@ int ltq_gpio_request(unsigned int pin, unsigned int alt0,
+ pin -= PINS_PER_PORT;
+ id++;
+ }
+- if (alt0)
++ if (mux & 0x2)
+ ltq_gpio_setbit(ltq_gpio_port[id].membase,
+ LTQ_GPIO_ALTSEL0, pin);
+ else
+ ltq_gpio_clearbit(ltq_gpio_port[id].membase,
+ LTQ_GPIO_ALTSEL0, pin);
+- if (alt1)
++ if (mux & 0x1)
+ ltq_gpio_setbit(ltq_gpio_port[id].membase,
+ LTQ_GPIO_ALTSEL1, pin);
+ else
+diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
+index ff9991c..2c78660 100644
+--- a/arch/mips/lantiq/xway/gpio_stp.c
++++ b/arch/mips/lantiq/xway/gpio_stp.c
+@@ -79,9 +79,9 @@ static struct gpio_chip ltq_stp_chip = {
+ static int ltq_stp_hw_init(void)
+ {
+ /* the 3 pins used to control the external stp */
+- ltq_gpio_request(4, 1, 0, 1, "stp-st");
+- ltq_gpio_request(5, 1, 0, 1, "stp-d");
+- ltq_gpio_request(6, 1, 0, 1, "stp-sh");
++ ltq_gpio_request(4, 2, 1, "stp-st");
++ ltq_gpio_request(5, 2, 1, "stp-d");
++ ltq_gpio_request(6, 2, 1, "stp-sh");
+
+ /* sane defaults */
+ ltq_stp_w32(0, LTQ_STP_AR);
+diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c
+index be1e1af..c001c5a 100644
+--- a/arch/mips/pci/pci-lantiq.c
++++ b/arch/mips/pci/pci-lantiq.c
+@@ -70,28 +70,27 @@
+
+ struct ltq_pci_gpio_map {
+ int pin;
+- int alt0;
+- int alt1;
++ int mux;
+ int dir;
+ char *name;
+ };
+
+ /* the pci core can make use of the following gpios */
+ static struct ltq_pci_gpio_map ltq_pci_gpio_map[] = {
+- { 0, 1, 0, 0, "pci-exin0" },
+- { 1, 1, 0, 0, "pci-exin1" },
+- { 2, 1, 0, 0, "pci-exin2" },
+- { 39, 1, 0, 0, "pci-exin3" },
+- { 10, 1, 0, 0, "pci-exin4" },
+- { 9, 1, 0, 0, "pci-exin5" },
+- { 30, 1, 0, 1, "pci-gnt1" },
+- { 23, 1, 0, 1, "pci-gnt2" },
+- { 19, 1, 0, 1, "pci-gnt3" },
+- { 38, 1, 0, 1, "pci-gnt4" },
+- { 29, 1, 0, 0, "pci-req1" },
+- { 31, 1, 0, 0, "pci-req2" },
+- { 3, 1, 0, 0, "pci-req3" },
+- { 37, 1, 0, 0, "pci-req4" },
++ { 0, 2, 0, "pci-exin0" },
++ { 1, 2, 0, "pci-exin1" },
++ { 2, 2, 0, "pci-exin2" },
++ { 39, 2, 0, "pci-exin3" },
++ { 10, 2, 0, "pci-exin4" },
++ { 9, 2, 0, "pci-exin5" },
++ { 30, 2, 1, "pci-gnt1" },
++ { 23, 2, 1, "pci-gnt2" },
++ { 19, 2, 1, "pci-gnt3" },
++ { 38, 2, 1, "pci-gnt4" },
++ { 29, 2, 0, "pci-req1" },
++ { 31, 2, 0, "pci-req2" },
++ { 3, 2, 0, "pci-req3" },
++ { 37, 2, 0, "pci-req4" },
+ };
+
+ __iomem void *ltq_pci_mapped_cfg;
+@@ -157,13 +156,12 @@ static void ltq_pci_setup_gpio(int gpio)
+ for (i = 0; i < ARRAY_SIZE(ltq_pci_gpio_map); i++) {
+ if (gpio & (1 << i)) {
+ ltq_gpio_request(ltq_pci_gpio_map[i].pin,
+- ltq_pci_gpio_map[i].alt0,
+- ltq_pci_gpio_map[i].alt1,
++ ltq_pci_gpio_map[i].mux,
+ ltq_pci_gpio_map[i].dir,
+ ltq_pci_gpio_map[i].name);
+ }
+ }
+- ltq_gpio_request(21, 0, 0, 1, "pci-reset");
++ ltq_gpio_request(21, 0, 1, "pci-reset");
+ ltq_pci_req_mask = (gpio >> PCI_REQ_SHIFT) & PCI_REQ_MASK;
+ }
+
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0005-MIPS-lantiq-make-irq.c-support-the-FALC-ON.patch b/target/linux/lantiq/patches-3.2/0007-MIPS-lantiq-make-irq.c-support-the-FALC-ON.patch
index 97d9461..fd45e61 100644
--- a/target/linux/lantiq/patches/0005-MIPS-lantiq-make-irq.c-support-the-FALC-ON.patch
+++ b/target/linux/lantiq/patches-3.2/0007-MIPS-lantiq-make-irq.c-support-the-FALC-ON.patch
@@ -1,7 +1,7 @@
-From d9355bb07878f9aa40856cc437c43cedc87662fc Mon Sep 17 00:00:00 2001
+From 03f55cae0f5d9a4c30f935abf8d621ced64ae425 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 11 Aug 2011 12:25:55 +0200
-Subject: [PATCH 05/24] MIPS: lantiq: make irq.c support the FALC-ON
+Subject: [PATCH 07/70] MIPS: lantiq: make irq.c support the FALC-ON
There are minor differences in how irqs work on xway and falcon socs.
Xway needs 2 quirks that we need to disable for falcon to also work with
@@ -10,16 +10,17 @@ this code.
* EBU irq does not need to send a special ack to the EBU
* The EIU does not exist
-Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
-Cc: linux-mips@linux-mips.org
+Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/lantiq/irq.c | 24 +++++++++++++-----------
1 files changed, 13 insertions(+), 11 deletions(-)
+diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
+index f9737bb..17c057f 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
-@@ -195,7 +195,7 @@ static void ltq_hw_irqdispatch(int modul
+@@ -195,7 +195,7 @@ static void ltq_hw_irqdispatch(int module)
do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
/* if this is a EBU irq, we need to ack it or get a deadlock */
@@ -37,15 +38,14 @@ Cc: linux-mips@linux-mips.org
+ if (LTQ_EIU_BASE_ADDR) {
+ if (insert_resource(&iomem_resource, &ltq_eiu_resource) < 0)
+ panic("Failed to insert eiu memory\n");
-+
-+ if (request_mem_region(ltq_eiu_resource.start,
-+ resource_size(&ltq_eiu_resource), "eiu") < 0)
-+ panic("Failed to request eiu memory\n");
- if (request_mem_region(ltq_eiu_resource.start,
- resource_size(&ltq_eiu_resource), "eiu") < 0)
- panic("Failed to request eiu memory\n");
--
++ if (request_mem_region(ltq_eiu_resource.start,
++ resource_size(&ltq_eiu_resource), "eiu") < 0)
++ panic("Failed to request eiu memory\n");
+
- ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
+ ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
resource_size(&ltq_eiu_resource));
@@ -68,3 +68,6 @@ Cc: linux-mips@linux-mips.org
irq_set_chip_and_handler(i, &ltq_eiu_type,
handle_level_irq);
/* EIU3-5 only exist on ar9 and vr9 */
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0006-MIPS-lantiq-add-basic-support-for-FALC-ON.patch b/target/linux/lantiq/patches-3.2/0008-MIPS-lantiq-add-basic-support-for-FALC-ON.patch
index 780afa0..72b0fa7 100644
--- a/target/linux/lantiq/patches/0006-MIPS-lantiq-add-basic-support-for-FALC-ON.patch
+++ b/target/linux/lantiq/patches-3.2/0008-MIPS-lantiq-add-basic-support-for-FALC-ON.patch
@@ -1,18 +1,16 @@
-From ff57bc17a9964d24708759c6d78a51e337563d5f Mon Sep 17 00:00:00 2001
+From d54a53bc8bc25bf2f9076013f89b30cb9103f99f Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 11 Aug 2011 14:33:04 +0200
-Subject: [PATCH 06/24] MIPS: lantiq: add basic support for FALC-ON
+Subject: [PATCH 08/70] MIPS: lantiq: add basic support for FALC-ON
-Adds support for the FALC-ON SoC. This SoC is from the fiber to the home GPON
-series.
+Adds support for the FALC-ON SoC. This SoC is from the FTTH/GPON SoC family.
-Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
-Cc: linux-mips@linux-mips.org
+Signed-off-by: John Crispin <blogic@openwrt.org>
---
.../include/asm/mach-lantiq/falcon/falcon_irq.h | 268 ++++++++++++++++++++
arch/mips/include/asm/mach-lantiq/falcon/irq.h | 18 ++
- .../include/asm/mach-lantiq/falcon/lantiq_soc.h | 140 ++++++++++
+ .../include/asm/mach-lantiq/falcon/lantiq_soc.h | 143 +++++++++++
arch/mips/include/asm/mach-lantiq/lantiq.h | 1 +
arch/mips/lantiq/Kconfig | 4 +
arch/mips/lantiq/Makefile | 1 +
@@ -21,10 +19,10 @@ Cc: linux-mips@linux-mips.org
arch/mips/lantiq/falcon/clk.c | 44 ++++
arch/mips/lantiq/falcon/devices.c | 87 +++++++
arch/mips/lantiq/falcon/devices.h | 18 ++
- arch/mips/lantiq/falcon/prom.c | 72 ++++++
+ arch/mips/lantiq/falcon/prom.c | 93 +++++++
arch/mips/lantiq/falcon/reset.c | 87 +++++++
- arch/mips/lantiq/falcon/sysctrl.c | 181 +++++++++++++
- 14 files changed, 923 insertions(+), 0 deletions(-)
+ arch/mips/lantiq/falcon/sysctrl.c | 183 +++++++++++++
+ 14 files changed, 949 insertions(+), 0 deletions(-)
create mode 100644 arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h
create mode 100644 arch/mips/include/asm/mach-lantiq/falcon/irq.h
create mode 100644 arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
@@ -36,6 +34,9 @@ Cc: linux-mips@linux-mips.org
create mode 100644 arch/mips/lantiq/falcon/reset.c
create mode 100644 arch/mips/lantiq/falcon/sysctrl.c
+diff --git a/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h b/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h
+new file mode 100644
+index 0000000..4dc6466
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h
@@ -0,0 +1,268 @@
@@ -307,6 +308,9 @@ Cc: linux-mips@linux-mips.org
+#define FALCON_IRQ_VPE0_PMCIR (INT_NUM_IM4_IRL0 + 31)
+
+#endif /* _FALCON_IRQ__ */
+diff --git a/arch/mips/include/asm/mach-lantiq/falcon/irq.h b/arch/mips/include/asm/mach-lantiq/falcon/irq.h
+new file mode 100644
+index 0000000..2caccd9
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/falcon/irq.h
@@ -0,0 +1,18 @@
@@ -328,9 +332,12 @@ Cc: linux-mips@linux-mips.org
+#include_next <irq.h>
+
+#endif
+diff --git a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
+new file mode 100644
+index 0000000..b074748
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
-@@ -0,0 +1,140 @@
+@@ -0,0 +1,143 @@
+/*
+ * 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
@@ -361,8 +368,10 @@ Cc: linux-mips@linux-mips.org
+#define LTQ_ASC_RIR(x) (INT_NUM_IM3_IRL0 + (x * 8) + 1)
+#define LTQ_ASC_EIR(x) (INT_NUM_IM3_IRL0 + (x * 8) + 2)
+
-+/* during early_printk no ioremap possible at this early stage
-+ lets use KSEG1 instead */
++/*
++ * during early_printk no ioremap possible at this early stage
++ * lets use KSEG1 instead
++ */
+#define LTQ_EARLY_ASC KSEG1ADDR(LTQ_ASC0_BASE_ADDR)
+
+/* ICU - interrupt control unit */
@@ -407,6 +416,7 @@ Cc: linux-mips@linux-mips.org
+#define LTQ_STATUS_BASE_ADDR 0x1E802000
+
+#define LTQ_FALCON_CHIPID ((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x0c))
++#define LTQ_FALCON_CHIPTYPE ((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x38))
+#define LTQ_FALCON_CHIPCONF ((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x40))
+
+/* SYSCTL - start/stop/restart/configure/... different parts of the Soc */
@@ -457,7 +467,7 @@ Cc: linux-mips@linux-mips.org
+ ltq_sys1_w32((ltq_sys1_r32(reg) & ~(clear)) | (set), reg)
+
+/* gpio_request wrapper to help configure the pin */
-+extern int ltq_gpio_request(unsigned int pin, unsigned int val,
++extern int ltq_gpio_request(unsigned int pin, unsigned int mux,
+ unsigned int dir, const char *name);
+extern int ltq_gpio_mux_set(unsigned int pin, unsigned int mux);
+
@@ -471,9 +481,11 @@ Cc: linux-mips@linux-mips.org
+
+#endif /* CONFIG_SOC_FALCON */
+#endif /* _LTQ_XWAY_H__ */
+diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h
+index 66d7300..188de0f 100644
--- a/arch/mips/include/asm/mach-lantiq/lantiq.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
-@@ -25,6 +25,7 @@ extern unsigned int ltq_get_soc_type(voi
+@@ -25,6 +25,7 @@ extern unsigned int ltq_get_soc_type(void);
/* clock speeds */
#define CLOCK_60M 60000000
#define CLOCK_83M 83333333
@@ -481,6 +493,8 @@ Cc: linux-mips@linux-mips.org
#define CLOCK_111M 111111111
#define CLOCK_133M 133333333
#define CLOCK_167M 166666667
+diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
+index 3fccf21..cb6b39f 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -16,8 +16,12 @@ config SOC_XWAY
@@ -496,13 +510,17 @@ Cc: linux-mips@linux-mips.org
+source "arch/mips/lantiq/falcon/Kconfig"
endif
+diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile
+index e5dae0e..7e9c69e 100644
--- a/arch/mips/lantiq/Makefile
+++ b/arch/mips/lantiq/Makefile
-@@ -9,3 +9,4 @@ obj-y := irq.o setup.o clk.o prom.o devi
+@@ -9,3 +9,4 @@ obj-y := irq.o setup.o clk.o prom.o devices.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_SOC_TYPE_XWAY) += xway/
+obj-$(CONFIG_SOC_FALCON) += falcon/
+diff --git a/arch/mips/lantiq/Platform b/arch/mips/lantiq/Platform
+index f3dff05..b3ec498 100644
--- a/arch/mips/lantiq/Platform
+++ b/arch/mips/lantiq/Platform
@@ -6,3 +6,4 @@ platform-$(CONFIG_LANTIQ) += lantiq/
@@ -510,10 +528,16 @@ Cc: linux-mips@linux-mips.org
load-$(CONFIG_LANTIQ) = 0xffffffff80002000
cflags-$(CONFIG_SOC_TYPE_XWAY) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway
+cflags-$(CONFIG_SOC_FALCON) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon
+diff --git a/arch/mips/lantiq/falcon/Makefile b/arch/mips/lantiq/falcon/Makefile
+new file mode 100644
+index 0000000..e9c7455
--- /dev/null
+++ b/arch/mips/lantiq/falcon/Makefile
@@ -0,0 +1 @@
+obj-y := clk.o prom.o reset.o sysctrl.o devices.o
+diff --git a/arch/mips/lantiq/falcon/clk.c b/arch/mips/lantiq/falcon/clk.c
+new file mode 100644
+index 0000000..afe1b52
--- /dev/null
+++ b/arch/mips/lantiq/falcon/clk.c
@@ -0,0 +1,44 @@
@@ -527,7 +551,7 @@ Cc: linux-mips@linux-mips.org
+ */
+
+#include <linux/ioport.h>
-+#include <linux/module.h>
++#include <linux/export.h>
+
+#include <lantiq_soc.h>
+
@@ -561,6 +585,9 @@ Cc: linux-mips@linux-mips.org
+ return CLOCK_100M;
+}
+EXPORT_SYMBOL(ltq_get_fpi_hz);
+diff --git a/arch/mips/lantiq/falcon/devices.c b/arch/mips/lantiq/falcon/devices.c
+new file mode 100644
+index 0000000..c4606f2
--- /dev/null
+++ b/arch/mips/lantiq/falcon/devices.c
@@ -0,0 +1,87 @@
@@ -651,6 +678,9 @@ Cc: linux-mips@linux-mips.org
+{
+ platform_device_register(&ltq_flash_nand);
+}
+diff --git a/arch/mips/lantiq/falcon/devices.h b/arch/mips/lantiq/falcon/devices.h
+new file mode 100644
+index 0000000..e802a7c
--- /dev/null
+++ b/arch/mips/lantiq/falcon/devices.h
@@ -0,0 +1,18 @@
@@ -672,9 +702,12 @@ Cc: linux-mips@linux-mips.org
+extern void falcon_register_nand(void);
+
+#endif
+diff --git a/arch/mips/lantiq/falcon/prom.c b/arch/mips/lantiq/falcon/prom.c
+new file mode 100644
+index 0000000..b50d6f9
--- /dev/null
+++ b/arch/mips/lantiq/falcon/prom.c
-@@ -0,0 +1,72 @@
+@@ -0,0 +1,93 @@
+/*
+ * 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
@@ -691,6 +724,9 @@ Cc: linux-mips@linux-mips.org
+#include "../prom.h"
+
+#define SOC_FALCON "Falcon"
++#define SOC_FALCON_D "Falcon-D"
++#define SOC_FALCON_V "Falcon-V"
++#define SOC_FALCON_M "Falcon-M"
+
+#define PART_SHIFT 12
+#define PART_MASK 0x0FFFF000
@@ -698,6 +734,8 @@ Cc: linux-mips@linux-mips.org
+#define REV_MASK 0xF0000000
+#define SREV_SHIFT 22
+#define SREV_MASK 0x03C00000
++#define TYPE_SHIFT 26
++#define TYPE_MASK 0x3C000000
+
+#define MUXC_SIF_RX_PIN 112
+#define MUXC_SIF_TX_PIN 113
@@ -731,14 +769,30 @@ Cc: linux-mips@linux-mips.org
+void __init
+ltq_soc_detect(struct ltq_soc_info *i)
+{
++ u32 type;
+ i->partnum = (ltq_r32(LTQ_FALCON_CHIPID) & PART_MASK) >> PART_SHIFT;
+ i->rev = (ltq_r32(LTQ_FALCON_CHIPID) & REV_MASK) >> REV_SHIFT;
-+ i->srev = (ltq_r32(LTQ_FALCON_CHIPCONF) & SREV_MASK) >> SREV_SHIFT;
++ i->srev = ((ltq_r32(LTQ_FALCON_CHIPCONF) & SREV_MASK) >> SREV_SHIFT);
+ sprintf(i->rev_type, "%c%d%d", (i->srev & 0x4) ? ('B') : ('A'),
-+ i->rev & 0x7, i->srev & 0x3);
++ i->rev & 0x7, (i->srev & 0x3) + 1);
++
+ switch (i->partnum) {
+ case SOC_ID_FALCON:
-+ i->name = SOC_FALCON;
++ type = (ltq_r32(LTQ_FALCON_CHIPTYPE) & TYPE_MASK) >> TYPE_SHIFT;
++ switch (type) {
++ case 0:
++ i->name = SOC_FALCON_D;
++ break;
++ case 1:
++ i->name = SOC_FALCON_V;
++ break;
++ case 2:
++ i->name = SOC_FALCON_M;
++ break;
++ default:
++ i->name = SOC_FALCON;
++ break;
++ }
+ i->type = SOC_TYPE_FALCON;
+ break;
+
@@ -747,6 +801,9 @@ Cc: linux-mips@linux-mips.org
+ break;
+ }
+}
+diff --git a/arch/mips/lantiq/falcon/reset.c b/arch/mips/lantiq/falcon/reset.c
+new file mode 100644
+index 0000000..cbcadc5
--- /dev/null
+++ b/arch/mips/lantiq/falcon/reset.c
@@ -0,0 +1,87 @@
@@ -763,7 +820,7 @@ Cc: linux-mips@linux-mips.org
+#include <linux/io.h>
+#include <linux/pm.h>
+#include <asm/reboot.h>
-+#include <linux/module.h>
++#include <linux/export.h>
+
+#include <lantiq_soc.h>
+
@@ -837,9 +894,12 @@ Cc: linux-mips@linux-mips.org
+}
+
+arch_initcall(mips_reboot_setup);
+diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c
+new file mode 100644
+index 0000000..905a142
--- /dev/null
+++ b/arch/mips/lantiq/falcon/sysctrl.c
-@@ -0,0 +1,181 @@
+@@ -0,0 +1,183 @@
+/*
+ * 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
@@ -850,6 +910,7 @@ Cc: linux-mips@linux-mips.org
+ */
+
+#include <linux/ioport.h>
++#include <linux/export.h>
+#include <asm/delay.h>
+
+#include <lantiq_soc.h>
@@ -905,11 +966,12 @@ Cc: linux-mips@linux-mips.org
+#define ltq_status_r32(x) ltq_r32(ltq_status_membase + (x))
+
+static inline void
-+ltq_sysctl_wait(int module, unsigned int mask, unsigned int test)
++ltq_sysctl_wait(int module, unsigned int mask,
++ unsigned int test, unsigned int reg)
+{
+ int err = 1000000;
+
-+ do {} while (--err && ((ltq_reg_r32(module, LTQ_SYSCTL_ACTS)
++ do {} while (--err && ((ltq_reg_r32(module, reg)
+ & mask) != test));
+ if (!err)
+ pr_err("module de/activation failed %d %08X %08X\n",
@@ -924,7 +986,7 @@ Cc: linux-mips@linux-mips.org
+
+ ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKEN);
+ ltq_reg_w32(module, mask, LTQ_SYSCTL_ACT);
-+ ltq_sysctl_wait(module, mask, mask);
++ ltq_sysctl_wait(module, mask, mask, LTQ_SYSCTL_ACTS);
+}
+EXPORT_SYMBOL(ltq_sysctl_activate);
+
@@ -936,7 +998,7 @@ Cc: linux-mips@linux-mips.org
+
+ ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKCLR);
+ ltq_reg_w32(module, mask, LTQ_SYSCTL_DEACT);
-+ ltq_sysctl_wait(module, mask, 0);
++ ltq_sysctl_wait(module, mask, 0, LTQ_SYSCTL_ACTS);
+}
+EXPORT_SYMBOL(ltq_sysctl_deactivate);
+
@@ -947,7 +1009,7 @@ Cc: linux-mips@linux-mips.org
+ return;
+
+ ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKEN);
-+ ltq_sysctl_wait(module, mask, mask);
++ ltq_sysctl_wait(module, mask, mask, LTQ_SYSCTL_CLKS);
+}
+EXPORT_SYMBOL(ltq_sysctl_clken);
+
@@ -958,7 +1020,7 @@ Cc: linux-mips@linux-mips.org
+ return;
+
+ ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKCLR);
-+ ltq_sysctl_wait(module, mask, 0);
++ ltq_sysctl_wait(module, mask, 0, LTQ_SYSCTL_CLKS);
+}
+EXPORT_SYMBOL(ltq_sysctl_clkdis);
+
@@ -974,7 +1036,7 @@ Cc: linux-mips@linux-mips.org
+ if ((~act & mask) != 0)
+ ltq_sysctl_activate(module, ~act & mask);
+ ltq_reg_w32(module, act & mask, LTQ_SYSCTL_RBT);
-+ ltq_sysctl_wait(module, mask, mask);
++ ltq_sysctl_wait(module, mask, mask, LTQ_SYSCTL_ACTS);
+}
+EXPORT_SYMBOL(ltq_sysctl_reboot);
+
@@ -1021,3 +1083,6 @@ Cc: linux-mips@linux-mips.org
+
+ ltq_gpe_enable();
+}
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0007-MIPS-lantiq-add-support-for-FALC-ON-GPIOs.patch b/target/linux/lantiq/patches-3.2/0009-MIPS-lantiq-add-support-for-FALC-ON-GPIOs.patch
index 2f747d9..2e50422 100644
--- a/target/linux/lantiq/patches/0007-MIPS-lantiq-add-support-for-FALC-ON-GPIOs.patch
+++ b/target/linux/lantiq/patches-3.2/0009-MIPS-lantiq-add-support-for-FALC-ON-GPIOs.patch
@@ -1,27 +1,30 @@
-From 02d9df56be1ba23c7bec51c94e5d2ac0d13d2d78 Mon Sep 17 00:00:00 2001
+From 95e7c9e7b37b06462c8b3b8431dc64d60369eb38 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 11 Aug 2011 14:35:02 +0200
-Subject: [PATCH 07/24] MIPS: lantiq: add support for FALC-ON GPIOs
+Subject: [PATCH 09/70] MIPS: lantiq: add support for FALC-ON GPIOs
FALC-ON uses a different GPIO core than the other Lantiq SoCs. This patch adds
the new driver.
Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
Signed-off-by: John Crispin <blogic@openwrt.org>
-Cc: linux-mips@linux-mips.org
---
arch/mips/lantiq/falcon/Makefile | 2 +-
arch/mips/lantiq/falcon/devices.c | 41 ++++
arch/mips/lantiq/falcon/devices.h | 2 +
- arch/mips/lantiq/falcon/gpio.c | 398 +++++++++++++++++++++++++++++++++++++
- 4 files changed, 442 insertions(+), 1 deletions(-)
+ arch/mips/lantiq/falcon/gpio.c | 399 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 443 insertions(+), 1 deletions(-)
create mode 100644 arch/mips/lantiq/falcon/gpio.c
+diff --git a/arch/mips/lantiq/falcon/Makefile b/arch/mips/lantiq/falcon/Makefile
+index e9c7455..de72209 100644
--- a/arch/mips/lantiq/falcon/Makefile
+++ b/arch/mips/lantiq/falcon/Makefile
@@ -1 +1 @@
-obj-y := clk.o prom.o reset.o sysctrl.o devices.o
+obj-y := clk.o prom.o reset.o sysctrl.o devices.o gpio.o
+diff --git a/arch/mips/lantiq/falcon/devices.c b/arch/mips/lantiq/falcon/devices.c
+index c4606f2..4f47b44 100644
--- a/arch/mips/lantiq/falcon/devices.c
+++ b/arch/mips/lantiq/falcon/devices.c
@@ -9,6 +9,7 @@
@@ -76,6 +79,8 @@ Cc: linux-mips@linux-mips.org
+ ltq_sysctl_activate(SYSCTL_SYS1,
+ ACTS_PADCTRL3 | ACTS_PADCTRL4 | ACTS_P3 | ACTS_P4);
+}
+diff --git a/arch/mips/lantiq/falcon/devices.h b/arch/mips/lantiq/falcon/devices.h
+index e802a7c..18be8b6 100644
--- a/arch/mips/lantiq/falcon/devices.h
+++ b/arch/mips/lantiq/falcon/devices.h
@@ -14,5 +14,7 @@
@@ -86,9 +91,12 @@ Cc: linux-mips@linux-mips.org
+extern void falcon_register_gpio_extra(void);
#endif
+diff --git a/arch/mips/lantiq/falcon/gpio.c b/arch/mips/lantiq/falcon/gpio.c
+new file mode 100644
+index 0000000..28f8639
--- /dev/null
+++ b/arch/mips/lantiq/falcon/gpio.c
-@@ -0,0 +1,398 @@
+@@ -0,0 +1,399 @@
+/*
+ * 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
@@ -101,6 +109,7 @@ Cc: linux-mips@linux-mips.org
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
++#include <linux/export.h>
+#include <linux/platform_device.h>
+
+#include <lantiq_soc.h>
@@ -187,8 +196,8 @@ Cc: linux-mips@linux-mips.org
+}
+EXPORT_SYMBOL(ltq_gpio_mux_set);
+
-+int ltq_gpio_request(unsigned int pin, unsigned int val,
-+ unsigned int dir, const char *name)
++int ltq_gpio_request(unsigned int pin, unsigned int mux,
++ unsigned int dir, const char *name)
+{
+ int port = pin / 100;
+ int offset = pin % 100;
@@ -206,7 +215,7 @@ Cc: linux-mips@linux-mips.org
+ else
+ gpio_direction_input(pin);
+
-+ return ltq_gpio_mux_set(pin, val);
++ return ltq_gpio_mux_set(pin, mux);
+}
+EXPORT_SYMBOL(ltq_gpio_request);
+
@@ -487,3 +496,6 @@ Cc: linux-mips@linux-mips.org
+}
+
+postcore_initcall(falcon_gpio_init);
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0008-MIPS-lantiq-add-support-for-the-EASY98000-evaluation.patch b/target/linux/lantiq/patches-3.2/0010-MIPS-lantiq-add-support-for-the-EASY98000-evaluation.patch
index 10c73f5..93d608e 100644
--- a/target/linux/lantiq/patches/0008-MIPS-lantiq-add-support-for-the-EASY98000-evaluation.patch
+++ b/target/linux/lantiq/patches-3.2/0010-MIPS-lantiq-add-support-for-the-EASY98000-evaluation.patch
@@ -1,14 +1,13 @@
-From ec6ba0f79c010a878d679c057fb6306b50a201b0 Mon Sep 17 00:00:00 2001
+From 9397aa9584bade07ae667ecd5135653f9c04e236 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 11 Aug 2011 14:09:35 +0200
-Subject: [PATCH 08/24] MIPS: lantiq: add support for the EASY98000 evaluation
+Subject: [PATCH 10/70] MIPS: lantiq: add support for the EASY98000 evaluation
board
This patch adds the machine code for the EASY9800 evaluation board.
Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
Signed-off-by: John Crispin <blogic@openwrt.org>
-Cc: linux-mips@linux-mips.org
---
arch/mips/lantiq/falcon/Kconfig | 11 +++
arch/mips/lantiq/falcon/Makefile | 1 +
@@ -18,6 +17,9 @@ Cc: linux-mips@linux-mips.org
create mode 100644 arch/mips/lantiq/falcon/Kconfig
create mode 100644 arch/mips/lantiq/falcon/mach-easy98000.c
+diff --git a/arch/mips/lantiq/falcon/Kconfig b/arch/mips/lantiq/falcon/Kconfig
+new file mode 100644
+index 0000000..03e999d
--- /dev/null
+++ b/arch/mips/lantiq/falcon/Kconfig
@@ -0,0 +1,11 @@
@@ -32,11 +34,16 @@ Cc: linux-mips@linux-mips.org
+endmenu
+
+endif
+diff --git a/arch/mips/lantiq/falcon/Makefile b/arch/mips/lantiq/falcon/Makefile
+index de72209..56b22eb 100644
--- a/arch/mips/lantiq/falcon/Makefile
+++ b/arch/mips/lantiq/falcon/Makefile
@@ -1 +1,2 @@
obj-y := clk.o prom.o reset.o sysctrl.o devices.o gpio.o
+obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o
+diff --git a/arch/mips/lantiq/falcon/mach-easy98000.c b/arch/mips/lantiq/falcon/mach-easy98000.c
+new file mode 100644
+index 0000000..361b8f0
--- /dev/null
+++ b/arch/mips/lantiq/falcon/mach-easy98000.c
@@ -0,0 +1,110 @@
@@ -150,6 +157,8 @@ Cc: linux-mips@linux-mips.org
+ "EASY98000NAND",
+ "EASY98000 Eval Board (NAND Flash)",
+ easy98000nand_init);
+diff --git a/arch/mips/lantiq/machtypes.h b/arch/mips/lantiq/machtypes.h
+index 7e01b8c..dfc6af7 100644
--- a/arch/mips/lantiq/machtypes.h
+++ b/arch/mips/lantiq/machtypes.h
@@ -15,6 +15,11 @@ enum lantiq_mach_type {
@@ -164,3 +173,6 @@ Cc: linux-mips@linux-mips.org
};
#endif
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0001-MIPS-lantiq-fix-early-printk.patch b/target/linux/lantiq/patches-3.2/0011-MIPS-lantiq-fix-early-printk.patch
index 57b330d..8cffe09 100644
--- a/target/linux/lantiq/patches/0001-MIPS-lantiq-fix-early-printk.patch
+++ b/target/linux/lantiq/patches-3.2/0011-MIPS-lantiq-fix-early-printk.patch
@@ -1,33 +1,38 @@
-From 91f8d0c8fbb9ea70bf78a291e312157177be8ee3 Mon Sep 17 00:00:00 2001
+From 68e9e86dda22c491e5e3c44271a91aefcf636434 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sat, 20 Aug 2011 18:55:13 +0200
-Subject: [PATCH 01/24] MIPS: lantiq: fix early printk
+Subject: [PATCH 11/70] MIPS: lantiq: fix early printk
-The code was using a 32bit write operation in the early_printk code. This
-resulted in 3 zero bytes also being written to the serial port. Change the
-memory access to 8bit.
+The code was using a 32bit write operations in the early_printk code. This
+resulted in 3 zero bytes also being written to the serial port. This patch
+changes the memory access to 8bit.
Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
Signed-off-by: John Crispin <blogic@openwrt.org>
-Cc: linux-mips@linux-mips.org
---
- .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 4 ++++
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 6 ++++++
arch/mips/lantiq/early_printk.c | 14 ++++++++------
- 2 files changed, 12 insertions(+), 6 deletions(-)
+ 2 files changed, 14 insertions(+), 6 deletions(-)
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index 87f6d24..e31f52d 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
-@@ -34,6 +34,10 @@
+@@ -34,6 +34,12 @@
#define LTQ_ASC1_BASE_ADDR 0x1E100C00
#define LTQ_ASC_SIZE 0x400
-+/* during early_printk no ioremap is possible
-+ lets use KSEG1 instead */
++/*
++ * during early_printk no ioremap is possible
++ * lets use KSEG1 instead
++ */
+#define LTQ_EARLY_ASC KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
+
/* RCU - reset control unit */
#define LTQ_RCU_BASE_ADDR 0x1F203000
#define LTQ_RCU_SIZE 0x1000
+diff --git a/arch/mips/lantiq/early_printk.c b/arch/mips/lantiq/early_printk.c
+index 972e05f..5089075 100644
--- a/arch/mips/lantiq/early_printk.c
+++ b/arch/mips/lantiq/early_printk.c
@@ -12,11 +12,13 @@
@@ -58,3 +63,6 @@ Cc: linux-mips@linux-mips.org
+ ltq_w8(c, LTQ_ASC_TBUF);
local_irq_restore(flags);
}
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0002-MIPS-lantiq-fix-cmdline-parsing.patch b/target/linux/lantiq/patches-3.2/0012-MIPS-lantiq-fix-cmdline-parsing.patch
index 6966e1c..ac8103d 100644
--- a/target/linux/lantiq/patches/0002-MIPS-lantiq-fix-cmdline-parsing.patch
+++ b/target/linux/lantiq/patches-3.2/0012-MIPS-lantiq-fix-cmdline-parsing.patch
@@ -1,21 +1,22 @@
-From b85d5204f2fe8c3b5e6172f7cc1741ad6e849334 Mon Sep 17 00:00:00 2001
+From 3be934b64f874e6cd2af7945f4fc441c7fadb34f Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 12 Aug 2011 16:27:38 +0200
-Subject: [PATCH 02/24] MIPS: lantiq: fix cmdline parsing
+Subject: [PATCH 12/70] MIPS: lantiq: fix cmdline parsing
The code tested if the KSEG1 mapped address of argv was != 0. We need to use
CPHYSADDR instead to make the conditional actually work.
Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
Signed-off-by: John Crispin <blogic@openwrt.org>
-Cc: linux-mips@linux-mips.org
---
arch/mips/lantiq/prom.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
+diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
+index e3b1e25..acb8921 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
-@@ -45,10 +45,12 @@ static void __init prom_init_cmdline(voi
+@@ -49,10 +49,12 @@ static void __init prom_init_cmdline(void)
char **argv = (char **) KSEG1ADDR(fw_arg1);
int i;
@@ -30,3 +31,6 @@ Cc: linux-mips@linux-mips.org
strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
}
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0024-MIPS-lantiq-fixes-STP-based-gpios.patch b/target/linux/lantiq/patches-3.2/0013-MIPS-lantiq-fix-STP-gpio-groups.patch
index 04f84e0..7ca3b7a 100644
--- a/target/linux/lantiq/patches/0024-MIPS-lantiq-fixes-STP-based-gpios.patch
+++ b/target/linux/lantiq/patches-3.2/0013-MIPS-lantiq-fix-STP-gpio-groups.patch
@@ -1,9 +1,10 @@
-From 2dfa2b3e50c5ac49052233d15fa427a9b9136df8 Mon Sep 17 00:00:00 2001
+From 556ba7f7149a0350a47ecf26185aed99c8d87176 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 27 Oct 2011 20:06:05 +0200
-Subject: [PATCH 10/22] MIPS: lantiq: fixes STP based gpios
+Subject: [PATCH 13/70] MIPS: lantiq: fix STP gpio groups
The STP engine has 3 groups of 8 pins. Only the first was activated by default.
+This patch activates the 2 missing groups.
Signed-off-by: Matti Laakso <malaakso@elisanet.fi>
Signed-off-by: John Crispin <blogic@openwrt.org>
@@ -11,6 +12,8 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
arch/mips/lantiq/xway/gpio_stp.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
+diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
+index 2c78660..cb6f170 100644
--- a/arch/mips/lantiq/xway/gpio_stp.c
+++ b/arch/mips/lantiq/xway/gpio_stp.c
@@ -35,6 +35,8 @@
@@ -34,3 +37,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
/* stp are update periodically by the FPI bus */
ltq_stp_w32_mask(LTQ_STP_UPD_MASK, LTQ_STP_UPD_FPI, LTQ_STP_CON1);
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0025-MIPS-lantiq-activate-pull-up-resistors-when-gpio-is-.patch b/target/linux/lantiq/patches-3.2/0014-MIPS-lantiq-fix-pull-gpio-up-resistors-usage.patch
index f8146f7..40b8667 100644
--- a/target/linux/lantiq/patches/0025-MIPS-lantiq-activate-pull-up-resistors-when-gpio-is-.patch
+++ b/target/linux/lantiq/patches-3.2/0014-MIPS-lantiq-fix-pull-gpio-up-resistors-usage.patch
@@ -1,10 +1,10 @@
-From 6efd9a5f303c4561eee14ae429b8c0fafa6c5a83 Mon Sep 17 00:00:00 2001
+From e97f45d255f4a223d38e2f39c1ddf7a3e0766527 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 27 Oct 2011 20:06:30 +0200
-Subject: [PATCH 11/22] MIPS: lantiq: activate pull up resistors when gpio is
- a input
+Subject: [PATCH 14/70] MIPS: lantiq: fix pull gpio up resistors usage
-The register that enables a gpios internal pullups was not set.
+The register that enables a gpios internal pullups was not used. This patch
+makes sure the pullups are activated correctly.
Signed-off-by: Matti Laakso <malaakso@elisanet.fi>
Signed-off-by: John Crispin <blogic@openwrt.org>
@@ -12,6 +12,8 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
arch/mips/lantiq/xway/gpio.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
+diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c
+index f204f6c..14ff7c7 100644
--- a/arch/mips/lantiq/xway/gpio.c
+++ b/arch/mips/lantiq/xway/gpio.c
@@ -21,6 +21,8 @@
@@ -23,7 +25,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
#define PINS_PER_PORT 16
#define MAX_PORTS 3
-@@ -106,6 +108,8 @@ static int ltq_gpio_direction_input(stru
+@@ -106,6 +108,8 @@ static int ltq_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
@@ -32,7 +34,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
return 0;
}
-@@ -117,6 +121,8 @@ static int ltq_gpio_direction_output(str
+@@ -117,6 +121,8 @@ static int ltq_gpio_direction_output(struct gpio_chip *chip,
ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
@@ -41,3 +43,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
ltq_gpio_set(chip, offset, value);
return 0;
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0015-MIPS-lantiq-add-default-configs.patch b/target/linux/lantiq/patches-3.2/0015-MIPS-lantiq-add-default-configs.patch
new file mode 100644
index 0000000..bc55e51
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0015-MIPS-lantiq-add-default-configs.patch
@@ -0,0 +1,247 @@
+From 9946990028431fc732d1244c6ccdfface1ee5640 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 11 Nov 2011 22:02:27 +0100
+Subject: [PATCH 15/70] MIPS: lantiq: add default configs
+
+This patch adds the default config for 3 Lantiq SoCs
+
+* Danube/AR9 (xway)
+* Amazon-SE
+* Falc-ON
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/configs/ase_defconfig | 67 +++++++++++++++++++++++++++++++++
+ arch/mips/configs/falcon_defconfig | 72 ++++++++++++++++++++++++++++++++++++
+ arch/mips/configs/xway_defconfig | 66 +++++++++++++++++++++++++++++++++
+ 3 files changed, 205 insertions(+), 0 deletions(-)
+ create mode 100644 arch/mips/configs/ase_defconfig
+ create mode 100644 arch/mips/configs/falcon_defconfig
+ create mode 100644 arch/mips/configs/xway_defconfig
+
+diff --git a/arch/mips/configs/ase_defconfig b/arch/mips/configs/ase_defconfig
+new file mode 100644
+index 0000000..5bb1d93
+--- /dev/null
++++ b/arch/mips/configs/ase_defconfig
+@@ -0,0 +1,67 @@
++CONFIG_LANTIQ=y
++CONFIG_SOC_AMAZON_SE=y
++CONFIG_CPU_MIPS32_R2=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_EXPERIMENTAL=y
++CONFIG_DEFAULT_HOSTNAME="amazon_se"
++CONFIG_SYSVIPC=y
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE="../root-lantiq/ ../root-lantiq/initramfs-base-files.txt"
++CONFIG_INITRAMFS_ROOT_UID=1000
++CONFIG_INITRAMFS_ROOT_GID=1000
+++# CONFIG_RD_GZIP is not set
++CONFIG_RD_LZMA=y
++CONFIG_EMBEDDED=y
++CONFIG_SLAB=y
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_DEFAULT_DEADLINE=y
++CONFIG_NET=y
++CONFIG_PACKET=y
++CONFIG_UNIX=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_IP_ROUTE_MULTIPATH=y
++CONFIG_IP_ROUTE_VERBOSE=y
++CONFIG_IP_MROUTE=y
++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
++CONFIG_ARPD=y
++CONFIG_SYN_COOKIES=y
++CONFIG_NETFILTER=y
++CONFIG_BRIDGE=m
++CONFIG_VLAN_8021Q=y
++CONFIG_NET_SCHED=y
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_MTD=y
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++CONFIG_MTD_CFI=y
++CONFIG_MTD_CFI_ADV_OPTIONS=y
++CONFIG_MTD_CFI_GEOMETRY=y
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_CFI_AMDSTD=y
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++CONFIG_MTD_LANTIQ=y
++CONFIG_MISC_DEVICES=y
++CONFIG_NETDEVICES=y
++CONFIG_MII=y
++CONFIG_LANTIQ_ETOP=y
++CONFIG_PHYLIB=y
++CONFIG_SERIAL_LANTIQ=y
++CONFIG_PINCTRL=y
++CONFIG_GPIO_SYSFS=y
++CONFIG_WATCHDOG=y
++CONFIG_LANTIQ_WDT=y
++CONFIG_TMPFS=y
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_SUMMARY=y
++CONFIG_JFFS2_FS_XATTR=y
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_SQUASHFS=y
++CONFIG_SQUASHFS_XZ=y
++CONFIG_STRIP_ASM_SYMS=y
++CONFIG_DEBUG_FS=y
+diff --git a/arch/mips/configs/falcon_defconfig b/arch/mips/configs/falcon_defconfig
+new file mode 100644
+index 0000000..ce242a8
+--- /dev/null
++++ b/arch/mips/configs/falcon_defconfig
+@@ -0,0 +1,72 @@
++CONFIG_LANTIQ=y
++CONFIG_SOC_FALCON=y
++CONFIG_CPU_MIPS32_R2=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_EXPERIMENTAL=y
++CONFIG_DEFAULT_HOSTNAME="falcon"
++CONFIG_SYSVIPC=y
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE="../root-lantiq/ ../root-lantiq/initramfs-base-files.txt"
++CONFIG_INITRAMFS_ROOT_UID=1000
++CONFIG_INITRAMFS_ROOT_GID=1000
+++# CONFIG_RD_GZIP is not set
++CONFIG_RD_LZMA=y
++CONFIG_EMBEDDED=y
++CONFIG_SLAB=y
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_DEFAULT_DEADLINE=y
++CONFIG_NET=y
++CONFIG_PACKET=y
++CONFIG_UNIX=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_IP_ROUTE_MULTIPATH=y
++CONFIG_IP_ROUTE_VERBOSE=y
++CONFIG_IP_MROUTE=y
++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
++CONFIG_ARPD=y
++CONFIG_SYN_COOKIES=y
++CONFIG_NETFILTER=y
++CONFIG_BRIDGE=m
++CONFIG_VLAN_8021Q=y
++CONFIG_NET_SCHED=y
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_MTD=y
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++CONFIG_MTD_CFI=y
++CONFIG_MTD_CFI_ADV_OPTIONS=y
++CONFIG_MTD_CFI_GEOMETRY=y
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_CFI_AMDSTD=y
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++CONFIG_MTD_LANTIQ=y
++CONFIG_MTD_M25P80=y
++CONFIG_MISC_DEVICES=y
++CONFIG_EEPROM_AT24=y
++CONFIG_NETDEVICES=y
++CONFIG_MII=y
++CONFIG_PHYLIB=y
++CONFIG_SERIAL_LANTIQ=y
++CONFIG_I2C=y
++CONFIG_I2C_FALCON=y
++CONFIG_SPI=y
++CONFIG_SPI_FALCON=y
++CONFIG_PINCTRL=y
++CONFIG_GPIO_SYSFS=y
++CONFIG_WATCHDOG=y
++CONFIG_LANTIQ_WDT=y
++CONFIG_TMPFS=y
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_SUMMARY=y
++CONFIG_JFFS2_FS_XATTR=y
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_SQUASHFS=y
++CONFIG_SQUASHFS_XZ=y
++CONFIG_STRIP_ASM_SYMS=y
++CONFIG_DEBUG_FS=y
+diff --git a/arch/mips/configs/xway_defconfig b/arch/mips/configs/xway_defconfig
+new file mode 100644
+index 0000000..510a964
+--- /dev/null
++++ b/arch/mips/configs/xway_defconfig
+@@ -0,0 +1,66 @@
++CONFIG_LANTIQ=y
++CONFIG_CPU_MIPS32_R2=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_EXPERIMENTAL=y
++CONFIG_DEFAULT_HOSTNAME="danube"
++CONFIG_SYSVIPC=y
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE="../root-lantiq/ ../root-lantiq/initramfs-base-files.txt"
++CONFIG_INITRAMFS_ROOT_UID=1000
++CONFIG_INITRAMFS_ROOT_GID=1000
++# CONFIG_RD_GZIP is not set
++CONFIG_RD_LZMA=y
++CONFIG_EMBEDDED=y
++CONFIG_SLAB=y
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_DEFAULT_DEADLINE=y
++CONFIG_NET=y
++CONFIG_PACKET=y
++CONFIG_UNIX=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++CONFIG_IP_ADVANCED_ROUTER=y
++CONFIG_IP_MULTIPLE_TABLES=y
++CONFIG_IP_ROUTE_MULTIPATH=y
++CONFIG_IP_ROUTE_VERBOSE=y
++CONFIG_IP_MROUTE=y
++CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
++CONFIG_ARPD=y
++CONFIG_SYN_COOKIES=y
++CONFIG_NETFILTER=y
++CONFIG_BRIDGE=m
++CONFIG_VLAN_8021Q=y
++CONFIG_NET_SCHED=y
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_MTD=y
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++CONFIG_MTD_CFI=y
++CONFIG_MTD_CFI_ADV_OPTIONS=y
++CONFIG_MTD_CFI_GEOMETRY=y
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_CFI_AMDSTD=y
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++CONFIG_MTD_LANTIQ=y
++CONFIG_MISC_DEVICES=y
++CONFIG_NETDEVICES=y
++CONFIG_MII=y
++CONFIG_LANTIQ_ETOP=y
++CONFIG_PHYLIB=y
++CONFIG_SERIAL_LANTIQ=y
++CONFIG_PINCTRL=y
++CONFIG_GPIO_SYSFS=y
++CONFIG_WATCHDOG=y
++CONFIG_LANTIQ_WDT=y
++CONFIG_TMPFS=y
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_SUMMARY=y
++CONFIG_JFFS2_FS_XATTR=y
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_SQUASHFS=y
++CONFIG_SQUASHFS_XZ=y
++CONFIG_STRIP_ASM_SYMS=y
++CONFIG_DEBUG_FS=y
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0016-MAINTAINERS-add-entry-for-Lantiq-related-files.patch b/target/linux/lantiq/patches-3.2/0016-MAINTAINERS-add-entry-for-Lantiq-related-files.patch
new file mode 100644
index 0000000..9b8e324
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0016-MAINTAINERS-add-entry-for-Lantiq-related-files.patch
@@ -0,0 +1,38 @@
+From c68f8bdcd4c58a0c1d92e20230a943e8089d865a Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 10 Nov 2011 19:32:37 +0100
+Subject: [PATCH 16/70] MAINTAINERS: add entry for Lantiq related files
+
+Adds new entry to MAINTAINERS file for Lantiq SoC related code.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ MAINTAINERS | 12 ++++++++++++
+ 1 files changed, 12 insertions(+), 0 deletions(-)
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 62f1cd3..c04defd 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -4348,6 +4348,18 @@ S: Supported
+ F: Documentation/mips/
+ F: arch/mips/
+
++MIPS/LANTIQ
++M: John Crispin <blogic@openwrt.org>
++M: Thomas Langer <thomas.langer@lantiq.com>
++S: Maintained
++F: arch/mips/lantiq/*
++F: drivers/i2c/busses/i2c-falcon.c
++F: drivers/mtd/maps/lantiq-flash.c
++F: drivers/net/ethernet/lantiq_etop.c
++F: drivers/spi/spi-falcon.c
++F: drivers/tty/serial/lantiq.c
++F: drivers/watchdog/lantiq_wdt.c
++
+ MISCELLANEOUS MCA-SUPPORT
+ M: James Bottomley <James.Bottomley@HansenPartnership.com>
+ S: Maintained
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0017-MIPS-make-oprofile-use-cp0_perfcount_irq-if-it-is-se.patch b/target/linux/lantiq/patches-3.2/0017-MIPS-make-oprofile-use-cp0_perfcount_irq-if-it-is-se.patch
new file mode 100644
index 0000000..a879cd8
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0017-MIPS-make-oprofile-use-cp0_perfcount_irq-if-it-is-se.patch
@@ -0,0 +1,55 @@
+From bc3a07e6c5149a82a22239a43e9f98514c2010d9 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 24 Aug 2011 13:24:11 +0200
+Subject: [PATCH 17/70] MIPS: make oprofile use cp0_perfcount_irq if it is set
+
+The patch makes the oprofile code use the performance counters irq.
+
+This patch is written by Felix Fietkau.
+
+Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/oprofile/op_model_mipsxx.c | 12 ++++++++++++
+ 1 files changed, 12 insertions(+), 0 deletions(-)
+
+diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
+index 54759f1..86cf234 100644
+--- a/arch/mips/oprofile/op_model_mipsxx.c
++++ b/arch/mips/oprofile/op_model_mipsxx.c
+@@ -298,6 +298,11 @@ static void reset_counters(void *arg)
+ }
+ }
+
++static irqreturn_t mipsxx_perfcount_int(int irq, void *dev_id)
++{
++ return mipsxx_perfcount_handler();
++}
++
+ static int __init mipsxx_init(void)
+ {
+ int counters;
+@@ -374,6 +379,10 @@ static int __init mipsxx_init(void)
+ save_perf_irq = perf_irq;
+ perf_irq = mipsxx_perfcount_handler;
+
++ if (cp0_perfcount_irq >= 0)
++ return request_irq(cp0_perfcount_irq, mipsxx_perfcount_int,
++ IRQF_SHARED, "Perfcounter", save_perf_irq);
++
+ return 0;
+ }
+
+@@ -381,6 +390,9 @@ static void mipsxx_exit(void)
+ {
+ int counters = op_model_mipsxx_ops.num_counters;
+
++ if (cp0_perfcount_irq >= 0)
++ free_irq(cp0_perfcount_irq, save_perf_irq);
++
+ counters = counters_per_cpu_to_total(counters);
+ on_each_cpu(reset_counters, (void *)(long)counters, 1);
+
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0010-MIPS-enable-oprofile-support-on-lantiq-targets.patch b/target/linux/lantiq/patches-3.2/0018-MIPS-lantiq-enable-oprofile-support-on-lantiq-target.patch
index d051788..7ab5ff7 100644
--- a/target/linux/lantiq/patches/0010-MIPS-enable-oprofile-support-on-lantiq-targets.patch
+++ b/target/linux/lantiq/patches-3.2/0018-MIPS-lantiq-enable-oprofile-support-on-lantiq-target.patch
@@ -1,20 +1,23 @@
-From cc4b9cdff8665a414ae51101d3a0ca6ed7444a27 Mon Sep 17 00:00:00 2001
+From e0bd3f1b16fbce1f0f7900a0dd624f9dc8a47f78 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 24 Aug 2011 13:28:55 +0200
-Subject: [PATCH 10/24] MIPS: enable oprofile support on lantiq targets
+Subject: [PATCH 18/70] MIPS: lantiq: enable oprofile support on lantiq
+ targets
-This patch sets the performance counters irq and HAVE_OPROFILE flag.
+This patch sets the performance counters irq and HAVE_OPROFILE flag for Lantiq
+SoCs.
Signed-off-by: John Crispin <blogic@openwrt.org>
-Cc: linux-mips@linux-mips.org
---
arch/mips/Kconfig | 1 +
arch/mips/lantiq/irq.c | 5 +++++
2 files changed, 6 insertions(+), 0 deletions(-)
+diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
+index d46f1da..c1ceadb 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
-@@ -230,6 +230,7 @@ config LANTIQ
+@@ -226,6 +226,7 @@ config LANTIQ
select SWAP_IO_SPACE
select BOOT_RAW
select HAVE_CLK
@@ -22,6 +25,8 @@ Cc: linux-mips@linux-mips.org
select MIPS_MACHINE
config LASAT
+diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
+index 17c057f..0b2ed87 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -40,6 +40,9 @@
@@ -43,3 +48,6 @@ Cc: linux-mips@linux-mips.org
}
unsigned int __cpuinit get_c0_compare_int(void)
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0015-MIPS-lantiq-adds-etop-support-for-ase-ar9.patch b/target/linux/lantiq/patches-3.2/0019-NET-MIPS-lantiq-make-etop-ethernet-work-on-ase-ar9.patch
index 503c6bf..d7e2ed9 100644
--- a/target/linux/lantiq/patches/0015-MIPS-lantiq-adds-etop-support-for-ase-ar9.patch
+++ b/target/linux/lantiq/patches-3.2/0019-NET-MIPS-lantiq-make-etop-ethernet-work-on-ase-ar9.patch
@@ -1,25 +1,26 @@
-From c7881d8d2b3aed9a90aa37dcf797328a9cfbe7b6 Mon Sep 17 00:00:00 2001
+From 4b24c79196e5777baff0f5d53b62cf2a964e26ff Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 10 Aug 2011 15:32:16 +0200
-Subject: [PATCH 15/24] MIPS: lantiq: adds etop support for ase/ar9
+Subject: [PATCH 19/70] NET: MIPS: lantiq: make etop ethernet work on ase/ar9
Extend the driver to handle the different DMA channel layout for AR9 and
-SoCs. The patch also adds support for the integrated PHY found on Amazon-SE
-and the gigabit switch found inside the AR9.
+Amazon-SE SoCs. The patch also adds support for the integrated PHY found
+on Amazon-SE and the gigabit switch found inside the AR9.
Signed-off-by: John Crispin <blogic@openwrt.org>
-Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
+Cc: netdev@vger.kernel.org
---
.../mips/include/asm/mach-lantiq/xway/lantiq_irq.h | 22 +---
.../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 10 ++
arch/mips/lantiq/xway/devices.c | 11 +-
- arch/mips/lantiq/xway/mach-easy50601.c | 5 +
- drivers/net/lantiq_etop.c | 172 ++++++++++++++++++--
- 5 files changed, 180 insertions(+), 40 deletions(-)
+ drivers/net/ethernet/lantiq_etop.c | 171 ++++++++++++++++++--
+ 4 files changed, 174 insertions(+), 40 deletions(-)
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
+index b4465a8..2a8d5ad 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
-@@ -40,26 +40,8 @@
+@@ -38,26 +38,8 @@
#define MIPS_CPU_TIMER_IRQ 7
@@ -48,17 +49,19 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
#define LTQ_PPE_MBOX_INT (INT_NUM_IM2_IRL0 + 24)
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index e31f52d..6983d75 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
-@@ -80,6 +80,7 @@
+@@ -82,6 +82,7 @@
#define LTQ_PMU_SIZE 0x1000
#define PMU_DMA 0x0020
+#define PMU_EPHY 0x0080
#define PMU_USB 0x8041
- #define PMU_SPI 0x0100
#define PMU_LED 0x0800
-@@ -92,6 +93,10 @@
+ #define PMU_GPT 0x1000
+@@ -93,6 +94,10 @@
#define LTQ_ETOP_BASE_ADDR 0x1E180000
#define LTQ_ETOP_SIZE 0x40000
@@ -69,7 +72,7 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
/* DMA */
#define LTQ_DMA_BASE_ADDR 0x1E104100
#define LTQ_DMA_SIZE 0x800
-@@ -146,6 +151,11 @@ extern void ltq_pmu_enable(unsigned int
+@@ -147,6 +152,11 @@ extern void ltq_pmu_enable(unsigned int module);
extern void ltq_pmu_disable(unsigned int module);
extern void ltq_cgu_enable(unsigned int clk);
@@ -81,6 +84,8 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
static inline int ltq_is_ar9(void)
{
return (ltq_get_soc_type() == SOC_TYPE_AR9);
+diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
+index f97e565..eab4644d 100644
--- a/arch/mips/lantiq/xway/devices.c
+++ b/arch/mips/lantiq/xway/devices.c
@@ -74,18 +74,23 @@ void __init ltq_register_ase_asc(void)
@@ -110,23 +115,18 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
if (eth) {
ltq_etop.dev.platform_data = eth;
platform_device_register(&ltq_etop);
---- a/drivers/net/lantiq_etop.c
-+++ b/drivers/net/lantiq_etop.c
-@@ -34,6 +34,7 @@
- #include <linux/init.h>
- #include <linux/delay.h>
- #include <linux/io.h>
-+#include <linux/dma-mapping.h>
-
- #include <asm/checksum.h>
-
-@@ -69,10 +70,43 @@
+diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
+index 0b3567a..d3d4931 100644
+--- a/drivers/net/ethernet/lantiq_etop.c
++++ b/drivers/net/ethernet/lantiq_etop.c
+@@ -71,10 +71,43 @@
#define ETOP_MII_REVERSE 0xe
#define ETOP_PLEN_UNDER 0x40
#define ETOP_CGEN 0x800
-+#define ETOP_CFG_MII0 0x01
-
+-
-/* use 2 static channels for TX/RX */
++#define ETOP_CFG_MII0 0x01
++
+#define LTQ_GBIT_MDIO_CTL 0xCC
+#define LTQ_GBIT_MDIO_DATA 0xd0
+#define LTQ_GBIT_GCTL0 0x68
@@ -166,7 +166,7 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
#define IS_TX(x) (x == LTQ_ETOP_TX_CHANNEL)
#define IS_RX(x) (x == LTQ_ETOP_RX_CHANNEL)
-@@ -81,9 +115,15 @@
+@@ -83,9 +116,15 @@
#define ltq_etop_w32_mask(x, y, z) \
ltq_w32_mask(x, y, ltq_etop_membase + (z))
@@ -182,7 +182,7 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
struct ltq_etop_chan {
int idx;
-@@ -108,6 +148,9 @@ struct ltq_etop_priv {
+@@ -110,6 +149,9 @@ struct ltq_etop_priv {
spinlock_t lock;
};
@@ -192,7 +192,7 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
static int
ltq_etop_alloc_skb(struct ltq_etop_chan *ch)
{
-@@ -209,7 +252,7 @@ static irqreturn_t
+@@ -211,7 +253,7 @@ static irqreturn_t
ltq_etop_dma_irq(int irq, void *_priv)
{
struct ltq_etop_priv *priv = _priv;
@@ -201,7 +201,7 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
napi_schedule(&priv->ch[ch].napi);
return IRQ_HANDLED;
-@@ -242,26 +285,66 @@ ltq_etop_hw_exit(struct net_device *dev)
+@@ -244,15 +286,43 @@ ltq_etop_hw_exit(struct net_device *dev)
ltq_etop_free_channel(dev, &priv->ch[i]);
}
@@ -210,8 +210,8 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
+{
+ ltq_pmu_enable(PMU_SWITCH);
+
-+ ltq_gpio_request(42, 1, 0, 1, "MDIO");
-+ ltq_gpio_request(43, 1, 0, 1, "MDC");
++ ltq_gpio_request(42, 2, 1, "MDIO");
++ ltq_gpio_request(43, 2, 1, "MDC");
+
+ ltq_gbit_w32_mask(0, GCTL0_SE, LTQ_GBIT_GCTL0);
+ /** Disable MDIO auto polling mode */
@@ -238,19 +238,15 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
- switch (priv->pldata->mii_mode) {
+ if (ltq_has_gbit()) {
+ ltq_etop_gbit_init();
++ /* force the etops link to the gbit to MII */
++ mii_mode = PHY_INTERFACE_MODE_MII;
+ }
+
+ switch (mii_mode) {
-+ case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RMII:
ltq_etop_w32_mask(ETOP_MII_MASK,
ETOP_MII_REVERSE, LTQ_ETOP_CFG);
- break;
-
-+ case PHY_INTERFACE_MODE_GMII:
- case PHY_INTERFACE_MODE_MII:
- ltq_etop_w32_mask(ETOP_MII_MASK,
- ETOP_MII_NORMAL, LTQ_ETOP_CFG);
+@@ -264,6 +334,18 @@ ltq_etop_hw_init(struct net_device *dev)
break;
default:
@@ -269,7 +265,7 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
netdev_err(dev, "unknown mii mode %d\n",
priv->pldata->mii_mode);
return -ENOTSUPP;
-@@ -273,7 +356,7 @@ ltq_etop_hw_init(struct net_device *dev)
+@@ -275,7 +357,7 @@ ltq_etop_hw_init(struct net_device *dev)
ltq_dma_init_port(DMA_PORT_ETOP);
for (i = 0; i < MAX_DMA_CHAN; i++) {
@@ -278,7 +274,7 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
struct ltq_etop_chan *ch = &priv->ch[i];
ch->idx = ch->dma.nr = i;
-@@ -337,6 +420,39 @@ static const struct ethtool_ops ltq_etop
+@@ -339,6 +421,39 @@ static const struct ethtool_ops ltq_etop_ethtool_ops = {
};
static int
@@ -318,7 +314,7 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data)
{
u32 val = MDIO_REQUEST |
-@@ -377,14 +493,11 @@ ltq_etop_mdio_probe(struct net_device *d
+@@ -379,14 +494,11 @@ ltq_etop_mdio_probe(struct net_device *dev)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
struct phy_device *phydev = NULL;
@@ -337,7 +333,7 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
if (!phydev) {
netdev_err(dev, "no PHY found\n");
-@@ -406,6 +519,9 @@ ltq_etop_mdio_probe(struct net_device *d
+@@ -408,6 +520,9 @@ ltq_etop_mdio_probe(struct net_device *dev)
| SUPPORTED_Autoneg
| SUPPORTED_MII
| SUPPORTED_TP);
@@ -347,7 +343,7 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
phydev->advertising = phydev->supported;
priv->phydev = phydev;
-@@ -431,8 +547,13 @@ ltq_etop_mdio_init(struct net_device *de
+@@ -433,8 +548,13 @@ ltq_etop_mdio_init(struct net_device *dev)
}
priv->mii_bus->priv = dev;
@@ -363,7 +359,7 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
priv->mii_bus->name = "ltq_mii";
snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
priv->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
-@@ -522,9 +643,9 @@ ltq_etop_tx(struct sk_buff *skb, struct
+@@ -524,9 +644,9 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
struct ltq_etop_priv *priv = netdev_priv(dev);
struct ltq_etop_chan *ch = &priv->ch[(queue << 1) | 1];
struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
@@ -374,7 +370,7 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
-@@ -698,7 +819,7 @@ ltq_etop_probe(struct platform_device *p
+@@ -700,7 +820,7 @@ ltq_etop_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct ltq_etop_priv *priv;
@@ -383,7 +379,7 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
int err;
int i;
-@@ -726,6 +847,23 @@ ltq_etop_probe(struct platform_device *p
+@@ -728,6 +848,23 @@ ltq_etop_probe(struct platform_device *pdev)
goto err_out;
}
@@ -407,3 +403,6 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
strcpy(dev->name, "eth%d");
dev->netdev_ops = &ltq_eth_netdev_ops;
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0020-NET-MIPS-lantiq-non-existing-phy-was-not-handled-gra.patch b/target/linux/lantiq/patches-3.2/0020-NET-MIPS-lantiq-non-existing-phy-was-not-handled-gra.patch
new file mode 100644
index 0000000..c0cc3d6
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0020-NET-MIPS-lantiq-non-existing-phy-was-not-handled-gra.patch
@@ -0,0 +1,67 @@
+From d9cddd0b4062e66f350297b4b855ef4db3a1c16b Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 15 Nov 2011 14:52:21 +0100
+Subject: [PATCH 20/70] NET: MIPS: lantiq: non existing phy was not handled
+ gracefully
+
+The code blindly assumed that that a PHY device was present causing a BadVA.
+In addition the driver should not fail to load incase no PHY was found.
+Instead we print the following line and continue with no attached PHY.
+
+ etop: mdio probe failed
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Cc: netdev@vger.kernel.org
+---
+ drivers/net/ethernet/lantiq_etop.c | 14 ++++++++------
+ 1 files changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
+index d3d4931..9fd6779 100644
+--- a/drivers/net/ethernet/lantiq_etop.c
++++ b/drivers/net/ethernet/lantiq_etop.c
+@@ -612,7 +612,8 @@ ltq_etop_open(struct net_device *dev)
+ ltq_dma_open(&ch->dma);
+ napi_enable(&ch->napi);
+ }
+- phy_start(priv->phydev);
++ if (priv->phydev)
++ phy_start(priv->phydev);
+ netif_tx_start_all_queues(dev);
+ return 0;
+ }
+@@ -624,7 +625,8 @@ ltq_etop_stop(struct net_device *dev)
+ int i;
+
+ netif_tx_stop_all_queues(dev);
+- phy_stop(priv->phydev);
++ if (priv->phydev)
++ phy_stop(priv->phydev);
+ for (i = 0; i < MAX_DMA_CHAN; i++) {
+ struct ltq_etop_chan *ch = &priv->ch[i];
+
+@@ -770,9 +772,10 @@ ltq_etop_init(struct net_device *dev)
+ if (err)
+ goto err_netdev;
+ ltq_etop_set_multicast_list(dev);
+- err = ltq_etop_mdio_init(dev);
+- if (err)
+- goto err_netdev;
++ if (!ltq_etop_mdio_init(dev))
++ dev->ethtool_ops = &ltq_etop_ethtool_ops;
++ else
++ pr_warn("etop: mdio probe failed\n");;
+ return 0;
+
+ err_netdev:
+@@ -868,7 +871,6 @@ ltq_etop_probe(struct platform_device *pdev)
+ dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
+ strcpy(dev->name, "eth%d");
+ dev->netdev_ops = &ltq_eth_netdev_ops;
+- dev->ethtool_ops = &ltq_etop_ethtool_ops;
+ priv = netdev_priv(dev);
+ priv->res = res;
+ priv->pldata = dev_get_platdata(&pdev->dev);
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0021-NET-MIPS-lantiq-return-value-of-request_irq-was-not-.patch b/target/linux/lantiq/patches-3.2/0021-NET-MIPS-lantiq-return-value-of-request_irq-was-not-.patch
new file mode 100644
index 0000000..f27ebfb
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0021-NET-MIPS-lantiq-return-value-of-request_irq-was-not-.patch
@@ -0,0 +1,71 @@
+From 6916ef9742e45213d524b69700d937976098d1e6 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 15 Nov 2011 15:56:06 +0100
+Subject: [PATCH 21/70] NET: MIPS: lantiq: return value of request_irq was not
+ handled gracefully
+
+The return values of request_irq() were not checked leading to the following
+error message.
+
+drivers/net/ethernet/lantiq_etop.c: In function 'ltq_etop_hw_init':
+drivers/net/ethernet/lantiq_etop.c:368:15: warning: ignoring return value of 'request_irq', declared with attribute warn_unused_result
+drivers/net/ethernet/lantiq_etop.c:377:15: warning: ignoring return value of 'request_irq', declared with attribute warn_unused_result
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Cc: netdev@vger.kernel.org
+---
+ drivers/net/ethernet/lantiq_etop.c | 14 ++++++++------
+ 1 files changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
+index 9fd6779..dddb9fe 100644
+--- a/drivers/net/ethernet/lantiq_etop.c
++++ b/drivers/net/ethernet/lantiq_etop.c
+@@ -312,6 +312,7 @@ ltq_etop_hw_init(struct net_device *dev)
+ {
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ unsigned int mii_mode = priv->pldata->mii_mode;
++ int err = 0;
+ int i;
+
+ ltq_pmu_enable(PMU_PPE);
+@@ -356,7 +357,7 @@ ltq_etop_hw_init(struct net_device *dev)
+
+ ltq_dma_init_port(DMA_PORT_ETOP);
+
+- for (i = 0; i < MAX_DMA_CHAN; i++) {
++ for (i = 0; i < MAX_DMA_CHAN && !err; i++) {
+ int irq = LTQ_DMA_ETOP + i;
+ struct ltq_etop_chan *ch = &priv->ch[i];
+
+@@ -364,21 +365,22 @@ ltq_etop_hw_init(struct net_device *dev)
+
+ if (IS_TX(i)) {
+ ltq_dma_alloc_tx(&ch->dma);
+- request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
++ err = request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
+ "etop_tx", priv);
+ } else if (IS_RX(i)) {
+ ltq_dma_alloc_rx(&ch->dma);
+ for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
+ ch->dma.desc++)
+ if (ltq_etop_alloc_skb(ch))
+- return -ENOMEM;
++ err = -ENOMEM;
+ ch->dma.desc = 0;
+- request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
++ err = request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
+ "etop_rx", priv);
+ }
+- ch->dma.irq = irq;
++ if (!err)
++ ch->dma.irq = irq;
+ }
+- return 0;
++ return err;
+ }
+
+ static void
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0022-MIPS-lantiq-use-devres-managed-gpios.patch b/target/linux/lantiq/patches-3.2/0022-MIPS-lantiq-use-devres-managed-gpios.patch
new file mode 100644
index 0000000..0d4a927
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0022-MIPS-lantiq-use-devres-managed-gpios.patch
@@ -0,0 +1,282 @@
+From 9819317c005d57e1a5924af1faa43f73ed156a2d Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Mar 2012 08:37:25 +0100
+Subject: [PATCH 22/70] MIPS: lantiq: use devres managed gpios
+
+3.2 introduced devm_request_gpio() to allow managed gpios.
+
+The devres api requires a struct device pointer to work. Add a parameter to ltq_gpio_request()
+so that managed gpios can work.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ .../include/asm/mach-lantiq/falcon/lantiq_soc.h | 4 +---
+ arch/mips/include/asm/mach-lantiq/lantiq.h | 4 ++++
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 3 ---
+ arch/mips/lantiq/falcon/gpio.c | 4 ++--
+ arch/mips/lantiq/falcon/prom.c | 7 -------
+ arch/mips/lantiq/xway/gpio.c | 4 ++--
+ arch/mips/lantiq/xway/gpio_stp.c | 13 ++++++++-----
+ arch/mips/pci/pci-lantiq.c | 18 ++++++++++--------
+ drivers/net/ethernet/lantiq_etop.c | 9 ++++++---
+ drivers/tty/serial/lantiq.c | 12 ++++++++++++
+ 10 files changed, 45 insertions(+), 33 deletions(-)
+
+diff --git a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
+index b074748..a5dc06a 100644
+--- a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
+@@ -126,9 +126,7 @@ extern __iomem void *ltq_sys1_membase;
+ #define ltq_sys1_w32_mask(clear, set, reg) \
+ ltq_sys1_w32((ltq_sys1_r32(reg) & ~(clear)) | (set), reg)
+
+-/* gpio_request wrapper to help configure the pin */
+-extern int ltq_gpio_request(unsigned int pin, unsigned int mux,
+- unsigned int dir, const char *name);
++/* gpio wrapper to help configure the pin muxing */
+ extern int ltq_gpio_mux_set(unsigned int pin, unsigned int mux);
+
+ /* to keep the irq code generic we need to define these to 0 as falcon
+diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h
+index 188de0f..924b91a 100644
+--- a/arch/mips/include/asm/mach-lantiq/lantiq.h
++++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
+@@ -37,6 +37,10 @@ extern unsigned int ltq_get_soc_type(void);
+ /* spinlock all ebu i/o */
+ extern spinlock_t ebu_lock;
+
++/* request a non-gpio and set the PIO config */
++extern int ltq_gpio_request(struct device *dev, unsigned int pin,
++ unsigned int mux, unsigned int dir, const char *name);
++
+ /* some irq helpers */
+ extern void ltq_disable_irq(struct irq_data *data);
+ extern void ltq_mask_and_ack_irq(struct irq_data *data);
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index 6983d75..6c5b705 100644
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -145,9 +145,6 @@
+ extern __iomem void *ltq_ebu_membase;
+ extern __iomem void *ltq_cgu_membase;
+
+-/* request a non-gpio and set the PIO config */
+-extern int ltq_gpio_request(unsigned int pin, unsigned int mux,
+- unsigned int dir, const char *name);
+ extern void ltq_pmu_enable(unsigned int module);
+ extern void ltq_pmu_disable(unsigned int module);
+ extern void ltq_cgu_enable(unsigned int clk);
+diff --git a/arch/mips/lantiq/falcon/gpio.c b/arch/mips/lantiq/falcon/gpio.c
+index 28f8639..a44f71b 100644
+--- a/arch/mips/lantiq/falcon/gpio.c
++++ b/arch/mips/lantiq/falcon/gpio.c
+@@ -97,7 +97,7 @@ int ltq_gpio_mux_set(unsigned int pin, unsigned int mux)
+ }
+ EXPORT_SYMBOL(ltq_gpio_mux_set);
+
+-int ltq_gpio_request(unsigned int pin, unsigned int mux,
++int ltq_gpio_request(struct device *dev, unsigned int pin, unsigned int mux,
+ unsigned int dir, const char *name)
+ {
+ int port = pin / 100;
+@@ -106,7 +106,7 @@ int ltq_gpio_request(unsigned int pin, unsigned int mux,
+ if (offset >= PINS_PER_PORT || port >= MAX_PORTS)
+ return -EINVAL;
+
+- if (gpio_request(pin, name)) {
++ if (devm_gpio_request(dev, pin, name)) {
+ pr_err("failed to setup lantiq gpio: %s\n", name);
+ return -EBUSY;
+ }
+diff --git a/arch/mips/lantiq/falcon/prom.c b/arch/mips/lantiq/falcon/prom.c
+index b50d6f9..f98b389 100644
+--- a/arch/mips/lantiq/falcon/prom.c
++++ b/arch/mips/lantiq/falcon/prom.c
+@@ -27,9 +27,6 @@
+ #define TYPE_SHIFT 26
+ #define TYPE_MASK 0x3C000000
+
+-#define MUXC_SIF_RX_PIN 112
+-#define MUXC_SIF_TX_PIN 113
+-
+ /* this parameter allows us enable/disable asc1 via commandline */
+ static int register_asc1;
+ static int __init
+@@ -48,10 +45,6 @@ ltq_soc_setup(void)
+ falcon_register_gpio();
+ if (register_asc1) {
+ ltq_register_asc(1);
+- if (ltq_gpio_request(MUXC_SIF_RX_PIN, 3, 0, "asc1-rx"))
+- pr_err("failed to request asc1-rx");
+- if (ltq_gpio_request(MUXC_SIF_TX_PIN, 3, 1, "asc1-tx"))
+- pr_err("failed to request asc1-tx");
+ ltq_sysctl_activate(SYSCTL_SYS1, ACTS_ASC1_ACT);
+ }
+ }
+diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c
+index 14ff7c7..54ec6c9 100644
+--- a/arch/mips/lantiq/xway/gpio.c
++++ b/arch/mips/lantiq/xway/gpio.c
+@@ -50,14 +50,14 @@ int irq_to_gpio(unsigned int gpio)
+ }
+ EXPORT_SYMBOL(irq_to_gpio);
+
+-int ltq_gpio_request(unsigned int pin, unsigned int mux,
++int ltq_gpio_request(struct device *dev, unsigned int pin, unsigned int mux,
+ unsigned int dir, const char *name)
+ {
+ int id = 0;
+
+ if (pin >= (MAX_PORTS * PINS_PER_PORT))
+ return -EINVAL;
+- if (gpio_request(pin, name)) {
++ if (devm_gpio_request(dev, pin, name)) {
+ pr_err("failed to setup lantiq gpio: %s\n", name);
+ return -EBUSY;
+ }
+diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
+index cb6f170..e6b4809 100644
+--- a/arch/mips/lantiq/xway/gpio_stp.c
++++ b/arch/mips/lantiq/xway/gpio_stp.c
+@@ -80,11 +80,6 @@ static struct gpio_chip ltq_stp_chip = {
+
+ static int ltq_stp_hw_init(void)
+ {
+- /* the 3 pins used to control the external stp */
+- ltq_gpio_request(4, 2, 1, "stp-st");
+- ltq_gpio_request(5, 2, 1, "stp-d");
+- ltq_gpio_request(6, 2, 1, "stp-sh");
+-
+ /* sane defaults */
+ ltq_stp_w32(0, LTQ_STP_AR);
+ ltq_stp_w32(0, LTQ_STP_CPU0);
+@@ -133,6 +128,14 @@ static int __devinit ltq_stp_probe(struct platform_device *pdev)
+ dev_err(&pdev->dev, "failed to remap STP memory\n");
+ return -ENOMEM;
+ }
++
++ /* the 3 pins used to control the external stp */
++ if (ltq_gpio_request(&pdev->dev, 4, 2, 1, "stp-st") ||
++ ltq_gpio_request(&pdev->dev, 5, 2, 1, "stp-d") ||
++ ltq_gpio_request(&pdev->dev, 6, 2, 1, "stp-sh")) {
++ dev_err(&pdev->dev, "failed to request needed gpios\n");
++ return -EBUSY;
++ }
+ ret = gpiochip_add(&ltq_stp_chip);
+ if (!ret)
+ ret = ltq_stp_hw_init();
+diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c
+index c001c5a..47b551c 100644
+--- a/arch/mips/pci/pci-lantiq.c
++++ b/arch/mips/pci/pci-lantiq.c
+@@ -150,24 +150,26 @@ static u32 ltq_calc_bar11mask(void)
+ return bar11mask;
+ }
+
+-static void ltq_pci_setup_gpio(int gpio)
++static void ltq_pci_setup_gpio(struct device *dev)
+ {
++ struct ltq_pci_data *conf = (struct ltq_pci_data *) dev->platform_data;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(ltq_pci_gpio_map); i++) {
+- if (gpio & (1 << i)) {
+- ltq_gpio_request(ltq_pci_gpio_map[i].pin,
++ if (conf->gpio & (1 << i)) {
++ ltq_gpio_request(dev, ltq_pci_gpio_map[i].pin,
+ ltq_pci_gpio_map[i].mux,
+ ltq_pci_gpio_map[i].dir,
+ ltq_pci_gpio_map[i].name);
+ }
+ }
+- ltq_gpio_request(21, 0, 1, "pci-reset");
+- ltq_pci_req_mask = (gpio >> PCI_REQ_SHIFT) & PCI_REQ_MASK;
++ ltq_gpio_request(dev, 21, 0, 1, "pci-reset");
++ ltq_pci_req_mask = (conf->gpio >> PCI_REQ_SHIFT) & PCI_REQ_MASK;
+ }
+
+-static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
++static int __devinit ltq_pci_startup(struct device *dev)
+ {
+ u32 temp_buffer;
++ struct ltq_pci_data *conf = (struct ltq_pci_data *) dev->platform_data;
+
+ /* set clock to 33Mhz */
+ if (ltq_is_ar9()) {
+@@ -190,7 +192,7 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
+ }
+
+ /* setup pci clock and gpis used by pci */
+- ltq_pci_setup_gpio(conf->gpio);
++ ltq_pci_setup_gpio(dev);
+
+ /* enable auto-switching between PCI and EBU */
+ ltq_pci_w32(0xa, PCI_CR_CLK_CTRL);
+@@ -275,7 +277,7 @@ static int __devinit ltq_pci_probe(struct platform_device *pdev)
+ ioremap_nocache(LTQ_PCI_CFG_BASE, LTQ_PCI_CFG_BASE);
+ ltq_pci_controller.io_map_base =
+ (unsigned long)ioremap(LTQ_PCI_IO_BASE, LTQ_PCI_IO_SIZE - 1);
+- ltq_pci_startup(ltq_pci_data);
++ ltq_pci_startup(&pdev->dev);
+ register_pci_controller(&ltq_pci_controller);
+
+ return 0;
+diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
+index dddb9fe..fcbb9c7 100644
+--- a/drivers/net/ethernet/lantiq_etop.c
++++ b/drivers/net/ethernet/lantiq_etop.c
+@@ -291,9 +291,6 @@ ltq_etop_gbit_init(void)
+ {
+ ltq_pmu_enable(PMU_SWITCH);
+
+- ltq_gpio_request(42, 2, 1, "MDIO");
+- ltq_gpio_request(43, 2, 1, "MDC");
+-
+ ltq_gbit_w32_mask(0, GCTL0_SE, LTQ_GBIT_GCTL0);
+ /** Disable MDIO auto polling mode */
+ ltq_gbit_w32_mask(0, PX_CTL_DMDIO, LTQ_GBIT_P0_CTL);
+@@ -868,6 +865,12 @@ ltq_etop_probe(struct platform_device *pdev)
+ err = -ENOMEM;
+ goto err_out;
+ }
++ if (ltq_gpio_request(&pdev->dev, 42, 2, 1, "MDIO") ||
++ ltq_gpio_request(&pdev->dev, 43, 2, 1, "MDC")) {
++ dev_err(&pdev->dev, "failed to request MDIO gpios\n");
++ err = -EBUSY;
++ goto err_out;
++ }
+ }
+
+ dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
+diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
+index 96c1cac..5d25828 100644
+--- a/drivers/tty/serial/lantiq.c
++++ b/drivers/tty/serial/lantiq.c
+@@ -107,6 +107,9 @@
+ #define ASCFSTAT_TXFREEMASK 0x3F000000
+ #define ASCFSTAT_TXFREEOFF 24
+
++#define MUXC_SIF_RX_PIN 112
++#define MUXC_SIF_TX_PIN 113
++
+ static void lqasc_tx_chars(struct uart_port *port);
+ static struct ltq_uart_port *lqasc_port[MAXPORTS];
+ static struct uart_driver lqasc_reg;
+@@ -529,6 +532,15 @@ lqasc_request_port(struct uart_port *port)
+ if (port->membase == NULL)
+ return -ENOMEM;
+ }
++ if (ltq_is_falcon() && (port->line == 1)) {
++ struct ltq_uart_port *ltq_port = lqasc_port[pdev->id];
++ if (ltq_gpio_request(&pdev->dev, MUXC_SIF_RX_PIN,
++ 3, 0, "asc1-rx"))
++ return -EBUSY;
++ if (ltq_gpio_request(&pdev->dev, MUXC_SIF_TX_PIN,
++ 3, 1, "asc1-tx"))
++ return -EBUSY;
++ }
+ return 0;
+ }
+
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0023-MIPS-add-clkdev.h.patch b/target/linux/lantiq/patches-3.2/0023-MIPS-add-clkdev.h.patch
new file mode 100644
index 0000000..f668638
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0023-MIPS-add-clkdev.h.patch
@@ -0,0 +1,49 @@
+From aeb5a729386db036163fa21a8f5e5e1f9a735ebf Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 16 Feb 2012 20:23:36 +0100
+Subject: [PATCH 23/70] MIPS: add clkdev.h
+
+For clkdev to work on MIPS we need this file
+
+include/linux/clkdev.h:#include <asm/clkdev.h>
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/include/asm/clkdev.h | 25 +++++++++++++++++++++++++
+ 1 files changed, 25 insertions(+), 0 deletions(-)
+ create mode 100644 arch/mips/include/asm/clkdev.h
+
+diff --git a/arch/mips/include/asm/clkdev.h b/arch/mips/include/asm/clkdev.h
+new file mode 100644
+index 0000000..2624754
+--- /dev/null
++++ b/arch/mips/include/asm/clkdev.h
+@@ -0,0 +1,25 @@
++/*
++ * based on arch/arm/include/asm/clkdev.h
++ *
++ * Copyright (C) 2008 Russell King.
++ *
++ * 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.
++ *
++ * Helper for the clk API to assist looking up a struct clk.
++ */
++#ifndef __ASM_CLKDEV_H
++#define __ASM_CLKDEV_H
++
++#include <linux/slab.h>
++
++#define __clk_get(clk) ({ 1; })
++#define __clk_put(clk) do { } while (0)
++
++static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
++{
++ return kzalloc(size, GFP_KERNEL);
++}
++
++#endif
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0024-MIPS-lantiq-helper-functions-for-SoC-detection.patch b/target/linux/lantiq/patches-3.2/0024-MIPS-lantiq-helper-functions-for-SoC-detection.patch
new file mode 100644
index 0000000..8fbb2c2
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0024-MIPS-lantiq-helper-functions-for-SoC-detection.patch
@@ -0,0 +1,59 @@
+From 8b47a5997efb253459fa62acce9c52202cbec9da Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 21 Feb 2012 14:25:03 +0100
+Subject: [PATCH 24/70] MIPS: lantiq: helper functions for SoC detection
+
+Add additional functions for runtime soc detection. We need these for the
+serial driver.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ .../include/asm/mach-lantiq/falcon/lantiq_soc.h | 16 ++++++++++++++--
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 5 +++++
+ 2 files changed, 19 insertions(+), 2 deletions(-)
+
+diff --git a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
+index a5dc06a..0aa1f16 100644
+--- a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
+@@ -134,8 +134,20 @@ extern int ltq_gpio_mux_set(unsigned int pin, unsigned int mux);
+ #define LTQ_EIU_BASE_ADDR 0
+ #define LTQ_EBU_PCC_ISTAT 0
+
+-#define ltq_is_ar9() 0
+-#define ltq_is_vr9() 0
++static inline int ltq_is_ar9(void)
++{
++ return 0;
++}
++
++static inline int ltq_is_vr9(void)
++{
++ return 0;
++}
++
++static inline int ltq_is_falcon(void)
++{
++ return 1;
++}
+
+ #endif /* CONFIG_SOC_FALCON */
+ #endif /* _LTQ_XWAY_H__ */
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index 6c5b705..45e480c 100644
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -164,5 +164,10 @@ static inline int ltq_is_vr9(void)
+ return (ltq_get_soc_type() == SOC_TYPE_VR9);
+ }
+
++static inline int ltq_is_falcon(void)
++{
++ return 0;
++}
++
+ #endif /* CONFIG_SOC_TYPE_XWAY */
+ #endif /* _LTQ_XWAY_H__ */
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0025-MIPS-lantiq-convert-to-clkdev-api.patch b/target/linux/lantiq/patches-3.2/0025-MIPS-lantiq-convert-to-clkdev-api.patch
new file mode 100644
index 0000000..cad0a99
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0025-MIPS-lantiq-convert-to-clkdev-api.patch
@@ -0,0 +1,299 @@
+From 25db3804c7c9ed3ee5161b00b38de84b1d19f6a8 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Mar 2012 08:39:06 +0100
+Subject: [PATCH 25/70] MIPS: lantiq: convert to clkdev api
+
+* Change setup from HAVE_CLK -> HAVE_MACH_CLKDEV/CLKDEV_LOOKUP
+* Add clk_activate/clk_deactivate
+* Add better error paths to the clk_*() functions
+* Change the way our static clocks are referenced
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/Kconfig | 3 +-
+ arch/mips/include/asm/mach-lantiq/lantiq.h | 20 ++----
+ arch/mips/lantiq/clk.c | 96 +++++++++++++++------------
+ arch/mips/lantiq/clk.h | 52 ++++++++++++++-
+ arch/mips/lantiq/prom.c | 1 -
+ 5 files changed, 111 insertions(+), 61 deletions(-)
+
+diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
+index c1ceadb..1b78cd7 100644
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -225,7 +225,8 @@ config LANTIQ
+ select ARCH_REQUIRE_GPIOLIB
+ select SWAP_IO_SPACE
+ select BOOT_RAW
+- select HAVE_CLK
++ select HAVE_MACH_CLKDEV
++ select CLKDEV_LOOKUP
+ select HAVE_OPROFILE
+ select MIPS_MACHINE
+
+diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h
+index 924b91a..622847f 100644
+--- a/arch/mips/include/asm/mach-lantiq/lantiq.h
++++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
+@@ -9,6 +9,7 @@
+ #define _LANTIQ_H__
+
+ #include <linux/irq.h>
++#include <linux/clk.h>
+ #include <linux/ioport.h>
+
+ /* generic reg access functions */
+@@ -22,18 +23,6 @@
+ extern unsigned int ltq_get_cpu_ver(void);
+ extern unsigned int ltq_get_soc_type(void);
+
+-/* clock speeds */
+-#define CLOCK_60M 60000000
+-#define CLOCK_83M 83333333
+-#define CLOCK_100M 100000000
+-#define CLOCK_111M 111111111
+-#define CLOCK_133M 133333333
+-#define CLOCK_167M 166666667
+-#define CLOCK_200M 200000000
+-#define CLOCK_266M 266666666
+-#define CLOCK_333M 333333333
+-#define CLOCK_400M 400000000
+-
+ /* spinlock all ebu i/o */
+ extern spinlock_t ebu_lock;
+
+@@ -46,6 +35,13 @@ extern void ltq_disable_irq(struct irq_data *data);
+ extern void ltq_mask_and_ack_irq(struct irq_data *data);
+ extern void ltq_enable_irq(struct irq_data *data);
+
++/* clock handling */
++extern int clk_activate(struct clk *clk);
++extern void clk_deactivate(struct clk *clk);
++extern struct clk *clk_get_cpu(void);
++extern struct clk *clk_get_fpi(void);
++extern struct clk *clk_get_io(void);
++
+ /* find out what caused the last cpu reset */
+ extern int ltq_reset_cause(void);
+
+diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
+index 39eef7f..84a201e 100644
+--- a/arch/mips/lantiq/clk.c
++++ b/arch/mips/lantiq/clk.c
+@@ -12,6 +12,7 @@
+ #include <linux/kernel.h>
+ #include <linux/types.h>
+ #include <linux/clk.h>
++#include <linux/clkdev.h>
+ #include <linux/err.h>
+ #include <linux/list.h>
+
+@@ -24,33 +25,29 @@
+ #include "clk.h"
+ #include "prom.h"
+
+-struct clk {
+- const char *name;
+- unsigned long rate;
+- unsigned long (*get_rate) (void);
+-};
++/* lantiq socs have 3 static clocks */
++static struct clk cpu_clk_generic[3];
+
+-static struct clk *cpu_clk;
+-static int cpu_clk_cnt;
++void clkdev_add_static(unsigned long cpu, unsigned long fpi, unsigned long io)
++{
++ cpu_clk_generic[0].rate = cpu;
++ cpu_clk_generic[1].rate = fpi;
++ cpu_clk_generic[2].rate = io;
++}
+
+-/* lantiq socs have 3 static clocks */
+-static struct clk cpu_clk_generic[] = {
+- {
+- .name = "cpu",
+- .get_rate = ltq_get_cpu_hz,
+- }, {
+- .name = "fpi",
+- .get_rate = ltq_get_fpi_hz,
+- }, {
+- .name = "io",
+- .get_rate = ltq_get_io_region_clock,
+- },
+-};
+-
+-void clk_init(void)
++struct clk *clk_get_cpu(void)
++{
++ return &cpu_clk_generic[0];
++}
++
++struct clk *clk_get_fpi(void)
+ {
+- cpu_clk = cpu_clk_generic;
+- cpu_clk_cnt = ARRAY_SIZE(cpu_clk_generic);
++ return &cpu_clk_generic[1];
++}
++
++struct clk *clk_get_io(void)
++{
++ return &cpu_clk_generic[2];
+ }
+
+ static inline int clk_good(struct clk *clk)
+@@ -73,36 +70,49 @@ unsigned long clk_get_rate(struct clk *clk)
+ }
+ EXPORT_SYMBOL(clk_get_rate);
+
+-struct clk *clk_get(struct device *dev, const char *id)
++int clk_enable(struct clk *clk)
+ {
+- int i;
++ if (unlikely(!clk_good(clk)))
++ return -1;
++
++ if (clk->enable)
++ return clk->enable(clk);
+
+- for (i = 0; i < cpu_clk_cnt; i++)
+- if (!strcmp(id, cpu_clk[i].name))
+- return &cpu_clk[i];
+- BUG();
+- return ERR_PTR(-ENOENT);
++ return -1;
+ }
+-EXPORT_SYMBOL(clk_get);
++EXPORT_SYMBOL(clk_enable);
+
+-void clk_put(struct clk *clk)
++void clk_disable(struct clk *clk)
+ {
+- /* not used */
++ if (unlikely(!clk_good(clk)))
++ return;
++
++ if (clk->disable)
++ clk->disable(clk);
+ }
+-EXPORT_SYMBOL(clk_put);
++EXPORT_SYMBOL(clk_disable);
+
+-int clk_enable(struct clk *clk)
++int clk_activate(struct clk *clk)
+ {
+- /* not used */
+- return 0;
++ if (unlikely(!clk_good(clk)))
++ return -1;
++
++ if (clk->activate)
++ return clk->activate(clk);
++
++ return -1;
+ }
+-EXPORT_SYMBOL(clk_enable);
++EXPORT_SYMBOL(clk_activate);
+
+-void clk_disable(struct clk *clk)
++void clk_deactivate(struct clk *clk)
+ {
+- /* not used */
++ if (unlikely(!clk_good(clk)))
++ return;
++
++ if (clk->deactivate)
++ clk->deactivate(clk);
+ }
+-EXPORT_SYMBOL(clk_disable);
++EXPORT_SYMBOL(clk_deactivate);
+
+ static inline u32 ltq_get_counter_resolution(void)
+ {
+@@ -126,7 +136,7 @@ void __init plat_time_init(void)
+
+ ltq_soc_init();
+
+- clk = clk_get(0, "cpu");
++ clk = clk_get_cpu();
+ mips_hpt_frequency = clk_get_rate(clk) / ltq_get_counter_resolution();
+ write_c0_compare(read_c0_count());
+ pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
+diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h
+index 3328925..d047768 100644
+--- a/arch/mips/lantiq/clk.h
++++ b/arch/mips/lantiq/clk.h
+@@ -9,10 +9,54 @@
+ #ifndef _LTQ_CLK_H__
+ #define _LTQ_CLK_H__
+
+-extern void clk_init(void);
++#include <linux/clkdev.h>
+
+-extern unsigned long ltq_get_cpu_hz(void);
+-extern unsigned long ltq_get_fpi_hz(void);
+-extern unsigned long ltq_get_io_region_clock(void);
++/* clock speeds */
++#define CLOCK_60M 60000000
++#define CLOCK_62_5M 62500000
++#define CLOCK_83M 83333333
++#define CLOCK_83_5M 83500000
++#define CLOCK_98_304M 98304000
++#define CLOCK_100M 100000000
++#define CLOCK_111M 111111111
++#define CLOCK_125M 125000000
++#define CLOCK_133M 133333333
++#define CLOCK_150M 150000000
++#define CLOCK_166M 166666666
++#define CLOCK_167M 166666667
++#define CLOCK_196_608M 196608000
++#define CLOCK_200M 200000000
++#define CLOCK_250M 250000000
++#define CLOCK_266M 266666666
++#define CLOCK_300M 300000000
++#define CLOCK_333M 333333333
++#define CLOCK_393M 393215332
++#define CLOCK_400M 400000000
++#define CLOCK_500M 500000000
++#define CLOCK_600M 600000000
++
++struct clk {
++ struct clk_lookup cl;
++ unsigned long rate;
++ unsigned long (*get_rate) (void);
++ unsigned int module;
++ unsigned int bits;
++ int (*enable) (struct clk *clk);
++ void (*disable) (struct clk *clk);
++ int (*activate) (struct clk *clk);
++ void (*deactivate) (struct clk *clk);
++ void (*reboot) (struct clk *clk);
++};
++
++extern void clkdev_add_static(unsigned long cpu, unsigned long fpi,
++ unsigned long io);
++
++extern unsigned long ltq_danube_cpu_hz(void);
++extern unsigned long ltq_danube_fpi_hz(void);
++extern unsigned long ltq_danube_io_region_clock(void);
++
++extern unsigned long ltq_vr9_cpu_hz(void);
++extern unsigned long ltq_vr9_fpi_hz(void);
++extern unsigned long ltq_vr9_io_region_clock(void);
+
+ #endif
+diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
+index acb8921..971554b 100644
+--- a/arch/mips/lantiq/prom.c
++++ b/arch/mips/lantiq/prom.c
+@@ -103,7 +103,6 @@ EXPORT_SYMBOL(ltq_remap_resource);
+ void __init prom_init(void)
+ {
+ ltq_soc_detect(&soc_info);
+- clk_init();
+ snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev %s",
+ soc_info.name, soc_info.rev_type);
+ soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0026-MIPS-lantiq-convert-xway-to-clkdev-api.patch b/target/linux/lantiq/patches-3.2/0026-MIPS-lantiq-convert-xway-to-clkdev-api.patch
new file mode 100644
index 0000000..c35f230
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0026-MIPS-lantiq-convert-xway-to-clkdev-api.patch
@@ -0,0 +1,736 @@
+From 418e330dc60aaabdb5cf4509ec08cce07d63f32e Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Mar 2012 11:18:22 +0100
+Subject: [PATCH 26/70] MIPS: lantiq: convert xway to clkdev api
+
+Unify xway/ase clock code and add clkdev hooks to sysctrl.c
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 13 --
+ arch/mips/lantiq/xway/Makefile | 6 +-
+ arch/mips/lantiq/xway/clk-ase.c | 48 ----
+ arch/mips/lantiq/xway/clk-xway.c | 223 -------------------
+ arch/mips/lantiq/xway/clk.c | 227 ++++++++++++++++++++
+ arch/mips/lantiq/xway/sysctrl.c | 104 ++++++++-
+ 6 files changed, 325 insertions(+), 296 deletions(-)
+ delete mode 100644 arch/mips/lantiq/xway/clk-ase.c
+ delete mode 100644 arch/mips/lantiq/xway/clk-xway.c
+ create mode 100644 arch/mips/lantiq/xway/clk.c
+
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index 45e480c..e9d2dd4 100644
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -81,15 +81,6 @@
+ #define LTQ_PMU_BASE_ADDR 0x1F102000
+ #define LTQ_PMU_SIZE 0x1000
+
+-#define PMU_DMA 0x0020
+-#define PMU_EPHY 0x0080
+-#define PMU_USB 0x8041
+-#define PMU_LED 0x0800
+-#define PMU_GPT 0x1000
+-#define PMU_PPE 0x2000
+-#define PMU_FPI 0x4000
+-#define PMU_SWITCH 0x10000000
+-
+ /* ETOP - ethernet */
+ #define LTQ_ETOP_BASE_ADDR 0x1E180000
+ #define LTQ_ETOP_SIZE 0x40000
+@@ -145,10 +136,6 @@
+ extern __iomem void *ltq_ebu_membase;
+ extern __iomem void *ltq_cgu_membase;
+
+-extern void ltq_pmu_enable(unsigned int module);
+-extern void ltq_pmu_disable(unsigned int module);
+-extern void ltq_cgu_enable(unsigned int clk);
+-
+ static inline int ltq_is_ase(void)
+ {
+ return (ltq_get_soc_type() == SOC_TYPE_AMAZON_SE);
+diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
+index 6678402..4dcb96f 100644
+--- a/arch/mips/lantiq/xway/Makefile
++++ b/arch/mips/lantiq/xway/Makefile
+@@ -1,7 +1,7 @@
+-obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o
++obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o
+
+-obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
+-obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
++obj-$(CONFIG_SOC_XWAY) += prom-xway.o
++obj-$(CONFIG_SOC_AMAZON_SE) += prom-ase.o
+
+ obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
+ obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
+diff --git a/arch/mips/lantiq/xway/clk-ase.c b/arch/mips/lantiq/xway/clk-ase.c
+deleted file mode 100644
+index 6522583..0000000
+--- a/arch/mips/lantiq/xway/clk-ase.c
++++ /dev/null
+@@ -1,48 +0,0 @@
+-/*
+- * 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.
+- *
+- * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+- */
+-
+-#include <linux/io.h>
+-#include <linux/export.h>
+-#include <linux/init.h>
+-#include <linux/clk.h>
+-
+-#include <asm/time.h>
+-#include <asm/irq.h>
+-#include <asm/div64.h>
+-
+-#include <lantiq_soc.h>
+-
+-/* cgu registers */
+-#define LTQ_CGU_SYS 0x0010
+-
+-unsigned int ltq_get_io_region_clock(void)
+-{
+- return CLOCK_133M;
+-}
+-EXPORT_SYMBOL(ltq_get_io_region_clock);
+-
+-unsigned int ltq_get_fpi_bus_clock(int fpi)
+-{
+- return CLOCK_133M;
+-}
+-EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
+-
+-unsigned int ltq_get_cpu_hz(void)
+-{
+- if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5))
+- return CLOCK_266M;
+- else
+- return CLOCK_133M;
+-}
+-EXPORT_SYMBOL(ltq_get_cpu_hz);
+-
+-unsigned int ltq_get_fpi_hz(void)
+-{
+- return CLOCK_133M;
+-}
+-EXPORT_SYMBOL(ltq_get_fpi_hz);
+diff --git a/arch/mips/lantiq/xway/clk-xway.c b/arch/mips/lantiq/xway/clk-xway.c
+deleted file mode 100644
+index 696b1a3..0000000
+--- a/arch/mips/lantiq/xway/clk-xway.c
++++ /dev/null
+@@ -1,223 +0,0 @@
+-/*
+- * 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.
+- *
+- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+- */
+-
+-#include <linux/io.h>
+-#include <linux/export.h>
+-#include <linux/init.h>
+-#include <linux/clk.h>
+-
+-#include <asm/time.h>
+-#include <asm/irq.h>
+-#include <asm/div64.h>
+-
+-#include <lantiq_soc.h>
+-
+-static unsigned int ltq_ram_clocks[] = {
+- CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
+-#define DDR_HZ ltq_ram_clocks[ltq_cgu_r32(LTQ_CGU_SYS) & 0x3]
+-
+-#define BASIC_FREQUENCY_1 35328000
+-#define BASIC_FREQUENCY_2 36000000
+-#define BASIS_REQUENCY_USB 12000000
+-
+-#define GET_BITS(x, msb, lsb) \
+- (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
+-
+-#define LTQ_CGU_PLL0_CFG 0x0004
+-#define LTQ_CGU_PLL1_CFG 0x0008
+-#define LTQ_CGU_PLL2_CFG 0x000C
+-#define LTQ_CGU_SYS 0x0010
+-#define LTQ_CGU_UPDATE 0x0014
+-#define LTQ_CGU_IF_CLK 0x0018
+-#define LTQ_CGU_OSC_CON 0x001C
+-#define LTQ_CGU_SMD 0x0020
+-#define LTQ_CGU_CT1SR 0x0028
+-#define LTQ_CGU_CT2SR 0x002C
+-#define LTQ_CGU_PCMCR 0x0030
+-#define LTQ_CGU_PCI_CR 0x0034
+-#define LTQ_CGU_PD_PC 0x0038
+-#define LTQ_CGU_FMR 0x003C
+-
+-#define CGU_PLL0_PHASE_DIVIDER_ENABLE \
+- (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 31))
+-#define CGU_PLL0_BYPASS \
+- (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 30))
+-#define CGU_PLL0_CFG_DSMSEL \
+- (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 28))
+-#define CGU_PLL0_CFG_FRAC_EN \
+- (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 27))
+-#define CGU_PLL1_SRC \
+- (ltq_cgu_r32(LTQ_CGU_PLL1_CFG) & (1 << 31))
+-#define CGU_PLL2_PHASE_DIVIDER_ENABLE \
+- (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & (1 << 20))
+-#define CGU_SYS_FPI_SEL (1 << 6)
+-#define CGU_SYS_DDR_SEL 0x3
+-#define CGU_PLL0_SRC (1 << 29)
+-
+-#define CGU_PLL0_CFG_PLLK GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 26, 17)
+-#define CGU_PLL0_CFG_PLLN GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 12, 6)
+-#define CGU_PLL0_CFG_PLLM GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 5, 2)
+-#define CGU_PLL2_SRC GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 18, 17)
+-#define CGU_PLL2_CFG_INPUT_DIV GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 16, 13)
+-
+-static unsigned int ltq_get_pll0_fdiv(void);
+-
+-static inline unsigned int get_input_clock(int pll)
+-{
+- switch (pll) {
+- case 0:
+- if (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & CGU_PLL0_SRC)
+- return BASIS_REQUENCY_USB;
+- else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
+- return BASIC_FREQUENCY_1;
+- else
+- return BASIC_FREQUENCY_2;
+- case 1:
+- if (CGU_PLL1_SRC)
+- return BASIS_REQUENCY_USB;
+- else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
+- return BASIC_FREQUENCY_1;
+- else
+- return BASIC_FREQUENCY_2;
+- case 2:
+- switch (CGU_PLL2_SRC) {
+- case 0:
+- return ltq_get_pll0_fdiv();
+- case 1:
+- return CGU_PLL2_PHASE_DIVIDER_ENABLE ?
+- BASIC_FREQUENCY_1 :
+- BASIC_FREQUENCY_2;
+- case 2:
+- return BASIS_REQUENCY_USB;
+- }
+- default:
+- return 0;
+- }
+-}
+-
+-static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den)
+-{
+- u64 res, clock = get_input_clock(pll);
+-
+- res = num * clock;
+- do_div(res, den);
+- return res;
+-}
+-
+-static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N,
+- unsigned int K)
+-{
+- unsigned int num = ((N + 1) << 10) + K;
+- unsigned int den = (M + 1) << 10;
+-
+- return cal_dsm(pll, num, den);
+-}
+-
+-static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N,
+- unsigned int K)
+-{
+- unsigned int num = ((N + 1) << 11) + K + 512;
+- unsigned int den = (M + 1) << 11;
+-
+- return cal_dsm(pll, num, den);
+-}
+-
+-static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N,
+- unsigned int K)
+-{
+- unsigned int num = K >= 512 ?
+- ((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
+- unsigned int den = (M + 1) << 12;
+-
+- return cal_dsm(pll, num, den);
+-}
+-
+-static inline unsigned int dsm(int pll, unsigned int M, unsigned int N,
+- unsigned int K, unsigned int dsmsel, unsigned int phase_div_en)
+-{
+- if (!dsmsel)
+- return mash_dsm(pll, M, N, K);
+- else if (!phase_div_en)
+- return mash_dsm(pll, M, N, K);
+- else
+- return ssff_dsm_2(pll, M, N, K);
+-}
+-
+-static inline unsigned int ltq_get_pll0_fosc(void)
+-{
+- if (CGU_PLL0_BYPASS)
+- return get_input_clock(0);
+- else
+- return !CGU_PLL0_CFG_FRAC_EN
+- ? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0,
+- CGU_PLL0_CFG_DSMSEL,
+- CGU_PLL0_PHASE_DIVIDER_ENABLE)
+- : dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN,
+- CGU_PLL0_CFG_PLLK, CGU_PLL0_CFG_DSMSEL,
+- CGU_PLL0_PHASE_DIVIDER_ENABLE);
+-}
+-
+-static unsigned int ltq_get_pll0_fdiv(void)
+-{
+- unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1;
+-
+- return (ltq_get_pll0_fosc() + (div >> 1)) / div;
+-}
+-
+-unsigned int ltq_get_io_region_clock(void)
+-{
+- unsigned int ret = ltq_get_pll0_fosc();
+-
+- switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
+- default:
+- case 0:
+- return (ret + 1) / 2;
+- case 1:
+- return (ret * 2 + 2) / 5;
+- case 2:
+- return (ret + 1) / 3;
+- case 3:
+- return (ret + 2) / 4;
+- }
+-}
+-EXPORT_SYMBOL(ltq_get_io_region_clock);
+-
+-unsigned int ltq_get_fpi_bus_clock(int fpi)
+-{
+- unsigned int ret = ltq_get_io_region_clock();
+-
+- if ((fpi == 2) && (ltq_cgu_r32(LTQ_CGU_SYS) & CGU_SYS_FPI_SEL))
+- ret >>= 1;
+- return ret;
+-}
+-EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
+-
+-unsigned int ltq_get_cpu_hz(void)
+-{
+- switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) {
+- case 0:
+- return CLOCK_333M;
+- case 4:
+- return DDR_HZ;
+- case 8:
+- return DDR_HZ << 1;
+- default:
+- return DDR_HZ >> 1;
+- }
+-}
+-EXPORT_SYMBOL(ltq_get_cpu_hz);
+-
+-unsigned int ltq_get_fpi_hz(void)
+-{
+- unsigned int ddr_clock = DDR_HZ;
+-
+- if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
+- return ddr_clock >> 1;
+- return ddr_clock;
+-}
+-EXPORT_SYMBOL(ltq_get_fpi_hz);
+diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c
+new file mode 100644
+index 0000000..f3b50fc
+--- /dev/null
++++ b/arch/mips/lantiq/xway/clk.c
+@@ -0,0 +1,227 @@
++/*
++ * 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.
++ *
++ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/io.h>
++#include <linux/export.h>
++#include <linux/init.h>
++#include <linux/clk.h>
++
++#include <asm/time.h>
++#include <asm/irq.h>
++#include <asm/div64.h>
++
++#include <lantiq_soc.h>
++
++#include "../clk.h"
++
++static unsigned int ltq_ram_clocks[] = {
++ CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
++#define DDR_HZ ltq_ram_clocks[ltq_cgu_r32(LTQ_CGU_SYS) & 0x3]
++
++#define BASIC_FREQUENCY_1 35328000
++#define BASIC_FREQUENCY_2 36000000
++#define BASIS_REQUENCY_USB 12000000
++
++#define GET_BITS(x, msb, lsb) \
++ (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
++
++/* legacy xway clock */
++#define LTQ_CGU_PLL0_CFG 0x0004
++#define LTQ_CGU_PLL1_CFG 0x0008
++#define LTQ_CGU_PLL2_CFG 0x000C
++#define LTQ_CGU_SYS 0x0010
++#define LTQ_CGU_UPDATE 0x0014
++#define LTQ_CGU_IF_CLK 0x0018
++#define LTQ_CGU_OSC_CON 0x001C
++#define LTQ_CGU_SMD 0x0020
++#define LTQ_CGU_CT1SR 0x0028
++#define LTQ_CGU_CT2SR 0x002C
++#define LTQ_CGU_PCMCR 0x0030
++#define LTQ_CGU_PCI_CR 0x0034
++#define LTQ_CGU_PD_PC 0x0038
++#define LTQ_CGU_FMR 0x003C
++
++#define CGU_PLL0_PHASE_DIVIDER_ENABLE \
++ (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 31))
++#define CGU_PLL0_BYPASS \
++ (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 30))
++#define CGU_PLL0_CFG_DSMSEL \
++ (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 28))
++#define CGU_PLL0_CFG_FRAC_EN \
++ (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 27))
++#define CGU_PLL1_SRC \
++ (ltq_cgu_r32(LTQ_CGU_PLL1_CFG) & (1 << 31))
++#define CGU_PLL2_PHASE_DIVIDER_ENABLE \
++ (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & (1 << 20))
++#define CGU_SYS_FPI_SEL (1 << 6)
++#define CGU_SYS_DDR_SEL 0x3
++#define CGU_PLL0_SRC (1 << 29)
++
++#define CGU_PLL0_CFG_PLLK GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 26, 17)
++#define CGU_PLL0_CFG_PLLN GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 12, 6)
++#define CGU_PLL0_CFG_PLLM GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 5, 2)
++#define CGU_PLL2_SRC GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 18, 17)
++#define CGU_PLL2_CFG_INPUT_DIV GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 16, 13)
++
++/* vr9 clock */
++#define LTQ_CGU_SYS_VR9 0x0c
++#define LTQ_CGU_IF_CLK_VR9 0x24
++
++
++static unsigned int ltq_get_pll0_fdiv(void);
++
++static inline unsigned int get_input_clock(int pll)
++{
++ switch (pll) {
++ case 0:
++ if (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & CGU_PLL0_SRC)
++ return BASIS_REQUENCY_USB;
++ else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
++ return BASIC_FREQUENCY_1;
++ else
++ return BASIC_FREQUENCY_2;
++ case 1:
++ if (CGU_PLL1_SRC)
++ return BASIS_REQUENCY_USB;
++ else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
++ return BASIC_FREQUENCY_1;
++ else
++ return BASIC_FREQUENCY_2;
++ case 2:
++ switch (CGU_PLL2_SRC) {
++ case 0:
++ return ltq_get_pll0_fdiv();
++ case 1:
++ return CGU_PLL2_PHASE_DIVIDER_ENABLE ?
++ BASIC_FREQUENCY_1 :
++ BASIC_FREQUENCY_2;
++ case 2:
++ return BASIS_REQUENCY_USB;
++ }
++ default:
++ return 0;
++ }
++}
++
++static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den)
++{
++ u64 res, clock = get_input_clock(pll);
++
++ res = num * clock;
++ do_div(res, den);
++ return res;
++}
++
++static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N,
++ unsigned int K)
++{
++ unsigned int num = ((N + 1) << 10) + K;
++ unsigned int den = (M + 1) << 10;
++
++ return cal_dsm(pll, num, den);
++}
++
++static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N,
++ unsigned int K)
++{
++ unsigned int num = ((N + 1) << 11) + K + 512;
++ unsigned int den = (M + 1) << 11;
++
++ return cal_dsm(pll, num, den);
++}
++
++static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N,
++ unsigned int K)
++{
++ unsigned int num = K >= 512 ?
++ ((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
++ unsigned int den = (M + 1) << 12;
++
++ return cal_dsm(pll, num, den);
++}
++
++static inline unsigned int dsm(int pll, unsigned int M, unsigned int N,
++ unsigned int K, unsigned int dsmsel, unsigned int phase_div_en)
++{
++ if (!dsmsel)
++ return mash_dsm(pll, M, N, K);
++ else if (!phase_div_en)
++ return mash_dsm(pll, M, N, K);
++ else
++ return ssff_dsm_2(pll, M, N, K);
++}
++
++static inline unsigned int ltq_get_pll0_fosc(void)
++{
++ if (CGU_PLL0_BYPASS)
++ return get_input_clock(0);
++ else
++ return !CGU_PLL0_CFG_FRAC_EN
++ ? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0,
++ CGU_PLL0_CFG_DSMSEL,
++ CGU_PLL0_PHASE_DIVIDER_ENABLE)
++ : dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN,
++ CGU_PLL0_CFG_PLLK, CGU_PLL0_CFG_DSMSEL,
++ CGU_PLL0_PHASE_DIVIDER_ENABLE);
++}
++
++static unsigned int ltq_get_pll0_fdiv(void)
++{
++ unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1;
++
++ return (ltq_get_pll0_fosc() + (div >> 1)) / div;
++}
++
++unsigned long ltq_danube_io_region_clock(void)
++{
++ unsigned int ret = ltq_get_pll0_fosc();
++
++ switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
++ default:
++ case 0:
++ return (ret + 1) / 2;
++ case 1:
++ return (ret * 2 + 2) / 5;
++ case 2:
++ return (ret + 1) / 3;
++ case 3:
++ return (ret + 2) / 4;
++ }
++}
++
++unsigned long ltq_danube_fpi_bus_clock(int fpi)
++{
++ unsigned long ret = ltq_danube_io_region_clock();
++
++ if ((fpi == 2) && (ltq_cgu_r32(LTQ_CGU_SYS) & CGU_SYS_FPI_SEL))
++ ret >>= 1;
++ return ret;
++}
++
++unsigned long ltq_danube_cpu_hz(void)
++{
++ switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) {
++ case 0:
++ return CLOCK_333M;
++ case 4:
++ return DDR_HZ;
++ case 8:
++ return DDR_HZ << 1;
++ default:
++ return DDR_HZ >> 1;
++ }
++}
++
++unsigned long ltq_danube_fpi_hz(void)
++{
++ unsigned long ddr_clock = DDR_HZ;
++
++ if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
++ return ddr_clock >> 1;
++ return ddr_clock;
++}
+diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
+index 8fd13a1..c5782b5 100644
+--- a/arch/mips/lantiq/xway/sysctrl.c
++++ b/arch/mips/lantiq/xway/sysctrl.c
+@@ -8,17 +8,48 @@
+
+ #include <linux/ioport.h>
+ #include <linux/export.h>
++#include <linux/clkdev.h>
+
+ #include <lantiq_soc.h>
+
++#include "../clk.h"
+ #include "../devices.h"
+
+ /* clock control register */
+ #define LTQ_CGU_IFCCR 0x0018
++/* system clock register */
++#define LTQ_CGU_SYS 0x0010
+
+ /* the enable / disable registers */
+ #define LTQ_PMU_PWDCR 0x1C
+ #define LTQ_PMU_PWDSR 0x20
++#define LTQ_PMU_PWDCR1 0x24
++#define LTQ_PMU_PWDSR1 0x28
++
++#define PWDCR(x) ((x) ? (LTQ_PMU_PWDCR1) : (LTQ_PMU_PWDCR))
++#define PWDSR(x) ((x) ? (LTQ_PMU_PWDSR1) : (LTQ_PMU_PWDSR))
++
++/* CGU - clock generation unit */
++#define CGU_EPHY 0x10
++
++/* PMU - power management unit */
++#define PMU_DMA 0x0020
++#define PMU_SPI 0x0100
++#define PMU_EPHY 0x0080
++#define PMU_USB 0x8041
++#define PMU_STP 0x0800
++#define PMU_GPT 0x1000
++#define PMU_PPE 0x2000
++#define PMU_FPI 0x4000
++#define PMU_SWITCH 0x10000000
++#define PMU_AHBS 0x2000
++#define PMU_AHBM 0x8000
++#define PMU_PCIE_CLK 0x80000000
++
++#define PMU1_PCIE_PHY 0x0001
++#define PMU1_PCIE_CTL 0x0002
++#define PMU1_PCIE_MSI 0x0020
++#define PMU1_PCIE_PDI 0x0010
+
+ #define ltq_pmu_w32(x, y) ltq_w32((x), ltq_pmu_membase + (y))
+ #define ltq_pmu_r32(x) ltq_r32(ltq_pmu_membase + (x))
+@@ -36,28 +67,64 @@ void __iomem *ltq_cgu_membase;
+ void __iomem *ltq_ebu_membase;
+ static void __iomem *ltq_pmu_membase;
+
+-void ltq_cgu_enable(unsigned int clk)
++static int ltq_cgu_enable(struct clk *clk)
+ {
+- ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | clk, LTQ_CGU_IFCCR);
++ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | clk->bits, LTQ_CGU_IFCCR);
++ return 0;
+ }
+
+-void ltq_pmu_enable(unsigned int module)
++static void ltq_cgu_disable(struct clk *clk)
++{
++ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~clk->bits, LTQ_CGU_IFCCR);
++}
++
++static int ltq_pmu_enable(struct clk *clk)
+ {
+ int err = 1000000;
+
+- ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) & ~module, LTQ_PMU_PWDCR);
+- do {} while (--err && (ltq_pmu_r32(LTQ_PMU_PWDSR) & module));
++ ltq_pmu_w32(ltq_pmu_r32(PWDCR(clk->module)) & ~clk->bits,
++ PWDCR(clk->module));
++ do {} while (--err && (ltq_pmu_r32(PWDSR(clk->module)) & clk->bits));
+
+ if (!err)
+ panic("activating PMU module failed!\n");
++
++ return 0;
+ }
+-EXPORT_SYMBOL(ltq_pmu_enable);
+
+-void ltq_pmu_disable(unsigned int module)
++static void ltq_pmu_disable(struct clk *clk)
+ {
+- ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | module, LTQ_PMU_PWDCR);
++ ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | clk->bits, LTQ_PMU_PWDCR);
++}
++
++static inline void clkdev_add_pmu(const char *dev, const char *con,
++ unsigned int module, unsigned int bits)
++{
++ struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
++
++ clk->cl.dev_id = dev;
++ clk->cl.con_id = con;
++ clk->cl.clk = clk;
++ clk->enable = ltq_pmu_enable;
++ clk->disable = ltq_pmu_disable;
++ clk->module = module;
++ clk->bits = bits;
++ clkdev_add(&clk->cl);
++}
++
++static inline void clkdev_add_cgu(const char *dev, const char *con,
++ unsigned int bits)
++{
++ struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
++
++ clk->cl.dev_id = dev;
++ clk->cl.con_id = con;
++ clk->cl.clk = clk;
++ clk->enable = ltq_cgu_enable;
++ clk->disable = ltq_cgu_disable;
++ clk->bits = bits;
++ clkdev_add(&clk->cl);
+ }
+-EXPORT_SYMBOL(ltq_pmu_disable);
+
+ void __init ltq_soc_init(void)
+ {
+@@ -75,4 +142,23 @@ void __init ltq_soc_init(void)
+
+ /* make sure to unprotect the memory region where flash is located */
+ ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
++
++ /* add our clocks */
++ clkdev_add_pmu("ltq_dma", NULL, 0, PMU_DMA);
++ clkdev_add_pmu("ltq_stp", NULL, 0, PMU_STP);
++ clkdev_add_pmu("ltq_spi", NULL, 0, PMU_SPI);
++ clkdev_add_pmu("ltq_etop", NULL, 0, PMU_PPE);
++ if (ltq_is_ase()) {
++ if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5))
++ clkdev_add_static(CLOCK_266M, CLOCK_133M, CLOCK_133M);
++ else
++ clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M);
++ clkdev_add_cgu("ltq_etop", "ephycgu", CGU_EPHY),
++ clkdev_add_pmu("ltq_etop", "ephy", 0, PMU_EPHY);
++ } else {
++ clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
++ ltq_danube_io_region_clock());
++ if (ltq_is_ar9())
++ clkdev_add_pmu("ltq_etop", "switch", 0, PMU_SWITCH);
++ }
+ }
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0027-MIPS-lantiq-convert-falcon-to-clkdev-api.patch b/target/linux/lantiq/patches-3.2/0027-MIPS-lantiq-convert-falcon-to-clkdev-api.patch
new file mode 100644
index 0000000..83cd89e
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0027-MIPS-lantiq-convert-falcon-to-clkdev-api.patch
@@ -0,0 +1,244 @@
+From 07c4da1cf419022e5874c881511f051bb81e984e Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Mar 2012 11:19:11 +0100
+Subject: [PATCH 27/70] MIPS: lantiq: convert falcon to clkdev api
+
+Unify sysctrl/clock code and add clkdev hooks to sysctrl.c
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ .../include/asm/mach-lantiq/falcon/lantiq_soc.h | 8 +-
+ arch/mips/lantiq/falcon/Makefile | 2 +-
+ arch/mips/lantiq/falcon/sysctrl.c | 129 ++++++++++++--------
+ 3 files changed, 80 insertions(+), 59 deletions(-)
+
+diff --git a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
+index 0aa1f16..120c56c 100644
+--- a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
+@@ -95,6 +95,7 @@
+
+ /* Activation Status Register */
+ #define ACTS_ASC1_ACT 0x00000800
++#define ACTS_I2C_ACT 0x00004000
+ #define ACTS_P0 0x00010000
+ #define ACTS_P1 0x00010000
+ #define ACTS_P2 0x00020000
+@@ -106,13 +107,6 @@
+ #define ACTS_PADCTRL3 0x00200000
+ #define ACTS_PADCTRL4 0x00400000
+
+-extern void ltq_sysctl_activate(int module, unsigned int mask);
+-extern void ltq_sysctl_deactivate(int module, unsigned int mask);
+-extern void ltq_sysctl_clken(int module, unsigned int mask);
+-extern void ltq_sysctl_clkdis(int module, unsigned int mask);
+-extern void ltq_sysctl_reboot(int module, unsigned int mask);
+-extern int ltq_gpe_is_activated(unsigned int mask);
+-
+ /* global register ranges */
+ extern __iomem void *ltq_ebu_membase;
+ extern __iomem void *ltq_sys1_membase;
+diff --git a/arch/mips/lantiq/falcon/Makefile b/arch/mips/lantiq/falcon/Makefile
+index 56b22eb..3634154 100644
+--- a/arch/mips/lantiq/falcon/Makefile
++++ b/arch/mips/lantiq/falcon/Makefile
+@@ -1,2 +1,2 @@
+-obj-y := clk.o prom.o reset.o sysctrl.o devices.o gpio.o
++obj-y := prom.o reset.o sysctrl.o devices.o gpio.o
+ obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o
+diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c
+index 905a142..900f0e5 100644
+--- a/arch/mips/lantiq/falcon/sysctrl.c
++++ b/arch/mips/lantiq/falcon/sysctrl.c
+@@ -9,11 +9,13 @@
+
+ #include <linux/ioport.h>
+ #include <linux/export.h>
++#include <linux/clkdev.h>
+ #include <asm/delay.h>
+
+ #include <lantiq_soc.h>
+
+ #include "devices.h"
++#include "../clk.h"
+
+ /* infrastructure control register */
+ #define SYS1_INFRAC 0x00bc
+@@ -38,6 +40,10 @@
+ #define LTQ_SYSCTL_DEACT 0x0028
+ /* reboot Register */
+ #define LTQ_SYSCTL_RBT 0x002c
++/* CPU0 Clock Control Register */
++#define LTQ_SYS1_CPU0CC 0x0040
++/* clock divider bit */
++#define LTQ_CPU0CC_CPUDIV 0x0001
+
+ static struct resource ltq_sysctl_res[] = {
+ MEM_RES("sys1", LTQ_SYS1_BASE_ADDR, LTQ_SYS1_SIZE),
+@@ -64,79 +70,67 @@ void __iomem *ltq_ebu_membase;
+ #define ltq_status_r32(x) ltq_r32(ltq_status_membase + (x))
+
+ static inline void
+-ltq_sysctl_wait(int module, unsigned int mask,
++ltq_sysctl_wait(struct clk *clk,
+ unsigned int test, unsigned int reg)
+ {
+ int err = 1000000;
+
+- do {} while (--err && ((ltq_reg_r32(module, reg)
+- & mask) != test));
++ do {} while (--err && ((ltq_reg_r32(clk->module, reg)
++ & clk->bits) != test));
+ if (!err)
+- pr_err("module de/activation failed %d %08X %08X\n",
+- module, mask, test);
++ pr_err("module de/activation failed %d %08X %08X %08X\n",
++ clk->module, clk->bits, test,
++ ltq_reg_r32(clk->module, reg) & clk->bits);
+ }
+
+-void
+-ltq_sysctl_activate(int module, unsigned int mask)
++static int
++ltq_sysctl_activate(struct clk *clk)
+ {
+- if (module > SYSCTL_SYSGPE)
+- return;
+-
+- ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKEN);
+- ltq_reg_w32(module, mask, LTQ_SYSCTL_ACT);
+- ltq_sysctl_wait(module, mask, mask, LTQ_SYSCTL_ACTS);
++ ltq_reg_w32(clk->module, clk->bits, LTQ_SYSCTL_CLKEN);
++ ltq_reg_w32(clk->module, clk->bits, LTQ_SYSCTL_ACT);
++ ltq_sysctl_wait(clk, clk->bits, LTQ_SYSCTL_ACTS);
++ return 0;
+ }
+-EXPORT_SYMBOL(ltq_sysctl_activate);
+
+-void
+-ltq_sysctl_deactivate(int module, unsigned int mask)
++static void
++ltq_sysctl_deactivate(struct clk *clk)
+ {
+- if (module > SYSCTL_SYSGPE)
+- return;
+-
+- ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKCLR);
+- ltq_reg_w32(module, mask, LTQ_SYSCTL_DEACT);
+- ltq_sysctl_wait(module, mask, 0, LTQ_SYSCTL_ACTS);
++ ltq_reg_w32(clk->module, clk->bits, LTQ_SYSCTL_CLKCLR);
++ ltq_reg_w32(clk->module, clk->bits, LTQ_SYSCTL_DEACT);
++ ltq_sysctl_wait(clk, 0, LTQ_SYSCTL_ACTS);
+ }
+-EXPORT_SYMBOL(ltq_sysctl_deactivate);
+
+-void
+-ltq_sysctl_clken(int module, unsigned int mask)
++static int
++ltq_sysctl_clken(struct clk *clk)
+ {
+- if (module > SYSCTL_SYSGPE)
+- return;
+-
+- ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKEN);
+- ltq_sysctl_wait(module, mask, mask, LTQ_SYSCTL_CLKS);
++ ltq_reg_w32(clk->module, clk->bits, LTQ_SYSCTL_CLKEN);
++ ltq_sysctl_wait(clk, clk->bits, LTQ_SYSCTL_CLKS);
++ return 0;
+ }
+-EXPORT_SYMBOL(ltq_sysctl_clken);
+
+-void
+-ltq_sysctl_clkdis(int module, unsigned int mask)
++static void
++ltq_sysctl_clkdis(struct clk *clk)
+ {
+- if (module > SYSCTL_SYSGPE)
+- return;
+-
+- ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKCLR);
+- ltq_sysctl_wait(module, mask, 0, LTQ_SYSCTL_CLKS);
++ ltq_reg_w32(clk->module, clk->bits, LTQ_SYSCTL_CLKCLR);
++ ltq_sysctl_wait(clk, 0, LTQ_SYSCTL_CLKS);
+ }
+-EXPORT_SYMBOL(ltq_sysctl_clkdis);
+
+-void
+-ltq_sysctl_reboot(int module, unsigned int mask)
++static void
++ltq_sysctl_reboot(struct clk *clk)
+ {
+ unsigned int act;
+-
+- if (module > SYSCTL_SYSGPE)
+- return;
+-
+- act = ltq_reg_r32(module, LTQ_SYSCTL_ACT);
+- if ((~act & mask) != 0)
+- ltq_sysctl_activate(module, ~act & mask);
+- ltq_reg_w32(module, act & mask, LTQ_SYSCTL_RBT);
+- ltq_sysctl_wait(module, mask, mask, LTQ_SYSCTL_ACTS);
++ unsigned int bits;
++
++ act = ltq_reg_r32(clk->module, LTQ_SYSCTL_ACT);
++ bits = ~act & clk->bits;
++ if (bits != 0) {
++ ltq_reg_w32(clk->module, bits, LTQ_SYSCTL_CLKEN);
++ ltq_reg_w32(clk->module, bits, LTQ_SYSCTL_ACT);
++ ltq_sysctl_wait(clk, bits, LTQ_SYSCTL_ACTS);
++ }
++ ltq_reg_w32(clk->module, act & clk->bits, LTQ_SYSCTL_RBT);
++ ltq_sysctl_wait(clk, clk->bits, LTQ_SYSCTL_ACTS);
+ }
+-EXPORT_SYMBOL(ltq_sysctl_reboot);
+
+ /* enable the ONU core */
+ static void
+@@ -167,6 +161,24 @@ ltq_gpe_enable(void)
+ udelay(1);
+ }
+
++static inline void
++clkdev_add_sys(const char *dev, unsigned int module,
++ unsigned int bits)
++{
++ struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
++
++ clk->cl.dev_id = dev;
++ clk->cl.con_id = NULL;
++ clk->cl.clk = clk;
++ clk->module = module;
++ clk->activate = ltq_sysctl_activate;
++ clk->deactivate = ltq_sysctl_deactivate;
++ clk->enable = ltq_sysctl_clken;
++ clk->disable = ltq_sysctl_clkdis;
++ clk->reboot = ltq_sysctl_reboot;
++ clkdev_add(&clk->cl);
++}
++
+ void __init
+ ltq_soc_init(void)
+ {
+@@ -180,4 +192,19 @@ ltq_soc_init(void)
+ ltq_ebu_membase = ltq_remap_resource(&ltq_ebu_res);
+
+ ltq_gpe_enable();
++
++ /* get our 3 static rates for cpu, fpi and io clocks */
++ if (ltq_sys1_r32(LTQ_SYS1_CPU0CC) & LTQ_CPU0CC_CPUDIV)
++ clkdev_add_static(CLOCK_200M, CLOCK_100M, CLOCK_200M);
++ else
++ clkdev_add_static(CLOCK_400M, CLOCK_100M, CLOCK_200M);
++
++ /* add our clock domains */
++ clkdev_add_sys("falcon_gpio.0", SYSCTL_SYSETH, ACTS_PADCTRL0 | ACTS_P0);
++ clkdev_add_sys("falcon_gpio.1", SYSCTL_SYS1, ACTS_PADCTRL1 | ACTS_P1);
++ clkdev_add_sys("falcon_gpio.2", SYSCTL_SYSETH, ACTS_PADCTRL2 | ACTS_P2);
++ clkdev_add_sys("falcon_gpio.3", SYSCTL_SYS1, ACTS_PADCTRL3 | ACTS_P3);
++ clkdev_add_sys("falcon_gpio.4", SYSCTL_SYS1, ACTS_PADCTRL4 | ACTS_P4);
++ clkdev_add_sys("ltq_asc.1", SYSCTL_SYS1, ACTS_ASC1_ACT);
++ clkdev_add_sys("falcon_i2c", SYSCTL_SYS1, ACTS_I2C_ACT);
+ }
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0028-MIPS-lantiq-convert-dma-driver-to-clkdev-api.patch b/target/linux/lantiq/patches-3.2/0028-MIPS-lantiq-convert-dma-driver-to-clkdev-api.patch
new file mode 100644
index 0000000..6458af5
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0028-MIPS-lantiq-convert-dma-driver-to-clkdev-api.patch
@@ -0,0 +1,65 @@
+From e6a19ba12790d04267a9f052a3dc64fa1a8cac16 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Mar 2012 11:21:08 +0100
+Subject: [PATCH 28/70] MIPS: lantiq: convert dma driver to clkdev api
+
+Update from old pmu_{dis,en}able() to ckldev api.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/lantiq/xway/Makefile.rej | 11 +++++++++++
+ arch/mips/lantiq/xway/dma.c | 6 +++++-
+ 2 files changed, 16 insertions(+), 1 deletions(-)
+ create mode 100644 arch/mips/lantiq/xway/Makefile.rej
+
+diff --git a/arch/mips/lantiq/xway/Makefile.rej b/arch/mips/lantiq/xway/Makefile.rej
+new file mode 100644
+index 0000000..c0d5b52
+--- /dev/null
++++ b/arch/mips/lantiq/xway/Makefile.rej
+@@ -0,0 +1,11 @@
++--- arch/mips/lantiq/xway/Makefile
+++++ arch/mips/lantiq/xway/Makefile
++@@ -1,7 +1,4 @@
++-obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o
++-
++-obj-$(CONFIG_SOC_XWAY) += prom-xway.o
++-obj-$(CONFIG_SOC_AMAZON_SE) += prom-ase.o
+++obj-y := prom.o sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o
++
++ obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
++ obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
+diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
+index 60cd11f..388f1aa 100644
+--- a/arch/mips/lantiq/xway/dma.c
++++ b/arch/mips/lantiq/xway/dma.c
+@@ -20,6 +20,7 @@
+ #include <linux/io.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/export.h>
++#include <linux/clk.h>
+
+ #include <lantiq_soc.h>
+ #include <xway_dma.h>
+@@ -216,6 +217,7 @@ EXPORT_SYMBOL_GPL(ltq_dma_init_port);
+ int __init
+ ltq_dma_init(void)
+ {
++ struct clk *clk;
+ int i;
+
+ /* remap dma register range */
+@@ -224,7 +226,9 @@ ltq_dma_init(void)
+ panic("Failed to remap dma memory\n");
+
+ /* power up and reset the dma engine */
+- ltq_pmu_enable(PMU_DMA);
++ clk = clk_get_sys("ltq_dma", NULL);
++ WARN_ON(!clk);
++ clk_enable(clk);
+ ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL);
+
+ /* disable all interrupts */
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0029-MIPS-lantiq-convert-gpio_stp-driver-to-clkdev-api.patch b/target/linux/lantiq/patches-3.2/0029-MIPS-lantiq-convert-gpio_stp-driver-to-clkdev-api.patch
new file mode 100644
index 0000000..7b56c4f
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0029-MIPS-lantiq-convert-gpio_stp-driver-to-clkdev-api.patch
@@ -0,0 +1,60 @@
+From 81cf50fd6cfff13e06cd587094f5094dec32d57d Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Mar 2012 11:21:33 +0100
+Subject: [PATCH 29/70] MIPS: lantiq: convert gpio_stp driver to clkdev api
+
+Update from old pmu_{dis,en}able() to ckldev api.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/lantiq/xway/gpio_stp.c | 12 +++++++++---
+ 1 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
+index e6b4809..da91c5e 100644
+--- a/arch/mips/lantiq/xway/gpio_stp.c
++++ b/arch/mips/lantiq/xway/gpio_stp.c
+@@ -15,6 +15,8 @@
+ #include <linux/mutex.h>
+ #include <linux/io.h>
+ #include <linux/gpio.h>
++#include <linux/clk.h>
++#include <linux/err.h>
+
+ #include <lantiq_soc.h>
+
+@@ -78,8 +80,10 @@ static struct gpio_chip ltq_stp_chip = {
+ .owner = THIS_MODULE,
+ };
+
+-static int ltq_stp_hw_init(void)
++static int ltq_stp_hw_init(struct device *dev)
+ {
++ struct clk *clk;
++
+ /* sane defaults */
+ ltq_stp_w32(0, LTQ_STP_AR);
+ ltq_stp_w32(0, LTQ_STP_CPU0);
+@@ -105,7 +109,9 @@ static int ltq_stp_hw_init(void)
+ */
+ ltq_stp_w32_mask(0, LTQ_STP_ADSL_SRC, LTQ_STP_CON0);
+
+- ltq_pmu_enable(PMU_LED);
++ clk = clk_get(dev, NULL);
++ WARN_ON(IS_ERR(clk));
++ clk_enable(clk);
+ return 0;
+ }
+
+@@ -138,7 +144,7 @@ static int __devinit ltq_stp_probe(struct platform_device *pdev)
+ }
+ ret = gpiochip_add(&ltq_stp_chip);
+ if (!ret)
+- ret = ltq_stp_hw_init();
++ ret = ltq_stp_hw_init(&pdev->dev);
+
+ return ret;
+ }
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0030-MIPS-lantiq-convert-falcon-gpio-to-clkdev-api.patch b/target/linux/lantiq/patches-3.2/0030-MIPS-lantiq-convert-falcon-gpio-to-clkdev-api.patch
new file mode 100644
index 0000000..733112e
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0030-MIPS-lantiq-convert-falcon-gpio-to-clkdev-api.patch
@@ -0,0 +1,73 @@
+From 3cb13f9992ae1948b6ca05c88d2bd25cf9e7cd41 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Mar 2012 11:22:03 +0100
+Subject: [PATCH 30/70] MIPS: lantiq: convert falcon gpio to clkdev api
+
+The falcon gpio clocks used to be enabled when registering the platform device.
+Move this code into the driver and use clkdev api.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/lantiq/falcon/devices.c | 5 -----
+ arch/mips/lantiq/falcon/gpio.c | 10 ++++++++++
+ 2 files changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/arch/mips/lantiq/falcon/devices.c b/arch/mips/lantiq/falcon/devices.c
+index 4f47b44..6cd7a88 100644
+--- a/arch/mips/lantiq/falcon/devices.c
++++ b/arch/mips/lantiq/falcon/devices.c
+@@ -111,9 +111,6 @@ falcon_register_gpio(void)
+ falcon_gpio1_res, ARRAY_SIZE(falcon_gpio1_res));
+ platform_device_register_simple("falcon_gpio", 2,
+ falcon_gpio2_res, ARRAY_SIZE(falcon_gpio2_res));
+- ltq_sysctl_activate(SYSCTL_SYS1, ACTS_PADCTRL1 | ACTS_P1);
+- ltq_sysctl_activate(SYSCTL_SYSETH, ACTS_PADCTRL0 |
+- ACTS_PADCTRL2 | ACTS_P0 | ACTS_P2);
+ }
+
+ void __init
+@@ -123,6 +120,4 @@ falcon_register_gpio_extra(void)
+ falcon_gpio3_res, ARRAY_SIZE(falcon_gpio3_res));
+ platform_device_register_simple("falcon_gpio", 4,
+ falcon_gpio4_res, ARRAY_SIZE(falcon_gpio4_res));
+- ltq_sysctl_activate(SYSCTL_SYS1,
+- ACTS_PADCTRL3 | ACTS_PADCTRL4 | ACTS_P3 | ACTS_P4);
+ }
+diff --git a/arch/mips/lantiq/falcon/gpio.c b/arch/mips/lantiq/falcon/gpio.c
+index a44f71b..4147d61 100644
+--- a/arch/mips/lantiq/falcon/gpio.c
++++ b/arch/mips/lantiq/falcon/gpio.c
+@@ -11,6 +11,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/slab.h>
+ #include <linux/export.h>
++#include <linux/err.h>
+ #include <linux/platform_device.h>
+
+ #include <lantiq_soc.h>
+@@ -71,6 +72,7 @@ struct falcon_gpio_port {
+ void __iomem *port;
+ unsigned int irq_base;
+ unsigned int chained_irq;
++ struct clk *clk;
+ };
+
+ static struct falcon_gpio_port ltq_gpio_port[MAX_PORTS];
+@@ -332,6 +334,14 @@ falcon_gpio_probe(struct platform_device *pdev)
+ goto err;
+ }
+
++ gpio_port->clk = clk_get(&pdev->dev, NULL);
++ if (IS_ERR(gpio_port->clk)) {
++ dev_err(&pdev->dev, "Could not get clock\n");
++ ret = PTR_ERR(gpio_port->clk);;
++ goto err;
++ }
++ clk_enable(gpio_port->clk);
++
+ if (irq > 0) {
+ /* irq_chip support */
+ gpio_port->gpio_chip.to_irq = falcon_gpio_to_irq;
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0031-SERIAL-MIPS-lantiq-convert-serial-driver-to-clkdev-a.patch b/target/linux/lantiq/patches-3.2/0031-SERIAL-MIPS-lantiq-convert-serial-driver-to-clkdev-a.patch
new file mode 100644
index 0000000..dc651aa
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0031-SERIAL-MIPS-lantiq-convert-serial-driver-to-clkdev-a.patch
@@ -0,0 +1,41 @@
+From 1fdd8c04b65bd55730e6931a520cc1dabfc4d190 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 16 Feb 2012 20:17:16 +0100
+Subject: [PATCH 31/70] SERIAL: MIPS: lantiq: convert serial driver to clkdev
+ api
+
+Reference the FPI clock via its new access function.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Cc: linux-serial@vger.kernel.org
+---
+ drivers/tty/serial/lantiq.c | 6 +++++-
+ 1 files changed, 5 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
+index 5d25828..1542ad6 100644
+--- a/drivers/tty/serial/lantiq.c
++++ b/drivers/tty/serial/lantiq.c
+@@ -540,6 +540,10 @@ lqasc_request_port(struct uart_port *port)
+ if (ltq_gpio_request(&pdev->dev, MUXC_SIF_TX_PIN,
+ 3, 1, "asc1-tx"))
+ return -EBUSY;
++ ltq_port->clk = clk_get(&pdev->dev, NULL);
++ if (IS_ERR(ltq_port->clk))
++ return PTR_ERR(ltq_port->clk);
++ clk_enable(ltq_port->clk);
+ }
+ return 0;
+ }
+@@ -698,7 +702,7 @@ lqasc_probe(struct platform_device *pdev)
+ if (lqasc_port[pdev->id] != NULL)
+ return -EBUSY;
+
+- clk = clk_get(&pdev->dev, "fpi");
++ clk = clk_get_fpi();
+ if (IS_ERR(clk)) {
+ pr_err("failed to get fpi clk\n");
+ return -ENOENT;
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0032-MIPS-lantiq-convert-falcon-debug-uart-to-clkdev-api.patch b/target/linux/lantiq/patches-3.2/0032-MIPS-lantiq-convert-falcon-debug-uart-to-clkdev-api.patch
new file mode 100644
index 0000000..e13f951
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0032-MIPS-lantiq-convert-falcon-debug-uart-to-clkdev-api.patch
@@ -0,0 +1,73 @@
+From 005044f41ed9884ee23d756a5950e38679d31cc7 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 21 Feb 2012 14:25:21 +0100
+Subject: [PATCH 32/70] MIPS: lantiq: convert falcon debug uart to clkdev api
+
+On Falcon SoCs we have a secondary serial port that can be used to help
+debug the voice core. For the port to work several clocking bits need to
+be activated. We convert the code to clkdev api.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/lantiq/falcon/prom.c | 4 +---
+ drivers/tty/serial/lantiq.c | 7 ++++---
+ 2 files changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/arch/mips/lantiq/falcon/prom.c b/arch/mips/lantiq/falcon/prom.c
+index f98b389..2a4eea1 100644
+--- a/arch/mips/lantiq/falcon/prom.c
++++ b/arch/mips/lantiq/falcon/prom.c
+@@ -43,10 +43,8 @@ ltq_soc_setup(void)
+ ltq_register_asc(0);
+ ltq_register_wdt();
+ falcon_register_gpio();
+- if (register_asc1) {
++ if (register_asc1)
+ ltq_register_asc(1);
+- ltq_sysctl_activate(SYSCTL_SYS1, ACTS_ASC1_ACT);
+- }
+ }
+
+ void __init
+diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
+index 1542ad6..82956de 100644
+--- a/drivers/tty/serial/lantiq.c
++++ b/drivers/tty/serial/lantiq.c
+@@ -117,6 +117,7 @@ static DEFINE_SPINLOCK(ltq_asc_lock);
+
+ struct ltq_uart_port {
+ struct uart_port port;
++ struct clk *fpiclk;
+ struct clk *clk;
+ unsigned int tx_irq;
+ unsigned int rx_irq;
+@@ -319,7 +320,7 @@ lqasc_startup(struct uart_port *port)
+ struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
+ int retval;
+
+- port->uartclk = clk_get_rate(ltq_port->clk);
++ port->uartclk = clk_get_rate(ltq_port->fpiclk);
+
+ ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
+ port->membase + LTQ_ASC_CLC);
+@@ -646,7 +647,7 @@ lqasc_console_setup(struct console *co, char *options)
+
+ port = &ltq_port->port;
+
+- port->uartclk = clk_get_rate(ltq_port->clk);
++ port->uartclk = clk_get_rate(ltq_port->fpiclk);
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+@@ -731,7 +732,7 @@ lqasc_probe(struct platform_device *pdev)
+ port->irq = tx_irq; /* unused, just to be backward-compatibe */
+ port->mapbase = mmres->start;
+
+- ltq_port->clk = clk;
++ ltq_port->fpiclk = clk;
+
+ ltq_port->tx_irq = tx_irq;
+ ltq_port->rx_irq = rx_irq;
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0033-NET-MIPS-lantiq-convert-etop-driver-to-clkdev-api.patch b/target/linux/lantiq/patches-3.2/0033-NET-MIPS-lantiq-convert-etop-driver-to-clkdev-api.patch
new file mode 100644
index 0000000..a57b956
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0033-NET-MIPS-lantiq-convert-etop-driver-to-clkdev-api.patch
@@ -0,0 +1,123 @@
+From c96f5cae05788c326f63c8b769e53c6e15215e70 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Mar 2012 11:23:00 +0100
+Subject: [PATCH 33/70] NET: MIPS: lantiq: convert etop driver to clkdev api
+
+Update from old pmu_{dis,en}able() to ckldev api.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Cc: netdev@vger.kernel.org
+---
+ drivers/net/ethernet/lantiq_etop.c | 49 ++++++++++++++++++++++++++++++-----
+ 1 files changed, 42 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
+index fcbb9c7..a084d74 100644
+--- a/drivers/net/ethernet/lantiq_etop.c
++++ b/drivers/net/ethernet/lantiq_etop.c
+@@ -36,6 +36,7 @@
+ #include <linux/io.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/module.h>
++#include <linux/clk.h>
+
+ #include <asm/checksum.h>
+
+@@ -147,6 +148,11 @@ struct ltq_etop_priv {
+ int tx_free[MAX_DMA_CHAN >> 1];
+
+ spinlock_t lock;
++
++ struct clk *clk_ppe;
++ struct clk *clk_switch;
++ struct clk *clk_ephy;
++ struct clk *clk_ephycgu;
+ };
+
+ static int ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr,
+@@ -280,16 +286,27 @@ ltq_etop_hw_exit(struct net_device *dev)
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ int i;
+
+- ltq_pmu_disable(PMU_PPE);
++ clk_disable(priv->clk_ppe);
++
++ if (ltq_has_gbit())
++ clk_disable(priv->clk_switch);
++
++ if (ltq_is_ase()) {
++ clk_disable(priv->clk_ephy);
++ clk_disable(priv->clk_ephycgu);
++ }
++
+ for (i = 0; i < MAX_DMA_CHAN; i++)
+ if (IS_TX(i) || IS_RX(i))
+ ltq_etop_free_channel(dev, &priv->ch[i]);
+ }
+
+ static void
+-ltq_etop_gbit_init(void)
++ltq_etop_gbit_init(struct net_device *dev)
+ {
+- ltq_pmu_enable(PMU_SWITCH);
++ struct ltq_etop_priv *priv = netdev_priv(dev);
++
++ clk_enable(priv->clk_switch);
+
+ ltq_gbit_w32_mask(0, GCTL0_SE, LTQ_GBIT_GCTL0);
+ /** Disable MDIO auto polling mode */
+@@ -312,10 +329,10 @@ ltq_etop_hw_init(struct net_device *dev)
+ int err = 0;
+ int i;
+
+- ltq_pmu_enable(PMU_PPE);
++ clk_enable(priv->clk_ppe);
+
+ if (ltq_has_gbit()) {
+- ltq_etop_gbit_init();
++ ltq_etop_gbit_init(dev);
+ /* force the etops link to the gbit to MII */
+ mii_mode = PHY_INTERFACE_MODE_MII;
+ }
+@@ -333,11 +350,11 @@ ltq_etop_hw_init(struct net_device *dev)
+
+ default:
+ if (ltq_is_ase()) {
+- ltq_pmu_enable(PMU_EPHY);
++ clk_enable(priv->clk_ephy);
+ /* disable external MII */
+ ltq_etop_w32_mask(0, ETOP_CFG_MII0, LTQ_ETOP_CFG);
+ /* enable clock for internal PHY */
+- ltq_cgu_enable(CGU_EPHY);
++ clk_enable(priv->clk_ephycgu);
+ /* we need to write this magic to the internal phy to
+ make it work */
+ ltq_etop_mdio_wr(NULL, 0x8, 0x12, 0xC020);
+@@ -880,6 +897,24 @@ ltq_etop_probe(struct platform_device *pdev)
+ priv->res = res;
+ priv->pldata = dev_get_platdata(&pdev->dev);
+ priv->netdev = dev;
++
++ priv->clk_ppe = clk_get(&pdev->dev, NULL);
++ if (IS_ERR(priv->clk_ppe))
++ return PTR_ERR(priv->clk_ppe);
++ if (ltq_has_gbit()) {
++ priv->clk_switch = clk_get(&pdev->dev, "switch");
++ if (IS_ERR(priv->clk_switch))
++ return PTR_ERR(priv->clk_switch);
++ }
++ if (ltq_is_ase()) {
++ priv->clk_ephy = clk_get(&pdev->dev, "ephy");
++ if (IS_ERR(priv->clk_ephy))
++ return PTR_ERR(priv->clk_ephy);
++ priv->clk_ephycgu = clk_get(&pdev->dev, "ephycgu");
++ if (IS_ERR(priv->clk_ephycgu))
++ return PTR_ERR(priv->clk_ephycgu);
++ }
++
+ spin_lock_init(&priv->lock);
+
+ for (i = 0; i < MAX_DMA_CHAN; i++) {
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0034-WDT-MIPS-lantiq-convert-watchdog-driver-to-clkdev-ap.patch b/target/linux/lantiq/patches-3.2/0034-WDT-MIPS-lantiq-convert-watchdog-driver-to-clkdev-ap.patch
new file mode 100644
index 0000000..8eb401d
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0034-WDT-MIPS-lantiq-convert-watchdog-driver-to-clkdev-ap.patch
@@ -0,0 +1,30 @@
+From ac9ded7942720231ed139ac0660e60a3a2f82b86 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 16 Feb 2012 20:17:50 +0100
+Subject: [PATCH 34/70] WDT: MIPS: lantiq: convert watchdog driver to clkdev
+ api
+
+Refrence the IO region clock via its new access function.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Cc: linux-watchdog@vger.kernel.org
+---
+ drivers/watchdog/lantiq_wdt.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c
+index 179bf98..da2b09f 100644
+--- a/drivers/watchdog/lantiq_wdt.c
++++ b/drivers/watchdog/lantiq_wdt.c
+@@ -206,7 +206,7 @@ ltq_wdt_probe(struct platform_device *pdev)
+ }
+
+ /* we do not need to enable the clock as it is always running */
+- clk = clk_get(&pdev->dev, "io");
++ clk = clk_get_io();
+ WARN_ON(!clk);
+ ltq_io_region_clk_rate = clk_get_rate(clk);
+ clk_put(clk);
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0035-MIPS-lantiq-unify-xway-prom-code.patch b/target/linux/lantiq/patches-3.2/0035-MIPS-lantiq-unify-xway-prom-code.patch
new file mode 100644
index 0000000..69a0ffb
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0035-MIPS-lantiq-unify-xway-prom-code.patch
@@ -0,0 +1,262 @@
+From cab49331fac138102493dea8f1b1d8c28cae6db5 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Mar 2012 11:44:55 +0100
+Subject: [PATCH 35/70] MIPS: lantiq: unify xway prom code
+
+The xway prom-ase.c and prom-xway.c files are redundant. Unify the 2 files.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/lantiq/xway/Makefile | 5 +--
+ arch/mips/lantiq/xway/Makefile.rej | 11 -----
+ arch/mips/lantiq/xway/prom-ase.c | 48 ----------------------
+ arch/mips/lantiq/xway/prom-xway.c | 64 -----------------------------
+ arch/mips/lantiq/xway/prom.c | 79 ++++++++++++++++++++++++++++++++++++
+ 5 files changed, 80 insertions(+), 127 deletions(-)
+ delete mode 100644 arch/mips/lantiq/xway/Makefile.rej
+ delete mode 100644 arch/mips/lantiq/xway/prom-ase.c
+ delete mode 100644 arch/mips/lantiq/xway/prom-xway.c
+ create mode 100644 arch/mips/lantiq/xway/prom.c
+
+diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
+index 4dcb96f..9d1a0a2 100644
+--- a/arch/mips/lantiq/xway/Makefile
++++ b/arch/mips/lantiq/xway/Makefile
+@@ -1,7 +1,4 @@
+-obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o
+-
+-obj-$(CONFIG_SOC_XWAY) += prom-xway.o
+-obj-$(CONFIG_SOC_AMAZON_SE) += prom-ase.o
++obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o prom.o
+
+ obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
+ obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
+diff --git a/arch/mips/lantiq/xway/Makefile.rej b/arch/mips/lantiq/xway/Makefile.rej
+deleted file mode 100644
+index c0d5b52..0000000
+--- a/arch/mips/lantiq/xway/Makefile.rej
++++ /dev/null
+@@ -1,11 +0,0 @@
+---- arch/mips/lantiq/xway/Makefile
+-+++ arch/mips/lantiq/xway/Makefile
+-@@ -1,7 +1,4 @@
+--obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o
+--
+--obj-$(CONFIG_SOC_XWAY) += prom-xway.o
+--obj-$(CONFIG_SOC_AMAZON_SE) += prom-ase.o
+-+obj-y := prom.o sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o
+-
+- obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
+- obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
+diff --git a/arch/mips/lantiq/xway/prom-ase.c b/arch/mips/lantiq/xway/prom-ase.c
+deleted file mode 100644
+index 3f86a3b..0000000
+--- a/arch/mips/lantiq/xway/prom-ase.c
++++ /dev/null
+@@ -1,48 +0,0 @@
+-/*
+- * 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.
+- *
+- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+- */
+-
+-#include <linux/export.h>
+-#include <linux/clk.h>
+-#include <asm/bootinfo.h>
+-#include <asm/time.h>
+-
+-#include <lantiq_soc.h>
+-
+-#include "devices.h"
+-#include "../prom.h"
+-
+-#define SOC_AMAZON_SE "Amazon_SE"
+-
+-#define PART_SHIFT 12
+-#define PART_MASK 0x0FFFFFFF
+-#define REV_SHIFT 28
+-#define REV_MASK 0xF0000000
+-
+-void __init ltq_soc_detect(struct ltq_soc_info *i)
+-{
+- i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
+- i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
+- sprintf(i->rev_type, "1.%d", i->rev);
+- switch (i->partnum) {
+- case SOC_ID_AMAZON_SE:
+- i->name = SOC_AMAZON_SE;
+- i->type = SOC_TYPE_AMAZON_SE;
+- break;
+-
+- default:
+- unreachable();
+- break;
+- }
+-}
+-
+-void __init ltq_soc_setup(void)
+-{
+- ltq_register_ase_asc();
+- ltq_register_gpio();
+- ltq_register_wdt();
+-}
+diff --git a/arch/mips/lantiq/xway/prom-xway.c b/arch/mips/lantiq/xway/prom-xway.c
+deleted file mode 100644
+index d823a92..0000000
+--- a/arch/mips/lantiq/xway/prom-xway.c
++++ /dev/null
+@@ -1,64 +0,0 @@
+-/*
+- * 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.
+- *
+- * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+- */
+-
+-#include <linux/export.h>
+-#include <linux/clk.h>
+-#include <asm/bootinfo.h>
+-#include <asm/time.h>
+-
+-#include <lantiq_soc.h>
+-
+-#include "devices.h"
+-#include "../prom.h"
+-
+-#define SOC_DANUBE "Danube"
+-#define SOC_TWINPASS "Twinpass"
+-#define SOC_AR9 "AR9"
+-
+-#define PART_SHIFT 12
+-#define PART_MASK 0x0FFFFFFF
+-#define REV_SHIFT 28
+-#define REV_MASK 0xF0000000
+-
+-void __init ltq_soc_detect(struct ltq_soc_info *i)
+-{
+- i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
+- i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
+- sprintf(i->rev_type, "1.%d", i->rev);
+- switch (i->partnum) {
+- case SOC_ID_DANUBE1:
+- case SOC_ID_DANUBE2:
+- i->name = SOC_DANUBE;
+- i->type = SOC_TYPE_DANUBE;
+- break;
+-
+- case SOC_ID_TWINPASS:
+- i->name = SOC_TWINPASS;
+- i->type = SOC_TYPE_DANUBE;
+- break;
+-
+- case SOC_ID_ARX188:
+- case SOC_ID_ARX168:
+- case SOC_ID_ARX182:
+- i->name = SOC_AR9;
+- i->type = SOC_TYPE_AR9;
+- break;
+-
+- default:
+- unreachable();
+- break;
+- }
+-}
+-
+-void __init ltq_soc_setup(void)
+-{
+- ltq_register_asc(0);
+- ltq_register_asc(1);
+- ltq_register_gpio();
+- ltq_register_wdt();
+-}
+diff --git a/arch/mips/lantiq/xway/prom.c b/arch/mips/lantiq/xway/prom.c
+new file mode 100644
+index 0000000..0929acb
+--- /dev/null
++++ b/arch/mips/lantiq/xway/prom.c
+@@ -0,0 +1,79 @@
++/*
++ * 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.
++ *
++ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/export.h>
++#include <linux/clk.h>
++#include <asm/bootinfo.h>
++#include <asm/time.h>
++
++#include <lantiq_soc.h>
++
++#include "../prom.h"
++#include "devices.h"
++
++#define SOC_DANUBE "Danube"
++#define SOC_TWINPASS "Twinpass"
++#define SOC_AR9 "AR9"
++#define SOC_VR9 "VR9"
++
++#define PART_SHIFT 12
++#define PART_MASK 0x0FFFFFFF
++#define REV_SHIFT 28
++#define REV_MASK 0xF0000000
++
++#define SOC_AMAZON_SE "Amazon_SE"
++
++void __init ltq_soc_detect(struct ltq_soc_info *i)
++{
++ i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
++ i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
++ sprintf(i->rev_type, "1.%d", i->rev);
++ switch (i->partnum) {
++ case SOC_ID_DANUBE1:
++ case SOC_ID_DANUBE2:
++ i->name = SOC_DANUBE;
++ i->type = SOC_TYPE_DANUBE;
++ break;
++
++ case SOC_ID_TWINPASS:
++ i->name = SOC_TWINPASS;
++ i->type = SOC_TYPE_DANUBE;
++ break;
++
++ case SOC_ID_ARX188:
++ case SOC_ID_ARX168:
++ case SOC_ID_ARX182:
++ i->name = SOC_AR9;
++ i->type = SOC_TYPE_AR9;
++ break;
++
++ case SOC_ID_AMAZON_SE:
++ i->name = SOC_AMAZON_SE;
++ i->type = SOC_TYPE_AMAZON_SE;
++#ifdef CONFIG_PCI
++ panic("ase is only supported for non pci kernels");
++#endif
++ break;
++
++ default:
++ unreachable();
++ break;
++ }
++}
++
++void __init ltq_soc_setup(void)
++{
++ if (ltq_is_ase()) {
++ ltq_register_ase_asc();
++ } else {
++ ltq_register_asc(0);
++ ltq_register_asc(1);
++ }
++ ltq_register_gpio();
++ ltq_register_wdt();
++}
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0036-MIPS-lantiq-add-vr9-support.patch b/target/linux/lantiq/patches-3.2/0036-MIPS-lantiq-add-vr9-support.patch
new file mode 100644
index 0000000..c63be05
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0036-MIPS-lantiq-add-vr9-support.patch
@@ -0,0 +1,172 @@
+From 27c4128ab1835a2aff1a0ce6413bb21cfa614d93 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 21 Feb 2012 09:48:11 +0100
+Subject: [PATCH 36/70] MIPS: lantiq: add vr9 support
+
+VR9 is a VDSL SoC made by Lantiq. It is very similar to the AR9.
+This patch adds the clkdev init code and SoC detection for the VR9.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
+---
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 3 +
+ arch/mips/lantiq/xway/clk.c | 83 ++++++++++++++++++++
+ arch/mips/lantiq/xway/prom.c | 6 ++
+ arch/mips/lantiq/xway/sysctrl.c | 12 +++-
+ 4 files changed, 103 insertions(+), 1 deletions(-)
+
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index e9d2dd4..5d11eb7 100644
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -21,6 +21,9 @@
+ #define SOC_ID_ARX188 0x16C
+ #define SOC_ID_ARX168 0x16D
+ #define SOC_ID_ARX182 0x16F
++#define SOC_ID_VRX288 0x1C0 /* VRX288 v1.1 */
++#define SOC_ID_VRX268 0x1C2 /* VRX268 v1.1 */
++#define SOC_ID_GRX288 0x1C9 /* GRX288 v1.1 */
+
+ /* SoC Types */
+ #define SOC_TYPE_DANUBE 0x01
+diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c
+index f3b50fc..3635c9f 100644
+--- a/arch/mips/lantiq/xway/clk.c
++++ b/arch/mips/lantiq/xway/clk.c
+@@ -225,3 +225,86 @@ unsigned long ltq_danube_fpi_hz(void)
+ return ddr_clock >> 1;
+ return ddr_clock;
+ }
++
++unsigned long ltq_vr9_cpu_hz(void)
++{
++ unsigned int cpu_sel;
++ unsigned long clk;
++
++ cpu_sel = (ltq_cgu_r32(LTQ_CGU_SYS_VR9) >> 4) & 0xf;
++
++ switch (cpu_sel) {
++ case 0:
++ clk = CLOCK_600M;
++ break;
++ case 1:
++ clk = CLOCK_500M;
++ break;
++ case 2:
++ clk = CLOCK_393M;
++ break;
++ case 3:
++ clk = CLOCK_333M;
++ break;
++ case 5:
++ case 6:
++ clk = CLOCK_196_608M;
++ break;
++ case 7:
++ clk = CLOCK_167M;
++ break;
++ case 4:
++ case 8:
++ case 9:
++ clk = CLOCK_125M;
++ break;
++ default:
++ clk = 0;
++ break;
++ }
++
++ return clk;
++}
++
++unsigned long ltq_vr9_fpi_hz(void)
++{
++ unsigned int ocp_sel, cpu_clk;
++ unsigned long clk;
++
++ cpu_clk = ltq_vr9_cpu_hz();
++ ocp_sel = ltq_cgu_r32(LTQ_CGU_SYS_VR9) & 0x3;
++
++ switch (ocp_sel) {
++ case 0:
++ /* OCP ratio 1 */
++ clk = cpu_clk;
++ break;
++ case 2:
++ /* OCP ratio 2 */
++ clk = cpu_clk / 2;
++ break;
++ case 3:
++ /* OCP ratio 2.5 */
++ clk = (cpu_clk * 2) / 5;
++ break;
++ case 4:
++ /* OCP ratio 3 */
++ clk = cpu_clk / 3;
++ break;
++ default:
++ clk = 0;
++ break;
++ }
++
++ return clk;
++}
++
++unsigned long ltq_vr9_io_region_clock(void)
++{
++ return ltq_vr9_fpi_hz();
++}
++
++unsigned long ltq_vr9_fpi_bus_clock(int fpi)
++{
++ return ltq_vr9_fpi_hz();
++}
+diff --git a/arch/mips/lantiq/xway/prom.c b/arch/mips/lantiq/xway/prom.c
+index 0929acb..b6f56b7 100644
+--- a/arch/mips/lantiq/xway/prom.c
++++ b/arch/mips/lantiq/xway/prom.c
+@@ -60,6 +60,12 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
+ #endif
+ break;
+
++ case SOC_ID_VRX268:
++ case SOC_ID_VRX288:
++ i->name = SOC_VR9;
++ i->type = SOC_TYPE_VR9;
++ break;
++
+ default:
+ unreachable();
+ break;
+diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
+index c5782b5..38f02f9 100644
+--- a/arch/mips/lantiq/xway/sysctrl.c
++++ b/arch/mips/lantiq/xway/sysctrl.c
+@@ -147,7 +147,8 @@ void __init ltq_soc_init(void)
+ clkdev_add_pmu("ltq_dma", NULL, 0, PMU_DMA);
+ clkdev_add_pmu("ltq_stp", NULL, 0, PMU_STP);
+ clkdev_add_pmu("ltq_spi", NULL, 0, PMU_SPI);
+- clkdev_add_pmu("ltq_etop", NULL, 0, PMU_PPE);
++ if (!ltq_is_vr9())
++ clkdev_add_pmu("ltq_etop", NULL, 0, PMU_PPE);
+ if (ltq_is_ase()) {
+ if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5))
+ clkdev_add_static(CLOCK_266M, CLOCK_133M, CLOCK_133M);
+@@ -155,6 +156,15 @@ void __init ltq_soc_init(void)
+ clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M);
+ clkdev_add_cgu("ltq_etop", "ephycgu", CGU_EPHY),
+ clkdev_add_pmu("ltq_etop", "ephy", 0, PMU_EPHY);
++ } else if (ltq_is_vr9()) {
++ clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(),
++ ltq_vr9_io_region_clock());
++ clkdev_add_pmu("ltq_pcie", "phy", 1, PMU1_PCIE_PHY);
++ clkdev_add_pmu("ltq_pcie", "bus", 0, PMU_PCIE_CLK);
++ clkdev_add_pmu("ltq_pcie", "msi", 1, PMU1_PCIE_MSI);
++ clkdev_add_pmu("ltq_pcie", "pdi", 1, PMU1_PCIE_PDI);
++ clkdev_add_pmu("ltq_pcie", "ctl", 1, PMU1_PCIE_CTL);
++ clkdev_add_pmu("ltq_pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
+ } else {
+ clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
+ ltq_danube_io_region_clock());
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0037-MIPS-lantiq-add-ipi-handlers-to-make-vsmp-work.patch b/target/linux/lantiq/patches-3.2/0037-MIPS-lantiq-add-ipi-handlers-to-make-vsmp-work.patch
new file mode 100644
index 0000000..06e7dd3
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0037-MIPS-lantiq-add-ipi-handlers-to-make-vsmp-work.patch
@@ -0,0 +1,124 @@
+From 58d1ae79d144e6725a68fab99ef6a9b20b25a765 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 21 Feb 2012 21:09:01 +0100
+Subject: [PATCH 37/70] MIPS: lantiq: add ipi handlers to make vsmp work
+
+Add IPI handlers to the interrupt code. This patch makes MIPS_MT_SMP work
+on lantiq SoCs.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+---
+ arch/mips/lantiq/irq.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++
+ arch/mips/lantiq/prom.c | 5 ++++
+ 2 files changed, 66 insertions(+), 0 deletions(-)
+
+diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
+index 0b2ed87..770a10c 100644
+--- a/arch/mips/lantiq/irq.c
++++ b/arch/mips/lantiq/irq.c
+@@ -9,6 +9,7 @@
+
+ #include <linux/interrupt.h>
+ #include <linux/ioport.h>
++#include <linux/sched.h>
+
+ #include <asm/bootinfo.h>
+ #include <asm/irq_cpu.h>
+@@ -54,6 +55,14 @@
+ #define ltq_eiu_w32(x, y) ltq_w32((x), ltq_eiu_membase + (y))
+ #define ltq_eiu_r32(x) ltq_r32(ltq_eiu_membase + (x))
+
++/* our 2 ipi interrupts for VSMP */
++#define MIPS_CPU_IPI_RESCHED_IRQ 0
++#define MIPS_CPU_IPI_CALL_IRQ 1
++
++#if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
++int gic_present;
++#endif
++
+ static unsigned short ltq_eiu_irq[MAX_EIU] = {
+ LTQ_EIU_IR0,
+ LTQ_EIU_IR1,
+@@ -219,6 +228,47 @@ static void ltq_hw5_irqdispatch(void)
+ do_IRQ(MIPS_CPU_TIMER_IRQ);
+ }
+
++#ifdef CONFIG_MIPS_MT_SMP
++void __init arch_init_ipiirq(int irq, struct irqaction *action)
++{
++ setup_irq(irq, action);
++ irq_set_handler(irq, handle_percpu_irq);
++}
++
++static void ltq_sw0_irqdispatch(void)
++{
++ do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
++}
++
++static void ltq_sw1_irqdispatch(void)
++{
++ do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
++}
++static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
++{
++ scheduler_ipi();
++ return IRQ_HANDLED;
++}
++
++static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
++{
++ smp_call_function_interrupt();
++ return IRQ_HANDLED;
++}
++
++static struct irqaction irq_resched = {
++ .handler = ipi_resched_interrupt,
++ .flags = IRQF_PERCPU,
++ .name = "IPI_resched"
++};
++
++static struct irqaction irq_call = {
++ .handler = ipi_call_interrupt,
++ .flags = IRQF_PERCPU,
++ .name = "IPI_call"
++};
++#endif
++
+ asmlinkage void plat_irq_dispatch(void)
+ {
+ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+@@ -314,6 +364,17 @@ void __init arch_init_irq(void)
+ irq_set_chip_and_handler(i, &ltq_irq_type,
+ handle_level_irq);
+
++#if defined(CONFIG_MIPS_MT_SMP)
++ if (cpu_has_vint) {
++ pr_info("Setting up IPI vectored interrupts\n");
++ set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ltq_sw0_irqdispatch);
++ set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ltq_sw1_irqdispatch);
++ }
++ arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ,
++ &irq_resched);
++ arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ, &irq_call);
++#endif
++
+ #if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
+ set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
+ IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
+diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
+index 971554b..00ad59c 100644
+--- a/arch/mips/lantiq/prom.c
++++ b/arch/mips/lantiq/prom.c
+@@ -108,4 +108,9 @@ void __init prom_init(void)
+ soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
+ pr_info("SoC: %s\n", soc_info.sys_type);
+ prom_init_cmdline();
++
++#if defined(CONFIG_MIPS_MT_SMP)
++ if (register_vsmp_smp_ops())
++ panic("failed to register_vsmp_smp_ops()");
++#endif
+ }
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0038-MIPS-lantiq-add-additional-soc-ids.patch b/target/linux/lantiq/patches-3.2/0038-MIPS-lantiq-add-additional-soc-ids.patch
new file mode 100644
index 0000000..d5ab384
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0038-MIPS-lantiq-add-additional-soc-ids.patch
@@ -0,0 +1,156 @@
+From 655f264da58e9e49d61bf26374f877e2175125e4 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 12 Mar 2012 15:23:39 +0100
+Subject: [PATCH 38/70] MIPS: lantiq: add additional soc ids
+
+---
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 38 +++++++++++++++----
+ arch/mips/lantiq/xway/prom.c | 35 ++++++++++++++++--
+ 2 files changed, 61 insertions(+), 12 deletions(-)
+
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index 5d11eb7..3f22acb 100644
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -17,20 +17,32 @@
+ #define SOC_ID_DANUBE1 0x129
+ #define SOC_ID_DANUBE2 0x12B
+ #define SOC_ID_TWINPASS 0x12D
+-#define SOC_ID_AMAZON_SE 0x152
++#define SOC_ID_AMAZON_SE_1 0x152 /* 50601 */
++#define SOC_ID_AMAZON_SE_2 0x153 /* 50600 */
+ #define SOC_ID_ARX188 0x16C
+-#define SOC_ID_ARX168 0x16D
++#define SOC_ID_ARX168_1 0x16D
++#define SOC_ID_ARX168_2 0x16E
+ #define SOC_ID_ARX182 0x16F
+-#define SOC_ID_VRX288 0x1C0 /* VRX288 v1.1 */
+-#define SOC_ID_VRX268 0x1C2 /* VRX268 v1.1 */
+-#define SOC_ID_GRX288 0x1C9 /* GRX288 v1.1 */
++#define SOC_ID_GRX188 0x170
++#define SOC_ID_GRX168 0x171
++
++#define SOC_ID_VRX288 0x1C0 /* v1.1 */
++#define SOC_ID_VRX282 0x1C1 /* v1.1 */
++#define SOC_ID_VRX268 0x1C2 /* v1.1 */
++#define SOC_ID_GRX268 0x1C8 /* v1.1 */
++#define SOC_ID_GRX288 0x1C9 /* v1.1 */
++#define SOC_ID_VRX288_2 0x00B /* v1.2 */
++#define SOC_ID_VRX268_2 0x00C /* v1.2 */
++#define SOC_ID_GRX288_2 0x00D /* v1.2 */
++#define SOC_ID_GRX282_2 0x00E /* v1.2 */
+
+ /* SoC Types */
+ #define SOC_TYPE_DANUBE 0x01
+ #define SOC_TYPE_TWINPASS 0x02
+ #define SOC_TYPE_AR9 0x03
+-#define SOC_TYPE_VR9 0x04
+-#define SOC_TYPE_AMAZON_SE 0x05
++#define SOC_TYPE_VR9_1 0x04 /* v1.1 */
++#define SOC_TYPE_VR9_2 0x05 /* v1.2 */
++#define SOC_TYPE_AMAZON_SE 0x06
+
+ /* ASC0/1 - serial port */
+ #define LTQ_ASC0_BASE_ADDR 0x1E100400
+@@ -149,9 +161,19 @@ static inline int ltq_is_ar9(void)
+ return (ltq_get_soc_type() == SOC_TYPE_AR9);
+ }
+
++static inline int ltq_is_vr9_1(void)
++{
++ return (ltq_get_soc_type() == SOC_TYPE_VR9_1);
++}
++
++static inline int ltq_is_vr9_2(void)
++{
++ return (ltq_get_soc_type() == SOC_TYPE_VR9_2);
++}
++
+ static inline int ltq_is_vr9(void)
+ {
+- return (ltq_get_soc_type() == SOC_TYPE_VR9);
++ return (ltq_is_vr9_1() || ltq_is_vr9_2());
+ }
+
+ static inline int ltq_is_falcon(void)
+diff --git a/arch/mips/lantiq/xway/prom.c b/arch/mips/lantiq/xway/prom.c
+index b6f56b7..e3dcbbd 100644
+--- a/arch/mips/lantiq/xway/prom.c
++++ b/arch/mips/lantiq/xway/prom.c
+@@ -18,7 +18,9 @@
+
+ #define SOC_DANUBE "Danube"
+ #define SOC_TWINPASS "Twinpass"
++#define SOC_AMAZON_SE "Amazon_SE"
+ #define SOC_AR9 "AR9"
++#define SOC_GR9 "GR9"
+ #define SOC_VR9 "VR9"
+
+ #define PART_SHIFT 12
+@@ -26,7 +28,6 @@
+ #define REV_SHIFT 28
+ #define REV_MASK 0xF0000000
+
+-#define SOC_AMAZON_SE "Amazon_SE"
+
+ void __init ltq_soc_detect(struct ltq_soc_info *i)
+ {
+@@ -46,13 +47,21 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
+ break;
+
+ case SOC_ID_ARX188:
+- case SOC_ID_ARX168:
++ case SOC_ID_ARX168_1:
++ case SOC_ID_ARX168_2:
+ case SOC_ID_ARX182:
+ i->name = SOC_AR9;
+ i->type = SOC_TYPE_AR9;
+ break;
+
+- case SOC_ID_AMAZON_SE:
++ case SOC_ID_GRX188:
++ case SOC_ID_GRX168:
++ i->name = SOC_GR9;
++ i->type = SOC_TYPE_AR9;
++ break;
++
++ case SOC_ID_AMAZON_SE_1:
++ case SOC_ID_AMAZON_SE_2:
+ i->name = SOC_AMAZON_SE;
+ i->type = SOC_TYPE_AMAZON_SE;
+ #ifdef CONFIG_PCI
+@@ -60,12 +69,30 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
+ #endif
+ break;
+
++ case SOC_ID_VRX282:
+ case SOC_ID_VRX268:
+ case SOC_ID_VRX288:
+ i->name = SOC_VR9;
+- i->type = SOC_TYPE_VR9;
++ i->type = SOC_TYPE_VR9_1;
+ break;
+
++ case SOC_ID_GRX268:
++ case SOC_ID_GRX288:
++ i->name = SOC_GR9;
++ i->type = SOC_TYPE_VR9_1;
++ break;
++
++ case SOC_ID_VRX268_2:
++ case SOC_ID_VRX288_2:
++ i->name = SOC_VR9;
++ i->type = SOC_TYPE_VR9_2;
++ break;
++
++ case SOC_ID_GRX282_2:
++ case SOC_ID_GRX288_2:
++ i->name = SOC_GR9;
++ i->type = SOC_TYPE_VR9_2;
++
+ default:
+ unreachable();
+ break;
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0013-MIPS-lantiq-adds-FALC-ON-spi-driver.patch b/target/linux/lantiq/patches-3.2/0039-SPI-MIPS-lantiq-add-FALC-ON-spi-driver.patch
index 079e401..384ed2e 100644
--- a/target/linux/lantiq/patches/0013-MIPS-lantiq-adds-FALC-ON-spi-driver.patch
+++ b/target/linux/lantiq/patches-3.2/0039-SPI-MIPS-lantiq-add-FALC-ON-spi-driver.patch
@@ -1,43 +1,34 @@
-From 2bd534c30688bcb3f70f1816fbcff813fc746103 Mon Sep 17 00:00:00 2001
+From 0ebdb2202a06d096114aa7676f02d5f426a20366 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sat, 27 Aug 2011 18:12:26 +0200
-Subject: [PATCH 13/24] MIPS: lantiq: adds FALC-ON spi driver
+Subject: [PATCH 39/70] SPI: MIPS: lantiq: add FALC-ON spi driver
The external bus unit (EBU) found on the FALC-ON SoC has spi emulation that is
-designed for serial flash access.
+designed for serial flash access. This driver has only been tested with m25p80
+type chips. The hardware has no support for other types of spi peripherals.
Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
Signed-off-by: John Crispin <blogic@openwrt.org>
+Cc: spi-devel-general@lists.sourceforge.net
---
- arch/mips/lantiq/falcon/devices.c | 12 +-
+ arch/mips/lantiq/falcon/devices.c | 13 +
arch/mips/lantiq/falcon/devices.h | 4 +
arch/mips/lantiq/falcon/mach-easy98000.c | 27 ++
drivers/spi/Kconfig | 4 +
drivers/spi/Makefile | 1 +
- drivers/spi/spi-falcon.c | 477 ++++++++++++++++++++++++++++++
- 6 files changed, 523 insertions(+), 2 deletions(-)
+ drivers/spi/spi-falcon.c | 483 ++++++++++++++++++++++++++++++
+ 6 files changed, 532 insertions(+), 0 deletions(-)
create mode 100644 drivers/spi/spi-falcon.c
+diff --git a/arch/mips/lantiq/falcon/devices.c b/arch/mips/lantiq/falcon/devices.c
+index 6cd7a88..92ec571 100644
--- a/arch/mips/lantiq/falcon/devices.c
+++ b/arch/mips/lantiq/falcon/devices.c
-@@ -129,7 +129,7 @@ falcon_register_gpio_extra(void)
-
- /* i2c */
- static struct resource falcon_i2c_resources[] = {
-- MEM_RES("i2c", GPON_I2C_BASE,GPON_I2C_END),
-+ MEM_RES("i2c", LTQ_I2C_BASE_ADDR, LTQ_I2C_SIZE),
- IRQ_RES("i2c_lb", FALCON_IRQ_I2C_LBREQ),
- IRQ_RES("i2c_b", FALCON_IRQ_I2C_BREQ),
- IRQ_RES("i2c_err", FALCON_IRQ_I2C_I2C_ERR),
-@@ -140,10 +140,18 @@ void __init falcon_register_i2c(void)
- {
- platform_device_register_simple("i2c-falcon", 0,
- falcon_i2c_resources, ARRAY_SIZE(falcon_i2c_resources));
-- sys1_hw_activate(ACTS_I2C_ACT);
-+ ltq_sysctl_activate(SYSCTL_SYS1, ACTS_I2C_ACT);
+@@ -121,3 +121,16 @@ falcon_register_gpio_extra(void)
+ platform_device_register_simple("falcon_gpio", 4,
+ falcon_gpio4_res, ARRAY_SIZE(falcon_gpio4_res));
}
-
--void __init falcon_register_crypto(void)
++
+/* spi flash */
+static struct platform_device ltq_spi = {
+ .name = "falcon_spi",
@@ -46,14 +37,15 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+
+void __init
+falcon_register_spi_flash(struct spi_board_info *data)
- {
-- platform_device_register_simple("ltq_falcon_deu", 0, NULL, 0);
++{
+ spi_register_board_info(data, 1);
+ platform_device_register(&ltq_spi);
- }
++}
+diff --git a/arch/mips/lantiq/falcon/devices.h b/arch/mips/lantiq/falcon/devices.h
+index 18be8b6..5e6f720 100644
--- a/arch/mips/lantiq/falcon/devices.h
+++ b/arch/mips/lantiq/falcon/devices.h
-@@ -11,11 +11,15 @@
+@@ -11,10 +11,14 @@
#ifndef _FALCON_DEVICES_H__
#define _FALCON_DEVICES_H__
@@ -65,13 +57,14 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
extern void falcon_register_nand(void);
extern void falcon_register_gpio(void);
extern void falcon_register_gpio_extra(void);
- extern void falcon_register_i2c(void);
+extern void falcon_register_spi_flash(struct spi_board_info *data);
#endif
+diff --git a/arch/mips/lantiq/falcon/mach-easy98000.c b/arch/mips/lantiq/falcon/mach-easy98000.c
+index 361b8f0..1a7caad 100644
--- a/arch/mips/lantiq/falcon/mach-easy98000.c
+++ b/arch/mips/lantiq/falcon/mach-easy98000.c
-@@ -40,6 +40,21 @@ struct physmap_flash_data easy98000_nor_
+@@ -40,6 +40,21 @@ struct physmap_flash_data easy98000_nor_flash_data = {
.parts = easy98000_nor_partitions,
};
@@ -119,9 +112,11 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
MIPS_MACHINE(LANTIQ_MACH_EASY98000NAND,
"EASY98000NAND",
"EASY98000 Eval Board (NAND Flash)",
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index 8ba4510..b8424ba 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
-@@ -189,6 +189,10 @@ config SPI_MPC52xx
+@@ -180,6 +180,10 @@ config SPI_MPC52xx
This drivers supports the MPC52xx SPI controller in master SPI
mode.
@@ -132,9 +127,11 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
config SPI_MPC52xx_PSC
tristate "Freescale MPC52xx PSC SPI controller"
depends on PPC_MPC52xx && EXPERIMENTAL
+diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
+index 61c3261..570894c 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
-@@ -25,6 +25,7 @@ obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmi
+@@ -25,6 +25,7 @@ obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o
obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o
spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o
obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o
@@ -142,9 +139,12 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o
obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
+diff --git a/drivers/spi/spi-falcon.c b/drivers/spi/spi-falcon.c
+new file mode 100644
+index 0000000..447bbaa
--- /dev/null
+++ b/drivers/spi/spi-falcon.c
-@@ -0,0 +1,477 @@
+@@ -0,0 +1,483 @@
+/*
+ * 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
@@ -287,8 +287,10 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ txp++;
+ bytelen--;
+ if (bytelen) {
-+ /* more data:
-+ * maybe address and/or dummy */
++ /*
++ * more data:
++ * maybe address and/or dummy
++ */
+ state = state_command_prepare;
+ break;
+ } else {
@@ -313,8 +315,8 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ state = state_end;
+ break;
+ }
-+ case state_command_prepare: /* collect tx data for
-+ address and dummy phase */
++ /* collect tx data for address and dummy phase */
++ case state_command_prepare:
+ {
+ /* txp is valid, already checked */
+ val = 0;
@@ -353,8 +355,10 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ /* end of sequence? */
+ state = state_disable_cs;
+ } else {
-+ /* go to end and expect another
-+ * call (read or write) */
++ /*
++ * go to end and expect another
++ * call (read or write)
++ */
+ state = state_end;
+ }
+ break;
@@ -452,7 +456,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+falcon_spi_setup(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
-+ const u32 ebuclk = CLOCK_100M;
++ const u32 ebuclk = 100000000;
+ unsigned int i;
+ unsigned long flags;
+
@@ -486,8 +490,10 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+ | (i << (SFTIME_SCK_PER_OFFSET + 1)),
+ LTQ_SFTIME);
+
-+ /* set some bits of unused_wd, to not trigger HOLD/WP
-+ * signals on non QUAD flashes */
++ /*
++ * set some bits of unused_wd, to not trigger HOLD/WP
++ * signals on non QUAD flashes
++ */
+ ltq_ebu_w32((SFIO_UNUSED_WD_MASK & (0x8 | 0x4)), LTQ_SFIO);
+
+ ltq_ebu_w32(BUSRCON0_AGEN_SERIAL_FLASH | BUSRCON0_PORTW_8_BIT_MUX,
@@ -622,24 +628,6 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Lantiq Falcon SPI controller driver");
---- a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
-+++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
-@@ -48,6 +48,10 @@
-
- #define LTQ_EBU_MODCON 0x000C
-
-+/* I2C */
-+#define LTQ_I2C_BASE_ADDR 0x1E200000
-+#define LTQ_I2C_SIZE 0x00010000
-+
- /* GPIO */
- #define LTQ_GPIO0_BASE_ADDR 0x1D810000
- #define LTQ_GPIO0_SIZE 0x0080
-@@ -92,6 +96,7 @@
-
- /* Activation Status Register */
- #define ACTS_ASC1_ACT 0x00000800
-+#define ACTS_I2C_ACT 0x00004000
- #define ACTS_P0 0x00010000
- #define ACTS_P1 0x00010000
- #define ACTS_P2 0x00020000
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0011-MIPS-lantiq-adds-falcon-I2C.patch b/target/linux/lantiq/patches-3.2/0040-I2C-MIPS-lantiq-add-FALC-ON-i2c-bus-master.patch
index eceb1e4..f8534bf 100644
--- a/target/linux/lantiq/patches/0011-MIPS-lantiq-adds-falcon-I2C.patch
+++ b/target/linux/lantiq/patches-3.2/0040-I2C-MIPS-lantiq-add-FALC-ON-i2c-bus-master.patch
@@ -1,78 +1,185 @@
-From 6437f41dfdf9475178e22ab0dd886af033f90cc2 Mon Sep 17 00:00:00 2001
+From 97050437c6a3ce59ce2c5a8286b9bc1c9f1b3b60 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
-Date: Thu, 29 Sep 2011 21:10:16 +0200
-Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+Date: Fri, 4 Nov 2011 16:00:34 +0100
+Subject: [PATCH 40/70] I2C: MIPS: lantiq: add FALC-ON i2c bus master
+This patch adds the driver needed to make the I2C bus work on FALC-ON SoCs.
+
+Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Cc: linux-i2c@vger.kernel.org
---
- arch/mips/lantiq/falcon/devices.c | 21 +
- arch/mips/lantiq/falcon/devices.h | 1 +
- drivers/i2c/busses/Kconfig | 4 +
- drivers/i2c/busses/Makefile | 1 +
- drivers/i2c/busses/i2c-falcon.c | 815 +++++++++++++++++++++++++++++++++++++
- 5 files changed, 842 insertions(+), 0 deletions(-)
+ .../include/asm/mach-lantiq/falcon/lantiq_soc.h | 5 +
+ arch/mips/lantiq/falcon/clk.c | 44 -
+ arch/mips/lantiq/falcon/devices.c | 16 +
+ arch/mips/lantiq/falcon/devices.h | 1 +
+ arch/mips/lantiq/falcon/mach-easy98000.c | 1 +
+ drivers/i2c/busses/Kconfig | 10 +
+ drivers/i2c/busses/Makefile | 1 +
+ drivers/i2c/busses/i2c-falcon.c | 1040 ++++++++++++++++++++
+ 8 files changed, 1074 insertions(+), 44 deletions(-)
+ delete mode 100644 arch/mips/lantiq/falcon/clk.c
create mode 100644 drivers/i2c/busses/i2c-falcon.c
+diff --git a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
+index 120c56c..fff5ecd 100644
+--- a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
+@@ -72,6 +72,10 @@
+ #define LTQ_PADCTRL4_BASE_ADDR 0x1E800600
+ #define LTQ_PADCTRL4_SIZE 0x0100
+
++/* I2C */
++#define GPON_I2C_BASE 0x1E200000
++#define GPON_I2C_SIZE 0x00010000
++
+ /* CHIP ID */
+ #define LTQ_STATUS_BASE_ADDR 0x1E802000
+
+@@ -106,6 +110,7 @@
+ #define ACTS_PADCTRL2 0x00200000
+ #define ACTS_PADCTRL3 0x00200000
+ #define ACTS_PADCTRL4 0x00400000
++#define ACTS_I2C_ACT 0x00004000
+
+ /* global register ranges */
+ extern __iomem void *ltq_ebu_membase;
+diff --git a/arch/mips/lantiq/falcon/clk.c b/arch/mips/lantiq/falcon/clk.c
+deleted file mode 100644
+index afe1b52..0000000
+--- a/arch/mips/lantiq/falcon/clk.c
++++ /dev/null
+@@ -1,44 +0,0 @@
+-/*
+- * 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.
+- *
+- * Copyright (C) 2011 Thomas Langer <thomas.langer@lantiq.com>
+- * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+- */
+-
+-#include <linux/ioport.h>
+-#include <linux/export.h>
+-
+-#include <lantiq_soc.h>
+-
+-#include "devices.h"
+-
+-/* CPU0 Clock Control Register */
+-#define LTQ_SYS1_CPU0CC 0x0040
+-/* clock divider bit */
+-#define LTQ_CPU0CC_CPUDIV 0x0001
+-
+-unsigned int
+-ltq_get_io_region_clock(void)
+-{
+- return CLOCK_200M;
+-}
+-EXPORT_SYMBOL(ltq_get_io_region_clock);
+-
+-unsigned int
+-ltq_get_cpu_hz(void)
+-{
+- if (ltq_sys1_r32(LTQ_SYS1_CPU0CC) & LTQ_CPU0CC_CPUDIV)
+- return CLOCK_200M;
+- else
+- return CLOCK_400M;
+-}
+-EXPORT_SYMBOL(ltq_get_cpu_hz);
+-
+-unsigned int
+-ltq_get_fpi_hz(void)
+-{
+- return CLOCK_100M;
+-}
+-EXPORT_SYMBOL(ltq_get_fpi_hz);
+diff --git a/arch/mips/lantiq/falcon/devices.c b/arch/mips/lantiq/falcon/devices.c
+index 92ec571..e684ed4 100644
--- a/arch/mips/lantiq/falcon/devices.c
+++ b/arch/mips/lantiq/falcon/devices.c
-@@ -126,3 +126,24 @@ falcon_register_gpio_extra(void)
- ltq_sysctl_activate(SYSCTL_SYS1,
- ACTS_PADCTRL3 | ACTS_PADCTRL4 | ACTS_P3 | ACTS_P4);
+@@ -134,3 +134,19 @@ falcon_register_spi_flash(struct spi_board_info *data)
+ spi_register_board_info(data, 1);
+ platform_device_register(&ltq_spi);
}
+
+/* i2c */
+static struct resource falcon_i2c_resources[] = {
-+ MEM_RES("i2c", GPON_I2C_BASE,GPON_I2C_END),
-+ IRQ_RES("i2c_lb", FALCON_IRQ_I2C_LBREQ),
-+ IRQ_RES("i2c_b", FALCON_IRQ_I2C_BREQ),
-+ IRQ_RES("i2c_err", FALCON_IRQ_I2C_I2C_ERR),
-+ IRQ_RES("i2c_p", FALCON_IRQ_I2C_I2C_P),
++ MEM_RES("i2c", GPON_I2C_BASE, GPON_I2C_SIZE),
++ IRQ_RES(i2c_lb, FALCON_IRQ_I2C_LBREQ),
++ IRQ_RES(i2c_b, FALCON_IRQ_I2C_BREQ),
++ IRQ_RES(i2c_err, FALCON_IRQ_I2C_I2C_ERR),
++ IRQ_RES(i2c_p, FALCON_IRQ_I2C_I2C_P),
+};
+
-+void __init falcon_register_i2c(void)
++void __init
++falcon_register_i2c(void)
+{
+ platform_device_register_simple("i2c-falcon", 0,
-+ falcon_i2c_resources, ARRAY_SIZE(falcon_i2c_resources));
-+ sys1_hw_activate(ACTS_I2C_ACT);
-+}
-+
-+void __init falcon_register_crypto(void)
-+{
-+ platform_device_register_simple("ltq_falcon_deu", 0, NULL, 0);
++ falcon_i2c_resources, ARRAY_SIZE(falcon_i2c_resources));
+}
+diff --git a/arch/mips/lantiq/falcon/devices.h b/arch/mips/lantiq/falcon/devices.h
+index 5e6f720..d81edbe 100644
--- a/arch/mips/lantiq/falcon/devices.h
+++ b/arch/mips/lantiq/falcon/devices.h
-@@ -16,5 +16,6 @@
- extern void falcon_register_nand(void);
+@@ -20,5 +20,6 @@ extern void falcon_register_nand(void);
extern void falcon_register_gpio(void);
extern void falcon_register_gpio_extra(void);
+ extern void falcon_register_spi_flash(struct spi_board_info *data);
+extern void falcon_register_i2c(void);
#endif
+diff --git a/arch/mips/lantiq/falcon/mach-easy98000.c b/arch/mips/lantiq/falcon/mach-easy98000.c
+index 1a7caad..fc5720d 100644
+--- a/arch/mips/lantiq/falcon/mach-easy98000.c
++++ b/arch/mips/lantiq/falcon/mach-easy98000.c
+@@ -98,6 +98,7 @@ easy98000_init_common(void)
+ {
+ spi_register_board_info(&easy98000_spi_gpio_devices, 1);
+ platform_device_register(&easy98000_spi_gpio_device);
++ falcon_register_i2c();
+ }
+
+ static void __init
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index a3afac4..41be6cc 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
-@@ -284,6 +284,10 @@ config I2C_POWERMAC
-
- comment "I2C system bus drivers (mostly embedded / system-on-chip)"
+@@ -369,6 +369,16 @@ config I2C_DESIGNWARE_PCI
+ This driver can also be built as a module. If so, the module
+ will be called i2c-designware-pci.
+config I2C_FALCON
+ tristate "Falcon I2C interface"
-+# depends on SOC_FALCON
-+
- config I2C_AT91
- tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
- depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
++ depends on SOC_FALCON
++ help
++ If you say yes to this option, support will be included for the
++ Lantiq FALC-ON I2C core.
++
++ This driver can also be built as a module. If so, the module
++ will be called i2c-falcon.
++
+ config I2C_GPIO
+ tristate "GPIO-based bitbanging I2C"
+ depends on GENERIC_GPIO
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index fba6da6..36239c8 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
-@@ -82,5 +82,6 @@ obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
- obj-$(CONFIG_I2C_STUB) += i2c-stub.o
- obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
- obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
+@@ -37,6 +37,7 @@ obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o
+ i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o
+ obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o
+ i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o
+obj-$(CONFIG_I2C_FALCON) += i2c-falcon.o
-
- ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
+ obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
+ obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o
+ obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
+diff --git a/drivers/i2c/busses/i2c-falcon.c b/drivers/i2c/busses/i2c-falcon.c
+new file mode 100644
+index 0000000..fc4f0eb
--- /dev/null
+++ b/drivers/i2c/busses/i2c-falcon.c
-@@ -0,0 +1,815 @@
+@@ -0,0 +1,1040 @@
+/*
+ * Lantiq FALC(tm) ON - I2C bus adapter
+ *
@@ -91,14 +198,21 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
+ */
+
-+/* #define DEBUG */
++/*
++ * CURRENT ISSUES:
++ * - no high speed support
++ * - supports only master mode
++ * - ten bit mode is not tested (no slave devices)
++ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
-+#include <linux/slab.h> /* for kzalloc, kfree */
++#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/errno.h>
@@ -107,25 +221,242 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
++#include <linux/err.h>
+#include <linux/gpio.h>
+
-+#include <falcon/lantiq_soc.h>
-+
-+/* CURRENT ISSUES:
-+ * - no high speed support
-+ * - supports only master mode
-+ * - ten bit mode is not tested (no slave devices)
++#include <lantiq_soc.h>
++
++/* I2C Identification Register */
++/* Module ID */
++#define I2C_ID_ID_MASK 0x0000FF00
++/* field offset */
++#define I2C_ID_ID_OFFSET 8
++/* Revision */
++#define I2C_ID_REV_MASK 0x000000FF
++/* field offset */
++#define I2C_ID_REV_OFFSET 0
++
++/* I2C Error Interrupt Request Source Status Register */
++/* TXF_OFL */
++#define I2C_ERR_IRQSS_TXF_OFL 0x00000008
++/* TXF_UFL */
++#define I2C_ERR_IRQSS_TXF_UFL 0x00000004
++/* RXF_OFL */
++#define I2C_ERR_IRQSS_RXF_OFL 0x00000002
++/* RXF_UFL */
++#define I2C_ERR_IRQSS_RXF_UFL 0x00000001
++
++/* I2C Bus Status Register */
++/* Bus Status */
++#define I2C_BUS_STAT_BS_MASK 0x00000003
++/* I2C Bus is free. */
++#define I2C_BUS_STAT_BS_FREE 0x00000000
++/*
++ * The device is working as master and has claimed the control
++ * on the I2C-bus (busy master).
++ */
++#define I2C_BUS_STAT_BS_BM 0x00000002
++
++/* I2C Interrupt Clear Register */
++/* Clear */
++#define I2C_ICR_BREQ_INT_CLR 0x00000008
++/* Clear */
++#define I2C_ICR_LBREQ_INT_CLR 0x00000004
++
++/* I2C RUN Control Register */
++/* Enable */
++#define I2C_RUN_CTRL_RUN_EN 0x00000001
++
++/* I2C Kernel Clock Control Register */
++/* field offset */
++#define I2C_CLC_RMC_OFFSET 8
++/* Enable */
++#define I2C_IMSC_I2C_P_INT_EN 0x00000020
++/* Enable */
++#define I2C_IMSC_I2C_ERR_INT_EN 0x00000010
++/* Enable */
++#define I2C_IMSC_BREQ_INT_EN 0x00000008
++/* Enable */
++#define I2C_IMSC_LBREQ_INT_EN 0x00000004
++
++/* I2C Fractional Divider Configuration Register */
++/* field offset */
++#define I2C_FDIV_CFG_INC_OFFSET 16
++/* field offset */
++#define I2C_FDIV_CFG_DEC_OFFSET 0
++
++/* I2C Fractional Divider (highspeed mode) Configuration Register */
++/* field offset */
++#define I2C_FDIV_HIGH_CFG_INC_OFFSET 16
++/* field offset */
++#define I2C_FDIV_HIGH_CFG_DEC_OFFSET 0
++
++/* I2C Address Register */
++/* Enable */
++#define I2C_ADDR_CFG_SOPE_EN 0x00200000
++/* Enable */
++#define I2C_ADDR_CFG_SONA_EN 0x00100000
++/* Enable */
++#define I2C_ADDR_CFG_MnS_EN 0x00080000
++
++/* I2C Protocol Interrupt Request Source Status Register */
++/* RX */
++#define I2C_P_IRQSS_RX 0x00000040
++/* TX_END */
++#define I2C_P_IRQSS_TX_END 0x00000020
++/* NACK */
++#define I2C_P_IRQSS_NACK 0x00000010
++/* AL */
++#define I2C_P_IRQSS_AL 0x00000008
++
++/* I2C Raw Interrupt Status Register */
++/* Read: Interrupt occurred. */
++#define I2C_RIS_I2C_P_INT_INTOCC 0x00000020
++/* Read: Interrupt occurred. */
++#define I2C_RIS_I2C_ERR_INT_INTOCC 0x00000010
++
++/* I2C End Data Control Register */
++/*
++ * Set End of Transmission - Note: Do not write '1' to this bit when bus is
++ * free. This will cause an abort after the first byte when a new transfer
++ * is started.
+ */
++#define I2C_ENDD_CTRL_SETEND 0x00000002
++/* TX FIFO Flow Control */
++#define I2C_FIFO_CFG_TXFC 0x00020000
++/* RX FIFO Flow Control */
++#define I2C_FIFO_CFG_RXFC 0x00010000
++/* Word aligned (character alignment of four characters) */
++#define I2C_FIFO_CFG_TXFA_TXFA2 0x00002000
++/* Word aligned (character alignment of four characters) */
++#define I2C_FIFO_CFG_RXFA_RXFA2 0x00000200
++/* 1 word */
++#define I2C_FIFO_CFG_TXBS_TXBS0 0x00000000
++/* 1 word */
++#define I2C_FIFO_CFG_RXBS_RXBS0 0x00000000
++
++
++/* I2C register structure */
++struct gpon_reg_i2c {
++ /* I2C Kernel Clock Control Register */
++ unsigned int clc; /* 0x00000000 */
++ /* Reserved */
++ unsigned int res_0; /* 0x00000004 */
++ /* I2C Identification Register */
++ unsigned int id; /* 0x00000008 */
++ /* Reserved */
++ unsigned int res_1; /* 0x0000000C */
++ /*
++ * I2C RUN Control Register - This register enables and disables the I2C
++ * peripheral. Before enabling, the I2C has to be configured properly.
++ * After enabling no configuration is possible
++ */
++ unsigned int run_ctrl; /* 0x00000010 */
++ /*
++ * I2C End Data Control Register - This register is used to either turn
++ * around the data transmission direction or to address another slave
++ * without sending a stop condition. Also the software can stop the
++ * slave-transmitter by sending a not-accolade when working as
++ * master-receiver or even stop data transmission immediately when
++ * operating as master-transmitter. The writing to the bits of this
++ * control register is only effective when in MASTER RECEIVES BYTES,
++ * MASTER TRANSMITS BYTES, MASTER RESTART or SLAVE RECEIVE BYTES state
++ */
++ unsigned int endd_ctrl; /* 0x00000014 */
++ /*
++ * I2C Fractional Divider Configuration Register - These register is
++ * used to program the fractional divider of the I2C bus. Before the
++ * peripheral is switched on by setting the RUN-bit the two (fixed)
++ * values for the two operating frequencies are programmed into these
++ * (configuration) registers. The Register FDIV_HIGH_CFG has the same
++ * layout as I2C_FDIV_CFG.
++ */
++ unsigned int fdiv_cfg; /* 0x00000018 */
++ /*
++ * I2C Fractional Divider (highspeed mode) Configuration Register
++ * These register is used to program the fractional divider of the I2C
++ * bus. Before the peripheral is switched on by setting the RUN-bit the
++ * two (fixed) values for the two operating frequencies are programmed
++ * into these (configuration) registers. The Register FDIV_CFG has the
++ * same layout as I2C_FDIV_CFG.
++ */
++ unsigned int fdiv_high_cfg; /* 0x0000001C */
++ /* I2C Address Configuration Register */
++ unsigned int addr_cfg; /* 0x00000020 */
++ /*
++ * I2C Bus Status Register - This register gives a status information
++ * of the I2C. This additional information can be used by the software
++ * to start proper actions.
++ */
++ unsigned int bus_stat; /* 0x00000024 */
++ /* I2C FIFO Configuration Register */
++ unsigned int fifo_cfg; /* 0x00000028 */
++ /* I2C Maximum Received Packet Size Register */
++ unsigned int mrps_ctrl; /* 0x0000002C */
++ /* I2C Received Packet Size Status Register */
++ unsigned int rps_stat; /* 0x00000030 */
++ /* I2C Transmit Packet Size Register */
++ unsigned int tps_ctrl; /* 0x00000034 */
++ /* I2C Filled FIFO Stages Status Register */
++ unsigned int ffs_stat; /* 0x00000038 */
++ /* Reserved */
++ unsigned int res_2; /* 0x0000003C */
++ /* I2C Timing Configuration Register */
++ unsigned int tim_cfg; /* 0x00000040 */
++ /* Reserved */
++ unsigned int res_3[7]; /* 0x00000044 */
++ /* I2C Error Interrupt Request Source Mask Register */
++ unsigned int err_irqsm; /* 0x00000060 */
++ /* I2C Error Interrupt Request Source Status Register */
++ unsigned int err_irqss; /* 0x00000064 */
++ /* I2C Error Interrupt Request Source Clear Register */
++ unsigned int err_irqsc; /* 0x00000068 */
++ /* Reserved */
++ unsigned int res_4; /* 0x0000006C */
++ /* I2C Protocol Interrupt Request Source Mask Register */
++ unsigned int p_irqsm; /* 0x00000070 */
++ /* I2C Protocol Interrupt Request Source Status Register */
++ unsigned int p_irqss; /* 0x00000074 */
++ /* I2C Protocol Interrupt Request Source Clear Register */
++ unsigned int p_irqsc; /* 0x00000078 */
++ /* Reserved */
++ unsigned int res_5; /* 0x0000007C */
++ /* I2C Raw Interrupt Status Register */
++ unsigned int ris; /* 0x00000080 */
++ /* I2C Interrupt Mask Control Register */
++ unsigned int imsc; /* 0x00000084 */
++ /* I2C Masked Interrupt Status Register */
++ unsigned int mis; /* 0x00000088 */
++ /* I2C Interrupt Clear Register */
++ unsigned int icr; /* 0x0000008C */
++ /* I2C Interrupt Set Register */
++ unsigned int isr; /* 0x00000090 */
++ /* I2C DMA Enable Register */
++ unsigned int dmae; /* 0x00000094 */
++ /* Reserved */
++ unsigned int res_6[8154]; /* 0x00000098 */
++ /* I2C Transmit Data Register */
++ unsigned int txd; /* 0x00008000 */
++ /* Reserved */
++ unsigned int res_7[4095]; /* 0x00008004 */
++ /* I2C Receive Data Register */
++ unsigned int rxd; /* 0x0000C000 */
++ /* Reserved */
++ unsigned int res_8[4095]; /* 0x0000C004 */
++};
+
+/* mapping for access macros */
++#define i2c ((struct gpon_reg_i2c *)priv->membase)
+#define reg_r32(reg) __raw_readl(reg)
+#define reg_w32(val, reg) __raw_writel(val, reg)
+#define reg_w32_mask(clear, set, reg) \
+ reg_w32((reg_r32(reg) & ~(clear)) | (set), reg)
+#define reg_r32_table(reg, idx) reg_r32(&((uint32_t *)&reg)[idx])
+#define reg_w32_table(val, reg, idx) reg_w32(val, &((uint32_t *)&reg)[idx])
-+#define i2c (priv->membase)
-+#include <falcon/i2c_reg.h>
++
++#define i2c_r32(reg) reg_r32(&i2c->reg)
++#define i2c_w32(val, reg) reg_w32(val, &i2c->reg)
++#define i2c_w32_mask(clear, set, reg) reg_w32_mask(clear, set, &i2c->reg)
+
+#define DRV_NAME "i2c-falcon"
+#define DRV_VERSION "1.01"
@@ -133,12 +464,12 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+#define FALCON_I2C_BUSY_TIMEOUT 20 /* ms */
+
+#ifdef DEBUG
-+#define FALCON_I2C_XFER_TIMEOUT 25*HZ
++#define FALCON_I2C_XFER_TIMEOUT (25 * HZ)
+#else
+#define FALCON_I2C_XFER_TIMEOUT HZ
+#endif
+#if defined(DEBUG) && 0
-+#define PRINTK(arg...) printk(arg)
++#define PRINTK(arg...) pr_info(arg)
+#else
+#define PRINTK(arg...) do {} while (0)
+#endif
@@ -209,7 +540,7 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+static void prepare_msg_send_addr(struct falcon_i2c *priv)
+{
+ struct i2c_msg *msg = priv->current_msg;
-+ int rd = !!(msg->flags & I2C_M_RD); /* extends to 0 or 1 */
++ int rd = !!(msg->flags & I2C_M_RD);
+ u16 addr = msg->addr;
+
+ /* new i2c_msg */
@@ -233,7 +564,7 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+ struct i2c_msg *msg = priv->current_msg;
+ int len = (msg->flags & I2C_M_TEN) ? 2 : 1;
+
-+ PRINTK("set_tx_len %cX\n", (msg->flags & I2C_M_RD)?'R':'T');
++ PRINTK("set_tx_len %cX\n", (msg->flags & I2C_M_RD) ? ('R') : ('T'));
+
+ priv->status = STATUS_ADDR;
+
@@ -297,8 +628,8 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+ fifo_cfg);
+
+ /* configure address */
-+ i2c_w32(I2C_ADDR_CFG_SOPE_EN | /* generate stop when no more data in the
-+ fifo */
++ i2c_w32(I2C_ADDR_CFG_SOPE_EN | /* generate stop when no more data
++ in the fifo */
+ I2C_ADDR_CFG_SONA_EN | /* generate stop when NA received */
+ I2C_ADDR_CFG_MnS_EN | /* we are master device */
+ 0, /* our slave address (not used!) */
@@ -339,14 +670,13 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+ } else
+ last = 1;
+
-+ if (last) {
++ if (last)
+ disable_burst_irq(priv);
-+ }
+}
+
+static void falcon_i2c_rx(struct falcon_i2c *priv, int last)
+{
-+ u32 fifo_stat,timeout;
++ u32 fifo_stat, timeout;
+ if (priv->msg_buf_len && priv->msg_buf) {
+ timeout = 5000000;
+ do {
@@ -406,10 +736,10 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+{
+#if defined(DEBUG)
+ int i, j;
-+ printk("Messages %d %s\n", num, rx ? "out" : "in");
++ pr_info("Messages %d %s\n", num, rx ? "out" : "in");
+ for (i = 0; i < num; i++) {
-+ printk("%2d %cX Msg(%d) addr=0x%X: ", i,
-+ (msgs[i].flags & I2C_M_RD)?'R':'T',
++ pr_info("%2d %cX Msg(%d) addr=0x%X: ", i,
++ (msgs[i].flags & I2C_M_RD) ? ('R') : ('T'),
+ msgs[i].len, msgs[i].addr);
+ if (!(msgs[i].flags & I2C_M_RD) || rx) {
+ for (j = 0; j < msgs[i].len; j++)
@@ -470,9 +800,8 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+ ret = -EREMOTEIO;
+ goto done;
+ }
-+ if (--priv->msgs_num) {
++ if (--priv->msgs_num)
+ priv->current_msg++;
-+ }
+ }
+ /* no error? */
+ ret = num;
@@ -482,7 +811,7 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+
+ mutex_unlock(&priv->mutex);
+
-+ if (ret>=0)
++ if (ret >= 0)
+ dump_msgs(msgs, num, 1);
+
+ PRINTK("XFER ret %d\n", ret);
@@ -514,7 +843,7 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+ break;
+ default:
+ disable_burst_irq(priv);
-+ printk("Status R %d\n", priv->status);
++ PRINTK("Status R %d\n", priv->status);
+ break;
+ }
+ } else {
@@ -529,7 +858,7 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+ break;
+ default:
+ disable_burst_irq(priv);
-+ printk("Status W %d\n", priv->status);
++ PRINTK("Status W %d\n", priv->status);
+ break;
+ }
+ }
@@ -585,7 +914,7 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+
+static irqreturn_t falcon_i2c_isr(int irq, void *dev_id)
+{
-+ u32 i_raw, i_err=0;
++ u32 i_raw, i_err = 0;
+ struct falcon_i2c *priv = dev_id;
+
+ i_raw = i2c_r32(mis);
@@ -662,7 +991,7 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+ return -ENODEV;
+ }
+
-+ clk = clk_get(&pdev->dev, "fpi");
++ clk = clk_get_fpi();
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "failed to get fpi clk\n");
+ return -ENOENT;
@@ -672,6 +1001,11 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+ dev_err(&pdev->dev, "input clock is not 100MHz\n");
+ return -ENOENT;
+ }
++ clk = clk_get(&pdev->dev, NULL);
++ if (IS_ERR(clk)) {
++ dev_err(&pdev->dev, "failed to get i2c clk\n");
++ return -ENOENT;
++ }
+
+ /* allocate private data */
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
@@ -694,16 +1028,10 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+ init_completion(&priv->cmd_complete);
+ mutex_init(&priv->mutex);
+
-+ ret = ltq_gpio_request(107, 0, 0, 0, DRV_NAME":sda");
-+ if (ret) {
-+ dev_err(&pdev->dev, "I2C gpio 107 (sda) not available\n");
-+ ret = -ENXIO;
-+ goto err_free_priv;
-+ }
-+ ret = ltq_gpio_request(108, 0, 0, 0, DRV_NAME":scl");
-+ if (ret) {
-+ gpio_free(107);
-+ dev_err(&pdev->dev, "I2C gpio 108 (scl) not available\n");
++ if (ltq_gpio_request(&pdev->dev, 107, 0, 0, DRV_NAME":sda") ||
++ ltq_gpio_request(&pdev->dev, 108, 0, 0, DRV_NAME":scl"))
++ {
++ dev_err(&pdev->dev, "I2C gpios not available\n");
+ ret = -ENXIO;
+ goto err_free_priv;
+ }
@@ -729,7 +1057,8 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+ ret = request_irq(priv->irq_lb, falcon_i2c_isr_burst, IRQF_DISABLED,
+ irqres_lb->name, priv);
+ if (ret) {
-+ dev_err(&pdev->dev, "can't get last burst IRQ %d\n", irqres_lb->start);
++ dev_err(&pdev->dev, "can't get last burst IRQ %d\n",
++ irqres_lb->start);
+ ret = -ENODEV;
+ goto err_unmap_mem;
+ }
@@ -738,7 +1067,8 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+ ret = request_irq(priv->irq_b, falcon_i2c_isr_burst, IRQF_DISABLED,
+ irqres_b->name, priv);
+ if (ret) {
-+ dev_err(&pdev->dev, "can't get burst IRQ %d\n", irqres_b->start);
++ dev_err(&pdev->dev, "can't get burst IRQ %d\n",
++ irqres_b->start);
+ ret = -ENODEV;
+ goto err_free_lb_irq;
+ }
@@ -747,7 +1077,8 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+ ret = request_irq(priv->irq_err, falcon_i2c_isr, IRQF_DISABLED,
+ irqres_err->name, priv);
+ if (ret) {
-+ dev_err(&pdev->dev, "can't get error IRQ %d\n", irqres_err->start);
++ dev_err(&pdev->dev, "can't get error IRQ %d\n",
++ irqres_err->start);
+ ret = -ENODEV;
+ goto err_free_b_irq;
+ }
@@ -756,7 +1087,8 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+ ret = request_irq(priv->irq_p, falcon_i2c_isr, IRQF_DISABLED,
+ irqres_p->name, priv);
+ if (ret) {
-+ dev_err(&pdev->dev, "can't get protocol IRQ %d\n", irqres_p->start);
++ dev_err(&pdev->dev, "can't get protocol IRQ %d\n",
++ irqres_p->start);
+ ret = -ENODEV;
+ goto err_free_err_irq;
+ }
@@ -888,3 +1220,6 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0041-MIPS-lantiq-add-xway-nand-driver.patch b/target/linux/lantiq/patches-3.2/0041-MIPS-lantiq-add-xway-nand-driver.patch
new file mode 100644
index 0000000..c2e2e1b
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0041-MIPS-lantiq-add-xway-nand-driver.patch
@@ -0,0 +1,310 @@
+From 9c7a6f8804aef7559ee8edcb7466676ee7d00c09 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 27 Aug 2011 20:08:14 +0200
+Subject: [PATCH 41/70] MIPS: lantiq: add xway nand driver
+
+This patch adds a nand driver for XWAY SoCs. The patch makes use of the
+plat_nand driver. As with the EBU NOR driver merged in 3.0, we have the
+endianess swap problem on read. To workaround this problem we make the
+read_byte() callback available via the plat_nand driver causing the nand
+layer to do byte reads.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+
+TODO : memory ranges
+ cs lines
+ plat dev
+ ebu2 and not ebu1 ?
+---
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 2 +
+ arch/mips/lantiq/xway/Makefile | 2 +-
+ arch/mips/lantiq/xway/devices.h | 1 +
+ arch/mips/lantiq/xway/nand.c | 216 ++++++++++++++++++++
+ drivers/mtd/nand/plat_nand.c | 1 +
+ include/linux/mtd/nand.h | 1 +
+ 6 files changed, 222 insertions(+), 1 deletions(-)
+ create mode 100644 arch/mips/lantiq/xway/nand.c
+
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index 3f22acb..ab2d236 100644
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -145,6 +145,8 @@
+ /* register access macros for EBU and CGU */
+ #define ltq_ebu_w32(x, y) ltq_w32((x), ltq_ebu_membase + (y))
+ #define ltq_ebu_r32(x) ltq_r32(ltq_ebu_membase + (x))
++#define ltq_ebu_w32_mask(x, y, z) \
++ ltq_w32_mask(x, y, ltq_ebu_membase + (z))
+ #define ltq_cgu_w32(x, y) ltq_w32((x), ltq_cgu_membase + (y))
+ #define ltq_cgu_r32(x) ltq_r32(ltq_cgu_membase + (x))
+
+diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
+index 9d1a0a2..277aa34 100644
+--- a/arch/mips/lantiq/xway/Makefile
++++ b/arch/mips/lantiq/xway/Makefile
+@@ -1,4 +1,4 @@
+-obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o prom.o
++obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o prom.o nand.o
+
+ obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
+ obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
+diff --git a/arch/mips/lantiq/xway/devices.h b/arch/mips/lantiq/xway/devices.h
+index e904934..d825cbd 100644
+--- a/arch/mips/lantiq/xway/devices.h
++++ b/arch/mips/lantiq/xway/devices.h
+@@ -16,5 +16,6 @@ extern void ltq_register_gpio(void);
+ extern void ltq_register_gpio_stp(void);
+ extern void ltq_register_ase_asc(void);
+ extern void ltq_register_etop(struct ltq_eth_data *eth);
++extern void xway_register_nand(struct mtd_partition *parts, int count);
+
+ #endif
+diff --git a/arch/mips/lantiq/xway/nand.c b/arch/mips/lantiq/xway/nand.c
+new file mode 100644
+index 0000000..9ab91d8
+--- /dev/null
++++ b/arch/mips/lantiq/xway/nand.c
+@@ -0,0 +1,216 @@
++/*
++ * 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.
++ *
++ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/mtd/physmap.h>
++#include <linux/mtd/nand.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++
++#include <lantiq_soc.h>
++#include <lantiq_irq.h>
++#include <lantiq_platform.h>
++
++#include "devices.h"
++
++/* nand registers */
++#define LTQ_EBU_NAND_WAIT 0xB4
++#define LTQ_EBU_NAND_ECC0 0xB8
++#define LTQ_EBU_NAND_ECC_AC 0xBC
++#define LTQ_EBU_NAND_CON 0xB0
++#define LTQ_EBU_ADDSEL1 0x24
++
++/* gpio definitions */
++#define PIN_ALE 13
++#define PIN_CLE 24
++#define PIN_CS1 23
++#define PIN_RDY 48 /* NFLASH_READY */
++#define PIN_RD 49 /* NFLASH_READ_N */
++
++#define NAND_CMD_ALE (1 << 2)
++#define NAND_CMD_CLE (1 << 3)
++#define NAND_CMD_CS (1 << 4)
++#define NAND_WRITE_CMD_RESET 0xff
++#define NAND_WRITE_CMD (NAND_CMD_CS | NAND_CMD_CLE)
++#define NAND_WRITE_ADDR (NAND_CMD_CS | NAND_CMD_ALE)
++#define NAND_WRITE_DATA (NAND_CMD_CS)
++#define NAND_READ_DATA (NAND_CMD_CS)
++#define NAND_WAIT_WR_C (1 << 3)
++#define NAND_WAIT_RD (0x1)
++
++#define ADDSEL1_MASK(x) (x << 4)
++#define ADDSEL1_REGEN 1
++#define BUSCON1_SETUP (1 << 22)
++#define BUSCON1_BCGEN_RES (0x3 << 12)
++#define BUSCON1_WAITWRC2 (2 << 8)
++#define BUSCON1_WAITRDC2 (2 << 6)
++#define BUSCON1_HOLDC1 (1 << 4)
++#define BUSCON1_RECOVC1 (1 << 2)
++#define BUSCON1_CMULT4 1
++#define NAND_CON_NANDM 1
++#define NAND_CON_CSMUX (1 << 1)
++#define NAND_CON_CS_P (1 << 4)
++#define NAND_CON_SE_P (1 << 5)
++#define NAND_CON_WP_P (1 << 6)
++#define NAND_CON_PRE_P (1 << 7)
++#define NAND_CON_IN_CS0 0
++#define NAND_CON_OUT_CS0 0
++#define NAND_CON_IN_CS1 (1 << 8)
++#define NAND_CON_OUT_CS1 (1 << 10)
++#define NAND_CON_CE (1 << 20)
++
++#define NAND_BASE_ADDRESS (KSEG1 | 0x14000000)
++
++static const char *part_probes[] = { "cmdlinepart", NULL };
++
++static void xway_select_chip(struct mtd_info *mtd, int chip)
++{
++ switch (chip) {
++ case -1:
++ ltq_ebu_w32_mask(NAND_CON_CE, 0, LTQ_EBU_NAND_CON);
++ ltq_ebu_w32_mask(NAND_CON_NANDM, 0, LTQ_EBU_NAND_CON);
++ break;
++ case 0:
++ ltq_ebu_w32_mask(0, NAND_CON_NANDM, LTQ_EBU_NAND_CON);
++ ltq_ebu_w32_mask(0, NAND_CON_CE, LTQ_EBU_NAND_CON);
++ /* reset the nand chip */
++ while ((ltq_ebu_r32(LTQ_EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
++ ;
++ ltq_w32(NAND_WRITE_CMD_RESET,
++ ((u32 *) (NAND_BASE_ADDRESS | NAND_WRITE_CMD)));
++ break;
++ default:
++ BUG();
++ }
++}
++
++static void xway_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
++{
++ struct nand_chip *this = mtd->priv;
++
++ if (ctrl & NAND_CTRL_CHANGE) {
++ if (ctrl & NAND_CLE)
++ this->IO_ADDR_W = (void __iomem *)
++ (NAND_BASE_ADDRESS | NAND_WRITE_CMD);
++ else if (ctrl & NAND_ALE)
++ this->IO_ADDR_W = (void __iomem *)
++ (NAND_BASE_ADDRESS | NAND_WRITE_ADDR);
++ }
++
++ if (data != NAND_CMD_NONE) {
++ *(volatile u8*) ((u32) this->IO_ADDR_W) = data;
++ while ((ltq_ebu_r32(LTQ_EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
++ ;
++ }
++}
++
++static int xway_dev_ready(struct mtd_info *mtd)
++{
++ return ltq_ebu_r32(LTQ_EBU_NAND_WAIT) & NAND_WAIT_RD;
++}
++
++void nand_write(unsigned int addr, unsigned int val)
++{
++ ltq_w32(val, ((u32 *) (NAND_BASE_ADDRESS | addr)));
++ while ((ltq_ebu_r32(LTQ_EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
++ ;
++}
++
++unsigned char xway_read_byte(struct mtd_info *mtd)
++{
++ return ltq_r8((void __iomem *)(NAND_BASE_ADDRESS | (NAND_READ_DATA)));
++}
++
++static void xway_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
++{
++ int i;
++
++ for (i = 0; i < len; i++)
++ {
++ unsigned char res8 = ltq_r8((void __iomem *)(NAND_BASE_ADDRESS | (NAND_READ_DATA)));
++ buf[i] = res8;
++ }
++}
++
++static void xway_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
++{
++ int i;
++
++ for (i = 0; i < len; i++)
++ {
++ ltq_w8(buf[i], ((u32*)(NAND_BASE_ADDRESS | (NAND_WRITE_DATA))));
++ while((ltq_ebu_r32(LTQ_EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0);
++ }
++}
++
++int xway_probe(struct platform_device *pdev)
++{
++ /* might need this later ?
++ ltq_gpio_request(PIN_CS1, 2, 1, "NAND_CS1");
++ */
++ ltq_gpio_request(&pdev->dev, PIN_CLE, 2, 1, "NAND_CLE");
++ ltq_gpio_request(&pdev->dev, PIN_ALE, 2, 1, "NAND_ALE");
++ if (ltq_is_ar9() || ltq_is_vr9()) {
++ ltq_gpio_request(&pdev->dev, PIN_RDY, 2, 0, "NAND_BSY");
++ ltq_gpio_request(&pdev->dev, PIN_RD, 2, 1, "NAND_RD");
++ }
++
++ ltq_ebu_w32((NAND_BASE_ADDRESS & 0x1fffff00)
++ | ADDSEL1_MASK(3) | ADDSEL1_REGEN, LTQ_EBU_ADDSEL1);
++
++ ltq_ebu_w32(BUSCON1_SETUP | BUSCON1_BCGEN_RES | BUSCON1_WAITWRC2
++ | BUSCON1_WAITRDC2 | BUSCON1_HOLDC1 | BUSCON1_RECOVC1
++ | BUSCON1_CMULT4, LTQ_EBU_BUSCON1);
++
++ ltq_ebu_w32(NAND_CON_NANDM | NAND_CON_CSMUX | NAND_CON_CS_P
++ | NAND_CON_SE_P | NAND_CON_WP_P | NAND_CON_PRE_P
++ | NAND_CON_IN_CS0 | NAND_CON_OUT_CS0, LTQ_EBU_NAND_CON);
++
++ ltq_w32(NAND_WRITE_CMD_RESET,
++ ((u32 *) (NAND_BASE_ADDRESS | NAND_WRITE_CMD)));
++ while ((ltq_ebu_r32(LTQ_EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0)
++ ;
++
++ return 0;
++}
++
++static struct platform_nand_data falcon_flash_nand_data = {
++ .chip = {
++ .nr_chips = 1,
++ .chip_delay = 30,
++ .part_probe_types = part_probes,
++ },
++ .ctrl = {
++ .probe = xway_probe,
++ .cmd_ctrl = xway_cmd_ctrl,
++ .dev_ready = xway_dev_ready,
++ .select_chip = xway_select_chip,
++ .read_byte = xway_read_byte,
++ .read_buf = xway_read_buf,
++ .write_buf = xway_write_buf,
++ }
++};
++
++static struct resource ltq_nand_res =
++ MEM_RES("nand", 0x14000000, 0x7ffffff);
++
++static struct platform_device ltq_flash_nand = {
++ .name = "gen_nand",
++ .id = -1,
++ .num_resources = 1,
++ .resource = &ltq_nand_res,
++ .dev = {
++ .platform_data = &falcon_flash_nand_data,
++ },
++};
++
++void __init xway_register_nand(struct mtd_partition *parts, int count)
++{
++ falcon_flash_nand_data.chip.partitions = parts;
++ falcon_flash_nand_data.chip.nr_partitions = count;
++ platform_device_register(&ltq_flash_nand);
++}
+diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
+index ea8e123..9040ba1 100644
+--- a/drivers/mtd/nand/plat_nand.c
++++ b/drivers/mtd/nand/plat_nand.c
+@@ -75,6 +75,7 @@ static int __devinit plat_nand_probe(struct platform_device *pdev)
+ data->chip.select_chip = pdata->ctrl.select_chip;
+ data->chip.write_buf = pdata->ctrl.write_buf;
+ data->chip.read_buf = pdata->ctrl.read_buf;
++ data->chip.read_byte = pdata->ctrl.read_byte;
+ data->chip.chip_delay = pdata->chip.chip_delay;
+ data->chip.options |= pdata->chip.options;
+ data->chip.bbt_options |= pdata->chip.bbt_options;
+diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
+index 904131b..80e11b9 100644
+--- a/include/linux/mtd/nand.h
++++ b/include/linux/mtd/nand.h
+@@ -650,6 +650,7 @@ struct platform_nand_ctrl {
+ void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
+ void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
+ void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
++ unsigned char (*read_byte)(struct mtd_info *mtd);
+ void *priv;
+ };
+
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0014-MIPS-lantiq-adds-xway-spi.patch b/target/linux/lantiq/patches-3.2/0042-SPI-MIPS-lantiq-adds-spi-xway.patch
index 76ab292..ca6e892 100644
--- a/target/linux/lantiq/patches/0014-MIPS-lantiq-adds-xway-spi.patch
+++ b/target/linux/lantiq/patches-3.2/0042-SPI-MIPS-lantiq-adds-spi-xway.patch
@@ -1,18 +1,19 @@
-From e29263339db41d49d79482c93463c4c0cbe764d7 Mon Sep 17 00:00:00 2001
+From b257baf20b44e97770a2654a07f196fcbcd46e92 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
-Date: Fri, 30 Sep 2011 14:23:42 +0200
-Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+Date: Mon, 10 Oct 2011 22:29:13 +0200
+Subject: [PATCH 42/70] SPI: MIPS: lantiq: adds spi xway
---
.../mips/include/asm/mach-lantiq/lantiq_platform.h | 9 +
.../mips/include/asm/mach-lantiq/xway/lantiq_irq.h | 2 +
- .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 1 +
drivers/spi/Kconfig | 8 +
- drivers/spi/Makefile | 2 +-
- drivers/spi/spi-xway.c | 1062 ++++++++++++++++++++
- 6 files changed, 1083 insertions(+), 1 deletions(-)
+ drivers/spi/Makefile | 1 +
+ drivers/spi/spi-xway.c | 1068 ++++++++++++++++++++
+ 5 files changed, 1088 insertions(+), 0 deletions(-)
create mode 100644 drivers/spi/spi-xway.c
+diff --git a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
+index a305f1d..38ed938 100644
--- a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
@@ -50,4 +50,13 @@ struct ltq_eth_data {
@@ -29,6 +30,8 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+};
+
#endif
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
+index 2a8d5ad..b7f10e6 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
@@ -27,6 +27,8 @@
@@ -40,19 +43,11 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
#define LTQ_SSC_EIR (INT_NUM_IM0_IRL0 + 16)
#define LTQ_MEI_DYING_GASP_INT (INT_NUM_IM1_IRL0 + 21)
---- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
-+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
-@@ -81,6 +81,7 @@
-
- #define PMU_DMA 0x0020
- #define PMU_USB 0x8041
-+#define PMU_SPI 0x0100
- #define PMU_LED 0x0800
- #define PMU_GPT 0x1000
- #define PMU_PPE 0x2000
+diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
+index b8424ba..ca4189c 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
-@@ -393,6 +393,14 @@ config SPI_NUC900
+@@ -384,6 +384,14 @@ config SPI_NUC900
help
SPI driver for Nuvoton NUC900 series ARM SoCs
@@ -67,17 +62,22 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
#
# Add new SPI master controllers in alphabetical order above this line
#
+diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
+index 570894c..a465d9a 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
-@@ -60,4 +60,5 @@ obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x
+@@ -59,4 +59,5 @@ obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x0.o
obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o
obj-$(CONFIG_SPI_TXX9) += spi-txx9.o
obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o
+obj-$(CONFIG_SPI_XWAY) += spi-xway.o
+diff --git a/drivers/spi/spi-xway.c b/drivers/spi/spi-xway.c
+new file mode 100644
+index 0000000..016a6d0
--- /dev/null
+++ b/drivers/spi/spi-xway.c
-@@ -0,0 +1,1062 @@
+@@ -0,0 +1,1068 @@
+/*
+ * Lantiq SoC SPI controller
+ *
@@ -234,7 +234,8 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+
+ struct device *dev;
+ void __iomem *base;
-+ struct clk *clk;
++ struct clk *fpiclk;
++ struct clk *spiclk;
+
+ int status;
+ int irq[3];
@@ -267,8 +268,7 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+
+struct ltq_spi_cs_gpio_map {
+ unsigned gpio;
-+ unsigned altsel0;
-+ unsigned altsel1;
++ unsigned mux;
+};
+
+static inline struct ltq_spi *ltq_spi_to_hw(struct spi_device *spi)
@@ -309,7 +309,7 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+ u32 clc;
+
+ /* Power-up mdule */
-+ ltq_pmu_enable(PMU_SPI);
++ clk_enable(hw->spiclk);
+
+ /*
+ * Set clock divider for run mode to 1 to
@@ -325,7 +325,7 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+ ltq_spi_reg_write(hw, LTQ_SPI_CLC_DISS, LTQ_SPI_CLC);
+
+ /* Power-down mdule */
-+ ltq_pmu_disable(PMU_SPI);
++ clk_disable(hw->spiclk);
+}
+
+static void ltq_spi_reset_fifos(struct ltq_spi *hw)
@@ -475,7 +475,7 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+ * SPI module clock is derived from FPI bus clock dependent on
+ * divider value in CLC.RMS which is always set to 1.
+ */
-+ spi_clk = clk_get_rate(hw->clk);
++ spi_clk = clk_get_rate(hw->fpiclk);
+
+ /*
+ * Maximum SPI clock frequency in master mode is half of
@@ -628,12 +628,12 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+}
+
+static const struct ltq_spi_cs_gpio_map ltq_spi_cs[] = {
-+ { 15, 1, 0 },
-+ { 22, 1, 0 },
-+ { 13, 0, 1 },
-+ { 10, 0, 1 },
-+ { 9, 0, 1 },
-+ { 11, 1, 1 },
++ { 15, 2 },
++ { 22, 2 },
++ { 13, 1 },
++ { 10, 1 },
++ { 9, 1 },
++ { 11, 3 },
+};
+
+static int ltq_spi_setup(struct spi_device *spi)
@@ -680,9 +680,8 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+ cstate->cs_activate = ltq_spi_gpio_cs_activate;
+ cstate->cs_deactivate = ltq_spi_gpio_cs_deactivate;
+ } else {
-+ ret = ltq_gpio_request(ltq_spi_cs[spi->chip_select].gpio,
-+ ltq_spi_cs[spi->chip_select].altsel0,
-+ ltq_spi_cs[spi->chip_select].altsel1,
++ ret = ltq_gpio_request(&spi->dev, ltq_spi_cs[spi->chip_select].gpio,
++ ltq_spi_cs[spi->chip_select].mux,
+ 1, "spi-cs");
+ if (ret)
+ return -EBUSY;
@@ -989,10 +988,17 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+ goto err_master;
+ }
+
-+ hw->clk = clk_get(&pdev->dev, "fpi");
-+ if (IS_ERR(hw->clk)) {
++ hw->fpiclk = clk_get_fpi();
++ if (IS_ERR(hw->fpiclk)) {
++ dev_err(&pdev->dev, "clk_get\n");
++ ret = PTR_ERR(hw->fpiclk);
++ goto err_master;
++ }
++
++ hw->spiclk = clk_get(&pdev->dev, NULL);
++ if (IS_ERR(hw->spiclk)) {
+ dev_err(&pdev->dev, "clk_get\n");
-+ ret = PTR_ERR(hw->clk);
++ ret = PTR_ERR(hw->spiclk);
+ goto err_master;
+ }
+
@@ -1028,9 +1034,9 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+ spin_lock_init(&hw->lock);
+
+ /* Set GPIO alternate functions to SPI */
-+ ltq_gpio_request(LTQ_SPI_GPIO_DI, 1, 0, 0, "spi-di");
-+ ltq_gpio_request(LTQ_SPI_GPIO_DO, 1, 0, 1, "spi-do");
-+ ltq_gpio_request(LTQ_SPI_GPIO_CLK, 1, 0, 1, "spi-clk");
++ ltq_gpio_request(&pdev->dev, LTQ_SPI_GPIO_DI, 2, 0, "spi-di");
++ ltq_gpio_request(&pdev->dev, LTQ_SPI_GPIO_DO, 2, 1, "spi-do");
++ ltq_gpio_request(&pdev->dev, LTQ_SPI_GPIO_CLK, 2, 1, "spi-clk");
+
+ ltq_spi_hw_enable(hw);
+
@@ -1076,7 +1082,7 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+ ltq_spi_hw_disable(hw);
+
+err_irq:
-+ clk_put(hw->clk);
++ clk_put(hw->fpiclk);
+
+ for (; i > 0; i--)
+ free_irq(hw->irq[i], hw);
@@ -1110,7 +1116,7 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+ gpio_free(LTQ_SPI_GPIO_DO);
+ gpio_free(LTQ_SPI_GPIO_CLK);
+
-+ clk_put(hw->clk);
++ clk_put(hw->fpiclk);
+ spi_master_put(hw->bitbang.master);
+
+ return 0;
@@ -1118,7 +1124,7 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+
+static struct platform_driver ltq_spi_driver = {
+ .driver = {
-+ .name = "ltq-spi",
++ .name = "ltq_spi",
+ .owner = THIS_MODULE,
+ },
+ .remove = __exit_p(ltq_spi_remove),
@@ -1140,3 +1146,6 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
+MODULE_AUTHOR("Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ltq-spi");
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0043-NET-adds-driver-for-lantiq-vr9-ethernet.patch b/target/linux/lantiq/patches-3.2/0043-NET-adds-driver-for-lantiq-vr9-ethernet.patch
new file mode 100644
index 0000000..312ac56
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0043-NET-adds-driver-for-lantiq-vr9-ethernet.patch
@@ -0,0 +1,1470 @@
+From 7591c5702cfe842f415e42f387532fe71ea3640f Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 9 Mar 2012 19:03:40 +0100
+Subject: [PATCH 43/70] NET: adds driver for lantiq vr9 ethernet
+
+---
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 2 +-
+ arch/mips/lantiq/xway/devices.c | 20 +
+ arch/mips/lantiq/xway/devices.h | 1 +
+ drivers/net/ethernet/Kconfig | 6 +
+ drivers/net/ethernet/Makefile | 1 +
+ drivers/net/ethernet/lantiq_vrx200.c | 1358 ++++++++++++++++++++
+ 6 files changed, 1387 insertions(+), 1 deletions(-)
+ create mode 100644 drivers/net/ethernet/lantiq_vrx200.c
+
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index ab2d236..d1b8cc8 100644
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -102,7 +102,7 @@
+
+ /* GBIT - gigabit switch */
+ #define LTQ_GBIT_BASE_ADDR 0x1E108000
+-#define LTQ_GBIT_SIZE 0x200
++#define LTQ_GBIT_SIZE 0x4000
+
+ /* DMA */
+ #define LTQ_DMA_BASE_ADDR 0x1E104100
+diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
+index eab4644d..5efa4f3 100644
+--- a/arch/mips/lantiq/xway/devices.c
++++ b/arch/mips/lantiq/xway/devices.c
+@@ -83,6 +83,7 @@ static struct platform_device ltq_etop = {
+ .name = "ltq_etop",
+ .resource = ltq_etop_resources,
+ .num_resources = 1,
++ .id = -1,
+ };
+
+ void __init
+@@ -96,3 +97,22 @@ ltq_register_etop(struct ltq_eth_data *eth)
+ platform_device_register(&ltq_etop);
+ }
+ }
++
++/* ethernet */
++static struct resource ltq_vrx200_resources[] = {
++ MEM_RES("gbit", LTQ_GBIT_BASE_ADDR, LTQ_GBIT_SIZE),
++};
++
++static struct platform_device ltq_vrx200 = {
++ .name = "ltq_vrx200",
++ .resource = ltq_vrx200_resources,
++ .num_resources = 1,
++ .id = -1,
++};
++
++void __init
++ltq_register_vrx200(struct ltq_eth_data *eth)
++{
++ ltq_vrx200.dev.platform_data = eth;
++ platform_device_register(&ltq_vrx200);
++}
+diff --git a/arch/mips/lantiq/xway/devices.h b/arch/mips/lantiq/xway/devices.h
+index d825cbd..08befd9 100644
+--- a/arch/mips/lantiq/xway/devices.h
++++ b/arch/mips/lantiq/xway/devices.h
+@@ -17,5 +17,6 @@ extern void ltq_register_gpio_stp(void);
+ extern void ltq_register_ase_asc(void);
+ extern void ltq_register_etop(struct ltq_eth_data *eth);
+ extern void xway_register_nand(struct mtd_partition *parts, int count);
++extern void ltq_register_vrx200(struct ltq_eth_data *eth);
+
+ #endif
+diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
+index 597f4d4..2035cab 100644
+--- a/drivers/net/ethernet/Kconfig
++++ b/drivers/net/ethernet/Kconfig
+@@ -84,6 +84,12 @@ config LANTIQ_ETOP
+ ---help---
+ Support for the MII0 inside the Lantiq SoC
+
++config LANTIQ_VRX200
++ tristate "Lantiq SoC vrx200 driver"
++ depends on SOC_TYPE_XWAY
++ ---help---
++ Support for the MII0 inside the Lantiq SoC
++
+ source "drivers/net/ethernet/marvell/Kconfig"
+ source "drivers/net/ethernet/mellanox/Kconfig"
+ source "drivers/net/ethernet/micrel/Kconfig"
+diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
+index be5dde0..4fde2be 100644
+--- a/drivers/net/ethernet/Makefile
++++ b/drivers/net/ethernet/Makefile
+@@ -35,6 +35,7 @@ obj-$(CONFIG_IP1000) += icplus/
+ obj-$(CONFIG_JME) += jme.o
+ obj-$(CONFIG_KORINA) += korina.o
+ obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
++obj-$(CONFIG_LANTIQ_VRX200) += lantiq_vrx200.o
+ obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/
+ obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/
+ obj-$(CONFIG_NET_VENDOR_MICREL) += micrel/
+diff --git a/drivers/net/ethernet/lantiq_vrx200.c b/drivers/net/ethernet/lantiq_vrx200.c
+new file mode 100644
+index 0000000..d79d380
+--- /dev/null
++++ b/drivers/net/ethernet/lantiq_vrx200.c
+@@ -0,0 +1,1358 @@
++/*
++ * 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.
++ *
++ * 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) 2011 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/interrupt.h>
++#include <linux/uaccess.h>
++#include <linux/in.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/phy.h>
++#include <linux/ip.h>
++#include <linux/tcp.h>
++#include <linux/skbuff.h>
++#include <linux/mm.h>
++#include <linux/platform_device.h>
++#include <linux/ethtool.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/io.h>
++#include <linux/dma-mapping.h>
++#include <linux/module.h>
++#include <linux/clk.h>
++
++#include <asm/checksum.h>
++
++#include <lantiq_soc.h>
++#include <xway_dma.h>
++#include <lantiq_platform.h>
++
++#define LTQ_SWITCH_BASE 0x1E108000
++#define LTQ_SWITCH_CORE_BASE LTQ_SWITCH_BASE
++#define LTQ_SWITCH_TOP_PDI_BASE LTQ_SWITCH_CORE_BASE
++#define LTQ_SWITCH_BM_PDI_BASE (LTQ_SWITCH_CORE_BASE + 4 * 0x40)
++#define LTQ_SWITCH_MAC_PDI_0_BASE (LTQ_SWITCH_CORE_BASE + 4 * 0x900)
++#define LTQ_SWITCH_MAC_PDI_X_BASE(x) (LTQ_SWITCH_MAC_PDI_0_BASE + x * 0x30)
++#define LTQ_SWITCH_TOPLEVEL_BASE (LTQ_SWITCH_BASE + 4 * 0xC40)
++#define LTQ_SWITCH_MDIO_PDI_BASE (LTQ_SWITCH_TOPLEVEL_BASE)
++#define LTQ_SWITCH_MII_PDI_BASE (LTQ_SWITCH_TOPLEVEL_BASE + 4 * 0x36)
++#define LTQ_SWITCH_PMAC_PDI_BASE (LTQ_SWITCH_TOPLEVEL_BASE + 4 * 0x82)
++
++#define LTQ_ETHSW_MAC_CTRL0_PADEN (1 << 8)
++#define LTQ_ETHSW_MAC_CTRL0_FCS (1 << 7)
++#define LTQ_ETHSW_MAC_CTRL1_SHORTPRE (1 << 8)
++#define LTQ_ETHSW_MAC_CTRL2_MLEN (1 << 3)
++#define LTQ_ETHSW_MAC_CTRL2_LCHKL (1 << 2)
++#define LTQ_ETHSW_MAC_CTRL2_LCHKS_DIS 0
++#define LTQ_ETHSW_MAC_CTRL2_LCHKS_UNTAG 1
++#define LTQ_ETHSW_MAC_CTRL2_LCHKS_TAG 2
++#define LTQ_ETHSW_MAC_CTRL6_RBUF_DLY_WP_SHIFT 9
++#define LTQ_ETHSW_MAC_CTRL6_RXBUF_BYPASS (1 << 6)
++#define LTQ_ETHSW_GLOB_CTRL_SE (1 << 15)
++#define LTQ_ETHSW_MDC_CFG1_MCEN (1 << 8)
++#define LTQ_ETHSW_PMAC_HD_CTL_FC (1 << 10)
++#define LTQ_ETHSW_PMAC_HD_CTL_RC (1 << 4)
++#define LTQ_ETHSW_PMAC_HD_CTL_AC (1 << 2)
++#define ADVERTIZE_MPD (1 << 10)
++
++#define MDIO_DEVAD_NONE (-1)
++
++#define LTQ_ETH_RX_BUFFER_CNT PKTBUFSRX
++
++#define LTQ_MDIO_DRV_NAME "ltq-mdio"
++#define LTQ_ETH_DRV_NAME "ltq-eth"
++
++#define LTQ_ETHSW_MAX_GMAC 1
++#define LTQ_ETHSW_PMAC 1
++
++#define ltq_setbits(a, set) \
++ ltq_w32(ltq_r32(a) | (set), a)
++
++enum ltq_reset_modules {
++ LTQ_RESET_CORE,
++ LTQ_RESET_DMA,
++ LTQ_RESET_ETH,
++ LTQ_RESET_PHY,
++ LTQ_RESET_HARD,
++ LTQ_RESET_SOFT,
++};
++
++static inline void
++dbg_ltq_writel(void *a, unsigned int b)
++{
++ ltq_w32(b, a);
++}
++
++int ltq_reset_once(enum ltq_reset_modules module, ulong usec);
++
++struct ltq_ethsw_mac_pdi_x_regs {
++ u32 pstat; /* Port status */
++ u32 pisr; /* Interrupt status */
++ u32 pier; /* Interrupt enable */
++ u32 ctrl_0; /* Control 0 */
++ u32 ctrl_1; /* Control 1 */
++ u32 ctrl_2; /* Control 2 */
++ u32 ctrl_3; /* Control 3 */
++ u32 ctrl_4; /* Control 4 */
++ u32 ctrl_5; /* Control 5 */
++ u32 ctrl_6; /* Control 6 */
++ u32 bufst; /* TX/RX buffer control */
++ u32 testen; /* Test enable */
++};
++
++struct ltq_ethsw_mac_pdi_regs {
++ struct ltq_ethsw_mac_pdi_x_regs mac[12];
++};
++
++struct ltq_ethsw_mdio_pdi_regs {
++ u32 glob_ctrl; /* Global control 0 */
++ u32 rsvd0[7];
++ u32 mdio_ctrl; /* MDIO control */
++ u32 mdio_read; /* MDIO read data */
++ u32 mdio_write; /* MDIO write data */
++ u32 mdc_cfg_0; /* MDC clock configuration 0 */
++ u32 mdc_cfg_1; /* MDC clock configuration 1 */
++ u32 rsvd[3];
++ u32 phy_addr_5; /* PHY address port 5 */
++ u32 phy_addr_4; /* PHY address port 4 */
++ u32 phy_addr_3; /* PHY address port 3 */
++ u32 phy_addr_2; /* PHY address port 2 */
++ u32 phy_addr_1; /* PHY address port 1 */
++ u32 phy_addr_0; /* PHY address port 0 */
++ u32 mdio_stat_0; /* MDIO PHY polling status port 0 */
++ u32 mdio_stat_1; /* MDIO PHY polling status port 1 */
++ u32 mdio_stat_2; /* MDIO PHY polling status port 2 */
++ u32 mdio_stat_3; /* MDIO PHY polling status port 3 */
++ u32 mdio_stat_4; /* MDIO PHY polling status port 4 */
++ u32 mdio_stat_5; /* MDIO PHY polling status port 5 */
++};
++
++struct ltq_ethsw_mii_pdi_regs {
++ u32 mii_cfg0; /* xMII port 0 configuration */
++ u32 pcdu0; /* Port 0 clock delay configuration */
++ u32 mii_cfg1; /* xMII port 1 configuration */
++ u32 pcdu1; /* Port 1 clock delay configuration */
++ u32 mii_cfg2; /* xMII port 2 configuration */
++ u32 rsvd0;
++ u32 mii_cfg3; /* xMII port 3 configuration */
++ u32 rsvd1;
++ u32 mii_cfg4; /* xMII port 4 configuration */
++ u32 rsvd2;
++ u32 mii_cfg5; /* xMII port 5 configuration */
++ u32 pcdu5; /* Port 5 clock delay configuration */
++};
++
++struct ltq_ethsw_pmac_pdi_regs {
++ u32 hd_ctl; /* PMAC header control */
++ u32 tl; /* PMAC type/length */
++ u32 sa1; /* PMAC source address 1 */
++ u32 sa2; /* PMAC source address 2 */
++ u32 sa3; /* PMAC source address 3 */
++ u32 da1; /* PMAC destination address 1 */
++ u32 da2; /* PMAC destination address 2 */
++ u32 da3; /* PMAC destination address 3 */
++ u32 vlan; /* PMAC VLAN */
++ u32 rx_ipg; /* PMAC interpacket gap in RX direction */
++ u32 st_etype; /* PMAC special tag ethertype */
++ u32 ewan; /* PMAC ethernet WAN group */
++};
++
++struct ltq_mdio_phy_addr_reg {
++ union {
++ struct {
++ unsigned rsvd:1;
++ unsigned lnkst:2; /* Link status control */
++ unsigned speed:2; /* Speed control */
++ unsigned fdup:2; /* Full duplex control */
++ unsigned fcontx:2; /* Flow control mode TX */
++ unsigned fconrx:2; /* Flow control mode RX */
++ unsigned addr:5; /* PHY address */
++ } bits;
++ u16 val;
++ };
++};
++
++enum ltq_mdio_phy_addr_lnkst {
++ LTQ_MDIO_PHY_ADDR_LNKST_AUTO = 0,
++ LTQ_MDIO_PHY_ADDR_LNKST_UP = 1,
++ LTQ_MDIO_PHY_ADDR_LNKST_DOWN = 2,
++};
++
++enum ltq_mdio_phy_addr_speed {
++ LTQ_MDIO_PHY_ADDR_SPEED_M10 = 0,
++ LTQ_MDIO_PHY_ADDR_SPEED_M100 = 1,
++ LTQ_MDIO_PHY_ADDR_SPEED_G1 = 2,
++ LTQ_MDIO_PHY_ADDR_SPEED_AUTO = 3,
++};
++
++enum ltq_mdio_phy_addr_fdup {
++ LTQ_MDIO_PHY_ADDR_FDUP_AUTO = 0,
++ LTQ_MDIO_PHY_ADDR_FDUP_ENABLE = 1,
++ LTQ_MDIO_PHY_ADDR_FDUP_DISABLE = 3,
++};
++
++enum ltq_mdio_phy_addr_fcon {
++ LTQ_MDIO_PHY_ADDR_FCON_AUTO = 0,
++ LTQ_MDIO_PHY_ADDR_FCON_ENABLE = 1,
++ LTQ_MDIO_PHY_ADDR_FCON_DISABLE = 3,
++};
++
++struct ltq_mii_mii_cfg_reg {
++ union {
++ struct {
++ unsigned res:1; /* Hardware reset */
++ unsigned en:1; /* xMII interface enable */
++ unsigned isol:1; /* xMII interface isolate */
++ unsigned ldclkdis:1; /* Link down clock disable */
++ unsigned rsvd:1;
++ unsigned crs:2; /* CRS sensitivity config */
++ unsigned rgmii_ibs:1; /* RGMII In Band status */
++ unsigned rmii:1; /* RMII ref clock direction */
++ unsigned miirate:3; /* xMII interface clock rate */
++ unsigned miimode:4; /* xMII interface mode */
++ } bits;
++ u16 val;
++ };
++};
++
++enum ltq_mii_mii_cfg_miirate {
++ LTQ_MII_MII_CFG_MIIRATE_M2P5 = 0,
++ LTQ_MII_MII_CFG_MIIRATE_M25 = 1,
++ LTQ_MII_MII_CFG_MIIRATE_M125 = 2,
++ LTQ_MII_MII_CFG_MIIRATE_M50 = 3,
++ LTQ_MII_MII_CFG_MIIRATE_AUTO = 4,
++};
++
++enum ltq_mii_mii_cfg_miimode {
++ LTQ_MII_MII_CFG_MIIMODE_MIIP = 0,
++ LTQ_MII_MII_CFG_MIIMODE_MIIM = 1,
++ LTQ_MII_MII_CFG_MIIMODE_RMIIP = 2,
++ LTQ_MII_MII_CFG_MIIMODE_RMIIM = 3,
++ LTQ_MII_MII_CFG_MIIMODE_RGMII = 4,
++};
++
++struct ltq_eth_priv {
++ struct ltq_dma_device *dma_dev;
++ struct mii_dev *bus;
++ struct eth_device *dev;
++ struct phy_device *phymap[LTQ_ETHSW_MAX_GMAC];
++ int rx_num;
++};
++
++enum ltq_mdio_mbusy {
++ LTQ_MDIO_MBUSY_IDLE = 0,
++ LTQ_MDIO_MBUSY_BUSY = 1,
++};
++
++enum ltq_mdio_op {
++ LTQ_MDIO_OP_WRITE = 1,
++ LTQ_MDIO_OP_READ = 2,
++};
++
++struct ltq_mdio_access {
++ union {
++ struct {
++ unsigned rsvd:3;
++ unsigned mbusy:1;
++ unsigned op:2;
++ unsigned phyad:5;
++ unsigned regad:5;
++ } bits;
++ u16 val;
++ };
++};
++
++enum LTQ_ETH_PORT_FLAGS {
++ LTQ_ETH_PORT_NONE = 0,
++ LTQ_ETH_PORT_PHY = 1,
++ LTQ_ETH_PORT_SWITCH = (1 << 1),
++ LTQ_ETH_PORT_MAC = (1 << 2),
++};
++
++struct ltq_eth_port_config {
++ u8 num;
++ u8 phy_addr;
++ u16 flags;
++ phy_interface_t phy_if;
++};
++
++struct ltq_eth_board_config {
++ const struct ltq_eth_port_config *ports;
++ int num_ports;
++};
++
++static const struct ltq_eth_port_config eth_port_config[] = {
++ /* GMAC0: external Lantiq PEF7071 10/100/1000 PHY for LAN port 0 */
++ { 0, 0x0, LTQ_ETH_PORT_PHY, PHY_INTERFACE_MODE_RGMII },
++ /* GMAC1: external Lantiq PEF7071 10/100/1000 PHY for LAN port 1 */
++ { 1, 0x1, LTQ_ETH_PORT_PHY, PHY_INTERFACE_MODE_RGMII },
++};
++
++static const struct ltq_eth_board_config board_config = {
++ .ports = eth_port_config,
++ .num_ports = ARRAY_SIZE(eth_port_config),
++};
++
++static struct ltq_ethsw_mac_pdi_regs *ltq_ethsw_mac_pdi_regs =
++ (struct ltq_ethsw_mac_pdi_regs *) CKSEG1ADDR(LTQ_SWITCH_MAC_PDI_0_BASE);
++
++static struct ltq_ethsw_mdio_pdi_regs *ltq_ethsw_mdio_pdi_regs =
++ (struct ltq_ethsw_mdio_pdi_regs *) CKSEG1ADDR(LTQ_SWITCH_MDIO_PDI_BASE);
++
++static struct ltq_ethsw_mii_pdi_regs *ltq_ethsw_mii_pdi_regs =
++ (struct ltq_ethsw_mii_pdi_regs *) CKSEG1ADDR(LTQ_SWITCH_MII_PDI_BASE);
++
++static struct ltq_ethsw_pmac_pdi_regs *ltq_ethsw_pmac_pdi_regs =
++ (struct ltq_ethsw_pmac_pdi_regs *) CKSEG1ADDR(LTQ_SWITCH_PMAC_PDI_BASE);
++
++
++#define MAX_DMA_CHAN 0x8
++#define MAX_DMA_CRC_LEN 0x4
++#define MAX_DMA_DATA_LEN 0x600
++
++/* use 2 static channels for TX/RX
++ depending on the SoC we need to use different DMA channels for ethernet */
++#define LTQ_ETOP_TX_CHANNEL 1
++#define LTQ_ETOP_RX_CHANNEL 0
++
++#define IS_TX(x) (x == LTQ_ETOP_TX_CHANNEL)
++#define IS_RX(x) (x == LTQ_ETOP_RX_CHANNEL)
++
++#define DRV_VERSION "1.0"
++
++static void __iomem *ltq_vrx200_membase;
++
++struct ltq_vrx200_chan {
++ int idx;
++ int tx_free;
++ struct net_device *netdev;
++ struct napi_struct napi;
++ struct ltq_dma_channel dma;
++ struct sk_buff *skb[LTQ_DESC_NUM];
++};
++
++struct ltq_vrx200_priv {
++ struct net_device *netdev;
++ struct ltq_eth_data *pldata;
++ struct resource *res;
++
++ struct mii_bus *mii_bus;
++ struct phy_device *phydev;
++
++ struct ltq_vrx200_chan ch[MAX_DMA_CHAN];
++ int tx_free[MAX_DMA_CHAN >> 1];
++
++ spinlock_t lock;
++
++ struct clk *clk_ppe;
++};
++
++static int ltq_vrx200_mdio_wr(struct mii_bus *bus, int phy_addr,
++ int phy_reg, u16 phy_data);
++
++static int
++ltq_vrx200_alloc_skb(struct ltq_vrx200_chan *ch)
++{
++ ch->skb[ch->dma.desc] = dev_alloc_skb(MAX_DMA_DATA_LEN);
++ if (!ch->skb[ch->dma.desc])
++ return -ENOMEM;
++ ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL,
++ ch->skb[ch->dma.desc]->data, MAX_DMA_DATA_LEN,
++ DMA_FROM_DEVICE);
++ ch->dma.desc_base[ch->dma.desc].addr =
++ CPHYSADDR(ch->skb[ch->dma.desc]->data);
++ ch->dma.desc_base[ch->dma.desc].ctl =
++ LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
++ MAX_DMA_DATA_LEN;
++ skb_reserve(ch->skb[ch->dma.desc], NET_IP_ALIGN);
++ return 0;
++}
++
++static void
++ltq_vrx200_hw_receive(struct ltq_vrx200_chan *ch)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(ch->netdev);
++ struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
++ struct sk_buff *skb = ch->skb[ch->dma.desc];
++ int len = (desc->ctl & LTQ_DMA_SIZE_MASK) - MAX_DMA_CRC_LEN;
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ if (ltq_vrx200_alloc_skb(ch)) {
++ netdev_err(ch->netdev,
++ "failed to allocate new rx buffer, stopping DMA\n");
++ ltq_dma_close(&ch->dma);
++ }
++ ch->dma.desc++;
++ ch->dma.desc %= LTQ_DESC_NUM;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ skb_put(skb, len);
++ skb->dev = ch->netdev;
++ skb->protocol = eth_type_trans(skb, ch->netdev);
++ netif_receive_skb(skb);
++}
++
++static int
++ltq_vrx200_poll_rx(struct napi_struct *napi, int budget)
++{
++ struct ltq_vrx200_chan *ch = container_of(napi,
++ struct ltq_vrx200_chan, napi);
++ struct ltq_vrx200_priv *priv = netdev_priv(ch->netdev);
++ int rx = 0;
++ int complete = 0;
++ unsigned long flags;
++
++ while ((rx < budget) && !complete) {
++ struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
++
++ if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
++ ltq_vrx200_hw_receive(ch);
++ rx++;
++ } else {
++ complete = 1;
++ }
++ }
++ if (complete || !rx) {
++ napi_complete(&ch->napi);
++ spin_lock_irqsave(&priv->lock, flags);
++ ltq_dma_ack_irq(&ch->dma);
++ spin_unlock_irqrestore(&priv->lock, flags);
++ }
++ return rx;
++}
++
++static int
++ltq_vrx200_poll_tx(struct napi_struct *napi, int budget)
++{
++ struct ltq_vrx200_chan *ch =
++ container_of(napi, struct ltq_vrx200_chan, napi);
++ struct ltq_vrx200_priv *priv = netdev_priv(ch->netdev);
++ struct netdev_queue *txq =
++ netdev_get_tx_queue(ch->netdev, ch->idx >> 1);
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ while ((ch->dma.desc_base[ch->tx_free].ctl &
++ (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
++ dev_kfree_skb_any(ch->skb[ch->tx_free]);
++ ch->skb[ch->tx_free] = NULL;
++ memset(&ch->dma.desc_base[ch->tx_free], 0,
++ sizeof(struct ltq_dma_desc));
++ ch->tx_free++;
++ ch->tx_free %= LTQ_DESC_NUM;
++ }
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ if (netif_tx_queue_stopped(txq))
++ netif_tx_start_queue(txq);
++ napi_complete(&ch->napi);
++ spin_lock_irqsave(&priv->lock, flags);
++ ltq_dma_ack_irq(&ch->dma);
++ spin_unlock_irqrestore(&priv->lock, flags);
++ return 1;
++}
++
++static irqreturn_t
++ltq_vrx200_dma_irq(int irq, void *_priv)
++{
++ struct ltq_vrx200_priv *priv = _priv;
++ int ch = irq - LTQ_DMA_ETOP;
++
++ napi_schedule(&priv->ch[ch].napi);
++ return IRQ_HANDLED;
++}
++
++static void
++ltq_vrx200_free_channel(struct net_device *dev, struct ltq_vrx200_chan *ch)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++
++ ltq_dma_free(&ch->dma);
++ if (ch->dma.irq)
++ free_irq(ch->dma.irq, priv);
++ if (IS_RX(ch->idx)) {
++ int desc;
++ for (desc = 0; desc < LTQ_DESC_NUM; desc++)
++ dev_kfree_skb_any(ch->skb[ch->dma.desc]);
++ }
++}
++
++static void
++ltq_vrx200_hw_exit(struct net_device *dev)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++ int i;
++
++ clk_disable(priv->clk_ppe);
++
++ for (i = 0; i < MAX_DMA_CHAN; i++)
++ if (IS_TX(i) || IS_RX(i))
++ ltq_vrx200_free_channel(dev, &priv->ch[i]);
++}
++
++static void *ltq_eth_phy_addr_reg(int num)
++{
++ switch (num) {
++ case 0:
++ return &ltq_ethsw_mdio_pdi_regs->phy_addr_0;
++ case 1:
++ return &ltq_ethsw_mdio_pdi_regs->phy_addr_1;
++ case 2:
++ return &ltq_ethsw_mdio_pdi_regs->phy_addr_2;
++ case 3:
++ return &ltq_ethsw_mdio_pdi_regs->phy_addr_3;
++ case 4:
++ return &ltq_ethsw_mdio_pdi_regs->phy_addr_4;
++ case 5:
++ return &ltq_ethsw_mdio_pdi_regs->phy_addr_5;
++ }
++
++ return NULL;
++}
++
++static void *ltq_eth_mii_cfg_reg(int num)
++{
++ switch (num) {
++ case 0:
++ return &ltq_ethsw_mii_pdi_regs->mii_cfg0;
++ case 1:
++ return &ltq_ethsw_mii_pdi_regs->mii_cfg1;
++ case 2:
++ return &ltq_ethsw_mii_pdi_regs->mii_cfg2;
++ case 3:
++ return &ltq_ethsw_mii_pdi_regs->mii_cfg3;
++ case 4:
++ return &ltq_ethsw_mii_pdi_regs->mii_cfg4;
++ case 5:
++ return &ltq_ethsw_mii_pdi_regs->mii_cfg5;
++ }
++
++ return NULL;
++}
++
++static void ltq_eth_gmac_update(struct phy_device *phydev, int num)
++{
++ struct ltq_mdio_phy_addr_reg phy_addr_reg;
++ struct ltq_mii_mii_cfg_reg mii_cfg_reg;
++ void *phy_addr = ltq_eth_phy_addr_reg(num);
++ void *mii_cfg = ltq_eth_mii_cfg_reg(num);
++
++ phy_addr_reg.val = ltq_r32(phy_addr);
++ mii_cfg_reg.val = ltq_r32(mii_cfg);
++
++ phy_addr_reg.bits.addr = phydev->addr;
++
++ if (phydev->link)
++ phy_addr_reg.bits.lnkst = LTQ_MDIO_PHY_ADDR_LNKST_UP;
++ else
++ phy_addr_reg.bits.lnkst = LTQ_MDIO_PHY_ADDR_LNKST_DOWN;
++
++ switch (phydev->speed) {
++ case SPEED_1000:
++ phy_addr_reg.bits.speed = LTQ_MDIO_PHY_ADDR_SPEED_G1;
++ mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M125;
++ break;
++ case SPEED_100:
++ phy_addr_reg.bits.speed = LTQ_MDIO_PHY_ADDR_SPEED_M100;
++ switch (mii_cfg_reg.bits.miimode) {
++ case LTQ_MII_MII_CFG_MIIMODE_RMIIM:
++ case LTQ_MII_MII_CFG_MIIMODE_RMIIP:
++ mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M50;
++ break;
++ default:
++ mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M25;
++ break;
++ }
++ break;
++ default:
++ phy_addr_reg.bits.speed = LTQ_MDIO_PHY_ADDR_SPEED_M10;
++ mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M2P5;
++ break;
++ }
++
++ if (phydev->duplex == DUPLEX_FULL)
++ phy_addr_reg.bits.fdup = LTQ_MDIO_PHY_ADDR_FDUP_ENABLE;
++ else
++ phy_addr_reg.bits.fdup = LTQ_MDIO_PHY_ADDR_FDUP_DISABLE;
++
++ dbg_ltq_writel(phy_addr, phy_addr_reg.val);
++ dbg_ltq_writel(mii_cfg, mii_cfg_reg.val);
++ udelay(1);
++}
++
++
++static void ltq_eth_port_config(struct ltq_vrx200_priv *priv,
++ const struct ltq_eth_port_config *port)
++{
++ struct ltq_mii_mii_cfg_reg mii_cfg_reg;
++ void *mii_cfg = ltq_eth_mii_cfg_reg(port->num);
++ int setup_gpio = 0;
++
++ mii_cfg_reg.val = ltq_r32(mii_cfg);
++
++
++ switch (port->num) {
++ case 0: /* xMII0 */
++ case 1: /* xMII1 */
++ switch (port->phy_if) {
++ case PHY_INTERFACE_MODE_MII:
++ if (port->flags & LTQ_ETH_PORT_PHY)
++ /* MII MAC mode, connected to external PHY */
++ mii_cfg_reg.bits.miimode =
++ LTQ_MII_MII_CFG_MIIMODE_MIIM;
++ else
++ /* MII PHY mode, connected to external MAC */
++ mii_cfg_reg.bits.miimode =
++ LTQ_MII_MII_CFG_MIIMODE_MIIP;
++ setup_gpio = 1;
++ break;
++ case PHY_INTERFACE_MODE_RMII:
++ if (port->flags & LTQ_ETH_PORT_PHY)
++ /* RMII MAC mode, connected to external PHY */
++ mii_cfg_reg.bits.miimode =
++ LTQ_MII_MII_CFG_MIIMODE_RMIIM;
++ else
++ /* RMII PHY mode, connected to external MAC */
++ mii_cfg_reg.bits.miimode =
++ LTQ_MII_MII_CFG_MIIMODE_RMIIP;
++ setup_gpio = 1;
++ break;
++ case PHY_INTERFACE_MODE_RGMII:
++ /* RGMII MAC mode, connected to external PHY */
++ mii_cfg_reg.bits.miimode =
++ LTQ_MII_MII_CFG_MIIMODE_RGMII;
++ setup_gpio = 1;
++ break;
++ default:
++ break;
++ }
++ break;
++ case 2: /* internal GPHY0 */
++ case 3: /* internal GPHY0 */
++ case 4: /* internal GPHY1 */
++ switch (port->phy_if) {
++ case PHY_INTERFACE_MODE_MII:
++ case PHY_INTERFACE_MODE_GMII:
++ /* MII MAC mode, connected to internal GPHY */
++ mii_cfg_reg.bits.miimode =
++ LTQ_MII_MII_CFG_MIIMODE_MIIM;
++ setup_gpio = 1;
++ break;
++ default:
++ break;
++ }
++ break;
++ case 5: /* internal GPHY1 or xMII2 */
++ switch (port->phy_if) {
++ case PHY_INTERFACE_MODE_MII:
++ /* MII MAC mode, connected to internal GPHY */
++ mii_cfg_reg.bits.miimode =
++ LTQ_MII_MII_CFG_MIIMODE_MIIM;
++ setup_gpio = 1;
++ break;
++ case PHY_INTERFACE_MODE_RGMII:
++ /* RGMII MAC mode, connected to external PHY */
++ mii_cfg_reg.bits.miimode =
++ LTQ_MII_MII_CFG_MIIMODE_RGMII;
++ setup_gpio = 1;
++ break;
++ default:
++ break;
++ }
++ break;
++ default:
++ break;
++ }
++
++ /* Enable MII interface */
++ mii_cfg_reg.bits.en = port->flags ? 1 : 0;
++ dbg_ltq_writel(mii_cfg, mii_cfg_reg.val);
++
++}
++
++static void ltq_eth_gmac_init(int num)
++{
++ struct ltq_mdio_phy_addr_reg phy_addr_reg;
++ struct ltq_mii_mii_cfg_reg mii_cfg_reg;
++ void *phy_addr = ltq_eth_phy_addr_reg(num);
++ void *mii_cfg = ltq_eth_mii_cfg_reg(num);
++ struct ltq_ethsw_mac_pdi_x_regs *mac_pdi_regs;
++
++ mac_pdi_regs = &ltq_ethsw_mac_pdi_regs->mac[num];
++
++ /* Reset PHY status to link down */
++ phy_addr_reg.val = ltq_r32(phy_addr);
++ phy_addr_reg.bits.addr = num;
++ phy_addr_reg.bits.lnkst = LTQ_MDIO_PHY_ADDR_LNKST_DOWN;
++ phy_addr_reg.bits.speed = LTQ_MDIO_PHY_ADDR_SPEED_M10;
++ phy_addr_reg.bits.fdup = LTQ_MDIO_PHY_ADDR_FDUP_DISABLE;
++ dbg_ltq_writel(phy_addr, phy_addr_reg.val);
++
++ /* Reset and disable MII interface */
++ mii_cfg_reg.val = ltq_r32(mii_cfg);
++ mii_cfg_reg.bits.en = 0;
++ mii_cfg_reg.bits.res = 1;
++ mii_cfg_reg.bits.miirate = LTQ_MII_MII_CFG_MIIRATE_M2P5;
++ dbg_ltq_writel(mii_cfg, mii_cfg_reg.val);
++
++ /*
++ * Enable padding of short frames, enable frame checksum generation
++ * in transmit direction
++ */
++ dbg_ltq_writel(&mac_pdi_regs->ctrl_0, LTQ_ETHSW_MAC_CTRL0_PADEN |
++ LTQ_ETHSW_MAC_CTRL0_FCS);
++
++ /* Set inter packet gap size to 12 bytes */
++ dbg_ltq_writel(&mac_pdi_regs->ctrl_1, 12);
++
++ /*
++ * Configure frame length checks:
++ * - allow jumbo frames
++ * - enable long length check
++ * - enable short length without VLAN tags
++ */
++ dbg_ltq_writel(&mac_pdi_regs->ctrl_2, LTQ_ETHSW_MAC_CTRL2_MLEN |
++ LTQ_ETHSW_MAC_CTRL2_LCHKL |
++ LTQ_ETHSW_MAC_CTRL2_LCHKS_UNTAG);
++}
++
++
++static void ltq_eth_pmac_init(void)
++{
++ struct ltq_ethsw_mac_pdi_x_regs *mac_pdi_regs;
++
++ mac_pdi_regs = &ltq_ethsw_mac_pdi_regs->mac[LTQ_ETHSW_PMAC];
++
++ /*
++ * Enable padding of short frames, enable frame checksum generation
++ * in transmit direction
++ */
++ dbg_ltq_writel(&mac_pdi_regs->ctrl_0, LTQ_ETHSW_MAC_CTRL0_PADEN |
++ LTQ_ETHSW_MAC_CTRL0_FCS);
++
++ /*
++ * Configure frame length checks:
++ * - allow jumbo frames
++ * - enable long length check
++ * - enable short length without VLAN tags
++ */
++ dbg_ltq_writel(&mac_pdi_regs->ctrl_2, LTQ_ETHSW_MAC_CTRL2_MLEN |
++ LTQ_ETHSW_MAC_CTRL2_LCHKL |
++ LTQ_ETHSW_MAC_CTRL2_LCHKS_UNTAG);
++
++ /*
++ * Apply workaround for buffer congestion:
++ * - shorten preambel to 1 byte
++ * - set minimum inter packet gap size to 7 bytes
++ * - enable receive buffer bypass mode
++ */
++ dbg_ltq_writel(&mac_pdi_regs->ctrl_1, LTQ_ETHSW_MAC_CTRL1_SHORTPRE | 7);
++ dbg_ltq_writel(&mac_pdi_regs->ctrl_6,
++ (6 << LTQ_ETHSW_MAC_CTRL6_RBUF_DLY_WP_SHIFT) |
++ LTQ_ETHSW_MAC_CTRL6_RXBUF_BYPASS);
++
++ /* Set request assertion threshold to 8, IPG counter to 11 */
++ dbg_ltq_writel(&ltq_ethsw_pmac_pdi_regs->rx_ipg, 0x8B);
++
++ /*
++ * Configure frame header control:
++ * - enable reaction on pause frames (flow control)
++ * - remove CRC for packets from PMAC to DMA
++ * - add CRC for packets from DMA to PMAC
++ */
++ dbg_ltq_writel(&ltq_ethsw_pmac_pdi_regs->hd_ctl, LTQ_ETHSW_PMAC_HD_CTL_FC |
++ /*LTQ_ETHSW_PMAC_HD_CTL_RC | */LTQ_ETHSW_PMAC_HD_CTL_AC);
++}
++
++static int
++ltq_vrx200_hw_init(struct net_device *dev)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++ int err = 0;
++ int i;
++
++ netdev_info(dev, "setting up dma\n");
++ ltq_dma_init_port(DMA_PORT_ETOP);
++
++ netdev_info(dev, "setting up pmu\n");
++ clk_enable(priv->clk_ppe);
++
++ /* Reset ethernet and switch subsystems */
++ netdev_info(dev, "reset core\n");
++ ltq_reset_once(BIT(8), 10);
++
++ /* Enable switch macro */
++ ltq_setbits(&ltq_ethsw_mdio_pdi_regs->glob_ctrl,
++ LTQ_ETHSW_GLOB_CTRL_SE);
++
++ /* Disable MDIO auto-polling for all ports */
++ dbg_ltq_writel(&ltq_ethsw_mdio_pdi_regs->mdc_cfg_0, 0);
++
++ /*
++ * Enable and set MDIO management clock to 2.5 MHz. This is the
++ * maximum clock for FE PHYs.
++ * Formula for clock is:
++ *
++ * 50 MHz
++ * x = ----------- - 1
++ * 2 * f_MDC
++ */
++ dbg_ltq_writel(&ltq_ethsw_mdio_pdi_regs->mdc_cfg_1,
++ LTQ_ETHSW_MDC_CFG1_MCEN | 9);
++
++ /* Init MAC connected to CPU */
++ ltq_eth_pmac_init();
++
++ /* Init MACs connected to external MII interfaces */
++ for (i = 0; i < LTQ_ETHSW_MAX_GMAC; i++)
++ ltq_eth_gmac_init(i);
++
++ for (i = 0; i < MAX_DMA_CHAN && !err; i++) {
++ int irq = LTQ_DMA_ETOP + i;
++ struct ltq_vrx200_chan *ch = &priv->ch[i];
++
++ ch->idx = ch->dma.nr = i;
++
++ if (IS_TX(i)) {
++ ltq_dma_alloc_tx(&ch->dma);
++ err = request_irq(irq, ltq_vrx200_dma_irq, IRQF_DISABLED,
++ "vrx200_tx", priv);
++ } else if (IS_RX(i)) {
++ ltq_dma_alloc_rx(&ch->dma);
++ for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
++ ch->dma.desc++)
++ if (ltq_vrx200_alloc_skb(ch))
++ err = -ENOMEM;
++ ch->dma.desc = 0;
++ err = request_irq(irq, ltq_vrx200_dma_irq, IRQF_DISABLED,
++ "vrx200_rx", priv);
++ }
++ if (!err)
++ ch->dma.irq = irq;
++ }
++ for (i = 0; i < board_config.num_ports; i++)
++ ltq_eth_port_config(priv, &board_config.ports[i]);
++ return err;
++}
++
++static void
++ltq_vrx200_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
++{
++ strcpy(info->driver, "Lantiq ETOP");
++ strcpy(info->bus_info, "internal");
++ strcpy(info->version, DRV_VERSION);
++}
++
++static int
++ltq_vrx200_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++
++ return phy_ethtool_gset(priv->phydev, cmd);
++}
++
++static int
++ltq_vrx200_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++
++ return phy_ethtool_sset(priv->phydev, cmd);
++}
++
++static int
++ltq_vrx200_nway_reset(struct net_device *dev)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++
++ return phy_start_aneg(priv->phydev);
++}
++
++static const struct ethtool_ops ltq_vrx200_ethtool_ops = {
++ .get_drvinfo = ltq_vrx200_get_drvinfo,
++ .get_settings = ltq_vrx200_get_settings,
++ .set_settings = ltq_vrx200_set_settings,
++ .nway_reset = ltq_vrx200_nway_reset,
++};
++
++static inline int ltq_mdio_poll(struct mii_bus *bus)
++{
++ struct ltq_mdio_access acc;
++ unsigned cnt = 10000;
++
++ while (likely(cnt--)) {
++ acc.val = ltq_r32(&ltq_ethsw_mdio_pdi_regs->mdio_ctrl);
++ if (!acc.bits.mbusy)
++ return 0;
++ }
++
++ return 1;
++}
++
++static int
++ltq_vrx200_mdio_wr(struct mii_bus *bus, int addr, int regnum, u16 val)
++{
++ struct ltq_mdio_access acc;
++ int ret;
++
++ acc.val = 0;
++ acc.bits.mbusy = LTQ_MDIO_MBUSY_BUSY;
++ acc.bits.op = LTQ_MDIO_OP_WRITE;
++ acc.bits.phyad = addr;
++ acc.bits.regad = regnum;
++
++ ret = ltq_mdio_poll(bus);
++ if (ret)
++ return ret;
++
++ dbg_ltq_writel(&ltq_ethsw_mdio_pdi_regs->mdio_write, val);
++ dbg_ltq_writel(&ltq_ethsw_mdio_pdi_regs->mdio_ctrl, acc.val);
++
++ return 0;
++}
++
++static int
++ltq_vrx200_mdio_rd(struct mii_bus *bus, int addr, int regnum)
++{
++ struct ltq_mdio_access acc;
++ int ret;
++
++ acc.val = 0;
++ acc.bits.mbusy = LTQ_MDIO_MBUSY_BUSY;
++ acc.bits.op = LTQ_MDIO_OP_READ;
++ acc.bits.phyad = addr;
++ acc.bits.regad = regnum;
++
++ ret = ltq_mdio_poll(bus);
++ if (ret)
++ goto timeout;
++
++ dbg_ltq_writel(&ltq_ethsw_mdio_pdi_regs->mdio_ctrl, acc.val);
++
++ ret = ltq_mdio_poll(bus);
++ if (ret)
++ goto timeout;
++
++ ret = ltq_r32(&ltq_ethsw_mdio_pdi_regs->mdio_read);
++
++ return ret;
++timeout:
++ return -1;
++}
++
++static void
++ltq_vrx200_mdio_link(struct net_device *dev)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++ ltq_eth_gmac_update(priv->phydev, 0);
++}
++
++static int
++ltq_vrx200_mdio_probe(struct net_device *dev)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++ struct phy_device *phydev = NULL;
++ int val;
++
++ phydev = priv->mii_bus->phy_map[0];
++
++ if (!phydev) {
++ netdev_err(dev, "no PHY found\n");
++ return -ENODEV;
++ }
++
++ phydev = phy_connect(dev, dev_name(&phydev->dev), &ltq_vrx200_mdio_link,
++ 0, 0);
++
++ if (IS_ERR(phydev)) {
++ netdev_err(dev, "Could not attach to PHY\n");
++ return PTR_ERR(phydev);
++ }
++
++ phydev->supported &= (SUPPORTED_10baseT_Half
++ | SUPPORTED_10baseT_Full
++ | SUPPORTED_100baseT_Half
++ | SUPPORTED_100baseT_Full
++ | SUPPORTED_1000baseT_Half
++ | SUPPORTED_1000baseT_Full
++ | SUPPORTED_Autoneg
++ | SUPPORTED_MII
++ | SUPPORTED_TP);
++ phydev->advertising = phydev->supported;
++ priv->phydev = phydev;
++
++ pr_info("%s: attached PHY [%s] (phy_addr=%s, irq=%d)\n",
++ dev->name, phydev->drv->name,
++ dev_name(&phydev->dev), phydev->irq);
++
++ val = ltq_vrx200_mdio_rd(priv->mii_bus, MDIO_DEVAD_NONE, MII_CTRL1000);
++ val |= ADVERTIZE_MPD;
++ ltq_vrx200_mdio_wr(priv->mii_bus, MDIO_DEVAD_NONE, MII_CTRL1000, val);
++ ltq_vrx200_mdio_wr(priv->mii_bus, 0, 0, 0x1040);
++
++ phy_start_aneg(phydev);
++
++ return 0;
++}
++
++static int
++ltq_vrx200_mdio_init(struct net_device *dev)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++ int i;
++ int err;
++
++ priv->mii_bus = mdiobus_alloc();
++ if (!priv->mii_bus) {
++ netdev_err(dev, "failed to allocate mii bus\n");
++ err = -ENOMEM;
++ goto err_out;
++ }
++
++ priv->mii_bus->priv = dev;
++ priv->mii_bus->read = ltq_vrx200_mdio_rd;
++ priv->mii_bus->write = ltq_vrx200_mdio_wr;
++ priv->mii_bus->name = "ltq_mii";
++ snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
++ priv->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
++ if (!priv->mii_bus->irq) {
++ err = -ENOMEM;
++ goto err_out_free_mdiobus;
++ }
++
++ for (i = 0; i < PHY_MAX_ADDR; ++i)
++ priv->mii_bus->irq[i] = PHY_POLL;
++
++ if (mdiobus_register(priv->mii_bus)) {
++ err = -ENXIO;
++ goto err_out_free_mdio_irq;
++ }
++
++ if (ltq_vrx200_mdio_probe(dev)) {
++ err = -ENXIO;
++ goto err_out_unregister_bus;
++ }
++ return 0;
++
++err_out_unregister_bus:
++ mdiobus_unregister(priv->mii_bus);
++err_out_free_mdio_irq:
++ kfree(priv->mii_bus->irq);
++err_out_free_mdiobus:
++ mdiobus_free(priv->mii_bus);
++err_out:
++ return err;
++}
++
++static void
++ltq_vrx200_mdio_cleanup(struct net_device *dev)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++
++ phy_disconnect(priv->phydev);
++ mdiobus_unregister(priv->mii_bus);
++ kfree(priv->mii_bus->irq);
++ mdiobus_free(priv->mii_bus);
++}
++
++void phy_dump(struct net_device *dev)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++ int i;
++ for (i = 0; i < 0x1F; i++) {
++ unsigned int val = ltq_vrx200_mdio_rd(priv->mii_bus, 0, i);
++ printk("%d %4X\n", i, val);
++ }
++}
++
++static int
++ltq_vrx200_open(struct net_device *dev)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++ int i;
++ unsigned long flags;
++
++ for (i = 0; i < MAX_DMA_CHAN; i++) {
++ struct ltq_vrx200_chan *ch = &priv->ch[i];
++
++ if (!IS_TX(i) && (!IS_RX(i)))
++ continue;
++ napi_enable(&ch->napi);
++ spin_lock_irqsave(&priv->lock, flags);
++ ltq_dma_open(&ch->dma);
++ spin_unlock_irqrestore(&priv->lock, flags);
++ }
++ if (priv->phydev) {
++ phy_start(priv->phydev);
++ phy_dump(dev);
++ }
++ netif_tx_start_all_queues(dev);
++ return 0;
++}
++
++static int
++ltq_vrx200_stop(struct net_device *dev)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++ int i;
++ unsigned long flags;
++
++ netif_tx_stop_all_queues(dev);
++ if (priv->phydev)
++ phy_stop(priv->phydev);
++ for (i = 0; i < MAX_DMA_CHAN; i++) {
++ struct ltq_vrx200_chan *ch = &priv->ch[i];
++
++ if (!IS_RX(i) && !IS_TX(i))
++ continue;
++ napi_disable(&ch->napi);
++ spin_lock_irqsave(&priv->lock, flags);
++ ltq_dma_close(&ch->dma);
++ spin_unlock_irqrestore(&priv->lock, flags);
++ }
++ return 0;
++}
++
++static int
++ltq_vrx200_tx(struct sk_buff *skb, struct net_device *dev)
++{
++ int queue = skb_get_queue_mapping(skb);
++ struct netdev_queue *txq = netdev_get_tx_queue(dev, queue);
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++ struct ltq_vrx200_chan *ch = &priv->ch[(queue << 1) | 1];
++ struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
++ unsigned long flags;
++ u32 byte_offset;
++ int len;
++
++ len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
++
++ if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) {
++ netdev_err(dev, "tx ring full\n");
++ netif_tx_stop_queue(txq);
++ return NETDEV_TX_BUSY;
++ }
++
++ /* dma needs to start on a 16 byte aligned address */
++ byte_offset = CPHYSADDR(skb->data) % 16;
++ ch->skb[ch->dma.desc] = skb;
++
++ dev->trans_start = jiffies;
++
++ spin_lock_irqsave(&priv->lock, flags);
++ desc->addr = ((unsigned int) dma_map_single(NULL, skb->data, len,
++ DMA_TO_DEVICE)) - byte_offset;
++ wmb();
++ desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP |
++ LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK);
++ ch->dma.desc++;
++ ch->dma.desc %= LTQ_DESC_NUM;
++ spin_unlock_irqrestore(&priv->lock, flags);
++
++ if (ch->dma.desc_base[ch->dma.desc].ctl & LTQ_DMA_OWN)
++ netif_tx_stop_queue(txq);
++
++ return NETDEV_TX_OK;
++}
++
++static int
++ltq_vrx200_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++
++ /* TODO: mii-toll reports "No MII transceiver present!." ?!*/
++ return phy_mii_ioctl(priv->phydev, rq, cmd);
++}
++
++static u16
++ltq_vrx200_select_queue(struct net_device *dev, struct sk_buff *skb)
++{
++ /* we are currently only using the first queue */
++ return 0;
++}
++
++static int
++ltq_vrx200_init(struct net_device *dev)
++{
++ struct ltq_vrx200_priv *priv = netdev_priv(dev);
++ struct sockaddr mac;
++ int err;
++
++ ether_setup(dev);
++ dev->watchdog_timeo = 10 * HZ;
++
++ err = ltq_vrx200_hw_init(dev);
++ if (err)
++ goto err_hw;
++
++ memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr));
++ if (!is_valid_ether_addr(mac.sa_data)) {
++ pr_warn("vrx200: invalid MAC, using random\n");
++ random_ether_addr(mac.sa_data);
++ }
++ eth_mac_addr(dev, &mac);
++
++ if (!ltq_vrx200_mdio_init(dev))
++ dev->ethtool_ops = &ltq_vrx200_ethtool_ops;
++ else
++ pr_warn("vrx200: mdio probe failed\n");;
++ return 0;
++
++err_hw:
++ ltq_vrx200_hw_exit(dev);
++ return err;
++}
++
++static void
++ltq_vrx200_tx_timeout(struct net_device *dev)
++{
++ int err;
++
++ ltq_vrx200_hw_exit(dev);
++ err = ltq_vrx200_hw_init(dev);
++ if (err)
++ goto err_hw;
++ dev->trans_start = jiffies;
++ netif_wake_queue(dev);
++ return;
++
++err_hw:
++ ltq_vrx200_hw_exit(dev);
++ netdev_err(dev, "failed to restart vrx200 after TX timeout\n");
++}
++
++static const struct net_device_ops ltq_eth_netdev_ops = {
++ .ndo_open = ltq_vrx200_open,
++ .ndo_stop = ltq_vrx200_stop,
++ .ndo_start_xmit = ltq_vrx200_tx,
++ .ndo_change_mtu = eth_change_mtu,
++ .ndo_do_ioctl = ltq_vrx200_ioctl,
++ .ndo_set_mac_address = eth_mac_addr,
++ .ndo_validate_addr = eth_validate_addr,
++ .ndo_select_queue = ltq_vrx200_select_queue,
++ .ndo_init = ltq_vrx200_init,
++ .ndo_tx_timeout = ltq_vrx200_tx_timeout,
++};
++
++static int __devinit
++ltq_vrx200_probe(struct platform_device *pdev)
++{
++ struct net_device *dev;
++ struct ltq_vrx200_priv *priv;
++ struct resource *res;
++ int err;
++ int i;
++
++ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!res) {
++ dev_err(&pdev->dev, "failed to get vrx200 resource\n");
++ err = -ENOENT;
++ goto err_out;
++ }
++
++ res = devm_request_mem_region(&pdev->dev, res->start,
++ resource_size(res), dev_name(&pdev->dev));
++ if (!res) {
++ dev_err(&pdev->dev, "failed to request vrx200 resource\n");
++ err = -EBUSY;
++ goto err_out;
++ }
++
++ ltq_vrx200_membase = devm_ioremap_nocache(&pdev->dev,
++ res->start, resource_size(res));
++ if (!ltq_vrx200_membase) {
++ dev_err(&pdev->dev, "failed to remap vrx200 engine %d\n",
++ pdev->id);
++ err = -ENOMEM;
++ goto err_out;
++ }
++
++ if (ltq_gpio_request(&pdev->dev, 42, 2, 1, "MDIO") ||
++ ltq_gpio_request(&pdev->dev, 43, 2, 1, "MDC")) {
++ dev_err(&pdev->dev, "failed to request MDIO gpios\n");
++ err = -EBUSY;
++ goto err_out;
++ }
++
++ dev = alloc_etherdev_mq(sizeof(struct ltq_vrx200_priv), 4);
++ strcpy(dev->name, "eth%d");
++ dev->netdev_ops = &ltq_eth_netdev_ops;
++ priv = netdev_priv(dev);
++ priv->res = res;
++ priv->pldata = dev_get_platdata(&pdev->dev);
++ priv->netdev = dev;
++
++ priv->clk_ppe = clk_get(&pdev->dev, NULL);
++ if (IS_ERR(priv->clk_ppe))
++ return PTR_ERR(priv->clk_ppe);
++
++ spin_lock_init(&priv->lock);
++
++ for (i = 0; i < MAX_DMA_CHAN; i++) {
++ if (IS_TX(i))
++ netif_napi_add(dev, &priv->ch[i].napi,
++ ltq_vrx200_poll_tx, 8);
++ else if (IS_RX(i))
++ netif_napi_add(dev, &priv->ch[i].napi,
++ ltq_vrx200_poll_rx, 32);
++ priv->ch[i].netdev = dev;
++ }
++
++ err = register_netdev(dev);
++ if (err)
++ goto err_free;
++
++ platform_set_drvdata(pdev, dev);
++ return 0;
++
++err_free:
++ kfree(dev);
++err_out:
++ return err;
++}
++
++static int __devexit
++ltq_vrx200_remove(struct platform_device *pdev)
++{
++ struct net_device *dev = platform_get_drvdata(pdev);
++
++ if (dev) {
++ netif_tx_stop_all_queues(dev);
++ ltq_vrx200_hw_exit(dev);
++ ltq_vrx200_mdio_cleanup(dev);
++ unregister_netdev(dev);
++ }
++ return 0;
++}
++
++static struct platform_driver ltq_mii_driver = {
++ .probe = ltq_vrx200_probe,
++ .remove = __devexit_p(ltq_vrx200_remove),
++ .driver = {
++ .name = "ltq_vrx200",
++ .owner = THIS_MODULE,
++ },
++};
++
++module_platform_driver(ltq_mii_driver);
++
++MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
++MODULE_DESCRIPTION("Lantiq SoC ETOP");
++MODULE_LICENSE("GPL");
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0044-MIPS-NET-several-fixes-to-etop-driver.patch b/target/linux/lantiq/patches-3.2/0044-MIPS-NET-several-fixes-to-etop-driver.patch
new file mode 100644
index 0000000..dbb205b
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0044-MIPS-NET-several-fixes-to-etop-driver.patch
@@ -0,0 +1,445 @@
+From 06663beb0230c02d1962eca8d9f6709c2e852328 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 21 Mar 2012 18:14:06 +0100
+Subject: [PATCH 44/70] MIPS: NET: several fixes to etop driver
+
+---
+ drivers/net/ethernet/lantiq_etop.c | 208 +++++++++++++++++++-----------------
+ 1 files changed, 108 insertions(+), 100 deletions(-)
+
+diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
+index a084d74..1a807d8 100644
+--- a/drivers/net/ethernet/lantiq_etop.c
++++ b/drivers/net/ethernet/lantiq_etop.c
+@@ -103,15 +103,6 @@
+ /* the newer xway socks have a embedded 3/7 port gbit multiplexer */
+ #define ltq_has_gbit() (ltq_is_ar9() || ltq_is_vr9())
+
+-/* use 2 static channels for TX/RX
+- depending on the SoC we need to use different DMA channels for ethernet */
+-#define LTQ_ETOP_TX_CHANNEL 1
+-#define LTQ_ETOP_RX_CHANNEL ((ltq_is_ase()) ? (5) : \
+- ((ltq_has_gbit()) ? (0) : (6)))
+-
+-#define IS_TX(x) (x == LTQ_ETOP_TX_CHANNEL)
+-#define IS_RX(x) (x == LTQ_ETOP_RX_CHANNEL)
+-
+ #define ltq_etop_r32(x) ltq_r32(ltq_etop_membase + (x))
+ #define ltq_etop_w32(x, y) ltq_w32(x, ltq_etop_membase + (y))
+ #define ltq_etop_w32_mask(x, y, z) \
+@@ -128,8 +119,8 @@ static void __iomem *ltq_etop_membase;
+ static void __iomem *ltq_gbit_membase;
+
+ struct ltq_etop_chan {
+- int idx;
+ int tx_free;
++ int irq;
+ struct net_device *netdev;
+ struct napi_struct napi;
+ struct ltq_dma_channel dma;
+@@ -144,8 +135,8 @@ struct ltq_etop_priv {
+ struct mii_bus *mii_bus;
+ struct phy_device *phydev;
+
+- struct ltq_etop_chan ch[MAX_DMA_CHAN];
+- int tx_free[MAX_DMA_CHAN >> 1];
++ struct ltq_etop_chan txch;
++ struct ltq_etop_chan rxch;
+
+ spinlock_t lock;
+
+@@ -206,8 +197,10 @@ ltq_etop_poll_rx(struct napi_struct *napi, int budget)
+ {
+ struct ltq_etop_chan *ch = container_of(napi,
+ struct ltq_etop_chan, napi);
++ struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
+ int rx = 0;
+ int complete = 0;
++ unsigned long flags;
+
+ while ((rx < budget) && !complete) {
+ struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+@@ -221,7 +214,9 @@ ltq_etop_poll_rx(struct napi_struct *napi, int budget)
+ }
+ if (complete || !rx) {
+ napi_complete(&ch->napi);
++ spin_lock_irqsave(&priv->lock, flags);
+ ltq_dma_ack_irq(&ch->dma);
++ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ return rx;
+ }
+@@ -233,7 +228,7 @@ ltq_etop_poll_tx(struct napi_struct *napi, int budget)
+ container_of(napi, struct ltq_etop_chan, napi);
+ struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
+ struct netdev_queue *txq =
+- netdev_get_tx_queue(ch->netdev, ch->idx >> 1);
++ netdev_get_tx_queue(ch->netdev, ch->dma.nr >> 1);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+@@ -251,7 +246,9 @@ ltq_etop_poll_tx(struct napi_struct *napi, int budget)
+ if (netif_tx_queue_stopped(txq))
+ netif_tx_start_queue(txq);
+ napi_complete(&ch->napi);
++ spin_lock_irqsave(&priv->lock, flags);
+ ltq_dma_ack_irq(&ch->dma);
++ spin_unlock_irqrestore(&priv->lock, flags);
+ return 1;
+ }
+
+@@ -259,9 +256,10 @@ static irqreturn_t
+ ltq_etop_dma_irq(int irq, void *_priv)
+ {
+ struct ltq_etop_priv *priv = _priv;
+- int ch = irq - LTQ_DMA_ETOP;
+-
+- napi_schedule(&priv->ch[ch].napi);
++ if (irq == priv->txch.dma.irq)
++ napi_schedule(&priv->txch.napi);
++ else
++ napi_schedule(&priv->rxch.napi);
+ return IRQ_HANDLED;
+ }
+
+@@ -273,7 +271,7 @@ ltq_etop_free_channel(struct net_device *dev, struct ltq_etop_chan *ch)
+ ltq_dma_free(&ch->dma);
+ if (ch->dma.irq)
+ free_irq(ch->dma.irq, priv);
+- if (IS_RX(ch->idx)) {
++ if (ch == &priv->txch) {
+ int desc;
+ for (desc = 0; desc < LTQ_DESC_NUM; desc++)
+ dev_kfree_skb_any(ch->skb[ch->dma.desc]);
+@@ -284,7 +282,6 @@ static void
+ ltq_etop_hw_exit(struct net_device *dev)
+ {
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+- int i;
+
+ clk_disable(priv->clk_ppe);
+
+@@ -296,9 +293,8 @@ ltq_etop_hw_exit(struct net_device *dev)
+ clk_disable(priv->clk_ephycgu);
+ }
+
+- for (i = 0; i < MAX_DMA_CHAN; i++)
+- if (IS_TX(i) || IS_RX(i))
+- ltq_etop_free_channel(dev, &priv->ch[i]);
++ ltq_etop_free_channel(dev, &priv->txch);
++ ltq_etop_free_channel(dev, &priv->rxch);
+ }
+
+ static void
+@@ -326,8 +322,6 @@ ltq_etop_hw_init(struct net_device *dev)
+ {
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ unsigned int mii_mode = priv->pldata->mii_mode;
+- int err = 0;
+- int i;
+
+ clk_enable(priv->clk_ppe);
+
+@@ -369,31 +363,50 @@ ltq_etop_hw_init(struct net_device *dev)
+ /* enable crc generation */
+ ltq_etop_w32(PPE32_CGEN, LQ_PPE32_ENET_MAC_CFG);
+
++ return 0;
++}
++
++static int
++ltq_etop_dma_init(struct net_device *dev)
++{
++ struct ltq_etop_priv *priv = netdev_priv(dev);
++ int tx = 1;
++ int rx = ((ltq_is_ase()) ? (5) : \
++ ((ltq_is_ar9()) ? (0) : (6)));
++ int tx_irq = LTQ_DMA_ETOP + tx;
++ int rx_irq = LTQ_DMA_ETOP + rx;
++ int err;
++
+ ltq_dma_init_port(DMA_PORT_ETOP);
+
+- for (i = 0; i < MAX_DMA_CHAN && !err; i++) {
+- int irq = LTQ_DMA_ETOP + i;
+- struct ltq_etop_chan *ch = &priv->ch[i];
+-
+- ch->idx = ch->dma.nr = i;
+-
+- if (IS_TX(i)) {
+- ltq_dma_alloc_tx(&ch->dma);
+- err = request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
+- "etop_tx", priv);
+- } else if (IS_RX(i)) {
+- ltq_dma_alloc_rx(&ch->dma);
+- for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
+- ch->dma.desc++)
+- if (ltq_etop_alloc_skb(ch))
+- err = -ENOMEM;
+- ch->dma.desc = 0;
+- err = request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
+- "etop_rx", priv);
++ priv->txch.dma.nr = tx;
++ ltq_dma_alloc_tx(&priv->txch.dma);
++ err = request_irq(tx_irq, ltq_etop_dma_irq, IRQF_DISABLED,
++ "eth_tx", priv);
++ if (err) {
++ netdev_err(dev, "failed to allocate tx irq\n");
++ goto err_out;
++ }
++ priv->txch.dma.irq = tx_irq;
++
++ priv->rxch.dma.nr = rx;
++ ltq_dma_alloc_rx(&priv->rxch.dma);
++ for (priv->rxch.dma.desc = 0; priv->rxch.dma.desc < LTQ_DESC_NUM;
++ priv->rxch.dma.desc++) {
++ if (ltq_etop_alloc_skb(&priv->rxch)) {
++ netdev_err(dev, "failed to allocate skbs\n");
++ err = -ENOMEM;
++ goto err_out;
+ }
+- if (!err)
+- ch->dma.irq = irq;
+ }
++ priv->rxch.dma.desc = 0;
++ err = request_irq(rx_irq, ltq_etop_dma_irq, IRQF_DISABLED,
++ "eth_rx", priv);
++ if (err)
++ netdev_err(dev, "failed to allocate rx irq\n");
++ else
++ priv->rxch.dma.irq = rx_irq;
++err_out:
+ return err;
+ }
+
+@@ -410,7 +423,10 @@ ltq_etop_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+
+- return phy_ethtool_gset(priv->phydev, cmd);
++ if (priv->phydev)
++ return phy_ethtool_gset(priv->phydev, cmd);
++ else
++ return 0;
+ }
+
+ static int
+@@ -418,7 +434,10 @@ ltq_etop_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+ {
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+
+- return phy_ethtool_sset(priv->phydev, cmd);
++ if (priv->phydev)
++ return phy_ethtool_sset(priv->phydev, cmd);
++ else
++ return 0;
+ }
+
+ static int
+@@ -426,7 +445,10 @@ ltq_etop_nway_reset(struct net_device *dev)
+ {
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+
+- return phy_start_aneg(priv->phydev);
++ if (priv->phydev)
++ return phy_start_aneg(priv->phydev);
++ else
++ return 0;
+ }
+
+ static const struct ethtool_ops ltq_etop_ethtool_ops = {
+@@ -618,18 +640,19 @@ static int
+ ltq_etop_open(struct net_device *dev)
+ {
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+- int i;
++ unsigned long flags;
+
+- for (i = 0; i < MAX_DMA_CHAN; i++) {
+- struct ltq_etop_chan *ch = &priv->ch[i];
++ napi_enable(&priv->txch.napi);
++ napi_enable(&priv->rxch.napi);
++
++ spin_lock_irqsave(&priv->lock, flags);
++ ltq_dma_open(&priv->txch.dma);
++ ltq_dma_open(&priv->rxch.dma);
++ spin_unlock_irqrestore(&priv->lock, flags);
+
+- if (!IS_TX(i) && (!IS_RX(i)))
+- continue;
+- ltq_dma_open(&ch->dma);
+- napi_enable(&ch->napi);
+- }
+ if (priv->phydev)
+ phy_start(priv->phydev);
++
+ netif_tx_start_all_queues(dev);
+ return 0;
+ }
+@@ -638,19 +661,19 @@ static int
+ ltq_etop_stop(struct net_device *dev)
+ {
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+- int i;
++ unsigned long flags;
+
+ netif_tx_stop_all_queues(dev);
+ if (priv->phydev)
+ phy_stop(priv->phydev);
+- for (i = 0; i < MAX_DMA_CHAN; i++) {
+- struct ltq_etop_chan *ch = &priv->ch[i];
++ napi_disable(&priv->txch.napi);
++ napi_disable(&priv->rxch.napi);
++
++ spin_lock_irqsave(&priv->lock, flags);
++ ltq_dma_close(&priv->txch.dma);
++ ltq_dma_close(&priv->rxch.dma);
++ spin_unlock_irqrestore(&priv->lock, flags);
+
+- if (!IS_RX(i) && !IS_TX(i))
+- continue;
+- napi_disable(&ch->napi);
+- ltq_dma_close(&ch->dma);
+- }
+ return 0;
+ }
+
+@@ -660,16 +683,16 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
+ int queue = skb_get_queue_mapping(skb);
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, queue);
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+- struct ltq_etop_chan *ch = &priv->ch[(queue << 1) | 1];
+- struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
++ struct ltq_dma_desc *desc =
++ &priv->txch.dma.desc_base[priv->txch.dma.desc];
+ unsigned long flags;
+ u32 byte_offset;
+ int len;
+
+ len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+
+- if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) {
+- dev_kfree_skb_any(skb);
++ if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) ||
++ priv->txch.skb[priv->txch.dma.desc]) {
+ netdev_err(dev, "tx ring full\n");
+ netif_tx_stop_queue(txq);
+ return NETDEV_TX_BUSY;
+@@ -677,7 +700,7 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
+
+ /* dma needs to start on a 16 byte aligned address */
+ byte_offset = CPHYSADDR(skb->data) % 16;
+- ch->skb[ch->dma.desc] = skb;
++ priv->txch.skb[priv->txch.dma.desc] = skb;
+
+ dev->trans_start = jiffies;
+
+@@ -687,11 +710,11 @@ ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
+ wmb();
+ desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP |
+ LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK);
+- ch->dma.desc++;
+- ch->dma.desc %= LTQ_DESC_NUM;
++ priv->txch.dma.desc++;
++ priv->txch.dma.desc %= LTQ_DESC_NUM;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+- if (ch->dma.desc_base[ch->dma.desc].ctl & LTQ_DMA_OWN)
++ if (priv->txch.dma.desc_base[priv->txch.dma.desc].ctl & LTQ_DMA_OWN)
+ netif_tx_stop_queue(txq);
+
+ return NETDEV_TX_OK;
+@@ -776,6 +799,10 @@ ltq_etop_init(struct net_device *dev)
+ err = ltq_etop_hw_init(dev);
+ if (err)
+ goto err_hw;
++ err = ltq_etop_dma_init(dev);
++ if (err)
++ goto err_hw;
++
+ ltq_etop_change_mtu(dev, 1500);
+
+ memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr));
+@@ -811,6 +838,9 @@ ltq_etop_tx_timeout(struct net_device *dev)
+ err = ltq_etop_hw_init(dev);
+ if (err)
+ goto err_hw;
++ err = ltq_etop_dma_init(dev);
++ if (err)
++ goto err_hw;
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+ return;
+@@ -834,14 +864,13 @@ static const struct net_device_ops ltq_eth_netdev_ops = {
+ .ndo_tx_timeout = ltq_etop_tx_timeout,
+ };
+
+-static int __init
++static int __devinit
+ ltq_etop_probe(struct platform_device *pdev)
+ {
+ struct net_device *dev;
+ struct ltq_etop_priv *priv;
+ struct resource *res, *gbit_res;
+ int err;
+- int i;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+@@ -917,15 +946,10 @@ ltq_etop_probe(struct platform_device *pdev)
+
+ spin_lock_init(&priv->lock);
+
+- for (i = 0; i < MAX_DMA_CHAN; i++) {
+- if (IS_TX(i))
+- netif_napi_add(dev, &priv->ch[i].napi,
+- ltq_etop_poll_tx, 8);
+- else if (IS_RX(i))
+- netif_napi_add(dev, &priv->ch[i].napi,
+- ltq_etop_poll_rx, 32);
+- priv->ch[i].netdev = dev;
+- }
++ netif_napi_add(dev, &priv->txch.napi, ltq_etop_poll_tx, 8);
++ netif_napi_add(dev, &priv->rxch.napi, ltq_etop_poll_rx, 32);
++ priv->txch.netdev = dev;
++ priv->rxch.netdev = dev;
+
+ err = register_netdev(dev);
+ if (err)
+@@ -955,6 +979,7 @@ ltq_etop_remove(struct platform_device *pdev)
+ }
+
+ static struct platform_driver ltq_mii_driver = {
++ .probe = ltq_etop_probe,
+ .remove = __devexit_p(ltq_etop_remove),
+ .driver = {
+ .name = "ltq_etop",
+@@ -962,24 +987,7 @@ static struct platform_driver ltq_mii_driver = {
+ },
+ };
+
+-int __init
+-init_ltq_etop(void)
+-{
+- int ret = platform_driver_probe(&ltq_mii_driver, ltq_etop_probe);
+-
+- if (ret)
+- pr_err("ltq_etop: Error registering platfom driver!");
+- return ret;
+-}
+-
+-static void __exit
+-exit_ltq_etop(void)
+-{
+- platform_driver_unregister(&ltq_mii_driver);
+-}
+-
+-module_init(init_ltq_etop);
+-module_exit(exit_ltq_etop);
++module_platform_driver(ltq_mii_driver);
+
+ MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+ MODULE_DESCRIPTION("Lantiq SoC ETOP");
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0045-MTD-MIPS-lantiq-use-module_platform_driver-inside-la.patch b/target/linux/lantiq/patches-3.2/0045-MTD-MIPS-lantiq-use-module_platform_driver-inside-la.patch
new file mode 100644
index 0000000..afbdbc9
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0045-MTD-MIPS-lantiq-use-module_platform_driver-inside-la.patch
@@ -0,0 +1,64 @@
+From f94454615da63008ac865e6a7b03bbe79041e8c2 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 20 Feb 2012 12:15:25 +0100
+Subject: [PATCH 45/70] MTD: MIPS: lantiq: use module_platform_driver inside
+ lantiq map driver
+
+Reduce boilerplate code by converting driver to module_platform_driver.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Cc: linux-mtd@lists.infradead.org
+---
+ drivers/mtd/maps/lantiq-flash.c | 22 +++-------------------
+ 1 files changed, 3 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
+index 764d468..b55212c 100644
+--- a/drivers/mtd/maps/lantiq-flash.c
++++ b/drivers/mtd/maps/lantiq-flash.c
+@@ -108,7 +108,7 @@ ltq_copy_to(struct map_info *map, unsigned long to,
+ spin_unlock_irqrestore(&ebu_lock, flags);
+ }
+
+-static int __init
++static int __devinit
+ ltq_mtd_probe(struct platform_device *pdev)
+ {
+ struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev);
+@@ -208,6 +208,7 @@ ltq_mtd_remove(struct platform_device *pdev)
+ }
+
+ static struct platform_driver ltq_mtd_driver = {
++ .probe = ltq_mtd_probe,
+ .remove = __devexit_p(ltq_mtd_remove),
+ .driver = {
+ .name = "ltq_nor",
+@@ -215,24 +216,7 @@ static struct platform_driver ltq_mtd_driver = {
+ },
+ };
+
+-static int __init
+-init_ltq_mtd(void)
+-{
+- int ret = platform_driver_probe(&ltq_mtd_driver, ltq_mtd_probe);
+-
+- if (ret)
+- pr_err("ltq_nor: error registering platform driver");
+- return ret;
+-}
+-
+-static void __exit
+-exit_ltq_mtd(void)
+-{
+- platform_driver_unregister(&ltq_mtd_driver);
+-}
+-
+-module_init(init_ltq_mtd);
+-module_exit(exit_ltq_mtd);
++module_platform_driver(ltq_mtd_driver);
+
+ MODULE_LICENSE("GPL");
+ MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0046-WDT-MIPS-lantiq-use-module_platform_driver-inside-la.patch b/target/linux/lantiq/patches-3.2/0046-WDT-MIPS-lantiq-use-module_platform_driver-inside-la.patch
new file mode 100644
index 0000000..f8a247b
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0046-WDT-MIPS-lantiq-use-module_platform_driver-inside-la.patch
@@ -0,0 +1,61 @@
+From 7d332825d131e70daff66b934797c89f50c11ace Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 20 Feb 2012 12:16:31 +0100
+Subject: [PATCH 46/70] WDT: MIPS: lantiq: use module_platform_driver inside
+ lantiq watchdog driver
+
+Reduce boilerplate code by converting driver to module_platform_driver.
+
+Signed-off-by: John Crispin <blogic@openwrt.org>
+Cc: linux-watchdog@vger.kernel.org
+---
+ drivers/watchdog/lantiq_wdt.c | 19 +++----------------
+ 1 files changed, 3 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c
+index da2b09f..40c9eb7 100644
+--- a/drivers/watchdog/lantiq_wdt.c
++++ b/drivers/watchdog/lantiq_wdt.c
+@@ -182,7 +182,7 @@ static struct miscdevice ltq_wdt_miscdev = {
+ .fops = &ltq_wdt_fops,
+ };
+
+-static int __init
++static int __devinit
+ ltq_wdt_probe(struct platform_device *pdev)
+ {
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+@@ -230,6 +230,7 @@ ltq_wdt_remove(struct platform_device *pdev)
+
+
+ static struct platform_driver ltq_wdt_driver = {
++ .probe = ltq_wdt_probe,
+ .remove = __devexit_p(ltq_wdt_remove),
+ .driver = {
+ .name = "ltq_wdt",
+@@ -237,21 +238,7 @@ static struct platform_driver ltq_wdt_driver = {
+ },
+ };
+
+-static int __init
+-init_ltq_wdt(void)
+-{
+- return platform_driver_probe(&ltq_wdt_driver, ltq_wdt_probe);
+-}
+-
+-static void __exit
+-exit_ltq_wdt(void)
+-{
+- return platform_driver_unregister(&ltq_wdt_driver);
+-}
+-
+-module_init(init_ltq_wdt);
+-module_exit(exit_ltq_wdt);
+-
++module_platform_driver(ltq_wdt_driver);
+ module_param(nowayout, int, 0);
+ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0017-MIPS-lantiq-adds-GPTU-driver.patch b/target/linux/lantiq/patches-3.2/0047-MIPS-lantiq-adds-GPTU-driver.patch
index 4b7c7b5..8be0ad5 100644
--- a/target/linux/lantiq/patches/0017-MIPS-lantiq-adds-GPTU-driver.patch
+++ b/target/linux/lantiq/patches-3.2/0047-MIPS-lantiq-adds-GPTU-driver.patch
@@ -1,16 +1,20 @@
-From 45dbb232686978816e8148753e12f27caa2b2eb3 Mon Sep 17 00:00:00 2001
+From b672c54f9ae4504687a80bb51cdfe102bdae96e1 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 29 Sep 2011 17:16:38 +0200
-Subject: [PATCH 17/24] MIPS: lantiq: adds GPTU driver
+Subject: [PATCH 47/70] MIPS: lantiq: adds GPTU driver
---
arch/mips/include/asm/mach-lantiq/lantiq_timer.h | 155 ++++
arch/mips/lantiq/xway/Makefile | 2 +-
- arch/mips/lantiq/xway/timer.c | 830 ++++++++++++++++++++++
- 3 files changed, 986 insertions(+), 1 deletions(-)
+ arch/mips/lantiq/xway/sysctrl.c | 1 +
+ arch/mips/lantiq/xway/timer.c | 846 ++++++++++++++++++++++
+ 4 files changed, 1003 insertions(+), 1 deletions(-)
create mode 100644 arch/mips/include/asm/mach-lantiq/lantiq_timer.h
create mode 100644 arch/mips/lantiq/xway/timer.c
+diff --git a/arch/mips/include/asm/mach-lantiq/lantiq_timer.h b/arch/mips/include/asm/mach-lantiq/lantiq_timer.h
+new file mode 100644
+index 0000000..ef564ab
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/lantiq_timer.h
@@ -0,0 +1,155 @@
@@ -169,17 +173,34 @@ Subject: [PATCH 17/24] MIPS: lantiq: adds GPTU driver
+ u32 reload, unsigned long arg1, unsigned long arg2);
+
+#endif /* __DANUBE_GPTU_DEV_H__2005_07_26__10_19__ */
+diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
+index 277aa34..4c3106f 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,4 +1,4 @@
--obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o nand.o
-+obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o nand.o timer.o
+-obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o prom.o nand.o
++obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o prom.o nand.o timer.o
- obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
- obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
+ obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
+ obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
+diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
+index 38f02f9..1a2e2d4 100644
+--- a/arch/mips/lantiq/xway/sysctrl.c
++++ b/arch/mips/lantiq/xway/sysctrl.c
+@@ -147,6 +147,7 @@ void __init ltq_soc_init(void)
+ clkdev_add_pmu("ltq_dma", NULL, 0, PMU_DMA);
+ clkdev_add_pmu("ltq_stp", NULL, 0, PMU_STP);
+ clkdev_add_pmu("ltq_spi", NULL, 0, PMU_SPI);
++ clkdev_add_pmu("ltq_gptu", NULL, 0, PMU_GPT);
+ if (!ltq_is_vr9())
+ clkdev_add_pmu("ltq_etop", NULL, 0, PMU_PPE);
+ if (ltq_is_ase()) {
+diff --git a/arch/mips/lantiq/xway/timer.c b/arch/mips/lantiq/xway/timer.c
+new file mode 100644
+index 0000000..9794c87
--- /dev/null
+++ b/arch/mips/lantiq/xway/timer.c
-@@ -0,0 +1,830 @@
+@@ -0,0 +1,846 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
@@ -195,6 +216,7 @@ Subject: [PATCH 17/24] MIPS: lantiq: adds GPTU driver
+
+#include <asm/irq.h>
+#include <asm/div64.h>
++#include "../clk.h"
+
+#include <lantiq_soc.h>
+#include <lantiq_irq.h>
@@ -332,7 +354,18 @@ Subject: [PATCH 17/24] MIPS: lantiq: adds GPTU driver
+ struct timer_dev_timer timer[MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2];
+};
+
-+unsigned int ltq_get_fpi_bus_clock(int fpi);
++unsigned long ltq_danube_fpi_bus_clock(int fpi);
++unsigned long ltq_vr9_fpi_bus_clock(int fpi);
++
++unsigned int ltq_get_fpi_bus_clock(int fpi) {
++ if (ltq_is_ase())
++ return CLOCK_133M;
++ else if (ltq_is_vr9())
++ return ltq_vr9_fpi_bus_clock(fpi);
++
++ return ltq_danube_fpi_bus_clock(fpi);
++}
++
+
+static long gptu_ioctl(struct file *, unsigned int, unsigned long);
+static int gptu_open(struct inode *, struct file *);
@@ -387,7 +420,10 @@ Subject: [PATCH 17/24] MIPS: lantiq: adds GPTU driver
+
+static inline void lq_enable_gptu(void)
+{
-+ ltq_pmu_enable(PMU_GPT);
++ struct clk *clk = clk_get_sys("ltq_gptu", NULL);
++ clk_enable(clk);
++
++ //ltq_pmu_enable(PMU_GPT);
+
+ /* Set divider as 1, disable write protection for SPEN, enable module. */
+ *LQ_GPTU_CLC =
@@ -402,6 +438,7 @@ Subject: [PATCH 17/24] MIPS: lantiq: adds GPTU driver
+
+static inline void lq_disable_gptu(void)
+{
++ struct clk *clk = clk_get_sys("ltq_gptu", NULL);
+ ltq_w32(0x00, LQ_GPTU_IRNEN);
+ ltq_w32(0xfff, LQ_GPTU_IRNCR);
+
@@ -415,7 +452,7 @@ Subject: [PATCH 17/24] MIPS: lantiq: adds GPTU driver
+ GPTU_CLC_SPEN_SET(0) |
+ GPTU_CLC_DISR_SET(1);
+
-+ ltq_pmu_disable(PMU_GPT);
++ clk_enable(clk);
+}
+
+int lq_request_timer(unsigned int timer, unsigned int flag,
@@ -1010,3 +1047,6 @@ Subject: [PATCH 17/24] MIPS: lantiq: adds GPTU driver
+
+module_init(lq_gptu_init);
+module_exit(lq_gptu_exit);
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0018-MIPS-lantiq-adds-dwc_otg.patch b/target/linux/lantiq/patches-3.2/0048-MIPS-lantiq-adds-dwc_otg.patch
index dd0b103..2f47a2d 100644
--- a/target/linux/lantiq/patches/0018-MIPS-lantiq-adds-dwc_otg.patch
+++ b/target/linux/lantiq/patches-3.2/0048-MIPS-lantiq-adds-dwc_otg.patch
@@ -1,7 +1,7 @@
-From ffd7924fcc69ff146d62f131d72ef18575bf0227 Mon Sep 17 00:00:00 2001
+From 668e5f88aa80ef8c4c8cb935c7c222146de79825 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 30 Sep 2011 14:37:36 +0200
-Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+Subject: [PATCH 48/70] MIPS: lantiq: adds dwc_otg
---
drivers/usb/Kconfig | 2 +
@@ -45,9 +45,11 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
create mode 100644 drivers/usb/dwc_otg/dwc_otg_plat.h
create mode 100644 drivers/usb/dwc_otg/dwc_otg_regs.h
+diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
+index 791f11b..1eafa7a 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
-@@ -116,6 +116,8 @@ source "drivers/usb/wusbcore/Kconfig"
+@@ -129,6 +129,8 @@ source "drivers/usb/wusbcore/Kconfig"
source "drivers/usb/host/Kconfig"
@@ -56,9 +58,11 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
source "drivers/usb/musb/Kconfig"
source "drivers/usb/renesas_usbhs/Kconfig"
+diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
+index 75eca76..7fe8e83 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
-@@ -28,6 +28,8 @@ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/
+@@ -30,6 +30,8 @@ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/
obj-$(CONFIG_USB_WUSB) += wusbcore/
@@ -67,9 +71,11 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
obj-$(CONFIG_USB_ACM) += class/
obj-$(CONFIG_USB_PRINTER) += class/
obj-$(CONFIG_USB_WDM) += class/
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 7978146..6a7df52 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
-@@ -2891,11 +2891,11 @@ hub_port_init (struct usb_hub *hub, stru
+@@ -2935,11 +2935,11 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
udev->ttport = hdev->ttport;
} else if (udev->speed != USB_SPEED_HIGH
&& hdev->speed == USB_SPEED_HIGH) {
@@ -83,6 +89,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
udev->tt = &hub->tt;
udev->ttport = port1;
}
+diff --git a/drivers/usb/dwc_otg/Kconfig b/drivers/usb/dwc_otg/Kconfig
+new file mode 100644
+index 0000000..e018490
--- /dev/null
+++ b/drivers/usb/dwc_otg/Kconfig
@@ -0,0 +1,37 @@
@@ -123,6 +132,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+config DWC_OTG_DEBUG
+ bool "Enable debug mode"
+ depends on DWC_OTG
+diff --git a/drivers/usb/dwc_otg/Makefile b/drivers/usb/dwc_otg/Makefile
+new file mode 100644
+index 0000000..d4d2355
--- /dev/null
+++ b/drivers/usb/dwc_otg/Makefile
@@ -0,0 +1,39 @@
@@ -165,6 +177,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+
+#obj-$(CONFIG_DWC_OTG_IFX) := dwc_otg_ifx.o
+#dwc_otg_ifx-objs := dwc_otg_ifx.o
+diff --git a/drivers/usb/dwc_otg/dwc_otg_attr.c b/drivers/usb/dwc_otg/dwc_otg_attr.c
+new file mode 100644
+index 0000000..4675a5c
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_attr.c
@@ -0,0 +1,802 @@
@@ -970,6 +985,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+ device_remove_file(_dev, &dev_attr_rd_reg_test);
+ device_remove_file(_dev, &dev_attr_wr_reg_test);
+}
+diff --git a/drivers/usb/dwc_otg/dwc_otg_attr.h b/drivers/usb/dwc_otg/dwc_otg_attr.h
+new file mode 100644
+index 0000000..4bbf7df
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_attr.h
@@ -0,0 +1,67 @@
@@ -1040,6 +1058,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+void dwc_otg_attr_remove (struct device *_dev);
+
+#endif
+diff --git a/drivers/usb/dwc_otg/dwc_otg_cil.c b/drivers/usb/dwc_otg/dwc_otg_cil.c
+new file mode 100644
+index 0000000..42c69eb
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_cil.c
@@ -0,0 +1,3025 @@
@@ -4068,6 +4089,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+ _cb->p = _p;
+}
+
+diff --git a/drivers/usb/dwc_otg/dwc_otg_cil.h b/drivers/usb/dwc_otg/dwc_otg_cil.h
+new file mode 100644
+index 0000000..bbb9516
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_cil.h
@@ -0,0 +1,911 @@
@@ -4982,6 +5006,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+
+
+#endif
+diff --git a/drivers/usb/dwc_otg/dwc_otg_cil_ifx.h b/drivers/usb/dwc_otg/dwc_otg_cil_ifx.h
+new file mode 100644
+index 0000000..b0298ec
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_cil_ifx.h
@@ -0,0 +1,58 @@
@@ -5043,6 +5070,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+
+#endif // __DWC_OTG_CIL_IFX_H__
+
+diff --git a/drivers/usb/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/dwc_otg/dwc_otg_cil_intr.c
+new file mode 100644
+index 0000000..d469ab4
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_cil_intr.c
@@ -0,0 +1,708 @@
@@ -5754,6 +5784,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+ }
+ return retval;
+}
+diff --git a/drivers/usb/dwc_otg/dwc_otg_driver.c b/drivers/usb/dwc_otg/dwc_otg_driver.c
+new file mode 100644
+index 0000000..1b0daab
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_driver.c
@@ -0,0 +1,1274 @@
@@ -7031,6 +7064,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+ </td></tr>
+
+*/
+diff --git a/drivers/usb/dwc_otg/dwc_otg_driver.h b/drivers/usb/dwc_otg/dwc_otg_driver.h
+new file mode 100644
+index 0000000..7e6940d
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_driver.h
@@ -0,0 +1,84 @@
@@ -7118,6 +7154,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+//#define dev_dbg(fake, format, arg...) printk(KERN_CRIT __FILE__ ":%d: " format "\n" , __LINE__, ## arg)
+
+#endif
+diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd.c b/drivers/usb/dwc_otg/dwc_otg_hcd.c
+new file mode 100644
+index 0000000..ad6bc72
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd.c
@@ -0,0 +1,2870 @@
@@ -9991,6 +10030,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+#endif
+}
+#endif /* DWC_DEVICE_ONLY */
+diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd.h b/drivers/usb/dwc_otg/dwc_otg_hcd.h
+new file mode 100644
+index 0000000..8a20dff
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd.h
@@ -0,0 +1,676 @@
@@ -10670,6 +10712,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+#endif // DEBUG
+#endif // __DWC_HCD_H__
+#endif /* DWC_DEVICE_ONLY */
+diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c
+new file mode 100644
+index 0000000..834b5e0
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c
@@ -0,0 +1,1841 @@
@@ -12514,6 +12559,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+}
+
+#endif /* DWC_DEVICE_ONLY */
+diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c
+new file mode 100644
+index 0000000..fcb5ce6
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c
@@ -0,0 +1,794 @@
@@ -13311,6 +13359,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+}
+
+#endif /* DWC_DEVICE_ONLY */
+diff --git a/drivers/usb/dwc_otg/dwc_otg_ifx.c b/drivers/usb/dwc_otg/dwc_otg_ifx.c
+new file mode 100644
+index 0000000..0a4c209
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_ifx.c
@@ -0,0 +1,100 @@
@@ -13414,6 +13465,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+void ifx_usb_hc_remove(void)
+{
+}
+diff --git a/drivers/usb/dwc_otg/dwc_otg_ifx.h b/drivers/usb/dwc_otg/dwc_otg_ifx.h
+new file mode 100644
+index 0000000..402d7a6
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_ifx.h
@@ -0,0 +1,85 @@
@@ -13502,6 +13556,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+ ltq_mask_and_ack_irq(&d);
+}
+#endif //__DWC_OTG_IFX_H__
+diff --git a/drivers/usb/dwc_otg/dwc_otg_plat.h b/drivers/usb/dwc_otg/dwc_otg_plat.h
+new file mode 100644
+index 0000000..727d0c4
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_plat.h
@@ -0,0 +1,269 @@
@@ -13774,6 +13831,9 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+
+#endif
+
+diff --git a/drivers/usb/dwc_otg/dwc_otg_regs.h b/drivers/usb/dwc_otg/dwc_otg_regs.h
+new file mode 100644
+index 0000000..397a954
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_regs.h
@@ -0,0 +1,1797 @@
@@ -15574,3 +15634,6 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
+} dwc_otg_host_if_t;
+
+#endif
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0049-dwc_otg-remove-bogus-halt_channel.patch b/target/linux/lantiq/patches-3.2/0049-dwc_otg-remove-bogus-halt_channel.patch
new file mode 100644
index 0000000..0a4d817
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0049-dwc_otg-remove-bogus-halt_channel.patch
@@ -0,0 +1,26 @@
+From 7f73b86b26fc58e0513a792533b7e11450aa0737 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 23 Mar 2012 16:14:33 +0100
+Subject: [PATCH 49/70] dwc_otg: remove bogus halt_channel
+
+https://lists.openwrt.org/pipermail/openwrt-devel/2012-March/014524.html
+---
+ drivers/usb/dwc_otg/dwc_otg_hcd_intr.c | 2 --
+ 1 files changed, 0 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c
+index 834b5e0..f6f3f3d 100644
+--- a/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c
++++ b/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c
+@@ -1278,8 +1278,6 @@ static int32_t handle_hc_ack_intr(dwc_otg_hcd_t *_hcd,
+ * automatically executes the PING, then the transfer.
+ */
+ halt_channel(_hcd, _hc, _qtd, DWC_OTG_HC_XFER_ACK, must_free);
+- } else {
+- halt_channel(_hcd, _hc, _qtd, _hc->halt_status, must_free);
+ }
+ }
+
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0050-MIPS-adds-ifxhcd.patch b/target/linux/lantiq/patches-3.2/0050-MIPS-adds-ifxhcd.patch
new file mode 100644
index 0000000..51a2c98
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0050-MIPS-adds-ifxhcd.patch
@@ -0,0 +1,16672 @@
+From 09071b501014528984b158bc5408d8a738ef6883 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sun, 11 Mar 2012 15:59:39 +0100
+Subject: [PATCH 50/70] MIPS: adds ifxhcd
+
+---
+ arch/mips/lantiq/xway/Makefile | 2 +-
+ arch/mips/lantiq/xway/dev-ifxhcd.c | 45 +
+ arch/mips/lantiq/xway/dev-ifxhcd.h | 17 +
+ arch/mips/lantiq/xway/sysctrl.c | 2 +
+ drivers/usb/Kconfig | 2 +
+ drivers/usb/Makefile | 2 +
+ drivers/usb/ifxhcd/Kconfig | 58 +
+ drivers/usb/ifxhcd/Makefile | 85 +
+ drivers/usb/ifxhcd/TagHistory | 171 ++
+ drivers/usb/ifxhcd/ifxhcd.c | 2523 +++++++++++++++++++++++
+ drivers/usb/ifxhcd/ifxhcd.h | 628 ++++++
+ drivers/usb/ifxhcd/ifxhcd_es.c | 549 +++++
+ drivers/usb/ifxhcd/ifxhcd_intr.c | 3742 +++++++++++++++++++++++++++++++++++
+ drivers/usb/ifxhcd/ifxhcd_queue.c | 418 ++++
+ drivers/usb/ifxhcd/ifxusb_cif.c | 1458 ++++++++++++++
+ drivers/usb/ifxhcd/ifxusb_cif.h | 665 +++++++
+ drivers/usb/ifxhcd/ifxusb_cif_d.c | 458 +++++
+ drivers/usb/ifxhcd/ifxusb_cif_h.c | 846 ++++++++
+ drivers/usb/ifxhcd/ifxusb_ctl.c | 1385 +++++++++++++
+ drivers/usb/ifxhcd/ifxusb_driver.c | 970 +++++++++
+ drivers/usb/ifxhcd/ifxusb_plat.h | 1018 ++++++++++
+ drivers/usb/ifxhcd/ifxusb_regs.h | 1420 +++++++++++++
+ drivers/usb/ifxhcd/ifxusb_version.h | 5 +
+ 23 files changed, 16468 insertions(+), 1 deletions(-)
+ create mode 100644 arch/mips/lantiq/xway/dev-ifxhcd.c
+ create mode 100644 arch/mips/lantiq/xway/dev-ifxhcd.h
+ create mode 100644 drivers/usb/ifxhcd/Kconfig
+ create mode 100644 drivers/usb/ifxhcd/Makefile
+ create mode 100644 drivers/usb/ifxhcd/TagHistory
+ create mode 100644 drivers/usb/ifxhcd/ifxhcd.c
+ create mode 100644 drivers/usb/ifxhcd/ifxhcd.h
+ create mode 100644 drivers/usb/ifxhcd/ifxhcd_es.c
+ create mode 100644 drivers/usb/ifxhcd/ifxhcd_intr.c
+ create mode 100644 drivers/usb/ifxhcd/ifxhcd_queue.c
+ create mode 100644 drivers/usb/ifxhcd/ifxusb_cif.c
+ create mode 100644 drivers/usb/ifxhcd/ifxusb_cif.h
+ create mode 100644 drivers/usb/ifxhcd/ifxusb_cif_d.c
+ create mode 100644 drivers/usb/ifxhcd/ifxusb_cif_h.c
+ create mode 100644 drivers/usb/ifxhcd/ifxusb_ctl.c
+ create mode 100644 drivers/usb/ifxhcd/ifxusb_driver.c
+ create mode 100644 drivers/usb/ifxhcd/ifxusb_plat.h
+ create mode 100644 drivers/usb/ifxhcd/ifxusb_regs.h
+ create mode 100644 drivers/usb/ifxhcd/ifxusb_version.h
+
+diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
+index 4c3106f..c9baf91 100644
+--- a/arch/mips/lantiq/xway/Makefile
++++ b/arch/mips/lantiq/xway/Makefile
+@@ -1,4 +1,4 @@
+-obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o prom.o nand.o timer.o
++obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o prom.o nand.o timer.o dev-ifxhcd.o
+
+ obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
+ obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
+diff --git a/arch/mips/lantiq/xway/dev-ifxhcd.c b/arch/mips/lantiq/xway/dev-ifxhcd.c
+new file mode 100644
+index 0000000..ea08a35
+--- /dev/null
++++ b/arch/mips/lantiq/xway/dev-ifxhcd.c
+@@ -0,0 +1,45 @@
++/*
++ * 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.
++ *
++ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/string.h>
++#include <linux/mtd/physmap.h>
++#include <linux/kernel.h>
++#include <linux/reboot.h>
++#include <linux/platform_device.h>
++#include <linux/leds.h>
++#include <linux/etherdevice.h>
++#include <linux/reboot.h>
++#include <linux/time.h>
++#include <linux/io.h>
++#include <linux/gpio.h>
++#include <linux/leds.h>
++
++#include <asm/bootinfo.h>
++#include <asm/irq.h>
++
++#include <lantiq_soc.h>
++#include <lantiq_irq.h>
++#include <lantiq_platform.h>
++
++static u64 dmamask = (u32)0x1fffffff;
++
++static struct platform_device platform_dev = {
++ .name = "ifxusb_hcd",
++ .dev.dma_mask = &dmamask,
++};
++
++int __init
++xway_register_hcd(int *pins)
++{
++ platform_dev.dev.platform_data = pins;
++ return platform_device_register(&platform_dev);
++}
+diff --git a/arch/mips/lantiq/xway/dev-ifxhcd.h b/arch/mips/lantiq/xway/dev-ifxhcd.h
+new file mode 100644
+index 0000000..18b3d2d
+--- /dev/null
++++ b/arch/mips/lantiq/xway/dev-ifxhcd.h
+@@ -0,0 +1,17 @@
++/*
++ * 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.
++ *
++ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
++ */
++
++#ifndef _LTQ_DEV_HCD_H__
++#define _LTQ_DEV_HCD_H__
++
++#include <lantiq_platform.h>
++
++extern void __init xway_register_hcd(int *pin);
++
++#endif
+diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
+index 1a2e2d4..ac7383f 100644
+--- a/arch/mips/lantiq/xway/sysctrl.c
++++ b/arch/mips/lantiq/xway/sysctrl.c
+@@ -166,6 +166,8 @@ void __init ltq_soc_init(void)
+ clkdev_add_pmu("ltq_pcie", "pdi", 1, PMU1_PCIE_PDI);
+ clkdev_add_pmu("ltq_pcie", "ctl", 1, PMU1_PCIE_CTL);
+ clkdev_add_pmu("ltq_pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
++ clkdev_add_pmu("usb0", NULL, 0, (1<<6) | 1);
++ clkdev_add_pmu("usb1", NULL, 0, (1<<26) | (1<<27));
+ } else {
+ clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
+ ltq_danube_io_region_clock());
+diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
+index 1eafa7a..0f7926e 100644
+--- a/drivers/usb/Kconfig
++++ b/drivers/usb/Kconfig
+@@ -183,4 +183,6 @@ source "drivers/usb/gadget/Kconfig"
+
+ source "drivers/usb/otg/Kconfig"
+
++source "drivers/usb/ifxhcd/Kconfig"
++
+ endif # USB_SUPPORT
+diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
+index 7fe8e83..61b4c88 100644
+--- a/drivers/usb/Makefile
++++ b/drivers/usb/Makefile
+@@ -57,3 +57,5 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg/
+ obj-$(CONFIG_USB_GADGET) += gadget/
+
+ obj-$(CONFIG_USB_COMMON) += usb-common.o
++
++obj-$(CONFIG_USB_HOST_IFX) += ifxhcd/
+diff --git a/drivers/usb/ifxhcd/Kconfig b/drivers/usb/ifxhcd/Kconfig
+new file mode 100644
+index 0000000..7eb8ceb
+--- /dev/null
++++ b/drivers/usb/ifxhcd/Kconfig
+@@ -0,0 +1,58 @@
++
++config USB_HOST_IFX
++ tristate "Infineon USB Host Controller Driver"
++ depends on USB
++ default n
++ help
++ Infineon USB Host Controller
++
++config USB_HOST_IFX_B
++ bool "USB host mode on core 1 and 2"
++ depends on USB_HOST_IFX
++ help
++ Both cores run as host
++
++#config USB_HOST_IFX_1
++#config USB_HOST_IFX_2
++
++#config IFX_DANUBE
++#config IFX_AMAZON_SE
++config IFX_AR9
++ depends on USB_HOST_IFX
++ bool "AR9"
++
++config IFX_VR9
++ depends on USB_HOST_IFX
++ bool "VR9"
++
++#config USB_HOST_IFX_FORCE_USB11
++# bool "Forced USB1.1"
++# depends on USB_HOST_IFX
++# default n
++# help
++# force to be USB 1.1
++
++#config USB_HOST_IFX_WITH_HS_ELECT_TST
++# bool "With HS_Electrical Test"
++# depends on USB_HOST_IFX
++# default n
++# help
++# With USBIF HSET routines
++
++#config USB_HOST_IFX_WITH_ISO
++# bool "With ISO transfer"
++# depends on USB_HOST_IFX
++# default n
++# help
++# With USBIF ISO transfer
++
++config USB_HOST_IFX_UNALIGNED_ADJ
++ bool "Adjust"
++ depends on USB_HOST_IFX
++ help
++ USB_HOST_IFX_UNALIGNED_ADJ
++
++#config USB_HOST_IFX_UNALIGNED_CHK
++#config USB_HOST_IFX_UNALIGNED_NONE
++
++
+diff --git a/drivers/usb/ifxhcd/Makefile b/drivers/usb/ifxhcd/Makefile
+new file mode 100644
+index 0000000..0a2ac99
+--- /dev/null
++++ b/drivers/usb/ifxhcd/Makefile
+@@ -0,0 +1,85 @@
++
++#
++# Makefile for USB Core files and filesystem
++#
++ ifxusb_host-objs := ifxusb_driver.o
++ ifxusb_host-objs += ifxusb_ctl.o
++ ifxusb_host-objs += ifxusb_cif.o
++ ifxusb_host-objs += ifxusb_cif_h.o
++ ifxusb_host-objs += ifxhcd.o
++ ifxusb_host-objs += ifxhcd_es.o
++ ifxusb_host-objs += ifxhcd_intr.o
++ ifxusb_host-objs += ifxhcd_queue.o
++
++ifeq ($(CONFIG_IFX_TWINPASS),y)
++ EXTRA_CFLAGS += -D__IS_TWINPASS__
++endif
++ifeq ($(CONFIG_IFX_DANUBE),y)
++ EXTRA_CFLAGS += -D__IS_DANUBE__
++endif
++ifeq ($(CONFIG_IFX_AMAZON_SE),y)
++ EXTRA_CFLAGS += -D__IS_AMAZON_SE__
++endif
++ifeq ($(CONFIG_IFX_AR9),y)
++ EXTRA_CFLAGS += -D__IS_AR9__
++endif
++ifeq ($(CONFIG_IFX_AMAZON_S),y)
++ EXTRA_CFLAGS += -D__IS_AR9__
++endif
++ifeq ($(CONFIG_IFX_VR9),y)
++ EXTRA_CFLAGS += -D__IS_VR9__
++endif
++
++ifeq ($(CONFIG_USB_HOST_IFX),y)
++ EXTRA_CFLAGS += -Dlinux -D__LINUX__
++ EXTRA_CFLAGS += -D__IS_HOST__
++ EXTRA_CFLAGS += -D__KERNEL__
++endif
++
++ifeq ($(CONFIG_USB_HOST_IFX),m)
++ EXTRA_CFLAGS += -Dlinux -D__LINUX__
++ EXTRA_CFLAGS += -D__IS_HOST__
++ EXTRA_CFLAGS += -D__KERNEL__
++endif
++
++ifeq ($(CONFIG_USB_DEBUG),y)
++ EXTRA_CFLAGS += -D__DEBUG__
++ EXTRA_CFLAGS += -D__ENABLE_DUMP__
++endif
++
++ifeq ($(CONFIG_USB_HOST_IFX_B),y)
++ EXTRA_CFLAGS += -D__IS_DUAL__
++endif
++ifeq ($(CONFIG_USB_HOST_IFX_1),y)
++ EXTRA_CFLAGS += -D__IS_FIRST__
++endif
++ifeq ($(CONFIG_USB_HOST_IFX_2),y)
++ EXTRA_CFLAGS += -D__IS_SECOND__
++endif
++
++ifeq ($(CONFIG_USB_HOST_IFX_FORCE_USB11),y)
++ EXTRA_CFLAGS += -D__FORCE_USB11__
++endif
++ifeq ($(CONFIG_USB_HOST_IFX_WITH_HS_ELECT_TST),y)
++ EXTRA_CFLAGS += -D__WITH_HS_ELECT_TST__
++endif
++ifeq ($(CONFIG_USB_HOST_IFX_WITH_ISO),y)
++ EXTRA_CFLAGS += -D__EN_ISOC__
++endif
++ifeq ($(CONFIG_USB_HOST_IFX_UNALIGNED_ADJ),y)
++ EXTRA_CFLAGS += -D__UNALIGNED_BUFFER_ADJ__
++endif
++ifeq ($(CONFIG_USB_HOST_IFX_UNALIGNED_CHK),y)
++ EXTRA_CFLAGS += -D__UNALIGNED_BUFFER_CHK__
++endif
++
++# EXTRA_CFLAGS += -D__DYN_SOF_INTR__
++ EXTRA_CFLAGS += -D__UEIP__
++# EXTRA_CFLAGS += -D__EN_ISOC__
++# EXTRA_CFLAGS += -D__EN_ISOC_SPLIT__
++
++## 20110628 AVM/WK New flag for less SOF IRQs
++ EXTRA_CFLAGS += -D__USE_TIMER_4_SOF__
++
++obj-$(CONFIG_USB_HOST_IFX) += ifxusb_host.o
++
+diff --git a/drivers/usb/ifxhcd/TagHistory b/drivers/usb/ifxhcd/TagHistory
+new file mode 100644
+index 0000000..3820d70
+--- /dev/null
++++ b/drivers/usb/ifxhcd/TagHistory
+@@ -0,0 +1,171 @@
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://embeddedvm/home/SVN/drivers/usb_host20/tags/5.18-r240-non_musb_ar9_vr9-SOF_Timer_Fixed
++| Erzeugt mit SVN-Tagger Version 3.74.
+++----------------------------------------------------------------------+
++FIX - Korrektur bei der SOF-Timer/IRQ Steuerung. (Bug in Tag 5.17)
++FIX - Fehlerbehandlung an mehreren Stellen korrigiert bzw. eingebaut.
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://embeddedvm/home/SVN/drivers/usb_host20/tags/5.17-r237-non_musb_ar9_vr9-2_6_32_41_Kompatibel
++| Erzeugt mit SVN-Tagger Version 3.73.
+++----------------------------------------------------------------------+
++FIX - Kompatiblität zum Update auf Kernel 2.6.32-41. Weiterhin für 28er geeignet.
++ENH - Reduktion der Interrruptlast durch Nutzung eines hrtimers anstatt SOF-IRQ.
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.16-r208-non_musb_ar9_vr9-20110421_Zero_Paket_Optimiert
++| Erzeugt mit SVN-Tagger Version 3.66.
+++----------------------------------------------------------------------+
++
++FIX - VR9 / AR9 - Zero Packet. Optimierung korrigiert.
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.15-r205-non_musb_ar9_vr9-20110421_Zero_Paket_WA_funktioniert
++| Erzeugt mit SVN-Tagger Version 3.66.
+++----------------------------------------------------------------------+
++
++FIX - VR9 / AR9 - "Zero Packet" funktioniert nun wirklich. Letzter Tag hatte einen Bug.
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.14-r202-non_musb_ar9_vr9-20110420_Zero_Paket_WA
++| Erzeugt mit SVN-Tagger Version 3.66.
+++----------------------------------------------------------------------+
++
++FIX - VR9 / AR9 - Zero Packet Workaround: ZLP wird nun geschickt wenn URB_ZERO_PACKET aktiv ist.
++ Wird von LTE Altair Firmware benoetig.
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.13-r199-non_musb_ar9_vr9-20110310_Init_Fix
++| Erzeugt mit SVN-Tagger Version 3.64.
+++----------------------------------------------------------------------+
++
++FIX - VR9 / AR9 - Timing der Initialisierungsphase angepasst zum Kernel 2.6.28 mit UGW-4.3.1.
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.12-r184-non_musb_ar9_vr9-20110118_Full_Speed_Fix
++| Erzeugt mit SVN-Tagger Version 3.58.
+++----------------------------------------------------------------------+
++AR9/VR9 (3370,6840,7320):
++Makefile - FIX - (Workaround) Debug Modus hilft gegen Enumerationsfehler bei Full Speed Drucker.
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.11-r175-non_musb_ar9_vr9-20101220_VR9_2_Ports_DMA_Fix
++| Erzeugt mit SVN-Tagger Version 3.58.
+++----------------------------------------------------------------------+
++
++FIX - VR9 - Workaround DMA Burst Size. Wenn beiden USB Ports benutzt werden, geht der USB Host nicht mehr.
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.10-r169-non_musb_ar9_vr9-Fix_Spontan_Reboot
++| Erzeugt mit SVN-Tagger Version 3.58.
+++----------------------------------------------------------------------+
++
++FIX - Endlosschleife führte zu einem spontanen Reboot.
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.9-r166-non_musb_ar9_vr9-20101112_deferred_completion
++| Erzeugt mit SVN-Tagger Version 3.58.
+++----------------------------------------------------------------------+
++
++ENH - Deferred URB Completion Mechanismus eingebaut. Nun ca. 10% schneller bei usb-storage.
++
++FIX - PING Flow Control gefixt.
++FIX - Channel Halt wird nun immer angerufen. (Split Transaction wurde nicht erfolgreich gestoppt).
++FIX - Spinlock Benutzung verbessert. Mehr Stabilitaet.
++
++CHG - Ubersetztungsoption __DEBUG__ ist nun abhaengig von CONFIG_USB_DEBUG
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.8-r149-non_musb_ar9_vr9-20100827_LTE_Interrupt_EP_Fix
++| Erzeugt mit SVN-Tagger Version 3.57.
+++----------------------------------------------------------------------+
++AR9/VR9 - FIX - Interrupt Packets gingen verloren, wegen falschem Timing beim OddFrame Bit.
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.7-r142-non_musb_ar9_vr9-20100728_Unaligned_Buf_Fix
++| Erzeugt mit SVN-Tagger Version 3.57.
+++----------------------------------------------------------------------+
++FIX - "Unaligned Data" Flag wieder nach Transfer geloescht.
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.6-r133-non_musb_ar9_vr9-20100714_Toggle_Datenverlust_Fix
++| Erzeugt mit SVN-Tagger Version 3.57.
+++----------------------------------------------------------------------+
++TL5508 - Einige UMTS Modems funktionierten nicht korrekt an der 7320 (AR9).
++FIX - USB Data Toggle des usbcore benutzen. Datenverlust nach EP-Halt.
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.5-r130-non_musb_ar9_vr9-20100712_USB_Ports_abschaltbar
++| Erzeugt mit SVN-Tagger Version 3.57.
+++----------------------------------------------------------------------+
++Power - Fix - Beide USB Port abschaltbar bei rmmod.
++rmmod - FIX - URB_Dequeue funktionierte beim Entladen des Treibers nicht (mehrere Ursachen).
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.4-r126-non_musb_ar9_vr9-20100701_Lost_Interrupt_Workaround
++| Erzeugt mit SVN-Tagger Version 3.57.
+++----------------------------------------------------------------------+
++FIX - Workaround wegen verpasstem Interrupt, bei Full-Speed Interrupt EP.
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.3-r123-non_musb_ar9_vr9-20100630_UMTS_Fixes
++| Erzeugt mit SVN-Tagger Version 3.57.
+++----------------------------------------------------------------------+
++FIX - Full-Speed Interrupt Endpoint hinter Hi-Speed Hub funktioniert nun (UMTS Modems)
++FIX - usb_hcd_link_urb_from_ep API von USBCore muss benutzt werden.
++FIX - Interrupt URBs nicht bei NAK completen.
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.2-r114-non_musb_ar9_vr9-20100520_StickAndSurf_funktioniert
++| Erzeugt mit SVN-Tagger Version 3.56.
+++----------------------------------------------------------------------+
++- Merge mit neuen LANTIQ Sourcen "3.0alpha B100312"
++- Fix - Spin_lock eingebaut, Stick&Surf funktioniert nun
++
++- DEP - CONFIG_USB_HOST_IFX_WITH_ISO wird nicht unterstuetzt: In der Kernel Config deaktivieren.
++
++
++
+++----------------------------------------------------------------------+
++| TAG: svn://EmbeddedVM/home/SVN/drivers/usb_host20/tags/5.1-r107-non_musb_ar9_vr9-20100505_IFXUSB_Host_mit_Energiemonitor
++| Erzeugt mit SVN-Tagger Version 3.56.
+++----------------------------------------------------------------------+
++USB Host Treiber für AR9 und VR9
++--------------------------------
++FIX - Toggle Error nach STALL - Einfacher Workaround - Nun werden Massenspeicherpartitionen erkannt!
++AVM_POWERMETER - USB Energiemonitor Support.
++
++Bekanntes Problem: Stick and Surf funktioniert nur sporadisch, weil CONTROL_IRQ manchmal ausbleibt.
++
+diff --git a/drivers/usb/ifxhcd/ifxhcd.c b/drivers/usb/ifxhcd/ifxhcd.c
+new file mode 100644
+index 0000000..d2ae125
+--- /dev/null
++++ b/drivers/usb/ifxhcd/ifxhcd.c
+@@ -0,0 +1,2523 @@
++/*****************************************************************************
++ ** FILE NAME : ifxhcd.c
++ ** PROJECT : IFX USB sub-system V3
++ ** MODULES : IFX USB sub-system Host and Device driver
++ ** SRC VERSION : 1.0
++ ** DATE : 1/Jan/2009
++ ** AUTHOR : Chen, Howard
++ ** DESCRIPTION : This file contains the structures, constants, and interfaces for
++ ** the Host Contoller Driver (HCD).
++ **
++ ** The Host Controller Driver (HCD) is responsible for translating requests
++ ** from the USB Driver into the appropriate actions on the IFXUSB controller.
++ ** It isolates the USBD from the specifics of the controller by providing an
++ ** API to the USBD.
++ *****************************************************************************/
++
++/*!
++ \file ifxhcd.c
++ \ingroup IFXUSB_DRIVER_V3
++ \brief This file contains the implementation of the HCD. In Linux,
++ the HCD implements the hc_driver API.
++*/
++
++#include <linux/version.h>
++#include "ifxusb_version.h"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++
++#include <linux/device.h>
++
++#include <linux/errno.h>
++#include <linux/list.h>
++#include <linux/interrupt.h>
++#include <linux/string.h>
++
++#include <linux/dma-mapping.h>
++
++
++#include "ifxusb_plat.h"
++#include "ifxusb_regs.h"
++#include "ifxusb_cif.h"
++#include "ifxhcd.h"
++
++#include <asm/irq.h>
++
++#ifdef CONFIG_AVM_POWERMETER
++#include <linux/avm_power.h>
++#endif /*--- #ifdef CONFIG_AVM_POWERMETER ---*/
++
++#ifdef __DEBUG__
++ static void dump_urb_info(struct urb *_urb, char* _fn_name);
++ static void dump_channel_info(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh);
++#endif
++
++
++/*!
++ \brief Sets the final status of an URB and returns it to the device driver. Any
++ required cleanup of the URB is performed.
++ */
++void ifxhcd_complete_urb(ifxhcd_hcd_t *_ifxhcd, ifxhcd_urbd_t *_urbd, int _status)
++{
++ struct urb *urb=NULL;
++ unsigned long flags = 0;
++
++ /*== AVM/BC 20101111 Function called with Lock ==*/
++ //SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
++
++ if (!list_empty(&_urbd->urbd_list_entry))
++ list_del_init (&_urbd->urbd_list_entry);
++
++ if(!_urbd->urb)
++ {
++ IFX_ERROR("%s: invalid urb\n",__func__);
++ /*== AVM/BC 20101111 Function called with Lock ==*/
++ //SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
++ return;
++ }
++
++ urb=_urbd->urb;
++
++ #ifdef __DEBUG__
++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB))
++ {
++ IFX_PRINT("%s: _urbd %p, urb %p, device %d, ep %d %s/%s, status=%d\n",
++ __func__, _urbd,_urbd->urb, usb_pipedevice(_urbd->urb->pipe),
++ usb_pipeendpoint(_urbd->urb->pipe),
++ usb_pipein(_urbd->urb->pipe) ? "IN" : "OUT",
++ (_urbd->is_in) ? "IN" : "OUT",
++ _status);
++ if (_urbd->epqh->ep_type == IFXUSB_EP_TYPE_ISOC)
++ {
++ int i;
++ for (i = 0; i < _urbd->urb->number_of_packets; i++)
++ IFX_PRINT(" ISO Desc %d status: %d\n", i, _urbd->urb->iso_frame_desc[i].status);
++ }
++ }
++ #endif
++
++ if (!_urbd->epqh)
++ IFX_ERROR("%s: invalid epqd\n",__func__);
++
++ #if defined(__UNALIGNED_BUFFER_ADJ__)
++ else if(_urbd->is_active)
++ {
++ if( _urbd->epqh->aligned_checked &&
++ _urbd->epqh->using_aligned_buf &&
++ _urbd->xfer_buff &&
++ _urbd->is_in )
++ memcpy(_urbd->xfer_buff,_urbd->epqh->aligned_buf,_urbd->xfer_len);
++ _urbd->epqh->using_aligned_buf=0;
++ _urbd->epqh->using_aligned_setup=0;
++ _urbd->epqh->aligned_checked=0;
++ }
++ #endif
++
++ urb->status = _status;
++ urb->hcpriv=NULL;
++ kfree(_urbd);
++
++ usb_hcd_unlink_urb_from_ep(ifxhcd_to_syshcd(_ifxhcd), urb);
++ SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
++
++// usb_hcd_giveback_urb(ifxhcd_to_syshcd(_ifxhcd), urb);
++ usb_hcd_giveback_urb(ifxhcd_to_syshcd(_ifxhcd), urb, _status);
++
++ /*== AVM/BC 20100630 - 2.6.28 needs HCD link/unlink URBs ==*/
++ SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
++}
++
++/*== AVM/BC 20101111 URB Complete deferred
++ * Must be called with Spinlock
++ */
++
++/*!
++ \brief Inserts an urbd structur in the completion list. The urbd will be
++ later completed by select_eps_sub
++ */
++void defer_ifxhcd_complete_urb(ifxhcd_hcd_t *_ifxhcd, ifxhcd_urbd_t *_urbd, int _status)
++{
++
++ _urbd->status = _status;
++
++ //Unlink Urbd from epqh / Insert it into the complete list
++ list_move_tail(&_urbd->urbd_list_entry, &_ifxhcd->urbd_complete_list);
++
++}
++
++/*!
++ \brief Processes all the URBs in a single EPQHs. Completes them with
++ status and frees the URBD.
++ */
++//static
++void kill_all_urbs_in_epqh(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh, int _status)
++{
++ struct list_head *urbd_item;
++ ifxhcd_urbd_t *urbd;
++
++ if(!_epqh)
++ return;
++
++ for (urbd_item = _epqh->urbd_list.next;
++ urbd_item != &_epqh->urbd_list;
++ urbd_item = _epqh->urbd_list.next)
++ {
++ urbd = list_entry(urbd_item, ifxhcd_urbd_t, urbd_list_entry);
++ ifxhcd_complete_urb(_ifxhcd, urbd, _status);
++ }
++}
++
++
++/*!
++ \brief Free all EPS in one Processes all the URBs in a single list of EPQHs. Completes them with
++ -ETIMEDOUT and frees the URBD.
++ */
++//static
++void epqh_list_free(ifxhcd_hcd_t *_ifxhcd, struct list_head *_epqh_list)
++{
++ struct list_head *item;
++ ifxhcd_epqh_t *epqh;
++
++ if (!_epqh_list)
++ return;
++ if (_epqh_list->next == NULL) /* The list hasn't been initialized yet. */
++ return;
++
++ /* Ensure there are no URBDs or URBs left. */
++ for (item = _epqh_list->next; item != _epqh_list; item = _epqh_list->next)
++ {
++ epqh = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
++ kill_all_urbs_in_epqh(_ifxhcd, epqh, -ETIMEDOUT);
++ ifxhcd_epqh_free(epqh);
++ }
++}
++
++
++
++//static
++void epqh_list_free_all(ifxhcd_hcd_t *_ifxhcd)
++{
++ unsigned long flags;
++
++ /*== AVM/BC 20101111 - 2.6.28 Needs Spinlock ==*/
++ SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
++
++ epqh_list_free(_ifxhcd, &_ifxhcd->epqh_np_active );
++ epqh_list_free(_ifxhcd, &_ifxhcd->epqh_np_ready );
++ epqh_list_free(_ifxhcd, &_ifxhcd->epqh_intr_active );
++ epqh_list_free(_ifxhcd, &_ifxhcd->epqh_intr_ready );
++ #ifdef __EN_ISOC__
++ epqh_list_free(_ifxhcd, &_ifxhcd->epqh_isoc_active );
++ epqh_list_free(_ifxhcd, &_ifxhcd->epqh_isoc_ready );
++ #endif
++ epqh_list_free(_ifxhcd, &_ifxhcd->epqh_stdby );
++
++ SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
++
++}
++
++
++/*!
++ \brief This function is called to handle the disconnection of host port.
++ */
++int32_t ifxhcd_disconnect(ifxhcd_hcd_t *_ifxhcd)
++{
++ IFX_DEBUGPL(DBG_HCDV, "%s(%p)\n", __func__, _ifxhcd);
++
++ /* Set status flags for the hub driver. */
++ _ifxhcd->flags.b.port_connect_status_change = 1;
++ _ifxhcd->flags.b.port_connect_status = 0;
++
++ /*
++ * Shutdown any transfers in process by clearing the Tx FIFO Empty
++ * interrupt mask and status bits and disabling subsequent host
++ * channel interrupts.
++ */
++ {
++ gint_data_t intr = { .d32 = 0 };
++ intr.b.nptxfempty = 1;
++ intr.b.ptxfempty = 1;
++ intr.b.hcintr = 1;
++ ifxusb_mreg (&_ifxhcd->core_if.core_global_regs->gintmsk, intr.d32, 0);
++ ifxusb_mreg (&_ifxhcd->core_if.core_global_regs->gintsts, intr.d32, 0);
++ }
++
++ /* Respond with an error status to all URBs in the schedule. */
++ epqh_list_free_all(_ifxhcd);
++
++ /* Clean up any host channels that were in use. */
++ {
++ int num_channels;
++ ifxhcd_hc_t *channel;
++ ifxusb_hc_regs_t *hc_regs;
++ hcchar_data_t hcchar;
++ int i;
++
++ num_channels = _ifxhcd->core_if.params.host_channels;
++
++ for (i = 0; i < num_channels; i++)
++ {
++ channel = &_ifxhcd->ifxhc[i];
++ if (list_empty(&channel->hc_list_entry))
++ {
++ hc_regs = _ifxhcd->core_if.hc_regs[i];
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ if (hcchar.b.chen)
++ {
++ /* Halt the channel. */
++ hcchar.b.chdis = 1;
++ ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
++ }
++ list_add_tail(&channel->hc_list_entry, &_ifxhcd->free_hc_list);
++ ifxhcd_hc_cleanup(&_ifxhcd->core_if, channel);
++ }
++ }
++ }
++ return 1;
++}
++
++
++/*!
++ \brief Frees secondary storage associated with the ifxhcd_hcd structure contained
++ in the struct usb_hcd field.
++ */
++static void ifxhcd_freeextra(struct usb_hcd *_syshcd)
++{
++ ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd(_syshcd);
++
++ IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD FREE\n");
++
++ /* Free memory for EPQH/URBD lists */
++ epqh_list_free_all(ifxhcd);
++
++ /* Free memory for the host channels. */
++ ifxusb_free_buf(ifxhcd->status_buf);
++ return;
++}
++#ifdef __USE_TIMER_4_SOF__
++static enum hrtimer_restart ifxhcd_timer_func(struct hrtimer *timer) {
++ ifxhcd_hcd_t *ifxhcd = container_of(timer, ifxhcd_hcd_t, hr_timer);
++
++ ifxhcd_handle_intr(ifxhcd);
++
++ return HRTIMER_NORESTART;
++}
++#endif
++
++/*!
++ \brief Initializes the HCD. This function allocates memory for and initializes the
++ static parts of the usb_hcd and ifxhcd_hcd structures. It also registers the
++ USB bus with the core and calls the hc_driver->start() function. It returns
++ a negative error on failure.
++ */
++int ifxhcd_init(ifxhcd_hcd_t *_ifxhcd)
++{
++ int retval = 0;
++ struct usb_hcd *syshcd = NULL;
++
++ IFX_DEBUGPL(DBG_HCD, "IFX USB HCD INIT\n");
++
++ spin_lock_init(&_ifxhcd->lock);
++#ifdef __USE_TIMER_4_SOF__
++ hrtimer_init(&_ifxhcd->hr_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ _ifxhcd->hr_timer.function = ifxhcd_timer_func;
++#endif
++ _ifxhcd->hc_driver.description = _ifxhcd->core_if.core_name;
++ _ifxhcd->hc_driver.product_desc = "IFX USB Controller";
++ //_ifxhcd->hc_driver.hcd_priv_size = sizeof(ifxhcd_hcd_t);
++ _ifxhcd->hc_driver.hcd_priv_size = sizeof(unsigned long);
++ _ifxhcd->hc_driver.irq = ifxhcd_irq;
++ _ifxhcd->hc_driver.flags = HCD_MEMORY | HCD_USB2;
++ _ifxhcd->hc_driver.start = ifxhcd_start;
++ _ifxhcd->hc_driver.stop = ifxhcd_stop;
++ //_ifxhcd->hc_driver.reset =
++ //_ifxhcd->hc_driver.suspend =
++ //_ifxhcd->hc_driver.resume =
++ _ifxhcd->hc_driver.urb_enqueue = ifxhcd_urb_enqueue;
++ _ifxhcd->hc_driver.urb_dequeue = ifxhcd_urb_dequeue;
++ _ifxhcd->hc_driver.endpoint_disable = ifxhcd_endpoint_disable;
++ _ifxhcd->hc_driver.get_frame_number = ifxhcd_get_frame_number;
++ _ifxhcd->hc_driver.hub_status_data = ifxhcd_hub_status_data;
++ _ifxhcd->hc_driver.hub_control = ifxhcd_hub_control;
++ //_ifxhcd->hc_driver.hub_suspend =
++ //_ifxhcd->hc_driver.hub_resume =
++
++ /* Allocate memory for and initialize the base HCD and */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
++ syshcd = usb_create_hcd(&_ifxhcd->hc_driver, _ifxhcd->dev, _ifxhcd->core_if.core_name);
++#else
++ syshcd = usb_create_hcd(&_ifxhcd->hc_driver, _ifxhcd->dev, _ifxhcd->dev->bus_id);
++#endif
++
++ if (syshcd == NULL)
++ {
++ retval = -ENOMEM;
++ goto error1;
++ }
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
++ syshcd->has_tt = 1;
++#endif
++
++ syshcd->rsrc_start = (unsigned long)_ifxhcd->core_if.core_global_regs;
++ syshcd->regs = (void *)_ifxhcd->core_if.core_global_regs;
++ syshcd->self.otg_port = 0;
++
++ //*((unsigned long *)(&(syshcd->hcd_priv)))=(unsigned long)_ifxhcd;
++ //*((unsigned long *)(&(syshcd->hcd_priv[0])))=(unsigned long)_ifxhcd;
++ syshcd->hcd_priv[0]=(unsigned long)_ifxhcd;
++ _ifxhcd->syshcd=syshcd;
++
++ INIT_LIST_HEAD(&_ifxhcd->epqh_np_active );
++ INIT_LIST_HEAD(&_ifxhcd->epqh_np_ready );
++ INIT_LIST_HEAD(&_ifxhcd->epqh_intr_active );
++ INIT_LIST_HEAD(&_ifxhcd->epqh_intr_ready );
++ #ifdef __EN_ISOC__
++ INIT_LIST_HEAD(&_ifxhcd->epqh_isoc_active );
++ INIT_LIST_HEAD(&_ifxhcd->epqh_isoc_ready );
++ #endif
++ INIT_LIST_HEAD(&_ifxhcd->epqh_stdby );
++ INIT_LIST_HEAD(&_ifxhcd->urbd_complete_list);
++
++ /*
++ * Create a host channel descriptor for each host channel implemented
++ * in the controller. Initialize the channel descriptor array.
++ */
++ INIT_LIST_HEAD(&_ifxhcd->free_hc_list);
++ {
++ int num_channels = _ifxhcd->core_if.params.host_channels;
++ int i;
++ for (i = 0; i < num_channels; i++)
++ {
++ _ifxhcd->ifxhc[i].hc_num = i;
++ IFX_DEBUGPL(DBG_HCDV, "HCD Added channel #%d\n", i);
++ }
++ }
++
++ /* Set device flags indicating whether the HCD supports DMA. */
++ if(_ifxhcd->dev->dma_mask)
++ *(_ifxhcd->dev->dma_mask) = ~0;
++ _ifxhcd->dev->coherent_dma_mask = ~0;
++
++ /*
++ * Finish generic HCD initialization and start the HCD. This function
++ * allocates the DMA buffer pool, registers the USB bus, requests the
++ * IRQ line, and calls ifxusb_hcd_start method.
++ */
++// retval = usb_add_hcd(syshcd, _ifxhcd->core_if.irq, SA_INTERRUPT|SA_SHIRQ);
++ retval = usb_add_hcd(syshcd, _ifxhcd->core_if.irq, IRQF_DISABLED | IRQF_SHARED );
++ if (retval < 0)
++ goto error2;
++
++ /*
++ * Allocate space for storing data on status transactions. Normally no
++ * data is sent, but this space acts as a bit bucket. This must be
++ * done after usb_add_hcd since that function allocates the DMA buffer
++ * pool.
++ */
++ _ifxhcd->status_buf = ifxusb_alloc_buf(IFXHCD_STATUS_BUF_SIZE, 1);
++
++ if (_ifxhcd->status_buf)
++ {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32)
++ IFX_DEBUGPL(DBG_HCD, "IFX USB HCD Initialized, bus=%s, usbbus=%d\n", _ifxhcd->core_if.core_name, syshcd->self.busnum);
++#else
++ IFX_DEBUGPL(DBG_HCD, "IFX USB HCD Initialized, bus=%s, usbbus=%d\n", _ifxhcd->dev->bus_id, syshcd->self.busnum);
++#endif
++ return 0;
++ }
++ IFX_ERROR("%s: status_buf allocation failed\n", __func__);
++
++ /* Error conditions */
++ usb_remove_hcd(syshcd);
++error2:
++ ifxhcd_freeextra(syshcd);
++ usb_put_hcd(syshcd);
++error1:
++ return retval;
++}
++
++/*!
++ \brief Removes the HCD.
++ Frees memory and resources associated with the HCD and deregisters the bus.
++ */
++void ifxhcd_remove(ifxhcd_hcd_t *_ifxhcd)
++{
++ struct usb_hcd *syshcd = ifxhcd_to_syshcd(_ifxhcd);
++
++ IFX_DEBUGPL(DBG_HCD, "IFX USB HCD REMOVE\n");
++
++/* == AVM/WK 20100709 - Fix: Order changed, disable IRQs not before remove_hcd == */
++
++ usb_remove_hcd(syshcd);
++
++ /* Turn off all interrupts */
++ ifxusb_wreg (&_ifxhcd->core_if.core_global_regs->gintmsk, 0);
++ ifxusb_mreg (&_ifxhcd->core_if.core_global_regs->gahbcfg, 1, 0);
++
++ ifxhcd_freeextra(syshcd);
++
++ usb_put_hcd(syshcd);
++
++ return;
++}
++
++
++/* =========================================================================
++ * Linux HC Driver Functions
++ * ========================================================================= */
++
++/*!
++ \brief Initializes the IFXUSB controller and its root hub and prepares it for host
++ mode operation. Activates the root port. Returns 0 on success and a negative
++ error code on failure.
++ Called by USB stack.
++ */
++int ifxhcd_start(struct usb_hcd *_syshcd)
++{
++ ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
++ ifxusb_core_if_t *core_if = &ifxhcd->core_if;
++ struct usb_bus *bus;
++
++ IFX_DEBUGPL(DBG_HCD, "IFX USB HCD START\n");
++
++ bus = hcd_to_bus(_syshcd);
++
++ /* Initialize the bus state. */
++ _syshcd->state = HC_STATE_RUNNING;
++
++ /* Initialize and connect root hub if one is not already attached */
++ if (bus->root_hub)
++ {
++ IFX_DEBUGPL(DBG_HCD, "IFX USB HCD Has Root Hub\n");
++ /* Inform the HUB driver to resume. */
++ usb_hcd_resume_root_hub(_syshcd);
++ }
++
++ ifxhcd->flags.d32 = 0;
++
++ /* Put all channels in the free channel list and clean up channel states.*/
++ {
++ struct list_head *item;
++ item = ifxhcd->free_hc_list.next;
++ while (item != &ifxhcd->free_hc_list)
++ {
++ list_del(item);
++ item = ifxhcd->free_hc_list.next;
++ }
++ }
++ {
++ int num_channels = ifxhcd->core_if.params.host_channels;
++ int i;
++ for (i = 0; i < num_channels; i++)
++ {
++ ifxhcd_hc_t *channel;
++ channel = &ifxhcd->ifxhc[i];
++ list_add_tail(&channel->hc_list_entry, &ifxhcd->free_hc_list);
++ ifxhcd_hc_cleanup(&ifxhcd->core_if, channel);
++ }
++ }
++ /* Initialize the USB core for host mode operation. */
++
++ ifxusb_host_enable_interrupts(core_if);
++ ifxusb_enable_global_interrupts(core_if);
++ ifxusb_phy_power_on (core_if);
++
++ ifxusb_vbus_init(core_if);
++
++ /* Turn on the vbus power. */
++ {
++ hprt0_data_t hprt0;
++ hprt0.d32 = ifxusb_read_hprt0(core_if);
++
++ IFX_PRINT("Init: Power Port (%d)\n", hprt0.b.prtpwr);
++ if (hprt0.b.prtpwr == 0 )
++ {
++ hprt0.b.prtpwr = 1;
++ ifxusb_wreg(core_if->hprt0, hprt0.d32);
++ ifxusb_vbus_on(core_if);
++ }
++ }
++ return 0;
++}
++
++
++/*!
++ \brief Halts the IFXUSB host mode operations in a clean manner. USB transfers are
++ stopped.
++ */
++void ifxhcd_stop(struct usb_hcd *_syshcd)
++{
++ ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd(_syshcd);
++ hprt0_data_t hprt0 = { .d32=0 };
++
++ IFX_DEBUGPL(DBG_HCD, "IFX USB HCD STOP\n");
++
++ /* Turn off all interrupts. */
++ ifxusb_disable_global_interrupts(&ifxhcd->core_if );
++ ifxusb_host_disable_interrupts(&ifxhcd->core_if );
++#ifdef __USE_TIMER_4_SOF__
++ hrtimer_cancel(&ifxhcd->hr_timer);
++#endif
++ /*
++ * The root hub should be disconnected before this function is called.
++ * The disconnect will clear the URBD lists (via ..._hcd_urb_dequeue)
++ * and the EPQH lists (via ..._hcd_endpoint_disable).
++ */
++
++ /* Turn off the vbus power */
++ IFX_PRINT("PortPower off\n");
++
++ ifxusb_vbus_off(&ifxhcd->core_if );
++
++ ifxusb_vbus_free(&ifxhcd->core_if );
++
++ hprt0.b.prtpwr = 0;
++ ifxusb_wreg(ifxhcd->core_if.hprt0, hprt0.d32);
++ return;
++}
++
++/*!
++ \brief Returns the current frame number
++ */
++int ifxhcd_get_frame_number(struct usb_hcd *_syshcd)
++{
++ ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd(_syshcd);
++ hfnum_data_t hfnum;
++
++ hfnum.d32 = ifxusb_rreg(&ifxhcd->core_if.host_global_regs->hfnum);
++
++ return hfnum.b.frnum;
++}
++
++/*!
++ \brief Starts processing a USB transfer request specified by a USB Request Block
++ (URB). mem_flags indicates the type of memory allocation to use while
++ processing this URB.
++ */
++int ifxhcd_urb_enqueue( struct usb_hcd *_syshcd,
++ /*--- struct usb_host_endpoint *_sysep, Parameter im 2.6.28 entfallen ---*/
++ struct urb *_urb,
++ gfp_t _mem_flags)
++{
++ int retval = 0;
++ ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
++ struct usb_host_endpoint *_sysep = ifxhcd_urb_to_endpoint(_urb);
++ ifxhcd_epqh_t *epqh;
++
++ #ifdef __DEBUG__
++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB))
++ dump_urb_info(_urb, "ifxusb_hcd_urb_enqueue");
++ #endif //__DEBUG__
++
++ if (!ifxhcd->flags.b.port_connect_status) /* No longer connected. */
++ return -ENODEV;
++
++ #ifndef __EN_ISOC__
++ if(usb_pipetype(_urb->pipe) == PIPE_ISOCHRONOUS)
++ {
++ IFX_ERROR("ISOC transfer not supported!!!\n");
++ return -ENODEV;
++ }
++ #endif
++
++ retval=ifxhcd_urbd_create (ifxhcd,_urb);
++
++ if (retval)
++ {
++ IFX_ERROR("IFXUSB HCD URB Enqueue failed creating URBD\n");
++ return retval;
++ }
++ epqh = (ifxhcd_epqh_t *) _sysep->hcpriv;
++ ifxhcd_epqh_ready(ifxhcd, epqh);
++
++ select_eps(ifxhcd);
++ //enable_sof(ifxhcd);
++ {
++ gint_data_t gintsts;
++ gintsts.d32=0;
++ gintsts.b.sofintr = 1;
++ ifxusb_mreg(&ifxhcd->core_if.core_global_regs->gintmsk, 0,gintsts.d32);
++ }
++
++ return retval;
++}
++
++/*!
++ \brief Aborts/cancels a USB transfer request. Always returns 0 to indicate
++ success.
++ */
++int ifxhcd_urb_dequeue( struct usb_hcd *_syshcd,
++ struct urb *_urb, int status /* Parameter neu in 2.6.28 */)
++{
++ unsigned long flags;
++ ifxhcd_hcd_t *ifxhcd;
++ ifxhcd_urbd_t *urbd;
++ ifxhcd_epqh_t *epqh;
++ int is_active=0;
++ int rc;
++
++ struct usb_host_endpoint *_sysep;
++
++ IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD URB Dequeue\n");
++
++ #ifndef __EN_ISOC__
++ if(usb_pipetype(_urb->pipe) == PIPE_ISOCHRONOUS)
++ return 0;
++ #endif
++
++ _sysep = ifxhcd_urb_to_endpoint(_urb);
++
++ ifxhcd = syshcd_to_ifxhcd(_syshcd);
++
++ SPIN_LOCK_IRQSAVE(&ifxhcd->lock, flags);
++
++ /*== AVM/BC 20100630 - 2.6.28 needs HCD link/unlink URBs ==*/
++ rc = usb_hcd_check_unlink_urb(_syshcd, _urb, status);
++ if (rc) {
++ SPIN_UNLOCK_IRQRESTORE(&ifxhcd->lock, flags);
++ return rc;
++ }
++
++ urbd = (ifxhcd_urbd_t *) _urb->hcpriv;
++
++ if(_sysep)
++ epqh = (ifxhcd_epqh_t *) _sysep->hcpriv;
++ else
++ epqh = (ifxhcd_epqh_t *) urbd->epqh;
++
++ if(epqh!=urbd->epqh)
++ IFX_ERROR("%s inconsistant epqh %p %p\n",__func__,epqh,urbd->epqh);
++
++ #ifdef __DEBUG__
++ if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB))
++ {
++ dump_urb_info(_urb, "ifxhcd_urb_dequeue");
++ if (epqh->is_active)
++ dump_channel_info(ifxhcd, epqh);
++ }
++ #endif //__DEBUG__
++
++ if(!epqh->hc)
++ epqh->is_active=0;
++ else if (!ifxhcd->flags.b.port_connect_status)
++ epqh->is_active=0;
++ else if (epqh->is_active && urbd->is_active)
++ {
++ /*== AVM/WK 20100709 - halt channel only if really started ==*/
++ //if (epqh->hc->xfer_started && !epqh->hc->wait_for_sof) {
++ /*== AVM/WK 20101112 - halt channel if started ==*/
++ if (epqh->hc->xfer_started) {
++ /*
++ * If still connected (i.e. in host mode), halt the
++ * channel so it can be used for other transfers. If
++ * no longer connected, the host registers can't be
++ * written to halt the channel since the core is in
++ * device mode.
++ */
++ /* == 20110803 AVM/WK FIX propagate status == */
++ if (_urb->status == -EINPROGRESS) {
++ _urb->status = status;
++ }
++ ifxhcd_hc_halt(&ifxhcd->core_if, epqh->hc, HC_XFER_URB_DEQUEUE);
++ epqh->hc = NULL;
++ is_active=1;
++ }
++ }
++
++ if(is_active)
++ {
++ SPIN_UNLOCK_IRQRESTORE(&ifxhcd->lock, flags);
++ }
++ else
++ {
++ list_del_init(&urbd->urbd_list_entry);
++ kfree (urbd);
++
++ /*== AVM/BC 20100630 - 2.6.28 needs HCD link/unlink URBs ==*/
++ usb_hcd_unlink_urb_from_ep(_syshcd, _urb);
++
++ SPIN_UNLOCK_IRQRESTORE(&ifxhcd->lock, flags);
++ _urb->hcpriv = NULL;
++// usb_hcd_giveback_urb(_syshcd, _urb);
++ usb_hcd_giveback_urb(_syshcd, _urb, status /* neu in 2.6.28 */);
++ select_eps(ifxhcd);
++ }
++
++ return 0;
++}
++
++
++
++/*!
++ \brief Frees resources in the IFXUSB controller related to a given endpoint. Also
++ clears state in the HCD related to the endpoint. Any URBs for the endpoint
++ must already be dequeued.
++ */
++void ifxhcd_endpoint_disable( struct usb_hcd *_syshcd,
++ struct usb_host_endpoint *_sysep)
++{
++ ifxhcd_epqh_t *epqh;
++ ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd(_syshcd);
++ unsigned long flags;
++
++ int retry = 0;
++
++ IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD EP DISABLE: _bEndpointAddress=0x%02x, "
++ "endpoint=%d\n", _sysep->desc.bEndpointAddress,
++ ifxhcd_ep_addr_to_endpoint(_sysep->desc.bEndpointAddress));
++
++ SPIN_LOCK_IRQSAVE(&ifxhcd->lock, flags);
++ if((uint32_t)_sysep>=0x80000000 && (uint32_t)_sysep->hcpriv>=(uint32_t)0x80000000)
++ {
++ epqh = (ifxhcd_epqh_t *)(_sysep->hcpriv);
++ if (epqh && epqh->sysep==_sysep)
++ {
++
++#if 1 /*== AVM/BC 20101111 CHG Option active: Kill URBs when disabling EP ==*/
++ while (!list_empty(&epqh->urbd_list))
++ {
++ if (retry++ > 250)
++ {
++ IFX_WARN("IFXUSB HCD EP DISABLE:"
++ " URBD List for this endpoint is not empty\n");
++ break;
++ }
++ kill_all_urbs_in_epqh(ifxhcd, epqh, -ETIMEDOUT);
++ }
++#else
++ while (!list_empty(&epqh->urbd_list))
++ {
++ /** Check that the QTD list is really empty */
++ if (retry++ > 250)
++ {
++ IFX_WARN("IFXUSB HCD EP DISABLE:"
++ " URBD List for this endpoint is not empty\n");
++ break;
++ }
++ SPIN_UNLOCK_IRQRESTORE(&ifxhcd->lock, flags);
++ schedule_timeout_uninterruptible(1);
++ SPIN_LOCK_IRQSAVE(&ifxhcd->lock, flags);
++ }
++#endif
++
++ ifxhcd_epqh_free(epqh);
++ _sysep->hcpriv = NULL;
++ }
++ }
++ SPIN_UNLOCK_IRQRESTORE(&ifxhcd->lock, flags);
++}
++
++
++/*!
++ \brief Handles host mode interrupts for the IFXUSB controller. Returns IRQ_NONE if
++ * there was no interrupt to handle. Returns IRQ_HANDLED if there was a valid
++ * interrupt.
++ *
++ * This function is called by the USB core when an interrupt occurs
++ */
++irqreturn_t ifxhcd_irq(struct usb_hcd *_syshcd)
++{
++ ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
++ int32_t retval=0;
++
++ //mask_and_ack_ifx_irq (ifxhcd->core_if.irq);
++ retval = ifxhcd_handle_intr(ifxhcd);
++ return IRQ_RETVAL(retval);
++}
++
++
++/*!
++ \brief Handles host mode Over Current Interrupt
++ */
++irqreturn_t ifxhcd_oc_irq(int _irq , void *_dev)
++{
++ ifxhcd_hcd_t *ifxhcd = _dev;
++ int32_t retval=1;
++
++ ifxhcd->flags.b.port_over_current_change = 1;
++ ifxusb_vbus_off(&ifxhcd->core_if);
++ IFX_DEBUGP("OC INTERRUPT # %d\n",ifxhcd->core_if.core_no);
++
++ //mask_and_ack_ifx_irq (_irq);
++ return IRQ_RETVAL(retval);
++}
++
++/*!
++ \brief Creates Status Change bitmap for the root hub and root port. The bitmap is
++ returned in buf. Bit 0 is the status change indicator for the root hub. Bit 1
++ is the status change indicator for the single root port. Returns 1 if either
++ change indicator is 1, otherwise returns 0.
++ */
++int ifxhcd_hub_status_data(struct usb_hcd *_syshcd, char *_buf)
++{
++ ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
++
++ _buf[0] = 0;
++ _buf[0] |= (ifxhcd->flags.b.port_connect_status_change ||
++ ifxhcd->flags.b.port_reset_change ||
++ ifxhcd->flags.b.port_enable_change ||
++ ifxhcd->flags.b.port_suspend_change ||
++ ifxhcd->flags.b.port_over_current_change) << 1;
++
++ #ifdef __DEBUG__
++ if (_buf[0])
++ {
++ IFX_DEBUGPL(DBG_HCD, "IFXUSB HCD HUB STATUS DATA:"
++ " Root port status changed\n");
++ IFX_DEBUGPL(DBG_HCDV, " port_connect_status_change: %d\n",
++ ifxhcd->flags.b.port_connect_status_change);
++ IFX_DEBUGPL(DBG_HCDV, " port_reset_change: %d\n",
++ ifxhcd->flags.b.port_reset_change);
++ IFX_DEBUGPL(DBG_HCDV, " port_enable_change: %d\n",
++ ifxhcd->flags.b.port_enable_change);
++ IFX_DEBUGPL(DBG_HCDV, " port_suspend_change: %d\n",
++ ifxhcd->flags.b.port_suspend_change);
++ IFX_DEBUGPL(DBG_HCDV, " port_over_current_change: %d\n",
++ ifxhcd->flags.b.port_over_current_change);
++ }
++ #endif //__DEBUG__
++ return (_buf[0] != 0);
++}
++
++#ifdef __WITH_HS_ELECT_TST__
++ extern void do_setup(ifxusb_core_if_t *_core_if) ;
++ extern void do_in_ack(ifxusb_core_if_t *_core_if);
++#endif //__WITH_HS_ELECT_TST__
++
++/*!
++ \brief Handles hub class-specific requests.
++ */
++int ifxhcd_hub_control( struct usb_hcd *_syshcd,
++ u16 _typeReq,
++ u16 _wValue,
++ u16 _wIndex,
++ char *_buf,
++ u16 _wLength)
++{
++ int retval = 0;
++
++ ifxhcd_hcd_t *ifxhcd = syshcd_to_ifxhcd (_syshcd);
++ ifxusb_core_if_t *core_if = &ifxhcd->core_if;
++ struct usb_hub_descriptor *desc;
++ hprt0_data_t hprt0 = {.d32 = 0};
++
++ uint32_t port_status;
++
++ switch (_typeReq)
++ {
++ case ClearHubFeature:
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "ClearHubFeature 0x%x\n", _wValue);
++ switch (_wValue)
++ {
++ case C_HUB_LOCAL_POWER:
++ case C_HUB_OVER_CURRENT:
++ /* Nothing required here */
++ break;
++ default:
++ retval = -EINVAL;
++ IFX_ERROR ("IFXUSB HCD - "
++ "ClearHubFeature request %xh unknown\n", _wValue);
++ }
++ break;
++ case ClearPortFeature:
++ if (!_wIndex || _wIndex > 1)
++ goto error;
++
++ switch (_wValue)
++ {
++ case USB_PORT_FEAT_ENABLE:
++ IFX_DEBUGPL (DBG_ANY, "IFXUSB HCD HUB CONTROL - "
++ "ClearPortFeature USB_PORT_FEAT_ENABLE\n");
++ hprt0.d32 = ifxusb_read_hprt0 (core_if);
++ hprt0.b.prtena = 1;
++ ifxusb_wreg(core_if->hprt0, hprt0.d32);
++ break;
++ case USB_PORT_FEAT_SUSPEND:
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
++ hprt0.d32 = ifxusb_read_hprt0 (core_if);
++ hprt0.b.prtres = 1;
++ ifxusb_wreg(core_if->hprt0, hprt0.d32);
++ /* Clear Resume bit */
++ mdelay (100);
++ hprt0.b.prtres = 0;
++ ifxusb_wreg(core_if->hprt0, hprt0.d32);
++ break;
++ case USB_PORT_FEAT_POWER:
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "ClearPortFeature USB_PORT_FEAT_POWER\n");
++ #ifdef __IS_DUAL__
++ ifxusb_vbus_off(core_if);
++ #else
++ ifxusb_vbus_off(core_if);
++ #endif
++ hprt0.d32 = ifxusb_read_hprt0 (core_if);
++ hprt0.b.prtpwr = 0;
++ ifxusb_wreg(core_if->hprt0, hprt0.d32);
++ break;
++ case USB_PORT_FEAT_INDICATOR:
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "ClearPortFeature USB_PORT_FEAT_INDICATOR\n");
++ /* Port inidicator not supported */
++ break;
++ case USB_PORT_FEAT_C_CONNECTION:
++ /* Clears drivers internal connect status change
++ * flag */
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "ClearPortFeature USB_PORT_FEAT_C_CONNECTION\n");
++ ifxhcd->flags.b.port_connect_status_change = 0;
++ break;
++ case USB_PORT_FEAT_C_RESET:
++ /* Clears the driver's internal Port Reset Change
++ * flag */
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "ClearPortFeature USB_PORT_FEAT_C_RESET\n");
++ ifxhcd->flags.b.port_reset_change = 0;
++ break;
++ case USB_PORT_FEAT_C_ENABLE:
++ /* Clears the driver's internal Port
++ * Enable/Disable Change flag */
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "ClearPortFeature USB_PORT_FEAT_C_ENABLE\n");
++ ifxhcd->flags.b.port_enable_change = 0;
++ break;
++ case USB_PORT_FEAT_C_SUSPEND:
++ /* Clears the driver's internal Port Suspend
++ * Change flag, which is set when resume signaling on
++ * the host port is complete */
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "ClearPortFeature USB_PORT_FEAT_C_SUSPEND\n");
++ ifxhcd->flags.b.port_suspend_change = 0;
++ break;
++ case USB_PORT_FEAT_C_OVER_CURRENT:
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "ClearPortFeature USB_PORT_FEAT_C_OVER_CURRENT\n");
++ ifxhcd->flags.b.port_over_current_change = 0;
++ break;
++ default:
++ retval = -EINVAL;
++ IFX_ERROR ("IFXUSB HCD - "
++ "ClearPortFeature request %xh "
++ "unknown or unsupported\n", _wValue);
++ }
++ break;
++ case GetHubDescriptor:
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "GetHubDescriptor\n");
++ desc = (struct usb_hub_descriptor *)_buf;
++ desc->bDescLength = 9;
++ desc->bDescriptorType = 0x29;
++ desc->bNbrPorts = 1;
++ desc->wHubCharacteristics = 0x08;
++ desc->bPwrOn2PwrGood = 1;
++ desc->bHubContrCurrent = 0;
++// desc->bitmap[0] = 0;
++// desc->bitmap[1] = 0xff;
++ break;
++ case GetHubStatus:
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "GetHubStatus\n");
++ memset (_buf, 0, 4);
++ break;
++ case GetPortStatus:
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "GetPortStatus\n");
++ if (!_wIndex || _wIndex > 1)
++ goto error;
++
++# ifdef CONFIG_AVM_POWERMETER
++ {
++ /* first port only, but 2 Hosts */
++ static unsigned char ucOldPower1 = 255;
++ static unsigned char ucOldPower2 = 255;
++
++ unsigned char ucNewPower = 0;
++ struct usb_device *childdev = _syshcd->self.root_hub->children[0];
++
++ if (childdev != NULL) {
++ ucNewPower = (childdev->actconfig != NULL)
++ ? childdev->actconfig->desc.bMaxPower
++ : 50;/* default: 50 means 100 mA*/
++ }
++ if (_syshcd->self.busnum == 1) {
++ if (ucOldPower1 != ucNewPower) {
++ ucOldPower1 = ucNewPower;
++ printk (KERN_INFO "IFXHCD#1: AVM Powermeter changed to %u mA\n", ucNewPower*2);
++ PowerManagmentRessourceInfo(powerdevice_usb_host, ucNewPower*2);
++ }
++ } else {
++ if (ucOldPower2 != ucNewPower) {
++ ucOldPower2 = ucNewPower;
++ printk (KERN_INFO "IFXHCD#2: AVM Powermeter changed to %u mA\n", ucNewPower*2);
++ PowerManagmentRessourceInfo(powerdevice_usb_host2, ucNewPower*2);
++ }
++ }
++ }
++# endif /*--- #ifdef CONFIG_AVM_POWERMETER ---*/
++
++ port_status = 0;
++ if (ifxhcd->flags.b.port_connect_status_change)
++ port_status |= (1 << USB_PORT_FEAT_C_CONNECTION);
++ if (ifxhcd->flags.b.port_enable_change)
++ port_status |= (1 << USB_PORT_FEAT_C_ENABLE);
++ if (ifxhcd->flags.b.port_suspend_change)
++ port_status |= (1 << USB_PORT_FEAT_C_SUSPEND);
++ if (ifxhcd->flags.b.port_reset_change)
++ port_status |= (1 << USB_PORT_FEAT_C_RESET);
++ if (ifxhcd->flags.b.port_over_current_change)
++ {
++ IFX_ERROR("Device Not Supported\n");
++ port_status |= (1 << USB_PORT_FEAT_C_OVER_CURRENT);
++ }
++ if (!ifxhcd->flags.b.port_connect_status)
++ {
++ /*
++ * The port is disconnected, which means the core is
++ * either in device mode or it soon will be. Just
++ * return 0's for the remainder of the port status
++ * since the port register can't be read if the core
++ * is in device mode.
++ */
++ *((u32 *) _buf) = cpu_to_le32(port_status);
++ break;
++ }
++
++ hprt0.d32 = ifxusb_rreg(core_if->hprt0);
++ IFX_DEBUGPL(DBG_HCDV, " HPRT0: 0x%08x\n", hprt0.d32);
++ if (hprt0.b.prtconnsts)
++ port_status |= (1 << USB_PORT_FEAT_CONNECTION);
++ if (hprt0.b.prtena)
++ port_status |= (1 << USB_PORT_FEAT_ENABLE);
++ if (hprt0.b.prtsusp)
++ port_status |= (1 << USB_PORT_FEAT_SUSPEND);
++ if (hprt0.b.prtovrcurract)
++ port_status |= (1 << USB_PORT_FEAT_OVER_CURRENT);
++ if (hprt0.b.prtrst)
++ port_status |= (1 << USB_PORT_FEAT_RESET);
++ if (hprt0.b.prtpwr)
++ port_status |= (1 << USB_PORT_FEAT_POWER);
++/* if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_HIGH_SPEED)
++ port_status |= (1 << USB_PORT_FEAT_HIGHSPEED);
++ else if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_LOW_SPEED)
++ port_status |= (1 << USB_PORT_FEAT_LOWSPEED);*/
++ if (hprt0.b.prttstctl)
++ port_status |= (1 << USB_PORT_FEAT_TEST);
++ /* USB_PORT_FEAT_INDICATOR unsupported always 0 */
++ *((u32 *) _buf) = cpu_to_le32(port_status);
++ break;
++ case SetHubFeature:
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "SetHubFeature\n");
++ /* No HUB features supported */
++ break;
++ case SetPortFeature:
++ if (_wValue != USB_PORT_FEAT_TEST && (!_wIndex || _wIndex > 1))
++ goto error;
++ /*
++ * The port is disconnected, which means the core is
++ * either in device mode or it soon will be. Just
++ * return without doing anything since the port
++ * register can't be written if the core is in device
++ * mode.
++ */
++ if (!ifxhcd->flags.b.port_connect_status)
++ break;
++ switch (_wValue)
++ {
++ case USB_PORT_FEAT_SUSPEND:
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "SetPortFeature - USB_PORT_FEAT_SUSPEND\n");
++ hprt0.d32 = ifxusb_read_hprt0 (core_if);
++ hprt0.b.prtsusp = 1;
++ ifxusb_wreg(core_if->hprt0, hprt0.d32);
++ //IFX_PRINT( "SUSPEND: HPRT0=%0x\n", hprt0.d32);
++ /* Suspend the Phy Clock */
++ {
++ pcgcctl_data_t pcgcctl = {.d32=0};
++ pcgcctl.b.stoppclk = 1;
++ ifxusb_wreg(core_if->pcgcctl, pcgcctl.d32);
++ }
++ break;
++ case USB_PORT_FEAT_POWER:
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "SetPortFeature - USB_PORT_FEAT_POWER\n");
++ ifxusb_vbus_on (core_if);
++ hprt0.d32 = ifxusb_read_hprt0 (core_if);
++ hprt0.b.prtpwr = 1;
++ ifxusb_wreg(core_if->hprt0, hprt0.d32);
++ break;
++ case USB_PORT_FEAT_RESET:
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "SetPortFeature - USB_PORT_FEAT_RESET\n");
++ hprt0.d32 = ifxusb_read_hprt0 (core_if);
++ hprt0.b.prtrst = 1;
++ ifxusb_wreg(core_if->hprt0, hprt0.d32);
++ /* Clear reset bit in 10ms (FS/LS) or 50ms (HS) */
++ MDELAY (60);
++ hprt0.b.prtrst = 0;
++ ifxusb_wreg(core_if->hprt0, hprt0.d32);
++ break;
++ #ifdef __WITH_HS_ELECT_TST__
++ case USB_PORT_FEAT_TEST:
++ {
++ uint32_t t;
++ gint_data_t gintmsk;
++ t = (_wIndex >> 8); /* MSB wIndex USB */
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "SetPortFeature - USB_PORT_FEAT_TEST %d\n", t);
++ warn("USB_PORT_FEAT_TEST %d\n", t);
++ if (t < 6)
++ {
++ hprt0.d32 = ifxusb_read_hprt0 (core_if);
++ hprt0.b.prttstctl = t;
++ ifxusb_wreg(core_if->hprt0, hprt0.d32);
++ }
++ else if (t == 6) /* HS_HOST_PORT_SUSPEND_RESUME */
++ {
++ /* Save current interrupt mask */
++ gintmsk.d32 = ifxusb_rreg(&core_if->core_global_regs->gintmsk);
++
++ /* Disable all interrupts while we muck with
++ * the hardware directly
++ */
++ ifxusb_wreg(&core_if->core_global_regs->gintmsk, 0);
++
++ /* 15 second delay per the test spec */
++ mdelay(15000);
++
++ /* Drive suspend on the root port */
++ hprt0.d32 = ifxusb_read_hprt0 (core_if);
++ hprt0.b.prtsusp = 1;
++ hprt0.b.prtres = 0;
++ ifxusb_wreg(core_if->hprt0, hprt0.d32);
++
++ /* 15 second delay per the test spec */
++ mdelay(15000);
++
++ /* Drive resume on the root port */
++ hprt0.d32 = ifxusb_read_hprt0 (core_if);
++ hprt0.b.prtsusp = 0;
++ hprt0.b.prtres = 1;
++ ifxusb_wreg(core_if->hprt0, hprt0.d32);
++ mdelay(100);
++
++ /* Clear the resume bit */
++ hprt0.b.prtres = 0;
++ ifxusb_wreg(core_if->hprt0, hprt0.d32);
++
++ /* Restore interrupts */
++ ifxusb_wreg(&core_if->core_global_regs->gintmsk, gintmsk.d32);
++ }
++ else if (t == 7) /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR setup */
++ {
++ /* Save current interrupt mask */
++ gintmsk.d32 = ifxusb_rreg(&core_if->core_global_regs->gintmsk);
++
++ /* Disable all interrupts while we muck with
++ * the hardware directly
++ */
++ ifxusb_wreg(&core_if->core_global_regs->gintmsk, 0);
++
++ /* 15 second delay per the test spec */
++ mdelay(15000);
++
++ /* Send the Setup packet */
++ do_setup(core_if);
++
++ /* 15 second delay so nothing else happens for awhile */
++ mdelay(15000);
++
++ /* Restore interrupts */
++ ifxusb_wreg(&core_if->core_global_regs->gintmsk, gintmsk.d32);
++ }
++
++ else if (t == 8) /* SINGLE_STEP_GET_DEVICE_DESCRIPTOR execute */
++ {
++ /* Save current interrupt mask */
++ gintmsk.d32 = ifxusb_rreg(&core_if->core_global_regs->gintmsk);
++
++ /* Disable all interrupts while we muck with
++ * the hardware directly
++ */
++ ifxusb_wreg(&core_if->core_global_regs->gintmsk, 0);
++
++ /* Send the Setup packet */
++ do_setup(core_if);
++
++ /* 15 second delay so nothing else happens for awhile */
++ mdelay(15000);
++
++ /* Send the In and Ack packets */
++ do_in_ack(core_if);
++
++ /* 15 second delay so nothing else happens for awhile */
++ mdelay(15000);
++
++ /* Restore interrupts */
++ ifxusb_wreg(&core_if->core_global_regs->gintmsk, gintmsk.d32);
++ }
++ }
++ break;
++ #endif //__WITH_HS_ELECT_TST__
++ case USB_PORT_FEAT_INDICATOR:
++ IFX_DEBUGPL (DBG_HCD, "IFXUSB HCD HUB CONTROL - "
++ "SetPortFeature - USB_PORT_FEAT_INDICATOR\n");
++ /* Not supported */
++ break;
++ default:
++ retval = -EINVAL;
++ IFX_ERROR ("IFXUSB HCD - "
++ "SetPortFeature request %xh "
++ "unknown or unsupported\n", _wValue);
++ }
++ break;
++ default:
++ error:
++ retval = -EINVAL;
++ IFX_WARN ("IFXUSB HCD - "
++ "Unknown hub control request type or invalid typeReq: %xh wIndex: %xh wValue: %xh\n",
++ _typeReq, _wIndex, _wValue);
++ }
++ return retval;
++}
++
++
++/*!
++ \brief Assigns transactions from a URBD to a free host channel and initializes the
++ host channel to perform the transactions. The host channel is removed from
++ the free list.
++ \param _ifxhcd The HCD state structure.
++ \param _epqh Transactions from the first URBD for this EPQH are selected and assigned to a free host channel.
++ */
++static int assign_and_init_hc(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh)
++{
++ ifxhcd_hc_t *ifxhc;
++ ifxhcd_urbd_t *urbd;
++ struct urb *urb;
++
++ IFX_DEBUGPL(DBG_HCDV, "%s(%p,%p)\n", __func__, _ifxhcd, _epqh);
++
++ if(list_empty(&_epqh->urbd_list))
++ return 0;
++
++ ifxhc = list_entry(_ifxhcd->free_hc_list.next, ifxhcd_hc_t, hc_list_entry);
++ /* Remove the host channel from the free list. */
++ list_del_init(&ifxhc->hc_list_entry);
++
++ urbd = list_entry(_epqh->urbd_list.next, ifxhcd_urbd_t, urbd_list_entry);
++ urb = urbd->urb;
++
++ _epqh->hc = ifxhc;
++ _epqh->urbd = urbd;
++ ifxhc->epqh = _epqh;
++
++ urbd->is_active=1;
++
++ /*
++ * Use usb_pipedevice to determine device address. This address is
++ * 0 before the SET_ADDRESS command and the correct address afterward.
++ */
++ ifxhc->dev_addr = usb_pipedevice(urb->pipe);
++ ifxhc->ep_num = usb_pipeendpoint(urb->pipe);
++
++ ifxhc->xfer_started = 0;
++
++ if (urb->dev->speed == USB_SPEED_LOW) ifxhc->speed = IFXUSB_EP_SPEED_LOW;
++ else if (urb->dev->speed == USB_SPEED_FULL) ifxhc->speed = IFXUSB_EP_SPEED_FULL;
++ else ifxhc->speed = IFXUSB_EP_SPEED_HIGH;
++
++ ifxhc->mps = _epqh->mps;
++ ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++
++ ifxhc->ep_type = _epqh->ep_type;
++
++ if(_epqh->ep_type==IFXUSB_EP_TYPE_CTRL)
++ {
++ ifxhc->control_phase=IFXHCD_CONTROL_SETUP;
++ ifxhc->is_in = 0;
++ ifxhc->data_pid_start = IFXUSB_HC_PID_SETUP;
++ ifxhc->xfer_buff = urbd->setup_buff;
++ ifxhc->xfer_len = 8;
++ ifxhc->xfer_count = 0;
++ ifxhc->short_rw =(urb->transfer_flags & URB_ZERO_PACKET)?1:0;
++ }
++ else
++ {
++ ifxhc->is_in = urbd->is_in;
++ ifxhc->xfer_buff = urbd->xfer_buff;
++ ifxhc->xfer_len = urbd->xfer_len;
++ ifxhc->xfer_count = 0;
++ /* == AVM/WK 20100710 Fix - Use toggle of usbcore ==*/
++ //ifxhc->data_pid_start = _epqh->data_toggle;
++ ifxhc->data_pid_start = usb_gettoggle (urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout (urb->pipe))
++ ? IFXUSB_HC_PID_DATA1
++ : IFXUSB_HC_PID_DATA0;
++ if(ifxhc->is_in)
++ ifxhc->short_rw =0;
++ else
++ ifxhc->short_rw =(urb->transfer_flags & URB_ZERO_PACKET)?1:0;
++
++ #ifdef __EN_ISOC__
++ if(_epqh->ep_type==IFXUSB_EP_TYPE_ISOC)
++ {
++ struct usb_iso_packet_descriptor *frame_desc;
++ frame_desc = &urb->iso_frame_desc[urbd->isoc_frame_index];
++ ifxhc->xfer_buff += frame_desc->offset + urbd->isoc_split_offset;
++ ifxhc->xfer_len = frame_desc->length - urbd->isoc_split_offset;
++ if (ifxhc->isoc_xact_pos == IFXUSB_HCSPLIT_XACTPOS_ALL)
++ {
++ if (ifxhc->xfer_len <= 188)
++ ifxhc->isoc_xact_pos = IFXUSB_HCSPLIT_XACTPOS_ALL;
++ else
++ ifxhc->isoc_xact_pos = IFXUSB_HCSPLIT_XACTPOS_BEGIN;
++ }
++ }
++ #endif
++ }
++
++ ifxhc->do_ping=0;
++ if (_ifxhcd->core_if.snpsid < 0x4f54271a && ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
++ ifxhc->do_ping=1;
++
++
++ /* Set the split attributes */
++ ifxhc->split = 0;
++ if (_epqh->need_split) {
++ ifxhc->split = 1;
++ ifxhc->hub_addr = urb->dev->tt->hub->devnum;
++ ifxhc->port_addr = urb->dev->ttport;
++ }
++
++ //ifxhc->uint16_t pkt_count_limit
++
++ {
++ hcint_data_t hc_intr_mask;
++ uint8_t hc_num = ifxhc->hc_num;
++ ifxusb_hc_regs_t *hc_regs = _ifxhcd->core_if.hc_regs[hc_num];
++
++ /* Clear old interrupt conditions for this host channel. */
++ hc_intr_mask.d32 = 0xFFFFFFFF;
++ hc_intr_mask.b.reserved = 0;
++ ifxusb_wreg(&hc_regs->hcint, hc_intr_mask.d32);
++
++ /* Enable channel interrupts required for this transfer. */
++ hc_intr_mask.d32 = 0;
++ hc_intr_mask.b.chhltd = 1;
++ hc_intr_mask.b.ahberr = 1;
++
++ ifxusb_wreg(&hc_regs->hcintmsk, hc_intr_mask.d32);
++
++ /* Enable the top level host channel interrupt. */
++ {
++ uint32_t intr_enable;
++ intr_enable = (1 << hc_num);
++ ifxusb_mreg(&_ifxhcd->core_if.host_global_regs->haintmsk, 0, intr_enable);
++ }
++
++ /* Make sure host channel interrupts are enabled. */
++ {
++ gint_data_t gintmsk ={.d32 = 0};
++ gintmsk.b.hcintr = 1;
++ ifxusb_mreg(&_ifxhcd->core_if.core_global_regs->gintmsk, 0, gintmsk.d32);
++ }
++
++ /*
++ * Program the HCCHARn register with the endpoint characteristics for
++ * the current transfer.
++ */
++ {
++ hcchar_data_t hcchar;
++
++ hcchar.d32 = 0;
++ hcchar.b.devaddr = ifxhc->dev_addr;
++ hcchar.b.epnum = ifxhc->ep_num;
++ hcchar.b.lspddev = (ifxhc->speed == IFXUSB_EP_SPEED_LOW);
++ hcchar.b.eptype = ifxhc->ep_type;
++ hcchar.b.mps = ifxhc->mps;
++ ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
++
++ IFX_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, ifxhc->hc_num);
++ IFX_DEBUGPL(DBG_HCDV, " Dev Addr: %d\n" , hcchar.b.devaddr);
++ IFX_DEBUGPL(DBG_HCDV, " Ep Num: %d\n" , hcchar.b.epnum);
++ IFX_DEBUGPL(DBG_HCDV, " Is Low Speed: %d\n", hcchar.b.lspddev);
++ IFX_DEBUGPL(DBG_HCDV, " Ep Type: %d\n" , hcchar.b.eptype);
++ IFX_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n" , hcchar.b.mps);
++ IFX_DEBUGPL(DBG_HCDV, " Multi Cnt: %d\n" , hcchar.b.multicnt);
++ }
++ /* Program the HCSPLIT register for SPLITs */
++ {
++ hcsplt_data_t hcsplt;
++
++ hcsplt.d32 = 0;
++ if (ifxhc->split)
++ {
++ IFX_DEBUGPL(DBG_HCDV, "Programming HC %d with split --> %s\n", ifxhc->hc_num,
++ (ifxhc->split==2) ? "CSPLIT" : "SSPLIT");
++ hcsplt.b.spltena = 1;
++ hcsplt.b.compsplt = (ifxhc->split==2);
++ #ifdef __EN_ISOC__
++ if(_epqh->ep_type==IFXUSB_EP_TYPE_ISOC)
++ hcsplt.b.xactpos = ifxhc->isoc_xact_pos;
++ else
++ #endif
++ hcsplt.b.xactpos = IFXUSB_HCSPLIT_XACTPOS_ALL;
++ hcsplt.b.hubaddr = ifxhc->hub_addr;
++ hcsplt.b.prtaddr = ifxhc->port_addr;
++ IFX_DEBUGPL(DBG_HCDV, " comp split %d\n" , hcsplt.b.compsplt);
++ IFX_DEBUGPL(DBG_HCDV, " xact pos %d\n" , hcsplt.b.xactpos);
++ IFX_DEBUGPL(DBG_HCDV, " hub addr %d\n" , hcsplt.b.hubaddr);
++ IFX_DEBUGPL(DBG_HCDV, " port addr %d\n" , hcsplt.b.prtaddr);
++ IFX_DEBUGPL(DBG_HCDV, " is_in %d\n" , ifxhc->is_in);
++ IFX_DEBUGPL(DBG_HCDV, " Max Pkt: %d\n" , ifxhc->mps);
++ IFX_DEBUGPL(DBG_HCDV, " xferlen: %d\n" , ifxhc->xfer_len);
++ }
++ ifxusb_wreg(&hc_regs->hcsplt, hcsplt.d32);
++ }
++ }
++
++ ifxhc->nak_retry_r=ifxhc->nak_retry=0;
++ ifxhc->nak_countdown_r=ifxhc->nak_countdown=0;
++
++ if (ifxhc->split)
++ {
++ if(ifxhc->is_in)
++ {
++ }
++ else
++ {
++ }
++ }
++ else if(_epqh->ep_type==IFXUSB_EP_TYPE_CTRL)
++ {
++ if(ifxhc->is_in)
++ {
++ }
++ else
++ {
++ }
++ }
++ else if(_epqh->ep_type==IFXUSB_EP_TYPE_BULK)
++ {
++ if(ifxhc->is_in)
++ {
++// ifxhc->nak_retry_r=ifxhc->nak_retry=nak_retry_max;
++// ifxhc->nak_countdown_r=ifxhc->nak_countdown=nak_countdown_max;
++ }
++ else
++ {
++ }
++ }
++ else if(_epqh->ep_type==IFXUSB_EP_TYPE_INTR)
++ {
++ if(ifxhc->is_in)
++ {
++ }
++ else
++ {
++ }
++ }
++ else if(_epqh->ep_type==IFXUSB_EP_TYPE_ISOC)
++ {
++ if(ifxhc->is_in)
++ {
++ }
++ else
++ {
++ }
++ }
++
++ return 1;
++}
++
++/*!
++ \brief This function selects transactions from the HCD transfer schedule and
++ assigns them to available host channels. It is called from HCD interrupt
++ handler functions.
++ */
++static void select_eps_sub(ifxhcd_hcd_t *_ifxhcd)
++{
++ struct list_head *epqh_ptr;
++ struct list_head *urbd_ptr;
++ ifxhcd_epqh_t *epqh;
++ ifxhcd_urbd_t *urbd;
++ int ret_val=0;
++
++ /*== AVM/BC 20101111 Function called with Lock ==*/
++
++// #ifdef __DEBUG__
++// IFX_DEBUGPL(DBG_HCD, " ifxhcd_select_ep\n");
++// #endif
++
++ /* Process entries in the periodic ready list. */
++ #ifdef __EN_ISOC__
++ epqh_ptr = _ifxhcd->epqh_isoc_ready.next;
++ while (epqh_ptr != &_ifxhcd->epqh_isoc_ready && !list_empty(&_ifxhcd->free_hc_list))
++ {
++ epqh = list_entry(epqh_ptr, ifxhcd_epqh_t, epqh_list_entry);
++ epqh_ptr = epqh_ptr->next;
++ if(epqh->period_do)
++ {
++ if(assign_and_init_hc(_ifxhcd, epqh))
++ {
++ IFX_DEBUGPL(DBG_HCD, " select_eps ISOC\n");
++ list_move_tail(&epqh->epqh_list_entry, &_ifxhcd->epqh_isoc_active);
++ epqh->is_active=1;
++ ret_val=1;
++ epqh->period_do=0;
++ }
++ }
++ }
++ #endif
++
++ epqh_ptr = _ifxhcd->epqh_intr_ready.next;
++ while (epqh_ptr != &_ifxhcd->epqh_intr_ready && !list_empty(&_ifxhcd->free_hc_list))
++ {
++ epqh = list_entry(epqh_ptr, ifxhcd_epqh_t, epqh_list_entry);
++ epqh_ptr = epqh_ptr->next;
++ if(epqh->period_do)
++ {
++ if(assign_and_init_hc(_ifxhcd, epqh))
++ {
++ IFX_DEBUGPL(DBG_HCD, " select_eps INTR\n");
++ list_move_tail(&epqh->epqh_list_entry, &_ifxhcd->epqh_intr_active);
++ epqh->is_active=1;
++ ret_val=1;
++ epqh->period_do=0;
++ }
++ }
++ }
++
++ epqh_ptr = _ifxhcd->epqh_np_ready.next;
++ while (epqh_ptr != &_ifxhcd->epqh_np_ready && !list_empty(&_ifxhcd->free_hc_list)) // may need to preserve at lease one for period
++ {
++ epqh = list_entry(epqh_ptr, ifxhcd_epqh_t, epqh_list_entry);
++ epqh_ptr = epqh_ptr->next;
++ if(assign_and_init_hc(_ifxhcd, epqh))
++ {
++ IFX_DEBUGPL(DBG_HCD, " select_eps CTRL/BULK\n");
++ list_move_tail(&epqh->epqh_list_entry, &_ifxhcd->epqh_np_active);
++ epqh->is_active=1;
++ ret_val=1;
++ }
++ }
++ if(ret_val)
++ /*== AVM/BC 20101111 Function called with Lock ==*/
++ process_channels_sub(_ifxhcd);
++
++ /* AVM/BC 20101111 Urbds completion loop */
++ while (!list_empty(&_ifxhcd->urbd_complete_list))
++ {
++ urbd_ptr = _ifxhcd->urbd_complete_list.next;
++ list_del_init(urbd_ptr);
++
++ urbd = list_entry(urbd_ptr, ifxhcd_urbd_t, urbd_list_entry);
++
++ ifxhcd_complete_urb(_ifxhcd, urbd, urbd->status);
++
++ }
++
++}
++
++static void select_eps_func(unsigned long data)
++{
++ unsigned long flags;
++
++ ifxhcd_hcd_t *ifxhcd;
++ ifxhcd=((ifxhcd_hcd_t *)data);
++
++ /* AVM/BC 20101111 select_eps_in_use flag removed */
++
++ SPIN_LOCK_IRQSAVE(&ifxhcd->lock, flags);
++
++ /*if(ifxhcd->select_eps_in_use){
++ SPIN_UNLOCK_IRQRESTORE(&ifxhcd->lock, flags);
++ return;
++ }
++ ifxhcd->select_eps_in_use=1;
++ */
++
++ select_eps_sub(ifxhcd);
++
++ //ifxhcd->select_eps_in_use=0;
++
++ SPIN_UNLOCK_IRQRESTORE(&ifxhcd->lock, flags);
++}
++
++void select_eps(ifxhcd_hcd_t *_ifxhcd)
++{
++ if(in_irq())
++ {
++ if(!_ifxhcd->select_eps.func)
++ {
++ _ifxhcd->select_eps.next = NULL;
++ _ifxhcd->select_eps.state = 0;
++ atomic_set( &_ifxhcd->select_eps.count, 0);
++ _ifxhcd->select_eps.func = select_eps_func;
++ _ifxhcd->select_eps.data = (unsigned long)_ifxhcd;
++ }
++ tasklet_schedule(&_ifxhcd->select_eps);
++ }
++ else
++ {
++ unsigned long flags;
++
++ /* AVM/BC 20101111 select_eps_in_use flag removed */
++
++ SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
++
++ /*if(_ifxhcd->select_eps_in_use){
++ printk ("select_eps non_irq: busy\n");
++ SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
++ return;
++ }
++ _ifxhcd->select_eps_in_use=1;
++ */
++
++ select_eps_sub(_ifxhcd);
++
++ //_ifxhcd->select_eps_in_use=0;
++
++ SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
++ }
++}
++
++/*!
++ \brief
++ */
++static void process_unaligned( ifxhcd_epqh_t *_epqh)
++{
++ #if defined(__UNALIGNED_BUFFER_ADJ__)
++ if(!_epqh->aligned_checked)
++ {
++ uint32_t xfer_len;
++ xfer_len=_epqh->urbd->xfer_len;
++ if(_epqh->urbd->is_in && xfer_len<_epqh->mps)
++ xfer_len = _epqh->mps;
++ _epqh->using_aligned_buf=0;
++
++ if(xfer_len > 0 && ((unsigned long)_epqh->urbd->xfer_buff) & 3)
++ {
++ if( _epqh->aligned_buf
++ && _epqh->aligned_buf_len > 0
++ && _epqh->aligned_buf_len < xfer_len
++ )
++ {
++ ifxusb_free_buf(_epqh->aligned_buf);
++ _epqh->aligned_buf=NULL;
++ _epqh->aligned_buf_len=0;
++ }
++ if(! _epqh->aligned_buf || ! _epqh->aligned_buf_len)
++ {
++ _epqh->aligned_buf = ifxusb_alloc_buf(xfer_len, _epqh->urbd->is_in);
++ if(_epqh->aligned_buf)
++ _epqh->aligned_buf_len = xfer_len;
++ }
++ if(_epqh->aligned_buf)
++ {
++ if(!_epqh->urbd->is_in)
++ memcpy(_epqh->aligned_buf, _epqh->urbd->xfer_buff, xfer_len);
++ _epqh->using_aligned_buf=1;
++ _epqh->hc->xfer_buff = _epqh->aligned_buf;
++ }
++ else
++ IFX_WARN("%s():%d\n",__func__,__LINE__);
++ }
++ if(_epqh->ep_type==IFXUSB_EP_TYPE_CTRL)
++ {
++ _epqh->using_aligned_setup=0;
++ if(((unsigned long)_epqh->urbd->setup_buff) & 3)
++ {
++ if(! _epqh->aligned_setup)
++ _epqh->aligned_setup = ifxusb_alloc_buf(8,0);
++ if(_epqh->aligned_setup)
++ {
++ memcpy(_epqh->aligned_setup, _epqh->urbd->setup_buff, 8);
++ _epqh->using_aligned_setup=1;
++ }
++ else
++ IFX_WARN("%s():%d\n",__func__,__LINE__);
++ _epqh->hc->xfer_buff = _epqh->aligned_setup;
++ }
++ }
++ }
++ #elif defined(__UNALIGNED_BUFFER_CHK__)
++ if(!_epqh->aligned_checked)
++ {
++ if(_epqh->urbd->is_in)
++ {
++ if(_epqh->urbd->xfer_len==0)
++ IFX_WARN("%s():%d IN xfer while length is zero \n",__func__,__LINE__);
++ else{
++ if(_epqh->urbd->xfer_len < _epqh->mps)
++ IFX_WARN("%s():%d IN xfer while length < mps \n",__func__,__LINE__);
++
++ if(((unsigned long)_epqh->urbd->xfer_buff) & 3)
++ IFX_WARN("%s():%d IN xfer Buffer UNALIGNED\n",__func__,__LINE__);
++ }
++ }
++ else
++ {
++ if(_epqh->urbd->xfer_len > 0 && (((unsigned long)_epqh->urbd->xfer_buff) & 3) )
++ IFX_WARN("%s():%d OUT xfer Buffer UNALIGNED\n",__func__,__LINE__);
++ }
++
++ if(_epqh->ep_type==IFXUSB_EP_TYPE_CTRL)
++ {
++ if(((unsigned long)_epqh->urbd->setup_buff) & 3)
++ IFX_WARN("%s():%d SETUP xfer Buffer UNALIGNED\n",__func__,__LINE__);
++ }
++ }
++ #endif
++ _epqh->aligned_checked=1;
++}
++
++
++/*!
++ \brief
++ */
++void process_channels_sub(ifxhcd_hcd_t *_ifxhcd)
++{
++ ifxhcd_epqh_t *epqh;
++ struct list_head *epqh_item;
++ struct ifxhcd_hc *hc;
++
++ #ifdef __EN_ISOC__
++ if (!list_empty(&_ifxhcd->epqh_isoc_active))
++ {
++ for (epqh_item = _ifxhcd->epqh_isoc_active.next;
++ epqh_item != &_ifxhcd->epqh_isoc_active;
++ )
++ {
++ epqh = list_entry(epqh_item, ifxhcd_epqh_t, epqh_list_entry);
++ epqh_item = epqh_item->next;
++ hc=epqh->hc;
++ if(hc && !hc->xfer_started && epqh->period_do)
++ {
++ if(hc->split==0
++ || hc->split==1
++ )
++ {
++ //epqh->ping_state = 0;
++ process_unaligned(epqh);
++ hc->wait_for_sof=epqh->wait_for_sof;
++ epqh->wait_for_sof=0;
++ ifxhcd_hc_start(&_ifxhcd->core_if, hc);
++ epqh->period_do=0;
++ {
++ gint_data_t gintsts = {.d32 = 0};
++ gintsts.b.sofintr = 1;
++ ifxusb_mreg(&_ifxhcd->core_if.core_global_regs->gintmsk,0, gintsts.d32);
++ }
++ }
++ }
++ }
++ }
++ #endif
++
++ if (!list_empty(&_ifxhcd->epqh_intr_active))
++ {
++ for (epqh_item = _ifxhcd->epqh_intr_active.next;
++ epqh_item != &_ifxhcd->epqh_intr_active;
++ )
++ {
++ epqh = list_entry(epqh_item, ifxhcd_epqh_t, epqh_list_entry);
++ epqh_item = epqh_item->next;
++ hc=epqh->hc;
++ if(hc && !hc->xfer_started && epqh->period_do)
++ {
++ if(hc->split==0
++ || hc->split==1
++ )
++ {
++ //epqh->ping_state = 0;
++ process_unaligned(epqh);
++ hc->wait_for_sof=epqh->wait_for_sof;
++ epqh->wait_for_sof=0;
++ ifxhcd_hc_start(&_ifxhcd->core_if, hc);
++ epqh->period_do=0;
++#ifdef __USE_TIMER_4_SOF__
++ /* AVM/WK change: let hc_start decide, if irq is needed */
++#else
++ {
++ gint_data_t gintsts = {.d32 = 0};
++ gintsts.b.sofintr = 1;
++ ifxusb_mreg(&_ifxhcd->core_if.core_global_regs->gintmsk,0, gintsts.d32);
++ }
++#endif
++ }
++ }
++
++ }
++ }
++
++ if (!list_empty(&_ifxhcd->epqh_np_active))
++ {
++ for (epqh_item = _ifxhcd->epqh_np_active.next;
++ epqh_item != &_ifxhcd->epqh_np_active;
++ )
++ {
++ epqh = list_entry(epqh_item, ifxhcd_epqh_t, epqh_list_entry);
++ epqh_item = epqh_item->next;
++ hc=epqh->hc;
++ if(hc)
++ {
++ if(!hc->xfer_started)
++ {
++ if(hc->split==0
++ || hc->split==1
++ //|| hc->split_counter == 0
++ )
++ {
++ //epqh->ping_state = 0;
++ process_unaligned(epqh);
++ hc->wait_for_sof=epqh->wait_for_sof;
++ epqh->wait_for_sof=0;
++ ifxhcd_hc_start(&_ifxhcd->core_if, hc);
++ }
++ }
++ }
++ }
++ }
++}
++
++void process_channels(ifxhcd_hcd_t *_ifxhcd)
++{
++ unsigned long flags;
++
++ /* AVM/WK Fix: use spin_lock instead busy flag
++ **/
++ SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
++
++ //if(_ifxhcd->process_channels_in_use)
++ // return;
++ //_ifxhcd->process_channels_in_use=1;
++
++ process_channels_sub(_ifxhcd);
++ //_ifxhcd->process_channels_in_use=0;
++ SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
++}
++
++
++#ifdef __HC_XFER_TIMEOUT__
++ static void hc_xfer_timeout(unsigned long _ptr)
++ {
++ hc_xfer_info_t *xfer_info = (hc_xfer_info_t *)_ptr;
++ int hc_num = xfer_info->hc->hc_num;
++ IFX_WARN("%s: timeout on channel %d\n", __func__, hc_num);
++ IFX_WARN(" start_hcchar_val 0x%08x\n", xfer_info->hc->start_hcchar_val);
++ }
++#endif
++
++void ifxhcd_hc_dumb_rx(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc,uint8_t *dump_buf)
++{
++ ifxusb_hc_regs_t *hc_regs = _core_if->hc_regs[_ifxhc->hc_num];
++ hctsiz_data_t hctsiz= { .d32=0 };
++ hcchar_data_t hcchar;
++
++
++ _ifxhc->xfer_len = _ifxhc->mps;
++ hctsiz.b.xfersize = _ifxhc->mps;
++ hctsiz.b.pktcnt = 0;
++ hctsiz.b.pid = _ifxhc->data_pid_start;
++ ifxusb_wreg(&hc_regs->hctsiz, hctsiz.d32);
++
++ ifxusb_wreg(&hc_regs->hcdma, (uint32_t)(CPHYSADDR( ((uint32_t)(dump_buf)))));
++
++ {
++ hcint_data_t hcint= { .d32=0 };
++// hcint.b.nak =1;
++// hcint.b.nyet=1;
++// hcint.b.ack =1;
++ hcint.d32 =0xFFFFFFFF;
++ ifxusb_wreg(&hc_regs->hcint, hcint.d32);
++ }
++
++ /* Set host channel enable after all other setup is complete. */
++ hcchar.b.chen = 1;
++ hcchar.b.chdis = 0;
++ hcchar.b.epdir = 1;
++ IFX_DEBUGPL(DBG_HCDV, " HCCHART: 0x%08x\n", hcchar.d32);
++ ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
++}
++
++/*!
++ \brief This function trigger a data transfer for a host channel and
++ starts the transfer.
++
++ For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
++ register along with a packet count of 1 and the channel is enabled. This
++ causes a single PING transaction to occur. Other fields in HCTSIZ are
++ simply set to 0 since no data transfer occurs in this case.
++
++ For a PING transfer in DMA mode, the HCTSIZ register is initialized with
++ all the information required to perform the subsequent data transfer. In
++ addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
++ controller performs the entire PING protocol, then starts the data
++ transfer.
++ \param _core_if Pointer of core_if structure
++ \param _ifxhc Information needed to initialize the host channel. The xfer_len
++ value may be reduced to accommodate the max widths of the XferSize and
++ PktCnt fields in the HCTSIZn register. The multi_count value may be changed
++ to reflect the final xfer_len value.
++ */
++void ifxhcd_hc_start(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc)
++{
++ hctsiz_data_t hctsiz= { .d32=0 };
++ hcchar_data_t hcchar;
++ uint32_t max_hc_xfer_size = _core_if->params.max_transfer_size;
++ uint16_t max_hc_pkt_count = _core_if->params.max_packet_count;
++ ifxusb_hc_regs_t *hc_regs = _core_if->hc_regs[_ifxhc->hc_num];
++ hfnum_data_t hfnum;
++
++ hctsiz.b.dopng = 0;
++// if(_ifxhc->do_ping && !_ifxhc->is_in) hctsiz.b.dopng = 1;
++
++ _ifxhc->nak_countdown=_ifxhc->nak_countdown_r;
++
++ /* AVM/BC 20101111 Workaround: Always PING if HI-Speed Out and xfer_len > 0 */
++ if(/*_ifxhc->do_ping &&*/
++ (!_ifxhc->is_in) &&
++ (_ifxhc->speed == IFXUSB_EP_SPEED_HIGH) &&
++ ((_ifxhc->ep_type == IFXUSB_EP_TYPE_BULK) || ((_ifxhc->ep_type == IFXUSB_EP_TYPE_CTRL) && (_ifxhc->control_phase != IFXHCD_CONTROL_SETUP))) &&
++ _ifxhc->xfer_len
++ )
++ hctsiz.b.dopng = 1;
++
++ _ifxhc->xfer_started = 1;
++
++ if(_ifxhc->epqh->pkt_count_limit > 0 && _ifxhc->epqh->pkt_count_limit < max_hc_pkt_count )
++ {
++ max_hc_pkt_count=_ifxhc->epqh->pkt_count_limit;
++ if(max_hc_pkt_count * _ifxhc->mps < max_hc_xfer_size)
++ max_hc_xfer_size = max_hc_pkt_count * _ifxhc->mps;
++ }
++ if (_ifxhc->split > 0)
++ {
++ {
++ gint_data_t gintsts = {.d32 = 0};
++ gintsts.b.sofintr = 1;
++ ifxusb_mreg(&_core_if->core_global_regs->gintmsk,0, gintsts.d32);
++ }
++
++ _ifxhc->start_pkt_count = 1;
++ if(!_ifxhc->is_in && _ifxhc->split>1) // OUT CSPLIT
++ _ifxhc->xfer_len = 0;
++ if (_ifxhc->xfer_len > _ifxhc->mps)
++ _ifxhc->xfer_len = _ifxhc->mps;
++ if (_ifxhc->xfer_len > 188)
++ _ifxhc->xfer_len = 188;
++ }
++ else if(_ifxhc->is_in)
++ {
++ _ifxhc->short_rw = 0;
++ if (_ifxhc->xfer_len > 0)
++ {
++ if (_ifxhc->xfer_len > max_hc_xfer_size)
++ _ifxhc->xfer_len = max_hc_xfer_size - _ifxhc->mps + 1;
++ _ifxhc->start_pkt_count = (_ifxhc->xfer_len + _ifxhc->mps - 1) / _ifxhc->mps;
++ if (_ifxhc->start_pkt_count > max_hc_pkt_count)
++ _ifxhc->start_pkt_count = max_hc_pkt_count;
++ }
++ else /* Need 1 packet for transfer length of 0. */
++ _ifxhc->start_pkt_count = 1;
++ _ifxhc->xfer_len = _ifxhc->start_pkt_count * _ifxhc->mps;
++ }
++ else //non-split out
++ {
++ if (_ifxhc->xfer_len == 0)
++ {
++ /*== AVM/BC WK 20110421 ZERO PACKET Workaround: Is not an error ==*/
++ //if(_ifxhc->short_rw==0)
++ // printk(KERN_INFO "%s() line %d: ZLP write without short_rw set!\n",__func__,__LINE__);
++ _ifxhc->start_pkt_count = 1;
++ }
++ else
++ {
++ if (_ifxhc->xfer_len > max_hc_xfer_size)
++ {
++ _ifxhc->start_pkt_count = (max_hc_xfer_size / _ifxhc->mps);
++ _ifxhc->xfer_len = _ifxhc->start_pkt_count * _ifxhc->mps;
++ }
++ else
++ {
++ _ifxhc->start_pkt_count = (_ifxhc->xfer_len+_ifxhc->mps-1) / _ifxhc->mps;
++// if(_ifxhc->start_pkt_count * _ifxhc->mps == _ifxhc->xfer_len )
++// _ifxhc->start_pkt_count += _ifxhc->short_rw;
++ /*== AVM/BC WK 20110421 ZERO PACKET Workaround / check if short_rw is needed ==*/
++ if(_ifxhc->start_pkt_count * _ifxhc->mps != _ifxhc->xfer_len )
++ _ifxhc->short_rw = 0;
++ }
++ }
++ }
++
++ #ifdef __EN_ISOC__
++ if (_ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
++ {
++ /* Set up the initial PID for the transfer. */
++ #if 1
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
++ #else
++ if (_ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
++ {
++ if (_ifxhc->is_in)
++ {
++ if (_ifxhc->multi_count == 1)
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
++ else if (_ifxhc->multi_count == 2)
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA1;
++ else
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA2;
++ }
++ else
++ {
++ if (_ifxhc->multi_count == 1)
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
++ else
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_MDATA;
++ }
++ }
++ else
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
++ #endif
++ }
++ #endif
++
++ hctsiz.b.xfersize = _ifxhc->xfer_len;
++ hctsiz.b.pktcnt = _ifxhc->start_pkt_count;
++ hctsiz.b.pid = _ifxhc->data_pid_start;
++
++ ifxusb_wreg(&hc_regs->hctsiz, hctsiz.d32);
++
++
++ IFX_DEBUGPL(DBG_HCDV, "%s: Channel %d\n", __func__, _ifxhc->hc_num);
++ IFX_DEBUGPL(DBG_HCDV, " Xfer Size: %d\n", hctsiz.b.xfersize);
++ IFX_DEBUGPL(DBG_HCDV, " Num Pkts: %d\n" , hctsiz.b.pktcnt);
++ IFX_DEBUGPL(DBG_HCDV, " Start PID: %d\n", hctsiz.b.pid);
++ IFX_DEBUGPL(DBG_HCDV, " DMA: 0x%08x\n", (uint32_t)(CPHYSADDR( ((uint32_t)(_ifxhc->xfer_buff))+ _ifxhc->xfer_count )));
++ ifxusb_wreg(&hc_regs->hcdma, (uint32_t)(CPHYSADDR( ((uint32_t)(_ifxhc->xfer_buff))+ _ifxhc->xfer_count )));
++
++ /* Start the split */
++ if (_ifxhc->split>0)
++ {
++ hcsplt_data_t hcsplt;
++ hcsplt.d32 = ifxusb_rreg (&hc_regs->hcsplt);
++ hcsplt.b.spltena = 1;
++ if (_ifxhc->split>1)
++ hcsplt.b.compsplt = 1;
++ else
++ hcsplt.b.compsplt = 0;
++
++ #ifdef __EN_ISOC__
++ if (_ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
++ hcsplt.b.xactpos = _ifxhc->isoc_xact_pos;
++ else
++ #endif
++ hcsplt.b.xactpos = IFXUSB_HCSPLIT_XACTPOS_ALL;// if not ISO
++ ifxusb_wreg(&hc_regs->hcsplt, hcsplt.d32);
++ IFX_DEBUGPL(DBG_HCDV, " SPLIT: XACT_POS:0x%08x\n", hcsplt.d32);
++ }
++
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++// hcchar.b.multicnt = _ifxhc->multi_count;
++ hcchar.b.multicnt = 1;
++
++ #ifdef __DEBUG__
++ _ifxhc->start_hcchar_val = hcchar.d32;
++ if (hcchar.b.chdis)
++ IFX_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n",
++ __func__, _ifxhc->hc_num, hcchar.d32);
++ #endif
++
++ /* Set host channel enable after all other setup is complete. */
++ hcchar.b.chen = 1;
++ hcchar.b.chdis = 0;
++ hcchar.b.epdir = _ifxhc->is_in;
++ _ifxhc->hcchar=hcchar.d32;
++
++ IFX_DEBUGPL(DBG_HCDV, " HCCHART: 0x%08x\n", _ifxhc->hcchar);
++
++ /* == 20110901 AVM/WK Fix: Clear IRQ flags in any case ==*/
++ {
++ hcint_data_t hcint= { .d32=0 };
++ hcint.d32 =0xFFFFFFFF;
++ ifxusb_wreg(&hc_regs->hcint, hcint.d32);
++ }
++
++ if(_ifxhc->wait_for_sof==0)
++ {
++ hcint_data_t hcint;
++
++ hcint.d32=ifxusb_rreg(&hc_regs->hcintmsk);
++
++ hcint.b.nak =0;
++ hcint.b.ack =0;
++ /* == 20110901 AVM/WK Fix: We don't need NOT YET IRQ ==*/
++ hcint.b.nyet=0;
++ if(_ifxhc->nak_countdown_r)
++ hcint.b.nak =1;
++ ifxusb_wreg(&hc_regs->hcintmsk, hcint.d32);
++
++ /* AVM WK / BC 20100827
++ * MOVED. Oddframe updated inmediatly before write HCChar Register.
++ */
++ if (_ifxhc->ep_type == IFXUSB_EP_TYPE_INTR || _ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
++ {
++ hfnum.d32 = ifxusb_rreg(&_core_if->host_global_regs->hfnum);
++ /* 1 if _next_ frame is odd, 0 if it's even */
++ hcchar.b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;
++ _ifxhc->hcchar=hcchar.d32;
++ }
++
++ ifxusb_wreg(&hc_regs->hcchar, _ifxhc->hcchar);
++#ifdef __USE_TIMER_4_SOF__
++ } else {
++ //activate SOF IRQ
++ gint_data_t gintsts = {.d32 = 0};
++ gintsts.b.sofintr = 1;
++ ifxusb_mreg(&_core_if->core_global_regs->gintmsk,0, gintsts.d32);
++#endif
++ }
++
++ #ifdef __HC_XFER_TIMEOUT__
++ /* Start a timer for this transfer. */
++ init_timer(&_ifxhc->hc_xfer_timer);
++ _ifxhc->hc_xfer_timer.function = hc_xfer_timeout;
++ _ifxhc->hc_xfer_timer.core_if = _core_if;
++ _ifxhc->hc_xfer_timer.hc = _ifxhc;
++ _ifxhc->hc_xfer_timer.data = (unsigned long)(&_ifxhc->hc_xfer_info);
++ _ifxhc->hc_xfer_timer.expires = jiffies + (HZ*10);
++ add_timer(&_ifxhc->hc_xfer_timer);
++ #endif
++}
++
++/*!
++ \brief Attempts to halt a host channel. This function should only be called
++ to abort a transfer in DMA mode. Under normal circumstances in DMA mode, the
++ controller halts the channel when the transfer is complete or a condition
++ occurs that requires application intervention.
++
++ In DMA mode, always sets the Channel Enable and Channel Disable bits of the
++ HCCHARn register. The controller ensures there is space in the request
++ queue before submitting the halt request.
++
++ Some time may elapse before the core flushes any posted requests for this
++ host channel and halts. The Channel Halted interrupt handler completes the
++ deactivation of the host channel.
++ */
++void ifxhcd_hc_halt(ifxusb_core_if_t *_core_if,
++ ifxhcd_hc_t *_ifxhc,
++ ifxhcd_halt_status_e _halt_status)
++{
++ hcchar_data_t hcchar;
++ ifxusb_hc_regs_t *hc_regs;
++
++ hc_regs = _core_if->hc_regs[_ifxhc->hc_num];
++
++ WARN_ON(_halt_status == HC_XFER_NO_HALT_STATUS);
++
++ if (_halt_status == HC_XFER_URB_DEQUEUE ||
++ _halt_status == HC_XFER_AHB_ERR)
++ {
++ /*
++ * Disable all channel interrupts except Ch Halted. The URBD
++ * and EPQH state associated with this transfer has been cleared
++ * (in the case of URB_DEQUEUE), so the channel needs to be
++ * shut down carefully to prevent crashes.
++ */
++ hcint_data_t hcintmsk;
++ hcintmsk.d32 = 0;
++ hcintmsk.b.chhltd = 1;
++ ifxusb_wreg(&hc_regs->hcintmsk, hcintmsk.d32);
++
++ /*
++ * Make sure no other interrupts besides halt are currently
++ * pending. Handling another interrupt could cause a crash due
++ * to the URBD and EPQH state.
++ */
++ ifxusb_wreg(&hc_regs->hcint, ~hcintmsk.d32);
++
++ /*
++ * Make sure the halt status is set to URB_DEQUEUE or AHB_ERR
++ * even if the channel was already halted for some other
++ * reason.
++ */
++ _ifxhc->halt_status = _halt_status;
++
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ if (hcchar.b.chen == 0)
++ {
++ /*
++ * The channel is either already halted or it hasn't
++ * started yet. In DMA mode, the transfer may halt if
++ * it finishes normally or a condition occurs that
++ * requires driver intervention. Don't want to halt
++ * the channel again. In either Slave or DMA mode,
++ * it's possible that the transfer has been assigned
++ * to a channel, but not started yet when an URB is
++ * dequeued. Don't want to halt a channel that hasn't
++ * started yet.
++ */
++ return;
++ }
++ }
++
++ if (_ifxhc->halting)
++ {
++ /*
++ * A halt has already been issued for this channel. This might
++ * happen when a transfer is aborted by a higher level in
++ * the stack.
++ */
++ #ifdef __DEBUG__
++ IFX_PRINT("*** %s: Channel %d, _hc->halting already set ***\n",
++ __func__, _ifxhc->hc_num);
++ #endif
++ //ifxusb_dump_global_registers(_core_if); */
++ //ifxusb_dump_host_registers(_core_if); */
++ return;
++ }
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ /* == AVM/WK 20100709 halt channel only if enabled ==*/
++ if (hcchar.b.chen) {
++ _ifxhc->halting = 1;
++ hcchar.b.chdis = 1;
++
++ ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
++ _ifxhc->halt_status = _halt_status;
++ }
++
++ IFX_DEBUGPL(DBG_HCDV, "%s: Channel %d\n" , __func__, _ifxhc->hc_num);
++ IFX_DEBUGPL(DBG_HCDV, " hcchar: 0x%08x\n" , hcchar.d32);
++ IFX_DEBUGPL(DBG_HCDV, " halting: %d\n" , _ifxhc->halting);
++ IFX_DEBUGPL(DBG_HCDV, " halt_status: %d\n" , _ifxhc->halt_status);
++
++ return;
++}
++
++/*!
++ \brief Clears a host channel.
++ */
++void ifxhcd_hc_cleanup(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc)
++{
++ ifxusb_hc_regs_t *hc_regs;
++
++ _ifxhc->xfer_started = 0;
++ /*
++ * Clear channel interrupt enables and any unhandled channel interrupt
++ * conditions.
++ */
++ hc_regs = _core_if->hc_regs[_ifxhc->hc_num];
++ ifxusb_wreg(&hc_regs->hcintmsk, 0);
++ ifxusb_wreg(&hc_regs->hcint, 0xFFFFFFFF);
++
++ #ifdef __HC_XFER_TIMEOUT__
++ del_timer(&_ifxhc->hc_xfer_timer);
++ #endif
++ #ifdef __DEBUG__
++ {
++ hcchar_data_t hcchar;
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ if (hcchar.b.chdis)
++ IFX_WARN("%s: chdis set, channel %d, hcchar 0x%08x\n", __func__, _ifxhc->hc_num, hcchar.d32);
++ }
++ #endif
++}
++
++
++
++
++
++
++
++
++#ifdef __DEBUG__
++ static void dump_urb_info(struct urb *_urb, char* _fn_name)
++ {
++ IFX_PRINT("%s, urb %p\n" , _fn_name, _urb);
++ IFX_PRINT(" Device address: %d\n", usb_pipedevice(_urb->pipe));
++ IFX_PRINT(" Endpoint: %d, %s\n" , usb_pipeendpoint(_urb->pipe),
++ (usb_pipein(_urb->pipe) ? "IN" : "OUT"));
++ IFX_PRINT(" Endpoint type: %s\n",
++ ({ char *pipetype;
++ switch (usb_pipetype(_urb->pipe)) {
++ case PIPE_CONTROL: pipetype = "CONTROL"; break;
++ case PIPE_BULK: pipetype = "BULK"; break;
++ case PIPE_INTERRUPT: pipetype = "INTERRUPT"; break;
++ case PIPE_ISOCHRONOUS: pipetype = "ISOCHRONOUS"; break;
++ default: pipetype = "UNKNOWN"; break;
++ };
++ pipetype;
++ }));
++ IFX_PRINT(" Speed: %s\n",
++ ({ char *speed;
++ switch (_urb->dev->speed) {
++ case USB_SPEED_HIGH: speed = "HIGH"; break;
++ case USB_SPEED_FULL: speed = "FULL"; break;
++ case USB_SPEED_LOW: speed = "LOW"; break;
++ default: speed = "UNKNOWN"; break;
++ };
++ speed;
++ }));
++ IFX_PRINT(" Max packet size: %d\n",
++ usb_maxpacket(_urb->dev, _urb->pipe, usb_pipeout(_urb->pipe)));
++ IFX_PRINT(" Data buffer length: %d\n", _urb->transfer_buffer_length);
++ IFX_PRINT(" Transfer buffer: %p, Transfer DMA: %p\n",
++ _urb->transfer_buffer, (void *)_urb->transfer_dma);
++ IFX_PRINT(" Setup buffer: %p, Setup DMA: %p\n",
++ _urb->setup_packet, (void *)_urb->setup_dma);
++ IFX_PRINT(" Interval: %d\n", _urb->interval);
++ if (usb_pipetype(_urb->pipe) == PIPE_ISOCHRONOUS)
++ {
++ int i;
++ for (i = 0; i < _urb->number_of_packets; i++)
++ {
++ IFX_PRINT(" ISO Desc %d:\n", i);
++ IFX_PRINT(" offset: %d, length %d\n",
++ _urb->iso_frame_desc[i].offset,
++ _urb->iso_frame_desc[i].length);
++ }
++ }
++ }
++
++ static void dump_channel_info(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh)
++ {
++ if (_epqh->hc != NULL)
++ {
++ ifxhcd_hc_t *hc = _epqh->hc;
++ struct list_head *item;
++ ifxhcd_epqh_t *epqh_item;
++
++ ifxusb_hc_regs_t *hc_regs;
++
++ hcchar_data_t hcchar;
++ hcsplt_data_t hcsplt;
++ hctsiz_data_t hctsiz;
++ uint32_t hcdma;
++
++ hc_regs = _ifxhcd->core_if.hc_regs[hc->hc_num];
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ hcsplt.d32 = ifxusb_rreg(&hc_regs->hcsplt);
++ hctsiz.d32 = ifxusb_rreg(&hc_regs->hctsiz);
++ hcdma = ifxusb_rreg(&hc_regs->hcdma);
++
++ IFX_PRINT(" Assigned to channel %d:\n" , hc->hc_num);
++ IFX_PRINT(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);
++ IFX_PRINT(" hctsiz 0x%08x, hcdma 0x%08x\n" , hctsiz.d32, hcdma);
++ IFX_PRINT(" dev_addr: %d, ep_num: %d, is_in: %d\n",
++ hc->dev_addr, hc->ep_num, hc->is_in);
++ IFX_PRINT(" ep_type: %d\n" , hc->ep_type);
++ IFX_PRINT(" max_packet_size: %d\n", hc->mps);
++ IFX_PRINT(" data_pid_start: %d\n" , hc->data_pid_start);
++ IFX_PRINT(" xfer_started: %d\n" , hc->xfer_started);
++ IFX_PRINT(" halt_status: %d\n" , hc->halt_status);
++ IFX_PRINT(" xfer_buff: %p\n" , hc->xfer_buff);
++ IFX_PRINT(" xfer_len: %d\n" , hc->xfer_len);
++ IFX_PRINT(" epqh: %p\n" , hc->epqh);
++ IFX_PRINT(" NP Active:\n");
++ list_for_each(item, &_ifxhcd->epqh_np_active)
++ {
++ epqh_item = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
++ IFX_PRINT(" %p\n", epqh_item);
++ }
++ IFX_PRINT(" NP Ready:\n");
++ list_for_each(item, &_ifxhcd->epqh_np_ready)
++ {
++ epqh_item = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
++ IFX_PRINT(" %p\n", epqh_item);
++ }
++ IFX_PRINT(" INTR Active:\n");
++ list_for_each(item, &_ifxhcd->epqh_intr_active)
++ {
++ epqh_item = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
++ IFX_PRINT(" %p\n", epqh_item);
++ }
++ IFX_PRINT(" INTR Ready:\n");
++ list_for_each(item, &_ifxhcd->epqh_intr_ready)
++ {
++ epqh_item = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
++ IFX_PRINT(" %p\n", epqh_item);
++ }
++ #ifdef __EN_ISOC__
++ IFX_PRINT(" ISOC Active:\n");
++ list_for_each(item, &_ifxhcd->epqh_isoc_active)
++ {
++ epqh_item = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
++ IFX_PRINT(" %p\n", epqh_item);
++ }
++ IFX_PRINT(" ISOC Ready:\n");
++ list_for_each(item, &_ifxhcd->epqh_isoc_ready)
++ {
++ epqh_item = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
++ IFX_PRINT(" %p\n", epqh_item);
++ }
++ #endif
++ IFX_PRINT(" Standby:\n");
++ list_for_each(item, &_ifxhcd->epqh_stdby)
++ {
++ epqh_item = list_entry(item, ifxhcd_epqh_t, epqh_list_entry);
++ IFX_PRINT(" %p\n", epqh_item);
++ }
++ }
++ }
++#endif //__DEBUG__
++
++
++/*!
++ \brief This function writes a packet into the Tx FIFO associated with the Host
++ Channel. For a channel associated with a non-periodic EP, the non-periodic
++ Tx FIFO is written. For a channel associated with a periodic EP, the
++ periodic Tx FIFO is written. This function should only be called in Slave
++ mode.
++
++ Upon return the xfer_buff and xfer_count fields in _hc are incremented by
++ then number of bytes written to the Tx FIFO.
++ */
++
++#ifdef __ENABLE_DUMP__
++ void ifxhcd_dump_state(ifxhcd_hcd_t *_ifxhcd)
++ {
++ int num_channels;
++ int i;
++ num_channels = _ifxhcd->core_if.params.host_channels;
++ IFX_PRINT("\n");
++ IFX_PRINT("************************************************************\n");
++ IFX_PRINT("HCD State:\n");
++ IFX_PRINT(" Num channels: %d\n", num_channels);
++ for (i = 0; i < num_channels; i++) {
++ ifxhcd_hc_t *hc = &_ifxhcd->ifxhc[i];
++ IFX_PRINT(" Channel %d:\n", hc->hc_num);
++ IFX_PRINT(" dev_addr: %d, ep_num: %d, ep_is_in: %d\n",
++ hc->dev_addr, hc->ep_num, hc->is_in);
++ IFX_PRINT(" speed: %d\n" , hc->speed);
++ IFX_PRINT(" ep_type: %d\n" , hc->ep_type);
++ IFX_PRINT(" mps: %d\n", hc->mps);
++ IFX_PRINT(" data_pid_start: %d\n" , hc->data_pid_start);
++ IFX_PRINT(" xfer_started: %d\n" , hc->xfer_started);
++ IFX_PRINT(" xfer_buff: %p\n" , hc->xfer_buff);
++ IFX_PRINT(" xfer_len: %d\n" , hc->xfer_len);
++ IFX_PRINT(" xfer_count: %d\n" , hc->xfer_count);
++ IFX_PRINT(" halting: %d\n" , hc->halting);
++ IFX_PRINT(" halt_status: %d\n" , hc->halt_status);
++ IFX_PRINT(" split: %d\n" , hc->split);
++ IFX_PRINT(" hub_addr: %d\n" , hc->hub_addr);
++ IFX_PRINT(" port_addr: %d\n" , hc->port_addr);
++ #ifdef __EN_ISOC__
++ IFX_PRINT(" isoc_xact_pos: %d\n" , hc->isoc_xact_pos);
++ #endif
++ IFX_PRINT(" epqh: %p\n" , hc->epqh);
++ IFX_PRINT(" short_rw: %d\n" , hc->short_rw);
++ IFX_PRINT(" do_ping: %d\n" , hc->do_ping);
++ IFX_PRINT(" control_phase: %d\n" , hc->control_phase);
++ IFX_PRINT(" pkt_count_limit: %d\n", hc->epqh->pkt_count_limit);
++ IFX_PRINT(" start_pkt_count: %d\n" , hc->start_pkt_count);
++ }
++ IFX_PRINT("************************************************************\n");
++ IFX_PRINT("\n");
++ }
++#endif //__ENABLE_DUMP__
++
+diff --git a/drivers/usb/ifxhcd/ifxhcd.h b/drivers/usb/ifxhcd/ifxhcd.h
+new file mode 100644
+index 0000000..3a40851
+--- /dev/null
++++ b/drivers/usb/ifxhcd/ifxhcd.h
+@@ -0,0 +1,628 @@
++/*****************************************************************************
++ ** FILE NAME : ifxhcd.h
++ ** PROJECT : IFX USB sub-system V3
++ ** MODULES : IFX USB sub-system Host and Device driver
++ ** SRC VERSION : 1.0
++ ** DATE : 1/Jan/2009
++ ** AUTHOR : Chen, Howard
++ ** DESCRIPTION : This file contains the structures, constants, and interfaces for
++ ** the Host Contoller Driver (HCD).
++ **
++ ** The Host Controller Driver (HCD) is responsible for translating requests
++ ** from the USB Driver into the appropriate actions on the IFXUSB controller.
++ ** It isolates the USBD from the specifics of the controller by providing an
++ ** API to the USBD.
++ ** FUNCTIONS :
++ ** COMPILER : gcc
++ ** REFERENCE : Synopsys DWC-OTG Driver 2.7
++ ** COPYRIGHT :
++ ** Version Control Section **
++ ** $Author$
++ ** $Date$
++ ** $Revisions$
++ ** $Log$ Revision history
++*****************************************************************************/
++
++/*!
++ \defgroup IFXUSB_HCD HCD Interface
++ \ingroup IFXUSB_DRIVER_V3
++ \brief The Host Controller Driver (HCD) is responsible for translating requests
++ from the USB Driver into the appropriate actions on the IFXUSB controller.
++ It isolates the USBD from the specifics of the controller by providing an
++ API to the USBD.
++ */
++
++
++/*!
++ \file ifxhcd.h
++ \ingroup IFXUSB_DRIVER_V3
++ \brief This file contains the structures, constants, and interfaces for
++ the Host Contoller Driver (HCD).
++ */
++
++#if !defined(__IFXHCD_H__)
++#define __IFXHCD_H__
++
++#include <linux/list.h>
++#include <linux/usb.h>
++
++#ifdef __USE_TIMER_4_SOF__
++#include <linux/hrtimer.h>
++#endif
++#include <linux/usb/hcd.h>
++
++#include "ifxusb_cif.h"
++#include "ifxusb_plat.h"
++
++
++
++/*!
++ \addtogroup IFXUSB_HCD
++ */
++/*@{*/
++
++/* Phases for control transfers.*/
++typedef enum ifxhcd_control_phase {
++ IFXHCD_CONTROL_SETUP,
++ IFXHCD_CONTROL_DATA,
++ IFXHCD_CONTROL_STATUS
++} ifxhcd_control_phase_e;
++
++/* Reasons for halting a host channel. */
++typedef enum ifxhcd_halt_status
++{
++ HC_XFER_NO_HALT_STATUS, // Initial
++ HC_XFER_COMPLETE, // Xact complete without error, upward
++ HC_XFER_URB_COMPLETE, // Xfer complete without error, short upward
++ HC_XFER_STALL, // HC stopped abnormally, upward/downward
++ HC_XFER_XACT_ERR, // HC stopped abnormally, upward
++ HC_XFER_FRAME_OVERRUN, // HC stopped abnormally, upward
++ HC_XFER_BABBLE_ERR, // HC stopped abnormally, upward
++ HC_XFER_AHB_ERR, // HC stopped abnormally, upward
++ HC_XFER_DATA_TOGGLE_ERR,
++ HC_XFER_URB_DEQUEUE, // HC stopper manually, downward
++ HC_XFER_NAK // HC stopped by nak monitor, downward
++} ifxhcd_halt_status_e;
++
++struct ifxhcd_urbd;
++struct ifxhcd_hc ;
++struct ifxhcd_epqh ;
++struct ifxhcd_hcd;
++
++/*!
++ \brief A URB Descriptor (URBD) holds the state of a bulk, control,
++ interrupt, or isochronous transfer. A single URBD is created for each URB
++ (of one of these types) submitted to the HCD. The transfer associated with
++ a URBD may require one or multiple transactions.
++
++ A URBD is linked to a EP Queue Head, which is entered in either the
++ isoc, intr or non-periodic schedule for execution. When a URBD is chosen for
++ execution, some or all of its transactions may be executed. After
++ execution, the state of the URBD is updated. The URBD may be retired if all
++ its transactions are complete or if an error occurred. Otherwise, it
++ remains in the schedule so more transactions can be executed later.
++ */
++typedef struct ifxhcd_urbd {
++ struct list_head urbd_list_entry; // Hook for EPQH->urbd_list and ifxhcd->urbd_complete_list
++ struct urb *urb; /*!< URB for this transfer */
++ //struct urb {
++ // struct list_head urb_list;
++ // struct list_head anchor_list;
++ // struct usb_anchor * anchor;
++ // struct usb_device * dev;
++ // struct usb_host_endpoint * ep;
++ // unsigned int pipe;
++ // int status;
++ // unsigned int transfer_flags;
++ // void * transfer_buffer;
++ // dma_addr_t transfer_dma;
++ // u32 transfer_buffer_length;
++ // u32 actual_length;
++ // unsigned char * setup_packet;
++ // dma_addr_t setup_dma;
++ // int start_frame;
++ // int number_of_packets;
++ // int interval;
++ // int error_count;
++ // void * context;
++ // usb_complete_t complete;
++ // struct usb_iso_packet_descriptor iso_frame_desc[0];
++ //};
++ //urb_list For use by current owner of the URB.
++ //anchor_list membership in the list of an anchor
++ //anchor to anchor URBs to a common mooring
++ //dev Identifies the USB device to perform the request.
++ //ep Points to the endpoint's data structure. Will
++ // eventually replace pipe.
++ //pipe Holds endpoint number, direction, type, and more.
++ // Create these values with the eight macros available; u
++ // sb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is
++ // "ctrl", "bulk", "int" or "iso". For example
++ // usb_sndbulkpipe or usb_rcvintpipe. Endpoint numbers
++ // range from zero to fifteen. Note that "in" endpoint two
++ // is a different endpoint (and pipe) from "out" endpoint
++ // two. The current configuration controls the existence,
++ // type, and maximum packet size of any given endpoint.
++ //status This is read in non-iso completion functions to get
++ // the status of the particular request. ISO requests
++ // only use it to tell whether the URB was unlinked;
++ // detailed status for each frame is in the fields of
++ // the iso_frame-desc.
++ //transfer_flags A variety of flags may be used to affect how URB
++ // submission, unlinking, or operation are handled.
++ // Different kinds of URB can use different flags.
++ // URB_SHORT_NOT_OK
++ // URB_ISO_ASAP
++ // URB_NO_TRANSFER_DMA_MAP
++ // URB_NO_SETUP_DMA_MAP
++ // URB_NO_FSBR
++ // URB_ZERO_PACKET
++ // URB_NO_INTERRUPT
++ //transfer_buffer This identifies the buffer to (or from) which the I/O
++ // request will be performed (unless URB_NO_TRANSFER_DMA_MAP
++ // is set). This buffer must be suitable for DMA; allocate it
++ // with kmalloc or equivalent. For transfers to "in"
++ // endpoints, contents of this buffer will be modified. This
++ // buffer is used for the data stage of control transfers.
++ //transfer_dma When transfer_flags includes URB_NO_TRANSFER_DMA_MAP, the
++ // device driver is saying that it provided this DMA address,
++ // which the host controller driver should use in preference
++ // to the transfer_buffer.
++ //transfer_buffer_length How big is transfer_buffer. The transfer may be broken
++ // up into chunks according to the current maximum packet size
++ // for the endpoint, which is a function of the configuration
++ // and is encoded in the pipe. When the length is zero, neither
++ // transfer_buffer nor transfer_dma is used.
++ //actual_length This is read in non-iso completion functions, and it tells
++ // how many bytes (out of transfer_buffer_length) were transferred.
++ // It will normally be the same as requested, unless either an error
++ // was reported or a short read was performed. The URB_SHORT_NOT_OK
++ // transfer flag may be used to make such short reads be reported
++ // as errors.
++ //setup_packet Only used for control transfers, this points to eight bytes of
++ // setup data. Control transfers always start by sending this data
++ // to the device. Then transfer_buffer is read or written, if needed.
++ //setup_dma For control transfers with URB_NO_SETUP_DMA_MAP set, the device
++ // driver has provided this DMA address for the setup packet. The
++ // host controller driver should use this in preference to setup_packet.
++ //start_frame Returns the initial frame for isochronous transfers.
++ //number_of_packets Lists the number of ISO transfer buffers.
++ //interval Specifies the polling interval for interrupt or isochronous transfers.
++ // The units are frames (milliseconds) for for full and low speed devices,
++ // and microframes (1/8 millisecond) for highspeed ones.
++ //error_count Returns the number of ISO transfers that reported errors.
++ //context For use in completion functions. This normally points to request-specific
++ // driver context.
++ //complete Completion handler. This URB is passed as the parameter to the completion
++ // function. The completion function may then do what it likes with the URB,
++ // including resubmitting or freeing it.
++ //iso_frame_desc[0] Used to provide arrays of ISO transfer buffers and to collect the transfer
++ // status for each buffer.
++
++ struct ifxhcd_epqh *epqh;
++ // Actual data portion, not SETUP or STATUS in case of CTRL XFER
++ // DMA adjusted
++ uint8_t *setup_buff; /*!< Pointer to the entire transfer buffer. (CPU accessable)*/
++ uint8_t *xfer_buff; /*!< Pointer to the entire transfer buffer. (CPU accessable)*/
++ uint32_t xfer_len; /*!< Total number of bytes to transfer in this xfer. */
++ unsigned is_in :1;
++ unsigned is_active:1;
++
++ // For ALL XFER
++ uint8_t error_count; /*!< Holds the number of bus errors that have occurred for a transaction
++ within this transfer.
++ */
++ /*== AVM/BC 20101111 Needed for URB Complete List ==*/
++ int status;
++ // For ISOC XFER only
++ #ifdef __EN_ISOC__
++ int isoc_frame_index; /*!< Index of the next frame descriptor for an isochronous transfer. A
++ frame descriptor describes the buffer position and length of the
++ data to be transferred in the next scheduled (micro)frame of an
++ isochronous transfer. It also holds status for that transaction.
++ The frame index starts at 0.
++ */
++ // For SPLITed ISOC XFER only
++ uint8_t isoc_split_pos; /*!< Position of the ISOC split on full/low speed */
++ uint16_t isoc_split_offset;/*!< Position of the ISOC split in the buffer for the current frame */
++ #endif
++} ifxhcd_urbd_t;
++
++/*!
++ \brief A EP Queue Head (EPQH) holds the static characteristics of an endpoint and
++ maintains a list of transfers (URBDs) for that endpoint. A EPQH structure may
++ be entered in either the isoc, intr or non-periodic schedule.
++ */
++
++typedef struct ifxhcd_epqh {
++ struct list_head epqh_list_entry; // Hook for EP Queues
++ struct list_head urbd_list; /*!< List of URBDs for this EPQH. */
++ struct ifxhcd_hc *hc; /*!< Host channel currently processing transfers for this EPQH. */
++ struct ifxhcd_urbd *urbd; /*!< URBD currently assigned to a host channel for this EPQH. */
++ struct usb_host_endpoint *sysep;
++ uint8_t ep_type; /*!< Endpoint type. One of the following values:
++ - IFXUSB_EP_TYPE_CTRL
++ - IFXUSB_EP_TYPE_ISOC
++ - IFXUSB_EP_TYPE_BULK
++ - IFXUSB_EP_TYPE_INTR
++ */
++ uint16_t mps; /*!< wMaxPacketSize Field of Endpoint Descriptor. */
++
++ /* == AVM/WK 20100710 Fix - Use toggle of usbcore ==*/
++ /*uint8_t data_toggle;*/ /*!< Determines the PID of the next data packet
++ One of the following values:
++ - IFXHCD_HC_PID_DATA0
++ - IFXHCD_HC_PID_DATA1
++ */
++ uint8_t is_active;
++
++ uint8_t pkt_count_limit;
++ #ifdef __EPQD_DESTROY_TIMEOUT__
++ struct timer_list destroy_timer;
++ #endif
++
++ uint16_t wait_for_sof;
++ uint8_t need_split; /*!< Full/low speed endpoint on high-speed hub requires split. */
++ uint16_t interval; /*!< Interval between transfers in (micro)frames. (for INTR)*/
++
++ uint16_t period_counter; /*!< Interval between transfers in (micro)frames. */
++ uint8_t period_do;
++
++ uint8_t aligned_checked;
++
++ #if defined(__UNALIGNED_BUFFER_ADJ__)
++ uint8_t using_aligned_setup;
++ uint8_t *aligned_setup;
++ uint8_t using_aligned_buf;
++ uint8_t *aligned_buf;
++ unsigned aligned_buf_len : 19;
++ #endif
++
++ uint8_t *dump_buf;
++} ifxhcd_epqh_t;
++
++
++#if defined(__HC_XFER_TIMEOUT__)
++ struct ifxusb_core_if;
++ struct ifxhcd_hc;
++ typedef struct hc_xfer_info
++ {
++ struct ifxusb_core_if *core_if;
++ struct ifxhcd_hc *hc;
++ } hc_xfer_info_t;
++#endif //defined(__HC_XFER_TIMEOUT__)
++
++
++/*!
++ \brief Host channel descriptor. This structure represents the state of a single
++ host channel when acting in host mode. It contains the data items needed to
++ transfer packets to an endpoint via a host channel.
++ */
++typedef struct ifxhcd_hc
++{
++ struct list_head hc_list_entry ; // Hook to free hc
++ struct ifxhcd_epqh *epqh ; /*!< EP Queue Head for the transfer being processed by this channel. */
++
++ uint8_t hc_num ; /*!< Host channel number used for register address lookup */
++ uint8_t *xfer_buff ; /*!< Pointer to the entire transfer buffer. */
++ uint32_t xfer_count ; /*!< Number of bytes transferred so far. The offset of the begin of the buf */
++ uint32_t xfer_len ; /*!< Total number of bytes to transfer in this xfer. */
++ uint16_t start_pkt_count ; /*!< Packet count at start of transfer. Used to calculate the actual xfer size*/
++ ifxhcd_halt_status_e halt_status; /*!< Reason for halting the host channel. */
++
++ unsigned dev_addr : 7; /*!< Device to access */
++ unsigned ep_num : 4; /*!< EP to access */
++ unsigned is_in : 1; /*!< EP direction. 0: OUT, 1: IN */
++ unsigned speed : 2; /*!< EP speed. */
++ unsigned ep_type : 2; /*!< Endpoint type. */
++ unsigned mps :11; /*!< Max packet size in bytes */
++ unsigned data_pid_start : 2; /*!< PID for initial transaction. */
++ unsigned do_ping : 1; /*!< Set to 1 to indicate that a PING request should be issued on this
++ channel. If 0, process normally.
++ */
++
++ unsigned xfer_started : 1; /*!< Flag to indicate whether the transfer has been started. Set to 1 if
++ it has been started, 0 otherwise.
++ */
++ unsigned halting : 1; /*!< Set to 1 if the host channel has been halted, but the core is not
++ finished flushing queued requests. Otherwise 0.
++ */
++ unsigned short_rw : 1; /*!< When Tx, means termination needed.
++ When Rx, indicate Short Read */
++ /* Split settings for the host channel */
++ unsigned split : 2; /*!< Split: 0-Non Split, 1-SSPLIT, 2&3 CSPLIT */
++
++ /*== AVM/BC 20100701 - Workaround FullSpeed Interrupts with HiSpeed Hub ==*/
++ unsigned nyet_count;
++
++ /* nak monitor */
++ unsigned nak_retry_r : 16;
++ unsigned nak_retry : 16;
++ #define nak_retry_max 40000
++ unsigned nak_countdown : 8;
++ unsigned nak_countdown_r: 8;
++ #define nak_countdown_max 1
++
++ uint16_t wait_for_sof;
++ ifxhcd_control_phase_e control_phase; /*!< Current phase for control transfers (Setup, Data, or Status). */
++ uint32_t ssplit_out_xfer_count; /*!< How many bytes transferred during SSPLIT OUT */
++ #ifdef __DEBUG__
++ uint32_t start_hcchar_val;
++ #endif
++ #ifdef __HC_XFER_TIMEOUT__
++ hc_xfer_info_t hc_xfer_info;
++ struct timer_list hc_xfer_timer;
++ #endif
++ uint32_t hcchar;
++
++ /* Split settings for the host channel */
++ uint8_t hub_addr; /*!< Address of high speed hub */
++ uint8_t port_addr; /*!< Port of the low/full speed device */
++ #ifdef __EN_ISOC__
++ uint8_t isoc_xact_pos; /*!< Split transaction position */
++ #endif
++} ifxhcd_hc_t;
++
++
++/*!
++ \brief This structure holds the state of the HCD, including the non-periodic and
++ periodic schedules.
++ */
++typedef struct ifxhcd_hcd
++{
++ struct device *dev;
++ struct hc_driver hc_driver;
++ ifxusb_core_if_t core_if; /*!< Pointer to the core interface structure. */
++ struct usb_hcd *syshcd;
++
++ volatile union ifxhcd_internal_flags
++ {
++ uint32_t d32;
++ struct
++ {
++ unsigned port_connect_status_change : 1;
++ unsigned port_connect_status : 1;
++ unsigned port_reset_change : 1;
++ unsigned port_enable_change : 1;
++ unsigned port_suspend_change : 1;
++ unsigned port_over_current_change : 1;
++ unsigned reserved : 27;
++ } b;
++ } flags; /*!< Internal HCD Flags */
++
++ struct ifxhcd_hc ifxhc[MAX_EPS_CHANNELS]; /*!< Array of pointers to the host channel descriptors. Allows accessing
++ a host channel descriptor given the host channel number. This is
++ useful in interrupt handlers.
++ */
++ struct list_head free_hc_list; /*!< Free host channels in the controller. This is a list of ifxhcd_hc_t items. */
++ uint8_t *status_buf; /*!< Buffer to use for any data received during the status phase of a
++ control transfer. Normally no data is transferred during the status
++ phase. This buffer is used as a bit bucket.
++ */
++ #define IFXHCD_STATUS_BUF_SIZE 64
++
++ struct list_head epqh_np_active; // with URBD, with HC
++ struct list_head epqh_np_ready; // with URBD, No HC
++
++ struct list_head epqh_intr_active; // with URBD, with HC
++ struct list_head epqh_intr_ready; // with URBD, no pass, No HC
++
++ #ifdef __EN_ISOC__
++ struct list_head epqh_isoc_active; // with URBD, with HC
++ struct list_head epqh_isoc_ready; // with URBD, no pass, No HC
++ #endif
++
++ /*== AVM/BC 20101111 URB Complete List ==*/
++ struct list_head urbd_complete_list;
++
++ struct list_head epqh_stdby;
++
++ /* AVM/BC 20101111 flags removed */
++ //unsigned process_channels_in_use : 1;
++ //unsigned select_eps_in_use : 1;
++
++ struct tasklet_struct select_eps; /*!< Tasket to do a reset */
++ uint32_t lastframe;
++ spinlock_t lock;
++#ifdef __USE_TIMER_4_SOF__
++ struct hrtimer hr_timer;
++#endif
++} ifxhcd_hcd_t;
++
++/* Gets the ifxhcd_hcd from a struct usb_hcd */
++static inline ifxhcd_hcd_t *syshcd_to_ifxhcd(struct usb_hcd *syshcd)
++{
++ return (ifxhcd_hcd_t *)(syshcd->hcd_priv[0]);
++}
++
++/* Gets the struct usb_hcd that contains a ifxhcd_hcd_t. */
++static inline struct usb_hcd *ifxhcd_to_syshcd(ifxhcd_hcd_t *ifxhcd)
++{
++ return (struct usb_hcd *)(ifxhcd->syshcd);
++}
++
++/*! \brief HCD Create/Destroy Functions */
++/*@{*/
++ extern int ifxhcd_init (ifxhcd_hcd_t *_ifxhcd);
++ extern void ifxhcd_remove(ifxhcd_hcd_t *_ifxhcd);
++/*@}*/
++
++/*! \brief Linux HC Driver API Functions */
++/*@{*/
++extern int ifxhcd_start(struct usb_hcd *hcd);
++extern void ifxhcd_stop (struct usb_hcd *hcd);
++extern int ifxhcd_get_frame_number(struct usb_hcd *hcd);
++
++
++/*!
++ \brief This function does the setup for a data transfer for a host channel and
++ starts the transfer. May be called in either Slave mode or DMA mode. In
++ Slave mode, the caller must ensure that there is sufficient space in the
++ request queue and Tx Data FIFO.
++
++ For an OUT transfer in Slave mode, it loads a data packet into the
++ appropriate FIFO. If necessary, additional data packets will be loaded in
++ the Host ISR.
++
++ For an IN transfer in Slave mode, a data packet is requested. The data
++ packets are unloaded from the Rx FIFO in the Host ISR. If necessary,
++ additional data packets are requested in the Host ISR.
++
++ For a PING transfer in Slave mode, the Do Ping bit is set in the HCTSIZ
++ register along with a packet count of 1 and the channel is enabled. This
++ causes a single PING transaction to occur. Other fields in HCTSIZ are
++ simply set to 0 since no data transfer occurs in this case.
++
++ For a PING transfer in DMA mode, the HCTSIZ register is initialized with
++ all the information required to perform the subsequent data transfer. In
++ addition, the Do Ping bit is set in the HCTSIZ register. In this case, the
++ controller performs the entire PING protocol, then starts the data
++ transfer.
++
++ @param _ifxhc Information needed to initialize the host channel. The xfer_len
++ value may be reduced to accommodate the max widths of the XferSize and
++ PktCnt fields in the HCTSIZn register. The multi_count value may be changed
++ to reflect the final xfer_len value.
++ */
++extern void ifxhcd_hc_start(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc);
++
++//extern int ifxhcd_urb_enqueue(struct usb_hcd *_syshcd, struct usb_host_endpoint *_sysep, struct urb *_urb, gfp_t mem_flags);
++//extern int ifxhcd_urb_dequeue(struct usb_hcd *_syshcd, struct urb *_urb);
++extern irqreturn_t ifxhcd_irq(struct usb_hcd *_syshcd);
++int ifxhcd_urb_enqueue( struct usb_hcd *_syshcd,
++ /*--- struct usb_host_endpoint *_sysep, Parameter im 2.6.28 entfallen ---*/
++ struct urb *_urb,
++ gfp_t _mem_flags);
++int ifxhcd_urb_dequeue( struct usb_hcd *_syshcd,
++ struct urb *_urb, int status /* Parameter neu in 2.6.28 */);
++
++extern void ifxhcd_endpoint_disable(struct usb_hcd *_syshcd, struct usb_host_endpoint *_sysep);
++
++extern int ifxhcd_hub_status_data(struct usb_hcd *_syshcd, char *_buf);
++extern int ifxhcd_hub_control( struct usb_hcd *_syshcd,
++ u16 _typeReq,
++ u16 _wValue,
++ u16 _wIndex,
++ char *_buf,
++ u16 _wLength);
++
++/*@}*/
++
++/*! \brief Transaction Execution Functions */
++/*@{*/
++extern void ifxhcd_complete_urb (ifxhcd_hcd_t *_ifxhcd, ifxhcd_urbd_t *_urbd, int _status);
++
++/*@}*/
++
++/*! \brief Deferred Transaction Execution Functions */
++/*@{*/
++
++/*== AVM/BC 20101111 URB Complete List ==*/
++extern void defer_ifxhcd_complete_urb (ifxhcd_hcd_t *_ifxhcd, ifxhcd_urbd_t *_urbd, int _status);
++
++/*!
++ \brief Clears the transfer state for a host channel. This function is normally
++ called after a transfer is done and the host channel is being released.
++ */
++extern void ifxhcd_hc_cleanup(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc);
++
++/*!
++ \brief Attempts to halt a host channel. This function should only be called in
++ Slave mode or to abort a transfer in either Slave mode or DMA mode. Under
++ normal circumstances in DMA mode, the controller halts the channel when the
++ transfer is complete or a condition occurs that requires application
++ intervention.
++
++ In slave mode, checks for a free request queue entry, then sets the Channel
++ Enable and Channel Disable bits of the Host Channel Characteristics
++ register of the specified channel to intiate the halt. If there is no free
++ request queue entry, sets only the Channel Disable bit of the HCCHARn
++ register to flush requests for this channel. In the latter case, sets a
++ flag to indicate that the host channel needs to be halted when a request
++ queue slot is open.
++
++ In DMA mode, always sets the Channel Enable and Channel Disable bits of the
++ HCCHARn register. The controller ensures there is space in the request
++ queue before submitting the halt request.
++
++ Some time may elapse before the core flushes any posted requests for this
++ host channel and halts. The Channel Halted interrupt handler completes the
++ deactivation of the host channel.
++ */
++extern void ifxhcd_hc_halt(ifxusb_core_if_t *_core_if,
++ ifxhcd_hc_t *_ifxhc,
++ ifxhcd_halt_status_e _halt_status);
++
++/*!
++ \brief Prepares a host channel for transferring packets to/from a specific
++ endpoint. The HCCHARn register is set up with the characteristics specified
++ in _ifxhc. Host channel interrupts that may need to be serviced while this
++ transfer is in progress are enabled.
++ */
++extern void ifxhcd_hc_init(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc);
++
++/*!
++ \brief This function is called to handle the disconnection of host port.
++ */
++int32_t ifxhcd_disconnect(ifxhcd_hcd_t *_ifxhcd);
++/*@}*/
++
++/*! \brief Interrupt Handler Functions */
++/*@{*/
++extern irqreturn_t ifxhcd_oc_irq(int _irq, void *_dev);
++
++extern int32_t ifxhcd_handle_oc_intr(ifxhcd_hcd_t *_ifxhcd);
++extern int32_t ifxhcd_handle_intr (ifxhcd_hcd_t *_ifxhcd);
++/*@}*/
++
++
++/*! \brief Schedule Queue Functions */
++/*@{*/
++extern ifxhcd_epqh_t *ifxhcd_epqh_create (ifxhcd_hcd_t *_ifxhcd, struct urb *_urb);
++extern void ifxhcd_epqh_free ( ifxhcd_epqh_t *_epqh);
++extern void select_eps (ifxhcd_hcd_t *_ifxhcd);
++extern void process_channels(ifxhcd_hcd_t *_ifxhcd);
++extern void process_channels_sub(ifxhcd_hcd_t *_ifxhcd);
++extern void complete_channel(ifxhcd_hcd_t *_ifxhcd, ifxhcd_hc_t *_ifxhc, ifxhcd_urbd_t *_urbd);
++extern void ifxhcd_epqh_ready(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh);
++extern void ifxhcd_epqh_active(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh);
++extern void ifxhcd_epqh_idle(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh);
++extern void ifxhcd_epqh_idle_periodic(ifxhcd_epqh_t *_epqh);
++extern int ifxhcd_urbd_create (ifxhcd_hcd_t *_ifxhcd,struct urb *_urb);
++/*@}*/
++
++/*! \brief Gets the usb_host_endpoint associated with an URB. */
++static inline struct usb_host_endpoint *ifxhcd_urb_to_endpoint(struct urb *_urb)
++{
++ struct usb_device *dev = _urb->dev;
++ int ep_num = usb_pipeendpoint(_urb->pipe);
++
++ return (usb_pipein(_urb->pipe))?(dev->ep_in[ep_num]):(dev->ep_out[ep_num]);
++}
++
++/*!
++ * \brief Gets the endpoint number from a _bEndpointAddress argument. The endpoint is
++ * qualified with its direction (possible 32 endpoints per device).
++ */
++#define ifxhcd_ep_addr_to_endpoint(_bEndpointAddress_) ((_bEndpointAddress_ & USB_ENDPOINT_NUMBER_MASK) | \
++ ((_bEndpointAddress_ & USB_DIR_IN) != 0) << 4)
++
++
++/* AVM/WK: not needed?
++
++extern struct usb_device *usb_alloc_dev (struct usb_device *parent, struct usb_bus *, unsigned port);
++extern int usb_add_hcd (struct usb_hcd *syshcd, unsigned int irqnum, unsigned long irqflags);
++extern void usb_remove_hcd (struct usb_hcd *syshcd);
++extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, struct device *dev, char *bus_name);
++extern void usb_hcd_giveback_urb (struct usb_hcd *syshcd, struct urb *urb);
++extern void usb_put_hcd (struct usb_hcd *syshcd);
++extern long usb_calc_bus_time (int speed, int is_input, int isoc, int bytecount);
++
++*/
++/** Internal Functions */
++void ifxhcd_dump_state(ifxhcd_hcd_t *_ifxhcd);
++extern char *syserr(int errno);
++
++/*@}*//*IFXUSB_HCD*/
++
++#endif // __IFXHCD_H__
+diff --git a/drivers/usb/ifxhcd/ifxhcd_es.c b/drivers/usb/ifxhcd/ifxhcd_es.c
+new file mode 100644
+index 0000000..ef9e8c0
+--- /dev/null
++++ b/drivers/usb/ifxhcd/ifxhcd_es.c
+@@ -0,0 +1,549 @@
++/*****************************************************************************
++ ** FILE NAME : ifxhcd_es.c
++ ** PROJECT : IFX USB sub-system V3
++ ** MODULES : IFX USB sub-system Host and Device driver
++ ** SRC VERSION : 1.0
++ ** DATE : 1/Jan/2009
++ ** AUTHOR : Chen, Howard
++ ** DESCRIPTION : The file contain function to enable host mode USB-IF Electrical Test function.
++ *****************************************************************************/
++
++/*!
++ \file ifxhcd_es.c
++ \ingroup IFXUSB_DRIVER_V3
++ \brief The file contain function to enable host mode USB-IF Electrical Test function.
++*/
++
++#include <linux/version.h>
++#include "ifxusb_version.h"
++
++#include <linux/kernel.h>
++
++#include <linux/errno.h>
++
++#include <linux/dma-mapping.h>
++
++#include "ifxusb_plat.h"
++#include "ifxusb_regs.h"
++#include "ifxusb_cif.h"
++#include "ifxhcd.h"
++
++
++#ifdef __WITH_HS_ELECT_TST__
++ /*
++ * Quick and dirty hack to implement the HS Electrical Test
++ * SINGLE_STEP_GET_DEVICE_DESCRIPTOR feature.
++ *
++ * This code was copied from our userspace app "hset". It sends a
++ * Get Device Descriptor control sequence in two parts, first the
++ * Setup packet by itself, followed some time later by the In and
++ * Ack packets. Rather than trying to figure out how to add this
++ * functionality to the normal driver code, we just hijack the
++ * hardware, using these two function to drive the hardware
++ * directly.
++ */
++
++
++ void do_setup(ifxusb_core_if_t *_core_if)
++ {
++
++ ifxusb_core_global_regs_t *global_regs = _core_if->core_global_regs;
++ ifxusb_host_global_regs_t *hc_global_regs = _core_if->host_global_regs;
++ ifxusb_hc_regs_t *hc_regs = _core_if->hc_regs[0];
++ uint32_t *data_fifo = _core_if->data_fifo[0];
++
++ gint_data_t gintsts;
++ hctsiz_data_t hctsiz;
++ hcchar_data_t hcchar;
++ haint_data_t haint;
++ hcint_data_t hcint;
++
++
++ /* Enable HAINTs */
++ ifxusb_wreg(&hc_global_regs->haintmsk, 0x0001);
++
++ /* Enable HCINTs */
++ ifxusb_wreg(&hc_regs->hcintmsk, 0x04a3);
++
++ /* Read GINTSTS */
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
++
++ /* Read HAINT */
++ haint.d32 = ifxusb_rreg(&hc_global_regs->haint);
++ //fprintf(stderr, "HAINT: %08x\n", haint.d32);
++
++ /* Read HCINT */
++ hcint.d32 = ifxusb_rreg(&hc_regs->hcint);
++ //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
++
++ /* Read HCCHAR */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
++
++ /* Clear HCINT */
++ ifxusb_wreg(&hc_regs->hcint, hcint.d32);
++
++ /* Clear HAINT */
++ ifxusb_wreg(&hc_global_regs->haint, haint.d32);
++
++ /* Clear GINTSTS */
++ ifxusb_wreg(&global_regs->gintsts, gintsts.d32);
++
++ /* Read GINTSTS */
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
++
++ /*
++ * Send Setup packet (Get Device Descriptor)
++ */
++
++ /* Make sure channel is disabled */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ if (hcchar.b.chen) {
++ //fprintf(stderr, "Channel already enabled 1, HCCHAR = %08x\n", hcchar.d32);
++ hcchar.b.chdis = 1;
++ // hcchar.b.chen = 1;
++ ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
++ //sleep(1);
++ mdelay(1000);
++
++ /* Read GINTSTS */
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
++
++ /* Read HAINT */
++ haint.d32 = ifxusb_rreg(&hc_global_regs->haint);
++ //fprintf(stderr, "HAINT: %08x\n", haint.d32);
++
++ /* Read HCINT */
++ hcint.d32 = ifxusb_rreg(&hc_regs->hcint);
++ //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
++
++ /* Read HCCHAR */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
++
++ /* Clear HCINT */
++ ifxusb_wreg(&hc_regs->hcint, hcint.d32);
++
++ /* Clear HAINT */
++ ifxusb_wreg(&hc_global_regs->haint, haint.d32);
++
++ /* Clear GINTSTS */
++ ifxusb_wreg(&global_regs->gintsts, gintsts.d32);
++
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ //if (hcchar.b.chen) {
++ // fprintf(stderr, "** Channel _still_ enabled 1, HCCHAR = %08x **\n", hcchar.d32);
++ //}
++ }
++
++ /* Set HCTSIZ */
++ hctsiz.d32 = 0;
++ hctsiz.b.xfersize = 8;
++ hctsiz.b.pktcnt = 1;
++ hctsiz.b.pid = IFXUSB_HC_PID_SETUP;
++ ifxusb_wreg(&hc_regs->hctsiz, hctsiz.d32);
++
++ /* Set HCCHAR */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ hcchar.b.eptype = IFXUSB_EP_TYPE_CTRL;
++ hcchar.b.epdir = 0;
++ hcchar.b.epnum = 0;
++ hcchar.b.mps = 8;
++ hcchar.b.chen = 1;
++ ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
++
++ /* Fill FIFO with Setup data for Get Device Descriptor */
++ ifxusb_wreg(data_fifo++, 0x01000680);
++ ifxusb_wreg(data_fifo++, 0x00080000);
++
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "Waiting for HCINTR intr 1, GINTSTS = %08x\n", gintsts.d32);
++
++ /* Wait for host channel interrupt */
++ do {
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ } while (gintsts.b.hcintr == 0);
++
++ //fprintf(stderr, "Got HCINTR intr 1, GINTSTS = %08x\n", gintsts.d32);
++
++ /* Disable HCINTs */
++ ifxusb_wreg(&hc_regs->hcintmsk, 0x0000);
++
++ /* Disable HAINTs */
++ ifxusb_wreg(&hc_global_regs->haintmsk, 0x0000);
++
++ /* Read HAINT */
++ haint.d32 = ifxusb_rreg(&hc_global_regs->haint);
++ //fprintf(stderr, "HAINT: %08x\n", haint.d32);
++
++ /* Read HCINT */
++ hcint.d32 = ifxusb_rreg(&hc_regs->hcint);
++ //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
++
++ /* Read HCCHAR */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
++
++ /* Clear HCINT */
++ ifxusb_wreg(&hc_regs->hcint, hcint.d32);
++
++ /* Clear HAINT */
++ ifxusb_wreg(&hc_global_regs->haint, haint.d32);
++
++ /* Clear GINTSTS */
++ ifxusb_wreg(&global_regs->gintsts, gintsts.d32);
++
++ /* Read GINTSTS */
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
++ }
++
++ void do_in_ack(ifxusb_core_if_t *_core_if)
++ {
++
++ ifxusb_core_global_regs_t *global_regs = _core_if->core_global_regs;
++ ifxusb_host_global_regs_t *hc_global_regs = _core_if->host_global_regs;
++ ifxusb_hc_regs_t *hc_regs = _core_if->hc_regs[0];
++ uint32_t *data_fifo = _core_if->data_fifo[0];
++
++ gint_data_t gintsts;
++ hctsiz_data_t hctsiz;
++ hcchar_data_t hcchar;
++ haint_data_t haint;
++ hcint_data_t hcint;
++ grxsts_data_t grxsts;
++
++ /* Enable HAINTs */
++ ifxusb_wreg(&hc_global_regs->haintmsk, 0x0001);
++
++ /* Enable HCINTs */
++ ifxusb_wreg(&hc_regs->hcintmsk, 0x04a3);
++
++ /* Read GINTSTS */
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
++
++ /* Read HAINT */
++ haint.d32 = ifxusb_rreg(&hc_global_regs->haint);
++ //fprintf(stderr, "HAINT: %08x\n", haint.d32);
++
++ /* Read HCINT */
++ hcint.d32 = ifxusb_rreg(&hc_regs->hcint);
++ //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
++
++ /* Read HCCHAR */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
++
++ /* Clear HCINT */
++ ifxusb_wreg(&hc_regs->hcint, hcint.d32);
++
++ /* Clear HAINT */
++ ifxusb_wreg(&hc_global_regs->haint, haint.d32);
++
++ /* Clear GINTSTS */
++ ifxusb_wreg(&global_regs->gintsts, gintsts.d32);
++
++ /* Read GINTSTS */
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
++
++ /*
++ * Receive Control In packet
++ */
++
++ /* Make sure channel is disabled */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ if (hcchar.b.chen) {
++ //fprintf(stderr, "Channel already enabled 2, HCCHAR = %08x\n", hcchar.d32);
++ hcchar.b.chdis = 1;
++ hcchar.b.chen = 1;
++ ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
++ //sleep(1);
++ mdelay(1000);
++
++ /* Read GINTSTS */
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
++
++ /* Read HAINT */
++ haint.d32 = ifxusb_rreg(&hc_global_regs->haint);
++ //fprintf(stderr, "HAINT: %08x\n", haint.d32);
++
++ /* Read HCINT */
++ hcint.d32 = ifxusb_rreg(&hc_regs->hcint);
++ //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
++
++ /* Read HCCHAR */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
++
++ /* Clear HCINT */
++ ifxusb_wreg(&hc_regs->hcint, hcint.d32);
++
++ /* Clear HAINT */
++ ifxusb_wreg(&hc_global_regs->haint, haint.d32);
++
++ /* Clear GINTSTS */
++ ifxusb_wreg(&global_regs->gintsts, gintsts.d32);
++
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ //if (hcchar.b.chen) {
++ // fprintf(stderr, "** Channel _still_ enabled 2, HCCHAR = %08x **\n", hcchar.d32);
++ //}
++ }
++
++ /* Set HCTSIZ */
++ hctsiz.d32 = 0;
++ hctsiz.b.xfersize = 8;
++ hctsiz.b.pktcnt = 1;
++ hctsiz.b.pid = IFXUSB_HC_PID_DATA1;
++ ifxusb_wreg(&hc_regs->hctsiz, hctsiz.d32);
++
++ /* Set HCCHAR */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ hcchar.b.eptype = IFXUSB_EP_TYPE_CTRL;
++ hcchar.b.epdir = 1;
++ hcchar.b.epnum = 0;
++ hcchar.b.mps = 8;
++ hcchar.b.chen = 1;
++ ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
++
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "Waiting for RXSTSQLVL intr 1, GINTSTS = %08x\n", gintsts.d32);
++
++ /* Wait for receive status queue interrupt */
++ do {
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ } while (gintsts.b.rxstsqlvl == 0);
++
++ //fprintf(stderr, "Got RXSTSQLVL intr 1, GINTSTS = %08x\n", gintsts.d32);
++
++ /* Read RXSTS */
++ grxsts.d32 = ifxusb_rreg(&global_regs->grxstsp);
++ //fprintf(stderr, "GRXSTS: %08x\n", grxsts.d32);
++
++ /* Clear RXSTSQLVL in GINTSTS */
++ gintsts.d32 = 0;
++ gintsts.b.rxstsqlvl = 1;
++ ifxusb_wreg(&global_regs->gintsts, gintsts.d32);
++
++ switch (grxsts.hb.pktsts) {
++ case IFXUSB_HSTS_DATA_UPDT:
++ /* Read the data into the host buffer */
++ if (grxsts.hb.bcnt > 0) {
++ int i;
++ int word_count = (grxsts.hb.bcnt + 3) / 4;
++
++ for (i = 0; i < word_count; i++) {
++ (void)ifxusb_rreg(data_fifo++);
++ }
++ }
++
++ //fprintf(stderr, "Received %u bytes\n", (unsigned)grxsts.hb.bcnt);
++ break;
++
++ default:
++ //fprintf(stderr, "** Unexpected GRXSTS packet status 1 **\n");
++ break;
++ }
++
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "Waiting for RXSTSQLVL intr 2, GINTSTS = %08x\n", gintsts.d32);
++
++ /* Wait for receive status queue interrupt */
++ do {
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ } while (gintsts.b.rxstsqlvl == 0);
++
++ //fprintf(stderr, "Got RXSTSQLVL intr 2, GINTSTS = %08x\n", gintsts.d32);
++
++ /* Read RXSTS */
++ grxsts.d32 = ifxusb_rreg(&global_regs->grxstsp);
++ //fprintf(stderr, "GRXSTS: %08x\n", grxsts.d32);
++
++ /* Clear RXSTSQLVL in GINTSTS */
++ gintsts.d32 = 0;
++ gintsts.b.rxstsqlvl = 1;
++ ifxusb_wreg(&global_regs->gintsts, gintsts.d32);
++
++ switch (grxsts.hb.pktsts) {
++ case IFXUSB_HSTS_XFER_COMP:
++ break;
++
++ default:
++ //fprintf(stderr, "** Unexpected GRXSTS packet status 2 **\n");
++ break;
++ }
++
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "Waiting for HCINTR intr 2, GINTSTS = %08x\n", gintsts.d32);
++
++ /* Wait for host channel interrupt */
++ do {
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ } while (gintsts.b.hcintr == 0);
++
++ //fprintf(stderr, "Got HCINTR intr 2, GINTSTS = %08x\n", gintsts.d32);
++
++ /* Read HAINT */
++ haint.d32 = ifxusb_rreg(&hc_global_regs->haint);
++ //fprintf(stderr, "HAINT: %08x\n", haint.d32);
++
++ /* Read HCINT */
++ hcint.d32 = ifxusb_rreg(&hc_regs->hcint);
++ //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
++
++ /* Read HCCHAR */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
++
++ /* Clear HCINT */
++ ifxusb_wreg(&hc_regs->hcint, hcint.d32);
++
++ /* Clear HAINT */
++ ifxusb_wreg(&hc_global_regs->haint, haint.d32);
++
++ /* Clear GINTSTS */
++ ifxusb_wreg(&global_regs->gintsts, gintsts.d32);
++
++ /* Read GINTSTS */
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
++
++ // usleep(100000);
++ // mdelay(100);
++ mdelay(1);
++
++ /*
++ * Send handshake packet
++ */
++
++ /* Read HAINT */
++ haint.d32 = ifxusb_rreg(&hc_global_regs->haint);
++ //fprintf(stderr, "HAINT: %08x\n", haint.d32);
++
++ /* Read HCINT */
++ hcint.d32 = ifxusb_rreg(&hc_regs->hcint);
++ //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
++
++ /* Read HCCHAR */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
++
++ /* Clear HCINT */
++ ifxusb_wreg(&hc_regs->hcint, hcint.d32);
++
++ /* Clear HAINT */
++ ifxusb_wreg(&hc_global_regs->haint, haint.d32);
++
++ /* Clear GINTSTS */
++ ifxusb_wreg(&global_regs->gintsts, gintsts.d32);
++
++ /* Read GINTSTS */
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
++
++ /* Make sure channel is disabled */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ if (hcchar.b.chen) {
++ //fprintf(stderr, "Channel already enabled 3, HCCHAR = %08x\n", hcchar.d32);
++ hcchar.b.chdis = 1;
++ hcchar.b.chen = 1;
++ ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
++ //sleep(1);
++ mdelay(1000);
++
++ /* Read GINTSTS */
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
++
++ /* Read HAINT */
++ haint.d32 = ifxusb_rreg(&hc_global_regs->haint);
++ //fprintf(stderr, "HAINT: %08x\n", haint.d32);
++
++ /* Read HCINT */
++ hcint.d32 = ifxusb_rreg(&hc_regs->hcint);
++ //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
++
++ /* Read HCCHAR */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
++
++ /* Clear HCINT */
++ ifxusb_wreg(&hc_regs->hcint, hcint.d32);
++
++ /* Clear HAINT */
++ ifxusb_wreg(&hc_global_regs->haint, haint.d32);
++
++ /* Clear GINTSTS */
++ ifxusb_wreg(&global_regs->gintsts, gintsts.d32);
++
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ //if (hcchar.b.chen) {
++ // fprintf(stderr, "** Channel _still_ enabled 3, HCCHAR = %08x **\n", hcchar.d32);
++ //}
++ }
++
++ /* Set HCTSIZ */
++ hctsiz.d32 = 0;
++ hctsiz.b.xfersize = 0;
++ hctsiz.b.pktcnt = 1;
++ hctsiz.b.pid = IFXUSB_HC_PID_DATA1;
++ ifxusb_wreg(&hc_regs->hctsiz, hctsiz.d32);
++
++ /* Set HCCHAR */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ hcchar.b.eptype = IFXUSB_EP_TYPE_CTRL;
++ hcchar.b.epdir = 0;
++ hcchar.b.epnum = 0;
++ hcchar.b.mps = 8;
++ hcchar.b.chen = 1;
++ ifxusb_wreg(&hc_regs->hcchar, hcchar.d32);
++
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "Waiting for HCINTR intr 3, GINTSTS = %08x\n", gintsts.d32);
++
++ /* Wait for host channel interrupt */
++ do {
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ } while (gintsts.b.hcintr == 0);
++
++ //fprintf(stderr, "Got HCINTR intr 3, GINTSTS = %08x\n", gintsts.d32);
++
++ /* Disable HCINTs */
++ ifxusb_wreg(&hc_regs->hcintmsk, 0x0000);
++
++ /* Disable HAINTs */
++ ifxusb_wreg(&hc_global_regs->haintmsk, 0x0000);
++
++ /* Read HAINT */
++ haint.d32 = ifxusb_rreg(&hc_global_regs->haint);
++ //fprintf(stderr, "HAINT: %08x\n", haint.d32);
++
++ /* Read HCINT */
++ hcint.d32 = ifxusb_rreg(&hc_regs->hcint);
++ //fprintf(stderr, "HCINT: %08x\n", hcint.d32);
++
++ /* Read HCCHAR */
++ hcchar.d32 = ifxusb_rreg(&hc_regs->hcchar);
++ //fprintf(stderr, "HCCHAR: %08x\n", hcchar.d32);
++
++ /* Clear HCINT */
++ ifxusb_wreg(&hc_regs->hcint, hcint.d32);
++
++ /* Clear HAINT */
++ ifxusb_wreg(&hc_global_regs->haint, haint.d32);
++
++ /* Clear GINTSTS */
++ ifxusb_wreg(&global_regs->gintsts, gintsts.d32);
++
++ /* Read GINTSTS */
++ gintsts.d32 = ifxusb_rreg(&global_regs->gintsts);
++ //fprintf(stderr, "GINTSTS: %08x\n", gintsts.d32);
++ }
++#endif //__WITH_HS_ELECT_TST__
++
+diff --git a/drivers/usb/ifxhcd/ifxhcd_intr.c b/drivers/usb/ifxhcd/ifxhcd_intr.c
+new file mode 100644
+index 0000000..76fe602
+--- /dev/null
++++ b/drivers/usb/ifxhcd/ifxhcd_intr.c
+@@ -0,0 +1,3742 @@
++/*****************************************************************************
++ ** FILE NAME : ifxhcd_intr.c
++ ** PROJECT : IFX USB sub-system V3
++ ** MODULES : IFX USB sub-system Host and Device driver
++ ** SRC VERSION : 1.0
++ ** DATE : 1/Jan/2009
++ ** AUTHOR : Chen, Howard
++ ** DESCRIPTION : This file contains the implementation of the HCD Interrupt handlers.
++ *****************************************************************************/
++
++/*!
++ \file ifxhcd_intr.c
++ \ingroup IFXUSB_DRIVER_V3
++ \brief This file contains the implementation of the HCD Interrupt handlers.
++*/
++
++
++#include <linux/version.h>
++#include "ifxusb_version.h"
++
++#include "ifxusb_plat.h"
++#include "ifxusb_regs.h"
++#include "ifxusb_cif.h"
++
++#include "ifxhcd.h"
++
++/* AVM/WK 20100520*/
++#ifdef __EN_ISOC__
++#error AVM/WK: CONFIG_USB_HOST_IFX_WITH_ISO currently not supported!
++#endif
++
++/* Macro used to clear one channel interrupt */
++#define clear_hc_int(_hc_regs_,_intr_) \
++ do { \
++ hcint_data_t hcint_clear = {.d32 = 0}; \
++ hcint_clear.b._intr_ = 1; \
++ ifxusb_wreg(&((_hc_regs_)->hcint), hcint_clear.d32); \
++ } while (0)
++
++/*
++ * Macro used to disable one channel interrupt. Channel interrupts are
++ * disabled when the channel is halted or released by the interrupt handler.
++ * There is no need to handle further interrupts of that type until the
++ * channel is re-assigned. In fact, subsequent handling may cause crashes
++ * because the channel structures are cleaned up when the channel is released.
++ */
++#define disable_hc_int(_hc_regs_,_intr_) \
++ do { \
++ hcint_data_t hcintmsk = {.d32 = 0}; \
++ hcintmsk.b._intr_ = 1; \
++ ifxusb_mreg(&((_hc_regs_)->hcintmsk), hcintmsk.d32, 0); \
++ } while (0)
++
++#define enable_hc_int(_hc_regs_,_intr_) \
++ do { \
++ hcint_data_t hcintmsk = {.d32 = 0}; \
++ hcintmsk.b._intr_ = 1; \
++ ifxusb_mreg(&((_hc_regs_)->hcintmsk),0, hcintmsk.d32); \
++ } while (0)
++
++/*
++ * Save the starting data toggle for the next transfer. The data toggle is
++ * saved in the QH for non-control transfers and it's saved in the QTD for
++ * control transfers.
++ */
++uint8_t read_data_toggle(ifxusb_hc_regs_t *_hc_regs)
++{
++ hctsiz_data_t hctsiz;
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++ return(hctsiz.b.pid);
++}
++
++
++static void release_channel_dump(ifxhcd_hc_t *ifxhc,
++ struct urb *urb,
++ ifxhcd_epqh_t *epqh,
++ ifxhcd_urbd_t *urbd,
++ ifxhcd_halt_status_e halt_status)
++{
++ #ifdef __DEBUG__
++ printk(KERN_INFO);
++ switch (halt_status)
++ {
++ case HC_XFER_NO_HALT_STATUS:
++ printk("HC_XFER_NO_HALT_STATUS");break;
++ case HC_XFER_URB_COMPLETE:
++ printk("HC_XFER_URB_COMPLETE");break;
++ case HC_XFER_AHB_ERR:
++ printk("HC_XFER_AHB_ERR");break;
++ case HC_XFER_STALL:
++ printk("HC_XFER_STALL");break;
++ case HC_XFER_BABBLE_ERR:
++ printk("HC_XFER_BABBLE_ERR");break;
++ case HC_XFER_XACT_ERR:
++ printk("HC_XFER_XACT_ERR");break;
++ case HC_XFER_URB_DEQUEUE:
++ printk("HC_XFER_URB_DEQUEUE");break;
++ case HC_XFER_FRAME_OVERRUN:
++ printk("HC_XFER_FRAME_OVERRUN");break;
++ case HC_XFER_DATA_TOGGLE_ERR:
++ printk("HC_XFER_DATA_TOGGLE_ERR");break;
++ case HC_XFER_NAK:
++ printk("HC_XFER_NAK");break;
++ case HC_XFER_COMPLETE:
++ printk("HC_XFER_COMPLETE");break;
++ default:
++ printk("KNOWN");break;
++ }
++ if(ifxhc)
++ printk("Ch %d %s%s S%d " , ifxhc->hc_num
++ ,(ifxhc->ep_type == IFXUSB_EP_TYPE_CTRL)?"CTRL-":
++ ((ifxhc->ep_type == IFXUSB_EP_TYPE_BULK)?"BULK-":
++ ((ifxhc->ep_type == IFXUSB_EP_TYPE_INTR)?"INTR-":
++ ((ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)?"ISOC-":"????"
++ )
++ )
++ )
++ ,(ifxhc->is_in)?"IN":"OUT"
++ ,(ifxhc->split)
++ );
++ else
++ printk(" [NULL HC] ");
++ printk("urb=%p epqh=%p urbd=%p\n",urb,epqh,urbd);
++
++ if(urb)
++ {
++ printk(KERN_INFO " Device address: %d\n", usb_pipedevice(urb->pipe));
++ printk(KERN_INFO " Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe),
++ (usb_pipein(urb->pipe) ? "IN" : "OUT"));
++ printk(KERN_INFO " Endpoint type: %s\n",
++ ({char *pipetype;
++ switch (usb_pipetype(urb->pipe)) {
++ case PIPE_CONTROL: pipetype = "CTRL"; break;
++ case PIPE_BULK: pipetype = "BULK"; break;
++ case PIPE_INTERRUPT: pipetype = "INTR"; break;
++ case PIPE_ISOCHRONOUS: pipetype = "ISOC"; break;
++ default: pipetype = "????"; break;
++ }; pipetype;}));
++ printk(KERN_INFO " Speed: %s\n",
++ ({char *speed;
++ switch (urb->dev->speed) {
++ case USB_SPEED_HIGH: speed = "HS"; break;
++ case USB_SPEED_FULL: speed = "FS"; break;
++ case USB_SPEED_LOW: speed = "LS"; break;
++ default: speed = "????"; break;
++ }; speed;}));
++ printk(KERN_INFO " Max packet size: %d\n",
++ usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)));
++ printk(KERN_INFO " Data buffer length: %d\n", urb->transfer_buffer_length);
++ printk(KERN_INFO " Transfer buffer: %p, Transfer DMA: %p\n",
++ urb->transfer_buffer, (void *)urb->transfer_dma);
++ printk(KERN_INFO " Setup buffer: %p, Setup DMA: %p\n",
++ urb->setup_packet, (void *)urb->setup_dma);
++ printk(KERN_INFO " Interval: %d\n", urb->interval);
++ switch (urb->status)
++ {
++ case HC_XFER_NO_HALT_STATUS:
++ printk(KERN_INFO " STATUS:HC_XFER_NO_HALT_STATUS\n");break;
++ case HC_XFER_URB_COMPLETE:
++ printk(KERN_INFO " STATUS:HC_XFER_URB_COMPLETE\n");break;
++ case HC_XFER_AHB_ERR:
++ printk(KERN_INFO " STATUS:HC_XFER_AHB_ERR\n");break;
++ case HC_XFER_STALL:
++ printk(KERN_INFO " STATUS:HC_XFER_STALL\n");break;
++ case HC_XFER_BABBLE_ERR:
++ printk(KERN_INFO " STATUS:HC_XFER_BABBLE_ERR\n");break;
++ case HC_XFER_XACT_ERR:
++ printk(KERN_INFO " STATUS:HC_XFER_XACT_ERR\n");break;
++ case HC_XFER_URB_DEQUEUE:
++ printk(KERN_INFO " STATUS:HC_XFER_URB_DEQUEUE\n");break;
++ case HC_XFER_FRAME_OVERRUN:
++ printk(KERN_INFO " STATUS:HC_XFER_FRAME_OVERRUN\n");break;
++ case HC_XFER_DATA_TOGGLE_ERR:
++ printk(KERN_INFO " STATUS:HC_XFER_DATA_TOGGLE_ERR\n");break;
++ case HC_XFER_COMPLETE:
++ printk(KERN_INFO " STATUS:HC_XFER_COMPLETE\n");break;
++ default:
++ printk(KERN_INFO " STATUS:KNOWN\n");break;
++ }
++ }
++ #endif
++}
++
++
++static void release_channel(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxhcd_halt_status_e _halt_status)
++{
++ ifxusb_hc_regs_t *hc_regs = _ifxhcd->core_if.hc_regs[_ifxhc->hc_num];
++ struct urb *urb = NULL;
++ ifxhcd_epqh_t *epqh = NULL;
++ ifxhcd_urbd_t *urbd = NULL;
++
++ IFX_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d\n",
++ __func__, _ifxhc->hc_num, _halt_status);
++
++ epqh=_ifxhc->epqh;
++
++ if(!epqh)
++ IFX_ERROR("%s epqh=null\n",__func__);
++ else
++ {
++ urbd=epqh->urbd;
++ if(!urbd)
++ IFX_ERROR("%s urbd=null\n",__func__);
++ else
++ {
++ urb=urbd->urb;
++ if(!urb)
++ IFX_ERROR("%s urb =null\n",__func__);
++ else {
++ /* == AVM/WK 20100710 Fix - Use toggle of usbcore ==*/
++ unsigned toggle = (read_data_toggle(hc_regs) == IFXUSB_HC_PID_DATA0)? 0: 1;
++ usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout(urb->pipe), toggle);
++ }
++ }
++ //epqh->data_toggle = read_data_toggle(hc_regs);
++
++ }
++
++ switch (_halt_status)
++ {
++ case HC_XFER_NO_HALT_STATUS:
++ IFX_ERROR("%s: No halt_status, channel %d\n", __func__, _ifxhc->hc_num);
++ break;
++ case HC_XFER_COMPLETE:
++ IFX_ERROR("%s: Inavalid halt_status HC_XFER_COMPLETE, channel %d\n", __func__, _ifxhc->hc_num);
++ break;
++ case HC_XFER_URB_COMPLETE:
++ case HC_XFER_URB_DEQUEUE:
++ case HC_XFER_AHB_ERR:
++ case HC_XFER_XACT_ERR:
++ case HC_XFER_FRAME_OVERRUN:
++ if(urbd && urb) {
++ /* == 20110803 AVM/WK FIX set status, if still in progress == */
++ if (urb->status == -EINPROGRESS) {
++ switch (_halt_status) {
++ case HC_XFER_URB_COMPLETE:
++ urb->status = 0;
++ break;
++ case HC_XFER_URB_DEQUEUE:
++ urb->status = -ECONNRESET;
++ break;
++ case HC_XFER_AHB_ERR:
++ case HC_XFER_XACT_ERR:
++ case HC_XFER_FRAME_OVERRUN:
++ urb->status = -EPROTO;
++ break;
++ default:
++ break;
++ }
++ }
++ /*== AVM/BC 20101111 Deferred Complete ==*/
++ defer_ifxhcd_complete_urb(_ifxhcd, urbd, urb->status);
++ }
++ else
++ {
++ IFX_WARN("WARNING %s():%d urbd=%p urb=%p\n",__func__,__LINE__,urbd,urb);
++ release_channel_dump(_ifxhc,urb,epqh,urbd,_halt_status);
++ }
++ if(epqh)
++ ifxhcd_epqh_idle(_ifxhcd, epqh);
++ else
++ {
++ IFX_WARN("WARNING %s():%d epqh=%p\n",__func__,__LINE__,epqh);
++ release_channel_dump(_ifxhc,urb,epqh,urbd,_halt_status);
++ }
++
++ list_add_tail(&_ifxhc->hc_list_entry, &_ifxhcd->free_hc_list);
++ ifxhcd_hc_cleanup(&_ifxhcd->core_if, _ifxhc);
++ break;
++ case HC_XFER_STALL:
++ release_channel_dump(_ifxhc,urb,epqh,urbd,_halt_status);
++ if(urbd)
++ /*== AVM/BC 20101111 Deferred Complete ==*/
++ defer_ifxhcd_complete_urb(_ifxhcd, urbd, -EPIPE);
++ else
++ IFX_WARN("WARNING %s():%d urbd=%p urb=%p\n",__func__,__LINE__,urbd,urb);
++ if(epqh)
++ {
++// epqh->data_toggle = 0;
++ ifxhcd_epqh_idle(_ifxhcd, epqh);
++ }
++ else
++ IFX_WARN("WARNING %s():%d epqh=%p\n",__func__,__LINE__,epqh);
++ list_add_tail(&_ifxhc->hc_list_entry, &_ifxhcd->free_hc_list);
++ ifxhcd_hc_cleanup(&_ifxhcd->core_if, _ifxhc);
++ break;
++ case HC_XFER_NAK:
++ release_channel_dump(_ifxhc,urb,epqh,urbd,_halt_status);
++ if(urbd)
++ {
++ //ifxhcd_complete_urb(_ifxhcd, urbd, -ETIMEDOUT);
++ urb->status = 0;
++ /*== AVM/BC 20101111 Deferred Complete ==*/
++ defer_ifxhcd_complete_urb(_ifxhcd, urbd, urb->status);
++ }
++ else
++ IFX_WARN("WARNING %s():%d urbd=%p urb=%p\n",__func__,__LINE__,urbd,urb);
++ if(epqh)
++ ifxhcd_epqh_idle(_ifxhcd, epqh);
++ else
++ IFX_WARN("WARNING %s():%d epqh=%p\n",__func__,__LINE__,epqh);
++ list_add_tail(&_ifxhc->hc_list_entry, &_ifxhcd->free_hc_list);
++ ifxhcd_hc_cleanup(&_ifxhcd->core_if, _ifxhc);
++ break;
++ case HC_XFER_BABBLE_ERR:
++ case HC_XFER_DATA_TOGGLE_ERR:
++ release_channel_dump(_ifxhc,urb,epqh,urbd,_halt_status);
++ if(urbd)
++ /*== AVM/BC 20101111 Deferred Complete ==*/
++ defer_ifxhcd_complete_urb(_ifxhcd, urbd, -EOVERFLOW);
++ else
++ IFX_WARN("WARNING %s():%d urbd=%p urb=%p\n",__func__,__LINE__,urbd,urb);
++ if(epqh)
++ ifxhcd_epqh_idle(_ifxhcd, epqh);
++ else
++ IFX_WARN("WARNING %s():%d epqh=%p\n",__func__,__LINE__,epqh);
++ list_add_tail(&_ifxhc->hc_list_entry, &_ifxhcd->free_hc_list);
++ ifxhcd_hc_cleanup(&_ifxhcd->core_if, _ifxhc);
++ break;
++ }
++ select_eps(_ifxhcd);
++}
++
++/*
++ * Updates the state of the URB after a Transfer Complete interrupt on the
++ * host channel. Updates the actual_length field of the URB based on the
++ * number of bytes transferred via the host channel. Sets the URB status
++ * if the data transfer is finished.
++ *
++ * @return 1 if the data transfer specified by the URB is completely finished,
++ * 0 otherwise.
++ */
++static int update_urb_state_xfer_comp(ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ struct urb *_urb,
++ ifxhcd_urbd_t *_urbd)
++{
++ int xfer_done = 0;
++
++ if (_ifxhc->is_in)
++ {
++ hctsiz_data_t hctsiz;
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++ _urb->actual_length += (_ifxhc->xfer_len - hctsiz.b.xfersize);
++ if ((hctsiz.b.xfersize != 0) || (_urb->actual_length >= _urb->transfer_buffer_length))
++ {
++ xfer_done = 1;
++ _urb->status = 0;
++ /* 20110805 AVM/WK Workaround: catch overflow error here, hardware does not */
++ if (_urb->actual_length > _urb->transfer_buffer_length) {
++ _urb->status = -EOVERFLOW;
++ }
++ #if 0
++ if (_urb->actual_length < _urb->transfer_buffer_length && _urb->transfer_flags & URB_SHORT_NOT_OK)
++ _urb->status = -EREMOTEIO;
++ #endif
++ }
++
++ }
++ else
++ {
++ if (_ifxhc->split)
++ _urb->actual_length += _ifxhc->ssplit_out_xfer_count;
++ else
++ _urb->actual_length += _ifxhc->xfer_len;
++
++ if (_urb->actual_length >= _urb->transfer_buffer_length)
++ {
++ /*== AVM/BC WK 20110421 ZERO PACKET Workaround ==*/
++ if ((_ifxhc->short_rw == 1) && ( _ifxhc->xfer_len > 0) && ( _ifxhc->xfer_len % _ifxhc->mps == 0 ))
++ {
++ _ifxhc->short_rw = 0;
++ //Transfer not finished. Another iteration for ZLP.
++ }
++ else
++ {
++ xfer_done = 1;
++ }
++ _urb->status = 0;
++ }
++ }
++
++ #ifdef __DEBUG__
++ {
++ hctsiz_data_t hctsiz;
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++ IFX_DEBUGPL(DBG_HCDV, "IFXUSB: %s: %s, channel %d\n",
++ __func__, (_ifxhc->is_in ? "IN" : "OUT"), _ifxhc->hc_num);
++ IFX_DEBUGPL(DBG_HCDV, " hc->xfer_len %d\n", _ifxhc->xfer_len);
++ IFX_DEBUGPL(DBG_HCDV, " hctsiz.xfersize %d\n", hctsiz.b.xfersize);
++ IFX_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n",
++ _urb->transfer_buffer_length);
++ IFX_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n", _urb->actual_length);
++ }
++ #endif
++ return xfer_done;
++}
++
++/*== AVM/BC 20101111 Function called with Lock ==*/
++
++void complete_channel(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxhcd_urbd_t *_urbd)
++{
++ ifxusb_hc_regs_t *hc_regs = _ifxhcd->core_if.hc_regs[_ifxhc->hc_num];
++ struct urb *urb = NULL;
++ ifxhcd_epqh_t *epqh = NULL;
++ int urb_xfer_done;
++
++ IFX_DEBUGPL(DBG_HCD, "--Complete Channel %d : \n", _ifxhc->hc_num);
++
++ if(!_urbd)
++ {
++ IFX_ERROR("ERROR %s():%d urbd=%p\n",__func__,__LINE__,_urbd);
++ return;
++ }
++
++ urb = _urbd->urb;
++ epqh = _urbd->epqh;
++
++ if(!urb || !epqh)
++ {
++ IFX_ERROR("ERROR %s():%d urb=%p epqh=%p\n",__func__,__LINE__,urb,epqh);
++ return;
++ }
++
++ _ifxhc->do_ping=0;
++
++ if (_ifxhc->split)
++ _ifxhc->split = 1;
++
++ switch (epqh->ep_type)
++ {
++ case IFXUSB_EP_TYPE_CTRL:
++ switch (_ifxhc->control_phase)
++ {
++ case IFXHCD_CONTROL_SETUP:
++ IFX_DEBUGPL(DBG_HCDV, " Control setup transaction done\n");
++ if (_urbd->xfer_len > 0)
++ {
++ _ifxhc->control_phase = IFXHCD_CONTROL_DATA;
++ _ifxhc->is_in = _urbd->is_in;
++ _ifxhc->xfer_len = _urbd->xfer_len;
++ #if defined(__UNALIGNED_BUFFER_ADJ__)
++ if(epqh->using_aligned_buf)
++ _ifxhc->xfer_buff = epqh->aligned_buf;
++ else
++ #endif
++ _ifxhc->xfer_buff = _urbd->xfer_buff;
++ }
++ else
++ {
++ _ifxhc->control_phase = IFXHCD_CONTROL_STATUS;
++ _ifxhc->is_in = 1;
++ _ifxhc->xfer_len = 0;
++ _ifxhc->xfer_buff = _ifxhcd->status_buf;
++ }
++ if(_ifxhc->is_in)
++ _ifxhc->short_rw =0;
++ else
++ _ifxhc->short_rw =(urb->transfer_flags & URB_ZERO_PACKET)?1:0;
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA1;
++ _ifxhc->xfer_count = 0;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ /*== AVM/BC 20101111 Lock not needed ==*/
++ process_channels_sub(_ifxhcd);
++ break;
++ case IFXHCD_CONTROL_DATA:
++ urb_xfer_done = update_urb_state_xfer_comp(_ifxhc, hc_regs, urb, _urbd);
++ if (urb_xfer_done)
++ {
++ _ifxhc->control_phase = IFXHCD_CONTROL_STATUS;
++ _ifxhc->is_in = (_urbd->is_in)?0:1;
++ _ifxhc->xfer_len = 0;
++ _ifxhc->xfer_count = 0;
++ _ifxhc->xfer_buff = _ifxhcd->status_buf;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA1;
++ if(_ifxhc->is_in)
++ _ifxhc->short_rw =0;
++ else
++ _ifxhc->short_rw =1;
++ }
++ else // continue
++ {
++ _ifxhc->xfer_len = _urbd->xfer_len - urb->actual_length;
++ _ifxhc->xfer_count = urb->actual_length;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ _ifxhc->data_pid_start = read_data_toggle(hc_regs);
++ }
++ /*== AVM/BC 20101111 Lock not needed ==*/
++ process_channels_sub(_ifxhcd);
++ break;
++ case IFXHCD_CONTROL_STATUS:
++ if (urb->status == -EINPROGRESS)
++ urb->status = 0;
++ release_channel(_ifxhcd,_ifxhc,HC_XFER_URB_COMPLETE);
++ break;
++ }
++ break;
++ case IFXUSB_EP_TYPE_BULK:
++ IFX_DEBUGPL(DBG_HCDV, " Bulk transfer complete\n");
++ urb_xfer_done = update_urb_state_xfer_comp(_ifxhc, hc_regs, urb, _urbd);
++ if (urb_xfer_done)
++ release_channel(_ifxhcd,_ifxhc,HC_XFER_URB_COMPLETE);
++ else
++ {
++ _ifxhc->xfer_len = _urbd->xfer_len - urb->actual_length;
++ _ifxhc->xfer_count = urb->actual_length;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ _ifxhc->data_pid_start = read_data_toggle(hc_regs);
++ /*== AVM/BC 20101111 Lock not needed ==*/
++ process_channels_sub(_ifxhcd);
++ }
++ break;
++ case IFXUSB_EP_TYPE_INTR:
++ urb_xfer_done = update_urb_state_xfer_comp(_ifxhc, hc_regs, urb, _urbd);
++ release_channel(_ifxhcd,_ifxhc,HC_XFER_URB_COMPLETE);
++ break;
++ case IFXUSB_EP_TYPE_ISOC:
++// if (_urbd->isoc_split_pos == IFXUSB_HCSPLIT_XACTPOS_ALL)
++// halt_status = update_isoc_urb_state(_ifxhcd, _ifxhc, hc_regs, _urbd, HC_XFER_COMPLETE);
++// complete_periodic_xfer(_ifxhcd, _ifxhc, hc_regs, _urbd, halt_status);
++ urb_xfer_done = update_urb_state_xfer_comp(_ifxhc, hc_regs, urb, _urbd);
++ release_channel(_ifxhcd,_ifxhc,HC_XFER_URB_COMPLETE);
++ break;
++ }
++}
++
++
++
++void showint(uint32_t val_hcint
++ ,uint32_t val_hcintmsk
++ ,uint32_t val_hctsiz)
++{
++#ifdef __DEBUG__
++ hcint_data_t hcint = {.d32 = val_hcint};
++ hcint_data_t hcintmsk = {.d32 = val_hcintmsk};
++
++ printk(KERN_INFO " WITH FLAG: Sz:%08x I:%08X/M:%08X %s%s%s%s%s%s%s%s%s%s\n"
++ ,val_hctsiz,hcint.d32 ,hcintmsk.d32
++ ,(hcint.b.datatglerr || hcintmsk.b.datatglerr)?
++ (
++ (hcint.b.datatglerr && hcintmsk.b.datatglerr)?"datatglerr[*/*] ":
++ (
++ (hcint.b.datatglerr)?"datatglerr[*/] ":"datatglerr[/*] "
++ )
++ )
++ :""
++ ,(hcint.b.frmovrun || hcintmsk.b.frmovrun)?
++ (
++ (hcint.b.frmovrun && hcintmsk.b.frmovrun)?"frmovrun[*/*] ":
++ (
++ (hcint.b.frmovrun)?"frmovrun[*/] ":"frmovrun[/*] "
++ )
++ )
++ :""
++ ,(hcint.b.bblerr || hcintmsk.b.bblerr)?
++ (
++ (hcint.b.bblerr && hcintmsk.b.bblerr)?"bblerr[*/*] ":
++ (
++ (hcint.b.bblerr)?"bblerr[*/] ":"bblerr[/*] "
++ )
++ )
++ :""
++ ,(hcint.b.xacterr || hcintmsk.b.xacterr)?
++ (
++ (hcint.b.xacterr && hcintmsk.b.xacterr)?"xacterr[*/*] ":
++ (
++ (hcint.b.xacterr)?"xacterr[*/] ":"xacterr[/*] "
++ )
++ )
++ :""
++ ,(hcint.b.nyet || hcintmsk.b.nyet)?
++ (
++ (hcint.b.nyet && hcintmsk.b.nyet)?"nyet[*/*] ":
++ (
++ (hcint.b.nyet)?"nyet[*/] ":"nyet[/*] "
++ )
++ )
++ :""
++ ,(hcint.b.nak || hcintmsk.b.nak)?
++ (
++ (hcint.b.nak && hcintmsk.b.nak)?"nak[*/*] ":
++ (
++ (hcint.b.nak)?"nak[*/] ":"nak[/*] "
++ )
++ )
++ :""
++ ,(hcint.b.ack || hcintmsk.b.ack)?
++ (
++ (hcint.b.ack && hcintmsk.b.ack)?"ack[*/*] ":
++ (
++ (hcint.b.ack)?"ack[*/] ":"ack[/*] "
++ )
++ )
++ :""
++ ,(hcint.b.stall || hcintmsk.b.stall)?
++ (
++ (hcint.b.stall && hcintmsk.b.stall)?"stall[*/*] ":
++ (
++ (hcint.b.stall)?"stall[*/] ":"stall[/*] "
++ )
++ )
++ :""
++ ,(hcint.b.ahberr || hcintmsk.b.ahberr)?
++ (
++ (hcint.b.ahberr && hcintmsk.b.ahberr)?"ahberr[*/*] ":
++ (
++ (hcint.b.ahberr)?"ahberr[*/] ":"ahberr[/*] "
++ )
++ )
++ :""
++ ,(hcint.b.xfercomp || hcintmsk.b.xfercomp)?
++ (
++ (hcint.b.xfercomp && hcintmsk.b.xfercomp)?"xfercomp[*/*] ":
++ (
++ (hcint.b.xfercomp)?"xfercomp[*/] ":"xfercomp[/*] "
++ )
++ )
++ :""
++ );
++#endif
++}
++
++
++extern void ifxhcd_hc_dumb_rx(ifxusb_core_if_t *_core_if, ifxhcd_hc_t *_ifxhc,uint8_t *dump_buf);
++
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_ctrlbulk_rx_nonsplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++ _ifxhc->do_ping = 0;
++
++ if(_ifxhc->halt_status == HC_XFER_NAK)
++ {
++ if(_ifxhc->nak_retry_r)
++ {
++ _urbd->urb->actual_length += (_ifxhc->xfer_len - hctsiz.b.xfersize);
++ _ifxhc->nak_retry--;
++ if(_ifxhc->nak_retry)
++ {
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ _ifxhc->wait_for_sof = 1;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ else
++ {
++ _ifxhc->wait_for_sof = 0;
++ release_channel(_ifxhcd, _ifxhc, _ifxhc->halt_status);
++ }
++ }
++ else
++ {
++ _urbd->urb->actual_length += (_ifxhc->xfer_len - hctsiz.b.xfersize);
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ _ifxhc->wait_for_sof = 1;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ return 1;
++ }
++
++ if (hcint.b.xfercomp)
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ return 1;
++ }
++ else if (hcint.b.stall)
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ // ZLP shortcut
++ #if 0
++ if(hctsiz.b.pktcnt==0)
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ else
++ #endif
++ {
++ // Stall FIFO compensation.
++ #if 0
++ int sz1,sz2;
++ sz2=_ifxhc->start_pkt_count - hctsiz.b.pktcnt;
++ sz2*=_ifxhc->mps;
++ sz1=_ifxhc->xfer_len - hctsiz.b.xfersize;
++ sz2-=sz1;
++ if(sz2)
++ ifxhcd_hc_dumb_rx(&_ifxhcd->core_if, _ifxhc,_ifxhc->epqh->dump_buf);
++ #endif
++ _urbd->urb->actual_length += (_ifxhc->xfer_len - hctsiz.b.xfersize);
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_STALL);
++ }
++ return 1;
++ }
++ else if (hcint.b.bblerr)
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++
++ // ZLP shortcut
++ #if 0
++ if(hctsiz.b.pktcnt==0)
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ else
++ #endif
++ _urbd->urb->actual_length += (_ifxhc->xfer_len - hctsiz.b.xfersize);
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_BABBLE_ERR);
++ return 1;
++ }
++ else if (hcint.b.xacterr)
++ {
++ // ZLP shortcut
++ #if 1
++ if(hctsiz.b.pktcnt==0)
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ }
++ else
++ #endif
++ {
++ _urbd->urb->actual_length += (_ifxhc->xfer_len - hctsiz.b.xfersize);
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++
++ /* 20110803 AVM/WK FIX: Reset error count on any handshake */
++ if (hcint.b.nak || hcint.b.nyet || hcint.b.ack) {
++ _urbd->error_count = 1;
++ } else {
++ _urbd->error_count++;
++ }
++
++ if (_urbd->error_count >= 3)
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_XACT_ERR);
++ }
++ else
++ {
++ _ifxhc->wait_for_sof = 1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ }
++ return 1;
++ }
++ else if(hcint.b.datatglerr )
++ {
++ _urbd->urb->actual_length += (_ifxhc->xfer_len - hctsiz.b.xfersize);
++ #if 1
++ if(_ifxhc->data_pid_start == IFXUSB_HC_PID_DATA0)
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA1;
++ else
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
++ _ifxhc->wait_for_sof = 1;
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ #else
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_DATA_TOGGLE_ERR);
++ #endif
++ return 1;
++ }
++ else if(hcint.b.frmovrun )
++ {
++IFX_WARN("%s() %d Warning CTRLBULK IN SPLIT0 FRMOVRUN [should be Period only]\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_FRAME_OVERRUN);
++ return 1;
++ }
++ else if(hcint.b.nyet )
++ {
++IFX_WARN("%s() %d Warning CTRLBULK IN SPLIT0 NYET [should be Out only]\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ }
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_ctrlbulk_tx_nonsplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++ int out_nak_enh = 0;
++
++#ifdef __DEBUG__
++static int first=0;
++#endif
++
++ if (_ifxhcd->core_if.snpsid >= 0x4f54271a && _ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
++ out_nak_enh = 1;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++
++#ifdef __DEBUG__
++if(!first&& _ifxhc->ep_type == IFXUSB_EP_TYPE_BULK
++ &&(hcint.b.stall || hcint.b.datatglerr || hcint.b.frmovrun || hcint.b.bblerr || hcint.b.xacterr) && !hcint.b.ack)
++{
++ showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ first=1;
++ printk(KERN_INFO " [%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X] \n"
++ ,*(_ifxhc->xfer_buff+ 0),*(_ifxhc->xfer_buff+ 1),*(_ifxhc->xfer_buff+ 2),*(_ifxhc->xfer_buff+ 3)
++ ,*(_ifxhc->xfer_buff+ 4),*(_ifxhc->xfer_buff+ 5),*(_ifxhc->xfer_buff+ 6),*(_ifxhc->xfer_buff+ 7)
++ ,*(_ifxhc->xfer_buff+ 8),*(_ifxhc->xfer_buff+ 9),*(_ifxhc->xfer_buff+10),*(_ifxhc->xfer_buff+11)
++ ,*(_ifxhc->xfer_buff+12),*(_ifxhc->xfer_buff+13),*(_ifxhc->xfer_buff+14),*(_ifxhc->xfer_buff+15));
++
++ printk(KERN_INFO " [_urbd->urb->actual_length:%08X _ifxhc->start_pkt_count:%08X hctsiz.b.pktcnt:%08X ,_urbd->xfer_len:%08x] \n"
++ ,_urbd->urb->actual_length
++ ,_ifxhc->start_pkt_count
++ ,hctsiz.b.pktcnt
++ ,_urbd->xfer_len);
++}
++#endif
++
++ if(_ifxhc->halt_status == HC_XFER_NAK)
++ {
++ if(_ifxhc->nak_retry_r)
++ {
++ _ifxhc->nak_retry--;
++ if(_ifxhc->nak_retry)
++ {
++ if(_ifxhc->xfer_len!=0)
++ _urbd->urb->actual_length += ((_ifxhc->start_pkt_count - hctsiz.b.pktcnt ) * _ifxhc->mps);
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ _ifxhc->wait_for_sof = 1;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ else
++ {
++ _ifxhc->wait_for_sof = 0;
++ release_channel(_ifxhcd, _ifxhc, _ifxhc->halt_status);
++ }
++ }
++ else
++ {
++ if(_ifxhc->xfer_len!=0)
++ _urbd->urb->actual_length += ((_ifxhc->start_pkt_count - hctsiz.b.pktcnt ) * _ifxhc->mps);
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ _ifxhc->wait_for_sof = 1;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ return 1;
++ }
++
++ if (hcint.b.xfercomp)
++ {
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++ _urbd->error_count =0;
++ if(_ifxhc->xfer_len==0 && !hcint.b.ack && hcint.b.nak)
++ {
++ // Walkaround: When sending ZLP and receive NAK but also issue CMPT intr
++ // Solution: NoSplit: Resend at next SOF
++ // Split : Resend at next SOF with SSPLIT
++ if(hcint.b.nyet && !out_nak_enh)
++ _ifxhc->do_ping = 1;
++ else
++ _ifxhc->do_ping = 0;
++ _ifxhc->xfer_len = 0;
++ _ifxhc->xfer_count = 0;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ _ifxhc->wait_for_sof = 1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ else
++ {
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->do_ping = 0;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ }
++ return 1;
++ }
++ else if (hcint.b.stall)
++ {
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++
++ // ZLP shortcut
++ #if 1
++ if(hctsiz.b.pktcnt==0)
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ else
++ #endif
++ {
++ if(_ifxhc->xfer_len!=0)
++ _urbd->urb->actual_length += ((_ifxhc->start_pkt_count - hctsiz.b.pktcnt ) * _ifxhc->mps);
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_STALL);
++ }
++ return 1;
++ }
++ else if (hcint.b.xacterr)
++ {
++ // ZLP shortcut
++ #if 1
++ if(hctsiz.b.pktcnt==0)
++ {
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ }
++ else
++ #endif
++ {
++ if(_ifxhc->xfer_len!=0)
++ _urbd->urb->actual_length += ((_ifxhc->start_pkt_count - hctsiz.b.pktcnt ) * _ifxhc->mps);
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++
++ if (hcint.b.nak || hcint.b.nyet || hcint.b.ack)
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =1;
++ enable_hc_int(_hc_regs,ack);
++ enable_hc_int(_hc_regs,nak);
++ enable_hc_int(_hc_regs,nyet);
++ if(!out_nak_enh)
++ _ifxhc->do_ping =1;
++ else
++ _ifxhc->do_ping =0;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ else
++ {
++ _urbd->error_count ++ ;
++ if (_urbd->error_count == 3)
++ {
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_XACT_ERR);
++ }
++ else
++ {
++ enable_hc_int(_hc_regs,ack);
++ enable_hc_int(_hc_regs,nak);
++ enable_hc_int(_hc_regs,nyet);
++ _ifxhc->wait_for_sof =1;
++ if(!out_nak_enh)
++ _ifxhc->do_ping =1;
++ else
++ _ifxhc->do_ping =0;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ }
++ }
++ return 1;
++ }
++ else if(hcint.b.bblerr )
++ {
++IFX_WARN("%s() %d Warning CTRLBULK OUT SPLIT0 BABBLE [should be IN only]\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ _ifxhc->do_ping = 0;
++ if(_ifxhc->xfer_len!=0)
++ _urbd->urb->actual_length += ((_ifxhc->start_pkt_count - hctsiz.b.pktcnt ) * _ifxhc->mps);
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_BABBLE_ERR);
++ return 1;
++ }
++ else if(hcint.b.nak || hcint.b.nyet)
++ {
++ if(!out_nak_enh)
++ {
++ // ZLP shortcut
++ #if 1
++ if(hctsiz.b.pktcnt==0)
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ }
++ else
++ #endif
++ {
++ if(!out_nak_enh)
++ _ifxhc->do_ping =1;
++ else
++ _ifxhc->do_ping =0;
++ if(_ifxhc->xfer_len!=0)
++ {
++ _urbd->urb->actual_length += ((_ifxhc->start_pkt_count - hctsiz.b.pktcnt ) * _ifxhc->mps);
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ }
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ _ifxhc->wait_for_sof = 1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ return 1;
++ }
++ }
++ else if(hcint.b.datatglerr )
++ {
++IFX_WARN("%s() %d Warning CTRLBULK OUT SPLIT0 DATATGLERR [should be IN only]\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_DATA_TOGGLE_ERR);
++ return 1;
++ }
++ else if(hcint.b.frmovrun )
++ {
++IFX_WARN("%s() %d Warning CTRLBULK OUT SPLIT0 FRMOVRUN [should be PERIODIC only]\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_FRAME_OVERRUN);
++ return 1;
++ }
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_intr_rx_nonsplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++ _ifxhc->do_ping =0;
++
++ if(_ifxhc->halt_status == HC_XFER_NAK)
++ {
++ if(_ifxhc->nak_retry_r)
++ {
++ _ifxhc->nak_retry--;
++ if(_ifxhc->nak_retry)
++ {
++ if(_ifxhc->xfer_len!=0)
++ _urbd->urb->actual_length += ((_ifxhc->start_pkt_count - hctsiz.b.pktcnt ) * _ifxhc->mps);
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ _ifxhc->wait_for_sof = 1;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ else
++ {
++ _ifxhc->wait_for_sof = 0;
++ release_channel(_ifxhcd, _ifxhc, _ifxhc->halt_status);
++ }
++ }
++ else
++ {
++ if(_ifxhc->xfer_len!=0)
++ _urbd->urb->actual_length += ((_ifxhc->start_pkt_count - hctsiz.b.pktcnt ) * _ifxhc->mps);
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ _ifxhc->wait_for_sof = 1;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ return 1;
++ }
++
++ if(hcint.b.xfercomp )
++ {
++ _urbd->error_count =0;
++ //restart INTR immediately
++ #if 1
++ if(hctsiz.b.pktcnt>0)
++ {
++ // TODO Re-initialize Channel (in next b_interval - 1 uF/F)
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ else
++ #endif
++ {
++ _ifxhc->wait_for_sof =0;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ }
++ return 1;
++ }
++ else if (hcint.b.stall)
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++
++ // Don't care shortcut
++ #if 0
++ if(hctsiz.b.pktcnt==0)
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ else
++ #endif
++ {
++ // Stall FIFO compensation.
++ #if 0
++ int sz1,sz2;
++ sz2=_ifxhc->start_pkt_count - hctsiz.b.pktcnt;
++ sz2*=_ifxhc->mps;
++ sz1=_ifxhc->xfer_len - hctsiz.b.xfersize;
++ sz2-=sz1;
++ if(sz2)
++ ifxhcd_hc_dumb_rx(&_ifxhcd->core_if, _ifxhc,_ifxhc->epqh->dump_buf);
++ #endif
++ _urbd->urb->actual_length += (_ifxhc->xfer_len - hctsiz.b.xfersize);
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_STALL);
++ }
++ return 1;
++ }
++
++
++ else if (hcint.b.bblerr)
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++
++ // Don't care shortcut
++ #if 0
++ if(hctsiz.b.pktcnt==0)
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ else
++ #endif
++ {
++ _urbd->urb->actual_length += (_ifxhc->xfer_len - hctsiz.b.xfersize);
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_BABBLE_ERR);
++ }
++ return 1;
++ }
++ else if (hcint.b.nak || hcint.b.datatglerr || hcint.b.frmovrun)
++ {
++ _urbd->error_count =0;
++ //restart INTR immediately
++ #if 1
++ if(hctsiz.b.pktcnt>0)
++ {
++ // TODO Re-initialize Channel (in next b_interval - 1 uF/F)
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ else
++ #endif
++ {
++ _ifxhc->wait_for_sof =0;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ }
++ return 1;
++ }
++ else if (hcint.b.xacterr)
++ {
++ // ZLP shortcut
++ #if 1
++ if(hctsiz.b.pktcnt==0)
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ }
++ else
++ #endif
++ {
++ /* 20110803 AVM/WK FIX: Reset error count on any handshake */
++ if (hcint.b.nak || hcint.b.nyet || hcint.b.ack) {
++ _urbd->error_count = 1;
++ } else {
++ _urbd->error_count++;
++ }
++
++ if(_urbd->error_count>=3)
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_XACT_ERR);
++ }
++ else
++ {
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ }
++ return 1;
++ }
++ else if(hcint.b.nyet )
++ {
++IFX_WARN("%s() %d Warning INTR IN SPLIT0 NYET [should be OUT only]\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ return 1;
++ }
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_intr_tx_nonsplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++ int out_nak_enh = 0;
++
++ if (_ifxhcd->core_if.snpsid >= 0x4f54271a && _ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
++ out_nak_enh = 1;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++
++ if(_ifxhc->halt_status == HC_XFER_NAK)
++ {
++ if(_ifxhc->nak_retry_r)
++ {
++ _ifxhc->nak_retry--;
++ if(_ifxhc->nak_retry)
++ {
++ if(_ifxhc->xfer_len!=0)
++ _urbd->urb->actual_length += ((_ifxhc->start_pkt_count - hctsiz.b.pktcnt ) * _ifxhc->mps);
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ _ifxhc->wait_for_sof = 1;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ else
++ {
++ _ifxhc->wait_for_sof = 0;
++ release_channel(_ifxhcd, _ifxhc, _ifxhc->halt_status);
++ }
++ }
++ else
++ {
++ if(_ifxhc->xfer_len!=0)
++ _urbd->urb->actual_length += ((_ifxhc->start_pkt_count - hctsiz.b.pktcnt ) * _ifxhc->mps);
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ _ifxhc->wait_for_sof = 1;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ return 1;
++ }
++
++ if(hcint.b.xfercomp )
++ {
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++ _urbd->error_count =0;
++ //restart INTR immediately
++ #if 0
++ if(hctsiz.b.pktcnt>0)
++ {
++ // TODO Re-initialize Channel (in next b_interval - 1 uF/F)
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ if(hcint.b.nyet && !out_nak_enh )
++ _ifxhc->do_ping =1;
++ else
++ _ifxhc->do_ping =0;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ else
++ #endif
++ {
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ }
++ return 1;
++ }
++ else if (hcint.b.stall)
++ {
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nyet);
++ disable_hc_int(_hc_regs,nak);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++
++ // Don't care shortcut
++ #if 0
++ if(hctsiz.b.pktcnt==0)
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ else
++ #endif
++ {
++ if(_ifxhc->xfer_len!=0)// !_ifxhc->is_in
++ _urbd->urb->actual_length += ((_ifxhc->start_pkt_count - hctsiz.b.pktcnt ) * _ifxhc->mps);
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_STALL);
++ }
++ return 1;
++ }
++ else if(hcint.b.nak || hcint.b.frmovrun )
++ {
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nyet);
++ disable_hc_int(_hc_regs,nak);
++ _urbd->error_count =0;
++ //restart INTR immediately
++ #if 0
++ if(hctsiz.b.pktcnt>0)
++ {
++ // TODO Re-initialize Channel (in next b_interval - 1 uF/F)
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ if(!out_nak_enh )
++ _ifxhc->do_ping =1;
++ else
++ _ifxhc->do_ping =0;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ else
++ #endif
++ {
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ }
++ return 1;
++ }
++ else if(hcint.b.xacterr )
++ {
++ // ZLP shortcut
++ #if 1
++ if(hctsiz.b.pktcnt==0)
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ }
++ else
++ #endif
++ {
++ /* 20110803 AVM/WK FIX: Reset error count on any handshake */
++ if (hcint.b.nak || hcint.b.nyet || hcint.b.ack) {
++ _urbd->error_count = 1;
++ } else {
++ _urbd->error_count++;
++ }
++
++ if(_urbd->error_count>=3)
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_XACT_ERR);
++ }
++ else
++ {
++ //_ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ //if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ _ifxhc->wait_for_sof=1;
++ if(!out_nak_enh )
++ _ifxhc->do_ping =1;
++ else
++ _ifxhc->do_ping =0;
++
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ }
++ return 1;
++ }
++ else if(hcint.b.bblerr )
++ {
++IFX_WARN("%s() %d Warning INTR OUT SPLIT0 BABBLEERR [should be IN only]\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_BABBLE_ERR);
++ return 1;
++ }
++ else if(hcint.b.datatglerr )
++ {
++IFX_WARN("%s() %d Warning INTR OUT SPLIT0 DATATGLERR\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_DATA_TOGGLE_ERR);
++ return 1;
++ }
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_isoc_rx_nonsplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ #if defined(__EN_ISOC__)
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++
++ if (hcint.b.xfercomp || hcint.b.frmovrun)
++ {
++ _urbd->error_count=0;
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++ _ifxhc->wait_for_sof = 0;
++ if (hcint.b.xfercomp)
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ else
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_FRAME_OVERRUN);
++ }
++ else if (hcint.b.xacterr || hcint.b.bblerr)
++ {
++ #ifndef VR9Skip
++ if(hctsiz.b.pktcnt==0)
++ {
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ }
++ else
++ {
++ int sz1,sz2;
++ sz2=_ifxhc->start_pkt_count - hctsiz.b.pktcnt;
++ sz2*=_ifxhc->mps;
++ sz1=_ifxhc->xfer_len - hctsiz.b.xfersize;
++ sz2-=sz1;
++ if(sz2)
++ ifxhcd_hc_dumb_rx(&_ifxhcd->core_if, _ifxhc,_ifxhc->epqh->dump_buf);
++ _urbd->urb->actual_length += (_ifxhc->xfer_len - hctsiz.b.xfersize);
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ _urbd->error_count++;
++ if(_urbd->error_count>=3)
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_BABBLE_ERR);
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_XACT_ERR);
++ }
++ else
++ {
++ _ifxhc->wait_for_sof = 1;
++ enable_hc_int(_hc_regs,ack);
++ enable_hc_int(_hc_regs,nak);
++ enable_hc_int(_hc_regs,nyet);
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ }
++ #endif
++ }
++ else if(hcint.b.datatglerr )
++ {
++ warning
++ }
++ else if(hcint.b.stall )
++ {
++ warning
++ }
++ #else
++ #endif
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_isoc_tx_nonsplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ #if defined(__EN_ISOC__)
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++ int out_nak_enh = 0;
++
++ if (_ifxhcd->core_if.snpsid >= 0x4f54271a && _ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
++ out_nak_enh = 1;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++
++ if (hcint.b.xfercomp)
++ {
++ _urbd->error_count=0;
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++ _ifxhc->wait_for_sof = 0;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ return 1;
++ }
++ else if (hcint.b.frmovrun)
++ {
++ #ifndef VR9Skip
++ _urbd->error_count=0;
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++ _ifxhc->wait_for_sof = 0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_FRAME_OVERRUN);
++ #endif
++ }
++ else if(hcint.b.datatglerr )
++ {
++ warning
++ }
++ else if(hcint.b.bblerr )
++ {
++ #ifndef VR9Skip
++ if(hctsiz.b.pktcnt==0)
++ {
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ }
++ else
++ {
++ int sz1,sz2;
++ sz2=_ifxhc->start_pkt_count - hctsiz.b.pktcnt;
++ sz2*=_ifxhc->mps;
++ sz1=_ifxhc->xfer_len - hctsiz.b.xfersize;
++ sz2-=sz1;
++ if(sz2)
++ ifxhcd_hc_dumb_rx(&_ifxhcd->core_if, _ifxhc,_ifxhc->epqh->dump_buf);
++ _urbd->urb->actual_length += (_ifxhc->xfer_len - hctsiz.b.xfersize);
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ _urbd->error_count++;
++ if(_urbd->error_count>=3)
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_BABBLE_ERR);
++ }
++ else
++ {
++ _ifxhc->wait_for_sof = 1;
++ enable_hc_int(_hc_regs,ack);
++ enable_hc_int(_hc_regs,nak);
++ enable_hc_int(_hc_regs,nyet);
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ }
++ #endif
++ }
++ else if(hcint.b.xacterr )
++ {
++ if(hctsiz.b.pktcnt==0)
++ {
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ return 1;
++ }
++ _urbd->error_count++;
++ if(_urbd->error_count>=3)
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_XACT_ERR);
++ }
++ else
++ {
++ _ifxhc->wait_for_sof = 1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ return 1;
++ }
++ else if(hcint.b.stall )
++ {
++ warning
++ }
++ #else
++ #endif
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_ctrlbulk_rx_ssplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++
++ _ifxhc->do_ping =0;
++
++ if (hcint.b.ack)
++ {
++ _urbd->error_count=0;
++ _ifxhc->split=2;
++ _ifxhc->wait_for_sof = 8;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if (hcint.b.nak)
++ {
++ _ifxhc->wait_for_sof = 1;
++ _urbd->error_count = 0;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if (hcint.b.xacterr)
++ {
++ _urbd->error_count++;
++ if(_urbd->error_count>=3)
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_XACT_ERR);
++ }
++ else
++ {
++ _ifxhc->wait_for_sof =1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ return 1;
++ }
++ else if(hcint.b.bblerr )
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_BABBLE_ERR);
++ return 1;
++ }
++ else if(hcint.b.stall )
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_STALL);
++ return 1;
++ }
++ else if(hcint.b.datatglerr )
++ {
++IFX_WARN("%s() %d Warning CTRLBULK IN SPLIT1 HC_XFER_DATA_TOGGLE_ERR\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_DATA_TOGGLE_ERR);
++ return 1;
++ }
++ else if(hcint.b.frmovrun )
++ {
++IFX_WARN("%s() %d Warning CTRLBULK IN SPLIT1 HC_XFER_FRAME_OVERRUN\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_FRAME_OVERRUN);
++ return 1;
++ }
++ else if(hcint.b.nyet )
++ {
++IFX_WARN("%s() %d Warning CTRLBULK IN SPLIT1 NYET\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ }
++ else if(hcint.b.xfercomp )
++ {
++IFX_WARN("%s() %d Warning CTRLBULK IN SPLIT1 COMPLETE\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ }
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_ctrlbulk_tx_ssplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++ int out_nak_enh = 0;
++
++#ifdef __DEBUG__
++static int first=0;
++#endif
++
++ if (_ifxhcd->core_if.snpsid >= 0x4f54271a && _ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
++ out_nak_enh = 1;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++
++#ifdef __DEBUG__
++ if(!first&& _ifxhc->ep_type == IFXUSB_EP_TYPE_BULK
++ &&(hcint.b.stall || hcint.b.datatglerr || hcint.b.frmovrun || hcint.b.bblerr || hcint.b.xacterr) && !hcint.b.ack)
++ {
++ showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ first=1;
++ printk(KERN_INFO " [%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X] \n"
++ ,*(_ifxhc->xfer_buff+ 0),*(_ifxhc->xfer_buff+ 1),*(_ifxhc->xfer_buff+ 2),*(_ifxhc->xfer_buff+ 3)
++ ,*(_ifxhc->xfer_buff+ 4),*(_ifxhc->xfer_buff+ 5),*(_ifxhc->xfer_buff+ 6),*(_ifxhc->xfer_buff+ 7)
++ ,*(_ifxhc->xfer_buff+ 8),*(_ifxhc->xfer_buff+ 9),*(_ifxhc->xfer_buff+10),*(_ifxhc->xfer_buff+11)
++ ,*(_ifxhc->xfer_buff+12),*(_ifxhc->xfer_buff+13),*(_ifxhc->xfer_buff+14),*(_ifxhc->xfer_buff+15));
++
++ printk(KERN_INFO " [_urbd->urb->actual_length:%08X _ifxhc->start_pkt_count:%08X hctsiz.b.pktcnt:%08X ,_urbd->xfer_len:%08x] \n"
++ ,_urbd->urb->actual_length
++ ,_ifxhc->start_pkt_count
++ ,hctsiz.b.pktcnt
++ ,_urbd->xfer_len);
++ }
++#endif
++
++ if (hcint.b.ack )
++ {
++ _urbd->error_count=0;
++ if (_ifxhc->ep_type == IFXUSB_EP_TYPE_BULK || _ifxhc->control_phase != IFXHCD_CONTROL_SETUP)
++ _ifxhc->ssplit_out_xfer_count = _ifxhc->xfer_len;
++ _ifxhc->split=2;
++ _ifxhc->wait_for_sof =8;
++ _ifxhc->data_pid_start =read_data_toggle(_hc_regs);
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.nyet)
++ {
++IFX_WARN("%s() %d Warning CTRLBULK OUT SPLIT1 NYET\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ _urbd->error_count=0;
++ if (_ifxhc->ep_type == IFXUSB_EP_TYPE_BULK || _ifxhc->control_phase != IFXHCD_CONTROL_SETUP)
++ _ifxhc->ssplit_out_xfer_count = _ifxhc->xfer_len;
++ _ifxhc->split=2;
++ _ifxhc->wait_for_sof =1;
++ _ifxhc->data_pid_start =read_data_toggle(_hc_regs);
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.nak )
++ {
++ _ifxhc->wait_for_sof =1;
++ if(!out_nak_enh )
++ _ifxhc->do_ping =1;
++ else
++ _ifxhc->do_ping =0;
++ _urbd->error_count =0;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.xacterr )
++ {
++ _urbd->error_count++;
++ if(_urbd->error_count>=3)
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_XACT_ERR);
++ }
++ else
++ {
++ _ifxhc->wait_for_sof =1;
++ _ifxhc->do_ping =1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ return 1;
++ }
++ else if(hcint.b.datatglerr )
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_DATA_TOGGLE_ERR);
++ return 1;
++ }
++ else if(hcint.b.bblerr )
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_BABBLE_ERR);
++ return 1;
++ }
++ else if(hcint.b.stall )
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_STALL);
++ return 1;
++ }
++ else if(hcint.b.frmovrun )
++ {
++IFX_WARN("%s() %d Warning CTRLBULK OUT SPLIT1 HC_XFER_FRAME_OVERRUN\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ _ifxhc->do_ping =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_FRAME_OVERRUN);
++ return 1;
++ }
++ else if(hcint.b.xfercomp )
++ {
++ printk(KERN_INFO "%s() %d Warning CTRLBULK OUT SPLIT1 COMPLETE\n",__func__,__LINE__);
++ }
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_intr_rx_ssplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++
++ _ifxhc->do_ping =0;
++
++ if (hcint.b.ack )
++ {
++ /*== AVM/BC 20100701 - Workaround FullSpeed Interrupts with HiSpeed Hub ==*/
++ _ifxhc->nyet_count=0;
++
++ _urbd->error_count=0;
++ _ifxhc->split=2;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.nak )
++ {
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ _urbd->error_count=0;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.xacterr )
++ {
++ hcchar_data_t hcchar;
++ hcchar.d32 = ifxusb_rreg(&_hc_regs->hcchar);
++ _urbd->error_count=hcchar.b.multicnt;
++ if(_urbd->error_count>=3)
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_XACT_ERR);
++ }
++ else
++ {
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ return 1;
++ }
++ else if(hcint.b.stall )
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_STALL);
++ return 1;
++ }
++ else if(hcint.b.bblerr )
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_BABBLE_ERR);
++ return 1;
++ }
++ else if(hcint.b.frmovrun )
++ {
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.datatglerr )
++ {
++IFX_WARN( "%s() %d Warning INTR IN SPLIT1 DATATGLERR\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_DATA_TOGGLE_ERR);
++ return 1;
++ }
++ else if(hcint.b.xfercomp )
++ {
++IFX_WARN("%s() %d Warning INTR IN SPLIT1 COMPLETE\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ }
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_intr_tx_ssplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++ int out_nak_enh = 0;
++
++ if (_ifxhcd->core_if.snpsid >= 0x4f54271a && _ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
++ out_nak_enh = 1;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++
++ if (hcint.b.ack )
++ {
++ /*== AVM/BC 20100701 - Workaround FullSpeed Interrupts with HiSpeed Hub ==*/
++ _ifxhc->nyet_count=0;
++
++ _urbd->error_count=0;
++ _ifxhc->ssplit_out_xfer_count = _ifxhc->xfer_len;
++ _ifxhc->split=2;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.nyet)
++ {
++IFX_WARN("%s() %d Warning INTR OUT SPLIT1 NYET\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ _urbd->error_count=0;
++ _ifxhc->ssplit_out_xfer_count = _ifxhc->xfer_len;
++ _ifxhc->split=2;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->data_pid_start = read_data_toggle(_hc_regs);
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.nak )
++ {
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ _urbd->error_count =0;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.frmovrun )
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.xacterr )
++ {
++ hcchar_data_t hcchar;
++ hcchar.d32 = ifxusb_rreg(&_hc_regs->hcchar);
++ _urbd->error_count=hcchar.b.multicnt;
++ if(_urbd->error_count>=3)
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_XACT_ERR);
++ }
++ else
++ {
++ enable_hc_int(_hc_regs,ack);
++ enable_hc_int(_hc_regs,nak);
++ enable_hc_int(_hc_regs,nyet);
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ return 1;
++ }
++ else if(hcint.b.datatglerr )
++ {
++IFX_WARN("%s() %d Warning INTR IN SPLIT1 DATATGLERR\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_DATA_TOGGLE_ERR);
++ return 1;
++ }
++ else if(hcint.b.bblerr )
++ {
++IFX_WARN("%s() %d Warning INTR IN SPLIT1 BABBLEERR\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_BABBLE_ERR);
++ return 1;
++ }
++ else if(hcint.b.stall )
++ {
++IFX_WARN("%s() %d Warning INTR IN SPLIT1 STALL\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof =0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_STALL);
++ return 1;
++ }
++ else if(hcint.b.xfercomp )
++ {
++IFX_WARN("%s() %d Warning INTR IN SPLIT1 COMPLETE\n",__func__,__LINE__);
++showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ }
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_isoc_rx_ssplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ #if defined(__EN_ISOC__) && defined(__EN_ISOC_SPLIT__)
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++ if (hcint.b.ack )
++ {
++ Do Complete Split
++ }
++ else if(hcint.b.frmovrun )
++ {
++ Rewind Buffer Pointers
++ Retry Start Split (in next b_interval ¡V 1 uF)
++ }
++ else if(hcint.b.datatglerr )
++ {
++ warning
++ }
++ else if(hcint.b.bblerr )
++ {
++ warning
++ }
++ else if(hcint.b.xacterr )
++ {
++ warning
++ }
++ else if(hcint.b.stall )
++ {
++ warning
++ }
++ else if(hcint.b.nak )
++ {
++ warning
++ }
++ else if(hcint.b.xfercomp )
++ {
++ warning
++ }
++ else if(hcint.b.nyet)
++ {
++ warning
++ }
++ #endif
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_isoc_tx_ssplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ #if defined(__EN_ISOC__) && defined(__EN_ISOC_SPLIT__)
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++ int out_nak_enh = 0;
++
++ if (_ifxhcd->core_if.snpsid >= 0x4f54271a && _ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
++ out_nak_enh = 1;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++ if (hcint.b.ack )
++ {
++ Do Next Start Split (in next b_interval ¡V 1 uF)
++ }
++ else if(hcint.b.frmovrun )
++ {
++ Do Next Transaction in next frame.
++ }
++ else if(hcint.b.datatglerr )
++ {
++ warning
++ }
++ else if(hcint.b.bblerr )
++ {
++ warning
++ }
++ else if(hcint.b.xacterr )
++ {
++ warning
++ }
++ else if(hcint.b.stall )
++ {
++ warning
++ }
++ else if(hcint.b.nak )
++ {
++ warning
++ }
++ else if(hcint.b.xfercomp )
++ {
++ warning
++ }
++ else if(hcint.b.nyet)
++ {
++ warning
++ }
++ #endif
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_ctrlbulk_rx_csplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++
++ _ifxhc->do_ping = 0;
++
++ if (hcint.b.xfercomp)
++ {
++ _urbd->error_count =0;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->split=1;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ return 1;
++ }
++ else if (hcint.b.nak)
++ {
++ _urbd->error_count=0;
++
++ _ifxhc->split = 1;
++ _ifxhc->wait_for_sof = 1;
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.nyet)
++ {
++ _urbd->error_count=0;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ _ifxhc->wait_for_sof = 1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.stall || hcint.b.bblerr )
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ if (hcint.b.stall)
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_STALL);
++ else if(hcint.b.bblerr )
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_BABBLE_ERR);
++ return 1;
++ }
++ else if(hcint.b.xacterr )
++ {
++ _urbd->error_count++;
++ if(_urbd->error_count>=3)
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_XACT_ERR);
++ }
++ else
++ {
++ _ifxhc->split=1;
++ _ifxhc->wait_for_sof = 1;
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ return 1;
++ }
++ else if(hcint.b.datatglerr )
++ {
++ if(_ifxhc->data_pid_start == IFXUSB_HC_PID_DATA0)
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA1;
++ else
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
++ _ifxhc->split=1;
++ _ifxhc->wait_for_sof = 1;
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.frmovrun )
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_FRAME_OVERRUN);
++ return 1;
++ }
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_ctrlbulk_tx_csplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++ int out_nak_enh = 0;
++
++#if 1
++static int first=0;
++#endif
++
++ if (_ifxhcd->core_if.snpsid >= 0x4f54271a && _ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
++ out_nak_enh = 1;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++
++#if 1
++ if(!first&& _ifxhc->ep_type == IFXUSB_EP_TYPE_BULK
++ &&(hcint.b.stall || hcint.b.datatglerr || hcint.b.frmovrun || hcint.b.bblerr || hcint.b.xacterr) && !hcint.b.ack)
++ {
++ showint( hcint.d32,hcintmsk.d32,hctsiz.d32);
++ first=1;
++ printk(KERN_INFO " [%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X] \n"
++ ,*(_ifxhc->xfer_buff+ 0),*(_ifxhc->xfer_buff+ 1),*(_ifxhc->xfer_buff+ 2),*(_ifxhc->xfer_buff+ 3)
++ ,*(_ifxhc->xfer_buff+ 4),*(_ifxhc->xfer_buff+ 5),*(_ifxhc->xfer_buff+ 6),*(_ifxhc->xfer_buff+ 7)
++ ,*(_ifxhc->xfer_buff+ 8),*(_ifxhc->xfer_buff+ 9),*(_ifxhc->xfer_buff+10),*(_ifxhc->xfer_buff+11)
++ ,*(_ifxhc->xfer_buff+12),*(_ifxhc->xfer_buff+13),*(_ifxhc->xfer_buff+14),*(_ifxhc->xfer_buff+15));
++
++ printk(KERN_INFO " [_urbd->urb->actual_length:%08X _ifxhc->start_pkt_count:%08X hctsiz.b.pktcnt:%08X ,_urbd->xfer_len:%08x] \n"
++ ,_urbd->urb->actual_length
++ ,_ifxhc->start_pkt_count
++ ,hctsiz.b.pktcnt
++ ,_urbd->xfer_len);
++ }
++#endif
++
++ if(hcint.b.xfercomp )
++ {
++ _urbd->error_count=0;
++ _ifxhc->split=1;
++ _ifxhc->do_ping= 0;
++ #if 0
++ if(_ifxhc->xfer_len==0 && !hcint.b.ack && (hcint.b.nak || hcint.b.nyet))
++ {
++ // Walkaround: When sending ZLP and receive NYEY or NAK but also issue CMPT intr
++ // Solution: NoSplit: Resend at next SOF
++ // Split : Resend at next SOF with SSPLIT
++ _ifxhc->xfer_len = 0;
++ _ifxhc->xfer_count = 0;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ _ifxhc->wait_for_sof = 1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ else
++ #endif
++ {
++ _ifxhc->wait_for_sof = 0;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ }
++ return 1;
++ }
++ else if(hcint.b.nak )
++ {
++ _urbd->error_count=0;
++
++ _ifxhc->split = 1;
++ _ifxhc->wait_for_sof = 1;
++ if(!out_nak_enh )
++ _ifxhc->do_ping =1;
++ else
++ _ifxhc->do_ping =0;
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.nyet)
++ {
++ //Retry Complete Split
++ // Issue Retry instantly on next SOF, without gothrough process_channels
++ _urbd->error_count=0;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ _ifxhc->wait_for_sof = 1;
++ _ifxhc->do_ping = 0;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.stall )
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->do_ping = 0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_STALL);
++ return 1;
++ }
++ else if(hcint.b.xacterr )
++ {
++ _urbd->error_count++;
++ if(_urbd->error_count>=3)
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->do_ping = 0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_XACT_ERR);
++ }
++ else
++ {
++ _ifxhc->split=1;
++ _ifxhc->wait_for_sof = 1;
++ if(!out_nak_enh )
++ _ifxhc->do_ping =1;
++ else
++ _ifxhc->do_ping =0;
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ return 1;
++ }
++ else if(hcint.b.datatglerr )
++ {
++ if(_ifxhc->data_pid_start == IFXUSB_HC_PID_DATA0)
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA1;
++ else
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
++ _ifxhc->split=1;
++ _ifxhc->wait_for_sof = 1;
++ if(!out_nak_enh )
++ _ifxhc->do_ping =1;
++ else
++ _ifxhc->do_ping =0;
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.frmovrun )
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->do_ping = 0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_FRAME_OVERRUN);
++ return 1;
++ }
++ else if(hcint.b.bblerr )
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->do_ping = 0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_BABBLE_ERR);
++ return 1;
++ }
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_intr_rx_csplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++ _ifxhc->do_ping = 0;
++
++ if (hcint.b.xfercomp )
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->split=1;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ return 1;
++ }
++ else if(hcint.b.nak )
++ {
++ _urbd->error_count=0;
++ _ifxhc->split = 1;
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.nyet)
++ {
++ _urbd->error_count=0;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ _ifxhc->wait_for_sof = 0;
++
++ /*== AVM/BC 20100701 - Workaround FullSpeed Interrupts with HiSpeed Hub ==*/
++ _ifxhc->nyet_count++;
++ if(_ifxhc->nyet_count > 2) {
++ _ifxhc->split = 1;
++ _ifxhc->nyet_count = 0;
++ _ifxhc->wait_for_sof = 5;
++ }
++
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.frmovrun || hcint.b.bblerr || hcint.b.stall )
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ if (hcint.b.stall)
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_STALL);
++ else if(hcint.b.bblerr )
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_BABBLE_ERR);
++ else if(hcint.b.frmovrun )
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_FRAME_OVERRUN);
++ return 1;
++ }
++ else if(hcint.b.xacterr )
++ {
++ hcchar_data_t hcchar;
++ hcchar.d32 = ifxusb_rreg(&_hc_regs->hcchar);
++ _urbd->error_count=hcchar.b.multicnt;
++ if(_urbd->error_count>=3)
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_XACT_ERR);
++ }
++ else
++ {
++ _ifxhc->split=1;
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ return 1;
++ }
++ else if(hcint.b.datatglerr )
++ {
++ if(_ifxhc->data_pid_start == IFXUSB_HC_PID_DATA0)
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA1;
++ else
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
++ _ifxhc->split=1;
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_intr_tx_csplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++ int out_nak_enh = 0;
++
++ if (_ifxhcd->core_if.snpsid >= 0x4f54271a && _ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
++ out_nak_enh = 1;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++
++ if(hcint.b.xfercomp )
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->split=1;
++ _ifxhc->do_ping = 0;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ return 1;
++ }
++ else if(hcint.b.nak )
++ {
++ _urbd->error_count=0;
++ _ifxhc->split = 1;
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ if(!out_nak_enh )
++ _ifxhc->do_ping =1;
++ else
++ _ifxhc->do_ping =0;
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.nyet)
++ {
++ _urbd->error_count=0;
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->do_ping = 0;
++
++ /*== AVM/BC 20100701 - Workaround FullSpeed Interrupts with HiSpeed Hub ==*/
++ _ifxhc->nyet_count++;
++ if(_ifxhc->nyet_count > 2) {
++ _ifxhc->split = 1;
++ _ifxhc->nyet_count = 0;
++ _ifxhc->wait_for_sof = 5;
++ }
++
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.stall || hcint.b.frmovrun)
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->do_ping = 0;
++ if (hcint.b.stall)
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_STALL);
++ else if(hcint.b.frmovrun )
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_FRAME_OVERRUN);
++ return 1;
++ }
++ else if(hcint.b.xacterr )
++ {
++ hcchar_data_t hcchar;
++ hcchar.d32 = ifxusb_rreg(&_hc_regs->hcchar);
++ _urbd->error_count=hcchar.b.multicnt;
++ if(_urbd->error_count>=3)
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->do_ping = 0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_XACT_ERR);
++ }
++ else
++ {
++ _ifxhc->split=1;
++ _ifxhc->wait_for_sof = _ifxhc->epqh->interval-1;
++ if(!_ifxhc->wait_for_sof) _ifxhc->wait_for_sof=1;
++ if(!out_nak_enh )
++ _ifxhc->do_ping =1;
++ else
++ _ifxhc->do_ping =0;
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ }
++ return 1;
++ }
++ else if(hcint.b.datatglerr )
++ {
++ if(_ifxhc->data_pid_start == IFXUSB_HC_PID_DATA0)
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA1;
++ else
++ _ifxhc->data_pid_start = IFXUSB_HC_PID_DATA0;
++ _ifxhc->split=1;
++ if(!out_nak_enh )
++ _ifxhc->do_ping =1;
++ else
++ _ifxhc->do_ping =0;
++ _ifxhc->xfer_len = _urbd->xfer_len - _urbd->urb->actual_length;
++ _ifxhc->xfer_count = _urbd->urb->actual_length;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.bblerr )
++ {
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->do_ping = 0;
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_BABBLE_ERR);
++ return 1;
++ }
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_isoc_rx_csplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ #if defined(__EN_ISOC__) && defined(__EN_ISOC_SPLIT__)
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++ if(hcint.b.xfercomp )
++ {
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,nyet);
++ _urbd->error_count=0;
++ _ifxhc->wait_for_sof = 0;
++ _ifxhc->split=1;
++ complete_channel(_ifxhcd, _ifxhc, _urbd);
++ return 1;
++ }
++ else if(hcint.b.nak )
++ {
++ Retry Start Split (in next b_interval ¡V 1 uF)
++ }
++ else if(hcint.b.nyet)
++ {
++ //Do Next Complete Split
++ // Issue Retry instantly on next SOF, without gothrough process_channels
++ _urbd->error_count=0;
++ //disable_hc_int(_hc_regs,ack);
++ //disable_hc_int(_hc_regs,nak);
++ //disable_hc_int(_hc_regs,datatglerr);
++ _ifxhc->halt_status = HC_XFER_NO_HALT_STATUS;
++ _ifxhc->wait_for_sof = 1;
++ ifxhcd_hc_start(&_ifxhcd->core_if, _ifxhc);
++ return 1;
++ }
++ else if(hcint.b.frmovrun || hcint.b.stall || hcint.b.bblerr)
++ {
++ _urbd->error_count=0;
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nyet);
++ disable_hc_int(_hc_regs,nak);
++ _ifxhc->wait_for_sof = 0;
++
++ //if(hctsiz.b.pktcnt==0)
++ //{
++ // complete_channel(_ifxhcd, _ifxhc, _urbd);
++ // return 1;
++ //}
++ //else
++ // _urbd->urb->actual_length += (_ifxhc->xfer_len - hctsiz.b.xfersize);
++ if (hcint.b.stall)
++ release_channel(_ifxhcd, _ifxhc, HC_XFER_STALL);
++ else if(hcint.b.frmovrun )
++ else if(hcint.b.bblerr )
++ return 1;
++ }
++ else if(hcint.b.xacterr )
++ {
++ Rewind Buffer Pointers
++ if (HCCHARn.EC = = 3) // ERR response received
++ {
++ Record ERR error
++ Do Next Start Split (in next frame)
++ }
++ else
++ {
++ De-allocate Channel
++ }
++ }
++ else if(hcint.b.datatglerr )
++ {
++ warning
++ }
++ else if(hcint.b.ack )
++ {
++ warning
++ }
++ #endif
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++static int32_t chhltd_isoc_tx_csplit(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ #if defined(__EN_ISOC__) && defined(__EN_ISOC_SPLIT__)
++ hcint_data_t hcint;
++ hcint_data_t hcintmsk;
++ hctsiz_data_t hctsiz;
++ int out_nak_enh = 0;
++
++ if (_ifxhcd->core_if.snpsid >= 0x4f54271a && _ifxhc->speed == IFXUSB_EP_SPEED_HIGH)
++ out_nak_enh = 1;
++
++ hcint.d32 = ifxusb_rreg(&_hc_regs->hcint);
++ hcintmsk.d32 = ifxusb_rreg(&_hc_regs->hcintmsk);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++ warning
++ #endif
++ return 0;
++}
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++
++static int32_t handle_hc_chhltd_intr(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ IFX_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: Channel Halted--\n", _ifxhc->hc_num);
++
++ _ifxhc->halting = 0;
++ _ifxhc->xfer_started = 0;
++
++ if (_ifxhc->halt_status == HC_XFER_URB_DEQUEUE ||
++ _ifxhc->halt_status == HC_XFER_AHB_ERR) {
++ /*
++ * Just release the channel. A dequeue can happen on a
++ * transfer timeout. In the case of an AHB Error, the channel
++ * was forced to halt because there's no way to gracefully
++ * recover.
++ */
++ release_channel(_ifxhcd, _ifxhc, _ifxhc->halt_status);
++ return 1;
++ }
++
++ if (_ifxhc->ep_type == IFXUSB_EP_TYPE_CTRL || _ifxhc->ep_type == IFXUSB_EP_TYPE_BULK)
++ {
++ if (_ifxhc->split==0)
++ {
++ if(_ifxhc->is_in)
++ return (chhltd_ctrlbulk_rx_nonsplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ else
++ return (chhltd_ctrlbulk_tx_nonsplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ }
++ else if(_ifxhc->split==1)
++ {
++ if(_ifxhc->is_in)
++ return (chhltd_ctrlbulk_rx_ssplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ else
++ return (chhltd_ctrlbulk_tx_ssplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ }
++ else if(_ifxhc->split==2)
++ {
++ if(_ifxhc->is_in)
++ return (chhltd_ctrlbulk_rx_csplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ else
++ return (chhltd_ctrlbulk_tx_csplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ }
++ }
++ else if(_ifxhc->ep_type == IFXUSB_EP_TYPE_INTR)
++ {
++ if (_ifxhc->split==0)
++ {
++ if(_ifxhc->is_in)
++ return (chhltd_intr_rx_nonsplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ else
++ return (chhltd_intr_tx_nonsplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ }
++ else if(_ifxhc->split==1)
++ {
++ if(_ifxhc->is_in)
++ return (chhltd_intr_rx_ssplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ else
++ return (chhltd_intr_tx_ssplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ }
++ else if(_ifxhc->split==2)
++ {
++ if(_ifxhc->is_in)
++ return (chhltd_intr_rx_csplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ else
++ return (chhltd_intr_tx_csplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ }
++ }
++ else if(_ifxhc->ep_type == IFXUSB_EP_TYPE_ISOC)
++ {
++ if (_ifxhc->split==0)
++ {
++ if(_ifxhc->is_in)
++ return (chhltd_isoc_rx_nonsplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ else
++ return (chhltd_isoc_tx_nonsplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ }
++ else if(_ifxhc->split==1)
++ {
++ if(_ifxhc->is_in)
++ return (chhltd_isoc_rx_ssplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ else
++ return (chhltd_isoc_tx_ssplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ }
++ else if(_ifxhc->split==2)
++ {
++ if(_ifxhc->is_in)
++ return (chhltd_isoc_rx_csplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ else
++ return (chhltd_isoc_tx_csplit(_ifxhcd,_ifxhc,_hc_regs,_urbd));
++ }
++ }
++ return 0;
++}
++
++/*
++ * Handles a host channel AHB error interrupt. This handler is only called in
++ * DMA mode.
++ */
++static void hc_other_intr_dump(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ #ifdef __DEBUG__
++ hcchar_data_t hcchar;
++ hcsplt_data_t hcsplt;
++ hctsiz_data_t hctsiz;
++ uint32_t hcdma;
++ struct urb *urb = _urbd->urb;
++ hcchar.d32 = ifxusb_rreg(&_hc_regs->hcchar);
++ hcsplt.d32 = ifxusb_rreg(&_hc_regs->hcsplt);
++ hctsiz.d32 = ifxusb_rreg(&_hc_regs->hctsiz);
++ hcdma = ifxusb_rreg(&_hc_regs->hcdma);
++
++ IFX_ERROR("Channel %d\n", _ifxhc->hc_num);
++ IFX_ERROR(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);
++ IFX_ERROR(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma);
++ IFX_ERROR(" Device address: %d\n", usb_pipedevice(urb->pipe));
++ IFX_ERROR(" Endpoint: %d, %s\n", usb_pipeendpoint(urb->pipe),
++ (usb_pipein(urb->pipe) ? "IN" : "OUT"));
++ IFX_ERROR(" Endpoint type: %s\n",
++ ({char *pipetype;
++ switch (usb_pipetype(urb->pipe)) {
++ case PIPE_CONTROL: pipetype = "CTRL"; break;
++ case PIPE_BULK: pipetype = "BULK"; break;
++ case PIPE_INTERRUPT: pipetype = "INTR"; break;
++ case PIPE_ISOCHRONOUS: pipetype = "ISOC"; break;
++ default: pipetype = "????"; break;
++ }; pipetype;}));
++ IFX_ERROR(" Speed: %s\n",
++ ({char *speed;
++ switch (urb->dev->speed) {
++ case USB_SPEED_HIGH: speed = "HS"; break;
++ case USB_SPEED_FULL: speed = "FS"; break;
++ case USB_SPEED_LOW: speed = "LS"; break;
++ default: speed = "????"; break;
++ }; speed;}));
++ IFX_ERROR(" Max packet size: %d\n",
++ usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)));
++ IFX_ERROR(" Data buffer length: %d\n", urb->transfer_buffer_length);
++ IFX_ERROR(" Transfer buffer: %p, Transfer DMA: %p\n",
++ urb->transfer_buffer, (void *)urb->transfer_dma);
++ IFX_ERROR(" Setup buffer: %p, Setup DMA: %p\n",
++ urb->setup_packet, (void *)urb->setup_dma);
++ IFX_ERROR(" Interval: %d\n", urb->interval);
++ #endif //__DEBUG__
++}
++
++/*
++ * Handles a host channel ACK interrupt. This interrupt is enabled when
++ * errors occur, and during Start Split transactions.
++ */
++static int32_t handle_hc_ack_intr(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ _urbd->error_count=0;
++ if(_ifxhc->nak_countdown_r)
++ {
++ _ifxhc->nak_retry=_ifxhc->nak_retry_r;
++ _ifxhc->nak_countdown=_ifxhc->nak_countdown_r;
++ }
++ else
++ disable_hc_int(_hc_regs,nak);
++ disable_hc_int(_hc_regs,ack);
++ return 1;
++}
++
++/*
++ * Handles a host channel ACK interrupt. This interrupt is enabled when
++ * errors occur, and during Start Split transactions.
++ */
++static int32_t handle_hc_nak_intr(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++
++ _urbd->error_count=0;
++
++ if(_ifxhc->nak_countdown_r)
++ {
++ _ifxhc->nak_countdown--;
++ if(!_ifxhc->nak_countdown)
++ {
++ _ifxhc->nak_countdown=_ifxhc->nak_countdown_r;
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ ifxhcd_hc_halt(&_ifxhcd->core_if, _ifxhc, HC_XFER_NAK);
++ }
++ else
++ enable_hc_int(_hc_regs,ack);
++ }
++ else
++ {
++ disable_hc_int(_hc_regs,ack);
++ disable_hc_int(_hc_regs,nak);
++ }
++ return 1;
++}
++
++/*
++ * Handles a host channel AHB error interrupt. This handler is only called in
++ * DMA mode.
++ */
++static int32_t handle_hc_ahberr_intr(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ IFX_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
++ "AHB Error--\n", _ifxhc->hc_num);
++ hc_other_intr_dump(_ifxhcd,_ifxhc,_hc_regs,_urbd);
++
++ ifxhcd_hc_halt(&_ifxhcd->core_if, _ifxhc, HC_XFER_AHB_ERR);
++ return 1;
++}
++
++/*
++ * Datatoggle
++ */
++static int32_t handle_hc_datatglerr_intr(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ IFX_ERROR( "--Host Channel %d Interrupt: "
++ "DATATOGGLE Error--\n", _ifxhc->hc_num);
++ hc_other_intr_dump(_ifxhcd,_ifxhc,_hc_regs,_urbd);
++ disable_hc_int(_hc_regs,datatglerr);
++ return 1;
++}
++
++
++
++/*
++ * Interrupts which should not been triggered
++ */
++static int32_t handle_hc_frmovrun_intr(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ IFX_ERROR( "--Host Channel %d Interrupt: "
++ "FrameOverRun Error--\n", _ifxhc->hc_num);
++ hc_other_intr_dump(_ifxhcd,_ifxhc,_hc_regs,_urbd);
++ disable_hc_int(_hc_regs,frmovrun);
++ return 1;
++}
++
++static int32_t handle_hc_bblerr_intr(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ IFX_ERROR( "--Host Channel %d Interrupt: "
++ "BBL Error--\n", _ifxhc->hc_num);
++ hc_other_intr_dump(_ifxhcd,_ifxhc,_hc_regs,_urbd);
++ disable_hc_int(_hc_regs,bblerr);
++ return 1;
++}
++
++static int32_t handle_hc_xacterr_intr(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ IFX_ERROR( "--Host Channel %d Interrupt: "
++ "XACT Error--\n", _ifxhc->hc_num);
++ hc_other_intr_dump(_ifxhcd,_ifxhc,_hc_regs,_urbd);
++ disable_hc_int(_hc_regs,xacterr);
++ return 1;
++}
++
++static int32_t handle_hc_nyet_intr(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ IFX_ERROR( "--Host Channel %d Interrupt: "
++ "NYET--\n", _ifxhc->hc_num);
++ hc_other_intr_dump(_ifxhcd,_ifxhc,_hc_regs,_urbd);
++ _urbd->error_count=0;
++ disable_hc_int(_hc_regs,nyet);
++ return 1;
++}
++
++static int32_t handle_hc_stall_intr(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ IFX_ERROR( "--Host Channel %d Interrupt: "
++ "STALL--\n", _ifxhc->hc_num);
++ hc_other_intr_dump(_ifxhcd,_ifxhc,_hc_regs,_urbd);
++ disable_hc_int(_hc_regs,stall);
++ return 1;
++}
++
++static int32_t handle_hc_xfercomp_intr(ifxhcd_hcd_t *_ifxhcd,
++ ifxhcd_hc_t *_ifxhc,
++ ifxusb_hc_regs_t *_hc_regs,
++ ifxhcd_urbd_t *_urbd)
++{
++ IFX_ERROR( "--Host Channel %d Interrupt: "
++ "XFERCOMP--\n", _ifxhc->hc_num);
++ hc_other_intr_dump(_ifxhcd,_ifxhc,_hc_regs,_urbd);
++ disable_hc_int(_hc_regs,xfercomp);
++ return 1;
++}
++
++
++
++/* This interrupt indicates that the specified host channels has a pending
++ * interrupt. There are multiple conditions that can cause each host channel
++ * interrupt. This function determines which conditions have occurred for this
++ * host channel interrupt and handles them appropriately. */
++static int32_t handle_hc_n_intr (ifxhcd_hcd_t *_ifxhcd, uint32_t _num)
++{
++ uint32_t hcintval,hcintmsk;
++ hcint_data_t hcint;
++ ifxhcd_hc_t *ifxhc;
++ ifxusb_hc_regs_t *hc_regs;
++ ifxhcd_urbd_t *urbd;
++ unsigned long flags;
++
++ int retval = 0;
++
++ IFX_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", _num);
++
++ /*== AVM/BC 20101111 Lock needed ==*/
++ SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
++
++ ifxhc = &_ifxhcd->ifxhc[_num];
++ hc_regs = _ifxhcd->core_if.hc_regs[_num];
++
++ hcintval = ifxusb_rreg(&hc_regs->hcint);
++ hcintmsk = ifxusb_rreg(&hc_regs->hcintmsk);
++ hcint.d32 = hcintval & hcintmsk;
++ IFX_DEBUGPL(DBG_HCDV, " 0x%08x & 0x%08x = 0x%08x\n",
++ hcintval, hcintmsk, hcint.d32);
++
++ urbd = list_entry(ifxhc->epqh->urbd_list.next, ifxhcd_urbd_t, urbd_list_entry);
++
++ if (hcint.b.datatglerr)
++ retval |= handle_hc_datatglerr_intr(_ifxhcd, ifxhc, hc_regs, urbd);
++ if (hcint.b.frmovrun)
++ retval |= handle_hc_frmovrun_intr(_ifxhcd, ifxhc, hc_regs, urbd);
++ if (hcint.b.bblerr)
++ retval |= handle_hc_bblerr_intr(_ifxhcd, ifxhc, hc_regs, urbd);
++ if (hcint.b.xacterr)
++ retval |= handle_hc_xacterr_intr(_ifxhcd, ifxhc, hc_regs, urbd);
++ if (hcint.b.nyet)
++ retval |= handle_hc_nyet_intr(_ifxhcd, ifxhc, hc_regs, urbd);
++ if (hcint.b.ack)
++ retval |= handle_hc_ack_intr(_ifxhcd, ifxhc, hc_regs, urbd);
++ if (hcint.b.nak)
++ retval |= handle_hc_nak_intr(_ifxhcd, ifxhc, hc_regs, urbd);
++ if (hcint.b.stall)
++ retval |= handle_hc_stall_intr(_ifxhcd, ifxhc, hc_regs, urbd);
++ if (hcint.b.ahberr) {
++ clear_hc_int(hc_regs, ahberr);
++ retval |= handle_hc_ahberr_intr(_ifxhcd, ifxhc, hc_regs, urbd);
++ }
++ if (hcint.b.chhltd) {
++ /* == 20110901 AVM/WK Fix: Flag must not be cleared after restart of channel ==*/
++ clear_hc_int(hc_regs, chhltd);
++ retval |= handle_hc_chhltd_intr(_ifxhcd, ifxhc, hc_regs, urbd);
++ }
++ if (hcint.b.xfercomp)
++ retval |= handle_hc_xfercomp_intr(_ifxhcd, ifxhc, hc_regs, urbd);
++
++ /* == 20110901 AVM/WK Fix: Never clear possibly new intvals ==*/
++ //ifxusb_wreg(&hc_regs->hcint,hcintval);
++
++ SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
++
++ return retval;
++}
++
++
++
++
++
++
++static uint8_t update_interval_counter(ifxhcd_epqh_t *_epqh,uint32_t _diff)
++{
++ if(_diff>=_epqh->period_counter)
++ {
++ _epqh->period_do=1;
++ if(_diff>_epqh->interval)
++ _epqh->period_counter=1;
++ else
++ _epqh->period_counter=_epqh->period_counter+_epqh->interval-_diff;
++ return 1;
++ }
++ _epqh->period_counter=_epqh->period_counter-_diff;
++ return 0;
++}
++
++
++
++
++/*
++ * Handles the start-of-frame interrupt in host mode. Non-periodic
++ * transactions may be queued to the DWC_otg controller for the current
++ * (micro)frame. Periodic transactions may be queued to the controller for the
++ * next (micro)frame.
++ */
++static int32_t handle_sof_intr (ifxhcd_hcd_t *_ifxhcd)
++{
++ #ifdef __DYN_SOF_INTR__
++ uint8_t with_count_down=0;
++ #endif
++ uint8_t active_on=0;
++ uint8_t ready_on=0;
++ struct list_head *epqh_entry;
++ ifxhcd_epqh_t *epqh;
++ hfnum_data_t hfnum;
++ uint32_t fndiff;
++
++ unsigned long flags;
++#ifdef __USE_TIMER_4_SOF__
++ uint32_t wait_for_sof = 0x10000;
++#endif
++
++ SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
++
++ {
++ int num_channels;
++ ifxusb_hc_regs_t *hc_regs;
++ int i;
++ num_channels = _ifxhcd->core_if.params.host_channels;
++
++// AVM/WK moved block here due to use of SOF timer
++ hfnum.d32 = ifxusb_rreg(&_ifxhcd->core_if.host_global_regs->hfnum);
++ fndiff = hfnum.b.frnum;
++ fndiff+= 0x00004000;
++ fndiff-= _ifxhcd->lastframe ;
++ fndiff&= 0x00003FFF;
++ if(!fndiff) fndiff =1;
++
++ for (i = 0; i < num_channels; i++)
++ {
++ if(_ifxhcd->ifxhc[i].wait_for_sof && _ifxhcd->ifxhc[i].xfer_started)
++ {
++#ifdef __USE_TIMER_4_SOF__
++ if (_ifxhcd->ifxhc[i].wait_for_sof > fndiff) {
++ _ifxhcd->ifxhc[i].wait_for_sof -= fndiff;
++ } else {
++ _ifxhcd->ifxhc[i].wait_for_sof = 0;
++ }
++#else
++ _ifxhcd->ifxhc[i].wait_for_sof--;
++#endif
++ if(_ifxhcd->ifxhc[i].wait_for_sof==0)
++ {
++ hcint_data_t hcint= { .d32=0 };
++ hc_regs = _ifxhcd->core_if.hc_regs[i];
++
++ hcint.d32 =0xFFFFFFFF;
++ ifxusb_wreg(&hc_regs->hcint, hcint.d32);
++
++ hcint.d32=ifxusb_rreg(&hc_regs->hcintmsk);
++ hcint.b.nak =0;
++ hcint.b.ack =0;
++ /* == 20110901 AVM/WK Fix: We don't need NOT YET IRQ ==*/
++ hcint.b.nyet=0;
++ _ifxhcd->ifxhc[i].nak_countdown=_ifxhcd->ifxhc[i].nak_countdown_r;
++ if(_ifxhcd->ifxhc[i].nak_countdown_r)
++ hcint.b.nak =1;
++ ifxusb_wreg(&hc_regs->hcintmsk, hcint.d32);
++
++ /* AVM WK / BC 20100827
++ * FIX: Packet was ignored because of wrong Oddframe bit
++ */
++ if (_ifxhcd->ifxhc[i].ep_type == IFXUSB_EP_TYPE_INTR || _ifxhcd->ifxhc[i].ep_type == IFXUSB_EP_TYPE_ISOC)
++ {
++ hcchar_data_t hcchar;
++ hcchar.d32 = _ifxhcd->ifxhc[i].hcchar;
++ hfnum.d32 = ifxusb_rreg(&_ifxhcd->core_if.host_global_regs->hfnum);
++ /* 1 if _next_ frame is odd, 0 if it's even */
++ hcchar.b.oddfrm = (hfnum.b.frnum & 0x1) ? 0 : 1;
++ _ifxhcd->ifxhc[i].hcchar = hcchar.d32;
++ }
++
++ ifxusb_wreg(&hc_regs->hcchar, _ifxhcd->ifxhc[i].hcchar);
++
++ }
++ }
++ else
++ _ifxhcd->ifxhc[i].wait_for_sof=0;
++
++#ifdef __USE_TIMER_4_SOF__
++ if (_ifxhcd->ifxhc[i].wait_for_sof && (wait_for_sof > _ifxhcd->ifxhc[i].wait_for_sof)) {
++ wait_for_sof = _ifxhcd->ifxhc[i].wait_for_sof;
++ }
++#endif
++ }
++ }
++
++ // ISOC Active
++ #ifdef __EN_ISOC__
++ #error ISOC not supported: missing SOF code
++ epqh_entry = _ifxhcd->epqh_isoc_active.next;
++ while (epqh_entry != &_ifxhcd->epqh_isoc_active)
++ {
++ epqh = list_entry(epqh_entry, ifxhcd_epqh_t, epqh_list_entry);
++ epqh_entry = epqh_entry->next;
++ #ifdef __DYN_SOF_INTR__
++ with_count_down=1;
++ #endif
++ active_on+=update_interval_counter(epqh,fndiff);
++ }
++
++ // ISOC Ready
++ epqh_entry = _ifxhcd->epqh_isoc_ready.next;
++ while (epqh_entry != &_ifxhcd->epqh_isoc_ready)
++ {
++ epqh = list_entry(epqh_entry, ifxhcd_epqh_t, epqh_list_entry);
++ epqh_entry = epqh_entry->next;
++ #ifdef __DYN_SOF_INTR__
++ with_count_down=1;
++ #endif
++ ready_on+=update_interval_counter(epqh,fndiff);
++ }
++ #endif
++
++ // INTR Active
++ epqh_entry = _ifxhcd->epqh_intr_active.next;
++ while (epqh_entry != &_ifxhcd->epqh_intr_active)
++ {
++ epqh = list_entry(epqh_entry, ifxhcd_epqh_t, epqh_list_entry);
++ epqh_entry = epqh_entry->next;
++ #ifdef __DYN_SOF_INTR__
++ with_count_down=1;
++ #endif
++#ifdef __USE_TIMER_4_SOF__
++ if (update_interval_counter(epqh,fndiff)) {
++ active_on ++;
++ wait_for_sof = 1;
++ } else {
++ if (epqh->period_counter && (wait_for_sof > epqh->period_counter)) {
++ wait_for_sof = epqh->period_counter;
++ }
++ }
++#else
++ active_on+=update_interval_counter(epqh,fndiff);
++#endif
++ }
++
++ // INTR Ready
++ epqh_entry = _ifxhcd->epqh_intr_ready.next;
++ while (epqh_entry != &_ifxhcd->epqh_intr_ready)
++ {
++ epqh = list_entry(epqh_entry, ifxhcd_epqh_t, epqh_list_entry);
++ epqh_entry = epqh_entry->next;
++ #ifdef __DYN_SOF_INTR__
++ with_count_down=1;
++ #endif
++#ifdef __USE_TIMER_4_SOF__
++ if (update_interval_counter(epqh,fndiff)) {
++ ready_on ++;
++ wait_for_sof = 1;
++ } else {
++ if (epqh->period_counter && (wait_for_sof > epqh->period_counter)) {
++ wait_for_sof = epqh->period_counter;
++ }
++ }
++#else
++ ready_on+=update_interval_counter(epqh,fndiff);
++#endif
++ }
++
++ // Stdby
++ epqh_entry = _ifxhcd->epqh_stdby.next;
++ while (epqh_entry != &_ifxhcd->epqh_stdby)
++ {
++ epqh = list_entry(epqh_entry, ifxhcd_epqh_t, epqh_list_entry);
++ epqh_entry = epqh_entry->next;
++ if(epqh->period_counter > 0 ) {
++#ifdef __USE_TIMER_4_SOF__
++ if (epqh->period_counter > fndiff) {
++ epqh->period_counter -= fndiff;
++ } else {
++ epqh->period_counter = 0;
++ }
++#else
++ epqh->period_counter --;
++#endif
++ #ifdef __DYN_SOF_INTR__
++ with_count_down=1;
++ #endif
++ }
++ if(epqh->period_counter == 0) {
++ ifxhcd_epqh_idle_periodic(epqh);
++ }
++#ifdef __USE_TIMER_4_SOF__
++ else {
++ if (wait_for_sof > epqh->period_counter) {
++ wait_for_sof = epqh->period_counter;
++ }
++ }
++#endif
++ }
++ SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
++
++ if(ready_on)
++ select_eps(_ifxhcd);
++ else if(active_on)
++ process_channels(_ifxhcd);
++
++ /* Clear interrupt */
++ {
++ gint_data_t gintsts;
++ gintsts.d32=0;
++ gintsts.b.sofintr = 1;
++ ifxusb_wreg(&_ifxhcd->core_if.core_global_regs->gintsts, gintsts.d32);
++
++ #ifdef __DYN_SOF_INTR__
++ if(!with_count_down)
++ ifxusb_mreg(&_ifxhcd->core_if.core_global_regs->gintmsk, gintsts.d32,0);
++ #endif
++#ifdef __USE_TIMER_4_SOF__
++ wait_for_sof &= 0xFFFF; // reduce to 16 Bits.
++
++ if(wait_for_sof == 1) {
++ // enable SOF
++ gint_data_t gintsts;
++ gintsts.d32=0;
++ gintsts.b.sofintr = 1;
++ ifxusb_mreg(&_ifxhcd->core_if.core_global_regs->gintmsk, 0,gintsts.d32);
++ } else {
++ // disable SOF
++ ifxusb_mreg(&_ifxhcd->core_if.core_global_regs->gintmsk, gintsts.d32,0);
++ if (wait_for_sof > 1) {
++ // use timer, not SOF IRQ
++ hprt0_data_t hprt0;
++ ktime_t ktime;
++ hprt0.d32 = ifxusb_read_hprt0 (&_ifxhcd->core_if);
++ if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_HIGH_SPEED) {
++ ktime = ktime_set(0, wait_for_sof * 125 * 1000); /*--- wakeup in n*125usec ---*/
++ } else {
++ ktime = ktime_set(0, wait_for_sof * (1000*1000)); /*--- wakeup in n*1000usec ---*/
++ }
++ hrtimer_start(&_ifxhcd->hr_timer, ktime, HRTIMER_MODE_REL);
++ }
++ }
++#endif
++ }
++ _ifxhcd->lastframe=hfnum.b.frnum;
++ return 1;
++}
++
++
++
++/* There are multiple conditions that can cause a port interrupt. This function
++ * determines which interrupt conditions have occurred and handles them
++ * appropriately. */
++static int32_t handle_port_intr (ifxhcd_hcd_t *_ifxhcd)
++{
++ int retval = 0;
++ hprt0_data_t hprt0;
++ hprt0_data_t hprt0_modify;
++
++ hprt0.d32 =
++ hprt0_modify.d32 = ifxusb_rreg(_ifxhcd->core_if.hprt0);
++
++ /* Clear appropriate bits in HPRT0 to clear the interrupt bit in
++ * GINTSTS */
++
++ hprt0_modify.b.prtena = 0;
++ hprt0_modify.b.prtconndet = 0;
++ hprt0_modify.b.prtenchng = 0;
++ hprt0_modify.b.prtovrcurrchng = 0;
++
++ /* Port Connect Detected
++ * Set flag and clear if detected */
++ if (hprt0.b.prtconndet) {
++ IFX_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x "
++ "Port Connect Detected--\n", hprt0.d32);
++ _ifxhcd->flags.b.port_connect_status_change = 1;
++ _ifxhcd->flags.b.port_connect_status = 1;
++ hprt0_modify.b.prtconndet = 1;
++
++ /* The Hub driver asserts a reset when it sees port connect
++ * status change flag */
++ retval |= 1;
++ }
++
++ /* Port Enable Changed
++ * Clear if detected - Set internal flag if disabled */
++ if (hprt0.b.prtenchng) {
++
++ IFX_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x "
++ "Port Enable Changed--\n", hprt0.d32);
++ hprt0_modify.b.prtenchng = 1;
++ if (hprt0.b.prtena == 1)
++ /* Port has been enabled set the reset change flag */
++ _ifxhcd->flags.b.port_reset_change = 1;
++ else
++ _ifxhcd->flags.b.port_enable_change = 1;
++ retval |= 1;
++ }
++
++ /* Overcurrent Change Interrupt */
++
++ if (hprt0.b.prtovrcurrchng) {
++ IFX_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x "
++ "Port Overcurrent Changed--\n", hprt0.d32);
++ _ifxhcd->flags.b.port_over_current_change = 1;
++ hprt0_modify.b.prtovrcurrchng = 1;
++ retval |= 1;
++ }
++
++ /* Clear Port Interrupts */
++ ifxusb_wreg(_ifxhcd->core_if.hprt0, hprt0_modify.d32);
++ return retval;
++}
++
++/*
++ * This interrupt indicates that SUSPEND state has been detected on
++ * the USB.
++ * No Functioning in Host Mode
++ */
++static int32_t handle_usb_suspend_intr(ifxhcd_hcd_t *_ifxhcd)
++{
++ gint_data_t gintsts;
++ IFX_DEBUGP("USB SUSPEND RECEIVED!\n");
++ /* Clear interrupt */
++ gintsts.d32 = 0;
++ gintsts.b.usbsuspend = 1;
++ ifxusb_wreg(&_ifxhcd->core_if.core_global_regs->gintsts, gintsts.d32);
++ return 1;
++}
++
++/*
++ * This interrupt indicates that the IFXUSB controller has detected a
++ * resume or remote wakeup sequence. If the IFXUSB controller is in
++ * low power mode, the handler must brings the controller out of low
++ * power mode. The controller automatically begins resume
++ * signaling. The handler schedules a time to stop resume signaling.
++ */
++static int32_t handle_wakeup_detected_intr(ifxhcd_hcd_t *_ifxhcd)
++{
++ gint_data_t gintsts;
++ hprt0_data_t hprt0 = {.d32=0};
++ pcgcctl_data_t pcgcctl = {.d32=0};
++ ifxusb_core_if_t *core_if = &_ifxhcd->core_if;
++
++ IFX_DEBUGPL(DBG_ANY, "++Resume and Remote Wakeup Detected Interrupt++\n");
++
++ /*
++ * Clear the Resume after 70ms. (Need 20 ms minimum. Use 70 ms
++ * so that OPT tests pass with all PHYs).
++ */
++ /* Restart the Phy Clock */
++ pcgcctl.b.stoppclk = 1;
++ ifxusb_mreg(core_if->pcgcctl, pcgcctl.d32, 0);
++ UDELAY(10);
++
++ /* Now wait for 70 ms. */
++ hprt0.d32 = ifxusb_read_hprt0( core_if );
++ IFX_DEBUGPL(DBG_ANY,"Resume: HPRT0=%0x\n", hprt0.d32);
++ MDELAY(70);
++ hprt0.b.prtres = 0; /* Resume */
++ ifxusb_wreg(core_if->hprt0, hprt0.d32);
++ IFX_DEBUGPL(DBG_ANY,"Clear Resume: HPRT0=%0x\n", ifxusb_rreg(core_if->hprt0));
++
++ /* Clear interrupt */
++ gintsts.d32 = 0;
++ gintsts.b.wkupintr = 1;
++ ifxusb_wreg(&core_if->core_global_regs->gintsts, gintsts.d32);
++ return 1;
++}
++
++/*
++ * This interrupt indicates that a device is initiating the Session
++ * Request Protocol to request the host to turn on bus power so a new
++ * session can begin. The handler responds by turning on bus power. If
++ * the DWC_otg controller is in low power mode, the handler brings the
++ * controller out of low power mode before turning on bus power.
++ */
++static int32_t handle_session_req_intr(ifxhcd_hcd_t *_ifxhcd)
++{
++ /* Clear interrupt */
++ gint_data_t gintsts = { .d32 = 0 };
++ gintsts.b.sessreqintr = 1;
++ ifxusb_wreg(&_ifxhcd->core_if.core_global_regs->gintsts, gintsts.d32);
++ return 1;
++}
++
++/*
++ * This interrupt indicates that a device has been disconnected from
++ * the root port.
++ */
++static int32_t handle_disconnect_intr(ifxhcd_hcd_t *_ifxhcd)
++{
++ gint_data_t gintsts;
++
++ ifxhcd_disconnect(_ifxhcd);
++
++ gintsts.d32 = 0;
++ gintsts.b.disconnect = 1;
++ ifxusb_wreg(&_ifxhcd->core_if.core_global_regs->gintsts, gintsts.d32);
++ return 1;
++}
++
++/*
++ * This function handles the Connector ID Status Change Interrupt. It
++ * reads the OTG Interrupt Register (GOTCTL) to determine whether this
++ * is a Device to Host Mode transition or a Host Mode to Device
++ * Transition.
++ * This only occurs when the cable is connected/removed from the PHY
++ * connector.
++ */
++static int32_t handle_conn_id_status_change_intr(ifxhcd_hcd_t *_ifxhcd)
++{
++ gint_data_t gintsts;
++
++ IFX_WARN("ID Status Change Interrupt: currently in %s mode\n",
++ ifxusb_mode(&_ifxhcd->core_if) ? "Host" : "Device");
++
++ gintsts.d32 = 0;
++ gintsts.b.conidstschng = 1;
++ ifxusb_wreg(&_ifxhcd->core_if.core_global_regs->gintsts, gintsts.d32);
++ return 1;
++}
++
++static int32_t handle_otg_intr(ifxhcd_hcd_t *_ifxhcd)
++{
++ ifxusb_core_global_regs_t *global_regs = _ifxhcd->core_if.core_global_regs;
++ gotgint_data_t gotgint;
++ gotgint.d32 = ifxusb_rreg( &global_regs->gotgint);
++ /* Clear GOTGINT */
++ ifxusb_wreg (&global_regs->gotgint, gotgint.d32);
++ return 1;
++}
++
++/** This function will log a debug message */
++static int32_t handle_mode_mismatch_intr(ifxhcd_hcd_t *_ifxhcd)
++{
++ gint_data_t gintsts;
++
++ IFX_WARN("Mode Mismatch Interrupt: currently in %s mode\n",
++ ifxusb_mode(&_ifxhcd->core_if) ? "Host" : "Device");
++ gintsts.d32 = 0;
++ gintsts.b.modemismatch = 1;
++ ifxusb_wreg(&_ifxhcd->core_if.core_global_regs->gintsts, gintsts.d32);
++ return 1;
++}
++
++/** This function handles interrupts for the HCD. */
++int32_t ifxhcd_handle_intr (ifxhcd_hcd_t *_ifxhcd)
++{
++ int retval = 0;
++
++ ifxusb_core_if_t *core_if = &_ifxhcd->core_if;
++ /* AVM/BC 20101111 Unnecesary variable removed*/
++ //gint_data_t gintsts,gintsts2;
++ gint_data_t gintsts;
++
++ /* Check if HOST Mode */
++ if (ifxusb_is_device_mode(core_if))
++ {
++ IFX_ERROR("%s() CRITICAL! IN DEVICE MODE\n", __func__);
++ return 0;
++ }
++
++ gintsts.d32 = ifxusb_read_core_intr(core_if);
++
++ if (!gintsts.d32)
++ return 0;
++
++ //Common INT
++ if (gintsts.b.modemismatch)
++ {
++ retval |= handle_mode_mismatch_intr(_ifxhcd);
++ gintsts.b.modemismatch=0;
++ }
++ if (gintsts.b.otgintr)
++ {
++ retval |= handle_otg_intr(_ifxhcd);
++ gintsts.b.otgintr=0;
++ }
++ if (gintsts.b.conidstschng)
++ {
++ retval |= handle_conn_id_status_change_intr(_ifxhcd);
++ gintsts.b.conidstschng=0;
++ }
++ if (gintsts.b.disconnect)
++ {
++ retval |= handle_disconnect_intr(_ifxhcd);
++ gintsts.b.disconnect=0;
++ }
++ if (gintsts.b.sessreqintr)
++ {
++ retval |= handle_session_req_intr(_ifxhcd);
++ gintsts.b.sessreqintr=0;
++ }
++ if (gintsts.b.wkupintr)
++ {
++ retval |= handle_wakeup_detected_intr(_ifxhcd);
++ gintsts.b.wkupintr=0;
++ }
++ if (gintsts.b.usbsuspend)
++ {
++ retval |= handle_usb_suspend_intr(_ifxhcd);
++ gintsts.b.usbsuspend=0;
++ }
++
++ //Host Int
++ if (gintsts.b.sofintr)
++ {
++ retval |= handle_sof_intr (_ifxhcd);
++ gintsts.b.sofintr=0;
++ }
++ if (gintsts.b.portintr)
++ {
++ retval |= handle_port_intr (_ifxhcd);
++ gintsts.b.portintr=0;
++ }
++ if (gintsts.b.hcintr)
++ {
++ int i;
++ haint_data_t haint;
++ haint.d32 = ifxusb_read_host_all_channels_intr(core_if);
++ for (i=0; i< core_if->params.host_channels; i++)
++ if (haint.b2.chint & (1 << i))
++ retval |= handle_hc_n_intr (_ifxhcd, i);
++ gintsts.b.hcintr=0;
++ }
++ return retval;
++}
+diff --git a/drivers/usb/ifxhcd/ifxhcd_queue.c b/drivers/usb/ifxhcd/ifxhcd_queue.c
+new file mode 100644
+index 0000000..8f9dd25
+--- /dev/null
++++ b/drivers/usb/ifxhcd/ifxhcd_queue.c
+@@ -0,0 +1,418 @@
++/*****************************************************************************
++ ** FILE NAME : ifxhcd_queue.c
++ ** PROJECT : IFX USB sub-system V3
++ ** MODULES : IFX USB sub-system Host and Device driver
++ ** SRC VERSION : 1.0
++ ** DATE : 1/Jan/2009
++ ** AUTHOR : Chen, Howard
++ ** DESCRIPTION : This file contains the functions to manage Queue Heads and Queue
++ ** Transfer Descriptors.
++ *****************************************************************************/
++
++/*!
++ \file ifxhcd_queue.c
++ \ingroup IFXUSB_DRIVER_V3
++ \brief This file contains the functions to manage Queue Heads and Queue
++ Transfer Descriptors.
++*/
++#include <linux/version.h>
++#include "ifxusb_version.h"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/errno.h>
++#include <linux/list.h>
++#include <linux/interrupt.h>
++#include <linux/string.h>
++
++#include "ifxusb_plat.h"
++#include "ifxusb_regs.h"
++#include "ifxusb_cif.h"
++#include "ifxhcd.h"
++
++#ifdef __EPQD_DESTROY_TIMEOUT__
++ #define epqh_self_destroy_timeout 5
++ static void eqph_destroy_func(unsigned long _ptr)
++ {
++ ifxhcd_epqh_t *epqh=(ifxhcd_epqh_t *)_ptr;
++ if(epqh)
++ {
++ ifxhcd_epqh_free (epqh);
++ }
++ }
++#endif
++
++#define SCHEDULE_SLOP 10
++
++/*!
++ \brief This function allocates and initializes a EPQH.
++
++ \param _ifxhcd The HCD state structure for the USB Host controller.
++ \param[in] _urb Holds the information about the device/endpoint that we need
++ to initialize the EPQH.
++
++ \return Returns pointer to the newly allocated EPQH, or NULL on error.
++ */
++ifxhcd_epqh_t *ifxhcd_epqh_create (ifxhcd_hcd_t *_ifxhcd, struct urb *_urb)
++{
++ ifxhcd_epqh_t *epqh;
++
++ hprt0_data_t hprt0;
++ struct usb_host_endpoint *sysep = ifxhcd_urb_to_endpoint(_urb);
++
++ /* Allocate memory */
++// epqh=(ifxhcd_epqh_t *) kmalloc (sizeof(ifxhcd_epqh_t), GFP_KERNEL);
++ epqh=(ifxhcd_epqh_t *) kmalloc (sizeof(ifxhcd_epqh_t), GFP_ATOMIC);
++
++ if(epqh == NULL)
++ return NULL;
++
++ memset (epqh, 0, sizeof (ifxhcd_epqh_t));
++
++ epqh->sysep=sysep;
++
++ /* Initialize EPQH */
++ switch (usb_pipetype(_urb->pipe))
++ {
++ case PIPE_CONTROL : epqh->ep_type = IFXUSB_EP_TYPE_CTRL; break;
++ case PIPE_BULK : epqh->ep_type = IFXUSB_EP_TYPE_BULK; break;
++ case PIPE_ISOCHRONOUS: epqh->ep_type = IFXUSB_EP_TYPE_ISOC; break;
++ case PIPE_INTERRUPT : epqh->ep_type = IFXUSB_EP_TYPE_INTR; break;
++ }
++
++ //epqh->data_toggle = IFXUSB_HC_PID_DATA0;
++
++ epqh->mps = usb_maxpacket(_urb->dev, _urb->pipe, !(usb_pipein(_urb->pipe)));
++
++ hprt0.d32 = ifxusb_read_hprt0 (&_ifxhcd->core_if);
++
++ INIT_LIST_HEAD(&epqh->urbd_list);
++ INIT_LIST_HEAD(&epqh->epqh_list_entry);
++ epqh->hc = NULL;
++
++ epqh->dump_buf = ifxusb_alloc_buf(epqh->mps, 0);
++
++ /* FS/LS Enpoint on HS Hub
++ * NOT virtual root hub */
++ epqh->need_split = 0;
++ epqh->pkt_count_limit=0;
++ if(epqh->ep_type == IFXUSB_EP_TYPE_BULK && !(usb_pipein(_urb->pipe)) )
++ epqh->pkt_count_limit=4;
++ if (hprt0.b.prtspd == IFXUSB_HPRT0_PRTSPD_HIGH_SPEED &&
++ ((_urb->dev->speed == USB_SPEED_LOW) ||
++ (_urb->dev->speed == USB_SPEED_FULL)) &&
++ (_urb->dev->tt) && (_urb->dev->tt->hub->devnum != 1))
++ {
++ IFX_DEBUGPL(DBG_HCD, "QH init: EP %d: TT found at hub addr %d, for port %d\n",
++ usb_pipeendpoint(_urb->pipe), _urb->dev->tt->hub->devnum,
++ _urb->dev->ttport);
++ epqh->need_split = 1;
++ epqh->pkt_count_limit=1;
++ }
++
++ if (epqh->ep_type == IFXUSB_EP_TYPE_INTR ||
++ epqh->ep_type == IFXUSB_EP_TYPE_ISOC)
++ {
++ /* Compute scheduling parameters once and save them. */
++ epqh->interval = _urb->interval;
++ if(epqh->need_split)
++ epqh->interval *= 8;
++ }
++
++ epqh->period_counter=0;
++ epqh->is_active=0;
++
++ #ifdef __EPQD_DESTROY_TIMEOUT__
++ /* Start a timer for this transfer. */
++ init_timer(&epqh->destroy_timer);
++ epqh->destroy_timer.function = eqph_destroy_func;
++ epqh->destroy_timer.data = (unsigned long)(epqh);
++ #endif
++
++ #ifdef __DEBUG__
++ IFX_DEBUGPL(DBG_HCD , "IFXUSB HCD EPQH Initialized\n");
++ IFX_DEBUGPL(DBG_HCDV, "IFXUSB HCD EPQH - epqh = %p\n", epqh);
++ IFX_DEBUGPL(DBG_HCDV, "IFXUSB HCD EPQH - Device Address = %d EP %d, %s\n",
++ _urb->dev->devnum,
++ usb_pipeendpoint(_urb->pipe),
++ usb_pipein(_urb->pipe) == USB_DIR_IN ? "IN" : "OUT");
++ IFX_DEBUGPL(DBG_HCDV, "IFXUSB HCD EPQH - Speed = %s\n",
++ ({ char *speed; switch (_urb->dev->speed) {
++ case USB_SPEED_LOW: speed = "low" ; break;
++ case USB_SPEED_FULL: speed = "full"; break;
++ case USB_SPEED_HIGH: speed = "high"; break;
++ default: speed = "?"; break;
++ }; speed;}));
++ IFX_DEBUGPL(DBG_HCDV, "IFXUSB HCD EPQH - Type = %s\n",
++ ({
++ char *type; switch (epqh->ep_type)
++ {
++ case IFXUSB_EP_TYPE_ISOC: type = "isochronous"; break;
++ case IFXUSB_EP_TYPE_INTR: type = "interrupt" ; break;
++ case IFXUSB_EP_TYPE_CTRL: type = "control" ; break;
++ case IFXUSB_EP_TYPE_BULK: type = "bulk" ; break;
++ default: type = "?"; break;
++ };
++ type;
++ }));
++ if (epqh->ep_type == IFXUSB_EP_TYPE_INTR)
++ IFX_DEBUGPL(DBG_HCDV, "IFXUSB HCD EPQH - interval = %d\n", epqh->interval);
++ #endif
++
++ return epqh;
++}
++
++
++
++
++
++
++/*!
++ \brief Free the EPQH. EPQH should already be removed from a list.
++ URBD list should already be empty if called from URB Dequeue.
++
++ \param[in] _epqh The EPQH to free.
++ */
++void ifxhcd_epqh_free (ifxhcd_epqh_t *_epqh)
++{
++ unsigned long flags;
++
++ if(_epqh->sysep) _epqh->sysep->hcpriv=NULL;
++ _epqh->sysep=NULL;
++
++ if(!_epqh)
++ return;
++
++ /* Free each QTD in the QTD list */
++ local_irq_save (flags);
++ if (!list_empty(&_epqh->urbd_list))
++ IFX_WARN("%s() invalid epqh state\n",__func__);
++
++ #if defined(__UNALIGNED_BUFFER_ADJ__)
++ if(_epqh->aligned_buf)
++ ifxusb_free_buf(_epqh->aligned_buf);
++ if(_epqh->aligned_setup)
++ ifxusb_free_buf(_epqh->aligned_setup);
++ #endif
++
++ if (!list_empty(&_epqh->epqh_list_entry))
++ list_del_init(&_epqh->epqh_list_entry);
++
++ #ifdef __EPQD_DESTROY_TIMEOUT__
++ del_timer(&_epqh->destroy_timer);
++ #endif
++ if(_epqh->dump_buf)
++ ifxusb_free_buf(_epqh->dump_buf);
++ _epqh->dump_buf=0;
++
++
++ kfree (_epqh);
++ local_irq_restore (flags);
++}
++
++/*!
++ \brief This function adds a EPQH to
++
++ \return 0 if successful, negative error code otherwise.
++ */
++void ifxhcd_epqh_ready(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh)
++{
++ unsigned long flags;
++ local_irq_save(flags);
++ if (list_empty(&_epqh->epqh_list_entry))
++ {
++ #ifdef __EN_ISOC__
++ if (_epqh->ep_type == IFXUSB_EP_TYPE_ISOC)
++ list_add_tail(&_epqh->epqh_list_entry, &_ifxhcd->epqh_isoc_ready);
++ else
++ #endif
++ if(_epqh->ep_type == IFXUSB_EP_TYPE_INTR)
++ list_add_tail(&_epqh->epqh_list_entry, &_ifxhcd->epqh_intr_ready);
++ else
++ list_add_tail(&_epqh->epqh_list_entry, &_ifxhcd->epqh_np_ready);
++ _epqh->is_active=0;
++ }
++ else if(!_epqh->is_active)
++ {
++ #ifdef __EN_ISOC__
++ if (_epqh->ep_type == IFXUSB_EP_TYPE_ISOC)
++ list_move_tail(&_epqh->epqh_list_entry, &_ifxhcd->epqh_isoc_ready);
++ else
++ #endif
++ if(_epqh->ep_type == IFXUSB_EP_TYPE_INTR)
++ list_move_tail(&_epqh->epqh_list_entry, &_ifxhcd->epqh_intr_ready);
++ else
++ list_move_tail(&_epqh->epqh_list_entry, &_ifxhcd->epqh_np_ready);
++ }
++ #ifdef __EPQD_DESTROY_TIMEOUT__
++ del_timer(&_epqh->destroy_timer);
++ #endif
++ local_irq_restore(flags);
++}
++
++void ifxhcd_epqh_active(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh)
++{
++ unsigned long flags;
++ local_irq_save(flags);
++ if (list_empty(&_epqh->epqh_list_entry))
++ IFX_WARN("%s() invalid epqh state\n",__func__);
++ #ifdef __EN_ISOC__
++ if (_epqh->ep_type == IFXUSB_EP_TYPE_ISOC)
++ list_move_tail(&_epqh->epqh_list_entry, &_ifxhcd->epqh_isoc_active);
++ else
++ #endif
++ if(_epqh->ep_type == IFXUSB_EP_TYPE_INTR)
++ list_move_tail(&_epqh->epqh_list_entry, &_ifxhcd->epqh_intr_active);
++ else
++ list_move_tail(&_epqh->epqh_list_entry, &_ifxhcd->epqh_np_active);
++ _epqh->is_active=1;
++ #ifdef __EPQD_DESTROY_TIMEOUT__
++ del_timer(&_epqh->destroy_timer);
++ #endif
++ local_irq_restore(flags);
++}
++
++void ifxhcd_epqh_idle(ifxhcd_hcd_t *_ifxhcd, ifxhcd_epqh_t *_epqh)
++{
++ unsigned long flags;
++ local_irq_save(flags);
++
++ if (list_empty(&_epqh->urbd_list))
++ {
++ if(_epqh->ep_type == IFXUSB_EP_TYPE_ISOC || _epqh->ep_type == IFXUSB_EP_TYPE_INTR)
++ {
++ list_move_tail(&_epqh->epqh_list_entry, &_ifxhcd->epqh_stdby);
++ }
++ else
++ {
++ list_del_init(&_epqh->epqh_list_entry);
++ #ifdef __EPQD_DESTROY_TIMEOUT__
++ del_timer(&_epqh->destroy_timer);
++ _epqh->destroy_timer.expires = jiffies + (HZ*epqh_self_destroy_timeout);
++ add_timer(&_epqh->destroy_timer );
++ #endif
++ }
++ }
++ else
++ {
++ #ifdef __EN_ISOC__
++ if (_epqh->ep_type == IFXUSB_EP_TYPE_ISOC)
++ list_move_tail(&_epqh->epqh_list_entry, &_ifxhcd->epqh_isoc_ready);
++ else
++ #endif
++ if(_epqh->ep_type == IFXUSB_EP_TYPE_INTR)
++ list_move_tail(&_epqh->epqh_list_entry, &_ifxhcd->epqh_intr_ready);
++ else
++ list_move_tail(&_epqh->epqh_list_entry, &_ifxhcd->epqh_np_ready);
++ }
++ _epqh->is_active=0;
++ local_irq_restore(flags);
++}
++
++
++void ifxhcd_epqh_idle_periodic(ifxhcd_epqh_t *_epqh)
++{
++ unsigned long flags;
++ if(_epqh->ep_type != IFXUSB_EP_TYPE_ISOC && _epqh->ep_type != IFXUSB_EP_TYPE_INTR)
++ return;
++
++ local_irq_save(flags);
++
++ if (list_empty(&_epqh->epqh_list_entry))
++ IFX_WARN("%s() invalid epqh state\n",__func__);
++ if (!list_empty(&_epqh->urbd_list))
++ IFX_WARN("%s() invalid epqh state(not empty)\n",__func__);
++
++ _epqh->is_active=0;
++ list_del_init(&_epqh->epqh_list_entry);
++ #ifdef __EPQD_DESTROY_TIMEOUT__
++ del_timer(&_epqh->destroy_timer);
++ _epqh->destroy_timer.expires = jiffies + (HZ*epqh_self_destroy_timeout);
++ add_timer(&_epqh->destroy_timer );
++ #endif
++
++ local_irq_restore(flags);
++}
++
++
++int ifxhcd_urbd_create (ifxhcd_hcd_t *_ifxhcd,struct urb *_urb)
++{
++ ifxhcd_urbd_t *urbd;
++ struct usb_host_endpoint *sysep;
++ ifxhcd_epqh_t *epqh;
++ unsigned long flags;
++ /* == AVM/WK 20100714 retval correctly initialized ==*/
++ int retval = -ENOMEM;
++
++ /*== AVM/BC 20100630 - Spinlock ==*/
++ //local_irq_save(flags);
++ SPIN_LOCK_IRQSAVE(&_ifxhcd->lock, flags);
++
++// urbd = (ifxhcd_urbd_t *) kmalloc (sizeof(ifxhcd_urbd_t), GFP_KERNEL);
++ urbd = (ifxhcd_urbd_t *) kmalloc (sizeof(ifxhcd_urbd_t), GFP_ATOMIC);
++ if (urbd != NULL) /* Initializes a QTD structure.*/
++ {
++ retval = 0;
++ memset (urbd, 0, sizeof (ifxhcd_urbd_t));
++
++ sysep = ifxhcd_urb_to_endpoint(_urb);
++ epqh = (ifxhcd_epqh_t *)sysep->hcpriv;
++ if (epqh == NULL)
++ {
++ epqh = ifxhcd_epqh_create (_ifxhcd, _urb);
++ if (epqh == NULL)
++ {
++ retval = -ENOSPC;
++ kfree(urbd);
++ //local_irq_restore (flags);
++ SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
++ return retval;
++ }
++ sysep->hcpriv = epqh;
++ }
++
++ INIT_LIST_HEAD(&urbd->urbd_list_entry);
++
++ /*== AVM/BC 20100630 - 2.6.28 needs HCD link/unlink URBs ==*/
++ retval = usb_hcd_link_urb_to_ep(ifxhcd_to_syshcd(_ifxhcd), _urb);
++
++ if (unlikely(retval)){
++ kfree(urbd);
++ kfree(epqh);
++ SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
++ return retval;
++ }
++
++ list_add_tail(&urbd->urbd_list_entry, &epqh->urbd_list);
++ urbd->urb = _urb;
++ _urb->hcpriv = urbd;
++
++ urbd->epqh=epqh;
++ urbd->is_in=usb_pipein(_urb->pipe) ? 1 : 0;;
++
++ urbd->xfer_len=_urb->transfer_buffer_length;
++#define URB_NO_SETUP_DMA_MAP 0
++
++ if(urbd->xfer_len>0)
++ {
++ if(_urb->transfer_flags && URB_NO_TRANSFER_DMA_MAP)
++ urbd->xfer_buff = (uint8_t *) (KSEG1ADDR((uint32_t *)_urb->transfer_dma));
++ else
++ urbd->xfer_buff = (uint8_t *) _urb->transfer_buffer;
++ }
++ if(epqh->ep_type == IFXUSB_EP_TYPE_CTRL)
++ {
++ if(_urb->transfer_flags && URB_NO_SETUP_DMA_MAP)
++ urbd->setup_buff = (uint8_t *) (KSEG1ADDR((uint32_t *)_urb->setup_dma));
++ else
++ urbd->setup_buff = (uint8_t *) _urb->setup_packet;
++ }
++ }
++ //local_irq_restore (flags);
++ SPIN_UNLOCK_IRQRESTORE(&_ifxhcd->lock, flags);
++ return retval;
++}
++
+diff --git a/drivers/usb/ifxhcd/ifxusb_cif.c b/drivers/usb/ifxhcd/ifxusb_cif.c
+new file mode 100644
+index 0000000..10b1292
+--- /dev/null
++++ b/drivers/usb/ifxhcd/ifxusb_cif.c
+@@ -0,0 +1,1458 @@
++/*****************************************************************************
++ ** FILE NAME : ifxusb_cif.c
++ ** PROJECT : IFX USB sub-system V3
++ ** MODULES : IFX USB sub-system Host and Device driver
++ ** SRC VERSION : 1.0
++ ** DATE : 1/Jan/2009
++ ** AUTHOR : Chen, Howard
++ ** DESCRIPTION : The Core Interface provides basic services for accessing and
++ ** managing the IFX USB hardware. These services are used by both the
++ ** Host Controller Driver and the Peripheral Controller Driver.
++ *****************************************************************************/
++
++/*!
++ \file ifxusb_cif.c
++ \ingroup IFXUSB_DRIVER_V3
++ \brief This file contains the interface to the IFX USB Core.
++*/
++
++#include <linux/clk.h>
++#include <linux/version.h>
++#include "ifxusb_version.h"
++
++#include <asm/byteorder.h>
++#include <asm/unaligned.h>
++
++
++#include <linux/jiffies.h>
++#include <linux/platform_device.h>
++#include <linux/kernel.h>
++#include <linux/ioport.h>
++
++#if defined(__UEIP__)
++// #include <asm/ifx/ifx_pmu.h>
++// #include <ifx_pmu.h>
++#endif
++
++
++#include "ifxusb_plat.h"
++#include "ifxusb_regs.h"
++#include "ifxusb_cif.h"
++
++
++#ifdef __IS_DEVICE__
++ #include "ifxpcd.h"
++#endif
++
++#ifdef __IS_HOST__
++ #include "ifxhcd.h"
++#endif
++
++#include <linux/mm.h>
++
++#include <linux/gfp.h>
++
++#if defined(__UEIP__)
++// #include <asm/ifx/ifx_board.h>
++ //#include <ifx_board.h>
++#endif
++
++//#include <asm/ifx/ifx_gpio.h>
++//#include <ifx_gpio.h>
++#if defined(__UEIP__)
++// #include <asm/ifx/ifx_led.h>
++ //#include <ifx_led.h>
++#endif
++
++
++
++#if defined(__UEIP__)
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__) || defined(__IS_AMAZON_SE__)
++ #ifndef USB_CTRL_PMU_SETUP
++ #define USB_CTRL_PMU_SETUP(__x) USB0_CTRL_PMU_SETUP(__x)
++ #endif
++ #ifndef USB_PHY_PMU_SETUP
++ #define USB_PHY_PMU_SETUP(__x) USB0_PHY_PMU_SETUP(__x)
++ #endif
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__) || defined(__IS_AMAZON_SE__)
++#endif // defined(__UEIP__)
++
++/*!
++ \brief This function is called to allocate buffer of specified size.
++ The allocated buffer is mapped into DMA accessable address.
++ \param size Size in BYTE to be allocated
++ \param clear 0: don't do clear after buffer allocated, other: do clear to zero
++ \return 0/NULL: Fail; uncached pointer of allocated buffer
++ */
++void *ifxusb_alloc_buf(size_t size, int clear)
++{
++ uint32_t *cached,*uncached;
++ uint32_t totalsize,page;
++
++ if(!size)
++ return 0;
++
++ size=(size+3)&0xFFFFFFFC;
++ totalsize=size + 12;
++ page=get_order(totalsize);
++
++ cached = (void *) __get_free_pages(( GFP_ATOMIC | GFP_DMA), page);
++
++ if(!cached)
++ {
++ IFX_PRINT("%s Allocation Failed size:%d\n",__func__,size);
++ return NULL;
++ }
++
++ uncached = (uint32_t *)(KSEG1ADDR(cached));
++ if(clear)
++ memset(uncached, 0, totalsize);
++
++ *(uncached+0)=totalsize;
++ *(uncached+1)=page;
++ *(uncached+2)=(uint32_t)cached;
++ return (void *)(uncached+3);
++}
++
++
++/*!
++ \brief This function is called to free allocated buffer.
++ \param vaddr the uncached pointer of the buffer
++ */
++void ifxusb_free_buf(void *vaddr)
++{
++ uint32_t totalsize,page;
++ uint32_t *cached,*uncached;
++
++ if(vaddr != NULL)
++ {
++ uncached=vaddr;
++ uncached-=3;
++ totalsize=*(uncached+0);
++ page=*(uncached+1);
++ cached=(uint32_t *)(*(uncached+2));
++ if(totalsize && page==get_order(totalsize) && cached==(uint32_t *)(KSEG0ADDR(uncached)))
++ {
++ free_pages((unsigned long)cached, page);
++ return;
++ }
++ // the memory is not allocated by ifxusb_alloc_buf. Allowed but must be careful.
++ return;
++ }
++}
++
++
++
++/*!
++ \brief This function is called to initialize the IFXUSB CSR data
++ structures. The register addresses in the device and host
++ structures are initialized from the base address supplied by the
++ caller. The calling function must make the OS calls to get the
++ base address of the IFXUSB controller registers.
++
++ \param _core_if Pointer of core_if structure
++ \param _irq irq number
++ \param _reg_base_addr Base address of IFXUSB core registers
++ \param _fifo_base_addr Fifo base address
++ \param _fifo_dbg_addr Fifo debug address
++ \return 0: success;
++ */
++int ifxusb_core_if_init(ifxusb_core_if_t *_core_if,
++ int _irq,
++ uint32_t _reg_base_addr,
++ uint32_t _fifo_base_addr,
++ uint32_t _fifo_dbg_addr)
++{
++ int retval = 0;
++ uint32_t *reg_base =NULL;
++ uint32_t *fifo_base =NULL;
++ uint32_t *fifo_dbg =NULL;
++
++ int i;
++
++ IFX_DEBUGPL(DBG_CILV, "%s(%p,%d,0x%08X,0x%08X,0x%08X)\n", __func__,
++ _core_if,
++ _irq,
++ _reg_base_addr,
++ _fifo_base_addr,
++ _fifo_dbg_addr);
++
++ if( _core_if == NULL)
++ {
++ IFX_ERROR("%s() invalid _core_if\n", __func__);
++ retval = -ENOMEM;
++ goto fail;
++ }
++
++ //memset(_core_if, 0, sizeof(ifxusb_core_if_t));
++
++ _core_if->irq=_irq;
++
++ reg_base =ioremap_nocache(_reg_base_addr , IFXUSB_IOMEM_SIZE );
++ fifo_base =ioremap_nocache(_fifo_base_addr, IFXUSB_FIFOMEM_SIZE);
++ fifo_dbg =ioremap_nocache(_fifo_dbg_addr , IFXUSB_FIFODBG_SIZE);
++ if( reg_base == NULL || fifo_base == NULL || fifo_dbg == NULL)
++ {
++ IFX_ERROR("%s() usb ioremap() failed\n", __func__);
++ retval = -ENOMEM;
++ goto fail;
++ }
++
++ _core_if->core_global_regs = (ifxusb_core_global_regs_t *)reg_base;
++
++ /*
++ * Attempt to ensure this device is really a IFXUSB Controller.
++ * Read and verify the SNPSID register contents. The value should be
++ * 0x45F42XXX
++ */
++ {
++ int32_t snpsid;
++ snpsid = ifxusb_rreg(&_core_if->core_global_regs->gsnpsid);
++ if ((snpsid & 0xFFFFF000) != 0x4F542000)
++ {
++ IFX_ERROR("%s() snpsid error(0x%08x) failed\n", __func__,snpsid);
++ retval = -EINVAL;
++ goto fail;
++ }
++ _core_if->snpsid=snpsid;
++ }
++
++ #ifdef __IS_HOST__
++ _core_if->host_global_regs = (ifxusb_host_global_regs_t *)
++ ((uint32_t)reg_base + IFXUSB_HOST_GLOBAL_REG_OFFSET);
++ _core_if->hprt0 = (uint32_t*)((uint32_t)reg_base + IFXUSB_HOST_PORT_REGS_OFFSET);
++
++ for (i=0; i<MAX_EPS_CHANNELS; i++)
++ {
++ _core_if->hc_regs[i] = (ifxusb_hc_regs_t *)
++ ((uint32_t)reg_base + IFXUSB_HOST_CHAN_REGS_OFFSET +
++ (i * IFXUSB_CHAN_REGS_OFFSET));
++ IFX_DEBUGPL(DBG_CILV, "hc_reg[%d]->hcchar=%p\n",
++ i, &_core_if->hc_regs[i]->hcchar);
++ }
++ #endif //__IS_HOST__
++
++ #ifdef __IS_DEVICE__
++ _core_if->dev_global_regs =
++ (ifxusb_device_global_regs_t *)((uint32_t)reg_base + IFXUSB_DEV_GLOBAL_REG_OFFSET);
++
++ for (i=0; i<MAX_EPS_CHANNELS; i++)
++ {
++ _core_if->in_ep_regs[i] = (ifxusb_dev_in_ep_regs_t *)
++ ((uint32_t)reg_base + IFXUSB_DEV_IN_EP_REG_OFFSET +
++ (i * IFXUSB_EP_REG_OFFSET));
++ _core_if->out_ep_regs[i] = (ifxusb_dev_out_ep_regs_t *)
++ ((uint32_t)reg_base + IFXUSB_DEV_OUT_EP_REG_OFFSET +
++ (i * IFXUSB_EP_REG_OFFSET));
++ IFX_DEBUGPL(DBG_CILV, "in_ep_regs[%d]->diepctl=%p/%p %p/0x%08X/0x%08X\n",
++ i, &_core_if->in_ep_regs[i]->diepctl, _core_if->in_ep_regs[i],
++ reg_base,IFXUSB_DEV_IN_EP_REG_OFFSET,(i * IFXUSB_EP_REG_OFFSET)
++ );
++ IFX_DEBUGPL(DBG_CILV, "out_ep_regs[%d]->doepctl=%p/%p %p/0x%08X/0x%08X\n",
++ i, &_core_if->out_ep_regs[i]->doepctl, _core_if->out_ep_regs[i],
++ reg_base,IFXUSB_DEV_OUT_EP_REG_OFFSET,(i * IFXUSB_EP_REG_OFFSET)
++ );
++ }
++ #endif //__IS_DEVICE__
++
++ /* Setting the FIFO and other Address. */
++ for (i=0; i<MAX_EPS_CHANNELS; i++)
++ {
++ _core_if->data_fifo[i] = fifo_base + (i * IFXUSB_DATA_FIFO_SIZE);
++ IFX_DEBUGPL(DBG_CILV, "data_fifo[%d]=0x%08x\n",
++ i, (unsigned)_core_if->data_fifo[i]);
++ }
++
++ _core_if->data_fifo_dbg = fifo_dbg;
++ _core_if->pcgcctl = (uint32_t*)(((uint32_t)reg_base) + IFXUSB_PCGCCTL_OFFSET);
++
++ /*
++ * Store the contents of the hardware configuration registers here for
++ * easy access later.
++ */
++ _core_if->hwcfg1.d32 = ifxusb_rreg(&_core_if->core_global_regs->ghwcfg1);
++ _core_if->hwcfg2.d32 = ifxusb_rreg(&_core_if->core_global_regs->ghwcfg2);
++ _core_if->hwcfg3.d32 = ifxusb_rreg(&_core_if->core_global_regs->ghwcfg3);
++ _core_if->hwcfg4.d32 = ifxusb_rreg(&_core_if->core_global_regs->ghwcfg4);
++
++ IFX_DEBUGPL(DBG_CILV,"hwcfg1=%08x\n",_core_if->hwcfg1.d32);
++ IFX_DEBUGPL(DBG_CILV,"hwcfg2=%08x\n",_core_if->hwcfg2.d32);
++ IFX_DEBUGPL(DBG_CILV,"hwcfg3=%08x\n",_core_if->hwcfg3.d32);
++ IFX_DEBUGPL(DBG_CILV,"hwcfg4=%08x\n",_core_if->hwcfg4.d32);
++
++
++ #ifdef __DED_FIFO__
++ IFX_PRINT("Waiting for PHY Clock Lock!\n");
++ while(!( ifxusb_rreg(&_core_if->core_global_regs->grxfsiz) & (1<<9)))
++ {
++ }
++ IFX_PRINT("PHY Clock Locked!\n");
++ //ifxusb_clean_spram(_core_if,128*1024/4);
++ #endif
++
++ /* Create new workqueue and init works */
++#if 0
++ _core_if->wq_usb = create_singlethread_workqueue(_core_if->core_name);
++
++ if(_core_if->wq_usb == 0)
++ {
++ IFX_DEBUGPL(DBG_CIL, "Creation of wq_usb failed\n");
++ retval = -EINVAL;
++ goto fail;
++ }
++
++ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
++ INIT_WORK(&core_if->w_conn_id, w_conn_id_status_change, core_if);
++ INIT_WORK(&core_if->w_wkp, w_wakeup_detected, core_if);
++ #else
++ INIT_WORK(&core_if->w_conn_id, w_conn_id_status_change);
++ INIT_DELAYED_WORK(&core_if->w_wkp, w_wakeup_detected);
++ #endif
++#endif
++ return 0;
++
++fail:
++ if( reg_base != NULL) iounmap(reg_base );
++ if( fifo_base != NULL) iounmap(fifo_base);
++ if( fifo_dbg != NULL) iounmap(fifo_dbg );
++ return retval;
++}
++
++/*!
++ \brief This function free the mapped address in the IFXUSB CSR data structures.
++ \param _core_if Pointer of core_if structure
++ */
++void ifxusb_core_if_remove(ifxusb_core_if_t *_core_if)
++{
++ /* Disable all interrupts */
++ if( _core_if->core_global_regs != NULL)
++ {
++ ifxusb_mreg( &_core_if->core_global_regs->gahbcfg, 1, 0);
++ ifxusb_wreg( &_core_if->core_global_regs->gintmsk, 0);
++ }
++
++ if( _core_if->core_global_regs != NULL) iounmap(_core_if->core_global_regs );
++ if( _core_if->data_fifo[0] != NULL) iounmap(_core_if->data_fifo[0] );
++ if( _core_if->data_fifo_dbg != NULL) iounmap(_core_if->data_fifo_dbg );
++
++#if 0
++ if (_core_if->wq_usb)
++ destroy_workqueue(_core_if->wq_usb);
++#endif
++ memset(_core_if, 0, sizeof(ifxusb_core_if_t));
++}
++
++
++
++
++/*!
++ \brief This function enbles the controller's Global Interrupt in the AHB Config register.
++ \param _core_if Pointer of core_if structure
++ */
++void ifxusb_enable_global_interrupts( ifxusb_core_if_t *_core_if )
++{
++ gahbcfg_data_t ahbcfg ={ .d32 = 0};
++ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */
++ ifxusb_mreg(&_core_if->core_global_regs->gahbcfg, 0, ahbcfg.d32);
++}
++
++/*!
++ \brief This function disables the controller's Global Interrupt in the AHB Config register.
++ \param _core_if Pointer of core_if structure
++ */
++void ifxusb_disable_global_interrupts( ifxusb_core_if_t *_core_if )
++{
++ gahbcfg_data_t ahbcfg ={ .d32 = 0};
++ ahbcfg.b.glblintrmsk = 1; /* Enable interrupts */
++ ifxusb_mreg(&_core_if->core_global_regs->gahbcfg, ahbcfg.d32, 0);
++}
++
++
++
++
++/*!
++ \brief Flush Tx and Rx FIFO.
++ \param _core_if Pointer of core_if structure
++ */
++void ifxusb_flush_both_fifo( ifxusb_core_if_t *_core_if )
++{
++ ifxusb_core_global_regs_t *global_regs = _core_if->core_global_regs;
++ volatile grstctl_t greset ={ .d32 = 0};
++ int count = 0;
++
++ IFX_DEBUGPL((DBG_CIL|DBG_PCDV), "%s\n", __func__);
++ greset.b.rxfflsh = 1;
++ greset.b.txfflsh = 1;
++ greset.b.txfnum = 0x10;
++ greset.b.intknqflsh=1;
++ greset.b.hstfrm=1;
++ ifxusb_wreg( &global_regs->grstctl, greset.d32 );
++
++ do
++ {
++ greset.d32 = ifxusb_rreg( &global_regs->grstctl);
++ if (++count > 10000)
++ {
++ IFX_WARN("%s() HANG! GRSTCTL=%0x\n", __func__, greset.d32);
++ break;
++ }
++ } while (greset.b.rxfflsh == 1 || greset.b.txfflsh == 1);
++ /* Wait for 3 PHY Clocks*/
++ UDELAY(1);
++}
++
++/*!
++ \brief Flush a Tx FIFO.
++ \param _core_if Pointer of core_if structure
++ \param _num Tx FIFO to flush. ( 0x10 for ALL TX FIFO )
++ */
++void ifxusb_flush_tx_fifo( ifxusb_core_if_t *_core_if, const int _num )
++{
++ ifxusb_core_global_regs_t *global_regs = _core_if->core_global_regs;
++ volatile grstctl_t greset ={ .d32 = 0};
++ int count = 0;
++
++ IFX_DEBUGPL((DBG_CIL|DBG_PCDV), "Flush Tx FIFO %d\n", _num);
++
++ greset.b.intknqflsh=1;
++ greset.b.txfflsh = 1;
++ greset.b.txfnum = _num;
++ ifxusb_wreg( &global_regs->grstctl, greset.d32 );
++
++ do
++ {
++ greset.d32 = ifxusb_rreg( &global_regs->grstctl);
++ if (++count > 10000&&(_num==0 ||_num==0x10))
++ {
++ IFX_WARN("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
++ __func__, greset.d32,
++ ifxusb_rreg( &global_regs->gnptxsts));
++ break;
++ }
++ } while (greset.b.txfflsh == 1);
++ /* Wait for 3 PHY Clocks*/
++ UDELAY(1);
++}
++
++
++/*!
++ \brief Flush Rx FIFO.
++ \param _core_if Pointer of core_if structure
++ */
++void ifxusb_flush_rx_fifo( ifxusb_core_if_t *_core_if )
++{
++ ifxusb_core_global_regs_t *global_regs = _core_if->core_global_regs;
++ volatile grstctl_t greset ={ .d32 = 0};
++ int count = 0;
++
++ IFX_DEBUGPL((DBG_CIL|DBG_PCDV), "%s\n", __func__);
++ greset.b.rxfflsh = 1;
++ ifxusb_wreg( &global_regs->grstctl, greset.d32 );
++
++ do
++ {
++ greset.d32 = ifxusb_rreg( &global_regs->grstctl);
++ if (++count > 10000)
++ {
++ IFX_WARN("%s() HANG! GRSTCTL=%0x\n", __func__, greset.d32);
++ break;
++ }
++ } while (greset.b.rxfflsh == 1);
++ /* Wait for 3 PHY Clocks*/
++ UDELAY(1);
++}
++
++
++#define SOFT_RESET_DELAY 100
++
++/*!
++ \brief Do a soft reset of the core. Be careful with this because it
++ resets all the internal state machines of the core.
++ \param _core_if Pointer of core_if structure
++ */
++int ifxusb_core_soft_reset(ifxusb_core_if_t *_core_if)
++{
++ ifxusb_core_global_regs_t *global_regs = _core_if->core_global_regs;
++ volatile grstctl_t greset ={ .d32 = 0};
++ int count = 0;
++
++ IFX_DEBUGPL(DBG_CILV, "%s\n", __func__);
++ /* Wait for AHB master IDLE state. */
++ do
++ {
++ UDELAY(10);
++ greset.d32 = ifxusb_rreg( &global_regs->grstctl);
++ if (++count > 100000)
++ {
++ IFX_WARN("%s() HANG! AHB Idle GRSTCTL=%0x %x\n", __func__,
++ greset.d32, greset.b.ahbidle);
++ break;
++ }
++ } while (greset.b.ahbidle == 0);
++
++ UDELAY(1);
++
++ /* Core Soft Reset */
++ count = 0;
++ greset.b.csftrst = 1;
++ ifxusb_wreg( &global_regs->grstctl, greset.d32 );
++
++ #ifdef SOFT_RESET_DELAY
++ MDELAY(SOFT_RESET_DELAY);
++ #endif
++
++ do
++ {
++ UDELAY(10);
++ greset.d32 = ifxusb_rreg( &global_regs->grstctl);
++ if (++count > 100000)
++ {
++ IFX_WARN("%s() HANG! Soft Reset GRSTCTL=%0x\n", __func__, greset.d32);
++ return -1;
++ }
++ } while (greset.b.csftrst == 1);
++
++ #ifdef SOFT_RESET_DELAY
++ MDELAY(SOFT_RESET_DELAY);
++ #endif
++
++
++ #if defined(__IS_VR9__)
++ if(_core_if->core_no==0)
++ {
++ set_bit (4, VR9_RCU_USBRESET2);
++ MDELAY(50);
++ clear_bit (4, VR9_RCU_USBRESET2);
++ }
++ else
++ {
++ set_bit (5, VR9_RCU_USBRESET2);
++ MDELAY(50);
++ clear_bit (5, VR9_RCU_USBRESET2);
++ }
++ MDELAY(50);
++ #endif //defined(__IS_VR9__)
++
++ IFX_PRINT("USB core #%d soft-reset\n",_core_if->core_no);
++
++ return 0;
++}
++
++/*!
++ \brief Turn on the USB Core Power
++ \param _core_if Pointer of core_if structure
++*/
++void ifxusb_power_on (ifxusb_core_if_t *_core_if)
++{
++ struct clk *clk0 = clk_get_sys("usb0", NULL);
++ struct clk *clk1 = clk_get_sys("usb1", NULL);
++ // set clock gating
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ #if defined(__UEIP__)
++
++ #if defined(__IS_TWINPASS) || defined(__IS_DANUBE__)
++ set_bit (4, (volatile unsigned long *)DANUBE_CGU_IFCCR);
++ set_bit (5, (volatile unsigned long *)DANUBE_CGU_IFCCR);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ // clear_bit (4, (volatile unsigned long *)AMAZON_SE_CGU_IFCCR);
++ clear_bit (5, (volatile unsigned long *)AMAZON_SE_CGU_IFCCR);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ set_bit (0, (volatile unsigned long *)AR9_CGU_IFCCR);
++ set_bit (1, (volatile unsigned long *)AR9_CGU_IFCCR);
++ #endif //defined(__IS_AR9__)
++ #if defined(__IS_VR9__)
++// set_bit (0, (volatile unsigned long *)VR9_CGU_IFCCR);
++// set_bit (1, (volatile unsigned long *)VR9_CGU_IFCCR);
++ #endif //defined(__IS_VR9__)
++
++ MDELAY(50);
++
++ // set power
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__) || defined(__IS_AMAZON_SE__)
++ USB_CTRL_PMU_SETUP(IFX_PMU_ENABLE);
++ //#if defined(__IS_TWINPASS__)
++ // ifxusb_enable_afe_oc();
++ //#endif
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__) || defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__) || defined(__IS_VR9__)
++ if(_core_if->core_no==0)
++ clk_enable(clk0);
++// USB0_CTRL_PMU_SETUP(IFX_PMU_ENABLE);
++ else
++ clk_enable(clk1);
++// USB1_CTRL_PMU_SETUP(IFX_PMU_ENABLE);
++ #endif //defined(__IS_AR9__) || defined(__IS_VR9__)
++
++ if(_core_if->core_global_regs)
++ {
++ // PHY configurations.
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AR9__)
++ #if defined(__IS_VR9__)
++ //ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_VR9__)
++ }
++ #else //defined(__UEIP__)
++ #if defined(__IS_TWINPASS) || defined(__IS_DANUBE__)
++ set_bit (4, (volatile unsigned long *)DANUBE_CGU_IFCCR);
++ set_bit (5, (volatile unsigned long *)DANUBE_CGU_IFCCR);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ // clear_bit (4, (volatile unsigned long *)AMAZON_SE_CGU_IFCCR);
++ clear_bit (5, (volatile unsigned long *)AMAZON_SE_CGU_IFCCR);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ set_bit (0, (volatile unsigned long *)AMAZON_S_CGU_IFCCR);
++ set_bit (1, (volatile unsigned long *)AMAZON_S_CGU_IFCCR);
++ #endif //defined(__IS_AR9__)
++
++ MDELAY(50);
++
++ // set power
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ clear_bit (6, (volatile unsigned long *)DANUBE_PMU_PWDCR);//USB
++ clear_bit (9, (volatile unsigned long *)DANUBE_PMU_PWDCR);//DSL
++ clear_bit (15, (volatile unsigned long *)DANUBE_PMU_PWDCR);//AHB
++ #if defined(__IS_TWINPASS__)
++ ifxusb_enable_afe_oc();
++ #endif
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ clear_bit (6, (volatile unsigned long *)AMAZON_SE_PMU_PWDCR);
++ clear_bit (9, (volatile unsigned long *)AMAZON_SE_PMU_PWDCR);
++ clear_bit (15, (volatile unsigned long *)AMAZON_SE_PMU_PWDCR);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ if(_core_if->core_no==0)
++ clear_bit (6, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//USB
++ else
++ clear_bit (27, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//USB
++ clear_bit (9, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//DSL
++ clear_bit (15, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//AHB
++ #endif //defined(__IS_AR9__)
++
++ if(_core_if->core_global_regs)
++ {
++ // PHY configurations.
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AR9__)
++ }
++
++ #endif //defined(__UEIP__)
++}
++
++/*!
++ \brief Turn off the USB Core Power
++ \param _core_if Pointer of core_if structure
++*/
++void ifxusb_power_off (ifxusb_core_if_t *_core_if)
++{
++ struct clk *clk0 = clk_get_sys("usb0", NULL);
++ struct clk *clk1 = clk_get_sys("usb1", NULL);
++ ifxusb_phy_power_off (_core_if);
++
++ // set power
++ #if defined(__UEIP__)
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__) || defined(__IS_AMAZON_SE__)
++ USB_CTRL_PMU_SETUP(IFX_PMU_DISABLE);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__) || defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__) || defined(__IS_VR9__)
++ if(_core_if->core_no==0)
++ clk_disable(clk0);
++ //USB0_CTRL_PMU_SETUP(IFX_PMU_DISABLE);
++ else
++ clk_disable(clk1);
++ //USB1_CTRL_PMU_SETUP(IFX_PMU_DISABLE);
++ #endif //defined(__IS_AR9__) || defined(__IS_VR9__)
++ #else //defined(__UEIP__)
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ set_bit (6, (volatile unsigned long *)DANUBE_PMU_PWDCR);//USB
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ set_bit (6, (volatile unsigned long *)AMAZON_SE_PMU_PWDCR);//USB
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ if(_core_if->core_no==0)
++ set_bit (6, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//USB
++ else
++ set_bit (27, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//USB
++ #endif //defined(__IS_AR9__)
++ #endif //defined(__UEIP__)
++}
++
++/*!
++ \brief Turn on the USB PHY Power
++ \param _core_if Pointer of core_if structure
++*/
++void ifxusb_phy_power_on (ifxusb_core_if_t *_core_if)
++{
++ struct clk *clk0 = clk_get_sys("usb0", NULL);
++ struct clk *clk1 = clk_get_sys("usb1", NULL);
++ #if defined(__UEIP__)
++ if(_core_if->core_global_regs)
++ {
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AR9__)
++ #if defined(__IS_VR9_S__)
++ if(_core_if->core_no==0)
++ set_bit (0, VR9_RCU_USB_ANA_CFG1A);
++ else
++ set_bit (0, VR9_RCU_USB_ANA_CFG1B);
++ #endif //defined(__IS_VR9__)
++ }
++
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__) || defined(__IS_AMAZON_SE__)
++ USB_PHY_PMU_SETUP(IFX_PMU_ENABLE);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__) || defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__) || defined(__IS_VR9__)
++ if(_core_if->core_no==0)
++ clk_enable(clk0);
++ //USB0_PHY_PMU_SETUP(IFX_PMU_ENABLE);
++ else
++ clk_enable(clk1);
++ //USB1_PHY_PMU_SETUP(IFX_PMU_ENABLE);
++ #endif //defined(__IS_AR9__) || defined(__IS_VR9__)
++
++ // PHY configurations.
++ if(_core_if->core_global_regs)
++ {
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AR9__)
++ #if defined(__IS_VR9_S__)
++ if(_core_if->core_no==0)
++ set_bit (0, VR9_RCU_USB_ANA_CFG1A);
++ else
++ set_bit (0, VR9_RCU_USB_ANA_CFG1B);
++ #endif //defined(__IS_VR9__)
++ }
++ #else //defined(__UEIP__)
++ // PHY configurations.
++ if(_core_if->core_global_regs)
++ {
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AR9__)
++ }
++
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ clear_bit (0, (volatile unsigned long *)DANUBE_PMU_PWDCR);//PHY
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ clear_bit (0, (volatile unsigned long *)AMAZON_SE_PMU_PWDCR);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ if(_core_if->core_no==0)
++ clear_bit (0, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//PHY
++ else
++ clear_bit (26, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//PHY
++ #endif //defined(__IS_AR9__)
++
++ // PHY configurations.
++ if(_core_if->core_global_regs)
++ {
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AR9__)
++ }
++ #endif //defined(__UEIP__)
++}
++
++
++/*!
++ \brief Turn off the USB PHY Power
++ \param _core_if Pointer of core_if structure
++*/
++void ifxusb_phy_power_off (ifxusb_core_if_t *_core_if)
++{
++ struct clk *clk0 = clk_get_sys("usb0", NULL);
++ struct clk *clk1 = clk_get_sys("usb1", NULL);
++ #if defined(__UEIP__)
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__) || defined(__IS_AMAZON_SE__)
++ USB_PHY_PMU_SETUP(IFX_PMU_DISABLE);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__) || defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__) || defined(__IS_VR9__)
++ if(_core_if->core_no==0)
++ clk_disable(clk0);
++ //USB0_PHY_PMU_SETUP(IFX_PMU_DISABLE);
++ else
++ clk_disable(clk1);
++ //USB1_PHY_PMU_SETUP(IFX_PMU_DISABLE);
++ #endif // defined(__IS_AR9__) || defined(__IS_VR9__)
++ #else //defined(__UEIP__)
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ set_bit (0, (volatile unsigned long *)DANUBE_PMU_PWDCR);//PHY
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ set_bit (0, (volatile unsigned long *)AMAZON_SE_PMU_PWDCR);//PHY
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ if(_core_if->core_no==0)
++ set_bit (0, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//PHY
++ else
++ set_bit (26, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//PHY
++ #endif //defined(__IS_AR9__)
++ #endif //defined(__UEIP__)
++}
++
++
++/*!
++ \brief Reset on the USB Core RCU
++ \param _core_if Pointer of core_if structure
++ */
++#if defined(__IS_VR9__)
++ int already_hard_reset=0;
++#endif
++void ifxusb_hard_reset(ifxusb_core_if_t *_core_if)
++{
++ #if defined(__UEIP__)
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined (__IS_HOST__)
++ clear_bit (DANUBE_USBCFG_HDSEL_BIT, (volatile unsigned long *)DANUBE_RCU_USBCFG);
++ #elif defined (__IS_DEVICE__)
++ set_bit (DANUBE_USBCFG_HDSEL_BIT, (volatile unsigned long *)DANUBE_RCU_USBCFG);
++ #endif
++ #endif //defined(__IS_AMAZON_SE__)
++
++ #if defined(__IS_AMAZON_SE__)
++ #if defined (__IS_HOST__)
++ clear_bit (AMAZON_SE_USBCFG_HDSEL_BIT, (volatile unsigned long *)AMAZON_SE_RCU_USBCFG);
++ #elif defined (__IS_DEVICE__)
++ set_bit (AMAZON_SE_USBCFG_HDSEL_BIT, (volatile unsigned long *)AMAZON_SE_RCU_USBCFG);
++ #endif
++ #endif //defined(__IS_AMAZON_SE__)
++
++ #if defined(__IS_AR9__)
++ if(_core_if->core_no==0)
++ {
++ #if defined (__IS_HOST__)
++ clear_bit (AR9_USBCFG_HDSEL_BIT, (volatile unsigned long *)AR9_RCU_USB1CFG);
++ #elif defined (__IS_DEVICE__)
++ set_bit (AR9_USBCFG_HDSEL_BIT, (volatile unsigned long *)AR9_RCU_USB1CFG);
++ #endif
++ }
++ else
++ {
++ #if defined (__IS_HOST__)
++ clear_bit (AR9_USBCFG_HDSEL_BIT, (volatile unsigned long *)AR9_RCU_USB2CFG);
++ #elif defined (__IS_DEVICE__)
++ set_bit (AR9_USBCFG_HDSEL_BIT, (volatile unsigned long *)AR9_RCU_USB2CFG);
++ #endif
++ }
++ #endif //defined(__IS_AR9__)
++
++ #if defined(__IS_VR9__)
++ if(_core_if->core_no==0)
++ {
++ #if defined (__IS_HOST__)
++ clear_bit (VR9_USBCFG_HDSEL_BIT, (volatile unsigned long *)VR9_RCU_USB1CFG);
++ #elif defined (__IS_DEVICE__)
++ set_bit (VR9_USBCFG_HDSEL_BIT, (volatile unsigned long *)VR9_RCU_USB1CFG);
++ #endif
++ }
++ else
++ {
++ #if defined (__IS_HOST__)
++ clear_bit (VR9_USBCFG_HDSEL_BIT, (volatile unsigned long *)VR9_RCU_USB2CFG);
++ #elif defined (__IS_DEVICE__)
++ set_bit (VR9_USBCFG_HDSEL_BIT, (volatile unsigned long *)VR9_RCU_USB2CFG);
++ #endif
++ }
++ #endif //defined(__IS_VR9__)
++
++
++ // set the HC's byte-order to big-endian
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ set_bit (DANUBE_USBCFG_HOST_END_BIT, (volatile unsigned long *)DANUBE_RCU_USBCFG);
++ clear_bit (DANUBE_USBCFG_SLV_END_BIT, (volatile unsigned long *)DANUBE_RCU_USBCFG);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ set_bit (AMAZON_SE_USBCFG_HOST_END_BIT, (volatile unsigned long *)AMAZON_SE_RCU_USBCFG);
++ clear_bit (AMAZON_SE_USBCFG_SLV_END_BIT, (volatile unsigned long *)AMAZON_SE_RCU_USBCFG);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ if(_core_if->core_no==0)
++ {
++ set_bit (AR9_USBCFG_HOST_END_BIT, (volatile unsigned long *)AR9_RCU_USB1CFG);
++ clear_bit (AR9_USBCFG_SLV_END_BIT, (volatile unsigned long *)AR9_RCU_USB1CFG);
++ }
++ else
++ {
++ set_bit (AR9_USBCFG_HOST_END_BIT, (volatile unsigned long *)AR9_RCU_USB2CFG);
++ clear_bit (AR9_USBCFG_SLV_END_BIT, (volatile unsigned long *)AR9_RCU_USB2CFG);
++ }
++ #endif //defined(__IS_AR9__)
++ #if defined(__IS_VR9__)
++ if(_core_if->core_no==0)
++ {
++ set_bit (VR9_USBCFG_HOST_END_BIT, (volatile unsigned long *)VR9_RCU_USB1CFG);
++ clear_bit (VR9_USBCFG_SLV_END_BIT, (volatile unsigned long *)VR9_RCU_USB1CFG);
++ }
++ else
++ {
++ set_bit (VR9_USBCFG_HOST_END_BIT, (volatile unsigned long *)VR9_RCU_USB2CFG);
++ clear_bit (VR9_USBCFG_SLV_END_BIT, (volatile unsigned long *)VR9_RCU_USB2CFG);
++ }
++ #endif //defined(__IS_VR9__)
++
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ set_bit (4, DANUBE_RCU_RESET);
++ MDELAY(500);
++ clear_bit (4, DANUBE_RCU_RESET);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++
++ #if defined(__IS_AMAZON_SE__)
++ set_bit (4, AMAZON_SE_RCU_RESET);
++ MDELAY(500);
++ clear_bit (4, AMAZON_SE_RCU_RESET);
++ MDELAY(500);
++ #endif //defined(__IS_AMAZON_SE__)
++
++ #if defined(__IS_AR9__)
++ if(_core_if->core_no==0)
++ {
++ set_bit (4, AR9_RCU_USBRESET);
++ MDELAY(500);
++ clear_bit (4, AR9_RCU_USBRESET);
++ }
++ else
++ {
++ set_bit (28, AR9_RCU_USBRESET);
++ MDELAY(500);
++ clear_bit (28, AR9_RCU_USBRESET);
++ }
++ MDELAY(500);
++ #endif //defined(__IS_AR9__)
++ #if defined(__IS_VR9__)
++ if(!already_hard_reset)
++ {
++ set_bit (4, VR9_RCU_USBRESET);
++ MDELAY(500);
++ clear_bit (4, VR9_RCU_USBRESET);
++ MDELAY(500);
++ already_hard_reset=1;
++ }
++ #endif //defined(__IS_VR9__)
++
++ #if defined(__IS_TWINPASS__)
++ ifxusb_enable_afe_oc();
++ #endif
++
++ if(_core_if->core_global_regs)
++ {
++ // PHY configurations.
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AR9__)
++ #if defined(__IS_VR9__)
++ // ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_VR9__)
++ }
++ #else //defined(__UEIP__)
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined (__IS_HOST__)
++ clear_bit (DANUBE_USBCFG_HDSEL_BIT, (volatile unsigned long *)DANUBE_RCU_USBCFG);
++ #elif defined (__IS_DEVICE__)
++ set_bit (DANUBE_USBCFG_HDSEL_BIT, (volatile unsigned long *)DANUBE_RCU_USBCFG);
++ #endif
++ #endif //defined(__IS_AMAZON_SE__)
++
++ #if defined(__IS_AMAZON_SE__)
++ #if defined (__IS_HOST__)
++ clear_bit (AMAZON_SE_USBCFG_HDSEL_BIT, (volatile unsigned long *)AMAZON_SE_RCU_USBCFG);
++ #elif defined (__IS_DEVICE__)
++ set_bit (AMAZON_SE_USBCFG_HDSEL_BIT, (volatile unsigned long *)AMAZON_SE_RCU_USBCFG);
++ #endif
++ #endif //defined(__IS_AMAZON_SE__)
++
++ #if defined(__IS_AR9__)
++ if(_core_if->core_no==0)
++ {
++ #if defined (__IS_HOST__)
++ clear_bit (AMAZON_S_USBCFG_HDSEL_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB1CFG);
++ #elif defined (__IS_DEVICE__)
++ set_bit (AMAZON_S_USBCFG_HDSEL_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB1CFG);
++ #endif
++ }
++ else
++ {
++ #if defined (__IS_HOST__)
++ clear_bit (AMAZON_S_USBCFG_HDSEL_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB2CFG);
++ #elif defined (__IS_DEVICE__)
++ set_bit (AMAZON_S_USBCFG_HDSEL_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB2CFG);
++ #endif
++ }
++ #endif //defined(__IS_AR9__)
++
++ // set the HC's byte-order to big-endian
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ set_bit (DANUBE_USBCFG_HOST_END_BIT, (volatile unsigned long *)DANUBE_RCU_USBCFG);
++ clear_bit (DANUBE_USBCFG_SLV_END_BIT, (volatile unsigned long *)DANUBE_RCU_USBCFG);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ set_bit (AMAZON_SE_USBCFG_HOST_END_BIT, (volatile unsigned long *)AMAZON_SE_RCU_USBCFG);
++ clear_bit (AMAZON_SE_USBCFG_SLV_END_BIT, (volatile unsigned long *)AMAZON_SE_RCU_USBCFG);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ if(_core_if->core_no==0)
++ {
++ set_bit (AMAZON_S_USBCFG_HOST_END_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB1CFG);
++ clear_bit (AMAZON_S_USBCFG_SLV_END_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB1CFG);
++ }
++ else
++ {
++ set_bit (AMAZON_S_USBCFG_HOST_END_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB2CFG);
++ clear_bit (AMAZON_S_USBCFG_SLV_END_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB2CFG);
++ }
++ #endif //defined(__IS_AR9__)
++
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ set_bit (4, DANUBE_RCU_RESET);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ set_bit (4, AMAZON_SE_RCU_RESET);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ if(_core_if->core_no==0)
++ {
++ set_bit (4, AMAZON_S_RCU_USBRESET);
++ }
++ else
++ {
++ set_bit (28, AMAZON_S_RCU_USBRESET);
++ }
++ #endif //defined(__IS_AR9__)
++
++ MDELAY(500);
++
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ clear_bit (4, DANUBE_RCU_RESET);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ clear_bit (4, AMAZON_SE_RCU_RESET);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ if(_core_if->core_no==0)
++ {
++ clear_bit (4, AMAZON_S_RCU_USBRESET);
++ }
++ else
++ {
++ clear_bit (28, AMAZON_S_RCU_USBRESET);
++ }
++ #endif //defined(__IS_AR9__)
++
++ MDELAY(500);
++
++ #if defined(__IS_TWINPASS__)
++ ifxusb_enable_afe_oc();
++ #endif
++
++ if(_core_if->core_global_regs)
++ {
++ // PHY configurations.
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ ifxusb_wreg (&_core_if->core_global_regs->guid,0x14014);
++ #endif //defined(__IS_AR9__)
++ }
++ #endif //defined(__UEIP__)
++}
++
++#if defined(__GADGET_LED__) || defined(__HOST_LED__)
++ #if defined(__UEIP__)
++ static void *g_usb_led_trigger = NULL;
++ #endif
++
++ void ifxusb_led_init(ifxusb_core_if_t *_core_if)
++ {
++ #if defined(__UEIP__)
++ if ( !g_usb_led_trigger )
++ {
++ ifx_led_trigger_register("usb_link", &g_usb_led_trigger);
++ if ( g_usb_led_trigger != NULL )
++ {
++ struct ifx_led_trigger_attrib attrib = {0};
++ attrib.delay_on = 250;
++ attrib.delay_off = 250;
++ attrib.timeout = 2000;
++ attrib.def_value = 1;
++ attrib.flags = IFX_LED_TRIGGER_ATTRIB_DELAY_ON | IFX_LED_TRIGGER_ATTRIB_DELAY_OFF | IFX_LED_TRIGGER_ATTRIB_TIMEOUT | IFX_LED_TRIGGER_ATTRIB_DEF_VALUE;
++ IFX_DEBUGP("Reg USB LED!!\n");
++ ifx_led_trigger_set_attrib(g_usb_led_trigger, &attrib);
++ }
++ }
++ #endif //defined(__UEIP__)
++ }
++
++ void ifxusb_led_free(ifxusb_core_if_t *_core_if)
++ {
++ #if defined(__UEIP__)
++ if ( g_usb_led_trigger )
++ {
++ ifx_led_trigger_deregister(g_usb_led_trigger);
++ g_usb_led_trigger = NULL;
++ }
++ #endif //defined(__UEIP__)
++ }
++
++ /*!
++ \brief Turn off the USB 5V VBus Power
++ \param _core_if Pointer of core_if structure
++ */
++ void ifxusb_led(ifxusb_core_if_t *_core_if)
++ {
++ #if defined(__UEIP__)
++ if(g_usb_led_trigger)
++ ifx_led_trigger_activate(g_usb_led_trigger);
++ #else
++ #endif //defined(__UEIP__)
++ }
++#endif // defined(__GADGET_LED__) || defined(__HOST_LED__)
++
++
++
++#if defined(__IS_HOST__) && defined(__DO_OC_INT__) && defined(__DO_OC_INT_ENABLE__)
++/*!
++ \brief Turn on the OC Int
++ */
++ void ifxusb_oc_int_on()
++ {
++ #if defined(__UEIP__)
++ #else
++ #if defined(__IS_TWINPASS__)
++ irq_enable(DANUBE_USB_OC_INT);
++ #endif
++ #endif //defined(__UEIP__)
++ }
++/*!
++ \brief Turn off the OC Int
++ */
++ void ifxusb_oc_int_off()
++ {
++ #if defined(__UEIP__)
++ #else
++ #if defined(__IS_TWINPASS__)
++ irq_disable(DANUBE_USB_OC_INT);
++ #endif
++ #endif //defined(__UEIP__)
++ }
++#endif //defined(__IS_HOST__) && defined(__DO_OC_INT__) && defined(__DO_OC_INT_ENABLE__)
++
++/* internal routines for debugging */
++void ifxusb_dump_msg(const u8 *buf, unsigned int length)
++{
++#ifdef __DEBUG__
++ unsigned int start, num, i;
++ char line[52], *p;
++
++ if (length >= 512)
++ return;
++ start = 0;
++ while (length > 0)
++ {
++ num = min(length, 16u);
++ p = line;
++ for (i = 0; i < num; ++i)
++ {
++ if (i == 8)
++ *p++ = ' ';
++ sprintf(p, " %02x", buf[i]);
++ p += 3;
++ }
++ *p = 0;
++ IFX_PRINT( "%6x: %s\n", start, line);
++ buf += num;
++ start += num;
++ length -= num;
++ }
++#endif
++}
++
++/* This functions reads the SPRAM and prints its content */
++void ifxusb_dump_spram(ifxusb_core_if_t *_core_if)
++{
++#ifdef __ENABLE_DUMP__
++ volatile uint8_t *addr, *start_addr, *end_addr;
++ uint32_t size;
++ IFX_PRINT("SPRAM Data:\n");
++ start_addr = (void*)_core_if->core_global_regs;
++ IFX_PRINT("Base Address: 0x%8X\n", (uint32_t)start_addr);
++
++ start_addr = (void*)_core_if->data_fifo_dbg;
++ IFX_PRINT("Starting Address: 0x%8X\n", (uint32_t)start_addr);
++
++ size=_core_if->hwcfg3.b.dfifo_depth;
++ size<<=2;
++ size+=0x200;
++ size&=0x0003FFFC;
++
++ end_addr = (void*)_core_if->data_fifo_dbg;
++ end_addr += size;
++
++ for(addr = start_addr; addr < end_addr; addr+=16)
++ {
++ IFX_PRINT("0x%8X:\t%02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", (uint32_t)addr,
++ addr[ 0], addr[ 1], addr[ 2], addr[ 3],
++ addr[ 4], addr[ 5], addr[ 6], addr[ 7],
++ addr[ 8], addr[ 9], addr[10], addr[11],
++ addr[12], addr[13], addr[14], addr[15]
++ );
++ }
++ return;
++#endif //__ENABLE_DUMP__
++}
++
++
++
++
++/* This function reads the core global registers and prints them */
++void ifxusb_dump_registers(ifxusb_core_if_t *_core_if)
++{
++#ifdef __ENABLE_DUMP__
++ int i;
++ volatile uint32_t *addr;
++ #ifdef __IS_DEVICE__
++ volatile uint32_t *addri,*addro;
++ #endif
++
++ IFX_PRINT("Core Global Registers\n");
++ addr=&_core_if->core_global_regs->gotgctl;
++ IFX_PRINT("GOTGCTL @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->gotgint;
++ IFX_PRINT("GOTGINT @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->gahbcfg;
++ IFX_PRINT("GAHBCFG @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->gusbcfg;
++ IFX_PRINT("GUSBCFG @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->grstctl;
++ IFX_PRINT("GRSTCTL @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->gintsts;
++ IFX_PRINT("GINTSTS @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->gintmsk;
++ IFX_PRINT("GINTMSK @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->gi2cctl;
++ IFX_PRINT("GI2CCTL @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->gpvndctl;
++ IFX_PRINT("GPVNDCTL @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->ggpio;
++ IFX_PRINT("GGPIO @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->guid;
++ IFX_PRINT("GUID @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->gsnpsid;
++ IFX_PRINT("GSNPSID @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->ghwcfg1;
++ IFX_PRINT("GHWCFG1 @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->ghwcfg2;
++ IFX_PRINT("GHWCFG2 @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->ghwcfg3;
++ IFX_PRINT("GHWCFG3 @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->ghwcfg4;
++ IFX_PRINT("GHWCFG4 @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++
++ addr=_core_if->pcgcctl;
++ IFX_PRINT("PCGCCTL @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++
++ addr=&_core_if->core_global_regs->grxfsiz;
++ IFX_PRINT("GRXFSIZ @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++
++ #ifdef __IS_HOST__
++ addr=&_core_if->core_global_regs->gnptxfsiz;
++ IFX_PRINT("GNPTXFSIZ @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->core_global_regs->hptxfsiz;
++ IFX_PRINT("HPTXFSIZ @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ #endif //__IS_HOST__
++
++ #ifdef __IS_DEVICE__
++ #ifdef __DED_FIFO__
++ addr=&_core_if->core_global_regs->gnptxfsiz;
++ IFX_PRINT("GNPTXFSIZ @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ for (i=0; i<= _core_if->hwcfg4.b.num_in_eps; i++)
++ {
++ addr=&_core_if->core_global_regs->dptxfsiz_dieptxf[i];
++ IFX_PRINT("DPTXFSIZ[%d] @0x%08X : 0x%08X\n",i,(uint32_t)addr,ifxusb_rreg(addr));
++ }
++ #else
++ addr=&_core_if->core_global_regs->gnptxfsiz;
++ IFX_PRINT("TXFSIZ[00] @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ for (i=0; i< _core_if->hwcfg4.b.num_dev_perio_in_ep; i++)
++ {
++ addr=&_core_if->core_global_regs->dptxfsiz_dieptxf[i];
++ IFX_PRINT("TXFSIZ[%02d] @0x%08X : 0x%08X\n",i+1,(uint32_t)addr,ifxusb_rreg(addr));
++ }
++ #endif
++ #endif //__IS_DEVICE__
++
++ #ifdef __IS_HOST__
++ IFX_PRINT("Host Global Registers\n");
++ addr=&_core_if->host_global_regs->hcfg;
++ IFX_PRINT("HCFG @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->host_global_regs->hfir;
++ IFX_PRINT("HFIR @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->host_global_regs->hfnum;
++ IFX_PRINT("HFNUM @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->host_global_regs->hptxsts;
++ IFX_PRINT("HPTXSTS @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->host_global_regs->haint;
++ IFX_PRINT("HAINT @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->host_global_regs->haintmsk;
++ IFX_PRINT("HAINTMSK @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr= _core_if->hprt0;
++ IFX_PRINT("HPRT0 @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++
++ for (i=0; i<MAX_EPS_CHANNELS; i++)
++ {
++ IFX_PRINT("Host Channel %d Specific Registers\n", i);
++ addr=&_core_if->hc_regs[i]->hcchar;
++ IFX_PRINT("HCCHAR @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->hc_regs[i]->hcsplt;
++ IFX_PRINT("HCSPLT @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->hc_regs[i]->hcint;
++ IFX_PRINT("HCINT @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->hc_regs[i]->hcintmsk;
++ IFX_PRINT("HCINTMSK @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->hc_regs[i]->hctsiz;
++ IFX_PRINT("HCTSIZ @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->hc_regs[i]->hcdma;
++ IFX_PRINT("HCDMA @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ }
++ #endif //__IS_HOST__
++
++ #ifdef __IS_DEVICE__
++ IFX_PRINT("Device Global Registers\n");
++ addr=&_core_if->dev_global_regs->dcfg;
++ IFX_PRINT("DCFG @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->dev_global_regs->dctl;
++ IFX_PRINT("DCTL @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->dev_global_regs->dsts;
++ IFX_PRINT("DSTS @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->dev_global_regs->diepmsk;
++ IFX_PRINT("DIEPMSK @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->dev_global_regs->doepmsk;
++ IFX_PRINT("DOEPMSK @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->dev_global_regs->daintmsk;
++ IFX_PRINT("DAINTMSK @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->dev_global_regs->daint;
++ IFX_PRINT("DAINT @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->dev_global_regs->dvbusdis;
++ IFX_PRINT("DVBUSID @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ addr=&_core_if->dev_global_regs->dvbuspulse;
++ IFX_PRINT("DVBUSPULSE @0x%08X : 0x%08X\n", (uint32_t)addr,ifxusb_rreg(addr));
++
++ addr=&_core_if->dev_global_regs->dtknqr1;
++ IFX_PRINT("DTKNQR1 @0x%08X : 0x%08X\n",(uint32_t)addr,ifxusb_rreg(addr));
++ if (_core_if->hwcfg2.b.dev_token_q_depth > 6) {
++ addr=&_core_if->dev_global_regs->dtknqr2;
++ IFX_PRINT("DTKNQR2 @0x%08X : 0x%08X\n", (uint32_t)addr,ifxusb_rreg(addr));
++ }
++
++ if (_core_if->hwcfg2.b.dev_token_q_depth > 14)
++ {
++ addr=&_core_if->dev_global_regs->dtknqr3_dthrctl;
++ IFX_PRINT("DTKNQR3_DTHRCTL @0x%08X : 0x%08X\n", (uint32_t)addr, ifxusb_rreg(addr));
++ }
++
++ if (_core_if->hwcfg2.b.dev_token_q_depth > 22)
++ {
++ addr=&_core_if->dev_global_regs->dtknqr4_fifoemptymsk;
++ IFX_PRINT("DTKNQR4 @0x%08X : 0x%08X\n", (uint32_t)addr, ifxusb_rreg(addr));
++ }
++
++ //for (i=0; i<= MAX_EPS_CHANNELS; i++)
++ //for (i=0; i<= 10; i++)
++ for (i=0; i<= 3; i++)
++ {
++ IFX_PRINT("Device EP %d Registers\n", i);
++ addri=&_core_if->in_ep_regs[i]->diepctl;addro=&_core_if->out_ep_regs[i]->doepctl;
++ IFX_PRINT("DEPCTL I: 0x%08X O: 0x%08X\n",ifxusb_rreg(addri),ifxusb_rreg(addro));
++ addro=&_core_if->out_ep_regs[i]->doepfn;
++ IFX_PRINT("DEPFN I: O: 0x%08X\n",ifxusb_rreg(addro));
++ addri=&_core_if->in_ep_regs[i]->diepint;addro=&_core_if->out_ep_regs[i]->doepint;
++ IFX_PRINT("DEPINT I: 0x%08X O: 0x%08X\n",ifxusb_rreg(addri),ifxusb_rreg(addro));
++ addri=&_core_if->in_ep_regs[i]->dieptsiz;addro=&_core_if->out_ep_regs[i]->doeptsiz;
++ IFX_PRINT("DETSIZ I: 0x%08X O: 0x%08X\n",ifxusb_rreg(addri),ifxusb_rreg(addro));
++ addri=&_core_if->in_ep_regs[i]->diepdma;addro=&_core_if->out_ep_regs[i]->doepdma;
++ IFX_PRINT("DEPDMA I: 0x%08X O: 0x%08X\n",ifxusb_rreg(addri),ifxusb_rreg(addro));
++ addri=&_core_if->in_ep_regs[i]->dtxfsts;
++ IFX_PRINT("DTXFSTS I: 0x%08X\n",ifxusb_rreg(addri) );
++ addri=&_core_if->in_ep_regs[i]->diepdmab;addro=&_core_if->out_ep_regs[i]->doepdmab;
++ IFX_PRINT("DEPDMAB I: 0x%08X O: 0x%08X\n",ifxusb_rreg(addri),ifxusb_rreg(addro));
++ }
++ #endif //__IS_DEVICE__
++#endif //__ENABLE_DUMP__
++}
++
++void ifxusb_clean_spram(ifxusb_core_if_t *_core_if,uint32_t dwords)
++{
++ volatile uint32_t *addr1,*addr2, *start_addr, *end_addr;
++
++ if(!dwords)
++ return;
++
++ start_addr = (uint32_t *)_core_if->data_fifo_dbg;
++
++ end_addr = (uint32_t *)_core_if->data_fifo_dbg;
++ end_addr += dwords;
++
++ IFX_PRINT("Clearning SPRAM: 0x%8X-0x%8X\n", (uint32_t)start_addr,(uint32_t)end_addr);
++ for(addr1 = start_addr; addr1 < end_addr; addr1+=4)
++ {
++ for(addr2 = addr1; addr2 < addr1+4; addr2++)
++ *addr2=0x00000000;
++ }
++ IFX_PRINT("Clearning SPRAM: 0x%8X-0x%8X Done\n", (uint32_t)start_addr,(uint32_t)end_addr);
++ return;
++}
++
+diff --git a/drivers/usb/ifxhcd/ifxusb_cif.h b/drivers/usb/ifxhcd/ifxusb_cif.h
+new file mode 100644
+index 0000000..191781f
+--- /dev/null
++++ b/drivers/usb/ifxhcd/ifxusb_cif.h
+@@ -0,0 +1,665 @@
++/*****************************************************************************
++ ** FILE NAME : ifxusb_cif.h
++ ** PROJECT : IFX USB sub-system V3
++ ** MODULES : IFX USB sub-system Host and Device driver
++ ** SRC VERSION : 1.0
++ ** DATE : 1/Jan/2009
++ ** AUTHOR : Chen, Howard
++ ** DESCRIPTION : The Core Interface provides basic services for accessing and
++ ** managing the IFX USB hardware. These services are used by both the
++ ** Host Controller Driver and the Peripheral Controller Driver.
++ ** FUNCTIONS :
++ ** COMPILER : gcc
++ ** REFERENCE : IFX hardware ref handbook for each plateforms
++ ** COPYRIGHT :
++ ** Version Control Section **
++ ** $Author$
++ ** $Date$
++ ** $Revisions$
++ ** $Log$ Revision history
++*****************************************************************************/
++
++/*!
++ \defgroup IFXUSB_DRIVER_V3 IFX USB SS Project
++ \brief IFX USB subsystem V3.x
++ */
++
++/*!
++ \defgroup IFXUSB_CIF Core Interface APIs
++ \ingroup IFXUSB_DRIVER_V3
++ \brief The Core Interface provides basic services for accessing and
++ managing the IFXUSB hardware. These services are used by both the
++ Host Controller Driver and the Peripheral Controller Driver.
++ */
++
++
++/*!
++ \file ifxusb_cif.h
++ \ingroup IFXUSB_DRIVER_V3
++ \brief This file contains the interface to the IFX USB Core.
++ */
++
++#if !defined(__IFXUSB_CIF_H__)
++#define __IFXUSB_CIF_H__
++
++#include <linux/workqueue.h>
++
++#include <linux/version.h>
++#include <asm/param.h>
++
++#include "ifxusb_plat.h"
++#include "ifxusb_regs.h"
++
++#ifdef __DEBUG__
++ #include "linux/timer.h"
++#endif
++
++///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++
++#define IFXUSB_PARAM_SPEED_HIGH 0
++#define IFXUSB_PARAM_SPEED_FULL 1
++
++#define IFXUSB_EP_SPEED_LOW 0
++#define IFXUSB_EP_SPEED_FULL 1
++#define IFXUSB_EP_SPEED_HIGH 2
++
++#define IFXUSB_EP_TYPE_CTRL 0
++#define IFXUSB_EP_TYPE_ISOC 1
++#define IFXUSB_EP_TYPE_BULK 2
++#define IFXUSB_EP_TYPE_INTR 3
++
++#define IFXUSB_HC_PID_DATA0 0
++#define IFXUSB_HC_PID_DATA2 1
++#define IFXUSB_HC_PID_DATA1 2
++#define IFXUSB_HC_PID_MDATA 3
++#define IFXUSB_HC_PID_SETUP 3
++
++
++/*!
++ \addtogroup IFXUSB_CIF
++ */
++/*@{*/
++
++/*!
++ \struct ifxusb_params
++ \brief IFXUSB Parameters structure.
++ This structure is used for both importing from insmod stage and run-time storage.
++ These parameters define how the IFXUSB controller should be configured.
++ */
++typedef struct ifxusb_params
++{
++ int32_t dma_burst_size; /*!< The DMA Burst size (applicable only for Internal DMA
++ Mode). 0(for single), 1(incr), 4(incr4), 8(incr8) 16(incr16)
++ */
++ /* Translate this to GAHBCFG values */
++ int32_t speed; /*!< Specifies the maximum speed of operation in host and device mode.
++ The actual speed depends on the speed of the attached device and
++ the value of phy_type. The actual speed depends on the speed of the
++ attached device.
++ 0 - High Speed (default)
++ 1 - Full Speed
++ */
++
++ int32_t data_fifo_size; /*!< Total number of dwords in the data FIFO memory. This
++ memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
++ Tx FIFOs.
++ 32 to 32768
++ */
++ #ifdef __IS_DEVICE__
++ int32_t rx_fifo_size; /*!< Number of dwords in the Rx FIFO in device mode.
++ 16 to 32768
++ */
++
++
++ int32_t tx_fifo_size[MAX_EPS_CHANNELS]; /*!< Number of dwords in each of the Tx FIFOs in device mode.
++ 4 to 768
++ */
++ #ifdef __DED_FIFO__
++ int32_t thr_ctl; /*!< Threshold control on/off */
++ int32_t tx_thr_length; /*!< Threshold length for Tx */
++ int32_t rx_thr_length; /*!< Threshold length for Rx*/
++ #endif
++ #else //__IS_HOST__
++ int32_t host_channels; /*!< The number of host channel registers to use.
++ 1 to 16
++ */
++
++ int32_t rx_fifo_size; /*!< Number of dwords in the Rx FIFO in host mode.
++ 16 to 32768
++ */
++
++ int32_t nperio_tx_fifo_size;/*!< Number of dwords in the non-periodic Tx FIFO in host mode.
++ 16 to 32768
++ */
++
++ int32_t perio_tx_fifo_size; /*!< Number of dwords in the host periodic Tx FIFO.
++ 16 to 32768
++ */
++ #endif //__IS_HOST__
++
++ int32_t max_transfer_size; /*!< The maximum transfer size supported in bytes.
++ 2047 to 65,535
++ */
++
++ int32_t max_packet_count; /*!< The maximum number of packets in a transfer.
++ 15 to 511 (default 511)
++ */
++ int32_t phy_utmi_width; /*!< Specifies the UTMI+ Data Width.
++ 8 or 16 bits (default 16)
++ */
++
++ int32_t turn_around_time_hs; /*!< Specifies the Turn-Around time at HS*/
++ int32_t turn_around_time_fs; /*!< Specifies the Turn-Around time at FS*/
++
++ int32_t timeout_cal_hs; /*!< Specifies the Timeout_Calibration at HS*/
++ int32_t timeout_cal_fs; /*!< Specifies the Timeout_Calibration at FS*/
++} ifxusb_params_t;
++
++///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++
++/*!
++ \struct ifxusb_core_if
++ \brief The ifx_core_if structure contains information needed to manage
++ the IFX USB controller acting in either host or device mode. It
++ represents the programming view of the controller as a whole.
++ */
++typedef struct ifxusb_core_if
++{
++ ifxusb_params_t params; /*!< Run-time Parameters */
++
++ uint8_t core_no; /*!< core number (used as id when multi-core case */
++ char *core_name; /*!< core name used for registration and informative purpose*/
++ int irq; /*!< irq number this core is hooked */
++
++ /*****************************************************************
++ * Structures and pointers to physical register interface.
++ *****************************************************************/
++ /** Core Global registers starting at offset 000h. */
++ ifxusb_core_global_regs_t *core_global_regs; /*!< pointer to Core Global Registers, offset at 000h */
++
++ /** Host-specific registers */
++ #ifdef __IS_HOST__
++ /** Host Global Registers starting at offset 400h.*/
++ ifxusb_host_global_regs_t *host_global_regs; /*!< pointer to Host Global Registers, offset at 400h */
++ #define IFXUSB_HOST_GLOBAL_REG_OFFSET 0x400
++ /** Host Port 0 Control and Status Register */
++ volatile uint32_t *hprt0; /*!< pointer to HPRT0 Registers, offset at 440h */
++ #define IFXUSB_HOST_PORT_REGS_OFFSET 0x440
++ /** Host Channel Specific Registers at offsets 500h-5FCh. */
++ ifxusb_hc_regs_t *hc_regs[MAX_EPS_CHANNELS]; /*!< pointer to Host-Channel n Registers, offset at 500h */
++ #define IFXUSB_HOST_CHAN_REGS_OFFSET 0x500
++ #define IFXUSB_CHAN_REGS_OFFSET 0x20
++ #endif
++
++ /** Device-specific registers */
++ #ifdef __IS_DEVICE__
++ /** Device Global Registers starting at offset 800h */
++ ifxusb_device_global_regs_t *dev_global_regs; /*!< pointer to Device Global Registers, offset at 800h */
++ #define IFXUSB_DEV_GLOBAL_REG_OFFSET 0x800
++
++ /** Device Logical IN Endpoint-Specific Registers 900h-AFCh */
++ ifxusb_dev_in_ep_regs_t *in_ep_regs[MAX_EPS_CHANNELS]; /*!< pointer to Device IN-EP Registers, offset at 900h */
++ #define IFXUSB_DEV_IN_EP_REG_OFFSET 0x900
++ #define IFXUSB_EP_REG_OFFSET 0x20
++ /** Device Logical OUT Endpoint-Specific Registers B00h-CFCh */
++ ifxusb_dev_out_ep_regs_t *out_ep_regs[MAX_EPS_CHANNELS];/*!< pointer to Device OUT-EP Registers, offset at 900h */
++ #define IFXUSB_DEV_OUT_EP_REG_OFFSET 0xB00
++ #endif
++
++ /** Power and Clock Gating Control Register */
++ volatile uint32_t *pcgcctl; /*!< pointer to Power and Clock Gating Control Registers, offset at E00h */
++ #define IFXUSB_PCGCCTL_OFFSET 0xE00
++
++ /** Push/pop addresses for endpoints or host channels.*/
++ uint32_t *data_fifo[MAX_EPS_CHANNELS]; /*!< pointer to FIFO access windows, offset at 1000h */
++ #define IFXUSB_DATA_FIFO_OFFSET 0x1000
++ #define IFXUSB_DATA_FIFO_SIZE 0x1000
++
++ uint32_t *data_fifo_dbg; /*!< pointer to FIFO debug windows, offset at 1000h */
++
++ /** Hardware Configuration -- stored here for convenience.*/
++ hwcfg1_data_t hwcfg1; /*!< preserved Hardware Configuration 1 */
++ hwcfg2_data_t hwcfg2; /*!< preserved Hardware Configuration 2 */
++ hwcfg3_data_t hwcfg3; /*!< preserved Hardware Configuration 3 */
++ hwcfg4_data_t hwcfg4; /*!< preserved Hardware Configuration 3 */
++ uint32_t snpsid; /*!< preserved SNPSID */
++
++ /*****************************************************************
++ * Run-time informations.
++ *****************************************************************/
++ /* Set to 1 if the core PHY interface bits in USBCFG have been initialized. */
++ uint8_t phy_init_done; /*!< indicated PHY is initialized. */
++
++ #ifdef __IS_HOST__
++ uint8_t queuing_high_bandwidth; /*!< Host mode, Queueing High Bandwidth. */
++ #endif
++} ifxusb_core_if_t;
++
++/*@}*//*IFXUSB_CIF*/
++
++
++/*!
++ \fn void *ifxusb_alloc_buf(size_t size, int clear)
++ \brief This function is called to allocate buffer of specified size.
++ The allocated buffer is mapped into DMA accessable address.
++ \param size Size in BYTE to be allocated
++ \param clear 0: don't do clear after buffer allocated, other: do clear to zero
++ \return 0/NULL: Fail; uncached pointer of allocated buffer
++ \ingroup IFXUSB_CIF
++ */
++extern void *ifxusb_alloc_buf(size_t size, int clear);
++
++/*!
++ \fn void ifxusb_free_buf(void *vaddr)
++ \brief This function is called to free allocated buffer.
++ \param vaddr the uncached pointer of the buffer
++ \ingroup IFXUSB_CIF
++ */
++extern void ifxusb_free_buf(void *vaddr);
++
++/*!
++ \fn int ifxusb_core_if_init(ifxusb_core_if_t *_core_if,
++ int _irq,
++ uint32_t _reg_base_addr,
++ uint32_t _fifo_base_addr,
++ uint32_t _fifo_dbg_addr)
++ \brief This function is called to initialize the IFXUSB CSR data
++ structures. The register addresses in the device and host
++ structures are initialized from the base address supplied by the
++ caller. The calling function must make the OS calls to get the
++ base address of the IFXUSB controller registers.
++ \param _core_if Pointer of core_if structure
++ \param _irq irq number
++ \param _reg_base_addr Base address of IFXUSB core registers
++ \param _fifo_base_addr Fifo base address
++ \param _fifo_dbg_addr Fifo debug address
++ \return 0: success;
++ \ingroup IFXUSB_CIF
++ */
++extern int ifxusb_core_if_init(ifxusb_core_if_t *_core_if,
++ int _irq,
++ uint32_t _reg_base_addr,
++ uint32_t _fifo_base_addr,
++ uint32_t _fifo_dbg_addr);
++
++
++/*!
++ \fn void ifxusb_core_if_remove(ifxusb_core_if_t *_core_if)
++ \brief This function free the mapped address in the IFXUSB CSR data structures.
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++extern void ifxusb_core_if_remove(ifxusb_core_if_t *_core_if);
++
++/*!
++ \fn void ifxusb_enable_global_interrupts( ifxusb_core_if_t *_core_if )
++ \brief This function enbles the controller's Global Interrupt in the AHB Config register.
++ \param _core_if Pointer of core_if structure
++ */
++extern void ifxusb_enable_global_interrupts( ifxusb_core_if_t *_core_if );
++
++/*!
++ \fn void ifxusb_disable_global_interrupts( ifxusb_core_if_t *_core_if )
++ \brief This function disables the controller's Global Interrupt in the AHB Config register.
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++extern void ifxusb_disable_global_interrupts( ifxusb_core_if_t *_core_if );
++
++/*!
++ \fn void ifxusb_flush_tx_fifo( ifxusb_core_if_t *_core_if, const int _num )
++ \brief Flush a Tx FIFO.
++ \param _core_if Pointer of core_if structure
++ \param _num Tx FIFO to flush. ( 0x10 for ALL TX FIFO )
++ \ingroup IFXUSB_CIF
++ */
++extern void ifxusb_flush_tx_fifo( ifxusb_core_if_t *_core_if, const int _num );
++
++/*!
++ \fn void ifxusb_flush_rx_fifo( ifxusb_core_if_t *_core_if )
++ \brief Flush Rx FIFO.
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++extern void ifxusb_flush_rx_fifo( ifxusb_core_if_t *_core_if );
++
++/*!
++ \fn void ifxusb_flush_both_fifo( ifxusb_core_if_t *_core_if )
++ \brief Flush ALL Rx and Tx FIFO.
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++extern void ifxusb_flush_both_fifo( ifxusb_core_if_t *_core_if );
++
++
++/*!
++ \fn int ifxusb_core_soft_reset(ifxusb_core_if_t *_core_if)
++ \brief Do core a soft reset of the core. Be careful with this because it
++ resets all the internal state machines of the core.
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++extern int ifxusb_core_soft_reset(ifxusb_core_if_t *_core_if);
++
++
++/*!
++ \brief Turn on the USB Core Power
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++*/
++extern void ifxusb_power_on (ifxusb_core_if_t *_core_if);
++
++/*!
++ \fn void ifxusb_power_off (ifxusb_core_if_t *_core_if)
++ \brief Turn off the USB Core Power
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++*/
++extern void ifxusb_power_off (ifxusb_core_if_t *_core_if);
++
++/*!
++ \fn void ifxusb_phy_power_on (ifxusb_core_if_t *_core_if)
++ \brief Turn on the USB PHY Power
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++*/
++extern void ifxusb_phy_power_on (ifxusb_core_if_t *_core_if);
++
++/*!
++ \fn void ifxusb_phy_power_off (ifxusb_core_if_t *_core_if)
++ \brief Turn off the USB PHY Power
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++*/
++extern void ifxusb_phy_power_off (ifxusb_core_if_t *_core_if);
++
++/*!
++ \fn void ifxusb_hard_reset(ifxusb_core_if_t *_core_if)
++ \brief Reset on the USB Core RCU
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++extern void ifxusb_hard_reset(ifxusb_core_if_t *_core_if);
++
++///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++
++
++#ifdef __IS_HOST__
++ /*!
++ \fn void ifxusb_host_core_init(ifxusb_core_if_t *_core_if, ifxusb_params_t *_params)
++ \brief This function initializes the IFXUSB controller registers for Host mode.
++ This function flushes the Tx and Rx FIFOs and it flushes any entries in the
++ request queues.
++ \param _core_if Pointer of core_if structure
++ \param _params parameters to be set
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_host_core_init(ifxusb_core_if_t *_core_if, ifxusb_params_t *_params);
++
++ /*!
++ \fn void ifxusb_host_enable_interrupts(ifxusb_core_if_t *_core_if)
++ \brief This function enables the Host mode interrupts.
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_host_enable_interrupts(ifxusb_core_if_t *_core_if);
++
++ /*!
++ \fn void ifxusb_host_disable_interrupts(ifxusb_core_if_t *_core_if)
++ \brief This function disables the Host mode interrupts.
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_host_disable_interrupts(ifxusb_core_if_t *_core_if);
++
++ #if defined(__IS_TWINPASS__)
++ extern void ifxusb_enable_afe_oc(void);
++ #endif
++
++ /*!
++ \fn void ifxusb_vbus_init(ifxusb_core_if_t *_core_if)
++ \brief This function init the VBUS control.
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_vbus_init(ifxusb_core_if_t *_core_if);
++
++ /*!
++ \fn void ifxusb_vbus_free(ifxusb_core_if_t *_core_if)
++ \brief This function free the VBUS control.
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_vbus_free(ifxusb_core_if_t *_core_if);
++
++ /*!
++ \fn void ifxusb_vbus_on(ifxusb_core_if_t *_core_if)
++ \brief Turn on the USB 5V VBus Power
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_vbus_on(ifxusb_core_if_t *_core_if);
++
++ /*!
++ \fn void ifxusb_vbus_off(ifxusb_core_if_t *_core_if)
++ \brief Turn off the USB 5V VBus Power
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_vbus_off(ifxusb_core_if_t *_core_if);
++
++ /*!
++ \fn int ifxusb_vbus(ifxusb_core_if_t *_core_if)
++ \brief Read Current VBus status
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++ extern int ifxusb_vbus(ifxusb_core_if_t *_core_if);
++
++ #if defined(__DO_OC_INT__) && defined(__DO_OC_INT_ENABLE__)
++ /*!
++ \fn void ifxusb_oc_int_on(void)
++ \brief Turn on the OC interrupt
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_oc_int_on(void);
++
++ /*!
++ \fn void ifxusb_oc_int_off(void)
++ \brief Turn off the OC interrupt
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_oc_int_off(void);
++ #endif //defined(__DO_OC_INT__) && defined(__DO_OC_INT_ENABLE__)
++#endif
++
++///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++
++
++#ifdef __IS_DEVICE__
++ /*!
++ \fn void ifxusb_dev_enable_interrupts(ifxusb_core_if_t *_core_if)
++ \brief This function enables the Device mode interrupts.
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_dev_enable_interrupts(ifxusb_core_if_t *_core_if);
++
++ /*!
++ \fn uint32_t ifxusb_dev_get_frame_number(ifxusb_core_if_t *_core_if)
++ \brief Gets the current USB frame number. This is the frame number from the last SOF packet.
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++ extern uint32_t ifxusb_dev_get_frame_number(ifxusb_core_if_t *_core_if);
++
++ /*!
++ \fn void ifxusb_dev_ep_set_stall(ifxusb_core_if_t *_core_if, uint8_t _epno, uint8_t _is_in)
++ \brief Set the EP STALL.
++ \param _core_if Pointer of core_if structure
++ \param _epno EP number
++ \param _is_in 1: is IN transfer
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_dev_ep_set_stall(ifxusb_core_if_t *_core_if, uint8_t _epno, uint8_t _is_in);
++
++ /*!
++ \fn void ifxusb_dev_ep_clear_stall(ifxusb_core_if_t *_core_if, uint8_t _epno, uint8_t _ep_type, uint8_t _is_in)
++ \brief Set the EP STALL.
++ \param _core_if Pointer of core_if structure
++ \param _epno EP number
++ \param _ep_type EP Type
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_dev_ep_clear_stall(ifxusb_core_if_t *_core_if, uint8_t _epno, uint8_t _ep_type, uint8_t _is_in);
++
++ /*!
++ \fn void ifxusb_dev_core_init(ifxusb_core_if_t *_core_if, ifxusb_params_t *_params)
++ \brief This function initializes the IFXUSB controller registers for Device mode.
++ This function flushes the Tx and Rx FIFOs and it flushes any entries in the
++ request queues.
++ This function validate the imported parameters and store the result in the CIF structure.
++ After
++ \param _core_if Pointer of core_if structure
++ \param _params structure of inported parameters
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_dev_core_init(ifxusb_core_if_t *_core_if, ifxusb_params_t *_params);
++#endif
++
++///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++
++#if defined(__GADGET_LED__) || defined(__HOST_LED__)
++ /*!
++ \fn void ifxusb_led_init(ifxusb_core_if_t *_core_if)
++ \brief This function init the LED control.
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_led_init(ifxusb_core_if_t *_core_if);
++
++ /*!
++ \fn void ifxusb_led_free(ifxusb_core_if_t *_core_if)
++ \brief This function free the LED control.
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_led_free(ifxusb_core_if_t *_core_if);
++
++ /*!
++ \fn void ifxusb_led(ifxusb_core_if_t *_core_if)
++ \brief This function trigger the LED access.
++ \param _core_if Pointer of core_if structure
++ \ingroup IFXUSB_CIF
++ */
++ extern void ifxusb_led(ifxusb_core_if_t *_core_if);
++#endif
++
++///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++
++/* internal routines for debugging */
++extern void ifxusb_dump_msg(const u8 *buf, unsigned int length);
++extern void ifxusb_dump_spram(ifxusb_core_if_t *_core_if);
++extern void ifxusb_dump_registers(ifxusb_core_if_t *_core_if);
++extern void ifxusb_clean_spram(ifxusb_core_if_t *_core_if,uint32_t dwords);
++
++///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++
++static inline uint32_t ifxusb_read_core_intr(ifxusb_core_if_t *_core_if)
++{
++ return (ifxusb_rreg(&_core_if->core_global_regs->gintsts) &
++ (ifxusb_rreg(&_core_if->core_global_regs->gintmsk)
++#ifdef __USE_TIMER_4_SOF__
++ | IFXUSB_SOF_INTR_MASK
++#endif
++ ));
++}
++
++static inline uint32_t ifxusb_read_otg_intr (ifxusb_core_if_t *_core_if)
++{
++ return (ifxusb_rreg (&_core_if->core_global_regs->gotgint));
++}
++
++static inline uint32_t ifxusb_mode(ifxusb_core_if_t *_core_if)
++{
++ return (ifxusb_rreg( &_core_if->core_global_regs->gintsts ) & 0x1);
++}
++static inline uint8_t ifxusb_is_device_mode(ifxusb_core_if_t *_core_if)
++{
++ return (ifxusb_mode(_core_if) != 1);
++}
++static inline uint8_t ifxusb_is_host_mode(ifxusb_core_if_t *_core_if)
++{
++ return (ifxusb_mode(_core_if) == 1);
++}
++
++///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++
++#ifdef __IS_HOST__
++ static inline uint32_t ifxusb_read_hprt0(ifxusb_core_if_t *_core_if)
++ {
++ hprt0_data_t hprt0;
++ hprt0.d32 = ifxusb_rreg(_core_if->hprt0);
++ hprt0.b.prtena = 0;
++ hprt0.b.prtconndet = 0;
++ hprt0.b.prtenchng = 0;
++ hprt0.b.prtovrcurrchng = 0;
++ return hprt0.d32;
++ }
++
++ static inline uint32_t ifxusb_read_host_all_channels_intr (ifxusb_core_if_t *_core_if)
++ {
++ return (ifxusb_rreg (&_core_if->host_global_regs->haint));
++ }
++
++ static inline uint32_t ifxusb_read_host_channel_intr (ifxusb_core_if_t *_core_if, int hc_num)
++ {
++ return (ifxusb_rreg (&_core_if->hc_regs[hc_num]->hcint));
++ }
++#endif
++
++#ifdef __IS_DEVICE__
++ static inline uint32_t ifxusb_read_dev_all_in_ep_intr(ifxusb_core_if_t *_core_if)
++ {
++ uint32_t v;
++ v = ifxusb_rreg(&_core_if->dev_global_regs->daint) &
++ ifxusb_rreg(&_core_if->dev_global_regs->daintmsk);
++ return (v & 0xffff);
++ }
++
++ static inline uint32_t ifxusb_read_dev_all_out_ep_intr(ifxusb_core_if_t *_core_if)
++ {
++ uint32_t v;
++ v = ifxusb_rreg(&_core_if->dev_global_regs->daint) &
++ ifxusb_rreg(&_core_if->dev_global_regs->daintmsk);
++ return ((v & 0xffff0000) >> 16);
++ }
++
++ static inline uint32_t ifxusb_read_dev_in_ep_intr(ifxusb_core_if_t *_core_if, int _ep_num)
++ {
++ uint32_t v;
++ v = ifxusb_rreg(&_core_if->in_ep_regs[_ep_num]->diepint) &
++ ifxusb_rreg(&_core_if->dev_global_regs->diepmsk);
++ return v;
++ }
++
++ static inline uint32_t ifxusb_read_dev_out_ep_intr(ifxusb_core_if_t *_core_if, int _ep_num)
++ {
++ uint32_t v;
++ v = ifxusb_rreg(&_core_if->out_ep_regs[_ep_num]->doepint) &
++ ifxusb_rreg(&_core_if->dev_global_regs->doepmsk);
++ return v;
++ }
++
++#endif
++
++extern void ifxusb_attr_create (void *_dev);
++
++extern void ifxusb_attr_remove (void *_dev);
++
++///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++
++#endif // !defined(__IFXUSB_CIF_H__)
++
++
+diff --git a/drivers/usb/ifxhcd/ifxusb_cif_d.c b/drivers/usb/ifxhcd/ifxusb_cif_d.c
+new file mode 100644
+index 0000000..36ab0e7
+--- /dev/null
++++ b/drivers/usb/ifxhcd/ifxusb_cif_d.c
+@@ -0,0 +1,458 @@
++/*****************************************************************************
++ ** FILE NAME : ifxusb_cif_d.c
++ ** PROJECT : IFX USB sub-system V3
++ ** MODULES : IFX USB sub-system Host and Device driver
++ ** SRC VERSION : 1.0
++ ** DATE : 1/Jan/2009
++ ** AUTHOR : Chen, Howard
++ ** DESCRIPTION : The Core Interface provides basic services for accessing and
++ ** managing the IFX USB hardware. These services are used by the
++ ** Peripheral Controller Driver only.
++ *****************************************************************************/
++
++/*!
++ \file ifxusb_cif_d.c
++ \ingroup IFXUSB_DRIVER_V3
++ \brief This file contains the interface to the IFX USB Core.
++*/
++
++#include <linux/version.h>
++#include "ifxusb_version.h"
++
++
++#include <asm/byteorder.h>
++#include <asm/unaligned.h>
++
++#ifdef __DEBUG__
++ #include <linux/jiffies.h>
++#endif
++
++#include "ifxusb_plat.h"
++#include "ifxusb_regs.h"
++#include "ifxusb_cif.h"
++
++#include "ifxpcd.h"
++
++
++
++/*!
++ \brief Initializes the DevSpd field of the DCFG register depending on the PHY type
++ and the enumeration speed of the device.
++ \param _core_if Pointer of core_if structure
++ */
++void ifxusb_dev_init_spd(ifxusb_core_if_t *_core_if)
++{
++ uint32_t val;
++ dcfg_data_t dcfg;
++
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ if (_core_if->params.speed == IFXUSB_PARAM_SPEED_FULL)
++ /* High speed PHY running at full speed */
++ val = 0x1;
++ else
++ /* High speed PHY running at high speed and full speed*/
++ val = 0x0;
++
++ IFX_DEBUGPL(DBG_CIL, "Initializing DCFG.DevSpd to 0x%1x\n", val);
++ dcfg.d32 = ifxusb_rreg(&_core_if->dev_global_regs->dcfg);
++ dcfg.b.devspd = val;
++ ifxusb_wreg(&_core_if->dev_global_regs->dcfg, dcfg.d32);
++}
++
++
++/*!
++ \brief This function enables the Device mode interrupts.
++ \param _core_if Pointer of core_if structure
++ */
++void ifxusb_dev_enable_interrupts(ifxusb_core_if_t *_core_if)
++{
++ gint_data_t intr_mask ={ .d32 = 0};
++ ifxusb_core_global_regs_t *global_regs = _core_if->core_global_regs;
++
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ IFX_DEBUGPL(DBG_CIL, "%s()\n", __func__);
++
++ /* Clear any pending OTG Interrupts */
++ ifxusb_wreg( &global_regs->gotgint, 0xFFFFFFFF);
++
++ /* Clear any pending interrupts */
++ ifxusb_wreg( &global_regs->gintsts, 0xFFFFFFFF);
++
++ /* Enable the interrupts in the GINTMSK.*/
++ intr_mask.b.modemismatch = 1;
++ intr_mask.b.conidstschng = 1;
++ intr_mask.b.wkupintr = 1;
++ intr_mask.b.disconnect = 1;
++ intr_mask.b.usbsuspend = 1;
++
++ intr_mask.b.usbreset = 1;
++ intr_mask.b.enumdone = 1;
++ intr_mask.b.inepintr = 1;
++ intr_mask.b.outepintr = 1;
++ intr_mask.b.erlysuspend = 1;
++ #ifndef __DED_FIFO__
++// intr_mask.b.epmismatch = 1;
++ #endif
++
++ ifxusb_mreg( &global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
++ IFX_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__, ifxusb_rreg( &global_regs->gintmsk));
++}
++
++/*!
++ \brief Gets the current USB frame number. This is the frame number from the last SOF packet.
++ \param _core_if Pointer of core_if structure
++ */
++uint32_t ifxusb_dev_get_frame_number(ifxusb_core_if_t *_core_if)
++{
++ dsts_data_t dsts;
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ dsts.d32 = ifxusb_rreg(&_core_if->dev_global_regs->dsts);
++ /* read current frame/microfreme number from DSTS register */
++ return dsts.b.soffn;
++}
++
++
++/*!
++ \brief Set the EP STALL.
++ */
++void ifxusb_dev_ep_set_stall(ifxusb_core_if_t *_core_if, uint8_t _epno, uint8_t _is_in)
++{
++ depctl_data_t depctl;
++ volatile uint32_t *depctl_addr;
++
++ IFX_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, _epno, (_is_in?"IN":"OUT"));
++
++ depctl_addr = (_is_in)? (&(_core_if->in_ep_regs [_epno]->diepctl)):
++ (&(_core_if->out_ep_regs[_epno]->doepctl));
++ depctl.d32 = ifxusb_rreg(depctl_addr);
++ depctl.b.stall = 1;
++
++ if (_is_in && depctl.b.epena)
++ depctl.b.epdis = 1;
++
++ ifxusb_wreg(depctl_addr, depctl.d32);
++ IFX_DEBUGPL(DBG_PCD,"DEPCTL=%0x\n",ifxusb_rreg(depctl_addr));
++ return;
++}
++
++/*!
++\brief Clear the EP STALL.
++ */
++void ifxusb_dev_ep_clear_stall(ifxusb_core_if_t *_core_if, uint8_t _epno, uint8_t _ep_type, uint8_t _is_in)
++{
++ depctl_data_t depctl;
++ volatile uint32_t *depctl_addr;
++
++ IFX_DEBUGPL(DBG_PCD, "%s ep%d-%s\n", __func__, _epno, (_is_in?"IN":"OUT"));
++
++ depctl_addr = (_is_in)? (&(_core_if->in_ep_regs [_epno]->diepctl)):
++ (&(_core_if->out_ep_regs[_epno]->doepctl));
++
++ depctl.d32 = ifxusb_rreg(depctl_addr);
++ /* clear the stall bits */
++ depctl.b.stall = 0;
++
++ /*
++ * USB Spec 9.4.5: For endpoints using data toggle, regardless
++ * of whether an endpoint has the Halt feature set, a
++ * ClearFeature(ENDPOINT_HALT) request always results in the
++ * data toggle being reinitialized to DATA0.
++ */
++ if (_ep_type == IFXUSB_EP_TYPE_INTR || _ep_type == IFXUSB_EP_TYPE_BULK)
++ depctl.b.setd0pid = 1; /* DATA0 */
++
++ ifxusb_wreg(depctl_addr, depctl.d32);
++ IFX_DEBUGPL(DBG_PCD,"DEPCTL=%0x\n",ifxusb_rreg(depctl_addr));
++ return;
++}
++
++/*!
++ \brief This function initializes the IFXUSB controller registers for Device mode.
++ This function flushes the Tx and Rx FIFOs and it flushes any entries in the
++ request queues.
++ \param _core_if Pointer of core_if structure
++ \param _params parameters to be set
++ */
++void ifxusb_dev_core_init(ifxusb_core_if_t *_core_if, ifxusb_params_t *_params)
++{
++ ifxusb_core_global_regs_t *global_regs = _core_if->core_global_regs;
++
++ gusbcfg_data_t usbcfg ={.d32 = 0};
++ gahbcfg_data_t ahbcfg ={.d32 = 0};
++ dcfg_data_t dcfg ={.d32 = 0};
++ grstctl_t resetctl ={.d32 = 0};
++ gotgctl_data_t gotgctl ={.d32 = 0};
++
++ uint32_t dir;
++ int i;
++
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ IFX_DEBUGPL(DBG_CILV, "%s(%p)\n",__func__,_core_if);
++
++ /* Copy Params */
++ _core_if->params.dma_burst_size = _params->dma_burst_size;
++ _core_if->params.speed = _params->speed;
++ if(_params->max_transfer_size < 2048 || _params->max_transfer_size > ((1 << (_core_if->hwcfg3.b.xfer_size_cntr_width + 11)) - 1) )
++ _core_if->params.max_transfer_size = ((1 << (_core_if->hwcfg3.b.xfer_size_cntr_width + 11)) - 1);
++ else
++ _core_if->params.max_transfer_size = _params->max_transfer_size;
++
++ if(_params->max_packet_count < 16 || _params->max_packet_count > ((1 << (_core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1) )
++ _core_if->params.max_packet_count= ((1 << (_core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1);
++ else
++ _core_if->params.max_packet_count= _params->max_packet_count;
++ _core_if->params.phy_utmi_width = _params->phy_utmi_width;
++ _core_if->params.turn_around_time_hs = _params->turn_around_time_hs;
++ _core_if->params.turn_around_time_fs = _params->turn_around_time_fs;
++ _core_if->params.timeout_cal_hs = _params->timeout_cal_hs;
++ _core_if->params.timeout_cal_fs = _params->timeout_cal_fs;
++
++ #ifdef __DED_FIFO__
++ _core_if->params.thr_ctl = _params->thr_ctl;
++ _core_if->params.tx_thr_length = _params->tx_thr_length;
++ _core_if->params.rx_thr_length = _params->rx_thr_length;
++ #endif
++
++ /* Reset the Controller */
++ do
++ {
++ while(ifxusb_core_soft_reset( _core_if ))
++ ifxusb_hard_reset(_core_if);
++ } while (ifxusb_is_host_mode(_core_if));
++
++ usbcfg.d32 = ifxusb_rreg(&global_regs->gusbcfg);
++ #if 0
++ #if defined(__DED_FIFO__)
++ usbcfg.b.ForceDevMode = 1;
++ usbcfg.b.ForceHstMode = 0;
++ #endif
++ #endif
++ usbcfg.b.term_sel_dl_pulse = 0;
++ ifxusb_wreg (&global_regs->gusbcfg, usbcfg.d32);
++
++ /* This programming sequence needs to happen in FS mode before any other
++ * programming occurs */
++ /* High speed PHY. */
++ if (!_core_if->phy_init_done)
++ {
++ _core_if->phy_init_done = 1;
++ /* HS PHY parameters. These parameters are preserved
++ * during soft reset so only program the first time. Do
++ * a soft reset immediately after setting phyif. */
++ usbcfg.b.ulpi_utmi_sel = 0; //UTMI+
++ usbcfg.b.phyif = ( _core_if->params.phy_utmi_width == 16)?1:0;
++ ifxusb_wreg( &global_regs->gusbcfg, usbcfg.d32);
++ /* Reset after setting the PHY parameters */
++ ifxusb_core_soft_reset( _core_if );
++ }
++
++ /* Program the GAHBCFG Register.*/
++ switch (_core_if->params.dma_burst_size)
++ {
++ case 0 :
++ ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_SINGLE;
++ break;
++ case 1 :
++ ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_INCR;
++ break;
++ case 4 :
++ ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_INCR4;
++ break;
++ case 8 :
++ ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_INCR8;
++ break;
++ case 16:
++ ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_INCR16;
++ break;
++ }
++ ahbcfg.b.dmaenable = 1;
++ ifxusb_wreg(&global_regs->gahbcfg, ahbcfg.d32);
++
++ /* Program the GUSBCFG register. */
++ usbcfg.d32 = ifxusb_rreg( &global_regs->gusbcfg );
++ usbcfg.b.hnpcap = 0;
++ usbcfg.b.srpcap = 0;
++ ifxusb_wreg( &global_regs->gusbcfg, usbcfg.d32);
++
++ /* Restart the Phy Clock */
++ ifxusb_wreg(_core_if->pcgcctl, 0);
++
++ /* Device configuration register */
++ ifxusb_dev_init_spd(_core_if);
++ dcfg.d32 = ifxusb_rreg( &_core_if->dev_global_regs->dcfg);
++ dcfg.b.perfrint = IFXUSB_DCFG_FRAME_INTERVAL_80;
++ #if defined(__DED_FIFO__)
++ #if defined(__DESC_DMA__)
++ dcfg.b.descdma = 1;
++ #else
++ dcfg.b.descdma = 0;
++ #endif
++ #endif
++
++ ifxusb_wreg( &_core_if->dev_global_regs->dcfg, dcfg.d32 );
++
++ /* Configure data FIFO sizes */
++ _core_if->params.data_fifo_size = _core_if->hwcfg3.b.dfifo_depth;
++ _core_if->params.rx_fifo_size = ifxusb_rreg(&global_regs->grxfsiz);
++ IFX_DEBUGPL(DBG_CIL, "Initial: FIFO Size=0x%06X\n" , _core_if->params.data_fifo_size);
++ IFX_DEBUGPL(DBG_CIL, " Rx FIFO Size=0x%06X\n", _core_if->params.rx_fifo_size);
++
++ _core_if->params.tx_fifo_size[0]= ifxusb_rreg(&global_regs->gnptxfsiz) >> 16;
++
++ #ifdef __DED_FIFO__
++ for (i=1; i <= _core_if->hwcfg4.b.num_in_eps; i++)
++ _core_if->params.tx_fifo_size[i] =
++ ifxusb_rreg(&global_regs->dptxfsiz_dieptxf[i-1]) >> 16;
++ #else
++ for (i=0; i < _core_if->hwcfg4.b.num_dev_perio_in_ep; i++)
++ _core_if->params.tx_fifo_size[i+1] =
++ ifxusb_rreg(&global_regs->dptxfsiz_dieptxf[i]) >> 16;
++ #endif
++
++ #ifdef __DEBUG__
++ #ifdef __DED_FIFO__
++ for (i=0; i <= _core_if->hwcfg4.b.num_in_eps; i++)
++ IFX_DEBUGPL(DBG_CIL, " Tx[%02d] FIFO Size=0x%06X\n",i, _core_if->params.tx_fifo_size[i]);
++ #else
++ IFX_DEBUGPL(DBG_CIL, " NPTx FIFO Size=0x%06X\n", _core_if->params.tx_fifo_size[0]);
++ for (i=0; i < _core_if->hwcfg4.b.num_dev_perio_in_ep; i++)
++ IFX_DEBUGPL(DBG_CIL, " PTx[%02d] FIFO Size=0x%06X\n",i, _core_if->params.tx_fifo_size[i+1]);
++ #endif
++ #endif
++
++ {
++ fifosize_data_t txfifosize;
++ if(_params->data_fifo_size >=0 && _params->data_fifo_size < _core_if->params.data_fifo_size)
++ _core_if->params.data_fifo_size = _params->data_fifo_size;
++
++
++ if(_params->rx_fifo_size >=0 && _params->rx_fifo_size < _core_if->params.rx_fifo_size)
++ _core_if->params.rx_fifo_size = _params->rx_fifo_size;
++ if(_core_if->params.data_fifo_size < _core_if->params.rx_fifo_size)
++ _core_if->params.rx_fifo_size = _core_if->params.data_fifo_size;
++ ifxusb_wreg( &global_regs->grxfsiz, _core_if->params.rx_fifo_size);
++
++ for (i=0; i < MAX_EPS_CHANNELS; i++)
++ if(_params->tx_fifo_size[i] >=0 && _params->tx_fifo_size[i] < _core_if->params.tx_fifo_size[i])
++ _core_if->params.tx_fifo_size[i] = _params->tx_fifo_size[i];
++
++ txfifosize.b.startaddr = _core_if->params.rx_fifo_size;
++ #ifdef __DED_FIFO__
++ if(txfifosize.b.startaddr + _core_if->params.tx_fifo_size[0] > _core_if->params.data_fifo_size)
++ _core_if->params.tx_fifo_size[0]= _core_if->params.data_fifo_size - txfifosize.b.startaddr;
++ txfifosize.b.depth=_core_if->params.tx_fifo_size[0];
++ ifxusb_wreg( &global_regs->gnptxfsiz, txfifosize.d32);
++ txfifosize.b.startaddr += _core_if->params.tx_fifo_size[0];
++ for (i=1; i <= _core_if->hwcfg4.b.num_in_eps; i++)
++ {
++ if(txfifosize.b.startaddr + _core_if->params.tx_fifo_size[i] > _core_if->params.data_fifo_size)
++ _core_if->params.tx_fifo_size[i]= _core_if->params.data_fifo_size - txfifosize.b.startaddr;
++ txfifosize.b.depth=_core_if->params.tx_fifo_size[i];
++ ifxusb_wreg( &global_regs->dptxfsiz_dieptxf[i-1], txfifosize.d32);
++ txfifosize.b.startaddr += _core_if->params.tx_fifo_size[i];
++ }
++ #else
++ if(txfifosize.b.startaddr + _core_if->params.tx_fifo_size[0] > _core_if->params.data_fifo_size)
++ _core_if->params.tx_fifo_size[0]= _core_if->params.data_fifo_size - txfifosize.b.startaddr;
++ txfifosize.b.depth=_core_if->params.tx_fifo_size[0];
++ ifxusb_wreg( &global_regs->gnptxfsiz, txfifosize.d32);
++ txfifosize.b.startaddr += _core_if->params.tx_fifo_size[0];
++ for (i=0; i < _core_if->hwcfg4.b.num_dev_perio_in_ep; i++)
++ {
++ if(txfifosize.b.startaddr + _core_if->params.tx_fifo_size[i+1] > _core_if->params.data_fifo_size)
++ _core_if->params.tx_fifo_size[i+1]= _core_if->params.data_fifo_size - txfifosize.b.startaddr;
++ //txfifosize.b.depth=_core_if->params.tx_fifo_size[i+1];
++ ifxusb_wreg( &global_regs->dptxfsiz_dieptxf[i], txfifosize.d32);
++ txfifosize.b.startaddr += _core_if->params.tx_fifo_size[i+1];
++ }
++ #endif
++ }
++
++ #ifdef __DEBUG__
++ {
++ fifosize_data_t fifosize;
++ IFX_DEBUGPL(DBG_CIL, "Result : FIFO Size=0x%06X\n" , _core_if->params.data_fifo_size);
++
++ IFX_DEBUGPL(DBG_CIL, " Rx FIFO =0x%06X Sz=0x%06X\n", 0,ifxusb_rreg(&global_regs->grxfsiz));
++ #ifdef __DED_FIFO__
++ fifosize.d32=ifxusb_rreg(&global_regs->gnptxfsiz);
++ IFX_DEBUGPL(DBG_CIL, " Tx[00] FIFO =0x%06X Sz=0x%06X\n", fifosize.b.startaddr,fifosize.b.depth);
++ for (i=1; i <= _core_if->hwcfg4.b.num_in_eps; i++)
++ {
++ fifosize.d32=ifxusb_rreg(&global_regs->dptxfsiz_dieptxf[i-1]);
++ IFX_DEBUGPL(DBG_CIL, " Tx[%02d] FIFO 0x%06X Sz=0x%06X\n",i, fifosize.b.startaddr,fifosize.b.depth);
++ }
++ #else
++ fifosize.d32=ifxusb_rreg(&global_regs->gnptxfsiz);
++ IFX_DEBUGPL(DBG_CIL, " NPTx FIFO =0x%06X Sz=0x%06X\n", fifosize.b.startaddr,fifosize.b.depth);
++ for (i=0; i < _core_if->hwcfg4.b.num_dev_perio_in_ep; i++)
++ {
++ fifosize.d32=ifxusb_rreg(&global_regs->dptxfsiz_dieptxf[i]);
++ IFX_DEBUGPL(DBG_CIL, " PTx[%02d] FIFO 0x%06X Sz=0x%06X\n",i, fifosize.b.startaddr,fifosize.b.depth);
++ }
++ #endif
++ }
++ #endif
++
++ /* Clear Host Set HNP Enable in the OTG Control Register */
++ gotgctl.b.hstsethnpen = 1;
++ ifxusb_mreg( &global_regs->gotgctl, gotgctl.d32, 0);
++
++ /* Flush the FIFOs */
++ ifxusb_flush_tx_fifo(_core_if, 0x10); /* all Tx FIFOs */
++ ifxusb_flush_rx_fifo(_core_if);
++
++ /* Flush the Learning Queue. */
++ resetctl.b.intknqflsh = 1;
++ ifxusb_wreg( &global_regs->grstctl, resetctl.d32);
++
++ /* Clear all pending Device Interrupts */
++ ifxusb_wreg( &_core_if->dev_global_regs->diepmsk , 0 );
++ ifxusb_wreg( &_core_if->dev_global_regs->doepmsk , 0 );
++ ifxusb_wreg( &_core_if->dev_global_regs->daint , 0xFFFFFFFF );
++ ifxusb_wreg( &_core_if->dev_global_regs->daintmsk, 0 );
++
++ dir=_core_if->hwcfg1.d32;
++ for (i=0; i <= _core_if->hwcfg2.b.num_dev_ep ; i++,dir>>=2)
++ {
++ depctl_data_t depctl;
++ if((dir&0x03)==0 || (dir&0x03) ==1)
++ {
++ depctl.d32 = ifxusb_rreg(&_core_if->in_ep_regs[i]->diepctl);
++ if (depctl.b.epena)
++ {
++ depctl.d32 = 0;
++ depctl.b.epdis = 1;
++ depctl.b.snak = 1;
++ }
++ else
++ depctl.d32 = 0;
++ ifxusb_wreg( &_core_if->in_ep_regs[i]->diepctl, depctl.d32);
++ #ifndef __DESC_DMA__
++ ifxusb_wreg( &_core_if->in_ep_regs[i]->dieptsiz, 0);
++ #endif
++ ifxusb_wreg( &_core_if->in_ep_regs[i]->diepdma, 0);
++ ifxusb_wreg( &_core_if->in_ep_regs[i]->diepint, 0xFF);
++ }
++
++ if((dir&0x03)==0 || (dir&0x03) ==2)
++ {
++ depctl.d32 = ifxusb_rreg(&_core_if->out_ep_regs[i]->doepctl);
++ if (depctl.b.epena)
++ {
++ depctl.d32 = 0;
++ depctl.b.epdis = 1;
++ depctl.b.snak = 1;
++ }
++ else
++ depctl.d32 = 0;
++ ifxusb_wreg( &_core_if->out_ep_regs[i]->doepctl, depctl.d32);
++ #ifndef __DESC_DMA__
++ ifxusb_wreg( &_core_if->out_ep_regs[i]->doeptsiz, 0);
++ #endif
++ ifxusb_wreg( &_core_if->out_ep_regs[i]->doepdma, 0);
++ ifxusb_wreg( &_core_if->out_ep_regs[i]->doepint, 0xFF);
++ }
++ }
++}
++
+diff --git a/drivers/usb/ifxhcd/ifxusb_cif_h.c b/drivers/usb/ifxhcd/ifxusb_cif_h.c
+new file mode 100644
+index 0000000..0f47ecd
+--- /dev/null
++++ b/drivers/usb/ifxhcd/ifxusb_cif_h.c
+@@ -0,0 +1,846 @@
++/*****************************************************************************
++ ** FILE NAME : ifxusb_cif_h.c
++ ** PROJECT : IFX USB sub-system V3
++ ** MODULES : IFX USB sub-system Host and Device driver
++ ** SRC VERSION : 1.0
++ ** DATE : 1/Jan/2009
++ ** AUTHOR : Chen, Howard
++ ** DESCRIPTION : The Core Interface provides basic services for accessing and
++ ** managing the IFX USB hardware. These services are used by the
++ ** Host Controller Driver only.
++ *****************************************************************************/
++
++/*!
++ \file ifxusb_cif_h.c
++ \ingroup IFXUSB_DRIVER_V3
++ \brief This file contains the interface to the IFX USB Core.
++*/
++#include <linux/version.h>
++#include "ifxusb_version.h"
++
++#include <asm/byteorder.h>
++#include <asm/unaligned.h>
++
++#ifdef __DEBUG__
++ #include <linux/jiffies.h>
++#endif
++#include <linux/platform_device.h>
++#include <linux/kernel.h>
++#include <linux/ioport.h>
++#if defined(__UEIP__)
++// #include <asm/ifx/ifx_board.h>
++#endif
++
++//#include <asm/ifx/ifx_gpio.h>
++#if defined(__UEIP__)
++// #include <asm/ifx/ifx_led.h>
++#endif
++
++#include "ifxusb_plat.h"
++#include "ifxusb_regs.h"
++#include "ifxusb_cif.h"
++
++#include "ifxhcd.h"
++
++#if !defined(__UEIP__)
++ #undef __USING_LED_AS_GPIO__
++#endif
++
++
++/*!
++ \brief This function enables the Host mode interrupts.
++ \param _core_if Pointer of core_if structure
++ */
++void ifxusb_host_enable_interrupts(ifxusb_core_if_t *_core_if)
++{
++ gint_data_t intr_mask ={ .d32 = 0};
++ ifxusb_core_global_regs_t *global_regs = _core_if->core_global_regs;
++
++ IFX_DEBUGPL(DBG_CIL, "%s()\n", __func__);
++
++ /* Clear any pending OTG Interrupts */
++ ifxusb_wreg( &global_regs->gotgint, 0xFFFFFFFF);
++
++ /* Clear any pending interrupts */
++ ifxusb_wreg( &global_regs->gintsts, 0xFFFFFFFF);
++
++ /* Enable the interrupts in the GINTMSK.*/
++
++ /* Common interrupts */
++ intr_mask.b.modemismatch = 1;
++ intr_mask.b.conidstschng = 1;
++ intr_mask.b.wkupintr = 1;
++ intr_mask.b.disconnect = 1;
++ intr_mask.b.usbsuspend = 1;
++
++ /* Host interrupts */
++ intr_mask.b.sofintr = 1;
++ intr_mask.b.portintr = 1;
++ intr_mask.b.hcintr = 1;
++
++ ifxusb_mreg( &global_regs->gintmsk, intr_mask.d32, intr_mask.d32);
++ IFX_DEBUGPL(DBG_CIL, "%s() gintmsk=%0x\n", __func__, ifxusb_rreg( &global_regs->gintmsk));
++}
++
++/*!
++ \brief This function disables the Host mode interrupts.
++ \param _core_if Pointer of core_if structure
++ */
++void ifxusb_host_disable_interrupts(ifxusb_core_if_t *_core_if)
++{
++ ifxusb_core_global_regs_t *global_regs = _core_if->core_global_regs;
++
++ IFX_DEBUGPL(DBG_CILV, "%s()\n", __func__);
++
++ #if 1
++ ifxusb_wreg( &global_regs->gintmsk, 0);
++ #else
++ /* Common interrupts */
++ {
++ gint_data_t intr_mask ={.d32 = 0};
++ intr_mask.b.modemismatch = 1;
++ intr_mask.b.rxstsqlvl = 1;
++ intr_mask.b.conidstschng = 1;
++ intr_mask.b.wkupintr = 1;
++ intr_mask.b.disconnect = 1;
++ intr_mask.b.usbsuspend = 1;
++
++ /* Host interrupts */
++ intr_mask.b.sofintr = 1;
++ intr_mask.b.portintr = 1;
++ intr_mask.b.hcintr = 1;
++ intr_mask.b.ptxfempty = 1;
++ intr_mask.b.nptxfempty = 1;
++ ifxusb_mreg(&global_regs->gintmsk, intr_mask.d32, 0);
++ }
++ #endif
++}
++
++/*!
++ \brief This function initializes the IFXUSB controller registers for Host mode.
++ This function flushes the Tx and Rx FIFOs and it flushes any entries in the
++ request queues.
++ \param _core_if Pointer of core_if structure
++ \param _params parameters to be set
++ */
++void ifxusb_host_core_init(ifxusb_core_if_t *_core_if, ifxusb_params_t *_params)
++{
++ ifxusb_core_global_regs_t *global_regs = _core_if->core_global_regs;
++
++ gusbcfg_data_t usbcfg ={.d32 = 0};
++ gahbcfg_data_t ahbcfg ={.d32 = 0};
++ gotgctl_data_t gotgctl ={.d32 = 0};
++
++ int i;
++
++ IFX_DEBUGPL(DBG_CILV, "%s(%p)\n",__func__,_core_if);
++
++ /* Copy Params */
++
++ _core_if->params.dma_burst_size = _params->dma_burst_size;
++ _core_if->params.speed = _params->speed;
++ _core_if->params.max_transfer_size = _params->max_transfer_size;
++ _core_if->params.max_packet_count = _params->max_packet_count;
++ _core_if->params.phy_utmi_width = _params->phy_utmi_width;
++ _core_if->params.turn_around_time_hs = _params->turn_around_time_hs;
++ _core_if->params.turn_around_time_fs = _params->turn_around_time_fs;
++ _core_if->params.timeout_cal_hs = _params->timeout_cal_hs;
++ _core_if->params.timeout_cal_fs = _params->timeout_cal_fs;
++
++ /* Reset the Controller */
++ do
++ {
++ while(ifxusb_core_soft_reset( _core_if ))
++ ifxusb_hard_reset(_core_if);
++ } while (ifxusb_is_device_mode(_core_if));
++
++ usbcfg.d32 = ifxusb_rreg(&global_regs->gusbcfg);
++// usbcfg.b.ulpi_ext_vbus_drv = 1;
++ usbcfg.b.term_sel_dl_pulse = 0;
++ ifxusb_wreg (&global_regs->gusbcfg, usbcfg.d32);
++
++ /* This programming sequence needs to happen in FS mode before any other
++ * programming occurs */
++ /* High speed PHY. */
++ if (!_core_if->phy_init_done)
++ {
++ _core_if->phy_init_done = 1;
++ /* HS PHY parameters. These parameters are preserved
++ * during soft reset so only program the first time. Do
++ * a soft reset immediately after setting phyif. */
++ usbcfg.b.ulpi_utmi_sel = 0; //UTMI+
++ usbcfg.b.phyif = ( _core_if->params.phy_utmi_width == 16)?1:0;
++ ifxusb_wreg( &global_regs->gusbcfg, usbcfg.d32);
++ /* Reset after setting the PHY parameters */
++ ifxusb_core_soft_reset( _core_if );
++ }
++
++ usbcfg.d32 = ifxusb_rreg(&global_regs->gusbcfg);
++// usbcfg.b.ulpi_fsls = 0;
++// usbcfg.b.ulpi_clk_sus_m = 0;
++ ifxusb_wreg(&global_regs->gusbcfg, usbcfg.d32);
++
++ /* Program the GAHBCFG Register.*/
++ switch (_core_if->params.dma_burst_size)
++ {
++ case 0 :
++ ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_SINGLE;
++ break;
++ case 1 :
++ ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_INCR;
++ break;
++ case 4 :
++ ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_INCR4;
++ break;
++ case 8 :
++ ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_INCR8;
++ break;
++ case 16:
++ ahbcfg.b.hburstlen = IFXUSB_GAHBCFG_INT_DMA_BURST_INCR16;
++ break;
++ }
++ ahbcfg.b.dmaenable = 1;
++ ifxusb_wreg(&global_regs->gahbcfg, ahbcfg.d32);
++
++ /* Program the GUSBCFG register. */
++ usbcfg.d32 = ifxusb_rreg( &global_regs->gusbcfg );
++ usbcfg.b.hnpcap = 0;
++ usbcfg.b.srpcap = 0;
++ ifxusb_wreg( &global_regs->gusbcfg, usbcfg.d32);
++
++ /* Restart the Phy Clock */
++ ifxusb_wreg(_core_if->pcgcctl, 0);
++
++ /* Initialize Host Configuration Register */
++ {
++ hcfg_data_t hcfg;
++ hcfg.d32 = ifxusb_rreg(&_core_if->host_global_regs->hcfg);
++ hcfg.b.fslspclksel = IFXUSB_HCFG_30_60_MHZ;
++ if (_params->speed == IFXUSB_PARAM_SPEED_FULL)
++ hcfg.b.fslssupp = 1;
++ ifxusb_wreg(&_core_if->host_global_regs->hcfg, hcfg.d32);
++ }
++
++ _core_if->params.host_channels=(_core_if->hwcfg2.b.num_host_chan + 1);
++
++ if(_params->host_channels>0 && _params->host_channels < _core_if->params.host_channels)
++ _core_if->params.host_channels = _params->host_channels;
++
++ /* Configure data FIFO sizes */
++ _core_if->params.data_fifo_size = _core_if->hwcfg3.b.dfifo_depth;
++ _core_if->params.rx_fifo_size = ifxusb_rreg(&global_regs->grxfsiz);
++ _core_if->params.nperio_tx_fifo_size= ifxusb_rreg(&global_regs->gnptxfsiz) >> 16;
++ _core_if->params.perio_tx_fifo_size = ifxusb_rreg(&global_regs->hptxfsiz) >> 16;
++ IFX_DEBUGPL(DBG_CIL, "Initial: FIFO Size=0x%06X\n" , _core_if->params.data_fifo_size);
++ IFX_DEBUGPL(DBG_CIL, " Rx FIFO Size=0x%06X\n", _core_if->params.rx_fifo_size);
++ IFX_DEBUGPL(DBG_CIL, " NPTx FIFO Size=0x%06X\n", _core_if->params.nperio_tx_fifo_size);
++ IFX_DEBUGPL(DBG_CIL, " PTx FIFO Size=0x%06X\n", _core_if->params.perio_tx_fifo_size);
++
++ {
++ fifosize_data_t txfifosize;
++ if(_params->data_fifo_size >=0 && _params->data_fifo_size < _core_if->params.data_fifo_size)
++ _core_if->params.data_fifo_size = _params->data_fifo_size;
++
++ if( _params->rx_fifo_size >= 0 && _params->rx_fifo_size < _core_if->params.rx_fifo_size)
++ _core_if->params.rx_fifo_size = _params->rx_fifo_size;
++ if( _params->nperio_tx_fifo_size >=0 && _params->nperio_tx_fifo_size < _core_if->params.nperio_tx_fifo_size)
++ _core_if->params.nperio_tx_fifo_size = _params->nperio_tx_fifo_size;
++ if( _params->perio_tx_fifo_size >=0 && _params->perio_tx_fifo_size < _core_if->params.perio_tx_fifo_size)
++ _core_if->params.perio_tx_fifo_size = _params->perio_tx_fifo_size;
++
++ if(_core_if->params.data_fifo_size < _core_if->params.rx_fifo_size)
++ _core_if->params.rx_fifo_size = _core_if->params.data_fifo_size;
++ ifxusb_wreg( &global_regs->grxfsiz, _core_if->params.rx_fifo_size);
++ txfifosize.b.startaddr = _core_if->params.rx_fifo_size;
++
++ if(txfifosize.b.startaddr + _core_if->params.nperio_tx_fifo_size > _core_if->params.data_fifo_size)
++ _core_if->params.nperio_tx_fifo_size = _core_if->params.data_fifo_size - txfifosize.b.startaddr;
++ txfifosize.b.depth=_core_if->params.nperio_tx_fifo_size;
++ ifxusb_wreg( &global_regs->gnptxfsiz, txfifosize.d32);
++ txfifosize.b.startaddr += _core_if->params.nperio_tx_fifo_size;
++
++ if(txfifosize.b.startaddr + _core_if->params.perio_tx_fifo_size > _core_if->params.data_fifo_size)
++ _core_if->params.perio_tx_fifo_size = _core_if->params.data_fifo_size - txfifosize.b.startaddr;
++ txfifosize.b.depth=_core_if->params.perio_tx_fifo_size;
++ ifxusb_wreg( &global_regs->hptxfsiz, txfifosize.d32);
++ txfifosize.b.startaddr += _core_if->params.perio_tx_fifo_size;
++ }
++
++ #ifdef __DEBUG__
++ {
++ fifosize_data_t fifosize;
++ IFX_DEBUGPL(DBG_CIL, "Result : FIFO Size=0x%06X\n" , _core_if->params.data_fifo_size);
++
++ fifosize.d32=ifxusb_rreg(&global_regs->grxfsiz);
++ IFX_DEBUGPL(DBG_CIL, " Rx FIFO =0x%06X 0x%06X\n", fifosize.b.startaddr,fifosize.b.depth);
++ fifosize.d32=ifxusb_rreg(&global_regs->gnptxfsiz);
++ IFX_DEBUGPL(DBG_CIL, " NPTx FIFO =0x%06X 0x%06X\n", fifosize.b.startaddr,fifosize.b.depth);
++ fifosize.d32=ifxusb_rreg(&global_regs->hptxfsiz);
++ IFX_DEBUGPL(DBG_CIL, " PTx FIFO =0x%06X 0x%06X\n", fifosize.b.startaddr,fifosize.b.depth);
++ }
++ #endif
++
++ /* Clear Host Set HNP Enable in the OTG Control Register */
++ gotgctl.b.hstsethnpen = 1;
++ ifxusb_mreg( &global_regs->gotgctl, gotgctl.d32, 0);
++
++ /* Flush the FIFOs */
++ ifxusb_flush_tx_fifo(_core_if, 0x10); /* all Tx FIFOs */
++ ifxusb_flush_rx_fifo(_core_if);
++
++ for (i = 0; i < _core_if->hwcfg2.b.num_host_chan + 1; i++)
++ {
++ hcchar_data_t hcchar;
++ hcchar.d32 = ifxusb_rreg(&_core_if->hc_regs[i]->hcchar);
++ hcchar.b.chen = 0;
++ hcchar.b.chdis = 1;
++ hcchar.b.epdir = 0;
++ ifxusb_wreg(&_core_if->hc_regs[i]->hcchar, hcchar.d32);
++ }
++ /* Halt all channels to put them into a known state. */
++ for (i = 0; i < _core_if->hwcfg2.b.num_host_chan + 1; i++)
++ {
++ hcchar_data_t hcchar;
++ int count = 0;
++
++ hcchar.d32 = ifxusb_rreg(&_core_if->hc_regs[i]->hcchar);
++ hcchar.b.chen = 1;
++ hcchar.b.chdis = 1;
++ hcchar.b.epdir = 0;
++ ifxusb_wreg(&_core_if->hc_regs[i]->hcchar, hcchar.d32);
++
++ IFX_DEBUGPL(DBG_HCDV, "%s: Halt channel %d\n", __func__, i);
++ do{
++ hcchar.d32 = ifxusb_rreg(&_core_if->hc_regs[i]->hcchar);
++ if (++count > 1000)
++ {
++ IFX_ERROR("%s: Unable to clear halt on channel %d\n", __func__, i);
++ break;
++ }
++ } while (hcchar.b.chen);
++ }
++}
++
++//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++
++#if defined(__UEIP__)
++ #if defined(IFX_GPIO_USB_VBUS) || defined(IFX_LEDGPIO_USB_VBUS) || defined(IFX_LEDLED_USB_VBUS)
++ int ifxusb_vbus_status =-1;
++ #endif
++
++ #if defined(IFX_GPIO_USB_VBUS1) || defined(IFX_LEDGPIO_USB_VBUS1) || defined(IFX_LEDLED_USB_VBUS1)
++ int ifxusb_vbus1_status =-1;
++ #endif
++
++ #if defined(IFX_GPIO_USB_VBUS2) || defined(IFX_LEDGPIO_USB_VBUS2) || defined(IFX_LEDLED_USB_VBUS2)
++ int ifxusb_vbus2_status =-1;
++ #endif
++
++ #if defined(IFX_LEDGPIO_USB_VBUS) || defined(IFX_LEDLED_USB_VBUS)
++ static void *g_usb_vbus_trigger = NULL;
++ #endif
++ #if defined(IFX_LEDGPIO_USB_VBUS1) || defined(IFX_LEDLED_USB_VBUS1)
++ static void *g_usb_vbus1_trigger = NULL;
++ #endif
++ #if defined(IFX_LEDGPIO_USB_VBUS2) || defined(IFX_LEDLED_USB_VBUS2)
++ static void *g_usb_vbus2_trigger = NULL;
++ #endif
++
++ #if defined(IFX_GPIO_USB_VBUS) || defined(IFX_GPIO_USB_VBUS1) || defined(IFX_GPIO_USB_VBUS2)
++ int ifxusb_vbus_gpio_inited=0;
++ #endif
++
++#else //defined(__UEIP__)
++ int ifxusb_vbus_gpio_inited=0;
++#endif
++
++//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
++
++void ifxusb_vbus_init(ifxusb_core_if_t *_core_if)
++{
++ #if defined(__UEIP__)
++ #if defined(IFX_LEDGPIO_USB_VBUS) || defined(IFX_LEDLED_USB_VBUS)
++ if ( !g_usb_vbus_trigger )
++ {
++ ifx_led_trigger_register("USB_VBUS", &g_usb_vbus_trigger);
++ if ( g_usb_vbus_trigger != NULL )
++ {
++ struct ifx_led_trigger_attrib attrib = {0};
++ attrib.delay_on = 0;
++ attrib.delay_off = 0;
++ attrib.timeout = 0;
++ attrib.def_value = 0;
++ attrib.flags = IFX_LED_TRIGGER_ATTRIB_DELAY_ON | IFX_LED_TRIGGER_ATTRIB_DELAY_OFF | IFX_LED_TRIGGER_ATTRIB_TIMEOUT | IFX_LED_TRIGGER_ATTRIB_DEF_VALUE;
++ IFX_DEBUGP("Reg USB power!!\n");
++ ifx_led_trigger_set_attrib(g_usb_vbus_trigger, &attrib);
++ ifxusb_vbus_status =0;
++ }
++ }
++ #endif
++ #if defined(IFX_LEDGPIO_USB_VBUS1) || defined(IFX_LEDLED_USB_VBUS1)
++ if(_core_if->core_no==0 && !g_usb_vbus1_trigger )
++ {
++ ifx_led_trigger_register("USB_VBUS1", &g_usb_vbus1_trigger);
++ if ( g_usb_vbus1_trigger != NULL )
++ {
++ struct ifx_led_trigger_attrib attrib = {0};
++ attrib.delay_on = 0;
++ attrib.delay_off = 0;
++ attrib.timeout = 0;
++ attrib.def_value = 0;
++ attrib.flags = IFX_LED_TRIGGER_ATTRIB_DELAY_ON | IFX_LED_TRIGGER_ATTRIB_DELAY_OFF | IFX_LED_TRIGGER_ATTRIB_TIMEOUT | IFX_LED_TRIGGER_ATTRIB_DEF_VALUE;
++ IFX_DEBUGP("Reg USB1 power!!\n");
++ ifx_led_trigger_set_attrib(g_usb_vbus1_trigger, &attrib);
++ ifxusb_vbus1_status =0;
++ }
++ }
++ #endif
++ #if defined(IFX_LEDGPIO_USB_VBUS2) || defined(IFX_LEDLED_USB_VBUS2)
++ if(_core_if->core_no==1 && !g_usb_vbus2_trigger )
++ {
++ ifx_led_trigger_register("USB_VBUS2", &g_usb_vbus2_trigger);
++ if ( g_usb_vbus2_trigger != NULL )
++ {
++ struct ifx_led_trigger_attrib attrib = {0};
++ attrib.delay_on = 0;
++ attrib.delay_off = 0;
++ attrib.timeout = 0;
++ attrib.def_value = 0;
++ attrib.flags = IFX_LED_TRIGGER_ATTRIB_DELAY_ON | IFX_LED_TRIGGER_ATTRIB_DELAY_OFF | IFX_LED_TRIGGER_ATTRIB_TIMEOUT | IFX_LED_TRIGGER_ATTRIB_DEF_VALUE;
++ IFX_DEBUGP("Reg USB2 power!!\n");
++ ifx_led_trigger_set_attrib(g_usb_vbus2_trigger, &attrib);
++ ifxusb_vbus2_status =0;
++ }
++ }
++ #endif
++
++ #if defined(IFX_GPIO_USB_VBUS) || defined(IFX_GPIO_USB_VBUS1) || defined(IFX_GPIO_USB_VBUS2)
++ /* == 20100712 AVM/WK use gpio_inited as bitmask == */
++ if(ifxusb_vbus_gpio_inited == 0)
++ {
++ if(!ifx_gpio_register(IFX_GPIO_MODULE_USB))
++ {
++ IFX_DEBUGP("Register USB VBus through GPIO OK!!\n");
++ #ifdef IFX_GPIO_USB_VBUS
++ ifxusb_vbus_status =0;
++ #endif //IFX_GPIO_USB_VBUS
++ #ifdef IFX_GPIO_USB_VBUS1
++ ifxusb_vbus1_status=0;
++ #endif //IFX_GPIO_USB_VBUS1
++ #ifdef IFX_GPIO_USB_VBUS2
++ ifxusb_vbus2_status=0;
++ #endif //IFX_GPIO_USB_VBUS2
++ ifxusb_vbus_gpio_inited|= (1<<_core_if->core_no);
++ }
++ else
++ IFX_PRINT("Register USB VBus Failed!!\n");
++ } else {
++ ifxusb_vbus_gpio_inited|= (1<<_core_if->core_no);
++ }
++ #endif //defined(IFX_GPIO_USB_VBUS) || defined(IFX_GPIO_USB_VBUS1) || defined(IFX_GPIO_USB_VBUS2)
++ #endif //defined(__UEIP__)
++}
++
++void ifxusb_vbus_free(ifxusb_core_if_t *_core_if)
++{
++ #if defined(__UEIP__)
++ #if defined(IFX_LEDGPIO_USB_VBUS) || defined(IFX_LEDLED_USB_VBUS)
++ if ( g_usb_vbus_trigger )
++ {
++ ifx_led_trigger_deregister(g_usb_vbus_trigger);
++ g_usb_vbus_trigger = NULL;
++ ifxusb_vbus_status =-1;
++ }
++ #endif
++ #if defined(IFX_LEDGPIO_USB_VBUS1) || defined(IFX_LEDLED_USB_VBUS1)
++ if(_core_if->core_no==0 && g_usb_vbus1_trigger )
++ {
++ ifx_led_trigger_deregister(g_usb_vbus1_trigger);
++ g_usb_vbus1_trigger = NULL;
++ ifxusb_vbus1_status =-1;
++ }
++ #endif
++ #if defined(IFX_LEDGPIO_USB_VBUS2) || defined(IFX_LEDLED_USB_VBUS2)
++ if(_core_if->core_no==1 && g_usb_vbus2_trigger )
++ {
++ ifx_led_trigger_deregister(g_usb_vbus2_trigger);
++ g_usb_vbus2_trigger = NULL;
++ ifxusb_vbus2_status =-1;
++ }
++ #endif
++
++ #if defined(IFX_GPIO_USB_VBUS) || defined(IFX_GPIO_USB_VBUS1) || defined(IFX_GPIO_USB_VBUS2)
++ /* == 20100712 AVM/WK use gpio_inited as bitmask == */
++ if((ifxusb_vbus_gpio_inited & (1<<_core_if->core_no)) == ifxusb_vbus_gpio_inited)
++ {
++ ifx_gpio_deregister(IFX_GPIO_MODULE_USB);
++ #ifdef IFX_GPIO_USB_VBUS
++ ifxusb_vbus_status =-1;
++ #endif //IFX_GPIO_USB_VBUS
++ #ifdef IFX_GPIO_USB_VBUS1
++ ifxusb_vbus1_status=-1;
++ #endif //IFX_GPIO_USB_VBUS1
++ #ifdef IFX_GPIO_USB_VBUS2
++ ifxusb_vbus2_status=-1;
++ #endif //IFX_GPIO_USB_VBUS2
++ }
++ ifxusb_vbus_gpio_inited &= ~(1<<_core_if->core_no);
++ #endif //defined(IFX_GPIO_USB_VBUS) || defined(IFX_GPIO_USB_VBUS1) || defined(IFX_GPIO_USB_VBUS2)
++ #endif //defined(__UEIP__)
++}
++
++
++/*!
++ \brief Turn on the USB 5V VBus Power
++ \param _core_if Pointer of core_if structure
++ */
++void ifxusb_vbus_on(ifxusb_core_if_t *_core_if)
++{
++ IFX_DEBUGP("SENDING VBus POWER UP\n");
++ #if defined(__UEIP__)
++ #if defined(IFX_LEDGPIO_USB_VBUS) || defined(IFX_LEDLED_USB_VBUS)
++ if ( g_usb_vbus_trigger && ifxusb_vbus_status==0)
++ {
++ ifx_led_trigger_activate(g_usb_vbus_trigger);
++ IFX_DEBUGP("Enable USB power!!\n");
++ ifxusb_vbus_status=1;
++ }
++ #endif
++ #if defined(IFX_LEDGPIO_USB_VBUS1) || defined(IFX_LEDLED_USB_VBUS1)
++ if(_core_if->core_no==0 && g_usb_vbus1_trigger && ifxusb_vbus1_status==0)
++ {
++ ifx_led_trigger_activate(g_usb_vbus1_trigger);
++ IFX_DEBUGP("Enable USB1 power!!\n");
++ ifxusb_vbus1_status=1;
++ }
++ #endif
++ #if defined(IFX_LEDGPIO_USB_VBUS2) || defined(IFX_LEDLED_USB_VBUS2)
++ if(_core_if->core_no==1 && g_usb_vbus2_trigger && ifxusb_vbus2_status==0)
++ {
++ ifx_led_trigger_activate(g_usb_vbus2_trigger);
++ IFX_DEBUGP("Enable USB2 power!!\n");
++ ifxusb_vbus2_status=1;
++ }
++ #endif
++
++ #if defined(IFX_GPIO_USB_VBUS) || defined(IFX_GPIO_USB_VBUS1) || defined(IFX_GPIO_USB_VBUS2)
++ if(ifxusb_vbus_gpio_inited)
++ {
++ #if defined(IFX_GPIO_USB_VBUS)
++ if(ifxusb_vbus_status==0)
++ {
++ ifx_gpio_output_set(IFX_GPIO_USB_VBUS,IFX_GPIO_MODULE_USB);
++ ifxusb_vbus_status=1;
++ }
++ #endif
++ #if defined(IFX_GPIO_USB_VBUS1)
++ if(_core_if->core_no==0 && ifxusb_vbus1_status==0)
++ {
++ ifx_gpio_output_set(IFX_GPIO_USB_VBUS1,IFX_GPIO_MODULE_USB);
++ ifxusb_vbus1_status=1;
++ }
++ #endif
++ #if defined(IFX_GPIO_USB_VBUS2)
++ if(_core_if->core_no==1 && ifxusb_vbus2_status==0)
++ {
++ ifx_gpio_output_set(IFX_GPIO_USB_VBUS2,IFX_GPIO_MODULE_USB);
++ ifxusb_vbus2_status=1;
++ }
++ #endif
++ }
++ #endif //defined(IFX_GPIO_USB_VBUS) || defined(IFX_GPIO_USB_VBUS1) || defined(IFX_GPIO_USB_VBUS2)
++ #else
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ ifxusb_vbus_status=1;
++ //usb_set_vbus_on();
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ set_bit (4, (volatile unsigned long *)AMAZON_SE_GPIO_P0_OUT);
++ ifxusb_vbus_status=1;
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ if(_core_if->core_no==0)
++ {
++ if (bsp_port_reserve_pin(1, 13, PORT_MODULE_USB) != 0)
++ {
++ IFX_PRINT("Can't enable USB1 5.5V power!!\n");
++ return;
++ }
++ bsp_port_clear_altsel0(1, 13, PORT_MODULE_USB);
++ bsp_port_clear_altsel1(1, 13, PORT_MODULE_USB);
++ bsp_port_set_dir_out(1, 13, PORT_MODULE_USB);
++ bsp_port_set_pudsel(1, 13, PORT_MODULE_USB);
++ bsp_port_set_puden(1, 13, PORT_MODULE_USB);
++ bsp_port_set_output(1, 13, PORT_MODULE_USB);
++ IFX_DEBUGP("Enable USB1 power!!\n");
++ ifxusb_vbus1_status=1;
++ }
++ else
++ {
++ if (bsp_port_reserve_pin(3, 4, PORT_MODULE_USB) != 0)
++ {
++ IFX_PRINT("Can't enable USB2 5.5V power!!\n");
++ return;
++ }
++ bsp_port_clear_altsel0(3, 4, PORT_MODULE_USB);
++ bsp_port_clear_altsel1(3, 4, PORT_MODULE_USB);
++ bsp_port_set_dir_out(3, 4, PORT_MODULE_USB);
++ bsp_port_set_pudsel(3, 4, PORT_MODULE_USB);
++ bsp_port_set_puden(3, 4, PORT_MODULE_USB);
++ bsp_port_set_output(3, 4, PORT_MODULE_USB);
++ IFX_DEBUGP("Enable USB2 power!!\n");
++ ifxusb_vbus2_status=1;
++ }
++ #endif //defined(__IS_AR9__)
++ #if defined(__IS_VR9__)
++ if(_core_if->core_no==0)
++ {
++ ifxusb_vbus1_status=1;
++ }
++ else
++ {
++ ifxusb_vbus2_status=1;
++ }
++ #endif //defined(__IS_VR9__)
++ #endif //defined(__UEIP__)
++}
++
++
++/*!
++ \brief Turn off the USB 5V VBus Power
++ \param _core_if Pointer of core_if structure
++ */
++void ifxusb_vbus_off(ifxusb_core_if_t *_core_if)
++{
++ IFX_DEBUGP("SENDING VBus POWER OFF\n");
++
++ #if defined(__UEIP__)
++ #if defined(IFX_LEDGPIO_USB_VBUS) || defined(IFX_LEDLED_USB_VBUS)
++ if ( g_usb_vbus_trigger && ifxusb_vbus_status==1)
++ {
++ ifx_led_trigger_deactivate(g_usb_vbus_trigger);
++ IFX_DEBUGP("Disable USB power!!\n");
++ ifxusb_vbus_status=0;
++ }
++ #endif
++ #if defined(IFX_LEDGPIO_USB_VBUS1) || defined(IFX_LEDLED_USB_VBUS1)
++ if(_core_if->core_no==0 && g_usb_vbus1_trigger && ifxusb_vbus1_status==1)
++ {
++ ifx_led_trigger_deactivate(g_usb_vbus1_trigger);
++ IFX_DEBUGP("Disable USB1 power!!\n");
++ ifxusb_vbus1_status=0;
++ }
++ #endif
++ #if defined(IFX_LEDGPIO_USB_VBUS2) || defined(IFX_LEDLED_USB_VBUS2)
++ if(_core_if->core_no==1 && g_usb_vbus2_trigger && ifxusb_vbus2_status==1)
++ {
++ ifx_led_trigger_deactivate(g_usb_vbus2_trigger);
++ IFX_DEBUGP("Disable USB2 power!!\n");
++ ifxusb_vbus2_status=0;
++ }
++ #endif
++
++ #if defined(IFX_GPIO_USB_VBUS) || defined(IFX_GPIO_USB_VBUS1) || defined(IFX_GPIO_USB_VBUS2)
++ if(ifxusb_vbus_gpio_inited)
++ {
++ #if defined(IFX_GPIO_USB_VBUS)
++ if(ifxusb_vbus_status==1)
++ {
++ ifx_gpio_output_clear(IFX_GPIO_USB_VBUS,IFX_GPIO_MODULE_USB);
++ ifxusb_vbus_status=0;
++ }
++ #endif
++ #if defined(IFX_GPIO_USB_VBUS1)
++ if(_core_if->core_no==0 && ifxusb_vbus1_status==1)
++ {
++ ifx_gpio_output_clear(IFX_GPIO_USB_VBUS1,IFX_GPIO_MODULE_USB);
++ ifxusb_vbus1_status=0;
++ }
++ #endif
++ #if defined(IFX_GPIO_USB_VBUS2)
++ if(_core_if->core_no==1 && ifxusb_vbus2_status==1)
++ {
++ ifx_gpio_output_clear(IFX_GPIO_USB_VBUS2,IFX_GPIO_MODULE_USB);
++ ifxusb_vbus2_status=0;
++ }
++ #endif
++ }
++ #endif //defined(IFX_GPIO_USB_VBUS) || defined(IFX_GPIO_USB_VBUS1) || defined(IFX_GPIO_USB_VBUS2)
++ #else
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ ifxusb_vbus_status=0;
++ //usb_set_vbus_on();
++ #endif //defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++ #if defined(__IS_AMAZON_SE__)
++ clear_bit (4, (volatile unsigned long *)AMAZON_SE_GPIO_P0_OUT);
++ ifxusb_vbus_status=0;
++ #endif //defined(__IS_AMAZON_SE__)
++ #if defined(__IS_AR9__)
++ if(_core_if->core_no==0)
++ {
++ if (bsp_port_reserve_pin(1, 13, PORT_MODULE_USB) != 0) {
++ IFX_PRINT("Can't Disable USB1 5.5V power!!\n");
++ return;
++ }
++ bsp_port_clear_altsel0(1, 13, PORT_MODULE_USB);
++ bsp_port_clear_altsel1(1, 13, PORT_MODULE_USB);
++ bsp_port_set_dir_out(1, 13, PORT_MODULE_USB);
++ bsp_port_set_pudsel(1, 13, PORT_MODULE_USB);
++ bsp_port_set_puden(1, 13, PORT_MODULE_USB);
++ bsp_port_clear_output(1, 13, PORT_MODULE_USB);
++ IFX_DEBUGP("Disable USB1 power!!\n");
++ ifxusb_vbus1_status=0;
++ }
++ else
++ {
++ if (bsp_port_reserve_pin(3, 4, PORT_MODULE_USB) != 0) {
++ IFX_PRINT("Can't Disable USB2 5.5V power!!\n");
++ return;
++ }
++ bsp_port_clear_altsel0(3, 4, PORT_MODULE_USB);
++ bsp_port_clear_altsel1(3, 4, PORT_MODULE_USB);
++ bsp_port_set_dir_out(3, 4, PORT_MODULE_USB);
++ bsp_port_set_pudsel(3, 4, PORT_MODULE_USB);
++ bsp_port_set_puden(3, 4, PORT_MODULE_USB);
++ bsp_port_clear_output(3, 4, PORT_MODULE_USB);
++ IFX_DEBUGP("Disable USB2 power!!\n");
++
++ ifxusb_vbus2_status=0;
++ }
++ #endif //defined(__IS_AR9__)
++ #if defined(__IS_VR9__)
++ if(_core_if->core_no==0)
++ {
++ ifxusb_vbus1_status=0;
++ }
++ else
++ {
++ ifxusb_vbus2_status=0;
++ }
++ #endif //defined(__IS_VR9__)
++ #endif //defined(__UEIP__)
++}
++
++
++
++/*!
++ \brief Read Current VBus status
++ \param _core_if Pointer of core_if structure
++ */
++int ifxusb_vbus(ifxusb_core_if_t *_core_if)
++{
++#if defined(__UEIP__)
++ #if defined(IFX_GPIO_USB_VBUS) || defined(IFX_LEDGPIO_USB_VBUS) || defined(IFX_LEDLED_USB_VBUS)
++ return (ifxusb_vbus_status);
++ #endif
++
++ #if defined(IFX_GPIO_USB_VBUS1) || defined(IFX_LEDGPIO_USB_VBUS1) || defined(IFX_LEDLED_USB_VBUS1)
++ if(_core_if->core_no==0)
++ return (ifxusb_vbus1_status);
++ #endif
++
++ #if defined(IFX_GPIO_USB_VBUS2) || defined(IFX_LEDGPIO_USB_VBUS2) || defined(IFX_LEDLED_USB_VBUS2)
++ if(_core_if->core_no==1)
++ return (ifxusb_vbus2_status);
++ #endif
++#else //defined(__UEIP__)
++#endif
++ return -1;
++}
++
++#if defined(__UEIP__)
++#else
++ #if defined(__IS_TWINPASS__)
++ #define ADSL_BASE 0x20000
++ #define CRI_BASE 0x31F00
++ #define CRI_CCR0 CRI_BASE + 0x00
++ #define CRI_CCR1 CRI_BASE + 0x01*4
++ #define CRI_CDC0 CRI_BASE + 0x02*4
++ #define CRI_CDC1 CRI_BASE + 0x03*4
++ #define CRI_RST CRI_BASE + 0x04*4
++ #define CRI_MASK0 CRI_BASE + 0x05*4
++ #define CRI_MASK1 CRI_BASE + 0x06*4
++ #define CRI_MASK2 CRI_BASE + 0x07*4
++ #define CRI_STATUS0 CRI_BASE + 0x08*4
++ #define CRI_STATUS1 CRI_BASE + 0x09*4
++ #define CRI_STATUS2 CRI_BASE + 0x0A*4
++ #define CRI_AMASK0 CRI_BASE + 0x0B*4
++ #define CRI_AMASK1 CRI_BASE + 0x0C*4
++ #define CRI_UPDCTL CRI_BASE + 0x0D*4
++ #define CRI_MADST CRI_BASE + 0x0E*4
++ // 0x0f is missing
++ #define CRI_EVENT0 CRI_BASE + 0x10*4
++ #define CRI_EVENT1 CRI_BASE + 0x11*4
++ #define CRI_EVENT2 CRI_BASE + 0x12*4
++
++ #define IRI_I_ENABLE 0x32000
++ #define STY_SMODE 0x3c004
++ #define AFE_TCR_0 0x3c0dc
++ #define AFE_ADDR_ADDR 0x3c0e8
++ #define AFE_RDATA_ADDR 0x3c0ec
++ #define AFE_WDATA_ADDR 0x3c0f0
++ #define AFE_CONFIG 0x3c0f4
++ #define AFE_SERIAL_CFG 0x3c0fc
++
++ #define DFE_BASE_ADDR 0xBE116000
++ //#define DFE_BASE_ADDR 0x9E116000
++
++ #define MEI_FR_ARCINT_C (DFE_BASE_ADDR + 0x0000001C)
++ #define MEI_DBG_WADDR_C (DFE_BASE_ADDR + 0x00000024)
++ #define MEI_DBG_RADDR_C (DFE_BASE_ADDR + 0x00000028)
++ #define MEI_DBG_DATA_C (DFE_BASE_ADDR + 0x0000002C)
++ #define MEI_DBG_DECO_C (DFE_BASE_ADDR + 0x00000030)
++ #define MEI_DBG_MASTER_C (DFE_BASE_ADDR + 0x0000003C)
++
++ static void WriteARCmem(uint32_t addr, uint32_t data)
++ {
++ writel(1 ,(volatile uint32_t *)MEI_DBG_MASTER_C);
++ writel(1 ,(volatile uint32_t *)MEI_DBG_DECO_C );
++ writel(addr ,(volatile uint32_t *)MEI_DBG_WADDR_C );
++ writel(data ,(volatile uint32_t *)MEI_DBG_DATA_C );
++ while( (ifxusb_rreg((volatile uint32_t *)MEI_FR_ARCINT_C) & 0x20) != 0x20 ){};
++ writel(0 ,(volatile uint32_t *)MEI_DBG_MASTER_C);
++ IFX_DEBUGP("WriteARCmem %08x %08x\n",addr,data);
++ };
++
++ static uint32_t ReadARCmem(uint32_t addr)
++ {
++ u32 data;
++ writel(1 ,(volatile uint32_t *)MEI_DBG_MASTER_C);
++ writel(1 ,(volatile uint32_t *)MEI_DBG_DECO_C );
++ writel(addr ,(volatile uint32_t *)MEI_DBG_RADDR_C );
++ while( (ifxusb_rreg((volatile uint32_t *)MEI_FR_ARCINT_C) & 0x20) != 0x20 ){};
++ data = ifxusb_rreg((volatile uint32_t *)MEI_DBG_DATA_C );
++ writel(0 ,(volatile uint32_t *)MEI_DBG_MASTER_C);
++ IFX_DEBUGP("ReadARCmem %08x %08x\n",addr,data);
++ return data;
++ };
++
++ void ifxusb_enable_afe_oc(void)
++ {
++ /* Start the clock */
++ WriteARCmem(CRI_UPDCTL ,0x00000008);
++ WriteARCmem(CRI_CCR0 ,0x00000014);
++ WriteARCmem(CRI_CCR1 ,0x00000500);
++ WriteARCmem(AFE_CONFIG ,0x000001c8);
++ WriteARCmem(AFE_SERIAL_CFG,0x00000016); // (DANUBE_PCI_CFG_BASE+(1<<addrline))AFE serial interface clock & data latch edge
++ WriteARCmem(AFE_TCR_0 ,0x00000002);
++ //Take afe out of reset
++ WriteARCmem(AFE_CONFIG ,0x000000c0);
++ WriteARCmem(IRI_I_ENABLE ,0x00000101);
++ WriteARCmem(STY_SMODE ,0x00001980);
++
++ ReadARCmem(CRI_UPDCTL );
++ ReadARCmem(CRI_CCR0 );
++ ReadARCmem(CRI_CCR1 );
++ ReadARCmem(AFE_CONFIG );
++ ReadARCmem(AFE_SERIAL_CFG); // (DANUBE_PCI_CFG_BASE+(1<<addrline))AFE serial interface clock & data latch edge
++ ReadARCmem(AFE_TCR_0 );
++ ReadARCmem(AFE_CONFIG );
++ ReadARCmem(IRI_I_ENABLE );
++ ReadARCmem(STY_SMODE );
++ }
++ #endif //defined(__IS_TWINPASS__)
++#endif //defined(__UEIP__)
++
++
+diff --git a/drivers/usb/ifxhcd/ifxusb_ctl.c b/drivers/usb/ifxhcd/ifxusb_ctl.c
+new file mode 100644
+index 0000000..ade8e13
+--- /dev/null
++++ b/drivers/usb/ifxhcd/ifxusb_ctl.c
+@@ -0,0 +1,1385 @@
++/*****************************************************************************
++ ** FILE NAME : ifxusb_ctl.c
++ ** PROJECT : IFX USB sub-system V3
++ ** MODULES : IFX USB sub-system Host and Device driver
++ ** SRC VERSION : 1.0
++ ** DATE : 1/Jan/2009
++ ** AUTHOR : Chen, Howard
++ ** DESCRIPTION : Implementing the procfs and sysfs for IFX USB driver
++ *****************************************************************************/
++
++/*! \file ifxusb_ctl.c
++ \ingroup IFXUSB_DRIVER_V3
++ \brief Implementing the procfs and sysfs for IFX USB driver
++*/
++
++#include <linux/version.h>
++#include "ifxusb_version.h"
++
++
++#include <linux/proc_fs.h>
++#include <asm/byteorder.h>
++#include <asm/unaligned.h>
++#include <asm/uaccess.h>
++
++#include "ifxusb_plat.h"
++#include "ifxusb_regs.h"
++#include "ifxusb_cif.h"
++
++#ifdef __IS_DEVICE__
++ #include "ifxpcd.h"
++#endif
++
++#ifdef __IS_HOST__
++ #include "ifxhcd.h"
++#endif
++
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/gfp.h>
++
++
++#ifdef __IS_HOST__
++ extern char ifxusb_driver_name[];
++
++ #ifdef __IS_DUAL__
++ extern ifxhcd_hcd_t ifxusb_hcd_1;
++ extern ifxhcd_hcd_t ifxusb_hcd_2;
++ extern char ifxusb_hcd_name_1[];
++ extern char ifxusb_hcd_name_2[];
++ #else
++ extern ifxhcd_hcd_t ifxusb_hcd;
++ extern char ifxusb_hcd_name[];
++ #endif
++
++#endif
++
++#ifdef __IS_DEVICE__
++ extern char ifxusb_driver_name[];
++
++ extern ifxpcd_pcd_t ifxusb_pcd;
++ extern char ifxusb_pcd_name[];
++#endif
++
++
++//Attributes for sysfs (for 2.6 only)
++
++extern struct device_attribute dev_attr_dbglevel;
++
++#ifdef __IS_DUAL__
++ extern struct device_attribute dev_attr_dump_params_1;
++ extern struct device_attribute dev_attr_dump_params_2;
++#else
++ extern struct device_attribute dev_attr_dump_params;
++#endif
++
++#ifdef __IS_DUAL__
++ extern struct device_attribute dev_attr_mode_1;
++ extern struct device_attribute dev_attr_mode_2;
++#else
++ extern struct device_attribute dev_attr_mode;
++#endif
++
++#ifdef __IS_HOST__
++ #ifdef __IS_DUAL__
++ extern struct device_attribute dev_attr_buspower_1;
++ extern struct device_attribute dev_attr_buspower_2;
++ extern struct device_attribute dev_attr_bussuspend_1;
++ extern struct device_attribute dev_attr_bussuspend_2;
++ extern struct device_attribute dev_attr_busconnected_1;
++ extern struct device_attribute dev_attr_busconnected_2;
++ extern struct device_attribute dev_attr_connectspeed_1;
++ extern struct device_attribute dev_attr_connectspeed_1;
++ #else
++ extern struct device_attribute dev_attr_buspower;
++ extern struct device_attribute dev_attr_bussuspend;
++ extern struct device_attribute dev_attr_busconnected;
++ extern struct device_attribute dev_attr_connectspeed;
++ #endif
++#endif //__IS_HOST__
++
++#ifdef __IS_DEVICE__
++ extern struct device_attribute dev_attr_devspeed;
++ extern struct device_attribute dev_attr_enumspeed;
++#endif //__IS_DEVICE__
++
++#ifdef __ENABLE_DUMP__
++ #ifdef __IS_DUAL__
++ extern struct device_attribute dev_attr_dump_reg_1;
++ extern struct device_attribute dev_attr_dump_reg_2;
++ extern struct device_attribute dev_attr_dump_spram_1;
++ extern struct device_attribute dev_attr_dump_spram_2;
++ #ifdef __IS_HOST__
++ extern struct device_attribute dev_attr_dump_host_state_1;
++ extern struct device_attribute dev_attr_dump_host_state_2;
++ #else
++ #endif
++ #else
++ extern struct device_attribute dev_attr_dump_reg;
++ extern struct device_attribute dev_attr_dump_spram;
++ #ifdef __IS_HOST__
++ extern struct device_attribute dev_attr_dump_host_state;
++ #else
++ #endif
++ #endif
++#endif //__ENABLE_DUMP__
++
++
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++
++static ssize_t procfs_dbglevel_show(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++{
++ #ifdef __IS_HOST__
++ return sprintf( buf, "%08X\n",h_dbg_lvl );
++ #else
++ return sprintf( buf, "%08X\n",d_dbg_lvl );
++ #endif
++}
++
++static ssize_t procfs_dbglevel_store(struct file *file, const char *buffer, unsigned long count, void *data)
++{
++ char buf[10];
++ int i = 0;
++ uint32_t value;
++ if (copy_from_user(buf, &buffer[i], sizeof("0xFFFFFFFF\n")+1))
++ return -EFAULT;
++ value = simple_strtoul(buf, NULL, 16);
++ #ifdef __IS_HOST__
++ h_dbg_lvl =value;
++ #else
++ d_dbg_lvl =value;
++ #endif
++ //turn on and off power
++ return count;
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_dbglevel_show( struct device *_dev, struct device_attribute *attr,char *buf)
++#else
++ static ssize_t sysfs_dbglevel_show( struct device *_dev, char *buf)
++#endif
++{
++ #ifdef __IS_HOST__
++ return sprintf( buf, "%08X\n",h_dbg_lvl );
++ #else
++ return sprintf( buf, "%08X\n",d_dbg_lvl );
++ #endif
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_dbglevel_store( struct device *_dev, struct device_attribute *attr,const char *buffer, size_t count )
++#else
++ static ssize_t sysfs_dbglevel_store( struct device *_dev, const char *buffer, size_t count )
++#endif
++{
++ char buf[10];
++ int i = 0;
++ uint32_t value;
++ if (copy_from_user(buf, &buffer[i], sizeof("0xFFFFFFFF\n")+1))
++ return -EFAULT;
++ value = simple_strtoul(buf, NULL, 16);
++ #ifdef __IS_HOST__
++ h_dbg_lvl =value;
++ #else
++ d_dbg_lvl =value;
++ #endif
++ //turn on and off power
++ return count;
++}
++
++DEVICE_ATTR(dbglevel, S_IRUGO|S_IWUSR, sysfs_dbglevel_show, sysfs_dbglevel_store);
++
++
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++
++static void ifxusb_dump_params(ifxusb_core_if_t *_core_if);
++
++#ifdef __IS_DUAL__
++ static void dump_params_1(void)
++ {
++ ifxusb_dump_params(&ifxusb_hcd_1.core_if);
++ }
++ static void dump_params_2(void)
++ {
++ ifxusb_dump_params(&ifxusb_hcd_2.core_if);
++ }
++
++ static ssize_t procfs_dump_params_show_1(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ dump_params_1();
++ return 0;
++ }
++ static ssize_t procfs_dump_params_show_2(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ dump_params_2();
++ return 0;
++ }
++
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_dump_params_show_1( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_dump_params_show_1( struct device *_dev,char *buf)
++ #endif
++ {
++ dump_params_1();
++ return 0;
++ }
++ DEVICE_ATTR(dump_params_1, S_IRUGO|S_IWUSR, sysfs_dump_params_show_1, NULL);
++
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_dump_params_show_2( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_dump_params_show_2( struct device *_dev,char *buf)
++ #endif
++ {
++ dump_params_2();
++ return 0;
++ }
++
++ DEVICE_ATTR(dump_params_2, S_IRUGO|S_IWUSR, sysfs_dump_params_show_2, NULL);
++#else
++ static void dump_params(void)
++ {
++ #ifdef __IS_HOST__
++ ifxusb_dump_params(&ifxusb_hcd.core_if);
++ #else
++ ifxusb_dump_params(&ifxusb_pcd.core_if);
++ #endif
++ }
++
++ static ssize_t procfs_dump_params_show(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ dump_params();
++ return 0;
++ }
++
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_dump_params_show( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_dump_params_show( struct device *_dev,char *buf)
++ #endif
++ {
++ dump_params();
++ return 0;
++ }
++ DEVICE_ATTR(dump_params, S_IRUGO|S_IWUSR, sysfs_dump_params_show, NULL);
++#endif
++
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++
++#ifdef __IS_DUAL__
++ static ssize_t mode_show_1(char *buf)
++ {
++ if((ifxusb_rreg(&ifxusb_hcd_1.core_if.core_global_regs->gintsts ) & 0x1) == 1)
++ return sprintf( buf, "HOST\n" );
++ else
++ return sprintf( buf, "DEVICE(INCORRECT!)\n" );
++ }
++
++ static ssize_t mode_show_2(char *buf)
++ {
++ if((ifxusb_rreg(&ifxusb_hcd_2.core_if.core_global_regs->gintsts ) & 0x1) == 1)
++ return sprintf( buf, "HOST\n" );
++ else
++ return sprintf( buf, "DEVICE(INCORRECT!)\n" );
++ }
++
++ static ssize_t procfs_mode_show_1(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return mode_show_1(buf);
++ }
++ static ssize_t procfs_mode_show_2(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return mode_show_2(buf);
++ }
++
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_mode_show_1( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_mode_show_1( struct device *_dev,char *buf)
++ #endif
++ {
++ return mode_show_1(buf);
++ }
++
++ DEVICE_ATTR(mode_1, S_IRUGO|S_IWUSR, sysfs_mode_show_1, 0);
++
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_mode_show_2( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_mode_show_2( struct device *_dev,char *buf)
++ #endif
++ {
++ return mode_show_2(buf);
++ }
++ DEVICE_ATTR(mode_2, S_IRUGO|S_IWUSR, sysfs_mode_show_2, NULL);
++#else
++ static ssize_t mode_show(char *buf)
++ {
++ #ifdef __IS_HOST__
++ if((ifxusb_rreg(&ifxusb_hcd.core_if.core_global_regs->gintsts ) & 0x1) == 1)
++ return sprintf( buf, "HOST\n" );
++ else
++ return sprintf( buf, "DEVICE(INCORRECT!)\n" );
++ #else
++ if((ifxusb_rreg(&ifxusb_pcd.core_if.core_global_regs->gintsts ) & 0x1) != 1)
++ return sprintf( buf, "DEVICE\n" );
++ else
++ return sprintf( buf, "HOST(INCORRECT!)\n" );
++ #endif
++ }
++ static ssize_t procfs_mode_show(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return mode_show(buf);
++ }
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_mode_show( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_mode_show( struct device *_dev, char *buf)
++ #endif
++ {
++ return mode_show(buf);
++ }
++ DEVICE_ATTR(mode, S_IRUGO|S_IWUSR, sysfs_mode_show, NULL);
++#endif
++
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++
++#ifdef __IS_HOST__
++ #ifdef __IS_DUAL__
++ static ssize_t buspower_show_1(char *buf)
++ {
++ if(ifxusb_vbus (&ifxusb_hcd_1.core_if)==1) return sprintf( buf, "1\n" );
++ if(ifxusb_vbus (&ifxusb_hcd_1.core_if)==0) return sprintf( buf, "0\n" );
++ return sprintf( buf, "UNKNOWN\n" );
++ }
++ static void buspower_store_1(uint32_t value)
++ {
++ if (value==1) ifxusb_vbus_on (&ifxusb_hcd_1.core_if);
++ else if(value==0) ifxusb_vbus_off(&ifxusb_hcd_1.core_if);
++ }
++ static ssize_t buspower_show_2(char *buf)
++ {
++ if(ifxusb_vbus (&ifxusb_hcd_2.core_if)==1) return sprintf( buf, "1\n" );
++ if(ifxusb_vbus (&ifxusb_hcd_2.core_if)==0) return sprintf( buf, "0\n" );
++ return sprintf( buf, "UNKNOWN\n" );
++ }
++ static void buspower_store_2(uint32_t value)
++ {
++ if (value==1) ifxusb_vbus_on (&ifxusb_hcd_2.core_if);
++ else if(value==0) ifxusb_vbus_off(&ifxusb_hcd_2.core_if);
++ }
++ static ssize_t procfs_buspower_show_1(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return buspower_show_1(buf);
++ }
++ static ssize_t procfs_buspower_store_1(struct file *file, const char *buffer, unsigned long count, void *data)
++ {
++ char buf[10];
++ int i = 0;
++ uint32_t value;
++ if (copy_from_user(buf, &buffer[i], sizeof("0xFFFFFFFF\n")+1))
++ return -EFAULT;
++ value = simple_strtoul(buf, NULL, 16);
++ buspower_store_1(value);
++ return count;
++ }
++ static ssize_t procfs_buspower_show_2(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return buspower_show_2(buf);
++ }
++ static ssize_t procfs_buspower_store_2(struct file *file, const char *buffer, unsigned long count, void *data)
++ {
++ char buf[10];
++ int i = 0;
++ uint32_t value;
++ if (copy_from_user(buf, &buffer[i], sizeof("0xFFFFFFFF\n")+1))
++ return -EFAULT;
++ value = simple_strtoul(buf, NULL, 16);
++ buspower_store_2(value);
++ return count;
++ }
++
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_buspower_show_1( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_buspower_show_1( struct device *_dev,char *buf)
++ #endif
++ {
++ return buspower_show_1(buf);
++ }
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_buspower_store_1( struct device *_dev, struct device_attribute *attr,const char *buffer, size_t count )
++ #else
++ static ssize_t sysfs_buspower_store_1( struct device *_dev, const char *buffer, size_t count )
++ #endif
++ {
++ char buf[10];
++ int i = 0;
++ uint32_t value;
++ if (copy_from_user(buf, &buffer[i], sizeof("0xFFFFFFFF\n")+1))
++ return -EFAULT;
++ value = simple_strtoul(buf, NULL, 16);
++ buspower_store_1(value);
++ return count;
++ }
++ DEVICE_ATTR(buspower_1, S_IRUGO|S_IWUSR, sysfs_buspower_show_1, sysfs_buspower_store_1);
++
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_buspower_show_2( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_buspower_show_2( struct device *_dev,char *buf)
++ #endif
++ {
++ return buspower_show_2(buf);
++ }
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_buspower_store_2( struct device *_dev, struct device_attribute *attr,const char *buffer, size_t count )
++ #else
++ static ssize_t sysfs_buspower_store_2( struct device *_dev, const char *buffer, size_t count )
++ #endif
++ {
++ char buf[10];
++ int i = 0;
++ uint32_t value;
++ if (copy_from_user(buf, &buffer[i], sizeof("0xFFFFFFFF\n")+1))
++ return -EFAULT;
++ value = simple_strtoul(buf, NULL, 16);
++ buspower_store_2(value);
++ return count;
++ }
++ DEVICE_ATTR(buspower_2, S_IRUGO|S_IWUSR, sysfs_buspower_show_2, sysfs_buspower_store_2);
++ #else
++ static ssize_t buspower_show(char *buf)
++ {
++ if(ifxusb_vbus (&ifxusb_hcd.core_if)==1) return sprintf( buf, "1\n" );
++ if(ifxusb_vbus (&ifxusb_hcd.core_if)==0) return sprintf( buf, "0\n" );
++ return sprintf( buf, "UNKNOWN\n" );
++ }
++ static void buspower_store(uint32_t value)
++ {
++ if (value==1) ifxusb_vbus_on (&ifxusb_hcd.core_if);
++ else if(value==0) ifxusb_vbus_off(&ifxusb_hcd.core_if);
++ }
++ static ssize_t procfs_buspower_show(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return buspower_show(buf);
++ }
++ static ssize_t procfs_buspower_store(struct file *file, const char *buffer, unsigned long count, void *data)
++ {
++ char buf[10];
++ int i = 0;
++ uint32_t value;
++ if (copy_from_user(buf, &buffer[i], sizeof("0xFFFFFFFF\n")+1))
++ return -EFAULT;
++ value = simple_strtoul(buf, NULL, 16);
++ buspower_store(value);
++ return count;
++ }
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_buspower_show( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_buspower_show( struct device *_dev, char *buf)
++ #endif
++ {
++ return buspower_show(buf);
++ }
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_buspower_store( struct device *_dev, struct device_attribute *attr,const char *buffer, size_t count )
++ #else
++ static ssize_t sysfs_buspower_store( struct device *_dev, const char *buffer, size_t count )
++ #endif
++ {
++ char buf[10];
++ int i = 0;
++ uint32_t value;
++ if (copy_from_user(buf, &buffer[i], sizeof("0xFFFFFFFF\n")+1))
++ return -EFAULT;
++ value = simple_strtoul(buf, NULL, 16);
++ buspower_store(value);
++ return count;
++ }
++ DEVICE_ATTR(buspower, S_IRUGO|S_IWUSR, sysfs_buspower_show, sysfs_buspower_store);
++ #endif
++
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++
++
++ #ifdef __IS_DUAL__
++ static ssize_t bussuspend_show_1(char *buf)
++ {
++ hprt0_data_t val;
++ val.d32 = ifxusb_rreg(ifxusb_hcd_1.core_if.hprt0);
++ return sprintf (buf, "Bus Suspend = 0x%x\n", val.b.prtsusp);
++ }
++ static ssize_t bussuspend_show_2(char *buf)
++ {
++ hprt0_data_t val;
++ val.d32 = ifxusb_rreg(ifxusb_hcd_2.core_if.hprt0);
++ return sprintf (buf, "Bus Suspend = 0x%x\n", val.b.prtsusp);
++ }
++
++ static ssize_t procfs_bussuspend_show_1(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return bussuspend_show_1(buf);
++ }
++ static ssize_t procfs_bussuspend_show_2(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return bussuspend_show_2(buf);
++ }
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_bussuspend_show_1( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_bussuspend_show_1( struct device *_dev,char *buf)
++ #endif
++ {
++ return bussuspend_show_1(buf);
++ }
++ DEVICE_ATTR(bussuspend_1, S_IRUGO|S_IWUSR, sysfs_bussuspend_show_1, 0);
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_bussuspend_show_2( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_bussuspend_show_2( struct device *_dev,char *buf)
++ #endif
++ {
++ return bussuspend_show_2(buf);
++ }
++ DEVICE_ATTR(bussuspend_2, S_IRUGO|S_IWUSR, sysfs_bussuspend_show_2, 0);
++ #else
++ static ssize_t bussuspend_show(char *buf)
++ {
++ hprt0_data_t val;
++ val.d32 = ifxusb_rreg(ifxusb_hcd.core_if.hprt0);
++ return sprintf (buf, "Bus Suspend = 0x%x\n", val.b.prtsusp);
++ }
++ static ssize_t procfs_bussuspend_show(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return bussuspend_show(buf);
++ }
++
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_bussuspend_show( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_bussuspend_show( struct device *_dev, char *buf)
++ #endif
++ {
++ return bussuspend_show(buf);
++ }
++ DEVICE_ATTR(bussuspend, S_IRUGO|S_IWUSR, sysfs_bussuspend_show, 0);
++ #endif
++
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++
++ #ifdef __IS_DUAL__
++ static ssize_t busconnected_show_1(char *buf)
++ {
++ hprt0_data_t val;
++ val.d32 = ifxusb_rreg(ifxusb_hcd_1.core_if.hprt0);
++ return sprintf (buf, "Bus Connected = 0x%x\n", val.b.prtconnsts);
++ }
++ static ssize_t busconnected_show_2(char *buf)
++ {
++ hprt0_data_t val;
++ val.d32 = ifxusb_rreg(ifxusb_hcd_2.core_if.hprt0);
++ return sprintf (buf, "Bus Connected = 0x%x\n", val.b.prtconnsts);
++ }
++
++ static ssize_t procfs_busconnected_show_1(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return busconnected_show_1(buf);
++ }
++ static ssize_t procfs_busconnected_show_2(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return busconnected_show_2(buf);
++ }
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_busconnected_show_1( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_busconnected_show_1( struct device *_dev,char *buf)
++ #endif
++ {
++ return busconnected_show_1(buf);
++ }
++ DEVICE_ATTR(busconnected_1, S_IRUGO|S_IWUSR, sysfs_busconnected_show_1, 0);
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_busconnected_show_2( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_busconnected_show_2( struct device *_dev,char *buf)
++ #endif
++ {
++ return busconnected_show_2(buf);
++ }
++ DEVICE_ATTR(busconnected_2, S_IRUGO|S_IWUSR, sysfs_busconnected_show_2, 0);
++ #else
++ static ssize_t busconnected_show(char *buf)
++ {
++ hprt0_data_t val;
++ val.d32 = ifxusb_rreg(ifxusb_hcd.core_if.hprt0);
++ return sprintf (buf, "Bus Connected = 0x%x\n", val.b.prtconnsts);
++ }
++ static ssize_t procfs_busconnected_show(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return busconnected_show(buf);
++ }
++
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_busconnected_show( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_busconnected_show( struct device *_dev, char *buf)
++ #endif
++ {
++ return busconnected_show(buf);
++ }
++ DEVICE_ATTR(busconnected, S_IRUGO|S_IWUSR, sysfs_busconnected_show, 0);
++ #endif
++
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++
++ #ifdef __IS_DUAL__
++ static ssize_t connectspeed_show_1(char *buf)
++ {
++ hprt0_data_t val;
++ val.d32 = ifxusb_rreg(ifxusb_hcd_1.core_if.hprt0);
++ if( val.b.prtspd ==0) return sprintf (buf, "Bus Speed = High (%d)\n", val.b.prtspd);
++ if( val.b.prtspd ==1) return sprintf (buf, "Bus Speed = Full (%d)\n", val.b.prtspd);
++ if( val.b.prtspd ==2) return sprintf (buf, "Bus Speed = Low (%d)\n", val.b.prtspd);
++ return sprintf (buf, "Bus Speed = Unknown (%d)\n", val.b.prtspd);
++ }
++ static ssize_t connectspeed_show_2(char *buf)
++ {
++ hprt0_data_t val;
++ val.d32 = ifxusb_rreg(ifxusb_hcd_2.core_if.hprt0);
++ if( val.b.prtspd ==0) return sprintf (buf, "Bus Speed = High (%d)\n", val.b.prtspd);
++ if( val.b.prtspd ==1) return sprintf (buf, "Bus Speed = Full (%d)\n", val.b.prtspd);
++ if( val.b.prtspd ==2) return sprintf (buf, "Bus Speed = Low (%d)\n", val.b.prtspd);
++ return sprintf (buf, "Bus Speed = Unknown (%d)\n", val.b.prtspd);
++ }
++
++ static ssize_t procfs_connectspeed_show_1(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return connectspeed_show_1(buf);
++ }
++ static ssize_t procfs_connectspeed_show_2(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return connectspeed_show_2(buf);
++ }
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_connectspeed_show_1( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_connectspeed_show_1( struct device *_dev,char *buf)
++ #endif
++ {
++ return connectspeed_show_1(buf);
++ }
++ DEVICE_ATTR(connectspeed_1, S_IRUGO|S_IWUSR, sysfs_connectspeed_show_1, 0);
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_connectspeed_show_2( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_connectspeed_show_2( struct device *_dev,char *buf)
++ #endif
++ {
++ return connectspeed_show_2(buf);
++ }
++ DEVICE_ATTR(connectspeed_2, S_IRUGO|S_IWUSR, sysfs_connectspeed_show_2, 0);
++ #else
++ static ssize_t connectspeed_show(char *buf)
++ {
++ hprt0_data_t val;
++ val.d32 = ifxusb_rreg(ifxusb_hcd.core_if.hprt0);
++ if( val.b.prtspd ==0) return sprintf (buf, "Bus Speed = High (%d)\n", val.b.prtspd);
++ if( val.b.prtspd ==1) return sprintf (buf, "Bus Speed = Full (%d)\n", val.b.prtspd);
++ if( val.b.prtspd ==2) return sprintf (buf, "Bus Speed = Low (%d)\n", val.b.prtspd);
++ return sprintf (buf, "Bus Speed = Unknown (%d)\n", val.b.prtspd);
++ }
++
++ static ssize_t procfs_connectspeed_show(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return connectspeed_show(buf);
++ }
++
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_connectspeed_show( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_connectspeed_show( struct device *_dev, char *buf)
++ #endif
++ {
++ return connectspeed_show(buf);
++ }
++ DEVICE_ATTR(connectspeed, S_IRUGO|S_IWUSR, sysfs_connectspeed_show, 0);
++ #endif
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++#endif
++
++
++#ifdef __IS_DEVICE__
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++ static ssize_t devspeed_show(char *buf)
++ {
++ dcfg_data_t val;
++ val.d32 = ifxusb_rreg(&ifxusb_pcd.core_if.dev_global_regs->dcfg);
++ if( val.b.devspd ==0) return sprintf (buf, "Dev Speed = High (%d)\n", val.b.devspd);
++ if( val.b.devspd ==1) return sprintf (buf, "Dev Speed = Full (%d)\n", val.b.devspd);
++ if( val.b.devspd ==3) return sprintf (buf, "Dev Speed = Full (%d)\n", val.b.devspd);
++ return sprintf (buf, "Dev Speed = Unknown (%d)\n", val.b.devspd);
++ }
++
++ static ssize_t procfs_devspeed_show(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return devspeed_show(buf);
++ }
++
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_devspeed_show( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_devspeed_show( struct device *_dev, char *buf)
++ #endif
++ {
++ return devspeed_show(buf);
++ }
++ DEVICE_ATTR(devspeed, S_IRUGO|S_IWUSR, sysfs_devspeed_show, 0);
++
++ static ssize_t enumspeed_show(char *buf)
++ {
++ dsts_data_t val;
++ val.d32 = ifxusb_rreg(&ifxusb_pcd.core_if.dev_global_regs->dsts);
++ if( val.b.enumspd ==0) return sprintf (buf, "Enum Speed = High (%d)\n", val.b.enumspd);
++ if( val.b.enumspd ==1) return sprintf (buf, "Enum Speed = Full (%d)\n", val.b.enumspd);
++ if( val.b.enumspd ==2) return sprintf (buf, "Enum Speed = Low (%d)\n", val.b.enumspd);
++ return sprintf (buf, "Enum Speed = invalid(%d)\n", val.b.enumspd);
++ }
++
++ static ssize_t procfs_enumspeed_show(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ return enumspeed_show(buf);
++ }
++
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_enumspeed_show( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_enumspeed_show( struct device *_dev, char *buf)
++ #endif
++ {
++ return enumspeed_show(buf);
++ }
++ DEVICE_ATTR(enumspeed, S_IRUGO|S_IWUSR, sysfs_enumspeed_show, 0);
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++#endif
++
++
++//////////////////////////////////////////////////////////////////////////////////
++#ifdef __ENABLE_DUMP__
++
++ #ifdef __IS_DUAL__
++ static void dump_reg_1(void)
++ {
++ ifxusb_dump_registers(&ifxusb_hcd_1.core_if);
++ }
++ static void dump_reg_2(void)
++ {
++ ifxusb_dump_registers(&ifxusb_hcd_2.core_if);
++ }
++
++ static ssize_t procfs_dump_reg_show_1(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ dump_reg_1();
++ return 0;
++ }
++ static ssize_t procfs_dump_reg_show_2(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ dump_reg_2();
++ return 0;
++ }
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_dump_reg_show_1( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_dump_reg_show_1( struct device *_dev,char *buf)
++ #endif
++ {
++ dump_reg_1();
++ return 0;
++ }
++ DEVICE_ATTR(dump_reg_1, S_IRUGO|S_IWUSR, sysfs_dump_reg_show_1, 0);
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_dump_reg_show_2( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_dump_reg_show_2( struct device *_dev,char *buf)
++ #endif
++ {
++ dump_reg_2();
++ return 0;
++ }
++ DEVICE_ATTR(dump_reg_2, S_IRUGO|S_IWUSR, sysfs_dump_reg_show_2, 0);
++ #else
++ static void dump_reg(void)
++ {
++ #ifdef __IS_HOST__
++ ifxusb_dump_registers(&ifxusb_hcd.core_if);
++ #endif
++ #ifdef __IS_DEVICE__
++ ifxusb_dump_registers(&ifxusb_pcd.core_if);
++ #endif
++ }
++ static ssize_t procfs_dump_reg_show(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ dump_reg();
++ return 0;
++ }
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_dump_reg_show( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_dump_reg_show( struct device *_dev,char *buf)
++ #endif
++ {
++ dump_reg();
++ return 0;
++ }
++ DEVICE_ATTR(dump_reg, S_IRUGO|S_IWUSR, sysfs_dump_reg_show, 0);
++ #endif
++
++
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++
++ #ifdef __IS_DUAL__
++ static void dump_spram_1(void)
++ {
++ ifxusb_dump_spram(&ifxusb_hcd_1.core_if);
++ }
++ static void dump_spram_2(void)
++ {
++ ifxusb_dump_spram(&ifxusb_hcd_2.core_if);
++ }
++
++ static ssize_t procfs_dump_spram_show_1(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ dump_spram_1();
++ return 0;
++ }
++ static ssize_t procfs_dump_spram_show_2(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ dump_spram_2();
++ return 0;
++ }
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_dump_spram_show_1( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_dump_spram_show_1( struct device *_dev,char *buf)
++ #endif
++ {
++ dump_spram_1();
++ return 0;
++ }
++ DEVICE_ATTR(dump_spram_1, S_IRUGO|S_IWUSR, sysfs_dump_spram_show_1, 0);
++
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_dump_spram_show_2( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_dump_spram_show_2( struct device *_dev,char *buf)
++ #endif
++ {
++ dump_spram_2();
++ return 0;
++ }
++ DEVICE_ATTR(dump_spram_2, S_IRUGO|S_IWUSR, sysfs_dump_spram_show_2, 0);
++ #else
++ static void dump_spram(void)
++ {
++ #ifdef __IS_HOST__
++ ifxusb_dump_spram(&ifxusb_hcd.core_if);
++ #endif
++ #ifdef __IS_DEVICE__
++ ifxusb_dump_spram(&ifxusb_pcd.core_if);
++ #endif
++ }
++ static ssize_t procfs_dump_spram_show(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ dump_spram();
++ return 0;
++ }
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_dump_spram_show( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_dump_spram_show( struct device *_dev,char *buf)
++ #endif
++ {
++ dump_spram();
++ return 0;
++ }
++ DEVICE_ATTR(dump_spram, S_IRUGO|S_IWUSR, sysfs_dump_spram_show, 0);
++ #endif
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++
++ #ifdef __IS_HOST__
++ #ifdef __IS_DUAL__
++ static ssize_t procfs_dump_host_state_show_1(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ ifxhcd_dump_state(&ifxusb_hcd_1);
++ return 0;
++ }
++ static ssize_t procfs_dump_host_state_show_2(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ ifxhcd_dump_state(&ifxusb_hcd_2);
++ return 0;
++ }
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_dump_host_state_show_1( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_dump_host_state_show_1( struct device *_dev,char *buf)
++ #endif
++ {
++ ifxhcd_dump_state(&ifxusb_hcd_1);
++ return 0;
++ }
++ DEVICE_ATTR(dump_host_state_1, S_IRUGO|S_IWUSR, sysfs_dump_host_state_show_1, 0);
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_dump_host_state_show_2( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_dump_host_state_show_2( struct device *_dev,char *buf)
++ #endif
++ {
++ ifxhcd_dump_state(&ifxusb_hcd_2);
++ return 0;
++ }
++ DEVICE_ATTR(dump_host_state_2, S_IRUGO|S_IWUSR, sysfs_dump_host_state_show_2, 0);
++ #else
++ static ssize_t procfs_dump_host_state_show(char *buf, char **start, off_t offset, int count, int *eof, void *data)
++ {
++ ifxhcd_dump_state(&ifxusb_hcd);
++ return 0;
++ }
++ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ static ssize_t sysfs_dump_host_state_show( struct device *_dev, struct device_attribute *attr,char *buf)
++ #else
++ static ssize_t sysfs_dump_host_state_show( struct device *_dev,char *buf)
++ #endif
++ {
++ ifxhcd_dump_state(&ifxusb_hcd);
++ return 0;
++ }
++ DEVICE_ATTR(dump_host_state, S_IRUGO|S_IWUSR, sysfs_dump_host_state_show, 0);
++ #endif
++
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++/////////////////////////////////////////////////////////////////////////////////////////////////////
++
++ #endif //IS_HOST_
++
++#endif //__ENABLE_DUMP__
++
++//////////////////////////////////////////////////////////////////////////////////
++
++static int ifx_proc_addproc(char *funcname, read_proc_t *hookfuncr, write_proc_t *hookfuncw);
++static void ifx_proc_delproc(char *funcname);
++
++//////////////////////////////////////////////////////////////////////////////////
++
++/*!
++ \brief This function create the sysfs and procfs entries
++ \param[in] _dev Pointer of device structure, if applied
++ */
++void ifxusb_attr_create (void *_dev)
++{
++ int error;
++
++ struct device *dev = (struct device *) _dev;
++
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ error = ifx_proc_addproc("dbglevel", procfs_dbglevel_show, procfs_dbglevel_store);
++ error = device_create_file(dev, &dev_attr_dbglevel);
++
++ #ifdef __IS_DUAL__
++ error = ifx_proc_addproc("dump_params_1", procfs_dump_params_show_1, NULL);
++ error = ifx_proc_addproc("dump_params_2", procfs_dump_params_show_2, NULL);
++ error = device_create_file(dev, &dev_attr_dump_params_1);
++ error = device_create_file(dev, &dev_attr_dump_params_2);
++ #else
++ error = ifx_proc_addproc("dump_params", procfs_dump_params_show, NULL);
++ error = device_create_file(dev, &dev_attr_dump_params);
++ #endif
++
++ #ifdef __IS_DUAL__
++ error = ifx_proc_addproc("mode_1", procfs_mode_show_1, NULL);
++ error = ifx_proc_addproc("mode_2", procfs_mode_show_2, NULL);
++ error = device_create_file(dev, &dev_attr_mode_1);
++ error = device_create_file(dev, &dev_attr_mode_2);
++ #else
++ error = ifx_proc_addproc("mode", procfs_mode_show, NULL);
++ error = device_create_file(dev, &dev_attr_mode);
++ #endif
++
++ #ifdef __IS_HOST__
++ #ifdef __IS_DUAL__
++ error = ifx_proc_addproc("buspower_1", procfs_buspower_show_1, procfs_buspower_store_1);
++ error = ifx_proc_addproc("buspower_2", procfs_buspower_show_2, procfs_buspower_store_2);
++ error = device_create_file(dev, &dev_attr_buspower_1);
++ error = device_create_file(dev, &dev_attr_buspower_2);
++ #else
++ error = ifx_proc_addproc("buspower", procfs_buspower_show, procfs_buspower_store);
++ error = device_create_file(dev, &dev_attr_buspower);
++ #endif
++
++ #ifdef __IS_DUAL__
++ error = ifx_proc_addproc("bussuspend_1", procfs_bussuspend_show_1, NULL);
++ error = ifx_proc_addproc("bussuspend_2", procfs_bussuspend_show_2, NULL);
++ error = device_create_file(dev, &dev_attr_bussuspend_1);
++ error = device_create_file(dev, &dev_attr_bussuspend_2);
++ #else
++ error = ifx_proc_addproc("bussuspend", procfs_bussuspend_show, NULL);
++ error = device_create_file(dev, &dev_attr_bussuspend);
++ #endif
++
++ #ifdef __IS_DUAL__
++ error = ifx_proc_addproc("busconnected_1", procfs_busconnected_show_1, NULL);
++ error = ifx_proc_addproc("busconnected_2", procfs_busconnected_show_2, NULL);
++ error = device_create_file(dev, &dev_attr_busconnected_1);
++ error = device_create_file(dev, &dev_attr_busconnected_2);
++ #else
++ error = ifx_proc_addproc("busconnected", procfs_busconnected_show, NULL);
++ error = device_create_file(dev, &dev_attr_busconnected);
++ #endif
++
++ #ifdef __IS_DUAL__
++ error = ifx_proc_addproc("connectspeed_1", procfs_connectspeed_show_1, NULL);
++ error = ifx_proc_addproc("connectspeed_2", procfs_connectspeed_show_2, NULL);
++ error = device_create_file(dev, &dev_attr_connectspeed_1);
++ error = device_create_file(dev, &dev_attr_connectspeed_2);
++ #else
++ error = ifx_proc_addproc("connectspeed", procfs_connectspeed_show, NULL);
++ error = device_create_file(dev, &dev_attr_connectspeed);
++ #endif
++ #endif
++
++ #ifdef __IS_DEVICE__
++ error = ifx_proc_addproc("devspeed", procfs_devspeed_show, NULL);
++ error = device_create_file(dev, &dev_attr_devspeed);
++ error = ifx_proc_addproc("enumspeed", procfs_enumspeed_show, NULL);
++ error = device_create_file(dev, &dev_attr_enumspeed);
++ #endif
++
++ //////////////////////////////////////////////////////
++ #ifdef __ENABLE_DUMP__
++ #ifdef __IS_DUAL__
++ error = ifx_proc_addproc("dump_reg_1", procfs_dump_reg_show_1, NULL);
++ error = ifx_proc_addproc("dump_reg_2", procfs_dump_reg_show_2, NULL);
++ error = device_create_file(dev, &dev_attr_dump_reg_1);
++ error = device_create_file(dev, &dev_attr_dump_reg_2);
++ #else
++ error = ifx_proc_addproc("dump_reg", procfs_dump_reg_show, NULL);
++ error = device_create_file(dev, &dev_attr_dump_reg);
++ #endif
++
++ #ifdef __IS_DUAL__
++ error = ifx_proc_addproc("dump_spram_1", procfs_dump_spram_show_1, NULL);
++ error = ifx_proc_addproc("dump_spram_2", procfs_dump_spram_show_2, NULL);
++ error = device_create_file(dev, &dev_attr_dump_spram_1);
++ error = device_create_file(dev, &dev_attr_dump_spram_2);
++ #else
++ error = ifx_proc_addproc("dump_spram", procfs_dump_spram_show, NULL);
++ error = device_create_file(dev, &dev_attr_dump_spram);
++ #endif
++
++ #ifdef __IS_HOST__
++ #ifdef __IS_DUAL__
++ error = ifx_proc_addproc("dump_host_state_1", procfs_dump_host_state_show_1, NULL);
++ error = ifx_proc_addproc("dump_host_state_2", procfs_dump_host_state_show_2, NULL);
++ error = device_create_file(dev, &dev_attr_dump_host_state_1);
++ error = device_create_file(dev, &dev_attr_dump_host_state_2);
++ #else
++ error = ifx_proc_addproc("dump_host_state", procfs_dump_host_state_show, NULL);
++ error = device_create_file(dev, &dev_attr_dump_host_state);
++ #endif
++ #endif
++ #endif //__ENABLE_DUMP__
++ //////////////////////////////////////////////////////
++}
++
++
++/*!
++ \brief This function remove the sysfs and procfs entries
++ \param[in] _dev Pointer of device structure, if applied
++ */
++void ifxusb_attr_remove (void *_dev)
++{
++ struct device *dev = (struct device *) _dev;
++
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ ifx_proc_delproc("dbglevel");
++ device_remove_file(dev, &dev_attr_dbglevel);
++
++ #ifdef __IS_DUAL__
++ ifx_proc_delproc("dump_params_1");
++ ifx_proc_delproc("dump_params_2");
++ device_remove_file(dev, &dev_attr_dump_params_1);
++ device_remove_file(dev, &dev_attr_dump_params_2);
++ #else
++ ifx_proc_delproc("dump_params");
++ device_remove_file(dev, &dev_attr_dump_params);
++ #endif
++
++ #ifdef __IS_DUAL__
++ ifx_proc_delproc("mode_1");
++ ifx_proc_delproc("mode_2");
++ device_remove_file(dev, &dev_attr_mode_1);
++ device_remove_file(dev, &dev_attr_mode_2);
++ #else
++ ifx_proc_delproc("mode");
++ device_remove_file(dev, &dev_attr_mode);
++ #endif
++
++ #ifdef __IS_HOST__
++ #ifdef __IS_DUAL__
++ ifx_proc_delproc("buspower_1");
++ ifx_proc_delproc("buspower_2");
++ device_remove_file(dev, &dev_attr_buspower_1);
++ device_remove_file(dev, &dev_attr_buspower_2);
++ #else
++ ifx_proc_delproc("buspower");
++ device_remove_file(dev, &dev_attr_buspower);
++ #endif
++
++ #ifdef __IS_DUAL__
++ ifx_proc_delproc("bussuspend_1");
++ ifx_proc_delproc("bussuspend_2");
++ device_remove_file(dev, &dev_attr_bussuspend_1);
++ device_remove_file(dev, &dev_attr_bussuspend_2);
++ #else
++ ifx_proc_delproc("bussuspend");
++ device_remove_file(dev, &dev_attr_bussuspend);
++ #endif
++
++ #ifdef __IS_DUAL__
++ ifx_proc_delproc("busconnected_1");
++ ifx_proc_delproc("busconnected_2");
++ device_remove_file(dev, &dev_attr_busconnected_1);
++ device_remove_file(dev, &dev_attr_busconnected_2);
++ #else
++ ifx_proc_delproc("busconnected");
++ device_remove_file(dev, &dev_attr_busconnected);
++ #endif
++
++ #ifdef __IS_DUAL__
++ ifx_proc_delproc("connectspeed_1");
++ ifx_proc_delproc("connectspeed_2");
++ device_remove_file(dev, &dev_attr_connectspeed_1);
++ device_remove_file(dev, &dev_attr_connectspeed_2);
++ #else
++ ifx_proc_delproc("connectspeed");
++ device_remove_file(dev, &dev_attr_connectspeed);
++ #endif
++ #endif
++
++ #ifdef __IS_DEVICE__
++ ifx_proc_delproc("devspeed");
++ device_remove_file(dev, &dev_attr_devspeed);
++ ifx_proc_delproc("enumspeed");
++ device_remove_file(dev, &dev_attr_enumspeed);
++ #endif
++
++ #ifdef __ENABLE_DUMP__
++ #ifdef __IS_DUAL__
++ ifx_proc_delproc("dump_reg_1");
++ ifx_proc_delproc("dump_reg_2");
++ device_remove_file(dev, &dev_attr_dump_reg_1);
++ device_remove_file(dev, &dev_attr_dump_reg_2);
++ #else
++ ifx_proc_delproc("dump_reg");
++ device_remove_file(dev, &dev_attr_dump_reg);
++ #endif
++
++ #ifdef __IS_DUAL__
++ ifx_proc_delproc("dump_spram_1");
++ ifx_proc_delproc("dump_spram_2");
++ device_remove_file(dev, &dev_attr_dump_spram_1);
++ device_remove_file(dev, &dev_attr_dump_spram_2);
++ #else
++ ifx_proc_delproc("dump_spram");
++ device_remove_file(dev, &dev_attr_dump_spram);
++ #endif
++
++ #ifdef __IS_HOST__
++ #ifdef __IS_DUAL__
++ ifx_proc_delproc("dump_host_state_1");
++ ifx_proc_delproc("dump_host_state_2");
++ device_remove_file(dev, &dev_attr_dump_host_state_1);
++ device_remove_file(dev, &dev_attr_dump_host_state_2);
++ #else
++ ifx_proc_delproc("dump_host_state");
++ device_remove_file(dev, &dev_attr_dump_host_state);
++ #endif
++ #endif
++ #endif //__ENABLE_DUMP__
++ /* AVM/WK fix: del IFXUSB root dir*/
++ ifx_proc_delproc(NULL);
++}
++
++static struct proc_dir_entry * proc_ifx_root = NULL;
++
++/* initialize the proc file system and make a dir named /proc/[name] */
++static void ifx_proc_init(void)
++{
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ proc_ifx_root = proc_mkdir(ifxusb_driver_name, (void *)0);
++ if (!proc_ifx_root){
++ IFX_PRINT("%s proc initialization failed! \n", ifxusb_driver_name);
++ return;
++ }
++}
++
++/* proc file system add function for debugging. */
++static int ifx_proc_addproc(char *funcname, read_proc_t *hookfuncr, write_proc_t *hookfuncw)
++{
++ struct proc_dir_entry *pe;
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ if (!proc_ifx_root)
++ ifx_proc_init();
++
++ if (hookfuncw == NULL)
++ {
++ pe = create_proc_read_entry(funcname, S_IRUGO, proc_ifx_root, hookfuncr, NULL);
++ if (!pe)
++ {
++ IFX_PRINT("ERROR in creating read proc entry (%s)! \n", funcname);
++ return -1;
++ }
++ }
++ else
++ {
++ pe = create_proc_entry(funcname, S_IRUGO | S_IWUGO, proc_ifx_root);
++ if (pe)
++ {
++ pe->read_proc = hookfuncr;
++ pe->write_proc = hookfuncw;
++ }
++ else
++ {
++ IFX_PRINT("ERROR in creating proc entry (%s)! \n", funcname);
++ return -1;
++ }
++ }
++ return 0;
++}
++
++
++/* proc file system del function for removing module. */
++static void ifx_proc_delproc(char *funcname)
++{
++/* AVM/WK Fix*/
++ if (funcname != NULL) {
++ remove_proc_entry(funcname, proc_ifx_root);
++ } else {
++ remove_proc_entry(ifxusb_driver_name, NULL);
++ proc_ifx_root = NULL;
++ }
++}
++
++static void ifxusb_dump_params(ifxusb_core_if_t *_core_if)
++{
++ ifxusb_params_t *params=&_core_if->params;
++
++ #ifdef __IS_HOST__
++ IFX_PRINT("IFXUSB Dump Parameters ( Host Mode) \n");
++ #endif //__IS_HOST__
++ #ifdef __IS_DEVICE__
++ IFX_PRINT("IFXUSB Dump Parameters ( Device Mode) \n");
++ #endif //__IS_DEVICE__
++
++ #ifdef __DESC_DMA__
++ IFX_PRINT("DMA: Hermes DMA\n");
++ #else
++ IFX_PRINT("DMA: Non-Desc DMA\n");
++ #endif
++ IFX_PRINT(" Burst size: %d\n",params->dma_burst_size);
++
++ if (params->speed==1)
++ IFX_PRINT("Full Speed only\n");
++ else if(params->speed==0)
++ IFX_PRINT("Full/Hign Speed\n");
++ else
++ IFX_PRINT("Unkonwn setting (%d) for Speed\n",params->speed);
++
++ IFX_PRINT("Total Data FIFO size: %d(0x%06X) DWord, %d(0x%06X) Bytes\n",
++ params->data_fifo_size,params->data_fifo_size,
++ params->data_fifo_size*4, params->data_fifo_size*4
++ );
++
++ #ifdef __IS_DEVICE__
++ IFX_PRINT("Rx FIFO size: %d(0x%06X) DWord, %d(0x%06X) Bytes\n",
++ params->rx_fifo_size,params->rx_fifo_size,
++ params->rx_fifo_size*4, params->rx_fifo_size*4
++ );
++ {
++ int i;
++ for(i=0;i<MAX_EPS_CHANNELS;i++)
++ {
++ IFX_PRINT("Tx FIFO #%d size: %d(0x%06X) DWord, %d(0x%06X) Bytes\n",i,
++ params->tx_fifo_size[i],params->tx_fifo_size[i],
++ params->tx_fifo_size[i]*4, params->tx_fifo_size[i]*4
++ );
++ }
++ }
++ #ifdef __DED_FIFO__
++ IFX_PRINT("Treshold : %s Rx:%d Tx:%d \n",
++ (params->thr_ctl)?"On":"Off",params->tx_thr_length,params->rx_thr_length);
++ #endif
++ #else //__IS_HOST__
++ IFX_PRINT("Host Channels: %d\n",params->host_channels);
++
++ IFX_PRINT("Rx FIFO size: %d(0x%06X) DWord, %d(0x%06X) Bytes\n",
++ params->data_fifo_size,params->data_fifo_size,
++ params->data_fifo_size*4, params->data_fifo_size*4
++ );
++
++ IFX_PRINT("NP Tx FIFO size: %d(0x%06X) DWord, %d(0x%06X) Bytes\n",
++ params->nperio_tx_fifo_size,params->nperio_tx_fifo_size,
++ params->nperio_tx_fifo_size*4, params->nperio_tx_fifo_size*4
++ );
++
++ IFX_PRINT(" P Tx FIFO size: %d(0x%06X) DWord, %d(0x%06X) Bytes\n",
++ params->perio_tx_fifo_size,params->perio_tx_fifo_size,
++ params->perio_tx_fifo_size*4, params->perio_tx_fifo_size*4
++ );
++ #endif //__IS_HOST__
++
++ IFX_PRINT("Max Transfer size: %d(0x%06X) Bytes\n",
++ params->max_transfer_size,params->max_transfer_size
++ );
++ IFX_PRINT("Max Packet Count: %d(0x%06X)\n",
++ params->max_packet_count,params->max_packet_count
++ );
++
++ IFX_PRINT("PHY UTMI Width: %d\n",params->phy_utmi_width);
++
++ IFX_PRINT("Turn Around Time: HS:%d FS:%d\n",params->turn_around_time_hs,params->turn_around_time_fs);
++ IFX_PRINT("Timeout Calibration: HS:%d FS:%d\n",params->timeout_cal_hs,params->timeout_cal_fs);
++
++
++ IFX_PRINT("==================================================\n");
++ IFX_PRINT("End of Parameters Dump\n");
++ IFX_PRINT("==================================================\n");
++}
++
++
+diff --git a/drivers/usb/ifxhcd/ifxusb_driver.c b/drivers/usb/ifxhcd/ifxusb_driver.c
+new file mode 100644
+index 0000000..2334905
+--- /dev/null
++++ b/drivers/usb/ifxhcd/ifxusb_driver.c
+@@ -0,0 +1,970 @@
++/*****************************************************************************
++ ** FILE NAME : ifxusb_driver.c
++ ** PROJECT : IFX USB sub-system V3
++ ** MODULES : IFX USB sub-system Host and Device driver
++ ** SRC VERSION : 1.0
++ ** DATE : 1/Jan/2009
++ ** AUTHOR : Chen, Howard
++ ** DESCRIPTION : The provides the initialization and cleanup entry
++ ** points for the IFX USB driver. This module can be
++ ** dynamically loaded with insmod command or built-in
++ ** with kernel. When loaded or executed the ifxusb_driver_init
++ ** function is called. When the module is removed (using rmmod),
++ ** the ifxusb_driver_cleanup function is called.
++ *****************************************************************************/
++
++/*!
++ \file ifxusb_driver.c
++ \brief This file contains the loading/unloading interface to the Linux driver.
++*/
++
++#include <linux/version.h>
++#include "ifxusb_version.h"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++
++#include <linux/device.h>
++#include <linux/platform_device.h>
++
++#include <linux/errno.h>
++#include <linux/types.h>
++#include <linux/stat.h> /* permission constants */
++#include <linux/gpio.h>
++#include <lantiq_soc.h>
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
++ #include <linux/irq.h>
++#endif
++
++#include <asm/io.h>
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
++ #include <asm/irq.h>
++#endif
++
++#include "ifxusb_plat.h"
++
++#include "ifxusb_cif.h"
++
++#ifdef __IS_HOST__
++ #include "ifxhcd.h"
++
++ #define USB_DRIVER_DESC "IFX USB HCD driver"
++ const char ifxusb_driver_name[] = "ifxusb_hcd";
++
++ #ifdef __IS_DUAL__
++ ifxhcd_hcd_t ifxusb_hcd_1;
++ ifxhcd_hcd_t ifxusb_hcd_2;
++ const char ifxusb_hcd_name_1[] = "ifxusb_hcd_1";
++ const char ifxusb_hcd_name_2[] = "ifxusb_hcd_2";
++ #else
++ ifxhcd_hcd_t ifxusb_hcd;
++ const char ifxusb_hcd_name[] = "ifxusb_hcd";
++ #endif
++
++ #if defined(__DO_OC_INT__)
++ static unsigned int oc_int_installed=0;
++ static ifxhcd_hcd_t *oc_int_id=NULL;
++ #endif
++#endif
++
++#ifdef __IS_DEVICE__
++ #include "ifxpcd.h"
++
++ #define USB_DRIVER_DESC "IFX USB PCD driver"
++ const char ifxusb_driver_name[] = "ifxusb_pcd";
++
++ ifxpcd_pcd_t ifxusb_pcd;
++ const char ifxusb_pcd_name[] = "ifxusb_pcd";
++#endif
++
++/* Global Debug Level Mask. */
++#ifdef __IS_HOST__
++ uint32_t h_dbg_lvl = 0x00;
++#endif
++
++#ifdef __IS_DEVICE__
++ uint32_t d_dbg_lvl = 0x00;
++#endif
++
++ifxusb_params_t ifxusb_module_params;
++
++static void parse_parms(void);
++
++
++#include <lantiq_irq.h>
++#define IFX_USB0_IR (INT_NUM_IM1_IRL0 + 22)
++#define IFX_USB1_IR (INT_NUM_IM2_IRL0 + 19)
++
++/*!
++ \brief This function is called when a driver is unregistered. This happens when
++ the rmmod command is executed. The device may or may not be electrically
++ present. If it is present, the driver stops device processing. Any resources
++ used on behalf of this device are freed.
++*/
++static int ifxusb_driver_remove(struct platform_device *_dev)
++{
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ #ifdef __IS_HOST__
++ #if defined(__DO_OC_INT__)
++ #if defined(__DO_OC_INT_ENABLE__)
++ ifxusb_oc_int_off();
++ #endif
++
++ if(oc_int_installed && oc_int_id)
++ free_irq((unsigned int)IFXUSB_OC_IRQ, oc_int_id );
++ oc_int_installed=0;
++ oc_int_id=NULL;
++ #endif
++
++ #if defined(__IS_DUAL__)
++ ifxhcd_remove(&ifxusb_hcd_1);
++ ifxusb_core_if_remove(&ifxusb_hcd_1.core_if );
++ ifxhcd_remove(&ifxusb_hcd_2);
++ ifxusb_core_if_remove(&ifxusb_hcd_2.core_if );
++ #else
++ ifxhcd_remove(&ifxusb_hcd);
++ ifxusb_core_if_remove(&ifxusb_hcd.core_if );
++ #endif
++ #endif
++
++ #ifdef __IS_DEVICE__
++ ifxpcd_remove();
++ ifxusb_core_if_remove(&ifxusb_pcd.core_if );
++ #endif
++
++ /* Remove the device attributes */
++
++ ifxusb_attr_remove(&_dev->dev);
++
++ return 0;
++}
++
++
++/* Function to setup the structures to control one usb core running as host*/
++#ifdef __IS_HOST__
++/*!
++ \brief inlined by ifxusb_driver_probe(), handling host mode probing. Run at each host core.
++*/
++ static inline int ifxusb_driver_probe_h(ifxhcd_hcd_t *_hcd,
++ int _irq,
++ uint32_t _iobase,
++ uint32_t _fifomem,
++ uint32_t _fifodbg
++ )
++ {
++ int retval = 0;
++
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++
++#ifdef __DEV_NEW__
++ ifxusb_power_off (&_hcd->core_if);
++ ifxusb_phy_power_off (&_hcd->core_if); // Test
++ mdelay(500);
++#endif //__DEV_NEW__
++ ifxusb_power_on (&_hcd->core_if);
++ mdelay(50);
++ ifxusb_phy_power_on (&_hcd->core_if); // Test
++ mdelay(50);
++ ifxusb_hard_reset(&_hcd->core_if);
++ retval =ifxusb_core_if_init(&_hcd->core_if,
++ _irq,
++ _iobase,
++ _fifomem,
++ _fifodbg);
++ if(retval)
++ return retval;
++
++ ifxusb_host_core_init(&_hcd->core_if,&ifxusb_module_params);
++
++ ifxusb_disable_global_interrupts( &_hcd->core_if);
++
++ /* The driver is now initialized and need to be registered into Linux USB sub-system */
++
++ retval = ifxhcd_init(_hcd); // hook the hcd into usb ss
++
++ if (retval != 0)
++ {
++ IFX_ERROR("_hcd_init failed\n");
++ return retval;
++ }
++
++ //ifxusb_enable_global_interrupts( _hcd->core_if ); // this should be done at hcd_start , including hcd_interrupt
++ return 0;
++ }
++#endif //__IS_HOST__
++
++#ifdef __IS_DEVICE__
++/*!
++ \brief inlined by ifxusb_driver_probe(), handling device mode probing.
++*/
++ static inline int ifxusb_driver_probe_d(ifxpcd_pcd_t *_pcd,
++ int _irq,
++ uint32_t _iobase,
++ uint32_t _fifomem,
++ uint32_t _fifodbg
++ )
++ {
++ int retval = 0;
++
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++#ifdef __DEV_NEW__
++ ifxusb_power_off (&_pcd->core_if);
++ ifxusb_phy_power_off (&_pcd->core_if); // Test
++ mdelay(500);
++#endif // __DEV_NEW__
++ ifxusb_power_on (&_pcd->core_if);
++ mdelay(50);
++ ifxusb_phy_power_on (&_pcd->core_if); // Test
++ mdelay(50);
++ ifxusb_hard_reset(&_pcd->core_if);
++ retval =ifxusb_core_if_init(&_pcd->core_if,
++ _irq,
++ _iobase,
++ _fifomem,
++ _fifodbg);
++ if(retval)
++ return retval;
++
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ ifxusb_dev_core_init(&_pcd->core_if,&ifxusb_module_params);
++
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ ifxusb_disable_global_interrupts( &_pcd->core_if);
++
++ /* The driver is now initialized and need to be registered into
++ Linux USB Gadget sub-system
++ */
++ retval = ifxpcd_init();
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++
++ if (retval != 0)
++ {
++ IFX_ERROR("_pcd_init failed\n");
++ return retval;
++ }
++ //ifxusb_enable_global_interrupts( _pcd->core_if ); // this should be done at gadget bind or start
++ return 0;
++ }
++#endif //__IS_DEVICE__
++
++
++
++/*!
++ \brief This function is called by module management in 2.6 kernel or by ifxusb_driver_init with 2.4 kernel
++ It is to probe and setup IFXUSB core(s).
++*/
++static int ifxusb_driver_probe(struct platform_device *_dev)
++{
++ int retval = 0;
++ int *pins = _dev->dev.platform_data;
++ if (ltq_is_vr9()) {
++ gpio_request(6, "id1");
++ gpio_request(9, "id2");
++ gpio_direction_input(6);
++ gpio_direction_input(9);
++ }
++ if (pins) {
++ if (pins[0]) {
++ gpio_request(pins[0], "vbus1");
++ gpio_direction_output(pins[0], 1);
++ }
++ if (pins[1] && ltq_is_vr9()) {
++ gpio_request(pins[1], "vbus2");
++ gpio_direction_output(pins[1], 1);
++ }
++ }
++ // Parsing and store the parameters
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ parse_parms();
++
++ #ifdef __IS_HOST__
++ #if defined(__IS_DUAL__)
++ memset(&ifxusb_hcd_1, 0, sizeof(ifxhcd_hcd_t));
++ memset(&ifxusb_hcd_2, 0, sizeof(ifxhcd_hcd_t));
++
++ ifxusb_hcd_1.core_if.core_no=0;
++ ifxusb_hcd_2.core_if.core_no=1;
++ ifxusb_hcd_1.core_if.core_name=(char *)ifxusb_hcd_name_1;
++ ifxusb_hcd_2.core_if.core_name=(char *)ifxusb_hcd_name_2;
++
++ ifxusb_hcd_1.dev=&_dev->dev;
++ ifxusb_hcd_2.dev=&_dev->dev;
++
++ retval = ifxusb_driver_probe_h(&ifxusb_hcd_1,
++ IFX_USB0_IR,
++ IFXUSB1_IOMEM_BASE,
++ IFXUSB1_FIFOMEM_BASE,
++ IFXUSB1_FIFODBG_BASE
++ );
++ if(retval)
++ goto ifxusb_driver_probe_fail;
++
++ retval = ifxusb_driver_probe_h(&ifxusb_hcd_2,
++ IFX_USB1_IR,
++ IFXUSB2_IOMEM_BASE,
++ IFXUSB2_FIFOMEM_BASE,
++ IFXUSB2_FIFODBG_BASE
++ );
++ if(retval)
++ goto ifxusb_driver_probe_fail;
++
++ #elif defined(__IS_FIRST__)
++ memset(&ifxusb_hcd, 0, sizeof(ifxhcd_hcd_t));
++
++ ifxusb_hcd.core_if.core_no=0;
++ ifxusb_hcd.core_if.core_name=(char *)ifxusb_hcd_name;
++
++ ifxusb_hcd.dev=&_dev->dev;
++
++ retval = ifxusb_driver_probe_h(&ifxusb_hcd,
++ IFX_USB0_IR,
++ IFXUSB1_IOMEM_BASE,
++ IFXUSB1_FIFOMEM_BASE,
++ IFXUSB1_FIFODBG_BASE
++ );
++ if(retval)
++ goto ifxusb_driver_probe_fail;
++
++ #elif defined(__IS_SECOND__)
++ memset(&ifxusb_hcd, 0, sizeof(ifxhcd_hcd_t));
++
++ ifxusb_hcd.core_if.core_no=1;
++ ifxusb_hcd.core_if.core_name=(char *)ifxusb_hcd_name;
++
++ ifxusb_hcd.dev=&_dev->dev;
++
++ retval = ifxusb_driver_probe_h(&ifxusb_hcd,
++ IFX_USB1_IR,
++ IFXUSB2_IOMEM_BASE,
++ IFXUSB2_FIFOMEM_BASE,
++ IFXUSB2_FIFODBG_BASE
++ );
++ if(retval)
++ goto ifxusb_driver_probe_fail;
++
++ #else
++ memset(&ifxusb_hcd, 0, sizeof(ifxhcd_hcd_t));
++
++ ifxusb_hcd.core_if.core_no=0;
++ ifxusb_hcd.core_if.core_name=(char *)ifxusb_hcd_name;
++
++ ifxusb_hcd.dev=&_dev->dev;
++
++ retval = ifxusb_driver_probe_h(&ifxusb_hcd,
++ IFXUSB_IRQ,
++ IFXUSB_IOMEM_BASE,
++ IFXUSB_FIFOMEM_BASE,
++ IFXUSB_FIFODBG_BASE
++ );
++ if(retval)
++ goto ifxusb_driver_probe_fail;
++ #endif
++
++ #if defined(__DO_OC_INT__)
++ IFXUSB_DEBUGPL( DBG_CIL, "registering (overcurrent) handler for irq%d\n", IFXUSB_OC_IRQ);
++ #if defined(__IS_DUAL__)
++ request_irq((unsigned int)IFXUSB_OC_IRQ, &ifx_hcd_oc_irq,
++// SA_INTERRUPT|SA_SHIRQ, "ifxusb_oc", (void *)&ifxusb_hcd_1);
++ IRQF_DISABLED | IRQF_SHARED, "ifxusb_oc", (void *)&ifxusb_hcd_1);
++ oc_int_id=&ifxusb_hcd_1;
++ #else
++ request_irq((unsigned int)IFXUSB_OC_IRQ, &ifx_hcd_oc_irq,
++// SA_INTERRUPT|SA_SHIRQ, "ifxusb_oc", (void *)&ifxusb_hcd);
++ IRQF_DISABLED | IRQF_SHARED, "ifxusb_oc", (void *)&ifxusb_hcd);
++ oc_int_id=&ifxusb_hcd;
++ #endif
++ oc_int_installed=1;
++
++ #if defined(__DO_OC_INT_ENABLE__)
++ ifxusb_oc_int_on();
++ #endif
++ #endif
++
++ #endif
++
++ #ifdef __IS_DEVICE__
++ memset(&ifxusb_pcd, 0, sizeof(ifxpcd_pcd_t));
++ ifxusb_pcd.core_if.core_name=(char *)&ifxusb_pcd_name[0];
++
++ ifxusb_pcd.dev=&_dev->dev;
++
++ #if defined(__IS_FIRST__)
++ ifxusb_pcd.core_if.core_no=0;
++ retval = ifxusb_driver_probe_d(&ifxusb_pcd,
++ IFXUSB1_IRQ,
++ IFXUSB1_IOMEM_BASE,
++ IFXUSB1_FIFOMEM_BASE,
++ IFXUSB1_FIFODBG_BASE
++ );
++ #elif defined(__IS_SECOND__)
++ ifxusb_pcd.core_if.core_no=1;
++ retval = ifxusb_driver_probe_d(&ifxusb_pcd,
++ IFXUSB2_IRQ,
++ IFXUSB2_IOMEM_BASE,
++ IFXUSB2_FIFOMEM_BASE,
++ IFXUSB2_FIFODBG_BASE
++ );
++ #else
++ ifxusb_pcd.core_if.core_no=0;
++ retval = ifxusb_driver_probe_d(&ifxusb_pcd,
++ IFXUSB_IRQ,
++ IFXUSB_IOMEM_BASE,
++ IFXUSB_FIFOMEM_BASE,
++ IFXUSB_FIFODBG_BASE
++ );
++ #endif
++ if(retval)
++ goto ifxusb_driver_probe_fail;
++ #endif
++
++ ifxusb_attr_create(&_dev->dev);
++
++ return 0;
++
++ifxusb_driver_probe_fail:
++ ifxusb_driver_remove(_dev);
++ return retval;
++}
++
++
++
++/*!
++ \brief This function is called when the ifxusb_driver is installed with the insmod command.
++*/
++
++
++static struct platform_driver ifxusb_driver = {
++ .driver = {
++ .name = ifxusb_driver_name,
++ .owner = THIS_MODULE,
++ },
++ .probe = ifxusb_driver_probe,
++ .remove = ifxusb_driver_remove,
++};
++
++int __init ifxusb_driver_init(void)
++{
++ int retval = 0;
++
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ IFX_PRINT("%s: version %s\n", ifxusb_driver_name, IFXUSB_VERSION);
++
++ retval = platform_driver_register(&ifxusb_driver);
++
++ if (retval < 0) {
++ IFX_ERROR("%s retval=%d\n", __func__, retval);
++ return retval;
++ }
++ return retval;
++}
++
++#if 0 // 2.4
++ int __init ifxusb_driver_init(void)
++ {
++ int retval = 0;
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ IFX_PRINT("%s: version %s\n", ifxusb_driver_name, IFXUSB_VERSION);
++ retval = ifxusb_driver_probe();
++
++ if (retval < 0) {
++ IFX_ERROR("%s retval=%d\n", __func__, retval);
++ return retval;
++ }
++
++ return retval;
++ }
++#endif
++
++module_init(ifxusb_driver_init);
++
++
++/*!
++ \brief This function is called when the driver is removed from the kernel
++ with the rmmod command. The driver unregisters itself with its bus
++ driver.
++*/
++
++void __exit ifxusb_driver_cleanup(void)
++{
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++
++ platform_driver_unregister(&ifxusb_driver);
++
++ IFX_PRINT("%s module removed\n", ifxusb_driver_name);
++}
++#if 0
++ void __exit ifxusb_driver_cleanup(void)
++ {
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ ifxusb_driver_remove();
++ IFX_PRINT("%s module removed\n", ifxusb_driver_name);
++ }
++#endif
++module_exit(ifxusb_driver_cleanup);
++
++
++
++MODULE_DESCRIPTION(USB_DRIVER_DESC);
++MODULE_AUTHOR("Infineon");
++MODULE_LICENSE("GPL");
++
++
++
++// Parameters set when loaded
++//static long dbg_lvl =0xFFFFFFFF;
++static long dbg_lvl =0;
++static short dma_burst_size =-1;
++static short speed =-1;
++static long data_fifo_size =-1;
++#ifdef __IS_DEVICE__
++ static long rx_fifo_size =-1;
++ #ifdef __DED_FIFO__
++ static long tx_fifo_size_00 =-1;
++ static long tx_fifo_size_01 =-1;
++ static long tx_fifo_size_02 =-1;
++ static long tx_fifo_size_03 =-1;
++ static long tx_fifo_size_04 =-1;
++ static long tx_fifo_size_05 =-1;
++ static long tx_fifo_size_06 =-1;
++ static long tx_fifo_size_07 =-1;
++ static long tx_fifo_size_08 =-1;
++ static long tx_fifo_size_09 =-1;
++ static long tx_fifo_size_10 =-1;
++ static long tx_fifo_size_11 =-1;
++ static long tx_fifo_size_12 =-1;
++ static long tx_fifo_size_13 =-1;
++ static long tx_fifo_size_14 =-1;
++ static long tx_fifo_size_15 =-1;
++ static short thr_ctl=-1;
++ static long tx_thr_length =-1;
++ static long rx_thr_length =-1;
++ #else
++ static long nperio_tx_fifo_size =-1;
++ static long perio_tx_fifo_size_01 =-1;
++ static long perio_tx_fifo_size_02 =-1;
++ static long perio_tx_fifo_size_03 =-1;
++ static long perio_tx_fifo_size_04 =-1;
++ static long perio_tx_fifo_size_05 =-1;
++ static long perio_tx_fifo_size_06 =-1;
++ static long perio_tx_fifo_size_07 =-1;
++ static long perio_tx_fifo_size_08 =-1;
++ static long perio_tx_fifo_size_09 =-1;
++ static long perio_tx_fifo_size_10 =-1;
++ static long perio_tx_fifo_size_11 =-1;
++ static long perio_tx_fifo_size_12 =-1;
++ static long perio_tx_fifo_size_13 =-1;
++ static long perio_tx_fifo_size_14 =-1;
++ static long perio_tx_fifo_size_15 =-1;
++ #endif
++ static short dev_endpoints =-1;
++#endif
++
++#ifdef __IS_HOST__
++ static long rx_fifo_size =-1;
++ static long nperio_tx_fifo_size =-1;
++ static long perio_tx_fifo_size =-1;
++ static short host_channels =-1;
++#endif
++
++static long max_transfer_size =-1;
++static long max_packet_count =-1;
++static long phy_utmi_width =-1;
++static long turn_around_time_hs =-1;
++static long turn_around_time_fs =-1;
++static long timeout_cal_hs =-1;
++static long timeout_cal_fs =-1;
++
++/*!
++ \brief Parsing the parameters taken when module load
++*/
++static void parse_parms(void)
++{
++
++ IFX_DEBUGPL(DBG_ENTRY, "%s() %d\n", __func__, __LINE__ );
++ #ifdef __IS_HOST__
++ h_dbg_lvl=dbg_lvl;
++ #endif
++ #ifdef __IS_DEVICE__
++ d_dbg_lvl=dbg_lvl;
++ #endif
++
++ switch(dma_burst_size)
++ {
++ case 0:
++ case 1:
++ case 4:
++ case 8:
++ case 16:
++ ifxusb_module_params.dma_burst_size=dma_burst_size;
++ break;
++ default:
++ ifxusb_module_params.dma_burst_size=default_param_dma_burst_size;
++ }
++
++ if(speed==0 || speed==1)
++ ifxusb_module_params.speed=speed;
++ else
++ ifxusb_module_params.speed=default_param_speed;
++
++ if(max_transfer_size>=2048 && max_transfer_size<=65535)
++ ifxusb_module_params.max_transfer_size=max_transfer_size;
++ else
++ ifxusb_module_params.max_transfer_size=default_param_max_transfer_size;
++
++ if(max_packet_count>=15 && max_packet_count<=511)
++ ifxusb_module_params.max_packet_count=max_packet_count;
++ else
++ ifxusb_module_params.max_packet_count=default_param_max_packet_count;
++
++ switch(phy_utmi_width)
++ {
++ case 8:
++ case 16:
++ ifxusb_module_params.phy_utmi_width=phy_utmi_width;
++ break;
++ default:
++ ifxusb_module_params.phy_utmi_width=default_param_phy_utmi_width;
++ }
++
++ if(turn_around_time_hs>=0 && turn_around_time_hs<=7)
++ ifxusb_module_params.turn_around_time_hs=turn_around_time_hs;
++ else
++ ifxusb_module_params.turn_around_time_hs=default_param_turn_around_time_hs;
++
++ if(turn_around_time_fs>=0 && turn_around_time_fs<=7)
++ ifxusb_module_params.turn_around_time_fs=turn_around_time_fs;
++ else
++ ifxusb_module_params.turn_around_time_fs=default_param_turn_around_time_fs;
++
++ if(timeout_cal_hs>=0 && timeout_cal_hs<=7)
++ ifxusb_module_params.timeout_cal_hs=timeout_cal_hs;
++ else
++ ifxusb_module_params.timeout_cal_hs=default_param_timeout_cal_hs;
++
++ if(timeout_cal_fs>=0 && timeout_cal_fs<=7)
++ ifxusb_module_params.timeout_cal_fs=timeout_cal_fs;
++ else
++ ifxusb_module_params.timeout_cal_fs=default_param_timeout_cal_fs;
++
++ if(data_fifo_size>=32 && data_fifo_size<=32768)
++ ifxusb_module_params.data_fifo_size=data_fifo_size;
++ else
++ ifxusb_module_params.data_fifo_size=default_param_data_fifo_size;
++
++ #ifdef __IS_HOST__
++ if(host_channels>=1 && host_channels<=16)
++ ifxusb_module_params.host_channels=host_channels;
++ else
++ ifxusb_module_params.host_channels=default_param_host_channels;
++
++ if(rx_fifo_size>=16 && rx_fifo_size<=32768)
++ ifxusb_module_params.rx_fifo_size=rx_fifo_size;
++ else
++ ifxusb_module_params.rx_fifo_size=default_param_rx_fifo_size;
++
++ if(nperio_tx_fifo_size>=16 && nperio_tx_fifo_size<=32768)
++ ifxusb_module_params.nperio_tx_fifo_size=nperio_tx_fifo_size;
++ else
++ ifxusb_module_params.nperio_tx_fifo_size=default_param_nperio_tx_fifo_size;
++
++ if(perio_tx_fifo_size>=16 && perio_tx_fifo_size<=32768)
++ ifxusb_module_params.perio_tx_fifo_size=perio_tx_fifo_size;
++ else
++ ifxusb_module_params.perio_tx_fifo_size=default_param_perio_tx_fifo_size;
++ #endif //__IS_HOST__
++
++ #ifdef __IS_DEVICE__
++ if(rx_fifo_size>=16 && rx_fifo_size<=32768)
++ ifxusb_module_params.rx_fifo_size=rx_fifo_size;
++ else
++ ifxusb_module_params.rx_fifo_size=default_param_rx_fifo_size;
++ #ifdef __DED_FIFO__
++ if(tx_fifo_size_00>=16 && tx_fifo_size_00<=32768)
++ ifxusb_module_params.tx_fifo_size[ 0]=tx_fifo_size_00;
++ else
++ ifxusb_module_params.tx_fifo_size[ 0]=default_param_tx_fifo_size_00;
++ if(tx_fifo_size_01>=0 && tx_fifo_size_01<=32768)
++ ifxusb_module_params.tx_fifo_size[ 1]=tx_fifo_size_01;
++ else
++ ifxusb_module_params.tx_fifo_size[ 1]=default_param_tx_fifo_size_01;
++ if(tx_fifo_size_02>=0 && tx_fifo_size_02<=32768)
++ ifxusb_module_params.tx_fifo_size[ 2]=tx_fifo_size_02;
++ else
++ ifxusb_module_params.tx_fifo_size[ 2]=default_param_tx_fifo_size_02;
++ if(tx_fifo_size_03>=0 && tx_fifo_size_03<=32768)
++ ifxusb_module_params.tx_fifo_size[ 3]=tx_fifo_size_03;
++ else
++ ifxusb_module_params.tx_fifo_size[ 3]=default_param_tx_fifo_size_03;
++ if(tx_fifo_size_04>=0 && tx_fifo_size_04<=32768)
++ ifxusb_module_params.tx_fifo_size[ 4]=tx_fifo_size_04;
++ else
++ ifxusb_module_params.tx_fifo_size[ 4]=default_param_tx_fifo_size_04;
++ if(tx_fifo_size_05>=0 && tx_fifo_size_05<=32768)
++ ifxusb_module_params.tx_fifo_size[ 5]=tx_fifo_size_05;
++ else
++ ifxusb_module_params.tx_fifo_size[ 5]=default_param_tx_fifo_size_05;
++ if(tx_fifo_size_06>=0 && tx_fifo_size_06<=32768)
++ ifxusb_module_params.tx_fifo_size[ 6]=tx_fifo_size_06;
++ else
++ ifxusb_module_params.tx_fifo_size[ 6]=default_param_tx_fifo_size_06;
++ if(tx_fifo_size_07>=0 && tx_fifo_size_07<=32768)
++ ifxusb_module_params.tx_fifo_size[ 7]=tx_fifo_size_07;
++ else
++ ifxusb_module_params.tx_fifo_size[ 7]=default_param_tx_fifo_size_07;
++ if(tx_fifo_size_08>=0 && tx_fifo_size_08<=32768)
++ ifxusb_module_params.tx_fifo_size[ 8]=tx_fifo_size_08;
++ else
++ ifxusb_module_params.tx_fifo_size[ 8]=default_param_tx_fifo_size_08;
++ if(tx_fifo_size_09>=0 && tx_fifo_size_09<=32768)
++ ifxusb_module_params.tx_fifo_size[ 9]=tx_fifo_size_09;
++ else
++ ifxusb_module_params.tx_fifo_size[ 9]=default_param_tx_fifo_size_09;
++ if(tx_fifo_size_10>=0 && tx_fifo_size_10<=32768)
++ ifxusb_module_params.tx_fifo_size[10]=tx_fifo_size_10;
++ else
++ ifxusb_module_params.tx_fifo_size[10]=default_param_tx_fifo_size_10;
++ if(tx_fifo_size_11>=0 && tx_fifo_size_11<=32768)
++ ifxusb_module_params.tx_fifo_size[11]=tx_fifo_size_11;
++ else
++ ifxusb_module_params.tx_fifo_size[11]=default_param_tx_fifo_size_11;
++ if(tx_fifo_size_12>=0 && tx_fifo_size_12<=32768)
++ ifxusb_module_params.tx_fifo_size[12]=tx_fifo_size_12;
++ else
++ ifxusb_module_params.tx_fifo_size[12]=default_param_tx_fifo_size_12;
++ if(tx_fifo_size_13>=0 && tx_fifo_size_13<=32768)
++ ifxusb_module_params.tx_fifo_size[13]=tx_fifo_size_13;
++ else
++ ifxusb_module_params.tx_fifo_size[13]=default_param_tx_fifo_size_13;
++ if(tx_fifo_size_14>=0 && tx_fifo_size_14<=32768)
++ ifxusb_module_params.tx_fifo_size[14]=tx_fifo_size_14;
++ else
++ ifxusb_module_params.tx_fifo_size[14]=default_param_tx_fifo_size_14;
++ if(tx_fifo_size_15>=0 && tx_fifo_size_15<=32768)
++ ifxusb_module_params.tx_fifo_size[15]=tx_fifo_size_15;
++ else
++ ifxusb_module_params.tx_fifo_size[15]=default_param_tx_fifo_size_15;
++ if(thr_ctl==0 || thr_ctl==1)
++ ifxusb_module_params.thr_ctl=thr_ctl;
++ else
++ ifxusb_module_params.thr_ctl=default_param_thr_ctl;
++ if(tx_thr_length>=16 && tx_thr_length<=511)
++ ifxusb_module_params.tx_thr_length=tx_thr_length;
++ else
++ ifxusb_module_params.tx_thr_length=default_param_tx_thr_length;
++ if(rx_thr_length>=16 && rx_thr_length<=511)
++ ifxusb_module_params.rx_thr_length=rx_thr_length;
++ else
++ ifxusb_module_params.rx_thr_length=default_param_rx_thr_length;
++ #else //__DED_FIFO__
++ if(nperio_tx_fifo_size>=16 && nperio_tx_fifo_size<=32768)
++ ifxusb_module_params.tx_fifo_size[ 0]=nperio_tx_fifo_size;
++ else
++ ifxusb_module_params.tx_fifo_size[ 0]=default_param_nperio_tx_fifo_size;
++ if(perio_tx_fifo_size_01>=0 && perio_tx_fifo_size_01<=32768)
++ ifxusb_module_params.tx_fifo_size[ 1]=perio_tx_fifo_size_01;
++ else
++ ifxusb_module_params.tx_fifo_size[ 1]=default_param_perio_tx_fifo_size_01;
++ if(perio_tx_fifo_size_02>=0 && perio_tx_fifo_size_02<=32768)
++ ifxusb_module_params.tx_fifo_size[ 2]=perio_tx_fifo_size_02;
++ else
++ ifxusb_module_params.tx_fifo_size[ 2]=default_param_perio_tx_fifo_size_02;
++ if(perio_tx_fifo_size_03>=0 && perio_tx_fifo_size_03<=32768)
++ ifxusb_module_params.tx_fifo_size[ 3]=perio_tx_fifo_size_03;
++ else
++ ifxusb_module_params.tx_fifo_size[ 3]=default_param_perio_tx_fifo_size_03;
++ if(perio_tx_fifo_size_04>=0 && perio_tx_fifo_size_04<=32768)
++ ifxusb_module_params.tx_fifo_size[ 4]=perio_tx_fifo_size_04;
++ else
++ ifxusb_module_params.tx_fifo_size[ 4]=default_param_perio_tx_fifo_size_04;
++ if(perio_tx_fifo_size_05>=0 && perio_tx_fifo_size_05<=32768)
++ ifxusb_module_params.tx_fifo_size[ 5]=perio_tx_fifo_size_05;
++ else
++ ifxusb_module_params.tx_fifo_size[ 5]=default_param_perio_tx_fifo_size_05;
++ if(perio_tx_fifo_size_06>=0 && perio_tx_fifo_size_06<=32768)
++ ifxusb_module_params.tx_fifo_size[ 6]=perio_tx_fifo_size_06;
++ else
++ ifxusb_module_params.tx_fifo_size[ 6]=default_param_perio_tx_fifo_size_06;
++ if(perio_tx_fifo_size_07>=0 && perio_tx_fifo_size_07<=32768)
++ ifxusb_module_params.tx_fifo_size[ 7]=perio_tx_fifo_size_07;
++ else
++ ifxusb_module_params.tx_fifo_size[ 7]=default_param_perio_tx_fifo_size_07;
++ if(perio_tx_fifo_size_08>=0 && perio_tx_fifo_size_08<=32768)
++ ifxusb_module_params.tx_fifo_size[ 8]=perio_tx_fifo_size_08;
++ else
++ ifxusb_module_params.tx_fifo_size[ 8]=default_param_perio_tx_fifo_size_08;
++ if(perio_tx_fifo_size_09>=0 && perio_tx_fifo_size_09<=32768)
++ ifxusb_module_params.tx_fifo_size[ 9]=perio_tx_fifo_size_09;
++ else
++ ifxusb_module_params.tx_fifo_size[ 9]=default_param_perio_tx_fifo_size_09;
++ if(perio_tx_fifo_size_10>=0 && perio_tx_fifo_size_10<=32768)
++ ifxusb_module_params.tx_fifo_size[10]=perio_tx_fifo_size_10;
++ else
++ ifxusb_module_params.tx_fifo_size[10]=default_param_perio_tx_fifo_size_10;
++ if(perio_tx_fifo_size_11>=0 && perio_tx_fifo_size_11<=32768)
++ ifxusb_module_params.tx_fifo_size[11]=perio_tx_fifo_size_11;
++ else
++ ifxusb_module_params.tx_fifo_size[11]=default_param_perio_tx_fifo_size_11;
++ if(perio_tx_fifo_size_12>=0 && perio_tx_fifo_size_12<=32768)
++ ifxusb_module_params.tx_fifo_size[12]=perio_tx_fifo_size_12;
++ else
++ ifxusb_module_params.tx_fifo_size[12]=default_param_perio_tx_fifo_size_12;
++ if(perio_tx_fifo_size_13>=0 && perio_tx_fifo_size_13<=32768)
++ ifxusb_module_params.tx_fifo_size[13]=perio_tx_fifo_size_13;
++ else
++ ifxusb_module_params.tx_fifo_size[13]=default_param_perio_tx_fifo_size_13;
++ if(perio_tx_fifo_size_14>=0 && perio_tx_fifo_size_14<=32768)
++ ifxusb_module_params.tx_fifo_size[14]=perio_tx_fifo_size_14;
++ else
++ ifxusb_module_params.tx_fifo_size[14]=default_param_perio_tx_fifo_size_14;
++ if(perio_tx_fifo_size_15>=0 && perio_tx_fifo_size_15<=32768)
++ ifxusb_module_params.tx_fifo_size[15]=perio_tx_fifo_size_15;
++ else
++ ifxusb_module_params.tx_fifo_size[15]=default_param_perio_tx_fifo_size_15;
++ #endif //__DED_FIFO__
++ #endif //__IS_DEVICE__
++}
++
++
++
++
++
++
++
++module_param(dbg_lvl, long, 0444);
++MODULE_PARM_DESC(dbg_lvl, "Debug level.");
++
++module_param(dma_burst_size, short, 0444);
++MODULE_PARM_DESC(dma_burst_size, "DMA Burst Size 0, 1, 4, 8, 16");
++
++module_param(speed, short, 0444);
++MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed");
++
++module_param(data_fifo_size, long, 0444);
++MODULE_PARM_DESC(data_fifo_size, "Total number of words in the data FIFO memory 32-32768");
++
++#ifdef __IS_DEVICE__
++ module_param(rx_fifo_size, long, 0444);
++ MODULE_PARM_DESC(rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
++
++ #ifdef __DED_FIFO__
++ module_param(tx_fifo_size_00, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_00, "Number of words in the Tx FIFO #00 16-32768");
++ module_param(tx_fifo_size_01, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_01, "Number of words in the Tx FIFO #01 0-32768");
++ module_param(tx_fifo_size_02, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_02, "Number of words in the Tx FIFO #02 0-32768");
++ module_param(tx_fifo_size_03, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_03, "Number of words in the Tx FIFO #03 0-32768");
++ module_param(tx_fifo_size_04, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_04, "Number of words in the Tx FIFO #04 0-32768");
++ module_param(tx_fifo_size_05, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_05, "Number of words in the Tx FIFO #05 0-32768");
++ module_param(tx_fifo_size_06, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_06, "Number of words in the Tx FIFO #06 0-32768");
++ module_param(tx_fifo_size_07, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_07, "Number of words in the Tx FIFO #07 0-32768");
++ module_param(tx_fifo_size_08, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_08, "Number of words in the Tx FIFO #08 0-32768");
++ module_param(tx_fifo_size_09, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_09, "Number of words in the Tx FIFO #09 0-32768");
++ module_param(tx_fifo_size_10, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_10, "Number of words in the Tx FIFO #10 0-32768");
++ module_param(tx_fifo_size_11, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_11, "Number of words in the Tx FIFO #11 0-32768");
++ module_param(tx_fifo_size_12, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_12, "Number of words in the Tx FIFO #12 0-32768");
++ module_param(tx_fifo_size_13, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_13, "Number of words in the Tx FIFO #13 0-32768");
++ module_param(tx_fifo_size_14, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_14, "Number of words in the Tx FIFO #14 0-32768");
++ module_param(tx_fifo_size_15, long, 0444);
++ MODULE_PARM_DESC(tx_fifo_size_15, "Number of words in the Tx FIFO #15 0-32768");
++
++ module_param(thr_ctl, short, 0444);
++ MODULE_PARM_DESC(thr_ctl, "0=Without 1=With Theshold Ctrl");
++
++ module_param(tx_thr_length, long, 0444);
++ MODULE_PARM_DESC(tx_thr_length, "TX Threshold length");
++
++ module_param(rx_thr_length, long, 0444);
++ MODULE_PARM_DESC(rx_thr_length, "RX Threshold length");
++
++ #else
++ module_param(nperio_tx_fifo_size, long, 0444);
++ MODULE_PARM_DESC(nperio_tx_fifo_size, "Number of words in the non-periodic Tx FIFO 16-32768");
++
++ module_param(perio_tx_fifo_size_01, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_01, "Number of words in the periodic Tx FIFO #01 0-32768");
++ module_param(perio_tx_fifo_size_02, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_02, "Number of words in the periodic Tx FIFO #02 0-32768");
++ module_param(perio_tx_fifo_size_03, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_03, "Number of words in the periodic Tx FIFO #03 0-32768");
++ module_param(perio_tx_fifo_size_04, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_04, "Number of words in the periodic Tx FIFO #04 0-32768");
++ module_param(perio_tx_fifo_size_05, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_05, "Number of words in the periodic Tx FIFO #05 0-32768");
++ module_param(perio_tx_fifo_size_06, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_06, "Number of words in the periodic Tx FIFO #06 0-32768");
++ module_param(perio_tx_fifo_size_07, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_07, "Number of words in the periodic Tx FIFO #07 0-32768");
++ module_param(perio_tx_fifo_size_08, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_08, "Number of words in the periodic Tx FIFO #08 0-32768");
++ module_param(perio_tx_fifo_size_09, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_09, "Number of words in the periodic Tx FIFO #09 0-32768");
++ module_param(perio_tx_fifo_size_10, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_10, "Number of words in the periodic Tx FIFO #10 0-32768");
++ module_param(perio_tx_fifo_size_11, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_11, "Number of words in the periodic Tx FIFO #11 0-32768");
++ module_param(perio_tx_fifo_size_12, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_12, "Number of words in the periodic Tx FIFO #12 0-32768");
++ module_param(perio_tx_fifo_size_13, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_13, "Number of words in the periodic Tx FIFO #13 0-32768");
++ module_param(perio_tx_fifo_size_14, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_14, "Number of words in the periodic Tx FIFO #14 0-32768");
++ module_param(perio_tx_fifo_size_15, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size_15, "Number of words in the periodic Tx FIFO #15 0-32768");
++ #endif//__DED_FIFO__
++ module_param(dev_endpoints, short, 0444);
++ MODULE_PARM_DESC(dev_endpoints, "The number of endpoints in addition to EP0 available for device mode 1-15");
++#endif
++
++#ifdef __IS_HOST__
++ module_param(rx_fifo_size, long, 0444);
++ MODULE_PARM_DESC(rx_fifo_size, "Number of words in the Rx FIFO 16-32768");
++
++ module_param(nperio_tx_fifo_size, long, 0444);
++ MODULE_PARM_DESC(nperio_tx_fifo_size, "Number of words in the non-periodic Tx FIFO 16-32768");
++
++ module_param(perio_tx_fifo_size, long, 0444);
++ MODULE_PARM_DESC(perio_tx_fifo_size, "Number of words in the host periodic Tx FIFO 16-32768");
++
++ module_param(host_channels, short, 0444);
++ MODULE_PARM_DESC(host_channels, "The number of host channel registers to use 1-16");
++#endif
++
++module_param(max_transfer_size, long, 0444);
++MODULE_PARM_DESC(max_transfer_size, "The maximum transfer size supported in bytes 2047-65535");
++
++module_param(max_packet_count, long, 0444);
++MODULE_PARM_DESC(max_packet_count, "The maximum number of packets in a transfer 15-511");
++
++module_param(phy_utmi_width, long, 0444);
++MODULE_PARM_DESC(phy_utmi_width, "Specifies the UTMI+ Data Width 8 or 16 bits");
++
++module_param(turn_around_time_hs, long, 0444);
++MODULE_PARM_DESC(turn_around_time_hs, "Turn-Around time for HS");
++
++module_param(turn_around_time_fs, long, 0444);
++MODULE_PARM_DESC(turn_around_time_fs, "Turn-Around time for FS");
++
++module_param(timeout_cal_hs, long, 0444);
++MODULE_PARM_DESC(timeout_cal_hs, "Timeout Cal for HS");
++
++module_param(timeout_cal_fs, long, 0444);
++MODULE_PARM_DESC(timeout_cal_fs, "Timeout Cal for FS");
++
++
+diff --git a/drivers/usb/ifxhcd/ifxusb_plat.h b/drivers/usb/ifxhcd/ifxusb_plat.h
+new file mode 100644
+index 0000000..a50294f
+--- /dev/null
++++ b/drivers/usb/ifxhcd/ifxusb_plat.h
+@@ -0,0 +1,1018 @@
++/*****************************************************************************
++ ** FILE NAME : ifxusb_plat.h
++ ** PROJECT : IFX USB sub-system V3
++ ** MODULES : IFX USB sub-system Host and Device driver
++ ** SRC VERSION : 1.0
++ ** DATE : 1/Jan/2009
++ ** AUTHOR : Chen, Howard
++ ** DESCRIPTION : This file contains the Platform Specific constants, interfaces
++ ** (functions and macros).
++ ** FUNCTIONS :
++ ** COMPILER : gcc
++ ** REFERENCE : IFX hardware ref handbook for each plateforms
++ ** COPYRIGHT :
++ ** Version Control Section **
++ ** $Author$
++ ** $Date$
++ ** $Revisions$
++ ** $Log$ Revision history
++ *****************************************************************************/
++
++
++/*!
++ \defgroup IFXUSB_PLATEFORM_DEFINITION Platform Specific constants, interfaces (functions and macros).
++ \ingroup IFXUSB_DRIVER_V3
++ \brief Maintain plateform specific definitions and macros in this file.
++ Each plateform has its own definition zone.
++ */
++
++/*!
++ \defgroup IFXUSB_PLATEFORM_MEM_ADDR Definition of memory address and size and default parameters
++ \ingroup IFXUSB_PLATEFORM_DEFINITION
++ */
++
++/*!
++ \defgroup IFXUSB_DBG_ROUTINE Routines for debug message
++ \ingroup IFXUSB_PLATEFORM_DEFINITION
++ */
++
++
++/*! \file ifxusb_plat.h
++ \ingroup IFXUSB_DRIVER_V3
++ \brief This file contains the Platform Specific constants, interfaces (functions and macros).
++*/
++
++#if !defined(__IFXUSB_PLAT_H__)
++#define __IFXUSB_PLAT_H__
++
++
++#include <linux/types.h>
++#include <linux/slab.h>
++#include <linux/list.h>
++#include <linux/delay.h>
++#include <asm/io.h>
++
++
++#define IFXUSB_IOMEM_SIZE 0x00001000
++#define IFXUSB_FIFOMEM_SIZE 0x00010000
++#define IFXUSB_FIFODBG_SIZE 0x00020000
++
++
++
++/*!
++ \addtogroup IFXUSB_PLATEFORM_MEM_ADDR
++ */
++/*@{*/
++#if defined(__UEIP__)
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++// #define IFXUSB_IRQ 54
++ #define IFXUSB_IOMEM_BASE 0x1e101000
++ #define IFXUSB_FIFOMEM_BASE 0x1e120000
++ #define IFXUSB_FIFODBG_BASE 0x1e140000
++// #define IFXUSB_OC_IRQ 151
++
++ #ifndef DANUBE_RCU_BASE_ADDR
++ #define DANUBE_RCU_BASE_ADDR (0xBF203000)
++ #endif
++
++ #ifndef DANUBE_CGU
++ #define DANUBE_CGU (0xBF103000)
++ #endif
++ #ifndef DANUBE_CGU_IFCCR
++ #define DANUBE_CGU_IFCCR ((volatile unsigned long *)(DANUBE_CGU+ 0x0018))
++ #endif
++ #ifndef DANUBE_PMU
++ #define DANUBE_PMU (KSEG1+0x1F102000)
++ #endif
++ #ifndef DANUBE_PMU_PWDCR
++ #define DANUBE_PMU_PWDCR ((volatile unsigned long *)(DANUBE_PMU+0x001C))
++ #endif
++
++ #ifndef DANUBE_GPIO_P0_OUT
++ #define DANUBE_GPIO_P0_OUT (0xBF103000+0x10)
++ #define DANUBE_GPIO_P0_DIR (0xBF103000+0x18)
++ #define DANUBE_GPIO_P0_ALTSEL0 (0xBF103000+0x1C)
++ #define DANUBE_GPIO_P0_ALTSEL1 (0xBF103000+0x20)
++ #define DANUBE_GPIO_P0_OD (0xBF103000+0x24)
++ #define DANUBE_GPIO_P0_PUDSEL (0xBF103000+0x2C)
++ #define DANUBE_GPIO_P0_PUDEN (0xBF103000+0x30)
++ #define DANUBE_GPIO_P1_OUT (0xBF103000+0x40)
++ #define DANUBE_GPIO_P1_DIR (0xBF103000+0x48)
++ #define DANUBE_GPIO_P1_ALTSEL0 (0xBF103000+0x4C)
++ #define DANUBE_GPIO_P1_ALTSEL1 (0xBF103000+0x50)
++ #define DANUBE_GPIO_P1_OD (0xBF103000+0x54)
++ #define DANUBE_GPIO_P1_PUDSEL (0xBF103000+0x5C)
++ #define DANUBE_GPIO_P1_PUDEN (0xBF103000+0x60)
++ #endif
++
++ #define DANUBE_RCU_USBCFG ((volatile unsigned long *)(DANUBE_RCU_BASE_ADDR + 0x18))
++ #define DANUBE_RCU_RESET ((volatile unsigned long *)(DANUBE_RCU_BASE_ADDR + 0x10))
++ #define DANUBE_USBCFG_HDSEL_BIT 11 // 0:host, 1:device
++ #define DANUBE_USBCFG_HOST_END_BIT 10 // 0:little_end, 1:big_end
++ #define DANUBE_USBCFG_SLV_END_BIT 9 // 0:little_end, 1:big_end
++
++ #define default_param_dma_burst_size 4
++
++ #define default_param_speed IFXUSB_PARAM_SPEED_HIGH
++
++ #define default_param_max_transfer_size -1 //(Max, hwcfg)
++ #define default_param_max_packet_count -1 //(Max, hwcfg)
++ #define default_param_phy_utmi_width 16
++
++ #define default_param_turn_around_time_hs 4
++ #define default_param_turn_around_time_fs 4
++ #define default_param_timeout_cal_hs -1 //(NoChange)
++ #define default_param_timeout_cal_fs -1 //(NoChange)
++
++ #define default_param_data_fifo_size -1 //(Max, hwcfg)
++
++ #ifdef __IS_HOST__
++ #define default_param_host_channels -1 //(Max, hwcfg)
++ #define default_param_rx_fifo_size 640
++ #define default_param_nperio_tx_fifo_size 640
++ #define default_param_perio_tx_fifo_size 768
++ #endif //__IS_HOST__
++
++ #ifdef __IS_DEVICE__
++ #ifdef __DED_INTR__
++ #define default_param_rx_fifo_size 1024
++ #define default_param_nperio_tx_fifo_size 1016
++ #define default_param_perio_tx_fifo_size_01 8
++ #else
++ #define default_param_rx_fifo_size 1024
++ #define default_param_nperio_tx_fifo_size 1024
++ #define default_param_perio_tx_fifo_size_01 0
++ #endif
++ #define default_param_perio_tx_fifo_size_02 0
++ #define default_param_perio_tx_fifo_size_03 0
++ #define default_param_perio_tx_fifo_size_04 0
++ #define default_param_perio_tx_fifo_size_05 0
++ #define default_param_perio_tx_fifo_size_06 0
++ #define default_param_perio_tx_fifo_size_07 0
++ #define default_param_perio_tx_fifo_size_08 0
++ #define default_param_perio_tx_fifo_size_09 0
++ #define default_param_perio_tx_fifo_size_10 0
++ #define default_param_perio_tx_fifo_size_11 0
++ #define default_param_perio_tx_fifo_size_12 0
++ #define default_param_perio_tx_fifo_size_13 0
++ #define default_param_perio_tx_fifo_size_14 0
++ #define default_param_perio_tx_fifo_size_15 0
++ #endif //__IS_DEVICE__
++
++ #elif defined(__IS_AMAZON_SE__)
++ //#include <asm/amazon_se/amazon_se.h>
++ //#include <asm/amazon_se/irq.h>
++
++// #define IFXUSB_IRQ 31
++ #define IFXUSB_IOMEM_BASE 0x1e101000
++ #define IFXUSB_FIFOMEM_BASE 0x1e120000
++ #define IFXUSB_FIFODBG_BASE 0x1e140000
++// #define IFXUSB_OC_IRQ 20
++
++ #ifndef AMAZON_SE_RCU_BASE_ADDR
++ #define AMAZON_SE_RCU_BASE_ADDR (0xBF203000)
++ #endif
++ #define AMAZON_SE_RCU_USBCFG ((volatile unsigned long *)(AMAZON_SE_RCU_BASE_ADDR + 0x18))
++ #define AMAZON_SE_RCU_RESET ((volatile unsigned long *)(AMAZON_SE_RCU_BASE_ADDR + 0x10))
++ #define AMAZON_SE_USBCFG_HDSEL_BIT 11 // 0:host, 1:device
++ #define AMAZON_SE_USBCFG_HOST_END_BIT 10 // 0:little_end, 1:big_end
++ #define AMAZON_SE_USBCFG_SLV_END_BIT 9 // 0:little_end, 1:big_end
++
++ #ifndef AMAZON_SE_GPIO_P0_OUT
++ #define AMAZON_SE_GPIO_P0_OUT (0xBF103000+0x10)
++ #define AMAZON_SE_GPIO_P0_DIR (0xBF103000+0x18)
++ #define AMAZON_SE_GPIO_P0_ALTSEL0 (0xBF103000+0x1C)
++ #define AMAZON_SE_GPIO_P0_ALTSEL1 (0xBF103000+0x20)
++ #define AMAZON_SE_GPIO_P0_OD (0xBF103000+0x24)
++ #define AMAZON_SE_GPIO_P0_PUDSEL (0xBF103000+0x2C)
++ #define AMAZON_SE_GPIO_P0_PUDEN (0xBF103000+0x30)
++ #define AMAZON_SE_GPIO_P1_OUT (0xBF103000+0x40)
++ #define AMAZON_SE_GPIO_P1_DIR (0xBF103000+0x48)
++ #define AMAZON_SE_GPIO_P1_ALTSEL0 (0xBF103000+0x4C)
++ #define AMAZON_SE_GPIO_P1_ALTSEL1 (0xBF103000+0x50)
++ #define AMAZON_SE_GPIO_P1_OD (0xBF103000+0x54)
++ #define AMAZON_SE_GPIO_P1_PUDSEL (0xBF103000+0x5C)
++ #define AMAZON_SE_GPIO_P1_PUDEN (0xBF103000+0x60)
++ #endif
++
++ #ifndef AMAZON_SE_CGU
++ #define AMAZON_SE_CGU (0xBF103000)
++ #endif
++ #ifndef AMAZON_SE_CGU_IFCCR
++ #define AMAZON_SE_CGU_IFCCR ((volatile unsigned long *)(AMAZON_SE_CGU+ 0x0018))
++ #endif
++ #ifndef AMAZON_SE_PMU
++ #define AMAZON_SE_PMU (KSEG1+0x1F102000)
++ #endif
++ #ifndef AMAZON_SE_PMU_PWDCR
++ #define AMAZON_SE_PMU_PWDCR ((volatile unsigned long *)(AMAZON_SE_PMU+0x001C))
++ #endif
++
++ #define default_param_dma_burst_size 4
++
++ #define default_param_speed IFXUSB_PARAM_SPEED_HIGH
++
++ #define default_param_max_transfer_size -1 //(Max, hwcfg)
++ #define default_param_max_packet_count -1 //(Max, hwcfg)
++ #define default_param_phy_utmi_width 16
++
++ #define default_param_turn_around_time_hs 4 //(NoChange)
++ #define default_param_turn_around_time_fs 4 //(NoChange)
++ #define default_param_timeout_cal_hs -1 //(NoChange)
++ #define default_param_timeout_cal_fs -1 //(NoChange)
++
++ #define default_param_data_fifo_size -1 //(Max, hwcfg)
++
++ #ifdef __IS_HOST__
++ #define default_param_host_channels -1 //(Max, hwcfg)
++ #define default_param_rx_fifo_size 240
++ #define default_param_nperio_tx_fifo_size 240
++ #define default_param_perio_tx_fifo_size 32
++ #endif //__IS_HOST__
++ #ifdef __IS_DEVICE__
++ #ifdef __DED_INTR__
++ #define default_param_rx_fifo_size 256
++ #define default_param_nperio_tx_fifo_size 248
++ #define default_param_perio_tx_fifo_size_01 8
++ #else
++ #define default_param_rx_fifo_size 256
++ #define default_param_nperio_tx_fifo_size 256
++ #define default_param_perio_tx_fifo_size_01 0
++ #endif
++ #define default_param_perio_tx_fifo_size_02 0
++ #define default_param_perio_tx_fifo_size_03 0
++ #define default_param_perio_tx_fifo_size_04 0
++ #define default_param_perio_tx_fifo_size_05 0
++ #define default_param_perio_tx_fifo_size_06 0
++ #define default_param_perio_tx_fifo_size_07 0
++ #define default_param_perio_tx_fifo_size_08 0
++ #define default_param_perio_tx_fifo_size_09 0
++ #define default_param_perio_tx_fifo_size_10 0
++ #define default_param_perio_tx_fifo_size_11 0
++ #define default_param_perio_tx_fifo_size_12 0
++ #define default_param_perio_tx_fifo_size_13 0
++ #define default_param_perio_tx_fifo_size_14 0
++ #define default_param_perio_tx_fifo_size_15 0
++ #endif //__IS_DEVICE__
++
++ #elif defined(__IS_AR9__)
++// #define IFXUSB1_IRQ 54
++ #define IFXUSB1_IOMEM_BASE 0x1E101000
++ #define IFXUSB1_FIFOMEM_BASE 0x1E120000
++ #define IFXUSB1_FIFODBG_BASE 0x1E140000
++
++// #define IFXUSB2_IRQ 83
++ #define IFXUSB2_IOMEM_BASE 0x1E106000
++ #define IFXUSB2_FIFOMEM_BASE 0x1E1E0000
++ #define IFXUSB2_FIFODBG_BASE 0x1E1C0000
++
++// #define IFXUSB_OC_IRQ 60
++
++ #ifndef AR9_RCU_BASE_ADDR
++ #define AR9_RCU_BASE_ADDR (0xBF203000)
++ #endif
++
++ #ifndef AR9_CGU
++ #define AR9_CGU (0xBF103000)
++ #endif
++ #ifndef AR9_CGU_IFCCR
++ #define AR9_CGU_IFCCR ((volatile unsigned long *)(AR9_CGU+ 0x0018))
++ #endif
++
++ #ifndef AR9_PMU
++ #define AR9_PMU (KSEG1+0x1F102000)
++ #endif
++ #ifndef AR9_PMU_PWDCR
++ #define AR9_PMU_PWDCR ((volatile unsigned long *)(AR9_PMU+0x001C))
++ #endif
++
++ #ifndef AR9_GPIO_P0_OUT
++ #define AR9_GPIO_P0_OUT (0xBF103000+0x10)
++ #define AR9_GPIO_P0_DIR (0xBF103000+0x18)
++ #define AR9_GPIO_P0_ALTSEL0 (0xBF103000+0x1C)
++ #define AR9_GPIO_P0_ALTSEL1 (0xBF103000+0x20)
++ #define AR9_GPIO_P0_OD (0xBF103000+0x24)
++ #define AR9_GPIO_P0_PUDSEL (0xBF103000+0x2C)
++ #define AR9_GPIO_P0_PUDEN (0xBF103000+0x30)
++ #define AR9_GPIO_P1_OUT (0xBF103000+0x40)
++ #define AR9_GPIO_P1_DIR (0xBF103000+0x48)
++ #define AR9_GPIO_P1_ALTSEL0 (0xBF103000+0x4C)
++ #define AR9_GPIO_P1_ALTSEL1 (0xBF103000+0x50)
++ #define AR9_GPIO_P1_OD (0xBF103000+0x54)
++ #define AR9_GPIO_P1_PUDSEL (0xBF103000+0x5C)
++ #define AR9_GPIO_P1_PUDEN (0xBF103000+0x60)
++ #endif
++
++ #define AR9_RCU_USB1CFG ((volatile unsigned long *)(AR9_RCU_BASE_ADDR + 0x18))
++ #define AR9_RCU_USB2CFG ((volatile unsigned long *)(AR9_RCU_BASE_ADDR + 0x34))
++ #define AR9_RCU_USBRESET ((volatile unsigned long *)(AR9_RCU_BASE_ADDR + 0x10))
++ #define AR9_USBCFG_ARB 7 //
++ #define AR9_USBCFG_HDSEL_BIT 11 // 0:host, 1:device
++ #define AR9_USBCFG_HOST_END_BIT 10 // 0:little_end, 1:big_end
++ #define AR9_USBCFG_SLV_END_BIT 17 // 0:little_end, 1:big_end
++
++ #define default_param_dma_burst_size 4
++
++ #define default_param_speed IFXUSB_PARAM_SPEED_HIGH
++
++ #define default_param_max_transfer_size -1 //(Max, hwcfg)
++ #define default_param_max_packet_count -1 //(Max, hwcfg)
++ #define default_param_phy_utmi_width 16
++
++ #define default_param_turn_around_time_hs 4 //(NoChange)
++ #define default_param_turn_around_time_fs 4 //(NoChange)
++ #define default_param_timeout_cal_hs -1 //(NoChange)
++ #define default_param_timeout_cal_fs -1 //(NoChange)
++
++ #define default_param_data_fifo_size -1 //(Max, hwcfg)
++
++ #ifdef __IS_HOST__
++ #define default_param_host_channels -1 //(Max, hwcfg)
++ #define default_param_rx_fifo_size 240
++ #define default_param_nperio_tx_fifo_size 240
++ #define default_param_perio_tx_fifo_size 32
++ #endif //__IS_HOST__
++ #ifdef __IS_DEVICE__
++ #ifdef __DED_INTR__
++ #define default_param_rx_fifo_size 256
++// #define default_param_nperio_tx_fifo_size 248
++// #define default_param_perio_tx_fifo_size_01 8
++ #define default_param_nperio_tx_fifo_size 252
++ #define default_param_perio_tx_fifo_size_01 4
++ #else
++ #define default_param_rx_fifo_size 256
++ #define default_param_nperio_tx_fifo_size 256
++ #define default_param_perio_tx_fifo_size_01 0
++ #endif
++ #define default_param_perio_tx_fifo_size_02 0
++ #define default_param_perio_tx_fifo_size_03 0
++ #define default_param_perio_tx_fifo_size_04 0
++ #define default_param_perio_tx_fifo_size_05 0
++ #define default_param_perio_tx_fifo_size_06 0
++ #define default_param_perio_tx_fifo_size_07 0
++ #define default_param_perio_tx_fifo_size_08 0
++ #define default_param_perio_tx_fifo_size_09 0
++ #define default_param_perio_tx_fifo_size_10 0
++ #define default_param_perio_tx_fifo_size_11 0
++ #define default_param_perio_tx_fifo_size_12 0
++ #define default_param_perio_tx_fifo_size_13 0
++ #define default_param_perio_tx_fifo_size_14 0
++ #define default_param_perio_tx_fifo_size_15 0
++ #endif //__IS_DEVICE__
++
++ #elif defined(__IS_VR9__)
++// #define IFXUSB1_IRQ 54
++ #define IFXUSB1_IOMEM_BASE 0x1E101000
++ #define IFXUSB1_FIFOMEM_BASE 0x1E120000
++ #define IFXUSB1_FIFODBG_BASE 0x1E140000
++
++// #define IFXUSB2_IRQ 83
++ #define IFXUSB2_IOMEM_BASE 0x1E106000
++ #define IFXUSB2_FIFOMEM_BASE 0x1E1E0000
++ #define IFXUSB2_FIFODBG_BASE 0x1E1C0000
++// #define IFXUSB_OC_IRQ 60
++
++ #ifndef VR9_RCU_BASE_ADDR
++ #define VR9_RCU_BASE_ADDR (0xBF203000)
++ #endif
++
++ #ifndef VR9_CGU
++ #define VR9_CGU (0xBF103000)
++ #endif
++ #ifndef VR9_CGU_IFCCR
++ #define VR9_CGU_IFCCR ((volatile unsigned long *)(VR9_CGU+ 0x0018))
++ #endif
++
++ #ifndef VR9_PMU
++ #define VR9_PMU (KSEG1+0x1F102000)
++ #endif
++ #ifndef VR9_PMU_PWDCR
++ #define VR9_PMU_PWDCR ((volatile unsigned long *)(VR9_PMU+0x001C))
++ #endif
++
++ #ifndef VR9_GPIO_P0_OUT
++ #define VR9_GPIO_P0_OUT (0xBF103000+0x10)
++ #define VR9_GPIO_P0_DIR (0xBF103000+0x18)
++ #define VR9_GPIO_P0_ALTSEL0 (0xBF103000+0x1C)
++ #define VR9_GPIO_P0_ALTSEL1 (0xBF103000+0x20)
++ #define VR9_GPIO_P0_OD (0xBF103000+0x24)
++ #define VR9_GPIO_P0_PUDSEL (0xBF103000+0x2C)
++ #define VR9_GPIO_P0_PUDEN (0xBF103000+0x30)
++ #define VR9_GPIO_P1_OUT (0xBF103000+0x40)
++ #define VR9_GPIO_P1_DIR (0xBF103000+0x48)
++ #define VR9_GPIO_P1_ALTSEL0 (0xBF103000+0x4C)
++ #define VR9_GPIO_P1_ALTSEL1 (0xBF103000+0x50)
++ #define VR9_GPIO_P1_OD (0xBF103000+0x54)
++ #define VR9_GPIO_P1_PUDSEL (0xBF103000+0x5C)
++ #define VR9_GPIO_P1_PUDEN (0xBF103000+0x60)
++ #endif
++
++ #define VR9_RCU_USB1CFG ((volatile unsigned long *)(VR9_RCU_BASE_ADDR + 0x18))
++ #define VR9_RCU_USB2CFG ((volatile unsigned long *)(VR9_RCU_BASE_ADDR + 0x34))
++ #define VR9_RCU_USB_ANA_CFG1A ((volatile unsigned long *)(AR9_RCU_BASE_ADDR + 0x38))
++ #define VR9_RCU_USB_ANA_CFG1B ((volatile unsigned long *)(AR9_RCU_BASE_ADDR + 0x3C))
++ #define VR9_RCU_USBRESET ((volatile unsigned long *)(VR9_RCU_BASE_ADDR + 0x10))
++ #define VR9_RCU_USBRESET2 ((volatile unsigned long *)(VR9_RCU_BASE_ADDR + 0x48))
++ #define VR9_USBCFG_ARB 7 //
++ #define VR9_USBCFG_HDSEL_BIT 11 // 0:host, 1:device
++ #define VR9_USBCFG_HOST_END_BIT 10 // 0:little_end, 1:big_end
++ #define VR9_USBCFG_SLV_END_BIT 9 // 0:little_end, 1:big_end
++
++ /*== AVM/BC 20101220 Workaround VR9 DMA burst size ==
++ * Using 2 Devices in diferent ports cause a general USB Host Error.
++ * Workaround found in UGW4.3
++ */
++// #define default_param_dma_burst_size 4 //(ALL)
++ //WA for AHB
++ #define default_param_dma_burst_size 0 //(ALL)
++
++ #define default_param_speed IFXUSB_PARAM_SPEED_HIGH
++
++ #define default_param_max_transfer_size -1 //(Max, hwcfg)
++ #define default_param_max_packet_count -1 //(Max, hwcfg)
++ #define default_param_phy_utmi_width 16
++
++ #define default_param_turn_around_time_hs 6 //(NoChange) snpsid >= 0x4f54260a
++ #define default_param_turn_around_time_fs 6 //(NoChange) snpsid >= 0x4f54260a
++ #define default_param_timeout_cal_hs -1 //(NoChange)
++ #define default_param_timeout_cal_fs -1 //(NoChange)
++
++ #define default_param_data_fifo_size -1 //(Max, hwcfg)
++
++ #ifdef __IS_HOST__
++ #define default_param_host_channels -1 //(Max, hwcfg)
++ #define default_param_rx_fifo_size 240
++ #define default_param_nperio_tx_fifo_size 240
++ #define default_param_perio_tx_fifo_size 32
++ #endif //__IS_HOST__
++ #ifdef __IS_DEVICE__
++#if 0
++ #define default_param_rx_fifo_size 256
++ #define default_param_tx_fifo_size_00 -1
++ #define default_param_tx_fifo_size_01 -1
++ #define default_param_tx_fifo_size_02 -1
++#else
++ #define default_param_rx_fifo_size 256
++ #define default_param_tx_fifo_size_00 32
++ #define default_param_tx_fifo_size_01 200
++ #define default_param_tx_fifo_size_02 8
++#endif
++ #define default_param_tx_fifo_size_03 -1
++ #define default_param_tx_fifo_size_04 -1
++ #define default_param_tx_fifo_size_05 -1
++ #define default_param_tx_fifo_size_06 -1
++ #define default_param_tx_fifo_size_07 -1
++ #define default_param_tx_fifo_size_08 -1
++ #define default_param_tx_fifo_size_09 -1
++ #define default_param_tx_fifo_size_10 -1
++ #define default_param_tx_fifo_size_11 -1
++ #define default_param_tx_fifo_size_12 -1
++ #define default_param_tx_fifo_size_13 -1
++ #define default_param_tx_fifo_size_14 -1
++ #define default_param_tx_fifo_size_15 -1
++ #define default_param_dma_unalgned_tx -1
++ #define default_param_dma_unalgned_rx -1
++ #define default_param_thr_ctl -1
++ #define default_param_tx_thr_length -1
++ #define default_param_rx_thr_length -1
++ #endif //__IS_DEVICE__
++ #else // __IS_VR9__
++ #error "Please choose one platform!!"
++ #endif // __IS_VR9__
++
++#else //UEIP
++ #if defined(__IS_TWINPASS__) || defined(__IS_DANUBE__)
++// #define IFXUSB_IRQ 54
++ #define IFXUSB_IOMEM_BASE 0x1e101000
++ #define IFXUSB_FIFOMEM_BASE 0x1e120000
++ #define IFXUSB_FIFODBG_BASE 0x1e140000
++// #define IFXUSB_OC_IRQ 151
++
++
++ #ifndef DANUBE_RCU_BASE_ADDR
++ #define DANUBE_RCU_BASE_ADDR (0xBF203000)
++ #endif
++
++ #ifndef DANUBE_CGU
++ #define DANUBE_CGU (0xBF103000)
++ #endif
++ #ifndef DANUBE_CGU_IFCCR
++ #define DANUBE_CGU_IFCCR ((volatile unsigned long *)(DANUBE_CGU+ 0x0018))
++ #endif
++ #ifndef DANUBE_PMU
++ #define DANUBE_PMU (KSEG1+0x1F102000)
++ #endif
++ #ifndef DANUBE_PMU_PWDCR
++ #define DANUBE_PMU_PWDCR ((volatile unsigned long *)(DANUBE_PMU+0x001C))
++ #endif
++
++ #ifndef DANUBE_GPIO_P0_OUT
++ #define DANUBE_GPIO_P0_OUT (0xBF103000+0x10)
++ #define DANUBE_GPIO_P0_DIR (0xBF103000+0x18)
++ #define DANUBE_GPIO_P0_ALTSEL0 (0xBF103000+0x1C)
++ #define DANUBE_GPIO_P0_ALTSEL1 (0xBF103000+0x20)
++ #define DANUBE_GPIO_P0_OD (0xBF103000+0x24)
++ #define DANUBE_GPIO_P0_PUDSEL (0xBF103000+0x2C)
++ #define DANUBE_GPIO_P0_PUDEN (0xBF103000+0x30)
++ #define DANUBE_GPIO_P1_OUT (0xBF103000+0x40)
++ #define DANUBE_GPIO_P1_DIR (0xBF103000+0x48)
++ #define DANUBE_GPIO_P1_ALTSEL0 (0xBF103000+0x4C)
++ #define DANUBE_GPIO_P1_ALTSEL1 (0xBF103000+0x50)
++ #define DANUBE_GPIO_P1_OD (0xBF103000+0x54)
++ #define DANUBE_GPIO_P1_PUDSEL (0xBF103000+0x5C)
++ #define DANUBE_GPIO_P1_PUDEN (0xBF103000+0x60)
++ #endif
++
++
++ #define DANUBE_RCU_USBCFG ((volatile unsigned long *)(DANUBE_RCU_BASE_ADDR + 0x18))
++ #define DANUBE_RCU_RESET ((volatile unsigned long *)(DANUBE_RCU_BASE_ADDR + 0x10))
++ #define DANUBE_USBCFG_HDSEL_BIT 11 // 0:host, 1:device
++ #define DANUBE_USBCFG_HOST_END_BIT 10 // 0:little_end, 1:big_end
++ #define DANUBE_USBCFG_SLV_END_BIT 9 // 0:little_end, 1:big_end
++
++ #define default_param_dma_burst_size 4
++
++ #define default_param_speed IFXUSB_PARAM_SPEED_HIGH
++
++ #define default_param_max_transfer_size -1 //(Max, hwcfg)
++ #define default_param_max_packet_count -1 //(Max, hwcfg)
++ #define default_param_phy_utmi_width 16
++
++ #define default_param_turn_around_time_hs 4 //(NoChange)
++ #define default_param_turn_around_time_fs 4 //(NoChange)
++ #define default_param_timeout_cal_hs -1 //(NoChange)
++ #define default_param_timeout_cal_fs -1 //(NoChange)
++
++ #define default_param_data_fifo_size -1 //(Max, hwcfg)
++ #ifdef __IS_HOST__
++ #define default_param_host_channels -1 //(Max, hwcfg)
++ #define default_param_rx_fifo_size 640
++ #define default_param_nperio_tx_fifo_size 640
++ #define default_param_perio_tx_fifo_size 768
++ #endif //__IS_HOST__
++
++ #ifdef __IS_DEVICE__
++ #ifdef __DED_INTR__
++ #define default_param_rx_fifo_size 1024
++ #define default_param_nperio_tx_fifo_size 1016
++ #define default_param_perio_tx_fifo_size_01 8
++ #else
++ #define default_param_rx_fifo_size 1024
++ #define default_param_nperio_tx_fifo_size 1024
++ #define default_param_perio_tx_fifo_size_01 0
++ #endif
++ #define default_param_perio_tx_fifo_size_02 0
++ #define default_param_perio_tx_fifo_size_03 0
++ #define default_param_perio_tx_fifo_size_04 0
++ #define default_param_perio_tx_fifo_size_05 0
++ #define default_param_perio_tx_fifo_size_06 0
++ #define default_param_perio_tx_fifo_size_07 0
++ #define default_param_perio_tx_fifo_size_08 0
++ #define default_param_perio_tx_fifo_size_09 0
++ #define default_param_perio_tx_fifo_size_10 0
++ #define default_param_perio_tx_fifo_size_11 0
++ #define default_param_perio_tx_fifo_size_12 0
++ #define default_param_perio_tx_fifo_size_13 0
++ #define default_param_perio_tx_fifo_size_14 0
++ #define default_param_perio_tx_fifo_size_15 0
++ #endif //__IS_DEVICE__
++
++ #elif defined(__IS_AMAZON_SE__)
++ #include <asm/amazon_se/amazon_se.h>
++ //#include <asm/amazon_se/irq.h>
++
++// #define IFXUSB_IRQ 31
++ #define IFXUSB_IOMEM_BASE 0x1e101000
++ #define IFXUSB_FIFOMEM_BASE 0x1e120000
++ #define IFXUSB_FIFODBG_BASE 0x1e140000
++// #define IFXUSB_OC_IRQ 20
++
++ #define AMAZON_SE_RCU_USBCFG ((volatile unsigned long *)(AMAZON_SE_RCU_BASE_ADDR + 0x18))
++ #define AMAZON_SE_RCU_RESET ((volatile unsigned long *)(AMAZON_SE_RCU_BASE_ADDR + 0x10))
++ #define AMAZON_SE_USBCFG_HDSEL_BIT 11 // 0:host, 1:device
++ #define AMAZON_SE_USBCFG_HOST_END_BIT 10 // 0:little_end, 1:big_end
++ #define AMAZON_SE_USBCFG_SLV_END_BIT 9 // 0:little_end, 1:big_end
++
++ #ifndef AMAZON_SE_GPIO_P0_OUT
++ #define AMAZON_SE_GPIO_P0_OUT (0xBF103000+0x10)
++ #define AMAZON_SE_GPIO_P0_DIR (0xBF103000+0x18)
++ #define AMAZON_SE_GPIO_P0_ALTSEL0 (0xBF103000+0x1C)
++ #define AMAZON_SE_GPIO_P0_ALTSEL1 (0xBF103000+0x20)
++ #define AMAZON_SE_GPIO_P0_OD (0xBF103000+0x24)
++ #define AMAZON_SE_GPIO_P0_PUDSEL (0xBF103000+0x2C)
++ #define AMAZON_SE_GPIO_P0_PUDEN (0xBF103000+0x30)
++ #define AMAZON_SE_GPIO_P1_OUT (0xBF103000+0x40)
++ #define AMAZON_SE_GPIO_P1_DIR (0xBF103000+0x48)
++ #define AMAZON_SE_GPIO_P1_ALTSEL0 (0xBF103000+0x4C)
++ #define AMAZON_SE_GPIO_P1_ALTSEL1 (0xBF103000+0x50)
++ #define AMAZON_SE_GPIO_P1_OD (0xBF103000+0x54)
++ #define AMAZON_SE_GPIO_P1_PUDSEL (0xBF103000+0x5C)
++ #define AMAZON_SE_GPIO_P1_PUDEN (0xBF103000+0x60)
++ #endif
++
++
++ #ifndef AMAZON_SE_CGU
++ #define AMAZON_SE_CGU (0xBF103000)
++ #endif
++ #ifndef AMAZON_SE_CGU_IFCCR
++ #define AMAZON_SE_CGU_IFCCR ((volatile unsigned long *)(AMAZON_SE_CGU+ 0x0018))
++ #endif
++ #ifndef AMAZON_SE_PMU
++ #define AMAZON_SE_PMU (KSEG1+0x1F102000)
++ #endif
++ #ifndef AMAZON_SE_PMU_PWDCR
++ #define AMAZON_SE_PMU_PWDCR ((volatile unsigned long *)(AMAZON_SE_PMU+0x001C))
++ #endif
++
++ #define default_param_dma_burst_size 4
++
++ #define default_param_speed IFXUSB_PARAM_SPEED_HIGH
++
++ #define default_param_max_transfer_size -1 //(Max, hwcfg)
++ #define default_param_max_packet_count -1 //(Max, hwcfg)
++ #define default_param_phy_utmi_width 16
++
++ #define default_param_turn_around_time_hs 4 //(NoChange)
++ #define default_param_turn_around_time_fs 4 //(NoChange)
++ #define default_param_timeout_cal_hs -1 //(NoChange)
++ #define default_param_timeout_cal_fs -1 //(NoChange)
++
++ #define default_param_data_fifo_size -1 //(Max, hwcfg)
++
++ #ifdef __IS_HOST__
++ #define default_param_host_channels -1 //(Max, hwcfg)
++ #define default_param_rx_fifo_size 240
++ #define default_param_nperio_tx_fifo_size 240
++ #define default_param_perio_tx_fifo_size 32
++ #endif //__IS_HOST__
++ #ifdef __IS_DEVICE__
++ #ifdef __DED_INTR__
++ #define default_param_rx_fifo_size 256
++ #define default_param_nperio_tx_fifo_size 248
++ #define default_param_perio_tx_fifo_size_01 8
++ #else
++ #define default_param_rx_fifo_size 256
++ #define default_param_nperio_tx_fifo_size 256
++ #define default_param_perio_tx_fifo_size_01 0
++ #endif
++ #define default_param_perio_tx_fifo_size_02 0
++ #define default_param_perio_tx_fifo_size_03 0
++ #define default_param_perio_tx_fifo_size_04 0
++ #define default_param_perio_tx_fifo_size_05 0
++ #define default_param_perio_tx_fifo_size_06 0
++ #define default_param_perio_tx_fifo_size_07 0
++ #define default_param_perio_tx_fifo_size_08 0
++ #define default_param_perio_tx_fifo_size_09 0
++ #define default_param_perio_tx_fifo_size_10 0
++ #define default_param_perio_tx_fifo_size_11 0
++ #define default_param_perio_tx_fifo_size_12 0
++ #define default_param_perio_tx_fifo_size_13 0
++ #define default_param_perio_tx_fifo_size_14 0
++ #define default_param_perio_tx_fifo_size_15 0
++ #endif //__IS_DEVICE__
++
++ #elif defined(__IS_AR9__)
++// #define IFXUSB1_IRQ 54
++ #define IFXUSB1_IOMEM_BASE 0x1E101000
++ #define IFXUSB1_FIFOMEM_BASE 0x1E120000
++ #define IFXUSB1_FIFODBG_BASE 0x1E140000
++
++// #define IFXUSB2_IRQ 83
++ #define IFXUSB2_IOMEM_BASE 0x1E106000
++ #define IFXUSB2_FIFOMEM_BASE 0x1E1E0000
++ #define IFXUSB2_FIFODBG_BASE 0x1E1C0000
++
++// #define IFXUSB_OC_IRQ 60
++
++ #ifndef AMAZON_S_RCU_BASE_ADDR
++ #define AMAZON_S_RCU_BASE_ADDR (0xBF203000)
++ #endif
++
++ #ifndef AMAZON_S_CGU
++ #define AMAZON_S_CGU (0xBF103000)
++ #endif
++ #ifndef AMAZON_S_CGU_IFCCR
++ #define AMAZON_S_CGU_IFCCR ((volatile unsigned long *)(AMAZON_S_CGU+ 0x0018))
++ #endif
++
++ #ifndef AMAZON_S_PMU
++ #define AMAZON_S_PMU (KSEG1+0x1F102000)
++ #endif
++ #ifndef AMAZON_S_PMU_PWDCR
++ #define AMAZON_S_PMU_PWDCR ((volatile unsigned long *)(AMAZON_S_PMU+0x001C))
++ #endif
++
++ #ifndef AMAZON_S_GPIO_P0_OUT
++ #define AMAZON_S_GPIO_P0_OUT (0xBF103000+0x10)
++ #define AMAZON_S_GPIO_P0_DIR (0xBF103000+0x18)
++ #define AMAZON_S_GPIO_P0_ALTSEL0 (0xBF103000+0x1C)
++ #define AMAZON_S_GPIO_P0_ALTSEL1 (0xBF103000+0x20)
++ #define AMAZON_S_GPIO_P0_OD (0xBF103000+0x24)
++ #define AMAZON_S_GPIO_P0_PUDSEL (0xBF103000+0x2C)
++ #define AMAZON_S_GPIO_P0_PUDEN (0xBF103000+0x30)
++ #define AMAZON_S_GPIO_P1_OUT (0xBF103000+0x40)
++ #define AMAZON_S_GPIO_P1_DIR (0xBF103000+0x48)
++ #define AMAZON_S_GPIO_P1_ALTSEL0 (0xBF103000+0x4C)
++ #define AMAZON_S_GPIO_P1_ALTSEL1 (0xBF103000+0x50)
++ #define AMAZON_S_GPIO_P1_OD (0xBF103000+0x54)
++ #define AMAZON_S_GPIO_P1_PUDSEL (0xBF103000+0x5C)
++ #define AMAZON_S_GPIO_P1_PUDEN (0xBF103000+0x60)
++ #endif
++
++ #define AMAZON_S_RCU_USB1CFG ((volatile unsigned long *)(AMAZON_S_RCU_BASE_ADDR + 0x18))
++ #define AMAZON_S_RCU_USB2CFG ((volatile unsigned long *)(AMAZON_S_RCU_BASE_ADDR + 0x34))
++ #define AMAZON_S_RCU_USBRESET ((volatile unsigned long *)(AMAZON_S_RCU_BASE_ADDR + 0x10))
++ #define AMAZON_S_USBCFG_ARB 7 //
++ #define AMAZON_S_USBCFG_HDSEL_BIT 11 // 0:host, 1:device
++ #define AMAZON_S_USBCFG_HOST_END_BIT 10 // 0:little_end, 1:big_end
++ #define AMAZON_S_USBCFG_SLV_END_BIT 17 // 0:little_end, 1:big_end
++
++ #define default_param_dma_burst_size 4
++
++ #define default_param_speed IFXUSB_PARAM_SPEED_HIGH
++
++ #define default_param_max_transfer_size -1 //(Max, hwcfg)
++ #define default_param_max_packet_count -1 //(Max, hwcfg)
++ #define default_param_phy_utmi_width 16
++
++ #define default_param_turn_around_time_hs 4 //(NoChange)
++ #define default_param_turn_around_time_fs 4 //(NoChange)
++ #define default_param_timeout_cal_hs -1 //(NoChange)
++ #define default_param_timeout_cal_fs -1 //(NoChange)
++
++ #define default_param_data_fifo_size -1 //(Max, hwcfg)
++
++ #ifdef __IS_HOST__
++ #define default_param_host_channels -1 //(Max, hwcfg)
++ #define default_param_rx_fifo_size 240
++ #define default_param_nperio_tx_fifo_size 240
++ #define default_param_perio_tx_fifo_size 32
++ #endif //__IS_HOST__
++ #ifdef __IS_DEVICE__
++ #ifdef __DED_INTR__
++ #define default_param_rx_fifo_size 256
++ #define default_param_nperio_tx_fifo_size 248
++ #define default_param_perio_tx_fifo_size_01 8
++ #else
++ #define default_param_rx_fifo_size 256
++ #define default_param_nperio_tx_fifo_size 256
++ #define default_param_perio_tx_fifo_size_01 0
++ #endif
++ #define default_param_perio_tx_fifo_size_02 0
++ #define default_param_perio_tx_fifo_size_03 0
++ #define default_param_perio_tx_fifo_size_04 0
++ #define default_param_perio_tx_fifo_size_05 0
++ #define default_param_perio_tx_fifo_size_06 0
++ #define default_param_perio_tx_fifo_size_07 0
++ #define default_param_perio_tx_fifo_size_08 0
++ #define default_param_perio_tx_fifo_size_09 0
++ #define default_param_perio_tx_fifo_size_10 0
++ #define default_param_perio_tx_fifo_size_11 0
++ #define default_param_perio_tx_fifo_size_12 0
++ #define default_param_perio_tx_fifo_size_13 0
++ #define default_param_perio_tx_fifo_size_14 0
++ #define default_param_perio_tx_fifo_size_15 0
++ #endif //__IS_DEVICE__
++
++ #elif defined(__IS_VR9__)
++// #define IFXUSB1_IRQ 54
++ #define IFXUSB1_IOMEM_BASE 0x1E101000
++ #define IFXUSB1_FIFOMEM_BASE 0x1E120000
++ #define IFXUSB1_FIFODBG_BASE 0x1E140000
++
++// #define IFXUSB2_IRQ 83
++ #define IFXUSB2_IOMEM_BASE 0x1E106000
++ #define IFXUSB2_FIFOMEM_BASE 0x1E1E0000
++ #define IFXUSB2_FIFODBG_BASE 0x1E1C0000
++// #define IFXUSB_OC_IRQ 60
++
++ #ifndef AMAZON_S_RCU_BASE_ADDR
++ #define AMAZON_S_RCU_BASE_ADDR (0xBF203000)
++ #endif
++
++ #ifndef AMAZON_S_CGU
++ #define AMAZON_S_CGU (0xBF103000)
++ #endif
++ #ifndef AMAZON_S_CGU_IFCCR
++ #define AMAZON_S_CGU_IFCCR ((volatile unsigned long *)(AMAZON_S_CGU+ 0x0018))
++ #endif
++
++ #ifndef AMAZON_S_PMU
++ #define AMAZON_S_PMU (KSEG1+0x1F102000)
++ #endif
++ #ifndef AMAZON_S_PMU_PWDCR
++ #define AMAZON_S_PMU_PWDCR ((volatile unsigned long *)(AMAZON_S_PMU+0x001C))
++ #endif
++
++ #ifndef AMAZON_S_GPIO_P0_OUT
++ #define AMAZON_S_GPIO_P0_OUT (0xBF103000+0x10)
++ #define AMAZON_S_GPIO_P0_DIR (0xBF103000+0x18)
++ #define AMAZON_S_GPIO_P0_ALTSEL0 (0xBF103000+0x1C)
++ #define AMAZON_S_GPIO_P0_ALTSEL1 (0xBF103000+0x20)
++ #define AMAZON_S_GPIO_P0_OD (0xBF103000+0x24)
++ #define AMAZON_S_GPIO_P0_PUDSEL (0xBF103000+0x2C)
++ #define AMAZON_S_GPIO_P0_PUDEN (0xBF103000+0x30)
++ #define AMAZON_S_GPIO_P1_OUT (0xBF103000+0x40)
++ #define AMAZON_S_GPIO_P1_DIR (0xBF103000+0x48)
++ #define AMAZON_S_GPIO_P1_ALTSEL0 (0xBF103000+0x4C)
++ #define AMAZON_S_GPIO_P1_ALTSEL1 (0xBF103000+0x50)
++ #define AMAZON_S_GPIO_P1_OD (0xBF103000+0x54)
++ #define AMAZON_S_GPIO_P1_PUDSEL (0xBF103000+0x5C)
++ #define AMAZON_S_GPIO_P1_PUDEN (0xBF103000+0x60)
++ #endif
++
++ #define AMAZON_S_RCU_USB1CFG ((volatile unsigned long *)(AMAZON_S_RCU_BASE_ADDR + 0x18))
++ #define AMAZON_S_RCU_USB2CFG ((volatile unsigned long *)(AMAZON_S_RCU_BASE_ADDR + 0x34))
++ #define AMAZON_S_RCU_USBRESET ((volatile unsigned long *)(AMAZON_S_RCU_BASE_ADDR + 0x10))
++ #define AMAZON_S_USBCFG_ARB 7 //
++ #define AMAZON_S_USBCFG_HDSEL_BIT 11 // 0:host, 1:device
++ #define AMAZON_S_USBCFG_HOST_END_BIT 10 // 0:little_end, 1:big_end
++ #define AMAZON_S_USBCFG_SLV_END_BIT 17 // 0:little_end, 1:big_end
++
++ #define default_param_dma_burst_size 4 //(ALL)
++
++ #define default_param_speed IFXUSB_PARAM_SPEED_HIGH
++
++ #define default_param_max_transfer_size -1 //(Max, hwcfg)
++ #define default_param_max_packet_count -1 //(Max, hwcfg)
++ #define default_param_phy_utmi_width 16
++
++ #define default_param_turn_around_time_hs 6 //(NoChange) snpsid >= 0x4f54260a
++ #define default_param_turn_around_time_fs 6 //(NoChange) snpsid >= 0x4f54260a
++ #define default_param_timeout_cal_hs -1 //(NoChange)
++ #define default_param_timeout_cal_fs -1 //(NoChange)
++
++ #define default_param_data_fifo_size -1 //(Max, hwcfg)
++
++ #ifdef __IS_HOST__
++ #define default_param_host_channels -1 //(Max, hwcfg)
++ #define default_param_rx_fifo_size 240
++ #define default_param_nperio_tx_fifo_size 240
++ #define default_param_perio_tx_fifo_size 32
++ #endif //__IS_HOST__
++ #ifdef __IS_DEVICE__
++ #define default_param_rx_fifo_size 256
++ #define default_param_tx_fifo_size_00 -1
++ #define default_param_tx_fifo_size_01 -1
++ #define default_param_tx_fifo_size_02 -1
++ #define default_param_tx_fifo_size_03 -1
++ #define default_param_tx_fifo_size_04 -1
++ #define default_param_tx_fifo_size_05 -1
++ #define default_param_tx_fifo_size_06 -1
++ #define default_param_tx_fifo_size_07 -1
++ #define default_param_tx_fifo_size_08 -1
++ #define default_param_tx_fifo_size_09 -1
++ #define default_param_tx_fifo_size_10 -1
++ #define default_param_tx_fifo_size_11 -1
++ #define default_param_tx_fifo_size_12 -1
++ #define default_param_tx_fifo_size_13 -1
++ #define default_param_tx_fifo_size_14 -1
++ #define default_param_tx_fifo_size_15 -1
++ #define default_param_dma_unalgned_tx -1
++ #define default_param_dma_unalgned_rx -1
++ #define default_param_thr_ctl -1
++ #define default_param_tx_thr_length -1
++ #define default_param_rx_thr_length -1
++ #endif //__IS_DEVICE__
++ #else // __IS_VR9__
++ #error "Please choose one platform!!"
++ #endif // __IS_VR9__
++#endif //UEIP
++
++/*@}*//*IFXUSB_PLATEFORM_MEM_ADDR*/
++
++/////////////////////////////////////////////////////////////////////////
++
++#ifdef __IS_HOST__
++ #ifdef CONFIG_USB_HOST_IFX_FORCE_USB11
++ #undef default_param_speed
++ #define default_param_speed IFXUSB_PARAM_SPEED_FULL
++ #endif
++#endif
++#ifdef __IS_DEVICE__
++ #ifndef CONFIG_USB_GADGET_DUALSPEED
++ #undef default_param_speed
++ #define default_param_speed IFXUSB_PARAM_SPEED_FULL
++ #endif
++#endif
++
++/////////////////////////////////////////////////////////////////////////
++
++static __inline__ void UDELAY( const uint32_t _usecs )
++{
++ udelay( _usecs );
++}
++
++static __inline__ void MDELAY( const uint32_t _msecs )
++{
++ mdelay( _msecs );
++}
++
++static __inline__ void SPIN_LOCK( spinlock_t *_lock )
++{
++ spin_lock(_lock);
++}
++
++static __inline__ void SPIN_UNLOCK( spinlock_t *_lock )
++{
++ spin_unlock(_lock);
++}
++
++#define SPIN_LOCK_IRQSAVE( _l, _f ) \
++ { \
++ spin_lock_irqsave(_l,_f); \
++ }
++
++#define SPIN_UNLOCK_IRQRESTORE( _l,_f ) \
++ { \
++ spin_unlock_irqrestore(_l,_f); \
++ }
++
++/////////////////////////////////////////////////////////////////////////
++/*!
++ \addtogroup IFXUSB_DBG_ROUTINE
++ */
++/*@{*/
++#ifdef __IS_HOST__
++ extern uint32_t h_dbg_lvl;
++#endif
++
++#ifdef __IS_DEVICE__
++ extern uint32_t d_dbg_lvl;
++#endif
++
++/*! \brief When debug level has the DBG_CIL bit set, display CIL Debug messages. */
++#define DBG_CIL (0x2)
++/*! \brief When debug level has the DBG_CILV bit set, display CIL Verbose debug messages */
++#define DBG_CILV (0x20)
++/*! \brief When debug level has the DBG_PCD bit set, display PCD (Device) debug messages */
++#define DBG_PCD (0x4)
++/*! \brief When debug level has the DBG_PCDV set, display PCD (Device) Verbose debug messages */
++#define DBG_PCDV (0x40)
++/*! \brief When debug level has the DBG_HCD bit set, display Host debug messages */
++#define DBG_HCD (0x8)
++/*! \brief When debug level has the DBG_HCDV bit set, display Verbose Host debug messages */
++#define DBG_HCDV (0x80)
++/*! \brief When debug level has the DBG_HCD_URB bit set, display enqueued URBs in host mode. */
++#define DBG_HCD_URB (0x800)
++/*! \brief When debug level has any bit set, display debug messages */
++#define DBG_ANY (0xFF)
++/*! \brief All debug messages off */
++#define DBG_OFF 0
++
++#define DBG_ENTRY (0x8000)
++
++#define IFXUSB "IFXUSB: "
++
++/*!
++ \fn inline uint32_t SET_DEBUG_LEVEL( const uint32_t _new )
++ \brief Set the Debug Level variable.
++ \param _new 32-bit mask of debug level.
++ \return previous debug level
++ */
++static inline uint32_t SET_DEBUG_LEVEL( const uint32_t _new )
++{
++ #ifdef __IS_HOST__
++ uint32_t old = h_dbg_lvl;
++ h_dbg_lvl = _new;
++ #endif
++
++ #ifdef __IS_DEVICE__
++ uint32_t old = d_dbg_lvl;
++ d_dbg_lvl = _new;
++ #endif
++ return old;
++}
++
++#ifdef __DEBUG__
++ #ifdef __IS_HOST__
++ # define IFX_DEBUGPL(lvl, x...) do{ if ((lvl)&h_dbg_lvl)printk( KERN_DEBUG IFXUSB x ); }while(0)
++ # define CHK_DEBUG_LEVEL(level) ((level) & h_dbg_lvl)
++ #endif
++
++ #ifdef __IS_DEVICE__
++ # define IFX_DEBUGPL(lvl, x...) do{ if ((lvl)&d_dbg_lvl)printk( KERN_DEBUG IFXUSB x ); }while(0)
++ # define CHK_DEBUG_LEVEL(level) ((level) & d_dbg_lvl)
++ #endif
++
++ # define IFX_DEBUGP(x...) IFX_DEBUGPL(DBG_ANY, x )
++#else
++ # define IFX_DEBUGPL(lvl, x...) do{}while(0)
++ # define IFX_DEBUGP(x...)
++ # define CHK_DEBUG_LEVEL(level) (0)
++#endif //__DEBUG__
++
++/* Print an Error message. */
++#define IFX_ERROR(x...) printk( KERN_ERR IFXUSB x )
++/* Print a Warning message. */
++#define IFX_WARN(x...) printk( KERN_WARNING IFXUSB x )
++/* Print a notice (normal but significant message). */
++#define IFX_NOTICE(x...) printk( KERN_NOTICE IFXUSB x )
++/* Basic message printing. */
++#define IFX_PRINT(x...) printk( KERN_INFO IFXUSB x )
++
++/*@}*//*IFXUSB_DBG_ROUTINE*/
++
++
++#endif //__IFXUSB_PLAT_H__
++
+diff --git a/drivers/usb/ifxhcd/ifxusb_regs.h b/drivers/usb/ifxhcd/ifxusb_regs.h
+new file mode 100644
+index 0000000..014c6db
+--- /dev/null
++++ b/drivers/usb/ifxhcd/ifxusb_regs.h
+@@ -0,0 +1,1420 @@
++/*****************************************************************************
++ ** FILE NAME : ifxusb_regs.h
++ ** PROJECT : IFX USB sub-system V3
++ ** MODULES : IFX USB sub-system Host and Device driver
++ ** SRC VERSION : 1.0
++ ** DATE : 1/Jan/2009
++ ** AUTHOR : Chen, Howard
++ ** DESCRIPTION : This file contains the data structures for accessing the IFXUSB core
++ ** registers.
++ ** The application interfaces with the USB core by reading from and
++ ** writing to the Control and Status Register (CSR) space through the
++ ** AHB Slave interface. These registers are 32 bits wide, and the
++ ** addresses are 32-bit-block aligned.
++ ** CSRs are classified as follows:
++ ** - Core Global Registers
++ ** - Device Mode Registers
++ ** - Device Global Registers
++ ** - Device Endpoint Specific Registers
++ ** - Host Mode Registers
++ ** - Host Global Registers
++ ** - Host Port CSRs
++ ** - Host Channel Specific Registers
++ **
++ ** Only the Core Global registers can be accessed in both Device and
++ ** Host modes. When the USB core is operating in one mode, either
++ ** Device or Host, the application must not access registers from the
++ ** other mode. When the core switches from one mode to another, the
++ ** registers in the new mode of operation must be reprogrammed as they
++ ** would be after a power-on reset.
++ ** FUNCTIONS :
++ ** COMPILER : gcc
++ ** REFERENCE : Synopsys DWC-OTG Driver 2.7
++ ** COPYRIGHT :
++ ** Version Control Section **
++ ** $Author$
++ ** $Date$
++ ** $Revisions$
++ ** $Log$ Revision history
++*****************************************************************************/
++
++
++
++/*!
++ \defgroup IFXUSB_CSR_DEFINITION Control and Status Register bit-map definition
++ \ingroup IFXUSB_DRIVER_V3
++ \brief Data structures for accessing the IFXUSB core registers.
++ The application interfaces with the USB core by reading from and
++ writing to the Control and Status Register (CSR) space through the
++ AHB Slave interface. These registers are 32 bits wide, and the
++ addresses are 32-bit-block aligned.
++ CSRs are classified as follows:
++ - Core Global Registers
++ - Device Mode Registers
++ - Device Global Registers
++ - Device Endpoint Specific Registers
++ - Host Mode Registers
++ - Host Global Registers
++ - Host Port CSRs
++ - Host Channel Specific Registers
++
++ Only the Core Global registers can be accessed in both Device andHost modes.
++ When the USB core is operating in one mode, either Device or Host, the
++ application must not access registers from the other mode. When the core
++ switches from one mode to another, the registers in the new mode of operation
++ must be reprogrammed as they would be after a power-on reset.
++ */
++
++/*!
++ \defgroup IFXUSB_CSR_DEVICE_GLOBAL_REG Device Mode Registers
++ \ingroup IFXUSB_CSR_DEFINITION
++ \brief Bit-mapped structure to access Device Mode Global Registers
++ */
++
++/*!
++ \defgroup IFXUSB_CSR_DEVICE_EP_REG Device Mode EP Registers
++ \ingroup IFXUSB_CSR_DEFINITION
++ \brief Bit-mapped structure to access Device Mode EP Registers
++ There will be one set of endpoint registers per logical endpoint
++ implemented.
++ These registers are visible only in Device mode and must not be
++ accessed in Host mode, as the results are unknown.
++ */
++
++/*!
++ \defgroup IFXUSB_CSR_DEVICE_DMA_DESC Device mode scatter dma descriptor strusture
++ \ingroup IFXUSB_CSR_DEFINITION
++ \brief Bit-mapped structure to DMA descriptor
++ */
++
++
++/*!
++ \defgroup IFXUSB_CSR_HOST_GLOBAL_REG Host Mode Registers
++ \ingroup IFXUSB_CSR_DEFINITION
++ \brief Bit-mapped structure to access Host Mode Global Registers
++ */
++
++/*!
++ \defgroup IFXUSB_CSR_HOST_HC_REG Host Mode HC Registers
++ \ingroup IFXUSB_CSR_DEFINITION
++ \brief Bit-mapped structure to access Host Mode Host Channel Registers
++ There will be one set of endpoint registers per host channel
++ implemented.
++ These registers are visible only in Host mode and must not be
++ accessed in Device mode, as the results are unknown.
++ */
++
++/*!
++ \defgroup IFXUSB_CSR_PWR_CLK_GATING_REG Power and Clock Gating Control Register
++ \ingroup IFXUSB_CSR_DEFINITION
++ \brief Bit-mapped structure to Power and Clock Gating Control Register
++ */
++
++
++
++
++
++
++
++
++/*!
++ \defgroup IFXUSB_CSR_CORE_GLOBAL_REG Core Global Registers
++ \ingroup IFXUSB_CSR_DEFINITION
++ \brief Bit-mapped structure to access Core Global Registers
++ */
++/*!
++ \defgroup IFXUSB_CSR_CORE_GLOBAL_REG Core Global Registers
++ \ingroup IFXUSB_CSR_DEFINITION
++ \brief Bit-mapped structure to access Core Global Registers
++ */
++
++
++
++
++
++
++
++
++
++/*!
++ \file ifxusb_regs.h
++ \ingroup IFXUSB_DRIVER_V3
++ \brief This file contains the data structures for accessing the IFXUSB core registers.
++ */
++
++
++#ifndef __IFXUSB_REGS_H__
++#define __IFXUSB_REGS_H__
++
++/****************************************************************************/
++
++#define MAX_PERIO_FIFOS 15 /** Maximum number of Periodic FIFOs */
++#define MAX_TX_FIFOS 15 /** Maximum number of Periodic FIFOs */
++#define MAX_EPS_CHANNELS 16 /** Maximum number of Endpoints/HostChannels */
++
++/****************************************************************************/
++
++/*!
++ \addtogroup IFXUSB_CSR_ACCESS_MACROS
++ */
++/*@{*/
++
++//#define RecordRegRW
++
++/*!
++ \fn static __inline__ uint32_t ifxusb_rreg( volatile uint32_t *_reg)
++ \brief Reads the content of a register.
++ \param _reg address of register to read.
++ \return contents of the register.
++ */
++static __inline__ uint32_t ifxusb_rreg( volatile uint32_t *_reg)
++{
++ #ifdef RecordRegRW
++ uint32_t r;
++ r=*(_reg);
++ return (r);
++ #else
++ return (*(_reg));
++ #endif
++};
++
++
++/*!
++ \fn static __inline__ void ifxusb_wreg( volatile uint32_t *_reg, const uint32_t _value)
++ \brief Writes a register with a 32 bit value.
++ \param _reg address of register to write.
++ \param _value value to write to _reg.
++ */
++static __inline__ void ifxusb_wreg( volatile uint32_t *_reg, const uint32_t _value)
++{
++ #ifdef RecordRegRW
++ printk(KERN_INFO "[W %p<-%08X]\n",_reg,_value);
++ #else
++ *(_reg)=_value;
++ #endif
++};
++
++/*!
++ \fn static __inline__ void ifxusb_mreg( volatile uint32_t *_reg, const uint32_t _clear_mask, const uint32_t _set_mask)
++ \brief Modifies bit values in a register. Using the
++ algorithm: (reg_contents & ~clear_mask) | set_mask.
++ \param _reg address of register to modify.
++ \param _clear_mask bit mask to be cleared.
++ \param _set_mask bit mask to be set.
++ */
++static __inline__ void ifxusb_mreg( volatile uint32_t *_reg, const uint32_t _clear_mask, const uint32_t _set_mask)
++{
++ uint32_t v;
++ #ifdef RecordRegRW
++ uint32_t r;
++ v= *(_reg);
++ r=v;
++ r&=(~_clear_mask);
++ r|= _set_mask;
++ *(_reg)=r ;
++ printk(KERN_INFO "[M %p->%08X+%08X/%08X<-%08X]\n",_reg,r,_clear_mask,_set_mask,r);
++ #else
++ v= *(_reg);
++ v&=(~_clear_mask);
++ v|= _set_mask;
++ *(_reg)=v ;
++ #endif
++};
++
++/*@}*//*IFXUSB_CSR_ACCESS_MACROS*/
++/****************************************************************************/
++
++/*!
++ \addtogroup IFXUSB_CSR_CORE_GLOBAL_REG
++ */
++/*@{*/
++
++/*!
++ \struct ifxusb_core_global_regs
++ \brief IFXUSB Core registers .
++ The ifxusb_core_global_regs structure defines the size
++ and relative field offsets for the Core Global registers.
++ */
++typedef struct ifxusb_core_global_regs
++{
++ volatile uint32_t gotgctl; /*!< 000h OTG Control and Status Register. */
++ volatile uint32_t gotgint; /*!< 004h OTG Interrupt Register. */
++ volatile uint32_t gahbcfg; /*!< 008h Core AHB Configuration Register. */
++ volatile uint32_t gusbcfg; /*!< 00Ch Core USB Configuration Register. */
++ volatile uint32_t grstctl; /*!< 010h Core Reset Register. */
++ volatile uint32_t gintsts; /*!< 014h Core Interrupt Register. */
++ volatile uint32_t gintmsk; /*!< 018h Core Interrupt Mask Register. */
++ volatile uint32_t grxstsr; /*!< 01Ch Receive Status Queue Read Register (Read Only). */
++ volatile uint32_t grxstsp; /*!< 020h Receive Status Queue Read & POP Register (Read Only). */
++ volatile uint32_t grxfsiz; /*!< 024h Receive FIFO Size Register. */
++ volatile uint32_t gnptxfsiz; /*!< 028h Non Periodic Transmit FIFO Size Register. */
++ volatile uint32_t gnptxsts; /*!< 02Ch Non Periodic Transmit FIFO/Queue Status Register (Read Only). */
++ volatile uint32_t gi2cctl; /*!< 030h I2C Access Register. */
++ volatile uint32_t gpvndctl; /*!< 034h PHY Vendor Control Register. */
++ volatile uint32_t ggpio; /*!< 038h General Purpose Input/Output Register. */
++ volatile uint32_t guid; /*!< 03Ch User ID Register. */
++ volatile uint32_t gsnpsid; /*!< 040h Synopsys ID Register (Read Only). */
++ volatile uint32_t ghwcfg1; /*!< 044h User HW Config1 Register (Read Only). */
++ volatile uint32_t ghwcfg2; /*!< 048h User HW Config2 Register (Read Only). */
++ volatile uint32_t ghwcfg3; /*!< 04Ch User HW Config3 Register (Read Only). */
++ volatile uint32_t ghwcfg4; /*!< 050h User HW Config4 Register (Read Only). */
++ volatile uint32_t reserved[43]; /*!< 054h Reserved 054h-0FFh */
++ volatile uint32_t hptxfsiz; /*!< 100h Host Periodic Transmit FIFO Size Register. */
++ volatile uint32_t dptxfsiz_dieptxf[15];/*!< 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15.
++ Device Periodic Transmit FIFO#n Register if dedicated
++ fifos are disabled, otherwise Device Transmit FIFO#n
++ Register.
++ */
++} ifxusb_core_global_regs_t;
++
++/*!
++ \brief Bits of the Core OTG Control and Status Register (GOTGCTL).
++ */
++typedef union gotgctl_data
++{
++ uint32_t d32;
++ struct{
++ unsigned reserved21_31 : 11;
++ unsigned currmod : 1 ; /*!< 20 */
++ unsigned bsesvld : 1 ; /*!< 19 */
++ unsigned asesvld : 1 ; /*!< 18 */
++ unsigned reserved17 : 1 ;
++ unsigned conidsts : 1 ; /*!< 16 */
++ unsigned reserved12_15 : 4 ;
++ unsigned devhnpen : 1 ; /*!< 11 */
++ unsigned hstsethnpen : 1 ; /*!< 10 */
++ unsigned hnpreq : 1 ; /*!< 09 */
++ unsigned hstnegscs : 1 ; /*!< 08 */
++ unsigned reserved2_7 : 6 ;
++ unsigned sesreq : 1 ; /*!< 01 */
++ unsigned sesreqscs : 1 ; /*!< 00 */
++ } b;
++} gotgctl_data_t;
++
++/*!
++ \brief Bit fields of the Core OTG Interrupt Register (GOTGINT).
++ */
++typedef union gotgint_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved31_20 : 12;
++ unsigned debdone : 1 ; /*!< 19 Debounce Done */
++ unsigned adevtoutchng : 1 ; /*!< 18 A-Device Timeout Change */
++ unsigned hstnegdet : 1 ; /*!< 17 Host Negotiation Detected */
++ unsigned reserver10_16 : 7 ;
++ unsigned hstnegsucstschng : 1 ; /*!< 09 Host Negotiation Success Status Change */
++ unsigned sesreqsucstschng : 1 ; /*!< 08 Session Request Success Status Change */
++ unsigned reserved3_7 : 5 ;
++ unsigned sesenddet : 1 ; /*!< 02 Session End Detected */
++ unsigned reserved0_1 : 2 ;
++ } b;
++} gotgint_data_t;
++
++/*!
++ \brief Bit fields of the Core AHB Configuration Register (GAHBCFG).
++ */
++typedef union gahbcfg_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved9_31 : 23;
++ unsigned ptxfemplvl : 1 ; /*!< 08 Periodic FIFO empty level trigger condition*/
++ unsigned nptxfemplvl : 1 ; /*!< 07 Non-Periodic FIFO empty level trigger condition*/
++ #define IFXUSB_GAHBCFG_TXFEMPTYLVL_EMPTY 1
++ #define IFXUSB_GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0
++ unsigned reserved : 1 ;
++ unsigned dmaenable : 1 ; /*!< 05 DMA enable*/
++ #define IFXUSB_GAHBCFG_DMAENABLE 1
++ unsigned hburstlen : 4 ; /*!< 01-04 DMA Burst-length*/
++ #define IFXUSB_GAHBCFG_INT_DMA_BURST_SINGLE 0
++ #define IFXUSB_GAHBCFG_INT_DMA_BURST_INCR 1
++ #define IFXUSB_GAHBCFG_INT_DMA_BURST_INCR4 3
++ #define IFXUSB_GAHBCFG_INT_DMA_BURST_INCR8 5
++ #define IFXUSB_GAHBCFG_INT_DMA_BURST_INCR16 7
++ unsigned glblintrmsk : 1 ; /*!< 00 USB Global Interrupt Enable */
++ #define IFXUSB_GAHBCFG_GLBINT_ENABLE 1
++ } b;
++} gahbcfg_data_t;
++
++/*!
++ \brief Bit fields of the Core USB Configuration Register (GUSBCFG).
++*/
++typedef union gusbcfg_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved31 : 1;
++ unsigned ForceDevMode : 1; /*!< 30 Force Device Mode */
++ unsigned ForceHstMode : 1; /*!< 29 Force Host Mode */
++ unsigned TxEndDelay : 1; /*!< 28 Tx End Delay */
++ unsigned reserved2723 : 5;
++ unsigned term_sel_dl_pulse : 1; /*!< 22 TermSel DLine Pulsing Selection */
++ unsigned reserved2117 : 5;
++ unsigned otgutmifssel : 1; /*!< 16 UTMIFS Select */
++ unsigned phylpwrclksel : 1; /*!< 15 PHY Low-Power Clock Select */
++ unsigned reserved14 : 1;
++ unsigned usbtrdtim : 4; /*!< 13-10 USB Turnaround Time */
++ unsigned hnpcap : 1; /*!< 09 HNP-Capable */
++ unsigned srpcap : 1; /*!< 08 SRP-Capable */
++ unsigned reserved07 : 1;
++ unsigned physel : 1; /*!< 06 USB 2.0 High-Speed PHY or
++ USB 1.1 Full-Speed Serial
++ Transceiver Select */
++ unsigned fsintf : 1; /*!< 05 Full-Speed Serial Interface Select */
++ unsigned ulpi_utmi_sel : 1; /*!< 04 ULPI or UTMI+ Select */
++ unsigned phyif : 1; /*!< 03 PHY Interface */
++ unsigned toutcal : 3; /*!< 00-02 HS/FS Timeout Calibration */
++ }b;
++} gusbcfg_data_t;
++
++/*!
++ \brief Bit fields of the Core Reset Register (GRSTCTL).
++ */
++typedef union grstctl_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned ahbidle : 1; /*!< 31 AHB Master Idle. Indicates the AHB Master State
++ Machine is in IDLE condition. */
++ unsigned dmareq : 1; /*!< 30 DMA Request Signal. Indicated DMA request is in
++ probress. Used for debug purpose. */
++ unsigned reserved11_29 :19;
++ unsigned txfnum : 5; /*!< 10-06 TxFIFO Number (TxFNum) to be flushed.
++ 0x00: Non Periodic TxFIFO Flush or TxFIFO 0
++ 0x01-0x0F: Periodic TxFIFO Flush or TxFIFO n
++ 0x10: Flush all TxFIFO
++ */
++ unsigned txfflsh : 1; /*!< 05 TxFIFO Flush */
++ unsigned rxfflsh : 1; /*!< 04 RxFIFO Flush */
++ unsigned intknqflsh : 1; /*!< 03 In Token Sequence Learning Queue Flush (Device Only) */
++ unsigned hstfrm : 1; /*!< 02 Host Frame Counter Reset (Host Only) */
++ unsigned hsftrst : 1; /*!< 01 Hclk Soft Reset */
++
++ unsigned csftrst : 1; /*!< 00 Core Soft Reset
++ The application can flush the control logic in the
++ entire core using this bit. This bit resets the
++ pipelines in the AHB Clock domain as well as the
++ PHY Clock domain.
++ The state machines are reset to an IDLE state, the
++ control bits in the CSRs are cleared, all the
++ transmit FIFOs and the receive FIFO are flushed.
++ The status mask bits that control the generation of
++ the interrupt, are cleared, to clear the
++ interrupt. The interrupt status bits are not
++ cleared, so the application can get the status of
++ any events that occurred in the core after it has
++ set this bit.
++ Any transactions on the AHB are terminated as soon
++ as possible following the protocol. Any
++ transactions on the USB are terminated immediately.
++ The configuration settings in the CSRs are
++ unchanged, so the software doesn't have to
++ reprogram these registers (Device
++ Configuration/Host Configuration/Core System
++ Configuration/Core PHY Configuration).
++ The application can write to this bit, any time it
++ wants to reset the core. This is a self clearing
++ bit and the core clears this bit after all the
++ necessary logic is reset in the core, which may
++ take several clocks, depending on the current state
++ of the core.
++ */
++ }b;
++} grstctl_t;
++
++/*!
++ \brief Bit fields of the Core Interrupt Mask Register (GINTMSK) and
++ Core Interrupt Register (GINTSTS).
++ */
++typedef union gint_data
++{
++ uint32_t d32;
++ #define IFXUSB_SOF_INTR_MASK 0x0008
++ struct
++ {
++ unsigned wkupintr : 1; /*!< 31 Resume/Remote Wakeup Detected Interrupt */
++ unsigned sessreqintr : 1; /*!< 30 Session Request/New Session Detected Interrupt */
++ unsigned disconnect : 1; /*!< 29 Disconnect Detected Interrupt */
++ unsigned conidstschng : 1; /*!< 28 Connector ID Status Change */
++ unsigned reserved27 : 1;
++ unsigned ptxfempty : 1; /*!< 26 Periodic TxFIFO Empty */
++ unsigned hcintr : 1; /*!< 25 Host Channels Interrupt */
++ unsigned portintr : 1; /*!< 24 Host Port Interrupt */
++ unsigned reserved23 : 1;
++ unsigned fetsuspmsk : 1; /*!< 22 Data Fetch Suspended */
++ unsigned incomplisoout : 1; /*!< 21 Incomplete IsochronousOUT/Period Transfer */
++ unsigned incomplisoin : 1; /*!< 20 Incomplete Isochronous IN Transfer */
++ unsigned outepintr : 1; /*!< 19 OUT Endpoints Interrupt */
++ unsigned inepintr : 1; /*!< 18 IN Endpoints Interrupt */
++ unsigned epmismatch : 1; /*!< 17 Endpoint Mismatch Interrupt */
++ unsigned reserved16 : 1;
++ unsigned eopframe : 1; /*!< 15 End of Periodic Frame Interrupt */
++ unsigned isooutdrop : 1; /*!< 14 Isochronous OUT Packet Dropped Interrupt */
++ unsigned enumdone : 1; /*!< 13 Enumeration Done */
++ unsigned usbreset : 1; /*!< 12 USB Reset */
++ unsigned usbsuspend : 1; /*!< 11 USB Suspend */
++ unsigned erlysuspend : 1; /*!< 10 Early Suspend */
++ unsigned i2cintr : 1; /*!< 09 I2C Interrupt */
++ unsigned reserved8 : 1;
++ unsigned goutnakeff : 1; /*!< 07 Global OUT NAK Effective */
++ unsigned ginnakeff : 1; /*!< 06 Global Non-periodic IN NAK Effective */
++ unsigned nptxfempty : 1; /*!< 05 Non-periodic TxFIFO Empty */
++ unsigned rxstsqlvl : 1; /*!< 04 Receive FIFO Non-Empty */
++ unsigned sofintr : 1; /*!< 03 Start of (u)Frame */
++ unsigned otgintr : 1; /*!< 02 OTG Interrupt */
++ unsigned modemismatch : 1; /*!< 01 Mode Mismatch Interrupt */
++ unsigned reserved0 : 1;
++ } b;
++} gint_data_t;
++
++/*!
++ \brief Bit fields in the Receive Status Read and Pop Registers (GRXSTSR, GRXSTSP)
++ */
++typedef union grxsts_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved : 7;
++ unsigned fn : 4; /*!< 24-21 Frame Number */
++ unsigned pktsts : 4; /*!< 20-17 Packet Status */
++ #define IFXUSB_DSTS_DATA_UPDT 0x2 // OUT Data Packet
++ #define IFXUSB_DSTS_XFER_COMP 0x3 // OUT Data Transfer Complete
++ #define IFXUSB_DSTS_GOUT_NAK 0x1 // Global OUT NAK
++ #define IFXUSB_DSTS_SETUP_COMP 0x4 // Setup Phase Complete
++ #define IFXUSB_DSTS_SETUP_UPDT 0x6 // SETUP Packet
++ unsigned dpid : 2; /*!< 16-15 Data PID */
++ unsigned bcnt :11; /*!< 14-04 Byte Count */
++ unsigned epnum : 4; /*!< 03-00 Endpoint Number */
++ } db;
++ struct
++ {
++ unsigned reserved :11;
++ unsigned pktsts : 4; /*!< 20-17 Packet Status */
++ #define IFXUSB_HSTS_DATA_UPDT 0x2 // OUT Data Packet
++ #define IFXUSB_HSTS_XFER_COMP 0x3 // OUT Data Transfer Complete
++ #define IFXUSB_HSTS_DATA_TOGGLE_ERR 0x5 // DATA TOGGLE Error
++ #define IFXUSB_HSTS_CH_HALTED 0x7 // Channel Halted
++ unsigned dpid : 2; /*!< 16-15 Data PID */
++ unsigned bcnt :11; /*!< 14-04 Byte Count */
++ unsigned chnum : 4; /*!< 03-00 Channel Number */
++ } hb;
++} grxsts_data_t;
++
++/*!
++ \brief Bit fields in the FIFO Size Registers (HPTXFSIZ, GNPTXFSIZ, DPTXFSIZn).
++ */
++typedef union fifosize_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned depth : 16; /*!< 31-16 TxFIFO Depth (in DWord)*/
++ unsigned startaddr : 16; /*!< 15-00 RAM Starting address */
++ } b;
++} fifosize_data_t;
++
++/*!
++ \brief Bit fields in the Non-Periodic Transmit FIFO/Queue Status Register (GNPTXSTS).
++ */
++
++typedef union gnptxsts_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved : 1;
++ unsigned nptxqtop_chnep : 4; /*!< 30-27 Channel/EP Number of top of the Non-Periodic
++ Transmit Request Queue
++ */
++ unsigned nptxqtop_token : 2; /*!< 26-25 Token Type top of the Non-Periodic
++ Transmit Request Queue
++ 0 - IN/OUT
++ 1 - Zero Length OUT
++ 2 - PING/Complete Split
++ 3 - Channel Halt
++ */
++ unsigned nptxqtop_terminate : 1; /*!< 24 Terminate (Last entry for the selected
++ channel/EP)*/
++ unsigned nptxqspcavail : 8; /*!< 23-16 Transmit Request Queue Space Available */
++ unsigned nptxfspcavail :16; /*!< 15-00 TxFIFO Space Avail (in DWord)*/
++ }b;
++} gnptxsts_data_t;
++
++
++/*!
++ \brief Bit fields in the Transmit FIFO Status Register (DTXFSTS).
++ */
++typedef union dtxfsts_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved : 16;
++ unsigned txfspcavail : 16; /*!< 15-00 TxFIFO Space Avail (in DWord)*/
++ }b;
++} dtxfsts_data_t;
++
++
++/*!
++ \brief Bit fields in the I2C Control Register (I2CCTL).
++ */
++typedef union gi2cctl_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned bsydne : 1; /*!< 31 I2C Busy/Done*/
++ unsigned rw : 1; /*!< 30 Read/Write Indicator */
++ unsigned reserved : 2;
++ unsigned i2cdevaddr : 2; /*!< 27-26 I2C Device Address */
++ unsigned i2csuspctl : 1; /*!< 25 I2C Suspend Control */
++ unsigned ack : 1; /*!< 24 I2C ACK */
++ unsigned i2cen : 1; /*!< 23 I2C Enable */
++ unsigned addr : 7; /*!< 22-16 I2C Address */
++ unsigned regaddr : 8; /*!< 15-08 I2C Register Addr */
++ unsigned rwdata : 8; /*!< I2C Read/Write Data */
++ } b;
++} gi2cctl_data_t;
++
++
++/*!
++ \brief Bit fields in the User HW Config1 Register.
++ */
++typedef union hwcfg1_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned ep_dir15 : 2; /*!< Direction of each EP
++ 0: BIDIR (IN and OUT) endpoint
++ 1: IN endpoint
++ 2: OUT endpoint
++ 3: Reserved
++ */
++ unsigned ep_dir14 : 2;
++ unsigned ep_dir13 : 2;
++ unsigned ep_dir12 : 2;
++ unsigned ep_dir11 : 2;
++ unsigned ep_dir10 : 2;
++ unsigned ep_dir09 : 2;
++ unsigned ep_dir08 : 2;
++ unsigned ep_dir07 : 2;
++ unsigned ep_dir06 : 2;
++ unsigned ep_dir05 : 2;
++ unsigned ep_dir04 : 2;
++ unsigned ep_dir03 : 2;
++ unsigned ep_dir02 : 2;
++ unsigned ep_dir01 : 2;
++ unsigned ep_dir00 : 2;
++ }b;
++} hwcfg1_data_t;
++
++/*!
++ \brief Bit fields in the User HW Config2 Register.
++ */
++typedef union hwcfg2_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved31 : 1;
++ unsigned dev_token_q_depth : 5; /*!< 30-26 Device Mode IN Token Sequence Learning Queue Depth */
++ unsigned host_perio_tx_q_depth : 2; /*!< 25-24 Host Mode Periodic Request Queue Depth */
++ unsigned nonperio_tx_q_depth : 2; /*!< 23-22 Non-periodic Request Queue Depth */
++ unsigned rx_status_q_depth : 2; /*!< 21-20 Multi Processor Interrupt Enabled */
++ unsigned dynamic_fifo : 1; /*!< 19 Dynamic FIFO Sizing Enabled */
++ unsigned perio_ep_supported : 1; /*!< 18 Periodic OUT Channels Supported in Host Mode */
++ unsigned num_host_chan : 4; /*!< 17-14 Number of Host Channels */
++ unsigned num_dev_ep : 4; /*!< 13-10 Number of Device Endpoints */
++ unsigned fs_phy_type : 2; /*!< 09-08 Full-Speed PHY Interface Type */
++ #define IFXUSB_HWCFG2_FS_PHY_TYPE_NOT_SUPPORTED 0
++ #define IFXUSB_HWCFG2_FS_PHY_TYPE_DEDICATE 1
++ #define IFXUSB_HWCFG2_FS_PHY_TYPE_UTMI 2
++ #define IFXUSB_HWCFG2_FS_PHY_TYPE_ULPI 3
++ unsigned hs_phy_type : 2; /*!< 07-06 High-Speed PHY Interface Type */
++ #define IFXUSB_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
++ #define IFXUSB_HWCFG2_HS_PHY_TYPE_UTMI 1
++ #define IFXUSB_HWCFG2_HS_PHY_TYPE_ULPI 2
++ #define IFXUSB_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
++ unsigned point2point : 1; /*!< 05 Point-to-Point */
++ unsigned architecture : 2; /*!< 04-03 Architecture */
++ #define IFXUSB_HWCFG2_ARCH_SLAVE_ONLY 0
++ #define IFXUSB_HWCFG2_ARCH_EXT_DMA 1
++ #define IFXUSB_HWCFG2_ARCH_INT_DMA 2
++ unsigned op_mode : 3; /*!< 02-00 Mode of Operation */
++ #define IFXUSB_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0
++ #define IFXUSB_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1
++ #define IFXUSB_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2
++ #define IFXUSB_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
++ #define IFXUSB_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
++ #define IFXUSB_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
++ #define IFXUSB_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
++ } b;
++} hwcfg2_data_t;
++
++/*!
++ \brief Bit fields in the User HW Config3 Register.
++ */
++typedef union hwcfg3_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned dfifo_depth :16; /*!< 31-16 DFIFO Depth */
++ unsigned reserved15_12 : 4;
++ unsigned synch_reset_type : 1; /*!< 11 Reset Style for Clocked always Blocks in RTL */
++ unsigned optional_features : 1; /*!< 10 Optional Features Removed */
++ unsigned vendor_ctrl_if : 1; /*!< 09 Vendor Control Interface Support */
++ unsigned i2c : 1; /*!< 08 I2C Selection */
++ unsigned otg_func : 1; /*!< 07 OTG Function Enabled */
++ unsigned packet_size_cntr_width : 3; /*!< 06-04 Width of Packet Size Counters */
++ unsigned xfer_size_cntr_width : 4; /*!< 03-00 Width of Transfer Size Counters */
++ } b;
++} hwcfg3_data_t;
++
++/*!
++ \brief Bit fields in the User HW Config4
++ * Register. Read the register into the <i>d32</i> element then read
++ * out the bits using the <i>b</i>it elements.
++ */
++typedef union hwcfg4_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned desc_dma_dyn : 1; /*!< 31 Scatter/Gather DMA */
++ unsigned desc_dma : 1; /*!< 30 Scatter/Gather DMA configuration */
++ unsigned num_in_eps : 4; /*!< 29-26 Number of Device Mode IN Endpoints Including Control Endpoints */
++ unsigned ded_fifo_en : 1; /*!< 25 Enable Dedicated Transmit FIFO for device IN Endpoints */
++ unsigned session_end_filt_en : 1; /*!< 24 session_end Filter Enabled */
++ unsigned b_valid_filt_en : 1; /*!< 23 b_valid Filter Enabled */
++ unsigned a_valid_filt_en : 1; /*!< 22 a_valid Filter Enabled */
++ unsigned vbus_valid_filt_en : 1; /*!< 21 vbus_valid Filter Enabled */
++ unsigned iddig_filt_en : 1; /*!< 20 iddig Filter Enable */
++ unsigned num_dev_mode_ctrl_ep : 4; /*!< 19-16 Number of Device Mode Control Endpoints in Addition to Endpoint 0 */
++ unsigned utmi_phy_data_width : 2; /*!< 15-14 UTMI+ PHY/ULPI-to-Internal UTMI+ Wrapper Data Width */
++ unsigned reserved13_06 : 8;
++ unsigned min_ahb_freq : 1; /*!< 05 Minimum AHB Frequency Less Than 60 MHz */
++ unsigned power_optimiz : 1; /*!< 04 Enable Power Optimization? */
++ unsigned num_dev_perio_in_ep : 4; /*!< 03-00 Number of Device Mode Periodic IN Endpoints */
++ } b;
++} hwcfg4_data_t;
++
++/*@}*//*IFXUSB_CSR_CORE_GLOBAL_REG*/
++
++/****************************************************************************/
++/*!
++ \addtogroup IFXUSB_CSR_DEVICE_GLOBAL_REG
++ */
++/*@{*/
++
++/*!
++ \struct ifxusb_dev_global_regs
++ \brief IFXUSB Device Mode Global registers. Offsets 800h-BFFh
++ The ifxusb_dev_global_regs structure defines the size
++ and relative field offsets for the Device Global registers.
++ These registers are visible only in Device mode and must not be
++ accessed in Host mode, as the results are unknown.
++ */
++typedef struct ifxusb_dev_global_regs
++{
++ volatile uint32_t dcfg; /*!< 800h Device Configuration Register. */
++ volatile uint32_t dctl; /*!< 804h Device Control Register. */
++ volatile uint32_t dsts; /*!< 808h Device Status Register (Read Only). */
++ uint32_t unused;
++ volatile uint32_t diepmsk; /*!< 810h Device IN Endpoint Common Interrupt Mask Register. */
++ volatile uint32_t doepmsk; /*!< 814h Device OUT Endpoint Common Interrupt Mask Register. */
++ volatile uint32_t daint; /*!< 818h Device All Endpoints Interrupt Register. */
++ volatile uint32_t daintmsk; /*!< 81Ch Device All Endpoints Interrupt Mask Register. */
++ volatile uint32_t dtknqr1; /*!< 820h Device IN Token Queue Read Register-1 (Read Only). */
++ volatile uint32_t dtknqr2; /*!< 824h Device IN Token Queue Read Register-2 (Read Only). */
++ volatile uint32_t dvbusdis; /*!< 828h Device VBUS discharge Register.*/
++ volatile uint32_t dvbuspulse; /*!< 82Ch Device VBUS Pulse Register. */
++ volatile uint32_t dtknqr3_dthrctl; /*!< 830h Device IN Token Queue Read Register-3 (Read Only).
++ Device Thresholding control register (Read/Write)
++ */
++ volatile uint32_t dtknqr4_fifoemptymsk; /*!< 834h Device IN Token Queue Read Register-4 (Read Only).
++ Device IN EPs empty Inr. Mask Register (Read/Write)
++ */
++} ifxusb_device_global_regs_t;
++
++/*!
++ \brief Bit fields in the Device Configuration Register.
++ */
++
++typedef union dcfg_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved31_26 : 6;
++ unsigned perschintvl : 2; /*!< 25-24 Periodic Scheduling Interval */
++ unsigned descdma : 1; /*!< 23 Enable Descriptor DMA in Device mode */
++ unsigned epmscnt : 5; /*!< 22-18 In Endpoint Mis-match count */
++ unsigned reserved13_17 : 5;
++ unsigned perfrint : 2; /*!< 12-11 Periodic Frame Interval */
++ #define IFXUSB_DCFG_FRAME_INTERVAL_80 0
++ #define IFXUSB_DCFG_FRAME_INTERVAL_85 1
++ #define IFXUSB_DCFG_FRAME_INTERVAL_90 2
++ #define IFXUSB_DCFG_FRAME_INTERVAL_95 3
++ unsigned devaddr : 7; /*!< 10-04 Device Addresses */
++ unsigned reserved3 : 1;
++ unsigned nzstsouthshk : 1; /*!< 02 Non Zero Length Status OUT Handshake */
++ #define IFXUSB_DCFG_SEND_STALL 1
++ unsigned devspd : 2; /*!< 01-00 Device Speed */
++ } b;
++} dcfg_data_t;
++
++/*!
++ \brief Bit fields in the Device Control Register.
++ */
++typedef union dctl_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved16_31 :16;
++ unsigned ifrmnum : 1; /*!< 15 Ignore Frame Number for ISOC EPs */
++ unsigned gmc : 2; /*!< 14-13 Global Multi Count */
++ unsigned gcontbna : 1; /*!< 12 Global Continue on BNA */
++ unsigned pwronprgdone : 1; /*!< 11 Power-On Programming Done */
++ unsigned cgoutnak : 1; /*!< 10 Clear Global OUT NAK */
++ unsigned sgoutnak : 1; /*!< 09 Set Global OUT NAK */
++ unsigned cgnpinnak : 1; /*!< 08 Clear Global Non-Periodic IN NAK */
++ unsigned sgnpinnak : 1; /*!< 07 Set Global Non-Periodic IN NAK */
++ unsigned tstctl : 3; /*!< 06-04 Test Control */
++ unsigned goutnaksts : 1; /*!< 03 Global OUT NAK Status */
++ unsigned gnpinnaksts : 1; /*!< 02 Global Non-Periodic IN NAK Status */
++ unsigned sftdiscon : 1; /*!< 01 Soft Disconnect */
++ unsigned rmtwkupsig : 1; /*!< 00 Remote Wakeup */
++ } b;
++} dctl_data_t;
++
++
++/*!
++ \brief Bit fields in the Device Status Register.
++ */
++typedef union dsts_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved22_31 :10;
++ unsigned soffn :14; /*!< 21-08 Frame or Microframe Number of the received SOF */
++ unsigned reserved4_7 : 4;
++ unsigned errticerr : 1; /*!< 03 Erratic Error */
++ unsigned enumspd : 2; /*!< 02-01 Enumerated Speed */
++ #define IFXUSB_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ 0
++ #define IFXUSB_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ 1
++ #define IFXUSB_DSTS_ENUMSPD_LS_PHY_6MHZ 2
++ #define IFXUSB_DSTS_ENUMSPD_FS_PHY_48MHZ 3
++ unsigned suspsts : 1; /*!< 00 Suspend Status */
++ } b;
++} dsts_data_t;
++
++/*!
++ \brief Bit fields in the Device IN EP Interrupt Register
++ and the Device IN EP Common Mask Register.
++ */
++typedef union diepint_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved14_31 :18;
++ unsigned nakmsk : 1; /*!< 13 NAK interrupt Mask */
++ unsigned reserved10_12 : 3;
++ unsigned bna : 1; /*!< 09 BNA Interrupt mask */
++ unsigned txfifoundrn : 1; /*!< 08 Fifo Underrun Mask */
++ unsigned emptyintr : 1; /*!< 07 IN Endpoint HAK Effective mask */
++ unsigned inepnakeff : 1; /*!< 06 IN Endpoint HAK Effective mask */
++ unsigned intknepmis : 1; /*!< 05 IN Token Received with EP mismatch mask */
++ unsigned intktxfemp : 1; /*!< 04 IN Token received with TxF Empty mask */
++ unsigned timeout : 1; /*!< 03 TimeOUT Handshake mask (non-ISOC EPs) */
++ unsigned ahberr : 1; /*!< 02 AHB Error mask */
++ unsigned epdisabled : 1; /*!< 01 Endpoint disable mask */
++ unsigned xfercompl : 1; /*!< 00 Transfer complete mask */
++ } b;
++} diepint_data_t;
++
++
++/*!
++ \brief Bit fields in the Device OUT EP Interrupt Register and
++ Device OUT EP Common Interrupt Mask Register.
++ */
++typedef union doepint_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved15_31 :17;
++ unsigned nyetmsk : 1; /*!< 14 NYET Interrupt */
++ unsigned nakmsk : 1; /*!< 13 NAK Interrupt */
++ unsigned bbleerrmsk : 1; /*!< 12 Babble Interrupt */
++ unsigned reserved10_11 : 2;
++ unsigned bna : 1; /*!< 09 BNA Interrupt */
++ unsigned outpkterr : 1; /*!< 08 OUT packet Error */
++ unsigned reserved07 : 1;
++ unsigned back2backsetup : 1; /*!< 06 Back-to-Back SETUP Packets Received */
++ unsigned stsphsercvd : 1; /*!< 05 */
++ unsigned outtknepdis : 1; /*!< 04 OUT Token Received when Endpoint Disabled */
++ unsigned setup : 1; /*!< 03 Setup Phase Done (contorl EPs) */
++ unsigned ahberr : 1; /*!< 02 AHB Error */
++ unsigned epdisabled : 1; /*!< 01 Endpoint disable */
++ unsigned xfercompl : 1; /*!< 00 Transfer complete */
++ } b;
++} doepint_data_t;
++
++
++/*!
++ \brief Bit fields in the Device All EP Interrupt Registers.
++ */
++typedef union daint_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned out : 16; /*!< 31-16 OUT Endpoint bits */
++ unsigned in : 16; /*!< 15-00 IN Endpoint bits */
++ } eps;
++ struct
++ {
++ /** OUT Endpoint bits */
++ unsigned outep15 : 1;
++ unsigned outep14 : 1;
++ unsigned outep13 : 1;
++ unsigned outep12 : 1;
++ unsigned outep11 : 1;
++ unsigned outep10 : 1;
++ unsigned outep09 : 1;
++ unsigned outep08 : 1;
++ unsigned outep07 : 1;
++ unsigned outep06 : 1;
++ unsigned outep05 : 1;
++ unsigned outep04 : 1;
++ unsigned outep03 : 1;
++ unsigned outep02 : 1;
++ unsigned outep01 : 1;
++ unsigned outep00 : 1;
++ /** IN Endpoint bits */
++ unsigned inep15 : 1;
++ unsigned inep14 : 1;
++ unsigned inep13 : 1;
++ unsigned inep12 : 1;
++ unsigned inep11 : 1;
++ unsigned inep10 : 1;
++ unsigned inep09 : 1;
++ unsigned inep08 : 1;
++ unsigned inep07 : 1;
++ unsigned inep06 : 1;
++ unsigned inep05 : 1;
++ unsigned inep04 : 1;
++ unsigned inep03 : 1;
++ unsigned inep02 : 1;
++ unsigned inep01 : 1;
++ unsigned inep00 : 1;
++ } ep;
++} daint_data_t;
++
++
++/*!
++ \brief Bit fields in the Device IN Token Queue Read Registers.
++ */
++typedef union dtknq1_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned epnums0_5 :24; /*!< 31-08 EP Numbers of IN Tokens 0 ... 4 */
++ unsigned wrap_bit : 1; /*!< 07 write pointer has wrapped */
++ unsigned reserved05_06 : 2;
++ unsigned intknwptr : 5; /*!< 04-00 In Token Queue Write Pointer */
++ }b;
++} dtknq1_data_t;
++
++
++/*!
++ \brief Bit fields in Threshold control Register
++ */
++typedef union dthrctl_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved26_31 : 6;
++ unsigned rx_thr_len : 9; /*!< 25-17 Rx Thr. Length */
++ unsigned rx_thr_en : 1; /*!< 16 Rx Thr. Enable */
++ unsigned reserved11_15 : 5;
++ unsigned tx_thr_len : 9; /*!< 10-02 Tx Thr. Length */
++ unsigned iso_thr_en : 1; /*!< 01 ISO Tx Thr. Enable */
++ unsigned non_iso_thr_en : 1; /*!< 00 non ISO Tx Thr. Enable */
++ } b;
++} dthrctl_data_t;
++
++/*@}*//*IFXUSB_CSR_DEVICE_GLOBAL_REG*/
++
++/****************************************************************************/
++
++/*!
++ \addtogroup IFXUSB_CSR_DEVICE_EP_REG
++ */
++/*@{*/
++
++/*!
++ \struct ifxusb_dev_in_ep_regs
++ \brief Device Logical IN Endpoint-Specific Registers.
++ There will be one set of endpoint registers per logical endpoint
++ implemented.
++ each EP's IN EP Register are offset at :
++ 900h + * (ep_num * 20h)
++ */
++
++typedef struct ifxusb_dev_in_ep_regs
++{
++ volatile uint32_t diepctl; /*!< 00h: Endpoint Control Register */
++ uint32_t reserved04; /*!< 04h: */
++ volatile uint32_t diepint; /*!< 08h: Endpoint Interrupt Register */
++ uint32_t reserved0C; /*!< 0Ch: */
++ volatile uint32_t dieptsiz; /*!< 10h: Endpoint Transfer Size Register.*/
++ volatile uint32_t diepdma; /*!< 14h: Endpoint DMA Address Register. */
++ volatile uint32_t dtxfsts; /*!< 18h: Endpoint Transmit FIFO Status Register. */
++ volatile uint32_t diepdmab; /*!< 1Ch: Endpoint DMA Buffer Register. */
++} ifxusb_dev_in_ep_regs_t;
++
++/*!
++ \brief Device Logical OUT Endpoint-Specific Registers.
++ There will be one set of endpoint registers per logical endpoint
++ implemented.
++ each EP's OUT EP Register are offset at :
++ B00h + * (ep_num * 20h) + 00h
++ */
++typedef struct ifxusb_dev_out_ep_regs
++{
++ volatile uint32_t doepctl; /*!< 00h: Endpoint Control Register */
++ volatile uint32_t doepfn; /*!< 04h: Endpoint Frame number Register */
++ volatile uint32_t doepint; /*!< 08h: Endpoint Interrupt Register */
++ uint32_t reserved0C; /*!< 0Ch: */
++ volatile uint32_t doeptsiz; /*!< 10h: Endpoint Transfer Size Register.*/
++ volatile uint32_t doepdma; /*!< 14h: Endpoint DMA Address Register. */
++ uint32_t reserved18; /*!< 18h: */
++ volatile uint32_t doepdmab; /*!< 1Ch: Endpoint DMA Buffer Register. */
++} ifxusb_dev_out_ep_regs_t;
++
++
++/*!
++ \brief Bit fields in the Device EP Control
++ Register.
++ */
++typedef union depctl_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned epena : 1; /*!< 31 Endpoint Enable */
++ unsigned epdis : 1; /*!< 30 Endpoint Disable */
++ unsigned setd1pid : 1; /*!< 29 Set DATA1 PID (INTR/Bulk IN and OUT endpoints) */
++ unsigned setd0pid : 1; /*!< 28 Set DATA0 PID (INTR/Bulk IN and OUT endpoints) */
++ unsigned snak : 1; /*!< 27 Set NAK */
++ unsigned cnak : 1; /*!< 26 Clear NAK */
++ unsigned txfnum : 4; /*!< 25-22 Tx Fifo Number */
++ unsigned stall : 1; /*!< 21 Stall Handshake */
++ unsigned snp : 1; /*!< 20 Snoop Mode */
++ unsigned eptype : 2; /*!< 19-18 Endpoint Type
++ 0: Control
++ 1: Isochronous
++ 2: Bulk
++ 3: Interrupt
++ */
++ unsigned naksts : 1; /*!< 17 NAK Status */
++ unsigned dpid : 1; /*!< 16 Endpoint DPID (INTR/Bulk IN and OUT endpoints) */
++ unsigned usbactep : 1; /*!< 15 USB Active Endpoint */
++ unsigned nextep : 4; /*!< 14-11 Next Endpoint */
++ unsigned mps :11; /*!< 10-00 Maximum Packet Size */
++ #define IFXUSB_DEP0CTL_MPS_64 0
++ #define IFXUSB_DEP0CTL_MPS_32 1
++ #define IFXUSB_DEP0CTL_MPS_16 2
++ #define IFXUSB_DEP0CTL_MPS_8 3
++ } b;
++} depctl_data_t;
++
++
++/*!
++ \brief Bit fields in the Device EP Transfer Size Register. (EP0 and EPn)
++ */
++typedef union deptsiz_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved31 : 1;
++ unsigned supcnt : 2; /*!< 30-29 Setup Packet Count */
++ unsigned reserved20_28 : 9;
++ unsigned pktcnt : 1; /*!< 19 Packet Count */
++ unsigned reserved7_18 :12;
++ unsigned xfersize : 7; /*!< 06-00 Transfer size */
++ }b0;
++ struct
++ {
++ unsigned reserved : 1;
++ unsigned mc : 2; /*!< 30-29 Multi Count */
++ unsigned pktcnt :10; /*!< 28-19 Packet Count */
++ unsigned xfersize :19; /*!< 18-00 Transfer size */
++ } b;
++} deptsiz_data_t;
++
++/*@}*//*IFXUSB_CSR_DEVICE_EP_REG*/
++/****************************************************************************/
++
++/*!
++ \addtogroup IFXUSB_CSR_DEVICE_DMA_DESC
++ */
++/*@{*/
++/*!
++ \struct desc_sts_data
++ \brief Bit fields in the DMA Descriptor status quadlet.
++ */
++typedef union desc_sts_data
++{
++ struct
++ {
++ unsigned bs : 2; /*!< 31-30 Buffer Status */
++ #define BS_HOST_READY 0x0
++ #define BS_DMA_BUSY 0x1
++ #define BS_DMA_DONE 0x2
++ #define BS_HOST_BUSY 0x3
++ unsigned sts : 2; /*!< 29-28 Receive/Trasmit Status */
++ #define RTS_SUCCESS 0x0
++ #define RTS_BUFFLUSH 0x1
++ #define RTS_RESERVED 0x2
++ #define RTS_BUFERR 0x3
++ unsigned l : 1; /*!< 27 Last */
++ unsigned sp : 1; /*!< 26 Short Packet */
++ unsigned ioc : 1; /*!< 25 Interrupt On Complete */
++ unsigned sr : 1; /*!< 24 Setup Packet received */
++ unsigned mtrf : 1; /*!< 23 Multiple Transfer */
++ unsigned reserved16_22 : 7;
++ unsigned bytes :16; /*!< 15-00 Transfer size in bytes */
++ } b;
++ uint32_t d32; /*!< DMA Descriptor data buffer pointer */
++} desc_sts_data_t;
++
++/*@}*//*IFXUSB_CSR_DEVICE_DMA_DESC*/
++/****************************************************************************/
++
++/*!
++ \addtogroup IFXUSB_CSR_HOST_GLOBAL_REG
++ */
++/*@{*/
++/*!
++ \struct ifxusb_host_global_regs
++ \brief IFXUSB Host Mode Global registers. Offsets 400h-7FFh
++ The ifxusb_host_global_regs structure defines the size
++ and relative field offsets for the Host Global registers.
++ These registers are visible only in Host mode and must not be
++ accessed in Device mode, as the results are unknown.
++ */
++typedef struct ifxusb_host_global_regs
++{
++ volatile uint32_t hcfg; /*!< 400h Host Configuration Register. */
++ volatile uint32_t hfir; /*!< 404h Host Frame Interval Register. */
++ volatile uint32_t hfnum; /*!< 408h Host Frame Number / Frame Remaining Register. */
++ uint32_t reserved40C;
++ volatile uint32_t hptxsts; /*!< 410h Host Periodic Transmit FIFO/ Queue Status Register. */
++ volatile uint32_t haint; /*!< 414h Host All Channels Interrupt Register. */
++ volatile uint32_t haintmsk; /*!< 418h Host All Channels Interrupt Mask Register. */
++} ifxusb_host_global_regs_t;
++
++/*!
++ \brief Bit fields in the Host Configuration Register.
++ */
++typedef union hcfg_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved31_03 :29;
++ unsigned fslssupp : 1; /*!< 02 FS/LS Only Support */
++ unsigned fslspclksel : 2; /*!< 01-00 FS/LS Phy Clock Select */
++ #define IFXUSB_HCFG_30_60_MHZ 0
++ #define IFXUSB_HCFG_48_MHZ 1
++ #define IFXUSB_HCFG_6_MHZ 2
++ } b;
++} hcfg_data_t;
++
++/*!
++ \brief Bit fields in the Host Frame Interval Register.
++ */
++typedef union hfir_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved : 16;
++ unsigned frint : 16; /*!< 15-00 Frame Interval */
++ } b;
++} hfir_data_t;
++
++/*!
++ \brief Bit fields in the Host Frame Time Remaing/Number Register.
++ */
++typedef union hfnum_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned frrem : 16; /*!< 31-16 Frame Time Remaining */
++ unsigned frnum : 16; /*!< 15-00 Frame Number*/
++ #define IFXUSB_HFNUM_MAX_FRNUM 0x3FFF
++ } b;
++} hfnum_data_t;
++
++/*!
++ \brief Bit fields in the Host Periodic Transmit FIFO/Queue Status Register
++ */
++typedef union hptxsts_data
++{
++ /** raw register data */
++ uint32_t d32;
++ struct
++ {
++ /** Top of the Periodic Transmit Request Queue
++ * - bit 24 - Terminate (last entry for the selected channel)
++ */
++ unsigned ptxqtop_odd : 1; /*!< 31 Top of the Periodic Transmit Request
++ Queue Odd/even microframe*/
++ unsigned ptxqtop_chnum : 4; /*!< 30-27 Top of the Periodic Transmit Request
++ Channel Number */
++ unsigned ptxqtop_token : 2; /*!< 26-25 Top of the Periodic Transmit Request
++ Token Type
++ 0 - Zero length
++ 1 - Ping
++ 2 - Disable
++ */
++ unsigned ptxqtop_terminate : 1; /*!< 24 Top of the Periodic Transmit Request
++ Terminate (last entry for the selected channel)*/
++ unsigned ptxqspcavail : 8; /*!< 23-16 Periodic Transmit Request Queue Space Available */
++ unsigned ptxfspcavail :16; /*!< 15-00 Periodic Transmit Data FIFO Space Available */
++ } b;
++} hptxsts_data_t;
++
++/*!
++ \brief Bit fields in the Host Port Control and Status Register.
++ */
++typedef union hprt0_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved19_31 :13;
++ unsigned prtspd : 2; /*!< 18-17 Port Speed */
++ #define IFXUSB_HPRT0_PRTSPD_HIGH_SPEED 0
++ #define IFXUSB_HPRT0_PRTSPD_FULL_SPEED 1
++ #define IFXUSB_HPRT0_PRTSPD_LOW_SPEED 2
++ unsigned prttstctl : 4; /*!< 16-13 Port Test Control */
++ unsigned prtpwr : 1; /*!< 12 Port Power */
++ unsigned prtlnsts : 2; /*!< 11-10 Port Line Status */
++ unsigned reserved9 : 1;
++ unsigned prtrst : 1; /*!< 08 Port Reset */
++ unsigned prtsusp : 1; /*!< 07 Port Suspend */
++ unsigned prtres : 1; /*!< 06 Port Resume */
++ unsigned prtovrcurrchng : 1; /*!< 05 Port Overcurrent Change */
++ unsigned prtovrcurract : 1; /*!< 04 Port Overcurrent Active */
++ unsigned prtenchng : 1; /*!< 03 Port Enable/Disable Change */
++ unsigned prtena : 1; /*!< 02 Port Enable */
++ unsigned prtconndet : 1; /*!< 01 Port Connect Detected */
++ unsigned prtconnsts : 1; /*!< 00 Port Connect Status */
++ }b;
++} hprt0_data_t;
++
++/*!
++ \brief Bit fields in the Host All Interrupt Register.
++ */
++typedef union haint_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved : 16;
++ unsigned ch15 : 1;
++ unsigned ch14 : 1;
++ unsigned ch13 : 1;
++ unsigned ch12 : 1;
++ unsigned ch11 : 1;
++ unsigned ch10 : 1;
++ unsigned ch09 : 1;
++ unsigned ch08 : 1;
++ unsigned ch07 : 1;
++ unsigned ch06 : 1;
++ unsigned ch05 : 1;
++ unsigned ch04 : 1;
++ unsigned ch03 : 1;
++ unsigned ch02 : 1;
++ unsigned ch01 : 1;
++ unsigned ch00 : 1;
++ } b;
++ struct
++ {
++ unsigned reserved : 16;
++ unsigned chint : 16;
++ } b2;
++} haint_data_t;
++/*@}*//*IFXUSB_CSR_HOST_GLOBAL_REG*/
++/****************************************************************************/
++/*!
++ \addtogroup IFXUSB_CSR_HOST_HC_REG
++ */
++/*@{*/
++/*!
++ \brief Host Channel Specific Registers
++ There will be one set of hc registers per host channelimplemented.
++ each HC's Register are offset at :
++ 500h + * (hc_num * 20h)
++ */
++typedef struct ifxusb_hc_regs
++{
++ volatile uint32_t hcchar; /*!< 00h Host Channel Characteristic Register.*/
++ volatile uint32_t hcsplt; /*!< 04h Host Channel Split Control Register.*/
++ volatile uint32_t hcint; /*!< 08h Host Channel Interrupt Register. */
++ volatile uint32_t hcintmsk; /*!< 0Ch Host Channel Interrupt Mask Register. */
++ volatile uint32_t hctsiz; /*!< 10h Host Channel Transfer Size Register. */
++ volatile uint32_t hcdma; /*!< 14h Host Channel DMA Address Register. */
++ uint32_t reserved[2]; /*!< 18h Reserved. */
++} ifxusb_hc_regs_t;
++
++
++/*!
++ \brief Bit fields in the Host Channel Characteristics Register.
++ */
++typedef union hcchar_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned chen : 1; /*!< 31 Channel enable */
++ unsigned chdis : 1; /*!< 30 Channel disable */
++ unsigned oddfrm : 1; /*!< 29 Frame to transmit periodic transaction */
++ unsigned devaddr : 7; /*!< 28-22 Device address */
++ unsigned multicnt : 2; /*!< 21-20 Packets per frame for periodic transfers */
++ unsigned eptype : 2; /*!< 19-18 0: Control, 1: Isoc, 2: Bulk, 3: Intr */
++ unsigned lspddev : 1; /*!< 17 0: Full/high speed device, 1: Low speed device */
++ unsigned reserved : 1;
++ unsigned epdir : 1; /*!< 15 0: OUT, 1: IN */
++ unsigned epnum : 4; /*!< 14-11 Endpoint number */
++ unsigned mps :11; /*!< 10-00 Maximum packet size in bytes */
++ } b;
++} hcchar_data_t;
++
++/*!
++ \brief Bit fields in the Host Channel Split Control Register
++ */
++typedef union hcsplt_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned spltena : 1; /*!< 31 Split Enble */
++ unsigned reserved :14;
++ unsigned compsplt : 1; /*!< 16 Do Complete Split */
++ unsigned xactpos : 2; /*!< 15-14 Transaction Position */
++ #define IFXUSB_HCSPLIT_XACTPOS_MID 0
++ #define IFXUSB_HCSPLIT_XACTPOS_END 1
++ #define IFXUSB_HCSPLIT_XACTPOS_BEGIN 2
++ #define IFXUSB_HCSPLIT_XACTPOS_ALL 3
++ unsigned hubaddr : 7; /*!< 13-07 Hub Address */
++ unsigned prtaddr : 7; /*!< 06-00 Port Address */
++ } b;
++} hcsplt_data_t;
++
++/*!
++ \brief Bit fields in the Host Interrupt Register.
++ */
++typedef union hcint_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved :21;
++ unsigned datatglerr : 1; /*!< 10 Data Toggle Error */
++ unsigned frmovrun : 1; /*!< 09 Frame Overrun */
++ unsigned bblerr : 1; /*!< 08 Babble Error */
++ unsigned xacterr : 1; /*!< 07 Transaction Err */
++ unsigned nyet : 1; /*!< 06 NYET Response Received */
++ unsigned ack : 1; /*!< 05 ACK Response Received */
++ unsigned nak : 1; /*!< 04 NAK Response Received */
++ unsigned stall : 1; /*!< 03 STALL Response Received */
++ unsigned ahberr : 1; /*!< 02 AHB Error */
++ unsigned chhltd : 1; /*!< 01 Channel Halted */
++ unsigned xfercomp : 1; /*!< 00 Channel Halted */
++ }b;
++} hcint_data_t;
++
++
++/*!
++ \brief Bit fields in the Host Channel Transfer Size
++ Register.
++ */
++typedef union hctsiz_data
++{
++ uint32_t d32;
++ struct
++ {
++ /** */
++ unsigned dopng : 1; /*!< 31 Do PING protocol when 1 */
++ /**
++ * Packet ID for next data packet
++ * 0: DATA0
++ * 1: DATA2
++ * 2: DATA1
++ * 3: MDATA (non-Control), SETUP (Control)
++ */
++ unsigned pid : 2; /*!< 30-29 Packet ID for next data packet
++ 0: DATA0
++ 1: DATA2
++ 2: DATA1
++ 3: MDATA (non-Control), SETUP (Control)
++ */
++ #define IFXUSB_HCTSIZ_DATA0 0
++ #define IFXUSB_HCTSIZ_DATA1 2
++ #define IFXUSB_HCTSIZ_DATA2 1
++ #define IFXUSB_HCTSIZ_MDATA 3
++ #define IFXUSB_HCTSIZ_SETUP 3
++ unsigned pktcnt :10; /*!< 28-19 Data packets to transfer */
++ unsigned xfersize :19; /*!< 18-00 Total transfer size in bytes */
++ }b;
++} hctsiz_data_t;
++
++/*@}*//*IFXUSB_CSR_HOST_HC_REG*/
++
++/****************************************************************************/
++
++/*!
++ \addtogroup IFXUSB_CSR_PWR_CLK_GATING_REG
++ */
++/*@{*/
++/*!
++ \brief Bit fields in the Power and Clock Gating Control Register
++ */
++typedef union pcgcctl_data
++{
++ uint32_t d32;
++ struct
++ {
++ unsigned reserved : 27;
++ unsigned physuspended : 1; /*!< 04 PHY Suspended */
++ unsigned rstpdwnmodule : 1; /*!< 03 Reset Power Down Modules */
++ unsigned pwrclmp : 1; /*!< 02 Power Clamp */
++ unsigned gatehclk : 1; /*!< 01 Gate Hclk */
++ unsigned stoppclk : 1; /*!< 00 Stop Pclk */
++ } b;
++} pcgcctl_data_t;
++/*@}*//*IFXUSB_CSR_PWR_CLK_GATING_REG*/
++
++/****************************************************************************/
++
++#endif //__IFXUSB_REGS_H__
+diff --git a/drivers/usb/ifxhcd/ifxusb_version.h b/drivers/usb/ifxhcd/ifxusb_version.h
+new file mode 100644
+index 0000000..2dff735
+--- /dev/null
++++ b/drivers/usb/ifxhcd/ifxusb_version.h
+@@ -0,0 +1,5 @@
++
++#ifndef IFXUSB_VERSION
++#define IFXUSB_VERSION "3.0alpha B100312"
++#endif
++
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0051-MIPS-adds-gptu-driver.patch b/target/linux/lantiq/patches-3.2/0051-MIPS-adds-gptu-driver.patch
new file mode 100644
index 0000000..e8b9318
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0051-MIPS-adds-gptu-driver.patch
@@ -0,0 +1,195 @@
+From a7c55f5e927b69bb30912fe1c3e5bcd8751e8381 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 14 Mar 2012 15:37:19 +0100
+Subject: [PATCH 51/70] MIPS: adds gptu driver
+
+---
+ arch/mips/lantiq/xway/gptu.c | 176 ++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 176 insertions(+), 0 deletions(-)
+ create mode 100644 arch/mips/lantiq/xway/gptu.c
+
+diff --git a/arch/mips/lantiq/xway/gptu.c b/arch/mips/lantiq/xway/gptu.c
+new file mode 100644
+index 0000000..ac82c37
+--- /dev/null
++++ b/arch/mips/lantiq/xway/gptu.c
+@@ -0,0 +1,176 @@
++/*
++ * 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.
++ *
++ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/ioport.h>
++#include <linux/pm.h>
++#include <linux/export.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <asm/reboot.h>
++
++#include <lantiq_soc.h>
++#include "../clk.h"
++
++#include "../devices.h"
++
++#define ltq_gptu_w32(x, y) ltq_w32((x), ltq_gptu_membase + (y))
++#define ltq_gptu_r32(x) ltq_r32(ltq_gptu_membase + (x))
++
++
++/* the magic ID byte of the core */
++#define GPTU_MAGIC 0x59
++/* clock control register */
++#define GPTU_CLC 0x00
++/* id register */
++#define GPTU_ID 0x08
++/* interrupt node enable */
++#define GPTU_IRNEN 0xf4
++/* interrupt control register */
++#define GPTU_IRCR 0xf8
++/* interrupt capture register */
++#define GPTU_IRNCR 0xfc
++/* there are 3 identical blocks of 2 timers. calculate register offsets */
++#define GPTU_SHIFT(x) (x % 2 ? 4 : 0)
++#define GPTU_BASE(x) (((x >> 1) * 0x20) + 0x10)
++/* timer control register */
++#define GPTU_CON(x) (GPTU_BASE(x) + GPTU_SHIFT(x) + 0x00)
++/* timer auto reload register */
++#define GPTU_RUN(x) (GPTU_BASE(x) + GPTU_SHIFT(x) + 0x08)
++/* timer manual reload register */
++#define GPTU_RLD(x) (GPTU_BASE(x) + GPTU_SHIFT(x) + 0x10)
++/* timer count register */
++#define GPTU_CNT(x) (GPTU_BASE(x) + GPTU_SHIFT(x) + 0x18)
++
++/* GPTU_CON(x) */
++#define CON_CNT BIT(2)
++#define CON_EDGE_FALL BIT(7)
++#define CON_SYNC BIT(8)
++#define CON_CLK_INT BIT(10)
++
++/* GPTU_RUN(x) */
++#define RUN_SEN BIT(0)
++#define RUN_RL BIT(2)
++
++/* set clock to runmode */
++#define CLC_RMC BIT(8)
++/* bring core out of suspend */
++#define CLC_SUSPEND BIT(4)
++/* the disable bit */
++#define CLC_DISABLE BIT(0)
++
++#define TIMER_INTERRUPT (INT_NUM_IM3_IRL0 + 22)
++
++enum gptu_timer {
++ TIMER1A = 0,
++ TIMER1B,
++ TIMER2A,
++ TIMER2B,
++ TIMER3A,
++ TIMER3B
++};
++
++static struct resource ltq_gptu_resource =
++ MEM_RES("GPTU", LTQ_GPTU_BASE_ADDR, LTQ_GPTU_SIZE);
++
++static void __iomem *ltq_gptu_membase;
++
++static irqreturn_t timer_irq_handler(int irq, void *priv)
++{
++ int timer = irq - TIMER_INTERRUPT;
++ ltq_gptu_w32(1 << timer, GPTU_IRNCR);
++ return IRQ_HANDLED;
++}
++
++static void gptu_hwinit(void)
++{
++ struct clk *clk = clk_get_sys("ltq_gptu", NULL);
++ clk_enable(clk);
++ ltq_gptu_w32(0x00, GPTU_IRNEN);
++ ltq_gptu_w32(0xff, GPTU_IRNCR);
++ ltq_gptu_w32(CLC_RMC | CLC_SUSPEND, GPTU_CLC);
++}
++
++static void gptu_hwexit(void)
++{
++ ltq_gptu_w32(0x00, GPTU_IRNEN);
++ ltq_gptu_w32(0xff, GPTU_IRNCR);
++ ltq_gptu_w32(CLC_DISABLE, GPTU_CLC);
++}
++
++static int ltq_gptu_enable(struct clk *clk)
++{
++ int ret = request_irq(TIMER_INTERRUPT + clk->bits, timer_irq_handler,
++ IRQF_TIMER, "timer", NULL);
++ if (ret) {
++ pr_err("gptu: failed to request irq\n");
++ return ret;
++ }
++
++ ltq_gptu_w32(CON_CNT | CON_EDGE_FALL | CON_SYNC | CON_CLK_INT,
++ GPTU_CON(clk->bits));
++ ltq_gptu_w32(1, GPTU_RLD(clk->bits));
++ ltq_gptu_w32(ltq_gptu_r32(GPTU_IRNEN) | clk->bits, GPTU_IRNEN);
++ ltq_gptu_w32(RUN_SEN | RUN_RL, GPTU_RUN(clk->bits));
++ return 0;
++}
++
++static void ltq_gptu_disable(struct clk *clk)
++{
++ ltq_gptu_w32(0, GPTU_RUN(clk->bits));
++ ltq_gptu_w32(0, GPTU_CON(clk->bits));
++ ltq_gptu_w32(0, GPTU_RLD(clk->bits));
++ ltq_gptu_w32(ltq_gptu_r32(GPTU_IRNEN) & ~clk->bits, GPTU_IRNEN);
++ free_irq(TIMER_INTERRUPT + clk->bits, NULL);
++}
++
++static inline void clkdev_add_gptu(const char *con, unsigned int timer)
++{
++ struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
++
++ clk->cl.dev_id = "ltq_gptu";
++ clk->cl.con_id = con;
++ clk->cl.clk = clk;
++ clk->enable = ltq_gptu_enable;
++ clk->disable = ltq_gptu_disable;
++ clk->bits = timer;
++ clkdev_add(&clk->cl);
++}
++
++static int __init gptu_setup(void)
++{
++ /* remap gptu register range */
++ ltq_gptu_membase = ltq_remap_resource(&ltq_gptu_resource);
++ if (!ltq_gptu_membase)
++ panic("Failed to remap gptu memory");
++
++ /* power up the core */
++ gptu_hwinit();
++
++ /* the gptu has a ID register */
++ if (((ltq_gptu_r32(GPTU_ID) >> 8) & 0xff) != GPTU_MAGIC) {
++ pr_err("gptu: failed to find magic\n");
++ gptu_hwexit();
++ return -ENAVAIL;
++ }
++
++ /* register the clocks */
++ clkdev_add_gptu("timer1a", TIMER1A);
++ clkdev_add_gptu("timer1b", TIMER1B);
++ clkdev_add_gptu("timer2a", TIMER2A);
++ clkdev_add_gptu("timer2b", TIMER2B);
++ clkdev_add_gptu("timer3a", TIMER3A);
++ clkdev_add_gptu("timer3b", TIMER3B);
++
++ pr_info("gptu: 6 timers loaded\n");
++
++ return 0;
++}
++
++arch_initcall(gptu_setup);
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0052-MIPS-lantiq-pci-rename-variable-inside.patch b/target/linux/lantiq/patches-3.2/0052-MIPS-lantiq-pci-rename-variable-inside.patch
new file mode 100644
index 0000000..5c1cb55
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0052-MIPS-lantiq-pci-rename-variable-inside.patch
@@ -0,0 +1,79 @@
+From 3571f6a294783e617c2f8f52021f9c33bc9e5a36 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Mar 2012 12:00:17 +0100
+Subject: [PATCH 52/70] MIPS: lantiq: pci: rename variable inside
+
+* rename a global var inside the pci code
+---
+ arch/mips/pci/ops-lantiq.c | 6 +++---
+ arch/mips/pci/pci-lantiq.c | 6 +++---
+ arch/mips/pci/pci-lantiq.h | 2 +-
+ 3 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/arch/mips/pci/ops-lantiq.c b/arch/mips/pci/ops-lantiq.c
+index 1f2afb5..5cbb0cf 100644
+--- a/arch/mips/pci/ops-lantiq.c
++++ b/arch/mips/pci/ops-lantiq.c
+@@ -41,7 +41,7 @@ static int ltq_pci_config_access(unsigned char access_type, struct pci_bus *bus,
+
+ spin_lock_irqsave(&ebu_lock, flags);
+
+- cfg_base = (unsigned long) ltq_pci_mapped_cfg;
++ cfg_base = (unsigned long) ltq_pci_cfgbase;
+ cfg_base |= (bus->number << LTQ_PCI_CFG_BUSNUM_SHF) | (devfn <<
+ LTQ_PCI_CFG_FUNNUM_SHF) | (where & ~0x3);
+
+@@ -55,11 +55,11 @@ static int ltq_pci_config_access(unsigned char access_type, struct pci_bus *bus,
+ wmb();
+
+ /* clean possible Master abort */
+- cfg_base = (unsigned long) ltq_pci_mapped_cfg;
++ cfg_base = (unsigned long) ltq_pci_cfgbase;
+ cfg_base |= (0x0 << LTQ_PCI_CFG_FUNNUM_SHF) + 4;
+ temp = ltq_r32(((u32 *)(cfg_base)));
+ temp = swab32(temp);
+- cfg_base = (unsigned long) ltq_pci_mapped_cfg;
++ cfg_base = (unsigned long) ltq_pci_cfgbase;
+ cfg_base |= (0x68 << LTQ_PCI_CFG_FUNNUM_SHF) + 4;
+ ltq_w32(temp, ((u32 *)cfg_base));
+
+diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c
+index 47b551c..efcdd45 100644
+--- a/arch/mips/pci/pci-lantiq.c
++++ b/arch/mips/pci/pci-lantiq.c
+@@ -65,8 +65,8 @@
+ #define ltq_pci_w32(x, y) ltq_w32((x), ltq_pci_membase + (y))
+ #define ltq_pci_r32(x) ltq_r32(ltq_pci_membase + (x))
+
+-#define ltq_pci_cfg_w32(x, y) ltq_w32((x), ltq_pci_mapped_cfg + (y))
+-#define ltq_pci_cfg_r32(x) ltq_r32(ltq_pci_mapped_cfg + (x))
++#define ltq_pci_cfg_w32(x, y) ltq_w32((x), ltq_pci_cfgbase + (y))
++#define ltq_pci_cfg_r32(x) ltq_r32(ltq_pci_cfgbase + (x))
+
+ struct ltq_pci_gpio_map {
+ int pin;
+@@ -273,7 +273,7 @@ static int __devinit ltq_pci_probe(struct platform_device *pdev)
+ pci_probe_only = 0;
+ ltq_pci_irq_map = ltq_pci_data->irq;
+ ltq_pci_membase = ioremap_nocache(PCI_CR_BASE_ADDR, PCI_CR_SIZE);
+- ltq_pci_mapped_cfg =
++ ltq_pci_cfgbase =
+ ioremap_nocache(LTQ_PCI_CFG_BASE, LTQ_PCI_CFG_BASE);
+ ltq_pci_controller.io_map_base =
+ (unsigned long)ioremap(LTQ_PCI_IO_BASE, LTQ_PCI_IO_SIZE - 1);
+diff --git a/arch/mips/pci/pci-lantiq.h b/arch/mips/pci/pci-lantiq.h
+index 66bf6cd..c4721b4 100644
+--- a/arch/mips/pci/pci-lantiq.h
++++ b/arch/mips/pci/pci-lantiq.h
+@@ -9,7 +9,7 @@
+ #ifndef _LTQ_PCI_H__
+ #define _LTQ_PCI_H__
+
+-extern __iomem void *ltq_pci_mapped_cfg;
++extern __iomem void *ltq_pci_cfgbase;
+ extern int ltq_pci_read_config_dword(struct pci_bus *bus,
+ unsigned int devfn, int where, int size, u32 *val);
+ extern int ltq_pci_write_config_dword(struct pci_bus *bus,
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0053-MIPS-lantiq-pci-give-xway-pci-support-its-own-kbuild.patch b/target/linux/lantiq/patches-3.2/0053-MIPS-lantiq-pci-give-xway-pci-support-its-own-kbuild.patch
new file mode 100644
index 0000000..fd5ba07
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0053-MIPS-lantiq-pci-give-xway-pci-support-its-own-kbuild.patch
@@ -0,0 +1,45 @@
+From 00dda451e12b6fc519cd4f575a696c4216f45992 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Mar 2012 13:13:31 +0100
+Subject: [PATCH 53/70] MIPS: lantiq: pci: give xway pci support its own
+ kbuild symbol
+
+---
+ arch/mips/lantiq/Kconfig | 5 +++++
+ arch/mips/pci/Makefile | 2 +-
+ 2 files changed, 6 insertions(+), 1 deletions(-)
+
+diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
+index cb6b39f..dde9fc6 100644
+--- a/arch/mips/lantiq/Kconfig
++++ b/arch/mips/lantiq/Kconfig
+@@ -19,8 +19,13 @@ config SOC_XWAY
+
+ config SOC_FALCON
+ bool "FALCON"
++
+ endchoice
+
++config PCI_LANTIQ
++ bool "PCI Support"
++ depends on SOC_XWAY && PCI
++
+ source "arch/mips/lantiq/xway/Kconfig"
+ source "arch/mips/lantiq/falcon/Kconfig"
+
+diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
+index bb82cbd..afad91d 100644
+--- a/arch/mips/pci/Makefile
++++ b/arch/mips/pci/Makefile
+@@ -40,7 +40,7 @@ obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o
+ obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o
+ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o
+ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o
+-obj-$(CONFIG_SOC_XWAY) += pci-lantiq.o ops-lantiq.o
++obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o
+ obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
+ obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
+ obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0054-MIPS-lantiq-pci-move-pcibios-code-into-fixup-lantiq..patch b/target/linux/lantiq/patches-3.2/0054-MIPS-lantiq-pci-move-pcibios-code-into-fixup-lantiq..patch
new file mode 100644
index 0000000..500b224
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0054-MIPS-lantiq-pci-move-pcibios-code-into-fixup-lantiq..patch
@@ -0,0 +1,131 @@
+From 49b5d2242091e216736216d98d7f940870d4f1ec Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Mar 2012 15:53:10 +0100
+Subject: [PATCH 54/70] MIPS: lantiq: pci: move pcibios code into
+ fixup-lantiq.c
+
+---
+ arch/mips/pci/Makefile | 1 +
+ arch/mips/pci/fixup-lantiq.c | 42 ++++++++++++++++++++++++++++++++++++++++++
+ arch/mips/pci/pci-lantiq.c | 24 ++----------------------
+ 3 files changed, 45 insertions(+), 22 deletions(-)
+ create mode 100644 arch/mips/pci/fixup-lantiq.c
+
+diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
+index afad91d..3ca5f75 100644
+--- a/arch/mips/pci/Makefile
++++ b/arch/mips/pci/Makefile
+@@ -40,6 +40,7 @@ obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o
+ obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o
+ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o
+ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o
++obj-$(CONFIG_LANTIQ) += fixup-lantiq.o
+ obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o
+ obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
+ obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
+diff --git a/arch/mips/pci/fixup-lantiq.c b/arch/mips/pci/fixup-lantiq.c
+new file mode 100644
+index 0000000..daf5ae9
+--- /dev/null
++++ b/arch/mips/pci/fixup-lantiq.c
+@@ -0,0 +1,42 @@
++/*
++ * 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.
++ *
++ * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
++ */
++
++#include <linux/of_irq.h>
++#include <linux/of_pci.h>
++
++int (*ltqpci_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin) = NULL;
++int (*ltqpci_plat_arch_init)(struct pci_dev *dev) = NULL;
++int (*ltqpci_plat_dev_init)(struct pci_dev *dev) = NULL;
++int *ltq_pci_irq_map;
++
++int pcibios_plat_dev_init(struct pci_dev *dev)
++{
++ if (ltqpci_plat_arch_init)
++ return ltqpci_plat_arch_init(dev);
++
++ if (ltqpci_plat_dev_init)
++ return ltqpci_plat_dev_init(dev);
++
++ return 0;
++}
++
++int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++ if (ltqpci_map_irq)
++ return ltqpci_map_irq(dev, slot, pin);
++ if (ltq_pci_irq_map[slot]) {
++ dev_info(&dev->dev, "SLOT:%d PIN:%d IRQ:%d\n", slot, pin, ltq_pci_irq_map[slot]);
++ return ltq_pci_irq_map[slot];
++ }
++ printk(KERN_ERR "lq_pci: trying to map irq for unknown slot %d\n",
++ slot);
++
++ return 0;
++}
++
++
+diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c
+index efcdd45..7a29738 100644
+--- a/arch/mips/pci/pci-lantiq.c
++++ b/arch/mips/pci/pci-lantiq.c
+@@ -93,16 +93,14 @@ static struct ltq_pci_gpio_map ltq_pci_gpio_map[] = {
+ { 37, 2, 0, "pci-req4" },
+ };
+
+-__iomem void *ltq_pci_mapped_cfg;
++__iomem void *ltq_pci_cfgbase;
+ static __iomem void *ltq_pci_membase;
+
+-int (*ltqpci_plat_dev_init)(struct pci_dev *dev) = NULL;
+-
+ /* Since the PCI REQ pins can be reused for other functionality, make it
+ possible to exclude those from interpretation by the PCI controller */
+ static int ltq_pci_req_mask = 0xf;
+
+-static int *ltq_pci_irq_map;
++extern int *ltq_pci_irq_map;
+
+ struct pci_ops ltq_pci_ops = {
+ .read = ltq_pci_read_config_dword,
+@@ -131,14 +129,6 @@ static struct pci_controller ltq_pci_controller = {
+ .io_offset = 0x00000000UL,
+ };
+
+-int pcibios_plat_dev_init(struct pci_dev *dev)
+-{
+- if (ltqpci_plat_dev_init)
+- return ltqpci_plat_dev_init(dev);
+-
+- return 0;
+-}
+-
+ static u32 ltq_calc_bar11mask(void)
+ {
+ u32 mem, bar11mask;
+@@ -256,16 +246,6 @@ static int __devinit ltq_pci_startup(struct device *dev)
+ return 0;
+ }
+
+-int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+-{
+- if (ltq_pci_irq_map[slot])
+- return ltq_pci_irq_map[slot];
+- printk(KERN_ERR "lq_pci: trying to map irq for unknown slot %d\n",
+- slot);
+-
+- return 0;
+-}
+-
+ static int __devinit ltq_pci_probe(struct platform_device *pdev)
+ {
+ struct ltq_pci_data *ltq_pci_data =
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0055-MIPS-lantiq-pcie-add-pcie-driver.patch b/target/linux/lantiq/patches-3.2/0055-MIPS-lantiq-pcie-add-pcie-driver.patch
new file mode 100644
index 0000000..85766a7
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0055-MIPS-lantiq-pcie-add-pcie-driver.patch
@@ -0,0 +1,3503 @@
+From a53d622001ae396d89c9abacb62f3c3c7fbd3c13 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Thu, 8 Mar 2012 15:57:33 +0100
+Subject: [PATCH 55/70] MIPS: lantiq: pcie: add pcie driver
+
+---
+ arch/mips/Kconfig | 1 +
+ arch/mips/lantiq/Kconfig | 4 -
+ arch/mips/lantiq/xway/Kconfig | 21 +
+ arch/mips/pci/Makefile | 2 +
+ arch/mips/pci/fixup-lantiq-pcie.c | 81 +++
+ arch/mips/pci/pci.c | 25 +
+ arch/mips/pci/pcie-lantiq-msi.c | 399 +++++++++++
+ arch/mips/pci/pcie-lantiq-phy.c | 408 ++++++++++++
+ arch/mips/pci/pcie-lantiq.c | 1146 ++++++++++++++++++++++++++++++++
+ arch/mips/pci/pcie-lantiq.h | 1305 +++++++++++++++++++++++++++++++++++++
+ 10 files changed, 3388 insertions(+), 4 deletions(-)
+ create mode 100644 arch/mips/pci/fixup-lantiq-pcie.c
+ create mode 100644 arch/mips/pci/pcie-lantiq-msi.c
+ create mode 100644 arch/mips/pci/pcie-lantiq-phy.c
+ create mode 100644 arch/mips/pci/pcie-lantiq.c
+ create mode 100644 arch/mips/pci/pcie-lantiq.h
+
+diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
+index 1b78cd7..bbaff9b 100644
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -2329,6 +2329,7 @@ config PCI_DOMAINS
+ bool
+
+ source "drivers/pci/Kconfig"
++source "drivers/pci/pcie/Kconfig"
+
+ #
+ # ISA support is now enabled via select. Too many systems still have the one
+diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
+index dde9fc6..d21d9d4 100644
+--- a/arch/mips/lantiq/Kconfig
++++ b/arch/mips/lantiq/Kconfig
+@@ -22,10 +22,6 @@ config SOC_FALCON
+
+ endchoice
+
+-config PCI_LANTIQ
+- bool "PCI Support"
+- depends on SOC_XWAY && PCI
+-
+ source "arch/mips/lantiq/xway/Kconfig"
+ source "arch/mips/lantiq/falcon/Kconfig"
+
+diff --git a/arch/mips/lantiq/xway/Kconfig b/arch/mips/lantiq/xway/Kconfig
+index 2b857de..54a51ff 100644
+--- a/arch/mips/lantiq/xway/Kconfig
++++ b/arch/mips/lantiq/xway/Kconfig
+@@ -8,6 +8,27 @@ config LANTIQ_MACH_EASY50712
+
+ endmenu
+
++choice
++ prompt "PCI"
++ default PCI_LANTIQ_NONE
++
++config PCI_LANTIQ_NONE
++ bool "None"
++
++config PCI_LANTIQ
++ bool "PCI Support"
++ depends on PCI
++
++config PCIE_LANTIQ
++ bool "PCIE Support"
++ select ARCH_SUPPORTS_MSI
++
++endchoice
++
++config PCIE_LANTIQ_MSI
++ bool
++ depends on PCIE_LANTIQ && PCI_MSI
++ default y
+ endif
+
+ if SOC_AMAZON_SE
+diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
+index 3ca5f75..3386888 100644
+--- a/arch/mips/pci/Makefile
++++ b/arch/mips/pci/Makefile
+@@ -42,6 +42,8 @@ obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o
+ obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o
+ obj-$(CONFIG_LANTIQ) += fixup-lantiq.o
+ obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o
++obj-$(CONFIG_PCIE_LANTIQ) += pcie-lantiq-phy.o pcie-lantiq.o fixup-lantiq-pcie.o
++obj-$(CONFIG_PCIE_LANTIQ_MSI) += pcie-lantiq-msi.o
+ obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
+ obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
+ obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
+diff --git a/arch/mips/pci/fixup-lantiq-pcie.c b/arch/mips/pci/fixup-lantiq-pcie.c
+new file mode 100644
+index 0000000..84517df
+--- /dev/null
++++ b/arch/mips/pci/fixup-lantiq-pcie.c
+@@ -0,0 +1,81 @@
++/******************************************************************************
++**
++** FILE NAME : ifxmips_fixup_pcie.c
++** PROJECT : IFX UEIP for VRX200
++** MODULES : PCIe
++**
++** DATE : 02 Mar 2009
++** AUTHOR : Lei Chuanhua
++** DESCRIPTION : PCIe Root Complex Driver
++** COPYRIGHT : Copyright (c) 2009
++** Infineon Technologies AG
++** Am Campeon 1-12, 85579 Neubiberg, Germany
++**
++** 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.
++** HISTORY
++** $Version $Date $Author $Comment
++** 0.0.1 17 Mar,2009 Lei Chuanhua Initial version
++*******************************************************************************/
++/*!
++ \file ifxmips_fixup_pcie.c
++ \ingroup IFX_PCIE
++ \brief PCIe Fixup functions source file
++*/
++#include <linux/pci.h>
++#include <linux/pci_regs.h>
++#include <linux/pci_ids.h>
++
++#include <lantiq_soc.h>
++
++#include "pcie-lantiq.h"
++
++#define PCI_VENDOR_ID_INFINEON 0x15D1
++#define PCI_DEVICE_ID_INFINEON_DANUBE 0x000F
++#define PCI_DEVICE_ID_INFINEON_PCIE 0x0011
++#define PCI_VENDOR_ID_LANTIQ 0x1BEF
++#define PCI_DEVICE_ID_LANTIQ_PCIE 0x0011
++
++
++
++static void __devinit
++ifx_pcie_fixup_resource(struct pci_dev *dev)
++{
++ u32 reg;
++
++ IFX_PCIE_PRINT(PCIE_MSG_FIXUP, "%s dev %s: enter\n", __func__, pci_name(dev));
++
++ IFX_PCIE_PRINT(PCIE_MSG_FIXUP, "%s: fixup host controller %s (%04x:%04x)\n",
++ __func__, pci_name(dev), dev->vendor, dev->device);
++
++ /* Setup COMMAND register */
++ reg = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER /* |
++ PCI_COMMAND_INTX_DISABLE */| PCI_COMMAND_SERR;
++ pci_write_config_word(dev, PCI_COMMAND, reg);
++ IFX_PCIE_PRINT(PCIE_MSG_FIXUP, "%s dev %s: exit\n", __func__, pci_name(dev));
++}
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INFINEON, PCI_DEVICE_ID_INFINEON_PCIE, ifx_pcie_fixup_resource);
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LANTIQ, PCI_VENDOR_ID_LANTIQ, ifx_pcie_fixup_resource);
++
++static void __devinit
++ifx_pcie_rc_class_early_fixup(struct pci_dev *dev)
++{
++ IFX_PCIE_PRINT(PCIE_MSG_FIXUP, "%s dev %s: enter\n", __func__, pci_name(dev));
++
++ if (dev->devfn == PCI_DEVFN(0, 0) &&
++ (dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) {
++
++ dev->class = (PCI_CLASS_BRIDGE_PCI << 8) | (dev->class & 0xff);
++
++ printk(KERN_INFO "%s: fixed pcie host bridge to pci-pci bridge\n", __func__);
++ }
++ IFX_PCIE_PRINT(PCIE_MSG_FIXUP, "%s dev %s: exit\n", __func__, pci_name(dev));
++}
++
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INFINEON, PCI_DEVICE_ID_INFINEON_PCIE,
++ ifx_pcie_rc_class_early_fixup);
++
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_LANTIQ, PCI_DEVICE_ID_LANTIQ_PCIE,
++ ifx_pcie_rc_class_early_fixup);
+diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
+index 41af7fa..2239cda 100644
+--- a/arch/mips/pci/pci.c
++++ b/arch/mips/pci/pci.c
+@@ -167,6 +167,31 @@ static int __init pcibios_init(void)
+
+ subsys_initcall(pcibios_init);
+
++int pcibios_host_nr(void)
++{
++ int count;
++ struct pci_controller *hose;
++ for (count = 0, hose = hose_head; hose; hose = hose->next, count++) {
++ ;
++ }
++ return count;
++}
++EXPORT_SYMBOL(pcibios_host_nr);
++
++int pcibios_1st_host_bus_nr(void)
++{
++ int bus_nr = 0;
++ struct pci_controller *hose = hose_head;
++
++ if (hose != NULL) {
++ if (hose->bus != NULL) {
++ bus_nr = hose->bus->subordinate + 1;
++ }
++ }
++ return bus_nr;
++}
++EXPORT_SYMBOL(pcibios_1st_host_bus_nr);
++
+ static int pcibios_enable_resources(struct pci_dev *dev, int mask)
+ {
+ u16 cmd, old_cmd;
+diff --git a/arch/mips/pci/pcie-lantiq-msi.c b/arch/mips/pci/pcie-lantiq-msi.c
+new file mode 100644
+index 0000000..9cbf639
+--- /dev/null
++++ b/arch/mips/pci/pcie-lantiq-msi.c
+@@ -0,0 +1,399 @@
++/******************************************************************************
++**
++** FILE NAME : ifxmips_pcie_msi.c
++** PROJECT : IFX UEIP for VRX200
++** MODULES : PCI MSI sub module
++**
++** DATE : 02 Mar 2009
++** AUTHOR : Lei Chuanhua
++** DESCRIPTION : PCIe MSI Driver
++** COPYRIGHT : Copyright (c) 2009
++** Infineon Technologies AG
++** Am Campeon 1-12, 85579 Neubiberg, Germany
++**
++** 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.
++** HISTORY
++** $Date $Author $Comment
++** 02 Mar,2009 Lei Chuanhua Initial version
++*******************************************************************************/
++/*!
++ \defgroup IFX_PCIE_MSI MSI OS APIs
++ \ingroup IFX_PCIE
++ \brief PCIe bus driver OS interface functions
++*/
++
++/*!
++ \file ifxmips_pcie_msi.c
++ \ingroup IFX_PCIE
++ \brief PCIe MSI OS interface file
++*/
++
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/kernel_stat.h>
++#include <linux/pci.h>
++#include <linux/msi.h>
++#include <linux/module.h>
++#include <asm/bootinfo.h>
++#include <asm/irq.h>
++#include <asm/traps.h>
++
++#include "pcie-lantiq.h"
++
++#define IFX_MSI_IRQ_NUM 16
++#define SM(_v, _f) (((_v) << _f##_S) & (_f))
++
++#define IFX_MSI_PIC_REG_BASE (KSEG1 | 0x1F700000)
++#define IFX_PCIE_MSI_IR0 (INT_NUM_IM4_IRL0 + 27)
++#define IFX_PCIE_MSI_IR1 (INT_NUM_IM4_IRL0 + 28)
++#define IFX_PCIE_MSI_IR2 (INT_NUM_IM4_IRL0 + 29)
++#define IFX_PCIE_MSI_IR3 (INT_NUM_IM0_IRL0 + 30)
++
++#define IFX_MSI_PCI_INT_DISABLE 0x80000000
++#define IFX_MSI_PIC_INT_LINE 0x30000000
++#define IFX_MSI_PIC_MSG_ADDR 0x0FFF0000
++#define IFX_MSI_PIC_MSG_DATA 0x0000FFFF
++#define IFX_MSI_PIC_BIG_ENDIAN 1
++#define IFX_MSI_PIC_INT_LINE_S 28
++#define IFX_MSI_PIC_MSG_ADDR_S 16
++#define IFX_MSI_PIC_MSG_DATA_S 0x0
++
++enum {
++ IFX_PCIE_MSI_IDX0 = 0,
++ IFX_PCIE_MSI_IDX1,
++ IFX_PCIE_MSI_IDX2,
++ IFX_PCIE_MSI_IDX3,
++};
++
++typedef struct ifx_msi_irq_idx {
++ const int irq;
++ const int idx;
++}ifx_msi_irq_idx_t;
++
++struct ifx_msi_pic {
++ volatile u32 pic_table[IFX_MSI_IRQ_NUM];
++ volatile u32 pic_endian; /* 0x40 */
++};
++typedef struct ifx_msi_pic *ifx_msi_pic_t;
++
++typedef struct ifx_msi_irq {
++ const volatile ifx_msi_pic_t msi_pic_p;
++ const u32 msi_phy_base;
++ const ifx_msi_irq_idx_t msi_irq_idx[IFX_MSI_IRQ_NUM];
++ /*
++ * Each bit in msi_free_irq_bitmask represents a MSI interrupt that is
++ * in use.
++ */
++ u16 msi_free_irq_bitmask;
++
++ /*
++ * Each bit in msi_multiple_irq_bitmask tells that the device using
++ * this bit in msi_free_irq_bitmask is also using the next bit. This
++ * is used so we can disable all of the MSI interrupts when a device
++ * uses multiple.
++ */
++ u16 msi_multiple_irq_bitmask;
++}ifx_msi_irq_t;
++
++static ifx_msi_irq_t msi_irqs[IFX_PCIE_CORE_NR] = {
++ {
++ .msi_pic_p = (const volatile ifx_msi_pic_t)IFX_MSI_PIC_REG_BASE,
++ .msi_phy_base = PCIE_MSI_PHY_BASE,
++ .msi_irq_idx = {
++ {IFX_PCIE_MSI_IR0, IFX_PCIE_MSI_IDX0}, {IFX_PCIE_MSI_IR1, IFX_PCIE_MSI_IDX1},
++ {IFX_PCIE_MSI_IR2, IFX_PCIE_MSI_IDX2}, {IFX_PCIE_MSI_IR3, IFX_PCIE_MSI_IDX3},
++ {IFX_PCIE_MSI_IR0, IFX_PCIE_MSI_IDX0}, {IFX_PCIE_MSI_IR1, IFX_PCIE_MSI_IDX1},
++ {IFX_PCIE_MSI_IR2, IFX_PCIE_MSI_IDX2}, {IFX_PCIE_MSI_IR3, IFX_PCIE_MSI_IDX3},
++ {IFX_PCIE_MSI_IR0, IFX_PCIE_MSI_IDX0}, {IFX_PCIE_MSI_IR1, IFX_PCIE_MSI_IDX1},
++ {IFX_PCIE_MSI_IR2, IFX_PCIE_MSI_IDX2}, {IFX_PCIE_MSI_IR3, IFX_PCIE_MSI_IDX3},
++ {IFX_PCIE_MSI_IR0, IFX_PCIE_MSI_IDX0}, {IFX_PCIE_MSI_IR1, IFX_PCIE_MSI_IDX1},
++ {IFX_PCIE_MSI_IR2, IFX_PCIE_MSI_IDX2}, {IFX_PCIE_MSI_IR3, IFX_PCIE_MSI_IDX3},
++ },
++ .msi_free_irq_bitmask = 0,
++ .msi_multiple_irq_bitmask= 0,
++ },
++#ifdef CONFIG_IFX_PCIE_2ND_CORE
++ {
++ .msi_pic_p = (const volatile ifx_msi_pic_t)IFX_MSI1_PIC_REG_BASE,
++ .msi_phy_base = PCIE1_MSI_PHY_BASE,
++ .msi_irq_idx = {
++ {IFX_PCIE1_MSI_IR0, IFX_PCIE_MSI_IDX0}, {IFX_PCIE1_MSI_IR1, IFX_PCIE_MSI_IDX1},
++ {IFX_PCIE1_MSI_IR2, IFX_PCIE_MSI_IDX2}, {IFX_PCIE1_MSI_IR3, IFX_PCIE_MSI_IDX3},
++ {IFX_PCIE1_MSI_IR0, IFX_PCIE_MSI_IDX0}, {IFX_PCIE1_MSI_IR1, IFX_PCIE_MSI_IDX1},
++ {IFX_PCIE1_MSI_IR2, IFX_PCIE_MSI_IDX2}, {IFX_PCIE1_MSI_IR3, IFX_PCIE_MSI_IDX3},
++ {IFX_PCIE1_MSI_IR0, IFX_PCIE_MSI_IDX0}, {IFX_PCIE1_MSI_IR1, IFX_PCIE_MSI_IDX1},
++ {IFX_PCIE1_MSI_IR2, IFX_PCIE_MSI_IDX2}, {IFX_PCIE1_MSI_IR3, IFX_PCIE_MSI_IDX3},
++ {IFX_PCIE1_MSI_IR0, IFX_PCIE_MSI_IDX0}, {IFX_PCIE1_MSI_IR1, IFX_PCIE_MSI_IDX1},
++ {IFX_PCIE1_MSI_IR2, IFX_PCIE_MSI_IDX2}, {IFX_PCIE1_MSI_IR3, IFX_PCIE_MSI_IDX3},
++ },
++ .msi_free_irq_bitmask = 0,
++ .msi_multiple_irq_bitmask= 0,
++
++ },
++#endif /* CONFIG_IFX_PCIE_2ND_CORE */
++};
++
++/*
++ * This lock controls updates to msi_free_irq_bitmask,
++ * msi_multiple_irq_bitmask and pic register settting
++ */
++static DEFINE_SPINLOCK(ifx_pcie_msi_lock);
++
++void pcie_msi_pic_init(int pcie_port)
++{
++ spin_lock(&ifx_pcie_msi_lock);
++ msi_irqs[pcie_port].msi_pic_p->pic_endian = IFX_MSI_PIC_BIG_ENDIAN;
++ spin_unlock(&ifx_pcie_msi_lock);
++}
++
++/**
++ * \fn int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
++ * \brief Called when a driver request MSI interrupts instead of the
++ * legacy INT A-D. This routine will allocate multiple interrupts
++ * for MSI devices that support them. A device can override this by
++ * programming the MSI control bits [6:4] before calling
++ * pci_enable_msi().
++ *
++ * \param[in] pdev Device requesting MSI interrupts
++ * \param[in] desc MSI descriptor
++ *
++ * \return -EINVAL Invalid pcie root port or invalid msi bit
++ * \return 0 OK
++ * \ingroup IFX_PCIE_MSI
++ */
++int
++arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
++{
++ int irq, pos;
++ u16 control;
++ int irq_idx;
++ int irq_step;
++ int configured_private_bits;
++ int request_private_bits;
++ struct msi_msg msg;
++ u16 search_mask;
++ struct ifx_pci_controller *ctrl = pdev->bus->sysdata;
++ int pcie_port = ctrl->port;
++
++ IFX_PCIE_PRINT(PCIE_MSG_MSI, "%s %s enter\n", __func__, pci_name(pdev));
++
++ /* XXX, skip RC MSI itself */
++ if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT) {
++ IFX_PCIE_PRINT(PCIE_MSG_MSI, "%s RC itself doesn't use MSI interrupt\n", __func__);
++ return -EINVAL;
++ }
++
++ /*
++ * Read the MSI config to figure out how many IRQs this device
++ * wants. Most devices only want 1, which will give
++ * configured_private_bits and request_private_bits equal 0.
++ */
++ pci_read_config_word(pdev, desc->msi_attrib.pos + PCI_MSI_FLAGS, &control);
++
++ /*
++ * If the number of private bits has been configured then use
++ * that value instead of the requested number. This gives the
++ * driver the chance to override the number of interrupts
++ * before calling pci_enable_msi().
++ */
++ configured_private_bits = (control & PCI_MSI_FLAGS_QSIZE) >> 4;
++ if (configured_private_bits == 0) {
++ /* Nothing is configured, so use the hardware requested size */
++ request_private_bits = (control & PCI_MSI_FLAGS_QMASK) >> 1;
++ }
++ else {
++ /*
++ * Use the number of configured bits, assuming the
++ * driver wanted to override the hardware request
++ * value.
++ */
++ request_private_bits = configured_private_bits;
++ }
++
++ /*
++ * The PCI 2.3 spec mandates that there are at most 32
++ * interrupts. If this device asks for more, only give it one.
++ */
++ if (request_private_bits > 5) {
++ request_private_bits = 0;
++ }
++again:
++ /*
++ * The IRQs have to be aligned on a power of two based on the
++ * number being requested.
++ */
++ irq_step = (1 << request_private_bits);
++
++ /* Mask with one bit for each IRQ */
++ search_mask = (1 << irq_step) - 1;
++
++ /*
++ * We're going to search msi_free_irq_bitmask_lock for zero
++ * bits. This represents an MSI interrupt number that isn't in
++ * use.
++ */
++ spin_lock(&ifx_pcie_msi_lock);
++ for (pos = 0; pos < IFX_MSI_IRQ_NUM; pos += irq_step) {
++ if ((msi_irqs[pcie_port].msi_free_irq_bitmask & (search_mask << pos)) == 0) {
++ msi_irqs[pcie_port].msi_free_irq_bitmask |= search_mask << pos;
++ msi_irqs[pcie_port].msi_multiple_irq_bitmask |= (search_mask >> 1) << pos;
++ break;
++ }
++ }
++ spin_unlock(&ifx_pcie_msi_lock);
++
++ /* Make sure the search for available interrupts didn't fail */
++ if (pos >= IFX_MSI_IRQ_NUM) {
++ if (request_private_bits) {
++ IFX_PCIE_PRINT(PCIE_MSG_MSI, "%s: Unable to find %d free "
++ "interrupts, trying just one", __func__, 1 << request_private_bits);
++ request_private_bits = 0;
++ goto again;
++ }
++ else {
++ printk(KERN_ERR "%s: Unable to find a free MSI interrupt\n", __func__);
++ return -EINVAL;
++ }
++ }
++ irq = msi_irqs[pcie_port].msi_irq_idx[pos].irq;
++ irq_idx = msi_irqs[pcie_port].msi_irq_idx[pos].idx;
++
++ IFX_PCIE_PRINT(PCIE_MSG_MSI, "pos %d, irq %d irq_idx %d\n", pos, irq, irq_idx);
++
++ /*
++ * Initialize MSI. This has to match the memory-write endianess from the device
++ * Address bits [23:12]
++ */
++ spin_lock(&ifx_pcie_msi_lock);
++ msi_irqs[pcie_port].msi_pic_p->pic_table[pos] = SM(irq_idx, IFX_MSI_PIC_INT_LINE) |
++ SM((msi_irqs[pcie_port].msi_phy_base >> 12), IFX_MSI_PIC_MSG_ADDR) |
++ SM((1 << pos), IFX_MSI_PIC_MSG_DATA);
++
++ /* Enable this entry */
++ msi_irqs[pcie_port].msi_pic_p->pic_table[pos] &= ~IFX_MSI_PCI_INT_DISABLE;
++ spin_unlock(&ifx_pcie_msi_lock);
++
++ IFX_PCIE_PRINT(PCIE_MSG_MSI, "pic_table[%d]: 0x%08x\n",
++ pos, msi_irqs[pcie_port].msi_pic_p->pic_table[pos]);
++
++ /* Update the number of IRQs the device has available to it */
++ control &= ~PCI_MSI_FLAGS_QSIZE;
++ control |= (request_private_bits << 4);
++ pci_write_config_word(pdev, desc->msi_attrib.pos + PCI_MSI_FLAGS, control);
++
++ irq_set_msi_desc(irq, desc);
++ msg.address_hi = 0x0;
++ msg.address_lo = msi_irqs[pcie_port].msi_phy_base;
++ msg.data = SM((1 << pos), IFX_MSI_PIC_MSG_DATA);
++ IFX_PCIE_PRINT(PCIE_MSG_MSI, "msi_data: pos %d 0x%08x\n", pos, msg.data);
++
++ write_msi_msg(irq, &msg);
++ IFX_PCIE_PRINT(PCIE_MSG_MSI, "%s exit\n", __func__);
++ return 0;
++}
++
++static int
++pcie_msi_irq_to_port(unsigned int irq, int *port)
++{
++ int ret = 0;
++
++ if (irq == IFX_PCIE_MSI_IR0 || irq == IFX_PCIE_MSI_IR1 ||
++ irq == IFX_PCIE_MSI_IR2 || irq == IFX_PCIE_MSI_IR3) {
++ *port = IFX_PCIE_PORT0;
++ }
++#ifdef CONFIG_IFX_PCIE_2ND_CORE
++ else if (irq == IFX_PCIE1_MSI_IR0 || irq == IFX_PCIE1_MSI_IR1 ||
++ irq == IFX_PCIE1_MSI_IR2 || irq == IFX_PCIE1_MSI_IR3) {
++ *port = IFX_PCIE_PORT1;
++ }
++#endif /* CONFIG_IFX_PCIE_2ND_CORE */
++ else {
++ printk(KERN_ERR "%s: Attempted to teardown illegal "
++ "MSI interrupt (%d)\n", __func__, irq);
++ ret = -EINVAL;
++ }
++ return ret;
++}
++
++/**
++ * \fn void arch_teardown_msi_irq(unsigned int irq)
++ * \brief Called when a device no longer needs its MSI interrupts. All
++ * MSI interrupts for the device are freed.
++ *
++ * \param irq The devices first irq number. There may be multple in sequence.
++ * \return none
++ * \ingroup IFX_PCIE_MSI
++ */
++void
++arch_teardown_msi_irq(unsigned int irq)
++{
++ int pos;
++ int number_irqs;
++ u16 bitmask;
++ int pcie_port;
++
++ IFX_PCIE_PRINT(PCIE_MSG_MSI, "%s enter\n", __func__);
++
++ BUG_ON(irq > (INT_NUM_IM4_IRL0 + 31));
++
++ if (pcie_msi_irq_to_port(irq, &pcie_port) != 0) {
++ return;
++ }
++
++ /* Shift the mask to the correct bit location, not always correct
++ * Probally, the first match will be chosen.
++ */
++ for (pos = 0; pos < IFX_MSI_IRQ_NUM; pos++) {
++ if ((msi_irqs[pcie_port].msi_irq_idx[pos].irq == irq)
++ && (msi_irqs[pcie_port].msi_free_irq_bitmask & ( 1 << pos))) {
++ break;
++ }
++ }
++ if (pos >= IFX_MSI_IRQ_NUM) {
++ printk(KERN_ERR "%s: Unable to find a matched MSI interrupt\n", __func__);
++ return;
++ }
++ spin_lock(&ifx_pcie_msi_lock);
++ /* Disable this entry */
++ msi_irqs[pcie_port].msi_pic_p->pic_table[pos] |= IFX_MSI_PCI_INT_DISABLE;
++ msi_irqs[pcie_port].msi_pic_p->pic_table[pos] &= ~(IFX_MSI_PIC_INT_LINE | IFX_MSI_PIC_MSG_ADDR | IFX_MSI_PIC_MSG_DATA);
++ spin_unlock(&ifx_pcie_msi_lock);
++ /*
++ * Count the number of IRQs we need to free by looking at the
++ * msi_multiple_irq_bitmask. Each bit set means that the next
++ * IRQ is also owned by this device.
++ */
++ number_irqs = 0;
++ while (((pos + number_irqs) < IFX_MSI_IRQ_NUM) &&
++ (msi_irqs[pcie_port].msi_multiple_irq_bitmask & (1 << (pos + number_irqs)))) {
++ number_irqs++;
++ }
++ number_irqs++;
++
++ /* Mask with one bit for each IRQ */
++ bitmask = (1 << number_irqs) - 1;
++
++ bitmask <<= pos;
++ if ((msi_irqs[pcie_port].msi_free_irq_bitmask & bitmask) != bitmask) {
++ printk(KERN_ERR "%s: Attempted to teardown MSI "
++ "interrupt (%d) not in use\n", __func__, irq);
++ return;
++ }
++ /* Checks are done, update the in use bitmask */
++ spin_lock(&ifx_pcie_msi_lock);
++ msi_irqs[pcie_port].msi_free_irq_bitmask &= ~bitmask;
++ msi_irqs[pcie_port].msi_multiple_irq_bitmask &= ~(bitmask >> 1);
++ spin_unlock(&ifx_pcie_msi_lock);
++ IFX_PCIE_PRINT(PCIE_MSG_MSI, "%s exit\n", __func__);
++}
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Chuanhua.Lei@infineon.com");
++MODULE_SUPPORTED_DEVICE("Infineon PCIe IP builtin MSI PIC module");
++MODULE_DESCRIPTION("Infineon PCIe IP builtin MSI PIC driver");
++
+diff --git a/arch/mips/pci/pcie-lantiq-phy.c b/arch/mips/pci/pcie-lantiq-phy.c
+new file mode 100644
+index 0000000..9f5027d
+--- /dev/null
++++ b/arch/mips/pci/pcie-lantiq-phy.c
+@@ -0,0 +1,408 @@
++/******************************************************************************
++**
++** FILE NAME : ifxmips_pcie_phy.c
++** PROJECT : IFX UEIP for VRX200
++** MODULES : PCIe PHY sub module
++**
++** DATE : 14 May 2009
++** AUTHOR : Lei Chuanhua
++** DESCRIPTION : PCIe Root Complex Driver
++** COPYRIGHT : Copyright (c) 2009
++** Infineon Technologies AG
++** Am Campeon 1-12, 85579 Neubiberg, Germany
++**
++** 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.
++** HISTORY
++** $Version $Date $Author $Comment
++** 0.0.1 14 May,2009 Lei Chuanhua Initial version
++*******************************************************************************/
++/*!
++ \file ifxmips_pcie_phy.c
++ \ingroup IFX_PCIE
++ \brief PCIe PHY PLL register programming source file
++*/
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <asm/paccess.h>
++#include <linux/delay.h>
++
++#include "pcie-lantiq.h"
++
++/* PCIe PDI only supports 16 bit operation */
++
++#define IFX_PCIE_PHY_REG_WRITE16(__addr, __data) \
++ ((*(volatile u16 *) (__addr)) = (__data))
++
++#define IFX_PCIE_PHY_REG_READ16(__addr) \
++ (*(volatile u16 *) (__addr))
++
++#define IFX_PCIE_PHY_REG16(__addr) \
++ (*(volatile u16 *) (__addr))
++
++#define IFX_PCIE_PHY_REG(__reg, __value, __mask) do { \
++ u16 read_data; \
++ u16 write_data; \
++ read_data = IFX_PCIE_PHY_REG_READ16((__reg)); \
++ write_data = (read_data & ((u16)~(__mask))) | (((u16)(__value)) & ((u16)(__mask)));\
++ IFX_PCIE_PHY_REG_WRITE16((__reg), write_data); \
++} while (0)
++
++#define IFX_PCIE_PLL_TIMEOUT 1000 /* Tunnable */
++
++static void
++pcie_phy_comm_setup(int pcie_port)
++{
++ /* PLL Setting */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL1(pcie_port), 0x120e, 0xFFFF);
++
++ /* increase the bias reference voltage */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL2(pcie_port), 0x39D7, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL3(pcie_port), 0x0900, 0xFFFF);
++
++ /* Endcnt */
++ IFX_PCIE_PHY_REG(PCIE_PHY_RX1_EI(pcie_port), 0x0004, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_RX1_A_CTRL(pcie_port), 0x6803, 0xFFFF);
++
++ /* force */
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL1(pcie_port), 0x0008, 0x0008);
++
++ /* predrv_ser_en */
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_A_CTRL2(pcie_port), 0x0706, 0xFFFF);
++
++ /* ctrl_lim */
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL3(pcie_port), 0x1FFF, 0xFFFF);
++
++ /* ctrl */
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_A_CTRL1(pcie_port), 0x0800, 0xFF00);
++
++ /* predrv_ser_en */
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX2_A_CTRL2(pcie_port), 0x4702, 0x7F00);
++
++ /* RTERM*/
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL2(pcie_port), 0x2e00, 0xFFFF);
++
++ /* Improved 100MHz clock output */
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX2_CTRL2(pcie_port), 0x3096, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX2_A_CTRL2(pcie_port), 0x4707, 0xFFFF);
++
++ /* Reduced CDR BW to avoid glitches */
++ IFX_PCIE_PHY_REG(PCIE_PHY_RX1_CDR(pcie_port), 0x0235, 0xFFFF);
++}
++
++#ifdef CONFIG_IFX_PCIE_PHY_36MHZ_MODE
++static void
++pcie_phy_36mhz_mode_setup(int pcie_port)
++{
++ IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d enter\n", __func__, pcie_port);
++
++ /* en_ext_mmd_div_ratio */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0000, 0x0002);
++
++ /* ext_mmd_div_ratio*/
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0000, 0x0070);
++
++ /* pll_ensdm */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0200, 0x0200);
++
++ /* en_const_sdm */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0100, 0x0100);
++
++ /* mmd */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL3(pcie_port), 0x2000, 0xe000);
++
++ /* lf_mode */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL2(pcie_port), 0x0000, 0x4000);
++
++ /* const_sdm */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL1(pcie_port), 0x38e4, 0xFFFF);
++
++ /* const sdm */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x00ee, 0x00FF);
++
++ /* pllmod */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL7(pcie_port), 0x0002, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL6(pcie_port), 0x3a04, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL5(pcie_port), 0xfae3, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL4(pcie_port), 0x1b72, 0xFFFF);
++
++ IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d exit\n", __func__, pcie_port);
++}
++#endif /* CONFIG_IFX_PCIE_PHY_36MHZ_MODE */
++
++#ifdef CONFIG_IFX_PCIE_PHY_36MHZ_SSC_MODE
++static void
++pcie_phy_36mhz_ssc_mode_setup(int pcie_port)
++{
++ IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d enter\n", __func__, pcie_port);
++
++ /* PLL Setting */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL1(pcie_port), 0x120e, 0xFFFF);
++
++ /* Increase the bias reference voltage */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL2(pcie_port), 0x39D7, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL3(pcie_port), 0x0900, 0xFFFF);
++
++ /* Endcnt */
++ IFX_PCIE_PHY_REG(PCIE_PHY_RX1_EI(pcie_port), 0x0004, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_RX1_A_CTRL(pcie_port), 0x6803, 0xFFFF);
++
++ /* Force */
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL1(pcie_port), 0x0008, 0x0008);
++
++ /* Predrv_ser_en */
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_A_CTRL2(pcie_port), 0x0706, 0xFFFF);
++
++ /* ctrl_lim */
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL3(pcie_port), 0x1FFF, 0xFFFF);
++
++ /* ctrl */
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_A_CTRL1(pcie_port), 0x0800, 0xFF00);
++
++ /* predrv_ser_en */
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX2_A_CTRL2(pcie_port), 0x4702, 0x7F00);
++
++ /* RTERM*/
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL2(pcie_port), 0x2e00, 0xFFFF);
++
++ /* en_ext_mmd_div_ratio */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0000, 0x0002);
++
++ /* ext_mmd_div_ratio*/
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0000, 0x0070);
++
++ /* pll_ensdm */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0400, 0x0400);
++
++ /* en_const_sdm */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0200, 0x0200);
++
++ /* mmd */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL3(pcie_port), 0x2000, 0xe000);
++
++ /* lf_mode */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL2(pcie_port), 0x0000, 0x4000);
++
++ /* const_sdm */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL1(pcie_port), 0x38e4, 0xFFFF);
++
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0000, 0x0100);
++ /* const sdm */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x00ee, 0x00FF);
++
++ /* pllmod */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL7(pcie_port), 0x0002, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL6(pcie_port), 0x3a04, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL5(pcie_port), 0xfae3, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL4(pcie_port), 0x1c72, 0xFFFF);
++
++ /* improved 100MHz clock output */
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX2_CTRL2(pcie_port), 0x3096, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX2_A_CTRL2(pcie_port), 0x4707, 0xFFFF);
++
++ /* reduced CDR BW to avoid glitches */
++ IFX_PCIE_PHY_REG(PCIE_PHY_RX1_CDR(pcie_port), 0x0235, 0xFFFF);
++
++ IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d exit\n", __func__, pcie_port);
++}
++#endif /* CONFIG_IFX_PCIE_PHY_36MHZ_SSC_MODE */
++
++#ifdef CONFIG_IFX_PCIE_PHY_25MHZ_MODE
++static void
++pcie_phy_25mhz_mode_setup(int pcie_port)
++{
++ IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d enter\n", __func__, pcie_port);
++ /* en_const_sdm */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0100, 0x0100);
++
++ /* pll_ensdm */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0000, 0x0200);
++
++ /* en_ext_mmd_div_ratio*/
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0002, 0x0002);
++
++ /* ext_mmd_div_ratio*/
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0040, 0x0070);
++
++ /* mmd */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL3(pcie_port), 0x6000, 0xe000);
++
++ /* lf_mode */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL2(pcie_port), 0x4000, 0x4000);
++
++ IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d exit\n", __func__, pcie_port);
++}
++#endif /* CONFIG_IFX_PCIE_PHY_25MHZ_MODE */
++
++#ifdef CONFIG_IFX_PCIE_PHY_100MHZ_MODE
++static void
++pcie_phy_100mhz_mode_setup(int pcie_port)
++{
++ IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d enter\n", __func__, pcie_port);
++ /* en_ext_mmd_div_ratio */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0000, 0x0002);
++
++ /* ext_mmd_div_ratio*/
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL3(pcie_port), 0x0000, 0x0070);
++
++ /* pll_ensdm */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0200, 0x0200);
++
++ /* en_const_sdm */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x0100, 0x0100);
++
++ /* mmd */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL3(pcie_port), 0x2000, 0xe000);
++
++ /* lf_mode */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_A_CTRL2(pcie_port), 0x0000, 0x4000);
++
++ /* const_sdm */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL1(pcie_port), 0x38e4, 0xFFFF);
++
++ /* const sdm */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL2(pcie_port), 0x00ee, 0x00FF);
++
++ /* pllmod */
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL7(pcie_port), 0x0002, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL6(pcie_port), 0x3a04, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL5(pcie_port), 0xfae3, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_PLL_CTRL4(pcie_port), 0x1b72, 0xFFFF);
++
++ IFX_PCIE_PRINT(PCIE_MSG_PHY, "%s pcie_port %d exit\n", __func__, pcie_port);
++}
++#endif /* CONFIG_IFX_PCIE_PHY_100MHZ_MODE */
++
++static int
++pcie_phy_wait_startup_ready(int pcie_port)
++{
++ int i;
++
++ for (i = 0; i < IFX_PCIE_PLL_TIMEOUT; i++) {
++ if ((IFX_PCIE_PHY_REG16(PCIE_PHY_PLL_STATUS(pcie_port)) & 0x0040) != 0) {
++ break;
++ }
++ udelay(10);
++ }
++ if (i >= IFX_PCIE_PLL_TIMEOUT) {
++ printk(KERN_ERR "%s PLL Link timeout\n", __func__);
++ return -1;
++ }
++ return 0;
++}
++
++static void
++pcie_phy_load_enable(int pcie_port, int slice)
++{
++ /* Set the load_en of tx/rx slice to '1' */
++ switch (slice) {
++ case 1:
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL1(pcie_port), 0x0010, 0x0010);
++ break;
++ case 2:
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX2_CTRL1(pcie_port), 0x0010, 0x0010);
++ break;
++ case 3:
++ IFX_PCIE_PHY_REG(PCIE_PHY_RX1_CTRL1(pcie_port), 0x0002, 0x0002);
++ break;
++ }
++}
++
++static void
++pcie_phy_load_disable(int pcie_port, int slice)
++{
++ /* set the load_en of tx/rx slice to '0' */
++ switch (slice) {
++ case 1:
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_CTRL1(pcie_port), 0x0000, 0x0010);
++ break;
++ case 2:
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX2_CTRL1(pcie_port), 0x0000, 0x0010);
++ break;
++ case 3:
++ IFX_PCIE_PHY_REG(PCIE_PHY_RX1_CTRL1(pcie_port), 0x0000, 0x0002);
++ break;
++ }
++}
++
++static void pcie_phy_load_war(int pcie_port)
++{
++ int slice;
++
++ for (slice = 1; slice < 4; slice++) {
++ pcie_phy_load_enable(pcie_port, slice);
++ udelay(1);
++ pcie_phy_load_disable(pcie_port, slice);
++ }
++}
++
++static void pcie_phy_tx2_modulation(int pcie_port)
++{
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX2_MOD1(pcie_port), 0x1FFE, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX2_MOD2(pcie_port), 0xFFFE, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX2_MOD3(pcie_port), 0x0601, 0xFFFF);
++ mdelay(1);
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX2_MOD3(pcie_port), 0x0001, 0xFFFF);
++}
++
++static void pcie_phy_tx1_modulation(int pcie_port)
++{
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_MOD1(pcie_port), 0x1FFE, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_MOD2(pcie_port), 0xFFFE, 0xFFFF);
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_MOD3(pcie_port), 0x0601, 0xFFFF);
++ mdelay(1);
++ IFX_PCIE_PHY_REG(PCIE_PHY_TX1_MOD3(pcie_port), 0x0001, 0xFFFF);
++}
++
++static void pcie_phy_tx_modulation_war(int pcie_port)
++{
++ int i;
++#define PCIE_PHY_MODULATION_NUM 5
++ for (i = 0; i < PCIE_PHY_MODULATION_NUM; i++) {
++ pcie_phy_tx2_modulation(pcie_port);
++ pcie_phy_tx1_modulation(pcie_port);
++ }
++#undef PCIE_PHY_MODULATION_NUM
++}
++
++void pcie_phy_clock_mode_setup(int pcie_port)
++{
++ pcie_pdi_big_endian(pcie_port);
++
++ /* Enable PDI to access PCIe PHY register */
++ pcie_pdi_pmu_enable(pcie_port);
++
++ /* Configure PLL and PHY clock */
++ pcie_phy_comm_setup(pcie_port);
++
++#ifdef CONFIG_IFX_PCIE_PHY_36MHZ_MODE
++ pcie_phy_36mhz_mode_setup(pcie_port);
++#elif defined(CONFIG_IFX_PCIE_PHY_36MHZ_SSC_MODE)
++ pcie_phy_36mhz_ssc_mode_setup(pcie_port);
++#elif defined(CONFIG_IFX_PCIE_PHY_25MHZ_MODE)
++ pcie_phy_25mhz_mode_setup(pcie_port);
++#elif defined (CONFIG_IFX_PCIE_PHY_100MHZ_MODE)
++ pcie_phy_100mhz_mode_setup(pcie_port);
++#else
++ #error "PCIE PHY Clock Mode must be chosen first!!!!"
++#endif /* CONFIG_IFX_PCIE_PHY_36MHZ_MODE */
++
++ /* Enable PCIe PHY and make PLL setting take effect */
++ pcie_phy_pmu_enable(pcie_port);
++
++ /* Check if we are in startup_ready status */
++ pcie_phy_wait_startup_ready(pcie_port);
++
++ pcie_phy_load_war(pcie_port);
++
++ /* Apply TX modulation workarounds */
++ pcie_phy_tx_modulation_war(pcie_port);
++
++#ifdef IFX_PCI_PHY_REG_DUMP
++ IFX_PCIE_PRINT(PCIE_MSG_PHY, "Modified PHY register dump\n");
++ pcie_phy_reg_dump(pcie_port);
++#endif
++}
++
+diff --git a/arch/mips/pci/pcie-lantiq.c b/arch/mips/pci/pcie-lantiq.c
+new file mode 100644
+index 0000000..1df55b5
+--- /dev/null
++++ b/arch/mips/pci/pcie-lantiq.c
+@@ -0,0 +1,1146 @@
++#include <linux/types.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/mm.h>
++#include <asm/paccess.h>
++#include <linux/pci.h>
++#include <linux/pci_regs.h>
++#include <linux/platform_device.h>
++
++#define CONFIG_IFX_PCIE_1ST_CORE
++
++#include "pcie-lantiq.h"
++
++#define IFX_PCIE_IR (INT_NUM_IM4_IRL0 + 25)
++#define IFX_PCIE_INTA (INT_NUM_IM4_IRL0 + 8)
++#define IFX_PCIE_INTB (INT_NUM_IM4_IRL0 + 9)
++#define IFX_PCIE_INTC (INT_NUM_IM4_IRL0 + 10)
++#define IFX_PCIE_INTD (INT_NUM_IM4_IRL0 + 11)
++#define MS(_v, _f) (((_v) & (_f)) >> _f##_S)
++#define SM(_v, _f) (((_v) << _f##_S) & (_f))
++#define IFX_REG_SET_BIT(_f, _r) \
++ IFX_REG_W32((IFX_REG_R32((_r)) &~ (_f)) | (_f), (_r))
++#define IFX_PCIE_LTSSM_ENABLE_TIMEOUT 10
++#define IFX_PCIE_PHY_LINK_UP_TIMEOUT 1000
++#define IFX_PCIE_PHY_LOOP_CNT 5
++
++static DEFINE_SPINLOCK(ifx_pcie_lock);
++
++int pcibios_1st_host_bus_nr(void);
++
++unsigned int g_pcie_debug_flag = PCIE_MSG_ANY & (~PCIE_MSG_CFG);
++
++static ifx_pcie_irq_t pcie_irqs[IFX_PCIE_CORE_NR] = {
++ {
++ .ir_irq = {
++ .irq = IFX_PCIE_IR,
++ .name = "ifx_pcie_rc0",
++ },
++
++ .legacy_irq = {
++ {
++ .irq_bit = PCIE_IRN_INTA,
++ .irq = IFX_PCIE_INTA,
++ },
++ {
++ .irq_bit = PCIE_IRN_INTB,
++ .irq = IFX_PCIE_INTB,
++ },
++ {
++ .irq_bit = PCIE_IRN_INTC,
++ .irq = IFX_PCIE_INTC,
++ },
++ {
++ .irq_bit = PCIE_IRN_INTD,
++ .irq = IFX_PCIE_INTD,
++ },
++ },
++ },
++};
++
++static inline int pcie_ltssm_enable(int pcie_port)
++{
++ int i;
++
++ IFX_REG_W32(PCIE_RC_CCR_LTSSM_ENABLE, PCIE_RC_CCR(pcie_port)); /* Enable LTSSM */
++
++ /* Wait for the link to come up */
++ for (i = 0; i < IFX_PCIE_LTSSM_ENABLE_TIMEOUT; i++) {
++ if (!(IFX_REG_R32(PCIE_LCTLSTS(pcie_port)) & PCIE_LCTLSTS_RETRAIN_PENDING)) {
++ break;
++ }
++ udelay(10);
++ }
++ if (i >= IFX_PCIE_LTSSM_ENABLE_TIMEOUT) {
++ IFX_PCIE_PRINT(PCIE_MSG_INIT, "%s link timeout!!!!!\n", __func__);
++ return -1;
++ }
++ return 0;
++}
++
++static inline void pcie_status_register_clear(int pcie_port)
++{
++ IFX_REG_W32(0, PCIE_RC_DR(pcie_port));
++ IFX_REG_W32(0, PCIE_PCICMDSTS(pcie_port));
++ IFX_REG_W32(0, PCIE_DCTLSTS(pcie_port));
++ IFX_REG_W32(0, PCIE_LCTLSTS(pcie_port));
++ IFX_REG_W32(0, PCIE_SLCTLSTS(pcie_port));
++ IFX_REG_W32(0, PCIE_RSTS(pcie_port));
++ IFX_REG_W32(0, PCIE_UES_R(pcie_port));
++ IFX_REG_W32(0, PCIE_UEMR(pcie_port));
++ IFX_REG_W32(0, PCIE_UESR(pcie_port));
++ IFX_REG_W32(0, PCIE_CESR(pcie_port));
++ IFX_REG_W32(0, PCIE_CEMR(pcie_port));
++ IFX_REG_W32(0, PCIE_RESR(pcie_port));
++ IFX_REG_W32(0, PCIE_PVCCRSR(pcie_port));
++ IFX_REG_W32(0, PCIE_VC0_RSR0(pcie_port));
++ IFX_REG_W32(0, PCIE_TPFCS(pcie_port));
++ IFX_REG_W32(0, PCIE_TNPFCS(pcie_port));
++ IFX_REG_W32(0, PCIE_TCFCS(pcie_port));
++ IFX_REG_W32(0, PCIE_QSR(pcie_port));
++ IFX_REG_W32(0, PCIE_IOBLSECS(pcie_port));
++}
++
++static inline int ifx_pcie_link_up(int pcie_port)
++{
++ return (IFX_REG_R32(PCIE_PHY_SR(pcie_port)) & PCIE_PHY_SR_PHY_LINK_UP) ? 1 : 0;
++}
++
++static inline void pcie_mem_io_setup(int pcie_port)
++{
++ unsigned int reg;
++ /*
++ * BAR[0:1] readonly register
++ * RC contains only minimal BARs for packets mapped to this device
++ * Mem/IO filters defines a range of memory occupied by memory mapped IO devices that
++ * reside on the downstream side fo the bridge.
++ */
++ reg = SM((PCIE_MEM_PHY_PORT_TO_END(pcie_port) >> 20), PCIE_MBML_MEM_LIMIT_ADDR)
++ | SM((PCIE_MEM_PHY_PORT_TO_BASE(pcie_port) >> 20), PCIE_MBML_MEM_BASE_ADDR);
++ IFX_REG_W32(reg, PCIE_MBML(pcie_port));
++
++ /* PCIe_PBML, same as MBML */
++ IFX_REG_W32(IFX_REG_R32(PCIE_MBML(pcie_port)), PCIE_PMBL(pcie_port));
++
++ /* IO Address Range */
++ reg = SM((PCIE_IO_PHY_PORT_TO_END(pcie_port) >> 12), PCIE_IOBLSECS_IO_LIMIT_ADDR)
++ | SM((PCIE_IO_PHY_PORT_TO_BASE(pcie_port) >> 12), PCIE_IOBLSECS_IO_BASE_ADDR);
++ reg |= PCIE_IOBLSECS_32BIT_IO_ADDR;
++ IFX_REG_W32(reg, PCIE_IOBLSECS(pcie_port));
++
++ reg = SM((PCIE_IO_PHY_PORT_TO_END(pcie_port) >> 16), PCIE_IO_BANDL_UPPER_16BIT_IO_LIMIT)
++ | SM((PCIE_IO_PHY_PORT_TO_BASE(pcie_port) >> 16), PCIE_IO_BANDL_UPPER_16BIT_IO_BASE);
++ IFX_REG_W32(reg, PCIE_IO_BANDL(pcie_port));
++}
++
++static inline void pcie_msi_setup(int pcie_port)
++{
++ unsigned int reg;
++
++ /* XXX, MSI stuff should only apply to EP */
++ /* MSI Capability: Only enable 32-bit addresses */
++ reg = IFX_REG_R32(PCIE_MCAPR(pcie_port));
++ reg &= ~PCIE_MCAPR_ADDR64_CAP;
++ reg |= PCIE_MCAPR_MSI_ENABLE;
++
++ /* Disable multiple message */
++ reg &= ~(PCIE_MCAPR_MULTI_MSG_CAP | PCIE_MCAPR_MULTI_MSG_ENABLE);
++ IFX_REG_W32(reg, PCIE_MCAPR(pcie_port));
++}
++
++static inline void pcie_pm_setup(int pcie_port)
++{
++ unsigned int reg;
++
++ /* Enable PME, Soft reset enabled */
++ reg = IFX_REG_R32(PCIE_PM_CSR(pcie_port));
++ reg |= PCIE_PM_CSR_PME_ENABLE | PCIE_PM_CSR_SW_RST;
++ IFX_REG_W32(reg, PCIE_PM_CSR(pcie_port));
++}
++
++static inline void pcie_bus_setup(int pcie_port)
++{
++ unsigned int reg;
++
++ reg = SM(0, PCIE_BNR_PRIMARY_BUS_NUM) | SM(1, PCIE_PNR_SECONDARY_BUS_NUM) | SM(0xFF, PCIE_PNR_SUB_BUS_NUM);
++ IFX_REG_W32(reg, PCIE_BNR(pcie_port));
++}
++
++static inline void pcie_device_setup(int pcie_port)
++{
++ unsigned int reg;
++
++ /* Device capability register, set up Maximum payload size */
++ reg = IFX_REG_R32(PCIE_DCAP(pcie_port));
++ reg |= PCIE_DCAP_ROLE_BASE_ERR_REPORT;
++ reg |= SM(PCIE_MAX_PAYLOAD_128, PCIE_DCAP_MAX_PAYLOAD_SIZE);
++
++ /* Only available for EP */
++ reg &= ~(PCIE_DCAP_EP_L0S_LATENCY | PCIE_DCAP_EP_L1_LATENCY);
++ IFX_REG_W32(reg, PCIE_DCAP(pcie_port));
++
++ /* Device control and status register */
++ /* Set Maximum Read Request size for the device as a Requestor */
++ reg = IFX_REG_R32(PCIE_DCTLSTS(pcie_port));
++
++ /*
++ * Request size can be larger than the MPS used, but the completions returned
++ * for the read will be bounded by the MPS size.
++ * In our system, Max request size depends on AHB burst size. It is 64 bytes.
++ * but we set it as 128 as minimum one.
++ */
++ reg |= SM(PCIE_MAX_PAYLOAD_128, PCIE_DCTLSTS_MAX_READ_SIZE)
++ | SM(PCIE_MAX_PAYLOAD_128, PCIE_DCTLSTS_MAX_PAYLOAD_SIZE);
++
++ /* Enable relaxed ordering, no snoop, and all kinds of errors */
++ reg |= PCIE_DCTLSTS_RELAXED_ORDERING_EN | PCIE_DCTLSTS_ERR_EN | PCIE_DCTLSTS_NO_SNOOP_EN;
++
++ IFX_REG_W32(reg, PCIE_DCTLSTS(pcie_port));
++}
++
++static inline void pcie_link_setup(int pcie_port)
++{
++ unsigned int reg;
++
++ /*
++ * XXX, Link capability register, bit 18 for EP CLKREQ# dynamic clock management for L1, L2/3 CPM
++ * L0s is reported during link training via TS1 order set by N_FTS
++ */
++ reg = IFX_REG_R32(PCIE_LCAP(pcie_port));
++ reg &= ~PCIE_LCAP_L0S_EIXT_LATENCY;
++ reg |= SM(3, PCIE_LCAP_L0S_EIXT_LATENCY);
++ IFX_REG_W32(reg, PCIE_LCAP(pcie_port));
++
++ /* Link control and status register */
++ reg = IFX_REG_R32(PCIE_LCTLSTS(pcie_port));
++
++ /* Link Enable, ASPM enabled */
++ reg &= ~PCIE_LCTLSTS_LINK_DISABLE;
++
++#ifdef CONFIG_PCIEASPM
++ /*
++ * We use the same physical reference clock that the platform provides on the connector
++ * It paved the way for ASPM to calculate the new exit Latency
++ */
++ reg |= PCIE_LCTLSTS_SLOT_CLK_CFG;
++ reg |= PCIE_LCTLSTS_COM_CLK_CFG;
++ /*
++ * We should disable ASPM by default except that we have dedicated power management support
++ * Enable ASPM will cause the system hangup/instability, performance degration
++ */
++ reg |= PCIE_LCTLSTS_ASPM_ENABLE;
++#else
++ reg &= ~PCIE_LCTLSTS_ASPM_ENABLE;
++#endif /* CONFIG_PCIEASPM */
++
++ /*
++ * The maximum size of any completion with data packet is bounded by the MPS setting
++ * in device control register
++ */
++ /* RCB may cause multiple split transactions, two options available, we use 64 byte RCB */
++ reg &= ~ PCIE_LCTLSTS_RCB128;
++ IFX_REG_W32(reg, PCIE_LCTLSTS(pcie_port));
++}
++
++static inline void pcie_error_setup(int pcie_port)
++{
++ unsigned int reg;
++
++ /*
++ * Forward ERR_COR, ERR_NONFATAL, ERR_FATAL to the backbone
++ * Poisoned write TLPs and completions indicating poisoned TLPs will set the PCIe_PCICMDSTS.MDPE
++ */
++ reg = IFX_REG_R32(PCIE_INTRBCTRL(pcie_port));
++ reg |= PCIE_INTRBCTRL_SERR_ENABLE | PCIE_INTRBCTRL_PARITY_ERR_RESP_ENABLE;
++
++ IFX_REG_W32(reg, PCIE_INTRBCTRL(pcie_port));
++
++ /* Uncorrectable Error Mask Register, Unmask <enable> all bits in PCIE_UESR */
++ reg = IFX_REG_R32(PCIE_UEMR(pcie_port));
++ reg &= ~PCIE_ALL_UNCORRECTABLE_ERR;
++ IFX_REG_W32(reg, PCIE_UEMR(pcie_port));
++
++ /* Uncorrectable Error Severity Register, ALL errors are FATAL */
++ IFX_REG_W32(PCIE_ALL_UNCORRECTABLE_ERR, PCIE_UESR(pcie_port));
++
++ /* Correctable Error Mask Register, unmask <enable> all bits */
++ reg = IFX_REG_R32(PCIE_CEMR(pcie_port));
++ reg &= ~PCIE_CORRECTABLE_ERR;
++ IFX_REG_W32(reg, PCIE_CEMR(pcie_port));
++
++ /* Advanced Error Capabilities and Control Registr */
++ reg = IFX_REG_R32(PCIE_AECCR(pcie_port));
++ reg |= PCIE_AECCR_ECRC_CHECK_EN | PCIE_AECCR_ECRC_GEN_EN;
++ IFX_REG_W32(reg, PCIE_AECCR(pcie_port));
++
++ /* Root Error Command Register, Report all types of errors */
++ reg = IFX_REG_R32(PCIE_RECR(pcie_port));
++ reg |= PCIE_RECR_ERR_REPORT_EN;
++ IFX_REG_W32(reg, PCIE_RECR(pcie_port));
++
++ /* Clear the Root status register */
++ reg = IFX_REG_R32(PCIE_RESR(pcie_port));
++ IFX_REG_W32(reg, PCIE_RESR(pcie_port));
++}
++
++static inline void pcie_root_setup(int pcie_port)
++{
++ unsigned int reg;
++
++ /* Root control and capabilities register */
++ reg = IFX_REG_R32(PCIE_RCTLCAP(pcie_port));
++ reg |= PCIE_RCTLCAP_SERR_ENABLE | PCIE_RCTLCAP_PME_INT_EN;
++ IFX_REG_W32(reg, PCIE_RCTLCAP(pcie_port));
++}
++
++static inline void pcie_vc_setup(int pcie_port)
++{
++ unsigned int reg;
++
++ /* Port VC Capability Register 2 */
++ reg = IFX_REG_R32(PCIE_PVC2(pcie_port));
++ reg &= ~PCIE_PVC2_VC_ARB_WRR;
++ reg |= PCIE_PVC2_VC_ARB_16P_FIXED_WRR;
++ IFX_REG_W32(reg, PCIE_PVC2(pcie_port));
++
++ /* VC0 Resource Capability Register */
++ reg = IFX_REG_R32(PCIE_VC0_RC(pcie_port));
++ reg &= ~PCIE_VC0_RC_REJECT_SNOOP;
++ IFX_REG_W32(reg, PCIE_VC0_RC(pcie_port));
++}
++
++static inline void pcie_port_logic_setup(int pcie_port)
++{
++ unsigned int reg;
++
++ /* FTS number, default 12, increase to 63, may increase time from/to L0s to L0 */
++ reg = IFX_REG_R32(PCIE_AFR(pcie_port));
++ reg &= ~(PCIE_AFR_FTS_NUM | PCIE_AFR_COM_FTS_NUM);
++ reg |= SM(PCIE_AFR_FTS_NUM_DEFAULT, PCIE_AFR_FTS_NUM)
++ | SM(PCIE_AFR_FTS_NUM_DEFAULT, PCIE_AFR_COM_FTS_NUM);
++ /* L0s and L1 entry latency */
++ reg &= ~(PCIE_AFR_L0S_ENTRY_LATENCY | PCIE_AFR_L1_ENTRY_LATENCY);
++ reg |= SM(PCIE_AFR_L0S_ENTRY_LATENCY_DEFAULT, PCIE_AFR_L0S_ENTRY_LATENCY)
++ | SM(PCIE_AFR_L1_ENTRY_LATENCY_DEFAULT, PCIE_AFR_L1_ENTRY_LATENCY);
++ IFX_REG_W32(reg, PCIE_AFR(pcie_port));
++
++ /* Port Link Control Register */
++ reg = IFX_REG_R32(PCIE_PLCR(pcie_port));
++ reg |= PCIE_PLCR_DLL_LINK_EN; /* Enable the DLL link */
++ IFX_REG_W32(reg, PCIE_PLCR(pcie_port));
++
++ /* Lane Skew Register */
++ reg = IFX_REG_R32(PCIE_LSR(pcie_port));
++ /* Enable ACK/NACK and FC */
++ reg &= ~(PCIE_LSR_ACKNAK_DISABLE | PCIE_LSR_FC_DISABLE);
++ IFX_REG_W32(reg, PCIE_LSR(pcie_port));
++
++ /* Symbol Timer Register and Filter Mask Register 1 */
++ reg = IFX_REG_R32(PCIE_STRFMR(pcie_port));
++
++ /* Default SKP interval is very accurate already, 5us */
++ /* Enable IO/CFG transaction */
++ reg |= PCIE_STRFMR_RX_CFG_TRANS_ENABLE | PCIE_STRFMR_RX_IO_TRANS_ENABLE;
++ /* Disable FC WDT */
++ reg &= ~PCIE_STRFMR_FC_WDT_DISABLE;
++ IFX_REG_W32(reg, PCIE_STRFMR(pcie_port));
++
++ /* Filter Masker Register 2 */
++ reg = IFX_REG_R32(PCIE_FMR2(pcie_port));
++ reg |= PCIE_FMR2_VENDOR_MSG1_PASSED_TO_TRGT1 | PCIE_FMR2_VENDOR_MSG0_PASSED_TO_TRGT1;
++ IFX_REG_W32(reg, PCIE_FMR2(pcie_port));
++
++ /* VC0 Completion Receive Queue Control Register */
++ reg = IFX_REG_R32(PCIE_VC0_CRQCR(pcie_port));
++ reg &= ~PCIE_VC0_CRQCR_CPL_TLP_QUEUE_MODE;
++ reg |= SM(PCIE_VC0_TLP_QUEUE_MODE_BYPASS, PCIE_VC0_CRQCR_CPL_TLP_QUEUE_MODE);
++ IFX_REG_W32(reg, PCIE_VC0_CRQCR(pcie_port));
++}
++
++static inline void pcie_rc_cfg_reg_setup(int pcie_port)
++{
++ /* diable ltssm */
++ IFX_REG_W32(0, PCIE_RC_CCR(pcie_port));
++
++ pcie_mem_io_setup(pcie_port);
++ pcie_msi_setup(pcie_port);
++ pcie_pm_setup(pcie_port);
++ pcie_bus_setup(pcie_port);
++ pcie_device_setup(pcie_port);
++ pcie_link_setup(pcie_port);
++ pcie_error_setup(pcie_port);
++ pcie_root_setup(pcie_port);
++ pcie_vc_setup(pcie_port);
++ pcie_port_logic_setup(pcie_port);
++}
++
++static int ifx_pcie_wait_phy_link_up(int pcie_port)
++{
++ int i;
++
++ /* Wait for PHY link is up */
++ for (i = 0; i < IFX_PCIE_PHY_LINK_UP_TIMEOUT; i++) {
++ if (ifx_pcie_link_up(pcie_port)) {
++ break;
++ }
++ udelay(100);
++ }
++ if (i >= IFX_PCIE_PHY_LINK_UP_TIMEOUT) {
++ printk(KERN_ERR "%s timeout\n", __func__);
++ return -1;
++ }
++
++ /* Check data link up or not */
++ if (!(IFX_REG_R32(PCIE_RC_DR(pcie_port)) & PCIE_RC_DR_DLL_UP)) {
++ printk(KERN_ERR "%s DLL link is still down\n", __func__);
++ return -1;
++ }
++
++ /* Check Data link active or not */
++ if (!(IFX_REG_R32(PCIE_LCTLSTS(pcie_port)) & PCIE_LCTLSTS_DLL_ACTIVE)) {
++ printk(KERN_ERR "%s DLL is not active\n", __func__);
++ return -1;
++ }
++ return 0;
++}
++
++static inline int pcie_app_loigc_setup(int pcie_port)
++{
++ IFX_REG_W32(PCIE_AHB_CTRL_BUS_ERROR_SUPPRESS, PCIE_AHB_CTRL(pcie_port));
++
++ /* Pull PCIe EP out of reset */
++ pcie_device_rst_deassert(pcie_port);
++
++ /* Start LTSSM training between RC and EP */
++ pcie_ltssm_enable(pcie_port);
++
++ /* Check PHY status after enabling LTSSM */
++ if (ifx_pcie_wait_phy_link_up(pcie_port) != 0) {
++ return -1;
++ }
++ return 0;
++}
++
++/*
++ * Must be done after ltssm due to based on negotiated link
++ * width and payload size
++ * Update the Replay Time Limit. Empirically, some PCIe
++ * devices take a little longer to respond than expected under
++ * load. As a workaround for this we configure the Replay Time
++ * Limit to the value expected for a 512 byte MPS instead of
++ * our actual 128 byte MPS. The numbers below are directly
++ * from the PCIe spec table 3-4/5.
++ */
++static inline void pcie_replay_time_update(int pcie_port)
++{
++ unsigned int reg;
++ int nlw;
++ int rtl;
++
++ reg = IFX_REG_R32(PCIE_LCTLSTS(pcie_port));
++
++ nlw = MS(reg, PCIE_LCTLSTS_NEGOTIATED_LINK_WIDTH);
++ switch (nlw) {
++ case PCIE_MAX_LENGTH_WIDTH_X1:
++ rtl = 1677;
++ break;
++ case PCIE_MAX_LENGTH_WIDTH_X2:
++ rtl = 867;
++ break;
++ case PCIE_MAX_LENGTH_WIDTH_X4:
++ rtl = 462;
++ break;
++ case PCIE_MAX_LENGTH_WIDTH_X8:
++ rtl = 258;
++ break;
++ default:
++ rtl = 1677;
++ break;
++ }
++ reg = IFX_REG_R32(PCIE_ALTRT(pcie_port));
++ reg &= ~PCIE_ALTRT_REPLAY_TIME_LIMIT;
++ reg |= SM(rtl, PCIE_ALTRT_REPLAY_TIME_LIMIT);
++ IFX_REG_W32(reg, PCIE_ALTRT(pcie_port));
++
++ IFX_PCIE_PRINT(PCIE_MSG_REG, "%s PCIE_ALTRT 0x%08x\n",
++ __func__, IFX_REG_R32(PCIE_ALTRT(pcie_port)));
++}
++
++/*
++ * Table 359 Enhanced Configuration Address Mapping1)
++ * 1) This table is defined in Table 7-1, page 341, PCI Express Base Specification v1.1
++ * Memory Address PCI Express Configuration Space
++ * A[(20+n-1):20] Bus Number 1 < n < 8
++ * A[19:15] Device Number
++ * A[14:12] Function Number
++ * A[11:8] Extended Register Number
++ * A[7:2] Register Number
++ * A[1:0] Along with size of the access, used to generate Byte Enables
++ * For VR9, only the address bits [22:0] are mapped to the configuration space:
++ * . Address bits [22:20] select the target bus (1-of-8)1)
++ * . Address bits [19:15] select the target device (1-of-32) on the bus
++ * . Address bits [14:12] select the target function (1-of-8) within the device.
++ * . Address bits [11:2] selects the target dword (1-of-1024) within the selected function.s configuration space
++ * . Address bits [1:0] define the start byte location within the selected dword.
++ */
++static inline unsigned int pcie_bus_addr(u8 bus_num, u16 devfn, int where)
++{
++ unsigned int addr;
++ u8 bus;
++
++ if (!bus_num) {
++ /* type 0 */
++ addr = ((PCI_SLOT(devfn) & 0x1F) << 15) | ((PCI_FUNC(devfn) & 0x7) << 12) | ((where & 0xFFF)& ~3);
++ } else {
++ bus = bus_num;
++ /* type 1, only support 8 buses */
++ addr = ((bus & 0x7) << 20) | ((PCI_SLOT(devfn) & 0x1F) << 15) |
++ ((PCI_FUNC(devfn) & 0x7) << 12) | ((where & 0xFFF) & ~3);
++ }
++ IFX_PCIE_PRINT(PCIE_MSG_CFG, "%s: bus addr : %02x:%02x.%01x/%02x, addr=%08x\n",
++ __func__, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn), where, addr);
++ return addr;
++}
++
++static int pcie_valid_config(int pcie_port, int bus, int dev)
++{
++ /* RC itself */
++ if ((bus == 0) && (dev == 0))
++ return 1;
++
++ /* No physical link */
++ if (!ifx_pcie_link_up(pcie_port))
++ return 0;
++
++ /* Bus zero only has RC itself
++ * XXX, check if EP will be integrated
++ */
++ if ((bus == 0) && (dev != 0))
++ return 0;
++
++ /* Maximum 8 buses supported for VRX */
++ if (bus > 9)
++ return 0;
++
++ /*
++ * PCIe is PtP link, one bus only supports only one device
++ * except bus zero and PCIe switch which is virtual bus device
++ * The following two conditions really depends on the system design
++ * and attached the device.
++ * XXX, how about more new switch
++ */
++ if ((bus == 1) && (dev != 0))
++ return 0;
++
++ if ((bus >= 3) && (dev != 0))
++ return 0;
++ return 1;
++}
++
++static inline unsigned int ifx_pcie_cfg_rd(int pcie_port, unsigned int reg)
++{
++ return IFX_REG_R32((volatile unsigned int *)(PCIE_CFG_PORT_TO_BASE(pcie_port) + reg));
++}
++
++static inline void ifx_pcie_cfg_wr(int pcie_port, unsigned int reg, unsigned int val)
++{
++ IFX_REG_W32( val, (volatile unsigned int *)(PCIE_CFG_PORT_TO_BASE(pcie_port) + reg));
++}
++
++static inline unsigned int ifx_pcie_rc_cfg_rd(int pcie_port, unsigned int reg)
++{
++ return IFX_REG_R32((volatile unsigned int *)(PCIE_RC_PORT_TO_BASE(pcie_port) + reg));
++}
++
++static inline void ifx_pcie_rc_cfg_wr(int pcie_port, unsigned int reg, unsigned int val)
++{
++ IFX_REG_W32(val, (volatile unsigned int *)(PCIE_RC_PORT_TO_BASE(pcie_port) + reg));
++}
++
++unsigned int ifx_pcie_bus_enum_read_hack(int where, unsigned int value)
++{
++ unsigned int tvalue = value;
++
++ if (where == PCI_PRIMARY_BUS) {
++ u8 primary, secondary, subordinate;
++
++ primary = tvalue & 0xFF;
++ secondary = (tvalue >> 8) & 0xFF;
++ subordinate = (tvalue >> 16) & 0xFF;
++ primary += pcibios_1st_host_bus_nr();
++ secondary += pcibios_1st_host_bus_nr();
++ subordinate += pcibios_1st_host_bus_nr();
++ tvalue = (tvalue & 0xFF000000) | (unsigned int)primary | (unsigned int)(secondary << 8) | (unsigned int)(subordinate << 16);
++ }
++ return tvalue;
++}
++
++unsigned int ifx_pcie_bus_enum_write_hack(int where, unsigned int value)
++{
++ unsigned int tvalue = value;
++
++ if (where == PCI_PRIMARY_BUS) {
++ u8 primary, secondary, subordinate;
++
++ primary = tvalue & 0xFF;
++ secondary = (tvalue >> 8) & 0xFF;
++ subordinate = (tvalue >> 16) & 0xFF;
++ if (primary > 0 && primary != 0xFF)
++ primary -= pcibios_1st_host_bus_nr();
++ if (secondary > 0 && secondary != 0xFF)
++ secondary -= pcibios_1st_host_bus_nr();
++ if (subordinate > 0 && subordinate != 0xFF)
++ subordinate -= pcibios_1st_host_bus_nr();
++ tvalue = (tvalue & 0xFF000000) | (unsigned int)primary | (unsigned int)(secondary << 8) | (unsigned int)(subordinate << 16);
++ } else if (where == PCI_SUBORDINATE_BUS) {
++ u8 subordinate = tvalue & 0xFF;
++ subordinate = subordinate > 0 ? subordinate - pcibios_1st_host_bus_nr() : 0;
++ tvalue = subordinate;
++ }
++ return tvalue;
++}
++
++/**
++ * \fn static int ifx_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
++ * int where, int size, unsigned int *value)
++ * \brief Read a value from configuration space
++ *
++ * \param[in] bus Pointer to pci bus
++ * \param[in] devfn PCI device function number
++ * \param[in] where PCI register number
++ * \param[in] size Register read size
++ * \param[out] value Pointer to return value
++ * \return PCIBIOS_BAD_REGISTER_NUMBER Invalid register number
++ * \return PCIBIOS_FUNC_NOT_SUPPORTED PCI function not supported
++ * \return PCIBIOS_DEVICE_NOT_FOUND PCI device not found
++ * \return PCIBIOS_SUCCESSFUL OK
++ * \ingroup IFX_PCIE_OS
++ */
++static int ifx_pcie_read_config(struct pci_bus *bus, unsigned int devfn, int where, int size, unsigned int *value)
++{
++ unsigned int data = 0;
++ int bus_number = bus->number;
++ static const unsigned int mask[8] = {0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0};
++ int ret = PCIBIOS_SUCCESSFUL;
++ struct ifx_pci_controller *ctrl = bus->sysdata;
++ int pcie_port = ctrl->port;
++
++ if (unlikely(size != 1 && size != 2 && size != 4)){
++ ret = PCIBIOS_BAD_REGISTER_NUMBER;
++ goto out;
++ }
++
++ /* Make sure the address is aligned to natural boundary */
++ if (unlikely(((size - 1) & where))) {
++ ret = PCIBIOS_BAD_REGISTER_NUMBER;
++ goto out;
++ }
++
++ /*
++ * If we are second controller, we have to cheat OS so that it assume
++ * its bus number starts from 0 in host controller
++ */
++ bus_number = ifx_pcie_bus_nr_deduct(bus_number, pcie_port);
++
++ /*
++ * We need to force the bus number to be zero on the root
++ * bus. Linux numbers the 2nd root bus to start after all
++ * busses on root 0.
++ */
++ if (bus->parent == NULL)
++ bus_number = 0;
++
++ /*
++ * PCIe only has a single device connected to it. It is
++ * always device ID 0. Don't bother doing reads for other
++ * device IDs on the first segment.
++ */
++ if ((bus_number == 0) && (PCI_SLOT(devfn) != 0)) {
++ ret = PCIBIOS_FUNC_NOT_SUPPORTED;
++ goto out;
++ }
++
++ if (pcie_valid_config(pcie_port, bus_number, PCI_SLOT(devfn)) == 0) {
++ *value = 0xffffffff;
++ ret = PCIBIOS_DEVICE_NOT_FOUND;
++ goto out;
++ }
++
++ IFX_PCIE_PRINT(PCIE_MSG_READ_CFG, "%s: %02x:%02x.%01x/%02x:%01d\n", __func__, bus_number,
++ PCI_SLOT(devfn), PCI_FUNC(devfn), where, size);
++
++ PCIE_IRQ_LOCK(ifx_pcie_lock);
++ if (bus_number == 0) { /* RC itself */
++ unsigned int t;
++
++ t = (where & ~3);
++ data = ifx_pcie_rc_cfg_rd(pcie_port, t);
++ IFX_PCIE_PRINT(PCIE_MSG_READ_CFG, "%s: rd local cfg, offset:%08x, data:%08x\n",
++ __func__, t, data);
++ } else {
++ unsigned int addr = pcie_bus_addr(bus_number, devfn, where);
++
++ data = ifx_pcie_cfg_rd(pcie_port, addr);
++ if (pcie_port == IFX_PCIE_PORT0) {
++#ifdef CONFIG_IFX_PCIE_HW_SWAP
++ data = le32_to_cpu(data);
++#endif /* CONFIG_IFX_PCIE_HW_SWAP */
++ } else {
++#ifdef CONFIG_IFX_PCIE1_HW_SWAP
++ data = le32_to_cpu(data);
++#endif /* CONFIG_IFX_PCIE_HW_SWAP */
++ }
++ }
++ /* To get a correct PCI topology, we have to restore the bus number to OS */
++ data = ifx_pcie_bus_enum_hack(bus, devfn, where, data, pcie_port, 1);
++
++ PCIE_IRQ_UNLOCK(ifx_pcie_lock);
++ IFX_PCIE_PRINT(PCIE_MSG_READ_CFG, "%s: read config: data=%08x raw=%08x\n",
++ __func__, (data >> (8 * (where & 3))) & mask[size & 7], data);
++
++ *value = (data >> (8 * (where & 3))) & mask[size & 7];
++out:
++ return ret;
++}
++
++static unsigned int ifx_pcie_size_to_value(int where, int size, unsigned int data, unsigned int value)
++{
++ unsigned int shift;
++ unsigned int tdata = data;
++
++ switch (size) {
++ case 1:
++ shift = (where & 0x3) << 3;
++ tdata &= ~(0xffU << shift);
++ tdata |= ((value & 0xffU) << shift);
++ break;
++ case 2:
++ shift = (where & 3) << 3;
++ tdata &= ~(0xffffU << shift);
++ tdata |= ((value & 0xffffU) << shift);
++ break;
++ case 4:
++ tdata = value;
++ break;
++ }
++ return tdata;
++}
++
++/**
++ * \fn static static int ifx_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
++ * int where, int size, unsigned int value)
++ * \brief Write a value to PCI configuration space
++ *
++ * \param[in] bus Pointer to pci bus
++ * \param[in] devfn PCI device function number
++ * \param[in] where PCI register number
++ * \param[in] size The register size to be written
++ * \param[in] value The valule to be written
++ * \return PCIBIOS_BAD_REGISTER_NUMBER Invalid register number
++ * \return PCIBIOS_DEVICE_NOT_FOUND PCI device not found
++ * \return PCIBIOS_SUCCESSFUL OK
++ * \ingroup IFX_PCIE_OS
++ */
++static int ifx_pcie_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, unsigned int value)
++{
++ int bus_number = bus->number;
++ int ret = PCIBIOS_SUCCESSFUL;
++ struct ifx_pci_controller *ctrl = bus->sysdata;
++ int pcie_port = ctrl->port;
++ unsigned int tvalue = value;
++ unsigned int data;
++
++ /* Make sure the address is aligned to natural boundary */
++ if (unlikely(((size - 1) & where))) {
++ ret = PCIBIOS_BAD_REGISTER_NUMBER;
++ goto out;
++ }
++ /*
++ * If we are second controller, we have to cheat OS so that it assume
++ * its bus number starts from 0 in host controller
++ */
++ bus_number = ifx_pcie_bus_nr_deduct(bus_number, pcie_port);
++
++ /*
++ * We need to force the bus number to be zero on the root
++ * bus. Linux numbers the 2nd root bus to start after all
++ * busses on root 0.
++ */
++ if (bus->parent == NULL)
++ bus_number = 0;
++
++ if (pcie_valid_config(pcie_port, bus_number, PCI_SLOT(devfn)) == 0) {
++ ret = PCIBIOS_DEVICE_NOT_FOUND;
++ goto out;
++ }
++
++ IFX_PCIE_PRINT(PCIE_MSG_WRITE_CFG, "%s: %02x:%02x.%01x/%02x:%01d value=%08x\n", __func__,
++ bus_number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, value);
++
++ /* XXX, some PCIe device may need some delay */
++ PCIE_IRQ_LOCK(ifx_pcie_lock);
++
++ /*
++ * To configure the correct bus topology using native way, we have to cheat Os so that
++ * it can configure the PCIe hardware correctly.
++ */
++ tvalue = ifx_pcie_bus_enum_hack(bus, devfn, where, value, pcie_port, 0);
++
++ if (bus_number == 0) { /* RC itself */
++ unsigned int t;
++
++ t = (where & ~3);
++ IFX_PCIE_PRINT(PCIE_MSG_WRITE_CFG,"%s: wr local cfg, offset:%08x, fill:%08x\n", __func__, t, value);
++ data = ifx_pcie_rc_cfg_rd(pcie_port, t);
++ IFX_PCIE_PRINT(PCIE_MSG_WRITE_CFG,"%s: rd local cfg, offset:%08x, data:%08x\n", __func__, t, data);
++
++ data = ifx_pcie_size_to_value(where, size, data, tvalue);
++
++ IFX_PCIE_PRINT(PCIE_MSG_WRITE_CFG,"%s: wr local cfg, offset:%08x, value:%08x\n", __func__, t, data);
++ ifx_pcie_rc_cfg_wr(pcie_port, t, data);
++ IFX_PCIE_PRINT(PCIE_MSG_WRITE_CFG,"%s: rd local cfg, offset:%08x, value:%08x\n",
++ __func__, t, ifx_pcie_rc_cfg_rd(pcie_port, t));
++ } else {
++ unsigned int addr = pcie_bus_addr(bus_number, devfn, where);
++
++ IFX_PCIE_PRINT(PCIE_MSG_WRITE_CFG,"%s: wr cfg, offset:%08x, fill:%08x\n", __func__, addr, value);
++ data = ifx_pcie_cfg_rd(pcie_port, addr);
++ if (pcie_port == IFX_PCIE_PORT0) {
++#ifdef CONFIG_IFX_PCIE_HW_SWAP
++ data = le32_to_cpu(data);
++#endif /* CONFIG_IFX_PCIE_HW_SWAP */
++ } else {
++#ifdef CONFIG_IFX_PCIE1_HW_SWAP
++ data = le32_to_cpu(data);
++#endif /* CONFIG_IFX_PCIE_HW_SWAP */
++ }
++ IFX_PCIE_PRINT(PCIE_MSG_WRITE_CFG,"%s: rd cfg, offset:%08x, data:%08x\n", __func__, addr, data);
++
++ data = ifx_pcie_size_to_value(where, size, data, tvalue);
++ if (pcie_port == IFX_PCIE_PORT0) {
++#ifdef CONFIG_IFX_PCIE_HW_SWAP
++ data = cpu_to_le32(data);
++#endif /* CONFIG_IFX_PCIE_HW_SWAP */
++ } else {
++#ifdef CONFIG_IFX_PCIE1_HW_SWAP
++ data = cpu_to_le32(data);
++#endif /* CONFIG_IFX_PCIE_HW_SWAP */
++ }
++ IFX_PCIE_PRINT(PCIE_MSG_WRITE_CFG, "%s: wr cfg, offset:%08x, value:%08x\n", __func__, addr, data);
++ ifx_pcie_cfg_wr(pcie_port, addr, data);
++ IFX_PCIE_PRINT(PCIE_MSG_WRITE_CFG, "%s: rd cfg, offset:%08x, value:%08x\n",
++ __func__, addr, ifx_pcie_cfg_rd(pcie_port, addr));
++ }
++ PCIE_IRQ_UNLOCK(ifx_pcie_lock);
++out:
++ return ret;
++}
++
++static struct resource ifx_pcie_io_resource = {
++ .name = "PCIe0 I/O space",
++ .start = PCIE_IO_PHY_BASE,
++ .end = PCIE_IO_PHY_END,
++ .flags = IORESOURCE_IO,
++};
++
++static struct resource ifx_pcie_mem_resource = {
++ .name = "PCIe0 Memory space",
++ .start = PCIE_MEM_PHY_BASE,
++ .end = PCIE_MEM_PHY_END,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct pci_ops ifx_pcie_ops = {
++ .read = ifx_pcie_read_config,
++ .write = ifx_pcie_write_config,
++};
++
++static struct ifx_pci_controller ifx_pcie_controller[IFX_PCIE_CORE_NR] = {
++ {
++ .pcic = {
++ .pci_ops = &ifx_pcie_ops,
++ .mem_resource = &ifx_pcie_mem_resource,
++ .io_resource = &ifx_pcie_io_resource,
++ },
++ .port = IFX_PCIE_PORT0,
++ },
++};
++
++static inline void pcie_core_int_clear_all(int pcie_port)
++{
++ unsigned int reg;
++ reg = IFX_REG_R32(PCIE_IRNCR(pcie_port));
++ reg &= PCIE_RC_CORE_COMBINED_INT;
++ IFX_REG_W32(reg, PCIE_IRNCR(pcie_port));
++}
++
++static irqreturn_t pcie_rc_core_isr(int irq, void *dev_id)
++{
++ struct ifx_pci_controller *ctrl = (struct ifx_pci_controller *)dev_id;
++ int pcie_port = ctrl->port;
++
++ IFX_PCIE_PRINT(PCIE_MSG_ISR, "PCIe RC error intr %d\n", irq);
++ pcie_core_int_clear_all(pcie_port);
++ return IRQ_HANDLED;
++}
++
++static int pcie_rc_core_int_init(int pcie_port)
++{
++ int ret;
++
++ /* Enable core interrupt */
++ IFX_REG_SET_BIT(PCIE_RC_CORE_COMBINED_INT, PCIE_IRNEN(pcie_port));
++
++ /* Clear it first */
++ IFX_REG_SET_BIT(PCIE_RC_CORE_COMBINED_INT, PCIE_IRNCR(pcie_port));
++ ret = request_irq(pcie_irqs[pcie_port].ir_irq.irq, pcie_rc_core_isr, IRQF_DISABLED,
++ pcie_irqs[pcie_port].ir_irq.name, &ifx_pcie_controller[pcie_port]);
++ if (ret)
++ printk(KERN_ERR "%s request irq %d failed\n", __func__, IFX_PCIE_IR);
++
++ return ret;
++}
++
++int ifx_pcie_bios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++ unsigned int irq_bit = 0;
++ int irq = 0;
++ struct ifx_pci_controller *ctrl = dev->bus->sysdata;
++ int pcie_port = ctrl->port;
++
++ IFX_PCIE_PRINT(PCIE_MSG_FIXUP, "%s port %d dev %s slot %d pin %d \n", __func__, pcie_port, pci_name(dev), slot, pin);
++
++ if ((pin == PCIE_LEGACY_DISABLE) || (pin > PCIE_LEGACY_INT_MAX)) {
++ printk(KERN_WARNING "WARNING: dev %s: invalid interrupt pin %d\n", pci_name(dev), pin);
++ return -1;
++ }
++ /* Pin index so minus one */
++ irq_bit = pcie_irqs[pcie_port].legacy_irq[pin - 1].irq_bit;
++ irq = pcie_irqs[pcie_port].legacy_irq[pin - 1].irq;
++ IFX_REG_SET_BIT(irq_bit, PCIE_IRNEN(pcie_port));
++ IFX_REG_SET_BIT(irq_bit, PCIE_IRNCR(pcie_port));
++ IFX_PCIE_PRINT(PCIE_MSG_FIXUP, "%s dev %s irq %d assigned\n", __func__, pci_name(dev), irq);
++ return irq;
++}
++
++/**
++ * \fn int ifx_pcie_bios_plat_dev_init(struct pci_dev *dev)
++ * \brief Called to perform platform specific PCI setup
++ *
++ * \param[in] dev The Linux PCI device structure for the device to map
++ * \return OK
++ * \ingroup IFX_PCIE_OS
++ */
++int ifx_pcie_bios_plat_dev_init(struct pci_dev *dev)
++{
++ u16 config;
++ unsigned int dconfig;
++ int pos;
++ /* Enable reporting System errors and parity errors on all devices */
++ /* Enable parity checking and error reporting */
++ pci_read_config_word(dev, PCI_COMMAND, &config);
++ config |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR /*| PCI_COMMAND_INVALIDATE |
++ PCI_COMMAND_FAST_BACK*/;
++ pci_write_config_word(dev, PCI_COMMAND, config);
++
++ if (dev->subordinate) {
++ /* Set latency timers on sub bridges */
++ pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 0x40); /* XXX, */
++ /* More bridge error detection */
++ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &config);
++ config |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR;
++ pci_write_config_word(dev, PCI_BRIDGE_CONTROL, config);
++ }
++ /* Enable the PCIe normal error reporting */
++ pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
++ if (pos) {
++ /* Disable system error generation in response to error messages */
++ pci_read_config_word(dev, pos + PCI_EXP_RTCTL, &config);
++ config &= ~(PCI_EXP_RTCTL_SECEE | PCI_EXP_RTCTL_SENFEE | PCI_EXP_RTCTL_SEFEE);
++ pci_write_config_word(dev, pos + PCI_EXP_RTCTL, config);
++
++ /* Clear PCIE Capability's Device Status */
++ pci_read_config_word(dev, pos + PCI_EXP_DEVSTA, &config);
++ pci_write_config_word(dev, pos + PCI_EXP_DEVSTA, config);
++
++ /* Update Device Control */
++ pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &config);
++ /* Correctable Error Reporting */
++ config |= PCI_EXP_DEVCTL_CERE;
++ /* Non-Fatal Error Reporting */
++ config |= PCI_EXP_DEVCTL_NFERE;
++ /* Fatal Error Reporting */
++ config |= PCI_EXP_DEVCTL_FERE;
++ /* Unsupported Request */
++ config |= PCI_EXP_DEVCTL_URRE;
++ pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, config);
++ }
++
++ /* Find the Advanced Error Reporting capability */
++ pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
++ if (pos) {
++ /* Clear Uncorrectable Error Status */
++ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &dconfig);
++ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, dconfig);
++ /* Enable reporting of all uncorrectable errors */
++ /* Uncorrectable Error Mask - turned on bits disable errors */
++ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, 0);
++ /*
++ * Leave severity at HW default. This only controls if
++ * errors are reported as uncorrectable or
++ * correctable, not if the error is reported.
++ */
++ /* PCI_ERR_UNCOR_SEVER - Uncorrectable Error Severity */
++ /* Clear Correctable Error Status */
++ pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &dconfig);
++ pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, dconfig);
++ /* Enable reporting of all correctable errors */
++ /* Correctable Error Mask - turned on bits disable errors */
++ pci_write_config_dword(dev, pos + PCI_ERR_COR_MASK, 0);
++ /* Advanced Error Capabilities */
++ pci_read_config_dword(dev, pos + PCI_ERR_CAP, &dconfig);
++ /* ECRC Generation Enable */
++ if (dconfig & PCI_ERR_CAP_ECRC_GENC)
++ dconfig |= PCI_ERR_CAP_ECRC_GENE;
++ /* ECRC Check Enable */
++ if (dconfig & PCI_ERR_CAP_ECRC_CHKC)
++ dconfig |= PCI_ERR_CAP_ECRC_CHKE;
++ pci_write_config_dword(dev, pos + PCI_ERR_CAP, dconfig);
++
++ /* PCI_ERR_HEADER_LOG - Header Log Register (16 bytes) */
++ /* Enable Root Port's interrupt in response to error messages */
++ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND,
++ PCI_ERR_ROOT_CMD_COR_EN |
++ PCI_ERR_ROOT_CMD_NONFATAL_EN |
++ PCI_ERR_ROOT_CMD_FATAL_EN);
++ /* Clear the Root status register */
++ pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &dconfig);
++ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, dconfig);
++ }
++ /* WAR, only 128 MRRS is supported, force all EPs to support this value */
++ pcie_set_readrq(dev, 128);
++ return 0;
++}
++
++static void pcie_phy_rst(int pcie_port)
++{
++ pcie_phy_rst_assert(pcie_port);
++ pcie_phy_rst_deassert(pcie_port);
++ /* Make sure PHY PLL is stable */
++ udelay(20);
++}
++
++static int pcie_rc_initialize(int pcie_port)
++{
++ int i;
++
++ pcie_rcu_endian_setup(pcie_port);
++
++ pcie_ep_gpio_rst_init(pcie_port);
++
++ /*
++ * XXX, PCIe elastic buffer bug will cause not to be detected. One more
++ * reset PCIe PHY will solve this issue
++ */
++ for (i = 0; i < IFX_PCIE_PHY_LOOP_CNT; i++) {
++ /* Disable PCIe PHY Analog part for sanity check */
++ pcie_phy_pmu_disable(pcie_port);
++ pcie_phy_rst(pcie_port);
++ /* PCIe Core reset enabled, low active, sw programmed */
++ pcie_core_rst_assert(pcie_port);
++ /* Put PCIe EP in reset status */
++ pcie_device_rst_assert(pcie_port);
++ /* PCI PHY & Core reset disabled, high active, sw programmed */
++ pcie_core_rst_deassert(pcie_port);
++ /* Already in a quiet state, program PLL, enable PHY, check ready bit */
++ pcie_phy_clock_mode_setup(pcie_port);
++ /* Enable PCIe PHY and Clock */
++ pcie_core_pmu_setup(pcie_port);
++ /* Clear status registers */
++ pcie_status_register_clear(pcie_port);
++#ifdef CONFIG_PCI_MSI
++ pcie_msi_init(pcie_port);
++#endif /* CONFIG_PCI_MSI */
++ pcie_rc_cfg_reg_setup(pcie_port);
++
++ /* Once link is up, break out */
++ if (pcie_app_loigc_setup(pcie_port) == 0)
++ break;
++ }
++ if (i >= IFX_PCIE_PHY_LOOP_CNT) {
++ printk(KERN_ERR "%s link up failed!!!!!\n", __func__);
++ return -EIO;
++ }
++ /* NB, don't increase ACK/NACK timer timeout value, which will cause a lot of COR errors */
++ pcie_replay_time_update(pcie_port);
++ return 0;
++}
++
++static int inline ifx_pcie_startup_port_nr(void)
++{
++ int pcie_port = IFX_PCIE_PORT0;
++
++ pcie_port = IFX_PCIE_PORT0;
++ return pcie_port;
++}
++
++/**
++ * \fn static int __init ifx_pcie_bios_init(void)
++ * \brief Initialize the IFX PCIe controllers
++ *
++ * \return -EIO PCIe PHY link is not up
++ * \return -ENOMEM Configuration/IO space failed to map
++ * \return 0 OK
++ * \ingroup IFX_PCIE_OS
++ */
++extern int (*ltqpci_plat_arch_init)(struct pci_dev *dev);
++extern int (*ltqpci_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
++static int __devinit ltq_pcie_probe(struct platform_device *pdev)
++{
++ char ver_str[128] = {0};
++ void __iomem *io_map_base;
++ int pcie_port;
++ int startup_port;
++ ltqpci_map_irq = ifx_pcie_bios_map_irq;
++ ltqpci_plat_arch_init = ifx_pcie_bios_plat_dev_init;
++ /* Enable AHB Master/ Slave */
++ pcie_ahb_pmu_setup();
++
++ startup_port = ifx_pcie_startup_port_nr();
++
++ ltq_gpio_request(&pdev->dev, IFX_PCIE_GPIO_RESET, 0, 1, "pcie-reset");
++
++ for (pcie_port = startup_port; pcie_port < IFX_PCIE_CORE_NR; pcie_port++){
++ if (pcie_rc_initialize(pcie_port) == 0) {
++ /* Otherwise, warning will pop up */
++ io_map_base = ioremap(PCIE_IO_PHY_PORT_TO_BASE(pcie_port), PCIE_IO_SIZE);
++ if (io_map_base == NULL)
++ return -ENOMEM;
++ ifx_pcie_controller[pcie_port].pcic.io_map_base = (unsigned long)io_map_base;
++ register_pci_controller(&ifx_pcie_controller[pcie_port].pcic);
++ /* XXX, clear error status */
++ pcie_rc_core_int_init(pcie_port);
++ }
++ }
++
++ printk(KERN_INFO "%s", ver_str);
++return 0;
++}
++
++static struct platform_driver ltq_pcie_driver = {
++ .probe = ltq_pcie_probe,
++ .driver = {
++ .name = "pcie-xway",
++ .owner = THIS_MODULE,
++ },
++};
++
++int __init pciebios_init(void)
++{
++ return platform_driver_register(&ltq_pcie_driver);
++}
++
++arch_initcall(pciebios_init);
+diff --git a/arch/mips/pci/pcie-lantiq.h b/arch/mips/pci/pcie-lantiq.h
+new file mode 100644
+index 0000000..d877c23
+--- /dev/null
++++ b/arch/mips/pci/pcie-lantiq.h
+@@ -0,0 +1,1305 @@
++/******************************************************************************
++**
++** FILE NAME : ifxmips_pcie_reg.h
++** PROJECT : IFX UEIP for VRX200
++** MODULES : PCIe module
++**
++** DATE : 02 Mar 2009
++** AUTHOR : Lei Chuanhua
++** DESCRIPTION : PCIe Root Complex Driver
++** COPYRIGHT : Copyright (c) 2009
++** Infineon Technologies AG
++** Am Campeon 1-12, 85579 Neubiberg, Germany
++**
++** 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.
++** HISTORY
++** $Version $Date $Author $Comment
++** 0.0.1 17 Mar,2009 Lei Chuanhua Initial version
++*******************************************************************************/
++#ifndef IFXMIPS_PCIE_REG_H
++#define IFXMIPS_PCIE_REG_H
++#include <linux/version.h>
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/interrupt.h>
++/*!
++ \file ifxmips_pcie_reg.h
++ \ingroup IFX_PCIE
++ \brief header file for PCIe module register definition
++*/
++/* PCIe Address Mapping Base */
++#define PCIE_CFG_PHY_BASE 0x1D000000UL
++#define PCIE_CFG_BASE (KSEG1 + PCIE_CFG_PHY_BASE)
++#define PCIE_CFG_SIZE (8 * 1024 * 1024)
++
++#define PCIE_MEM_PHY_BASE 0x1C000000UL
++#define PCIE_MEM_BASE (KSEG1 + PCIE_MEM_PHY_BASE)
++#define PCIE_MEM_SIZE (16 * 1024 * 1024)
++#define PCIE_MEM_PHY_END (PCIE_MEM_PHY_BASE + PCIE_MEM_SIZE - 1)
++
++#define PCIE_IO_PHY_BASE 0x1D800000UL
++#define PCIE_IO_BASE (KSEG1 + PCIE_IO_PHY_BASE)
++#define PCIE_IO_SIZE (1 * 1024 * 1024)
++#define PCIE_IO_PHY_END (PCIE_IO_PHY_BASE + PCIE_IO_SIZE - 1)
++
++#define PCIE_RC_CFG_BASE (KSEG1 + 0x1D900000)
++#define PCIE_APP_LOGIC_REG (KSEG1 + 0x1E100900)
++#define PCIE_MSI_PHY_BASE 0x1F600000UL
++
++#define PCIE_PDI_PHY_BASE 0x1F106800UL
++#define PCIE_PDI_BASE (KSEG1 + PCIE_PDI_PHY_BASE)
++#define PCIE_PDI_SIZE 0x400
++
++#define PCIE1_CFG_PHY_BASE 0x19000000UL
++#define PCIE1_CFG_BASE (KSEG1 + PCIE1_CFG_PHY_BASE)
++#define PCIE1_CFG_SIZE (8 * 1024 * 1024)
++
++#define PCIE1_MEM_PHY_BASE 0x18000000UL
++#define PCIE1_MEM_BASE (KSEG1 + PCIE1_MEM_PHY_BASE)
++#define PCIE1_MEM_SIZE (16 * 1024 * 1024)
++#define PCIE1_MEM_PHY_END (PCIE1_MEM_PHY_BASE + PCIE1_MEM_SIZE - 1)
++
++#define PCIE1_IO_PHY_BASE 0x19800000UL
++#define PCIE1_IO_BASE (KSEG1 + PCIE1_IO_PHY_BASE)
++#define PCIE1_IO_SIZE (1 * 1024 * 1024)
++#define PCIE1_IO_PHY_END (PCIE1_IO_PHY_BASE + PCIE1_IO_SIZE - 1)
++
++#define PCIE1_RC_CFG_BASE (KSEG1 + 0x19900000)
++#define PCIE1_APP_LOGIC_REG (KSEG1 + 0x1E100700)
++#define PCIE1_MSI_PHY_BASE 0x1F400000UL
++
++#define PCIE1_PDI_PHY_BASE 0x1F700400UL
++#define PCIE1_PDI_BASE (KSEG1 + PCIE1_PDI_PHY_BASE)
++#define PCIE1_PDI_SIZE 0x400
++
++#define PCIE_CFG_PORT_TO_BASE(X) ((X) > 0 ? (PCIE1_CFG_BASE) : (PCIE_CFG_BASE))
++#define PCIE_MEM_PORT_TO_BASE(X) ((X) > 0 ? (PCIE1_MEM_BASE) : (PCIE_MEM_BASE))
++#define PCIE_IO_PORT_TO_BASE(X) ((X) > 0 ? (PCIE1_IO_BASE) : (PCIE_IO_BASE))
++#define PCIE_MEM_PHY_PORT_TO_BASE(X) ((X) > 0 ? (PCIE1_MEM_PHY_BASE) : (PCIE_MEM_PHY_BASE))
++#define PCIE_MEM_PHY_PORT_TO_END(X) ((X) > 0 ? (PCIE1_MEM_PHY_END) : (PCIE_MEM_PHY_END))
++#define PCIE_IO_PHY_PORT_TO_BASE(X) ((X) > 0 ? (PCIE1_IO_PHY_BASE) : (PCIE_IO_PHY_BASE))
++#define PCIE_IO_PHY_PORT_TO_END(X) ((X) > 0 ? (PCIE1_IO_PHY_END) : (PCIE_IO_PHY_END))
++#define PCIE_APP_PORT_TO_BASE(X) ((X) > 0 ? (PCIE1_APP_LOGIC_REG) : (PCIE_APP_LOGIC_REG))
++#define PCIE_RC_PORT_TO_BASE(X) ((X) > 0 ? (PCIE1_RC_CFG_BASE) : (PCIE_RC_CFG_BASE))
++#define PCIE_PHY_PORT_TO_BASE(X) ((X) > 0 ? (PCIE1_PDI_BASE) : (PCIE_PDI_BASE))
++
++/* PCIe Application Logic Register */
++/* RC Core Control Register */
++#define PCIE_RC_CCR(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x10)
++/* This should be enabled after initializing configuratin registers
++ * Also should check link status retraining bit
++ */
++#define PCIE_RC_CCR_LTSSM_ENABLE 0x00000001 /* Enable LTSSM to continue link establishment */
++
++/* RC Core Debug Register */
++#define PCIE_RC_DR(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x14)
++#define PCIE_RC_DR_DLL_UP 0x00000001 /* Data Link Layer Up */
++#define PCIE_RC_DR_CURRENT_POWER_STATE 0x0000000E /* Current Power State */
++#define PCIE_RC_DR_CURRENT_POWER_STATE_S 1
++#define PCIE_RC_DR_CURRENT_LTSSM_STATE 0x000001F0 /* Current LTSSM State */
++#define PCIE_RC_DR_CURRENT_LTSSM_STATE_S 4
++
++#define PCIE_RC_DR_PM_DEV_STATE 0x00000E00 /* Power Management D-State */
++#define PCIE_RC_DR_PM_DEV_STATE_S 9
++
++#define PCIE_RC_DR_PM_ENABLED 0x00001000 /* Power Management State from PMU */
++#define PCIE_RC_DR_PME_EVENT_ENABLED 0x00002000 /* Power Management Event Enable State */
++#define PCIE_RC_DR_AUX_POWER_ENABLED 0x00004000 /* Auxiliary Power Enable */
++
++/* Current Power State Definition */
++enum {
++ PCIE_RC_DR_D0 = 0,
++ PCIE_RC_DR_D1, /* Not supported */
++ PCIE_RC_DR_D2, /* Not supported */
++ PCIE_RC_DR_D3,
++ PCIE_RC_DR_UN,
++};
++
++/* PHY Link Status Register */
++#define PCIE_PHY_SR(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x18)
++#define PCIE_PHY_SR_PHY_LINK_UP 0x00000001 /* PHY Link Up/Down Indicator */
++
++/* Electromechanical Control Register */
++#define PCIE_EM_CR(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x1C)
++#define PCIE_EM_CR_CARD_IS_PRESENT 0x00000001 /* Card Presence Detect State */
++#define PCIE_EM_CR_MRL_OPEN 0x00000002 /* MRL Sensor State */
++#define PCIE_EM_CR_POWER_FAULT_SET 0x00000004 /* Power Fault Detected */
++#define PCIE_EM_CR_MRL_SENSOR_SET 0x00000008 /* MRL Sensor Changed */
++#define PCIE_EM_CR_PRESENT_DETECT_SET 0x00000010 /* Card Presense Detect Changed */
++#define PCIE_EM_CR_CMD_CPL_INT_SET 0x00000020 /* Command Complete Interrupt */
++#define PCIE_EM_CR_SYS_INTERLOCK_SET 0x00000040 /* System Electromechanical IterLock Engaged */
++#define PCIE_EM_CR_ATTENTION_BUTTON_SET 0x00000080 /* Attention Button Pressed */
++
++/* Interrupt Status Register */
++#define PCIE_IR_SR(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x20)
++#define PCIE_IR_SR_PME_CAUSE_MSI 0x00000002 /* MSI caused by PME */
++#define PCIE_IR_SR_HP_PME_WAKE_GEN 0x00000004 /* Hotplug PME Wake Generation */
++#define PCIE_IR_SR_HP_MSI 0x00000008 /* Hotplug MSI */
++#define PCIE_IR_SR_AHB_LU_ERR 0x00000030 /* AHB Bridge Lookup Error Signals */
++#define PCIE_IR_SR_AHB_LU_ERR_S 4
++#define PCIE_IR_SR_INT_MSG_NUM 0x00003E00 /* Interrupt Message Number */
++#define PCIE_IR_SR_INT_MSG_NUM_S 9
++#define PCIE_IR_SR_AER_INT_MSG_NUM 0xF8000000 /* Advanced Error Interrupt Message Number */
++#define PCIE_IR_SR_AER_INT_MSG_NUM_S 27
++
++/* Message Control Register */
++#define PCIE_MSG_CR(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x30)
++#define PCIE_MSG_CR_GEN_PME_TURN_OFF_MSG 0x00000001 /* Generate PME Turn Off Message */
++#define PCIE_MSG_CR_GEN_UNLOCK_MSG 0x00000002 /* Generate Unlock Message */
++
++#define PCIE_VDM_DR(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x34)
++
++/* Vendor-Defined Message Requester ID Register */
++#define PCIE_VDM_RID(X) (PCIE_APP_PORT_TO_BASE (X) + 0x38)
++#define PCIE_VDM_RID_VENROR_MSG_REQ_ID 0x0000FFFF
++#define PCIE_VDM_RID_VDMRID_S 0
++
++/* ASPM Control Register */
++#define PCIE_ASPM_CR(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x40)
++#define PCIE_ASPM_CR_HOT_RST 0x00000001 /* Hot Reset Request to the downstream device */
++#define PCIE_ASPM_CR_REQ_EXIT_L1 0x00000002 /* Request to Exit L1 */
++#define PCIE_ASPM_CR_REQ_ENTER_L1 0x00000004 /* Request to Enter L1 */
++
++/* Vendor Message DW0 Register */
++#define PCIE_VM_MSG_DW0(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x50)
++#define PCIE_VM_MSG_DW0_TYPE 0x0000001F /* Message type */
++#define PCIE_VM_MSG_DW0_TYPE_S 0
++#define PCIE_VM_MSG_DW0_FORMAT 0x00000060 /* Format */
++#define PCIE_VM_MSG_DW0_FORMAT_S 5
++#define PCIE_VM_MSG_DW0_TC 0x00007000 /* Traffic Class */
++#define PCIE_VM_MSG_DW0_TC_S 12
++#define PCIE_VM_MSG_DW0_ATTR 0x000C0000 /* Atrributes */
++#define PCIE_VM_MSG_DW0_ATTR_S 18
++#define PCIE_VM_MSG_DW0_EP_TLP 0x00100000 /* Poisoned TLP */
++#define PCIE_VM_MSG_DW0_TD 0x00200000 /* TLP Digest */
++#define PCIE_VM_MSG_DW0_LEN 0xFFC00000 /* Length */
++#define PCIE_VM_MSG_DW0_LEN_S 22
++
++/* Format Definition */
++enum {
++ PCIE_VM_MSG_FORMAT_00 = 0, /* 3DW Hdr, no data*/
++ PCIE_VM_MSG_FORMAT_01, /* 4DW Hdr, no data */
++ PCIE_VM_MSG_FORMAT_10, /* 3DW Hdr, with data */
++ PCIE_VM_MSG_FORMAT_11, /* 4DW Hdr, with data */
++};
++
++/* Traffic Class Definition */
++enum {
++ PCIE_VM_MSG_TC0 = 0,
++ PCIE_VM_MSG_TC1,
++ PCIE_VM_MSG_TC2,
++ PCIE_VM_MSG_TC3,
++ PCIE_VM_MSG_TC4,
++ PCIE_VM_MSG_TC5,
++ PCIE_VM_MSG_TC6,
++ PCIE_VM_MSG_TC7,
++};
++
++/* Attributes Definition */
++enum {
++ PCIE_VM_MSG_ATTR_00 = 0, /* RO and No Snoop cleared */
++ PCIE_VM_MSG_ATTR_01, /* RO cleared , No Snoop set */
++ PCIE_VM_MSG_ATTR_10, /* RO set, No Snoop cleared*/
++ PCIE_VM_MSG_ATTR_11, /* RO and No Snoop set */
++};
++
++/* Payload Size Definition */
++#define PCIE_VM_MSG_LEN_MIN 0
++#define PCIE_VM_MSG_LEN_MAX 1024
++
++/* Vendor Message DW1 Register */
++#define PCIE_VM_MSG_DW1(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x54)
++#define PCIE_VM_MSG_DW1_FUNC_NUM 0x00000070 /* Function Number */
++#define PCIE_VM_MSG_DW1_FUNC_NUM_S 8
++#define PCIE_VM_MSG_DW1_CODE 0x00FF0000 /* Message Code */
++#define PCIE_VM_MSG_DW1_CODE_S 16
++#define PCIE_VM_MSG_DW1_TAG 0xFF000000 /* Tag */
++#define PCIE_VM_MSG_DW1_TAG_S 24
++
++#define PCIE_VM_MSG_DW2(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x58)
++#define PCIE_VM_MSG_DW3(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x5C)
++
++/* Vendor Message Request Register */
++#define PCIE_VM_MSG_REQR(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x60)
++#define PCIE_VM_MSG_REQR_REQ 0x00000001 /* Vendor Message Request */
++
++
++/* AHB Slave Side Band Control Register */
++#define PCIE_AHB_SSB(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x70)
++#define PCIE_AHB_SSB_REQ_BCM 0x00000001 /* Slave Reques BCM filed */
++#define PCIE_AHB_SSB_REQ_EP 0x00000002 /* Slave Reques EP filed */
++#define PCIE_AHB_SSB_REQ_TD 0x00000004 /* Slave Reques TD filed */
++#define PCIE_AHB_SSB_REQ_ATTR 0x00000018 /* Slave Reques Attribute number */
++#define PCIE_AHB_SSB_REQ_ATTR_S 3
++#define PCIE_AHB_SSB_REQ_TC 0x000000E0 /* Slave Request TC Field */
++#define PCIE_AHB_SSB_REQ_TC_S 5
++
++/* AHB Master SideBand Ctrl Register */
++#define PCIE_AHB_MSB(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x74)
++#define PCIE_AHB_MSB_RESP_ATTR 0x00000003 /* Master Response Attribute number */
++#define PCIE_AHB_MSB_RESP_ATTR_S 0
++#define PCIE_AHB_MSB_RESP_BAD_EOT 0x00000004 /* Master Response Badeot filed */
++#define PCIE_AHB_MSB_RESP_BCM 0x00000008 /* Master Response BCM filed */
++#define PCIE_AHB_MSB_RESP_EP 0x00000010 /* Master Response EP filed */
++#define PCIE_AHB_MSB_RESP_TD 0x00000020 /* Master Response TD filed */
++#define PCIE_AHB_MSB_RESP_FUN_NUM 0x000003C0 /* Master Response Function number */
++#define PCIE_AHB_MSB_RESP_FUN_NUM_S 6
++
++/* AHB Control Register, fixed bus enumeration exception */
++#define PCIE_AHB_CTRL(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0x78)
++#define PCIE_AHB_CTRL_BUS_ERROR_SUPPRESS 0x00000001
++
++/* Interrupt Enalbe Register */
++#define PCIE_IRNEN(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0xF4)
++#define PCIE_IRNCR(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0xF8)
++#define PCIE_IRNICR(X) (volatile u32*)(PCIE_APP_PORT_TO_BASE(X) + 0xFC)
++
++/* PCIe interrupt enable/control/capture register definition */
++#define PCIE_IRN_AER_REPORT 0x00000001 /* AER Interrupt */
++#define PCIE_IRN_AER_MSIX 0x00000002 /* Advanced Error MSI-X Interrupt */
++#define PCIE_IRN_PME 0x00000004 /* PME Interrupt */
++#define PCIE_IRN_HOTPLUG 0x00000008 /* Hotplug Interrupt */
++#define PCIE_IRN_RX_VDM_MSG 0x00000010 /* Vendor-Defined Message Interrupt */
++#define PCIE_IRN_RX_CORRECTABLE_ERR_MSG 0x00000020 /* Correctable Error Message Interrupt */
++#define PCIE_IRN_RX_NON_FATAL_ERR_MSG 0x00000040 /* Non-fatal Error Message */
++#define PCIE_IRN_RX_FATAL_ERR_MSG 0x00000080 /* Fatal Error Message */
++#define PCIE_IRN_RX_PME_MSG 0x00000100 /* PME Message Interrupt */
++#define PCIE_IRN_RX_PME_TURNOFF_ACK 0x00000200 /* PME Turnoff Ack Message Interrupt */
++#define PCIE_IRN_AHB_BR_FATAL_ERR 0x00000400 /* AHB Fatal Error Interrupt */
++#define PCIE_IRN_LINK_AUTO_BW_STATUS 0x00000800 /* Link Auto Bandwidth Status Interrupt */
++#define PCIE_IRN_BW_MGT 0x00001000 /* Bandwidth Managment Interrupt */
++#define PCIE_IRN_INTA 0x00002000 /* INTA */
++#define PCIE_IRN_INTB 0x00004000 /* INTB */
++#define PCIE_IRN_INTC 0x00008000 /* INTC */
++#define PCIE_IRN_INTD 0x00010000 /* INTD */
++#define PCIE_IRN_WAKEUP 0x00020000 /* Wake up Interrupt */
++
++#define PCIE_RC_CORE_COMBINED_INT (PCIE_IRN_AER_REPORT | PCIE_IRN_AER_MSIX | PCIE_IRN_PME | \
++ PCIE_IRN_HOTPLUG | PCIE_IRN_RX_VDM_MSG | PCIE_IRN_RX_CORRECTABLE_ERR_MSG |\
++ PCIE_IRN_RX_NON_FATAL_ERR_MSG | PCIE_IRN_RX_FATAL_ERR_MSG | \
++ PCIE_IRN_RX_PME_MSG | PCIE_IRN_RX_PME_TURNOFF_ACK | PCIE_IRN_AHB_BR_FATAL_ERR | \
++ PCIE_IRN_LINK_AUTO_BW_STATUS | PCIE_IRN_BW_MGT)
++/* PCIe RC Configuration Register */
++#define PCIE_VDID(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x00)
++
++/* Bit definition from pci_reg.h */
++#define PCIE_PCICMDSTS(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x04)
++#define PCIE_CCRID(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x08)
++#define PCIE_CLSLTHTBR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x0C) /* EP only */
++/* BAR0, BAR1,Only necessary if the bridges implements a device-specific register set or memory buffer */
++#define PCIE_BAR0(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x10) /* Not used*/
++#define PCIE_BAR1(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x14) /* Not used */
++
++#define PCIE_BNR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x18) /* Mandatory */
++/* Bus Number Register bits */
++#define PCIE_BNR_PRIMARY_BUS_NUM 0x000000FF
++#define PCIE_BNR_PRIMARY_BUS_NUM_S 0
++#define PCIE_PNR_SECONDARY_BUS_NUM 0x0000FF00
++#define PCIE_PNR_SECONDARY_BUS_NUM_S 8
++#define PCIE_PNR_SUB_BUS_NUM 0x00FF0000
++#define PCIE_PNR_SUB_BUS_NUM_S 16
++
++/* IO Base/Limit Register bits */
++#define PCIE_IOBLSECS(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x1C) /* RC only */
++#define PCIE_IOBLSECS_32BIT_IO_ADDR 0x00000001
++#define PCIE_IOBLSECS_IO_BASE_ADDR 0x000000F0
++#define PCIE_IOBLSECS_IO_BASE_ADDR_S 4
++#define PCIE_IOBLSECS_32BIT_IOLIMT 0x00000100
++#define PCIE_IOBLSECS_IO_LIMIT_ADDR 0x0000F000
++#define PCIE_IOBLSECS_IO_LIMIT_ADDR_S 12
++
++/* Non-prefetchable Memory Base/Limit Register bit */
++#define PCIE_MBML(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x20) /* RC only */
++#define PCIE_MBML_MEM_BASE_ADDR 0x0000FFF0
++#define PCIE_MBML_MEM_BASE_ADDR_S 4
++#define PCIE_MBML_MEM_LIMIT_ADDR 0xFFF00000
++#define PCIE_MBML_MEM_LIMIT_ADDR_S 20
++
++/* Prefetchable Memory Base/Limit Register bit */
++#define PCIE_PMBL(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x24) /* RC only */
++#define PCIE_PMBL_64BIT_ADDR 0x00000001
++#define PCIE_PMBL_UPPER_12BIT 0x0000FFF0
++#define PCIE_PMBL_UPPER_12BIT_S 4
++#define PCIE_PMBL_E64MA 0x00010000
++#define PCIE_PMBL_END_ADDR 0xFFF00000
++#define PCIE_PMBL_END_ADDR_S 20
++#define PCIE_PMBU32(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x28) /* RC only */
++#define PCIE_PMLU32(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x2C) /* RC only */
++
++/* I/O Base/Limit Upper 16 bits register */
++#define PCIE_IO_BANDL(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x30) /* RC only */
++#define PCIE_IO_BANDL_UPPER_16BIT_IO_BASE 0x0000FFFF
++#define PCIE_IO_BANDL_UPPER_16BIT_IO_BASE_S 0
++#define PCIE_IO_BANDL_UPPER_16BIT_IO_LIMIT 0xFFFF0000
++#define PCIE_IO_BANDL_UPPER_16BIT_IO_LIMIT_S 16
++
++#define PCIE_CPR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x34)
++#define PCIE_EBBAR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x38)
++
++/* Interrupt and Secondary Bridge Control Register */
++#define PCIE_INTRBCTRL(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x3C)
++
++#define PCIE_INTRBCTRL_INT_LINE 0x000000FF
++#define PCIE_INTRBCTRL_INT_LINE_S 0
++#define PCIE_INTRBCTRL_INT_PIN 0x0000FF00
++#define PCIE_INTRBCTRL_INT_PIN_S 8
++#define PCIE_INTRBCTRL_PARITY_ERR_RESP_ENABLE 0x00010000 /* #PERR */
++#define PCIE_INTRBCTRL_SERR_ENABLE 0x00020000 /* #SERR */
++#define PCIE_INTRBCTRL_ISA_ENABLE 0x00040000 /* ISA enable, IO 64KB only */
++#define PCIE_INTRBCTRL_VGA_ENABLE 0x00080000 /* VGA enable */
++#define PCIE_INTRBCTRL_VGA_16BIT_DECODE 0x00100000 /* VGA 16bit decode */
++#define PCIE_INTRBCTRL_RST_SECONDARY_BUS 0x00400000 /* Secondary bus rest, hot rest, 1ms */
++/* Others are read only */
++enum {
++ PCIE_INTRBCTRL_INT_NON = 0,
++ PCIE_INTRBCTRL_INTA,
++ PCIE_INTRBCTRL_INTB,
++ PCIE_INTRBCTRL_INTC,
++ PCIE_INTRBCTRL_INTD,
++};
++
++#define PCIE_PM_CAPR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x40)
++
++/* Power Management Control and Status Register */
++#define PCIE_PM_CSR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x44)
++
++#define PCIE_PM_CSR_POWER_STATE 0x00000003 /* Power State */
++#define PCIE_PM_CSR_POWER_STATE_S 0
++#define PCIE_PM_CSR_SW_RST 0x00000008 /* Soft Reset Enabled */
++#define PCIE_PM_CSR_PME_ENABLE 0x00000100 /* PME Enable */
++#define PCIE_PM_CSR_PME_STATUS 0x00008000 /* PME status */
++
++/* MSI Capability Register for EP */
++#define PCIE_MCAPR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x50)
++
++#define PCIE_MCAPR_MSI_CAP_ID 0x000000FF /* MSI Capability ID */
++#define PCIE_MCAPR_MSI_CAP_ID_S 0
++#define PCIE_MCAPR_MSI_NEXT_CAP_PTR 0x0000FF00 /* Next Capability Pointer */
++#define PCIE_MCAPR_MSI_NEXT_CAP_PTR_S 8
++#define PCIE_MCAPR_MSI_ENABLE 0x00010000 /* MSI Enable */
++#define PCIE_MCAPR_MULTI_MSG_CAP 0x000E0000 /* Multiple Message Capable */
++#define PCIE_MCAPR_MULTI_MSG_CAP_S 17
++#define PCIE_MCAPR_MULTI_MSG_ENABLE 0x00700000 /* Multiple Message Enable */
++#define PCIE_MCAPR_MULTI_MSG_ENABLE_S 20
++#define PCIE_MCAPR_ADDR64_CAP 0X00800000 /* 64-bit Address Capable */
++
++/* MSI Message Address Register */
++#define PCIE_MA(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x54)
++
++#define PCIE_MA_ADDR_MASK 0xFFFFFFFC /* Message Address */
++
++/* MSI Message Upper Address Register */
++#define PCIE_MUA(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x58)
++
++/* MSI Message Data Register */
++#define PCIE_MD(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x5C)
++
++#define PCIE_MD_DATA 0x0000FFFF /* Message Data */
++#define PCIE_MD_DATA_S 0
++
++/* PCI Express Capability Register */
++#define PCIE_XCAP(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x70)
++
++#define PCIE_XCAP_ID 0x000000FF /* PCI Express Capability ID */
++#define PCIE_XCAP_ID_S 0
++#define PCIE_XCAP_NEXT_CAP 0x0000FF00 /* Next Capability Pointer */
++#define PCIE_XCAP_NEXT_CAP_S 8
++#define PCIE_XCAP_VER 0x000F0000 /* PCI Express Capability Version */
++#define PCIE_XCAP_VER_S 16
++#define PCIE_XCAP_DEV_PORT_TYPE 0x00F00000 /* Device Port Type */
++#define PCIE_XCAP_DEV_PORT_TYPE_S 20
++#define PCIE_XCAP_SLOT_IMPLEMENTED 0x01000000 /* Slot Implemented */
++#define PCIE_XCAP_MSG_INT_NUM 0x3E000000 /* Interrupt Message Number */
++#define PCIE_XCAP_MSG_INT_NUM_S 25
++
++/* Device Capability Register */
++#define PCIE_DCAP(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x74)
++
++#define PCIE_DCAP_MAX_PAYLOAD_SIZE 0x00000007 /* Max Payload size */
++#define PCIE_DCAP_MAX_PAYLOAD_SIZE_S 0
++#define PCIE_DCAP_PHANTOM_FUNC 0x00000018 /* Phanton Function, not supported */
++#define PCIE_DCAP_PHANTOM_FUNC_S 3
++#define PCIE_DCAP_EXT_TAG 0x00000020 /* Extended Tag Field */
++#define PCIE_DCAP_EP_L0S_LATENCY 0x000001C0 /* EP L0s latency only */
++#define PCIE_DCAP_EP_L0S_LATENCY_S 6
++#define PCIE_DCAP_EP_L1_LATENCY 0x00000E00 /* EP L1 latency only */
++#define PCIE_DCAP_EP_L1_LATENCY_S 9
++#define PCIE_DCAP_ROLE_BASE_ERR_REPORT 0x00008000 /* Role Based ERR */
++
++/* Maximum payload size supported */
++enum {
++ PCIE_MAX_PAYLOAD_128 = 0,
++ PCIE_MAX_PAYLOAD_256,
++ PCIE_MAX_PAYLOAD_512,
++ PCIE_MAX_PAYLOAD_1024,
++ PCIE_MAX_PAYLOAD_2048,
++ PCIE_MAX_PAYLOAD_4096,
++};
++
++/* Device Control and Status Register */
++#define PCIE_DCTLSTS(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x78)
++
++#define PCIE_DCTLSTS_CORRECTABLE_ERR_EN 0x00000001 /* COR-ERR */
++#define PCIE_DCTLSTS_NONFATAL_ERR_EN 0x00000002 /* Non-fatal ERR */
++#define PCIE_DCTLSTS_FATAL_ERR_EN 0x00000004 /* Fatal ERR */
++#define PCIE_DCTLSYS_UR_REQ_EN 0x00000008 /* UR ERR */
++#define PCIE_DCTLSTS_RELAXED_ORDERING_EN 0x00000010 /* Enable relaxing ordering */
++#define PCIE_DCTLSTS_MAX_PAYLOAD_SIZE 0x000000E0 /* Max payload mask */
++#define PCIE_DCTLSTS_MAX_PAYLOAD_SIZE_S 5
++#define PCIE_DCTLSTS_EXT_TAG_EN 0x00000100 /* Extended tag field */
++#define PCIE_DCTLSTS_PHANTOM_FUNC_EN 0x00000200 /* Phantom Function Enable */
++#define PCIE_DCTLSTS_AUX_PM_EN 0x00000400 /* AUX Power PM Enable */
++#define PCIE_DCTLSTS_NO_SNOOP_EN 0x00000800 /* Enable no snoop, except root port*/
++#define PCIE_DCTLSTS_MAX_READ_SIZE 0x00007000 /* Max Read Request size*/
++#define PCIE_DCTLSTS_MAX_READ_SIZE_S 12
++#define PCIE_DCTLSTS_CORRECTABLE_ERR 0x00010000 /* COR-ERR Detected */
++#define PCIE_DCTLSTS_NONFATAL_ERR 0x00020000 /* Non-Fatal ERR Detected */
++#define PCIE_DCTLSTS_FATAL_ER 0x00040000 /* Fatal ERR Detected */
++#define PCIE_DCTLSTS_UNSUPPORTED_REQ 0x00080000 /* UR Detected */
++#define PCIE_DCTLSTS_AUX_POWER 0x00100000 /* Aux Power Detected */
++#define PCIE_DCTLSTS_TRANSACT_PENDING 0x00200000 /* Transaction pending */
++
++#define PCIE_DCTLSTS_ERR_EN (PCIE_DCTLSTS_CORRECTABLE_ERR_EN | \
++ PCIE_DCTLSTS_NONFATAL_ERR_EN | PCIE_DCTLSTS_FATAL_ERR_EN | \
++ PCIE_DCTLSYS_UR_REQ_EN)
++
++/* Link Capability Register */
++#define PCIE_LCAP(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x7C)
++#define PCIE_LCAP_MAX_LINK_SPEED 0x0000000F /* Max link speed, 0x1 by default */
++#define PCIE_LCAP_MAX_LINK_SPEED_S 0
++#define PCIE_LCAP_MAX_LENGTH_WIDTH 0x000003F0 /* Maxium Length Width */
++#define PCIE_LCAP_MAX_LENGTH_WIDTH_S 4
++#define PCIE_LCAP_ASPM_LEVEL 0x00000C00 /* Active State Link PM Support */
++#define PCIE_LCAP_ASPM_LEVEL_S 10
++#define PCIE_LCAP_L0S_EIXT_LATENCY 0x00007000 /* L0s Exit Latency */
++#define PCIE_LCAP_L0S_EIXT_LATENCY_S 12
++#define PCIE_LCAP_L1_EXIT_LATENCY 0x00038000 /* L1 Exit Latency */
++#define PCIE_LCAP_L1_EXIT_LATENCY_S 15
++#define PCIE_LCAP_CLK_PM 0x00040000 /* Clock Power Management */
++#define PCIE_LCAP_SDER 0x00080000 /* Surprise Down Error Reporting */
++#define PCIE_LCAP_DLL_ACTIVE_REPROT 0x00100000 /* Data Link Layer Active Reporting Capable */
++#define PCIE_LCAP_PORT_NUM 0xFF0000000 /* Port number */
++#define PCIE_LCAP_PORT_NUM_S 24
++
++/* Maximum Length width definition */
++#define PCIE_MAX_LENGTH_WIDTH_RES 0x00
++#define PCIE_MAX_LENGTH_WIDTH_X1 0x01 /* Default */
++#define PCIE_MAX_LENGTH_WIDTH_X2 0x02
++#define PCIE_MAX_LENGTH_WIDTH_X4 0x04
++#define PCIE_MAX_LENGTH_WIDTH_X8 0x08
++#define PCIE_MAX_LENGTH_WIDTH_X12 0x0C
++#define PCIE_MAX_LENGTH_WIDTH_X16 0x10
++#define PCIE_MAX_LENGTH_WIDTH_X32 0x20
++
++/* Active State Link PM definition */
++enum {
++ PCIE_ASPM_RES0 = 0,
++ PCIE_ASPM_L0S_ENTRY_SUPPORT, /* L0s */
++ PCIE_ASPM_RES1,
++ PCIE_ASPM_L0S_L1_ENTRY_SUPPORT, /* L0s and L1, default */
++};
++
++/* L0s Exit Latency definition */
++enum {
++ PCIE_L0S_EIXT_LATENCY_L64NS = 0, /* < 64 ns */
++ PCIE_L0S_EIXT_LATENCY_B64A128, /* > 64 ns < 128 ns */
++ PCIE_L0S_EIXT_LATENCY_B128A256, /* > 128 ns < 256 ns */
++ PCIE_L0S_EIXT_LATENCY_B256A512, /* > 256 ns < 512 ns */
++ PCIE_L0S_EIXT_LATENCY_B512TO1U, /* > 512 ns < 1 us */
++ PCIE_L0S_EIXT_LATENCY_B1A2U, /* > 1 us < 2 us */
++ PCIE_L0S_EIXT_LATENCY_B2A4U, /* > 2 us < 4 us */
++ PCIE_L0S_EIXT_LATENCY_M4US, /* > 4 us */
++};
++
++/* L1 Exit Latency definition */
++enum {
++ PCIE_L1_EXIT_LATENCY_L1US = 0, /* < 1 us */
++ PCIE_L1_EXIT_LATENCY_B1A2, /* > 1 us < 2 us */
++ PCIE_L1_EXIT_LATENCY_B2A4, /* > 2 us < 4 us */
++ PCIE_L1_EXIT_LATENCY_B4A8, /* > 4 us < 8 us */
++ PCIE_L1_EXIT_LATENCY_B8A16, /* > 8 us < 16 us */
++ PCIE_L1_EXIT_LATENCY_B16A32, /* > 16 us < 32 us */
++ PCIE_L1_EXIT_LATENCY_B32A64, /* > 32 us < 64 us */
++ PCIE_L1_EXIT_LATENCY_M64US, /* > 64 us */
++};
++
++/* Link Control and Status Register */
++#define PCIE_LCTLSTS(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x80)
++#define PCIE_LCTLSTS_ASPM_ENABLE 0x00000003 /* Active State Link PM Control */
++#define PCIE_LCTLSTS_ASPM_ENABLE_S 0
++#define PCIE_LCTLSTS_RCB128 0x00000008 /* Read Completion Boundary 128*/
++#define PCIE_LCTLSTS_LINK_DISABLE 0x00000010 /* Link Disable */
++#define PCIE_LCTLSTS_RETRIAN_LINK 0x00000020 /* Retrain Link */
++#define PCIE_LCTLSTS_COM_CLK_CFG 0x00000040 /* Common Clock Configuration */
++#define PCIE_LCTLSTS_EXT_SYNC 0x00000080 /* Extended Synch */
++#define PCIE_LCTLSTS_CLK_PM_EN 0x00000100 /* Enable Clock Powerm Management */
++#define PCIE_LCTLSTS_LINK_SPEED 0x000F0000 /* Link Speed */
++#define PCIE_LCTLSTS_LINK_SPEED_S 16
++#define PCIE_LCTLSTS_NEGOTIATED_LINK_WIDTH 0x03F00000 /* Negotiated Link Width */
++#define PCIE_LCTLSTS_NEGOTIATED_LINK_WIDTH_S 20
++#define PCIE_LCTLSTS_RETRAIN_PENDING 0x08000000 /* Link training is ongoing */
++#define PCIE_LCTLSTS_SLOT_CLK_CFG 0x10000000 /* Slot Clock Configuration */
++#define PCIE_LCTLSTS_DLL_ACTIVE 0x20000000 /* Data Link Layer Active */
++
++/* Slot Capabilities Register */
++#define PCIE_SLCAP(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x84)
++
++/* Slot Capabilities */
++#define PCIE_SLCTLSTS(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x88)
++
++/* Root Control and Capability Register */
++#define PCIE_RCTLCAP(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x8C)
++#define PCIE_RCTLCAP_SERR_ON_CORRECTABLE_ERR 0x00000001 /* #SERR on COR-ERR */
++#define PCIE_RCTLCAP_SERR_ON_NONFATAL_ERR 0x00000002 /* #SERR on Non-Fatal ERR */
++#define PCIE_RCTLCAP_SERR_ON_FATAL_ERR 0x00000004 /* #SERR on Fatal ERR */
++#define PCIE_RCTLCAP_PME_INT_EN 0x00000008 /* PME Interrupt Enable */
++#define PCIE_RCTLCAP_SERR_ENABLE (PCIE_RCTLCAP_SERR_ON_CORRECTABLE_ERR | \
++ PCIE_RCTLCAP_SERR_ON_NONFATAL_ERR | PCIE_RCTLCAP_SERR_ON_FATAL_ERR)
++/* Root Status Register */
++#define PCIE_RSTS(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x90)
++#define PCIE_RSTS_PME_REQ_ID 0x0000FFFF /* PME Request ID */
++#define PCIE_RSTS_PME_REQ_ID_S 0
++#define PCIE_RSTS_PME_STATUS 0x00010000 /* PME Status */
++#define PCIE_RSTS_PME_PENDING 0x00020000 /* PME Pending */
++
++/* PCI Express Enhanced Capability Header */
++#define PCIE_ENHANCED_CAP(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x100)
++#define PCIE_ENHANCED_CAP_ID 0x0000FFFF /* PCI Express Extended Capability ID */
++#define PCIE_ENHANCED_CAP_ID_S 0
++#define PCIE_ENHANCED_CAP_VER 0x000F0000 /* Capability Version */
++#define PCIE_ENHANCED_CAP_VER_S 16
++#define PCIE_ENHANCED_CAP_NEXT_OFFSET 0xFFF00000 /* Next Capability Offset */
++#define PCIE_ENHANCED_CAP_NEXT_OFFSET_S 20
++
++/* Uncorrectable Error Status Register */
++#define PCIE_UES_R(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x104)
++#define PCIE_DATA_LINK_PROTOCOL_ERR 0x00000010 /* Data Link Protocol Error Status */
++#define PCIE_SURPRISE_DOWN_ERROR 0x00000020 /* Surprise Down Error Status */
++#define PCIE_POISONED_TLP 0x00001000 /* Poisoned TLP Status */
++#define PCIE_FC_PROTOCOL_ERR 0x00002000 /* Flow Control Protocol Error Status */
++#define PCIE_COMPLETION_TIMEOUT 0x00004000 /* Completion Timeout Status */
++#define PCIE_COMPLETOR_ABORT 0x00008000 /* Completer Abort Error */
++#define PCIE_UNEXPECTED_COMPLETION 0x00010000 /* Unexpected Completion Status */
++#define PCIE_RECEIVER_OVERFLOW 0x00020000 /* Receive Overflow Status */
++#define PCIE_MALFORNED_TLP 0x00040000 /* Malformed TLP Stauts */
++#define PCIE_ECRC_ERR 0x00080000 /* ECRC Error Stauts */
++#define PCIE_UR_REQ 0x00100000 /* Unsupported Request Error Status */
++#define PCIE_ALL_UNCORRECTABLE_ERR (PCIE_DATA_LINK_PROTOCOL_ERR | PCIE_SURPRISE_DOWN_ERROR | \
++ PCIE_POISONED_TLP | PCIE_FC_PROTOCOL_ERR | PCIE_COMPLETION_TIMEOUT | \
++ PCIE_COMPLETOR_ABORT | PCIE_UNEXPECTED_COMPLETION | PCIE_RECEIVER_OVERFLOW |\
++ PCIE_MALFORNED_TLP | PCIE_ECRC_ERR | PCIE_UR_REQ)
++
++/* Uncorrectable Error Mask Register, Mask means no report */
++#define PCIE_UEMR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x108)
++
++/* Uncorrectable Error Severity Register */
++#define PCIE_UESR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x10C)
++
++/* Correctable Error Status Register */
++#define PCIE_CESR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x110)
++#define PCIE_RX_ERR 0x00000001 /* Receive Error Status */
++#define PCIE_BAD_TLP 0x00000040 /* Bad TLP Status */
++#define PCIE_BAD_DLLP 0x00000080 /* Bad DLLP Status */
++#define PCIE_REPLAY_NUM_ROLLOVER 0x00000100 /* Replay Number Rollover Status */
++#define PCIE_REPLAY_TIMER_TIMEOUT_ERR 0x00001000 /* Reply Timer Timeout Status */
++#define PCIE_ADVISORY_NONFTAL_ERR 0x00002000 /* Advisory Non-Fatal Error Status */
++#define PCIE_CORRECTABLE_ERR (PCIE_RX_ERR | PCIE_BAD_TLP | PCIE_BAD_DLLP | PCIE_REPLAY_NUM_ROLLOVER |\
++ PCIE_REPLAY_TIMER_TIMEOUT_ERR | PCIE_ADVISORY_NONFTAL_ERR)
++
++/* Correctable Error Mask Register */
++#define PCIE_CEMR(X) (volatile u32*)(PCIE_RC_CFG_BASE + 0x114)
++
++/* Advanced Error Capabilities and Control Register */
++#define PCIE_AECCR(X) (volatile u32*)(PCIE_RC_CFG_BASE + 0x118)
++#define PCIE_AECCR_FIRST_ERR_PTR 0x0000001F /* First Error Pointer */
++#define PCIE_AECCR_FIRST_ERR_PTR_S 0
++#define PCIE_AECCR_ECRC_GEN_CAP 0x00000020 /* ECRC Generation Capable */
++#define PCIE_AECCR_ECRC_GEN_EN 0x00000040 /* ECRC Generation Enable */
++#define PCIE_AECCR_ECRC_CHECK_CAP 0x00000080 /* ECRC Check Capable */
++#define PCIE_AECCR_ECRC_CHECK_EN 0x00000100 /* ECRC Check Enable */
++
++/* Header Log Register 1 */
++#define PCIE_HLR1(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x11C)
++
++/* Header Log Register 2 */
++#define PCIE_HLR2(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x120)
++
++/* Header Log Register 3 */
++#define PCIE_HLR3(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x124)
++
++/* Header Log Register 4 */
++#define PCIE_HLR4(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x128)
++
++/* Root Error Command Register */
++#define PCIE_RECR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x12C)
++#define PCIE_RECR_CORRECTABLE_ERR_REPORT_EN 0x00000001 /* COR-ERR */
++#define PCIE_RECR_NONFATAL_ERR_REPORT_EN 0x00000002 /* Non-Fatal ERR */
++#define PCIE_RECR_FATAL_ERR_REPORT_EN 0x00000004 /* Fatal ERR */
++#define PCIE_RECR_ERR_REPORT_EN (PCIE_RECR_CORRECTABLE_ERR_REPORT_EN | \
++ PCIE_RECR_NONFATAL_ERR_REPORT_EN | PCIE_RECR_FATAL_ERR_REPORT_EN)
++
++/* Root Error Status Register */
++#define PCIE_RESR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x130)
++#define PCIE_RESR_CORRECTABLE_ERR 0x00000001 /* COR-ERR Receveid */
++#define PCIE_RESR_MULTI_CORRECTABLE_ERR 0x00000002 /* Multiple COR-ERR Received */
++#define PCIE_RESR_FATAL_NOFATAL_ERR 0x00000004 /* ERR Fatal/Non-Fatal Received */
++#define PCIE_RESR_MULTI_FATAL_NOFATAL_ERR 0x00000008 /* Multiple ERR Fatal/Non-Fatal Received */
++#define PCIE_RESR_FIRST_UNCORRECTABLE_FATAL_ERR 0x00000010 /* First UN-COR Fatal */
++#define PCIR_RESR_NON_FATAL_ERR 0x00000020 /* Non-Fatal Error Message Received */
++#define PCIE_RESR_FATAL_ERR 0x00000040 /* Fatal Message Received */
++#define PCIE_RESR_AER_INT_MSG_NUM 0xF8000000 /* Advanced Error Interrupt Message Number */
++#define PCIE_RESR_AER_INT_MSG_NUM_S 27
++
++/* Error Source Indentification Register */
++#define PCIE_ESIR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x134)
++#define PCIE_ESIR_CORRECTABLE_ERR_SRC_ID 0x0000FFFF
++#define PCIE_ESIR_CORRECTABLE_ERR_SRC_ID_S 0
++#define PCIE_ESIR_FATAL_NON_FATAL_SRC_ID 0xFFFF0000
++#define PCIE_ESIR_FATAL_NON_FATAL_SRC_ID_S 16
++
++/* VC Enhanced Capability Header */
++#define PCIE_VC_ECH(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x140)
++
++/* Port VC Capability Register */
++#define PCIE_PVC1(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x144)
++#define PCIE_PVC1_EXT_VC_CNT 0x00000007 /* Extended VC Count */
++#define PCIE_PVC1_EXT_VC_CNT_S 0
++#define PCIE_PVC1_LOW_PRI_EXT_VC_CNT 0x00000070 /* Low Priority Extended VC Count */
++#define PCIE_PVC1_LOW_PRI_EXT_VC_CNT_S 4
++#define PCIE_PVC1_REF_CLK 0x00000300 /* Reference Clock */
++#define PCIE_PVC1_REF_CLK_S 8
++#define PCIE_PVC1_PORT_ARB_TAB_ENTRY_SIZE 0x00000C00 /* Port Arbitration Table Entry Size */
++#define PCIE_PVC1_PORT_ARB_TAB_ENTRY_SIZE_S 10
++
++/* Extended Virtual Channel Count Defintion */
++#define PCIE_EXT_VC_CNT_MIN 0
++#define PCIE_EXT_VC_CNT_MAX 7
++
++/* Port Arbitration Table Entry Size Definition */
++enum {
++ PCIE_PORT_ARB_TAB_ENTRY_SIZE_S1BIT = 0,
++ PCIE_PORT_ARB_TAB_ENTRY_SIZE_S2BIT,
++ PCIE_PORT_ARB_TAB_ENTRY_SIZE_S4BIT,
++ PCIE_PORT_ARB_TAB_ENTRY_SIZE_S8BIT,
++};
++
++/* Port VC Capability Register 2 */
++#define PCIE_PVC2(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x148)
++#define PCIE_PVC2_VC_ARB_16P_FIXED_WRR 0x00000001 /* HW Fixed arbitration, 16 phase WRR */
++#define PCIE_PVC2_VC_ARB_32P_WRR 0x00000002 /* 32 phase WRR */
++#define PCIE_PVC2_VC_ARB_64P_WRR 0x00000004 /* 64 phase WRR */
++#define PCIE_PVC2_VC_ARB_128P_WRR 0x00000008 /* 128 phase WRR */
++#define PCIE_PVC2_VC_ARB_WRR 0x0000000F
++#define PCIE_PVC2_VC_ARB_TAB_OFFSET 0xFF000000 /* VC arbitration table offset, not support */
++#define PCIE_PVC2_VC_ARB_TAB_OFFSET_S 24
++
++/* Port VC Control and Status Register */
++#define PCIE_PVCCRSR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x14C)
++#define PCIE_PVCCRSR_LOAD_VC_ARB_TAB 0x00000001 /* Load VC Arbitration Table */
++#define PCIE_PVCCRSR_VC_ARB_SEL 0x0000000E /* VC Arbitration Select */
++#define PCIE_PVCCRSR_VC_ARB_SEL_S 1
++#define PCIE_PVCCRSR_VC_ARB_TAB_STATUS 0x00010000 /* Arbitration Status */
++
++/* VC0 Resource Capability Register */
++#define PCIE_VC0_RC(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x150)
++#define PCIE_VC0_RC_PORT_ARB_HW_FIXED 0x00000001 /* HW Fixed arbitration */
++#define PCIE_VC0_RC_PORT_ARB_32P_WRR 0x00000002 /* 32 phase WRR */
++#define PCIE_VC0_RC_PORT_ARB_64P_WRR 0x00000004 /* 64 phase WRR */
++#define PCIE_VC0_RC_PORT_ARB_128P_WRR 0x00000008 /* 128 phase WRR */
++#define PCIE_VC0_RC_PORT_ARB_TM_128P_WRR 0x00000010 /* Time-based 128 phase WRR */
++#define PCIE_VC0_RC_PORT_ARB_TM_256P_WRR 0x00000020 /* Time-based 256 phase WRR */
++#define PCIE_VC0_RC_PORT_ARB (PCIE_VC0_RC_PORT_ARB_HW_FIXED | PCIE_VC0_RC_PORT_ARB_32P_WRR |\
++ PCIE_VC0_RC_PORT_ARB_64P_WRR | PCIE_VC0_RC_PORT_ARB_128P_WRR | \
++ PCIE_VC0_RC_PORT_ARB_TM_128P_WRR | PCIE_VC0_RC_PORT_ARB_TM_256P_WRR)
++
++#define PCIE_VC0_RC_REJECT_SNOOP 0x00008000 /* Reject Snoop Transactioin */
++#define PCIE_VC0_RC_MAX_TIMESLOTS 0x007F0000 /* Maximum time Slots */
++#define PCIE_VC0_RC_MAX_TIMESLOTS_S 16
++#define PCIE_VC0_RC_PORT_ARB_TAB_OFFSET 0xFF000000 /* Port Arbitration Table Offset */
++#define PCIE_VC0_RC_PORT_ARB_TAB_OFFSET_S 24
++
++/* VC0 Resource Control Register */
++#define PCIE_VC0_RC0(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x154)
++#define PCIE_VC0_RC0_TVM0 0x00000001 /* TC0 and VC0 */
++#define PCIE_VC0_RC0_TVM1 0x00000002 /* TC1 and VC1 */
++#define PCIE_VC0_RC0_TVM2 0x00000004 /* TC2 and VC2 */
++#define PCIE_VC0_RC0_TVM3 0x00000008 /* TC3 and VC3 */
++#define PCIE_VC0_RC0_TVM4 0x00000010 /* TC4 and VC4 */
++#define PCIE_VC0_RC0_TVM5 0x00000020 /* TC5 and VC5 */
++#define PCIE_VC0_RC0_TVM6 0x00000040 /* TC6 and VC6 */
++#define PCIE_VC0_RC0_TVM7 0x00000080 /* TC7 and VC7 */
++#define PCIE_VC0_RC0_TC_VC 0x000000FF /* TC/VC mask */
++
++#define PCIE_VC0_RC0_LOAD_PORT_ARB_TAB 0x00010000 /* Load Port Arbitration Table */
++#define PCIE_VC0_RC0_PORT_ARB_SEL 0x000E0000 /* Port Arbitration Select */
++#define PCIE_VC0_RC0_PORT_ARB_SEL_S 17
++#define PCIE_VC0_RC0_VC_ID 0x07000000 /* VC ID */
++#define PCIE_VC0_RC0_VC_ID_S 24
++#define PCIE_VC0_RC0_VC_EN 0x80000000 /* VC Enable */
++
++/* VC0 Resource Status Register */
++#define PCIE_VC0_RSR0(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x158)
++#define PCIE_VC0_RSR0_PORT_ARB_TAB_STATUS 0x00010000 /* Port Arbitration Table Status,not used */
++#define PCIE_VC0_RSR0_VC_NEG_PENDING 0x00020000 /* VC Negotiation Pending */
++
++/* Ack Latency Timer and Replay Timer Register */
++#define PCIE_ALTRT(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x700)
++#define PCIE_ALTRT_ROUND_TRIP_LATENCY_LIMIT 0x0000FFFF /* Round Trip Latency Time Limit */
++#define PCIE_ALTRT_ROUND_TRIP_LATENCY_LIMIT_S 0
++#define PCIE_ALTRT_REPLAY_TIME_LIMIT 0xFFFF0000 /* Replay Time Limit */
++#define PCIE_ALTRT_REPLAY_TIME_LIMIT_S 16
++
++/* Other Message Register */
++#define PCIE_OMR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x704)
++
++/* Port Force Link Register */
++#define PCIE_PFLR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x708)
++#define PCIE_PFLR_LINK_NUM 0x000000FF /* Link Number */
++#define PCIE_PFLR_LINK_NUM_S 0
++#define PCIE_PFLR_FORCE_LINK 0x00008000 /* Force link */
++#define PCIE_PFLR_LINK_STATE 0x003F0000 /* Link State */
++#define PCIE_PFLR_LINK_STATE_S 16
++#define PCIE_PFLR_LOW_POWER_ENTRY_CNT 0xFF000000 /* Low Power Entrance Count, only for EP */
++#define PCIE_PFLR_LOW_POWER_ENTRY_CNT_S 24
++
++/* Ack Frequency Register */
++#define PCIE_AFR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x70C)
++#define PCIE_AFR_AF 0x000000FF /* Ack Frequency */
++#define PCIE_AFR_AF_S 0
++#define PCIE_AFR_FTS_NUM 0x0000FF00 /* The number of Fast Training Sequence from L0S to L0 */
++#define PCIE_AFR_FTS_NUM_S 8
++#define PCIE_AFR_COM_FTS_NUM 0x00FF0000 /* N_FTS; when common clock is used*/
++#define PCIE_AFR_COM_FTS_NUM_S 16
++#define PCIE_AFR_L0S_ENTRY_LATENCY 0x07000000 /* L0s Entrance Latency */
++#define PCIE_AFR_L0S_ENTRY_LATENCY_S 24
++#define PCIE_AFR_L1_ENTRY_LATENCY 0x38000000 /* L1 Entrance Latency */
++#define PCIE_AFR_L1_ENTRY_LATENCY_S 27
++#define PCIE_AFR_FTS_NUM_DEFAULT 32
++#define PCIE_AFR_L0S_ENTRY_LATENCY_DEFAULT 7
++#define PCIE_AFR_L1_ENTRY_LATENCY_DEFAULT 5
++
++/* Port Link Control Register */
++#define PCIE_PLCR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x710)
++#define PCIE_PLCR_OTHER_MSG_REQ 0x00000001 /* Other Message Request */
++#define PCIE_PLCR_SCRAMBLE_DISABLE 0x00000002 /* Scramble Disable */
++#define PCIE_PLCR_LOOPBACK_EN 0x00000004 /* Loopback Enable */
++#define PCIE_PLCR_LTSSM_HOT_RST 0x00000008 /* Force LTSSM to the hot reset */
++#define PCIE_PLCR_DLL_LINK_EN 0x00000020 /* Enable Link initialization */
++#define PCIE_PLCR_FAST_LINK_SIM_EN 0x00000080 /* Sets all internal timers to fast mode for simulation purposes */
++#define PCIE_PLCR_LINK_MODE 0x003F0000 /* Link Mode Enable Mask */
++#define PCIE_PLCR_LINK_MODE_S 16
++#define PCIE_PLCR_CORRUPTED_CRC_EN 0x02000000 /* Enabled Corrupt CRC */
++
++/* Lane Skew Register */
++#define PCIE_LSR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x714)
++#define PCIE_LSR_LANE_SKEW_NUM 0x00FFFFFF /* Insert Lane Skew for Transmit, not applicable */
++#define PCIE_LSR_LANE_SKEW_NUM_S 0
++#define PCIE_LSR_FC_DISABLE 0x01000000 /* Disable of Flow Control */
++#define PCIE_LSR_ACKNAK_DISABLE 0x02000000 /* Disable of Ack/Nak */
++#define PCIE_LSR_LANE_DESKEW_DISABLE 0x80000000 /* Disable of Lane-to-Lane Skew */
++
++/* Symbol Number Register */
++#define PCIE_SNR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x718)
++#define PCIE_SNR_TS 0x0000000F /* Number of TS Symbol */
++#define PCIE_SNR_TS_S 0
++#define PCIE_SNR_SKP 0x00000700 /* Number of SKP Symbol */
++#define PCIE_SNR_SKP_S 8
++#define PCIE_SNR_REPLAY_TIMER 0x0007C000 /* Timer Modifier for Replay Timer */
++#define PCIE_SNR_REPLAY_TIMER_S 14
++#define PCIE_SNR_ACKNAK_LATENCY_TIMER 0x00F80000 /* Timer Modifier for Ack/Nak Latency Timer */
++#define PCIE_SNR_ACKNAK_LATENCY_TIMER_S 19
++#define PCIE_SNR_FC_TIMER 0x1F000000 /* Timer Modifier for Flow Control Watchdog Timer */
++#define PCIE_SNR_FC_TIMER_S 28
++
++/* Symbol Timer Register and Filter Mask Register 1 */
++#define PCIE_STRFMR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x71C)
++#define PCIE_STRFMR_SKP_INTERVAL 0x000007FF /* SKP lnterval Value */
++#define PCIE_STRFMR_SKP_INTERVAL_S 0
++#define PCIE_STRFMR_FC_WDT_DISABLE 0x00008000 /* Disable of FC Watchdog Timer */
++#define PCIE_STRFMR_TLP_FUNC_MISMATCH_OK 0x00010000 /* Mask Function Mismatch Filtering for Incoming Requests */
++#define PCIE_STRFMR_POISONED_TLP_OK 0x00020000 /* Mask Poisoned TLP Filtering */
++#define PCIE_STRFMR_BAR_MATCH_OK 0x00040000 /* Mask BAR Match Filtering */
++#define PCIE_STRFMR_TYPE1_CFG_REQ_OK 0x00080000 /* Mask Type 1 Configuration Request Filtering */
++#define PCIE_STRFMR_LOCKED_REQ_OK 0x00100000 /* Mask Locked Request Filtering */
++#define PCIE_STRFMR_CPL_TAG_ERR_RULES_OK 0x00200000 /* Mask Tag Error Rules for Received Completions */
++#define PCIE_STRFMR_CPL_REQUESTOR_ID_MISMATCH_OK 0x00400000 /* Mask Requester ID Mismatch Error for Received Completions */
++#define PCIE_STRFMR_CPL_FUNC_MISMATCH_OK 0x00800000 /* Mask Function Mismatch Error for Received Completions */
++#define PCIE_STRFMR_CPL_TC_MISMATCH_OK 0x01000000 /* Mask Traffic Class Mismatch Error for Received Completions */
++#define PCIE_STRFMR_CPL_ATTR_MISMATCH_OK 0x02000000 /* Mask Attribute Mismatch Error for Received Completions */
++#define PCIE_STRFMR_CPL_LENGTH_MISMATCH_OK 0x04000000 /* Mask Length Mismatch Error for Received Completions */
++#define PCIE_STRFMR_TLP_ECRC_ERR_OK 0x08000000 /* Mask ECRC Error Filtering */
++#define PCIE_STRFMR_CPL_TLP_ECRC_OK 0x10000000 /* Mask ECRC Error Filtering for Completions */
++#define PCIE_STRFMR_RX_TLP_MSG_NO_DROP 0x20000000 /* Send Message TLPs */
++#define PCIE_STRFMR_RX_IO_TRANS_ENABLE 0x40000000 /* Mask Filtering of received I/O Requests */
++#define PCIE_STRFMR_RX_CFG_TRANS_ENABLE 0x80000000 /* Mask Filtering of Received Configuration Requests */
++
++#define PCIE_DEF_SKP_INTERVAL 700 /* 1180 ~1538 , 125MHz * 2, 250MHz * 1 */
++
++/* Filter Masker Register 2 */
++#define PCIE_FMR2(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x720)
++#define PCIE_FMR2_VENDOR_MSG0_PASSED_TO_TRGT1 0x00000001 /* Mask RADM Filtering and Error Handling Rules */
++#define PCIE_FMR2_VENDOR_MSG1_PASSED_TO_TRGT1 0x00000002 /* Mask RADM Filtering and Error Handling Rules */
++
++/* Debug Register 0 */
++#define PCIE_DBR0(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x728)
++
++/* Debug Register 1 */
++#define PCIE_DBR1(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x72C)
++
++/* Transmit Posted FC Credit Status Register */
++#define PCIE_TPFCS(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x730)
++#define PCIE_TPFCS_TX_P_DATA_FC_CREDITS 0x00000FFF /* Transmit Posted Data FC Credits */
++#define PCIE_TPFCS_TX_P_DATA_FC_CREDITS_S 0
++#define PCIE_TPFCS_TX_P_HDR_FC_CREDITS 0x000FF000 /* Transmit Posted Header FC Credits */
++#define PCIE_TPFCS_TX_P_HDR_FC_CREDITS_S 12
++
++/* Transmit Non-Posted FC Credit Status */
++#define PCIE_TNPFCS(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x734)
++#define PCIE_TNPFCS_TX_NP_DATA_FC_CREDITS 0x00000FFF /* Transmit Non-Posted Data FC Credits */
++#define PCIE_TNPFCS_TX_NP_DATA_FC_CREDITS_S 0
++#define PCIE_TNPFCS_TX_NP_HDR_FC_CREDITS 0x000FF000 /* Transmit Non-Posted Header FC Credits */
++#define PCIE_TNPFCS_TX_NP_HDR_FC_CREDITS_S 12
++
++/* Transmit Complete FC Credit Status Register */
++#define PCIE_TCFCS(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x738)
++#define PCIE_TCFCS_TX_CPL_DATA_FC_CREDITS 0x00000FFF /* Transmit Completion Data FC Credits */
++#define PCIE_TCFCS_TX_CPL_DATA_FC_CREDITS_S 0
++#define PCIE_TCFCS_TX_CPL_HDR_FC_CREDITS 0x000FF000 /* Transmit Completion Header FC Credits */
++#define PCIE_TCFCS_TX_CPL_HDR_FC_CREDITS_S 12
++
++/* Queue Status Register */
++#define PCIE_QSR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x73C)
++#define PCIE_QSR_WAIT_UPDATE_FC_DLL 0x00000001 /* Received TLP FC Credits Not Returned */
++#define PCIE_QSR_TX_RETRY_BUF_NOT_EMPTY 0x00000002 /* Transmit Retry Buffer Not Empty */
++#define PCIE_QSR_RX_QUEUE_NOT_EMPTY 0x00000004 /* Received Queue Not Empty */
++
++/* VC Transmit Arbitration Register 1 */
++#define PCIE_VCTAR1(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x740)
++#define PCIE_VCTAR1_WRR_WEIGHT_VC0 0x000000FF /* WRR Weight for VC0 */
++#define PCIE_VCTAR1_WRR_WEIGHT_VC1 0x0000FF00 /* WRR Weight for VC1 */
++#define PCIE_VCTAR1_WRR_WEIGHT_VC2 0x00FF0000 /* WRR Weight for VC2 */
++#define PCIE_VCTAR1_WRR_WEIGHT_VC3 0xFF000000 /* WRR Weight for VC3 */
++
++/* VC Transmit Arbitration Register 2 */
++#define PCIE_VCTAR2(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x744)
++#define PCIE_VCTAR2_WRR_WEIGHT_VC4 0x000000FF /* WRR Weight for VC4 */
++#define PCIE_VCTAR2_WRR_WEIGHT_VC5 0x0000FF00 /* WRR Weight for VC5 */
++#define PCIE_VCTAR2_WRR_WEIGHT_VC6 0x00FF0000 /* WRR Weight for VC6 */
++#define PCIE_VCTAR2_WRR_WEIGHT_VC7 0xFF000000 /* WRR Weight for VC7 */
++
++/* VC0 Posted Receive Queue Control Register */
++#define PCIE_VC0_PRQCR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x748)
++#define PCIE_VC0_PRQCR_P_DATA_CREDITS 0x00000FFF /* VC0 Posted Data Credits */
++#define PCIE_VC0_PRQCR_P_DATA_CREDITS_S 0
++#define PCIE_VC0_PRQCR_P_HDR_CREDITS 0x000FF000 /* VC0 Posted Header Credits */
++#define PCIE_VC0_PRQCR_P_HDR_CREDITS_S 12
++#define PCIE_VC0_PRQCR_P_TLP_QUEUE_MODE 0x00E00000 /* VC0 Posted TLP Queue Mode */
++#define PCIE_VC0_PRQCR_P_TLP_QUEUE_MODE_S 20
++#define PCIE_VC0_PRQCR_TLP_RELAX_ORDER 0x40000000 /* TLP Type Ordering for VC0 */
++#define PCIE_VC0_PRQCR_VC_STRICT_ORDER 0x80000000 /* VC0 Ordering for Receive Queues */
++
++/* VC0 Non-Posted Receive Queue Control */
++#define PCIE_VC0_NPRQCR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x74C)
++#define PCIE_VC0_NPRQCR_NP_DATA_CREDITS 0x00000FFF /* VC0 Non-Posted Data Credits */
++#define PCIE_VC0_NPRQCR_NP_DATA_CREDITS_S 0
++#define PCIE_VC0_NPRQCR_NP_HDR_CREDITS 0x000FF000 /* VC0 Non-Posted Header Credits */
++#define PCIE_VC0_NPRQCR_NP_HDR_CREDITS_S 12
++#define PCIE_VC0_NPRQCR_NP_TLP_QUEUE_MODE 0x00E00000 /* VC0 Non-Posted TLP Queue Mode */
++#define PCIE_VC0_NPRQCR_NP_TLP_QUEUE_MODE_S 20
++
++/* VC0 Completion Receive Queue Control */
++#define PCIE_VC0_CRQCR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x750)
++#define PCIE_VC0_CRQCR_CPL_DATA_CREDITS 0x00000FFF /* VC0 Completion TLP Queue Mode */
++#define PCIE_VC0_CRQCR_CPL_DATA_CREDITS_S 0
++#define PCIE_VC0_CRQCR_CPL_HDR_CREDITS 0x000FF000 /* VC0 Completion Header Credits */
++#define PCIE_VC0_CRQCR_CPL_HDR_CREDITS_S 12
++#define PCIE_VC0_CRQCR_CPL_TLP_QUEUE_MODE 0x00E00000 /* VC0 Completion Data Credits */
++#define PCIE_VC0_CRQCR_CPL_TLP_QUEUE_MODE_S 21
++
++/* Applicable to the above three registers */
++enum {
++ PCIE_VC0_TLP_QUEUE_MODE_STORE_FORWARD = 1,
++ PCIE_VC0_TLP_QUEUE_MODE_CUT_THROUGH = 2,
++ PCIE_VC0_TLP_QUEUE_MODE_BYPASS = 4,
++};
++
++/* VC0 Posted Buffer Depth Register */
++#define PCIE_VC0_PBD(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x7A8)
++#define PCIE_VC0_PBD_P_DATA_QUEUE_ENTRIES 0x00003FFF /* VC0 Posted Data Queue Depth */
++#define PCIE_VC0_PBD_P_DATA_QUEUE_ENTRIES_S 0
++#define PCIE_VC0_PBD_P_HDR_QUEUE_ENTRIES 0x03FF0000 /* VC0 Posted Header Queue Depth */
++#define PCIE_VC0_PBD_P_HDR_QUEUE_ENTRIES_S 16
++
++/* VC0 Non-Posted Buffer Depth Register */
++#define PCIE_VC0_NPBD(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x7AC)
++#define PCIE_VC0_NPBD_NP_DATA_QUEUE_ENTRIES 0x00003FFF /* VC0 Non-Posted Data Queue Depth */
++#define PCIE_VC0_NPBD_NP_DATA_QUEUE_ENTRIES_S 0
++#define PCIE_VC0_NPBD_NP_HDR_QUEUE_ENTRIES 0x03FF0000 /* VC0 Non-Posted Header Queue Depth */
++#define PCIE_VC0_NPBD_NP_HDR_QUEUE_ENTRIES_S 16
++
++/* VC0 Completion Buffer Depth Register */
++#define PCIE_VC0_CBD(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x7B0)
++#define PCIE_VC0_CBD_CPL_DATA_QUEUE_ENTRIES 0x00003FFF /* C0 Completion Data Queue Depth */
++#define PCIE_VC0_CBD_CPL_DATA_QUEUE_ENTRIES_S 0
++#define PCIE_VC0_CBD_CPL_HDR_QUEUE_ENTRIES 0x03FF0000 /* VC0 Completion Header Queue Depth */
++#define PCIE_VC0_CBD_CPL_HDR_QUEUE_ENTRIES_S 16
++
++/* PHY Status Register, all zeros in VR9 */
++#define PCIE_PHYSR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x810)
++
++/* PHY Control Register, all zeros in VR9 */
++#define PCIE_PHYCR(X) (volatile u32*)(PCIE_RC_PORT_TO_BASE(X) + 0x814)
++
++/*
++ * PCIe PDI PHY register definition, suppose all the following
++ * stuff is confidential.
++ * XXX, detailed bit definition
++ */
++#define PCIE_PHY_PLL_CTRL1(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x22 << 1))
++#define PCIE_PHY_PLL_CTRL2(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x23 << 1))
++#define PCIE_PHY_PLL_CTRL3(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x24 << 1))
++#define PCIE_PHY_PLL_CTRL4(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x25 << 1))
++#define PCIE_PHY_PLL_CTRL5(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x26 << 1))
++#define PCIE_PHY_PLL_CTRL6(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x27 << 1))
++#define PCIE_PHY_PLL_CTRL7(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x28 << 1))
++#define PCIE_PHY_PLL_A_CTRL1(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x29 << 1))
++#define PCIE_PHY_PLL_A_CTRL2(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x2A << 1))
++#define PCIE_PHY_PLL_A_CTRL3(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x2B << 1))
++#define PCIE_PHY_PLL_STATUS(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x2C << 1))
++
++#define PCIE_PHY_TX1_CTRL1(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x30 << 1))
++#define PCIE_PHY_TX1_CTRL2(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x31 << 1))
++#define PCIE_PHY_TX1_CTRL3(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x32 << 1))
++#define PCIE_PHY_TX1_A_CTRL1(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x33 << 1))
++#define PCIE_PHY_TX1_A_CTRL2(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x34 << 1))
++#define PCIE_PHY_TX1_MOD1(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x35 << 1))
++#define PCIE_PHY_TX1_MOD2(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x36 << 1))
++#define PCIE_PHY_TX1_MOD3(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x37 << 1))
++
++#define PCIE_PHY_TX2_CTRL1(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x38 << 1))
++#define PCIE_PHY_TX2_CTRL2(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x39 << 1))
++#define PCIE_PHY_TX2_A_CTRL1(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x3B << 1))
++#define PCIE_PHY_TX2_A_CTRL2(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x3C << 1))
++#define PCIE_PHY_TX2_MOD1(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x3D << 1))
++#define PCIE_PHY_TX2_MOD2(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x3E << 1))
++#define PCIE_PHY_TX2_MOD3(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x3F << 1))
++
++#define PCIE_PHY_RX1_CTRL1(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x50 << 1))
++#define PCIE_PHY_RX1_CTRL2(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x51 << 1))
++#define PCIE_PHY_RX1_CDR(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x52 << 1))
++#define PCIE_PHY_RX1_EI(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x53 << 1))
++#define PCIE_PHY_RX1_A_CTRL(X) (PCIE_PHY_PORT_TO_BASE(X) + (0x55 << 1))
++
++/* Interrupt related stuff */
++#define PCIE_LEGACY_DISABLE 0
++#define PCIE_LEGACY_INTA 1
++#define PCIE_LEGACY_INTB 2
++#define PCIE_LEGACY_INTC 3
++#define PCIE_LEGACY_INTD 4
++#define PCIE_LEGACY_INT_MAX PCIE_LEGACY_INTD
++
++#define PCIE_IRQ_LOCK(lock) do { \
++ unsigned long flags; \
++ spin_lock_irqsave(&(lock), flags);
++#define PCIE_IRQ_UNLOCK(lock) \
++ spin_unlock_irqrestore(&(lock), flags); \
++} while (0)
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
++#define IRQF_SHARED SA_SHIRQ
++#endif
++
++#define PCIE_MSG_MSI 0x00000001
++#define PCIE_MSG_ISR 0x00000002
++#define PCIE_MSG_FIXUP 0x00000004
++#define PCIE_MSG_READ_CFG 0x00000008
++#define PCIE_MSG_WRITE_CFG 0x00000010
++#define PCIE_MSG_CFG (PCIE_MSG_READ_CFG | PCIE_MSG_WRITE_CFG)
++#define PCIE_MSG_REG 0x00000020
++#define PCIE_MSG_INIT 0x00000040
++#define PCIE_MSG_ERR 0x00000080
++#define PCIE_MSG_PHY 0x00000100
++#define PCIE_MSG_ANY 0x000001ff
++
++#define IFX_PCIE_PORT0 0
++#define IFX_PCIE_PORT1 1
++
++#ifdef CONFIG_IFX_PCIE_2ND_CORE
++#define IFX_PCIE_CORE_NR 2
++#else
++#define IFX_PCIE_CORE_NR 1
++#endif
++
++//#define IFX_PCIE_ERROR_INT
++
++//#define IFX_PCIE_DBG
++
++#if defined(IFX_PCIE_DBG)
++#define IFX_PCIE_PRINT(_m, _fmt, args...) do { \
++ if (g_pcie_debug_flag & (_m)) { \
++ ifx_pcie_debug((_fmt), ##args); \
++ } \
++} while (0)
++
++#define INLINE
++#else
++#define IFX_PCIE_PRINT(_m, _fmt, args...) \
++ do {} while(0)
++#define INLINE inline
++#endif
++
++struct ifx_pci_controller {
++ struct pci_controller pcic;
++
++ /* RC specific, per host bus information */
++ u32 port; /* Port index, 0 -- 1st core, 1 -- 2nd core */
++};
++
++typedef struct ifx_pcie_ir_irq {
++ const unsigned int irq;
++ const char name[16];
++}ifx_pcie_ir_irq_t;
++
++typedef struct ifx_pcie_legacy_irq{
++ const u32 irq_bit;
++ const int irq;
++}ifx_pcie_legacy_irq_t;
++
++typedef struct ifx_pcie_irq {
++ ifx_pcie_ir_irq_t ir_irq;
++ ifx_pcie_legacy_irq_t legacy_irq[PCIE_LEGACY_INT_MAX];
++}ifx_pcie_irq_t;
++
++extern u32 g_pcie_debug_flag;
++extern void ifx_pcie_debug(const char *fmt, ...);
++extern void pcie_phy_clock_mode_setup(int pcie_port);
++extern void pcie_msi_pic_init(int pcie_port);
++extern u32 ifx_pcie_bus_enum_read_hack(int where, u32 value);
++extern u32 ifx_pcie_bus_enum_write_hack(int where, u32 value);
++
++
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/gpio.h>
++#include <linux/clk.h>
++
++#include <lantiq_soc.h>
++
++#define IFX_PCIE_GPIO_RESET 38
++#define IFX_REG_R32 ltq_r32
++#define IFX_REG_W32 ltq_w32
++#define CONFIG_IFX_PCIE_HW_SWAP
++#define IFX_RCU_AHB_ENDIAN ((volatile u32*)(IFX_RCU + 0x004C))
++#define IFX_RCU_RST_REQ ((volatile u32*)(IFX_RCU + 0x0010))
++#define IFX_RCU_AHB_BE_PCIE_PDI 0x00000080 /* Configure PCIE PDI module in big endian*/
++
++#define IFX_RCU (KSEG1 | 0x1F203000)
++#define IFX_RCU_AHB_BE_PCIE_M 0x00000001 /* Configure AHB master port that connects to PCIe RC in big endian */
++#define IFX_RCU_AHB_BE_PCIE_S 0x00000010 /* Configure AHB slave port that connects to PCIe RC in little endian */
++#define IFX_RCU_AHB_BE_XBAR_M 0x00000002 /* Configure AHB master port that connects to XBAR in big endian */
++#define CONFIG_IFX_PCIE_PHY_36MHZ_MODE
++
++#define IFX_PMU1_MODULE_PCIE_PHY (0)
++#define IFX_PMU1_MODULE_PCIE_CTRL (1)
++#define IFX_PMU1_MODULE_PDI (4)
++#define IFX_PMU1_MODULE_MSI (5)
++
++#define IFX_PMU_MODULE_PCIE_L0_CLK (31)
++
++
++static inline void pcie_ep_gpio_rst_init(int pcie_port)
++{
++}
++
++static inline void pcie_ahb_pmu_setup(void)
++{
++ struct clk *clk;
++ clk = clk_get_sys("ltq_pcie", "ahb");
++ clk_enable(clk);
++ //ltq_pmu_enable(PMU_AHBM | PMU_AHBS);
++}
++
++static inline void pcie_rcu_endian_setup(int pcie_port)
++{
++ u32 reg;
++
++ reg = IFX_REG_R32(IFX_RCU_AHB_ENDIAN);
++#ifdef CONFIG_IFX_PCIE_HW_SWAP
++ reg |= IFX_RCU_AHB_BE_PCIE_M;
++ reg |= IFX_RCU_AHB_BE_PCIE_S;
++ reg &= ~IFX_RCU_AHB_BE_XBAR_M;
++#else
++ reg |= IFX_RCU_AHB_BE_PCIE_M;
++ reg &= ~IFX_RCU_AHB_BE_PCIE_S;
++ reg &= ~IFX_RCU_AHB_BE_XBAR_M;
++#endif /* CONFIG_IFX_PCIE_HW_SWAP */
++ IFX_REG_W32(reg, IFX_RCU_AHB_ENDIAN);
++ IFX_PCIE_PRINT(PCIE_MSG_REG, "%s IFX_RCU_AHB_ENDIAN: 0x%08x\n", __func__, IFX_REG_R32(IFX_RCU_AHB_ENDIAN));
++}
++
++static inline void pcie_phy_pmu_enable(int pcie_port)
++{
++ struct clk *clk;
++ clk = clk_get_sys("ltq_pcie", "phy");
++ clk_enable(clk);
++ //ltq_pmu1_enable(1<<IFX_PMU1_MODULE_PCIE_PHY);
++}
++
++static inline void pcie_phy_pmu_disable(int pcie_port)
++{
++ struct clk *clk;
++ clk = clk_get_sys("ltq_pcie", "phy");
++ clk_disable(clk);
++ //ltq_pmu1_disable(1<<IFX_PMU1_MODULE_PCIE_PHY);
++}
++
++static inline void pcie_pdi_big_endian(int pcie_port)
++{
++ u32 reg;
++
++ /* SRAM2PDI endianness control. */
++ reg = IFX_REG_R32(IFX_RCU_AHB_ENDIAN);
++ /* Config AHB->PCIe and PDI endianness */
++ reg |= IFX_RCU_AHB_BE_PCIE_PDI;
++ IFX_REG_W32(reg, IFX_RCU_AHB_ENDIAN);
++}
++
++static inline void pcie_pdi_pmu_enable(int pcie_port)
++{
++ struct clk *clk;
++ clk = clk_get_sys("ltq_pcie", "pdi");
++ clk_enable(clk);
++ //ltq_pmu1_enable(1<<IFX_PMU1_MODULE_PDI);
++}
++
++static inline void pcie_core_rst_assert(int pcie_port)
++{
++ u32 reg;
++
++ reg = IFX_REG_R32(IFX_RCU_RST_REQ);
++
++ /* Reset PCIe PHY & Core, bit 22, bit 26 may be affected if write it directly */
++ reg |= 0x00400000;
++ IFX_REG_W32(reg, IFX_RCU_RST_REQ);
++}
++
++static inline void pcie_core_rst_deassert(int pcie_port)
++{
++ u32 reg;
++
++ /* Make sure one micro-second delay */
++ udelay(1);
++
++ /* Reset PCIe PHY & Core, bit 22 */
++ reg = IFX_REG_R32(IFX_RCU_RST_REQ);
++ reg &= ~0x00400000;
++ IFX_REG_W32(reg, IFX_RCU_RST_REQ);
++}
++
++static inline void pcie_phy_rst_assert(int pcie_port)
++{
++ u32 reg;
++
++ reg = IFX_REG_R32(IFX_RCU_RST_REQ);
++ reg |= 0x00001000; /* Bit 12 */
++ IFX_REG_W32(reg, IFX_RCU_RST_REQ);
++}
++
++static inline void pcie_phy_rst_deassert(int pcie_port)
++{
++ u32 reg;
++
++ /* Make sure one micro-second delay */
++ udelay(1);
++
++ reg = IFX_REG_R32(IFX_RCU_RST_REQ);
++ reg &= ~0x00001000; /* Bit 12 */
++ IFX_REG_W32(reg, IFX_RCU_RST_REQ);
++}
++
++static inline void pcie_device_rst_assert(int pcie_port)
++{
++ gpio_set_value(IFX_PCIE_GPIO_RESET, 0);
++ // ifx_gpio_output_clear(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id);
++}
++
++static inline void pcie_device_rst_deassert(int pcie_port)
++{
++ mdelay(100);
++ gpio_set_value(IFX_PCIE_GPIO_RESET, 1);
++// ifx_gpio_output_set(IFX_PCIE_GPIO_RESET, ifx_pcie_gpio_module_id);
++}
++
++static inline void pcie_core_pmu_setup(int pcie_port)
++{
++ struct clk *clk;
++ clk = clk_get_sys("ltq_pcie", "ctl");
++ clk_enable(clk);
++ clk = clk_get_sys("ltq_pcie", "bus");
++ clk_enable(clk);
++
++ //ltq_pmu1_enable(1 << IFX_PMU1_MODULE_PCIE_CTRL);
++ //ltq_pmu_enable(1 << IFX_PMU_MODULE_PCIE_L0_CLK);
++}
++
++static inline void pcie_msi_init(int pcie_port)
++{
++ struct clk *clk;
++ pcie_msi_pic_init(pcie_port);
++ clk = clk_get_sys("ltq_pcie", "msi");
++ clk_enable(clk);
++ //ltq_pmu1_enable(1 << IFX_PMU1_MODULE_MSI);
++}
++
++static inline u32
++ifx_pcie_bus_nr_deduct(u32 bus_number, int pcie_port)
++{
++ u32 tbus_number = bus_number;
++
++#ifdef CONFIG_IFX_PCI
++ if (pcibios_host_nr() > 1) {
++ tbus_number -= pcibios_1st_host_bus_nr();
++ }
++#endif /* CONFIG_IFX_PCI */
++ return tbus_number;
++}
++
++static inline u32
++ifx_pcie_bus_enum_hack(struct pci_bus *bus, u32 devfn, int where, u32 value, int pcie_port, int read)
++{
++ struct pci_dev *pdev;
++ u32 tvalue = value;
++
++ /* Sanity check */
++ pdev = pci_get_slot(bus, devfn);
++ if (pdev == NULL) {
++ return tvalue;
++ }
++
++ /* Only care about PCI bridge */
++ if (pdev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
++ return tvalue;
++ }
++
++ if (read) { /* Read hack */
++ #ifdef CONFIG_IFX_PCI
++ if (pcibios_host_nr() > 1) {
++ tvalue = ifx_pcie_bus_enum_read_hack(where, tvalue);
++ }
++ #endif /* CONFIG_IFX_PCI */
++ }
++ else { /* Write hack */
++ #ifdef CONFIG_IFX_PCI
++ if (pcibios_host_nr() > 1) {
++ tvalue = ifx_pcie_bus_enum_write_hack(where, tvalue);
++ }
++ #endif
++ }
++ return tvalue;
++}
++
++#endif /* IFXMIPS_PCIE_VR9_H */
++
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0026-MIPS-lantiq-adds-GPIO3-support-on-AR9.patch b/target/linux/lantiq/patches-3.2/0056-MIPS-lantiq-make-GPIO3-work-on-AR9.patch
index ee41b3a..295e7ac 100644
--- a/target/linux/lantiq/patches/0026-MIPS-lantiq-adds-GPIO3-support-on-AR9.patch
+++ b/target/linux/lantiq/patches-3.2/0056-MIPS-lantiq-make-GPIO3-work-on-AR9.patch
@@ -1,7 +1,7 @@
-From 92b24777385cd8388e0fa8b9f1d24e5bc4466641 Mon Sep 17 00:00:00 2001
+From b11a96f2bdf1730fe3fd3be1d0667e20a4eb5bff Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Sat, 13 Aug 2011 13:59:50 +0200
-Subject: [PATCH 12/22] MIPS: lantiq: make GPIO3 work on AR9
+Subject: [PATCH 56/70] MIPS: lantiq: make GPIO3 work on AR9
There are 3 16bit and 1 8bit gpio ports on AR9. The gpio driver needs a hack
at 2 places to make the different register layout of the GPIO3 work properly
@@ -13,14 +13,16 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
---
.../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 2 +
arch/mips/lantiq/xway/devices.c | 3 +
- arch/mips/lantiq/xway/gpio.c | 62 ++++++++++++++++----
+ arch/mips/lantiq/xway/gpio.c | 84 ++++++++++++++++----
arch/mips/lantiq/xway/gpio_ebu.c | 3 +-
arch/mips/lantiq/xway/gpio_stp.c | 3 +-
- 5 files changed, 57 insertions(+), 16 deletions(-)
+ 5 files changed, 75 insertions(+), 20 deletions(-)
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index d1b8cc8..bfdeb16 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
-@@ -121,7 +121,9 @@
+@@ -126,7 +126,9 @@
#define LTQ_GPIO0_BASE_ADDR 0x1E100B10
#define LTQ_GPIO1_BASE_ADDR 0x1E100B40
#define LTQ_GPIO2_BASE_ADDR 0x1E100B70
@@ -30,9 +32,11 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
/* SSC */
#define LTQ_SSC_BASE_ADDR 0x1e100800
+diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
+index 5efa4f3..e6d45bc 100644
--- a/arch/mips/lantiq/xway/devices.c
+++ b/arch/mips/lantiq/xway/devices.c
-@@ -34,6 +34,7 @@ static struct resource ltq_gpio_resource
+@@ -34,6 +34,7 @@ static struct resource ltq_gpio_resource[] = {
MEM_RES("gpio0", LTQ_GPIO0_BASE_ADDR, LTQ_GPIO_SIZE),
MEM_RES("gpio1", LTQ_GPIO1_BASE_ADDR, LTQ_GPIO_SIZE),
MEM_RES("gpio2", LTQ_GPIO2_BASE_ADDR, LTQ_GPIO_SIZE),
@@ -49,14 +53,18 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
}
}
+diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c
+index 54ec6c9..375329b 100644
--- a/arch/mips/lantiq/xway/gpio.c
+++ b/arch/mips/lantiq/xway/gpio.c
-@@ -23,9 +23,15 @@
+@@ -23,9 +23,17 @@
#define LTQ_GPIO_OD 0x14
#define LTQ_GPIO_PUDSEL 0x1C
#define LTQ_GPIO_PUDEN 0x20
+#define LTQ_GPIO3_OD 0x24
+#define LTQ_GPIO3_ALTSEL1 0x24
++#define LTQ_GPIO3_PUDSEL 0x28
++#define LTQ_GPIO3_PUDEN 0x2C
+/* PORT3 only has 8 pins and its register layout
+ is slightly different */
@@ -68,34 +76,34 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
#define ltq_gpio_getbit(m, r, p) (!!(ltq_r32(m + r) & (1 << p)))
#define ltq_gpio_setbit(m, r, p) ltq_w32_mask(0, (1 << p), m + r)
-@@ -55,7 +61,7 @@ int ltq_gpio_request(unsigned int pin, u
+@@ -55,7 +63,7 @@ int ltq_gpio_request(struct device *dev, unsigned int pin, unsigned int mux,
{
int id = 0;
- if (pin >= (MAX_PORTS * PINS_PER_PORT))
+ if (pin >= MAX_PIN)
return -EINVAL;
- if (gpio_request(pin, name)) {
+ if (devm_gpio_request(dev, pin, name)) {
pr_err("failed to setup lantiq gpio: %s\n", name);
-@@ -75,12 +81,21 @@ int ltq_gpio_request(unsigned int pin, u
+@@ -75,12 +83,21 @@ int ltq_gpio_request(struct device *dev, unsigned int pin, unsigned int mux,
else
ltq_gpio_clearbit(ltq_gpio_port[id].membase,
LTQ_GPIO_ALTSEL0, pin);
-- if (alt1)
+- if (mux & 0x1)
- ltq_gpio_setbit(ltq_gpio_port[id].membase,
- LTQ_GPIO_ALTSEL1, pin);
- else
- ltq_gpio_clearbit(ltq_gpio_port[id].membase,
- LTQ_GPIO_ALTSEL1, pin);
+ if (id == 3) {
-+ if (alt1)
++ if (mux & 0x1)
+ ltq_gpio_setbit(ltq_gpio_port[1].membase,
+ LTQ_GPIO3_ALTSEL1, pin);
+ else
+ ltq_gpio_clearbit(ltq_gpio_port[1].membase,
+ LTQ_GPIO3_ALTSEL1, pin);
+ } else {
-+ if (alt1)
++ if (mux & 0x1)
+ ltq_gpio_setbit(ltq_gpio_port[id].membase,
+ LTQ_GPIO_ALTSEL1, pin);
+ else
@@ -105,32 +113,53 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
return 0;
}
EXPORT_SYMBOL(ltq_gpio_request);
-@@ -106,7 +121,11 @@ static int ltq_gpio_direction_input(stru
+@@ -106,10 +123,19 @@ static int ltq_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
- ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
-+ if (chip->ngpio == PINS_PORT3)
++ if (chip->ngpio == PINS_PORT3) {
+ ltq_gpio_clearbit(ltq_gpio_port[0].membase,
+ LTQ_GPIO3_OD, offset);
-+ else
++ ltq_gpio_setbit(ltq_gpio_port[0].membase,
++ LTQ_GPIO3_PUDSEL, offset);
++ ltq_gpio_setbit(ltq_gpio_port[0].membase,
++ LTQ_GPIO3_PUDEN, offset);
++ } else {
+ ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
++ ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_PUDSEL, offset);
++ ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_PUDEN, offset);
++ }
ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
- ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_PUDSEL, offset);
- ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_PUDEN, offset);
-@@ -119,7 +138,10 @@ static int ltq_gpio_direction_output(str
+- ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_PUDSEL, offset);
+- ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_PUDEN, offset);
+
+ return 0;
+ }
+@@ -119,10 +145,19 @@ static int ltq_gpio_direction_output(struct gpio_chip *chip,
{
struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
- ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
-+ if (chip->ngpio == PINS_PORT3)
-+ ltq_gpio_setbit(ltq_gpio_port[0].membase, LTQ_GPIO3_OD, offset);
-+ else
++ if (chip->ngpio == PINS_PORT3) {
++ ltq_gpio_setbit(ltq_gpio_port[0].membase,
++ LTQ_GPIO3_OD, offset);
++ ltq_gpio_clearbit(ltq_gpio_port[0].membase,
++ LTQ_GPIO3_PUDSEL, offset);
++ ltq_gpio_clearbit(ltq_gpio_port[0].membase,
++ LTQ_GPIO3_PUDEN, offset);
++ } else {
+ ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
++ ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_PUDSEL, offset);
++ ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_PUDEN, offset);
++ }
ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
- ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_PUDSEL, offset);
- ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_PUDEN, offset);
-@@ -133,7 +155,11 @@ static int ltq_gpio_req(struct gpio_chip
+- ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_PUDSEL, offset);
+- ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_PUDEN, offset);
+ ltq_gpio_set(chip, offset, value);
+
+ return 0;
+@@ -133,7 +168,11 @@ static int ltq_gpio_req(struct gpio_chip *chip, unsigned offset)
struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL0, offset);
@@ -143,14 +172,15 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
return 0;
}
-@@ -146,6 +172,15 @@ static int ltq_gpio_probe(struct platfor
+@@ -146,6 +185,16 @@ static int ltq_gpio_probe(struct platform_device *pdev)
pdev->id);
return -EINVAL;
}
+
+ /* dirty hack - The registers of port3 are not mapped linearly.
+ Port 3 may only load if Port 1/2 are mapped */
-+ if ((pdev->id == 3) && (!ltq_gpio_port[1].membase || !ltq_gpio_port[2].membase)) {
++ if ((pdev->id == 3) && (!ltq_gpio_port[1].membase
++ || !ltq_gpio_port[2].membase)) {
+ dev_err(&pdev->dev,
+ "ports 1/2 need to be loaded before port 3 works\n");
+ return -ENOMEM;
@@ -159,7 +189,7 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "failed to get memory for gpio port %d\n",
-@@ -175,7 +210,10 @@ static int ltq_gpio_probe(struct platfor
+@@ -175,7 +224,10 @@ static int ltq_gpio_probe(struct platform_device *pdev)
ltq_gpio_port[pdev->id].chip.set = ltq_gpio_set;
ltq_gpio_port[pdev->id].chip.request = ltq_gpio_req;
ltq_gpio_port[pdev->id].chip.base = PINS_PER_PORT * pdev->id;
@@ -171,6 +201,8 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
platform_set_drvdata(pdev, &ltq_gpio_port[pdev->id]);
return gpiochip_add(&ltq_gpio_port[pdev->id].chip);
}
+diff --git a/arch/mips/lantiq/xway/gpio_ebu.c b/arch/mips/lantiq/xway/gpio_ebu.c
+index b91c7f1..bc5696b 100644
--- a/arch/mips/lantiq/xway/gpio_ebu.c
+++ b/arch/mips/lantiq/xway/gpio_ebu.c
@@ -61,9 +61,8 @@ static struct gpio_chip ltq_ebu_chip = {
@@ -184,9 +216,11 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
.owner = THIS_MODULE,
};
+diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
+index da91c5e..9610c10 100644
--- a/arch/mips/lantiq/xway/gpio_stp.c
+++ b/arch/mips/lantiq/xway/gpio_stp.c
-@@ -72,9 +72,8 @@ static struct gpio_chip ltq_stp_chip = {
+@@ -74,9 +74,8 @@ static struct gpio_chip ltq_stp_chip = {
.label = "ltq_stp",
.direction_output = ltq_stp_direction_output,
.set = ltq_stp_set,
@@ -197,3 +231,6 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
.owner = THIS_MODULE,
};
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0019-MIPS-lantiq-adds-VPE-extensions.patch b/target/linux/lantiq/patches-3.2/0057-MIPS-lantiq-VPE-extensions.patch
index 1bd4c5b..a1320d6 100644
--- a/target/linux/lantiq/patches/0019-MIPS-lantiq-adds-VPE-extensions.patch
+++ b/target/linux/lantiq/patches-3.2/0057-MIPS-lantiq-VPE-extensions.patch
@@ -1,7 +1,7 @@
-From c6c810d83f0d95f54c3a6b338d219cec7ccef4c9 Mon Sep 17 00:00:00 2001
+From 587ca6b21ab64ab014625b1cacb36ef711c74962 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 29 Sep 2011 20:30:40 +0200
-Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
+Subject: [PATCH 57/70] MIPS: lantiq: VPE extensions
---
arch/mips/Kconfig | 22 +++
@@ -17,9 +17,11 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
create mode 100644 arch/mips/kernel/mtsched_proc.c
create mode 100644 arch/mips/kernel/perf_proc.c
+diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
+index bbaff9b..902aedb 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
-@@ -1915,6 +1915,28 @@ config MIPS_VPE_LOADER
+@@ -1897,6 +1897,28 @@ config MIPS_VPE_LOADER
Includes a loader for loading an elf relocatable object
onto another VPE and running it.
@@ -48,6 +50,8 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
config MIPS_MT_SMTC_IM_BACKSTOP
bool "Use per-TC register bits as backstop for inhibited IM bits"
depends on MIPS_MT_SMTC
+diff --git a/arch/mips/include/asm/mipsmtregs.h b/arch/mips/include/asm/mipsmtregs.h
+index c9420aa..04bfb4b 100644
--- a/arch/mips/include/asm/mipsmtregs.h
+++ b/arch/mips/include/asm/mipsmtregs.h
@@ -28,14 +28,34 @@
@@ -157,9 +161,11 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
/* GPR */
#define read_tc_gpr_sp() mftgpr(29)
+diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
+index 1a96618..bc5989e 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
-@@ -86,7 +86,8 @@ obj-$(CONFIG_MIPS32_O32) += binfmt_elfo3
+@@ -88,7 +88,8 @@ obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_PROC_FS) += proc.o
@@ -169,6 +175,8 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
obj-$(CONFIG_64BIT) += cpu-bugs64.o
obj-$(CONFIG_I8253) += i8253.o
+diff --git a/arch/mips/kernel/mips-mt.c b/arch/mips/kernel/mips-mt.c
+index c23d11f..11d6489 100644
--- a/arch/mips/kernel/mips-mt.c
+++ b/arch/mips/kernel/mips-mt.c
@@ -21,26 +21,96 @@
@@ -273,7 +281,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
/*
* Dump new MIPS MT state for the core. Does not leave TCs halted.
-@@ -78,18 +148,18 @@ void mips_mt_regdump(unsigned long mvpct
+@@ -78,18 +148,18 @@ void mips_mt_regdump(unsigned long mvpctl)
if ((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
printk(" VPE %d\n", i);
printk(" VPEControl : %08lx\n",
@@ -309,6 +317,9 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
}
/*
+diff --git a/arch/mips/kernel/mtsched_proc.c b/arch/mips/kernel/mtsched_proc.c
+new file mode 100644
+index 0000000..4dafded
--- /dev/null
+++ b/arch/mips/kernel/mtsched_proc.c
@@ -0,0 +1,279 @@
@@ -591,6 +602,9 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
+
+/* Automagically create the entry */
+module_init(init_mtsched_proc);
+diff --git a/arch/mips/kernel/perf_proc.c b/arch/mips/kernel/perf_proc.c
+new file mode 100644
+index 0000000..7eec015
--- /dev/null
+++ b/arch/mips/kernel/perf_proc.c
@@ -0,0 +1,191 @@
@@ -785,6 +799,8 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
+
+/* Automagically create the entry */
+module_init(init_perf_proc);
+diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
+index e309665..2de204f 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -7,6 +7,7 @@
@@ -795,7 +811,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
#include <asm/bootinfo.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
-@@ -110,3 +111,19 @@ const struct seq_operations cpuinfo_op =
+@@ -110,3 +111,19 @@ const struct seq_operations cpuinfo_op = {
.stop = c_stop,
.show = show_cpuinfo,
};
@@ -815,9 +831,11 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
+ mips_proc = proc_mkdir("mips", NULL);
+ return(mips_proc);
+}
+diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c
+index f0895e7..199e853 100644
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
-@@ -1334,6 +1334,13 @@ void smtc_get_new_mmu_context(struct mm_
+@@ -1334,6 +1334,13 @@ void smtc_get_new_mmu_context(struct mm_struct *mm, unsigned long cpu)
asid = asid_cache(cpu);
do {
@@ -831,9 +849,11 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
if (!((asid += ASID_INC) & ASID_MASK) ) {
if (cpu_has_vtag_icache)
flush_icache_all();
+diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
+index bfa12a4..e338ba5 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
-@@ -76,6 +76,58 @@ static struct kspd_notifications kspd_ev
+@@ -75,6 +75,58 @@ static struct kspd_notifications kspd_events;
static int kspd_events_reqd;
#endif
@@ -892,7 +912,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
/* grab the likely amount of memory we will need. */
#ifdef CONFIG_MIPS_VPE_LOADER_TOM
#define P_SIZE (2 * 1024 * 1024)
-@@ -268,6 +320,13 @@ static void *alloc_progmem(unsigned long
+@@ -267,6 +319,13 @@ static void *alloc_progmem(unsigned long len)
void *addr;
#ifdef CONFIG_MIPS_VPE_LOADER_TOM
@@ -906,7 +926,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
/*
* This means you must tell Linux to use less memory than you
* physically have, for example by passing a mem= boot argument.
-@@ -746,6 +805,12 @@ static int vpe_run(struct vpe * v)
+@@ -745,6 +804,12 @@ static int vpe_run(struct vpe * v)
}
/* Write the address we want it to start running from in the TCPC register. */
@@ -919,7 +939,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
write_tc_c0_tcrestart((unsigned long)v->__start);
write_tc_c0_tccontext((unsigned long)0);
-@@ -759,6 +824,20 @@ static int vpe_run(struct vpe * v)
+@@ -758,6 +823,20 @@ static int vpe_run(struct vpe * v)
write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H);
@@ -940,7 +960,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
/*
* The sde-kit passes 'memsize' to __start in $a3, so set something
* here... Or set $a3 to zero and define DFLT_STACK_SIZE and
-@@ -833,6 +912,9 @@ static int find_vpe_symbols(struct vpe *
+@@ -832,6 +911,9 @@ static int find_vpe_symbols(struct vpe * v, Elf_Shdr * sechdrs,
if ( (v->__start == 0) || (v->shared_ptr == NULL))
return -1;
@@ -950,7 +970,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
return 0;
}
-@@ -994,6 +1076,15 @@ static int vpe_elfload(struct vpe * v)
+@@ -993,6 +1075,15 @@ static int vpe_elfload(struct vpe * v)
(unsigned long)v->load_addr + v->len);
if ((find_vpe_symbols(v, sechdrs, symindex, strtab, &mod)) < 0) {
@@ -966,7 +986,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
if (v->__start == 0) {
printk(KERN_WARNING "VPE loader: program does not contain "
"a __start symbol\n");
-@@ -1064,6 +1155,9 @@ static int vpe_open(struct inode *inode,
+@@ -1063,6 +1154,9 @@ static int vpe_open(struct inode *inode, struct file *filp)
struct vpe_notifications *not;
struct vpe *v;
int ret;
@@ -976,7 +996,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
if (minor != iminor(inode)) {
/* assume only 1 device at the moment. */
-@@ -1089,7 +1183,12 @@ static int vpe_open(struct inode *inode,
+@@ -1088,7 +1182,12 @@ static int vpe_open(struct inode *inode, struct file *filp)
release_progmem(v->load_addr);
cleanup_tc(get_tc(tclimit));
}
@@ -990,7 +1010,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
/* this of-course trashes what was there before... */
v->pbuffer = vmalloc(P_SIZE);
if (!v->pbuffer) {
-@@ -1097,11 +1196,14 @@ static int vpe_open(struct inode *inode,
+@@ -1096,11 +1195,14 @@ static int vpe_open(struct inode *inode, struct file *filp)
return -ENOMEM;
}
v->plen = P_SIZE;
@@ -1005,7 +1025,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
#ifdef CONFIG_MIPS_APSP_KSPD
/* get kspd to tell us when a syscall_exit happens */
-@@ -1349,6 +1451,133 @@ static void kspd_sp_exit( int sp_id)
+@@ -1348,6 +1450,133 @@ static void kspd_sp_exit( int sp_id)
cleanup_tc(get_tc(sp_id));
}
#endif
@@ -1139,7 +1159,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
static ssize_t store_kill(struct device *dev, struct device_attribute *attr,
const char *buf, size_t len)
-@@ -1430,6 +1659,18 @@ static int __init vpe_module_init(void)
+@@ -1429,6 +1658,18 @@ static int __init vpe_module_init(void)
printk("VPE loader: not a MIPS MT capable processor\n");
return -ENODEV;
}
@@ -1158,7 +1178,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
if (vpelimit == 0) {
printk(KERN_WARNING "No VPEs reserved for AP/SP, not "
-@@ -1474,10 +1715,12 @@ static int __init vpe_module_init(void)
+@@ -1473,10 +1714,12 @@ static int __init vpe_module_init(void)
mtflags = dmt();
vpflags = dvpe();
@@ -1172,7 +1192,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
val = read_c0_mvpconf0();
hw_tcs = (val & MVPCONF0_PTC) + 1;
-@@ -1489,6 +1732,7 @@ static int __init vpe_module_init(void)
+@@ -1488,6 +1731,7 @@ static int __init vpe_module_init(void)
* reschedule send IPIs or similar we might hang.
*/
clear_c0_mvpcontrol(MVPCONTROL_VPC);
@@ -1180,7 +1200,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
evpe(vpflags);
emt(mtflags);
local_irq_restore(flags);
-@@ -1514,6 +1758,7 @@ static int __init vpe_module_init(void)
+@@ -1513,6 +1757,7 @@ static int __init vpe_module_init(void)
}
v->ntcs = hw_tcs - tclimit;
@@ -1188,7 +1208,7 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
/* add the tc to the list of this vpe's tc's. */
list_add(&t->tc, &v->tc);
-@@ -1582,6 +1827,7 @@ static int __init vpe_module_init(void)
+@@ -1581,6 +1826,7 @@ static int __init vpe_module_init(void)
out_reenable:
/* release config state */
clear_c0_mvpcontrol(MVPCONTROL_VPC);
@@ -1196,3 +1216,6 @@ Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
evpe(vpflags);
emt(mtflags);
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0020-MIPS-lantiq-adds-falcon-VPE-softdog.patch b/target/linux/lantiq/patches-3.2/0058-MIPS-lantiq-falcon-VPE-softdog.patch
index 9173a5d..d2865eb 100644
--- a/target/linux/lantiq/patches/0020-MIPS-lantiq-adds-falcon-VPE-softdog.patch
+++ b/target/linux/lantiq/patches-3.2/0058-MIPS-lantiq-falcon-VPE-softdog.patch
@@ -1,7 +1,7 @@
-From e3c377986855f820513edf2924a022a39c363908 Mon Sep 17 00:00:00 2001
+From 6a76c0c9a33c32464319c24ff5647f7676642c51 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 29 Sep 2011 21:29:14 +0200
-Subject: [PATCH 20/24] MIPS: lantiq: adds falcon VPE softdog
+Subject: [PATCH 58/70] MIPS: lantiq: falcon VPE softdog
---
arch/mips/include/asm/mach-lantiq/falcon/vpe.h | 44 ++++++++++
@@ -10,6 +10,9 @@ Subject: [PATCH 20/24] MIPS: lantiq: adds falcon VPE softdog
create mode 100644 arch/mips/include/asm/mach-lantiq/falcon/vpe.h
create mode 100644 arch/mips/lantiq/falcon/softdog_vpe.c
+diff --git a/arch/mips/include/asm/mach-lantiq/falcon/vpe.h b/arch/mips/include/asm/mach-lantiq/falcon/vpe.h
+new file mode 100644
+index 0000000..22a701b
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/falcon/vpe.h
@@ -0,0 +1,44 @@
@@ -57,6 +60,9 @@ Subject: [PATCH 20/24] MIPS: lantiq: adds falcon VPE softdog
+int32_t vpe1_sw_wdog_register_reset_handler(VPE_SW_WDOG_RESET reset_fn);
+
+#endif
+diff --git a/arch/mips/lantiq/falcon/softdog_vpe.c b/arch/mips/lantiq/falcon/softdog_vpe.c
+new file mode 100644
+index 0000000..85d22a2
--- /dev/null
+++ b/arch/mips/lantiq/falcon/softdog_vpe.c
@@ -0,0 +1,109 @@
@@ -169,9 +175,6 @@ Subject: [PATCH 20/24] MIPS: lantiq: adds falcon VPE softdog
+MODULE_AUTHOR("LXDB");
+MODULE_DESCRIPTION("Software Watchdog For VPE1");
+MODULE_LICENSE("GPL");
---- a/arch/mips/lantiq/falcon/Makefile
-+++ b/arch/mips/lantiq/falcon/Makefile
-@@ -1,2 +1,2 @@
--obj-y := clk.o prom.o reset.o sysctrl.o devices.o gpio.o
-+obj-y := clk.o prom.o reset.o sysctrl.o devices.o gpio.o softdog_vpe.o
- obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0022-MIPS-lantiq-adds-udp-in-kernel-redirect.patch b/target/linux/lantiq/patches-3.2/0059-MIPS-lantiq-udp-in-kernel-redirect.patch
index c80731e..74025e8 100644
--- a/target/linux/lantiq/patches/0022-MIPS-lantiq-adds-udp-in-kernel-redirect.patch
+++ b/target/linux/lantiq/patches-3.2/0059-MIPS-lantiq-udp-in-kernel-redirect.patch
@@ -1,7 +1,7 @@
-From 14ff975c660696fa636e8d6b58d0abed0ddc72ce Mon Sep 17 00:00:00 2001
+From 268b631d81d5428cdf1a82b9655e9f44f64a8238 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 29 Sep 2011 20:29:54 +0200
-Subject: [PATCH 22/24] MIPS: lantiq: adds udp in-kernel redirect
+Subject: [PATCH 59/70] MIPS: lantiq: udp in-kernel redirect
---
include/linux/udp_redirect.h | 57 +++++++++++++
@@ -13,6 +13,9 @@ Subject: [PATCH 22/24] MIPS: lantiq: adds udp in-kernel redirect
create mode 100644 include/linux/udp_redirect.h
create mode 100644 net/ipv4/udp_redirect_symb.c
+diff --git a/include/linux/udp_redirect.h b/include/linux/udp_redirect.h
+new file mode 100644
+index 0000000..de1e64f
--- /dev/null
+++ b/include/linux/udp_redirect.h
@@ -0,0 +1,57 @@
@@ -73,6 +76,8 @@ Subject: [PATCH 22/24] MIPS: lantiq: adds udp in-kernel redirect
+extern int udpredirect_getfrag(void *p, char * to, int offset,
+ int fraglen, int odd, struct sk_buff *skb);
+#endif
+diff --git a/net/Kconfig b/net/Kconfig
+index a073148..d13e3fa 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -72,6 +72,12 @@ config INET
@@ -88,9 +93,11 @@ Subject: [PATCH 22/24] MIPS: lantiq: adds udp in-kernel redirect
if INET
source "net/ipv4/Kconfig"
source "net/ipv6/Kconfig"
+diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
+index f2dc69c..6badd72 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
-@@ -14,6 +14,9 @@ obj-y := route.o inetpeer.o protocol
+@@ -14,6 +14,9 @@ obj-y := route.o inetpeer.o protocol.o \
inet_fragment.o ping.o
obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o
@@ -100,6 +107,8 @@ Subject: [PATCH 22/24] MIPS: lantiq: adds udp in-kernel redirect
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
obj-$(CONFIG_IP_MROUTE) += ipmr.o
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 5a65eea..cdfa0d4 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -108,6 +108,10 @@
@@ -113,7 +122,7 @@ Subject: [PATCH 22/24] MIPS: lantiq: adds udp in-kernel redirect
struct udp_table udp_table __read_mostly;
EXPORT_SYMBOL(udp_table);
-@@ -803,7 +807,7 @@ int udp_sendmsg(struct kiocb *iocb, stru
+@@ -803,7 +807,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
u8 tos;
int err, is_udplite = IS_UDPLITE(sk);
int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
@@ -122,7 +131,7 @@ Subject: [PATCH 22/24] MIPS: lantiq: adds udp in-kernel redirect
struct sk_buff *skb;
struct ip_options_data opt_copy;
-@@ -820,7 +824,13 @@ int udp_sendmsg(struct kiocb *iocb, stru
+@@ -820,7 +824,13 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
ipc.opt = NULL;
ipc.tx_flags = 0;
@@ -137,7 +146,7 @@ Subject: [PATCH 22/24] MIPS: lantiq: adds udp in-kernel redirect
fl4 = &inet->cork.fl.u.ip4;
if (up->pending) {
-@@ -1621,6 +1631,7 @@ int __udp4_lib_rcv(struct sk_buff *skb,
+@@ -1623,6 +1633,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
struct rtable *rt = skb_rtable(skb);
__be32 saddr, daddr;
struct net *net = dev_net(skb->dev);
@@ -145,7 +154,7 @@ Subject: [PATCH 22/24] MIPS: lantiq: adds udp in-kernel redirect
/*
* Validate the packet.
-@@ -1653,7 +1664,16 @@ int __udp4_lib_rcv(struct sk_buff *skb,
+@@ -1655,7 +1666,16 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
if (sk != NULL) {
@@ -163,7 +172,7 @@ Subject: [PATCH 22/24] MIPS: lantiq: adds udp in-kernel redirect
sock_put(sk);
/* a return value > 0 means to resubmit the input, but
-@@ -1950,7 +1970,7 @@ struct proto udp_prot = {
+@@ -1952,7 +1972,7 @@ struct proto udp_prot = {
.clear_sk = sk_prot_clear_portaddr_nulls,
};
EXPORT_SYMBOL(udp_prot);
@@ -172,6 +181,9 @@ Subject: [PATCH 22/24] MIPS: lantiq: adds udp in-kernel redirect
/* ------------------------------------------------------------------------ */
#ifdef CONFIG_PROC_FS
+diff --git a/net/ipv4/udp_redirect_symb.c b/net/ipv4/udp_redirect_symb.c
+new file mode 100644
+index 0000000..5617e86
--- /dev/null
+++ b/net/ipv4/udp_redirect_symb.c
@@ -0,0 +1,186 @@
@@ -361,3 +373,6 @@ Subject: [PATCH 22/24] MIPS: lantiq: adds udp in-kernel redirect
+EXPORT_SYMBOL(udp_do_redirect_fn);
+EXPORT_SYMBOL(udpredirect_getfrag_fn);
+#endif /* CONFIG_IFX_UDP_REDIRECT* */
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/0021-MIPS-lantiq-adds-cache-split.patch b/target/linux/lantiq/patches-3.2/0060-MIPS-lantiq-cache-split.patch
index 640d1e2..cb0ad4a 100644
--- a/target/linux/lantiq/patches/0021-MIPS-lantiq-adds-cache-split.patch
+++ b/target/linux/lantiq/patches-3.2/0060-MIPS-lantiq-cache-split.patch
@@ -1,7 +1,7 @@
-From 0f85e79f6f01f50cb703866a555085a9c65bad2f Mon Sep 17 00:00:00 2001
+From 307ba9e4d8fb0608566aacf88ab8cded5e20e005 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 29 Sep 2011 20:31:54 +0200
-Subject: [PATCH 21/24] MIPS: lantiq: adds cache split
+Subject: [PATCH 60/70] MIPS: lantiq: cache split
---
arch/mips/Kconfig | 22 ++++++
@@ -9,9 +9,11 @@ Subject: [PATCH 21/24] MIPS: lantiq: adds cache split
arch/mips/mm/c-r4k.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 260 insertions(+), 0 deletions(-)
+diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
+index 902aedb..12ee3df 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
-@@ -1922,6 +1922,28 @@ config IFX_VPE_EXT
+@@ -1904,6 +1904,28 @@ config IFX_VPE_EXT
help
IFX included extensions in APRP
@@ -40,9 +42,11 @@ Subject: [PATCH 21/24] MIPS: lantiq: adds cache split
config PERFCTRS
bool "34K Performance counters"
depends on MIPS_MT && PROC_FS
+diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
+index e338ba5..0511d11 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
-@@ -128,6 +128,13 @@ __setup("vpe1_wdog_timeout=", wdog_timeo
+@@ -127,6 +127,13 @@ __setup("vpe1_wdog_timeout=", wdog_timeout);
EXPORT_SYMBOL(vpe1_wdog_timeout);
#endif
@@ -56,7 +60,7 @@ Subject: [PATCH 21/24] MIPS: lantiq: adds cache split
/* grab the likely amount of memory we will need. */
#ifdef CONFIG_MIPS_VPE_LOADER_TOM
#define P_SIZE (2 * 1024 * 1024)
-@@ -866,6 +873,65 @@ static int vpe_run(struct vpe * v)
+@@ -865,6 +872,65 @@ static int vpe_run(struct vpe * v)
/* enable this VPE */
write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
@@ -122,9 +126,11 @@ Subject: [PATCH 21/24] MIPS: lantiq: adds cache split
/* clear out any left overs from a previous program */
write_vpe_c0_status(0);
write_vpe_c0_cause(0);
+diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
+index a79fe9a..94cb24f 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
-@@ -1350,6 +1350,106 @@ static int __init setcoherentio(char *st
+@@ -1383,6 +1383,106 @@ static int __init setcoherentio(char *str)
__setup("coherentio", setcoherentio);
#endif
@@ -231,7 +237,7 @@ Subject: [PATCH 21/24] MIPS: lantiq: adds cache split
void __cpuinit r4k_cache_init(void)
{
extern void build_clear_page(void);
-@@ -1369,6 +1469,78 @@ void __cpuinit r4k_cache_init(void)
+@@ -1402,6 +1502,78 @@ void __cpuinit r4k_cache_init(void)
break;
}
@@ -310,36 +316,6 @@ Subject: [PATCH 21/24] MIPS: lantiq: adds cache split
probe_pcache();
setup_scache();
---- a/arch/mips/lantiq/setup.c
-+++ b/arch/mips/lantiq/setup.c
-@@ -18,10 +18,11 @@
- #include "devices.h"
- #include "prom.h"
-
-+/* assume 16M as default incase uboot fails to pass proper ramsize */
-+unsigned long physical_memsize = 16L;
-+
- void __init plat_mem_setup(void)
- {
-- /* assume 16M as default incase uboot fails to pass proper ramsize */
-- unsigned long memsize = 16;
- char **envp = (char **) KSEG1ADDR(fw_arg2);
-
- ioport_resource.start = IOPORT_RESOURCE_START;
-@@ -35,13 +36,13 @@ void __init plat_mem_setup(void)
- char *e = (char *)KSEG1ADDR(*envp);
- if (!strncmp(e, "memsize=", 8)) {
- e += 8;
-- if (strict_strtoul(e, 0, &memsize))
-+ if (strict_strtoul(e, 0, &physical_memsize))
- pr_warn("bad memsize specified\n");
- }
- envp++;
- }
-- memsize *= 1024 * 1024;
-- add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
-+ physical_memsize *= 1024 * 1024;
-+ add_memory_region(0x00000000, physical_memsize, BOOT_MEM_RAM);
- }
-
- static int __init
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0061-MIPS-clean-up-clock-code.patch b/target/linux/lantiq/patches-3.2/0061-MIPS-clean-up-clock-code.patch
new file mode 100644
index 0000000..9ec89ed
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0061-MIPS-clean-up-clock-code.patch
@@ -0,0 +1,319 @@
+From d23a3c21962bcc3dc18e7916c2499cd3b26feaf0 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 20 Mar 2012 08:26:04 +0100
+Subject: [PATCH 61/70] MIPS: clean up clock code
+
+---
+ arch/mips/lantiq/clk.c | 11 +++
+ arch/mips/lantiq/clk.h | 3 +-
+ arch/mips/lantiq/xway/devices.c | 2 +-
+ arch/mips/lantiq/xway/sysctrl.c | 166 ++++++++++++++++++++++++++++++---------
+ 4 files changed, 143 insertions(+), 39 deletions(-)
+
+diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
+index 84a201e..5494b6e 100644
+--- a/arch/mips/lantiq/clk.c
++++ b/arch/mips/lantiq/clk.c
+@@ -44,6 +44,7 @@ struct clk *clk_get_fpi(void)
+ {
+ return &cpu_clk_generic[1];
+ }
++EXPORT_SYMBOL_GPL(clk_get_fpi);
+
+ struct clk *clk_get_io(void)
+ {
+@@ -70,6 +71,16 @@ unsigned long clk_get_rate(struct clk *clk)
+ }
+ EXPORT_SYMBOL(clk_get_rate);
+
++int clk_set_rate(struct clk *clk, unsigned long rate)
++{
++ if (unlikely(!clk_good(clk)))
++ return 0;
++
++ clk->rate = rate;
++ return 0;
++}
++EXPORT_SYMBOL(clk_set_rate);
++
+ int clk_enable(struct clk *clk)
+ {
+ if (unlikely(!clk_good(clk)))
+diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h
+index d047768..b34e675 100644
+--- a/arch/mips/lantiq/clk.h
++++ b/arch/mips/lantiq/clk.h
+@@ -12,6 +12,7 @@
+ #include <linux/clkdev.h>
+
+ /* clock speeds */
++#define CLOCK_33M 33333333
+ #define CLOCK_60M 60000000
+ #define CLOCK_62_5M 62500000
+ #define CLOCK_83M 83333333
+@@ -38,9 +39,9 @@
+ struct clk {
+ struct clk_lookup cl;
+ unsigned long rate;
+- unsigned long (*get_rate) (void);
+ unsigned int module;
+ unsigned int bits;
++ unsigned long (*get_rate) (void);
+ int (*enable) (struct clk *clk);
+ void (*disable) (struct clk *clk);
+ int (*activate) (struct clk *clk);
+diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
+index e6d45bc..5d4650d 100644
+--- a/arch/mips/lantiq/xway/devices.c
++++ b/arch/mips/lantiq/xway/devices.c
+@@ -59,7 +59,7 @@ static struct resource ltq_stp_resource =
+
+ void __init ltq_register_gpio_stp(void)
+ {
+- platform_device_register_simple("ltq_stp", 0, &ltq_stp_resource, 1);
++ platform_device_register_simple("ltq_stp", -1, &ltq_stp_resource, 1);
+ }
+
+ /* asc ports - amazon se has its own serial mapping */
+diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
+index ac7383f..9df048c 100644
+--- a/arch/mips/lantiq/xway/sysctrl.c
++++ b/arch/mips/lantiq/xway/sysctrl.c
+@@ -16,40 +16,57 @@
+ #include "../devices.h"
+
+ /* clock control register */
+-#define LTQ_CGU_IFCCR 0x0018
++#define CGU_IFCCR 0x0018
+ /* system clock register */
+-#define LTQ_CGU_SYS 0x0010
+-
+-/* the enable / disable registers */
+-#define LTQ_PMU_PWDCR 0x1C
+-#define LTQ_PMU_PWDSR 0x20
+-#define LTQ_PMU_PWDCR1 0x24
+-#define LTQ_PMU_PWDSR1 0x28
+-
+-#define PWDCR(x) ((x) ? (LTQ_PMU_PWDCR1) : (LTQ_PMU_PWDCR))
+-#define PWDSR(x) ((x) ? (LTQ_PMU_PWDSR1) : (LTQ_PMU_PWDSR))
+-
+-/* CGU - clock generation unit */
+-#define CGU_EPHY 0x10
++#define CGU_SYS 0x0010
++/* pci control register */
++#define CGU_PCICR 0x0034
++/* ephy configuration register */
++#define CGU_EPHY 0x10
++/* power control register */
++#define PMU_PWDCR 0x1C
++/* power status register */
++#define PMU_PWDSR 0x20
++/* power control register */
++#define PMU_PWDCR1 0x24
++/* power status register */
++#define PMU_PWDSR1 0x28
++/* power control register */
++#define PWDCR(x) ((x) ? (PMU_PWDCR1) : (PMU_PWDCR))
++/* power status register */
++#define PWDSR(x) ((x) ? (PMU_PWDSR1) : (PMU_PWDSR))
+
+ /* PMU - power management unit */
+-#define PMU_DMA 0x0020
+-#define PMU_SPI 0x0100
+-#define PMU_EPHY 0x0080
+-#define PMU_USB 0x8041
+-#define PMU_STP 0x0800
+-#define PMU_GPT 0x1000
+-#define PMU_PPE 0x2000
+-#define PMU_FPI 0x4000
+-#define PMU_SWITCH 0x10000000
+-#define PMU_AHBS 0x2000
+-#define PMU_AHBM 0x8000
+-#define PMU_PCIE_CLK 0x80000000
+-
+-#define PMU1_PCIE_PHY 0x0001
+-#define PMU1_PCIE_CTL 0x0002
+-#define PMU1_PCIE_MSI 0x0020
+-#define PMU1_PCIE_PDI 0x0010
++#define PMU_USB0_P BIT(0)
++#define PMU_PCI BIT(4)
++#define PMU_DMA BIT(5)
++#define PMU_USB0 BIT(5)
++#define PMU_SPI BIT(8)
++#define PMU_EPHY BIT(7)
++#define PMU_EBU BIT(10)
++#define PMU_STP BIT(11)
++#define PMU_GPT BIT(12)
++#define PMU_PPE BIT(13)
++#define PMU_AHBS BIT(13) /* vr9 */
++#define PMU_FPI BIT(14)
++#define PMU_AHBM BIT(15)
++#define PMU_PPE_QSB BIT(18)
++#define PMU_PPE_SLL01 BIT(19)
++#define PMU_PPE_TC BIT(21)
++#define PMU_PPE_EMA BIT(22)
++#define PMU_PPE_DPLUM BIT(23)
++#define PMU_PPE_DPLUS BIT(24)
++#define PMU_USB1_P BIT(26)
++#define PMU_USB1 BIT(27)
++#define PMU_SWITCH BIT(28)
++#define PMU_PPE_TOP BIT(29)
++#define PMU_GPHY BIT(30)
++#define PMU_PCIE_CLK BIT(31)
++
++#define PMU1_PCIE_PHY BIT(0)
++#define PMU1_PCIE_CTL BIT(1)
++#define PMU1_PCIE_PDI BIT(4)
++#define PMU1_PCIE_MSI BIT(5)
+
+ #define ltq_pmu_w32(x, y) ltq_w32((x), ltq_pmu_membase + (y))
+ #define ltq_pmu_r32(x) ltq_r32(ltq_pmu_membase + (x))
+@@ -69,13 +86,13 @@ static void __iomem *ltq_pmu_membase;
+
+ static int ltq_cgu_enable(struct clk *clk)
+ {
+- ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | clk->bits, LTQ_CGU_IFCCR);
++ ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | clk->bits, CGU_IFCCR);
+ return 0;
+ }
+
+ static void ltq_cgu_disable(struct clk *clk)
+ {
+- ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~clk->bits, LTQ_CGU_IFCCR);
++ ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~clk->bits, CGU_IFCCR);
+ }
+
+ static int ltq_pmu_enable(struct clk *clk)
+@@ -94,9 +111,49 @@ static int ltq_pmu_enable(struct clk *clk)
+
+ static void ltq_pmu_disable(struct clk *clk)
+ {
+- ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | clk->bits, LTQ_PMU_PWDCR);
++ ltq_pmu_w32(ltq_pmu_r32(PWDCR(clk->module)) | clk->bits,
++ PWDCR(clk->module));
++}
++
++static int ltq_pci_enable(struct clk *clk)
++{
++ unsigned int ifccr = ltq_cgu_r32(CGU_IFCCR);
++ /* set clock bus speed */
++ if (ltq_is_ar9()) {
++ ifccr &= ~0x1f00000;
++ if (clk->rate == CLOCK_33M)
++ ifccr |= 0xe00000;
++ else
++ ifccr |= 0x700000; /* 62.5M */
++ } else {
++ ifccr &= ~0xf00000;
++ if (clk->rate == CLOCK_33M)
++ ifccr |= 0x800000;
++ else
++ ifccr |= 0x400000; /* 62.5M */
++ }
++ ltq_cgu_w32(ifccr, CGU_IFCCR);
++ return 0;
++}
++
++static int ltq_pci_ext_enable(struct clk *clk)
++{
++ /* enable external pci clock */
++ ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) & ~(1 << 16),
++ CGU_IFCCR);
++ ltq_cgu_w32((1 << 30), CGU_PCICR);
++ return 0;
++}
++
++static void ltq_pci_ext_disable(struct clk *clk)
++{
++ /* enable external pci clock */
++ ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | (1 << 16),
++ CGU_IFCCR);
++ ltq_cgu_w32((1 << 31) | (1 << 30), CGU_PCICR);
+ }
+
++/* manage the clock gates via PMU */
+ static inline void clkdev_add_pmu(const char *dev, const char *con,
+ unsigned int module, unsigned int bits)
+ {
+@@ -112,6 +169,7 @@ static inline void clkdev_add_pmu(const char *dev, const char *con,
+ clkdev_add(&clk->cl);
+ }
+
++/* manage the clock generator */
+ static inline void clkdev_add_cgu(const char *dev, const char *con,
+ unsigned int bits)
+ {
+@@ -126,6 +184,33 @@ static inline void clkdev_add_cgu(const char *dev, const char *con,
+ clkdev_add(&clk->cl);
+ }
+
++/* pci needs its own enable function */
++static inline void clkdev_add_pci(void)
++{
++ struct clk *clk = kzalloc(sizeof(struct clk), GFP_KERNEL);
++ struct clk *clk_ext = kzalloc(sizeof(struct clk), GFP_KERNEL);
++
++ /* main pci clock */
++ clk->cl.dev_id = "ltq_pci";
++ clk->cl.con_id = NULL;
++ clk->cl.clk = clk;
++ clk->rate = CLOCK_33M;
++ clk->enable = ltq_pci_enable;
++ clk->disable = ltq_pmu_disable;
++ clk->module = 0;
++ clk->bits = PMU_PCI;
++ clkdev_add(&clk->cl);
++
++ /* use internal/external bus clock */
++ clk_ext->cl.dev_id = "ltq_pci";
++ clk_ext->cl.con_id = "external";
++ clk_ext->cl.clk = clk_ext;
++ clk_ext->enable = ltq_pci_ext_enable;
++ clk_ext->disable = ltq_pci_ext_disable;
++ clkdev_add(&clk_ext->cl);
++
++}
++
+ void __init ltq_soc_init(void)
+ {
+ ltq_pmu_membase = ltq_remap_resource(&ltq_pmu_resource);
+@@ -144,14 +229,16 @@ void __init ltq_soc_init(void)
+ ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
+
+ /* add our clocks */
++ clkdev_add_pmu("ltq_fpi", NULL, 0, PMU_FPI);
+ clkdev_add_pmu("ltq_dma", NULL, 0, PMU_DMA);
+ clkdev_add_pmu("ltq_stp", NULL, 0, PMU_STP);
+ clkdev_add_pmu("ltq_spi", NULL, 0, PMU_SPI);
+ clkdev_add_pmu("ltq_gptu", NULL, 0, PMU_GPT);
++ clkdev_add_pmu("ltq_ebu", NULL, 0, PMU_EBU);
+ if (!ltq_is_vr9())
+ clkdev_add_pmu("ltq_etop", NULL, 0, PMU_PPE);
+ if (ltq_is_ase()) {
+- if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5))
++ if (ltq_cgu_r32(CGU_SYS) & (1 << 5))
+ clkdev_add_static(CLOCK_266M, CLOCK_133M, CLOCK_133M);
+ else
+ clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M);
+@@ -166,11 +253,16 @@ void __init ltq_soc_init(void)
+ clkdev_add_pmu("ltq_pcie", "pdi", 1, PMU1_PCIE_PDI);
+ clkdev_add_pmu("ltq_pcie", "ctl", 1, PMU1_PCIE_CTL);
+ clkdev_add_pmu("ltq_pcie", "ahb", 0, PMU_AHBM | PMU_AHBS);
+- clkdev_add_pmu("usb0", NULL, 0, (1<<6) | 1);
+- clkdev_add_pmu("usb1", NULL, 0, (1<<26) | (1<<27));
++ clkdev_add_pmu("usb0", NULL, 0, PMU_USB0 | PMU_USB0_P);
++ clkdev_add_pmu("usb1", NULL, 0, PMU_USB1 | PMU_USB1_P);
++ clkdev_add_pmu("ltq_vrx200", NULL, 0,
++ PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
++ PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
++ PMU_PPE_QSB);
+ } else {
+ clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
+ ltq_danube_io_region_clock());
++ clkdev_add_pci();
+ if (ltq_is_ar9())
+ clkdev_add_pmu("ltq_etop", "switch", 0, PMU_SWITCH);
+ }
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0062-MIPS-cleanup-reset-code.patch b/target/linux/lantiq/patches-3.2/0062-MIPS-cleanup-reset-code.patch
new file mode 100644
index 0000000..e6fae3f
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0062-MIPS-cleanup-reset-code.patch
@@ -0,0 +1,103 @@
+From 1748dc7b4974109040d0249ac1fc322c120eb528 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 16 Mar 2012 15:49:32 +0100
+Subject: [PATCH 62/70] MIPS: cleanup reset code
+
+---
+ arch/mips/lantiq/xway/reset.c | 59 ++++++++++++++++++++++++++++++++++------
+ 1 files changed, 50 insertions(+), 9 deletions(-)
+
+diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
+index ca2212a..8a5dff1 100644
+--- a/arch/mips/lantiq/xway/reset.c
++++ b/arch/mips/lantiq/xway/reset.c
+@@ -11,6 +11,7 @@
+ #include <linux/ioport.h>
+ #include <linux/pm.h>
+ #include <linux/export.h>
++#include <linux/delay.h>
+ #include <asm/reboot.h>
+
+ #include <lantiq_soc.h>
+@@ -20,12 +21,45 @@
+ #define ltq_rcu_w32(x, y) ltq_w32((x), ltq_rcu_membase + (y))
+ #define ltq_rcu_r32(x) ltq_r32(ltq_rcu_membase + (x))
+
+-/* register definitions */
+-#define LTQ_RCU_RST 0x0010
+-#define LTQ_RCU_RST_ALL 0x40000000
+-
+-#define LTQ_RCU_RST_STAT 0x0014
+-#define LTQ_RCU_STAT_SHIFT 26
++/* reset request register */
++#define RCU_RST_REQ 0x0010
++/* reset status register */
++#define RCU_RST_STAT 0x0014
++
++/* reset cause */
++#define RCU_STAT_SHIFT 26
++/* Global SW Reset */
++#define RCU_RD_SRST BIT(30)
++/* Memory Controller */
++#define RCU_RD_MC BIT(14)
++/* PCI core */
++#define RCU_RD_PCI BIT(13)
++/* Voice DFE/AFE */
++#define RCU_RD_DFE_AFE BIT(12)
++/* DSL AFE */
++#define RCU_RD_DSL_AFE BIT(11)
++/* SDIO core */
++#define RCU_RD_SDIO BIT(10)
++/* DMA core */
++#define RCU_RD_DMA BIT(9)
++/* PPE core */
++#define RCU_RD_PPE BIT(8)
++/* ARC/DFE core */
++#define RCU_RD_ARC_DFE BIT(7)
++/* AHB bus */
++#define RCU_RD_AHB BIT(6)
++/* Ethernet MAC1 */
++#define RCU_RD_ENET_MAC1 BIT(5)
++/* USB and Phy core */
++#define RCU_RD_USB BIT(4)
++/* CPU1 subsystem */
++#define RCU_RD_CPU1 BIT(3)
++/* FPI bus */
++#define RCU_RD_FPI BIT(2)
++/* CPU0 subsystem */
++#define RCU_RD_CPU0 BIT(1)
++/* HW reset via HRST pin */
++#define RCU_RD_HRST BIT(0)
+
+ static struct resource ltq_rcu_resource =
+ MEM_RES("rcu", LTQ_RCU_BASE_ADDR, LTQ_RCU_SIZE);
+@@ -36,16 +70,23 @@ static void __iomem *ltq_rcu_membase;
+ /* This function is used by the watchdog driver */
+ int ltq_reset_cause(void)
+ {
+- u32 val = ltq_rcu_r32(LTQ_RCU_RST_STAT);
+- return val >> LTQ_RCU_STAT_SHIFT;
++ u32 val = ltq_rcu_r32(RCU_RST_STAT);
++ return val >> RCU_STAT_SHIFT;
+ }
+ EXPORT_SYMBOL_GPL(ltq_reset_cause);
+
++void ltq_reset_once(unsigned int module, ulong usec)
++{
++ ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | module, RCU_RST_REQ);
++ udelay(usec);
++ ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) & ~module, RCU_RST_REQ);
++}
++
+ static void ltq_machine_restart(char *command)
+ {
+ pr_notice("System restart\n");
+ local_irq_disable();
+- ltq_rcu_w32(ltq_rcu_r32(LTQ_RCU_RST) | LTQ_RCU_RST_ALL, LTQ_RCU_RST);
++ ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | RCU_RD_SRST, RCU_RST_REQ);
+ unreachable();
+ }
+
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0063-MIPS-lantiq-fixes-ar9-vr9-clock.patch b/target/linux/lantiq/patches-3.2/0063-MIPS-lantiq-fixes-ar9-vr9-clock.patch
new file mode 100644
index 0000000..4a74160
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0063-MIPS-lantiq-fixes-ar9-vr9-clock.patch
@@ -0,0 +1,116 @@
+From 449adc45e29be18da14b23e9ccd97ba5251ffcc9 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Sat, 17 Mar 2012 09:58:07 +0100
+Subject: [PATCH 63/70] MIPS: lantiq: fixes ar9/vr9 clock
+
+---
+ arch/mips/lantiq/clk.h | 4 +++-
+ arch/mips/lantiq/xway/clk.c | 29 ++++++++++++++++++++++++-----
+ arch/mips/lantiq/xway/sysctrl.c | 13 ++++++++-----
+ 3 files changed, 35 insertions(+), 11 deletions(-)
+
+diff --git a/arch/mips/lantiq/clk.h b/arch/mips/lantiq/clk.h
+index b34e675..010dfa7 100644
+--- a/arch/mips/lantiq/clk.h
++++ b/arch/mips/lantiq/clk.h
+@@ -56,8 +56,10 @@ extern unsigned long ltq_danube_cpu_hz(void);
+ extern unsigned long ltq_danube_fpi_hz(void);
+ extern unsigned long ltq_danube_io_region_clock(void);
+
++extern unsigned long ltq_ar9_cpu_hz(void);
++extern unsigned long ltq_ar9_fpi_hz(void);
++
+ extern unsigned long ltq_vr9_cpu_hz(void);
+ extern unsigned long ltq_vr9_fpi_hz(void);
+-extern unsigned long ltq_vr9_io_region_clock(void);
+
+ #endif
+diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c
+index 3635c9f..2bafc04 100644
+--- a/arch/mips/lantiq/xway/clk.c
++++ b/arch/mips/lantiq/xway/clk.c
+@@ -217,6 +217,30 @@ unsigned long ltq_danube_cpu_hz(void)
+ }
+ }
+
++unsigned long ltq_ar9_sys_hz(void)
++{
++ if (((ltq_cgu_r32(LTQ_CGU_SYS) >> 3) & 0x3) == 0x2)
++ return CLOCK_393M;
++ return CLOCK_333M;
++}
++
++unsigned long ltq_ar9_fpi_hz(void)
++{
++ unsigned long sys = ltq_ar9_sys_hz();
++
++ if (ltq_cgu_r32(LTQ_CGU_SYS) & BIT(0))
++ return sys;
++ return sys >> 1;
++}
++
++unsigned long ltq_ar9_cpu_hz(void)
++{
++ if (ltq_cgu_r32(LTQ_CGU_SYS) & BIT(2))
++ return ltq_ar9_fpi_hz();
++ else
++ return ltq_ar9_sys_hz();
++}
++
+ unsigned long ltq_danube_fpi_hz(void)
+ {
+ unsigned long ddr_clock = DDR_HZ;
+@@ -299,11 +323,6 @@ unsigned long ltq_vr9_fpi_hz(void)
+ return clk;
+ }
+
+-unsigned long ltq_vr9_io_region_clock(void)
+-{
+- return ltq_vr9_fpi_hz();
+-}
+-
+ unsigned long ltq_vr9_fpi_bus_clock(int fpi)
+ {
+ return ltq_vr9_fpi_hz();
+diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
+index 9df048c..6771a7e 100644
+--- a/arch/mips/lantiq/xway/sysctrl.c
++++ b/arch/mips/lantiq/xway/sysctrl.c
+@@ -237,6 +237,8 @@ void __init ltq_soc_init(void)
+ clkdev_add_pmu("ltq_ebu", NULL, 0, PMU_EBU);
+ if (!ltq_is_vr9())
+ clkdev_add_pmu("ltq_etop", NULL, 0, PMU_PPE);
++ if (!ltq_is_ase())
++ clkdev_add_pci();
+ if (ltq_is_ase()) {
+ if (ltq_cgu_r32(CGU_SYS) & (1 << 5))
+ clkdev_add_static(CLOCK_266M, CLOCK_133M, CLOCK_133M);
+@@ -246,7 +248,7 @@ void __init ltq_soc_init(void)
+ clkdev_add_pmu("ltq_etop", "ephy", 0, PMU_EPHY);
+ } else if (ltq_is_vr9()) {
+ clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(),
+- ltq_vr9_io_region_clock());
++ ltq_vr9_fpi_hz());
+ clkdev_add_pmu("ltq_pcie", "phy", 1, PMU1_PCIE_PHY);
+ clkdev_add_pmu("ltq_pcie", "bus", 0, PMU_PCIE_CLK);
+ clkdev_add_pmu("ltq_pcie", "msi", 1, PMU1_PCIE_MSI);
+@@ -259,11 +261,12 @@ void __init ltq_soc_init(void)
+ PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
+ PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
+ PMU_PPE_QSB);
++ } else if (ltq_is_ar9()) {
++ clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
++ ltq_ar9_fpi_hz());
++ clkdev_add_pmu("ltq_etop", "switch", 0, PMU_SWITCH);
+ } else {
+ clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
+- ltq_danube_io_region_clock());
+- clkdev_add_pci();
+- if (ltq_is_ar9())
+- clkdev_add_pmu("ltq_etop", "switch", 0, PMU_SWITCH);
++ ltq_danube_io_region_clock());
+ }
+ }
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0064-MIPS-lantiq-fixes-danube-clock.patch b/target/linux/lantiq/patches-3.2/0064-MIPS-lantiq-fixes-danube-clock.patch
new file mode 100644
index 0000000..6d3cbf2
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0064-MIPS-lantiq-fixes-danube-clock.patch
@@ -0,0 +1,57 @@
+From 1303ac4fbe98c7132717102223089dc10d0ab4a2 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Mon, 19 Mar 2012 15:53:37 +0100
+Subject: [PATCH 64/70] MIPS: lantiq: fixes danube clock
+
+---
+ arch/mips/lantiq/xway/clk.c | 20 ++++++++++----------
+ 1 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/arch/mips/lantiq/xway/clk.c b/arch/mips/lantiq/xway/clk.c
+index 2bafc04..5d850dc 100644
+--- a/arch/mips/lantiq/xway/clk.c
++++ b/arch/mips/lantiq/xway/clk.c
+@@ -181,7 +181,7 @@ unsigned long ltq_danube_io_region_clock(void)
+ {
+ unsigned int ret = ltq_get_pll0_fosc();
+
+- switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
++ switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0x3) {
+ default:
+ case 0:
+ return (ret + 1) / 2;
+@@ -203,6 +203,15 @@ unsigned long ltq_danube_fpi_bus_clock(int fpi)
+ return ret;
+ }
+
++unsigned long ltq_danube_fpi_hz(void)
++{
++ unsigned long ddr_clock = DDR_HZ;
++
++ if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
++ return ddr_clock >> 1;
++ return ddr_clock;
++}
++
+ unsigned long ltq_danube_cpu_hz(void)
+ {
+ switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) {
+@@ -241,15 +250,6 @@ unsigned long ltq_ar9_cpu_hz(void)
+ return ltq_ar9_sys_hz();
+ }
+
+-unsigned long ltq_danube_fpi_hz(void)
+-{
+- unsigned long ddr_clock = DDR_HZ;
+-
+- if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
+- return ddr_clock >> 1;
+- return ddr_clock;
+-}
+-
+ unsigned long ltq_vr9_cpu_hz(void)
+ {
+ unsigned int cpu_sel;
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0065-MIPS-adds-dsl-clocks.patch b/target/linux/lantiq/patches-3.2/0065-MIPS-adds-dsl-clocks.patch
new file mode 100644
index 0000000..2d7de34
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0065-MIPS-adds-dsl-clocks.patch
@@ -0,0 +1,66 @@
+From a840d623b6a70428e8b698f0116fecc38e16e668 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 20 Mar 2012 13:05:11 +0100
+Subject: [PATCH 65/70] MIPS: adds dsl clocks
+
+---
+ arch/mips/lantiq/xway/sysctrl.c | 15 +++++++++++++--
+ 1 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
+index 6771a7e..3672fc6 100644
+--- a/arch/mips/lantiq/xway/sysctrl.c
++++ b/arch/mips/lantiq/xway/sysctrl.c
+@@ -41,8 +41,9 @@
+ #define PMU_PCI BIT(4)
+ #define PMU_DMA BIT(5)
+ #define PMU_USB0 BIT(5)
++#define PMU_EPHY BIT(7) /* ase */
+ #define PMU_SPI BIT(8)
+-#define PMU_EPHY BIT(7)
++#define PMU_DFE BIT(9)
+ #define PMU_EBU BIT(10)
+ #define PMU_STP BIT(11)
+ #define PMU_GPT BIT(12)
+@@ -147,7 +148,7 @@ static int ltq_pci_ext_enable(struct clk *clk)
+
+ static void ltq_pci_ext_disable(struct clk *clk)
+ {
+- /* enable external pci clock */
++ /* disable external pci clock (internal) */
+ ltq_cgu_w32(ltq_cgu_r32(CGU_IFCCR) | (1 << 16),
+ CGU_IFCCR);
+ ltq_cgu_w32((1 << 31) | (1 << 30), CGU_PCICR);
+@@ -246,6 +247,9 @@ void __init ltq_soc_init(void)
+ clkdev_add_static(CLOCK_133M, CLOCK_133M, CLOCK_133M);
+ clkdev_add_cgu("ltq_etop", "ephycgu", CGU_EPHY),
+ clkdev_add_pmu("ltq_etop", "ephy", 0, PMU_EPHY);
++ clkdev_add_pmu("ltq_dsl", NULL, 0,
++ PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
++ PMU_AHBS | PMU_DFE);
+ } else if (ltq_is_vr9()) {
+ clkdev_add_static(ltq_vr9_cpu_hz(), ltq_vr9_fpi_hz(),
+ ltq_vr9_fpi_hz());
+@@ -261,12 +265,19 @@ void __init ltq_soc_init(void)
+ PMU_SWITCH | PMU_PPE_DPLUS | PMU_PPE_DPLUM |
+ PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
+ PMU_PPE_QSB);
++ clkdev_add_pmu("ltq_dsl", NULL, 0, PMU_DFE | PMU_AHBS);
+ } else if (ltq_is_ar9()) {
+ clkdev_add_static(ltq_ar9_cpu_hz(), ltq_ar9_fpi_hz(),
+ ltq_ar9_fpi_hz());
+ clkdev_add_pmu("ltq_etop", "switch", 0, PMU_SWITCH);
++ clkdev_add_pmu("ltq_dsl", NULL, 0,
++ PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
++ PMU_PPE_QSB | PMU_AHBS | PMU_DFE);
+ } else {
+ clkdev_add_static(ltq_danube_cpu_hz(), ltq_danube_fpi_hz(),
+ ltq_danube_io_region_clock());
++ clkdev_add_pmu("ltq_dsl", NULL, 0,
++ PMU_PPE_EMA | PMU_PPE_TC | PMU_PPE_SLL01 |
++ PMU_PPE_QSB | PMU_AHBS | PMU_DFE);
+ }
+ }
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0066-MIPS-lantiq-dont-always-register-asc0.patch b/target/linux/lantiq/patches-3.2/0066-MIPS-lantiq-dont-always-register-asc0.patch
new file mode 100644
index 0000000..460dd2b
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0066-MIPS-lantiq-dont-always-register-asc0.patch
@@ -0,0 +1,31 @@
+From ff4470f274b61cebaeb1586f2f462ff66b8041cb Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 20 Mar 2012 08:22:11 +0100
+Subject: [PATCH 66/70] MIPS: lantiq: dont always register asc0
+
+---
+ arch/mips/lantiq/xway/prom.c | 6 ++----
+ 1 files changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/arch/mips/lantiq/xway/prom.c b/arch/mips/lantiq/xway/prom.c
+index e3dcbbd..f776d5a 100644
+--- a/arch/mips/lantiq/xway/prom.c
++++ b/arch/mips/lantiq/xway/prom.c
+@@ -101,12 +101,10 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
+
+ void __init ltq_soc_setup(void)
+ {
+- if (ltq_is_ase()) {
++ if (ltq_is_ase())
+ ltq_register_ase_asc();
+- } else {
+- ltq_register_asc(0);
++ else
+ ltq_register_asc(1);
+- }
+ ltq_register_gpio();
+ ltq_register_wdt();
+ }
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0067-MIPS-lantiq-irqs-were-not-cleared-properly-on-boot.patch b/target/linux/lantiq/patches-3.2/0067-MIPS-lantiq-irqs-were-not-cleared-properly-on-boot.patch
new file mode 100644
index 0000000..a97259c
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0067-MIPS-lantiq-irqs-were-not-cleared-properly-on-boot.patch
@@ -0,0 +1,34 @@
+From 845d2430d74cf6e2326da95b9205258170b30c86 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Tue, 20 Mar 2012 09:44:27 +0100
+Subject: [PATCH 67/70] MIPS: lantiq: irqs were not cleared properly on boot
+
+---
+ arch/mips/lantiq/irq.c | 10 +++++-----
+ 1 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
+index 770a10c..d4e70b4 100644
+--- a/arch/mips/lantiq/irq.c
++++ b/arch/mips/lantiq/irq.c
+@@ -327,12 +327,12 @@ void __init arch_init_irq(void)
+ panic("Failed to remap eiu memory\n");
+ }
+
+- /* make sure all irqs are turned off by default */
+- for (i = 0; i < 5; i++)
++ for (i = 0; i < 5; i++) {
++ /* make sure all irqs are turned off by default */
+ ltq_icu_w32(0, LTQ_ICU_IM0_IER + (i * LTQ_ICU_OFFSET));
+-
+- /* clear all possibly pending interrupts */
+- ltq_icu_w32(~0, LTQ_ICU_IM0_ISR + (i * LTQ_ICU_OFFSET));
++ /* clear all possibly pending interrupts */
++ ltq_icu_w32(~0, LTQ_ICU_IM0_ISR + (i * LTQ_ICU_OFFSET));
++ }
+
+ mips_cpu_irq_init();
+
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0068-MIPS-lantiq-adds-bootsel-helper.patch b/target/linux/lantiq/patches-3.2/0068-MIPS-lantiq-adds-bootsel-helper.patch
new file mode 100644
index 0000000..81a0cdb
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0068-MIPS-lantiq-adds-bootsel-helper.patch
@@ -0,0 +1,66 @@
+From 091358d0004ae2d2a28c9132e6976d46cf96fd3e Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Wed, 21 Mar 2012 14:17:37 +0100
+Subject: [PATCH 68/70] MIPS: lantiq: adds bootsel helper
+
+---
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 12 ++++++++++++
+ arch/mips/lantiq/xway/reset.c | 12 +++++++++++-
+ 2 files changed, 23 insertions(+), 1 deletions(-)
+
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+index bfdeb16..1ec8f2a 100644
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -144,6 +144,18 @@
+ #define LTQ_MPS_BASE_ADDR (KSEG1 + 0x1F107000)
+ #define LTQ_MPS_CHIPID ((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
+
++/* BOOT_SEL - find what boot media we have */
++#define BS_EXT_ROM 0x0
++#define BS_FLASH 0x1
++#define BS_MII0 0x2
++#define BS_PCI 0x3
++#define BS_UART1 0x4
++#define BS_SPI 0x5
++#define BS_NAND 0x6
++#define BS_RMII0 0x7
++
++extern unsigned char ltq_boot_select(void);
++
+ /* register access macros for EBU and CGU */
+ #define ltq_ebu_w32(x, y) ltq_w32((x), ltq_ebu_membase + (y))
+ #define ltq_ebu_r32(x) ltq_r32(ltq_ebu_membase + (x))
+diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
+index 8a5dff1..b8f7ffb 100644
+--- a/arch/mips/lantiq/xway/reset.c
++++ b/arch/mips/lantiq/xway/reset.c
+@@ -27,7 +27,11 @@
+ #define RCU_RST_STAT 0x0014
+
+ /* reset cause */
+-#define RCU_STAT_SHIFT 26
++#define RCU_STAT_SHIFT 26
++/* boot selection */
++#define RCU_BOOT_SEL_SHIFT 26
++#define RCU_BOOT_SEL_MASK 0x7
++
+ /* Global SW Reset */
+ #define RCU_RD_SRST BIT(30)
+ /* Memory Controller */
+@@ -75,6 +79,12 @@ int ltq_reset_cause(void)
+ }
+ EXPORT_SYMBOL_GPL(ltq_reset_cause);
+
++unsigned char ltq_boot_select(void)
++{
++ u32 val = ltq_rcu_r32(RCU_RST_STAT);
++ return (val >> RCU_BOOT_SEL_SHIFT) & RCU_BOOT_SEL_MASK;
++}
++
+ void ltq_reset_once(unsigned int module, ulong usec)
+ {
+ ltq_rcu_w32(ltq_rcu_r32(RCU_RST_REQ) | module, RCU_RST_REQ);
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches-3.2/0069-MIPS-lantiq-adds-USB_ARCH_HAS_HCD-to-CONFIG_LANTIQ.patch b/target/linux/lantiq/patches-3.2/0069-MIPS-lantiq-adds-USB_ARCH_HAS_HCD-to-CONFIG_LANTIQ.patch
new file mode 100644
index 0000000..a7ea1ad
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/0069-MIPS-lantiq-adds-USB_ARCH_HAS_HCD-to-CONFIG_LANTIQ.patch
@@ -0,0 +1,24 @@
+From 749d1baf548fda72bb1a74b7653415a63b00e8a0 Mon Sep 17 00:00:00 2001
+From: John Crispin <blogic@openwrt.org>
+Date: Fri, 23 Mar 2012 11:28:22 +0100
+Subject: [PATCH 69/70] MIPS: lantiq: adds USB_ARCH_HAS_HCD to CONFIG_LANTIQ
+
+---
+ arch/mips/Kconfig | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
+index 12ee3df..81b22c1 100644
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -229,6 +229,7 @@ config LANTIQ
+ select CLKDEV_LOOKUP
+ select HAVE_OPROFILE
+ select MIPS_MACHINE
++ select USB_ARCH_HAS_HCD
+
+ config LASAT
+ bool "LASAT Networks platforms"
+--
+1.7.7.1
+
diff --git a/target/linux/lantiq/patches/100-falcon_bsp_header.patch b/target/linux/lantiq/patches-3.2/100-falcon_bsp_header.patch
index 6110550..6110550 100644
--- a/target/linux/lantiq/patches/100-falcon_bsp_header.patch
+++ b/target/linux/lantiq/patches-3.2/100-falcon_bsp_header.patch
diff --git a/target/linux/lantiq/patches/110-sdk-compat.patch b/target/linux/lantiq/patches-3.2/101-sdk-compat.patch
index ca8d92e..ca8d92e 100644
--- a/target/linux/lantiq/patches/110-sdk-compat.patch
+++ b/target/linux/lantiq/patches-3.2/101-sdk-compat.patch
diff --git a/target/linux/lantiq/patches/200-owrt-netif_receive_skb.patch b/target/linux/lantiq/patches-3.2/200-owrt-netif_receive_skb.patch
index d1cb2ab..8bf776c 100644
--- a/target/linux/lantiq/patches/200-owrt-netif_receive_skb.patch
+++ b/target/linux/lantiq/patches-3.2/200-owrt-netif_receive_skb.patch
@@ -1,5 +1,5 @@
---- a/drivers/net/lantiq_etop.c
-+++ b/drivers/net/lantiq_etop.c
+--- a/drivers/net/ethernet/lantiq_etop.c
++++ b/drivers/net/ethernet/lantiq_etop.c
@@ -190,8 +190,12 @@ ltq_etop_hw_receive(struct ltq_etop_chan
skb_put(skb, len);
diff --git a/target/linux/lantiq/patches-3.2/201-owrt-mtd_split.patch b/target/linux/lantiq/patches-3.2/201-owrt-mtd_split.patch
new file mode 100644
index 0000000..aaf2395
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/201-owrt-mtd_split.patch
@@ -0,0 +1,244 @@
+Index: linux-3.2.9/drivers/mtd/Kconfig
+===================================================================
+--- linux-3.2.9.orig/drivers/mtd/Kconfig 2012-03-17 17:43:47.395607926 +0100
++++ linux-3.2.9/drivers/mtd/Kconfig 2012-03-17 20:49:30.279873461 +0100
+@@ -31,6 +31,10 @@
+ bool "Automatically split 'rootfs' partition for squashfs"
+ default y
+
++config MTD_UIMAGE_SPLIT
++ bool "Automatically split 'linux' partition into 'kernel' and 'rootfs'"
++ default y
++
+ config MTD_REDBOOT_PARTS
+ tristate "RedBoot partition table parsing"
+ ---help---
+Index: linux-3.2.9/drivers/mtd/mtdpart.c
+===================================================================
+--- linux-3.2.9.orig/drivers/mtd/mtdpart.c 2012-03-17 17:43:47.407607922 +0100
++++ linux-3.2.9/drivers/mtd/mtdpart.c 2012-03-17 20:49:42.987873819 +0100
+@@ -874,6 +874,169 @@
+ }
+ #endif /* CONFIG_MTD_ROOTFS_SPLIT */
+
++
++#ifdef CONFIG_MTD_UIMAGE_SPLIT
++static unsigned long find_uimage_size(struct mtd_info *mtd,
++ unsigned long offset)
++{
++#define UBOOT_MAGIC 0x56190527
++ unsigned long magic = 0;
++ unsigned long temp;
++ size_t len;
++ int ret;
++
++ ret = mtd->read(mtd, offset, 4, &len, (void *)&magic);
++ if (ret || len != sizeof(magic))
++ return 0;
++
++ if (le32_to_cpu(magic) != UBOOT_MAGIC)
++ return 0;
++
++ ret = mtd->read(mtd, offset + 12, 4, &len, (void *)&temp);
++ if (ret || len != sizeof(temp))
++ return 0;
++
++ return temp + 0x40;
++}
++
++static unsigned long find_eva_size(struct mtd_info *mtd,
++ unsigned long offset)
++{
++#define EVA_MAGIC 0xfeed1281
++ unsigned long magic = 0;
++ unsigned long temp;
++ size_t len;
++ int ret;
++
++ ret = mtd->read(mtd, offset, 4, &len, (void *)&magic);
++ if (ret || len != sizeof(magic))
++ return 0;
++
++ if (le32_to_cpu(magic) != EVA_MAGIC)
++ return 0;
++
++ ret = mtd->read(mtd, offset + 4, 4, &len, (void *)&temp);
++ if (ret || len != sizeof(temp))
++ return 0;
++
++ /* add eva header size */
++ temp = le32_to_cpu(temp) + 0x18;
++
++ temp &= ~0xffff;
++ temp += 0x10000;
++ return temp;
++}
++
++static int detect_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
++{
++ unsigned long temp;
++ size_t len;
++ int ret;
++
++ ret = mtd->read(mtd, offset, 4, &len, (void *)&temp);
++ if (ret || len != sizeof(temp))
++ return 0;
++
++
++ return le32_to_cpu(temp) == SQUASHFS_MAGIC;
++}
++
++static int detect_eva_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
++{
++ unsigned long temp;
++ size_t len;
++ int ret;
++
++ ret = mtd->read(mtd, offset, 4, &len, (void *)&temp);
++ if (ret || len != sizeof(temp))
++ return 0;
++
++ return be32_to_cpu(temp) == SQUASHFS_MAGIC;
++}
++
++static unsigned long find_brnimage_size(struct mtd_info *mtd,
++ unsigned long offset)
++{
++ unsigned long buf[4];
++ // Assume at most 2MB of kernel image
++ unsigned long end = offset + (2 << 20);
++ unsigned long ptr = offset + 0x400 - 12;
++ size_t len;
++ int ret;
++
++ while (ptr < end) {
++ long size_min = ptr - 0x400 - 12 - offset;
++ long size_max = ptr + 12 - offset;
++ ret = mtd->read(mtd, ptr, 16, &len, (void *)buf);
++ if (ret || len != 16)
++ return 0;
++
++ if (le32_to_cpu(buf[0]) < size_min ||
++ le32_to_cpu(buf[0]) > size_max) {
++ ptr += 0x400;
++ continue;
++ }
++
++ if (le32_to_cpu(buf[3]) == SQUASHFS_MAGIC)
++ return ptr + 12 - offset;
++
++ ptr += 0x400;
++ }
++
++ return 0;
++}
++
++static int split_uimage(struct mtd_info *mtd,
++ const struct mtd_partition *part)
++{
++ static struct mtd_partition split_partitions[] = {
++ {
++ .name = "kernel",
++ .offset = 0x0,
++ .size = 0x0,
++ }, {
++ .name = "rootfs",
++ .offset = 0x0,
++ .size = 0x0,
++ },
++ };
++
++ split_partitions[0].size = find_uimage_size(mtd, part->offset);
++ if (!split_partitions[0].size) {
++ split_partitions[0].size = find_eva_size(mtd, part->offset);
++ if (!split_partitions[0].size) {
++ split_partitions[0].size = find_brnimage_size(mtd, part->offset);
++ if (!split_partitions[0].size) {
++ printk(KERN_NOTICE "no uImage or brnImage or eva found in linux partition\n");
++ return -1;
++ }
++ }
++ }
++
++ if (detect_eva_squashfs_partition(mtd,
++ part->offset
++ + split_partitions[0].size)) {
++ split_partitions[0].size += 0x100;
++ pr_info("found eva dummy squashfs behind kernel\n");
++ } else if (!detect_squashfs_partition(mtd,
++ part->offset
++ + split_partitions[0].size)) {
++ split_partitions[0].size &= ~(mtd->erasesize - 1);
++ split_partitions[0].size += mtd->erasesize;
++ } else {
++ pr_info("found squashfs behind kernel\n");
++ }
++
++ split_partitions[0].offset = part->offset;
++ split_partitions[1].offset = part->offset + split_partitions[0].size;
++ split_partitions[1].size = part->size - split_partitions[0].size;
++
++ add_mtd_partitions(mtd, split_partitions, 2);
++
++ return 0;
++}
++#endif
++
+ /*
+ * This function, given a master MTD object and a partition table, creates
+ * and registers slave MTD objects which are bound to the master according to
+@@ -907,6 +1070,17 @@
+
+ add_mtd_device(&slave->mtd);
+
++#ifdef CONFIG_MTD_UIMAGE_SPLIT
++ if (!strcmp(parts[i].name, "linux")) {
++ ret = split_uimage(master, &parts[i]);
++
++ if (ret) {
++ printk(KERN_WARNING
++ "Can't split linux partition\n");
++ }
++ }
++#endif
++
+ if (!strcmp(parts[i].name, "rootfs")) {
+ #ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
+ if (ROOT_DEV == 0) {
+Index: linux-3.2.9/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+===================================================================
+--- linux-3.2.9.orig/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h 2012-03-17 20:49:32.000000000 +0100
++++ linux-3.2.9/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h 2012-03-17 20:50:07.815874369 +0100
+@@ -156,6 +156,7 @@
+
+ extern __iomem void *ltq_ebu_membase;
+ extern __iomem void *ltq_cgu_membase;
++extern unsigned long ltq_brn_boot;
+
+ static inline int ltq_is_ase(void)
+ {
+Index: linux-3.2.9/arch/mips/lantiq/setup.c
+===================================================================
+--- linux-3.2.9.orig/arch/mips/lantiq/setup.c 2012-03-17 20:49:32.000000000 +0100
++++ linux-3.2.9/arch/mips/lantiq/setup.c 2012-03-17 20:50:07.815874369 +0100
+@@ -18,6 +18,9 @@
+ #include "devices.h"
+ #include "prom.h"
+
++/* set to 1 if the bootloader is BRN-BOOT instead of u-boot */
++unsigned long ltq_brn_boot = 0;
++
+ void __init plat_mem_setup(void)
+ {
+ /* assume 16M as default incase uboot fails to pass proper ramsize */
+@@ -38,6 +41,10 @@
+ if (strict_strtoul(e, 0, &memsize))
+ pr_warn("bad memsize specified\n");
+ }
++ if (!strncmp(e, "BRN-BOOT", 8)){
++ pr_info("Found BRN-BOOT instead of u-boot\n");
++ ltq_brn_boot = 1;
++ }
+ envp++;
+ }
+ memsize *= 1024 * 1024;
diff --git a/target/linux/lantiq/patches/202-owrt-atm.patch b/target/linux/lantiq/patches-3.2/202-owrt-atm.patch
index 00af6e9..5f7be88 100644
--- a/target/linux/lantiq/patches/202-owrt-atm.patch
+++ b/target/linux/lantiq/patches-3.2/202-owrt-atm.patch
@@ -1,14 +1,16 @@
---- a/arch/mips/lantiq/irq.c
-+++ b/arch/mips/lantiq/irq.c
-@@ -9,6 +9,7 @@
-
+Index: linux-3.2.9/arch/mips/lantiq/irq.c
+===================================================================
+--- linux-3.2.9.orig/arch/mips/lantiq/irq.c 2012-03-08 17:17:13.937473031 +0100
++++ linux-3.2.9/arch/mips/lantiq/irq.c 2012-03-08 17:32:57.389513360 +0100
+@@ -10,6 +10,7 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
+ #include <linux/sched.h>
+#include <linux/module.h>
#include <asm/bootinfo.h>
#include <asm/irq_cpu.h>
-@@ -102,6 +103,7 @@ void ltq_mask_and_ack_irq(struct irq_dat
+@@ -111,6 +112,7 @@
ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier);
ltq_icu_w32((1 << irq_nr), isr);
}
@@ -16,9 +18,11 @@
static void ltq_ack_irq(struct irq_data *d)
{
---- a/arch/mips/mm/cache.c
-+++ b/arch/mips/mm/cache.c
-@@ -52,6 +52,8 @@ void (*_dma_cache_wback)(unsigned long s
+Index: linux-3.2.9/arch/mips/mm/cache.c
+===================================================================
+--- linux-3.2.9.orig/arch/mips/mm/cache.c 2012-03-01 01:32:49.000000000 +0100
++++ linux-3.2.9/arch/mips/mm/cache.c 2012-03-08 17:17:14.193473042 +0100
+@@ -57,6 +57,8 @@
void (*_dma_cache_inv)(unsigned long start, unsigned long size);
EXPORT_SYMBOL(_dma_cache_wback_inv);
@@ -27,9 +31,11 @@
#endif /* CONFIG_DMA_NONCOHERENT */
---- a/net/atm/proc.c
-+++ b/net/atm/proc.c
-@@ -154,7 +154,7 @@ static void *vcc_seq_next(struct seq_fil
+Index: linux-3.2.9/net/atm/proc.c
+===================================================================
+--- linux-3.2.9.orig/net/atm/proc.c 2012-03-01 01:32:49.000000000 +0100
++++ linux-3.2.9/net/atm/proc.c 2012-03-08 17:17:14.193473042 +0100
+@@ -154,7 +154,7 @@
static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc)
{
static const char *const class_name[] = {
@@ -38,9 +44,11 @@
static const char *const aal_name[] = {
"---", "1", "2", "3/4", /* 0- 3 */
"???", "5", "???", "???", /* 4- 7 */
---- a/net/atm/common.c
-+++ b/net/atm/common.c
-@@ -62,11 +62,17 @@ static void vcc_remove_socket(struct soc
+Index: linux-3.2.9/net/atm/common.c
+===================================================================
+--- linux-3.2.9.orig/net/atm/common.c 2012-03-01 01:32:49.000000000 +0100
++++ linux-3.2.9/net/atm/common.c 2012-03-08 17:17:14.193473042 +0100
+@@ -62,11 +62,17 @@
write_unlock_irq(&vcc_sklist_lock);
}
diff --git a/target/linux/lantiq/patches/203-owrt-cmdline.patch b/target/linux/lantiq/patches-3.2/203-owrt-cmdline.patch
index cd7c95a..cd7c95a 100644
--- a/target/linux/lantiq/patches/203-owrt-cmdline.patch
+++ b/target/linux/lantiq/patches-3.2/203-owrt-cmdline.patch
diff --git a/target/linux/lantiq/patches/204-owrt-dm9000-polling.patch b/target/linux/lantiq/patches-3.2/204-owrt-dm9000-polling.patch
index 11fa539..4f5ce9e 100644
--- a/target/linux/lantiq/patches/204-owrt-dm9000-polling.patch
+++ b/target/linux/lantiq/patches-3.2/204-owrt-dm9000-polling.patch
@@ -1,5 +1,5 @@
---- a/drivers/net/dm9000.c
-+++ b/drivers/net/dm9000.c
+--- a/drivers/net/ethernet/davicom/dm9000.c
++++ b/drivers/net/ethernet/davicom/dm9000.c
@@ -19,6 +19,7 @@
* Sascha Hauer <s.hauer@pengutronix.de>
*/
diff --git a/target/linux/lantiq/patches/205-owrt-gpio-export.patch b/target/linux/lantiq/patches-3.2/205-owrt-gpio-export.patch
index 7839327..7839327 100644
--- a/target/linux/lantiq/patches/205-owrt-gpio-export.patch
+++ b/target/linux/lantiq/patches-3.2/205-owrt-gpio-export.patch
diff --git a/target/linux/lantiq/patches/210-machtypes.patch b/target/linux/lantiq/patches-3.2/206-machtypes.patch
index 55b6742..c964488 100644
--- a/target/linux/lantiq/patches/210-machtypes.patch
+++ b/target/linux/lantiq/patches-3.2/206-machtypes.patch
@@ -1,6 +1,6 @@
--- a/arch/mips/lantiq/machtypes.h
+++ b/arch/mips/lantiq/machtypes.h
-@@ -20,9 +20,34 @@ enum lantiq_mach_type {
+@@ -20,6 +20,36 @@ enum lantiq_mach_type {
LANTIQ_MACH_EASY98000, /* Falcon Eval Board, NOR Flash */
LANTIQ_MACH_EASY98000SF, /* Falcon Eval Board, Serial Flash */
LANTIQ_MACH_EASY98000NAND, /* Falcon Eval Board, NAND Flash */
@@ -8,14 +8,12 @@
+ LANTIQ_MACH_EASY98020_1LAN, /* EASY98020 Eval Board (1 LAN port) */
+ LANTIQ_MACH_EASY98020_2LAN, /* EASY98020 Eval Board (2 LAN port) */
+ LANTIQ_MACH_95C3AM1, /* 95C3AM1 Eval Board */
-
- /* FRITZ!BOX */
- LANTIQ_MACH_FRITZ3370, /* FRITZ!BOX 3370 vdsl cpe */
+
+ /* Arcadyan */
+ LANTIQ_MACH_ARV3527P, /* Arcor easybox a401 */
+ LANTIQ_MACH_ARV4510PW, /* Wippies Homebox */
+ LANTIQ_MACH_ARV4518PW, /* Airties WAV-221, SMC-7908A-ISP */
++ LANTIQ_MACH_ARV4519PW, /* Vodafone, Pirelli */
+ LANTIQ_MACH_ARV4520PW, /* Airties WAV-281, Arcor EasyboxA800 */
+ LANTIQ_MACH_ARV452CPW, /* Arcor EasyboxA801 */
+ LANTIQ_MACH_ARV4525PW, /* Speedport W502V */
@@ -27,6 +25,10 @@
+ /* Netgear */
+ LANTIQ_MACH_DGN3500B, /* Netgear DGN3500 */
+
++ /* FRITZ!BOX */
++ LANTIQ_MACH_FRITZ3370, /* FRITZ!BOX 3370 vdsl cpe */
++ LANTIQ_MACH_FRITZ7320, /* FRITZ!BOX 7320 1&1 homeserver */
++
+ /* Gigaset */
+ LANTIQ_MACH_GIGASX76X, /* Gigaset SX76x */
+
@@ -37,12 +39,12 @@
#endif
--- a/arch/mips/lantiq/xway/Kconfig
+++ b/arch/mips/lantiq/xway/Kconfig
-@@ -6,6 +6,22 @@ config LANTIQ_MACH_EASY50712
+@@ -6,6 +6,30 @@ config LANTIQ_MACH_EASY50712
bool "Easy50712 - Danube"
default y
-+config LANTIQ_MACH_ARV45XX
-+ bool "ARV45XX"
++config LANTIQ_MACH_ARV
++ bool "ARV"
+ default y
+
+config LANTIQ_MACH_NETGEAR
@@ -57,18 +59,28 @@
+ bool "WBMR-HP-G300H"
+ default y
+
++config LANTIQ_MACH_FRITZ_VR9
++ bool "FRITZ3370"
++ default y
++
++config LANTIQ_MACH_FRITZ_AR9
++ bool "FRITZ7320"
++ default y
++
endmenu
- endif
+ choice
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
-@@ -7,3 +7,7 @@ obj-$(CONFIG_SOC_VR9) += clk-vr9.o prom-
+@@ -2,3 +2,9 @@ obj-y := sysctrl.o reset.o gpio.o gpio_s
+
obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
- obj-$(CONFIG_LANTIQ_MACH_FRITZ3370) += mach-fritz.o
-+obj-$(CONFIG_LANTIQ_MACH_ARV45XX) += mach-arv45xx.o
-+obj-$(CONFIG_LANTIQ_MACH_NETGEAR) += mach-netgear.o
++obj-$(CONFIG_LANTIQ_MACH_ARV) += mach-arv.o
++obj-$(CONFIG_LANTIQ_MACH_FRITZ_AR9) += mach-fritz_ar9.o
++obj-$(CONFIG_LANTIQ_MACH_FRITZ_VR9) += mach-fritz_vr9.o
+obj-$(CONFIG_LANTIQ_MACH_GIGASX76X) += mach-gigasx76x.o
++obj-$(CONFIG_LANTIQ_MACH_NETGEAR) += mach-netgear.o
+obj-$(CONFIG_LANTIQ_MACH_WBMR) += mach-wbmr.o
--- a/arch/mips/lantiq/falcon/Kconfig
+++ b/arch/mips/lantiq/falcon/Kconfig
@@ -90,7 +102,7 @@
--- a/arch/mips/lantiq/falcon/Makefile
+++ b/arch/mips/lantiq/falcon/Makefile
@@ -1,2 +1,6 @@
- obj-y := clk.o prom.o reset.o sysctrl.o devices.o gpio.o softdog_vpe.o
+ obj-y := prom.o reset.o sysctrl.o devices.o gpio.o
+obj-$(CONFIG_LANTIQ_MACH_EASY98000) += addon-easy98000.o
+obj-$(CONFIG_LANTIQ_MACH_EASY98000) += dev-leds-easy98000-cpld.o
obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o
@@ -138,10 +150,10 @@
+#define EASY98000_GPIO_LED_3 12
+#define EASY98000_GPIO_LED_4 13
+#define EASY98000_GPIO_LED_5 14
-+
-+extern unsigned char ltq_ethaddr[6];
-static struct mtd_partition easy98000_nor_partitions[] = {
++extern unsigned char ltq_ethaddr[6];
++
+static struct mtd_partition easy98000_nor_partitions[] =
+{
{
@@ -267,48 +279,27 @@
#define SPI_GPIO_BUS_NUM 1
static struct spi_gpio_platform_data easy98000_spi_gpio_data = {
-@@ -93,29 +201,36 @@ static struct spi_board_info easy98000_s
- .platform_data = &at25160n,
+@@ -94,11 +202,22 @@ static struct spi_board_info easy98000_s
};
--static void __init
+ static void __init
-easy98000_init_common(void)
-+static void __init easy98000_spi_gpio_init(void)
++easy98000_spi_gpio_init(void)
{
spi_register_board_info(&easy98000_spi_gpio_devices, 1);
platform_device_register(&easy98000_spi_gpio_device);
- }
-
--static void __init
--easy98000_init(void)
-+static void __init easy98000_init_common(void)
++}
++
++static void __init
++easy98000_init_common(void)
+{
-+ falcon_register_i2c();
+ falcon_register_i2c();
+ platform_device_register(&easy98000_i2c_gpio_device);
+ register_davicom();
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(easy98000_leds_gpio),
-+ easy98000_leds_gpio);
++ easy98000_leds_gpio);
+ register_easy98000_cpld();
+ easy98000_spi_gpio_init();
-+}
-+
-+static void __init easy98000_init(void)
- {
- easy98000_init_common();
- ltq_register_nor(&easy98000_nor_flash_data);
- }
-
--static void __init
--easy98000sf_init(void)
-+static void __init easy98000sf_init(void)
- {
- easy98000_init_common();
- falcon_register_spi_flash(&easy98000_spi_flash_data);
}
--static void __init
--easy98000nand_init(void)
-+static void __init easy98000nand_init(void)
- {
- easy98000_init_common();
- falcon_register_nand();
+ static void __init
diff --git a/target/linux/lantiq/patches/211-devices.patch b/target/linux/lantiq/patches-3.2/207-devices.patch
index 408d680..2bc498d 100644
--- a/target/linux/lantiq/patches/211-devices.patch
+++ b/target/linux/lantiq/patches-3.2/207-devices.patch
@@ -40,14 +40,15 @@
#endif
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
-@@ -1,5 +1,7 @@
- obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o nand.o timer.o
+@@ -1,5 +1,8 @@
+ obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o clk.o prom.o nand.o timer.o dev-ifxhcd.o
-+obj-y += dev-dwc_otg.o dev-wifi-rt2x00.o dev-wifi-ath5k.o
++obj-y += dev-dwc_otg.o
++obj-$(CONFIG_PCI) += dev-wifi-rt2x00.o dev-wifi-athxk.o pci-ath-fixup.o
+
- obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
- obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
- obj-$(CONFIG_SOC_VR9) += clk-vr9.o prom-vr9.o
+ obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
+ obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
+ obj-$(CONFIG_LANTIQ_MACH_ARV) += mach-arv.o
--- a/arch/mips/lantiq/xway/devices.c
+++ b/arch/mips/lantiq/xway/devices.c
@@ -19,6 +19,7 @@
@@ -58,25 +59,11 @@
#include <asm/bootinfo.h>
#include <asm/irq.h>
-@@ -99,3 +100,98 @@ ltq_register_etop(struct ltq_eth_data *e
- platform_device_register(&ltq_etop);
- }
+@@ -119,3 +120,84 @@ ltq_register_vrx200(struct ltq_eth_data
+ ltq_vrx200.dev.platform_data = eth;
+ platform_device_register(&ltq_vrx200);
}
+
-+/* madwifi */
-+int lantiq_emulate_madwifi_eep = 0;
-+EXPORT_SYMBOL(lantiq_emulate_madwifi_eep);
-+
-+int lantiq_madwifi_eep_addr = 0;
-+EXPORT_SYMBOL(lantiq_madwifi_eep_addr);
-+
-+void __init
-+ltq_register_madwifi_eep(unsigned long long addr)
-+{
-+ lantiq_madwifi_eep_addr = addr;
-+ lantiq_emulate_madwifi_eep = 1;
-+}
-+
+/* ebu */
+static struct resource ltq_ebu_resource =
+{
@@ -159,7 +146,7 @@
+}
--- a/arch/mips/lantiq/xway/devices.h
+++ b/arch/mips/lantiq/xway/devices.h
-@@ -11,10 +11,17 @@
+@@ -11,6 +11,8 @@
#include "../devices.h"
#include <linux/phy.h>
@@ -168,12 +155,13 @@
extern void ltq_register_gpio(void);
extern void ltq_register_gpio_stp(void);
- extern void ltq_register_ase_asc(void);
+@@ -18,5 +20,9 @@ extern void ltq_register_ase_asc(void);
extern void ltq_register_etop(struct ltq_eth_data *eth);
+ extern void xway_register_nand(struct mtd_partition *parts, int count);
+ extern void ltq_register_vrx200(struct ltq_eth_data *eth);
+extern void ltq_register_gpio_ebu(unsigned int value);
+extern void ltq_register_spi(struct ltq_spi_platform_data *pdata,
+ struct spi_board_info const *info, unsigned n);
-+extern void ltq_register_madwifi_eep(unsigned long long addr);
+extern void ltq_register_gpio_buttons(struct gpio_button *buttons, int cnt);
#endif
diff --git a/target/linux/lantiq/patches/810-fix-mach-easy98000.patch b/target/linux/lantiq/patches-3.2/208-fix-mach-easy98000.patch
index 94b7b92..021bb88 100644
--- a/target/linux/lantiq/patches/810-fix-mach-easy98000.patch
+++ b/target/linux/lantiq/patches-3.2/208-fix-mach-easy98000.patch
@@ -1,5 +1,7 @@
---- a/arch/mips/lantiq/falcon/mach-easy98000.c
-+++ b/arch/mips/lantiq/falcon/mach-easy98000.c
+Index: linux-3.2.9/arch/mips/lantiq/falcon/mach-easy98000.c
+===================================================================
+--- linux-3.2.9.orig/arch/mips/lantiq/falcon/mach-easy98000.c 2012-03-07 19:30:22.000000000 +0100
++++ linux-3.2.9/arch/mips/lantiq/falcon/mach-easy98000.c 2012-03-07 19:35:47.804810934 +0100
@@ -17,10 +17,11 @@
#include <linux/spi/eeprom.h>
#include <falcon/lantiq_soc.h>
@@ -31,7 +33,7 @@
static struct mtd_partition easy98000_nor_partitions[] =
{
-@@ -70,7 +80,7 @@ static struct spi_board_info easy98000_s
+@@ -70,7 +80,7 @@
.platform_data = &easy98000_spi_flash_platform_data
};
@@ -40,7 +42,7 @@
{
.name = "easy98000:green:0",
.gpio = EASY98000_GPIO_LED_0,
-@@ -104,12 +114,11 @@ static struct gpio_led easy98000_leds_gp
+@@ -104,12 +114,11 @@
static struct dm9000_plat_data dm9000_plat_data = {
.flags = DM9000_PLATF_8BITONLY,
@@ -55,14 +57,14 @@
[2] = {
/* with irq (210 -> gpio 110) the driver is very unreliable */
.start = -1, /* use polling */
-@@ -212,8 +221,8 @@ static void __init easy98000_init_common
+@@ -214,8 +223,8 @@
falcon_register_i2c();
platform_device_register(&easy98000_i2c_gpio_device);
register_davicom();
- ltq_add_device_leds_gpio(-1, ARRAY_SIZE(easy98000_leds_gpio),
-- easy98000_leds_gpio);
+- easy98000_leds_gpio);
+ ltq_add_device_gpio_leds(-1, ARRAY_SIZE(easy98000_gpio_leds),
-+ easy98000_gpio_leds);
++ easy98000_gpio_leds);
register_easy98000_cpld();
easy98000_spi_gpio_init();
}
diff --git a/target/linux/lantiq/patches-3.2/209-fritz_ram.patch b/target/linux/lantiq/patches-3.2/209-fritz_ram.patch
new file mode 100644
index 0000000..cb77a86
--- /dev/null
+++ b/target/linux/lantiq/patches-3.2/209-fritz_ram.patch
@@ -0,0 +1,17 @@
+Index: linux-3.2.9/arch/mips/lantiq/setup.c
+===================================================================
+--- linux-3.2.9.orig/arch/mips/lantiq/setup.c 2012-03-20 11:23:49.000000000 +0100
++++ linux-3.2.9/arch/mips/lantiq/setup.c 2012-03-20 11:25:54.119568502 +0100
+@@ -40,6 +40,12 @@
+ e += 8;
+ if (strict_strtoul(e, 0, &memsize))
+ pr_warn("bad memsize specified\n");
++ } else if (!strcmp(e, "memsize")) {
++ envp++;
++ e = (char *)KSEG1ADDR(*envp);
++ if (strict_strtoul(e, 0, &memsize))
++ pr_warn("bad memsize specified\n");
++ memsize /= 1024 * 1024;
+ }
+ if (!strncmp(e, "BRN-BOOT", 8)){
+ pr_info("Found BRN-BOOT instead of u-boot\n");
diff --git a/target/linux/lantiq/patches/0016-MIPS-lantiq-adds-xway-nand-driver.patch b/target/linux/lantiq/patches/0016-MIPS-lantiq-adds-xway-nand-driver.patch
deleted file mode 100644
index b7ad789..0000000
--- a/target/linux/lantiq/patches/0016-MIPS-lantiq-adds-xway-nand-driver.patch
+++ /dev/null
@@ -1,253 +0,0 @@
-From e2d5b4ba92289cb0fcc9db741d159ef5eb852d9f Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sat, 27 Aug 2011 20:08:14 +0200
-Subject: [PATCH 16/24] MIPS: lantiq: adds xway nand driver
-
-This patch adds a nand driver for XWAY SoCs. The patch makes use of the
-plat_nand driver. As with the EBU NOR driver merged in 3.0, we have the
-endianess swap problem on read. To workaround this problem we make the
-read_byte() callback available via the plat_nand driver causing the nand
-layer to do byte reads.
-
-Signed-off-by: John Crispin <blogic@openwrt.org>
-
-TODO : memory ranges
- cs lines
- plat dev
- ebu2 and not ebu1 ?
----
- .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 2 +
- arch/mips/lantiq/xway/Makefile | 2 +-
- arch/mips/lantiq/xway/nand.c | 185 ++++++++++++++++++++
- drivers/mtd/nand/plat_nand.c | 1 +
- include/linux/mtd/nand.h | 1 +
- 5 files changed, 190 insertions(+), 1 deletions(-)
- create mode 100644 arch/mips/lantiq/xway/nand.c
-
---- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
-+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
-@@ -138,6 +138,8 @@
- /* register access macros for EBU and CGU */
- #define ltq_ebu_w32(x, y) ltq_w32((x), ltq_ebu_membase + (y))
- #define ltq_ebu_r32(x) ltq_r32(ltq_ebu_membase + (x))
-+#define ltq_ebu_w32_mask(x, y, z) \
-+ ltq_w32_mask(x, y, ltq_ebu_membase + (z))
- #define ltq_cgu_w32(x, y) ltq_w32((x), ltq_cgu_membase + (y))
- #define ltq_cgu_r32(x) ltq_r32(ltq_cgu_membase + (x))
-
---- a/arch/mips/lantiq/xway/Makefile
-+++ b/arch/mips/lantiq/xway/Makefile
-@@ -1,4 +1,4 @@
--obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o
-+obj-y := sysctrl.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o nand.o
-
- obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
- obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
---- /dev/null
-+++ b/arch/mips/lantiq/xway/nand.c
-@@ -0,0 +1,185 @@
-+/*
-+ * 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.
-+ *
-+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#include <linux/mtd/physmap.h>
-+#include <linux/mtd/nand.h>
-+#include <linux/platform_device.h>
-+
-+#include <lantiq_soc.h>
-+#include <lantiq_irq.h>
-+#include <lantiq_platform.h>
-+
-+#include "devices.h"
-+
-+/* nand registers */
-+#define LTQ_EBU_NAND_WAIT 0xB4
-+#define LTQ_EBU_NAND_ECC0 0xB8
-+#define LTQ_EBU_NAND_ECC_AC 0xBC
-+#define LTQ_EBU_NAND_CON 0xB0
-+#define LTQ_EBU_ADDSEL1 0x24
-+
-+/* gpio definitions */
-+#define PIN_ALE 13
-+#define PIN_CLE 24
-+#define PIN_CS1 23
-+#define PIN_RDY 48 /* NFLASH_READY */
-+#define PIN_RD 49 /* NFLASH_READ_N */
-+
-+#define NAND_CMD_ALE (1 << 2)
-+#define NAND_CMD_CLE (1 << 3)
-+#define NAND_CMD_CS (1 << 4)
-+#define NAND_WRITE_CMD_RESET 0xff
-+#define NAND_WRITE_CMD (NAND_CMD_CS | NAND_CMD_CLE)
-+#define NAND_WRITE_ADDR (NAND_CMD_CS | NAND_CMD_ALE)
-+#define NAND_WRITE_DATA (NAND_CMD_CS)
-+#define NAND_READ_DATA (NAND_CMD_CS)
-+#define NAND_WAIT_WR_C (1 << 3)
-+#define NAND_WAIT_RD (0x1)
-+
-+#define ADDSEL1_MASK(x) (x << 4)
-+#define ADDSEL1_REGEN 1
-+#define BUSCON1_SETUP (1 << 22)
-+#define BUSCON1_BCGEN_RES (0x3 << 12)
-+#define BUSCON1_WAITWRC2 (2 << 8)
-+#define BUSCON1_WAITRDC2 (2 << 6)
-+#define BUSCON1_HOLDC1 (1 << 4)
-+#define BUSCON1_RECOVC1 (1 << 2)
-+#define BUSCON1_CMULT4 1
-+#define NAND_CON_NANDM 1
-+#define NAND_CON_CSMUX (1 << 1)
-+#define NAND_CON_CS_P (1 << 4)
-+#define NAND_CON_SE_P (1 << 5)
-+#define NAND_CON_WP_P (1 << 6)
-+#define NAND_CON_PRE_P (1 << 7)
-+#define NAND_CON_IN_CS0 0
-+#define NAND_CON_OUT_CS0 0
-+#define NAND_CON_IN_CS1 (1 << 8)
-+#define NAND_CON_OUT_CS1 (1 << 10)
-+#define NAND_CON_CE (1 << 20)
-+
-+#define NAND_BASE_ADDRESS (KSEG1 | 0x14000000)
-+
-+static const char *part_probes[] = { "cmdlinepart", NULL };
-+
-+static void
-+xway_select_chip(struct mtd_info *mtd, int chip)
-+{
-+ switch (chip) {
-+ case -1:
-+ ltq_ebu_w32_mask(NAND_CON_CE, 0, LTQ_EBU_NAND_CON);
-+ ltq_ebu_w32_mask(NAND_CON_NANDM, 0, LTQ_EBU_NAND_CON);
-+ break;
-+ case 0:
-+ ltq_ebu_w32_mask(0, NAND_CON_NANDM, LTQ_EBU_NAND_CON);
-+ ltq_ebu_w32_mask(0, NAND_CON_CE, LTQ_EBU_NAND_CON);
-+ /* reset the nand chip */
-+ while((ltq_ebu_r32(LTQ_EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0);
-+ ltq_w32(NAND_WRITE_CMD_RESET, ((u32*)(NAND_BASE_ADDRESS | NAND_WRITE_CMD)));
-+ break;
-+ default:
-+ BUG();
-+ }
-+}
-+
-+static void
-+xway_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
-+{
-+ struct nand_chip *this = mtd->priv;
-+
-+ if (ctrl & NAND_CTRL_CHANGE) {
-+ if(ctrl & NAND_CLE)
-+ this->IO_ADDR_W = (void __iomem *)(NAND_BASE_ADDRESS | NAND_WRITE_CMD);
-+ else if(ctrl & NAND_ALE)
-+ this->IO_ADDR_W = (void __iomem *)(NAND_BASE_ADDRESS | NAND_WRITE_ADDR);
-+ }
-+
-+ if(data != NAND_CMD_NONE) {
-+ *(volatile u8*)((u32)this->IO_ADDR_W) = data;
-+ while((ltq_ebu_r32(LTQ_EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0);
-+ }
-+}
-+
-+static int
-+xway_dev_ready(struct mtd_info *mtd)
-+{
-+ return ltq_ebu_r32(LTQ_EBU_NAND_WAIT) & NAND_WAIT_RD;
-+}
-+
-+void
-+nand_write(unsigned int addr, unsigned int val)
-+{
-+ ltq_w32(val, ((u32*)(NAND_BASE_ADDRESS | addr)));
-+ while((ltq_ebu_r32(LTQ_EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0);
-+}
-+
-+unsigned char
-+ltq_nand_read_byte(struct mtd_info *mtd)
-+{
-+ return ltq_r8((void __iomem *)(NAND_BASE_ADDRESS | (NAND_READ_DATA)));
-+}
-+
-+int xway_nand_probe(struct platform_device *pdev)
-+{
-+// ltq_gpio_request(PIN_CS1, 1, 0, 1, "NAND_CS1");
-+ ltq_gpio_request(PIN_CLE, 1, 0, 1, "NAND_CLE");
-+ ltq_gpio_request(PIN_ALE, 1, 0, 1, "NAND_ALE");
-+ if (ltq_is_ar9() || ltq_is_vr9()) {
-+ ltq_gpio_request(PIN_RDY, 1, 0, 0, "NAND_BSY");
-+ ltq_gpio_request(PIN_RD, 1, 0, 1, "NAND_RD");
-+ }
-+
-+ ltq_ebu_w32((NAND_BASE_ADDRESS & 0x1fffff00)
-+ | ADDSEL1_MASK(3) | ADDSEL1_REGEN, LTQ_EBU_ADDSEL1);
-+
-+ ltq_ebu_w32(BUSCON1_SETUP | BUSCON1_BCGEN_RES | BUSCON1_WAITWRC2
-+ | BUSCON1_WAITRDC2 | BUSCON1_HOLDC1 | BUSCON1_RECOVC1
-+ | BUSCON1_CMULT4, LTQ_EBU_BUSCON1);
-+
-+ ltq_ebu_w32(NAND_CON_NANDM | NAND_CON_CSMUX | NAND_CON_CS_P
-+ | NAND_CON_SE_P | NAND_CON_WP_P | NAND_CON_PRE_P
-+ | NAND_CON_IN_CS0 | NAND_CON_OUT_CS0, LTQ_EBU_NAND_CON);
-+
-+ ltq_w32(NAND_WRITE_CMD_RESET, ((u32*)(NAND_BASE_ADDRESS | NAND_WRITE_CMD)));
-+ while((ltq_ebu_r32(LTQ_EBU_NAND_WAIT) & NAND_WAIT_WR_C) == 0);
-+
-+ return 0;
-+}
-+
-+static struct platform_nand_data falcon_flash_nand_data = {
-+ .chip = {
-+ .nr_chips = 1,
-+ .chip_delay = 30,
-+ .part_probe_types = part_probes,
-+ },
-+ .ctrl = {
-+ .probe = xway_nand_probe,
-+ .cmd_ctrl = xway_cmd_ctrl,
-+ .dev_ready = xway_dev_ready,
-+ .select_chip = xway_select_chip,
-+ .read_byte = ltq_nand_read_byte,
-+ }
-+};
-+
-+static struct resource ltq_nand_res =
-+ MEM_RES("nand", 0x14000000, 0x3ffffff);
-+
-+static struct platform_device ltq_flash_nand = {
-+ .name = "gen_nand",
-+ .id = -1,
-+ .num_resources = 1,
-+ .resource = &ltq_nand_res,
-+ .dev = {
-+ .platform_data = &falcon_flash_nand_data,
-+ },
-+};
-+
-+void __init
-+xway_register_nand(void)
-+{
-+ platform_device_register(&ltq_flash_nand);
-+}
---- a/drivers/mtd/nand/plat_nand.c
-+++ b/drivers/mtd/nand/plat_nand.c
-@@ -77,6 +77,7 @@ static int __devinit plat_nand_probe(str
- data->chip.select_chip = pdata->ctrl.select_chip;
- data->chip.write_buf = pdata->ctrl.write_buf;
- data->chip.read_buf = pdata->ctrl.read_buf;
-+ data->chip.read_byte = pdata->ctrl.read_byte;
- data->chip.chip_delay = pdata->chip.chip_delay;
- data->chip.options |= pdata->chip.options;
-
---- a/include/linux/mtd/nand.h
-+++ b/include/linux/mtd/nand.h
-@@ -657,6 +657,7 @@ struct platform_nand_ctrl {
- void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
- void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
- void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
-+ unsigned char (*read_byte)(struct mtd_info *mtd);
- void *priv;
- };
-
diff --git a/target/linux/lantiq/patches/0023-MIPS-lantiq-adds-basic-vr9-support.patch b/target/linux/lantiq/patches/0023-MIPS-lantiq-adds-basic-vr9-support.patch
deleted file mode 100644
index bb7422c..0000000
--- a/target/linux/lantiq/patches/0023-MIPS-lantiq-adds-basic-vr9-support.patch
+++ /dev/null
@@ -1,262 +0,0 @@
-From 780a64cd52209fad15c7133f950b2b2d6b9b59e2 Mon Sep 17 00:00:00 2001
-From: John Crispin <blogic@openwrt.org>
-Date: Sat, 27 Aug 2011 21:44:32 +0200
-Subject: [PATCH 23/24] MIPS: lantiq: adds basic vr9 support
-
----
- .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 2 +
- arch/mips/lantiq/Kconfig | 9 ++
- arch/mips/lantiq/Platform | 1 +
- arch/mips/lantiq/machtypes.h | 3 +
- arch/mips/lantiq/xway/Kconfig | 12 +++
- arch/mips/lantiq/xway/Makefile | 2 +
- arch/mips/lantiq/xway/clk-vr9.c | 78 ++++++++++++++++++++
- arch/mips/lantiq/xway/mach-fritz.c | 74 +++++++++++++++++++
- arch/mips/lantiq/xway/prom-vr9.c | 55 ++++++++++++++
- arch/mips/pci/Makefile | 2 +-
- 10 files changed, 237 insertions(+), 1 deletions(-)
- create mode 100644 arch/mips/lantiq/xway/clk-vr9.c
- create mode 100644 arch/mips/lantiq/xway/mach-fritz.c
- create mode 100644 arch/mips/lantiq/xway/prom-vr9.c
-
---- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
-+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
-@@ -21,6 +21,7 @@
- #define SOC_ID_ARX188 0x16C
- #define SOC_ID_ARX168 0x16D
- #define SOC_ID_ARX182 0x16F
-+#define SOC_ID_VRX288 0x1C0
-
- /* SoC Types */
- #define SOC_TYPE_DANUBE 0x01
-@@ -91,6 +92,7 @@
-
- /* ETOP - ethernet */
- #define LTQ_ETOP_BASE_ADDR 0x1E180000
-+#define LTQ_ETOP_BASE_ADDR_VR9 0x1E200000
- #define LTQ_ETOP_SIZE 0x40000
-
- /* GBIT - gigabit switch */
---- a/arch/mips/lantiq/Kconfig
-+++ b/arch/mips/lantiq/Kconfig
-@@ -1,5 +1,8 @@
- if LANTIQ
-
-+config LANTIQ_PCIE
-+ bool
-+
- config SOC_TYPE_XWAY
- bool
- default n
-@@ -17,6 +20,12 @@ config SOC_XWAY
- select SOC_TYPE_XWAY
- select HW_HAS_PCI
-
-+config SOC_VR9
-+ bool "VR9"
-+ select SOC_TYPE_XWAY
-+ select HW_HAS_PCI
-+ select LANTIQ_PCIE
-+
- config SOC_FALCON
- bool "FALCON"
- endchoice
---- a/arch/mips/lantiq/Platform
-+++ b/arch/mips/lantiq/Platform
-@@ -6,4 +6,5 @@ platform-$(CONFIG_LANTIQ) += lantiq/
- cflags-$(CONFIG_LANTIQ) += -I$(srctree)/arch/mips/include/asm/mach-lantiq
- load-$(CONFIG_LANTIQ) = 0xffffffff80002000
- cflags-$(CONFIG_SOC_TYPE_XWAY) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway
-+cflags-$(CONFIG_SOC_TYPE_VR9) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway
- cflags-$(CONFIG_SOC_FALCON) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon
---- a/arch/mips/lantiq/machtypes.h
-+++ b/arch/mips/lantiq/machtypes.h
-@@ -20,6 +20,9 @@ enum lantiq_mach_type {
- LANTIQ_MACH_EASY98000, /* Falcon Eval Board, NOR Flash */
- LANTIQ_MACH_EASY98000SF, /* Falcon Eval Board, Serial Flash */
- LANTIQ_MACH_EASY98000NAND, /* Falcon Eval Board, NAND Flash */
-+
-+ /* FRITZ!BOX */
-+ LANTIQ_MACH_FRITZ3370, /* FRITZ!BOX 3370 vdsl cpe */
- };
-
- #endif
---- a/arch/mips/lantiq/xway/Kconfig
-+++ b/arch/mips/lantiq/xway/Kconfig
-@@ -21,3 +21,15 @@ config LANTIQ_MACH_EASY50601
- endmenu
-
- endif
-+
-+if SOC_VR9
-+
-+menu "MIPS Machine"
-+
-+config LANTIQ_MACH_FRITZ3370
-+ bool "Fritz!Box 3370"
-+ default y
-+
-+endmenu
-+
-+endif
---- a/arch/mips/lantiq/xway/Makefile
-+++ b/arch/mips/lantiq/xway/Makefile
-@@ -2,6 +2,8 @@ obj-y := sysctrl.o reset.o gpio.o gpio_s
-
- obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
- obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
-+obj-$(CONFIG_SOC_VR9) += clk-vr9.o prom-vr9.o
-
- obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
- obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
-+obj-$(CONFIG_LANTIQ_MACH_FRITZ3370) += mach-fritz.o
---- /dev/null
-+++ b/arch/mips/lantiq/xway/clk-vr9.c
-@@ -0,0 +1,78 @@
-+/*
-+ * 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.
-+ *
-+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/init.h>
-+#include <linux/clk.h>
-+
-+#include <asm/time.h>
-+#include <asm/irq.h>
-+#include <asm/div64.h>
-+
-+#include <lantiq_soc.h>
-+
-+#define CLOCK_62_5M 62500000
-+#define CLOCK_83_5M 83500000
-+#define CLOCK_125M 125000000
-+#define CLOCK_200M 200000000
-+#define CLOCK_250M 250000000
-+#define CLOCK_300M 300000000
-+#define CLOCK_98_304M 98304000
-+#define CLOCK_150M 150000000
-+#define CLOCK_196_608M 196608000
-+#define CLOCK_600M 600000000
-+#define CLOCK_500M 500000000
-+#define CLOCK_393M 393215332
-+#define CLOCK_166M 166666666
-+
-+#define LTQ_CGU_SYS 0x0c
-+#define LTQ_CGU_IF_CLK 0x24
-+
-+unsigned int ltq_get_cpu_hz(void)
-+{
-+ int clks[] = {
-+ CLOCK_600M, CLOCK_500M, CLOCK_393M, CLOCK_333M, CLOCK_125M,
-+ CLOCK_125M, CLOCK_196_608M, CLOCK_166M, CLOCK_125M, CLOCK_125M };
-+ int val = (ltq_cgu_r32(LTQ_CGU_SYS) >> 4) & 0xf;
-+
-+ if (val > 9)
-+ panic("bad cpu speed\n");
-+ if (val == 2)
-+ panic("missing workaround\n");
-+ //cgu_get_pll1_fosc(); //CLOCK_393M;
-+ return clks[val];
-+}
-+EXPORT_SYMBOL(ltq_get_cpu_hz);
-+
-+unsigned int ltq_get_fpi_hz(void)
-+{
-+ int clks[] = {
-+ CLOCK_62_5M, CLOCK_62_5M, CLOCK_83_5M, CLOCK_125M, CLOCK_125M,
-+ CLOCK_125M, CLOCK_167M, CLOCK_200M, CLOCK_250M, CLOCK_300M,
-+ CLOCK_62_5M, CLOCK_98_304M, CLOCK_150M, CLOCK_196_608M };
-+ int val = ((ltq_cgu_r32(LTQ_CGU_IF_CLK) >> 25) & 0xf);
-+
-+ if (val > 13)
-+ panic("bad fpi speed\n");
-+
-+ return clks[val];
-+}
-+EXPORT_SYMBOL(ltq_get_fpi_hz);
-+
-+unsigned int ltq_get_io_region_clock(void)
-+{
-+ return ltq_get_fpi_hz() / 2;
-+}
-+EXPORT_SYMBOL(ltq_get_io_region_clock);
-+
-+unsigned int ltq_get_fpi_bus_clock(int fpi)
-+{
-+ return ltq_get_fpi_hz();
-+}
-+EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
---- /dev/null
-+++ b/arch/mips/lantiq/xway/prom-vr9.c
-@@ -0,0 +1,55 @@
-+/*
-+ * 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.
-+ *
-+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
-+ */
-+
-+#include <linux/module.h>
-+#include <linux/clk.h>
-+#include <asm/bootinfo.h>
-+#include <asm/time.h>
-+
-+#include <lantiq_soc.h>
-+
-+#include "devices.h"
-+#include "../prom.h"
-+
-+#define SOC_VRX288 "VRX288"
-+
-+#define PART_SHIFT 12
-+#define PART_MASK 0x0FFFFFFF
-+#define REV_SHIFT 28
-+#define REV_MASK 0xF0000000
-+
-+void __init ltq_soc_detect(struct ltq_soc_info *i)
-+{
-+ i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
-+ i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
-+ sprintf(i->rev_type, "1.%d", i->rev);
-+ switch (i->partnum) {
-+ case SOC_ID_VRX288:
-+ i->name = SOC_VRX288;
-+ i->type = SOC_TYPE_VR9;
-+ break;
-+
-+ default:
-+ unreachable();
-+ break;
-+ }
-+ printk("%08X\n", i->partnum);
-+}
-+
-+void __init ltq_soc_setup(void)
-+{
-+ /*
-+ reg = IFX_REG_R32(IFX_XBAR_ALWAYS_LAST);
-+ reg &= ~ IFX_XBAR_FPI_BURST_EN;
-+ IFX_REG_W32(reg, IFX_XBAR_ALWAYS_LAST);
-+ */
-+
-+ ltq_register_asc(1);
-+ ltq_register_gpio();
-+ ltq_register_wdt();
-+}
---- a/arch/mips/pci/Makefile
-+++ b/arch/mips/pci/Makefile
-@@ -41,7 +41,7 @@ obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1
- obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o
- obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o
- obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o
--obj-$(CONFIG_SOC_XWAY) += pci-lantiq.o ops-lantiq.o
-+obj-$(CONFIG_LANTIQ) += pci-lantiq.o ops-lantiq.o
- obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
- obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
- obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
diff --git a/target/linux/lantiq/patches/201-owrt-mtd_uimage_split.patch b/target/linux/lantiq/patches/201-owrt-mtd_uimage_split.patch
deleted file mode 100644
index 6c6a45a..0000000
--- a/target/linux/lantiq/patches/201-owrt-mtd_uimage_split.patch
+++ /dev/null
@@ -1,116 +0,0 @@
---- a/drivers/mtd/Kconfig
-+++ b/drivers/mtd/Kconfig
-@@ -41,6 +41,10 @@ config MTD_ROOTFS_SPLIT
- bool "Automatically split 'rootfs' partition for squashfs"
- default y
-
-+config MTD_UIMAGE_SPLIT
-+ bool "Automatically split 'linux' partition into 'kernel' and 'rootfs'"
-+ default y
-+
- config MTD_REDBOOT_PARTS
- tristate "RedBoot partition table parsing"
- ---help---
---- a/drivers/mtd/mtdpart.c
-+++ b/drivers/mtd/mtdpart.c
-@@ -861,6 +861,82 @@ static int refresh_rootfs_split(struct m
- }
- #endif /* CONFIG_MTD_ROOTFS_SPLIT */
-
-+
-+#ifdef CONFIG_MTD_UIMAGE_SPLIT
-+static unsigned long find_uimage_size(struct mtd_info *mtd,
-+ unsigned long offset)
-+{
-+#define UBOOT_MAGIC 0x56190527
-+ unsigned long magic = 0;
-+ unsigned long temp;
-+ size_t len;
-+ int ret;
-+
-+ ret = mtd->read(mtd, offset, 4, &len, (void *)&magic);
-+ if (ret || len != sizeof(magic))
-+ return 0;
-+
-+ if (le32_to_cpu(magic) != UBOOT_MAGIC)
-+ return 0;
-+
-+ ret = mtd->read(mtd, offset + 12, 4, &len, (void *)&temp);
-+ if (ret || len != sizeof(temp))
-+ return 0;
-+
-+ return temp + 0x40;
-+}
-+
-+static int detect_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
-+{
-+ unsigned long temp;
-+ size_t len;
-+ int ret;
-+
-+ ret = mtd->read(mtd, offset, 4, &len, (void *)&temp);
-+ if (ret || len != sizeof(temp))
-+ return 0;
-+
-+ return le32_to_cpu(temp) == SQUASHFS_MAGIC;
-+}
-+
-+static int split_uimage(struct mtd_info *mtd,
-+ const struct mtd_partition *part)
-+{
-+ static struct mtd_partition split_partitions[] = {
-+ {
-+ .name = "kernel",
-+ .offset = 0x0,
-+ .size = 0x0,
-+ }, {
-+ .name = "rootfs",
-+ .offset = 0x0,
-+ .size = 0x0,
-+ },
-+ };
-+
-+ split_partitions[0].size = find_uimage_size(mtd, part->offset);
-+ if (!split_partitions[0].size) {
-+ printk(KERN_NOTICE "no uImage found in linux partition\n");
-+ return -1;
-+ }
-+
-+ if (!detect_squashfs_partition(mtd,
-+ part->offset
-+ + split_partitions[0].size)) {
-+ split_partitions[0].size &= ~(mtd->erasesize - 1);
-+ split_partitions[0].size += mtd->erasesize;
-+ }
-+
-+ split_partitions[0].offset = part->offset;
-+ split_partitions[1].offset = part->offset + split_partitions[0].size;
-+ split_partitions[1].size = part->size - split_partitions[0].size;
-+
-+ add_mtd_partitions(mtd, split_partitions, 2);
-+
-+ return 0;
-+}
-+#endif
-+
- /*
- * This function, given a master MTD object and a partition table, creates
- * and registers slave MTD objects which are bound to the master according to
-@@ -894,6 +970,17 @@ int add_mtd_partitions(struct mtd_info *
-
- add_mtd_device(&slave->mtd);
-
-+#ifdef CONFIG_MTD_UIMAGE_SPLIT
-+ if (!strcmp(parts[i].name, "linux")) {
-+ ret = split_uimage(master, &parts[i]);
-+
-+ if (ret) {
-+ printk(KERN_WARNING
-+ "Can't split linux partition\n");
-+ }
-+ }
-+#endif
-+
- if (!strcmp(parts[i].name, "rootfs")) {
- #ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
- if (ROOT_DEV == 0) {
diff --git a/target/linux/lantiq/patches/206-owrt-brnboot.patch b/target/linux/lantiq/patches/206-owrt-brnboot.patch
deleted file mode 100644
index d10d66b..0000000
--- a/target/linux/lantiq/patches/206-owrt-brnboot.patch
+++ /dev/null
@@ -1,93 +0,0 @@
-Index: linux-3.1.10/drivers/mtd/mtdpart.c
-===================================================================
---- linux-3.1.10.orig/drivers/mtd/mtdpart.c 2012-02-14 19:38:40.102266817 +0100
-+++ linux-3.1.10/drivers/mtd/mtdpart.c 2012-02-14 19:38:40.146266819 +0100
-@@ -899,6 +899,38 @@
- return le32_to_cpu(temp) == SQUASHFS_MAGIC;
- }
-
-+static unsigned long find_brnimage_size(struct mtd_info *mtd,
-+ unsigned long offset)
-+{
-+ unsigned long buf[4];
-+ // Assume at most 2MB of kernel image
-+ unsigned long end = offset + (2 << 20);
-+ unsigned long ptr = offset + 0x400 - 12;
-+ size_t len;
-+ int ret;
-+
-+ while (ptr < end) {
-+ long size_min = ptr - 0x400 - 12 - offset;
-+ long size_max = ptr + 12 - offset;
-+ ret = mtd->read(mtd, ptr, 16, &len, (void *)buf);
-+ if (ret || len != 16)
-+ return 0;
-+
-+ if (le32_to_cpu(buf[0]) < size_min ||
-+ le32_to_cpu(buf[0]) > size_max) {
-+ ptr += 0x400;
-+ continue;
-+ }
-+
-+ if (le32_to_cpu(buf[3]) == SQUASHFS_MAGIC)
-+ return ptr + 12 - offset;
-+
-+ ptr += 0x400;
-+ }
-+
-+ return 0;
-+}
-+
- static int split_uimage(struct mtd_info *mtd,
- const struct mtd_partition *part)
- {
-@@ -916,8 +948,11 @@
-
- split_partitions[0].size = find_uimage_size(mtd, part->offset);
- if (!split_partitions[0].size) {
-- printk(KERN_NOTICE "no uImage found in linux partition\n");
-- return -1;
-+ split_partitions[0].size = find_brnimage_size(mtd, part->offset);
-+ if (!split_partitions[0].size) {
-+ printk(KERN_NOTICE "no uImage or brnImage found in linux partition\n");
-+ return -1;
-+ }
- }
-
- if (!detect_squashfs_partition(mtd,
-Index: linux-3.1.10/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
-===================================================================
---- linux-3.1.10.orig/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h 2012-02-14 19:38:40.058266816 +0100
-+++ linux-3.1.10/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h 2012-02-14 19:57:07.790314179 +0100
-@@ -149,6 +149,7 @@
-
- extern __iomem void *ltq_ebu_membase;
- extern __iomem void *ltq_cgu_membase;
-+extern unsigned long ltq_brn_boot;
-
- /* request a non-gpio and set the PIO config */
- extern int ltq_gpio_request(unsigned int pin, unsigned int alt0,
-Index: linux-3.1.10/arch/mips/lantiq/setup.c
-===================================================================
---- linux-3.1.10.orig/arch/mips/lantiq/setup.c 2012-02-14 19:38:40.010266814 +0100
-+++ linux-3.1.10/arch/mips/lantiq/setup.c 2012-02-14 19:38:40.150266820 +0100
-@@ -20,6 +20,8 @@
-
- /* assume 16M as default incase uboot fails to pass proper ramsize */
- unsigned long physical_memsize = 16L;
-+/* set to 1 if the bootloader is BRN-BOOT instead of u-boot */
-+unsigned long ltq_brn_boot = 0;
-
- void __init plat_mem_setup(void)
- {
-@@ -39,6 +41,10 @@
- if (strict_strtoul(e, 0, &physical_memsize))
- pr_warn("bad memsize specified\n");
- }
-+ if (!strncmp(e, "BRN-BOOT", 8)){
-+ pr_info("Found BRN-BOOT instead of u-boot\n");
-+ ltq_brn_boot = 1;
-+ }
- envp++;
- }
- physical_memsize *= 1024 * 1024;
diff --git a/target/linux/lantiq/patches/800-fix-etop.patch b/target/linux/lantiq/patches/800-fix-etop.patch
deleted file mode 100644
index 462a2c3..0000000
--- a/target/linux/lantiq/patches/800-fix-etop.patch
+++ /dev/null
@@ -1,67 +0,0 @@
---- a/drivers/net/lantiq_etop.c
-+++ b/drivers/net/lantiq_etop.c
-@@ -397,7 +397,10 @@ ltq_etop_get_settings(struct net_device
- {
- struct ltq_etop_priv *priv = netdev_priv(dev);
-
-- return phy_ethtool_gset(priv->phydev, cmd);
-+ if (priv->phydev)
-+ return phy_ethtool_gset(priv->phydev, cmd);
-+ else
-+ return 0;
- }
-
- static int
-@@ -405,7 +408,10 @@ ltq_etop_set_settings(struct net_device
- {
- struct ltq_etop_priv *priv = netdev_priv(dev);
-
-- return phy_ethtool_sset(priv->phydev, cmd);
-+ if (priv->phydev)
-+ return phy_ethtool_sset(priv->phydev, cmd);
-+ else
-+ return 0;
- }
-
- static int
-@@ -413,7 +419,10 @@ ltq_etop_nway_reset(struct net_device *d
- {
- struct ltq_etop_priv *priv = netdev_priv(dev);
-
-- return phy_start_aneg(priv->phydev);
-+ if (priv->phydev)
-+ return phy_start_aneg(priv->phydev);
-+ else
-+ return 0;
- }
-
- static const struct ethtool_ops ltq_etop_ethtool_ops = {
-@@ -615,7 +624,8 @@ ltq_etop_open(struct net_device *dev)
- ltq_dma_open(&ch->dma);
- napi_enable(&ch->napi);
- }
-- phy_start(priv->phydev);
-+ if (priv->phydev)
-+ phy_start(priv->phydev);
- netif_tx_start_all_queues(dev);
- return 0;
- }
-@@ -627,7 +637,8 @@ ltq_etop_stop(struct net_device *dev)
- int i;
-
- netif_tx_stop_all_queues(dev);
-- phy_stop(priv->phydev);
-+ if (priv->phydev)
-+ phy_stop(priv->phydev);
- for (i = 0; i < MAX_DMA_CHAN; i++) {
- struct ltq_etop_chan *ch = &priv->ch[i];
-
-@@ -775,7 +786,7 @@ ltq_etop_init(struct net_device *dev)
- ltq_etop_set_multicast_list(dev);
- err = ltq_etop_mdio_init(dev);
- if (err)
-- goto err_netdev;
-+ pr_warn("etop: mdio probe failed\n");;
- return 0;
-
- err_netdev:
diff --git a/target/linux/lantiq/patches/820-fix-falcon-ltq_gpio_request.patch b/target/linux/lantiq/patches/820-fix-falcon-ltq_gpio_request.patch
deleted file mode 100644
index b3fdf33..0000000
--- a/target/linux/lantiq/patches/820-fix-falcon-ltq_gpio_request.patch
+++ /dev/null
@@ -1,53 +0,0 @@
---- a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
-+++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
-@@ -129,8 +129,8 @@ extern __iomem void *ltq_sys1_membase;
- ltq_sys1_w32((ltq_sys1_r32(reg) & ~(clear)) | (set), reg)
-
- /* gpio_request wrapper to help configure the pin */
--extern int ltq_gpio_request(unsigned int pin, unsigned int val,
-- unsigned int dir, const char *name);
-+extern int ltq_gpio_request(unsigned int pin, unsigned int alt0,
-+ unsigned int alt1, unsigned int dir, const char *name);
- extern int ltq_gpio_mux_set(unsigned int pin, unsigned int mux);
-
- /* to keep the irq code generic we need to define these to 0 as falcon
---- a/arch/mips/lantiq/falcon/gpio.c
-+++ b/arch/mips/lantiq/falcon/gpio.c
-@@ -96,11 +96,12 @@ int ltq_gpio_mux_set(unsigned int pin, u
- }
- EXPORT_SYMBOL(ltq_gpio_mux_set);
-
--int ltq_gpio_request(unsigned int pin, unsigned int val,
-- unsigned int dir, const char *name)
-+int ltq_gpio_request(unsigned int pin, unsigned int alt0,
-+ unsigned int alt1, unsigned int dir, const char *name)
- {
- int port = pin / 100;
- int offset = pin % 100;
-+ unsigned int mux = (!!alt0) & ((!!alt1) << 1);
-
- if (offset >= PINS_PER_PORT || port >= MAX_PORTS)
- return -EINVAL;
-@@ -115,7 +116,7 @@ int ltq_gpio_request(unsigned int pin, u
- else
- gpio_direction_input(pin);
-
-- return ltq_gpio_mux_set(pin, val);
-+ return ltq_gpio_mux_set(pin, mux);
- }
- EXPORT_SYMBOL(ltq_gpio_request);
-
---- a/arch/mips/lantiq/falcon/prom.c
-+++ b/arch/mips/lantiq/falcon/prom.c
-@@ -43,9 +43,9 @@ ltq_soc_setup(void)
- falcon_register_gpio();
- if (register_asc1) {
- ltq_register_asc(1);
-- if (ltq_gpio_request(MUXC_SIF_RX_PIN, 3, 0, "asc1-rx"))
-+ if (ltq_gpio_request(MUXC_SIF_RX_PIN, 1, 1, 0, "asc1-rx"))
- pr_err("failed to request asc1-rx");
-- if (ltq_gpio_request(MUXC_SIF_TX_PIN, 3, 1, "asc1-tx"))
-+ if (ltq_gpio_request(MUXC_SIF_TX_PIN, 1, 1, 1, "asc1-tx"))
- pr_err("failed to request asc1-tx");
- ltq_sysctl_activate(SYSCTL_SYS1, ACTS_ASC1_ACT);
- }
diff --git a/target/linux/lantiq/patches/830-fix-falcon-i2c-resources.patch b/target/linux/lantiq/patches/830-fix-falcon-i2c-resources.patch
deleted file mode 100644
index ad0a11a..0000000
--- a/target/linux/lantiq/patches/830-fix-falcon-i2c-resources.patch
+++ /dev/null
@@ -1,17 +0,0 @@
---- a/arch/mips/lantiq/falcon/devices.c
-+++ b/arch/mips/lantiq/falcon/devices.c
-@@ -130,10 +130,10 @@ falcon_register_gpio_extra(void)
- /* i2c */
- static struct resource falcon_i2c_resources[] = {
- MEM_RES("i2c", LTQ_I2C_BASE_ADDR, LTQ_I2C_SIZE),
-- IRQ_RES("i2c_lb", FALCON_IRQ_I2C_LBREQ),
-- IRQ_RES("i2c_b", FALCON_IRQ_I2C_BREQ),
-- IRQ_RES("i2c_err", FALCON_IRQ_I2C_I2C_ERR),
-- IRQ_RES("i2c_p", FALCON_IRQ_I2C_I2C_P),
-+ IRQ_RES(i2c_lb, FALCON_IRQ_I2C_LBREQ),
-+ IRQ_RES(i2c_b, FALCON_IRQ_I2C_BREQ),
-+ IRQ_RES(i2c_err, FALCON_IRQ_I2C_I2C_ERR),
-+ IRQ_RES(i2c_p, FALCON_IRQ_I2C_I2C_P),
- };
-
- void __init falcon_register_i2c(void)
diff --git a/target/linux/lantiq/patches/840-fix-falcon-sysctrl.patch b/target/linux/lantiq/patches/840-fix-falcon-sysctrl.patch
deleted file mode 100644
index 1a9b6fc..0000000
--- a/target/linux/lantiq/patches/840-fix-falcon-sysctrl.patch
+++ /dev/null
@@ -1,61 +0,0 @@
---- a/arch/mips/lantiq/falcon/sysctrl.c
-+++ b/arch/mips/lantiq/falcon/sysctrl.c
-@@ -63,11 +63,11 @@ void __iomem *ltq_ebu_membase;
- #define ltq_status_r32(x) ltq_r32(ltq_status_membase + (x))
-
- static inline void
--ltq_sysctl_wait(int module, unsigned int mask, unsigned int test)
-+ltq_sysctl_wait(int module, unsigned int mask, unsigned int test, unsigned int reg)
- {
- int err = 1000000;
-
-- do {} while (--err && ((ltq_reg_r32(module, LTQ_SYSCTL_ACTS)
-+ do {} while (--err && ((ltq_reg_r32(module, reg)
- & mask) != test));
- if (!err)
- pr_err("module de/activation failed %d %08X %08X\n",
-@@ -82,7 +82,7 @@ ltq_sysctl_activate(int module, unsigned
-
- ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKEN);
- ltq_reg_w32(module, mask, LTQ_SYSCTL_ACT);
-- ltq_sysctl_wait(module, mask, mask);
-+ ltq_sysctl_wait(module, mask, mask, LTQ_SYSCTL_ACTS);
- }
- EXPORT_SYMBOL(ltq_sysctl_activate);
-
-@@ -94,7 +94,7 @@ ltq_sysctl_deactivate(int module, unsign
-
- ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKCLR);
- ltq_reg_w32(module, mask, LTQ_SYSCTL_DEACT);
-- ltq_sysctl_wait(module, mask, 0);
-+ ltq_sysctl_wait(module, mask, 0, LTQ_SYSCTL_ACTS);
- }
- EXPORT_SYMBOL(ltq_sysctl_deactivate);
-
-@@ -105,7 +105,7 @@ ltq_sysctl_clken(int module, unsigned in
- return;
-
- ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKEN);
-- ltq_sysctl_wait(module, mask, mask);
-+ ltq_sysctl_wait(module, mask, mask, LTQ_SYSCTL_CLKS);
- }
- EXPORT_SYMBOL(ltq_sysctl_clken);
-
-@@ -116,7 +116,7 @@ ltq_sysctl_clkdis(int module, unsigned i
- return;
-
- ltq_reg_w32(module, mask, LTQ_SYSCTL_CLKCLR);
-- ltq_sysctl_wait(module, mask, 0);
-+ ltq_sysctl_wait(module, mask, 0, LTQ_SYSCTL_CLKS);
- }
- EXPORT_SYMBOL(ltq_sysctl_clkdis);
-
-@@ -132,7 +132,7 @@ ltq_sysctl_reboot(int module, unsigned i
- if ((~act & mask) != 0)
- ltq_sysctl_activate(module, ~act & mask);
- ltq_reg_w32(module, act & mask, LTQ_SYSCTL_RBT);
-- ltq_sysctl_wait(module, mask, mask);
-+ ltq_sysctl_wait(module, mask, mask, LTQ_SYSCTL_ACTS);
- }
- EXPORT_SYMBOL(ltq_sysctl_reboot);
-
diff --git a/target/linux/lantiq/patches/850-etop_irq.patch b/target/linux/lantiq/patches/850-etop_irq.patch
deleted file mode 100644
index bc868f8..0000000
--- a/target/linux/lantiq/patches/850-etop_irq.patch
+++ /dev/null
@@ -1,70 +0,0 @@
-Index: linux-3.1.10/drivers/net/lantiq_etop.c
-===================================================================
---- linux-3.1.10.orig/drivers/net/lantiq_etop.c 2012-02-23 09:06:47.274557678 +0100
-+++ linux-3.1.10/drivers/net/lantiq_etop.c 2012-02-23 09:07:03.006558044 +0100
-@@ -203,8 +203,10 @@
- {
- struct ltq_etop_chan *ch = container_of(napi,
- struct ltq_etop_chan, napi);
-+ struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
- int rx = 0;
- int complete = 0;
-+ unsigned long flags;
-
- while ((rx < budget) && !complete) {
- struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
-@@ -218,7 +220,9 @@
- }
- if (complete || !rx) {
- napi_complete(&ch->napi);
-+ spin_lock_irqsave(&priv->lock, flags);
- ltq_dma_ack_irq(&ch->dma);
-+ spin_unlock_irqrestore(&priv->lock, flags);
- }
- return rx;
- }
-@@ -248,7 +252,9 @@
- if (netif_tx_queue_stopped(txq))
- netif_tx_start_queue(txq);
- napi_complete(&ch->napi);
-+ spin_lock_irqsave(&priv->lock, flags);
- ltq_dma_ack_irq(&ch->dma);
-+ spin_unlock_irqrestore(&priv->lock, flags);
- return 1;
- }
-
-@@ -615,13 +621,16 @@
- {
- struct ltq_etop_priv *priv = netdev_priv(dev);
- int i;
-+ unsigned long flags;
-
- for (i = 0; i < MAX_DMA_CHAN; i++) {
- struct ltq_etop_chan *ch = &priv->ch[i];
-
- if (!IS_TX(i) && (!IS_RX(i)))
- continue;
-+ spin_lock_irqsave(&priv->lock, flags);
- ltq_dma_open(&ch->dma);
-+ spin_unlock_irqrestore(&priv->lock, flags);
- napi_enable(&ch->napi);
- }
- if (priv->phydev)
-@@ -635,6 +644,7 @@
- {
- struct ltq_etop_priv *priv = netdev_priv(dev);
- int i;
-+ unsigned long flags;
-
- netif_tx_stop_all_queues(dev);
- if (priv->phydev)
-@@ -645,7 +655,9 @@
- if (!IS_RX(i) && !IS_TX(i))
- continue;
- napi_disable(&ch->napi);
-+ spin_lock_irqsave(&priv->lock, flags);
- ltq_dma_close(&ch->dma);
-+ spin_unlock_irqrestore(&priv->lock, flags);
- }
- return 0;
- }
diff --git a/target/linux/lantiq/patches/860-falcon-fix-version.patch b/target/linux/lantiq/patches/860-falcon-fix-version.patch
deleted file mode 100644
index e934d2e..0000000
--- a/target/linux/lantiq/patches/860-falcon-fix-version.patch
+++ /dev/null
@@ -1,65 +0,0 @@
---- a/arch/mips/lantiq/falcon/prom.c
-+++ b/arch/mips/lantiq/falcon/prom.c
-@@ -14,6 +14,9 @@
- #include "../prom.h"
-
- #define SOC_FALCON "Falcon"
-+#define SOC_FALCON_D "Falcon-D"
-+#define SOC_FALCON_V "Falcon-V"
-+#define SOC_FALCON_M "Falcon-M"
-
- #define PART_SHIFT 12
- #define PART_MASK 0x0FFFF000
-@@ -21,6 +24,8 @@
- #define REV_MASK 0xF0000000
- #define SREV_SHIFT 22
- #define SREV_MASK 0x03C00000
-+#define TYPE_SHIFT 26
-+#define TYPE_MASK 0x3C000000
-
- #define MUXC_SIF_RX_PIN 112
- #define MUXC_SIF_TX_PIN 113
-@@ -54,14 +59,30 @@ ltq_soc_setup(void)
- void __init
- ltq_soc_detect(struct ltq_soc_info *i)
- {
-+ u32 type;
- i->partnum = (ltq_r32(LTQ_FALCON_CHIPID) & PART_MASK) >> PART_SHIFT;
- i->rev = (ltq_r32(LTQ_FALCON_CHIPID) & REV_MASK) >> REV_SHIFT;
-- i->srev = (ltq_r32(LTQ_FALCON_CHIPCONF) & SREV_MASK) >> SREV_SHIFT;
-+ i->srev = ((ltq_r32(LTQ_FALCON_CHIPCONF) & SREV_MASK) >> SREV_SHIFT);
- sprintf(i->rev_type, "%c%d%d", (i->srev & 0x4) ? ('B') : ('A'),
-- i->rev & 0x7, i->srev & 0x3);
-+ i->rev & 0x7, (i->srev & 0x3) + 1);
-+
- switch (i->partnum) {
- case SOC_ID_FALCON:
-- i->name = SOC_FALCON;
-+ type = (ltq_r32(LTQ_FALCON_CHIPTYPE) & TYPE_MASK) >> TYPE_SHIFT;
-+ switch (type) {
-+ case 0:
-+ i->name = SOC_FALCON_D;
-+ break;
-+ case 1:
-+ i->name = SOC_FALCON_V;
-+ break;
-+ case 2:
-+ i->name = SOC_FALCON_M;
-+ break;
-+ default:
-+ i->name = SOC_FALCON;
-+ break;
-+ }
- i->type = SOC_TYPE_FALCON;
- break;
-
---- a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
-+++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
-@@ -78,6 +78,7 @@
- #define LTQ_STATUS_BASE_ADDR 0x1E802000
-
- #define LTQ_FALCON_CHIPID ((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x0c))
-+#define LTQ_FALCON_CHIPTYPE ((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x38))
- #define LTQ_FALCON_CHIPCONF ((u32 *)(KSEG1 + LTQ_STATUS_BASE_ADDR + 0x40))
-
- /* SYSCTL - start/stop/restart/configure/... different parts of the Soc */
diff --git a/target/linux/lantiq/patches/999-mtd.patch b/target/linux/lantiq/patches/999-mtd.patch
deleted file mode 100644
index 713dd1f..0000000
--- a/target/linux/lantiq/patches/999-mtd.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/drivers/mtd/maps/lantiq-flash.c
-+++ b/drivers/mtd/maps/lantiq-flash.c
-@@ -20,6 +20,8 @@
- #include <linux/platform_device.h>
- #include <linux/mtd/physmap.h>
-
-+#include "../mtdcore.h"
-+
- #include <lantiq_soc.h>
- #include <lantiq_platform.h>
-
diff --git a/target/linux/lantiq/vr9/config-default b/target/linux/lantiq/vr9/config-default
index c2fc001..5fe73db 100644
--- a/target/linux/lantiq/vr9/config-default
+++ b/target/linux/lantiq/vr9/config-default
@@ -1,50 +1,54 @@
CONFIG_ADM6996_PHY=y
CONFIG_AR8216_PHY=y
-# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
-# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
-# CONFIG_ATH79 is not set
-CONFIG_GENERIC_ATOMIC64=y
-CONFIG_GENERIC_IRQ_SHOW=y
-CONFIG_HAVE_ARCH_JUMP_LABEL=y
-CONFIG_HAVE_C_RECORDMCOUNT=y
-CONFIG_HAVE_DMA_API_DEBUG=y
-CONFIG_HAVE_DMA_ATTRS=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
-CONFIG_HAVE_GENERIC_HARDIRQS=y
-CONFIG_HAVE_IRQ_WORK=y
-CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_ATMEL_PWM is not set
+CONFIG_BLK_DEV_SD=y
+CONFIG_CLKDEV_LOOKUP=y
+CONFIG_FSNOTIFY=y
+CONFIG_HAVE_MACH_CLKDEV=y
CONFIG_HW_HAS_PCI=y
CONFIG_INPUT=y
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_GPIO_BUTTONS is not set
CONFIG_INPUT_POLLDEV=y
+CONFIG_IRQ_FORCED_THREADING=y
# CONFIG_ISDN is not set
-CONFIG_LANTIQ_ETOP=y
-CONFIG_LANTIQ_MACH_FRITZ3370=y
-CONFIG_MACH_NO_WESTBRIDGE=y
-# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set
-CONFIG_NEED_DMA_MAP_STATE=y
-CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_LANTIQ_ETOP is not set
+# CONFIG_LANTIQ_MACH_ARV is not set
+# CONFIG_LANTIQ_MACH_EASY50712 is not set
+# CONFIG_LANTIQ_MACH_FRITZ_AR9 is not set
+CONFIG_LANTIQ_MACH_FRITZ_VR9=y
+# CONFIG_LANTIQ_MACH_GIGASX76X is not set
+# CONFIG_LANTIQ_MACH_NETGEAR is not set
+# CONFIG_LANTIQ_MACH_WBMR is not set
+CONFIG_LANTIQ_VRX200=y
+CONFIG_M25PXX_USE_FAST_READ=y
+CONFIG_MDIO_BOARDINFO=y
+# CONFIG_MLX4_CORE is not set
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ECC=y
+CONFIG_MTD_NAND_PLATFORM=y
+# CONFIG_MTD_SM_COMMON is not set
+CONFIG_NLS=y
CONFIG_PCI=y
+CONFIG_PCIEAER=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIE_LANTIQ=y
CONFIG_PCI_DOMAINS=y
-CONFIG_PERF_USE_VMALLOC=y
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_QUOTACTL is not set
+# CONFIG_PCI_LANTIQ is not set
+# CONFIG_PCI_LANTIQ_NONE is not set
CONFIG_RTL8306_PHY=y
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
# CONFIG_SOC_AMAZON_SE is not set
-CONFIG_SOC_VR9=y
# CONFIG_SOC_FALCON is not set
CONFIG_SOC_TYPE_XWAY=y
-# CONFIG_SOC_XWAY is not set
+CONFIG_SOC_XWAY=y
CONFIG_SPI=y
CONFIG_SPI_BITBANG=y
-# CONFIG_SPI_GPIO is not set
-CONFIG_SPI_LANTIQ=y
+CONFIG_SPI_GPIO=y
CONFIG_SPI_MASTER=y
+# CONFIG_SPI_XWAY is not set
+CONFIG_USB_ARCH_HAS_XHCI=y
CONFIG_USB_SUPPORT=y
-CONFIG_XZ_DEC=y
-CONFIG_SPI_XWAY=y
diff --git a/target/linux/lantiq/vr9/profiles/001-avm.mk b/target/linux/lantiq/vr9/profiles/001-avm.mk
new file mode 100644
index 0000000..30de76a
--- /dev/null
+++ b/target/linux/lantiq/vr9/profiles/001-avm.mk
@@ -0,0 +1,6 @@
+define Profile/FRITZ3370
+ NAME:=FRITZ3370 - Ftizbox
+ PACKAGES:=kmod-leds-gpio button-hotplug kmod-usb-ifxhcd
+endef
+
+$(eval $(call Profile,FRITZ3370))