Browse Source

* backport 2.6.8 patches to .39 / .32.33
* remove lqtapi
* bump tapi/dsl to .39
* migrate to new ltq_ style api
* add amazon_se support

SVN-Revision: 27026

John Crispin 14 năm trước cách đây
mục cha
commit
6608f419d1
100 tập tin đã thay đổi với 9401 bổ sung4717 xóa
  1. 0 73
      package/lqtapi/Makefile
  2. 0 1
      package/lqtapi/src/Makefile
  3. 0 37
      package/lqtapi/src/include/linux/tapi/tapi-event.h
  4. 0 20
      package/lqtapi/src/include/linux/tapi/tapi-ioctl.h
  5. 0 231
      package/lqtapi/src/include/linux/tapi/tapi.h
  6. 0 8
      package/lqtapi/src/mps/Makefile
  7. 0 238
      package/lqtapi/src/mps/mps-core.c
  8. 0 102
      package/lqtapi/src/mps/mps-fifo.c
  9. 0 157
      package/lqtapi/src/mps/mps-irq.c
  10. 0 18
      package/lqtapi/src/mps/mps-irq.h
  11. 0 19
      package/lqtapi/src/mps/mps-msg.c
  12. 0 87
      package/lqtapi/src/mps/mps-msg.h
  13. 0 85
      package/lqtapi/src/mps/mps.h
  14. 0 129
      package/lqtapi/src/mps/vmmc-alm.c
  15. 0 42
      package/lqtapi/src/mps/vmmc-alm.h
  16. 0 98
      package/lqtapi/src/mps/vmmc-cmds.h
  17. 0 221
      package/lqtapi/src/mps/vmmc-coder.c
  18. 0 14
      package/lqtapi/src/mps/vmmc-coder.h
  19. 0 646
      package/lqtapi/src/mps/vmmc-core.c
  20. 0 52
      package/lqtapi/src/mps/vmmc-link.c
  21. 0 10
      package/lqtapi/src/mps/vmmc-link.h
  22. 0 130
      package/lqtapi/src/mps/vmmc-module.c
  23. 0 64
      package/lqtapi/src/mps/vmmc-module.h
  24. 0 48
      package/lqtapi/src/mps/vmmc-port.c
  25. 0 22
      package/lqtapi/src/mps/vmmc-port.h
  26. 0 19
      package/lqtapi/src/mps/vmmc-sig.h
  27. 0 69
      package/lqtapi/src/mps/vmmc-signal.c
  28. 0 73
      package/lqtapi/src/mps/vmmc-stream.c
  29. 0 10
      package/lqtapi/src/mps/vmmc-stream.h
  30. 0 90
      package/lqtapi/src/mps/vmmc.c
  31. 0 68
      package/lqtapi/src/mps/vmmc.h
  32. 0 7
      package/lqtapi/src/tapi/Makefile
  33. 0 193
      package/lqtapi/src/tapi/tapi-control.c
  34. 0 250
      package/lqtapi/src/tapi/tapi-core.c
  35. 0 99
      package/lqtapi/src/tapi/tapi-input.c
  36. 0 62
      package/lqtapi/src/tapi/tapi-nl.c
  37. 0 82
      package/lqtapi/src/tapi/tapi-port.c
  38. 0 201
      package/lqtapi/src/tapi/tapi-stream.c
  39. 0 107
      package/lqtapi/src/tapi/tapi-sysfs-port.c
  40. 2 2
      package/ltq-dsl/Makefile
  41. 23 14
      package/ltq-dsl/patches/500-portability.patch
  42. 6 3
      package/ltq-dsl/src/ifxmips_atm_core.c
  43. 1 2
      package/ltq-dsl/src/ifxmips_atm_danube.c
  44. 1 1
      package/ltq-dsl/src/ifxmips_atm_ppe_danube.h
  45. 1 1
      package/ltq-dsl/src/ifxmips_compat.h
  46. 96 82
      package/ltq-dsl/src/lantiq_mei.c
  47. 12 0
      package/ltq-ifxos/patches/120-linaro.patch
  48. 47 4
      package/ltq-tapi/patches/200-linux-37.patch
  49. 6 6
      package/ltq-vmmc/patches/100-ifxmips.patch
  50. 94 8
      package/ltq-vmmc/patches/200-kernel-37.patch
  51. 12 0
      target/linux/generic/patches-2.6.32/251-atm_header_changes.patch
  52. 12 0
      target/linux/generic/patches-2.6.39/652-atm_header_changes.patch
  53. 3 2
      target/linux/lantiq/Makefile
  54. 15 0
      target/linux/lantiq/ase/config-2.6.32
  55. 39 0
      target/linux/lantiq/ase/config-default
  56. 6 0
      target/linux/lantiq/ase/profiles/000-generic.mk
  57. 10 0
      target/linux/lantiq/ase/profiles/001-lantiq.mk
  58. 10 0
      target/linux/lantiq/ase/target.mk
  59. 2 2
      target/linux/lantiq/base-files/etc/inittab
  60. 149 0
      target/linux/lantiq/config-2.6.32
  61. 4 38
      target/linux/lantiq/config-default
  62. 0 9
      target/linux/lantiq/extract.py
  63. 0 44
      target/linux/lantiq/extract.sh
  64. 33 0
      target/linux/lantiq/falcon/config-2.6.32
  65. 39 7
      target/linux/lantiq/falcon/config-default
  66. 24 2
      target/linux/lantiq/image/Makefile
  67. 898 0
      target/linux/lantiq/patches-2.6.32/0001-MIPS-Lantiq-Add-initial-support-for-Lantiq-SoCs.patch
  68. 1151 0
      target/linux/lantiq/patches-2.6.32/0002-MIPS-Lantiq-add-SoC-specific-code-for-XWAY-family.patch
  69. 546 0
      target/linux/lantiq/patches-2.6.32/0003-MIPS-Lantiq-Add-PCI-controller-support.patch
  70. 301 0
      target/linux/lantiq/patches-2.6.32/0004-MIPS-Lantiq-Add-NOR-flash-support.patch
  71. 338 0
      target/linux/lantiq/patches-2.6.32/0005-MIPS-Lantiq-Add-platform-device-support.patch
  72. 170 0
      target/linux/lantiq/patches-2.6.32/0006-MIPS-Lantiq-Add-mips_machine-support.patch
  73. 230 0
      target/linux/lantiq/patches-2.6.32/0007-MIPS-Lantiq-Add-machtypes-for-lantiq-eval-kits.patch
  74. 330 0
      target/linux/lantiq/patches-2.6.32/0008-MIPS-Lantiq-Add-more-gpio-drivers.patch
  75. 261 256
      target/linux/lantiq/patches-2.6.32/0009-SERIAL-Lantiq-Add-driver-for-MIPS-Lantiq-SOCs.patch
  76. 387 0
      target/linux/lantiq/patches-2.6.32/0010-MIPS-Lantiq-Add-DMA-support.patch
  77. 943 0
      target/linux/lantiq/patches-2.6.32/0011-MIPS-Lantiq-Add-ethernet-driver.patch
  78. 50 0
      target/linux/lantiq/patches-2.6.32/0012-MIPS-Lantiq-Add-etop-board-support.patch
  79. 310 0
      target/linux/lantiq/patches-2.6.32/0013-MIPS-Lantiq-Add-watchdog-support.patch
  80. 0 12
      target/linux/lantiq/patches-2.6.32/100-falcon_header.patch
  81. 105 105
      target/linux/lantiq/patches-2.6.32/110-falcon_board.patch
  82. 4 3
      target/linux/lantiq/patches-2.6.32/120-falcon-i2c.patch
  83. 9 9
      target/linux/lantiq/patches-2.6.32/130-falcon-spi-flash.patch
  84. 4 4
      target/linux/lantiq/patches-2.6.32/140-falcon-easy98000-cpld-led.patch
  85. 5 5
      target/linux/lantiq/patches-2.6.32/150-falcon-easy98020.patch
  86. 15 15
      target/linux/lantiq/patches-2.6.32/160-falcon-95C3AM1.patch
  87. 130 161
      target/linux/lantiq/patches-2.6.32/200-mach-arv45xx.patch
  88. 3 3
      target/linux/lantiq/patches-2.6.32/210-mtd_uimage_split.patch
  89. 42 0
      target/linux/lantiq/patches-2.6.32/220-atm_hack.patch
  90. 45 0
      target/linux/lantiq/patches-2.6.32/230-cmdline_hack.patch
  91. 9 8
      target/linux/lantiq/patches-2.6.32/240-udp_redirect.patch
  92. 1174 0
      target/linux/lantiq/patches-2.6.32/250-mt-vpe.patch
  93. 5 5
      target/linux/lantiq/patches-2.6.32/260-ar9-cache-split.patch
  94. 8 0
      target/linux/lantiq/patches-2.6.32/270-m25p80-fast-read.patch
  95. 14 22
      target/linux/lantiq/patches-2.6.32/400-spi1.patch
  96. 1103 0
      target/linux/lantiq/patches-2.6.32/410-spi2.patch
  97. 49 0
      target/linux/lantiq/patches-2.6.32/420-spi3.patch
  98. 41 0
      target/linux/lantiq/patches-2.6.32/500-register_ebu.patch
  99. 28 0
      target/linux/lantiq/patches-2.6.32/510-register_madwifi.patch
  100. 46 0
      target/linux/lantiq/patches-2.6.32/520-register_buttons.patch

+ 0 - 73
package/lqtapi/Makefile

@@ -1,73 +0,0 @@
-# 
-# Copyright (C) 2006-2010 OpenWrt.org
-#
-# This is free software, licensed under the GNU General Public License v2.
-# See /LICENSE for more information.
-#
-
-include $(TOPDIR)/rules.mk
-include $(INCLUDE_DIR)/kernel.mk
-
-PKG_NAME:=lqtapi
-PKG_VERSION:=1
-PKG_RELEASE:=1
-
-FW_SOURCE:=danube_firmware.bin
-FW_URL:=http://www.arcor.de/hilfe/files/pdf/
-FW_FILE=arcor_A800_452CPW_FW_1.02.206(20081201).bin
-FW_MD5SUM:=19d9af4e369287a0f0abaed415cdac10
-
-include $(INCLUDE_DIR)/package.mk
-
-define Download/firmware
-  FILE:=$(FW_FILE)
-  URL:=$(FW_URL)
-  MD5SUM:=$(FW_MD5SUM)
-endef
-$(eval $(call Download,firmware))
-
-define KernelPackage/lqtapi
-  SUBMENU:=Voice over IP
-  TITLE:=Tapi drivers for Lantiq SoC
-  DEPENDS:=@TARGET_lantiq_xway @BROKEN
-  FILES:=$(PKG_BUILD_DIR)/tapi/tapi.ko \
-	$(PKG_BUILD_DIR)/mps/mps.ko \
-  	$(PKG_BUILD_DIR)/mps/vmmc.ko
-  AUTOLOAD:=$(call AutoLoad,80,tapi) \
-	$(call AutoLoad,81,mps)
-endef
-
-define Package/lqtapi-firmware-danube
-  SECTION:=sys
-  CATEGORY:=Kernel modules
-  SUBMENU:=Voice over IP
-  TITLE:=Danube firmware
-  DEPENDS:=+kmod-lqtapi
-endef
-
-include $(INCLUDE_DIR)/kernel-defaults.mk
-
-define KernelPackage/lqtapi/description
-	FOSS drivers for Lantiq SoC voip core
-endef
-
-define Build/Prepare
-	mkdir -p $(PKG_BUILD_DIR)
-	$(CP) src/* $(PKG_BUILD_DIR)/
-endef
-
-define Build/Compile
-	$(MAKE) $(KERNEL_MAKEOPTS) \
-		SUBDIRS="$(PKG_BUILD_DIR)" \
-		EXTRA_CFLAGS=-I$(PKG_BUILD_DIR)/include/ \
-		modules
-endef
-
-define Package/lqtapi-firmware-danube/install
-	$(TOPDIR)/target/linux/$(BOARD)/extract.sh $(DL_DIR) '$(FW_FILE)' 
-	$(INSTALL_DIR) $(1)/lib/firmware/
-	$(INSTALL_DATA) $(DL_DIR)/voip.bin $(1)/lib/firmware/$(FW_SOURCE)
-endef
-
-$(eval $(call KernelPackage,lqtapi))
-$(eval $(call BuildPackage,lqtapi-firmware-danube))

+ 0 - 1
package/lqtapi/src/Makefile

@@ -1 +0,0 @@
-obj-m = tapi/ mps/

+ 0 - 37
package/lqtapi/src/include/linux/tapi/tapi-event.h

@@ -1,37 +0,0 @@
-#ifndef __LINUX_TAPI_TAPI_EVENT_H__
-#define __LINUX_TAPI_TAPI_EVENT_H__
-
-
-struct tapi_device;
-struct tapi_port;
-
-struct tapi_hook_event {
-	bool on;
-};
-
-struct tapi_dtmf_event {
-	unsigned char code;
-};
-
-enum tapi_event_type {
-	TAPI_EVENT_TYPE_HOOK,
-	TAPI_EVENT_TYPE_DTMF,
-};
-
-struct tapi_event {
-	struct timeval time;
-	enum tapi_event_type type;
-	unsigned int port;
-	union {
-		struct tapi_hook_event hook;
-		struct tapi_dtmf_event dtmf;
-	};
-};
-
-void tapi_report_event(struct tapi_device *tdev, struct tapi_event *event);
-void tapi_report_hook_event(struct tapi_device *tdev, struct tapi_port *port,
-	bool on);
-void tapi_report_dtmf_event(struct tapi_device *tdev, struct tapi_port *port,
-	unsigned char code);
-
-#endif

+ 0 - 20
package/lqtapi/src/include/linux/tapi/tapi-ioctl.h

@@ -1,20 +0,0 @@
-
-#include <linux/ioctl.h>
-
-#define TAPI_MAGIC 't'
-#define TAPI_IOCTL(x) _IO(TAPI_MAGIC, (x))
-
-#define TAPI_CONTROL_IOCTL_LINK_ALLOC TAPI_IOCTL(0)
-#define TAPI_CONTROL_IOCTL_LINK_FREE  TAPI_IOCTL(1)
-#define TAPI_CONTROL_IOCTL_LINK_ENABLE TAPI_IOCTL(2)
-#define TAPI_CONTROL_IOCTL_LINK_DISABLE TAPI_IOCTL(3)
-
-#define TAPI_CONTROL_IOCTL_SYNC TAPI_IOCTL(4)
-
-#define TAPI_PORT_IOCTL_GET_ENDPOINT TAPI_IOCTL(5)
-#define TAPI_PORT_IOCTL_SET_RING TAPI_IOCTL(6)
-
-#define TAPI_STREAM_IOCTL_GET_ENDPOINT TAPI_IOCTL(7)
-#define TAPI_STREAM_IOCTL_CONFIGURE TAPI_IOCTL(8)
-#define TAPI_STREAM_IOCTL_START TAPI_IOCTL(9)
-#define TAPI_STREAM_IOCTL_STOP TAPI_IOCTL(10)

+ 0 - 231
package/lqtapi/src/include/linux/tapi/tapi.h

@@ -1,231 +0,0 @@
-#ifndef __LINUX_TAPI_H__
-#define __LINUX_TAPI_H__
-
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/mutex.h>
-
-#include <linux/input.h>
-
-#include <asm/atomic.h>
-#include <linux/list.h>
-
-#include <linux/cdev.h>
-
-#include <linux/skbuff.h>
-#include <linux/wait.h>
-
-#include <linux/tapi/tapi-event.h>
-
-struct tapi_device;
-
-struct tapi_char_device {
-	struct tapi_device *tdev;
-	struct device dev;
-	struct cdev cdev;
-};
-
-static inline struct tapi_char_device *cdev_to_tapi_char_device(struct cdev *cdev)
-{
-	return container_of(cdev, struct tapi_char_device, cdev);
-}
-
-int tapi_char_device_register(struct tapi_device *tdev,
-	struct tapi_char_device *tchrdev, const struct file_operations *fops);
-
-
-struct tapi_endpoint {
-	unsigned int id;
-	void *data;
-};
-
-static inline void tapi_endpoint_set_data(struct tapi_endpoint *ep, void *data)
-{
-	ep->data = data;
-}
-
-static inline void *tapi_endpoint_get_data(struct tapi_endpoint *ep)
-{
-	return ep->data;
-}
-
-struct tapi_port {
-	unsigned int id;
-	struct tapi_endpoint ep;
-	struct input_dev *input;
-	struct tapi_char_device chrdev;
-};
-
-struct tapi_stream {
-	unsigned int id;
-	struct list_head head;
-	struct tapi_endpoint ep;
-
-	struct sk_buff_head recv_queue;
-	wait_queue_head_t recv_wait;
-	struct sk_buff_head send_queue;
-};
-
-struct tapi_link {
-	unsigned int id;
-	struct list_head head;
-};
-
-enum tapi_codec {
-	TAPI_CODEC_L16,
-};
-
-struct tapi_stream_config {
-	enum tapi_codec codec;
-	unsigned int buffer_size;
-};
-
-struct tapi_ops {
-	int (*send_dtmf_events)(struct tapi_device *, struct tapi_port *port,
-		struct tapi_dtmf_event *, size_t num_events, unsigned int dealy);
-	int (*send_dtmf_event)(struct tapi_device *, struct tapi_port *port,
-		struct tapi_dtmf_event *);
-	int (*ring)(struct tapi_device *, struct tapi_port *port, bool ring);
-
-	struct tapi_stream *(*stream_alloc)(struct tapi_device *);
-	void (*stream_free)(struct tapi_device *, struct tapi_stream *);
-	int (*stream_configure)(struct tapi_device *, struct tapi_stream *,
-		struct tapi_stream_config *);
-	int (*stream_start)(struct tapi_device *, struct tapi_stream *);
-	int (*stream_stop)(struct tapi_device *, struct tapi_stream *);
-	int (*stream_send)(struct tapi_device *, struct tapi_stream *,
-		struct sk_buff *);
-
-	struct tapi_link *(*link_alloc)(struct tapi_device *,
-		struct tapi_endpoint *ep1, struct tapi_endpoint *ep2);
-	void (*link_free)(struct tapi_device *, struct tapi_link *);
-	int (*link_enable)(struct tapi_device *, struct tapi_link *);
-	int (*link_disable)(struct tapi_device *, struct tapi_link *);
-
-	int (*sync)(struct tapi_device *);
-};
-
-int tapi_stream_recv(struct tapi_device *, struct tapi_stream *, struct sk_buff *);
-
-struct tapi_device {
-	unsigned int id;
-
-	const struct tapi_ops *ops;
-	unsigned int num_ports;
-
-	struct device dev;
-
-	struct mutex lock;
-
-	struct tapi_port *ports;
-	struct list_head streams;
-	struct list_head links;
-	atomic_t stream_id;
-	atomic_t link_id;
-
-	struct tapi_char_device stream_dev;
-	struct tapi_char_device control_dev;
-};
-
-static inline struct tapi_device *dev_to_tapi(struct device *dev)
-{
-	return container_of(dev, struct tapi_device, dev);
-}
-
-static inline struct tapi_stream *tapi_stream_from_id(struct tapi_device *tdev,
-	unsigned int id)
-{
-	struct tapi_stream *stream;
-
-	mutex_lock(&tdev->lock);
-
-	list_for_each_entry(stream, &tdev->streams, head) {
-		if (stream->id == id)
-			goto out;
-	}
-	stream = NULL;
-
-out:
-	mutex_unlock(&tdev->lock);
-	return stream;
-}
-
-struct tapi_link *tapi_link_alloc(struct tapi_device *, struct tapi_endpoint *,
-	struct tapi_endpoint *);
-void tapi_link_free(struct tapi_device *, struct tapi_link *);
-
-struct tapi_stream *tapi_stream_alloc(struct tapi_device *tdev);
-void tapi_stream_free(struct tapi_device *tdev, struct tapi_stream *stream);
-
-static inline int tapi_sync(struct tapi_device *tdev)
-{
-	if (!tdev->ops || !tdev->ops->sync)
-		return 0;
-
-	return tdev->ops->sync(tdev);
-}
-
-static inline int tapi_link_enable(struct tapi_device *tdev,
-	struct tapi_link *link)
-{
-	if (!tdev->ops || !tdev->ops->link_enable)
-		return 0;
-
-	return tdev->ops->link_enable(tdev, link);
-}
-
-static inline int tapi_link_disable(struct tapi_device *tdev,
-	struct tapi_link *link)
-{
-	if (!tdev->ops || !tdev->ops->link_disable)
-		return 0;
-
-	return tdev->ops->link_disable(tdev, link);
-}
-
-static inline int tapi_port_send_dtmf(struct tapi_device *tdev,
-	struct tapi_port *port,	struct tapi_dtmf_event *dtmf)
-{
-	if (!tdev->ops || !tdev->ops->send_dtmf_event)
-		return -ENOSYS;
-
-	return tdev->ops->send_dtmf_event(tdev, port, dtmf);
-}
-
-static inline int tapi_port_set_ring(struct tapi_device *tdev,
-	struct tapi_port *port, bool ring)
-{
-	if (!tdev->ops || !tdev->ops->ring)
-		return -ENOSYS;
-
-	return tdev->ops->ring(tdev, port, ring);
-}
-
-static inline int tapi_stream_start(struct tapi_device *tdev,
-struct tapi_stream *stream)
-{
-	if (!tdev->ops || !tdev->ops->stream_start)
-		return -ENOSYS;
-
-	return tdev->ops->stream_start(tdev, stream);
-}
-
-static inline int tapi_stream_stop(struct tapi_device *tdev,
-struct tapi_stream *stream)
-{
-	if (!tdev->ops || !tdev->ops->stream_stop)
-		return -ENOSYS;
-
-	return tdev->ops->stream_stop(tdev, stream);
-}
-
-int tapi_device_register(struct tapi_device *tdev, const char *name,
-	struct device *parent);
-void tapi_device_unregister(struct tapi_device *tdev);
-
-struct tapi_sysfs_port;
-
-struct tapi_sysfs_port *tapi_port_alloc(struct tapi_device *tdev, unsigned int id);
-void tapi_port_delete(struct tapi_sysfs_port *);
-
-#endif

+ 0 - 8
package/lqtapi/src/mps/Makefile

@@ -1,8 +0,0 @@
-
-
-mps-objs := mps-core.o mps-irq.o mps-fifo.o
-obj-m += mps.o
-
-vmmc-objs := vmmc-core.o vmmc-alm.o vmmc-module.o vmmc-link.o vmmc-port.o \
-	vmmc-signal.o vmmc-stream.o vmmc-coder.o
-obj-m += vmmc.o

+ 0 - 238
package/lqtapi/src/mps/mps-core.c

@@ -1,238 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <ifxmips.h>
-#include <ifxmips_cgu.h>
-
-#include <ifxmips_prom.h>
-#include <ifxmips_irq.h>
-
-#include "mps.h"
-
-extern int mps_irq_init(struct mps *mps);
-extern void mps_irq_exit(struct mps *mps);
-
-#define MPS_CPU0_BOOT_RVEC	0x1c0
-#define MPS_CPU0_BOOT_NVEC	0x1c4
-#define MPS_CPU0_BOOT_EVEC	0x1c8
-#define MPS_CPU0_CP0_STATUS	0x1cc
-#define MPS_CPU0_CP0_EEPC	0x1d0
-#define MPS_CPU0_CP0_EPC	0x1d4
-#define MPS_CPU0_BOOT_SIZE	0x1d8
-#define MPS_CPU0_CFG_STAT	0x1dc
-#define MPS_CPU1_BOOT_RVEC	0x1e0
-#define MPS_CPU1_BOOT_NVEC	0x1e4
-#define MPS_CPU1_BOOT_EVEC	0x1e8
-#define MPS_CPU1_CP0_STATUS	0x1ec
-#define MPS_CPU1_CP0_EEPC	0x1f0
-#define MPS_CPU1_CP0_EPC	0x1f4
-#define MPS_CPU1_BOOT_SIZE	0x1f8
-#define MPS_CPU1_CFG_STAT	0x1fc
-
-static void mps_reset(void)
-{
-	ifxmips_w32(ifxmips_r32(IFXMIPS_RCU_RST) | IFXMIPS_RCU_RST_CPU1,
-		IFXMIPS_RCU_RST);
-	smp_wmb();
-}
-
-static void mps_release(void)
-{
-	uint32_t val;
-	val = ifxmips_r32(IFXMIPS_RCU_RST);
-	val |= 0x20000000;
-	val &= ~IFXMIPS_RCU_RST_CPU1;
-	ifxmips_w32(val, IFXMIPS_RCU_RST);
-	smp_wmb();
-}
-
-void mps_load_firmware(struct mps *mps, const void *data, size_t size,
-	enum mps_boot_config config)
-{
-	uint32_t cfg = 0;
-	uint32_t fw_size = size;
-
-	if (config == MPS_BOOT_LEGACY) {
-		cfg = 0x00020000;
-		fw_size -= sizeof(uint32_t);
-	} else {
-		if(config == MPS_BOOT_ENCRYPTED) {
-			cfg = __raw_readl(mps->mbox_base + MPS_CPU1_CFG_STAT);
-			cfg |= 0x00700000;
-		} else {
-			printk("PANIC!\n");
-		}
-	}
-
-	mps_reset();
-
-	memcpy_toio(mps->cp1_base, data, size);
-
-	__raw_writel(cfg, mps->mbox_base + MPS_CPU1_CFG_STAT);
-	__raw_writel(fw_size, mps->mbox_base + MPS_CPU1_BOOT_SIZE);
-	__raw_writel((uint32_t)mps->cp1_base, mps->mbox_base + MPS_CPU1_BOOT_RVEC);
-
-	mps_release();
-}
-EXPORT_SYMBOL_GPL(mps_load_firmware);
-
-void mps_configure_fifo(struct mps *mps, struct mps_fifo *fifo,
-	const struct mps_fifo_config *config)
-{
-	mps_fifo_init(fifo, mps->mbox_base + config->base,
-		mps->mbox_base + config->head_addr,
-		mps->mbox_base + config->tail_addr,
-		config->size);
-
-	__raw_writel(config->size, mps->mbox_base + config->size_addr);
-	__raw_writel(mps->mbox_res->start + config->base,
-		mps->mbox_base + config->base_addr);
-}
-EXPORT_SYMBOL_GPL(mps_configure_fifo);
-
-void mps_configure_mailbox(struct mps *mps, struct mps_mailbox *mbox,
-	const struct mps_fifo_config *upstream_config,
-	const struct mps_fifo_config *downstream_config)
-{
-	mps_configure_fifo(mps, &mbox->upstream, upstream_config);
-	mps_configure_fifo(mps, &mbox->downstream, downstream_config);
-}
-EXPORT_SYMBOL_GPL(mps_configure_mailbox);
-
-static int __devinit mps_probe(struct platform_device *pdev)
-{
-	int ret;
-	struct mps *mps;
-	struct resource *res;
-
-	mps = kzalloc(sizeof(*mps), GFP_KERNEL);
-
-	if (!mps)
-		return -ENOMEM;
-
-	mps->dev = &pdev->dev;
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem");
-	if (!res) {
-		dev_err(&pdev->dev, "Failed to get mem resource");
-		ret = -ENOENT;
-		goto err_free;
-	}
-
-	res = request_mem_region(res->start, resource_size(res),
-		dev_name(&pdev->dev));
-
-	if (!res) {
-		dev_err(&pdev->dev, "Failed to request mem resource");
-		ret = -EBUSY;
-		goto err_free;
-	}
-
-	mps->base = ioremap_nocache(res->start, resource_size(res));
-
-	if (!mps->base) {
-		dev_err(&pdev->dev, "Failed to ioremap mem region\n");
-		ret = -EBUSY;
-		goto err_release_mem_region;
-	}
-
-	mps->res = res;
-
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mailbox");
-	if (!res) {
-		dev_err(&pdev->dev, "Failed to get mailbox mem region\n");
-		ret = -ENOENT;
-		goto err_free;
-	}
-
-	res = request_mem_region(res->start, resource_size(res),
-		dev_name(&pdev->dev));
-
-	if (!res) {
-		dev_err(&pdev->dev, "Failed to request mailbox mem region\n");
-		ret = -EBUSY;
-		goto err_free;
-	}
-
-	mps->mbox_base = ioremap_nocache(res->start, resource_size(res));
-
-	if (!mps->mbox_base) {
-		dev_err(&pdev->dev, "Failed to ioremap mailbox mem region\n");
-		ret = -EBUSY;
-		goto err_release_mem_region;
-	}
-
-	mps->mbox_res = res;
-
-	mps->cp1_base = ioremap_nocache((unsigned int)pdev->dev.platform_data, 1 << 20);
-
-	if (!mps->cp1_base) {
-		dev_err(&pdev->dev, "Failed to ioremap cp1 address\n");
-		ret = -EBUSY;
-		goto err_release_mem_region;
-	}
-
-	mps->irq_ad0 = INT_NUM_IM4_IRL18;
-	mps->irq_ad1 = INT_NUM_IM4_IRL19;
-	mps->irq_base = 160;
-
-	ret = mps_irq_init(mps);
-	if (ret < 0)
-		goto err_iounmap;
-
-	platform_set_drvdata(pdev, mps);
-
-	return 0;
-
-err_iounmap:
-	iounmap(mps->mbox_base);
-err_release_mem_region:
-	release_mem_region(res->start, resource_size(res));
-err_free:
-	kfree(mps);
-
-	return ret;
-}
-
-static int __devexit mps_remove(struct platform_device *pdev)
-{
-	struct mps *mps = platform_get_drvdata(pdev);
-
-	mps_irq_exit(mps);
-
-	iounmap(mps->mbox_base);
-	release_mem_region(mps->mbox_res->start, resource_size(mps->mbox_res));
-	iounmap(mps->base);
-	release_mem_region(mps->res->start, resource_size(mps->res));
-
-	kfree(mps);
-	return 0;
-}
-
-static struct platform_driver mps_driver = {
-	.probe = mps_probe,
-	.remove = __devexit_p(mps_remove),
-	.driver = {
-		.name = "mps",
-		.owner = THIS_MODULE
-	},
-};
-
-static int __init mps_init(void)
-{
-	return platform_driver_register(&mps_driver);
-}
-module_init(mps_init);
-
-static void __exit mps_exit(void)
-{
-	platform_driver_unregister(&mps_driver);
-}
-module_exit(mps_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Lars-Peter Clausen <[email protected]>");

+ 0 - 102
package/lqtapi/src/mps/mps-fifo.c

@@ -1,102 +0,0 @@
-#include <linux/io.h>
-
-#include "mps.h"
-
-void mps_fifo_init(struct mps_fifo *fifo, void __iomem *base,
-	void __iomem *head_addr, void __iomem *tail_addr, uint32_t size)
-{
-	fifo->base = base;
-	fifo->head_addr = head_addr;
-	fifo->tail_addr = tail_addr;
-	fifo->size = size;
-	mps_fifo_reset(fifo);
-}
-
-void mps_fifo_in(struct mps_fifo *fifo, const uint32_t *from, size_t len)
-{
-	uint32_t head = __raw_readl(fifo->head_addr);
-	void __iomem *base = fifo->base + head;
-	size_t i = 0;
-	size_t byte_len = len * 4;
-
-	if (head < byte_len) {
-		for(; i <= head / 4; ++i) {
-			__raw_writel(from[i], base);
-			base -= 4;
-		}
-
-		base += fifo->size;
-		head += fifo->size;
-	}
-
-	for(; i < len; ++i) {
-		__raw_writel(from[i], base);
-		base -= 4;
-	}
-
-	head -= byte_len;
-	__raw_writel(head, fifo->head_addr);
-
-}
-EXPORT_SYMBOL_GPL(mps_fifo_in);
-
-void mps_fifo_out(struct mps_fifo *fifo, uint32_t *to, size_t len)
-{
-	uint32_t tail = __raw_readl(fifo->tail_addr);
-	void __iomem *base = fifo->base + tail;
-	size_t i = 0;
-	size_t byte_len = len * 4;
-
-	if (tail < byte_len) {
-		for(; i <= tail / 4; ++i) {
-			to[i] = __raw_readl(base);
-			base -= 4;
-		}
-
-		base += fifo->size;
-		tail += fifo->size;
-	}
-
-	for(; i < len; ++i) {
-		to[i] = __raw_readl(base);
-		base -= 4;
-	}
-
-	tail -= byte_len;
-	__raw_writel(tail, fifo->tail_addr);
-}
-EXPORT_SYMBOL_GPL(mps_fifo_out);
-
-uint32_t mps_fifo_peek(struct mps_fifo *fifo)
-{
-	uint32_t tail = __raw_readl(fifo->tail_addr);
-	void __iomem *base = fifo->base + tail;
-	return __raw_readl(base);
-}
-
-void mps_fifo_reset(struct mps_fifo *fifo)
-{
-	void __iomem *base = fifo->base + fifo->size - 4;
-	size_t i;
-
-	__raw_writel(fifo->size - 4, fifo->head_addr);
-	__raw_writel(fifo->size - 4, fifo->tail_addr);
-
-	for(i = 0; i < 16; ++i) {
-		__raw_writel(0x0, base);
-		base -= 4;
-	}
-}
-
-size_t mps_fifo_len(struct mps_fifo *fifo)
-{
-	uint32_t head = __raw_readl(fifo->head_addr);
-	uint32_t tail = __raw_readl(fifo->tail_addr);
-
-	if (tail < head)
-		return head - tail;
-	else
-		return fifo->size - (tail - head);
-}
-EXPORT_SYMBOL_GPL(mps_fifo_len);
-

+ 0 - 157
package/lqtapi/src/mps/mps-irq.c

@@ -1,157 +0,0 @@
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <ifxmips_irq.h>
-
-#include "mps.h"
-#include "mps-irq.h"
-
-#define MPS_REG_AD0_IRQ_BASE	0x40
-#define MPS_REG_AD1_IRQ_BASE	0x44
-
-#define MPS_REG_AD_IRQ_STATUS	0x00
-#define MPS_REG_AD_IRQ_SET	0x08
-#define MPS_REG_AD_IRQ_CLEAR	0x10
-#define MPS_REG_AD_IRQ_ENABLE	0x18
-
-struct mps_irq_desc
-{
-    void __iomem *base;
-    unsigned int irq_base;
-};
-
-static inline unsigned int mps_irq_bit(struct mps_irq_desc *mps_desc, int irq)
-{
-	return BIT(irq - mps_desc->irq_base);
-}
-
-static void mps_irq_ack(unsigned int irq)
-{
-	struct mps_irq_desc *mps_desc = get_irq_chip_data(irq);
-
-	__raw_writel(mps_irq_bit(mps_desc, irq),
-		mps_desc->base + MPS_REG_AD_IRQ_CLEAR);
-}
-
-static void mps_irq_mask(unsigned int irq)
-{
-	struct mps_irq_desc *mps_desc = get_irq_chip_data(irq);
-	uint32_t mask;
-
-	mask = __raw_readl(mps_desc->base + MPS_REG_AD_IRQ_ENABLE);
-	mask &= ~mps_irq_bit(mps_desc, irq);
-	__raw_writel(mask, mps_desc->base + MPS_REG_AD_IRQ_ENABLE);
-}
-
-static void mps_irq_unmask(unsigned int irq)
-{
-	struct mps_irq_desc *mps_desc = get_irq_chip_data(irq);
-	uint32_t mask;
-
-	mask = __raw_readl(mps_desc->base + MPS_REG_AD_IRQ_ENABLE);
-	mask |= mps_irq_bit(mps_desc, irq) | 0xffff;
-	__raw_writel(mask, mps_desc->base + MPS_REG_AD_IRQ_ENABLE);
-}
-
-static struct irq_chip mps_irq_chip = {
-	.name = "mps",
-	.ack = mps_irq_ack,
-	.mask = mps_irq_mask,
-	.unmask = mps_irq_unmask,
-};
-
-static void mps_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
-{
-	struct mps_irq_desc *mps_desc = get_irq_data(irq);
-	uint32_t val;
-	int mps_irq;
-
-	desc->chip->mask(irq);
-
-	val = __raw_readl(mps_desc->base + MPS_REG_AD_IRQ_STATUS);
-	mps_irq = ffs(val);
-
-/*	printk("irq: %d %x\n", mps_irq, val);*/
-
-	if (mps_irq > 16)
-	    printk("PANIC!\n");
-
-	if (mps_irq)
-		generic_handle_irq(mps_irq + mps_desc->irq_base - 1);
-
-	desc->chip->ack(irq);
-	desc->chip->unmask(irq);
-}
-
-#if 0
-
-static const uint32_t ring_msg[] = {
-0x01010004, 0x00030000,
-};
-
-static irqreturn_t mps_irq_ad0(int irq, void *devid)
-{
-    struct mps *mps = devid;
-    uint32_t val;
-
-    val = __raw_readl(mps->base + MPS_REG_AD0_IRQ_STATUS);
-    printk("WOHO ein IRQ: %x\n", val);
-    __raw_writel(val, mps->base + MPS_REG_AD0_IRQ_CLEAR);
-
-	if (val & BIT(MPS_IRQ_DOWNLOAD_DONE))
-		complete(&mps->init_completion);
-
-	if (val & BIT(MPS_IRQ_EVENT))
-		mps_fifo_in(&mps->mbox_cmd.downstream, ring_msg, ARRAY_SIZE(ring_msg));
-
-    return IRQ_HANDLED;
-}
-#endif
-
-#define MPS_NUM_AD_IRQS 32
-
-struct mps_irq_desc mps_irq_descs[2];
-
-int mps_irq_init(struct mps *mps)
-{
-	int ret = 0;
-	int irq;
-
-	mps_irq_descs[0].base = mps->base + MPS_REG_AD0_IRQ_BASE;
-	mps_irq_descs[0].irq_base = mps->irq_base;
-	mps_irq_descs[1].base = mps->base + MPS_REG_AD1_IRQ_BASE;
-	mps_irq_descs[1].irq_base = mps->irq_base + 16;
-
-
-	set_irq_data(mps->irq_ad0, &mps_irq_descs[0]);
-	set_irq_chained_handler(mps->irq_ad0, mps_irq_demux_handler);
-	set_irq_data(mps->irq_ad1, &mps_irq_descs[1]);
-	set_irq_chained_handler(mps->irq_ad1, mps_irq_demux_handler);
-
-/*
-	ret = request_irq(mps->irq_ad0, mps_irq_demux_handler, IRQF_DISABLED,
-		"mps ad0", &mps_irq_descs[0]);
-	ret = request_irq(mps->irq_ad1, mps_irq_demux_handler, IRQF_DISABLED,
-		"mps ad0", &mps_irq_descs[1]);
-*/
-	for (irq = 0; irq < MPS_NUM_AD_IRQS; ++irq) {
-	    set_irq_chip_data(irq + mps->irq_base, &mps_irq_descs[irq / 16]);
-	    set_irq_chip_and_handler(irq + mps->irq_base, &mps_irq_chip, handle_level_irq);
-	}
-
-
-/*
-	res = request_irq(INT_NUM_IM4_IRL18, mps_irq_ad0, IRQF_DISABLED,
-	    "mps ad0", mps);
-
-	irqs = BIT(MPS_IRQ_CMD_UPSTREAM) | BIT(MPS_IRQ_DATA_UPSTREAM)
-	 | BIT(MPS_IRQ_DOWNLOAD_DONE) | BIT(MPS_IRQ_EVENT) | BIT(MPS_IRQ_CMD_ERROR); 
-
-	 __raw_writel(irqs, mps->base + MPS_REG_AD0_IRQ_ENA);
-*/
-	return ret;
-}
-
-void mps_irq_exit(struct mps *mps)
-{
-	free_irq(INT_NUM_IM4_IRL18, mps);
-}

+ 0 - 18
package/lqtapi/src/mps/mps-irq.h

@@ -1,18 +0,0 @@
-
-#define MPS_IRQ_BASE 160
-#define MPS_IRQ(x) (MPS_IRQ_BASE + (x))
-#define MPS_IRQ_CMD_UPSTREAM MPS_IRQ(0)
-#define MPS_IRQ_DATA_UPSTREAM MPS_IRQ(1)
-#define MPS_IRQ_CMD_DOWNSTREAM MPS_IRQ(2)
-#define MPS_IRQ_DATA_DOWNSTREAM MPS_IRQ(3)
-#define MPS_IRQ_RCV_OVERFLOW MPS_IRQ(4)
-#define MPS_IRQ_EVENT MPS_IRQ(5)
-#define MPS_IRQ_EVENT_OVERFLOW MPS_IRQ(6)
-#define MPS_IRQ_CMD_ERROR MPS_IRQ(8)
-#define MPS_IRQ_PCM_CRASH MPS_IRQ(9)
-#define MPS_IRQ_DATA_ERROR MPS_IRQ(10)
-#define MPS_IRQ_MIPS_OL MPS_IRQ(11)
-#define MPS_IRQ_WATCHDOG_FAIL MPS_IRQ(14)
-#define MPS_IRQ_DOWNLOAD_DONE MPS_IRQ(15)
-
-

+ 0 - 19
package/lqtapi/src/mps/mps-msg.c

@@ -1,19 +0,0 @@
-
-
-int mps_message_send(struct mps_fifo *fifo, struct mps_message *msg)
-{
-}
-
-int mps_message_recv(struct mps_fifo *fifo, struct mps_message *msg)
-{
-	mps_fifo_out(fifo, &msg->header, sizeof(msg->header));
-	mps_fifo_out(fifo, &msg->data, mps_message_size(msg));
-}
-
-struct mps_message *msg mps_message_recv_alloc(struct mps_fifo *fifo)
-{
-	struct mps_message *msg;
-
-	mps_fifo_out(fifo, &msg->header, sizeof(msg->header));
-	mps_fifo_out(fifo, &msg->data, mps_message_size(msg));
-}

+ 0 - 87
package/lqtapi/src/mps/mps-msg.h

@@ -1,87 +0,0 @@
-#ifndef __MPS_MSG_H__
-#define __MPS_MSG_H__
-
-#include <linux/slab.h>
-
-struct mps_message {
-	uint32_t header;
-	uint32_t data[0];
-};
-
-#define MPS_MSG_HEADER(_rw, _sc, _bc, _cmd, _chan, _mode, _ecmd, _length) \
-	(((_rw) << 31) | ((_sc) << 30) | ((_bc) << 29) | ((_cmd) << 24) | \
-	((_chan) << 16) | ((_mode) << 13) | ((_ecmd) << 8) | (_length))
-
-#define MPS_MSG_INIT(_msg, _rw, _sc, _bc, _cmd, _chan, _mode, _ecmd, _length) \
-	do { \
-		(_msg)->header = MPS_MSG_HEADER(_rw, _sc, _bc, _cmd, _chan, _mode, \
-			_ecmd, _length); \
-	} while(0)
-
-
-static inline void mps_msg_init(struct mps_message *msg, uint32_t rw, uint32_t sc,
-	uint32_t bc, uint32_t cmd, uint32_t chan, uint32_t mode, uint32_t ecmd,
-	uint32_t length)
-{
-	msg->header = MPS_MSG_HEADER(rw, sc, bc, cmd, chan, mode, ecmd, length);
-}
-
-#define DECLARE_MESSAGE(_name, _size) struct mps_message _name; \
-	uint32_t __mps_msg_data_ ## __FUNCTION__ ## __LINE__[_size]
-
-static inline struct mps_message *mps_message_alloc(size_t size)
-{
-	return kmalloc(sizeof(struct mps_message) + size * sizeof(uint32_t), GFP_KERNEL);
-}
-
-static inline size_t mps_message_size(const struct mps_message *msg)
-{
-	return msg->header & 0xff;
-}
-
-enum {
-	MPS_MSG_WRITE = 0,
-	MPS_MSG_READ = 1,
-};
-
-enum {
-	MPS_CMD_ALI = 1,
-	MPS_CMD_DECT = 3,
-	MPS_CMD_SDD = 4,
-	MPS_CMD_EOP = 6,
-};
-
-#define MOD_PCM 0
-#define MOD_SDD 0
-#define MOD_ALI 1
-#define MOD_SIGNALING 2
-#define MOD_CODER 3
-#define MOD_RESOURCE 6
-#define MOD_SYSTEM 7
-#define ECMD_SYS_VER 6
-#define SYS_CAP_ECMD 7
-#define ECMD_CIDS_DATA 9
-#define ECMD_DCCTL_DEBUG 0x0a
-
-#define ALI_CHAN_CMD 6
-#define ALI_CHAN_ECMD 1
-
-#define MPS_MSG_HEADER_W(_sc, _bc, _cmd, _chan, _mode, _ecmd, _length) \
-	MPS_MSG_HEADER(MPS_MSG_WRITE, _sc, _bc, _cmd, _chan, _mode, _ecmd, _length)
-
-#define MPS_MSG_HEADER_R(_sc, _bc, _cmd, _chan, _mode, _ecmd, _length) \
-	MPS_MSG_HEADER(MPS_MSG_READ, _sc, _bc, _cmd, _chan, _mode, _ecmd, _length)
-
-#define MPS_MSG_CMD_EOP(_mode, _ecmd, _length) \
-	MPS_MSG_HEADER_R(0, 0, MPS_CMD_EOP, 0, _mode, _ecmd, _length)
-
-#define MPS_MSG_CMD_EOP_SYSTEM(_ecmd, _length) \
-	MPS_MSG_CMD_EOP(MOD_SYSTEM, _ecmd, _length)
-
-#define MPS_CMD_GET_VERSION \
-	MPS_MSG_CMD_EOP_SYSTEM(ECMD_SYS_VER, 4)
-
-#define MPS_CMD_ALI(_chan) \
-	MPS_MSG_HEADER_W(0, 0, ALI_CHAN_CMD, _chan, MOD_ALI, ALI_CHAN_ECMD, 12)
-
-#endif

+ 0 - 85
package/lqtapi/src/mps/mps.h

@@ -1,85 +0,0 @@
-#ifndef __MPS_H__
-#define __MPS_H__
-
-#include <linux/platform_device.h>
-#include <linux/completion.h>
-
-struct mps_fifo_config
-{
-	size_t head_addr;
-	size_t tail_addr;
-	size_t base_addr;
-	size_t size_addr;
-
-	size_t base;
-	size_t size;
-};
-
-struct mps_fifo {
-	void __iomem *base;
-	void __iomem *head_addr;
-	void __iomem *tail_addr;
-	uint32_t size;
-};
-
-struct mps_mailbox {
-	struct mps_fifo upstream;
-	struct mps_fifo downstream;
-};
-
-enum mps_boot_config
-{
-	MPS_BOOT_LEGACY = 1,
-	MPS_BOOT_ENCRYPTED = 2,
-};
-
-struct mps {
-	struct resource *res;
-	void __iomem *base;
-
-	struct resource *mbox_res;
-	void __iomem *mbox_base;
-
-	struct resource *cp1_res;
-	void __iomem *cp1_base;
-
-	struct device *dev;
-
-	int irq_ad0;
-	int irq_ad1;
-	int irq_base;
-};
-
-void mps_configure_fifo(struct mps *mps, struct mps_fifo *fifo,
-	const struct mps_fifo_config *config);
-
-void mps_configure_mailbox(struct mps *mps, struct mps_mailbox *mbox,
-	const struct mps_fifo_config *upstream_config,
-	const struct mps_fifo_config *downstream_config);
-
-void mps_load_firmware(struct mps *mps, const void *data, size_t size,
-	enum mps_boot_config config);
-
-static inline struct mps *device_to_mps(struct device *dev)
-{
-	return (struct mps *)dev_get_drvdata(dev);
-}
-
-/* fifo */
-void mps_fifo_init(struct mps_fifo *fifo, void __iomem *data_addr,
-	void __iomem *head_addr, void __iomem *tail_addr, uint32_t size);
-void mps_fifo_in(struct mps_fifo *fifo, const uint32_t *from, size_t len);
-void mps_fifo_out(struct mps_fifo *fifo, uint32_t *to, size_t len);
-uint32_t mps_fifo_peek(struct mps_fifo *fifo);
-void mps_fifo_reset(struct mps_fifo *fifo);
-size_t mps_fifo_len(struct mps_fifo *fifo);
-
-/* Mailbox */
-int mps_mailbox_init(struct mps_mailbox *mbox, const char *name, int irq);
-int mps_mailbox_command_read(struct mps_mailbox *mbox, uint32_t cmd,
-	uint32_t *result);
-int mps_mailbox_command_write(struct mps_mailbox *mbox, uint32_t cmd,
-	const uint32_t *data);
-
-
-#endif

+ 0 - 129
package/lqtapi/src/mps/vmmc-alm.c

@@ -1,129 +0,0 @@
-#include <linux/kernel.h>
-
-#include "vmmc.h"
-#include "vmmc-cmds.h"
-#include "vmmc-alm.h"
-#include "vmmc-module.h"
-#include "mps.h"
-
-static inline struct vmmc_alm *vmmc_module_to_alm(struct vmmc_module *module)
-{
-	return container_of(module, struct vmmc_alm, module);
-}
-
-int vmmc_alm_set_state(struct vmmc_alm *alm, enum vmmc_alm_state state)
-{
-	int ret;
-
-	ret = vmmc_command_write(alm->vmmc, VMMC_CMD_OPMODE(alm->id), &state);
-	if (!ret)
-		alm->state = state;
-
-	return ret;
-}
-
-enum vmmc_alm_state vmmc_alm_get_state(struct vmmc_alm *alm)
-{
-	return alm->state;
-}
-
-static struct vmmc_alm_coef *vmmc_alm_coef_alloc(unsigned int offset, size_t len)
-{
-	struct vmmc_alm_coef *coef;
-
-	coef = kzalloc(sizeof(*coef) + sizeof(uint32_t) * DIV_ROUND_UP(len, 4),
-			GFP_KERNEL);
-	coef->offset = offset;
-	coef->len = len;
-
-	return coef;
-}
-
-int vmcc_alm_set_coefficents(struct vmmc_alm *alm,
-	const struct vmmc_alm_coef *coef_list)
-{
-	int ret = 0;
-	uint32_t cmd;
-	struct vmmc_alm_coef *coef;
-	struct list_head l;
-
-	INIT_LIST_HEAD(&l);
-
-	coef = vmmc_alm_coef_alloc(0x37, 8);
-	coef->data[0] = 0x76d7871d;
-	coef->data[1] = 0x7fbb7ff4;
-	list_add_tail(&coef->list, &l);
-	coef = vmmc_alm_coef_alloc(0x5e, 2);
-	coef->data[0] = 0x7e000000;
-	list_add_tail(&coef->list, &l);
-	coef = vmmc_alm_coef_alloc(0x6c, 2);
-	coef->data[0] = 0x7e000000;
-	list_add_tail(&coef->list, &l);
-
-	list_for_each_entry(coef, &l, list) {
-		cmd = VMMC_CMD_ALM_COEF(alm->id, coef->offset, coef->len);
-		ret = vmmc_command_write(alm->vmmc, cmd, coef->data);
-		if (ret)
-			break;
-	}
-
-	return ret;
-}
-
-static int vmmc_alm_sync(struct vmmc_module *module)
-{
-	struct vmmc_alm *alm = vmmc_module_to_alm(module);
-
-	alm->cmd_cache[0] = VMMC_CMD_ALI_DATA1(1, 0, 0, 1, 0, module->pins[0], 0x4000);
-	alm->cmd_cache[1] = VMMC_CMD_ALI_DATA2(0x4000, module->pins[1], module->pins[2]);
-	alm->cmd_cache[2] = VMMC_CMD_ALI_DATA3(module->pins[3], module->pins[4]);
-
-	return vmmc_command_write(alm->vmmc, VMMC_CMD_ALI(alm->id), alm->cmd_cache);
-}
-
-static int vmmc_alm_enable(struct vmmc_module *module, bool enable)
-{
-	struct vmmc_alm *alm = vmmc_module_to_alm(module);
-
-	return vmmc_command_write(alm->vmmc, VMMC_CMD_ALI(alm->id), alm->cmd_cache);
-}
-
-static const struct vmmc_module_ops vmmc_alm_module_ops = {
-	.sync = vmmc_alm_sync,
-	.enable = vmmc_alm_enable,
-};
-
-int vmmc_alm_init(struct vmmc_alm *alm, struct vmmc *vmmc, unsigned int id)
-{
-	int ret;
-
-	ret = vmmc_module_init(&alm->module, 5, &vmmc_alm_module_ops);
-	if (ret)
-		return ret;
-
-	alm->id = id;
-	alm->module.id = id + 0x4;
-	alm->vmmc = vmmc;
-
-	alm->cmd_cache[0] = VMMC_CMD_ALI_DATA1(1, 0, 0, 1, 0, 0, 0x2000);
-	alm->cmd_cache[1] = VMMC_CMD_ALI_DATA2(0x2000, 0, 0);
-	alm->cmd_cache[2] = VMMC_CMD_ALI_DATA3(0, 0);
-
-	vmmc_command_write(alm->vmmc, VMMC_CMD_ALI(alm->id), alm->cmd_cache);
-	vmcc_alm_set_coefficents(alm, NULL);
-	vmmc_register_module(vmmc, &alm->module);
-
-// disable lec
-// write lec coef
-// write nlp coef
-// enable lec
-
-// ALI_LEC ALI_ES RES_LEC_COEF RES_LEC_NLP_COEF
-
-	return ret;
-}
-
-void vmmc_alm_hook_event_handler(struct vmmc *vmmc, uint32_t id, uint32_t data)
-{
-	tapi_report_hook_event(&vmmc->tdev, &vmmc->tdev.ports[id], data & 1);
-}

+ 0 - 42
package/lqtapi/src/mps/vmmc-alm.h

@@ -1,42 +0,0 @@
-#ifndef  __VMMC_ALM_H__
-#define  __VMMC_ALM_H__
-
-#include "vmmc-module.h"
-
-struct vmmc;
-enum vmmc_alm_state {
-	VMMC_ALM_STATE_OFF = 0 << 16,
-	VMMC_ALM_STATE_ONHOOK = 1 << 16,
-	VMMC_ALM_STATE_RING = 3 << 16,
-	VMMC_ALM_STATE_ACTIVE = 2 << 16,
-};
-
-struct vmmc_alm {
-	struct vmmc *vmmc;
-	unsigned int id;
-
-	enum vmmc_alm_state state;
-
-	struct vmmc_module module;
-
-	uint32_t cmd_cache[3];
-};
-
-struct vmmc_alm_coef {
-	struct list_head list;
-	unsigned int offset;
-	size_t len;
-	uint32_t data[0];
-};
-
-int vmmc_alm_init(struct vmmc_alm *alm, struct vmmc *vmmc, unsigned int id);
-
-int vmmc_alm_set_state(struct vmmc_alm *alm, enum vmmc_alm_state state);
-enum vmmc_alm_state vmmc_alm_get_state(struct vmmc_alm *alm);
-
-int vmcc_alm_set_coefficents(struct vmmc_alm *alm,
-	const struct vmmc_alm_coef *coef_list);
-
-void vmmc_alm_hook_event_handler(struct vmmc *vmmc, uint32_t event, uint32_t data);
-
-#endif

+ 0 - 98
package/lqtapi/src/mps/vmmc-cmds.h

@@ -1,98 +0,0 @@
-#ifndef __VMMC_CMDS_H__
-#define __VMMC_CMDS_H__
-
-#define _VMMC_CMD(_x) ((_x) << 24)
-#define _VMMC_MOD(_x) ((_x) << 13)
-#define _VMMC_ECMD(_x) ((_x) << 8)
-
-#define _VMMC_MSG(_cmd, _mod, _ecmd) \
-	(_VMMC_CMD(_cmd) | _VMMC_ECMD(_ecmd) | _VMMC_MOD(_mod))
-
-#define _VMMC_CHAN(_chan) ((_chan) << 16)
-#define _VMMC_LENGTH(_length) ((_length) << 2)
-
-#define VMMC_CMD_OPMODE(_chan) (_VMMC_MSG(1, 0, 0) | _VMMC_CHAN(_chan) | _VMMC_LENGTH(1))
-
-#define VMMC_CMD_SIG(_chan) (_VMMC_MSG(6, 2, 1) | _VMMC_CHAN(_chan) | _VMMC_LENGTH(1))
-#define VMMC_CMD_SIG_DATA(_enable, _event, _rate, _i1, _i2, _mute1, _mute2) \
-	(((_enable) << 31) | ((_event) << 30) | ((_i1) << 24) | ((_i2) << 16) | \
-	((_rate) << 23) | ((_mute1) << 15) | ((_mute2) << 14))
-
-#define VMMC_CMD_SIG_SET_ENABLE(_data, _enable) (((_data) & ~BIT(31)) | ((_enable) << 31))
-#define VMMC_CMD_SIG_SET_INPUTS(_data, _i1, _i2) (((_data) & ~0x3f3f0000) | \
-	((_i1) << 24) | ((_i2) << 16))
-
-#define VMMC_CMD_DTMFR(_chan) (_VMMC_MSG(6, 2, 4) | _VMMC_CHAN(_chan) | _VMMC_LENGTH(1))
-#define VMMC_CMD_DTMFR_DATA(_enable, _event, _nr) \
-	(((_enable) << 31) | ((_event) << 30) | (6 << 27) | ((_nr) << 16))
-
-#define VMMC_CMD_CODER(_chan) (_VMMC_MSG(6, 3, 1) | _VMMC_CHAN(_chan) | _VMMC_LENGTH(4))
-
-#define VMMC_CMD_CODER_DATA1(_enable, _rate, _ns, _pte, _nr, _i1, _hp, _pf, \
-	_cng, _bfi, _dec, _im, _pst, _sic, _em, _enc) \
-	(((_enable) << 31) | ((_rate) << 30) | ((_ns) << 29) | ((_pte) << 26) | \
-	((_nr) << 22) | ((_i1) << 16) | ((_hp) << 15) | ((_pf) << 14) | \
-	((_cng) << 13) | ((_bfi) << 12) | ((_dec) << 11) | ((_im) << 10) | \
-	((_pst) << 9) | ((_sic) << 8) | ((_em) << 7) | (_enc))
-
-#define VMMC_CMD_CODER_DATA2(_gain1, _gain2) (((_gain1) << 16) | (_gain2))
-
-#define VMMC_CMD_CODER_DATA3(_de, _ee, _i2, _red, _i3, _plc, _i4, _i5) \
-	(((_de) << 31) | ((_ee) << 30) | ((_i2) << 24) | ((_red) << 22) | \
-	((_i3) << 16) | ((_plc) << 15) | ((_i4) << 8) | (_i5))
-
-#define VMMC_CMD_SERR_ACK(_chan) _VMMC_MSG(6, 7, 1) | _VMMC_CHAN(_chan) | _VMMC_LENGTH(1)
-
-#define VMMC_CMD_SERR_ACK_DATA1(_foo) ((_foo) << 22)
-
-#define VMMC_CMD_CODER_DATA4(_tsf) ((_tsf) << 31)
-
-#define VMMC_EVENT_ID_MASK (_VMMC_MSG(0x1f, 0x7, 0x1f) | 0xff)
-
-#define VMMC_MSG_GET_CHAN(_msg) (((_msg) >> 16) & 0x1f)
-
-#define VMMC_EVENT_HOOK_STATE(_data) ((_data) & 1)
-
-#define VMMC_EVENT_HOOK_ID (_VMMC_MSG(9, 1, 1) | _VMMC_LENGTH(1))
-#define VMMC_EVENT_DTMF_ID (_VMMC_MSG(9, 2, 0) | _VMMC_LENGTH(1))
-
-#define VMMC_VOICE_DATA(_type, _chan, _len) (((_type) << 24) | ((_chan) << 16) \
-	| (_len))
-
-
-#define VMMC_CMD_ALI(_chan) (_VMMC_MSG(6, 1, 1) | _VMMC_CHAN(_chan) | _VMMC_LENGTH(3))
-
-#define VMMC_CMD_ALI_DATA1(_enable, _rate, _ud, _eh, _eo, _i1, _dg1) \
-	(((_enable) << 31) | ((_rate) << 30) | ((_ud) << 29) | ((_eh) << 27) | \
-	((_eo) << 26) | ((_i1) << 16) | (_dg1))
-
-#define VMMC_CMD_ALI_DATA2(_dg2, _i2, _i3) \
-	(((_dg2) << 16) | ((_i2) << 8) | (_i3))
-
-#define VMMC_CMD_ALI_DATA3(_i4, _i5) \
-	(((_i4) << 24) | ((_i5) << 16))
-
-#define VMMC_CMD_ALM_COEF(_chan, _offset, _len) \
-	(_VMMC_MSG(2, 0, _offset) | _VMMC_CHAN(_chan) | (_len))
-
-#define CMD_VOICEREC_STATUS_PACKET  0x0
-#define CMD_VOICEREC_DATA_PACKET    0x1
-#define CMD_RTP_VOICE_DATA_PACKET   0x4
-#define CMD_RTP_EVENT_PACKET        0x5
-#define CMD_ADDRESS_PACKET          0x8
-#define CMD_FAX_DATA_PACKET         0x10
-#define CMD_FAX_STATUS_PACKET       0x11
-#define CMD_P_PHONE_DATA_PACKET     0x12
-#define CMD_P_PHONE_STATUS_PACKET   0x13
-
-#define VMMC_CMD_RTP_CFG_US(_chan) \
-	(_VMMC_MSG(6, 3, 17) | _VMMC_CHAN(_chan) | (36))
-#define VMMC_CMD_RTP_CFG_DS(_chan) \
-	(_VMMC_MSG(6, 3, 25) | _VMMC_CHAN(_chan) | (32))
-
-#define VMMC_CMD_LEC(_chan) \
-	(_VMMC_MSG(6, 2, 1) | _VMMC_CHAN(_chan) | _VMMC_LENGTH(1))
-//	(_VMMC_MSG(CMD_EOP, ALI_LEC_ECMD, MOD_ALI) | _VMMC_CHAN(_chan) | (32))
-
-#define VMMC_CMD_LEC_DATA() 
-#endif

+ 0 - 221
package/lqtapi/src/mps/vmmc-coder.c

@@ -1,221 +0,0 @@
-#include <linux/kernel.h>
-
-#include "vmmc.h"
-#include "vmmc-cmds.h"
-#include "vmmc-coder.h"
-#include "vmmc-module.h"
-#include "mps.h"
-
-enum vmmc_coder_encoding {
-	VMMC_CODER_ENCODING_ALAW = 2,
-	VMMC_CODER_ENCODING_MLAW = 3,
-	VMMC_CODER_ENCODING_G726_16 = 4,
-	VMMC_CODER_ENCODING_G726_24 = 5,
-	VMMC_CODER_ENCODING_G726_32 = 6,
-	VMMC_CODER_ENCODING_G726_40 = 7,
-	VMMC_CODER_ENCODING_AMR_4_75 = 8,
-	VMMC_CODER_ENCODING_AMR_5_15 = 9,
-	VMMC_CODER_ENCODING_AMR_5_9 = 10,
-	VMMC_CODER_ENCODING_AMR_6_7 = 11,
-	VMMC_CODER_ENCODING_AMR_7_4 = 12,
-	VMMC_CODER_ENCODING_AMR_7_95 = 13,
-	VMMC_CODER_ENCODING_AMR_10_2 = 14,
-	VMMC_CODER_ENCODING_AMR_12_2 = 15,
-	VMMC_CODER_ENCODING_G728_16 = 16,
-	VMMC_CODER_ENCODING_G729AB_8 = 18,
-	VMMC_CODER_ENCODING_G729E_11_8 = 19,
-	VMMC_CODER_ENCODING_G7221_24 = 20,
-	VMMC_CODER_ENCODING_G7221_32 = 21,
-	VMMC_CODER_ENCODING_G722_64 = 22,
-	VMMC_CODER_ENCODING_L16_8 = 24,
-	VMMC_CODER_ENCODING_L16_16 = 25,
-	VMMC_CODER_ENCODING_ILBC_15_2 = 26,
-	VMMC_CODER_ENCODING_ILBC_13_3 = 27,
-	VMMC_CODER_ENCODING_G7231_5_3 = 28,
-	VMMC_CODER_ENCODING_G7231_6_3 = 29,
-	VMMC_CODER_ENCODING_ALAW_VBD = 30,
-	VMMC_CODER_ENCODING_MLAW_VBD = 31,
-};
-
-static const uint8_t vmmc_coder_payload_mapping[] = {
-	[VMMC_CODER_ENCODING_ALAW] = 8,
-	[VMMC_CODER_ENCODING_MLAW] = 0,
-	[VMMC_CODER_ENCODING_G726_16] = 35,
-	[VMMC_CODER_ENCODING_G726_24] = 36,
-	[VMMC_CODER_ENCODING_G726_32] = 37,
-	[VMMC_CODER_ENCODING_G726_40] = 38,
-	[VMMC_CODER_ENCODING_AMR_4_75] = 39,
-	[VMMC_CODER_ENCODING_AMR_5_15] = 40,
-	[VMMC_CODER_ENCODING_AMR_5_9] = 41,
-	[VMMC_CODER_ENCODING_AMR_6_7] = 42,
-	[VMMC_CODER_ENCODING_AMR_7_4] = 43,
-	[VMMC_CODER_ENCODING_AMR_7_95] = 44,
-	[VMMC_CODER_ENCODING_AMR_10_2] = 45,
-	[VMMC_CODER_ENCODING_AMR_12_2] = 46,
-	[VMMC_CODER_ENCODING_G728_16] = 47,
-	[VMMC_CODER_ENCODING_G729AB_8] = 48,
-	[VMMC_CODER_ENCODING_G729E_11_8] = 49,
-	[VMMC_CODER_ENCODING_G7221_24] = 50,
-	[VMMC_CODER_ENCODING_G7221_32] = 51,
-	[VMMC_CODER_ENCODING_G722_64] = 52,
-	[VMMC_CODER_ENCODING_L16_8] = 11,
-	[VMMC_CODER_ENCODING_L16_16] = 10,
-	[VMMC_CODER_ENCODING_ILBC_15_2] = 53,
-	[VMMC_CODER_ENCODING_ILBC_13_3] = 54,
-	[VMMC_CODER_ENCODING_G7231_5_3] = 4,
-	[VMMC_CODER_ENCODING_G7231_6_3] = 4,
-	[VMMC_CODER_ENCODING_ALAW_VBD] = 55,
-	[VMMC_CODER_ENCODING_MLAW_VBD] = 56,
-};
-
-static uint32_t payload_enc[9];
-static uint32_t payload_dec[8];
-
-static inline struct vmmc_coder *vmmc_module_to_coder(struct vmmc_module *module)
-{
-	return container_of(module, struct vmmc_coder, module);
-}
-
-static int vmmc_coder_enable(struct vmmc_module *module, bool enable)
-{
-	struct vmmc_coder *coder = vmmc_module_to_coder(module);
-
-	coder->enabled = enable;
-
-/*	coder->cmd_cache[0] = VMMC_CMD_CODER_DATA1(coder->enabled, 0, 0, 0, coder->id,
-		module->pins[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-	return vmmc_command_write(coder->vmmc, VMMC_CMD_CODER(coder->id),
-	coder->cmd_cache);*/
-	return 0;
-}
-
-static int vmmc_coder_sync(struct vmmc_module *module)
-{
-	struct vmmc_coder *coder = vmmc_module_to_coder(module);
-
-	coder->cmd_cache[0] = VMMC_CMD_CODER_DATA1(coder->enabled, 0, 1, 1, coder->id,
-		module->pins[0], 1, 1, 1, 1, 1, 1, 0, 0, 0, VMMC_CODER_ENCODING_MLAW);
-	coder->cmd_cache[1] = VMMC_CMD_CODER_DATA2(0x2000, 0x2000);
-	coder->cmd_cache[2] = VMMC_CMD_CODER_DATA3(0, 0, module->pins[1], 0,
-		module->pins[2], 0, module->pins[3], module->pins[4]);
-
-	return vmmc_command_write(coder->vmmc, VMMC_CMD_CODER(coder->id), coder->cmd_cache);
-}
-
-static const struct vmmc_module_ops vmmc_coder_module_ops = {
-	.sync = vmmc_coder_sync,
-	.enable = vmmc_coder_enable,
-};
-
-#define VMMC_CMD_CODER_JB(_chan) (_VMMC_MSG(6, 3, 18) | _VMMC_CHAN(_chan) | 8)
-#define VMMC_CMD_CODER_JB_DATA1(_sf, _prp, _pje, _dvf, _nam, _rad, _adap, _init_pod) \
-	(((_sf) << 31) | ((_prp) << 23) | ((_pje) << 22) | ((_dvf) << 21) | \
-	((_nam) << 20) | ((_rad) << 17) | ((_adap) << 16) | (_init_pod))
-#define VMMC_CMD_CODER_JB_DATA2(_min_pod, _max_pod) \
-	(((_min_pod) << 16) | (_max_pod))
-#define VMMC_CMD_CODER_JB_DATA3(_adap_factor, _min_margin, _mode) \
-	(((_adap_factor) << 24) | ((_min_margin) << 16) | (_mode))
-
-int vmmc_coder_init(struct vmmc_coder *coder, struct vmmc *vmmc, unsigned int id)
-{
-	int ret;
-
-	ret = vmmc_module_init(&coder->module, 5, &vmmc_coder_module_ops);
-	if (ret)
-		return ret;
-
-	coder->id = id;
-	coder->module.id = id + 0x18;
-	coder->vmmc = vmmc;
-	coder->enabled = 0;
-
-	coder->cmd_cache[0] = VMMC_CMD_CODER_DATA1(0, 0, 0, 0, id, 0,
-		0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-	coder->cmd_cache[1] = VMMC_CMD_CODER_DATA2(0, 0);
-	coder->cmd_cache[2] = VMMC_CMD_CODER_DATA3(0, 0, 0, 0, 0, 0, 0, 0);
-	coder->cmd_cache[3] = VMMC_CMD_CODER_DATA4(0);
-
-	coder->jitter_buffer_cache[0] = VMMC_CMD_CODER_JB_DATA1(0x16, 1, 0, 0, 1, 1,
-	1, 0x50);
-	coder->jitter_buffer_cache[1] = VMMC_CMD_CODER_JB_DATA2(0x50, 0x05a0);
-	coder->jitter_buffer_cache[2] = VMMC_CMD_CODER_JB_DATA3(0x0d, 0x28, 1);
-
-	vmmc_command_write(coder->vmmc, VMMC_CMD_RTP_CFG_US(coder->id), payload_enc);
-	vmmc_command_write(coder->vmmc, VMMC_CMD_RTP_CFG_DS(coder->id), payload_dec);
-	vmmc_command_write(coder->vmmc, VMMC_CMD_CODER_JB(coder->id),
-	coder->jitter_buffer_cache);
-	vmmc_command_write(coder->vmmc, VMMC_CMD_CODER(coder->id), coder->cmd_cache);
-
-	vmmc_register_module(vmmc, &coder->module);
-
-	return ret;
-}
-
-void vmmc_coder_event(struct vmmc *vmmc, unsigned int chan, unsigned int type)
-{
-}
-
-/*
-void vmmc_coder_event(struct vmmc_coder *coder, unsigned int len)
-{
-	struct sk_buff *skb;
-	provide_mem_region(coder->vmmc, vmmc_coder_alloc_paket(coder)->head, 512);
-
-	skb = skb_dequeue(&coder->paket_queue);
-	skb_put(skb, len);
-
-	tapi_stream_recv(&coder->vmmc->tdev, skb);
-}
-*/
-/*
-int vmmc_coder_set_codec(struct vmmc_coder *coder, enum vmmc_codec codec)
-{
-}*/
-
-void vmmc_init_coders(struct vmmc *vmmc)
-{
-	unsigned int i;
-
-	payload_enc[0] = 0;
-	payload_enc[1] = 0x0;
-	payload_enc[1] |= vmmc_coder_payload_mapping[2] << 8;
-	payload_enc[1] |= vmmc_coder_payload_mapping[3] << 8;
-	for (i = 2; i < 9; ++i) {
-		payload_enc[i] = vmmc_coder_payload_mapping[i*4 - 4] << 24;
-		payload_enc[i] |= vmmc_coder_payload_mapping[i*4 - 3] << 16;
-		payload_enc[i] |= vmmc_coder_payload_mapping[i*4 - 2] << 8;
-		payload_enc[i] |= vmmc_coder_payload_mapping[i*4 - 1];
-		payload_enc[i] |= 0x80808080;
-	}
-	for (i = 0; i < 7; ++i) {
-		payload_dec[i] = vmmc_coder_payload_mapping[i*4 + 2] << 24;
-		payload_dec[i] |= vmmc_coder_payload_mapping[i*4 + 3] << 16;
-		payload_dec[i] |= vmmc_coder_payload_mapping[i*4 + 4] << 8;
-		payload_dec[i] |= vmmc_coder_payload_mapping[i*4 + 5];
-	}
-	payload_dec[i] = vmmc_coder_payload_mapping[i*4 + 2] << 24;
-	payload_dec[i] |= vmmc_coder_payload_mapping[i*4 + 3] << 16;
-
-
-	vmmc->num_coders = 5;
-	vmmc->coder = kcalloc(sizeof(*vmmc->coder), vmmc->num_coders, GFP_KERNEL);
-
-	for (i = 0; i < vmmc->num_coders; ++i)
-		vmmc_coder_init(&vmmc->coder[i], vmmc, i);
-}
-
-struct vmmc_coder *vmmc_coder_get(struct vmmc *vmmc)
-{
-	unsigned int i;
-	for (i = 0; i < vmmc->num_coders; ++i) {
-		if (!test_and_set_bit(i, &vmmc->coder_used))
-			return &vmmc->coder[i];
-	}
-
-	return NULL;
-}
-
-void vmmc_coder_put(struct vmmc *vmmc, struct vmmc_coder *coder)
-{
-	clear_bit(coder->id, &vmmc->coder_used);
-}

+ 0 - 14
package/lqtapi/src/mps/vmmc-coder.h

@@ -1,14 +0,0 @@
-
-struct vmmc_coder {
-	struct vmmc *vmmc;
-	unsigned int id;
-
-	struct vmmc_module module;
-
-	unsigned int enabled;
-
-	uint32_t cmd_cache[4];
-	uint32_t jitter_buffer_cache[3];
-
-	struct tapi_stream *stream;
-};

+ 0 - 646
package/lqtapi/src/mps/vmmc-core.c

@@ -1,646 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-
-#include <linux/firmware.h>
-
-#include <linux/delay.h>
-
-#include <ifxmips_gptu.h>
-
-#include <linux/tapi/tapi.h>
-
-#include "vmmc.h"
-#include "mps.h"
-#include "mps-msg.h"
-#include "mps-irq.h"
-#include "vmmc-cmds.h"
-
-#include "vmmc-port.h"
-#include "vmmc-stream.h"
-#include "vmmc-link.h"
-#include "vmmc-coder.h"
-
-struct vmmc_capabilities {
-	uint8_t num_alm;
-	uint8_t num_pcm;
-	uint8_t num_signal;
-	uint8_t num_coder;
-	uint8_t num_agc;
-	uint8_t num_eq;
-	uint8_t num_nlec;
-	uint8_t num_wlec;
-	uint8_t num_nwlec;
-	uint8_t num_wwlec;
-	uint8_t num_tone_generators;
-	uint8_t num_dtmf_generators;
-	uint8_t num_caller_id_senders;
-	uint8_t num_caller_id_recivers;
-};
-
-#define MPS_FIRMWARE_MAGIC 0xcc123456
-
-struct vmmc_firmware_head {
-	uint32_t crc;
-	uint32_t crc_start_addr;
-	uint32_t crc_end_addr;
-	uint32_t version;
-	uint32_t encrypted;
-	uint32_t magic;
-	uint32_t mem;
-} __packed;
-
-#define VMMC_FIFO_UPSTREAM_CMD_BASE_ADDR	0x00
-#define VMMC_FIFO_UPSTREAM_CMD_SIZE_ADDR	0x04
-#define VMMC_FIFO_DOWNSTREAM_CMD_BASE_ADDR	0x08
-#define VMMC_FIFO_DOWNSTREAM_CMD_SIZE_ADDR	0x0c
-#define VMMC_FIFO_UPSTREAM_DATA_BASE_ADDR	0x10
-#define VMMC_FIFO_UPSTREAM_DATA_SIZE_ADDR	0x14
-#define VMMC_FIFO_DOWNSTREAM_DATA_BASE_ADDR	0x18
-#define VMMC_FIFO_DOWNSTREAM_DATA_SIZE_ADDR	0x1c
-#define VMMC_FIFO_UPSTREAM_CMD_TAIL_ADDR	0x20
-#define VMMC_FIFO_UPSTREAM_CMD_HEAD_ADDR	0x24
-#define VMMC_FIFO_DOWNSTREAM_CMD_TAIL_ADDR	0x28
-#define VMMC_FIFO_DOWNSTREAM_CMD_HEAD_ADDR	0x2c
-#define VMMC_FIFO_UPSTREAM_DATA_TAIL_ADDR	0x30
-#define VMMC_FIFO_UPSTREAM_DATA_HEAD_ADDR	0x34
-#define VMMC_FIFO_DOWNSTREAM_DATA_TAIL_ADDR	0x38
-#define VMMC_FIFO_DOWNSTREAM_DATA_HEAD_ADDR	0x3c
-
-#define VMMC_FIFO_EVENT_BASE_ADDR		0x180
-#define VMMC_FIFO_EVENT_SIZE_ADDR		0x184
-#define VMMC_FIFO_EVENT_TAIL_ADDR		0x188
-#define VMMC_FIFO_EVENT_HEAD_ADDR		0x18c
-
-
-/* Calculates the base of the fifo behind the given fifo */
-#define VMMC_NEXT_FIFO_BASE0(_fifo) \
-	(VMMC_FIFO_ ## _fifo ## _BASE + VMMC_FIFO_ ## _fifo ## _SIZE)
-#define VMMC_NEXT_FIFO_BASE1(_fifo) \
-	(VMMC_FIFO_ ## _fifo ## _BASE + VMMC_FIFO_ ## _fifo ## _SIZE)
-#define VMMC_NEXT_FIFO_BASE2(_fifo) \
-	(VMMC_FIFO_ ## _fifo ## _BASE + VMMC_FIFO_ ## _fifo ## _SIZE)
-
-/* Fifo sizes */
-#define VMMC_FIFO_UPSTREAM_CMD_SIZE	64
-#define VMMC_FIFO_DOWNSTREAM_CMD_SIZE	64
-#define VMMC_FIFO_UPSTREAM_DATA_SIZE	64
-#define VMMC_FIFO_DOWNSTREAM_DATA_SIZE	128
-#define VMMC_FIFO_EVENT_SIZE		64
-
-/* Fifo addresses */
-#define VMMC_FIFO_UPSTREAM_CMD_BASE	0x40
-#define VMMC_FIFO_DOWNSTREAM_CMD_BASE	VMMC_NEXT_FIFO_BASE0(UPSTREAM_CMD)
-#define VMMC_FIFO_UPSTREAM_DATA_BASE	VMMC_NEXT_FIFO_BASE1(DOWNSTREAM_CMD)
-#define VMMC_FIFO_DOWNSTREAM_DATA_BASE	VMMC_NEXT_FIFO_BASE2(UPSTREAM_DATA)
-#define VMMC_FIFO_EVENT_BASE		0x190
-
-#define VMMC_DECLARE_FIFO_CONFIG(_name, _fifo) \
-static const struct mps_fifo_config _name = { \
-	.tail_addr = VMMC_FIFO_ ## _fifo ## _TAIL_ADDR, \
-	.head_addr = VMMC_FIFO_ ## _fifo ## _HEAD_ADDR, \
-	.base_addr = VMMC_FIFO_ ## _fifo ## _BASE_ADDR, \
-	.size_addr = VMMC_FIFO_ ## _fifo ## _SIZE_ADDR, \
-	.base = VMMC_FIFO_ ## _fifo ## _BASE, \
-	.size = VMMC_FIFO_ ## _fifo ## _SIZE, \
-}
-
-VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_upstream_cmd, UPSTREAM_CMD);
-VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_downstream_cmd, DOWNSTREAM_CMD);
-VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_upstream_data, UPSTREAM_DATA);
-VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_downstream_data, DOWNSTREAM_DATA);
-VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_event, EVENT);
-
-static void vmmc_setup_fifos(struct vmmc *vmmc)
-{
-    mps_configure_mailbox(vmmc->mps, &vmmc->mbox_cmd,
-		&vmmc_fifo_config_upstream_cmd, &vmmc_fifo_config_downstream_cmd);
-    mps_configure_mailbox(vmmc->mps, &vmmc->mbox_data,
-		&vmmc_fifo_config_upstream_data, &vmmc_fifo_config_downstream_data);
-
-    mps_configure_fifo(vmmc->mps, &vmmc->fifo_event, &vmmc_fifo_config_event);
-}
-
-static uint32_t cram_data[] = {
-0x00200000, 0x00008e59, 0x165235cd, 0x17e2f141, 0xe3eef301, 0x0a431281,
-0x04fdf20d, 0x7fe363d5, 0xfd4b7333, 0x7ffffd44, 0xfcf80298, 0xfecd00c9,
-0xff900042, 0xfff70003, 0x000923b7, 0xe92a354d, 0xc8981f44, 0x9c0f1257,
-0x26aacf33, 0x27db9836, 0x10586f5b, 0x9c167d2d, 0x94b679a7, 0x8c227660,
-0x83fa7491, 0x7ce0826a, 0x7ff87ff4, 0x296b4e22, 0x76e67fff, 0x008ffc04,
-0x02cbfb36, 0x026afeba, 0x009effc3, 0x0013fffd, 0x23b7e92a, 0x354dc898,
-0x1f449c0f, 0x125726aa, 0xcf3327db, 0x98361058, 0x74bc93d6, 0x7ebc8f61,
-0x7d068986, 0x7b46833b, 0x7a3b7f00, 0x287a47b1, 0x05800367, 0x20ae2715,
-0x0fb5da12, 0x1935f53b, 0x01230240, 0xfc717f00, 0x2000d346,
-};
-
-static void vmmc_push_data_paket(struct vmmc *vmmc, int type, unsigned int chan,
-	void __iomem *addr, size_t len)
-{
-	uint32_t data[3];
-
-	data[0] = VMMC_VOICE_DATA(type, chan, 8);
-	data[1] = CPHYSADDR(addr);
-	data[2] = len;
-
-	mps_fifo_in(&vmmc->mbox_data.downstream, data, 3);
-}
-
-static struct sk_buff *vmmc_alloc_data_paket(struct vmmc *vmmc)
-{
-	struct sk_buff *skb;
-
-	skb = alloc_skb(512, GFP_KERNEL);
-
-	skb_queue_tail(&vmmc->recv_queue, skb);
-
-	return skb;
-}
-
-static void vmmc_provide_paket(struct vmmc *vmmc)
-{
-	struct sk_buff *skb = vmmc_alloc_data_paket(vmmc);
-	vmmc_push_data_paket(vmmc, CMD_ADDRESS_PACKET, 0, skb->data, skb->len);
-}
-
-static void vmmc_recv_paket(struct vmmc *vmmc, unsigned int chan, void __iomem *addr, size_t len)
-{
-	struct sk_buff *skb;
-	struct sk_buff *tmp;
-
-	skb_queue_walk_safe(&vmmc->recv_queue, skb, tmp) {
-		if (skb->data == addr)
-			break;
-	}
-
-	if (skb == (struct sk_buff *)(&vmmc->recv_queue)) {
-		printk("AHHHH\n");
-		return;
-	}
-
-	dma_cache_inv((u32)addr, len);
-	skb_unlink(skb, &vmmc->recv_queue);
-
-	if (!vmmc->coder[chan].stream) {
-		kfree_skb(skb);
-		return;
-	}
-
-	skb_put(skb, len);
-	tapi_stream_recv(&vmmc->tdev, vmmc->coder[chan].stream, skb);
-}
-
-void vmmc_send_paket(struct vmmc *vmmc, unsigned int chan, struct sk_buff *skb)
-{
-	skb_queue_tail(&vmmc->send_queue, skb);
-
-	dma_cache_wback((u32)skb->data, skb->len);
-	vmmc_push_data_paket(vmmc, CMD_RTP_VOICE_DATA_PACKET, chan, skb->data,
-		skb->len);
-}
-
-static void vmmc_free_paket(struct vmmc *vmmc, void __iomem *addr, size_t len)
-{
-	struct sk_buff *skb;
-	struct sk_buff *tmp;
-
-	skb_queue_walk_safe(&vmmc->send_queue, skb, tmp) {
-		if (skb->data == addr)
-			break;
-	}
-
-	if (skb == (struct sk_buff *)(&vmmc->send_queue)) {
-		printk("AHHHH\n");
-	} else {
-		skb_unlink(skb, &vmmc->send_queue);
-		kfree_skb(skb);
-	}
-}
-
-
-static void vmmc_write_cram_data(struct vmmc *vmmc, unsigned int id,
-	uint32_t *data, size_t length)
-{
-	size_t transfer_length;
-	size_t offset = 0;
-	uint32_t cmd;
-
-	length *= 4;
-	offset = 0x5;
-
-	while (length) {
-		transfer_length = length > 56 ? 56 : length;
-		cmd = VMMC_CMD_ALM_COEF(id, offset, transfer_length);
-		vmmc_command_write(vmmc, cmd, data);
-
-		data += transfer_length >> 2;
-		offset += transfer_length >> 1;
-		length -= transfer_length;
-	}
-}
-
-int vmmc_command_read(struct vmmc *vmmc, uint32_t cmd, uint32_t *result)
-{
-	struct mps_mailbox *mbox = &vmmc->mbox_cmd;
-
-	INIT_COMPLETION(vmmc->cmd_completion);
-
-	mps_fifo_in(&mbox->downstream, &cmd, 1);
-
-	wait_for_completion(&vmmc->cmd_completion);
-
-	mps_fifo_out(&mbox->upstream, result, 1);
-	mps_fifo_out(&mbox->upstream, result, (*result & 0xff) / 4);
-
-	return 0;
-}
-
-int vmmc_command_write(struct vmmc *vmmc, uint32_t cmd,
-	const uint32_t *data)
-{
-	struct mps_mailbox *mbox = &vmmc->mbox_cmd;
-/*	int i;
-
-	printk("cmd: %x\n", cmd);
-	for (i = 0; i < DIV_ROUND_UP((cmd & 0xff), 4); ++i) {
-		printk("data[%d] = %x\n", i, data[i]);
-	}
-*/
-	while (mps_fifo_len(&mbox->downstream) < (cmd & 0xff) + 4)
-		mdelay(100);
-
-	mps_fifo_in(&mbox->downstream, &cmd, 1);
-	mps_fifo_in(&mbox->downstream, data, DIV_ROUND_UP((cmd & 0xff), 4));
-
-	mdelay(100);
-
-	return 0;
-}
-
-static int vmmc_modules_sync(struct tapi_device *tapi)
-{
-	struct vmmc *vmmc = tdev_to_vmmc(tapi);
-	struct vmmc_module *module;
-
-	list_for_each_entry(module, &vmmc->modules, head)
-		vmmc_module_sync(module);
-
-	return 0;
-}
-
-static const struct tapi_ops vmmc_tapi_ops = {
-	.send_dtmf_event = vmmc_port_send_dtmf_event,
-	.ring = vmmc_port_ring,
-
-	.sync = vmmc_modules_sync,
-
-	.stream_alloc = vmmc_stream_alloc,
-	.stream_free = vmmc_stream_free,
-	.stream_send = vmmc_stream_send,
-
-	.link_alloc = vmmc_tapi_link_alloc,
-	.link_free = vmmc_tapi_link_free,
-	.link_enable = vmmc_tapi_link_enable,
-	.link_disable = vmmc_tapi_link_disable,
-};
-
-static void setup_alm(struct vmmc *vmmc)
-{
-	int i;
-
-	vmmc->tdev.ports = kcalloc(2, sizeof(*vmmc->tdev.ports), GFP_KERNEL);
-	vmmc->ports = kcalloc(2, sizeof(*vmmc->ports), GFP_KERNEL);
-
-	for (i = 0; i < 2; ++i)
-		vmmc_port_init(vmmc, &vmmc->ports[i], &vmmc->tdev.ports[i], i);
-
-	skb_queue_head_init(&vmmc->send_queue);
-	skb_queue_head_init(&vmmc->recv_queue);
-
-	for (i = 0; i < 10; ++i)
-		vmmc_provide_paket(vmmc);
-
-	vmmc->tdev.num_ports = 2;
-	vmmc->tdev.ops = &vmmc_tapi_ops;
-	tapi_device_register(&vmmc->tdev, "vmmc", vmmc->dev);
-}
-
-static void vmmc_init_timer(struct vmmc *vmmc)
-{
-	unsigned int timer;
-	unsigned int timer_flags;
-	int ret;
-	unsigned long loops, count;
-
-	timer = TIMER1B;
-
-	timer_flags =
-	  TIMER_FLAG_16BIT | TIMER_FLAG_COUNTER | TIMER_FLAG_CYCLIC |
-	  TIMER_FLAG_DOWN | TIMER_FLAG_FALL_EDGE | TIMER_FLAG_SYNC |
-	  TIMER_FLAG_CALLBACK_IN_IRQ;
-	ret = ifxmips_request_timer (timer, timer_flags, 1, 0, 0);
-	if (ret < 0) {
-		printk("FAILED TO INIT TIMER\n");
-		return;
-	}
-	ret = ifxmips_start_timer (timer, 0);
-	if (ret < 0) {
-		printk("FAILED TO START TIMER\n");
-		return;
-	}
-	do
-	{
-		loops++;
-		ifxmips_get_count_value(timer, &count);
-	} while (count);
-
-	*((volatile uint32_t *) (KSEG1 + 0x1e100a00 + 0x0014)) = 0x000005c5;
-}
-
-static void vmmc_free_timer(struct vmmc *vmmc)
-{
-	ifxmips_free_timer(TIMER1B);
-}
-
-static void vmmc_get_capabilities(struct vmmc *vmmc)
-{
-	uint32_t data[10];
-	uint8_t len;
-
-	vmmc_command_read(vmmc,
-		MPS_MSG_CMD_EOP_SYSTEM(SYS_CAP_ECMD, sizeof(uint32_t)), data);
-
-	len = ((data[0] >> 16) & 0xff) - sizeof(uint32_t);
-
-	if (len > sizeof(data))
-		len = sizeof(data);
-
-	vmmc_command_read(vmmc,
-		MPS_MSG_CMD_EOP_SYSTEM(SYS_CAP_ECMD, len), data);
-
-	len /= 4;
-
-/*	for (;len > 0; --len) {
-		printk("fw cap(%d): %.2x\n", 10-len, data[10-len]);
-	}
-*/
-	setup_alm(vmmc);
-}
-
-static void vmmc_get_firmware_version(struct vmmc *vmmc)
-{
-	uint32_t data[1];
-
-	vmmc_command_read(vmmc, MPS_CMD_GET_VERSION, data);
-
-	printk("firmware version: %x\n", *data);
-
-	vmmc_get_capabilities(vmmc);
-}
-
-static irqreturn_t vmmc_firmware_loaded_irq(int irq, void *devid)
-{
-	struct vmmc *vmmc = devid;
-	complete(&vmmc->firmware_loaded_completion);
-	printk("Firmware loaded irq\n");
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t vmmc_cmd_error_irq(int irq, void *devid)
-{
-/*	struct vmmc *vmmc = devid;*/
-
-	printk("cmd error!!!!\n");
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t vmmc_recv_ov_irq(int irq, void *devid)
-{
-	struct vmmc *vmmc = devid;
-	uint32_t data[2] = {
-		VMMC_CMD_SERR_ACK(0),
-		VMMC_CMD_SERR_ACK_DATA1(1)
-	};
-	uint32_t voice_data[64];
-
-	return IRQ_HANDLED;
-
-	mps_fifo_in(&vmmc->mbox_cmd.downstream, data, 2);
-	mps_fifo_out(&vmmc->mbox_data.upstream, voice_data, 15);
-
-	printk("recv overflow: %x\n", voice_data[0]);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t vmmc_event_fifo_irq(int irq, void *devid)
-{
-	struct vmmc *vmmc = devid;
-	uint32_t event, event_id;
-	uint32_t data = 0;
-	unsigned int chan;
-
-	mps_fifo_out(&vmmc->fifo_event, &event, 1);
-
-	event_id = event & VMMC_EVENT_ID_MASK;
-	chan = VMMC_MSG_GET_CHAN(event);
-
-	if (event & 0xff)
-		mps_fifo_out(&vmmc->fifo_event, &data, 1);
-
-	switch (event_id) {
-	case VMMC_EVENT_HOOK_ID:
-		vmmc_alm_hook_event_handler(vmmc, chan, data);
-		break;
-	case VMMC_EVENT_DTMF_ID:
-		vmmc_sig_dtmf_event_handler(vmmc, chan, data);
-		break;
-	default:
-		printk("Ein unbekanntes Event: %x %x\n", event, data);
-		break;
-	}
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t vmmc_mbox_data_irq_handler(int irq, void *devid)
-{
-	struct vmmc *vmmc = devid;
-	struct mps_mailbox *mbox = &vmmc->mbox_data;
-	unsigned int count, type, chan;
-	uint32_t data[2];
-	void __iomem *addr;
-	size_t len;
-
-	mps_fifo_out(&mbox->upstream, data, 1);
-
-	count = (data[0] & 0xff) / 8;
-	type = (data[0] >> 24) & 0xff;
-	chan = (data[0] >> 16) & 0xff;
-
-	while (count) {
-		mps_fifo_out(&mbox->upstream, data, 2);
-
-		addr = (void __iomem *)CKSEG0ADDR(data[0]);
-		len = data[1];
-
-		switch (type) {
-		case CMD_ADDRESS_PACKET:
-			vmmc_free_paket(vmmc, addr, len);
-			break;
-		case CMD_RTP_VOICE_DATA_PACKET:
-			vmmc_provide_paket(vmmc);
-			vmmc_recv_paket(vmmc, chan, addr, len);
-			break;
-		}
-		--count;
-	}
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t vmmc_mbox_cmd_irq_handler(int irq, void *devid)
-{
-	struct vmmc *vmmc = devid;
-
-	complete(&vmmc->cmd_completion);
-
-	return IRQ_HANDLED;
-}
-
-static void vmmc_load_firmware(const struct firmware *fw, void *context)
-{
-	struct vmmc *vmmc = context;
-	struct vmmc_firmware_head *fw_head;
-	size_t tail_size;
-	enum mps_boot_config config;
-
-	if (!fw) {
-		printk("failed to load tapi firmware\n");
-//		request_firmware_nowait(THIS_MODULE, 1, "danube_firmware.bin", vmmc->dev,
-//			GFP_KERNEL, vmmc, vmmc_load_firmware);
-		return;
-	}
-
-	if (fw->size < sizeof(*fw_head))
-		return;
-
-	fw_head = (struct vmmc_firmware_head *)((uint8_t *)fw->data + fw->size - sizeof(*fw_head));
-
-	if (fw_head->magic != MPS_FIRMWARE_MAGIC) {
-		config = MPS_BOOT_LEGACY;
-		tail_size = sizeof(uint32_t);
-	} else {
-		config = MPS_BOOT_ENCRYPTED;
-		tail_size = sizeof(*fw_head) - sizeof(uint32_t);
-	}
-
-	vmmc_setup_fifos(vmmc);
-	init_completion(&vmmc->firmware_loaded_completion);
-	mps_load_firmware(vmmc->mps, fw->data, fw->size - tail_size, config);
-	wait_for_completion_timeout(&vmmc->firmware_loaded_completion, 5*HZ);
-	vmmc_init_timer(vmmc);
-	vmmc_write_cram_data(vmmc, 0, cram_data, ARRAY_SIZE(cram_data));
-	vmmc_write_cram_data(vmmc, 1, cram_data, ARRAY_SIZE(cram_data));
-	vmmc_get_firmware_version(vmmc);
-	vmmc_init_coders(vmmc);
-}
-
-static int vmmc_request_irqs(struct vmmc *vmmc)
-{
-	int ret;
-
-	ret = request_irq(vmmc->irq_fw_loaded, vmmc_firmware_loaded_irq, 0, "vmmc fw loaded", vmmc);
-	ret = request_irq(vmmc->irq_event_fifo, vmmc_event_fifo_irq, 0, "vmmc event fifo", vmmc);
-	ret = request_irq(vmmc->irq_cmd_error, vmmc_cmd_error_irq, 0,
-		"cmd error irq", vmmc);
-	ret = request_irq(MPS_IRQ_RCV_OVERFLOW, vmmc_recv_ov_irq, 0,
-		"recv_ov irq", vmmc);
-
-	ret = request_irq(vmmc->irq_mbox_cmd, vmmc_mbox_cmd_irq_handler, 0,
-		"vmmc cmd mailbox irq", vmmc);
-
-	ret = request_irq(vmmc->irq_mbox_data, vmmc_mbox_data_irq_handler, 0,
-		"vmmc data mailbox irq", vmmc);
-
-	return ret;
-}
-
-static int __devinit vmmc_probe(struct platform_device *pdev)
-{
-	struct vmmc *vmmc;
-	int ret = 0;
-
-	vmmc = kzalloc(sizeof(*vmmc), GFP_KERNEL);
-
-	if (!vmmc)
-		return -ENOMEM;
-
-	vmmc->dev = &pdev->dev;
-	vmmc->mps = device_to_mps(pdev->dev.parent);
-
-	if (!vmmc->mps) {
-		goto err_free;
-		ret = -EBUSY;
-	}
-
-	INIT_LIST_HEAD(&vmmc->modules);
-	init_completion(&vmmc->cmd_completion);
-
-	vmmc->irq_fw_loaded = MPS_IRQ_DOWNLOAD_DONE;
-	vmmc->irq_mbox_cmd = MPS_IRQ_CMD_UPSTREAM;
-	vmmc->irq_mbox_data = MPS_IRQ_DATA_UPSTREAM;
-	vmmc->irq_event_fifo = MPS_IRQ_EVENT;
-	vmmc->irq_cmd_error = MPS_IRQ_CMD_ERROR;
-
-	platform_set_drvdata(pdev, vmmc);
-
-	vmmc_request_irqs(vmmc);
-
-	request_firmware_nowait(THIS_MODULE, 1, "danube_firmware.bin", &pdev->dev,
-		GFP_KERNEL, vmmc, vmmc_load_firmware);
-
-	return 0;
-
-err_free:
-	kfree(vmmc);
-
-	return ret;
-}
-
-static int __devexit vmmc_remove(struct platform_device *pdev)
-{
-	struct vmmc *vmmc = platform_get_drvdata(pdev);
-	vmmc_free_timer(vmmc);
-
-	tapi_device_unregister(&vmmc->tdev);
-
-	return 0;
-}
-
-static struct platform_driver vmmc_driver = {
-	.probe = vmmc_probe,
-	.remove = __devexit_p(vmmc_remove),
-	.driver = {
-		.name = "vmmc",
-		.owner = THIS_MODULE
-	},
-};
-
-static int __init vmmc_init(void)
-{
-	return platform_driver_register(&vmmc_driver);
-}
-module_init(vmmc_init);
-
-static void __exit vmmc_exit(void)
-{
-	platform_driver_unregister(&vmmc_driver);
-}
-module_exit(vmmc_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Lars-Peter Clausen <[email protected]>");

+ 0 - 52
package/lqtapi/src/mps/vmmc-link.c

@@ -1,52 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/tapi/tapi.h>
-
-#include "vmmc-link.h"
-#include "vmmc-module.h"
-
-struct vmmc_tapi_link {
-	struct tapi_link tapi_link;
-	struct vmmc_link vmmc_link;
-};
-
-struct tapi_link *vmmc_tapi_link_alloc(struct tapi_device *tdev,
-	struct tapi_endpoint *ep1, struct tapi_endpoint *ep2)
-{
-	struct vmmc_tapi_link *link = kzalloc(sizeof(*link), GFP_KERNEL);
-	struct vmmc_module *module1 = tapi_endpoint_to_vmmc_module(ep1);
-	struct vmmc_module *module2 = tapi_endpoint_to_vmmc_module(ep2);
-
-	vmmc_link_init(&link->vmmc_link, module1, module2);
-
-	return &link->tapi_link;
-}
-
-void vmmc_tapi_link_free(struct tapi_device *tdev, struct tapi_link *tapi_link)
-{
-	struct vmmc_tapi_link *link = container_of(tapi_link, struct vmmc_tapi_link,
-		tapi_link);
-
-	vmmc_link_put(&link->vmmc_link);
-	kfree(link);
-}
-
-int vmmc_tapi_link_enable(struct tapi_device *tdev,
-	struct tapi_link *tapi_link)
-{
-	struct vmmc_tapi_link *link = container_of(tapi_link, struct vmmc_tapi_link,
-		tapi_link);
-
-	vmmc_link_enable(&link->vmmc_link);
-	return 0;
-}
-
-int vmmc_tapi_link_disable(struct tapi_device *tdev,
-	struct tapi_link *tapi_link)
-{
-	struct vmmc_tapi_link *link = container_of(tapi_link, struct vmmc_tapi_link,
-		tapi_link);
-
-	vmmc_link_disable(&link->vmmc_link);
-	return 0;
-}

+ 0 - 10
package/lqtapi/src/mps/vmmc-link.h

@@ -1,10 +0,0 @@
-#ifndef __VMMC_LINK_H__
-#define __VMMC_LINK_H__
-
-struct tapi_link *vmmc_tapi_link_alloc(struct tapi_device *tdev,
-	struct tapi_endpoint *ep1, struct tapi_endpoint *ep2);
-void vmmc_tapi_link_free(struct tapi_device *tdev, struct tapi_link *link);
-int vmmc_tapi_link_enable(struct tapi_device *tdev, struct tapi_link *link);
-int vmmc_tapi_link_disable(struct tapi_device *tdev, struct tapi_link *link);
-
-#endif

+ 0 - 130
package/lqtapi/src/mps/vmmc-module.c

@@ -1,130 +0,0 @@
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-
-#include <asm/bitops.h>
-
-#include "vmmc-module.h"
-
-int vmmc_module_init(struct vmmc_module *module, size_t num_pins,
-	const struct vmmc_module_ops *ops)
-{
-	module->pins = kcalloc(num_pins, sizeof(*module->pins), GFP_KERNEL);
-
-	if (!module->pins)
-		return -ENOMEM;
-
-	module->num_pins = num_pins;
-	module->ops = ops;
-
-	mutex_init(&module->lock);
-	module->refcount = 0;
-
-	return 0;
-}
-
-int vmmc_module_sync(struct vmmc_module *module)
-{
-	if (!test_and_clear_bit(VMMC_MODULE_FLAG_MODIFIED, &module->flags))
-		return 0;
-
-	return module->ops->sync(module);
-}
-
-int vmmc_module_get_pin(struct vmmc_module *module)
-{
-	size_t i = 0;
-	int ret = 0;
-
-	for (i = 0; i < module->num_pins; ++i) {
-		if (!test_and_set_bit(VMMC_MODULE_FLAG_PIN_USED(i), &module->flags))
-			break;
-	}
-	if (i == module->num_pins)
-		ret = -EBUSY;
-	else
-		ret = i;
-
-	return ret;
-}
-
-void vmmc_module_put_pin(struct vmmc_module *module, unsigned int pin)
-{
-	module->pins[pin] = 0;
-	clear_bit(VMMC_MODULE_FLAG_PIN_USED(pin), &module->flags);
-}
-
-void vmmc_module_set_pin_input(struct vmmc_module *module, unsigned int pin,
-	struct vmmc_module *input)
-{
-	if (input)
-		module->pins[pin] = input->id;
-	else
-		module->pins[pin] = 0;
-
-	set_bit(VMMC_MODULE_FLAG_MODIFIED, &module->flags);
-}
-
-static void vmmc_module_enable(struct vmmc_module *module)
-{
-	mutex_lock(&module->lock);
-
-	if (++module->refcount == 1)
-		module->ops->enable(module, true);
-
-	mutex_unlock(&module->lock);
-}
-
-static void vmmc_module_disable(struct vmmc_module *module)
-{
-	mutex_lock(&module->lock);
-
-	if (module->refcount <= 0)
-		printk(KERN_ERR "vmmc module: unbalanced disable\n");
-	else if (--module->refcount == 0)
-		module->ops->enable(module, false);
-
-	mutex_unlock(&module->lock);
-}
-
-
-unsigned int vmmc_link_init(struct vmmc_link *link,
-	struct vmmc_module *a, struct vmmc_module *b)
-{
-	link->pins[0] = vmmc_module_get_pin(a);
-	link->pins[1] = vmmc_module_get_pin(b);
-	link->modules[0] = a;
-	link->modules[1] = b;
-
-	return 0;
-}
-
-void vmmc_link_put(struct vmmc_link *link)
-{
-	vmmc_link_disable(link);
-	vmmc_module_sync(link->modules[0]);
-	vmmc_module_sync(link->modules[1]);
-	vmmc_module_put_pin(link->modules[0], link->pins[0]);
-	vmmc_module_put_pin(link->modules[1], link->pins[1]);
-}
-
-void vmmc_link_enable(struct vmmc_link *link)
-{
-	vmmc_module_set_pin_input(link->modules[0], link->pins[0],
-		link->modules[1]);
-	vmmc_module_set_pin_input(link->modules[1], link->pins[1],
-		link->modules[0]);
-
-	vmmc_module_enable(link->modules[0]);
-	vmmc_module_enable(link->modules[1]);
-}
-
-void vmmc_link_disable(struct vmmc_link *link)
-{
-	vmmc_module_set_pin_input(link->modules[0], link->pins[0], NULL);
-	vmmc_module_set_pin_input(link->modules[1], link->pins[1], NULL);
-
-	vmmc_module_disable(link->modules[0]);
-	vmmc_module_disable(link->modules[1]);
-}

+ 0 - 64
package/lqtapi/src/mps/vmmc-module.h

@@ -1,64 +0,0 @@
-#ifndef __VMMC_MODULE_H__
-#define __VMMC_MODULE_H__
-
-#include <linux/list.h>
-#include <linux/kernel.h>
-#include <linux/tapi/tapi.h>
-
-struct vmmc_module;
-
-struct vmmc_module_ops {
-	int (*sync)(struct vmmc_module *);
-	int (*enable)(struct vmmc_module *, bool enable);
-};
-
-struct vmmc_module
-{
-	unsigned int id;
-
-	size_t num_pins;
-	unsigned int *pins;
-
-	const struct vmmc_module_ops *ops;
-
-	unsigned long flags;
-#define VMMC_MODULE_FLAG_PIN_USED(x) (x)
-#define VMMC_MODULE_FLAG_MODIFIED 31
-	struct mutex lock;
-	struct list_head head;
-
-	unsigned int refcount;
-};
-
-int vmmc_module_init(struct vmmc_module *module, size_t num_pins,
-	const struct vmmc_module_ops *ops);
-int vmmc_module_sync(struct vmmc_module *module);
-
-struct vmmc_link {
-	struct vmmc_module *modules[2];
-	unsigned int pins[2];
-};
-
-struct vmmc_endpoint {
-	struct tapi_endpoint ep;
-	struct vmmc_module *module;
-};
-
-void vmmc_link_enable(struct vmmc_link *link);
-void vmmc_link_disable(struct vmmc_link *link);
-unsigned int vmmc_link_init(struct vmmc_link *link, 
-	struct vmmc_module *a, struct vmmc_module *b);
-void vmmc_link_put(struct vmmc_link *link);
-
-int vmmc_module_get_pin(struct vmmc_module *module);
-void vmmc_module_put_pin(struct vmmc_module *module, unsigned int pin);
-void vmmc_module_set_pin_input(struct vmmc_module *module, unsigned int pin,
-	struct vmmc_module *input);
-
-
-static inline struct vmmc_module *tapi_endpoint_to_vmmc_module(struct tapi_endpoint *ep)
-{
-	return tapi_endpoint_get_data(ep);
-}
-
-#endif

+ 0 - 48
package/lqtapi/src/mps/vmmc-port.c

@@ -1,48 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/slab.h>
-
-#include <linux/tapi/tapi.h>
-
-#include "vmmc.h"
-#include "vmmc-port.h"
-#include "vmmc-alm.h"
-#include "vmmc-sig.h"
-
-int vmmc_port_ring(struct tapi_device *tdev, struct tapi_port *port, bool ring)
-{
-	struct vmmc *vmmc = tdev_to_vmmc(tdev);
-
-	return vmmc_alm_set_state(&vmmc->ports[port->id].alm,
-		ring ? VMMC_ALM_STATE_RING : VMMC_ALM_STATE_ONHOOK);
-}
-
-int vmmc_port_send_dtmf_event(struct tapi_device *tdev,
-	struct tapi_port *port, struct tapi_dtmf_event *event)
-{
-	return 0;
-}
-
-struct vmmc_port *vmmc_port_init(struct vmmc *vmmc, struct vmmc_port *port,
-	struct tapi_port *tport, unsigned int id)
-{
-	vmmc_alm_init(&port->alm, vmmc, id);
-	vmmc_sig_init(&port->sig, vmmc, id);
-
-	port->sig_pin = vmmc_module_get_pin(&port->sig.module);
-	vmmc_module_set_pin_input(&port->sig.module, port->sig_pin,
-		&port->alm.module);
-
-	vmmc_module_sync(&port->sig.module);
-
-	vmmc_alm_set_state(&port->alm, VMMC_ALM_STATE_ONHOOK);
-
-	tport->id = id;
-	tapi_endpoint_set_data(&tport->ep, &port->alm.module);
-
-	return port;
-}
-
-void vmmc_port_put(struct vmmc *vmmc, struct vmmc_port *port)
-{
-	vmmc_module_put_pin(&port->sig.module, port->sig_pin);
-}

+ 0 - 22
package/lqtapi/src/mps/vmmc-port.h

@@ -1,22 +0,0 @@
-#ifndef __VMMC_PORT_H__
-#define __VMMC_PORT_H__
-
-#include "vmmc-alm.h"
-#include "vmmc-sig.h"
-
-void vmmc_port_free(struct vmmc *vmmc, struct vmmc_port *port);
-
-int vmmc_port_ring(struct tapi_device *tdev, struct tapi_port *port, bool ring);
-int vmmc_port_send_dtmf_event(struct tapi_device *tdev,
-	struct tapi_port *port, struct tapi_dtmf_event *event);
-struct vmmc_port *vmmc_port_init(struct vmmc *vmmc, struct vmmc_port *port,
-struct tapi_port *tport, unsigned int id);
-
-struct vmmc_port
-{
-	struct vmmc_alm alm;
-	struct vmmc_sig sig;
-	unsigned int sig_pin;
-};
-
-#endif

+ 0 - 19
package/lqtapi/src/mps/vmmc-sig.h

@@ -1,19 +0,0 @@
-#ifndef __VMMC_SIG_H__
-#define __VMMC_SIG_H__
-
-#include "vmmc-module.h"
-
-struct vmmc_sig {
-	struct vmmc *vmmc;
-	unsigned int id;
-	struct vmmc_module module;
-
-	uint32_t sig_cache;
-	uint32_t dtmfr_cache;
-};
-
-int vmmc_sig_init(struct vmmc_sig *sig, struct vmmc *vmmc, unsigned int id);
-
-void vmmc_sig_dtmf_event_handler(struct vmmc *vmmc, uint32_t event, uint32_t data);
-
-#endif

+ 0 - 69
package/lqtapi/src/mps/vmmc-signal.c

@@ -1,69 +0,0 @@
-#include <linux/kernel.h>
-
-#include "vmmc.h"
-#include "vmmc-sig.h"
-#include "vmmc-cmds.h"
-
-static struct vmmc_sig *vmmc_module_to_sig(struct vmmc_module *module)
-{
-	return container_of(module, struct vmmc_sig, module);
-}
-
-static int vmmc_sig_enable(struct vmmc_module *module, bool enabled)
-{
-	struct vmmc_sig *sig = vmmc_module_to_sig(module);
-
-	return 0;
-
-	sig->sig_cache = VMMC_CMD_SIG_SET_ENABLE(sig->sig_cache, enabled);
-
-	return vmmc_command_write(sig->vmmc, VMMC_CMD_SIG(sig->id), &sig->sig_cache);
-}
-
-static int vmmc_sig_sync(struct vmmc_module *module)
-{
-	struct vmmc_sig *sig = vmmc_module_to_sig(module);
-
-	sig->sig_cache = VMMC_CMD_SIG_SET_INPUTS(sig->sig_cache,
-		module->pins[0], module->pins[1]);
-
-	vmmc_command_write(sig->vmmc, VMMC_CMD_SIG(sig->id),
-		&sig->sig_cache);
-
-	return vmmc_command_write(sig->vmmc, VMMC_CMD_DTMFR(sig->id),
-		&sig->dtmfr_cache);
-}
-
-static const struct vmmc_module_ops vmmc_sig_ops = {
-	.enable = vmmc_sig_enable,
-	.sync = vmmc_sig_sync,
-};
-
-int vmmc_sig_init(struct vmmc_sig *sig, struct vmmc *vmmc, unsigned int id)
-{
-	int ret;
-
-	ret = vmmc_module_init(&sig->module, 2, &vmmc_sig_ops);
-	if (ret)
-		return ret;
-
-	sig->id = id;
-	sig->module.id = id + 0x1e;
-	sig->vmmc = vmmc;
-	sig->sig_cache = VMMC_CMD_SIG_DATA(1, 1, 0, 0, 0, 0, 0);
-	sig->dtmfr_cache = VMMC_CMD_DTMFR_DATA(1, 1, id);
-
-	vmmc_register_module(vmmc, &sig->module);
-
-	vmmc_command_write(sig->vmmc, VMMC_CMD_SIG(sig->id),
-		&sig->sig_cache);
-	vmmc_command_write(sig->vmmc, VMMC_CMD_DTMFR(sig->id),
-		&sig->dtmfr_cache);
-
-	return ret;
-}
-
-void vmmc_sig_dtmf_event_handler(struct vmmc *vmmc, uint32_t id, uint32_t data)
-{
-	tapi_report_dtmf_event(&vmmc->tdev, &vmmc->tdev.ports[id], data & 0xf);
-}

+ 0 - 73
package/lqtapi/src/mps/vmmc-stream.c

@@ -1,73 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/tapi/tapi.h>
-#include <linux/skbuff.h>
-
-#include "vmmc.h"
-#include "vmmc-coder.h"
-
-struct vmmc_tapi_stream {
-	struct vmmc_coder *coder;
-	struct tapi_stream stream;
-};
-
-struct vmmc_tapi_stream *tapi_to_vmmc_stream(struct tapi_stream * stream)
-{
-	return container_of(stream, struct vmmc_tapi_stream, stream);
-}
-
-struct tapi_stream *vmmc_stream_alloc(struct tapi_device *tdev)
-{
-	struct vmmc *vmmc = tdev_to_vmmc(tdev);
-	struct vmmc_tapi_stream *stream;
-	struct vmmc_coder *coder;
-
-	coder = vmmc_coder_get(vmmc);
-	if (!coder)
-		return ERR_PTR(-ENODEV);
-
-	stream = kzalloc(sizeof(*stream), GFP_KERNEL);
-	if (!stream)
-		return ERR_PTR(-ENOMEM);
-
-	stream->coder = coder;
-	coder->stream = &stream->stream;
-	tapi_endpoint_set_data(&stream->stream.ep, &coder->module);
-
-	return &stream->stream;
-}
-
-void vmmc_stream_free(struct tapi_device *tdev, struct tapi_stream *tstream)
-{
-	struct vmmc *vmmc = tdev_to_vmmc(tdev);
-	struct vmmc_tapi_stream *stream = tapi_to_vmmc_stream(tstream);
-
-	stream->coder->stream = NULL;
-
-	vmmc_coder_put(vmmc, stream->coder);
-	kfree(stream);
-}
-
-int vmmc_stream_start(struct tapi_device *tdev, struct tapi_stream *stream)
-{
-	return 0;
-}
-
-int vmmc_stream_stop(struct tapi_device *tdev, struct tapi_stream *stream)
-{
-	return 0;
-}
-
-int vmmc_stream_send(struct tapi_device *tdev, struct tapi_stream *stream,
-	struct sk_buff *skb)
-{
-	struct vmmc *vmmc = tdev_to_vmmc(tdev);
-	struct vmmc_coder *coder = tapi_to_vmmc_stream(stream)->coder;
-
-	vmmc_send_paket(vmmc, coder->id, skb);
-	return 0;
-}
-/*
-int vmmc_stream_recv(struct vmmc_stream *stream)
-{
-	tapi_stream_recv(&stream->coder->vmmc->tdev stream->stream, skb);
-}*/

+ 0 - 10
package/lqtapi/src/mps/vmmc-stream.h

@@ -1,10 +0,0 @@
-#ifndef __VMMC_STREAM_H__
-#define __VMMC_STREAM_H__
-
-struct tapi_stream *vmmc_stream_alloc(struct tapi_device *tdev);
-void vmmc_stream_free(struct tapi_device *tdev, struct tapi_stream *stream);
-int vmmc_stream_start(struct tapi_device *tdev, struct tapi_stream *stream);
-int vmmc_stream_send(struct tapi_device *tdev, struct tapi_stream *stream,
-	struct sk_buff *skb);
-
-#endif

+ 0 - 90
package/lqtapi/src/mps/vmmc.c

@@ -1,90 +0,0 @@
-static uint32_t magic_init[] = {
-/* ALI INIT */
-/*0x0601210c, 0x88002000, 0x20000000, 0x00000000, 0xffffffff,*/
-/* COD_CHAN_SPEECH_ECMD */
-/*0x06016110, 0x2462f700, 0x20002000, 0x00000000, 0x00000000, 0xffffffff,*/
-/* COD_DEC_STAT_ECMD */
-/*0x06017504, 0x00c00000, 0xffffffff,*/
-/* COD_JB_CONF_ECMD */
-/*0x06017208, 0x16410050, 0x005005a0, 0xffffffff,*/
-/* SIG_RTP_SUP */
-/*0x0601500c, 0x00000000, 0x00000060, 0x0712007f, 0xffffffff,*/
-/* SIG_CHAN */
-/*0x06014104, 0xc0190000, 0xffffffff,*/
-/* SIG_CIDS_CTRL_ECMD */
-/*0x06014204, 0x3811e000, 0xffffffff, */
-/* SIG_DTMFATG_DATA */
-/*0x06014b04, 0x00010000, 0xffffffff,*/
-/* SIG_DTMFATG_CTRL */
-/*0x06014304, 0x6a110000, 0xffffffff,
-0x0601cc04, 0xe21c2000, 0xffffffff,
-0x06014404, 0xb0110000, 0xffffffff,
-0x06014a04, 0x04510000, 0xffffffff,
-0x06014604, 0x04560000, 0xffffffff,
-0x06014104, 0xc0190000, 0xffffffff,*/
-/* COD_CHAN_RTP_SUP_CFG_USD */
-/*0x06017124, 0x00000000, 0x00008880, 0xe3e4e5e6, 0x72727272, 0x72727272,
-0x0f7f1261, 0x7374097f, 0xf1f06767, 0x04047675, 0xffffffff,*/
-/* COD_CHAN_RTP_SUP_CFG_DS */
-/* 0x06017920, 0x08006364, 0x65667272, 0x72727272, 0x72720f7f, 0x12617374,
-0x097f7170, 0x67670404, 0x76750000, 0xffffffff, */
-/* OPMODE_CMD */
-0x01010004, 0x00010000, 0xffffffff,
-0x01000004, 0x00030000, 0xffffffff,
-/*0x01010004, 0x00010000, 0xffffffff,*/
-/* COD_CHAN_RTP_SUP_CFG_US */
-/* 0x06017124, 0x00000000, 0x00008880, 0xe3e4e5e6, 0x72727272, 0x72727272,
-0x0f7f1261, 0x7374097f, 0xf1f06767, 0x04047675, 0xffffffff, */
-/* COD_CHAN_RTP_SUP_CFG_DS */
-/* 0x06017920, 0x08006364, 0x65667272, 0x72727272, 0x72720f7f, 0x12617374,
-0x097f7170, 0x67670404, 0x76750000, 0xffffffff, */
-/* COD_JB_CONF */
-/* 0x06017208, 0x16410050, 0x005005a0, 0xffffffff, */
-/* COD_CHAN_RTP_SUP_CFG_US */
-/*0x06017108, 0x00000000, 0x00008880, 0xffffffff,*/
-/* COD_CHAN_RTP_TIMESTAMP */
-/*0x06017004, 0x00000000, 0xffffffff,*/
-/* SIG_RTP_SUP */
-/* 0x0601500c, 0x00000000, 0x00000062, 0x0712007f, 0xffffffff,*/
-/* SIG_DTMFR_CTRL */
-/*0x06014404, 0xb0010000, 0xffffffff,*/
-/* COD_CHAN_SPEECH */
-/* 0x06016110, 0x0462d600, 0x20002000, 0x00000000, 0x00000000, 0xffffffff, */
-/* ALI_CHAN */
-0x0601210c, 0x88232000, 0x20000000, 0x00000000, 0xffffffff,
-/* SIG_CHAN */
-/*0x06014104, 0xc5190000, 0xffffffff,*/
-/* SIG_DTMFR_CTRL_ECMD */
-/*0x06014404, 0x30010000, 0xffffffff,*/
-/* SIG_CHAN_ECMD */
-/*0x06014104, 0x45190000, 0xffffffff,*/
-};
-
-static void setup_alm(struct mps *mps, int chan)
-{
-	uint32_t *data = magic_init;
-	int size, i;
-
-/*	data[0] = ALI_CHAN_DATA1(1, 0, 0, 1, 1, 0, 0);
-	data[1] = ALI_CHAN_DATA2(0, 0, 0);
-	data[2] = ALI_CHAN_DATA3(0, 0);*/
-
-	size = 1;
-	for (i = 1; i < ARRAY_SIZE(magic_init); ++i) {
-		if (magic_init[i] == 0xffffffff) {
-
-			printk("cmd: %x\n", *data);
-			VMMC_FIFO_fifo_in(&mps->mbox_cmd.downstream, data, size);
-			size = 0;
-			data = &magic_init[i+1];
-			mdelay(500);
-		} else {
-			size += 1;
-		}
-	}
-
-
-/*	VMMC_FIFO_mailbox_command_write(&mps->mbox_cmd, MPS_CMD_ALI(chan), data);*/
-}
-
-

+ 0 - 68
package/lqtapi/src/mps/vmmc.h

@@ -1,68 +0,0 @@
-#ifndef __VMMC_H__
-
-#include <linux/list.h>
-#include <linux/tapi/tapi.h>
-
-#include "mps.h"
-#include "vmmc-module.h"
-
-struct vmmc
-{
-	struct mps *mps;
-	struct device *dev;
-
-	struct vmmc_port *ports;
-
-	struct completion firmware_loaded_completion;
-	struct completion cmd_completion;
-
-	struct mps_mailbox mbox_cmd;
-	struct mps_mailbox mbox_data;
-	struct mps_fifo fifo_event;
-
-	int irq_fw_loaded;
-	int irq_mbox_cmd;
-	int irq_mbox_data;
-	int irq_event_fifo;
-	int irq_cmd_error;
-
-	unsigned int num_coders;
-	struct vmmc_coder *coder;
-	unsigned long coder_used;
-
-	struct list_head modules;
-
-	struct tapi_device tdev;
-
-	struct sk_buff_head recv_queue;
-	struct sk_buff_head send_queue;
-};
-
-static inline struct vmmc *tdev_to_vmmc(struct tapi_device *tdev)
-{
-	return container_of(tdev, struct vmmc, tdev);
-}
-
-static inline void vmmc_register_module(struct vmmc *vmmc,
-	struct vmmc_module *module)
-{
-	list_add_tail(&module->head, &vmmc->modules);
-}
-
-static inline void vmmc_unregister_module(struct vmmc *vmmc,
-	struct vmmc_module *module)
-{
-	list_del(&module->head);
-}
-
-int vmmc_command_write(struct vmmc *vmmc, uint32_t cmd,
-	const uint32_t *data);
-int vmmc_command_read(struct vmmc *vmmc, uint32_t cmd, uint32_t *result);
-
-struct vmmc_coder *vmmc_coder_get(struct vmmc *);
-void vmmc_coder_put(struct vmmc *, struct vmmc_coder *);
-void vmmc_init_coders(struct vmmc *);
-
-void vmmc_send_paket(struct vmmc *vmmc, unsigned int chan, struct sk_buff *skb);
-
-#endif

+ 0 - 7
package/lqtapi/src/tapi/Makefile

@@ -1,7 +0,0 @@
-
-tapi-objs := tapi-core.o tapi-port.o tapi-input.o
-tapi-objs += tapi-control.o
-tapi-objs += tapi-stream.o
-tapi-objs += tapi-sysfs-port.o
-
-obj-m += tapi.o

+ 0 - 193
package/lqtapi/src/tapi/tapi-control.c

@@ -1,193 +0,0 @@
-#include <linux/cdev.h>
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/list.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include <linux/tapi/tapi.h>
-#include <linux/tapi/tapi-ioctl.h>
-
-/* FIXME Does it acutally make sense to allow more then one application at a
- * time to open the control device? For example calling sync from one app will
- * also sync all others. */
-
-struct tapi_control_file {
-	struct tapi_device *tdev;
-	struct list_head links;
-};
-
-static struct tapi_endpoint *tapi_lookup_endpoint(struct tapi_device *tdev,
-	unsigned int ep_id)
-{
-	struct tapi_stream *stream;
-
-	if (ep_id < tdev->num_ports)
-		return &tdev->ports[ep_id].ep;
-
-	list_for_each_entry(stream, &tdev->streams, head) {
-		if (stream->ep.id == ep_id)
-			return &stream->ep;
-	}
-
-	return ERR_PTR(-ENOENT);
-}
-
-static inline struct tapi_device *inode_to_tdev(struct inode *inode)
-{
-	return container_of(inode->i_cdev, struct tapi_char_device, cdev)->tdev;
-}
-
-static int tapi_control_open(struct inode *inode, struct file *file)
-{
-	int ret;
-	struct tapi_device *tdev = inode_to_tdev(inode);
-	struct tapi_control_file *tctrl;
-
-	get_device(&tdev->dev);
-
-	tctrl = kzalloc(sizeof(*tctrl), GFP_KERNEL);
-	if (!tctrl) {
-		ret = -ENOMEM;
-		goto err_put_device;
-	}
-
-	INIT_LIST_HEAD(&tctrl->links);
-	tctrl->tdev = tdev;
-
-	file->private_data = tctrl;
-
-	return 0;
-
-err_put_device:
-	put_device(&tdev->dev);
-
-	return ret;
-}
-
-static int tapi_control_release(struct inode *inode, struct file *file)
-{
-	struct tapi_control_file *tctrl = file->private_data;
-	struct tapi_link *link;
-
-	if (tctrl) {
-		list_for_each_entry(link, &tctrl->links, head)
-			tapi_link_free(tctrl->tdev, link);
-
-		put_device(&tctrl->tdev->dev);
-	}
-
-	return 0;
-}
-
-static long tapi_control_ioctl_link_alloc(struct tapi_control_file *tctrl,
-	unsigned long arg)
-{
-	struct tapi_link *link;
-	struct tapi_endpoint *ep1, *ep2;
-
-	ep1 = tapi_lookup_endpoint(tctrl->tdev, arg >> 16);
-	ep2 = tapi_lookup_endpoint(tctrl->tdev, arg & 0xffff);
-
-	link = tapi_link_alloc(tctrl->tdev, ep1, ep2);
-	if (IS_ERR(link))
-		return PTR_ERR(link);
-
-	list_add_tail(&link->head, &tctrl->links);
-
-	return link->id;
-}
-
-struct tapi_link *tapi_control_lookup_link(struct tapi_control_file *tctrl,
-	unsigned int id)
-{
-	struct tapi_link *link;
-
-	list_for_each_entry(link, &tctrl->links, head) {
-		if (link->id == id)
-			return link;
-	}
-
-	return NULL;
-}
-
-static long tapi_control_ioctl_link_free(struct tapi_control_file *tctrl,
-	unsigned long arg)
-{
-	struct tapi_link *link = tapi_control_lookup_link(tctrl, arg);
-	if (!link)
-		return -ENOENT;
-
-	tapi_link_free(tctrl->tdev, link);
-	list_del(&link->head);
-
-	return 0;
-}
-
-static long tapi_control_ioctl_link_enable(struct tapi_control_file *tctrl,
-	unsigned long arg)
-{
-	struct tapi_link *link = tapi_control_lookup_link(tctrl, arg);
-	if (!link)
-		return -ENOENT;
-
-	return tapi_link_enable(tctrl->tdev, link);
-}
-
-static long tapi_control_ioctl_link_disable(struct tapi_control_file *tctrl,
-	unsigned long arg)
-{
-	struct tapi_link *link = tapi_control_lookup_link(tctrl, arg);
-	if (!link)
-		return -ENOENT;
-
-	return tapi_link_disable(tctrl->tdev, link);
-}
-
-static long tapi_control_ioctl_sync(struct tapi_control_file *tctrl)
-{
-	return tapi_sync(tctrl->tdev);
-}
-
-static long tapi_control_ioctl(struct file *file, unsigned int cmd,
-	unsigned long arg)
-{
-	int ret;
-	struct tapi_control_file *tctrl = file->private_data;
-
-	switch (cmd) {
-	case TAPI_CONTROL_IOCTL_LINK_ALLOC:
-		ret = tapi_control_ioctl_link_alloc(tctrl, arg);
-		break;
-	case TAPI_CONTROL_IOCTL_LINK_FREE:
-		ret = tapi_control_ioctl_link_free(tctrl, arg);
-		break;
-	case TAPI_CONTROL_IOCTL_LINK_ENABLE:
-		ret = tapi_control_ioctl_link_enable(tctrl, arg);
-		break;
-	case TAPI_CONTROL_IOCTL_LINK_DISABLE:
-		ret = tapi_control_ioctl_link_disable(tctrl, arg);
-		break;
-	case TAPI_CONTROL_IOCTL_SYNC:
-		ret = tapi_control_ioctl_sync(tctrl);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return ret;
-}
-
-static const struct file_operations tapi_control_file_ops = {
-	.owner = THIS_MODULE,
-	.open = tapi_control_open,
-	.release = tapi_control_release,
-	.unlocked_ioctl = tapi_control_ioctl,
-};
-
-int tapi_register_control_device(struct tapi_device* tdev)
-{
-	dev_set_name(&tdev->control_dev.dev, "tapi%uC", tdev->id);
-	return tapi_char_device_register(tdev, &tdev->control_dev, &tapi_control_file_ops);
-}

+ 0 - 250
package/lqtapi/src/tapi/tapi-core.c

@@ -1,250 +0,0 @@
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/list.h>
-
-#include <linux/cdev.h>
-#include <linux/err.h>
-
-#include <linux/tapi/tapi.h>
-
-
-void tapi_alloc_input(struct tapi_device *tdev, struct tapi_port *port);
-int tapi_register_port_device(struct tapi_device* tdev, struct tapi_port *port);
-int tapi_register_stream_device(struct tapi_device* tdev);
-int tapi_register_control_device(struct tapi_device* tdev);
-
-static struct class *tapi_class;
-static int tapi_major;
-
-#define TAPI_MAX_MINORS 255
-
-static bool tapi_minors[TAPI_MAX_MINORS];
-
-static int tapi_get_free_minor(void)
-{
-	int i;
-	for (i = 0; i < TAPI_MAX_MINORS; ++i) {
-		if (!tapi_minors[i]) {
-			tapi_minors[i] = true;
-			return i;
-		}
-	}
-
-	return -1;
-}
-
-/*
-int tapi_port_send_dtmf_events(struct tapi_device *tdev, unsigned int port, struct tapi_dtmf *, size_t num_events, unsigned int dealy)
-{
-}
-EXPORT_SYMBOL_GPL(tapi_port_send_dtmf_events);
-*/
-
-void tapi_report_hook_event(struct tapi_device *tdev, struct tapi_port *port,
-	bool on)
-{
-	struct tapi_event event;
-	event.type = TAPI_EVENT_TYPE_HOOK;
-	event.port = port->id;
-	event.hook.on = on;
-
-	tapi_report_event(tdev, &event);
-}
-EXPORT_SYMBOL_GPL(tapi_report_hook_event);
-
-void tapi_report_dtmf_event(struct tapi_device *tdev, struct tapi_port *port,
-	unsigned char code)
-{
-	struct tapi_event event;
-	event.type = TAPI_EVENT_TYPE_DTMF;
-	event.port = port->id;
-	event.dtmf.code = code;
-
-	tapi_report_event(tdev, &event);
-}
-EXPORT_SYMBOL_GPL(tapi_report_dtmf_event);
-
-struct tapi_stream *tapi_stream_alloc(struct tapi_device *tdev)
-{
-	struct tapi_stream *stream;
-	printk("tdev %p\n", tdev);
-
-	if (!tdev->ops || !tdev->ops->stream_alloc)
-		return ERR_PTR(-ENOSYS);
-
-	stream = tdev->ops->stream_alloc(tdev);
-	printk("stream %p\n", stream);
-	if (IS_ERR(stream))
-		return stream;
-
-	stream->id = atomic_inc_return(&tdev->stream_id) - 1;
-	stream->ep.id = stream->id;
-
-/*	mutex_lock(&tdev->lock);*/
-	list_add_tail(&stream->head, &tdev->streams);
-/*	mutex_unlock(&tdev->lock);*/
-
-	return stream;
-}
-EXPORT_SYMBOL_GPL(tapi_stream_alloc);
-
-void tapi_stream_free(struct tapi_device *tdev, struct tapi_stream *stream)
-{
-	mutex_lock(&tdev->lock);
-	list_del(&stream->head);
-	mutex_unlock(&tdev->lock);
-
-	tdev->ops->stream_free(tdev, stream);
-}
-EXPORT_SYMBOL_GPL(tapi_stream_free);
-
-struct tapi_link *tapi_link_alloc(struct tapi_device *tdev,
-	struct tapi_endpoint *ep1, struct tapi_endpoint *ep2)
-{
-	struct tapi_link *link;
-
-	if (!tdev->ops || !tdev->ops->link_alloc)
-		return ERR_PTR(-ENOSYS);
-
-	link = tdev->ops->link_alloc(tdev, ep1, ep2);
-	if (IS_ERR(link))
-		return link;
-
-	link->id = atomic_inc_return(&tdev->link_id) - 1;
-
-/*
-	mutex_lock(&tdev->lock);
-	list_add_tail(&link->head, &tdev->links);
-	mutex_unlock(&tdev->lock);
-*/
-	return link;
-}
-EXPORT_SYMBOL_GPL(tapi_link_alloc);
-
-void tapi_link_free(struct tapi_device *tdev, struct tapi_link *link)
-{
-/*
-	mutex_lock(&tdev->lock);
-	list_del(&link->head);
-	mutex_unlock(&tdev->lock);
-*/
-	tdev->ops->link_free(tdev, link);
-}
-EXPORT_SYMBOL_GPL(tapi_link_free);
-
-int tapi_char_device_register(struct tapi_device *tdev,
-	struct tapi_char_device *tchrdev, const struct file_operations *fops)
-{
-	int ret;
-	struct device *dev = &tchrdev->dev;
-	dev_t devt;
-	int minor = tapi_get_free_minor();
-
-	devt = MKDEV(tapi_major, minor);
-
-	dev->devt = devt;
-	dev->class = tapi_class;
-	dev->parent = &tdev->dev;
-
-	tchrdev->tdev = tdev;
-
-	cdev_init(&tchrdev->cdev, fops);
-	tchrdev->cdev.owner = THIS_MODULE;
-	ret = cdev_add(&tchrdev->cdev, devt, 1);
-	if (ret)
-		return ret;
-
-	ret = device_register(&tchrdev->dev);
-	if (ret)
-		goto err_cdev_del;
-
-	return 0;
-
-err_cdev_del:
-	cdev_del(&tchrdev->cdev);
-
-	return ret;
-}
-
-int tapi_device_register(struct tapi_device *tdev, const char *name,
-	struct device *parent)
-{
-	static atomic_t tapi_device_id = ATOMIC_INIT(0);
-	int ret, i;
-
-	tdev->dev.class = tapi_class;
-	tdev->dev.parent = parent;
-	dev_set_name(&tdev->dev, "%s", name);
-
-	ret = device_register(&tdev->dev);
-	if (ret)
-		return ret;
-
-	tdev->id = atomic_inc_return(&tapi_device_id) - 1;
-
-	mutex_init(&tdev->lock);
-	INIT_LIST_HEAD(&tdev->streams);
-	INIT_LIST_HEAD(&tdev->links);
-	atomic_set(&tdev->link_id, 0);
-	atomic_set(&tdev->stream_id, tdev->num_ports);
-
-	tapi_register_stream_device(tdev);
-	tapi_register_control_device(tdev);
-
-	for (i = 0; i < tdev->num_ports; ++i) {
-		tapi_port_alloc(tdev, i);
-		tapi_alloc_input(tdev, &tdev->ports[i]);
-		tapi_register_port_device(tdev, &tdev->ports[i]);
-		tdev->ports[i].id = i;
-		tdev->ports[i].ep.id = i;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(tapi_device_register);
-
-void tapi_device_unregister(struct tapi_device *tdev)
-{
-	device_unregister(&tdev->dev);
-}
-EXPORT_SYMBOL_GPL(tapi_device_unregister);
-
-static int __init tapi_class_init(void)
-{
-	int ret;
-	dev_t dev;
-
-	tapi_class = class_create(THIS_MODULE, "tapi");
-
-	if (IS_ERR(tapi_class)) {
-		ret = PTR_ERR(tapi_class);
-		printk(KERN_ERR "tapi: Failed to create device class: %d\n", ret);
-		goto err;
-	}
-
-	ret = alloc_chrdev_region(&dev, 0, TAPI_MAX_MINORS, "tapi");
-	if (ret) {
-		printk(KERN_ERR "tapi: Failed to allocate chrdev region: %d\n", ret);
-		goto err_class_destory;
-	}
-	tapi_major = MAJOR(dev);
-
-	return 0;
-err_class_destory:
-	class_destroy(tapi_class);
-err:
-	return ret;
-}
-subsys_initcall(tapi_class_init);
-
-static void __exit tapi_class_exit(void)
-{
-	unregister_chrdev_region(MKDEV(tapi_major, 0), TAPI_MAX_MINORS);
-	class_destroy(tapi_class);
-}
-module_exit(tapi_class_exit);
-
-MODULE_AUTHOR("Lars-Peter Clausen <[email protected]>");
-MODULE_DESCRIPTION("TAPI class");
-MODULE_LICENSE("GPL");

+ 0 - 99
package/lqtapi/src/tapi/tapi-input.c

@@ -1,99 +0,0 @@
-
-#include <linux/tapi/tapi.h>
-
-#include <linux/input.h>
-
-static unsigned short tapi_keycodes[] = {
-	[0] = KEY_NUMERIC_0,
-	[1] = KEY_NUMERIC_1,
-	[2] = KEY_NUMERIC_2,
-	[3] = KEY_NUMERIC_3,
-	[4] = KEY_NUMERIC_4,
-	[5] = KEY_NUMERIC_5,
-	[6] = KEY_NUMERIC_6,
-	[7] = KEY_NUMERIC_7,
-	[8] = KEY_NUMERIC_8,
-	[9] = KEY_NUMERIC_9,
-	[10] = KEY_NUMERIC_STAR,
-	[11] = KEY_NUMERIC_POUND,
-	[12] = KEY_ENTER,
-	[13] = KEY_ESC,
-};
-
-static int tapi_input_event(struct input_dev *input, unsigned int type,
-	unsigned int code, int value)
-{
-	struct tapi_device *tdev = dev_to_tapi(input->dev.parent);
-	struct tapi_port *port = input_get_drvdata(input);
-
-
-	if (type != EV_SND || code != SND_BELL)
-		return -EINVAL;
-
-	tapi_port_set_ring(tdev, port, value);
-
-	return 0;
-}
-
-void tapi_alloc_input(struct tapi_device *tdev, struct tapi_port *port)
-{
-	struct input_dev *input;
-	int i;
-	char *phys;
-
-	input = input_allocate_device();
-
-	phys = kzalloc(sizeof("tapi/input000"), GFP_KERNEL);
-	sprintf(phys, "tapi/input%d", port->id);
-
-	input->name = "tapi";
-	input->phys = phys;
-	input->id.bustype = BUS_HOST;
-	input->dev.parent = &tdev->dev;
-	input->evbit[0] = BIT(EV_KEY) | BIT(EV_SND);
-	input->sndbit[0] = BIT(SND_BELL);
-
-	input->event = tapi_input_event;
-
-	input->keycodesize = sizeof(unsigned short);
-	input->keycodemax = ARRAY_SIZE(tapi_keycodes);
-	input->keycode = tapi_keycodes;
-
-	port->input = input;
-
-	for (i = 0; i < ARRAY_SIZE(tapi_keycodes); ++i)
-		__set_bit(tapi_keycodes[i], input->keybit);
-
-	input_set_drvdata(input, port);
-	input_register_device(input);
-}
-
-void tapi_report_event(struct tapi_device *tdev,
-	struct tapi_event *event)
-{
-	unsigned short key_code;
-	struct input_dev *input;
-
-	if (!tdev || !tdev->ports)
-		return;
-
-	switch (event->type) {
-		case TAPI_EVENT_TYPE_HOOK:
-			if (event->hook.on)
-				key_code = KEY_ENTER;
-			else
-				key_code = KEY_ESC;
-			break;
-		case TAPI_EVENT_TYPE_DTMF:
-			key_code = tapi_keycodes[event->dtmf.code];
-			break;
-		default:
-			return;
-	}
-
-	input = tdev->ports[event->port].input;
-	input_report_key(input, key_code, 1);
-	input_sync(input);
-	input_report_key(input, key_code, 0);
-	input_sync(input);
-}

+ 0 - 62
package/lqtapi/src/tapi/tapi-nl.c

@@ -1,62 +0,0 @@
-
-static struct tapi_attr default_port[] = {
-	[PORTS] = {
-		.type = TAPI_TYPE_PORTS,
-		.name = "ports",
-		.description = "foobar",
-		.set = tapi_set_ports,
-		.get = tapi_get_ports,
-	},
-};
-
-static const struct nla_policy tapi_policy[] = {
-	[TAPI_ATTR_ID] = { .type = NLA_U32 },
-	[TAPI_ATTR_PORT] = { .type = NLA_U32 },
-	[TAPI_ATTR_ENDPOINT] = { .type = NLA_U32 },
-	[TAPI_ATTR_STREAM] = { .type = NLA_U32 }
-};
-
-static const struct nla_policy tapi_port_policy[] = {
-	[TAPI_PORT_ID] = { .type = NLA_U32 },
-};
-
-static const struct nla_policy tapi_endpoint_policy[] = {
-	[TAPI_ENDPOINT_ID] = { .type = NLA_U32 },
-};
-
-static const struct nla_policy tapi_stream_policy[] = {
-	[TAPI_STREAM_ID] = { .type = NLA_U32 },
-};
-
-static struct genl_family tapi_nl_family = {
-	.id = GENL_ID_GENERATE,
-	.name = "tapi",
-	.hdrsize = 0,
-	.version = 1,
-	.maxattr = ARRAY_SIZE(tapi_policy),
-};
-
-
-
-static struct genl_ops tapi_nl_ops[] = {
-	TAPI_NL_OP(TAPI_CMD_LIST, list_attr),
-
-};
-
-static int __init tapi_nl_init(void)
-{
-	ret = genl_unregister_family(&tapi_nl_family);
-	if (ret)
-		return ret;
-
-	genl_register_ops(&tapi_nl_family, tapi_nl_ops);
-
-	return 0;
-}
-module_init(tapi_nl_init);
-
-static void __exit tapi_nl_exit(void)
-{
-	genl_unregister_family(&tapi_nl_family);
-}
-

+ 0 - 82
package/lqtapi/src/tapi/tapi-port.c

@@ -1,82 +0,0 @@
-#include <linux/cdev.h>
-#include <linux/fs.h>
-#include <linux/list.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-#include <linux/tapi/tapi.h>
-#include <linux/tapi/tapi-ioctl.h>
-
-static inline struct tapi_port *tapi_char_device_to_port(struct tapi_char_device *chrdev)
-{
-	return container_of(chrdev, struct tapi_port, chrdev);
-}
-
-static int tapi_port_open(struct inode *inode, struct file *file)
-{
-	struct tapi_device *tdev = cdev_to_tapi_char_device(inode->i_cdev)->tdev;
-
-	get_device(&tdev->dev);
-	file->private_data = cdev_to_tapi_char_device(inode->i_cdev);
-
-	return 0;
-}
-
-static int tapi_port_release(struct inode *inode, struct file *file)
-{
-	struct tapi_device *tdev = cdev_to_tapi_char_device(inode->i_cdev)->tdev;
-
-	put_device(&tdev->dev);
-
-	return 0;
-}
-
-static long tapi_port_ioctl_get_endpoint(struct tapi_device *tdev,
-	struct tapi_port *port, unsigned long arg)
-{
-	return port->ep.id;
-}
-
-static long tapi_port_ioctl_set_ring(struct tapi_device *tdev,
-	struct tapi_port *port, unsigned long arg)
-{
-	tapi_port_set_ring(tdev, port, arg);
-	return 0;
-}
-
-static long tapi_port_ioctl(struct file *file, unsigned int cmd,
-	unsigned long arg)
-{
-	int ret;
-	struct tapi_char_device *tchrdev = file->private_data;
-	struct tapi_device *tdev = tchrdev->tdev;
-	struct tapi_port *port = tapi_char_device_to_port(tchrdev);
-
-	switch (cmd) {
-	case TAPI_PORT_IOCTL_GET_ENDPOINT:
-		ret = tapi_port_ioctl_get_endpoint(tdev, port, arg);
-		break;
-	case TAPI_PORT_IOCTL_SET_RING:
-		ret = tapi_port_ioctl_set_ring(tdev, port, arg);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-static const struct file_operations tapi_port_file_ops = {
-	.owner = THIS_MODULE,
-	.open = tapi_port_open,
-	.release = tapi_port_release,
-	.unlocked_ioctl = tapi_port_ioctl,
-};
-
-int tapi_register_port_device(struct tapi_device* tdev, struct tapi_port *port)
-{
-	dev_set_name(&port->chrdev.dev, "tapi%uP%u", tdev->id, port->id);
-	return tapi_char_device_register(tdev, &port->chrdev, &tapi_port_file_ops);
-}

+ 0 - 201
package/lqtapi/src/tapi/tapi-stream.c

@@ -1,201 +0,0 @@
-#include <linux/cdev.h>
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/list.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/poll.h>
-
-#include <linux/tapi/tapi.h>
-#include <linux/tapi/tapi-ioctl.h>
-
-
-struct tapi_stream_file {
-	struct tapi_device *tdev;
-	struct tapi_stream *stream;
-};
-
-static inline struct tapi_device *inode_to_tdev(struct inode *inode)
-{
-	return container_of(inode->i_cdev, struct tapi_char_device, cdev)->tdev;
-}
-
-static int tapi_stream_open(struct inode *inode, struct file *file)
-{
-	int ret;
-	struct tapi_device *tdev = inode_to_tdev(inode);
-	struct tapi_stream_file *stream;
-
-	get_device(&tdev->dev);
-
-	stream = kzalloc(sizeof(*stream), GFP_KERNEL);
-	if (!stream) {
-		ret = -ENOMEM;
-		goto err_put;
-	}
-
-	stream->stream = tapi_stream_alloc(tdev);
-	if (IS_ERR(stream->stream)) {
-		ret = PTR_ERR(stream->stream);
-		goto err_free;
-	}
-	stream->tdev = tdev;
-
-	init_waitqueue_head(&stream->stream->recv_wait);
-	skb_queue_head_init(&stream->stream->recv_queue);
-
-	file->private_data = stream;
-
-	return 0;
-
-err_free:
-	kfree(stream);
-err_put:
-	put_device(&tdev->dev);
-	return ret;
-}
-
-static int tapi_stream_release(struct inode *inode, struct file *file)
-{
-	struct tapi_stream_file *stream = file->private_data;
-
-	if (stream) {
-		tapi_stream_free(stream->tdev, stream->stream);
-		put_device(&stream->tdev->dev);
-		kfree(stream);
-	}
-
-	return 0;
-}
-
-static long tapi_stream_ioctl(struct file *file, unsigned int cmd,
-	unsigned long arg)
-{
-	int ret = 0;
-	struct tapi_stream_file *stream = file->private_data;
-	struct tapi_device *tdev = stream->tdev;
-
-	switch (cmd) {
-	case TAPI_STREAM_IOCTL_GET_ENDPOINT:
-		ret = stream->stream->ep.id;
-		break;
-	case TAPI_STREAM_IOCTL_CONFIGURE:
-		break;
-	case TAPI_STREAM_IOCTL_START:
-		ret = tapi_stream_start(tdev, stream->stream);
-		break;
-	case TAPI_STREAM_IOCTL_STOP:
-		ret = tapi_stream_stop(tdev, stream->stream);
-		break;
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-static unsigned int tapi_stream_poll(struct file *file, struct poll_table_struct *wait)
-{
-	struct tapi_stream_file *stream = file->private_data;
-	int ret;
-
-	poll_wait(file, &stream->stream->recv_wait, wait);
-
-	ret = POLLOUT;
-
-	if (!skb_queue_empty(&stream->stream->recv_queue))
-		ret |= POLLIN;
-
-	return ret;
-}
-
-static ssize_t tapi_stream_read(struct file *file, char __user *buffer,
-	size_t count, loff_t *offset)
-{
-	struct tapi_stream_file *stream = file->private_data;
-	struct sk_buff *skb;
-
-	skb = skb_dequeue(&stream->stream->recv_queue);
-	if (!skb) {
-		if (file->f_flags & O_NONBLOCK)
-			return -EAGAIN;
-
-		do {
-			interruptible_sleep_on(&stream->stream->recv_wait);
-			skb = skb_dequeue(&stream->stream->recv_queue);
-		} while (skb == NULL && !signal_pending(current));
-
-		if (skb == NULL)
-			return -ERESTARTNOHAND;
-	}
-
-	if (skb->len > count) {
-		skb_queue_head(&stream->stream->recv_queue, skb);
-		return -EMSGSIZE;
-	}
-
-	if (copy_to_user(buffer, skb->data, skb->len)) {
-		skb_queue_head(&stream->stream->recv_queue, skb);
-		return -EFAULT;
-	}
-
-	count = skb->len;
-
-	kfree_skb(skb);
-
-	return count;
-}
-
-static ssize_t tapi_stream_write(struct file *file, const char __user *buffer,
-	size_t count, loff_t *ppos)
-{
-	struct tapi_stream_file *stream = file->private_data;
-	struct tapi_device *tdev = stream->tdev;
-	struct sk_buff *skb;
-
-	if (count == 0)
-		return 0;
-
-	skb = alloc_skb(count, GFP_USER);
-	if (!skb)
-		return -ENOMEM;
-
-	if (copy_from_user(skb_put(skb, count), buffer, count)) {
-		kfree_skb(skb);
-		return -EFAULT;
-	}
-
-	tdev->ops->stream_send(tdev, stream->stream, skb);
-
-	return count;
-}
-
-static const struct file_operations tapi_stream_file_ops = {
-	.owner = THIS_MODULE,
-	.read = tapi_stream_read,
-	.write = tapi_stream_write,
-	.open = tapi_stream_open,
-	.release = tapi_stream_release,
-	.poll = tapi_stream_poll,
-	.unlocked_ioctl = tapi_stream_ioctl,
-};
-
-int tapi_register_stream_device(struct tapi_device* tdev)
-{
-	dev_set_name(&tdev->stream_dev.dev, "tapi%uS", tdev->id);
-	return tapi_char_device_register(tdev, &tdev->stream_dev, &tapi_stream_file_ops);
-}
-
-int tapi_stream_recv(struct tapi_device *tdev, struct tapi_stream * stream,
-	struct sk_buff *skb)
-{
-	skb_queue_tail(&stream->recv_queue, skb);
-	wake_up(&stream->recv_wait);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(tapi_stream_recv);

+ 0 - 107
package/lqtapi/src/tapi/tapi-sysfs-port.c

@@ -1,107 +0,0 @@
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/sysfs.h>
-
-#include <linux/err.h>
-#include <linux/tapi/tapi.h>
-
-struct tapi_sysfs_port {
-	struct tapi_device *tdev;
-	unsigned int id;
-	struct kobject kobj;
-};
-
-struct tapi_sysfs_entry {
-	ssize_t (*show)(struct tapi_device *, unsigned int port, char *);
-	ssize_t (*store)(struct tapi_device *, unsigned int port, const char *, size_t);
-	struct attribute attr;
-};
-
-static ssize_t tapi_port_store(struct kobject *kobj, struct attribute *attr,
-	const char *s, size_t len)
-{
-	struct tapi_sysfs_port *port = container_of(kobj, struct tapi_sysfs_port, kobj);
-	struct tapi_sysfs_entry *entry = container_of(attr, struct tapi_sysfs_entry,
-								attr);
-
-	if (!entry->store)
-		return -ENOSYS;
-
-	return entry->store(port->tdev, port->id, s, len);
-}
-
-static ssize_t tapi_port_show(struct kobject *kobj, struct attribute *attr,
-	char *s)
-{
-	return -ENOSYS;
-}
-
-#define TAPI_PORT_ATTR(_name, _mode, _show, _store) \
-	struct tapi_sysfs_entry tapi_port_ ## _name ## _attr = \
-		__ATTR(_name, _mode, _show, _store)
-
-static int tapi_port_store_ring(struct tapi_device *tdev, unsigned int port,
-	const char *s, size_t len)
-{
-	int ret;
-	unsigned long val;
-
-	ret = strict_strtoul(s, 10, &val);
-
-	if (ret)
-		return ret;
-
-	ret = tapi_port_set_ring(tdev, &tdev->ports[port], val);
-	if (ret)
-		return ret;
-	return len;
-}
-
-static TAPI_PORT_ATTR(ring, 0644, NULL, tapi_port_store_ring);
-
-static struct attribute *tapi_port_default_attrs[] = {
-	&tapi_port_ring_attr.attr,
-	NULL,
-};
-
-static void tapi_port_free(struct kobject *kobj)
-{
-	struct tapi_sysfs_port *port = container_of(kobj, struct tapi_sysfs_port, kobj);
-	kfree(port);
-}
-
-static struct sysfs_ops tapi_port_sysfs_ops = {
-	.show		= tapi_port_show,
-	.store		= tapi_port_store,
-};
-
-static struct kobj_type tapi_port_ktype = {
-	.release	= tapi_port_free,
-	.sysfs_ops	= &tapi_port_sysfs_ops,
-	.default_attrs	= tapi_port_default_attrs,
-};
-
-struct tapi_sysfs_port *tapi_port_alloc(struct tapi_device *tdev, unsigned int id)
-{
-	struct tapi_sysfs_port *port;
-	int ret;
-
-	port = kzalloc(sizeof(*port), GFP_KERNEL);
-	port->tdev = tdev;
-	port->id = id;
-
-	ret = kobject_init_and_add(&port->kobj, &tapi_port_ktype, &tdev->dev.kobj,
-		"port%d", id);
-	if (ret) {
-		kfree(port);
-		return ERR_PTR(ret);
-	}
-
-	return port;
-}
-
-void tapi_port_delete(struct tapi_sysfs_port *port)
-{
-	kobject_del(&port->kobj);
-	kobject_put(&port->kobj);
-}

+ 2 - 2
package/ltq-dsl/Makefile

@@ -155,12 +155,12 @@ define Build/InstallDev
 	$(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_cmv_danube.h $(1)/usr/include
 endef
 
-define Package/ltq-dsl-firmware-a/install
+define Package/kmod-ltq-dsl-firmware-a/install
 	$(INSTALL_DIR) $(1)/lib/firmware/
 	$(CP) $(PKG_BUILD_DIR)/$(FW_BASE_NAME)_a_$(FW_A_FILE_VER).bin $(1)/lib/firmware/ModemHWE.bin
 endef
 
-define Package/ltq-dsl-firmware-b/install
+define Package/kmod-ltq-dsl-firmware-b/install
 	$(INSTALL_DIR) $(1)/lib/firmware/
 	$(CP) $(PKG_BUILD_DIR)/$(FW_BASE_NAME)_b_$(FW_B_FILE_VER).bin $(1)/lib/firmware/ModemHWE.bin
 endef

+ 23 - 14
package/ltq-dsl/patches/500-portability.patch

@@ -1,7 +1,5 @@
-Index: drv_dsl_cpe_api-3.24.4.4/configure.in
-===================================================================
---- drv_dsl_cpe_api-3.24.4.4.orig/configure.in	2009-08-13 13:39:21.000000000 +0200
-+++ drv_dsl_cpe_api-3.24.4.4/configure.in	2010-10-14 02:14:55.000000000 +0200
+--- a/configure.in
++++ b/configure.in
 @@ -310,7 +310,7 @@
  AC_ARG_ENABLE(kernelbuild,
      AC_HELP_STRING(--enable-kernel-build=x,Set the target kernel build path),
@@ -167,10 +165,8 @@ Index: drv_dsl_cpe_api-3.24.4.4/configure.in
  ])
  
  AC_CONFIG_FILES([Makefile src/Makefile])
-Index: drv_dsl_cpe_api-3.24.4.4/src/Makefile.am
-===================================================================
---- drv_dsl_cpe_api-3.24.4.4.orig/src/Makefile.am	2009-07-03 14:06:34.000000000 +0200
-+++ drv_dsl_cpe_api-3.24.4.4/src/Makefile.am	2010-10-14 02:14:55.000000000 +0200
+--- a/src/Makefile.am
++++ b/src/Makefile.am
 @@ -303,7 +303,7 @@
  drv_dsl_cpe_api_OBJS = "$(subst .c,.o,$(filter %.c,$(drv_dsl_cpe_api_SOURCES)))"
  
@@ -195,10 +191,8 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/Makefile.am
  	$(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules
  
  clean-generic:
-Index: drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_os_linux.h
-===================================================================
---- drv_dsl_cpe_api-3.24.4.4.orig/src/include/drv_dsl_cpe_os_linux.h	2010-10-14 02:14:55.000000000 +0200
-+++ drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_os_linux.h	2010-10-14 02:14:55.000000000 +0200
+--- a/src/include/drv_dsl_cpe_os_linux.h
++++ b/src/include/drv_dsl_cpe_os_linux.h
 @@ -16,8 +16,6 @@
     extern "C" {
  #endif
@@ -208,10 +202,25 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_os_linux.h
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
-@@ -40,6 +38,7 @@
+@@ -26,8 +24,10 @@
+ #include <linux/spinlock.h>
+ #include <linux/sched.h>
+ 
+-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
+-   #include <generated/utsrelease.h>
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
++#include <linux/utsrelease.h>
++#else
++#include <generated/utsrelease.h>
+ #endif
+ 
+ #include <linux/types.h>
+@@ -39,7 +39,8 @@
+ #include <linux/delay.h>
  #include <linux/poll.h>
  #include <asm/uaccess.h>
- #include <linux/smp_lock.h>
+-#include <linux/smp_lock.h>
++//#include <linux/smp_lock.h>
 +#include <asm/ioctl.h>
  
  #ifdef INCLUDE_DSL_CPE_API_IFXOS_SUPPORT

+ 6 - 3
package/ltq-dsl/src/ifxmips_atm_core.c

@@ -59,8 +59,7 @@
 /*
  *  Chip Specific Head File
  */
-#include <lantiq.h>
-#include <lantiq_regs.h>
+#include <lantiq_soc.h>
 #include "ifxmips_atm_core.h"
 
 
@@ -2403,7 +2402,11 @@ static int __devinit ifx_atm_init(void)
 
     /*  create devices  */
     for ( port_num = 0; port_num < ATM_PORT_NUMBER; port_num++ ) {
-        g_atm_priv_data.port[port_num].dev = atm_dev_register("ifxmips_atm", NULL, &g_ifx_atm_ops, -1, NULL);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+	g_atm_priv_data.port[port_num].dev = atm_dev_register("ifxmips_atm", &g_ifx_atm_ops, -1, NULL);
+#else
+	g_atm_priv_data.port[port_num].dev = atm_dev_register("ifxmips_atm", NULL, &g_ifx_atm_ops, -1, NULL);
+#endif
         if ( !g_atm_priv_data.port[port_num].dev ) {
             err("failed to register atm device %d!", port_num);
             ret = -EIO;

+ 1 - 2
package/ltq-dsl/src/ifxmips_atm_danube.c

@@ -45,8 +45,7 @@
 /*
  *  Chip Specific Head File
  */
-#include <lantiq.h>
-#include <lantiq_regs.h>
+#include <lantiq_soc.h>
 #include "ifxmips_compat.h"
 #include "ifxmips_atm_core.h"
 #include "ifxmips_atm_fw_danube.h"

+ 1 - 1
package/ltq-dsl/src/ifxmips_atm_ppe_danube.h

@@ -93,7 +93,7 @@
 /*
  *  Mailbox IGU1 Interrupt
  */
-#define PPE_MAILBOX_IGU1_INT            LQ_PPE_MBOX_INT
+#define PPE_MAILBOX_IGU1_INT            LTQ_PPE_MBOX_INT
 
 
 

+ 1 - 1
package/ltq-dsl/src/ifxmips_compat.h

@@ -26,7 +26,7 @@
 #define IFX_PMU_MODULE_PPE_EMA    (1 << 22)
 #define IFX_PMU_MODULE_PPE_TOP    (1 << 29)
 
-#define ifx_pmu_set(a,b)	{if(a == IFX_PMU_ENABLE) lq_pmu_enable(b); else lq_pmu_disable(b);}
+#define ifx_pmu_set(a,b)	{if(a == IFX_PMU_ENABLE) ltq_pmu_enable(b); else ltq_pmu_disable(b);}
 
 #define PPE_TOP_PMU_SETUP(__x)    ifx_pmu_set(IFX_PMU_MODULE_PPE_TOP, (__x))
 #define PPE_SLL01_PMU_SETUP(__x)  ifx_pmu_set(IFX_PMU_MODULE_PPE_SLL01, (__x))

+ 96 - 82
package/ltq-dsl/src/lantiq_mei.c

@@ -29,7 +29,11 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+#include <linux/utsrelease.h>
+#else
 #include <generated/utsrelease.h>
+#endif
 #include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
@@ -46,22 +50,21 @@
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
 
-#include <lantiq.h>
-#include <lantiq_regs.h>
+#include <lantiq_soc.h>
 #include "ifxmips_atm.h"
 #define IFX_MEI_BSP
 #include "ifxmips_mei_interface.h"
 
-/*#define LQ_RCU_RST                   IFX_RCU_RST_REQ
-#define LQ_RCU_RST_REQ_ARC_JTAG      IFX_RCU_RST_REQ_ARC_JTAG
-#define LQ_RCU_RST_REQ_DFE		  IFX_RCU_RST_REQ_DFE
-#define LQ_RCU_RST_REQ_AFE		  IFX_RCU_RST_REQ_AFE
+/*#define LTQ_RCU_RST                   IFX_RCU_RST_REQ
+#define LTQ_RCU_RST_REQ_ARC_JTAG      IFX_RCU_RST_REQ_ARC_JTAG
+#define LTQ_RCU_RST_REQ_DFE		  IFX_RCU_RST_REQ_DFE
+#define LTQ_RCU_RST_REQ_AFE		  IFX_RCU_RST_REQ_AFE
 #define IFXMIPS_FUSE_BASE_ADDR            IFX_FUSE_BASE_ADDR
 #define IFXMIPS_ICU_IM0_IER               IFX_ICU_IM0_IER
 #define IFXMIPS_ICU_IM2_IER               IFX_ICU_IM2_IER
-#define LQ_MEI_INT                   IFX_MEI_INT
-#define LQ_MEI_DYING_GASP_INT        IFX_MEI_DYING_GASP_INT
-#define LQ_MEI_BASE_ADDR  		  IFX_MEI_SPACE_ACCESS
+#define LTQ_MEI_INT                   IFX_MEI_INT
+#define LTQ_MEI_DYING_GASP_INT        IFX_MEI_DYING_GASP_INT
+#define LTQ_MEI_BASE_ADDR  		  IFX_MEI_SPACE_ACCESS
 #define IFXMIPS_PMU_PWDCR		  IFX_PMU_PWDCR
 #define IFXMIPS_MPS_CHIPID                IFX_MPS_CHIPID
 
@@ -73,40 +76,44 @@
 #define ifxmips_port_free_pin		  ifx_gpio_pin_free
 #define ifxmips_mask_and_ack_irq	  bsp_mask_and_ack_irq
 #define IFXMIPS_MPS_CHIPID_VERSION_GET    IFX_MCD_CHIPID_VERSION_GET
-#define lq_r32(reg)                        __raw_readl(reg)
-#define lq_w32(val, reg)                   __raw_writel(val, reg)
-#define lq_w32_mask(clear, set, reg)       lq_w32((lq_r32(reg) & ~clear) | set, reg)
+#define ltq_r32(reg)                        __raw_readl(reg)
+#define ltq_w32(val, reg)                   __raw_writel(val, reg)
+#define ltq_w32_mask(clear, set, reg)       ltq_w32((ltq_r32(reg) & ~clear) | set, reg)
 */
 
-#define LQ_RCU_RST_REQ_DFE		(1 << 7)
-#define LQ_RCU_RST_REQ_AFE		(1 << 11)
-#define LQ_PMU_PWDCR        ((u32 *)(LQ_PMU_BASE_ADDR + 0x001C))
-#define LQ_PMU_PWDSR        ((u32 *)(LQ_PMU_BASE_ADDR + 0x0020))
-#define LQ_RCU_RST          ((u32 *)(LQ_RCU_BASE_ADDR + 0x0010))
-#define LQ_RCU_RST_ALL      0x40000000
-#define LQ_ICU_BASE_ADDR    (KSEG1 | 0x1F880200)
+#define LTQ_RCU_RST_REQ_DFE		(1 << 7)
+#define LTQ_RCU_RST_REQ_AFE		(1 << 11)
+
+#define LTQ_PMU_BASE		(KSEG1 + LTQ_PMU_BASE_ADDR)
+#define LTQ_RCU_BASE		(KSEG1 + LTQ_RCU_BASE_ADDR)
+#define LTQ_ICU_BASE		(KSEG1 + LTQ_ICU_BASE_ADDR)
 
-#define LQ_ICU_IM0_ISR      ((u32 *)(LQ_ICU_BASE_ADDR + 0x0000))
-#define LQ_ICU_IM0_IER      ((u32 *)(LQ_ICU_BASE_ADDR + 0x0008))
-#define LQ_ICU_IM0_IOSR     ((u32 *)(LQ_ICU_BASE_ADDR + 0x0010))
-#define LQ_ICU_IM0_IRSR     ((u32 *)(LQ_ICU_BASE_ADDR + 0x0018))
-#define LQ_ICU_IM0_IMR      ((u32 *)(LQ_ICU_BASE_ADDR + 0x0020))
+#define LTQ_PMU_PWDCR        ((u32 *)(LTQ_PMU_BASE + 0x001C))
+#define LTQ_PMU_PWDSR        ((u32 *)(LTQ_PMU_BASE + 0x0020))
+#define LTQ_RCU_RST          ((u32 *)(LTQ_RCU_BASE + 0x0010))
+#define LTQ_RCU_RST_ALL      0x40000000
 
+#define LTQ_ICU_IM0_ISR      ((u32 *)(LTQ_ICU_BASE + 0x0000))
+#define LTQ_ICU_IM0_IER      ((u32 *)(LTQ_ICU_BASE + 0x0008))
+#define LTQ_ICU_IM0_IOSR     ((u32 *)(LTQ_ICU_BASE + 0x0010))
+#define LTQ_ICU_IM0_IRSR     ((u32 *)(LTQ_ICU_BASE + 0x0018))
+#define LTQ_ICU_IM0_IMR      ((u32 *)(LTQ_ICU_BASE + 0x0020))
 
-#define LQ_ICU_IM1_ISR      ((u32 *)(LQ_ICU_BASE_ADDR + 0x0028))
-#define LQ_ICU_IM2_ISR      ((u32 *)(LQ_ICU_BASE_ADDR + 0x0050))
-#define LQ_ICU_IM3_ISR      ((u32 *)(LQ_ICU_BASE_ADDR + 0x0078))
-#define LQ_ICU_IM4_ISR      ((u32 *)(LQ_ICU_BASE_ADDR + 0x00A0))
 
-#define LQ_ICU_OFFSET       (LQ_ICU_IM1_ISR - LQ_ICU_IM0_ISR)
-#define LQ_ICU_IM2_IER		(LQ_ICU_IM0_IER + LQ_ICU_OFFSET)
+#define LTQ_ICU_IM1_ISR      ((u32 *)(LTQ_ICU_BASE + 0x0028))
+#define LTQ_ICU_IM2_ISR      ((u32 *)(LTQ_ICU_BASE + 0x0050))
+#define LTQ_ICU_IM3_ISR      ((u32 *)(LTQ_ICU_BASE + 0x0078))
+#define LTQ_ICU_IM4_ISR      ((u32 *)(LTQ_ICU_BASE + 0x00A0))
+
+#define LTQ_ICU_OFFSET       (LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR)
+#define LTQ_ICU_IM2_IER		(LTQ_ICU_IM0_IER + LTQ_ICU_OFFSET)
 
 #define IFX_MEI_EMSG(fmt, args...) pr_err("[%s %d]: " fmt,__FUNCTION__, __LINE__, ## args)
 #define IFX_MEI_DMSG(fmt, args...) pr_debug("[%s %d]: " fmt,__FUNCTION__, __LINE__, ## args)
 
-#define LQ_FUSE_BASE          (KSEG1 + 0x1F107354)
+#define LTQ_FUSE_BASE          (KSEG1 + 0x1F107354)
 
-#ifdef CONFIG_LQ_MEI_FW_LOOPBACK
+#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK
 //#define DFE_MEM_TEST
 //#define DFE_PING_TEST
 #define DFE_ATM_LOOPBACK
@@ -193,9 +200,18 @@ static void *g_xdata_addr = NULL;
 
 static u32 *mei_arc_swap_buff = NULL;	//  holding swap pages
 
-extern void lq_mask_and_ack_irq(unsigned int irq_nr);
-#define MEI_MASK_AND_ACK_IRQ lq_mask_and_ack_irq
-
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+extern void ltq_mask_and_ack_irq(unsigned int irq_nr);
+#define MEI_MASK_AND_ACK_IRQ ltq_mask_and_ack_irq
+#else
+extern void ltq_mask_and_ack_irq(struct irq_data *d);
+static void inline MEI_MASK_AND_ACK_IRQ(int x)
+{
+	struct irq_data d;
+	d.irq = x;
+	ltq_mask_and_ack_irq(&d);
+}
+#endif
 #define MEI_MAJOR	105
 static int dev_major = MEI_MAJOR;
 
@@ -704,9 +720,9 @@ IFX_MEI_FuseProg (DSL_DEV_Device_t * pDev)
 	u32 reg_data, fuse_value;
 	int i = 0;
 
-	IFX_MEI_LongWordRead ((u32) LQ_RCU_RST, &reg_data);
+	IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
 	while ((reg_data & 0x10000000) == 0) {
-		IFX_MEI_LongWordRead ((u32) LQ_RCU_RST,  &reg_data);
+		IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST,  &reg_data);
 		i++;
 		/* 0x4000 translate to  about 16 ms@111M, so should be enough */
 		if (i == 0x4000)
@@ -714,12 +730,12 @@ IFX_MEI_FuseProg (DSL_DEV_Device_t * pDev)
 	}
 	// STEP a: Prepare memory for external accesses
 	// Write fuse_en bit24
-	IFX_MEI_LongWordRead ((u32) LQ_RCU_RST, &reg_data);
-	IFX_MEI_LongWordWrite ((u32) LQ_RCU_RST, reg_data | (1 << 24));
+	IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
+	IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data | (1 << 24));
 
 	IFX_MEI_FuseInit (pDev);
 	for (i = 0; i < 4; i++) {
-		IFX_MEI_LongWordRead ((u32) (LQ_FUSE_BASE) + i * 4, &fuse_value);
+		IFX_MEI_LongWordRead ((u32) (LTQ_FUSE_BASE) + i * 4, &fuse_value);
 		switch (fuse_value & 0xF0000) {
 		case 0x80000:
 			reg_data = ((fuse_value & RX_DILV_ADDR_BIT_MASK) |
@@ -765,9 +781,9 @@ IFX_MEI_FuseProg (DSL_DEV_Device_t * pDev)
 			break;
 		}
 	}
-	IFX_MEI_LongWordRead ((u32) LQ_RCU_RST, &reg_data);
-	IFX_MEI_LongWordWrite ((u32) LQ_RCU_RST, reg_data & ~(1 << 24));
-	IFX_MEI_LongWordRead ((u32) LQ_RCU_RST, &reg_data);
+	IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
+	IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data & ~(1 << 24));
+	IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
 }
 
 /**
@@ -868,9 +884,9 @@ IFX_MEI_ResetARC (DSL_DEV_Device_t * pDev)
 
 	IFX_MEI_HaltArc (pDev);
 
-	IFX_MEI_LongWordRead ((u32) LQ_RCU_RST, &arc_debug_data);
-	IFX_MEI_LongWordWrite ((u32) LQ_RCU_RST,
-		arc_debug_data | LQ_RCU_RST_REQ_DFE | LQ_RCU_RST_REQ_AFE);
+	IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &arc_debug_data);
+	IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST,
+		arc_debug_data | LTQ_RCU_RST_REQ_DFE | LTQ_RCU_RST_REQ_AFE);
 
 	// reset ARC
 	IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_RST_CTRL, MEI_SOFT_RESET);
@@ -1034,8 +1050,8 @@ IFX_MEI_ArcJtagEnable (DSL_DEV_Device_t *dev, int enable)
 		ifxmips_port_clear_altsel1(0, 11);
 		ifxmips_port_set_open_drain(0, 11);
         //enable ARC JTAG
-        IFX_MEI_LongWordRead ((u32) LQ_RCU_RST, &reg_data);
-        IFX_MEI_LongWordWrite ((u32) LQ_RCU_RST, reg_data | LQ_RCU_RST_REQ_ARC_JTAG);
+        IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &reg_data);
+        IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data | LTQ_RCU_RST_REQ_ARC_JTAG);
 		break;
 	case 0:
 	default:
@@ -1045,8 +1061,6 @@ jtag_end:
 	if (meierr)
 		return DSL_DEV_MEI_ERR_FAILURE;
 */
-	printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
-	printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
 
 	return DSL_DEV_MEI_ERR_SUCCESS;
 };
@@ -1333,17 +1347,17 @@ IFX_MEI_RunAdslModem (DSL_DEV_Device_t *pDev)
 
 	IFX_MEI_DownloadBootCode (pDev);
 
-	im0_register = (*LQ_ICU_IM0_IER) & (1 << 20);
-	im2_register = (*LQ_ICU_IM2_IER) & (1 << 20);
+	im0_register = (*LTQ_ICU_IM0_IER) & (1 << 20);
+	im2_register = (*LTQ_ICU_IM2_IER) & (1 << 20);
 	/* Turn off irq */
-	#ifdef CONFIG_LANTIQ_AMAZON_SE
+	#ifdef CONFIG_SOC_AMAZON_SE
 	disable_irq (IFXMIPS_USB_OC_INT0);
 	disable_irq (IFXMIPS_USB_OC_INT2);
 	#elif defined(CONFIG_LANTIQ_AR9)
 	disable_irq (IFXMIPS_USB_OC_INT0);
 	disable_irq (IFXMIPS_USB_OC_INT2);
-	#elif defined(CONFIG_SOC_LANTIQ_XWAY)
-	disable_irq (LQ_USB_OC_INT);
+	#elif defined(CONFIG_SOC_XWAY)
+	disable_irq (LTQ_USB_OC_INT);
 	#else
 	#error unkonwn arch
 	#endif
@@ -1353,14 +1367,14 @@ IFX_MEI_RunAdslModem (DSL_DEV_Device_t *pDev)
 
 	MEI_WAIT_EVENT_TIMEOUT (DSL_DEV_PRIVATE(pDev)->wait_queue_modemready, 1000);
 
-	#ifdef CONFIG_LANTIQ_AMAZON_SE
+	#ifdef CONFIG_SOC_AMAZON_SE
 	MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT0);
 	MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT2);
 	#elif defined(CONFIG_LANTIQ_AMAZON_S)
 	MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT0);
 	MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT2);
-	#elif defined(CONFIG_SOC_LANTIQ_XWAY)
-	MEI_MASK_AND_ACK_IRQ (LQ_USB_OC_INT);
+	#elif defined(CONFIG_SOC_XWAY)
+	MEI_MASK_AND_ACK_IRQ (LTQ_USB_OC_INT);
 	#else
 	#error unkonwn arch
 	#endif
@@ -1368,8 +1382,8 @@ IFX_MEI_RunAdslModem (DSL_DEV_Device_t *pDev)
 
 	/* Re-enable irq */
 	enable_irq(pDev->nIrq[IFX_DYING_GASP]);
-	*LQ_ICU_IM0_IER |= im0_register;
-	*LQ_ICU_IM2_IER |= im2_register;
+	*LTQ_ICU_IM0_IER |= im0_register;
+	*LTQ_ICU_IM2_IER |= im2_register;
 
 	if (DSL_DEV_PRIVATE(pDev)->modem_ready != 1) {
 		IFX_MEI_EMSG ("Modem failed to be ready!\n");
@@ -1780,7 +1794,7 @@ static irqreturn_t IFX_MEI_IrqHandle (int int1, void *void0)
 {
 	u32 scratch;
 	DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) void0;
-#if defined(CONFIG_LQ_MEI_FW_LOOPBACK) && defined(DFE_PING_TEST)
+#if defined(CONFIG_LTQ_MEI_FW_LOOPBACK) && defined(DFE_PING_TEST)
 	dfe_loopback_irq_handler (pDev);
 	return IRQ_HANDLED;
 #endif //CONFIG_AMAZON_S_MEI_FW_LOOPBACK
@@ -1889,7 +1903,7 @@ DSL_BSP_GetEventCB (int (**ifx_adsl_callback)
 }
 #endif
 
-#ifdef CONFIG_LQ_MEI_FW_LOOPBACK
+#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK
 #define mte_reg_base	(0x4800*4+0x20000)
 
 /* Iridia Registers Address Constants */
@@ -1949,20 +1963,20 @@ MEIWriteARCValue (u32 address, u32 value)
 	u32 i, check = 0;
 
 	/* Write address register */
-	IFX_MEI_WRITE_REGISTER_L (address,  ME_DBG_WR_AD + LQ_MEI_BASE_ADDR);
+	IFX_MEI_WRITE_REGISTER_L (address,  ME_DBG_WR_AD + LTQ_MEI_BASE_ADDR);
 
 	/* Write data register */
-	IFX_MEI_WRITE_REGISTER_L (value, ME_DBG_DATA + LQ_MEI_BASE_ADDR);
+	IFX_MEI_WRITE_REGISTER_L (value, ME_DBG_DATA + LTQ_MEI_BASE_ADDR);
 
 	/* wait until complete - timeout at 40 */
 	for (i = 0; i < 40; i++) {
-		check = IFX_MEI_READ_REGISTER_L (ME_ARC2ME_STAT + LQ_MEI_BASE_ADDR);
+		check = IFX_MEI_READ_REGISTER_L (ME_ARC2ME_STAT + LTQ_MEI_BASE_ADDR);
 
 		if ((check & ARC_TO_MEI_DBG_DONE))
 			break;
 	}
 	/* clear the flag */
-	IFX_MEI_WRITE_REGISTER_L (ARC_TO_MEI_DBG_DONE, ME_ARC2ME_STAT + LQ_MEI_BASE_ADDR);
+	IFX_MEI_WRITE_REGISTER_L (ARC_TO_MEI_DBG_DONE, ME_ARC2ME_STAT + LTQ_MEI_BASE_ADDR);
 }
 
 void
@@ -2145,7 +2159,7 @@ DFE_Loopback_Test (void)
 	IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
 	temp = 0;
 	_IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK,
-		(u32) ME_XDATA_BASE_SH +  LQ_MEI_BASE_ADDR, temp);
+		(u32) ME_XDATA_BASE_SH +  LTQ_MEI_BASE_ADDR, temp);
 	IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
 
 	i = IFX_MEI_DFEMemoryAlloc (pDev, SDRAM_SEGMENT_SIZE * 16);
@@ -2155,9 +2169,9 @@ DFE_Loopback_Test (void)
 		for (idx = 0; idx < i; idx++) {
 			DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].type = FREE_RELOAD;
 			IFX_MEI_WRITE_REGISTER_L ((((uint32_t) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address) & 0x0fffffff),
-							LQ_MEI_BASE_ADDR + ME_XMEM_BAR_BASE  + idx * 4);
+							LTQ_MEI_BASE_ADDR + ME_XMEM_BAR_BASE  + idx * 4);
 			IFX_MEI_DMSG("bar%d(%X)=%X\n", idx,
-				LQ_MEI_BASE_ADDR + ME_XMEM_BAR_BASE  +
+				LTQ_MEI_BASE_ADDR + ME_XMEM_BAR_BASE  +
 				idx * 4, (((uint32_t)
 					   ((ifx_mei_device_private_t *)
 					    pDev->pPriv)->adsl_mem_info[idx].
@@ -2271,18 +2285,18 @@ IFX_MEI_InitDevice (int num)
 		sizeof (smmu_mem_info_t) * MAX_BAR_REGISTERS);
 
 	if (num == 0) {
-		pDev->nIrq[IFX_DFEIR]      = LQ_MEI_INT;
-		pDev->nIrq[IFX_DYING_GASP] = LQ_MEI_DYING_GASP_INT;
-		pDev->base_address = LQ_MEI_BASE_ADDR;
+		pDev->nIrq[IFX_DFEIR]      = LTQ_MEI_INT;
+		pDev->nIrq[IFX_DYING_GASP] = LTQ_MEI_DYING_GASP_INT;
+		pDev->base_address = KSEG1 + LTQ_MEI_BASE_ADDR;
 
                 /* Power up MEI */
 #ifdef CONFIG_LANTIQ_AMAZON_SE
-		*LQ_PMU_PWDCR &= ~(1 << 9);  // enable dsl
-                *LQ_PMU_PWDCR &= ~(1 << 15); // enable AHB base
+		*LTQ_PMU_PWDCR &= ~(1 << 9);  // enable dsl
+                *LTQ_PMU_PWDCR &= ~(1 << 15); // enable AHB base
 #else
-        	temp = lq_r32(LQ_PMU_PWDCR);
+        	temp = ltq_r32(LTQ_PMU_PWDCR);
         	temp &= 0xffff7dbe;
-        	lq_w32(temp, LQ_PMU_PWDCR);
+        	ltq_w32(temp, LTQ_PMU_PWDCR);
 #endif
 	}
 	pDev->nInUse = 0;
@@ -2443,7 +2457,7 @@ IFX_MEI_Ioctls (DSL_DEV_Device_t * pDev, int from_kernel, unsigned int command,
 {
 	int i = 0;
 	int meierr = DSL_DEV_MEI_ERR_SUCCESS;
-	u32 base_address = LQ_MEI_BASE_ADDR;
+	u32 base_address = LTQ_MEI_BASE_ADDR;
 	DSL_DEV_WinHost_Message_t winhost_msg, m;
 	DSL_DEV_MeiDebug_t debugrdwr;
 	DSL_DEV_MeiReg_t regrdwr;
@@ -2569,10 +2583,10 @@ IFX_MEI_Ioctls (DSL_DEV_Device_t * pDev, int from_kernel, unsigned int command,
 		IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&bsp_mei_version), sizeof (DSL_DEV_Version_t));
 		break;
 
-#define LQ_MPS_CHIPID_VERSION_GET(value)  (((value) >> 28) & ((1 << 4) - 1))
+#define LTQ_MPS_CHIPID_VERSION_GET(value)  (((value) >> 28) & ((1 << 4) - 1))
 	case DSL_FIO_BSP_GET_CHIP_INFO:
                 bsp_chip_info.major = 1;
-                bsp_chip_info.minor = LQ_MPS_CHIPID_VERSION_GET(*LQ_MPS_CHIPID);
+                bsp_chip_info.minor = LTQ_MPS_CHIPID_VERSION_GET(*LTQ_MPS_CHIPID);
                 IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&bsp_chip_info), sizeof (DSL_DEV_HwVersion_t));
                 meierr = DSL_DEV_MEI_ERR_SUCCESS;
 		break;
@@ -2608,7 +2622,7 @@ IFX_MEI_Ioctls (DSL_DEV_Device_t * pDev, int from_kernel, unsigned int command,
 void AMAZON_SE_MEI_ARC_MUX_Test(void)
 {
 	u32 *p, i;
-	*LQ_RCU_RST |= LQ_RCU_RST_REQ_MUX_ARC;
+	*LTQ_RCU_RST |= LTQ_RCU_RST_REQ_MUX_ARC;
 
 	p = (u32*)(DFE_LDST_BASE_ADDR + IRAM0_BASE);
 	IFX_MEI_EMSG("Writing to IRAM0(%p)...\n", p);
@@ -2657,7 +2671,7 @@ void AMAZON_SE_MEI_ARC_MUX_Test(void)
 		if (*p != 0xdeadbeef)
 			IFX_MEI_EMSG("%p: %#x\n", p, *p);
 	}
-	*LQ_RCU_RST &= ~LQ_RCU_RST_REQ_MUX_ARC;
+	*LTQ_RCU_RST &= ~LTQ_RCU_RST_REQ_MUX_ARC;
 }
 #endif
 int
@@ -2959,7 +2973,7 @@ IFX_MEI_ModuleInit (void)
 		for (i = 0; i <= DSL_BSP_CB_LAST ; i++)
 		dsl_bsp_event_callback[i].function = NULL;
 
-#ifdef CONFIG_LQ_MEI_FW_LOOPBACK
+#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK
 	IFX_MEI_DMSG("Start loopback test...\n");
 	DFE_Loopback_Test ();
 #endif

+ 12 - 0
package/ltq-ifxos/patches/120-linaro.patch

@@ -9,3 +9,15 @@
  #  error "missing endian definiton"
  #endif
  
+--- a/src/linux/ifxos_linux_thread_drv.c
++++ b/src/linux/ifxos_linux_thread_drv.c
+@@ -34,7 +34,9 @@
+ #include <linux/sched.h>
+ #include <linux/version.h>
+ #include <linux/completion.h>
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+ #include <linux/smp_lock.h>
++#endif
+ #include <linux/signal.h>
+ 
+ 

+ 47 - 4
package/ltq-tapi/patches/200-linux-37.patch

@@ -1,6 +1,26 @@
 --- a/src/drv_tapi_linux.c
 +++ b/src/drv_tapi_linux.c
-@@ -146,8 +146,13 @@ static ssize_t ifx_tapi_write(struct fil
+@@ -47,7 +47,9 @@
+ #include <linux/errno.h>
+ #include <asm/uaccess.h>               /* copy_from_user(), ... */
+ #include <asm/byteorder.h>
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+ #include <linux/smp_lock.h>         /* lock_kernel() */
++#endif
+ #include <asm/io.h>
+ 
+ #ifdef LINUX_2_6
+@@ -65,7 +67,9 @@
+ #else
+    #include <linux/tqueue.h>
+    #include <linux/sched.h>
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
+    #include <linux/smp_lock.h>         /* lock_kernel() */
++#endif
+ #endif /* LINUX_2_6 */
+ 
+ #include "drv_tapi.h"
+@@ -133,8 +137,13 @@
                                size_t count, loff_t * ppos);
  static ssize_t ifx_tapi_read(struct file * filp, char *buf,
                                size_t length, loff_t * ppos);
@@ -14,7 +34,7 @@
  static unsigned int ifx_tapi_poll (struct file *filp, poll_table *table);
  
  #ifdef CONFIG_PROC_FS
-@@ -231,7 +236,11 @@ IFX_return_t TAPI_OS_RegisterLLDrv (IFX_
+@@ -218,7 +227,11 @@
     IFX_char_t   *pRegDrvName = IFX_NULL;
     IFX_int32_t ret = 0;
  
@@ -26,7 +46,7 @@
     {
  #ifdef MODULE
        tapi_fops.owner =    THIS_MODULE;
-@@ -239,7 +248,11 @@ IFX_return_t TAPI_OS_RegisterLLDrv (IFX_
+@@ -226,7 +239,11 @@
        tapi_fops.read =     ifx_tapi_read;
        tapi_fops.write =    ifx_tapi_write;
        tapi_fops.poll =     ifx_tapi_poll;
@@ -38,7 +58,7 @@
        tapi_fops.open =     ifx_tapi_open;
        tapi_fops.release =  ifx_tapi_release;
     }
-@@ -894,8 +907,13 @@ static IFX_uint32_t ifx_tapi_poll (struc
+@@ -881,8 +898,13 @@
     - 0 and positive values - success
     - negative value - ioctl failed
  */
@@ -52,6 +72,29 @@
  {
     TAPI_FD_PRIV_DATA_t *pTapiPriv;
     IFX_TAPI_ioctlCtx_t  ctx;
+@@ -3721,7 +3743,9 @@
+             kernel lock (lock_kernel()). The lock must be
+             grabbed before changing the terminate
+             flag and released after the down() call. */
+-         lock_kernel();
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
++	 lock_kernel();
++#endif
+          mb();
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
+          kill_proc(pThrCntrl->tid, SIGKILL, 1);
+@@ -3729,8 +3753,10 @@
+          kill_pid(find_vpid(pThrCntrl->tid), SIGKILL, 1);
+ #endif
+          /* release the big kernel lock */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+          unlock_kernel();
+-         wait_for_completion (&pThrCntrl->thrCompletion);
++#endif
++	 wait_for_completion (&pThrCntrl->thrCompletion);
+ 
+ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
+          /* Now we are sure the thread is in zombie state.
 --- a/src/lib/lib_fifo/lib_fifo.c
 +++ b/src/lib/lib_fifo/lib_fifo.c
 @@ -41,7 +41,7 @@

+ 6 - 6
package/ltq-vmmc/patches/100-ifxmips.patch

@@ -33,7 +33,7 @@
  
  #if defined SYSTEM_DANUBE
 -#include <asm/ifx/ifx_gpio.h>
-+#include <xway/xway.h>
++#include <lantiq_soc.h>
 +
  #else
  #error no system selected
@@ -158,7 +158,7 @@
 +#  define ifx_gptu_timer_free       lq_free_timer
 +
 +
-+#  define bsp_mask_and_ack_irq      lq_mask_and_ack_irq
++#  define bsp_mask_and_ack_irq      ltq_mask_and_ack_irq
 +#else
 +#  include <asm/ifx/ifx_regs.h>
 +#  include <asm/ifx/ifx_gptu.h>
@@ -443,14 +443,14 @@
 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28))
 +IFX_uint32_t ifx_get_cp1_size(IFX_void_t)
 +{
-+	return 2;
++	return 1;
 +}
 +
-+unsigned int *lq_get_cp1_base(void);
++unsigned int *ltq_get_cp1_base(void);
 +
 +IFX_uint32_t *ifx_get_cp1_base(IFX_void_t)
 +{
-+	return lq_get_cp1_base();
++	return ltq_get_cp1_base();
 +}
 +#endif
 +
@@ -501,7 +501,7 @@
 +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28))
 +#  include <lantiq.h>
 +#  include <irq.h>
-+#  include <xway/xway.h>
++#  include <lantiq_soc.h>
 +#  include <gpio.h>
 +#define IFXMIPS_MPS_SRAM		((u32 *)(KSEG1 + 0x1F200000))
 +#define IFXMIPS_MPS_BASE_ADDR		(KSEG1 + 0x1F107000)

+ 94 - 8
package/ltq-vmmc/patches/200-kernel-37.patch

@@ -1,6 +1,6 @@
 --- a/src/drv_vmmc_init.c
 +++ b/src/drv_vmmc_init.c
-@@ -784,7 +784,7 @@ IFX_int32_t VMMC_TAPI_LL_FW_Start(IFX_TA
+@@ -784,7 +784,7 @@
        dwld.fwDwld.length = IoInit.pram_size;
  
       /* download firmware */
@@ -9,7 +9,7 @@
                            (IFX_uint32_t) &dwld.fwDwld);
     }
  
-@@ -1594,7 +1594,7 @@ IFX_void_t VMMC_DeviceDriverStop(IFX_voi
+@@ -1594,7 +1594,7 @@
  #ifdef VMMC_DRIVER_UNLOAD_HOOK
     if (VDevices[0].nDevState & DS_GPIO_RESERVED)
     {
@@ -20,7 +20,7 @@
        {
 --- a/src/mps/drv_mps_vmmc_linux.c
 +++ b/src/mps/drv_mps_vmmc_linux.c
-@@ -110,7 +110,7 @@ IFX_int32_t ifx_mps_get_status_proc (IFX
+@@ -110,7 +110,7 @@
  #ifndef __KERNEL__
  IFX_int32_t ifx_mps_open (struct inode *inode, struct file *file_p);
  IFX_int32_t ifx_mps_close (struct inode *inode, struct file *file_p);
@@ -29,7 +29,7 @@
                             IFX_uint32_t nCmd, IFX_ulong_t arg);
  IFX_int32_t ifx_mps_read_mailbox (mps_devices type, mps_message * rw);
  IFX_int32_t ifx_mps_write_mailbox (mps_devices type, mps_message * rw);
-@@ -171,7 +171,7 @@ IFX_char_t voice_channel_int_name[NUM_VO
+@@ -171,7 +171,7 @@
  static struct file_operations ifx_mps_fops = {
   owner:THIS_MODULE,
   poll:ifx_mps_poll,
@@ -38,7 +38,7 @@
   open:ifx_mps_open,
   release:ifx_mps_close
  };
-@@ -614,7 +614,7 @@ static IFX_uint32_t ifx_mps_poll (struct
+@@ -614,7 +614,7 @@
   * \return  -ENOIOCTLCMD Invalid command
   * \ingroup API
   */
@@ -47,7 +47,7 @@
                             IFX_uint32_t nCmd, IFX_ulong_t arg)
  {
     IFX_int32_t retvalue = -EINVAL;
-@@ -629,17 +629,18 @@ IFX_int32_t ifx_mps_ioctl (struct inode 
+@@ -629,17 +629,18 @@
        'mps_devices' enum type, which in fact is [0..8]; So, if inode value is
        [0..NUM_VOICE_CHANNEL+1], then we make sure that we are calling from
        kernel space. */
@@ -71,7 +71,7 @@
     {
 --- a/src/drv_vmmc_ioctl.c
 +++ b/src/drv_vmmc_ioctl.c
-@@ -427,18 +427,18 @@ IFX_int32_t VMMC_Dev_Spec_Ioctl (IFX_TAP
+@@ -427,18 +427,18 @@
           /* MPS driver will do the USR2KERN so just pass on the pointer. */
           dwnld_struct.data = (IFX_void_t *)IoInit.pPRAMfw;
  
@@ -95,7 +95,7 @@
        case FIO_LASTERR:
 --- a/src/mps/drv_mps_vmmc.h
 +++ b/src/mps/drv_mps_vmmc.h
-@@ -279,7 +279,7 @@ typedef struct
+@@ -279,7 +279,7 @@
  #include <linux/fs.h>
  IFX_int32_t ifx_mps_open (struct inode *inode, struct file *file_p);
  IFX_int32_t ifx_mps_close (struct inode *inode, struct file *filp);
@@ -104,3 +104,89 @@
                             IFX_uint32_t nCmd, unsigned long arg);
  IFX_int32_t ifx_mps_register_data_callback (mps_devices type, IFX_uint32_t dir,
                                              IFX_void_t (*callback) (mps_devices
+--- a/src/drv_vmmc_linux.c
++++ b/src/drv_vmmc_linux.c
+@@ -32,7 +32,11 @@
+ #ifdef LINUX_2_6
+ #include <linux/version.h>
+ #ifndef UTS_RELEASE
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
++#include <linux/utsrelease.h>
++#else
+ #include <generated/utsrelease.h>
++#endif
+ #endif /* UTC_RELEASE */
+ #undef CONFIG_DEVFS_FS
+ #endif /* LINUX_2_6 */
+--- a/src/mps/drv_mps_vmmc_common.c
++++ b/src/mps/drv_mps_vmmc_common.c
+@@ -22,7 +22,11 @@
+ #undef USE_PLAIN_VOICE_FIRMWARE
+ #undef PRINT_ON_ERR_INTERRUPT
+ #undef FAIL_ON_ERR_INTERRUPT
+-#include <generated/autoconf.h>
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
++#include <linux/utsrelease.h>
++#else
++#include <generated/utsrelease.h>
++#endif
+ #include <linux/interrupt.h>
+ #include <linux/delay.h>
+ 
+@@ -47,8 +51,19 @@
+ #  define ifx_gptu_timer_free       lq_free_timer
+ 
+ 
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+ #  define bsp_mask_and_ack_irq      ltq_mask_and_ack_irq
+ #else
++extern void ltq_mask_and_ack_irq(struct irq_data *d);
++static void inline bsp_mask_and_ack_irq(int x)
++{
++	struct irq_data d;
++	d.irq = x;
++	ltq_mask_and_ack_irq(&d);
++}
++#endif
++
++#else
+ #  include <asm/ifx/ifx_regs.h>
+ #  include <asm/ifx/ifx_gptu.h>
+ #endif
+@@ -107,7 +122,9 @@
+ extern mps_mbx_dev *ifx_mps_get_device (mps_devices type);
+ 
+ #ifdef LINUX_2_6
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+ extern IFX_void_t bsp_mask_and_ack_irq (IFX_uint32_t irq_nr);
++#endif
+ 
+ #else /* */
+ extern IFX_void_t mask_and_ack_danube_irq (IFX_uint32_t irq_nr);
+--- a/src/mps/drv_mps_vmmc_danube.c
++++ b/src/mps/drv_mps_vmmc_danube.c
+@@ -16,11 +16,16 @@
+ /* ============================= */
+ /* Includes                      */
+ /* ============================= */
++#include "linux/version.h"
+ #include "drv_config.h"
+ 
+ #ifdef SYSTEM_DANUBE            /* defined in drv_mps_vmmc_config.h */
+ 
++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) 
++#include <linux/autoconf.h>
++#else
+ #include <generated/autoconf.h>
++#endif
+ 
+ /* lib_ifxos headers */
+ #include "ifx_types.h"
+@@ -39,6 +44,7 @@
+ #  include <linux/dma-mapping.h>
+ 
+ 
++#define LQ_RCU_BASE_ADDR	(KSEG1 + LTQ_RCU_BASE_ADDR)
+ # define LQ_RCU_RST		((u32 *)(LQ_RCU_BASE_ADDR + 0x0010))
+ #define IFX_RCU_RST_REQ_CPU1             (1 << 3)
+ #  define IFX_RCU_RST_REQ        LQ_RCU_RST

+ 12 - 0
target/linux/generic/patches-2.6.32/251-atm_header_changes.patch

@@ -0,0 +1,12 @@
+--- a/include/linux/atm.h
++++ b/include/linux/atm.h
+@@ -139,6 +139,9 @@ struct atm_trafprm {
+ 	int		min_pcr;	/* minimum PCR in cells per second */
+ 	int		max_cdv;	/* maximum CDV in microseconds */
+ 	int		max_sdu;	/* maximum SDU in bytes */
++	int		scr;		/* sustained rate in cells per second */
++	int		mbs;		/* maximum burst size (MBS) in cells */
++	int		cdv;		/* Cell delay varition */
+         /* extra params for ABR */
+         unsigned int 	icr;         	/* Initial Cell Rate (24-bit) */
+         unsigned int	tbe;		/* Transient Buffer Exposure (24-bit) */ 

+ 12 - 0
target/linux/generic/patches-2.6.39/652-atm_header_changes.patch

@@ -0,0 +1,12 @@
+--- a/include/linux/atm.h
++++ b/include/linux/atm.h
+@@ -139,6 +139,9 @@ struct atm_trafprm {
+ 	int		min_pcr;	/* minimum PCR in cells per second */
+ 	int		max_cdv;	/* maximum CDV in microseconds */
+ 	int		max_sdu;	/* maximum SDU in bytes */
++	int		scr;		/* sustained rate in cells per second */
++	int		mbs;		/* maximum burst size (MBS) in cells */
++	int		cdv;		/* Cell delay varition */
+         /* extra params for ABR */
+         unsigned int 	icr;         	/* Initial Cell Rate (24-bit) */
+         unsigned int	tbe;		/* Transient Buffer Exposure (24-bit) */ 

+ 3 - 2
target/linux/lantiq/Makefile

@@ -10,9 +10,10 @@ ARCH:=mips
 BOARD:=lantiq
 BOARDNAME:=Lantiq GPON/XWAY
 FEATURES:=squashfs jffs2
-SUBTARGETS:=falcon xway
+SUBTARGETS:=falcon xway ase
 
-LINUX_VERSION:=2.6.37.6
+LINUX_VERSION:=2.6.39
+#LINUX_VERSION:=2.6.32.33
 
 CFLAGS=-Os -pipe -mips32r2 -mtune=mips32r2 -fno-caller-saves
 

+ 15 - 0
target/linux/lantiq/ase/config-2.6.32

@@ -0,0 +1,15 @@
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+# CONFIG_DM9000 is not set
+CONFIG_INPUT=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_GPIO_BUTTONS is not set
+CONFIG_INPUT_POLLDEV=y
+# CONFIG_ISDN is not set
+CONFIG_LANTIQ_ETOP=y
+CONFIG_LANTIQ_MACH_EASY50601=y
+CONFIG_SOC_AMAZON_SE=y
+# CONFIG_SOC_FALCON is not set
+CONFIG_SOC_TYPE_XWAY=y
+# CONFIG_SOC_XWAY is not set
+# CONFIG_I2C_DESIGNWARE is not set

+ 39 - 0
target/linux/lantiq/ase/config-default

@@ -0,0 +1,39 @@
+# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+# CONFIG_ATH79 is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+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_INPUT=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_GPIO_BUTTONS is not set
+CONFIG_INPUT_POLLDEV=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_SOC_AMAZON_SE=y
+# CONFIG_SOC_FALCON is not set
+CONFIG_SOC_TYPE_XWAY=y
+# CONFIG_SOC_XWAY is not set
+CONFIG_XZ_DEC=y

+ 6 - 0
target/linux/lantiq/ase/profiles/000-generic.mk

@@ -0,0 +1,6 @@
+define Profile/Generic
+  NAME:=Generic - all boards
+  PACKAGES:=kmod-leds-gpio button-hotplug
+endef
+
+$(eval $(call Profile,Generic))

+ 10 - 0
target/linux/lantiq/ase/profiles/001-lantiq.mk

@@ -0,0 +1,10 @@
+define Profile/EASY50601
+  NAME:=EASY50601
+  PACKAGES:= kmod-usb-core kmod-usb-dwc-otg kmod-leds-gpio
+endef
+
+define Profile/EASY50601/Description
+	Lantiq EASY50601 evalkit
+endef
+
+$(eval $(call Profile,EASY50601))

+ 10 - 0
target/linux/lantiq/ase/target.mk

@@ -0,0 +1,10 @@
+ARCH:=mips
+SUBTARGET:=ase
+BOARDNAME:=Amazon-SE
+FEATURES:=squashfs jffs2 atm
+
+DEFAULT_PACKAGES+=kmod-pppoa ppp-mod-pppoa linux-atm atm-tools br2684ctl kmod-ltq-dsl ltq-dsl-app
+
+define Target/Description
+	Lantiq ASE
+endef

+ 2 - 2
target/linux/lantiq/base-files/etc/inittab

@@ -1,4 +1,4 @@
 ::sysinit:/etc/init.d/rcS S boot
 ::shutdown:/etc/init.d/rcS K stop
-ttyS0::askfirst:/bin/ash --login
-ttyS1::askfirst:/bin/ash --login
+ttyLTQ0::askfirst:/bin/ash --login
+ttyLTQ1::askfirst:/bin/ash --login

+ 149 - 0
target/linux/lantiq/config-2.6.32

@@ -0,0 +1,149 @@
+CONFIG_32BIT=y
+# CONFIG_64BIT is not set
+# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
+# CONFIG_AR7 is not set
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+CONFIG_ARCH_SUPPORTS_OPROFILE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+# CONFIG_BCM47XX is not set
+# CONFIG_BCM63XX is not set
+CONFIG_BITREVERSE=y
+CONFIG_BOOT_RAW=y
+# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
+# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
+CONFIG_CEVT_R4K=y
+CONFIG_CEVT_R4K_LIB=y
+CONFIG_CFG80211_DEFAULT_PS_VALUE=0
+CONFIG_CPU_BIG_ENDIAN=y
+# CONFIG_CPU_CAVIUM_OCTEON is not set
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_CPU_HAS_SYNC=y
+# CONFIG_CPU_LITTLE_ENDIAN is not set
+# CONFIG_CPU_LOONGSON2E is not set
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R2=y
+# CONFIG_CPU_MIPS64_R1 is not set
+# CONFIG_CPU_MIPS64_R2 is not set
+CONFIG_CPU_MIPSR2=y
+# CONFIG_CPU_NEVADA is not set
+# CONFIG_CPU_R10000 is not set
+# CONFIG_CPU_R3000 is not set
+# CONFIG_CPU_R4300 is not set
+# CONFIG_CPU_R4X00 is not set
+# CONFIG_CPU_R5000 is not set
+# CONFIG_CPU_R5432 is not set
+# CONFIG_CPU_R5500 is not set
+# CONFIG_CPU_R6000 is not set
+# CONFIG_CPU_R8000 is not set
+# CONFIG_CPU_RM7000 is not set
+# CONFIG_CPU_RM9000 is not set
+# CONFIG_CPU_SB1 is not set
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+# CONFIG_CPU_TX39XX is not set
+# CONFIG_CPU_TX49XX is not set
+# CONFIG_CPU_VR41XX is not set
+CONFIG_CSRC_R4K=y
+CONFIG_CSRC_R4K_LIB=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DMA_NEED_PCI_MAP_STATE=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_FSNOTIFY is not set
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_HARDWARE_WATCHPOINTS=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAVE_ARCH_KGDB=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_HAVE_IDE=y
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HW_RANDOM=y
+CONFIG_HZ=250
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+CONFIG_IFX_UDP_REDIRECT=y
+CONFIG_IMAGE_CMDLINE_HACK=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_IRQ_CPU=y
+CONFIG_LANTIQ=y
+CONFIG_LANTIQ_WDT=y
+CONFIG_LEDS_GPIO=y
+# CONFIG_MACH_ALCHEMY is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_LOONGSON is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+CONFIG_MIPS=y
+# CONFIG_MIPS_COBALT is not set
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_MIPS_MACHINE=y
+# CONFIG_MIPS_MALTA is not set
+CONFIG_MIPS_MT_DISABLED=y
+# CONFIG_MIPS_MT_SMP is not set
+# CONFIG_MIPS_MT_SMTC is not set
+# CONFIG_MIPS_SIM is not set
+# CONFIG_MIPS_VPE_LOADER is not set
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_LANTIQ=y
+CONFIG_MTD_UIMAGE_SPLIT=y
+CONFIG_NLS=y
+# CONFIG_NO_IOPORT is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_PHYLIB=y
+# CONFIG_PMC_MSP is not set
+# CONFIG_PMC_YOSEMITE is not set
+# CONFIG_PNX8550_JBS is not set
+# CONFIG_PNX8550_STB810 is not set
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SERIAL_8250 is not set
+CONFIG_SERIAL_LANTIQ=y
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_SWARM is not set
+CONFIG_SWAP_IO_SPACE=y
+CONFIG_SWCONFIG=y
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_MULTITHREADING=y
+CONFIG_TRAD_SIGNALS=y
+# CONFIG_TREE_PREEMPT_RCU is not set
+CONFIG_TREE_RCU=y
+CONFIG_ZONE_DMA_FLAG=0

+ 4 - 38
target/linux/lantiq/config-default

@@ -5,28 +5,26 @@ CONFIG_32BIT=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
 CONFIG_ARCH_HIBERNATION_POSSIBLE=y
-# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
 CONFIG_ARCH_POPULATES_NODE_MAP=y
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 CONFIG_ARCH_SUPPORTS_OPROFILE=y
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
-# CONFIG_AUTO_IRQ_AFFINITY is not set
 # CONFIG_BCM47XX is not set
 # CONFIG_BCM63XX is not set
 CONFIG_BITREVERSE=y
-CONFIG_BKL=y
+CONFIG_BOOT_RAW=y
 # CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
 # CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
 CONFIG_CEVT_R4K=y
 CONFIG_CEVT_R4K_LIB=y
+CONFIG_CFG80211_DEFAULT_PS_VALUE=0
 CONFIG_CPU_BIG_ENDIAN=y
 # CONFIG_CPU_CAVIUM_OCTEON is not set
 CONFIG_CPU_HAS_PREFETCH=y
 CONFIG_CPU_HAS_SYNC=y
 # CONFIG_CPU_LITTLE_ENDIAN is not set
 # CONFIG_CPU_LOONGSON2E is not set
-# CONFIG_CPU_LOONGSON2F is not set
 CONFIG_CPU_MIPS32=y
 # CONFIG_CPU_MIPS32_R1 is not set
 CONFIG_CPU_MIPS32_R2=y
@@ -54,63 +52,43 @@ CONFIG_CPU_SUPPORTS_HIGHMEM=y
 CONFIG_CSRC_R4K=y
 CONFIG_CSRC_R4K_LIB=y
 CONFIG_DECOMPRESS_LZMA=y
-CONFIG_DEVPORT=y
-# CONFIG_DM9000 is not set
 CONFIG_DMA_NEED_PCI_MAP_STATE=y
 CONFIG_DMA_NONCOHERENT=y
 CONFIG_EARLY_PRINTK=y
 # CONFIG_FSNOTIFY is not set
-CONFIG_GENERIC_ATOMIC64=y
 CONFIG_GENERIC_CLOCKEVENTS=y
 CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
 CONFIG_GENERIC_CMOS_UPDATE=y
 CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_GENERIC_FIND_NEXT_BIT=y
 CONFIG_GENERIC_GPIO=y
-# CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set
 CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-# CONFIG_GENERIC_PENDING_IRQ is not set
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
-# CONFIG_HARDIRQS_SW_RESEND is not set
 CONFIG_HARDWARE_WATCHPOINTS=y
 CONFIG_HAS_DMA=y
 CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAVE_ARCH_KGDB=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_CLK=y
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
-CONFIG_HAVE_GENERIC_HARDIRQS=y
-# CONFIG_HAVE_IDE is not set
+CONFIG_HAVE_IDE=y
 CONFIG_HAVE_OPROFILE=y
-CONFIG_HAVE_PERF_EVENTS=y
-# CONFIG_HAVE_SPARSE_IRQ is not set
 CONFIG_HW_RANDOM=y
 CONFIG_HZ=250
 # CONFIG_HZ_100 is not set
 CONFIG_HZ_250=y
-# CONFIG_I2C_FALCON is not set
 CONFIG_IFX_UDP_REDIRECT=y
 CONFIG_IMAGE_CMDLINE_HACK=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_IRQ_CPU=y
-# CONFIG_IRQ_PER_CPU is not set
 CONFIG_LANTIQ=y
 CONFIG_LANTIQ_WDT=y
 CONFIG_LEDS_GPIO=y
-CONFIG_LOONGSON_UART_BASE=y
 # CONFIG_MACH_ALCHEMY is not set
 # CONFIG_MACH_DECSTATION is not set
 # CONFIG_MACH_JAZZ is not set
 # CONFIG_MACH_LOONGSON is not set
-CONFIG_MACH_NO_WESTBRIDGE=y
 # CONFIG_MACH_TX39XX is not set
 # CONFIG_MACH_TX49XX is not set
 # CONFIG_MACH_VR41XX is not set
@@ -130,28 +108,19 @@ CONFIG_MTD_CFI_GEOMETRY=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_LANTIQ=y
 CONFIG_MTD_UIMAGE_SPLIT=y
-CONFIG_NEED_DMA_MAP_STATE=y
-CONFIG_NEED_PER_CPU_KM=y
 CONFIG_NLS=y
 # CONFIG_NO_IOPORT is not set
 # CONFIG_NXP_STB220 is not set
 # CONFIG_NXP_STB225 is not set
 CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_PCI=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PERF_USE_VMALLOC=y
 CONFIG_PHYLIB=y
 # CONFIG_PMC_MSP is not set
 # CONFIG_PMC_YOSEMITE is not set
 # CONFIG_PNX8550_JBS is not set
 # CONFIG_PNX8550_STB810 is not set
-# CONFIG_POWERTV is not set
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_QUOTACTL is not set
 CONFIG_SCHED_OMIT_FRAME_POINTER=y
 # CONFIG_SCSI_DMA is not set
 # CONFIG_SERIAL_8250 is not set
-# CONFIG_SERIAL_8250_EXTENDED is not set
 CONFIG_SERIAL_LANTIQ=y
 # CONFIG_SGI_IP22 is not set
 # CONFIG_SGI_IP27 is not set
@@ -165,7 +134,6 @@ CONFIG_SERIAL_LANTIQ=y
 # CONFIG_SIBYTE_RHONE is not set
 # CONFIG_SIBYTE_SENTOSA is not set
 # CONFIG_SIBYTE_SWARM is not set
-CONFIG_SOC_LANTIQ=y
 CONFIG_SWAP_IO_SPACE=y
 CONFIG_SWCONFIG=y
 CONFIG_SYS_HAS_CPU_MIPS32_R1=y
@@ -175,8 +143,6 @@ CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
 CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
 CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
 CONFIG_SYS_SUPPORTS_MULTITHREADING=y
-# CONFIG_TC35815 is not set
-CONFIG_TINY_RCU=y
 CONFIG_TRAD_SIGNALS=y
 # CONFIG_TREE_PREEMPT_RCU is not set
 CONFIG_TREE_RCU=y

+ 0 - 9
target/linux/lantiq/extract.py

@@ -1,9 +0,0 @@
-#!/usr/bin/python
-from sys import stdin, stdout
-while True:
-	c = stdin.read(2)
-	if len(c) < 2:
-		break
-	n1, n2 = ord(c[0]), ord(c[1])
-	stdout.write(chr(((n2 & 15) << 4) + ((n2 & 240) >> 4)))
-	stdout.write(chr(((n1 & 15) << 4) + ((n1 & 240) >> 4)))

+ 0 - 44
target/linux/lantiq/extract.sh

@@ -1,44 +0,0 @@
-#!/bin/sh
-
-DIR="$1/"
-FILE="$1/$2"
-
-echo "This tool downloads the arcor a800 firmware release and extracts the voip firmware for the danube."
-echo "Please only do so if it is legal in your country"
-
-[ ! -f ${FILE} ] && {
-	echo ${FILE} is missing
-	exit 1
-}
-
-[ -f ${DIR}/ifxmips_fw_decodev2.tar.bz2 -a ! -f ${DIR}voip_coef.bin ] && {
-	[ ! -f ${DIR}decode_ifx_fw && -f ${DIR}ifxmips_fw_decodev2.tar.bz2 ] && {
-		tar xjf ${DIR}ifxmips_fw_decodev2.tar.bz2 ifxmips_fw_decode/decode.c -O > ${DIR}decode.c
-		gcc -o ${DIR}decode_ifx_fw ${DIR}decode.c
-	}
-	[ ! -f ${DIR}decode_ifx_fw ] && {
-		[ ! -f ${DIR}voip_coef.lzma ] && {
-			${DIR}decode_ifx_fw $FILE ${DIR}voip_coef.lzma
-		}
-		lzma d ${DIR}voip_coef.lzma ${DIR}voip_coef.bin
-	}
-}
-[ ! -f ${DIR}dsl_a.bin ] && {
-	dd if=${FILE} of=${DIR}dsl1.lzma bs=1 skip=2168832 count=150724
-	lzma d ${DIR}dsl2.lzma ${DIR}dsl_a.bin
-}
-
-[ ! -f ${DIR}dsl_b.bin ] && {
-	dd if=${FILE} of=${DIR}dsl2.lzma bs=1 skip=2320384 count=148343
-	lzma d ${DIR}dsl1.lzma ${DIR}dsl_b.bin
-}
-
-[ ! -f ${DIR}voip.bin ] && {
-	dd if=${FILE} of=${DIR}voip.lzma bs=1 skip=2468864 count=452105
-	lzma d ${DIR}voip.lzma ${DIR}voip.bin
-}
-exit 0
-
-# get lzma offsets
-# hexdump -C arcor_A800_452CPW_FW_1.02.206\(20081201\).bin | grep "5d 00 00 80"
-# hexdump -C arcor_A800_452CPW_FW_1.02.206\(20081201\).bin | grep "00 d5 08 00"

+ 33 - 0
target/linux/lantiq/falcon/config-2.6.32

@@ -0,0 +1,33 @@
+CONFIG_CPU_MIPSR2_IRQ_EI=y
+CONFIG_CPU_MIPSR2_IRQ_VI=y
+# CONFIG_CRYPTO is not set
+CONFIG_DM9000=y
+CONFIG_DM9000_DEBUGLEVEL=4
+CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_DESIGNWARE is not set
+CONFIG_I2C_FALCON=y
+CONFIG_IFX_VPE_CACHE_SPLIT=y
+CONFIG_IFX_VPE_EXT=y
+CONFIG_LANTIQ_MACH_95C3AM1=y
+CONFIG_LANTIQ_MACH_EASY98000=y
+CONFIG_LANTIQ_MACH_EASY98020=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_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_SPI=y
+# CONFIG_SPI_BITBANG is not set
+CONFIG_SPI_FALCON=y
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_MASTER=y
+# CONFIG_SPI_SPIDEV is not set

+ 39 - 7
target/linux/lantiq/falcon/config-default

@@ -1,31 +1,63 @@
+# CONFIG_ALTERA_STAPL is not set
+# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
+# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
+# CONFIG_ATH79 is not set
 CONFIG_CPU_MIPSR2_IRQ_EI=y
 CONFIG_CPU_MIPSR2_IRQ_VI=y
 # CONFIG_CRYPTO is not set
 CONFIG_DM9000=y
 CONFIG_DM9000_DEBUGLEVEL=4
 CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
-CONFIG_HAVE_IDE=y
-CONFIG_HW_HAS_PCI=y
+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_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_FALCON=y
+# CONFIG_I2C_PXA_PCI is not set
 CONFIG_IFX_VPE_CACHE_SPLIT=y
 CONFIG_IFX_VPE_EXT=y
 CONFIG_LANTIQ_MACH_95C3AM1=y
 CONFIG_LANTIQ_MACH_EASY98000=y
 CONFIG_LANTIQ_MACH_EASY98020=y
-CONFIG_LANTIQ_PROM_ASC0=y
-# CONFIG_LANTIQ_PROM_ASC1 is not set
+# CONFIG_LEDS_LM3530 is not set
 CONFIG_M25PXX_USE_FAST_READ=y
+CONFIG_MACH_NO_WESTBRIDGE=y
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set
 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_LATCH_ADDR is not set
 CONFIG_MTD_M25P80=y
 CONFIG_MTSCHED=y
-# CONFIG_PCI is not set
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_PER_CPU_KM=y
 # CONFIG_PERFCTRS is not set
-CONFIG_SOC_LANTIQ_FALCON=y
-# CONFIG_SOC_LANTIQ_XWAY is not set
+CONFIG_PERF_USE_VMALLOC=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_QUOTACTL 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_SPI=y
 # CONFIG_SPI_BITBANG is not set
 CONFIG_SPI_FALCON=y
 # CONFIG_SPI_GPIO is not set
 CONFIG_SPI_MASTER=y
+# CONFIG_TPS6105X is not set
+CONFIG_XZ_DEC=y

+ 24 - 2
target/linux/lantiq/image/Makefile

@@ -9,8 +9,9 @@ include $(INCLUDE_DIR)/image.mk
 
 JFFS2_BLOCKSIZE = 64k 128k 256k
 
-xway_cmdline=-console=ttyS1,115200 rootfstype=squashfs,jffs2
-falcon_cmdline=-console=ttyS0,115200 rootfstype=squashfs,jffs2
+ase_cmdline=-console=ttyLTQ1,115200 rootfstype=squashfs,jffs2
+xway_cmdline=-console=ttyLTQ1,115200 rootfstype=squashfs,jffs2
+falcon_cmdline=-console=ttyLTQ0,115200 rootfstype=squashfs,jffs2
 
 define CompressLzma
   $(STAGING_DIR_HOST)/bin/lzma e $(1) $(2)
@@ -184,6 +185,27 @@ define Image/Build/Profile/Generic
 endef
 endif
 
+ifeq ($(CONFIG_TARGET_lantiq_ase),y)
+define Image/BuildKernel/Profile/EASY50601
+	$(call Image/BuildKernel/Template,EASY50601,$(ase_cmdline))
+endef
+
+define Image/Build/Profile/EASY50601
+	$(call Image/Build/$(1),$(1),EASY50601)
+endef
+
+define Image/BuildKernel/Profile/Generic
+	$(call Image/BuildKernel/Template,EASY50601,$(ase_cmdline))
+	$(call Image/BuildKernel/Template,NONE)
+endef
+
+define Image/Build/Profile/Generic
+	$(call Image/Build/$(1),$(1),EASY50601)
+	$(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

+ 898 - 0
target/linux/lantiq/patches-2.6.32/0001-MIPS-Lantiq-Add-initial-support-for-Lantiq-SoCs.patch

@@ -0,0 +1,898 @@
+From 9e0235e97ea2617beaacaa16ab5f0b9e75f4680e Mon Sep 17 00:00:00 2001
+From: John Crispin <[email protected]>
+Date: Wed, 30 Mar 2011 09:27:47 +0200
+Subject: [PATCH 01/13] MIPS: Lantiq: Add initial support for Lantiq SoCs
+
+Add initial support for Mips based SoCs made by Lantiq. This series will add
+support for the XWAY family.
+
+The series allows booting a minimal system using a initramfs or NOR. Missing
+drivers and support for Amazon and GPON family will be provided in a later
+series.
+
+[Ralf: Remove some cargo cult programming and fixed formatting.]
+
+Signed-off-by: John Crispin <[email protected]>
+Signed-off-by: Ralph Hempel <[email protected]>
+Signed-off-by: David Daney <[email protected]>
+Cc: [email protected]
+Patchwork: https://patchwork.linux-mips.org/patch/2252/
+Patchwork: https://patchwork.linux-mips.org/patch/2371/
+Signed-off-by: Ralf Baechle <[email protected]>
+---
+ arch/mips/Kbuild.platforms                 |    1 +
+ arch/mips/Kconfig                          |   17 ++
+ arch/mips/include/asm/mach-lantiq/lantiq.h |   63 ++++++
+ arch/mips/include/asm/mach-lantiq/war.h    |   24 ++
+ arch/mips/lantiq/Makefile                  |    9 +
+ arch/mips/lantiq/Platform                  |    7 +
+ arch/mips/lantiq/clk.c                     |  140 ++++++++++++
+ arch/mips/lantiq/clk.h                     |   18 ++
+ arch/mips/lantiq/early_printk.c            |   33 +++
+ arch/mips/lantiq/irq.c                     |  326 ++++++++++++++++++++++++++++
+ arch/mips/lantiq/prom.c                    |   71 ++++++
+ arch/mips/lantiq/prom.h                    |   24 ++
+ arch/mips/lantiq/setup.c                   |   41 ++++
+ 13 files changed, 774 insertions(+), 0 deletions(-)
+ create mode 100644 arch/mips/include/asm/mach-lantiq/lantiq.h
+ create mode 100644 arch/mips/include/asm/mach-lantiq/war.h
+ create mode 100644 arch/mips/lantiq/Makefile
+ create mode 100644 arch/mips/lantiq/Platform
+ create mode 100644 arch/mips/lantiq/clk.c
+ create mode 100644 arch/mips/lantiq/clk.h
+ create mode 100644 arch/mips/lantiq/early_printk.c
+ create mode 100644 arch/mips/lantiq/irq.c
+ create mode 100644 arch/mips/lantiq/prom.c
+ create mode 100644 arch/mips/lantiq/prom.h
+ create mode 100644 arch/mips/lantiq/setup.c
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -174,6 +174,23 @@
+ 	 Members include the Acer PICA, MIPS Magnum 4000, MIPS Millennium and
+ 	 Olivetti M700-10 workstations.
+ 
++config LANTIQ
++	bool "Lantiq based platforms"
++	select DMA_NONCOHERENT
++	select IRQ_CPU
++	select CEVT_R4K
++	select CSRC_R4K
++	select SYS_HAS_CPU_MIPS32_R1
++	select SYS_HAS_CPU_MIPS32_R2
++	select SYS_SUPPORTS_BIG_ENDIAN
++	select SYS_SUPPORTS_32BIT_KERNEL
++	select SYS_SUPPORTS_MULTITHREADING
++	select SYS_HAS_EARLY_PRINTK
++	select ARCH_REQUIRE_GPIOLIB
++	select SWAP_IO_SPACE
++	select BOOT_RAW
++	select HAVE_CLK
++
+ config LASAT
+ 	bool "LASAT Networks platforms"
+ 	select CEVT_R4K
+--- /dev/null
++++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
+@@ -0,0 +1,63 @@
++/*
++ *  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 <[email protected]>
++ */
++#ifndef _LANTIQ_H__
++#define _LANTIQ_H__
++
++#include <linux/irq.h>
++
++/* generic reg access functions */
++#define ltq_r32(reg)		__raw_readl(reg)
++#define ltq_w32(val, reg)	__raw_writel(val, reg)
++#define ltq_w32_mask(clear, set, reg)	\
++	ltq_w32((ltq_r32(reg) & ~(clear)) | (set), reg)
++#define ltq_r8(reg)		__raw_readb(reg)
++#define ltq_w8(val, reg)	__raw_writeb(val, reg)
++
++/* 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_cgu_w32(x, y)	ltq_w32((x), ltq_cgu_membase + (y))
++#define ltq_cgu_r32(x)		ltq_r32(ltq_cgu_membase + (x))
++
++extern __iomem void *ltq_ebu_membase;
++extern __iomem void *ltq_cgu_membase;
++
++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_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;
++
++/* some irq helpers */
++extern void ltq_disable_irq(unsigned int irq);
++extern void ltq_mask_and_ack_irq(unsigned int irq);
++extern void ltq_enable_irq(unsigned int irq);
++
++/* find out what caused the last cpu reset */
++extern int ltq_reset_cause(void);
++#define LTQ_RST_CAUSE_WDTRST	0x20
++
++#define IOPORT_RESOURCE_START	0x10000000
++#define IOPORT_RESOURCE_END	0xffffffff
++#define IOMEM_RESOURCE_START	0x10000000
++#define IOMEM_RESOURCE_END	0xffffffff
++#define LTQ_FLASH_START		0x10000000
++#define LTQ_FLASH_MAX		0x04000000
++
++#endif
+--- /dev/null
++++ b/arch/mips/include/asm/mach-lantiq/war.h
+@@ -0,0 +1,24 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License.  See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ */
++#ifndef __ASM_MIPS_MACH_LANTIQ_WAR_H
++#define __ASM_MIPS_MACH_LANTIQ_WAR_H
++
++#define R4600_V1_INDEX_ICACHEOP_WAR     0
++#define R4600_V1_HIT_CACHEOP_WAR        0
++#define R4600_V2_HIT_CACHEOP_WAR        0
++#define R5432_CP0_INTERRUPT_WAR         0
++#define BCM1250_M3_WAR                  0
++#define SIBYTE_1956_WAR                 0
++#define MIPS4K_ICACHE_REFILL_WAR        0
++#define MIPS_CACHE_SYNC_WAR             0
++#define TX49XX_ICACHE_INDEX_INV_WAR     0
++#define RM9000_CDEX_SMP_WAR             0
++#define ICACHE_REFILLS_WORKAROUND_WAR   0
++#define R10000_LLSC_WAR                 0
++#define MIPS34K_MISSED_ITLB_WAR         0
++
++#endif
+--- /dev/null
++++ b/arch/mips/lantiq/Makefile
+@@ -0,0 +1,9 @@
++# Copyright (C) 2010 John Crispin <[email protected]>
++#
++# This program is free software; you can redistribute it and/or modify it
++# under the terms of the GNU General Public License version 2 as published
++# by the Free Software Foundation.
++
++obj-y := irq.o setup.o clk.o prom.o
++
++obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+--- /dev/null
++++ b/arch/mips/lantiq/Platform
+@@ -0,0 +1,7 @@
++#
++# Lantiq
++#
++
++platform-$(CONFIG_LANTIQ)	+= lantiq/
++cflags-$(CONFIG_LANTIQ)		+= -I$(srctree)/arch/mips/include/asm/mach-lantiq
++load-$(CONFIG_LANTIQ)		= 0xffffffff80002000
+--- /dev/null
++++ b/arch/mips/lantiq/clk.c
+@@ -0,0 +1,144 @@
++/*
++ *  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 Thomas Langer <[email protected]>
++ * Copyright (C) 2010 John Crispin <[email protected]>
++ */
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/clk.h>
++#include <linux/err.h>
++#include <linux/list.h>
++
++#include <asm/time.h>
++#include <asm/irq.h>
++#include <asm/div64.h>
++
++#include <lantiq_soc.h>
++
++#include "clk.h"
++
++struct clk {
++	const char *name;
++	unsigned long rate;
++	unsigned long (*get_rate) (void);
++};
++
++static struct clk *cpu_clk;
++static int cpu_clk_cnt;
++
++/* 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,
++	},
++};
++
++#ifdef CONFIG_SOC_TYPE_XWAY
++static struct resource ltq_cgu_resource = {
++	.name	= "cgu",
++	.start	= LTQ_CGU_BASE_ADDR,
++	.end	= LTQ_CGU_BASE_ADDR + LTQ_CGU_SIZE - 1,
++	.flags	= IORESOURCE_MEM,
++};
++
++/* remapped clock register range */
++void __iomem *ltq_cgu_membase;
++#endif
++
++void clk_init(void)
++{
++	cpu_clk = cpu_clk_generic;
++	cpu_clk_cnt = ARRAY_SIZE(cpu_clk_generic);
++}
++
++static inline int clk_good(struct clk *clk)
++{
++	return clk && !IS_ERR(clk);
++}
++
++unsigned long clk_get_rate(struct clk *clk)
++{
++	if (unlikely(!clk_good(clk)))
++		return 0;
++
++	if (clk->rate != 0)
++		return clk->rate;
++
++	if (clk->get_rate != NULL)
++		return clk->get_rate();
++
++	return 0;
++}
++EXPORT_SYMBOL(clk_get_rate);
++
++struct clk *clk_get(struct device *dev, const char *id)
++{
++	int i;
++
++	for (i = 0; i < cpu_clk_cnt; i++)
++		if (!strcmp(id, cpu_clk[i].name))
++			return &cpu_clk[i];
++	BUG();
++	return ERR_PTR(-ENOENT);
++}
++EXPORT_SYMBOL(clk_get);
++
++void clk_put(struct clk *clk)
++{
++	/* not used */
++}
++EXPORT_SYMBOL(clk_put);
++
++static inline u32 ltq_get_counter_resolution(void)
++{
++	u32 res;
++
++	__asm__ __volatile__(
++		".set   push\n"
++		".set   mips32r2\n"
++		"rdhwr  %0, $3\n"
++		".set pop\n"
++		: "=&r" (res)
++		: /* no input */
++		: "memory");
++
++	return res;
++}
++
++void __init plat_time_init(void)
++{
++	struct clk *clk;
++
++#ifdef CONFIG_SOC_TYPE_XWAY
++	if (insert_resource(&iomem_resource, &ltq_cgu_resource) < 0)
++		panic("Failed to insert cgu memory\n");
++
++	if (request_mem_region(ltq_cgu_resource.start,
++			resource_size(&ltq_cgu_resource), "cgu") < 0)
++		panic("Failed to request cgu memory\n");
++
++	ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start,
++				resource_size(&ltq_cgu_resource));
++	if (!ltq_cgu_membase) {
++		pr_err("Failed to remap cgu memory\n");
++		unreachable();
++	}
++#endif
++	clk = clk_get(0, "cpu");
++	mips_hpt_frequency = clk_get_rate(clk) / ltq_get_counter_resolution();
++	write_c0_compare(read_c0_count());
++	clk_put(clk);
++}
+--- /dev/null
++++ b/arch/mips/lantiq/clk.h
+@@ -0,0 +1,18 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#ifndef _LTQ_CLK_H__
++#define _LTQ_CLK_H__
++
++extern void clk_init(void);
++
++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);
++
++#endif
+--- /dev/null
++++ b/arch/mips/lantiq/early_printk.c
+@@ -0,0 +1,37 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#include <linux/init.h>
++#include <linux/cpu.h>
++
++#include <lantiq.h>
++#include <lantiq_soc.h>
++
++/* no ioremap possible at this early stage, lets use KSEG1 instead  */
++#ifdef CONFIG_SOC_FALCON
++#define LTQ_ASC_BASE  KSEG1ADDR(LTQ_ASC0_BASE_ADDR)
++#else
++#define LTQ_ASC_BASE	KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
++#endif
++#define ASC_BUF		1024
++#define LTQ_ASC_FSTAT	((u32 *)(LTQ_ASC_BASE + 0x0048))
++#define LTQ_ASC_TBUF	((u32 *)(LTQ_ASC_BASE + 0x0020))
++#define TXMASK		0x3F00
++#define TXOFFSET	8
++
++void prom_putchar(char c)
++{
++	unsigned long flags;
++
++	local_irq_save(flags);
++	do { } while ((ltq_r32(LTQ_ASC_FSTAT) & TXMASK) >> TXOFFSET);
++	if (c == '\n')
++		ltq_w32('\r', LTQ_ASC_TBUF);
++	ltq_w32(c, LTQ_ASC_TBUF);
++	local_irq_restore(flags);
++}
+--- /dev/null
++++ b/arch/mips/lantiq/irq.c
+@@ -0,0 +1,353 @@
++/*
++ *  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 <[email protected]>
++ * Copyright (C) 2010 Thomas Langer <[email protected]>
++ */
++
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/module.h>
++
++#include <asm/bootinfo.h>
++#include <asm/irq_cpu.h>
++
++#include <lantiq_soc.h>
++#include <irq.h>
++
++/* register definitions */
++#define LTQ_ICU_IM0_ISR		0x0000
++#define LTQ_ICU_IM0_IER		0x0008
++#define LTQ_ICU_IM0_IOSR	0x0010
++#define LTQ_ICU_IM0_IRSR	0x0018
++#define LTQ_ICU_IM0_IMR		0x0020
++#define LTQ_ICU_IM1_ISR		0x0028
++#define LTQ_ICU_OFFSET		(LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR)
++
++#ifdef CONFIG_SOC_TYPE_XWAY
++
++#define LTQ_EIU_EXIN_C		0x0000
++#define LTQ_EIU_EXIN_INIC	0x0004
++#define LTQ_EIU_EXIN_INEN	0x000C
++
++/* irq numbers used by the external interrupt unit (EIU) */
++#define LTQ_EIU_IR0		(INT_NUM_IM4_IRL0 + 30)
++#define LTQ_EIU_IR1		(INT_NUM_IM3_IRL0 + 31)
++#define LTQ_EIU_IR2		(INT_NUM_IM1_IRL0 + 26)
++#define LTQ_EIU_IR3		INT_NUM_IM1_IRL0
++#define LTQ_EIU_IR4		(INT_NUM_IM1_IRL0 + 1)
++#define LTQ_EIU_IR5		(INT_NUM_IM1_IRL0 + 2)
++#define LTQ_EIU_IR6		(INT_NUM_IM2_IRL0 + 30)
++
++#define MAX_EIU			6
++
++/* irqs generated by device attached to the EBU need to be acked in
++ * a special manner
++ */
++#define LTQ_ICU_EBU_IRQ		22
++
++#define ltq_eiu_w32(x, y)	ltq_w32((x), ltq_eiu_membase + (y))
++#define ltq_eiu_r32(x)		ltq_r32(ltq_eiu_membase + (x))
++
++static unsigned short ltq_eiu_irq[MAX_EIU] = {
++	LTQ_EIU_IR0,
++	LTQ_EIU_IR1,
++	LTQ_EIU_IR2,
++	LTQ_EIU_IR3,
++	LTQ_EIU_IR4,
++	LTQ_EIU_IR5,
++};
++
++static void __iomem *ltq_eiu_membase;
++
++static struct resource ltq_eiu_resource = {
++	.name	= "eiu",
++	.start	= LTQ_EIU_BASE_ADDR,
++	.end	= LTQ_EIU_BASE_ADDR + LTQ_ICU_SIZE - 1,
++	.flags	= IORESOURCE_MEM,
++};
++
++#endif
++
++static struct resource ltq_icu_resource = {
++	.name	= "icu",
++	.start	= LTQ_ICU_BASE_ADDR,
++	.end	= LTQ_ICU_BASE_ADDR + LTQ_ICU_SIZE - 1,
++	.flags	= IORESOURCE_MEM,
++};
++
++#define ltq_icu_w32(x, y)	ltq_w32((x), ltq_icu_membase + (y))
++#define ltq_icu_r32(x)		ltq_r32(ltq_icu_membase + (x))
++
++static void __iomem *ltq_icu_membase;
++
++void
++ltq_disable_irq(unsigned int irq_nr)
++{
++	u32 ier = LTQ_ICU_IM0_IER;
++
++	irq_nr -= INT_NUM_IRQ0;
++	ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
++	irq_nr %= INT_NUM_IM_OFFSET;
++	ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier);
++}
++
++void
++ltq_mask_and_ack_irq(unsigned int irq_nr)
++{
++	u32 ier = LTQ_ICU_IM0_IER;
++	u32 isr = LTQ_ICU_IM0_ISR;
++
++	irq_nr -= INT_NUM_IRQ0;
++	ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
++	isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
++	irq_nr %= INT_NUM_IM_OFFSET;
++	ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier);
++	ltq_icu_w32((1 << irq_nr), isr);
++}
++EXPORT_SYMBOL(ltq_mask_and_ack_irq);
++
++static void
++ltq_ack_irq(unsigned int irq_nr)
++{
++	u32 isr = LTQ_ICU_IM0_ISR;
++
++	irq_nr -= INT_NUM_IRQ0;
++	isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
++	irq_nr %= INT_NUM_IM_OFFSET;
++	ltq_icu_w32((1 << irq_nr), isr);
++}
++
++void
++ltq_enable_irq(unsigned int irq_nr)
++{
++	u32 ier = LTQ_ICU_IM0_IER;
++
++	irq_nr -= INT_NUM_IRQ0;
++	ier += LTQ_ICU_OFFSET  * (irq_nr / INT_NUM_IM_OFFSET);
++	irq_nr %= INT_NUM_IM_OFFSET;
++	ltq_icu_w32(ltq_icu_r32(ier) | (1 << irq_nr), ier);
++}
++
++#ifdef CONFIG_SOC_TYPE_XWAY
++static unsigned int
++ltq_startup_eiu_irq(unsigned int irq)
++{
++	int i;
++
++	ltq_enable_irq(irq);
++	for (i = 0; i < MAX_EIU; i++) {
++		if (irq == ltq_eiu_irq[i]) {
++			/* low level - we should really handle set_type */
++			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_C) | (0x6 << (i * 4)),
++				LTQ_EIU_EXIN_C);
++			/* clear all pending */
++			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INIC) & ~(1 << i),
++				LTQ_EIU_EXIN_INIC);
++			/* enable */
++			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) | (1 << i),
++				LTQ_EIU_EXIN_INEN);
++			break;
++		}
++	}
++	return 0;
++}
++
++static void
++ltq_shutdown_eiu_irq(unsigned int irq)
++{
++	int i;
++
++	ltq_disable_irq(irq);
++	for (i = 0; i < MAX_EIU; i++) {
++		if (irq == ltq_eiu_irq[i]) {
++			/* disable */
++			ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) & ~(1 << i),
++			LTQ_EIU_EXIN_INEN);
++			break;
++		}
++	}
++}
++#endif
++
++static void
++ltq_end_irq(unsigned int irq)
++{
++	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
++		ltq_enable_irq(irq);
++}
++
++static struct irq_chip
++ltq_irq_type = {
++	"ltq_irq",
++	.enable = ltq_enable_irq,
++	.disable = ltq_disable_irq,
++	.unmask = ltq_enable_irq,
++	.ack = ltq_ack_irq,
++	.mask = ltq_disable_irq,
++	.mask_ack = ltq_mask_and_ack_irq,
++	.end = ltq_end_irq,
++};
++
++#ifdef CONFIG_SOC_TYPE_XWAY
++static struct irq_chip
++ltq_eiu_type = {
++	"ltq_eiu_irq",
++	.startup = ltq_startup_eiu_irq,
++	.shutdown = ltq_shutdown_eiu_irq,
++	.enable = ltq_enable_irq,
++	.disable = ltq_disable_irq,
++	.unmask = ltq_enable_irq,
++	.ack = ltq_ack_irq,
++	.mask = ltq_disable_irq,
++	.mask_ack = ltq_mask_and_ack_irq,
++	.end = ltq_end_irq,
++};
++#endif
++
++static void ltq_hw_irqdispatch(int module)
++{
++	u32 irq;
++
++	irq = ltq_icu_r32(LTQ_ICU_IM0_IOSR + (module * LTQ_ICU_OFFSET));
++	if (irq == 0)
++		return;
++
++	/* silicon bug causes only the msb set to 1 to be valid. all
++	 * other bits might be bogus
++	 */
++	irq = __fls(irq);
++	do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
++
++#ifdef CONFIG_SOC_TYPE_XWAY
++	/* if this is a EBU irq, we need to ack it or get a deadlock */
++	if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0))
++		ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10,
++			LTQ_EBU_PCC_ISTAT);
++#endif
++}
++
++#define DEFINE_HWx_IRQDISPATCH(x)					\
++	static void ltq_hw ## x ## _irqdispatch(void)			\
++	{								\
++		ltq_hw_irqdispatch(x);					\
++	}
++DEFINE_HWx_IRQDISPATCH(0)
++DEFINE_HWx_IRQDISPATCH(1)
++DEFINE_HWx_IRQDISPATCH(2)
++DEFINE_HWx_IRQDISPATCH(3)
++DEFINE_HWx_IRQDISPATCH(4)
++
++static void ltq_hw5_irqdispatch(void)
++{
++	do_IRQ(MIPS_CPU_TIMER_IRQ);
++}
++
++asmlinkage void plat_irq_dispatch(void)
++{
++	unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
++	unsigned int i;
++
++	if (pending & CAUSEF_IP7) {
++		do_IRQ(MIPS_CPU_TIMER_IRQ);
++		goto out;
++	} else {
++		for (i = 0; i < 5; i++) {
++			if (pending & (CAUSEF_IP2 << i)) {
++				ltq_hw_irqdispatch(i);
++				goto out;
++			}
++		}
++	}
++	pr_alert("Spurious IRQ: CAUSE=0x%08x\n", read_c0_status());
++
++out:
++	return;
++}
++
++static struct irqaction cascade = {
++	.handler = no_action,
++	.flags = IRQF_DISABLED,
++	.name = "cascade",
++};
++
++void __init arch_init_irq(void)
++{
++	int i;
++
++	if (insert_resource(&iomem_resource, &ltq_icu_resource) < 0)
++		panic("Failed to insert icu memory\n");
++
++	if (request_mem_region(ltq_icu_resource.start,
++			resource_size(&ltq_icu_resource), "icu") < 0)
++		panic("Failed to request icu memory\n");
++
++	ltq_icu_membase = ioremap_nocache(ltq_icu_resource.start,
++				resource_size(&ltq_icu_resource));
++	if (!ltq_icu_membase)
++		panic("Failed to remap icu memory\n");
++
++#ifdef CONFIG_SOC_TYPE_XWAY
++	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");
++
++	ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
++				resource_size(&ltq_eiu_resource));
++	if (!ltq_eiu_membase)
++		panic("Failed to remap eiu memory\n");
++#endif
++	/* make sure all irqs are turned off by default */
++	for (i = 0; i < 5; i++)
++		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));
++
++	mips_cpu_irq_init();
++
++	for (i = 2; i <= 6; i++)
++		setup_irq(i, &cascade);
++
++	if (cpu_has_vint) {
++		pr_info("Setting up vectored interrupts\n");
++		set_vi_handler(2, ltq_hw0_irqdispatch);
++		set_vi_handler(3, ltq_hw1_irqdispatch);
++		set_vi_handler(4, ltq_hw2_irqdispatch);
++		set_vi_handler(5, ltq_hw3_irqdispatch);
++		set_vi_handler(6, ltq_hw4_irqdispatch);
++		set_vi_handler(7, ltq_hw5_irqdispatch);
++	}
++
++	for (i = INT_NUM_IRQ0;
++		i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++)
++#ifdef CONFIG_SOC_TYPE_XWAY
++			if ((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) || (i == LTQ_EIU_IR2))
++				set_irq_chip_and_handler(i, &ltq_eiu_type, handle_level_irq);
++			/* EIU3-5 only exist on ar9 and vr9 */
++			else if (((i == LTQ_EIU_IR3) || (i == LTQ_EIU_IR4) ||
++				(i == LTQ_EIU_IR5)) && (ltq_is_ar9() || ltq_is_vr9()))
++				set_irq_chip_and_handler(i, &ltq_eiu_type, handle_level_irq);
++			else
++#endif
++				set_irq_chip_and_handler(i, &ltq_irq_type, handle_level_irq);
++
++#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);
++#else
++	set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 |
++		IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
++#endif
++	cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ;
++}
++
++unsigned int __cpuinit get_c0_compare_int(void)
++{
++	return CP0_LEGACY_COMPARE_IRQ;
++}
+--- /dev/null
++++ b/arch/mips/lantiq/prom.c
+@@ -0,0 +1,71 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#include <linux/module.h>
++#include <linux/clk.h>
++#include <asm/bootinfo.h>
++#include <asm/time.h>
++
++#include <lantiq.h>
++
++#include "prom.h"
++#include "clk.h"
++
++static struct ltq_soc_info soc_info;
++
++unsigned int ltq_get_cpu_ver(void)
++{
++	return soc_info.rev;
++}
++EXPORT_SYMBOL(ltq_get_cpu_ver);
++
++unsigned int ltq_get_soc_type(void)
++{
++	return soc_info.type;
++}
++EXPORT_SYMBOL(ltq_get_soc_type);
++
++const char *get_system_type(void)
++{
++	return soc_info.sys_type;
++}
++
++void prom_free_prom_memory(void)
++{
++}
++
++static void __init prom_init_cmdline(void)
++{
++	int argc = fw_arg0;
++	char **argv = (char **) KSEG1ADDR(fw_arg1);
++	int i;
++
++	for (i = 0; i < argc; i++) {
++		char *p = (char *)  KSEG1ADDR(argv[i]);
++
++		if (p && *p) {
++			strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
++			strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
++		}
++	}
++}
++
++void __init prom_init(void)
++{
++	struct clk *clk;
++
++	ltq_soc_detect(&soc_info);
++	clk_init();
++	clk = clk_get(0, "cpu");
++	snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev1.%d",
++		soc_info.name, soc_info.rev);
++	clk_put(clk);
++	soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
++	pr_info("SoC: %s\n", soc_info.sys_type);
++	prom_init_cmdline();
++}
+--- /dev/null
++++ b/arch/mips/lantiq/prom.h
+@@ -0,0 +1,24 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#ifndef _LTQ_PROM_H__
++#define _LTQ_PROM_H__
++
++#define LTQ_SYS_TYPE_LEN	0x100
++
++struct ltq_soc_info {
++	unsigned char *name;
++	unsigned int rev;
++	unsigned int partnum;
++	unsigned int type;
++	unsigned char sys_type[LTQ_SYS_TYPE_LEN];
++};
++
++extern void ltq_soc_detect(struct ltq_soc_info *i);
++
++#endif
+--- /dev/null
++++ b/arch/mips/lantiq/setup.c
+@@ -0,0 +1,41 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/io.h>
++#include <linux/ioport.h>
++#include <asm/bootinfo.h>
++
++#include <lantiq_soc.h>
++
++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;
++	ioport_resource.end = IOPORT_RESOURCE_END;
++	iomem_resource.start = IOMEM_RESOURCE_START;
++	iomem_resource.end = IOMEM_RESOURCE_END;
++
++	set_io_port_base((unsigned long) KSEG1);
++
++	while (*envp) {
++		char *e = (char *)KSEG1ADDR(*envp);
++		if (!strncmp(e, "memsize=", 8)) {
++			e += 8;
++			if (strict_strtoul(e, 0, &memsize))
++				pr_warn("bad memsize specified\n");
++		}
++		envp++;
++	}
++	memsize *= 1024 * 1024;
++	add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
++}

+ 1151 - 0
target/linux/lantiq/patches-2.6.32/0002-MIPS-Lantiq-add-SoC-specific-code-for-XWAY-family.patch

@@ -0,0 +1,1151 @@
+From 36cc26a362c6ad64ba3d176809847ec60cc40859 Mon Sep 17 00:00:00 2001
+From: John Crispin <[email protected]>
+Date: Wed, 30 Mar 2011 09:27:48 +0200
+Subject: [PATCH 02/13] MIPS: Lantiq: add SoC specific code for XWAY family
+
+Add support for the Lantiq XWAY family of Mips24KEc SoCs.
+
+* Danube (PSB50702)
+* Twinpass (PSB4000)
+* AR9 (PSB50802)
+* Amazon SE (PSB5061)
+
+The Amazon SE is a lightweight SoC and has no PCI as well as a different
+clock. We split the code out into seperate files to handle this.
+
+The GPIO pins on the SoCs are multi function and there are several bits
+we can use to configure the pins. To be as compatible as possible to
+GPIOLIB we add a function
+
+int ltq_gpio_request(unsigned int pin, unsigned int alt0,
+        unsigned int alt1, unsigned int dir, const char *name);
+
+which lets you configure the 2 "alternate function" bits. This way drivers like
+PCI can make use of GPIOLIB without a cubersome wrapper.
+
+The PLL code inside arch/mips/lantiq/xway/clk-xway.c is voodoo to me. It was
+taken from a 2.4.20 source tree and was never really changed by me since then.
+
+Signed-off-by: John Crispin <[email protected]>
+Signed-off-by: Ralph Hempel <[email protected]>
+Cc: [email protected]
+Patchwork: https://patchwork.linux-mips.org/patch/2249/
+Signed-off-by: Ralf Baechle <[email protected]>
+---
+ arch/mips/Kconfig                                  |    1 +
+ arch/mips/include/asm/mach-lantiq/xway/irq.h       |   18 ++
+ .../mips/include/asm/mach-lantiq/xway/lantiq_irq.h |   66 ++++++
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |  140 ++++++++++++
+ arch/mips/lantiq/Kconfig                           |   21 ++
+ arch/mips/lantiq/Makefile                          |    2 +
+ arch/mips/lantiq/Platform                          |    1 +
+ arch/mips/lantiq/xway/Makefile                     |    4 +
+ arch/mips/lantiq/xway/clk-ase.c                    |   48 +++++
+ arch/mips/lantiq/xway/clk-xway.c                   |  223 ++++++++++++++++++++
+ arch/mips/lantiq/xway/ebu.c                        |   53 +++++
+ arch/mips/lantiq/xway/gpio.c                       |  195 +++++++++++++++++
+ arch/mips/lantiq/xway/pmu.c                        |   70 ++++++
+ arch/mips/lantiq/xway/prom-ase.c                   |   39 ++++
+ arch/mips/lantiq/xway/prom-xway.c                  |   54 +++++
+ arch/mips/lantiq/xway/reset.c                      |   91 ++++++++
+ 16 files changed, 1026 insertions(+), 0 deletions(-)
+ create mode 100644 arch/mips/include/asm/mach-lantiq/xway/irq.h
+ create mode 100644 arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
+ create mode 100644 arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+ create mode 100644 arch/mips/lantiq/Kconfig
+ create mode 100644 arch/mips/lantiq/xway/Makefile
+ create mode 100644 arch/mips/lantiq/xway/clk-ase.c
+ create mode 100644 arch/mips/lantiq/xway/clk-xway.c
+ create mode 100644 arch/mips/lantiq/xway/ebu.c
+ create mode 100644 arch/mips/lantiq/xway/gpio.c
+ create mode 100644 arch/mips/lantiq/xway/pmu.c
+ create mode 100644 arch/mips/lantiq/xway/prom-ase.c
+ create mode 100644 arch/mips/lantiq/xway/prom-xway.c
+ create mode 100644 arch/mips/lantiq/xway/reset.c
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -694,6 +694,7 @@
+ source "arch/mips/basler/excite/Kconfig"
+ source "arch/mips/bcm63xx/Kconfig"
+ source "arch/mips/jazz/Kconfig"
++source "arch/mips/lantiq/Kconfig"
+ source "arch/mips/lasat/Kconfig"
+ source "arch/mips/pmc-sierra/Kconfig"
+ source "arch/mips/sgi-ip27/Kconfig"
+--- /dev/null
++++ b/arch/mips/include/asm/mach-lantiq/xway/irq.h
+@@ -0,0 +1,18 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#ifndef __LANTIQ_IRQ_H
++#define __LANTIQ_IRQ_H
++
++#include <lantiq_irq.h>
++
++#define NR_IRQS 256
++
++#include_next <irq.h>
++
++#endif
+--- /dev/null
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
+@@ -0,0 +1,66 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#ifndef _LANTIQ_XWAY_IRQ_H__
++#define _LANTIQ_XWAY_IRQ_H__
++
++#define INT_NUM_IRQ0		8
++#define INT_NUM_IM0_IRL0	(INT_NUM_IRQ0 + 0)
++#define INT_NUM_IM1_IRL0	(INT_NUM_IRQ0 + 32)
++#define INT_NUM_IM2_IRL0	(INT_NUM_IRQ0 + 64)
++#define INT_NUM_IM3_IRL0	(INT_NUM_IRQ0 + 96)
++#define INT_NUM_IM4_IRL0	(INT_NUM_IRQ0 + 128)
++#define INT_NUM_IM_OFFSET	(INT_NUM_IM1_IRL0 - INT_NUM_IM0_IRL0)
++
++#define LTQ_ASC_TIR(x)		(INT_NUM_IM3_IRL0 + (x * 8))
++#define LTQ_ASC_RIR(x)		(INT_NUM_IM3_IRL0 + (x * 8) + 1)
++#define LTQ_ASC_EIR(x)		(INT_NUM_IM3_IRL0 + (x * 8) + 2)
++
++#define LTQ_ASC_ASE_TIR		INT_NUM_IM2_IRL0
++#define LTQ_ASC_ASE_RIR		(INT_NUM_IM2_IRL0 + 2)
++#define LTQ_ASC_ASE_EIR		(INT_NUM_IM2_IRL0 + 3)
++
++#define LTQ_SSC_TIR		(INT_NUM_IM0_IRL0 + 15)
++#define LTQ_SSC_RIR		(INT_NUM_IM0_IRL0 + 14)
++#define LTQ_SSC_EIR		(INT_NUM_IM0_IRL0 + 16)
++
++#define LTQ_MEI_DYING_GASP_INT	(INT_NUM_IM1_IRL0 + 21)
++#define LTQ_MEI_INT		(INT_NUM_IM1_IRL0 + 23)
++
++#define LTQ_TIMER6_INT		(INT_NUM_IM1_IRL0 + 23)
++#define LTQ_USB_INT		(INT_NUM_IM1_IRL0 + 22)
++#define LTQ_USB_OC_INT		(INT_NUM_IM4_IRL0 + 23)
++
++#define MIPS_CPU_TIMER_IRQ		7
++
++#define LTQ_DMA_CH0_INT		(INT_NUM_IM2_IRL0)
++#define LTQ_DMA_CH1_INT		(INT_NUM_IM2_IRL0 + 1)
++#define LTQ_DMA_CH2_INT		(INT_NUM_IM2_IRL0 + 2)
++#define LTQ_DMA_CH3_INT		(INT_NUM_IM2_IRL0 + 3)
++#define LTQ_DMA_CH4_INT		(INT_NUM_IM2_IRL0 + 4)
++#define LTQ_DMA_CH5_INT		(INT_NUM_IM2_IRL0 + 5)
++#define LTQ_DMA_CH6_INT		(INT_NUM_IM2_IRL0 + 6)
++#define LTQ_DMA_CH7_INT		(INT_NUM_IM2_IRL0 + 7)
++#define LTQ_DMA_CH8_INT		(INT_NUM_IM2_IRL0 + 8)
++#define LTQ_DMA_CH9_INT		(INT_NUM_IM2_IRL0 + 9)
++#define LTQ_DMA_CH10_INT	(INT_NUM_IM2_IRL0 + 10)
++#define LTQ_DMA_CH11_INT	(INT_NUM_IM2_IRL0 + 11)
++#define LTQ_DMA_CH12_INT	(INT_NUM_IM2_IRL0 + 25)
++#define LTQ_DMA_CH13_INT	(INT_NUM_IM2_IRL0 + 26)
++#define LTQ_DMA_CH14_INT	(INT_NUM_IM2_IRL0 + 27)
++#define LTQ_DMA_CH15_INT	(INT_NUM_IM2_IRL0 + 28)
++#define LTQ_DMA_CH16_INT	(INT_NUM_IM2_IRL0 + 29)
++#define LTQ_DMA_CH17_INT	(INT_NUM_IM2_IRL0 + 30)
++#define LTQ_DMA_CH18_INT	(INT_NUM_IM2_IRL0 + 16)
++#define LTQ_DMA_CH19_INT	(INT_NUM_IM2_IRL0 + 21)
++
++#define LTQ_PPE_MBOX_INT	(INT_NUM_IM2_IRL0 + 24)
++
++#define INT_NUM_IM4_IRL14	(INT_NUM_IM4_IRL0 + 14)
++
++#endif
+--- /dev/null
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -0,0 +1,140 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#ifndef _LTQ_XWAY_H__
++#define _LTQ_XWAY_H__
++
++#ifdef CONFIG_SOC_TYPE_XWAY
++
++#include <lantiq.h>
++
++/* Chip IDs */
++#define SOC_ID_DANUBE1		0x129
++#define SOC_ID_DANUBE2		0x12B
++#define SOC_ID_TWINPASS		0x12D
++#define SOC_ID_AMAZON_SE	0x152
++#define SOC_ID_ARX188		0x16C
++#define SOC_ID_ARX168		0x16D
++#define SOC_ID_ARX182		0x16F
++
++/* 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
++
++/* ASC0/1 - serial port */
++#define LTQ_ASC0_BASE_ADDR	0x1E100400
++#define LTQ_ASC1_BASE_ADDR	0x1E100C00
++#define LTQ_ASC_SIZE		0x400
++
++/* RCU - reset control unit */
++#define LTQ_RCU_BASE_ADDR	0x1F203000
++#define LTQ_RCU_SIZE		0x1000
++
++/* GPTU - general purpose timer unit */
++#define LTQ_GPTU_BASE_ADDR	0x18000300
++#define LTQ_GPTU_SIZE		0x100
++
++/* EBU - external bus unit */
++#define LTQ_EBU_GPIO_START	0x14000000
++#define LTQ_EBU_GPIO_SIZE	0x1000
++
++#define LTQ_EBU_BASE_ADDR	0x1E105300
++#define LTQ_EBU_SIZE		0x100
++
++#define LTQ_EBU_BUSCON0		0x0060
++#define LTQ_EBU_PCC_CON		0x0090
++#define LTQ_EBU_PCC_IEN		0x00A4
++#define LTQ_EBU_PCC_ISTAT	0x00A0
++#define LTQ_EBU_BUSCON1		0x0064
++#define LTQ_EBU_ADDRSEL1	0x0024
++#define EBU_WRDIS		0x80000000
++
++/* CGU - clock generation unit */
++#define LTQ_CGU_BASE_ADDR	0x1F103000
++#define LTQ_CGU_SIZE		0x1000
++
++/* ICU - interrupt control unit */
++#define LTQ_ICU_BASE_ADDR	0x1F880200
++#define LTQ_ICU_SIZE		0x100
++
++/* EIU - external interrupt unit */
++#define LTQ_EIU_BASE_ADDR	0x1F101000
++#define LTQ_EIU_SIZE		0x1000
++
++/* PMU - power management unit */
++#define LTQ_PMU_BASE_ADDR	0x1F102000
++#define LTQ_PMU_SIZE		0x1000
++
++#define PMU_DMA			0x0020
++#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_PPE32_BASE_ADDR	0xBE180000
++#define LTQ_PPE32_SIZE		0x40000
++
++/* DMA */
++#define LTQ_DMA_BASE_ADDR	0xBE104100
++
++/* PCI */
++#define PCI_CR_BASE_ADDR	0x1E105400
++#define PCI_CR_SIZE		0x400
++
++/* WDT */
++#define LTQ_WDT_BASE_ADDR	0x1F8803F0
++#define LTQ_WDT_SIZE		0x10
++
++/* STP - serial to parallel conversion unit */
++#define LTQ_STP_BASE_ADDR	0x1E100BB0
++#define LTQ_STP_SIZE		0x40
++
++/* GPIO */
++#define LTQ_GPIO0_BASE_ADDR	0x1E100B10
++#define LTQ_GPIO1_BASE_ADDR	0x1E100B40
++#define LTQ_GPIO2_BASE_ADDR	0x1E100B70
++#define LTQ_GPIO_SIZE		0x30
++
++/* SSC */
++#define LTQ_SSC_BASE_ADDR	0x1e100800
++#define LTQ_SSC_SIZE		0x100
++
++/* MEI - dsl core */
++#define LTQ_MEI_BASE_ADDR	0x1E116000
++
++/* DEU - data encryption unit */
++#define LTQ_DEU_BASE_ADDR	0x1E103100
++
++/* MPS - multi processor unit (voice) */
++#define LTQ_MPS_BASE_ADDR	(KSEG1 + 0x1F107000)
++#define LTQ_MPS_CHIPID		((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344))
++
++/* 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 void ltq_pmu_enable(unsigned int module);
++extern void ltq_pmu_disable(unsigned int module);
++
++static inline int ltq_is_ar9(void)
++{
++	return (ltq_get_soc_type() == SOC_TYPE_AR9);
++}
++
++static inline int ltq_is_vr9(void)
++{
++	return (ltq_get_soc_type() == SOC_TYPE_VR9);
++}
++
++#endif /* CONFIG_SOC_TYPE_XWAY */
++#endif /* _LTQ_XWAY_H__ */
+--- /dev/null
++++ b/arch/mips/lantiq/Kconfig
+@@ -0,0 +1,21 @@
++if LANTIQ
++
++config SOC_TYPE_XWAY
++	bool
++	default n
++
++choice
++	prompt "SoC Type"
++	default SOC_XWAY
++
++config SOC_AMAZON_SE
++	bool "Amazon SE"
++	select SOC_TYPE_XWAY
++
++config SOC_XWAY
++	bool "XWAY"
++	select SOC_TYPE_XWAY
++	select HW_HAS_PCI
++endchoice
++
++endif
+--- a/arch/mips/lantiq/Makefile
++++ b/arch/mips/lantiq/Makefile
+@@ -7,3 +7,5 @@
+ obj-y := irq.o setup.o clk.o prom.o
+ 
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
++
++obj-$(CONFIG_SOC_TYPE_XWAY) += xway/
+--- a/arch/mips/lantiq/Platform
++++ b/arch/mips/lantiq/Platform
+@@ -5,3 +5,4 @@
+ 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
+--- /dev/null
++++ b/arch/mips/lantiq/xway/Makefile
+@@ -0,0 +1,4 @@
++obj-y := pmu.o ebu.o reset.o gpio.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/clk-ase.c
+@@ -0,0 +1,48 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#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>
++
++/* 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);
+--- /dev/null
++++ b/arch/mips/lantiq/xway/clk-xway.c
+@@ -0,0 +1,223 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#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>
++
++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);
+--- /dev/null
++++ b/arch/mips/lantiq/xway/ebu.c
+@@ -0,0 +1,53 @@
++/*
++ *  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.
++ *
++ *  EBU - the external bus unit attaches PCI, NOR and NAND
++ *
++ *  Copyright (C) 2010 John Crispin <[email protected]>
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/ioport.h>
++
++#include <lantiq_soc.h>
++
++/* all access to the ebu must be locked */
++DEFINE_SPINLOCK(ebu_lock);
++EXPORT_SYMBOL_GPL(ebu_lock);
++
++static struct resource ltq_ebu_resource = {
++	.name	= "ebu",
++	.start	= LTQ_EBU_BASE_ADDR,
++	.end	= LTQ_EBU_BASE_ADDR + LTQ_EBU_SIZE - 1,
++	.flags	= IORESOURCE_MEM,
++};
++
++/* remapped base addr of the clock unit and external bus unit */
++void __iomem *ltq_ebu_membase;
++
++static int __init lantiq_ebu_init(void)
++{
++	/* insert and request the memory region */
++	if (insert_resource(&iomem_resource, &ltq_ebu_resource) < 0)
++		panic("Failed to insert ebu memory\n");
++
++	if (request_mem_region(ltq_ebu_resource.start,
++			resource_size(&ltq_ebu_resource), "ebu") < 0)
++		panic("Failed to request ebu memory\n");
++
++	/* remap ebu register range */
++	ltq_ebu_membase = ioremap_nocache(ltq_ebu_resource.start,
++				resource_size(&ltq_ebu_resource));
++	if (!ltq_ebu_membase)
++		panic("Failed to remap ebu memory\n");
++
++	/* 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);
++	return 0;
++}
++
++postcore_initcall(lantiq_ebu_init);
+--- /dev/null
++++ b/arch/mips/lantiq/xway/gpio.c
+@@ -0,0 +1,195 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#include <linux/slab.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/gpio.h>
++#include <linux/ioport.h>
++#include <linux/io.h>
++
++#include <lantiq_soc.h>
++
++#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 PINS_PER_PORT		16
++#define MAX_PORTS		3
++
++#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)
++#define ltq_gpio_clearbit(m, r, p)	ltq_w32_mask((1 << p), 0, m + r)
++
++struct ltq_gpio {
++	void __iomem *membase;
++	struct gpio_chip chip;
++};
++
++static struct ltq_gpio ltq_gpio_port[MAX_PORTS];
++
++int gpio_to_irq(unsigned int gpio)
++{
++	return -EINVAL;
++}
++EXPORT_SYMBOL(gpio_to_irq);
++
++int irq_to_gpio(unsigned int gpio)
++{
++	return -EINVAL;
++}
++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 id = 0;
++
++	if (pin >= (MAX_PORTS * PINS_PER_PORT))
++		return -EINVAL;
++	if (gpio_request(pin, name)) {
++		pr_err("failed to setup lantiq gpio: %s\n", name);
++		return -EBUSY;
++	}
++	if (dir)
++		gpio_direction_output(pin, 1);
++	else
++		gpio_direction_input(pin);
++	while (pin >= PINS_PER_PORT) {
++		pin -= PINS_PER_PORT;
++		id++;
++	}
++	if (alt0)
++		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)
++		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);
++	return 0;
++}
++EXPORT_SYMBOL(ltq_gpio_request);
++
++static void ltq_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
++{
++	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
++
++	if (value)
++		ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OUT, offset);
++	else
++		ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OUT, offset);
++}
++
++static int ltq_gpio_get(struct gpio_chip *chip, unsigned int offset)
++{
++	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
++
++	return ltq_gpio_getbit(ltq_gpio->membase, LTQ_GPIO_IN, offset);
++}
++
++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);
++	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
++
++	return 0;
++}
++
++static int ltq_gpio_direction_output(struct gpio_chip *chip,
++	unsigned int offset, int value)
++{
++	struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
++
++	ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
++	ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
++	ltq_gpio_set(chip, offset, value);
++
++	return 0;
++}
++
++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);
++	ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL1, offset);
++	return 0;
++}
++
++static int ltq_gpio_probe(struct platform_device *pdev)
++{
++	struct resource *res;
++
++	if (pdev->id >= MAX_PORTS) {
++		dev_err(&pdev->dev, "invalid gpio port %d\n",
++			pdev->id);
++		return -EINVAL;
++	}
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!res) {
++		dev_err(&pdev->dev, "failed to get memory for gpio port %d\n",
++			pdev->id);
++		return -ENOENT;
++	}
++	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 memory for gpio port %d\n",
++			pdev->id);
++		return -EBUSY;
++	}
++	ltq_gpio_port[pdev->id].membase = devm_ioremap_nocache(&pdev->dev,
++		res->start, resource_size(res));
++	if (!ltq_gpio_port[pdev->id].membase) {
++		dev_err(&pdev->dev, "failed to remap memory for gpio port %d\n",
++			pdev->id);
++		return -ENOMEM;
++	}
++	ltq_gpio_port[pdev->id].chip.label = "ltq_gpio";
++	ltq_gpio_port[pdev->id].chip.direction_input = ltq_gpio_direction_input;
++	ltq_gpio_port[pdev->id].chip.direction_output =
++		ltq_gpio_direction_output;
++	ltq_gpio_port[pdev->id].chip.get = ltq_gpio_get;
++	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;
++	ltq_gpio_port[pdev->id].chip.ngpio = PINS_PER_PORT;
++	platform_set_drvdata(pdev, &ltq_gpio_port[pdev->id]);
++	return gpiochip_add(&ltq_gpio_port[pdev->id].chip);
++}
++
++static struct platform_driver
++ltq_gpio_driver = {
++	.probe = ltq_gpio_probe,
++	.driver = {
++		.name = "ltq_gpio",
++		.owner = THIS_MODULE,
++	},
++};
++
++int __init ltq_gpio_init(void)
++{
++	int ret = platform_driver_register(&ltq_gpio_driver);
++
++	if (ret)
++		pr_info("ltq_gpio : Error registering platfom driver!");
++	return ret;
++}
++
++postcore_initcall(ltq_gpio_init);
+--- /dev/null
++++ b/arch/mips/lantiq/xway/pmu.c
+@@ -0,0 +1,70 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/ioport.h>
++
++#include <lantiq_soc.h>
++
++/* PMU - the power management unit allows us to turn part of the core
++ * on and off
++ */
++
++/* the enable / disable registers */
++#define LTQ_PMU_PWDCR	0x1C
++#define LTQ_PMU_PWDSR	0x20
++
++#define ltq_pmu_w32(x, y)	ltq_w32((x), ltq_pmu_membase + (y))
++#define ltq_pmu_r32(x)		ltq_r32(ltq_pmu_membase + (x))
++
++static struct resource ltq_pmu_resource = {
++	.name	= "pmu",
++	.start	= LTQ_PMU_BASE_ADDR,
++	.end	= LTQ_PMU_BASE_ADDR + LTQ_PMU_SIZE - 1,
++	.flags	= IORESOURCE_MEM,
++};
++
++static void __iomem *ltq_pmu_membase;
++
++void ltq_pmu_enable(unsigned int module)
++{
++	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));
++
++	if (!err)
++		panic("activating PMU module failed!\n");
++}
++EXPORT_SYMBOL(ltq_pmu_enable);
++
++void ltq_pmu_disable(unsigned int module)
++{
++	ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | module, LTQ_PMU_PWDCR);
++}
++EXPORT_SYMBOL(ltq_pmu_disable);
++
++int __init ltq_pmu_init(void)
++{
++	if (insert_resource(&iomem_resource, &ltq_pmu_resource) < 0)
++		panic("Failed to insert pmu memory\n");
++
++	if (request_mem_region(ltq_pmu_resource.start,
++			resource_size(&ltq_pmu_resource), "pmu") < 0)
++		panic("Failed to request pmu memory\n");
++
++	ltq_pmu_membase = ioremap_nocache(ltq_pmu_resource.start,
++				resource_size(&ltq_pmu_resource));
++	if (!ltq_pmu_membase)
++		panic("Failed to remap pmu memory\n");
++	return 0;
++}
++
++core_initcall(ltq_pmu_init);
+--- /dev/null
++++ b/arch/mips/lantiq/xway/prom-ase.c
+@@ -0,0 +1,39 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#include <linux/module.h>
++#include <linux/clk.h>
++#include <asm/bootinfo.h>
++#include <asm/time.h>
++
++#include <lantiq_soc.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;
++	switch (i->partnum) {
++	case SOC_ID_AMAZON_SE:
++		i->name = SOC_AMAZON_SE;
++		i->type = SOC_TYPE_AMAZON_SE;
++		break;
++
++	default:
++		unreachable();
++		break;
++	}
++}
+--- /dev/null
++++ b/arch/mips/lantiq/xway/prom-xway.c
+@@ -0,0 +1,54 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#include <linux/module.h>
++#include <linux/clk.h>
++#include <asm/bootinfo.h>
++#include <asm/time.h>
++
++#include <lantiq_soc.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;
++	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;
++	}
++}
+--- /dev/null
++++ b/arch/mips/lantiq/xway/reset.c
+@@ -0,0 +1,91 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#include <linux/init.h>
++#include <linux/io.h>
++#include <linux/ioport.h>
++#include <linux/pm.h>
++#include <linux/module.h>
++#include <asm/reboot.h>
++
++#include <lantiq_soc.h>
++
++#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
++
++static struct resource ltq_rcu_resource = {
++	.name   = "rcu",
++	.start  = LTQ_RCU_BASE_ADDR,
++	.end    = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1,
++	.flags  = IORESOURCE_MEM,
++};
++
++/* remapped base addr of the reset control unit */
++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;
++}
++EXPORT_SYMBOL_GPL(ltq_reset_cause);
++
++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);
++	unreachable();
++}
++
++static void ltq_machine_halt(void)
++{
++	pr_notice("System halted.\n");
++	local_irq_disable();
++	unreachable();
++}
++
++static void ltq_machine_power_off(void)
++{
++	pr_notice("Please turn off the power now.\n");
++	local_irq_disable();
++	unreachable();
++}
++
++static int __init mips_reboot_setup(void)
++{
++	/* insert and request the memory region */
++	if (insert_resource(&iomem_resource, &ltq_rcu_resource) < 0)
++		panic("Failed to insert rcu memory\n");
++
++	if (request_mem_region(ltq_rcu_resource.start,
++			resource_size(&ltq_rcu_resource), "rcu") < 0)
++		panic("Failed to request rcu memory\n");
++
++	/* remap rcu register range */
++	ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start,
++				resource_size(&ltq_rcu_resource));
++	if (!ltq_rcu_membase)
++		panic("Failed to remap rcu memory\n");
++
++	_machine_restart = ltq_machine_restart;
++	_machine_halt = ltq_machine_halt;
++	pm_power_off = ltq_machine_power_off;
++
++	return 0;
++}
++
++arch_initcall(mips_reboot_setup);

+ 546 - 0
target/linux/lantiq/patches-2.6.32/0003-MIPS-Lantiq-Add-PCI-controller-support.patch

@@ -0,0 +1,546 @@
+From 08127ed36bad367903591bbf0f244179683ccb28 Mon Sep 17 00:00:00 2001
+From: John Crispin <[email protected]>
+Date: Wed, 30 Mar 2011 09:27:49 +0200
+Subject: [PATCH 03/13] MIPS: Lantiq: Add PCI controller support.
+
+The Lantiq family of SoCs have a EBU (External Bus Unit). This patch adds
+the driver that allows us to use the EBU as a PCI controller. In order for
+PCI to work the EBU is set to endianess swap all the data. In addition we
+need to make use of SWAP_IO_SPACE for device->host DMA to work.
+
+The clock of the PCI works in several modes (internal/external). If this
+is not configured correctly the SoC will hang.
+
+Signed-off-by: John Crispin <[email protected]>
+Signed-off-by: Ralph Hempel <[email protected]>
+Cc: [email protected]
+Patchwork: https://patchwork.linux-mips.org/patch/2250/
+Signed-off-by: Ralf Baechle <[email protected]>
+---
+ .../mips/include/asm/mach-lantiq/lantiq_platform.h |   46 +++
+ arch/mips/pci/Makefile                             |    1 +
+ arch/mips/pci/ops-lantiq.c                         |  116 ++++++++
+ arch/mips/pci/pci-lantiq.c                         |  297 ++++++++++++++++++++
+ arch/mips/pci/pci-lantiq.h                         |   18 ++
+ 5 files changed, 478 insertions(+), 0 deletions(-)
+ create mode 100644 arch/mips/include/asm/mach-lantiq/lantiq_platform.h
+ create mode 100644 arch/mips/pci/ops-lantiq.c
+ create mode 100644 arch/mips/pci/pci-lantiq.c
+ create mode 100644 arch/mips/pci/pci-lantiq.h
+
+diff --git a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
+new file mode 100644
+index 0000000..1f1dba6
+--- /dev/null
++++ b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
+@@ -0,0 +1,46 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#ifndef _LANTIQ_PLATFORM_H__
++#define _LANTIQ_PLATFORM_H__
++
++#include <linux/mtd/partitions.h>
++
++/* struct used to pass info to the pci core */
++enum {
++	PCI_CLOCK_INT = 0,
++	PCI_CLOCK_EXT
++};
++
++#define PCI_EXIN0	0x0001
++#define PCI_EXIN1	0x0002
++#define PCI_EXIN2	0x0004
++#define PCI_EXIN3	0x0008
++#define PCI_EXIN4	0x0010
++#define PCI_EXIN5	0x0020
++#define PCI_EXIN_MAX	6
++
++#define PCI_GNT1	0x0040
++#define PCI_GNT2	0x0080
++#define PCI_GNT3	0x0100
++#define PCI_GNT4	0x0200
++
++#define PCI_REQ1	0x0400
++#define PCI_REQ2	0x0800
++#define PCI_REQ3	0x1000
++#define PCI_REQ4	0x2000
++#define PCI_REQ_SHIFT	10
++#define PCI_REQ_MASK	0xf
++
++struct ltq_pci_data {
++	int clock;
++	int gpio;
++	int irq[16];
++};
++
++#endif
+diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
+index f0d5329..4df8799 100644
+--- a/arch/mips/pci/Makefile
++++ b/arch/mips/pci/Makefile
+@@ -41,6 +41,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_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/ops-lantiq.c b/arch/mips/pci/ops-lantiq.c
+new file mode 100644
+index 0000000..1f2afb5
+--- /dev/null
++++ b/arch/mips/pci/ops-lantiq.c
+@@ -0,0 +1,116 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/mm.h>
++#include <asm/addrspace.h>
++#include <linux/vmalloc.h>
++
++#include <lantiq_soc.h>
++
++#include "pci-lantiq.h"
++
++#define LTQ_PCI_CFG_BUSNUM_SHF 16
++#define LTQ_PCI_CFG_DEVNUM_SHF 11
++#define LTQ_PCI_CFG_FUNNUM_SHF 8
++
++#define PCI_ACCESS_READ  0
++#define PCI_ACCESS_WRITE 1
++
++static int ltq_pci_config_access(unsigned char access_type, struct pci_bus *bus,
++	unsigned int devfn, unsigned int where, u32 *data)
++{
++	unsigned long cfg_base;
++	unsigned long flags;
++	u32 temp;
++
++	/* we support slot from 0 to 15 dev_fn & 0x68 (AD29) is the
++	   SoC itself */
++	if ((bus->number != 0) || ((devfn & 0xf8) > 0x78)
++		|| ((devfn & 0xf8) == 0) || ((devfn & 0xf8) == 0x68))
++		return 1;
++
++	spin_lock_irqsave(&ebu_lock, flags);
++
++	cfg_base = (unsigned long) ltq_pci_mapped_cfg;
++	cfg_base |= (bus->number << LTQ_PCI_CFG_BUSNUM_SHF) | (devfn <<
++			LTQ_PCI_CFG_FUNNUM_SHF) | (where & ~0x3);
++
++	/* Perform access */
++	if (access_type == PCI_ACCESS_WRITE) {
++		ltq_w32(swab32(*data), ((u32 *)cfg_base));
++	} else {
++		*data = ltq_r32(((u32 *)(cfg_base)));
++		*data = swab32(*data);
++	}
++	wmb();
++
++	/* clean possible Master abort */
++	cfg_base = (unsigned long) ltq_pci_mapped_cfg;
++	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 |= (0x68 << LTQ_PCI_CFG_FUNNUM_SHF) + 4;
++	ltq_w32(temp, ((u32 *)cfg_base));
++
++	spin_unlock_irqrestore(&ebu_lock, flags);
++
++	if (((*data) == 0xffffffff) && (access_type == PCI_ACCESS_READ))
++		return 1;
++
++	return 0;
++}
++
++int ltq_pci_read_config_dword(struct pci_bus *bus, unsigned int devfn,
++	int where, int size, u32 *val)
++{
++	u32 data = 0;
++
++	if (ltq_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
++		return PCIBIOS_DEVICE_NOT_FOUND;
++
++	if (size == 1)
++		*val = (data >> ((where & 3) << 3)) & 0xff;
++	else if (size == 2)
++		*val = (data >> ((where & 3) << 3)) & 0xffff;
++	else
++		*val = data;
++
++	return PCIBIOS_SUCCESSFUL;
++}
++
++int ltq_pci_write_config_dword(struct pci_bus *bus, unsigned int devfn,
++	int where, int size, u32 val)
++{
++	u32 data = 0;
++
++	if (size == 4) {
++		data = val;
++	} else {
++		if (ltq_pci_config_access(PCI_ACCESS_READ, bus,
++				devfn, where, &data))
++			return PCIBIOS_DEVICE_NOT_FOUND;
++
++		if (size == 1)
++			data = (data & ~(0xff << ((where & 3) << 3))) |
++				(val << ((where & 3) << 3));
++		else if (size == 2)
++			data = (data & ~(0xffff << ((where & 3) << 3))) |
++				(val << ((where & 3) << 3));
++	}
++
++	if (ltq_pci_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
++		return PCIBIOS_DEVICE_NOT_FOUND;
++
++	return PCIBIOS_SUCCESSFUL;
++}
+diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c
+new file mode 100644
+index 0000000..603d749
+--- /dev/null
++++ b/arch/mips/pci/pci-lantiq.c
+@@ -0,0 +1,297 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#include <linux/types.h>
++#include <linux/pci.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/mm.h>
++#include <linux/vmalloc.h>
++#include <linux/platform_device.h>
++
++#include <asm/pci.h>
++#include <asm/gpio.h>
++#include <asm/addrspace.h>
++
++#include <lantiq_soc.h>
++#include <lantiq_irq.h>
++#include <lantiq_platform.h>
++
++#include "pci-lantiq.h"
++
++#define LTQ_PCI_CFG_BASE		0x17000000
++#define LTQ_PCI_CFG_SIZE		0x00008000
++#define LTQ_PCI_MEM_BASE		0x18000000
++#define LTQ_PCI_MEM_SIZE		0x02000000
++#define LTQ_PCI_IO_BASE			0x1AE00000
++#define LTQ_PCI_IO_SIZE			0x00200000
++
++#define PCI_CR_FCI_ADDR_MAP0		0x00C0
++#define PCI_CR_FCI_ADDR_MAP1		0x00C4
++#define PCI_CR_FCI_ADDR_MAP2		0x00C8
++#define PCI_CR_FCI_ADDR_MAP3		0x00CC
++#define PCI_CR_FCI_ADDR_MAP4		0x00D0
++#define PCI_CR_FCI_ADDR_MAP5		0x00D4
++#define PCI_CR_FCI_ADDR_MAP6		0x00D8
++#define PCI_CR_FCI_ADDR_MAP7		0x00DC
++#define PCI_CR_CLK_CTRL			0x0000
++#define PCI_CR_PCI_MOD			0x0030
++#define PCI_CR_PC_ARB			0x0080
++#define PCI_CR_FCI_ADDR_MAP11hg		0x00E4
++#define PCI_CR_BAR11MASK		0x0044
++#define PCI_CR_BAR12MASK		0x0048
++#define PCI_CR_BAR13MASK		0x004C
++#define PCI_CS_BASE_ADDR1		0x0010
++#define PCI_CR_PCI_ADDR_MAP11		0x0064
++#define PCI_CR_FCI_BURST_LENGTH		0x00E8
++#define PCI_CR_PCI_EOI			0x002C
++#define PCI_CS_STS_CMD			0x0004
++
++#define PCI_MASTER0_REQ_MASK_2BITS	8
++#define PCI_MASTER1_REQ_MASK_2BITS	10
++#define PCI_MASTER2_REQ_MASK_2BITS	12
++#define INTERNAL_ARB_ENABLE_BIT		0
++
++#define LTQ_CGU_IFCCR		0x0018
++#define LTQ_CGU_PCICR		0x0034
++
++#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))
++
++struct ltq_pci_gpio_map {
++	int pin;
++	int alt0;
++	int alt1;
++	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" },
++};
++
++__iomem void *ltq_pci_mapped_cfg;
++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;
++
++struct pci_ops ltq_pci_ops = {
++	.read	= ltq_pci_read_config_dword,
++	.write	= ltq_pci_write_config_dword
++};
++
++static struct resource pci_io_resource = {
++	.name	= "pci io space",
++	.start	= LTQ_PCI_IO_BASE,
++	.end	= LTQ_PCI_IO_BASE + LTQ_PCI_IO_SIZE - 1,
++	.flags	= IORESOURCE_IO
++};
++
++static struct resource pci_mem_resource = {
++	.name	= "pci memory space",
++	.start	= LTQ_PCI_MEM_BASE,
++	.end	= LTQ_PCI_MEM_BASE + LTQ_PCI_MEM_SIZE - 1,
++	.flags	= IORESOURCE_MEM
++};
++
++static struct pci_controller ltq_pci_controller = {
++	.pci_ops	= &ltq_pci_ops,
++	.mem_resource	= &pci_mem_resource,
++	.mem_offset	= 0x00000000UL,
++	.io_resource	= &pci_io_resource,
++	.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;
++
++	/* BAR11MASK value depends on available memory on system. */
++	mem = num_physpages * PAGE_SIZE;
++	bar11mask = (0x0ffffff0 & ~((1 << (fls(mem) - 1)) - 1)) | 8;
++
++	return bar11mask;
++}
++
++static void ltq_pci_setup_gpio(int gpio)
++{
++	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,
++				ltq_pci_gpio_map[i].alt0,
++				ltq_pci_gpio_map[i].alt1,
++				ltq_pci_gpio_map[i].dir,
++				ltq_pci_gpio_map[i].name);
++		}
++	}
++	ltq_gpio_request(21, 0, 0, 1, "pci-reset");
++	ltq_pci_req_mask = (gpio >> PCI_REQ_SHIFT) & PCI_REQ_MASK;
++}
++
++static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
++{
++	u32 temp_buffer;
++
++	/* set clock to 33Mhz */
++	ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR);
++	ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR);
++
++	/* external or internal clock ? */
++	if (conf->clock) {
++		ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~(1 << 16),
++			LTQ_CGU_IFCCR);
++		ltq_cgu_w32((1 << 30), LTQ_CGU_PCICR);
++	} else {
++		ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | (1 << 16),
++			LTQ_CGU_IFCCR);
++		ltq_cgu_w32((1 << 31) | (1 << 30), LTQ_CGU_PCICR);
++	}
++
++	/* setup pci clock and gpis used by pci */
++	ltq_pci_setup_gpio(conf->gpio);
++
++	/* enable auto-switching between PCI and EBU */
++	ltq_pci_w32(0xa, PCI_CR_CLK_CTRL);
++
++	/* busy, i.e. configuration is not done, PCI access has to be retried */
++	ltq_pci_w32(ltq_pci_r32(PCI_CR_PCI_MOD) & ~(1 << 24), PCI_CR_PCI_MOD);
++	wmb();
++	/* BUS Master/IO/MEM access */
++	ltq_pci_cfg_w32(ltq_pci_cfg_r32(PCI_CS_STS_CMD) | 7, PCI_CS_STS_CMD);
++
++	/* enable external 2 PCI masters */
++	temp_buffer = ltq_pci_r32(PCI_CR_PC_ARB);
++	temp_buffer &= (~(ltq_pci_req_mask << 16));
++	/* enable internal arbiter */
++	temp_buffer |= (1 << INTERNAL_ARB_ENABLE_BIT);
++	/* enable internal PCI master reqest */
++	temp_buffer &= (~(3 << PCI_MASTER0_REQ_MASK_2BITS));
++
++	/* enable EBU request */
++	temp_buffer &= (~(3 << PCI_MASTER1_REQ_MASK_2BITS));
++
++	/* enable all external masters request */
++	temp_buffer &= (~(3 << PCI_MASTER2_REQ_MASK_2BITS));
++	ltq_pci_w32(temp_buffer, PCI_CR_PC_ARB);
++	wmb();
++
++	/* setup BAR memory regions */
++	ltq_pci_w32(0x18000000, PCI_CR_FCI_ADDR_MAP0);
++	ltq_pci_w32(0x18400000, PCI_CR_FCI_ADDR_MAP1);
++	ltq_pci_w32(0x18800000, PCI_CR_FCI_ADDR_MAP2);
++	ltq_pci_w32(0x18c00000, PCI_CR_FCI_ADDR_MAP3);
++	ltq_pci_w32(0x19000000, PCI_CR_FCI_ADDR_MAP4);
++	ltq_pci_w32(0x19400000, PCI_CR_FCI_ADDR_MAP5);
++	ltq_pci_w32(0x19800000, PCI_CR_FCI_ADDR_MAP6);
++	ltq_pci_w32(0x19c00000, PCI_CR_FCI_ADDR_MAP7);
++	ltq_pci_w32(0x1ae00000, PCI_CR_FCI_ADDR_MAP11hg);
++	ltq_pci_w32(ltq_calc_bar11mask(), PCI_CR_BAR11MASK);
++	ltq_pci_w32(0, PCI_CR_PCI_ADDR_MAP11);
++	ltq_pci_w32(0, PCI_CS_BASE_ADDR1);
++	/* both TX and RX endian swap are enabled */
++	ltq_pci_w32(ltq_pci_r32(PCI_CR_PCI_EOI) | 3, PCI_CR_PCI_EOI);
++	wmb();
++	ltq_pci_w32(ltq_pci_r32(PCI_CR_BAR12MASK) | 0x80000000,
++		PCI_CR_BAR12MASK);
++	ltq_pci_w32(ltq_pci_r32(PCI_CR_BAR13MASK) | 0x80000000,
++		PCI_CR_BAR13MASK);
++	/*use 8 dw burst length */
++	ltq_pci_w32(0x303, PCI_CR_FCI_BURST_LENGTH);
++	ltq_pci_w32(ltq_pci_r32(PCI_CR_PCI_MOD) | (1 << 24), PCI_CR_PCI_MOD);
++	wmb();
++
++	/* setup irq line */
++	ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_CON) | 0xc, LTQ_EBU_PCC_CON);
++	ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN);
++
++	/* toggle reset pin */
++	__gpio_set_value(21, 0);
++	wmb();
++	mdelay(1);
++	__gpio_set_value(21, 1);
++	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 "ltq_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 =
++		(struct ltq_pci_data *) pdev->dev.platform_data;
++	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 =
++		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);
++	register_pci_controller(&ltq_pci_controller);
++
++	return 0;
++}
++
++static struct platform_driver
++ltq_pci_driver = {
++	.probe = ltq_pci_probe,
++	.driver = {
++		.name = "ltq_pci",
++		.owner = THIS_MODULE,
++	},
++};
++
++int __init pcibios_init(void)
++{
++	int ret = platform_driver_register(&ltq_pci_driver);
++	if (ret)
++		printk(KERN_INFO "ltq_pci: Error registering platfom driver!");
++	return ret;
++}
++
++arch_initcall(pcibios_init);
+diff --git a/arch/mips/pci/pci-lantiq.h b/arch/mips/pci/pci-lantiq.h
+new file mode 100644
+index 0000000..66bf6cd
+--- /dev/null
++++ b/arch/mips/pci/pci-lantiq.h
+@@ -0,0 +1,18 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#ifndef _LTQ_PCI_H__
++#define _LTQ_PCI_H__
++
++extern __iomem void *ltq_pci_mapped_cfg;
++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,
++	unsigned int devfn, int where, int size, u32 val);
++
++#endif
+-- 
+1.7.2.3
+

+ 301 - 0
target/linux/lantiq/patches-2.6.32/0004-MIPS-Lantiq-Add-NOR-flash-support.patch

@@ -0,0 +1,301 @@
+From cd0d53b24ca744295d2cdf69bb2b659571091b75 Mon Sep 17 00:00:00 2001
+From: John Crispin <[email protected]>
+Date: Tue, 12 Apr 2011 18:10:01 +0200
+Subject: [PATCH 04/13] MIPS: Lantiq: Add NOR flash support
+
+This patch adds the driver/map for NOR devices attached to the SoC via the
+External Bus Unit (EBU).
+
+Signed-off-by: John Crispin <[email protected]>
+Signed-off-by: Ralph Hempel <[email protected]>
+Cc: David Woodhouse <[email protected]>
+Cc: Daniel Schwierzeck <[email protected]>
+Cc: [email protected]
+Cc: [email protected]
+Acked-by: Artem Bityutskiy <[email protected]>
+Patchwork: https://patchwork.linux-mips.org/patch/2285/
+Signed-off-by: Ralf Baechle <[email protected]>
+---
+ drivers/mtd/maps/Kconfig        |    7 +
+ drivers/mtd/maps/Makefile       |    1 +
+ drivers/mtd/maps/lantiq-flash.c |  251 +++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 259 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/mtd/maps/lantiq-flash.c
+
+--- a/drivers/mtd/maps/Kconfig
++++ b/drivers/mtd/maps/Kconfig
+@@ -259,6 +259,13 @@
+ 	help
+ 	  Flash memory access on AMD Alchemy Pb/Db/RDK Reference Boards
+ 
++config MTD_LANTIQ
++	tristate "Lantiq SoC NOR support"
++	depends on LANTIQ
++	select MTD_PARTITIONS
++	help
++	  Support for NOR flash attached to the Lantiq SoC's External Bus Unit.
++
+ config MTD_DILNETPC
+ 	tristate "CFI Flash device mapped on DIL/Net PC"
+ 	depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN
+--- a/drivers/mtd/maps/Makefile
++++ b/drivers/mtd/maps/Makefile
+@@ -61,3 +61,4 @@
+ obj-$(CONFIG_MTD_RBTX4939)	+= rbtx4939-flash.o
+ obj-$(CONFIG_MTD_VMU)		+= vmu-flash.o
+ obj-$(CONFIG_MTD_GPIO_ADDR)	+= gpio-addr-flash.o
++obj-$(CONFIG_MTD_LANTIQ)	+= lantiq-flash.o
+--- /dev/null
++++ b/drivers/mtd/maps/lantiq-flash.c
+@@ -0,0 +1,251 @@
++/*
++ *  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) 2004 Liu Peng Infineon IFAP DC COM CPE
++ *  Copyright (C) 2010 John Crispin <[email protected]>
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/io.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++#include <linux/mtd/cfi.h>
++#include <linux/platform_device.h>
++#include <linux/mtd/physmap.h>
++
++#include <lantiq_soc.h>
++#include <lantiq_platform.h>
++
++/*
++ * The NOR flash is connected to the same external bus unit (EBU) as PCI.
++ * To make PCI work we need to enable the endianness swapping for the address
++ * written to the EBU. This endianness swapping works for PCI correctly but
++ * fails for attached NOR devices. To workaround this we need to use a complex
++ * map. The workaround involves swapping all addresses whilst probing the chip.
++ * Once probing is complete we stop swapping the addresses but swizzle the
++ * unlock addresses to ensure that access to the NOR device works correctly.
++ */
++
++enum {
++	LTQ_NOR_PROBING,
++	LTQ_NOR_NORMAL
++};
++
++struct ltq_mtd {
++	struct resource *res;
++	struct mtd_info *mtd;
++	struct map_info *map;
++};
++
++static char ltq_map_name[] = "ltq_nor";
++
++static map_word
++ltq_read16(struct map_info *map, unsigned long adr)
++{
++	unsigned long flags;
++	map_word temp;
++
++	if (map->map_priv_1 == LTQ_NOR_PROBING)
++		adr ^= 2;
++	spin_lock_irqsave(&ebu_lock, flags);
++	temp.x[0] = *(u16 *)(map->virt + adr);
++	spin_unlock_irqrestore(&ebu_lock, flags);
++	return temp;
++}
++
++static void
++ltq_write16(struct map_info *map, map_word d, unsigned long adr)
++{
++	unsigned long flags;
++
++	if (map->map_priv_1 == LTQ_NOR_PROBING)
++		adr ^= 2;
++	spin_lock_irqsave(&ebu_lock, flags);
++	*(u16 *)(map->virt + adr) = d.x[0];
++	spin_unlock_irqrestore(&ebu_lock, flags);
++}
++
++/*
++ * The following 2 functions copy data between iomem and a cached memory
++ * section. As memcpy() makes use of pre-fetching we cannot use it here.
++ * The normal alternative of using memcpy_{to,from}io also makes use of
++ * memcpy() on MIPS so it is not applicable either. We are therefore stuck
++ * with having to use our own loop.
++ */
++static void
++ltq_copy_from(struct map_info *map, void *to,
++	unsigned long from, ssize_t len)
++{
++	unsigned char *f = (unsigned char *)map->virt + from;
++	unsigned char *t = (unsigned char *)to;
++	unsigned long flags;
++
++	spin_lock_irqsave(&ebu_lock, flags);
++	while (len--)
++		*t++ = *f++;
++	spin_unlock_irqrestore(&ebu_lock, flags);
++}
++
++static void
++ltq_copy_to(struct map_info *map, unsigned long to,
++	const void *from, ssize_t len)
++{
++	unsigned char *f = (unsigned char *)from;
++	unsigned char *t = (unsigned char *)map->virt + to;
++	unsigned long flags;
++
++	spin_lock_irqsave(&ebu_lock, flags);
++	while (len--)
++		*t++ = *f++;
++	spin_unlock_irqrestore(&ebu_lock, flags);
++}
++
++static const char const *part_probe_types[] = { "cmdlinepart", NULL };
++
++static int __init
++ltq_mtd_probe(struct platform_device *pdev)
++{
++	struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev);
++	struct ltq_mtd *ltq_mtd;
++	struct mtd_partition *parts;
++	struct resource *res;
++	int nr_parts = 0;
++	struct cfi_private *cfi;
++	int err;
++
++	ltq_mtd = kzalloc(sizeof(struct ltq_mtd), GFP_KERNEL);
++	platform_set_drvdata(pdev, ltq_mtd);
++
++	ltq_mtd->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!ltq_mtd->res) {
++		dev_err(&pdev->dev, "failed to get memory resource");
++		err = -ENOENT;
++		goto err_out;
++	}
++
++	res = devm_request_mem_region(&pdev->dev, ltq_mtd->res->start,
++		resource_size(ltq_mtd->res), dev_name(&pdev->dev));
++	if (!ltq_mtd->res) {
++		dev_err(&pdev->dev, "failed to request mem resource");
++		err = -EBUSY;
++		goto err_out;
++	}
++
++	ltq_mtd->map = kzalloc(sizeof(struct map_info), GFP_KERNEL);
++	ltq_mtd->map->phys = res->start;
++	ltq_mtd->map->size = resource_size(res);
++	ltq_mtd->map->virt = devm_ioremap_nocache(&pdev->dev,
++				ltq_mtd->map->phys, ltq_mtd->map->size);
++	if (!ltq_mtd->map->virt) {
++		dev_err(&pdev->dev, "failed to ioremap!\n");
++		err = -ENOMEM;
++		goto err_free;
++	}
++
++	ltq_mtd->map->name = ltq_map_name;
++	ltq_mtd->map->bankwidth = 2;
++	ltq_mtd->map->read = ltq_read16;
++	ltq_mtd->map->write = ltq_write16;
++	ltq_mtd->map->copy_from = ltq_copy_from;
++	ltq_mtd->map->copy_to = ltq_copy_to;
++
++	ltq_mtd->map->map_priv_1 = LTQ_NOR_PROBING;
++	ltq_mtd->mtd = do_map_probe("cfi_probe", ltq_mtd->map);
++	ltq_mtd->map->map_priv_1 = LTQ_NOR_NORMAL;
++
++	if (!ltq_mtd->mtd) {
++		dev_err(&pdev->dev, "probing failed\n");
++		err = -ENXIO;
++		goto err_unmap;
++	}
++
++	ltq_mtd->mtd->owner = THIS_MODULE;
++
++	cfi = ltq_mtd->map->fldrv_priv;
++	cfi->addr_unlock1 ^= 1;
++	cfi->addr_unlock2 ^= 1;
++
++	nr_parts = parse_mtd_partitions(ltq_mtd->mtd,
++				part_probe_types, &parts, 0);
++	if (nr_parts > 0) {
++		dev_info(&pdev->dev,
++			"using %d partitions from cmdline", nr_parts);
++	} else {
++		nr_parts = ltq_mtd_data->nr_parts;
++		parts = ltq_mtd_data->parts;
++	}
++
++	err = add_mtd_partitions(ltq_mtd->mtd, parts, nr_parts);
++	if (err) {
++		dev_err(&pdev->dev, "failed to add partitions\n");
++		goto err_destroy;
++	}
++
++	return 0;
++
++err_destroy:
++	map_destroy(ltq_mtd->mtd);
++err_unmap:
++	iounmap(ltq_mtd->map->virt);
++err_free:
++	kfree(ltq_mtd->map);
++err_out:
++	kfree(ltq_mtd);
++	return err;
++}
++
++static int __devexit
++ltq_mtd_remove(struct platform_device *pdev)
++{
++	struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev);
++
++	if (ltq_mtd) {
++		if (ltq_mtd->mtd) {
++			del_mtd_partitions(ltq_mtd->mtd);
++			map_destroy(ltq_mtd->mtd);
++		}
++		if (ltq_mtd->map->virt)
++			iounmap(ltq_mtd->map->virt);
++		kfree(ltq_mtd->map);
++		kfree(ltq_mtd);
++	}
++	return 0;
++}
++
++static struct platform_driver ltq_mtd_driver = {
++	.remove = __devexit_p(ltq_mtd_remove),
++	.driver = {
++		.name = "ltq_nor",
++		.owner = THIS_MODULE,
++	},
++};
++
++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_LICENSE("GPL");
++MODULE_AUTHOR("John Crispin <[email protected]>");
++MODULE_DESCRIPTION("Lantiq SoC NOR");

+ 338 - 0
target/linux/lantiq/patches-2.6.32/0005-MIPS-Lantiq-Add-platform-device-support.patch

@@ -0,0 +1,338 @@
+From 09e57348261c1ae0ff89c68679126fc76a28b2a2 Mon Sep 17 00:00:00 2001
+From: John Crispin <[email protected]>
+Date: Wed, 30 Mar 2011 09:27:53 +0200
+Subject: [PATCH 05/13] MIPS: Lantiq: Add platform device support
+
+This patch adds the wrappers for registering our platform devices.
+
+Signed-off-by: John Crispin <[email protected]>
+Signed-off-by: Ralph Hempel <[email protected]>
+Cc: [email protected]
+Patchwork: https://patchwork.linux-mips.org/patch/2254/
+Patchwork: https://patchwork.linux-mips.org/patch/2360/
+Patchwork: https://patchwork.linux-mips.org/patch/2359/
+Signed-off-by: Ralf Baechle <[email protected]>
+---
+ arch/mips/lantiq/Makefile       |    2 +-
+ arch/mips/lantiq/devices.c      |  122 +++++++++++++++++++++++++++++++++++++++
+ arch/mips/lantiq/devices.h      |   23 +++++++
+ arch/mips/lantiq/xway/Makefile  |    2 +-
+ arch/mips/lantiq/xway/devices.c |   98 +++++++++++++++++++++++++++++++
+ arch/mips/lantiq/xway/devices.h |   18 ++++++
+ 6 files changed, 263 insertions(+), 2 deletions(-)
+ create mode 100644 arch/mips/lantiq/devices.c
+ create mode 100644 arch/mips/lantiq/devices.h
+ create mode 100644 arch/mips/lantiq/xway/devices.c
+ create mode 100644 arch/mips/lantiq/xway/devices.h
+
+diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile
+index a268391..e5dae0e 100644
+--- a/arch/mips/lantiq/Makefile
++++ b/arch/mips/lantiq/Makefile
+@@ -4,7 +4,7 @@
+ # under the terms of the GNU General Public License version 2 as published
+ # by the Free Software Foundation.
+ 
+-obj-y := irq.o setup.o clk.o prom.o
++obj-y := irq.o setup.o clk.o prom.o devices.o
+ 
+ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
+ 
+diff --git a/arch/mips/lantiq/devices.c b/arch/mips/lantiq/devices.c
+new file mode 100644
+index 0000000..7b82c34
+--- /dev/null
++++ b/arch/mips/lantiq/devices.c
+@@ -0,0 +1,122 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/string.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 "devices.h"
++
++/* nor flash */
++static struct resource ltq_nor_resource = {
++	.name	= "nor",
++	.start	= LTQ_FLASH_START,
++	.end	= LTQ_FLASH_START + LTQ_FLASH_MAX - 1,
++	.flags  = IORESOURCE_MEM,
++};
++
++static struct platform_device ltq_nor = {
++	.name		= "ltq_nor",
++	.resource	= &ltq_nor_resource,
++	.num_resources	= 1,
++};
++
++void __init ltq_register_nor(struct physmap_flash_data *data)
++{
++	ltq_nor.dev.platform_data = data;
++	platform_device_register(&ltq_nor);
++}
++
++/* watchdog */
++static struct resource ltq_wdt_resource = {
++	.name	= "watchdog",
++	.start  = LTQ_WDT_BASE_ADDR,
++	.end    = LTQ_WDT_BASE_ADDR + LTQ_WDT_SIZE - 1,
++	.flags  = IORESOURCE_MEM,
++};
++
++void __init ltq_register_wdt(void)
++{
++	platform_device_register_simple("ltq_wdt", 0, &ltq_wdt_resource, 1);
++}
++
++/* asc ports */
++static struct resource ltq_asc0_resources[] = {
++	{
++		.name	= "asc0",
++		.start  = LTQ_ASC0_BASE_ADDR,
++		.end    = LTQ_ASC0_BASE_ADDR + LTQ_ASC_SIZE - 1,
++		.flags  = IORESOURCE_MEM,
++	},
++	IRQ_RES(tx, LTQ_ASC_TIR(0)),
++	IRQ_RES(rx, LTQ_ASC_RIR(0)),
++	IRQ_RES(err, LTQ_ASC_EIR(0)),
++};
++
++static struct resource ltq_asc1_resources[] = {
++	{
++		.name	= "asc1",
++		.start  = LTQ_ASC1_BASE_ADDR,
++		.end    = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
++		.flags  = IORESOURCE_MEM,
++	},
++	IRQ_RES(tx, LTQ_ASC_TIR(1)),
++	IRQ_RES(rx, LTQ_ASC_RIR(1)),
++	IRQ_RES(err, LTQ_ASC_EIR(1)),
++};
++
++void __init ltq_register_asc(int port)
++{
++	switch (port) {
++	case 0:
++		platform_device_register_simple("ltq_asc", 0,
++			ltq_asc0_resources, ARRAY_SIZE(ltq_asc0_resources));
++		break;
++	case 1:
++		platform_device_register_simple("ltq_asc", 1,
++			ltq_asc1_resources, ARRAY_SIZE(ltq_asc1_resources));
++		break;
++	default:
++		break;
++	}
++}
++
++#ifdef CONFIG_PCI
++/* pci */
++static struct platform_device ltq_pci = {
++	.name		= "ltq_pci",
++	.num_resources	= 0,
++};
++
++void __init ltq_register_pci(struct ltq_pci_data *data)
++{
++	ltq_pci.dev.platform_data = data;
++	platform_device_register(&ltq_pci);
++}
++#else
++void __init ltq_register_pci(struct ltq_pci_data *data)
++{
++	pr_err("kernel is compiled without PCI support\n");
++}
++#endif
+diff --git a/arch/mips/lantiq/devices.h b/arch/mips/lantiq/devices.h
+new file mode 100644
+index 0000000..2947bb1
+--- /dev/null
++++ b/arch/mips/lantiq/devices.h
+@@ -0,0 +1,23 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#ifndef _LTQ_DEVICES_H__
++#define _LTQ_DEVICES_H__
++
++#include <lantiq_platform.h>
++#include <linux/mtd/physmap.h>
++
++#define IRQ_RES(resname, irq) \
++	{.name = #resname, .start = (irq), .flags = IORESOURCE_IRQ}
++
++extern void ltq_register_nor(struct physmap_flash_data *data);
++extern void ltq_register_wdt(void);
++extern void ltq_register_asc(int port);
++extern void ltq_register_pci(struct ltq_pci_data *data);
++
++#endif
+diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
+index 9c85ff9..74ce438 100644
+--- a/arch/mips/lantiq/xway/Makefile
++++ b/arch/mips/lantiq/xway/Makefile
+@@ -1,4 +1,4 @@
+-obj-y := pmu.o ebu.o reset.o gpio.o
++obj-y := pmu.o ebu.o reset.o gpio.o devices.o
+ 
+ obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
+ obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
+diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
+new file mode 100644
+index 0000000..a71b3b5
+--- /dev/null
++++ b/arch/mips/lantiq/xway/devices.c
+@@ -0,0 +1,98 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#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>
++
++#include "devices.h"
++
++/* gpio */
++static struct resource ltq_gpio_resource[] = {
++	{
++		.name	= "gpio0",
++		.start  = LTQ_GPIO0_BASE_ADDR,
++		.end    = LTQ_GPIO0_BASE_ADDR + LTQ_GPIO_SIZE - 1,
++		.flags  = IORESOURCE_MEM,
++	}, {
++		.name	= "gpio1",
++		.start  = LTQ_GPIO1_BASE_ADDR,
++		.end    = LTQ_GPIO1_BASE_ADDR + LTQ_GPIO_SIZE - 1,
++		.flags  = IORESOURCE_MEM,
++	}, {
++		.name	= "gpio2",
++		.start  = LTQ_GPIO2_BASE_ADDR,
++		.end    = LTQ_GPIO2_BASE_ADDR + LTQ_GPIO_SIZE - 1,
++		.flags  = IORESOURCE_MEM,
++	}
++};
++
++void __init ltq_register_gpio(void)
++{
++	platform_device_register_simple("ltq_gpio", 0,
++		&ltq_gpio_resource[0], 1);
++	platform_device_register_simple("ltq_gpio", 1,
++		&ltq_gpio_resource[1], 1);
++
++	/* AR9 and VR9 have an extra gpio block */
++	if (ltq_is_ar9() || ltq_is_vr9()) {
++		platform_device_register_simple("ltq_gpio", 2,
++			&ltq_gpio_resource[2], 1);
++	}
++}
++
++/* serial to parallel conversion */
++static struct resource ltq_stp_resource = {
++	.name   = "stp",
++	.start  = LTQ_STP_BASE_ADDR,
++	.end    = LTQ_STP_BASE_ADDR + LTQ_STP_SIZE - 1,
++	.flags  = IORESOURCE_MEM,
++};
++
++void __init ltq_register_gpio_stp(void)
++{
++	platform_device_register_simple("ltq_stp", 0, &ltq_stp_resource, 1);
++}
++
++/* asc ports - amazon se has its own serial mapping */
++static struct resource ltq_ase_asc_resources[] = {
++	{
++		.name	= "asc0",
++		.start  = LTQ_ASC1_BASE_ADDR,
++		.end    = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
++		.flags  = IORESOURCE_MEM,
++	},
++	IRQ_RES(tx, LTQ_ASC_ASE_TIR),
++	IRQ_RES(rx, LTQ_ASC_ASE_RIR),
++	IRQ_RES(err, LTQ_ASC_ASE_EIR),
++};
++
++void __init ltq_register_ase_asc(void)
++{
++	platform_device_register_simple("ltq_asc", 0,
++		ltq_ase_asc_resources, ARRAY_SIZE(ltq_ase_asc_resources));
++}
+diff --git a/arch/mips/lantiq/xway/devices.h b/arch/mips/lantiq/xway/devices.h
+new file mode 100644
+index 0000000..51f56b5
+--- /dev/null
++++ b/arch/mips/lantiq/xway/devices.h
+@@ -0,0 +1,18 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#ifndef _LTQ_DEVICES_XWAY_H__
++#define _LTQ_DEVICES_XWAY_H__
++
++#include "../devices.h"
++
++extern void ltq_register_gpio(void);
++extern void ltq_register_gpio_stp(void);
++extern void ltq_register_ase_asc(void);
++
++#endif
+-- 
+1.7.2.3
+

+ 170 - 0
target/linux/lantiq/patches-2.6.32/0006-MIPS-Lantiq-Add-mips_machine-support.patch

@@ -0,0 +1,170 @@
+From 52a5369d1067d4feddbfa7ff4486a77ac9a2971e Mon Sep 17 00:00:00 2001
+From: John Crispin <[email protected]>
+Date: Wed, 30 Mar 2011 09:27:54 +0200
+Subject: [PATCH 06/13] MIPS: Lantiq: Add mips_machine support
+
+This patch adds support for Gabor's mips_machine patch.
+
+Signed-off-by: John Crispin <[email protected]>
+Signed-off-by: Ralph Hempel <[email protected]>
+Cc: Gabor Juhos <[email protected]>
+Cc: [email protected]
+Patchwork: https://patchwork.linux-mips.org/patch/2251/
+Patchwork: https://patchwork.linux-mips.org/patch/2358/
+Signed-off-by: Ralf Baechle <[email protected]>
+---
+ arch/mips/Kconfig                  |    1 +
+ arch/mips/lantiq/machtypes.h       |   18 ++++++++++++++++++
+ arch/mips/lantiq/prom.h            |    1 +
+ arch/mips/lantiq/setup.c           |   25 +++++++++++++++++++++++++
+ arch/mips/lantiq/xway/Makefile     |    4 ++--
+ arch/mips/lantiq/xway/setup-ase.c  |   19 +++++++++++++++++++
+ arch/mips/lantiq/xway/setup-xway.c |   20 ++++++++++++++++++++
+ 7 files changed, 86 insertions(+), 2 deletions(-)
+ create mode 100644 arch/mips/lantiq/machtypes.h
+ create mode 100644 arch/mips/lantiq/xway/setup-ase.c
+ create mode 100644 arch/mips/lantiq/xway/setup-xway.c
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -190,6 +190,7 @@
+ 	select SWAP_IO_SPACE
+ 	select BOOT_RAW
+ 	select HAVE_CLK
++	select MIPS_MACHINE
+ 
+ config LASAT
+ 	bool "LASAT Networks platforms"
+--- /dev/null
++++ b/arch/mips/lantiq/machtypes.h
+@@ -0,0 +1,18 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#ifndef _LANTIQ_MACH_H__
++#define _LANTIQ_MACH_H__
++
++#include <asm/mips_machine.h>
++
++enum lantiq_mach_type {
++	LTQ_MACH_GENERIC = 0,
++};
++
++#endif
+--- a/arch/mips/lantiq/prom.h
++++ b/arch/mips/lantiq/prom.h
+@@ -20,5 +20,6 @@
+ };
+ 
+ extern void ltq_soc_detect(struct ltq_soc_info *i);
++extern void ltq_soc_setup(void);
+ 
+ #endif
+--- a/arch/mips/lantiq/setup.c
++++ b/arch/mips/lantiq/setup.c
+@@ -14,6 +14,12 @@
+ 
+ #include <lantiq_soc.h>
+ 
++#include "machtypes.h"
++#include "devices.h"
++#include "prom.h"
++
++unsigned long physical_memsize = 0L;
++
+ void __init plat_mem_setup(void)
+ {
+ 	/* assume 16M as default incase uboot fails to pass proper ramsize */
+@@ -32,10 +38,32 @@
+ 		if (!strncmp(e, "memsize=", 8)) {
+ 			e += 8;
+ 			if (strict_strtoul(e, 0, &memsize))
+-				pr_warn("bad memsize specified\n");
++				pr_warning("bad memsize specified\n");
+ 		}
+ 		envp++;
+ 	}
+ 	memsize *= 1024 * 1024;
+ 	add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
++	physical_memsize = memsize;
++}
++
++static int __init
++lantiq_setup(void)
++{
++	ltq_soc_setup();
++	mips_machine_setup();
++	return 0;
+ }
++
++arch_initcall(lantiq_setup);
++
++static void __init
++lantiq_generic_init(void)
++{
++	/* Nothing to do */
++}
++
++MIPS_MACHINE(LTQ_MACH_GENERIC,
++	     "Generic",
++	     "Generic Lantiq based board",
++	     lantiq_generic_init);
+--- a/arch/mips/lantiq/xway/Makefile
++++ b/arch/mips/lantiq/xway/Makefile
+@@ -1,4 +1,4 @@
+ obj-y := pmu.o ebu.o reset.o gpio.o devices.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) += clk-xway.o prom-xway.o setup-xway.o
++obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o
+--- /dev/null
++++ b/arch/mips/lantiq/xway/setup-ase.c
+@@ -0,0 +1,19 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#include <lantiq_soc.h>
++
++#include "../prom.h"
++#include "devices.h"
++
++void __init ltq_soc_setup(void)
++{
++	ltq_register_ase_asc();
++	ltq_register_gpio();
++	ltq_register_wdt();
++}
+--- /dev/null
++++ b/arch/mips/lantiq/xway/setup-xway.c
+@@ -0,0 +1,20 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#include <lantiq_soc.h>
++
++#include "../prom.h"
++#include "devices.h"
++
++void __init ltq_soc_setup(void)
++{
++	ltq_register_asc(0);
++	ltq_register_asc(1);
++	ltq_register_gpio();
++	ltq_register_wdt();
++}

+ 230 - 0
target/linux/lantiq/patches-2.6.32/0007-MIPS-Lantiq-Add-machtypes-for-lantiq-eval-kits.patch

@@ -0,0 +1,230 @@
+From ab2182fc419548455d03979683eb0e92c372ed79 Mon Sep 17 00:00:00 2001
+From: John Crispin <[email protected]>
+Date: Wed, 30 Mar 2011 09:27:55 +0200
+Subject: [PATCH 07/13] MIPS: Lantiq: Add machtypes for lantiq eval kits
+
+This patch adds mach specific code for the Lantiq EASY50712/50601 evaluation
+boards
+
+Signed-off-by: John Crispin <[email protected]>
+Signed-off-by: Ralph Hempel <[email protected]>
+Cc: [email protected]
+Patchwork: https://patchwork.linux-mips.org/patch/2255/
+Patchwork: https://patchwork.linux-mips.org/patch/2361/
+Signed-off-by: Ralf Baechle <[email protected]>
+---
+ arch/mips/lantiq/Kconfig               |    2 +
+ arch/mips/lantiq/machtypes.h           |    2 +
+ arch/mips/lantiq/xway/Kconfig          |   23 +++++++++++
+ arch/mips/lantiq/xway/Makefile         |    3 +
+ arch/mips/lantiq/xway/mach-easy50601.c |   57 ++++++++++++++++++++++++++
+ arch/mips/lantiq/xway/mach-easy50712.c |   68 ++++++++++++++++++++++++++++++++
+ 6 files changed, 155 insertions(+), 0 deletions(-)
+ create mode 100644 arch/mips/lantiq/xway/Kconfig
+ create mode 100644 arch/mips/lantiq/xway/mach-easy50601.c
+ create mode 100644 arch/mips/lantiq/xway/mach-easy50712.c
+
+diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
+index 2780461..3fccf21 100644
+--- a/arch/mips/lantiq/Kconfig
++++ b/arch/mips/lantiq/Kconfig
+@@ -18,4 +18,6 @@ config SOC_XWAY
+ 	select HW_HAS_PCI
+ endchoice
+ 
++source "arch/mips/lantiq/xway/Kconfig"
++
+ endif
+diff --git a/arch/mips/lantiq/machtypes.h b/arch/mips/lantiq/machtypes.h
+index ffcacfc..7e01b8c 100644
+--- a/arch/mips/lantiq/machtypes.h
++++ b/arch/mips/lantiq/machtypes.h
+@@ -13,6 +13,8 @@
+ 
+ enum lantiq_mach_type {
+ 	LTQ_MACH_GENERIC = 0,
++	LTQ_MACH_EASY50712,	/* Danube evaluation board */
++	LTQ_MACH_EASY50601,	/* Amazon SE evaluation board */
+ };
+ 
+ #endif
+diff --git a/arch/mips/lantiq/xway/Kconfig b/arch/mips/lantiq/xway/Kconfig
+new file mode 100644
+index 0000000..2b857de
+--- /dev/null
++++ b/arch/mips/lantiq/xway/Kconfig
+@@ -0,0 +1,23 @@
++if SOC_XWAY
++
++menu "MIPS Machine"
++
++config LANTIQ_MACH_EASY50712
++	bool "Easy50712 - Danube"
++	default y
++
++endmenu
++
++endif
++
++if SOC_AMAZON_SE
++
++menu "MIPS Machine"
++
++config LANTIQ_MACH_EASY50601
++	bool "Easy50601 - Amazon SE"
++	default y
++
++endmenu
++
++endif
+diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
+index 8c06a97..b1d3640 100644
+--- a/arch/mips/lantiq/xway/Makefile
++++ b/arch/mips/lantiq/xway/Makefile
+@@ -2,3 +2,6 @@ obj-y := pmu.o ebu.o reset.o gpio.o devices.o
+ 
+ obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o
+ obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-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/mach-easy50601.c b/arch/mips/lantiq/xway/mach-easy50601.c
+new file mode 100644
+index 0000000..d5aaf63
+--- /dev/null
++++ b/arch/mips/lantiq/xway/mach-easy50601.c
+@@ -0,0 +1,57 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#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 <lantiq.h>
++
++#include "../machtypes.h"
++#include "devices.h"
++
++static struct mtd_partition easy50601_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 easy50601_flash_data = {
++	.nr_parts	= ARRAY_SIZE(easy50601_partitions),
++	.parts		= easy50601_partitions,
++};
++
++static void __init easy50601_init(void)
++{
++	ltq_register_nor(&easy50601_flash_data);
++}
++
++MIPS_MACHINE(LTQ_MACH_EASY50601,
++			"EASY50601",
++			"EASY50601 Eval Board",
++			easy50601_init);
+diff --git a/arch/mips/lantiq/xway/mach-easy50712.c b/arch/mips/lantiq/xway/mach-easy50712.c
+new file mode 100644
+index 0000000..e5e7e09
+--- /dev/null
++++ b/arch/mips/lantiq/xway/mach-easy50712.c
+@@ -0,0 +1,68 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#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 <lantiq_soc.h>
++#include <irq.h>
++
++#include "../machtypes.h"
++#include "devices.h"
++
++static struct mtd_partition easy50712_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 easy50712_flash_data = {
++	.nr_parts	= ARRAY_SIZE(easy50712_partitions),
++	.parts		= easy50712_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 void __init easy50712_init(void)
++{
++	ltq_register_gpio_stp();
++	ltq_register_nor(&easy50712_flash_data);
++	ltq_register_pci(&ltq_pci_data);
++}
++
++MIPS_MACHINE(LTQ_MACH_EASY50712,
++	     "EASY50712",
++	     "EASY50712 Eval Board",
++	      easy50712_init);
+-- 
+1.7.2.3
+

+ 330 - 0
target/linux/lantiq/patches-2.6.32/0008-MIPS-Lantiq-Add-more-gpio-drivers.patch

@@ -0,0 +1,330 @@
+From f9391211e47cdcc31f341d710efef4b3b46c333d Mon Sep 17 00:00:00 2001
+From: John Crispin <[email protected]>
+Date: Wed, 30 Mar 2011 09:27:56 +0200
+Subject: [PATCH 08/13] MIPS: Lantiq: Add more gpio drivers
+
+The XWAY family allows to extend the number of gpios by using shift registers or latches. This patch adds the 2 drivers needed for this. The extended gpios are output only.
+
+[[email protected]: Fixed ltq_stp_probe section() attributes.]
+
+Signed-off-by: John Crispin <[email protected]>
+Signed-off-by: Ralph Hempel <[email protected]>
+Cc: [email protected]
+Patchwork: https://patchwork.linux-mips.org/patch/2258/
+Signed-off-by: Ralf Baechle <[email protected]>
+---
+ arch/mips/lantiq/xway/Makefile   |    2 +-
+ arch/mips/lantiq/xway/gpio_ebu.c |  126 ++++++++++++++++++++++++++++++
+ arch/mips/lantiq/xway/gpio_stp.c |  157 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 284 insertions(+), 1 deletions(-)
+ create mode 100644 arch/mips/lantiq/xway/gpio_ebu.c
+ create mode 100644 arch/mips/lantiq/xway/gpio_stp.c
+
+diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
+index b1d3640..6b5e07e 100644
+--- a/arch/mips/lantiq/xway/Makefile
++++ b/arch/mips/lantiq/xway/Makefile
+@@ -1,4 +1,4 @@
+-obj-y := pmu.o ebu.o reset.o gpio.o devices.o
++obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o
+ 
+ obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o
+ obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o
+diff --git a/arch/mips/lantiq/xway/gpio_ebu.c b/arch/mips/lantiq/xway/gpio_ebu.c
+new file mode 100644
+index 0000000..a479355
+--- /dev/null
++++ b/arch/mips/lantiq/xway/gpio_ebu.c
+@@ -0,0 +1,126 @@
++/*
++ *  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 <[email protected]>
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/platform_device.h>
++#include <linux/mutex.h>
++#include <linux/gpio.h>
++#include <linux/io.h>
++
++#include <lantiq_soc.h>
++
++/*
++ * By attaching hardware latches to the EBU it is possible to create output
++ * only gpios. This driver configures a special memory address, which when
++ * written to outputs 16 bit to the latches.
++ */
++
++#define LTQ_EBU_BUSCON	0x1e7ff		/* 16 bit access, slowest timing */
++#define LTQ_EBU_WP	0x80000000	/* write protect bit */
++
++/* we keep a shadow value of the last value written to the ebu */
++static int ltq_ebu_gpio_shadow = 0x0;
++static void __iomem *ltq_ebu_gpio_membase;
++
++static void ltq_ebu_apply(void)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&ebu_lock, flags);
++	ltq_ebu_w32(LTQ_EBU_BUSCON, LTQ_EBU_BUSCON1);
++	*((__u16 *)ltq_ebu_gpio_membase) = ltq_ebu_gpio_shadow;
++	ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1);
++	spin_unlock_irqrestore(&ebu_lock, flags);
++}
++
++static void ltq_ebu_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++	if (value)
++		ltq_ebu_gpio_shadow |= (1 << offset);
++	else
++		ltq_ebu_gpio_shadow &= ~(1 << offset);
++	ltq_ebu_apply();
++}
++
++static int ltq_ebu_direction_output(struct gpio_chip *chip, unsigned offset,
++	int value)
++{
++	ltq_ebu_set(chip, offset, value);
++
++	return 0;
++}
++
++static struct gpio_chip ltq_ebu_chip = {
++	.label = "ltq_ebu",
++	.direction_output = ltq_ebu_direction_output,
++	.set = ltq_ebu_set,
++	.base = 72,
++	.ngpio = 16,
++	.can_sleep = 1,
++	.owner = THIS_MODULE,
++};
++
++static int ltq_ebu_probe(struct platform_device *pdev)
++{
++	int ret = 0;
++	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++
++	if (!res) {
++		dev_err(&pdev->dev, "failed to get memory resource\n");
++		return -ENOENT;
++	}
++
++	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 memory resource\n");
++		return -EBUSY;
++	}
++
++	ltq_ebu_gpio_membase = devm_ioremap_nocache(&pdev->dev, res->start,
++		resource_size(res));
++	if (!ltq_ebu_gpio_membase) {
++		dev_err(&pdev->dev, "Failed to ioremap mem region\n");
++		return -ENOMEM;
++	}
++
++	/* grab the default shadow value passed form the platform code */
++	ltq_ebu_gpio_shadow = (unsigned int) pdev->dev.platform_data;
++
++	/* tell the ebu controller which memory address we will be using */
++	ltq_ebu_w32(pdev->resource->start | 0x1, LTQ_EBU_ADDRSEL1);
++
++	/* write protect the region */
++	ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1);
++
++	ret = gpiochip_add(&ltq_ebu_chip);
++	if (!ret)
++		ltq_ebu_apply();
++	return ret;
++}
++
++static struct platform_driver ltq_ebu_driver = {
++	.probe = ltq_ebu_probe,
++	.driver = {
++		.name = "ltq_ebu",
++		.owner = THIS_MODULE,
++	},
++};
++
++static int __init ltq_ebu_init(void)
++{
++	int ret = platform_driver_register(&ltq_ebu_driver);
++
++	if (ret)
++		pr_info("ltq_ebu : Error registering platfom driver!");
++	return ret;
++}
++
++postcore_initcall(ltq_ebu_init);
+diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
+new file mode 100644
+index 0000000..67d59d6
+--- /dev/null
++++ b/arch/mips/lantiq/xway/gpio_stp.c
+@@ -0,0 +1,157 @@
++/*
++ *  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) 2007 John Crispin <[email protected]>
++ *
++ */
++
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/platform_device.h>
++#include <linux/mutex.h>
++#include <linux/io.h>
++#include <linux/gpio.h>
++
++#include <lantiq_soc.h>
++
++#define LTQ_STP_CON0		0x00
++#define LTQ_STP_CON1		0x04
++#define LTQ_STP_CPU0		0x08
++#define LTQ_STP_CPU1		0x0C
++#define LTQ_STP_AR		0x10
++
++#define LTQ_STP_CON_SWU		(1 << 31)
++#define LTQ_STP_2HZ		0
++#define LTQ_STP_4HZ		(1 << 23)
++#define LTQ_STP_8HZ		(2 << 23)
++#define LTQ_STP_10HZ		(3 << 23)
++#define LTQ_STP_SPEED_MASK	(0xf << 23)
++#define LTQ_STP_UPD_FPI		(1 << 31)
++#define LTQ_STP_UPD_MASK	(3 << 30)
++#define LTQ_STP_ADSL_SRC	(3 << 24)
++
++#define LTQ_STP_GROUP0		(1 << 0)
++
++#define LTQ_STP_RISING		0
++#define LTQ_STP_FALLING		(1 << 26)
++#define LTQ_STP_EDGE_MASK	(1 << 26)
++
++#define ltq_stp_r32(reg)	__raw_readl(ltq_stp_membase + reg)
++#define ltq_stp_w32(val, reg)	__raw_writel(val, ltq_stp_membase + reg)
++#define ltq_stp_w32_mask(clear, set, reg) \
++		ltq_w32((ltq_r32(ltq_stp_membase + reg) & ~(clear)) | (set), \
++		ltq_stp_membase + (reg))
++
++static int ltq_stp_shadow = 0xffff;
++static void __iomem *ltq_stp_membase;
++
++static void ltq_stp_set(struct gpio_chip *chip, unsigned offset, int value)
++{
++	if (value)
++		ltq_stp_shadow |= (1 << offset);
++	else
++		ltq_stp_shadow &= ~(1 << offset);
++	ltq_stp_w32(ltq_stp_shadow, LTQ_STP_CPU0);
++}
++
++static int ltq_stp_direction_output(struct gpio_chip *chip, unsigned offset,
++	int value)
++{
++	ltq_stp_set(chip, offset, value);
++
++	return 0;
++}
++
++static struct gpio_chip ltq_stp_chip = {
++	.label = "ltq_stp",
++	.direction_output = ltq_stp_direction_output,
++	.set = ltq_stp_set,
++	.base = 48,
++	.ngpio = 24,
++	.can_sleep = 1,
++	.owner = THIS_MODULE,
++};
++
++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");
++
++	/* sane defaults */
++	ltq_stp_w32(0, LTQ_STP_AR);
++	ltq_stp_w32(0, LTQ_STP_CPU0);
++	ltq_stp_w32(0, LTQ_STP_CPU1);
++	ltq_stp_w32(LTQ_STP_CON_SWU, LTQ_STP_CON0);
++	ltq_stp_w32(0, LTQ_STP_CON1);
++
++	/* rising or falling edge */
++	ltq_stp_w32_mask(LTQ_STP_EDGE_MASK, LTQ_STP_FALLING, LTQ_STP_CON0);
++
++	/* per default stp 15-0 are set */
++	ltq_stp_w32_mask(0, LTQ_STP_GROUP0, LTQ_STP_CON1);
++
++	/* stp are update periodically by the FPI bus */
++	ltq_stp_w32_mask(LTQ_STP_UPD_MASK, LTQ_STP_UPD_FPI, LTQ_STP_CON1);
++
++	/* set stp update speed */
++	ltq_stp_w32_mask(LTQ_STP_SPEED_MASK, LTQ_STP_8HZ, LTQ_STP_CON1);
++
++	/* tell the hardware that pin (led) 0 and 1 are controlled
++	 *  by the dsl arc
++	 */
++	ltq_stp_w32_mask(0, LTQ_STP_ADSL_SRC, LTQ_STP_CON0);
++
++	ltq_pmu_enable(PMU_LED);
++	return 0;
++}
++
++static int __devinit ltq_stp_probe(struct platform_device *pdev)
++{
++	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	int ret = 0;
++
++	if (!res)
++		return -ENOENT;
++	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 STP memory\n");
++		return -EBUSY;
++	}
++	ltq_stp_membase = devm_ioremap_nocache(&pdev->dev, res->start,
++		resource_size(res));
++	if (!ltq_stp_membase) {
++		dev_err(&pdev->dev, "failed to remap STP memory\n");
++		return -ENOMEM;
++	}
++	ret = gpiochip_add(&ltq_stp_chip);
++	if (!ret)
++		ret = ltq_stp_hw_init();
++
++	return ret;
++}
++
++static struct platform_driver ltq_stp_driver = {
++	.probe = ltq_stp_probe,
++	.driver = {
++		.name = "ltq_stp",
++		.owner = THIS_MODULE,
++	},
++};
++
++int __init ltq_stp_init(void)
++{
++	int ret = platform_driver_register(&ltq_stp_driver);
++
++	if (ret)
++		pr_info("ltq_stp: error registering platfom driver");
++	return ret;
++}
++
++postcore_initcall(ltq_stp_init);
+-- 
+1.7.2.3
+

+ 261 - 256
target/linux/lantiq/patches/200-serial.patch → target/linux/lantiq/patches-2.6.32/0009-SERIAL-Lantiq-Add-driver-for-MIPS-Lantiq-SOCs.patch

@@ -1,30 +1,27 @@
---- a/drivers/serial/Kconfig
-+++ b/drivers/serial/Kconfig
-@@ -1454,6 +1454,14 @@
- 	help
- 	  Support for Console on the NWP serial ports.
- 
-+config SERIAL_LANTIQ
-+	bool "Lantiq serial driver"
-+	depends on LANTIQ
-+	select SERIAL_CORE
-+	select SERIAL_CORE_CONSOLE
-+	help
-+	  Driver for the Lantiq SoC ASC hardware
-+
- config SERIAL_QE
- 	tristate "Freescale QUICC Engine serial port support"
- 	depends on QUICC_ENGINE
---- a/drivers/serial/Makefile
-+++ b/drivers/serial/Makefile
-@@ -89,3 +89,4 @@
- obj-$(CONFIG_SERIAL_MRST_MAX3110)	+= mrst_max3110.o
- obj-$(CONFIG_SERIAL_MFD_HSU)	+= mfd.o
- obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
-+obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o
+From 1d2b44b1afa3ef081cd817dbf947d48eb8f5d21a Mon Sep 17 00:00:00 2001
+From: John Crispin <[email protected]>
+Date: Tue, 5 Apr 2011 14:10:57 +0200
+Subject: [PATCH 09/13] SERIAL: Lantiq: Add driver for MIPS Lantiq SOCs.
+
+Signed-off-by: John Crispin <[email protected]>
+Signed-off-by: Ralph Hempel <[email protected]>
+Signed-off-by: Felix Fietkau <[email protected]>
+Cc: [email protected]
+Cc: [email protected]
+Cc: [email protected]
+Patchwork: https://patchwork.linux-mips.org/patch/2269/
+Acked-by: Alan Cox <[email protected]>
+Signed-off-by: Ralf Baechle <[email protected]>
+---
+ drivers/tty/serial/Kconfig  |    8 +
+ drivers/tty/serial/Makefile |    1 +
+ drivers/tty/serial/lantiq.c |  756 +++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 765 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/tty/serial/lantiq.c
+
 --- /dev/null
 +++ b/drivers/serial/lantiq.c
-@@ -0,0 +1,772 @@
+@@ -0,0 +1,756 @@
 +/*
 + *  Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
 + *
@@ -44,7 +41,7 @@
 + * Copyright (C) 2004 Infineon IFAP DC COM CPE
 + * Copyright (C) 2007 Felix Fietkau <[email protected]>
 + * Copyright (C) 2007 John Crispin <[email protected]>
-+ * Copyright (C) 2010 Thomas Langer, Lantiq Deutschland
++ * Copyright (C) 2010 Thomas Langer, <[email protected]>
 + */
 +
 +#include <linux/slab.h>
@@ -62,112 +59,95 @@
 +#include <linux/io.h>
 +#include <linux/clk.h>
 +
-+#define lq_r32(reg)			__raw_readl(reg)
-+#define lq_r8(reg)				__raw_readb(reg)
-+#define lq_w32(val, reg)			__raw_writel(val, reg)
-+#define lq_w8(val, reg)			__raw_writeb(val, reg)
-+#define lq_w32_mask(clear, set, reg)	lq_w32((lq_r32(reg) & ~(clear)) | (set), reg)
++#include <lantiq_soc.h>
 +
-+#define PORT_IFXMIPSASC		111
++#define PORT_LTQ_ASC		111
 +#define MAXPORTS		2
-+
-+#define UART_DUMMY_UER_RX 1
-+
-+#define DRVNAME "lq_asc"
-+
++#define UART_DUMMY_UER_RX	1
++#define DRVNAME			"ltq_asc"
 +#ifdef __BIG_ENDIAN
-+#define IFXMIPS_ASC_TBUF		(0x0020 + 3)
-+#define IFXMIPS_ASC_RBUF		(0x0024 + 3)
++#define LTQ_ASC_TBUF		(0x0020 + 3)
++#define LTQ_ASC_RBUF		(0x0024 + 3)
 +#else
-+#define IFXMIPS_ASC_TBUF		0x0020
-+#define IFXMIPS_ASC_RBUF		0x0024
++#define LTQ_ASC_TBUF		0x0020
++#define LTQ_ASC_RBUF		0x0024
 +#endif
-+
-+#define IFXMIPS_ASC_FSTAT		0x0048
-+#define IFXMIPS_ASC_WHBSTATE		0x0018
-+#define IFXMIPS_ASC_STATE		0x0014
-+#define IFXMIPS_ASC_IRNCR		0x00F8
-+#define IFXMIPS_ASC_CLC			0x0000
-+#define IFXMIPS_ASC_ID			0x0008
-+#define IFXMIPS_ASC_PISEL		0x0004
-+#define IFXMIPS_ASC_TXFCON		0x0044
-+#define IFXMIPS_ASC_RXFCON		0x0040
-+#define IFXMIPS_ASC_CON			0x0010
-+#define IFXMIPS_ASC_BG			0x0050
-+#define IFXMIPS_ASC_IRNREN		0x00F4
-+
-+#define ASC_IRNREN_TX			0x1
-+#define ASC_IRNREN_RX			0x2
-+#define ASC_IRNREN_ERR			0x4
-+#define ASC_IRNREN_TX_BUF		0x8
-+#define ASC_IRNCR_TIR			0x1
-+#define ASC_IRNCR_RIR			0x2
-+#define ASC_IRNCR_EIR			0x4
-+
-+#define ASCOPT_CSIZE			0x3
-+#define ASCOPT_CS7			0x1
-+#define ASCOPT_CS8			0x2
-+#define ASCOPT_PARENB			0x4
-+#define ASCOPT_STOPB			0x8
-+#define ASCOPT_PARODD			0x0
-+#define ASCOPT_CREAD			0x20
-+#define TXFIFO_FL			1
-+#define RXFIFO_FL			1
-+#define ASCCLC_DISS			0x2
-+#define ASCCLC_RMCMASK			0x0000FF00
-+#define ASCCLC_RMCOFFSET		8
-+#define ASCCON_M_8ASYNC			0x0
-+#define ASCCON_M_7ASYNC			0x2
-+#define ASCCON_ODD			0x00000020
-+#define ASCCON_STP			0x00000080
-+#define ASCCON_BRS			0x00000100
-+#define ASCCON_FDE			0x00000200
-+#define ASCCON_R			0x00008000
-+#define ASCCON_FEN			0x00020000
-+#define ASCCON_ROEN			0x00080000
-+#define ASCCON_TOEN			0x00100000
-+#define ASCSTATE_PE			0x00010000
-+#define ASCSTATE_FE			0x00020000
-+#define ASCSTATE_ROE			0x00080000
-+#define ASCSTATE_ANY			(ASCSTATE_ROE|ASCSTATE_PE|ASCSTATE_FE)
-+#define ASCWHBSTATE_CLRREN		0x00000001
-+#define ASCWHBSTATE_SETREN		0x00000002
-+#define ASCWHBSTATE_CLRPE		0x00000004
-+#define ASCWHBSTATE_CLRFE		0x00000008
-+#define ASCWHBSTATE_CLRROE		0x00000020
-+#define ASCTXFCON_TXFEN			0x0001
-+#define ASCTXFCON_TXFFLU		0x0002
-+#define ASCTXFCON_TXFITLMASK		0x3F00
-+#define ASCTXFCON_TXFITLOFF		8
-+#define ASCRXFCON_RXFEN			0x0001
-+#define ASCRXFCON_RXFFLU		0x0002
-+#define ASCRXFCON_RXFITLMASK		0x3F00
-+#define ASCRXFCON_RXFITLOFF		8
-+#define ASCFSTAT_RXFFLMASK		0x003F
-+#define ASCFSTAT_TXFFLMASK		0x3F00
-+#define ASCFSTAT_TXFFLOFF		8
-+#define ASCFSTAT_RXFREEMASK		0x003F0000
-+#define ASCFSTAT_RXFREEOFF		16
-+#define ASCFSTAT_TXFREEMASK		0x3F000000
-+#define ASCFSTAT_TXFREEOFF		24
++#define LTQ_ASC_FSTAT		0x0048
++#define LTQ_ASC_WHBSTATE	0x0018
++#define LTQ_ASC_STATE		0x0014
++#define LTQ_ASC_IRNCR		0x00F8
++#define LTQ_ASC_CLC		0x0000
++#define LTQ_ASC_ID		0x0008
++#define LTQ_ASC_PISEL		0x0004
++#define LTQ_ASC_TXFCON		0x0044
++#define LTQ_ASC_RXFCON		0x0040
++#define LTQ_ASC_CON		0x0010
++#define LTQ_ASC_BG		0x0050
++#define LTQ_ASC_IRNREN		0x00F4
++
++#define ASC_IRNREN_TX		0x1
++#define ASC_IRNREN_RX		0x2
++#define ASC_IRNREN_ERR		0x4
++#define ASC_IRNREN_TX_BUF	0x8
++#define ASC_IRNCR_TIR		0x1
++#define ASC_IRNCR_RIR		0x2
++#define ASC_IRNCR_EIR		0x4
++
++#define ASCOPT_CSIZE		0x3
++#define TXFIFO_FL		1
++#define RXFIFO_FL		1
++#define ASCCLC_DISS		0x2
++#define ASCCLC_RMCMASK		0x0000FF00
++#define ASCCLC_RMCOFFSET	8
++#define ASCCON_M_8ASYNC		0x0
++#define ASCCON_M_7ASYNC		0x2
++#define ASCCON_ODD		0x00000020
++#define ASCCON_STP		0x00000080
++#define ASCCON_BRS		0x00000100
++#define ASCCON_FDE		0x00000200
++#define ASCCON_R		0x00008000
++#define ASCCON_FEN		0x00020000
++#define ASCCON_ROEN		0x00080000
++#define ASCCON_TOEN		0x00100000
++#define ASCSTATE_PE		0x00010000
++#define ASCSTATE_FE		0x00020000
++#define ASCSTATE_ROE		0x00080000
++#define ASCSTATE_ANY		(ASCSTATE_ROE|ASCSTATE_PE|ASCSTATE_FE)
++#define ASCWHBSTATE_CLRREN	0x00000001
++#define ASCWHBSTATE_SETREN	0x00000002
++#define ASCWHBSTATE_CLRPE	0x00000004
++#define ASCWHBSTATE_CLRFE	0x00000008
++#define ASCWHBSTATE_CLRROE	0x00000020
++#define ASCTXFCON_TXFEN		0x0001
++#define ASCTXFCON_TXFFLU	0x0002
++#define ASCTXFCON_TXFITLMASK	0x3F00
++#define ASCTXFCON_TXFITLOFF	8
++#define ASCRXFCON_RXFEN		0x0001
++#define ASCRXFCON_RXFFLU	0x0002
++#define ASCRXFCON_RXFITLMASK	0x3F00
++#define ASCRXFCON_RXFITLOFF	8
++#define ASCFSTAT_RXFFLMASK	0x003F
++#define ASCFSTAT_TXFFLMASK	0x3F00
++#define ASCFSTAT_TXFREEMASK	0x3F000000
++#define ASCFSTAT_TXFREEOFF	24
 +
 +static void lqasc_tx_chars(struct uart_port *port);
-+extern void prom_printf(const char *fmt, ...);
-+static struct lq_uart_port *lqasc_port[2];
++static struct ltq_uart_port *lqasc_port[MAXPORTS];
 +static struct uart_driver lqasc_reg;
++static DEFINE_SPINLOCK(ltq_asc_lock);
 +
-+struct lq_uart_port {
++struct ltq_uart_port {
 +	struct uart_port	port;
-+	struct clk			*clk;
++	struct clk		*clk;
 +	unsigned int		tx_irq;
 +	unsigned int		rx_irq;
 +	unsigned int		err_irq;
 +};
 +
 +static inline struct
-+lq_uart_port *to_lq_uart_port(struct uart_port *port)
++ltq_uart_port *to_ltq_uart_port(struct uart_port *port)
 +{
-+	return container_of(port, struct lq_uart_port, port);
++	return container_of(port, struct ltq_uart_port, port);
 +}
 +
 +static void
@@ -180,16 +160,16 @@
 +lqasc_start_tx(struct uart_port *port)
 +{
 +	unsigned long flags;
-+	local_irq_save(flags);
++	spin_lock_irqsave(&ltq_asc_lock, flags);
 +	lqasc_tx_chars(port);
-+	local_irq_restore(flags);
++	spin_unlock_irqrestore(&ltq_asc_lock, flags);
 +	return;
 +}
 +
 +static void
 +lqasc_stop_rx(struct uart_port *port)
 +{
-+	lq_w32(ASCWHBSTATE_CLRREN, port->membase + IFXMIPS_ASC_WHBSTATE);
++	ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
 +}
 +
 +static void
@@ -197,17 +177,22 @@
 +{
 +}
 +
-+static void
++static int
 +lqasc_rx_chars(struct uart_port *port)
 +{
-+	struct tty_struct *tty = port->state->port.tty;
++	struct tty_struct *tty = tty_port_tty_get(&port->state->port);
 +	unsigned int ch = 0, rsr = 0, fifocnt;
 +
-+	fifocnt = lq_r32(port->membase + IFXMIPS_ASC_FSTAT) & ASCFSTAT_RXFFLMASK;
++	if (!tty) {
++		dev_dbg(port->dev, "%s:tty is busy now", __func__);
++		return -EBUSY;
++	}
++	fifocnt =
++		ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_RXFFLMASK;
 +	while (fifocnt--) {
 +		u8 flag = TTY_NORMAL;
-+		ch = lq_r8(port->membase + IFXMIPS_ASC_RBUF);
-+		rsr = (lq_r32(port->membase + IFXMIPS_ASC_STATE)
++		ch = ltq_r8(port->membase + LTQ_ASC_RBUF);
++		rsr = (ltq_r32(port->membase + LTQ_ASC_STATE)
 +			& ASCSTATE_ANY) | UART_DUMMY_UER_RX;
 +		tty_flip_buffer_push(tty);
 +		port->icount.rx++;
@@ -219,17 +204,17 @@
 +		if (rsr & ASCSTATE_ANY) {
 +			if (rsr & ASCSTATE_PE) {
 +				port->icount.parity++;
-+				lq_w32_mask(0, ASCWHBSTATE_CLRPE,
-+					port->membase + IFXMIPS_ASC_WHBSTATE);
++				ltq_w32_mask(0, ASCWHBSTATE_CLRPE,
++					port->membase + LTQ_ASC_WHBSTATE);
 +			} else if (rsr & ASCSTATE_FE) {
 +				port->icount.frame++;
-+				lq_w32_mask(0, ASCWHBSTATE_CLRFE,
-+					port->membase + IFXMIPS_ASC_WHBSTATE);
++				ltq_w32_mask(0, ASCWHBSTATE_CLRFE,
++					port->membase + LTQ_ASC_WHBSTATE);
 +			}
 +			if (rsr & ASCSTATE_ROE) {
 +				port->icount.overrun++;
-+				lq_w32_mask(0, ASCWHBSTATE_CLRROE,
-+					port->membase + IFXMIPS_ASC_WHBSTATE);
++				ltq_w32_mask(0, ASCWHBSTATE_CLRROE,
++					port->membase + LTQ_ASC_WHBSTATE);
 +			}
 +
 +			rsr &= port->read_status_mask;
@@ -253,7 +238,8 @@
 +	}
 +	if (ch != 0)
 +		tty_flip_buffer_push(tty);
-+	return;
++	tty_kref_put(tty);
++	return 0;
 +}
 +
 +static void
@@ -265,10 +251,10 @@
 +		return;
 +	}
 +
-+	while (((lq_r32(port->membase + IFXMIPS_ASC_FSTAT) &
++	while (((ltq_r32(port->membase + LTQ_ASC_FSTAT) &
 +		ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) {
 +		if (port->x_char) {
-+			lq_w8(port->x_char, port->membase + IFXMIPS_ASC_TBUF);
++			ltq_w8(port->x_char, port->membase + LTQ_ASC_TBUF);
 +			port->icount.tx++;
 +			port->x_char = 0;
 +			continue;
@@ -277,8 +263,8 @@
 +		if (uart_circ_empty(xmit))
 +			break;
 +
-+		lq_w8(port->state->xmit.buf[port->state->xmit.tail],
-+			port->membase + IFXMIPS_ASC_TBUF);
++		ltq_w8(port->state->xmit.buf[port->state->xmit.tail],
++			port->membase + LTQ_ASC_TBUF);
 +		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
 +		port->icount.tx++;
 +	}
@@ -290,8 +276,11 @@
 +static irqreturn_t
 +lqasc_tx_int(int irq, void *_port)
 +{
++	unsigned long flags;
 +	struct uart_port *port = (struct uart_port *)_port;
-+	lq_w32(ASC_IRNCR_TIR, port->membase + IFXMIPS_ASC_IRNCR);
++	spin_lock_irqsave(&ltq_asc_lock, flags);
++	ltq_w32(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
++	spin_unlock_irqrestore(&ltq_asc_lock, flags);
 +	lqasc_start_tx(port);
 +	return IRQ_HANDLED;
 +}
@@ -299,19 +288,25 @@
 +static irqreturn_t
 +lqasc_err_int(int irq, void *_port)
 +{
++	unsigned long flags;
 +	struct uart_port *port = (struct uart_port *)_port;
++	spin_lock_irqsave(&ltq_asc_lock, flags);
 +	/* clear any pending interrupts */
-+	lq_w32_mask(0, ASCWHBSTATE_CLRPE | ASCWHBSTATE_CLRFE | ASCWHBSTATE_CLRROE,
-+		port->membase + IFXMIPS_ASC_WHBSTATE);
++	ltq_w32_mask(0, ASCWHBSTATE_CLRPE | ASCWHBSTATE_CLRFE |
++		ASCWHBSTATE_CLRROE, port->membase + LTQ_ASC_WHBSTATE);
++	spin_unlock_irqrestore(&ltq_asc_lock, flags);
 +	return IRQ_HANDLED;
 +}
 +
 +static irqreturn_t
 +lqasc_rx_int(int irq, void *_port)
 +{
++	unsigned long flags;
 +	struct uart_port *port = (struct uart_port *)_port;
-+	lq_w32(ASC_IRNCR_RIR, port->membase + IFXMIPS_ASC_IRNCR);
++	spin_lock_irqsave(&ltq_asc_lock, flags);
++	ltq_w32(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
 +	lqasc_rx_chars(port);
++	spin_unlock_irqrestore(&ltq_asc_lock, flags);
 +	return IRQ_HANDLED;
 +}
 +
@@ -319,7 +314,7 @@
 +lqasc_tx_empty(struct uart_port *port)
 +{
 +	int status;
-+	status = lq_r32(port->membase + IFXMIPS_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
++	status = ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
 +	return status ? 0 : TIOCSER_TEMT;
 +}
 +
@@ -342,73 +337,75 @@
 +static int
 +lqasc_startup(struct uart_port *port)
 +{
-+	struct lq_uart_port *ifx_port = to_lq_uart_port(port);
++	struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
 +	int retval;
 +
-+	port->uartclk = clk_get_rate(ifx_port->clk);
++	port->uartclk = clk_get_rate(ltq_port->clk);
 +
-+	lq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
-+		port->membase + IFXMIPS_ASC_CLC);
++	ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
++		port->membase + LTQ_ASC_CLC);
 +
-+	lq_w32(0, port->membase + IFXMIPS_ASC_PISEL);
-+	lq_w32(
++	ltq_w32(0, port->membase + LTQ_ASC_PISEL);
++	ltq_w32(
 +		((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) |
 +		ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU,
-+		port->membase + IFXMIPS_ASC_TXFCON);
-+	lq_w32(
++		port->membase + LTQ_ASC_TXFCON);
++	ltq_w32(
 +		((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK)
 +		| ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU,
-+		port->membase + IFXMIPS_ASC_RXFCON);
-+	/* make sure other settings are written to hardware before setting enable bits */
++		port->membase + LTQ_ASC_RXFCON);
++	/* make sure other settings are written to hardware before
++	 * setting enable bits
++	 */
 +	wmb();
-+	lq_w32_mask(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN |
-+		ASCCON_ROEN, port->membase + IFXMIPS_ASC_CON);
++	ltq_w32_mask(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN |
++		ASCCON_ROEN, port->membase + LTQ_ASC_CON);
 +
-+	retval = request_irq(ifx_port->tx_irq, lqasc_tx_int,
++	retval = request_irq(ltq_port->tx_irq, lqasc_tx_int,
 +		IRQF_DISABLED, "asc_tx", port);
 +	if (retval) {
 +		pr_err("failed to request lqasc_tx_int\n");
 +		return retval;
 +	}
 +
-+	retval = request_irq(ifx_port->rx_irq, lqasc_rx_int,
++	retval = request_irq(ltq_port->rx_irq, lqasc_rx_int,
 +		IRQF_DISABLED, "asc_rx", port);
 +	if (retval) {
 +		pr_err("failed to request lqasc_rx_int\n");
 +		goto err1;
 +	}
 +
-+	retval = request_irq(ifx_port->err_irq, lqasc_err_int,
++	retval = request_irq(ltq_port->err_irq, lqasc_err_int,
 +		IRQF_DISABLED, "asc_err", port);
 +	if (retval) {
 +		pr_err("failed to request lqasc_err_int\n");
 +		goto err2;
 +	}
 +
-+	lq_w32(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
-+		port->membase + IFXMIPS_ASC_IRNREN);
++	ltq_w32(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
++		port->membase + LTQ_ASC_IRNREN);
 +	return 0;
 +
 +err2:
-+	free_irq(ifx_port->rx_irq, port);
++	free_irq(ltq_port->rx_irq, port);
 +err1:
-+	free_irq(ifx_port->tx_irq, port);
++	free_irq(ltq_port->tx_irq, port);
 +	return retval;
 +}
 +
 +static void
 +lqasc_shutdown(struct uart_port *port)
 +{
-+	struct lq_uart_port *ifx_port = to_lq_uart_port(port);
-+	free_irq(ifx_port->tx_irq, port);
-+	free_irq(ifx_port->rx_irq, port);
-+	free_irq(ifx_port->err_irq, port);
-+
-+	lq_w32(0, port->membase + IFXMIPS_ASC_CON);
-+	lq_w32_mask(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU,
-+		port->membase + IFXMIPS_ASC_RXFCON);
-+	lq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
-+		port->membase + IFXMIPS_ASC_TXFCON);
++	struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
++	free_irq(ltq_port->tx_irq, port);
++	free_irq(ltq_port->rx_irq, port);
++	free_irq(ltq_port->err_irq, port);
++
++	ltq_w32(0, port->membase + LTQ_ASC_CON);
++	ltq_w32_mask(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU,
++		port->membase + LTQ_ASC_RXFCON);
++	ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
++		port->membase + LTQ_ASC_TXFCON);
 +}
 +
 +static void
@@ -417,7 +414,7 @@
 +{
 +	unsigned int cflag;
 +	unsigned int iflag;
-+	unsigned int quot;
++	unsigned int divisor;
 +	unsigned int baud;
 +	unsigned int con = 0;
 +	unsigned long flags;
@@ -433,10 +430,14 @@
 +	case CS5:
 +	case CS6:
 +	default:
++		new->c_cflag &= ~ CSIZE;
++		new->c_cflag |= CS8;
 +		con = ASCCON_M_8ASYNC;
 +		break;
 +	}
 +
++	cflag &= ~CMSPAR; /* Mark/Space parity is not supported */
++
 +	if (cflag & CSTOPB)
 +		con |= ASCCON_STP;
 +
@@ -470,41 +471,45 @@
 +	/* set error signals  - framing, parity  and overrun, enable receiver */
 +	con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN;
 +
-+	local_irq_save(flags);
++	spin_lock_irqsave(&ltq_asc_lock, flags);
 +
 +	/* set up CON */
-+	lq_w32_mask(0, con, port->membase + IFXMIPS_ASC_CON);
++	ltq_w32_mask(0, con, port->membase + LTQ_ASC_CON);
 +
 +	/* Set baud rate - take a divider of 2 into account */
 +	baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
-+	quot = uart_get_divisor(port, baud);
-+	quot = quot / 2 - 1;
++	divisor = uart_get_divisor(port, baud);
++	divisor = divisor / 2 - 1;
 +
 +	/* disable the baudrate generator */
-+	lq_w32_mask(ASCCON_R, 0, port->membase + IFXMIPS_ASC_CON);
++	ltq_w32_mask(ASCCON_R, 0, port->membase + LTQ_ASC_CON);
 +
 +	/* make sure the fractional divider is off */
-+	lq_w32_mask(ASCCON_FDE, 0, port->membase + IFXMIPS_ASC_CON);
++	ltq_w32_mask(ASCCON_FDE, 0, port->membase + LTQ_ASC_CON);
 +
 +	/* set up to use divisor of 2 */
-+	lq_w32_mask(ASCCON_BRS, 0, port->membase + IFXMIPS_ASC_CON);
++	ltq_w32_mask(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON);
 +
 +	/* now we can write the new baudrate into the register */
-+	lq_w32(quot, port->membase + IFXMIPS_ASC_BG);
++	ltq_w32(divisor, port->membase + LTQ_ASC_BG);
 +
 +	/* turn the baudrate generator back on */
-+	lq_w32_mask(0, ASCCON_R, port->membase + IFXMIPS_ASC_CON);
++	ltq_w32_mask(0, ASCCON_R, port->membase + LTQ_ASC_CON);
 +
 +	/* enable rx */
-+	lq_w32(ASCWHBSTATE_SETREN, port->membase + IFXMIPS_ASC_WHBSTATE);
++	ltq_w32(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
++
++	spin_unlock_irqrestore(&ltq_asc_lock, flags);
 +
-+	local_irq_restore(flags);
++	/* Don't rewrite B0 */
++        if (tty_termios_baud_rate(new))
++		tty_termios_encode_baud_rate(new, baud, baud);
 +}
 +
 +static const char*
 +lqasc_type(struct uart_port *port)
 +{
-+	if (port->type == PORT_IFXMIPSASC)
++	if (port->type == PORT_LTQ_ASC)
 +		return DRVNAME;
 +	else
 +		return NULL;
@@ -523,16 +528,26 @@
 +lqasc_request_port(struct uart_port *port)
 +{
 +	struct platform_device *pdev = to_platform_device(port->dev);
-+	struct resource *mmres;
++	struct resource *res;
 +	int size;
 +
-+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+	if (!mmres)
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!res) {
++		dev_err(&pdev->dev, "cannot obtain I/O memory region");
 +		return -ENODEV;
-+	size = resource_size(mmres);
++	}
++	size = resource_size(res);
++
++	res = devm_request_mem_region(&pdev->dev, res->start,
++		size, dev_name(&pdev->dev));
++	if (!res) {
++		dev_err(&pdev->dev, "cannot request I/O memory region");
++		return -EBUSY;
++	}
 +
 +	if (port->flags & UPF_IOREMAP) {
-+		port->membase = ioremap_nocache(port->mapbase, size);
++		port->membase = devm_ioremap_nocache(&pdev->dev,
++			port->mapbase, size);
 +		if (port->membase == NULL)
 +			return -ENOMEM;
 +	}
@@ -543,7 +558,7 @@
 +lqasc_config_port(struct uart_port *port, int flags)
 +{
 +	if (flags & UART_CONFIG_TYPE) {
-+		port->type = PORT_IFXMIPSASC;
++		port->type = PORT_LTQ_ASC;
 +		lqasc_request_port(port);
 +	}
 +}
@@ -553,7 +568,7 @@
 +	struct serial_struct *ser)
 +{
 +	int ret = 0;
-+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_IFXMIPSASC)
++	if (ser->type != PORT_UNKNOWN && ser->type != PORT_LTQ_ASC)
 +		ret = -EINVAL;
 +	if (ser->irq < 0 || ser->irq >= NR_IRQS)
 +		ret = -EINVAL;
@@ -590,38 +605,38 @@
 +		return;
 +
 +	do {
-+		fifofree = (lq_r32(port->membase + IFXMIPS_ASC_FSTAT)
++		fifofree = (ltq_r32(port->membase + LTQ_ASC_FSTAT)
 +			& ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
 +	} while (fifofree == 0);
-+	lq_w8(ch, port->membase + IFXMIPS_ASC_TBUF);
++	ltq_w8(ch, port->membase + LTQ_ASC_TBUF);
 +}
 +
 +
 +static void
 +lqasc_console_write(struct console *co, const char *s, u_int count)
 +{
-+	struct lq_uart_port *ifx_port;
++	struct ltq_uart_port *ltq_port;
 +	struct uart_port *port;
 +	unsigned long flags;
 +
 +	if (co->index >= MAXPORTS)
 +		return;
 +
-+	ifx_port = lqasc_port[co->index];
-+	if (!ifx_port)
++	ltq_port = lqasc_port[co->index];
++	if (!ltq_port)
 +		return;
 +
-+	port = &ifx_port->port;
++	port = &ltq_port->port;
 +
-+	local_irq_save(flags);
++	spin_lock_irqsave(&ltq_asc_lock, flags);
 +	uart_console_write(port, s, count, lqasc_console_putchar);
-+	local_irq_restore(flags);
++	spin_unlock_irqrestore(&ltq_asc_lock, flags);
 +}
 +
 +static int __init
 +lqasc_console_setup(struct console *co, char *options)
 +{
-+	struct lq_uart_port *ifx_port;
++	struct ltq_uart_port *ltq_port;
 +	struct uart_port *port;
 +	int baud = 115200;
 +	int bits = 8;
@@ -631,13 +646,13 @@
 +	if (co->index >= MAXPORTS)
 +		return -ENODEV;
 +
-+	ifx_port = lqasc_port[co->index];
-+	if (!ifx_port)
++	ltq_port = lqasc_port[co->index];
++	if (!ltq_port)
 +		return -ENODEV;
 +
-+	port = &ifx_port->port;
++	port = &ltq_port->port;
 +
-+	port->uartclk = clk_get_rate(ifx_port->clk);
++	port->uartclk = clk_get_rate(ltq_port->clk);
 +
 +	if (options)
 +		uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -645,7 +660,7 @@
 +}
 +
 +static struct console lqasc_console = {
-+	.name =		"ttyS",
++	.name =		"ttyLTQ",
 +	.write =	lqasc_console_write,
 +	.device =	uart_console_device,
 +	.setup =	lqasc_console_setup,
@@ -665,17 +680,17 @@
 +static struct uart_driver lqasc_reg = {
 +	.owner =	THIS_MODULE,
 +	.driver_name =	DRVNAME,
-+	.dev_name =	"ttyS",
-+	.major =	TTY_MAJOR,
-+	.minor =	64,
++	.dev_name =	"ttyLTQ",
++	.major =	0,
++	.minor =	0,
 +	.nr =		MAXPORTS,
 +	.cons =		&lqasc_console,
 +};
 +
-+static int __devinit
++static int __init
 +lqasc_probe(struct platform_device *pdev)
 +{
-+	struct lq_uart_port *ifx_port;
++	struct ltq_uart_port *ltq_port;
 +	struct uart_port *port;
 +	struct resource *mmres, *irqres;
 +	int tx_irq, rx_irq, err_irq;
@@ -700,69 +715,43 @@
 +	}
 +
 +	tx_irq = platform_get_irq_byname(pdev, "tx");
-+	if (tx_irq < 0) {
-+		/* without named resources: assume standard irq scheme */
-+		tx_irq = irqres->start;
-+		rx_irq = irqres->start+2;
-+		err_irq = irqres->start+3;
-+	} else {
-+		/* other irqs must be named also! */
-+		rx_irq = platform_get_irq_byname(pdev, "rx");
-+		err_irq = platform_get_irq_byname(pdev, "err");
-+		if ((rx_irq < 0) | (err_irq < 0))
-+			return -ENODEV;
-+	}
++	rx_irq = platform_get_irq_byname(pdev, "rx");
++	err_irq = platform_get_irq_byname(pdev, "err");
++	if ((tx_irq < 0) | (rx_irq < 0) | (err_irq < 0))
++		return -ENODEV;
 +
-+	ifx_port = kzalloc(sizeof(struct lq_uart_port), GFP_KERNEL);
-+	if (!ifx_port)
++	ltq_port = kzalloc(sizeof(struct ltq_uart_port), GFP_KERNEL);
++	if (!ltq_port)
 +		return -ENOMEM;
 +
-+	port = &ifx_port->port;
++	port = &ltq_port->port;
 +
 +	port->iotype	= SERIAL_IO_MEM;
 +	port->flags	= ASYNC_BOOT_AUTOCONF | UPF_IOREMAP;
 +	port->ops	= &lqasc_pops;
 +	port->fifosize	= 16;
-+	port->type	= PORT_IFXMIPSASC,
++	port->type	= PORT_LTQ_ASC,
 +	port->line	= pdev->id;
 +	port->dev	= &pdev->dev;
 +
 +	port->irq	= tx_irq; /* unused, just to be backward-compatibe */
 +	port->mapbase	= mmres->start;
 +
-+	ifx_port->clk	= clk;
++	ltq_port->clk	= clk;
 +
-+	ifx_port->tx_irq = tx_irq;
-+	ifx_port->rx_irq = rx_irq;
-+	ifx_port->err_irq = err_irq;
++	ltq_port->tx_irq = tx_irq;
++	ltq_port->rx_irq = rx_irq;
++	ltq_port->err_irq = err_irq;
 +
-+	lqasc_port[pdev->id] = ifx_port;
-+	platform_set_drvdata(pdev, ifx_port);
++	lqasc_port[pdev->id] = ltq_port;
++	platform_set_drvdata(pdev, ltq_port);
 +
 +	ret = uart_add_one_port(&lqasc_reg, port);
 +
 +	return ret;
 +}
 +
-+static int __devexit
-+lqasc_remove(struct platform_device *pdev)
-+{
-+	struct lq_uart_port *ifx_port = platform_get_drvdata(pdev);
-+	int ret;
-+
-+	clk_put(ifx_port->clk);
-+	platform_set_drvdata(pdev, NULL);
-+	lqasc_port[pdev->id] = NULL;
-+	ret = uart_remove_one_port(&lqasc_reg, &ifx_port->port);
-+	kfree(ifx_port);
-+
-+	return 0;
-+}
-+
 +static struct platform_driver lqasc_driver = {
-+	.probe		= lqasc_probe,
-+	.remove		= __devexit_p(lqasc_remove),
-+
 +	.driver		= {
 +		.name	= DRVNAME,
 +		.owner	= THIS_MODULE,
@@ -778,22 +767,38 @@
 +	if (ret != 0)
 +		return ret;
 +
-+	ret = platform_driver_register(&lqasc_driver);
++	ret = platform_driver_probe(&lqasc_driver, lqasc_probe);
 +	if (ret != 0)
 +		uart_unregister_driver(&lqasc_reg);
 +
 +	return ret;
 +}
 +
-+void __exit
-+exit_lqasc(void)
-+{
-+	platform_driver_unregister(&lqasc_driver);
-+	uart_unregister_driver(&lqasc_reg);
-+}
-+
 +module_init(init_lqasc);
-+module_exit(exit_lqasc);
 +
 +MODULE_DESCRIPTION("Lantiq serial port driver");
 +MODULE_LICENSE("GPL");
+--- a/drivers/serial/Kconfig
++++ b/drivers/serial/Kconfig
+@@ -1383,6 +1383,14 @@
+ 	help
+ 	  Support for Console on the NWP serial ports.
+ 
++config SERIAL_LANTIQ
++	bool "Lantiq serial driver"
++	depends on LANTIQ
++	select SERIAL_CORE
++	select SERIAL_CORE_CONSOLE
++	help
++	  Support for console and UART on Lantiq SoCs.
++
+ config SERIAL_QE
+ 	tristate "Freescale QUICC Engine serial port support"
+ 	depends on QUICC_ENGINE
+--- a/drivers/serial/Makefile
++++ b/drivers/serial/Makefile
+@@ -81,3 +81,4 @@
+ obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
+ obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
+ obj-$(CONFIG_SERIAL_TIMBERDALE)	+= timbuart.o
++obj-$(CONFIG_SERIAL_LANTIQ)	+= lantiq.o

+ 387 - 0
target/linux/lantiq/patches-2.6.32/0010-MIPS-Lantiq-Add-DMA-support.patch

@@ -0,0 +1,387 @@
+From bd620ec1ca053bab8ce2562968700e6f80e4ff83 Mon Sep 17 00:00:00 2001
+From: John Crispin <[email protected]>
+Date: Fri, 6 May 2011 00:10:00 +0200
+Subject: [PATCH 10/13] MIPS: Lantiq: Add DMA support
+
+This patch adds support for the DMA engine found inside the XWAY family of
+SoCs. The engine has 5 ports and 20 channels.
+
+Signed-off-by: John Crispin <[email protected]>
+Signed-off-by: Ralph Hempel <[email protected]>
+Cc: [email protected]
+Patchwork: https://patchwork.linux-mips.org/patch/2355/
+Signed-off-by: Ralf Baechle <[email protected]>
+---
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |    3 +-
+ arch/mips/include/asm/mach-lantiq/xway/xway_dma.h  |   60 +++++
+ arch/mips/lantiq/xway/Makefile                     |    2 +-
+ arch/mips/lantiq/xway/devices.h                    |    1 +
+ arch/mips/lantiq/xway/dma.c                        |  253 ++++++++++++++++++++
+ 5 files changed, 317 insertions(+), 2 deletions(-)
+ create mode 100644 arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
+ create mode 100644 arch/mips/lantiq/xway/dma.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 343e82c..4827afb 100644
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -86,7 +86,8 @@
+ #define LTQ_PPE32_SIZE		0x40000
+ 
+ /* DMA */
+-#define LTQ_DMA_BASE_ADDR	0xBE104100
++#define LTQ_DMA_BASE_ADDR	0x1E104100
++#define LTQ_DMA_SIZE		0x800
+ 
+ /* PCI */
+ #define PCI_CR_BASE_ADDR	0x1E105400
+diff --git a/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h b/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
+new file mode 100644
+index 0000000..872943a
+--- /dev/null
++++ b/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
+@@ -0,0 +1,60 @@
++/*
++ *   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 <[email protected]>
++ */
++
++#ifndef LTQ_DMA_H__
++#define LTQ_DMA_H__
++
++#define LTQ_DESC_SIZE		0x08	/* each descriptor is 64bit */
++#define LTQ_DESC_NUM		0x40	/* 64 descriptors / channel */
++
++#define LTQ_DMA_OWN		BIT(31)	/* owner bit */
++#define LTQ_DMA_C		BIT(30) /* complete bit */
++#define LTQ_DMA_SOP		BIT(29) /* start of packet */
++#define LTQ_DMA_EOP		BIT(28) /* end of packet */
++#define LTQ_DMA_TX_OFFSET(x)	((x & 0x1f) << 23) /* data bytes offset */
++#define LTQ_DMA_RX_OFFSET(x)	((x & 0x7) << 23) /* data bytes offset */
++#define LTQ_DMA_SIZE_MASK	(0xffff) /* the size field is 16 bit */
++
++struct ltq_dma_desc {
++	u32 ctl;
++	u32 addr;
++};
++
++struct ltq_dma_channel {
++	int nr;				/* the channel number */
++	int irq;			/* the mapped irq */
++	int desc;			/* the current descriptor */
++	struct ltq_dma_desc *desc_base;	/* the descriptor base */
++	int phys;			/* physical addr */
++};
++
++enum {
++	DMA_PORT_ETOP = 0,
++	DMA_PORT_DEU,
++};
++
++extern void ltq_dma_enable_irq(struct ltq_dma_channel *ch);
++extern void ltq_dma_disable_irq(struct ltq_dma_channel *ch);
++extern void ltq_dma_ack_irq(struct ltq_dma_channel *ch);
++extern void ltq_dma_open(struct ltq_dma_channel *ch);
++extern void ltq_dma_close(struct ltq_dma_channel *ch);
++extern void ltq_dma_alloc_tx(struct ltq_dma_channel *ch);
++extern void ltq_dma_alloc_rx(struct ltq_dma_channel *ch);
++extern void ltq_dma_free(struct ltq_dma_channel *ch);
++extern void ltq_dma_init_port(int p);
++
++#endif
+diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
+index 6b5e07e..c517f2e 100644
+--- a/arch/mips/lantiq/xway/Makefile
++++ b/arch/mips/lantiq/xway/Makefile
+@@ -1,4 +1,4 @@
+-obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o
++obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o
+ 
+ obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o
+ obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o
+diff --git a/arch/mips/lantiq/xway/devices.h b/arch/mips/lantiq/xway/devices.h
+index 51f56b5..d573084 100644
+--- a/arch/mips/lantiq/xway/devices.h
++++ b/arch/mips/lantiq/xway/devices.h
+@@ -10,6 +10,7 @@
+ #define _LTQ_DEVICES_XWAY_H__
+ 
+ #include "../devices.h"
++#include <linux/phy.h>
+ 
+ extern void ltq_register_gpio(void);
+ extern void ltq_register_gpio_stp(void);
+diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
+new file mode 100644
+index 0000000..4278a45
+--- /dev/null
++++ b/arch/mips/lantiq/xway/dma.c
+@@ -0,0 +1,253 @@
++/*
++ *   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 <[email protected]>
++ */
++
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/dma-mapping.h>
++
++#include <lantiq_soc.h>
++#include <xway_dma.h>
++
++#define LTQ_DMA_CTRL		0x10
++#define LTQ_DMA_CPOLL		0x14
++#define LTQ_DMA_CS		0x18
++#define LTQ_DMA_CCTRL		0x1C
++#define LTQ_DMA_CDBA		0x20
++#define LTQ_DMA_CDLEN		0x24
++#define LTQ_DMA_CIS		0x28
++#define LTQ_DMA_CIE		0x2C
++#define LTQ_DMA_PS		0x40
++#define LTQ_DMA_PCTRL		0x44
++#define LTQ_DMA_IRNEN		0xf4
++
++#define DMA_DESCPT		BIT(3)		/* descriptor complete irq */
++#define DMA_TX			BIT(8)		/* TX channel direction */
++#define DMA_CHAN_ON		BIT(0)		/* channel on / off bit */
++#define DMA_PDEN		BIT(6)		/* enable packet drop */
++#define DMA_CHAN_RST		BIT(1)		/* channel on / off bit */
++#define DMA_RESET		BIT(0)		/* channel on / off bit */
++#define DMA_IRQ_ACK		0x7e		/* IRQ status register */
++#define DMA_POLL		BIT(31)		/* turn on channel polling */
++#define DMA_CLK_DIV4		BIT(6)		/* polling clock divider */
++#define DMA_2W_BURST		BIT(1)		/* 2 word burst length */
++#define DMA_MAX_CHANNEL		20		/* the soc has 20 channels */
++#define DMA_ETOP_ENDIANESS	(0xf << 8) /* endianess swap etop channels */
++#define DMA_WEIGHT	(BIT(17) | BIT(16))	/* default channel wheight */
++
++#define ltq_dma_r32(x)			ltq_r32(ltq_dma_membase + (x))
++#define ltq_dma_w32(x, y)		ltq_w32(x, ltq_dma_membase + (y))
++#define ltq_dma_w32_mask(x, y, z)	ltq_w32_mask(x, y, \
++						ltq_dma_membase + (z))
++
++static struct resource ltq_dma_resource = {
++	.name	= "dma",
++	.start	= LTQ_DMA_BASE_ADDR,
++	.end	= LTQ_DMA_BASE_ADDR + LTQ_DMA_SIZE - 1,
++	.flags  = IORESOURCE_MEM,
++};
++
++static void __iomem *ltq_dma_membase;
++
++void
++ltq_dma_enable_irq(struct ltq_dma_channel *ch)
++{
++	unsigned long flags;
++
++	local_irq_save(flags);
++	ltq_dma_w32(ch->nr, LTQ_DMA_CS);
++	ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN);
++	local_irq_restore(flags);
++}
++EXPORT_SYMBOL_GPL(ltq_dma_enable_irq);
++
++void
++ltq_dma_disable_irq(struct ltq_dma_channel *ch)
++{
++	unsigned long flags;
++
++	local_irq_save(flags);
++	ltq_dma_w32(ch->nr, LTQ_DMA_CS);
++	ltq_dma_w32_mask(1 << ch->nr, 0, LTQ_DMA_IRNEN);
++	local_irq_restore(flags);
++}
++EXPORT_SYMBOL_GPL(ltq_dma_disable_irq);
++
++void
++ltq_dma_ack_irq(struct ltq_dma_channel *ch)
++{
++	unsigned long flags;
++
++	local_irq_save(flags);
++	ltq_dma_w32(ch->nr, LTQ_DMA_CS);
++	ltq_dma_w32(DMA_IRQ_ACK, LTQ_DMA_CIS);
++	local_irq_restore(flags);
++}
++EXPORT_SYMBOL_GPL(ltq_dma_ack_irq);
++
++void
++ltq_dma_open(struct ltq_dma_channel *ch)
++{
++	unsigned long flag;
++
++	local_irq_save(flag);
++	ltq_dma_w32(ch->nr, LTQ_DMA_CS);
++	ltq_dma_w32_mask(0, DMA_CHAN_ON, LTQ_DMA_CCTRL);
++	ltq_dma_enable_irq(ch);
++	local_irq_restore(flag);
++}
++EXPORT_SYMBOL_GPL(ltq_dma_open);
++
++void
++ltq_dma_close(struct ltq_dma_channel *ch)
++{
++	unsigned long flag;
++
++	local_irq_save(flag);
++	ltq_dma_w32(ch->nr, LTQ_DMA_CS);
++	ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
++	ltq_dma_disable_irq(ch);
++	local_irq_restore(flag);
++}
++EXPORT_SYMBOL_GPL(ltq_dma_close);
++
++static void
++ltq_dma_alloc(struct ltq_dma_channel *ch)
++{
++	unsigned long flags;
++
++	ch->desc = 0;
++	ch->desc_base = dma_alloc_coherent(NULL,
++				LTQ_DESC_NUM * LTQ_DESC_SIZE,
++				&ch->phys, GFP_ATOMIC);
++	memset(ch->desc_base, 0, LTQ_DESC_NUM * LTQ_DESC_SIZE);
++
++	local_irq_save(flags);
++	ltq_dma_w32(ch->nr, LTQ_DMA_CS);
++	ltq_dma_w32(ch->phys, LTQ_DMA_CDBA);
++	ltq_dma_w32(LTQ_DESC_NUM, LTQ_DMA_CDLEN);
++	ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
++	wmb();
++	ltq_dma_w32_mask(0, DMA_CHAN_RST, LTQ_DMA_CCTRL);
++	while (ltq_dma_r32(LTQ_DMA_CCTRL) & DMA_CHAN_RST)
++		;
++	local_irq_restore(flags);
++}
++
++void
++ltq_dma_alloc_tx(struct ltq_dma_channel *ch)
++{
++	unsigned long flags;
++
++	ltq_dma_alloc(ch);
++
++	local_irq_save(flags);
++	ltq_dma_w32(DMA_DESCPT, LTQ_DMA_CIE);
++	ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN);
++	ltq_dma_w32(DMA_WEIGHT | DMA_TX, LTQ_DMA_CCTRL);
++	local_irq_restore(flags);
++}
++EXPORT_SYMBOL_GPL(ltq_dma_alloc_tx);
++
++void
++ltq_dma_alloc_rx(struct ltq_dma_channel *ch)
++{
++	unsigned long flags;
++
++	ltq_dma_alloc(ch);
++
++	local_irq_save(flags);
++	ltq_dma_w32(DMA_DESCPT, LTQ_DMA_CIE);
++	ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN);
++	ltq_dma_w32(DMA_WEIGHT, LTQ_DMA_CCTRL);
++	local_irq_restore(flags);
++}
++EXPORT_SYMBOL_GPL(ltq_dma_alloc_rx);
++
++void
++ltq_dma_free(struct ltq_dma_channel *ch)
++{
++	if (!ch->desc_base)
++		return;
++	ltq_dma_close(ch);
++	dma_free_coherent(NULL, LTQ_DESC_NUM * LTQ_DESC_SIZE,
++		ch->desc_base, ch->phys);
++}
++EXPORT_SYMBOL_GPL(ltq_dma_free);
++
++void
++ltq_dma_init_port(int p)
++{
++	ltq_dma_w32(p, LTQ_DMA_PS);
++	switch (p) {
++	case DMA_PORT_ETOP:
++		/*
++		 * Tell the DMA engine to swap the endianess of data frames and
++		 * drop packets if the channel arbitration fails.
++		 */
++		ltq_dma_w32_mask(0, DMA_ETOP_ENDIANESS | DMA_PDEN,
++			LTQ_DMA_PCTRL);
++		break;
++
++	case DMA_PORT_DEU:
++		ltq_dma_w32((DMA_2W_BURST << 4) | (DMA_2W_BURST << 2),
++			LTQ_DMA_PCTRL);
++		break;
++
++	default:
++		break;
++	}
++}
++EXPORT_SYMBOL_GPL(ltq_dma_init_port);
++
++int __init
++ltq_dma_init(void)
++{
++	int i;
++
++	/* insert and request the memory region */
++	if (insert_resource(&iomem_resource, &ltq_dma_resource) < 0)
++		panic("Failed to insert dma memory\n");
++
++	if (request_mem_region(ltq_dma_resource.start,
++			resource_size(&ltq_dma_resource), "dma") < 0)
++		panic("Failed to request dma memory\n");
++
++	/* remap dma register range */
++	ltq_dma_membase = ioremap_nocache(ltq_dma_resource.start,
++				resource_size(&ltq_dma_resource));
++	if (!ltq_dma_membase)
++		panic("Failed to remap dma memory\n");
++
++	/* power up and reset the dma engine */
++	ltq_pmu_enable(PMU_DMA);
++	ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL);
++
++	/* disable all interrupts */
++	ltq_dma_w32(0, LTQ_DMA_IRNEN);
++
++	/* reset/configure each channel */
++	for (i = 0; i < DMA_MAX_CHANNEL; i++) {
++		ltq_dma_w32(i, LTQ_DMA_CS);
++		ltq_dma_w32(DMA_CHAN_RST, LTQ_DMA_CCTRL);
++		ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
++		ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
++	}
++	return 0;
++}
++
++postcore_initcall(ltq_dma_init);
+-- 
+1.7.2.3
+

+ 943 - 0
target/linux/lantiq/patches-2.6.32/0011-MIPS-Lantiq-Add-ethernet-driver.patch

@@ -0,0 +1,943 @@
+From 435de86088af82496bcba69165cd7422bb4622ec Mon Sep 17 00:00:00 2001
+From: John Crispin <[email protected]>
+Date: Fri, 6 May 2011 00:10:01 +0200
+Subject: [PATCH 11/13] MIPS: Lantiq: Add ethernet driver
+
+This patch adds the driver for the ETOP Packet Processing Engine (PPE32)
+found inside the XWAY family of Lantiq MIPS SoCs. This driver makes 100MBit
+ethernet work. Support for all 8 dma channels, gbit and the embedded switch
+found on the ar9/vr9 still needs to be implemented.
+
+Signed-off-by: John Crispin <[email protected]>
+Signed-off-by: Ralph Hempel <[email protected]>
+Cc: [email protected]
+Cc: [email protected]
+Patchwork: https://patchwork.linux-mips.org/patch/2357/
+Acked-by: David S. Miller <[email protected]>
+Signed-off-by: Ralf Baechle <[email protected]>
+---
+ .../mips/include/asm/mach-lantiq/lantiq_platform.h |    7 +
+ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h |    4 +-
+ arch/mips/lantiq/xway/devices.c                    |   23 +
+ arch/mips/lantiq/xway/devices.h                    |    1 +
+ drivers/net/Kconfig                                |    7 +
+ drivers/net/Makefile                               |    1 +
+ drivers/net/lantiq_etop.c                          |  805 ++++++++++++++++++++
+ 7 files changed, 846 insertions(+), 2 deletions(-)
+ create mode 100644 drivers/net/lantiq_etop.c
+
+--- a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
++++ b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
+@@ -10,6 +10,7 @@
+ #define _LANTIQ_PLATFORM_H__
+ 
+ #include <linux/mtd/partitions.h>
++#include <linux/socket.h>
+ 
+ /* struct used to pass info to the pci core */
+ enum {
+@@ -43,4 +44,10 @@
+ 	int irq[16];
+ };
+ 
++/* struct used to pass info to network drivers */
++struct ltq_eth_data {
++	struct sockaddr mac;
++	int mii_mode;
++};
++
+ #endif
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -82,8 +82,8 @@
+ #define PMU_SWITCH		0x10000000
+ 
+ /* ETOP - ethernet */
+-#define LTQ_PPE32_BASE_ADDR	0xBE180000
+-#define LTQ_PPE32_SIZE		0x40000
++#define LTQ_ETOP_BASE_ADDR	0x1E180000
++#define LTQ_ETOP_SIZE		0x40000
+ 
+ /* DMA */
+ #define LTQ_DMA_BASE_ADDR	0x1E104100
+--- a/arch/mips/lantiq/xway/devices.c
++++ b/arch/mips/lantiq/xway/devices.c
+@@ -96,3 +96,26 @@
+ 	platform_device_register_simple("ltq_asc", 0,
+ 		ltq_ase_asc_resources, ARRAY_SIZE(ltq_ase_asc_resources));
+ }
++
++/* ethernet */
++static struct resource ltq_etop_resources = {
++	.name	= "etop",
++	.start	= LTQ_ETOP_BASE_ADDR,
++	.end	= LTQ_ETOP_BASE_ADDR + LTQ_ETOP_SIZE - 1,
++	.flags	= IORESOURCE_MEM,
++};
++
++static struct platform_device ltq_etop = {
++	.name		= "ltq_etop",
++	.resource	= &ltq_etop_resources,
++	.num_resources	= 1,
++};
++
++void __init
++ltq_register_etop(struct ltq_eth_data *eth)
++{
++	if (eth) {
++		ltq_etop.dev.platform_data = eth;
++		platform_device_register(&ltq_etop);
++	}
++}
+--- a/arch/mips/lantiq/xway/devices.h
++++ b/arch/mips/lantiq/xway/devices.h
+@@ -15,5 +15,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);
+ 
+ #endif
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -1951,6 +1951,13 @@
+ 	  This driver supports the ethernet MACs in the Broadcom 63xx
+ 	  MIPS chipset family (BCM63XX).
+ 
++config LANTIQ_ETOP
++	tristate "Lantiq SoC ETOP driver"
++	depends on SOC_TYPE_XWAY
++	help
++	  Support for the MII0 inside the Lantiq SoC
++
++
+ source "drivers/net/fs_enet/Kconfig"
+ 
+ endif # NET_ETHERNET
+--- a/drivers/net/Makefile
++++ b/drivers/net/Makefile
+@@ -246,6 +246,7 @@
+ obj-$(CONFIG_MLX4_CORE) += mlx4/
+ obj-$(CONFIG_ENC28J60) += enc28j60.o
+ obj-$(CONFIG_ETHOC) += ethoc.o
++obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
+ 
+ obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o
+ 
+--- /dev/null
++++ b/drivers/net/lantiq_etop.c
+@@ -0,0 +1,814 @@
++/*
++ *   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 <[email protected]>
++ */
++
++#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 <asm/checksum.h>
++
++#include <lantiq_soc.h>
++#include <xway_dma.h>
++#include <lantiq_platform.h>
++
++#define LTQ_ETOP_MDIO		0x11804
++#define MDIO_REQUEST		0x80000000
++#define MDIO_READ		0x40000000
++#define MDIO_ADDR_MASK		0x1f
++#define MDIO_ADDR_OFFSET	0x15
++#define MDIO_REG_MASK		0x1f
++#define MDIO_REG_OFFSET		0x10
++#define MDIO_VAL_MASK		0xffff
++
++#define PPE32_CGEN		0x800
++#define LTQ_PPE32_ENET_MAC_CFG	0x1840
++
++#define LTQ_ETOP_ENETS0		0x11850
++#define LTQ_ETOP_MAC_DA0	0x1186C
++#define LTQ_ETOP_MAC_DA1	0x11870
++#define LTQ_ETOP_CFG		0x16020
++#define LTQ_ETOP_IGPLEN		0x16080
++
++#define MAX_DMA_CHAN		0x8
++#define MAX_DMA_CRC_LEN		0x4
++#define MAX_DMA_DATA_LEN	0x600
++
++#define ETOP_FTCU		BIT(28)
++#define ETOP_MII_MASK		0xf
++#define ETOP_MII_NORMAL		0xd
++#define ETOP_MII_REVERSE	0xe
++#define ETOP_PLEN_UNDER		0x40
++#define ETOP_CGEN		0x800
++
++/* use 2 static channels for TX/RX */
++#define LTQ_ETOP_TX_CHANNEL	1
++#define LTQ_ETOP_RX_CHANNEL	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)	\
++		ltq_w32_mask(x, y, ltq_etop_membase + (z))
++
++#define DRV_VERSION	"1.0"
++
++#ifndef netdev_err
++#define netdev_err(a, b, ...)	printk(b, ##__VA_ARGS__)
++#endif
++
++#ifndef pr_warn
++#define pr_warn pr_warning
++#endif
++
++static void __iomem *ltq_etop_membase;
++
++struct ltq_etop_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_etop_priv {
++	struct net_device *netdev;
++	struct ltq_eth_data *pldata;
++	struct resource *res;
++
++	struct mii_bus *mii_bus;
++	struct phy_device *phydev;
++
++	struct ltq_etop_chan ch[MAX_DMA_CHAN];
++	int tx_free[MAX_DMA_CHAN >> 1];
++
++	spinlock_t lock;
++};
++
++static int
++ltq_etop_alloc_skb(struct ltq_etop_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_etop_hw_receive(struct ltq_etop_chan *ch)
++{
++	struct ltq_etop_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_etop_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_etop_poll_rx(struct napi_struct *napi, int budget)
++{
++	struct ltq_etop_chan *ch = container_of(napi,
++				struct ltq_etop_chan, napi);
++	int rx = 0;
++	int complete = 0;
++
++	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_etop_hw_receive(ch);
++			rx++;
++		} else {
++			complete = 1;
++		}
++	}
++	if (complete || !rx) {
++		napi_complete(&ch->napi);
++		ltq_dma_ack_irq(&ch->dma);
++	}
++	return rx;
++}
++
++static int
++ltq_etop_poll_tx(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);
++	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);
++	ltq_dma_ack_irq(&ch->dma);
++	return 1;
++}
++
++static irqreturn_t
++ltq_etop_dma_irq(int irq, void *_priv)
++{
++	struct ltq_etop_priv *priv = _priv;
++	int ch = irq - LTQ_DMA_CH0_INT;
++
++	napi_schedule(&priv->ch[ch].napi);
++	return IRQ_HANDLED;
++}
++
++static void
++ltq_etop_free_channel(struct net_device *dev, struct ltq_etop_chan *ch)
++{
++	struct ltq_etop_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_etop_hw_exit(struct net_device *dev)
++{
++	struct ltq_etop_priv *priv = netdev_priv(dev);
++	int i;
++
++	ltq_pmu_disable(PMU_PPE);
++	for (i = 0; i < MAX_DMA_CHAN; i++)
++		if (IS_TX(i) || IS_RX(i))
++			ltq_etop_free_channel(dev, &priv->ch[i]);
++}
++
++static int
++ltq_etop_hw_init(struct net_device *dev)
++{
++	struct ltq_etop_priv *priv = netdev_priv(dev);
++	int i;
++
++	ltq_pmu_enable(PMU_PPE);
++
++	switch (priv->pldata->mii_mode) {
++	case PHY_INTERFACE_MODE_RMII:
++		ltq_etop_w32_mask(ETOP_MII_MASK,
++			ETOP_MII_REVERSE, LTQ_ETOP_CFG);
++		break;
++
++	case PHY_INTERFACE_MODE_MII:
++		ltq_etop_w32_mask(ETOP_MII_MASK,
++			ETOP_MII_NORMAL, LTQ_ETOP_CFG);
++		break;
++
++	default:
++		netdev_err(dev, "unknown mii mode %d\n",
++			priv->pldata->mii_mode);
++		return -ENOTSUPP;
++	}
++
++	/* enable crc generation */
++	ltq_etop_w32(PPE32_CGEN, LTQ_PPE32_ENET_MAC_CFG);
++
++	ltq_dma_init_port(DMA_PORT_ETOP);
++
++	for (i = 0; i < MAX_DMA_CHAN; i++) {
++		int irq = LTQ_DMA_CH0_INT + 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);
++			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;
++			ch->dma.desc = 0;
++			request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
++				"etop_rx", priv);
++		}
++		ch->dma.irq = irq;
++	}
++	return 0;
++}
++
++static void
++ltq_etop_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_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);
++}
++
++static int
++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);
++}
++
++static int
++ltq_etop_nway_reset(struct net_device *dev)
++{
++	struct ltq_etop_priv *priv = netdev_priv(dev);
++
++	return phy_start_aneg(priv->phydev);
++}
++
++static const struct ethtool_ops ltq_etop_ethtool_ops = {
++	.get_drvinfo = ltq_etop_get_drvinfo,
++	.get_settings = ltq_etop_get_settings,
++	.set_settings = ltq_etop_set_settings,
++	.nway_reset = ltq_etop_nway_reset,
++};
++
++static int
++ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data)
++{
++	u32 val = MDIO_REQUEST |
++		((phy_addr & MDIO_ADDR_MASK) << MDIO_ADDR_OFFSET) |
++		((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET) |
++		phy_data;
++
++	while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
++		;
++	ltq_etop_w32(val, LTQ_ETOP_MDIO);
++	return 0;
++}
++
++static int
++ltq_etop_mdio_rd(struct mii_bus *bus, int phy_addr, int phy_reg)
++{
++	u32 val = MDIO_REQUEST | MDIO_READ |
++		((phy_addr & MDIO_ADDR_MASK) << MDIO_ADDR_OFFSET) |
++		((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET);
++
++	while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
++		;
++	ltq_etop_w32(val, LTQ_ETOP_MDIO);
++	while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
++		;
++	val = ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_VAL_MASK;
++	return val;
++}
++
++static void
++ltq_etop_mdio_link(struct net_device *dev)
++{
++	/* nothing to do  */
++}
++
++static int
++ltq_etop_mdio_probe(struct net_device *dev)
++{
++	struct ltq_etop_priv *priv = netdev_priv(dev);
++	struct phy_device *phydev = NULL;
++	int phy_addr;
++
++	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
++		if (priv->mii_bus->phy_map[phy_addr]) {
++			phydev = priv->mii_bus->phy_map[phy_addr];
++			break;
++		}
++	}
++
++	if (!phydev) {
++		netdev_err(dev, "no PHY found\n");
++		return -ENODEV;
++	}
++
++	phydev = phy_connect(dev, dev_name(&phydev->dev), &ltq_etop_mdio_link,
++			0, priv->pldata->mii_mode);
++
++	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_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);
++
++	return 0;
++}
++
++static int
++ltq_etop_mdio_init(struct net_device *dev)
++{
++	struct ltq_etop_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_etop_mdio_rd;
++	priv->mii_bus->write = ltq_etop_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_etop_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_etop_mdio_cleanup(struct net_device *dev)
++{
++	struct ltq_etop_priv *priv = netdev_priv(dev);
++
++	phy_disconnect(priv->phydev);
++	mdiobus_unregister(priv->mii_bus);
++	kfree(priv->mii_bus->irq);
++	mdiobus_free(priv->mii_bus);
++}
++
++static int
++ltq_etop_open(struct net_device *dev)
++{
++	struct ltq_etop_priv *priv = netdev_priv(dev);
++	int i;
++
++	for (i = 0; i < MAX_DMA_CHAN; i++) {
++		struct ltq_etop_chan *ch = &priv->ch[i];
++
++		if (!IS_TX(i) && (!IS_RX(i)))
++			continue;
++		ltq_dma_open(&ch->dma);
++		napi_enable(&ch->napi);
++	}
++	phy_start(priv->phydev);
++	netif_tx_start_all_queues(dev);
++	return 0;
++}
++
++static int
++ltq_etop_stop(struct net_device *dev)
++{
++	struct ltq_etop_priv *priv = netdev_priv(dev);
++	int i;
++
++	netif_tx_stop_all_queues(dev);
++	phy_stop(priv->phydev);
++	for (i = 0; i < MAX_DMA_CHAN; i++) {
++		struct ltq_etop_chan *ch = &priv->ch[i];
++
++		if (!IS_RX(i) && !IS_TX(i))
++			continue;
++		napi_disable(&ch->napi);
++		ltq_dma_close(&ch->dma);
++	}
++	return 0;
++}
++
++static int
++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];
++	int len;
++	unsigned long flags;
++	u32 byte_offset;
++
++	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);
++		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_etop_change_mtu(struct net_device *dev, int new_mtu)
++{
++	int ret = eth_change_mtu(dev, new_mtu);
++
++	if (!ret) {
++		struct ltq_etop_priv *priv = netdev_priv(dev);
++		unsigned long flags;
++
++		spin_lock_irqsave(&priv->lock, flags);
++		ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu,
++			LTQ_ETOP_IGPLEN);
++		spin_unlock_irqrestore(&priv->lock, flags);
++	}
++	return ret;
++}
++
++static int
++ltq_etop_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++	struct ltq_etop_priv *priv = netdev_priv(dev);
++	struct mii_ioctl_data *data = if_mii(rq);
++
++	/* TODO: mii-toll reports "No MII transceiver present!." ?!*/
++	return phy_mii_ioctl(priv->phydev, data, cmd);
++}
++
++static int
++ltq_etop_set_mac_address(struct net_device *dev, void *p)
++{
++	int ret = eth_mac_addr(dev, p);
++
++	if (!ret) {
++		struct ltq_etop_priv *priv = netdev_priv(dev);
++		unsigned long flags;
++
++		/* store the mac for the unicast filter */
++		spin_lock_irqsave(&priv->lock, flags);
++		ltq_etop_w32(*((u32 *)dev->dev_addr), LTQ_ETOP_MAC_DA0);
++		ltq_etop_w32(*((u16 *)&dev->dev_addr[4]) << 16,
++			LTQ_ETOP_MAC_DA1);
++		spin_unlock_irqrestore(&priv->lock, flags);
++	}
++	return ret;
++}
++
++static void
++ltq_etop_set_multicast_list(struct net_device *dev)
++{
++	struct ltq_etop_priv *priv = netdev_priv(dev);
++	unsigned long flags;
++
++	/* ensure that the unicast filter is not enabled in promiscious mode */
++	spin_lock_irqsave(&priv->lock, flags);
++	if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI))
++		ltq_etop_w32_mask(ETOP_FTCU, 0, LTQ_ETOP_ENETS0);
++	else
++		ltq_etop_w32_mask(0, ETOP_FTCU, LTQ_ETOP_ENETS0);
++	spin_unlock_irqrestore(&priv->lock, flags);
++}
++
++static u16
++ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb)
++{
++	/* we are currently only using the first queue */
++	return 0;
++}
++
++static int
++ltq_etop_init(struct net_device *dev)
++{
++	struct ltq_etop_priv *priv = netdev_priv(dev);
++	struct sockaddr mac;
++	int err;
++
++	ether_setup(dev);
++	dev->watchdog_timeo = 10 * HZ;
++	err = ltq_etop_hw_init(dev);
++	if (err)
++		goto err_hw;
++	ltq_etop_change_mtu(dev, 1500);
++
++	memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr));
++	if (!is_valid_ether_addr(mac.sa_data)) {
++		pr_warn("etop: invalid MAC, using random\n");
++		random_ether_addr(mac.sa_data);
++	}
++
++	err = ltq_etop_set_mac_address(dev, &mac);
++	if (err)
++		goto err_netdev;
++	ltq_etop_set_multicast_list(dev);
++	err = ltq_etop_mdio_init(dev);
++	if (err)
++		goto err_netdev;
++	return 0;
++
++err_netdev:
++	unregister_netdev(dev);
++	free_netdev(dev);
++err_hw:
++	ltq_etop_hw_exit(dev);
++	return err;
++}
++
++static void
++ltq_etop_tx_timeout(struct net_device *dev)
++{
++	int err;
++
++	ltq_etop_hw_exit(dev);
++	err = ltq_etop_hw_init(dev);
++	if (err)
++		goto err_hw;
++	dev->trans_start = jiffies;
++	netif_wake_queue(dev);
++	return;
++
++err_hw:
++	ltq_etop_hw_exit(dev);
++	netdev_err(dev, "failed to restart etop after TX timeout\n");
++}
++
++static const struct net_device_ops ltq_eth_netdev_ops = {
++	.ndo_open = ltq_etop_open,
++	.ndo_stop = ltq_etop_stop,
++	.ndo_start_xmit = ltq_etop_tx,
++	.ndo_change_mtu = ltq_etop_change_mtu,
++	.ndo_do_ioctl = ltq_etop_ioctl,
++	.ndo_set_mac_address = ltq_etop_set_mac_address,
++	.ndo_validate_addr = eth_validate_addr,
++	.ndo_set_multicast_list = ltq_etop_set_multicast_list,
++	.ndo_select_queue = ltq_etop_select_queue,
++	.ndo_init = ltq_etop_init,
++	.ndo_tx_timeout = ltq_etop_tx_timeout,
++};
++
++static int __init
++ltq_etop_probe(struct platform_device *pdev)
++{
++	struct net_device *dev;
++	struct ltq_etop_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 etop 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 etop resource\n");
++		err = -EBUSY;
++		goto err_out;
++	}
++
++	ltq_etop_membase = devm_ioremap_nocache(&pdev->dev,
++		res->start, resource_size(res));
++	if (!ltq_etop_membase) {
++		dev_err(&pdev->dev, "failed to remap etop engine %d\n",
++			pdev->id);
++		err = -ENOMEM;
++		goto err_out;
++	}
++
++	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);
++	priv->netdev = dev;
++	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;
++	}
++
++	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_etop_remove(struct platform_device *pdev)
++{
++	struct net_device *dev = platform_get_drvdata(pdev);
++
++	if (dev) {
++		netif_tx_stop_all_queues(dev);
++		ltq_etop_hw_exit(dev);
++		ltq_etop_mdio_cleanup(dev);
++		unregister_netdev(dev);
++	}
++	return 0;
++}
++
++static struct platform_driver ltq_mii_driver = {
++	.remove = __devexit_p(ltq_etop_remove),
++	.driver = {
++		.name = "ltq_etop",
++		.owner = THIS_MODULE,
++	},
++};
++
++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_AUTHOR("John Crispin <[email protected]>");
++MODULE_DESCRIPTION("Lantiq SoC ETOP");
++MODULE_LICENSE("GPL");

+ 50 - 0
target/linux/lantiq/patches-2.6.32/0012-MIPS-Lantiq-Add-etop-board-support.patch

@@ -0,0 +1,50 @@
+From 72a9b536ef81f06bb8042abee0410458f5df93d2 Mon Sep 17 00:00:00 2001
+From: John Crispin <[email protected]>
+Date: Fri, 6 May 2011 00:10:02 +0200
+Subject: [PATCH 12/13] MIPS: Lantiq: Add etop board support
+
+Register the etop platform device inside the machtype specific init code.
+
+Signed-off-by: John Crispin <[email protected]>
+Signed-off-by: Ralph Hempel <[email protected]>
+Signed-off-by: David Daney <[email protected]>
+Cc: [email protected]
+Patchwork: https://patchwork.linux-mips.org/patch/2356/
+Patchwork: https://patchwork.linux-mips.org/patch/2370/
+Signed-off-by: Ralf Baechle <[email protected]>
+---
+ arch/mips/lantiq/xway/mach-easy50712.c |    6 ++++++
+ 1 files changed, 6 insertions(+), 0 deletions(-)
+
+diff --git a/arch/mips/lantiq/xway/mach-easy50712.c b/arch/mips/lantiq/xway/mach-easy50712.c
+index e5e7e09..ea5027b 100644
+--- a/arch/mips/lantiq/xway/mach-easy50712.c
++++ b/arch/mips/lantiq/xway/mach-easy50712.c
+@@ -12,6 +12,7 @@
+ #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>
+@@ -55,11 +56,16 @@ static struct ltq_pci_data ltq_pci_data = {
+ 	},
+ };
+ 
++static struct ltq_eth_data ltq_eth_data = {
++	.mii_mode = PHY_INTERFACE_MODE_MII,
++};
++
+ static void __init easy50712_init(void)
+ {
+ 	ltq_register_gpio_stp();
+ 	ltq_register_nor(&easy50712_flash_data);
+ 	ltq_register_pci(&ltq_pci_data);
++	ltq_register_etop(&ltq_eth_data);
+ }
+ 
+ MIPS_MACHINE(LTQ_MACH_EASY50712,
+-- 
+1.7.2.3
+

+ 310 - 0
target/linux/lantiq/patches-2.6.32/0013-MIPS-Lantiq-Add-watchdog-support.patch

@@ -0,0 +1,310 @@
+From 3466449c8f455da0cb646231602e6af16190f592 Mon Sep 17 00:00:00 2001
+From: John Crispin <[email protected]>
+Date: Thu, 5 May 2011 23:00:23 +0200
+Subject: [PATCH 13/13] MIPS: Lantiq: Add watchdog support
+
+This patch adds the driver for the watchdog found inside the Lantiq SoC family.
+
+Signed-off-by: John Crispin <[email protected]>
+Signed-off-by: Ralph Hempel <[email protected]>
+Cc: Wim Van Sebroeck <[email protected]>
+Cc: [email protected]
+Cc: [email protected]
+Patchwork: https://patchwork.linux-mips.org/patch/2327/
+Signed-off-by: Ralf Baechle <[email protected]>
+---
+ drivers/watchdog/Kconfig      |    6 +
+ drivers/watchdog/Makefile     |    1 +
+ drivers/watchdog/lantiq_wdt.c |  261 +++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 268 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/watchdog/lantiq_wdt.c
+
+--- a/drivers/watchdog/Kconfig
++++ b/drivers/watchdog/Kconfig
+@@ -850,6 +850,12 @@
+ 	help
+ 	  Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs.
+ 
++config LANTIQ_WDT
++	tristate "Lantiq SoC watchdog"
++	depends on LANTIQ
++	help
++	  Hardware driver for the Lantiq SoC Watchdog Timer.
++
+ # PARISC Architecture
+ 
+ # POWERPC Architecture
+--- a/drivers/watchdog/Makefile
++++ b/drivers/watchdog/Makefile
+@@ -113,6 +113,7 @@
+ obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
+ obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
+ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
++obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
+ 
+ # PARISC Architecture
+ 
+--- /dev/null
++++ b/drivers/watchdog/lantiq_wdt.c
+@@ -0,0 +1,261 @@
++/*
++ *  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 <[email protected]>
++ *  Based on EP93xx wdt driver
++ */
++
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <linux/watchdog.h>
++#include <linux/platform_device.h>
++#include <linux/uaccess.h>
++#include <linux/clk.h>
++#include <linux/io.h>
++
++#include <lantiq.h>
++
++/* Section 3.4 of the datasheet
++ * The password sequence protects the WDT control register from unintended
++ * write actions, which might cause malfunction of the WDT.
++ *
++ * essentially the following two magic passwords need to be written to allow
++ * IO access to the WDT core
++ */
++#define LTQ_WDT_PW1		0x00BE0000
++#define LTQ_WDT_PW2		0x00DC0000
++
++#define LTQ_WDT_CR		0x0	/* watchdog control register */
++#define LTQ_WDT_SR		0x8	/* watchdog status register */
++
++#define LTQ_WDT_SR_EN		(0x1 << 31)	/* enable bit */
++#define LTQ_WDT_SR_PWD		(0x3 << 26)	/* turn on power */
++#define LTQ_WDT_SR_CLKDIV	(0x3 << 24)	/* turn on clock and set */
++						/* divider to 0x40000 */
++#define LTQ_WDT_DIVIDER		0x40000
++#define LTQ_MAX_TIMEOUT		((1 << 16) - 1)	/* the reload field is 16 bit */
++
++static int nowayout = WATCHDOG_NOWAYOUT;
++
++static void __iomem *ltq_wdt_membase;
++static unsigned long ltq_io_region_clk_rate;
++
++static unsigned long ltq_wdt_bootstatus;
++static unsigned long ltq_wdt_in_use;
++static int ltq_wdt_timeout = 30;
++static int ltq_wdt_ok_to_close;
++
++static void
++ltq_wdt_enable(void)
++{
++	ltq_wdt_timeout = ltq_wdt_timeout *
++			(ltq_io_region_clk_rate / LTQ_WDT_DIVIDER) + 0x1000;
++	if (ltq_wdt_timeout > LTQ_MAX_TIMEOUT)
++		ltq_wdt_timeout = LTQ_MAX_TIMEOUT;
++
++	/* write the first password magic */
++	ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR);
++	/* write the second magic plus the configuration and new timeout */
++	ltq_w32(LTQ_WDT_SR_EN | LTQ_WDT_SR_PWD | LTQ_WDT_SR_CLKDIV |
++		LTQ_WDT_PW2 | ltq_wdt_timeout, ltq_wdt_membase + LTQ_WDT_CR);
++}
++
++static void
++ltq_wdt_disable(void)
++{
++	/* write the first password magic */
++	ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR);
++	/* write the second password magic with no config
++	 * this turns the watchdog off
++	 */
++	ltq_w32(LTQ_WDT_PW2, ltq_wdt_membase + LTQ_WDT_CR);
++}
++
++static ssize_t
++ltq_wdt_write(struct file *file, const char __user *data,
++		size_t len, loff_t *ppos)
++{
++	if (len) {
++		if (!nowayout) {
++			size_t i;
++
++			ltq_wdt_ok_to_close = 0;
++			for (i = 0; i != len; i++) {
++				char c;
++
++				if (get_user(c, data + i))
++					return -EFAULT;
++				if (c == 'V')
++					ltq_wdt_ok_to_close = 1;
++				else
++					ltq_wdt_ok_to_close = 0;
++			}
++		}
++		ltq_wdt_enable();
++	}
++
++	return len;
++}
++
++static struct watchdog_info ident = {
++	.options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
++			WDIOF_CARDRESET,
++	.identity = "ltq_wdt",
++};
++
++static long
++ltq_wdt_ioctl(struct file *file,
++		unsigned int cmd, unsigned long arg)
++{
++	int ret = -ENOTTY;
++
++	switch (cmd) {
++	case WDIOC_GETSUPPORT:
++		ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
++				sizeof(ident)) ? -EFAULT : 0;
++		break;
++
++	case WDIOC_GETBOOTSTATUS:
++		ret = put_user(ltq_wdt_bootstatus, (int __user *)arg);
++		break;
++
++	case WDIOC_GETSTATUS:
++		ret = put_user(0, (int __user *)arg);
++		break;
++
++	case WDIOC_SETTIMEOUT:
++		ret = get_user(ltq_wdt_timeout, (int __user *)arg);
++		if (!ret)
++			ltq_wdt_enable();
++		/* intentional drop through */
++	case WDIOC_GETTIMEOUT:
++		ret = put_user(ltq_wdt_timeout, (int __user *)arg);
++		break;
++
++	case WDIOC_KEEPALIVE:
++		ltq_wdt_enable();
++		ret = 0;
++		break;
++	}
++	return ret;
++}
++
++static int
++ltq_wdt_open(struct inode *inode, struct file *file)
++{
++	if (test_and_set_bit(0, &ltq_wdt_in_use))
++		return -EBUSY;
++	ltq_wdt_in_use = 1;
++	ltq_wdt_enable();
++
++	return nonseekable_open(inode, file);
++}
++
++static int
++ltq_wdt_release(struct inode *inode, struct file *file)
++{
++	if (ltq_wdt_ok_to_close)
++		ltq_wdt_disable();
++	else
++		pr_err("ltq_wdt: watchdog closed without warning\n");
++	ltq_wdt_ok_to_close = 0;
++	clear_bit(0, &ltq_wdt_in_use);
++
++	return 0;
++}
++
++static const struct file_operations ltq_wdt_fops = {
++	.owner		= THIS_MODULE,
++	.write		= ltq_wdt_write,
++	.unlocked_ioctl	= ltq_wdt_ioctl,
++	.open		= ltq_wdt_open,
++	.release	= ltq_wdt_release,
++	.llseek		= no_llseek,
++};
++
++static struct miscdevice ltq_wdt_miscdev = {
++	.minor	= WATCHDOG_MINOR,
++	.name	= "watchdog",
++	.fops	= &ltq_wdt_fops,
++};
++
++static int __init
++ltq_wdt_probe(struct platform_device *pdev)
++{
++	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	struct clk *clk;
++
++	if (!res) {
++		dev_err(&pdev->dev, "cannot obtain I/O memory region");
++		return -ENOENT;
++	}
++	res = devm_request_mem_region(&pdev->dev, res->start,
++		resource_size(res), dev_name(&pdev->dev));
++	if (!res) {
++		dev_err(&pdev->dev, "cannot request I/O memory region");
++		return -EBUSY;
++	}
++	ltq_wdt_membase = devm_ioremap_nocache(&pdev->dev, res->start,
++		resource_size(res));
++	if (!ltq_wdt_membase) {
++		dev_err(&pdev->dev, "cannot remap I/O memory region\n");
++		return -ENOMEM;
++	}
++
++	/* we do not need to enable the clock as it is always running */
++	clk = clk_get(&pdev->dev, "io");
++	WARN_ON(!clk);
++	ltq_io_region_clk_rate = clk_get_rate(clk);
++	clk_put(clk);
++
++	if (ltq_reset_cause() == LTQ_RST_CAUSE_WDTRST)
++		ltq_wdt_bootstatus = WDIOF_CARDRESET;
++
++	return misc_register(&ltq_wdt_miscdev);
++}
++
++static int __devexit
++ltq_wdt_remove(struct platform_device *pdev)
++{
++	misc_deregister(&ltq_wdt_miscdev);
++
++	if (ltq_wdt_membase)
++		iounmap(ltq_wdt_membase);
++
++	return 0;
++}
++
++
++static struct platform_driver ltq_wdt_driver = {
++	.remove = __devexit_p(ltq_wdt_remove),
++	.driver = {
++		.name = "ltq_wdt",
++		.owner = THIS_MODULE,
++	},
++};
++
++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_param(nowayout, int, 0);
++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
++
++MODULE_AUTHOR("John Crispin <[email protected]>");
++MODULE_DESCRIPTION("Lantiq SoC Watchdog");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);

+ 0 - 12
target/linux/lantiq/patches/900-header_falcon.patch → target/linux/lantiq/patches-2.6.32/100-falcon_header.patch

@@ -12406,18 +12406,6 @@
 +extern int sys_gpe_hw_is_activated(u32 mask);
 +
 +#endif /* __FALCON_SYSCTRL_H */
---- a/arch/mips/include/asm/mach-lantiq/lantiq_regs.h
-+++ b/arch/mips/include/asm/mach-lantiq/lantiq_regs.h
-@@ -12,6 +12,9 @@
- #ifdef CONFIG_SOC_LANTIQ_XWAY
- #include <xway.h>
- #include <xway_irq.h>
-+#elif defined(CONFIG_SOC_LANTIQ_FALCON)
-+#include <lantiq_falcon.h>
-+#include <lantiq_falcon_irq.h>
- #endif
- 
- #endif
 --- /dev/null
 +++ b/arch/mips/include/asm/mach-lantiq/falcon/cpu-feature-overrides.h
 @@ -0,0 +1,58 @@

+ 105 - 105
target/linux/lantiq/patches/901-board_falcon.patch → target/linux/lantiq/patches-2.6.32/110-falcon_board.patch

@@ -1,7 +1,7 @@
 --- /dev/null
 +++ b/arch/mips/lantiq/falcon/Kconfig
 @@ -0,0 +1,11 @@
-+if SOC_LANTIQ_FALCON
++if SOC_FALCON
 +
 +menu "Mips Machine"
 +
@@ -20,7 +20,7 @@
 +obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o
 --- /dev/null
 +++ b/arch/mips/lantiq/falcon/clk-falcon.c
-@@ -0,0 +1,46 @@
+@@ -0,0 +1,48 @@
 +/*
 + * 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
@@ -38,35 +38,37 @@
 +#include <asm/irq.h>
 +#include <asm/div64.h>
 +
-+#include <falcon.h>
++#include <lantiq_soc.h>
 +
-+#include <falcon/sys1_reg.h>
++#include <falcon.h>
++#include <gpon_reg_base.h>
++#include <sys1_reg.h>
 +
 +static struct gpon_reg_sys1 * const pSYS1 = (struct gpon_reg_sys1 *)GPON_SYS1_BASE;
 +
 +unsigned int
-+lq_get_io_region_clock(void)
++ltq_get_io_region_clock(void)
 +{
 +	return 200000000; /* 200 MHz */
 +}
-+EXPORT_SYMBOL(lq_get_io_region_clock);
++EXPORT_SYMBOL(ltq_get_io_region_clock);
 +
 +unsigned int
-+lq_get_cpu_hz(void)
++ltq_get_cpu_hz(void)
 +{
-+	if ((lq_r32(&pSYS1->cpu0cc) & CPU0CC_CPUDIV) == CPU0CC_CPUDIV_SELFHALF)
++	if ((ltq_r32(&pSYS1->cpu0cc) & CPU0CC_CPUDIV) == CPU0CC_CPUDIV_SELFHALF)
 +		return 200000000; /* 200 MHz */
 +	else
 +		return 400000000; /* 400 MHz */
 +}
-+EXPORT_SYMBOL(lq_get_cpu_hz);
++EXPORT_SYMBOL(ltq_get_cpu_hz);
 +
 +unsigned int
-+lq_get_fpi_hz(void)
++ltq_get_fpi_hz(void)
 +{
 +	return 100000000;
 +}
-+EXPORT_SYMBOL(lq_get_fpi_hz);
++EXPORT_SYMBOL(ltq_get_fpi_hz);
 --- /dev/null
 +++ b/arch/mips/lantiq/falcon/devices.c
 @@ -0,0 +1,180 @@
@@ -101,15 +103,15 @@
 +
 +#include "devices.h"
 +
-+unsigned char lq_ethaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-+EXPORT_SYMBOL(lq_ethaddr);
++unsigned char ltq_ethaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
++EXPORT_SYMBOL(ltq_ethaddr);
 +
 +static int __init
 +falcon_set_ethaddr(char *str)
 +{
 +	sscanf(str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
-+		&lq_ethaddr[0], &lq_ethaddr[1], &lq_ethaddr[2],
-+		&lq_ethaddr[3], &lq_ethaddr[4], &lq_ethaddr[5]);
++		&ltq_ethaddr[0], &ltq_ethaddr[1], &ltq_ethaddr[2],
++		&ltq_ethaddr[3], &ltq_ethaddr[4], &ltq_ethaddr[5]);
 +	return 0;
 +}
 +__setup("ethaddr=", falcon_set_ethaddr);
@@ -135,11 +137,11 @@
 +{
 +	switch (port) {
 +	case 0:
-+		platform_device_register_simple("lq_asc", 0,
++		platform_device_register_simple("ltq_asc", 0,
 +			falcon_asc0_resources, ARRAY_SIZE(falcon_asc0_resources));
 +		break;
 +	case 1:
-+		platform_device_register_simple("lq_asc", 1,
++		platform_device_register_simple("ltq_asc", 1,
 +			falcon_asc1_resources, ARRAY_SIZE(falcon_asc1_resources));
 +		break;
 +	default:
@@ -148,37 +150,37 @@
 +}
 +
 +/* nor flash */
-+static struct resource lq_nor_resource =
-+	MEM_RES("nor",LQ_FLASH_START,LQ_FLASH_START + LQ_FLASH_MAX - 1);
++static struct resource ltq_nor_resource =
++	MEM_RES("nor",LTQ_FLASH_START,LTQ_FLASH_START + LTQ_FLASH_MAX - 1);
 +
-+static struct platform_device lq_nor = {
-+	.name			= "lq_nor",
-+	.resource		= &lq_nor_resource,
++static struct platform_device ltq_nor = {
++	.name			= "ltq_nor",
++	.resource		= &ltq_nor_resource,
 +	.num_resources	= 1,
 +};
 +
 +void __init falcon_register_nor(struct physmap_flash_data *data)
 +{
-+	lq_nor.dev.platform_data = data;
-+	platform_device_register(&lq_nor);
++	ltq_nor.dev.platform_data = data;
++	platform_device_register(&ltq_nor);
 +}
 +
 +/* spi flash */
-+static struct resource lq_spi_resources[] = {
++static struct resource ltq_spi_resources[] = {
 +	MEM_RES("ebu", GPON_EBU_BASE, GPON_EBU_END),
 +	MEM_RES("sys1", GPON_SYS1_BASE, GPON_SYS1_END)
 +};
 +
-+static struct platform_device lq_spi = {
++static struct platform_device ltq_spi = {
 +	.name			= "falcon_spi",
-+	.resource		= lq_spi_resources,
-+	.num_resources		= ARRAY_SIZE(lq_spi_resources)
++	.resource		= ltq_spi_resources,
++	.num_resources		= ARRAY_SIZE(ltq_spi_resources)
 +};
 +
 +void __init falcon_register_spi_flash(struct spi_board_info *data)
 +{
 +	spi_register_board_info(data, 1);
-+	platform_device_register(&lq_spi);
++	platform_device_register(&ltq_spi);
 +}
 +
 +/* watchdog */
@@ -187,7 +189,7 @@
 +
 +void __init falcon_register_wdt(void)
 +{
-+	platform_device_register_simple("lq_wdt", 0, &falcon_wdt_resource, 1);
++	platform_device_register_simple("ltq_wdt", 0, &falcon_wdt_resource, 1);
 +}
 +
 +/* gpio */
@@ -248,7 +250,7 @@
 +
 +void __init falcon_register_crypto(void)
 +{
-+	platform_device_register_simple("lq_falcon_deu", 0, NULL, 0);
++	platform_device_register_simple("ltq_falcon_deu", 0, NULL, 0);
 +}
 --- /dev/null
 +++ b/arch/mips/lantiq/falcon/devices.h
@@ -276,7 +278,7 @@
 +#endif
 --- /dev/null
 +++ b/arch/mips/lantiq/falcon/prom.c
-@@ -0,0 +1,44 @@
+@@ -0,0 +1,52 @@
 +/*
 + * 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
@@ -291,6 +293,8 @@
 +#include <asm/bootinfo.h>
 +#include <asm/time.h>
 +
++#include <lantiq_soc.h>
++
 +#include <falcon.h>
 +
 +#include <falcon/gpon_reg_base.h>
@@ -304,10 +308,16 @@
 +#define SOC_FALCON		"Falcon"
 +
 +void __init
-+lq_soc_detect(struct lq_soc_info *i)
++ltq_soc_setup(void)
++{
++	/* not used */
++}
++
++void __init
++ltq_soc_detect(struct ltq_soc_info *i)
 +{
-+	i->partnum = (lq_r32(&pSTATUS->chipid) & STATUS_CHIPID_PARTNR_MASK) >> STATUS_CHIPID_PARTNR_OFFSET;
-+	i->rev = (lq_r32(&pSTATUS->chipid) & STATUS_CHIPID_VERSION_MASK) >> STATUS_CHIPID_VERSION_OFFSET;
++	i->partnum = (ltq_r32(&pSTATUS->chipid) & STATUS_CHIPID_PARTNR_MASK) >> STATUS_CHIPID_PARTNR_OFFSET;
++	i->rev = (ltq_r32(&pSTATUS->chipid) & STATUS_CHIPID_VERSION_MASK) >> STATUS_CHIPID_VERSION_OFFSET;
 +	switch (i->partnum)
 +	{
 +	case SOC_ID_FALCON:
@@ -1173,7 +1183,7 @@
 +module_exit(falcon_gpio_exit);
 --- /dev/null
 +++ b/arch/mips/include/asm/mach-lantiq/falcon/falcon.h
-@@ -0,0 +1,30 @@
+@@ -0,0 +1,16 @@
 +/*
 + *   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
@@ -1184,29 +1194,15 @@
 + *   Copyright (C) 2010 John Crispin <[email protected]>
 + */
 +
-+#ifdef CONFIG_SOC_LANTIQ_FALCON
++#ifdef CONFIG_SOC_FALCON
 +
-+#ifndef _LQ_FALCON_H__
-+#define _LQ_FALCON_H__
-+
-+#include <lantiq.h>
++#include <lantiq_soc.h>
 +#include <falcon/gpon_reg_base.h>
 +
-+/*------------ GENERAL */
-+#define BOARD_SYSTEM_TYPE		"LANTIQ"
-+
-+/*------------ Chip IDs */
-+#define SOC_ID_FALCON		0x01B8
-+
-+/*------------ SoC Types */
-+#define SOC_TYPE_FALCON		0x01
-+
-+#endif
-+
 +#endif
 --- /dev/null
 +++ b/arch/mips/lantiq/falcon/reset.c
-@@ -0,0 +1,72 @@
+@@ -0,0 +1,80 @@
 +/*
 + * 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
@@ -1220,6 +1216,7 @@
 +#include <linux/io.h>
 +#include <linux/pm.h>
 +#include <asm/reboot.h>
++#include <linux/module.h>
 +
 +#include <falcon.h>
 +#include <falcon/gpon_reg_base.h>
@@ -1232,18 +1229,25 @@
 +#define WDT_PW2			0x00DC0000
 +#define WDT_REG_BASE		(KSEG1 | 0x1F8803F0)
 +
++/* This function is used by the watchdog driver */
++int ltq_reset_cause(void)
++{
++	return 0;
++}
++EXPORT_SYMBOL_GPL(ltq_reset_cause);
++
 +static void
-+lq_machine_restart(char *command)
++ltq_machine_restart(char *command)
 +{
 +	printk(KERN_NOTICE "System restart\n");
 +	local_irq_disable();
-+	lq_w32(0, (void*)0xBF200000); /* reset Bootreg RVEC */
++	ltq_w32(0, (void*)0xBF200000); /* reset Bootreg RVEC */
 +#if 0
-+	lq_w32(RBT_CPU_TRIG, &pSYS1->rbt);
++	ltq_w32(RBT_CPU_TRIG, &pSYS1->rbt);
 +#else
 +	/* use workaround via watchdog timer */
-+	lq_w32(WDT_PW1, (void*)WDT_REG_BASE);
-+	lq_w32(WDT_PW2 |
++	ltq_w32(WDT_PW1, (void*)WDT_REG_BASE);
++	ltq_w32(WDT_PW2 |
 +		(0x3 << 26) | /* PWL */
 +		(0x2 << 24) | /* CLKDIV */
 +		(0x1 << 31) | /* enable */
@@ -1254,7 +1258,7 @@
 +}
 +
 +static void
-+lq_machine_halt(void)
++ltq_machine_halt(void)
 +{
 +	printk(KERN_NOTICE "System halted.\n");
 +	local_irq_disable();
@@ -1262,7 +1266,7 @@
 +}
 +
 +static void
-+lq_machine_power_off(void)
++ltq_machine_power_off(void)
 +{
 +	printk(KERN_NOTICE "Please turn off the power now.\n");
 +	local_irq_disable();
@@ -1272,16 +1276,16 @@
 +static int __init
 +mips_reboot_setup(void)
 +{
-+	_machine_restart = lq_machine_restart;
-+	_machine_halt = lq_machine_halt;
-+	pm_power_off = lq_machine_power_off;
++	_machine_restart = ltq_machine_restart;
++	_machine_halt = ltq_machine_halt;
++	pm_power_off = ltq_machine_power_off;
 +	return 0;
 +}
 +
 +arch_initcall(mips_reboot_setup);
 --- /dev/null
 +++ b/arch/mips/lantiq/falcon/mach-easy98000.c
-@@ -0,0 +1,246 @@
+@@ -0,0 +1,247 @@
 +#include <linux/init.h>
 +#include <linux/platform_device.h>
 +#include <linux/leds.h>
@@ -1299,7 +1303,8 @@
 +#include <linux/spi/spi.h>
 +#include <linux/spi/spi_gpio.h>
 +#include <linux/spi/eeprom.h>
-+#include <machine.h>
++
++#include "../machtypes.h"
 +
 +#include "devices.h"
 +#include "dev-leds-gpio.h"
@@ -1311,7 +1316,7 @@
 +#define EASY98000_GPIO_LED_4 13
 +#define EASY98000_GPIO_LED_5 14
 +
-+extern unsigned char lq_ethaddr[6];
++extern unsigned char ltq_ethaddr[6];
 +
 +#ifdef CONFIG_MTD_PARTITIONS
 +static struct mtd_partition easy98000_nor_partitions[] =
@@ -1420,10 +1425,10 @@
 +
 +static void __init register_davicom(void)
 +{
-+	if (!is_valid_ether_addr(lq_ethaddr))
++	if (!is_valid_ether_addr(ltq_ethaddr))
 +		random_ether_addr(dm9000_plat_data.dev_addr);
 +	else {
-+		memcpy(dm9000_plat_data.dev_addr, lq_ethaddr, 6);
++		memcpy(dm9000_plat_data.dev_addr, ltq_ethaddr, 6);
 +		/* change to "Locally Administered Address" */
 +		dm9000_plat_data.dev_addr[0] |= 0x2;
 +	}
@@ -1500,7 +1505,7 @@
 +	falcon_register_i2c();
 +	platform_device_register(&easy98000_i2c_gpio_device);
 +	register_davicom();
-+	lq_add_device_leds_gpio(-1, ARRAY_SIZE(easy98000_leds_gpio),
++	ltq_add_device_leds_gpio(-1, ARRAY_SIZE(easy98000_leds_gpio),
 +					easy98000_leds_gpio);
 +	register_easy98000_cpld_led();
 +	falcon_register_crypto();
@@ -1689,49 +1694,44 @@
 +#endif
 --- a/arch/mips/lantiq/Kconfig
 +++ b/arch/mips/lantiq/Kconfig
-@@ -21,16 +21,16 @@ choice
- 	prompt "SoC Type"
- 	default SOC_LANTIQ_XWAY
- 
--#config SOC_LANTIQ_FALCON
--#	bool "FALCON"
--#	select SOC_LANTIQ
-+config SOC_LANTIQ_FALCON
-+	bool "FALCON"
-+	select SOC_LANTIQ
- 
- config SOC_LANTIQ_XWAY
+@@ -16,8 +16,12 @@
  	bool "XWAY"
- 	select SOC_LANTIQ
+ 	select SOC_TYPE_XWAY
+ 	select HW_HAS_PCI
++
++config SOC_FALCON
++	bool "FALCON"
  endchoice
  
--#source "arch/mips/lantiq/falcon/Kconfig"
-+source "arch/mips/lantiq/falcon/Kconfig"
  source "arch/mips/lantiq/xway/Kconfig"
++source "arch/mips/lantiq/falcon/Kconfig"
  
- if EARLY_PRINTK
---- a/arch/mips/include/asm/mach-lantiq/machine.h
-+++ b/arch/mips/include/asm/mach-lantiq/machine.h
-@@ -5,6 +5,7 @@ enum lantiq_mach_type {
- 
- 	/* FALCON */
- 	LANTIQ_MACH_EASY98000,		/* Falcon Eval Board, NOR Flash */
-+	LANTIQ_MACH_EASY98000SF,	/* Falcon Eval Board, Serial Flash */
- 	LANTIQ_MACH_EASY98020,		/* Falcon Reference Board */
- 
- 	/* XWAY */
+ endif
 --- a/arch/mips/lantiq/Makefile
 +++ b/arch/mips/lantiq/Makefile
-@@ -1,3 +1,4 @@
- obj-y := dev-leds-gpio.o irq.o setup.o clk.o prom.o
+@@ -9,3 +9,4 @@
  obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
-+obj-$(CONFIG_SOC_LANTIQ_FALCON) += falcon/
- obj-$(CONFIG_SOC_LANTIQ_XWAY) += xway/
+ 
+ obj-$(CONFIG_SOC_TYPE_XWAY) += xway/
++obj-$(CONFIG_SOC_FALCON) += falcon/
 --- a/arch/mips/lantiq/Platform
 +++ b/arch/mips/lantiq/Platform
-@@ -5,4 +5,5 @@
- platform-$(CONFIG_LANTIQ)      += lantiq/
- cflags-$(CONFIG_LANTIQ)       += -I$(srctree)/arch/mips/include/asm/mach-lantiq
- load-$(CONFIG_LANTIQ)          = 0xffffffff80002000
-+cflags-$(CONFIG_SOC_LANTIQ_FALCON) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon
- cflags-$(CONFIG_SOC_LANTIQ_XWAY) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway
+@@ -6,3 +6,4 @@
+ 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_FALCON)	+= -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon
+--- a/arch/mips/lantiq/machtypes.h
++++ b/arch/mips/lantiq/machtypes.h
+@@ -15,6 +15,11 @@
+ 	LTQ_MACH_GENERIC = 0,
+ 	LTQ_MACH_EASY50712,	/* Danube evaluation board */
+ 	LTQ_MACH_EASY50601,	/* Amazon SE evaluation board */
++
++	/* FALCON */
++	LANTIQ_MACH_EASY98000,		/* Falcon Eval Board, NOR Flash */
++	LANTIQ_MACH_EASY98000SF,	/* Falcon Eval Board, Serial Flash */
++	LANTIQ_MACH_EASY98020,		/* Falcon Reference Board */
+ };
+ 
+ #endif

+ 4 - 3
target/linux/lantiq/patches/910-falcon-i2c.patch → target/linux/lantiq/patches-2.6.32/120-falcon-i2c.patch

@@ -1,15 +1,16 @@
 --- a/drivers/i2c/busses/Makefile
 +++ b/drivers/i2c/busses/Makefile
-@@ -76,5 +76,6 @@
+@@ -74,6 +74,7 @@
  obj-$(CONFIG_I2C_STUB)		+= i2c-stub.o
  obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o
  obj-$(CONFIG_SCx200_I2C)	+= scx200_i2c.o
 +obj-$(CONFIG_I2C_FALCON)	+= i2c-falcon.o
  
- ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
+ ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
+ EXTRA_CFLAGS += -DDEBUG
 --- a/drivers/i2c/busses/Kconfig
 +++ b/drivers/i2c/busses/Kconfig
-@@ -281,6 +281,10 @@
+@@ -278,6 +278,10 @@
  
  comment "I2C system bus drivers (mostly embedded / system-on-chip)"
  

+ 9 - 9
target/linux/lantiq/patches/915-falcon-spi-flash.patch → target/linux/lantiq/patches-2.6.32/130-falcon-spi-flash.patch

@@ -1,9 +1,9 @@
 --- a/drivers/spi/Makefile
 +++ b/drivers/spi/Makefile
-@@ -22,6 +22,7 @@ obj-$(CONFIG_SPI_DESIGNWARE)		+= dw_spi.
- obj-$(CONFIG_SPI_DW_PCI)		+= dw_spi_pci.o
- obj-$(CONFIG_SPI_DW_MMIO)		+= dw_spi_mmio.o
- obj-$(CONFIG_SPI_EP93XX)		+= ep93xx_spi.o
+@@ -16,6 +16,7 @@
+ obj-$(CONFIG_SPI_BITBANG)		+= spi_bitbang.o
+ obj-$(CONFIG_SPI_AU1550)		+= au1550_spi.o
+ obj-$(CONFIG_SPI_BUTTERFLY)		+= spi_butterfly.o
 +obj-$(CONFIG_SPI_FALCON)		+= spi_falcon.o
  obj-$(CONFIG_SPI_GPIO)			+= spi_gpio.o
  obj-$(CONFIG_SPI_GPIO_OLD)		+= spi_gpio_old.o
@@ -484,14 +484,14 @@
 +MODULE_DESCRIPTION("Lantiq Falcon SPI controller driver");
 --- a/drivers/spi/Kconfig
 +++ b/drivers/spi/Kconfig
-@@ -169,6 +169,10 @@ config SPI_LM70_LLP
+@@ -142,6 +142,10 @@
  	  which interfaces to an LM70 temperature sensor using
  	  a parallel port.
  
 +config SPI_FALCON
 +	tristate "Falcon SPI controller support"
-+	depends on SOC_LANTIQ_FALCON
++	depends on SOC_FALCON
 +
- config SPI_MPC52xx
- 	tristate "Freescale MPC52xx SPI (non-PSC) controller support"
- 	depends on PPC_MPC52xx && SPI
+ config SPI_MPC52xx_PSC
+ 	tristate "Freescale MPC52xx PSC SPI controller"
+ 	depends on PPC_MPC52xx && EXPERIMENTAL

+ 4 - 4
target/linux/lantiq/patches/920-falcon-easy98000-cpld-led.patch → target/linux/lantiq/patches-2.6.32/140-falcon-easy98000-cpld-led.patch

@@ -44,8 +44,8 @@
 +#define cpld_base7			((u16 *)(KSEG1 | 0x17c0000c))
 +#define cpld_base8			((u16 *)(KSEG1 | 0x17c00012))
 +
-+#define lq_r16(reg)			__raw_readw(reg)
-+#define lq_w16(val, reg)		__raw_writew(val, reg)
++#define ltq_r16(reg)			__raw_readw(reg)
++#define ltq_w16(val, reg)		__raw_writew(val, reg)
 +
 +struct cpld_led_dev {
 +	struct led_classdev	cdev;
@@ -60,12 +60,12 @@
 +
 +void led_set(u8 mask, u16 *base)
 +{
-+	lq_w16(lq_r16(base) | mask, base);
++	ltq_w16(ltq_r16(base) | mask, base);
 +}
 +
 +void led_clear(u8 mask, u16 *base)
 +{
-+	lq_w16(lq_r16(base) & (~mask), base);
++	ltq_w16(ltq_r16(base) & (~mask), base);
 +}
 +
 +void led_blink_clear(u8 mask, u16 *base)

+ 5 - 5
target/linux/lantiq/patches/920-falcon-easy98020.patch → target/linux/lantiq/patches-2.6.32/150-falcon-easy98020.patch

@@ -12,7 +12,7 @@
 +#include <linux/interrupt.h>
 +#include <linux/spi/spi.h>
 +#include <linux/spi/flash.h>
-+#include <machine.h>
++#include "../machtypes.h"
 +
 +#include "devices.h"
 +#include "dev-leds-gpio.h"
@@ -22,7 +22,7 @@
 +#define EASY98020_GPIO_LED_2 11
 +#define EASY98020_GPIO_LED_3 12
 +
-+extern unsigned char lq_ethaddr[6];
++extern unsigned char ltq_ethaddr[6];
 +
 +#ifdef CONFIG_MTD_PARTITIONS
 +static struct mtd_partition easy98020_spi_partitions[] =
@@ -89,7 +89,7 @@
 +	falcon_register_wdt();
 +	falcon_register_i2c();
 +	falcon_register_spi_flash(&easy98020_spi_flash_data);
-+	lq_add_device_leds_gpio(-1, ARRAY_SIZE(easy98020_leds_gpio),
++	ltq_add_device_leds_gpio(-1, ARRAY_SIZE(easy98020_leds_gpio),
 +					easy98020_leds_gpio);
 +	falcon_register_crypto();
 +}
@@ -100,7 +100,7 @@
 +			easy98020_init);
 --- a/arch/mips/lantiq/falcon/Kconfig
 +++ b/arch/mips/lantiq/falcon/Kconfig
-@@ -6,6 +6,10 @@ config LANTIQ_MACH_EASY98000
+@@ -6,6 +6,10 @@
  	bool "Easy98000"
  	default y
  
@@ -113,7 +113,7 @@
  endif
 --- a/arch/mips/lantiq/falcon/Makefile
 +++ b/arch/mips/lantiq/falcon/Makefile
-@@ -2,3 +2,4 @@ obj-y := clk-falcon.o devices.o gpio.o p
+@@ -2,3 +2,4 @@
  obj-y += softdog_vpe.o
  obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o
  obj-$(CONFIG_LANTIQ_MACH_EASY98000) += dev-leds-easy98000-cpld.o

+ 15 - 15
target/linux/lantiq/patches/930-falcon-95C3AM1.patch → target/linux/lantiq/patches-2.6.32/160-falcon-95C3AM1.patch

@@ -4,7 +4,7 @@
 +#include <linux/init.h>
 +#include <linux/platform_device.h>
 +#include <linux/i2c-gpio.h>
-+#include <machine.h>
++#include "../machtypes.h"
 +
 +#include "devices.h"
 +#include "dev-leds-gpio.h"
@@ -14,7 +14,7 @@
 +#define BOARD_95C3AM1_GPIO_LED_2 12
 +#define BOARD_95C3AM1_GPIO_LED_3 13
 +
-+extern unsigned char lq_ethaddr[6];
++extern unsigned char ltq_ethaddr[6];
 +
 +#ifdef CONFIG_MTD_PARTITIONS
 +static struct mtd_partition board_95C3AM1_partitions[] =
@@ -95,7 +95,7 @@
 +	falcon_register_i2c();
 +	falcon_register_spi_flash(&board_95C3AM1_flash_data);
 +	platform_device_register(&board_95C3AM1_i2c_gpio_device);
-+	lq_add_device_leds_gpio(-1, ARRAY_SIZE(board_95C3AM1_leds_gpio),
++	ltq_add_device_leds_gpio(-1, ARRAY_SIZE(board_95C3AM1_leds_gpio),
 +						board_95C3AM1_leds_gpio);
 +	falcon_register_crypto();
 +}
@@ -104,19 +104,9 @@
 +			"95C3AM1",
 +			"95C3AM1 Board",
 +			board_95C3AM1_init);
---- a/arch/mips/include/asm/mach-lantiq/machine.h
-+++ b/arch/mips/include/asm/mach-lantiq/machine.h
-@@ -7,6 +7,7 @@ enum lantiq_mach_type {
- 	LANTIQ_MACH_EASY98000,		/* Falcon Eval Board, NOR Flash */
- 	LANTIQ_MACH_EASY98000SF,	/* Falcon Eval Board, Serial Flash */
- 	LANTIQ_MACH_EASY98020,		/* Falcon Reference Board */
-+	LANTIQ_MACH_95C3AM1,		/* Board 95C3AM1 */
- 
- 	/* XWAY */
- 	LANTIQ_MACH_EASY4010,		/* Twinpass evalkit */
 --- a/arch/mips/lantiq/falcon/Kconfig
 +++ b/arch/mips/lantiq/falcon/Kconfig
-@@ -10,6 +10,10 @@ config LANTIQ_MACH_EASY98020
+@@ -10,6 +10,10 @@
  	bool "Easy98020"
  	default y
  
@@ -129,8 +119,18 @@
  endif
 --- a/arch/mips/lantiq/falcon/Makefile
 +++ b/arch/mips/lantiq/falcon/Makefile
-@@ -3,3 +3,4 @@ obj-y += softdog_vpe.o
+@@ -3,3 +3,4 @@
  obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o
  obj-$(CONFIG_LANTIQ_MACH_EASY98000) += dev-leds-easy98000-cpld.o
  obj-$(CONFIG_LANTIQ_MACH_EASY98020) += mach-easy98020.o
 +obj-$(CONFIG_LANTIQ_MACH_95C3AM1)   += mach-95C3AM1.o
+--- a/arch/mips/lantiq/machtypes.h
++++ b/arch/mips/lantiq/machtypes.h
+@@ -20,6 +20,7 @@
+ 	LANTIQ_MACH_EASY98000,		/* Falcon Eval Board, NOR Flash */
+ 	LANTIQ_MACH_EASY98000SF,	/* Falcon Eval Board, Serial Flash */
+ 	LANTIQ_MACH_EASY98020,		/* Falcon Reference Board */
++	LANTIQ_MACH_95C3AM1,		/* Board 95C3AM1 */
+ };
+ 
+ #endif

+ 130 - 161
target/linux/lantiq/patches/400-mach-arv45xx.patch → target/linux/lantiq/patches-2.6.32/200-mach-arv45xx.patch

@@ -1,25 +1,7 @@
---- a/arch/mips/include/asm/mach-lantiq/machine.h
-+++ b/arch/mips/include/asm/mach-lantiq/machine.h
-@@ -11,4 +11,15 @@
- 	LANTIQ_MACH_EASY4010,		/* Twinpass evalkit */
- 	LANTIQ_MACH_EASY50712,		/* Danube evalkit */
- 	LANTIQ_MACH_EASY50812,		/* AR9 eval board */
-+
-+	/* Arcadyan */
-+	LANTIQ_MACH_ARV3527P,		/* Arcor easybox a401 */
-+	LANTIQ_MACH_ARV4510PW,		/* Wippies Homebox */
-+	LANTIQ_MACH_ARV4518PW,		/* Airties WAV-221, SMC-7908A-ISP */
-+	LANTIQ_MACH_ARV4520PW,		/* Airties WAV-281, Arcor EasyboxA800 */
-+	LANTIQ_MACH_ARV452CPW,		/* Arcor EasyboxA801 */
-+	LANTIQ_MACH_ARV4525PW,		/* Speedport W502V */
-+	LANTIQ_MACH_ARV752DPW,		/* Arcor easybox a802 */
-+	LANTIQ_MACH_ARV752DPW22,	/* Arcor easybox a803 */
-+	LANTIQ_MACH_ARV7518PW,		/* ASTORIA */
- };
 --- a/arch/mips/lantiq/xway/Kconfig
 +++ b/arch/mips/lantiq/xway/Kconfig
-@@ -14,6 +14,10 @@
- 	bool "Easy4010"
+@@ -6,6 +6,10 @@
+ 	bool "Easy50712 - Danube"
  	default y
  
 +config LANTIQ_MACH_ARV45XX
@@ -31,14 +13,14 @@
  endif
 --- a/arch/mips/lantiq/xway/Makefile
 +++ b/arch/mips/lantiq/xway/Makefile
-@@ -3,3 +3,4 @@
- obj-$(CONFIG_LANTIQ_MACH_EASY50812) += mach-easy50812.o
+@@ -5,3 +5,4 @@
+ 
  obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
- obj-$(CONFIG_LANTIQ_MACH_EASY4010) += mach-easy4010.o
+ obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
 +obj-$(CONFIG_LANTIQ_MACH_ARV45XX) += mach-arv45xx.o
 --- /dev/null
 +++ b/arch/mips/lantiq/xway/mach-arv45xx.c
-@@ -0,0 +1,537 @@
+@@ -0,0 +1,504 @@
 +/*
 + *  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
@@ -60,12 +42,12 @@
 +#include <linux/ath5k_platform.h>
 +#include <linux/pci.h>
 +
-+#include <machine.h>
-+
-+#include <xway.h>
++#include <lantiq_soc.h>
 +#include <lantiq_platform.h>
 +
++#include "../machtypes.h"
 +#include "devices.h"
++#include "dev-leds-gpio.h"
 +#include "dev-dwc_otg.h"
 +
 +#ifdef CONFIG_MTD_PARTITIONS
@@ -164,17 +146,16 @@
 +#endif
 +};
 +
-+static struct lq_pci_data lq_pci_data = {
-+	.clock      = PCI_CLOCK_EXT,
++static struct ltq_pci_data ltq_pci_data = {
++	.clock  = PCI_CLOCK_EXT,
 +	.gpio   = PCI_GNT1 | PCI_REQ1,
 +	.irq    = {
 +		[14] = INT_NUM_IM0_IRL0 + 22,
 +	},
 +};
 +
-+static struct lq_eth_data lq_eth_data = {
-+	.mii_mode	= REV_MII_MODE,
-+	.mac		= "\xff\xff\xff\xff\xff\xff",
++static struct ltq_eth_data ltq_eth_data = {
++	.mii_mode	= PHY_INTERFACE_MODE_RMII,
 +};
 +
 +static struct gpio_led
@@ -191,10 +172,10 @@
 +	{ .name = "soc:yellow:wps", .gpio = 7, .active_low = 1, .default_trigger = "default-on" },
 +	{ .name = "soc:red:fail", .gpio = 8, .active_low = 1, .default_trigger = "default-on" },
 +	{ .name = "soc:green:usb", .gpio = 19, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:green:voip", .gpio = 32, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:green:fxs1", .gpio = 33, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:green:fxs2", .gpio = 34, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:green:fxo", .gpio = 35, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:green:voip", .gpio = 72, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:green:fxs1", .gpio = 73, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:green:fxs2", .gpio = 74, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:green:fxo", .gpio = 75, .active_low = 1, .default_trigger = "default-on" },
 +};
 +
 +static struct gpio_button
@@ -212,13 +193,13 @@
 +	{ .name = "soc:red:power", .gpio = 6, .active_low = 1, },
 +	{ .name = "soc:yellow:wps", .gpio = 7, .active_low = 1, },
 +	{ .name = "soc:red:wps", .gpio = 9, .active_low = 1, },
-+	{ .name = "soc:blue:voip", .gpio = 32, .active_low = 1, },
-+	{ .name = "soc:blue:fxs1", .gpio = 33, .active_low = 1, },
-+	{ .name = "soc:blue:fxs2", .gpio = 34, .active_low = 1, },
-+	{ .name = "soc:blue:fxo", .gpio = 35, .active_low = 1, },
-+	{ .name = "soc:blue:voice", .gpio = 36, .active_low = 1, },
-+	{ .name = "soc:blue:usb", .gpio = 37, .active_low = 1, },
-+	{ .name = "soc:blue:wlan", .gpio = 38, .active_low = 1, },
++	{ .name = "soc:blue:voip", .gpio = 72, .active_low = 1, },
++	{ .name = "soc:blue:fxs1", .gpio = 73, .active_low = 1, },
++	{ .name = "soc:blue:fxs2", .gpio = 74, .active_low = 1, },
++	{ .name = "soc:blue:fxo", .gpio = 75, .active_low = 1, },
++	{ .name = "soc:blue:voice", .gpio = 76, .active_low = 1, },
++	{ .name = "soc:blue:usb", .gpio = 77, .active_low = 1, },
++	{ .name = "soc:blue:wlan", .gpio = 78, .active_low = 1, },
 +};
 +
 +static struct gpio_led
@@ -229,15 +210,15 @@
 +	{ .name = "soc:red:power", .gpio = 6, .active_low = 1, .default_trigger = "default-on" },
 +	{ .name = "soc:yellow:wps", .gpio = 7, .active_low = 1, .default_trigger = "default-on" },
 +	{ .name = "soc:red:wps", .gpio = 9, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:blue:fxs1", .gpio = 32, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:blue:fxs2", .gpio = 33, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:blue:wps", .gpio = 34, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:blue:fxo", .gpio = 35, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:blue:voice", .gpio = 36, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:blue:usb", .gpio = 37, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:blue:wlan", .gpio = 38, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:blue:internet", .gpio = 40, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:red:internet", .gpio = 41, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:blue:fxs1", .gpio = 72, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:blue:fxs2", .gpio = 73, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:blue:wps", .gpio = 74, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:blue:fxo", .gpio = 75, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:blue:voice", .gpio = 76, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:blue:usb", .gpio = 77, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:blue:wlan", .gpio = 78, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:blue:internet", .gpio = 80, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:red:internet", .gpio = 81, .active_low = 1, .default_trigger = "default-on" },
 +};
 +
 +static struct gpio_led
@@ -255,17 +236,17 @@
 +	{ .name = "soc:red:internet", .gpio = 5, .active_low = 1, .default_trigger = "default-on" },
 +	{ .name = "soc:red:power", .gpio = 6, .active_low = 1, .default_trigger = "default-on" },
 +	{ .name = "soc:red:wps", .gpio = 8, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:red:fxo", .gpio = 35, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:red:voice", .gpio = 36, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:green:usb", .gpio = 37, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:green:wlan", .gpio = 38, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:green:wlan1", .gpio = 39, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:blue:wlan", .gpio = 40, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:blue:wlan1", .gpio = 41, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:green:eth1", .gpio = 43, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:green:eth2", .gpio = 44, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:green:eth3", .gpio = 45, .active_low = 1, .default_trigger = "default-on" },
-+	{ .name = "soc:green:eth4", .gpio = 46, .active_low = 1, .default_trigger = "default-on", },
++	{ .name = "soc:red:fxo", .gpio = 75, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:red:voice", .gpio = 76, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:green:usb", .gpio = 77, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:green:wlan", .gpio = 78, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:green:wlan1", .gpio = 79, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:blue:wlan", .gpio = 80, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:blue:wlan1", .gpio = 81, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:green:eth1", .gpio = 83, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:green:eth2", .gpio = 84, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:green:eth3", .gpio = 85, .active_low = 1, .default_trigger = "default-on" },
++	{ .name = "soc:green:eth4", .gpio = 86, .active_low = 1, .default_trigger = "default-on", },
 +};
 +
 +static struct gpio_button
@@ -295,27 +276,27 @@
 +arv45xx_register_ethernet(void)
 +{
 +#define ARV45XX_BRN_MAC			0x3f0016
-+	memcpy_fromio(lq_eth_data.mac,
-+		(void *)KSEG1ADDR(LQ_FLASH_START + ARV45XX_BRN_MAC), 6);
-+	lq_register_ethernet(&lq_eth_data);
++	memcpy_fromio(&ltq_eth_data.mac,
++		(void *)KSEG1ADDR(LTQ_FLASH_START + ARV45XX_BRN_MAC), 6);
++	ltq_register_etop(&ltq_eth_data);
 +}
 +
 +static void
 +arv75xx_register_ethernet(void)
 +{
 +#define ARV75XX_BRN_MAC			0x7f0016
-+	memcpy_fromio(lq_eth_data.mac,
-+		(void *)KSEG1ADDR(LQ_FLASH_START + ARV75XX_BRN_MAC), 6);
-+	lq_register_ethernet(&lq_eth_data);
++	memcpy_fromio(&ltq_eth_data.mac,
++		(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(lq_eth_data.mac,
-+		(void *)KSEG1ADDR(LQ_FLASH_START + BEWAN_BRN_MAC), 6);
-+	lq_register_ethernet(&lq_eth_data);
++	memcpy_fromio(&ltq_eth_data.mac,
++		(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];
@@ -337,10 +318,10 @@
 +	u32 *p = (u32*)arv45xx_ath5k_eeprom_data;
 +
 +	memcpy_fromio(eeprom_mac,
-+		(void *)KSEG1ADDR(LQ_FLASH_START + ARV45XX_BRN_MAC), 6);
++		(void *)KSEG1ADDR(LTQ_FLASH_START + ARV45XX_BRN_MAC), 6);
 +	eeprom_mac[5]++;
 +	memcpy_fromio(arv45xx_ath5k_eeprom_data,
-+		(void *)KSEG1ADDR(LQ_FLASH_START + ARV45XX_BRN_ATH), ATH5K_PLAT_EEP_MAX_WORDS);
++		(void *)KSEG1ADDR(LTQ_FLASH_START + ARV45XX_BRN_ATH), 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);
@@ -356,19 +337,15 @@
 +	}
 +	arv45xx_ath5k_platform_data.eeprom_data = arv45xx_ath5k_eeprom_data;
 +	arv45xx_ath5k_platform_data.macaddr = eeprom_mac;
-+	lqpci_plat_dev_init = arv45xx_pci_plat_dev_init;
++	//lqpci_plat_dev_init = arv45xx_pci_plat_dev_init;
 +}
 +
 +static void __init
 +arv3527p_init(void)
 +{
-+	lq_register_gpio();
-+	lq_register_gpio_stp();
-+	//lq_register_gpio_leds(arv3527p_leds_gpio, ARRAY_SIZE(arv3527p_leds_gpio));
-+	lq_register_asc(0);
-+	lq_register_asc(1);
-+	lq_register_nor(&arv45xx_flash_data);
-+	lq_register_wdt();
++	ltq_register_gpio_stp();
++	//ltq_add_device_leds_gpio(arv3527p_leds_gpio, ARRAY_SIZE(arv3527p_leds_gpio));
++	ltq_register_nor(&arv45xx_flash_data);
 +	arv45xx_register_ethernet();
 +}
 +
@@ -380,17 +357,13 @@
 +static void __init
 +arv4510pw_init(void)
 +{
-+	lq_register_gpio();
-+	lq_register_gpio_stp();
-+	lq_register_gpio_leds(arv4510pw_leds_gpio, ARRAY_SIZE(arv4510pw_leds_gpio));
-+	lq_register_asc(0);
-+	lq_register_asc(1);
-+	lq_register_nor(&arv4510_flash_data);
-+	lq_pci_data.irq[12] = (INT_NUM_IM2_IRL0 + 31);
-+	lq_pci_data.irq[15] = (INT_NUM_IM0_IRL0 + 26);
-+	lq_pci_data.gpio |= PCI_EXIN2 | PCI_REQ2;
-+	lq_register_pci(&lq_pci_data);
-+	lq_register_wdt();
++	ltq_register_gpio_stp();
++	ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv4510pw_leds_gpio), arv4510pw_leds_gpio);
++	ltq_register_nor(&arv4510_flash_data);
++	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();
 +}
 +
@@ -406,17 +379,13 @@
 +#define ARV4518PW_USB			14
 +#define ARV4518PW_SWITCH_RESET		13
 +
-+	lq_register_gpio();
-+	lq_register_gpio_ebu(ARV4518PW_EBU);
-+	lq_register_gpio_leds(arv4518pw_leds_gpio, ARRAY_SIZE(arv4518pw_leds_gpio));
-+	lq_register_gpio_buttons(arv4518pw_gpio_buttons, ARRAY_SIZE(arv4518pw_gpio_buttons));
-+	lq_register_asc(0);
-+	lq_register_asc(1);
-+	lq_register_nor(&arv45xx_flash_data);
-+	lq_pci_data.gpio = PCI_GNT2 | PCI_REQ2;
-+	lq_register_pci(&lq_pci_data);
-+	lq_register_wdt();
-+	lq_register_madwifi_eep();
++	ltq_register_gpio_ebu(ARV4518PW_EBU);
++	ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv4518pw_leds_gpio), arv4518pw_leds_gpio);
++	ltq_register_gpio_buttons(arv4518pw_gpio_buttons, ARRAY_SIZE(arv4518pw_gpio_buttons));
++	ltq_register_nor(&arv45xx_flash_data);
++	ltq_pci_data.gpio = PCI_GNT2 | PCI_REQ2;
++	ltq_register_pci(&ltq_pci_data);
++	ltq_register_madwifi_eep();
 +	xway_register_dwc(ARV4518PW_USB);
 +	arv45xx_register_ethernet();
 +	arv45xx_register_ath5k();
@@ -436,17 +405,13 @@
 +{
 +#define ARV4520PW_EBU			0x400
 +#define ARV4520PW_USB			28
-+#define ARV4520PW_SWITCH_RESET		42
-+
-+	lq_register_gpio();
-+	lq_register_gpio_ebu(ARV4520PW_EBU);
-+	lq_register_gpio_leds(arv4520pw_leds_gpio, ARRAY_SIZE(arv4520pw_leds_gpio));
-+	lq_register_asc(0);
-+	lq_register_asc(1);
-+	lq_register_nor(&arv45xx_flash_data);
-+	lq_register_pci(&lq_pci_data);
-+	lq_register_wdt();
-+	lq_register_tapi();
++#define ARV4520PW_SWITCH_RESET		82
++
++	ltq_register_gpio_ebu(ARV4520PW_EBU);
++	ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv4520pw_leds_gpio), arv4520pw_leds_gpio);
++	ltq_register_nor(&arv45xx_flash_data);
++	ltq_register_pci(&ltq_pci_data);
++	ltq_register_tapi();
 +	arv45xx_register_ethernet();
 +	xway_register_dwc(ARV4520PW_USB);
 +
@@ -465,18 +430,14 @@
 +#define ARV452CPW_EBU			0x77f
 +#define ARV452CPW_USB			28
 +#define ARV452CPW_RELAY1		31
-+#define ARV452CPW_RELAY2		39
-+#define ARV452CPW_SWITCH_RESET		42
-+
-+	lq_register_gpio();
-+	lq_register_gpio_ebu(ARV452CPW_EBU);
-+	lq_register_gpio_leds(arv452cpw_leds_gpio, ARRAY_SIZE(arv452cpw_leds_gpio));
-+	lq_register_asc(0);
-+	lq_register_asc(1);
-+	lq_register_nor(&arv45xx_flash_data);
-+	lq_register_pci(&lq_pci_data);
-+	lq_register_wdt();
-+	lq_register_madwifi_eep();
++#define ARV452CPW_RELAY2		79
++#define ARV452CPW_SWITCH_RESET		82
++
++	ltq_register_gpio_ebu(ARV452CPW_EBU);
++	ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv452cpw_leds_gpio), arv452cpw_leds_gpio);
++	ltq_register_nor(&arv45xx_flash_data);
++	ltq_register_pci(&ltq_pci_data);
++	ltq_register_madwifi_eep();
 +	xway_register_dwc(ARV452CPW_USB);
 +	arv45xx_register_ethernet();
 +	arv45xx_register_ath5k();
@@ -502,16 +463,12 @@
 +static void __init
 +arv4525pw_init(void)
 +{
-+	lq_register_gpio();
-+	lq_register_gpio_leds(arv4525pw_leds_gpio, ARRAY_SIZE(arv4525pw_leds_gpio));
-+	lq_register_asc(0);
-+	lq_register_asc(1);
-+	lq_register_nor(&arv45xx_flash_data);
-+	lq_pci_data.clock = PCI_CLOCK_INT;
-+	lq_register_pci(&lq_pci_data);
-+	lq_register_wdt();
-+	lq_register_madwifi_eep();
-+	lq_eth_data.mii_mode = MII_MODE;
++	ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv4525pw_leds_gpio), arv4525pw_leds_gpio);
++	ltq_register_nor(&arv45xx_flash_data);
++	ltq_pci_data.clock = PCI_CLOCK_INT;
++	ltq_register_pci(&ltq_pci_data);
++	ltq_register_madwifi_eep();
++	ltq_eth_data.mii_mode = PHY_INTERFACE_MODE_MII;
 +	arv45xx_register_ethernet();
 +}
 +
@@ -526,16 +483,12 @@
 +#define ARV7518PW_EBU			0x2
 +#define ARV7518PW_USB			14
 +
-+	lq_register_gpio();
-+	lq_register_gpio_ebu(ARV7518PW_EBU);
-+	lq_register_asc(0);
-+	lq_register_asc(1);
-+	lq_register_gpio_leds(arv7518pw_leds_gpio, ARRAY_SIZE(arv7518pw_leds_gpio));
-+	lq_register_gpio_buttons(arv7518pw_gpio_buttons, ARRAY_SIZE(arv7518pw_gpio_buttons));
-+	lq_register_nor(&arv75xx_flash_data);
-+	lq_register_pci(&lq_pci_data);
-+	lq_register_wdt();
-+	lq_register_tapi();
++	ltq_register_gpio_ebu(ARV7518PW_EBU);
++	ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv7518pw_leds_gpio), arv7518pw_leds_gpio);
++	ltq_register_gpio_buttons(arv7518pw_gpio_buttons, ARRAY_SIZE(arv7518pw_gpio_buttons));
++	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);
@@ -550,20 +503,16 @@
 +arv752dpw22_init(void)
 +{
 +#define ARV752DPW22_EBU			0x2
-+#define ARV752DPW22_USB			32
-+#define ARV752DPW22_RELAY		33
-+
-+	lq_register_gpio();
-+	lq_register_gpio_ebu(ARV752DPW22_EBU);
-+	lq_register_asc(0);
-+	lq_register_asc(1);
-+	lq_register_gpio_leds(arv752dpw22_leds_gpio, ARRAY_SIZE(arv752dpw22_leds_gpio));
-+	lq_register_gpio_buttons(arv752dpw22_gpio_buttons, ARRAY_SIZE(arv752dpw22_gpio_buttons));
-+	lq_register_nor(&arv75xx_flash_data);
-+	lq_pci_data.irq[15] = (INT_NUM_IM2_IRL0 + 31);
-+	lq_pci_data.gpio |= PCI_EXIN1 | PCI_REQ2;
-+	lq_register_pci(&lq_pci_data);
-+	lq_register_wdt();
++#define ARV752DPW22_USB			72
++#define ARV752DPW22_RELAY		73
++
++	ltq_register_gpio_ebu(ARV752DPW22_EBU);
++	ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv752dpw22_leds_gpio), arv752dpw22_leds_gpio);
++	ltq_register_gpio_buttons(arv752dpw22_gpio_buttons, ARRAY_SIZE(arv752dpw22_gpio_buttons));
++	ltq_register_nor(&arv75xx_flash_data);
++	ltq_pci_data.irq[15] = (INT_NUM_IM2_IRL0 + 31);
++	ltq_pci_data.gpio |= PCI_EXIN1 | PCI_REQ2;
++	ltq_register_pci(&ltq_pci_data);
 +	xway_register_dwc(ARV752DPW22_USB);
 +	arv75xx_register_ethernet();
 +
@@ -576,3 +525,23 @@
 +			"ARV752DPW22",
 +			"ARV752DPW22 - Arcor A803",
 +			arv752dpw22_init);
+--- a/arch/mips/lantiq/machtypes.h
++++ b/arch/mips/lantiq/machtypes.h
+@@ -21,6 +21,17 @@
+ 	LANTIQ_MACH_EASY98000SF,	/* Falcon Eval Board, Serial Flash */
+ 	LANTIQ_MACH_EASY98020,		/* Falcon Reference Board */
+ 	LANTIQ_MACH_95C3AM1,		/* Board 95C3AM1 */
++
++	/* Arcadyan */
++	LANTIQ_MACH_ARV3527P,		/* Arcor easybox a401 */
++	LANTIQ_MACH_ARV4510PW,		/* Wippies Homebox */
++	LANTIQ_MACH_ARV4518PW,		/* Airties WAV-221, SMC-7908A-ISP */
++	LANTIQ_MACH_ARV4520PW,		/* Airties WAV-281, Arcor EasyboxA800 */
++	LANTIQ_MACH_ARV452CPW,		/* Arcor EasyboxA801 */
++	LANTIQ_MACH_ARV4525PW,		/* Speedport W502V */
++	LANTIQ_MACH_ARV752DPW,		/* Arcor easybox a802 */
++	LANTIQ_MACH_ARV752DPW22,	/* Arcor easybox a803 */
++	LANTIQ_MACH_ARV7518PW,		/* ASTORIA */
+ };
+ 
+ #endif

+ 3 - 3
target/linux/lantiq/patches/220-mtd_uimage_split.patch → target/linux/lantiq/patches-2.6.32/210-mtd_uimage_split.patch

@@ -1,6 +1,6 @@
 --- a/drivers/mtd/Kconfig
 +++ b/drivers/mtd/Kconfig
-@@ -63,6 +63,10 @@ config MTD_ROOTFS_SPLIT
+@@ -63,6 +63,10 @@
  	depends on MTD_PARTITIONS
  	default y
  
@@ -13,7 +13,7 @@
  	depends on MTD_PARTITIONS
 --- a/drivers/mtd/mtdpart.c
 +++ b/drivers/mtd/mtdpart.c
-@@ -722,6 +722,82 @@ static int refresh_rootfs_split(struct m
+@@ -724,6 +724,82 @@
  }
  #endif /* CONFIG_MTD_ROOTFS_SPLIT */
  
@@ -96,7 +96,7 @@
  /*
   * 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
-@@ -746,6 +822,17 @@ int add_mtd_partitions(struct mtd_info *
+@@ -748,6 +824,17 @@
  		if (!slave)
  			return -ENOMEM;
  

+ 42 - 0
target/linux/lantiq/patches-2.6.32/220-atm_hack.patch

@@ -0,0 +1,42 @@
+--- a/arch/mips/mm/cache.c
++++ b/arch/mips/mm/cache.c
+@@ -52,6 +52,8 @@
+ void (*_dma_cache_inv)(unsigned long start, unsigned long size);
+ 
+ EXPORT_SYMBOL(_dma_cache_wback_inv);
++EXPORT_SYMBOL(_dma_cache_wback);
++EXPORT_SYMBOL(_dma_cache_inv);
+ 
+ #endif /* CONFIG_DMA_NONCOHERENT */
+ 
+--- a/net/atm/proc.c
++++ b/net/atm/proc.c
+@@ -152,7 +152,7 @@
+ static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc)
+ {
+ 	static const char *const class_name[] =
+-		{"off","UBR","CBR","VBR","ABR"};
++		{"off","UBR","CBR","NTR-VBR","ABR","ANY","RT-VBR","UBR+","GFR"};
+ 	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
+@@ -57,11 +57,17 @@
+ }
+ 
+ 
++struct sk_buff* (*ifx_atm_alloc_tx)(struct atm_vcc *, unsigned int) = NULL;
++EXPORT_SYMBOL(ifx_atm_alloc_tx);
++
+ static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
+ {
+ 	struct sk_buff *skb;
+ 	struct sock *sk = sk_atm(vcc);
+ 
++	if (ifx_atm_alloc_tx != NULL)
++		return ifx_atm_alloc_tx(vcc, size);
++
+ 	if (sk_wmem_alloc_get(sk) && !atm_may_send(vcc, size)) {
+ 		pr_debug("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n",
+ 			sk_wmem_alloc_get(sk), size,

+ 45 - 0
target/linux/lantiq/patches-2.6.32/230-cmdline_hack.patch

@@ -0,0 +1,45 @@
+--- a/arch/mips/lantiq/prom.c
++++ b/arch/mips/lantiq/prom.c
+@@ -39,6 +39,34 @@
+ {
+ }
+ 
++#ifdef CONFIG_IMAGE_CMDLINE_HACK
++extern char __image_cmdline[];
++
++static void __init
++prom_init_image_cmdline(void)
++{
++	char *p = __image_cmdline;
++	int replace = 0;
++
++	if (*p == '-') {
++		replace = 1;
++		p++;
++	}
++
++	if (*p == '\0')
++		return;
++
++	if (replace) {
++		strlcpy(arcs_cmdline, p, sizeof(arcs_cmdline));
++	} else {
++		strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
++		strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
++	}
++}
++#else
++static void __init prom_init_image_cmdline(void) { return; }
++#endif
++
+ static void __init prom_init_cmdline(void)
+ {
+ 	int argc = fw_arg0;
+@@ -53,6 +81,7 @@
+ 			strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
+ 		}
+ 	}
++	prom_init_image_cmdline();
+ }
+ 
+ void __init prom_init(void)

+ 9 - 8
target/linux/lantiq/patches/300-udp_redirect.patch → target/linux/lantiq/patches-2.6.32/240-udp_redirect.patch

@@ -261,18 +261,19 @@
  obj-$(CONFIG_PROC_FS) += proc.o
 --- a/net/ipv4/udp.c
 +++ b/net/ipv4/udp.c
-@@ -107,6 +107,10 @@
+@@ -106,7 +106,11 @@
  #include <net/xfrm.h>
  #include "udp_impl.h"
  
 +#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
 +#include <linux/udp_redirect.h>
 +#endif
+ struct udp_table udp_table;
 +
- struct udp_table udp_table __read_mostly;
  EXPORT_SYMBOL(udp_table);
  
-@@ -784,7 +788,7 @@
+ int sysctl_udp_mem[3] __read_mostly;
+@@ -591,7 +595,7 @@
  	u8  tos;
  	int err, is_udplite = IS_UDPLITE(sk);
  	int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
@@ -281,7 +282,7 @@
  
  	if (len > 0xFFFF)
  		return -EMSGSIZE;
-@@ -946,6 +950,12 @@
+@@ -753,6 +757,12 @@
  
  do_append_data:
  	up->len += ulen;
@@ -294,7 +295,7 @@
  	getfrag  =  is_udplite ?  udplite_getfrag : ip_generic_getfrag;
  	err = ip_append_data(sk, getfrag, msg->msg_iov, ulen,
  			sizeof(struct udphdr), &ipc, &rt,
-@@ -1573,6 +1583,7 @@
+@@ -1283,6 +1293,7 @@
  	struct rtable *rt = skb_rtable(skb);
  	__be32 saddr, daddr;
  	struct net *net = dev_net(skb->dev);
@@ -302,7 +303,7 @@
  
  	/*
  	 *  Validate the packet.
-@@ -1605,7 +1616,16 @@
+@@ -1315,7 +1326,16 @@
  	sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
  
  	if (sk != NULL) {
@@ -320,8 +321,8 @@
  		sock_put(sk);
  
  		/* a return value > 0 means to resubmit the input, but
-@@ -1902,7 +1922,7 @@
- 	.clear_sk	   = sk_prot_clear_portaddr_nulls,
+@@ -1610,7 +1630,7 @@
+ #endif
  };
  EXPORT_SYMBOL(udp_prot);
 -

+ 1174 - 0
target/linux/lantiq/patches-2.6.32/250-mt-vpe.patch

@@ -0,0 +1,1174 @@
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -1646,6 +1646,28 @@
+ 	  Includes a loader for loading an elf relocatable object
+ 	  onto another VPE and running it.
+ 
++config IFX_VPE_EXT
++	bool "IFX APRP Extensions"
++	depends on MIPS_VPE_LOADER
++	default y
++	help
++	  IFX included extensions in APRP
++
++config PERFCTRS
++	bool "34K Performance counters"
++	depends on MIPS_MT && PROC_FS
++	default n
++	help
++	  34K Performance counter through /proc
++
++config MTSCHED
++	bool "Support mtsched priority configuration for TCs"
++	depends on MIPS_MT && PROC_FS
++	default y
++	help
++	  Support for mtsched priority configuration for TCs through
++	  /proc/mips/mtsched
++
+ config MIPS_MT_SMTC_IM_BACKSTOP
+ 	bool "Use per-TC register bits as backstop for inhibited IM bits"
+ 	depends on MIPS_MT_SMTC
+--- a/arch/mips/include/asm/mipsmtregs.h
++++ b/arch/mips/include/asm/mipsmtregs.h
+@@ -28,14 +28,34 @@
+ #define read_c0_vpeconf0()		__read_32bit_c0_register($1, 2)
+ #define write_c0_vpeconf0(val)		__write_32bit_c0_register($1, 2, val)
+ 
++#define read_c0_vpeconf1()              __read_32bit_c0_register($1, 3)
++#define write_c0_vpeconf1(val)          __write_32bit_c0_register($1, 3, val)
++
++#define read_c0_vpeschedule()           __read_32bit_c0_register($1, 5)
++#define write_c0_vpeschedule(val)       __write_32bit_c0_register($1, 5, val)
++
++#define read_c0_vpeschefback()      	__read_32bit_c0_register($1, 6)
++#define write_c0_vpeschefback(val)  	__write_32bit_c0_register($1, 6, val)
++
++#define read_c0_vpeopt()              __read_32bit_c0_register($1, 7)
++#define write_c0_vpeopt(val)          __write_32bit_c0_register($1, 7, val)
++
+ #define read_c0_tcstatus()		__read_32bit_c0_register($2, 1)
+ #define write_c0_tcstatus(val)		__write_32bit_c0_register($2, 1, val)
+ 
+ #define read_c0_tcbind()		__read_32bit_c0_register($2, 2)
++#define write_c0_tcbind(val)		__write_32bit_c0_register($2, 2, val)
+ 
+ #define read_c0_tccontext()		__read_32bit_c0_register($2, 5)
+ #define write_c0_tccontext(val)		__write_32bit_c0_register($2, 5, val)
+ 
++#define read_c0_tcschedule()		__read_32bit_c0_register($2, 6)
++#define write_c0_tcschedule(val)	__write_32bit_c0_register($2, 6, val)
++
++#define read_c0_tcschefback()		__read_32bit_c0_register($2, 7)
++#define write_c0_tcschefback(val)	__write_32bit_c0_register($2, 7, val)
++
++
+ #else /* Assembly */
+ /*
+  * Macros for use in assembly language code
+@@ -74,6 +94,8 @@
+ #define MVPCONTROL_STLB_SHIFT	2
+ #define MVPCONTROL_STLB		(_ULCAST_(1) << MVPCONTROL_STLB_SHIFT)
+ 
++#define MVPCONTROL_CPA_SHIFT	3
++#define MVPCONTROL_CPA		(_ULCAST_(1) << MVPCONTROL_CPA_SHIFT)
+ 
+ /* MVPConf0 fields */
+ #define MVPCONF0_PTC_SHIFT	0
+@@ -84,6 +106,8 @@
+ #define MVPCONF0_TCA		( _ULCAST_(1) << MVPCONF0_TCA_SHIFT)
+ #define MVPCONF0_PTLBE_SHIFT	16
+ #define MVPCONF0_PTLBE		(_ULCAST_(0x3ff) << MVPCONF0_PTLBE_SHIFT)
++#define MVPCONF0_PCP_SHIFT	27
++#define MVPCONF0_PCP		(_ULCAST_(1) << MVPCONF0_PCP_SHIFT)
+ #define MVPCONF0_TLBS_SHIFT	29
+ #define MVPCONF0_TLBS		(_ULCAST_(1) << MVPCONF0_TLBS_SHIFT)
+ #define MVPCONF0_M_SHIFT	31
+@@ -121,9 +145,25 @@
+ #define VPECONF0_VPA		(_ULCAST_(1) << VPECONF0_VPA_SHIFT)
+ #define VPECONF0_MVP_SHIFT	1
+ #define VPECONF0_MVP		(_ULCAST_(1) << VPECONF0_MVP_SHIFT)
++#define VPECONF0_ICS_SHIFT      16
++#define VPECONF0_ICS		(_ULCAST_(1) << VPECONF0_ICS_SHIFT)
++#define VPECONF0_DCS_SHIFT      17
++#define VPECONF0_DCS            (_ULCAST_(1) << VPECONF0_DCS_SHIFT)
+ #define VPECONF0_XTC_SHIFT	21
+ #define VPECONF0_XTC		(_ULCAST_(0xff) << VPECONF0_XTC_SHIFT)
+ 
++/* VPEOpt fields */
++#define VPEOPT_DWX_SHIFT	0
++#define VPEOPT_IWX_SHIFT	8
++#define VPEOPT_IWX0		( _ULCAST_(0x1) << VPEOPT_IWX_SHIFT)
++#define VPEOPT_IWX1		( _ULCAST_(0x2) << VPEOPT_IWX_SHIFT)
++#define VPEOPT_IWX2		( _ULCAST_(0x4) << VPEOPT_IWX_SHIFT)
++#define VPEOPT_IWX3		( _ULCAST_(0x8) << VPEOPT_IWX_SHIFT)
++#define VPEOPT_DWX0		( _ULCAST_(0x1) << VPEOPT_DWX_SHIFT)
++#define VPEOPT_DWX1		( _ULCAST_(0x2) << VPEOPT_DWX_SHIFT)
++#define VPEOPT_DWX2		( _ULCAST_(0x4) << VPEOPT_DWX_SHIFT)
++#define VPEOPT_DWX3		( _ULCAST_(0x8) << VPEOPT_DWX_SHIFT)
++
+ /* TCStatus fields (per TC) */
+ #define TCSTATUS_TASID		(_ULCAST_(0xff))
+ #define TCSTATUS_IXMT_SHIFT	10
+@@ -350,6 +390,14 @@
+ #define write_vpe_c0_vpecontrol(val)	mttc0(1, 1, val)
+ #define read_vpe_c0_vpeconf0()		mftc0(1, 2)
+ #define write_vpe_c0_vpeconf0(val)	mttc0(1, 2, val)
++#define read_vpe_c0_vpeschedule()	mftc0(1, 5)
++#define write_vpe_c0_vpeschedule(val)	mttc0(1, 5, val)
++#define read_vpe_c0_vpeschefback()	mftc0(1, 6)
++#define write_vpe_c0_vpeschefback(val)	mttc0(1, 6, val)
++#define read_vpe_c0_vpeopt()            mftc0(1, 7)
++#define write_vpe_c0_vpeopt(val)        mttc0(1, 7, val)
++#define read_vpe_c0_wired()		mftc0(6, 0)
++#define write_vpe_c0_wired(val)		mttc0(6, 0, val)
+ #define read_vpe_c0_count()		mftc0(9, 0)
+ #define write_vpe_c0_count(val)		mttc0(9, 0, val)
+ #define read_vpe_c0_status()		mftc0(12, 0)
+@@ -381,6 +429,12 @@
+ #define write_tc_c0_tchalt(val)		mttc0(2, 4, val)
+ #define read_tc_c0_tccontext()		mftc0(2, 5)
+ #define write_tc_c0_tccontext(val)	mttc0(2, 5, val)
++#define read_tc_c0_tcschedule()		mftc0(2, 6)
++#define write_tc_c0_tcschedule(val)	mttc0(2, 6, val)
++#define read_tc_c0_tcschefback()	mftc0(2, 7)
++#define write_tc_c0_tcschefback(val)	mttc0(2, 7, val)
++#define read_tc_c0_entryhi()            mftc0(10, 0)
++#define write_tc_c0_entryhi(val)        mttc0(10, 0, val)
+ 
+ /* GPR */
+ #define read_tc_gpr_sp()		mftgpr(29)
+--- a/arch/mips/kernel/Makefile
++++ b/arch/mips/kernel/Makefile
+@@ -78,7 +78,8 @@
+ 
+ obj-$(CONFIG_KGDB)		+= kgdb.o
+ obj-$(CONFIG_PROC_FS)		+= proc.o
+-
++obj-$(CONFIG_MTSCHED)		+= mtsched_proc.o
++obj-$(CONFIG_PERFCTRS)		+= perf_proc.o
+ obj-$(CONFIG_64BIT)		+= cpu-bugs64.o
+ 
+ obj-$(CONFIG_I8253)		+= i8253.o
+--- a/arch/mips/kernel/mips-mt.c
++++ b/arch/mips/kernel/mips-mt.c
+@@ -21,26 +21,96 @@
+ #include <asm/cacheflush.h>
+ 
+ int vpelimit;
+-
+ static int __init maxvpes(char *str)
+ {
+ 	get_option(&str, &vpelimit);
+-
+ 	return 1;
+ }
+-
+ __setup("maxvpes=", maxvpes);
+ 
+ int tclimit;
+-
+ static int __init maxtcs(char *str)
+ {
+ 	get_option(&str, &tclimit);
++	return 1;
++}
++__setup("maxtcs=", maxtcs);
+ 
++#ifdef CONFIG_IFX_VPE_EXT
++int stlb;
++static int __init istlbshared(char *str)
++{
++	get_option(&str, &stlb);
+ 	return 1;
+ }
++__setup("vpe_tlb_shared=", istlbshared);
+ 
+-__setup("maxtcs=", maxtcs);
++int vpe0_wired;
++static int __init vpe0wired(char *str)
++{
++	get_option(&str, &vpe0_wired);
++	return 1;
++}
++__setup("vpe0_wired_tlb_entries=", vpe0wired);
++
++int vpe1_wired;
++static int __init vpe1wired(char *str)
++{
++	get_option(&str, &vpe1_wired);
++	return 1;
++}
++__setup("vpe1_wired_tlb_entries=", vpe1wired);
++
++#ifdef CONFIG_MIPS_MT_SMTC
++extern int nostlb;
++#endif
++void configure_tlb(void)
++{
++	int vpeflags, tcflags, tlbsiz;
++	unsigned int config1val;
++	vpeflags = dvpe();
++	tcflags = dmt();
++	write_c0_vpeconf0((read_c0_vpeconf0() | VPECONF0_MVP));
++	write_c0_mvpcontrol((read_c0_mvpcontrol() | MVPCONTROL_VPC));
++	mips_ihb();
++	//printk("stlb = %d, vpe0_wired = %d vpe1_wired=%d\n", stlb,vpe0_wired, vpe1_wired);
++	if (stlb) {
++		if (!(read_c0_mvpconf0() & MVPCONF0_TLBS)) {
++			emt(tcflags);
++			evpe(vpeflags);
++			return;
++		}
++
++		write_c0_mvpcontrol(read_c0_mvpcontrol() | MVPCONTROL_STLB);
++		write_c0_wired(vpe0_wired + vpe1_wired);
++		if (((read_vpe_c0_config() & MIPS_CONF_MT) >> 7) == 1) {
++			config1val = read_vpe_c0_config1();
++			tlbsiz = (((config1val >> 25) & 0x3f) + 1);
++			if (tlbsiz > 64)
++				tlbsiz = 64;
++			cpu_data[0].tlbsize = tlbsiz;
++			current_cpu_data.tlbsize = tlbsiz;
++		}
++
++	}
++	else {
++		write_c0_mvpcontrol(read_c0_mvpcontrol() & ~MVPCONTROL_STLB);
++		write_c0_wired(vpe0_wired);
++	}
++
++	ehb();
++	write_c0_mvpcontrol((read_c0_mvpcontrol() & ~MVPCONTROL_VPC));
++	ehb();
++	local_flush_tlb_all();
++
++	printk("Wired TLB entries for Linux read_c0_wired() = %d\n", read_c0_wired());
++#ifdef CONFIG_MIPS_MT_SMTC
++	nostlb = !stlb;
++#endif
++	emt(tcflags);
++	evpe(vpeflags);
++}
++#endif
+ 
+ /*
+  * Dump new MIPS MT state for the core. Does not leave TCs halted.
+@@ -78,18 +148,18 @@
+ 			if ((read_tc_c0_tcbind() & TCBIND_CURVPE) == i) {
+ 				printk("  VPE %d\n", i);
+ 				printk("   VPEControl : %08lx\n",
+-				       read_vpe_c0_vpecontrol());
++					read_vpe_c0_vpecontrol());
+ 				printk("   VPEConf0 : %08lx\n",
+-				       read_vpe_c0_vpeconf0());
++					read_vpe_c0_vpeconf0());
+ 				printk("   VPE%d.Status : %08lx\n",
+-				       i, read_vpe_c0_status());
++					i, read_vpe_c0_status());
+ 				printk("   VPE%d.EPC : %08lx %pS\n",
+-				       i, read_vpe_c0_epc(),
+-				       (void *) read_vpe_c0_epc());
++					i, read_vpe_c0_epc(),
++					(void *) read_vpe_c0_epc());
+ 				printk("   VPE%d.Cause : %08lx\n",
+-				       i, read_vpe_c0_cause());
++					i, read_vpe_c0_cause());
+ 				printk("   VPE%d.Config7 : %08lx\n",
+-				       i, read_vpe_c0_config7());
++					i, read_vpe_c0_config7());
+ 				break; /* Next VPE */
+ 			}
+ 		}
+@@ -287,6 +357,9 @@
+ 		printk("Mapped %ld ITC cells starting at 0x%08x\n",
+ 			((itcblkgrn & 0x7fe00000) >> 20), itc_base);
+ 	}
++#ifdef CONFIG_IFX_VPE_EXT
++	configure_tlb();
++#endif
+ }
+ 
+ /*
+--- a/arch/mips/kernel/proc.c
++++ b/arch/mips/kernel/proc.c
+@@ -7,6 +7,7 @@
+ #include <linux/kernel.h>
+ #include <linux/sched.h>
+ #include <linux/seq_file.h>
++#include <linux/proc_fs.h>
+ #include <asm/bootinfo.h>
+ #include <asm/cpu.h>
+ #include <asm/cpu-features.h>
+@@ -108,3 +109,19 @@
+ 	.stop	= c_stop,
+ 	.show	= show_cpuinfo,
+ };
++
++/*
++ * Support for MIPS/local /proc hooks in /proc/mips/
++ */
++
++static struct proc_dir_entry *mips_proc = NULL;
++
++struct proc_dir_entry *get_mips_proc_dir(void)
++{
++       /*
++        * This ought not to be preemptable.
++        */
++       if(mips_proc == NULL)
++               mips_proc = proc_mkdir("mips", NULL);
++       return(mips_proc);
++}
+--- a/arch/mips/kernel/smtc.c
++++ b/arch/mips/kernel/smtc.c
+@@ -1328,6 +1328,13 @@
+ 	asid = asid_cache(cpu);
+ 
+ 	do {
++#ifdef CONFIG_IFX_VPE_EXT
++		/* If TLB is shared between AP and RP (AP is running SMTC),
++		   leave out max ASID i.e., ASID_MASK for RP
++		 */
++		if (!nostlb && ((asid & ASID_MASK) == (ASID_MASK - 1)))
++			asid++;
++#endif
+ 		if (!((asid += ASID_INC) & ASID_MASK) ) {
+ 			if (cpu_has_vtag_icache)
+ 				flush_icache_all();
+--- a/arch/mips/kernel/vpe.c
++++ b/arch/mips/kernel/vpe.c
+@@ -77,6 +77,58 @@
+ static int kspd_events_reqd;
+ #endif
+ 
++#ifdef CONFIG_IFX_VPE_EXT
++static int is_sdepgm;
++extern int stlb;
++extern int vpe0_wired;
++extern int vpe1_wired;
++unsigned int vpe1_load_addr;
++
++static int __init load_address(char *str)
++{
++	get_option(&str, &vpe1_load_addr);
++	return 1;
++}
++__setup("vpe1_load_addr=", load_address);
++
++#include <asm/mipsmtregs.h>
++#define write_vpe_c0_wired(val)		mttc0(6, 0, val)
++
++#ifndef COMMAND_LINE_SIZE
++#	define COMMAND_LINE_SIZE	512
++#endif
++
++char command_line[COMMAND_LINE_SIZE * 2];
++
++static unsigned int vpe1_mem;
++static int __init vpe1mem(char *str)
++{
++	vpe1_mem = memparse(str, &str);
++	return 1;
++}
++__setup("vpe1_mem=", vpe1mem);
++
++uint32_t vpe1_wdog_ctr;
++static int __init wdog_ctr(char *str)
++{
++	get_option(&str, &vpe1_wdog_ctr);
++	return 1;
++}
++
++__setup("vpe1_wdog_ctr_addr=", wdog_ctr);
++EXPORT_SYMBOL(vpe1_wdog_ctr);
++
++uint32_t vpe1_wdog_timeout;
++static int __init wdog_timeout(char *str)
++{
++        get_option(&str, &vpe1_wdog_timeout);
++        return 1;
++}
++
++__setup("vpe1_wdog_timeout=", wdog_timeout);
++EXPORT_SYMBOL(vpe1_wdog_timeout);
++
++#endif
+ /* grab the likely amount of memory we will need. */
+ #ifdef CONFIG_MIPS_VPE_LOADER_TOM
+ #define P_SIZE (2 * 1024 * 1024)
+@@ -269,6 +321,13 @@
+ 	void *addr;
+ 
+ #ifdef CONFIG_MIPS_VPE_LOADER_TOM
++#ifdef CONFIG_IFX_VPE_EXT
++	if (vpe1_load_addr) {
++		memset((void *)vpe1_load_addr, 0, len);
++		return (void *)vpe1_load_addr;
++	}
++#endif
++
+ 	/*
+ 	 * This means you must tell Linux to use less memory than you
+ 	 * physically have, for example by passing a mem= boot argument.
+@@ -747,6 +806,12 @@
+ 	}
+ 
+ 	/* Write the address we want it to start running from in the TCPC register. */
++#if defined(CONFIG_IFX_VPE_EXT) && 0
++	if (stlb)
++		write_vpe_c0_wired(vpe0_wired + vpe1_wired);
++	else
++		write_vpe_c0_wired(vpe1_wired);
++#endif
+ 	write_tc_c0_tcrestart((unsigned long)v->__start);
+ 	write_tc_c0_tccontext((unsigned long)0);
+ 
+@@ -760,6 +825,20 @@
+ 
+ 	write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H);
+ 
++#if defined(CONFIG_IFX_VPE_EXT) && 0
++	/*
++	 * $a2 & $a3 are used to pass command line parameters to VPE1. $a2
++	 * points to the start of the command line string and $a3 points to
++	 * the end of the string. This convention is identical to the Linux
++	 * kernel boot parameter passing mechanism. Please note that $a3 is
++	 * used to pass physical memory size or 0 in SDE tool kit. So, if you
++	 * are passing comand line parameters through $a2 & $a3 SDE programs
++	 * don't work as desired.
++	 */
++	mttgpr(6, command_line);
++	mttgpr(7, (command_line + strlen(command_line)));
++	if (is_sdepgm)
++#endif
+ 	/*
+ 	 * The sde-kit passes 'memsize' to __start in $a3, so set something
+ 	 * here...  Or set $a3 to zero and define DFLT_STACK_SIZE and
+@@ -834,6 +913,9 @@
+ 	if ( (v->__start == 0) || (v->shared_ptr == NULL))
+ 		return -1;
+ 
++#ifdef CONFIG_IFX_VPE_EXT
++	is_sdepgm = 1;
++#endif
+ 	return 0;
+ }
+ 
+@@ -995,6 +1077,15 @@
+ 			   (unsigned long)v->load_addr + v->len);
+ 
+ 	if ((find_vpe_symbols(v, sechdrs, symindex, strtab, &mod)) < 0) {
++#ifdef CONFIG_IFX_VPE_EXT
++		if (vpe1_load_addr) {
++			/* Conversion to KSEG1 is required ??? */
++			v->__start = KSEG1ADDR(vpe1_load_addr);
++			is_sdepgm = 0;
++			return 0;
++		}
++#endif
++
+ 		if (v->__start == 0) {
+ 			printk(KERN_WARNING "VPE loader: program does not contain "
+ 			       "a __start symbol\n");
+@@ -1065,6 +1156,9 @@
+ 	struct vpe_notifications *not;
+ 	struct vpe *v;
+ 	int ret;
++#ifdef CONFIG_IFX_VPE_EXT
++   int progsize;
++#endif
+ 
+ 	if (minor != iminor(inode)) {
+ 		/* assume only 1 device at the moment. */
+@@ -1091,14 +1185,22 @@
+ 		cleanup_tc(get_tc(tclimit));
+ 	}
+ 
++#ifdef CONFIG_IFX_VPE_EXT
++	progsize = (vpe1_mem  != 0) ? vpe1_mem : P_SIZE;
++	//printk("progsize = %x\n", progsize);
++	v->pbuffer = vmalloc(progsize);
++	v->plen = progsize;
++#else
+ 	/* this of-course trashes what was there before... */
+ 	v->pbuffer = vmalloc(P_SIZE);
+ 	v->plen = P_SIZE;
++#endif
+ 	v->load_addr = NULL;
+ 	v->len = 0;
+-
++#if 0
+ 	v->uid = filp->f_cred->fsuid;
+ 	v->gid = filp->f_cred->fsgid;
++#endif
+ 
+ #ifdef CONFIG_MIPS_APSP_KSPD
+ 	/* get kspd to tell us when a syscall_exit happens */
+@@ -1351,6 +1453,133 @@
+ 	cleanup_tc(get_tc(sp_id));
+ }
+ #endif
++#ifdef CONFIG_IFX_VPE_EXT
++int32_t vpe1_sw_start(void* sw_start_addr, uint32_t tcmask, uint32_t flags)
++{
++	enum vpe_state state;
++	struct vpe *v = get_vpe(tclimit);
++	struct vpe_notifications *not;
++
++	if (tcmask || flags) {
++		printk(KERN_WARNING "Currently tcmask and flags should be 0.\
++				other values not supported\n");
++		return -1;
++	}
++
++	state = xchg(&v->state, VPE_STATE_INUSE);
++	if (state != VPE_STATE_UNUSED) {
++		vpe_stop(v);
++
++		list_for_each_entry(not, &v->notify, list) {
++			not->stop(tclimit);
++		}
++	}
++
++	v->__start = (unsigned long)sw_start_addr;
++	is_sdepgm = 0;
++
++	if (!vpe_run(v)) {
++		printk(KERN_DEBUG "VPE loader: VPE1 running successfully\n");
++		return 0;
++	}
++	return -1;
++}
++
++EXPORT_SYMBOL(vpe1_sw_start);
++
++int32_t vpe1_sw_stop(uint32_t flags)
++{
++	struct vpe *v = get_vpe(tclimit);
++
++	if (!vpe_free(v)) {
++		printk(KERN_DEBUG "RP Stopped\n");
++		return 0;
++	}
++	else
++		return -1;
++}
++
++EXPORT_SYMBOL(vpe1_sw_stop);
++
++uint32_t vpe1_get_load_addr (uint32_t flags)
++{
++	return vpe1_load_addr;
++}
++
++EXPORT_SYMBOL(vpe1_get_load_addr);
++
++uint32_t vpe1_get_max_mem (uint32_t flags)
++{
++	if (!vpe1_mem)
++		return P_SIZE;
++	else
++		return vpe1_mem;
++}
++
++EXPORT_SYMBOL(vpe1_get_max_mem);
++
++void* vpe1_get_cmdline_argument(void)
++{
++	return saved_command_line;
++}
++
++EXPORT_SYMBOL(vpe1_get_cmdline_argument);
++
++int32_t vpe1_set_boot_param(char *field, char *value, char flags)
++{
++	char *ptr, string[64];
++	int start_off, end_off;
++	if (!field)
++		return -1;
++	strcpy(string, field);
++	if (value) {
++		strcat(string, "=");
++		strcat(string, value);
++		strcat(command_line, " ");
++		strcat(command_line, string);
++	}
++	else {
++		ptr = strstr(command_line, string);
++		if (ptr) {
++			start_off = ptr - command_line;
++			ptr += strlen(string);
++			while ((*ptr != ' ') && (*ptr != '\0'))
++				ptr++;
++			end_off = ptr - command_line;
++			command_line[start_off] = '\0';
++			strcat (command_line, command_line+end_off);
++		}
++	}
++	return 0;
++}
++
++EXPORT_SYMBOL(vpe1_set_boot_param);
++
++int32_t vpe1_get_boot_param(char *field, char **value, char flags)
++{
++	char *ptr, string[64];
++	int i = 0;
++	if (!field)
++		return -1;
++	if ((ptr = strstr(command_line, field))) {
++		ptr += strlen(field) + 1; /* including = */
++		while ((*ptr != ' ') && (*ptr != '\0'))
++			string[i++] = *ptr++;
++		string[i] = '\0';
++		*value = kmalloc((strlen(string) + 1), GFP_KERNEL);
++		if (*value != NULL)
++			strcpy(*value, string);
++	}
++	else
++		*value = NULL;
++
++	return 0;
++}
++
++EXPORT_SYMBOL(vpe1_get_boot_param);
++
++extern void configure_tlb(void);
++#endif
+ 
+ static ssize_t store_kill(struct device *dev, struct device_attribute *attr,
+ 			  const char *buf, size_t len)
+@@ -1432,6 +1661,18 @@
+ 		printk("VPE loader: not a MIPS MT capable processor\n");
+ 		return -ENODEV;
+ 	}
++#ifdef CONFIG_IFX_VPE_EXT
++#ifndef CONFIG_MIPS_MT_SMTC
++	configure_tlb();
++#endif
++#endif
++
++#ifndef CONFIG_MIPS_MT_SMTC
++	if (!vpelimit)
++		vpelimit = 1;
++	if (!tclimit)
++		tclimit = 1;
++#endif
+ 
+ 	if (vpelimit == 0) {
+ 		printk(KERN_WARNING "No VPEs reserved for AP/SP, not "
+@@ -1476,10 +1717,12 @@
+ 	mtflags = dmt();
+ 	vpflags = dvpe();
+ 
++	back_to_back_c0_hazard();
++
+ 	/* Put MVPE's into 'configuration state' */
+ 	set_c0_mvpcontrol(MVPCONTROL_VPC);
+ 
+-	/* dump_mtregs(); */
++	dump_mtregs();
+ 
+ 	val = read_c0_mvpconf0();
+ 	hw_tcs = (val & MVPCONF0_PTC) + 1;
+@@ -1491,6 +1734,7 @@
+ 		 * reschedule send IPIs or similar we might hang.
+ 		 */
+ 		clear_c0_mvpcontrol(MVPCONTROL_VPC);
++		back_to_back_c0_hazard();
+ 		evpe(vpflags);
+ 		emt(mtflags);
+ 		local_irq_restore(flags);
+@@ -1516,6 +1760,7 @@
+ 			}
+ 
+ 			v->ntcs = hw_tcs - tclimit;
++                        write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | 1);
+ 
+ 			/* add the tc to the list of this vpe's tc's. */
+ 			list_add(&t->tc, &v->tc);
+@@ -1584,6 +1829,7 @@
+ out_reenable:
+ 	/* release config state */
+ 	clear_c0_mvpcontrol(MVPCONTROL_VPC);
++	back_to_back_c0_hazard();
+ 
+ 	evpe(vpflags);
+ 	emt(mtflags);
+--- /dev/null
++++ b/arch/mips/kernel/mtsched_proc.c
+@@ -0,0 +1,279 @@
++/*
++ * /proc hooks for MIPS MT scheduling policy management for 34K cores
++ *
++ *  This program is free software; you can distribute it and/or modify it
++ *  under the terms of the GNU General Public License (Version 2) as
++ *  published by the Free Software Foundation.
++ *
++ *  This program is distributed in the hope it will be useful, but WITHOUT
++ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ *  for more details.
++ *
++ *  You should have received a copy of the GNU General Public License along
++ *  with this program; if not, write to the Free Software Foundation, Inc.,
++ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
++ *
++ * Copyright (C) 2006 Mips Technologies, Inc
++ */
++
++#include <linux/kernel.h>
++
++#include <asm/cpu.h>
++#include <asm/processor.h>
++#include <asm/system.h>
++#include <asm/mipsregs.h>
++#include <asm/mipsmtregs.h>
++#include <asm/uaccess.h>
++#include <linux/proc_fs.h>
++
++static struct proc_dir_entry *mtsched_proc;
++
++#ifndef CONFIG_MIPS_MT_SMTC
++#define NTCS 2
++#else
++#define NTCS NR_CPUS
++#endif
++#define NVPES 2
++
++int lastvpe = 1;
++int lasttc = 8;
++
++static int proc_read_mtsched(char *page, char **start, off_t off,
++			int count, int *eof, void *data)
++{
++	int totalen = 0;
++	int len;
++
++	int i;
++	int vpe;
++	int mytc;
++	unsigned long flags;
++	unsigned int mtflags;
++	unsigned int haltstate;
++	unsigned int vpes_checked[NVPES];
++	unsigned int vpeschedule[NVPES];
++	unsigned int vpeschefback[NVPES];
++	unsigned int tcschedule[NTCS];
++	unsigned int tcschefback[NTCS];
++
++	/* Dump the state of the MIPS MT scheduling policy manager */
++	/* Inititalize control state */
++	for(i = 0; i < NVPES; i++) {
++		vpes_checked[i] = 0;
++		vpeschedule[i] = 0;
++		vpeschefback[i] = 0;
++	}
++	for(i = 0; i < NTCS; i++) {
++		tcschedule[i] = 0;
++		tcschefback[i] = 0;
++	}
++
++	/* Disable interrupts and multithreaded issue */
++	local_irq_save(flags);
++	mtflags = dvpe();
++
++	/* Then go through the TCs, halt 'em, and extract the values */
++	mytc = (read_c0_tcbind() & TCBIND_CURTC) >> TCBIND_CURTC_SHIFT;
++	for(i = 0; i < NTCS; i++) {
++		if(i == mytc) {
++			/* No need to halt ourselves! */
++			tcschedule[i] = read_c0_tcschedule();
++			tcschefback[i] = read_c0_tcschefback();
++			/* If VPE bound to TC hasn't been checked, do it */
++			vpe = read_c0_tcbind() & TCBIND_CURVPE;
++			if(!vpes_checked[vpe]) {
++				vpeschedule[vpe] = read_c0_vpeschedule();
++				vpeschefback[vpe] = read_c0_vpeschefback();
++				vpes_checked[vpe] = 1;
++			}
++		} else {
++			settc(i);
++			haltstate = read_tc_c0_tchalt();
++			write_tc_c0_tchalt(TCHALT_H);
++			mips_ihb();
++			tcschedule[i] = read_tc_c0_tcschedule();
++			tcschefback[i] = read_tc_c0_tcschefback();
++			/* If VPE bound to TC hasn't been checked, do it */
++			vpe = read_tc_c0_tcbind() & TCBIND_CURVPE;
++			if(!vpes_checked[vpe]) {
++			    vpeschedule[vpe] = read_vpe_c0_vpeschedule();
++			    vpeschefback[vpe] = read_vpe_c0_vpeschefback();
++			    vpes_checked[vpe] = 1;
++			}
++			if(!haltstate) write_tc_c0_tchalt(0);
++		}
++	}
++	/* Re-enable MT and interrupts */
++	evpe(mtflags);
++	local_irq_restore(flags);
++
++	for(vpe=0; vpe < NVPES; vpe++) {
++		len = sprintf(page, "VPE[%d].VPEschedule  = 0x%08x\n",
++			vpe, vpeschedule[vpe]);
++		totalen += len;
++		page += len;
++		len = sprintf(page, "VPE[%d].VPEschefback = 0x%08x\n",
++			vpe, vpeschefback[vpe]);
++		totalen += len;
++		page += len;
++	}
++	for(i=0; i < NTCS; i++) {
++		len = sprintf(page, "TC[%d].TCschedule    = 0x%08x\n",
++			i, tcschedule[i]);
++		totalen += len;
++		page += len;
++		len = sprintf(page, "TC[%d].TCschefback   = 0x%08x\n",
++			i, tcschefback[i]);
++		totalen += len;
++		page += len;
++	}
++	return totalen;
++}
++
++/*
++ * Write to perf counter registers based on text input
++ */
++
++#define TXTBUFSZ 100
++
++static int proc_write_mtsched(struct file *file, const char *buffer,
++				unsigned long count, void *data)
++{
++	int len = 0;
++	char mybuf[TXTBUFSZ];
++	/* At most, we will set up 9 TCs and 2 VPEs, 11 entries in all */
++	char entity[1];   //, entity1[1];
++	int number[1];
++	unsigned long value[1];
++	int nparsed = 0 , index = 0;
++	unsigned long flags;
++	unsigned int mtflags;
++	unsigned int haltstate;
++	unsigned int tcbindval;
++
++	if(count >= TXTBUFSZ) len = TXTBUFSZ-1;
++	else len = count;
++	memset(mybuf,0,TXTBUFSZ);
++	if(copy_from_user(mybuf, buffer, len)) return -EFAULT;
++
++	nparsed = sscanf(mybuf, "%c%d %lx",
++		 &entity[0] ,&number[0], &value[0]);
++
++	/*
++	 * Having acquired the inputs, which might have
++	 * generated exceptions and preemptions,
++	 * program the registers.
++	 */
++	/* Disable interrupts and multithreaded issue */
++	local_irq_save(flags);
++	mtflags = dvpe();
++
++	if(entity[index] == 't' ) {
++		/* Set TCSchedule or TCScheFBack of specified TC */
++		if(number[index] > NTCS) goto skip;
++		/* If it's our own TC, do it direct */
++		if(number[index] ==
++				((read_c0_tcbind() & TCBIND_CURTC)
++				>> TCBIND_CURTC_SHIFT)) {
++			if(entity[index] == 't')
++				 write_c0_tcschedule(value[index]);
++			else
++				write_c0_tcschefback(value[index]);
++		} else {
++		/* Otherwise, we do it via MTTR */
++			settc(number[index]);
++			haltstate = read_tc_c0_tchalt();
++			write_tc_c0_tchalt(TCHALT_H);
++			mips_ihb();
++			if(entity[index] == 't')
++				 write_tc_c0_tcschedule(value[index]);
++			else
++				write_tc_c0_tcschefback(value[index]);
++			mips_ihb();
++			if(!haltstate) write_tc_c0_tchalt(0);
++		}
++	} else if(entity[index] == 'v') {
++		/* Set VPESchedule of specified VPE */
++		if(number[index] > NVPES) goto skip;
++		tcbindval = read_c0_tcbind();
++		/* Are we doing this to our current VPE? */
++		if((tcbindval & TCBIND_CURVPE) == number[index]) {
++			/* Then life is simple */
++			write_c0_vpeschedule(value[index]);
++		} else {
++			/*
++			 * Bind ourselves to the other VPE long enough
++			 * to program the bind value.
++			 */
++			write_c0_tcbind((tcbindval & ~TCBIND_CURVPE)
++					   | number[index]);
++			mips_ihb();
++			write_c0_vpeschedule(value[index]);
++			mips_ihb();
++			/* Restore previous binding */
++			write_c0_tcbind(tcbindval);
++			mips_ihb();
++		}
++	}
++
++	else if(entity[index] == 'r') {
++		unsigned int vpes_checked[2], vpe ,i , mytc;
++		vpes_checked[0] = vpes_checked[1] = 0;
++
++		/* Then go through the TCs, halt 'em, and extract the values */
++		mytc = (read_c0_tcbind() & TCBIND_CURTC) >> TCBIND_CURTC_SHIFT;
++
++		for(i = 0; i < NTCS; i++) {
++			if(i == mytc) {
++				/* No need to halt ourselves! */
++				write_c0_vpeschefback(0);
++				write_c0_tcschefback(0);
++			} else {
++				settc(i);
++				haltstate = read_tc_c0_tchalt();
++				write_tc_c0_tchalt(TCHALT_H);
++				mips_ihb();
++				write_tc_c0_tcschefback(0);
++				/* If VPE bound to TC hasn't been checked, do it */
++				vpe = read_tc_c0_tcbind() & TCBIND_CURVPE;
++				if(!vpes_checked[vpe]) {
++				    write_vpe_c0_vpeschefback(0);
++				    vpes_checked[vpe] = 1;
++				}
++				if(!haltstate) write_tc_c0_tchalt(0);
++			}
++		}
++	}
++	else {
++		printk ("\n Usage : <t/v><0/1> <Hex Value>\n Example : t0 0x01\n");
++	}
++
++skip:
++	/* Re-enable MT and interrupts */
++	evpe(mtflags);
++	local_irq_restore(flags);
++	return (len);
++}
++
++static int __init init_mtsched_proc(void)
++{
++	extern struct proc_dir_entry *get_mips_proc_dir(void);
++	struct proc_dir_entry *mips_proc_dir;
++
++	if (!cpu_has_mipsmt) {
++		printk("mtsched: not a MIPS MT capable processor\n");
++		return -ENODEV;
++	}
++
++	mips_proc_dir = get_mips_proc_dir();
++
++	mtsched_proc = create_proc_entry("mtsched", 0644, mips_proc_dir);
++	mtsched_proc->read_proc = proc_read_mtsched;
++	mtsched_proc->write_proc = proc_write_mtsched;
++
++	return 0;
++}
++
++/* Automagically create the entry */
++module_init(init_mtsched_proc);
+--- /dev/null
++++ b/arch/mips/kernel/perf_proc.c
+@@ -0,0 +1,191 @@
++/*
++ * /proc hooks for CPU performance counter support for SMTC kernel
++ * (and ultimately others)
++ * Copyright (C) 2006 Mips Technologies, Inc
++ */
++
++#include <linux/kernel.h>
++
++#include <asm/cpu.h>
++#include <asm/processor.h>
++#include <asm/system.h>
++#include <asm/mipsregs.h>
++#include <asm/uaccess.h>
++#include <linux/proc_fs.h>
++
++/*
++ * /proc diagnostic and statistics hooks
++ */
++
++
++/* Internal software-extended event counters */
++
++static unsigned long long extencount[4] = {0,0,0,0};
++
++static struct proc_dir_entry *perf_proc;
++
++static int proc_read_perf(char *page, char **start, off_t off,
++				int count, int *eof, void *data)
++{
++	int totalen = 0;
++	int len;
++
++	len = sprintf(page, "PerfCnt[0].Ctl : 0x%08x\n", read_c0_perfctrl0());
++	totalen += len;
++	page += len;
++	len = sprintf(page, "PerfCnt[0].Cnt : %Lu\n",
++		extencount[0] + (unsigned long long)((unsigned)read_c0_perfcntr0()));
++	totalen += len;
++	page += len;
++	len = sprintf(page, "PerfCnt[1].Ctl : 0x%08x\n", read_c0_perfctrl1());
++	totalen += len;
++	page += len;
++	len = sprintf(page, "PerfCnt[1].Cnt : %Lu\n",
++		extencount[1] + (unsigned long long)((unsigned)read_c0_perfcntr1()));
++	totalen += len;
++	page += len;
++	len = sprintf(page, "PerfCnt[2].Ctl : 0x%08x\n", read_c0_perfctrl2());
++	totalen += len;
++	page += len;
++	len = sprintf(page, "PerfCnt[2].Cnt : %Lu\n",
++		extencount[2] + (unsigned long long)((unsigned)read_c0_perfcntr2()));
++	totalen += len;
++	page += len;
++	len = sprintf(page, "PerfCnt[3].Ctl : 0x%08x\n", read_c0_perfctrl3());
++	totalen += len;
++	page += len;
++	len = sprintf(page, "PerfCnt[3].Cnt : %Lu\n",
++		extencount[3] + (unsigned long long)((unsigned)read_c0_perfcntr3()));
++	totalen += len;
++	page += len;
++
++	return totalen;
++}
++
++/*
++ * Write to perf counter registers based on text input
++ */
++
++#define TXTBUFSZ 100
++
++static int proc_write_perf(struct file *file, const char *buffer,
++				unsigned long count, void *data)
++{
++	int len;
++	int nparsed;
++	int index;
++	char mybuf[TXTBUFSZ];
++
++	int which[4];
++	unsigned long control[4];
++	long long ctrdata[4];
++
++	if(count >= TXTBUFSZ) len = TXTBUFSZ-1;
++	else len = count;
++	memset(mybuf,0,TXTBUFSZ);
++	if(copy_from_user(mybuf, buffer, len)) return -EFAULT;
++
++	nparsed = sscanf(mybuf,
++			"%d %lx %Ld %d %lx %Ld %d %lx %Ld %d %lx %Ld",
++				&which[0], &control[0], &ctrdata[0],
++				&which[1], &control[1], &ctrdata[1],
++				&which[2], &control[2], &ctrdata[2],
++				&which[3], &control[3], &ctrdata[3]);
++
++	for(index = 0; nparsed >= 3; index++) {
++		switch (which[index]) {
++		case 0:
++			write_c0_perfctrl0(control[index]);
++			if(ctrdata[index] != -1) {
++			    extencount[0] = (unsigned long long)ctrdata[index];
++			    write_c0_perfcntr0((unsigned long)0);
++			}
++			break;
++		case 1:
++			write_c0_perfctrl1(control[index]);
++			if(ctrdata[index] != -1) {
++			    extencount[1] = (unsigned long long)ctrdata[index];
++			    write_c0_perfcntr1((unsigned long)0);
++			}
++			break;
++		case 2:
++			write_c0_perfctrl2(control[index]);
++			if(ctrdata[index] != -1) {
++			    extencount[2] = (unsigned long long)ctrdata[index];
++			    write_c0_perfcntr2((unsigned long)0);
++			}
++			break;
++		case 3:
++			write_c0_perfctrl3(control[index]);
++			if(ctrdata[index] != -1) {
++			    extencount[3] = (unsigned long long)ctrdata[index];
++			    write_c0_perfcntr3((unsigned long)0);
++			}
++			break;
++		}
++		nparsed -= 3;
++	}
++	return (len);
++}
++
++extern int (*perf_irq)(void);
++
++/*
++ * Invoked when timer interrupt vector picks up a perf counter overflow
++ */
++
++static int perf_proc_irq(void)
++{
++	unsigned long snapshot;
++
++	/*
++	 * It would be nice to do this as a loop, but we don't have
++	 * indirect access to CP0 registers.
++	 */
++	snapshot = read_c0_perfcntr0();
++	if ((long)snapshot < 0) {
++		extencount[0] +=
++			(unsigned long long)((unsigned)read_c0_perfcntr0());
++		write_c0_perfcntr0(0);
++	}
++	snapshot = read_c0_perfcntr1();
++	if ((long)snapshot < 0) {
++		extencount[1] +=
++			(unsigned long long)((unsigned)read_c0_perfcntr1());
++		write_c0_perfcntr1(0);
++	}
++	snapshot = read_c0_perfcntr2();
++	if ((long)snapshot < 0) {
++		extencount[2] +=
++			(unsigned long long)((unsigned)read_c0_perfcntr2());
++		write_c0_perfcntr2(0);
++	}
++	snapshot = read_c0_perfcntr3();
++	if ((long)snapshot < 0) {
++		extencount[3] +=
++			(unsigned long long)((unsigned)read_c0_perfcntr3());
++		write_c0_perfcntr3(0);
++	}
++	return 0;
++}
++
++static int __init init_perf_proc(void)
++{
++	extern struct proc_dir_entry *get_mips_proc_dir(void);
++
++	struct proc_dir_entry *mips_proc_dir = get_mips_proc_dir();
++
++	write_c0_perfcntr0(0);
++	write_c0_perfcntr1(0);
++	write_c0_perfcntr2(0);
++	write_c0_perfcntr3(0);
++	perf_proc = create_proc_entry("perf", 0644, mips_proc_dir);
++	perf_proc->read_proc = proc_read_perf;
++	perf_proc->write_proc = proc_write_perf;
++	perf_irq = perf_proc_irq;
++
++	return 0;
++}
++
++/* Automagically create the entry */
++module_init(init_perf_proc);

+ 5 - 5
target/linux/lantiq/patches/810-ar9-cache-split.patch → target/linux/lantiq/patches-2.6.32/260-ar9-cache-split.patch

@@ -1,6 +1,6 @@
 --- a/arch/mips/Kconfig
 +++ b/arch/mips/Kconfig
-@@ -1844,6 +1844,28 @@
+@@ -1653,6 +1653,28 @@
  	help
  	  IFX included extensions in APRP
  
@@ -31,7 +31,7 @@
  	depends on MIPS_MT && PROC_FS
 --- a/arch/mips/kernel/vpe.c
 +++ b/arch/mips/kernel/vpe.c
-@@ -128,6 +128,13 @@
+@@ -129,6 +129,13 @@
  EXPORT_SYMBOL(vpe1_wdog_timeout);
  
  #endif
@@ -45,7 +45,7 @@
  /* 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 @@
+@@ -867,6 +874,65 @@
  	/* enable this VPE */
  	write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
  
@@ -113,7 +113,7 @@
  	write_vpe_c0_cause(0);
 --- a/arch/mips/mm/c-r4k.c
 +++ b/arch/mips/mm/c-r4k.c
-@@ -1347,6 +1347,106 @@
+@@ -1348,6 +1348,106 @@
  __setup("coherentio", setcoherentio);
  #endif
  
@@ -220,7 +220,7 @@
  void __cpuinit r4k_cache_init(void)
  {
  	extern void build_clear_page(void);
-@@ -1366,6 +1466,78 @@
+@@ -1367,6 +1467,78 @@
  		break;
  	}
  

+ 8 - 0
target/linux/lantiq/patches-2.6.32/270-m25p80-fast-read.patch

@@ -0,0 +1,8 @@
+--- a/drivers/mtd/devices/m25p80.c
++++ b/drivers/mtd/devices/m25p80.c
+@@ -1,3 +1,5 @@
++
++
+ /*
+  * MTD SPI driver for ST M25Pxx (and similar) serial flash chips
+  *

+ 14 - 22
target/linux/lantiq/patches/940-spi1.patch → target/linux/lantiq/patches-2.6.32/400-spi1.patch

@@ -10,35 +10,27 @@ Signed-off-by: Daniel Schwierzeck <[email protected]>
 
 --- a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
 +++ b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
-@@ -48,4 +48,13 @@
- 
- extern int (*lqpci_plat_dev_init)(struct pci_dev *dev);
+@@ -50,4 +50,13 @@
+ 	int mii_mode;
+ };
  
 +
-+struct lq_spi_platform_data {
++struct ltq_spi_platform_data {
 +	u16 num_chipselect;
 +};
 +
-+struct lq_spi_controller_data {
++struct ltq_spi_controller_data {
 +	unsigned gpio;
 +};
 +
  #endif
---- a/arch/mips/include/asm/mach-lantiq/xway/xway.h
-+++ b/arch/mips/include/asm/mach-lantiq/xway/xway.h
-@@ -72,6 +72,7 @@
- #define LQ_PMU_BASE_ADDR	(KSEG1 + 0x1F102000)
- 
- #define PMU_DMA				0x0020
-+#define PMU_SPI				0x0100
- #define PMU_USB				0x8041
- #define PMU_LED				0x0800
- #define PMU_GPT				0x1000
-@@ -105,6 +106,7 @@
- 
- /*------------ SSC */
- #define LQ_SSC_BASE_ADDR	(KSEG1 + 0x1e100800)
-+#define LQ_SSC_SIZE		0x100
+--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+@@ -75,6 +75,7 @@
  
- /*------------ MEI */
- #define LQ_MEI_BASE_ADDR	(KSEG1 + 0x1E116000)
+ #define PMU_DMA			0x0020
+ #define PMU_USB			0x8041
++#define PMU_SPI			0x0100
+ #define PMU_LED			0x0800
+ #define PMU_GPT			0x1000
+ #define PMU_PPE			0x2000

+ 1103 - 0
target/linux/lantiq/patches-2.6.32/410-spi2.patch

@@ -0,0 +1,1103 @@
+From: Daniel Schwierzeck <[email protected]>
+Date: Thu, 3 Mar 2011 17:15:30 +0000 (+0100)
+Subject: SPI: lantiq: Add driver for Lantiq SoC SPI controller
+X-Git-Url: http://nbd.name/gitweb.cgi?p=lantiq.git;a=commitdiff_plain;h=653c95b8b9066c9c6ac08bd64d0ceee439e9fd90;hp=3d21b04682ae8eb1c1965aba39d1796e8c5ad84b
+
+SPI: lantiq: Add driver for Lantiq SoC SPI controller
+
+Signed-off-by: Daniel Schwierzeck <[email protected]>
+---
+
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -133,6 +133,14 @@
+ 	  This enables using the Freescale i.MX SPI controllers in master
+ 	  mode.
+ 
++config SPI_LANTIQ
++	tristate "Lantiq SoC SPI controller"
++	depends on SOC_LANTIQ_XWAY
++	select SPI_BITBANG
++	help
++	  This driver supports the Lantiq SoC SPI controller in master
++	  mode.
++
+ config SPI_LM70_LLP
+ 	tristate "Parallel port adapter for LM70 eval board (DEVELOPMENT)"
+ 	depends on PARPORT && EXPERIMENTAL
+--- a/drivers/spi/Makefile
++++ b/drivers/spi/Makefile
+@@ -20,6 +20,7 @@
+ obj-$(CONFIG_SPI_GPIO)			+= spi_gpio.o
+ obj-$(CONFIG_SPI_GPIO_OLD)		+= spi_gpio_old.o
+ obj-$(CONFIG_SPI_IMX)			+= spi_imx.o
++obj-$(CONFIG_SPI_LANTIQ)		+= spi_lantiq.o
+ obj-$(CONFIG_SPI_LM70_LLP)		+= spi_lm70llp.o
+ obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
+ obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o
+--- /dev/null
++++ b/drivers/spi/spi_lantiq.c
+@@ -0,0 +1,1063 @@
++/*
++ * Lantiq SoC SPI controller
++ *
++ * Copyright (C) 2011 Daniel Schwierzeck <[email protected]>
++ *
++ * This program is free software; you can distribute it and/or modify it
++ * under the terms of the GNU General Public License (Version 2) as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/workqueue.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/sched.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++#include <linux/completion.h>
++#include <linux/spinlock.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++#include <linux/gpio.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/spi_bitbang.h>
++
++#include <xway.h>
++#include <xway_irq.h>
++#include <lantiq_platform.h>
++
++#define LTQ_SPI_CLC		0x00	/* Clock control */
++#define LTQ_SPI_PISEL		0x04	/* Port input select */
++#define LTQ_SPI_ID		0x08	/* Identification */
++#define LTQ_SPI_CON		0x10	/* Control */
++#define LTQ_SPI_STAT		0x14	/* Status */
++#define LTQ_SPI_WHBSTATE	0x18	/* Write HW modified state */
++#define LTQ_SPI_TB		0x20	/* Transmit buffer */
++#define LTQ_SPI_RB		0x24	/* Receive buffer */
++#define LTQ_SPI_RXFCON		0x30	/* Receive FIFO control */
++#define LTQ_SPI_TXFCON		0x34	/* Transmit FIFO control */
++#define LTQ_SPI_FSTAT		0x38	/* FIFO status */
++#define LTQ_SPI_BRT		0x40	/* Baudrate timer */
++#define LTQ_SPI_BRSTAT		0x44	/* Baudrate timer status */
++#define LTQ_SPI_SFCON		0x60	/* Serial frame control */
++#define LTQ_SPI_SFSTAT		0x64	/* Serial frame status */
++#define LTQ_SPI_GPOCON		0x70	/* General purpose output control */
++#define LTQ_SPI_GPOSTAT		0x74	/* General purpose output status */
++#define LTQ_SPI_FGPO		0x78	/* Forced general purpose output */
++#define LTQ_SPI_RXREQ		0x80	/* Receive request */
++#define LTQ_SPI_RXCNT		0x84	/* Receive count */
++#define LTQ_SPI_DMACON		0xEC	/* DMA control */
++#define LTQ_SPI_IRNEN		0xF4	/* Interrupt node enable */
++#define LTQ_SPI_IRNICR		0xF8	/* Interrupt node interrupt capture */
++#define LTQ_SPI_IRNCR		0xFC	/* Interrupt node control */
++
++#define LTQ_SPI_CLC_SMC_SHIFT	16	/* Clock divider for sleep mode */
++#define LTQ_SPI_CLC_SMC_MASK	0xFF
++#define LTQ_SPI_CLC_RMC_SHIFT	8	/* Clock divider for normal run mode */
++#define LTQ_SPI_CLC_RMC_MASK	0xFF
++#define LTQ_SPI_CLC_DISS	BIT(1)	/* Disable status bit */
++#define LTQ_SPI_CLC_DISR	BIT(0)	/* Disable request bit */
++
++#define LTQ_SPI_ID_TXFS_SHIFT	24	/* Implemented TX FIFO size */
++#define LTQ_SPI_ID_TXFS_MASK	0x3F
++#define LTQ_SPI_ID_RXFS_SHIFT	16	/* Implemented RX FIFO size */
++#define LTQ_SPI_ID_RXFS_MASK	0x3F
++#define LTQ_SPI_ID_REV_MASK	0x1F	/* Hardware revision number */
++#define LTQ_SPI_ID_CFG		BIT(5)	/* DMA interface support */
++
++#define LTQ_SPI_CON_BM_SHIFT	16	/* Data width selection */
++#define LTQ_SPI_CON_BM_MASK	0x1F
++#define LTQ_SPI_CON_EM		BIT(24)	/* Echo mode */
++#define LTQ_SPI_CON_IDLE	BIT(23)	/* Idle bit value */
++#define LTQ_SPI_CON_ENBV	BIT(22)	/* Enable byte valid control */
++#define LTQ_SPI_CON_RUEN	BIT(12)	/* Receive underflow error enable */
++#define LTQ_SPI_CON_TUEN	BIT(11)	/* Transmit underflow error enable */
++#define LTQ_SPI_CON_AEN		BIT(10)	/* Abort error enable */
++#define LTQ_SPI_CON_REN		BIT(9)	/* Receive overflow error enable */
++#define LTQ_SPI_CON_TEN		BIT(8)	/* Transmit overflow error enable */
++#define LTQ_SPI_CON_LB		BIT(7)	/* Loopback control */
++#define LTQ_SPI_CON_PO		BIT(6)	/* Clock polarity control */
++#define LTQ_SPI_CON_PH		BIT(5)	/* Clock phase control */
++#define LTQ_SPI_CON_HB		BIT(4)	/* Heading control */
++#define LTQ_SPI_CON_RXOFF	BIT(1)	/* Switch receiver off */
++#define LTQ_SPI_CON_TXOFF	BIT(0)	/* Switch transmitter off */
++
++#define LTQ_SPI_STAT_RXBV_MASK	0x7
++#define LTQ_SPI_STAT_RXBV_SHIFT	28
++#define LTQ_SPI_STAT_BSY	BIT(13)	/* Busy flag */
++#define LTQ_SPI_STAT_RUE	BIT(12)	/* Receive underflow error flag */
++#define LTQ_SPI_STAT_TUE	BIT(11)	/* Transmit underflow error flag */
++#define LTQ_SPI_STAT_AE		BIT(10)	/* Abort error flag */
++#define LTQ_SPI_STAT_RE		BIT(9)	/* Receive error flag */
++#define LTQ_SPI_STAT_TE		BIT(8)	/* Transmit error flag */
++#define LTQ_SPI_STAT_MS		BIT(1)	/* Master/slave select bit */
++#define LTQ_SPI_STAT_EN		BIT(0)	/* Enable bit */
++
++#define LTQ_SPI_WHBSTATE_SETTUE	BIT(15)	/* Set transmit underflow error flag */
++#define LTQ_SPI_WHBSTATE_SETAE	BIT(14)	/* Set abort error flag */
++#define LTQ_SPI_WHBSTATE_SETRE	BIT(13)	/* Set receive error flag */
++#define LTQ_SPI_WHBSTATE_SETTE	BIT(12)	/* Set transmit error flag */
++#define LTQ_SPI_WHBSTATE_CLRTUE	BIT(11)	/* Clear transmit underflow error flag */
++#define LTQ_SPI_WHBSTATE_CLRAE	BIT(10)	/* Clear abort error flag */
++#define LTQ_SPI_WHBSTATE_CLRRE	BIT(9)	/* Clear receive error flag */
++#define LTQ_SPI_WHBSTATE_CLRTE	BIT(8)	/* Clear transmit error flag */
++#define LTQ_SPI_WHBSTATE_SETME	BIT(7)	/* Set mode error flag */
++#define LTQ_SPI_WHBSTATE_CLRME	BIT(6)	/* Clear mode error flag */
++#define LTQ_SPI_WHBSTATE_SETRUE	BIT(5)	/* Set receive underflow error flag */
++#define LTQ_SPI_WHBSTATE_CLRRUE	BIT(4)	/* Clear receive underflow error flag */
++#define LTQ_SPI_WHBSTATE_SETMS	BIT(3)	/* Set master select bit */
++#define LTQ_SPI_WHBSTATE_CLRMS	BIT(2)	/* Clear master select bit */
++#define LTQ_SPI_WHBSTATE_SETEN	BIT(1)	/* Set enable bit (operational mode) */
++#define LTQ_SPI_WHBSTATE_CLREN	BIT(0)	/* Clear enable bit (config mode */
++#define LTQ_SPI_WHBSTATE_CLR_ERRORS	0x0F50
++
++#define LTQ_SPI_RXFCON_RXFITL_SHIFT	8	/* FIFO interrupt trigger level */
++#define LTQ_SPI_RXFCON_RXFITL_MASK	0x3F
++#define LTQ_SPI_RXFCON_RXFLU		BIT(1)	/* FIFO flush */
++#define LTQ_SPI_RXFCON_RXFEN		BIT(0)	/* FIFO enable */
++
++#define LTQ_SPI_TXFCON_TXFITL_SHIFT	8	/* FIFO interrupt trigger level */
++#define LTQ_SPI_TXFCON_TXFITL_MASK	0x3F
++#define LTQ_SPI_TXFCON_TXFLU		BIT(1)	/* FIFO flush */
++#define LTQ_SPI_TXFCON_TXFEN		BIT(0)	/* FIFO enable */
++
++#define LTQ_SPI_FSTAT_RXFFL_MASK	0x3f
++#define LTQ_SPI_FSTAT_RXFFL_SHIFT	0
++#define LTQ_SPI_FSTAT_TXFFL_MASK	0x3f
++#define LTQ_SPI_FSTAT_TXFFL_SHIFT	8
++
++#define LTQ_SPI_GPOCON_ISCSBN_SHIFT	8
++#define LTQ_SPI_GPOCON_INVOUTN_SHIFT	0
++
++#define LTQ_SPI_FGPO_SETOUTN_SHIFT	8
++#define LTQ_SPI_FGPO_CLROUTN_SHIFT	0
++
++#define LTQ_SPI_RXREQ_RXCNT_MASK	0xFFFF	/* Receive count value */
++#define LTQ_SPI_RXCNT_TODO_MASK		0xFFFF	/* Recevie to-do value */
++
++#define LTQ_SPI_IRNEN_F		BIT(3)	/* Frame end interrupt request */
++#define LTQ_SPI_IRNEN_E		BIT(2)	/* Error end interrupt request */
++#define LTQ_SPI_IRNEN_T		BIT(1)	/* Transmit end interrupt request */
++#define LTQ_SPI_IRNEN_R		BIT(0)	/* Receive end interrupt request */
++#define LTQ_SPI_IRNEN_ALL	0xF
++
++/* Hard-wired GPIOs used by SPI controller */
++#define LTQ_SPI_GPIO_DI 	16
++#define LTQ_SPI_GPIO_DO		17
++#define LTQ_SPI_GPIO_CLK	18
++
++struct ltq_spi {
++	struct spi_bitbang	bitbang;
++	struct completion	done;
++	spinlock_t		lock;
++
++	struct device		*dev;
++	void __iomem		*base;
++	struct clk		*clk;
++
++	int			status;
++	int			irq[3];
++
++	const u8		*tx;
++	u8			*rx;
++	u32			tx_cnt;
++	u32			rx_cnt;
++	u32			len;
++	struct spi_transfer	*curr_transfer;
++
++	u32 (*get_tx) (struct ltq_spi *);
++
++	u16			txfs;
++	u16			rxfs;
++	unsigned		dma_support:1;
++	unsigned		cfg_mode:1;
++
++};
++
++struct ltq_spi_controller_state {
++	void (*cs_activate) (struct spi_device *);
++	void (*cs_deactivate) (struct spi_device *);
++};
++
++struct ltq_spi_irq_map {
++	char		*name;
++	irq_handler_t	handler;
++};
++
++struct ltq_spi_cs_gpio_map {
++	unsigned	gpio;
++	unsigned	altsel0;
++	unsigned	altsel1;
++};
++
++static inline struct ltq_spi *ltq_spi_to_hw(struct spi_device *spi)
++{
++	return spi_master_get_devdata(spi->master);
++}
++
++static inline u32 ltq_spi_reg_read(struct ltq_spi *hw, u32 reg)
++{
++	return ioread32be(hw->base + reg);
++}
++
++static inline void ltq_spi_reg_write(struct ltq_spi *hw, u32 val, u32 reg)
++{
++	iowrite32be(val, hw->base + reg);
++}
++
++static inline void ltq_spi_reg_setbit(struct ltq_spi *hw, u32 bits, u32 reg)
++{
++	u32 val;
++
++	val = ltq_spi_reg_read(hw, reg);
++	val |= bits;
++	ltq_spi_reg_write(hw, val, reg);
++}
++
++static inline void ltq_spi_reg_clearbit(struct ltq_spi *hw, u32 bits, u32 reg)
++{
++	u32 val;
++
++	val = ltq_spi_reg_read(hw, reg);
++	val &= ~bits;
++	ltq_spi_reg_write(hw, val, reg);
++}
++
++static void ltq_spi_hw_enable(struct ltq_spi *hw)
++{
++	u32 clc;
++
++	/* Power-up mdule */
++	ltq_pmu_enable(PMU_SPI);
++
++	/*
++	 * Set clock divider for run mode to 1 to
++	 * run at same frequency as FPI bus
++	 */
++	clc = (1 << LTQ_SPI_CLC_RMC_SHIFT);
++	ltq_spi_reg_write(hw, clc, LTQ_SPI_CLC);
++}
++
++static void ltq_spi_hw_disable(struct ltq_spi *hw)
++{
++	/* Set clock divider to 0 and set module disable bit */
++	ltq_spi_reg_write(hw, LTQ_SPI_CLC_DISS, LTQ_SPI_CLC);
++
++	/* Power-down mdule */
++	ltq_pmu_disable(PMU_SPI);
++}
++
++static void ltq_spi_reset_fifos(struct ltq_spi *hw)
++{
++	u32 val;
++
++	/*
++	 * Enable and flush FIFOs. Set interrupt trigger level to
++	 * half of FIFO count implemented in hardware.
++	 */
++	if (hw->txfs > 1) {
++		val = hw->txfs << (LTQ_SPI_TXFCON_TXFITL_SHIFT - 1);
++		val |= LTQ_SPI_TXFCON_TXFEN | LTQ_SPI_TXFCON_TXFLU;
++		ltq_spi_reg_write(hw, val, LTQ_SPI_TXFCON);
++	}
++
++	if (hw->rxfs > 1) {
++		val = hw->rxfs << (LTQ_SPI_RXFCON_RXFITL_SHIFT - 1);
++		val |= LTQ_SPI_RXFCON_RXFEN | LTQ_SPI_RXFCON_RXFLU;
++		ltq_spi_reg_write(hw, val, LTQ_SPI_RXFCON);
++	}
++}
++
++static inline int ltq_spi_wait_ready(struct ltq_spi *hw)
++{
++	u32 stat;
++	unsigned long timeout;
++
++	timeout = jiffies + msecs_to_jiffies(200);
++
++	do {
++		stat = ltq_spi_reg_read(hw, LTQ_SPI_STAT);
++		if (!(stat & LTQ_SPI_STAT_BSY))
++			return 0;
++
++		cond_resched();
++	} while (!time_after_eq(jiffies, timeout));
++
++	dev_err(hw->dev, "SPI wait ready timed out\n");
++
++	return -ETIMEDOUT;
++}
++
++static void ltq_spi_config_mode_set(struct ltq_spi *hw)
++{
++	if (hw->cfg_mode)
++		return;
++
++	/*
++	 * Putting the SPI module in config mode is only safe if no
++	 * transfer is in progress as indicated by busy flag STATE.BSY.
++	 */
++	if (ltq_spi_wait_ready(hw)) {
++		ltq_spi_reset_fifos(hw);
++		hw->status = -ETIMEDOUT;
++	}
++	ltq_spi_reg_write(hw, LTQ_SPI_WHBSTATE_CLREN, LTQ_SPI_WHBSTATE);
++
++	hw->cfg_mode = 1;
++}
++
++static void ltq_spi_run_mode_set(struct ltq_spi *hw)
++{
++	if (!hw->cfg_mode)
++		return;
++
++	ltq_spi_reg_write(hw, LTQ_SPI_WHBSTATE_SETEN, LTQ_SPI_WHBSTATE);
++
++	hw->cfg_mode = 0;
++}
++
++static u32 ltq_spi_tx_word_u8(struct ltq_spi *hw)
++{
++	const u8 *tx = hw->tx;
++	u32 data = *tx++;
++
++	hw->tx_cnt++;
++	hw->tx++;
++
++	return data;
++}
++
++static u32 ltq_spi_tx_word_u16(struct ltq_spi *hw)
++{
++	const u16 *tx = (u16 *) hw->tx;
++	u32 data = *tx++;
++
++	hw->tx_cnt += 2;
++	hw->tx += 2;
++
++	return data;
++}
++
++static u32 ltq_spi_tx_word_u32(struct ltq_spi *hw)
++{
++	const u32 *tx = (u32 *) hw->tx;
++	u32 data = *tx++;
++
++	hw->tx_cnt += 4;
++	hw->tx += 4;
++
++	return data;
++}
++
++static void ltq_spi_bits_per_word_set(struct spi_device *spi)
++{
++	struct ltq_spi *hw = ltq_spi_to_hw(spi);
++	u32 bm;
++	u8 bits_per_word = spi->bits_per_word;
++
++	/*
++	 * Use either default value of SPI device or value
++	 * from current transfer.
++	 */
++	if (hw->curr_transfer && hw->curr_transfer->bits_per_word)
++		bits_per_word = hw->curr_transfer->bits_per_word;
++
++	if (bits_per_word <= 8)
++		hw->get_tx = ltq_spi_tx_word_u8;
++	else if (bits_per_word <= 16)
++		hw->get_tx = ltq_spi_tx_word_u16;
++	else if (bits_per_word <= 32)
++		hw->get_tx = ltq_spi_tx_word_u32;
++
++	/* CON.BM value = bits_per_word - 1 */
++	bm = (bits_per_word - 1) << LTQ_SPI_CON_BM_SHIFT;
++
++	ltq_spi_reg_clearbit(hw, LTQ_SPI_CON_BM_MASK <<
++			     LTQ_SPI_CON_BM_SHIFT, LTQ_SPI_CON);
++	ltq_spi_reg_setbit(hw, bm, LTQ_SPI_CON);
++}
++
++static void ltq_spi_speed_set(struct spi_device *spi)
++{
++	struct ltq_spi *hw = ltq_spi_to_hw(spi);
++	u32 br, max_speed_hz, spi_clk;
++	u32 speed_hz = spi->max_speed_hz;
++
++	/*
++	 * Use either default value of SPI device or value
++	 * from current transfer.
++	 */
++	if (hw->curr_transfer && hw->curr_transfer->speed_hz)
++		speed_hz = hw->curr_transfer->speed_hz;
++
++	/*
++	 * 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);
++
++	/*
++	 * Maximum SPI clock frequency in master mode is half of
++	 * SPI module clock frequency. Maximum reload value of
++	 * baudrate generator BR is 2^16.
++	 */
++	max_speed_hz = spi_clk / 2;
++	if (speed_hz >= max_speed_hz)
++		br = 0;
++	else
++		br = (max_speed_hz / speed_hz) - 1;
++
++	if (br > 0xFFFF)
++		br = 0xFFFF;
++
++	ltq_spi_reg_write(hw, br, LTQ_SPI_BRT);
++}
++
++static void ltq_spi_clockmode_set(struct spi_device *spi)
++{
++	struct ltq_spi *hw = ltq_spi_to_hw(spi);
++	u32 con;
++
++	con = ltq_spi_reg_read(hw, LTQ_SPI_CON);
++
++	/*
++	 * SPI mode mapping in CON register:
++	 * Mode CPOL CPHA CON.PO CON.PH
++	 *  0    0    0      0      1
++	 *  1    0    1      0      0
++	 *  2    1    0      1      1
++	 *  3    1    1      1      0
++	 */
++	if (spi->mode & SPI_CPHA)
++		con &= ~LTQ_SPI_CON_PH;
++	else
++		con |= LTQ_SPI_CON_PH;
++
++	if (spi->mode & SPI_CPOL)
++		con |= LTQ_SPI_CON_PO;
++	else
++		con &= ~LTQ_SPI_CON_PO;
++
++	/* Set heading control */
++	if (spi->mode & SPI_LSB_FIRST)
++		con &= ~LTQ_SPI_CON_HB;
++	else
++		con |= LTQ_SPI_CON_HB;
++
++	ltq_spi_reg_write(hw, con, LTQ_SPI_CON);
++}
++
++static void ltq_spi_xmit_set(struct ltq_spi *hw, struct spi_transfer *t)
++{
++	u32 con;
++
++	con = ltq_spi_reg_read(hw, LTQ_SPI_CON);
++
++	if (t) {
++		if (t->tx_buf && t->rx_buf) {
++			con &= ~(LTQ_SPI_CON_TXOFF | LTQ_SPI_CON_RXOFF);
++		} else if (t->rx_buf) {
++			con &= ~LTQ_SPI_CON_RXOFF;
++			con |= LTQ_SPI_CON_TXOFF;
++		} else if (t->tx_buf) {
++			con &= ~LTQ_SPI_CON_TXOFF;
++			con |= LTQ_SPI_CON_RXOFF;
++		}
++	} else
++		con |= (LTQ_SPI_CON_TXOFF | LTQ_SPI_CON_RXOFF);
++
++	ltq_spi_reg_write(hw, con, LTQ_SPI_CON);
++}
++
++static void ltq_spi_gpio_cs_activate(struct spi_device *spi)
++{
++	struct ltq_spi_controller_data *cdata = spi->controller_data;
++	int val = spi->mode & SPI_CS_HIGH ? 1 : 0;
++
++	gpio_set_value(cdata->gpio, val);
++}
++
++static void ltq_spi_gpio_cs_deactivate(struct spi_device *spi)
++{
++	struct ltq_spi_controller_data *cdata = spi->controller_data;
++	int val = spi->mode & SPI_CS_HIGH ? 0 : 1;
++
++	gpio_set_value(cdata->gpio, val);
++}
++
++static void ltq_spi_internal_cs_activate(struct spi_device *spi)
++{
++	struct ltq_spi *hw = ltq_spi_to_hw(spi);
++	u32 fgpo;
++
++	fgpo = (1 << (spi->chip_select + LTQ_SPI_FGPO_CLROUTN_SHIFT));
++	ltq_spi_reg_setbit(hw, fgpo, LTQ_SPI_FGPO);
++}
++
++static void ltq_spi_internal_cs_deactivate(struct spi_device *spi)
++{
++	struct ltq_spi *hw = ltq_spi_to_hw(spi);
++	u32 fgpo;
++
++	fgpo = (1 << (spi->chip_select + LTQ_SPI_FGPO_SETOUTN_SHIFT));
++	ltq_spi_reg_setbit(hw, fgpo, LTQ_SPI_FGPO);
++}
++
++static void ltq_spi_chipselect(struct spi_device *spi, int cs)
++{
++	struct ltq_spi *hw = ltq_spi_to_hw(spi);
++	struct ltq_spi_controller_state *cstate = spi->controller_state;
++
++	switch (cs) {
++	case BITBANG_CS_ACTIVE:
++		ltq_spi_bits_per_word_set(spi);
++		ltq_spi_speed_set(spi);
++		ltq_spi_clockmode_set(spi);
++		ltq_spi_run_mode_set(hw);
++
++		cstate->cs_activate(spi);
++		break;
++
++	case BITBANG_CS_INACTIVE:
++		cstate->cs_deactivate(spi);
++
++		ltq_spi_config_mode_set(hw);
++
++		break;
++	}
++}
++
++static int ltq_spi_setup_transfer(struct spi_device *spi,
++				  struct spi_transfer *t)
++{
++	struct ltq_spi *hw = ltq_spi_to_hw(spi);
++	u8 bits_per_word = spi->bits_per_word;
++
++	hw->curr_transfer = t;
++
++	if (t && t->bits_per_word)
++		bits_per_word = t->bits_per_word;
++
++	if (bits_per_word > 32)
++		return -EINVAL;
++
++	ltq_spi_config_mode_set(hw);
++
++	return 0;
++}
++
++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 },
++};
++
++static int ltq_spi_setup(struct spi_device *spi)
++{
++	struct ltq_spi *hw = ltq_spi_to_hw(spi);
++	struct ltq_spi_controller_data *cdata = spi->controller_data;
++	struct ltq_spi_controller_state *cstate;
++	u32 gpocon, fgpo;
++	int ret;
++
++	/* Set default word length to 8 if not set */
++	if (!spi->bits_per_word)
++		spi->bits_per_word = 8;
++
++	if (spi->bits_per_word > 32)
++		return -EINVAL;
++
++	if (!spi->controller_state) {
++		cstate = kzalloc(sizeof(struct ltq_spi_controller_state),
++				 GFP_KERNEL);
++		if (!cstate)
++			return -ENOMEM;
++
++		spi->controller_state = cstate;
++	} else
++		return 0;
++
++	/*
++	 * Up to six GPIOs can be connected to the SPI module
++	 * via GPIO alternate function to control the chip select lines.
++	 * For more flexibility in board layout this driver can also control
++	 * the CS lines via GPIO API. If GPIOs should be used, board setup code
++	 * have to register the SPI device with struct ltq_spi_controller_data
++	 * attached.
++	 */
++	if (cdata && cdata->gpio) {
++		ret = gpio_request(cdata->gpio, "spi-cs");
++		if (ret)
++			return -EBUSY;
++
++		ret = spi->mode & SPI_CS_HIGH ? 0 : 1;
++		gpio_direction_output(cdata->gpio, ret);
++
++		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,
++				1, "spi-cs");
++		if (ret)
++			return -EBUSY;
++
++		gpocon = (1 << (spi->chip_select +
++				LTQ_SPI_GPOCON_ISCSBN_SHIFT));
++
++		if (spi->mode & SPI_CS_HIGH)
++			gpocon |= (1 << spi->chip_select);
++
++		fgpo = (1 << (spi->chip_select + LTQ_SPI_FGPO_SETOUTN_SHIFT));
++
++		ltq_spi_reg_setbit(hw, gpocon, LTQ_SPI_GPOCON);
++		ltq_spi_reg_setbit(hw, fgpo, LTQ_SPI_FGPO);
++
++		cstate->cs_activate = ltq_spi_internal_cs_activate;
++		cstate->cs_deactivate = ltq_spi_internal_cs_deactivate;
++	}
++
++	return 0;
++}
++
++static void ltq_spi_cleanup(struct spi_device *spi)
++{
++	struct ltq_spi_controller_data *cdata = spi->controller_data;
++	struct ltq_spi_controller_state *cstate = spi->controller_state;
++	unsigned gpio;
++
++	if (cdata && cdata->gpio)
++		gpio = cdata->gpio;
++	else
++		gpio = ltq_spi_cs[spi->chip_select].gpio;
++
++	gpio_free(gpio);
++	kfree(cstate);
++}
++
++static void ltq_spi_txfifo_write(struct ltq_spi *hw)
++{
++	u32 fstat, data;
++	u16 fifo_space;
++
++	/* Determine how much FIFOs are free for TX data */
++	fstat = ltq_spi_reg_read(hw, LTQ_SPI_FSTAT);
++	fifo_space = hw->txfs - ((fstat >> LTQ_SPI_FSTAT_TXFFL_SHIFT) &
++					LTQ_SPI_FSTAT_TXFFL_MASK);
++
++	if (!fifo_space)
++		return;
++
++	while (hw->tx_cnt < hw->len && fifo_space) {
++		data = hw->get_tx(hw);
++		ltq_spi_reg_write(hw, data, LTQ_SPI_TB);
++		fifo_space--;
++	}
++}
++
++static void ltq_spi_rxfifo_read(struct ltq_spi *hw)
++{
++	u32 fstat, data, *rx32;
++	u16 fifo_fill;
++	u8 rxbv, shift, *rx8;
++
++	/* Determine how much FIFOs are filled with RX data */
++	fstat = ltq_spi_reg_read(hw, LTQ_SPI_FSTAT);
++	fifo_fill = ((fstat >> LTQ_SPI_FSTAT_RXFFL_SHIFT)
++			& LTQ_SPI_FSTAT_RXFFL_MASK);
++
++	if (!fifo_fill)
++		return;
++
++	/*
++	 * The 32 bit FIFO is always used completely independent from the
++	 * bits_per_word value. Thus four bytes have to be read at once
++	 * per FIFO.
++	 */
++	rx32 = (u32 *) hw->rx;
++	while (hw->len - hw->rx_cnt >= 4 && fifo_fill) {
++		*rx32++ = ltq_spi_reg_read(hw, LTQ_SPI_RB);
++		hw->rx_cnt += 4;
++		hw->rx += 4;
++		fifo_fill--;
++	}
++
++	/*
++	 * If there are remaining bytes, read byte count from STAT.RXBV
++	 * register and read the data byte-wise.
++	 */
++	while (fifo_fill && hw->rx_cnt < hw->len) {
++		rxbv = (ltq_spi_reg_read(hw, LTQ_SPI_STAT) >>
++			LTQ_SPI_STAT_RXBV_SHIFT) & LTQ_SPI_STAT_RXBV_MASK;
++		data = ltq_spi_reg_read(hw, LTQ_SPI_RB);
++
++		shift = (rxbv - 1) * 8;
++		rx8 = hw->rx;
++
++		while (rxbv) {
++			*rx8++ = (data >> shift) & 0xFF;
++			rxbv--;
++			shift -= 8;
++			hw->rx_cnt++;
++			hw->rx++;
++		}
++
++		fifo_fill--;
++	}
++}
++
++static void ltq_spi_rxreq_set(struct ltq_spi *hw)
++{
++	u32 rxreq, rxreq_max, rxtodo;
++
++	rxtodo = ltq_spi_reg_read(hw, LTQ_SPI_RXCNT) & LTQ_SPI_RXCNT_TODO_MASK;
++
++	/*
++	 * In RX-only mode the serial clock is activated only after writing
++	 * the expected amount of RX bytes into RXREQ register.
++	 * To avoid receive overflows at high clocks it is better to request
++	 * only the amount of bytes that fits into all FIFOs. This value
++	 * depends on the FIFO size implemented in hardware.
++	 */
++	rxreq = hw->len - hw->rx_cnt;
++	rxreq_max = hw->rxfs << 2;
++	rxreq = min(rxreq_max, rxreq);
++
++	if (!rxtodo && rxreq)
++		ltq_spi_reg_write(hw, rxreq, LTQ_SPI_RXREQ);
++}
++
++static inline void ltq_spi_complete(struct ltq_spi *hw)
++{
++	complete(&hw->done);
++}
++
++irqreturn_t ltq_spi_tx_irq(int irq, void *data)
++{
++	struct ltq_spi *hw = data;
++	unsigned long flags;
++	int completed = 0;
++
++	spin_lock_irqsave(&hw->lock, flags);
++
++	if (hw->tx_cnt < hw->len)
++		ltq_spi_txfifo_write(hw);
++
++	if (hw->tx_cnt == hw->len)
++		completed = 1;
++
++	spin_unlock_irqrestore(&hw->lock, flags);
++
++	if (completed)
++		ltq_spi_complete(hw);
++
++	return IRQ_HANDLED;
++}
++
++irqreturn_t ltq_spi_rx_irq(int irq, void *data)
++{
++	struct ltq_spi *hw = data;
++	unsigned long flags;
++	int completed = 0;
++
++	spin_lock_irqsave(&hw->lock, flags);
++
++	if (hw->rx_cnt < hw->len) {
++		ltq_spi_rxfifo_read(hw);
++
++		if (hw->tx && hw->tx_cnt < hw->len)
++			ltq_spi_txfifo_write(hw);
++	}
++
++	if (hw->rx_cnt == hw->len)
++		completed = 1;
++	else if (!hw->tx)
++		ltq_spi_rxreq_set(hw);
++
++	spin_unlock_irqrestore(&hw->lock, flags);
++
++	if (completed)
++		ltq_spi_complete(hw);
++
++	return IRQ_HANDLED;
++}
++
++irqreturn_t ltq_spi_err_irq(int irq, void *data)
++{
++	struct ltq_spi *hw = data;
++	unsigned long flags;
++
++	spin_lock_irqsave(&hw->lock, flags);
++
++	/* Disable all interrupts */
++	ltq_spi_reg_clearbit(hw, LTQ_SPI_IRNEN_ALL, LTQ_SPI_IRNEN);
++
++	/* Clear all error flags */
++	ltq_spi_reg_write(hw, LTQ_SPI_WHBSTATE_CLR_ERRORS, LTQ_SPI_WHBSTATE);
++
++	/* Flush FIFOs */
++	ltq_spi_reg_setbit(hw, LTQ_SPI_RXFCON_RXFLU, LTQ_SPI_RXFCON);
++	ltq_spi_reg_setbit(hw, LTQ_SPI_TXFCON_TXFLU, LTQ_SPI_TXFCON);
++
++	hw->status = -EIO;
++	spin_unlock_irqrestore(&hw->lock, flags);
++
++	ltq_spi_complete(hw);
++
++	return IRQ_HANDLED;
++}
++
++static int ltq_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
++{
++	struct ltq_spi *hw = ltq_spi_to_hw(spi);
++	u32 irq_flags = 0;
++
++	hw->tx = t->tx_buf;
++	hw->rx = t->rx_buf;
++	hw->len = t->len;
++	hw->tx_cnt = 0;
++	hw->rx_cnt = 0;
++	hw->status = 0;
++	INIT_COMPLETION(hw->done);
++
++	ltq_spi_xmit_set(hw, t);
++
++	/* Enable error interrupts */
++	ltq_spi_reg_setbit(hw, LTQ_SPI_IRNEN_E, LTQ_SPI_IRNEN);
++
++	if (hw->tx) {
++		/* Initially fill TX FIFO with as much data as possible */
++		ltq_spi_txfifo_write(hw);
++		irq_flags |= LTQ_SPI_IRNEN_T;
++
++		/* Always enable RX interrupt in Full Duplex mode */
++		if (hw->rx)
++			irq_flags |= LTQ_SPI_IRNEN_R;
++	} else if (hw->rx) {
++		/* Start RX clock */
++		ltq_spi_rxreq_set(hw);
++
++		/* Enable RX interrupt to receive data from RX FIFOs */
++		irq_flags |= LTQ_SPI_IRNEN_R;
++	}
++
++	/* Enable TX or RX interrupts */
++	ltq_spi_reg_setbit(hw, irq_flags, LTQ_SPI_IRNEN);
++	wait_for_completion_interruptible(&hw->done);
++
++	/* Disable all interrupts */
++	ltq_spi_reg_clearbit(hw, LTQ_SPI_IRNEN_ALL, LTQ_SPI_IRNEN);
++
++	/*
++	 * Return length of current transfer for bitbang utility code if
++	 * no errors occured during transmission.
++	 */
++	if (!hw->status)
++		hw->status = hw->len;
++
++	return hw->status;
++}
++
++static const struct ltq_spi_irq_map ltq_spi_irqs[] = {
++	{ "spi_tx", ltq_spi_tx_irq },
++	{ "spi_rx", ltq_spi_rx_irq },
++	{ "spi_err", ltq_spi_err_irq },
++};
++
++static int __init ltq_spi_probe(struct platform_device *pdev)
++{
++	struct spi_master *master;
++	struct resource *r;
++	struct ltq_spi *hw;
++	struct ltq_spi_platform_data *pdata = pdev->dev.platform_data;
++	int ret, i;
++	u32 data, id;
++
++	master = spi_alloc_master(&pdev->dev, sizeof(struct ltq_spi));
++	if (!master) {
++		dev_err(&pdev->dev, "spi_alloc_master\n");
++		ret = -ENOMEM;
++		goto err;
++	}
++
++	hw = spi_master_get_devdata(master);
++
++	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (r == NULL) {
++		dev_err(&pdev->dev, "platform_get_resource\n");
++		ret = -ENOENT;
++		goto err_master;
++	}
++
++	r = devm_request_mem_region(&pdev->dev, r->start, resource_size(r),
++			pdev->name);
++	if (!r) {
++		dev_err(&pdev->dev, "devm_request_mem_region\n");
++		ret = -ENXIO;
++		goto err_master;
++	}
++
++	hw->base = devm_ioremap_nocache(&pdev->dev, r->start, resource_size(r));
++	if (!hw->base) {
++		dev_err(&pdev->dev, "devm_ioremap_nocache\n");
++		ret = -ENXIO;
++		goto err_master;
++	}
++
++	hw->clk = clk_get(&pdev->dev, "fpi");
++	if (IS_ERR(hw->clk)) {
++		dev_err(&pdev->dev, "clk_get\n");
++		ret = PTR_ERR(hw->clk);
++		goto err_master;
++	}
++
++	memset(hw->irq, 0, sizeof(hw->irq));
++	for (i = 0; i < ARRAY_SIZE(ltq_spi_irqs); i++) {
++		ret = platform_get_irq_byname(pdev, ltq_spi_irqs[i].name);
++		if (0 > ret) {
++			dev_err(&pdev->dev, "platform_get_irq_byname\n");
++			goto err_irq;
++		}
++
++		hw->irq[i] = ret;
++		ret = request_irq(hw->irq[i], ltq_spi_irqs[i].handler,
++				  0, ltq_spi_irqs[i].name, hw);
++		if (ret) {
++			dev_err(&pdev->dev, "request_irq\n");
++			goto err_irq;
++		}
++	}
++
++	hw->bitbang.master = spi_master_get(master);
++	hw->bitbang.chipselect = ltq_spi_chipselect;
++	hw->bitbang.setup_transfer = ltq_spi_setup_transfer;
++	hw->bitbang.txrx_bufs = ltq_spi_txrx_bufs;
++
++	master->bus_num = pdev->id;
++	master->num_chipselect = pdata->num_chipselect;
++	master->setup = ltq_spi_setup;
++	master->cleanup = ltq_spi_cleanup;
++
++	hw->dev = &pdev->dev;
++	init_completion(&hw->done);
++	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_spi_hw_enable(hw);
++
++	/* Read module capabilities */
++	id = ltq_spi_reg_read(hw, LTQ_SPI_ID);
++	hw->txfs = (id >> LTQ_SPI_ID_TXFS_SHIFT) & LTQ_SPI_ID_TXFS_MASK;
++	hw->rxfs = (id >> LTQ_SPI_ID_TXFS_SHIFT) & LTQ_SPI_ID_TXFS_MASK;
++	hw->dma_support = (id & LTQ_SPI_ID_CFG) ? 1 : 0;
++
++	ltq_spi_config_mode_set(hw);
++
++	/* Enable error checking, disable TX/RX, set idle value high */
++	data = LTQ_SPI_CON_RUEN | LTQ_SPI_CON_AEN |
++	    LTQ_SPI_CON_TEN | LTQ_SPI_CON_REN |
++	    LTQ_SPI_CON_TXOFF | LTQ_SPI_CON_RXOFF | LTQ_SPI_CON_IDLE;
++	ltq_spi_reg_write(hw, data, LTQ_SPI_CON);
++
++	/* Enable master mode and clear error flags */
++	ltq_spi_reg_write(hw, LTQ_SPI_WHBSTATE_SETMS |
++			  LTQ_SPI_WHBSTATE_CLR_ERRORS, LTQ_SPI_WHBSTATE);
++
++	/* Reset GPIO/CS registers */
++	ltq_spi_reg_write(hw, 0x0, LTQ_SPI_GPOCON);
++	ltq_spi_reg_write(hw, 0xFF00, LTQ_SPI_FGPO);
++
++	/* Enable and flush FIFOs */
++	ltq_spi_reset_fifos(hw);
++
++	ret = spi_bitbang_start(&hw->bitbang);
++	if (ret) {
++		dev_err(&pdev->dev, "spi_bitbang_start\n");
++		goto err_bitbang;
++	}
++
++	platform_set_drvdata(pdev, hw);
++
++	pr_info("Lantiq SoC SPI controller rev %u (TXFS %u, RXFS %u, DMA %u)\n",
++		id & LTQ_SPI_ID_REV_MASK, hw->txfs, hw->rxfs, hw->dma_support);
++
++	return 0;
++
++err_bitbang:
++	ltq_spi_hw_disable(hw);
++
++err_irq:
++	clk_put(hw->clk);
++
++	for (; i > 0; i--)
++		free_irq(hw->irq[i], hw);
++
++err_master:
++	spi_master_put(master);
++
++err:
++	return ret;
++}
++
++static int __exit ltq_spi_remove(struct platform_device *pdev)
++{
++	struct ltq_spi *hw = platform_get_drvdata(pdev);
++	int ret, i;
++
++	ret = spi_bitbang_stop(&hw->bitbang);
++	if (ret)
++		return ret;
++
++	platform_set_drvdata(pdev, NULL);
++
++	ltq_spi_config_mode_set(hw);
++	ltq_spi_hw_disable(hw);
++
++	for (i = 0; i < ARRAY_SIZE(hw->irq); i++)
++		if (0 < hw->irq[i])
++			free_irq(hw->irq[i], hw);
++
++	gpio_free(LTQ_SPI_GPIO_DI);
++	gpio_free(LTQ_SPI_GPIO_DO);
++	gpio_free(LTQ_SPI_GPIO_CLK);
++
++	clk_put(hw->clk);
++	spi_master_put(hw->bitbang.master);
++
++	return 0;
++}
++
++static struct platform_driver ltq_spi_driver = {
++	.driver = {
++		   .name = "ltq-spi",
++		   .owner = THIS_MODULE,
++		   },
++	.remove = __exit_p(ltq_spi_remove),
++};
++
++static int __init ltq_spi_init(void)
++{
++	return platform_driver_probe(&ltq_spi_driver, ltq_spi_probe);
++}
++module_init(ltq_spi_init);
++
++static void __exit ltq_spi_exit(void)
++{
++	platform_driver_unregister(&ltq_spi_driver);
++}
++module_exit(ltq_spi_exit);
++
++MODULE_DESCRIPTION("Lantiq SoC SPI controller driver");
++MODULE_AUTHOR("Daniel Schwierzeck <[email protected]>");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:ltq-spi");

+ 49 - 0
target/linux/lantiq/patches-2.6.32/420-spi3.patch

@@ -0,0 +1,49 @@
+From: Daniel Schwierzeck <[email protected]>
+Date: Thu, 3 Mar 2011 20:42:26 +0000 (+0100)
+Subject: MIPS: lantiq: Add device register helper for SPI controller and devices
+X-Git-Url: http://nbd.name/gitweb.cgi?p=lantiq.git;a=commitdiff_plain;h=b35b07062b718ece9b9cb7b23b12d83a087eafb0;hp=653c95b8b9066c9c6ac08bd64d0ceee439e9fd90
+
+MIPS: lantiq: Add device register helper for SPI controller and devices
+
+Signed-off-by: Daniel Schwierzeck <[email protected]>
+---
+
+--- a/arch/mips/lantiq/xway/devices.c
++++ b/arch/mips/lantiq/xway/devices.c
+@@ -21,6 +21,7 @@
+ #include <linux/io.h>
+ #include <linux/gpio.h>
+ #include <linux/leds.h>
++#include <linux/spi/spi.h>
+ 
+ #include <asm/bootinfo.h>
+ #include <asm/irq.h>
+@@ -119,3 +120,28 @@
+ 		platform_device_register(&ltq_etop);
+ 	}
+ }
++
++static struct resource ltq_spi_resources[] = {
++	{
++		.start  = LTQ_SSC_BASE_ADDR,
++		.end    = LTQ_SSC_BASE_ADDR + LTQ_SSC_SIZE - 1,
++		.flags  = IORESOURCE_MEM,
++	},
++	IRQ_RES(spi_tx, LTQ_SSC_TIR),
++	IRQ_RES(spi_rx, LTQ_SSC_RIR),
++	IRQ_RES(spi_err, LTQ_SSC_EIR),
++};
++
++static struct platform_device ltq_spi = {
++	.name		= "ltq-spi",
++	.resource	= ltq_spi_resources,
++	.num_resources	= ARRAY_SIZE(ltq_spi_resources),
++};
++
++void __init ltq_register_spi(struct ltq_spi_platform_data *pdata,
++		struct spi_board_info const *info, unsigned n)
++{
++	spi_register_board_info(info, n);
++	ltq_spi.dev.platform_data = pdata;
++	platform_device_register(&ltq_spi);
++}

+ 41 - 0
target/linux/lantiq/patches-2.6.32/500-register_ebu.patch

@@ -0,0 +1,41 @@
+--- a/arch/mips/lantiq/xway/devices.c
++++ b/arch/mips/lantiq/xway/devices.c
+@@ -121,6 +121,29 @@
+ 	}
+ }
+ 
++/* ebu */
++static struct resource ltq_ebu_resource =
++{
++	.name   = "gpio_ebu",
++	.start  = LTQ_EBU_GPIO_START,
++	.end    = LTQ_EBU_GPIO_START + LTQ_EBU_GPIO_SIZE - 1,
++	.flags  = IORESOURCE_MEM,
++};
++
++static struct platform_device ltq_ebu =
++{
++	.name           = "ltq_ebu",
++	.resource       = &ltq_ebu_resource,
++	.num_resources  = 1,
++};
++
++void __init
++ltq_register_gpio_ebu(unsigned int value)
++{
++	ltq_ebu.dev.platform_data = (void*) value;
++	platform_device_register(&ltq_ebu);
++}
++
+ static struct resource ltq_spi_resources[] = {
+ 	{
+ 		.start  = LTQ_SSC_BASE_ADDR,
+--- a/arch/mips/lantiq/xway/devices.h
++++ b/arch/mips/lantiq/xway/devices.h
+@@ -16,5 +16,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 ltq_register_gpio_ebu(unsigned int value);
+ 
+ #endif

+ 28 - 0
target/linux/lantiq/patches-2.6.32/510-register_madwifi.patch

@@ -0,0 +1,28 @@
+--- a/arch/mips/lantiq/xway/devices.c
++++ b/arch/mips/lantiq/xway/devices.c
+@@ -144,6 +144,16 @@
+ 	platform_device_register(&ltq_ebu);
+ }
+ 
++/* madwifi */
++int lantiq_emulate_madwifi_eep = 0;
++EXPORT_SYMBOL(lantiq_emulate_madwifi_eep);
++
++void __init
++ltq_register_madwifi_eep(void)
++{
++	lantiq_emulate_madwifi_eep = 1;
++}
++
+ static struct resource ltq_spi_resources[] = {
+ 	{
+ 		.start  = LTQ_SSC_BASE_ADDR,
+--- a/arch/mips/lantiq/xway/devices.h
++++ b/arch/mips/lantiq/xway/devices.h
+@@ -17,5 +17,6 @@
+ extern void ltq_register_ase_asc(void);
+ extern void ltq_register_etop(struct ltq_eth_data *eth);
+ extern void ltq_register_gpio_ebu(unsigned int value);
++extern void ltq_register_madwifi_eep(void);
+ 
+ #endif

+ 46 - 0
target/linux/lantiq/patches-2.6.32/520-register_buttons.patch

@@ -0,0 +1,46 @@
+--- a/arch/mips/lantiq/xway/devices.c
++++ b/arch/mips/lantiq/xway/devices.c
+@@ -154,6 +154,26 @@
+ 	lantiq_emulate_madwifi_eep = 1;
+ }
+ 
++/* gpio buttons */
++static struct gpio_buttons_platform_data ltq_gpio_buttons_platform_data;
++
++static struct platform_device ltq_gpio_buttons_platform_device =
++{
++	.name = "gpio-buttons",
++	.id = 0,
++	.dev = {
++		.platform_data = (void *) &ltq_gpio_buttons_platform_data,
++	},
++};
++
++void __init
++ltq_register_gpio_buttons(struct gpio_button *buttons, int cnt)
++{
++	ltq_gpio_buttons_platform_data.buttons = buttons;
++	ltq_gpio_buttons_platform_data.nbuttons = cnt;
++	platform_device_register(&ltq_gpio_buttons_platform_device);
++}
++
+ static struct resource ltq_spi_resources[] = {
+ 	{
+ 		.start  = LTQ_SSC_BASE_ADDR,
+--- a/arch/mips/lantiq/xway/devices.h
++++ b/arch/mips/lantiq/xway/devices.h
+@@ -11,6 +11,7 @@
+ 
+ #include "../devices.h"
+ #include <linux/phy.h>
++#include <linux/gpio_buttons.h>
+ 
+ extern void ltq_register_gpio(void);
+ extern void ltq_register_gpio_stp(void);
+@@ -18,5 +19,6 @@
+ extern void ltq_register_etop(struct ltq_eth_data *eth);
+ extern void ltq_register_gpio_ebu(unsigned int value);
+ extern void ltq_register_madwifi_eep(void);
++extern void ltq_register_gpio_buttons(struct gpio_button *buttons, int cnt);
+ 
+ #endif

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác