newton:add IRDA driver
authorlyx <lyx@rock-chips.com>
Mon, 4 Jul 2011 03:13:57 +0000 (20:13 -0700)
committerlyx <lyx@rock-chips.com>
Mon, 4 Jul 2011 03:13:57 +0000 (20:13 -0700)
now is just for sir

15 files changed:
arch/arm/configs/rk29_newton_defconfig [changed mode: 0644->0755]
arch/arm/mach-rk29/board-rk29-newton.c
arch/arm/mach-rk29/include/mach/board.h
arch/arm/mach-rk29/include/mach/rk29_smc.h [new file with mode: 0755]
drivers/Kconfig
drivers/Makefile
drivers/net/irda/Kconfig [changed mode: 0644->0755]
drivers/net/irda/Makefile [changed mode: 0644->0755]
drivers/net/irda/bu92725guw.c [new file with mode: 0755]
drivers/net/irda/bu92725guw.h [new file with mode: 0755]
drivers/net/irda/rk29_ir.c [new file with mode: 0755]
drivers/net/irda/rk29_ir.h [new file with mode: 0755]
drivers/smc/Kconfig [new file with mode: 0755]
drivers/smc/Makefile [new file with mode: 0755]
drivers/smc/rk29_smc.c [new file with mode: 0755]

old mode 100644 (file)
new mode 100755 (executable)
index eb198a7..b2cc190
@@ -487,7 +487,47 @@ CONFIG_ANDROID_PARANOID_NETWORK=y
 # CONFIG_NET_PKTGEN is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_CAN is not set
-# CONFIG_IRDA is not set
+CONFIG_IRDA=y
+
+#
+# IrDA protocols
+#
+CONFIG_IRLAN=y
+CONFIG_IRNET=y
+# CONFIG_IRCOMM is not set
+# CONFIG_IRDA_ULTRA is not set
+
+#
+# IrDA options
+#
+# CONFIG_IRDA_CACHE_LAST_LSAP is not set
+# CONFIG_IRDA_FAST_RR is not set
+CONFIG_IRDA_DEBUG=y
+
+#
+# Infrared-port device drivers
+#
+
+#
+# SIR device drivers
+#
+# CONFIG_IRTTY_SIR is not set
+
+#
+# Dongle support
+#
+# CONFIG_KINGSUN_DONGLE is not set
+# CONFIG_KSDAZZLE_DONGLE is not set
+# CONFIG_KS959_DONGLE is not set
+
+#
+# FIR device drivers
+#
+# CONFIG_USB_IRDA is not set
+# CONFIG_SIGMATEL_FIR is not set
+# CONFIG_MCS_FIR is not set
+CONFIG_RK_IRDA=y
+CONFIG_BU92725GUW=y
 CONFIG_BT=y
 CONFIG_BT_L2CAP=y
 CONFIG_BT_SCO=y
@@ -1774,6 +1814,7 @@ CONFIG_RK29_IPP=y
 #
 # CONFIG_CMMB is not set
 # CONFIG_TEST_CODE is not set
+CONFIG_RK29_SMC=y
 
 #
 # File systems
index 190070164d7ad289e2b42e1d7d0e7e2828fbd35a..77b164b6f6206d8af093d4f626439666f23fe894 100755 (executable)
@@ -45,6 +45,7 @@
 #include <mach/sram.h>
 #include <mach/ddr.h>
 #include <mach/cpufreq.h>
+#include <mach/rk29_smc.h>
 
 #include <linux/regulator/rk29-pwm-regulator.h>
 #include <linux/regulator/machine.h>
