diff --git a/package/nozomi/Makefile b/package/nozomi/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..6a698032bc4ee1d3098c7c522e7d64910a2215e6
--- /dev/null
+++ b/package/nozomi/Makefile
@@ -0,0 +1,50 @@
+# 
+# Copyright (C) 2006 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# $Id: Makefile 4855 2006-09-24 20:49:31Z nico $
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=nozomi
+PKG_VERSION:=060209
+PKG_RELEASE:=1
+
+PKG_SOURCE:=nozomi_$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=http://www.pharscape.org/3G
+PKG_MD5SUM:=a90e4d8f389a18b5579f7234a23e32e99
+PKG_CAT:=zcat
+
+PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+PKG_UNPACK:=mkdir -p $(PKG_BUILD_DIR); $(ZCAT) $(DL_DIR)/$(PKG_SOURCE) | $(TAR) -C $(PKG_BUILD_DIR) $(TAR_OPTIONS)
+
+define KernelPackage/nozomi
+  SUBMENU:=Other modules
+  TITLE:=Option Globetrotter HSDPA driver
+  DESCRIPTION:=Option Globetrotter HSDPA driver
+  URL:=http://www.pharscape.org/
+  VERSION:=$(LINUX_VERSION)+$(PKG_VERSION)-$(BOARD)-$(PKG_RELEASE)
+  FILES:=$(PKG_BUILD_DIR)/noz.$(LINUX_KMOD_SUFFIX)
+  AUTOLOAD:=$(call AutoLoad,70,noz)
+endef
+
+define Build/Configure
+	$(CP) ./files/Makefile $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+	$(MAKE) -C "$(LINUX_DIR)" \
+		CROSS_COMPILE="$(TARGET_CROSS)" \
+		ARCH="$(LINUX_KARCH)" \
+		PATH="$(TARGET_PATH)" \
+		SUBDIRS="$(PKG_BUILD_DIR)" \
+		modules
+endef
+
+$(eval $(call KernelPackage,nozomi))
diff --git a/package/nozomi/files/Makefile b/package/nozomi/files/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..85ea948f6f0043e4792a16c8369b6d40bd7f8f57
--- /dev/null
+++ b/package/nozomi/files/Makefile
@@ -0,0 +1,15 @@
+# $Id$
+
+O_TARGET	:= noz.o
+
+export-objs	:= nozomi.o kfifo.o
+
+list-multi := noz.o
+noz-objs := nozomi.o kfifo.o
+
+obj-m := noz.o
+
+include $(TOPDIR)/Rules.make
+
+noz.o:	$(noz-objs)
+	$(LD) -r -o $@ $(noz-objs) 
diff --git a/package/nozomi/patches/001-devfs.patch b/package/nozomi/patches/001-devfs.patch
new file mode 100644
index 0000000000000000000000000000000000000000..a532e579ff9460ee6716430c636bfceca4b5a195
--- /dev/null
+++ b/package/nozomi/patches/001-devfs.patch
@@ -0,0 +1,19 @@
+--- kmod-nozomi.orig/nozomi.c	2006-02-09 18:07:27.000000000 +0100
++++ kmod-nozomi/nozomi.c	2006-09-06 10:55:48.000000000 +0200
+@@ -2093,11 +2093,15 @@
+ 
+ 	td->magic                 = TTY_DRIVER_MAGIC;
+ 	td->driver_name           = NOZOMI_NAME_TTY;
++#ifndef CONFIG_DEVFS_FS
+ 	td->name                  = "noz";
++#else
++	td->name                  = "noz%d";
++#endif
+ 	td->major                 = NTTY_TTY_MAJOR,
+ 	td->type                  = TTY_DRIVER_TYPE_SERIAL,
+ 	td->subtype               = SERIAL_TYPE_NORMAL,
+-	td->flags                 = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
++	td->flags                 = TTY_DRIVER_REAL_RAW,
+ 	td->init_termios          = tty_std_termios;
+ 	td->init_termios.c_cflag  = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
+ 
diff --git a/package/nozomi/patches/002-nozomi_vf_01.patch b/package/nozomi/patches/002-nozomi_vf_01.patch
new file mode 100644
index 0000000000000000000000000000000000000000..77dca1fbbfee7e97d7bc20a93f96fa3b87cad687
--- /dev/null
+++ b/package/nozomi/patches/002-nozomi_vf_01.patch
@@ -0,0 +1,251 @@
+--- nozomi/nozomi.c.orig	2006-04-16 12:15:42.000000000 +0100
++++ nozomi/nozomi.c	2006-04-19 18:27:29.000000000 +0100
+@@ -7,6 +7,9 @@
+  *
+  * Maintained by: Paul Hardwick, p.hardwick@option.com
+  *
++ * Patches:
++ *          Locking code changes for Vodafone, Andrew Bird & Phil Sanderson
++ *
+  * Source has been ported from an implementation made by Filip Aben, f.aben@option.com
+  *
+  * --------------------------------------------------------------------------
+@@ -61,6 +64,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/kmod.h>
+ #include <linux/proc_fs.h>
++#include <linux/init.h>
+ #include <asm/uaccess.h>
+ 
+ 
+@@ -133,23 +137,23 @@
+ /* TODO: rewrite to optimize macros... */
+ #define SET_FCR(value__) \
+   do {  \
+-	writew((value__), (void*) (dc->REG_FCR )); \
++	writew((value__), (dc->REG_FCR )); \
+ } while(0)
+ 
+ #define SET_IER(value__, mask__) \
+   do {  \
+ 	dc->ier_last_written = (dc->ier_last_written & ~mask__) | (value__ & mask__ );\
+-    writew( dc->ier_last_written, (void*) (dc->REG_IER));\
++    writew( dc->ier_last_written, (dc->REG_IER));\
+ } while(0)
+ 
+ #define GET_IER(read_val__) \
+   do {  \
+-	(read_val__) = readw((void*) (dc->REG_IER));\
++	(read_val__) = readw((dc->REG_IER));\
+ } while(0)
+ 
+ #define GET_IIR(read_val__) \
+   do {  \
+-	(read_val__) = readw((void*) (dc->REG_IIR));\
++	(read_val__) = readw( (dc->REG_IIR));\
+ } while(0)
+ 
+ #define GET_MEM(value__, addr__, length__) \
+@@ -265,7 +268,7 @@
+ /* There are two types of nozomi cards, one with 2048 memory and with 8192 memory */
+ typedef enum {
+ 	F32_2 = 2048, /* Has 512 bytes downlink and uplink * 2             -> 2048 */
+-	F32_8 = 9192, /* Has 3072 bytes downlink and 1024 bytes uplink * 2 -> 8192 */
++	F32_8 = 8192, /* Has 3072 bytes downlink and 1024 bytes uplink * 2 -> 8192 */
+ } card_type_t;
+ 
+ /* Two different toggle channels exist */
+@@ -438,12 +441,12 @@
+ 	u32				     base_addr;
+ 	u8				     closing;
+ 
+-	/* Register addresses */
+-	u32				     REG_IIR;
+-	u32				     REG_FCR;
+-	u32				     REG_IER;
++   /* Pointers to registers ( register is tagged volatile, not pointer ) */
++	volatile u16 * REG_IIR;
++	volatile u16 * REG_FCR;
++	volatile u16 * REG_IER;
+ 
+-	volatile u16		 ier_last_written;
++	u16		 ier_last_written;
+ 	card_type_t 	     card_type;
+ 	config_table_t 	     config_table; /* Configuration table */
+ 	struct pci_dev 	    *pdev;
+@@ -490,7 +493,7 @@
+ 
+ /* Used to store interrupt variables */
+ typedef struct {
+-	volatile u16 read_iir; /* Holds current interrupt tokens */
++	u16 read_iir; /* Holds current interrupt tokens */
+ } irq_t;
+ 
+ MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl);
+@@ -1345,9 +1348,9 @@
+ 	u32 offset = dc->base_addr + dc->card_type/2;
+ 	int i;
+ 
+-	dc->REG_FCR = offset + R_FCR;
+-	dc->REG_IIR = offset + R_IIR;
+-	dc->REG_IER = offset + R_IER;
++	dc->REG_FCR = (u16 *) (offset + R_FCR);
++	dc->REG_IIR = (u16 *) (offset + R_IIR);
++	dc->REG_IER = (u16 *) (offset + R_IER);
+ 	dc->ier_last_written = 0;
+ 	dc->closing = 0;
+ 
+@@ -1366,13 +1369,16 @@
+ static void tty_flip_queue_function(void *tmp_dc) {
+ 	dc_t *dc = (dc_t*) tmp_dc;
+ 	int i;
++   u32 flags;
+ 
+ 	/* Enable interrupt for that port */
+ 	for(i=0;i<MAX_PORT;i++) {
+ 		if (dc->port[i].tty_dont_flip) {
+ 			D6("Enable for port: %d", i);
+ 			dc->port[i].tty_dont_flip = 0;
++         spin_lock_irqsave(&dc->spin_mutex, flags);
+ 			enable_transmit_dl(dc->port[i].tty_index, dc);
++         spin_unlock_irqrestore(&dc->spin_mutex, flags);
+ 		}
+ 	}
+ }
+@@ -1555,7 +1561,11 @@
+ 
+ static void tty_do_close(dc_t *dc, port_t *port) {
+ 
+-	down(&port->tty_sem);
++	u32      flags;
++
++	if(down_interruptible(&port->tty_sem)){
++      return;
++   }
+ 
+ 	if ( !port->tty_open_count ) {
+ 		goto exit;
+@@ -1569,7 +1579,9 @@
+ 
+ 	if ( port->tty_open_count == 0) {
+         D1("close: %d", port->token_dl );
++      spin_lock_irqsave(&dc->spin_mutex, flags);
+ 		SET_IER( 0,  port->token_dl );
++      spin_unlock_irqrestore(&dc->spin_mutex, flags);
+ 	}
+ 
+ exit:
+@@ -1679,8 +1691,11 @@
+ 	s32 index = get_index(tty);
+ 	port_t *port = get_port_by_tty(tty);
+ 	dc_t *dc = get_dc_by_tty(tty);
++	u32      flags;
+ 
+-	down(&port->tty_sem);
++   if(down_interruptible(&port->tty_sem)){
++      return -ERESTARTSYS;
++   }
+ 
+ 	tty->low_latency  = 1;
+ 	tty->driver_data  = port;
+@@ -1698,7 +1713,9 @@
+ 	if ( port->tty_open_count == 1) {
+ 		port->rx_data = port->tx_data = 0;
+         D1("open: %d", port->token_dl );
++      spin_lock_irqsave(&dc->spin_mutex, flags);
+ 		SET_IER( port->token_dl,  port->token_dl );
++      spin_unlock_irqrestore(&dc->spin_mutex, flags);
+ 	}
+ 
+ 	up(&port->tty_sem);
+@@ -1722,6 +1739,7 @@
+ 	int                  rval = -EINVAL;
+ 	dc_t                *dc = get_dc_by_tty(tty);
+ 	port_t              *port = (port_t *) tty->driver_data;
++	u32      flags;
+ 
+ 	/* D1( "WRITEx: %d, index = %d", count, index); */
+ 
+@@ -1729,7 +1747,10 @@
+ 		return -ENODEV;
+ 	}
+ 
+-	down(&port->tty_sem);
++   if(down_trylock(&port->tty_sem) ) { // must test lock as tty layer wraps calls to this function with BKL
++      ERR("Would have deadlocked - return ERESTARTSYS");
++      return -ERESTARTSYS;
++   }
+ 
+ 	if (! port->tty_open_count) {
+         D1( " ");
+@@ -1752,6 +1773,7 @@
+ 		goto exit;
+ 	}
+ 
++   spin_lock_irqsave(&dc->spin_mutex, flags);
+ 	// CTS is only valid on the modem channel
+ 	if ( port == &(dc->port[PORT_MDM]) ) {
+ 		if ( port->ctrl_dl.CTS ) {
+@@ -1763,6 +1785,7 @@
+ 	} else {
+ 		enable_transmit_ul(port->tty_index, dc );
+ 	}
++   spin_unlock_irqrestore(&dc->spin_mutex, flags);
+ 
+ exit:
+ 	up(&port->tty_sem);
+@@ -1782,7 +1805,9 @@
+         return 0;
+ 	}
+ 
+-	down(&port->tty_sem);
++   if(down_interruptible(&port->tty_sem)){
++      return 0;
++   }
+ 
+ 	if (! port->tty_open_count) {
+ 		goto exit;
+@@ -1969,6 +1994,8 @@
+ 
+ static int ntty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) {
+ 	port_t *port = (port_t *) tty->driver_data;
++	dc_t    *dc = get_dc_by_tty(tty);
++	u32      flags;
+ 	int mask;
+ 	int rval = -ENOIOCTLCMD;
+ 
+@@ -1991,7 +2018,9 @@
+ 		rval =  ntty_ioctl_tiocgicount(tty, file, cmd, arg);
+ 		break;
+ 	case TIOCMGET:
++      spin_lock_irqsave(&dc->spin_mutex, flags);
+ 		rval = ntty_tiocmget(tty, file);
++      spin_unlock_irqrestore(&dc->spin_mutex, flags);
+ 		break;
+ 	case TIOCMSET:
+ 		rval = ntty_tiocmset(tty, file, arg);
+@@ -2000,20 +2029,24 @@
+ 		if (get_user(mask, (unsigned long *) arg))
+ 			return -EFAULT;
+ 
++      spin_lock_irqsave(&dc->spin_mutex, flags);
+ 		if (mask & TIOCM_RTS)
+ 			set_rts(port->tty_index, 0);
+ 		if (mask & TIOCM_DTR)
+ 			set_dtr(port->tty_index, 0);
++      spin_unlock_irqrestore(&dc->spin_mutex, flags);
+ 		rval = 0;
+ 		break;
+    	case TIOCMBIS:
+ 		if (get_user(mask, (unsigned long *) arg))
+ 			return -EFAULT;
+ 
++      spin_lock_irqsave(&dc->spin_mutex, flags);
+ 		if (mask & TIOCM_RTS)
+ 			set_rts(port->tty_index, 1);
+ 		if (mask & TIOCM_DTR)
+ 			set_dtr(port->tty_index, 1);
++      spin_unlock_irqrestore(&dc->spin_mutex, flags);
+ 		rval = 0;
+ 		break;
+ 	case TCFLSH: