summaryrefslogtreecommitdiffstats
path: root/uClinux-2.4.20-uc1/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'uClinux-2.4.20-uc1/drivers/char')
-rw-r--r--uClinux-2.4.20-uc1/drivers/char/vdd.c944
-rwxr-xr-xuClinux-2.4.20-uc1/drivers/char/w90n745_i2c.c1200
-rw-r--r--uClinux-2.4.20-uc1/drivers/char/w90n745_i2c.h246
-rwxr-xr-xuClinux-2.4.20-uc1/drivers/char/w90n745_keypad.c506
-rwxr-xr-xuClinux-2.4.20-uc1/drivers/char/w90n745_keypad.h114
-rwxr-xr-xuClinux-2.4.20-uc1/drivers/char/w90n745_usi.c662
-rwxr-xr-xuClinux-2.4.20-uc1/drivers/char/w90n745_usi.h146
7 files changed, 1909 insertions, 1909 deletions
diff --git a/uClinux-2.4.20-uc1/drivers/char/vdd.c b/uClinux-2.4.20-uc1/drivers/char/vdd.c
index ff6c6d9..3661ebe 100644
--- a/uClinux-2.4.20-uc1/drivers/char/vdd.c
+++ b/uClinux-2.4.20-uc1/drivers/char/vdd.c
@@ -1,472 +1,472 @@
-/*
- * linux/drivers/char/vdd.c
- *
- * Winbond uclinux virtual debug device.
- * yyang1|pc32 030528
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/page.h>
-#include <linux/errno.h>
-
-#ifndef _DEBUG
-#define _DEBUG
-#endif
-#undef _DEBUG
-
-#ifndef EOF
-#define EOF (-1)
-#endif
-
-typedef unsigned char BYTE;
-typedef unsigned int BOOL;
-#define TRUE 1
-#define FALSE 0
-
-#define MALLOC(x) kmalloc((x), GFP_KERNEL)
-#define FREE kfree
-#define MEMCPY memcpy //or use "copy_to_user"
-
-#define DEBUGBUF_SIZE (1024 * 2)
-
-
-#define VDD_CLEAR 0x5901 //clear current queue
-#define MAX_VDD_DEV 2
-#define VDD_MAJOR 99
-
-typedef struct Queue
-{
- void * queue;
- size_t MaxSize;
- size_t begin;
- size_t end;
- size_t usage;
-} Queue_t;
-
-#ifdef CONFIG_DEVFS_FS
-#include <linux/devfs_fs_kernel.h>
-static devfs_handle_t devfs_vdd_handle[MAX_VDD_DEV];
-static DECLARE_MUTEX(vdd_table_mutex);
-#endif
-
-static Queue_t debug_queue = {NULL, DEBUGBUF_SIZE + 1, 0, 0, 0};
-
-static int vdd_open(struct inode *inode, struct file *filep);
-static int vdd_release(struct inode *inode, struct file *filep);
-static ssize_t vdd_read(struct file *filp, char * buf, size_t count, loff_t *f_pos);
-static ssize_t vdd_write(struct file *filp, const char * buf, size_t count, loff_t *f_pos);
-static loff_t vdd_llseek (struct file *, loff_t, int);
-static int vdd_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg);
-
-
-static struct file_operations vdd_ops =
-{
- open: vdd_open,
- read: vdd_read,
- write: vdd_write,
- llseek: vdd_llseek,
- release: vdd_release,
- ioctl: vdd_ioctl,
-};
-
-//----------------------------queue funcs----------------------------------//
-#define _Capacity() (debug_queue.MaxSize - 1)
-
-#define _IsEmpty() (debug_queue.begin == debug_queue.end)
-#define _IsFull() (((debug_queue.end + 1) % debug_queue.MaxSize == debug_queue.begin) ? TRUE : FALSE)
-#define _Free() (_Capacity() - _Size())
-
-#define _Begin() (debug_queue.begin)
-#define _End() (debug_queue.end)
-#define _nIterator(x) ((_Begin() + (x)) % debug_queue.MaxSize)
-
-#define _First() (((BYTE *)debug_queue.queue)[(debug_queue.begin + 1) % debug_queue.MaxSize])
-#define _Last() (((BYTE *)debug_queue.queue)[debug_queue.end])
-
-#define _Usage() (debug_queue.usage)
-
-static size_t _Size()
-{
- long diff_ = (long)debug_queue.end - (long)debug_queue.begin;
- return (diff_ >= 0) ? diff_ : (debug_queue.MaxSize + diff_);
-}
-
-static size_t _Distance(size_t begin, size_t end)
-{
- long diff_ = (long)end - (long)begin;
- return (diff_ >= 0) ? diff_ : (debug_queue.MaxSize + diff_);
-}
-
-static BYTE _nElement(size_t index) // index = 0 --> *(begin + 1)
-{
-// ASSERT((index >= 0) && (index < _Size()));
- return ((BYTE *)debug_queue.queue)[_nIterator(index + 1)];
-}
-
-static void _Delete()
-{
- if (_IsEmpty())
- return;
-
- debug_queue.begin = (debug_queue.begin + 1) % debug_queue.MaxSize;
-}
-
-static void _Add(BYTE x)
-{
- if (_IsFull())
- _Delete();
-
- debug_queue.end = (debug_queue.end + 1) % debug_queue.MaxSize;
- ((BYTE *)debug_queue.queue)[debug_queue.end] = x;
-}
-
-//random and memcpy to optimize..
-static size_t N_copy(void *buf, size_t begin, size_t end)
-{
- void * src_, *dst_ = buf;
- size_t copy_num = 0;
-
-// ASSERT(buf && (begin < debug_queue.MaxSize) && (end < debug_queue.MaxSize));
-
- if(end == begin)
- return 0;
-
- if(end < begin)
- {
- size_t split_diff = _Capacity() - begin;
- if(split_diff)
- {
- (BYTE *)src_ = (BYTE *)debug_queue.queue + (begin + 1) % _Capacity();
- MEMCPY(dst_, src_, split_diff);
- copy_num += split_diff;
- (BYTE *)dst_ += copy_num;
- }
-
- src_ = debug_queue.queue;
- MEMCPY(dst_, src_, end + 1);
- copy_num += end + 1;
- }
- else // greater than
- {
- copy_num = end - begin;
- (BYTE *)src_ = (BYTE *)debug_queue.queue + begin + 1;
- MEMCPY(dst_, src_, copy_num);
- }
-
- return copy_num;
-}
-
-static void N_Delete(size_t n)
-{
- if (_Size() < n)
- {
- debug_queue.begin = debug_queue.end;
- return;
- }
-
- debug_queue.begin = (debug_queue.begin + n) % debug_queue.MaxSize;
-}
-
-static void N_Add(const void *buf, size_t count)
-{
- size_t freed_;
- size_t valid_ = (count > _Capacity()) ? _Capacity() : count;
- void * src_, *dst_;
- src_ = (BYTE *)buf + count - valid_;
- dst_ = (BYTE *)debug_queue.queue + (debug_queue.end + 1) % debug_queue.MaxSize;
-
-#ifdef _DEBUG
- printk("***N_Add(buf = 0x%x, count = %d).\n", buf, count);
-#endif
-
- freed_ = _Free();
- if (freed_ < valid_)
- {
-#ifdef _DEBUG
- printk("Free: %d, valid %d.\n", _Free(), valid_);
-#endif
-
- N_Delete(valid_ - freed_);
- }
-
- if(debug_queue.end >= debug_queue.begin)
- {
- size_t split_diff = _Capacity() - debug_queue.end;
- if(valid_ > split_diff)
- {
- MEMCPY(dst_, src_, split_diff);
-
- debug_queue.end = _Capacity();
-
- (BYTE *)src_ += split_diff;
- valid_ -= split_diff;
- dst_ = debug_queue.queue;
- }
- }
-
- MEMCPY(dst_, src_, valid_);
- debug_queue.end = ((BYTE *)dst_ - (BYTE *)debug_queue.queue) + valid_ - 1;
-}
-
-//----------------------------driver funcs----------------------------------//
-static int vdd_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg)
-{
-
-
-#ifdef _DEBUG
- printk("***vdd_ioctl: cmd = 0x%x, arg = 0x%x\n", cmd, arg);
-#endif
-
- switch(cmd)
- {
- case VDD_CLEAR:
- {
- debug_queue.begin = debug_queue.end = 0;
-
-#ifdef _DEBUG
- printk("***vdd_ioctl[VDD_CLEAR], now queue size = %d.\n", _Size());
-#endif
-
- break;
- }
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static loff_t vdd_llseek (struct file *filp, loff_t off, int whence)
-{
- long newpos;
-
-#ifdef _DEBUG
- printk("*** 1 vdd_llseek off = %llu, whence = %d.\n", off, whence);
-#endif
-
- switch(whence)
- {
- case 0: //begin
- newpos = off;
- break;
-
- case 1: //current
- newpos = filp->f_pos + off;
- break;
-
- case 2: //end
- newpos = _Size() + off;
- break;
-
- default:
- return -EINVAL;
- }
-
- if(newpos < 0)
- return -EINVAL;
-
- filp->f_pos = newpos;
-
-#ifdef _DEBUG
- printk("*** 2 vdd_llseek newpos = %d, f_pos = %llu, whence = %d.\n", newpos, filp->f_pos, whence);
-#endif
-
- return newpos;
-}
-
-static ssize_t vdd_read(struct file *filep, char * buf, size_t count, loff_t *f_pos)
-{
- size_t read_num = 0;
- size_t begin_, end_;
-
- if(!debug_queue.queue || !count)
- return 0;
-
-#ifdef _DEBUG
- printk("***before debug_read count = %d, buf = 0x%x, f_pos = 0x%x.\n", count, buf, filep->f_pos);
-#endif
-
-#if 0
-
- begin_ = (count >= _Size()) ? _Begin() : (_nIterator(_Size() - count));
- read_num = N_copy(buf, begin_, _End());
-
-#else
-
- if(filep->f_pos >= _Size())
- {
- //filep->f_pos = 0; //if end, then lseek to begin...
- read_num = 0;
- }
- else
- {
- begin_ = _nIterator(filep->f_pos);
- end_ = (count >= _Distance(begin_, _End())) ? _End() : (_nIterator(_Distance(_Begin(), begin_) + count));
-
- _Usage()++;
- read_num = N_copy(buf, begin_, end_);
- _Usage()--;
-
-#ifdef _DEBUG
- printk("***debug_reading begin_ = %d, end_ = %d, read_num = %d.\n", begin_, end_, read_num);
-#endif
- filep->f_pos += read_num;
- }
-
-#endif
-
-#ifdef _DEBUG
- printk("***after debug_read count = %d, buf = 0x%x, f_pos = 0x%x.\n", count, buf, filep->f_pos);
-#endif
-
- return read_num;
-}
-
-static ssize_t vdd_write(struct file *filep, const char * buf, size_t count, loff_t *f_pos)
-{
- if(!debug_queue.queue)
- return 0;
-
- _Usage()++;
- N_Add(buf, count);
- _Usage()--;
-
-#ifdef _DEBUG
- printk("***debug_write count = %d, buf = 0x%x, f_pos = 0x%x.\n", count, buf, filep->f_pos);
-#endif
-
- return count;
-}
-
-
-
-
-static int vdd_open(struct inode *inode, struct file *filep)
-{
- unsigned int dev = MINOR(inode->i_rdev);
-
- if(dev >= MAX_VDD_DEV)
- return -EFAULT;
-
- //030529?
- if(_Usage())
- return -EFAULT;
-
- filep->f_op = &vdd_ops;
- filep->f_pos = 0;
-
- MOD_INC_USE_COUNT;
-
-#ifdef _DEBUG
- printk("open VDD[vdd%d] succeed!\n", dev);
-#endif
-
- return 0;
-}
-
-static int vdd_release(struct inode *inode, struct file *filep)
-{
- MOD_DEC_USE_COUNT;
-
-#ifdef _DEBUG
- printk("close VDD succeed!\n");
-#endif
- return 0;
-}
-#ifdef CONFIG_DEVFS_FS
-static void register_vdd_usr(void)
-{
- int i;
-
- down(&vdd_table_mutex);
-
- MOD_INC_USE_COUNT;
-
- for (i=0; i< MAX_VDD_DEV; i++)
- {
- char name[8];
- sprintf(name, "vdd%d", i);
-
- devfs_vdd_handle[i] = devfs_register(NULL, name,
- DEVFS_FL_DEFAULT, VDD_MAJOR, i,
- S_IFCHR | S_IRUGO | S_IWUGO,
- &vdd_ops, NULL);
-
- }
-
- up(&vdd_table_mutex);
-}
-
-static void unregister_vdd_usr(void)
-{
- int i;
-
- down(&vdd_table_mutex);
-
- MOD_DEC_USE_COUNT;
-
- for (i=0; i< MAX_VDD_DEV; i++)
- devfs_unregister(devfs_vdd_handle[i]);
-
- up(&vdd_table_mutex);
-}
-#endif
-//----------------------------module funcs----------------------------------//
-int vdd_init(void)
-{
- int result;
-
-#ifdef _DEBUG
- char *cptr = "Winbond Virtual Debug Device[c, 2k, round queue]!\n";
- printk("****vdd initing...");
-#endif
-#ifdef CONFIG_DEVFS_FS
- result = devfs_register_chrdev(VDD_MAJOR, "vdd", &vdd_ops);
- if(result < 0)
- {
- printk("VDD: can't register vdd.\n");
- return result;
- }
-
- register_vdd_usr();
-#else
- result = register_chrdev(VDD_MAJOR, "vdd", &vdd_ops);
- if(result < 0)
- {
- printk("VDD: can't register vdd.\n");
- return result;
- }
-#endif
- if(!debug_queue.queue)
- debug_queue.queue = MALLOC(debug_queue.MaxSize);
-
-#ifdef _DEBUG
- N_Add(cptr, strlen(cptr));
-#endif
- return 0;
-}
-
-void vdd_cleanup(void)
-{
- if(debug_queue.queue)
- {
- FREE(debug_queue.queue);
- debug_queue.queue = NULL;
- }
-#ifdef CONFIG_DEVFS_FS
- unregister_vdd_usr();
- devfs_unregister_chrdev(VDD_MAJOR, "vdd");
-#else
- unregister_chrdev(VDD_MAJOR, "vdd");
-#endif
-}
-
-module_init(vdd_init);
-module_exit(vdd_cleanup);
+/*
+ * linux/drivers/char/vdd.c
+ *
+ * Winbond uclinux virtual debug device.
+ * yyang1|pc32 030528
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <linux/errno.h>
+
+#ifndef _DEBUG
+#define _DEBUG
+#endif
+#undef _DEBUG
+
+#ifndef EOF
+#define EOF (-1)
+#endif
+
+typedef unsigned char BYTE;
+typedef unsigned int BOOL;
+#define TRUE 1
+#define FALSE 0
+
+#define MALLOC(x) kmalloc((x), GFP_KERNEL)
+#define FREE kfree
+#define MEMCPY memcpy //or use "copy_to_user"
+
+#define DEBUGBUF_SIZE (1024 * 2)
+
+
+#define VDD_CLEAR 0x5901 //clear current queue
+#define MAX_VDD_DEV 2
+#define VDD_MAJOR 99
+
+typedef struct Queue
+{
+ void * queue;
+ size_t MaxSize;
+ size_t begin;
+ size_t end;
+ size_t usage;
+} Queue_t;
+
+#ifdef CONFIG_DEVFS_FS
+#include <linux/devfs_fs_kernel.h>
+static devfs_handle_t devfs_vdd_handle[MAX_VDD_DEV];
+static DECLARE_MUTEX(vdd_table_mutex);
+#endif
+
+static Queue_t debug_queue = {NULL, DEBUGBUF_SIZE + 1, 0, 0, 0};
+
+static int vdd_open(struct inode *inode, struct file *filep);
+static int vdd_release(struct inode *inode, struct file *filep);
+static ssize_t vdd_read(struct file *filp, char * buf, size_t count, loff_t *f_pos);
+static ssize_t vdd_write(struct file *filp, const char * buf, size_t count, loff_t *f_pos);
+static loff_t vdd_llseek (struct file *, loff_t, int);
+static int vdd_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg);
+
+
+static struct file_operations vdd_ops =
+{
+ open: vdd_open,
+ read: vdd_read,
+ write: vdd_write,
+ llseek: vdd_llseek,
+ release: vdd_release,
+ ioctl: vdd_ioctl,
+};
+
+//----------------------------queue funcs----------------------------------//
+#define _Capacity() (debug_queue.MaxSize - 1)
+
+#define _IsEmpty() (debug_queue.begin == debug_queue.end)
+#define _IsFull() (((debug_queue.end + 1) % debug_queue.MaxSize == debug_queue.begin) ? TRUE : FALSE)
+#define _Free() (_Capacity() - _Size())
+
+#define _Begin() (debug_queue.begin)
+#define _End() (debug_queue.end)
+#define _nIterator(x) ((_Begin() + (x)) % debug_queue.MaxSize)
+
+#define _First() (((BYTE *)debug_queue.queue)[(debug_queue.begin + 1) % debug_queue.MaxSize])
+#define _Last() (((BYTE *)debug_queue.queue)[debug_queue.end])
+
+#define _Usage() (debug_queue.usage)
+
+static size_t _Size()
+{
+ long diff_ = (long)debug_queue.end - (long)debug_queue.begin;
+ return (diff_ >= 0) ? diff_ : (debug_queue.MaxSize + diff_);
+}
+
+static size_t _Distance(size_t begin, size_t end)
+{
+ long diff_ = (long)end - (long)begin;
+ return (diff_ >= 0) ? diff_ : (debug_queue.MaxSize + diff_);
+}
+
+static BYTE _nElement(size_t index) // index = 0 --> *(begin + 1)
+{
+// ASSERT((index >= 0) && (index < _Size()));
+ return ((BYTE *)debug_queue.queue)[_nIterator(index + 1)];
+}
+
+static void _Delete()
+{
+ if (_IsEmpty())
+ return;
+
+ debug_queue.begin = (debug_queue.begin + 1) % debug_queue.MaxSize;
+}
+
+static void _Add(BYTE x)
+{
+ if (_IsFull())
+ _Delete();
+
+ debug_queue.end = (debug_queue.end + 1) % debug_queue.MaxSize;
+ ((BYTE *)debug_queue.queue)[debug_queue.end] = x;
+}
+
+//random and memcpy to optimize..
+static size_t N_copy(void *buf, size_t begin, size_t end)
+{
+ void * src_, *dst_ = buf;
+ size_t copy_num = 0;
+
+// ASSERT(buf && (begin < debug_queue.MaxSize) && (end < debug_queue.MaxSize));
+
+ if(end == begin)
+ return 0;
+
+ if(end < begin)
+ {
+ size_t split_diff = _Capacity() - begin;
+ if(split_diff)
+ {
+ (BYTE *)src_ = (BYTE *)debug_queue.queue + (begin + 1) % _Capacity();
+ MEMCPY(dst_, src_, split_diff);
+ copy_num += split_diff;
+ (BYTE *)dst_ += copy_num;
+ }
+
+ src_ = debug_queue.queue;
+ MEMCPY(dst_, src_, end + 1);
+ copy_num += end + 1;
+ }
+ else // greater than
+ {
+ copy_num = end - begin;
+ (BYTE *)src_ = (BYTE *)debug_queue.queue + begin + 1;
+ MEMCPY(dst_, src_, copy_num);
+ }
+
+ return copy_num;
+}
+
+static void N_Delete(size_t n)
+{
+ if (_Size() < n)
+ {
+ debug_queue.begin = debug_queue.end;
+ return;
+ }
+
+ debug_queue.begin = (debug_queue.begin + n) % debug_queue.MaxSize;
+}
+
+static void N_Add(const void *buf, size_t count)
+{
+ size_t freed_;
+ size_t valid_ = (count > _Capacity()) ? _Capacity() : count;
+ void * src_, *dst_;
+ src_ = (BYTE *)buf + count - valid_;
+ dst_ = (BYTE *)debug_queue.queue + (debug_queue.end + 1) % debug_queue.MaxSize;
+
+#ifdef _DEBUG
+ printk("***N_Add(buf = 0x%x, count = %d).\n", buf, count);
+#endif
+
+ freed_ = _Free();
+ if (freed_ < valid_)
+ {
+#ifdef _DEBUG
+ printk("Free: %d, valid %d.\n", _Free(), valid_);
+#endif
+
+ N_Delete(valid_ - freed_);
+ }
+
+ if(debug_queue.end >= debug_queue.begin)
+ {
+ size_t split_diff = _Capacity() - debug_queue.end;
+ if(valid_ > split_diff)
+ {
+ MEMCPY(dst_, src_, split_diff);
+
+ debug_queue.end = _Capacity();
+
+ (BYTE *)src_ += split_diff;
+ valid_ -= split_diff;
+ dst_ = debug_queue.queue;
+ }
+ }
+
+ MEMCPY(dst_, src_, valid_);
+ debug_queue.end = ((BYTE *)dst_ - (BYTE *)debug_queue.queue) + valid_ - 1;
+}
+
+//----------------------------driver funcs----------------------------------//
+static int vdd_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, unsigned long arg)
+{
+
+
+#ifdef _DEBUG
+ printk("***vdd_ioctl: cmd = 0x%x, arg = 0x%x\n", cmd, arg);
+#endif
+
+ switch(cmd)
+ {
+ case VDD_CLEAR:
+ {
+ debug_queue.begin = debug_queue.end = 0;
+
+#ifdef _DEBUG
+ printk("***vdd_ioctl[VDD_CLEAR], now queue size = %d.\n", _Size());
+#endif
+
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static loff_t vdd_llseek (struct file *filp, loff_t off, int whence)
+{
+ long newpos;
+
+#ifdef _DEBUG
+ printk("*** 1 vdd_llseek off = %llu, whence = %d.\n", off, whence);
+#endif
+
+ switch(whence)
+ {
+ case 0: //begin
+ newpos = off;
+ break;
+
+ case 1: //current
+ newpos = filp->f_pos + off;
+ break;
+
+ case 2: //end
+ newpos = _Size() + off;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if(newpos < 0)
+ return -EINVAL;
+
+ filp->f_pos = newpos;
+
+#ifdef _DEBUG
+ printk("*** 2 vdd_llseek newpos = %d, f_pos = %llu, whence = %d.\n", newpos, filp->f_pos, whence);
+#endif
+
+ return newpos;
+}
+
+static ssize_t vdd_read(struct file *filep, char * buf, size_t count, loff_t *f_pos)
+{
+ size_t read_num = 0;
+ size_t begin_, end_;
+
+ if(!debug_queue.queue || !count)
+ return 0;
+
+#ifdef _DEBUG
+ printk("***before debug_read count = %d, buf = 0x%x, f_pos = 0x%x.\n", count, buf, filep->f_pos);
+#endif
+
+#if 0
+
+ begin_ = (count >= _Size()) ? _Begin() : (_nIterator(_Size() - count));
+ read_num = N_copy(buf, begin_, _End());
+
+#else
+
+ if(filep->f_pos >= _Size())
+ {
+ //filep->f_pos = 0; //if end, then lseek to begin...
+ read_num = 0;
+ }
+ else
+ {
+ begin_ = _nIterator(filep->f_pos);
+ end_ = (count >= _Distance(begin_, _End())) ? _End() : (_nIterator(_Distance(_Begin(), begin_) + count));
+
+ _Usage()++;
+ read_num = N_copy(buf, begin_, end_);
+ _Usage()--;
+
+#ifdef _DEBUG
+ printk("***debug_reading begin_ = %d, end_ = %d, read_num = %d.\n", begin_, end_, read_num);
+#endif
+ filep->f_pos += read_num;
+ }
+
+#endif
+
+#ifdef _DEBUG
+ printk("***after debug_read count = %d, buf = 0x%x, f_pos = 0x%x.\n", count, buf, filep->f_pos);
+#endif
+
+ return read_num;
+}
+
+static ssize_t vdd_write(struct file *filep, const char * buf, size_t count, loff_t *f_pos)
+{
+ if(!debug_queue.queue)
+ return 0;
+
+ _Usage()++;
+ N_Add(buf, count);
+ _Usage()--;
+
+#ifdef _DEBUG
+ printk("***debug_write count = %d, buf = 0x%x, f_pos = 0x%x.\n", count, buf, filep->f_pos);
+#endif
+
+ return count;
+}
+
+
+
+
+static int vdd_open(struct inode *inode, struct file *filep)
+{
+ unsigned int dev = MINOR(inode->i_rdev);
+
+ if(dev >= MAX_VDD_DEV)
+ return -EFAULT;
+
+ //030529?
+ if(_Usage())
+ return -EFAULT;
+
+ filep->f_op = &vdd_ops;
+ filep->f_pos = 0;
+
+ MOD_INC_USE_COUNT;
+
+#ifdef _DEBUG
+ printk("open VDD[vdd%d] succeed!\n", dev);
+#endif
+
+ return 0;
+}
+
+static int vdd_release(struct inode *inode, struct file *filep)
+{
+ MOD_DEC_USE_COUNT;
+
+#ifdef _DEBUG
+ printk("close VDD succeed!\n");
+#endif
+ return 0;
+}
+#ifdef CONFIG_DEVFS_FS
+static void register_vdd_usr(void)
+{
+ int i;
+
+ down(&vdd_table_mutex);
+
+ MOD_INC_USE_COUNT;
+
+ for (i=0; i< MAX_VDD_DEV; i++)
+ {
+ char name[8];
+ sprintf(name, "vdd%d", i);
+
+ devfs_vdd_handle[i] = devfs_register(NULL, name,
+ DEVFS_FL_DEFAULT, VDD_MAJOR, i,
+ S_IFCHR | S_IRUGO | S_IWUGO,
+ &vdd_ops, NULL);
+
+ }
+
+ up(&vdd_table_mutex);
+}
+
+static void unregister_vdd_usr(void)
+{
+ int i;
+
+ down(&vdd_table_mutex);
+
+ MOD_DEC_USE_COUNT;
+
+ for (i=0; i< MAX_VDD_DEV; i++)
+ devfs_unregister(devfs_vdd_handle[i]);
+
+ up(&vdd_table_mutex);
+}
+#endif
+//----------------------------module funcs----------------------------------//
+int vdd_init(void)
+{
+ int result;
+
+#ifdef _DEBUG
+ char *cptr = "Winbond Virtual Debug Device[c, 2k, round queue]!\n";
+ printk("****vdd initing...");
+#endif
+#ifdef CONFIG_DEVFS_FS
+ result = devfs_register_chrdev(VDD_MAJOR, "vdd", &vdd_ops);
+ if(result < 0)
+ {
+ printk("VDD: can't register vdd.\n");
+ return result;
+ }
+
+ register_vdd_usr();
+#else
+ result = register_chrdev(VDD_MAJOR, "vdd", &vdd_ops);
+ if(result < 0)
+ {
+ printk("VDD: can't register vdd.\n");
+ return result;
+ }
+#endif
+ if(!debug_queue.queue)
+ debug_queue.queue = MALLOC(debug_queue.MaxSize);
+
+#ifdef _DEBUG
+ N_Add(cptr, strlen(cptr));
+#endif
+ return 0;
+}
+
+void vdd_cleanup(void)
+{
+ if(debug_queue.queue)
+ {
+ FREE(debug_queue.queue);
+ debug_queue.queue = NULL;
+ }
+#ifdef CONFIG_DEVFS_FS
+ unregister_vdd_usr();
+ devfs_unregister_chrdev(VDD_MAJOR, "vdd");
+#else
+ unregister_chrdev(VDD_MAJOR, "vdd");
+#endif
+}
+
+module_init(vdd_init);
+module_exit(vdd_cleanup);
diff --git a/uClinux-2.4.20-uc1/drivers/char/w90n745_i2c.c b/uClinux-2.4.20-uc1/drivers/char/w90n745_i2c.c
index 7b9cd9b..fd0f815 100755
--- a/uClinux-2.4.20-uc1/drivers/char/w90n745_i2c.c
+++ b/uClinux-2.4.20-uc1/drivers/char/w90n745_i2c.c
@@ -1,600 +1,600 @@
-/****************************************************************************
- *
- * Copyright (c) 2004 - 2006 Winbond Electronics Corp. All rights reserved.
- *
- ****************************************************************************/
-
-/****************************************************************************
- *
- * FILENAME
- * w90n745_i2c.c
- *
- * VERSION
- * 1.0
- *
- * DESCRIPTION
- * Winbond W90N710 I2C Driver
- *
- * DATA STRUCTURES
- * None
- *
- * FUNCTIONS
- * None
- *
- * HISTORY
- * 2005/05/20 Ver 1.0 Created by PC34 QFu
- *
- * REMARK
- * None
- *************************************************************************/
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/semaphore.h>
-
-#include "w90n745_i2c.h"
-
-
-//#define I2C_DEBUG
-//#define I2C_DEBUG_PRINT_LINE
-//#define I2C_DEBUG_ENABLE_ENTER_LEAVE
-//#define I2C_DEBUG_ENABLE_MSG
-//#define I2C_DEBUG_ENABLE_MSG2
-
-#ifdef I2C_DEBUG
-#define PDEBUG(fmt, arg...) printk(fmt, ##arg)
-#else
-#define PDEBUG(fmt, arg...)
-#endif
-
-#ifdef I2C_DEBUG_PRINT_LINE
-#define PRN_LINE() PDEBUG("[%-20s] : %d\n", __FUNCTION__, __LINE__)
-#else
-#define PRN_LINE()
-#endif
-
-#ifdef I2C_DEBUG_ENABLE_ENTER_LEAVE
-#define ENTER() PDEBUG("[%-20s] : Enter...\n", __FUNCTION__)
-#define LEAVE() PDEBUG("[%-20s] : Leave...\n", __FUNCTION__)
-#else
-#define ENTER()
-#define LEAVE()
-#endif
-
-#ifdef I2C_DEBUG_ENABLE_MSG
-#define MSG(msg) PDEBUG("[%-20s] : %s", __FUNCTION__, msg)
-#else
-#define MSG(msg)
-#endif
-
-#ifdef I2C_DEBUG_ENABLE_MSG2
-#define MSG2(fmt, arg...) PDEBUG("[%-20s] : "fmt, __FUNCTION__, ##arg)
-#define PRNBUF(buf, count) {int i;MSG2("CID Data: ");for(i=0;i<count;i++)\
- PDEBUG("%02x ", buf[i]);PDEBUG("\n");}
-#else
-#define MSG2(fmt, arg...)
-#define PRNBUF(buf, count)
-#endif
-
-
-
-#define i2c_outl(dev, dword, addr) outl(dword, base[dev->no] + addr)
-#define i2c_inl(dev, addr) inl(base[dev->no] + addr)
-
-
-static const int base[I2C_NUMBER] = {I2C0_IO_BASE, I2C1_IO_BASE};
-static const int irq[I2C_NUMBER] = {I2C0_IRQ, I2C1_IRQ};
-static int bNackValid;
-
-static void i2c_Disable(i2c_dev *dev) /* Disable i2c core and interrupt */
-{
-
- i2c_outl(dev, 0x00, CSR);
-}
-
-static void i2c_Enable(i2c_dev *dev) /* Enable i2c core and interrupt */
-{
- i2c_outl(dev, 0x03, CSR);
-}
-
-static int i2c_SetSpeed(i2c_dev *dev, int sp)
-{
- unsigned int d;
-
- if( sp != 100 && sp != 400)
- return -1;
-
- d = I2C_INPUT_CLOCK/(sp * 5) -1;
-
- i2c_outl(dev, d & 0xffff, DIVIDER);
-
- MSG2("Set Speed = %d\n", sp);
-
- return 0;
-}
-
-static int i2c_IsBusFree(i2c_dev *dev)
-{
- if( (i2c_inl(dev, SWR) & 0x18) == 0x18 && //SDR and SCR keep high
- (i2c_inl(dev, CSR) & 0x0400) == 0 ){ //I2C_BUSY is false
- //MSG("Bus Free\n");
-
- return 1;
- }
- else{
- //MSG("Bus Busy\n");
-
- return 0;
- }
-
-}
-
-static int i2c_Command(i2c_dev *dev, int cmd)
-{
-
-#if 0
- printk("CMD : ");
-
- if(cmd & I2C_CMD_START){
- printk("START ");
- }
-
- if (cmd & I2C_CMD_STOP){
- printk("STOP ");
-
- }
-
- if(cmd & I2C_CMD_NACK){
- printk("NACK ");
- }
-
- if(cmd & I2C_CMD_WRITE){
- printk("WRITE : [%02x]", i2c_inl(dev, TXR) & 0xff);
- }
-
- if(cmd & I2C_CMD_READ){
- printk("READ : [%02x]", i2c_inl(dev, RXR) & 0xff);
- }
-
- printk("\n");
-
-#endif
-
- if(cmd & I2C_CMD_WRITE)
- bNackValid = 1;
- else
- bNackValid = 0;
-
- i2c_outl(dev, cmd, CMDR);
-
- return 0;
-
-}
-
-
-static int i2c_CalculateAddress(i2c_dev *dev, int mode)
-{
- int i;
- unsigned int addr;
- unsigned int subaddr;
-
- subaddr = dev->subaddr;
- addr = dev->addr;
-
- addr = ((addr << 1) & 0xfe) | I2C_WRITE;
-
- dev->buffer[0] = addr & 0xff;
-
- for(i = dev->subaddr_len; i > 0; i--){
- dev->buffer[i] = subaddr & 0xff;
- subaddr >>= 8;
- }
-
- if(mode == I2C_STATE_READ){
- i = dev->subaddr_len + 1;
- dev->buffer[i] = (addr & 0xfe) | I2C_READ;
- }
-
-#ifdef I2C_DEBUG
- if(mode == I2C_STATE_WRITE){
- MSG2("Begin Write to Device [%02x] Address [%02x]\n",
- dev->addr, dev->subaddr);
- MSG("Buffer : \n");
- for(i = 0; i < dev->subaddr_len +1; i++)
- PDEBUG("%02x ", dev->buffer[i]);
- PDEBUG("\n");
- }
- else{
- MSG2("Begin Read from Device [%02x] Address [%02x]\n",
- dev->addr, dev->subaddr);
- MSG("Buffer : \n");
- for(i = 0; i < dev->subaddr_len +2; i++)
- PDEBUG("%02x ", dev->buffer[i]);
- PDEBUG("\n");
- }
-#endif
-
- return 0;
-}
-
-/* init i2c_dev after open */
-static int i2c_ResetI2C(i2c_dev *dev)
-{
- u32 reg;
-
- // configure i2c pin
- reg = inl(REG_GPIO_CFG5);
- reg &= 0x3ff00fff;
- reg |= 0x00055000;
- outl(reg, REG_GPIO_CFG5);
-
- dev->addr = -1;
- dev->last_error = 0;
- dev->subaddr = 0;
- dev->subaddr_len = 0;
-
- init_waitqueue_head(&dev->wq);
-
- return i2c_SetSpeed(dev, 100);
-
-}
-
-void i2c_interrupt(int irq, void *data, struct pt_regs *reg)
-{
- i2c_dev *dev = (i2c_dev *)data;
- int csr, val;
-
- csr = i2c_inl(dev, CSR);
-
- //MSG2("INT : CSR : [%02x] dev->pos = [%02x]\n", csr, dev->pos);
-
- csr |= 0x04;
-
- i2c_outl(dev, csr, CSR);
-
- if(dev->state == I2C_STATE_NOP)
- return;
-
- MSG2("bNackValid = %d\n", bNackValid);
-
- if((csr & 0x800) && bNackValid){ /* NACK only valid in WRITE */
- MSG("NACK Error\n");
- dev->last_error = I2C_ERR_NACK;
- i2c_Command(dev, I2C_CMD_STOP);
- goto wake_up_quit;
- }
- else if(csr & 0x200){ /* Arbitration lost */
- MSG("Arbitration lost\n");
- dev->last_error = I2C_ERR_LOSTARBITRATION;
- i2c_Command(dev, I2C_CMD_STOP);
- goto wake_up_quit;
- }
- else if(!(csr & 0x100)){ /* transmit complete */
- if(dev->pos < dev->subaddr_len + 1){ /* send address state */
- MSG("Send Address\n");
- val = dev->buffer[dev->pos++] & 0xff;
- i2c_outl(dev, val, TXR);
- i2c_Command(dev, I2C_CMD_WRITE);
- }
- else if(dev->state == I2C_STATE_READ){
-
- /* sub address send over , begin restart a read command */
-
- if(dev->pos == dev->subaddr_len + 1){
-
- MSG("Restart Reading...\n");
-
- val = dev->buffer[dev->pos++];
- i2c_outl(dev, val, TXR);
- i2c_Command(dev, I2C_CMD_START | I2C_CMD_WRITE);
- }
- else{
-
- dev->buffer[dev->pos++] = i2c_inl(dev, RXR) & 0xff;
-
- MSG2("Read Pos : [%02x] Data : [%02x]\n",
- dev->pos, dev->buffer[dev->pos-1]);
-
- if( dev->pos < dev->len){
- MSG("Read Next\n");
- if(dev->pos == dev->len -1 ) /* last character */
- i2c_Command(dev, I2C_CMD_READ |
- I2C_CMD_STOP |
- I2C_CMD_NACK);
- else
- i2c_Command(dev, I2C_CMD_READ);
- }
- else{
- MSG("Read Over \n");
- goto wake_up_quit;
- }
- }
- }
- else if(dev->state == I2C_STATE_WRITE){ /* write data */
-
- if( dev->pos < dev->len){
- MSG2("Write Pos : [%02x] Data : [%02x]\n",
- dev->pos, dev->buffer[dev->pos]);
-
- val = dev->buffer[dev->pos];
-
- i2c_outl(dev, val, TXR);
-
- if(dev->pos == dev->len -1 ) /* last character */
- i2c_Command(dev, I2C_CMD_WRITE| I2C_CMD_STOP);
- else
- i2c_Command(dev, I2C_CMD_WRITE);
-
- dev->pos ++;
- }
- else{
- MSG("Write Over\n");
- goto wake_up_quit;
- }
- }
- //else if(dev->state == I2C_STATE_PROBE){
- // MSG2("Probe Address : [%02x]\n", dev->addr);
- // goto wake_up_quit;
- //}
-
- }
-
- return;
-
-wake_up_quit:
-
- MSG("Wake up \n");
-
- dev->state = I2C_STATE_NOP;
- wake_up_interruptible(&dev->wq);
-
- return;
-}
-
-static int i2c_open(struct inode *inode, struct file *filp)
-{
- i2c_dev *dev;
-
- unsigned int num = MINOR(inode->i_rdev);
-
- if( num >= I2C_NUMBER) {
- printk("I2C : no dev\n");
- return -ENODEV;
- }
- dev = (i2c_dev *)kmalloc(sizeof(i2c_dev), GFP_KERNEL);
- if(dev == NULL) {
- printk("no mem\n");
- return -ENOMEM;
- }
- dev->no = num;
-
- if(request_irq(irq[num], i2c_interrupt, SA_INTERRUPT, "i2c", dev) < 0){
- printk("I2C : Request Irq error\n");
- kfree(dev);
- return -EIO;
- }
-
- if(i2c_ResetI2C(dev)){
- free_irq(irq[num], dev);
- kfree(dev);
- printk("eio\n");
- return -EIO;
- }
-
-
- MOD_INC_USE_COUNT;
-
- filp->private_data = dev;
-
- return 0;
-}
-
-static int i2c_release(struct inode *inode, struct file *flip)
-{
- i2c_dev *dev = flip->private_data;
-
- MSG2("Free IRQ %d\n", irq[dev->no]);
-
- free_irq(irq[dev->no], dev);
- kfree(dev);
- MOD_DEC_USE_COUNT;
-
- return 0;
-}
-
-static int i2c_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
-{
- i2c_dev *dev = (i2c_dev *)filp->private_data;
-
- if(count == 0)
- return 0;
-
- if(!i2c_IsBusFree(dev))
- return -EBUSY;
-
- if(count > I2C_MAX_BUF_LEN - 10)
- count = I2C_MAX_BUF_LEN - 10;
-
- dev->state = I2C_STATE_READ;
- dev->pos = 1;
- dev->len = dev->subaddr_len + 1 + count + 2;/* plus 1 unused char */
- dev->last_error = 0;
-
- i2c_CalculateAddress(dev, I2C_STATE_READ);
-
- i2c_Enable(dev);
-
- i2c_outl(dev, dev->buffer[0] & 0xff, TXR);
-
- i2c_Command(dev, I2C_CMD_START | I2C_CMD_WRITE);
-
- wait_event_interruptible(dev->wq, dev->state == I2C_STATE_NOP);
-
- i2c_Disable(dev);
-
- if(dev->last_error)
- return -EIO;
-
- if(copy_to_user(buf, dev->buffer + dev->subaddr_len + 3, count))
- return -EFAULT;
-
- dev->subaddr += count;
-
- return count;
-}
-
-static int i2c_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
-{
- i2c_dev *dev = (i2c_dev *)filp->private_data;
-
-
- if(count == 0)
- return 0;
-
- if(!i2c_IsBusFree(dev))
- return -EBUSY;
-
-
- if(count > I2C_MAX_BUF_LEN - 10)
- count = I2C_MAX_BUF_LEN - 10;
-
- if(copy_from_user(dev->buffer + dev->subaddr_len + 1 , buf, count))
- return -EFAULT;
-
-
- dev->state = I2C_STATE_WRITE;
- dev->pos = 1;
- dev->len = dev->subaddr_len + 1 + count;
- dev->last_error = 0;
-
- i2c_CalculateAddress(dev, I2C_STATE_WRITE);
-
- i2c_Enable(dev);
-
- i2c_outl(dev, dev->buffer[0] & 0xff, TXR);
-
- i2c_Command(dev, I2C_CMD_START | I2C_CMD_WRITE);
-
- wait_event_interruptible(dev->wq, dev->state == I2C_STATE_NOP);
-
- i2c_Disable(dev);
-
- if(dev->last_error)
- return -EIO;
-
- dev->subaddr += count;
-
- return count;
-}
-
-static int i2c_ioctl(struct inode *inode, struct file *flip, unsigned int cmd, unsigned long arg)
-{
- int err = 0, tmp, retval = 0;
- struct sub_address sub_addr;
- i2c_dev *dev =(i2c_dev *)flip->private_data;
-
- if(_IOC_TYPE(cmd) != I2C_IOC_MAGIC) return -ENOTTY;
- if(_IOC_NR(cmd) > I2C_IOC_MAXNR) return -ENOTTY;
-
- if(_IOC_DIR(cmd) & _IOC_READ)
- err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
- else if(_IOC_DIR(cmd) & _IOC_WRITE)
- err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
-
- if(err)
- return -EFAULT;
-
- switch(cmd){
- case I2C_IOC_SET_DEV_ADDRESS:
- dev->addr = arg;
- MSG2("Address : %02x\n", arg&0xff);
- break;
-
- case I2C_IOC_SET_SPEED:
- if(i2c_SetSpeed(dev, arg))
- retval = -EPERM;
-
- break;
-
- case I2C_IOC_GET_LAST_ERROR:
- if(put_user(dev->last_error, (int *)arg)){
- retval = -EFAULT;
- break;
- }
-
- break;
-
- case I2C_IOC_SET_SUB_ADDRESS:
- if(copy_from_user(&sub_addr, (void *)arg, sizeof(sub_addr))){
- retval = -EFAULT;
- break;
- }
-
- if(sub_addr.sub_addr_len > 4){
- retval = -EPERM;
- break;
- }
-
- MSG2("Sub Address = %02x, length = %d\n",
- sub_addr.sub_addr, sub_addr.sub_addr_len);
-
- dev->subaddr = sub_addr.sub_addr;
- dev->subaddr_len = sub_addr.sub_addr_len;
-
- break;
-
- default:
- retval = -ENOTTY;
- break;
- }
-
- return retval;
-
-}
-
-
-struct file_operations i2c_fops =
-{
- owner: THIS_MODULE,
- open: i2c_open,
- release: i2c_release,
- ioctl: i2c_ioctl,
- read: i2c_read,
- write: i2c_write,
-};
-
-static void i2c_module_exit(void)
-{
- unregister_chrdev(I2C_MAJOR, "i2c");
-}
-
-static int __init i2c_module_init(void)
-{
- int i, retval;
-
- retval = register_chrdev(I2C_MAJOR, "i2c", &i2c_fops);
- if(retval < 0)
- goto failed;
-
- printk("I2C Bus Driver has been installed successfully.\n");
-
- return 0;
-
-failed:
-
- i2c_module_exit();
-
- printk("Init I2C Bus Driver failed!\n");
-
- return retval;
-}
-
-module_init(i2c_module_init);
-module_exit(i2c_module_exit);
-
+/****************************************************************************
+ *
+ * Copyright (c) 2004 - 2006 Winbond Electronics Corp. All rights reserved.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ *
+ * FILENAME
+ * w90n745_i2c.c
+ *
+ * VERSION
+ * 1.0
+ *
+ * DESCRIPTION
+ * Winbond W90N710 I2C Driver
+ *
+ * DATA STRUCTURES
+ * None
+ *
+ * FUNCTIONS
+ * None
+ *
+ * HISTORY
+ * 2005/05/20 Ver 1.0 Created by PC34 QFu
+ *
+ * REMARK
+ * None
+ *************************************************************************/
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#include "w90n745_i2c.h"
+
+
+//#define I2C_DEBUG
+//#define I2C_DEBUG_PRINT_LINE
+//#define I2C_DEBUG_ENABLE_ENTER_LEAVE
+//#define I2C_DEBUG_ENABLE_MSG
+//#define I2C_DEBUG_ENABLE_MSG2
+
+#ifdef I2C_DEBUG
+#define PDEBUG(fmt, arg...) printk(fmt, ##arg)
+#else
+#define PDEBUG(fmt, arg...)
+#endif
+
+#ifdef I2C_DEBUG_PRINT_LINE
+#define PRN_LINE() PDEBUG("[%-20s] : %d\n", __FUNCTION__, __LINE__)
+#else
+#define PRN_LINE()
+#endif
+
+#ifdef I2C_DEBUG_ENABLE_ENTER_LEAVE
+#define ENTER() PDEBUG("[%-20s] : Enter...\n", __FUNCTION__)
+#define LEAVE() PDEBUG("[%-20s] : Leave...\n", __FUNCTION__)
+#else
+#define ENTER()
+#define LEAVE()
+#endif
+
+#ifdef I2C_DEBUG_ENABLE_MSG
+#define MSG(msg) PDEBUG("[%-20s] : %s", __FUNCTION__, msg)
+#else
+#define MSG(msg)
+#endif
+
+#ifdef I2C_DEBUG_ENABLE_MSG2
+#define MSG2(fmt, arg...) PDEBUG("[%-20s] : "fmt, __FUNCTION__, ##arg)
+#define PRNBUF(buf, count) {int i;MSG2("CID Data: ");for(i=0;i<count;i++)\
+ PDEBUG("%02x ", buf[i]);PDEBUG("\n");}
+#else
+#define MSG2(fmt, arg...)
+#define PRNBUF(buf, count)
+#endif
+
+
+
+#define i2c_outl(dev, dword, addr) outl(dword, base[dev->no] + addr)
+#define i2c_inl(dev, addr) inl(base[dev->no] + addr)
+
+
+static const int base[I2C_NUMBER] = {I2C0_IO_BASE, I2C1_IO_BASE};
+static const int irq[I2C_NUMBER] = {I2C0_IRQ, I2C1_IRQ};
+static int bNackValid;
+
+static void i2c_Disable(i2c_dev *dev) /* Disable i2c core and interrupt */
+{
+
+ i2c_outl(dev, 0x00, CSR);
+}
+
+static void i2c_Enable(i2c_dev *dev) /* Enable i2c core and interrupt */
+{
+ i2c_outl(dev, 0x03, CSR);
+}
+
+static int i2c_SetSpeed(i2c_dev *dev, int sp)
+{
+ unsigned int d;
+
+ if( sp != 100 && sp != 400)
+ return -1;
+
+ d = I2C_INPUT_CLOCK/(sp * 5) -1;
+
+ i2c_outl(dev, d & 0xffff, DIVIDER);
+
+ MSG2("Set Speed = %d\n", sp);
+
+ return 0;
+}
+
+static int i2c_IsBusFree(i2c_dev *dev)
+{
+ if( (i2c_inl(dev, SWR) & 0x18) == 0x18 && //SDR and SCR keep high
+ (i2c_inl(dev, CSR) & 0x0400) == 0 ){ //I2C_BUSY is false
+ //MSG("Bus Free\n");
+
+ return 1;
+ }
+ else{
+ //MSG("Bus Busy\n");
+
+ return 0;
+ }
+
+}
+
+static int i2c_Command(i2c_dev *dev, int cmd)
+{
+
+#if 0
+ printk("CMD : ");
+
+ if(cmd & I2C_CMD_START){
+ printk("START ");
+ }
+
+ if (cmd & I2C_CMD_STOP){
+ printk("STOP ");
+
+ }
+
+ if(cmd & I2C_CMD_NACK){
+ printk("NACK ");
+ }
+
+ if(cmd & I2C_CMD_WRITE){
+ printk("WRITE : [%02x]", i2c_inl(dev, TXR) & 0xff);
+ }
+
+ if(cmd & I2C_CMD_READ){
+ printk("READ : [%02x]", i2c_inl(dev, RXR) & 0xff);
+ }
+
+ printk("\n");
+
+#endif
+
+ if(cmd & I2C_CMD_WRITE)
+ bNackValid = 1;
+ else
+ bNackValid = 0;
+
+ i2c_outl(dev, cmd, CMDR);
+
+ return 0;
+
+}
+
+
+static int i2c_CalculateAddress(i2c_dev *dev, int mode)
+{
+ int i;
+ unsigned int addr;
+ unsigned int subaddr;
+
+ subaddr = dev->subaddr;
+ addr = dev->addr;
+
+ addr = ((addr << 1) & 0xfe) | I2C_WRITE;
+
+ dev->buffer[0] = addr & 0xff;
+
+ for(i = dev->subaddr_len; i > 0; i--){
+ dev->buffer[i] = subaddr & 0xff;
+ subaddr >>= 8;
+ }
+
+ if(mode == I2C_STATE_READ){
+ i = dev->subaddr_len + 1;
+ dev->buffer[i] = (addr & 0xfe) | I2C_READ;
+ }
+
+#ifdef I2C_DEBUG
+ if(mode == I2C_STATE_WRITE){
+ MSG2("Begin Write to Device [%02x] Address [%02x]\n",
+ dev->addr, dev->subaddr);
+ MSG("Buffer : \n");
+ for(i = 0; i < dev->subaddr_len +1; i++)
+ PDEBUG("%02x ", dev->buffer[i]);
+ PDEBUG("\n");
+ }
+ else{
+ MSG2("Begin Read from Device [%02x] Address [%02x]\n",
+ dev->addr, dev->subaddr);
+ MSG("Buffer : \n");
+ for(i = 0; i < dev->subaddr_len +2; i++)
+ PDEBUG("%02x ", dev->buffer[i]);
+ PDEBUG("\n");
+ }
+#endif
+
+ return 0;
+}
+
+/* init i2c_dev after open */
+static int i2c_ResetI2C(i2c_dev *dev)
+{
+ u32 reg;
+
+ // configure i2c pin
+ reg = inl(REG_GPIO_CFG5);
+ reg &= 0x3ff00fff;
+ reg |= 0x00055000;
+ outl(reg, REG_GPIO_CFG5);
+
+ dev->addr = -1;
+ dev->last_error = 0;
+ dev->subaddr = 0;
+ dev->subaddr_len = 0;
+
+ init_waitqueue_head(&dev->wq);
+
+ return i2c_SetSpeed(dev, 100);
+
+}
+
+void i2c_interrupt(int irq, void *data, struct pt_regs *reg)
+{
+ i2c_dev *dev = (i2c_dev *)data;
+ int csr, val;
+
+ csr = i2c_inl(dev, CSR);
+
+ //MSG2("INT : CSR : [%02x] dev->pos = [%02x]\n", csr, dev->pos);
+
+ csr |= 0x04;
+
+ i2c_outl(dev, csr, CSR);
+
+ if(dev->state == I2C_STATE_NOP)
+ return;
+
+ MSG2("bNackValid = %d\n", bNackValid);
+
+ if((csr & 0x800) && bNackValid){ /* NACK only valid in WRITE */
+ MSG("NACK Error\n");
+ dev->last_error = I2C_ERR_NACK;
+ i2c_Command(dev, I2C_CMD_STOP);
+ goto wake_up_quit;
+ }
+ else if(csr & 0x200){ /* Arbitration lost */
+ MSG("Arbitration lost\n");
+ dev->last_error = I2C_ERR_LOSTARBITRATION;
+ i2c_Command(dev, I2C_CMD_STOP);
+ goto wake_up_quit;
+ }
+ else if(!(csr & 0x100)){ /* transmit complete */
+ if(dev->pos < dev->subaddr_len + 1){ /* send address state */
+ MSG("Send Address\n");
+ val = dev->buffer[dev->pos++] & 0xff;
+ i2c_outl(dev, val, TXR);
+ i2c_Command(dev, I2C_CMD_WRITE);
+ }
+ else if(dev->state == I2C_STATE_READ){
+
+ /* sub address send over , begin restart a read command */
+
+ if(dev->pos == dev->subaddr_len + 1){
+
+ MSG("Restart Reading...\n");
+
+ val = dev->buffer[dev->pos++];
+ i2c_outl(dev, val, TXR);
+ i2c_Command(dev, I2C_CMD_START | I2C_CMD_WRITE);
+ }
+ else{
+
+ dev->buffer[dev->pos++] = i2c_inl(dev, RXR) & 0xff;
+
+ MSG2("Read Pos : [%02x] Data : [%02x]\n",
+ dev->pos, dev->buffer[dev->pos-1]);
+
+ if( dev->pos < dev->len){
+ MSG("Read Next\n");
+ if(dev->pos == dev->len -1 ) /* last character */
+ i2c_Command(dev, I2C_CMD_READ |
+ I2C_CMD_STOP |
+ I2C_CMD_NACK);
+ else
+ i2c_Command(dev, I2C_CMD_READ);
+ }
+ else{
+ MSG("Read Over \n");
+ goto wake_up_quit;
+ }
+ }
+ }
+ else if(dev->state == I2C_STATE_WRITE){ /* write data */
+
+ if( dev->pos < dev->len){
+ MSG2("Write Pos : [%02x] Data : [%02x]\n",
+ dev->pos, dev->buffer[dev->pos]);
+
+ val = dev->buffer[dev->pos];
+
+ i2c_outl(dev, val, TXR);
+
+ if(dev->pos == dev->len -1 ) /* last character */
+ i2c_Command(dev, I2C_CMD_WRITE| I2C_CMD_STOP);
+ else
+ i2c_Command(dev, I2C_CMD_WRITE);
+
+ dev->pos ++;
+ }
+ else{
+ MSG("Write Over\n");
+ goto wake_up_quit;
+ }
+ }
+ //else if(dev->state == I2C_STATE_PROBE){
+ // MSG2("Probe Address : [%02x]\n", dev->addr);
+ // goto wake_up_quit;
+ //}
+
+ }
+
+ return;
+
+wake_up_quit:
+
+ MSG("Wake up \n");
+
+ dev->state = I2C_STATE_NOP;
+ wake_up_interruptible(&dev->wq);
+
+ return;
+}
+
+static int i2c_open(struct inode *inode, struct file *filp)
+{
+ i2c_dev *dev;
+
+ unsigned int num = MINOR(inode->i_rdev);
+
+ if( num >= I2C_NUMBER) {
+ printk("I2C : no dev\n");
+ return -ENODEV;
+ }
+ dev = (i2c_dev *)kmalloc(sizeof(i2c_dev), GFP_KERNEL);
+ if(dev == NULL) {
+ printk("no mem\n");
+ return -ENOMEM;
+ }
+ dev->no = num;
+
+ if(request_irq(irq[num], i2c_interrupt, SA_INTERRUPT, "i2c", dev) < 0){
+ printk("I2C : Request Irq error\n");
+ kfree(dev);
+ return -EIO;
+ }
+
+ if(i2c_ResetI2C(dev)){
+ free_irq(irq[num], dev);
+ kfree(dev);
+ printk("eio\n");
+ return -EIO;
+ }
+
+
+ MOD_INC_USE_COUNT;
+
+ filp->private_data = dev;
+
+ return 0;
+}
+
+static int i2c_release(struct inode *inode, struct file *flip)
+{
+ i2c_dev *dev = flip->private_data;
+
+ MSG2("Free IRQ %d\n", irq[dev->no]);
+
+ free_irq(irq[dev->no], dev);
+ kfree(dev);
+ MOD_DEC_USE_COUNT;
+
+ return 0;
+}
+
+static int i2c_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
+{
+ i2c_dev *dev = (i2c_dev *)filp->private_data;
+
+ if(count == 0)
+ return 0;
+
+ if(!i2c_IsBusFree(dev))
+ return -EBUSY;
+
+ if(count > I2C_MAX_BUF_LEN - 10)
+ count = I2C_MAX_BUF_LEN - 10;
+
+ dev->state = I2C_STATE_READ;
+ dev->pos = 1;
+ dev->len = dev->subaddr_len + 1 + count + 2;/* plus 1 unused char */
+ dev->last_error = 0;
+
+ i2c_CalculateAddress(dev, I2C_STATE_READ);
+
+ i2c_Enable(dev);
+
+ i2c_outl(dev, dev->buffer[0] & 0xff, TXR);
+
+ i2c_Command(dev, I2C_CMD_START | I2C_CMD_WRITE);
+
+ wait_event_interruptible(dev->wq, dev->state == I2C_STATE_NOP);
+
+ i2c_Disable(dev);
+
+ if(dev->last_error)
+ return -EIO;
+
+ if(copy_to_user(buf, dev->buffer + dev->subaddr_len + 3, count))
+ return -EFAULT;
+
+ dev->subaddr += count;
+
+ return count;
+}
+
+static int i2c_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
+{
+ i2c_dev *dev = (i2c_dev *)filp->private_data;
+
+
+ if(count == 0)
+ return 0;
+
+ if(!i2c_IsBusFree(dev))
+ return -EBUSY;
+
+
+ if(count > I2C_MAX_BUF_LEN - 10)
+ count = I2C_MAX_BUF_LEN - 10;
+
+ if(copy_from_user(dev->buffer + dev->subaddr_len + 1 , buf, count))
+ return -EFAULT;
+
+
+ dev->state = I2C_STATE_WRITE;
+ dev->pos = 1;
+ dev->len = dev->subaddr_len + 1 + count;
+ dev->last_error = 0;
+
+ i2c_CalculateAddress(dev, I2C_STATE_WRITE);
+
+ i2c_Enable(dev);
+
+ i2c_outl(dev, dev->buffer[0] & 0xff, TXR);
+
+ i2c_Command(dev, I2C_CMD_START | I2C_CMD_WRITE);
+
+ wait_event_interruptible(dev->wq, dev->state == I2C_STATE_NOP);
+
+ i2c_Disable(dev);
+
+ if(dev->last_error)
+ return -EIO;
+
+ dev->subaddr += count;
+
+ return count;
+}
+
+static int i2c_ioctl(struct inode *inode, struct file *flip, unsigned int cmd, unsigned long arg)
+{
+ int err = 0, tmp, retval = 0;
+ struct sub_address sub_addr;
+ i2c_dev *dev =(i2c_dev *)flip->private_data;
+
+ if(_IOC_TYPE(cmd) != I2C_IOC_MAGIC) return -ENOTTY;
+ if(_IOC_NR(cmd) > I2C_IOC_MAXNR) return -ENOTTY;
+
+ if(_IOC_DIR(cmd) & _IOC_READ)
+ err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
+ else if(_IOC_DIR(cmd) & _IOC_WRITE)
+ err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
+
+ if(err)
+ return -EFAULT;
+
+ switch(cmd){
+ case I2C_IOC_SET_DEV_ADDRESS:
+ dev->addr = arg;
+ MSG2("Address : %02x\n", arg&0xff);
+ break;
+
+ case I2C_IOC_SET_SPEED:
+ if(i2c_SetSpeed(dev, arg))
+ retval = -EPERM;
+
+ break;
+
+ case I2C_IOC_GET_LAST_ERROR:
+ if(put_user(dev->last_error, (int *)arg)){
+ retval = -EFAULT;
+ break;
+ }
+
+ break;
+
+ case I2C_IOC_SET_SUB_ADDRESS:
+ if(copy_from_user(&sub_addr, (void *)arg, sizeof(sub_addr))){
+ retval = -EFAULT;
+ break;
+ }
+
+ if(sub_addr.sub_addr_len > 4){
+ retval = -EPERM;
+ break;
+ }
+
+ MSG2("Sub Address = %02x, length = %d\n",
+ sub_addr.sub_addr, sub_addr.sub_addr_len);
+
+ dev->subaddr = sub_addr.sub_addr;
+ dev->subaddr_len = sub_addr.sub_addr_len;
+
+ break;
+
+ default:
+ retval = -ENOTTY;
+ break;
+ }
+
+ return retval;
+
+}
+
+
+struct file_operations i2c_fops =
+{
+ owner: THIS_MODULE,
+ open: i2c_open,
+ release: i2c_release,
+ ioctl: i2c_ioctl,
+ read: i2c_read,
+ write: i2c_write,
+};
+
+static void i2c_module_exit(void)
+{
+ unregister_chrdev(I2C_MAJOR, "i2c");
+}
+
+static int __init i2c_module_init(void)
+{
+ int i, retval;
+
+ retval = register_chrdev(I2C_MAJOR, "i2c", &i2c_fops);
+ if(retval < 0)
+ goto failed;
+
+ printk("I2C Bus Driver has been installed successfully.\n");
+
+ return 0;
+
+failed:
+
+ i2c_module_exit();
+
+ printk("Init I2C Bus Driver failed!\n");
+
+ return retval;
+}
+
+module_init(i2c_module_init);
+module_exit(i2c_module_exit);
+
diff --git a/uClinux-2.4.20-uc1/drivers/char/w90n745_i2c.h b/uClinux-2.4.20-uc1/drivers/char/w90n745_i2c.h
index b1ab388..5ff85a8 100644
--- a/uClinux-2.4.20-uc1/drivers/char/w90n745_i2c.h
+++ b/uClinux-2.4.20-uc1/drivers/char/w90n745_i2c.h
@@ -1,123 +1,123 @@
-/****************************************************************************
- *
- * Copyright (c) 2004 - 2006 Winbond Electronics Corp. All rights reserved.
- *
- ****************************************************************************/
-
-/****************************************************************************
- *
- * FILENAME
- * w90n745_i2c.h
- *
- * VERSION
- * 1.0
- *
- * DESCRIPTION
- * Winbond W90N745 I2C Driver header
- *
- * DATA STRUCTURES
- * None
- *
- * FUNCTIONS
- * None
- *
- * HISTORY
- * 2005/05/20 Ver 1.0 Created by PC34 QFu
- *
- * REMARK
- * None
- *************************************************************************/
-#ifndef _W90N745_I2C_H_
-#define _W90N745_I2C_H_
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-#include <asm/arch/irqs.h>
-
-#ifdef __KERNEL__
-
-#define I2C_NUMBER 2
-
-#define I2C_FIFO_LEN 4
-#define I2C_MAX_BUF_LEN 450
-
-#define I2C0_IRQ INT_I2C0
-#define I2C1_IRQ INT_I2C1
-
-#define I2C_MAJOR 89
-#define I2C0_IO_BASE 0xfff86000
-#define I2C1_IO_BASE 0xfff86100
-#define I2C_IOMEM_SIZE 0x18
-
-#define REG_GPIO_CFG5 0xFFF83050
-#define I2C_INPUT_CLOCK 80000 /* 80 000 KHz */
-
-/* register map */
-#define CSR 0x00
-#define DIVIDER 0x04
-#define CMDR 0x08
-#define SWR 0x0c /* not available in W90n710 */
-#define RXR 0x10
-#define TXR 0x14
-
-/* bit map in CMDR */
-#define I2C_CMD_START 0x10
-#define I2C_CMD_STOP 0x08
-#define I2C_CMD_READ 0x04
-#define I2C_CMD_WRITE 0x02
-#define I2C_CMD_NACK 0x01
-
-/* for transfer use */
-#define I2C_WRITE 0x00
-#define I2C_READ 0x01
-
-
-#define I2C_STATE_NOP 0x00
-#define I2C_STATE_READ 0x01
-#define I2C_STATE_WRITE 0x02
-#define I2C_STATE_PROBE 0x03
-
-typedef struct _i2c_dev{
- int no; /* i2c bus number */
- volatile int state;
- int last_error;
- int addr;
-
- unsigned subaddr;
- int subaddr_len;
-
- unsigned char buffer[I2C_MAX_BUF_LEN];
- volatile unsigned int pos, len;
-
- wait_queue_head_t wq;
-
-}i2c_dev;
-
-#endif
-
-struct sub_address{
- char sub_addr_len;
- unsigned int sub_addr;
-};
-
-/* error code */
-#define I2C_ERR_ID (0x00)
-
-#define I2C_ERR_NOERROR (0x00)
-#define I2C_ERR_LOSTARBITRATION (0x01 | I2C_ERR_ID)
-#define I2C_ERR_BUSBUSY (0x02 | I2C_ERR_ID)
-#define I2C_ERR_NACK (0x03 | I2C_ERR_ID) /* data transfer error */
-#define I2C_ERR_SLAVENACK (0x04 | I2C_ERR_ID) /* slave not respond after address */
-
-/* define ioctl command */
-#define I2C_IOC_MAGIC 'i'
-
-#define I2C_IOC_MAXNR 3
-
-#define I2C_IOC_SET_DEV_ADDRESS _IOW(I2C_IOC_MAGIC, 0, int)
-#define I2C_IOC_SET_SUB_ADDRESS _IOW(I2C_IOC_MAGIC, 1, int)
-#define I2C_IOC_SET_SPEED _IOW(I2C_IOC_MAGIC, 2, int)
-#define I2C_IOC_GET_LAST_ERROR _IOR(I2C_IOC_MAGIC, 3, int)
-#endif
-
+/****************************************************************************
+ *
+ * Copyright (c) 2004 - 2006 Winbond Electronics Corp. All rights reserved.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ *
+ * FILENAME
+ * w90n745_i2c.h
+ *
+ * VERSION
+ * 1.0
+ *
+ * DESCRIPTION
+ * Winbond W90N745 I2C Driver header
+ *
+ * DATA STRUCTURES
+ * None
+ *
+ * FUNCTIONS
+ * None
+ *
+ * HISTORY
+ * 2005/05/20 Ver 1.0 Created by PC34 QFu
+ *
+ * REMARK
+ * None
+ *************************************************************************/
+#ifndef _W90N745_I2C_H_
+#define _W90N745_I2C_H_
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#include <asm/arch/irqs.h>
+
+#ifdef __KERNEL__
+
+#define I2C_NUMBER 2
+
+#define I2C_FIFO_LEN 4
+#define I2C_MAX_BUF_LEN 450
+
+#define I2C0_IRQ INT_I2C0
+#define I2C1_IRQ INT_I2C1
+
+#define I2C_MAJOR 89
+#define I2C0_IO_BASE 0xfff86000
+#define I2C1_IO_BASE 0xfff86100
+#define I2C_IOMEM_SIZE 0x18
+
+#define REG_GPIO_CFG5 0xFFF83050
+#define I2C_INPUT_CLOCK 80000 /* 80 000 KHz */
+
+/* register map */
+#define CSR 0x00
+#define DIVIDER 0x04
+#define CMDR 0x08
+#define SWR 0x0c /* not available in W90n710 */
+#define RXR 0x10
+#define TXR 0x14
+
+/* bit map in CMDR */
+#define I2C_CMD_START 0x10
+#define I2C_CMD_STOP 0x08
+#define I2C_CMD_READ 0x04
+#define I2C_CMD_WRITE 0x02
+#define I2C_CMD_NACK 0x01
+
+/* for transfer use */
+#define I2C_WRITE 0x00
+#define I2C_READ 0x01
+
+
+#define I2C_STATE_NOP 0x00
+#define I2C_STATE_READ 0x01
+#define I2C_STATE_WRITE 0x02
+#define I2C_STATE_PROBE 0x03
+
+typedef struct _i2c_dev{
+ int no; /* i2c bus number */
+ volatile int state;
+ int last_error;
+ int addr;
+
+ unsigned subaddr;
+ int subaddr_len;
+
+ unsigned char buffer[I2C_MAX_BUF_LEN];
+ volatile unsigned int pos, len;
+
+ wait_queue_head_t wq;
+
+}i2c_dev;
+
+#endif
+
+struct sub_address{
+ char sub_addr_len;
+ unsigned int sub_addr;
+};
+
+/* error code */
+#define I2C_ERR_ID (0x00)
+
+#define I2C_ERR_NOERROR (0x00)
+#define I2C_ERR_LOSTARBITRATION (0x01 | I2C_ERR_ID)
+#define I2C_ERR_BUSBUSY (0x02 | I2C_ERR_ID)
+#define I2C_ERR_NACK (0x03 | I2C_ERR_ID) /* data transfer error */
+#define I2C_ERR_SLAVENACK (0x04 | I2C_ERR_ID) /* slave not respond after address */
+
+/* define ioctl command */
+#define I2C_IOC_MAGIC 'i'
+
+#define I2C_IOC_MAXNR 3
+
+#define I2C_IOC_SET_DEV_ADDRESS _IOW(I2C_IOC_MAGIC, 0, int)
+#define I2C_IOC_SET_SUB_ADDRESS _IOW(I2C_IOC_MAGIC, 1, int)
+#define I2C_IOC_SET_SPEED _IOW(I2C_IOC_MAGIC, 2, int)
+#define I2C_IOC_GET_LAST_ERROR _IOR(I2C_IOC_MAGIC, 3, int)
+#endif
+
diff --git a/uClinux-2.4.20-uc1/drivers/char/w90n745_keypad.c b/uClinux-2.4.20-uc1/drivers/char/w90n745_keypad.c
index d350a47..9f65862 100755
--- a/uClinux-2.4.20-uc1/drivers/char/w90n745_keypad.c
+++ b/uClinux-2.4.20-uc1/drivers/char/w90n745_keypad.c
@@ -1,253 +1,253 @@
-/****************************************************************************
- * *
- * Copyright (c) 2004 - 2006 Winbond Electronics Corp. All rights reserved. *
- * *
- ****************************************************************************/
-
-/****************************************************************************
- *
- * FILENAME
- * w90n745_keypad.c
- *
- * VERSION
- * 1.0
- *
- * DESCRIPTION
- * The Winbond 64-keyboard driver
- *
- * DATA STRUCTURES
- * None
- *
- * FUNCTIONS
- * None
- *
- * HISTORY
- * 2005/09/09 Ver 1.0 Created by PC34 YHan
- *
- * REMARK
- * None
- *************************************************************************/
-
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <asm/errno.h>
-#include <asm/delay.h>
-//#include <asm/fcntl.h>
-#include <asm/arch/irqs.h>
-#include <linux/mm.h>
-#include <linux/poll.h>
-#include <linux/module.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include "w90n745_keypad.h"
-
-#define MAJOR_NUM 192
-
-static int volatile kpd_get=0;
-static int volatile kpd_block=1;
-unsigned char DEV_NAME[10] = "Keypad";
-
-typedef struct _keymap
-{
- short row;
- short col;
-}keymap;
-
-keymap key __attribute__ ((aligned (4)));
-
-static DECLARE_WAIT_QUEUE_HEAD(read_wait_a);
-
-static void read_task_block()
-{
- DECLARE_WAITQUEUE(wait, current);
- add_wait_queue(&read_wait_a, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
-
- schedule();
-
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&read_wait_a, &wait);
-
- return ;
-}
-
-static void read_task_wake_up(void)
-{
- wake_up_interruptible(&read_wait_a);
-
- return ;
-}
-
-void keypad745_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
-
- volatile unsigned int status;
- kpd_get=1;
-
- key.row = 0;
- key.col = 0;
-
- status = readl(KPISTATUS);
- #ifdef KPI_DEBUG
- printk("KPI ISR KPISTATUS=0x%08x\n",status);
- #endif
- if(status&0x00210000)
- {
- key.row = (status&0x00000078)>>3;
- key.col = (status&0x00000007);
- }
-
- if(kpd_block)
- read_task_wake_up();
-
- return;
-
-}
-
-int keypad745_open(struct inode* i,struct file* f)
-{
- int result;
- int irq;
- int old_cfg;
- kpd_block=1;
-
- if(f->f_flags & 0x800) //0x800:04000
- kpd_block=0;
-
-
- irq = INT_KEYPAD;
-
- MOD_INC_USE_COUNT;
-
- result = request_irq(irq,keypad745_irq,0,DEV_NAME,NULL);
- if(result!=0)
- printk("register the keypad_irq failed!\n");
-
- old_cfg=readl(GPIO_CFG);
- old_cfg=old_cfg&GPIO_CFG_MASK;
- old_cfg=old_cfg|GPIO_CFG_VALUE;
- writel(old_cfg,GPIO_CFG);
-
- #ifdef KPI_DEBUG
- printk("KPI OPEN:\nKPICONF=0x%08x\nGPIO_CFG=0x%08x\n",readl(KPICONF),readl(GPIO_CFG));
- #endif
-
- return 0;
-}
-
-int keypad745_close(struct inode* i,struct file* f)
-{
- MOD_DEC_USE_COUNT;
- free_irq(INT_KEYPAD,NULL);
-
- return 0;
-}
-
-
-ssize_t keypad745_read(struct file *filp, char *buff, size_t read_mode, loff_t *offp)
-{
- kpd_block = read_mode ;
-
- if(kpd_block)
- {
- read_task_block();
- }
-
- if(kpd_get)
- {
- kpd_get=0;
- copy_to_user(buff,(char*)&key,sizeof(keymap));
- key.row = 0;
- key.col = 0;
- return 1;
- }
- else
- return -1;
-}
-
-static int keypad745_ioctl(struct inode *inode, struct file *flip,
- unsigned int cmd, unsigned long arg)
-{
- int err = 0;
-
- if(_IOC_TYPE(cmd) != KEYPAD_MAGIC) return -ENOTTY;
- if(_IOC_NR(cmd) > KEYPAD_MAXNR) return -ENOTTY;
-
- if(_IOC_DIR(cmd) & _IOC_READ)
- err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
- else if(_IOC_DIR(cmd) & _IOC_WRITE)
- err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
-
- if(err)
- return -EFAULT;
-
- switch (cmd)
- {
- case KPD_BLOCK:
- kpd_block=1;
- flip->f_flags &= ~0x800;
- break;
- case KPD_NONBLOCK:
- kpd_block=0;
- flip->f_flags |= ~0x800;
-
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-struct file_operations keypad745_fops =
-{
- owner: THIS_MODULE,
- open: keypad745_open,
- read: keypad745_read,
- ioctl:keypad745_ioctl,
- release: keypad745_close,
-};
-
-static int __init keypad_745_reg(void)
-{
- int result;
- int old_cfg;
- result = register_chrdev(MAJOR_NUM,DEV_NAME,&keypad745_fops);
- if(result<0)
- {
- printk("initial the device error!\n");
- return (result);
- }
-
- old_cfg=readl(GPIO_CFG);
- old_cfg=old_cfg&GPIO_CFG_MASK;
- old_cfg=old_cfg|GPIO_CFG_VALUE;
- writel(old_cfg,GPIO_CFG);
-
- writel(0,KPICONF);
- writel(0,KPI3KCONF);
- writel(0,KPISTATUS);
-#ifdef __WB_EVB__
- old_cfg=readl(GPIO_DIR);
- old_cfg |= 0x3FF0000;
- writel(old_cfg,GPIO_DIR);
-#endif
- writel(KPICONF_VALUE,KPICONF);
-
- init_waitqueue_head(&read_wait_a);
-
- printk("W90N745 Keypad initialized successful\n");
-
- return (result);
-
-}
-
-static void keypad_745_exit(void)
-{
- unregister_chrdev(MAJOR_NUM,DEV_NAME);
-
- return;
-}
-
-module_init(keypad_745_reg);
-module_exit(keypad_745_exit);
+/****************************************************************************
+ * *
+ * Copyright (c) 2004 - 2006 Winbond Electronics Corp. All rights reserved. *
+ * *
+ ****************************************************************************/
+
+/****************************************************************************
+ *
+ * FILENAME
+ * w90n745_keypad.c
+ *
+ * VERSION
+ * 1.0
+ *
+ * DESCRIPTION
+ * The Winbond 64-keyboard driver
+ *
+ * DATA STRUCTURES
+ * None
+ *
+ * FUNCTIONS
+ * None
+ *
+ * HISTORY
+ * 2005/09/09 Ver 1.0 Created by PC34 YHan
+ *
+ * REMARK
+ * None
+ *************************************************************************/
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <asm/errno.h>
+#include <asm/delay.h>
+//#include <asm/fcntl.h>
+#include <asm/arch/irqs.h>
+#include <linux/mm.h>
+#include <linux/poll.h>
+#include <linux/module.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include "w90n745_keypad.h"
+
+#define MAJOR_NUM 192
+
+static int volatile kpd_get=0;
+static int volatile kpd_block=1;
+unsigned char DEV_NAME[10] = "Keypad";
+
+typedef struct _keymap
+{
+ short row;
+ short col;
+}keymap;
+
+keymap key __attribute__ ((aligned (4)));
+
+static DECLARE_WAIT_QUEUE_HEAD(read_wait_a);
+
+static void read_task_block()
+{
+ DECLARE_WAITQUEUE(wait, current);
+ add_wait_queue(&read_wait_a, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ schedule();
+
+ set_current_state(TASK_RUNNING);
+ remove_wait_queue(&read_wait_a, &wait);
+
+ return ;
+}
+
+static void read_task_wake_up(void)
+{
+ wake_up_interruptible(&read_wait_a);
+
+ return ;
+}
+
+void keypad745_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+ volatile unsigned int status;
+ kpd_get=1;
+
+ key.row = 0;
+ key.col = 0;
+
+ status = readl(KPISTATUS);
+ #ifdef KPI_DEBUG
+ printk("KPI ISR KPISTATUS=0x%08x\n",status);
+ #endif
+ if(status&0x00210000)
+ {
+ key.row = (status&0x00000078)>>3;
+ key.col = (status&0x00000007);
+ }
+
+ if(kpd_block)
+ read_task_wake_up();
+
+ return;
+
+}
+
+int keypad745_open(struct inode* i,struct file* f)
+{
+ int result;
+ int irq;
+ int old_cfg;
+ kpd_block=1;
+
+ if(f->f_flags & 0x800) //0x800:04000
+ kpd_block=0;
+
+
+ irq = INT_KEYPAD;
+
+ MOD_INC_USE_COUNT;
+
+ result = request_irq(irq,keypad745_irq,0,DEV_NAME,NULL);
+ if(result!=0)
+ printk("register the keypad_irq failed!\n");
+
+ old_cfg=readl(GPIO_CFG);
+ old_cfg=old_cfg&GPIO_CFG_MASK;
+ old_cfg=old_cfg|GPIO_CFG_VALUE;
+ writel(old_cfg,GPIO_CFG);
+
+ #ifdef KPI_DEBUG
+ printk("KPI OPEN:\nKPICONF=0x%08x\nGPIO_CFG=0x%08x\n",readl(KPICONF),readl(GPIO_CFG));
+ #endif
+
+ return 0;
+}
+
+int keypad745_close(struct inode* i,struct file* f)
+{
+ MOD_DEC_USE_COUNT;
+ free_irq(INT_KEYPAD,NULL);
+
+ return 0;
+}
+
+
+ssize_t keypad745_read(struct file *filp, char *buff, size_t read_mode, loff_t *offp)
+{
+ kpd_block = read_mode ;
+
+ if(kpd_block)
+ {
+ read_task_block();
+ }
+
+ if(kpd_get)
+ {
+ kpd_get=0;
+ copy_to_user(buff,(char*)&key,sizeof(keymap));
+ key.row = 0;
+ key.col = 0;
+ return 1;
+ }
+ else
+ return -1;
+}
+
+static int keypad745_ioctl(struct inode *inode, struct file *flip,
+ unsigned int cmd, unsigned long arg)
+{
+ int err = 0;
+
+ if(_IOC_TYPE(cmd) != KEYPAD_MAGIC) return -ENOTTY;
+ if(_IOC_NR(cmd) > KEYPAD_MAXNR) return -ENOTTY;
+
+ if(_IOC_DIR(cmd) & _IOC_READ)
+ err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
+ else if(_IOC_DIR(cmd) & _IOC_WRITE)
+ err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
+
+ if(err)
+ return -EFAULT;
+
+ switch (cmd)
+ {
+ case KPD_BLOCK:
+ kpd_block=1;
+ flip->f_flags &= ~0x800;
+ break;
+ case KPD_NONBLOCK:
+ kpd_block=0;
+ flip->f_flags |= ~0x800;
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+struct file_operations keypad745_fops =
+{
+ owner: THIS_MODULE,
+ open: keypad745_open,
+ read: keypad745_read,
+ ioctl:keypad745_ioctl,
+ release: keypad745_close,
+};
+
+static int __init keypad_745_reg(void)
+{
+ int result;
+ int old_cfg;
+ result = register_chrdev(MAJOR_NUM,DEV_NAME,&keypad745_fops);
+ if(result<0)
+ {
+ printk("initial the device error!\n");
+ return (result);
+ }
+
+ old_cfg=readl(GPIO_CFG);
+ old_cfg=old_cfg&GPIO_CFG_MASK;
+ old_cfg=old_cfg|GPIO_CFG_VALUE;
+ writel(old_cfg,GPIO_CFG);
+
+ writel(0,KPICONF);
+ writel(0,KPI3KCONF);
+ writel(0,KPISTATUS);
+#ifdef __WB_EVB__
+ old_cfg=readl(GPIO_DIR);
+ old_cfg |= 0x3FF0000;
+ writel(old_cfg,GPIO_DIR);
+#endif
+ writel(KPICONF_VALUE,KPICONF);
+
+ init_waitqueue_head(&read_wait_a);
+
+ printk("W90N745 Keypad initialized successful\n");
+
+ return (result);
+
+}
+
+static void keypad_745_exit(void)
+{
+ unregister_chrdev(MAJOR_NUM,DEV_NAME);
+
+ return;
+}
+
+module_init(keypad_745_reg);
+module_exit(keypad_745_exit);
diff --git a/uClinux-2.4.20-uc1/drivers/char/w90n745_keypad.h b/uClinux-2.4.20-uc1/drivers/char/w90n745_keypad.h
index 4395461..a3965fa 100755
--- a/uClinux-2.4.20-uc1/drivers/char/w90n745_keypad.h
+++ b/uClinux-2.4.20-uc1/drivers/char/w90n745_keypad.h
@@ -1,57 +1,57 @@
-/****************************************************************************
- *
- * Copyright (c) 2004 - 2006 Winbond Electronics Corp. All rights reserved.
- *
- ****************************************************************************/
-
-/****************************************************************************
- *
- * FILENAME
- * w90n745_keypad.h
- *
- * VERSION
- * 1.0
- *
- * DESCRIPTION
- * The winbond 64-keyboard driver header file
- *
- * DATA STRUCTURES
- * None
- *
- * FUNCTIONS
- * None
- *
- * HISTORY
- * 2005/09/09 Ver 1.0 Created by PC34 YHan
- *
- * REMARK
- * None
- *************************************************************************/
-
-#ifndef W90N745__KEYPAD_H
-#define W90N745__KEYPAD_H
-
-//#define KPI_DEBUG
-
-#define KPICONF 0xFFF88000
-#define KPI3KCONF 0xFFF88004
-#define KPILPCONF 0xFFF88008
-#define KPISTATUS 0xFFF8800C
-
-#ifdef __WB_EVB__
-#define GPIO_CFG 0xFFF83020
-#define GPIO_DIR 0xFFF83024
-#define GPIO_CFG_MASK 0xFFF00000
-#define GPIO_CFG_VALUE 0x000AAAAA
-#define KPICONF_VALUE 0x000405FA
-#endif
-
-
-
-#define KEYPAD_MAGIC 'k'
-#define KEYPAD_MAXNR 2
-
-#define KPD_BLOCK _IOW('k', 1, unsigned int)
-#define KPD_NONBLOCK _IOW('k', 2, unsigned int)
-
-#endif
+/****************************************************************************
+ *
+ * Copyright (c) 2004 - 2006 Winbond Electronics Corp. All rights reserved.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ *
+ * FILENAME
+ * w90n745_keypad.h
+ *
+ * VERSION
+ * 1.0
+ *
+ * DESCRIPTION
+ * The winbond 64-keyboard driver header file
+ *
+ * DATA STRUCTURES
+ * None
+ *
+ * FUNCTIONS
+ * None
+ *
+ * HISTORY
+ * 2005/09/09 Ver 1.0 Created by PC34 YHan
+ *
+ * REMARK
+ * None
+ *************************************************************************/
+
+#ifndef W90N745__KEYPAD_H
+#define W90N745__KEYPAD_H
+
+//#define KPI_DEBUG
+
+#define KPICONF 0xFFF88000
+#define KPI3KCONF 0xFFF88004
+#define KPILPCONF 0xFFF88008
+#define KPISTATUS 0xFFF8800C
+
+#ifdef __WB_EVB__
+#define GPIO_CFG 0xFFF83020
+#define GPIO_DIR 0xFFF83024
+#define GPIO_CFG_MASK 0xFFF00000
+#define GPIO_CFG_VALUE 0x000AAAAA
+#define KPICONF_VALUE 0x000405FA
+#endif
+
+
+
+#define KEYPAD_MAGIC 'k'
+#define KEYPAD_MAXNR 2
+
+#define KPD_BLOCK _IOW('k', 1, unsigned int)
+#define KPD_NONBLOCK _IOW('k', 2, unsigned int)
+
+#endif
diff --git a/uClinux-2.4.20-uc1/drivers/char/w90n745_usi.c b/uClinux-2.4.20-uc1/drivers/char/w90n745_usi.c
index a8765c4..68e7082 100755
--- a/uClinux-2.4.20-uc1/drivers/char/w90n745_usi.c
+++ b/uClinux-2.4.20-uc1/drivers/char/w90n745_usi.c
@@ -1,331 +1,331 @@
-/****************************************************************************
- *
- * Copyright (c) 2004 - 2006 Winbond Electronics Corp. All rights reserved.
- *
- ****************************************************************************/
-
-/****************************************************************************
- *
- * FILENAME
- * w90n745_usi.c
- *
- * VERSION
- * 1.0
- *
- * DESCRIPTION
- * USI driver supported for W90n710.
- *
- * FUNCTIONS
- * all functions, if they has return value, return 0 if they success, others failed.
- *
- * HISTORY
- * 2006/01/10 Created by QFu
- *
- * REMARK
- * None
- *************************************************************************/
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/time.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include <asm/arch/hardware.h>
-#include <asm/arch/irqs.h>
-
-#include <asm/uaccess.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/string.h>
-#include <asm/atomic.h>
-
-#include "w90n745_usi.h"
-
-//#define USI_DEBUG
-//#define USI_DEBUG_ENABLE_ENTER_LEAVE
-//#define USI_DEBUG_ENABLE_MSG
-//#define USI_DEBUG_ENABLE_MSG2
-
-#ifdef USI_DEBUG
-#define PDEBUG(fmt, arg...) printk(fmt, ##arg)
-#else
-#define PDEBUG(fmt, arg...)
-#endif
-
-#ifdef USI_DEBUG_ENABLE_ENTER_LEAVE
-#define ENTER() PDEBUG("[%-20s] : Enter...\n", __FUNCTION__)
-#define LEAVE() PDEBUG("[%-20s] : Leave...\n", __FUNCTION__)
-#else
-#define ENTER()
-#define LEAVE()
-#endif
-
-#ifdef USI_DEBUG_ENABLE_MSG
-#define MSG(msg) PDEBUG("[%-20s] : %s\n", __FUNCTION__, msg)
-#else
-#define MSG(msg)
-#endif
-
-#ifdef USI_DEBUG_ENABLE_MSG2
-#define MSG2(fmt, arg...) PDEBUG("[%-20s] : "fmt, __FUNCTION__, ##arg)
-#define PRNBUF(buf, count) {int i;MSG2("Data: ");for(i=0;i<count;i++)\
- PDEBUG("%02x ", buf[i]);PDEBUG("\n");}
-#else
-#define MSG2(fmt, arg...)
-#define PRNBUF(buf, count)
-#endif
-
-#define usi_inl(addr) (*((volatile u32 *)(addr)))
-#define usi_outl(val, addr) (*((volatile u32 *)(addr))=(val))
-
-
-static atomic_t usi_available = ATOMIC_INIT(1);
-static struct usi_parameter global_parameter;
-static wait_queue_head_t wq;
-static volatile int trans_finish, slave_select;
-
-void usi_deselect_slave(void)
-{
- usi_outl(usi_inl(USI_SSR)&0xc, USI_SSR);
- slave_select = 0;
-}
-
-void usi_select_slave(int x)
-{
- usi_outl((global_parameter.active_level << 2)|(1 << x), USI_SSR);
- slave_select = 1;
-}
-
-static void usi_interrupt(int irq, void * dev_id, struct pt_regs *regs)
-{
- u32 reg;
-
- ENTER();
-
- reg = usi_inl(USI_CNTRL);
-
- if (!(reg & 0x10000)) /* it not me ? */
- return;
-
- reg |= 0x10000;
- usi_outl(reg, USI_CNTRL); /* clear interrupt flag */
-
- trans_finish = 1;
-
- wake_up_interruptible(&wq);
-
- LEAVE();
-}
-
-static int usi_transit(struct usi_data *data_ptr)
-{
- u32 reg,mask;
-
- ENTER();
-
- if (slave_select == 0)
- return -ENODEV;
-
- mask = (1 << data_ptr->bit_len) - 1;
-
- MSG2("bit_len : %d, mask : %x\n", data_ptr->bit_len, mask);
-
- usi_outl(data_ptr->write_data & mask , USI_TX0); /* write data to hardware buffer */
-
- MSG2("-> %x\n", data_ptr->write_data & mask);
-
- reg = (global_parameter.sleep << 12) |
- (global_parameter.lsb << 10) |
- (data_ptr->bit_len << 3) |
- (global_parameter.tx_neg << 2) |
- (global_parameter.rx_neg << 1) | 0x20001;
-
- trans_finish = 0;
- usi_outl(reg, USI_CNTRL); /* start */
- wait_event_interruptible(wq, trans_finish != 0);
-
- data_ptr->read_data = usi_inl(USI_RX0) & mask;
-
- MSG2("<- %x\n", data_ptr->read_data & mask);
-
- LEAVE();
-
- return 0;
-
-}
-
-static int usi_ioctl(struct inode *inode, struct file *flip, unsigned int cmd, unsigned long arg)
-{
- int err = 0;
- struct usi_parameter tmp_parameter;
- struct usi_data tmp_data;
-
- ENTER();
-
- if(_IOC_TYPE(cmd) != USI_IOC_MAGIC) return -ENOTTY;
- if(_IOC_NR(cmd) > USI_IOC_MAXNR) return -ENOTTY;
-
- if(_IOC_DIR(cmd) & _IOC_READ)
- err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
- else if(_IOC_DIR(cmd) & _IOC_WRITE)
- err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
-
- if(err)
- return -EFAULT;
-
- switch(cmd) {
- case USI_IOC_GETPARAMETER:
- if (copy_to_user((void *)arg, &global_parameter,
- sizeof(struct usi_parameter)))
- return -EFAULT;
- break;
- case USI_IOC_SETPARAMETER:
- if (copy_from_user(&tmp_parameter, (void *)arg,
- sizeof(struct usi_parameter)))
- return -EFAULT;
- memcpy(&global_parameter, &tmp_parameter,
- sizeof(struct usi_parameter));
-
- usi_outl(global_parameter.divider, USI_DIVIDER); /* update clock */
-
- break;
-
- case USI_IOC_SELECTSLAVE:
- if (arg < -1 && arg > 1)
- return -EPERM;
- if (arg == -1)
- usi_deselect_slave();
- else
- usi_select_slave(arg);
- break;
-
- case USI_IOC_TRANSIT:
- if (copy_from_user(&tmp_data, (void *)arg, sizeof(tmp_data)))
- return -EFAULT;
- err = usi_transit(&tmp_data);
- if (err)
- return err;
- if (copy_to_user((void *)arg, &tmp_data, sizeof(tmp_data)))
- return -EFAULT;
- break;
-
- default:
- return -ENOTTY;
-
- }
-
- LEAVE();
-
- return 0;
-}
-
-
-static int usi_open(struct inode *inode, struct file *filp)
-{
- u32 reg;
- int retval = -EBUSY;
-
- ENTER();
-
- if (! atomic_dec_and_test (&usi_available))
- goto failed;
-
- global_parameter.active_level = 0;
- global_parameter.lsb = 0;
- global_parameter.rx_neg = 0;
- global_parameter.tx_neg = 1;
- global_parameter.divider = 0x1;
- global_parameter.sleep = 0;
- slave_select = 0;
-
- reg = usi_inl(0xFFF83050) & 0xfff00fff;
- reg |= 0xaa000;
- usi_outl(reg, 0xFFF83050);
-
- reg = usi_inl(USI_CNTRL);
- reg |= 0x20000;
- usi_outl(reg, USI_CNTRL);
-
- MSG2("GPIO 5 : %x\n", usi_inl(0xFFF83050));
-
- usi_outl(global_parameter.divider, USI_DIVIDER); /* set clock */
-
- if ((retval = request_irq(INT_SPI, usi_interrupt, SA_INTERRUPT, "usi", NULL)) < 0) {
- printk("usi : request irq error\n");
- goto failed;
- }
-
- LEAVE();
-
- return 0; /* success */
-
-failed:
-
- atomic_inc(&usi_available); /* release the device */
-
- return retval;
-}
-
-static int usi_release(struct inode *inode, struct file *flip)
-{
- u32 reg;
-
- ENTER();
-
- reg = usi_inl(USI_CNTRL);
- reg &= 0xffff;
- usi_outl(reg, USI_CNTRL);
-
- free_irq(INT_SPI, NULL);
- usi_deselect_slave();
- atomic_inc(&usi_available); /* release the device */
-
- LEAVE();
-
- return 0;
-}
-
-
-struct file_operations usi_fops =
-{
- owner: THIS_MODULE,
- open: usi_open,
- release: usi_release,
- ioctl: usi_ioctl,
-};
-
-static int __init usi_init(void)
-{
- u32 reg;
- int result;
-
- init_waitqueue_head(&wq);
-
- /* every things ok, now, we can register char device safely */
-
- result = register_chrdev(USI_MAJOR, "usi", &usi_fops);
- if( result < 0){
- unregister_chrdev(USI_MAJOR, "usi");
- printk("usi : can't get major %d\n", USI_MAJOR);
- goto failed;
- }
-
- printk("USI driver has been installed successfully!\n");
-
-failed:
-
- return result;
-
-}
-
-static void __exit usi_exit(void)
-{
- unregister_chrdev(USI_MAJOR, "usi");
-}
-
-module_init(usi_init);
-module_exit(usi_exit);
-
+/****************************************************************************
+ *
+ * Copyright (c) 2004 - 2006 Winbond Electronics Corp. All rights reserved.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ *
+ * FILENAME
+ * w90n745_usi.c
+ *
+ * VERSION
+ * 1.0
+ *
+ * DESCRIPTION
+ * USI driver supported for W90n710.
+ *
+ * FUNCTIONS
+ * all functions, if they has return value, return 0 if they success, others failed.
+ *
+ * HISTORY
+ * 2006/01/10 Created by QFu
+ *
+ * REMARK
+ * None
+ *************************************************************************/
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <asm/arch/hardware.h>
+#include <asm/arch/irqs.h>
+
+#include <asm/uaccess.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/string.h>
+#include <asm/atomic.h>
+
+#include "w90n745_usi.h"
+
+//#define USI_DEBUG
+//#define USI_DEBUG_ENABLE_ENTER_LEAVE
+//#define USI_DEBUG_ENABLE_MSG
+//#define USI_DEBUG_ENABLE_MSG2
+
+#ifdef USI_DEBUG
+#define PDEBUG(fmt, arg...) printk(fmt, ##arg)
+#else
+#define PDEBUG(fmt, arg...)
+#endif
+
+#ifdef USI_DEBUG_ENABLE_ENTER_LEAVE
+#define ENTER() PDEBUG("[%-20s] : Enter...\n", __FUNCTION__)
+#define LEAVE() PDEBUG("[%-20s] : Leave...\n", __FUNCTION__)
+#else
+#define ENTER()
+#define LEAVE()
+#endif
+
+#ifdef USI_DEBUG_ENABLE_MSG
+#define MSG(msg) PDEBUG("[%-20s] : %s\n", __FUNCTION__, msg)
+#else
+#define MSG(msg)
+#endif
+
+#ifdef USI_DEBUG_ENABLE_MSG2
+#define MSG2(fmt, arg...) PDEBUG("[%-20s] : "fmt, __FUNCTION__, ##arg)
+#define PRNBUF(buf, count) {int i;MSG2("Data: ");for(i=0;i<count;i++)\
+ PDEBUG("%02x ", buf[i]);PDEBUG("\n");}
+#else
+#define MSG2(fmt, arg...)
+#define PRNBUF(buf, count)
+#endif
+
+#define usi_inl(addr) (*((volatile u32 *)(addr)))
+#define usi_outl(val, addr) (*((volatile u32 *)(addr))=(val))
+
+
+static atomic_t usi_available = ATOMIC_INIT(1);
+static struct usi_parameter global_parameter;
+static wait_queue_head_t wq;
+static volatile int trans_finish, slave_select;
+
+void usi_deselect_slave(void)
+{
+ usi_outl(usi_inl(USI_SSR)&0xc, USI_SSR);
+ slave_select = 0;
+}
+
+void usi_select_slave(int x)
+{
+ usi_outl((global_parameter.active_level << 2)|(1 << x), USI_SSR);
+ slave_select = 1;
+}
+
+static void usi_interrupt(int irq, void * dev_id, struct pt_regs *regs)
+{
+ u32 reg;
+
+ ENTER();
+
+ reg = usi_inl(USI_CNTRL);
+
+ if (!(reg & 0x10000)) /* it not me ? */
+ return;
+
+ reg |= 0x10000;
+ usi_outl(reg, USI_CNTRL); /* clear interrupt flag */
+
+ trans_finish = 1;
+
+ wake_up_interruptible(&wq);
+
+ LEAVE();
+}
+
+static int usi_transit(struct usi_data *data_ptr)
+{
+ u32 reg,mask;
+
+ ENTER();
+
+ if (slave_select == 0)
+ return -ENODEV;
+
+ mask = (1 << data_ptr->bit_len) - 1;
+
+ MSG2("bit_len : %d, mask : %x\n", data_ptr->bit_len, mask);
+
+ usi_outl(data_ptr->write_data & mask , USI_TX0); /* write data to hardware buffer */
+
+ MSG2("-> %x\n", data_ptr->write_data & mask);
+
+ reg = (global_parameter.sleep << 12) |
+ (global_parameter.lsb << 10) |
+ (data_ptr->bit_len << 3) |
+ (global_parameter.tx_neg << 2) |
+ (global_parameter.rx_neg << 1) | 0x20001;
+
+ trans_finish = 0;
+ usi_outl(reg, USI_CNTRL); /* start */
+ wait_event_interruptible(wq, trans_finish != 0);
+
+ data_ptr->read_data = usi_inl(USI_RX0) & mask;
+
+ MSG2("<- %x\n", data_ptr->read_data & mask);
+
+ LEAVE();
+
+ return 0;
+
+}
+
+static int usi_ioctl(struct inode *inode, struct file *flip, unsigned int cmd, unsigned long arg)
+{
+ int err = 0;
+ struct usi_parameter tmp_parameter;
+ struct usi_data tmp_data;
+
+ ENTER();
+
+ if(_IOC_TYPE(cmd) != USI_IOC_MAGIC) return -ENOTTY;
+ if(_IOC_NR(cmd) > USI_IOC_MAXNR) return -ENOTTY;
+
+ if(_IOC_DIR(cmd) & _IOC_READ)
+ err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
+ else if(_IOC_DIR(cmd) & _IOC_WRITE)
+ err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
+
+ if(err)
+ return -EFAULT;
+
+ switch(cmd) {
+ case USI_IOC_GETPARAMETER:
+ if (copy_to_user((void *)arg, &global_parameter,
+ sizeof(struct usi_parameter)))
+ return -EFAULT;
+ break;
+ case USI_IOC_SETPARAMETER:
+ if (copy_from_user(&tmp_parameter, (void *)arg,
+ sizeof(struct usi_parameter)))
+ return -EFAULT;
+ memcpy(&global_parameter, &tmp_parameter,
+ sizeof(struct usi_parameter));
+
+ usi_outl(global_parameter.divider, USI_DIVIDER); /* update clock */
+
+ break;
+
+ case USI_IOC_SELECTSLAVE:
+ if (arg < -1 && arg > 1)
+ return -EPERM;
+ if (arg == -1)
+ usi_deselect_slave();
+ else
+ usi_select_slave(arg);
+ break;
+
+ case USI_IOC_TRANSIT:
+ if (copy_from_user(&tmp_data, (void *)arg, sizeof(tmp_data)))
+ return -EFAULT;
+ err = usi_transit(&tmp_data);
+ if (err)
+ return err;
+ if (copy_to_user((void *)arg, &tmp_data, sizeof(tmp_data)))
+ return -EFAULT;
+ break;
+
+ default:
+ return -ENOTTY;
+
+ }
+
+ LEAVE();
+
+ return 0;
+}
+
+
+static int usi_open(struct inode *inode, struct file *filp)
+{
+ u32 reg;
+ int retval = -EBUSY;
+
+ ENTER();
+
+ if (! atomic_dec_and_test (&usi_available))
+ goto failed;
+
+ global_parameter.active_level = 0;
+ global_parameter.lsb = 0;
+ global_parameter.rx_neg = 0;
+ global_parameter.tx_neg = 1;
+ global_parameter.divider = 0x1;
+ global_parameter.sleep = 0;
+ slave_select = 0;
+
+ reg = usi_inl(0xFFF83050) & 0xfff00fff;
+ reg |= 0xaa000;
+ usi_outl(reg, 0xFFF83050);
+
+ reg = usi_inl(USI_CNTRL);
+ reg |= 0x20000;
+ usi_outl(reg, USI_CNTRL);
+
+ MSG2("GPIO 5 : %x\n", usi_inl(0xFFF83050));
+
+ usi_outl(global_parameter.divider, USI_DIVIDER); /* set clock */
+
+ if ((retval = request_irq(INT_SPI, usi_interrupt, SA_INTERRUPT, "usi", NULL)) < 0) {
+ printk("usi : request irq error\n");
+ goto failed;
+ }
+
+ LEAVE();
+
+ return 0; /* success */
+
+failed:
+
+ atomic_inc(&usi_available); /* release the device */
+
+ return retval;
+}
+
+static int usi_release(struct inode *inode, struct file *flip)
+{
+ u32 reg;
+
+ ENTER();
+
+ reg = usi_inl(USI_CNTRL);
+ reg &= 0xffff;
+ usi_outl(reg, USI_CNTRL);
+
+ free_irq(INT_SPI, NULL);
+ usi_deselect_slave();
+ atomic_inc(&usi_available); /* release the device */
+
+ LEAVE();
+
+ return 0;
+}
+
+
+struct file_operations usi_fops =
+{
+ owner: THIS_MODULE,
+ open: usi_open,
+ release: usi_release,
+ ioctl: usi_ioctl,
+};
+
+static int __init usi_init(void)
+{
+ u32 reg;
+ int result;
+
+ init_waitqueue_head(&wq);
+
+ /* every things ok, now, we can register char device safely */
+
+ result = register_chrdev(USI_MAJOR, "usi", &usi_fops);
+ if( result < 0){
+ unregister_chrdev(USI_MAJOR, "usi");
+ printk("usi : can't get major %d\n", USI_MAJOR);
+ goto failed;
+ }
+
+ printk("USI driver has been installed successfully!\n");
+
+failed:
+
+ return result;
+
+}
+
+static void __exit usi_exit(void)
+{
+ unregister_chrdev(USI_MAJOR, "usi");
+}
+
+module_init(usi_init);
+module_exit(usi_exit);
+
diff --git a/uClinux-2.4.20-uc1/drivers/char/w90n745_usi.h b/uClinux-2.4.20-uc1/drivers/char/w90n745_usi.h
index 14c8867..345ac6a 100755
--- a/uClinux-2.4.20-uc1/drivers/char/w90n745_usi.h
+++ b/uClinux-2.4.20-uc1/drivers/char/w90n745_usi.h
@@ -1,73 +1,73 @@
-/****************************************************************************
- *
- * Copyright (c) 2004 - 2006 Winbond Electronics Corp. All rights reserved.
- *
- ****************************************************************************/
-
-/****************************************************************************
- *
- * FILENAME
- * w90n745_usi.h
- *
- * VERSION
- * 1.0
- *
- * DESCRIPTION
- * USI driver supported for W90n710.
- *
- * FUNCTIONS
- * all functions, if they has return value, return 0 if they success, others failed.
- *
- * HISTORY
- * 2006/01/10 Created by QFu
- *
- * REMARK
- * None
- *************************************************************************/
-#ifndef _W90N745_USI_H_
-#define _W90N745_USI_H_
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-#define USI_BASE 0xfff86200
-#define USI_SIZE 0x30
-
-#define USI_CNTRL (USI_BASE | 0x00)
-#define USI_DIVIDER (USI_BASE | 0x04)
-#define USI_SSR (USI_BASE | 0x08)
-
-#define USI_RX0 (USI_BASE | 0x10)
-#define USI_RX1 (USI_BASE | 0x14)
-#define USI_RX2 (USI_BASE | 0x18)
-#define USI_RX3 (USI_BASE | 0x1c)
-
-#define USI_TX0 (USI_BASE | 0x10)
-#define USI_TX1 (USI_BASE | 0x14)
-#define USI_TX2 (USI_BASE | 0x18)
-#define USI_TX3 (USI_BASE | 0x1c)
-
-struct usi_parameter{
- unsigned int active_level:1;
- unsigned int lsb:1, tx_neg:1, rx_neg:1, divider:16;
- unsigned int sleep:4;
-};
-
-struct usi_data{
- unsigned int write_data;
- unsigned int read_data;
- unsigned int bit_len;
-};
-
-#define USI_MAJOR 231
-
-#define USI_IOC_MAGIC 'u'
-#define USI_IOC_MAXNR 3
-
-#define USI_IOC_GETPARAMETER _IOR(USI_IOC_MAGIC, 0, struct usi_parameter *)
-#define USI_IOC_SETPARAMETER _IOW(USI_IOC_MAGIC, 1, struct usi_parameter *)
-#define USI_IOC_SELECTSLAVE _IOW(USI_IOC_MAGIC, 2, int)
-#define USI_IOC_TRANSIT _IOW(USI_IOC_MAGIC, 3, struct usi_data *)
-
-#endif /* _W90N745_USI_H_ */
-
+/****************************************************************************
+ *
+ * Copyright (c) 2004 - 2006 Winbond Electronics Corp. All rights reserved.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ *
+ * FILENAME
+ * w90n745_usi.h
+ *
+ * VERSION
+ * 1.0
+ *
+ * DESCRIPTION
+ * USI driver supported for W90n710.
+ *
+ * FUNCTIONS
+ * all functions, if they has return value, return 0 if they success, others failed.
+ *
+ * HISTORY
+ * 2006/01/10 Created by QFu
+ *
+ * REMARK
+ * None
+ *************************************************************************/
+#ifndef _W90N745_USI_H_
+#define _W90N745_USI_H_
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define USI_BASE 0xfff86200
+#define USI_SIZE 0x30
+
+#define USI_CNTRL (USI_BASE | 0x00)
+#define USI_DIVIDER (USI_BASE | 0x04)
+#define USI_SSR (USI_BASE | 0x08)
+
+#define USI_RX0 (USI_BASE | 0x10)
+#define USI_RX1 (USI_BASE | 0x14)
+#define USI_RX2 (USI_BASE | 0x18)
+#define USI_RX3 (USI_BASE | 0x1c)
+
+#define USI_TX0 (USI_BASE | 0x10)
+#define USI_TX1 (USI_BASE | 0x14)
+#define USI_TX2 (USI_BASE | 0x18)
+#define USI_TX3 (USI_BASE | 0x1c)
+
+struct usi_parameter{
+ unsigned int active_level:1;
+ unsigned int lsb:1, tx_neg:1, rx_neg:1, divider:16;
+ unsigned int sleep:4;
+};
+
+struct usi_data{
+ unsigned int write_data;
+ unsigned int read_data;
+ unsigned int bit_len;
+};
+
+#define USI_MAJOR 231
+
+#define USI_IOC_MAGIC 'u'
+#define USI_IOC_MAXNR 3
+
+#define USI_IOC_GETPARAMETER _IOR(USI_IOC_MAGIC, 0, struct usi_parameter *)
+#define USI_IOC_SETPARAMETER _IOW(USI_IOC_MAGIC, 1, struct usi_parameter *)
+#define USI_IOC_SELECTSLAVE _IOW(USI_IOC_MAGIC, 2, int)
+#define USI_IOC_TRANSIT _IOW(USI_IOC_MAGIC, 3, struct usi_data *)
+
+#endif /* _W90N745_USI_H_ */
+