@@ -365,6 +366,140 @@ struct platform_device rk29_device_dma_cpy = {
 
 #endif
 
+#if defined(CONFIG_RK_IRDA) || defined(CONFIG_BU92747GUW_CIR)
+#define BU92747GUW_RESET_PIN         RK29_PIN3_PD4// INVALID_GPIO //
+#define BU92747GUW_RESET_MUX_NAME    GPIO3D4_HOSTWRN_NAME//NULL //
+#define BU92747GUW_RESET_MUX_MODE    GPIO3H_GPIO3D4//NULL //
+
+#define BU92747GUW_PWDN_PIN          RK29_PIN3_PD3//RK29_PIN5_PA7 //
+#define BU92747GUW_PWDN_MUX_NAME     GPIO3D3_HOSTRDN_NAME//GPIO5A7_HSADCDATA2_NAME //
+#define BU92747GUW_PWDN_MUX_MODE     GPIO3H_GPIO3D3//GPIO5L_GPIO5A7  //
+
+static int bu92747guw_io_init(void)
+{
+       int ret;
+       
+       //reset pin
+    if(BU92747GUW_RESET_MUX_NAME != NULL)
+    {
+        rk29_mux_api_set(BU92747GUW_RESET_MUX_NAME, BU92747GUW_RESET_MUX_MODE);
+    }
+       ret = gpio_request(BU92747GUW_RESET_PIN, NULL);
+       if(ret != 0)
+       {
+               gpio_free(BU92747GUW_RESET_PIN);
+               printk(">>>>>> BU92747GUW_RESET_PIN gpio_request err \n ");
+       }
+       gpio_direction_output(BU92747GUW_RESET_PIN, GPIO_HIGH);
+
+       //power down pin
+    if(BU92747GUW_PWDN_MUX_NAME != NULL)
+    {
+        rk29_mux_api_set(BU92747GUW_PWDN_MUX_NAME, BU92747GUW_PWDN_MUX_MODE);
+    }
+       ret = gpio_request(BU92747GUW_PWDN_PIN, NULL);
+       if(ret != 0)
+       {
+               gpio_free(BU92747GUW_PWDN_PIN);
+               printk(">>>>>> BU92747GUW_PWDN_PIN gpio_request err \n ");
+       }
+
+       //power down as default
+       gpio_direction_output(BU92747GUW_PWDN_PIN, GPIO_LOW);
+       
+       return 0;
+}
+
+
+static int bu92747guw_io_deinit(void)
+{
+       gpio_free(BU92747GUW_PWDN_PIN);
+       gpio_free(BU92747GUW_RESET_PIN);
+       return 0;
+}
+
+//power ctl func is share with irda and remote
+static int nPowerOnCount = 0;
+static DEFINE_MUTEX(bu92747_power_mutex);
+
+//1---power on;  0---power off
+static int bu92747guw_power_ctl(int enable)
+{
+    printk("%s \n",__FUNCTION__);
+
+       mutex_lock(&bu92747_power_mutex);
+       if (enable) {
+               nPowerOnCount++;
+               if (nPowerOnCount == 1) {//power on first       
+                       //smc0_init(NULL);
+                       gpio_set_value(BU92747GUW_PWDN_PIN, GPIO_HIGH);
+                       gpio_set_value(BU92747GUW_RESET_PIN, GPIO_LOW);
+                       mdelay(5);
+                       gpio_set_value(BU92747GUW_RESET_PIN, GPIO_HIGH);
+                       mdelay(5);
+               }
+       }
+       else {
+               nPowerOnCount--;
+               if (nPowerOnCount == 0) {//power down final
+                       //smc0_exit();
+                       gpio_set_value(BU92747GUW_PWDN_PIN, GPIO_LOW);
+               }
+       }
+       mutex_unlock(&bu92747_power_mutex);
+       return 0;
+}
+#endif
+
+#ifdef CONFIG_RK_IRDA
+#define IRDA_IRQ_PIN           RK29_PIN5_PB2
+#define IRDA_IRQ_MUX_NAME      GPIO5B2_HSADCDATA5_NAME
+#define IRDA_IRQ_MUX_MODE      GPIO5L_GPIO5B2
+
+int irda_iomux_init(void)
+{
+    int ret = 0;
+
+       //irda irq pin
+    if(IRDA_IRQ_MUX_NAME != NULL)
+    {
+        rk29_mux_api_set(IRDA_IRQ_MUX_NAME, IRDA_IRQ_MUX_MODE);
+    }
+       ret = gpio_request(IRDA_IRQ_PIN, NULL);
+       if(ret != 0)
+       {
+               gpio_free(IRDA_IRQ_PIN);
+               printk(">>>>>> IRDA_IRQ_PIN gpio_request err \n ");
+       }
+       gpio_pull_updown(IRDA_IRQ_PIN, GPIO_HIGH);
+       gpio_direction_input(IRDA_IRQ_PIN);
+
+    return 0;
+}
+
+int irda_iomux_deinit(void)
+{
+       gpio_free(IRDA_IRQ_PIN);
+       return 0;
+}
+
+static struct irda_info rk29_irda_info = {
+    .intr_pin = IRDA_IRQ_PIN,
+    .iomux_init = irda_iomux_init,
+    .iomux_deinit = irda_iomux_deinit,
+       .irda_pwr_ctl = bu92747guw_power_ctl,
+};
+
+static struct platform_device irda_device = {
+       .name           = "rk_irda",
+    .id                  = -1,
+       .dev            = {
+               .platform_data  = &rk29_irda_info,
+       }
+};
+#endif
+
+
 static struct android_pmem_platform_data android_pmem_pdata = {
        .name           = "pmem",
        .start          = PMEM_UI_BASE,
@@ -1486,6 +1621,9 @@ static struct platform_device *devices[] __initdata = {
 #ifdef CONFIG_RK29_NEWTON
        &rk29_device_newton,
 #endif
+#ifdef CONFIG_RK_IRDA
+    &irda_device,
+#endif
 };
 
 /*****************************************************************************************
@@ -1686,6 +1824,12 @@ static void __init machine_rk29_board_init(void)
 #endif
 
        board_usb_detect_init(RK29_PIN0_PA0);
+
+#if defined(CONFIG_RK_IRDA) || defined(CONFIG_BU92747GUW_CIR)
+       smc0_init(NULL);
+       bu92747guw_io_init();
+#endif
+
 }
 
 static void __init machine_rk29_fixup(struct machine_desc *desc, struct tag *tags,
index e4b3d924b6ef3edc708c2aaae84c590482430554..8c9eec37c046913e3c1f6f29a0c1cbf15143ffff 100755 (executable)
 #include <linux/timer.h>
 #include <linux/notifier.h>
 
+struct irda_info{
+    u32 intr_pin;
+    int (*iomux_init)(void);
+    int (*iomux_deinit)(void);
+    int (*irda_pwr_ctl)(int en);
+};
+
 struct rk29_button_light_info{
        u32 led_on_pin;
        u32 led_on_level;
diff --git a/arch/arm/mach-rk29/include/mach/rk29_smc.h b/arch/arm/mach-rk29/include/mach/rk29_smc.h
new file mode 100755 (executable)
index 0000000..264057f
--- /dev/null
@@ -0,0 +1,11 @@
+\r
+#ifndef __DRIVER_IRDA_SMC_H\r
+#define __DRIVER_IRDA_SMC_H\r
+\r
+extern int smc0_init(u8 **base_addr);\r
+extern void smc0_exit(void);\r
+extern int smc0_write(u32 addr, u32 data);\r
+extern int smc0_read(u32 addr);\r
+extern int smc0_enable(int enable);\r
+#endif\r
+\r
index 33a14a76a6b309ea5d05b315db3919f2dba277fa..32f588c5fc2c95b30c56cf2cf088f4e0d397a8d8 100755 (executable)
@@ -126,4 +126,5 @@ source "drivers/cmmb/Kconfig"
 
 source "drivers/testcode/Kconfig"
 
+source "drivers/smc/Kconfig"
 endmenu
index d5633915775237d5062ade117cdade1643bf0e2a..8a5da3179476b0ab26acc3a92a5317cc6e5c3f59 100755 (executable)
@@ -116,5 +116,6 @@ obj-y                               += platform/
 obj-y                          += ieee802154/
 obj-$(CONFIG_CMMB)             += cmmb/
 obj-$(CONFIG_TEST_CODE)                += testcode/
+obj-y          += smc/
 obj-y                          += dbg/
 
old mode 100644 (file)
new mode 100755 (executable)
index f763842..1fb4578
@@ -387,5 +387,19 @@ config MCS_FIR
          To compile it as a module, choose M here: the module will be called
          mcs7780.
 
+config RK_IRDA
+       tristate "rockchip rk29 IrDA"
+       depends on IRDA && RK29_SMC
+       help
+         Say Y or M here if you want to build support for the rk29
+         built-in IRDA interface which can support both SIR, MIR and FIR.
+
+choice
+    depends on RK_IRDA
+       prompt  "irda module select"
+config BU92725GUW
+       bool "bu92725guw"
+endchoice
+
 endmenu
 
old mode 100644 (file)
new mode 100755 (executable)
index d82e1e3..8aa32fa
@@ -37,6 +37,8 @@ obj-$(CONFIG_EP7211_DONGLE)   += ep7211-sir.o
 obj-$(CONFIG_KINGSUN_DONGLE)   += kingsun-sir.o
 obj-$(CONFIG_KSDAZZLE_DONGLE)  += ksdazzle-sir.o
 obj-$(CONFIG_KS959_DONGLE)     += ks959-sir.o
+obj-$(CONFIG_RK_IRDA)           += rk29_ir.o
+obj-$(CONFIG_BU92725GUW)        += bu92725guw.o
 
 # The SIR helper module
 sir-dev-objs := sir_dev.o sir_dongle.o
diff --git a/drivers/net/irda/bu92725guw.c b/drivers/net/irda/bu92725guw.c
new file mode 100755 (executable)
index 0000000..b1794b3
--- /dev/null
@@ -0,0 +1,687 @@
+/***************************************************************************\r
+ *\r
+ * File:          bu92725guw.c\r
+ *\r
+ * Description:   functions of operating with bu92725guw board.\r
+ *\r
+ * Created:       2007/9\r
+ *\r
+ * Rev 1.1\r
+ *\r
+ *\r
+ * Confidential ROHM CO.,LTD.\r
+ *\r
+ ****************************************************************************/\r
+\r
+#include <linux/module.h>\r
+#include <linux/delay.h>\r
+#include <linux/errno.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/fs.h>\r
+#include <linux/kernel.h>\r
+#include <linux/slab.h>\r
+#include <linux/mm.h>\r
+#include <linux/ioport.h>\r
+#include <linux/init.h>\r
+#include <linux/sched.h>\r
+#include <linux/pci.h>\r
+#include <linux/random.h>\r
+#include <linux/version.h>\r
+#include <linux/mutex.h>\r
+#include <linux/videodev2.h>\r
+#include <linux/dma-mapping.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/kthread.h>\r
+#include <linux/highmem.h>\r
+#include <linux/freezer.h>\r
+\r
+#include "rk29_ir.h"\r
+\r
+#if 0\r
+#define RK29IR_DBG(x...) printk(x)\r
+#else\r
+#define RK29IR_DBG(x...)\r
+#endif\r
+\r
+\r
+ /*---------------------------------------------------------------------------\r
+                               Data\r
+----------------------------------------------------------------------------*/\r
+/* record current setting\r
+*/\r
+static u32 curTrans_mode;  /* SIR, MIR, FIR */\r
+static u32 curTrans_speed; /* 2.4kbps, 9.6kbps,..., 4Mbps */\r
+static u32 curTrans_way;   /* idle, send, receive, auto-multi-receive, multi-receive, multi-send */\r
+static u16 curFIT;         /* FIT2,1,0 in PWR/FIT register */\r
+\r
+/*---------------------------------------------------------------------------\r
+                               Function Proto\r
+----------------------------------------------------------------------------*/\r
+static void internal_set(u8 modeChg);\r
+\r
+/*---------------------------------------------------------------------------\r
+                               global Function Implement\r
+----------------------------------------------------------------------------*/\r
+/*\r
+ * Synopsis:  board initialize\r
+ *\r
+ * Paras:     none\r
+ *\r
+ * Return:    none\r
+ */\r
+void irda_hw_init(struct rk29_irda *si)\r
+{\r
+    //smc0_init(&si->irda_base_addr);\r
+\r
+    //printk("%s [%d]\n",__FUNCTION__,__LINE__);\r
+}\r
+void irda_hw_deinit(struct rk29_irda *si)\r
+{\r
+   // smc0_init(&si->irda_base_addr);\r
+}\r
+\r
+int irda_hw_startup(struct rk29_irda *si)\r
+{\r
+    volatile u16 val;\r
+    int i=0;\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+\r
+    //IER (disable all)\r
+       BU92725GUW_WRITE_REG(REG_IER_ADDR, 0x0000);\r
+\r
+//MCR (use IrDA Controller func, 9.6kbps, SIR)\r
+       BU92725GUW_WRITE_REG(REG_MCR_ADDR, REG_MCR_9600 | REG_MCR_SIR);\r
+\r
+//PWR/FIT (default)\r
+       BU92725GUW_WRITE_REG(REG_PWR_FIT_ADDR, REG_PWR_FIT_MPW_3 | REG_PWR_FIT_FPW_2 | REG_PWR_FIT_FIT_0);\r
+\r
+//TRCR (idle, clr fifo, IrDA power on, mode select enable)\r
+       BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_FCLR | REG_TRCR_MS_EN);\r
+       val = BU92725GUW_READ_REG(REG_TRCR_ADDR);\r
+       while (val & REG_TRCR_MS_EN) {\r
+               val = BU92725GUW_READ_REG(REG_TRCR_ADDR);\r
+       }\r
+\r
+//FTLV\r
+       BU92725GUW_WRITE_REG(REG_FTLV_ADDR, 0x0000);\r
+\r
+//    for(i=0; i<REG_WREC_ADDR;i=(i+2))//%REG_WREC_ADDR) //\r
+//        printk("reg %d = 0x%x\n",i,BU92725GUW_READ_REG(i));\r
+\r
+       curTrans_mode = BU92725GUW_SIR;\r
+       curTrans_speed = 9600;\r
+       curTrans_way = BU92725GUW_IDLE;\r
+       curFIT = REG_PWR_FIT_FIT_0;\r
+    return 0;\r
+}\r
+\r
+int irda_hw_shutdown(struct rk29_irda *si)\r
+{\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+\r
+    //IER (diable all)\r
+       BU92725GUW_WRITE_REG(REG_IER_ADDR, 0x0000);\r
+\r
+//MCR (use IrDA Controller func, 9.6kbps, SIR)\r
+       BU92725GUW_WRITE_REG(REG_MCR_ADDR, REG_MCR_9600 | REG_MCR_SIR);\r
+\r
+//PWR/FIT (default)\r
+       BU92725GUW_WRITE_REG(REG_PWR_FIT_ADDR, REG_PWR_FIT_MPW_3 | REG_PWR_FIT_FPW_2 | REG_PWR_FIT_FIT_0);\r
+\r
+//TRCR (idle, clr fifo, IrDA power down)\r
+       BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_FCLR | REG_TRCR_IRPD);\r
+\r
+//FTLV\r
+       BU92725GUW_WRITE_REG(REG_FTLV_ADDR, 0x0000);\r
+\r
+       curTrans_mode = BU92725GUW_SIR;\r
+       curTrans_speed = 9600;\r
+       curTrans_way = BU92725GUW_IDLE;\r
+       curFIT = REG_PWR_FIT_FIT_0;\r
+\r
+    return 0;\r
+}\r
+\r
+/*\r
+ * Synopsis:  set data transfer speed\r
+ *\r
+ * Paras:     speed - speed value will be set; value is from enum eTrans_Speed\r
+ *\r
+ * Return:    none\r
+ */\r
+int irda_hw_set_speed(u32 speed)\r
+{\r
+       u32 mode;\r
+       u8 modeChg = 0;\r
+\r
+       /* do nothing if speed is same as current */\r
+       RK29IR_DBG("line %d: enter %s, speed=%d\n", __LINE__, __FUNCTION__, speed);\r
+\r
+       if (speed == curTrans_speed)\r
+               return 0;\r
+\r
+       /* mode */\r
+       switch (speed) {\r
+       case 2400:\r
+       case 9600:\r
+       case 19200:\r
+       case 38400:\r
+       case 57600:\r
+       case 115200:\r
+               mode = BU92725GUW_SIR;\r
+               break;\r
+       case 576000:\r
+       case 1152000:\r
+               mode = BU92725GUW_MIR;\r
+               break;\r
+       case 4000000:\r
+               mode = BU92725GUW_FIR;\r
+               break;\r
+       default:\r
+               return -1; //invalid\r
+       }\r
+\r
+       /* speed */\r
+       curTrans_speed = speed;\r
+\r
+       /* change trans way if needed */\r
+       switch (curTrans_way) {\r
+       case BU92725GUW_IDLE:\r
+               break;\r
+       case BU92725GUW_REV:\r
+               if (mode != BU92725GUW_SIR)\r
+                       curTrans_way = BU92725GUW_AUTO_MULTI_REV;\r
+                       //curTrans_way = BU92725GUW_MULTI_REV;\r
+               break;\r
+       case BU92725GUW_SEND:\r
+               if (mode != BU92725GUW_SIR)\r
+                       curTrans_way = BU92725GUW_MULTI_SEND;\r
+               break;\r
+       case BU92725GUW_AUTO_MULTI_REV:\r
+               if (mode == BU92725GUW_SIR)\r
+                       curTrans_way = BU92725GUW_REV;\r
+               break;\r
+       case BU92725GUW_MULTI_REV: //not used now\r
+               if (mode == BU92725GUW_SIR)\r
+                       curTrans_way = BU92725GUW_REV;\r
+               break;\r
+       case BU92725GUW_MULTI_SEND:\r
+               if (mode == BU92725GUW_SIR)\r
+                       curTrans_way = BU92725GUW_SEND;\r
+               break;\r
+       }\r
+\r
+       if (mode != curTrans_mode) {\r
+               if ((mode == BU92725GUW_FIR) || (curTrans_mode == BU92725GUW_FIR))\r
+                       modeChg = 1; /* need set TRCR5:MS_EN */\r
+       }\r
+\r
+       curTrans_mode = mode;\r
+\r
+       /* set bu92725guw registers */\r
+       //internal_set(modeChg);\r
+       internal_set(1);\r
+\r
+    return 0;\r
+}\r
+\r
+int irda_hw_tx_enable_irq(enum eTrans_Mode mode)\r
+{\r
+\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+       /* hardware-specific code\r
+       */\r
+       if (mode == BU92725GUW_SIR)\r
+               BU92725GUW_set_trans_way(BU92725GUW_SEND);\r
+       else\r
+               BU92725GUW_set_trans_way(BU92725GUW_MULTI_SEND);\r
+\r
+       //BU92725GUW_clr_fifo();\r
+\r
+    return 0;\r
+}\r
+\r
+int irda_hw_tx_enable(int len)\r
+{\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+    BU92725GUW_WRITE_REG(REG_FTLV_ADDR, len);\r
+    BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_TX_EN);\r
+    return 0;\r
+}\r
+\r
+int irda_hw_get_irqsrc(void)\r
+{\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+    return BU92725GUW_READ_REG(REG_EIR_ADDR);\r
+}\r
+\r
+int irda_hw_get_data16(char* data8)\r
+{\r
+    u16 data16 = 0;\r
+    int len = 0;\r
+\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+\r
+    len = BU92725GUW_READ_REG(REG_FLV_ADDR);\r
+    if(len > 0)\r
+    {\r
+        /* read data from RXD */\r
+       data16 = BU92725GUW_READ_REG(REG_RXD_ADDR);\r
+       data8[0]        = (u8)data16;\r
+       data8[1]        = (u8)(data16 >> 8);\r
+        return 2;\r
+    }   else    {\r
+        return 0;\r
+    }\r
+}\r
+\r
+void irda_hw_set_moderx(void)\r
+{\r
+   // frData.ucFlags &= ~(FRMF_TX_ACTIVE);\r
+   // frData.ucFlags |= FRMF_RX_ACTIVE;\r
+\r
+    int i=0;\r
+    /* hardware-specific code\r
+       */\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+       \r
+       //BU92725GUW_clr_fifo();\r
+\r
+       if (curTrans_mode == BU92725GUW_SIR)\r
+               BU92725GUW_set_trans_way(BU92725GUW_REV);\r
+       else\r
+               BU92725GUW_set_trans_way(BU92725GUW_AUTO_MULTI_REV);\r
+               //BU92725GUW_set_trans_way(BU92725GUW_MULTI_REV);\r
+}\r
+\r
+int irda_hw_get_mode(void)\r
+{\r
+       return curTrans_way;\r
+               \r
+    u16 val = 0;\r
+    val = BU92725GUW_READ_REG(REG_TRCR_ADDR);\r
+       RK29IR_DBG("line %d: enter %s, REG_TRCR_ADDR = 0x%x\n", __LINE__, __FUNCTION__, val);\r
+\r
+    return (val& (REG_TRCR_TX_EN | REG_TRCR_RX_EN));\r
+}\r
+\r
+/*\r
+ * Synopsis:  set data transfer way\r
+ *\r
+ * Paras:     way - transfer way will be set; value is from enum eThrans_Way\r
+ *\r
+ * Return:    none\r
+ */\r
+void BU92725GUW_set_trans_way(u32 way)\r
+{\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+       if (way == curTrans_way)\r
+               return;\r
+\r
+       curTrans_way = way;\r
+\r
+       /* set bu92725guw registers */\r
+       internal_set(1);\r
+}\r
+\r
+/*\r
+ * Synopsis:  clear fifo\r
+ *\r
+ * Paras:     none\r
+ *\r
+ * Return:    none\r
+ */\r
+void BU92725GUW_clr_fifo(void)\r
+{\r
+       volatile u16 val;\r
+\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+       /* set TRCR4:FCLR */\r
+       val = BU92725GUW_READ_REG(REG_TRCR_ADDR);\r
+       val &= 0xff8f;\r
+       val |= REG_TRCR_FCLR;\r
+       BU92725GUW_WRITE_REG(REG_TRCR_ADDR, val);\r
+\r
+       /* wait op complete */\r
+       val = BU92725GUW_READ_REG(REG_TRCR_ADDR);\r
+       while (val & REG_TRCR_FCLR)\r
+               val = BU92725GUW_READ_REG(REG_TRCR_ADDR);\r
+}\r
+\r
+/*\r
+ * Synopsis:  read frame data from fifo\r
+ *\r
+ * Paras:     buf - point to buffer for storing frame data\r
+ *\r
+ * Return:    number of data got from fifo (in byte)\r
+ */\r
+u16 BU92725GUW_get_data(u8 *buf)\r
+{\r
+       volatile u16 data;\r
+       u16 len, count, i;\r
+\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+\r
+       /* get data count from FLV or FLVII */\r
+       if (curTrans_way == BU92725GUW_REV)\r
+               len = BU92725GUW_READ_REG(REG_FLV_ADDR);\r
+       else\r
+               len = BU92725GUW_READ_REG(REG_FLVII_ADDR);\r
+\r
+       count = (len % 2)? (len / 2 + 1) : (len / 2);\r
+\r
+       /* read data from RXD */\r
+       for (i=0; i<count; i++) {\r
+               data = BU92725GUW_READ_REG(REG_RXD_ADDR);\r
+               buf[i * 2]              = (u8)data;\r
+               buf[i * 2 + 1]  = (u8)(data >> 8);\r
+       }\r
+\r
+        /* restart receive mode under SIR */\r
+       if (curTrans_way == BU92725GUW_REV) {\r
+               BU92725GUW_WRITE_REG(REG_TRCR_ADDR, 0x0000);\r
+               BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_RX_EN);\r
+       }\r
+\r
+       return len;\r
+}\r
+\r
+/*\r
+ * Synopsis:  write data from buffer1 and buffer2 into fifo\r
+ *\r
+ * Paras:     buf1 - point to buffer 1\r
+ *            len1 - length of data to write into fifo from buffer 1\r
+ *            buf2 - point to buffer 2\r
+ *            len2 - length of data to write into fifo from buffer 2\r
+ *\r
+ * Return:    none\r
+ */\r
+ void BU92725GUW_send_data(u8 *buf1, u16 len1, u8 *buf2, u16 len2)\r
+{/* buf2,len2 will be used by framer under MIR/FIR mode */\r
+       u16 data, len, pos;\r
+       u8  *ptr;\r
+\r
+       len = len1 + len2;\r
+       pos = 0;\r
+       ptr = (u8 *)(&data);\r
+\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+\r
+       if (len == 0)\r
+               return;\r
+       \r
+       /* set FTLV */\r
+       BU92725GUW_WRITE_REG(REG_FTLV_ADDR, len);\r
+\r
+       /* set TRCR:TX_EN under normal send mode */\r
+       if (curTrans_way == BU92725GUW_SEND)  {//SIR\r
+               BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_TX_EN);\r
+       }\r
+\r
+\r
+       /* set TXD */\r
+       while (pos < len) {\r
+\r
+               *ptr++ = (pos < len1)? buf1[pos] : buf2[pos-len1];\r
+\r
+               pos++;\r
+\r
+               if (pos < len) {\r
+                       *ptr-- = (pos < len1)? buf1[pos] : buf2[pos-len1];\r
+               } else\r
+                       *ptr-- = 0x00;\r
+\r
+               pos++;\r
+\r
+               BU92725GUW_WRITE_REG(REG_TXD_ADDR, data);\r
+       }\r
+}\r
+\r
+/*\r
+ * Synopsis:  set frame sending interval under multi-window send mode\r
+ *\r
+ * Paras:     us - interval time value to set\r
+ *\r
+ * Return:    none\r
+ */\r
+void BU92725GUW_set_frame_interval(u32 us)\r
+{\r
+       volatile u16 val;\r
+\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+       /* set PWR/FIT */\r
+\r
+       val = BU92725GUW_READ_REG(REG_PWR_FIT_ADDR);\r
+       //val &= 0xf8ff;\r
+       val &= 0xf0ff;\r
+       \r
+       if (us <= 100)\r
+               val |= REG_PWR_FIT_FIT_0;\r
+       else if (us <= 200)\r
+               val |= REG_PWR_FIT_FIT_1;\r
+       else if (us <= 300)\r
+               val |= REG_PWR_FIT_FIT_2;\r
+       else if (us <= 400)\r
+               val |= REG_PWR_FIT_FIT_3;\r
+       else if (us <= 500)\r
+               val |= REG_PWR_FIT_FIT_4;\r
+       else if (us <= 600)\r
+               val |= REG_PWR_FIT_FIT_5;\r
+       else if (us <= 800)\r
+               val |= REG_PWR_FIT_FIT_6;\r
+       else if (us <= 1000)\r
+               val |= REG_PWR_FIT_FIT_7;\r
+       else if (us <= 1200)\r
+               val |= REG_PWR_FIT_FIT_8;\r
+       else if (us <= 1400)\r
+               val |= REG_PWR_FIT_FIT_9;\r
+       else if (us <= 1600)\r
+               val |= REG_PWR_FIT_FIT_A;\r
+       else if (us <= 1800)\r
+               val |= REG_PWR_FIT_FIT_B;\r
+       else if (us <= 2000)\r
+               val |= REG_PWR_FIT_FIT_C;\r
+       else if (us <= 2200)\r
+               val |= REG_PWR_FIT_FIT_D;\r
+       else if (us <= 2400)\r
+               val |= REG_PWR_FIT_FIT_E;\r
+       else\r
+               val |= REG_PWR_FIT_FIT_F;\r
+\r
+       BU92725GUW_WRITE_REG(REG_PWR_FIT_ADDR, val);\r
+\r
+       //curFIT = val & 0x0700;\r
+       curFIT = val & 0x0F00;\r
+}\r
+\r
+/*\r
+ * Synopsis:  return current transfer mode (SIR/MIR/FIR)\r
+ *\r
+ * Paras:     none\r
+ *\r
+ * Return:    current transfer mode\r
+ */\r
+u32 BU92725GUW_get_trans_mode(void)\r
+{\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+       return curTrans_mode;\r
+}\r
+\r
+/*\r
+ * Synopsis:  add a IrDA pulse following frame\r
+ *\r
+ * Paras:     none\r
+ *\r
+ * Return:    none\r
+ */\r
+void BU92725GUW_add_pulse(void)\r
+{\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+       /* valid only under M/FIR send mode */\r
+       if (curTrans_way != BU92725GUW_MULTI_SEND)\r
+               return;\r
+\r
+       /* set TRCR3:IR_PLS */\r
+       BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_IR_PLS | REG_TRCR_TX_CON);\r
+}\r
+\r
+/*\r
+ * Synopsis:  soft reset bu92725guw board; will be called after some error happened\r
+ *\r
+ * Paras:     none\r
+ *\r
+ * Return:    none\r
+ */\r
+void BU92725GUW_reset(void)\r
+{\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+       /* set bu925725guw registers */\r
+       internal_set(1);\r
+}\r
+\r
+/*---------------------------------------------------------------------------\r
+                               local Function Implement\r
+----------------------------------------------------------------------------*/\r
+/*\r
+ * Synopsis:  set bu92725guw internal registers\r
+ *\r
+ * Paras:     modeChg - need set TRCR5:MS_EN or not\r
+ *\r
+ * Return:    none\r
+ */\r
+static void internal_set(u8 modeChg)\r
+{\r
+       volatile u16 val;\r
+\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+       /* disable INT */\r
+       BU92725GUW_WRITE_REG(REG_IER_ADDR, 0x0000);\r
+       val = BU92725GUW_READ_REG(REG_EIR_ADDR);\r
+\r
+       /* MCR */\r
+       val = 0;\r
+       switch (curTrans_mode) {\r
+       case BU92725GUW_SIR: //00\r
+               val |= REG_MCR_SIR;\r
+               break;\r
+       case BU92725GUW_MIR: //01\r
+               val |= REG_MCR_MIR;\r
+               break;\r
+       case BU92725GUW_FIR: //10\r
+               val |= REG_MCR_FIR;\r
+               break;\r
+       }\r
+       switch (curTrans_speed) {\r
+       case 2400: //000\r
+               val |= REG_MCR_2400;\r
+               break;\r
+       case 9600: //010\r
+               val |= REG_MCR_9600;\r
+               break;\r
+       case 19200: //011\r
+               val |= REG_MCR_19200;\r
+               break;\r
+       case 38400: //100\r
+               val |= REG_MCR_38400;\r
+               break;\r
+       case 57600: //101\r
+               val |= REG_MCR_57600;\r
+               break;\r
+       case 115200: //110\r
+               val |= REG_MCR_115200;\r
+               break;\r
+       case 576000: //001\r
+               val |= REG_MCR_576K;\r
+               break;\r
+       case 1152000: //010\r
+               val |= REG_MCR_1152K;\r
+               break;\r
+       case 4000000: //010\r
+               val |= REG_MCR_4M;\r
+               break;\r
+       }\r
+       BU92725GUW_WRITE_REG(REG_MCR_ADDR, val);\r
+       RK29IR_DBG("REG_MCR_ADDR: 0x%x\n", val);\r
+\r
+       /* PWR / FIT */\r
+       switch (curTrans_mode) {\r
+       case BU92725GUW_SIR:\r
+               val = 0x0000;\r
+               break;\r
+       case BU92725GUW_MIR:\r
+               val = REG_PWR_FIT_MPW_3 | curFIT;\r
+               break;\r
+       case BU92725GUW_FIR:\r
+               val = REG_PWR_FIT_FPW_2 | curFIT;\r
+               break;\r
+       }\r
+       BU92725GUW_WRITE_REG(REG_PWR_FIT_ADDR, val);\r
+       RK29IR_DBG("REG_PWR_FIT_ADDR: 0x%x\n", val);\r
+\r
+       /* TRCR:MS_EN */\r
+       if (modeChg) {\r
+               BU92725GUW_WRITE_REG(REG_TRCR_ADDR, REG_TRCR_MS_EN);\r
+               val = BU92725GUW_READ_REG(REG_TRCR_ADDR);\r
+               while (val & REG_TRCR_MS_EN) {\r
+                       val = BU92725GUW_READ_REG(REG_TRCR_ADDR);\r
+               }\r
+       }\r
+\r
+       /* TRCR */\r
+       switch (curTrans_way) {\r
+       case BU92725GUW_IDLE:\r
+               val = 0x0000;\r
+               break;\r
+       case BU92725GUW_REV:\r
+               val = REG_TRCR_RX_EN;\r
+               break;\r
+       case BU92725GUW_SEND:\r
+               val = 0x0000;\r
+               break;\r
+       case BU92725GUW_AUTO_MULTI_REV:\r
+               val = REG_TRCR_RX_EN | REG_TRCR_AUTO_FLV_CP;\r
+               break;\r
+       case BU92725GUW_MULTI_REV: //not used\r
+               val = REG_TRCR_RX_EN | REG_TRCR_RX_CON;\r
+               break;\r
+       case BU92725GUW_MULTI_SEND:\r
+               val = REG_TRCR_TX_CON;\r
+               break;\r
+       }\r
+       BU92725GUW_WRITE_REG(REG_TRCR_ADDR, val);\r
+       RK29IR_DBG("REG_TRCR_ADDR: 0x%x\n", val);\r
+\r
+       /* IER */\r
+       switch (curTrans_way) {\r
+       case BU92725GUW_IDLE:\r
+               val = 0x0000;\r
+               break;\r
+\r
+       case BU92725GUW_REV: /* SIR use */\r
+               val = REG_INT_EOFRX | REG_INT_TO | REG_INT_OE | REG_INT_FE; //IER1, 2, 5, 7\r
+               break;\r
+\r
+       case BU92725GUW_SEND: /* SIR use */\r
+               val = REG_INT_TXE; //IER3\r
+               break;\r
+\r
+       case BU92725GUW_MULTI_REV: /* not used */\r
+               val = REG_INT_STFRX | REG_INT_TO | REG_INT_CRC | REG_INT_OE | REG_INT_EOF | REG_INT_AC | REG_INT_DECE | \r
+                         REG_INT_RDOE | REG_INT_DEX | REG_INT_RDUE; //IER1,2, 4, 5, 6, 7, 8, 9, 10\r
+               break;\r
+\r
+       case BU92725GUW_AUTO_MULTI_REV: /* M/FIR use */\r
+               val = REG_INT_TO | REG_INT_CRC | REG_INT_OE | REG_INT_EOF | REG_INT_AC | REG_INT_DECE | \r
+                         REG_INT_RDOE | REG_INT_DEX | REG_INT_RDE; //IER2, 4, 5, 6, 7, 8, 9, 12\r
+               break;\r
+\r
+       case BU92725GUW_MULTI_SEND: /* M/FIR use */\r
+               val = REG_INT_TO | REG_INT_TXE | REG_INT_WRE; //IER2, 3, 11\r
+               break;\r
+       }\r
+       BU92725GUW_WRITE_REG(REG_IER_ADDR, val);\r
+       RK29IR_DBG("REG_IER_ADDR: 0x%x\n", val);\r
+}\r
+\r
+\r
+\r
diff --git a/drivers/net/irda/bu92725guw.h b/drivers/net/irda/bu92725guw.h
new file mode 100755 (executable)
index 0000000..cee61bc
--- /dev/null
@@ -0,0 +1,216 @@
+/***************************************************************************\r
+ *\r
+ * File:          bu92725guw.h\r
+ *\r
+ * Description:   This file contains configuration constants for the\r
+ *                bu92725guw board.\r
+ *\r
+ * Created:       2007/9\r
+ *\r
+ * Rev 1.1\r
+ *\r
+ *\r
+ * Confidential  ROHM CO.,LTD.\r
+ *\r
+ ****************************************************************************/\r
+#ifndef __BU92725GUW_H\r
+#define __BU92725GUW_H\r
+\r
+#include "mach/rk29_smc.h"\r
+\r
+\r
+/* irda registers addr  must be 2*ori_register when use smc control*/\r
+#define REG_TXD_ADDR           0\r
+#define REG_RXD_ADDR           0\r
+#define REG_IER_ADDR           2\r
+#define REG_EIR_ADDR           4\r
+#define REG_MCR_ADDR           6\r
+#define REG_PWR_FIT_ADDR       8\r
+#define REG_TRCR_ADDR          10\r
+#define REG_FTLV_ADDR          12\r
+#define REG_FLV_ADDR           14\r
+#define REG_FLVII_ADDR         16\r
+#define REG_FLVIII_ADDR                18\r
+#define REG_FLVIV_ADDR         20\r
+#define REG_TRCRII_ADDR                22\r
+#define REG_TXEC_ADDR          24\r
+#define REG_WREC_ADDR          26\r
+\r
+/*\r
+ *register bits definition (registers are all 16 bits)\r
+ */\r
+//interrupt reg (IER and EIR)\r
+#define REG_INT_DRX            (0x0001 << 0)\r
+#define REG_INT_EOFRX  (0x0001 << 1)\r
+#define REG_INT_STFRX  (0x0001 << 1)\r
+#define REG_INT_TO             (0x0001 << 2)\r
+#define REG_INT_TXE            (0x0001 << 3)\r
+#define REG_INT_CRC            (0x0001 << 4)\r
+#define REG_INT_OE             (0x0001 << 5)\r
+#define REG_INT_EOF            (0x0001 << 6)\r
+#define REG_INT_FE             (0x0001 << 7)\r
+#define REG_INT_AC             (0x0001 << 7)\r
+#define REG_INT_DECE   (0x0001 << 7)\r
+#define REG_INT_RDOE   (0x0001 << 8)\r
+#define REG_INT_DEX            (0x0001 << 9)\r
+#define REG_INT_RDUE   (0x0001 << 10)\r
+#define REG_INT_WRE            (0x0001 << 11)\r
+#define REG_INT_RDE            (0x0001 << 12)\r
+\r
+//MCR\r
+#define REG_MCR_CTLA   0x1000\r
+#define REG_MCR_RC_MODE        0x0800\r
+#define REG_MCR_RC_EN  0x0400\r
+#define REG_MCR_2400   (0x0000 << 5)\r
+#define REG_MCR_9600   (0x0002 << 5) //default\r
+#define REG_MCR_19200  (0x0003 << 5)\r
+#define REG_MCR_38400  (0x0004 << 5)\r
+#define REG_MCR_57600  (0x0005 << 5)\r
+#define REG_MCR_115200 (0x0006 << 5)\r
+#define REG_MCR_576K   (0x0001 << 5)\r
+#define REG_MCR_1152K  (0x0002 << 5)\r
+#define REG_MCR_4M             (0x0002 << 5)\r
+#define REG_MCR_SIR            0x0000 //default\r
+#define REG_MCR_MIR            0x0001\r
+#define REG_MCR_FIR            0x0002\r
+\r
+\r
+/* flag event bit\r
+ */\r
+#define FRM_EVT_RX_EOFRX       REG_INT_EOFRX   //IER1\r
+#define FRM_EVT_RX_RDE         REG_INT_RDE             //IER12\r
+#define FRM_EVT_TX_TXE         REG_INT_TXE             //IER3\r
+#define FRM_EVT_TX_WRE         REG_INT_WRE             //IER11\r
+#define FRM_EVT_EXIT_NOW       0x00010000\r
+\r
+\r
+enum eTrans_Mode {\r
+       BU92725GUW_SIR = 0,\r
+       BU92725GUW_MIR,\r
+       BU92725GUW_FIR,\r
+};\r
+enum eTrans_Speed {\r
+       BU92725GUW_2400 = 0,\r
+       BU92725GUW_9600,\r
+       BU92725GUW_19200,\r
+       BU92725GUW_38400,\r
+       BU92725GUW_57600,\r
+       BU92725GUW_115200,\r
+       BU92725GUW_576K,\r
+       BU92725GUW_1152K,\r
+       BU92725GUW_4M,\r
+};\r
+\r
+//PWR/FIT\r
+#define REG_PWR_FIT_SPW                0x0001\r
+#define REG_PWR_FIT_MPW_0      (0x0000 << 1)\r
+#define REG_PWR_FIT_MPW_1      (0x0001 << 1)\r
+#define REG_PWR_FIT_MPW_2      (0x0002 << 1)\r
+#define REG_PWR_FIT_MPW_3      (0x0003 << 1) //default\r
+#define REG_PWR_FIT_MPW_4      (0x0004 << 1)\r
+#define REG_PWR_FIT_MPW_5      (0x0005 << 1)\r
+#define REG_PWR_FIT_MPW_6      (0x0006 << 1)\r
+#define REG_PWR_FIT_MPW_7      (0x0007 << 1)\r
+#define REG_PWR_FIT_MPW_8      (0x0008 << 1)\r
+#define REG_PWR_FIT_MPW_9      (0x0009 << 1)\r
+#define REG_PWR_FIT_MPW_10     (0x000A << 1)\r
+#define REG_PWR_FIT_MPW_11     (0x000B << 1)\r
+#define REG_PWR_FIT_MPW_12     (0x000C << 1)\r
+#define REG_PWR_FIT_MPW_13  (0x000D << 1)\r
+#define REG_PWR_FIT_MPW_14     (0x000E << 1)\r
+#define REG_PWR_FIT_MPW_15     (0x000F << 1)\r
+#define REG_PWR_FIT_FPW_0      (0x0000 << 5)\r
+#define REG_PWR_FIT_FPW_1      (0x0001 << 5)\r
+#define REG_PWR_FIT_FPW_2      (0x0002 << 5) //default\r
+#define REG_PWR_FIT_FPW_3      (0x0003 << 5)\r
+#define REG_PWR_FIT_FIT_0      (0x0000 << 8) //default\r
+#define REG_PWR_FIT_FIT_1      (0x0001 << 8)\r
+#define REG_PWR_FIT_FIT_2      (0x0002 << 8)\r
+#define REG_PWR_FIT_FIT_3      (0x0003 << 8)\r
+#define REG_PWR_FIT_FIT_4      (0x0004 << 8)\r
+#define REG_PWR_FIT_FIT_5      (0x0005 << 8)\r
+#define REG_PWR_FIT_FIT_6      (0x0006 << 8)\r
+#define REG_PWR_FIT_FIT_7      (0x0007 << 8)\r
+#define REG_PWR_FIT_FIT_8      (0x0008 << 8) //default\r
+#define REG_PWR_FIT_FIT_9      (0x0009 << 8)\r
+#define REG_PWR_FIT_FIT_A      (0x000A << 8)\r
+#define REG_PWR_FIT_FIT_B      (0x000B << 8)\r
+#define REG_PWR_FIT_FIT_C      (0x000C << 8)\r
+#define REG_PWR_FIT_FIT_D      (0x000D << 8)\r
+#define REG_PWR_FIT_FIT_E      (0x000E << 8)\r
+#define REG_PWR_FIT_FIT_F      (0x000F << 8)\r
+\r
+//TRCR\r
+#define REG_TRCR_TX_EN                 0x0001\r
+#define REG_TRCR_RX_EN                 (0x0001 << 1)\r
+#define REG_TRCR_S_EOT                 (0x0001 << 2)\r
+#define REG_TRCR_IR_PLS                        (0x0001 << 3)\r
+#define REG_TRCR_FCLR                  (0x0001 << 4)\r
+#define REG_TRCR_MS_EN                 (0x0001 << 5)\r
+#define REG_TRCR_IRPD                  (0x0001 << 6)\r
+#define REG_TRCR_M_STA                 (0x0001 << 7)\r
+#define REG_TRCR_RXPWD                 (0x0001 << 8)\r
+#define REG_TRCR_TXPWD                 (0x0001 << 9)\r
+#define REG_TRCR_ONE_BIT_R             (0x0001 << 10)\r
+#define REG_TRCR_AUTO_FLV_CP   (0x0001 << 11)\r
+#define REG_TRCR_RX_CON                        (0x0001 << 12)\r
+#define REG_TRCR_FLV_CP                        (0x0001 << 13)\r
+#define REG_TRCR_TX_CON                        (0x0001 << 14)\r
+#define REG_TRCR_TX_NUM                        (0x0001 << 15)\r
+\r
+enum eThrans_Way {\r
+       BU92725GUW_IDLE = 0,\r
+       BU92725GUW_REV, /* SIR use */\r
+       BU92725GUW_SEND, /* SIR use */\r
+       BU92725GUW_AUTO_MULTI_REV, /* M/FIR use */\r
+       BU92725GUW_MULTI_REV, /* not used */\r
+       BU92725GUW_MULTI_SEND, /* M/FIR use */\r
+};\r
+\r
+\r
+#define BU92725GUW_FIFO_SIZE   (2560 * 2)\r
+\r
+#define BU92725GUW_MAX_FRM_INTERVAL            1000 /* 1000us */\r
+\r
+/*---------------------------------------------------------------------------\r
+                               Functions used by framer\r
+----------------------------------------------------------------------------*/\r
+#define BU92725GUW_READ_REG(regAddr)                   smc0_read(regAddr)\r
+#define BU92725GUW_WRITE_REG(regAddr, data)            smc0_write(regAddr, data)\r
+\r
+\r
+/* board initialize */\r
+extern void BU92725GUW_init(void);\r
+\r
+/* board deinit */\r
+extern void BU92725GUW_deinit(void);\r
+\r
+/* set data transfer speed */\r
+extern void BU92725GUW_set_trans_speed(u32 speed);\r
+\r
+/* set frame transfer way */\r
+extern void BU92725GUW_set_trans_way(u32 way);\r
+\r
+/* flush fifo */\r
+extern void BU92725GUW_clr_fifo(void);\r
+\r
+/* set frame sending interval */\r
+extern void BU92725GUW_set_frame_interval(u32 us);\r
+\r
+/* insert IrDA pulse follow frame sending */\r
+extern void BU92725GUW_add_pulse(void);\r
+\r
+/* soft reset when some error happened */\r
+extern void BU92725GUW_reset(void);\r
+\r
+/* return transfer mode */\r
+extern u32 BU92725GUW_get_trans_mode(void);\r
+\r
+/* get frame data from fifo */\r
+extern u16 BU92725GUW_get_data(u8 *buf);\r
+\r
+/* send frame data into fifo */\r
+extern void BU92725GUW_send_data(u8 *buf1, u16 len1, u8 *buf2, u16 len2);\r
+\r
+\r
+#endif /*__BU92725GUW_H*/\r
diff --git a/drivers/net/irda/rk29_ir.c b/drivers/net/irda/rk29_ir.c
new file mode 100755 (executable)
index 0000000..b7454d8
--- /dev/null
@@ -0,0 +1,712 @@
+/*\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the BSD Licence, GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2 of the\r
+ * License, or (at your option) any later version\r
+ */\r
+#include <linux/module.h>\r
+#include <linux/delay.h>\r
+#include <linux/errno.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/fs.h>\r
+#include <linux/kernel.h>\r
+#include <linux/slab.h>\r
+#include <linux/mm.h>\r
+#include <linux/ioport.h>\r
+#include <linux/init.h>\r
+#include <linux/sched.h>\r
+#include <linux/pci.h>\r
+#include <linux/random.h>\r
+#include <linux/version.h>\r
+#include <linux/mutex.h>\r
+#include <linux/videodev2.h>\r
+#include <linux/dma-mapping.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/kthread.h>\r
+#include <linux/highmem.h>\r
+#include <linux/freezer.h>\r
+#include <linux/netdevice.h>\r
+#include <linux/etherdevice.h>\r
+#include <linux/irq.h>\r
+#include <linux/wakelock.h>\r
+\r
+#include <mach/iomux.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h>\r
+#include <mach/rk29_iomap.h>\r
+#include <mach/pmu.h>\r
+#include <mach/rk29-dma-pl330.h>\r
+\r
+#include "rk29_ir.h"\r
+\r
+#if 0\r
+#define RK29IR_DBG(x...) printk(x)\r
+#else\r
+#define RK29IR_DBG(x...)\r
+#endif\r
+\r
+#if 0\r
+#define RK29IR_DATA_DBG(x...) printk(x)\r
+#else\r
+#define RK29IR_DATA_DBG(x...)\r
+#endif\r
+\r
+#define IRDA_NAME              "rk_irda"\r
+\r
+struct irda_driver {\r
+       struct irda_info *pin_info;\r
+       struct device                   *dev;\r
+};\r
+\r
+#define IS_FIR(si)             ((si)->speed >= 4000000)\r
+static int max_rate = 115200;\r
+#define IRDA_FRAME_SIZE_LIMIT  BU92725GUW_FIFO_SIZE\r
+\r
+#define RK29_MAX_RXLEN 2047\r
+\r
+static void rk29_irda_fir_test(struct work_struct *work);\r
+static DECLARE_DELAYED_WORK(dwork, rk29_irda_fir_test);\r
+\r
+\r
+/*\r
+ * Allocate and map the receive buffer, unless it is already allocated.\r
+ */\r
+static int rk29_irda_rx_alloc(struct rk29_irda *si)\r
+{\r
+       if (si->rxskb)\r
+               return 0;\r
+\r
+       si->rxskb = alloc_skb(RK29_MAX_RXLEN + 1, GFP_ATOMIC);\r
+\r
+       if (!si->rxskb) {\r
+               printk(KERN_ERR "rk29_ir: out of memory for RX SKB\n");\r
+               return -ENOMEM;\r
+       }\r
+\r
+       si->rxskb->len = 0;\r
+\r
+       /*\r
+        * Align any IP headers that may be contained\r
+        * within the frame.\r
+        */\r
+       skb_reserve(si->rxskb, 1);\r
+\r
+       return 0;\r
+}\r
+\r
+/*\r
+ * Set the IrDA communications speed.\r
+ */\r
+static int rk29_irda_set_speed(struct rk29_irda *si, int speed)\r
+{\r
+       unsigned long flags;\r
+       int ret = -EINVAL;\r
+       \r
+    printk("[%s][%d], speed=%d\n",__FUNCTION__,__LINE__,speed);\r
+\r
+       switch (speed) {\r
+       case 9600:      case 19200:     case 38400:\r
+       case 57600:     case 115200:\r
+               \r
+               local_irq_save(flags);\r
+               \r
+               irda_hw_set_speed(speed);\r
+\r
+               si->speed = speed;\r
+\r
+               local_irq_restore(flags);\r
+               ret = 0;\r
+               break;\r
+\r
+       case 4000000:\r
+               local_irq_save(flags);\r
+\r
+               si->speed = speed;\r
+               \r
+               irda_hw_set_speed(speed);\r
+               \r
+               rk29_irda_rx_alloc(si);\r
+\r
+               local_irq_restore(flags);\r
+               ret = 0;\r
+               break;\r
+\r
+       default:\r
+               break;\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+static irqreturn_t rk29_irda_irq(int irq, void *dev_id)\r
+{\r
+    struct net_device *dev = (struct net_device *)dev_id;\r
+    struct rk29_irda *si = netdev_priv(dev);\r
+    u8 data[2048]={0,0};\r
+    int tmp_len=0;\r
+    int i=0;\r
+    u32 irq_src = 0;   \r
+       u32 irda_setptn = 0;\r
+       \r
+    irq_src = irda_hw_get_irqsrc();\r
+       \r
+    printk("[%s][%d], 0x%x\n",__FUNCTION__,__LINE__, irq_src);\r
+       \r
+       //disable_irq(dev->irq);\r
+   \r
+        /* EIR 1, 3, 11, 12 */\r
+       irda_setptn |= irq_src & (REG_INT_EOFRX | REG_INT_TXE | REG_INT_WRE | REG_INT_RDE |\r
+                                 REG_INT_CRC | REG_INT_OE | REG_INT_FE | REG_INT_AC | \r
+                                 REG_INT_DECE | REG_INT_RDOE | REG_INT_DEX) ;\r
+\r
+       /* error */\r
+       if (irq_src & (REG_INT_TO| REG_INT_CRC | REG_INT_OE | REG_INT_FE | \r
+               REG_INT_AC | REG_INT_DECE | REG_INT_RDOE | REG_INT_DEX)) {\r
+        RK29IR_DBG("[%s][%d]: do err\n",__FUNCTION__,__LINE__);\r
+               BU92725GUW_clr_fifo();\r
+               BU92725GUW_reset();\r
+    }\r
+\r
+    if (IS_FIR(si))  //FIR\r
+    {\r
+        RK29IR_DBG("[%s][%d]: FIR\n",__FUNCTION__,__LINE__);\r
+        if(irda_hw_get_mode() == BU92725GUW_AUTO_MULTI_REV) {//rx\r
+                       struct sk_buff *skb = si->rxskb;\r
+            RK29IR_DBG("[%s][%d]: rx\n",__FUNCTION__,__LINE__);\r
+            if (irda_setptn & (REG_INT_FE | REG_INT_OE | REG_INT_CRC | REG_INT_DECE)) {\r
+                if (irda_setptn & REG_INT_FE) {\r
+                        printk(KERN_DEBUG "pxa_ir: fir receive frame error\n");\r
+                    dev->stats.rx_frame_errors++;\r
+                } else {\r
+                    printk(KERN_DEBUG "pxa_ir: fir receive abort\n");\r
+                    dev->stats.rx_errors++;\r
+                }\r
+            }\r
+            if ((irda_setptn & (FRM_EVT_RX_EOFRX | FRM_EVT_RX_RDE | REG_INT_EOF))) {\r
+                               tmp_len = BU92725GUW_get_data(skb->data+skb->len);\r
+                               skb->len += tmp_len;                    \r
+            }\r
+                       if (irda_setptn & (REG_INT_EOF | FRM_EVT_RX_EOFRX)) {                           \r
+                               RK29IR_DBG("[%s][%d]: report data:\n",__FUNCTION__,__LINE__);\r
+                               si->rxskb = NULL;\r
+                               RK29IR_DATA_DBG("[%s][%d]: fir report data:\n",__FUNCTION__,__LINE__);\r
+                               for (i=0;i<skb->len;i++) {\r
+                                       RK29IR_DATA_DBG("0x%2x ", skb->data[i]);\r
+                               }\r
+                               RK29IR_DATA_DBG("\n");\r
+                               \r
+                               skb_put(skb, skb->len);\r
+                               \r
+                               /* Feed it to IrLAP  */\r
+                               skb->dev = dev;\r
+                               skb_reset_mac_header(skb);\r
+                               skb->protocol = htons(ETH_P_IRDA);\r
+                               dev->stats.rx_packets++;\r
+                               dev->stats.rx_bytes += skb->len;\r
+                               \r
+                               /*\r
+                                * Before we pass the buffer up, allocate a new one.\r
+                                */\r
+                               rk29_irda_rx_alloc(si);\r
+                               \r
+                               netif_rx(skb);\r
+                       }                                               \r
+        }\r
+               else if (irda_hw_get_mode() == BU92725GUW_MULTI_SEND) {//tx\r
+                       struct sk_buff *skb = si->txskb;                        \r
+                       si->txskb = NULL;\r
+            RK29IR_DBG("[%s][%d]: tx\n",__FUNCTION__,__LINE__);\r
+            if (irda_setptn & (FRM_EVT_TX_TXE | FRM_EVT_TX_WRE)) {\r
+                               /*\r
+                                * Do we need to change speed?  Note that we're lazy\r
+                                * here - we don't free the old rxskb.  We don't need\r
+                                * to allocate a buffer either.\r
+                                */\r
+                               if (si->newspeed) {\r
+                                       rk29_irda_set_speed(si, si->newspeed);\r
+                                       si->newspeed = 0;\r
+                               }\r
+                               \r
+                               /*\r
+                                * Account and free the packet.\r
+                                */\r
+                               if (skb) {\r
+                                       dev->stats.tx_packets ++;\r
+                                       dev->stats.tx_bytes += skb->len;\r
+                                       dev_kfree_skb_irq(skb);\r
+                               }\r
+                               \r
+                               /*\r
+                                * Make sure that the TX queue is available for sending\r
+                                * (for retries).  TX has priority over RX at all times.\r
+                                */\r
+                               netif_wake_queue(dev);\r
+                               \r
+                               irda_hw_set_moderx();\r
+            }\r
+               }\r
+    }\r
+    else //SIR\r
+    {\r
+               RK29IR_DBG("[%d][%s], sir\n", __LINE__, __FUNCTION__);\r
+        if(irda_hw_get_mode() == BU92725GUW_REV) //rx\r
+        {\r
+                       RK29IR_DBG("[%d][%s], receive data:\n", __LINE__, __FUNCTION__);\r
+            if(irda_setptn & (REG_INT_OE | REG_INT_FE ))\r
+            {\r
+                dev->stats.rx_errors++;\r
+                if (irda_setptn & REG_INT_FE)\r
+                    dev->stats.rx_frame_errors++;\r
+                if (irda_setptn & REG_INT_OE)\r
+                    dev->stats.rx_fifo_errors++;\r
+            }\r
+            if((irda_setptn & ( FRM_EVT_RX_EOFRX| REG_INT_EOF /*|FRM_EVT_RX_RDE*/)))\r
+            {\r
+                tmp_len = BU92725GUW_get_data(data);\r
+                               RK29IR_DATA_DBG("[%d][%s], sir receive data:\n", __LINE__, __FUNCTION__);\r
+                for(i=0;i<=tmp_len;i++)\r
+                {\r
+                    RK29IR_DATA_DBG("0x%2x ",data[i]);\r
+                    async_unwrap_char(dev, &dev->stats, &si->rx_buff, data[i]);\r
+                }\r
+                               RK29IR_DATA_DBG("\n");\r
+             //BU92725GUW_clr_fifo();\r
+            }\r
+        }\r
+        else if(irda_hw_get_mode() == BU92725GUW_SEND) //tx\r
+        {\r
+                       RK29IR_DBG("[%d][%s], transmit data\n", __LINE__, __FUNCTION__);\r
+            if((irda_setptn & FRM_EVT_TX_TXE) && (si->tx_buff.len)) {\r
+                               RK29IR_DATA_DBG("[%d][%s], sir transmit data:\n", __LINE__, __FUNCTION__);\r
+                               for (i=0;i<si->tx_buff.len;i++) {\r
+                                       RK29IR_DATA_DBG("0x%2x ", *(si->tx_buff.data)++);\r
+                               }\r
+                               RK29IR_DATA_DBG("\n");\r
+\r
+                               BU92725GUW_send_data(si->tx_buff.data, si->tx_buff.len, NULL, 0);\r
+                si->tx_buff.len = 0;\r
+            }\r
+            else if (si->tx_buff.len == 0) {\r
+                dev->stats.tx_packets++;\r
+                dev->stats.tx_bytes += si->tx_buff.data - si->tx_buff.head;\r
+\r
+                /*\r
+                * Ok, we've finished transmitting.  Now enable\r
+                * the receiver.  Sometimes we get a receive IRQ\r
+                * immediately after a transmit...\r
+                */\r
+                if (si->newspeed) {\r
+                                       rk29_irda_set_speed(si, si->newspeed);\r
+                    si->newspeed = 0;\r
+                } \r
+\r
+                               irda_hw_set_moderx();\r
+                \r
+                /* I'm hungry! */\r
+                netif_wake_queue(dev);\r
+            }\r
+        }\r
+    }\r
+    //enable_irq(dev->irq);\r
+\r
+       return IRQ_HANDLED;\r
+}\r
+\r
+static int rk29_irda_start(struct net_device *dev)\r
+{\r
+       struct rk29_irda *si = netdev_priv(dev);\r
+       int err = 0;\r
+       \r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+       \r
+       si->speed = 9600;\r
+               \r
+       /*\r
+        *  irda module power up\r
+        */\r
+       if (si->pdata->irda_pwr_ctl)\r
+               si->pdata->irda_pwr_ctl(1);\r
+       si->power = 1;\r
+       \r
+       err = request_irq(dev->irq, rk29_irda_irq, IRQ_TYPE_LEVEL_LOW, dev->name, dev);//\r
+       if (err) {\r
+               printk("line %d: %s request_irq failed\n", __LINE__, __func__);\r
+               goto err_irq;\r
+       }\r
+\r
+       /*\r
+        * The interrupt must remain disabled for now.\r
+        */\r
+       disable_irq(dev->irq);\r
+\r
+       /*\r
+        * Setup the smc port for the specified speed.\r
+        */\r
+       err = irda_hw_startup(si);\r
+       if (err) {              \r
+               printk("line %d: %s irda_hw_startup err\n", __LINE__, __func__);\r
+               goto err_startup;\r
+       }\r
+    irda_hw_set_moderx();\r
+\r
+       /*\r
+        * Open a new IrLAP layer instance.\r
+        */\r
+       si->irlap = irlap_open(dev, &si->qos, "rk29");\r
+       err = -ENOMEM;\r
+       if (!si->irlap) {\r
+               printk("line %d: %s irlap_open err\n", __LINE__, __func__);\r
+               goto err_irlap;\r
+       }\r
+       \r
+       /*\r
+        * Now enable the interrupt and start the queue\r
+        */\r
+       si->open = 1;\r
+       enable_irq(dev->irq);\r
+       netif_start_queue(dev);\r
+       \r
+       printk("rk29_ir: irda driver opened\n");\r
+\r
+       //test\r
+       //rk29_irda_set_speed(si, 4000000);\r
+       //schedule_delayed_work(&dwork, msecs_to_jiffies(5000));\r
+\r
+       return 0;\r
+\r
+err_irlap:\r
+       si->open = 0;\r
+       irda_hw_shutdown(si);\r
+err_startup:\r
+       free_irq(dev->irq, dev);\r
+err_irq:\r
+       return err;\r
+}\r
+\r
+static int rk29_irda_stop(struct net_device *dev)\r
+{\r
+       struct rk29_irda *si = netdev_priv(dev);\r
+       \r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+\r
+       disable_irq(dev->irq);\r
+       irda_hw_shutdown(si);\r
+\r
+       /*\r
+        * If we have been doing DMA receive, make sure we\r
+        * tidy that up cleanly.\r
+        */\r
+       if (si->rxskb) {\r
+               dev_kfree_skb(si->rxskb);\r
+               si->rxskb = NULL;\r
+       }\r
+\r
+       /* Stop IrLAP */\r
+       if (si->irlap) {\r
+               irlap_close(si->irlap);\r
+               si->irlap = NULL;\r
+       }\r
+\r
+       netif_stop_queue(dev);\r
+       si->open = 0;\r
+\r
+       /*\r
+        * Free resources\r
+        */\r
+       free_irq(dev->irq, dev);\r
+\r
+       //irda module power down\r
+       if (si->pdata->irda_pwr_ctl)\r
+               si->pdata->irda_pwr_ctl(0);\r
+\r
+       si->power = 0;\r
+\r
+       return 0;\r
+}\r
+\r
+static int rk29_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)\r
+{\r
+    struct rk29_irda *si = netdev_priv(dev);\r
+    int speed = irda_get_next_speed(skb);\r
+       int i;\r
+\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+    /*\r
+     * Does this packet contain a request to change the interface\r
+     * speed?  If so, remember it until we complete the transmission\r
+     * of this frame.\r
+     */\r
+    if (speed != si->speed && speed != -1)\r
+        si->newspeed = speed;\r
+\r
+    /*\r
+     * If this is an empty frame, we can bypass a lot.\r
+     */\r
+    if (skb->len == 0) {\r
+        if (si->newspeed) {\r
+            si->newspeed = 0;\r
+                       rk29_irda_set_speed(si, speed);\r
+        }\r
+        dev_kfree_skb(skb);\r
+        return NETDEV_TX_OK;\r
+    }\r
+\r
+    netif_stop_queue(dev);\r
+\r
+    if (!IS_FIR(si)) {\r
+        si->tx_buff.data = si->tx_buff.head;\r
+        si->tx_buff.len  = async_wrap_skb(skb, si->tx_buff.data, si->tx_buff.truesize);\r
+\r
+        /* Disable STUART interrupts and switch to transmit mode. */\r
+        /* enable STUART and transmit interrupts */\r
+         irda_hw_tx_enable_irq(BU92725GUW_SIR);\r
+\r
+               RK29IR_DATA_DBG("[%d][%s], sir transmit data:\n", __LINE__, __FUNCTION__);\r
+               for (i=0;i<si->tx_buff.len;i++) {\r
+                       RK29IR_DATA_DBG("0x%2x ", *(si->tx_buff.data)++);\r
+               }\r
+               RK29IR_DATA_DBG("\n");\r
+\r
+               dev_kfree_skb(skb);\r
+               dev->trans_start = jiffies;\r
+               BU92725GUW_send_data(si->tx_buff.data, si->tx_buff.len, NULL, 0);\r
+               si->tx_buff.len = 0;\r
+\r
+    } \r
+       else {\r
+        unsigned long mtt = irda_get_mtt(skb);\r
+               si->txskb = skb;\r
+       \r
+          irda_hw_tx_enable_irq(BU92725GUW_FIR);\r
+\r
+         RK29IR_DATA_DBG("[%d][%s], fir transmit data:\n", __LINE__, __FUNCTION__);\r
+         for (i=0;i<skb->len;i++) {\r
+                 RK29IR_DATA_DBG("0x%2x ", skb->data[i]);\r
+         }\r
+         RK29IR_DATA_DBG("\n");\r
+         \r
+         dev->trans_start = jiffies; \r
+       BU92725GUW_send_data(skb->data, skb->len, NULL, 0);\r
+    }\r
+\r
+    return NETDEV_TX_OK;\r
+}\r
+\r
+static int\r
+rk29_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)\r
+{\r
+       struct if_irda_req *rq = (struct if_irda_req *)ifreq;\r
+       struct rk29_irda *si = netdev_priv(dev);\r
+       int ret = -EOPNOTSUPP;\r
+\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+\r
+       switch (cmd) {\r
+       case SIOCSBANDWIDTH:\r
+               if (capable(CAP_NET_ADMIN)) {\r
+                       /*\r
+                        * We are unable to set the speed if the\r
+                        * device is not running.\r
+                        */\r
+                       if (si->open) {\r
+                               ret = rk29_irda_set_speed(si, rq->ifr_baudrate );\r
+                       } else {\r
+                               printk("rk29_irda_ioctl: SIOCSBANDWIDTH: !netif_running\n");\r
+                               ret = 0;\r
+                       }\r
+               }\r
+               break;\r
+\r
+       case SIOCSMEDIABUSY:\r
+               ret = -EPERM;\r
+               if (capable(CAP_NET_ADMIN)) {\r
+                       irda_device_set_media_busy(dev, TRUE);\r
+                       ret = 0;\r
+               }\r
+               break;\r
+\r
+       case SIOCGRECEIVING:\r
+               rq->ifr_receiving = IS_FIR(si) ? 0\r
+                                       : si->rx_buff.state != OUTSIDE_FRAME;\r
+               break;\r
+\r
+       default:\r
+               break;\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+static const struct net_device_ops rk29_irda_netdev_ops = {\r
+       .ndo_open               = rk29_irda_start,\r
+       .ndo_stop               = rk29_irda_stop,\r
+       .ndo_start_xmit         = rk29_irda_hard_xmit,\r
+       .ndo_do_ioctl           = rk29_irda_ioctl,\r
+};\r
+\r
+\r
+static int rk29_irda_init_iobuf(iobuff_t *io, int size)\r
+{\r
+       io->head = kmalloc(size, GFP_KERNEL | GFP_DMA);\r
+       if (io->head != NULL) {\r
+               io->truesize = size;\r
+               io->in_frame = FALSE;\r
+               io->state    = OUTSIDE_FRAME;\r
+               io->data     = io->head;\r
+       }\r
+       return io->head ? 0 : -ENOMEM;\r
+}\r
+\r
+static void rk29_irda_fir_test(struct work_struct *work)\r
+{\r
+       char send_data[4] = {0,0,0,0};\r
+       irda_hw_tx_enable_irq(BU92725GUW_FIR);\r
+       \r
+       BU92725GUW_send_data(send_data, 4, NULL, 0);\r
+       \r
+       schedule_delayed_work(&dwork, msecs_to_jiffies(5000));\r
+       return ;\r
+}\r
+\r
+static int rk29_irda_probe(struct platform_device *pdev)\r
+{\r
+    struct irda_info *mach_info = NULL;\r
+       struct net_device *dev;\r
+       struct rk29_irda *si;\r
+       unsigned int baudrate_mask;\r
+       int err = -ENOMEM;\r
+\r
+    RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+\r
+    mach_info = pdev->dev.platform_data;\r
+\r
+    if (mach_info)\r
+               mach_info->iomux_init();\r
+\r
+    dev = alloc_irdadev(sizeof(struct rk29_irda));\r
+       if (!dev) {\r
+               printk("line %d: rk29_ir malloc failed\n", __LINE__);\r
+               goto err_mem_1;\r
+       }\r
+    SET_NETDEV_DEV(dev, &pdev->dev);\r
+       si = netdev_priv(dev);\r
+       si->dev = &pdev->dev;\r
+       si->pdata = pdev->dev.platform_data;\r
+\r
+    /*\r
+        * Initialise the HP-SIR buffers\r
+        */\r
+       err = rk29_irda_init_iobuf(&si->rx_buff, 14384);\r
+       if (err) {\r
+               printk("line %d: rk29_ir malloc failed\n", __LINE__);\r
+               goto err_mem_2;\r
+       }\r
+       err = rk29_irda_init_iobuf(&si->tx_buff, 4000);\r
+       if (err) {              \r
+               printk("line %d: rk29_ir malloc failed\n", __LINE__);\r
+               goto err_mem_3;\r
+       }\r
+       dev->netdev_ops = &rk29_irda_netdev_ops;\r
+       dev->irq = gpio_to_irq(mach_info->intr_pin);\r
+\r
+       irda_init_max_qos_capabilies(&si->qos);\r
+\r
+       /*\r
+        * We support original IRDA up to 115k2. (we don't currently\r
+        * support 4Mbps).  Min Turn Time set to 1ms or greater.\r
+        */\r
+       baudrate_mask = IR_9600;\r
+\r
+       switch (max_rate) {\r
+       case 4000000:           baudrate_mask |= IR_4000000 << 8;\r
+       case 115200:            baudrate_mask |= IR_115200;\r
+       case 57600:                 baudrate_mask |= IR_57600;\r
+       case 38400:                 baudrate_mask |= IR_38400;\r
+       case 19200:                 baudrate_mask |= IR_19200;\r
+       }\r
+\r
+       si->qos.baud_rate.bits &= baudrate_mask;\r
+       si->qos.min_turn_time.bits = 7;\r
+\r
+       irda_qos_bits_to_value(&si->qos);\r
+\r
+    /*\r
+        * Initially enable HP-SIR modulation, and ensure that the port\r
+        * is disabled.\r
+        */\r
+    irda_hw_init(si);\r
+\r
+       err = register_netdev(dev);\r
+       if (err) {      \r
+               printk("line %d: rk29_ir register_netdev failed\n", __LINE__);\r
+               goto err_register;\r
+       }\r
+       platform_set_drvdata(pdev, dev);\r
+\r
+       //test\r
+       //wake_lock_init(&w_lock, WAKE_LOCK_SUSPEND, "rk29_cir");\r
+       //wake_lock(&w_lock);\r
+       \r
+       return 0;\r
+       \r
+err_register:\r
+       irda_hw_deinit(si);\r
+       kfree(si->tx_buff.head);\r
+err_mem_3:\r
+       kfree(si->rx_buff.head);\r
+err_mem_2:\r
+       free_netdev(dev);\r
+err_mem_1:\r
+   return err;\r
+\r
+}\r
+\r
+static int rk29_irda_remove(struct platform_device *pdev)\r
+{\r
+       struct net_device *dev = platform_get_drvdata(pdev);\r
+       RK29IR_DBG("line %d: enter %s\n", __LINE__, __FUNCTION__);\r
+\r
+       if (dev) {\r
+               struct rk29_irda *si = netdev_priv(dev);\r
+               unregister_netdev(dev);\r
+               kfree(si->tx_buff.head);\r
+               kfree(si->rx_buff.head);\r
+               free_netdev(dev);\r
+        irda_hw_deinit(si);\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+\r
+static struct platform_driver irda_driver = {\r
+       .driver = {\r
+               .name = IRDA_NAME,\r
+        .owner = THIS_MODULE,\r
+       },\r
+       .probe = rk29_irda_probe,\r
+       .remove = rk29_irda_remove,\r
+       //.suspend = rk29_irda_suspend,\r
+       //.resume = rk29_irda_resume,\r
+};\r
+\r
+static int __init irda_init(void)\r
+{\r
+       if (platform_driver_register(&irda_driver) != 0) {\r
+       printk("Could not register irda driver\n");\r
+       return -EINVAL;\r
+       }\r
+       return 0;\r
+}\r
+\r
+static void __exit irda_exit(void)\r
+{\r
+       platform_driver_unregister(&irda_driver);\r
+}\r
+\r
+module_init(irda_init);\r
+module_exit(irda_exit);\r
+MODULE_AUTHOR("  zyw@rock-chips.com");\r
+MODULE_DESCRIPTION("Driver for irda device");\r
+MODULE_LICENSE("GPL");\r
+\r
diff --git a/drivers/net/irda/rk29_ir.h b/drivers/net/irda/rk29_ir.h
new file mode 100755 (executable)
index 0000000..ba4380f
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef __DRIVERS_NET_IRDA_RK29_IR_H\r
+#define __DRIVERS_NET_IRDA_RK29_IR_H\r
+\r
+#include "bu92725guw.h"\r
+#include <net/irda/irda.h>\r
+#include <net/irda/irmod.h>\r
+#include <net/irda/wrapper.h>\r
+#include <net/irda/irda_device.h>\r
+\r
+struct rk29_irda {\r
+    unsigned char*             irda_base_addr;\r
+       unsigned char           power;\r
+       unsigned char           open;\r
+\r
+       int                     speed;\r
+       int                     newspeed;\r
+\r
+       struct sk_buff          *txskb;\r
+       struct sk_buff          *rxskb;\r
+\r
+    unsigned char              *dma_rx_buff;\r
+       unsigned char           *dma_tx_buff;\r
+       u32                         dma_rx_buff_phy;\r
+       u32                         dma_tx_buff_phy;\r
+       unsigned int            dma_tx_buff_len;\r
+       int                     txdma;\r
+       int                     rxdma;\r
+\r
+\r
+       struct device           *dev;\r
+       struct irda_info *pdata;\r
+       struct irlap_cb         *irlap;\r
+       struct qos_info         qos;\r
+\r
+       iobuff_t                tx_buff;\r
+       iobuff_t                rx_buff;\r
+};\r
+extern void irda_hw_init(struct rk29_irda *si);\r
+extern int irda_hw_get_mode(void);\r
+extern void irda_hw_deinit(struct rk29_irda *si);\r
+extern int irda_hw_startup(struct rk29_irda *si);\r
+extern int irda_hw_shutdown(struct rk29_irda *si);\r
+extern int irda_hw_set_speed(u32 speed);\r
+extern int irda_hw_tx_enable_irq(enum eTrans_Mode mode);\r
+extern int irda_hw_tx_enable(int len);\r
+extern int irda_hw_get_irqsrc(void);\r
+extern int irda_hw_get_data16(char* data8);\r
+extern void irda_hw_set_moderx(void);\r
+extern int irda_hw_get_mode(void);\r
+\r
+\r
+#endif //__DRIVERS_NET_IRDA_RK29_IR_H\r
diff --git a/drivers/smc/Kconfig b/drivers/smc/Kconfig
new file mode 100755 (executable)
index 0000000..618908d
--- /dev/null
@@ -0,0 +1,9 @@
+
+config RK29_SMC
+       bool "rk29 smc interface"
+       default y
+       help
+         if you want to use smc in rk29, pls enable it
+         
+
+
diff --git a/drivers/smc/Makefile b/drivers/smc/Makefile
new file mode 100755 (executable)
index 0000000..5e5258e
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Makefile for the Linux IrDA infrared port device drivers.
+#
+# 9 Aug 2000, Christoph Hellwig <hch@infradead.org>
+# Rewritten to use lists instead of if-statements.
+#
+
+# FIR drivers
+obj-$(CONFIG_USB_IRDA)         += irda-usb.o
+obj-$(CONFIG_SIGMATEL_FIR)     += stir4200.o
+obj-$(CONFIG_NSC_FIR)          += nsc-ircc.o
+obj-$(CONFIG_WINBOND_FIR)      += w83977af_ir.o
+obj-$(CONFIG_SA1100_FIR)       += sa1100_ir.o
+obj-$(CONFIG_TOSHIBA_FIR)      += donauboe.o
+obj-$(CONFIG_SMC_IRCC_FIR)     += smsc-ircc2.o
+obj-$(CONFIG_ALI_FIR)          += ali-ircc.o
+obj-$(CONFIG_VLSI_FIR)         += vlsi_ir.o
+obj-$(CONFIG_VIA_FIR)          += via-ircc.o
+
+obj-$(CONFIG_RK29_SMC)        += rk29_smc.o
diff --git a/drivers/smc/rk29_smc.c b/drivers/smc/rk29_smc.c
new file mode 100755 (executable)
index 0000000..7f1339a
--- /dev/null
@@ -0,0 +1,181 @@
+#include <linux/module.h>\r
+#include <linux/kernel.h>\r
+#include <linux/errno.h>\r
+#include <linux/string.h>\r
+#include <linux/mm.h>\r
+#include <linux/slab.h>\r
+#include <linux/delay.h>\r
+#include <linux/device.h>\r
+#include <linux/init.h>\r
+#include <linux/dma-mapping.h>\r
+#include <linux/interrupt.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/clk.h>\r
+#include <linux/backlight.h>\r
+#include <linux/timer.h>\r
+#include <linux/time.h>\r
+#include <linux/wait.h>\r
+#include <linux/earlysuspend.h>\r
+#include <linux/cpufreq.h>\r
+#include <linux/wakelock.h>\r
+\r
+#include <asm/io.h>\r
+#include <asm/div64.h>\r
+#include <asm/uaccess.h>\r
+\r
+\r
+#include <mach/iomux.h>\r
+#include <mach/gpio.h>\r
+#include <mach/board.h>\r
+#include <mach/rk29_iomap.h>\r
+#include <mach/pmu.h>\r
+\r
+void __iomem *rank0_vir_base;  // virtual basic address of lcdc register\r
+struct clk      *smc_clk = NULL;\r
+struct clk      *smc_axi_clk = NULL;\r
+void __iomem *reg_vir_base;  // virtual basic address of lcdc register\r
+\r
+int smc0_enable(int enable)\r
+{\r
+    if(enable){\r
+        clk_enable(smc_axi_clk);\r
+        clk_enable(smc_clk);\r
+        __raw_writel(__raw_readl(RK29_GRF_BASE+0xbc) | 0x2000 , (RK29_GRF_BASE+0xbc));\r
+\r
+        __raw_writel((0x801), (reg_vir_base+0x18));\r
+        __raw_writel(0x00400000, (reg_vir_base+0x10));\r
+        __raw_writel((15 | (14<<8) | (15<<4) | (5<<11) ), (reg_vir_base+0x14));\r
+        //__raw_writel((15 | (10<<8) | (15<<4) | (7<<11) ), (reg_vir_base+0x14));\r
+\r
+        __raw_writel(0x00400000, (reg_vir_base+0x10));\r
+    }   else    {\r
+        clk_disable(smc_axi_clk);\r
+        clk_disable(smc_clk);\r
+    }\r
+    return 0;\r
+}\r
+\r
+int smc0_init(u8 **base_addr)\r
+{\r
+    u32 reg_phy_base;       // physical basic address of lcdc register\r
+       u32 len;               // physical map length of lcdc register\r
+    struct resource *mem;\r
+\r
+    u32 rank0_phy_base;       // physical basic address of lcdc register\r
+       u32 rank0_len;               // physical map length of lcdc register\r
+    struct resource *rank0_mem;\r
+\r
+    printk(" %s %d \n",__FUNCTION__, __LINE__);\r
+\r
+    if(smc_axi_clk == NULL)smc_axi_clk = clk_get(NULL, "aclk_smc");\r
+    if(smc_clk == NULL)smc_clk = clk_get(NULL, "smc");\r
+\r
+    rank0_phy_base = 0x11000000;  //0x12000000;//\r
+    rank0_len = SZ_4K;\r
+    rank0_mem = request_mem_region(rank0_phy_base, rank0_len, "smc_rank0");\r
+    if (rank0_mem == NULL)\r
+    {\r
+        printk("failed to get rank0 memory region [%d]\n",__LINE__);\r
+    }\r
+\r
+    rank0_vir_base = ioremap(rank0_phy_base, rank0_len);\r
+    if (rank0_vir_base == NULL)\r
+    {\r
+        printk("ioremap() of rank0 failed\n");\r
+    }\r
+\r
+    //*base_addr = rank0_vir_base;\r
+\r
+    reg_phy_base = RK29_SMC_PHYS;\r
+    len = SZ_16K;\r
+    mem = request_mem_region(reg_phy_base, len, "smc reg");\r
+    if (mem == NULL)\r
+    {\r
+        printk("failed to get memory region [%d]\n",__LINE__);\r
+    }\r
+\r
+    reg_vir_base = ioremap(reg_phy_base, len);\r
+    if (reg_vir_base == NULL)\r
+    {\r
+        printk("ioremap() of registers failed\n");\r
+    }\r
+\r
+    smc0_enable(1);\r
+\r
+    rk29_mux_api_set(GPIO0B7_EBCGDOE_SMCOEN_NAME, GPIO0L_SMC_OE_N);\r
+    rk29_mux_api_set(GPIO0B6_EBCSDSHR_SMCBLSN1_HOSTINT_NAME, GPIO0L_SMC_BLS_N_1 );\r
+    rk29_mux_api_set(GPIO0B5_EBCVCOM_SMCBLSN0_NAME, GPIO0L_SMC_BLS_N_0 );\r
+    rk29_mux_api_set(GPIO0B4_EBCBORDER1_SMCWEN_NAME, GPIO0L_SMC_WE_N);\r
+\r
+    rk29_mux_api_set(GPIO0B3_EBCBORDER0_SMCADDR3_HOSTDATA3_NAME, GPIO0L_SMC_ADDR3);\r
+    rk29_mux_api_set(GPIO0B2_EBCSDCE2_SMCADDR2_HOSTDATA2_NAME, GPIO0L_SMC_ADDR2);\r
+    rk29_mux_api_set(GPIO0B1_EBCSDCE1_SMCADDR1_HOSTDATA1_NAME, GPIO0L_SMC_ADDR1);\r
+    rk29_mux_api_set(GPIO0B0_EBCSDCE0_SMCADDR0_HOSTDATA0_NAME, GPIO0L_SMC_ADDR0);\r
+\r
+    rk29_mux_api_set(GPIO1A1_SMCCSN0_NAME, GPIO1L_SMC_CSN0);\r
+  //  rk29_mux_api_set(GPIO1A1_SMCCSN0_NAME, GPIO1L_GPIO1A1);\r
+\r
+  //  if(gpio_request(RK29_PIN1_PA1, NULL) != 0)\r
+    {\r
+  //      gpio_free(RK29_PIN1_PA1);\r
+ //       printk(">>>>>> RK29_PIN1_PA1 gpio_request err \n ");\r
+    }\r
+  //  gpio_direction_output(RK29_PIN1_PA1, GPIO_LOW);\r
+\r
+    rk29_mux_api_set(GPIO1A2_SMCCSN1_NAME, GPIO1L_SMC_CSN1);\r
+    rk29_mux_api_set(GPIO0D0_EBCSDOE_SMCADVN_NAME, GPIO0H_SMC_ADV_N);\r
+\r
+    rk29_mux_api_set(GPIO5C0_EBCSDDO0_SMCDATA0_NAME, GPIO5H_SMC_DATA0);\r
+    rk29_mux_api_set(GPIO5C1_EBCSDDO1_SMCDATA1_NAME, GPIO5H_SMC_DATA1);\r
+    rk29_mux_api_set(GPIO5C2_EBCSDDO2_SMCDATA2_NAME, GPIO5H_SMC_DATA2);\r
+    rk29_mux_api_set(GPIO5C3_EBCSDDO3_SMCDATA3_NAME, GPIO5H_SMC_DATA3);\r
+    rk29_mux_api_set(GPIO5C4_EBCSDDO4_SMCDATA4_NAME, GPIO5H_SMC_DATA4);\r
+    rk29_mux_api_set(GPIO5C5_EBCSDDO5_SMCDATA5_NAME, GPIO5H_SMC_DATA5);\r
+    rk29_mux_api_set(GPIO5C6_EBCSDDO6_SMCDATA6_NAME, GPIO5H_SMC_DATA6);\r
+    rk29_mux_api_set(GPIO5C7_EBCSDDO7_SMCDATA7_NAME, GPIO5H_SMC_DATA7);\r
+\r
+    rk29_mux_api_set(GPIO0C0_EBCGDSP_SMCDATA8_NAME, GPIO0H_SMC_DATA8);\r
+    rk29_mux_api_set(GPIO0C1_EBCGDR1_SMCDATA9_NAME, GPIO0H_SMC_DATA9);\r
+    rk29_mux_api_set(GPIO0C2_EBCSDCE0_SMCDATA10_NAME, GPIO0H_SMC_DATA10);\r
+    rk29_mux_api_set(GPIO0C3_EBCSDCE1_SMCDATA11_NAME, GPIO0H_SMC_DATA11);\r
+    rk29_mux_api_set(GPIO0C4_EBCSDCE2_SMCDATA12_NAME, GPIO0H_SMC_DATA12);\r
+    rk29_mux_api_set(GPIO0C5_EBCSDCE3_SMCDATA13_NAME, GPIO0H_SMC_DATA13);\r
+    rk29_mux_api_set(GPIO0C6_EBCSDCE4_SMCDATA14_NAME, GPIO0H_SMC_DATA14);\r
+    rk29_mux_api_set(GPIO0C7_EBCSDCE5_SMCDATA15_NAME, GPIO0H_SMC_DATA15);\r
+\r
+    return 0;\r
+\r
+}\r
+\r
+\r
+\r
+int smc0_write(u32 addr, u16 data)\r
+{\r
+  //  __raw_writel(data, rank0_vir_base + addr);\r
+    u16 *p = rank0_vir_base + addr;\r
+       int readdata;\r
+    *p = data;\r
+       udelay(5);\r
+       //readdata = *p;\r
+       //mdelay(5);\r
+       //mdelay(10);\r
+    //printk("%s addr=%x, data = %x, read date = %x\n",__FUNCTION__,addr,data,readdata);\r
+    return 0;\r
+}\r
+\r
+int smc0_read(u32 addr)\r
+{\r
+    u16 * p = rank0_vir_base + addr;\r
+       int readdata = *p; \r
+       //mdelay(5);\r
+       //printk("%s addr=%x, read date = %x\n",__FUNCTION__,addr,readdata);\r
+    return readdata;//__raw_readl(rank0_vir_base + addr);\r
+}\r
+\r
+void  smc0_exit(void)\r
+{\r
+     smc0_enable(0);\r
+}\r
+\r
+\r
+\r